⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bufffile.c

📁 b tree how to operate on b tr
💻 C
📖 第 1 页 / 共 2 页
字号:
      long offset;      next = p->BFP_Next;      offset = BF_PAGEOFFSET(bfp,p->BFP_PageNr);      if((offset + p->BFP_PageLen) > size) {	/*  Cannot truncate if exceeding page is still locked.	 *   We have a problem here: Counting locks doesn't	 *   provide enough information to decide if the	 *   truncation violates a locked region. We thus	 *   must trust the user who does the truncation.	 *   We only check for the obvious case where the	 *   start of the page lays already behind the new	 *   size.	 */	if(offset > size && p->BFP_Prot) {	  JSErrNo = _ERR_BFILETRUNC + 0;	  goto error;	}	/*  Truncate or free this page  */	if(offset < size) {	  p->BFP_PageLen = size - offset;	} else {	  /*  Remove page from linked list  */	  if(prev)	    prev->BFP_Next = next;	  else	    bfp->BF_HashTab[i] = next;	  freePage(p);	  continue; /*  prev doesn' change  */	}      }      prev = p;    }  }#ifndef CONFIG_NO_POSIX  if(ftruncate(bfp->BF_Handle,size) < 0) goto error;#endif  return(0);error:  return(-1);}/* ERROR-DEFINITIONS from bFileGet label _ERR_BFILEGET ord 16   Cannot map complete region   End of file*//*JS**********************************************************************   Returns the start pointer for the specified region*    [offset,offset + *pLen] in the file. The returned length in *pLen*    may be shorter, thus requiring additional calls to bFileGet.*    Properties for the region may be set immediately using mode:*    'BFILEMODE_PROT' prevents reusage, 'BFILEMODE_UNPROT' allows.*    'BFILEMODE_DIRTY' marks that the region must be written to disk.*    'BFILEMMODE_REREAD' forces re-reading the page.*************************************************************************/char *bFileGet(BuffFile *bfp,long offset,long *pLen,int mode)/************************************************************************/{  BuffFilePage *p,*lastUnlocked,*previous;  long len,pageNr;  int hash,count,flag;  len = *pLen;#ifdef CONFIG_USE_MMAP  if(bfp->BF_MMPage) {    if(len > 0 ? offset < bfp->BF_MMPageLen : offset <= bfp->BF_MMPageLen) {      /*  Check if boundary of memory mapped region is exceeded  */      if(len > 0) {	if((offset + len) > bfp->BF_MMPageLen) {	  if(mode & BFILEMODE_FULLMAP) goto maperror;	  *pLen = bfp->BF_MMPageLen - offset;	}      } else {	if((offset + len) < 0) {	  if(mode & BFILEMODE_FULLMAP) goto maperror;	  *pLen = -offset;	}      }      if(mode & BFILEMODE_PROT) bfp->BF_MMProt++;      if(mode & BFILEMODE_UNPROT) bfp->BF_MMProt--;      /*  Clearing lock takes precedence  */      if(mode & BFILEMODE_CLEARPROT) bfp->BF_MMProt = 0;      return(bfp->BF_MMPage + offset);    } else if(!(bfp->BF_Type & BFILE_WRITE)) {      /*  Trying to enlarge file in case of read-only       *   access doesn't make sense.       */      JSErrNo = _ERR_BFILEGET + 1;      goto error;    }  }#endif  if(len > 0) {    pageNr = offset >> bfp->BF_PageShift;    offset &= BF_PAGESIZE(bfp) - 1;  } else {    offset--;    pageNr = offset >> bfp->BF_PageShift;    offset &= BF_PAGESIZE(bfp) - 1;    offset++;  }  hash = pageNr % bfp->BF_HashLen;  flag = 0;  lastUnlocked = NULL;  for(count = 0, p = bfp->BF_HashTab[hash], previous = NULL ; p ;      previous = p, p = p->BFP_Next, count++) {    if(p->BFP_Prot == 0) {      lastUnlocked = previous;      flag |= 1; /*  page found  */    }    if(p->BFP_PageNr == pageNr) break;  }  if(p == NULL) {    if(count < BuffFileMaxPage || !(flag & 1)) {      /*  Allocate new page. We have not included the page in the structure       *   itself to be sure it is correctly aligned.       */      if((p = (BuffFilePage *)malloc(sizeof(*p))) == NULL)	goto error;      if((p->BFP_Page = (char *)malloc(BF_PAGESIZE(bfp))) == NULL) {	free(p);	goto error;      }      p->BFP_PageNr = -1;      p->BFP_Prot = 0;      /*  Hang in front of list  */      p->BFP_Next = bfp->BF_HashTab[hash];      bfp->BF_HashTab[hash] = p;    } else {      /*  Reuse page and hang in front of list  */      if(lastUnlocked) {	p = lastUnlocked->BFP_Next;	lastUnlocked->BFP_Next = p->BFP_Next;	p->BFP_Next = bfp->BF_HashTab[hash];	bfp->BF_HashTab[hash] = p;      } else {	/*  Page is already at head  */	p = bfp->BF_HashTab[hash];      }      if((p->BFP_Flags & BFP_DIRTY) && flushPage(bfp,p)) goto error;    }    /*  Load page  */    p->BFP_Flags = 0;    p->BFP_PageNr = pageNr;    flag |= 2;  } else if((p->BFP_Flags & BFP_REREAD) || (mode & BFILEMODE_REREAD)) {    flag |= 2;    p->BFP_Flags &= ~BFP_REREAD;  }  /*  Read page?  */  if(flag & 2) {    if(#ifndef CONFIG_NO_POSIX       lseek(bfp->BF_Handle,BF_PAGEOFFSET(bfp,p->BFP_PageNr),SEEK_SET) < 0 ||       (p->BFP_PageLen = read(bfp->BF_Handle,p->BFP_Page,BF_PAGESIZE(bfp)))#else       fseek(bfp->BF_Handle,BF_PAGEOFFSET(bfp,p->BFP_PageNr),SEEK_SET) < 0 ||       (p->BFP_PageLen = fread(p->BFP_Page,1,BF_PAGESIZE(bfp),bfp->BF_Handle))#endif       < 0)      goto error;  }  if(len > 0) {    if((offset + len) > p->BFP_PageLen) {      if(mode & BFILEMODE_DIRTY) {	/*  User requested writing, so increase area  */	p->BFP_PageLen = MIN(BF_PAGESIZE(bfp),offset + len);	if((offset + len) > p->BFP_PageLen) {	  if(mode & BFILEMODE_FULLMAP) goto maperror;	  *pLen = p->BFP_PageLen - offset;	}      } else {	/*  Check first for EOF before assuming map error  */	if((*pLen = p->BFP_PageLen - offset) < 0) {	  JSErrNo = _ERR_BFILEGET + 1;	  goto error;	}	if(mode & BFILEMODE_FULLMAP) goto maperror;      }    }  } else {    if(offset > p->BFP_PageLen) {      if(mode & BFILEMODE_DIRTY) {	/*  User requested writing, so increase area  */	p->BFP_PageLen = MIN(BF_PAGESIZE(bfp),offset);	if((offset + len) < 0) {	  if(mode & BFILEMODE_FULLMAP) goto maperror;	  *pLen = -offset;	}      } else {	/*  Doesn't work for negative lengths  */	JSErrNo = _ERR_BFILEGET + 1;	goto error;      }    } else if((offset + len) < 0) {      if(mode & BFILEMODE_FULLMAP) goto maperror;      *pLen = -offset;    }  }  if(mode & BFILEMODE_DIRTY) p->BFP_Flags |= BFP_DIRTY;  if(mode & BFILEMODE_PROT) p->BFP_Prot++;  if(mode & BFILEMODE_UNPROT) p->BFP_Prot--;  /*  Clearing lock takes precedence  */  if(mode & BFILEMODE_CLEARPROT) p->BFP_Prot = 0;  return(p->BFP_Page + offset);maperror:  JSErrNo = _ERR_BFILEGET + 0;error:  return(NULL);}/*JS**********************************************************************   Simple interface to bFileGet to avoid pointer argument if one expects*    the whole region to be mapped.*************************************************************************/char *bFileGet2(BuffFile *bfp,long offset,long len,int mode)/************************************************************************/{  return(bFileGet(bfp,offset,&len,mode));}/* ERROR-DEFINITIONS from bFileGet label _ERR_BFILESET ord 16   Page not in memory*//*JS**********************************************************************   Sets the specified property of the region: 'BFILEMODE_PROT' prevents*    reusage, 'BFILEMODE_UNPROT' allows. 'BFILEMODE_DIRTY' marks that the*    region must be written to disk.*************************************************************************/int bFileSet(BuffFile *bfp,long offset,long len,int mode)/************************************************************************/{  if(len < 0) {    /*  If len is negative, simply do it the other way round  */    offset += len;    len = -len;  }  while(len > 0) {    BuffFilePage *p;    long pageNr,pOffset,len2;#ifdef CONFIG_USE_MMAP    if(bfp->BF_MMPage && offset < bfp->BF_MMPageLen) {      /*  Check if boundary of memory mapped region is exceeded  */      len2 = MIN(len,bfp->BF_MMPageLen - offset);      if(mode & BFILEMODE_PROT) bfp->BF_MMProt++;      if(mode & BFILEMODE_UNPROT) bfp->BF_MMProt--;      /*  Clearing lock takes precedence  */      if(mode & BFILEMODE_CLEARPROT) bfp->BF_MMProt = 0;    } else#endif    {      pageNr = offset >> bfp->BF_PageShift;      pOffset = offset & (BF_PAGESIZE(bfp) - 1);      for(p = bfp->BF_HashTab[pageNr % bfp->BF_HashLen] ; p ; p = p->BFP_Next)	if(p->BFP_PageNr == pageNr) break;      if(p == NULL) {	JSErrNo = _ERR_BFILESET + 0;	return(-1);      }      if(mode & BFILEMODE_DIRTY) p->BFP_Flags |= BFP_DIRTY;      if(mode & BFILEMODE_PROT) p->BFP_Prot++;      if(mode & BFILEMODE_UNPROT) p->BFP_Prot--;      /*  Clearing lock takes precedence  */      if(mode & BFILEMODE_CLEARPROT) p->BFP_Prot = 0;      len2 = MIN(len,BF_PAGESIZE(bfp) - pOffset);    }    offset += len2;    len -= len2;  }  return(0);}/*JS**********************************************************************   Read the specified length into the buffer. The returned length may be*    shorter if the end of file is reached.*************************************************************************/int bFileRead(BuffFile *bfp,void *ptr,long offset,long size)/************************************************************************/{  long toRead,l;  for(toRead = size ; toRead > 0 ; toRead -= l) {    char *adr;    /*  Try to get as much as possible  */    l = toRead;    if((adr = bFileGet(bfp,offset,&l,0)) == NULL) return(-1);    /*  EOF reached?  */    if(l == 0) break;    memcpy(ptr,adr,l);    offset += l;    ptr = (void *)((char *)ptr + l);  }  return(size - toRead);}/*JS**********************************************************************   Write the specified length from the buffer to the file. The returned*    length may be shorter if an error occured.*************************************************************************/int bFileWrite(BuffFile *bfp,const void *ptr,long offset,long size)/************************************************************************/{  long toWrite,l;  for(toWrite = size ; toWrite > 0 ; toWrite -= l) {    char *adr;    l = toWrite;    if((adr = bFileGet(bfp,offset,&l,BFILEMODE_DIRTY)) == NULL) return(-1);    memcpy(adr,ptr,l);    offset += l;    ptr = (void *)((char *)ptr + l);  }  return(size - toWrite);}/*JS**********************************************************************   Set the region from offset to offset+size to the byte c.*************************************************************************/int bFileByteSet(BuffFile *bfp,int c,long offset,long size)/************************************************************************/{  long toSet,l;  for(toSet = size ; toSet > 0 ; toSet -= l) {    char *adr;    l = toSet;    if((adr = bFileGet(bfp,offset,&l,BFILEMODE_DIRTY)) == NULL) return(-1);    memset(adr,c,l);    offset += l;  }  return(size - toSet);}/*JS**********************************************************************   Copys size bytes from offset sOff to dOff. Doesn't work if the areas*    overlap.*************************************************************************/int bFileByteCopy(BuffFile *bfp,long sOff,long dOff,long size)/************************************************************************/{  long toCopy,l,l2;  for(toCopy = size ; toCopy > 0 ; toCopy -= l2) {    char *s,*d;    l = l2 = toCopy;    if((s = bFileGet(bfp,sOff,&l,BFILEMODE_PROT)) == NULL ||       (d = bFileGet(bfp,dOff,&l2,BFILEMODE_DIRTY)) == NULL)      return(-1);    if(l < l2) l2 = l;    memcpy(d,s,l2);    if(bFileSet(bfp,sOff,l,BFILEMODE_UNPROT) < 0) return(-1);    sOff += l2;    dOff += l2;  }  return(size - toCopy);}/*JS**********************************************************************   Moves size bytes from offset sOff to dOff. Works also if the areas*    overlap.*************************************************************************/int bFileByteMove(BuffFile *bfp,long sOff,long dOff,long size)/************************************************************************/{  long toCopy,l,l2;  /*  If the destination offset is greater than the source   *   offset, do it backwards in case areas overlap.   */  if(sOff < dOff) {    sOff += size;    dOff += size;    toCopy = -size;  } else    toCopy = size;  for( ; toCopy != 0 ; toCopy -= l2) {    char *s,*d;    l = l2 = toCopy;    if((s = bFileGet(bfp,sOff,&l,BFILEMODE_PROT)) == NULL ||       (d = bFileGet(bfp,dOff,&l2,BFILEMODE_DIRTY)) == NULL) return(-1);    if(toCopy > 0) {      if(l < l2) l2 = l;      memmove(d,s,l2);    } else {      if(l > l2) l2 = l;      memmove(d + l2,s + l2,-l2);    }    if(bFileSet(bfp,sOff,l,BFILEMODE_UNPROT) < 0) return(-1);    sOff += l2;    dOff += l2;  }  return(size - ABS(toCopy));}/*JS**********************************************************************   Count total number of locks currently present on buffered file.*************************************************************************/long bFileNLocks(BuffFile *bfp)/************************************************************************/{  int i;  long count;  count = bfp->BF_MMProt;  for(i = 0 ; i < bfp->BF_HashLen ; i++) {    BuffFilePage *p;    for(p = bfp->BF_HashTab[i] ; p ; p = p->BFP_Next)      count += p->BFP_Prot;  }  return(count);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -