From 597a1487c716b799428f4b4a4903e65df4c93ba9 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 15 Sep 2008 20:03:56 +0000 Subject: Whoa! Loads of NIDS work. It actually compiles, runs, and I'm optimizing the hell out of it. Good times, everyone. This is a major chunk for congo, and the new optimizations should be good. --- misc/raa_format.txt | 20 ++-- src/archive.cpp | 2 +- src/bitstring.cpp | 305 ++++++++++++++++++++++++++++------------------------ src/bitstring.h | 197 +++++++++++++++++---------------- src/file.h | 1 + src/fstring.h | 11 +- src/hash.h | 50 ++++++++- src/nids.cpp | 93 ++++++++++++++++ src/nids.h | 31 +++++- src/nidsstream.cpp | 88 ++++++++++++++- src/nidsstream.h | 32 +++++- src/tests/hash.cpp | 2 +- src/tests/nids.cpp | 19 ++++ src/unit/hash.cpp | 22 +++- src/util.h | 9 ++ 15 files changed, 620 insertions(+), 262 deletions(-) create mode 100644 src/tests/nids.cpp diff --git a/misc/raa_format.txt b/misc/raa_format.txt index 1b2c9f8..693cbc8 100644 --- a/misc/raa_format.txt +++ b/misc/raa_format.txt @@ -22,16 +22,17 @@ structures. The basic header: 00-03: Magic Number, something cute, I dunno yet (encoding independant) -04: Byte count/order for standard indexes (8/4 for 64/32bit systems) - High order bit masked out determines endianness (1 = big, 0 = small) +04: Version code (0) +05: Byte count/order for standard indexes (8/4 for 64/32bit systems) + High order bit masked out determines endianness (1 = big, 0 = little) The program will only accept one word-width for now, we can make it adjustable later, or fix this at 4 bytes. -05-08: Blocksize in bytes, could be anything, I don't think we need to worry +06-09: Blocksize in bytes, could be anything, I don't think we need to worry about OS related things for this, but it should be set intelligently by the owner. This includes the bytes reserved for a block header. -09-12: Total block count, includes both used and unused blocks. -13-16: Total used blocks, useful for determining when to expand. -17-24: Reserved for flags and the like, should be all zeros for now. +10-13: Total block count, includes both used and unused blocks. +14-17: Total used blocks, useful for determining when to expand. +18-24: Reserved for flags and the like, should be all zeros for now. At this point are a number of "blocks" each with their own header and data are laid out sequentially, accessing one should be easy, seek to @@ -45,10 +46,9 @@ The block header is as follows: then this block is the last in the chain. 08-11: Prev block in chain. If this number matches the current block index then this block is the first in the chain. -12-15: Number of bytes used/allocated remaining in the chain. If this is the - first block, then this is the total size of the object accross all - blocks in the chain. For the last block in the chain this will usually - be less than the available space. +12-15: Number of bytes used. If this is the first block, this is the total + amount of data in the stream, otherwise it's the amount of data in the + current block. 16-19: Reserved flagspace or something, make sure it's all zeros. 20-xx: Block data, whatever you wanted to store. At the moment this is going to be (blocksize) - 20 for now, it will change if the block header diff --git a/src/archive.cpp b/src/archive.cpp index 90211fe..c1c89cc 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -512,7 +512,7 @@ void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) if( !hPtrDest.has( id ) ) hPtrDest.insert( id, List() ); - hPtrDest[id].value().append( ptr ); + hPtrDest[id].getValue().append( ptr ); } void Bu::Archive::readID( const void *ptr, uint32_t id ) diff --git a/src/bitstring.cpp b/src/bitstring.cpp index 8d99992..85f89e2 100644 --- a/src/bitstring.cpp +++ b/src/bitstring.cpp @@ -7,59 +7,47 @@ #define random() rand() #endif -#define bitsToBytes( nBits ) (((nBits/8)+((nBits%8)?(1):(0)))); +#define bitsToBytes( iBits ) (((iBits/8)+((iBits%8)?(1):(0)))); Bu::BitString::BitString() { caData = NULL; cTopByteMask = 0; - nBits = nBytes = 0; + iBits = iBytes = 0; } Bu::BitString::BitString( const Bu::BitString &xSrc ) { - nBits = xSrc.nBits; - nBytes = xSrc.nBytes; + iBits = xSrc.iBits; + iBytes = xSrc.iBytes; cTopByteMask = xSrc.cTopByteMask; - caData = new unsigned char[nBytes]; - memcpy( caData, xSrc.caData, nBytes ); + caData = new unsigned char[iBytes]; + memcpy( caData, xSrc.caData, iBytes ); fixup(); } -Bu::BitString::BitString( long nNewBits, bool bFillRandomly ) +Bu::BitString::BitString( long iNewBits, bool bFillRandomly ) { long j; - nBits = nNewBits; - nBytes = bitsToBytes( nNewBits );//(nNewBits/8)+((nNewBits%8)?(1):(0)); - caData = new unsigned char[nBytes]; + iBits = iNewBits; + iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0)); + caData = new unsigned char[iBytes]; - // This can either mean that there are a multiple of eight bits or zero, if there are zero you're an idiot - // (zero can't happen, because we would allocate an extra byte and never use it) - if( (nBits%8 == 0) ) - { - cTopByteMask = 0xFF; - } - else - { - cTopByteMask = 0; - for( j = 0; j < (nBits%8); j++ ) - { - cTopByteMask |= (1<>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask)); } @@ -127,97 +115,97 @@ Bu::BitString Bu::BitString::operator<<( const long nAmt ) return xSub; } -Bu::BitString Bu::BitString::operator>>( const long nAmt ) +Bu::BitString Bu::BitString::operator>>( const long iAmt ) { - if( nAmt == 0 ) + if( iAmt == 0 ) { return (*this); } return (*this); } -void Bu::BitString::shiftLeft( long nAmt ) +void Bu::BitString::shiftLeft( long iAmt ) { - if( nAmt == 0 ) + if( iAmt == 0 ) { return; } - else if( nAmt < 0 ) + else if( iAmt < 0 ) { - shiftRight( -nAmt ); + shiftRight( -iAmt ); return; } - long nByteShift = nAmt/8; - long nBitShift = nAmt%8; + long iByteShift = iAmt/8; + long iBitShift = iAmt%8; long j; - for( j = nBytes-1; j >= 0; j-- ) + for( j = iBytes-1; j >= 0; j-- ) { - caData[j] = (((j-nByteShift)<0)?(0):((caData[j-nByteShift]<>(8-nBitShift)))); + caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<>(8-iBitShift)))); } fixup(); } -void Bu::BitString::shiftRight( long nAmt ) +void Bu::BitString::shiftRight( long iAmt ) { - if( nAmt == 0 ) + if( iAmt == 0 ) { return; } - else if( nAmt < 0 ) + else if( iAmt < 0 ) { - shiftLeft( -nAmt ); + shiftLeft( -iAmt ); return; } - long nByteShift = nAmt/8; - long nBitShift = nAmt%8; + long iByteShift = iAmt/8; + long iBitShift = iAmt%8; long j; - for( j = 0; j < nBytes; j++ ) + for( j = 0; j < iBytes; j++ ) { - caData[j] = (((j+nByteShift)>nBytes)?(0):((caData[j+nByteShift]>>nBitShift))) | (((j+nByteShift+1)>nBytes)?(0):((caData[j+nByteShift+1]<<(8-nBitShift)))); + caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift)))); } fixup(); } /* -long Bu::BitString::bitsToBytes( long nBits ) +long Bu::BitString::bitsToBytes( long iBits ) { - return (nBits/8)+((nBits%8)?(1):(0)); + return (iBits/8)+((iBits%8)?(1):(0)); } */ void Bu::BitString::fixup() { if( caData != NULL ) { - caData[nBytes-1] &= cTopByteMask; + caData[iBytes-1] &= cTopByteMask; } } -void Bu::BitString::setBit( long nBit, bool bBitState ) +void Bu::BitString::setBit( long iBit, bool bBitState ) { if( bBitState ) { - caData[nBit/8] |= (1<<(nBit%8)); + caData[iBit/8] |= (1<<(iBit%8)); } else { - caData[nBit/8] &= ~(1<<(nBit%8)); + caData[iBit/8] &= ~(1<<(iBit%8)); } } -void Bu::BitString::flipBit( long nBit ) +void Bu::BitString::flipBit( long iBit ) { - caData[nBit/8] ^= (1<<(nBit%8)); + caData[iBit/8] ^= (1<<(iBit%8)); } -bool Bu::BitString::getBit( long nBit ) +bool Bu::BitString::getBit( long iBit ) { - if( nBit >= nBits || nBit < 0 ) return false; - if( (caData[nBit/8] & (1<<(nBit%8))) == 0 ) + if( iBit >= iBits || iBit < 0 ) return false; + if( (caData[iBit/8] & (1<<(iBit%8))) == 0 ) { return false; } @@ -226,23 +214,28 @@ bool Bu::BitString::getBit( long nBit ) long Bu::BitString::getBitLength() { - return nBits; + return iBits; +} + +long Bu::BitString::getSize() +{ + return iBits; } -class Bu::BitString Bu::BitString::getSubString( long nLower, long nUpper ) +class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper ) { - if( nUpper == 0 || nUpper < nLower ) nUpper = nBits; + if( iUpper == 0 || iUpper < iLower ) iUpper = iBits; - Bu::BitString xSub( nUpper-nLower+1 ); + Bu::BitString xSub( iUpper-iLower+1 ); - long shft = (nLower%8); - long base = (nLower/8); + long shft = (iLower%8); + long base = (iLower/8); unsigned char lowmask=0; for( long j = 0; j < 8-shft; j++ ) { lowmask |= (1<>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask)); } @@ -251,15 +244,15 @@ class Bu::BitString Bu::BitString::getSubString( long nLower, long nUpper ) return xSub; } -long Bu::BitString::toLong( long nStart, long nSize ) +long Bu::BitString::toLong( long iStart, long iSize ) { - if( nSize < 1 ) nSize = 1; - if( nSize > 32 ) nSize = 32; - if( nStart < 0 ) return 0; - if( nStart+nSize > getBitLength() ) return 0; + if( iSize < 1 ) iSize = 1; + if( iSize > 32 ) iSize = 32; + if( iStart < 0 ) return 0; + if( iStart+iSize > getSize() ) return 0; Bu::BitString tmpo; - tmpo = getSubString( nStart, nStart+nSize-1 ); + tmpo = getSubString( iStart, iStart+iSize-1 ); long x = *((long *)tmpo.caData); return x; @@ -267,17 +260,17 @@ long Bu::BitString::toLong( long nStart, long nSize ) /* std::string Bu::BitString::toString( bool bAddSpacers ) { - long nSz = nBits; + long iSz = iBits; if( bAddSpacers ) { - nSz += (nBits/8); - if( nBits%8 == 0 ) nSz--; + iSz += (iBits/8); + if( iBits%8 == 0 ) iSz--; } std::string xStr; int bw=0; int of=0; - for( int j = nBits-1; j >= 0; j-- ) + for( int j = iBits-1; j >= 0; j-- ) { if( getBit( j ) ) { @@ -291,7 +284,7 @@ std::string Bu::BitString::toString( bool bAddSpacers ) if( bAddSpacers ) { bw++; - if( bw >= 8 && j < nBits-1 ) + if( bw >= 8 && j < iBits-1 ) { bw = 0; of++; @@ -303,74 +296,111 @@ std::string Bu::BitString::toString( bool bAddSpacers ) return xStr; } */ -void Bu::BitString::clearString() +void Bu::BitString::clear() { if( caData != NULL ) { - memset( caData, 0, nBytes ); + memset( caData, 0, iBytes ); } } -bool Bu::BitString::setBitLength( long nLength, bool bClear ) +bool Bu::BitString::setBitLength( long iLength, bool bClear ) { - if( nBits != nLength ) + return setSize( iLength, bClear ); +} + +bool Bu::BitString::setSize( long iLength, bool bClear ) +{ + // First, if there's nothing, then allocate an empty one. + if( caData == NULL ) { - if( bClear || caData == NULL ) + iBits = iLength; + iBytes = bitsToBytes( iLength ); + caData = new unsigned char[iBytes]; + memset( caData, 0, iBytes ); + return true; + } + + // If the new length is the same as the old, don't do anything, but do + // check to see if we should still clear the data. + if( iBits != iLength ) + { + // Ok, we are changing the number if bits, but are we changing the + // number of bytes? + long iNewBytes = bitsToBytes( iLength ); + if( iBytes == iNewBytes ) { - //long j; - nBits = nLength; - nBytes = bitsToBytes( nLength );//(nNewBits/8)+((nNewBits%8)?(1):(0)); - if( caData != NULL ) delete[] caData; - caData = new unsigned char[nBytes]; - memset( caData, 0, nBytes ); + // No? That makes life easier + iBits = iLength; + setMask(); + if( bClear ) + { + clear(); + } } else { - //long j; - nBits = nLength; - long nNewBytes = bitsToBytes( nLength );//(nNewBits/8)+((nNewBits%8)?(1):(0)); - unsigned char *tmp = caData; - caData = new unsigned char[nBytes]; - if( nNewBytes < nBytes ) + // Ok, reallocate and copy... + iBits = iLength; + long iNewBytes = bitsToBytes( iLength ); + if( bClear ) { - memcpy( caData, tmp, nNewBytes ); + delete[] caData; + caData = new unsigned char[iNewBytes]; + memset( caData, 0, iNewBytes ); } else { - memcpy( caData, tmp, nBytes ); + unsigned char *tmp = caData; + caData = new unsigned char[iBytes]; + if( iNewBytes < iBytes ) + { + memcpy( caData, tmp, iNewBytes ); + } + else + { + memcpy( caData, tmp, iBytes ); + } + delete[] tmp; } - delete[] tmp; - nBytes = nNewBytes; + iBytes = iNewBytes; + + setMask(); } - // This can either mean that there are a multiple of eight bits or zero, if there are zero you're an idiot - // (zero can't happen, because we would allocate an extra byte and never use it) - if( (nBits%8 == 0) ) - { - cTopByteMask = 0xFF; - } - else - { - cTopByteMask = 0; - for( long j = 0; j < (nBits%8); j++ ) - { - cTopByteMask |= (1<= 0; j-- ) + for( long j = iBits-1; j >= 0; j-- ) { if( getBit( j ) ) { @@ -405,34 +435,23 @@ long Bu::BitString::getHighestOrderBitPos() /* bool Bu::BitString::writeToFile( FILE *fh ) { - fwrite( &nBits, sizeof(long), 1, fh ); - fwrite( caData, sizeof(char), nBytes, fh ); + fwrite( &iBits, sizeof(long), 1, fh ); + fwrite( caData, sizeof(char), iBytes, fh ); return true; } bool Bu::BitString::readFromFile( FILE *fh ) { - fread( &nBits, sizeof(long), 1, fh ); + fread( &iBits, sizeof(long), 1, fh ); - nBytes = bitsToBytes( nBits ); + iBytes = bitsToBytes( iBits ); if( caData ) delete[] caData; - caData = new unsigned char[nBytes]; + caData = new unsigned char[iBytes]; - fread( caData, sizeof(char), nBytes, fh ); + fread( caData, sizeof(char), iBytes, fh ); - if( (nBits%8 == 0) ) - { - cTopByteMask = 0xFF; - } - else - { - cTopByteMask = 0; - for( int j = 0; j < (nBits%8); j++ ) - { - cTopByteMask |= (1<>. All data in the BitString is shifted to * the right by some number of bits, any data pushed off the edge of the * BitString is lost, and all new data coming in will be zeroed. - * Using a negative value in the shiftRight function will turn it into the - * shiftLeft function. - *@param nAmt The number of bit positions to shift all data. + * Using a negative value in the shiftRight function will turn it into + * the shiftLeft function. + *@param iAmt The number of bit positions to shift all data. */ - void shiftRight( long nAmt ); // just like >> + void shiftRight( long iAmt ); // just like >> /** * Searches through the BitString and returns the index of the highest - * order bit position (the highest index) with an on bit (a bit set to 1). - * This is a handy helper function and rather faster than calling getBit() - * over and over again. + * order bit position (the highest index) with an on bit (a bit set to + * 1). This is a handy helper function and rather faster than calling + * getBit() over and over again. *@returns The index of the highest indexed on bit. */ long getHighestOrderBitPos(); // Conversion /** - * Convert a block of data (no more than 32 bits) to a primitive long type. + * Convert a block of data (no more than 32 bits) to a primitive long + * type. * This is done in a little bit interesting way, so it may not always be * the fastest way to access the data that you want, although it will * always ensure that the long that is written makes numerical sense, as * we write numbers, regaurdless of platform. - *@param nStart The first bit in the BitString to include in the long - *@param nSize THe number of bits to include, if this value is set over + *@param iStart The first bit in the BitString to include in the long + *@param iSize THe number of bits to include, if this value is set over * 32 it will be automatically truncated to, or however many bits there * are in a long in your system. *@returns A long converted from your raw BitString data. */ - long toLong( long nStart = 0, long nSize = 32 ); + long toLong( long iStart = 0, long iSize = 32 ); /** * Converts the data into a human-readable SString object. SString is - * used to make transport of the string and management very simple. Since - * BitStrings will generally be longer than your average strip of ints a - * faculty is included and turned on by default that will insert spacers - * into the output text every 8 places. For debugging work, this is - * definately reccomended. - *@param bAddSpacers Leave set to true in order to have the output broken - * into logical groupings of 8 bits per block. Set to off to have a harder + * used to make transport of the string and management very simple. + * Since BitStrings will generally be longer than your average strip of + * ints a faculty is included and turned on by default that will insert + * spacers into the output text every 8 places. For debugging work, + * this is definately reccomended. + *@param bAddSpacers Leave set to true in order to have the output + * broken into logical groupings of 8 bits per block. Set to off to + * have a harder * to read solid block of bits. *@returns A SString object containing the produced string. */ @@ -202,24 +214,25 @@ namespace Bu // Utility /** * Converts the given number of bits into the smallest allocatable unit, - * which is bytes in C and on most systems nowadays. This is the minimum - * number of bytes needed to contain the given number of bits, so there is - * generally some slop if they are not evenly divisible. - *@param nBits The number of bits you wish to use. + * which is bytes in C and on most systems nowadays. This is the + * minimum number of bytes needed to contain the given number of bits, + * so there is generally some slop if they are not evenly divisible. + *@param iBits The number of bits you wish to use. *@returns The number of bytes you will need to contain the given number * of bits. */ - //static long bitsToBytes( long nBits ); + //static long bitsToBytes( long iBits ); /** * Writes all data in the BitString, including a small header block * describing the number of bits in the BitString to the file described - * by the given file descriptor. The data writen is purely sequential and - * probably not too easy to read by other mechanisms, although the + * by the given file descriptor. The data writen is purely sequential + * and probably not too easy to read by other mechanisms, although the * readFromFile function should always be able to do it. This function * does not open nor close the file pointed to by fh. *@param fh The file descriptor of the file to write the data to. - *@returns true if the operation completed without error, false otherwise. + *@returns true if the operation completed without error, false + * otherwise. */ //bool writeToFile( FILE *fh ); @@ -229,21 +242,23 @@ namespace Bu * original BitString that it may be replacing. This function does not * open nor close the file pointed to by fh. *@param fh The file descriptor to try to read the data from. - *@returns true if the operation completed without error, false otherwise. + *@returns true if the operation completed without error, false + * otherwise. */ //bool readFromFile( FILE *fh ); //operators BitString &operator=( const BitString &xSrc ); BitString operator~(); - BitString operator<<( const long nAmt ); - BitString operator>>( const long nAmt ); + BitString operator<<( const long iAmt ); + BitString operator>>( const long iAmt ); private: void fixup(); + void setMask(); unsigned char *caData; - long nBits; - long nBytes; + long iBits; + long iBytes; unsigned char cTopByteMask; }; }; diff --git a/src/file.h b/src/file.h index b7ce17d..554ebc9 100644 --- a/src/file.h +++ b/src/file.h @@ -32,6 +32,7 @@ namespace Bu virtual void close(); virtual size_t read( void *pBuf, size_t nBytes ); virtual size_t write( const void *pBuf, size_t nBytes ); + using Stream::write; virtual long tell(); virtual void seek( long offset ); diff --git a/src/fstring.h b/src/fstring.h index 31b55d2..a9b4c95 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -19,21 +19,12 @@ #include "bu/archival.h" #include "bu/archive.h" #include "bu/hash.h" +#include "bu/util.h" #ifndef min #define min( a, b ) ((a 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define DEPRECATED __attribute__((__deprecated__)) -#else -#define DEPRECATED -#endif /* __GNUC__ */ - - namespace Bu { template< typename chr > diff --git a/src/hash.h b/src/hash.h index 30ad256..25dc509 100644 --- a/src/hash.h +++ b/src/hash.h @@ -16,6 +16,7 @@ #include #include "bu/exceptionbase.h" #include "bu/list.h" +#include "bu/util.h" ///#include "archival.h" ///#include "archive.h" @@ -97,6 +98,7 @@ namespace Bu * Direct function for retrieving a value out of the HashProxy. *@returns (value_type &) The value pointed to by this HashProxy. */ + DEPRECATED _value &value() { if( bFilled == false ) @@ -106,6 +108,20 @@ namespace Bu ); return *pValue; } + + /** + * Direct function for retrieving a value out of the HashProxy. + *@returns (value_type &) The value pointed to by this HashProxy. + */ + _value &getValue() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return *pValue; + } /** * Whether this HashProxy points to something real or not. @@ -165,7 +181,39 @@ namespace Bu }; /** - * Libbu Template Hash Table + * Libbu++ Template Hash Table. This is your average hash table, that uses + * template functions in order to do fast, efficient, generalized hashing. + * It's pretty easy to use, and works well with all other libbu++ types so + * far. + * + * In order to use it, I recommend the following for all basic usage: + *@code + // Define a Hash typedef with strings as keys and ints as values. + typedef Bu::Hash StrIntHash; + + // Create one + StrIntHash hInts; + + // Insert some integers + hInts["one"] = 1; + hInts["forty-two"] = 42; + hInts.insert("forty two", 42 ); + + // Get values out of the hash, the last two options are the most explicit, + // and must be used if the hash's value type does not match what you're + // comparing to exactly. + if( hInts["one"] == 1 ) doSomething(); + if( hInts["forty-two"].value() == 42 ) doSomething(); + if( hInts.get("forty two") == 42 ) doSomething(); + + // Iterate through the Hash + for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) + { + // i.getValue() works too + print("'%s' = %d\n", i.getKey().getStr(), (*i) ); + } + + @endcode *@param key (typename) The datatype of the hashtable keys *@param value (typename) The datatype of the hashtable data *@param sizecalc (typename) Functor to compute new table size on rehash diff --git a/src/nids.cpp b/src/nids.cpp index b8ea13b..41c4dc1 100644 --- a/src/nids.cpp +++ b/src/nids.cpp @@ -1,8 +1,30 @@ #include "bu/nids.h" +#include "bu/stream.h" +#include "bu/nidsstream.h" +#include Bu::Nids::Nids( Bu::Stream &sStore ) : sStore( sStore ) { + printf("Stream caps:\n" + " canRead: %s\n" + " canWrite: %s\n" + " isReadable: %s\n" + " isWritable: %s\n" + " isSeekable: %s\n" + " isBlocking: %s\n" + " isEOS: %s\n" + " isOpen: %s\n", + sStore.canRead()?"yes":"no", + sStore.canWrite()?"yes":"no", + sStore.isReadable()?"yes":"no", + sStore.isWritable()?"yes":"no", + sStore.isSeekable()?"yes":"no", + sStore.isBlocking()?"yes":"no", + sStore.isEOS()?"yes":"no", + sStore.isOpen()?"yes":"no" + ); + printf("sizeof(Block) = %db\n", sizeof(Block) ); } Bu::Nids::~Nids() @@ -11,11 +33,82 @@ Bu::Nids::~Nids() void Bu::Nids::initialize( int iBlockSize, int iPreAllocate ) { + char cBuf = 0; + int iBuf = 0; + + // Magic number + sStore.write( "\xFF\xC3\x99\xBD", 4 ); + + // Version (0) + sStore.write( &cBuf, 1 ); + + // Bytes per int + cBuf = 4; + sStore.write( &cBuf, 1 ); + + // The size of each block and the number of blocks we're pre-allocating + sStore.write( &iBlockSize, 4 ); + sStore.write( &iPreAllocate, 4 ); + + // The number of used blocks + sStore.write( &iBuf, 4 ); + + // Reserved space + sStore.write( "\x00\x00\x00\x00\x00\x00\x00", 7 ); + + this->iBlockSize = iBlockSize; + this->iBlocks = iPreAllocate; + this->iBlockStart = sStore.tell(); + bsBlockUsed.setSize( iPreAllocate, true ); + + printf("%d blocks, %db each, %db block offset\n", + iBlocks, iBlockSize, iBlockStart ); + + char *block = new char[iBlockSize]; + memset( block, 0, iBlockSize ); + for( int j = 0; j < iPreAllocate; j++ ) + { + sStore.write( block, iBlockSize ); + } } int Bu::Nids::createStream( int iPreAllocate ) { + for( int j = 0; j < iBlocks; j++ ) + { + if( !bsBlockUsed.getBit( j ) ) + { + Block b = { j, blockUnused, blockUnused, 0, 0 }; + bsBlockUsed.setBit( j ); + sStore.setPos( iBlockStart+(iBlockSize*j) ); + sStore.write( &b, sizeof(b) ); + } + } return 0; } +void Bu::Nids::deleteStream( int iID ) +{ +} + +Bu::NidsStream Bu::Nids::openStream( int iID ) +{ + return NidsStream( *this ); +} + +void Bu::Nids::extendStream( int iID, int iBlockCount ) +{ +} + +void Bu::Nids::getBlock( int iIndex, Bu::Nids::Block *pBlock ) +{ + sStore.setPos( iBlockStart + (iBlockSize*iIndex) ); + sStore.read( pBlock, iBlockSize ); +} + +void Bu::Nids::setBlock( int iIndex, Bu::Nids::Block *pBlock ) +{ + sStore.setPos( iBlockStart + (iBlockSize*iIndex) ); + sStore.write( pBlock, iBlockSize ); +} diff --git a/src/nids.h b/src/nids.h index 9954146..e364289 100644 --- a/src/nids.h +++ b/src/nids.h @@ -1,9 +1,13 @@ #ifndef BU_NIDS_H #define BU_NIDS_H +#include +#include "bu/bitstring.h" + namespace Bu { class Stream; + class NidsStream; /** * Numerically Indexed Data Streams. This is a working name so I can @@ -14,6 +18,7 @@ namespace Bu */ class Nids { + friend class NidsStream; public: Nids( Bu::Stream &sStore ); virtual ~Nids(); @@ -39,10 +44,34 @@ namespace Bu /** * Return a new Stream object assosiated with the given stream ID. */ - Bu::Stream &openStream( int iID ); + NidsStream openStream( int iID ); + + private: + typedef struct Block + { + uint32_t iFirstBlock; + uint32_t iNextBlock; + uint32_t iPrevBlock; + uint32_t iBytesUsed; + uint32_t iReserved; + unsigned char pData[0]; + } Block; + + enum + { + blockUnused = 0xFFFFFFFFUL + }; + + void extendStream( int iID, int iBlockCount=1 ); + void getBlock( int iIndex, struct Nids::Block *pBlock ); + void setBlock( int iIndex, struct Nids::Block *pBlock ); private: Bu::Stream &sStore; + int iBlockSize; + int iBlocks; + int iBlockStart; + Bu::BitString bsBlockUsed; }; }; diff --git a/src/nidsstream.cpp b/src/nidsstream.cpp index d05fbc0..e3bd731 100644 --- a/src/nidsstream.cpp +++ b/src/nidsstream.cpp @@ -1,10 +1,96 @@ #include "bu/nidsstream.h" -Bu::NidsStream::NidsStream() +Bu::NidsStream::NidsStream( Nids &rNids ) : + rNids( rNids ) { } +Bu::NidsStream::NidsStream( const Bu::NidsStream &rSrc ) : + rNids( rSrc.rNids ) +{ + +} + Bu::NidsStream::~NidsStream() { } +void Bu::NidsStream::close() +{ +} + +size_t Bu::NidsStream::read( void *pBuf, size_t nBytes ) +{ + return 0; +} + +size_t Bu::NidsStream::write( const void *pBuf, size_t nBytes ) +{ + return 0; +} + +long Bu::NidsStream::tell() +{ + return 0; +} + +void Bu::NidsStream::seek( long offset ) +{ +} + +void Bu::NidsStream::setPos( long pos ) +{ +} + +void Bu::NidsStream::setPosEnd( long pos ) +{ +} + +bool Bu::NidsStream::isEOS() +{ + return true; +} + +bool Bu::NidsStream::isOpen() +{ + return true; +} + +void Bu::NidsStream::flush() +{ +} + +bool Bu::NidsStream::canRead() +{ + return true; +} + +bool Bu::NidsStream::canWrite() +{ + return true; +} + +bool Bu::NidsStream::isReadable() +{ + return true; +} + +bool Bu::NidsStream::isWritable() +{ + return true; +} + +bool Bu::NidsStream::isSeekable() +{ + return true; +} + +bool Bu::NidsStream::isBlocking() +{ + return true; +} + +void Bu::NidsStream::setBlocking( bool bBlocking ) +{ +} + diff --git a/src/nidsstream.h b/src/nidsstream.h index 08b45eb..8021dee 100644 --- a/src/nidsstream.h +++ b/src/nidsstream.h @@ -2,16 +2,46 @@ #define BU_NIDS_STREAM_H #include "bu/stream.h" +#include "bu/nids.h" namespace Bu { class NidsStream : public Bu::Stream { + friend class Nids; + private: + /** + * These can only be created by the Nids class. + */ + NidsStream( Nids &rNids ); + NidsStream( const NidsStream &rSrc ); + public: - NidsStream(); virtual ~NidsStream(); + virtual void close(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); + using Stream::write; + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + virtual bool isOpen(); + virtual void flush(); + virtual bool canRead(); + virtual bool canWrite(); + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + private: + Nids &rNids; + typedef struct Bu::Hash BlockHash; + BlockHash hBlock; }; }; diff --git a/src/tests/hash.cpp b/src/tests/hash.cpp index 76cf0ec..9cc45f5 100644 --- a/src/tests/hash.cpp +++ b/src/tests/hash.cpp @@ -25,7 +25,7 @@ int main() for( int j = 0; j < 10; j++ ) { - printf("%d\n", lb[j].value()->nID ); + printf("%d\n", lb[j].getValue()->nID ); } } diff --git a/src/tests/nids.cpp b/src/tests/nids.cpp new file mode 100644 index 0000000..1197ac1 --- /dev/null +++ b/src/tests/nids.cpp @@ -0,0 +1,19 @@ +#include "bu/file.h" +#include "bu/nids.h" + +int main( int argc, char *argv[] ) +{ + if( argc < 2 ) + { + printf("usage: %s \n\n", argv[0] ); + return 1; + } + + Bu::File fOut( argv[1], "wb"); + Bu::Nids n( fOut ); + + n.initialize( 1024, 5 ); + + Bu::NidsStream s = n.openStream( n.createStream() ); +} + diff --git a/src/unit/hash.cpp b/src/unit/hash.cpp index 481256b..b869bdd 100644 --- a/src/unit/hash.cpp +++ b/src/unit/hash.cpp @@ -15,18 +15,22 @@ class Unit : public Bu::UnitSuite { private: typedef Bu::Hash StrIntHash; + typedef Bu::Hash StrStrHash; + public: Unit() { setName("Hash"); - addTest( Unit::test_probe ); + addTest( Unit::insert1 ); + addTest( Unit::insert2 ); + addTest( Unit::probe1 ); } virtual ~Unit() { } - void test_probe() + void probe1() { StrIntHash h; char buf[20]; @@ -38,6 +42,20 @@ public: unitTest( h.has(sTmp) ); } } + + void insert1() + { + StrIntHash h; + h["Hi"] = 42; + unitTest( h["Hi"] == 42 ); + } + + void insert2() + { + StrStrHash h; + h["Hi"] = "Yo"; + unitTest( h["Hi"].getValue() == "Yo" ); + } }; int main( int argc, char *argv[] ) diff --git a/src/util.h b/src/util.h index 6205c04..b55ceee 100644 --- a/src/util.h +++ b/src/util.h @@ -8,6 +8,15 @@ #ifndef BU_UTIL_H #define BU_UTIL_H +/* I borrowed this from someone who borrowed it from glib who borrowed it + * from... + */ +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define DEPRECATED __attribute__((__deprecated__)) +#else +#define DEPRECATED +#endif /* __GNUC__ */ + namespace Bu { template -- cgit v1.2.3