/* read a stream of cells * RgetSomeCells views a raster as one linear stream of * cells, with row i+1 placed after row i. * In this stream any sequence can be read by specifying an * offset and the number of cells to be read * returns the number of cells read, just as fread * * example * .so examples/somecell.tr */ size_t RgetSomeCells( MAP *map, /* map handle */ size_t offset, /* offset from pixel (row,col) = (0,0) */ size_t nrCells, /* number of cells to be read */ void *buf)/* write-only. Buffer large enough to * hold nrCells cells in the in-file cell representation * or the in-app cell representation. */ { CSF_FADDR readAt; size_t cellsRead; UINT2 inFileCR = RgetCellRepr(map); offset <<= LOG_CELLSIZE(inFileCR); readAt = ADDR_DATA + (CSF_FADDR)offset; fseek(map->fp, (long)readAt, SEEK_SET); cellsRead = map->read(buf, (size_t)CELLSIZE(inFileCR), (size_t)nrCells, map->fp); PRECOND(map->file2app != NULL); map->file2app(nrCells, buf); return(cellsRead); }
/* write a stream of cells * RputSomeCells views a raster as one linear stream of * cells, with row i+1 placed after row i. * In this stream any sequence can be written by specifying an * offset and the number of cells to be written * returns the number of cells written, just as fwrite * * example * .so examples/somecell.tr */ size_t RputSomeCells( MAP *map, /* map handle */ size_t offset, /* offset from pixel (row,col) = (0,0) */ size_t nrCells, /* number of cells to be read */ void *buf)/* read-write. Buffer large enough to * hold nrCells cells in the in-file cell representation * or the in-app cell representation. * If these types are not equal then the buffer is * converted from the in-app to the in-file * cell representation. */ { CSF_FADDR writeAt; CSF_CR cr = map->raster.cellRepr; /* convert */ map->app2file(nrCells, buf); if (map->minMaxStatus == MM_KEEPTRACK) { const DF detMinMaxFunc[12] = { (DF)DetMinMaxUINT1, (DF)DetMinMaxUINT2, (DF)DetMinMaxUINT4, NULL /* 0x03 */ , (DF)DetMinMaxINT1 , (DF)DetMinMaxINT2 , (DF)DetMinMaxINT4 , NULL /* 0x07 */ , NULL /* 0x08 */ , NULL /* 0x09 */ , (DF)DetMinMaxREAL4, (DF)DetMinMaxREAL8 }; void *min = &(map->raster.minVal); void *max = &(map->raster.maxVal); PRECOND(CSF_UNIQ_CR_MASK(cr) < 12); PRECOND(detMinMaxFunc[CSF_UNIQ_CR_MASK(cr)] != NULL); detMinMaxFunc[CSF_UNIQ_CR_MASK(cr)](min, max, nrCells, buf); } else map->minMaxStatus = MM_WRONGVALUE; writeAt = ((CSF_FADDR)offset) << LOG_CELLSIZE(cr); writeAt += ADDR_DATA; if( csf_fseek(map->fp, writeAt, SEEK_SET) != 0 ) return 0; return(map->write(buf, (size_t)CELLSIZE(cr), (size_t)nrCells, map->fp)); }
/* seek to space for attribute (LIBRARY_INTERNAL) * CsfSeekAttrSpace seeks to the a point in the file where * the attribute must be stored and update the attribute control * blocks accordingly. * Writing can still fail since there is no check if that space is really * avalaible on the device. After this call returns the file is already * seeked to the point the functions returns. * returns the file position or 0 in case of error. * * Merrno * ATTRDUPL * NOACCESS * WRITE_ERROR */ CSF_FADDR32 CsfSeekAttrSpace( MAP *m, /* map handle */ CSF_ATTR_ID id, /* attribute identification only for check if avalaible */ size_t size) /* size to be seeked to */ { ATTR_CNTRL_BLOCK b; CSF_FADDR32 currBlockPos, prevBlockPos=USED_UNINIT_ZERO, newPos, endBlock, resultPos=0; int noPosFound; int i; if (MattributeAvail(m ,id)) { M_ERROR(ATTRDUPL); goto error; } if (! WRITE_ENABLE(m)) { M_ERROR(NOACCESS); goto error; } currBlockPos = m->main.attrTable; noPosFound = 1; while (noPosFound) { if (currBlockPos == 0) { if (m->main.attrTable == 0) { /* FIRST BLOCK */ newPos =( (CSF_FADDR)(m->raster.nrRows)* (CSF_FADDR)(m->raster.nrCols)* (CSF_FADDR)(CELLSIZE(RgetCellRepr(m)))) + ADDR_DATA; m->main.attrTable = newPos; } else { /* NEW/NEXT BLOCK */ newPos = b.attrs[LAST_ATTR_IN_BLOCK].attrOffset + b.attrs[LAST_ATTR_IN_BLOCK].attrSize; b.next = newPos; if (CsfWriteAttrBlock(m, prevBlockPos, &b)) { M_ERROR(WRITE_ERROR); resultPos = 0; } } InitBlock(&b); b.attrs[0].attrOffset = newPos + SIZE_OF_ATTR_CNTRL_BLOCK; currBlockPos = newPos; noPosFound = 0; } else CsfReadAttrBlock(m, currBlockPos, &b); i = 0; /* this is also the right index if a new block is added ! */ while (noPosFound && i < NR_ATTR_IN_BLOCK) switch (b.attrs[i].attrId) { case END_OF_ATTRS: POSTCOND(i >= 1); /* i >= 1 , no block otherwise */ b.attrs[i].attrOffset = b.attrs[i-1].attrOffset + b.attrs[i-1].attrSize; noPosFound = 0; break; case ATTR_NOT_USED: if (i == NR_ATTR_IN_BLOCK) endBlock = b.next; else endBlock = b.attrs[i+1].attrOffset; if ( (size_t)( endBlock - b.attrs[i].attrOffset) >= size) /* this position can hold the attr */ noPosFound = 0; else i++; break; default: i++; } /* switch */ /* if (b.next == 0) ? When did I change this CW remember this block position since it may be have to rewritten */ prevBlockPos = currBlockPos; if (noPosFound) currBlockPos = b.next; } /* while */ b.attrs[i].attrSize = size; b.attrs[i].attrId = id; resultPos = b.attrs[i].attrOffset; if (CsfWriteAttrBlock(m, currBlockPos, &b)) { M_ERROR(WRITE_ERROR); resultPos = 0; } fseek(m->fp, (long)resultPos, SEEK_SET); /* fsetpos() is better */ error: return resultPos; } /* CsfSeekAttrSpace */