/* wblock.c -- Copyright 1991, 1993, 1994, 1996 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. */ /* The low-level physical Word Database for lq-text. * * $Id: wblock.c,v 1.9 1996/05/14 16:36:03 lee Exp $ */ #include "error.h" #include "globals.h" /* defines and declarations for database filenames */ #include /* stderr, also for fileinfo.h */ #include #ifdef HAVE_FCNTL_H # ifdef HAVE_SYSV_FCNTL_H # include # endif # include #endif #include "fileinfo.h" /* for wordinfo.h */ #include "wordinfo.h" #include "pblock.h" #include "numbers.h" #include "wordrules.h" #include "putbyte.h" #include "blkheader.h" #include "liblqtext.h" /** C library functions that need to be declared: **/ /** lqtext library functions that need to be declared: **/ /** Functions within this file that need to be declared: **/ /** **/ /* * Database/Physical * LQT_FlushBlock * * Writes out the given block to the cache. This is really the * same as LQT_WriteBlock, except that it is used for the last * block in each chain of matches. * */ API void LQT_FlushBlock(db, Block, ByteCount, NextOffset, LastStart, WID) t_LQTEXT_Database *db; unsigned char *Block; int ByteCount; unsigned long *NextOffset, *LastStart; t_WID WID; { if (*LastStart && Block) { /*NOSTRICT*/ t_BlockHeader *BH = (t_BlockHeader *) Block; register unsigned char *p; int BlocksToWrite = (ByteCount + BLOCKSIZE - 1) / BLOCKSIZE; /* round up! */ BH->NextOffset = 0L; #ifdef WIDINBLOCK BH->WID = WID; #endif /* pad with -1 for future compatibility */ for ( p = &Block[BLOCKSIZE*BlocksToWrite - 1]; p >= &Block[ByteCount]; p-- ) { *p = (unsigned char) 0xFF; } LQT_SetLastBlockInChain(db, WID, LastStart, &Block[ByteCount], Block); LQT_WriteBlock(db, *LastStart, Block, BlocksToWrite, WID); } if (*NextOffset) { /* We allocated it in case we needed it, and we didn't need it */ LQT_SetBlockStatus(db, *NextOffset, SET_BLOCK_AS_FREE); } *LastStart = *NextOffset = 0L; } /* This is simply to help keep the source lines getting too long! */ typedef unsigned char *UCP; LIBRARY int LQTp__PutByte( db, Byte, WID, sp, Blockp, BlockLength, LastStart, NextBlock, NextLength ) t_LQTEXT_Database *db; unsigned int Byte; t_WID WID; unsigned char **sp; unsigned char **Blockp; unsigned int *BlockLength; unsigned long *NextBlock; unsigned long *NextLength; unsigned long *LastStart; /* for writing the linked list */ { t_BlockHeader *BH; if (*sp - (*Blockp) >= (*BlockLength)) { int NumberOfBlocks; if (!*NextBlock && !*LastStart) { return -1; /* only do the 1st block */ } NumberOfBlocks = (*BlockLength + BLOCKSIZE - 1) / BLOCKSIZE; if (*NextBlock == (unsigned long) 0) { *NextBlock = LQT_FindFreeBlock(db, WID, BlockLength, 0); } else { if (NextLength && *NextLength) { *BlockLength = (*NextLength); *NextLength = 0; } else { Error(E_BUG, "LQTp__PutByte: NextLength is %s", NextLength ? "zero" : "a null pointer" ); } } /* Complete the information in the previous block, if required */ if (*LastStart) { BH = (t_BlockHeader *) (*Blockp); #ifdef WIDINBLOCK BH->WID = WID; #endif BH->NextOffset = (*NextBlock); /* Write the old block */ LQT_WriteBlock(db, *LastStart, *Blockp, NumberOfBlocks, WID); *LastStart = 0L; } *LastStart = (*NextBlock); (*NextBlock) = 0L; *Blockp = LQT_ReadBlock(db, *LastStart, (t_WID) 0); /*NOSTRICT*/ BH = (t_BlockHeader *) (*Blockp); BH->NumberOfBlocks = (*BlockLength/BLOCKSIZE); /*exact*/ (*sp) = (UCP) BH->Data; } **sp = Byte; (*sp)++; return 0; } /* PutLong -- write a long number in compressed/abbreviated form into a * string. If this moves the string pointer beyond the block, write out * the block and start a new one. In that case, the number written may well * span the gap between the blocks. We use an overflow buffer to copy * the bytes (if any) that overflowed into it. * Then we write them at the start of the next block. * * This routine returns -1 and writes a partial number (no allocated block) * if *LastBlock and *NextBlock are zero. This allows PutwOrdPlaces to be * called to put the WordPlaces into the WIDFILE block without writing out * an entire chain. */ LIBRARY int LQTp__PutLong( db, Long, WID, sp, Blockp, BlockLength, LastStart, NextBlock, NextLength ) t_LQTEXT_Database *db; unsigned long Long; t_WID WID; unsigned char **sp; unsigned char **Blockp; unsigned int *BlockLength; unsigned long *NextBlock; unsigned long *NextLength; unsigned long *LastStart; /* for writing the linked list */ { unsigned char *Start = (*sp); if (LQT_sWriteNumber( (unsigned char **) sp, Long, *Blockp, *BlockLength ) < 0) { unsigned int BytesWritten; int NumberOfBlocks; t_BlockHeader *BH; if (!*NextBlock && !*LastStart) { /* We were being tentative, seeing if the data would fit * or not, and it didn't. */ return -1; } NumberOfBlocks = (*BlockLength + BLOCKSIZE - 1) / BLOCKSIZE; BytesWritten = (*BlockLength - (Start - (*Blockp))); if (*NextBlock == (unsigned long) 0) { *NextBlock = LQT_FindFreeBlock(db, WID, BlockLength, 0); } else { if (NextLength && *NextLength) { *BlockLength = (*NextLength); *NextLength = 0; } else { Error(E_BUG, "LQTp__PutLong: NextLength is %s", NextLength ? "zero" : "a null pointer" ); } } /* Complete the information in the previous block, if required */ if (*LastStart) { BH = (t_BlockHeader *) (*Blockp); BH->NextOffset = *NextBlock; #ifdef WIDINBLOCK BH->WID = WID; #endif /* Write the old block */ LQT_WriteBlock(db, *LastStart, *Blockp, NumberOfBlocks, WID); } /* If both LastStart and NextBlock are set, it is because * we allocated a block before calling LQT_WriteWordPlaces. * In that case, we will use that block next, and then after * that NextBlock will always be zero. */ *LastStart = (*NextBlock); (*NextBlock) = 0L; *Blockp = LQT_ReadBlock(db, *LastStart, (t_WID) 0); BH = (t_BlockHeader *) (*Blockp); (*sp) = (UCP) BH->Data; BH->NumberOfBlocks = *BlockLength / BLOCKSIZE; /* always exact */ /* now write the rest of the number out */ { unsigned char Buffer[sizeof(unsigned long) * 8 / 7 + 1]; unsigned char *Bufp = Buffer; register unsigned char *p; (void) LQT_sWriteNumber( &Bufp, Long, Buffer, sizeof Buffer ); for (p = &Buffer[BytesWritten]; p < Bufp; p++) { *((*sp)++) = (*p); } } } return 0; }