diff options
| author | Mike Buland <mike@xagasoft.com> | 2024-09-30 11:50:17 -0700 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2024-09-30 11:50:17 -0700 |
| commit | 0befcc026be9e4f6c40f8771c7f26f767ebddbf7 (patch) | |
| tree | e549bee70f50def02d24ef386b490e017bc6043b | |
| parent | 84c93fbf0f371bcd26893d1c33e3a5bf1a61223e (diff) | |
| download | libbu++-0befcc026be9e4f6c40f8771c7f26f767ebddbf7.tar.gz libbu++-0befcc026be9e4f6c40f8771c7f26f767ebddbf7.tar.bz2 libbu++-0befcc026be9e4f6c40f8771c7f26f767ebddbf7.tar.xz libbu++-0befcc026be9e4f6c40f8771c7f26f767ebddbf7.zip | |
Erasing streams works, stream map building works.
Diffstat (limited to '')
| -rw-r--r-- | src/stable/myriad.cpp | 66 | ||||
| -rw-r--r-- | src/stable/myriad.h | 4 | ||||
| -rw-r--r-- | src/tests/bigmyriad.cpp | 9 | ||||
| -rw-r--r-- | src/tools/myriad.cpp | 59 | ||||
| -rw-r--r-- | src/unstable/bitstring.cpp | 12 | ||||
| -rw-r--r-- | src/unstable/bitstring.h | 10 |
6 files changed, 119 insertions, 41 deletions
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp index eba1ebf..85daa0d 100644 --- a/src/stable/myriad.cpp +++ b/src/stable/myriad.cpp | |||
| @@ -252,6 +252,41 @@ int32_t Bu::Myriad::getTotalUnusedBytes(int32_t iAssumeBlockSize ) const | |||
| 252 | return iTotal; | 252 | return iTotal; |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | Bu::BitString Bu::Myriad::buildBlockUseMap() const | ||
| 256 | { | ||
| 257 | Bu::MutexLocker l( mAccess ); | ||
| 258 | Bu::BitString bsMap( iBlockCount ); | ||
| 259 | bsMap.fill(); | ||
| 260 | for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) | ||
| 261 | { | ||
| 262 | bsMap.setBit( *i, false ); | ||
| 263 | } | ||
| 264 | return bsMap; | ||
| 265 | } | ||
| 266 | |||
| 267 | Bu::Array<int32_t> Bu::Myriad::buildBlockMap() const | ||
| 268 | { | ||
| 269 | Bu::MutexLocker l( mAccess ); | ||
| 270 | Bu::Array<int32_t> bm( iBlockCount ); | ||
| 271 | for( int j = 0; j < iBlockCount; j++ ) | ||
| 272 | { | ||
| 273 | bm.append( -1 ); | ||
| 274 | } | ||
| 275 | Bu::MutexLocker l2( mhStream ); | ||
| 276 | for( StreamHash::const_iterator iStream = hStream.begin(); | ||
| 277 | iStream; iStream++ ) | ||
| 278 | { | ||
| 279 | int32_t iId = iStream.getKey(); | ||
| 280 | Stream *pStream = iStream.getValue(); | ||
| 281 | for( Bu::Array<int32_t>::const_iterator iBlock = | ||
| 282 | pStream->aBlocks.begin(); iBlock; iBlock++ ) | ||
| 283 | { | ||
| 284 | bm[*iBlock] = iId; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | return bm; | ||
| 288 | } | ||
| 289 | |||
| 255 | void Bu::Myriad::sync() | 290 | void Bu::Myriad::sync() |
| 256 | { | 291 | { |
| 257 | writeHeader(); | 292 | writeHeader(); |
| @@ -259,7 +294,7 @@ void Bu::Myriad::sync() | |||
| 259 | 294 | ||
| 260 | bool Bu::Myriad::loadMyriad() | 295 | bool Bu::Myriad::loadMyriad() |
| 261 | { | 296 | { |
| 262 | Bu::println("Load myriad!"); | 297 | //Bu::println("Load myriad!"); |
| 263 | char sMagicCode[4]; | 298 | char sMagicCode[4]; |
| 264 | rBacking.setPos( 0 ); | 299 | rBacking.setPos( 0 ); |
| 265 | MyriadRead( sMagicCode, 4 ); | 300 | MyriadRead( sMagicCode, 4 ); |
| @@ -362,7 +397,7 @@ bool Bu::Myriad::loadMyriad() | |||
| 362 | } | 397 | } |
| 363 | 398 | ||
| 364 | lFreeBlocks = hUnusedBlocks.getKeys(); | 399 | lFreeBlocks = hUnusedBlocks.getKeys(); |
| 365 | Bu::println("Free blocks: %1").arg( lFreeBlocks.getSize() ); | 400 | //Bu::println("Free blocks: %1").arg( lFreeBlocks.getSize() ); |
| 366 | 401 | ||
| 367 | return true; | 402 | return true; |
| 368 | } | 403 | } |
| @@ -389,22 +424,14 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ) | |||
| 389 | // plus one block index. | 424 | // plus one block index. |
| 390 | int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes+4, iBlockSize ); | 425 | int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes+4, iBlockSize ); |
| 391 | 426 | ||
| 392 | Bu::println("Initial estimate: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).") | 427 | //Bu::println("Initial estimate: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).").arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ).arg( iHeaderStreamBlocks ).arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ).arg( iHeaderStreamBlocks*iBlockSize ); |
| 393 | .arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ) | ||
| 394 | .arg( iHeaderStreamBlocks ) | ||
| 395 | .arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ) | ||
| 396 | .arg( iHeaderStreamBlocks*iBlockSize ); | ||
| 397 | while( iHeaderStreamBytes+(iHeaderStreamBlocks*4) | 428 | while( iHeaderStreamBytes+(iHeaderStreamBlocks*4) |
| 398 | > iHeaderStreamBlocks*iBlockSize ) | 429 | > iHeaderStreamBlocks*iBlockSize ) |
| 399 | { | 430 | { |
| 400 | iHeaderStreamBlocks = blkDiv((iHeaderStreamBytes+((iHeaderStreamBlocks+1)*4)), iBlockSize); | 431 | iHeaderStreamBlocks = blkDiv((iHeaderStreamBytes+((iHeaderStreamBlocks+1)*4)), iBlockSize); |
| 401 | if( iHeaderStreamBlocks > 100 ) | 432 | if( iHeaderStreamBlocks > 100 ) |
| 402 | break; | 433 | break; |
| 403 | Bu::println(" Adjustment: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).") | 434 | //Bu::println(" Adjustment: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).").arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ).arg( iHeaderStreamBlocks ).arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ).arg( iHeaderStreamBlocks*iBlockSize ); |
| 404 | .arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ) | ||
| 405 | .arg( iHeaderStreamBlocks ) | ||
| 406 | .arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ) | ||
| 407 | .arg( iHeaderStreamBlocks*iBlockSize ); | ||
| 408 | } | 435 | } |
| 409 | 436 | ||
| 410 | if( iPreallocateBlocks > iHeaderStreamBlocks ) | 437 | if( iPreallocateBlocks > iHeaderStreamBlocks ) |
| @@ -459,7 +486,7 @@ void Bu::Myriad::writeHeader() | |||
| 459 | Bu::MutexLocker l( mAccess ); | 486 | Bu::MutexLocker l( mAccess ); |
| 460 | if( !rBacking.isWritable() ) | 487 | if( !rBacking.isWritable() ) |
| 461 | return; | 488 | return; |
| 462 | Bu::println("Writing stream breakdown:"); | 489 | //Bu::println("Writing stream breakdown:"); |
| 463 | Bu::MemBuf mbHeader; | 490 | Bu::MemBuf mbHeader; |
| 464 | { | 491 | { |
| 465 | Bu::MutexLocker l2( mhStream ); | 492 | Bu::MutexLocker l2( mhStream ); |
| @@ -488,7 +515,7 @@ void Bu::Myriad::writeHeader() | |||
| 488 | psHeader->iSize = iHdrStreamSize; | 515 | psHeader->iSize = iHdrStreamSize; |
| 489 | } | 516 | } |
| 490 | 517 | ||
| 491 | Bu::println("Computed header size: %1 bytes. Ver=%2, Bpi=%3, BlockSize=%4").arg( iHdrStreamSize ).arg( 1 ).arg( 32 ).arg( iBlockSize ); | 518 | //Bu::println("Computed header size: %1 bytes. Ver=%2, Bpi=%3, BlockSize=%4").arg( iHdrStreamSize ).arg( 1 ).arg( 32 ).arg( iBlockSize ); |
| 492 | 519 | ||
| 493 | uint8_t uVer = 1; | 520 | uint8_t uVer = 1; |
| 494 | uint8_t uBpi = 32; | 521 | uint8_t uBpi = 32; |
| @@ -515,10 +542,7 @@ void Bu::Myriad::writeHeader() | |||
| 515 | mbHeader.write( &uStreamSize, 4 ); | 542 | mbHeader.write( &uStreamSize, 4 ); |
| 516 | Bu::Array<int32_t> aBlocks = pStream->getBlockList(); | 543 | Bu::Array<int32_t> aBlocks = pStream->getBlockList(); |
| 517 | 544 | ||
| 518 | Bu::println(" Stream %1 is %2 bytes %3 blocks (%4 blocks computed)") | 545 | //Bu::println(" Stream %1 is %2 bytes %3 blocks (%4 blocks computed)").arg( *i ).arg( uStreamSize ).arg( aBlocks.getSize() ).arg( Bu::blkDiv( (int)uStreamSize, (int)iBlockSize ) ); |
| 519 | .arg( *i ).arg( uStreamSize ) | ||
| 520 | .arg( aBlocks.getSize() ) | ||
| 521 | .arg( Bu::blkDiv( (int)uStreamSize, (int)iBlockSize ) ); | ||
| 522 | 546 | ||
| 523 | for( Bu::Array<int32_t>::iterator i = aBlocks.begin(); i; i++ ) | 547 | for( Bu::Array<int32_t>::iterator i = aBlocks.begin(); i; i++ ) |
| 524 | { | 548 | { |
| @@ -556,15 +580,15 @@ int32_t Bu::Myriad::__calcHeaderSize() | |||
| 556 | } | 580 | } |
| 557 | } | 581 | } |
| 558 | 582 | ||
| 559 | Bu::println("HeaderCalc:"); | 583 | //Bu::println("HeaderCalc:"); |
| 560 | Bu::println(" Base (no header stream): %1").arg( iHdrSize ); | 584 | //Bu::println(" Base (no header stream): %1").arg( iHdrSize ); |
| 561 | int32_t iNewSize = iHdrSize; | 585 | int32_t iNewSize = iHdrSize; |
| 562 | int32_t iOldSize; | 586 | int32_t iOldSize; |
| 563 | 587 | ||
| 564 | do { | 588 | do { |
| 565 | iOldSize = iNewSize; | 589 | iOldSize = iNewSize; |
| 566 | iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize)*4; | 590 | iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize)*4; |
| 567 | Bu::println(" Recomp: %1").arg( iNewSize ); | 591 | //Bu::println(" Recomp: %1").arg( iNewSize ); |
| 568 | } while( iOldSize != iNewSize ); | 592 | } while( iOldSize != iNewSize ); |
| 569 | 593 | ||
| 570 | return iNewSize; | 594 | return iNewSize; |
diff --git a/src/stable/myriad.h b/src/stable/myriad.h index 60c5a39..7f84c2a 100644 --- a/src/stable/myriad.h +++ b/src/stable/myriad.h | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include "bu/array.h" | 7 | #include "bu/array.h" |
| 8 | #include "bu/hash.h" | 8 | #include "bu/hash.h" |
| 9 | 9 | ||
| 10 | #include "bu/bitstring.h" | ||
| 11 | |||
| 10 | namespace Bu | 12 | namespace Bu |
| 11 | { | 13 | { |
| 12 | class MyriadStream; | 14 | class MyriadStream; |
| @@ -87,6 +89,8 @@ namespace Bu | |||
| 87 | int32_t getTotalStreams() const; | 89 | int32_t getTotalStreams() const; |
| 88 | int32_t getTotalUsedBytes() const; | 90 | int32_t getTotalUsedBytes() const; |
| 89 | int32_t getTotalUnusedBytes( int32_t iAssumeBlockSize=-1 ) const; | 91 | int32_t getTotalUnusedBytes( int32_t iAssumeBlockSize=-1 ) const; |
| 92 | Bu::BitString buildBlockUseMap() const; | ||
| 93 | Bu::Array<int32_t> buildBlockMap() const; | ||
| 90 | 94 | ||
| 91 | /** | 95 | /** |
| 92 | * Flush all caches to the backing stream, write all structural and | 96 | * Flush all caches to the backing stream, write all structural and |
diff --git a/src/tests/bigmyriad.cpp b/src/tests/bigmyriad.cpp index 9d24741..cce309d 100644 --- a/src/tests/bigmyriad.cpp +++ b/src/tests/bigmyriad.cpp | |||
| @@ -5,14 +5,15 @@ | |||
| 5 | int main() | 5 | int main() |
| 6 | { | 6 | { |
| 7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); | 7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); |
| 8 | Bu::Myriad m( f, 256, 12 ); | 8 | Bu::Myriad m( f, 1024, 12 ); |
| 9 | 9 | ||
| 10 | char *buf = new char[1024*1024*10]; | 10 | #define SSIZE (1024*8) // 1024*1024*10 |
| 11 | char *buf = new char[SSIZE]; | ||
| 11 | 12 | ||
| 12 | for( int j = 0; j < 25; j++ ) | 13 | for( int j = 0; j < 25; j++ ) |
| 13 | { | 14 | { |
| 14 | memset( buf, j, 1024*1024*10 ); | 15 | memset( buf, j, SSIZE ); |
| 15 | m.create( Bu::Myriad::Write ).write( buf, 1024*1024*10 ); | 16 | m.create( Bu::Myriad::Write ).write( buf, SSIZE ); |
| 16 | // m.sync(); | 17 | // m.sync(); |
| 17 | printf("\r%03d%%", (j+1)*100/25 ); | 18 | printf("\r%03d%%", (j+1)*100/25 ); |
| 18 | fflush( stdout ); | 19 | fflush( stdout ); |
diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp index 346cd85..0dd9840 100644 --- a/src/tools/myriad.cpp +++ b/src/tools/myriad.cpp | |||
| @@ -94,6 +94,49 @@ Bu::Formatter &operator>>( Bu::Formatter &f, Mode & /*e*/ ) | |||
| 94 | return f; | 94 | return f; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | void printMap( const Bu::BitString &bs ) | ||
| 98 | { | ||
| 99 | for( int j = 0; j < bs.getSize(); j++ ) | ||
| 100 | { | ||
| 101 | if( j>0 && (j%50) == 0 ) | ||
| 102 | Bu::println(""); | ||
| 103 | if( bs.getBit( j ) ) | ||
| 104 | Bu::print("#"); | ||
| 105 | else | ||
| 106 | Bu::print("-"); | ||
| 107 | } | ||
| 108 | Bu::println("\n"); | ||
| 109 | } | ||
| 110 | |||
| 111 | void printMap( const Bu::Array<int32_t> &bm ) | ||
| 112 | { | ||
| 113 | int iBigest = 0; | ||
| 114 | for( int j = 0; j < bm.getSize(); j++ ) | ||
| 115 | { | ||
| 116 | if( iBigest < bm[j] ) | ||
| 117 | iBigest = bm[j]; | ||
| 118 | } | ||
| 119 | int iWidth = Bu::String("%1").arg( iBigest ).end().getSize(); | ||
| 120 | Bu::String sEmpty; | ||
| 121 | for( int j = 0; j < iWidth; j++ ) | ||
| 122 | { | ||
| 123 | sEmpty += '-'; | ||
| 124 | } | ||
| 125 | int iBreakAt = 60/(iWidth+1); | ||
| 126 | for( int j = 0; j < bm.getSize(); j++ ) | ||
| 127 | { | ||
| 128 | if( j>0 && (j%iBreakAt) == 0 ) | ||
| 129 | Bu::println(""); | ||
| 130 | |||
| 131 | if( bm[j] < 0 ) | ||
| 132 | Bu::print("%1 ").arg( sEmpty, Bu::Fmt(2).right().fill(' ')); | ||
| 133 | else | ||
| 134 | Bu::print("%1 ").arg( bm[j], Bu::Fmt(2).right().fill(' ')); | ||
| 135 | |||
| 136 | } | ||
| 137 | Bu::println("\n"); | ||
| 138 | } | ||
| 139 | |||
| 97 | int main( int argc, char *argv[] ) | 140 | int main( int argc, char *argv[] ) |
| 98 | { | 141 | { |
| 99 | Options opts( argc, argv ); | 142 | Options opts( argc, argv ); |
| @@ -168,6 +211,8 @@ int main( int argc, char *argv[] ) | |||
| 168 | File fOut( opts.sFile, File::Write|File::Read ); | 211 | File fOut( opts.sFile, File::Write|File::Read ); |
| 169 | Myriad m( fOut ); | 212 | Myriad m( fOut ); |
| 170 | m.erase( opts.iStream ); | 213 | m.erase( opts.iStream ); |
| 214 | printMap( m.buildBlockUseMap() ); | ||
| 215 | printMap( m.buildBlockMap() ); | ||
| 171 | } | 216 | } |
| 172 | break; | 217 | break; |
| 173 | 218 | ||
| @@ -273,17 +318,8 @@ int main( int argc, char *argv[] ) | |||
| 273 | { | 318 | { |
| 274 | File fIn( opts.sFile, File::Write|File::Read ); | 319 | File fIn( opts.sFile, File::Write|File::Read ); |
| 275 | Myriad m( fIn ); | 320 | Myriad m( fIn ); |
| 276 | /* Bu::BitString bs = m.getBlocksUsed(); | 321 | printMap( m.buildBlockUseMap() ); |
| 277 | for( int j = 0; j < bs.getSize(); j++ ) | 322 | printMap( m.buildBlockMap() ); |
| 278 | { | ||
| 279 | if( j>0 && (j%50) == 0 ) | ||
| 280 | Bu::println(""); | ||
| 281 | if( bs.getBit( j ) ) | ||
| 282 | Bu::print("#"); | ||
| 283 | else | ||
| 284 | Bu::print("-"); | ||
| 285 | }*/ | ||
| 286 | Bu::println("\n"); | ||
| 287 | } | 323 | } |
| 288 | break; | 324 | break; |
| 289 | 325 | ||
| @@ -295,4 +331,3 @@ int main( int argc, char *argv[] ) | |||
| 295 | 331 | ||
| 296 | return 0; | 332 | return 0; |
| 297 | } | 333 | } |
| 298 | |||
diff --git a/src/unstable/bitstring.cpp b/src/unstable/bitstring.cpp index 21c1316..b80c073 100644 --- a/src/unstable/bitstring.cpp +++ b/src/unstable/bitstring.cpp | |||
| @@ -209,7 +209,7 @@ void Bu::BitString::flipBit( long iBit ) | |||
| 209 | caData[iBit/8] ^= (1<<(iBit%8)); | 209 | caData[iBit/8] ^= (1<<(iBit%8)); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | bool Bu::BitString::getBit( long iBit ) | 212 | bool Bu::BitString::getBit( long iBit ) const |
| 213 | { | 213 | { |
| 214 | if( iBit >= iBits || iBit < 0 ) return false; | 214 | if( iBit >= iBits || iBit < 0 ) return false; |
| 215 | if( (caData[iBit/8] & (1<<(iBit%8))) == 0 ) | 215 | if( (caData[iBit/8] & (1<<(iBit%8))) == 0 ) |
| @@ -224,7 +224,7 @@ long Bu::BitString::getBitLength() | |||
| 224 | return iBits; | 224 | return iBits; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | long Bu::BitString::getSize() | 227 | long Bu::BitString::getSize() const |
| 228 | { | 228 | { |
| 229 | return iBits; | 229 | return iBits; |
| 230 | } | 230 | } |
| @@ -311,6 +311,14 @@ void Bu::BitString::clear() | |||
| 311 | } | 311 | } |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | void Bu::BitString::fill() | ||
| 315 | { | ||
| 316 | if( caData != NULL ) | ||
| 317 | { | ||
| 318 | memset( caData, 0xff, iBytes ); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 314 | bool Bu::BitString::setBitLength( long iLength, bool bClear ) | 322 | bool Bu::BitString::setBitLength( long iLength, bool bClear ) |
| 315 | { | 323 | { |
| 316 | return setSize( iLength, bClear ); | 324 | return setSize( iLength, bClear ); |
diff --git a/src/unstable/bitstring.h b/src/unstable/bitstring.h index afc22fb..70ba822 100644 --- a/src/unstable/bitstring.h +++ b/src/unstable/bitstring.h | |||
| @@ -88,7 +88,7 @@ namespace Bu | |||
| 88 | *@param iBit The index of the bit to test. | 88 | *@param iBit The index of the bit to test. |
| 89 | *@returns True for a 1, false for a 0. | 89 | *@returns True for a 1, false for a 0. |
| 90 | */ | 90 | */ |
| 91 | bool getBit( long iBit ); | 91 | bool getBit( long iBit ) const; |
| 92 | 92 | ||
| 93 | /** | 93 | /** |
| 94 | * Inverts the entire BitString, in effect this calls flipBit on every | 94 | * Inverts the entire BitString, in effect this calls flipBit on every |
| @@ -106,7 +106,7 @@ namespace Bu | |||
| 106 | DEPRECATED | 106 | DEPRECATED |
| 107 | long getBitLength(); | 107 | long getBitLength(); |
| 108 | 108 | ||
| 109 | long getSize(); | 109 | long getSize() const; |
| 110 | 110 | ||
| 111 | /** | 111 | /** |
| 112 | * Sets the entire BitString to zeros, but it does it very quickly. | 112 | * Sets the entire BitString to zeros, but it does it very quickly. |
| @@ -115,6 +115,12 @@ namespace Bu | |||
| 115 | void clear(); | 115 | void clear(); |
| 116 | 116 | ||
| 117 | /** | 117 | /** |
| 118 | * Sets the entire BitString to ones, but it does it very quickly. | ||
| 119 | * This operation runs in O(N). | ||
| 120 | */ | ||
| 121 | void fill(); | ||
| 122 | |||
| 123 | /** | ||
| 118 | * Gets another BitString that is autonomous of the current one | 124 | * Gets another BitString that is autonomous of the current one |
| 119 | * (contains a copy of the memory, not a pointer) and contains a subset | 125 | * (contains a copy of the memory, not a pointer) and contains a subset |
| 120 | * of the data in the current BitString. This is an inclusive | 126 | * of the data in the current BitString. This is an inclusive |
