long mfseek(MEMFILE *mf,long offset,int whence) { long length; assert(mf!=NULL); if (mf->usedoffs == 0) return 0L; /* early exit: not a single byte in the file */ /* find the size of the memory file */ length=mflength(mf); /* convert the offset to an absolute position */ switch (whence) { case SEEK_SET: break; case SEEK_CUR: offset+=mf->offs; break; case SEEK_END: assert(offset<=0); offset+=length; break; } /* switch */ /* clamp to the file length limit */ if (offset<0) offset=0; else if (offset>length) offset=length; /* set new position and return it */ memfile_seek(mf, offset); return offset; }
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size) { long length; long numblocks; int blockpos,blocksize; unsigned int bytes; MEMFILE *block; assert(mf!=NULL); /* adjust the size to read */ length=mflength(mf); assert(mf->bufpos>=0 && mf->bufpos<=length); if (mf->bufpos+size>(unsigned long)length) size=(int)(length-mf->bufpos); assert(mf->bufpos+size<=(unsigned long)length); if (size==0) return 0; /* find the block to start reading from */ numblocks=mf->bufpos/BUFFERSIZE; /* # blocks to skip */ block=mf->next; while (numblocks-->0) { assert(block!=NULL); block=block->next; } /* while */ assert(block!=NULL); /* copy out of memory */ bytes=0; blockpos=(int)(mf->bufpos % BUFFERSIZE); do { blocksize=BUFFERSIZE-blockpos; if ((unsigned int)blocksize>size) blocksize=size; assert(block!=NULL); assert(block->bufpos>=0 && (unsigned long)block->bufpos<=BUFFERSIZE); assert(blockpos+blocksize<=block->bufpos); memcpy(buffer,block->buffer+blockpos,blocksize); buffer+=blocksize; size-=blocksize; bytes+=blocksize; block=block->next; blockpos=0; } while (size>0); /* adjust file pointer */ mf->bufpos+=bytes; return bytes; }
unsigned int mfwrite(MEMFILE *mf,unsigned char *buffer,unsigned int size) { long length; long numblocks; int blockpos,blocksize; unsigned int bytes; MEMFILE *block; assert(mf!=NULL); /* see whether more memory must be allocated */ length=mflength(mf); assert(mf->bufpos>=0 && mf->bufpos<=length); numblocks=(length+BUFFERSIZE-1)/BUFFERSIZE; /* # allocated blocks */ while (mf->bufpos+size>numblocks*BUFFERSIZE) { /* append a block */ MEMFILE *last; block=(MEMFILE*)malloc(sizeof(MEMFILE)); if (block==NULL) return 0; memset(block,0,sizeof(MEMFILE)); block->buffer=(unsigned char*)malloc(BUFFERSIZE); if (block->buffer==NULL) { free(block); return 0; } /* if */ for (last=mf; last->next!=NULL; last=last->next) /* nothing */; assert(last!=NULL); assert(last->next==NULL); last->next=block; numblocks++; } /* while */ if (size==0) return 0; /* find the block to start writing to */ numblocks=mf->bufpos/BUFFERSIZE; /* # blocks to skip */ block=mf->next; while (numblocks-->0) { assert(block!=NULL); block=block->next; } /* while */ assert(block!=NULL); /* copy into memory */ bytes=0; blockpos=(int)(mf->bufpos % BUFFERSIZE); do { blocksize=BUFFERSIZE-blockpos; assert(blocksize>=0); if ((unsigned int)blocksize>size) blocksize=size; assert(block!=NULL); memcpy(block->buffer+blockpos,buffer,blocksize); buffer+=blocksize; size-=blocksize; bytes+=blocksize; if (blockpos+blocksize>block->bufpos) block->bufpos=blockpos+blocksize; assert(block->bufpos>=0 && (unsigned long)block->bufpos<=BUFFERSIZE); block=block->next; blockpos=0; } while (size>0); /* adjust file pointer */ mf->bufpos+=bytes; return bytes; }