diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.h | 245 | ||||
| -rw-r--r-- | src/bitstring.cpp | 9 | ||||
| -rw-r--r-- | src/bitstring.h | 3 | ||||
| -rw-r--r-- | src/myriad.cpp | 284 | ||||
| -rw-r--r-- | src/myriad.h | 144 | ||||
| -rw-r--r-- | src/myriadstream.cpp | 223 | ||||
| -rw-r--r-- | src/myriadstream.h | 58 | ||||
| -rw-r--r-- | src/tests/nids.cpp | 10 | ||||
| -rw-r--r-- | src/tools/myriad.cpp | 115 | ||||
| -rw-r--r-- | src/unit/array.unit | 2 |
10 files changed, 1010 insertions, 83 deletions
diff --git a/src/array.h b/src/array.h index 6279382..af41c33 100644 --- a/src/array.h +++ b/src/array.h | |||
| @@ -11,10 +11,95 @@ | |||
| 11 | #include <memory> | 11 | #include <memory> |
| 12 | #include "bu/exceptionbase.h" | 12 | #include "bu/exceptionbase.h" |
| 13 | #include "bu/archivebase.h" | 13 | #include "bu/archivebase.h" |
| 14 | #include "bu/sharedcore.h" | ||
| 14 | 15 | ||
| 15 | namespace Bu | 16 | namespace Bu |
| 16 | { | 17 | { |
| 17 | subExceptionDecl( ArrayException ) | 18 | subExceptionDecl( ArrayException ) |
| 19 | |||
| 20 | template<typename value, int inc, typename valuealloc> | ||
| 21 | class ArrayCore | ||
| 22 | { | ||
| 23 | public: | ||
| 24 | ArrayCore() : | ||
| 25 | pData( NULL ), | ||
| 26 | iSize( 0 ), | ||
| 27 | iCapacity( 0 ) | ||
| 28 | { } | ||
| 29 | |||
| 30 | void setCapacity( int iNewLen ) | ||
| 31 | { | ||
| 32 | //clear(); | ||
| 33 | //iCapacity = iCapacity; | ||
| 34 | //pData = va.allocate( iCapacity ); | ||
| 35 | if( iNewLen <= iCapacity ) return; | ||
| 36 | value *pNewData = va.allocate( iNewLen ); | ||
| 37 | if( pData ) | ||
| 38 | { | ||
| 39 | for( int j = 0; j < iSize; j++ ) | ||
| 40 | { | ||
| 41 | va.construct( &pNewData[j], pData[j] ); | ||
| 42 | va.destroy( &pData[j] ); | ||
| 43 | } | ||
| 44 | va.deallocate( pData, iCapacity ); | ||
| 45 | } | ||
| 46 | pData = pNewData; | ||
| 47 | iCapacity = iNewLen; | ||
| 48 | } | ||
| 49 | |||
| 50 | virtual ~ArrayCore() | ||
| 51 | { | ||
| 52 | clear(); | ||
| 53 | } | ||
| 54 | |||
| 55 | void clear() | ||
| 56 | { | ||
| 57 | if( pData ) | ||
| 58 | { | ||
| 59 | for( int j = 0; j < iSize; j++ ) | ||
| 60 | { | ||
| 61 | va.destroy( &pData[j] ); | ||
| 62 | } | ||
| 63 | va.deallocate( pData, iCapacity ); | ||
| 64 | pData = NULL; | ||
| 65 | } | ||
| 66 | iSize = 0; | ||
| 67 | iCapacity = 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | void erase( int iPos ) | ||
| 71 | { | ||
| 72 | for( int j = iPos; j < iSize; j++ ) | ||
| 73 | { | ||
| 74 | va.destroy( &pData[j] ); | ||
| 75 | if( j == iSize-1 ) | ||
| 76 | { | ||
| 77 | iSize--; | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | va.construct( &pData[j], pData[j+1] ); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void swapErase( int iPos ) | ||
| 85 | { | ||
| 86 | if( iPos == iSize-1 ) | ||
| 87 | { | ||
| 88 | erase( iPos ); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | va.destroy( &pData[iPos] ); | ||
| 92 | va.construct( &pData[iPos], pData[iSize-1] ); | ||
| 93 | va.destroy( &pData[iSize-1] ); | ||
| 94 | iSize--; | ||
| 95 | } | ||
| 96 | |||
| 97 | valuealloc va; | ||
| 98 | value *pData; | ||
| 99 | long iSize; | ||
| 100 | long iCapacity; | ||
| 101 | }; | ||
| 102 | |||
| 18 | /** | 103 | /** |
| 19 | * Array type container, just like a normal array only flexible and keeps | 104 | * Array type container, just like a normal array only flexible and keeps |
| 20 | * track of your memory for you. | 105 | * track of your memory for you. |
| @@ -25,51 +110,57 @@ namespace Bu | |||
| 25 | *@ingroup Containers | 110 | *@ingroup Containers |
| 26 | */ | 111 | */ |
| 27 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > | 112 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > |
| 28 | class Array | 113 | class Array : public SharedCore<ArrayCore<value, inc, valuealloc> > |
| 29 | { | 114 | { |
| 30 | private: | 115 | private: |
| 31 | typedef class Array<value, inc, valuealloc> MyType; | 116 | typedef class Array<value, inc, valuealloc> MyType; |
| 117 | typedef class ArrayCore<value, inc, valuealloc> Core; | ||
| 118 | |||
| 119 | protected: | ||
| 120 | using SharedCore< Core >::core; | ||
| 121 | using SharedCore< Core >::_hardCopy; | ||
| 122 | using SharedCore< Core >::_allocateCore; | ||
| 32 | 123 | ||
| 33 | public: | 124 | public: |
| 34 | Array() : | 125 | struct const_iterator; |
| 35 | pData( NULL ), | 126 | struct iterator; |
| 36 | iSize( 0 ), | 127 | |
| 37 | iCapacity( 0 ) | 128 | Array() |
| 38 | { | 129 | { |
| 39 | } | 130 | } |
| 40 | 131 | ||
| 41 | Array( const MyType &src ) : | 132 | Array( const MyType &src ) : |
| 42 | pData( NULL ), | 133 | SharedCore< Core >( src ) |
| 43 | iSize( 0 ), | ||
| 44 | iCapacity( 0 ) | ||
| 45 | { | 134 | { |
| 46 | *this = src; | ||
| 47 | } | 135 | } |
| 48 | 136 | ||
| 49 | Array( long iSetCap ) : | 137 | Array( long iSetCap ) |
| 50 | pData( NULL ), | ||
| 51 | iSize( 0 ), | ||
| 52 | iCapacity( 0 ) | ||
| 53 | { | 138 | { |
| 54 | setCapacity( iSetCap ); | 139 | setCapacity( iSetCap ); |
| 55 | } | 140 | } |
| 56 | 141 | ||
| 57 | ~Array() | 142 | ~Array() |
| 58 | { | 143 | { |
| 59 | clear(); | ||
| 60 | } | 144 | } |
| 61 | 145 | ||
| 62 | MyType &operator=( const MyType &src ) | 146 | bool operator==( const MyType &src ) const |
| 63 | { | 147 | { |
| 64 | clear(); | 148 | if( core == src.core ) |
| 65 | setCapacity( src.iCapacity ); | 149 | return true; |
| 150 | if( core->iSize != src.core->iSize ) | ||
| 151 | return false; | ||
| 66 | 152 | ||
| 67 | long iTop = src.getSize(); | 153 | for( int j = 0; j < core->iSize; j++ ) |
| 68 | for( long i = 0; i < iTop; ++i ) | ||
| 69 | { | 154 | { |
| 70 | append( src[i] ); | 155 | if( core->pData[j] != src.core->pData[j] ) |
| 156 | return false; | ||
| 71 | } | 157 | } |
| 72 | return *this; | 158 | return true; |
| 159 | } | ||
| 160 | |||
| 161 | bool operator!=( const MyType &src ) const | ||
| 162 | { | ||
| 163 | return !(*this == src); | ||
| 73 | } | 164 | } |
| 74 | 165 | ||
| 75 | /** | 166 | /** |
| @@ -77,46 +168,61 @@ namespace Bu | |||
| 77 | */ | 168 | */ |
| 78 | void clear() | 169 | void clear() |
| 79 | { | 170 | { |
| 80 | if( pData ) | 171 | _hardCopy(); |
| 81 | { | 172 | core->clear(); |
| 82 | for( int j = 0; j < iSize; j++ ) | ||
| 83 | { | ||
| 84 | va.destroy( &pData[j] ); | ||
| 85 | } | ||
| 86 | va.deallocate( pData, iCapacity ); | ||
| 87 | pData = NULL; | ||
| 88 | } | ||
| 89 | iSize = 0; | ||
| 90 | iCapacity = 0; | ||
| 91 | } | 173 | } |
| 92 | 174 | ||
| 93 | void append( const value &rVal ) | 175 | void append( const value &rVal ) |
| 94 | { | 176 | { |
| 95 | if( iSize == iCapacity ) | 177 | _hardCopy(); |
| 178 | if( core->iSize == core->iCapacity ) | ||
| 96 | { | 179 | { |
| 97 | setCapacity( iCapacity + inc ); | 180 | core->setCapacity( core->iCapacity + inc ); |
| 98 | } | 181 | } |
| 99 | 182 | ||
| 100 | va.construct( &pData[iSize++], rVal ); | 183 | core->va.construct( &core->pData[core->iSize++], rVal ); |
| 101 | } | 184 | } |
| 102 | 185 | ||
| 103 | //operator | 186 | //operator |
| 104 | value &operator[]( long iIndex ) | 187 | value &operator[]( long iIndex ) |
| 105 | { | 188 | { |
| 106 | if( iIndex < 0 || iIndex >= iSize ) | 189 | _hardCopy(); |
| 190 | if( iIndex < 0 || iIndex >= core->iSize ) | ||
| 107 | throw ArrayException( | 191 | throw ArrayException( |
| 108 | "Index %d out of range 0:%d", iIndex, iSize ); | 192 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
| 109 | 193 | ||
| 110 | return pData[iIndex]; | 194 | return core->pData[iIndex]; |
| 111 | } | 195 | } |
| 112 | 196 | ||
| 113 | const value &operator[]( long iIndex ) const | 197 | const value &operator[]( long iIndex ) const |
| 114 | { | 198 | { |
| 115 | if( iIndex < 0 || iIndex >= iSize ) | 199 | if( iIndex < 0 || iIndex >= core->iSize ) |
| 116 | throw ArrayException( | 200 | throw ArrayException( |
| 117 | "Index %d out of range 0:%d", iIndex, iSize ); | 201 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
| 202 | |||
| 203 | return core->pData[iIndex]; | ||
| 204 | } | ||
| 205 | |||
| 206 | value &first() | ||
| 207 | { | ||
| 208 | _hardCopy(); | ||
| 209 | return core->pData[0]; | ||
| 210 | } | ||
| 211 | |||
| 212 | const value &first() const | ||
| 213 | { | ||
| 214 | return core->pData[0]; | ||
| 215 | } | ||
| 216 | |||
| 217 | value &last() | ||
| 218 | { | ||
| 219 | _hardCopy(); | ||
| 220 | return core->pData[core->iSize-1]; | ||
| 221 | } | ||
| 118 | 222 | ||
| 119 | return pData[iIndex]; | 223 | const value &last() const |
| 224 | { | ||
| 225 | return core->pData[core->iSize-1]; | ||
| 120 | } | 226 | } |
| 121 | 227 | ||
| 122 | /** | 228 | /** |
| @@ -125,7 +231,7 @@ namespace Bu | |||
| 125 | */ | 231 | */ |
| 126 | long getSize() const | 232 | long getSize() const |
| 127 | { | 233 | { |
| 128 | return iSize; | 234 | return core->iSize; |
| 129 | } | 235 | } |
| 130 | 236 | ||
| 131 | /** | 237 | /** |
| @@ -136,7 +242,7 @@ namespace Bu | |||
| 136 | */ | 242 | */ |
| 137 | long getCapacity() const | 243 | long getCapacity() const |
| 138 | { | 244 | { |
| 139 | return iCapacity; | 245 | return core->iCapacity; |
| 140 | } | 246 | } |
| 141 | 247 | ||
| 142 | /** | 248 | /** |
| @@ -149,19 +255,8 @@ namespace Bu | |||
| 149 | */ | 255 | */ |
| 150 | void setCapacity( long iNewLen ) | 256 | void setCapacity( long iNewLen ) |
| 151 | { | 257 | { |
| 152 | if( iNewLen <= iCapacity ) return; | 258 | _hardCopy(); |
| 153 | value *pNewData = va.allocate( iNewLen ); | 259 | core->setCapacity( iNewLen ); |
| 154 | if( pData ) | ||
| 155 | { | ||
| 156 | for( int j = 0; j < iSize; j++ ) | ||
| 157 | { | ||
| 158 | va.construct( &pNewData[j], pData[j] ); | ||
| 159 | va.destroy( &pData[j] ); | ||
| 160 | } | ||
| 161 | va.deallocate( pData, iCapacity ); | ||
| 162 | } | ||
| 163 | pData = pNewData; | ||
| 164 | iCapacity = iNewLen; | ||
| 165 | } | 260 | } |
| 166 | 261 | ||
| 167 | typedef struct iterator | 262 | typedef struct iterator |
| @@ -387,16 +482,8 @@ namespace Bu | |||
| 387 | */ | 482 | */ |
| 388 | void erase( iterator i ) | 483 | void erase( iterator i ) |
| 389 | { | 484 | { |
| 390 | for( int j = i.iPos; j < iSize; j++ ) | 485 | _hardCopy(); |
| 391 | { | 486 | core->erase( i.iPos ); |
| 392 | va.destroy( &pData[j] ); | ||
| 393 | if( j == iSize-1 ) | ||
| 394 | { | ||
| 395 | iSize--; | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | va.construct( &pData[j], pData[j+1] ); | ||
| 399 | } | ||
| 400 | } | 487 | } |
| 401 | 488 | ||
| 402 | /** | 489 | /** |
| @@ -408,22 +495,24 @@ namespace Bu | |||
| 408 | */ | 495 | */ |
| 409 | void swapErase( iterator i ) | 496 | void swapErase( iterator i ) |
| 410 | { | 497 | { |
| 411 | if( i.iPos == iSize-1 ) | 498 | _hardCopy(); |
| 412 | { | 499 | swapErase( i.iPos ); |
| 413 | erase( i ); | 500 | } |
| 414 | return; | 501 | |
| 502 | protected: | ||
| 503 | virtual Core *_copyCore( Core *src ) | ||
| 504 | { | ||
| 505 | Core *pRet = _allocateCore(); | ||
| 506 | pRet->setCapacity( src->iCapacity ); | ||
| 507 | pRet->iSize = src->iSize; | ||
| 508 | for( int j = 0; j < src->iSize; j++ ) | ||
| 509 | { | ||
| 510 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); | ||
| 415 | } | 511 | } |
| 416 | va.destroy( &pData[i.iPos] ); | 512 | return pRet; |
| 417 | va.construct( &pData[i.iPos], pData[iSize-1] ); | ||
| 418 | va.destroy( &pData[iSize-1] ); | ||
| 419 | iSize--; | ||
| 420 | } | 513 | } |
| 421 | 514 | ||
| 422 | private: | 515 | private: |
| 423 | valuealloc va; | ||
| 424 | value *pData; | ||
| 425 | long iSize; | ||
| 426 | long iCapacity; | ||
| 427 | }; | 516 | }; |
| 428 | 517 | ||
| 429 | class Formatter; | 518 | class Formatter; |
diff --git a/src/bitstring.cpp b/src/bitstring.cpp index f05818f..a7881cc 100644 --- a/src/bitstring.cpp +++ b/src/bitstring.cpp | |||
| @@ -443,6 +443,15 @@ long Bu::BitString::getHighestOrderBitPos() | |||
| 443 | 443 | ||
| 444 | return -1; | 444 | return -1; |
| 445 | } | 445 | } |
| 446 | |||
| 447 | Bu::FString Bu::BitString::toString() | ||
| 448 | { | ||
| 449 | Bu::FString sRet; | ||
| 450 | for( int j = iBits-1; j >= 0; j-- ) | ||
| 451 | sRet.append( getBit( j )?'1':'0' ); | ||
| 452 | return sRet; | ||
| 453 | } | ||
| 454 | |||
| 446 | /* | 455 | /* |
| 447 | bool Bu::BitString::writeToFile( FILE *fh ) | 456 | bool Bu::BitString::writeToFile( FILE *fh ) |
| 448 | { | 457 | { |
diff --git a/src/bitstring.h b/src/bitstring.h index b5f1ada..7a83f50 100644 --- a/src/bitstring.h +++ b/src/bitstring.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #define BU_BITSTRING_H | 9 | #define BU_BITSTRING_H |
| 10 | 10 | ||
| 11 | #include "bu/util.h" | 11 | #include "bu/util.h" |
| 12 | #include "bu/fstring.h" | ||
| 12 | 13 | ||
| 13 | namespace Bu | 14 | namespace Bu |
| 14 | { | 15 | { |
| @@ -202,6 +203,8 @@ namespace Bu | |||
| 202 | */ | 203 | */ |
| 203 | long toLong( long iStart = 0, long iSize = 32 ); | 204 | long toLong( long iStart = 0, long iSize = 32 ); |
| 204 | 205 | ||
| 206 | Bu::FString toString(); | ||
| 207 | |||
| 205 | //operators | 208 | //operators |
| 206 | BitString &operator=( const BitString &xSrc ); | 209 | BitString &operator=( const BitString &xSrc ); |
| 207 | BitString operator~(); | 210 | BitString operator~(); |
diff --git a/src/myriad.cpp b/src/myriad.cpp new file mode 100644 index 0000000..64c8d20 --- /dev/null +++ b/src/myriad.cpp | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "bu/myriad.h" | ||
| 9 | #include "bu/stream.h" | ||
| 10 | #include "bu/myriadstream.h" | ||
| 11 | #include <stdio.h> | ||
| 12 | |||
| 13 | #include "bu/sio.h" | ||
| 14 | using Bu::sio; | ||
| 15 | using Bu::Fmt; | ||
| 16 | |||
| 17 | #define Myriad_MAGIC_CODE ((unsigned char *)"\xFF\xC3\x99\xBD") | ||
| 18 | |||
| 19 | namespace Bu | ||
| 20 | { | ||
| 21 | subExceptionDef( MyriadException ) | ||
| 22 | template<typename t> t blkDiv( t total, t block ) { | ||
| 23 | return (total/block)+((total%block==0)?(0):(1)); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | Bu::Myriad::Myriad( Bu::Stream &sStore ) : | ||
| 28 | sStore( sStore ), | ||
| 29 | iBlockSize( 0 ), | ||
| 30 | iBlocks( 0 ), | ||
| 31 | iUsed( 0 ) | ||
| 32 | { | ||
| 33 | } | ||
| 34 | |||
| 35 | Bu::Myriad::~Myriad() | ||
| 36 | { | ||
| 37 | updateHeader(); | ||
| 38 | |||
| 39 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | ||
| 40 | { | ||
| 41 | delete *i; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | void Bu::Myriad::sync() | ||
| 46 | { | ||
| 47 | updateHeader(); | ||
| 48 | |||
| 49 | // Later, also flush all caches. | ||
| 50 | } | ||
| 51 | |||
| 52 | void Bu::Myriad::initialize() | ||
| 53 | { | ||
| 54 | sStore.setPosEnd( 0 ); | ||
| 55 | int iSize = sStore.tell(); | ||
| 56 | sStore.setPos( 0 ); | ||
| 57 | |||
| 58 | unsigned char buf[4]; | ||
| 59 | if( sStore.read( buf, 4 ) < 4 ) | ||
| 60 | throw MyriadException("Input stream appears to be empty."); | ||
| 61 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | ||
| 62 | { | ||
| 63 | throw MyriadException( | ||
| 64 | "Stream does not appear to be a valid Myriad format."); | ||
| 65 | } | ||
| 66 | sStore.read( buf, 2 ); | ||
| 67 | if( buf[0] != 1 ) | ||
| 68 | throw MyriadException( | ||
| 69 | "We can only handle version 1 for now."); | ||
| 70 | if( buf[1] != 32 ) | ||
| 71 | throw MyriadException( | ||
| 72 | "We can only handle 32-bit words at the moment."); | ||
| 73 | sStore.read( &iBlockSize, 4 ); | ||
| 74 | int iStreams; | ||
| 75 | sStore.read( &iStreams, 4 ); | ||
| 76 | |||
| 77 | iBlocks = iSize/iBlockSize; | ||
| 78 | sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize | ||
| 79 | << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; | ||
| 80 | |||
| 81 | int iHeaderSize = 14 + 8 + 4; | ||
| 82 | int iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
| 83 | |||
| 84 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | ||
| 85 | { | ||
| 86 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | ||
| 87 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
| 88 | } | ||
| 89 | |||
| 90 | sio << "Myriad: iHeaderSize=" << iHeaderSize | ||
| 91 | << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | ||
| 92 | |||
| 93 | bsBlockUsed.setSize( iBlocks, true ); | ||
| 94 | |||
| 95 | bool bCanSkip = false; // Can skip around, post initial header stream i/o | ||
| 96 | for( int j = 0; j < iStreams; j++ ) | ||
| 97 | { | ||
| 98 | int iHdrBlock = 0; | ||
| 99 | int iCurBlock = 0; | ||
| 100 | aStreams.append( new Stream() ); | ||
| 101 | Stream &s = *aStreams[j]; | ||
| 102 | sStore.read( &s.iId, 4 ); | ||
| 103 | sStore.read( &s.iSize, 4 ); | ||
| 104 | int iSBlocks = blkDiv(s.iSize, iBlockSize); | ||
| 105 | sio << "Myriad: - Stream::iId=" << s.iId << ", Stream::iSize=" << s.iSize | ||
| 106 | << ", Stream::aBlocks=" << iSBlocks | ||
| 107 | << ", sStore.tell()=" << sStore.tell() << sio.nl; | ||
| 108 | for( int k = 0; k < iSBlocks; k++ ) | ||
| 109 | { | ||
| 110 | int iBId; | ||
| 111 | sStore.read( &iBId, 4 ); | ||
| 112 | sio << "Myriad: - iBId=" << iBId | ||
| 113 | << ", iStartPos=" << iBId*iBlockSize | ||
| 114 | << ", sStore.tell()=" << sStore.tell() << sio.nl; | ||
| 115 | s.aBlocks.append( iBId ); | ||
| 116 | bsBlockUsed.setBit( iBId ); | ||
| 117 | if( (j == 0 && k == iHeaderBlocks-1) ) | ||
| 118 | { | ||
| 119 | sio << "Myriad: - End of prepartition, unlocking skipping." | ||
| 120 | << sio.nl; | ||
| 121 | bCanSkip = true; | ||
| 122 | iCurBlock = blkDiv( (int)sStore.tell(), iBlockSize ); | ||
| 123 | } | ||
| 124 | if( bCanSkip && sStore.tell() >= iCurBlock*iBlockSize+iBlockSize ) | ||
| 125 | { | ||
| 126 | iHdrBlock++; | ||
| 127 | iCurBlock = aStreams[0]->aBlocks[iHdrBlock]; | ||
| 128 | sio << "Myriad: Ran out of data in block, finding next header " | ||
| 129 | "block: " << iHdrBlock << " = " << iCurBlock << " (" | ||
| 130 | << iCurBlock*iBlockSize << "b)" << sio.nl; | ||
| 131 | sStore.setPos( iCurBlock*iBlockSize ); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | sio << bsBlockUsed.toString() << sio.nl; | ||
| 137 | |||
| 138 | //printf("%d blocks, %db each, %db block offset\n", | ||
| 139 | // iBlocks, iBlockSize, iBlockStart ); | ||
| 140 | |||
| 141 | } | ||
| 142 | |||
| 143 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) | ||
| 144 | { | ||
| 145 | int iHeaderSize = 14 + 8 + 4; | ||
| 146 | int iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
| 147 | char cBuf = 1; | ||
| 148 | int iBuf = 0; | ||
| 149 | |||
| 150 | Stream *pStr = new Stream; | ||
| 151 | pStr->iId = 0; | ||
| 152 | |||
| 153 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | ||
| 154 | { | ||
| 155 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | ||
| 156 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
| 157 | } | ||
| 158 | |||
| 159 | iPreAllocate += iHeaderBlocks; | ||
| 160 | |||
| 161 | sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" | ||
| 162 | << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | ||
| 163 | |||
| 164 | bsBlockUsed.setSize( iPreAllocate, true ); | ||
| 165 | |||
| 166 | char *pBlock = new char[iBlockSize]; | ||
| 167 | memset( pBlock, 0, iBlockSize ); | ||
| 168 | for( int j = 0; j < iPreAllocate; j++ ) | ||
| 169 | { | ||
| 170 | sStore.write( pBlock, iBlockSize ); | ||
| 171 | pStr->aBlocks.append( j ); | ||
| 172 | } | ||
| 173 | delete[] (char *)pBlock; | ||
| 174 | |||
| 175 | sStore.setPos( 0 ); | ||
| 176 | |||
| 177 | // Magic number | ||
| 178 | sStore.write( Myriad_MAGIC_CODE, 4 ); | ||
| 179 | |||
| 180 | // Version (0) | ||
| 181 | sStore.write( &cBuf, 1 ); | ||
| 182 | |||
| 183 | // Bits per int | ||
| 184 | cBuf = 32; | ||
| 185 | sStore.write( &cBuf, 1 ); | ||
| 186 | |||
| 187 | // The size of each block | ||
| 188 | sStore.write( &iBlockSize, 4 ); | ||
| 189 | |||
| 190 | iBuf = 1; | ||
| 191 | // The number of streams | ||
| 192 | sStore.write( &iBuf, 4 ); | ||
| 193 | |||
| 194 | // Stream header | ||
| 195 | iBuf = 0; | ||
| 196 | sStore.write( &iBuf, 4 ); | ||
| 197 | sStore.write( &iHeaderSize, 4 ); | ||
| 198 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) | ||
| 199 | { | ||
| 200 | sStore.write( &iBuf, 4 ); | ||
| 201 | } | ||
| 202 | |||
| 203 | this->iBlockSize = iBlockSize; | ||
| 204 | this->iBlocks = iPreAllocate; | ||
| 205 | |||
| 206 | pStr->iSize = sStore.tell(); | ||
| 207 | |||
| 208 | //hStreams.insert( 0, BlockArray( 0 ) ); | ||
| 209 | } | ||
| 210 | |||
| 211 | void Bu::Myriad::updateHeader() | ||
| 212 | { | ||
| 213 | if( !sStore.canWrite() ) | ||
| 214 | return; | ||
| 215 | |||
| 216 | |||
| 217 | |||
| 218 | // TODO: Use the stream class to access this really smoothly, I hope :) | ||
| 219 | } | ||
| 220 | |||
| 221 | int Bu::Myriad::createStream( int iPreAllocate ) | ||
| 222 | { | ||
| 223 | Stream *pStr = new Stream(); | ||
| 224 | pStr->iId = aStreams.last()->iId+1; | ||
| 225 | sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | ||
| 226 | << iPreAllocate << sio.nl; | ||
| 227 | pStr->iSize = 0; | ||
| 228 | |||
| 229 | for( int j = 0; j < iPreAllocate; j++ ) | ||
| 230 | { | ||
| 231 | int iFreeBlock = findEmptyBlock(); | ||
| 232 | sio << "Myriad: Adding block " << j << sio.nl; | ||
| 233 | pStr->aBlocks.append( j ); | ||
| 234 | bsBlockUsed.setBit( j ); | ||
| 235 | } | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | int Bu::Myriad::findEmptyBlock() | ||
| 241 | { | ||
| 242 | for( int j = 0; j < bsBlockUsed.getSize(); j++ ) | ||
| 243 | { | ||
| 244 | if( bsBlockUsed.getBit( j ) == false ) | ||
| 245 | return j; | ||
| 246 | } | ||
| 247 | sio << "Myriad: findEmptyBlock(): No empty blocks, adding new one." << sio.nl; | ||
| 248 | |||
| 249 | bsBlockUsed.setSize( bsBlockUsed.getSize()+1, false ); | ||
| 250 | sStore.setPos( iBlockSize*iBlocks ); | ||
| 251 | |||
| 252 | char *pBlock = new char[iBlockSize]; | ||
| 253 | memset( pBlock, 0, iBlockSize ); | ||
| 254 | sStore.write( pBlock, iBlockSize ); | ||
| 255 | delete pBlock; | ||
| 256 | |||
| 257 | return iBlockSize++; | ||
| 258 | } | ||
| 259 | |||
| 260 | void Bu::Myriad::deleteStream( int /*iID*/ ) | ||
| 261 | { | ||
| 262 | } | ||
| 263 | |||
| 264 | Bu::MyriadStream Bu::Myriad::openStream( int iID ) | ||
| 265 | { | ||
| 266 | return MyriadStream( *this, iID ); | ||
| 267 | } | ||
| 268 | |||
| 269 | int Bu::Myriad::getBlockSize() | ||
| 270 | { | ||
| 271 | return iBlockSize; | ||
| 272 | } | ||
| 273 | |||
| 274 | int Bu::Myriad::getNumBlocks() | ||
| 275 | { | ||
| 276 | return iBlocks; | ||
| 277 | } | ||
| 278 | |||
| 279 | int Bu::Myriad::getNumUsedBlocks() | ||
| 280 | { | ||
| 281 | return iUsed; | ||
| 282 | } | ||
| 283 | |||
| 284 | |||
diff --git a/src/myriad.h b/src/myriad.h new file mode 100644 index 0000000..772729f --- /dev/null +++ b/src/myriad.h | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef BU_MYRIAD_H | ||
| 9 | #define BU_MYRIAD_H | ||
| 10 | |||
| 11 | #include <stdint.h> | ||
| 12 | #include "bu/bitstring.h" | ||
| 13 | #include "bu/exceptionbase.h" | ||
| 14 | #include "bu/array.h" | ||
| 15 | |||
| 16 | namespace Bu | ||
| 17 | { | ||
| 18 | class Stream; | ||
| 19 | class MyriadStream; | ||
| 20 | |||
| 21 | subExceptionDecl( MyriadException ) | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Numerically Indexed Data Streams. This is a working name so I can | ||
| 25 | * actually get some code written instead of agonizing over the name. | ||
| 26 | * | ||
| 27 | * This is a system for creating streams that contain other streams in | ||
| 28 | * a flexible block-allocated system. | ||
| 29 | * | ||
| 30 | * Header format is as follows: | ||
| 31 | * | ||
| 32 | * MMMMvBssssSSSS* | ||
| 33 | * M = Magic number | ||
| 34 | * v = version number | ||
| 35 | * B = Bits per int | ||
| 36 | * s = Blocksize in bytes | ||
| 37 | * S = Number of Streams | ||
| 38 | * | ||
| 39 | * The * represents the Stream headers, one per stream, as follows: | ||
| 40 | * IIIIssss$ | ||
| 41 | * I = Id number of the stream | ||
| 42 | * s = size of stream in bytes | ||
| 43 | * | ||
| 44 | * The $ represents the Block headers, one per used block, as follows: | ||
| 45 | * IIII | ||
| 46 | * I = Index of the block | ||
| 47 | * | ||
| 48 | * The stream/block data is interleaved in the header, so all blocks stored | ||
| 49 | * with one stream are together. The block headers are in order, and the | ||
| 50 | * data in them is required to be "solid" you cannot fill partial blocks | ||
| 51 | * mid-way through a stream. | ||
| 52 | * | ||
| 53 | * The initial block starts with the nids header, and is both the zero block | ||
| 54 | * and the zero stream. For now, the minimum block size is the size needed | ||
| 55 | * to store the base header, the zero stream header, and the first two | ||
| 56 | * blocks of the zero stream, so 30 bytes. Since it's reccomended to use | ||
| 57 | * a size that will fit evenly into filesystem blocks, then a size of 32 is | ||
| 58 | * probably the smallest reccomended size because all powers of two equal | ||
| 59 | * to or greater than 32 are evenly divisible by 32. | ||
| 60 | * | ||
| 61 | * I have had a thought that if the block size were smaller than 42 bytes | ||
| 62 | * the header would consume the first N blocks where N * block size is | ||
| 63 | * enough space to house the initial header, the first stream header, and | ||
| 64 | * the first N block headers. This, of course, causes you to hit an | ||
| 65 | * infinite header if the block size is small enough. | ||
| 66 | */ | ||
| 67 | class Myriad | ||
| 68 | { | ||
| 69 | friend class MyriadStream; | ||
| 70 | public: | ||
| 71 | Myriad( Bu::Stream &sStore ); | ||
| 72 | virtual ~Myriad(); | ||
| 73 | |||
| 74 | /** | ||
| 75 | * Initialize this object based on the data already in the assosiated | ||
| 76 | * stream. This will be called automatically for you if you forget, | ||
| 77 | * but if you want to pre-initialize for some reason, just call this | ||
| 78 | * once before you actually start doing anything with your Myriad. | ||
| 79 | */ | ||
| 80 | void initialize(); | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Create a new Myriad system in the assosiated stream. This should be | ||
| 84 | * used carefully, it will destroy all data already within the stream. | ||
| 85 | * More options will probably be added soon. | ||
| 86 | */ | ||
| 87 | void initialize( int iBlockSize, int iPreAllocate=1 ); | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Create a new stream within the Myriad system. The ID of the new stream | ||
| 91 | * is returned. | ||
| 92 | */ | ||
| 93 | int createStream( int iPreAllocate=1 ); | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Delete a stream that's already within the Myriad. | ||
| 97 | */ | ||
| 98 | void deleteStream( int iID ); | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Return a new Stream object assosiated with the given stream ID. | ||
| 102 | */ | ||
| 103 | MyriadStream openStream( int iID ); | ||
| 104 | |||
| 105 | int getBlockSize(); | ||
| 106 | int getNumBlocks(); | ||
| 107 | int getNumUsedBlocks(); | ||
| 108 | int getBlockOverhead(); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Syncronize the header data, etc. with the storage stream. It's not | ||
| 112 | * a bad idea to call this periodically. | ||
| 113 | */ | ||
| 114 | void sync(); | ||
| 115 | |||
| 116 | private: | ||
| 117 | enum | ||
| 118 | { | ||
| 119 | blockUnused = 0xFFFFFFFFUL | ||
| 120 | }; | ||
| 121 | |||
| 122 | void updateHeader(); | ||
| 123 | int findEmptyBlock(); | ||
| 124 | |||
| 125 | private: | ||
| 126 | Bu::Stream &sStore; | ||
| 127 | int iBlockSize; | ||
| 128 | int iBlocks; | ||
| 129 | int iUsed; | ||
| 130 | Bu::BitString bsBlockUsed; | ||
| 131 | typedef Bu::Array<int> BlockArray; | ||
| 132 | class Stream | ||
| 133 | { | ||
| 134 | public: | ||
| 135 | int iId; | ||
| 136 | int iSize; | ||
| 137 | BlockArray aBlocks; | ||
| 138 | }; | ||
| 139 | typedef Bu::Array<Stream *> StreamArray; | ||
| 140 | StreamArray aStreams; | ||
| 141 | }; | ||
| 142 | }; | ||
| 143 | |||
| 144 | #endif | ||
diff --git a/src/myriadstream.cpp b/src/myriadstream.cpp new file mode 100644 index 0000000..c9b3326 --- /dev/null +++ b/src/myriadstream.cpp | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "bu/myriadstream.h" | ||
| 9 | |||
| 10 | #include <string.h> | ||
| 11 | |||
| 12 | Bu::MyriadStream::MyriadStream( Myriad &rMyriad, uint32_t uStream ) : | ||
| 13 | rMyriad( rMyriad ), | ||
| 14 | uStream( uStream ), | ||
| 15 | pCurBlock( NULL ), | ||
| 16 | uCurBlock( uStream ), | ||
| 17 | uSize( 0 ), | ||
| 18 | uBlockSize( rMyriad.iBlockSize ), | ||
| 19 | uPos( 0 ) | ||
| 20 | { | ||
| 21 | //printf("MyriadStream::allocated\n"); | ||
| 22 | //pCurBlock = rMyriad.newBlock(); | ||
| 23 | //rMyriad.getBlock( uStream, pCurBlock ); | ||
| 24 | //uSize = pCurBlock->uBytesUsed; | ||
| 25 | } | ||
| 26 | |||
| 27 | Bu::MyriadStream::~MyriadStream() | ||
| 28 | { | ||
| 29 | //printf("Destroying stream?\n"); | ||
| 30 | //rMyriad.updateStreamSize( uStream, uSize ); | ||
| 31 | //rMyriad.deleteBlock( pCurBlock ); | ||
| 32 | } | ||
| 33 | |||
| 34 | void Bu::MyriadStream::close() | ||
| 35 | { | ||
| 36 | } | ||
| 37 | |||
| 38 | size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) | ||
| 39 | { | ||
| 40 | /* | ||
| 41 | if( nBytes == 0 ) | ||
| 42 | return 0; | ||
| 43 | if( nBytes + uPos > uSize ) | ||
| 44 | nBytes = uSize - uPos; | ||
| 45 | if( (uPos%uBlockSize)+nBytes < uBlockSize ) | ||
| 46 | { | ||
| 47 | size_t iRead = nBytes; | ||
| 48 | if( iRead > pCurBlock->uBytesUsed-(uPos%uBlockSize) ) | ||
| 49 | iRead = pCurBlock->uBytesUsed-(uPos%uBlockSize); | ||
| 50 | memcpy( pBuf, pCurBlock->pData+(uPos%uBlockSize), iRead ); | ||
| 51 | //printf("read buffill: %ub, %u-%u/%u -> %d-%d/%d (a:%u)", | ||
| 52 | // iRead, uPos, uPos+iRead-1, uSize, 0, iRead-1, nBytes, uCurBlock ); | ||
| 53 | uPos += iRead; | ||
| 54 | //printf(" -- %u\n", uPos%uBlockSize ); | ||
| 55 | //printf("ra: block %u = %ub:%u (%ub total)\n", | ||
| 56 | // uCurBlock, uPos, nBytes, uSize ); | ||
| 57 | |||
| 58 | // This can't happen, if we're right on a boundery, it goes to the | ||
| 59 | // other case | ||
| 60 | //if( uPos%uBlockSize == 0 ) | ||
| 61 | // uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock, false ); | ||
| 62 | return iRead; | ||
| 63 | } | ||
| 64 | else | ||
| 65 | { | ||
| 66 | size_t nTotal = 0; | ||
| 67 | for(;;) | ||
| 68 | { | ||
| 69 | uint32_t iRead = nBytes; | ||
| 70 | if( iRead > uBlockSize-(uPos%uBlockSize) ) | ||
| 71 | iRead = uBlockSize-(uPos%uBlockSize); | ||
| 72 | if( iRead > pCurBlock->uBytesUsed-(uPos%uBlockSize) ) | ||
| 73 | iRead = pCurBlock->uBytesUsed-(uPos%uBlockSize); | ||
| 74 | memcpy( ((char *)pBuf)+nTotal, | ||
| 75 | pCurBlock->pData+(uPos%uBlockSize), iRead ); | ||
| 76 | //printf(" read buffill: %ub, %u-%u/%u -> %d-%d/%d (b:%u)\n", | ||
| 77 | // iRead, uPos, uPos+iRead-1, uSize, | ||
| 78 | // nTotal, nTotal+nBytes-1, nBytes, uCurBlock ); | ||
| 79 | uPos += iRead; | ||
| 80 | nBytes -= iRead; | ||
| 81 | nTotal += iRead; | ||
| 82 | //printf("rb: block %u = %ub:%u (%ub total)\n", | ||
| 83 | // uCurBlock, uPos, iRead, uSize ); | ||
| 84 | if( uPos%uBlockSize == 0 ) | ||
| 85 | uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock, false ); | ||
| 86 | if( nBytes == 0 || uPos >= uSize ) | ||
| 87 | return nTotal; | ||
| 88 | } | ||
| 89 | }*/ | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | size_t Bu::MyriadStream::write( const void *pBuf, size_t nBytes ) | ||
| 94 | { | ||
| 95 | if( nBytes == 0 ) | ||
| 96 | return 0; | ||
| 97 | /* if( pCurBlock->uBytesUsed >= uBlockSize ) | ||
| 98 | { | ||
| 99 | // We're at the end of our current block, allocate another before we do | ||
| 100 | // anything. | ||
| 101 | uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock ); | ||
| 102 | } */ | ||
| 103 | /* | ||
| 104 | if( (uPos%uBlockSize)+nBytes < uBlockSize ) | ||
| 105 | { | ||
| 106 | //printf("wa: %u:%u:%u:%u -> ", uPos, uPos%uBlockSize, uSize, pCurBlock->uBytesUsed ); | ||
| 107 | memcpy( pCurBlock->pData+(uPos%uBlockSize), pBuf, nBytes ); | ||
| 108 | //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (a:%u:%u)\n", | ||
| 109 | // nBytes, 0, nBytes-1, nBytes, | ||
| 110 | // uPos, uPos+nBytes-1, uSize, uCurBlock, | ||
| 111 | // pCurBlock->uBytesUsed ); | ||
| 112 | if( (uPos%uBlockSize)+nBytes > pCurBlock->uBytesUsed ) | ||
| 113 | pCurBlock->uBytesUsed = (uPos%uBlockSize)+nBytes; | ||
| 114 | rMyriad.setBlock( uCurBlock, pCurBlock ); | ||
| 115 | uPos += nBytes; | ||
| 116 | if( uPos > uSize ) | ||
| 117 | uSize = uPos; | ||
| 118 | //printf("block %u = %ub (%ub total) %d:%u\n", | ||
| 119 | // uCurBlock, pCurBlock->uBytesUsed, uSize, nBytes, uPos ); | ||
| 120 | return nBytes; | ||
| 121 | } | ||
| 122 | else | ||
| 123 | { | ||
| 124 | size_t nTotal = 0; | ||
| 125 | for(;;) | ||
| 126 | { | ||
| 127 | uint32_t uNow = uBlockSize-(uPos%uBlockSize); | ||
| 128 | //printf("uNow: %u (%u-(%u%%%u)) %d req\n", uNow, uBlockSize, uPos, uBlockSize, nBytes ); | ||
| 129 | if( nBytes < uNow ) | ||
| 130 | uNow = nBytes; | ||
| 131 | memcpy( pCurBlock->pData+(uPos%uBlockSize), | ||
| 132 | &((char *)pBuf)[nTotal], uNow ); | ||
| 133 | //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (b:%u:%u)\n", | ||
| 134 | // uNow, nTotal, nTotal+uNow-1, nBytes, | ||
| 135 | // uPos, uPos+uNow-1, uSize, uCurBlock, pCurBlock->uBytesUsed ); | ||
| 136 | if( (uPos%uBlockSize)+uNow > pCurBlock->uBytesUsed ) | ||
| 137 | pCurBlock->uBytesUsed = (uPos%uBlockSize)+uNow; | ||
| 138 | rMyriad.setBlock( uCurBlock, pCurBlock ); | ||
| 139 | uPos += uNow; | ||
| 140 | if( uPos > uSize ) | ||
| 141 | uSize = uPos; | ||
| 142 | nTotal += uNow; | ||
| 143 | nBytes -= uNow; | ||
| 144 | //printf("wb: block %u = %ub (%ub total)\n", | ||
| 145 | // uCurBlock, pCurBlock->uBytesUsed, uSize ); | ||
| 146 | //if( pCurBlock->uBytesUsed == uBlockSize ) | ||
| 147 | if( uPos%uBlockSize == 0 ) | ||
| 148 | uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock ); | ||
| 149 | if( nBytes == 0 ) | ||
| 150 | return nTotal; | ||
| 151 | } | ||
| 152 | }*/ | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | long Bu::MyriadStream::tell() | ||
| 157 | { | ||
| 158 | return uPos; | ||
| 159 | } | ||
| 160 | |||
| 161 | void Bu::MyriadStream::seek( long offset ) | ||
| 162 | { | ||
| 163 | uPos += offset; | ||
| 164 | } | ||
| 165 | |||
| 166 | void Bu::MyriadStream::setPos( long pos ) | ||
| 167 | { | ||
| 168 | uPos = pos; | ||
| 169 | } | ||
| 170 | |||
| 171 | void Bu::MyriadStream::setPosEnd( long pos ) | ||
| 172 | { | ||
| 173 | uPos = uSize-pos-1; | ||
| 174 | } | ||
| 175 | |||
| 176 | bool Bu::MyriadStream::isEos() | ||
| 177 | { | ||
| 178 | return true; | ||
| 179 | } | ||
| 180 | |||
| 181 | bool Bu::MyriadStream::isOpen() | ||
| 182 | { | ||
| 183 | return true; | ||
| 184 | } | ||
| 185 | |||
| 186 | void Bu::MyriadStream::flush() | ||
| 187 | { | ||
| 188 | } | ||
| 189 | |||
| 190 | bool Bu::MyriadStream::canRead() | ||
| 191 | { | ||
| 192 | return true; | ||
| 193 | } | ||
| 194 | |||
| 195 | bool Bu::MyriadStream::canWrite() | ||
| 196 | { | ||
| 197 | return true; | ||
| 198 | } | ||
| 199 | |||
| 200 | bool Bu::MyriadStream::isReadable() | ||
| 201 | { | ||
| 202 | return true; | ||
| 203 | } | ||
| 204 | |||
| 205 | bool Bu::MyriadStream::isWritable() | ||
| 206 | { | ||
| 207 | return true; | ||
| 208 | } | ||
| 209 | |||
| 210 | bool Bu::MyriadStream::isSeekable() | ||
| 211 | { | ||
| 212 | return true; | ||
| 213 | } | ||
| 214 | |||
| 215 | bool Bu::MyriadStream::isBlocking() | ||
| 216 | { | ||
| 217 | return true; | ||
| 218 | } | ||
| 219 | |||
| 220 | void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) | ||
| 221 | { | ||
| 222 | } | ||
| 223 | |||
diff --git a/src/myriadstream.h b/src/myriadstream.h new file mode 100644 index 0000000..755ff53 --- /dev/null +++ b/src/myriadstream.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef BU_MYRIAD_STREAM_H | ||
| 9 | #define BU_MYRIAD_STREAM_H | ||
| 10 | |||
| 11 | #include "bu/stream.h" | ||
| 12 | #include "bu/myriad.h" | ||
| 13 | |||
| 14 | namespace Bu | ||
| 15 | { | ||
| 16 | class MyriadStream : public Bu::Stream | ||
| 17 | { | ||
| 18 | friend class Myriad; | ||
| 19 | private: | ||
| 20 | /** | ||
| 21 | * These can only be created by the Myriad class. | ||
| 22 | */ | ||
| 23 | MyriadStream( Myriad &rMyriad, uint32_t uStream ); | ||
| 24 | |||
| 25 | public: | ||
| 26 | virtual ~MyriadStream(); | ||
| 27 | |||
| 28 | virtual void close(); | ||
| 29 | virtual size_t read( void *pBuf, size_t nBytes ); | ||
| 30 | virtual size_t write( const void *pBuf, size_t nBytes ); | ||
| 31 | using Stream::write; | ||
| 32 | virtual long tell(); | ||
| 33 | virtual void seek( long offset ); | ||
| 34 | virtual void setPos( long pos ); | ||
| 35 | virtual void setPosEnd( long pos ); | ||
| 36 | virtual bool isEos(); | ||
| 37 | virtual bool isOpen(); | ||
| 38 | virtual void flush(); | ||
| 39 | virtual bool canRead(); | ||
| 40 | virtual bool canWrite(); | ||
| 41 | virtual bool isReadable(); | ||
| 42 | virtual bool isWritable(); | ||
| 43 | virtual bool isSeekable(); | ||
| 44 | virtual bool isBlocking(); | ||
| 45 | virtual void setBlocking( bool bBlocking=true ); | ||
| 46 | |||
| 47 | private: | ||
| 48 | Myriad &rMyriad; | ||
| 49 | uint32_t uStream; | ||
| 50 | char *pCurBlock; | ||
| 51 | uint32_t uCurBlock; | ||
| 52 | uint32_t uSize; | ||
| 53 | uint32_t uBlockSize; | ||
| 54 | uint32_t uPos; | ||
| 55 | }; | ||
| 56 | }; | ||
| 57 | |||
| 58 | #endif | ||
diff --git a/src/tests/nids.cpp b/src/tests/nids.cpp index bb5993b..41d0432 100644 --- a/src/tests/nids.cpp +++ b/src/tests/nids.cpp | |||
| @@ -23,18 +23,19 @@ int main( int argc, char *argv[] ) | |||
| 23 | Bu::File::ReadWrite|Bu::File::Create|Bu::File::Truncate ); | 23 | Bu::File::ReadWrite|Bu::File::Create|Bu::File::Truncate ); |
| 24 | Bu::Nids n( fOut ); | 24 | Bu::Nids n( fOut ); |
| 25 | 25 | ||
| 26 | n.initialize( 120, 1 ); | 26 | n.initialize( 32, 1 ); |
| 27 | Bu::NidsStream s = n.openStream( n.createStream() ); | 27 | /* Bu::NidsStream s = n.openStream( n.createStream() ); |
| 28 | 28 | ||
| 29 | Bu::FString sBuf( 350 ); | 29 | Bu::FString sBuf( 350 ); |
| 30 | memset( sBuf.getStr(), 'a', 350 ); | 30 | memset( sBuf.getStr(), 'a', 350 ); |
| 31 | s.write( sBuf ); | 31 | s.write( sBuf );*/ |
| 32 | } | 32 | } |
| 33 | else if( argv[1][0] == 'r' ) | 33 | else if( argv[1][0] == 'r' ) |
| 34 | { | 34 | { |
| 35 | Bu::File fOut( argv[2], Bu::File::Read ); | 35 | Bu::File fOut( argv[2], Bu::File::Read ); |
| 36 | Bu::Nids n( fOut ); | 36 | Bu::Nids n( fOut ); |
| 37 | 37 | n.initialize(); | |
| 38 | /* | ||
| 38 | Bu::NidsStream s = n.openStream( 0 ); | 39 | Bu::NidsStream s = n.openStream( 0 ); |
| 39 | char buf[75]; | 40 | char buf[75]; |
| 40 | for( int j = 0; j < 3; j++ ) | 41 | for( int j = 0; j < 3; j++ ) |
| @@ -44,6 +45,7 @@ int main( int argc, char *argv[] ) | |||
| 44 | printf("\n(read %d chars)\n", iRead ); | 45 | printf("\n(read %d chars)\n", iRead ); |
| 45 | } | 46 | } |
| 46 | printf("Position: %ld\n", s.tell() ); | 47 | printf("Position: %ld\n", s.tell() ); |
| 48 | */ | ||
| 47 | } | 49 | } |
| 48 | else | 50 | else |
| 49 | { | 51 | { |
diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp new file mode 100644 index 0000000..e951882 --- /dev/null +++ b/src/tools/myriad.cpp | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
| 3 | * | ||
| 4 | * This file is part of the libbu++ library and is released under the | ||
| 5 | * terms of the license contained in the file LICENSE. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "bu/sio.h" | ||
| 9 | #include "bu/file.h" | ||
| 10 | #include "bu/myriad.h" | ||
| 11 | #include "bu/myriadstream.h" | ||
| 12 | #include "bu/optparser.h" | ||
| 13 | |||
| 14 | #include <stdlib.h> | ||
| 15 | |||
| 16 | using namespace Bu; | ||
| 17 | |||
| 18 | enum Mode | ||
| 19 | { | ||
| 20 | modeCreate, | ||
| 21 | modeInfo, | ||
| 22 | |||
| 23 | modeNone | ||
| 24 | }; | ||
| 25 | |||
| 26 | class Options : public OptParser | ||
| 27 | { | ||
| 28 | public: | ||
| 29 | Options( int argc, char *argv[] ) : | ||
| 30 | eMode( modeNone ), | ||
| 31 | iBlockSize( 64 ), | ||
| 32 | iPreallocate( 0 ) | ||
| 33 | { | ||
| 34 | addHelpBanner("Mode of operation:"); | ||
| 35 | addOption( eMode, 'c', "create", "Create a new NIDS file." ); | ||
| 36 | addOption( eMode, "info", "Display some info about a NIDS file." ); | ||
| 37 | addHelpOption(); | ||
| 38 | |||
| 39 | addHelpBanner("\nGeneral options:"); | ||
| 40 | addOption( iBlockSize, 'b', "block-size", "Set the block size." ); | ||
| 41 | addOption( iPreallocate, 'p', "preallocate", | ||
| 42 | "Number of blocks to preallocate." ); | ||
| 43 | addOption( sOutput, 'o', "output", "Set the output filename." ); | ||
| 44 | addOption( sInput, 'i', "input", "Set the input filename." ); | ||
| 45 | |||
| 46 | setOverride( "create", "create" ); | ||
| 47 | setOverride( "info", "info" ); | ||
| 48 | |||
| 49 | parse( argc, argv ); | ||
| 50 | } | ||
| 51 | |||
| 52 | Mode eMode; | ||
| 53 | int iBlockSize; | ||
| 54 | int iPreallocate; | ||
| 55 | Bu::FString sOutput; | ||
| 56 | Bu::FString sInput; | ||
| 57 | }; | ||
| 58 | |||
| 59 | Bu::Formatter &operator>>( Bu::Formatter &f, Mode &m ) | ||
| 60 | { | ||
| 61 | Bu::FString sTok = f.readToken(); | ||
| 62 | if( sTok == "create" || sTok == "c" ) | ||
| 63 | m = modeCreate; | ||
| 64 | else if( sTok == "info" ) | ||
| 65 | m = modeInfo; | ||
| 66 | else | ||
| 67 | m = modeNone; | ||
| 68 | return f; | ||
| 69 | } | ||
| 70 | |||
| 71 | int main( int argc, char *argv[] ) | ||
| 72 | { | ||
| 73 | Options opts( argc, argv ); | ||
| 74 | |||
| 75 | switch( opts.eMode ) | ||
| 76 | { | ||
| 77 | case modeCreate: | ||
| 78 | if( !opts.sOutput ) | ||
| 79 | { | ||
| 80 | sio << "Please specify an output file to create a stream for." | ||
| 81 | << sio.nl; | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | else | ||
| 85 | { | ||
| 86 | File fOut( opts.sOutput, File::WriteNew ); | ||
| 87 | Myriad n( fOut ); | ||
| 88 | n.initialize( opts.iBlockSize, opts.iPreallocate ); | ||
| 89 | } | ||
| 90 | break; | ||
| 91 | |||
| 92 | case modeInfo: | ||
| 93 | if( !opts.sInput ) | ||
| 94 | { | ||
| 95 | sio << "Please specify an input file to display info about." | ||
| 96 | << sio.nl; | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | else | ||
| 100 | { | ||
| 101 | File fIn( opts.sInput, File::Read ); | ||
| 102 | Myriad n( fIn ); | ||
| 103 | n.initialize(); | ||
| 104 | } | ||
| 105 | break; | ||
| 106 | |||
| 107 | case modeNone: | ||
| 108 | sio << "Please select a mode, for more info, try --help." | ||
| 109 | << sio.nl << sio.nl; | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
diff --git a/src/unit/array.unit b/src/unit/array.unit index b6528eb..daedd5f 100644 --- a/src/unit/array.unit +++ b/src/unit/array.unit | |||
| @@ -76,7 +76,7 @@ | |||
| 76 | 76 | ||
| 77 | StrHashArray a3; | 77 | StrHashArray a3; |
| 78 | a3 = a1; | 78 | a3 = a1; |
| 79 | 79 | ||
| 80 | unitTest( a3[0].get("Hi") == "Yo" ); | 80 | unitTest( a3[0].get("Hi") == "Yo" ); |
| 81 | unitTest( a3[0].get("Bye") == "Later" ); | 81 | unitTest( a3[0].get("Bye") == "Later" ); |
| 82 | unitTest( a3[1].get("Test") == "Bloop" ); | 82 | unitTest( a3[1].get("Test") == "Bloop" ); |
