aboutsummaryrefslogtreecommitdiff
path: root/src/unstable
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2012-11-05 22:41:51 +0000
committerMike Buland <eichlan@xagasoft.com>2012-11-05 22:41:51 +0000
commitec05778d5718a7912e506764d443a78d6a6179e3 (patch)
tree78a9a01532180030c095acefc45763f07c14edb8 /src/unstable
parentb20414ac1fe80a71a90601f4cd1767fa7014a9ba (diff)
downloadlibbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.gz
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.bz2
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.xz
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.zip
Converted tabs to spaces with tabconv.
Diffstat (limited to 'src/unstable')
-rw-r--r--src/unstable/bitstring.cpp660
-rw-r--r--src/unstable/bitstring.h412
-rw-r--r--src/unstable/fifo.cpp118
-rw-r--r--src/unstable/fifo.h80
-rw-r--r--src/unstable/itoserver.cpp312
-rw-r--r--src/unstable/itoserver.h224
-rw-r--r--src/unstable/minimacro.cpp252
-rw-r--r--src/unstable/minimacro.h212
-rw-r--r--src/unstable/myriadfs.cpp1078
-rw-r--r--src/unstable/myriadfs.h368
-rw-r--r--src/unstable/newline.cpp66
-rw-r--r--src/unstable/newline.h42
-rw-r--r--src/unstable/settings.cpp44
-rw-r--r--src/unstable/settings.h46
-rw-r--r--src/unstable/settingsdriver.h32
-rw-r--r--src/unstable/settingsdriverini.cpp258
-rw-r--r--src/unstable/settingsdriverini.h30
-rw-r--r--src/unstable/settingsdriverregistry.cpp116
-rw-r--r--src/unstable/settingsdriverregistry.h24
-rw-r--r--src/unstable/settingsdrivertaf.cpp148
-rw-r--r--src/unstable/settingsdrivertaf.h34
-rw-r--r--src/unstable/udpsocket.cpp216
-rw-r--r--src/unstable/udpsocket.h92
-rw-r--r--src/unstable/url.cpp378
-rw-r--r--src/unstable/url.h114
-rw-r--r--src/unstable/utfstring.cpp842
-rw-r--r--src/unstable/utfstring.h482
-rw-r--r--src/unstable/uuid.cpp150
-rw-r--r--src/unstable/uuid.h84
29 files changed, 3457 insertions, 3457 deletions
diff --git a/src/unstable/bitstring.cpp b/src/unstable/bitstring.cpp
index 9559aad..3f24ec7 100644
--- a/src/unstable/bitstring.cpp
+++ b/src/unstable/bitstring.cpp
@@ -16,460 +16,460 @@
16 16
17Bu::BitString::BitString() 17Bu::BitString::BitString()
18{ 18{
19 caData = NULL; 19 caData = NULL;
20 cTopByteMask = 0; 20 cTopByteMask = 0;
21 iBits = iBytes = 0; 21 iBits = iBytes = 0;
22} 22}
23 23
24Bu::BitString::BitString( const Bu::BitString &xSrc ) 24Bu::BitString::BitString( const Bu::BitString &xSrc )
25{ 25{
26 iBits = xSrc.iBits; 26 iBits = xSrc.iBits;
27 iBytes = xSrc.iBytes; 27 iBytes = xSrc.iBytes;
28 cTopByteMask = xSrc.cTopByteMask; 28 cTopByteMask = xSrc.cTopByteMask;
29 caData = new unsigned char[iBytes]; 29 caData = new unsigned char[iBytes];
30 memcpy( caData, xSrc.caData, iBytes ); 30 memcpy( caData, xSrc.caData, iBytes );
31 31
32 fixup(); 32 fixup();
33} 33}
34 34
35Bu::BitString::BitString( long iNewBits, bool bFillRandomly ) 35Bu::BitString::BitString( long iNewBits, bool bFillRandomly )
36{ 36{
37 long j; 37 long j;
38 iBits = iNewBits; 38 iBits = iNewBits;
39 iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0)); 39 iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0));
40 caData = new unsigned char[iBytes]; 40 caData = new unsigned char[iBytes];
41 41
42 setMask(); 42 setMask();
43 43
44 if( bFillRandomly ) 44 if( bFillRandomly )
45 { 45 {
46 // rand() only returns a value up to RAND_MAX (0x7FFF on my system) so 46 // rand() only returns a value up to RAND_MAX (0x7FFF on my system) so
47 // I'll just use the low order byte) 47 // I'll just use the low order byte)
48 for( j = 0; j < iBytes; j++ ) 48 for( j = 0; j < iBytes; j++ )
49 { 49 {
50 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF); 50 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF);
51 } 51 }
52 } 52 }
53 else 53 else
54 { 54 {
55 clear(); 55 clear();
56 } 56 }
57 57
58 fixup(); 58 fixup();
59} 59}
60 60
61Bu::BitString::~BitString() 61Bu::BitString::~BitString()
62{ 62{
63 if( caData != NULL ) delete[] caData; 63 if( caData != NULL ) delete[] caData;
64} 64}
65 65
66Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc ) 66Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc )
67{ 67{
68 if( caData != NULL ) 68 if( caData != NULL )
69 { 69 {
70 delete[] caData; 70 delete[] caData;
71 } 71 }
72 iBits = xSrc.iBits; 72 iBits = xSrc.iBits;
73 iBytes = xSrc.iBytes; 73 iBytes = xSrc.iBytes;
74 cTopByteMask = xSrc.cTopByteMask; 74 cTopByteMask = xSrc.cTopByteMask;
75 caData = new unsigned char[iBytes]; 75 caData = new unsigned char[iBytes];
76 memcpy( caData, xSrc.caData, iBytes ); 76 memcpy( caData, xSrc.caData, iBytes );
77 77
78 fixup(); 78 fixup();
79 79
80 return *this; 80 return *this;
81} 81}
82 82
83Bu::BitString Bu::BitString::operator~() 83Bu::BitString Bu::BitString::operator~()
84{ 84{
85 Bu::BitString xRet( *this ); 85 Bu::BitString xRet( *this );
86 86
87 for( int j = 0; j < xRet.iBytes; j++ ) 87 for( int j = 0; j < xRet.iBytes; j++ )
88 { 88 {
89 xRet.caData[j] = ~xRet.caData[j]; 89 xRet.caData[j] = ~xRet.caData[j];
90 } 90 }
91 91
92 xRet.fixup(); 92 xRet.fixup();
93 93
94 return xRet; 94 return xRet;
95} 95}
96 96
97Bu::BitString Bu::BitString::operator<<( const long iAmt ) 97Bu::BitString Bu::BitString::operator<<( const long iAmt )
98{ 98{
99 if( iAmt == 0 ) 99 if( iAmt == 0 )
100 { 100 {
101 return (*this); 101 return (*this);
102 } 102 }
103 //int iByteShift = iAmt/8; 103 //int iByteShift = iAmt/8;
104 104
105 Bu::BitString xSub( getSize() ); 105 Bu::BitString xSub( getSize() );
106 106
107 long shft = (iAmt%8); 107 long shft = (iAmt%8);
108 long base = (iAmt/8); 108 long base = (iAmt/8);
109 unsigned char lowmask=0; 109 unsigned char lowmask=0;
110 for( long j = 0; j < 8-shft; j++ ) 110 for( long j = 0; j < 8-shft; j++ )
111 { 111 {
112 lowmask |= (1<<j); 112 lowmask |= (1<<j);
113 } 113 }
114 for( long j = 0; j < xSub.iBytes; j++ ) 114 for( long j = 0; j < xSub.iBytes; j++ )
115 { 115 {
116 xSub.caData[base+j] = ((caData[j]>>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask)); 116 xSub.caData[base+j] = ((caData[j]>>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask));
117 } 117 }
118 xSub.fixup(); 118 xSub.fixup();
119 119
120 return xSub; 120 return xSub;
121} 121}
122 122
123Bu::BitString Bu::BitString::operator>>( const long iAmt ) 123Bu::BitString Bu::BitString::operator>>( const long iAmt )
124{ 124{
125 if( iAmt == 0 ) 125 if( iAmt == 0 )
126 { 126 {
127 return (*this); 127 return (*this);
128 } 128 }
129 return (*this); 129 return (*this);
130} 130}
131 131
132void Bu::BitString::shiftLeft( long iAmt ) 132void Bu::BitString::shiftLeft( long iAmt )
133{ 133{
134 if( iAmt == 0 ) 134 if( iAmt == 0 )
135 { 135 {
136 return; 136 return;
137 } 137 }
138 else if( iAmt < 0 ) 138 else if( iAmt < 0 )
139 { 139 {
140 shiftRight( -iAmt ); 140 shiftRight( -iAmt );
141 return; 141 return;
142 } 142 }
143 143
144 long iByteShift = iAmt/8; 144 long iByteShift = iAmt/8;
145 long iBitShift = iAmt%8; 145 long iBitShift = iAmt%8;
146 146
147 long j; 147 long j;
148 for( j = iBytes-1; j >= 0; j-- ) 148 for( j = iBytes-1; j >= 0; j-- )
149 { 149 {
150 caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<<iBitShift))) | (((j-iByteShift-1)<0)?(0):((caData[j-iByteShift-1]>>(8-iBitShift)))); 150 caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<<iBitShift))) | (((j-iByteShift-1)<0)?(0):((caData[j-iByteShift-1]>>(8-iBitShift))));
151 } 151 }
152 152
153 fixup(); 153 fixup();
154} 154}
155 155
156void Bu::BitString::shiftRight( long iAmt ) 156void Bu::BitString::shiftRight( long iAmt )
157{ 157{
158 if( iAmt == 0 ) 158 if( iAmt == 0 )
159 { 159 {
160 return; 160 return;
161 } 161 }
162 else if( iAmt < 0 ) 162 else if( iAmt < 0 )
163 { 163 {
164 shiftLeft( -iAmt ); 164 shiftLeft( -iAmt );
165 return; 165 return;
166 } 166 }
167 167
168 long iByteShift = iAmt/8; 168 long iByteShift = iAmt/8;
169 long iBitShift = iAmt%8; 169 long iBitShift = iAmt%8;
170 170
171 long j; 171 long j;
172 for( j = 0; j < iBytes; j++ ) 172 for( j = 0; j < iBytes; j++ )
173 { 173 {
174 caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift)))); 174 caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift))));
175 } 175 }
176 176
177 fixup(); 177 fixup();
178} 178}
179/* 179/*
180long Bu::BitString::bitsToBytes( long iBits ) 180long Bu::BitString::bitsToBytes( long iBits )
181{ 181{
182 return (iBits/8)+((iBits%8)?(1):(0)); 182 return (iBits/8)+((iBits%8)?(1):(0));
183} 183}
184*/ 184*/
185void Bu::BitString::fixup() 185void Bu::BitString::fixup()
186{ 186{
187 if( caData != NULL ) 187 if( caData != NULL )
188 { 188 {
189 caData[iBytes-1] &= cTopByteMask; 189 caData[iBytes-1] &= cTopByteMask;
190 } 190 }
191} 191}
192 192
193void Bu::BitString::setBit( long iBit, bool bBitState ) 193void Bu::BitString::setBit( long iBit, bool bBitState )
194{ 194{
195 if( iBit < 0 || iBit >= iBits ) 195 if( iBit < 0 || iBit >= iBits )
196 throw Bu::ExceptionBase("bit out of range: %d in (0-%d)", iBit, iBits ); 196 throw Bu::ExceptionBase("bit out of range: %d in (0-%d)", iBit, iBits );
197 if( bBitState ) 197 if( bBitState )
198 { 198 {
199 caData[iBit/8] |= (1<<(iBit%8)); 199 caData[iBit/8] |= (1<<(iBit%8));
200 } 200 }
201 else 201 else
202 { 202 {
203 caData[iBit/8] &= ~(1<<(iBit%8)); 203 caData[iBit/8] &= ~(1<<(iBit%8));
204 } 204 }
205} 205}
206 206
207void Bu::BitString::flipBit( long iBit ) 207void Bu::BitString::flipBit( long iBit )
208{ 208{
209 caData[iBit/8] ^= (1<<(iBit%8)); 209 caData[iBit/8] ^= (1<<(iBit%8));
210} 210}
211 211
212bool Bu::BitString::getBit( long iBit ) 212bool Bu::BitString::getBit( long iBit )
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 )
216 { 216 {
217 return false; 217 return false;
218 } 218 }
219 return true; 219 return true;
220} 220}
221 221
222long Bu::BitString::getBitLength() 222long Bu::BitString::getBitLength()
223{ 223{
224 return iBits; 224 return iBits;
225} 225}
226 226
227long Bu::BitString::getSize() 227long Bu::BitString::getSize()
228{ 228{
229 return iBits; 229 return iBits;
230} 230}
231 231
232class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper ) 232class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper )
233{ 233{
234 if( iUpper == 0 || iUpper < iLower ) iUpper = iBits; 234 if( iUpper == 0 || iUpper < iLower ) iUpper = iBits;
235 235
236 Bu::BitString xSub( iUpper-iLower+1 ); 236 Bu::BitString xSub( iUpper-iLower+1 );
237 237
238 long shft = (iLower%8); 238 long shft = (iLower%8);
239 long base = (iLower/8); 239 long base = (iLower/8);
240 unsigned char lowmask=0; 240 unsigned char lowmask=0;
241 for( long j = 0; j < 8-shft; j++ ) 241 for( long j = 0; j < 8-shft; j++ )
242 { 242 {
243 lowmask |= (1<<j); 243 lowmask |= (1<<j);
244 } 244 }
245 for( long j = 0; j < xSub.iBytes; j++ ) 245 for( long j = 0; j < xSub.iBytes; j++ )
246 { 246 {
247 xSub.caData[j] = ((caData[base+j]>>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask)); 247 xSub.caData[j] = ((caData[base+j]>>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask));
248 } 248 }
249 xSub.fixup(); 249 xSub.fixup();
250 250
251 return xSub; 251 return xSub;
252} 252}
253 253
254long Bu::BitString::toLong( long iStart, long iSize ) 254long Bu::BitString::toLong( long iStart, long iSize )
255{ 255{
256 if( iSize < 1 ) iSize = 1; 256 if( iSize < 1 ) iSize = 1;
257 if( iSize > 32 ) iSize = 32; 257 if( iSize > 32 ) iSize = 32;
258 if( iStart < 0 ) return 0; 258 if( iStart < 0 ) return 0;
259 if( iStart+iSize > getSize() ) return 0; 259 if( iStart+iSize > getSize() ) return 0;
260 260
261 Bu::BitString tmpo; 261 Bu::BitString tmpo;
262 tmpo = getSubString( iStart, iStart+iSize-1 ); 262 tmpo = getSubString( iStart, iStart+iSize-1 );
263 long x = *((long *)tmpo.caData); 263 long x = *((long *)tmpo.caData);
264 264
265 return x; 265 return x;
266} 266}
267/* 267/*
268std::string Bu::BitString::toString( bool bAddSpacers ) 268std::string Bu::BitString::toString( bool bAddSpacers )
269{ 269{
270 long iSz = iBits; 270 long iSz = iBits;
271 if( bAddSpacers ) 271 if( bAddSpacers )
272 { 272 {
273 iSz += (iBits/8); 273 iSz += (iBits/8);
274 if( iBits%8 == 0 ) iSz--; 274 if( iBits%8 == 0 ) iSz--;
275 } 275 }
276 std::string xStr; 276 std::string xStr;
277 277
278 int bw=0; 278 int bw=0;
279 int of=0; 279 int of=0;
280 for( int j = iBits-1; j >= 0; j-- ) 280 for( int j = iBits-1; j >= 0; j-- )
281 { 281 {
282 if( getBit( j ) ) 282 if( getBit( j ) )
283 { 283 {
284 xStr += '1'; 284 xStr += '1';
285 } 285 }
286 else 286 else
287 { 287 {
288 xStr += '0'; 288 xStr += '0';
289 } 289 }
290 290
291 if( bAddSpacers ) 291 if( bAddSpacers )
292 { 292 {
293 bw++; 293 bw++;
294 if( bw >= 8 && j < iBits-1 ) 294 if( bw >= 8 && j < iBits-1 )
295 { 295 {
296 bw = 0; 296 bw = 0;
297 of++; 297 of++;
298 xStr += ' '; 298 xStr += ' ';
299 } 299 }
300 } 300 }
301 } 301 }
302 302
303 return xStr; 303 return xStr;
304} 304}
305*/ 305*/
306void Bu::BitString::clear() 306void Bu::BitString::clear()
307{ 307{
308 if( caData != NULL ) 308 if( caData != NULL )
309 { 309 {
310 memset( caData, 0, iBytes ); 310 memset( caData, 0, iBytes );
311 } 311 }
312} 312}
313 313
314bool Bu::BitString::setBitLength( long iLength, bool bClear ) 314bool Bu::BitString::setBitLength( long iLength, bool bClear )
315{ 315{
316 return setSize( iLength, bClear ); 316 return setSize( iLength, bClear );
317} 317}
318 318
319bool Bu::BitString::setSize( long iLength, bool bClear ) 319bool Bu::BitString::setSize( long iLength, bool bClear )
320{ 320{
321 // First, if there's nothing, then allocate an empty one. 321 // First, if there's nothing, then allocate an empty one.
322 if( caData == NULL ) 322 if( caData == NULL )
323 { 323 {
324 iBits = iLength; 324 iBits = iLength;
325 iBytes = bitsToBytes( iLength ); 325 iBytes = bitsToBytes( iLength );
326 caData = new unsigned char[iBytes]; 326 caData = new unsigned char[iBytes];
327 memset( caData, 0, iBytes ); 327 memset( caData, 0, iBytes );
328 return true; 328 return true;
329 } 329 }
330 330
331 // If the new length is the same as the old, don't do anything, but do 331 // If the new length is the same as the old, don't do anything, but do
332 // check to see if we should still clear the data. 332 // check to see if we should still clear the data.
333 if( iBits != iLength ) 333 if( iBits != iLength )
334 { 334 {
335 // Ok, we are changing the number if bits, but are we changing the 335 // Ok, we are changing the number if bits, but are we changing the
336 // number of bytes? 336 // number of bytes?
337 long iNewBytes = bitsToBytes( iLength ); 337 long iNewBytes = bitsToBytes( iLength );
338 if( iBytes == iNewBytes ) 338 if( iBytes == iNewBytes )
339 { 339 {
340 // No? That makes life easier 340 // No? That makes life easier
341 iBits = iLength; 341 iBits = iLength;
342 setMask(); 342 setMask();
343 if( bClear ) 343 if( bClear )
344 { 344 {
345 clear(); 345 clear();
346 } 346 }
347 } 347 }
348 else 348 else
349 { 349 {
350 // Ok, reallocate and copy... 350 // Ok, reallocate and copy...
351 iBits = iLength; 351 iBits = iLength;
352// long iNewBytes = bitsToBytes( iLength ); 352// long iNewBytes = bitsToBytes( iLength );
353 if( bClear ) 353 if( bClear )
354 { 354 {
355 delete[] caData; 355 delete[] caData;
356 caData = new unsigned char[iNewBytes]; 356 caData = new unsigned char[iNewBytes];
357 memset( caData, 0, iNewBytes ); 357 memset( caData, 0, iNewBytes );
358 } 358 }
359 else 359 else
360 { 360 {
361 unsigned char *tmp = caData; 361 unsigned char *tmp = caData;
362 caData = new unsigned char[iNewBytes]; 362 caData = new unsigned char[iNewBytes];
363 if( iNewBytes < iBytes ) 363 if( iNewBytes < iBytes )
364 { 364 {
365 memcpy( caData, tmp, iNewBytes ); 365 memcpy( caData, tmp, iNewBytes );
366 } 366 }
367 else 367 else
368 { 368 {
369 memcpy( caData, tmp, iBytes ); 369 memcpy( caData, tmp, iBytes );
370 } 370 }
371 delete[] tmp; 371 delete[] tmp;
372 } 372 }
373 iBytes = iNewBytes; 373 iBytes = iNewBytes;
374 374
375 setMask(); 375 setMask();
376 } 376 }
377 377
378 } 378 }
379 else if( bClear ) 379 else if( bClear )
380 { 380 {
381 clear(); 381 clear();
382 } 382 }
383 383
384 return true; 384 return true;
385} 385}
386 386
387void Bu::BitString::setMask() 387void Bu::BitString::setMask()
388{ 388{
389 // This can either mean that there are a multiple of eight bits or 389 // This can either mean that there are a multiple of eight bits or
390 // zero, if there are zero you're an idiot (zero can't happen, because 390 // zero, if there are zero you're an idiot (zero can't happen, because
391 // we would allocate an extra byte and never use it) 391 // we would allocate an extra byte and never use it)
392 if( (iBits%8 == 0) ) 392 if( (iBits%8 == 0) )
393 { 393 {
394 cTopByteMask = 0xFF; 394 cTopByteMask = 0xFF;
395 } 395 }
396 else 396 else
397 { 397 {
398 cTopByteMask = 0; 398 cTopByteMask = 0;
399 for( long j = 0; j < (iBits%8); j++ ) 399 for( long j = 0; j < (iBits%8); j++ )
400 { 400 {
401 cTopByteMask |= (1<<j); 401 cTopByteMask |= (1<<j);
402 } 402 }
403 } 403 }
404} 404}
405 405
406void Bu::BitString::randomize() 406void Bu::BitString::randomize()
407{ 407{
408 if( caData != NULL ) 408 if( caData != NULL )
409 { 409 {
410 for( int j = 0; j < iBytes; j++ ) 410 for( int j = 0; j < iBytes; j++ )
411 { 411 {
412 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF); 412 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF);
413 } 413 }
414 fixup(); 414 fixup();
415 } 415 }
416} 416}
417 417
418void Bu::BitString::invert() 418void Bu::BitString::invert()
419{ 419{
420 if( caData != NULL ) 420 if( caData != NULL )
421 { 421 {
422 for( long j = 0; j < iBytes; j++ ) 422 for( long j = 0; j < iBytes; j++ )
423 { 423 {
424 caData[j] = ~caData[j]; 424 caData[j] = ~caData[j];
425 } 425 }
426 fixup(); 426 fixup();
427 } 427 }
428} 428}
429 429
430long Bu::BitString::getHighestOrderBitPos() 430long Bu::BitString::getHighestOrderBitPos()
431{ 431{
432 for( long j = iBits-1; j >= 0; j-- ) 432 for( long j = iBits-1; j >= 0; j-- )
433 { 433 {
434 if( getBit( j ) ) 434 if( getBit( j ) )
435 { 435 {
436 return j; 436 return j;
437 } 437 }
438 } 438 }
439 439
440 return -1; 440 return -1;
441} 441}
442 442
443Bu::String Bu::BitString::toString() 443Bu::String Bu::BitString::toString()
444{ 444{
445 Bu::String sRet; 445 Bu::String sRet;
446 for( int j = iBits-1; j >= 0; j-- ) 446 for( int j = iBits-1; j >= 0; j-- )
447 sRet.append( getBit( j )?'1':'0' ); 447 sRet.append( getBit( j )?'1':'0' );
448 return sRet; 448 return sRet;
449} 449}
450 450
451/* 451/*
452bool Bu::BitString::writeToFile( FILE *fh ) 452bool Bu::BitString::writeToFile( FILE *fh )
453{ 453{
454 fwrite( &iBits, sizeof(long), 1, fh ); 454 fwrite( &iBits, sizeof(long), 1, fh );
455 fwrite( caData, sizeof(char), iBytes, fh ); 455 fwrite( caData, sizeof(char), iBytes, fh );
456 456
457 return true; 457 return true;
458} 458}
459 459
460bool Bu::BitString::readFromFile( FILE *fh ) 460bool Bu::BitString::readFromFile( FILE *fh )
461{ 461{
462 fread( &iBits, sizeof(long), 1, fh ); 462 fread( &iBits, sizeof(long), 1, fh );
463 463
464 iBytes = bitsToBytes( iBits ); 464 iBytes = bitsToBytes( iBits );
465 if( caData ) delete[] caData; 465 if( caData ) delete[] caData;
466 caData = new unsigned char[iBytes]; 466 caData = new unsigned char[iBytes];
467 467
468 fread( caData, sizeof(char), iBytes, fh ); 468 fread( caData, sizeof(char), iBytes, fh );
469 469
470 setMask(); 470 setMask();
471 471
472 fixup(); 472 fixup();
473 473
474 return true; 474 return true;
475}*/ 475}*/
diff --git a/src/unstable/bitstring.h b/src/unstable/bitstring.h
index fd34402..ea884f6 100644
--- a/src/unstable/bitstring.h
+++ b/src/unstable/bitstring.h
@@ -13,212 +13,212 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 /** 16 /**
17 * Manages an arbitrarily sized string of bits, and allows basic interaction 17 * Manages an arbitrarily sized string of bits, and allows basic interaction
18 * with them. This includes basic non-mathematical bitwise operations such 18 * with them. This includes basic non-mathematical bitwise operations such
19 * as setting and testing bits, shifting the string, inversion and a few 19 * as setting and testing bits, shifting the string, inversion and a few
20 * extras like randomization. On linux systems this takes advantage of long 20 * extras like randomization. On linux systems this takes advantage of long
21 * longs giving you a maximum size of about 2tb per string. 21 * longs giving you a maximum size of about 2tb per string.
22 * 22 *
23 * For more general and mathematical type interaction see BitStringInt. 23 * For more general and mathematical type interaction see BitStringInt.
24 * 24 *
25 */ 25 */
26 class BitString 26 class BitString
27 { 27 {
28 public: 28 public:
29 /** 29 /**
30 * Constructs a blank and basic BitString. This is actually useful 30 * Constructs a blank and basic BitString. This is actually useful
31 * since you can resize BitStrings at will, and even retain the data 31 * since you can resize BitStrings at will, and even retain the data
32 * that was in them. 32 * that was in them.
33 */ 33 */
34 BitString(); 34 BitString();
35 35
36 /** 36 /**
37 * Constructs a BitString object as a copy of another BitString. This 37 * Constructs a BitString object as a copy of another BitString. This
38 * is a standard copy constructor and produces an exact duplicate of 38 * is a standard copy constructor and produces an exact duplicate of
39 * the original BitString object. 39 * the original BitString object.
40 *@param xSrc Source BitString to copy data from. 40 *@param xSrc Source BitString to copy data from.
41 */ 41 */
42 BitString( const BitString &xSrc ); 42 BitString( const BitString &xSrc );
43 43
44 /** 44 /**
45 * Constructs a BitString with length iBits and optionally fills it with 45 * Constructs a BitString with length iBits and optionally fills it with
46 * random data. The default setting, to not fill randomly, will produce 46 * random data. The default setting, to not fill randomly, will produce
47 * a blank (all zeros) string of the specified size. 47 * a blank (all zeros) string of the specified size.
48 *@param iBits The length of the new BitString in bits. 48 *@param iBits The length of the new BitString in bits.
49 *@param bFillRandomly Wether or not to randomize this BitString. 49 *@param bFillRandomly Wether or not to randomize this BitString.
50 */ 50 */
51 BitString( long iBits, bool bFillRandomly=false ); 51 BitString( long iBits, bool bFillRandomly=false );
52 52
53 /** 53 /**
54 * Virtual deconstructor for the BitString. Takes care of cleanup for 54 * Virtual deconstructor for the BitString. Takes care of cleanup for
55 * you. What more do you really want to know? 55 * you. What more do you really want to know?
56 */ 56 */
57 virtual ~BitString(); 57 virtual ~BitString();
58 58
59 // basic interaction 59 // basic interaction
60 /** 60 /**
61 * Sets a bit in the BitString. In it's normal mode it will always turn 61 * Sets a bit in the BitString. In it's normal mode it will always turn
62 * the given bit on, to clear a bit set bBitState to false instead of 62 * the given bit on, to clear a bit set bBitState to false instead of
63 * true. This operation runs in O(1). 63 * true. This operation runs in O(1).
64 *@param iBit The zero-based index of the bit to modify. 64 *@param iBit The zero-based index of the bit to modify.
65 *@param bBitState Set to true to set the bit to 1, set to false to set 65 *@param bBitState Set to true to set the bit to 1, set to false to set
66 * the bit to 0. 66 * the bit to 0.
67 */ 67 */
68 void setBit( long iBit, bool bBitState=true ); 68 void setBit( long iBit, bool bBitState=true );
69 69
70 /** 70 /**
71 * Reverses the state of the given bit. This will set the given bit 71 * Reverses the state of the given bit. This will set the given bit
72 * to a 1 if it was 0, and to 0 if it was 1. This operation runs in 72 * to a 1 if it was 0, and to 0 if it was 1. This operation runs in
73 * O(1), and it should be noted that using this is marginally faster 73 * O(1), and it should be noted that using this is marginally faster
74 * than doing the test and flip yourself with getBit and setBit since 74 * than doing the test and flip yourself with getBit and setBit since
75 * it uses a bitwise not operation and doesn't actually test the bit 75 * it uses a bitwise not operation and doesn't actually test the bit
76 * itself. 76 * itself.
77 *@param iBit The index of the bit to flip. 77 *@param iBit The index of the bit to flip.
78 */ 78 */
79 void flipBit( long iBit ); 79 void flipBit( long iBit );
80 80
81 /** 81 /**
82 * Gets the state of the given bit. This follows the standard 82 * Gets the state of the given bit. This follows the standard
83 * convention used so far, a returned value of true means the bit in 83 * convention used so far, a returned value of true means the bit in
84 * question is 1, and a value of flase means the bit is 0. All bits 84 * question is 1, and a value of flase means the bit is 0. All bits
85 * out of range of the BitString are treated as off, but are 85 * out of range of the BitString are treated as off, but are
86 * "accessable" in that this does not produce any kind of error 86 * "accessable" in that this does not produce any kind of error
87 * message. This is intentional. This operation runs in O(1). 87 * message. This is intentional. This operation runs in O(1).
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 );
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
95 * bit in the string but is faster since it can operate on whole bytes 95 * bit in the string but is faster since it can operate on whole bytes
96 * at a time instead of individual bits. This operation runs in O(N). 96 * at a time instead of individual bits. This operation runs in O(N).
97 */ 97 */
98 void invert(); 98 void invert();
99 99
100 /** 100 /**
101 * Returns the number of bits allocated in this BitString. This 101 * Returns the number of bits allocated in this BitString. This
102 * operation runs in O(1) time since this value is cached and not 102 * operation runs in O(1) time since this value is cached and not
103 * computed. 103 * computed.
104 *@returns The number of bits allocated in this BitString. 104 *@returns The number of bits allocated in this BitString.
105 */ 105 */
106 DEPRECATED 106 DEPRECATED
107 long getBitLength(); 107 long getBitLength();
108 108
109 long getSize(); 109 long getSize();
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.
113 * This operation runs in O(N). 113 * This operation runs in O(N).
114 */ 114 */
115 void clear(); 115 void clear();
116 116
117 /** 117 /**
118 * Gets another BitString that is autonomous of the current one 118 * Gets another BitString that is autonomous of the current one
119 * (contains a copy of the memory, not a pointer) and contains a subset 119 * (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 120 * of the data in the current BitString. This is an inclusive
121 * operation, so grabbing bits 0-5 will give you 6 bits. This is based 121 * operation, so grabbing bits 0-5 will give you 6 bits. This is based
122 * on a very tricky bit-shifting algorithm and runs very quickly, in 122 * on a very tricky bit-shifting algorithm and runs very quickly, in
123 * O(N) time. Passing in a value of zero for iUpper, or any value for 123 * O(N) time. Passing in a value of zero for iUpper, or any value for
124 * iUpper that is less than iLower will set iUpper equal to the number 124 * iUpper that is less than iLower will set iUpper equal to the number
125 * of bits in the BitString. 125 * of bits in the BitString.
126 *@param iLower The first bit in the current string, will be the first 126 *@param iLower The first bit in the current string, will be the first
127 * bit (0 index) in the new sub string. 127 * bit (0 index) in the new sub string.
128 *@param iUpper The last bit in the current string, will be the last 128 *@param iUpper The last bit in the current string, will be the last
129 * bit in the new sub string. iUpper is included in the sub string. 129 * bit in the new sub string. iUpper is included in the sub string.
130 *@returns A new BitString object ready to be used. Please note that 130 *@returns A new BitString object ready to be used. Please note that
131 * managing this new object is up to whomever calls this function. 131 * managing this new object is up to whomever calls this function.
132 */ 132 */
133 class BitString getSubString( long iLower, long iUpper ); 133 class BitString getSubString( long iLower, long iUpper );
134 134
135 /** 135 /**
136 * Sets the number of bits in the BitString, allocating more memory if 136 * Sets the number of bits in the BitString, allocating more memory if
137 * necesarry, or freeing extra if able. The default operation of this 137 * necesarry, or freeing extra if able. The default operation of this
138 * function clears all data in the BitString while resizing it. If you 138 * function clears all data in the BitString while resizing it. If you
139 * would like to keep as much of the data that you had in your BitString 139 * would like to keep as much of the data that you had in your BitString
140 * as possible, then set bClear to false, and any data that will fit 140 * as possible, then set bClear to false, and any data that will fit
141 * into the new BitString length will be retained. If increasing the 141 * into the new BitString length will be retained. If increasing the
142 * number of bits, the new bits will come into existance cleared (set 142 * number of bits, the new bits will come into existance cleared (set
143 * to 0). 143 * to 0).
144 *@param iLength The number of bits to set the BitString to. 144 *@param iLength The number of bits to set the BitString to.
145 *@param bClear When true, all data is eradicated and zeroed, when set 145 *@param bClear When true, all data is eradicated and zeroed, when set
146 * to false an effort is made to retain the existing data. 146 * to false an effort is made to retain the existing data.
147 *@returns true on success, false on failure. 147 *@returns true on success, false on failure.
148 */ 148 */
149 DEPRECATED 149 DEPRECATED
150 bool setBitLength( long iLength, bool bClear=true ); 150 bool setBitLength( long iLength, bool bClear=true );
151 bool setSize( long iLength, bool bClear=true ); 151 bool setSize( long iLength, bool bClear=true );
152 152
153 /** 153 /**
154 * Randomize the entire BitString, one bit at a time. This is actually 154 * Randomize the entire BitString, one bit at a time. This is actually
155 * the function called by the constructor when the user selects initial 155 * the function called by the constructor when the user selects initial
156 * randomization. This function uses the system random() function, so 156 * randomization. This function uses the system random() function, so
157 * srandom may be used to effect this process at will. 157 * srandom may be used to effect this process at will.
158 */ 158 */
159 void randomize(); 159 void randomize();
160 160
161 /** 161 /**
162 * Operates exactly like <<. All data in the BitString is shifted to 162 * Operates exactly like <<. All data in the BitString is shifted to
163 * the left by some number of bits, any data pushed off the edge of the 163 * the left by some number of bits, any data pushed off the edge of the
164 * BitString is lost, and all new data coming in will be zeroed. 164 * BitString is lost, and all new data coming in will be zeroed.
165 * Using a negative value in the shiftLeft function will turn it into 165 * Using a negative value in the shiftLeft function will turn it into
166 * the shiftRight function. 166 * the shiftRight function.
167 *@param iAmt The number of bit positions to shift all data. 167 *@param iAmt The number of bit positions to shift all data.
168 */ 168 */
169 void shiftLeft( long iAmt ); // just like << 169 void shiftLeft( long iAmt ); // just like <<
170 170
171 /** 171 /**
172 * Operates exactly like >>. All data in the BitString is shifted to 172 * Operates exactly like >>. All data in the BitString is shifted to
173 * the right by some number of bits, any data pushed off the edge of the 173 * the right by some number of bits, any data pushed off the edge of the
174 * BitString is lost, and all new data coming in will be zeroed. 174 * BitString is lost, and all new data coming in will be zeroed.
175 * Using a negative value in the shiftRight function will turn it into 175 * Using a negative value in the shiftRight function will turn it into
176 * the shiftLeft function. 176 * the shiftLeft function.
177 *@param iAmt The number of bit positions to shift all data. 177 *@param iAmt The number of bit positions to shift all data.
178 */ 178 */
179 void shiftRight( long iAmt ); // just like >> 179 void shiftRight( long iAmt ); // just like >>
180 180
181 /** 181 /**
182 * Searches through the BitString and returns the index of the highest 182 * Searches through the BitString and returns the index of the highest
183 * order bit position (the highest index) with an on bit (a bit set to 183 * order bit position (the highest index) with an on bit (a bit set to
184 * 1). This is a handy helper function and rather faster than calling 184 * 1). This is a handy helper function and rather faster than calling
185 * getBit() over and over again. 185 * getBit() over and over again.
186 *@returns The index of the highest indexed on bit. 186 *@returns The index of the highest indexed on bit.
187 */ 187 */
188 long getHighestOrderBitPos(); 188 long getHighestOrderBitPos();
189 189
190 // Conversion 190 // Conversion
191 /** 191 /**
192 * Convert a block of data (no more than 32 bits) to a primitive long 192 * Convert a block of data (no more than 32 bits) to a primitive long
193 * type. 193 * type.
194 * This is done in a little bit interesting way, so it may not always be 194 * This is done in a little bit interesting way, so it may not always be
195 * the fastest way to access the data that you want, although it will 195 * the fastest way to access the data that you want, although it will
196 * always ensure that the long that is written makes numerical sense, as 196 * always ensure that the long that is written makes numerical sense, as
197 * we write numbers, regaurdless of platform. 197 * we write numbers, regaurdless of platform.
198 *@param iStart The first bit in the BitString to include in the long 198 *@param iStart The first bit in the BitString to include in the long
199 *@param iSize THe number of bits to include, if this value is set over 199 *@param iSize THe number of bits to include, if this value is set over
200 * 32 it will be automatically truncated to, or however many bits there 200 * 32 it will be automatically truncated to, or however many bits there
201 * are in a long in your system. 201 * are in a long in your system.
202 *@returns A long converted from your raw BitString data. 202 *@returns A long converted from your raw BitString data.
203 */ 203 */
204 long toLong( long iStart = 0, long iSize = 32 ); 204 long toLong( long iStart = 0, long iSize = 32 );
205 205
206 Bu::String toString(); 206 Bu::String toString();
207 207
208 //operators 208 //operators
209 BitString &operator=( const BitString &xSrc ); 209 BitString &operator=( const BitString &xSrc );
210 BitString operator~(); 210 BitString operator~();
211 BitString operator<<( const long iAmt ); 211 BitString operator<<( const long iAmt );
212 BitString operator>>( const long iAmt ); 212 BitString operator>>( const long iAmt );
213 213
214 private: 214 private:
215 void fixup(); 215 void fixup();
216 void setMask(); 216 void setMask();
217 unsigned char *caData; 217 unsigned char *caData;
218 long iBits; 218 long iBits;
219 long iBytes; 219 long iBytes;
220 unsigned char cTopByteMask; 220 unsigned char cTopByteMask;
221 }; 221 };
222}; 222};
223 223
224#endif 224#endif
diff --git a/src/unstable/fifo.cpp b/src/unstable/fifo.cpp
index 6f327df..4b4a2bf 100644
--- a/src/unstable/fifo.cpp
+++ b/src/unstable/fifo.cpp
@@ -17,75 +17,75 @@
17namespace Bu { subExceptionDef( FifoException ) } 17namespace Bu { subExceptionDef( FifoException ) }
18 18
19Bu::Fifo::Fifo( const Bu::String &sName, int iFlags, mode_t mAcc ) : 19Bu::Fifo::Fifo( const Bu::String &sName, int iFlags, mode_t mAcc ) :
20 iFlags( iFlags ), 20 iFlags( iFlags ),
21 iIn( -1 ), 21 iIn( -1 ),
22 iOut( -1 ) 22 iOut( -1 )
23{ 23{
24#ifndef WIN32 24#ifndef WIN32
25 if( iFlags&Create ) 25 if( iFlags&Create )
26 { 26 {
27 if( mkfifo( sName.getStr(), mAcc ) ) 27 if( mkfifo( sName.getStr(), mAcc ) )
28 { 28 {
29 throw FifoException("Error creating fifo: %s\n", strerror( errno ) ); 29 throw FifoException("Error creating fifo: %s\n", strerror( errno ) );
30 } 30 }
31 } 31 }
32 if( iFlags&Read ) 32 if( iFlags&Read )
33 { 33 {
34 iIn = ::open( 34 iIn = ::open(
35 sName.getStr(), 35 sName.getStr(),
36 O_RDONLY|((iFlags&NonBlock)?O_NONBLOCK:0) 36 O_RDONLY|((iFlags&NonBlock)?O_NONBLOCK:0)
37 ); 37 );
38 } 38 }
39 if( iFlags&Write ) 39 if( iFlags&Write )
40 { 40 {
41 iOut = ::open( 41 iOut = ::open(
42 sName.getStr(), 42 sName.getStr(),
43 O_WRONLY 43 O_WRONLY
44 ); 44 );
45 } 45 }
46#else 46#else
47 #warning Bu::Fifo::Fifo IS A STUB for WIN32!!!! 47 #warning Bu::Fifo::Fifo IS A STUB for WIN32!!!!
48#endif 48#endif
49} 49}
50 50
51Bu::Fifo::~Fifo() 51Bu::Fifo::~Fifo()
52{ 52{
53 close(); 53 close();
54} 54}
55 55
56void Bu::Fifo::close() 56void Bu::Fifo::close()
57{ 57{
58 if( iIn > -1 ) 58 if( iIn > -1 )
59 { 59 {
60 ::close( iIn ); 60 ::close( iIn );
61 iIn = -1; 61 iIn = -1;
62 } 62 }
63 if( iOut > -1 ) 63 if( iOut > -1 )
64 { 64 {
65 ::close( iOut ); 65 ::close( iOut );
66 iOut = -1; 66 iOut = -1;
67 } 67 }
68} 68}
69 69
70Bu::size Bu::Fifo::read( void *pBuf, Bu::size nBytes ) 70Bu::size Bu::Fifo::read( void *pBuf, Bu::size nBytes )
71{ 71{
72 if( iIn < 0 ) 72 if( iIn < 0 )
73 throw FifoException("Fifo not open for reading."); 73 throw FifoException("Fifo not open for reading.");
74 74
75 return TEMP_FAILURE_RETRY( ::read( iIn, pBuf, nBytes ) ); 75 return TEMP_FAILURE_RETRY( ::read( iIn, pBuf, nBytes ) );
76} 76}
77 77
78Bu::size Bu::Fifo::write( const void *pBuf, Bu::size nBytes ) 78Bu::size Bu::Fifo::write( const void *pBuf, Bu::size nBytes )
79{ 79{
80 if( iOut < 0 ) 80 if( iOut < 0 )
81 throw FifoException("Fifo not open for writing."); 81 throw FifoException("Fifo not open for writing.");
82 82
83 return TEMP_FAILURE_RETRY( ::write( iOut, pBuf, nBytes ) ); 83 return TEMP_FAILURE_RETRY( ::write( iOut, pBuf, nBytes ) );
84} 84}
85 85
86Bu::size Bu::Fifo::tell() 86Bu::size Bu::Fifo::tell()
87{ 87{
88 return -1; 88 return -1;
89} 89}
90 90
91void Bu::Fifo::seek( Bu::size ) 91void Bu::Fifo::seek( Bu::size )
@@ -102,53 +102,53 @@ void Bu::Fifo::setPosEnd( Bu::size )
102 102
103bool Bu::Fifo::isEos() 103bool Bu::Fifo::isEos()
104{ 104{
105 return false; 105 return false;
106} 106}
107 107
108bool Bu::Fifo::canRead() 108bool Bu::Fifo::canRead()
109{ 109{
110 return (iIn>-1); 110 return (iIn>-1);
111} 111}
112 112
113bool Bu::Fifo::canWrite() 113bool Bu::Fifo::canWrite()
114{ 114{
115 return (iOut>-1); 115 return (iOut>-1);
116} 116}
117 117
118bool Bu::Fifo::isReadable() 118bool Bu::Fifo::isReadable()
119{ 119{
120 return (iIn>-1); 120 return (iIn>-1);
121} 121}
122 122
123bool Bu::Fifo::isWritable() 123bool Bu::Fifo::isWritable()
124{ 124{
125 return (iOut>-1); 125 return (iOut>-1);
126} 126}
127 127
128bool Bu::Fifo::isSeekable() 128bool Bu::Fifo::isSeekable()
129{ 129{
130 return false; 130 return false;
131} 131}
132 132
133bool Bu::Fifo::isBlocking() 133bool Bu::Fifo::isBlocking()
134{ 134{
135#ifndef WIN32 135#ifndef WIN32
136 return ((fcntl( iIn, F_GETFL, 0 )&O_NONBLOCK) == O_NONBLOCK); 136 return ((fcntl( iIn, F_GETFL, 0 )&O_NONBLOCK) == O_NONBLOCK);
137#else 137#else
138 #warning Bu::Fifo::isBlocking IS A STUB for WIN32!!!! 138 #warning Bu::Fifo::isBlocking IS A STUB for WIN32!!!!
139#endif 139#endif
140} 140}
141 141
142void Bu::Fifo::setBlocking( bool bBlocking ) 142void Bu::Fifo::setBlocking( bool bBlocking )
143{ 143{
144#ifndef WIN32 144#ifndef WIN32
145 if( bBlocking ) 145 if( bBlocking )
146 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )&(~O_NONBLOCK) ); 146 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )&(~O_NONBLOCK) );
147 else 147 else
148 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )|O_NONBLOCK ); 148 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )|O_NONBLOCK );
149#else 149#else
150 #warning Bu::Fifo::setBlocking IS A STUB for WIN32!!!! 150 #warning Bu::Fifo::setBlocking IS A STUB for WIN32!!!!
151#endif 151#endif
152} 152}
153 153
154void Bu::Fifo::flush() 154void Bu::Fifo::flush()
@@ -157,6 +157,6 @@ void Bu::Fifo::flush()
157 157
158bool Bu::Fifo::isOpen() 158bool Bu::Fifo::isOpen()
159{ 159{
160 return (iIn > -1) || (iOut > -1); 160 return (iIn > -1) || (iOut > -1);
161} 161}
162 162
diff --git a/src/unstable/fifo.h b/src/unstable/fifo.h
index ea32f04..3d9192a 100644
--- a/src/unstable/fifo.h
+++ b/src/unstable/fifo.h
@@ -18,55 +18,55 @@
18 18
19namespace Bu 19namespace Bu
20{ 20{
21 subExceptionDecl( FifoException ); 21 subExceptionDecl( FifoException );
22 22
23 /** 23 /**
24 * A fifo stream. 24 * A fifo stream.
25 *@ingroup Streams 25 *@ingroup Streams
26 */ 26 */
27 class Fifo : public Bu::Stream 27 class Fifo : public Bu::Stream
28 { 28 {
29 public: 29 public:
30 Fifo( const Bu::String &sName, int iFlags, mode_t mAcc=-1 ); 30 Fifo( const Bu::String &sName, int iFlags, mode_t mAcc=-1 );
31 virtual ~Fifo(); 31 virtual ~Fifo();
32 32
33 virtual void close(); 33 virtual void close();
34 virtual Bu::size read( void *pBuf, Bu::size nBytes ); 34 virtual Bu::size read( void *pBuf, Bu::size nBytes );
35 virtual Bu::size write( const void *pBuf, Bu::size nBytes ); 35 virtual Bu::size write( const void *pBuf, Bu::size nBytes );
36 using Stream::write; 36 using Stream::write;
37 37
38 virtual Bu::size tell(); 38 virtual Bu::size tell();
39 virtual void seek( Bu::size offset ); 39 virtual void seek( Bu::size offset );
40 virtual void setPos( Bu::size pos ); 40 virtual void setPos( Bu::size pos );
41 virtual void setPosEnd( Bu::size pos ); 41 virtual void setPosEnd( Bu::size pos );
42 virtual bool isEos(); 42 virtual bool isEos();
43 virtual bool isOpen(); 43 virtual bool isOpen();
44 44
45 virtual void flush(); 45 virtual void flush();
46 46
47 virtual bool canRead(); 47 virtual bool canRead();
48 virtual bool canWrite(); 48 virtual bool canWrite();
49 49
50 virtual bool isReadable(); 50 virtual bool isReadable();
51 virtual bool isWritable(); 51 virtual bool isWritable();
52 virtual bool isSeekable(); 52 virtual bool isSeekable();
53 53
54 virtual bool isBlocking(); 54 virtual bool isBlocking();
55 virtual void setBlocking( bool bBlocking=true ); 55 virtual void setBlocking( bool bBlocking=true );
56 56
57 enum { 57 enum {
58 Read = 0x01, 58 Read = 0x01,
59 Write = 0x02, 59 Write = 0x02,
60 Create = 0x04, 60 Create = 0x04,
61 Delete = 0x08, 61 Delete = 0x08,
62 NonBlock = 0x10 62 NonBlock = 0x10
63 }; 63 };
64 64
65 private: 65 private:
66 int iFlags; 66 int iFlags;
67 int iIn; 67 int iIn;
68 int iOut; 68 int iOut;
69 }; 69 };
70} 70}
71 71
72#endif 72#endif
diff --git a/src/unstable/itoserver.cpp b/src/unstable/itoserver.cpp
index 7dbce6c..103bf90 100644
--- a/src/unstable/itoserver.cpp
+++ b/src/unstable/itoserver.cpp
@@ -13,121 +13,121 @@
13#include "bu/tcpsocket.h" 13#include "bu/tcpsocket.h"
14 14
15Bu::ItoServer::ItoServer() : 15Bu::ItoServer::ItoServer() :
16 nTimeoutSec( 1 ), 16 nTimeoutSec( 1 ),
17 nTimeoutUSec( 0 ) 17 nTimeoutUSec( 0 )
18{ 18{
19 FD_ZERO( &fdActive ); 19 FD_ZERO( &fdActive );
20} 20}
21 21
22Bu::ItoServer::~ItoServer() 22Bu::ItoServer::~ItoServer()
23{ 23{
24 while( !qClientCleanup.isEmpty() ) 24 while( !qClientCleanup.isEmpty() )
25 { 25 {
26 ItoClient *pCli = qClientCleanup.dequeue(); 26 ItoClient *pCli = qClientCleanup.dequeue();
27 pCli->join(); 27 pCli->join();
28 delete pCli; 28 delete pCli;
29 } 29 }
30 // TODO: Make sure here that each client has shutdown it's socket, and 30 // TODO: Make sure here that each client has shutdown it's socket, and
31 // maybe even written any extra data, we could put a timelimit on this... 31 // maybe even written any extra data, we could put a timelimit on this...
32 // anyway, it's not as clean as it could be right now. 32 // anyway, it's not as clean as it could be right now.
33 for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) 33 for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ )
34 { 34 {
35 ItoClient *pCli = (*i); 35 ItoClient *pCli = (*i);
36 pCli->join(); 36 pCli->join();
37 delete pCli; 37 delete pCli;
38 } 38 }
39} 39}
40 40
41void Bu::ItoServer::addPort( int nPort, int nPoolSize ) 41void Bu::ItoServer::addPort( int nPort, int nPoolSize )
42{ 42{
43 TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); 43 TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize );
44 socket_t nSocket = s->getSocket(); 44 socket_t nSocket = s->getSocket();
45 FD_SET( nSocket, &fdActive ); 45 FD_SET( nSocket, &fdActive );
46 hServers.insert( nSocket, s ); 46 hServers.insert( nSocket, s );
47} 47}
48 48
49void Bu::ItoServer::addPort( const String &sAddr, int nPort, int nPoolSize ) 49void Bu::ItoServer::addPort( const String &sAddr, int nPort, int nPoolSize )
50{ 50{
51 TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); 51 TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize );
52 socket_t nSocket = s->getSocket(); 52 socket_t nSocket = s->getSocket();
53 FD_SET( nSocket, &fdActive ); 53 FD_SET( nSocket, &fdActive );
54 hServers.insert( nSocket, s ); 54 hServers.insert( nSocket, s );
55} 55}
56 56
57void Bu::ItoServer::setTimeout( int nTimeoutSec, int nTimeoutUSec ) 57void Bu::ItoServer::setTimeout( int nTimeoutSec, int nTimeoutUSec )
58{ 58{
59 this->nTimeoutSec = nTimeoutSec; 59 this->nTimeoutSec = nTimeoutSec;
60 this->nTimeoutUSec = nTimeoutUSec; 60 this->nTimeoutUSec = nTimeoutUSec;
61} 61}
62 62
63void Bu::ItoServer::addClient( socket_t nSocket, int nPort ) 63void Bu::ItoServer::addClient( socket_t nSocket, int nPort )
64{ 64{
65 ItoClient *pC = new ItoClient( *this, nSocket, nPort, nTimeoutSec, 65 ItoClient *pC = new ItoClient( *this, nSocket, nPort, nTimeoutSec,
66 nTimeoutUSec ); 66 nTimeoutUSec );
67 67
68 imClients.lock(); 68 imClients.lock();
69 hClients.insert( nSocket, pC ); 69 hClients.insert( nSocket, pC );
70 imClients.unlock(); 70 imClients.unlock();
71 71
72 pC->start(); 72 pC->start();
73} 73}
74 74
75void Bu::ItoServer::run() 75void Bu::ItoServer::run()
76{ 76{
77 for(;;) 77 for(;;)
78 { 78 {
79 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; 79 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec };
80 80
81 fd_set fdRead = fdActive; 81 fd_set fdRead = fdActive;
82 //fd_set fdWrite = fdActive; 82 //fd_set fdWrite = fdActive;
83 fd_set fdException = fdActive; 83 fd_set fdException = fdActive;
84 84
85 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, NULL, &fdException, &xTimeout ) ) < 0 ) 85 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, NULL, &fdException, &xTimeout ) ) < 0 )
86 { 86 {
87 throw ExceptionBase("Error attempting to scan open connections."); 87 throw ExceptionBase("Error attempting to scan open connections.");
88 } 88 }
89 89
90 for( ServerHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) 90 for( ServerHash::iterator i = hServers.begin(); i != hServers.end(); i++ )
91 { 91 {
92 if( FD_ISSET( i.getKey(), &fdRead ) ) 92 if( FD_ISSET( i.getKey(), &fdRead ) )
93 { 93 {
94 TcpServerSocket *pSrv = i.getValue(); 94 TcpServerSocket *pSrv = i.getValue();
95 addClient( pSrv->accept(), pSrv->getPort() ); 95 addClient( pSrv->accept(), pSrv->getPort() );
96 } 96 }
97 } 97 }
98 98
99 while( !qClientCleanup.isEmpty() ) 99 while( !qClientCleanup.isEmpty() )
100 { 100 {
101 ItoClient *pCli = qClientCleanup.dequeue(); 101 ItoClient *pCli = qClientCleanup.dequeue();
102 pCli->join(); 102 pCli->join();
103 delete pCli; 103 delete pCli;
104 } 104 }
105 } 105 }
106} 106}
107 107
108void Bu::ItoServer::clientCleanup( socket_t iSocket ) 108void Bu::ItoServer::clientCleanup( socket_t iSocket )
109{ 109{
110 imClients.lock(); 110 imClients.lock();
111 ItoClient *pCli = hClients.get( iSocket ); 111 ItoClient *pCli = hClients.get( iSocket );
112 imClients.unlock(); 112 imClients.unlock();
113 qClientCleanup.enqueue( pCli ); 113 qClientCleanup.enqueue( pCli );
114} 114}
115 115
116Bu::ItoServer::ItoClient::ItoClient( ItoServer &rSrv, Bu::ItoServer::socket_t iSocket, int iPort, 116Bu::ItoServer::ItoClient::ItoClient( ItoServer &rSrv, Bu::ItoServer::socket_t iSocket, int iPort,
117 int nTimeoutSec, int nTimeoutUSec ) : 117 int nTimeoutSec, int nTimeoutUSec ) :
118 rSrv( rSrv ), 118 rSrv( rSrv ),
119 iSocket( iSocket ), 119 iSocket( iSocket ),
120 iPort( iPort ), 120 iPort( iPort ),
121 nTimeoutSec( nTimeoutSec ), 121 nTimeoutSec( nTimeoutSec ),
122 nTimeoutUSec( nTimeoutUSec ) 122 nTimeoutUSec( nTimeoutUSec )
123{ 123{
124 FD_ZERO( &fdActive ); 124 FD_ZERO( &fdActive );
125 FD_SET( iSocket, &fdActive ); 125 FD_SET( iSocket, &fdActive );
126 126
127 pClient = new Client( 127 pClient = new Client(
128 new Bu::TcpSocket( iSocket ), 128 new Bu::TcpSocket( iSocket ),
129 new SrvClientLinkFactory( rSrv ) 129 new SrvClientLinkFactory( rSrv )
130 ); 130 );
131} 131}
132 132
133Bu::ItoServer::ItoClient::~ItoClient() 133Bu::ItoServer::ItoClient::~ItoClient()
@@ -136,67 +136,67 @@ Bu::ItoServer::ItoClient::~ItoClient()
136 136
137void Bu::ItoServer::ItoClient::run() 137void Bu::ItoServer::ItoClient::run()
138{ 138{
139 imProto.lock(); 139 imProto.lock();
140 rSrv.onNewConnection( pClient, iPort ); 140 rSrv.onNewConnection( pClient, iPort );
141 pClient->processOutput(); 141 pClient->processOutput();
142 imProto.unlock(); 142 imProto.unlock();
143 143
144 for(;;) 144 for(;;)
145 { 145 {
146 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; 146 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec };
147 147
148 fd_set fdRead = fdActive; 148 fd_set fdRead = fdActive;
149 fd_set fdWrite; 149 fd_set fdWrite;
150 fd_set fdException = fdActive; 150 fd_set fdException = fdActive;
151 151
152 FD_ZERO( &fdWrite ); 152 FD_ZERO( &fdWrite );
153 if( pClient->hasOutput() ) 153 if( pClient->hasOutput() )
154 FD_SET( iSocket, &fdWrite ); 154 FD_SET( iSocket, &fdWrite );
155 155
156 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, 156 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE,
157 &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) 157 &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 )
158 { 158 {
159 throw ExceptionBase("Error attempting to scan open connections."); 159 throw ExceptionBase("Error attempting to scan open connections.");
160 } 160 }
161 161
162 while( !qMsg.isEmpty() ) 162 while( !qMsg.isEmpty() )
163 { 163 {
164 imProto.lock(); 164 imProto.lock();
165 Bu::String *pMsg = qMsg.dequeue(); 165 Bu::String *pMsg = qMsg.dequeue();
166 pClient->onMessage( *pMsg ); 166 pClient->onMessage( *pMsg );
167 delete pMsg; 167 delete pMsg;
168 pClient->processOutput(); 168 pClient->processOutput();
169 imProto.unlock(); 169 imProto.unlock();
170 } 170 }
171 171
172 if( FD_ISSET( iSocket, &fdRead ) ) 172 if( FD_ISSET( iSocket, &fdRead ) )
173 { 173 {
174 imProto.lock(); 174 imProto.lock();
175 pClient->processInput(); 175 pClient->processInput();
176 imProto.unlock(); 176 imProto.unlock();
177 if( !pClient->isOpen() ) 177 if( !pClient->isOpen() )
178 { 178 {
179 imProto.lock(); 179 imProto.lock();
180 rSrv.onClosedConnection( pClient ); 180 rSrv.onClosedConnection( pClient );
181 imProto.unlock(); 181 imProto.unlock();
182 182
183 rSrv.clientCleanup( iSocket ); 183 rSrv.clientCleanup( iSocket );
184 184
185 return; 185 return;
186 } 186 }
187 } 187 }
188 188
189 if( FD_ISSET( iSocket, &fdWrite ) ) 189 if( FD_ISSET( iSocket, &fdWrite ) )
190 { 190 {
191 imProto.lock(); 191 imProto.lock();
192 pClient->processOutput(); 192 pClient->processOutput();
193 imProto.unlock(); 193 imProto.unlock();
194 } 194 }
195 } 195 }
196} 196}
197 197
198Bu::ItoServer::SrvClientLink::SrvClientLink( ItoClient *pClient ) : 198Bu::ItoServer::SrvClientLink::SrvClientLink( ItoClient *pClient ) :
199 pClient( pClient ) 199 pClient( pClient )
200{ 200{
201} 201}
202 202
@@ -206,22 +206,22 @@ Bu::ItoServer::SrvClientLink::~SrvClientLink()
206 206
207void Bu::ItoServer::SrvClientLink::sendMessage( const Bu::String &sMsg ) 207void Bu::ItoServer::SrvClientLink::sendMessage( const Bu::String &sMsg )
208{ 208{
209 if( !pClient->imProto.trylock() ) 209 if( !pClient->imProto.trylock() )
210 { 210 {
211 pClient->pClient->onMessage( sMsg ); 211 pClient->pClient->onMessage( sMsg );
212 pClient->pClient->processOutput(); 212 pClient->pClient->processOutput();
213 pClient->imProto.unlock(); 213 pClient->imProto.unlock();
214 } 214 }
215 else 215 else
216 { 216 {
217 Bu::String *pMsg = new Bu::String( sMsg ); 217 Bu::String *pMsg = new Bu::String( sMsg );
218 pClient->qMsg.enqueue( pMsg ); 218 pClient->qMsg.enqueue( pMsg );
219 } 219 }
220} 220}
221 221
222Bu::ItoServer::SrvClientLinkFactory::SrvClientLinkFactory( 222Bu::ItoServer::SrvClientLinkFactory::SrvClientLinkFactory(
223 Bu::ItoServer &rSrv ) : 223 Bu::ItoServer &rSrv ) :
224 rSrv( rSrv ) 224 rSrv( rSrv )
225{ 225{
226} 226}
227 227
@@ -230,12 +230,12 @@ Bu::ItoServer::SrvClientLinkFactory::~SrvClientLinkFactory()
230} 230}
231 231
232Bu::ClientLink *Bu::ItoServer::SrvClientLinkFactory::createLink( 232Bu::ClientLink *Bu::ItoServer::SrvClientLinkFactory::createLink(
233 Bu::Client *pClient ) 233 Bu::Client *pClient )
234{ 234{
235 rSrv.imClients.lock(); 235 rSrv.imClients.lock();
236 ItoClient *pCli = rSrv.hClients.get( *pClient->getSocket() ); 236 ItoClient *pCli = rSrv.hClients.get( *pClient->getSocket() );
237 rSrv.imClients.unlock(); 237 rSrv.imClients.unlock();
238 238
239 return new SrvClientLink( pCli ); 239 return new SrvClientLink( pCli );
240} 240}
241 241
diff --git a/src/unstable/itoserver.h b/src/unstable/itoserver.h
index 6a0df56..34f0fb1 100644
--- a/src/unstable/itoserver.h
+++ b/src/unstable/itoserver.h
@@ -11,7 +11,7 @@
11#include <stdint.h> 11#include <stdint.h>
12 12
13#ifndef WIN32 13#ifndef WIN32
14 #include <sys/select.h> 14 #include <sys/select.h>
15#endif 15#endif
16 16
17#include "bu/string.h" 17#include "bu/string.h"
@@ -26,122 +26,122 @@
26 26
27namespace Bu 27namespace Bu
28{ 28{
29 class TcpServerSocket; 29 class TcpServerSocket;
30 class TcpSocket; 30 class TcpSocket;
31 class Client; 31 class Client;
32 32
33 /** 33 /**
34 * Core of a network server. This class is distinct from a ServerSocket in 34 * Core of a network server. This class is distinct from a ServerSocket in
35 * that a ServerSocket is one listening socket, nothing more. Socket will 35 * that a ServerSocket is one listening socket, nothing more. Socket will
36 * manage a pool of both ServerSockets and connected Sockets along with 36 * manage a pool of both ServerSockets and connected Sockets along with
37 * their protocols and buffers. 37 * their protocols and buffers.
38 * 38 *
39 * To start serving on a new port, use the addPort functions. Each call to 39 * To start serving on a new port, use the addPort functions. Each call to
40 * addPort creates a new ServerSocket, starts it listening, and adds it to 40 * addPort creates a new ServerSocket, starts it listening, and adds it to
41 * the server pool. 41 * the server pool.
42 * 42 *
43 * All of the real work is done by scan, which will wait for up 43 * All of the real work is done by scan, which will wait for up
44 * to the timeout set by setTimeout before returning if there is no data 44 * to the timeout set by setTimeout before returning if there is no data
45 * pending. scan should probably be called in some sort of tight 45 * pending. scan should probably be called in some sort of tight
46 * loop, possibly in it's own thread, or in the main control loop. 46 * loop, possibly in it's own thread, or in the main control loop.
47 * 47 *
48 * In order to use a Server you must subclass it and implement the pure 48 * In order to use a Server you must subclass it and implement the pure
49 * virtual functions. These allow you to receive notification of events 49 * virtual functions. These allow you to receive notification of events
50 * happening within the server itself, and actually makes it useful. 50 * happening within the server itself, and actually makes it useful.
51 *@ingroup Threading Serving 51 *@ingroup Threading Serving
52 */ 52 */
53 class ItoServer : public Thread 53 class ItoServer : public Thread
54 { 54 {
55 friend class ItoClient; 55 friend class ItoClient;
56 friend class SrvClientLinkFactory; 56 friend class SrvClientLinkFactory;
57 public: 57 public:
58 ItoServer(); 58 ItoServer();
59 virtual ~ItoServer(); 59 virtual ~ItoServer();
60 60
61#ifdef WIN32 61#ifdef WIN32
62 typedef unsigned int socket_t; 62 typedef unsigned int socket_t;
63#else 63#else
64 typedef int socket_t; 64 typedef int socket_t;
65#endif 65#endif
66 66
67 void addPort( int nPort, int nPoolSize=40 ); 67 void addPort( int nPort, int nPoolSize=40 );
68 void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); 68 void addPort( const String &sAddr, int nPort, int nPoolSize=40 );
69 69
70 //void scan(); 70 //void scan();
71 void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); 71 void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 );
72 72
73 void addClient( socket_t nSocket, int nPort ); 73 void addClient( socket_t nSocket, int nPort );
74 74
75 virtual void onNewConnection( Client *pClient, int nPort )=0; 75 virtual void onNewConnection( Client *pClient, int nPort )=0;
76 virtual void onClosedConnection( Client *pClient )=0; 76 virtual void onClosedConnection( Client *pClient )=0;
77 77
78 protected: 78 protected:
79 virtual void run(); 79 virtual void run();
80 80
81 private: 81 private:
82 class SrvClientLink; 82 class SrvClientLink;
83 class ItoClient : public Thread 83 class ItoClient : public Thread
84 { 84 {
85 friend class Bu::ItoServer::SrvClientLink; 85 friend class Bu::ItoServer::SrvClientLink;
86 public: 86 public:
87 ItoClient( ItoServer &rSrv, socket_t nSocket, int nPort, 87 ItoClient( ItoServer &rSrv, socket_t nSocket, int nPort,
88 int nTimeoutSec, int nTimeoutUSec ); 88 int nTimeoutSec, int nTimeoutUSec );
89 virtual ~ItoClient(); 89 virtual ~ItoClient();
90 90
91 typedef SynchroQueue<Bu::String *> StringQueue; 91 typedef SynchroQueue<Bu::String *> StringQueue;
92 StringQueue qMsg; 92 StringQueue qMsg;
93 93
94 protected: 94 protected:
95 virtual void run(); 95 virtual void run();
96 96
97 private: 97 private:
98 ItoServer &rSrv; 98 ItoServer &rSrv;
99 Client *pClient; 99 Client *pClient;
100 fd_set fdActive; 100 fd_set fdActive;
101 socket_t iSocket; 101 socket_t iSocket;
102 int iPort; 102 int iPort;
103 int nTimeoutSec; 103 int nTimeoutSec;
104 int nTimeoutUSec; 104 int nTimeoutUSec;
105 Mutex imProto; 105 Mutex imProto;
106 }; 106 };
107 107
108 class SrvClientLink : public Bu::ClientLink 108 class SrvClientLink : public Bu::ClientLink
109 { 109 {
110 public: 110 public:
111 SrvClientLink( ItoClient *pClient ); 111 SrvClientLink( ItoClient *pClient );
112 virtual ~SrvClientLink(); 112 virtual ~SrvClientLink();
113 113
114 virtual void sendMessage( const Bu::String &sMsg ); 114 virtual void sendMessage( const Bu::String &sMsg );
115 115
116 private: 116 private:
117 ItoClient *pClient; 117 ItoClient *pClient;
118 }; 118 };
119 119
120 class SrvClientLinkFactory : public Bu::ClientLinkFactory 120 class SrvClientLinkFactory : public Bu::ClientLinkFactory
121 { 121 {
122 public: 122 public:
123 SrvClientLinkFactory( ItoServer &rSrv ); 123 SrvClientLinkFactory( ItoServer &rSrv );
124 virtual ~SrvClientLinkFactory(); 124 virtual ~SrvClientLinkFactory();
125 125
126 virtual Bu::ClientLink *createLink( Bu::Client *pClient ); 126 virtual Bu::ClientLink *createLink( Bu::Client *pClient );
127 127
128 private: 128 private:
129 ItoServer &rSrv; 129 ItoServer &rSrv;
130 }; 130 };
131 131
132 int nTimeoutSec; 132 int nTimeoutSec;
133 int nTimeoutUSec; 133 int nTimeoutUSec;
134 fd_set fdActive; 134 fd_set fdActive;
135 typedef Hash<socket_t,TcpServerSocket *> ServerHash; 135 typedef Hash<socket_t,TcpServerSocket *> ServerHash;
136 ServerHash hServers; 136 ServerHash hServers;
137 typedef Hash<socket_t,ItoClient *> ClientHash; 137 typedef Hash<socket_t,ItoClient *> ClientHash;
138 typedef SynchroQueue<ItoClient *> ClientQueue; 138 typedef SynchroQueue<ItoClient *> ClientQueue;
139 ClientHash hClients; 139 ClientHash hClients;
140 ClientQueue qClientCleanup; 140 ClientQueue qClientCleanup;
141 Mutex imClients; 141 Mutex imClients;
142 142
143 void clientCleanup( socket_t iSocket ); 143 void clientCleanup( socket_t iSocket );
144 }; 144 };
145} 145}
146 146
147#endif 147#endif
diff --git a/src/unstable/minimacro.cpp b/src/unstable/minimacro.cpp
index ff12267..72178ad 100644
--- a/src/unstable/minimacro.cpp
+++ b/src/unstable/minimacro.cpp
@@ -9,16 +9,16 @@
9 9
10Bu::MiniMacro::MiniMacro() 10Bu::MiniMacro::MiniMacro()
11{ 11{
12 hFuncs.insert("toupper", new FuncToUpper() ); 12 hFuncs.insert("toupper", new FuncToUpper() );
13 hFuncs.insert("tolower", new FuncToLower() ); 13 hFuncs.insert("tolower", new FuncToLower() );
14} 14}
15 15
16Bu::MiniMacro::MiniMacro( const StrHash &sVarSrc ) 16Bu::MiniMacro::MiniMacro( const StrHash &sVarSrc )
17{ 17{
18 for( StrHash::const_iterator i = sVarSrc.begin(); i != sVarSrc.end(); i++ ) 18 for( StrHash::const_iterator i = sVarSrc.begin(); i != sVarSrc.end(); i++ )
19 { 19 {
20 addVar( i.getKey(), i.getValue() ); 20 addVar( i.getKey(), i.getValue() );
21 } 21 }
22} 22}
23 23
24Bu::MiniMacro::~MiniMacro() 24Bu::MiniMacro::~MiniMacro()
@@ -27,161 +27,161 @@ Bu::MiniMacro::~MiniMacro()
27 27
28Bu::String Bu::MiniMacro::parse( const Bu::String &sIn ) 28Bu::String Bu::MiniMacro::parse( const Bu::String &sIn )
29{ 29{
30 bContinue = true; 30 bContinue = true;
31 Bu::String sOut; 31 Bu::String sOut;
32 for( sCur = sIn.getStr(); *sCur && bContinue; sCur++ ) 32 for( sCur = sIn.getStr(); *sCur && bContinue; sCur++ )
33 { 33 {
34 if( *sCur == '{' ) 34 if( *sCur == '{' )
35 { 35 {
36 switch( sCur[1] ) 36 switch( sCur[1] )
37 { 37 {
38 case '=': 38 case '=':
39 sCur += 2; 39 sCur += 2;
40 sOut += parseRepl(); 40 sOut += parseRepl();
41 break; 41 break;
42 42
43 case '?': 43 case '?':
44 sCur += 2; 44 sCur += 2;
45 sOut += parseCond(); 45 sOut += parseCond();
46 break; 46 break;
47 47
48 case ':': 48 case ':':
49 sCur += 2; 49 sCur += 2;
50 sOut += parseCmd(); 50 sOut += parseCmd();
51 break; 51 break;
52 52
53 default: 53 default:
54 sOut += *sCur; 54 sOut += *sCur;
55 continue; 55 continue;
56 } 56 }
57 } 57 }
58 else 58 else
59 { 59 {
60 sOut += *sCur; 60 sOut += *sCur;
61 } 61 }
62 } 62 }
63 63
64 iLastPos = (ptrdiff_t)sCur - (ptrdiff_t)sIn.getStr(); 64 iLastPos = (ptrdiff_t)sCur - (ptrdiff_t)sIn.getStr();
65 65
66 return sOut; 66 return sOut;
67} 67}
68 68
69Bu::String Bu::MiniMacro::parseRepl() 69Bu::String Bu::MiniMacro::parseRepl()
70{ 70{
71 Bu::String sOut; 71 Bu::String sOut;
72 bool bIsFirst = true; 72 bool bIsFirst = true;
73 for( const char *sNext = sCur;;) 73 for( const char *sNext = sCur;;)
74 { 74 {
75 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { } 75 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { }
76 if( *sNext == '\0' ) 76 if( *sNext == '\0' )
77 break; 77 break;
78 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur ); 78 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur );
79 if( bIsFirst ) 79 if( bIsFirst )
80 { 80 {
81 sOut = hVars[sName]; 81 sOut = hVars[sName];
82 bIsFirst = false; 82 bIsFirst = false;
83 //printf("Variable: \"%s\"\n", sName.getStr() ); 83 //printf("Variable: \"%s\"\n", sName.getStr() );
84 } 84 }
85 else 85 else
86 { 86 {
87 sOut = callFunc( sOut, sName ); 87 sOut = callFunc( sOut, sName );
88 //printf("Filter: \"%s\"\n", sName.getStr() ); 88 //printf("Filter: \"%s\"\n", sName.getStr() );
89 } 89 }
90 if( *sNext == '}' ) 90 if( *sNext == '}' )
91 { 91 {
92 sCur = sNext; 92 sCur = sNext;
93 break; 93 break;
94 } 94 }
95 else if( *sNext == ':' ) 95 else if( *sNext == ':' )
96 { 96 {
97 } 97 }
98 sNext++; 98 sNext++;
99 sCur = sNext; 99 sCur = sNext;
100 } 100 }
101 return sOut; 101 return sOut;
102} 102}
103 103
104Bu::String Bu::MiniMacro::parseCond() 104Bu::String Bu::MiniMacro::parseCond()
105{ 105{
106 Bu::String sOut; 106 Bu::String sOut;
107 //printf("%20s\n", sCur ); 107 //printf("%20s\n", sCur );
108 return sOut; 108 return sOut;
109} 109}
110 110
111Bu::String Bu::MiniMacro::parseCmd() 111Bu::String Bu::MiniMacro::parseCmd()
112{ 112{
113 Bu::String sOut; 113 Bu::String sOut;
114 const char *sNext = sCur; 114 const char *sNext = sCur;
115 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { } 115 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { }
116 if( *sNext != '\0' ) 116 if( *sNext != '\0' )
117 { 117 {
118 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur ); 118 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur );
119 if( sName == "end" ) 119 if( sName == "end" )
120 { 120 {
121 sCur = sNext; 121 sCur = sNext;
122 bContinue = false; 122 bContinue = false;
123 return sOut; 123 return sOut;
124 } 124 }
125 else 125 else
126 { 126 {
127 throw Bu::ExceptionBase("Unknown command '%s'.", 127 throw Bu::ExceptionBase("Unknown command '%s'.",
128 sName.getStr() 128 sName.getStr()
129 ); 129 );
130 } 130 }
131 } 131 }
132 else 132 else
133 { 133 {
134 //printf("Uh...?\n"); 134 //printf("Uh...?\n");
135 } 135 }
136 136
137 //printf("%20s\n", sCur ); 137 //printf("%20s\n", sCur );
138 return sOut; 138 return sOut;
139} 139}
140 140
141Bu::String Bu::MiniMacro::callFunc( 141Bu::String Bu::MiniMacro::callFunc(
142 const Bu::String &sIn, const Bu::String &sFunc ) 142 const Bu::String &sIn, const Bu::String &sFunc )
143{ 143{
144 int i = sFunc.findIdx('('); 144 int i = sFunc.findIdx('(');
145 if( i < 0 ) 145 if( i < 0 )
146 throw Bu::ExceptionBase("That doesn't look like a function call"); 146 throw Bu::ExceptionBase("That doesn't look like a function call");
147 Bu::String sName( sFunc.getStr(), i ); 147 Bu::String sName( sFunc.getStr(), i );
148 StrList lsParams; 148 StrList lsParams;
149 for( const char *s = sFunc.getStr()+i+1; *s && *s != ')'; s++ ) 149 for( const char *s = sFunc.getStr()+i+1; *s && *s != ')'; s++ )
150 { 150 {
151 for(; *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'; s++ ) { } 151 for(; *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'; s++ ) { }
152 const char *sNext; 152 const char *sNext;
153 for( sNext = s; *sNext && *sNext != ')' && *sNext != ','; sNext++ ) { } 153 for( sNext = s; *sNext && *sNext != ')' && *sNext != ','; sNext++ ) { }
154 Bu::String p( s, (ptrdiff_t)sNext-(ptrdiff_t)s ); 154 Bu::String p( s, (ptrdiff_t)sNext-(ptrdiff_t)s );
155 lsParams.append( p ); 155 lsParams.append( p );
156 sNext++; 156 sNext++;
157 s = sNext; 157 s = sNext;
158 } 158 }
159 return hFuncs.get( sName )->call( sIn, lsParams ); 159 return hFuncs.get( sName )->call( sIn, lsParams );
160} 160}
161 161
162void Bu::MiniMacro::addVar( 162void Bu::MiniMacro::addVar(
163 const Bu::String &sName, const Bu::String &sValue ) 163 const Bu::String &sName, const Bu::String &sValue )
164{ 164{
165 hVars.insert( sName, sValue ); 165 hVars.insert( sName, sValue );
166} 166}
167 167
168bool Bu::MiniMacro::hasVar( const Bu::String &sName ) 168bool Bu::MiniMacro::hasVar( const Bu::String &sName )
169{ 169{
170 return hVars.has( sName ); 170 return hVars.has( sName );
171} 171}
172 172
173const Bu::String &Bu::MiniMacro::getVar( const Bu::String &sName ) 173const Bu::String &Bu::MiniMacro::getVar( const Bu::String &sName )
174{ 174{
175 return hVars.get( sName ); 175 return hVars.get( sName );
176} 176}
177 177
178const Bu::StrHash &Bu::MiniMacro::getVars() 178const Bu::StrHash &Bu::MiniMacro::getVars()
179{ 179{
180 return hVars; 180 return hVars;
181} 181}
182 182
183int Bu::MiniMacro::getPosition() 183int Bu::MiniMacro::getPosition()
184{ 184{
185 return iLastPos; 185 return iLastPos;
186} 186}
187 187
diff --git a/src/unstable/minimacro.h b/src/unstable/minimacro.h
index dc38891..1c33ea4 100644
--- a/src/unstable/minimacro.h
+++ b/src/unstable/minimacro.h
@@ -13,118 +13,118 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 typedef Bu::Hash<Bu::String, Bu::String> StrHash; 16 typedef Bu::Hash<Bu::String, Bu::String> StrHash;
17 /** 17 /**
18 * A processor for Libbu++ brand Mini Macros. These are really simple, but 18 * A processor for Libbu++ brand Mini Macros. These are really simple, but
19 * still fairly flexible. It's mainly text replacement, but with a few 19 * still fairly flexible. It's mainly text replacement, but with a few
20 * extras like filter functions and conditional text segments. So far we 20 * extras like filter functions and conditional text segments. So far we
21 * don't support loops or anything, I'm not sure we ever will. 21 * don't support loops or anything, I'm not sure we ever will.
22 * 22 *
23 * Anatomy of a mini macro: 23 * Anatomy of a mini macro:
24 * - Every macro begins with a two character code, the first character is 24 * - Every macro begins with a two character code, the first character is
25 * always '{', the second character determines the operation to perform. 25 * always '{', the second character determines the operation to perform.
26 * - If the '{' is followed by a character that is not valid it is not 26 * - If the '{' is followed by a character that is not valid it is not
27 * considered for expansion and the characters are copied to the output. 27 * considered for expansion and the characters are copied to the output.
28 * - Every macro ends with a closing '}' 28 * - Every macro ends with a closing '}'
29 * - Macro types: 29 * - Macro types:
30 * - '=': variable replacement. The '=' is immediatley followed by the 30 * - '=': variable replacement. The '=' is immediatley followed by the
31 * name of the variable to replace, then any number of optional filter 31 * name of the variable to replace, then any number of optional filter
32 * segments. 32 * segments.
33 * - '?': conditional text. The '?' is immediately followed by the 33 * - '?': conditional text. The '?' is immediately followed by the
34 * variable to test. This works two ways, the variable can be alone, in 34 * variable to test. This works two ways, the variable can be alone, in
35 * which case it's existance is tested, or it can be followed by a "=" 35 * which case it's existance is tested, or it can be followed by a "="
36 * and a string to compare to. This is then followed by a text segment 36 * and a string to compare to. This is then followed by a text segment
37 * that will be used if the test is true, and an optional text segment 37 * that will be used if the test is true, and an optional text segment
38 * to be used if the test is false. 38 * to be used if the test is false.
39 * - ':': command. The ':' is immediately followed by a command string, 39 * - ':': command. The ':' is immediately followed by a command string,
40 * of which there's only one right now, but that's ok. These are not 40 * of which there's only one right now, but that's ok. These are not
41 * put into the output stream, but instead mark something for the 41 * put into the output stream, but instead mark something for the
42 * parser. Currently supported: 42 * parser. Currently supported:
43 * - {:end}: end of parsing, stop here, also make note of how many input 43 * - {:end}: end of parsing, stop here, also make note of how many input
44 * characters were used. 44 * characters were used.
45 * - Segments: 45 * - Segments:
46 * - Each segment is seperated by a colon. 46 * - Each segment is seperated by a colon.
47 * - Filter segments give the name of the filter, followed by 47 * - Filter segments give the name of the filter, followed by
48 * parenthesies. Parameters may be provided within the parenthesies. 48 * parenthesies. Parameters may be provided within the parenthesies.
49 * - Text segments should always be quoted, but may contain any characters 49 * - Text segments should always be quoted, but may contain any characters
50 * within the quotes, backslash is used as per C/ANSI/ISO standard. 50 * within the quotes, backslash is used as per C/ANSI/ISO standard.
51 * You can also quote any text using [' '] instead of quotes, which 51 * You can also quote any text using [' '] instead of quotes, which
52 * allows for nested strings. The [' token is only recognised within 52 * allows for nested strings. The [' token is only recognised within
53 * a macro. 53 * a macro.
54 * 54 *
55 *@verbatim 55 *@verbatim
56 {=name:tolower()} 56 {=name:tolower()}
57 {=name:ccsplit("_"):toupper()} 57 {=name:ccsplit("_"):toupper()}
58 {?name:"name exists and is {=name}"} 58 {?name:"name exists and is {=name}"}
59 {?name:"{=name}":"no name!"} 59 {?name:"{=name}":"no name!"}
60 {?name="bob":"You're named bob!":"Who are you? I only know bob..."} 60 {?name="bob":"You're named bob!":"Who are you? I only know bob..."}
61 @endverbatim 61 @endverbatim
62 */ 62 */
63 class MiniMacro 63 class MiniMacro
64 { 64 {
65 public: 65 public:
66 MiniMacro(); 66 MiniMacro();
67 MiniMacro( const StrHash &sVarSrc ); 67 MiniMacro( const StrHash &sVarSrc );
68 virtual ~MiniMacro(); 68 virtual ~MiniMacro();
69 69
70 Bu::String parse( const Bu::String &sIn ); 70 Bu::String parse( const Bu::String &sIn );
71 void addVar( const Bu::String &sName, const Bu::String &sValue ); 71 void addVar( const Bu::String &sName, const Bu::String &sValue );
72 bool hasVar( const Bu::String &sName ); 72 bool hasVar( const Bu::String &sName );
73 const Bu::String &getVar( const Bu::String &sName ); 73 const Bu::String &getVar( const Bu::String &sName );
74 const StrHash &getVars(); 74 const StrHash &getVars();
75 int getPosition(); 75 int getPosition();
76 76
77 private: 77 private:
78 const char *sCur; 78 const char *sCur;
79 Bu::String parseRepl(); 79 Bu::String parseRepl();
80 Bu::String parseCond(); 80 Bu::String parseCond();
81 Bu::String parseCmd(); 81 Bu::String parseCmd();
82 Bu::String callFunc( 82 Bu::String callFunc(
83 const Bu::String &sIn, const Bu::String &sFunc ); 83 const Bu::String &sIn, const Bu::String &sFunc );
84 84
85 StrHash hVars; 85 StrHash hVars;
86 bool bContinue; 86 bool bContinue;
87 int iLastPos; 87 int iLastPos;
88 88
89 public: 89 public:
90 typedef Bu::List<Bu::String> StrList; 90 typedef Bu::List<Bu::String> StrList;
91 class Func 91 class Func
92 { 92 {
93 public: 93 public:
94 Func(){} 94 Func(){}
95 virtual ~Func(){} 95 virtual ~Func(){}
96 virtual Bu::String call( 96 virtual Bu::String call(
97 const Bu::String &sIn, StrList &lsParam )=0; 97 const Bu::String &sIn, StrList &lsParam )=0;
98 }; 98 };
99 99
100 class FuncToUpper : public Func 100 class FuncToUpper : public Func
101 { 101 {
102 public: 102 public:
103 FuncToUpper(){} 103 FuncToUpper(){}
104 virtual ~FuncToUpper(){} 104 virtual ~FuncToUpper(){}
105 virtual Bu::String call( 105 virtual Bu::String call(
106 const Bu::String &sIn, StrList & ) 106 const Bu::String &sIn, StrList & )
107 { 107 {
108 return sIn.toUpper(); 108 return sIn.toUpper();
109 } 109 }
110 }; 110 };
111 111
112 class FuncToLower : public Func 112 class FuncToLower : public Func
113 { 113 {
114 public: 114 public:
115 FuncToLower(){} 115 FuncToLower(){}
116 virtual ~FuncToLower(){} 116 virtual ~FuncToLower(){}
117 virtual Bu::String call( 117 virtual Bu::String call(
118 const Bu::String &sIn, StrList & ) 118 const Bu::String &sIn, StrList & )
119 { 119 {
120 return sIn.toLower(); 120 return sIn.toLower();
121 } 121 }
122 }; 122 };
123 123
124 private: 124 private:
125 typedef Bu::Hash<Bu::String,class Func *> FuncHash; 125 typedef Bu::Hash<Bu::String,class Func *> FuncHash;
126 FuncHash hFuncs; 126 FuncHash hFuncs;
127 }; 127 };
128}; 128};
129 129
130#endif 130#endif
diff --git a/src/unstable/myriadfs.cpp b/src/unstable/myriadfs.cpp
index 6ed176d..3680c3f 100644
--- a/src/unstable/myriadfs.cpp
+++ b/src/unstable/myriadfs.cpp
@@ -19,686 +19,686 @@ using Bu::Fmt;
19 19
20namespace Bu { subExceptionDef( MyriadFsException ) } 20namespace Bu { subExceptionDef( MyriadFsException ) }
21 21
22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39") 22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39")
23 23
24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : 24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) :
25 rStore( rStore ), 25 rStore( rStore ),
26 mStore( rStore, iBlockSize ), 26 mStore( rStore, iBlockSize ),
27 iUser( 0 ), 27 iUser( 0 ),
28 iGroup( 0 ) 28 iGroup( 0 )
29{ 29{
30#ifndef WIN32 30#ifndef WIN32
31 iUser = getuid(); 31 iUser = getuid();
32 iGroup = getgid(); 32 iGroup = getgid();
33#endif 33#endif
34 34
35 if( mStore.hasStream( 1 ) ) 35 if( mStore.hasStream( 1 ) )
36 { 36 {
37 // Check to see if this is a MyriadFs stream. 37 // Check to see if this is a MyriadFs stream.
38 Bu::MyriadStream ms = mStore.openStream( 1 ); 38 Bu::MyriadStream ms = mStore.openStream( 1 );
39 char sMagic[4]; 39 char sMagic[4];
40 if( ms.read( sMagic, 4 ) < 4 ) 40 if( ms.read( sMagic, 4 ) < 4 )
41 throw MyriadFsException("The provided stream does not appear to be " 41 throw MyriadFsException("The provided stream does not appear to be "
42 "a MyriadFs stream."); 42 "a MyriadFs stream.");
43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) ) 43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) )
44 throw MyriadFsException("The provided stream does not appear to be " 44 throw MyriadFsException("The provided stream does not appear to be "
45 "a MyriadFs stream."); 45 "a MyriadFs stream.");
46 46
47 int8_t iVer; 47 int8_t iVer;
48 ms.read( &iVer, 1 ); 48 ms.read( &iVer, 1 );
49 49
50 int32_t iNumNodes; 50 int32_t iNumNodes;
51 ms.read( &iNumNodes, 4 ); 51 ms.read( &iNumNodes, 4 );
52 for( int32_t j = 0; j < iNumNodes; j++ ) 52 for( int32_t j = 0; j < iNumNodes; j++ )
53 { 53 {
54 int32_t iNode; 54 int32_t iNode;
55 int32_t iPos; 55 int32_t iPos;
56 ms.read( &iNode, 4 ); 56 ms.read( &iNode, 4 );
57 ms.read( &iPos, 4 ); 57 ms.read( &iPos, 4 );
58 hNodeIndex.insert( iNode, iPos ); 58 hNodeIndex.insert( iNode, iPos );
59 } 59 }
60 } 60 }
61 else 61 else
62 { 62 {
63 // Create initial header stream 63 // Create initial header stream
64 { 64 {
65 mStore.createStream( 1 ); 65 mStore.createStream( 1 );
66 Bu::MyriadStream ms = mStore.openStream( 1 ); 66 Bu::MyriadStream ms = mStore.openStream( 1 );
67 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 67 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
68 int8_t iVer = 1; 68 int8_t iVer = 1;
69 int32_t iTmp = 1; 69 int32_t iTmp = 1;
70 ms.write( &iVer, 1 ); 70 ms.write( &iVer, 1 );
71 ms.write( &iTmp, 4 ); // iNumNodes 71 ms.write( &iTmp, 4 ); // iNumNodes
72 iTmp = 0; 72 iTmp = 0;
73 ms.write( &iTmp, 4 ); // iInode 73 ms.write( &iTmp, 4 ); // iInode
74 ms.write( &iTmp, 4 ); // iPosition 74 ms.write( &iTmp, 4 ); // iPosition
75 hNodeIndex.insert( 0, 0 ); 75 hNodeIndex.insert( 0, 0 );
76 } 76 }
77 77
78 // Create initial inode stream, with one root node. 78 // Create initial inode stream, with one root node.
79 { 79 {
80 mStore.createStream( 2 ); 80 mStore.createStream( 2 );
81 Bu::MyriadStream ms = mStore.openStream( 2 ); 81 Bu::MyriadStream ms = mStore.openStream( 2 );
82 RawStat rs; 82 RawStat rs;
83 rs.iNode = 0; 83 rs.iNode = 0;
84 rs.iUser = iUser; 84 rs.iUser = iUser;
85 rs.iGroup = iGroup; 85 rs.iGroup = iGroup;
86 rs.uPerms = 0755|typeDir; 86 rs.uPerms = 0755|typeDir;
87 rs.iLinks = 1; 87 rs.iLinks = 1;
88 rs.uStreamIndex = 3; 88 rs.uStreamIndex = 3;
89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL); 89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL);
90 ms.write( &rs, sizeof(RawStat) ); 90 ms.write( &rs, sizeof(RawStat) );
91 } 91 }
92 92
93 // Create inode 0's storage stream. 93 // Create inode 0's storage stream.
94 { 94 {
95 mStore.createStream( 3 ); 95 mStore.createStream( 3 );
96 Bu::MyriadStream ms = mStore.openStream( 3 ); 96 Bu::MyriadStream ms = mStore.openStream( 3 );
97 int32_t iTmp32 = 0; 97 int32_t iTmp32 = 0;
98 ms.write( &iTmp32, 4 ); // iChildCount 98 ms.write( &iTmp32, 4 ); // iChildCount
99 } 99 }
100 } 100 }
101} 101}
102 102
103Bu::MyriadFs::~MyriadFs() 103Bu::MyriadFs::~MyriadFs()
104{ 104{
105 writeHeader(); 105 writeHeader();
106} 106}
107 107
108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) 108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf )
109{ 109{
110 int32_t iParent; 110 int32_t iParent;
111 int32_t iNode = lookupInode( sPath, iParent ); 111 int32_t iNode = lookupInode( sPath, iParent );
112 Bu::MyriadStream is = mStore.openStream( 2 ); 112 Bu::MyriadStream is = mStore.openStream( 2 );
113 stat( iNode, rBuf, is ); 113 stat( iNode, rBuf, is );
114} 114}
115 115
116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/, 116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/,
117 uint16_t uPerms ) 117 uint16_t uPerms )
118{ 118{
119 int32_t iParent = -1; 119 int32_t iParent = -1;
120 int32_t iNode; 120 int32_t iNode;
121 try 121 try
122 { 122 {
123 iNode = lookupInode( sPath, iParent ); 123 iNode = lookupInode( sPath, iParent );
124 sio << "File found." << sio.nl; 124 sio << "File found." << sio.nl;
125 // The file was found 125 // The file was found
126 return openByInode( iNode ); 126 return openByInode( iNode );
127 } 127 }
128 catch( Bu::MyriadFsException &e ) 128 catch( Bu::MyriadFsException &e )
129 { 129 {
130 if( iParent < 0 ) 130 if( iParent < 0 )
131 throw; 131 throw;
132 132
133 // This means that an intermediate path component couldn't be found 133 // This means that an intermediate path component couldn't be found
134 if( e.getErrorCode() == 1 ) 134 if( e.getErrorCode() == 1 )
135 throw; 135 throw;
136 136
137 // The file wasn't found, but the path leading up to it was. 137 // The file wasn't found, but the path leading up to it was.
138 // first, figure out the final path element... 138 // first, figure out the final path element...
139 Bu::String sName = filePart( sPath ); 139 Bu::String sName = filePart( sPath );
140 sio << "End filename: " << sName << sio.nl; 140 sio << "End filename: " << sName << sio.nl;
141 sio << "Parent inode: " << iParent << sio.nl; 141 sio << "Parent inode: " << iParent << sio.nl;
142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 ); 142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 );
143 sio << "New iNode: " << iNode << sio.nl; 143 sio << "New iNode: " << iNode << sio.nl;
144 return openByInode( iNode ); 144 return openByInode( iNode );
145 } 145 }
146} 146}
147 147
148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms ) 148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms )
149{ 149{
150 create( sPath, iPerms, 0 ); 150 create( sPath, iPerms, 0 );
151} 151}
152 152
153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
154 uint16_t iDevHi, uint16_t iDevLo ) 154 uint16_t iDevHi, uint16_t iDevLo )
155{ 155{
156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo ); 156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo );
157} 157}
158 158
159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
160 uint32_t uSpecial ) 160 uint32_t uSpecial )
161{ 161{
162 int32_t iParent = -1; 162 int32_t iParent = -1;
163 int32_t iNode; 163 int32_t iNode;
164 try 164 try
165 { 165 {
166 iNode = lookupInode( sPath, iParent ); 166 iNode = lookupInode( sPath, iParent );
167 sio << "File found." << sio.nl; 167 sio << "File found." << sio.nl;
168 // The file was found 168 // The file was found
169 throw Bu::MyriadFsException("Path already exists."); 169 throw Bu::MyriadFsException("Path already exists.");
170 } 170 }
171 catch( Bu::MyriadFsException &e ) 171 catch( Bu::MyriadFsException &e )
172 { 172 {
173 if( iParent < 0 ) 173 if( iParent < 0 )
174 throw; 174 throw;
175 175
176 // This means that an intermediate path component couldn't be found 176 // This means that an intermediate path component couldn't be found
177 if( e.getErrorCode() == 1 ) 177 if( e.getErrorCode() == 1 )
178 throw; 178 throw;
179 179
180 // The file wasn't found, but the path leading up to it was. 180 // The file wasn't found, but the path leading up to it was.
181 // first, figure out the final path element... 181 // first, figure out the final path element...
182 Bu::String sName = filePart( sPath ); 182 Bu::String sName = filePart( sPath );
183 sio << "End filename: " << sName << sio.nl; 183 sio << "End filename: " << sName << sio.nl;
184 sio << "Parent inode: " << iParent << sio.nl; 184 sio << "Parent inode: " << iParent << sio.nl;
185 iNode = create( iParent, sName, iPerms, uSpecial ); 185 iNode = create( iParent, sName, iPerms, uSpecial );
186 sio << "New iNode: " << iNode << sio.nl; 186 sio << "New iNode: " << iNode << sio.nl;
187 } 187 }
188} 188}
189 189
190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) 190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms )
191{ 191{
192 create( sPath, (iPerms&permMask)|typeDir, 0 ); 192 create( sPath, (iPerms&permMask)|typeDir, 0 );
193} 193}
194 194
195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget, 195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget,
196 const Bu::String &sPath ) 196 const Bu::String &sPath )
197{ 197{
198 int32_t iParent = -1; 198 int32_t iParent = -1;
199 int32_t iNode; 199 int32_t iNode;
200 try 200 try
201 { 201 {
202 iNode = lookupInode( sPath, iParent ); 202 iNode = lookupInode( sPath, iParent );
203 throw Bu::MyriadFsException("Path already exists."); 203 throw Bu::MyriadFsException("Path already exists.");
204 } 204 }
205 catch( Bu::MyriadFsException &e ) 205 catch( Bu::MyriadFsException &e )
206 { 206 {
207 if( iParent < 0 ) 207 if( iParent < 0 )
208 throw; 208 throw;
209 209
210 // This means that an intermediate path component couldn't be found 210 // This means that an intermediate path component couldn't be found
211 if( e.getErrorCode() == 1 ) 211 if( e.getErrorCode() == 1 )
212 throw; 212 throw;
213 213
214 // The file wasn't found, but the path leading up to it was. 214 // The file wasn't found, but the path leading up to it was.
215 // first, figure out the final path element... 215 // first, figure out the final path element...
216 Bu::String sName = filePart( sPath ); 216 Bu::String sName = filePart( sPath );
217 sio << "End filename: " << sName << sio.nl; 217 sio << "End filename: " << sName << sio.nl;
218 sio << "Parent inode: " << iParent << sio.nl; 218 sio << "Parent inode: " << iParent << sio.nl;
219 iNode = create( iParent, sName, 0777|typeSymLink, 0 ); 219 iNode = create( iParent, sName, 0777|typeSymLink, 0 );
220 sio << "New iNode: " << iNode << sio.nl; 220 sio << "New iNode: " << iNode << sio.nl;
221 MyriadStream ms = openByInode( iNode ); 221 MyriadStream ms = openByInode( iNode );
222 ms.write( sTarget ); 222 ms.write( sTarget );
223 } 223 }
224} 224}
225 225
226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget, 226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget,
227 const Bu::String &sPath ) 227 const Bu::String &sPath )
228{ 228{
229 int32_t iParent = -1; 229 int32_t iParent = -1;
230 int32_t iNode; 230 int32_t iNode;
231 231
232 iNode = lookupInode( sTarget, iParent ); 232 iNode = lookupInode( sTarget, iParent );
233 233
234 try 234 try
235 { 235 {
236 lookupInode( sPath, iParent ); 236 lookupInode( sPath, iParent );
237 throw Bu::MyriadFsException("Path already exists."); 237 throw Bu::MyriadFsException("Path already exists.");
238 } 238 }
239 catch( Bu::MyriadFsException &e ) 239 catch( Bu::MyriadFsException &e )
240 { 240 {
241 if( iParent < 0 ) 241 if( iParent < 0 )
242 throw; 242 throw;
243 243
244 // This means that an intermediate path component couldn't be found 244 // This means that an intermediate path component couldn't be found
245 if( e.getErrorCode() == 1 ) 245 if( e.getErrorCode() == 1 )
246 throw; 246 throw;
247 247
248 // The file wasn't found, but the path leading up to it was. 248 // The file wasn't found, but the path leading up to it was.
249 // first, figure out the final path element... 249 // first, figure out the final path element...
250 Bu::String sName = filePart( sPath ); 250 Bu::String sName = filePart( sPath );
251 sio << "End filename: " << sName << sio.nl; 251 sio << "End filename: " << sName << sio.nl;
252 sio << "Parent inode: " << iParent << sio.nl; 252 sio << "Parent inode: " << iParent << sio.nl;
253 addToDir( iParent, iNode, sName ); 253 addToDir( iParent, iNode, sName );
254 MyriadStream is = mStore.openStream( 2 ); 254 MyriadStream is = mStore.openStream( 2 );
255 RawStat rs; 255 RawStat rs;
256 readInode( iNode, rs, is ); 256 readInode( iNode, rs, is );
257 rs.iLinks++; 257 rs.iLinks++;
258 writeInode( rs, is ); 258 writeInode( rs, is );
259 } 259 }
260} 260}
261 261
262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath ) 262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath )
263{ 263{
264 int32_t iParent = -1; 264 int32_t iParent = -1;
265 int32_t iNode; 265 int32_t iNode;
266 iNode = lookupInode( sPath, iParent ); 266 iNode = lookupInode( sPath, iParent );
267 MyriadStream ms = openByInode( iNode ); 267 MyriadStream ms = openByInode( iNode );
268 Bu::String sRet; 268 Bu::String sRet;
269 sRet.setSize( ms.getSize() ); 269 sRet.setSize( ms.getSize() );
270 ms.read( sRet.getStr(), ms.getSize() ); 270 ms.read( sRet.getStr(), ms.getSize() );
271 return sRet; 271 return sRet;
272} 272}
273 273
274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) 274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath )
275{ 275{
276 int32_t iParent = -1; 276 int32_t iParent = -1;
277 int32_t iNode = lookupInode( sPath, iParent ); 277 int32_t iNode = lookupInode( sPath, iParent );
278 return readDir( iNode ); 278 return readDir( iNode );
279} 279}
280 280
281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime, 281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime,
282 int64_t iMTime ) 282 int64_t iMTime )
283{ 283{
284 int32_t iParent = -1; 284 int32_t iParent = -1;
285 int32_t iNode; 285 int32_t iNode;
286 286
287 iNode = lookupInode( sPath, iParent ); 287 iNode = lookupInode( sPath, iParent );
288 288
289 setTimes( iNode, iATime, iMTime ); 289 setTimes( iNode, iATime, iMTime );
290} 290}
291 291
292void Bu::MyriadFs::unlink( const Bu::String &sPath ) 292void Bu::MyriadFs::unlink( const Bu::String &sPath )
293{ 293{
294 int32_t iParent = -1; 294 int32_t iParent = -1;
295// int32_t iNode; 295// int32_t iNode;
296 296
297 /*iNode =*/ lookupInode( sPath, iParent ); 297 /*iNode =*/ lookupInode( sPath, iParent );
298 298
299 Dir lDir = readDir( iParent ); 299 Dir lDir = readDir( iParent );
300 300
301 Bu::String sName = filePart( sPath ); 301 Bu::String sName = filePart( sPath );
302 302
303 for( Dir::iterator i = lDir.begin(); i; i++ ) 303 for( Dir::iterator i = lDir.begin(); i; i++ )
304 { 304 {
305 if( sName == (*i).sName ) 305 if( sName == (*i).sName )
306 { 306 {
307 RawStat rs; 307 RawStat rs;
308 readInode( (*i).iNode, rs ); 308 readInode( (*i).iNode, rs );
309 if( (rs.uPerms&typeMask) == typeDir ) 309 if( (rs.uPerms&typeMask) == typeDir )
310 { 310 {
311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex ); 311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex );
312 int32_t iCount; 312 int32_t iCount;
313 msDir.read( &iCount, 4 ); 313 msDir.read( &iCount, 4 );
314 if( iCount > 0 ) 314 if( iCount > 0 )
315 { 315 {
316 throw Bu::MyriadFsException("Directory not empty."); 316 throw Bu::MyriadFsException("Directory not empty.");
317 } 317 }
318 } 318 }
319 if( --rs.iLinks == 0 ) 319 if( --rs.iLinks == 0 )
320 { 320 {
321 destroyNode( (*i).iNode ); 321 destroyNode( (*i).iNode );
322 } 322 }
323 else 323 else
324 { 324 {
325 writeInode( rs ); 325 writeInode( rs );
326 } 326 }
327 lDir.erase( i ); 327 lDir.erase( i );
328 break; 328 break;
329 } 329 }
330 } 330 }
331 331
332 Bu::MyriadStream ms = openByInode( iParent ); 332 Bu::MyriadStream ms = openByInode( iParent );
333 int32_t iNumChildren = lDir.getSize(); 333 int32_t iNumChildren = lDir.getSize();
334 ms.write( &iNumChildren, 4 ); 334 ms.write( &iNumChildren, 4 );
335 for( Dir::iterator i = lDir.begin(); i; i++ ) 335 for( Dir::iterator i = lDir.begin(); i; i++ )
336 { 336 {
337 ms.write( &(*i).iNode, 4 ); 337 ms.write( &(*i).iNode, 4 );
338 uint8_t iSize = (*i).sName.getSize(); 338 uint8_t iSize = (*i).sName.getSize();
339 ms.write( &iSize, 1 ); 339 ms.write( &iSize, 1 );
340 ms.write( (*i).sName.getStr(), iSize ); 340 ms.write( (*i).sName.getStr(), iSize );
341 } 341 }
342 ms.setSize( ms.tell() ); 342 ms.setSize( ms.tell() );
343} 343}
344 344
345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize ) 345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize )
346{ 346{
347 int32_t iParent = -1; 347 int32_t iParent = -1;
348 int32_t iNode; 348 int32_t iNode;
349 iNode = lookupInode( sPath, iParent ); 349 iNode = lookupInode( sPath, iParent );
350 MyriadStream ms = openByInode( iNode ); 350 MyriadStream ms = openByInode( iNode );
351 ms.setSize( iSize ); 351 ms.setSize( iSize );
352} 352}
353 353
354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo ) 354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo )
355{ 355{
356 mkHardLink( sFrom, sTo ); 356 mkHardLink( sFrom, sTo );
357 unlink( sFrom ); 357 unlink( sFrom );
358} 358}
359 359
360dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) 360dev_t Bu::MyriadFs::devToSys( uint32_t uDev )
361{ 361{
362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); 362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF));
363} 363}
364 364
365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev ) 365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev )
366{ 366{
367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF); 367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF);
368} 368}
369 369
370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) 370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent )
371{ 371{
372 if( sPath == "/" ) 372 if( sPath == "/" )
373 { 373 {
374 return 0; 374 return 0;
375 } 375 }
376 if( sPath[0] == '/' ) 376 if( sPath[0] == '/' )
377 { 377 {
378 // Absolute lookup 378 // Absolute lookup
379 return lookupInode( sPath.begin()+1, 0, iParent ); 379 return lookupInode( sPath.begin()+1, 0, iParent );
380 } 380 }
381 else 381 else
382 { 382 {
383 // Relative lookup 383 // Relative lookup
384 throw Bu::ExceptionBase( 384 throw Bu::ExceptionBase(
385 "Relative lookups in MyriadFs are not working yet."); 385 "Relative lookups in MyriadFs are not working yet.");
386 } 386 }
387} 387}
388 388
389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, 389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart,
390 int32_t iNode, int32_t &iParent ) 390 int32_t iNode, int32_t &iParent )
391{ 391{
392 iParent = iNode; 392 iParent = iNode;
393 393
394 Bu::String::const_iterator iEnd = iStart.find('/'); 394 Bu::String::const_iterator iEnd = iStart.find('/');
395 Bu::String sTok( iStart, iEnd ); 395 Bu::String sTok( iStart, iEnd );
396 396
397// sio << "Direcotry component: " << sTok << sio.nl; 397// sio << "Direcotry component: " << sTok << sio.nl;
398 398
399 Dir lDir = readDir( iNode ); 399 Dir lDir = readDir( iNode );
400 400
401 for( Dir::iterator i = lDir.begin(); i; i++ ) 401 for( Dir::iterator i = lDir.begin(); i; i++ )
402 { 402 {
403 if( (*i).sName == sTok ) 403 if( (*i).sName == sTok )
404 { 404 {
405 // We found an item 405 // We found an item
406 if( !iEnd ) 406 if( !iEnd )
407 { 407 {
408 // It's the last one in the requested path, return it 408 // It's the last one in the requested path, return it
409 return (*i).iNode; 409 return (*i).iNode;
410 } 410 }
411 else 411 else
412 { 412 {
413 // Not the last one in our path, double check it's a dir 413 // Not the last one in our path, double check it's a dir
414 if( ((*i).uPerms&typeMask) == typeDir ) 414 if( ((*i).uPerms&typeMask) == typeDir )
415 { 415 {
416 return lookupInode( iEnd+1, (*i).iNode, iParent ); 416 return lookupInode( iEnd+1, (*i).iNode, iParent );
417 } 417 }
418 else 418 else
419 { 419 {
420 iParent = -1; 420 iParent = -1;
421 throw Bu::MyriadFsException( 421 throw Bu::MyriadFsException(
422 "Element '%s' in given path is not a directory.", 422 "Element '%s' in given path is not a directory.",
423 sTok.getStr() ); 423 sTok.getStr() );
424 } 424 }
425 } 425 }
426 } 426 }
427 } 427 }
428 428
429 if( iEnd ) 429 if( iEnd )
430 throw Bu::MyriadFsException( 1, "Path not found"); 430 throw Bu::MyriadFsException( 1, "Path not found");
431 else 431 else
432 throw Bu::MyriadFsException( 2, "Path not found"); 432 throw Bu::MyriadFsException( 2, "Path not found");
433} 433}
434 434
435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ) 435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs )
436{ 436{
437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) ); 437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) );
438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
439 throw Bu::MyriadFsException("Filesystem corruption detected."); 439 throw Bu::MyriadFsException("Filesystem corruption detected.");
440 if( rs.iNode != iNode ) 440 if( rs.iNode != iNode )
441 throw Bu::MyriadFsException("Filesystem corruption detected."); 441 throw Bu::MyriadFsException("Filesystem corruption detected.");
442} 442}
443 443
444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs ) 444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs )
445{ 445{
446 MyriadStream ms = mStore.openStream( 2 ); 446 MyriadStream ms = mStore.openStream( 2 );
447 readInode( iNode, rs, ms ); 447 readInode( iNode, rs, ms );
448} 448}
449 449
450void Bu::MyriadFs::writeInode( const RawStat &rs, 450void Bu::MyriadFs::writeInode( const RawStat &rs,
451 MyriadStream &rOs ) 451 MyriadStream &rOs )
452{ 452{
453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) ); 453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) );
454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) ); 454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) );
455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
456 throw Bu::MyriadFsException("Error writing inode to header stream."); 456 throw Bu::MyriadFsException("Error writing inode to header stream.");
457} 457}
458 458
459void Bu::MyriadFs::writeInode( const RawStat &rs ) 459void Bu::MyriadFs::writeInode( const RawStat &rs )
460{ 460{
461 MyriadStream ms = mStore.openStream( 2 ); 461 MyriadStream ms = mStore.openStream( 2 );
462 writeInode( rs, ms ); 462 writeInode( rs, ms );
463} 463}
464 464
465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) 465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode )
466{ 466{
467 Bu::MyriadStream ms = openByInode( iNode ); 467 Bu::MyriadStream ms = openByInode( iNode );
468 int32_t iNumChildren = 0; 468 int32_t iNumChildren = 0;
469 ms.read( &iNumChildren, 4 ); 469 ms.read( &iNumChildren, 4 );
470 470
471 Bu::MyriadStream is = mStore.openStream( 2 ); 471 Bu::MyriadStream is = mStore.openStream( 2 );
472 Dir lDir; 472 Dir lDir;
473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl; 473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl;
474 for( int32_t j = 0; j < iNumChildren; j++ ) 474 for( int32_t j = 0; j < iNumChildren; j++ )
475 { 475 {
476 int32_t iChildNode; 476 int32_t iChildNode;
477 ms.read( &iChildNode, 4 ); 477 ms.read( &iChildNode, 4 );
478 Stat s; 478 Stat s;
479 stat( iChildNode, s, is ); 479 stat( iChildNode, s, is );
480 uint8_t uLen; 480 uint8_t uLen;
481 ms.read( &uLen, 1 ); 481 ms.read( &uLen, 1 );
482 s.sName.setSize( uLen ); 482 s.sName.setSize( uLen );
483 ms.read( s.sName.getStr(), uLen ); 483 ms.read( s.sName.getStr(), uLen );
484 lDir.append( s ); 484 lDir.append( s );
485 485
486// sio << " " << s.sName << sio.nl; 486// sio << " " << s.sName << sio.nl;
487 } 487 }
488 488
489 return lDir; 489 return lDir;
490} 490}
491 491
492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) 492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode )
493{ 493{
494 RawStat rs; 494 RawStat rs;
495 readInode( iNode, rs ); 495 readInode( iNode, rs );
496 switch( (rs.uPerms&typeMask) ) 496 switch( (rs.uPerms&typeMask) )
497 { 497 {
498 case typeDir: 498 case typeDir:
499 case typeSymLink: 499 case typeSymLink:
500 case typeRegFile: 500 case typeRegFile:
501 return mStore.openStream( rs.uStreamIndex ); 501 return mStore.openStream( rs.uStreamIndex );
502 502
503 default: 503 default:
504 throw Bu::MyriadFsException( 504 throw Bu::MyriadFsException(
505 "inode incorrect type for low-level openByInode."); 505 "inode incorrect type for low-level openByInode.");
506 } 506 }
507} 507}
508 508
509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode, 509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode,
510 const Bu::String &sName ) 510 const Bu::String &sName )
511{ 511{
512 if( sName.getSize() > 255 ) 512 if( sName.getSize() > 255 )
513 { 513 {
514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes."); 514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes.");
515 } 515 }
516 Bu::MyriadStream ms = openByInode( iDir ); 516 Bu::MyriadStream ms = openByInode( iDir );
517 int32_t iNumChildren = 0; 517 int32_t iNumChildren = 0;
518 ms.read( &iNumChildren, 4 ); 518 ms.read( &iNumChildren, 4 );
519 iNumChildren++; 519 iNumChildren++;
520 ms.setPos( 0 ); 520 ms.setPos( 0 );
521 ms.write( &iNumChildren, 4 ); 521 ms.write( &iNumChildren, 4 );
522 ms.setPosEnd( 0 ); 522 ms.setPosEnd( 0 );
523 ms.write( &iNode, 4 ); 523 ms.write( &iNode, 4 );
524 uint8_t uLen = sName.getSize(); 524 uint8_t uLen = sName.getSize();
525 ms.write( &uLen, 1 ); 525 ms.write( &uLen, 1 );
526 ms.write( sName.getStr(), uLen ); 526 ms.write( sName.getStr(), uLen );
527} 527}
528 528
529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, 529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName,
530 uint16_t uPerms, uint32_t uSpecial ) 530 uint16_t uPerms, uint32_t uSpecial )
531{ 531{
532 int32_t iNode = allocInode( uPerms, uSpecial ); 532 int32_t iNode = allocInode( uPerms, uSpecial );
533 addToDir( iParent, iNode, sName ); 533 addToDir( iParent, iNode, sName );
534 return iNode; 534 return iNode;
535} 535}
536 536
537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) 537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
538{ 538{
539 int32_t iNode = 0; 539 int32_t iNode = 0;
540 for(; iNode < 0xfffffff; iNode++ ) 540 for(; iNode < 0xfffffff; iNode++ )
541 { 541 {
542 if( !hNodeIndex.has( iNode ) ) 542 if( !hNodeIndex.has( iNode ) )
543 { 543 {
544 hNodeIndex.insert( iNode, hNodeIndex.getSize() ); 544 hNodeIndex.insert( iNode, hNodeIndex.getSize() );
545 RawStat rs; 545 RawStat rs;
546 rs.iNode = iNode; 546 rs.iNode = iNode;
547 rs.iUser = iUser; 547 rs.iUser = iUser;
548 rs.iGroup = iGroup; 548 rs.iGroup = iGroup;
549 rs.uPerms = uPerms; 549 rs.uPerms = uPerms;
550 rs.iLinks = 1; 550 rs.iLinks = 1;
551 switch( (uPerms&typeMask) ) 551 switch( (uPerms&typeMask) )
552 { 552 {
553 case typeRegFile: 553 case typeRegFile:
554 case typeSymLink: 554 case typeSymLink:
555 rs.uStreamIndex = mStore.createStream(); 555 rs.uStreamIndex = mStore.createStream();
556 break; 556 break;
557 557
558 case typeDir: 558 case typeDir:
559 rs.uStreamIndex = mStore.createStream(); 559 rs.uStreamIndex = mStore.createStream();
560 sio << "Creating directory node, storage: " 560 sio << "Creating directory node, storage: "
561 << rs.uStreamIndex << sio.nl; 561 << rs.uStreamIndex << sio.nl;
562 { 562 {
563 Bu::MyriadStream msDir = mStore.openStream( 563 Bu::MyriadStream msDir = mStore.openStream(
564 rs.uStreamIndex 564 rs.uStreamIndex
565 ); 565 );
566 uint32_t uSize = 0; 566 uint32_t uSize = 0;
567 msDir.write( &uSize, 4 ); 567 msDir.write( &uSize, 4 );
568 } 568 }
569 break; 569 break;
570 570
571 case typeChrDev: 571 case typeChrDev:
572 case typeBlkDev: 572 case typeBlkDev:
573 rs.uStreamIndex = uSpecial; 573 rs.uStreamIndex = uSpecial;
574 break; 574 break;
575 575
576 default: 576 default:
577 rs.uStreamIndex = 0; 577 rs.uStreamIndex = 0;
578 break; 578 break;
579 } 579 }
580 rs.iATime = time(NULL); 580 rs.iATime = time(NULL);
581 rs.iMTime = time(NULL); 581 rs.iMTime = time(NULL);
582 rs.iCTime = time(NULL); 582 rs.iCTime = time(NULL);
583 writeInode( rs ); 583 writeInode( rs );
584 584
585 return iNode; 585 return iNode;
586 } 586 }
587 } 587 }
588 588
589 throw Bu::MyriadFsException( 589 throw Bu::MyriadFsException(
590 "No inode could be allocated. You've run out!"); 590 "No inode could be allocated. You've run out!");
591} 591}
592 592
593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) 593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs )
594{ 594{
595 RawStat rs; 595 RawStat rs;
596 readInode( iNode, rs, rIs ); 596 readInode( iNode, rs, rIs );
597 rBuf.iNode = iNode; 597 rBuf.iNode = iNode;
598 rBuf.iUser = rs.iUser; 598 rBuf.iUser = rs.iUser;
599 rBuf.iGroup = rs.iGroup; 599 rBuf.iGroup = rs.iGroup;
600 rBuf.uPerms = rs.uPerms; 600 rBuf.uPerms = rs.uPerms;
601 rBuf.iLinks = rs.iLinks; 601 rBuf.iLinks = rs.iLinks;
602 rBuf.iATime = rs.iATime; 602 rBuf.iATime = rs.iATime;
603 rBuf.iMTime = rs.iMTime; 603 rBuf.iMTime = rs.iMTime;
604 rBuf.iCTime = rs.iCTime; 604 rBuf.iCTime = rs.iCTime;
605 rBuf.uDev = 0; 605 rBuf.uDev = 0;
606 rBuf.iSize = 0; 606 rBuf.iSize = 0;
607 switch( (rBuf.uPerms&typeMask) ) 607 switch( (rBuf.uPerms&typeMask) )
608 { 608 {
609 case typeRegFile: 609 case typeRegFile:
610 case typeSymLink: 610 case typeSymLink:
611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex ); 611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex );
612 break; 612 break;
613 613
614 case typeChrDev: 614 case typeChrDev:
615 case typeBlkDev: 615 case typeBlkDev:
616 rBuf.uDev = rs.uStreamIndex; 616 rBuf.uDev = rs.uStreamIndex;
617 break; 617 break;
618 618
619 default: 619 default:
620 rBuf.iSize = 0; 620 rBuf.iSize = 0;
621 break; 621 break;
622 } 622 }
623} 623}
624 624
625void Bu::MyriadFs::writeHeader() 625void Bu::MyriadFs::writeHeader()
626{ 626{
627 Bu::MyriadStream ms = mStore.openStream( 1 ); 627 Bu::MyriadStream ms = mStore.openStream( 1 );
628 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 628 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
629 int8_t iVer = 1; 629 int8_t iVer = 1;
630 int32_t iNumNodes = hNodeIndex.getSize(); 630 int32_t iNumNodes = hNodeIndex.getSize();
631 ms.write( &iVer, 1 ); 631 ms.write( &iVer, 1 );
632 ms.write( &iNumNodes, 4 ); // iNumNodes 632 ms.write( &iNumNodes, 4 ); // iNumNodes
633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ ) 633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ )
634 { 634 {
635 int32_t iNode = i.getKey(); 635 int32_t iNode = i.getKey();
636 int32_t iPosition = i.getValue(); 636 int32_t iPosition = i.getValue();
637 ms.write( &iNode, 4 ); 637 ms.write( &iNode, 4 );
638 ms.write( &iPosition, 4 ); 638 ms.write( &iPosition, 4 );
639 } 639 }
640 640
641 // Truncate the stream afterwards so we don't use up too much space. 641 // Truncate the stream afterwards so we don't use up too much space.
642 ms.setSize( ms.tell() ); 642 ms.setSize( ms.tell() );
643} 643}
644 644
645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ) 645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime )
646{ 646{
647 RawStat rs; 647 RawStat rs;
648 Bu::MyriadStream is = mStore.openStream( 2 ); 648 Bu::MyriadStream is = mStore.openStream( 2 );
649 649
650 readInode( iNode, rs, is ); 650 readInode( iNode, rs, is );
651 rs.iATime = iATime; 651 rs.iATime = iATime;
652 rs.iMTime = iMTime; 652 rs.iMTime = iMTime;
653 writeInode( rs, is ); 653 writeInode( rs, is );
654} 654}
655 655
656void Bu::MyriadFs::destroyNode( int32_t iNode ) 656void Bu::MyriadFs::destroyNode( int32_t iNode )
657{ 657{
658 if( iNode == 0 ) 658 if( iNode == 0 )
659 throw Bu::MyriadFsException("You cannot destroy the root."); 659 throw Bu::MyriadFsException("You cannot destroy the root.");
660 660
661 Bu::MyriadStream is = mStore.openStream( 2 ); 661 Bu::MyriadStream is = mStore.openStream( 2 );
662 662
663 // This will be overwritten with the last node 663 // This will be overwritten with the last node
664 uint32_t iPosition = hNodeIndex.get( iNode ); 664 uint32_t iPosition = hNodeIndex.get( iNode );
665 RawStat rsOld; 665 RawStat rsOld;
666 readInode( iNode, rsOld, is ); 666 readInode( iNode, rsOld, is );
667 switch( (rsOld.uPerms&typeMask) ) 667 switch( (rsOld.uPerms&typeMask) )
668 { 668 {
669 case typeRegFile: 669 case typeRegFile:
670 case typeDir: 670 case typeDir:
671 case typeSymLink: 671 case typeSymLink:
672 mStore.deleteStream( rsOld.uStreamIndex ); 672 mStore.deleteStream( rsOld.uStreamIndex );
673 break; 673 break;
674 } 674 }
675 675
676 hNodeIndex.erase( iNode ); 676 hNodeIndex.erase( iNode );
677 677
678 // Read the last node, can't use the helpers, because we don't know the 678 // Read the last node, can't use the helpers, because we don't know the
679 // iNode yet. 679 // iNode yet.
680 if( iPosition != hNodeIndex.getSize() ) 680 if( iPosition != hNodeIndex.getSize() )
681 { 681 {
682 // If this is the last node, then we don't need to do anything, but 682 // If this is the last node, then we don't need to do anything, but
683 // this case handles what to do if we aren't on the last node 683 // this case handles what to do if we aren't on the last node
684 RawStat rs; 684 RawStat rs;
685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) ); 685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) );
686 is.read( &rs, sizeof(RawStat) ); 686 is.read( &rs, sizeof(RawStat) );
687 687
688 hNodeIndex.get( rs.iNode ) = iPosition; 688 hNodeIndex.get( rs.iNode ) = iPosition;
689 writeInode( rs, is ); 689 writeInode( rs, is );
690 } 690 }
691 691
692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) ); 692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) );
693} 693}
694 694
695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath ) 695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath )
696{ 696{
697 Bu::String::const_iterator iStart = sPath.begin(); 697 Bu::String::const_iterator iStart = sPath.begin();
698 if( *iStart == '/' ) 698 if( *iStart == '/' )
699 iStart++; 699 iStart++;
700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; 700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
701 iStart = iEnd+1, iEnd = iStart.find('/') ) { } 701 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
702 return Bu::String( iStart, sPath.end() ); 702 return Bu::String( iStart, sPath.end() );
703} 703}
704 704
diff --git a/src/unstable/myriadfs.h b/src/unstable/myriadfs.h
index 126be7a..dfb051b 100644
--- a/src/unstable/myriadfs.h
+++ b/src/unstable/myriadfs.h
@@ -14,190 +14,190 @@
14 14
15namespace Bu 15namespace Bu
16{ 16{
17 class Stream; 17 class Stream;
18 18
19 subExceptionDecl( MyriadFsException ); 19 subExceptionDecl( MyriadFsException );
20 20
21 /** 21 /**
22 * A POSIX compliant, node based filesystem built on top of Myriad. 22 * A POSIX compliant, node based filesystem built on top of Myriad.
23 * 23 *
24 * A header is placed into stream 1. 24 * A header is placed into stream 1.
25 * Header format: 25 * Header format:
26 * int32_t iMagicHeader (A7188B39) 26 * int32_t iMagicHeader (A7188B39)
27 * int8_t iVersion (1) 27 * int8_t iVersion (1)
28 * int32_t iNumNodes 28 * int32_t iNumNodes
29 * NodeLookup[iNumNodes] nNode 29 * NodeLookup[iNumNodes] nNode
30 * 30 *
31 * Node lookup: 31 * Node lookup:
32 * int32_t iInode 32 * int32_t iInode
33 * int32_t iPosition 33 * int32_t iPosition
34 * 34 *
35 * The node headers or inode structures have a base size of 44 bytes. 35 * The node headers or inode structures have a base size of 44 bytes.
36 * The name is stored in the directory format. 36 * The name is stored in the directory format.
37 * Basic node header format: 37 * Basic node header format:
38 * int32_t iNode 38 * int32_t iNode
39 * int32_t iUser 39 * int32_t iUser
40 * int32_t iGroup 40 * int32_t iGroup
41 * uint16_t uPerms 41 * uint16_t uPerms
42 * int16_t iLinks 42 * int16_t iLinks
43 * uint32_t uStreamIndex 43 * uint32_t uStreamIndex
44 * int64_t iATime 44 * int64_t iATime
45 * int64_t iMTime 45 * int64_t iMTime
46 * int64_t iCTime 46 * int64_t iCTime
47 * 47 *
48 * Some types get special formats for their assosiated data stream, or 48 * Some types get special formats for their assosiated data stream, or
49 * other special considerations, here's a list: 49 * other special considerations, here's a list:
50 * 50 *
51 * - typeFifo: No stream, uStreamIndex unused (probably) 51 * - typeFifo: No stream, uStreamIndex unused (probably)
52 * - typeChrDev: No stream, uStreamIndex is device hi/lo 52 * - typeChrDev: No stream, uStreamIndex is device hi/lo
53 * - typeDir: The stream contains a directory contents listing, described 53 * - typeDir: The stream contains a directory contents listing, described
54 * below 54 * below
55 * - typeBlkDev: No stream, uStreamIndex is device hi/lo 55 * - typeBlkDev: No stream, uStreamIndex is device hi/lo
56 * - typeRegFile: The stream is the file data 56 * - typeRegFile: The stream is the file data
57 * - typeSymLink: The stream is the destination of the symlink 57 * - typeSymLink: The stream is the destination of the symlink
58 * - typeSocket: No steram, uStreamIndex unused (probably) 58 * - typeSocket: No steram, uStreamIndex unused (probably)
59 * 59 *
60 * Directory streams have this simple listing format. They contain a list 60 * Directory streams have this simple listing format. They contain a list
61 * of all child elements, with no particular order at the moment. The . and 61 * of all child elements, with no particular order at the moment. The . and
62 * .. entries are not listed, they are implicit: 62 * .. entries are not listed, they are implicit:
63 * int32_t iNumNodes 63 * int32_t iNumNodes
64 * NodeTable[iNumNodes] nChildren 64 * NodeTable[iNumNodes] nChildren
65 * 65 *
66 * NodeTable: 66 * NodeTable:
67 * int32_t iInode 67 * int32_t iInode
68 * uint8_t uNameSize 68 * uint8_t uNameSize
69 * char[uNameSize] sName 69 * char[uNameSize] sName
70 */ 70 */
71 class MyriadFs 71 class MyriadFs
72 { 72 {
73 public: 73 public:
74 MyriadFs( Bu::Stream &rStore, int iBlockSize=512 ); 74 MyriadFs( Bu::Stream &rStore, int iBlockSize=512 );
75 virtual ~MyriadFs(); 75 virtual ~MyriadFs();
76 76
77 enum 77 enum
78 { 78 {
79 permOthX = 0000001, 79 permOthX = 0000001,
80 permOthW = 0000002, 80 permOthW = 0000002,
81 permOthR = 0000004, 81 permOthR = 0000004,
82 permGrpX = 0000010, 82 permGrpX = 0000010,
83 permGrpW = 0000020, 83 permGrpW = 0000020,
84 permGrpR = 0000040, 84 permGrpR = 0000040,
85 permUsrX = 0000100, 85 permUsrX = 0000100,
86 permUsrW = 0000200, 86 permUsrW = 0000200,
87 permUsrR = 0000400, 87 permUsrR = 0000400,
88 permSticky = 0001000, 88 permSticky = 0001000,
89 permSetGid = 0002000, 89 permSetGid = 0002000,
90 permSetUid = 0004000, 90 permSetUid = 0004000,
91 permMask = 0007777, 91 permMask = 0007777,
92 typeFifo = 0010000, 92 typeFifo = 0010000,
93 typeChrDev = 0020000, 93 typeChrDev = 0020000,
94 typeDir = 0040000, 94 typeDir = 0040000,
95 typeBlkDev = 0060000, 95 typeBlkDev = 0060000,
96 typeRegFile = 0100000, 96 typeRegFile = 0100000,
97 typeSymLink = 0120000, 97 typeSymLink = 0120000,
98 typeSocket = 0140000, 98 typeSocket = 0140000,
99 typeMask = 0170000 99 typeMask = 0170000
100 }; 100 };
101 101
102 enum 102 enum
103 { 103 {
104 Read = 0x01, ///< Open file for reading 104 Read = 0x01, ///< Open file for reading
105 Write = 0x02, ///< Open file for writing 105 Write = 0x02, ///< Open file for writing
106 Create = 0x04, ///< Create file if it doesn't exist 106 Create = 0x04, ///< Create file if it doesn't exist
107 Truncate = 0x08, ///< Truncate file if it does exist 107 Truncate = 0x08, ///< Truncate file if it does exist
108 Append = 0x10, ///< Always append on every write 108 Append = 0x10, ///< Always append on every write
109 NonBlock = 0x20, ///< Open file in non-blocking mode 109 NonBlock = 0x20, ///< Open file in non-blocking mode
110 Exclusive = 0x44, ///< Create file, if it exists then fail 110 Exclusive = 0x44, ///< Create file, if it exists then fail
111 111
112 // Helpful mixes 112 // Helpful mixes
113 ReadWrite = 0x03, ///< Open for reading and writing 113 ReadWrite = 0x03, ///< Open for reading and writing
114 WriteNew = 0x0E ///< Create a file (or truncate) for writing. 114 WriteNew = 0x0E ///< Create a file (or truncate) for writing.
115 /// Same as Write|Create|Truncate 115 /// Same as Write|Create|Truncate
116 }; 116 };
117 117
118 class Stat 118 class Stat
119 { 119 {
120 public: 120 public:
121 int32_t iNode; 121 int32_t iNode;
122 int32_t iUser; 122 int32_t iUser;
123 int32_t iGroup; 123 int32_t iGroup;
124 uint16_t uPerms; 124 uint16_t uPerms;
125 int16_t iLinks; 125 int16_t iLinks;
126 int64_t iATime; 126 int64_t iATime;
127 int64_t iMTime; 127 int64_t iMTime;
128 int64_t iCTime; 128 int64_t iCTime;
129 int32_t iSize; 129 int32_t iSize;
130 uint32_t uDev; 130 uint32_t uDev;
131 Bu::String sName; 131 Bu::String sName;
132 }; 132 };
133 typedef Bu::List<Stat> Dir; 133 typedef Bu::List<Stat> Dir;
134 134
135 void stat( const Bu::String &sPath, Stat &rBuf ); 135 void stat( const Bu::String &sPath, Stat &rBuf );
136 MyriadStream open( const Bu::String &sPath, int iMode, 136 MyriadStream open( const Bu::String &sPath, int iMode,
137 uint16_t uPerms=0664 ); 137 uint16_t uPerms=0664 );
138 void create( const Bu::String &sPath, uint16_t iPerms ); 138 void create( const Bu::String &sPath, uint16_t iPerms );
139 void create( const Bu::String &sPath, uint16_t iPerms, 139 void create( const Bu::String &sPath, uint16_t iPerms,
140 uint16_t iDevHi, uint16_t iDevLo ); 140 uint16_t iDevHi, uint16_t iDevLo );
141 void create( const Bu::String &sPath, uint16_t iPerms, 141 void create( const Bu::String &sPath, uint16_t iPerms,
142 uint32_t uSpecial ); 142 uint32_t uSpecial );
143 void mkDir( const Bu::String &sPath, uint16_t iPerms ); 143 void mkDir( const Bu::String &sPath, uint16_t iPerms );
144 void mkSymLink( const Bu::String &sTarget, const Bu::String &sPath ); 144 void mkSymLink( const Bu::String &sTarget, const Bu::String &sPath );
145 void mkHardLink( const Bu::String &sTarget, const Bu::String &sPath ); 145 void mkHardLink( const Bu::String &sTarget, const Bu::String &sPath );
146 Bu::String readSymLink( const Bu::String &sPath ); 146 Bu::String readSymLink( const Bu::String &sPath );
147 Dir readDir( const Bu::String &sPath ); 147 Dir readDir( const Bu::String &sPath );
148 void setTimes( const Bu::String &sPath, int64_t iATime, 148 void setTimes( const Bu::String &sPath, int64_t iATime,
149 int64_t iMTime ); 149 int64_t iMTime );
150 void unlink( const Bu::String &sPath ); 150 void unlink( const Bu::String &sPath );
151 void setFileSize( const Bu::String &sPath, int32_t iSize ); 151 void setFileSize( const Bu::String &sPath, int32_t iSize );
152 void rename( const Bu::String &sFrom, const Bu::String &sTo ); 152 void rename( const Bu::String &sFrom, const Bu::String &sTo );
153 153
154 static dev_t devToSys( uint32_t uDev ); 154 static dev_t devToSys( uint32_t uDev );
155 static uint32_t sysToDev( dev_t uDev ); 155 static uint32_t sysToDev( dev_t uDev );
156 156
157 private: 157 private:
158 class RawStat 158 class RawStat
159 { 159 {
160 public: 160 public:
161 int32_t iNode; 161 int32_t iNode;
162 int32_t iUser; 162 int32_t iUser;
163 int32_t iGroup; 163 int32_t iGroup;
164 uint16_t uPerms; 164 uint16_t uPerms;
165 int16_t iLinks; 165 int16_t iLinks;
166 uint32_t uStreamIndex; 166 uint32_t uStreamIndex;
167 int64_t iATime; 167 int64_t iATime;
168 int64_t iMTime; 168 int64_t iMTime;
169 int64_t iCTime; 169 int64_t iCTime;
170 }; 170 };
171 typedef Bu::Hash<int32_t, int32_t> NodeIndex; 171 typedef Bu::Hash<int32_t, int32_t> NodeIndex;
172 172
173 private: 173 private:
174 int32_t lookupInode( const Bu::String &sPath, int32_t &iParent ); 174 int32_t lookupInode( const Bu::String &sPath, int32_t &iParent );
175 int32_t lookupInode( Bu::String::const_iterator iStart, 175 int32_t lookupInode( Bu::String::const_iterator iStart,
176 int32_t iNode, int32_t &iParent ); 176 int32_t iNode, int32_t &iParent );
177 void readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ); 177 void readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs );
178 void readInode( int32_t iNode, RawStat &rs ); 178 void readInode( int32_t iNode, RawStat &rs );
179 void writeInode( const RawStat &rs ); 179 void writeInode( const RawStat &rs );
180 void writeInode( const RawStat &rs, MyriadStream &rOs ); 180 void writeInode( const RawStat &rs, MyriadStream &rOs );
181 Dir readDir( int32_t iNode ); 181 Dir readDir( int32_t iNode );
182 MyriadStream openByInode( int32_t iNode ); 182 MyriadStream openByInode( int32_t iNode );
183 void addToDir( int32_t iDir, int32_t iNode, const Bu::String &sName ); 183 void addToDir( int32_t iDir, int32_t iNode, const Bu::String &sName );
184 int32_t create( int32_t iParent, const Bu::String &sName, 184 int32_t create( int32_t iParent, const Bu::String &sName,
185 uint16_t uPerms, uint32_t uSpecial ); 185 uint16_t uPerms, uint32_t uSpecial );
186 int32_t allocInode( uint16_t uPerms, uint32_t uSpecial ); 186 int32_t allocInode( uint16_t uPerms, uint32_t uSpecial );
187 void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ); 187 void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs );
188 void writeHeader(); 188 void writeHeader();
189 void setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ); 189 void setTimes( int32_t iNode, int64_t iATime, int64_t iMTime );
190 void destroyNode( int32_t iNode ); 190 void destroyNode( int32_t iNode );
191 191
192 Bu::String filePart( const Bu::String &sPath ); 192 Bu::String filePart( const Bu::String &sPath );
193 193
194 private: 194 private:
195 Bu::Stream &rStore; 195 Bu::Stream &rStore;
196 Bu::Myriad mStore; 196 Bu::Myriad mStore;
197 NodeIndex hNodeIndex; 197 NodeIndex hNodeIndex;
198 int32_t iUser; 198 int32_t iUser;
199 int32_t iGroup; 199 int32_t iGroup;
200 }; 200 };
201}; 201};
202 202
203#endif 203#endif
diff --git a/src/unstable/newline.cpp b/src/unstable/newline.cpp
index c7eb94c..50a4d4e 100644
--- a/src/unstable/newline.cpp
+++ b/src/unstable/newline.cpp
@@ -8,8 +8,8 @@
8#include "bu/newline.h" 8#include "bu/newline.h"
9 9
10Bu::NewLine::NewLine( Bu::Stream &rNext ) : 10Bu::NewLine::NewLine( Bu::Stream &rNext ) :
11 Bu::Filter( rNext ), 11 Bu::Filter( rNext ),
12 bExChar( false ) 12 bExChar( false )
13{ 13{
14} 14}
15 15
@@ -23,46 +23,46 @@ void Bu::NewLine::start()
23 23
24Bu::size Bu::NewLine::stop() 24Bu::size Bu::NewLine::stop()
25{ 25{
26 return 0; 26 return 0;
27} 27}
28 28
29Bu::size Bu::NewLine::read( void *pBufV, Bu::size iAmnt ) 29Bu::size Bu::NewLine::read( void *pBufV, Bu::size iAmnt )
30{ 30{
31 Bu::size iTotal = 0; 31 Bu::size iTotal = 0;
32 Bu::size iOffset = 0; 32 Bu::size iOffset = 0;
33 Bu::size iRead = rNext.read( pBufV, iAmnt ); 33 Bu::size iRead = rNext.read( pBufV, iAmnt );
34 char *pBuf = (char *)pBufV; 34 char *pBuf = (char *)pBufV;
35 35
36 for( Bu::size i = 0; i < iRead; i++ ) 36 for( Bu::size i = 0; i < iRead; i++ )
37 { 37 {
38 if( pBuf[i] == '\r' ) 38 if( pBuf[i] == '\r' )
39 { 39 {
40 pBuf[i+iOffset] = '\n'; 40 pBuf[i+iOffset] = '\n';
41 if( pBuf[i+1] == '\n' ) 41 if( pBuf[i+1] == '\n' )
42 { 42 {
43 iOffset--; 43 iOffset--;
44 } 44 }
45 } 45 }
46 else if( pBuf[i] == '\n' ) 46 else if( pBuf[i] == '\n' )
47 { 47 {
48 pBuf[i+iOffset] = '\n'; 48 pBuf[i+iOffset] = '\n';
49 if( pBuf[i+1] == '\r' ) 49 if( pBuf[i+1] == '\r' )
50 { 50 {
51 iOffset--; 51 iOffset--;
52 } 52 }
53 } 53 }
54 else if( iOffset ) 54 else if( iOffset )
55 { 55 {
56 pBuf[i+iOffset] = pBuf[i]; 56 pBuf[i+iOffset] = pBuf[i];
57 } 57 }
58 } 58 }
59 59
60 iTotal += iRead + iOffset; 60 iTotal += iRead + iOffset;
61 return iTotal; 61 return iTotal;
62} 62}
63 63
64Bu::size Bu::NewLine::write( const void *, Bu::size ) 64Bu::size Bu::NewLine::write( const void *, Bu::size )
65{ 65{
66 return 0; 66 return 0;
67} 67}
68 68
diff --git a/src/unstable/newline.h b/src/unstable/newline.h
index 417f8cc..1597dc6 100644
--- a/src/unstable/newline.h
+++ b/src/unstable/newline.h
@@ -12,30 +12,30 @@
12 12
13namespace Bu 13namespace Bu
14{ 14{
15 /** 15 /**
16 * Converts new-line characters from any standard convention into linefeeds 16 * Converts new-line characters from any standard convention into linefeeds
17 * (\\n) on reading, and converts them to either your OS's standard or a 17 * (\\n) on reading, and converts them to either your OS's standard or a
18 * specified standard, depending on how you construct the class. 18 * specified standard, depending on how you construct the class.
19 * 19 *
20 * If you're reading in a text file, then this filter is practically 20 * If you're reading in a text file, then this filter is practically
21 * required. 21 * required.
22 */ 22 */
23 class NewLine : public Bu::Filter 23 class NewLine : public Bu::Filter
24 { 24 {
25 public: 25 public:
26 NewLine( Bu::Stream &rNext ); 26 NewLine( Bu::Stream &rNext );
27 virtual ~NewLine(); 27 virtual ~NewLine();
28 28
29 virtual void start(); 29 virtual void start();
30 virtual Bu::size stop(); 30 virtual Bu::size stop();
31 31
32 virtual Bu::size read( void *pBuf, Bu::size iAmnt ); 32 virtual Bu::size read( void *pBuf, Bu::size iAmnt );
33 virtual Bu::size write( const void *pBuf, Bu::size iAmnt ); 33 virtual Bu::size write( const void *pBuf, Bu::size iAmnt );
34 34
35 private: 35 private:
36 bool bExChar; 36 bool bExChar;
37 char cExChar; 37 char cExChar;
38 }; 38 };
39}; 39};
40 40
41#endif 41#endif
diff --git a/src/unstable/settings.cpp b/src/unstable/settings.cpp
index b812b60..ced8c97 100644
--- a/src/unstable/settings.cpp
+++ b/src/unstable/settings.cpp
@@ -5,46 +5,46 @@
5#include "bu/settingsdriverini.h" 5#include "bu/settingsdriverini.h"
6 6
7Bu::Settings::Settings( const Bu::UtfString &sCompany, 7Bu::Settings::Settings( const Bu::UtfString &sCompany,
8 const Bu::UtfString &sProduct, Bu::Settings::Driver eDriver ) : 8 const Bu::UtfString &sProduct, Bu::Settings::Driver eDriver ) :
9 sCompany( sCompany ), 9 sCompany( sCompany ),
10 sProduct( sProduct ), 10 sProduct( sProduct ),
11 pDriver( NULL ) 11 pDriver( NULL )
12{ 12{
13 switch( eDriver ) 13 switch( eDriver )
14 { 14 {
15 case DriverNative: 15 case DriverNative:
16#if defined( WIN32 ) 16#if defined( WIN32 )
17 pDriver = new Bu::SettingsDriverRegistry(); 17 pDriver = new Bu::SettingsDriverRegistry();
18#else 18#else
19 pDriver = new Bu::SettingsDriverIni(); 19 pDriver = new Bu::SettingsDriverIni();
20#endif 20#endif
21 break; 21 break;
22 22
23 case DriverTaf: 23 case DriverTaf:
24 pDriver = new Bu::SettingsDriverTaf(); 24 pDriver = new Bu::SettingsDriverTaf();
25 break; 25 break;
26 26
27 case DriverIni: 27 case DriverIni:
28 pDriver = new Bu::SettingsDriverIni(); 28 pDriver = new Bu::SettingsDriverIni();
29 break; 29 break;
30 } 30 }
31 31
32 pDriver->init( sCompany, sProduct ); 32 pDriver->init( sCompany, sProduct );
33} 33}
34 34
35Bu::Settings::~Settings() 35Bu::Settings::~Settings()
36{ 36{
37 delete pDriver; 37 delete pDriver;
38} 38}
39 39
40void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 40void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
41{ 41{
42 pDriver->set( sKey, sValue ); 42 pDriver->set( sKey, sValue );
43} 43}
44 44
45Bu::UtfString Bu::Settings::get( const Bu::UtfString &sKey, 45Bu::UtfString Bu::Settings::get( const Bu::UtfString &sKey,
46 const Bu::UtfString &sValue ) 46 const Bu::UtfString &sValue )
47{ 47{
48 return pDriver->get( sKey, sValue ); 48 return pDriver->get( sKey, sValue );
49} 49}
50 50
diff --git a/src/unstable/settings.h b/src/unstable/settings.h
index c1d0e1c..80d3049 100644
--- a/src/unstable/settings.h
+++ b/src/unstable/settings.h
@@ -5,31 +5,31 @@
5 5
6namespace Bu 6namespace Bu
7{ 7{
8 /** 8 /**
9 * Simple access to configuration data. Provides a consistant, cross 9 * Simple access to configuration data. Provides a consistant, cross
10 * platform interface to configuration data using native storage. 10 * platform interface to configuration data using native storage.
11 */ 11 */
12 class Settings 12 class Settings
13 { 13 {
14 public: 14 public:
15 enum Driver 15 enum Driver
16 { 16 {
17 DriverNative, 17 DriverNative,
18 DriverTaf, 18 DriverTaf,
19 DriverIni 19 DriverIni
20 }; 20 };
21 Settings( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct, 21 Settings( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct,
22 Driver driver=DriverNative ); 22 Driver driver=DriverNative );
23 virtual ~Settings(); 23 virtual ~Settings();
24 24
25 void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 25 void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
26 Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue=Bu::UtfString() ); 26 Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue=Bu::UtfString() );
27 27
28 private: 28 private:
29 Bu::UtfString sCompany; 29 Bu::UtfString sCompany;
30 Bu::UtfString sProduct; 30 Bu::UtfString sProduct;
31 class SettingsDriver *pDriver; 31 class SettingsDriver *pDriver;
32 }; 32 };
33}; 33};
34 34
35#endif 35#endif
diff --git a/src/unstable/settingsdriver.h b/src/unstable/settingsdriver.h
index 47b7d9d..4dfe09c 100644
--- a/src/unstable/settingsdriver.h
+++ b/src/unstable/settingsdriver.h
@@ -5,24 +5,24 @@
5 5
6namespace Bu 6namespace Bu
7{ 7{
8 class Settings; 8 class Settings;
9 9
10 /** 10 /**
11 * Base class for i/o interfaces for Bu::Settings. By subclassing this you 11 * Base class for i/o interfaces for Bu::Settings. By subclassing this you
12 * can provide custom storage for application settings. 12 * can provide custom storage for application settings.
13 */ 13 */
14 class SettingsDriver 14 class SettingsDriver
15 { 15 {
16 friend class Bu::Settings; 16 friend class Bu::Settings;
17 public: 17 public:
18 SettingsDriver(); 18 SettingsDriver();
19 virtual ~SettingsDriver(); 19 virtual ~SettingsDriver();
20 20
21 protected: 21 protected:
22 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )=0; 22 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )=0;
23 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0; 23 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0;
24 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0; 24 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0;
25 }; 25 };
26}; 26};
27 27
28#endif 28#endif
diff --git a/src/unstable/settingsdriverini.cpp b/src/unstable/settingsdriverini.cpp
index 90debcb..31bc146 100644
--- a/src/unstable/settingsdriverini.cpp
+++ b/src/unstable/settingsdriverini.cpp
@@ -15,146 +15,146 @@ Bu::SettingsDriverIni::SettingsDriverIni()
15 15
16Bu::SettingsDriverIni::~SettingsDriverIni() 16Bu::SettingsDriverIni::~SettingsDriverIni()
17{ 17{
18 Bu::File fOut( sPath, Bu::File::WriteNew ); 18 Bu::File fOut( sPath, Bu::File::WriteNew );
19 Bu::Buffer bOut( fOut ); 19 Bu::Buffer bOut( fOut );
20 Bu::Formatter f( bOut ); 20 Bu::Formatter f( bOut );
21 21
22 for( GroupHash::iterator i = hGroup.begin(); i; i++ ) 22 for( GroupHash::iterator i = hGroup.begin(); i; i++ )
23 { 23 {
24 f << "[" << i.getKey().get() << "]" << f.nl; 24 f << "[" << i.getKey().get() << "]" << f.nl;
25 for( StrHash::iterator k = (*i).begin(); k; k++ ) 25 for( StrHash::iterator k = (*i).begin(); k; k++ )
26 { 26 {
27 f << k.getKey().get() << " = " << k.getValue().get() << f.nl; 27 f << k.getKey().get() << " = " << k.getValue().get() << f.nl;
28 } 28 }
29 f << f.nl; 29 f << f.nl;
30 } 30 }
31} 31}
32 32
33void Bu::SettingsDriverIni::init( const Bu::UtfString &sCompany, 33void Bu::SettingsDriverIni::init( const Bu::UtfString &sCompany,
34 const Bu::UtfString &sProduct ) 34 const Bu::UtfString &sProduct )
35{ 35{
36 Bu::UtfString us( getenv("HOME") ); 36 Bu::UtfString us( getenv("HOME") );
37 us += "/.config/"; 37 us += "/.config/";
38 us += sCompany; 38 us += sCompany;
39 us += "/"; 39 us += "/";
40 us += sProduct; 40 us += sProduct;
41 sPath = us.get(); 41 sPath = us.get();
42 try 42 try
43 { 43 {
44 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create ); 44 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create );
45 Bu::Buffer bIn( fIn ); 45 Bu::Buffer bIn( fIn );
46 StrHash hKeys; 46 StrHash hKeys;
47 Bu::String sGroup; 47 Bu::String sGroup;
48 bool bStart = true; 48 bool bStart = true;
49 while( !bIn.isEos() ) 49 while( !bIn.isEos() )
50 { 50 {
51 Bu::String sIn = bIn.readLine(); 51 Bu::String sIn = bIn.readLine();
52 if( sIn.isEmpty() ) 52 if( sIn.isEmpty() )
53 continue; 53 continue;
54 if( sIn[0] == '[' ) 54 if( sIn[0] == '[' )
55 { 55 {
56 if( bStart != true ) 56 if( bStart != true )
57 { 57 {
58 hGroup.insert( sGroup, hKeys ); 58 hGroup.insert( sGroup, hKeys );
59 hKeys.clear(); 59 hKeys.clear();
60 } 60 }
61 sGroup = Bu::String( sIn.begin()+1, sIn.find(']') ); 61 sGroup = Bu::String( sIn.begin()+1, sIn.find(']') );
62 bStart = false; 62 bStart = false;
63 } 63 }
64 else 64 else
65 { 65 {
66 Bu::String::iterator i = sIn.find('='); 66 Bu::String::iterator i = sIn.find('=');
67 if( !i ) 67 if( !i )
68 continue; 68 continue;
69 69
70 hKeys.insert( Bu::String( sIn.begin(), i ).trimWhitespace(), 70 hKeys.insert( Bu::String( sIn.begin(), i ).trimWhitespace(),
71 Bu::String( i+1, sIn.end() ).trimWhitespace() ); 71 Bu::String( i+1, sIn.end() ).trimWhitespace() );
72 } 72 }
73 } 73 }
74 hGroup.insert( sGroup, hKeys ); 74 hGroup.insert( sGroup, hKeys );
75 } 75 }
76 catch(...) 76 catch(...)
77 { 77 {
78 } 78 }
79} 79}
80 80
81void Bu::SettingsDriverIni::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 81void Bu::SettingsDriverIni::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
82{ 82{
83 Bu::String suKey = sKey.get(); 83 Bu::String suKey = sKey.get();
84 Bu::String::iterator i = suKey.find('/'); 84 Bu::String::iterator i = suKey.find('/');
85 Bu::UtfString sGrp; 85 Bu::UtfString sGrp;
86 Bu::UtfString sId; 86 Bu::UtfString sId;
87 if( !i ) 87 if( !i )
88 { 88 {
89 sGrp = ""; 89 sGrp = "";
90 sId = sKey; 90 sId = sKey;
91 } 91 }
92 else 92 else
93 { 93 {
94 Bu::String::iterator in; 94 Bu::String::iterator in;
95 for(;;) 95 for(;;)
96 { 96 {
97 in = i; 97 in = i;
98 i = (in + 1).find('/'); 98 i = (in + 1).find('/');
99 if( !i ) 99 if( !i )
100 break; 100 break;
101 } 101 }
102 102
103 sGrp.set( Bu::String( suKey.begin(), in ) ); 103 sGrp.set( Bu::String( suKey.begin(), in ) );
104 sId.set( Bu::String( in+1, suKey.end() ) ); 104 sId.set( Bu::String( in+1, suKey.end() ) );
105 } 105 }
106 106
107// sio << "Group: " << sGrp.get() << sio.nl 107// sio << "Group: " << sGrp.get() << sio.nl
108// << "Key: " << sId.get() << sio.nl; 108// << "Key: " << sId.get() << sio.nl;
109 109
110 if( !hGroup.has( sGrp ) ) 110 if( !hGroup.has( sGrp ) )
111 { 111 {
112 StrHash hVal; 112 StrHash hVal;
113 hVal.insert( sId, sValue ); 113 hVal.insert( sId, sValue );
114 hGroup.insert( sGrp, hVal ); 114 hGroup.insert( sGrp, hVal );
115 } 115 }
116 else 116 else
117 { 117 {
118 hGroup.get( sGrp ).insert( sId, sValue ); 118 hGroup.get( sGrp ).insert( sId, sValue );
119 } 119 }
120} 120}
121 121
122Bu::UtfString Bu::SettingsDriverIni::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 122Bu::UtfString Bu::SettingsDriverIni::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
123{ 123{
124 Bu::String suKey = sKey.get(); 124 Bu::String suKey = sKey.get();
125 Bu::String::iterator i = suKey.find('/'); 125 Bu::String::iterator i = suKey.find('/');
126 Bu::UtfString sGrp; 126 Bu::UtfString sGrp;
127 Bu::UtfString sId; 127 Bu::UtfString sId;
128 if( !i ) 128 if( !i )
129 { 129 {
130 sGrp = ""; 130 sGrp = "";
131 sId = sKey; 131 sId = sKey;
132 } 132 }
133 else 133 else
134 { 134 {
135 Bu::String::iterator in; 135 Bu::String::iterator in;
136 for(;;) 136 for(;;)
137 { 137 {
138 in = i; 138 in = i;
139 i = (in + 1).find('/'); 139 i = (in + 1).find('/');
140 if( !i ) 140 if( !i )
141 break; 141 break;
142 } 142 }
143 143
144 sGrp.set( Bu::String( suKey.begin(), in ) ); 144 sGrp.set( Bu::String( suKey.begin(), in ) );
145 sId.set( Bu::String( in+1, suKey.end() ) ); 145 sId.set( Bu::String( in+1, suKey.end() ) );
146 } 146 }
147 147
148// sio << "Group: " << sGrp.get() << sio.nl 148// sio << "Group: " << sGrp.get() << sio.nl
149// << "Key: " << sId.get() << sio.nl; 149// << "Key: " << sId.get() << sio.nl;
150 150
151 try 151 try
152 { 152 {
153 return hGroup.get( sGrp ).get( sId ); 153 return hGroup.get( sGrp ).get( sId );
154 } 154 }
155 catch(...) 155 catch(...)
156 { 156 {
157 return sValue; 157 return sValue;
158 } 158 }
159} 159}
160 160
diff --git a/src/unstable/settingsdriverini.h b/src/unstable/settingsdriverini.h
index c3942d6..bd3097d 100644
--- a/src/unstable/settingsdriverini.h
+++ b/src/unstable/settingsdriverini.h
@@ -7,23 +7,23 @@
7 7
8namespace Bu 8namespace Bu
9{ 9{
10 class SettingsDriverIni : public SettingsDriver 10 class SettingsDriverIni : public SettingsDriver
11 { 11 {
12 public: 12 public:
13 SettingsDriverIni(); 13 SettingsDriverIni();
14 virtual ~SettingsDriverIni(); 14 virtual ~SettingsDriverIni();
15 15
16 protected: 16 protected:
17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
20 20
21 private: 21 private:
22 Bu::String sPath; 22 Bu::String sPath;
23 typedef Bu::Hash<Bu::UtfString, Bu::UtfString> StrHash; 23 typedef Bu::Hash<Bu::UtfString, Bu::UtfString> StrHash;
24 typedef Bu::Hash<Bu::UtfString, StrHash> GroupHash; 24 typedef Bu::Hash<Bu::UtfString, StrHash> GroupHash;
25 GroupHash hGroup; 25 GroupHash hGroup;
26 }; 26 };
27}; 27};
28 28
29#endif 29#endif
diff --git a/src/unstable/settingsdriverregistry.cpp b/src/unstable/settingsdriverregistry.cpp
index 89eda7b..983f48e 100644
--- a/src/unstable/settingsdriverregistry.cpp
+++ b/src/unstable/settingsdriverregistry.cpp
@@ -12,80 +12,80 @@ Bu::SettingsDriverRegistry::SettingsDriverRegistry()
12 12
13Bu::SettingsDriverRegistry::~SettingsDriverRegistry() 13Bu::SettingsDriverRegistry::~SettingsDriverRegistry()
14{ 14{
15 RegCloseKey( *phKey ); 15 RegCloseKey( *phKey );
16} 16}
17 17
18void Bu::SettingsDriverRegistry::init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ) 18void Bu::SettingsDriverRegistry::init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )
19{ 19{
20 Bu::UtfString us("Software\\"); 20 Bu::UtfString us("Software\\");
21 us += sCompany; 21 us += sCompany;
22 us += "\\"; 22 us += "\\";
23 us += sProduct; 23 us += sProduct;
24 rphKey = new HKEY; 24 rphKey = new HKEY;
25 RegCreateKeyExA( HKEY_CURRENT_USER, us.get().getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, phKey, NULL ); 25 RegCreateKeyExA( HKEY_CURRENT_USER, us.get().getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, phKey, NULL );
26} 26}
27 27
28void Bu::SettingsDriverRegistry::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 28void Bu::SettingsDriverRegistry::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
29{ 29{
30 Bu::StringList lPath = sKey.get().split('/'); 30 Bu::StringList lPath = sKey.get().split('/');
31 Bu::StringList::iterator i = lPath.begin(); 31 Bu::StringList::iterator i = lPath.begin();
32 Bu::StringList::iterator in; 32 Bu::StringList::iterator in;
33 33
34 Bu::String sPKey; 34 Bu::String sPKey;
35 for(; i;) 35 for(; i;)
36 { 36 {
37 in = i; 37 in = i;
38 in++; 38 in++;
39 if( in ) 39 if( in )
40 { 40 {
41 if( !sPKey.isEmpty() ) 41 if( !sPKey.isEmpty() )
42 sPKey += "\\"; 42 sPKey += "\\";
43 sPKey += *i; 43 sPKey += *i;
44 } 44 }
45 i = in; 45 i = in;
46 } 46 }
47 47
48 HKEY key; 48 HKEY key;
49 RegCreateKeyExA( *phKey, sPKey.getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); 49 RegCreateKeyExA( *phKey, sPKey.getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
50 Bu::String sTmp = sValue.get(); 50 Bu::String sTmp = sValue.get();
51 RegSetValueExA( key, lPath.last().getStr(), 0, REG_SZ, (BYTE *)sTmp.getStr(), sTmp.getSize()+1 ); 51 RegSetValueExA( key, lPath.last().getStr(), 0, REG_SZ, (BYTE *)sTmp.getStr(), sTmp.getSize()+1 );
52 RegCloseKey( key ); 52 RegCloseKey( key );
53} 53}
54 54
55Bu::UtfString Bu::SettingsDriverRegistry::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 55Bu::UtfString Bu::SettingsDriverRegistry::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
56{ 56{
57 Bu::StringList lPath = sKey.get().split('/'); 57 Bu::StringList lPath = sKey.get().split('/');
58 Bu::StringList::iterator i = lPath.begin(); 58 Bu::StringList::iterator i = lPath.begin();
59 Bu::StringList::iterator in; 59 Bu::StringList::iterator in;
60 60
61 Bu::String sPKey; 61 Bu::String sPKey;
62 for(; i;) 62 for(; i;)
63 { 63 {
64 in = i; 64 in = i;
65 in++; 65 in++;
66 if( in ) 66 if( in )
67 { 67 {
68 if( !sPKey.isEmpty() ) 68 if( !sPKey.isEmpty() )
69 sPKey += "\\"; 69 sPKey += "\\";
70 sPKey += *i; 70 sPKey += *i;
71 } 71 }
72 i = in; 72 i = in;
73 } 73 }
74 74
75 HKEY key; 75 HKEY key;
76 if( RegOpenKeyExA( *phKey, sPKey.getStr(), 0, KEY_ALL_ACCESS, &key ) 76 if( RegOpenKeyExA( *phKey, sPKey.getStr(), 0, KEY_ALL_ACCESS, &key )
77 != ERROR_SUCCESS ) 77 != ERROR_SUCCESS )
78 return sValue; 78 return sValue;
79 char buf[4096]; 79 char buf[4096];
80 DWORD iRet = 4096; 80 DWORD iRet = 4096;
81 if( RegQueryValueEx( key, lPath.last().getStr(), NULL, NULL, (BYTE *)buf, &iRet ) != ERROR_SUCCESS ) 81 if( RegQueryValueEx( key, lPath.last().getStr(), NULL, NULL, (BYTE *)buf, &iRet ) != ERROR_SUCCESS )
82 { 82 {
83 RegCloseKey( key ); 83 RegCloseKey( key );
84 return sValue; 84 return sValue;
85 } 85 }
86 RegCloseKey( key ); 86 RegCloseKey( key );
87 87
88 return Bu::UtfString( Bu::String( buf, iRet ) ); 88 return Bu::UtfString( Bu::String( buf, iRet ) );
89} 89}
90 90
91#endif 91#endif
diff --git a/src/unstable/settingsdriverregistry.h b/src/unstable/settingsdriverregistry.h
index 2d718d2..d1a2896 100644
--- a/src/unstable/settingsdriverregistry.h
+++ b/src/unstable/settingsdriverregistry.h
@@ -7,20 +7,20 @@
7 7
8namespace Bu 8namespace Bu
9{ 9{
10 class SettingsDriverRegistry : public SettingsDriver 10 class SettingsDriverRegistry : public SettingsDriver
11 { 11 {
12 public: 12 public:
13 SettingsDriverRegistry(); 13 SettingsDriverRegistry();
14 virtual ~SettingsDriverRegistry(); 14 virtual ~SettingsDriverRegistry();
15 15
16 protected: 16 protected:
17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
20 20
21 private: 21 private:
22 void *rphKey; 22 void *rphKey;
23 }; 23 };
24}; 24};
25 25
26#endif 26#endif
diff --git a/src/unstable/settingsdrivertaf.cpp b/src/unstable/settingsdrivertaf.cpp
index 8cbcbc5..3fd61b3 100644
--- a/src/unstable/settingsdrivertaf.cpp
+++ b/src/unstable/settingsdrivertaf.cpp
@@ -6,97 +6,97 @@
6#include <stdlib.h> 6#include <stdlib.h>
7 7
8Bu::SettingsDriverTaf::SettingsDriverTaf() : 8Bu::SettingsDriverTaf::SettingsDriverTaf() :
9 pRoot( NULL ) 9 pRoot( NULL )
10{ 10{
11} 11}
12 12
13Bu::SettingsDriverTaf::~SettingsDriverTaf() 13Bu::SettingsDriverTaf::~SettingsDriverTaf()
14{ 14{
15 if( !pRoot ) 15 if( !pRoot )
16 return; 16 return;
17 17
18 Bu::File fOut( sPath, Bu::File::WriteNew ); 18 Bu::File fOut( sPath, Bu::File::WriteNew );
19 Bu::TafWriter tw( fOut ); 19 Bu::TafWriter tw( fOut );
20 tw.writeGroup( pRoot ); 20 tw.writeGroup( pRoot );
21 delete pRoot; 21 delete pRoot;
22} 22}
23 23
24void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany, 24void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany,
25 const Bu::UtfString &sProduct ) 25 const Bu::UtfString &sProduct )
26{ 26{
27 Bu::UtfString us( getenv("HOME") ); 27 Bu::UtfString us( getenv("HOME") );
28 us += "/.config/"; 28 us += "/.config/";
29 us += sCompany; 29 us += sCompany;
30 us += "/"; 30 us += "/";
31 us += sProduct; 31 us += sProduct;
32 sPath = us.get(); 32 sPath = us.get();
33 try 33 try
34 { 34 {
35 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create ); 35 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create );
36 Bu::TafReader tr( fIn ); 36 Bu::TafReader tr( fIn );
37 pRoot = tr.readGroup(); 37 pRoot = tr.readGroup();
38 } 38 }
39 catch(...) 39 catch(...)
40 { 40 {
41 } 41 }
42 if( !pRoot ) 42 if( !pRoot )
43 { 43 {
44 pRoot = new Bu::TafGroup( sProduct.get() ); 44 pRoot = new Bu::TafGroup( sProduct.get() );
45 } 45 }
46} 46}
47 47
48void Bu::SettingsDriverTaf::set( const Bu::UtfString &sKey, 48void Bu::SettingsDriverTaf::set( const Bu::UtfString &sKey,
49 const Bu::UtfString &sValue ) 49 const Bu::UtfString &sValue )
50{ 50{
51 Bu::StringList lPath = sKey.get().split('/'); 51 Bu::StringList lPath = sKey.get().split('/');
52 Bu::StringList::iterator i = lPath.begin(); 52 Bu::StringList::iterator i = lPath.begin();
53 Bu::StringList::iterator in; 53 Bu::StringList::iterator in;
54 Bu::TafGroup *pGrp = pRoot; 54 Bu::TafGroup *pGrp = pRoot;
55 for(; i;) 55 for(; i;)
56 { 56 {
57 in = i; 57 in = i;
58 in++; 58 in++;
59 if( in ) 59 if( in )
60 { 60 {
61 if( pGrp->hasChild( *i ) ) 61 if( pGrp->hasChild( *i ) )
62 pGrp = (Bu::TafGroup *)pGrp->getChild( *i ); 62 pGrp = (Bu::TafGroup *)pGrp->getChild( *i );
63 else 63 else
64 pGrp = pGrp->addGroup( *i ); 64 pGrp = pGrp->addGroup( *i );
65 } 65 }
66 else 66 else
67 { 67 {
68 pGrp->addProperty( *i, sValue.get() ); 68 pGrp->addProperty( *i, sValue.get() );
69 } 69 }
70 i = in; 70 i = in;
71 } 71 }
72} 72}
73 73
74Bu::UtfString Bu::SettingsDriverTaf::get( const Bu::UtfString &sKey, 74Bu::UtfString Bu::SettingsDriverTaf::get( const Bu::UtfString &sKey,
75 const Bu::UtfString &sValue ) 75 const Bu::UtfString &sValue )
76{ 76{
77 Bu::StringList lPath = sKey.get().split('/'); 77 Bu::StringList lPath = sKey.get().split('/');
78 Bu::StringList::iterator i = lPath.begin(); 78 Bu::StringList::iterator i = lPath.begin();
79 Bu::StringList::iterator in; 79 Bu::StringList::iterator in;
80 Bu::TafGroup *pGrp = pRoot; 80 Bu::TafGroup *pGrp = pRoot;
81 for(; i;) 81 for(; i;)
82 { 82 {
83 in = i; 83 in = i;
84 in++; 84 in++;
85 if( in ) 85 if( in )
86 { 86 {
87 if( pGrp->hasChild( *i ) ) 87 if( pGrp->hasChild( *i ) )
88 pGrp = (Bu::TafGroup *)pGrp->getChild( *i ); 88 pGrp = (Bu::TafGroup *)pGrp->getChild( *i );
89 else 89 else
90 return sValue; 90 return sValue;
91 } 91 }
92 else 92 else
93 { 93 {
94 if( pGrp->hasProperty( *i ) ) 94 if( pGrp->hasProperty( *i ) )
95 return pGrp->getProperty( *i ); 95 return pGrp->getProperty( *i );
96 else 96 else
97 return sValue; 97 return sValue;
98 } 98 }
99 i = in; 99 i = in;
100 } 100 }
101} 101}
102 102
diff --git a/src/unstable/settingsdrivertaf.h b/src/unstable/settingsdrivertaf.h
index b5f8b07..28b5f5c 100644
--- a/src/unstable/settingsdrivertaf.h
+++ b/src/unstable/settingsdrivertaf.h
@@ -6,26 +6,26 @@
6 6
7namespace Bu 7namespace Bu
8{ 8{
9 class TafGroup; 9 class TafGroup;
10 10
11 /** 11 /**
12 * The taf driver is flawed until I fix taf editing, I've been meaning to... 12 * The taf driver is flawed until I fix taf editing, I've been meaning to...
13 */ 13 */
14 class SettingsDriverTaf : public SettingsDriver 14 class SettingsDriverTaf : public SettingsDriver
15 { 15 {
16 public: 16 public:
17 SettingsDriverTaf(); 17 SettingsDriverTaf();
18 virtual ~SettingsDriverTaf(); 18 virtual ~SettingsDriverTaf();
19 19
20 protected: 20 protected:
21 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 21 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
22 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 22 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
23 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 23 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
24 24
25 private: 25 private:
26 Bu::String sPath; 26 Bu::String sPath;
27 class Bu::TafGroup *pRoot; 27 class Bu::TafGroup *pRoot;
28 }; 28 };
29}; 29};
30 30
31#endif 31#endif
diff --git a/src/unstable/udpsocket.cpp b/src/unstable/udpsocket.cpp
index f554165..141c2cf 100644
--- a/src/unstable/udpsocket.cpp
+++ b/src/unstable/udpsocket.cpp
@@ -24,135 +24,135 @@ namespace Bu { subExceptionDef( UdpSocketException ) }
24#define saTarget ( *((struct sockaddr_in *)paTarget) ) 24#define saTarget ( *((struct sockaddr_in *)paTarget) )
25 25
26Bu::UdpSocket::UdpSocket( int iUdpSocket ) : 26Bu::UdpSocket::UdpSocket( int iUdpSocket ) :
27 iUdpSocket( iUdpSocket ), 27 iUdpSocket( iUdpSocket ),
28 paTarget( NULL ), 28 paTarget( NULL ),
29 bBound( false ) 29 bBound( false )
30{ 30{
31} 31}
32 32
33Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) : 33Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) :
34 iUdpSocket( 0 ), 34 iUdpSocket( 0 ),
35 paTarget( NULL ), 35 paTarget( NULL ),
36 bBound( false ) 36 bBound( false )
37{ 37{
38 iUdpSocket = socket( PF_INET, SOCK_DGRAM, 0 ); 38 iUdpSocket = socket( PF_INET, SOCK_DGRAM, 0 );
39 if( iUdpSocket < 0 ) 39 if( iUdpSocket < 0 )
40 { 40 {
41 throw UdpSocketException("Couldn't open udp socket: %s", 41 throw UdpSocketException("Couldn't open udp socket: %s",
42 strerror( errno ) 42 strerror( errno )
43 ); 43 );
44 } 44 }
45 45
46 if( (iFlags&Broadcast) ) 46 if( (iFlags&Broadcast) )
47 { 47 {
48 int broadcast = 1; 48 int broadcast = 1;
49 if( (setsockopt( iUdpSocket, SOL_SOCKET, SO_BROADCAST, 49 if( (setsockopt( iUdpSocket, SOL_SOCKET, SO_BROADCAST,
50 &broadcast, sizeof(broadcast) )) == -1) 50 &broadcast, sizeof(broadcast) )) == -1)
51 { 51 {
52 throw UdpSocketException("Couldn't set udp socket to broadcast: %s", 52 throw UdpSocketException("Couldn't set udp socket to broadcast: %s",
53 strerror( errno ) 53 strerror( errno )
54 ); 54 );
55 } 55 }
56 } 56 }
57 57
58 paTarget = new struct sockaddr_in; 58 paTarget = new struct sockaddr_in;
59 saTarget.sin_family = AF_INET; 59 saTarget.sin_family = AF_INET;
60 saTarget.sin_port = htons( iPort ); 60 saTarget.sin_port = htons( iPort );
61 saTarget.sin_addr.s_addr = inet_addr( sAddr.getStr() ); // INADDR_ANY; 61 saTarget.sin_addr.s_addr = inet_addr( sAddr.getStr() ); // INADDR_ANY;
62 memset( saTarget.sin_zero, '\0', sizeof(saTarget.sin_zero) ); 62 memset( saTarget.sin_zero, '\0', sizeof(saTarget.sin_zero) );
63 63
64 if( (iFlags&Read) ) 64 if( (iFlags&Read) )
65 { 65 {
66 if( bind( iUdpSocket, (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ) 66 if( bind( iUdpSocket, (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) )
67 == -1 ) 67 == -1 )
68 { 68 {
69 throw UdpSocketException("Couldn't bind port to udp socket: %s", 69 throw UdpSocketException("Couldn't bind port to udp socket: %s",
70 strerror( errno ) 70 strerror( errno )
71 ); 71 );
72 } 72 }
73 bBound = true; 73 bBound = true;
74 } 74 }
75} 75}
76 76
77Bu::UdpSocket::~UdpSocket() 77Bu::UdpSocket::~UdpSocket()
78{ 78{
79 close(); 79 close();
80 delete (struct sockaddr_in *)paTarget; 80 delete (struct sockaddr_in *)paTarget;
81 paTarget = NULL; 81 paTarget = NULL;
82} 82}
83 83
84Bu::String Bu::UdpSocket::addrToStr( const addr &a ) 84Bu::String Bu::UdpSocket::addrToStr( const addr &a )
85{ 85{
86 return Bu::String("%1.%2.%3.%4"). 86 return Bu::String("%1.%2.%3.%4").
87 arg( (a&0xff) ). 87 arg( (a&0xff) ).
88 arg( (a&0xff00)>>8 ). 88 arg( (a&0xff00)>>8 ).
89 arg( (a&0xff0000)>>16 ). 89 arg( (a&0xff0000)>>16 ).
90 arg( (a&0xff000000)>>24 ); 90 arg( (a&0xff000000)>>24 );
91} 91}
92 92
93void Bu::UdpSocket::close() 93void Bu::UdpSocket::close()
94{ 94{
95 ::close( iUdpSocket ); 95 ::close( iUdpSocket );
96} 96}
97 97
98Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes ) 98Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes )
99{ 99{
100 return recv( iUdpSocket, pBuf, nBytes, 0 ); 100 return recv( iUdpSocket, pBuf, nBytes, 0 );
101} 101}
102 102
103Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes, 103Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes,
104 Bu::UdpSocket::addr &aHost, int &iPort ) 104 Bu::UdpSocket::addr &aHost, int &iPort )
105{ 105{
106 sockaddr_in name; 106 sockaddr_in name;
107 socklen_t size = sizeof(name); 107 socklen_t size = sizeof(name);
108 Bu::size ret = recvfrom( iUdpSocket, pBuf, nBytes, 0, 108 Bu::size ret = recvfrom( iUdpSocket, pBuf, nBytes, 0,
109 (struct sockaddr *)&name, &size ); 109 (struct sockaddr *)&name, &size );
110 aHost = name.sin_addr.s_addr; 110 aHost = name.sin_addr.s_addr;
111 iPort = ntohs(name.sin_port); 111 iPort = ntohs(name.sin_port);
112 return ret; 112 return ret;
113} 113}
114 114
115Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes ) 115Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes )
116{ 116{
117 if( bBound ) 117 if( bBound )
118 { 118 {
119 return sendto( iUdpSocket, pBuf, nBytes, 0, NULL, 0 ); 119 return sendto( iUdpSocket, pBuf, nBytes, 0, NULL, 0 );
120 } 120 }
121 else 121 else
122 { 122 {
123 return sendto( iUdpSocket, pBuf, nBytes, 0, 123 return sendto( iUdpSocket, pBuf, nBytes, 0,
124 (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ); 124 (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) );
125 } 125 }
126} 126}
127 127
128Bu::size Bu::UdpSocket::tell() 128Bu::size Bu::UdpSocket::tell()
129{ 129{
130 throw Bu::UnsupportedException(); 130 throw Bu::UnsupportedException();
131} 131}
132 132
133void Bu::UdpSocket::seek( Bu::size ) 133void Bu::UdpSocket::seek( Bu::size )
134{ 134{
135 throw Bu::UnsupportedException(); 135 throw Bu::UnsupportedException();
136} 136}
137 137
138void Bu::UdpSocket::setPos( Bu::size ) 138void Bu::UdpSocket::setPos( Bu::size )
139{ 139{
140 throw Bu::UnsupportedException(); 140 throw Bu::UnsupportedException();
141} 141}
142 142
143void Bu::UdpSocket::setPosEnd( Bu::size ) 143void Bu::UdpSocket::setPosEnd( Bu::size )
144{ 144{
145 throw Bu::UnsupportedException(); 145 throw Bu::UnsupportedException();
146} 146}
147 147
148bool Bu::UdpSocket::isEos() 148bool Bu::UdpSocket::isEos()
149{ 149{
150 return false; 150 return false;
151} 151}
152 152
153bool Bu::UdpSocket::isOpen() 153bool Bu::UdpSocket::isOpen()
154{ 154{
155 return true; 155 return true;
156} 156}
157 157
158void Bu::UdpSocket::flush() 158void Bu::UdpSocket::flush()
@@ -161,79 +161,79 @@ void Bu::UdpSocket::flush()
161 161
162bool Bu::UdpSocket::canRead() 162bool Bu::UdpSocket::canRead()
163{ 163{
164 return bBound; 164 return bBound;
165} 165}
166 166
167bool Bu::UdpSocket::canWrite() 167bool Bu::UdpSocket::canWrite()
168{ 168{
169 return true; 169 return true;
170} 170}
171 171
172bool Bu::UdpSocket::isReadable() 172bool Bu::UdpSocket::isReadable()
173{ 173{
174 return bBound; 174 return bBound;
175} 175}
176 176
177bool Bu::UdpSocket::isWritable() 177bool Bu::UdpSocket::isWritable()
178{ 178{
179 return true; 179 return true;
180} 180}
181 181
182bool Bu::UdpSocket::isSeekable() 182bool Bu::UdpSocket::isSeekable()
183{ 183{
184 return false; 184 return false;
185} 185}
186 186
187bool Bu::UdpSocket::isBlocking() 187bool Bu::UdpSocket::isBlocking()
188{ 188{
189 return true; 189 return true;
190} 190}
191 191
192void Bu::UdpSocket::setBlocking( bool bBlocking ) 192void Bu::UdpSocket::setBlocking( bool bBlocking )
193{ 193{
194#ifndef WIN32 194#ifndef WIN32
195 if( bBlocking ) 195 if( bBlocking )
196 { 196 {
197 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); 197 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) );
198 } 198 }
199 else 199 else
200 { 200 {
201 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) | O_NONBLOCK ); 201 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) | O_NONBLOCK );
202 } 202 }
203#else 203#else
204 u_long iMode; 204 u_long iMode;
205 if( bBlocking ) 205 if( bBlocking )
206 iMode = 0; 206 iMode = 0;
207 else 207 else
208 iMode = 1; 208 iMode = 1;
209 //------------------------- 209 //-------------------------
210 // Set the socket I/O mode: In this case FIONBIO 210 // Set the socket I/O mode: In this case FIONBIO
211 // enables or disables the blocking mode for the 211 // enables or disables the blocking mode for the
212 // socket based on the numerical value of iMode. 212 // socket based on the numerical value of iMode.
213 // If iMode = 0, blocking is enabled; 213 // If iMode = 0, blocking is enabled;
214 // If iMode != 0, non-blocking mode is enabled. 214 // If iMode != 0, non-blocking mode is enabled.
215 bu_ioctlsocket(iUdpSocket, FIONBIO, &iMode); 215 bu_ioctlsocket(iUdpSocket, FIONBIO, &iMode);
216#endif 216#endif
217} 217}
218 218
219void Bu::UdpSocket::setSize( Bu::size ) 219void Bu::UdpSocket::setSize( Bu::size )
220{ 220{
221 throw Bu::UnsupportedException(); 221 throw Bu::UnsupportedException();
222} 222}
223 223
224Bu::size Bu::UdpSocket::getSize() const 224Bu::size Bu::UdpSocket::getSize() const
225{ 225{
226 throw Bu::UnsupportedException(); 226 throw Bu::UnsupportedException();
227} 227}
228 228
229Bu::size Bu::UdpSocket::getBlockSize() const 229Bu::size Bu::UdpSocket::getBlockSize() const
230{ 230{
231 return 1500; 231 return 1500;
232} 232}
233 233
234Bu::String Bu::UdpSocket::getLocation() const 234Bu::String Bu::UdpSocket::getLocation() const
235{ 235{
236 throw Bu::UnsupportedException(); 236 throw Bu::UnsupportedException();
237} 237}
238 238
239#endif 239#endif
diff --git a/src/unstable/udpsocket.h b/src/unstable/udpsocket.h
index 8f8630a..569a6fb 100644
--- a/src/unstable/udpsocket.h
+++ b/src/unstable/udpsocket.h
@@ -15,68 +15,68 @@
15 15
16namespace Bu 16namespace Bu
17{ 17{
18 subExceptionDecl( UdpSocketException ); 18 subExceptionDecl( UdpSocketException );
19 19
20 class UdpSocket : public Stream 20 class UdpSocket : public Stream
21 { 21 {
22 public: 22 public:
23 UdpSocket( int iUdpSocket ); 23 UdpSocket( int iUdpSocket );
24 UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ); 24 UdpSocket( const Bu::String &sAddr, int iPort, int iFlags );
25 virtual ~UdpSocket(); 25 virtual ~UdpSocket();
26 26
27 typedef uint32_t addr; 27 typedef uint32_t addr;
28 28
29 static Bu::String addrToStr( const addr &a ); 29 static Bu::String addrToStr( const addr &a );
30 30
31 virtual void close(); 31 virtual void close();
32 virtual Bu::size read( void *pBuf, Bu::size nBytes ); 32 virtual Bu::size read( void *pBuf, Bu::size nBytes );
33 virtual Bu::size read( void *pBuf, Bu::size nBytes, 33 virtual Bu::size read( void *pBuf, Bu::size nBytes,
34 addr &sHost, int &iPort ); 34 addr &sHost, int &iPort );
35 virtual Bu::size write( const void *pBuf, Bu::size nBytes ); 35 virtual Bu::size write( const void *pBuf, Bu::size nBytes );
36 using Stream::write; 36 using Stream::write;
37 37
38 virtual Bu::size tell(); 38 virtual Bu::size tell();
39 virtual void seek( Bu::size offset ); 39 virtual void seek( Bu::size offset );
40 virtual void setPos( Bu::size pos ); 40 virtual void setPos( Bu::size pos );
41 virtual void setPosEnd( Bu::size pos ); 41 virtual void setPosEnd( Bu::size pos );
42 virtual bool isEos(); 42 virtual bool isEos();
43 virtual bool isOpen(); 43 virtual bool isOpen();
44 44
45 virtual void flush(); 45 virtual void flush();
46 46
47 virtual bool canRead(); 47 virtual bool canRead();
48 virtual bool canWrite(); 48 virtual bool canWrite();
49 49
50 virtual bool isReadable(); 50 virtual bool isReadable();
51 virtual bool isWritable(); 51 virtual bool isWritable();
52 virtual bool isSeekable(); 52 virtual bool isSeekable();
53 53
54 virtual bool isBlocking(); 54 virtual bool isBlocking();
55 virtual void setBlocking( bool bBlocking=true ); 55 virtual void setBlocking( bool bBlocking=true );
56 56
57 virtual void setSize( Bu::size iSize ); 57 virtual void setSize( Bu::size iSize );
58 58
59 enum { 59 enum {
60 // Flags 60 // Flags
61 Read = 0x01, ///< Open udp socket for reading 61 Read = 0x01, ///< Open udp socket for reading
62 Write = 0x02, ///< Open udp socket for writing 62 Write = 0x02, ///< Open udp socket for writing
63 ReadWrite = 0x03, ///< Open for both read and write 63 ReadWrite = 0x03, ///< Open for both read and write
64 Broadcast = 0x04, ///< Open for broadcast 64 Broadcast = 0x04, ///< Open for broadcast
65 }; 65 };
66 66
67 virtual size getSize() const; 67 virtual size getSize() const;
68 virtual size getBlockSize() const; 68 virtual size getBlockSize() const;
69 virtual Bu::String getLocation() const; 69 virtual Bu::String getLocation() const;
70 70
71 private: 71 private:
72#ifdef WIN32 72#ifdef WIN32
73 unsigned int iUdpSocket; 73 unsigned int iUdpSocket;
74#else 74#else
75 int iUdpSocket; 75 int iUdpSocket;
76#endif 76#endif
77 void *paTarget; 77 void *paTarget;
78 bool bBound; 78 bool bBound;
79 }; 79 };
80}; 80};
81 81
82#endif 82#endif
diff --git a/src/unstable/url.cpp b/src/unstable/url.cpp
index 3c9da4b..75131af 100644
--- a/src/unstable/url.cpp
+++ b/src/unstable/url.cpp
@@ -13,8 +13,8 @@
13#include <stdlib.h> 13#include <stdlib.h>
14 14
15char Bu::Url::hexcode[] = { 15char Bu::Url::hexcode[] = {
16 '0', '1', '2', '3', '4', '5', '6', '7', 16 '0', '1', '2', '3', '4', '5', '6', '7',
17 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 17 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
18}; 18};
19 19
20Bu::Url::Url() 20Bu::Url::Url()
@@ -23,7 +23,7 @@ Bu::Url::Url()
23 23
24Bu::Url::Url( const Bu::String &sUrl ) 24Bu::Url::Url( const Bu::String &sUrl )
25{ 25{
26 parseUrl( sUrl ); 26 parseUrl( sUrl );
27} 27}
28 28
29Bu::Url::~Url() 29Bu::Url::~Url()
@@ -32,254 +32,254 @@ Bu::Url::~Url()
32 32
33void Bu::Url::parseUrl( const Bu::String &sUrl ) 33void Bu::Url::parseUrl( const Bu::String &sUrl )
34{ 34{
35 clear(); 35 clear();
36 36
37 Bu::String::const_iterator i = sUrl.begin(); 37 Bu::String::const_iterator i = sUrl.begin();
38 parseProtocol( i ); 38 parseProtocol( i );
39 parseUserPass( i ); 39 parseUserPass( i );
40 parseHost( i ); 40 parseHost( i );
41 parsePath( i ); 41 parsePath( i );
42} 42}
43 43
44Bu::String Bu::Url::decode( const Bu::String &sStr ) 44Bu::String Bu::Url::decode( const Bu::String &sStr )
45{ 45{
46 Bu::String sRet; 46 Bu::String sRet;
47 char buf[3] = {0, 0, 0}; 47 char buf[3] = {0, 0, 0};
48 for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) 48 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
49 { 49 {
50 if( *i == '+' ) 50 if( *i == '+' )
51 { 51 {
52 sRet += ' '; 52 sRet += ' ';
53 } 53 }
54 else if( *i == '%' ) 54 else if( *i == '%' )
55 { 55 {
56 i++; 56 i++;
57 buf[0] = *i; 57 buf[0] = *i;
58 i++; 58 i++;
59 buf[1] = *i; 59 buf[1] = *i;
60 sRet += (char)((unsigned char)strtol( buf, NULL, 16 )); 60 sRet += (char)((unsigned char)strtol( buf, NULL, 16 ));
61 } 61 }
62 else 62 else
63 { 63 {
64 sRet += *i; 64 sRet += *i;
65 } 65 }
66 } 66 }
67 return sRet; 67 return sRet;
68} 68}
69 69
70Bu::String Bu::Url::encode( const Bu::String &sStr ) 70Bu::String Bu::Url::encode( const Bu::String &sStr )
71{ 71{
72 Bu::String sRet; 72 Bu::String sRet;
73 for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) 73 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
74 { 74 {
75 if( *i == ' ' ) 75 if( *i == ' ' )
76 { 76 {
77 sRet += '+'; 77 sRet += '+';
78 } 78 }
79 else if( 79 else if(
80 (*i >= 'A' && *i <= 'Z') || 80 (*i >= 'A' && *i <= 'Z') ||
81 (*i >= 'a' && *i <= 'z') || 81 (*i >= 'a' && *i <= 'z') ||
82 (*i >= '0' && *i <= '9') || 82 (*i >= '0' && *i <= '9') ||
83 (*i == '-' || *i == '_' || *i == '.' || *i == '~') 83 (*i == '-' || *i == '_' || *i == '.' || *i == '~')
84 ) 84 )
85 { 85 {
86 sRet += *i; 86 sRet += *i;
87 } 87 }
88 else 88 else
89 { 89 {
90 unsigned char b = *i; 90 unsigned char b = *i;
91 sRet += '%'; 91 sRet += '%';
92 sRet += hexcode[(b>>4)&0xF]; 92 sRet += hexcode[(b>>4)&0xF];
93 sRet += hexcode[b&0xF]; 93 sRet += hexcode[b&0xF];
94 } 94 }
95 } 95 }
96 return sRet; 96 return sRet;
97} 97}
98 98
99void Bu::Url::parseProtocol( Bu::String::const_iterator &i ) 99void Bu::Url::parseProtocol( Bu::String::const_iterator &i )
100{ 100{
101 Bu::String::const_iterator s = i.find("://", 3); 101 Bu::String::const_iterator s = i.find("://", 3);
102 if( !s ) 102 if( !s )
103 throw Bu::ExceptionBase("No :// in url"); 103 throw Bu::ExceptionBase("No :// in url");
104 Bu::String sTmp( i, s ); 104 Bu::String sTmp( i, s );
105 setProtocol( sTmp ); 105 setProtocol( sTmp );
106 i = s + 3; 106 i = s + 3;
107} 107}
108 108
109void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort ) 109void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort )
110{ 110{
111 sProtocol = sNewProto; 111 sProtocol = sNewProto;
112#ifndef WIN32 112#ifndef WIN32
113 if( bAutoSetPort ) 113 if( bAutoSetPort )
114 { 114 {
115 struct servent *se = getservbyname( sProtocol.getStr(), "tcp" ); 115 struct servent *se = getservbyname( sProtocol.getStr(), "tcp" );
116 if( se ) 116 if( se )
117 { 117 {
118 iPort = ntohs( se->s_port ); 118 iPort = ntohs( se->s_port );
119 } 119 }
120 } 120 }
121#endif 121#endif
122} 122}
123 123
124void Bu::Url::parseUserPass( Bu::String::const_iterator &i ) 124void Bu::Url::parseUserPass( Bu::String::const_iterator &i )
125{ 125{
126 Bu::String::const_iterator s = i.find('@'); 126 Bu::String::const_iterator s = i.find('@');
127 if( !s ) 127 if( !s )
128 return; 128 return;
129 129
130 Bu::String::const_iterator p = i.find(':'); 130 Bu::String::const_iterator p = i.find(':');
131 if( p ) 131 if( p )
132 { 132 {
133 sUser.set( i, p ); 133 sUser.set( i, p );
134 sPass.set( p+1, s ); 134 sPass.set( p+1, s );
135 } 135 }
136 else 136 else
137 { 137 {
138 sUser.set( i, s ); 138 sUser.set( i, s );
139 } 139 }
140 140
141 i = s + 1; 141 i = s + 1;
142} 142}
143 143
144void Bu::Url::parseHost( Bu::String::const_iterator &i ) 144void Bu::Url::parseHost( Bu::String::const_iterator &i )
145{ 145{
146 Bu::String::const_iterator s = i; 146 Bu::String::const_iterator s = i;
147 for( ; s && *s != '/'; s++ ) 147 for( ; s && *s != '/'; s++ )
148 { 148 {
149 if( *s == ':' ) 149 if( *s == ':' )
150 { 150 {
151 sHost.set( i, s ); 151 sHost.set( i, s );
152 i = s + 1; 152 i = s + 1;
153 s = i.find('/'); 153 s = i.find('/');
154 Bu::String sPort( i, s ); 154 Bu::String sPort( i, s );
155 iPort = strtol( sPort.getStr(), NULL, 10 ); 155 iPort = strtol( sPort.getStr(), NULL, 10 );
156 i = s; 156 i = s;
157 return; 157 return;
158 } 158 }
159 } 159 }
160 sHost.set( i, s ); 160 sHost.set( i, s );
161 i = s; 161 i = s;
162} 162}
163 163
164void Bu::Url::parsePath( const Bu::String &sPath ) 164void Bu::Url::parsePath( const Bu::String &sPath )
165{ 165{
166 Bu::String::const_iterator i = sPath.begin(); 166 Bu::String::const_iterator i = sPath.begin();
167 parsePath( i ); 167 parsePath( i );
168} 168}
169 169
170void Bu::Url::parsePath( Bu::String::const_iterator &i ) 170void Bu::Url::parsePath( Bu::String::const_iterator &i )
171{ 171{
172 if( i ) 172 if( i )
173 { 173 {
174 Bu::String::const_iterator s = i.find('?'); 174 Bu::String::const_iterator s = i.find('?');
175 sPath.set( i, s ); 175 sPath.set( i, s );
176 i = s + 1; 176 i = s + 1;
177 if( s ) 177 if( s )
178 { 178 {
179 parseParams( i ); 179 parseParams( i );
180 } 180 }
181 } 181 }
182 else 182 else
183 { 183 {
184 sPath = "/"; 184 sPath = "/";
185 } 185 }
186} 186}
187 187
188void Bu::Url::parseParams( const Bu::String &sQuery ) 188void Bu::Url::parseParams( const Bu::String &sQuery )
189{ 189{
190 Bu::String::const_iterator i = sQuery.begin(); 190 Bu::String::const_iterator i = sQuery.begin();
191 parseParams( i ); 191 parseParams( i );
192} 192}
193 193
194void Bu::Url::parseParams( Bu::String::const_iterator &i ) 194void Bu::Url::parseParams( Bu::String::const_iterator &i )
195{ 195{
196 bool bName = true; 196 bool bName = true;
197 Bu::String sName, sValue; 197 Bu::String sName, sValue;
198 for( Bu::String::const_iterator s = i; s; s++ ) 198 for( Bu::String::const_iterator s = i; s; s++ )
199 { 199 {
200 if( bName ) 200 if( bName )
201 { 201 {
202 if( *s == '&' ) 202 if( *s == '&' )
203 { 203 {
204 sName.set( i, s ); 204 sName.set( i, s );
205 sValue.clear(); 205 sValue.clear();
206 i = s + 1; 206 i = s + 1;
207 addParam( decode( sName ), decode( sValue ) ); 207 addParam( decode( sName ), decode( sValue ) );
208 } 208 }
209 else if( *s == '=' ) 209 else if( *s == '=' )
210 { 210 {
211 sName.set( i, s ); 211 sName.set( i, s );
212 i = s + 1; 212 i = s + 1;
213 bName = false; 213 bName = false;
214 } 214 }
215 } 215 }
216 else 216 else
217 { 217 {
218 if( *s == '&' ) 218 if( *s == '&' )
219 { 219 {
220 sValue.set( i, s ); 220 sValue.set( i, s );
221 i = s + 1; 221 i = s + 1;
222 bName = true; 222 bName = true;
223 addParam( decode( sName ), decode( sValue ) ); 223 addParam( decode( sName ), decode( sValue ) );
224 } 224 }
225 } 225 }
226 } 226 }
227 if( i ) 227 if( i )
228 { 228 {
229 if( bName ) 229 if( bName )
230 { 230 {
231 sName.set( i ); 231 sName.set( i );
232 sValue.clear(); 232 sValue.clear();
233 } 233 }
234 else 234 else
235 { 235 {
236 sValue.set( i ); 236 sValue.set( i );
237 } 237 }
238 addParam( decode( sName ), decode( sValue ) ); 238 addParam( decode( sName ), decode( sValue ) );
239 } 239 }
240} 240}
241 241
242void Bu::Url::addParam( const Bu::String &n, const Bu::String &v ) 242void Bu::Url::addParam( const Bu::String &n, const Bu::String &v )
243{ 243{
244 lParam.append( Param( n, v ) ); 244 lParam.append( Param( n, v ) );
245} 245}
246 246
247void Bu::Url::clear() 247void Bu::Url::clear()
248{ 248{
249 sProtocol.clear(); 249 sProtocol.clear();
250 sUser.clear(); 250 sUser.clear();
251 sPass.clear(); 251 sPass.clear();
252 sHost.clear(); 252 sHost.clear();
253 sPath.clear(); 253 sPath.clear();
254 iPort.clear(); 254 iPort.clear();
255} 255}
256 256
257Bu::String Bu::Url::getFullPath() const 257Bu::String Bu::Url::getFullPath() const
258{ 258{
259 Bu::String sBuf = sPath; 259 Bu::String sBuf = sPath;
260 if( !lParam.isEmpty() ) 260 if( !lParam.isEmpty() )
261 { 261 {
262 for( ParamList::const_iterator i = lParam.begin(); i; i++ ) 262 for( ParamList::const_iterator i = lParam.begin(); i; i++ )
263 { 263 {
264 if( i == lParam.begin() ) 264 if( i == lParam.begin() )
265 sBuf += "?"; 265 sBuf += "?";
266 else 266 else
267 sBuf += "&"; 267 sBuf += "&";
268 268
269 sBuf += encode( (*i).sName ); 269 sBuf += encode( (*i).sName );
270 if( !(*i).sValue.isEmpty() ) 270 if( !(*i).sValue.isEmpty() )
271 { 271 {
272 sBuf += "=" + encode( (*i).sValue ); 272 sBuf += "=" + encode( (*i).sValue );
273 } 273 }
274 } 274 }
275 } 275 }
276 276
277 return sBuf; 277 return sBuf;
278} 278}
279 279
280Bu::String Bu::Url::getUrl() const 280Bu::String Bu::Url::getUrl() const
281{ 281{
282 Bu::String sBuf = sProtocol + "://" + sHost + getFullPath(); 282 Bu::String sBuf = sProtocol + "://" + sHost + getFullPath();
283 return sBuf; 283 return sBuf;
284} 284}
285 285
diff --git a/src/unstable/url.h b/src/unstable/url.h
index 34a335d..3edf94b 100644
--- a/src/unstable/url.h
+++ b/src/unstable/url.h
@@ -13,73 +13,73 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class Url 16 class Url
17 { 17 {
18 public: 18 public:
19 typedef struct Param 19 typedef struct Param
20 { 20 {
21 Param() { } 21 Param() { }
22 Param( const Param &r ) : sName( r.sName ), sValue( r.sValue ) { } 22 Param( const Param &r ) : sName( r.sName ), sValue( r.sValue ) { }
23 Param( const Bu::String &n, const Bu::String &v ) : 23 Param( const Bu::String &n, const Bu::String &v ) :
24 sName( n ), sValue( v ) { } 24 sName( n ), sValue( v ) { }
25 Bu::String sName; 25 Bu::String sName;
26 Bu::String sValue; 26 Bu::String sValue;
27 } Param; 27 } Param;
28 typedef Bu::List<Param> ParamList; 28 typedef Bu::List<Param> ParamList;
29 29
30 public: 30 public:
31 Url(); 31 Url();
32 Url( const Bu::String &sUrl ); 32 Url( const Bu::String &sUrl );
33 virtual ~Url(); 33 virtual ~Url();
34 34
35 void parseUrl( const Bu::String &sUrl ); 35 void parseUrl( const Bu::String &sUrl );
36 void parseParams( const Bu::String &sQuery ); 36 void parseParams( const Bu::String &sQuery );
37 void parseParams( Bu::String::const_iterator &i ); 37 void parseParams( Bu::String::const_iterator &i );
38 void parsePath( const Bu::String &sPath ); 38 void parsePath( const Bu::String &sPath );
39 void parsePath( Bu::String::const_iterator &i ); 39 void parsePath( Bu::String::const_iterator &i );
40 void clear(); 40 void clear();
41 41
42 Bu::String getUrl() const; 42 Bu::String getUrl() const;
43 Bu::String getFullPath() const; 43 Bu::String getFullPath() const;
44 44
45 const Bu::String &getProtocol() const { return sProtocol; } 45 const Bu::String &getProtocol() const { return sProtocol; }
46 const Bu::String &getUser() const { return sUser; } 46 const Bu::String &getUser() const { return sUser; }
47 const Bu::String &getPass() const { return sPass; } 47 const Bu::String &getPass() const { return sPass; }
48 const Bu::String &getHost() const { return sHost; } 48 const Bu::String &getHost() const { return sHost; }
49 const Bu::String &getPath() const { return sPath; } 49 const Bu::String &getPath() const { return sPath; }
50 int getPort() const { return iPort; } 50 int getPort() const { return iPort; }
51 ParamList::const_iterator getParamBegin() const 51 ParamList::const_iterator getParamBegin() const
52 { return lParam.begin(); } 52 { return lParam.begin(); }
53 53
54 void setProtocol( const Bu::String &sNewHost, bool bAutoSetPort=true ); 54 void setProtocol( const Bu::String &sNewHost, bool bAutoSetPort=true );
55 void setUser( const Bu::String &s ) { sUser = s; } 55 void setUser( const Bu::String &s ) { sUser = s; }
56 void setPass( const Bu::String &s ) { sPass = s; } 56 void setPass( const Bu::String &s ) { sPass = s; }
57 void setHost( const Bu::String &s ) { sHost = s; } 57 void setHost( const Bu::String &s ) { sHost = s; }
58 void setPath( const Bu::String &s ) { sPath = s; } 58 void setPath( const Bu::String &s ) { sPath = s; }
59 void setPort( int i ) { iPort = i; } 59 void setPort( int i ) { iPort = i; }
60 void addParam( const Bu::String &n, const Bu::String &v ); 60 void addParam( const Bu::String &n, const Bu::String &v );
61 61
62 bool hasPort() const { return iPort.has(); } 62 bool hasPort() const { return iPort.has(); }
63 63
64 static Bu::String decode( const Bu::String &sStr ); 64 static Bu::String decode( const Bu::String &sStr );
65 static Bu::String encode( const Bu::String &sStr ); 65 static Bu::String encode( const Bu::String &sStr );
66 66
67 private: // Parsing code 67 private: // Parsing code
68 void parseProtocol( Bu::String::const_iterator &i ); 68 void parseProtocol( Bu::String::const_iterator &i );
69 void parseUserPass( Bu::String::const_iterator &i ); 69 void parseUserPass( Bu::String::const_iterator &i );
70 void parseHost( Bu::String::const_iterator &i ); 70 void parseHost( Bu::String::const_iterator &i );
71 71
72 private: 72 private:
73 Bu::String sProtocol; 73 Bu::String sProtocol;
74 Bu::String sUser; 74 Bu::String sUser;
75 Bu::String sPass; 75 Bu::String sPass;
76 Bu::String sHost; 76 Bu::String sHost;
77 Bu::String sPath; 77 Bu::String sPath;
78 Bu::Atom<int> iPort; 78 Bu::Atom<int> iPort;
79 ParamList lParam; 79 ParamList lParam;
80 80
81 static char hexcode[16]; 81 static char hexcode[16];
82 }; 82 };
83}; 83};
84 84
85#endif 85#endif
diff --git a/src/unstable/utfstring.cpp b/src/unstable/utfstring.cpp
index 9fe2d02..421d5fb 100644
--- a/src/unstable/utfstring.cpp
+++ b/src/unstable/utfstring.cpp
@@ -20,12 +20,12 @@ Bu::UtfString::UtfString()
20 20
21Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc ) 21Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc )
22{ 22{
23 set( sInput, eEnc ); 23 set( sInput, eEnc );
24} 24}
25 25
26Bu::UtfString::UtfString( const char *sInput, Encoding eEnc ) 26Bu::UtfString::UtfString( const char *sInput, Encoding eEnc )
27{ 27{
28 set( sInput, eEnc ); 28 set( sInput, eEnc );
29} 29}
30 30
31Bu::UtfString::~UtfString() 31Bu::UtfString::~UtfString()
@@ -34,340 +34,340 @@ Bu::UtfString::~UtfString()
34 34
35Bu::UtfString::iterator Bu::UtfString::begin() 35Bu::UtfString::iterator Bu::UtfString::begin()
36{ 36{
37 return Bu::UtfString::iterator( this, 0 ); 37 return Bu::UtfString::iterator( this, 0 );
38} 38}
39 39
40Bu::UtfString::const_iterator Bu::UtfString::begin() const 40Bu::UtfString::const_iterator Bu::UtfString::begin() const
41{ 41{
42 return Bu::UtfString::const_iterator( this, 0 ); 42 return Bu::UtfString::const_iterator( this, 0 );
43} 43}
44 44
45void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc ) 45void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc )
46{ 46{
47 switch( eEnc ) 47 switch( eEnc )
48 { 48 {
49 case Utf8: 49 case Utf8:
50 setUtf8( sInput ); 50 setUtf8( sInput );
51 break; 51 break;
52 52
53 case Utf16: 53 case Utf16:
54 setUtf16( sInput ); 54 setUtf16( sInput );
55 break; 55 break;
56 56
57 case Utf16be: 57 case Utf16be:
58 setUtf16be( sInput ); 58 setUtf16be( sInput );
59 break; 59 break;
60 60
61 case Utf16le: 61 case Utf16le:
62 setUtf16le( sInput ); 62 setUtf16le( sInput );
63 break; 63 break;
64 64
65 case Utf32: 65 case Utf32:
66 setUtf32( sInput ); 66 setUtf32( sInput );
67 break; 67 break;
68 68
69 case Utf32be: 69 case Utf32be:
70 setUtf32be( sInput ); 70 setUtf32be( sInput );
71 break; 71 break;
72 72
73 case Utf32le: 73 case Utf32le:
74 setUtf32le( sInput ); 74 setUtf32le( sInput );
75 break; 75 break;
76 76
77 case Ucs2: 77 case Ucs2:
78 throw Bu::ExceptionBase("Ucs2 not supported yet."); 78 throw Bu::ExceptionBase("Ucs2 not supported yet.");
79 break; 79 break;
80 80
81 case Ucs4: 81 case Ucs4:
82 throw Bu::ExceptionBase("Ucs4 not supported yet."); 82 throw Bu::ExceptionBase("Ucs4 not supported yet.");
83 break; 83 break;
84 84
85 case GuessEncoding: 85 case GuessEncoding:
86 throw Bu::ExceptionBase("Guessing mode not supported yet."); 86 throw Bu::ExceptionBase("Guessing mode not supported yet.");
87 break; 87 break;
88 } 88 }
89} 89}
90 90
91void Bu::UtfString::append( UtfChar ch ) 91void Bu::UtfString::append( UtfChar ch )
92{ 92{
93 if( ch >= 0x10000 ) 93 if( ch >= 0x10000 )
94 { 94 {
95 ch -= 0x10000; 95 ch -= 0x10000;
96 append16( ((ch>>10)&0x3FF)| 0xD800u ); 96 append16( ((ch>>10)&0x3FF)| 0xD800u );
97 append16( (ch&0x3FF)| 0xDC00u ); 97 append16( (ch&0x3FF)| 0xDC00u );
98 } 98 }
99 else 99 else
100 { 100 {
101 append16( (uint16_t)(ch) ); 101 append16( (uint16_t)(ch) );
102 } 102 }
103} 103}
104 104
105void Bu::UtfString::append( const UtfString &rSrc ) 105void Bu::UtfString::append( const UtfString &rSrc )
106{ 106{
107 aData.append( rSrc.aData ); 107 aData.append( rSrc.aData );
108 iRawLen += rSrc.iRawLen; 108 iRawLen += rSrc.iRawLen;
109 iCharLen += rSrc.iCharLen; 109 iCharLen += rSrc.iCharLen;
110} 110}
111 111
112void Bu::UtfString::setUtf8( const Bu::String &sInput ) 112void Bu::UtfString::setUtf8( const Bu::String &sInput )
113{ 113{
114 static uint8_t lmask[8] = { 114 static uint8_t lmask[8] = {
115 0x00, 115 0x00,
116 0x01, 116 0x01,
117 0x03, 117 0x03,
118 0x07, 118 0x07,
119 0x0f, 119 0x0f,
120 0x1f, 120 0x1f,
121 0x3f, 121 0x3f,
122 0x7f 122 0x7f
123 }; 123 };
124 for( Bu::String::const_iterator i = sInput.begin(); i; i++ ) 124 for( Bu::String::const_iterator i = sInput.begin(); i; i++ )
125 { 125 {
126 if( ((int)(uint8_t)*i)&0x80 ) 126 if( ((int)(uint8_t)*i)&0x80 )
127 { 127 {
128 int iBytes = 1; 128 int iBytes = 1;
129 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { } 129 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { }
130 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1)); 130 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1));
131 for( iBytes--; iBytes >= 1; iBytes-- ) 131 for( iBytes--; iBytes >= 1; iBytes-- )
132 { 132 {
133 i++; 133 i++;
134 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1)); 134 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1));
135 } 135 }
136 append( uPt ); 136 append( uPt );
137 } 137 }
138 else 138 else
139 { 139 {
140 append( (Bu::UtfChar)(*i) ); 140 append( (Bu::UtfChar)(*i) );
141 } 141 }
142 } 142 }
143} 143}
144 144
145void Bu::UtfString::setUtf16( const Bu::String &sInput ) 145void Bu::UtfString::setUtf16( const Bu::String &sInput )
146{ 146{
147// Bu::String::const_iterator i = sInput.begin(); 147// Bu::String::const_iterator i = sInput.begin();
148 if( (uint8_t)*sInput.begin() == 0xFF && 148 if( (uint8_t)*sInput.begin() == 0xFF &&
149 (uint8_t)*(sInput.begin()+1) == 0xFE ) 149 (uint8_t)*(sInput.begin()+1) == 0xFE )
150 { 150 {
151 setUtf16le( sInput ); 151 setUtf16le( sInput );
152 return; 152 return;
153 } 153 }
154 setUtf16be( sInput ); 154 setUtf16be( sInput );
155} 155}
156 156
157void Bu::UtfString::setUtf16be( const Bu::String &sInput ) 157void Bu::UtfString::setUtf16be( const Bu::String &sInput )
158{ 158{
159 Bu::String::const_iterator i = sInput.begin(); 159 Bu::String::const_iterator i = sInput.begin();
160 if( (uint8_t)*sInput.begin() == 0xFE && 160 if( (uint8_t)*sInput.begin() == 0xFE &&
161 (uint8_t)*(sInput.begin()+1) == 0xFF ) 161 (uint8_t)*(sInput.begin()+1) == 0xFF )
162 162
163 { 163 {
164 i += 2; 164 i += 2;
165 sio << "Verified big endian." << sio.nl; 165 sio << "Verified big endian." << sio.nl;
166 } 166 }
167 else 167 else
168 { 168 {
169 sio << "Assuming big endian." << sio.nl; 169 sio << "Assuming big endian." << sio.nl;
170 } 170 }
171 uint16_t hi, lo; 171 uint16_t hi, lo;
172 for( ; i; i++ ) 172 for( ; i; i++ )
173 { 173 {
174 hi = (((uint8_t)*i)<<8) | ((uint8_t)*(++i)); 174 hi = (((uint8_t)*i)<<8) | ((uint8_t)*(++i));
175 append16( hi ); 175 append16( hi );
176 if( (hi&0xD800u) == 0xD800u ) 176 if( (hi&0xD800u) == 0xD800u )
177 { 177 {
178 lo = (((uint8_t)*(++i))<<8) | ((uint8_t)*(++i)); 178 lo = (((uint8_t)*(++i))<<8) | ((uint8_t)*(++i));
179 append16( lo ); 179 append16( lo );
180 } 180 }
181 } 181 }
182} 182}
183 183
184void Bu::UtfString::setUtf16le( const Bu::String &sInput ) 184void Bu::UtfString::setUtf16le( const Bu::String &sInput )
185{ 185{
186 Bu::String::const_iterator i = sInput.begin(); 186 Bu::String::const_iterator i = sInput.begin();
187 if( (uint8_t)*sInput.begin() == 0xFF && 187 if( (uint8_t)*sInput.begin() == 0xFF &&
188 (uint8_t)*(sInput.begin()+1) == 0xFE ) 188 (uint8_t)*(sInput.begin()+1) == 0xFE )
189 { 189 {
190 i += 2; 190 i += 2;
191 sio << "Verified little endian." << sio.nl; 191 sio << "Verified little endian." << sio.nl;
192 } 192 }
193 else 193 else
194 { 194 {
195 sio << "Assuming little endian." << sio.nl; 195 sio << "Assuming little endian." << sio.nl;
196 } 196 }
197 uint16_t hi, lo; 197 uint16_t hi, lo;
198 for( ; i; i++ ) 198 for( ; i; i++ )
199 { 199 {
200 hi = (((uint8_t)*i)) | ((uint8_t)*(++i)<<8); 200 hi = (((uint8_t)*i)) | ((uint8_t)*(++i)<<8);
201 append16( hi ); 201 append16( hi );
202 if( (hi&0xD800u) == 0xD800u ) 202 if( (hi&0xD800u) == 0xD800u )
203 { 203 {
204 lo = (((uint8_t)*(++i))) | ((uint8_t)*(++i)<<8); 204 lo = (((uint8_t)*(++i))) | ((uint8_t)*(++i)<<8);
205 append16( lo ); 205 append16( lo );
206 } 206 }
207 } 207 }
208} 208}
209 209
210void Bu::UtfString::setUtf32( const Bu::String &sInput ) 210void Bu::UtfString::setUtf32( const Bu::String &sInput )
211{ 211{
212 Bu::String::const_iterator i = sInput.begin(); 212 Bu::String::const_iterator i = sInput.begin();
213 if( (uint8_t)*i == 0x00 && 213 if( (uint8_t)*i == 0x00 &&
214 (uint8_t)*(++i) == 0x00 && 214 (uint8_t)*(++i) == 0x00 &&
215 (uint8_t)*(++i) == 0xFF && 215 (uint8_t)*(++i) == 0xFF &&
216 (uint8_t)*(++i) == 0xFE ) 216 (uint8_t)*(++i) == 0xFE )
217 { 217 {
218 setUtf32le( sInput ); 218 setUtf32le( sInput );
219 return; 219 return;
220 } 220 }
221 setUtf32be( sInput ); 221 setUtf32be( sInput );
222} 222}
223 223
224void Bu::UtfString::setUtf32be( const Bu::String &sInput ) 224void Bu::UtfString::setUtf32be( const Bu::String &sInput )
225{ 225{
226 Bu::String::const_iterator i = sInput.begin(); 226 Bu::String::const_iterator i = sInput.begin();
227 if( (uint8_t)*i == 0x00 && 227 if( (uint8_t)*i == 0x00 &&
228 (uint8_t)*(++i) == 0x00 && 228 (uint8_t)*(++i) == 0x00 &&
229 (uint8_t)*(++i) == 0xFE && 229 (uint8_t)*(++i) == 0xFE &&
230 (uint8_t)*(++i) == 0xFF ) 230 (uint8_t)*(++i) == 0xFF )
231 { 231 {
232 i++; 232 i++;
233 sio << "Verified big endian." << sio.nl; 233 sio << "Verified big endian." << sio.nl;
234 } 234 }
235 else 235 else
236 { 236 {
237 i = sInput.begin(); 237 i = sInput.begin();
238 sio << "Assuming big endian." << sio.nl; 238 sio << "Assuming big endian." << sio.nl;
239 } 239 }
240 for( ; i; i++ ) 240 for( ; i; i++ )
241 { 241 {
242 append( (((uint8_t)*i)<<24) | 242 append( (((uint8_t)*i)<<24) |
243 (((uint8_t)*(++i))<<16) | 243 (((uint8_t)*(++i))<<16) |
244 (((uint8_t)*(++i))<<8) | 244 (((uint8_t)*(++i))<<8) |
245 ((uint8_t)*(++i)) 245 ((uint8_t)*(++i))
246 ); 246 );
247 } 247 }
248} 248}
249 249
250void Bu::UtfString::setUtf32le( const Bu::String &sInput ) 250void Bu::UtfString::setUtf32le( const Bu::String &sInput )
251{ 251{
252 Bu::String::const_iterator i = sInput.begin(); 252 Bu::String::const_iterator i = sInput.begin();
253 if( (uint8_t)*i == 0x00 && 253 if( (uint8_t)*i == 0x00 &&
254 (uint8_t)*(++i) == 0x00 && 254 (uint8_t)*(++i) == 0x00 &&
255 (uint8_t)*(++i) == 0xFF && 255 (uint8_t)*(++i) == 0xFF &&
256 (uint8_t)*(++i) == 0xFE ) 256 (uint8_t)*(++i) == 0xFE )
257 { 257 {
258 i++; 258 i++;
259 sio << "Verified little endian." << sio.nl; 259 sio << "Verified little endian." << sio.nl;
260 } 260 }
261 else 261 else
262 { 262 {
263 i = sInput.begin(); 263 i = sInput.begin();
264 sio << "Assuming little endian." << sio.nl; 264 sio << "Assuming little endian." << sio.nl;
265 } 265 }
266 for( ; i; i++ ) 266 for( ; i; i++ )
267 { 267 {
268 append( ((uint8_t)*i) | 268 append( ((uint8_t)*i) |
269 (((uint8_t)*(++i))<<8) | 269 (((uint8_t)*(++i))<<8) |
270 (((uint8_t)*(++i))<<16) | 270 (((uint8_t)*(++i))<<16) |
271 (((uint8_t)*(++i))<<24) 271 (((uint8_t)*(++i))<<24)
272 ); 272 );
273 } 273 }
274} 274}
275 275
276void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const 276void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const
277{ 277{
278 switch( eEnc ) 278 switch( eEnc )
279 { 279 {
280 case Utf8: 280 case Utf8:
281 writeUtf8( sOut ); 281 writeUtf8( sOut );
282 break; 282 break;
283 283
284 case Utf16: 284 case Utf16:
285// writeUtf16( sOut ); 285// writeUtf16( sOut );
286// break; 286// break;
287 287
288 case Utf16be: 288 case Utf16be:
289 writeUtf16be( sOut ); 289 writeUtf16be( sOut );
290 break; 290 break;
291 291
292 case Utf16le: 292 case Utf16le:
293 writeUtf16le( sOut ); 293 writeUtf16le( sOut );
294 break; 294 break;
295 295
296 case Utf32: 296 case Utf32:
297// writeUtf32( sOut ); 297// writeUtf32( sOut );
298// break; 298// break;
299 299
300 case Utf32be: 300 case Utf32be:
301 writeUtf32be( sOut ); 301 writeUtf32be( sOut );
302 break; 302 break;
303 303
304 case Utf32le: 304 case Utf32le:
305 writeUtf32le( sOut ); 305 writeUtf32le( sOut );
306 break; 306 break;
307 307
308 case Ucs2: 308 case Ucs2:
309 throw Bu::ExceptionBase("Ucs2 not supported yet."); 309 throw Bu::ExceptionBase("Ucs2 not supported yet.");
310 break; 310 break;
311 311
312 case Ucs4: 312 case Ucs4:
313 throw Bu::ExceptionBase("Ucs4 not supported yet."); 313 throw Bu::ExceptionBase("Ucs4 not supported yet.");
314 break; 314 break;
315 315
316 case GuessEncoding: 316 case GuessEncoding:
317 throw Bu::ExceptionBase( 317 throw Bu::ExceptionBase(
318 "GuessEncoding is incompatible with encoding."); 318 "GuessEncoding is incompatible with encoding.");
319 break; 319 break;
320 320
321 } 321 }
322} 322}
323 323
324void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const 324void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const
325{ 325{
326 int iPos = 0; 326 int iPos = 0;
327 while( iPos < aData.getSize() ) 327 while( iPos < aData.getSize() )
328 { 328 {
329 uint8_t uByte; 329 uint8_t uByte;
330 Bu::UtfChar chr = nextChar( iPos ); 330 Bu::UtfChar chr = nextChar( iPos );
331 if( chr >= 0x010000 ) 331 if( chr >= 0x010000 )
332 { 332 {
333 // Four bytes 333 // Four bytes
334 // 111 111111 111111 111111 334 // 111 111111 111111 111111
335 uByte = (chr>>18)|0xF0; 335 uByte = (chr>>18)|0xF0;
336 sOut.write( &uByte, 1 ); 336 sOut.write( &uByte, 1 );
337 uByte = ((chr>>12)&0x3F)|0x80; 337 uByte = ((chr>>12)&0x3F)|0x80;
338 sOut.write( &uByte, 1 ); 338 sOut.write( &uByte, 1 );
339 uByte = ((chr>>6)&0x3F)|0x80; 339 uByte = ((chr>>6)&0x3F)|0x80;
340 sOut.write( &uByte, 1 ); 340 sOut.write( &uByte, 1 );
341 uByte = (chr&0x3F)|0x80; 341 uByte = (chr&0x3F)|0x80;
342 sOut.write( &uByte, 1 ); 342 sOut.write( &uByte, 1 );
343 } 343 }
344 else if( chr >= 0x800 ) 344 else if( chr >= 0x800 )
345 { 345 {
346 // Three bytes 346 // Three bytes
347 // 1111 111111 111111 347 // 1111 111111 111111
348 uByte = (chr>>12)|0xE0; 348 uByte = (chr>>12)|0xE0;
349 sOut.write( &uByte, 1 ); 349 sOut.write( &uByte, 1 );
350 uByte = ((chr>>6)&0x3F)|0x80; 350 uByte = ((chr>>6)&0x3F)|0x80;
351 sOut.write( &uByte, 1 ); 351 sOut.write( &uByte, 1 );
352 uByte = (chr&0x3F)|0x80; 352 uByte = (chr&0x3F)|0x80;
353 sOut.write( &uByte, 1 ); 353 sOut.write( &uByte, 1 );
354 } 354 }
355 else if( chr >= 0x80 ) 355 else if( chr >= 0x80 )
356 { 356 {
357 // Two bytes 357 // Two bytes
358 // 11111 111111 358 // 11111 111111
359 uByte = (chr>>6)|0xC0; 359 uByte = (chr>>6)|0xC0;
360 sOut.write( &uByte, 1 ); 360 sOut.write( &uByte, 1 );
361 uByte = (chr&0x3F)|0x80; 361 uByte = (chr&0x3F)|0x80;
362 sOut.write( &uByte, 1 ); 362 sOut.write( &uByte, 1 );
363 } 363 }
364 else 364 else
365 { 365 {
366 // One byte 366 // One byte
367 uByte = chr; 367 uByte = chr;
368 sOut.write( &uByte, 1 ); 368 sOut.write( &uByte, 1 );
369 } 369 }
370 } 370 }
371} 371}
372/* 372/*
373void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) 373void Bu::UtfString::writeUtf16( Bu::Stream &sOut )
@@ -377,228 +377,228 @@ void Bu::UtfString::writeUtf16( Bu::Stream &sOut )
377void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const 377void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const
378{ 378{
379#if BYTE_ORDER == BIG_ENDIAN 379#if BYTE_ORDER == BIG_ENDIAN
380 uint16_t iTmp = 0xFEFF; // Byte Order Marker 380 uint16_t iTmp = 0xFEFF; // Byte Order Marker
381 sOut.write( &iTmp, 2 ); 381 sOut.write( &iTmp, 2 );
382 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 382 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
383 { 383 {
384 iTmp = *i; 384 iTmp = *i;
385 sOut.write( &iTmp, 2 ); 385 sOut.write( &iTmp, 2 );
386 } 386 }
387#else 387#else
388 uint16_t iTmp = 0xFEFF; // Byte Order Marker 388 uint16_t iTmp = 0xFEFF; // Byte Order Marker
389 iTmp = (iTmp>>8) | (iTmp<<8); 389 iTmp = (iTmp>>8) | (iTmp<<8);
390 sOut.write( &iTmp, 2 ); 390 sOut.write( &iTmp, 2 );
391 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 391 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
392 { 392 {
393 iTmp = *i; 393 iTmp = *i;
394 iTmp = (iTmp>>8) | (iTmp<<8); 394 iTmp = (iTmp>>8) | (iTmp<<8);
395 sOut.write( &iTmp, 2 ); 395 sOut.write( &iTmp, 2 );
396 } 396 }
397#endif 397#endif
398} 398}
399 399
400void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const 400void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const
401{ 401{
402#if BYTE_ORDER == LITTLE_ENDIAN 402#if BYTE_ORDER == LITTLE_ENDIAN
403 uint16_t iTmp = 0xFEFF; // Byte Order Marker 403 uint16_t iTmp = 0xFEFF; // Byte Order Marker
404 sOut.write( &iTmp, 2 ); 404 sOut.write( &iTmp, 2 );
405 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 405 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
406 { 406 {
407 iTmp = *i; 407 iTmp = *i;
408 sOut.write( &iTmp, 2 ); 408 sOut.write( &iTmp, 2 );
409 } 409 }
410#else 410#else
411 uint16_t iTmp = 0xFEFF; // Byte Order Marker 411 uint16_t iTmp = 0xFEFF; // Byte Order Marker
412 iTmp = (iTmp>>8) | (iTmp<<8); 412 iTmp = (iTmp>>8) | (iTmp<<8);
413 sOut.write( &iTmp, 2 ); 413 sOut.write( &iTmp, 2 );
414 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 414 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
415 { 415 {
416 iTmp = *i; 416 iTmp = *i;
417 iTmp = (iTmp>>8) | (iTmp<<8); 417 iTmp = (iTmp>>8) | (iTmp<<8);
418 sOut.write( &iTmp, 2 ); 418 sOut.write( &iTmp, 2 );
419 } 419 }
420#endif 420#endif
421} 421}
422 422
423void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const 423void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const
424{ 424{
425#if BYTE_ORDER == BIG_ENDIAN 425#if BYTE_ORDER == BIG_ENDIAN
426 uint32_t iTmp = 0xFEFF; // Byte Order Marker 426 uint32_t iTmp = 0xFEFF; // Byte Order Marker
427 sOut.write( &iTmp, 4 ); 427 sOut.write( &iTmp, 4 );
428 int i = 0; 428 int i = 0;
429 while( i < aData.getSize() ) 429 while( i < aData.getSize() )
430 { 430 {
431 iTmp = nextChar( i ); 431 iTmp = nextChar( i );
432 sOut.write( &iTmp, 4 ); 432 sOut.write( &iTmp, 4 );
433 } 433 }
434#else 434#else
435 uint32_t iTmp = 0xFEFF; // Byte Order Marker 435 uint32_t iTmp = 0xFEFF; // Byte Order Marker
436 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 436 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
437 sOut.write( &iTmp, 4 ); 437 sOut.write( &iTmp, 4 );
438 int i = 0; 438 int i = 0;
439 while( i < aData.getSize() ) 439 while( i < aData.getSize() )
440 { 440 {
441 iTmp = nextChar( i ); 441 iTmp = nextChar( i );
442 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 442 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
443 sOut.write( &iTmp, 4 ); 443 sOut.write( &iTmp, 4 );
444 } 444 }
445#endif 445#endif
446} 446}
447 447
448void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const 448void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const
449{ 449{
450#if BYTE_ORDER == LITTLE_ENDIAN 450#if BYTE_ORDER == LITTLE_ENDIAN
451 uint32_t iTmp = 0xFEFF; // Byte Order Marker 451 uint32_t iTmp = 0xFEFF; // Byte Order Marker
452 sOut.write( &iTmp, 4 ); 452 sOut.write( &iTmp, 4 );
453 int i = 0; 453 int i = 0;
454 while( i < aData.getSize() ) 454 while( i < aData.getSize() )
455 { 455 {
456 iTmp = nextChar( i ); 456 iTmp = nextChar( i );
457 sOut.write( &iTmp, 4 ); 457 sOut.write( &iTmp, 4 );
458 } 458 }
459#else 459#else
460 uint32_t iTmp = 0xFEFF; // Byte Order Marker 460 uint32_t iTmp = 0xFEFF; // Byte Order Marker
461 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 461 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
462 sOut.write( &iTmp, 4 ); 462 sOut.write( &iTmp, 4 );
463 int i = 0; 463 int i = 0;
464 while( i < aData.getSize() ) 464 while( i < aData.getSize() )
465 { 465 {
466 iTmp = nextChar( i ); 466 iTmp = nextChar( i );
467 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 467 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
468 sOut.write( &iTmp, 4 ); 468 sOut.write( &iTmp, 4 );
469 } 469 }
470#endif 470#endif
471} 471}
472 472
473Bu::UtfChar Bu::UtfString::get( int iIndex ) const 473Bu::UtfChar Bu::UtfString::get( int iIndex ) const
474{ 474{
475 return nextChar( iIndex ); 475 return nextChar( iIndex );
476} 476}
477 477
478Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const 478Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const
479{ 479{
480 Bu::UtfChar i = aData[iIndex++]; 480 Bu::UtfChar i = aData[iIndex++];
481 switch( i&0xFC00 ) 481 switch( i&0xFC00 )
482 { 482 {
483 case 0xD800: 483 case 0xD800:
484 return (((i&0x3FF)<<10) | ((aData[iIndex++]&0x3FF)))+0x10000; 484 return (((i&0x3FF)<<10) | ((aData[iIndex++]&0x3FF)))+0x10000;
485 485
486 case 0xDC00: 486 case 0xDC00:
487 return (((aData[iIndex-2]&0x3FF)<<10) | ((i&0x3FF)))+0x10000; 487 return (((aData[iIndex-2]&0x3FF)<<10) | ((i&0x3FF)))+0x10000;
488 488
489 default: 489 default:
490 return i; 490 return i;
491 } 491 }
492} 492}
493 493
494bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const 494bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const
495{ 495{
496 return aData == rhs.aData; 496 return aData == rhs.aData;
497} 497}
498 498
499Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs ) 499Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs )
500{ 500{
501 append( rhs ); 501 append( rhs );
502 return *this; 502 return *this;
503} 503}
504 504
505Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs ) 505Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs )
506{ 506{
507 append( rhs ); 507 append( rhs );
508 return *this; 508 return *this;
509} 509}
510 510
511Bu::String Bu::UtfString::get( Encoding eEnc ) const 511Bu::String Bu::UtfString::get( Encoding eEnc ) const
512{ 512{
513 Bu::MemBuf mb; 513 Bu::MemBuf mb;
514 write( mb, eEnc ); 514 write( mb, eEnc );
515 return mb.getString(); 515 return mb.getString();
516} 516}
517 517
518void Bu::UtfString::debug() const 518void Bu::UtfString::debug() const
519{ 519{
520 sio << "Raw Utf16: "; 520 sio << "Raw Utf16: ";
521 for( int i = 0; i < aData.getSize(); i++ ) 521 for( int i = 0; i < aData.getSize(); i++ )
522 { 522 {
523 if( i > 0 ) 523 if( i > 0 )
524 sio << ", "; 524 sio << ", ";
525 sio << "0x" << Fmt::hex() << aData[i]; 525 sio << "0x" << Fmt::hex() << aData[i];
526 } 526 }
527 sio << sio.nl; 527 sio << sio.nl;
528 sio << "Code Points: "; 528 sio << "Code Points: ";
529 for( int i = 0; i < aData.getSize(); i++ ) 529 for( int i = 0; i < aData.getSize(); i++ )
530 { 530 {
531 if( i > 0 ) 531 if( i > 0 )
532 sio << ", "; 532 sio << ", ";
533 sio << "0x" << Fmt::hex() << nextChar( i ); 533 sio << "0x" << Fmt::hex() << nextChar( i );
534 } 534 }
535 sio << sio.nl; 535 sio << sio.nl;
536} 536}
537/* 537/*
538void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 ) 538void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 )
539{ 539{
540 static uint8_t lmask[8] = { 540 static uint8_t lmask[8] = {
541 0x00, 541 0x00,
542 0x01, 542 0x01,
543 0x03, 543 0x03,
544 0x07, 544 0x07,
545 0x0f, 545 0x0f,
546 0x1f, 546 0x1f,
547 0x3f, 547 0x3f,
548 0x7f 548 0x7f
549 }; 549 };
550 for( Bu::String::const_iterator i = sUtf8.begin(); i; i++ ) 550 for( Bu::String::const_iterator i = sUtf8.begin(); i; i++ )
551 { 551 {
552 if( i != sUtf8.begin() ) 552 if( i != sUtf8.begin() )
553 sio << ", "; 553 sio << ", ";
554 if( ((int)(uint8_t)*i)&0x80 ) 554 if( ((int)(uint8_t)*i)&0x80 )
555 { 555 {
556// sio << "Flag byte: " << Bu::Fmt().radix(2).width(8).fill('0') 556// sio << "Flag byte: " << Bu::Fmt().radix(2).width(8).fill('0')
557// << (int)(uint8_t)*i << sio.nl; 557// << (int)(uint8_t)*i << sio.nl;
558 int iBytes = 1; 558 int iBytes = 1;
559 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { } 559 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { }
560// sio << "iBytes = " << iBytes << sio.nl; 560// sio << "iBytes = " << iBytes << sio.nl;
561 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1)); 561 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1));
562// sio << "mask: " << Bu::Fmt().radix(2).width(8).fill('0') 562// sio << "mask: " << Bu::Fmt().radix(2).width(8).fill('0')
563// << (int)lmask[7-iBytes] << sio.nl; 563// << (int)lmask[7-iBytes] << sio.nl;
564 for( iBytes--; iBytes >= 1; iBytes-- ) 564 for( iBytes--; iBytes >= 1; iBytes-- )
565 { 565 {
566// sio << "iBytes = " << iBytes << ", shift = " << (6*(iBytes-1)) 566// sio << "iBytes = " << iBytes << ", shift = " << (6*(iBytes-1))
567// << sio.nl; 567// << sio.nl;
568// sio << "next: " << Bu::Fmt().radix(2).width(8).fill('0') 568// sio << "next: " << Bu::Fmt().radix(2).width(8).fill('0')
569// << (int)(uint8_t)*i << sio.nl 569// << (int)(uint8_t)*i << sio.nl
570// << "mask: " << Bu::Fmt().radix(2).width(8).fill('0') 570// << "mask: " << Bu::Fmt().radix(2).width(8).fill('0')
571// << (int)lmask[6] << sio.nl; 571// << (int)lmask[6] << sio.nl;
572 i++; 572 i++;
573 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1)); 573 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1));
574 } 574 }
575 sio << uPt; 575 sio << uPt;
576// sio << " (" << Bu::Fmt( 8, 2 ).fill('0') 576// sio << " (" << Bu::Fmt( 8, 2 ).fill('0')
577// << uPt << ")"; 577// << uPt << ")";
578 } 578 }
579 else 579 else
580 { 580 {
581 sio << (int)((uint8_t)*i); 581 sio << (int)((uint8_t)*i);
582 } 582 }
583 } 583 }
584 sio << sio.nl; 584 sio << sio.nl;
585} 585}
586*/ 586*/
587 587
588template<> uint32_t Bu::__calcHashCode<Bu::UtfString>( const Bu::UtfString &k ) 588template<> uint32_t Bu::__calcHashCode<Bu::UtfString>( const Bu::UtfString &k )
589{ 589{
590 uint32_t uCode = 0; 590 uint32_t uCode = 0;
591 591
592 for( Bu::UtfString::const_iterator i = k.begin(); i; i++ ) 592 for( Bu::UtfString::const_iterator i = k.begin(); i; i++ )
593 { 593 {
594 uCode = *i + (uCode<<6) + (uCode<<16) - uCode; 594 uCode = *i + (uCode<<6) + (uCode<<16) - uCode;
595 } 595 }
596 596
597 return uCode; 597 return uCode;
598} 598}
599 599
600template<> bool Bu::__cmpHashKeys<Bu::UtfString>( 600template<> bool Bu::__cmpHashKeys<Bu::UtfString>(
601 const Bu::UtfString &a, const Bu::UtfString &b ) 601 const Bu::UtfString &a, const Bu::UtfString &b )
602{ 602{
603 return a == b; 603 return a == b;
604} 604}
diff --git a/src/unstable/utfstring.h b/src/unstable/utfstring.h
index 1bd4cce..560faae 100644
--- a/src/unstable/utfstring.h
+++ b/src/unstable/utfstring.h
@@ -13,247 +13,247 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class String; 16 class String;
17 class Stream; 17 class Stream;
18 18
19 /** 19 /**
20 * UtfChar isn't actually a character, unicode specifies "code points" not 20 * UtfChar isn't actually a character, unicode specifies "code points" not
21 * characters. The main reason for this is that not all code points define 21 * characters. The main reason for this is that not all code points define
22 * usable characters. Some control text directionality, some apply 22 * usable characters. Some control text directionality, some apply
23 * properties to other code points which are characters. However, most of 23 * properties to other code points which are characters. However, most of
24 * these distinctions are only important when implementing displays that 24 * these distinctions are only important when implementing displays that
25 * comply with the Unicode standard fully. 25 * comply with the Unicode standard fully.
26 */ 26 */
27 typedef uint32_t UtfChar; 27 typedef uint32_t UtfChar;
28 28
29 /** 29 /**
30 * A unicode string. This class represents a string of unicode code points. 30 * A unicode string. This class represents a string of unicode code points.
31 * Every character in unicode can be represented with 21 bits, but we don't 31 * Every character in unicode can be represented with 21 bits, but we don't
32 * have a datatype that's 24 bits long, so we return all code points as a 32 * have a datatype that's 24 bits long, so we return all code points as a
33 * 32 bit unsigned value represented by Bu::UtfChar. However, the UtfString 33 * 32 bit unsigned value represented by Bu::UtfChar. However, the UtfString
34 * class, for efficiency purposes doesn't store 32 bit values internally. 34 * class, for efficiency purposes doesn't store 32 bit values internally.
35 * It represents all code points in the native utf16 encodeng. This means 35 * It represents all code points in the native utf16 encodeng. This means
36 * that it may be very difficult to quickly determine the length of a 36 * that it may be very difficult to quickly determine the length of a
37 * UtfString in code points. Unlike many Unicode handling systems, this 37 * UtfString in code points. Unlike many Unicode handling systems, this
38 * one actually works with complete code points. When using this class you 38 * one actually works with complete code points. When using this class you
39 * don't ever have to know about the inner workings of the different 39 * don't ever have to know about the inner workings of the different
40 * encoding schemes. All of the data is dealt with as whole code points. 40 * encoding schemes. All of the data is dealt with as whole code points.
41 * 41 *
42 * As an aside, this means that when encoding a UtfString to a Utf16 42 * As an aside, this means that when encoding a UtfString to a Utf16
43 * encoding that matches your archetecture this operation will be very 43 * encoding that matches your archetecture this operation will be very
44 * fast since it will effectively be a raw dump of the internal data 44 * fast since it will effectively be a raw dump of the internal data
45 * structures. However, it is highly reccomended that you DO NOT use the 45 * structures. However, it is highly reccomended that you DO NOT use the
46 * little endian encodings if you can possibly avoid it. They are not 46 * little endian encodings if you can possibly avoid it. They are not
47 * reccomended by the Unicode Consortium and are mainly supported as a 47 * reccomended by the Unicode Consortium and are mainly supported as a
48 * means of communicating with other systems that encode their data 48 * means of communicating with other systems that encode their data
49 * incorrectly. That said, whenever UtfString encodes the contained string 49 * incorrectly. That said, whenever UtfString encodes the contained string
50 * it always includes a BOM at the begining (the byte order marker) so that 50 * it always includes a BOM at the begining (the byte order marker) so that
51 * proper byte order can be easily determined by the program reading the 51 * proper byte order can be easily determined by the program reading the
52 * data. 52 * data.
53 * 53 *
54 *@todo Investigate http://www.unicode.org/reports/tr6/ for compression. 54 *@todo Investigate http://www.unicode.org/reports/tr6/ for compression.
55 */ 55 */
56 class UtfString 56 class UtfString
57 { 57 {
58 public: 58 public:
59 enum Encoding 59 enum Encoding
60 { 60 {
61 Utf8, 61 Utf8,
62 Utf16, 62 Utf16,
63 Utf16be, 63 Utf16be,
64 Utf16le, 64 Utf16le,
65 Utf32, 65 Utf32,
66 Utf32be, 66 Utf32be,
67 Utf32le, 67 Utf32le,
68 Ucs2, 68 Ucs2,
69 Ucs4, 69 Ucs4,
70 GuessEncoding 70 GuessEncoding
71 }; 71 };
72 72
73 UtfString(); 73 UtfString();
74 UtfString( const Bu::String &sInput, Encoding eEnc=Utf8 ); 74 UtfString( const Bu::String &sInput, Encoding eEnc=Utf8 );
75 UtfString( const char *sInput, Encoding eEnc=Utf8 ); 75 UtfString( const char *sInput, Encoding eEnc=Utf8 );
76 virtual ~UtfString(); 76 virtual ~UtfString();
77 77
78 class iterator 78 class iterator
79 { 79 {
80 friend class UtfString; 80 friend class UtfString;
81 private: 81 private:
82 iterator( UtfString *pSrc, int iCodePos ) : 82 iterator( UtfString *pSrc, int iCodePos ) :
83 pSrc( pSrc ), iCodePos( iCodePos ) 83 pSrc( pSrc ), iCodePos( iCodePos )
84 { 84 {
85 } 85 }
86 86
87 public: 87 public:
88 iterator() : 88 iterator() :
89 pSrc( NULL ), iCodePos( 0 ) 89 pSrc( NULL ), iCodePos( 0 )
90 { 90 {
91 } 91 }
92 92
93 UtfChar operator*() 93 UtfChar operator*()
94 { 94 {
95 if( !pSrc ) 95 if( !pSrc )
96 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); 96 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced.");
97 return pSrc->get( iCodePos ); 97 return pSrc->get( iCodePos );
98 } 98 }
99 99
100 iterator operator++() 100 iterator operator++()
101 { 101 {
102 pSrc->nextChar( iCodePos ); 102 pSrc->nextChar( iCodePos );
103 return *this; 103 return *this;
104 } 104 }
105 105
106 iterator operator++( int ) 106 iterator operator++( int )
107 { 107 {
108 pSrc->nextChar( iCodePos ); 108 pSrc->nextChar( iCodePos );
109 return *this; 109 return *this;
110 } 110 }
111 111
112 operator bool() const 112 operator bool() const
113 { 113 {
114 return iCodePos < pSrc->aData.getSize(); 114 return iCodePos < pSrc->aData.getSize();
115 } 115 }
116 116
117 private: 117 private:
118 UtfString *pSrc; 118 UtfString *pSrc;
119 int iCodePos; 119 int iCodePos;
120 }; 120 };
121 121
122 class const_iterator 122 class const_iterator
123 { 123 {
124 friend class UtfString; 124 friend class UtfString;
125 private: 125 private:
126 const_iterator( const UtfString *pSrc, int iCodePos ) : 126 const_iterator( const UtfString *pSrc, int iCodePos ) :
127 pSrc( pSrc ), iCodePos( iCodePos ) 127 pSrc( pSrc ), iCodePos( iCodePos )
128 { 128 {
129 } 129 }
130 130
131 public: 131 public:
132 const_iterator() : 132 const_iterator() :
133 pSrc( NULL ), iCodePos( 0 ) 133 pSrc( NULL ), iCodePos( 0 )
134 { 134 {
135 } 135 }
136 136
137 UtfChar operator*() 137 UtfChar operator*()
138 { 138 {
139 if( !pSrc ) 139 if( !pSrc )
140 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); 140 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced.");
141 return pSrc->get( iCodePos ); 141 return pSrc->get( iCodePos );
142 } 142 }
143 143
144 const_iterator operator++() 144 const_iterator operator++()
145 { 145 {
146 pSrc->nextChar( iCodePos ); 146 pSrc->nextChar( iCodePos );
147 return *this; 147 return *this;
148 } 148 }
149 149
150 const_iterator operator++( int ) 150 const_iterator operator++( int )
151 { 151 {
152 pSrc->nextChar( iCodePos ); 152 pSrc->nextChar( iCodePos );
153 return *this; 153 return *this;
154 } 154 }
155 155
156 operator bool() const 156 operator bool() const
157 { 157 {
158 return iCodePos < pSrc->aData.getSize(); 158 return iCodePos < pSrc->aData.getSize();
159 } 159 }
160 160
161 private: 161 private:
162 const UtfString *pSrc; 162 const UtfString *pSrc;
163 int iCodePos; 163 int iCodePos;
164 }; 164 };
165 165
166 iterator begin(); 166 iterator begin();
167 const_iterator begin() const; 167 const_iterator begin() const;
168 168
169 /** 169 /**
170 * Append a UtfChar (A unicode code point) to the string. This can be 170 * Append a UtfChar (A unicode code point) to the string. This can be
171 * any valid code point, and is just the value of the code point, no 171 * any valid code point, and is just the value of the code point, no
172 * encoding necessary. 172 * encoding necessary.
173 */ 173 */
174 void append( UtfChar ch ); 174 void append( UtfChar ch );
175 175
176 void append( const UtfString &rSrc ); 176 void append( const UtfString &rSrc );
177 177
178 /** 178 /**
179 * Set the value of the entire string based on the given input and 179 * Set the value of the entire string based on the given input and
180 * encoding. The default encoding is Utf8, which is compatible with 180 * encoding. The default encoding is Utf8, which is compatible with
181 * 7-bit ascii, so it's a great choice for setting UtfStrings from 181 * 7-bit ascii, so it's a great choice for setting UtfStrings from
182 * string literals in code. 182 * string literals in code.
183 */ 183 */
184 void set( const Bu::String &sInput, Encoding eEnc=Utf8 ); 184 void set( const Bu::String &sInput, Encoding eEnc=Utf8 );
185 185
186 /** 186 /**
187 * This encodes the UtfString in the given encoding and outputs it to 187 * This encodes the UtfString in the given encoding and outputs it to
188 * the provided stream. all Utf16 and Utf32 encodings will have the 188 * the provided stream. all Utf16 and Utf32 encodings will have the
189 * correct BOM (byte order marker) at the begining. 189 * correct BOM (byte order marker) at the begining.
190 */ 190 */
191 void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ) const; 191 void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ) const;
192 192
193 /** 193 /**
194 * This encodes the UtfString in the given encoding and returns it as 194 * This encodes the UtfString in the given encoding and returns it as
195 * a binary Bu::String. Like write, this also includes the proper BOM 195 * a binary Bu::String. Like write, this also includes the proper BOM
196 * at the begining. 196 * at the begining.
197 */ 197 */
198 Bu::String get( Encoding eEnc=Utf8 ) const; 198 Bu::String get( Encoding eEnc=Utf8 ) const;
199 199
200 void debug() const; 200 void debug() const;
201 201
202 /** 202 /**
203 * This may or may not stick around, given an index, this returns a 203 * This may or may not stick around, given an index, this returns a
204 * codepoint, however there isn't necesarilly a 1:1 ratio between 204 * codepoint, however there isn't necesarilly a 1:1 ratio between
205 * indexes and code points. 205 * indexes and code points.
206 */ 206 */
207 UtfChar get( int iIndex ) const; 207 UtfChar get( int iIndex ) const;
208 208
209 /** 209 /**
210 * This is what to use if you want to iterate through a section of the 210 * This is what to use if you want to iterate through a section of the
211 * UtfString and you want to use a numerical index. In most cases it 211 * UtfString and you want to use a numerical index. In most cases it
212 * will be much easier to use an iterator, though. Given an index this 212 * will be much easier to use an iterator, though. Given an index this
213 * will return the codepoint at that position and increment iIndex an 213 * will return the codepoint at that position and increment iIndex an
214 * appropriate amount for it to point to the next code point. 214 * appropriate amount for it to point to the next code point.
215 */ 215 */
216 UtfChar nextChar( int &iIndex ) const; 216 UtfChar nextChar( int &iIndex ) const;
217 217
218 bool operator==( const Bu::UtfString &rhs ) const; 218 bool operator==( const Bu::UtfString &rhs ) const;
219 UtfString &operator+=( const Bu::UtfString &rhs ); 219 UtfString &operator+=( const Bu::UtfString &rhs );
220 UtfString &operator+=( const UtfChar &rhs ); 220 UtfString &operator+=( const UtfChar &rhs );
221 221
222 private: 222 private:
223 void append16( uint16_t i ) { aData.append( i ); } 223 void append16( uint16_t i ) { aData.append( i ); }
224 224
225 void setUtf8( const Bu::String &sInput ); 225 void setUtf8( const Bu::String &sInput );
226 void setUtf16( const Bu::String &sInput ); 226 void setUtf16( const Bu::String &sInput );
227 void setUtf16be( const Bu::String &sInput ); 227 void setUtf16be( const Bu::String &sInput );
228 void setUtf16le( const Bu::String &sInput ); 228 void setUtf16le( const Bu::String &sInput );
229 void setUtf32( const Bu::String &sInput ); 229 void setUtf32( const Bu::String &sInput );
230 void setUtf32be( const Bu::String &sInput ); 230 void setUtf32be( const Bu::String &sInput );
231 void setUtf32le( const Bu::String &sInput ); 231 void setUtf32le( const Bu::String &sInput );
232 232
233 void writeUtf8( Bu::Stream &sOut ) const; 233 void writeUtf8( Bu::Stream &sOut ) const;
234 void writeUtf16be( Bu::Stream &sOut ) const; 234 void writeUtf16be( Bu::Stream &sOut ) const;
235 void writeUtf16le( Bu::Stream &sOut ) const; 235 void writeUtf16le( Bu::Stream &sOut ) const;
236 void writeUtf32be( Bu::Stream &sOut ) const; 236 void writeUtf32be( Bu::Stream &sOut ) const;
237 void writeUtf32le( Bu::Stream &sOut ) const; 237 void writeUtf32le( Bu::Stream &sOut ) const;
238 238
239 private: 239 private:
240 Bu::Array<uint16_t> aData; 240 Bu::Array<uint16_t> aData;
241 int iRawLen; 241 int iRawLen;
242 int iCharLen; 242 int iCharLen;
243 }; 243 };
244 244
245 // 245 //
246 // Hash support 246 // Hash support
247 // 247 //
248 template<typename T> 248 template<typename T>
249 uint32_t __calcHashCode( const T &k ); 249 uint32_t __calcHashCode( const T &k );
250 250
251 template<typename T> 251 template<typename T>
252 bool __cmpHashKeys( const T &a, const T &b ); 252 bool __cmpHashKeys( const T &a, const T &b );
253 253
254 template<> uint32_t __calcHashCode<UtfString>( const UtfString &k ); 254 template<> uint32_t __calcHashCode<UtfString>( const UtfString &k );
255 template<> bool __cmpHashKeys<UtfString>( 255 template<> bool __cmpHashKeys<UtfString>(
256 const UtfString &a, const UtfString &b ); 256 const UtfString &a, const UtfString &b );
257}; 257};
258 258
259#endif 259#endif
diff --git a/src/unstable/uuid.cpp b/src/unstable/uuid.cpp
index aef8bc0..5400f8f 100644
--- a/src/unstable/uuid.cpp
+++ b/src/unstable/uuid.cpp
@@ -18,25 +18,25 @@
18 18
19Bu::Uuid::Uuid() 19Bu::Uuid::Uuid()
20{ 20{
21 clear(); 21 clear();
22} 22}
23 23
24Bu::Uuid::Uuid( const Uuid &src ) 24Bu::Uuid::Uuid( const Uuid &src )
25{ 25{
26 memcpy( data, src.data, 16 ); 26 memcpy( data, src.data, 16 );
27} 27}
28 28
29Bu::Uuid::Uuid( const Bu::String &sSrc ) 29Bu::Uuid::Uuid( const Bu::String &sSrc )
30{ 30{
31 if( sSrc.getSize() == 16 ) 31 if( sSrc.getSize() == 16 )
32 { 32 {
33 memcpy( data, sSrc.getStr(), 16 ); 33 memcpy( data, sSrc.getStr(), 16 );
34 } 34 }
35 else if( sSrc.getSize() == 36 ) 35 else if( sSrc.getSize() == 36 )
36 { 36 {
37 // Parse it 37 // Parse it
38 set( sSrc ); 38 set( sSrc );
39 } 39 }
40} 40}
41 41
42Bu::Uuid::~Uuid() 42Bu::Uuid::~Uuid()
@@ -45,130 +45,130 @@ Bu::Uuid::~Uuid()
45 45
46Bu::String Bu::Uuid::toRawString() const 46Bu::String Bu::Uuid::toRawString() const
47{ 47{
48 return Bu::String( (char *)data, 16 ); 48 return Bu::String( (char *)data, 16 );
49} 49}
50 50
51Bu::String Bu::Uuid::toString() const 51Bu::String Bu::Uuid::toString() const
52{ 52{
53 Bu::MemBuf mb; 53 Bu::MemBuf mb;
54 Bu::Formatter f( mb ); 54 Bu::Formatter f( mb );
55 55
56 for( int j = 0; j < 16; j++ ) 56 for( int j = 0; j < 16; j++ )
57 { 57 {
58 if( j == 4 || j == 6 || j == 8 || j == 10 ) 58 if( j == 4 || j == 6 || j == 8 || j == 10 )
59 f << '-'; 59 f << '-';
60 f << Bu::Fmt::hex(2).caps(false) << (unsigned int)data[j]; 60 f << Bu::Fmt::hex(2).caps(false) << (unsigned int)data[j];
61 } 61 }
62 62
63 return mb.getString(); 63 return mb.getString();
64} 64}
65 65
66Bu::String Bu::Uuid::toUrn() const 66Bu::String Bu::Uuid::toUrn() const
67{ 67{
68 return "urn:uuid:" + toString(); 68 return "urn:uuid:" + toString();
69} 69}
70 70
71int Bu::Uuid::getVersion() 71int Bu::Uuid::getVersion()
72{ 72{
73 return (data[6]&((8|4|2|1)<<4))>>4; 73 return (data[6]&((8|4|2|1)<<4))>>4;
74} 74}
75 75
76#define msb( i ) (1<<(7-i)) 76#define msb( i ) (1<<(7-i))
77 77
78void Bu::Uuid::clear() 78void Bu::Uuid::clear()
79{ 79{
80 data[7] = msb(0); 80 data[7] = msb(0);
81} 81}
82 82
83Bu::Uuid Bu::Uuid::generate( Bu::Uuid::Type eType ) 83Bu::Uuid Bu::Uuid::generate( Bu::Uuid::Type eType )
84{ 84{
85 switch( eType ) 85 switch( eType )
86 { 86 {
87 case Version1: 87 case Version1:
88 case Version2: 88 case Version2:
89 case Version3: 89 case Version3:
90 case Version4: 90 case Version4:
91 case Version5: 91 case Version5:
92 default: 92 default:
93 case System: 93 case System:
94#if defined(linux) 94#if defined(linux)
95 Bu::File fIn( "/proc/sys/kernel/random/uuid", Bu::File::Read ); 95 Bu::File fIn( "/proc/sys/kernel/random/uuid", Bu::File::Read );
96 char dat[36]; 96 char dat[36];
97 fIn.read( dat, 36 ); 97 fIn.read( dat, 36 );
98 Uuid id; 98 Uuid id;
99 id.set( dat ); 99 id.set( dat );
100 return id; 100 return id;
101#elif defined(WIN32) 101#elif defined(WIN32)
102 UUID uuid; 102 UUID uuid;
103 UuidCreate( &uuid ); 103 UuidCreate( &uuid );
104 Uuid id; 104 Uuid id;
105 id.data[0] = ((unsigned char *)&uuid.Data1)[3]; 105 id.data[0] = ((unsigned char *)&uuid.Data1)[3];
106 id.data[1] = ((unsigned char *)&uuid.Data1)[2]; 106 id.data[1] = ((unsigned char *)&uuid.Data1)[2];
107 id.data[2] = ((unsigned char *)&uuid.Data1)[1]; 107 id.data[2] = ((unsigned char *)&uuid.Data1)[1];
108 id.data[3] = ((unsigned char *)&uuid.Data1)[0]; 108 id.data[3] = ((unsigned char *)&uuid.Data1)[0];
109 id.data[4] = ((unsigned char *)&uuid.Data2)[1]; 109 id.data[4] = ((unsigned char *)&uuid.Data2)[1];
110 id.data[5] = ((unsigned char *)&uuid.Data2)[0]; 110 id.data[5] = ((unsigned char *)&uuid.Data2)[0];
111 id.data[6] = ((unsigned char *)&uuid.Data3)[1]; 111 id.data[6] = ((unsigned char *)&uuid.Data3)[1];
112 id.data[7] = ((unsigned char *)&uuid.Data3)[0]; 112 id.data[7] = ((unsigned char *)&uuid.Data3)[0];
113 memcpy( id.data+8, uuid.Data4, 8 ); 113 memcpy( id.data+8, uuid.Data4, 8 );
114 114
115 return id; 115 return id;
116#else 116#else
117# error We should be using one of the other fallbacks, but your platform is not supported yet. Sorry. 117# error We should be using one of the other fallbacks, but your platform is not supported yet. Sorry.
118#endif 118#endif
119 } 119 }
120} 120}
121 121
122void Bu::Uuid::set( const Bu::String &sSrc ) 122void Bu::Uuid::set( const Bu::String &sSrc )
123{ 123{
124 const char *dat = sSrc.getStr(); 124 const char *dat = sSrc.getStr();
125 int iNibble = 0; 125 int iNibble = 0;
126 memset( data, 0, 16 ); 126 memset( data, 0, 16 );
127 for( int j = 0; j < 36; j++ ) 127 for( int j = 0; j < 36; j++ )
128 { 128 {
129 if( dat[j] == '-' ) 129 if( dat[j] == '-' )
130 continue; 130 continue;
131 unsigned char c = (dat[j]>='0'&&dat[j]<='9')?(dat[j]-'0'):(dat[j]-'a'+10); 131 unsigned char c = (dat[j]>='0'&&dat[j]<='9')?(dat[j]-'0'):(dat[j]-'a'+10);
132 data[iNibble/2] |= (iNibble%2==0)?(c<<4):(c); 132 data[iNibble/2] |= (iNibble%2==0)?(c<<4):(c);
133 iNibble++; 133 iNibble++;
134 } 134 }
135} 135}
136 136
137bool Bu::Uuid::operator==( const Uuid &rhs ) const 137bool Bu::Uuid::operator==( const Uuid &rhs ) const
138{ 138{
139 return memcmp( data, rhs.data, 16 ) == 0; 139 return memcmp( data, rhs.data, 16 ) == 0;
140} 140}
141 141
142bool Bu::Uuid::operator!=( const Uuid &rhs ) const 142bool Bu::Uuid::operator!=( const Uuid &rhs ) const
143{ 143{
144 return !(*this == rhs); 144 return !(*this == rhs);
145} 145}
146 146
147Bu::Uuid &Bu::Uuid::operator=( const Uuid &rhs ) 147Bu::Uuid &Bu::Uuid::operator=( const Uuid &rhs )
148{ 148{
149 memcpy( data, rhs.data, 16 ); 149 memcpy( data, rhs.data, 16 );
150 return *this; 150 return *this;
151} 151}
152 152
153template<> uint32_t Bu::__calcHashCode<Bu::Uuid>( const Bu::Uuid &k ) 153template<> uint32_t Bu::__calcHashCode<Bu::Uuid>( const Bu::Uuid &k )
154{ 154{
155 return __calcHashCode<String>( k.toRawString() ); 155 return __calcHashCode<String>( k.toRawString() );
156} 156}
157 157
158template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid &b ) 158template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid &b )
159{ 159{
160 return a == b; 160 return a == b;
161} 161}
162 162
163Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u ) 163Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u )
164{ 164{
165 ar.read( u.data, 16 ); 165 ar.read( u.data, 16 );
166 return ar; 166 return ar;
167} 167}
168 168
169Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u ) 169Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u )
170{ 170{
171 ar.write( u.data, 16 ); 171 ar.write( u.data, 16 );
172 return ar; 172 return ar;
173} 173}
174 174
diff --git a/src/unstable/uuid.h b/src/unstable/uuid.h
index bb3d608..ecc142d 100644
--- a/src/unstable/uuid.h
+++ b/src/unstable/uuid.h
@@ -13,59 +13,59 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class Uuid 16 class Uuid
17 { 17 {
18 friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); 18 friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u );
19 friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); 19 friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u );
20 public: 20 public:
21 Uuid(); 21 Uuid();
22 Uuid( const Uuid &src ); 22 Uuid( const Uuid &src );
23 Uuid( const Bu::String &sSrc ); 23 Uuid( const Bu::String &sSrc );
24 virtual ~Uuid(); 24 virtual ~Uuid();
25 25
26 Bu::String toRawString() const; 26 Bu::String toRawString() const;
27 Bu::String toString() const; 27 Bu::String toString() const;
28 Bu::String toUrn() const; 28 Bu::String toUrn() const;
29 29
30 enum Type 30 enum Type
31 { 31 {
32 System, 32 System,
33 Version1, 33 Version1,
34 Version2, 34 Version2,
35 Version3, 35 Version3,
36 Version4, 36 Version4,
37 Version5, 37 Version5,
38 }; 38 };
39 39
40 int getVersion(); 40 int getVersion();
41 41
42 static Uuid generate( Type eType = System ); 42 static Uuid generate( Type eType = System );
43 DEPRECATED static Uuid gen() { return generate(); } 43 DEPRECATED static Uuid gen() { return generate(); }
44 44
45 void clear(); 45 void clear();
46 void set( const Bu::String &sSrc ); 46 void set( const Bu::String &sSrc );
47 47
48 bool operator==( const Uuid &rhs ) const; 48 bool operator==( const Uuid &rhs ) const;
49 bool operator!=( const Uuid &rhs ) const; 49 bool operator!=( const Uuid &rhs ) const;
50 Uuid &operator=( const Bu::String &rhs ) { set( rhs ); return *this; } 50 Uuid &operator=( const Bu::String &rhs ) { set( rhs ); return *this; }
51 Uuid &operator=( const Uuid &rhs ); 51 Uuid &operator=( const Uuid &rhs );
52 52
53 private: 53 private:
54 unsigned char data[16]; 54 unsigned char data[16];
55 }; 55 };
56 56
57 template<typename T> 57 template<typename T>
58 uint32_t __calcHashCode( const T &k ); 58 uint32_t __calcHashCode( const T &k );
59 59
60 template<typename T> 60 template<typename T>
61 bool __cmpHashKeys( const T &a, const T &b ); 61 bool __cmpHashKeys( const T &a, const T &b );
62 62
63 template<> uint32_t __calcHashCode<Uuid>( const Uuid &k ); 63 template<> uint32_t __calcHashCode<Uuid>( const Uuid &k );
64 template<> bool __cmpHashKeys<Uuid>( 64 template<> bool __cmpHashKeys<Uuid>(
65 const Uuid &a, const Uuid &b ); 65 const Uuid &a, const Uuid &b );
66 66
67 Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); 67 Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u );
68 Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); 68 Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u );
69}; 69};
70 70
71#endif 71#endif