diff options
Diffstat (limited to '')
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 | ||
17 | Bu::BitString::BitString() | 17 | Bu::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 | ||
24 | Bu::BitString::BitString( const Bu::BitString &xSrc ) | 24 | Bu::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 | ||
35 | Bu::BitString::BitString( long iNewBits, bool bFillRandomly ) | 35 | Bu::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 | ||
61 | Bu::BitString::~BitString() | 61 | Bu::BitString::~BitString() |
62 | { | 62 | { |
63 | if( caData != NULL ) delete[] caData; | 63 | if( caData != NULL ) delete[] caData; |
64 | } | 64 | } |
65 | 65 | ||
66 | Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc ) | 66 | Bu::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 | ||
83 | Bu::BitString Bu::BitString::operator~() | 83 | Bu::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 | ||
97 | Bu::BitString Bu::BitString::operator<<( const long iAmt ) | 97 | Bu::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 | ||
123 | Bu::BitString Bu::BitString::operator>>( const long iAmt ) | 123 | Bu::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 | ||
132 | void Bu::BitString::shiftLeft( long iAmt ) | 132 | void 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 | ||
156 | void Bu::BitString::shiftRight( long iAmt ) | 156 | void 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 | /* |
180 | long Bu::BitString::bitsToBytes( long iBits ) | 180 | long 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 | */ |
185 | void Bu::BitString::fixup() | 185 | void 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 | ||
193 | void Bu::BitString::setBit( long iBit, bool bBitState ) | 193 | void 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 | ||
207 | void Bu::BitString::flipBit( long iBit ) | 207 | void 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 | ||
212 | bool Bu::BitString::getBit( long iBit ) | 212 | bool 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 | ||
222 | long Bu::BitString::getBitLength() | 222 | long Bu::BitString::getBitLength() |
223 | { | 223 | { |
224 | return iBits; | 224 | return iBits; |
225 | } | 225 | } |
226 | 226 | ||
227 | long Bu::BitString::getSize() | 227 | long Bu::BitString::getSize() |
228 | { | 228 | { |
229 | return iBits; | 229 | return iBits; |
230 | } | 230 | } |
231 | 231 | ||
232 | class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper ) | 232 | class 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 | ||
254 | long Bu::BitString::toLong( long iStart, long iSize ) | 254 | long 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 | /* |
268 | std::string Bu::BitString::toString( bool bAddSpacers ) | 268 | std::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 | */ |
306 | void Bu::BitString::clear() | 306 | void 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 | ||
314 | bool Bu::BitString::setBitLength( long iLength, bool bClear ) | 314 | bool Bu::BitString::setBitLength( long iLength, bool bClear ) |
315 | { | 315 | { |
316 | return setSize( iLength, bClear ); | 316 | return setSize( iLength, bClear ); |
317 | } | 317 | } |
318 | 318 | ||
319 | bool Bu::BitString::setSize( long iLength, bool bClear ) | 319 | bool 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 | ||
387 | void Bu::BitString::setMask() | 387 | void 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 | ||
406 | void Bu::BitString::randomize() | 406 | void 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 | ||
418 | void Bu::BitString::invert() | 418 | void 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 | ||
430 | long Bu::BitString::getHighestOrderBitPos() | 430 | long 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 | ||
443 | Bu::String Bu::BitString::toString() | 443 | Bu::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 | /* |
452 | bool Bu::BitString::writeToFile( FILE *fh ) | 452 | bool 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 | ||
460 | bool Bu::BitString::readFromFile( FILE *fh ) | 460 | bool 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 | ||
14 | namespace Bu | 14 | namespace 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 @@ | |||
17 | namespace Bu { subExceptionDef( FifoException ) } | 17 | namespace Bu { subExceptionDef( FifoException ) } |
18 | 18 | ||
19 | Bu::Fifo::Fifo( const Bu::String &sName, int iFlags, mode_t mAcc ) : | 19 | Bu::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 | ||
51 | Bu::Fifo::~Fifo() | 51 | Bu::Fifo::~Fifo() |
52 | { | 52 | { |
53 | close(); | 53 | close(); |
54 | } | 54 | } |
55 | 55 | ||
56 | void Bu::Fifo::close() | 56 | void 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 | ||
70 | Bu::size Bu::Fifo::read( void *pBuf, Bu::size nBytes ) | 70 | Bu::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 | ||
78 | Bu::size Bu::Fifo::write( const void *pBuf, Bu::size nBytes ) | 78 | Bu::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 | ||
86 | Bu::size Bu::Fifo::tell() | 86 | Bu::size Bu::Fifo::tell() |
87 | { | 87 | { |
88 | return -1; | 88 | return -1; |
89 | } | 89 | } |
90 | 90 | ||
91 | void Bu::Fifo::seek( Bu::size ) | 91 | void Bu::Fifo::seek( Bu::size ) |
@@ -102,53 +102,53 @@ void Bu::Fifo::setPosEnd( Bu::size ) | |||
102 | 102 | ||
103 | bool Bu::Fifo::isEos() | 103 | bool Bu::Fifo::isEos() |
104 | { | 104 | { |
105 | return false; | 105 | return false; |
106 | } | 106 | } |
107 | 107 | ||
108 | bool Bu::Fifo::canRead() | 108 | bool Bu::Fifo::canRead() |
109 | { | 109 | { |
110 | return (iIn>-1); | 110 | return (iIn>-1); |
111 | } | 111 | } |
112 | 112 | ||
113 | bool Bu::Fifo::canWrite() | 113 | bool Bu::Fifo::canWrite() |
114 | { | 114 | { |
115 | return (iOut>-1); | 115 | return (iOut>-1); |
116 | } | 116 | } |
117 | 117 | ||
118 | bool Bu::Fifo::isReadable() | 118 | bool Bu::Fifo::isReadable() |
119 | { | 119 | { |
120 | return (iIn>-1); | 120 | return (iIn>-1); |
121 | } | 121 | } |
122 | 122 | ||
123 | bool Bu::Fifo::isWritable() | 123 | bool Bu::Fifo::isWritable() |
124 | { | 124 | { |
125 | return (iOut>-1); | 125 | return (iOut>-1); |
126 | } | 126 | } |
127 | 127 | ||
128 | bool Bu::Fifo::isSeekable() | 128 | bool Bu::Fifo::isSeekable() |
129 | { | 129 | { |
130 | return false; | 130 | return false; |
131 | } | 131 | } |
132 | 132 | ||
133 | bool Bu::Fifo::isBlocking() | 133 | bool 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 | ||
142 | void Bu::Fifo::setBlocking( bool bBlocking ) | 142 | void 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 | ||
154 | void Bu::Fifo::flush() | 154 | void Bu::Fifo::flush() |
@@ -157,6 +157,6 @@ void Bu::Fifo::flush() | |||
157 | 157 | ||
158 | bool Bu::Fifo::isOpen() | 158 | bool 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 | ||
19 | namespace Bu | 19 | namespace 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 | ||
15 | Bu::ItoServer::ItoServer() : | 15 | Bu::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 | ||
22 | Bu::ItoServer::~ItoServer() | 22 | Bu::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 | ||
41 | void Bu::ItoServer::addPort( int nPort, int nPoolSize ) | 41 | void 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 | ||
49 | void Bu::ItoServer::addPort( const String &sAddr, int nPort, int nPoolSize ) | 49 | void 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 | ||
57 | void Bu::ItoServer::setTimeout( int nTimeoutSec, int nTimeoutUSec ) | 57 | void 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 | ||
63 | void Bu::ItoServer::addClient( socket_t nSocket, int nPort ) | 63 | void 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 | ||
75 | void Bu::ItoServer::run() | 75 | void 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 | ||
108 | void Bu::ItoServer::clientCleanup( socket_t iSocket ) | 108 | void 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 | ||
116 | Bu::ItoServer::ItoClient::ItoClient( ItoServer &rSrv, Bu::ItoServer::socket_t iSocket, int iPort, | 116 | Bu::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 | ||
133 | Bu::ItoServer::ItoClient::~ItoClient() | 133 | Bu::ItoServer::ItoClient::~ItoClient() |
@@ -136,67 +136,67 @@ Bu::ItoServer::ItoClient::~ItoClient() | |||
136 | 136 | ||
137 | void Bu::ItoServer::ItoClient::run() | 137 | void 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 | ||
198 | Bu::ItoServer::SrvClientLink::SrvClientLink( ItoClient *pClient ) : | 198 | Bu::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 | ||
207 | void Bu::ItoServer::SrvClientLink::sendMessage( const Bu::String &sMsg ) | 207 | void 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 | ||
222 | Bu::ItoServer::SrvClientLinkFactory::SrvClientLinkFactory( | 222 | Bu::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 | ||
232 | Bu::ClientLink *Bu::ItoServer::SrvClientLinkFactory::createLink( | 232 | Bu::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 | ||
27 | namespace Bu | 27 | namespace 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 | ||
10 | Bu::MiniMacro::MiniMacro() | 10 | Bu::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 | ||
16 | Bu::MiniMacro::MiniMacro( const StrHash &sVarSrc ) | 16 | Bu::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 | ||
24 | Bu::MiniMacro::~MiniMacro() | 24 | Bu::MiniMacro::~MiniMacro() |
@@ -27,161 +27,161 @@ Bu::MiniMacro::~MiniMacro() | |||
27 | 27 | ||
28 | Bu::String Bu::MiniMacro::parse( const Bu::String &sIn ) | 28 | Bu::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 | ||
69 | Bu::String Bu::MiniMacro::parseRepl() | 69 | Bu::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 | ||
104 | Bu::String Bu::MiniMacro::parseCond() | 104 | Bu::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 | ||
111 | Bu::String Bu::MiniMacro::parseCmd() | 111 | Bu::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 | ||
141 | Bu::String Bu::MiniMacro::callFunc( | 141 | Bu::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 | ||
162 | void Bu::MiniMacro::addVar( | 162 | void 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 | ||
168 | bool Bu::MiniMacro::hasVar( const Bu::String &sName ) | 168 | bool Bu::MiniMacro::hasVar( const Bu::String &sName ) |
169 | { | 169 | { |
170 | return hVars.has( sName ); | 170 | return hVars.has( sName ); |
171 | } | 171 | } |
172 | 172 | ||
173 | const Bu::String &Bu::MiniMacro::getVar( const Bu::String &sName ) | 173 | const 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 | ||
178 | const Bu::StrHash &Bu::MiniMacro::getVars() | 178 | const Bu::StrHash &Bu::MiniMacro::getVars() |
179 | { | 179 | { |
180 | return hVars; | 180 | return hVars; |
181 | } | 181 | } |
182 | 182 | ||
183 | int Bu::MiniMacro::getPosition() | 183 | int 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 | ||
14 | namespace Bu | 14 | namespace 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 | ||
20 | namespace Bu { subExceptionDef( MyriadFsException ) } | 20 | namespace 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 | ||
24 | Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : | 24 | Bu::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 | ||
103 | Bu::MyriadFs::~MyriadFs() | 103 | Bu::MyriadFs::~MyriadFs() |
104 | { | 104 | { |
105 | writeHeader(); | 105 | writeHeader(); |
106 | } | 106 | } |
107 | 107 | ||
108 | void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) | 108 | void 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 | ||
116 | Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/, | 116 | Bu::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 | ||
148 | void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms ) | 148 | void 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 | ||
153 | void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, | 153 | void 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 | ||
159 | void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, | 159 | void 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 | ||
190 | void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) | 190 | void 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 | ||
195 | void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget, | 195 | void 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 | ||
226 | void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget, | 226 | void 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 | ||
262 | Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath ) | 262 | Bu::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 | ||
274 | Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) | 274 | Bu::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 | ||
281 | void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime, | 281 | void 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 | ||
292 | void Bu::MyriadFs::unlink( const Bu::String &sPath ) | 292 | void 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 | ||
345 | void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize ) | 345 | void 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 | ||
354 | void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo ) | 354 | void 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 | ||
360 | dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) | 360 | dev_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 | ||
365 | uint32_t Bu::MyriadFs::sysToDev( dev_t uDev ) | 365 | uint32_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 | ||
370 | int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) | 370 | int32_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 | ||
389 | int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, | 389 | int32_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 | ||
435 | void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ) | 435 | void 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 | ||
444 | void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs ) | 444 | void 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 | ||
450 | void Bu::MyriadFs::writeInode( const RawStat &rs, | 450 | void 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 | ||
459 | void Bu::MyriadFs::writeInode( const RawStat &rs ) | 459 | void 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 | ||
465 | Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) | 465 | Bu::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 | ||
492 | Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) | 492 | Bu::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 | ||
509 | void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode, | 509 | void 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 | ||
529 | int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, | 529 | int32_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 | ||
537 | int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) | 537 | int32_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 | ||
593 | void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) | 593 | void 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 | ||
625 | void Bu::MyriadFs::writeHeader() | 625 | void 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 | ||
645 | void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ) | 645 | void 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 | ||
656 | void Bu::MyriadFs::destroyNode( int32_t iNode ) | 656 | void 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 | ||
695 | Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath ) | 695 | Bu::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 | ||
15 | namespace Bu | 15 | namespace 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 | ||
10 | Bu::NewLine::NewLine( Bu::Stream &rNext ) : | 10 | Bu::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 | ||
24 | Bu::size Bu::NewLine::stop() | 24 | Bu::size Bu::NewLine::stop() |
25 | { | 25 | { |
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::size Bu::NewLine::read( void *pBufV, Bu::size iAmnt ) | 29 | Bu::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 | ||
64 | Bu::size Bu::NewLine::write( const void *, Bu::size ) | 64 | Bu::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 | ||
13 | namespace Bu | 13 | namespace 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 | ||
7 | Bu::Settings::Settings( const Bu::UtfString &sCompany, | 7 | Bu::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 | ||
35 | Bu::Settings::~Settings() | 35 | Bu::Settings::~Settings() |
36 | { | 36 | { |
37 | delete pDriver; | 37 | delete pDriver; |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) | 40 | void 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 | ||
45 | Bu::UtfString Bu::Settings::get( const Bu::UtfString &sKey, | 45 | Bu::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 | ||
6 | namespace Bu | 6 | namespace 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 | ||
6 | namespace Bu | 6 | namespace 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 | ||
16 | Bu::SettingsDriverIni::~SettingsDriverIni() | 16 | Bu::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 | ||
33 | void Bu::SettingsDriverIni::init( const Bu::UtfString &sCompany, | 33 | void 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 | ||
81 | void Bu::SettingsDriverIni::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) | 81 | void 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 | ||
122 | Bu::UtfString Bu::SettingsDriverIni::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) | 122 | Bu::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 | ||
8 | namespace Bu | 8 | namespace 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 | ||
13 | Bu::SettingsDriverRegistry::~SettingsDriverRegistry() | 13 | Bu::SettingsDriverRegistry::~SettingsDriverRegistry() |
14 | { | 14 | { |
15 | RegCloseKey( *phKey ); | 15 | RegCloseKey( *phKey ); |
16 | } | 16 | } |
17 | 17 | ||
18 | void Bu::SettingsDriverRegistry::init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ) | 18 | void 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 | ||
28 | void Bu::SettingsDriverRegistry::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) | 28 | void 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 | ||
55 | Bu::UtfString Bu::SettingsDriverRegistry::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) | 55 | Bu::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 | ||
8 | namespace Bu | 8 | namespace 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 | ||
8 | Bu::SettingsDriverTaf::SettingsDriverTaf() : | 8 | Bu::SettingsDriverTaf::SettingsDriverTaf() : |
9 | pRoot( NULL ) | 9 | pRoot( NULL ) |
10 | { | 10 | { |
11 | } | 11 | } |
12 | 12 | ||
13 | Bu::SettingsDriverTaf::~SettingsDriverTaf() | 13 | Bu::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 | ||
24 | void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany, | 24 | void 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 | ||
48 | void Bu::SettingsDriverTaf::set( const Bu::UtfString &sKey, | 48 | void 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 | ||
74 | Bu::UtfString Bu::SettingsDriverTaf::get( const Bu::UtfString &sKey, | 74 | Bu::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 | ||
7 | namespace Bu | 7 | namespace 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 | ||
26 | Bu::UdpSocket::UdpSocket( int iUdpSocket ) : | 26 | Bu::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 | ||
33 | Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) : | 33 | Bu::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 | ||
77 | Bu::UdpSocket::~UdpSocket() | 77 | Bu::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 | ||
84 | Bu::String Bu::UdpSocket::addrToStr( const addr &a ) | 84 | Bu::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 | ||
93 | void Bu::UdpSocket::close() | 93 | void Bu::UdpSocket::close() |
94 | { | 94 | { |
95 | ::close( iUdpSocket ); | 95 | ::close( iUdpSocket ); |
96 | } | 96 | } |
97 | 97 | ||
98 | Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes ) | 98 | Bu::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 | ||
103 | Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes, | 103 | Bu::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 | ||
115 | Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes ) | 115 | Bu::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 | ||
128 | Bu::size Bu::UdpSocket::tell() | 128 | Bu::size Bu::UdpSocket::tell() |
129 | { | 129 | { |
130 | throw Bu::UnsupportedException(); | 130 | throw Bu::UnsupportedException(); |
131 | } | 131 | } |
132 | 132 | ||
133 | void Bu::UdpSocket::seek( Bu::size ) | 133 | void Bu::UdpSocket::seek( Bu::size ) |
134 | { | 134 | { |
135 | throw Bu::UnsupportedException(); | 135 | throw Bu::UnsupportedException(); |
136 | } | 136 | } |
137 | 137 | ||
138 | void Bu::UdpSocket::setPos( Bu::size ) | 138 | void Bu::UdpSocket::setPos( Bu::size ) |
139 | { | 139 | { |
140 | throw Bu::UnsupportedException(); | 140 | throw Bu::UnsupportedException(); |
141 | } | 141 | } |
142 | 142 | ||
143 | void Bu::UdpSocket::setPosEnd( Bu::size ) | 143 | void Bu::UdpSocket::setPosEnd( Bu::size ) |
144 | { | 144 | { |
145 | throw Bu::UnsupportedException(); | 145 | throw Bu::UnsupportedException(); |
146 | } | 146 | } |
147 | 147 | ||
148 | bool Bu::UdpSocket::isEos() | 148 | bool Bu::UdpSocket::isEos() |
149 | { | 149 | { |
150 | return false; | 150 | return false; |
151 | } | 151 | } |
152 | 152 | ||
153 | bool Bu::UdpSocket::isOpen() | 153 | bool Bu::UdpSocket::isOpen() |
154 | { | 154 | { |
155 | return true; | 155 | return true; |
156 | } | 156 | } |
157 | 157 | ||
158 | void Bu::UdpSocket::flush() | 158 | void Bu::UdpSocket::flush() |
@@ -161,79 +161,79 @@ void Bu::UdpSocket::flush() | |||
161 | 161 | ||
162 | bool Bu::UdpSocket::canRead() | 162 | bool Bu::UdpSocket::canRead() |
163 | { | 163 | { |
164 | return bBound; | 164 | return bBound; |
165 | } | 165 | } |
166 | 166 | ||
167 | bool Bu::UdpSocket::canWrite() | 167 | bool Bu::UdpSocket::canWrite() |
168 | { | 168 | { |
169 | return true; | 169 | return true; |
170 | } | 170 | } |
171 | 171 | ||
172 | bool Bu::UdpSocket::isReadable() | 172 | bool Bu::UdpSocket::isReadable() |
173 | { | 173 | { |
174 | return bBound; | 174 | return bBound; |
175 | } | 175 | } |
176 | 176 | ||
177 | bool Bu::UdpSocket::isWritable() | 177 | bool Bu::UdpSocket::isWritable() |
178 | { | 178 | { |
179 | return true; | 179 | return true; |
180 | } | 180 | } |
181 | 181 | ||
182 | bool Bu::UdpSocket::isSeekable() | 182 | bool Bu::UdpSocket::isSeekable() |
183 | { | 183 | { |
184 | return false; | 184 | return false; |
185 | } | 185 | } |
186 | 186 | ||
187 | bool Bu::UdpSocket::isBlocking() | 187 | bool Bu::UdpSocket::isBlocking() |
188 | { | 188 | { |
189 | return true; | 189 | return true; |
190 | } | 190 | } |
191 | 191 | ||
192 | void Bu::UdpSocket::setBlocking( bool bBlocking ) | 192 | void 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 | ||
219 | void Bu::UdpSocket::setSize( Bu::size ) | 219 | void Bu::UdpSocket::setSize( Bu::size ) |
220 | { | 220 | { |
221 | throw Bu::UnsupportedException(); | 221 | throw Bu::UnsupportedException(); |
222 | } | 222 | } |
223 | 223 | ||
224 | Bu::size Bu::UdpSocket::getSize() const | 224 | Bu::size Bu::UdpSocket::getSize() const |
225 | { | 225 | { |
226 | throw Bu::UnsupportedException(); | 226 | throw Bu::UnsupportedException(); |
227 | } | 227 | } |
228 | 228 | ||
229 | Bu::size Bu::UdpSocket::getBlockSize() const | 229 | Bu::size Bu::UdpSocket::getBlockSize() const |
230 | { | 230 | { |
231 | return 1500; | 231 | return 1500; |
232 | } | 232 | } |
233 | 233 | ||
234 | Bu::String Bu::UdpSocket::getLocation() const | 234 | Bu::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 | ||
16 | namespace Bu | 16 | namespace 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 | ||
15 | char Bu::Url::hexcode[] = { | 15 | char 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 | ||
20 | Bu::Url::Url() | 20 | Bu::Url::Url() |
@@ -23,7 +23,7 @@ Bu::Url::Url() | |||
23 | 23 | ||
24 | Bu::Url::Url( const Bu::String &sUrl ) | 24 | Bu::Url::Url( const Bu::String &sUrl ) |
25 | { | 25 | { |
26 | parseUrl( sUrl ); | 26 | parseUrl( sUrl ); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Url::~Url() | 29 | Bu::Url::~Url() |
@@ -32,254 +32,254 @@ Bu::Url::~Url() | |||
32 | 32 | ||
33 | void Bu::Url::parseUrl( const Bu::String &sUrl ) | 33 | void 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 | ||
44 | Bu::String Bu::Url::decode( const Bu::String &sStr ) | 44 | Bu::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 | ||
70 | Bu::String Bu::Url::encode( const Bu::String &sStr ) | 70 | Bu::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 | ||
99 | void Bu::Url::parseProtocol( Bu::String::const_iterator &i ) | 99 | void 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 | ||
109 | void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort ) | 109 | void 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 | ||
124 | void Bu::Url::parseUserPass( Bu::String::const_iterator &i ) | 124 | void 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 | ||
144 | void Bu::Url::parseHost( Bu::String::const_iterator &i ) | 144 | void 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 | ||
164 | void Bu::Url::parsePath( const Bu::String &sPath ) | 164 | void 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 | ||
170 | void Bu::Url::parsePath( Bu::String::const_iterator &i ) | 170 | void 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 | ||
188 | void Bu::Url::parseParams( const Bu::String &sQuery ) | 188 | void 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 | ||
194 | void Bu::Url::parseParams( Bu::String::const_iterator &i ) | 194 | void 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 | ||
242 | void Bu::Url::addParam( const Bu::String &n, const Bu::String &v ) | 242 | void 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 | ||
247 | void Bu::Url::clear() | 247 | void 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 | ||
257 | Bu::String Bu::Url::getFullPath() const | 257 | Bu::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 | ||
280 | Bu::String Bu::Url::getUrl() const | 280 | Bu::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 | ||
14 | namespace Bu | 14 | namespace 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 | ||
21 | Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc ) | 21 | Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc ) |
22 | { | 22 | { |
23 | set( sInput, eEnc ); | 23 | set( sInput, eEnc ); |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::UtfString::UtfString( const char *sInput, Encoding eEnc ) | 26 | Bu::UtfString::UtfString( const char *sInput, Encoding eEnc ) |
27 | { | 27 | { |
28 | set( sInput, eEnc ); | 28 | set( sInput, eEnc ); |
29 | } | 29 | } |
30 | 30 | ||
31 | Bu::UtfString::~UtfString() | 31 | Bu::UtfString::~UtfString() |
@@ -34,340 +34,340 @@ Bu::UtfString::~UtfString() | |||
34 | 34 | ||
35 | Bu::UtfString::iterator Bu::UtfString::begin() | 35 | Bu::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 | ||
40 | Bu::UtfString::const_iterator Bu::UtfString::begin() const | 40 | Bu::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 | ||
45 | void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc ) | 45 | void 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 | ||
91 | void Bu::UtfString::append( UtfChar ch ) | 91 | void 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 | ||
105 | void Bu::UtfString::append( const UtfString &rSrc ) | 105 | void 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 | ||
112 | void Bu::UtfString::setUtf8( const Bu::String &sInput ) | 112 | void 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 | ||
145 | void Bu::UtfString::setUtf16( const Bu::String &sInput ) | 145 | void 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 | ||
157 | void Bu::UtfString::setUtf16be( const Bu::String &sInput ) | 157 | void 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 | ||
184 | void Bu::UtfString::setUtf16le( const Bu::String &sInput ) | 184 | void 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 | ||
210 | void Bu::UtfString::setUtf32( const Bu::String &sInput ) | 210 | void 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 | ||
224 | void Bu::UtfString::setUtf32be( const Bu::String &sInput ) | 224 | void 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 | ||
250 | void Bu::UtfString::setUtf32le( const Bu::String &sInput ) | 250 | void 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 | ||
276 | void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const | 276 | void 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 | ||
324 | void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const | 324 | void 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 | /* |
373 | void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) | 373 | void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) |
@@ -377,228 +377,228 @@ void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) | |||
377 | void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const | 377 | void 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 | ||
400 | void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const | 400 | void 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 | ||
423 | void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const | 423 | void 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 | ||
448 | void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const | 448 | void 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 | ||
473 | Bu::UtfChar Bu::UtfString::get( int iIndex ) const | 473 | Bu::UtfChar Bu::UtfString::get( int iIndex ) const |
474 | { | 474 | { |
475 | return nextChar( iIndex ); | 475 | return nextChar( iIndex ); |
476 | } | 476 | } |
477 | 477 | ||
478 | Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const | 478 | Bu::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 | ||
494 | bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const | 494 | bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const |
495 | { | 495 | { |
496 | return aData == rhs.aData; | 496 | return aData == rhs.aData; |
497 | } | 497 | } |
498 | 498 | ||
499 | Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs ) | 499 | Bu::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 | ||
505 | Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs ) | 505 | Bu::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 | ||
511 | Bu::String Bu::UtfString::get( Encoding eEnc ) const | 511 | Bu::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 | ||
518 | void Bu::UtfString::debug() const | 518 | void 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 | /* |
538 | void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 ) | 538 | void 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 | ||
588 | template<> uint32_t Bu::__calcHashCode<Bu::UtfString>( const Bu::UtfString &k ) | 588 | template<> 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 | ||
600 | template<> bool Bu::__cmpHashKeys<Bu::UtfString>( | 600 | template<> 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 | ||
14 | namespace Bu | 14 | namespace 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 | ||
19 | Bu::Uuid::Uuid() | 19 | Bu::Uuid::Uuid() |
20 | { | 20 | { |
21 | clear(); | 21 | clear(); |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::Uuid::Uuid( const Uuid &src ) | 24 | Bu::Uuid::Uuid( const Uuid &src ) |
25 | { | 25 | { |
26 | memcpy( data, src.data, 16 ); | 26 | memcpy( data, src.data, 16 ); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Uuid::Uuid( const Bu::String &sSrc ) | 29 | Bu::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 | ||
42 | Bu::Uuid::~Uuid() | 42 | Bu::Uuid::~Uuid() |
@@ -45,130 +45,130 @@ Bu::Uuid::~Uuid() | |||
45 | 45 | ||
46 | Bu::String Bu::Uuid::toRawString() const | 46 | Bu::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 | ||
51 | Bu::String Bu::Uuid::toString() const | 51 | Bu::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 | ||
66 | Bu::String Bu::Uuid::toUrn() const | 66 | Bu::String Bu::Uuid::toUrn() const |
67 | { | 67 | { |
68 | return "urn:uuid:" + toString(); | 68 | return "urn:uuid:" + toString(); |
69 | } | 69 | } |
70 | 70 | ||
71 | int Bu::Uuid::getVersion() | 71 | int 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 | ||
78 | void Bu::Uuid::clear() | 78 | void Bu::Uuid::clear() |
79 | { | 79 | { |
80 | data[7] = msb(0); | 80 | data[7] = msb(0); |
81 | } | 81 | } |
82 | 82 | ||
83 | Bu::Uuid Bu::Uuid::generate( Bu::Uuid::Type eType ) | 83 | Bu::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 | ||
122 | void Bu::Uuid::set( const Bu::String &sSrc ) | 122 | void 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 | ||
137 | bool Bu::Uuid::operator==( const Uuid &rhs ) const | 137 | bool 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 | ||
142 | bool Bu::Uuid::operator!=( const Uuid &rhs ) const | 142 | bool Bu::Uuid::operator!=( const Uuid &rhs ) const |
143 | { | 143 | { |
144 | return !(*this == rhs); | 144 | return !(*this == rhs); |
145 | } | 145 | } |
146 | 146 | ||
147 | Bu::Uuid &Bu::Uuid::operator=( const Uuid &rhs ) | 147 | Bu::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 | ||
153 | template<> uint32_t Bu::__calcHashCode<Bu::Uuid>( const Bu::Uuid &k ) | 153 | template<> 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 | ||
158 | template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid &b ) | 158 | template<> 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 | ||
163 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u ) | 163 | Bu::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 | ||
169 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u ) | 169 | Bu::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 | ||
14 | namespace Bu | 14 | namespace 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 |