diff options
-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" ); |