diff options
255 files changed, 31317 insertions, 31317 deletions
diff --git a/autoconfig.cpp b/autoconfig.cpp index c2649ad..28362ec 100644 --- a/autoconfig.cpp +++ b/autoconfig.cpp | |||
@@ -8,87 +8,87 @@ FILE *fOut = NULL; | |||
8 | 8 | ||
9 | bool testCpp( const char *prog ) | 9 | bool testCpp( const char *prog ) |
10 | { | 10 | { |
11 | FILE *pop = popen("g++ -x c++ - -o /dev/null", "w"); | 11 | FILE *pop = popen("g++ -x c++ - -o /dev/null", "w"); |
12 | fwrite( prog, 1, strlen( prog ), pop ); | 12 | fwrite( prog, 1, strlen( prog ), pop ); |
13 | return pclose(pop) == 0; | 13 | return pclose(pop) == 0; |
14 | } | 14 | } |
15 | 15 | ||
16 | void detectEndianness() | 16 | void detectEndianness() |
17 | { | 17 | { |
18 | printf("Detecting endian support..."); | 18 | printf("Detecting endian support..."); |
19 | fflush( stdout ); | 19 | fflush( stdout ); |
20 | if( testCpp("#include <endian.h>\n\nint main() { return BYTE_ORDER; }\n") ) | 20 | if( testCpp("#include <endian.h>\n\nint main() { return BYTE_ORDER; }\n") ) |
21 | { | 21 | { |
22 | fprintf( fOut, "#include <endian.h>\n\n"); | 22 | fprintf( fOut, "#include <endian.h>\n\n"); |
23 | printf("header file endian.h found, using that.\n"); | 23 | printf("header file endian.h found, using that.\n"); |
24 | } | 24 | } |
25 | else | 25 | else |
26 | { | 26 | { |
27 | uint16_t x=0x0100; | 27 | uint16_t x=0x0100; |
28 | fprintf( fOut, | 28 | fprintf( fOut, |
29 | "#define LITTLE_ENDIAN 0\n" | 29 | "#define LITTLE_ENDIAN 0\n" |
30 | "#define BIG_ENDIAN 1\n" | 30 | "#define BIG_ENDIAN 1\n" |
31 | "#define BYTE_ORDER %d\n\n", | 31 | "#define BYTE_ORDER %d\n\n", |
32 | ((uint8_t *)&x)[0] | 32 | ((uint8_t *)&x)[0] |
33 | ); | 33 | ); |
34 | printf("no header file found, faking it...\n" | 34 | printf("no header file found, faking it...\n" |
35 | "\tArchetecture is: %s Endian\n", | 35 | "\tArchetecture is: %s Endian\n", |
36 | ((uint8_t *)&x)[0]?"Big":"Little" | 36 | ((uint8_t *)&x)[0]?"Big":"Little" |
37 | ); | 37 | ); |
38 | } | 38 | } |
39 | } | 39 | } |
40 | 40 | ||
41 | int main( int argc, char *argv[] ) | 41 | int main( int argc, char *argv[] ) |
42 | { | 42 | { |
43 | if( argc == 1 ) | 43 | if( argc == 1 ) |
44 | { | 44 | { |
45 | fprintf( stderr, | 45 | fprintf( stderr, |
46 | "Invalid usage: specify a file to generate:\n" | 46 | "Invalid usage: specify a file to generate:\n" |
47 | " src/autoconfig.h\n" | 47 | " src/autoconfig.h\n" |
48 | " src/version.h\n" | 48 | " src/version.h\n" |
49 | "\n" | 49 | "\n" |
50 | ); | 50 | ); |
51 | return 127; | 51 | return 127; |
52 | } | 52 | } |
53 | if( strcmp( argv[1], "src/autoconfig.h" ) == 0 ) | 53 | if( strcmp( argv[1], "src/autoconfig.h" ) == 0 ) |
54 | { | 54 | { |
55 | fOut = fopen( argv[1], "w" ); | 55 | fOut = fopen( argv[1], "w" ); |
56 | fprintf( fOut, | 56 | fprintf( fOut, |
57 | "#ifndef BU_AUTO_CONFIG_H\n" | 57 | "#ifndef BU_AUTO_CONFIG_H\n" |
58 | "#define BU_AUTO_CONFIG_H\n\n" | 58 | "#define BU_AUTO_CONFIG_H\n\n" |
59 | ); | 59 | ); |
60 | 60 | ||
61 | detectEndianness(); | 61 | detectEndianness(); |
62 | 62 | ||
63 | fprintf( fOut, "#endif\n"); | 63 | fprintf( fOut, "#endif\n"); |
64 | } | 64 | } |
65 | else if( strcmp( argv[1], "src/version.h" ) == 0 ) | 65 | else if( strcmp( argv[1], "src/version.h" ) == 0 ) |
66 | { | 66 | { |
67 | FILE *fVer = fopen("version", "rt"); | 67 | FILE *fVer = fopen("version", "rt"); |
68 | char buf[1024]; | 68 | char buf[1024]; |
69 | buf[fread( buf, 1, 1024, fVer )] = '\0'; | 69 | buf[fread( buf, 1, 1024, fVer )] = '\0'; |
70 | for( int j = 0; buf[j]; j++ ) | 70 | for( int j = 0; buf[j]; j++ ) |
71 | if( buf[j] == '\n' ) | 71 | if( buf[j] == '\n' ) |
72 | buf[j] = '\0'; | 72 | buf[j] = '\0'; |
73 | fclose( fVer ); | 73 | fclose( fVer ); |
74 | 74 | ||
75 | fOut = fopen( argv[1], "w" ); | 75 | fOut = fopen( argv[1], "w" ); |
76 | fprintf( fOut, | 76 | fprintf( fOut, |
77 | "#ifndef BU_VERSION_H\n" | 77 | "#ifndef BU_VERSION_H\n" |
78 | "#define BU_VERSION_H\n\n" | 78 | "#define BU_VERSION_H\n\n" |
79 | "#define LIBBU_VERSION 0\n" | 79 | "#define LIBBU_VERSION 0\n" |
80 | "#define LIBBU_REVISION 1\n" | 80 | "#define LIBBU_REVISION 1\n" |
81 | "#define LIBBU_VERSION_STR \"%s\"\n" | 81 | "#define LIBBU_VERSION_STR \"%s\"\n" |
82 | "#define LIBBU_API 0\n" | 82 | "#define LIBBU_API 0\n" |
83 | "#define LIBBU_VC_ID \"", | 83 | "#define LIBBU_VC_ID \"", |
84 | buf | 84 | buf |
85 | ); | 85 | ); |
86 | FILE *psub = popen("svnversion -n", "r"); | 86 | FILE *psub = popen("svnversion -n", "r"); |
87 | fwrite( buf, fread( buf, 1, 1024, psub ), 1, fOut ); | 87 | fwrite( buf, fread( buf, 1, 1024, psub ), 1, fOut ); |
88 | pclose( psub ); | 88 | pclose( psub ); |
89 | fprintf( fOut, "\"\n\n#endif\n"); | 89 | fprintf( fOut, "\"\n\n#endif\n"); |
90 | } | 90 | } |
91 | 91 | ||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
diff --git a/default.bld b/default.bld index d46662c..83d2717 100644 --- a/default.bld +++ b/default.bld | |||
@@ -19,117 +19,117 @@ CXXFLAGS += "-ggdb -W -Wall -I."; | |||
19 | 19 | ||
20 | action "default" | 20 | action "default" |
21 | { | 21 | { |
22 | build: ["header-links", "libbu++.a", | 22 | build: ["header-links", "libbu++.a", |
23 | targets("tools")]; | 23 | targets("tools")]; |
24 | } | 24 | } |
25 | 25 | ||
26 | action "pkg" | 26 | action "pkg" |
27 | { | 27 | { |
28 | build: targets("pkg"); | 28 | build: targets("pkg"); |
29 | } | 29 | } |
30 | 30 | ||
31 | action "all" | 31 | action "all" |
32 | { | 32 | { |
33 | build: ["header-links", "libbu++.a", | 33 | build: ["header-links", "libbu++.a", |
34 | targets("tools"), targets("tests")]; | 34 | targets("tools"), targets("tests")]; |
35 | } | 35 | } |
36 | 36 | ||
37 | action "unit" | 37 | action "unit" |
38 | { | 38 | { |
39 | build: targets("unit tests"); | 39 | build: targets("unit tests"); |
40 | } | 40 | } |
41 | 41 | ||
42 | action "myriadfs" | 42 | action "myriadfs" |
43 | { | 43 | { |
44 | build: "myriadfs"; | 44 | build: "myriadfs"; |
45 | } | 45 | } |
46 | 46 | ||
47 | target ["src/autoconfig.h", "src/version.h"] | 47 | target ["src/autoconfig.h", "src/version.h"] |
48 | { | 48 | { |
49 | input "autoconfig"; | 49 | input "autoconfig"; |
50 | display "autoconfig"; | 50 | display "autoconfig"; |
51 | profile "build" | 51 | profile "build" |
52 | { | 52 | { |
53 | execute("./autoconfig ${OUTPUT}"); | 53 | execute("./autoconfig ${OUTPUT}"); |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | target "src/version.h" | 57 | target "src/version.h" |
58 | { | 58 | { |
59 | input ".svn"; | 59 | input ".svn"; |
60 | } | 60 | } |
61 | 61 | ||
62 | target "src/signals.h" | 62 | target "src/signals.h" |
63 | { | 63 | { |
64 | input "gensigs.bld"; | 64 | input "gensigs.bld"; |
65 | display "generate"; | 65 | display "generate"; |
66 | profile "build" | 66 | profile "build" |
67 | { | 67 | { |
68 | genSigs( OUTPUT ); | 68 | genSigs( OUTPUT ); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | 71 | ||
72 | target "autoconfig" | 72 | target "autoconfig" |
73 | { | 73 | { |
74 | rule "exe"; | 74 | rule "exe"; |
75 | input "autoconfig.cpp"; | 75 | input "autoconfig.cpp"; |
76 | } | 76 | } |
77 | 77 | ||
78 | for base in ["stable", "unstable", "experimental"] do | 78 | for base in ["stable", "unstable", "experimental"] do |
79 | { | 79 | { |
80 | target files("src/${base}/*.h").replace("src/${base}/", "bu/") | 80 | target files("src/${base}/*.h").replace("src/${base}/", "bu/") |
81 | { | 81 | { |
82 | tag "header-links"; | 82 | tag "header-links"; |
83 | display "symlink"; | 83 | display "symlink"; |
84 | input OUTPUT.replace("bu/","src/${base}/"); | 84 | input OUTPUT.replace("bu/","src/${base}/"); |
85 | profile "build" | 85 | profile "build" |
86 | { | 86 | { |
87 | DIR = OUTPUT.dirName(); | 87 | DIR = OUTPUT.dirName(); |
88 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); | 88 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); |
89 | } | 89 | } |
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] | 93 | target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] |
94 | { | 94 | { |
95 | tag "header-links"; | 95 | tag "header-links"; |
96 | display "symlink"; | 96 | display "symlink"; |
97 | input OUTPUT.replace("bu/","src/"); | 97 | input OUTPUT.replace("bu/","src/"); |
98 | profile "build" | 98 | profile "build" |
99 | { | 99 | { |
100 | DIR = OUTPUT.dirName(); | 100 | DIR = OUTPUT.dirName(); |
101 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); | 101 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); |
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | target files("src/compat/*.h").replace("src/", "bu/") | 105 | target files("src/compat/*.h").replace("src/", "bu/") |
106 | { | 106 | { |
107 | tag "header-links"; | 107 | tag "header-links"; |
108 | display "symlink"; | 108 | display "symlink"; |
109 | input OUTPUT.replace("bu/","src/"); | 109 | input OUTPUT.replace("bu/","src/"); |
110 | profile "build" | 110 | profile "build" |
111 | { | 111 | { |
112 | DIR = OUTPUT.dirName(); | 112 | DIR = OUTPUT.dirName(); |
113 | execute("mkdir -p ${DIR}; ln -s ../../${INPUT} ${OUTPUT}"); | 113 | execute("mkdir -p ${DIR}; ln -s ../../${INPUT} ${OUTPUT}"); |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
117 | target "header-links" | 117 | target "header-links" |
118 | { | 118 | { |
119 | input targets("header-links"); | 119 | input targets("header-links"); |
120 | display "symlinks"; | 120 | display "symlinks"; |
121 | profile "build" | 121 | profile "build" |
122 | { | 122 | { |
123 | condition always; | 123 | condition always; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | target "libbu++.a" | 127 | target "libbu++.a" |
128 | { | 128 | { |
129 | input files("src/stable/*.cpp", "src/unstable/*.cpp", | 129 | input files("src/stable/*.cpp", "src/unstable/*.cpp", |
130 | "src/experimental/*.cpp", "src/compat/*.cpp"); | 130 | "src/experimental/*.cpp", "src/compat/*.cpp"); |
131 | rule "lib"; | 131 | rule "lib"; |
132 | CXXFLAGS += "-I. -fPIC"; | 132 | CXXFLAGS += "-I. -fPIC"; |
133 | } | 133 | } |
134 | 134 | ||
135 | // | 135 | // |
@@ -138,31 +138,31 @@ target "libbu++.a" | |||
138 | 138 | ||
139 | target files("src/tools/*.cpp").replace("src/tools/","").replace(".cpp","") | 139 | target files("src/tools/*.cpp").replace("src/tools/","").replace(".cpp","") |
140 | { | 140 | { |
141 | input "src/tools/${OUTPUT}.cpp"; | 141 | input "src/tools/${OUTPUT}.cpp"; |
142 | rule "exe"; | 142 | rule "exe"; |
143 | requires "libbu++.a"; | 143 | requires "libbu++.a"; |
144 | tag "tools"; | 144 | tag "tools"; |
145 | CXXFLAGS += "-I."; | 145 | CXXFLAGS += "-I."; |
146 | LDFLAGS += "-L. -lbu++"; | 146 | LDFLAGS += "-L. -lbu++"; |
147 | } | 147 | } |
148 | 148 | ||
149 | target "viewcsv" | 149 | target "viewcsv" |
150 | { | 150 | { |
151 | LDFLAGS += "-lncurses"; | 151 | LDFLAGS += "-lncurses"; |
152 | } | 152 | } |
153 | 153 | ||
154 | target ["myriad", "myriadfs", "tests/myriad", "tests/myriadfs", "unit/myriad", "tests/bigmyriad", "tests/synchroqueue"] | 154 | target ["myriad", "myriadfs", "tests/myriad", "tests/myriadfs", "unit/myriad", "tests/bigmyriad", "tests/synchroqueue"] |
155 | { | 155 | { |
156 | LDFLAGS += "-lpthread"; | 156 | LDFLAGS += "-lpthread"; |
157 | } | 157 | } |
158 | 158 | ||
159 | target files("src/extra/*.cpp").replace("src/extra/","").replace(".cpp","") | 159 | target files("src/extra/*.cpp").replace("src/extra/","").replace(".cpp","") |
160 | { | 160 | { |
161 | input "src/extra/${OUTPUT}.cpp"; | 161 | input "src/extra/${OUTPUT}.cpp"; |
162 | rule "exe"; | 162 | rule "exe"; |
163 | requires "libbu++.a"; | 163 | requires "libbu++.a"; |
164 | CXXFLAGS += "-I."; | 164 | CXXFLAGS += "-I."; |
165 | LDFLAGS += "-L. -lbu++"; | 165 | LDFLAGS += "-L. -lbu++"; |
166 | } | 166 | } |
167 | 167 | ||
168 | // | 168 | // |
@@ -173,17 +173,17 @@ target files("src/extra/*.cpp").replace("src/extra/","").replace(".cpp","") | |||
173 | // | 173 | // |
174 | target "src/extra/myriadfs.o" | 174 | target "src/extra/myriadfs.o" |
175 | { | 175 | { |
176 | CXXFLAGS += "-D_FILE_OFFSET_BITS=64"; | 176 | CXXFLAGS += "-D_FILE_OFFSET_BITS=64"; |
177 | } | 177 | } |
178 | 178 | ||
179 | target "myriadfs" | 179 | target "myriadfs" |
180 | { | 180 | { |
181 | LDFLAGS += "-lfuse"; | 181 | LDFLAGS += "-lfuse"; |
182 | } | 182 | } |
183 | 183 | ||
184 | target "bin2cpp" | 184 | target "bin2cpp" |
185 | { | 185 | { |
186 | LDFLAGS += "-lz -lbz2 -llzma"; | 186 | LDFLAGS += "-lz -lbz2 -llzma"; |
187 | } | 187 | } |
188 | 188 | ||
189 | // | 189 | // |
@@ -192,34 +192,34 @@ target "bin2cpp" | |||
192 | 192 | ||
193 | target files("src/tests/*.cpp").replace("src/","").replace(".cpp","") | 193 | target files("src/tests/*.cpp").replace("src/","").replace(".cpp","") |
194 | { | 194 | { |
195 | input "src/${OUTPUT}.cpp"; | 195 | input "src/${OUTPUT}.cpp"; |
196 | rule "exe"; | 196 | rule "exe"; |
197 | requires "libbu++.a"; | 197 | requires "libbu++.a"; |
198 | tag ["tests", "general tests"]; | 198 | tag ["tests", "general tests"]; |
199 | CXXFLAGS += "-I."; | 199 | CXXFLAGS += "-I."; |
200 | LDFLAGS += "-L. -lbu++"; | 200 | LDFLAGS += "-L. -lbu++"; |
201 | } | 201 | } |
202 | 202 | ||
203 | // Some tests need extra libs and whatnot, that goes here. | 203 | // Some tests need extra libs and whatnot, that goes here. |
204 | 204 | ||
205 | target ["tests/bzip2", "tests/streamstack"] | 205 | target ["tests/bzip2", "tests/streamstack"] |
206 | { | 206 | { |
207 | LDFLAGS += "-lbz2"; | 207 | LDFLAGS += "-lbz2"; |
208 | } | 208 | } |
209 | 209 | ||
210 | target ["tests/deflate", "tests/enc"] | 210 | target ["tests/deflate", "tests/enc"] |
211 | { | 211 | { |
212 | LDFLAGS += "-lz"; | 212 | LDFLAGS += "-lz"; |
213 | } | 213 | } |
214 | 214 | ||
215 | target ["tests/lzma"] | 215 | target ["tests/lzma"] |
216 | { | 216 | { |
217 | LDFLAGS += "-llzma"; | 217 | LDFLAGS += "-llzma"; |
218 | } | 218 | } |
219 | 219 | ||
220 | target ["tests/threadid"] | 220 | target ["tests/threadid"] |
221 | { | 221 | { |
222 | LDFLAGS += "-lpthread"; | 222 | LDFLAGS += "-lpthread"; |
223 | } | 223 | } |
224 | 224 | ||
225 | // | 225 | // |
@@ -228,106 +228,106 @@ target ["tests/threadid"] | |||
228 | 228 | ||
229 | target files("src/unit/*.unit").replace("src/","").replace(".unit","") | 229 | target files("src/unit/*.unit").replace("src/","").replace(".unit","") |
230 | { | 230 | { |
231 | input "src/${OUTPUT}.unit"; | 231 | input "src/${OUTPUT}.unit"; |
232 | rule "exe"; | 232 | rule "exe"; |
233 | requires "libbu++.a"; | 233 | requires "libbu++.a"; |
234 | tag ["tests", "unit tests"]; | 234 | tag ["tests", "unit tests"]; |
235 | CXXFLAGS += "-I."; | 235 | CXXFLAGS += "-I."; |
236 | LDFLAGS += "-L. -lbu++"; | 236 | LDFLAGS += "-L. -lbu++"; |
237 | } | 237 | } |
238 | 238 | ||
239 | PKG_BASE = "libbu++-$(cat version)-r$(svnversion "-n").tar"; | 239 | PKG_BASE = "libbu++-$(cat version)-r$(svnversion "-n").tar"; |
240 | 240 | ||
241 | target PKG_BASE | 241 | target PKG_BASE |
242 | { | 242 | { |
243 | input [ | 243 | input [ |
244 | "LICENSE", | 244 | "LICENSE", |
245 | "Doxyfile", | 245 | "Doxyfile", |
246 | "Makefile", | 246 | "Makefile", |
247 | "version", | 247 | "version", |
248 | files("*.bld"), | 248 | files("*.bld"), |
249 | "support/vim/syntax/taf.vim", | 249 | "support/vim/syntax/taf.vim", |
250 | "support/vim/ftdetect/taf.vim", | 250 | "support/vim/ftdetect/taf.vim", |
251 | "support/vim/ftplugin/taf.vim", | 251 | "support/vim/ftplugin/taf.vim", |
252 | files("*.sh"), | 252 | files("*.sh"), |
253 | files("autoconfig.cpp"), | 253 | files("autoconfig.cpp"), |
254 | files("src/*.cpp"), | 254 | files("src/*.cpp"), |
255 | files("src/*.h"), | 255 | files("src/*.h"), |
256 | files("src/stable/*.cpp"), | 256 | files("src/stable/*.cpp"), |
257 | files("src/stable/*.h"), | 257 | files("src/stable/*.h"), |
258 | files("src/unstable/*.cpp"), | 258 | files("src/unstable/*.cpp"), |
259 | files("src/unstable/*.h"), | 259 | files("src/unstable/*.h"), |
260 | files("src/experimental/*.cpp"), | 260 | files("src/experimental/*.cpp"), |
261 | files("src/experimental/*.h"), | 261 | files("src/experimental/*.h"), |
262 | files("src/tests/*.cpp"), | 262 | files("src/tests/*.cpp"), |
263 | files("src/tests*.h"), | 263 | files("src/tests*.h"), |
264 | files("src/tools/*.cpp"), | 264 | files("src/tools/*.cpp"), |
265 | files("src/tools/*.h"), | 265 | files("src/tools/*.h"), |
266 | files("src/unit/*.unit"), | 266 | files("src/unit/*.unit"), |
267 | files("src/doxy/*.dox"), | 267 | files("src/doxy/*.dox"), |
268 | files("src/compat/*.cpp"), | 268 | files("src/compat/*.cpp"), |
269 | files("src/compat/*.h"), | 269 | files("src/compat/*.h"), |
270 | files("src/extra/*.cpp"), | 270 | files("src/extra/*.cpp"), |
271 | files("src/extra/*.h"), | 271 | files("src/extra/*.h"), |
272 | files("pregen/*"), | 272 | files("pregen/*"), |
273 | "api" | 273 | "api" |
274 | ]; | 274 | ]; |
275 | rule "tarball"; | 275 | rule "tarball"; |
276 | tag "pkg"; | 276 | tag "pkg"; |
277 | } | 277 | } |
278 | 278 | ||
279 | target PKG_BASE + ".gz" | 279 | target PKG_BASE + ".gz" |
280 | { | 280 | { |
281 | input PKG_BASE; | 281 | input PKG_BASE; |
282 | tag "pkg"; | 282 | tag "pkg"; |
283 | display "gzip"; | 283 | display "gzip"; |
284 | profile "build" | 284 | profile "build" |
285 | { | 285 | { |
286 | execute("gzip -9 < ${INPUT} > ${OUTPUT}"); | 286 | execute("gzip -9 < ${INPUT} > ${OUTPUT}"); |
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | target PKG_BASE + ".bz2" | 290 | target PKG_BASE + ".bz2" |
291 | { | 291 | { |
292 | input PKG_BASE; | 292 | input PKG_BASE; |
293 | tag "pkg"; | 293 | tag "pkg"; |
294 | display "bzip2"; | 294 | display "bzip2"; |
295 | profile "build" | 295 | profile "build" |
296 | { | 296 | { |
297 | execute("bzip2 -9 < ${INPUT} > ${OUTPUT}"); | 297 | execute("bzip2 -9 < ${INPUT} > ${OUTPUT}"); |
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | target PKG_BASE + ".xz" | 301 | target PKG_BASE + ".xz" |
302 | { | 302 | { |
303 | input PKG_BASE; | 303 | input PKG_BASE; |
304 | tag "pkg"; | 304 | tag "pkg"; |
305 | display "xz"; | 305 | display "xz"; |
306 | profile "build" | 306 | profile "build" |
307 | { | 307 | { |
308 | execute("xz -9vv < ${INPUT} > ${OUTPUT}"); | 308 | execute("xz -9vv < ${INPUT} > ${OUTPUT}"); |
309 | } | 309 | } |
310 | } | 310 | } |
311 | 311 | ||
312 | rule "tarball" | 312 | rule "tarball" |
313 | { | 313 | { |
314 | input matches("LICENSE", "Makefile", "*.cpp", "*.h", "*.conf", "*.bld", | 314 | input matches("LICENSE", "Makefile", "*.cpp", "*.h", "*.conf", "*.bld", |
315 | "Doxyfile", "*.vim", "*.sh", "*.unit", "api", "version"); | 315 | "Doxyfile", "*.vim", "*.sh", "*.unit", "api", "version"); |
316 | profile "build" | 316 | profile "build" |
317 | { | 317 | { |
318 | OUTDIR = OUTPUT.replace(".tar",""); | 318 | OUTDIR = OUTPUT.replace(".tar",""); |
319 | execute("tar -f ./${OUTPUT} --transform=\"s@^@${OUTDIR}/@\" -c ${INPUT}"); | 319 | execute("tar -f ./${OUTPUT} --transform=\"s@^@${OUTDIR}/@\" -c ${INPUT}"); |
320 | } | 320 | } |
321 | } | 321 | } |
322 | 322 | ||
323 | rule "unit" | 323 | rule "unit" |
324 | { | 324 | { |
325 | input "*.unit"; | 325 | input "*.unit"; |
326 | output INPUT.replace(".unit", ".cpp"); | 326 | output INPUT.replace(".unit", ".cpp"); |
327 | 327 | ||
328 | profile "build" | 328 | profile "build" |
329 | { | 329 | { |
330 | execute("./mkunit \"${INPUT}\" \"${OUTPUT}\""); | 330 | execute("./mkunit \"${INPUT}\" \"${OUTPUT}\""); |
331 | } | 331 | } |
332 | } | 332 | } |
333 | 333 | ||
@@ -13,90 +13,90 @@ CXXFLAGS += "-ggdb -W -Wall"; | |||
13 | 13 | ||
14 | action "default" | 14 | action "default" |
15 | { | 15 | { |
16 | build: [targets("header-links"), "libbu++win.a"]; | 16 | build: [targets("header-links"), "libbu++win.a"]; |
17 | } | 17 | } |
18 | 18 | ||
19 | for base in ["stable", "unstable", "experimental"] do | 19 | for base in ["stable", "unstable", "experimental"] do |
20 | { | 20 | { |
21 | target files("src/${base}/*.h").replace("src/${base}/", "bu/") | 21 | target files("src/${base}/*.h").replace("src/${base}/", "bu/") |
22 | { | 22 | { |
23 | tag "header-links"; | 23 | tag "header-links"; |
24 | display "symlink"; | 24 | display "symlink"; |
25 | input OUTPUT.replace("bu/","src/${base}/"); | 25 | input OUTPUT.replace("bu/","src/${base}/"); |
26 | profile "build" | 26 | profile "build" |
27 | { | 27 | { |
28 | DIR = OUTPUT.dirName(); | 28 | DIR = OUTPUT.dirName(); |
29 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); | 29 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | } | 32 | } |
33 | target files("src/compat/*.h").replace("src/", "bu/") | 33 | target files("src/compat/*.h").replace("src/", "bu/") |
34 | { | 34 | { |
35 | tag "header-links"; | 35 | tag "header-links"; |
36 | display "symlink"; | 36 | display "symlink"; |
37 | input OUTPUT.replace("bu/","src/"); | 37 | input OUTPUT.replace("bu/","src/"); |
38 | profile "build" | 38 | profile "build" |
39 | { | 39 | { |
40 | execute("mkdir -p $(dirname ${OUTPUT}); ln -s ../../${INPUT} ${OUTPUT}"); | 40 | execute("mkdir -p $(dirname ${OUTPUT}); ln -s ../../${INPUT} ${OUTPUT}"); |
41 | } | 41 | } |
42 | } | 42 | } |
43 | target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] | 43 | target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] |
44 | { | 44 | { |
45 | tag "header-links"; | 45 | tag "header-links"; |
46 | display "symlink"; | 46 | display "symlink"; |
47 | input OUTPUT.replace("bu/","src/"); | 47 | input OUTPUT.replace("bu/","src/"); |
48 | profile "build" | 48 | profile "build" |
49 | { | 49 | { |
50 | DIR = OUTPUT.dirName(); | 50 | DIR = OUTPUT.dirName(); |
51 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); | 51 | execute("mkdir -p ${DIR}; ln -s ../${INPUT} ${OUTPUT}"); |
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | target "libbu++win.a" | 55 | target "libbu++win.a" |
56 | { | 56 | { |
57 | input files("src/stable/*.cpp", "src/unstable/*.cpp", | 57 | input files("src/stable/*.cpp", "src/unstable/*.cpp", |
58 | "src/experimental/*.cpp", "src/compat/*.cpp"); | 58 | "src/experimental/*.cpp", "src/compat/*.cpp"); |
59 | rule "lib"; | 59 | rule "lib"; |
60 | CXXFLAGS += "-I. -Isupport/windows"; | 60 | CXXFLAGS += "-I. -Isupport/windows"; |
61 | } | 61 | } |
62 | 62 | ||
63 | target ["src/stable/lzma.win_o", "src/experimental/cachestorefiles.win_o", "src/experimental/regex.win_o"] | 63 | target ["src/stable/lzma.win_o", "src/experimental/cachestorefiles.win_o", "src/experimental/regex.win_o"] |
64 | { | 64 | { |
65 | profile "build" | 65 | profile "build" |
66 | { | 66 | { |
67 | execute("rm -f ${OUTPUT} && touch ${OUTPUT} && echo NOT BUILDING ${OUTPUT}"); | 67 | execute("rm -f ${OUTPUT} && touch ${OUTPUT} && echo NOT BUILDING ${OUTPUT}"); |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | function cppToWinObj() | 71 | function cppToWinObj() |
72 | { | 72 | { |
73 | if OBJ_DIR == null then | 73 | if OBJ_DIR == null then |
74 | { | 74 | { |
75 | return INPUT.regex("\\.cpp$", ".win_o"); | 75 | return INPUT.regex("\\.cpp$", ".win_o"); |
76 | } | 76 | } |
77 | else | 77 | else |
78 | { | 78 | { |
79 | return OBJ_DIR + "/" + INPUT.fileName().regex("\\.cpp$", ".win_o"); | 79 | return OBJ_DIR + "/" + INPUT.fileName().regex("\\.cpp$", ".win_o"); |
80 | } | 80 | } |
81 | 81 | ||
82 | } | 82 | } |
83 | 83 | ||
84 | rule "lib" | 84 | rule "lib" |
85 | { | 85 | { |
86 | input "*.win_o"; | 86 | input "*.win_o"; |
87 | profile "build" | 87 | profile "build" |
88 | { | 88 | { |
89 | execute("wine C:/MinGW/bin/ar.exe cr ${OUTPUT} ${INPUT}"); | 89 | execute("wine C:/MinGW/bin/ar.exe cr ${OUTPUT} ${INPUT}"); |
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | rule "wincpp" | 93 | rule "wincpp" |
94 | { | 94 | { |
95 | input "*.cpp"; | 95 | input "*.cpp"; |
96 | output INPUT.cppToWinObj(); | 96 | output INPUT.cppToWinObj(); |
97 | //requires getMakeDeps("wine C:/MinGW/bin/g++.exe ${CXXFLAGS} -M ${INPUT}"); | 97 | //requires getMakeDeps("wine C:/MinGW/bin/g++.exe ${CXXFLAGS} -M ${INPUT}"); |
98 | profile "build" | 98 | profile "build" |
99 | { | 99 | { |
100 | execute("wine C:/MinGW/bin/g++.exe ${CXXFLAGS} -c -o ${OUTPUT} ${INPUT}", "g++"); | 100 | execute("wine C:/MinGW/bin/g++.exe ${CXXFLAGS} -c -o ${OUTPUT} ${INPUT}", "g++"); |
101 | } | 101 | } |
102 | } | 102 | } |
diff --git a/misc/heap.cpp b/misc/heap.cpp index a913ef8..d558b0c 100644 --- a/misc/heap.cpp +++ b/misc/heap.cpp | |||
@@ -3,117 +3,117 @@ | |||
3 | 3 | ||
4 | void printHeap( int *aiHeap, int iHeapFill ) | 4 | void printHeap( int *aiHeap, int iHeapFill ) |
5 | { | 5 | { |
6 | printf("graph G {\n"); | 6 | printf("graph G {\n"); |
7 | for( int j = 0; j < iHeapFill; j++ ) | 7 | for( int j = 0; j < iHeapFill; j++ ) |
8 | { | 8 | { |
9 | if( j*2+1 < iHeapFill ) | 9 | if( j*2+1 < iHeapFill ) |
10 | printf(" %d -- %d;\n", | 10 | printf(" %d -- %d;\n", |
11 | j, j*2+1 | 11 | j, j*2+1 |
12 | ); | 12 | ); |
13 | if( j*2+2 < iHeapFill ) | 13 | if( j*2+2 < iHeapFill ) |
14 | printf(" %d -- %d;\n", | 14 | printf(" %d -- %d;\n", |
15 | j, j*2+2 | 15 | j, j*2+2 |
16 | ); | 16 | ); |
17 | } | 17 | } |
18 | for( int j = 0; j < iHeapFill; j++ ) | 18 | for( int j = 0; j < iHeapFill; j++ ) |
19 | { | 19 | { |
20 | printf(" %d [label=\"%d\"];\n", | 20 | printf(" %d [label=\"%d\"];\n", |
21 | j, aiHeap[j] | 21 | j, aiHeap[j] |
22 | ); | 22 | ); |
23 | } | 23 | } |
24 | printf("}\n"); | 24 | printf("}\n"); |
25 | } | 25 | } |
26 | 26 | ||
27 | void heapPush( int iNum, int *aiHeap, int &iHeapFill ) | 27 | void heapPush( int iNum, int *aiHeap, int &iHeapFill ) |
28 | { | 28 | { |
29 | for( int j = 0; j < iHeapFill; ) | 29 | for( int j = 0; j < iHeapFill; ) |
30 | { | 30 | { |
31 | if( iNum < aiHeap[j] ) | 31 | if( iNum < aiHeap[j] ) |
32 | { | 32 | { |
33 | int iTmp = aiHeap[j]; | 33 | int iTmp = aiHeap[j]; |
34 | aiHeap[j] = iNum; | 34 | aiHeap[j] = iNum; |
35 | iNum = iTmp; | 35 | iNum = iTmp; |
36 | } | 36 | } |
37 | 37 | ||
38 | if( iNum <= aiHeap[j*2+1] ) | 38 | if( iNum <= aiHeap[j*2+1] ) |
39 | { | 39 | { |
40 | j = j*2+1; | 40 | j = j*2+1; |
41 | continue; | 41 | continue; |
42 | } | 42 | } |
43 | else | 43 | else |
44 | { | 44 | { |
45 | j = j*2+2; | 45 | j = j*2+2; |
46 | continue; | 46 | continue; |
47 | } | 47 | } |
48 | } | 48 | } |
49 | aiHeap[iHeapFill] = iNum; | 49 | aiHeap[iHeapFill] = iNum; |
50 | for( int j = iHeapFill; j >= 0; ) | 50 | for( int j = iHeapFill; j >= 0; ) |
51 | { | 51 | { |
52 | int k = (j-1)/2; | 52 | int k = (j-1)/2; |
53 | if( aiHeap[k] <= aiHeap[j] ) | 53 | if( aiHeap[k] <= aiHeap[j] ) |
54 | break; | 54 | break; |
55 | 55 | ||
56 | int iTmp = aiHeap[k]; | 56 | int iTmp = aiHeap[k]; |
57 | aiHeap[k] = aiHeap[j]; | 57 | aiHeap[k] = aiHeap[j]; |
58 | aiHeap[j] = iTmp; | 58 | aiHeap[j] = iTmp; |
59 | j = k; | 59 | j = k; |
60 | } | 60 | } |
61 | iHeapFill++; | 61 | iHeapFill++; |
62 | } | 62 | } |
63 | 63 | ||
64 | int heapPop( int *aiHeap, int &iHeapFill ) | 64 | int heapPop( int *aiHeap, int &iHeapFill ) |
65 | { | 65 | { |
66 | int iRet = aiHeap[0]; | 66 | int iRet = aiHeap[0]; |
67 | 67 | ||
68 | int j; | 68 | int j; |
69 | for( j = 0; j < iHeapFill; ) | 69 | for( j = 0; j < iHeapFill; ) |
70 | { | 70 | { |
71 | if( aiHeap[j*2+1] >= aiHeap[j*2+2] && j*2+2 < iHeapFill ) | 71 | if( aiHeap[j*2+1] >= aiHeap[j*2+2] && j*2+2 < iHeapFill ) |
72 | { | 72 | { |
73 | aiHeap[j] = aiHeap[j*2+2]; | 73 | aiHeap[j] = aiHeap[j*2+2]; |
74 | j = j*2+2; | 74 | j = j*2+2; |
75 | } | 75 | } |
76 | else if( j*2+1 < iHeapFill ) | 76 | else if( j*2+1 < iHeapFill ) |
77 | { | 77 | { |
78 | aiHeap[j] = aiHeap[j*2+1]; | 78 | aiHeap[j] = aiHeap[j*2+1]; |
79 | j = j*2+1; | 79 | j = j*2+1; |
80 | } | 80 | } |
81 | else | 81 | else |
82 | break; | 82 | break; |
83 | } | 83 | } |
84 | aiHeap[j] = aiHeap[iHeapFill-1]; | 84 | aiHeap[j] = aiHeap[iHeapFill-1]; |
85 | iHeapFill--; | 85 | iHeapFill--; |
86 | return iRet; | 86 | return iRet; |
87 | } | 87 | } |
88 | 88 | ||
89 | int main( int argc, char *argv[] ) | 89 | int main( int argc, char *argv[] ) |
90 | { | 90 | { |
91 | int *aiHeap = new int[40]; | 91 | int *aiHeap = new int[40]; |
92 | int iHeapFill = 0; | 92 | int iHeapFill = 0; |
93 | 93 | ||
94 | int iNums = atoi( argv[1] ); | 94 | int iNums = atoi( argv[1] ); |
95 | int iOffs = atoi( argv[2] ); | 95 | int iOffs = atoi( argv[2] ); |
96 | char cDo = argv[3][0]; | 96 | char cDo = argv[3][0]; |
97 | 97 | ||
98 | for( int j = 0; j < iNums; j++ ) | 98 | for( int j = 0; j < iNums; j++ ) |
99 | { | 99 | { |
100 | int iNum = rand()%20; | 100 | int iNum = rand()%20; |
101 | if( cDo == 'y' ) printf("%d ", iNum ); | 101 | if( cDo == 'y' ) printf("%d ", iNum ); |
102 | heapPush( iNum, aiHeap, iHeapFill ); | 102 | heapPush( iNum, aiHeap, iHeapFill ); |
103 | } | 103 | } |
104 | if( cDo == 'y' ) printf("\n"); | 104 | if( cDo == 'y' ) printf("\n"); |
105 | 105 | ||
106 | for( int j = 0; j < iOffs; j++ ) | 106 | for( int j = 0; j < iOffs; j++ ) |
107 | { | 107 | { |
108 | if( cDo == 'y' ) | 108 | if( cDo == 'y' ) |
109 | printf("%d ", heapPop( aiHeap, iHeapFill ) ); | 109 | printf("%d ", heapPop( aiHeap, iHeapFill ) ); |
110 | else | 110 | else |
111 | heapPop( aiHeap, iHeapFill ); | 111 | heapPop( aiHeap, iHeapFill ); |
112 | } | 112 | } |
113 | if( cDo == 'y' ) printf("\n"); | 113 | if( cDo == 'y' ) printf("\n"); |
114 | else printHeap( aiHeap, iHeapFill ); | 114 | else printHeap( aiHeap, iHeapFill ); |
115 | 115 | ||
116 | delete[] aiHeap; | 116 | delete[] aiHeap; |
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
diff --git a/pregen/signals.h b/pregen/signals.h index 6020e59..27364da 100644 --- a/pregen/signals.h +++ b/pregen/signals.h | |||
@@ -13,1194 +13,1194 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | subExceptionDecl( SignalException ); | 16 | subExceptionDecl( SignalException ); |
17 | 17 | ||
18 | #ifndef BU_SIGNAL_PARAM_COUNT_0 | 18 | #ifndef BU_SIGNAL_PARAM_COUNT_0 |
19 | #define BU_SIGNAL_PARAM_COUNT_0 | 19 | #define BU_SIGNAL_PARAM_COUNT_0 |
20 | // | 20 | // |
21 | // 0 Parameter(s) | 21 | // 0 Parameter(s) |
22 | // | 22 | // |
23 | template<typename ret> | 23 | template<typename ret> |
24 | class _Slot0 | 24 | class _Slot0 |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | _Slot0() { } | 27 | _Slot0() { } |
28 | virtual ~_Slot0() { } | 28 | virtual ~_Slot0() { } |
29 | virtual ret operator()( )=0; | 29 | virtual ret operator()( )=0; |
30 | virtual _Slot0<ret> *clone() const=0; | 30 | virtual _Slot0<ret> *clone() const=0; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | template<typename cls, typename ret> | 33 | template<typename cls, typename ret> |
34 | class __Slot0 : public _Slot0<ret> | 34 | class __Slot0 : public _Slot0<ret> |
35 | { | 35 | { |
36 | public: | 36 | public: |
37 | __Slot0( cls *pCls, ret (cls::*pFnc)( ) ) : | 37 | __Slot0( cls *pCls, ret (cls::*pFnc)( ) ) : |
38 | pCls( pCls ), pFnc( pFnc ) { } | 38 | pCls( pCls ), pFnc( pFnc ) { } |
39 | virtual ~__Slot0() { } | 39 | virtual ~__Slot0() { } |
40 | 40 | ||
41 | virtual ret operator()( ) | 41 | virtual ret operator()( ) |
42 | { | 42 | { |
43 | return (pCls->*pFnc)( ); | 43 | return (pCls->*pFnc)( ); |
44 | } | 44 | } |
45 | 45 | ||
46 | virtual _Slot0<ret> *clone() const | 46 | virtual _Slot0<ret> *clone() const |
47 | { | 47 | { |
48 | return new __Slot0<cls, ret>( pCls, pFnc ); | 48 | return new __Slot0<cls, ret>( pCls, pFnc ); |
49 | } | 49 | } |
50 | 50 | ||
51 | private: | 51 | private: |
52 | cls *pCls; | 52 | cls *pCls; |
53 | ret (cls::*pFnc)( ); | 53 | ret (cls::*pFnc)( ); |
54 | }; | 54 | }; |
55 | 55 | ||
56 | template<typename ret> | 56 | template<typename ret> |
57 | class __Slot0F : public _Slot0<ret> | 57 | class __Slot0F : public _Slot0<ret> |
58 | { | 58 | { |
59 | public: | 59 | public: |
60 | __Slot0F( ret (*pFnc)( ) ) : | 60 | __Slot0F( ret (*pFnc)( ) ) : |
61 | pFnc( pFnc ) { } | 61 | pFnc( pFnc ) { } |
62 | virtual ~__Slot0F() { } | 62 | virtual ~__Slot0F() { } |
63 | 63 | ||
64 | virtual ret operator()( ) | 64 | virtual ret operator()( ) |
65 | { | 65 | { |
66 | return (*pFnc)( ); | 66 | return (*pFnc)( ); |
67 | } | 67 | } |
68 | 68 | ||
69 | virtual _Slot0<ret> *clone() const | 69 | virtual _Slot0<ret> *clone() const |
70 | { | 70 | { |
71 | return new __Slot0F<ret>( pFnc ); | 71 | return new __Slot0F<ret>( pFnc ); |
72 | } | 72 | } |
73 | 73 | ||
74 | private: | 74 | private: |
75 | ret (*pFnc)( ); | 75 | ret (*pFnc)( ); |
76 | }; | 76 | }; |
77 | 77 | ||
78 | template<typename ret> | 78 | template<typename ret> |
79 | class Signal0 | 79 | class Signal0 |
80 | { | 80 | { |
81 | public: | 81 | public: |
82 | Signal0() : pCb( NULL ) { } | 82 | Signal0() : pCb( NULL ) { } |
83 | Signal0( _Slot0<ret> *pCb ) : pCb( pCb ) { } | 83 | Signal0( _Slot0<ret> *pCb ) : pCb( pCb ) { } |
84 | Signal0( const Signal0<ret> &rSrc ) : | 84 | Signal0( const Signal0<ret> &rSrc ) : |
85 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 85 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
86 | virtual ~Signal0() { delete pCb; pCb = NULL; } | 86 | virtual ~Signal0() { delete pCb; pCb = NULL; } |
87 | 87 | ||
88 | ret operator()( ) | 88 | ret operator()( ) |
89 | { | 89 | { |
90 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 90 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
91 | return (*pCb)( ); | 91 | return (*pCb)( ); |
92 | } | 92 | } |
93 | 93 | ||
94 | bool isSet() const { return pCb != NULL; } | 94 | bool isSet() const { return pCb != NULL; } |
95 | operator bool() const { return isSet(); } | 95 | operator bool() const { return isSet(); } |
96 | 96 | ||
97 | Signal0<ret> &operator=( const Signal0<ret> &rhs ) | 97 | Signal0<ret> &operator=( const Signal0<ret> &rhs ) |
98 | { | 98 | { |
99 | pCb = rhs.pCb->clone(); | 99 | pCb = rhs.pCb->clone(); |
100 | return *this; | 100 | return *this; |
101 | } | 101 | } |
102 | 102 | ||
103 | private: | 103 | private: |
104 | _Slot0<ret> *pCb; | 104 | _Slot0<ret> *pCb; |
105 | }; | 105 | }; |
106 | 106 | ||
107 | template<typename cls, typename ret> | 107 | template<typename cls, typename ret> |
108 | Signal0<ret> slot( cls *pCls, ret (cls::*pFnc)( ) ) | 108 | Signal0<ret> slot( cls *pCls, ret (cls::*pFnc)( ) ) |
109 | { | 109 | { |
110 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 110 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
111 | return Signal0<ret>( | 111 | return Signal0<ret>( |
112 | new __Slot0<cls, ret>( pCls, pFnc ) | 112 | new __Slot0<cls, ret>( pCls, pFnc ) |
113 | ); | 113 | ); |
114 | } | 114 | } |
115 | 115 | ||
116 | template<typename ret> | 116 | template<typename ret> |
117 | Signal0<ret> slot( ret (*pFnc)( ) ) | 117 | Signal0<ret> slot( ret (*pFnc)( ) ) |
118 | { | 118 | { |
119 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 119 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
120 | return Signal0<ret>( | 120 | return Signal0<ret>( |
121 | new __Slot0F<ret>( pFnc ) | 121 | new __Slot0F<ret>( pFnc ) |
122 | ); | 122 | ); |
123 | } | 123 | } |
124 | #endif // BU_SIGNAL_PARAM_COUNT_0 | 124 | #endif // BU_SIGNAL_PARAM_COUNT_0 |
125 | 125 | ||
126 | #ifndef BU_SIGNAL_PARAM_COUNT_1 | 126 | #ifndef BU_SIGNAL_PARAM_COUNT_1 |
127 | #define BU_SIGNAL_PARAM_COUNT_1 | 127 | #define BU_SIGNAL_PARAM_COUNT_1 |
128 | // | 128 | // |
129 | // 1 Parameter(s) | 129 | // 1 Parameter(s) |
130 | // | 130 | // |
131 | template<typename ret, typename p1t> | 131 | template<typename ret, typename p1t> |
132 | class _Slot1 | 132 | class _Slot1 |
133 | { | 133 | { |
134 | public: | 134 | public: |
135 | _Slot1() { } | 135 | _Slot1() { } |
136 | virtual ~_Slot1() { } | 136 | virtual ~_Slot1() { } |
137 | virtual ret operator()( p1t p1 )=0; | 137 | virtual ret operator()( p1t p1 )=0; |
138 | virtual _Slot1<ret, p1t> *clone() const=0; | 138 | virtual _Slot1<ret, p1t> *clone() const=0; |
139 | }; | 139 | }; |
140 | 140 | ||
141 | template<typename cls, typename ret, typename p1t> | 141 | template<typename cls, typename ret, typename p1t> |
142 | class __Slot1 : public _Slot1<ret, p1t> | 142 | class __Slot1 : public _Slot1<ret, p1t> |
143 | { | 143 | { |
144 | public: | 144 | public: |
145 | __Slot1( cls *pCls, ret (cls::*pFnc)( p1t ) ) : | 145 | __Slot1( cls *pCls, ret (cls::*pFnc)( p1t ) ) : |
146 | pCls( pCls ), pFnc( pFnc ) { } | 146 | pCls( pCls ), pFnc( pFnc ) { } |
147 | virtual ~__Slot1() { } | 147 | virtual ~__Slot1() { } |
148 | 148 | ||
149 | virtual ret operator()( p1t p1 ) | 149 | virtual ret operator()( p1t p1 ) |
150 | { | 150 | { |
151 | return (pCls->*pFnc)( p1 ); | 151 | return (pCls->*pFnc)( p1 ); |
152 | } | 152 | } |
153 | 153 | ||
154 | virtual _Slot1<ret, p1t> *clone() const | 154 | virtual _Slot1<ret, p1t> *clone() const |
155 | { | 155 | { |
156 | return new __Slot1<cls, ret, p1t>( pCls, pFnc ); | 156 | return new __Slot1<cls, ret, p1t>( pCls, pFnc ); |
157 | } | 157 | } |
158 | 158 | ||
159 | private: | 159 | private: |
160 | cls *pCls; | 160 | cls *pCls; |
161 | ret (cls::*pFnc)( p1t ); | 161 | ret (cls::*pFnc)( p1t ); |
162 | }; | 162 | }; |
163 | 163 | ||
164 | template<typename ret, typename p1t> | 164 | template<typename ret, typename p1t> |
165 | class __Slot1F : public _Slot1<ret, p1t> | 165 | class __Slot1F : public _Slot1<ret, p1t> |
166 | { | 166 | { |
167 | public: | 167 | public: |
168 | __Slot1F( ret (*pFnc)( p1t ) ) : | 168 | __Slot1F( ret (*pFnc)( p1t ) ) : |
169 | pFnc( pFnc ) { } | 169 | pFnc( pFnc ) { } |
170 | virtual ~__Slot1F() { } | 170 | virtual ~__Slot1F() { } |
171 | 171 | ||
172 | virtual ret operator()( p1t p1 ) | 172 | virtual ret operator()( p1t p1 ) |
173 | { | 173 | { |
174 | return (*pFnc)( p1 ); | 174 | return (*pFnc)( p1 ); |
175 | } | 175 | } |
176 | 176 | ||
177 | virtual _Slot1<ret, p1t> *clone() const | 177 | virtual _Slot1<ret, p1t> *clone() const |
178 | { | 178 | { |
179 | return new __Slot1F<ret, p1t>( pFnc ); | 179 | return new __Slot1F<ret, p1t>( pFnc ); |
180 | } | 180 | } |
181 | 181 | ||
182 | private: | 182 | private: |
183 | ret (*pFnc)( p1t ); | 183 | ret (*pFnc)( p1t ); |
184 | }; | 184 | }; |
185 | 185 | ||
186 | template<typename ret, typename p1t> | 186 | template<typename ret, typename p1t> |
187 | class Signal1 | 187 | class Signal1 |
188 | { | 188 | { |
189 | public: | 189 | public: |
190 | Signal1() : pCb( NULL ) { } | 190 | Signal1() : pCb( NULL ) { } |
191 | Signal1( _Slot1<ret, p1t> *pCb ) : pCb( pCb ) { } | 191 | Signal1( _Slot1<ret, p1t> *pCb ) : pCb( pCb ) { } |
192 | Signal1( const Signal1<ret, p1t> &rSrc ) : | 192 | Signal1( const Signal1<ret, p1t> &rSrc ) : |
193 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 193 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
194 | virtual ~Signal1() { delete pCb; pCb = NULL; } | 194 | virtual ~Signal1() { delete pCb; pCb = NULL; } |
195 | 195 | ||
196 | ret operator()( p1t p1 ) | 196 | ret operator()( p1t p1 ) |
197 | { | 197 | { |
198 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 198 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
199 | return (*pCb)( p1 ); | 199 | return (*pCb)( p1 ); |
200 | } | 200 | } |
201 | 201 | ||
202 | bool isSet() const { return pCb != NULL; } | 202 | bool isSet() const { return pCb != NULL; } |
203 | operator bool() const { return isSet(); } | 203 | operator bool() const { return isSet(); } |
204 | 204 | ||
205 | Signal1<ret, p1t> &operator=( const Signal1<ret, p1t> &rhs ) | 205 | Signal1<ret, p1t> &operator=( const Signal1<ret, p1t> &rhs ) |
206 | { | 206 | { |
207 | pCb = rhs.pCb->clone(); | 207 | pCb = rhs.pCb->clone(); |
208 | return *this; | 208 | return *this; |
209 | } | 209 | } |
210 | 210 | ||
211 | private: | 211 | private: |
212 | _Slot1<ret, p1t> *pCb; | 212 | _Slot1<ret, p1t> *pCb; |
213 | }; | 213 | }; |
214 | 214 | ||
215 | template<typename cls, typename ret, typename p1t> | 215 | template<typename cls, typename ret, typename p1t> |
216 | Signal1<ret, p1t> slot( cls *pCls, ret (cls::*pFnc)( p1t ) ) | 216 | Signal1<ret, p1t> slot( cls *pCls, ret (cls::*pFnc)( p1t ) ) |
217 | { | 217 | { |
218 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 218 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
219 | return Signal1<ret, p1t>( | 219 | return Signal1<ret, p1t>( |
220 | new __Slot1<cls, ret, p1t>( pCls, pFnc ) | 220 | new __Slot1<cls, ret, p1t>( pCls, pFnc ) |
221 | ); | 221 | ); |
222 | } | 222 | } |
223 | 223 | ||
224 | template<typename ret, typename p1t> | 224 | template<typename ret, typename p1t> |
225 | Signal1<ret, p1t> slot( ret (*pFnc)( p1t ) ) | 225 | Signal1<ret, p1t> slot( ret (*pFnc)( p1t ) ) |
226 | { | 226 | { |
227 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 227 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
228 | return Signal1<ret, p1t>( | 228 | return Signal1<ret, p1t>( |
229 | new __Slot1F<ret, p1t>( pFnc ) | 229 | new __Slot1F<ret, p1t>( pFnc ) |
230 | ); | 230 | ); |
231 | } | 231 | } |
232 | #endif // BU_SIGNAL_PARAM_COUNT_1 | 232 | #endif // BU_SIGNAL_PARAM_COUNT_1 |
233 | 233 | ||
234 | #ifndef BU_SIGNAL_PARAM_COUNT_2 | 234 | #ifndef BU_SIGNAL_PARAM_COUNT_2 |
235 | #define BU_SIGNAL_PARAM_COUNT_2 | 235 | #define BU_SIGNAL_PARAM_COUNT_2 |
236 | // | 236 | // |
237 | // 2 Parameter(s) | 237 | // 2 Parameter(s) |
238 | // | 238 | // |
239 | template<typename ret, typename p1t, typename p2t> | 239 | template<typename ret, typename p1t, typename p2t> |
240 | class _Slot2 | 240 | class _Slot2 |
241 | { | 241 | { |
242 | public: | 242 | public: |
243 | _Slot2() { } | 243 | _Slot2() { } |
244 | virtual ~_Slot2() { } | 244 | virtual ~_Slot2() { } |
245 | virtual ret operator()( p1t p1, p2t p2 )=0; | 245 | virtual ret operator()( p1t p1, p2t p2 )=0; |
246 | virtual _Slot2<ret, p1t, p2t> *clone() const=0; | 246 | virtual _Slot2<ret, p1t, p2t> *clone() const=0; |
247 | }; | 247 | }; |
248 | 248 | ||
249 | template<typename cls, typename ret, typename p1t, typename p2t> | 249 | template<typename cls, typename ret, typename p1t, typename p2t> |
250 | class __Slot2 : public _Slot2<ret, p1t, p2t> | 250 | class __Slot2 : public _Slot2<ret, p1t, p2t> |
251 | { | 251 | { |
252 | public: | 252 | public: |
253 | __Slot2( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) : | 253 | __Slot2( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) : |
254 | pCls( pCls ), pFnc( pFnc ) { } | 254 | pCls( pCls ), pFnc( pFnc ) { } |
255 | virtual ~__Slot2() { } | 255 | virtual ~__Slot2() { } |
256 | 256 | ||
257 | virtual ret operator()( p1t p1, p2t p2 ) | 257 | virtual ret operator()( p1t p1, p2t p2 ) |
258 | { | 258 | { |
259 | return (pCls->*pFnc)( p1, p2 ); | 259 | return (pCls->*pFnc)( p1, p2 ); |
260 | } | 260 | } |
261 | 261 | ||
262 | virtual _Slot2<ret, p1t, p2t> *clone() const | 262 | virtual _Slot2<ret, p1t, p2t> *clone() const |
263 | { | 263 | { |
264 | return new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ); | 264 | return new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ); |
265 | } | 265 | } |
266 | 266 | ||
267 | private: | 267 | private: |
268 | cls *pCls; | 268 | cls *pCls; |
269 | ret (cls::*pFnc)( p1t, p2t ); | 269 | ret (cls::*pFnc)( p1t, p2t ); |
270 | }; | 270 | }; |
271 | 271 | ||
272 | template<typename ret, typename p1t, typename p2t> | 272 | template<typename ret, typename p1t, typename p2t> |
273 | class __Slot2F : public _Slot2<ret, p1t, p2t> | 273 | class __Slot2F : public _Slot2<ret, p1t, p2t> |
274 | { | 274 | { |
275 | public: | 275 | public: |
276 | __Slot2F( ret (*pFnc)( p1t, p2t ) ) : | 276 | __Slot2F( ret (*pFnc)( p1t, p2t ) ) : |
277 | pFnc( pFnc ) { } | 277 | pFnc( pFnc ) { } |
278 | virtual ~__Slot2F() { } | 278 | virtual ~__Slot2F() { } |
279 | 279 | ||
280 | virtual ret operator()( p1t p1, p2t p2 ) | 280 | virtual ret operator()( p1t p1, p2t p2 ) |
281 | { | 281 | { |
282 | return (*pFnc)( p1, p2 ); | 282 | return (*pFnc)( p1, p2 ); |
283 | } | 283 | } |
284 | 284 | ||
285 | virtual _Slot2<ret, p1t, p2t> *clone() const | 285 | virtual _Slot2<ret, p1t, p2t> *clone() const |
286 | { | 286 | { |
287 | return new __Slot2F<ret, p1t, p2t>( pFnc ); | 287 | return new __Slot2F<ret, p1t, p2t>( pFnc ); |
288 | } | 288 | } |
289 | 289 | ||
290 | private: | 290 | private: |
291 | ret (*pFnc)( p1t, p2t ); | 291 | ret (*pFnc)( p1t, p2t ); |
292 | }; | 292 | }; |
293 | 293 | ||
294 | template<typename ret, typename p1t, typename p2t> | 294 | template<typename ret, typename p1t, typename p2t> |
295 | class Signal2 | 295 | class Signal2 |
296 | { | 296 | { |
297 | public: | 297 | public: |
298 | Signal2() : pCb( NULL ) { } | 298 | Signal2() : pCb( NULL ) { } |
299 | Signal2( _Slot2<ret, p1t, p2t> *pCb ) : pCb( pCb ) { } | 299 | Signal2( _Slot2<ret, p1t, p2t> *pCb ) : pCb( pCb ) { } |
300 | Signal2( const Signal2<ret, p1t, p2t> &rSrc ) : | 300 | Signal2( const Signal2<ret, p1t, p2t> &rSrc ) : |
301 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 301 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
302 | virtual ~Signal2() { delete pCb; pCb = NULL; } | 302 | virtual ~Signal2() { delete pCb; pCb = NULL; } |
303 | 303 | ||
304 | ret operator()( p1t p1, p2t p2 ) | 304 | ret operator()( p1t p1, p2t p2 ) |
305 | { | 305 | { |
306 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 306 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
307 | return (*pCb)( p1, p2 ); | 307 | return (*pCb)( p1, p2 ); |
308 | } | 308 | } |
309 | 309 | ||
310 | bool isSet() const { return pCb != NULL; } | 310 | bool isSet() const { return pCb != NULL; } |
311 | operator bool() const { return isSet(); } | 311 | operator bool() const { return isSet(); } |
312 | 312 | ||
313 | Signal2<ret, p1t, p2t> &operator=( const Signal2<ret, p1t, p2t> &rhs ) | 313 | Signal2<ret, p1t, p2t> &operator=( const Signal2<ret, p1t, p2t> &rhs ) |
314 | { | 314 | { |
315 | pCb = rhs.pCb->clone(); | 315 | pCb = rhs.pCb->clone(); |
316 | return *this; | 316 | return *this; |
317 | } | 317 | } |
318 | 318 | ||
319 | private: | 319 | private: |
320 | _Slot2<ret, p1t, p2t> *pCb; | 320 | _Slot2<ret, p1t, p2t> *pCb; |
321 | }; | 321 | }; |
322 | 322 | ||
323 | template<typename cls, typename ret, typename p1t, typename p2t> | 323 | template<typename cls, typename ret, typename p1t, typename p2t> |
324 | Signal2<ret, p1t, p2t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) | 324 | Signal2<ret, p1t, p2t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) |
325 | { | 325 | { |
326 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 326 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
327 | return Signal2<ret, p1t, p2t>( | 327 | return Signal2<ret, p1t, p2t>( |
328 | new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ) | 328 | new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ) |
329 | ); | 329 | ); |
330 | } | 330 | } |
331 | 331 | ||
332 | template<typename ret, typename p1t, typename p2t> | 332 | template<typename ret, typename p1t, typename p2t> |
333 | Signal2<ret, p1t, p2t> slot( ret (*pFnc)( p1t, p2t ) ) | 333 | Signal2<ret, p1t, p2t> slot( ret (*pFnc)( p1t, p2t ) ) |
334 | { | 334 | { |
335 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 335 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
336 | return Signal2<ret, p1t, p2t>( | 336 | return Signal2<ret, p1t, p2t>( |
337 | new __Slot2F<ret, p1t, p2t>( pFnc ) | 337 | new __Slot2F<ret, p1t, p2t>( pFnc ) |
338 | ); | 338 | ); |
339 | } | 339 | } |
340 | #endif // BU_SIGNAL_PARAM_COUNT_2 | 340 | #endif // BU_SIGNAL_PARAM_COUNT_2 |
341 | 341 | ||
342 | #ifndef BU_SIGNAL_PARAM_COUNT_3 | 342 | #ifndef BU_SIGNAL_PARAM_COUNT_3 |
343 | #define BU_SIGNAL_PARAM_COUNT_3 | 343 | #define BU_SIGNAL_PARAM_COUNT_3 |
344 | // | 344 | // |
345 | // 3 Parameter(s) | 345 | // 3 Parameter(s) |
346 | // | 346 | // |
347 | template<typename ret, typename p1t, typename p2t, typename p3t> | 347 | template<typename ret, typename p1t, typename p2t, typename p3t> |
348 | class _Slot3 | 348 | class _Slot3 |
349 | { | 349 | { |
350 | public: | 350 | public: |
351 | _Slot3() { } | 351 | _Slot3() { } |
352 | virtual ~_Slot3() { } | 352 | virtual ~_Slot3() { } |
353 | virtual ret operator()( p1t p1, p2t p2, p3t p3 )=0; | 353 | virtual ret operator()( p1t p1, p2t p2, p3t p3 )=0; |
354 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const=0; | 354 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const=0; |
355 | }; | 355 | }; |
356 | 356 | ||
357 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> | 357 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> |
358 | class __Slot3 : public _Slot3<ret, p1t, p2t, p3t> | 358 | class __Slot3 : public _Slot3<ret, p1t, p2t, p3t> |
359 | { | 359 | { |
360 | public: | 360 | public: |
361 | __Slot3( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) : | 361 | __Slot3( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) : |
362 | pCls( pCls ), pFnc( pFnc ) { } | 362 | pCls( pCls ), pFnc( pFnc ) { } |
363 | virtual ~__Slot3() { } | 363 | virtual ~__Slot3() { } |
364 | 364 | ||
365 | virtual ret operator()( p1t p1, p2t p2, p3t p3 ) | 365 | virtual ret operator()( p1t p1, p2t p2, p3t p3 ) |
366 | { | 366 | { |
367 | return (pCls->*pFnc)( p1, p2, p3 ); | 367 | return (pCls->*pFnc)( p1, p2, p3 ); |
368 | } | 368 | } |
369 | 369 | ||
370 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const | 370 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const |
371 | { | 371 | { |
372 | return new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ); | 372 | return new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ); |
373 | } | 373 | } |
374 | 374 | ||
375 | private: | 375 | private: |
376 | cls *pCls; | 376 | cls *pCls; |
377 | ret (cls::*pFnc)( p1t, p2t, p3t ); | 377 | ret (cls::*pFnc)( p1t, p2t, p3t ); |
378 | }; | 378 | }; |
379 | 379 | ||
380 | template<typename ret, typename p1t, typename p2t, typename p3t> | 380 | template<typename ret, typename p1t, typename p2t, typename p3t> |
381 | class __Slot3F : public _Slot3<ret, p1t, p2t, p3t> | 381 | class __Slot3F : public _Slot3<ret, p1t, p2t, p3t> |
382 | { | 382 | { |
383 | public: | 383 | public: |
384 | __Slot3F( ret (*pFnc)( p1t, p2t, p3t ) ) : | 384 | __Slot3F( ret (*pFnc)( p1t, p2t, p3t ) ) : |
385 | pFnc( pFnc ) { } | 385 | pFnc( pFnc ) { } |
386 | virtual ~__Slot3F() { } | 386 | virtual ~__Slot3F() { } |
387 | 387 | ||
388 | virtual ret operator()( p1t p1, p2t p2, p3t p3 ) | 388 | virtual ret operator()( p1t p1, p2t p2, p3t p3 ) |
389 | { | 389 | { |
390 | return (*pFnc)( p1, p2, p3 ); | 390 | return (*pFnc)( p1, p2, p3 ); |
391 | } | 391 | } |
392 | 392 | ||
393 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const | 393 | virtual _Slot3<ret, p1t, p2t, p3t> *clone() const |
394 | { | 394 | { |
395 | return new __Slot3F<ret, p1t, p2t, p3t>( pFnc ); | 395 | return new __Slot3F<ret, p1t, p2t, p3t>( pFnc ); |
396 | } | 396 | } |
397 | 397 | ||
398 | private: | 398 | private: |
399 | ret (*pFnc)( p1t, p2t, p3t ); | 399 | ret (*pFnc)( p1t, p2t, p3t ); |
400 | }; | 400 | }; |
401 | 401 | ||
402 | template<typename ret, typename p1t, typename p2t, typename p3t> | 402 | template<typename ret, typename p1t, typename p2t, typename p3t> |
403 | class Signal3 | 403 | class Signal3 |
404 | { | 404 | { |
405 | public: | 405 | public: |
406 | Signal3() : pCb( NULL ) { } | 406 | Signal3() : pCb( NULL ) { } |
407 | Signal3( _Slot3<ret, p1t, p2t, p3t> *pCb ) : pCb( pCb ) { } | 407 | Signal3( _Slot3<ret, p1t, p2t, p3t> *pCb ) : pCb( pCb ) { } |
408 | Signal3( const Signal3<ret, p1t, p2t, p3t> &rSrc ) : | 408 | Signal3( const Signal3<ret, p1t, p2t, p3t> &rSrc ) : |
409 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 409 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
410 | virtual ~Signal3() { delete pCb; pCb = NULL; } | 410 | virtual ~Signal3() { delete pCb; pCb = NULL; } |
411 | 411 | ||
412 | ret operator()( p1t p1, p2t p2, p3t p3 ) | 412 | ret operator()( p1t p1, p2t p2, p3t p3 ) |
413 | { | 413 | { |
414 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 414 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
415 | return (*pCb)( p1, p2, p3 ); | 415 | return (*pCb)( p1, p2, p3 ); |
416 | } | 416 | } |
417 | 417 | ||
418 | bool isSet() const { return pCb != NULL; } | 418 | bool isSet() const { return pCb != NULL; } |
419 | operator bool() const { return isSet(); } | 419 | operator bool() const { return isSet(); } |
420 | 420 | ||
421 | Signal3<ret, p1t, p2t, p3t> &operator=( const Signal3<ret, p1t, p2t, p3t> &rhs ) | 421 | Signal3<ret, p1t, p2t, p3t> &operator=( const Signal3<ret, p1t, p2t, p3t> &rhs ) |
422 | { | 422 | { |
423 | pCb = rhs.pCb->clone(); | 423 | pCb = rhs.pCb->clone(); |
424 | return *this; | 424 | return *this; |
425 | } | 425 | } |
426 | 426 | ||
427 | private: | 427 | private: |
428 | _Slot3<ret, p1t, p2t, p3t> *pCb; | 428 | _Slot3<ret, p1t, p2t, p3t> *pCb; |
429 | }; | 429 | }; |
430 | 430 | ||
431 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> | 431 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> |
432 | Signal3<ret, p1t, p2t, p3t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) | 432 | Signal3<ret, p1t, p2t, p3t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) |
433 | { | 433 | { |
434 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 434 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
435 | return Signal3<ret, p1t, p2t, p3t>( | 435 | return Signal3<ret, p1t, p2t, p3t>( |
436 | new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ) | 436 | new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ) |
437 | ); | 437 | ); |
438 | } | 438 | } |
439 | 439 | ||
440 | template<typename ret, typename p1t, typename p2t, typename p3t> | 440 | template<typename ret, typename p1t, typename p2t, typename p3t> |
441 | Signal3<ret, p1t, p2t, p3t> slot( ret (*pFnc)( p1t, p2t, p3t ) ) | 441 | Signal3<ret, p1t, p2t, p3t> slot( ret (*pFnc)( p1t, p2t, p3t ) ) |
442 | { | 442 | { |
443 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 443 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
444 | return Signal3<ret, p1t, p2t, p3t>( | 444 | return Signal3<ret, p1t, p2t, p3t>( |
445 | new __Slot3F<ret, p1t, p2t, p3t>( pFnc ) | 445 | new __Slot3F<ret, p1t, p2t, p3t>( pFnc ) |
446 | ); | 446 | ); |
447 | } | 447 | } |
448 | #endif // BU_SIGNAL_PARAM_COUNT_3 | 448 | #endif // BU_SIGNAL_PARAM_COUNT_3 |
449 | 449 | ||
450 | #ifndef BU_SIGNAL_PARAM_COUNT_4 | 450 | #ifndef BU_SIGNAL_PARAM_COUNT_4 |
451 | #define BU_SIGNAL_PARAM_COUNT_4 | 451 | #define BU_SIGNAL_PARAM_COUNT_4 |
452 | // | 452 | // |
453 | // 4 Parameter(s) | 453 | // 4 Parameter(s) |
454 | // | 454 | // |
455 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 455 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
456 | class _Slot4 | 456 | class _Slot4 |
457 | { | 457 | { |
458 | public: | 458 | public: |
459 | _Slot4() { } | 459 | _Slot4() { } |
460 | virtual ~_Slot4() { } | 460 | virtual ~_Slot4() { } |
461 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 )=0; | 461 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 )=0; |
462 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const=0; | 462 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const=0; |
463 | }; | 463 | }; |
464 | 464 | ||
465 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 465 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
466 | class __Slot4 : public _Slot4<ret, p1t, p2t, p3t, p4t> | 466 | class __Slot4 : public _Slot4<ret, p1t, p2t, p3t, p4t> |
467 | { | 467 | { |
468 | public: | 468 | public: |
469 | __Slot4( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) : | 469 | __Slot4( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) : |
470 | pCls( pCls ), pFnc( pFnc ) { } | 470 | pCls( pCls ), pFnc( pFnc ) { } |
471 | virtual ~__Slot4() { } | 471 | virtual ~__Slot4() { } |
472 | 472 | ||
473 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) | 473 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) |
474 | { | 474 | { |
475 | return (pCls->*pFnc)( p1, p2, p3, p4 ); | 475 | return (pCls->*pFnc)( p1, p2, p3, p4 ); |
476 | } | 476 | } |
477 | 477 | ||
478 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const | 478 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const |
479 | { | 479 | { |
480 | return new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ); | 480 | return new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ); |
481 | } | 481 | } |
482 | 482 | ||
483 | private: | 483 | private: |
484 | cls *pCls; | 484 | cls *pCls; |
485 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t ); | 485 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t ); |
486 | }; | 486 | }; |
487 | 487 | ||
488 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 488 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
489 | class __Slot4F : public _Slot4<ret, p1t, p2t, p3t, p4t> | 489 | class __Slot4F : public _Slot4<ret, p1t, p2t, p3t, p4t> |
490 | { | 490 | { |
491 | public: | 491 | public: |
492 | __Slot4F( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) : | 492 | __Slot4F( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) : |
493 | pFnc( pFnc ) { } | 493 | pFnc( pFnc ) { } |
494 | virtual ~__Slot4F() { } | 494 | virtual ~__Slot4F() { } |
495 | 495 | ||
496 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) | 496 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) |
497 | { | 497 | { |
498 | return (*pFnc)( p1, p2, p3, p4 ); | 498 | return (*pFnc)( p1, p2, p3, p4 ); |
499 | } | 499 | } |
500 | 500 | ||
501 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const | 501 | virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const |
502 | { | 502 | { |
503 | return new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ); | 503 | return new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ); |
504 | } | 504 | } |
505 | 505 | ||
506 | private: | 506 | private: |
507 | ret (*pFnc)( p1t, p2t, p3t, p4t ); | 507 | ret (*pFnc)( p1t, p2t, p3t, p4t ); |
508 | }; | 508 | }; |
509 | 509 | ||
510 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 510 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
511 | class Signal4 | 511 | class Signal4 |
512 | { | 512 | { |
513 | public: | 513 | public: |
514 | Signal4() : pCb( NULL ) { } | 514 | Signal4() : pCb( NULL ) { } |
515 | Signal4( _Slot4<ret, p1t, p2t, p3t, p4t> *pCb ) : pCb( pCb ) { } | 515 | Signal4( _Slot4<ret, p1t, p2t, p3t, p4t> *pCb ) : pCb( pCb ) { } |
516 | Signal4( const Signal4<ret, p1t, p2t, p3t, p4t> &rSrc ) : | 516 | Signal4( const Signal4<ret, p1t, p2t, p3t, p4t> &rSrc ) : |
517 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 517 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
518 | virtual ~Signal4() { delete pCb; pCb = NULL; } | 518 | virtual ~Signal4() { delete pCb; pCb = NULL; } |
519 | 519 | ||
520 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) | 520 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) |
521 | { | 521 | { |
522 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 522 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
523 | return (*pCb)( p1, p2, p3, p4 ); | 523 | return (*pCb)( p1, p2, p3, p4 ); |
524 | } | 524 | } |
525 | 525 | ||
526 | bool isSet() const { return pCb != NULL; } | 526 | bool isSet() const { return pCb != NULL; } |
527 | operator bool() const { return isSet(); } | 527 | operator bool() const { return isSet(); } |
528 | 528 | ||
529 | Signal4<ret, p1t, p2t, p3t, p4t> &operator=( const Signal4<ret, p1t, p2t, p3t, p4t> &rhs ) | 529 | Signal4<ret, p1t, p2t, p3t, p4t> &operator=( const Signal4<ret, p1t, p2t, p3t, p4t> &rhs ) |
530 | { | 530 | { |
531 | pCb = rhs.pCb->clone(); | 531 | pCb = rhs.pCb->clone(); |
532 | return *this; | 532 | return *this; |
533 | } | 533 | } |
534 | 534 | ||
535 | private: | 535 | private: |
536 | _Slot4<ret, p1t, p2t, p3t, p4t> *pCb; | 536 | _Slot4<ret, p1t, p2t, p3t, p4t> *pCb; |
537 | }; | 537 | }; |
538 | 538 | ||
539 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 539 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
540 | Signal4<ret, p1t, p2t, p3t, p4t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) | 540 | Signal4<ret, p1t, p2t, p3t, p4t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) |
541 | { | 541 | { |
542 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 542 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
543 | return Signal4<ret, p1t, p2t, p3t, p4t>( | 543 | return Signal4<ret, p1t, p2t, p3t, p4t>( |
544 | new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ) | 544 | new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ) |
545 | ); | 545 | ); |
546 | } | 546 | } |
547 | 547 | ||
548 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 548 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
549 | Signal4<ret, p1t, p2t, p3t, p4t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) | 549 | Signal4<ret, p1t, p2t, p3t, p4t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) |
550 | { | 550 | { |
551 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 551 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
552 | return Signal4<ret, p1t, p2t, p3t, p4t>( | 552 | return Signal4<ret, p1t, p2t, p3t, p4t>( |
553 | new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ) | 553 | new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ) |
554 | ); | 554 | ); |
555 | } | 555 | } |
556 | #endif // BU_SIGNAL_PARAM_COUNT_4 | 556 | #endif // BU_SIGNAL_PARAM_COUNT_4 |
557 | 557 | ||
558 | #ifndef BU_SIGNAL_PARAM_COUNT_5 | 558 | #ifndef BU_SIGNAL_PARAM_COUNT_5 |
559 | #define BU_SIGNAL_PARAM_COUNT_5 | 559 | #define BU_SIGNAL_PARAM_COUNT_5 |
560 | // | 560 | // |
561 | // 5 Parameter(s) | 561 | // 5 Parameter(s) |
562 | // | 562 | // |
563 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 563 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
564 | class _Slot5 | 564 | class _Slot5 |
565 | { | 565 | { |
566 | public: | 566 | public: |
567 | _Slot5() { } | 567 | _Slot5() { } |
568 | virtual ~_Slot5() { } | 568 | virtual ~_Slot5() { } |
569 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 )=0; | 569 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 )=0; |
570 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const=0; | 570 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const=0; |
571 | }; | 571 | }; |
572 | 572 | ||
573 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 573 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
574 | class __Slot5 : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> | 574 | class __Slot5 : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> |
575 | { | 575 | { |
576 | public: | 576 | public: |
577 | __Slot5( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : | 577 | __Slot5( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : |
578 | pCls( pCls ), pFnc( pFnc ) { } | 578 | pCls( pCls ), pFnc( pFnc ) { } |
579 | virtual ~__Slot5() { } | 579 | virtual ~__Slot5() { } |
580 | 580 | ||
581 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 581 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
582 | { | 582 | { |
583 | return (pCls->*pFnc)( p1, p2, p3, p4, p5 ); | 583 | return (pCls->*pFnc)( p1, p2, p3, p4, p5 ); |
584 | } | 584 | } |
585 | 585 | ||
586 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const | 586 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const |
587 | { | 587 | { |
588 | return new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ); | 588 | return new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ); |
589 | } | 589 | } |
590 | 590 | ||
591 | private: | 591 | private: |
592 | cls *pCls; | 592 | cls *pCls; |
593 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ); | 593 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ); |
594 | }; | 594 | }; |
595 | 595 | ||
596 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 596 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
597 | class __Slot5F : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> | 597 | class __Slot5F : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> |
598 | { | 598 | { |
599 | public: | 599 | public: |
600 | __Slot5F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : | 600 | __Slot5F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : |
601 | pFnc( pFnc ) { } | 601 | pFnc( pFnc ) { } |
602 | virtual ~__Slot5F() { } | 602 | virtual ~__Slot5F() { } |
603 | 603 | ||
604 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 604 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
605 | { | 605 | { |
606 | return (*pFnc)( p1, p2, p3, p4, p5 ); | 606 | return (*pFnc)( p1, p2, p3, p4, p5 ); |
607 | } | 607 | } |
608 | 608 | ||
609 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const | 609 | virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const |
610 | { | 610 | { |
611 | return new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ); | 611 | return new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ); |
612 | } | 612 | } |
613 | 613 | ||
614 | private: | 614 | private: |
615 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ); | 615 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ); |
616 | }; | 616 | }; |
617 | 617 | ||
618 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 618 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
619 | class Signal5 | 619 | class Signal5 |
620 | { | 620 | { |
621 | public: | 621 | public: |
622 | Signal5() : pCb( NULL ) { } | 622 | Signal5() : pCb( NULL ) { } |
623 | Signal5( _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb ) : pCb( pCb ) { } | 623 | Signal5( _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb ) : pCb( pCb ) { } |
624 | Signal5( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rSrc ) : | 624 | Signal5( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rSrc ) : |
625 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 625 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
626 | virtual ~Signal5() { delete pCb; pCb = NULL; } | 626 | virtual ~Signal5() { delete pCb; pCb = NULL; } |
627 | 627 | ||
628 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 628 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
629 | { | 629 | { |
630 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 630 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
631 | return (*pCb)( p1, p2, p3, p4, p5 ); | 631 | return (*pCb)( p1, p2, p3, p4, p5 ); |
632 | } | 632 | } |
633 | 633 | ||
634 | bool isSet() const { return pCb != NULL; } | 634 | bool isSet() const { return pCb != NULL; } |
635 | operator bool() const { return isSet(); } | 635 | operator bool() const { return isSet(); } |
636 | 636 | ||
637 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> &operator=( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rhs ) | 637 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> &operator=( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rhs ) |
638 | { | 638 | { |
639 | pCb = rhs.pCb->clone(); | 639 | pCb = rhs.pCb->clone(); |
640 | return *this; | 640 | return *this; |
641 | } | 641 | } |
642 | 642 | ||
643 | private: | 643 | private: |
644 | _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb; | 644 | _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb; |
645 | }; | 645 | }; |
646 | 646 | ||
647 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 647 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
648 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) | 648 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) |
649 | { | 649 | { |
650 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 650 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
651 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( | 651 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( |
652 | new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ) | 652 | new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ) |
653 | ); | 653 | ); |
654 | } | 654 | } |
655 | 655 | ||
656 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 656 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
657 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) | 657 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) |
658 | { | 658 | { |
659 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 659 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
660 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( | 660 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( |
661 | new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ) | 661 | new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ) |
662 | ); | 662 | ); |
663 | } | 663 | } |
664 | #endif // BU_SIGNAL_PARAM_COUNT_5 | 664 | #endif // BU_SIGNAL_PARAM_COUNT_5 |
665 | 665 | ||
666 | #ifndef BU_SIGNAL_PARAM_COUNT_6 | 666 | #ifndef BU_SIGNAL_PARAM_COUNT_6 |
667 | #define BU_SIGNAL_PARAM_COUNT_6 | 667 | #define BU_SIGNAL_PARAM_COUNT_6 |
668 | // | 668 | // |
669 | // 6 Parameter(s) | 669 | // 6 Parameter(s) |
670 | // | 670 | // |
671 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 671 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
672 | class _Slot6 | 672 | class _Slot6 |
673 | { | 673 | { |
674 | public: | 674 | public: |
675 | _Slot6() { } | 675 | _Slot6() { } |
676 | virtual ~_Slot6() { } | 676 | virtual ~_Slot6() { } |
677 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 )=0; | 677 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 )=0; |
678 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const=0; | 678 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const=0; |
679 | }; | 679 | }; |
680 | 680 | ||
681 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 681 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
682 | class __Slot6 : public _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> | 682 | class __Slot6 : public _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> |
683 | { | 683 | { |
684 | public: | 684 | public: |
685 | __Slot6( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) : | 685 | __Slot6( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) : |
686 | pCls( pCls ), pFnc( pFnc ) { } | 686 | pCls( pCls ), pFnc( pFnc ) { } |
687 | virtual ~__Slot6() { } | 687 | virtual ~__Slot6() { } |
688 | 688 | ||
689 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) | 689 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) |
690 | { | 690 | { |
691 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6 ); | 691 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6 ); |
692 | } | 692 | } |
693 | 693 | ||
694 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const | 694 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const |
695 | { | 695 | { |
696 | return new __Slot6<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t>( pCls, pFnc ); | 696 | return new __Slot6<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t>( pCls, pFnc ); |
697 | } | 697 | } |
698 | 698 | ||
699 | private: | 699 | private: |
700 | cls *pCls; | 700 | cls *pCls; |
701 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ); | 701 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ); |
702 | }; | 702 | }; |
703 | 703 | ||
704 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 704 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
705 | class __Slot6F : public _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> | 705 | class __Slot6F : public _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> |
706 | { | 706 | { |
707 | public: | 707 | public: |
708 | __Slot6F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) : | 708 | __Slot6F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) : |
709 | pFnc( pFnc ) { } | 709 | pFnc( pFnc ) { } |
710 | virtual ~__Slot6F() { } | 710 | virtual ~__Slot6F() { } |
711 | 711 | ||
712 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) | 712 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) |
713 | { | 713 | { |
714 | return (*pFnc)( p1, p2, p3, p4, p5, p6 ); | 714 | return (*pFnc)( p1, p2, p3, p4, p5, p6 ); |
715 | } | 715 | } |
716 | 716 | ||
717 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const | 717 | virtual _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *clone() const |
718 | { | 718 | { |
719 | return new __Slot6F<ret, p1t, p2t, p3t, p4t, p5t, p6t>( pFnc ); | 719 | return new __Slot6F<ret, p1t, p2t, p3t, p4t, p5t, p6t>( pFnc ); |
720 | } | 720 | } |
721 | 721 | ||
722 | private: | 722 | private: |
723 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ); | 723 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ); |
724 | }; | 724 | }; |
725 | 725 | ||
726 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 726 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
727 | class Signal6 | 727 | class Signal6 |
728 | { | 728 | { |
729 | public: | 729 | public: |
730 | Signal6() : pCb( NULL ) { } | 730 | Signal6() : pCb( NULL ) { } |
731 | Signal6( _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *pCb ) : pCb( pCb ) { } | 731 | Signal6( _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *pCb ) : pCb( pCb ) { } |
732 | Signal6( const Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &rSrc ) : | 732 | Signal6( const Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &rSrc ) : |
733 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 733 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
734 | virtual ~Signal6() { delete pCb; pCb = NULL; } | 734 | virtual ~Signal6() { delete pCb; pCb = NULL; } |
735 | 735 | ||
736 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) | 736 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6 ) |
737 | { | 737 | { |
738 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 738 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
739 | return (*pCb)( p1, p2, p3, p4, p5, p6 ); | 739 | return (*pCb)( p1, p2, p3, p4, p5, p6 ); |
740 | } | 740 | } |
741 | 741 | ||
742 | bool isSet() const { return pCb != NULL; } | 742 | bool isSet() const { return pCb != NULL; } |
743 | operator bool() const { return isSet(); } | 743 | operator bool() const { return isSet(); } |
744 | 744 | ||
745 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &operator=( const Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &rhs ) | 745 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &operator=( const Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> &rhs ) |
746 | { | 746 | { |
747 | pCb = rhs.pCb->clone(); | 747 | pCb = rhs.pCb->clone(); |
748 | return *this; | 748 | return *this; |
749 | } | 749 | } |
750 | 750 | ||
751 | private: | 751 | private: |
752 | _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *pCb; | 752 | _Slot6<ret, p1t, p2t, p3t, p4t, p5t, p6t> *pCb; |
753 | }; | 753 | }; |
754 | 754 | ||
755 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 755 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
756 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) | 756 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) |
757 | { | 757 | { |
758 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 758 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
759 | return Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t>( | 759 | return Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t>( |
760 | new __Slot6<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t>( pCls, pFnc ) | 760 | new __Slot6<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t>( pCls, pFnc ) |
761 | ); | 761 | ); |
762 | } | 762 | } |
763 | 763 | ||
764 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> | 764 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t> |
765 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) | 765 | Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t ) ) |
766 | { | 766 | { |
767 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 767 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
768 | return Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t>( | 768 | return Signal6<ret, p1t, p2t, p3t, p4t, p5t, p6t>( |
769 | new __Slot6F<ret, p1t, p2t, p3t, p4t, p5t, p6t>( pFnc ) | 769 | new __Slot6F<ret, p1t, p2t, p3t, p4t, p5t, p6t>( pFnc ) |
770 | ); | 770 | ); |
771 | } | 771 | } |
772 | #endif // BU_SIGNAL_PARAM_COUNT_6 | 772 | #endif // BU_SIGNAL_PARAM_COUNT_6 |
773 | 773 | ||
774 | #ifndef BU_SIGNAL_PARAM_COUNT_7 | 774 | #ifndef BU_SIGNAL_PARAM_COUNT_7 |
775 | #define BU_SIGNAL_PARAM_COUNT_7 | 775 | #define BU_SIGNAL_PARAM_COUNT_7 |
776 | // | 776 | // |
777 | // 7 Parameter(s) | 777 | // 7 Parameter(s) |
778 | // | 778 | // |
779 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 779 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
780 | class _Slot7 | 780 | class _Slot7 |
781 | { | 781 | { |
782 | public: | 782 | public: |
783 | _Slot7() { } | 783 | _Slot7() { } |
784 | virtual ~_Slot7() { } | 784 | virtual ~_Slot7() { } |
785 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 )=0; | 785 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 )=0; |
786 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const=0; | 786 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const=0; |
787 | }; | 787 | }; |
788 | 788 | ||
789 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 789 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
790 | class __Slot7 : public _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> | 790 | class __Slot7 : public _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> |
791 | { | 791 | { |
792 | public: | 792 | public: |
793 | __Slot7( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) : | 793 | __Slot7( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) : |
794 | pCls( pCls ), pFnc( pFnc ) { } | 794 | pCls( pCls ), pFnc( pFnc ) { } |
795 | virtual ~__Slot7() { } | 795 | virtual ~__Slot7() { } |
796 | 796 | ||
797 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) | 797 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) |
798 | { | 798 | { |
799 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7 ); | 799 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7 ); |
800 | } | 800 | } |
801 | 801 | ||
802 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const | 802 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const |
803 | { | 803 | { |
804 | return new __Slot7<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pCls, pFnc ); | 804 | return new __Slot7<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pCls, pFnc ); |
805 | } | 805 | } |
806 | 806 | ||
807 | private: | 807 | private: |
808 | cls *pCls; | 808 | cls *pCls; |
809 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ); | 809 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ); |
810 | }; | 810 | }; |
811 | 811 | ||
812 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 812 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
813 | class __Slot7F : public _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> | 813 | class __Slot7F : public _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> |
814 | { | 814 | { |
815 | public: | 815 | public: |
816 | __Slot7F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) : | 816 | __Slot7F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) : |
817 | pFnc( pFnc ) { } | 817 | pFnc( pFnc ) { } |
818 | virtual ~__Slot7F() { } | 818 | virtual ~__Slot7F() { } |
819 | 819 | ||
820 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) | 820 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) |
821 | { | 821 | { |
822 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7 ); | 822 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7 ); |
823 | } | 823 | } |
824 | 824 | ||
825 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const | 825 | virtual _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *clone() const |
826 | { | 826 | { |
827 | return new __Slot7F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pFnc ); | 827 | return new __Slot7F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pFnc ); |
828 | } | 828 | } |
829 | 829 | ||
830 | private: | 830 | private: |
831 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ); | 831 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ); |
832 | }; | 832 | }; |
833 | 833 | ||
834 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 834 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
835 | class Signal7 | 835 | class Signal7 |
836 | { | 836 | { |
837 | public: | 837 | public: |
838 | Signal7() : pCb( NULL ) { } | 838 | Signal7() : pCb( NULL ) { } |
839 | Signal7( _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *pCb ) : pCb( pCb ) { } | 839 | Signal7( _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *pCb ) : pCb( pCb ) { } |
840 | Signal7( const Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &rSrc ) : | 840 | Signal7( const Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &rSrc ) : |
841 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 841 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
842 | virtual ~Signal7() { delete pCb; pCb = NULL; } | 842 | virtual ~Signal7() { delete pCb; pCb = NULL; } |
843 | 843 | ||
844 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) | 844 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7 ) |
845 | { | 845 | { |
846 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 846 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
847 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7 ); | 847 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7 ); |
848 | } | 848 | } |
849 | 849 | ||
850 | bool isSet() const { return pCb != NULL; } | 850 | bool isSet() const { return pCb != NULL; } |
851 | operator bool() const { return isSet(); } | 851 | operator bool() const { return isSet(); } |
852 | 852 | ||
853 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &operator=( const Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &rhs ) | 853 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &operator=( const Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> &rhs ) |
854 | { | 854 | { |
855 | pCb = rhs.pCb->clone(); | 855 | pCb = rhs.pCb->clone(); |
856 | return *this; | 856 | return *this; |
857 | } | 857 | } |
858 | 858 | ||
859 | private: | 859 | private: |
860 | _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *pCb; | 860 | _Slot7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> *pCb; |
861 | }; | 861 | }; |
862 | 862 | ||
863 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 863 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
864 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) | 864 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) |
865 | { | 865 | { |
866 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 866 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
867 | return Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( | 867 | return Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( |
868 | new __Slot7<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pCls, pFnc ) | 868 | new __Slot7<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pCls, pFnc ) |
869 | ); | 869 | ); |
870 | } | 870 | } |
871 | 871 | ||
872 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> | 872 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t> |
873 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) | 873 | Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t ) ) |
874 | { | 874 | { |
875 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 875 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
876 | return Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( | 876 | return Signal7<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( |
877 | new __Slot7F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pFnc ) | 877 | new __Slot7F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t>( pFnc ) |
878 | ); | 878 | ); |
879 | } | 879 | } |
880 | #endif // BU_SIGNAL_PARAM_COUNT_7 | 880 | #endif // BU_SIGNAL_PARAM_COUNT_7 |
881 | 881 | ||
882 | #ifndef BU_SIGNAL_PARAM_COUNT_8 | 882 | #ifndef BU_SIGNAL_PARAM_COUNT_8 |
883 | #define BU_SIGNAL_PARAM_COUNT_8 | 883 | #define BU_SIGNAL_PARAM_COUNT_8 |
884 | // | 884 | // |
885 | // 8 Parameter(s) | 885 | // 8 Parameter(s) |
886 | // | 886 | // |
887 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 887 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
888 | class _Slot8 | 888 | class _Slot8 |
889 | { | 889 | { |
890 | public: | 890 | public: |
891 | _Slot8() { } | 891 | _Slot8() { } |
892 | virtual ~_Slot8() { } | 892 | virtual ~_Slot8() { } |
893 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 )=0; | 893 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 )=0; |
894 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const=0; | 894 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const=0; |
895 | }; | 895 | }; |
896 | 896 | ||
897 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 897 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
898 | class __Slot8 : public _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> | 898 | class __Slot8 : public _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> |
899 | { | 899 | { |
900 | public: | 900 | public: |
901 | __Slot8( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) : | 901 | __Slot8( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) : |
902 | pCls( pCls ), pFnc( pFnc ) { } | 902 | pCls( pCls ), pFnc( pFnc ) { } |
903 | virtual ~__Slot8() { } | 903 | virtual ~__Slot8() { } |
904 | 904 | ||
905 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) | 905 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) |
906 | { | 906 | { |
907 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8 ); | 907 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8 ); |
908 | } | 908 | } |
909 | 909 | ||
910 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const | 910 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const |
911 | { | 911 | { |
912 | return new __Slot8<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pCls, pFnc ); | 912 | return new __Slot8<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pCls, pFnc ); |
913 | } | 913 | } |
914 | 914 | ||
915 | private: | 915 | private: |
916 | cls *pCls; | 916 | cls *pCls; |
917 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ); | 917 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ); |
918 | }; | 918 | }; |
919 | 919 | ||
920 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 920 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
921 | class __Slot8F : public _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> | 921 | class __Slot8F : public _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> |
922 | { | 922 | { |
923 | public: | 923 | public: |
924 | __Slot8F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) : | 924 | __Slot8F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) : |
925 | pFnc( pFnc ) { } | 925 | pFnc( pFnc ) { } |
926 | virtual ~__Slot8F() { } | 926 | virtual ~__Slot8F() { } |
927 | 927 | ||
928 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) | 928 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) |
929 | { | 929 | { |
930 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8 ); | 930 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8 ); |
931 | } | 931 | } |
932 | 932 | ||
933 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const | 933 | virtual _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *clone() const |
934 | { | 934 | { |
935 | return new __Slot8F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pFnc ); | 935 | return new __Slot8F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pFnc ); |
936 | } | 936 | } |
937 | 937 | ||
938 | private: | 938 | private: |
939 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ); | 939 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ); |
940 | }; | 940 | }; |
941 | 941 | ||
942 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 942 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
943 | class Signal8 | 943 | class Signal8 |
944 | { | 944 | { |
945 | public: | 945 | public: |
946 | Signal8() : pCb( NULL ) { } | 946 | Signal8() : pCb( NULL ) { } |
947 | Signal8( _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *pCb ) : pCb( pCb ) { } | 947 | Signal8( _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *pCb ) : pCb( pCb ) { } |
948 | Signal8( const Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &rSrc ) : | 948 | Signal8( const Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &rSrc ) : |
949 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 949 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
950 | virtual ~Signal8() { delete pCb; pCb = NULL; } | 950 | virtual ~Signal8() { delete pCb; pCb = NULL; } |
951 | 951 | ||
952 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) | 952 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8 ) |
953 | { | 953 | { |
954 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 954 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
955 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8 ); | 955 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8 ); |
956 | } | 956 | } |
957 | 957 | ||
958 | bool isSet() const { return pCb != NULL; } | 958 | bool isSet() const { return pCb != NULL; } |
959 | operator bool() const { return isSet(); } | 959 | operator bool() const { return isSet(); } |
960 | 960 | ||
961 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &operator=( const Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &rhs ) | 961 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &operator=( const Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> &rhs ) |
962 | { | 962 | { |
963 | pCb = rhs.pCb->clone(); | 963 | pCb = rhs.pCb->clone(); |
964 | return *this; | 964 | return *this; |
965 | } | 965 | } |
966 | 966 | ||
967 | private: | 967 | private: |
968 | _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *pCb; | 968 | _Slot8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> *pCb; |
969 | }; | 969 | }; |
970 | 970 | ||
971 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 971 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
972 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) | 972 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) |
973 | { | 973 | { |
974 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 974 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
975 | return Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( | 975 | return Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( |
976 | new __Slot8<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pCls, pFnc ) | 976 | new __Slot8<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pCls, pFnc ) |
977 | ); | 977 | ); |
978 | } | 978 | } |
979 | 979 | ||
980 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> | 980 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t> |
981 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) | 981 | Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t ) ) |
982 | { | 982 | { |
983 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 983 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
984 | return Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( | 984 | return Signal8<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( |
985 | new __Slot8F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pFnc ) | 985 | new __Slot8F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t>( pFnc ) |
986 | ); | 986 | ); |
987 | } | 987 | } |
988 | #endif // BU_SIGNAL_PARAM_COUNT_8 | 988 | #endif // BU_SIGNAL_PARAM_COUNT_8 |
989 | 989 | ||
990 | #ifndef BU_SIGNAL_PARAM_COUNT_9 | 990 | #ifndef BU_SIGNAL_PARAM_COUNT_9 |
991 | #define BU_SIGNAL_PARAM_COUNT_9 | 991 | #define BU_SIGNAL_PARAM_COUNT_9 |
992 | // | 992 | // |
993 | // 9 Parameter(s) | 993 | // 9 Parameter(s) |
994 | // | 994 | // |
995 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 995 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
996 | class _Slot9 | 996 | class _Slot9 |
997 | { | 997 | { |
998 | public: | 998 | public: |
999 | _Slot9() { } | 999 | _Slot9() { } |
1000 | virtual ~_Slot9() { } | 1000 | virtual ~_Slot9() { } |
1001 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 )=0; | 1001 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 )=0; |
1002 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const=0; | 1002 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const=0; |
1003 | }; | 1003 | }; |
1004 | 1004 | ||
1005 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 1005 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
1006 | class __Slot9 : public _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> | 1006 | class __Slot9 : public _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> |
1007 | { | 1007 | { |
1008 | public: | 1008 | public: |
1009 | __Slot9( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) : | 1009 | __Slot9( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) : |
1010 | pCls( pCls ), pFnc( pFnc ) { } | 1010 | pCls( pCls ), pFnc( pFnc ) { } |
1011 | virtual ~__Slot9() { } | 1011 | virtual ~__Slot9() { } |
1012 | 1012 | ||
1013 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) | 1013 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) |
1014 | { | 1014 | { |
1015 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); | 1015 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const | 1018 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const |
1019 | { | 1019 | { |
1020 | return new __Slot9<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pCls, pFnc ); | 1020 | return new __Slot9<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pCls, pFnc ); |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | private: | 1023 | private: |
1024 | cls *pCls; | 1024 | cls *pCls; |
1025 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ); | 1025 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ); |
1026 | }; | 1026 | }; |
1027 | 1027 | ||
1028 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 1028 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
1029 | class __Slot9F : public _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> | 1029 | class __Slot9F : public _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> |
1030 | { | 1030 | { |
1031 | public: | 1031 | public: |
1032 | __Slot9F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) : | 1032 | __Slot9F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) : |
1033 | pFnc( pFnc ) { } | 1033 | pFnc( pFnc ) { } |
1034 | virtual ~__Slot9F() { } | 1034 | virtual ~__Slot9F() { } |
1035 | 1035 | ||
1036 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) | 1036 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) |
1037 | { | 1037 | { |
1038 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); | 1038 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); |
1039 | } | 1039 | } |
1040 | 1040 | ||
1041 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const | 1041 | virtual _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *clone() const |
1042 | { | 1042 | { |
1043 | return new __Slot9F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pFnc ); | 1043 | return new __Slot9F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pFnc ); |
1044 | } | 1044 | } |
1045 | 1045 | ||
1046 | private: | 1046 | private: |
1047 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ); | 1047 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ); |
1048 | }; | 1048 | }; |
1049 | 1049 | ||
1050 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 1050 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
1051 | class Signal9 | 1051 | class Signal9 |
1052 | { | 1052 | { |
1053 | public: | 1053 | public: |
1054 | Signal9() : pCb( NULL ) { } | 1054 | Signal9() : pCb( NULL ) { } |
1055 | Signal9( _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *pCb ) : pCb( pCb ) { } | 1055 | Signal9( _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *pCb ) : pCb( pCb ) { } |
1056 | Signal9( const Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &rSrc ) : | 1056 | Signal9( const Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &rSrc ) : |
1057 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 1057 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
1058 | virtual ~Signal9() { delete pCb; pCb = NULL; } | 1058 | virtual ~Signal9() { delete pCb; pCb = NULL; } |
1059 | 1059 | ||
1060 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) | 1060 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9 ) |
1061 | { | 1061 | { |
1062 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 1062 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
1063 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); | 1063 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8, p9 ); |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | bool isSet() const { return pCb != NULL; } | 1066 | bool isSet() const { return pCb != NULL; } |
1067 | operator bool() const { return isSet(); } | 1067 | operator bool() const { return isSet(); } |
1068 | 1068 | ||
1069 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &operator=( const Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &rhs ) | 1069 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &operator=( const Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> &rhs ) |
1070 | { | 1070 | { |
1071 | pCb = rhs.pCb->clone(); | 1071 | pCb = rhs.pCb->clone(); |
1072 | return *this; | 1072 | return *this; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | private: | 1075 | private: |
1076 | _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *pCb; | 1076 | _Slot9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> *pCb; |
1077 | }; | 1077 | }; |
1078 | 1078 | ||
1079 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 1079 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
1080 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) | 1080 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) |
1081 | { | 1081 | { |
1082 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 1082 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
1083 | return Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( | 1083 | return Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( |
1084 | new __Slot9<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pCls, pFnc ) | 1084 | new __Slot9<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pCls, pFnc ) |
1085 | ); | 1085 | ); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> | 1088 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t> |
1089 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) | 1089 | Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t ) ) |
1090 | { | 1090 | { |
1091 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 1091 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
1092 | return Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( | 1092 | return Signal9<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( |
1093 | new __Slot9F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pFnc ) | 1093 | new __Slot9F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t>( pFnc ) |
1094 | ); | 1094 | ); |
1095 | } | 1095 | } |
1096 | #endif // BU_SIGNAL_PARAM_COUNT_9 | 1096 | #endif // BU_SIGNAL_PARAM_COUNT_9 |
1097 | 1097 | ||
1098 | #ifndef BU_SIGNAL_PARAM_COUNT_10 | 1098 | #ifndef BU_SIGNAL_PARAM_COUNT_10 |
1099 | #define BU_SIGNAL_PARAM_COUNT_10 | 1099 | #define BU_SIGNAL_PARAM_COUNT_10 |
1100 | // | 1100 | // |
1101 | // 10 Parameter(s) | 1101 | // 10 Parameter(s) |
1102 | // | 1102 | // |
1103 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1103 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1104 | class _Slot10 | 1104 | class _Slot10 |
1105 | { | 1105 | { |
1106 | public: | 1106 | public: |
1107 | _Slot10() { } | 1107 | _Slot10() { } |
1108 | virtual ~_Slot10() { } | 1108 | virtual ~_Slot10() { } |
1109 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 )=0; | 1109 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 )=0; |
1110 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const=0; | 1110 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const=0; |
1111 | }; | 1111 | }; |
1112 | 1112 | ||
1113 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1113 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1114 | class __Slot10 : public _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> | 1114 | class __Slot10 : public _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> |
1115 | { | 1115 | { |
1116 | public: | 1116 | public: |
1117 | __Slot10( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) : | 1117 | __Slot10( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) : |
1118 | pCls( pCls ), pFnc( pFnc ) { } | 1118 | pCls( pCls ), pFnc( pFnc ) { } |
1119 | virtual ~__Slot10() { } | 1119 | virtual ~__Slot10() { } |
1120 | 1120 | ||
1121 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) | 1121 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) |
1122 | { | 1122 | { |
1123 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); | 1123 | return (pCls->*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const | 1126 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const |
1127 | { | 1127 | { |
1128 | return new __Slot10<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pCls, pFnc ); | 1128 | return new __Slot10<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pCls, pFnc ); |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | private: | 1131 | private: |
1132 | cls *pCls; | 1132 | cls *pCls; |
1133 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ); | 1133 | ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ); |
1134 | }; | 1134 | }; |
1135 | 1135 | ||
1136 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1136 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1137 | class __Slot10F : public _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> | 1137 | class __Slot10F : public _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> |
1138 | { | 1138 | { |
1139 | public: | 1139 | public: |
1140 | __Slot10F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) : | 1140 | __Slot10F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) : |
1141 | pFnc( pFnc ) { } | 1141 | pFnc( pFnc ) { } |
1142 | virtual ~__Slot10F() { } | 1142 | virtual ~__Slot10F() { } |
1143 | 1143 | ||
1144 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) | 1144 | virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) |
1145 | { | 1145 | { |
1146 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); | 1146 | return (*pFnc)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const | 1149 | virtual _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *clone() const |
1150 | { | 1150 | { |
1151 | return new __Slot10F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pFnc ); | 1151 | return new __Slot10F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pFnc ); |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | private: | 1154 | private: |
1155 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ); | 1155 | ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ); |
1156 | }; | 1156 | }; |
1157 | 1157 | ||
1158 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1158 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1159 | class Signal10 | 1159 | class Signal10 |
1160 | { | 1160 | { |
1161 | public: | 1161 | public: |
1162 | Signal10() : pCb( NULL ) { } | 1162 | Signal10() : pCb( NULL ) { } |
1163 | Signal10( _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *pCb ) : pCb( pCb ) { } | 1163 | Signal10( _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *pCb ) : pCb( pCb ) { } |
1164 | Signal10( const Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &rSrc ) : | 1164 | Signal10( const Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &rSrc ) : |
1165 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } | 1165 | pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } |
1166 | virtual ~Signal10() { delete pCb; pCb = NULL; } | 1166 | virtual ~Signal10() { delete pCb; pCb = NULL; } |
1167 | 1167 | ||
1168 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) | 1168 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5, p6t p6, p7t p7, p8t p8, p9t p9, p10t p10 ) |
1169 | { | 1169 | { |
1170 | if( !pCb ) throw SignalException("Uninitialized signal called."); | 1170 | if( !pCb ) throw SignalException("Uninitialized signal called."); |
1171 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); | 1171 | return (*pCb)( p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ); |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | bool isSet() const { return pCb != NULL; } | 1174 | bool isSet() const { return pCb != NULL; } |
1175 | operator bool() const { return isSet(); } | 1175 | operator bool() const { return isSet(); } |
1176 | 1176 | ||
1177 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &operator=( const Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &rhs ) | 1177 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &operator=( const Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> &rhs ) |
1178 | { | 1178 | { |
1179 | pCb = rhs.pCb->clone(); | 1179 | pCb = rhs.pCb->clone(); |
1180 | return *this; | 1180 | return *this; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | private: | 1183 | private: |
1184 | _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *pCb; | 1184 | _Slot10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> *pCb; |
1185 | }; | 1185 | }; |
1186 | 1186 | ||
1187 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1187 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1188 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) | 1188 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) |
1189 | { | 1189 | { |
1190 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | 1190 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); |
1191 | return Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( | 1191 | return Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( |
1192 | new __Slot10<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pCls, pFnc ) | 1192 | new __Slot10<cls, ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pCls, pFnc ) |
1193 | ); | 1193 | ); |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> | 1196 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t, typename p6t, typename p7t, typename p8t, typename p9t, typename p10t> |
1197 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) | 1197 | Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t ) ) |
1198 | { | 1198 | { |
1199 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | 1199 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); |
1200 | return Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( | 1200 | return Signal10<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( |
1201 | new __Slot10F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pFnc ) | 1201 | new __Slot10F<ret, p1t, p2t, p3t, p4t, p5t, p6t, p7t, p8t, p9t, p10t>( pFnc ) |
1202 | ); | 1202 | ); |
1203 | } | 1203 | } |
1204 | #endif // BU_SIGNAL_PARAM_COUNT_10 | 1204 | #endif // BU_SIGNAL_PARAM_COUNT_10 |
1205 | 1205 | ||
1206 | }; | 1206 | }; |
diff --git a/src/compat/win32.cpp b/src/compat/win32.cpp index e1151b0..38b9ad7 100644 --- a/src/compat/win32.cpp +++ b/src/compat/win32.cpp | |||
@@ -10,7 +10,7 @@ | |||
10 | #ifdef WIN32 | 10 | #ifdef WIN32 |
11 | 11 | ||
12 | #define deffunc( name ) \ | 12 | #define deffunc( name ) \ |
13 | Bu::Winsock2::FNDEF_DYN_ ##name Bu::Winsock2::_fnptr_ ##name = NULL | 13 | Bu::Winsock2::FNDEF_DYN_ ##name Bu::Winsock2::_fnptr_ ##name = NULL |
14 | 14 | ||
15 | char Bu::Winsock2::scode[32]; | 15 | char Bu::Winsock2::scode[32]; |
16 | 16 | ||
@@ -33,133 +33,133 @@ deffunc( getpeername ); | |||
33 | deffunc( setsockopt ); | 33 | deffunc( setsockopt ); |
34 | deffunc( bind ); | 34 | deffunc( bind ); |
35 | deffunc( listen ); | 35 | deffunc( listen ); |
36 | deffunc( accept ); | 36 | deffunc( accept ); |
37 | deffunc( recv ); | 37 | deffunc( recv ); |
38 | deffunc( send ); | 38 | deffunc( send ); |
39 | deffunc( __WSAFDIsSet ); | 39 | deffunc( __WSAFDIsSet ); |
40 | 40 | ||
41 | // Safely get a function from the library | 41 | // Safely get a function from the library |
42 | #define getfunc( name ) \ | 42 | #define getfunc( name ) \ |
43 | Bu::Winsock2::_fnptr_ ##name = (FNDEF_DYN_ ##name) \ | 43 | Bu::Winsock2::_fnptr_ ##name = (FNDEF_DYN_ ##name) \ |
44 | GetProcAddress( Ws2_32, #name ); \ | 44 | GetProcAddress( Ws2_32, #name ); \ |
45 | if( Bu::Winsock2::_fnptr_ ##name == NULL ) { \ | 45 | if( Bu::Winsock2::_fnptr_ ##name == NULL ) { \ |
46 | throw Bu::ExceptionBase("Error loading function " #name " from dll.");\ | 46 | throw Bu::ExceptionBase("Error loading function " #name " from dll.");\ |
47 | } (void)0 | 47 | } (void)0 |
48 | 48 | ||
49 | Bu::Winsock2::Winsock2() | 49 | Bu::Winsock2::Winsock2() |
50 | { | 50 | { |
51 | Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); | 51 | Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); |
52 | 52 | ||
53 | getfunc( WSAStartup ); | 53 | getfunc( WSAStartup ); |
54 | getfunc( WSACleanup ); | 54 | getfunc( WSACleanup ); |
55 | getfunc( WSAGetLastError ); | 55 | getfunc( WSAGetLastError ); |
56 | getfunc( inet_ntoa ); | 56 | getfunc( inet_ntoa ); |
57 | getfunc( inet_addr ); | 57 | getfunc( inet_addr ); |
58 | getfunc( select ); | 58 | getfunc( select ); |
59 | getfunc( socket ); | 59 | getfunc( socket ); |
60 | getfunc( shutdown ); | 60 | getfunc( shutdown ); |
61 | getfunc( ioctlsocket ); | 61 | getfunc( ioctlsocket ); |
62 | getfunc( htons ); | 62 | getfunc( htons ); |
63 | getfunc( htonl ); | 63 | getfunc( htonl ); |
64 | getfunc( gethostbyname ); | 64 | getfunc( gethostbyname ); |
65 | getfunc( freeaddrinfo ); | 65 | getfunc( freeaddrinfo ); |
66 | getfunc( getaddrinfo ); | 66 | getfunc( getaddrinfo ); |
67 | getfunc( connect ); | 67 | getfunc( connect ); |
68 | getfunc( getpeername ); | 68 | getfunc( getpeername ); |
69 | getfunc( setsockopt ); | 69 | getfunc( setsockopt ); |
70 | getfunc( bind ); | 70 | getfunc( bind ); |
71 | getfunc( listen ); | 71 | getfunc( listen ); |
72 | getfunc( accept ); | 72 | getfunc( accept ); |
73 | getfunc( recv ); | 73 | getfunc( recv ); |
74 | getfunc( send ); | 74 | getfunc( send ); |
75 | getfunc( __WSAFDIsSet ); | 75 | getfunc( __WSAFDIsSet ); |
76 | 76 | ||
77 | Bu::Winsock2::WSAStartup( MAKEWORD(2, 2), &wsaData ); | 77 | Bu::Winsock2::WSAStartup( MAKEWORD(2, 2), &wsaData ); |
78 | } | 78 | } |
79 | 79 | ||
80 | Bu::Winsock2::~Winsock2() | 80 | Bu::Winsock2::~Winsock2() |
81 | { | 81 | { |
82 | Bu::Winsock2::WSACleanup(); | 82 | Bu::Winsock2::WSACleanup(); |
83 | FreeLibrary( Ws2_32 ); | 83 | FreeLibrary( Ws2_32 ); |
84 | } | 84 | } |
85 | 85 | ||
86 | char *Bu::Winsock2::gai_strerror( int iCode ) | 86 | char *Bu::Winsock2::gai_strerror( int iCode ) |
87 | { | 87 | { |
88 | sprintf( scode, "%d (%d)", iCode, Bu::Winsock2::WSAGetLastError() ); | 88 | sprintf( scode, "%d (%d)", iCode, Bu::Winsock2::WSAGetLastError() ); |
89 | return scode; | 89 | return scode; |
90 | } | 90 | } |
91 | 91 | ||
92 | int Bu::Winsock2::WSAStartup( WORD a, LPWSADATA b ) { | 92 | int Bu::Winsock2::WSAStartup( WORD a, LPWSADATA b ) { |
93 | return (*Bu::Winsock2::_fnptr_WSAStartup)( a, b ); | 93 | return (*Bu::Winsock2::_fnptr_WSAStartup)( a, b ); |
94 | } | 94 | } |
95 | int Bu::Winsock2::WSACleanup( ) { | 95 | int Bu::Winsock2::WSACleanup( ) { |
96 | return (*Bu::Winsock2::_fnptr_WSACleanup)(); | 96 | return (*Bu::Winsock2::_fnptr_WSACleanup)(); |
97 | } | 97 | } |
98 | int Bu::Winsock2::WSAGetLastError( ) { | 98 | int Bu::Winsock2::WSAGetLastError( ) { |
99 | return (*Bu::Winsock2::_fnptr_WSAGetLastError)(); | 99 | return (*Bu::Winsock2::_fnptr_WSAGetLastError)(); |
100 | } | 100 | } |
101 | char * Bu::Winsock2::inet_ntoa( struct in_addr a ) { | 101 | char * Bu::Winsock2::inet_ntoa( struct in_addr a ) { |
102 | return (*Bu::Winsock2::_fnptr_inet_ntoa)( a ); | 102 | return (*Bu::Winsock2::_fnptr_inet_ntoa)( a ); |
103 | } | 103 | } |
104 | unsigned long Bu::Winsock2::inet_addr( const char *s_in ) { | 104 | unsigned long Bu::Winsock2::inet_addr( const char *s_in ) { |
105 | return (*Bu::Winsock2::_fnptr_inet_addr)( s_in ); | 105 | return (*Bu::Winsock2::_fnptr_inet_addr)( s_in ); |
106 | } | 106 | } |
107 | int Bu::Winsock2::select( int a, fd_set *b, fd_set *c, fd_set *d, | 107 | int Bu::Winsock2::select( int a, fd_set *b, fd_set *c, fd_set *d, |
108 | const struct timeval *e ) { | 108 | const struct timeval *e ) { |
109 | return (*Bu::Winsock2::_fnptr_select)( a, b, c, d, e ); | 109 | return (*Bu::Winsock2::_fnptr_select)( a, b, c, d, e ); |
110 | } | 110 | } |
111 | SOCKET Bu::Winsock2::socket( int domain, int type, int protocol ) { | 111 | SOCKET Bu::Winsock2::socket( int domain, int type, int protocol ) { |
112 | return (*Bu::Winsock2::_fnptr_socket)( domain, type, protocol ); | 112 | return (*Bu::Winsock2::_fnptr_socket)( domain, type, protocol ); |
113 | } | 113 | } |
114 | int Bu::Winsock2::shutdown( SOCKET s, int how ) { | 114 | int Bu::Winsock2::shutdown( SOCKET s, int how ) { |
115 | return (*Bu::Winsock2::_fnptr_shutdown)( s, how ); | 115 | return (*Bu::Winsock2::_fnptr_shutdown)( s, how ); |
116 | } | 116 | } |
117 | int Bu::Winsock2::ioctlsocket( SOCKET s, long cmd, u_long *argp ) { | 117 | int Bu::Winsock2::ioctlsocket( SOCKET s, long cmd, u_long *argp ) { |
118 | return (*Bu::Winsock2::_fnptr_ioctlsocket)( s, cmd, argp ); | 118 | return (*Bu::Winsock2::_fnptr_ioctlsocket)( s, cmd, argp ); |
119 | } | 119 | } |
120 | u_short Bu::Winsock2::htons( u_short in ) { | 120 | u_short Bu::Winsock2::htons( u_short in ) { |
121 | return (*Bu::Winsock2::_fnptr_htons)( in ); | 121 | return (*Bu::Winsock2::_fnptr_htons)( in ); |
122 | } | 122 | } |
123 | u_long Bu::Winsock2::htonl( u_long in ) { | 123 | u_long Bu::Winsock2::htonl( u_long in ) { |
124 | return (*Bu::Winsock2::_fnptr_htonl)( in ); | 124 | return (*Bu::Winsock2::_fnptr_htonl)( in ); |
125 | } | 125 | } |
126 | struct hostent * Bu::Winsock2::gethostbyname( const char *name ) { | 126 | struct hostent * Bu::Winsock2::gethostbyname( const char *name ) { |
127 | return (*Bu::Winsock2::_fnptr_gethostbyname)( name ); | 127 | return (*Bu::Winsock2::_fnptr_gethostbyname)( name ); |
128 | } | 128 | } |
129 | void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) { | 129 | void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) { |
130 | return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai ); | 130 | return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai ); |
131 | } | 131 | } |
132 | int Bu::Winsock2::getaddrinfo( const char *a, const char *b, | 132 | int Bu::Winsock2::getaddrinfo( const char *a, const char *b, |
133 | const struct addrinfo *c, struct addrinfo **d ) { | 133 | const struct addrinfo *c, struct addrinfo **d ) { |
134 | return (*Bu::Winsock2::_fnptr_getaddrinfo)( a, b, c, d ); | 134 | return (*Bu::Winsock2::_fnptr_getaddrinfo)( a, b, c, d ); |
135 | } | 135 | } |
136 | int Bu::Winsock2::connect( SOCKET s, const struct sockaddr *a, int b ) { | 136 | int Bu::Winsock2::connect( SOCKET s, const struct sockaddr *a, int b ) { |
137 | return (*Bu::Winsock2::_fnptr_connect)( s, a, b ); | 137 | return (*Bu::Winsock2::_fnptr_connect)( s, a, b ); |
138 | } | 138 | } |
139 | int Bu::Winsock2::getpeername( SOCKET s, struct sockaddr *a, int *b ) { | 139 | int Bu::Winsock2::getpeername( SOCKET s, struct sockaddr *a, int *b ) { |
140 | return (*Bu::Winsock2::_fnptr_getpeername)( s, a, b); | 140 | return (*Bu::Winsock2::_fnptr_getpeername)( s, a, b); |
141 | } | 141 | } |
142 | int Bu::Winsock2::setsockopt( SOCKET s, int a, int b, | 142 | int Bu::Winsock2::setsockopt( SOCKET s, int a, int b, |
143 | const char *c, int d ) { | 143 | const char *c, int d ) { |
144 | return (*Bu::Winsock2::_fnptr_setsockopt)( s, a, b, c, d ); | 144 | return (*Bu::Winsock2::_fnptr_setsockopt)( s, a, b, c, d ); |
145 | } | 145 | } |
146 | int Bu::Winsock2::bind( SOCKET s, const struct sockaddr *a, int b ) { | 146 | int Bu::Winsock2::bind( SOCKET s, const struct sockaddr *a, int b ) { |
147 | return (*Bu::Winsock2::_fnptr_bind)( s, a, b ); | 147 | return (*Bu::Winsock2::_fnptr_bind)( s, a, b ); |
148 | } | 148 | } |
149 | int Bu::Winsock2::listen( SOCKET s, int backlog ) { | 149 | int Bu::Winsock2::listen( SOCKET s, int backlog ) { |
150 | return (*Bu::Winsock2::_fnptr_listen)( s, backlog ); | 150 | return (*Bu::Winsock2::_fnptr_listen)( s, backlog ); |
151 | } | 151 | } |
152 | SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) { | 152 | SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) { |
153 | return (*Bu::Winsock2::_fnptr_accept)( s, a, b ); | 153 | return (*Bu::Winsock2::_fnptr_accept)( s, a, b ); |
154 | } | 154 | } |
155 | int Bu::Winsock2::recv( SOCKET s, char *buf, int len, int flags ) { | 155 | int Bu::Winsock2::recv( SOCKET s, char *buf, int len, int flags ) { |
156 | return (*Bu::Winsock2::_fnptr_recv)( s, buf, len, flags ); | 156 | return (*Bu::Winsock2::_fnptr_recv)( s, buf, len, flags ); |
157 | } | 157 | } |
158 | int Bu::Winsock2::send( SOCKET s, const char *buf, int len, int flags ) { | 158 | int Bu::Winsock2::send( SOCKET s, const char *buf, int len, int flags ) { |
159 | return (*Bu::Winsock2::_fnptr_send)( s, buf, len, flags ); | 159 | return (*Bu::Winsock2::_fnptr_send)( s, buf, len, flags ); |
160 | } | 160 | } |
161 | int Bu::Winsock2::__WSAFDIsSet( SOCKET s, fd_set *set ) { | 161 | int Bu::Winsock2::__WSAFDIsSet( SOCKET s, fd_set *set ) { |
162 | return (*Bu::Winsock2::_fnptr___WSAFDIsSet)( s, set ); | 162 | return (*Bu::Winsock2::_fnptr___WSAFDIsSet)( s, set ); |
163 | } | 163 | } |
164 | 164 | ||
165 | Bu::String Bu::getLastWinError() | 165 | Bu::String Bu::getLastWinError() |
@@ -177,11 +177,11 @@ Bu::String Bu::getLastWinError() | |||
177 | (LPSTR) &lpMsgBuf, | 177 | (LPSTR) &lpMsgBuf, |
178 | 0, NULL ); | 178 | 0, NULL ); |
179 | 179 | ||
180 | Bu::String sRet( (char *)lpMsgBuf ); | 180 | Bu::String sRet( (char *)lpMsgBuf ); |
181 | 181 | ||
182 | LocalFree(lpMsgBuf); | 182 | LocalFree(lpMsgBuf); |
183 | 183 | ||
184 | return sRet; | 184 | return sRet; |
185 | } | 185 | } |
186 | 186 | ||
187 | #endif | 187 | #endif |
diff --git a/src/compat/win32.h b/src/compat/win32.h index 7e44c13..0cc42b6 100644 --- a/src/compat/win32.h +++ b/src/compat/win32.h | |||
@@ -32,9 +32,9 @@ extern "C" | |||
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #define decltype( ret, name, ... ) \ | 34 | #define decltype( ret, name, ... ) \ |
35 | typedef ret (__cdecl *FNDEF_DYN_ ##name)( __VA_ARGS__ ); \ | 35 | typedef ret (__cdecl *FNDEF_DYN_ ##name)( __VA_ARGS__ ); \ |
36 | static FNDEF_DYN_ ##name _fnptr_ ##name; \ | 36 | static FNDEF_DYN_ ##name _fnptr_ ##name; \ |
37 | static ret name( __VA_ARGS__ ) | 37 | static ret name( __VA_ARGS__ ) |
38 | 38 | ||
39 | __extension__ typedef int socklen_t; | 39 | __extension__ typedef int socklen_t; |
40 | 40 | ||
@@ -44,54 +44,54 @@ __extension__ typedef int socklen_t; | |||
44 | 44 | ||
45 | namespace Bu | 45 | namespace Bu |
46 | { | 46 | { |
47 | class Winsock2 : public Bu::Singleton<Winsock2> | 47 | class Winsock2 : public Bu::Singleton<Winsock2> |
48 | { | 48 | { |
49 | friend class Bu::Singleton<Winsock2>; | 49 | friend class Bu::Singleton<Winsock2>; |
50 | private: | 50 | private: |
51 | Winsock2(); | 51 | Winsock2(); |
52 | virtual ~Winsock2(); | 52 | virtual ~Winsock2(); |
53 | 53 | ||
54 | WSADATA wsaData; | 54 | WSADATA wsaData; |
55 | HINSTANCE Ws2_32; | 55 | HINSTANCE Ws2_32; |
56 | 56 | ||
57 | public: | 57 | public: |
58 | // decltype( return type, function name<, optional parameters> ) | 58 | // decltype( return type, function name<, optional parameters> ) |
59 | decltype( int, WSAStartup, WORD, LPWSADATA ); | 59 | decltype( int, WSAStartup, WORD, LPWSADATA ); |
60 | decltype( int, WSACleanup ); | 60 | decltype( int, WSACleanup ); |
61 | decltype( int, WSAGetLastError ); | 61 | decltype( int, WSAGetLastError ); |
62 | decltype( char *, inet_ntoa, struct in_addr ); | 62 | decltype( char *, inet_ntoa, struct in_addr ); |
63 | decltype( unsigned long, inet_addr, const char *s_in ); | 63 | decltype( unsigned long, inet_addr, const char *s_in ); |
64 | decltype( int, select, int nfds, fd_set *readfds, fd_set *writefds, | 64 | decltype( int, select, int nfds, fd_set *readfds, fd_set *writefds, |
65 | fd_set *exceptfds, const struct timeval *timeout ); | 65 | fd_set *exceptfds, const struct timeval *timeout ); |
66 | decltype( SOCKET, socket, int domain, int type, int protocol ); | 66 | decltype( SOCKET, socket, int domain, int type, int protocol ); |
67 | decltype( int, shutdown, SOCKET s, int how ); | 67 | decltype( int, shutdown, SOCKET s, int how ); |
68 | decltype( int, ioctlsocket, SOCKET s, long cmd, u_long *argp ); | 68 | decltype( int, ioctlsocket, SOCKET s, long cmd, u_long *argp ); |
69 | decltype( u_short, htons, u_short in ); | 69 | decltype( u_short, htons, u_short in ); |
70 | decltype( u_long, htonl, u_long in ); | 70 | decltype( u_long, htonl, u_long in ); |
71 | decltype( struct hostent *, gethostbyname, const char *name ); | 71 | decltype( struct hostent *, gethostbyname, const char *name ); |
72 | decltype( void, freeaddrinfo, struct addrinfo *ai ); | 72 | decltype( void, freeaddrinfo, struct addrinfo *ai ); |
73 | decltype( int, getaddrinfo, const char *nodename, const char *servname, | 73 | decltype( int, getaddrinfo, const char *nodename, const char *servname, |
74 | const struct addrinfo *hints, struct addrinfo **res ); | 74 | const struct addrinfo *hints, struct addrinfo **res ); |
75 | decltype( int, connect, SOCKET s, const struct sockaddr *serv_addr, | 75 | decltype( int, connect, SOCKET s, const struct sockaddr *serv_addr, |
76 | int addrlen ); | 76 | int addrlen ); |
77 | decltype( int, getpeername, SOCKET s, struct sockaddr *name, | 77 | decltype( int, getpeername, SOCKET s, struct sockaddr *name, |
78 | int *namelen ); | 78 | int *namelen ); |
79 | decltype( int, setsockopt, SOCKET s, int level, int optname, | 79 | decltype( int, setsockopt, SOCKET s, int level, int optname, |
80 | const char *optval, int optlen ); | 80 | const char *optval, int optlen ); |
81 | decltype( int, bind, SOCKET s, const struct sockaddr *my_addr, | 81 | decltype( int, bind, SOCKET s, const struct sockaddr *my_addr, |
82 | int addrlen ); | 82 | int addrlen ); |
83 | decltype( int, listen, SOCKET s, int backlog ); | 83 | decltype( int, listen, SOCKET s, int backlog ); |
84 | decltype( SOCKET, accept, SOCKET s, struct sockaddr *addr, | 84 | decltype( SOCKET, accept, SOCKET s, struct sockaddr *addr, |
85 | int *addrlen); | 85 | int *addrlen); |
86 | decltype( int, recv, SOCKET s, char *buf, int len, int flags ); | 86 | decltype( int, recv, SOCKET s, char *buf, int len, int flags ); |
87 | decltype( int, send, SOCKET s, const char *buf, int len, int flags ); | 87 | decltype( int, send, SOCKET s, const char *buf, int len, int flags ); |
88 | decltype( int, __WSAFDIsSet, SOCKET s, fd_set *set ); | 88 | decltype( int, __WSAFDIsSet, SOCKET s, fd_set *set ); |
89 | 89 | ||
90 | static char scode[32]; | 90 | static char scode[32]; |
91 | static char *gai_strerror( int iCode ); | 91 | static char *gai_strerror( int iCode ); |
92 | }; | 92 | }; |
93 | 93 | ||
94 | Bu::String getLastWinError(); | 94 | Bu::String getLastWinError(); |
95 | }; | 95 | }; |
96 | 96 | ||
97 | #ifdef FD_ISSET | 97 | #ifdef FD_ISSET |
@@ -117,7 +117,7 @@ namespace Bu | |||
117 | #define bu_setsockopt (*Bu::Winsock2::setsockopt) | 117 | #define bu_setsockopt (*Bu::Winsock2::setsockopt) |
118 | #define bu_bind (*Bu::Winsock2::bind) | 118 | #define bu_bind (*Bu::Winsock2::bind) |
119 | #define bu_listen (*Bu::Winsock2::listen) | 119 | #define bu_listen (*Bu::Winsock2::listen) |
120 | #define bu_accept (*Bu::Winsock2::accept) | 120 | #define bu_accept (*Bu::Winsock2::accept) |
121 | #define bu_recv (*Bu::Winsock2::recv) | 121 | #define bu_recv (*Bu::Winsock2::recv) |
122 | #define bu_send (*Bu::Winsock2::send) | 122 | #define bu_send (*Bu::Winsock2::send) |
123 | #define bu___WSAFDIsSet (*Bu::Winsock2::__WSAFDIsSet) | 123 | #define bu___WSAFDIsSet (*Bu::Winsock2::__WSAFDIsSet) |
diff --git a/src/config.h b/src/config.h index fa304bb..c73906b 100644 --- a/src/config.h +++ b/src/config.h | |||
@@ -20,9 +20,9 @@ | |||
20 | #ifndef WIN32 | 20 | #ifndef WIN32 |
21 | # include "bu/autoconfig.h" | 21 | # include "bu/autoconfig.h" |
22 | #else | 22 | #else |
23 | # define __LITTLE_ENDIAN 1234 | 23 | # define __LITTLE_ENDIAN 1234 |
24 | # define __BIG_ENDIAN 4321 | 24 | # define __BIG_ENDIAN 4321 |
25 | # define __PDP_ENDIAN 3412 | 25 | # define __PDP_ENDIAN 3412 |
26 | # define __BYTE_ORDER __LITTLE_ENDIAN | 26 | # define __BYTE_ORDER __LITTLE_ENDIAN |
27 | 27 | ||
28 | # ifndef LITTLE_ENDIAN | 28 | # ifndef LITTLE_ENDIAN |
diff --git a/src/experimental/blowfish.h b/src/experimental/blowfish.h index 0308026..b287bd4 100644 --- a/src/experimental/blowfish.h +++ b/src/experimental/blowfish.h | |||
@@ -23,454 +23,454 @@ | |||
23 | #define MAX_STRING 256 | 23 | #define MAX_STRING 256 |
24 | #define MAX_PASSWD 56 // 448bits | 24 | #define MAX_PASSWD 56 // 448bits |
25 | #define F(x) \ | 25 | #define F(x) \ |
26 | (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ | 26 | (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + \ |
27 | SB[3][x.byte.three]) | 27 | SB[3][x.byte.three]) |
28 | #define revBytes( x ) x = (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24)) | 28 | #define revBytes( x ) x = (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24)) |
29 | 29 | ||
30 | namespace Bu | 30 | namespace Bu |
31 | { | 31 | { |
32 | template<int Mode> | 32 | template<int Mode> |
33 | class Blowfish : public Bu::Cipher<8> | 33 | class Blowfish : public Bu::Cipher<8> |
34 | { | 34 | { |
35 | public: | 35 | public: |
36 | Blowfish( Bu::Stream &rNext ) : | 36 | Blowfish( Bu::Stream &rNext ) : |
37 | Bu::Cipher<8>( rNext ) | 37 | Bu::Cipher<8>( rNext ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | virtual ~Blowfish() | 41 | virtual ~Blowfish() |
42 | { | 42 | { |
43 | stop(); | 43 | stop(); |
44 | reset(); | 44 | reset(); |
45 | } | 45 | } |
46 | 46 | ||
47 | void setPassword( const Bu::String &sPass ) | 47 | void setPassword( const Bu::String &sPass ) |
48 | { | 48 | { |
49 | reset(); | 49 | reset(); |
50 | 50 | ||
51 | uint32_t i,j,len=sPass.getSize(); | 51 | uint32_t i,j,len=sPass.getSize(); |
52 | Word Work,null0,null1; | 52 | Word Work,null0,null1; |
53 | 53 | ||
54 | if (len > 0) | 54 | if (len > 0) |
55 | { | 55 | { |
56 | j = 0; | 56 | j = 0; |
57 | for (i=0;i<NUM_SUBKEYS;i++) | 57 | for (i=0;i<NUM_SUBKEYS;i++) |
58 | { | 58 | { |
59 | Work.byte.zero = sPass[(j++)%len]; | 59 | Work.byte.zero = sPass[(j++)%len]; |
60 | Work.byte.one = sPass[(j++)%len]; | 60 | Work.byte.one = sPass[(j++)%len]; |
61 | Work.byte.two = sPass[(j++)%len]; | 61 | Work.byte.two = sPass[(j++)%len]; |
62 | Work.byte.three = sPass[(j++)%len]; | 62 | Work.byte.three = sPass[(j++)%len]; |
63 | PA[i] ^= Work.word; | 63 | PA[i] ^= Work.word; |
64 | } | 64 | } |
65 | 65 | ||
66 | null0.word = null1.word = 0; | 66 | null0.word = null1.word = 0; |
67 | 67 | ||
68 | for (i=0;i<NUM_SUBKEYS;i+=2) | 68 | for (i=0;i<NUM_SUBKEYS;i+=2) |
69 | { | 69 | { |
70 | keyEncipher( null0, null1 ); | 70 | keyEncipher( null0, null1 ); |
71 | PA[i] = null0.word; | 71 | PA[i] = null0.word; |
72 | PA[i+1] = null1.word; | 72 | PA[i+1] = null1.word; |
73 | } | 73 | } |
74 | 74 | ||
75 | for (j=0;j<NUM_S_BOXES;j++) | 75 | for (j=0;j<NUM_S_BOXES;j++) |
76 | for (i=0;i<NUM_ENTRIES;i+=2) | 76 | for (i=0;i<NUM_ENTRIES;i+=2) |
77 | { | 77 | { |
78 | keyEncipher( null0, null1 ); | 78 | keyEncipher( null0, null1 ); |
79 | SB[j][i] = null0.word; | 79 | SB[j][i] = null0.word; |
80 | SB[j][i+1] = null1.word; | 80 | SB[j][i+1] = null1.word; |
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | Work.word = null0.word = null1.word = 0; | 84 | Work.word = null0.word = null1.word = 0; |
85 | len = 0; | 85 | len = 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | private: | 88 | private: |
89 | uint32_t PA[NUM_SUBKEYS]; | 89 | uint32_t PA[NUM_SUBKEYS]; |
90 | uint32_t SB[NUM_S_BOXES][NUM_ENTRIES]; | 90 | uint32_t SB[NUM_S_BOXES][NUM_ENTRIES]; |
91 | 91 | ||
92 | #if __BYTE_ORDER == __BIG_ENDIAN | 92 | #if __BYTE_ORDER == __BIG_ENDIAN |
93 | struct WordByte | 93 | struct WordByte |
94 | { | 94 | { |
95 | uint32_t zero:8; | 95 | uint32_t zero:8; |
96 | uint32_t one:8; | 96 | uint32_t one:8; |
97 | uint32_t two:8; | 97 | uint32_t two:8; |
98 | uint32_t three:8; | 98 | uint32_t three:8; |
99 | }; | 99 | }; |
100 | #elif __BYTE_ORDER == __LITTLE_ENDIAN | 100 | #elif __BYTE_ORDER == __LITTLE_ENDIAN |
101 | struct WordByte | 101 | struct WordByte |
102 | { | 102 | { |
103 | uint32_t three:8; | 103 | uint32_t three:8; |
104 | uint32_t two:8; | 104 | uint32_t two:8; |
105 | uint32_t one:8; | 105 | uint32_t one:8; |
106 | uint32_t zero:8; | 106 | uint32_t zero:8; |
107 | }; | 107 | }; |
108 | #else | 108 | #else |
109 | #error No endianness defined | 109 | #error No endianness defined |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | union Word | 112 | union Word |
113 | { | 113 | { |
114 | uint32_t word; | 114 | uint32_t word; |
115 | WordByte byte; | 115 | WordByte byte; |
116 | }; | 116 | }; |
117 | 117 | ||
118 | struct DWord | 118 | struct DWord |
119 | { | 119 | { |
120 | Word word0; | 120 | Word word0; |
121 | Word word1; | 121 | Word word1; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | void reset() | 124 | void reset() |
125 | { | 125 | { |
126 | uint32_t i,j; | 126 | uint32_t i,j; |
127 | 127 | ||
128 | static uint32_t PA_Init[NUM_SUBKEYS] = | 128 | static uint32_t PA_Init[NUM_SUBKEYS] = |
129 | { | 129 | { |
130 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, | 130 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, |
131 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, | 131 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, |
132 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, | 132 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, |
133 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, | 133 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, |
134 | 0x9216d5d9, 0x8979fb1b | 134 | 0x9216d5d9, 0x8979fb1b |
135 | }; | 135 | }; |
136 | 136 | ||
137 | static uint32_t SB_Init[NUM_S_BOXES][NUM_ENTRIES] = { | 137 | static uint32_t SB_Init[NUM_S_BOXES][NUM_ENTRIES] = { |
138 | { | 138 | { |
139 | 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, | 139 | 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, |
140 | 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, | 140 | 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, |
141 | 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, | 141 | 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, |
142 | 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, | 142 | 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, |
143 | 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, | 143 | 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, |
144 | 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, | 144 | 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, |
145 | 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, | 145 | 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, |
146 | 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, | 146 | 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, |
147 | 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, | 147 | 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, |
148 | 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, | 148 | 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, |
149 | 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, | 149 | 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, |
150 | 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, | 150 | 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, |
151 | 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, | 151 | 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, |
152 | 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, | 152 | 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, |
153 | 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, | 153 | 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, |
154 | 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, | 154 | 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, |
155 | 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, | 155 | 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, |
156 | 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, | 156 | 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, |
157 | 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, | 157 | 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, |
158 | 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, | 158 | 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, |
159 | 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, | 159 | 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, |
160 | 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, | 160 | 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, |
161 | 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, | 161 | 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, |
162 | 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, | 162 | 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, |
163 | 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, | 163 | 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, |
164 | 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, | 164 | 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, |
165 | 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, | 165 | 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, |
166 | 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, | 166 | 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, |
167 | 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, | 167 | 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, |
168 | 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, | 168 | 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, |
169 | 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, | 169 | 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, |
170 | 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, | 170 | 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, |
171 | 171 | ||
172 | 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, | 172 | 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, |
173 | 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, | 173 | 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, |
174 | 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, | 174 | 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, |
175 | 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, | 175 | 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, |
176 | 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, | 176 | 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, |
177 | 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, | 177 | 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, |
178 | 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, | 178 | 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, |
179 | 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, | 179 | 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, |
180 | 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, | 180 | 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, |
181 | 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, | 181 | 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, |
182 | 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, | 182 | 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, |
183 | 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, | 183 | 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, |
184 | 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, | 184 | 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, |
185 | 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, | 185 | 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, |
186 | 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, | 186 | 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, |
187 | 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, | 187 | 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, |
188 | 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, | 188 | 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, |
189 | 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, | 189 | 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, |
190 | 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, | 190 | 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, |
191 | 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, | 191 | 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, |
192 | 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, | 192 | 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, |
193 | 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, | 193 | 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, |
194 | 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, | 194 | 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, |
195 | 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, | 195 | 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, |
196 | 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, | 196 | 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, |
197 | 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, | 197 | 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, |
198 | 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, | 198 | 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, |
199 | 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, | 199 | 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, |
200 | 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, | 200 | 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, |
201 | 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, | 201 | 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, |
202 | 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, | 202 | 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, |
203 | 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a | 203 | 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a |
204 | }, { | 204 | }, { |
205 | 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, | 205 | 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, |
206 | 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, | 206 | 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, |
207 | 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, | 207 | 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, |
208 | 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, | 208 | 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, |
209 | 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, | 209 | 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, |
210 | 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, | 210 | 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, |
211 | 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, | 211 | 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, |
212 | 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, | 212 | 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, |
213 | 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, | 213 | 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, |
214 | 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, | 214 | 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, |
215 | 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, | 215 | 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, |
216 | 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, | 216 | 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, |
217 | 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, | 217 | 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, |
218 | 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, | 218 | 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, |
219 | 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, | 219 | 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, |
220 | 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, | 220 | 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, |
221 | 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, | 221 | 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, |
222 | 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, | 222 | 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, |
223 | 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, | 223 | 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, |
224 | 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, | 224 | 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, |
225 | 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, | 225 | 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, |
226 | 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, | 226 | 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, |
227 | 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, | 227 | 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, |
228 | 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, | 228 | 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, |
229 | 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, | 229 | 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, |
230 | 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, | 230 | 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, |
231 | 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, | 231 | 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, |
232 | 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, | 232 | 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, |
233 | 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, | 233 | 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, |
234 | 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, | 234 | 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, |
235 | 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, | 235 | 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, |
236 | 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, | 236 | 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, |
237 | 237 | ||
238 | 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, | 238 | 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, |
239 | 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, | 239 | 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, |
240 | 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, | 240 | 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, |
241 | 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, | 241 | 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, |
242 | 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, | 242 | 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, |
243 | 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, | 243 | 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, |
244 | 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, | 244 | 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, |
245 | 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, | 245 | 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, |
246 | 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, | 246 | 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, |
247 | 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, | 247 | 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, |
248 | 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, | 248 | 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, |
249 | 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, | 249 | 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, |
250 | 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, | 250 | 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, |
251 | 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, | 251 | 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, |
252 | 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, | 252 | 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, |
253 | 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, | 253 | 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, |
254 | 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, | 254 | 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, |
255 | 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, | 255 | 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, |
256 | 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, | 256 | 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, |
257 | 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, | 257 | 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, |
258 | 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, | 258 | 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, |
259 | 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, | 259 | 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, |
260 | 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, | 260 | 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, |
261 | 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, | 261 | 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, |
262 | 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, | 262 | 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, |
263 | 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, | 263 | 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, |
264 | 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, | 264 | 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, |
265 | 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, | 265 | 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, |
266 | 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, | 266 | 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, |
267 | 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, | 267 | 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, |
268 | 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, | 268 | 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, |
269 | 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 | 269 | 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 |
270 | }, { | 270 | }, { |
271 | 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, | 271 | 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, |
272 | 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, | 272 | 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, |
273 | 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, | 273 | 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, |
274 | 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, | 274 | 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, |
275 | 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, | 275 | 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, |
276 | 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, | 276 | 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, |
277 | 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, | 277 | 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, |
278 | 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, | 278 | 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, |
279 | 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, | 279 | 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, |
280 | 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, | 280 | 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, |
281 | 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, | 281 | 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, |
282 | 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, | 282 | 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, |
283 | 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, | 283 | 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, |
284 | 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, | 284 | 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, |
285 | 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, | 285 | 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, |
286 | 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, | 286 | 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, |
287 | 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, | 287 | 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, |
288 | 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, | 288 | 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, |
289 | 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, | 289 | 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, |
290 | 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, | 290 | 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, |
291 | 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, | 291 | 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, |
292 | 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, | 292 | 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, |
293 | 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, | 293 | 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, |
294 | 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, | 294 | 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, |
295 | 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, | 295 | 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, |
296 | 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, | 296 | 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, |
297 | 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, | 297 | 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, |
298 | 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, | 298 | 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, |
299 | 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, | 299 | 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, |
300 | 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, | 300 | 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, |
301 | 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, | 301 | 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, |
302 | 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, | 302 | 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, |
303 | 303 | ||
304 | 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, | 304 | 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, |
305 | 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, | 305 | 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, |
306 | 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, | 306 | 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, |
307 | 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, | 307 | 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, |
308 | 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, | 308 | 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, |
309 | 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, | 309 | 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, |
310 | 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, | 310 | 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, |
311 | 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, | 311 | 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, |
312 | 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, | 312 | 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, |
313 | 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, | 313 | 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, |
314 | 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, | 314 | 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, |
315 | 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, | 315 | 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, |
316 | 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, | 316 | 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, |
317 | 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, | 317 | 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, |
318 | 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, | 318 | 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, |
319 | 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, | 319 | 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, |
320 | 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, | 320 | 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, |
321 | 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, | 321 | 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, |
322 | 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, | 322 | 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, |
323 | 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, | 323 | 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, |
324 | 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, | 324 | 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, |
325 | 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, | 325 | 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, |
326 | 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, | 326 | 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, |
327 | 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, | 327 | 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, |
328 | 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, | 328 | 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, |
329 | 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, | 329 | 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, |
330 | 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, | 330 | 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, |
331 | 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, | 331 | 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, |
332 | 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, | 332 | 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, |
333 | 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, | 333 | 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, |
334 | 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, | 334 | 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, |
335 | 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 | 335 | 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 |
336 | }, { | 336 | }, { |
337 | 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, | 337 | 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, |
338 | 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, | 338 | 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, |
339 | 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, | 339 | 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, |
340 | 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, | 340 | 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, |
341 | 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, | 341 | 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, |
342 | 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, | 342 | 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, |
343 | 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, | 343 | 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, |
344 | 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, | 344 | 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, |
345 | 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, | 345 | 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, |
346 | 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, | 346 | 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, |
347 | 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, | 347 | 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, |
348 | 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, | 348 | 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, |
349 | 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, | 349 | 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, |
350 | 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, | 350 | 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, |
351 | 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, | 351 | 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, |
352 | 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, | 352 | 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, |
353 | 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, | 353 | 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, |
354 | 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, | 354 | 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, |
355 | 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, | 355 | 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, |
356 | 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, | 356 | 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, |
357 | 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, | 357 | 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, |
358 | 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, | 358 | 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, |
359 | 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, | 359 | 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, |
360 | 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, | 360 | 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, |
361 | 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, | 361 | 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, |
362 | 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, | 362 | 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, |
363 | 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, | 363 | 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, |
364 | 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, | 364 | 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, |
365 | 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, | 365 | 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, |
366 | 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, | 366 | 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, |
367 | 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, | 367 | 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, |
368 | 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, | 368 | 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, |
369 | 369 | ||
370 | 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, | 370 | 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, |
371 | 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, | 371 | 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, |
372 | 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, | 372 | 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, |
373 | 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, | 373 | 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, |
374 | 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, | 374 | 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, |
375 | 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, | 375 | 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, |
376 | 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, | 376 | 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, |
377 | 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, | 377 | 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, |
378 | 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, | 378 | 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, |
379 | 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, | 379 | 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, |
380 | 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, | 380 | 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, |
381 | 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, | 381 | 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, |
382 | 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, | 382 | 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, |
383 | 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, | 383 | 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, |
384 | 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, | 384 | 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, |
385 | 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, | 385 | 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, |
386 | 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, | 386 | 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, |
387 | 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, | 387 | 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, |
388 | 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, | 388 | 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, |
389 | 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, | 389 | 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, |
390 | 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, | 390 | 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, |
391 | 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, | 391 | 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, |
392 | 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, | 392 | 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, |
393 | 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, | 393 | 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, |
394 | 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, | 394 | 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, |
395 | 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, | 395 | 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, |
396 | 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, | 396 | 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, |
397 | 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, | 397 | 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, |
398 | 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, | 398 | 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, |
399 | 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, | 399 | 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, |
400 | 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, | 400 | 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, |
401 | 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 | 401 | 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 |
402 | } | 402 | } |
403 | }; | 403 | }; |
404 | 404 | ||
405 | for (i=0;i<NUM_SUBKEYS;i++) | 405 | for (i=0;i<NUM_SUBKEYS;i++) |
406 | PA[i] = PA_Init[i]; | 406 | PA[i] = PA_Init[i]; |
407 | 407 | ||
408 | for (j=0;j<NUM_S_BOXES;j++) | 408 | for (j=0;j<NUM_S_BOXES;j++) |
409 | for (i=0;i<NUM_ENTRIES;i++) | 409 | for (i=0;i<NUM_ENTRIES;i++) |
410 | SB[j][i] = SB_Init[j][i]; | 410 | SB[j][i] = SB_Init[j][i]; |
411 | } | 411 | } |
412 | 412 | ||
413 | protected: | 413 | protected: |
414 | virtual void encipher( void *pData ) | 414 | virtual void encipher( void *pData ) |
415 | { | 415 | { |
416 | DWord *dwWork = (DWord *)pData; | 416 | DWord *dwWork = (DWord *)pData; |
417 | Word &w1 = dwWork->word0, &w2 = dwWork->word1; | 417 | Word &w1 = dwWork->word0, &w2 = dwWork->word1; |
418 | 418 | ||
419 | w1.word = be32toh( w1.word ); | 419 | w1.word = be32toh( w1.word ); |
420 | w2.word = be32toh( w2.word ); | 420 | w2.word = be32toh( w2.word ); |
421 | 421 | ||
422 | keyEncipher( w1, w2 ); | 422 | keyEncipher( w1, w2 ); |
423 | 423 | ||
424 | revBytes( w1.word ); | 424 | revBytes( w1.word ); |
425 | revBytes( w2.word ); | 425 | revBytes( w2.word ); |
426 | } | 426 | } |
427 | 427 | ||
428 | virtual void decipher( void *pData ) | 428 | virtual void decipher( void *pData ) |
429 | { | 429 | { |
430 | DWord *dwWork = (DWord *)pData; | 430 | DWord *dwWork = (DWord *)pData; |
431 | Word &w1 = dwWork->word0, &w2 = dwWork->word1; | 431 | Word &w1 = dwWork->word0, &w2 = dwWork->word1; |
432 | 432 | ||
433 | revBytes( w1.word ); | 433 | revBytes( w1.word ); |
434 | revBytes( w2.word ); | 434 | revBytes( w2.word ); |
435 | 435 | ||
436 | w1.word ^= PA[17]; | 436 | w1.word ^= PA[17]; |
437 | w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15]; | 437 | w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15]; |
438 | w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13]; | 438 | w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13]; |
439 | w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11]; | 439 | w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11]; |
440 | w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9]; | 440 | w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9]; |
441 | w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7]; | 441 | w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7]; |
442 | w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5]; | 442 | w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5]; |
443 | w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3]; | 443 | w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3]; |
444 | w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1]; | 444 | w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1]; |
445 | w2.word ^= PA[0]; | 445 | w2.word ^= PA[0]; |
446 | 446 | ||
447 | Bu::swap( w1, w2 ); | 447 | Bu::swap( w1, w2 ); |
448 | 448 | ||
449 | w1.word = htobe32( w1.word ); | 449 | w1.word = htobe32( w1.word ); |
450 | w2.word = htobe32( w2.word ); | 450 | w2.word = htobe32( w2.word ); |
451 | } | 451 | } |
452 | 452 | ||
453 | inline void keyEncipher( Word &w1, Word &w2 ) | 453 | inline void keyEncipher( Word &w1, Word &w2 ) |
454 | { | 454 | { |
455 | w1.word ^= PA[0]; | 455 | w1.word ^= PA[0]; |
456 | w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2]; | 456 | w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2]; |
457 | w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4]; | 457 | w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4]; |
458 | w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6]; | 458 | w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6]; |
459 | w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8]; | 459 | w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8]; |
460 | w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10]; | 460 | w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10]; |
461 | w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12]; | 461 | w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12]; |
462 | w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14]; | 462 | w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14]; |
463 | w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16]; | 463 | w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16]; |
464 | w2.word ^= PA[17]; | 464 | w2.word ^= PA[17]; |
465 | 465 | ||
466 | Bu::swap( w1, w2 ); | 466 | Bu::swap( w1, w2 ); |
467 | } | 467 | } |
468 | }; | 468 | }; |
469 | 469 | ||
470 | typedef CipherModeEcb<8, Blowfish<1> > BlowfishEcb; | 470 | typedef CipherModeEcb<8, Blowfish<1> > BlowfishEcb; |
471 | typedef CipherModeCfb<8, Blowfish<1> > BlowfishCfb; | 471 | typedef CipherModeCfb<8, Blowfish<1> > BlowfishCfb; |
472 | typedef CipherModeCbc<8, Blowfish<1> > BlowfishCbc; | 472 | typedef CipherModeCbc<8, Blowfish<1> > BlowfishCbc; |
473 | typedef CipherModeOfb<8, Blowfish<1> > BlowfishOfb; | 473 | typedef CipherModeOfb<8, Blowfish<1> > BlowfishOfb; |
474 | }; | 474 | }; |
475 | 475 | ||
476 | #endif | 476 | #endif |
diff --git a/src/experimental/cache.h b/src/experimental/cache.h index e3c8483..795d180 100644 --- a/src/experimental/cache.h +++ b/src/experimental/cache.h | |||
@@ -18,420 +18,420 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | // template<class keytype, class obtype> | 21 | // template<class keytype, class obtype> |
22 | // keytype __cacheGetKey( obtype *&pObj ); | 22 | // keytype __cacheGetKey( obtype *&pObj ); |
23 | template<class keytype, class obtype> | 23 | template<class keytype, class obtype> |
24 | keytype __cacheGetKey( const obtype *pObj ) | 24 | keytype __cacheGetKey( const obtype *pObj ) |
25 | { | 25 | { |
26 | return pObj->getKey(); | 26 | return pObj->getKey(); |
27 | } | 27 | } |
28 | 28 | ||
29 | template<class keytype, class obtype> | 29 | template<class keytype, class obtype> |
30 | class Cache | 30 | class Cache |
31 | { | 31 | { |
32 | public: | 32 | public: |
33 | /** | 33 | /** |
34 | * Cache Pointer - Provides access to data that is held within the | 34 | * Cache Pointer - Provides access to data that is held within the |
35 | * cache. This provides safe, refcounting access to data stored in | 35 | * cache. This provides safe, refcounting access to data stored in |
36 | * the cache, with support for lazy loading. | 36 | * the cache, with support for lazy loading. |
37 | */ | 37 | */ |
38 | class Ptr | 38 | class Ptr |
39 | { | 39 | { |
40 | friend class Bu::Cache<keytype, obtype>; | 40 | friend class Bu::Cache<keytype, obtype>; |
41 | private: | 41 | private: |
42 | Ptr( Cache<keytype, obtype> *pCache, obtype *pData, | 42 | Ptr( Cache<keytype, obtype> *pCache, obtype *pData, |
43 | const keytype &kId ) : | 43 | const keytype &kId ) : |
44 | pCache( pCache ), | 44 | pCache( pCache ), |
45 | pData( pData ), | 45 | pData( pData ), |
46 | kId( kId ) | 46 | kId( kId ) |
47 | { | 47 | { |
48 | if( pCache ) | 48 | if( pCache ) |
49 | pCache->incRef( kId ); | 49 | pCache->incRef( kId ); |
50 | } | 50 | } |
51 | 51 | ||
52 | Ptr( Cache<keytype, obtype> *pCache, const keytype &kId ) : | 52 | Ptr( Cache<keytype, obtype> *pCache, const keytype &kId ) : |
53 | pCache( pCache ), | 53 | pCache( pCache ), |
54 | pData( NULL ), | 54 | pData( NULL ), |
55 | kId( kId ) | 55 | kId( kId ) |
56 | { | 56 | { |
57 | } | 57 | } |
58 | 58 | ||
59 | public: | 59 | public: |
60 | Ptr( const Ptr &rSrc ) : | 60 | Ptr( const Ptr &rSrc ) : |
61 | pCache( rSrc.pCache ), | 61 | pCache( rSrc.pCache ), |
62 | pData( rSrc.pData ), | 62 | pData( rSrc.pData ), |
63 | kId( rSrc.kId ) | 63 | kId( rSrc.kId ) |
64 | { | 64 | { |
65 | if( pCache && pData ) | 65 | if( pCache && pData ) |
66 | pCache->incRef( kId ); | 66 | pCache->incRef( kId ); |
67 | } | 67 | } |
68 | 68 | ||
69 | Ptr() : | 69 | Ptr() : |
70 | pCache( 0 ), | 70 | pCache( 0 ), |
71 | pData( 0 ) | 71 | pData( 0 ) |
72 | { | 72 | { |
73 | } | 73 | } |
74 | 74 | ||
75 | virtual ~Ptr() | 75 | virtual ~Ptr() |
76 | { | 76 | { |
77 | if( pCache && pData ) | 77 | if( pCache && pData ) |
78 | pCache->decRef( kId ); | 78 | pCache->decRef( kId ); |
79 | } | 79 | } |
80 | 80 | ||
81 | obtype &operator*() | 81 | obtype &operator*() |
82 | { | 82 | { |
83 | checkPtr(); | 83 | checkPtr(); |
84 | return *pData; | 84 | return *pData; |
85 | } | 85 | } |
86 | 86 | ||
87 | const obtype &operator*() const | 87 | const obtype &operator*() const |
88 | { | 88 | { |
89 | checkPtr(); | 89 | checkPtr(); |
90 | return *pData; | 90 | return *pData; |
91 | } | 91 | } |
92 | 92 | ||
93 | obtype *operator->() | 93 | obtype *operator->() |
94 | { | 94 | { |
95 | checkPtr(); | 95 | checkPtr(); |
96 | return pData; | 96 | return pData; |
97 | } | 97 | } |
98 | 98 | ||
99 | const obtype *operator->() const | 99 | const obtype *operator->() const |
100 | { | 100 | { |
101 | checkPtr(); | 101 | checkPtr(); |
102 | return pData; | 102 | return pData; |
103 | } | 103 | } |
104 | 104 | ||
105 | bool isValid() const | 105 | bool isValid() const |
106 | { | 106 | { |
107 | return pCache != NULL; | 107 | return pCache != NULL; |
108 | } | 108 | } |
109 | 109 | ||
110 | bool isBound() const | 110 | bool isBound() const |
111 | { | 111 | { |
112 | return pData != NULL; | 112 | return pData != NULL; |
113 | } | 113 | } |
114 | 114 | ||
115 | bool isSet() const | 115 | bool isSet() const |
116 | { | 116 | { |
117 | return pCache != NULL; | 117 | return pCache != NULL; |
118 | } | 118 | } |
119 | 119 | ||
120 | const keytype &getKey() const | 120 | const keytype &getKey() const |
121 | { | 121 | { |
122 | return kId; | 122 | return kId; |
123 | } | 123 | } |
124 | 124 | ||
125 | void unbind() | 125 | void unbind() |
126 | { | 126 | { |
127 | if( pCache && pData ) | 127 | if( pCache && pData ) |
128 | pCache->decRef( kId ); | 128 | pCache->decRef( kId ); |
129 | pData = NULL; | 129 | pData = NULL; |
130 | } | 130 | } |
131 | 131 | ||
132 | void clear() | 132 | void clear() |
133 | { | 133 | { |
134 | unbind(); | 134 | unbind(); |
135 | pCache = NULL; | 135 | pCache = NULL; |
136 | } | 136 | } |
137 | 137 | ||
138 | void unset() | 138 | void unset() |
139 | { | 139 | { |
140 | clear(); | 140 | clear(); |
141 | } | 141 | } |
142 | 142 | ||
143 | Ptr &operator=( const Ptr &rRhs ) | 143 | Ptr &operator=( const Ptr &rRhs ) |
144 | { | 144 | { |
145 | if( pCache && pData ) | 145 | if( pCache && pData ) |
146 | pCache->decRef( kId ); | 146 | pCache->decRef( kId ); |
147 | pCache = rRhs.pCache; | 147 | pCache = rRhs.pCache; |
148 | pData = rRhs.pData; | 148 | pData = rRhs.pData; |
149 | kId = rRhs.kId; | 149 | kId = rRhs.kId; |
150 | if( pCache && pData ) | 150 | if( pCache && pData ) |
151 | pCache->incRef( kId ); | 151 | pCache->incRef( kId ); |
152 | return *this; | 152 | return *this; |
153 | } | 153 | } |
154 | 154 | ||
155 | bool operator==( const Ptr &rRhs ) const | 155 | bool operator==( const Ptr &rRhs ) const |
156 | { | 156 | { |
157 | return pCache == rRhs.pCache && kId == rRhs.kId; | 157 | return pCache == rRhs.pCache && kId == rRhs.kId; |
158 | } | 158 | } |
159 | 159 | ||
160 | bool operator!=( const Ptr &rRhs ) const | 160 | bool operator!=( const Ptr &rRhs ) const |
161 | { | 161 | { |
162 | return pCache != rRhs.pCache || kId != rRhs.kId; | 162 | return pCache != rRhs.pCache || kId != rRhs.kId; |
163 | } | 163 | } |
164 | 164 | ||
165 | private: | 165 | private: |
166 | void checkPtr() const | 166 | void checkPtr() const |
167 | { | 167 | { |
168 | if( pCache && !pData ) | 168 | if( pCache && !pData ) |
169 | { | 169 | { |
170 | pData = pCache->getRaw( kId ); | 170 | pData = pCache->getRaw( kId ); |
171 | pCache->incRef( kId ); | 171 | pCache->incRef( kId ); |
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | private: | 175 | private: |
176 | Bu::Cache<keytype, obtype> *pCache; | 176 | Bu::Cache<keytype, obtype> *pCache; |
177 | mutable obtype *pData; | 177 | mutable obtype *pData; |
178 | mutable keytype kId; | 178 | mutable keytype kId; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | private: | 181 | private: |
182 | typedef Bu::CacheStore<keytype, obtype> Store; | 182 | typedef Bu::CacheStore<keytype, obtype> Store; |
183 | typedef Bu::List<Store *> StoreList; | 183 | typedef Bu::List<Store *> StoreList; |
184 | typedef Bu::CacheCalc<keytype, obtype> Calc; | 184 | typedef Bu::CacheCalc<keytype, obtype> Calc; |
185 | 185 | ||
186 | typedef struct CacheEntry | 186 | typedef struct CacheEntry |
187 | { | 187 | { |
188 | obtype *pData; | 188 | obtype *pData; |
189 | int iRefs; | 189 | int iRefs; |
190 | time_t tLastSync; | 190 | time_t tLastSync; |
191 | } CacheEntry; | 191 | } CacheEntry; |
192 | 192 | ||
193 | typedef Bu::Hash<keytype, CacheEntry> CidHash; | 193 | typedef Bu::Hash<keytype, CacheEntry> CidHash; |
194 | 194 | ||
195 | public: | 195 | public: |
196 | typedef keytype Key; | 196 | typedef keytype Key; |
197 | Cache( Calc *pCalc, Store *pStore ) : | 197 | Cache( Calc *pCalc, Store *pStore ) : |
198 | pCalc( pCalc ), | 198 | pCalc( pCalc ), |
199 | pStore( pStore ) | 199 | pStore( pStore ) |
200 | { | 200 | { |
201 | TRACE(); | 201 | TRACE(); |
202 | pCalc->setCache( this ); | 202 | pCalc->setCache( this ); |
203 | } | 203 | } |
204 | 204 | ||
205 | virtual ~Cache() | 205 | virtual ~Cache() |
206 | { | 206 | { |
207 | TRACE(); | 207 | TRACE(); |
208 | 208 | ||
209 | // Better safe than sorry, better try a sync before anything | 209 | // Better safe than sorry, better try a sync before anything |
210 | // else happens. | 210 | // else happens. |
211 | sync(); | 211 | sync(); |
212 | 212 | ||
213 | // Cycle through and unload all objects from the system. | 213 | // Cycle through and unload all objects from the system. |
214 | for( typename CidHash::iterator i = hEnt.begin(); | 214 | for( typename CidHash::iterator i = hEnt.begin(); |
215 | i != hEnt.end(); i++ ) | 215 | i != hEnt.end(); i++ ) |
216 | { | 216 | { |
217 | if( i.getValue().iRefs > 0 ) | 217 | if( i.getValue().iRefs > 0 ) |
218 | { | 218 | { |
219 | // TODO: Throw an error in this case? iRefs != 0 for an | 219 | // TODO: Throw an error in this case? iRefs != 0 for an |
220 | // object when the Cache is destroyed. | 220 | // object when the Cache is destroyed. |
221 | throw Bu::ExceptionBase("iRefs not zero."); | 221 | throw Bu::ExceptionBase("iRefs not zero."); |
222 | } | 222 | } |
223 | pStore->unload( | 223 | pStore->unload( |
224 | i.getValue().pData, | 224 | i.getValue().pData, |
225 | i.getKey() | 225 | i.getKey() |
226 | ); | 226 | ); |
227 | } | 227 | } |
228 | delete pCalc; | 228 | delete pCalc; |
229 | delete pStore; | 229 | delete pStore; |
230 | } | 230 | } |
231 | 231 | ||
232 | Ptr insert( obtype *pData ) | 232 | Ptr insert( obtype *pData ) |
233 | { | 233 | { |
234 | TRACE( pData ); | 234 | TRACE( pData ); |
235 | if( pStore->has( __cacheGetKey<keytype, obtype>( pData ) ) ) | 235 | if( pStore->has( __cacheGetKey<keytype, obtype>( pData ) ) ) |
236 | throw Bu::ExceptionBase("Key already exists in cache."); | 236 | throw Bu::ExceptionBase("Key already exists in cache."); |
237 | CacheEntry e = {pData, 0, 0}; | 237 | CacheEntry e = {pData, 0, 0}; |
238 | keytype k = pStore->create( pData ); | 238 | keytype k = pStore->create( pData ); |
239 | hEnt.insert( k, e ); | 239 | hEnt.insert( k, e ); |
240 | 240 | ||
241 | pCalc->onLoad( pData, k ); | 241 | pCalc->onLoad( pData, k ); |
242 | 242 | ||
243 | pStore->sync(); | 243 | pStore->sync(); |
244 | 244 | ||
245 | return Ptr( this, pData, k ); | 245 | return Ptr( this, pData, k ); |
246 | } | 246 | } |
247 | 247 | ||
248 | bool has( const keytype &cId ) | 248 | bool has( const keytype &cId ) |
249 | { | 249 | { |
250 | return hEnt.has( cId ) || pStore->has( cId ); | 250 | return hEnt.has( cId ) || pStore->has( cId ); |
251 | } | 251 | } |
252 | 252 | ||
253 | /** | 253 | /** |
254 | * Retrieve an object from the cache and return a pointer to it. | 254 | * Retrieve an object from the cache and return a pointer to it. |
255 | * The object returned may be loaded from backend storage if needed, | 255 | * The object returned may be loaded from backend storage if needed, |
256 | * or the currently live object will be returned. | 256 | * or the currently live object will be returned. |
257 | *@param cId The id of the object to load. | 257 | *@param cId The id of the object to load. |
258 | *@returns A pointer to the object. | 258 | *@returns A pointer to the object. |
259 | */ | 259 | */ |
260 | Ptr get( const keytype &cId ) | 260 | Ptr get( const keytype &cId ) |
261 | { | 261 | { |
262 | TRACE( cId ); | 262 | TRACE( cId ); |
263 | try { | 263 | try { |
264 | return Ptr( this, hEnt.get( cId ).pData, cId ); | 264 | return Ptr( this, hEnt.get( cId ).pData, cId ); |
265 | } | 265 | } |
266 | catch( Bu::HashException &e ) { | 266 | catch( Bu::HashException &e ) { |
267 | CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; | 267 | CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; |
268 | pCalc->onLoad( e.pData, cId ); | 268 | pCalc->onLoad( e.pData, cId ); |
269 | hEnt.insert( cId, e ); | 269 | hEnt.insert( cId, e ); |
270 | return Ptr( this, e.pData, cId ); | 270 | return Ptr( this, e.pData, cId ); |
271 | } | 271 | } |
272 | } | 272 | } |
273 | 273 | ||
274 | /** | 274 | /** |
275 | * Retrieve a handle to an object without loading it now. This function | 275 | * Retrieve a handle to an object without loading it now. This function |
276 | * will return a pointer that has not yet been "realized" but can be | 276 | * will return a pointer that has not yet been "realized" but can be |
277 | * used normally. Upon initial use in any way the object will be | 277 | * used normally. Upon initial use in any way the object will be |
278 | * loaded from the cache, either linking against the already loaded | 278 | * loaded from the cache, either linking against the already loaded |
279 | * object or loading it fresh from the backend storage. The advantage | 279 | * object or loading it fresh from the backend storage. The advantage |
280 | * of this is that you recieve a usable handle to the data, but it | 280 | * of this is that you recieve a usable handle to the data, but it |
281 | * does not count as a reference yet, meaning that the data is loaded | 281 | * does not count as a reference yet, meaning that the data is loaded |
282 | * when you need it, not before. | 282 | * when you need it, not before. |
283 | */ | 283 | */ |
284 | Ptr getLazy( const keytype &cId ) | 284 | Ptr getLazy( const keytype &cId ) |
285 | { | 285 | { |
286 | TRACE( cId ); | 286 | TRACE( cId ); |
287 | return Ptr( this, cId ); | 287 | return Ptr( this, cId ); |
288 | } | 288 | } |
289 | 289 | ||
290 | int getRefCount( const keytype &cId ) | 290 | int getRefCount( const keytype &cId ) |
291 | { | 291 | { |
292 | TRACE( cId ); | 292 | TRACE( cId ); |
293 | return hEnt.get( cId ).iRefs; | 293 | return hEnt.get( cId ).iRefs; |
294 | } | 294 | } |
295 | 295 | ||
296 | void unload( const keytype &cId ) | 296 | void unload( const keytype &cId ) |
297 | { | 297 | { |
298 | TRACE( cId ); | 298 | TRACE( cId ); |
299 | try { | 299 | try { |
300 | if( hEnt.get( cId ).iRefs > 0 ) | 300 | if( hEnt.get( cId ).iRefs > 0 ) |
301 | { | 301 | { |
302 | printf("Shouldn't unload, references still exist!\n"); | 302 | printf("Shouldn't unload, references still exist!\n"); |
303 | return; | 303 | return; |
304 | } | 304 | } |
305 | } | 305 | } |
306 | catch( Bu::HashException &e ) { | 306 | catch( Bu::HashException &e ) { |
307 | // It's not here? Eh, return. | 307 | // It's not here? Eh, return. |
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | obtype *pObj = hEnt.get( cId ).pData; | 310 | obtype *pObj = hEnt.get( cId ).pData; |
311 | pCalc->onUnload( pObj, cId ); | 311 | pCalc->onUnload( pObj, cId ); |
312 | hEnt.erase( cId ); | 312 | hEnt.erase( cId ); |
313 | 313 | ||
314 | // The unload has to happen last just in case cId is a reference | 314 | // The unload has to happen last just in case cId is a reference |
315 | // to data that is about to be deleted from memory by the unload. | 315 | // to data that is about to be deleted from memory by the unload. |
316 | pStore->unload( pObj, cId ); | 316 | pStore->unload( pObj, cId ); |
317 | } | 317 | } |
318 | 318 | ||
319 | void erase( const keytype &cId ) | 319 | void erase( const keytype &cId ) |
320 | { | 320 | { |
321 | TRACE( cId ); | 321 | TRACE( cId ); |
322 | try { | 322 | try { |
323 | if( hEnt.get( cId ).iRefs > 0 ) | 323 | if( hEnt.get( cId ).iRefs > 0 ) |
324 | { | 324 | { |
325 | printf("Shouldn't erase, references still exist!\n"); | 325 | printf("Shouldn't erase, references still exist!\n"); |
326 | return; | 326 | return; |
327 | } | 327 | } |
328 | 328 | ||
329 | obtype *pObj = hEnt.get( cId ).pData; | 329 | obtype *pObj = hEnt.get( cId ).pData; |
330 | pCalc->onDestroy( pObj, cId ); | 330 | pCalc->onDestroy( pObj, cId ); |
331 | hEnt.erase( cId ); | 331 | hEnt.erase( cId ); |
332 | 332 | ||
333 | pStore->destroy( pObj, cId ); | 333 | pStore->destroy( pObj, cId ); |
334 | pStore->sync(); | 334 | pStore->sync(); |
335 | } | 335 | } |
336 | catch( Bu::HashException &e ) { | 336 | catch( Bu::HashException &e ) { |
337 | pCalc->onDestroy( cId ); | 337 | pCalc->onDestroy( cId ); |
338 | 338 | ||
339 | if( hEnt.has( cId ) ) | 339 | if( hEnt.has( cId ) ) |
340 | { | 340 | { |
341 | // The object was loaded by onDestroy | 341 | // The object was loaded by onDestroy |
342 | erase( cId ); | 342 | erase( cId ); |
343 | } | 343 | } |
344 | else | 344 | else |
345 | { | 345 | { |
346 | pStore->destroy( cId ); | 346 | pStore->destroy( cId ); |
347 | pStore->sync(); | 347 | pStore->sync(); |
348 | } | 348 | } |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | typedef Bu::List<keytype> KeyList; | 352 | typedef Bu::List<keytype> KeyList; |
353 | KeyList getKeys() | 353 | KeyList getKeys() |
354 | { | 354 | { |
355 | return pStore->getKeys(); | 355 | return pStore->getKeys(); |
356 | } | 356 | } |
357 | 357 | ||
358 | KeyList getActiveKeys() | 358 | KeyList getActiveKeys() |
359 | { | 359 | { |
360 | return hEnt.getKeys(); | 360 | return hEnt.getKeys(); |
361 | } | 361 | } |
362 | 362 | ||
363 | int getSize() | 363 | int getSize() |
364 | { | 364 | { |
365 | return pStore->getSize(); | 365 | return pStore->getSize(); |
366 | } | 366 | } |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * Make sure all currently loaded but not-in-use objects are synced to | 369 | * Make sure all currently loaded but not-in-use objects are synced to |
370 | * the store. | 370 | * the store. |
371 | */ | 371 | */ |
372 | void sync() | 372 | void sync() |
373 | { | 373 | { |
374 | TRACE(); | 374 | TRACE(); |
375 | int iSynced = 0; | 375 | int iSynced = 0; |
376 | for( typename CidHash::iterator i = hEnt.begin(); | 376 | for( typename CidHash::iterator i = hEnt.begin(); |
377 | i != hEnt.end(); i++ ) | 377 | i != hEnt.end(); i++ ) |
378 | { | 378 | { |
379 | if( i.getValue().iRefs == 0 ) | 379 | if( i.getValue().iRefs == 0 ) |
380 | { | 380 | { |
381 | if( pCalc->shouldSync( | 381 | if( pCalc->shouldSync( |
382 | i.getValue().pData, | 382 | i.getValue().pData, |
383 | i.getKey(), | 383 | i.getKey(), |
384 | i.getValue().tLastSync | 384 | i.getValue().tLastSync |
385 | ) ) | 385 | ) ) |
386 | { | 386 | { |
387 | pStore->sync( | 387 | pStore->sync( |
388 | i.getValue().pData, | 388 | i.getValue().pData, |
389 | i.getKey() | 389 | i.getKey() |
390 | ); | 390 | ); |
391 | iSynced++; | 391 | iSynced++; |
392 | i.getValue().tLastSync = time( NULL ); | 392 | i.getValue().tLastSync = time( NULL ); |
393 | } | 393 | } |
394 | } | 394 | } |
395 | } | 395 | } |
396 | if( iSynced > 0 ) | 396 | if( iSynced > 0 ) |
397 | { | 397 | { |
398 | pStore->sync(); | 398 | pStore->sync(); |
399 | } | 399 | } |
400 | } | 400 | } |
401 | 401 | ||
402 | private: | 402 | private: |
403 | void incRef( const keytype &cId ) | 403 | void incRef( const keytype &cId ) |
404 | { | 404 | { |
405 | TRACE( cId ); | 405 | TRACE( cId ); |
406 | hEnt.get( cId ).iRefs++; | 406 | hEnt.get( cId ).iRefs++; |
407 | } | 407 | } |
408 | 408 | ||
409 | void decRef( const keytype &cId ) | 409 | void decRef( const keytype &cId ) |
410 | { | 410 | { |
411 | TRACE( cId ); | 411 | TRACE( cId ); |
412 | CacheEntry &e = hEnt.get( cId ); | 412 | CacheEntry &e = hEnt.get( cId ); |
413 | e.iRefs--; | 413 | e.iRefs--; |
414 | } | 414 | } |
415 | 415 | ||
416 | obtype *getRaw( const keytype &cId ) | 416 | obtype *getRaw( const keytype &cId ) |
417 | { | 417 | { |
418 | TRACE( cId ); | 418 | TRACE( cId ); |
419 | try { | 419 | try { |
420 | return hEnt.get( cId ).pData; | 420 | return hEnt.get( cId ).pData; |
421 | } | 421 | } |
422 | catch( Bu::HashException &e ) { | 422 | catch( Bu::HashException &e ) { |
423 | CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; | 423 | CacheEntry e = {pStore->load( cId ), 0, time( NULL )}; |
424 | pCalc->onLoad( e.pData, cId ); | 424 | pCalc->onLoad( e.pData, cId ); |
425 | hEnt.insert( cId, e ); | 425 | hEnt.insert( cId, e ); |
426 | return e.pData; | 426 | return e.pData; |
427 | } | 427 | } |
428 | } | 428 | } |
429 | 429 | ||
430 | private: | 430 | private: |
431 | CidHash hEnt; | 431 | CidHash hEnt; |
432 | Calc *pCalc; | 432 | Calc *pCalc; |
433 | Store *pStore; | 433 | Store *pStore; |
434 | }; | 434 | }; |
435 | }; | 435 | }; |
436 | 436 | ||
437 | #endif | 437 | #endif |
diff --git a/src/experimental/cachecalc.h b/src/experimental/cachecalc.h index ecfa3f4..cb5c755 100644 --- a/src/experimental/cachecalc.h +++ b/src/experimental/cachecalc.h | |||
@@ -14,50 +14,50 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | template<class keytype, class obtype> class Cache; | 17 | template<class keytype, class obtype> class Cache; |
18 | 18 | ||
19 | template<class keytype, class obtype> | 19 | template<class keytype, class obtype> |
20 | class CacheCalc | 20 | class CacheCalc |
21 | { | 21 | { |
22 | friend class Cache<keytype, obtype>; | 22 | friend class Cache<keytype, obtype>; |
23 | private: | 23 | private: |
24 | typedef Cache<keytype, obtype> MyCache; | 24 | typedef Cache<keytype, obtype> MyCache; |
25 | public: | 25 | public: |
26 | CacheCalc() : | 26 | CacheCalc() : |
27 | pCache( (MyCache *)0 ) | 27 | pCache( (MyCache *)0 ) |
28 | { | 28 | { |
29 | TRACE(); | 29 | TRACE(); |
30 | } | 30 | } |
31 | 31 | ||
32 | virtual ~CacheCalc() | 32 | virtual ~CacheCalc() |
33 | { | 33 | { |
34 | TRACE(); | 34 | TRACE(); |
35 | } | 35 | } |
36 | 36 | ||
37 | virtual void onLoad( obtype *pSrc, const keytype &key )=0; | 37 | virtual void onLoad( obtype *pSrc, const keytype &key )=0; |
38 | virtual void onUnload( obtype *pSrc, const keytype &key )=0; | 38 | virtual void onUnload( obtype *pSrc, const keytype &key )=0; |
39 | virtual void onDestroy( obtype *pSrc, const keytype &key )=0; | 39 | virtual void onDestroy( obtype *pSrc, const keytype &key )=0; |
40 | virtual void onDestroy( const keytype &key )=0; | 40 | virtual void onDestroy( const keytype &key )=0; |
41 | virtual bool shouldSync( obtype *pSrc, const keytype &key, | 41 | virtual bool shouldSync( obtype *pSrc, const keytype &key, |
42 | time_t tLastSync )=0; | 42 | time_t tLastSync )=0; |
43 | virtual void onTick() { }; | 43 | virtual void onTick() { }; |
44 | 44 | ||
45 | protected: | 45 | protected: |
46 | MyCache *getCache() | 46 | MyCache *getCache() |
47 | { | 47 | { |
48 | TRACE(); | 48 | TRACE(); |
49 | return pCache; | 49 | return pCache; |
50 | } | 50 | } |
51 | 51 | ||
52 | private: | 52 | private: |
53 | void setCache( MyCache *pCache ) | 53 | void setCache( MyCache *pCache ) |
54 | { | 54 | { |
55 | TRACE(); | 55 | TRACE(); |
56 | this->pCache = pCache; | 56 | this->pCache = pCache; |
57 | } | 57 | } |
58 | 58 | ||
59 | MyCache *pCache; | 59 | MyCache *pCache; |
60 | }; | 60 | }; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #endif | 63 | #endif |
diff --git a/src/experimental/cachestore.h b/src/experimental/cachestore.h index a332e49..5052670 100644 --- a/src/experimental/cachestore.h +++ b/src/experimental/cachestore.h | |||
@@ -12,35 +12,35 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Handles I/O for data in the cache. This also assigns ID's to the newly | 16 | * Handles I/O for data in the cache. This also assigns ID's to the newly |
17 | * created objects that are requested through this system. | 17 | * created objects that are requested through this system. |
18 | */ | 18 | */ |
19 | template<class keytype, class obtype> | 19 | template<class keytype, class obtype> |
20 | class CacheStore | 20 | class CacheStore |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | CacheStore() | 23 | CacheStore() |
24 | { | 24 | { |
25 | } | 25 | } |
26 | 26 | ||
27 | virtual ~CacheStore() | 27 | virtual ~CacheStore() |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
31 | virtual obtype *load( const keytype &key )=0; | 31 | virtual obtype *load( const keytype &key )=0; |
32 | virtual void unload( obtype *pObj, const keytype &key )=0; | 32 | virtual void unload( obtype *pObj, const keytype &key )=0; |
33 | virtual keytype create( obtype *pSrc )=0; | 33 | virtual keytype create( obtype *pSrc )=0; |
34 | virtual void sync()=0; | 34 | virtual void sync()=0; |
35 | virtual void sync( obtype *pObj, const keytype &key )=0; | 35 | virtual void sync( obtype *pObj, const keytype &key )=0; |
36 | virtual void destroy( obtype *pObj, const keytype &key )=0; | 36 | virtual void destroy( obtype *pObj, const keytype &key )=0; |
37 | virtual void destroy( const keytype &key )=0; | 37 | virtual void destroy( const keytype &key )=0; |
38 | virtual bool has( const keytype &key )=0; | 38 | virtual bool has( const keytype &key )=0; |
39 | virtual Bu::List<keytype> getKeys() { return Bu::List<keytype>(); } | 39 | virtual Bu::List<keytype> getKeys() { return Bu::List<keytype>(); } |
40 | virtual int getSize() { return -1; } | 40 | virtual int getSize() { return -1; } |
41 | 41 | ||
42 | private: | 42 | private: |
43 | }; | 43 | }; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | #endif | 46 | #endif |
diff --git a/src/experimental/cachestorefiles.h b/src/experimental/cachestorefiles.h index d3a6894..0805e7b 100644 --- a/src/experimental/cachestorefiles.h +++ b/src/experimental/cachestorefiles.h | |||
@@ -23,188 +23,188 @@ | |||
23 | 23 | ||
24 | namespace Bu | 24 | namespace Bu |
25 | { | 25 | { |
26 | template<class keytype, class obtype> | 26 | template<class keytype, class obtype> |
27 | keytype __cacheGetKey( const obtype *pObj ); | 27 | keytype __cacheGetKey( const obtype *pObj ); |
28 | 28 | ||
29 | template<class keytype, class obtype> | 29 | template<class keytype, class obtype> |
30 | obtype *__cacheStoreFilesAlloc( const keytype &key ) | 30 | obtype *__cacheStoreFilesAlloc( const keytype &key ) |
31 | { | 31 | { |
32 | return new obtype(); | 32 | return new obtype(); |
33 | } | 33 | } |
34 | 34 | ||
35 | template<class keytype, class obtype> | 35 | template<class keytype, class obtype> |
36 | void __cacheStoreFilesStore( Bu::Stream &s, obtype &rObj, | 36 | void __cacheStoreFilesStore( Bu::Stream &s, obtype &rObj, |
37 | const keytype & ) | 37 | const keytype & ) |
38 | { | 38 | { |
39 | Bu::Archive ar( s, Bu::Archive::save ); | 39 | Bu::Archive ar( s, Bu::Archive::save ); |
40 | ar << rObj; | 40 | ar << rObj; |
41 | } | 41 | } |
42 | 42 | ||
43 | template<class keytype, class obtype> | 43 | template<class keytype, class obtype> |
44 | obtype *__cacheStoreFilesLoad( Bu::Stream &s, const keytype &key ) | 44 | obtype *__cacheStoreFilesLoad( Bu::Stream &s, const keytype &key ) |
45 | { | 45 | { |
46 | obtype *pObj = __cacheStoreFilesAlloc<keytype, obtype>( key ); | 46 | obtype *pObj = __cacheStoreFilesAlloc<keytype, obtype>( key ); |
47 | Bu::Archive ar( s, Bu::Archive::load ); | 47 | Bu::Archive ar( s, Bu::Archive::load ); |
48 | ar >> (*pObj); | 48 | ar >> (*pObj); |
49 | return pObj; | 49 | return pObj; |
50 | } | 50 | } |
51 | 51 | ||
52 | template<class keytype, class obtype> | 52 | template<class keytype, class obtype> |
53 | class CacheStoreFiles : public CacheStore<keytype, obtype> | 53 | class CacheStoreFiles : public CacheStore<keytype, obtype> |
54 | { | 54 | { |
55 | public: | 55 | public: |
56 | CacheStoreFiles( const Bu::String &sPrefix ) : | 56 | CacheStoreFiles( const Bu::String &sPrefix ) : |
57 | sPrefix( sPrefix ) | 57 | sPrefix( sPrefix ) |
58 | { | 58 | { |
59 | if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) ) | 59 | if( access( sPrefix.getStr(), W_OK|R_OK|X_OK ) ) |
60 | { | 60 | { |
61 | #ifdef WIN32 | 61 | #ifdef WIN32 |
62 | mkdir( sPrefix.getStr() ); | 62 | mkdir( sPrefix.getStr() ); |
63 | #else | 63 | #else |
64 | mkdir( sPrefix.getStr(), 0755 ); | 64 | mkdir( sPrefix.getStr(), 0755 ); |
65 | #endif | 65 | #endif |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | virtual ~CacheStoreFiles() | 69 | virtual ~CacheStoreFiles() |
70 | { | 70 | { |
71 | } | 71 | } |
72 | 72 | ||
73 | virtual obtype *load( const keytype &key ) | 73 | virtual obtype *load( const keytype &key ) |
74 | { | 74 | { |
75 | // try | 75 | // try |
76 | // { | 76 | // { |
77 | Bu::MemBuf mb; | 77 | Bu::MemBuf mb; |
78 | Bu::Formatter f( mb ); | 78 | Bu::Formatter f( mb ); |
79 | f << sPrefix << "/" << key; | 79 | f << sPrefix << "/" << key; |
80 | Bu::File fIn( mb.getString(), Bu::File::Read ); | 80 | Bu::File fIn( mb.getString(), Bu::File::Read ); |
81 | obtype *pOb = __cacheStoreFilesLoad<keytype, obtype>( fIn, key ); | 81 | obtype *pOb = __cacheStoreFilesLoad<keytype, obtype>( fIn, key ); |
82 | return pOb; | 82 | return pOb; |
83 | // } | 83 | // } |
84 | // catch( std::exception &e ) | 84 | // catch( std::exception &e ) |
85 | // { | 85 | // { |
86 | // throw Bu::HashException( e.what() ); | 86 | // throw Bu::HashException( e.what() ); |
87 | // } | 87 | // } |
88 | } | 88 | } |
89 | 89 | ||
90 | virtual void unload( obtype *pObj, const keytype & ) | 90 | virtual void unload( obtype *pObj, const keytype & ) |
91 | { | 91 | { |
92 | delete pObj; | 92 | delete pObj; |
93 | } | 93 | } |
94 | 94 | ||
95 | virtual keytype create( obtype *pSrc ) | 95 | virtual keytype create( obtype *pSrc ) |
96 | { | 96 | { |
97 | keytype key = __cacheGetKey<keytype, obtype>( pSrc ); | 97 | keytype key = __cacheGetKey<keytype, obtype>( pSrc ); |
98 | Bu::MemBuf mb; | 98 | Bu::MemBuf mb; |
99 | Bu::Formatter f( mb ); | 99 | Bu::Formatter f( mb ); |
100 | f << sPrefix << "/" << key; | 100 | f << sPrefix << "/" << key; |
101 | 101 | ||
102 | Bu::File fTouch( mb.getString(), Bu::File::WriteNew ); | 102 | Bu::File fTouch( mb.getString(), Bu::File::WriteNew ); |
103 | 103 | ||
104 | return key; | 104 | return key; |
105 | } | 105 | } |
106 | 106 | ||
107 | virtual void sync() | 107 | virtual void sync() |
108 | { | 108 | { |
109 | } | 109 | } |
110 | 110 | ||
111 | virtual void sync( obtype *pSrc, const keytype &key ) | 111 | virtual void sync( obtype *pSrc, const keytype &key ) |
112 | { | 112 | { |
113 | Bu::MemBuf mb; | 113 | Bu::MemBuf mb; |
114 | Bu::Formatter f( mb ); | 114 | Bu::Formatter f( mb ); |
115 | f << sPrefix << "/" << key; | 115 | f << sPrefix << "/" << key; |
116 | 116 | ||
117 | Bu::File fOut( mb.getString(), Bu::File::WriteNew ); | 117 | Bu::File fOut( mb.getString(), Bu::File::WriteNew ); |
118 | __cacheStoreFilesStore<keytype, obtype>( fOut, *pSrc, key ); | 118 | __cacheStoreFilesStore<keytype, obtype>( fOut, *pSrc, key ); |
119 | } | 119 | } |
120 | 120 | ||
121 | virtual void destroy( obtype *pObj, const keytype &key ) | 121 | virtual void destroy( obtype *pObj, const keytype &key ) |
122 | { | 122 | { |
123 | Bu::MemBuf mb; | 123 | Bu::MemBuf mb; |
124 | Bu::Formatter f( mb ); | 124 | Bu::Formatter f( mb ); |
125 | f << sPrefix << "/" << key; | 125 | f << sPrefix << "/" << key; |
126 | 126 | ||
127 | unlink( mb.getString().getStr() ); | 127 | unlink( mb.getString().getStr() ); |
128 | delete pObj; | 128 | delete pObj; |
129 | } | 129 | } |
130 | 130 | ||
131 | virtual void destroy( const keytype &key ) | 131 | virtual void destroy( const keytype &key ) |
132 | { | 132 | { |
133 | Bu::MemBuf mb; | 133 | Bu::MemBuf mb; |
134 | Bu::Formatter f( mb ); | 134 | Bu::Formatter f( mb ); |
135 | f << sPrefix << "/" << key; | 135 | f << sPrefix << "/" << key; |
136 | 136 | ||
137 | unlink( mb.getString().getStr() ); | 137 | unlink( mb.getString().getStr() ); |
138 | } | 138 | } |
139 | 139 | ||
140 | virtual bool has( const keytype &key ) | 140 | virtual bool has( const keytype &key ) |
141 | { | 141 | { |
142 | Bu::MemBuf mb; | 142 | Bu::MemBuf mb; |
143 | Bu::Formatter f( mb ); | 143 | Bu::Formatter f( mb ); |
144 | f << sPrefix << "/"; | 144 | f << sPrefix << "/"; |
145 | Bu::String sBase = mb.getString(); | 145 | Bu::String sBase = mb.getString(); |
146 | f << key; | 146 | f << key; |
147 | 147 | ||
148 | if( sBase == mb.getString() ) | 148 | if( sBase == mb.getString() ) |
149 | return false; | 149 | return false; |
150 | 150 | ||
151 | return access( mb.getString().getStr(), F_OK ) == 0; | 151 | return access( mb.getString().getStr(), F_OK ) == 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | virtual Bu::List<keytype> getKeys() | 154 | virtual Bu::List<keytype> getKeys() |
155 | { | 155 | { |
156 | DIR *dir = opendir( sPrefix.getStr() ); | 156 | DIR *dir = opendir( sPrefix.getStr() ); |
157 | struct dirent *de; | 157 | struct dirent *de; |
158 | Bu::List<keytype> lKeys; | 158 | Bu::List<keytype> lKeys; |
159 | 159 | ||
160 | while( (de = readdir( dir ) ) ) | 160 | while( (de = readdir( dir ) ) ) |
161 | { | 161 | { |
162 | if( de->d_type != DT_REG ) | 162 | if( de->d_type != DT_REG ) |
163 | continue; | 163 | continue; |
164 | 164 | ||
165 | keytype tmp; | 165 | keytype tmp; |
166 | Bu::MemBuf mb( de->d_name ); | 166 | Bu::MemBuf mb( de->d_name ); |
167 | Bu::Formatter f( mb ); | 167 | Bu::Formatter f( mb ); |
168 | try | 168 | try |
169 | { | 169 | { |
170 | Fmt fm; | 170 | Fmt fm; |
171 | fm.tokenize( false ); | 171 | fm.tokenize( false ); |
172 | f << fm; | 172 | f << fm; |
173 | f >> tmp; | 173 | f >> tmp; |
174 | } | 174 | } |
175 | catch( Bu::ExceptionBase &e ) | 175 | catch( Bu::ExceptionBase &e ) |
176 | { | 176 | { |
177 | Bu::sio << "Parse error in dir-scan: " << e.what() | 177 | Bu::sio << "Parse error in dir-scan: " << e.what() |
178 | << Bu::sio.nl; | 178 | << Bu::sio.nl; |
179 | } | 179 | } |
180 | lKeys.append( tmp ); | 180 | lKeys.append( tmp ); |
181 | } | 181 | } |
182 | closedir( dir ); | 182 | closedir( dir ); |
183 | 183 | ||
184 | return lKeys; | 184 | return lKeys; |
185 | } | 185 | } |
186 | 186 | ||
187 | virtual int getSize() | 187 | virtual int getSize() |
188 | { | 188 | { |
189 | DIR *dir = opendir( sPrefix.getStr() ); | 189 | DIR *dir = opendir( sPrefix.getStr() ); |
190 | struct dirent *de; | 190 | struct dirent *de; |
191 | int iCount = 0; | 191 | int iCount = 0; |
192 | 192 | ||
193 | while( (de = readdir( dir ) ) ) | 193 | while( (de = readdir( dir ) ) ) |
194 | { | 194 | { |
195 | if( de->d_type != DT_REG ) | 195 | if( de->d_type != DT_REG ) |
196 | continue; | 196 | continue; |
197 | 197 | ||
198 | iCount++; | 198 | iCount++; |
199 | } | 199 | } |
200 | closedir( dir ); | 200 | closedir( dir ); |
201 | 201 | ||
202 | return iCount; | 202 | return iCount; |
203 | } | 203 | } |
204 | 204 | ||
205 | private: | 205 | private: |
206 | Bu::String sPrefix; | 206 | Bu::String sPrefix; |
207 | }; | 207 | }; |
208 | 208 | ||
209 | }; | 209 | }; |
210 | 210 | ||
diff --git a/src/experimental/cachestoremyriad.h b/src/experimental/cachestoremyriad.h index 1953b61..01fe307 100644 --- a/src/experimental/cachestoremyriad.h +++ b/src/experimental/cachestoremyriad.h | |||
@@ -18,141 +18,141 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | template<class keytype, class obtype> | 21 | template<class keytype, class obtype> |
22 | keytype __cacheGetKey( const obtype *pObj ); | 22 | keytype __cacheGetKey( const obtype *pObj ); |
23 | 23 | ||
24 | template<class keytype, class obtype> | 24 | template<class keytype, class obtype> |
25 | obtype *__cacheStoreMyriadAlloc( const keytype &key ) | 25 | obtype *__cacheStoreMyriadAlloc( const keytype &key ) |
26 | { | 26 | { |
27 | return new obtype(); | 27 | return new obtype(); |
28 | } | 28 | } |
29 | 29 | ||
30 | template<class keytype, class obtype> | 30 | template<class keytype, class obtype> |
31 | void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj, | 31 | void __cacheStoreMyriadStore( Bu::Stream &s, obtype &rObj, |
32 | const keytype & ) | 32 | const keytype & ) |
33 | { | 33 | { |
34 | Bu::Archive ar( s, Bu::Archive::save ); | 34 | Bu::Archive ar( s, Bu::Archive::save ); |
35 | ar << rObj; | 35 | ar << rObj; |
36 | } | 36 | } |
37 | 37 | ||
38 | template<class keytype, class obtype> | 38 | template<class keytype, class obtype> |
39 | obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key ) | 39 | obtype *__cacheStoreMyriadLoad( Bu::Stream &s, const keytype &key ) |
40 | { | 40 | { |
41 | obtype *pObj = __cacheStoreMyriadAlloc<keytype, obtype>( key ); | 41 | obtype *pObj = __cacheStoreMyriadAlloc<keytype, obtype>( key ); |
42 | Bu::Archive ar( s, Bu::Archive::load ); | 42 | Bu::Archive ar( s, Bu::Archive::load ); |
43 | ar >> (*pObj); | 43 | ar >> (*pObj); |
44 | return pObj; | 44 | return pObj; |
45 | } | 45 | } |
46 | 46 | ||
47 | template<class keytype, class obtype> | 47 | template<class keytype, class obtype> |
48 | class CacheStoreMyriad : public CacheStore<keytype, obtype> | 48 | class CacheStoreMyriad : public CacheStore<keytype, obtype> |
49 | { | 49 | { |
50 | public: | 50 | public: |
51 | CacheStoreMyriad( Bu::Stream &sArch, | 51 | CacheStoreMyriad( Bu::Stream &sArch, |
52 | int iBlockSize=512, int iPreAllocate=8 ) : | 52 | int iBlockSize=512, int iPreAllocate=8 ) : |
53 | mStore( sArch, iBlockSize, iPreAllocate ) | 53 | mStore( sArch, iBlockSize, iPreAllocate ) |
54 | { | 54 | { |
55 | try | 55 | try |
56 | { | 56 | { |
57 | MyriadStream ns = mStore.openStream( 1 ); | 57 | MyriadStream ns = mStore.openStream( 1 ); |
58 | Bu::Archive ar( ns, Bu::Archive::load ); | 58 | Bu::Archive ar( ns, Bu::Archive::load ); |
59 | ar >> hId; | 59 | ar >> hId; |
60 | } | 60 | } |
61 | catch( Bu::MyriadException &e ) | 61 | catch( Bu::MyriadException &e ) |
62 | { | 62 | { |
63 | int iStream = mStore.createStream(); | 63 | int iStream = mStore.createStream(); |
64 | if( iStream != 1 ) | 64 | if( iStream != 1 ) |
65 | throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", | 65 | throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", |
66 | iStream ); | 66 | iStream ); |
67 | MyriadStream ns = mStore.openStream( 1 ); | 67 | MyriadStream ns = mStore.openStream( 1 ); |
68 | Bu::Archive ar( ns, Bu::Archive::save ); | 68 | Bu::Archive ar( ns, Bu::Archive::save ); |
69 | ar << hId; | 69 | ar << hId; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | virtual ~CacheStoreMyriad() | 73 | virtual ~CacheStoreMyriad() |
74 | { | 74 | { |
75 | MyriadStream ns = mStore.openStream( 1 ); | 75 | MyriadStream ns = mStore.openStream( 1 ); |
76 | Bu::Archive ar( ns, Bu::Archive::save ); | 76 | Bu::Archive ar( ns, Bu::Archive::save ); |
77 | ar << hId; | 77 | ar << hId; |
78 | } | 78 | } |
79 | 79 | ||
80 | virtual obtype *load( const keytype &key ) | 80 | virtual obtype *load( const keytype &key ) |
81 | { | 81 | { |
82 | int iStream = hId.get( key ); | 82 | int iStream = hId.get( key ); |
83 | MyriadStream ns = mStore.openStream( iStream ); | 83 | MyriadStream ns = mStore.openStream( iStream ); |
84 | obtype *pOb = __cacheStoreMyriadLoad<keytype, obtype>( ns, key ); | 84 | obtype *pOb = __cacheStoreMyriadLoad<keytype, obtype>( ns, key ); |
85 | return pOb; | 85 | return pOb; |
86 | } | 86 | } |
87 | 87 | ||
88 | virtual void unload( obtype *pObj, const keytype & ) | 88 | virtual void unload( obtype *pObj, const keytype & ) |
89 | { | 89 | { |
90 | delete pObj; | 90 | delete pObj; |
91 | } | 91 | } |
92 | 92 | ||
93 | virtual keytype create( obtype *pSrc ) | 93 | virtual keytype create( obtype *pSrc ) |
94 | { | 94 | { |
95 | keytype key = __cacheGetKey<keytype, obtype>( pSrc ); | 95 | keytype key = __cacheGetKey<keytype, obtype>( pSrc ); |
96 | int iStream = mStore.createStream(); | 96 | int iStream = mStore.createStream(); |
97 | hId.insert( key, iStream ); | 97 | hId.insert( key, iStream ); |
98 | MyriadStream ns = mStore.openStream( iStream ); | 98 | MyriadStream ns = mStore.openStream( iStream ); |
99 | __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key ); | 99 | __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key ); |
100 | ns.setSize( ns.tell() ); | 100 | ns.setSize( ns.tell() ); |
101 | return key; | 101 | return key; |
102 | } | 102 | } |
103 | 103 | ||
104 | virtual void sync() | 104 | virtual void sync() |
105 | { | 105 | { |
106 | MyriadStream ns = mStore.openStream( 1 ); | 106 | MyriadStream ns = mStore.openStream( 1 ); |
107 | Bu::Archive ar( ns, Bu::Archive::save ); | 107 | Bu::Archive ar( ns, Bu::Archive::save ); |
108 | ar << hId; | 108 | ar << hId; |
109 | ns.setSize( ns.tell() ); | 109 | ns.setSize( ns.tell() ); |
110 | mStore.sync(); | 110 | mStore.sync(); |
111 | } | 111 | } |
112 | 112 | ||
113 | virtual void sync( obtype *pSrc, const keytype &key ) | 113 | virtual void sync( obtype *pSrc, const keytype &key ) |
114 | { | 114 | { |
115 | int iStream = hId.get( key ); | 115 | int iStream = hId.get( key ); |
116 | MyriadStream ns = mStore.openStream( iStream ); | 116 | MyriadStream ns = mStore.openStream( iStream ); |
117 | __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key ); | 117 | __cacheStoreMyriadStore<keytype, obtype>( ns, *pSrc, key ); |
118 | ns.setSize( ns.tell() ); | 118 | ns.setSize( ns.tell() ); |
119 | } | 119 | } |
120 | 120 | ||
121 | virtual void destroy( obtype *pObj, const keytype &key ) | 121 | virtual void destroy( obtype *pObj, const keytype &key ) |
122 | { | 122 | { |
123 | int iStream = hId.get( key ); | 123 | int iStream = hId.get( key ); |
124 | mStore.deleteStream( iStream ); | 124 | mStore.deleteStream( iStream ); |
125 | hId.erase( key ); | 125 | hId.erase( key ); |
126 | delete pObj; | 126 | delete pObj; |
127 | } | 127 | } |
128 | 128 | ||
129 | virtual void destroy( const keytype &key ) | 129 | virtual void destroy( const keytype &key ) |
130 | { | 130 | { |
131 | int iStream = hId.get( key ); | 131 | int iStream = hId.get( key ); |
132 | mStore.deleteStream( iStream ); | 132 | mStore.deleteStream( iStream ); |
133 | hId.erase( key ); | 133 | hId.erase( key ); |
134 | } | 134 | } |
135 | 135 | ||
136 | virtual bool has( const keytype &key ) | 136 | virtual bool has( const keytype &key ) |
137 | { | 137 | { |
138 | return hId.has( key ); | 138 | return hId.has( key ); |
139 | } | 139 | } |
140 | 140 | ||
141 | virtual Bu::List<keytype> getKeys() | 141 | virtual Bu::List<keytype> getKeys() |
142 | { | 142 | { |
143 | return hId.getKeys(); | 143 | return hId.getKeys(); |
144 | } | 144 | } |
145 | 145 | ||
146 | virtual int getSize() | 146 | virtual int getSize() |
147 | { | 147 | { |
148 | return hId.getSize(); | 148 | return hId.getSize(); |
149 | } | 149 | } |
150 | 150 | ||
151 | private: | 151 | private: |
152 | Myriad mStore; | 152 | Myriad mStore; |
153 | typedef Bu::Hash<keytype, long> StreamHash; | 153 | typedef Bu::Hash<keytype, long> StreamHash; |
154 | StreamHash hId; | 154 | StreamHash hId; |
155 | }; | 155 | }; |
156 | }; | 156 | }; |
157 | 157 | ||
158 | #endif | 158 | #endif |
diff --git a/src/experimental/cipher.h b/src/experimental/cipher.h index 5d5cb07..6e58613 100644 --- a/src/experimental/cipher.h +++ b/src/experimental/cipher.h | |||
@@ -13,115 +13,115 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | template<int iBlockSize> | 16 | template<int iBlockSize> |
17 | class Cipher : public Bu::Filter | 17 | class Cipher : public Bu::Filter |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | Cipher( Bu::Stream &rNext ) : | 20 | Cipher( Bu::Stream &rNext ) : |
21 | Bu::Filter( rNext ), | 21 | Bu::Filter( rNext ), |
22 | iReadBufFill( 0 ), | 22 | iReadBufFill( 0 ), |
23 | iReadBufPos( 0 ), | 23 | iReadBufPos( 0 ), |
24 | iWriteBufFill( 0 ) | 24 | iWriteBufFill( 0 ) |
25 | { | 25 | { |
26 | } | 26 | } |
27 | 27 | ||
28 | virtual ~Cipher() | 28 | virtual ~Cipher() |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | virtual void start() | 32 | virtual void start() |
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
36 | virtual Bu::size stop() | 36 | virtual Bu::size stop() |
37 | { | 37 | { |
38 | flush(); | 38 | flush(); |
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | virtual Bu::size read( void *pBuf, Bu::size iBytes ) | 42 | virtual Bu::size read( void *pBuf, Bu::size iBytes ) |
43 | { | 43 | { |
44 | Bu::size iRead = 0; | 44 | Bu::size iRead = 0; |
45 | while( iRead < iBytes ) | 45 | while( iRead < iBytes ) |
46 | { | 46 | { |
47 | if( iReadBufFill < iBlockSize ) | 47 | if( iReadBufFill < iBlockSize ) |
48 | { | 48 | { |
49 | int iR = rNext.read( | 49 | int iR = rNext.read( |
50 | aReadBuf+iReadBufFill, | 50 | aReadBuf+iReadBufFill, |
51 | iBlockSize-iReadBufFill | 51 | iBlockSize-iReadBufFill |
52 | ); | 52 | ); |
53 | if( iR == 0 ) | 53 | if( iR == 0 ) |
54 | return iRead; | 54 | return iRead; |
55 | 55 | ||
56 | iReadBufFill += iR; | 56 | iReadBufFill += iR; |
57 | 57 | ||
58 | if( iReadBufFill == iBlockSize ) | 58 | if( iReadBufFill == iBlockSize ) |
59 | decipher( aReadBuf ); | 59 | decipher( aReadBuf ); |
60 | } | 60 | } |
61 | 61 | ||
62 | if( iReadBufFill == iBlockSize ) | 62 | if( iReadBufFill == iBlockSize ) |
63 | { | 63 | { |
64 | int iCpy = Bu::buMin( (int)(iBytes-iRead), iBlockSize-iReadBufPos ); | 64 | int iCpy = Bu::buMin( (int)(iBytes-iRead), iBlockSize-iReadBufPos ); |
65 | memcpy( ((char *)pBuf)+iRead, aReadBuf+iReadBufPos, iCpy ); | 65 | memcpy( ((char *)pBuf)+iRead, aReadBuf+iReadBufPos, iCpy ); |
66 | iRead += iCpy; | 66 | iRead += iCpy; |
67 | iReadBufPos += iCpy; | 67 | iReadBufPos += iCpy; |
68 | if( iReadBufPos == iBlockSize ) | 68 | if( iReadBufPos == iBlockSize ) |
69 | { | 69 | { |
70 | iReadBufPos = iReadBufFill = 0; | 70 | iReadBufPos = iReadBufFill = 0; |
71 | } | 71 | } |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | return iRead; | 75 | return iRead; |
76 | } | 76 | } |
77 | 77 | ||
78 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ) | 78 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ) |
79 | { | 79 | { |
80 | Bu::size iPos = 0; | 80 | Bu::size iPos = 0; |
81 | 81 | ||
82 | while( iPos < iBytes ) | 82 | while( iPos < iBytes ) |
83 | { | 83 | { |
84 | int iLeft = Bu::buMin((int)(iBytes-iPos),iBlockSize-iWriteBufFill); | 84 | int iLeft = Bu::buMin((int)(iBytes-iPos),iBlockSize-iWriteBufFill); |
85 | memcpy( aWriteBuf+iWriteBufFill, (char *)pBuf+iPos, iLeft ); | 85 | memcpy( aWriteBuf+iWriteBufFill, (char *)pBuf+iPos, iLeft ); |
86 | iPos += iLeft; | 86 | iPos += iLeft; |
87 | iWriteBufFill += iLeft; | 87 | iWriteBufFill += iLeft; |
88 | if( iWriteBufFill == iBlockSize ) | 88 | if( iWriteBufFill == iBlockSize ) |
89 | { | 89 | { |
90 | encipher( aWriteBuf ); | 90 | encipher( aWriteBuf ); |
91 | rNext.write( aWriteBuf, iBlockSize ); | 91 | rNext.write( aWriteBuf, iBlockSize ); |
92 | iWriteBufFill = 0; | 92 | iWriteBufFill = 0; |
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | return iPos; | 96 | return iPos; |
97 | } | 97 | } |
98 | 98 | ||
99 | virtual void flush() | 99 | virtual void flush() |
100 | { | 100 | { |
101 | if( iWriteBufFill > 0 && iWriteBufFill < iBlockSize ) | 101 | if( iWriteBufFill > 0 && iWriteBufFill < iBlockSize ) |
102 | { | 102 | { |
103 | memset( aWriteBuf+iWriteBufFill, 0, iBlockSize-iWriteBufFill ); | 103 | memset( aWriteBuf+iWriteBufFill, 0, iBlockSize-iWriteBufFill ); |
104 | encipher( aWriteBuf ); | 104 | encipher( aWriteBuf ); |
105 | rNext.write( aWriteBuf, iBlockSize ); | 105 | rNext.write( aWriteBuf, iBlockSize ); |
106 | iWriteBufFill = 0; | 106 | iWriteBufFill = 0; |
107 | } | 107 | } |
108 | rNext.flush(); | 108 | rNext.flush(); |
109 | } | 109 | } |
110 | 110 | ||
111 | using Bu::Stream::read; | 111 | using Bu::Stream::read; |
112 | using Bu::Stream::write; | 112 | using Bu::Stream::write; |
113 | 113 | ||
114 | protected: | 114 | protected: |
115 | virtual void encipher( void *pData )=0; | 115 | virtual void encipher( void *pData )=0; |
116 | virtual void decipher( void *pData )=0; | 116 | virtual void decipher( void *pData )=0; |
117 | 117 | ||
118 | private: | 118 | private: |
119 | char aReadBuf[iBlockSize]; | 119 | char aReadBuf[iBlockSize]; |
120 | char aWriteBuf[iBlockSize]; | 120 | char aWriteBuf[iBlockSize]; |
121 | int iReadBufFill; | 121 | int iReadBufFill; |
122 | int iReadBufPos; | 122 | int iReadBufPos; |
123 | int iWriteBufFill; | 123 | int iWriteBufFill; |
124 | }; | 124 | }; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | #endif | 127 | #endif |
diff --git a/src/experimental/ciphermodecbc.h b/src/experimental/ciphermodecbc.h index 8fbf9f6..b06a972 100644 --- a/src/experimental/ciphermodecbc.h +++ b/src/experimental/ciphermodecbc.h | |||
@@ -6,49 +6,49 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | template<int iBlockSize, typename CipherType> | 9 | template<int iBlockSize, typename CipherType> |
10 | class CipherModeCbc : public CipherType | 10 | class CipherModeCbc : public CipherType |
11 | { | 11 | { |
12 | public: | 12 | public: |
13 | CipherModeCbc(class Stream &rNext ) : | 13 | CipherModeCbc(class Stream &rNext ) : |
14 | CipherType( rNext ), | 14 | CipherType( rNext ), |
15 | bStart( true ) | 15 | bStart( true ) |
16 | { | 16 | { |
17 | memset( aVector, 0, iBlockSize ); | 17 | memset( aVector, 0, iBlockSize ); |
18 | } | 18 | } |
19 | 19 | ||
20 | virtual ~CipherModeCbc() | 20 | virtual ~CipherModeCbc() |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
24 | void setIv( const Bu::String &sIv ) | 24 | void setIv( const Bu::String &sIv ) |
25 | { | 25 | { |
26 | memcpy( aVector, sIv.getStr(), iBlockSize ); | 26 | memcpy( aVector, sIv.getStr(), iBlockSize ); |
27 | } | 27 | } |
28 | 28 | ||
29 | protected: | 29 | protected: |
30 | void decipher( void *pBuf ) | 30 | void decipher( void *pBuf ) |
31 | { | 31 | { |
32 | uint8_t aTmp[iBlockSize]; | 32 | uint8_t aTmp[iBlockSize]; |
33 | memcpy( aTmp, pBuf, iBlockSize ); | 33 | memcpy( aTmp, pBuf, iBlockSize ); |
34 | CipherType::decipher( pBuf ); | 34 | CipherType::decipher( pBuf ); |
35 | for( int j = 0; j < iBlockSize; j++ ) | 35 | for( int j = 0; j < iBlockSize; j++ ) |
36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; | 36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; |
37 | memcpy( aVector, aTmp, iBlockSize ); | 37 | memcpy( aVector, aTmp, iBlockSize ); |
38 | } | 38 | } |
39 | 39 | ||
40 | void encipher( void *pBuf ) | 40 | void encipher( void *pBuf ) |
41 | { | 41 | { |
42 | for( int j = 0; j < iBlockSize; j++ ) | 42 | for( int j = 0; j < iBlockSize; j++ ) |
43 | ((uint8_t *)pBuf)[j] ^= aVector[j]; | 43 | ((uint8_t *)pBuf)[j] ^= aVector[j]; |
44 | CipherType::encipher( pBuf ); | 44 | CipherType::encipher( pBuf ); |
45 | memcpy( aVector, pBuf, iBlockSize ); | 45 | memcpy( aVector, pBuf, iBlockSize ); |
46 | } | 46 | } |
47 | 47 | ||
48 | private: | 48 | private: |
49 | bool bStart; | 49 | bool bStart; |
50 | uint8_t aVector[iBlockSize]; | 50 | uint8_t aVector[iBlockSize]; |
51 | }; | 51 | }; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #endif | 54 | #endif |
diff --git a/src/experimental/ciphermodecfb.h b/src/experimental/ciphermodecfb.h index dab6c2e..34c682f 100644 --- a/src/experimental/ciphermodecfb.h +++ b/src/experimental/ciphermodecfb.h | |||
@@ -6,48 +6,48 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | template<int iBlockSize, typename CipherType> | 9 | template<int iBlockSize, typename CipherType> |
10 | class CipherModeCfb : public CipherType | 10 | class CipherModeCfb : public CipherType |
11 | { | 11 | { |
12 | public: | 12 | public: |
13 | CipherModeCfb(class Stream &rNext ) : | 13 | CipherModeCfb(class Stream &rNext ) : |
14 | CipherType( rNext ), | 14 | CipherType( rNext ), |
15 | bStart( true ) | 15 | bStart( true ) |
16 | { | 16 | { |
17 | memset( aVector, 0, iBlockSize ); | 17 | memset( aVector, 0, iBlockSize ); |
18 | } | 18 | } |
19 | 19 | ||
20 | virtual ~CipherModeCfb() | 20 | virtual ~CipherModeCfb() |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
24 | void setIv( const Bu::String &sIv ) | 24 | void setIv( const Bu::String &sIv ) |
25 | { | 25 | { |
26 | memcpy( aVector, sIv.getStr(), iBlockSize ); | 26 | memcpy( aVector, sIv.getStr(), iBlockSize ); |
27 | } | 27 | } |
28 | 28 | ||
29 | protected: | 29 | protected: |
30 | void decipher( void *pBuf ) | 30 | void decipher( void *pBuf ) |
31 | { | 31 | { |
32 | uint8_t aTmp[iBlockSize]; | 32 | uint8_t aTmp[iBlockSize]; |
33 | memcpy( aTmp, pBuf, iBlockSize ); | 33 | memcpy( aTmp, pBuf, iBlockSize ); |
34 | CipherType::encipher( aVector ); | 34 | CipherType::encipher( aVector ); |
35 | for( int j = 0; j < iBlockSize; j++ ) | 35 | for( int j = 0; j < iBlockSize; j++ ) |
36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; | 36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; |
37 | memcpy( aVector, aTmp, iBlockSize ); | 37 | memcpy( aVector, aTmp, iBlockSize ); |
38 | } | 38 | } |
39 | 39 | ||
40 | void encipher( void *pBuf ) | 40 | void encipher( void *pBuf ) |
41 | { | 41 | { |
42 | CipherType::encipher( aVector ); | 42 | CipherType::encipher( aVector ); |
43 | for( int j = 0; j < iBlockSize; j++ ) | 43 | for( int j = 0; j < iBlockSize; j++ ) |
44 | aVector[j] = ((uint8_t *)pBuf)[j] ^= aVector[j]; | 44 | aVector[j] = ((uint8_t *)pBuf)[j] ^= aVector[j]; |
45 | } | 45 | } |
46 | 46 | ||
47 | private: | 47 | private: |
48 | bool bStart; | 48 | bool bStart; |
49 | uint8_t aVector[iBlockSize]; | 49 | uint8_t aVector[iBlockSize]; |
50 | }; | 50 | }; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | #endif | 53 | #endif |
diff --git a/src/experimental/ciphermodeecb.h b/src/experimental/ciphermodeecb.h index 006741a..cac2beb 100644 --- a/src/experimental/ciphermodeecb.h +++ b/src/experimental/ciphermodeecb.h | |||
@@ -3,30 +3,30 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | template<int iBlockSize, typename CipherType> | 6 | template<int iBlockSize, typename CipherType> |
7 | class CipherModeEcb : public CipherType | 7 | class CipherModeEcb : public CipherType |
8 | { | 8 | { |
9 | public: | 9 | public: |
10 | CipherModeEcb( class Stream &rNext ) : | 10 | CipherModeEcb( class Stream &rNext ) : |
11 | CipherType( rNext ) | 11 | CipherType( rNext ) |
12 | { | 12 | { |
13 | } | 13 | } |
14 | 14 | ||
15 | virtual ~CipherModeEcb() | 15 | virtual ~CipherModeEcb() |
16 | { | 16 | { |
17 | } | 17 | } |
18 | 18 | ||
19 | protected: | 19 | protected: |
20 | virtual void decipher( void *pBuf ) | 20 | virtual void decipher( void *pBuf ) |
21 | { | 21 | { |
22 | CipherType::decipher( pBuf ); | 22 | CipherType::decipher( pBuf ); |
23 | } | 23 | } |
24 | 24 | ||
25 | virtual void encipher( void *pBuf ) | 25 | virtual void encipher( void *pBuf ) |
26 | { | 26 | { |
27 | CipherType::encipher( pBuf ); | 27 | CipherType::encipher( pBuf ); |
28 | } | 28 | } |
29 | }; | 29 | }; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | #endif | 32 | #endif |
diff --git a/src/experimental/ciphermodeofb.h b/src/experimental/ciphermodeofb.h index 8c2aa20..e1b5108 100644 --- a/src/experimental/ciphermodeofb.h +++ b/src/experimental/ciphermodeofb.h | |||
@@ -6,51 +6,51 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | template<int iBlockSize, typename CipherType> | 9 | template<int iBlockSize, typename CipherType> |
10 | class CipherModeOfb : public CipherType | 10 | class CipherModeOfb : public CipherType |
11 | { | 11 | { |
12 | public: | 12 | public: |
13 | CipherModeOfb(class Stream &rNext ) : | 13 | CipherModeOfb(class Stream &rNext ) : |
14 | CipherType( rNext ), | 14 | CipherType( rNext ), |
15 | bStart( true ) | 15 | bStart( true ) |
16 | { | 16 | { |
17 | memset( aVector, 0, iBlockSize ); | 17 | memset( aVector, 0, iBlockSize ); |
18 | } | 18 | } |
19 | 19 | ||
20 | virtual ~CipherModeOfb() | 20 | virtual ~CipherModeOfb() |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
24 | void setIv( const Bu::String &sIv ) | 24 | void setIv( const Bu::String &sIv ) |
25 | { | 25 | { |
26 | memcpy( aVector, sIv.getStr(), iBlockSize ); | 26 | memcpy( aVector, sIv.getStr(), iBlockSize ); |
27 | } | 27 | } |
28 | 28 | ||
29 | protected: | 29 | protected: |
30 | void decipher( void *pBuf ) | 30 | void decipher( void *pBuf ) |
31 | { | 31 | { |
32 | CipherType::encipher( aVector ); | 32 | CipherType::encipher( aVector ); |
33 | uint8_t aTmp[iBlockSize]; | 33 | uint8_t aTmp[iBlockSize]; |
34 | memcpy( aTmp, aVector, iBlockSize ); | 34 | memcpy( aTmp, aVector, iBlockSize ); |
35 | for( int j = 0; j < iBlockSize; j++ ) | 35 | for( int j = 0; j < iBlockSize; j++ ) |
36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; | 36 | ((uint8_t *)pBuf)[j] ^= aVector[j]; |
37 | memcpy( aVector, aTmp, iBlockSize ); | 37 | memcpy( aVector, aTmp, iBlockSize ); |
38 | } | 38 | } |
39 | 39 | ||
40 | void encipher( void *pBuf ) | 40 | void encipher( void *pBuf ) |
41 | { | 41 | { |
42 | CipherType::encipher( aVector ); | 42 | CipherType::encipher( aVector ); |
43 | uint8_t aTmp[iBlockSize]; | 43 | uint8_t aTmp[iBlockSize]; |
44 | memcpy( aTmp, aVector, iBlockSize ); | 44 | memcpy( aTmp, aVector, iBlockSize ); |
45 | for( int j = 0; j < iBlockSize; j++ ) | 45 | for( int j = 0; j < iBlockSize; j++ ) |
46 | ((uint8_t *)pBuf)[j] ^= aVector[j]; | 46 | ((uint8_t *)pBuf)[j] ^= aVector[j]; |
47 | memcpy( aVector, aTmp, iBlockSize ); | 47 | memcpy( aVector, aTmp, iBlockSize ); |
48 | } | 48 | } |
49 | 49 | ||
50 | private: | 50 | private: |
51 | bool bStart; | 51 | bool bStart; |
52 | uint8_t aVector[iBlockSize]; | 52 | uint8_t aVector[iBlockSize]; |
53 | }; | 53 | }; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | #endif | 56 | #endif |
diff --git a/src/experimental/dir.h b/src/experimental/dir.h index 8e885d1..9e518eb 100644 --- a/src/experimental/dir.h +++ b/src/experimental/dir.h | |||
@@ -6,15 +6,15 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | class Dir : public FileSystem | 9 | class Dir : public FileSystem |
10 | { | 10 | { |
11 | public: | 11 | public: |
12 | Dir(); | 12 | Dir(); |
13 | Dir( const Bu::String &sPath ); | 13 | Dir( const Bu::String &sPath ); |
14 | virtual ~Dir(); | 14 | virtual ~Dir(); |
15 | 15 | ||
16 | private: | 16 | private: |
17 | }; | 17 | }; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | #endif | 20 | #endif |
diff --git a/src/experimental/fastcgi.cpp b/src/experimental/fastcgi.cpp index 7068fa8..71426b9 100644 --- a/src/experimental/fastcgi.cpp +++ b/src/experimental/fastcgi.cpp | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "bu/fastcgi.h" | 8 | #include "bu/fastcgi.h" |
9 | 9 | ||
10 | #ifndef WIN32 | 10 | #ifndef WIN32 |
11 | #include <arpa/inet.h> | 11 | #include <arpa/inet.h> |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #include <errno.h> | 14 | #include <errno.h> |
@@ -21,17 +21,17 @@ using Bu::sio; | |||
21 | using Bu::Fmt; | 21 | using Bu::Fmt; |
22 | 22 | ||
23 | Bu::FastCgi::FastCgi() : | 23 | Bu::FastCgi::FastCgi() : |
24 | pSrv( NULL ), | 24 | pSrv( NULL ), |
25 | bRunning( true ) | 25 | bRunning( true ) |
26 | { | 26 | { |
27 | pSrv = new Bu::TcpServerSocket( (Bu::TcpServerSocket::socket_t)STDIN_FILENO, false ); | 27 | pSrv = new Bu::TcpServerSocket( (Bu::TcpServerSocket::socket_t)STDIN_FILENO, false ); |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::FastCgi::FastCgi( int iPort ) : | 30 | Bu::FastCgi::FastCgi( int iPort ) : |
31 | pSrv( NULL ), | 31 | pSrv( NULL ), |
32 | bRunning( true ) | 32 | bRunning( true ) |
33 | { | 33 | { |
34 | pSrv = new Bu::TcpServerSocket( iPort ); | 34 | pSrv = new Bu::TcpServerSocket( iPort ); |
35 | } | 35 | } |
36 | 36 | ||
37 | Bu::FastCgi::~FastCgi() | 37 | Bu::FastCgi::~FastCgi() |
@@ -41,332 +41,332 @@ Bu::FastCgi::~FastCgi() | |||
41 | bool Bu::FastCgi::isEmbedded() | 41 | bool Bu::FastCgi::isEmbedded() |
42 | { | 42 | { |
43 | #ifndef WIN32 | 43 | #ifndef WIN32 |
44 | struct sockaddr name; | 44 | struct sockaddr name; |
45 | socklen_t namelen = sizeof(name); | 45 | socklen_t namelen = sizeof(name); |
46 | if( getpeername( STDIN_FILENO, &name, &namelen ) != 0 && | 46 | if( getpeername( STDIN_FILENO, &name, &namelen ) != 0 && |
47 | errno == ENOTCONN ) | 47 | errno == ENOTCONN ) |
48 | { | 48 | { |
49 | sio << "errno = " << errno << " (" << strerror( errno ) << ")" << | 49 | sio << "errno = " << errno << " (" << strerror( errno ) << ")" << |
50 | sio.nl; | 50 | sio.nl; |
51 | sio << "Socket found" << sio.nl; | 51 | sio << "Socket found" << sio.nl; |
52 | return true; | 52 | return true; |
53 | } | 53 | } |
54 | else | 54 | else |
55 | { | 55 | { |
56 | sio << "errno = " << errno << " (" << strerror( errno ) << ")" << | 56 | sio << "errno = " << errno << " (" << strerror( errno ) << ")" << |
57 | sio.nl; | 57 | sio.nl; |
58 | sio << "No socket detected, running in standalone mode" << sio.nl; | 58 | sio << "No socket detected, running in standalone mode" << sio.nl; |
59 | return false; | 59 | return false; |
60 | } | 60 | } |
61 | #else | 61 | #else |
62 | #warning Bu::FastCgi::isEmbedded IS A STUB for WIN32!!!! | 62 | #warning Bu::FastCgi::isEmbedded IS A STUB for WIN32!!!! |
63 | return false; | 63 | return false; |
64 | #endif | 64 | #endif |
65 | } | 65 | } |
66 | 66 | ||
67 | void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::Record &r ) | 67 | void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::Record &r ) |
68 | { | 68 | { |
69 | int iRead = s.read( &r, sizeof(Record) ); | 69 | int iRead = s.read( &r, sizeof(Record) ); |
70 | if( iRead != sizeof(Record) ) | 70 | if( iRead != sizeof(Record) ) |
71 | throw Bu::TcpSocketException("Hey, the size %d is wrong for Record. (%s)", | 71 | throw Bu::TcpSocketException("Hey, the size %d is wrong for Record. (%s)", |
72 | iRead, strerror( errno ) ); | 72 | iRead, strerror( errno ) ); |
73 | r.uRequestId = ntohs( r.uRequestId ); | 73 | r.uRequestId = ntohs( r.uRequestId ); |
74 | r.uContentLength = ntohs( r.uContentLength ); | 74 | r.uContentLength = ntohs( r.uContentLength ); |
75 | } | 75 | } |
76 | 76 | ||
77 | void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::Record r ) | 77 | void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::Record r ) |
78 | { | 78 | { |
79 | // sio << "Out -> " << r << sio.nl; | 79 | // sio << "Out -> " << r << sio.nl; |
80 | r.uRequestId = htons( r.uRequestId ); | 80 | r.uRequestId = htons( r.uRequestId ); |
81 | r.uContentLength = htons( r.uContentLength ); | 81 | r.uContentLength = htons( r.uContentLength ); |
82 | s.write( &r, sizeof(Record) ); | 82 | s.write( &r, sizeof(Record) ); |
83 | } | 83 | } |
84 | 84 | ||
85 | void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::BeginRequestBody &b ) | 85 | void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::BeginRequestBody &b ) |
86 | { | 86 | { |
87 | s.read( &b, sizeof(BeginRequestBody) ); | 87 | s.read( &b, sizeof(BeginRequestBody) ); |
88 | b.uRole = ntohs( b.uRole ); | 88 | b.uRole = ntohs( b.uRole ); |
89 | } | 89 | } |
90 | 90 | ||
91 | void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::EndRequestBody b ) | 91 | void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::EndRequestBody b ) |
92 | { | 92 | { |
93 | b.uStatus = htonl( b.uStatus ); | 93 | b.uStatus = htonl( b.uStatus ); |
94 | s.write( &b, sizeof(b) ); | 94 | s.write( &b, sizeof(b) ); |
95 | } | 95 | } |
96 | 96 | ||
97 | uint32_t Bu::FastCgi::readLen( Bu::TcpSocket &s, uint16_t &uRead ) | 97 | uint32_t Bu::FastCgi::readLen( Bu::TcpSocket &s, uint16_t &uRead ) |
98 | { | 98 | { |
99 | uint8_t uByte[4]; | 99 | uint8_t uByte[4]; |
100 | s.read( uByte, 1 ); | 100 | s.read( uByte, 1 ); |
101 | uRead++; | 101 | uRead++; |
102 | if( uByte[0] >> 7 == 0 ) | 102 | if( uByte[0] >> 7 == 0 ) |
103 | return uByte[0]; | 103 | return uByte[0]; |
104 | 104 | ||
105 | s.read( uByte+1, 3 ); | 105 | s.read( uByte+1, 3 ); |
106 | uRead += 3; | 106 | uRead += 3; |
107 | return ((uByte[0]&0x7f)<<24)|(uByte[1]<<16)|(uByte[2]<<8)|(uByte[3]); | 107 | return ((uByte[0]&0x7f)<<24)|(uByte[1]<<16)|(uByte[2]<<8)|(uByte[3]); |
108 | } | 108 | } |
109 | 109 | ||
110 | void Bu::FastCgi::readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uRead ) | 110 | void Bu::FastCgi::readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uRead ) |
111 | { | 111 | { |
112 | uint32_t uName = readLen( s, uRead ); | 112 | uint32_t uName = readLen( s, uRead ); |
113 | uint32_t uValue = readLen( s, uRead ); | 113 | uint32_t uValue = readLen( s, uRead ); |
114 | uRead += uName + uValue; | 114 | uRead += uName + uValue; |
115 | unsigned char *sName = new unsigned char[uName]; | 115 | unsigned char *sName = new unsigned char[uName]; |
116 | s.read( sName, uName ); | 116 | s.read( sName, uName ); |
117 | Bu::String fsName( (char *)sName, uName ); | 117 | Bu::String fsName( (char *)sName, uName ); |
118 | delete[] sName; | 118 | delete[] sName; |
119 | 119 | ||
120 | if( uValue > 0 ) | 120 | if( uValue > 0 ) |
121 | { | 121 | { |
122 | unsigned char *sValue = new unsigned char[uValue]; | 122 | unsigned char *sValue = new unsigned char[uValue]; |
123 | s.read( sValue, uValue ); | 123 | s.read( sValue, uValue ); |
124 | Bu::String fsValue( (char *)sValue, uValue ); | 124 | Bu::String fsValue( (char *)sValue, uValue ); |
125 | hParams.insert( fsName, fsValue ); | 125 | hParams.insert( fsName, fsValue ); |
126 | delete[] sValue; | 126 | delete[] sValue; |
127 | } | 127 | } |
128 | else | 128 | else |
129 | { | 129 | { |
130 | hParams.insert( fsName, "" ); | 130 | hParams.insert( fsName, "" ); |
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | bool Bu::FastCgi::hasChannel( int iChan ) | 134 | bool Bu::FastCgi::hasChannel( int iChan ) |
135 | { | 135 | { |
136 | if( aChannel.getSize() < iChan ) | 136 | if( aChannel.getSize() < iChan ) |
137 | return false; | 137 | return false; |
138 | if( aChannel[iChan-1] == NULL ) | 138 | if( aChannel[iChan-1] == NULL ) |
139 | return false; | 139 | return false; |
140 | return true; | 140 | return true; |
141 | } | 141 | } |
142 | 142 | ||
143 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ) | 143 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ) |
144 | { | 144 | { |
145 | f << "[Ver=" << (uint32_t)r.uVersion << | 145 | f << "[Ver=" << (uint32_t)r.uVersion << |
146 | ", Type=" << (uint32_t)r.uType << | 146 | ", Type=" << (uint32_t)r.uType << |
147 | ", Req=" << (uint32_t)r.uRequestId << | 147 | ", Req=" << (uint32_t)r.uRequestId << |
148 | ", clen=" << (uint32_t)r.uContentLength << | 148 | ", clen=" << (uint32_t)r.uContentLength << |
149 | ", plen=" << (uint32_t)r.uPaddingLength << | 149 | ", plen=" << (uint32_t)r.uPaddingLength << |
150 | ", resv=" << (uint32_t)r.uReserved << | 150 | ", resv=" << (uint32_t)r.uReserved << |
151 | "]"; | 151 | "]"; |
152 | return f; | 152 | return f; |
153 | } | 153 | } |
154 | 154 | ||
155 | void Bu::FastCgi::run() | 155 | void Bu::FastCgi::run() |
156 | { | 156 | { |
157 | // sio << "sizeof(Bu::FastCgi::Record) = " << sizeof(Record) << sio.nl; | 157 | // sio << "sizeof(Bu::FastCgi::Record) = " << sizeof(Record) << sio.nl; |
158 | bRunning = true; | 158 | bRunning = true; |
159 | while( bRunning ) | 159 | while( bRunning ) |
160 | { | 160 | { |
161 | int iSock = pSrv->accept( 5 ); | 161 | int iSock = pSrv->accept( 5 ); |
162 | if( iSock < 0 ) | 162 | if( iSock < 0 ) |
163 | continue; | 163 | continue; |
164 | 164 | ||
165 | Bu::TcpSocket s( iSock ); | 165 | Bu::TcpSocket s( iSock ); |
166 | s.setBlocking( true ); | 166 | s.setBlocking( true ); |
167 | // sio << "Got connection, blocking? " << s.isBlocking() << sio.nl; | 167 | // sio << "Got connection, blocking? " << s.isBlocking() << sio.nl; |
168 | try | 168 | try |
169 | { | 169 | { |
170 | for(;;) | 170 | for(;;) |
171 | { | 171 | { |
172 | Record r; | 172 | Record r; |
173 | memset( &r, 0, sizeof(r) ); | 173 | memset( &r, 0, sizeof(r) ); |
174 | // try | 174 | // try |
175 | // { | 175 | // { |
176 | read( s, r ); | 176 | read( s, r ); |
177 | // } | 177 | // } |
178 | // catch( Bu::ExceptionBase &e ) | 178 | // catch( Bu::ExceptionBase &e ) |
179 | // { | 179 | // { |
180 | // sio << "Error: " << e.what() << ", " << s.isOpen() << | 180 | // sio << "Error: " << e.what() << ", " << s.isOpen() << |
181 | // sio.nl; | 181 | // sio.nl; |
182 | // continue; | 182 | // continue; |
183 | // } | 183 | // } |
184 | Channel *pChan = NULL; | 184 | Channel *pChan = NULL; |
185 | if( r.uRequestId > 0 ) | 185 | if( r.uRequestId > 0 ) |
186 | { | 186 | { |
187 | if( !hasChannel( r.uRequestId ) && | 187 | if( !hasChannel( r.uRequestId ) && |
188 | r.uType != typeBeginRequest ) | 188 | r.uType != typeBeginRequest ) |
189 | { | 189 | { |
190 | sio << "Error, stream data without stream." << sio.nl; | 190 | sio << "Error, stream data without stream." << sio.nl; |
191 | sio << r << sio.nl; | 191 | sio << r << sio.nl; |
192 | if( r.uContentLength > 0 ) | 192 | if( r.uContentLength > 0 ) |
193 | { | 193 | { |
194 | char *buf = new char[r.uContentLength]; | 194 | char *buf = new char[r.uContentLength]; |
195 | sio << " (read " << s.read( buf, r.uContentLength ) | 195 | sio << " (read " << s.read( buf, r.uContentLength ) |
196 | << "/" << r.uContentLength << "):" << sio.nl; | 196 | << "/" << r.uContentLength << "):" << sio.nl; |
197 | sio.write( buf, r.uContentLength ); | 197 | sio.write( buf, r.uContentLength ); |
198 | sio << sio.nl << sio.nl; | 198 | sio << sio.nl << sio.nl; |
199 | } | 199 | } |
200 | } | 200 | } |
201 | while( aChannel.getSize() < r.uRequestId ) | 201 | while( aChannel.getSize() < r.uRequestId ) |
202 | aChannel.append( NULL ); | 202 | aChannel.append( NULL ); |
203 | if( r.uRequestId > 0 ) | 203 | if( r.uRequestId > 0 ) |
204 | pChan = aChannel[r.uRequestId-1]; | 204 | pChan = aChannel[r.uRequestId-1]; |
205 | } | 205 | } |
206 | 206 | ||
207 | // sio << "Record (id=" << r.uRequestId << ", len=" << | 207 | // sio << "Record (id=" << r.uRequestId << ", len=" << |
208 | // r.uContentLength << ", pad=" << | 208 | // r.uContentLength << ", pad=" << |
209 | // (unsigned int)r.uPaddingLength << "): "; | 209 | // (unsigned int)r.uPaddingLength << "): "; |
210 | // fflush( stdout ); | 210 | // fflush( stdout ); |
211 | 211 | ||
212 | switch( (RequestType)r.uType ) | 212 | switch( (RequestType)r.uType ) |
213 | { | 213 | { |
214 | case typeBeginRequest: | 214 | case typeBeginRequest: |
215 | // sio << "Begin Request."; | 215 | // sio << "Begin Request."; |
216 | { | 216 | { |
217 | BeginRequestBody b; | 217 | BeginRequestBody b; |
218 | read( s, b ); | 218 | read( s, b ); |
219 | if( pChan != NULL ) | 219 | if( pChan != NULL ) |
220 | { | 220 | { |
221 | sio << "Error!!!" << sio.nl; | 221 | sio << "Error!!!" << sio.nl; |
222 | return; | 222 | return; |
223 | } | 223 | } |
224 | pChan = aChannel[r.uRequestId-1] = new Channel(); | 224 | pChan = aChannel[r.uRequestId-1] = new Channel(); |
225 | } | 225 | } |
226 | break; | 226 | break; |
227 | 227 | ||
228 | case typeParams: | 228 | case typeParams: |
229 | // sio << "Params."; | 229 | // sio << "Params."; |
230 | if( r.uContentLength == 0 ) | 230 | if( r.uContentLength == 0 ) |
231 | { | 231 | { |
232 | pChan->uFlags |= chflgParamsDone; | 232 | pChan->uFlags |= chflgParamsDone; |
233 | } | 233 | } |
234 | else | 234 | else |
235 | { | 235 | { |
236 | uint16_t uUsed = 0; | 236 | uint16_t uUsed = 0; |
237 | while( uUsed < r.uContentLength ) | 237 | while( uUsed < r.uContentLength ) |
238 | { | 238 | { |
239 | readPair( s, pChan->hParams, uUsed ); | 239 | readPair( s, pChan->hParams, uUsed ); |
240 | } | 240 | } |
241 | } | 241 | } |
242 | break; | 242 | break; |
243 | 243 | ||
244 | case typeStdIn: | 244 | case typeStdIn: |
245 | // sio << "StdIn."; | 245 | // sio << "StdIn."; |
246 | if( r.uContentLength == 0 ) | 246 | if( r.uContentLength == 0 ) |
247 | { | 247 | { |
248 | pChan->uFlags |= chflgStdInDone; | 248 | pChan->uFlags |= chflgStdInDone; |
249 | } | 249 | } |
250 | else | 250 | else |
251 | { | 251 | { |
252 | char *buf = new char[r.uContentLength]; | 252 | char *buf = new char[r.uContentLength]; |
253 | int iTotal = 0; | 253 | int iTotal = 0; |
254 | do | 254 | do |
255 | { | 255 | { |
256 | size_t iRead = s.read( | 256 | size_t iRead = s.read( |
257 | buf, r.uContentLength-iTotal ); | 257 | buf, r.uContentLength-iTotal ); |
258 | iTotal += iRead; | 258 | iTotal += iRead; |
259 | // sio << " (read " << iRead << " " << iTotal | 259 | // sio << " (read " << iRead << " " << iTotal |
260 | // << "/" << r.uContentLength << ")"; | 260 | // << "/" << r.uContentLength << ")"; |
261 | pChan->sStdIn.append( buf, iRead ); | 261 | pChan->sStdIn.append( buf, iRead ); |
262 | } while( iTotal < r.uContentLength ); | 262 | } while( iTotal < r.uContentLength ); |
263 | delete[] buf; | 263 | delete[] buf; |
264 | } | 264 | } |
265 | break; | 265 | break; |
266 | 266 | ||
267 | case typeData: | 267 | case typeData: |
268 | // sio << "Data."; | 268 | // sio << "Data."; |
269 | if( r.uContentLength == 0 ) | 269 | if( r.uContentLength == 0 ) |
270 | { | 270 | { |
271 | pChan->uFlags |= chflgDataDone; | 271 | pChan->uFlags |= chflgDataDone; |
272 | } | 272 | } |
273 | else | 273 | else |
274 | { | 274 | { |
275 | char *buf = new char[r.uContentLength]; | 275 | char *buf = new char[r.uContentLength]; |
276 | s.read( buf, r.uContentLength ); | 276 | s.read( buf, r.uContentLength ); |
277 | pChan->sData.append( buf, r.uContentLength ); | 277 | pChan->sData.append( buf, r.uContentLength ); |
278 | delete[] buf; | 278 | delete[] buf; |
279 | } | 279 | } |
280 | break; | 280 | break; |
281 | 281 | ||
282 | case typeStdOut: | 282 | case typeStdOut: |
283 | case typeStdErr: | 283 | case typeStdErr: |
284 | case typeEndRequest: | 284 | case typeEndRequest: |
285 | case typeAbortRequest: | 285 | case typeAbortRequest: |
286 | case typeGetValuesResult: | 286 | case typeGetValuesResult: |
287 | // sio << "Scary."; | 287 | // sio << "Scary."; |
288 | // ??? we shouldn't get these. | 288 | // ??? we shouldn't get these. |
289 | break; | 289 | break; |
290 | 290 | ||
291 | case typeGetValues: | 291 | case typeGetValues: |
292 | break; | 292 | break; |
293 | } | 293 | } |
294 | 294 | ||
295 | // sio << sio.nl; | 295 | // sio << sio.nl; |
296 | 296 | ||
297 | if( pChan ) | 297 | if( pChan ) |
298 | { | 298 | { |
299 | if( pChan->uFlags == chflgAllDone ) | 299 | if( pChan->uFlags == chflgAllDone ) |
300 | { | 300 | { |
301 | // sio << "All done, generating output." << sio.nl; | 301 | // sio << "All done, generating output." << sio.nl; |
302 | Bu::MemBuf mStdOut, mStdErr; | 302 | Bu::MemBuf mStdOut, mStdErr; |
303 | int iRet = onRequest( | 303 | int iRet = onRequest( |
304 | pChan->hParams, pChan->sStdIn, | 304 | pChan->hParams, pChan->sStdIn, |
305 | mStdOut, mStdErr | 305 | mStdOut, mStdErr |
306 | ); | 306 | ); |
307 | 307 | ||
308 | Bu::String &sStdOut = mStdOut.getString(); | 308 | Bu::String &sStdOut = mStdOut.getString(); |
309 | Bu::String &sStdErr = mStdErr.getString(); | 309 | Bu::String &sStdErr = mStdErr.getString(); |
310 | 310 | ||
311 | Record rOut; | 311 | Record rOut; |
312 | memset( &rOut, 0, sizeof(rOut) ); | 312 | memset( &rOut, 0, sizeof(rOut) ); |
313 | rOut.uVersion = 1; | 313 | rOut.uVersion = 1; |
314 | rOut.uRequestId = r.uRequestId; | 314 | rOut.uRequestId = r.uRequestId; |
315 | rOut.uPaddingLength = 0; | 315 | rOut.uPaddingLength = 0; |
316 | rOut.uType = typeStdOut; | 316 | rOut.uType = typeStdOut; |
317 | if( sStdOut.getSize() > 0 ) | 317 | if( sStdOut.getSize() > 0 ) |
318 | { | 318 | { |
319 | for( int iPos = 0; iPos < sStdOut.getSize(); | 319 | for( int iPos = 0; iPos < sStdOut.getSize(); |
320 | iPos += 65528 ) | 320 | iPos += 65528 ) |
321 | { | 321 | { |
322 | int iSize = sStdOut.getSize()-iPos; | 322 | int iSize = sStdOut.getSize()-iPos; |
323 | if( iSize > 65528 ) | 323 | if( iSize > 65528 ) |
324 | iSize = 65528; | 324 | iSize = 65528; |
325 | rOut.uContentLength = iSize; | 325 | rOut.uContentLength = iSize; |
326 | write( s, rOut ); | 326 | write( s, rOut ); |
327 | s.write( sStdOut.getStr()+iPos, iSize ); | 327 | s.write( sStdOut.getStr()+iPos, iSize ); |
328 | } | 328 | } |
329 | } | 329 | } |
330 | rOut.uContentLength = 0; | 330 | rOut.uContentLength = 0; |
331 | write( s, rOut ); | 331 | write( s, rOut ); |
332 | 332 | ||
333 | rOut.uType = typeStdErr; | 333 | rOut.uType = typeStdErr; |
334 | if( sStdErr.getSize() > 0 ) | 334 | if( sStdErr.getSize() > 0 ) |
335 | { | 335 | { |
336 | for( int iPos = 0; iPos < sStdErr.getSize(); | 336 | for( int iPos = 0; iPos < sStdErr.getSize(); |
337 | iPos += 65528 ) | 337 | iPos += 65528 ) |
338 | { | 338 | { |
339 | int iSize = sStdErr.getSize()-iPos; | 339 | int iSize = sStdErr.getSize()-iPos; |
340 | if( iSize > 65528 ) | 340 | if( iSize > 65528 ) |
341 | iSize = 65528; | 341 | iSize = 65528; |
342 | rOut.uContentLength = iSize; | 342 | rOut.uContentLength = iSize; |
343 | write( s, rOut ); | 343 | write( s, rOut ); |
344 | s.write( sStdErr.getStr()+iPos, iSize ); | 344 | s.write( sStdErr.getStr()+iPos, iSize ); |
345 | } | 345 | } |
346 | } | 346 | } |
347 | rOut.uContentLength = 0; | 347 | rOut.uContentLength = 0; |
348 | write( s, rOut ); | 348 | write( s, rOut ); |
349 | 349 | ||
350 | rOut.uType = typeEndRequest; | 350 | rOut.uType = typeEndRequest; |
351 | rOut.uContentLength = 8; | 351 | rOut.uContentLength = 8; |
352 | write( s, rOut ); | 352 | write( s, rOut ); |
353 | 353 | ||
354 | EndRequestBody b; | 354 | EndRequestBody b; |
355 | memset( &b, 0, sizeof(b) ); | 355 | memset( &b, 0, sizeof(b) ); |
356 | b.uStatus = iRet; | 356 | b.uStatus = iRet; |
357 | write( s, b ); | 357 | write( s, b ); |
358 | 358 | ||
359 | delete pChan; | 359 | delete pChan; |
360 | aChannel[r.uRequestId-1] = NULL; | 360 | aChannel[r.uRequestId-1] = NULL; |
361 | } | 361 | } |
362 | } | 362 | } |
363 | } | 363 | } |
364 | } | 364 | } |
365 | catch( Bu::TcpSocketException &e ) | 365 | catch( Bu::TcpSocketException &e ) |
366 | { | 366 | { |
367 | // sio << "Bu::SocketException: " << e.what() << sio.nl << | 367 | // sio << "Bu::SocketException: " << e.what() << sio.nl << |
368 | // "\tSocket open: " << s.isOpen() << sio.nl; | 368 | // "\tSocket open: " << s.isOpen() << sio.nl; |
369 | } | 369 | } |
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
diff --git a/src/experimental/fastcgi.h b/src/experimental/fastcgi.h index 63d975f..50b10f5 100644 --- a/src/experimental/fastcgi.h +++ b/src/experimental/fastcgi.h | |||
@@ -16,118 +16,118 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class Stream; | 19 | class Stream; |
20 | 20 | ||
21 | class FastCgi | 21 | class FastCgi |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | FastCgi( int iPort ); | 24 | FastCgi( int iPort ); |
25 | FastCgi(); | 25 | FastCgi(); |
26 | virtual ~FastCgi(); | 26 | virtual ~FastCgi(); |
27 | 27 | ||
28 | static bool isEmbedded(); | 28 | static bool isEmbedded(); |
29 | 29 | ||
30 | typedef Bu::Hash<Bu::String, Bu::String> StrHash; | 30 | typedef Bu::Hash<Bu::String, Bu::String> StrHash; |
31 | enum RequestType | 31 | enum RequestType |
32 | { | 32 | { |
33 | typeBeginRequest = 1, | 33 | typeBeginRequest = 1, |
34 | typeAbortRequest = 2, | 34 | typeAbortRequest = 2, |
35 | typeEndRequest = 3, | 35 | typeEndRequest = 3, |
36 | typeParams = 4, | 36 | typeParams = 4, |
37 | typeStdIn = 5, | 37 | typeStdIn = 5, |
38 | typeStdOut = 6, | 38 | typeStdOut = 6, |
39 | typeStdErr = 7, | 39 | typeStdErr = 7, |
40 | typeData = 8, | 40 | typeData = 8, |
41 | typeGetValues = 9, | 41 | typeGetValues = 9, |
42 | typeGetValuesResult = 10 | 42 | typeGetValuesResult = 10 |
43 | }; | 43 | }; |
44 | 44 | ||
45 | enum Role | 45 | enum Role |
46 | { | 46 | { |
47 | roleResponder = 1, | 47 | roleResponder = 1, |
48 | roleAuthorizer = 2, | 48 | roleAuthorizer = 2, |
49 | roleFilter = 3 | 49 | roleFilter = 3 |
50 | }; | 50 | }; |
51 | 51 | ||
52 | enum Flags | 52 | enum Flags |
53 | { | 53 | { |
54 | flagsKeepConn = 1 | 54 | flagsKeepConn = 1 |
55 | }; | 55 | }; |
56 | 56 | ||
57 | enum Status | 57 | enum Status |
58 | { | 58 | { |
59 | statusRequestComplete = 0, | 59 | statusRequestComplete = 0, |
60 | statusCantMpxConn = 1, | 60 | statusCantMpxConn = 1, |
61 | statusOverloaded = 2, | 61 | statusOverloaded = 2, |
62 | statusUnknownRole = 3 | 62 | statusUnknownRole = 3 |
63 | }; | 63 | }; |
64 | 64 | ||
65 | typedef struct { | 65 | typedef struct { |
66 | uint8_t uVersion; | 66 | uint8_t uVersion; |
67 | uint8_t uType; | 67 | uint8_t uType; |
68 | uint16_t uRequestId; | 68 | uint16_t uRequestId; |
69 | uint16_t uContentLength; | 69 | uint16_t uContentLength; |
70 | uint8_t uPaddingLength; | 70 | uint8_t uPaddingLength; |
71 | uint8_t uReserved; | 71 | uint8_t uReserved; |
72 | } Record; | 72 | } Record; |
73 | 73 | ||
74 | typedef struct { | 74 | typedef struct { |
75 | uint16_t uRole; | 75 | uint16_t uRole; |
76 | uint8_t uFlags; | 76 | uint8_t uFlags; |
77 | uint8_t reserved[5]; | 77 | uint8_t reserved[5]; |
78 | } BeginRequestBody; | 78 | } BeginRequestBody; |
79 | 79 | ||
80 | typedef struct { | 80 | typedef struct { |
81 | uint32_t uStatus; | 81 | uint32_t uStatus; |
82 | uint8_t uProtocolStatus; | 82 | uint8_t uProtocolStatus; |
83 | uint8_t reserved[3]; | 83 | uint8_t reserved[3]; |
84 | } EndRequestBody; | 84 | } EndRequestBody; |
85 | 85 | ||
86 | typedef struct Channel { | 86 | typedef struct Channel { |
87 | Channel() : uFlags( 0 ) { } | 87 | Channel() : uFlags( 0 ) { } |
88 | StrHash hParams; | 88 | StrHash hParams; |
89 | Bu::String sStdIn; | 89 | Bu::String sStdIn; |
90 | Bu::String sData; | 90 | Bu::String sData; |
91 | uint8_t uFlags; | 91 | uint8_t uFlags; |
92 | } Channel; | 92 | } Channel; |
93 | 93 | ||
94 | enum ChannelFlags | 94 | enum ChannelFlags |
95 | { | 95 | { |
96 | chflgParamsDone = 0x01, | 96 | chflgParamsDone = 0x01, |
97 | chflgStdInDone = 0x02, | 97 | chflgStdInDone = 0x02, |
98 | chflgDataDone = 0x04, | 98 | chflgDataDone = 0x04, |
99 | 99 | ||
100 | chflgAllDone = 0x03 | 100 | chflgAllDone = 0x03 |
101 | }; | 101 | }; |
102 | 102 | ||
103 | virtual void run(); | 103 | virtual void run(); |
104 | 104 | ||
105 | void stopRunning() { bRunning = false; } | 105 | void stopRunning() { bRunning = false; } |
106 | 106 | ||
107 | virtual void onInit() { }; | 107 | virtual void onInit() { }; |
108 | virtual int onRequest( const StrHash &hParams, | 108 | virtual int onRequest( const StrHash &hParams, |
109 | const Bu::String &sStdIn, Bu::Stream &sStdOut, | 109 | const Bu::String &sStdIn, Bu::Stream &sStdOut, |
110 | Bu::Stream &sStdErr )=0; | 110 | Bu::Stream &sStdErr )=0; |
111 | virtual void onUninit() { }; | 111 | virtual void onUninit() { }; |
112 | 112 | ||
113 | private: | 113 | private: |
114 | void read( Bu::TcpSocket &s, Record &r ); | 114 | void read( Bu::TcpSocket &s, Record &r ); |
115 | void read( Bu::TcpSocket &s, BeginRequestBody &b ); | 115 | void read( Bu::TcpSocket &s, BeginRequestBody &b ); |
116 | uint32_t readLen( Bu::TcpSocket &s, uint16_t &uUsed ); | 116 | uint32_t readLen( Bu::TcpSocket &s, uint16_t &uUsed ); |
117 | void readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uUsed ); | 117 | void readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uUsed ); |
118 | 118 | ||
119 | void write( Bu::TcpSocket &s, Record r ); | 119 | void write( Bu::TcpSocket &s, Record r ); |
120 | void write( Bu::TcpSocket &s, EndRequestBody b ); | 120 | void write( Bu::TcpSocket &s, EndRequestBody b ); |
121 | 121 | ||
122 | bool hasChannel( int iChan ); | 122 | bool hasChannel( int iChan ); |
123 | 123 | ||
124 | private: | 124 | private: |
125 | Bu::TcpServerSocket *pSrv; | 125 | Bu::TcpServerSocket *pSrv; |
126 | bool bRunning; | 126 | bool bRunning; |
127 | Bu::Array<Channel *> aChannel; | 127 | Bu::Array<Channel *> aChannel; |
128 | }; | 128 | }; |
129 | 129 | ||
130 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ); | 130 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ); |
131 | }; | 131 | }; |
132 | 132 | ||
133 | #endif | 133 | #endif |
diff --git a/src/experimental/filesystem.h b/src/experimental/filesystem.h index 0c992a5..d25cb67 100644 --- a/src/experimental/filesystem.h +++ b/src/experimental/filesystem.h | |||
@@ -3,22 +3,22 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | /** | 6 | /** |
7 | * Represents an abstract baseclass for any file organization structure. | 7 | * Represents an abstract baseclass for any file organization structure. |
8 | * If you're looking for acessing a local filesystem, try Bu::Dir. This | 8 | * If you're looking for acessing a local filesystem, try Bu::Dir. This |
9 | * is used to make switching between different types of filesystems | 9 | * is used to make switching between different types of filesystems |
10 | * seamless. FileSystems could be anything that organizes and grants | 10 | * seamless. FileSystems could be anything that organizes and grants |
11 | * access to file data, local filesystems, FTP servers, zip or myriadfs | 11 | * access to file data, local filesystems, FTP servers, zip or myriadfs |
12 | * files, etc. | 12 | * files, etc. |
13 | */ | 13 | */ |
14 | class FileSystem | 14 | class FileSystem |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | FileSystem(); | 17 | FileSystem(); |
18 | virtual ~FileSystem(); | 18 | virtual ~FileSystem(); |
19 | 19 | ||
20 | 20 | ||
21 | }; | 21 | }; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | #endif | 24 | #endif |
diff --git a/src/experimental/httpget.cpp b/src/experimental/httpget.cpp index 7a8a89a..70c722c 100644 --- a/src/experimental/httpget.cpp +++ b/src/experimental/httpget.cpp | |||
@@ -8,11 +8,11 @@ | |||
8 | #include "bu/httpget.h" | 8 | #include "bu/httpget.h" |
9 | 9 | ||
10 | Bu::HttpGet::HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod ) : | 10 | Bu::HttpGet::HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod ) : |
11 | uSrc( uSrc ), | 11 | uSrc( uSrc ), |
12 | sMethod( sMethod ), | 12 | sMethod( sMethod ), |
13 | sSrv( uSrc.getHost(), uSrc.getPort() ) | 13 | sSrv( uSrc.getHost(), uSrc.getPort() ) |
14 | { | 14 | { |
15 | sSrv.write( sMethod + " " + uSrc.getFullPath() + " HTTP/1.1\r\n" ); | 15 | sSrv.write( sMethod + " " + uSrc.getFullPath() + " HTTP/1.1\r\n" ); |
16 | } | 16 | } |
17 | 17 | ||
18 | Bu::HttpGet::~HttpGet() | 18 | Bu::HttpGet::~HttpGet() |
@@ -25,28 +25,28 @@ void Bu::HttpGet::close() | |||
25 | 25 | ||
26 | void Bu::HttpGet::get() | 26 | void Bu::HttpGet::get() |
27 | { | 27 | { |
28 | for( MimeHash::iterator i = hMimeOut.begin(); i; i++ ) | 28 | for( MimeHash::iterator i = hMimeOut.begin(); i; i++ ) |
29 | { | 29 | { |
30 | sSrv.write( i.getKey() + ": " + i.getValue() + "\r\n" ); | 30 | sSrv.write( i.getKey() + ": " + i.getValue() + "\r\n" ); |
31 | } | 31 | } |
32 | sSrv.write("\r\n", 2 ); | 32 | sSrv.write("\r\n", 2 ); |
33 | 33 | ||
34 | // sSrv.read( | 34 | // sSrv.read( |
35 | } | 35 | } |
36 | 36 | ||
37 | Bu::size Bu::HttpGet::read( void * /*pBuf*/, Bu::size /*nBytes*/ ) | 37 | Bu::size Bu::HttpGet::read( void * /*pBuf*/, Bu::size /*nBytes*/ ) |
38 | { | 38 | { |
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::size Bu::HttpGet::write( const void * /*pBuf*/, Bu::size /*nBytes*/ ) | 42 | Bu::size Bu::HttpGet::write( const void * /*pBuf*/, Bu::size /*nBytes*/ ) |
43 | { | 43 | { |
44 | return 0; | 44 | return 0; |
45 | } | 45 | } |
46 | 46 | ||
47 | Bu::size Bu::HttpGet::tell() | 47 | Bu::size Bu::HttpGet::tell() |
48 | { | 48 | { |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | void Bu::HttpGet::seek( Bu::size ) | 52 | void Bu::HttpGet::seek( Bu::size ) |
@@ -63,12 +63,12 @@ void Bu::HttpGet::setPosEnd( Bu::size ) | |||
63 | 63 | ||
64 | bool Bu::HttpGet::isEos() | 64 | bool Bu::HttpGet::isEos() |
65 | { | 65 | { |
66 | return false; | 66 | return false; |
67 | } | 67 | } |
68 | 68 | ||
69 | bool Bu::HttpGet::isOpen() | 69 | bool Bu::HttpGet::isOpen() |
70 | { | 70 | { |
71 | return true; | 71 | return true; |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::HttpGet::flush() | 74 | void Bu::HttpGet::flush() |
@@ -77,32 +77,32 @@ void Bu::HttpGet::flush() | |||
77 | 77 | ||
78 | bool Bu::HttpGet::canRead() | 78 | bool Bu::HttpGet::canRead() |
79 | { | 79 | { |
80 | return true; | 80 | return true; |
81 | } | 81 | } |
82 | 82 | ||
83 | bool Bu::HttpGet::canWrite() | 83 | bool Bu::HttpGet::canWrite() |
84 | { | 84 | { |
85 | return false; | 85 | return false; |
86 | } | 86 | } |
87 | 87 | ||
88 | bool Bu::HttpGet::isReadable() | 88 | bool Bu::HttpGet::isReadable() |
89 | { | 89 | { |
90 | return true; | 90 | return true; |
91 | } | 91 | } |
92 | 92 | ||
93 | bool Bu::HttpGet::isWritable() | 93 | bool Bu::HttpGet::isWritable() |
94 | { | 94 | { |
95 | return false; | 95 | return false; |
96 | } | 96 | } |
97 | 97 | ||
98 | bool Bu::HttpGet::isSeekable() | 98 | bool Bu::HttpGet::isSeekable() |
99 | { | 99 | { |
100 | return false; | 100 | return false; |
101 | } | 101 | } |
102 | 102 | ||
103 | bool Bu::HttpGet::isBlocking() | 103 | bool Bu::HttpGet::isBlocking() |
104 | { | 104 | { |
105 | return true; | 105 | return true; |
106 | } | 106 | } |
107 | 107 | ||
108 | void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) | 108 | void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) |
@@ -111,16 +111,16 @@ void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) | |||
111 | 111 | ||
112 | Bu::size Bu::HttpGet::getSize() const | 112 | Bu::size Bu::HttpGet::getSize() const |
113 | { | 113 | { |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | Bu::size Bu::HttpGet::getBlockSize() const | 117 | Bu::size Bu::HttpGet::getBlockSize() const |
118 | { | 118 | { |
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | Bu::String Bu::HttpGet::getLocation() const | 122 | Bu::String Bu::HttpGet::getLocation() const |
123 | { | 123 | { |
124 | return uSrc.getUrl(); | 124 | return uSrc.getUrl(); |
125 | } | 125 | } |
126 | 126 | ||
diff --git a/src/experimental/httpget.h b/src/experimental/httpget.h index e8092e5..21e69d6 100644 --- a/src/experimental/httpget.h +++ b/src/experimental/httpget.h | |||
@@ -16,51 +16,51 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class HttpGet : public Bu::Stream | 19 | class HttpGet : public Bu::Stream |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod="GET" ); | 22 | HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod="GET" ); |
23 | virtual ~HttpGet(); | 23 | virtual ~HttpGet(); |
24 | 24 | ||
25 | void get(); | 25 | void get(); |
26 | 26 | ||
27 | // From Bu::Stream | 27 | // From Bu::Stream |
28 | virtual void close(); | 28 | virtual void close(); |
29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
31 | using Stream::write; | 31 | using Stream::write; |
32 | 32 | ||
33 | virtual Bu::size tell(); | 33 | virtual Bu::size tell(); |
34 | virtual void seek( Bu::size offset ); | 34 | virtual void seek( Bu::size offset ); |
35 | virtual void setPos( Bu::size pos ); | 35 | virtual void setPos( Bu::size pos ); |
36 | virtual void setPosEnd( Bu::size pos ); | 36 | virtual void setPosEnd( Bu::size pos ); |
37 | virtual bool isEos(); | 37 | virtual bool isEos(); |
38 | virtual bool isOpen(); | 38 | virtual bool isOpen(); |
39 | 39 | ||
40 | virtual void flush(); | 40 | virtual void flush(); |
41 | 41 | ||
42 | virtual bool canRead(); | 42 | virtual bool canRead(); |
43 | virtual bool canWrite(); | 43 | virtual bool canWrite(); |
44 | 44 | ||
45 | virtual bool isReadable(); | 45 | virtual bool isReadable(); |
46 | virtual bool isWritable(); | 46 | virtual bool isWritable(); |
47 | virtual bool isSeekable(); | 47 | virtual bool isSeekable(); |
48 | 48 | ||
49 | virtual bool isBlocking(); | 49 | virtual bool isBlocking(); |
50 | virtual void setBlocking( bool bBlocking=true ); | 50 | virtual void setBlocking( bool bBlocking=true ); |
51 | 51 | ||
52 | virtual size getSize() const; | 52 | virtual size getSize() const; |
53 | virtual size getBlockSize() const; | 53 | virtual size getBlockSize() const; |
54 | virtual Bu::String getLocation() const; | 54 | virtual Bu::String getLocation() const; |
55 | 55 | ||
56 | private: | 56 | private: |
57 | Bu::Url uSrc; | 57 | Bu::Url uSrc; |
58 | Bu::String sMethod; | 58 | Bu::String sMethod; |
59 | Bu::TcpSocket sSrv; | 59 | Bu::TcpSocket sSrv; |
60 | typedef Bu::Hash<Bu::String,Bu::String> MimeHash; | 60 | typedef Bu::Hash<Bu::String,Bu::String> MimeHash; |
61 | MimeHash hMimeIn; | 61 | MimeHash hMimeIn; |
62 | MimeHash hMimeOut; | 62 | MimeHash hMimeOut; |
63 | }; | 63 | }; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | #endif | 66 | #endif |
diff --git a/src/experimental/lexer.cpp b/src/experimental/lexer.cpp index 48ee017..ae95d09 100644 --- a/src/experimental/lexer.cpp +++ b/src/experimental/lexer.cpp | |||
@@ -18,23 +18,23 @@ Bu::Lexer::~Lexer() | |||
18 | } | 18 | } |
19 | 19 | ||
20 | Bu::Lexer::Token::Token() : | 20 | Bu::Lexer::Token::Token() : |
21 | iToken( -1 ) | 21 | iToken( -1 ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::Lexer::Token::Token( Bu::Lexer::TokenType iToken ) : | 25 | Bu::Lexer::Token::Token( Bu::Lexer::TokenType iToken ) : |
26 | iToken( iToken ) | 26 | iToken( iToken ) |
27 | { | 27 | { |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::String Bu::Lexer::tokenToString( const Bu::Lexer::Token &t ) | 30 | Bu::String Bu::Lexer::tokenToString( const Bu::Lexer::Token &t ) |
31 | { | 31 | { |
32 | Bu::MemBuf mb; | 32 | Bu::MemBuf mb; |
33 | Bu::Formatter f( mb ); | 33 | Bu::Formatter f( mb ); |
34 | f << "<" << t.iToken << ">"; | 34 | f << "<" << t.iToken << ">"; |
35 | if( t.vExtra.isSet() ) | 35 | if( t.vExtra.isSet() ) |
36 | f << " (" << t.vExtra << ")"; | 36 | f << " (" << t.vExtra << ")"; |
37 | 37 | ||
38 | return mb.getString(); | 38 | return mb.getString(); |
39 | } | 39 | } |
40 | 40 | ||
diff --git a/src/experimental/lexer.h b/src/experimental/lexer.h index 69f4106..273f3cf 100644 --- a/src/experimental/lexer.h +++ b/src/experimental/lexer.h | |||
@@ -12,47 +12,47 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class Stream; | 15 | class Stream; |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * The base class for creating a lexical analyzer. This is designed to work | 18 | * The base class for creating a lexical analyzer. This is designed to work |
19 | * in tandem with the Bu::Parser class, which uses this to tokenize textual | 19 | * in tandem with the Bu::Parser class, which uses this to tokenize textual |
20 | * input. It can be used by just about anything that cares about tokens | 20 | * input. It can be used by just about anything that cares about tokens |
21 | * more than raw input, though. | 21 | * more than raw input, though. |
22 | */ | 22 | */ |
23 | class Lexer | 23 | class Lexer |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | Lexer(); | 26 | Lexer(); |
27 | virtual ~Lexer(); | 27 | virtual ~Lexer(); |
28 | 28 | ||
29 | typedef int TokenType; | 29 | typedef int TokenType; |
30 | 30 | ||
31 | class Token | 31 | class Token |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | Token(); | 34 | Token(); |
35 | Token( TokenType iToken ); | 35 | Token( TokenType iToken ); |
36 | 36 | ||
37 | template<class t> | 37 | template<class t> |
38 | Token( TokenType iToken, const t &v ) : | 38 | Token( TokenType iToken, const t &v ) : |
39 | iToken( iToken )//, | 39 | iToken( iToken )//, |
40 | // vExtra( v ) | 40 | // vExtra( v ) |
41 | { | 41 | { |
42 | vExtra = v; | 42 | vExtra = v; |
43 | } | 43 | } |
44 | TokenType iToken; | 44 | TokenType iToken; |
45 | Bu::Variant vExtra; | 45 | Bu::Variant vExtra; |
46 | int iStartCol; | 46 | int iStartCol; |
47 | int iStartRow; | 47 | int iStartRow; |
48 | int iEndCol; | 48 | int iEndCol; |
49 | int iEndRow; | 49 | int iEndRow; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | virtual Token *nextToken()=0; | 52 | virtual Token *nextToken()=0; |
53 | 53 | ||
54 | virtual Bu::String tokenToString( const Token &t ); | 54 | virtual Bu::String tokenToString( const Token &t ); |
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | #endif | 58 | #endif |
diff --git a/src/experimental/parser.cpp b/src/experimental/parser.cpp index 9f10256..5d0d7eb 100644 --- a/src/experimental/parser.cpp +++ b/src/experimental/parser.cpp | |||
@@ -21,231 +21,231 @@ Bu::Parser::~Parser() | |||
21 | 21 | ||
22 | void Bu::Parser::pushLexer( Lexer *pLex ) | 22 | void Bu::Parser::pushLexer( Lexer *pLex ) |
23 | { | 23 | { |
24 | sLexer.push( pLex ); | 24 | sLexer.push( pLex ); |
25 | } | 25 | } |
26 | 26 | ||
27 | void Bu::Parser::popLexer() | 27 | void Bu::Parser::popLexer() |
28 | { | 28 | { |
29 | delete sLexer.peekPop(); | 29 | delete sLexer.peekPop(); |
30 | } | 30 | } |
31 | 31 | ||
32 | Lexer::Token *Bu::Parser::popToken() | 32 | Lexer::Token *Bu::Parser::popToken() |
33 | { | 33 | { |
34 | return sToken.peekPop(); | 34 | return sToken.peekPop(); |
35 | } | 35 | } |
36 | 36 | ||
37 | void Bu::Parser::pushToken( Lexer::Token *pTok ) | 37 | void Bu::Parser::pushToken( Lexer::Token *pTok ) |
38 | { | 38 | { |
39 | sToken.push( pTok ); | 39 | sToken.push( pTok ); |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::Parser::parse() | 42 | void Bu::Parser::parse() |
43 | { | 43 | { |
44 | int iCurNt = iRootNonTerminal; | 44 | int iCurNt = iRootNonTerminal; |
45 | Lexer::Token *ptCur = sLexer.peek()->nextToken(); | 45 | Lexer::Token *ptCur = sLexer.peek()->nextToken(); |
46 | sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | 46 | sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; |
47 | selectProduction( iCurNt, ptCur ); | 47 | selectProduction( iCurNt, ptCur ); |
48 | 48 | ||
49 | while( !sState.isEmpty() ) | 49 | while( !sState.isEmpty() ) |
50 | { | 50 | { |
51 | switch( (*sState.peek()).eType ) | 51 | switch( (*sState.peek()).eType ) |
52 | { | 52 | { |
53 | case State::typeTerminal: | 53 | case State::typeTerminal: |
54 | sio << "terminal: " << ptCur->iToken << " == " | 54 | sio << "terminal: " << ptCur->iToken << " == " |
55 | << (*sState.peek()).iIndex << sio.nl; | 55 | << (*sState.peek()).iIndex << sio.nl; |
56 | if( ptCur->iToken == (*sState.peek()).iIndex ) | 56 | if( ptCur->iToken == (*sState.peek()).iIndex ) |
57 | { | 57 | { |
58 | advanceState(); | 58 | advanceState(); |
59 | delete ptCur; | 59 | delete ptCur; |
60 | ptCur = sLexer.peek()->nextToken(); | 60 | ptCur = sLexer.peek()->nextToken(); |
61 | sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | 61 | sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; |
62 | } | 62 | } |
63 | else | 63 | else |
64 | { | 64 | { |
65 | throw Bu::ExceptionBase("Error parsing code."); | 65 | throw Bu::ExceptionBase("Error parsing code."); |
66 | } | 66 | } |
67 | break; | 67 | break; |
68 | 68 | ||
69 | case State::typeTerminalPush: | 69 | case State::typeTerminalPush: |
70 | sio << "terminalpush: " << ptCur->iToken << " == " | 70 | sio << "terminalpush: " << ptCur->iToken << " == " |
71 | << (*sState.peek()).iIndex << sio.nl; | 71 | << (*sState.peek()).iIndex << sio.nl; |
72 | if( ptCur->iToken == (*sState.peek()).iIndex ) | 72 | if( ptCur->iToken == (*sState.peek()).iIndex ) |
73 | { | 73 | { |
74 | advanceState(); | 74 | advanceState(); |
75 | sToken.push( ptCur ); | 75 | sToken.push( ptCur ); |
76 | 76 | ||
77 | ptCur = sLexer.peek()->nextToken(); | 77 | ptCur = sLexer.peek()->nextToken(); |
78 | sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | 78 | sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; |
79 | } | 79 | } |
80 | else | 80 | else |
81 | { | 81 | { |
82 | throw Bu::ExceptionBase("Error parsing code."); | 82 | throw Bu::ExceptionBase("Error parsing code."); |
83 | } | 83 | } |
84 | break; | 84 | break; |
85 | 85 | ||
86 | case State::typeNonTerminal: | 86 | case State::typeNonTerminal: |
87 | sio << "nonterminal: " << ptCur->iToken << " --> " | 87 | sio << "nonterminal: " << ptCur->iToken << " --> " |
88 | << (*sState.peek()).iIndex << sio.nl; | 88 | << (*sState.peek()).iIndex << sio.nl; |
89 | { | 89 | { |
90 | int iNt = (*sState.peek()).iIndex; | 90 | int iNt = (*sState.peek()).iIndex; |
91 | sio << "Current state: " << *sState.peek() << sio.nl; | 91 | sio << "Current state: " << *sState.peek() << sio.nl; |
92 | if( !selectProduction( iNt, ptCur ) ) | 92 | if( !selectProduction( iNt, ptCur ) ) |
93 | { | 93 | { |
94 | throw Bu::ExceptionBase("Error parsing code."); | 94 | throw Bu::ExceptionBase("Error parsing code."); |
95 | } | 95 | } |
96 | } | 96 | } |
97 | break; | 97 | break; |
98 | 98 | ||
99 | case State::typeReduction: | 99 | case State::typeReduction: |
100 | sio << "reduction" << sio.nl; | 100 | sio << "reduction" << sio.nl; |
101 | aReduction[(*sState.peek()).iIndex]( *this ); | 101 | aReduction[(*sState.peek()).iIndex]( *this ); |
102 | advanceState(); | 102 | advanceState(); |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | } | 105 | } |
106 | } | 106 | } |
107 | 107 | ||
108 | bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) | 108 | bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) |
109 | { | 109 | { |
110 | NonTerminal &nt = aNonTerminal[iNt]; | 110 | NonTerminal &nt = aNonTerminal[iNt]; |
111 | int j = 0; | 111 | int j = 0; |
112 | for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); | 112 | for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); |
113 | i; i++,j++ ) | 113 | i; i++,j++ ) |
114 | { | 114 | { |
115 | if( (*i).isEmpty() ) | 115 | if( (*i).isEmpty() ) |
116 | continue; | 116 | continue; |
117 | sio << "-->(Attempting production " << iNt << ":" << j << ": " | 117 | sio << "-->(Attempting production " << iNt << ":" << j << ": " |
118 | << (*i).first() << ")" << sio.nl; | 118 | << (*i).first() << ")" << sio.nl; |
119 | if( (*i).first().eType == State::typeTerminal || | 119 | if( (*i).first().eType == State::typeTerminal || |
120 | (*i).first().eType == State::typeTerminalPush ) | 120 | (*i).first().eType == State::typeTerminalPush ) |
121 | { | 121 | { |
122 | if( (*i).first().iIndex == ptCur->iToken ) | 122 | if( (*i).first().iIndex == ptCur->iToken ) |
123 | { | 123 | { |
124 | sState.push( (*i).begin() ); | 124 | sState.push( (*i).begin() ); |
125 | sio.incIndent(); | 125 | sio.incIndent(); |
126 | sio << "Pushing production " << j << " from nt " << iNt | 126 | sio << "Pushing production " << j << " from nt " << iNt |
127 | << sio.nl; | 127 | << sio.nl; |
128 | return true; | 128 | return true; |
129 | } | 129 | } |
130 | } | 130 | } |
131 | else if( (*i).first().eType == State::typeNonTerminal ) | 131 | else if( (*i).first().eType == State::typeNonTerminal ) |
132 | { | 132 | { |
133 | sState.push( (*i).begin() ); | 133 | sState.push( (*i).begin() ); |
134 | sio.incIndent(); | 134 | sio.incIndent(); |
135 | sio << "Pushing production " << j << " from nt " << iNt | 135 | sio << "Pushing production " << j << " from nt " << iNt |
136 | << " as test." << sio.nl; | 136 | << " as test." << sio.nl; |
137 | if( !selectProduction( (*i).first().iIndex, ptCur ) ) | 137 | if( !selectProduction( (*i).first().iIndex, ptCur ) ) |
138 | { | 138 | { |
139 | sio.decIndent(); | 139 | sio.decIndent(); |
140 | sState.pop(); | 140 | sState.pop(); |
141 | sio << "Production " << j << " from nt " << iNt | 141 | sio << "Production " << j << " from nt " << iNt |
142 | << " didn't work out." << sio.nl; | 142 | << " didn't work out." << sio.nl; |
143 | } | 143 | } |
144 | else | 144 | else |
145 | { | 145 | { |
146 | return true; | 146 | return true; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | if( nt.bCanSkip ) | 150 | if( nt.bCanSkip ) |
151 | { | 151 | { |
152 | sio << "Nothing matches, skipping non-terminal." << sio.nl; | 152 | sio << "Nothing matches, skipping non-terminal." << sio.nl; |
153 | advanceState(); | 153 | advanceState(); |
154 | return true; | 154 | return true; |
155 | } | 155 | } |
156 | sio << "-->(Found nothing)" << sio.nl; | 156 | sio << "-->(Found nothing)" << sio.nl; |
157 | return false; | 157 | return false; |
158 | } | 158 | } |
159 | 159 | ||
160 | void Bu::Parser::advanceState() | 160 | void Bu::Parser::advanceState() |
161 | { | 161 | { |
162 | if( sState.isEmpty() ) | 162 | if( sState.isEmpty() ) |
163 | return; | 163 | return; |
164 | 164 | ||
165 | sState.peek()++; | 165 | sState.peek()++; |
166 | if( !sState.peek() ) | 166 | if( !sState.peek() ) |
167 | { | 167 | { |
168 | sio.decIndent(); | 168 | sio.decIndent(); |
169 | sState.pop(); | 169 | sState.pop(); |
170 | sio << "State advanced, End of production." << sio.nl; | 170 | sio << "State advanced, End of production." << sio.nl; |
171 | advanceState(); | 171 | advanceState(); |
172 | return; | 172 | return; |
173 | } | 173 | } |
174 | sio << "State advanced, now: " << *(sState.peek()) << sio.nl; | 174 | sio << "State advanced, now: " << *(sState.peek()) << sio.nl; |
175 | } | 175 | } |
176 | 176 | ||
177 | void Bu::Parser::setRootNonTerminal( int iRoot ) | 177 | void Bu::Parser::setRootNonTerminal( int iRoot ) |
178 | { | 178 | { |
179 | iRootNonTerminal = iRoot; | 179 | iRootNonTerminal = iRoot; |
180 | } | 180 | } |
181 | 181 | ||
182 | void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) | 182 | void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) |
183 | { | 183 | { |
184 | setRootNonTerminal( hNonTerminalName.get( sRoot ) ); | 184 | setRootNonTerminal( hNonTerminalName.get( sRoot ) ); |
185 | } | 185 | } |
186 | 186 | ||
187 | int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) | 187 | int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) |
188 | { | 188 | { |
189 | int iId = aNonTerminal.getSize(); | 189 | int iId = aNonTerminal.getSize(); |
190 | aNonTerminal.append( nt ); | 190 | aNonTerminal.append( nt ); |
191 | hNonTerminalName.insert( sName, iId ); | 191 | hNonTerminalName.insert( sName, iId ); |
192 | sio << "nt '" << sName << "' = " << iId << sio.nl; | 192 | sio << "nt '" << sName << "' = " << iId << sio.nl; |
193 | return iId; | 193 | return iId; |
194 | } | 194 | } |
195 | 195 | ||
196 | int Bu::Parser::addNonTerminal( const Bu::String &sName ) | 196 | int Bu::Parser::addNonTerminal( const Bu::String &sName ) |
197 | { | 197 | { |
198 | int iId = aNonTerminal.getSize(); | 198 | int iId = aNonTerminal.getSize(); |
199 | aNonTerminal.append( NonTerminal() ); | 199 | aNonTerminal.append( NonTerminal() ); |
200 | hNonTerminalName.insert( sName, iId ); | 200 | hNonTerminalName.insert( sName, iId ); |
201 | sio << "nt '" << sName << "' = " << iId << sio.nl; | 201 | sio << "nt '" << sName << "' = " << iId << sio.nl; |
202 | return iId; | 202 | return iId; |
203 | } | 203 | } |
204 | 204 | ||
205 | void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) | 205 | void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) |
206 | { | 206 | { |
207 | aNonTerminal[hNonTerminalName.get(sName)] = nt; | 207 | aNonTerminal[hNonTerminalName.get(sName)] = nt; |
208 | } | 208 | } |
209 | 209 | ||
210 | int Bu::Parser::getNonTerminalId( const Bu::String &sName ) | 210 | int Bu::Parser::getNonTerminalId( const Bu::String &sName ) |
211 | { | 211 | { |
212 | return hNonTerminalName.get( sName ); | 212 | return hNonTerminalName.get( sName ); |
213 | } | 213 | } |
214 | 214 | ||
215 | bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) | 215 | bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) |
216 | { | 216 | { |
217 | return hNonTerminalName.has( sName ); | 217 | return hNonTerminalName.has( sName ); |
218 | } | 218 | } |
219 | 219 | ||
220 | int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) | 220 | int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) |
221 | { | 221 | { |
222 | int iId = aReduction.getSize(); | 222 | int iId = aReduction.getSize(); |
223 | aReduction.append( r ); | 223 | aReduction.append( r ); |
224 | hReductionName.insert( sName, iId ); | 224 | hReductionName.insert( sName, iId ); |
225 | return iId; | 225 | return iId; |
226 | } | 226 | } |
227 | 227 | ||
228 | int Bu::Parser::addReduction( const Bu::String &sName ) | 228 | int Bu::Parser::addReduction( const Bu::String &sName ) |
229 | { | 229 | { |
230 | int iId = aReduction.getSize(); | 230 | int iId = aReduction.getSize(); |
231 | aReduction.append( Reduction() ); | 231 | aReduction.append( Reduction() ); |
232 | hReductionName.insert( sName, iId ); | 232 | hReductionName.insert( sName, iId ); |
233 | return iId; | 233 | return iId; |
234 | } | 234 | } |
235 | 235 | ||
236 | void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) | 236 | void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) |
237 | { | 237 | { |
238 | aReduction[hReductionName.get(sName)] = r; | 238 | aReduction[hReductionName.get(sName)] = r; |
239 | } | 239 | } |
240 | 240 | ||
241 | int Bu::Parser::getReductionId( const Bu::String &sName ) | 241 | int Bu::Parser::getReductionId( const Bu::String &sName ) |
242 | { | 242 | { |
243 | return hReductionName.get( sName ); | 243 | return hReductionName.get( sName ); |
244 | } | 244 | } |
245 | 245 | ||
246 | bool Bu::Parser::hasReduction( const Bu::String &sName ) | 246 | bool Bu::Parser::hasReduction( const Bu::String &sName ) |
247 | { | 247 | { |
248 | return hReductionName.has( sName ); | 248 | return hReductionName.has( sName ); |
249 | } | 249 | } |
250 | 250 | ||
251 | // | 251 | // |
@@ -253,8 +253,8 @@ bool Bu::Parser::hasReduction( const Bu::String &sName ) | |||
253 | // | 253 | // |
254 | 254 | ||
255 | Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : | 255 | Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : |
256 | eType( eType ), | 256 | eType( eType ), |
257 | iIndex( iIndex ) | 257 | iIndex( iIndex ) |
258 | { | 258 | { |
259 | } | 259 | } |
260 | 260 | ||
@@ -267,7 +267,7 @@ Bu::Parser::State::~State() | |||
267 | // | 267 | // |
268 | 268 | ||
269 | Bu::Parser::NonTerminal::NonTerminal() : | 269 | Bu::Parser::NonTerminal::NonTerminal() : |
270 | bCanSkip( false ) | 270 | bCanSkip( false ) |
271 | { | 271 | { |
272 | } | 272 | } |
273 | 273 | ||
@@ -277,35 +277,35 @@ Bu::Parser::NonTerminal::~NonTerminal() | |||
277 | 277 | ||
278 | void Bu::Parser::NonTerminal::addProduction( Production p ) | 278 | void Bu::Parser::NonTerminal::addProduction( Production p ) |
279 | { | 279 | { |
280 | lProduction.append( p ); | 280 | lProduction.append( p ); |
281 | } | 281 | } |
282 | 282 | ||
283 | void Bu::Parser::NonTerminal::setCanSkip() | 283 | void Bu::Parser::NonTerminal::setCanSkip() |
284 | { | 284 | { |
285 | bCanSkip = true; | 285 | bCanSkip = true; |
286 | } | 286 | } |
287 | 287 | ||
288 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) | 288 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) |
289 | { | 289 | { |
290 | switch( t ) | 290 | switch( t ) |
291 | { | 291 | { |
292 | case Bu::Parser::State::typeTerminal: | 292 | case Bu::Parser::State::typeTerminal: |
293 | return f << "typeTerminal"; | 293 | return f << "typeTerminal"; |
294 | 294 | ||
295 | case Bu::Parser::State::typeTerminalPush: | 295 | case Bu::Parser::State::typeTerminalPush: |
296 | return f << "typeTerminalPush"; | 296 | return f << "typeTerminalPush"; |
297 | 297 | ||
298 | case Bu::Parser::State::typeNonTerminal: | 298 | case Bu::Parser::State::typeNonTerminal: |
299 | return f << "typeNonTerminal"; | 299 | return f << "typeNonTerminal"; |
300 | 300 | ||
301 | case Bu::Parser::State::typeReduction: | 301 | case Bu::Parser::State::typeReduction: |
302 | return f << "typeReduction"; | 302 | return f << "typeReduction"; |
303 | } | 303 | } |
304 | return f << "***error***"; | 304 | return f << "***error***"; |
305 | } | 305 | } |
306 | 306 | ||
307 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) | 307 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) |
308 | { | 308 | { |
309 | return f << "{" << s.eType << ": " << s.iIndex << "}"; | 309 | return f << "{" << s.eType << ": " << s.iIndex << "}"; |
310 | } | 310 | } |
311 | 311 | ||
diff --git a/src/experimental/parser.h b/src/experimental/parser.h index 953202d..50b6afb 100644 --- a/src/experimental/parser.h +++ b/src/experimental/parser.h | |||
@@ -18,115 +18,115 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | /** | 21 | /** |
22 | * The base framework for a LR(1) grammar parser. Provided a proper set of | 22 | * The base framework for a LR(1) grammar parser. Provided a proper set of |
23 | * ParserStates this will prase any input the lexer can provide. | 23 | * ParserStates this will prase any input the lexer can provide. |
24 | */ | 24 | */ |
25 | class Parser | 25 | class Parser |
26 | { | 26 | { |
27 | public: | 27 | public: |
28 | Parser(); | 28 | Parser(); |
29 | virtual ~Parser(); | 29 | virtual ~Parser(); |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * When a Lexer is pushed onto the stack it becomes the source for | 32 | * When a Lexer is pushed onto the stack it becomes the source for |
33 | * future tokens read by the parser until it is popped off the stack. | 33 | * future tokens read by the parser until it is popped off the stack. |
34 | * The Parser takes ownership of every Lexer pushed onto the stack, | 34 | * The Parser takes ownership of every Lexer pushed onto the stack, |
35 | * and will delete it when it is popped off the stack. | 35 | * and will delete it when it is popped off the stack. |
36 | */ | 36 | */ |
37 | void pushLexer( Lexer *pLex ); | 37 | void pushLexer( Lexer *pLex ); |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * Pop a lexer off the stack, and delete it. | 40 | * Pop a lexer off the stack, and delete it. |
41 | */ | 41 | */ |
42 | void popLexer(); | 42 | void popLexer(); |
43 | 43 | ||
44 | Lexer::Token *popToken(); | 44 | Lexer::Token *popToken(); |
45 | void pushToken( Lexer::Token *pTok ); | 45 | void pushToken( Lexer::Token *pTok ); |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Execute a parse. | 48 | * Execute a parse. |
49 | */ | 49 | */ |
50 | void parse(); | 50 | void parse(); |
51 | 51 | ||
52 | void setRootNonTerminal( int iRoot ); | 52 | void setRootNonTerminal( int iRoot ); |
53 | void setRootNonTerminal( const Bu::String &sRoot ); | 53 | void setRootNonTerminal( const Bu::String &sRoot ); |
54 | 54 | ||
55 | typedef Bu::Signal1<void, Parser &> Reduction; | 55 | typedef Bu::Signal1<void, Parser &> Reduction; |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * Represents a possible state, either a terminal or non-terminal symbol | 58 | * Represents a possible state, either a terminal or non-terminal symbol |
59 | * in a Production. | 59 | * in a Production. |
60 | */ | 60 | */ |
61 | class State | 61 | class State |
62 | { | 62 | { |
63 | public: | 63 | public: |
64 | enum Type | 64 | enum Type |
65 | { | 65 | { |
66 | typeTerminal, | 66 | typeTerminal, |
67 | typeTerminalPush, | 67 | typeTerminalPush, |
68 | typeNonTerminal, | 68 | typeNonTerminal, |
69 | typeReduction | 69 | typeReduction |
70 | }; | 70 | }; |
71 | 71 | ||
72 | State( Type eType, int iIndex ); | 72 | State( Type eType, int iIndex ); |
73 | virtual ~State(); | 73 | virtual ~State(); |
74 | 74 | ||
75 | //private: | 75 | //private: |
76 | Type eType; | 76 | Type eType; |
77 | int iIndex; | 77 | int iIndex; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | typedef Bu::List<State> Production; | 80 | typedef Bu::List<State> Production; |
81 | 81 | ||
82 | class NonTerminal | 82 | class NonTerminal |
83 | { | 83 | { |
84 | public: | 84 | public: |
85 | NonTerminal(); | 85 | NonTerminal(); |
86 | virtual ~NonTerminal(); | 86 | virtual ~NonTerminal(); |
87 | 87 | ||
88 | void addProduction( Production p ); | 88 | void addProduction( Production p ); |
89 | void setCanSkip(); | 89 | void setCanSkip(); |
90 | 90 | ||
91 | // private: | 91 | // private: |
92 | typedef Bu::List<Production> ProductionList; | 92 | typedef Bu::List<Production> ProductionList; |
93 | ProductionList lProduction; | 93 | ProductionList lProduction; |
94 | bool bCanSkip; | 94 | bool bCanSkip; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | int addNonTerminal( const Bu::String &sName, NonTerminal &nt ); | 97 | int addNonTerminal( const Bu::String &sName, NonTerminal &nt ); |
98 | int addNonTerminal( const Bu::String &sName ); | 98 | int addNonTerminal( const Bu::String &sName ); |
99 | void setNonTerminal( const Bu::String &sName, NonTerminal &nt ); | 99 | void setNonTerminal( const Bu::String &sName, NonTerminal &nt ); |
100 | int getNonTerminalId( const Bu::String &sName ); | 100 | int getNonTerminalId( const Bu::String &sName ); |
101 | bool hasNonTerminal( const Bu::String &sName ); | 101 | bool hasNonTerminal( const Bu::String &sName ); |
102 | 102 | ||
103 | int addReduction( const Bu::String &sName, const Reduction &r ); | 103 | int addReduction( const Bu::String &sName, const Reduction &r ); |
104 | int addReduction( const Bu::String &sName ); | 104 | int addReduction( const Bu::String &sName ); |
105 | void setReduction( const Bu::String &sName, const Reduction &r ); | 105 | void setReduction( const Bu::String &sName, const Reduction &r ); |
106 | int getReductionId( const Bu::String &sName ); | 106 | int getReductionId( const Bu::String &sName ); |
107 | bool hasReduction( const Bu::String &sName ); | 107 | bool hasReduction( const Bu::String &sName ); |
108 | 108 | ||
109 | private: | 109 | private: |
110 | bool selectProduction( int iNt, Lexer::Token *ptCur ); | 110 | bool selectProduction( int iNt, Lexer::Token *ptCur ); |
111 | void advanceState(); | 111 | void advanceState(); |
112 | 112 | ||
113 | private: | 113 | private: |
114 | typedef Bu::List<Lexer *> LexerStack; | 114 | typedef Bu::List<Lexer *> LexerStack; |
115 | typedef Bu::List<Lexer::Token *> TokenStack; | 115 | typedef Bu::List<Lexer::Token *> TokenStack; |
116 | typedef Bu::List<Production::const_iterator> StateStack; | 116 | typedef Bu::List<Production::const_iterator> StateStack; |
117 | typedef Bu::Array<Reduction> ReductionArray; | 117 | typedef Bu::Array<Reduction> ReductionArray; |
118 | typedef Bu::Hash<Bu::String,int> NameIndexHash; | 118 | typedef Bu::Hash<Bu::String,int> NameIndexHash; |
119 | typedef Bu::Array<NonTerminal> NonTerminalArray; | 119 | typedef Bu::Array<NonTerminal> NonTerminalArray; |
120 | 120 | ||
121 | LexerStack sLexer; | 121 | LexerStack sLexer; |
122 | TokenStack sToken; | 122 | TokenStack sToken; |
123 | StateStack sState; | 123 | StateStack sState; |
124 | ReductionArray aReduction; | 124 | ReductionArray aReduction; |
125 | NameIndexHash hReductionName; | 125 | NameIndexHash hReductionName; |
126 | NonTerminalArray aNonTerminal; | 126 | NonTerminalArray aNonTerminal; |
127 | NameIndexHash hNonTerminalName; | 127 | NameIndexHash hNonTerminalName; |
128 | int iRootNonTerminal; | 128 | int iRootNonTerminal; |
129 | }; | 129 | }; |
130 | Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ); | 130 | Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ); |
131 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::Parser::State &s ); | 131 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::Parser::State &s ); |
132 | }; | 132 | }; |
diff --git a/src/experimental/regex.cpp b/src/experimental/regex.cpp index de24935..dbe0e85 100644 --- a/src/experimental/regex.cpp +++ b/src/experimental/regex.cpp | |||
@@ -13,83 +13,83 @@ | |||
13 | #define aSubStr ((regmatch_t *)paSubStr) | 13 | #define aSubStr ((regmatch_t *)paSubStr) |
14 | 14 | ||
15 | Bu::RegEx::RegEx() : | 15 | Bu::RegEx::RegEx() : |
16 | pRegEx( NULL ), | 16 | pRegEx( NULL ), |
17 | bCompiled( false ), | 17 | bCompiled( false ), |
18 | paSubStr( NULL ) | 18 | paSubStr( NULL ) |
19 | { | 19 | { |
20 | } | 20 | } |
21 | 21 | ||
22 | Bu::RegEx::RegEx( const Bu::String &sSrc ) : | 22 | Bu::RegEx::RegEx( const Bu::String &sSrc ) : |
23 | pRegEx( NULL ), | 23 | pRegEx( NULL ), |
24 | bCompiled( false ), | 24 | bCompiled( false ), |
25 | paSubStr( NULL ) | 25 | paSubStr( NULL ) |
26 | { | 26 | { |
27 | compile( sSrc ); | 27 | compile( sSrc ); |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::RegEx::~RegEx() | 30 | Bu::RegEx::~RegEx() |
31 | { | 31 | { |
32 | if( bCompiled ) | 32 | if( bCompiled ) |
33 | { | 33 | { |
34 | regfree( re ); | 34 | regfree( re ); |
35 | delete re; | 35 | delete re; |
36 | delete[] aSubStr; | 36 | delete[] aSubStr; |
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::RegEx::compile( const Bu::String &sSrc ) | 40 | void Bu::RegEx::compile( const Bu::String &sSrc ) |
41 | { | 41 | { |
42 | if( bCompiled ) | 42 | if( bCompiled ) |
43 | { | 43 | { |
44 | regfree( re ); | 44 | regfree( re ); |
45 | delete re; | 45 | delete re; |
46 | delete[] aSubStr; | 46 | delete[] aSubStr; |
47 | bCompiled = false; | 47 | bCompiled = false; |
48 | } | 48 | } |
49 | pRegEx = (void *)(new regex_t); | 49 | pRegEx = (void *)(new regex_t); |
50 | 50 | ||
51 | int nErr = regcomp( re, sSrc.getStr(), REG_EXTENDED|REG_NEWLINE ); | 51 | int nErr = regcomp( re, sSrc.getStr(), REG_EXTENDED|REG_NEWLINE ); |
52 | if( nErr ) | 52 | if( nErr ) |
53 | { | 53 | { |
54 | size_t length = regerror( nErr, re, NULL, 0 ); | 54 | size_t length = regerror( nErr, re, NULL, 0 ); |
55 | char *buffer = new char[length]; | 55 | char *buffer = new char[length]; |
56 | (void) regerror( nErr, re, buffer, length ); | 56 | (void) regerror( nErr, re, buffer, length ); |
57 | Bu::String s( buffer ); | 57 | Bu::String s( buffer ); |
58 | delete[] buffer; | 58 | delete[] buffer; |
59 | throw "???"; // BuildException( s.getStr() ); | 59 | throw "???"; // BuildException( s.getStr() ); |
60 | } | 60 | } |
61 | bCompiled = true; | 61 | bCompiled = true; |
62 | this->sSrc = sSrc; | 62 | this->sSrc = sSrc; |
63 | 63 | ||
64 | nSubStr = re->re_nsub+1; | 64 | nSubStr = re->re_nsub+1; |
65 | paSubStr = (void *)(new regmatch_t[nSubStr]); | 65 | paSubStr = (void *)(new regmatch_t[nSubStr]); |
66 | } | 66 | } |
67 | 67 | ||
68 | int Bu::RegEx::getNumSubStrings() | 68 | int Bu::RegEx::getNumSubStrings() |
69 | { | 69 | { |
70 | return nSubStr; | 70 | return nSubStr; |
71 | } | 71 | } |
72 | 72 | ||
73 | bool Bu::RegEx::execute( const Bu::String &sSrc ) | 73 | bool Bu::RegEx::execute( const Bu::String &sSrc ) |
74 | { | 74 | { |
75 | sTest = sSrc; | 75 | sTest = sSrc; |
76 | if( regexec( re, sSrc.getStr(), nSubStr, aSubStr, 0 ) ) | 76 | if( regexec( re, sSrc.getStr(), nSubStr, aSubStr, 0 ) ) |
77 | return false; | 77 | return false; |
78 | return true; | 78 | return true; |
79 | } | 79 | } |
80 | 80 | ||
81 | void Bu::RegEx::getSubStringRange( int nIndex, int &iStart, int &iEnd ) | 81 | void Bu::RegEx::getSubStringRange( int nIndex, int &iStart, int &iEnd ) |
82 | { | 82 | { |
83 | iStart = aSubStr[nIndex].rm_so; | 83 | iStart = aSubStr[nIndex].rm_so; |
84 | iEnd = aSubStr[nIndex].rm_eo; | 84 | iEnd = aSubStr[nIndex].rm_eo; |
85 | } | 85 | } |
86 | 86 | ||
87 | Bu::String Bu::RegEx::getSubString( int nIndex ) | 87 | Bu::String Bu::RegEx::getSubString( int nIndex ) |
88 | { | 88 | { |
89 | // regmatch_t *Subs = aSubStr; | 89 | // regmatch_t *Subs = aSubStr; |
90 | return Bu::String( | 90 | return Bu::String( |
91 | sTest.getStr()+aSubStr[nIndex].rm_so, | 91 | sTest.getStr()+aSubStr[nIndex].rm_so, |
92 | aSubStr[nIndex].rm_eo - aSubStr[nIndex].rm_so | 92 | aSubStr[nIndex].rm_eo - aSubStr[nIndex].rm_so |
93 | ); | 93 | ); |
94 | } | 94 | } |
95 | 95 | ||
diff --git a/src/experimental/regex.h b/src/experimental/regex.h index c83ebe8..e723450 100644 --- a/src/experimental/regex.h +++ b/src/experimental/regex.h | |||
@@ -14,31 +14,31 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class RegEx | 17 | class RegEx |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | RegEx(); | 20 | RegEx(); |
21 | RegEx( const Bu::String &sSrc ); | 21 | RegEx( const Bu::String &sSrc ); |
22 | virtual ~RegEx(); | 22 | virtual ~RegEx(); |
23 | 23 | ||
24 | void compile( const Bu::String &sSrc ); | 24 | void compile( const Bu::String &sSrc ); |
25 | int getNumSubStrings(); | 25 | int getNumSubStrings(); |
26 | bool execute( const Bu::String &sSrc ); | 26 | bool execute( const Bu::String &sSrc ); |
27 | void getSubStringRange( int nIndex, int &iStart, int &iEnd ); | 27 | void getSubStringRange( int nIndex, int &iStart, int &iEnd ); |
28 | Bu::String getSubString( int nIndex ); | 28 | Bu::String getSubString( int nIndex ); |
29 | const Bu::String &getSource() | 29 | const Bu::String &getSource() |
30 | { | 30 | { |
31 | return sSrc; | 31 | return sSrc; |
32 | } | 32 | } |
33 | 33 | ||
34 | private: | 34 | private: |
35 | Bu::String sSrc; | 35 | Bu::String sSrc; |
36 | Bu::String sTest; | 36 | Bu::String sTest; |
37 | void *pRegEx; | 37 | void *pRegEx; |
38 | bool bCompiled; | 38 | bool bCompiled; |
39 | int nSubStr; | 39 | int nSubStr; |
40 | void *paSubStr; | 40 | void *paSubStr; |
41 | }; | 41 | }; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | #endif | 44 | #endif |
diff --git a/src/experimental/regexengine.h b/src/experimental/regexengine.h index ec181c1..133d418 100644 --- a/src/experimental/regexengine.h +++ b/src/experimental/regexengine.h | |||
@@ -7,136 +7,136 @@ | |||
7 | 7 | ||
8 | namespace Bu | 8 | namespace Bu |
9 | { | 9 | { |
10 | template<typename chr> class RegExEngine; | 10 | template<typename chr> class RegExEngine; |
11 | 11 | ||
12 | template<typename chr> | 12 | template<typename chr> |
13 | class RegExEngineCore | 13 | class RegExEngineCore |
14 | { | 14 | { |
15 | friend class RegExEngine<chr>; | 15 | friend class RegExEngine<chr>; |
16 | friend class SharedCore<RegExEngine<chr>, RegExEngineCore<chr> >; | 16 | friend class SharedCore<RegExEngine<chr>, RegExEngineCore<chr> >; |
17 | private: | 17 | private: |
18 | RegExEngineCore() | 18 | RegExEngineCore() |
19 | { | 19 | { |
20 | } | 20 | } |
21 | 21 | ||
22 | virtual ~RegExEngineCore() | 22 | virtual ~RegExEngineCore() |
23 | { | 23 | { |
24 | } | 24 | } |
25 | 25 | ||
26 | class Range | 26 | class Range |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | Range( chr cLower, chr cUpper, int iTrgState ) : | 29 | Range( chr cLower, chr cUpper, int iTrgState ) : |
30 | cLower( cLower ), cUpper( cUpper ), iTrgState( iTrgState ) | 30 | cLower( cLower ), cUpper( cUpper ), iTrgState( iTrgState ) |
31 | { | 31 | { |
32 | } | 32 | } |
33 | 33 | ||
34 | chr cLower; | 34 | chr cLower; |
35 | chr cUpper; | 35 | chr cUpper; |
36 | int iTrgState; | 36 | int iTrgState; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | class State | 39 | class State |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | Bu::Array<Range> aRange; | 42 | Bu::Array<Range> aRange; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | int addState() | 45 | int addState() |
46 | { | 46 | { |
47 | aState.append( State() ); | 47 | aState.append( State() ); |
48 | return aState.getSize()-1; | 48 | return aState.getSize()-1; |
49 | } | 49 | } |
50 | 50 | ||
51 | void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) | 51 | void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) |
52 | { | 52 | { |
53 | aState[iState].aRange.append( Range( cLower, cUpper, iTrgState ) ); | 53 | aState[iState].aRange.append( Range( cLower, cUpper, iTrgState ) ); |
54 | } | 54 | } |
55 | 55 | ||
56 | template<typename str> | 56 | template<typename str> |
57 | bool match( const str &sIn, int &iSize, int &iCompletion ) | 57 | bool match( const str &sIn, int &iSize, int &iCompletion ) |
58 | { | 58 | { |
59 | bool bMatch; | 59 | bool bMatch; |
60 | int iState = 0; | 60 | int iState = 0; |
61 | iSize = 0; | 61 | iSize = 0; |
62 | for( typename str::const_iterator i = sIn.begin(); i; i++ ) | 62 | for( typename str::const_iterator i = sIn.begin(); i; i++ ) |
63 | { | 63 | { |
64 | Bu::sio << "Finding char " << *i << " in state " << iState | 64 | Bu::sio << "Finding char " << *i << " in state " << iState |
65 | << ":" << Bu::sio.nl; | 65 | << ":" << Bu::sio.nl; |
66 | bMatch = false; | 66 | bMatch = false; |
67 | for( typename Bu::Array<Range>::iterator j = | 67 | for( typename Bu::Array<Range>::iterator j = |
68 | aState[iState].aRange.begin(); j; j++ ) | 68 | aState[iState].aRange.begin(); j; j++ ) |
69 | { | 69 | { |
70 | Bu::sio << " Testing range " << (*j).cLower << " - " << (*j).cUpper << Bu::sio.nl; | 70 | Bu::sio << " Testing range " << (*j).cLower << " - " << (*j).cUpper << Bu::sio.nl; |
71 | if( *i >= (*j).cLower && *i <= (*j).cUpper ) | 71 | if( *i >= (*j).cLower && *i <= (*j).cUpper ) |
72 | { | 72 | { |
73 | iState = (*j).iTrgState; | 73 | iState = (*j).iTrgState; |
74 | bMatch = true; | 74 | bMatch = true; |
75 | iSize++; | 75 | iSize++; |
76 | if( iState < 0 ) | 76 | if( iState < 0 ) |
77 | { | 77 | { |
78 | iCompletion = iState; | 78 | iCompletion = iState; |
79 | return true; | 79 | return true; |
80 | } | 80 | } |
81 | } | 81 | } |
82 | } | 82 | } |
83 | if( bMatch == false ) | 83 | if( bMatch == false ) |
84 | { | 84 | { |
85 | return false; | 85 | return false; |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | iCompletion = 0; | 89 | iCompletion = 0; |
90 | return true; | 90 | return true; |
91 | } | 91 | } |
92 | 92 | ||
93 | typedef Bu::Array<State> StateArray; | 93 | typedef Bu::Array<State> StateArray; |
94 | StateArray aState; | 94 | StateArray aState; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | template<typename chr> | 97 | template<typename chr> |
98 | class RegExEngine : public SharedCore<RegExEngine<chr>, | 98 | class RegExEngine : public SharedCore<RegExEngine<chr>, |
99 | RegExEngineCore<chr> > | 99 | RegExEngineCore<chr> > |
100 | { | 100 | { |
101 | private: | 101 | private: |
102 | typedef class RegExEngine<chr> MyType; | 102 | typedef class RegExEngine<chr> MyType; |
103 | typedef class RegExEngineCore<chr> Core; | 103 | typedef class RegExEngineCore<chr> Core; |
104 | typedef class Core::Range Range; | 104 | typedef class Core::Range Range; |
105 | typedef class Core::State State; | 105 | typedef class Core::State State; |
106 | 106 | ||
107 | protected: | 107 | protected: |
108 | using SharedCore<MyType, Core>::core; | 108 | using SharedCore<MyType, Core>::core; |
109 | using SharedCore<MyType, Core>::_hardCopy; | 109 | using SharedCore<MyType, Core>::_hardCopy; |
110 | using SharedCore<MyType, Core>::_resetCore; | 110 | using SharedCore<MyType, Core>::_resetCore; |
111 | using SharedCore<MyType, Core>::_allocateCore; | 111 | using SharedCore<MyType, Core>::_allocateCore; |
112 | 112 | ||
113 | public: | 113 | public: |
114 | RegExEngine() | 114 | RegExEngine() |
115 | { | 115 | { |
116 | } | 116 | } |
117 | 117 | ||
118 | virtual ~RegExEngine() | 118 | virtual ~RegExEngine() |
119 | { | 119 | { |
120 | } | 120 | } |
121 | 121 | ||
122 | int addState() | 122 | int addState() |
123 | { | 123 | { |
124 | return core->addState(); | 124 | return core->addState(); |
125 | } | 125 | } |
126 | 126 | ||
127 | void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) | 127 | void addCompletion( int iState, chr cLower, chr cUpper, int iTrgState ) |
128 | { | 128 | { |
129 | core->addCompletion( iState, cLower, cUpper, iTrgState ); | 129 | core->addCompletion( iState, cLower, cUpper, iTrgState ); |
130 | } | 130 | } |
131 | 131 | ||
132 | template<typename str> | 132 | template<typename str> |
133 | bool match( const str &sIn, int &iSize, int &iCompletion ) | 133 | bool match( const str &sIn, int &iSize, int &iCompletion ) |
134 | { | 134 | { |
135 | return core->match( sIn, iSize, iCompletion ); | 135 | return core->match( sIn, iSize, iCompletion ); |
136 | } | 136 | } |
137 | 137 | ||
138 | private: | 138 | private: |
139 | }; | 139 | }; |
140 | }; | 140 | }; |
141 | 141 | ||
142 | #endif | 142 | #endif |
diff --git a/src/experimental/xmlreader.cpp b/src/experimental/xmlreader.cpp index f11ac04..82f4684 100644 --- a/src/experimental/xmlreader.cpp +++ b/src/experimental/xmlreader.cpp | |||
@@ -11,13 +11,13 @@ | |||
11 | namespace Bu { subExceptionDef( XmlException ) } | 11 | namespace Bu { subExceptionDef( XmlException ) } |
12 | 12 | ||
13 | Bu::XmlReader::XmlReader( Stream &rInput ) : | 13 | Bu::XmlReader::XmlReader( Stream &rInput ) : |
14 | rInput( rInput ), | 14 | rInput( rInput ), |
15 | iCurToken( 0 ), | 15 | iCurToken( 0 ), |
16 | iNextToken( 0 ), | 16 | iNextToken( 0 ), |
17 | bIgnoreWS( true ) | 17 | bIgnoreWS( true ) |
18 | { | 18 | { |
19 | nextToken(); | 19 | nextToken(); |
20 | stDocument(); | 20 | stDocument(); |
21 | } | 21 | } |
22 | 22 | ||
23 | Bu::XmlReader::~XmlReader() | 23 | Bu::XmlReader::~XmlReader() |
@@ -26,148 +26,148 @@ Bu::XmlReader::~XmlReader() | |||
26 | 26 | ||
27 | void Bu::XmlReader::fillBuffer() | 27 | void Bu::XmlReader::fillBuffer() |
28 | { | 28 | { |
29 | if( rInput.isEos() ) | 29 | if( rInput.isEos() ) |
30 | return; | 30 | return; |
31 | char buf[1024]; | 31 | char buf[1024]; |
32 | int iSize = rInput.read( buf, 1024 ); | 32 | int iSize = rInput.read( buf, 1024 ); |
33 | sBuf.append( buf, iSize ); | 33 | sBuf.append( buf, iSize ); |
34 | } | 34 | } |
35 | 35 | ||
36 | void Bu::XmlReader::cleanupBuffer( int iUsed ) | 36 | void Bu::XmlReader::cleanupBuffer( int iUsed ) |
37 | { | 37 | { |
38 | for( int j = 0; j < iUsed; j++ ) | 38 | for( int j = 0; j < iUsed; j++ ) |
39 | { | 39 | { |
40 | if( sBuf[j] == '\n' ) | 40 | if( sBuf[j] == '\n' ) |
41 | { | 41 | { |
42 | spNextToken.iLine++; | 42 | spNextToken.iLine++; |
43 | spNextToken.iChar = 1; | 43 | spNextToken.iChar = 1; |
44 | } | 44 | } |
45 | else | 45 | else |
46 | { | 46 | { |
47 | spNextToken.iChar++; | 47 | spNextToken.iChar++; |
48 | } | 48 | } |
49 | } | 49 | } |
50 | 50 | ||
51 | printf("--Deleting %d bytes from front of buffer.\n", iUsed ); | 51 | printf("--Deleting %d bytes from front of buffer.\n", iUsed ); |
52 | sBuf.trimFront( iUsed ); | 52 | sBuf.trimFront( iUsed ); |
53 | } | 53 | } |
54 | 54 | ||
55 | int Bu::XmlReader::nextToken() | 55 | int Bu::XmlReader::nextToken() |
56 | { | 56 | { |
57 | fillBuffer(); | 57 | fillBuffer(); |
58 | 58 | ||
59 | int iUsed = 1; | 59 | int iUsed = 1; |
60 | 60 | ||
61 | iCurToken = iNextToken; | 61 | iCurToken = iNextToken; |
62 | spCurToken = spNextToken; | 62 | spCurToken = spNextToken; |
63 | 63 | ||
64 | switch( sBuf[0] ) | 64 | switch( sBuf[0] ) |
65 | { | 65 | { |
66 | case '<': | 66 | case '<': |
67 | if( !strncmp( sBuf.getStr(), "<?xml", 5 ) ) | 67 | if( !strncmp( sBuf.getStr(), "<?xml", 5 ) ) |
68 | { | 68 | { |
69 | iNextToken = tokXmlDeclHead; | 69 | iNextToken = tokXmlDeclHead; |
70 | iUsed = 5; | 70 | iUsed = 5; |
71 | } | 71 | } |
72 | else | 72 | else |
73 | { | 73 | { |
74 | iNextToken = '<'; | 74 | iNextToken = '<'; |
75 | } | 75 | } |
76 | break; | 76 | break; |
77 | 77 | ||
78 | case '?': | 78 | case '?': |
79 | if( sBuf[1] == '>' ) | 79 | if( sBuf[1] == '>' ) |
80 | { | 80 | { |
81 | iNextToken = tokXmlDeclEnd; | 81 | iNextToken = tokXmlDeclEnd; |
82 | iUsed = 2; | 82 | iUsed = 2; |
83 | } | 83 | } |
84 | else | 84 | else |
85 | { | 85 | { |
86 | iNextToken = '?'; | 86 | iNextToken = '?'; |
87 | } | 87 | } |
88 | break; | 88 | break; |
89 | 89 | ||
90 | case ' ': | 90 | case ' ': |
91 | case '\t': | 91 | case '\t': |
92 | case '\n': | 92 | case '\n': |
93 | case '\r': | 93 | case '\r': |
94 | for( int j = 1;; j++ ) | 94 | for( int j = 1;; j++ ) |
95 | { | 95 | { |
96 | if( j == sBuf.getSize() ) | 96 | if( j == sBuf.getSize() ) |
97 | { | 97 | { |
98 | if( rInput.isEos() ) | 98 | if( rInput.isEos() ) |
99 | error("Reached end of input while waiting for whitespace to end."); | 99 | error("Reached end of input while waiting for whitespace to end."); |
100 | 100 | ||
101 | fillBuffer(); | 101 | fillBuffer(); |
102 | } | 102 | } |
103 | if( sBuf[j] == ' ' || sBuf[j] == '\t' || | 103 | if( sBuf[j] == ' ' || sBuf[j] == '\t' || |
104 | sBuf[j] == '\n' || sBuf[j] == '\r' ) | 104 | sBuf[j] == '\n' || sBuf[j] == '\r' ) |
105 | iUsed++; | 105 | iUsed++; |
106 | else | 106 | else |
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | sStr.clear(); | 109 | sStr.clear(); |
110 | sStr.append( sBuf, iUsed ); | 110 | sStr.append( sBuf, iUsed ); |
111 | iNextToken = tokWS; | 111 | iNextToken = tokWS; |
112 | break; | 112 | break; |
113 | 113 | ||
114 | case '=': | 114 | case '=': |
115 | iNextToken = sBuf[0]; | 115 | iNextToken = sBuf[0]; |
116 | break; | 116 | break; |
117 | 117 | ||
118 | default: | 118 | default: |
119 | if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') || | 119 | if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') || |
120 | (sBuf[0] >= 'A' && sBuf[0] <= 'Z') ) | 120 | (sBuf[0] >= 'A' && sBuf[0] <= 'Z') ) |
121 | { | 121 | { |
122 | for( int j = 1;; j++ ) | 122 | for( int j = 1;; j++ ) |
123 | { | 123 | { |
124 | if( j == sBuf.getSize() ) | 124 | if( j == sBuf.getSize() ) |
125 | { | 125 | { |
126 | if( rInput.isEos() ) | 126 | if( rInput.isEos() ) |
127 | error("Reached end of input while waiting for a string to end."); | 127 | error("Reached end of input while waiting for a string to end."); |
128 | 128 | ||
129 | fillBuffer(); | 129 | fillBuffer(); |
130 | } | 130 | } |
131 | if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') || | 131 | if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') || |
132 | (sBuf[j] >= 'A' && sBuf[j] <= 'Z') ) | 132 | (sBuf[j] >= 'A' && sBuf[j] <= 'Z') ) |
133 | iUsed++; | 133 | iUsed++; |
134 | else | 134 | else |
135 | break; | 135 | break; |
136 | } | 136 | } |
137 | sStr.clear(); | 137 | sStr.clear(); |
138 | sStr.append( sBuf, iUsed ); | 138 | sStr.append( sBuf, iUsed ); |
139 | iNextToken = tokIdent; | 139 | iNextToken = tokIdent; |
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | cleanupBuffer( iUsed ); | 143 | cleanupBuffer( iUsed ); |
144 | 144 | ||
145 | return iCurToken; | 145 | return iCurToken; |
146 | } | 146 | } |
147 | 147 | ||
148 | void Bu::XmlReader::error( const char *sMessage ) | 148 | void Bu::XmlReader::error( const char *sMessage ) |
149 | { | 149 | { |
150 | throw Bu::XmlException("%d:%d: %s", | 150 | throw Bu::XmlException("%d:%d: %s", |
151 | spCurToken.iLine, spCurToken.iChar, sMessage ); | 151 | spCurToken.iLine, spCurToken.iChar, sMessage ); |
152 | } | 152 | } |
153 | 153 | ||
154 | void Bu::XmlReader::stDocument() | 154 | void Bu::XmlReader::stDocument() |
155 | { | 155 | { |
156 | stProlog(); | 156 | stProlog(); |
157 | } | 157 | } |
158 | 158 | ||
159 | void Bu::XmlReader::stProlog() | 159 | void Bu::XmlReader::stProlog() |
160 | { | 160 | { |
161 | stXmlDecl(); | 161 | stXmlDecl(); |
162 | } | 162 | } |
163 | 163 | ||
164 | void Bu::XmlReader::stXmlDecl() | 164 | void Bu::XmlReader::stXmlDecl() |
165 | { | 165 | { |
166 | if( nextToken() != tokXmlDeclHead ) | 166 | if( nextToken() != tokXmlDeclHead ) |
167 | error("You must begin your xml file with a declaration: <?xml ... ?>"); | 167 | error("You must begin your xml file with a declaration: <?xml ... ?>"); |
168 | if( nextToken() != tokIdent ) | 168 | if( nextToken() != tokIdent ) |
169 | error("A version comes first!"); | 169 | error("A version comes first!"); |
170 | if( sStr != "version" ) | 170 | if( sStr != "version" ) |
171 | error("No, a version!"); | 171 | error("No, a version!"); |
172 | } | 172 | } |
173 | 173 | ||
diff --git a/src/experimental/xmlreader.h b/src/experimental/xmlreader.h index d4bad1e..9615cfb 100644 --- a/src/experimental/xmlreader.h +++ b/src/experimental/xmlreader.h | |||
@@ -13,52 +13,52 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class Stream; | 16 | class Stream; |
17 | 17 | ||
18 | subExceptionDecl( XmlException ); | 18 | subExceptionDecl( XmlException ); |
19 | 19 | ||
20 | class XmlReader | 20 | class XmlReader |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | XmlReader( Stream &rInput ); | 23 | XmlReader( Stream &rInput ); |
24 | virtual ~XmlReader(); | 24 | virtual ~XmlReader(); |
25 | 25 | ||
26 | private: | 26 | private: |
27 | Stream &rInput; | 27 | Stream &rInput; |
28 | int iCurToken; | 28 | int iCurToken; |
29 | int iNextToken; | 29 | int iNextToken; |
30 | Bu::String sBuf; | 30 | Bu::String sBuf; |
31 | Bu::String sStr; | 31 | Bu::String sStr; |
32 | bool bIgnoreWS; | 32 | bool bIgnoreWS; |
33 | typedef struct StreamPos | 33 | typedef struct StreamPos |
34 | { | 34 | { |
35 | StreamPos() : iLine( 1 ), iChar( 1 ) { } | 35 | StreamPos() : iLine( 1 ), iChar( 1 ) { } |
36 | int iLine; | 36 | int iLine; |
37 | int iChar; | 37 | int iChar; |
38 | } StreamPos; | 38 | } StreamPos; |
39 | StreamPos spCurToken; | 39 | StreamPos spCurToken; |
40 | StreamPos spNextToken; | 40 | StreamPos spNextToken; |
41 | 41 | ||
42 | 42 | ||
43 | enum | 43 | enum |
44 | { | 44 | { |
45 | tokXmlDeclHead = 0x100, | 45 | tokXmlDeclHead = 0x100, |
46 | tokXmlDeclEnd, | 46 | tokXmlDeclEnd, |
47 | tokWS, | 47 | tokWS, |
48 | tokIdent, | 48 | tokIdent, |
49 | tokString | 49 | tokString |
50 | }; | 50 | }; |
51 | 51 | ||
52 | void fillBuffer(); | 52 | void fillBuffer(); |
53 | void cleanupBuffer( int iUsed ); | 53 | void cleanupBuffer( int iUsed ); |
54 | int nextToken(); | 54 | int nextToken(); |
55 | 55 | ||
56 | void stDocument(); | 56 | void stDocument(); |
57 | void stProlog(); | 57 | void stProlog(); |
58 | void stXmlDecl(); | 58 | void stXmlDecl(); |
59 | 59 | ||
60 | void error( const char *sMessage ); | 60 | void error( const char *sMessage ); |
61 | }; | 61 | }; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | #endif | 64 | #endif |
diff --git a/src/extra/myriadfs.cpp b/src/extra/myriadfs.cpp index 867a595..6dc3ff4 100644 --- a/src/extra/myriadfs.cpp +++ b/src/extra/myriadfs.cpp | |||
@@ -28,307 +28,307 @@ int64_t iNextFileId = 0; | |||
28 | #define TRACE | 28 | #define TRACE |
29 | 29 | ||
30 | extern "C" { | 30 | extern "C" { |
31 | static int myriadfs_getattr( const char *sPath, struct stat *stbuf ) | 31 | static int myriadfs_getattr( const char *sPath, struct stat *stbuf ) |
32 | { | 32 | { |
33 | #ifdef TRACE | 33 | #ifdef TRACE |
34 | printf("myriadfs_getattr(\"%s\", ... );\n", sPath ); | 34 | printf("myriadfs_getattr(\"%s\", ... );\n", sPath ); |
35 | #endif | 35 | #endif |
36 | try | 36 | try |
37 | { | 37 | { |
38 | Bu::MyriadFs::Stat st; | 38 | Bu::MyriadFs::Stat st; |
39 | pFs->stat( sPath, st ); | 39 | pFs->stat( sPath, st ); |
40 | stbuf->st_ino = st.iNode; | 40 | stbuf->st_ino = st.iNode; |
41 | stbuf->st_mode = st.uPerms; | 41 | stbuf->st_mode = st.uPerms; |
42 | stbuf->st_nlink = st.iLinks; | 42 | stbuf->st_nlink = st.iLinks; |
43 | stbuf->st_uid = st.iUser; | 43 | stbuf->st_uid = st.iUser; |
44 | stbuf->st_gid = st.iGroup; | 44 | stbuf->st_gid = st.iGroup; |
45 | stbuf->st_rdev = Bu::MyriadFs::devToSys( st.uDev ); | 45 | stbuf->st_rdev = Bu::MyriadFs::devToSys( st.uDev ); |
46 | stbuf->st_size = st.iSize; | 46 | stbuf->st_size = st.iSize; |
47 | stbuf->st_blocks = 8; | 47 | stbuf->st_blocks = 8; |
48 | stbuf->st_atime = st.iATime; | 48 | stbuf->st_atime = st.iATime; |
49 | stbuf->st_mtime = st.iMTime; | 49 | stbuf->st_mtime = st.iMTime; |
50 | stbuf->st_ctime = st.iCTime; | 50 | stbuf->st_ctime = st.iCTime; |
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | catch(...) | 53 | catch(...) |
54 | { | 54 | { |
55 | return -ENOENT; | 55 | return -ENOENT; |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | static int myriadfs_readdir( const char *sPath, void *buf, | 59 | static int myriadfs_readdir( const char *sPath, void *buf, |
60 | fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi ) | 60 | fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi ) |
61 | { | 61 | { |
62 | #ifdef TRACE | 62 | #ifdef TRACE |
63 | printf("myriadfs_readdir(\"%s\", ... );\n", sPath ); | 63 | printf("myriadfs_readdir(\"%s\", ... );\n", sPath ); |
64 | #endif | 64 | #endif |
65 | Bu::MyriadFs::Dir lDir = pFs->readDir( sPath ); | 65 | Bu::MyriadFs::Dir lDir = pFs->readDir( sPath ); |
66 | filler( buf, ".", NULL, 0 ); | 66 | filler( buf, ".", NULL, 0 ); |
67 | filler( buf, "..", NULL, 0 ); | 67 | filler( buf, "..", NULL, 0 ); |
68 | for( Bu::MyriadFs::Dir::iterator i = lDir.begin(); i; i++ ) | 68 | for( Bu::MyriadFs::Dir::iterator i = lDir.begin(); i; i++ ) |
69 | { | 69 | { |
70 | filler( buf, (*i).sName.getStr(), NULL, 0 ); | 70 | filler( buf, (*i).sName.getStr(), NULL, 0 ); |
71 | } | 71 | } |
72 | 72 | ||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static int myriadfs_mkdir( const char *sPath, mode_t uMode ) | 76 | static int myriadfs_mkdir( const char *sPath, mode_t uMode ) |
77 | { | 77 | { |
78 | #ifdef TRACE | 78 | #ifdef TRACE |
79 | printf("myriadfs_mkdir(\"%s\", 0%o );\n", sPath, uMode ); | 79 | printf("myriadfs_mkdir(\"%s\", 0%o );\n", sPath, uMode ); |
80 | #endif | 80 | #endif |
81 | pFs->mkDir( sPath, uMode ); | 81 | pFs->mkDir( sPath, uMode ); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static int myriadfs_open( const char *sPath, struct fuse_file_info *fi ) | 85 | static int myriadfs_open( const char *sPath, struct fuse_file_info *fi ) |
86 | { | 86 | { |
87 | #ifdef TRACE | 87 | #ifdef TRACE |
88 | printf("myriadfs_open(\"%s\", ... );\n", sPath ); | 88 | printf("myriadfs_open(\"%s\", ... );\n", sPath ); |
89 | #endif | 89 | #endif |
90 | try | 90 | try |
91 | { | 91 | { |
92 | Bu::MyriadStream ms = pFs->open( sPath, 0 ); | 92 | Bu::MyriadStream ms = pFs->open( sPath, 0 ); |
93 | fi->fh = iNextFileId; | 93 | fi->fh = iNextFileId; |
94 | hOpenFiles.insert( iNextFileId++, ms ); | 94 | hOpenFiles.insert( iNextFileId++, ms ); |
95 | // printf("File '%s' opened, %d files open now.\n", | 95 | // printf("File '%s' opened, %d files open now.\n", |
96 | // sPath, hOpenFiles.getSize() ); | 96 | // sPath, hOpenFiles.getSize() ); |
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | catch(...) | 99 | catch(...) |
100 | { | 100 | { |
101 | return -EACCES; | 101 | return -EACCES; |
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | static int myriadfs_read( const char *sPath, char *buf, size_t iSize, | 105 | static int myriadfs_read( const char *sPath, char *buf, size_t iSize, |
106 | off_t iOffset, struct fuse_file_info *fi ) | 106 | off_t iOffset, struct fuse_file_info *fi ) |
107 | { | 107 | { |
108 | #ifdef TRACE | 108 | #ifdef TRACE |
109 | printf("myriadfs_read(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, | 109 | printf("myriadfs_read(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, |
110 | iOffset ); | 110 | iOffset ); |
111 | #endif | 111 | #endif |
112 | Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); | 112 | Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); |
113 | ms.setPos( iOffset ); | 113 | ms.setPos( iOffset ); |
114 | return ms.read( buf, iSize ); | 114 | return ms.read( buf, iSize ); |
115 | } | 115 | } |
116 | 116 | ||
117 | static int myriadfs_write( const char *sPath, const char *buf, size_t iSize, | 117 | static int myriadfs_write( const char *sPath, const char *buf, size_t iSize, |
118 | off_t iOffset, struct fuse_file_info *fi ) | 118 | off_t iOffset, struct fuse_file_info *fi ) |
119 | { | 119 | { |
120 | #ifdef TRACE | 120 | #ifdef TRACE |
121 | printf("myriadfs_write(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, | 121 | printf("myriadfs_write(\"%s\", ..., %d, %d, ... );\n", sPath, iSize, |
122 | iOffset ); | 122 | iOffset ); |
123 | #endif | 123 | #endif |
124 | Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); | 124 | Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); |
125 | ms.setPos( iOffset ); | 125 | ms.setPos( iOffset ); |
126 | return ms.write( buf, iSize ); | 126 | return ms.write( buf, iSize ); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int myriadfs_create( const char *sPath, mode_t uPerms, | 129 | static int myriadfs_create( const char *sPath, mode_t uPerms, |
130 | struct fuse_file_info *fi ) | 130 | struct fuse_file_info *fi ) |
131 | { | 131 | { |
132 | #ifdef TRACE | 132 | #ifdef TRACE |
133 | printf("myriadfs_create(\"%s\", 0%o, ... );\n", sPath, uPerms ); | 133 | printf("myriadfs_create(\"%s\", 0%o, ... );\n", sPath, uPerms ); |
134 | #endif | 134 | #endif |
135 | try | 135 | try |
136 | { | 136 | { |
137 | Bu::MyriadStream ms = pFs->open( sPath, 0, uPerms ); | 137 | Bu::MyriadStream ms = pFs->open( sPath, 0, uPerms ); |
138 | fi->fh = iNextFileId; | 138 | fi->fh = iNextFileId; |
139 | hOpenFiles.insert( iNextFileId++, ms ); | 139 | hOpenFiles.insert( iNextFileId++, ms ); |
140 | // printf("File '%s' created, %d files open now.\n", | 140 | // printf("File '%s' created, %d files open now.\n", |
141 | // sPath, hOpenFiles.getSize() ); | 141 | // sPath, hOpenFiles.getSize() ); |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | catch(...) | 144 | catch(...) |
145 | { | 145 | { |
146 | return -EACCES; | 146 | return -EACCES; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | static int myriadfs_mknod( const char *sPath, mode_t uPerms, dev_t Dev ) | 150 | static int myriadfs_mknod( const char *sPath, mode_t uPerms, dev_t Dev ) |
151 | { | 151 | { |
152 | #ifdef TRACE | 152 | #ifdef TRACE |
153 | printf("myriadfs_mknod(\"%s\", 0%o, %x );\n", sPath, uPerms, Dev ); | 153 | printf("myriadfs_mknod(\"%s\", 0%o, %x );\n", sPath, uPerms, Dev ); |
154 | #endif | 154 | #endif |
155 | try | 155 | try |
156 | { | 156 | { |
157 | pFs->create( sPath, uPerms, Bu::MyriadFs::sysToDev( Dev ) ); | 157 | pFs->create( sPath, uPerms, Bu::MyriadFs::sysToDev( Dev ) ); |
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | catch(...) | 160 | catch(...) |
161 | { | 161 | { |
162 | return -EACCES; | 162 | return -EACCES; |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) | 166 | static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) |
167 | { | 167 | { |
168 | #ifdef TRACE | 168 | #ifdef TRACE |
169 | printf("myriadfs_release(\"%s\", ... );\n", sPath ); | 169 | printf("myriadfs_release(\"%s\", ... );\n", sPath ); |
170 | #endif | 170 | #endif |
171 | hOpenFiles.erase( fi->fh ); | 171 | hOpenFiles.erase( fi->fh ); |
172 | // printf("File '%s' released, %d files open now.\n", | 172 | // printf("File '%s' released, %d files open now.\n", |
173 | // sPath, hOpenFiles.getSize() ); | 173 | // sPath, hOpenFiles.getSize() ); |
174 | 174 | ||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int myriadfs_utimens( const char *sPath, | 178 | static int myriadfs_utimens( const char *sPath, |
179 | const struct timespec tv[2] ) | 179 | const struct timespec tv[2] ) |
180 | { | 180 | { |
181 | #ifdef TRACE | 181 | #ifdef TRACE |
182 | printf("myriadfs_utimens(\"%s\", ... );\n", sPath ); | 182 | printf("myriadfs_utimens(\"%s\", ... );\n", sPath ); |
183 | #endif | 183 | #endif |
184 | try | 184 | try |
185 | { | 185 | { |
186 | pFs->setTimes( sPath, tv[0].tv_sec, tv[1].tv_sec ); | 186 | pFs->setTimes( sPath, tv[0].tv_sec, tv[1].tv_sec ); |
187 | } | 187 | } |
188 | catch(...) | 188 | catch(...) |
189 | { | 189 | { |
190 | return -EACCES; | 190 | return -EACCES; |
191 | } | 191 | } |
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int myriadfs_unlink( const char *sPath ) | 195 | static int myriadfs_unlink( const char *sPath ) |
196 | { | 196 | { |
197 | #ifdef TRACE | 197 | #ifdef TRACE |
198 | printf("myriadfs_unlink(\"%s\");\n", sPath ); | 198 | printf("myriadfs_unlink(\"%s\");\n", sPath ); |
199 | #endif | 199 | #endif |
200 | try | 200 | try |
201 | { | 201 | { |
202 | pFs->unlink( sPath ); | 202 | pFs->unlink( sPath ); |
203 | } | 203 | } |
204 | catch( Bu::MyriadFsException &e ) | 204 | catch( Bu::MyriadFsException &e ) |
205 | { | 205 | { |
206 | printf("MyriadFsException: %s\n", e.what() ); | 206 | printf("MyriadFsException: %s\n", e.what() ); |
207 | return -EACCES; | 207 | return -EACCES; |
208 | } | 208 | } |
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int myriadfs_symlink( const char *sTarget, const char *sPath ) | 212 | static int myriadfs_symlink( const char *sTarget, const char *sPath ) |
213 | { | 213 | { |
214 | #ifdef TRACE | 214 | #ifdef TRACE |
215 | printf("myriadfs_symlink(\"%s\", \"%s\");\n", sTarget, sPath ); | 215 | printf("myriadfs_symlink(\"%s\", \"%s\");\n", sTarget, sPath ); |
216 | #endif | 216 | #endif |
217 | try | 217 | try |
218 | { | 218 | { |
219 | pFs->mkSymLink( sTarget, sPath ); | 219 | pFs->mkSymLink( sTarget, sPath ); |
220 | } | 220 | } |
221 | catch( Bu::MyriadFsException &e ) | 221 | catch( Bu::MyriadFsException &e ) |
222 | { | 222 | { |
223 | printf("MyriadFsException: %s\n", e.what() ); | 223 | printf("MyriadFsException: %s\n", e.what() ); |
224 | return -EACCES; | 224 | return -EACCES; |
225 | } | 225 | } |
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int myriadfs_readlink( const char *sPath, char *sOut, size_t s ) | 229 | static int myriadfs_readlink( const char *sPath, char *sOut, size_t s ) |
230 | { | 230 | { |
231 | #ifdef TRACE | 231 | #ifdef TRACE |
232 | printf("myriadfs_readlink(\"%s\", ... );\n", sPath ); | 232 | printf("myriadfs_readlink(\"%s\", ... );\n", sPath ); |
233 | #endif | 233 | #endif |
234 | try | 234 | try |
235 | { | 235 | { |
236 | Bu::String sTrg = pFs->readSymLink( sPath ); | 236 | Bu::String sTrg = pFs->readSymLink( sPath ); |
237 | size_t iLen = (s-1>sTrg.getSize())?(sTrg.getSize()):(s-1); | 237 | size_t iLen = (s-1>sTrg.getSize())?(sTrg.getSize()):(s-1); |
238 | memcpy( sOut, sTrg.getStr(), iLen ); | 238 | memcpy( sOut, sTrg.getStr(), iLen ); |
239 | sOut[iLen] = '\0'; | 239 | sOut[iLen] = '\0'; |
240 | } | 240 | } |
241 | catch( Bu::MyriadFsException &e ) | 241 | catch( Bu::MyriadFsException &e ) |
242 | { | 242 | { |
243 | printf("MyriadFsException: %s\n", e.what() ); | 243 | printf("MyriadFsException: %s\n", e.what() ); |
244 | return -EACCES; | 244 | return -EACCES; |
245 | } | 245 | } |
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int myriadfs_truncate( const char *sPath, off_t iSize ) | 249 | static int myriadfs_truncate( const char *sPath, off_t iSize ) |
250 | { | 250 | { |
251 | #ifdef TRACE | 251 | #ifdef TRACE |
252 | printf("myriadfs_truncate(\"%s\", %d );\n", sPath, iSize ); | 252 | printf("myriadfs_truncate(\"%s\", %d );\n", sPath, iSize ); |
253 | #endif | 253 | #endif |
254 | 254 | ||
255 | try | 255 | try |
256 | { | 256 | { |
257 | pFs->setFileSize( sPath, iSize ); | 257 | pFs->setFileSize( sPath, iSize ); |
258 | } | 258 | } |
259 | catch( Bu::MyriadFsException &e ) | 259 | catch( Bu::MyriadFsException &e ) |
260 | { | 260 | { |
261 | printf("MyriadFsException: %s\n", e.what() ); | 261 | printf("MyriadFsException: %s\n", e.what() ); |
262 | return -ENOENT; | 262 | return -ENOENT; |
263 | } | 263 | } |
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
267 | static int myriadfs_link( const char *sTarget, const char *sPath ) | 267 | static int myriadfs_link( const char *sTarget, const char *sPath ) |
268 | { | 268 | { |
269 | #ifdef TRACE | 269 | #ifdef TRACE |
270 | printf("myriadfs_link(\"%s\", \"%s\");\n", sTarget, sPath ); | 270 | printf("myriadfs_link(\"%s\", \"%s\");\n", sTarget, sPath ); |
271 | #endif | 271 | #endif |
272 | 272 | ||
273 | try | 273 | try |
274 | { | 274 | { |
275 | pFs->mkHardLink( sTarget, sPath ); | 275 | pFs->mkHardLink( sTarget, sPath ); |
276 | } | 276 | } |
277 | catch( Bu::MyriadFsException &e ) | 277 | catch( Bu::MyriadFsException &e ) |
278 | { | 278 | { |
279 | printf("MyriadFsException: %s\n", e.what() ); | 279 | printf("MyriadFsException: %s\n", e.what() ); |
280 | return -EACCES; | 280 | return -EACCES; |
281 | } | 281 | } |
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | static int myriadfs_rename( const char *sFrom, const char *sTo ) | 285 | static int myriadfs_rename( const char *sFrom, const char *sTo ) |
286 | { | 286 | { |
287 | #ifdef TRACE | 287 | #ifdef TRACE |
288 | printf("myriadfs_rename(\"%s\", \"%s\");\n", sFrom, sTo ); | 288 | printf("myriadfs_rename(\"%s\", \"%s\");\n", sFrom, sTo ); |
289 | #endif | 289 | #endif |
290 | 290 | ||
291 | try | 291 | try |
292 | { | 292 | { |
293 | pFs->rename( sFrom, sTo ); | 293 | pFs->rename( sFrom, sTo ); |
294 | } | 294 | } |
295 | catch( Bu::MyriadFsException &e ) | 295 | catch( Bu::MyriadFsException &e ) |
296 | { | 296 | { |
297 | printf("MyriadFsException: %s\n", e.what() ); | 297 | printf("MyriadFsException: %s\n", e.what() ); |
298 | return -EACCES; | 298 | return -EACCES; |
299 | } | 299 | } |
300 | return 0; | 300 | return 0; |
301 | } | 301 | } |
302 | 302 | ||
303 | static struct fuse_operations myriadfs_oper; | 303 | static struct fuse_operations myriadfs_oper; |
304 | 304 | ||
305 | int main( int argc, char *argv[] ) | 305 | int main( int argc, char *argv[] ) |
306 | { | 306 | { |
307 | pF = new Bu::File("store.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); | 307 | pF = new Bu::File("store.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); |
308 | pFs = new Bu::MyriadFs( *pF, 512 ); | 308 | pFs = new Bu::MyriadFs( *pF, 512 ); |
309 | memset( &myriadfs_oper, sizeof(myriadfs_oper), 0 ); | 309 | memset( &myriadfs_oper, sizeof(myriadfs_oper), 0 ); |
310 | myriadfs_oper.getattr = myriadfs_getattr; | 310 | myriadfs_oper.getattr = myriadfs_getattr; |
311 | myriadfs_oper.readdir = myriadfs_readdir; | 311 | myriadfs_oper.readdir = myriadfs_readdir; |
312 | myriadfs_oper.mkdir = myriadfs_mkdir; | 312 | myriadfs_oper.mkdir = myriadfs_mkdir; |
313 | myriadfs_oper.open = myriadfs_open; | 313 | myriadfs_oper.open = myriadfs_open; |
314 | myriadfs_oper.read = myriadfs_read; | 314 | myriadfs_oper.read = myriadfs_read; |
315 | myriadfs_oper.write = myriadfs_write; | 315 | myriadfs_oper.write = myriadfs_write; |
316 | myriadfs_oper.create = myriadfs_create; | 316 | myriadfs_oper.create = myriadfs_create; |
317 | myriadfs_oper.mknod = myriadfs_mknod; | 317 | myriadfs_oper.mknod = myriadfs_mknod; |
318 | myriadfs_oper.release = myriadfs_release; | 318 | myriadfs_oper.release = myriadfs_release; |
319 | myriadfs_oper.utimens = myriadfs_utimens; | 319 | myriadfs_oper.utimens = myriadfs_utimens; |
320 | myriadfs_oper.unlink = myriadfs_unlink; | 320 | myriadfs_oper.unlink = myriadfs_unlink; |
321 | myriadfs_oper.rmdir = myriadfs_unlink; | 321 | myriadfs_oper.rmdir = myriadfs_unlink; |
322 | myriadfs_oper.symlink = myriadfs_symlink; | 322 | myriadfs_oper.symlink = myriadfs_symlink; |
323 | myriadfs_oper.readlink = myriadfs_readlink; | 323 | myriadfs_oper.readlink = myriadfs_readlink; |
324 | myriadfs_oper.truncate = myriadfs_truncate; | 324 | myriadfs_oper.truncate = myriadfs_truncate; |
325 | myriadfs_oper.link = myriadfs_link; | 325 | myriadfs_oper.link = myriadfs_link; |
326 | myriadfs_oper.rename = myriadfs_rename; | 326 | myriadfs_oper.rename = myriadfs_rename; |
327 | printf("Starting fuse_main.\n"); | 327 | printf("Starting fuse_main.\n"); |
328 | int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); | 328 | int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); |
329 | printf("Done with fuse_main.\n"); | 329 | printf("Done with fuse_main.\n"); |
330 | delete pFs; | 330 | delete pFs; |
331 | delete pF; | 331 | delete pF; |
332 | return iRet; | 332 | return iRet; |
333 | } | 333 | } |
334 | } | 334 | } |
diff --git a/src/stable/archival.cpp b/src/stable/archival.cpp index 5e6e612..9ba10f2 100644 --- a/src/stable/archival.cpp +++ b/src/stable/archival.cpp | |||
@@ -17,19 +17,19 @@ Bu::Archival::~Archival() | |||
17 | 17 | ||
18 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) | 18 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) |
19 | { | 19 | { |
20 | const_cast<Bu::Archival &>(p).archive( s ); | 20 | const_cast<Bu::Archival &>(p).archive( s ); |
21 | return s; | 21 | return s; |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) | 24 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) |
25 | { | 25 | { |
26 | p.archive( s ); | 26 | p.archive( s ); |
27 | return s; | 27 | return s; |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) | 30 | Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) |
31 | { | 31 | { |
32 | p.archive( s ); | 32 | p.archive( s ); |
33 | return s; | 33 | return s; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/src/stable/archival.h b/src/stable/archival.h index 664bc98..78faffb 100644 --- a/src/stable/archival.h +++ b/src/stable/archival.h | |||
@@ -12,40 +12,40 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * The base class for any class you want to archive. Simply include this as | 16 | * The base class for any class you want to archive. Simply include this as |
17 | * a base class, implement the purely virtual archive function and you've | 17 | * a base class, implement the purely virtual archive function and you've |
18 | * got an easily archiveable class. | 18 | * got an easily archiveable class. |
19 | * | 19 | * |
20 | * Archival: "of or pertaining to archives or valuable records; contained | 20 | * Archival: "of or pertaining to archives or valuable records; contained |
21 | * in or comprising such archives or records." | 21 | * in or comprising such archives or records." |
22 | */ | 22 | */ |
23 | class Archival | 23 | class Archival |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | /** | 26 | /** |
27 | * Does nothing, here for completeness. | 27 | * Does nothing, here for completeness. |
28 | */ | 28 | */ |
29 | Archival(); | 29 | Archival(); |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Here to ensure the deconstructor is virtual. | 32 | * Here to ensure the deconstructor is virtual. |
33 | */ | 33 | */ |
34 | virtual ~Archival(); | 34 | virtual ~Archival(); |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * This is the main workhorse of the archive system, just override and | 37 | * This is the main workhorse of the archive system, just override and |
38 | * you've got a archiveable class. A reference to the Archive | 38 | * you've got a archiveable class. A reference to the Archive |
39 | * used is passed in as your only parameter, query it to discover if | 39 | * used is passed in as your only parameter, query it to discover if |
40 | * you are loading or saving. | 40 | * you are loading or saving. |
41 | * @param ar A reference to the Archive object to use. | 41 | * @param ar A reference to the Archive object to use. |
42 | */ | 42 | */ |
43 | virtual void archive( class ArchiveBase &ar )=0; | 43 | virtual void archive( class ArchiveBase &ar )=0; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); | 46 | ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); |
47 | ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); | 47 | ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); |
48 | ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); | 48 | ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); |
49 | 49 | ||
50 | } | 50 | } |
51 | 51 | ||
diff --git a/src/stable/archive.cpp b/src/stable/archive.cpp index 13480e1..3769e0e 100644 --- a/src/stable/archive.cpp +++ b/src/stable/archive.cpp | |||
@@ -12,9 +12,9 @@ | |||
12 | #include "bu/sio.h" | 12 | #include "bu/sio.h" |
13 | 13 | ||
14 | Bu::Archive::Archive( Stream &rStream, bool bLoading ) : | 14 | Bu::Archive::Archive( Stream &rStream, bool bLoading ) : |
15 | bLoading( bLoading ), | 15 | bLoading( bLoading ), |
16 | rStream( rStream ), | 16 | rStream( rStream ), |
17 | nNextID( 1 ) | 17 | nNextID( 1 ) |
18 | { | 18 | { |
19 | } | 19 | } |
20 | 20 | ||
@@ -24,66 +24,66 @@ Bu::Archive::~Archive() | |||
24 | 24 | ||
25 | void Bu::Archive::write( const void *pData, size_t nSize ) | 25 | void Bu::Archive::write( const void *pData, size_t nSize ) |
26 | { | 26 | { |
27 | if( nSize == 0 || pData == NULL ) | 27 | if( nSize == 0 || pData == NULL ) |
28 | return; | 28 | return; |
29 | 29 | ||
30 | rStream.write( (const char *)pData, nSize ); | 30 | rStream.write( (const char *)pData, nSize ); |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::Archive::read( void *pData, size_t nSize ) | 33 | void Bu::Archive::read( void *pData, size_t nSize ) |
34 | { | 34 | { |
35 | if( nSize == 0 || pData == NULL ) | 35 | if( nSize == 0 || pData == NULL ) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) | 38 | if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) |
39 | throw Bu::ExceptionBase("Insufficient data to unarchive object."); | 39 | throw Bu::ExceptionBase("Insufficient data to unarchive object."); |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::Archive::close() | 42 | void Bu::Archive::close() |
43 | { | 43 | { |
44 | rStream.close(); | 44 | rStream.close(); |
45 | } | 45 | } |
46 | 46 | ||
47 | bool Bu::Archive::isLoading() | 47 | bool Bu::Archive::isLoading() |
48 | { | 48 | { |
49 | return bLoading; | 49 | return bLoading; |
50 | } | 50 | } |
51 | 51 | ||
52 | uint32_t Bu::Archive::getID( const void *ptr ) | 52 | uint32_t Bu::Archive::getID( const void *ptr ) |
53 | { | 53 | { |
54 | if( hPtrID.has( (ptrdiff_t)ptr ) ) | 54 | if( hPtrID.has( (ptrdiff_t)ptr ) ) |
55 | return hPtrID.get( (ptrdiff_t)ptr ); | 55 | return hPtrID.get( (ptrdiff_t)ptr ); |
56 | hPtrID.insert( (ptrdiff_t)ptr, nNextID ); | 56 | hPtrID.insert( (ptrdiff_t)ptr, nNextID ); |
57 | return nNextID++; | 57 | return nNextID++; |
58 | } | 58 | } |
59 | 59 | ||
60 | void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) | 60 | void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) |
61 | { | 61 | { |
62 | if( hPtrID.has( id ) ) | 62 | if( hPtrID.has( id ) ) |
63 | { | 63 | { |
64 | *ptr = (void *)hPtrID.get( id ); | 64 | *ptr = (void *)hPtrID.get( id ); |
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | if( !hPtrDest.has( id ) ) | 68 | if( !hPtrDest.has( id ) ) |
69 | hPtrDest.insert( id, List<void **>() ); | 69 | hPtrDest.insert( id, List<void **>() ); |
70 | 70 | ||
71 | hPtrDest[id].getValue().append( ptr ); | 71 | hPtrDest[id].getValue().append( ptr ); |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::Archive::readID( const void *ptr, uint32_t id ) | 74 | void Bu::Archive::readID( const void *ptr, uint32_t id ) |
75 | { | 75 | { |
76 | hPtrID.insert( id, (ptrdiff_t)ptr ); | 76 | hPtrID.insert( id, (ptrdiff_t)ptr ); |
77 | 77 | ||
78 | if( hPtrDest.has( id ) ) | 78 | if( hPtrDest.has( id ) ) |
79 | { | 79 | { |
80 | Bu::List<void **> &l = hPtrDest.get( id ); | 80 | Bu::List<void **> &l = hPtrDest.get( id ); |
81 | for( Bu::List<void **>::iterator i = l.begin(); i != l.end(); i++ ) | 81 | for( Bu::List<void **>::iterator i = l.begin(); i != l.end(); i++ ) |
82 | { | 82 | { |
83 | *(*i) = (void *)ptr; | 83 | *(*i) = (void *)ptr; |
84 | } | 84 | } |
85 | 85 | ||
86 | hPtrDest.erase( id ); | 86 | hPtrDest.erase( id ); |
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
diff --git a/src/stable/archive.h b/src/stable/archive.h index 9716bb1..f98402d 100644 --- a/src/stable/archive.h +++ b/src/stable/archive.h | |||
@@ -16,123 +16,123 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class Archival; | 19 | class Archival; |
20 | class Stream; | 20 | class Stream; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * Provides a framework for serialization of objects and primitives. The | 23 | * Provides a framework for serialization of objects and primitives. The |
24 | * archive will handle any basic primitive, a few special types, like char * | 24 | * archive will handle any basic primitive, a few special types, like char * |
25 | * strings, as well as STL classes and anything that inherits from the | 25 | * strings, as well as STL classes and anything that inherits from the |
26 | * Archival class. Each Archive operates on a Stream, so you can send the | 26 | * Archival class. Each Archive operates on a Stream, so you can send the |
27 | * data using an Archive almost anywhere. | 27 | * data using an Archive almost anywhere. |
28 | * | 28 | * |
29 | * In order to use an Archive to store something to a file, try something | 29 | * In order to use an Archive to store something to a file, try something |
30 | * like: | 30 | * like: |
31 | *@code | 31 | *@code |
32 | * File sOut("output", "wb"); // This is a stream subclass | 32 | * File sOut("output", "wb"); // This is a stream subclass |
33 | * Archive ar( sOut, Archive::save ); | 33 | * Archive ar( sOut, Archive::save ); |
34 | * ar << myClass; | 34 | * ar << myClass; |
35 | @endcode | 35 | @endcode |
36 | * In this example myClass is any class that inherits from Archival. When | 36 | * In this example myClass is any class that inherits from Archival. When |
37 | * the storage operator is called, the Archival::archive() function in the | 37 | * the storage operator is called, the Archival::archive() function in the |
38 | * myClass object is called with a reference to the Archive. This can be | 38 | * myClass object is called with a reference to the Archive. This can be |
39 | * handled in one of two ways: | 39 | * handled in one of two ways: |
40 | *@code | 40 | *@code |
41 | * void MyClass::archive( Archive &ar ) | 41 | * void MyClass::archive( Archive &ar ) |
42 | * { | 42 | * { |
43 | * ar && sName && nAge && sJob; | 43 | * ar && sName && nAge && sJob; |
44 | * } | 44 | * } |
45 | @endcode | 45 | @endcode |
46 | * Here we don't worry about weather we're loading or saving by using the | 46 | * Here we don't worry about weather we're loading or saving by using the |
47 | * smart && operator. This allows us to write very consistent, very simple | 47 | * smart && operator. This allows us to write very consistent, very simple |
48 | * archive functions that really do a lot of work. If we wanted to do | 48 | * archive functions that really do a lot of work. If we wanted to do |
49 | * something different in the case of loading or saving we would do: | 49 | * something different in the case of loading or saving we would do: |
50 | *@code | 50 | *@code |
51 | * void MyClass::archive( Archive &ar ) | 51 | * void MyClass::archive( Archive &ar ) |
52 | * { | 52 | * { |
53 | * if( ar.isLoading() ) | 53 | * if( ar.isLoading() ) |
54 | * { | 54 | * { |
55 | * ar >> sName >> nAge >> sJob; | 55 | * ar >> sName >> nAge >> sJob; |
56 | * } else | 56 | * } else |
57 | * { | 57 | * { |
58 | * ar << sName << nAge << sJob; | 58 | * ar << sName << nAge << sJob; |
59 | * } | 59 | * } |
60 | * } | 60 | * } |
61 | @endcode | 61 | @endcode |
62 | * Archive currently does not provide facility to make fully portable | 62 | * Archive currently does not provide facility to make fully portable |
63 | * archives. For example, it will not convert between endianness for you, | 63 | * archives. For example, it will not convert between endianness for you, |
64 | * nor will it take into account differences between primitive sizes on | 64 | * nor will it take into account differences between primitive sizes on |
65 | * different platforms. This, at the moment, is up to the user to ensure. | 65 | * different platforms. This, at the moment, is up to the user to ensure. |
66 | * One way of dealing with the latter problem is to make sure and use | 66 | * One way of dealing with the latter problem is to make sure and use |
67 | * explicit primitive types from the stdint.h header, i.e. int32_t. | 67 | * explicit primitive types from the stdint.h header, i.e. int32_t. |
68 | */ | 68 | */ |
69 | class Archive : public ArchiveBase | 69 | class Archive : public ArchiveBase |
70 | { | 70 | { |
71 | private: | 71 | private: |
72 | bool bLoading; | 72 | bool bLoading; |
73 | public: | 73 | public: |
74 | bool isLoading(); | 74 | bool isLoading(); |
75 | 75 | ||
76 | enum | 76 | enum |
77 | { | 77 | { |
78 | load = true, | 78 | load = true, |
79 | save = false | 79 | save = false |
80 | }; | 80 | }; |
81 | 81 | ||
82 | Archive( Stream &rStream, bool bLoading ); | 82 | Archive( Stream &rStream, bool bLoading ); |
83 | virtual ~Archive(); | 83 | virtual ~Archive(); |
84 | virtual void close(); | 84 | virtual void close(); |
85 | 85 | ||
86 | virtual void write( const void *pData, size_t iSize ); | 86 | virtual void write( const void *pData, size_t iSize ); |
87 | virtual void read( void *pData, size_t iSize ); | 87 | virtual void read( void *pData, size_t iSize ); |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * For storage, get an ID for the pointer to the object you're going to | 90 | * For storage, get an ID for the pointer to the object you're going to |
91 | * write. | 91 | * write. |
92 | */ | 92 | */ |
93 | uint32_t getID( const void *ptr ); | 93 | uint32_t getID( const void *ptr ); |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * For loading. Assosiates an empty pointer with an id. When you wind | 96 | * For loading. Assosiates an empty pointer with an id. When you wind |
97 | * up loading an id reference to a pointer for an object that may or | 97 | * up loading an id reference to a pointer for an object that may or |
98 | * may not have loaded yet, call this with the id, if it has been loaded | 98 | * may not have loaded yet, call this with the id, if it has been loaded |
99 | * already, you'll immediately get a pointer, if not, it will write one | 99 | * already, you'll immediately get a pointer, if not, it will write one |
100 | * for you when the time comes. | 100 | * for you when the time comes. |
101 | */ | 101 | */ |
102 | void assocPtrID( void **ptr, uint32_t id ); | 102 | void assocPtrID( void **ptr, uint32_t id ); |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * For loading. Call this when you load an object that other things may | 105 | * For loading. Call this when you load an object that other things may |
106 | * have pointers to. It will assosiate every pointer that's been | 106 | * have pointers to. It will assosiate every pointer that's been |
107 | * registered with assocPtrID to the pointer passed in, and id passed | 107 | * registered with assocPtrID to the pointer passed in, and id passed |
108 | * in. It will also set things up so future calls to assocPtrID will | 108 | * in. It will also set things up so future calls to assocPtrID will |
109 | * automatically succeed immediately. | 109 | * automatically succeed immediately. |
110 | */ | 110 | */ |
111 | void readID( const void *ptr, uint32_t id ); | 111 | void readID( const void *ptr, uint32_t id ); |
112 | 112 | ||
113 | template<typename t> | 113 | template<typename t> |
114 | void setProp( const Bu::String &sId, const t &val ) | 114 | void setProp( const Bu::String &sId, const t &val ) |
115 | { | 115 | { |
116 | if( !hProps.has( sId ) ) | 116 | if( !hProps.has( sId ) ) |
117 | { | 117 | { |
118 | hProps.insert( sId, Variant() ); | 118 | hProps.insert( sId, Variant() ); |
119 | } | 119 | } |
120 | hProps.get( sId ) = val; | 120 | hProps.get( sId ) = val; |
121 | } | 121 | } |
122 | 122 | ||
123 | template<typename t> | 123 | template<typename t> |
124 | t getProp( const Bu::String &sId ) | 124 | t getProp( const Bu::String &sId ) |
125 | { | 125 | { |
126 | return hProps.get( sId ); | 126 | return hProps.get( sId ); |
127 | } | 127 | } |
128 | 128 | ||
129 | private: | 129 | private: |
130 | Stream &rStream; | 130 | Stream &rStream; |
131 | uint32_t nNextID; | 131 | uint32_t nNextID; |
132 | Hash<uint32_t,uint32_t> hPtrID; | 132 | Hash<uint32_t,uint32_t> hPtrID; |
133 | Hash<uint32_t,List<void **> > hPtrDest; | 133 | Hash<uint32_t,List<void **> > hPtrDest; |
134 | Hash<Bu::String, Variant> hProps; | 134 | Hash<Bu::String, Variant> hProps; |
135 | }; | 135 | }; |
136 | } | 136 | } |
137 | 137 | ||
138 | #endif | 138 | #endif |
diff --git a/src/stable/archivebase.cpp b/src/stable/archivebase.cpp index dcf08f4..d0d22ce 100644 --- a/src/stable/archivebase.cpp +++ b/src/stable/archivebase.cpp | |||
@@ -17,181 +17,181 @@ Bu::ArchiveBase::~ArchiveBase() | |||
17 | 17 | ||
18 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) | 18 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) |
19 | { | 19 | { |
20 | ar.write( &p, sizeof(p) ); | 20 | ar.write( &p, sizeof(p) ); |
21 | return ar; | 21 | return ar; |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) | 24 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) |
25 | { | 25 | { |
26 | ar.write( &p, sizeof(p) ); | 26 | ar.write( &p, sizeof(p) ); |
27 | return ar; | 27 | return ar; |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) | 30 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) |
31 | { | 31 | { |
32 | ar.write( &p, sizeof(p) ); | 32 | ar.write( &p, sizeof(p) ); |
33 | return ar; | 33 | return ar; |
34 | } | 34 | } |
35 | 35 | ||
36 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) | 36 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) |
37 | { | 37 | { |
38 | ar.write( &p, sizeof(p) ); | 38 | ar.write( &p, sizeof(p) ); |
39 | return ar; | 39 | return ar; |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) | 42 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) |
43 | { | 43 | { |
44 | ar.write( &p, sizeof(p) ); | 44 | ar.write( &p, sizeof(p) ); |
45 | return ar; | 45 | return ar; |
46 | } | 46 | } |
47 | 47 | ||
48 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) | 48 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) |
49 | { | 49 | { |
50 | ar.write( &p, sizeof(p) ); | 50 | ar.write( &p, sizeof(p) ); |
51 | return ar; | 51 | return ar; |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) | 54 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) |
55 | { | 55 | { |
56 | ar.write( &p, sizeof(p) ); | 56 | ar.write( &p, sizeof(p) ); |
57 | return ar; | 57 | return ar; |
58 | } | 58 | } |
59 | 59 | ||
60 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) | 60 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) |
61 | { | 61 | { |
62 | ar.write( &p, sizeof(p) ); | 62 | ar.write( &p, sizeof(p) ); |
63 | return ar; | 63 | return ar; |
64 | } | 64 | } |
65 | 65 | ||
66 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) | 66 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) |
67 | { | 67 | { |
68 | ar.write( &p, sizeof(p) ); | 68 | ar.write( &p, sizeof(p) ); |
69 | return ar; | 69 | return ar; |
70 | } | 70 | } |
71 | 71 | ||
72 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) | 72 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) |
73 | { | 73 | { |
74 | ar.write( &p, sizeof(p) ); | 74 | ar.write( &p, sizeof(p) ); |
75 | return ar; | 75 | return ar; |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) | 78 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) |
79 | { | 79 | { |
80 | ar.write( &p, sizeof(p) ); | 80 | ar.write( &p, sizeof(p) ); |
81 | return ar; | 81 | return ar; |
82 | } | 82 | } |
83 | 83 | ||
84 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) | 84 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) |
85 | { | 85 | { |
86 | ar.write( &p, sizeof(p) ); | 86 | ar.write( &p, sizeof(p) ); |
87 | return ar; | 87 | return ar; |
88 | } | 88 | } |
89 | 89 | ||
90 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) | 90 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) |
91 | { | 91 | { |
92 | ar.write( &p, sizeof(p) ); | 92 | ar.write( &p, sizeof(p) ); |
93 | return ar; | 93 | return ar; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) | 96 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) |
97 | { | 97 | { |
98 | ar.write( &p, sizeof(p) ); | 98 | ar.write( &p, sizeof(p) ); |
99 | return ar; | 99 | return ar; |
100 | } | 100 | } |
101 | 101 | ||
102 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) | 102 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) |
103 | { | 103 | { |
104 | ar.write( &p, sizeof(p) ); | 104 | ar.write( &p, sizeof(p) ); |
105 | return ar; | 105 | return ar; |
106 | } | 106 | } |
107 | 107 | ||
108 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) | 108 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) |
109 | { | 109 | { |
110 | ar.read( &p, sizeof(p) ); | 110 | ar.read( &p, sizeof(p) ); |
111 | return ar; | 111 | return ar; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) | 114 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) |
115 | { | 115 | { |
116 | ar.read( &p, sizeof(p) ); | 116 | ar.read( &p, sizeof(p) ); |
117 | return ar; | 117 | return ar; |
118 | } | 118 | } |
119 | 119 | ||
120 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) | 120 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) |
121 | { | 121 | { |
122 | ar.read( &p, sizeof(p) ); | 122 | ar.read( &p, sizeof(p) ); |
123 | return ar; | 123 | return ar; |
124 | } | 124 | } |
125 | 125 | ||
126 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) | 126 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) |
127 | { | 127 | { |
128 | ar.read( &p, sizeof(p) ); | 128 | ar.read( &p, sizeof(p) ); |
129 | return ar; | 129 | return ar; |
130 | } | 130 | } |
131 | 131 | ||
132 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) | 132 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) |
133 | { | 133 | { |
134 | ar.read( &p, sizeof(p) ); | 134 | ar.read( &p, sizeof(p) ); |
135 | return ar; | 135 | return ar; |
136 | } | 136 | } |
137 | 137 | ||
138 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) | 138 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) |
139 | { | 139 | { |
140 | ar.read( &p, sizeof(p) ); | 140 | ar.read( &p, sizeof(p) ); |
141 | return ar; | 141 | return ar; |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) | 144 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) |
145 | { | 145 | { |
146 | ar.read( &p, sizeof(p) ); | 146 | ar.read( &p, sizeof(p) ); |
147 | return ar; | 147 | return ar; |
148 | } | 148 | } |
149 | 149 | ||
150 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) | 150 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) |
151 | { | 151 | { |
152 | ar.read( &p, sizeof(p) ); | 152 | ar.read( &p, sizeof(p) ); |
153 | return ar; | 153 | return ar; |
154 | } | 154 | } |
155 | 155 | ||
156 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) | 156 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) |
157 | { | 157 | { |
158 | ar.read( &p, sizeof(p) ); | 158 | ar.read( &p, sizeof(p) ); |
159 | return ar; | 159 | return ar; |
160 | } | 160 | } |
161 | 161 | ||
162 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) | 162 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) |
163 | { | 163 | { |
164 | ar.read( &p, sizeof(p) ); | 164 | ar.read( &p, sizeof(p) ); |
165 | return ar; | 165 | return ar; |
166 | } | 166 | } |
167 | 167 | ||
168 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) | 168 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) |
169 | { | 169 | { |
170 | ar.read( &p, sizeof(p) ); | 170 | ar.read( &p, sizeof(p) ); |
171 | return ar; | 171 | return ar; |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) | 174 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) |
175 | { | 175 | { |
176 | ar.read( &p, sizeof(p) ); | 176 | ar.read( &p, sizeof(p) ); |
177 | return ar; | 177 | return ar; |
178 | } | 178 | } |
179 | 179 | ||
180 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) | 180 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) |
181 | { | 181 | { |
182 | ar.read( &p, sizeof(p) ); | 182 | ar.read( &p, sizeof(p) ); |
183 | return ar; | 183 | return ar; |
184 | } | 184 | } |
185 | 185 | ||
186 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) | 186 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) |
187 | { | 187 | { |
188 | ar.read( &p, sizeof(p) ); | 188 | ar.read( &p, sizeof(p) ); |
189 | return ar; | 189 | return ar; |
190 | } | 190 | } |
191 | 191 | ||
192 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) | 192 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) |
193 | { | 193 | { |
194 | ar.read( &p, sizeof(p) ); | 194 | ar.read( &p, sizeof(p) ); |
195 | return ar; | 195 | return ar; |
196 | } | 196 | } |
197 | 197 | ||
diff --git a/src/stable/archivebase.h b/src/stable/archivebase.h index 34ec1af..3f9e30f 100644 --- a/src/stable/archivebase.h +++ b/src/stable/archivebase.h | |||
@@ -13,63 +13,63 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class ArchiveBase | 16 | class ArchiveBase |
17 | { | 17 | { |
18 | public: | 18 | public: |
19 | ArchiveBase(); | 19 | ArchiveBase(); |
20 | virtual ~ArchiveBase(); | 20 | virtual ~ArchiveBase(); |
21 | 21 | ||
22 | virtual void close()=0; | 22 | virtual void close()=0; |
23 | virtual void write( const void *pData, size_t iLength )=0; | 23 | virtual void write( const void *pData, size_t iLength )=0; |
24 | virtual void read( void *pData, size_t iLength )=0; | 24 | virtual void read( void *pData, size_t iLength )=0; |
25 | virtual bool isLoading()=0; | 25 | virtual bool isLoading()=0; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | template<typename T> ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) | 28 | template<typename T> ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) |
29 | { | 29 | { |
30 | if( ar.isLoading() ) | 30 | if( ar.isLoading() ) |
31 | { | 31 | { |
32 | return ar >> dat; | 32 | return ar >> dat; |
33 | } | 33 | } |
34 | else | 34 | else |
35 | { | 35 | { |
36 | return ar << dat; | 36 | return ar << dat; |
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | ArchiveBase &operator<<( ArchiveBase &ar, bool p ); | 40 | ArchiveBase &operator<<( ArchiveBase &ar, bool p ); |
41 | ArchiveBase &operator<<( ArchiveBase &ar, char p ); | 41 | ArchiveBase &operator<<( ArchiveBase &ar, char p ); |
42 | ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); | 42 | ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); |
43 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); | 43 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); |
44 | ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); | 44 | ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); |
45 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); | 45 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); |
46 | ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); | 46 | ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); |
47 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); | 47 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); |
48 | ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); | 48 | ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); |
49 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); | 49 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); |
50 | ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); | 50 | ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); |
51 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); | 51 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); |
52 | ArchiveBase &operator<<( ArchiveBase &ar, float p ); | 52 | ArchiveBase &operator<<( ArchiveBase &ar, float p ); |
53 | ArchiveBase &operator<<( ArchiveBase &ar, double p ); | 53 | ArchiveBase &operator<<( ArchiveBase &ar, double p ); |
54 | ArchiveBase &operator<<( ArchiveBase &ar, long double p ); | 54 | ArchiveBase &operator<<( ArchiveBase &ar, long double p ); |
55 | 55 | ||
56 | ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); | 56 | ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); |
57 | ArchiveBase &operator>>( ArchiveBase &ar, char &p ); | 57 | ArchiveBase &operator>>( ArchiveBase &ar, char &p ); |
58 | ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); | 58 | ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); |
59 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); | 59 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); |
60 | ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); | 60 | ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); |
61 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); | 61 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); |
62 | ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); | 62 | ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); |
63 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); | 63 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); |
64 | ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); | 64 | ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); |
65 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); | 65 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); |
66 | ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); | 66 | ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); |
67 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); | 67 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); |
68 | ArchiveBase &operator>>( ArchiveBase &ar, float &p ); | 68 | ArchiveBase &operator>>( ArchiveBase &ar, float &p ); |
69 | ArchiveBase &operator>>( ArchiveBase &ar, double &p ); | 69 | ArchiveBase &operator>>( ArchiveBase &ar, double &p ); |
70 | ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); | 70 | ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); |
71 | 71 | ||
72 | 72 | ||
73 | }; | 73 | }; |
74 | 74 | ||
75 | #endif | 75 | #endif |
diff --git a/src/stable/array.h b/src/stable/array.h index f765e75..324c9ac 100644 --- a/src/stable/array.h +++ b/src/stable/array.h | |||
@@ -15,697 +15,697 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( ArrayException ) | 18 | subExceptionDecl( ArrayException ) |
19 | 19 | ||
20 | template<typename value, int inc, typename valuealloc> | 20 | template<typename value, int inc, typename valuealloc> |
21 | class Array; | 21 | class Array; |
22 | 22 | ||
23 | /** @cond DEVEL */ | 23 | /** @cond DEVEL */ |
24 | template<typename value, int inc, typename valuealloc> | 24 | template<typename value, int inc, typename valuealloc> |
25 | class ArrayCore | 25 | class ArrayCore |
26 | { | 26 | { |
27 | friend class Array<value, inc, valuealloc>; | 27 | friend class Array<value, inc, valuealloc>; |
28 | friend class SharedCore< | 28 | friend class SharedCore< |
29 | Array<value, inc, valuealloc>, | 29 | Array<value, inc, valuealloc>, |
30 | ArrayCore<value, inc, valuealloc> | 30 | ArrayCore<value, inc, valuealloc> |
31 | >; | 31 | >; |
32 | private: | 32 | private: |
33 | ArrayCore() : | 33 | ArrayCore() : |
34 | pData( NULL ), | 34 | pData( NULL ), |
35 | iSize( 0 ), | 35 | iSize( 0 ), |
36 | iCapacity( 0 ) | 36 | iCapacity( 0 ) |
37 | { } | 37 | { } |
38 | 38 | ||
39 | void setCapacity( int iNewLen ) | 39 | void setCapacity( int iNewLen ) |
40 | { | 40 | { |
41 | //clear(); | 41 | //clear(); |
42 | //iCapacity = iCapacity; | 42 | //iCapacity = iCapacity; |
43 | //pData = va.allocate( iCapacity ); | 43 | //pData = va.allocate( iCapacity ); |
44 | if( iNewLen <= iCapacity ) return; | 44 | if( iNewLen <= iCapacity ) return; |
45 | value *pNewData = va.allocate( iNewLen ); | 45 | value *pNewData = va.allocate( iNewLen ); |
46 | if( pData ) | 46 | if( pData ) |
47 | { | 47 | { |
48 | for( int j = 0; j < iSize; j++ ) | 48 | for( int j = 0; j < iSize; j++ ) |
49 | { | 49 | { |
50 | va.construct( &pNewData[j], pData[j] ); | 50 | va.construct( &pNewData[j], pData[j] ); |
51 | va.destroy( &pData[j] ); | 51 | va.destroy( &pData[j] ); |
52 | } | 52 | } |
53 | va.deallocate( pData, iCapacity ); | 53 | va.deallocate( pData, iCapacity ); |
54 | } | 54 | } |
55 | pData = pNewData; | 55 | pData = pNewData; |
56 | iCapacity = iNewLen; | 56 | iCapacity = iNewLen; |
57 | } | 57 | } |
58 | 58 | ||
59 | virtual ~ArrayCore() | 59 | virtual ~ArrayCore() |
60 | { | 60 | { |
61 | clear(); | 61 | clear(); |
62 | } | 62 | } |
63 | 63 | ||
64 | void clear() | 64 | void clear() |
65 | { | 65 | { |
66 | if( pData ) | 66 | if( pData ) |
67 | { | 67 | { |
68 | for( int j = 0; j < iSize; j++ ) | 68 | for( int j = 0; j < iSize; j++ ) |
69 | { | 69 | { |
70 | va.destroy( &pData[j] ); | 70 | va.destroy( &pData[j] ); |
71 | } | 71 | } |
72 | va.deallocate( pData, iCapacity ); | 72 | va.deallocate( pData, iCapacity ); |
73 | pData = NULL; | 73 | pData = NULL; |
74 | } | 74 | } |
75 | iSize = 0; | 75 | iSize = 0; |
76 | iCapacity = 0; | 76 | iCapacity = 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | void erase( int iPos ) | 79 | void erase( int iPos ) |
80 | { | 80 | { |
81 | for( int j = iPos; j < iSize; j++ ) | 81 | for( int j = iPos; j < iSize; j++ ) |
82 | { | 82 | { |
83 | va.destroy( &pData[j] ); | 83 | va.destroy( &pData[j] ); |
84 | if( j == iSize-1 ) | 84 | if( j == iSize-1 ) |
85 | { | 85 | { |
86 | iSize--; | 86 | iSize--; |
87 | return; | 87 | return; |
88 | } | 88 | } |
89 | va.construct( &pData[j], pData[j+1] ); | 89 | va.construct( &pData[j], pData[j+1] ); |
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | void swapErase( int iPos ) | 93 | void swapErase( int iPos ) |
94 | { | 94 | { |
95 | if( iPos == iSize-1 ) | 95 | if( iPos == iSize-1 ) |
96 | { | 96 | { |
97 | erase( iPos ); | 97 | erase( iPos ); |
98 | return; | 98 | return; |
99 | } | 99 | } |
100 | va.destroy( &pData[iPos] ); | 100 | va.destroy( &pData[iPos] ); |
101 | va.construct( &pData[iPos], pData[iSize-1] ); | 101 | va.construct( &pData[iPos], pData[iSize-1] ); |
102 | va.destroy( &pData[iSize-1] ); | 102 | va.destroy( &pData[iSize-1] ); |
103 | iSize--; | 103 | iSize--; |
104 | } | 104 | } |
105 | 105 | ||
106 | valuealloc va; | 106 | valuealloc va; |
107 | value *pData; | 107 | value *pData; |
108 | long iSize; | 108 | long iSize; |
109 | long iCapacity; | 109 | long iCapacity; |
110 | }; | 110 | }; |
111 | /** @endcond */ | 111 | /** @endcond */ |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Array type container, just like a normal array only flexible and keeps | 114 | * Array type container, just like a normal array only flexible and keeps |
115 | * track of your memory for you. | 115 | * track of your memory for you. |
116 | * | 116 | * |
117 | *@param value (typename) The type of data to store in your list | 117 | *@param value (typename) The type of data to store in your list |
118 | *@param valuealloc (typename) Memory Allocator for your value type | 118 | *@param valuealloc (typename) Memory Allocator for your value type |
119 | *@param linkalloc (typename) Memory Allocator for the list links. | 119 | *@param linkalloc (typename) Memory Allocator for the list links. |
120 | *@ingroup Containers | 120 | *@ingroup Containers |
121 | */ | 121 | */ |
122 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > | 122 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > |
123 | class Array : public SharedCore< | 123 | class Array : public SharedCore< |
124 | Array<value, inc, valuealloc>, | 124 | Array<value, inc, valuealloc>, |
125 | ArrayCore<value, inc, valuealloc> | 125 | ArrayCore<value, inc, valuealloc> |
126 | > | 126 | > |
127 | { | 127 | { |
128 | private: | 128 | private: |
129 | typedef class Array<value, inc, valuealloc> MyType; | 129 | typedef class Array<value, inc, valuealloc> MyType; |
130 | typedef class ArrayCore<value, inc, valuealloc> Core; | 130 | typedef class ArrayCore<value, inc, valuealloc> Core; |
131 | 131 | ||
132 | protected: | 132 | protected: |
133 | using SharedCore<MyType, Core>::core; | 133 | using SharedCore<MyType, Core>::core; |
134 | using SharedCore<MyType, Core>::_hardCopy; | 134 | using SharedCore<MyType, Core>::_hardCopy; |
135 | using SharedCore<MyType, Core>::_resetCore; | 135 | using SharedCore<MyType, Core>::_resetCore; |
136 | using SharedCore<MyType, Core>::_allocateCore; | 136 | using SharedCore<MyType, Core>::_allocateCore; |
137 | 137 | ||
138 | public: | 138 | public: |
139 | struct const_iterator; | 139 | struct const_iterator; |
140 | struct iterator; | 140 | struct iterator; |
141 | 141 | ||
142 | Array() | 142 | Array() |
143 | { | 143 | { |
144 | } | 144 | } |
145 | 145 | ||
146 | Array( const MyType &src ) : | 146 | Array( const MyType &src ) : |
147 | SharedCore<MyType, Core >( src ) | 147 | SharedCore<MyType, Core >( src ) |
148 | { | 148 | { |
149 | } | 149 | } |
150 | 150 | ||
151 | Array( long iSetCap ) | 151 | Array( long iSetCap ) |
152 | { | 152 | { |
153 | setCapacity( iSetCap ); | 153 | setCapacity( iSetCap ); |
154 | } | 154 | } |
155 | 155 | ||
156 | ~Array() | 156 | ~Array() |
157 | { | 157 | { |
158 | } | 158 | } |
159 | 159 | ||
160 | bool operator==( const MyType &src ) const | 160 | bool operator==( const MyType &src ) const |
161 | { | 161 | { |
162 | if( core == src.core ) | 162 | if( core == src.core ) |
163 | return true; | 163 | return true; |
164 | if( core->iSize != src.core->iSize ) | 164 | if( core->iSize != src.core->iSize ) |
165 | return false; | 165 | return false; |
166 | 166 | ||
167 | for( int j = 0; j < core->iSize; j++ ) | 167 | for( int j = 0; j < core->iSize; j++ ) |
168 | { | 168 | { |
169 | if( core->pData[j] != src.core->pData[j] ) | 169 | if( core->pData[j] != src.core->pData[j] ) |
170 | return false; | 170 | return false; |
171 | } | 171 | } |
172 | return true; | 172 | return true; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool operator!=( const MyType &src ) const | 175 | bool operator!=( const MyType &src ) const |
176 | { | 176 | { |
177 | return !(*this == src); | 177 | return !(*this == src); |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * Clear the array. | 181 | * Clear the array. |
182 | */ | 182 | */ |
183 | void clear() | 183 | void clear() |
184 | { | 184 | { |
185 | _resetCore(); | 185 | _resetCore(); |
186 | } | 186 | } |
187 | 187 | ||
188 | MyType &append( const value &rVal ) | 188 | MyType &append( const value &rVal ) |
189 | { | 189 | { |
190 | _hardCopy(); | 190 | _hardCopy(); |
191 | if( core->iSize == core->iCapacity ) | 191 | if( core->iSize == core->iCapacity ) |
192 | { | 192 | { |
193 | core->setCapacity( core->iCapacity + inc ); | 193 | core->setCapacity( core->iCapacity + inc ); |
194 | } | 194 | } |
195 | 195 | ||
196 | core->va.construct( &core->pData[core->iSize++], rVal ); | 196 | core->va.construct( &core->pData[core->iSize++], rVal ); |
197 | 197 | ||
198 | return *this; | 198 | return *this; |
199 | } | 199 | } |
200 | 200 | ||
201 | MyType &append( const MyType &rVal ) | 201 | MyType &append( const MyType &rVal ) |
202 | { | 202 | { |
203 | _hardCopy(); | 203 | _hardCopy(); |
204 | 204 | ||
205 | if( core->iSize + rVal.core->iSize > core->iCapacity ) | 205 | if( core->iSize + rVal.core->iSize > core->iCapacity ) |
206 | { | 206 | { |
207 | core->setCapacity( core->iSize + rVal.core->iSize + inc ); | 207 | core->setCapacity( core->iSize + rVal.core->iSize + inc ); |
208 | } | 208 | } |
209 | 209 | ||
210 | for( int j = 0; j < rVal.core->iSize; j++ ) | 210 | for( int j = 0; j < rVal.core->iSize; j++ ) |
211 | { | 211 | { |
212 | core->va.construct( | 212 | core->va.construct( |
213 | &core->pData[core->iSize++], | 213 | &core->pData[core->iSize++], |
214 | rVal.core->pData[j] | 214 | rVal.core->pData[j] |
215 | ); | 215 | ); |
216 | } | 216 | } |
217 | 217 | ||
218 | return *this; | 218 | return *this; |
219 | } | 219 | } |
220 | 220 | ||
221 | //operator | 221 | //operator |
222 | value &operator[]( long iIndex ) | 222 | value &operator[]( long iIndex ) |
223 | { | 223 | { |
224 | _hardCopy(); | 224 | _hardCopy(); |
225 | if( iIndex < 0 || iIndex >= core->iSize ) | 225 | if( iIndex < 0 || iIndex >= core->iSize ) |
226 | throw ArrayException( | 226 | throw ArrayException( |
227 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 227 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
228 | 228 | ||
229 | return core->pData[iIndex]; | 229 | return core->pData[iIndex]; |
230 | } | 230 | } |
231 | 231 | ||
232 | const value &operator[]( long iIndex ) const | 232 | const value &operator[]( long iIndex ) const |
233 | { | 233 | { |
234 | if( iIndex < 0 || iIndex >= core->iSize ) | 234 | if( iIndex < 0 || iIndex >= core->iSize ) |
235 | throw ArrayException( | 235 | throw ArrayException( |
236 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 236 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
237 | 237 | ||
238 | return core->pData[iIndex]; | 238 | return core->pData[iIndex]; |
239 | } | 239 | } |
240 | 240 | ||
241 | value &get( long iIndex ) | 241 | value &get( long iIndex ) |
242 | { | 242 | { |
243 | _hardCopy(); | 243 | _hardCopy(); |
244 | if( iIndex < 0 || iIndex >= core->iSize ) | 244 | if( iIndex < 0 || iIndex >= core->iSize ) |
245 | throw ArrayException( | 245 | throw ArrayException( |
246 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 246 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
247 | 247 | ||
248 | return core->pData[iIndex]; | 248 | return core->pData[iIndex]; |
249 | } | 249 | } |
250 | 250 | ||
251 | const value &get( long iIndex ) const | 251 | const value &get( long iIndex ) const |
252 | { | 252 | { |
253 | if( iIndex < 0 || iIndex >= core->iSize ) | 253 | if( iIndex < 0 || iIndex >= core->iSize ) |
254 | throw ArrayException( | 254 | throw ArrayException( |
255 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 255 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
256 | 256 | ||
257 | return core->pData[iIndex]; | 257 | return core->pData[iIndex]; |
258 | } | 258 | } |
259 | 259 | ||
260 | value &first() | 260 | value &first() |
261 | { | 261 | { |
262 | _hardCopy(); | 262 | _hardCopy(); |
263 | return core->pData[0]; | 263 | return core->pData[0]; |
264 | } | 264 | } |
265 | 265 | ||
266 | const value &first() const | 266 | const value &first() const |
267 | { | 267 | { |
268 | return core->pData[0]; | 268 | return core->pData[0]; |
269 | } | 269 | } |
270 | 270 | ||
271 | value &last() | 271 | value &last() |
272 | { | 272 | { |
273 | _hardCopy(); | 273 | _hardCopy(); |
274 | return core->pData[core->iSize-1]; | 274 | return core->pData[core->iSize-1]; |
275 | } | 275 | } |
276 | 276 | ||
277 | const value &last() const | 277 | const value &last() const |
278 | { | 278 | { |
279 | return core->pData[core->iSize-1]; | 279 | return core->pData[core->iSize-1]; |
280 | } | 280 | } |
281 | 281 | ||
282 | /** | 282 | /** |
283 | * Returns true if the array is empty. The capacity has no bearing on | 283 | * Returns true if the array is empty. The capacity has no bearing on |
284 | * this, only the size. | 284 | * this, only the size. |
285 | */ | 285 | */ |
286 | bool isEmpty() const | 286 | bool isEmpty() const |
287 | { | 287 | { |
288 | return core->iSize==0; | 288 | return core->iSize==0; |
289 | } | 289 | } |
290 | 290 | ||
291 | /** | 291 | /** |
292 | * Get the current size of the array. | 292 | * Get the current size of the array. |
293 | *@returns The current size of the array. | 293 | *@returns The current size of the array. |
294 | */ | 294 | */ |
295 | long getSize() const | 295 | long getSize() const |
296 | { | 296 | { |
297 | return core->iSize; | 297 | return core->iSize; |
298 | } | 298 | } |
299 | 299 | ||
300 | /** | 300 | /** |
301 | * Get the capacity of the array. This number will grow as data is | 301 | * Get the capacity of the array. This number will grow as data is |
302 | * added, and is mainly for the curious, it doesn't really determine | 302 | * added, and is mainly for the curious, it doesn't really determine |
303 | * much for the end user. | 303 | * much for the end user. |
304 | *@returns The current capacity of the array. | 304 | *@returns The current capacity of the array. |
305 | */ | 305 | */ |
306 | long getCapacity() const | 306 | long getCapacity() const |
307 | { | 307 | { |
308 | return core->iCapacity; | 308 | return core->iCapacity; |
309 | } | 309 | } |
310 | 310 | ||
311 | /** | 311 | /** |
312 | * Change the capacity of the array, very useful if you know you'll be | 312 | * Change the capacity of the array, very useful if you know you'll be |
313 | * adding a large amount of already counted items to the array, makes | 313 | * adding a large amount of already counted items to the array, makes |
314 | * the appending much faster afterwords. | 314 | * the appending much faster afterwords. |
315 | *@param iNewLen The new capacity of the array. | 315 | *@param iNewLen The new capacity of the array. |
316 | *@todo Set this up so it can reduce the size of the array as well as | 316 | *@todo Set this up so it can reduce the size of the array as well as |
317 | * make it bigger. | 317 | * make it bigger. |
318 | */ | 318 | */ |
319 | void setCapacity( long iNewLen ) | 319 | void setCapacity( long iNewLen ) |
320 | { | 320 | { |
321 | _hardCopy(); | 321 | _hardCopy(); |
322 | core->setCapacity( iNewLen ); | 322 | core->setCapacity( iNewLen ); |
323 | } | 323 | } |
324 | 324 | ||
325 | typedef struct iterator | 325 | typedef struct iterator |
326 | { | 326 | { |
327 | friend class Array<value, inc, valuealloc>; | 327 | friend class Array<value, inc, valuealloc>; |
328 | private: | 328 | private: |
329 | iterator( MyType &src, long iPos=0 ) : | 329 | iterator( MyType &src, long iPos=0 ) : |
330 | src( src ), | 330 | src( src ), |
331 | iPos( iPos ) | 331 | iPos( iPos ) |
332 | { | 332 | { |
333 | if( this->iPos >= src.getSize() ) | 333 | if( this->iPos >= src.getSize() ) |
334 | this->iPos = -1; | 334 | this->iPos = -1; |
335 | } | 335 | } |
336 | 336 | ||
337 | MyType &src; | 337 | MyType &src; |
338 | long iPos; | 338 | long iPos; |
339 | 339 | ||
340 | public: | 340 | public: |
341 | iterator operator++( int ) | 341 | iterator operator++( int ) |
342 | { | 342 | { |
343 | if( iPos < 0 ) | 343 | if( iPos < 0 ) |
344 | throw ArrayException( | 344 | throw ArrayException( |
345 | "Cannot increment iterator past end of array."); | 345 | "Cannot increment iterator past end of array."); |
346 | iPos++; | 346 | iPos++; |
347 | if( iPos >= src.getSize() ) | 347 | if( iPos >= src.getSize() ) |
348 | iPos = -1; | 348 | iPos = -1; |
349 | return *this; | 349 | return *this; |
350 | } | 350 | } |
351 | 351 | ||
352 | iterator operator++() | 352 | iterator operator++() |
353 | { | 353 | { |
354 | if( iPos >= 0 ) | 354 | if( iPos >= 0 ) |
355 | iPos++; | 355 | iPos++; |
356 | if( iPos >= src.getSize() ) | 356 | if( iPos >= src.getSize() ) |
357 | iPos = -1; | 357 | iPos = -1; |
358 | return *this; | 358 | return *this; |
359 | } | 359 | } |
360 | 360 | ||
361 | iterator operator+( int iAmnt ) | 361 | iterator operator+( int iAmnt ) |
362 | { | 362 | { |
363 | if( iPos < 0 ) | 363 | if( iPos < 0 ) |
364 | throw ArrayException( | 364 | throw ArrayException( |
365 | "Cannot increment iterator past end of array."); | 365 | "Cannot increment iterator past end of array."); |
366 | iPos += iAmnt; | 366 | iPos += iAmnt; |
367 | if( iPos >= src.getSize() ) | 367 | if( iPos >= src.getSize() ) |
368 | iPos = -1; | 368 | iPos = -1; |
369 | return *this; | 369 | return *this; |
370 | } | 370 | } |
371 | 371 | ||
372 | iterator operator--( int ) | 372 | iterator operator--( int ) |
373 | { | 373 | { |
374 | if( iPos < 0 ) | 374 | if( iPos < 0 ) |
375 | throw ArrayException( | 375 | throw ArrayException( |
376 | "Cannot increment iterator past end of array."); | 376 | "Cannot increment iterator past end of array."); |
377 | iPos--; | 377 | iPos--; |
378 | if( iPos < 0 ) | 378 | if( iPos < 0 ) |
379 | iPos = -1; | 379 | iPos = -1; |
380 | return *this; | 380 | return *this; |
381 | } | 381 | } |
382 | 382 | ||
383 | iterator operator--() | 383 | iterator operator--() |
384 | { | 384 | { |
385 | if( iPos < src.getSize() ) | 385 | if( iPos < src.getSize() ) |
386 | iPos--; | 386 | iPos--; |
387 | if( iPos <= 0 ) | 387 | if( iPos <= 0 ) |
388 | iPos = -1; | 388 | iPos = -1; |
389 | return *this; | 389 | return *this; |
390 | } | 390 | } |
391 | 391 | ||
392 | iterator operator-( int iAmnt ) | 392 | iterator operator-( int iAmnt ) |
393 | { | 393 | { |
394 | if( iPos < src.getSize() ) | 394 | if( iPos < src.getSize() ) |
395 | iPos -= iAmnt; | 395 | iPos -= iAmnt; |
396 | if( iPos <= 0 ) | 396 | if( iPos <= 0 ) |
397 | iPos = -1; | 397 | iPos = -1; |
398 | return *this; | 398 | return *this; |
399 | } | 399 | } |
400 | 400 | ||
401 | bool operator==( const iterator &oth ) const | 401 | bool operator==( const iterator &oth ) const |
402 | { | 402 | { |
403 | return iPos == oth.iPos; | 403 | return iPos == oth.iPos; |
404 | } | 404 | } |
405 | 405 | ||
406 | bool operator!=( const iterator &oth ) const | 406 | bool operator!=( const iterator &oth ) const |
407 | { | 407 | { |
408 | return iPos != oth.iPos; | 408 | return iPos != oth.iPos; |
409 | } | 409 | } |
410 | 410 | ||
411 | iterator operator=( const iterator &oth ) | 411 | iterator operator=( const iterator &oth ) |
412 | { | 412 | { |
413 | if( &src != &oth.src ) | 413 | if( &src != &oth.src ) |
414 | throw ArrayException( | 414 | throw ArrayException( |
415 | "Cannot mix iterators from different array objects."); | 415 | "Cannot mix iterators from different array objects."); |
416 | iPos = oth.iPos; | 416 | iPos = oth.iPos; |
417 | } | 417 | } |
418 | 418 | ||
419 | value &operator*() | 419 | value &operator*() |
420 | { | 420 | { |
421 | if( iPos < 0 ) | 421 | if( iPos < 0 ) |
422 | throw ArrayException( | 422 | throw ArrayException( |
423 | "Cannot dereference finished iterator."); | 423 | "Cannot dereference finished iterator."); |
424 | return src[iPos]; | 424 | return src[iPos]; |
425 | } | 425 | } |
426 | 426 | ||
427 | long getIndex() const | 427 | long getIndex() const |
428 | { | 428 | { |
429 | return iPos; | 429 | return iPos; |
430 | } | 430 | } |
431 | 431 | ||
432 | operator bool() const | 432 | operator bool() const |
433 | { | 433 | { |
434 | return iPos >= 0; | 434 | return iPos >= 0; |
435 | } | 435 | } |
436 | 436 | ||
437 | bool isValid() const | 437 | bool isValid() const |
438 | { | 438 | { |
439 | return iPos >= 0; | 439 | return iPos >= 0; |
440 | } | 440 | } |
441 | } iterator; | 441 | } iterator; |
442 | 442 | ||
443 | typedef struct const_iterator | 443 | typedef struct const_iterator |
444 | { | 444 | { |
445 | friend class Array<value, inc, valuealloc>; | 445 | friend class Array<value, inc, valuealloc>; |
446 | private: | 446 | private: |
447 | const_iterator( const MyType &src, long iPos=0 ) : | 447 | const_iterator( const MyType &src, long iPos=0 ) : |
448 | src( src ), | 448 | src( src ), |
449 | iPos( iPos ) | 449 | iPos( iPos ) |
450 | { | 450 | { |
451 | if( this->iPos >= src.getSize() ) | 451 | if( this->iPos >= src.getSize() ) |
452 | this->iPos = -1; | 452 | this->iPos = -1; |
453 | } | 453 | } |
454 | 454 | ||
455 | const MyType &src; | 455 | const MyType &src; |
456 | long iPos; | 456 | long iPos; |
457 | 457 | ||
458 | public: | 458 | public: |
459 | const_iterator( iterator &rSrc ) : | 459 | const_iterator( iterator &rSrc ) : |
460 | src( rSrc.src ), | 460 | src( rSrc.src ), |
461 | iPos( rSrc.iPos ) | 461 | iPos( rSrc.iPos ) |
462 | { | 462 | { |
463 | } | 463 | } |
464 | const_iterator operator++( int ) | 464 | const_iterator operator++( int ) |
465 | { | 465 | { |
466 | if( iPos < 0 ) | 466 | if( iPos < 0 ) |
467 | throw ArrayException( | 467 | throw ArrayException( |
468 | "Cannot increment iterator past end of array."); | 468 | "Cannot increment iterator past end of array."); |
469 | iPos++; | 469 | iPos++; |
470 | if( iPos >= src.getSize() ) | 470 | if( iPos >= src.getSize() ) |
471 | iPos = -1; | 471 | iPos = -1; |
472 | return *this; | 472 | return *this; |
473 | } | 473 | } |
474 | 474 | ||
475 | const_iterator operator++() | 475 | const_iterator operator++() |
476 | { | 476 | { |
477 | if( iPos >= 0 ) | 477 | if( iPos >= 0 ) |
478 | iPos++; | 478 | iPos++; |
479 | if( iPos >= src.getSize() ) | 479 | if( iPos >= src.getSize() ) |
480 | iPos = -1; | 480 | iPos = -1; |
481 | return *this; | 481 | return *this; |
482 | } | 482 | } |
483 | 483 | ||
484 | const_iterator operator--( int ) | 484 | const_iterator operator--( int ) |
485 | { | 485 | { |
486 | if( iPos < 0 ) | 486 | if( iPos < 0 ) |
487 | throw ArrayException( | 487 | throw ArrayException( |
488 | "Cannot increment iterator past end of array."); | 488 | "Cannot increment iterator past end of array."); |
489 | iPos--; | 489 | iPos--; |
490 | if( iPos < 0 ) | 490 | if( iPos < 0 ) |
491 | iPos = -1; | 491 | iPos = -1; |
492 | return *this; | 492 | return *this; |
493 | } | 493 | } |
494 | 494 | ||
495 | const_iterator operator--() | 495 | const_iterator operator--() |
496 | { | 496 | { |
497 | if( iPos < src.getSize() ) | 497 | if( iPos < src.getSize() ) |
498 | iPos--; | 498 | iPos--; |
499 | if( iPos <= 0 ) | 499 | if( iPos <= 0 ) |
500 | iPos = -1; | 500 | iPos = -1; |
501 | return *this; | 501 | return *this; |
502 | } | 502 | } |
503 | 503 | ||
504 | bool operator==( const const_iterator &oth ) const | 504 | bool operator==( const const_iterator &oth ) const |
505 | { | 505 | { |
506 | return iPos == oth.iPos; | 506 | return iPos == oth.iPos; |
507 | } | 507 | } |
508 | 508 | ||
509 | bool operator!=( const const_iterator &oth ) const | 509 | bool operator!=( const const_iterator &oth ) const |
510 | { | 510 | { |
511 | return iPos != oth.iPos; | 511 | return iPos != oth.iPos; |
512 | } | 512 | } |
513 | 513 | ||
514 | const_iterator operator=( const const_iterator &oth ) | 514 | const_iterator operator=( const const_iterator &oth ) |
515 | { | 515 | { |
516 | if( &src != &oth.src ) | 516 | if( &src != &oth.src ) |
517 | throw ArrayException( | 517 | throw ArrayException( |
518 | "Cannot mix iterators from different array objects."); | 518 | "Cannot mix iterators from different array objects."); |
519 | iPos = oth.iPos; | 519 | iPos = oth.iPos; |
520 | } | 520 | } |
521 | 521 | ||
522 | const value &operator*() const | 522 | const value &operator*() const |
523 | { | 523 | { |
524 | if( iPos < 0 ) | 524 | if( iPos < 0 ) |
525 | throw ArrayException( | 525 | throw ArrayException( |
526 | "Cannot dereference finished iterator."); | 526 | "Cannot dereference finished iterator."); |
527 | return src[iPos]; | 527 | return src[iPos]; |
528 | } | 528 | } |
529 | 529 | ||
530 | long getIndex() const | 530 | long getIndex() const |
531 | { | 531 | { |
532 | return iPos; | 532 | return iPos; |
533 | } | 533 | } |
534 | 534 | ||
535 | operator bool() const | 535 | operator bool() const |
536 | { | 536 | { |
537 | return iPos >= 0; | 537 | return iPos >= 0; |
538 | } | 538 | } |
539 | 539 | ||
540 | bool isValid() const | 540 | bool isValid() const |
541 | { | 541 | { |
542 | return iPos >= 0; | 542 | return iPos >= 0; |
543 | } | 543 | } |
544 | } const_iterator; | 544 | } const_iterator; |
545 | 545 | ||
546 | iterator begin() | 546 | iterator begin() |
547 | { | 547 | { |
548 | return iterator( *this ); | 548 | return iterator( *this ); |
549 | } | 549 | } |
550 | 550 | ||
551 | const_iterator begin() const | 551 | const_iterator begin() const |
552 | { | 552 | { |
553 | return const_iterator( *this ); | 553 | return const_iterator( *this ); |
554 | } | 554 | } |
555 | 555 | ||
556 | iterator end() | 556 | iterator end() |
557 | { | 557 | { |
558 | return iterator( *this, -1 ); | 558 | return iterator( *this, -1 ); |
559 | } | 559 | } |
560 | 560 | ||
561 | const_iterator end() const | 561 | const_iterator end() const |
562 | { | 562 | { |
563 | return const_iterator( *this, -1 ); | 563 | return const_iterator( *this, -1 ); |
564 | } | 564 | } |
565 | 565 | ||
566 | MyType &insert( iterator i, const value &rVal ) | 566 | MyType &insert( iterator i, const value &rVal ) |
567 | { | 567 | { |
568 | if( i.iPos == -1 ) | 568 | if( i.iPos == -1 ) |
569 | { | 569 | { |
570 | append( rVal ); | 570 | append( rVal ); |
571 | return *this; | 571 | return *this; |
572 | } | 572 | } |
573 | 573 | ||
574 | _hardCopy(); | 574 | _hardCopy(); |
575 | if( core->iSize == core->iCapacity ) | 575 | if( core->iSize == core->iCapacity ) |
576 | { | 576 | { |
577 | core->setCapacity( core->iCapacity + inc ); | 577 | core->setCapacity( core->iCapacity + inc ); |
578 | } | 578 | } |
579 | core->iSize++; | 579 | core->iSize++; |
580 | 580 | ||
581 | core->va.construct( | 581 | core->va.construct( |
582 | &core->pData[core->iSize-1], | 582 | &core->pData[core->iSize-1], |
583 | core->pData[core->iSize-2] | 583 | core->pData[core->iSize-2] |
584 | ); | 584 | ); |
585 | for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) | 585 | for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) |
586 | { | 586 | { |
587 | core->va.destroy( &core->pData[iPos] ); | 587 | core->va.destroy( &core->pData[iPos] ); |
588 | core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); | 588 | core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); |
589 | } | 589 | } |
590 | core->va.destroy( &core->pData[i.iPos] ); | 590 | core->va.destroy( &core->pData[i.iPos] ); |
591 | core->va.construct( &core->pData[i.iPos], rVal ); | 591 | core->va.construct( &core->pData[i.iPos], rVal ); |
592 | 592 | ||
593 | return *this; | 593 | return *this; |
594 | } | 594 | } |
595 | 595 | ||
596 | /** | 596 | /** |
597 | * If order is important, use this. It will delete the suggested item | 597 | * If order is important, use this. It will delete the suggested item |
598 | * and move the rest of the data up a spot. This is a time O(n) | 598 | * and move the rest of the data up a spot. This is a time O(n) |
599 | * operation. If the order isn't important, check swapErase | 599 | * operation. If the order isn't important, check swapErase |
600 | */ | 600 | */ |
601 | void erase( iterator i ) | 601 | void erase( iterator i ) |
602 | { | 602 | { |
603 | _hardCopy(); | 603 | _hardCopy(); |
604 | core->erase( i.iPos ); | 604 | core->erase( i.iPos ); |
605 | } | 605 | } |
606 | 606 | ||
607 | void erase( const value &v ) | 607 | void erase( const value &v ) |
608 | { | 608 | { |
609 | _hardCopy(); | 609 | _hardCopy(); |
610 | for( int j = 0; j < core->iSize; j++ ) | 610 | for( int j = 0; j < core->iSize; j++ ) |
611 | { | 611 | { |
612 | if( core->pData[j] == v ) | 612 | if( core->pData[j] == v ) |
613 | { | 613 | { |
614 | core->erase( j ); | 614 | core->erase( j ); |
615 | return; | 615 | return; |
616 | } | 616 | } |
617 | } | 617 | } |
618 | } | 618 | } |
619 | 619 | ||
620 | void eraseLast() | 620 | void eraseLast() |
621 | { | 621 | { |
622 | _hardCopy(); | 622 | _hardCopy(); |
623 | core->erase( core->iSize-1 ); | 623 | core->erase( core->iSize-1 ); |
624 | } | 624 | } |
625 | 625 | ||
626 | void eraseFirst() | 626 | void eraseFirst() |
627 | { | 627 | { |
628 | _hardCopy(); | 628 | _hardCopy(); |
629 | core->erase( 0 ); | 629 | core->erase( 0 ); |
630 | } | 630 | } |
631 | 631 | ||
632 | /** | 632 | /** |
633 | * In order to make swapErase faster, what it does is swap the given | 633 | * In order to make swapErase faster, what it does is swap the given |
634 | * item in the array with the last item, then make the array shorter | 634 | * item in the array with the last item, then make the array shorter |
635 | * by one. It changes the order of the elements in the array, so it | 635 | * by one. It changes the order of the elements in the array, so it |
636 | * should be used carefully, but it is time O(1) instead of O(n) like | 636 | * should be used carefully, but it is time O(1) instead of O(n) like |
637 | * erase. | 637 | * erase. |
638 | */ | 638 | */ |
639 | void swapErase( iterator i ) | 639 | void swapErase( iterator i ) |
640 | { | 640 | { |
641 | _hardCopy(); | 641 | _hardCopy(); |
642 | core->swapErase( i.iPos ); | 642 | core->swapErase( i.iPos ); |
643 | } | 643 | } |
644 | 644 | ||
645 | protected: | 645 | protected: |
646 | virtual Core *_copyCore( Core *src ) | 646 | virtual Core *_copyCore( Core *src ) |
647 | { | 647 | { |
648 | Core *pRet = _allocateCore(); | 648 | Core *pRet = _allocateCore(); |
649 | pRet->setCapacity( src->iCapacity ); | 649 | pRet->setCapacity( src->iCapacity ); |
650 | pRet->iSize = src->iSize; | 650 | pRet->iSize = src->iSize; |
651 | for( int j = 0; j < src->iSize; j++ ) | 651 | for( int j = 0; j < src->iSize; j++ ) |
652 | { | 652 | { |
653 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); | 653 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); |
654 | } | 654 | } |
655 | return pRet; | 655 | return pRet; |
656 | } | 656 | } |
657 | 657 | ||
658 | private: | 658 | private: |
659 | }; | 659 | }; |
660 | 660 | ||
661 | class Formatter; | 661 | class Formatter; |
662 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 662 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
663 | Formatter &operator<<( Formatter &rOut, signed char c ); | 663 | Formatter &operator<<( Formatter &rOut, signed char c ); |
664 | template<typename value> | 664 | template<typename value> |
665 | Formatter &operator<<( Formatter &f, const Bu::Array<value> &a ) | 665 | Formatter &operator<<( Formatter &f, const Bu::Array<value> &a ) |
666 | { | 666 | { |
667 | f << '['; | 667 | f << '['; |
668 | for( typename Bu::Array<value>::const_iterator i = a.begin(); i; i++ ) | 668 | for( typename Bu::Array<value>::const_iterator i = a.begin(); i; i++ ) |
669 | { | 669 | { |
670 | if( i != a.begin() ) | 670 | if( i != a.begin() ) |
671 | f << ", "; | 671 | f << ", "; |
672 | f << *i; | 672 | f << *i; |
673 | } | 673 | } |
674 | f << ']'; | 674 | f << ']'; |
675 | 675 | ||
676 | return f; | 676 | return f; |
677 | } | 677 | } |
678 | 678 | ||
679 | template<typename value, int inc, typename valuealloc> | 679 | template<typename value, int inc, typename valuealloc> |
680 | ArchiveBase &operator<<( ArchiveBase &ar, | 680 | ArchiveBase &operator<<( ArchiveBase &ar, |
681 | const Array<value, inc, valuealloc> &h ) | 681 | const Array<value, inc, valuealloc> &h ) |
682 | { | 682 | { |
683 | ar << h.getSize(); | 683 | ar << h.getSize(); |
684 | for( typename Array<value, inc, valuealloc>::const_iterator i = | 684 | for( typename Array<value, inc, valuealloc>::const_iterator i = |
685 | h.begin(); i != h.end(); i++ ) | 685 | h.begin(); i != h.end(); i++ ) |
686 | { | 686 | { |
687 | ar << (*i); | 687 | ar << (*i); |
688 | } | 688 | } |
689 | 689 | ||
690 | return ar; | 690 | return ar; |
691 | } | 691 | } |
692 | 692 | ||
693 | template<typename value, int inc, typename valuealloc> | 693 | template<typename value, int inc, typename valuealloc> |
694 | ArchiveBase &operator>>(ArchiveBase &ar, Array<value, inc, valuealloc> &h ) | 694 | ArchiveBase &operator>>(ArchiveBase &ar, Array<value, inc, valuealloc> &h ) |
695 | { | 695 | { |
696 | h.clear(); | 696 | h.clear(); |
697 | long nSize; | 697 | long nSize; |
698 | ar >> nSize; | 698 | ar >> nSize; |
699 | 699 | ||
700 | h.setCapacity( nSize ); | 700 | h.setCapacity( nSize ); |
701 | for( long j = 0; j < nSize; j++ ) | 701 | for( long j = 0; j < nSize; j++ ) |
702 | { | 702 | { |
703 | value v; | 703 | value v; |
704 | ar >> v; | 704 | ar >> v; |
705 | h.append( v ); | 705 | h.append( v ); |
706 | } | 706 | } |
707 | return ar; | 707 | return ar; |
708 | } | 708 | } |
709 | 709 | ||
710 | } | 710 | } |
711 | 711 | ||
diff --git a/src/stable/atom.h b/src/stable/atom.h index 105c29a..9679ab6 100644 --- a/src/stable/atom.h +++ b/src/stable/atom.h | |||
@@ -15,133 +15,133 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * | 19 | * |
20 | *@ingroup Containers | 20 | *@ingroup Containers |
21 | */ | 21 | */ |
22 | template <typename t, typename talloc=std::allocator<t> > | 22 | template <typename t, typename talloc=std::allocator<t> > |
23 | class Atom | 23 | class Atom |
24 | { | 24 | { |
25 | private: | 25 | private: |
26 | typedef struct Atom<t, talloc> MyType; | 26 | typedef struct Atom<t, talloc> MyType; |
27 | 27 | ||
28 | public: | 28 | public: |
29 | Atom() : | 29 | Atom() : |
30 | pData( NULL ) | 30 | pData( NULL ) |
31 | { | 31 | { |
32 | } | 32 | } |
33 | 33 | ||
34 | Atom( const MyType &oth ) : | 34 | Atom( const MyType &oth ) : |
35 | pData( NULL ) | 35 | pData( NULL ) |
36 | { | 36 | { |
37 | if( oth.pData ) | 37 | if( oth.pData ) |
38 | set( *oth.pData ); | 38 | set( *oth.pData ); |
39 | } | 39 | } |
40 | 40 | ||
41 | Atom( const t &oth ) : | 41 | Atom( const t &oth ) : |
42 | pData( NULL ) | 42 | pData( NULL ) |
43 | { | 43 | { |
44 | set( oth ); | 44 | set( oth ); |
45 | } | 45 | } |
46 | 46 | ||
47 | virtual ~Atom() | 47 | virtual ~Atom() |
48 | { | 48 | { |
49 | clear(); | 49 | clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | bool has() const | 52 | bool has() const |
53 | { | 53 | { |
54 | return (pData != NULL); | 54 | return (pData != NULL); |
55 | } | 55 | } |
56 | 56 | ||
57 | void set( const t &val ) | 57 | void set( const t &val ) |
58 | { | 58 | { |
59 | clear(); | 59 | clear(); |
60 | pData = ta.allocate( 1 ); | 60 | pData = ta.allocate( 1 ); |
61 | ta.construct( pData, val ); | 61 | ta.construct( pData, val ); |
62 | } | 62 | } |
63 | 63 | ||
64 | t &get() | 64 | t &get() |
65 | { | 65 | { |
66 | if( !pData ) | 66 | if( !pData ) |
67 | throw Bu::ExceptionBase("Not set"); | 67 | throw Bu::ExceptionBase("Not set"); |
68 | return *pData; | 68 | return *pData; |
69 | } | 69 | } |
70 | 70 | ||
71 | const t &get() const | 71 | const t &get() const |
72 | { | 72 | { |
73 | if( !pData ) | 73 | if( !pData ) |
74 | throw Bu::ExceptionBase("Not set"); | 74 | throw Bu::ExceptionBase("Not set"); |
75 | return *pData; | 75 | return *pData; |
76 | } | 76 | } |
77 | 77 | ||
78 | void clear() | 78 | void clear() |
79 | { | 79 | { |
80 | if( pData ) | 80 | if( pData ) |
81 | { | 81 | { |
82 | ta.destroy( pData ); | 82 | ta.destroy( pData ); |
83 | ta.deallocate( pData, 1 ); | 83 | ta.deallocate( pData, 1 ); |
84 | pData = NULL; | 84 | pData = NULL; |
85 | } | 85 | } |
86 | } | 86 | } |
87 | 87 | ||
88 | operator const t &() const | 88 | operator const t &() const |
89 | { | 89 | { |
90 | if( !pData ) | 90 | if( !pData ) |
91 | throw Bu::ExceptionBase("Not set"); | 91 | throw Bu::ExceptionBase("Not set"); |
92 | return *pData; | 92 | return *pData; |
93 | } | 93 | } |
94 | 94 | ||
95 | operator t &() | 95 | operator t &() |
96 | { | 96 | { |
97 | if( !pData ) | 97 | if( !pData ) |
98 | throw Bu::ExceptionBase("Not set"); | 98 | throw Bu::ExceptionBase("Not set"); |
99 | return *pData; | 99 | return *pData; |
100 | } | 100 | } |
101 | 101 | ||
102 | MyType &operator =( const t &oth ) | 102 | MyType &operator =( const t &oth ) |
103 | { | 103 | { |
104 | set( oth ); | 104 | set( oth ); |
105 | 105 | ||
106 | return *this; | 106 | return *this; |
107 | } | 107 | } |
108 | 108 | ||
109 | MyType &operator =( const MyType &oth ) | 109 | MyType &operator =( const MyType &oth ) |
110 | { | 110 | { |
111 | if( oth.pData ) | 111 | if( oth.pData ) |
112 | set( *oth.pData ); | 112 | set( *oth.pData ); |
113 | 113 | ||
114 | return *this; | 114 | return *this; |
115 | } | 115 | } |
116 | 116 | ||
117 | bool operator ==( const MyType &oth ) | 117 | bool operator ==( const MyType &oth ) |
118 | { | 118 | { |
119 | return (*pData) == (*oth.pData); | 119 | return (*pData) == (*oth.pData); |
120 | } | 120 | } |
121 | 121 | ||
122 | bool operator ==( const t &oth ) | 122 | bool operator ==( const t &oth ) |
123 | { | 123 | { |
124 | return (*pData) == oth; | 124 | return (*pData) == oth; |
125 | } | 125 | } |
126 | 126 | ||
127 | t *operator ->() | 127 | t *operator ->() |
128 | { | 128 | { |
129 | if( !pData ) | 129 | if( !pData ) |
130 | throw Bu::ExceptionBase("Not set"); | 130 | throw Bu::ExceptionBase("Not set"); |
131 | return pData; | 131 | return pData; |
132 | } | 132 | } |
133 | 133 | ||
134 | t &operator *() | 134 | t &operator *() |
135 | { | 135 | { |
136 | if( !pData ) | 136 | if( !pData ) |
137 | throw Bu::ExceptionBase("Not set"); | 137 | throw Bu::ExceptionBase("Not set"); |
138 | return *pData; | 138 | return *pData; |
139 | } | 139 | } |
140 | 140 | ||
141 | private: | 141 | private: |
142 | t *pData; | 142 | t *pData; |
143 | talloc ta; | 143 | talloc ta; |
144 | }; | 144 | }; |
145 | } | 145 | } |
146 | 146 | ||
147 | #endif | 147 | #endif |
diff --git a/src/stable/base64.cpp b/src/stable/base64.cpp index 5ace999..2dc123f 100644 --- a/src/stable/base64.cpp +++ b/src/stable/base64.cpp | |||
@@ -10,210 +10,210 @@ | |||
10 | namespace Bu { subExceptionDef( Base64Exception ) } | 10 | namespace Bu { subExceptionDef( Base64Exception ) } |
11 | 11 | ||
12 | const char Bu::Base64::tblEnc[65] = { | 12 | const char Bu::Base64::tblEnc[65] = { |
13 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | 13 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" |
14 | }; | 14 | }; |
15 | 15 | ||
16 | Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : | 16 | Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : |
17 | Bu::Filter( rNext ), | 17 | Bu::Filter( rNext ), |
18 | iBPos( 0 ), | 18 | iBPos( 0 ), |
19 | iBuf( 0 ), | 19 | iBuf( 0 ), |
20 | iRPos( 0 ), | 20 | iRPos( 0 ), |
21 | iChars( 0 ), | 21 | iChars( 0 ), |
22 | bEosIn( false ), | 22 | bEosIn( false ), |
23 | iTotalIn( 0 ), | 23 | iTotalIn( 0 ), |
24 | iTotalOut( 0 ), | 24 | iTotalOut( 0 ), |
25 | eMode( Nothing ), | 25 | eMode( Nothing ), |
26 | iChunkSize( iChunkSize ), | 26 | iChunkSize( iChunkSize ), |
27 | iCurChunk( 0 ) | 27 | iCurChunk( 0 ) |
28 | { | 28 | { |
29 | start(); | 29 | start(); |
30 | 30 | ||
31 | memset( tblDec, 0, 80 ); | 31 | memset( tblDec, 0, 80 ); |
32 | for( int j = 0; j < 64; j++ ) | 32 | for( int j = 0; j < 64; j++ ) |
33 | { | 33 | { |
34 | tblDec[tblEnc[j]-'+'] = j; | 34 | tblDec[tblEnc[j]-'+'] = j; |
35 | // printf("'%c' = %d\n", tblEnc[j], j ); | 35 | // printf("'%c' = %d\n", tblEnc[j], j ); |
36 | } | 36 | } |
37 | /* | 37 | /* |
38 | for( int j = 0; j < 64; j++ ) | 38 | for( int j = 0; j < 64; j++ ) |
39 | { | 39 | { |
40 | printf("'%c' = '%c' (%d = %d)\n", | 40 | printf("'%c' = '%c' (%d = %d)\n", |
41 | tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], | 41 | tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], |
42 | j, tblDec[tblEnc[j]-'+'] ); | 42 | j, tblDec[tblEnc[j]-'+'] ); |
43 | }*/ | 43 | }*/ |
44 | 44 | ||
45 | // The following is used to compute the table size for the decoding table. | 45 | // The following is used to compute the table size for the decoding table. |
46 | /* | 46 | /* |
47 | char low='A', high='A'; | 47 | char low='A', high='A'; |
48 | for( int j = 0; j < 64; j++ ) | 48 | for( int j = 0; j < 64; j++ ) |
49 | { | 49 | { |
50 | if( tblEnc[j] < low ) | 50 | if( tblEnc[j] < low ) |
51 | low = tblEnc[j]; | 51 | low = tblEnc[j]; |
52 | if( tblEnc[j] > high ) | 52 | if( tblEnc[j] > high ) |
53 | high = tblEnc[j]; | 53 | high = tblEnc[j]; |
54 | } | 54 | } |
55 | 55 | ||
56 | printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); | 56 | printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); |
57 | */ | 57 | */ |
58 | } | 58 | } |
59 | 59 | ||
60 | Bu::Base64::~Base64() | 60 | Bu::Base64::~Base64() |
61 | { | 61 | { |
62 | stop(); | 62 | stop(); |
63 | } | 63 | } |
64 | 64 | ||
65 | void Bu::Base64::start() | 65 | void Bu::Base64::start() |
66 | { | 66 | { |
67 | iCurChunk = 0; | 67 | iCurChunk = 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | Bu::size Bu::Base64::stop() | 70 | Bu::size Bu::Base64::stop() |
71 | { | 71 | { |
72 | if( eMode == Encode ) | 72 | if( eMode == Encode ) |
73 | { | 73 | { |
74 | char outBuf[4]; | 74 | char outBuf[4]; |
75 | int iBUsed = 4-(3-iBPos); | 75 | int iBUsed = 4-(3-iBPos); |
76 | if( iBPos == 0 ) | 76 | if( iBPos == 0 ) |
77 | return iTotalOut; | 77 | return iTotalOut; |
78 | for( int k = 0; k < 4; k++ ) | 78 | for( int k = 0; k < 4; k++ ) |
79 | { | 79 | { |
80 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; | 80 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; |
81 | } | 81 | } |
82 | for( int k = iBUsed; k < 4; k++ ) | 82 | for( int k = iBUsed; k < 4; k++ ) |
83 | { | 83 | { |
84 | outBuf[k] = '='; | 84 | outBuf[k] = '='; |
85 | } | 85 | } |
86 | iCurChunk += 4; | 86 | iCurChunk += 4; |
87 | if( iChunkSize && iCurChunk >= iChunkSize ) | 87 | if( iChunkSize && iCurChunk >= iChunkSize ) |
88 | { | 88 | { |
89 | iCurChunk = iCurChunk-iChunkSize; | 89 | iCurChunk = iCurChunk-iChunkSize; |
90 | iTotalOut += rNext.write( outBuf, 4-iCurChunk ); | 90 | iTotalOut += rNext.write( outBuf, 4-iCurChunk ); |
91 | iTotalOut += rNext.write("\r\n", 2 ); | 91 | iTotalOut += rNext.write("\r\n", 2 ); |
92 | iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); | 92 | iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); |
93 | } | 93 | } |
94 | else | 94 | else |
95 | iTotalOut += rNext.write( outBuf, 4 ); | 95 | iTotalOut += rNext.write( outBuf, 4 ); |
96 | return iTotalOut; | 96 | return iTotalOut; |
97 | } | 97 | } |
98 | else | 98 | else |
99 | { | 99 | { |
100 | return iTotalIn; | 100 | return iTotalIn; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) | 104 | Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) |
105 | { | 105 | { |
106 | if( eMode == Encode ) | 106 | if( eMode == Encode ) |
107 | throw Bu::Base64Exception("Cannot read from an output stream."); | 107 | throw Bu::Base64Exception("Cannot read from an output stream."); |
108 | eMode = Decode; | 108 | eMode = Decode; |
109 | 109 | ||
110 | if( bEosIn == true && iRPos == iChars ) | 110 | if( bEosIn == true && iRPos == iChars ) |
111 | return 0; | 111 | return 0; |
112 | Bu::size sIn = 0; | 112 | Bu::size sIn = 0; |
113 | char buf[4]; | 113 | char buf[4]; |
114 | while( sIn < nBytes ) | 114 | while( sIn < nBytes ) |
115 | { | 115 | { |
116 | for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) | 116 | for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) |
117 | { | 117 | { |
118 | ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; | 118 | ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; |
119 | } | 119 | } |
120 | if( iRPos == iChars ) | 120 | if( iRPos == iChars ) |
121 | { | 121 | { |
122 | if( bEosIn == true ) | 122 | if( bEosIn == true ) |
123 | return sIn; | 123 | return sIn; |
124 | else | 124 | else |
125 | iRPos = 0; | 125 | iRPos = 0; |
126 | } | 126 | } |
127 | else if( sIn == nBytes ) | 127 | else if( sIn == nBytes ) |
128 | return sIn; | 128 | return sIn; |
129 | //if( rNext.read( buf, 4 ) == 0 ) | 129 | //if( rNext.read( buf, 4 ) == 0 ) |
130 | // return sIn; | 130 | // return sIn; |
131 | for( int j = 0; j < 4; j++ ) | 131 | for( int j = 0; j < 4; j++ ) |
132 | { | 132 | { |
133 | if( rNext.read( &buf[j], 1 ) == 0 ) | 133 | if( rNext.read( &buf[j], 1 ) == 0 ) |
134 | { | 134 | { |
135 | if( rNext.isEos() ) | 135 | if( rNext.isEos() ) |
136 | { | 136 | { |
137 | if( iRPos == 0 ) | 137 | if( iRPos == 0 ) |
138 | iRPos = iChars; | 138 | iRPos = iChars; |
139 | bEosIn = true; | 139 | bEosIn = true; |
140 | if( j != 0 ) | 140 | if( j != 0 ) |
141 | { | 141 | { |
142 | throw Base64Exception( | 142 | throw Base64Exception( |
143 | "Premature end of stream detected while " | 143 | "Premature end of stream detected while " |
144 | "decoding Base64 data." | 144 | "decoding Base64 data." |
145 | ); | 145 | ); |
146 | } | 146 | } |
147 | } | 147 | } |
148 | return sIn; | 148 | return sIn; |
149 | } | 149 | } |
150 | if( buf[j] == ' ' || buf[j] == '\t' || | 150 | if( buf[j] == ' ' || buf[j] == '\t' || |
151 | buf[j] == '\n' || buf[j] == '\r' ) | 151 | buf[j] == '\n' || buf[j] == '\r' ) |
152 | { | 152 | { |
153 | j--; | 153 | j--; |
154 | } | 154 | } |
155 | } | 155 | } |
156 | iChars = 3; | 156 | iChars = 3; |
157 | iBuf = 0; | 157 | iBuf = 0; |
158 | for( int j = 0; j < 4; j++ ) | 158 | for( int j = 0; j < 4; j++ ) |
159 | { | 159 | { |
160 | if( buf[j] == '=' ) | 160 | if( buf[j] == '=' ) |
161 | { | 161 | { |
162 | iChars--; | 162 | iChars--; |
163 | bEosIn = true; | 163 | bEosIn = true; |
164 | } | 164 | } |
165 | else | 165 | else |
166 | iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); | 166 | iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); |
167 | //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); | 167 | //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); |
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | return sIn; | 171 | return sIn; |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) | 174 | Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) |
175 | { | 175 | { |
176 | if( eMode == Decode ) | 176 | if( eMode == Decode ) |
177 | throw Bu::Base64Exception("Cannot write to an input stream."); | 177 | throw Bu::Base64Exception("Cannot write to an input stream."); |
178 | eMode = Encode; | 178 | eMode = Encode; |
179 | 179 | ||
180 | Bu::size sOut = 0; | 180 | Bu::size sOut = 0; |
181 | char outBuf[4]; | 181 | char outBuf[4]; |
182 | for( Bu::size j = 0; j < nBytes; j++ ) | 182 | for( Bu::size j = 0; j < nBytes; j++ ) |
183 | { | 183 | { |
184 | iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); | 184 | iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); |
185 | if( iBPos == 3 ) | 185 | if( iBPos == 3 ) |
186 | { | 186 | { |
187 | for( int k = 0; k < 4; k++ ) | 187 | for( int k = 0; k < 4; k++ ) |
188 | { | 188 | { |
189 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; | 189 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; |
190 | } | 190 | } |
191 | iCurChunk += 4; | 191 | iCurChunk += 4; |
192 | if( iChunkSize && iCurChunk >= iChunkSize ) | 192 | if( iChunkSize && iCurChunk >= iChunkSize ) |
193 | { | 193 | { |
194 | iCurChunk = iCurChunk-iChunkSize; | 194 | iCurChunk = iCurChunk-iChunkSize; |
195 | sOut += rNext.write( outBuf, 4-iCurChunk ); | 195 | sOut += rNext.write( outBuf, 4-iCurChunk ); |
196 | sOut += rNext.write("\r\n", 2 ); | 196 | sOut += rNext.write("\r\n", 2 ); |
197 | sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); | 197 | sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); |
198 | } | 198 | } |
199 | else | 199 | else |
200 | sOut += rNext.write( outBuf, 4 ); | 200 | sOut += rNext.write( outBuf, 4 ); |
201 | iBPos = iBuf = 0; | 201 | iBPos = iBuf = 0; |
202 | } | 202 | } |
203 | } | 203 | } |
204 | iTotalOut += sOut; | 204 | iTotalOut += sOut; |
205 | return sOut; | 205 | return sOut; |
206 | } | 206 | } |
207 | 207 | ||
208 | bool Bu::Base64::isOpen() | 208 | bool Bu::Base64::isOpen() |
209 | { | 209 | { |
210 | return true; | 210 | return true; |
211 | } | 211 | } |
212 | 212 | ||
213 | bool Bu::Base64::isEos() | 213 | bool Bu::Base64::isEos() |
214 | { | 214 | { |
215 | if( bEosIn == true && iRPos == iChars ) | 215 | if( bEosIn == true && iRPos == iChars ) |
216 | return true; | 216 | return true; |
217 | return false; | 217 | return false; |
218 | } | 218 | } |
219 | 219 | ||
diff --git a/src/stable/base64.h b/src/stable/base64.h index b10aaeb..695a5ea 100644 --- a/src/stable/base64.h +++ b/src/stable/base64.h | |||
@@ -13,47 +13,47 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | subExceptionDecl( Base64Exception ); | 16 | subExceptionDecl( Base64Exception ); |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * | 19 | * |
20 | *@ingroup Streams | 20 | *@ingroup Streams |
21 | */ | 21 | */ |
22 | class Base64 : public Bu::Filter | 22 | class Base64 : public Bu::Filter |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Base64( Bu::Stream &rNext, int iChunkSize=0 ); | 25 | Base64( Bu::Stream &rNext, int iChunkSize=0 ); |
26 | virtual ~Base64(); | 26 | virtual ~Base64(); |
27 | 27 | ||
28 | virtual void start(); | 28 | virtual void start(); |
29 | virtual Bu::size stop(); | 29 | virtual Bu::size stop(); |
30 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 30 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
32 | 32 | ||
33 | virtual bool isOpen(); | 33 | virtual bool isOpen(); |
34 | 34 | ||
35 | virtual bool isEos(); | 35 | virtual bool isEos(); |
36 | 36 | ||
37 | private: | 37 | private: |
38 | int iBPos; | 38 | int iBPos; |
39 | int iBuf; | 39 | int iBuf; |
40 | int iRPos; | 40 | int iRPos; |
41 | int iChars; | 41 | int iChars; |
42 | bool bEosIn; | 42 | bool bEosIn; |
43 | Bu::size iTotalIn; | 43 | Bu::size iTotalIn; |
44 | Bu::size iTotalOut; | 44 | Bu::size iTotalOut; |
45 | static const char tblEnc[65]; | 45 | static const char tblEnc[65]; |
46 | char tblDec[80]; | 46 | char tblDec[80]; |
47 | enum Mode | 47 | enum Mode |
48 | { | 48 | { |
49 | Nothing = 0x00, | 49 | Nothing = 0x00, |
50 | Encode = 0x01, | 50 | Encode = 0x01, |
51 | Decode = 0x02, | 51 | Decode = 0x02, |
52 | }; | 52 | }; |
53 | Mode eMode; | 53 | Mode eMode; |
54 | int iChunkSize; | 54 | int iChunkSize; |
55 | int iCurChunk; | 55 | int iCurChunk; |
56 | }; | 56 | }; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | #endif | 59 | #endif |
diff --git a/src/stable/buffer.cpp b/src/stable/buffer.cpp index 16c3e2f..c787499 100644 --- a/src/stable/buffer.cpp +++ b/src/stable/buffer.cpp | |||
@@ -8,26 +8,26 @@ | |||
8 | #include "bu/buffer.h" | 8 | #include "bu/buffer.h" |
9 | 9 | ||
10 | Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : | 10 | Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | sSoFar( 0 ), | 12 | sSoFar( 0 ), |
13 | iBufSize( iBufSize ), | 13 | iBufSize( iBufSize ), |
14 | sReadBuf( NULL ), | 14 | sReadBuf( NULL ), |
15 | sWriteBuf( NULL ), | 15 | sWriteBuf( NULL ), |
16 | iReadBufFill( 0 ), | 16 | iReadBufFill( 0 ), |
17 | iReadPos( 0 ), | 17 | iReadPos( 0 ), |
18 | iWriteBufFill( 0 ), | 18 | iWriteBufFill( 0 ), |
19 | iWritePos( 0 ), | 19 | iWritePos( 0 ), |
20 | iWhat( iWhat ) | 20 | iWhat( iWhat ) |
21 | { | 21 | { |
22 | sReadBuf = new char[iBufSize]; | 22 | sReadBuf = new char[iBufSize]; |
23 | sWriteBuf = new char[iBufSize]; | 23 | sWriteBuf = new char[iBufSize]; |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::Buffer::~Buffer() | 26 | Bu::Buffer::~Buffer() |
27 | { | 27 | { |
28 | flush(); | 28 | flush(); |
29 | delete[] sReadBuf; | 29 | delete[] sReadBuf; |
30 | delete[] sWriteBuf; | 30 | delete[] sWriteBuf; |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::Buffer::start() | 33 | void Bu::Buffer::start() |
@@ -36,135 +36,135 @@ void Bu::Buffer::start() | |||
36 | 36 | ||
37 | Bu::size Bu::Buffer::stop() | 37 | Bu::size Bu::Buffer::stop() |
38 | { | 38 | { |
39 | flush(); | 39 | flush(); |
40 | iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; | 40 | iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; |
41 | return sSoFar; | 41 | return sSoFar; |
42 | } | 42 | } |
43 | 43 | ||
44 | void Bu::Buffer::fillReadBuf() | 44 | void Bu::Buffer::fillReadBuf() |
45 | { | 45 | { |
46 | if( iReadBufFill+iReadPos < iBufSize ) | 46 | if( iReadBufFill+iReadPos < iBufSize ) |
47 | { | 47 | { |
48 | iReadBufFill += rNext.read( | 48 | iReadBufFill += rNext.read( |
49 | sReadBuf+iReadPos+iReadBufFill, | 49 | sReadBuf+iReadPos+iReadBufFill, |
50 | iBufSize-iReadBufFill-iReadPos | 50 | iBufSize-iReadBufFill-iReadPos |
51 | ); | 51 | ); |
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) | 55 | Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) |
56 | { | 56 | { |
57 | if( (iWhat&Read) == 0 ) | 57 | if( (iWhat&Read) == 0 ) |
58 | return rNext.read( pBuf, nBytes ); | 58 | return rNext.read( pBuf, nBytes ); |
59 | 59 | ||
60 | if( nBytes <= 0 ) | 60 | if( nBytes <= 0 ) |
61 | { | 61 | { |
62 | fillReadBuf(); | 62 | fillReadBuf(); |
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | Bu::size nTotRead = 0; | 66 | Bu::size nTotRead = 0; |
67 | // fillReadBuf(); | 67 | // fillReadBuf(); |
68 | 68 | ||
69 | do | 69 | do |
70 | { | 70 | { |
71 | int iAmnt = nBytes-nTotRead; | 71 | int iAmnt = nBytes-nTotRead; |
72 | if( iAmnt > iReadBufFill ) | 72 | if( iAmnt > iReadBufFill ) |
73 | { | 73 | { |
74 | iAmnt = iReadBufFill; | 74 | iAmnt = iReadBufFill; |
75 | } | 75 | } |
76 | if( iAmnt > 0 ) | 76 | if( iAmnt > 0 ) |
77 | { | 77 | { |
78 | memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); | 78 | memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); |
79 | iReadPos += iAmnt; | 79 | iReadPos += iAmnt; |
80 | nTotRead += iAmnt; | 80 | nTotRead += iAmnt; |
81 | iReadBufFill -= iAmnt; | 81 | iReadBufFill -= iAmnt; |
82 | } | 82 | } |
83 | if( iReadBufFill == 0 ) | 83 | if( iReadBufFill == 0 ) |
84 | { | 84 | { |
85 | iReadPos = 0; | 85 | iReadPos = 0; |
86 | fillReadBuf(); | 86 | fillReadBuf(); |
87 | } | 87 | } |
88 | } | 88 | } |
89 | while( nTotRead < nBytes && iReadBufFill > 0 ); | 89 | while( nTotRead < nBytes && iReadBufFill > 0 ); |
90 | 90 | ||
91 | //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); | 91 | //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); |
92 | 92 | ||
93 | return nTotRead; | 93 | return nTotRead; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) | 96 | Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) |
97 | { | 97 | { |
98 | if( (iWhat&Write) == 0 ) | 98 | if( (iWhat&Write) == 0 ) |
99 | return rNext.write( pBuf, nBytes ); | 99 | return rNext.write( pBuf, nBytes ); |
100 | 100 | ||
101 | Bu::size nTotWrote = 0; | 101 | Bu::size nTotWrote = 0; |
102 | 102 | ||
103 | do | 103 | do |
104 | { | 104 | { |
105 | int iAmnt = nBytes-nTotWrote; | 105 | int iAmnt = nBytes-nTotWrote; |
106 | if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) | 106 | if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) |
107 | { | 107 | { |
108 | iAmnt = iBufSize-iWritePos-iWriteBufFill; | 108 | iAmnt = iBufSize-iWritePos-iWriteBufFill; |
109 | } | 109 | } |
110 | if( iAmnt > 0 ) | 110 | if( iAmnt > 0 ) |
111 | { | 111 | { |
112 | memcpy( | 112 | memcpy( |
113 | sWriteBuf+iWritePos+iWriteBufFill, | 113 | sWriteBuf+iWritePos+iWriteBufFill, |
114 | ((char *)pBuf)+nTotWrote, | 114 | ((char *)pBuf)+nTotWrote, |
115 | iAmnt | 115 | iAmnt |
116 | ); | 116 | ); |
117 | nTotWrote += iAmnt; | 117 | nTotWrote += iAmnt; |
118 | iWriteBufFill += iAmnt; | 118 | iWriteBufFill += iAmnt; |
119 | //printf("Buffer: Moved %db to write buffer, %db filled now.\n", | 119 | //printf("Buffer: Moved %db to write buffer, %db filled now.\n", |
120 | //iAmnt, iWriteBufFill ); | 120 | //iAmnt, iWriteBufFill ); |
121 | } | 121 | } |
122 | while( iWritePos+iWriteBufFill == iBufSize ) | 122 | while( iWritePos+iWriteBufFill == iBufSize ) |
123 | { | 123 | { |
124 | //printf("iWritePos = %d\n", iWritePos ); | 124 | //printf("iWritePos = %d\n", iWritePos ); |
125 | int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); | 125 | int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); |
126 | //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); | 126 | //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); |
127 | if( iWr == 0 ) | 127 | if( iWr == 0 ) |
128 | { | 128 | { |
129 | return nTotWrote; | 129 | return nTotWrote; |
130 | } | 130 | } |
131 | else if( iWr == iWriteBufFill ) | 131 | else if( iWr == iWriteBufFill ) |
132 | { | 132 | { |
133 | iWritePos = iWriteBufFill = 0; | 133 | iWritePos = iWriteBufFill = 0; |
134 | } | 134 | } |
135 | else | 135 | else |
136 | { | 136 | { |
137 | iWritePos += iWr; | 137 | iWritePos += iWr; |
138 | iWriteBufFill -= iWr; | 138 | iWriteBufFill -= iWr; |
139 | } | 139 | } |
140 | } | 140 | } |
141 | } | 141 | } |
142 | while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); | 142 | while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); |
143 | 143 | ||
144 | return nTotWrote; | 144 | return nTotWrote; |
145 | } | 145 | } |
146 | 146 | ||
147 | void Bu::Buffer::flush() | 147 | void Bu::Buffer::flush() |
148 | { | 148 | { |
149 | if( (iWhat&Write) == 0 ) | 149 | if( (iWhat&Write) == 0 ) |
150 | return rNext.flush(); | 150 | return rNext.flush(); |
151 | 151 | ||
152 | if( iWriteBufFill > 0 ) | 152 | if( iWriteBufFill > 0 ) |
153 | { | 153 | { |
154 | //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); | 154 | //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); |
155 | int iWr = 0; | 155 | int iWr = 0; |
156 | do | 156 | do |
157 | { | 157 | { |
158 | iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); | 158 | iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); |
159 | //printf("Buffer: %db written to stream.\n", iWr ); | 159 | //printf("Buffer: %db written to stream.\n", iWr ); |
160 | iWritePos += iWr; | 160 | iWritePos += iWr; |
161 | iWriteBufFill -= iWr; | 161 | iWriteBufFill -= iWr; |
162 | } while( iWriteBufFill > 0 && iWr > 0 ); | 162 | } while( iWriteBufFill > 0 && iWr > 0 ); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | bool Bu::Buffer::isEos() | 166 | bool Bu::Buffer::isEos() |
167 | { | 167 | { |
168 | return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); | 168 | return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); |
169 | } | 169 | } |
170 | 170 | ||
diff --git a/src/stable/buffer.h b/src/stable/buffer.h index a8303fa..21a5812 100644 --- a/src/stable/buffer.h +++ b/src/stable/buffer.h | |||
@@ -12,47 +12,47 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class Buffer : public Bu::Filter | 15 | class Buffer : public Bu::Filter |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); | 18 | Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); |
19 | virtual ~Buffer(); | 19 | virtual ~Buffer(); |
20 | 20 | ||
21 | enum | 21 | enum |
22 | { | 22 | { |
23 | Write = 1, | 23 | Write = 1, |
24 | Read = 2, | 24 | Read = 2, |
25 | Both = 3 | 25 | Both = 3 |
26 | }; | 26 | }; |
27 | 27 | ||
28 | virtual void start(); | 28 | virtual void start(); |
29 | virtual Bu::size stop(); | 29 | virtual Bu::size stop(); |
30 | 30 | ||
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
33 | using Stream::write; | 33 | using Stream::write; |
34 | 34 | ||
35 | Bu::size getReadFill() { return iReadBufFill; } | 35 | Bu::size getReadFill() { return iReadBufFill; } |
36 | bool isWritePending() { return iWriteBufFill > 0; } | 36 | bool isWritePending() { return iWriteBufFill > 0; } |
37 | 37 | ||
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | 39 | ||
40 | virtual bool isEos(); | 40 | virtual bool isEos(); |
41 | 41 | ||
42 | private: | 42 | private: |
43 | void fillReadBuf(); | 43 | void fillReadBuf(); |
44 | 44 | ||
45 | private: | 45 | private: |
46 | Bu::size sSoFar; | 46 | Bu::size sSoFar; |
47 | int iBufSize; | 47 | int iBufSize; |
48 | char *sReadBuf; | 48 | char *sReadBuf; |
49 | char *sWriteBuf; | 49 | char *sWriteBuf; |
50 | int iReadBufFill; | 50 | int iReadBufFill; |
51 | int iReadPos; | 51 | int iReadPos; |
52 | int iWriteBufFill; | 52 | int iWriteBufFill; |
53 | int iWritePos; | 53 | int iWritePos; |
54 | int iWhat; | 54 | int iWhat; |
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | #endif | 58 | #endif |
diff --git a/src/stable/bzip2.cpp b/src/stable/bzip2.cpp index 11b8873..5e660d0 100644 --- a/src/stable/bzip2.cpp +++ b/src/stable/bzip2.cpp | |||
@@ -15,222 +15,222 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : | 17 | Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ) | 21 | sTotalOut( 0 ) |
22 | { | 22 | { |
23 | TRACE( nCompression ); | 23 | TRACE( nCompression ); |
24 | start(); | 24 | start(); |
25 | } | 25 | } |
26 | 26 | ||
27 | Bu::BZip2::~BZip2() | 27 | Bu::BZip2::~BZip2() |
28 | { | 28 | { |
29 | TRACE(); | 29 | TRACE(); |
30 | stop(); | 30 | stop(); |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::BZip2::start() | 33 | void Bu::BZip2::start() |
34 | { | 34 | { |
35 | TRACE(); | 35 | TRACE(); |
36 | 36 | ||
37 | prState = new bz_stream; | 37 | prState = new bz_stream; |
38 | pState->state = NULL; | 38 | pState->state = NULL; |
39 | pState->bzalloc = NULL; | 39 | pState->bzalloc = NULL; |
40 | pState->bzfree = NULL; | 40 | pState->bzfree = NULL; |
41 | pState->opaque = NULL; | 41 | pState->opaque = NULL; |
42 | 42 | ||
43 | nBufSize = 64*1024; | 43 | nBufSize = 64*1024; |
44 | pBuf = new char[nBufSize]; | 44 | pBuf = new char[nBufSize]; |
45 | } | 45 | } |
46 | 46 | ||
47 | Bu::size Bu::BZip2::stop() | 47 | Bu::size Bu::BZip2::stop() |
48 | { | 48 | { |
49 | TRACE(); | 49 | TRACE(); |
50 | if( !pState ) | 50 | if( !pState ) |
51 | return 0; | 51 | return 0; |
52 | 52 | ||
53 | if( pState->state ) | 53 | if( pState->state ) |
54 | { | 54 | { |
55 | if( bReading ) | 55 | if( bReading ) |
56 | { | 56 | { |
57 | BZ2_bzDecompressEnd( pState ); | 57 | BZ2_bzDecompressEnd( pState ); |
58 | delete[] pBuf; | 58 | delete[] pBuf; |
59 | pBuf = NULL; | 59 | pBuf = NULL; |
60 | delete pState; | 60 | delete pState; |
61 | prState = NULL; | 61 | prState = NULL; |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | else | 64 | else |
65 | { | 65 | { |
66 | // Bu::size sTotal = 0; | 66 | // Bu::size sTotal = 0; |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | pState->next_in = NULL; | 69 | pState->next_in = NULL; |
70 | pState->avail_in = 0; | 70 | pState->avail_in = 0; |
71 | pState->avail_out = nBufSize; | 71 | pState->avail_out = nBufSize; |
72 | pState->next_out = pBuf; | 72 | pState->next_out = pBuf; |
73 | int res = BZ2_bzCompress( pState, BZ_FINISH ); | 73 | int res = BZ2_bzCompress( pState, BZ_FINISH ); |
74 | if( pState->avail_out < nBufSize ) | 74 | if( pState->avail_out < nBufSize ) |
75 | { | 75 | { |
76 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 76 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
77 | } | 77 | } |
78 | if( res == BZ_STREAM_END ) | 78 | if( res == BZ_STREAM_END ) |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | BZ2_bzCompressEnd( pState ); | 81 | BZ2_bzCompressEnd( pState ); |
82 | delete[] pBuf; | 82 | delete[] pBuf; |
83 | pBuf = NULL; | 83 | pBuf = NULL; |
84 | delete pState; | 84 | delete pState; |
85 | prState = NULL; | 85 | prState = NULL; |
86 | return sTotalOut; | 86 | return sTotalOut; |
87 | } | 87 | } |
88 | } | 88 | } |
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | void Bu::BZip2::bzError( int code ) | 92 | void Bu::BZip2::bzError( int code ) |
93 | { | 93 | { |
94 | TRACE( code ); | 94 | TRACE( code ); |
95 | switch( code ) | 95 | switch( code ) |
96 | { | 96 | { |
97 | case BZ_OK: | 97 | case BZ_OK: |
98 | case BZ_RUN_OK: | 98 | case BZ_RUN_OK: |
99 | case BZ_FLUSH_OK: | 99 | case BZ_FLUSH_OK: |
100 | case BZ_FINISH_OK: | 100 | case BZ_FINISH_OK: |
101 | return; | 101 | return; |
102 | 102 | ||
103 | case BZ_CONFIG_ERROR: | 103 | case BZ_CONFIG_ERROR: |
104 | throw ExceptionBase("BZip2: Library configured improperly, reinstall."); | 104 | throw ExceptionBase("BZip2: Library configured improperly, reinstall."); |
105 | 105 | ||
106 | case BZ_SEQUENCE_ERROR: | 106 | case BZ_SEQUENCE_ERROR: |
107 | throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); | 107 | throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); |
108 | 108 | ||
109 | case BZ_PARAM_ERROR: | 109 | case BZ_PARAM_ERROR: |
110 | throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); | 110 | throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); |
111 | 111 | ||
112 | case BZ_MEM_ERROR: | 112 | case BZ_MEM_ERROR: |
113 | throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); | 113 | throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); |
114 | 114 | ||
115 | case BZ_DATA_ERROR: | 115 | case BZ_DATA_ERROR: |
116 | throw ExceptionBase("BZip2: Data was corrupted before decompression."); | 116 | throw ExceptionBase("BZip2: Data was corrupted before decompression."); |
117 | 117 | ||
118 | case BZ_DATA_ERROR_MAGIC: | 118 | case BZ_DATA_ERROR_MAGIC: |
119 | throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); | 119 | throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); |
120 | 120 | ||
121 | case BZ_IO_ERROR: | 121 | case BZ_IO_ERROR: |
122 | throw ExceptionBase("BZip2: File couldn't be read from / written to."); | 122 | throw ExceptionBase("BZip2: File couldn't be read from / written to."); |
123 | 123 | ||
124 | case BZ_UNEXPECTED_EOF: | 124 | case BZ_UNEXPECTED_EOF: |
125 | throw ExceptionBase("BZip2: End of file encountered before end of stream."); | 125 | throw ExceptionBase("BZip2: End of file encountered before end of stream."); |
126 | 126 | ||
127 | case BZ_OUTBUFF_FULL: | 127 | case BZ_OUTBUFF_FULL: |
128 | throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); | 128 | throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); |
129 | 129 | ||
130 | default: | 130 | default: |
131 | throw ExceptionBase("BZip2: Unknown error encountered."); | 131 | throw ExceptionBase("BZip2: Unknown error encountered."); |
132 | 132 | ||
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) | 136 | Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) |
137 | { | 137 | { |
138 | TRACE( pData, nBytes ); | 138 | TRACE( pData, nBytes ); |
139 | if( !pState->state ) | 139 | if( !pState->state ) |
140 | { | 140 | { |
141 | bReading = true; | 141 | bReading = true; |
142 | BZ2_bzDecompressInit( pState, 0, 0 ); | 142 | BZ2_bzDecompressInit( pState, 0, 0 ); |
143 | pState->next_in = pBuf; | 143 | pState->next_in = pBuf; |
144 | pState->avail_in = 0; | 144 | pState->avail_in = 0; |
145 | } | 145 | } |
146 | if( bReading == false ) | 146 | if( bReading == false ) |
147 | throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); | 147 | throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); |
148 | 148 | ||
149 | int nRead = 0; | 149 | int nRead = 0; |
150 | int nReadTotal = pState->total_out_lo32; | 150 | int nReadTotal = pState->total_out_lo32; |
151 | pState->next_out = (char *)pData; | 151 | pState->next_out = (char *)pData; |
152 | pState->avail_out = nBytes; | 152 | pState->avail_out = nBytes; |
153 | for(;;) | 153 | for(;;) |
154 | { | 154 | { |
155 | int ret = BZ2_bzDecompress( pState ); | 155 | int ret = BZ2_bzDecompress( pState ); |
156 | 156 | ||
157 | nReadTotal += nRead-pState->avail_out; | 157 | nReadTotal += nRead-pState->avail_out; |
158 | 158 | ||
159 | if( ret == BZ_STREAM_END ) | 159 | if( ret == BZ_STREAM_END ) |
160 | { | 160 | { |
161 | if( pState->avail_in > 0 ) | 161 | if( pState->avail_in > 0 ) |
162 | { | 162 | { |
163 | if( rNext.isSeekable() ) | 163 | if( rNext.isSeekable() ) |
164 | { | 164 | { |
165 | rNext.seek( -(Bu::size)pState->avail_in ); | 165 | rNext.seek( -(Bu::size)pState->avail_in ); |
166 | } | 166 | } |
167 | } | 167 | } |
168 | return nBytes-pState->avail_out; | 168 | return nBytes-pState->avail_out; |
169 | } | 169 | } |
170 | bzError( ret ); | 170 | bzError( ret ); |
171 | 171 | ||
172 | if( pState->avail_out ) | 172 | if( pState->avail_out ) |
173 | { | 173 | { |
174 | if( pState->avail_in == 0 ) | 174 | if( pState->avail_in == 0 ) |
175 | { | 175 | { |
176 | nRead = rNext.read( pBuf, nBufSize ); | 176 | nRead = rNext.read( pBuf, nBufSize ); |
177 | if( nRead == 0 && rNext.isEos() ) | 177 | if( nRead == 0 && rNext.isEos() ) |
178 | { | 178 | { |
179 | throw Bu::ExceptionBase("Premature end of underlying " | 179 | throw Bu::ExceptionBase("Premature end of underlying " |
180 | "stream found reading bzip2 stream."); | 180 | "stream found reading bzip2 stream."); |
181 | } | 181 | } |
182 | pState->next_in = pBuf; | 182 | pState->next_in = pBuf; |
183 | pState->avail_in = nRead; | 183 | pState->avail_in = nRead; |
184 | } | 184 | } |
185 | } | 185 | } |
186 | else | 186 | else |
187 | { | 187 | { |
188 | return nBytes-pState->avail_out; | 188 | return nBytes-pState->avail_out; |
189 | } | 189 | } |
190 | } | 190 | } |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | 193 | ||
194 | Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) | 194 | Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) |
195 | { | 195 | { |
196 | TRACE( pData, nBytes ); | 196 | TRACE( pData, nBytes ); |
197 | if( !pState->state ) | 197 | if( !pState->state ) |
198 | { | 198 | { |
199 | bReading = false; | 199 | bReading = false; |
200 | BZ2_bzCompressInit( pState, nCompression, 0, 30 ); | 200 | BZ2_bzCompressInit( pState, nCompression, 0, 30 ); |
201 | } | 201 | } |
202 | if( bReading == true ) | 202 | if( bReading == true ) |
203 | throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); | 203 | throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); |
204 | 204 | ||
205 | // Bu::size sTotalOut = 0; | 205 | // Bu::size sTotalOut = 0; |
206 | pState->next_in = (char *)pData; | 206 | pState->next_in = (char *)pData; |
207 | pState->avail_in = nBytes; | 207 | pState->avail_in = nBytes; |
208 | for(;;) | 208 | for(;;) |
209 | { | 209 | { |
210 | pState->avail_out = nBufSize; | 210 | pState->avail_out = nBufSize; |
211 | pState->next_out = pBuf; | 211 | pState->next_out = pBuf; |
212 | 212 | ||
213 | bzError( BZ2_bzCompress( pState, BZ_RUN ) ); | 213 | bzError( BZ2_bzCompress( pState, BZ_RUN ) ); |
214 | 214 | ||
215 | if( pState->avail_out < nBufSize ) | 215 | if( pState->avail_out < nBufSize ) |
216 | { | 216 | { |
217 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 217 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
218 | } | 218 | } |
219 | if( pState->avail_in == 0 ) | 219 | if( pState->avail_in == 0 ) |
220 | break; | 220 | break; |
221 | } | 221 | } |
222 | 222 | ||
223 | return nBytes; | 223 | return nBytes; |
224 | } | 224 | } |
225 | 225 | ||
226 | bool Bu::BZip2::isOpen() | 226 | bool Bu::BZip2::isOpen() |
227 | { | 227 | { |
228 | TRACE(); | 228 | TRACE(); |
229 | return (pState->state != NULL); | 229 | return (pState->state != NULL); |
230 | } | 230 | } |
231 | 231 | ||
232 | Bu::size Bu::BZip2::getCompressedSize() | 232 | Bu::size Bu::BZip2::getCompressedSize() |
233 | { | 233 | { |
234 | return sTotalOut; | 234 | return sTotalOut; |
235 | } | 235 | } |
236 | 236 | ||
diff --git a/src/stable/bzip2.h b/src/stable/bzip2.h index d92dd2f..d53f325 100644 --- a/src/stable/bzip2.h +++ b/src/stable/bzip2.h | |||
@@ -14,36 +14,36 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides BZip2 type compression and decompression. | 18 | * Provides BZip2 type compression and decompression. |
19 | * | 19 | * |
20 | *@ingroup Streams | 20 | *@ingroup Streams |
21 | *@ingroup Compression | 21 | *@ingroup Compression |
22 | */ | 22 | */ |
23 | class BZip2 : public Bu::Filter | 23 | class BZip2 : public Bu::Filter |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | BZip2( Bu::Stream &rNext, int nCompression=9 ); | 26 | BZip2( Bu::Stream &rNext, int nCompression=9 ); |
27 | virtual ~BZip2(); | 27 | virtual ~BZip2(); |
28 | 28 | ||
29 | virtual void start(); | 29 | virtual void start(); |
30 | virtual Bu::size stop(); | 30 | virtual Bu::size stop(); |
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
33 | 33 | ||
34 | virtual bool isOpen(); | 34 | virtual bool isOpen(); |
35 | 35 | ||
36 | Bu::size getCompressedSize(); | 36 | Bu::size getCompressedSize(); |
37 | 37 | ||
38 | private: | 38 | private: |
39 | void bzError( int code ); | 39 | void bzError( int code ); |
40 | void *prState; | 40 | void *prState; |
41 | bool bReading; | 41 | bool bReading; |
42 | int nCompression; | 42 | int nCompression; |
43 | char *pBuf; | 43 | char *pBuf; |
44 | uint32_t nBufSize; | 44 | uint32_t nBufSize; |
45 | Bu::size sTotalOut; | 45 | Bu::size sTotalOut; |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/client.cpp b/src/stable/client.cpp index 7ae10f7..f5cc75f 100644 --- a/src/stable/client.cpp +++ b/src/stable/client.cpp | |||
@@ -14,307 +14,307 @@ | |||
14 | #include "bu/clientlinkfactory.h" | 14 | #include "bu/clientlinkfactory.h" |
15 | 15 | ||
16 | /** Read buffer size. */ | 16 | /** Read buffer size. */ |
17 | #define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess | 17 | #define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess |
18 | 18 | ||
19 | Bu::Client::Client( Bu::TcpSocket *pSocket, | 19 | Bu::Client::Client( Bu::TcpSocket *pSocket, |
20 | class Bu::ClientLinkFactory *pfLink ) : | 20 | class Bu::ClientLinkFactory *pfLink ) : |
21 | pTopStream( pSocket ), | 21 | pTopStream( pSocket ), |
22 | pSocket( pSocket ), | 22 | pSocket( pSocket ), |
23 | pProto( NULL ), | 23 | pProto( NULL ), |
24 | bWantsDisconnect( false ), | 24 | bWantsDisconnect( false ), |
25 | pfLink( pfLink ) | 25 | pfLink( pfLink ) |
26 | { | 26 | { |
27 | lFilts.prepend( pSocket ); | 27 | lFilts.prepend( pSocket ); |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::Client::~Client() | 30 | Bu::Client::~Client() |
31 | { | 31 | { |
32 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 32 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
33 | { | 33 | { |
34 | delete *i; | 34 | delete *i; |
35 | } | 35 | } |
36 | pTopStream = pSocket = NULL; | 36 | pTopStream = pSocket = NULL; |
37 | delete pfLink; | 37 | delete pfLink; |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::Client::processInput() | 40 | void Bu::Client::processInput() |
41 | { | 41 | { |
42 | char buf[RBS]; | 42 | char buf[RBS]; |
43 | Bu::size nRead, nTotal=0; | 43 | Bu::size nRead, nTotal=0; |
44 | 44 | ||
45 | for(;;) | 45 | for(;;) |
46 | { | 46 | { |
47 | try | 47 | try |
48 | { | 48 | { |
49 | nRead = pTopStream->read( buf, RBS ); | 49 | nRead = pTopStream->read( buf, RBS ); |
50 | 50 | ||
51 | if( nRead == 0 ) | 51 | if( nRead == 0 ) |
52 | { | 52 | { |
53 | break; | 53 | break; |
54 | } | 54 | } |
55 | else | 55 | else |
56 | { | 56 | { |
57 | nTotal += nRead; | 57 | nTotal += nRead; |
58 | qbRead.write( buf, nRead ); | 58 | qbRead.write( buf, nRead ); |
59 | if( !pTopStream->canRead() ) | 59 | if( !pTopStream->canRead() ) |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | } | 62 | } |
63 | catch( Bu::TcpSocketException &e ) | 63 | catch( Bu::TcpSocketException &e ) |
64 | { | 64 | { |
65 | pTopStream->close(); | 65 | pTopStream->close(); |
66 | bWantsDisconnect = true; | 66 | bWantsDisconnect = true; |
67 | break; | 67 | break; |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | if( nTotal == 0 ) | 71 | if( nTotal == 0 ) |
72 | { | 72 | { |
73 | pTopStream->close(); | 73 | pTopStream->close(); |
74 | bWantsDisconnect = true; | 74 | bWantsDisconnect = true; |
75 | } | 75 | } |
76 | 76 | ||
77 | if( pProto && nTotal ) | 77 | if( pProto && nTotal ) |
78 | { | 78 | { |
79 | pProto->onNewData( this ); | 79 | pProto->onNewData( this ); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::Client::processOutput() | 83 | void Bu::Client::processOutput() |
84 | { | 84 | { |
85 | char buf[RBS]; | 85 | char buf[RBS]; |
86 | if( qbWrite.getSize() > 0 ) | 86 | if( qbWrite.getSize() > 0 ) |
87 | { | 87 | { |
88 | int nAmnt = RBS; | 88 | int nAmnt = RBS; |
89 | nAmnt = qbWrite.peek( buf, nAmnt ); | 89 | nAmnt = qbWrite.peek( buf, nAmnt ); |
90 | int nReal = pTopStream->write( buf, nAmnt ); | 90 | int nReal = pTopStream->write( buf, nAmnt ); |
91 | qbWrite.seek( nReal ); | 91 | qbWrite.seek( nReal ); |
92 | pTopStream->flush(); | 92 | pTopStream->flush(); |
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::Client::setProtocol( Protocol *pProto ) | 96 | void Bu::Client::setProtocol( Protocol *pProto ) |
97 | { | 97 | { |
98 | this->pProto = pProto; | 98 | this->pProto = pProto; |
99 | this->pProto->onNewConnection( this ); | 99 | this->pProto->onNewConnection( this ); |
100 | } | 100 | } |
101 | 101 | ||
102 | Bu::Protocol *Bu::Client::getProtocol() | 102 | Bu::Protocol *Bu::Client::getProtocol() |
103 | { | 103 | { |
104 | return pProto; | 104 | return pProto; |
105 | } | 105 | } |
106 | 106 | ||
107 | void Bu::Client::clearProtocol() | 107 | void Bu::Client::clearProtocol() |
108 | { | 108 | { |
109 | pProto = NULL; | 109 | pProto = NULL; |
110 | } | 110 | } |
111 | /* | 111 | /* |
112 | Bu::String &Bu::Client::getInput() | 112 | Bu::String &Bu::Client::getInput() |
113 | { | 113 | { |
114 | return sReadBuf; | 114 | return sReadBuf; |
115 | } | 115 | } |
116 | 116 | ||
117 | Bu::String &Bu::Client::getOutput() | 117 | Bu::String &Bu::Client::getOutput() |
118 | { | 118 | { |
119 | return sWriteBuf; | 119 | return sWriteBuf; |
120 | } | 120 | } |
121 | */ | 121 | */ |
122 | 122 | ||
123 | bool Bu::Client::isOpen() | 123 | bool Bu::Client::isOpen() |
124 | { | 124 | { |
125 | if( !pTopStream ) return false; | 125 | if( !pTopStream ) return false; |
126 | return pTopStream->isOpen(); | 126 | return pTopStream->isOpen(); |
127 | } | 127 | } |
128 | 128 | ||
129 | Bu::size Bu::Client::write( const Bu::String &sData ) | 129 | Bu::size Bu::Client::write( const Bu::String &sData ) |
130 | { | 130 | { |
131 | return qbWrite.write( sData.getStr(), sData.getSize() ); | 131 | return qbWrite.write( sData.getStr(), sData.getSize() ); |
132 | } | 132 | } |
133 | 133 | ||
134 | Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) | 134 | Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) |
135 | { | 135 | { |
136 | return qbWrite.write( pData, nBytes ); | 136 | return qbWrite.write( pData, nBytes ); |
137 | } | 137 | } |
138 | 138 | ||
139 | Bu::size Bu::Client::write( int8_t nData ) | 139 | Bu::size Bu::Client::write( int8_t nData ) |
140 | { | 140 | { |
141 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 141 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::size Bu::Client::write( int16_t nData ) | 144 | Bu::size Bu::Client::write( int16_t nData ) |
145 | { | 145 | { |
146 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 146 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
147 | } | 147 | } |
148 | 148 | ||
149 | Bu::size Bu::Client::write( int32_t nData ) | 149 | Bu::size Bu::Client::write( int32_t nData ) |
150 | { | 150 | { |
151 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 151 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
152 | } | 152 | } |
153 | 153 | ||
154 | Bu::size Bu::Client::write( int64_t nData ) | 154 | Bu::size Bu::Client::write( int64_t nData ) |
155 | { | 155 | { |
156 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 156 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
157 | } | 157 | } |
158 | 158 | ||
159 | Bu::size Bu::Client::write( uint8_t nData ) | 159 | Bu::size Bu::Client::write( uint8_t nData ) |
160 | { | 160 | { |
161 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 161 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
162 | } | 162 | } |
163 | 163 | ||
164 | Bu::size Bu::Client::write( uint16_t nData ) | 164 | Bu::size Bu::Client::write( uint16_t nData ) |
165 | { | 165 | { |
166 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 166 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
167 | } | 167 | } |
168 | 168 | ||
169 | Bu::size Bu::Client::write( uint32_t nData ) | 169 | Bu::size Bu::Client::write( uint32_t nData ) |
170 | { | 170 | { |
171 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 171 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::size Bu::Client::write( uint64_t nData ) | 174 | Bu::size Bu::Client::write( uint64_t nData ) |
175 | { | 175 | { |
176 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 176 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
177 | } | 177 | } |
178 | 178 | ||
179 | Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) | 179 | Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) |
180 | { | 180 | { |
181 | return qbRead.read( pData, nBytes ); | 181 | return qbRead.read( pData, nBytes ); |
182 | } | 182 | } |
183 | 183 | ||
184 | Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) | 184 | Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) |
185 | { | 185 | { |
186 | return qbRead.peek( pData, nBytes, nOffset ); | 186 | return qbRead.peek( pData, nBytes, nOffset ); |
187 | } | 187 | } |
188 | 188 | ||
189 | Bu::size Bu::Client::getInputSize() | 189 | Bu::size Bu::Client::getInputSize() |
190 | { | 190 | { |
191 | return qbRead.getSize(); | 191 | return qbRead.getSize(); |
192 | } | 192 | } |
193 | 193 | ||
194 | Bu::size Bu::Client::getOutputSize() | 194 | Bu::size Bu::Client::getOutputSize() |
195 | { | 195 | { |
196 | return qbWrite.getSize(); | 196 | return qbWrite.getSize(); |
197 | } | 197 | } |
198 | 198 | ||
199 | const Bu::TcpSocket *Bu::Client::getSocket() const | 199 | const Bu::TcpSocket *Bu::Client::getSocket() const |
200 | { | 200 | { |
201 | return pSocket; | 201 | return pSocket; |
202 | } | 202 | } |
203 | 203 | ||
204 | void Bu::Client::disconnect() | 204 | void Bu::Client::disconnect() |
205 | { | 205 | { |
206 | bWantsDisconnect = true; | 206 | bWantsDisconnect = true; |
207 | } | 207 | } |
208 | 208 | ||
209 | bool Bu::Client::wantsDisconnect() | 209 | bool Bu::Client::wantsDisconnect() |
210 | { | 210 | { |
211 | return bWantsDisconnect; | 211 | return bWantsDisconnect; |
212 | } | 212 | } |
213 | 213 | ||
214 | void Bu::Client::close() | 214 | void Bu::Client::close() |
215 | { | 215 | { |
216 | pTopStream->close(); | 216 | pTopStream->close(); |
217 | } | 217 | } |
218 | 218 | ||
219 | Bu::ClientLink *Bu::Client::getLink() | 219 | Bu::ClientLink *Bu::Client::getLink() |
220 | { | 220 | { |
221 | return pfLink->createLink( this ); | 221 | return pfLink->createLink( this ); |
222 | } | 222 | } |
223 | 223 | ||
224 | void Bu::Client::onMessage( const Bu::String &sMsg ) | 224 | void Bu::Client::onMessage( const Bu::String &sMsg ) |
225 | { | 225 | { |
226 | if( pProto ) | 226 | if( pProto ) |
227 | pProto->onMessage( this, sMsg ); | 227 | pProto->onMessage( this, sMsg ); |
228 | } | 228 | } |
229 | 229 | ||
230 | void Bu::Client::tick() | 230 | void Bu::Client::tick() |
231 | { | 231 | { |
232 | if( pProto ) | 232 | if( pProto ) |
233 | pProto->onTick( this ); | 233 | pProto->onTick( this ); |
234 | } | 234 | } |
235 | 235 | ||
236 | Bu::size Bu::Client::tell() | 236 | Bu::size Bu::Client::tell() |
237 | { | 237 | { |
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | void Bu::Client::seek( Bu::size offset ) | 241 | void Bu::Client::seek( Bu::size offset ) |
242 | { | 242 | { |
243 | return qbRead.seek( offset ); | 243 | return qbRead.seek( offset ); |
244 | } | 244 | } |
245 | 245 | ||
246 | void Bu::Client::setPos( Bu::size ) | 246 | void Bu::Client::setPos( Bu::size ) |
247 | { | 247 | { |
248 | throw Bu::ExceptionBase(); | 248 | throw Bu::ExceptionBase(); |
249 | } | 249 | } |
250 | 250 | ||
251 | void Bu::Client::setPosEnd( Bu::size ) | 251 | void Bu::Client::setPosEnd( Bu::size ) |
252 | { | 252 | { |
253 | throw Bu::ExceptionBase(); | 253 | throw Bu::ExceptionBase(); |
254 | } | 254 | } |
255 | 255 | ||
256 | bool Bu::Client::isEos() | 256 | bool Bu::Client::isEos() |
257 | { | 257 | { |
258 | return true; | 258 | return true; |
259 | } | 259 | } |
260 | 260 | ||
261 | void Bu::Client::flush() | 261 | void Bu::Client::flush() |
262 | { | 262 | { |
263 | processOutput(); | 263 | processOutput(); |
264 | } | 264 | } |
265 | 265 | ||
266 | bool Bu::Client::canRead() | 266 | bool Bu::Client::canRead() |
267 | { | 267 | { |
268 | return qbRead.getSize() > 0; | 268 | return qbRead.getSize() > 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | bool Bu::Client::canWrite() | 271 | bool Bu::Client::canWrite() |
272 | { | 272 | { |
273 | return true; | 273 | return true; |
274 | } | 274 | } |
275 | 275 | ||
276 | bool Bu::Client::isReadable() | 276 | bool Bu::Client::isReadable() |
277 | { | 277 | { |
278 | return true; | 278 | return true; |
279 | } | 279 | } |
280 | 280 | ||
281 | bool Bu::Client::isWritable() | 281 | bool Bu::Client::isWritable() |
282 | { | 282 | { |
283 | return true; | 283 | return true; |
284 | } | 284 | } |
285 | 285 | ||
286 | bool Bu::Client::isSeekable() | 286 | bool Bu::Client::isSeekable() |
287 | { | 287 | { |
288 | return false; | 288 | return false; |
289 | } | 289 | } |
290 | 290 | ||
291 | bool Bu::Client::isBlocking() | 291 | bool Bu::Client::isBlocking() |
292 | { | 292 | { |
293 | return false; | 293 | return false; |
294 | } | 294 | } |
295 | 295 | ||
296 | void Bu::Client::setBlocking( bool ) | 296 | void Bu::Client::setBlocking( bool ) |
297 | { | 297 | { |
298 | throw Bu::ExceptionBase(); | 298 | throw Bu::ExceptionBase(); |
299 | } | 299 | } |
300 | 300 | ||
301 | void Bu::Client::setSize( Bu::size ) | 301 | void Bu::Client::setSize( Bu::size ) |
302 | { | 302 | { |
303 | throw Bu::ExceptionBase(); | 303 | throw Bu::ExceptionBase(); |
304 | } | 304 | } |
305 | 305 | ||
306 | Bu::size Bu::Client::getSize() const | 306 | Bu::size Bu::Client::getSize() const |
307 | { | 307 | { |
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | Bu::size Bu::Client::getBlockSize() const | 311 | Bu::size Bu::Client::getBlockSize() const |
312 | { | 312 | { |
313 | return pSocket->getBlockSize(); | 313 | return pSocket->getBlockSize(); |
314 | } | 314 | } |
315 | 315 | ||
316 | Bu::String Bu::Client::getLocation() const | 316 | Bu::String Bu::Client::getLocation() const |
317 | { | 317 | { |
318 | return pSocket->getLocation(); | 318 | return pSocket->getLocation(); |
319 | } | 319 | } |
320 | 320 | ||
diff --git a/src/stable/client.h b/src/stable/client.h index 6bd41af..cacc8aa 100644 --- a/src/stable/client.h +++ b/src/stable/client.h | |||
@@ -16,118 +16,118 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class Protocol; | 19 | class Protocol; |
20 | class Stream; | 20 | class Stream; |
21 | class TcpSocket; | 21 | class TcpSocket; |
22 | class ClientLinkFactory; | 22 | class ClientLinkFactory; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | *@ingroup Serving | 25 | *@ingroup Serving |
26 | */ | 26 | */ |
27 | class Client : public Bu::Stream | 27 | class Client : public Bu::Stream |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); | 30 | Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); |
31 | virtual ~Client(); | 31 | virtual ~Client(); |
32 | 32 | ||
33 | void processInput(); | 33 | void processInput(); |
34 | void processOutput(); | 34 | void processOutput(); |
35 | 35 | ||
36 | //Bu::String &getInput(); | 36 | //Bu::String &getInput(); |
37 | //Bu::String &getOutput(); | 37 | //Bu::String &getOutput(); |
38 | Bu::size write( const Bu::String &sData ); | 38 | Bu::size write( const Bu::String &sData ); |
39 | Bu::size write( const void *pData, Bu::size nBytes ); | 39 | Bu::size write( const void *pData, Bu::size nBytes ); |
40 | Bu::size write( int8_t nData ); | 40 | Bu::size write( int8_t nData ); |
41 | Bu::size write( int16_t nData ); | 41 | Bu::size write( int16_t nData ); |
42 | Bu::size write( int32_t nData ); | 42 | Bu::size write( int32_t nData ); |
43 | Bu::size write( int64_t nData ); | 43 | Bu::size write( int64_t nData ); |
44 | Bu::size write( uint8_t nData ); | 44 | Bu::size write( uint8_t nData ); |
45 | Bu::size write( uint16_t nData ); | 45 | Bu::size write( uint16_t nData ); |
46 | Bu::size write( uint32_t nData ); | 46 | Bu::size write( uint32_t nData ); |
47 | Bu::size write( uint64_t nData ); | 47 | Bu::size write( uint64_t nData ); |
48 | Bu::size read( void *pData, Bu::size nBytes ); | 48 | Bu::size read( void *pData, Bu::size nBytes ); |
49 | Bu::size peek( void *pData, int nBytes, int nOffset=0 ); | 49 | Bu::size peek( void *pData, int nBytes, int nOffset=0 ); |
50 | // void seek( int nBytes ); | 50 | // void seek( int nBytes ); |
51 | Bu::size getInputSize(); | 51 | Bu::size getInputSize(); |
52 | Bu::size getOutputSize(); | 52 | Bu::size getOutputSize(); |
53 | 53 | ||
54 | void setProtocol( Protocol *pProto ); | 54 | void setProtocol( Protocol *pProto ); |
55 | Bu::Protocol *getProtocol(); | 55 | Bu::Protocol *getProtocol(); |
56 | void clearProtocol(); | 56 | void clearProtocol(); |
57 | 57 | ||
58 | bool isOpen(); | 58 | bool isOpen(); |
59 | void close(); | 59 | void close(); |
60 | void tick(); | 60 | void tick(); |
61 | 61 | ||
62 | const Bu::TcpSocket *getSocket() const; | 62 | const Bu::TcpSocket *getSocket() const; |
63 | 63 | ||
64 | void disconnect(); | 64 | void disconnect(); |
65 | bool wantsDisconnect(); | 65 | bool wantsDisconnect(); |
66 | 66 | ||
67 | class ClientLink *getLink(); | 67 | class ClientLink *getLink(); |
68 | 68 | ||
69 | void onMessage( const Bu::String &sMsg ); | 69 | void onMessage( const Bu::String &sMsg ); |
70 | 70 | ||
71 | bool hasOutput() { return qbWrite.getSize() > 0; } | 71 | bool hasOutput() { return qbWrite.getSize() > 0; } |
72 | bool hasInput() { return qbRead.getSize() > 0; } | 72 | bool hasInput() { return qbRead.getSize() > 0; } |
73 | 73 | ||
74 | template<typename filter> | 74 | template<typename filter> |
75 | void pushFilter() | 75 | void pushFilter() |
76 | { | 76 | { |
77 | filter *pFlt = new filter( *pTopStream ); | 77 | filter *pFlt = new filter( *pTopStream ); |
78 | pTopStream = pFlt; | 78 | pTopStream = pFlt; |
79 | lFilts.prepend( pFlt ); | 79 | lFilts.prepend( pFlt ); |
80 | } | 80 | } |
81 | 81 | ||
82 | template<typename filter, typename p1t> | 82 | template<typename filter, typename p1t> |
83 | void pushFilter( p1t p1 ) | 83 | void pushFilter( p1t p1 ) |
84 | { | 84 | { |
85 | filter *pFlt = new filter( *pTopStream, p1 ); | 85 | filter *pFlt = new filter( *pTopStream, p1 ); |
86 | pTopStream = pFlt; | 86 | pTopStream = pFlt; |
87 | lFilts.prepend( pFlt ); | 87 | lFilts.prepend( pFlt ); |
88 | } | 88 | } |
89 | 89 | ||
90 | template<typename filter, typename p1t, typename p2t> | 90 | template<typename filter, typename p1t, typename p2t> |
91 | void pushFilter( p1t p1, p2t p2 ) | 91 | void pushFilter( p1t p1, p2t p2 ) |
92 | { | 92 | { |
93 | filter *pFlt = new filter( *pTopStream, p1, p2 ); | 93 | filter *pFlt = new filter( *pTopStream, p1, p2 ); |
94 | pTopStream = pFlt; | 94 | pTopStream = pFlt; |
95 | lFilts.prepend( pFlt ); | 95 | lFilts.prepend( pFlt ); |
96 | } | 96 | } |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * These are required to qualify as a stream, I dunno how many will | 99 | * These are required to qualify as a stream, I dunno how many will |
100 | * be implemented. | 100 | * be implemented. |
101 | */ | 101 | */ |
102 | virtual Bu::size tell(); | 102 | virtual Bu::size tell(); |
103 | virtual void seek( Bu::size offset ); | 103 | virtual void seek( Bu::size offset ); |
104 | virtual void setPos( Bu::size pos ); | 104 | virtual void setPos( Bu::size pos ); |
105 | virtual void setPosEnd( Bu::size pos ); | 105 | virtual void setPosEnd( Bu::size pos ); |
106 | virtual bool isEos(); | 106 | virtual bool isEos(); |
107 | virtual void flush(); | 107 | virtual void flush(); |
108 | virtual bool canRead(); | 108 | virtual bool canRead(); |
109 | virtual bool canWrite(); | 109 | virtual bool canWrite(); |
110 | virtual bool isReadable(); | 110 | virtual bool isReadable(); |
111 | virtual bool isWritable(); | 111 | virtual bool isWritable(); |
112 | virtual bool isSeekable(); | 112 | virtual bool isSeekable(); |
113 | virtual bool isBlocking(); | 113 | virtual bool isBlocking(); |
114 | virtual void setBlocking( bool bBlocking=true ); | 114 | virtual void setBlocking( bool bBlocking=true ); |
115 | virtual void setSize( Bu::size iSize ); | 115 | virtual void setSize( Bu::size iSize ); |
116 | virtual size getSize() const; | 116 | virtual size getSize() const; |
117 | virtual size getBlockSize() const; | 117 | virtual size getBlockSize() const; |
118 | virtual Bu::String getLocation() const; | 118 | virtual Bu::String getLocation() const; |
119 | 119 | ||
120 | private: | 120 | private: |
121 | typedef Bu::List<Bu::Stream *> FilterList; | 121 | typedef Bu::List<Bu::Stream *> FilterList; |
122 | FilterList lFilts; | 122 | FilterList lFilts; |
123 | Bu::Stream *pTopStream; | 123 | Bu::Stream *pTopStream; |
124 | Bu::TcpSocket *pSocket; | 124 | Bu::TcpSocket *pSocket; |
125 | Bu::Protocol *pProto; | 125 | Bu::Protocol *pProto; |
126 | Bu::QueueBuf qbRead; | 126 | Bu::QueueBuf qbRead; |
127 | Bu::QueueBuf qbWrite; | 127 | Bu::QueueBuf qbWrite; |
128 | bool bWantsDisconnect; | 128 | bool bWantsDisconnect; |
129 | class Bu::ClientLinkFactory *pfLink; | 129 | class Bu::ClientLinkFactory *pfLink; |
130 | }; | 130 | }; |
131 | } | 131 | } |
132 | 132 | ||
133 | #endif | 133 | #endif |
diff --git a/src/stable/clientlink.h b/src/stable/clientlink.h index b5cd74d..d822c93 100644 --- a/src/stable/clientlink.h +++ b/src/stable/clientlink.h | |||
@@ -12,14 +12,14 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class ClientLink | 15 | class ClientLink |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | ClientLink(); | 18 | ClientLink(); |
19 | virtual ~ClientLink(); | 19 | virtual ~ClientLink(); |
20 | 20 | ||
21 | virtual void sendMessage( const Bu::String &sMsg )=0; | 21 | virtual void sendMessage( const Bu::String &sMsg )=0; |
22 | }; | 22 | }; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #endif | 25 | #endif |
diff --git a/src/stable/clientlinkfactory.h b/src/stable/clientlinkfactory.h index b1b7670..bd64f6b 100644 --- a/src/stable/clientlinkfactory.h +++ b/src/stable/clientlinkfactory.h | |||
@@ -10,17 +10,17 @@ | |||
10 | 10 | ||
11 | namespace Bu | 11 | namespace Bu |
12 | { | 12 | { |
13 | class Client; | 13 | class Client; |
14 | class ClientLink; | 14 | class ClientLink; |
15 | 15 | ||
16 | class ClientLinkFactory | 16 | class ClientLinkFactory |
17 | { | 17 | { |
18 | public: | 18 | public: |
19 | ClientLinkFactory(); | 19 | ClientLinkFactory(); |
20 | virtual ~ClientLinkFactory(); | 20 | virtual ~ClientLinkFactory(); |
21 | 21 | ||
22 | virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; | 22 | virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; |
23 | }; | 23 | }; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | #endif | 26 | #endif |
diff --git a/src/stable/condition.cpp b/src/stable/condition.cpp index 79af262..f02eca7 100644 --- a/src/stable/condition.cpp +++ b/src/stable/condition.cpp | |||
@@ -11,39 +11,39 @@ | |||
11 | 11 | ||
12 | Bu::Condition::Condition() | 12 | Bu::Condition::Condition() |
13 | { | 13 | { |
14 | pthread_cond_init( &cond, NULL ); | 14 | pthread_cond_init( &cond, NULL ); |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::Condition::~Condition() | 17 | Bu::Condition::~Condition() |
18 | { | 18 | { |
19 | pthread_cond_destroy( &cond ); | 19 | pthread_cond_destroy( &cond ); |
20 | } | 20 | } |
21 | 21 | ||
22 | int Bu::Condition::wait() | 22 | int Bu::Condition::wait() |
23 | { | 23 | { |
24 | return pthread_cond_wait( &cond, &mutex ); | 24 | return pthread_cond_wait( &cond, &mutex ); |
25 | } | 25 | } |
26 | 26 | ||
27 | int Bu::Condition::wait( int nSec, int nUSec ) | 27 | int Bu::Condition::wait( int nSec, int nUSec ) |
28 | { | 28 | { |
29 | struct timeval now; | 29 | struct timeval now; |
30 | struct timespec timeout; | 30 | struct timespec timeout; |
31 | struct timezone tz; | 31 | struct timezone tz; |
32 | 32 | ||
33 | gettimeofday( &now, &tz ); | 33 | gettimeofday( &now, &tz ); |
34 | timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); | 34 | timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); |
35 | timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; | 35 | timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; |
36 | 36 | ||
37 | return pthread_cond_timedwait( &cond, &mutex, &timeout ); | 37 | return pthread_cond_timedwait( &cond, &mutex, &timeout ); |
38 | } | 38 | } |
39 | 39 | ||
40 | int Bu::Condition::signal() | 40 | int Bu::Condition::signal() |
41 | { | 41 | { |
42 | return pthread_cond_signal( &cond ); | 42 | return pthread_cond_signal( &cond ); |
43 | } | 43 | } |
44 | 44 | ||
45 | int Bu::Condition::broadcast() | 45 | int Bu::Condition::broadcast() |
46 | { | 46 | { |
47 | return pthread_cond_broadcast( &cond ); | 47 | return pthread_cond_broadcast( &cond ); |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/src/stable/condition.h b/src/stable/condition.h index 2c27720..53eb9ff 100644 --- a/src/stable/condition.h +++ b/src/stable/condition.h | |||
@@ -14,77 +14,77 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Ito condition. This is a fairly simple condition mechanism. As you may | 18 | * Ito condition. This is a fairly simple condition mechanism. As you may |
19 | * notice this class inherits from the Mutex class, this is because all | 19 | * notice this class inherits from the Mutex class, this is because all |
20 | * conditions must be within a locked block. The standard usage of a | 20 | * conditions must be within a locked block. The standard usage of a |
21 | * condition is to pause one thread, perhaps indefinately, until another | 21 | * condition is to pause one thread, perhaps indefinately, until another |
22 | * thread signals that it is alright to procede. | 22 | * thread signals that it is alright to procede. |
23 | * <br> | 23 | * <br> |
24 | * Standard usage for the thread that wants to wait is as follows: | 24 | * Standard usage for the thread that wants to wait is as follows: |
25 | * <pre> | 25 | * <pre> |
26 | * Condition cond; | 26 | * Condition cond; |
27 | * ... // Perform setup and enter your run loop | 27 | * ... // Perform setup and enter your run loop |
28 | * cond.lock(); | 28 | * cond.lock(); |
29 | * while( !isFinished() ) // Could be anything you're waiting for | 29 | * while( !isFinished() ) // Could be anything you're waiting for |
30 | * cond.wait(); | 30 | * cond.wait(); |
31 | * ... // Take care of what you have to. | 31 | * ... // Take care of what you have to. |
32 | * cond.unlock(); | 32 | * cond.unlock(); |
33 | * </pre> | 33 | * </pre> |
34 | * The usage for the triggering thread is much simpler, when it needs to | 34 | * The usage for the triggering thread is much simpler, when it needs to |
35 | * tell the others that it's time to grab some data it calls either signal | 35 | * tell the others that it's time to grab some data it calls either signal |
36 | * or broadcast. See both of those functions for the difference. | 36 | * or broadcast. See both of those functions for the difference. |
37 | *@ingroup Threading | 37 | *@ingroup Threading |
38 | */ | 38 | */ |
39 | class Condition : public Mutex | 39 | class Condition : public Mutex |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | /** | 42 | /** |
43 | * Create a condition. | 43 | * Create a condition. |
44 | */ | 44 | */ |
45 | Condition(); | 45 | Condition(); |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Destroy a condition. | 48 | * Destroy a condition. |
49 | */ | 49 | */ |
50 | ~Condition(); | 50 | ~Condition(); |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Wait forever, or until signalled. This has to be called from within | 53 | * Wait forever, or until signalled. This has to be called from within |
54 | * a locked section, i.e. before calling this this object's lock | 54 | * a locked section, i.e. before calling this this object's lock |
55 | * function should be called. | 55 | * function should be called. |
56 | */ | 56 | */ |
57 | int wait(); | 57 | int wait(); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * Wait for a maximum of nSec seconds and nUSec micro-seconds or until | 60 | * Wait for a maximum of nSec seconds and nUSec micro-seconds or until |
61 | * signalled. This is a little more friendly function if you want to | 61 | * signalled. This is a little more friendly function if you want to |
62 | * perform other operations in the thrad loop that calls this function. | 62 | * perform other operations in the thrad loop that calls this function. |
63 | * Like the other wait function, this must be inside a locked section. | 63 | * Like the other wait function, this must be inside a locked section. |
64 | *@param nSec The seconds to wait. | 64 | *@param nSec The seconds to wait. |
65 | *@param nUSec the micro-seconds to wait. | 65 | *@param nUSec the micro-seconds to wait. |
66 | */ | 66 | */ |
67 | int wait( int nSec, int nUSec ); | 67 | int wait( int nSec, int nUSec ); |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * Notify the next thread waiting on this condition that they can go | 70 | * Notify the next thread waiting on this condition that they can go |
71 | * ahead. This only signals one thread, the next one in the condition | 71 | * ahead. This only signals one thread, the next one in the condition |
72 | * queue, that it is safe to procede with whatever operation was being | 72 | * queue, that it is safe to procede with whatever operation was being |
73 | * waited on. | 73 | * waited on. |
74 | */ | 74 | */ |
75 | int signal(); | 75 | int signal(); |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Notify all threads waiting on this condition that they can go ahead | 78 | * Notify all threads waiting on this condition that they can go ahead |
79 | * now. This function is slower than signal, but more effective in | 79 | * now. This function is slower than signal, but more effective in |
80 | * certain situations where you may not know how many threads should be | 80 | * certain situations where you may not know how many threads should be |
81 | * activated. | 81 | * activated. |
82 | */ | 82 | */ |
83 | int broadcast(); | 83 | int broadcast(); |
84 | 84 | ||
85 | private: | 85 | private: |
86 | pthread_cond_t cond; /**< Internal condition reference. */ | 86 | pthread_cond_t cond; /**< Internal condition reference. */ |
87 | }; | 87 | }; |
88 | } | 88 | } |
89 | 89 | ||
90 | #endif | 90 | #endif |
diff --git a/src/stable/conduit.cpp b/src/stable/conduit.cpp index 8f5eba5..4c2fda6 100644 --- a/src/stable/conduit.cpp +++ b/src/stable/conduit.cpp | |||
@@ -8,9 +8,9 @@ | |||
8 | #include "bu/conduit.h" | 8 | #include "bu/conduit.h" |
9 | 9 | ||
10 | Bu::Conduit::Conduit( int iBlockSize ) : | 10 | Bu::Conduit::Conduit( int iBlockSize ) : |
11 | qb( iBlockSize ), | 11 | qb( iBlockSize ), |
12 | bBlocking( true ), | 12 | bBlocking( true ), |
13 | bOpen( true ) | 13 | bOpen( true ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,100 +20,100 @@ Bu::Conduit::~Conduit() | |||
20 | 20 | ||
21 | void Bu::Conduit::close() | 21 | void Bu::Conduit::close() |
22 | { | 22 | { |
23 | im.lock(); | 23 | im.lock(); |
24 | // qb.close(); | 24 | // qb.close(); |
25 | bOpen = false; | 25 | bOpen = false; |
26 | 26 | ||
27 | cBlock.signal(); | 27 | cBlock.signal(); |
28 | im.unlock(); | 28 | im.unlock(); |
29 | } | 29 | } |
30 | 30 | ||
31 | #include <stdio.h> | 31 | #include <stdio.h> |
32 | Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) | 32 | Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) |
33 | { | 33 | { |
34 | if( !isOpen() ) | 34 | if( !isOpen() ) |
35 | { | 35 | { |
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | im.lock(); | 38 | im.lock(); |
39 | if( bBlocking ) | 39 | if( bBlocking ) |
40 | { | 40 | { |
41 | im.unlock(); | 41 | im.unlock(); |
42 | cBlock.lock(); | 42 | cBlock.lock(); |
43 | for(;;) | 43 | for(;;) |
44 | { | 44 | { |
45 | im.lock(); | 45 | im.lock(); |
46 | if( qb.getSize() == 0 && bOpen == false ) | 46 | if( qb.getSize() == 0 && bOpen == false ) |
47 | { | 47 | { |
48 | im.unlock(); | 48 | im.unlock(); |
49 | cBlock.unlock(); | 49 | cBlock.unlock(); |
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | else if( qb.getSize() > 0 ) | 52 | else if( qb.getSize() > 0 ) |
53 | { | 53 | { |
54 | im.unlock(); | 54 | im.unlock(); |
55 | break; | 55 | break; |
56 | } | 56 | } |
57 | im.unlock(); | 57 | im.unlock(); |
58 | 58 | ||
59 | cBlock.wait(); | 59 | cBlock.wait(); |
60 | } | 60 | } |
61 | 61 | ||
62 | im.lock(); | 62 | im.lock(); |
63 | Bu::size iRet = qb.read( pBuf, nBytes ); | 63 | Bu::size iRet = qb.read( pBuf, nBytes ); |
64 | im.unlock(); | 64 | im.unlock(); |
65 | 65 | ||
66 | cBlock.unlock(); | 66 | cBlock.unlock(); |
67 | return iRet; | 67 | return iRet; |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | Bu::size iRet = qb.read( pBuf, nBytes ); | 71 | Bu::size iRet = qb.read( pBuf, nBytes ); |
72 | im.unlock(); | 72 | im.unlock(); |
73 | 73 | ||
74 | return iRet; | 74 | return iRet; |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) | 78 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) |
79 | { | 79 | { |
80 | im.lock(); | 80 | im.lock(); |
81 | Bu::size iRet = qb.peek( pBuf, nBytes ); | 81 | Bu::size iRet = qb.peek( pBuf, nBytes ); |
82 | im.unlock(); | 82 | im.unlock(); |
83 | 83 | ||
84 | return iRet; | 84 | return iRet; |
85 | } | 85 | } |
86 | 86 | ||
87 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) | 87 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) |
88 | { | 88 | { |
89 | im.lock(); | 89 | im.lock(); |
90 | Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); | 90 | Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); |
91 | im.unlock(); | 91 | im.unlock(); |
92 | 92 | ||
93 | return iRet; | 93 | return iRet; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) | 96 | Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) |
97 | { | 97 | { |
98 | im.lock(); | 98 | im.lock(); |
99 | if( bOpen == false ) | 99 | if( bOpen == false ) |
100 | { | 100 | { |
101 | im.unlock(); | 101 | im.unlock(); |
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | Bu::size sRet = qb.write( pBuf, nBytes ); | 104 | Bu::size sRet = qb.write( pBuf, nBytes ); |
105 | cBlock.signal(); | 105 | cBlock.signal(); |
106 | im.unlock(); | 106 | im.unlock(); |
107 | 107 | ||
108 | return sRet; | 108 | return sRet; |
109 | } | 109 | } |
110 | 110 | ||
111 | Bu::size Bu::Conduit::tell() | 111 | Bu::size Bu::Conduit::tell() |
112 | { | 112 | { |
113 | im.lock(); | 113 | im.lock(); |
114 | Bu::size sRet = qb.tell(); | 114 | Bu::size sRet = qb.tell(); |
115 | im.unlock(); | 115 | im.unlock(); |
116 | return sRet; | 116 | return sRet; |
117 | } | 117 | } |
118 | 118 | ||
119 | void Bu::Conduit::seek( Bu::size ) | 119 | void Bu::Conduit::seek( Bu::size ) |
@@ -130,18 +130,18 @@ void Bu::Conduit::setPosEnd( Bu::size ) | |||
130 | 130 | ||
131 | bool Bu::Conduit::isEos() | 131 | bool Bu::Conduit::isEos() |
132 | { | 132 | { |
133 | im.lock(); | 133 | im.lock(); |
134 | bool bRet = qb.isEos(); | 134 | bool bRet = qb.isEos(); |
135 | im.unlock(); | 135 | im.unlock(); |
136 | return bRet; | 136 | return bRet; |
137 | } | 137 | } |
138 | 138 | ||
139 | bool Bu::Conduit::isOpen() | 139 | bool Bu::Conduit::isOpen() |
140 | { | 140 | { |
141 | im.lock(); | 141 | im.lock(); |
142 | bool bRet = bOpen || (qb.getSize() > 0); | 142 | bool bRet = bOpen || (qb.getSize() > 0); |
143 | im.unlock(); | 143 | im.unlock(); |
144 | return bRet; | 144 | return bRet; |
145 | } | 145 | } |
146 | 146 | ||
147 | void Bu::Conduit::flush() | 147 | void Bu::Conduit::flush() |
@@ -150,57 +150,57 @@ void Bu::Conduit::flush() | |||
150 | 150 | ||
151 | bool Bu::Conduit::canRead() | 151 | bool Bu::Conduit::canRead() |
152 | { | 152 | { |
153 | im.lock(); | 153 | im.lock(); |
154 | bool bRet = qb.canRead(); | 154 | bool bRet = qb.canRead(); |
155 | im.unlock(); | 155 | im.unlock(); |
156 | return bRet; | 156 | return bRet; |
157 | } | 157 | } |
158 | 158 | ||
159 | bool Bu::Conduit::canWrite() | 159 | bool Bu::Conduit::canWrite() |
160 | { | 160 | { |
161 | im.lock(); | 161 | im.lock(); |
162 | bool bRet = qb.canWrite(); | 162 | bool bRet = qb.canWrite(); |
163 | im.unlock(); | 163 | im.unlock(); |
164 | return bRet; | 164 | return bRet; |
165 | } | 165 | } |
166 | 166 | ||
167 | bool Bu::Conduit::isReadable() | 167 | bool Bu::Conduit::isReadable() |
168 | { | 168 | { |
169 | im.lock(); | 169 | im.lock(); |
170 | bool bRet = qb.isReadable(); | 170 | bool bRet = qb.isReadable(); |
171 | im.unlock(); | 171 | im.unlock(); |
172 | return bRet; | 172 | return bRet; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool Bu::Conduit::isWritable() | 175 | bool Bu::Conduit::isWritable() |
176 | { | 176 | { |
177 | im.lock(); | 177 | im.lock(); |
178 | bool bRet = qb.isWritable(); | 178 | bool bRet = qb.isWritable(); |
179 | im.unlock(); | 179 | im.unlock(); |
180 | return bRet; | 180 | return bRet; |
181 | } | 181 | } |
182 | 182 | ||
183 | bool Bu::Conduit::isSeekable() | 183 | bool Bu::Conduit::isSeekable() |
184 | { | 184 | { |
185 | im.lock(); | 185 | im.lock(); |
186 | bool bRet = qb.isSeekable(); | 186 | bool bRet = qb.isSeekable(); |
187 | im.unlock(); | 187 | im.unlock(); |
188 | return bRet; | 188 | return bRet; |
189 | } | 189 | } |
190 | 190 | ||
191 | bool Bu::Conduit::isBlocking() | 191 | bool Bu::Conduit::isBlocking() |
192 | { | 192 | { |
193 | im.lock(); | 193 | im.lock(); |
194 | bool bRet = bBlocking; | 194 | bool bRet = bBlocking; |
195 | im.unlock(); | 195 | im.unlock(); |
196 | return bRet; | 196 | return bRet; |
197 | } | 197 | } |
198 | 198 | ||
199 | void Bu::Conduit::setBlocking( bool bBlocking ) | 199 | void Bu::Conduit::setBlocking( bool bBlocking ) |
200 | { | 200 | { |
201 | im.lock(); | 201 | im.lock(); |
202 | this->bBlocking = bBlocking; | 202 | this->bBlocking = bBlocking; |
203 | im.unlock(); | 203 | im.unlock(); |
204 | } | 204 | } |
205 | 205 | ||
206 | void Bu::Conduit::setSize( Bu::size ) | 206 | void Bu::Conduit::setSize( Bu::size ) |
@@ -209,25 +209,25 @@ void Bu::Conduit::setSize( Bu::size ) | |||
209 | 209 | ||
210 | Bu::size Bu::Conduit::getSize() const | 210 | Bu::size Bu::Conduit::getSize() const |
211 | { | 211 | { |
212 | im.lock(); | 212 | im.lock(); |
213 | Bu::size sRet = qb.getSize(); | 213 | Bu::size sRet = qb.getSize(); |
214 | im.unlock(); | 214 | im.unlock(); |
215 | return sRet; | 215 | return sRet; |
216 | } | 216 | } |
217 | 217 | ||
218 | Bu::size Bu::Conduit::getBlockSize() const | 218 | Bu::size Bu::Conduit::getBlockSize() const |
219 | { | 219 | { |
220 | im.lock(); | 220 | im.lock(); |
221 | Bu::size sRet = qb.getBlockSize(); | 221 | Bu::size sRet = qb.getBlockSize(); |
222 | im.unlock(); | 222 | im.unlock(); |
223 | return sRet; | 223 | return sRet; |
224 | } | 224 | } |
225 | 225 | ||
226 | Bu::String Bu::Conduit::getLocation() const | 226 | Bu::String Bu::Conduit::getLocation() const |
227 | { | 227 | { |
228 | im.lock(); | 228 | im.lock(); |
229 | Bu::String sRet = qb.getLocation(); | 229 | Bu::String sRet = qb.getLocation(); |
230 | im.unlock(); | 230 | im.unlock(); |
231 | return sRet; | 231 | return sRet; |
232 | } | 232 | } |
233 | 233 | ||
diff --git a/src/stable/conduit.h b/src/stable/conduit.h index a1959a9..78d24eb 100644 --- a/src/stable/conduit.h +++ b/src/stable/conduit.h | |||
@@ -16,49 +16,49 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Simple inter-thread communication stream. This acts like a pair of | 20 | * Simple inter-thread communication stream. This acts like a pair of |
21 | * pipes for stream communication between any two things, but without the | 21 | * pipes for stream communication between any two things, but without the |
22 | * use of pipes, making this a bad choice for IPC. | 22 | * use of pipes, making this a bad choice for IPC. |
23 | */ | 23 | */ |
24 | class Conduit : public Stream | 24 | class Conduit : public Stream |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | Conduit( int iBlockSize=256 ); | 27 | Conduit( int iBlockSize=256 ); |
28 | virtual ~Conduit(); | 28 | virtual ~Conduit(); |
29 | 29 | ||
30 | virtual void close(); | 30 | virtual void close(); |
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); |
33 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); | 33 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); |
34 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 34 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
35 | virtual Bu::size tell(); | 35 | virtual Bu::size tell(); |
36 | virtual void seek( Bu::size offset ); | 36 | virtual void seek( Bu::size offset ); |
37 | virtual void setPos( Bu::size pos ); | 37 | virtual void setPos( Bu::size pos ); |
38 | virtual void setPosEnd( Bu::size pos ); | 38 | virtual void setPosEnd( Bu::size pos ); |
39 | virtual bool isEos(); | 39 | virtual bool isEos(); |
40 | virtual bool isOpen(); | 40 | virtual bool isOpen(); |
41 | virtual void flush(); | 41 | virtual void flush(); |
42 | virtual bool canRead(); | 42 | virtual bool canRead(); |
43 | virtual bool canWrite(); | 43 | virtual bool canWrite(); |
44 | virtual bool isReadable(); | 44 | virtual bool isReadable(); |
45 | virtual bool isWritable(); | 45 | virtual bool isWritable(); |
46 | virtual bool isSeekable(); | 46 | virtual bool isSeekable(); |
47 | virtual bool isBlocking(); | 47 | virtual bool isBlocking(); |
48 | virtual void setBlocking( bool bBlocking=true ); | 48 | virtual void setBlocking( bool bBlocking=true ); |
49 | virtual void setSize( Bu::size iSize ); | 49 | virtual void setSize( Bu::size iSize ); |
50 | 50 | ||
51 | virtual size getSize() const; | 51 | virtual size getSize() const; |
52 | virtual size getBlockSize() const; | 52 | virtual size getBlockSize() const; |
53 | virtual Bu::String getLocation() const; | 53 | virtual Bu::String getLocation() const; |
54 | 54 | ||
55 | private: | 55 | private: |
56 | QueueBuf qb; | 56 | QueueBuf qb; |
57 | mutable Mutex im; | 57 | mutable Mutex im; |
58 | Condition cBlock; | 58 | Condition cBlock; |
59 | bool bBlocking; | 59 | bool bBlocking; |
60 | bool bOpen; | 60 | bool bOpen; |
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #endif | 64 | #endif |
diff --git a/src/stable/crypt.cpp b/src/stable/crypt.cpp index 3f7fc83..2915cf4 100644 --- a/src/stable/crypt.cpp +++ b/src/stable/crypt.cpp | |||
@@ -13,35 +13,35 @@ | |||
13 | 13 | ||
14 | Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) | 14 | Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) |
15 | { | 15 | { |
16 | Bu::Md5 md5; | 16 | Bu::Md5 md5; |
17 | Bu::MemBuf mbOut; | 17 | Bu::MemBuf mbOut; |
18 | Bu::Base64 b64Out( mbOut ); | 18 | Bu::Base64 b64Out( mbOut ); |
19 | 19 | ||
20 | Bu::String::const_iterator i = sSalt.find('$'); | 20 | Bu::String::const_iterator i = sSalt.find('$'); |
21 | Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); | 21 | Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); |
22 | 22 | ||
23 | md5.addData( sPass ); | 23 | md5.addData( sPass ); |
24 | md5.addData( sSaltSml ); | 24 | md5.addData( sSaltSml ); |
25 | md5.writeResult( b64Out ); | 25 | md5.writeResult( b64Out ); |
26 | 26 | ||
27 | b64Out.stop(); | 27 | b64Out.stop(); |
28 | 28 | ||
29 | return sSaltSml + "$" + mbOut.getString(); | 29 | return sSaltSml + "$" + mbOut.getString(); |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::String Bu::cryptPass( const Bu::String &sPass ) | 32 | Bu::String Bu::cryptPass( const Bu::String &sPass ) |
33 | { | 33 | { |
34 | Bu::MemBuf mbSalt; | 34 | Bu::MemBuf mbSalt; |
35 | Bu::Base64 b64Salt( mbSalt ); | 35 | Bu::Base64 b64Salt( mbSalt ); |
36 | Bu::File fRand("/dev/urandom", Bu::File::Read ); | 36 | Bu::File fRand("/dev/urandom", Bu::File::Read ); |
37 | 37 | ||
38 | #define STR 6 | 38 | #define STR 6 |
39 | char buf[STR]; | 39 | char buf[STR]; |
40 | fRand.read( buf, STR ); | 40 | fRand.read( buf, STR ); |
41 | b64Salt.write( buf, STR ); | 41 | b64Salt.write( buf, STR ); |
42 | 42 | ||
43 | b64Salt.stop(); | 43 | b64Salt.stop(); |
44 | 44 | ||
45 | return cryptPass( sPass, mbSalt.getString() ); | 45 | return cryptPass( sPass, mbSalt.getString() ); |
46 | } | 46 | } |
47 | 47 | ||
diff --git a/src/stable/crypt.h b/src/stable/crypt.h index 14adc3a..5093610 100644 --- a/src/stable/crypt.h +++ b/src/stable/crypt.h | |||
@@ -12,8 +12,8 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); | 15 | String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); |
16 | String cryptPass( const Bu::String &sPass ); | 16 | String cryptPass( const Bu::String &sPass ); |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #endif | 19 | #endif |
diff --git a/src/stable/cryptohash.cpp b/src/stable/cryptohash.cpp index dda734c..99a7d92 100644 --- a/src/stable/cryptohash.cpp +++ b/src/stable/cryptohash.cpp | |||
@@ -17,22 +17,22 @@ Bu::CryptoHash::~CryptoHash() | |||
17 | 17 | ||
18 | void Bu::CryptoHash::addData( const Bu::String &sData ) | 18 | void Bu::CryptoHash::addData( const Bu::String &sData ) |
19 | { | 19 | { |
20 | addData( sData.getStr(), sData.getSize() ); | 20 | addData( sData.getStr(), sData.getSize() ); |
21 | } | 21 | } |
22 | 22 | ||
23 | Bu::String Bu::CryptoHash::getHexResult() | 23 | Bu::String Bu::CryptoHash::getHexResult() |
24 | { | 24 | { |
25 | Bu::String sResult = getResult(); | 25 | Bu::String sResult = getResult(); |
26 | Bu::String sRet( 2*sResult.getSize() ); | 26 | Bu::String sRet( 2*sResult.getSize() ); |
27 | static const char hex_tab[] = {"0123456789abcdef"}; | 27 | static const char hex_tab[] = {"0123456789abcdef"}; |
28 | 28 | ||
29 | int k = 0; | 29 | int k = 0; |
30 | for( int i = 0; i < sResult.getSize(); i++ ) | 30 | for( int i = 0; i < sResult.getSize(); i++ ) |
31 | { | 31 | { |
32 | sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; | 32 | sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; |
33 | sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; | 33 | sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; |
34 | } | 34 | } |
35 | 35 | ||
36 | return sRet; | 36 | return sRet; |
37 | } | 37 | } |
38 | 38 | ||
diff --git a/src/stable/cryptohash.h b/src/stable/cryptohash.h index 3f13b05..a943590 100644 --- a/src/stable/cryptohash.h +++ b/src/stable/cryptohash.h | |||
@@ -12,22 +12,22 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class Stream; | 15 | class Stream; |
16 | 16 | ||
17 | class CryptoHash | 17 | class CryptoHash |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | CryptoHash(); | 20 | CryptoHash(); |
21 | virtual ~CryptoHash(); | 21 | virtual ~CryptoHash(); |
22 | 22 | ||
23 | virtual void reset() = 0; | 23 | virtual void reset() = 0; |
24 | virtual void setSalt( const Bu::String &sSalt ) = 0; | 24 | virtual void setSalt( const Bu::String &sSalt ) = 0; |
25 | virtual void addData( const void *sData, int iSize ) = 0; | 25 | virtual void addData( const void *sData, int iSize ) = 0; |
26 | virtual void addData( const Bu::String &sData ); | 26 | virtual void addData( const Bu::String &sData ); |
27 | virtual String getResult() = 0; | 27 | virtual String getResult() = 0; |
28 | virtual void writeResult( Stream &sOut ) = 0; | 28 | virtual void writeResult( Stream &sOut ) = 0; |
29 | virtual Bu::String getHexResult(); | 29 | virtual Bu::String getHexResult(); |
30 | }; | 30 | }; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #endif | 33 | #endif |
diff --git a/src/stable/csvreader.cpp b/src/stable/csvreader.cpp index ddc68f0..c27c8ee 100644 --- a/src/stable/csvreader.cpp +++ b/src/stable/csvreader.cpp | |||
@@ -12,24 +12,24 @@ | |||
12 | using namespace Bu; | 12 | using namespace Bu; |
13 | 13 | ||
14 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : | 14 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : |
15 | sIn( sIn ) | 15 | sIn( sIn ) |
16 | { | 16 | { |
17 | switch( eStyle ) | 17 | switch( eStyle ) |
18 | { | 18 | { |
19 | case styleExcel: | 19 | case styleExcel: |
20 | sDecode = Bu::slot( &decodeExcel ); | 20 | sDecode = Bu::slot( &decodeExcel ); |
21 | break; | 21 | break; |
22 | 22 | ||
23 | case styleC: | 23 | case styleC: |
24 | sDecode = Bu::slot( &decodeC ); | 24 | sDecode = Bu::slot( &decodeC ); |
25 | break; | 25 | break; |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, | 29 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, |
30 | Bu::CsvReader::DecodeSignal sDecode ) : | 30 | Bu::CsvReader::DecodeSignal sDecode ) : |
31 | sIn( sIn ), | 31 | sIn( sIn ), |
32 | sDecode( sDecode ) | 32 | sDecode( sDecode ) |
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
@@ -39,61 +39,61 @@ Bu::CsvReader::~CsvReader() | |||
39 | 39 | ||
40 | Bu::StrArray Bu::CsvReader::readLine() | 40 | Bu::StrArray Bu::CsvReader::readLine() |
41 | { | 41 | { |
42 | Bu::StrArray aVals; | 42 | Bu::StrArray aVals; |
43 | 43 | ||
44 | Bu::String sLine = sIn.readLine(); | 44 | Bu::String sLine = sIn.readLine(); |
45 | 45 | ||
46 | if( !sLine.isSet() ) | 46 | if( !sLine.isSet() ) |
47 | return Bu::StrArray(); | 47 | return Bu::StrArray(); |
48 | 48 | ||
49 | Bu::String::iterator i = sLine.begin(); | 49 | Bu::String::iterator i = sLine.begin(); |
50 | 50 | ||
51 | aVals.append( sDecode( i ) ); | 51 | aVals.append( sDecode( i ) ); |
52 | 52 | ||
53 | while( i ) | 53 | while( i ) |
54 | { | 54 | { |
55 | if( *i == ',' ) | 55 | if( *i == ',' ) |
56 | { | 56 | { |
57 | i++; | 57 | i++; |
58 | if( !i ) | 58 | if( !i ) |
59 | { | 59 | { |
60 | aVals.append(""); | 60 | aVals.append(""); |
61 | break; | 61 | break; |
62 | } | 62 | } |
63 | aVals.append( sDecode( i ) ); | 63 | aVals.append( sDecode( i ) ); |
64 | } | 64 | } |
65 | else | 65 | else |
66 | { | 66 | { |
67 | // Blanks and stuff? | 67 | // Blanks and stuff? |
68 | sio << "Out of bound: '" << *i << "'" << sio.nl; | 68 | sio << "Out of bound: '" << *i << "'" << sio.nl; |
69 | i++; | 69 | i++; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | return aVals; | 73 | return aVals; |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) | 76 | Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) |
77 | { | 77 | { |
78 | Bu::String sRet; | 78 | Bu::String sRet; |
79 | 79 | ||
80 | for(; i && (*i == ' ' || *i == '\t'); i++ ) { } | 80 | for(; i && (*i == ' ' || *i == '\t'); i++ ) { } |
81 | 81 | ||
82 | if( !i ) | 82 | if( !i ) |
83 | return sRet; | 83 | return sRet; |
84 | 84 | ||
85 | if( *i == '\"' ) | 85 | if( *i == '\"' ) |
86 | { | 86 | { |
87 | for( i++ ; i; i++ ) | 87 | for( i++ ; i; i++ ) |
88 | { | 88 | { |
89 | if( *i == '\"' ) | 89 | if( *i == '\"' ) |
90 | { | 90 | { |
91 | i++; | 91 | i++; |
92 | if( !i ) | 92 | if( !i ) |
93 | { | 93 | { |
94 | return sRet; | 94 | return sRet; |
95 | } | 95 | } |
96 | else if( *i == '\"' ) | 96 | else if( *i == '\"' ) |
97 | { | 97 | { |
98 | sRet += *i; | 98 | sRet += *i; |
99 | } | 99 | } |
diff --git a/src/stable/csvreader.h b/src/stable/csvreader.h index 6825da3..cb2a560 100644 --- a/src/stable/csvreader.h +++ b/src/stable/csvreader.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | typedef Bu::Array<Bu::String> StrArray; | 18 | typedef Bu::Array<Bu::String> StrArray; |
19 | 19 | ||
20 | class CsvReader | 20 | class CsvReader |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | typedef Bu::Signal1<Bu::String, Bu::String::iterator &> DecodeSignal; | 23 | typedef Bu::Signal1<Bu::String, Bu::String::iterator &> DecodeSignal; |
24 | enum Style | 24 | enum Style |
25 | { | 25 | { |
26 | styleExcel, ///< Excel style quotes around things that need em | 26 | styleExcel, ///< Excel style quotes around things that need em |
27 | styleC ///< Escape things that need it C-style | 27 | styleC ///< Escape things that need it C-style |
28 | }; | 28 | }; |
29 | 29 | ||
30 | CsvReader( Stream &sIn, Style eStyle=styleExcel ); | 30 | CsvReader( Stream &sIn, Style eStyle=styleExcel ); |
31 | CsvReader( Stream &sIn, DecodeSignal sDecode ); | 31 | CsvReader( Stream &sIn, DecodeSignal sDecode ); |
32 | virtual ~CsvReader(); | 32 | virtual ~CsvReader(); |
33 | 33 | ||
34 | StrArray readLine(); | 34 | StrArray readLine(); |
35 | 35 | ||
36 | private: | 36 | private: |
37 | Stream &sIn; | 37 | Stream &sIn; |
38 | DecodeSignal sDecode; | 38 | DecodeSignal sDecode; |
39 | 39 | ||
40 | static Bu::String decodeExcel( Bu::String::iterator &i ); | 40 | static Bu::String decodeExcel( Bu::String::iterator &i ); |
41 | static Bu::String decodeC( Bu::String::iterator &i ); | 41 | static Bu::String decodeC( Bu::String::iterator &i ); |
42 | }; | 42 | }; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/csvwriter.cpp b/src/stable/csvwriter.cpp index a89b309..8b51115 100644 --- a/src/stable/csvwriter.cpp +++ b/src/stable/csvwriter.cpp | |||
@@ -9,24 +9,24 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : | 11 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : |
12 | sOut( sOut ) | 12 | sOut( sOut ) |
13 | { | 13 | { |
14 | switch( eStyle ) | 14 | switch( eStyle ) |
15 | { | 15 | { |
16 | case styleExcel: | 16 | case styleExcel: |
17 | sEncode = Bu::slot( &encodeExcel ); | 17 | sEncode = Bu::slot( &encodeExcel ); |
18 | break; | 18 | break; |
19 | 19 | ||
20 | case styleC: | 20 | case styleC: |
21 | sEncode = Bu::slot( &encodeExcel ); | 21 | sEncode = Bu::slot( &encodeExcel ); |
22 | break; | 22 | break; |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, | 26 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, |
27 | Bu::CsvWriter::EncodeSignal sEncode ) : | 27 | Bu::CsvWriter::EncodeSignal sEncode ) : |
28 | sOut( sOut ), | 28 | sOut( sOut ), |
29 | sEncode( sEncode ) | 29 | sEncode( sEncode ) |
30 | { | 30 | { |
31 | } | 31 | } |
32 | 32 | ||
@@ -36,46 +36,46 @@ Bu::CsvWriter::~CsvWriter() | |||
36 | 36 | ||
37 | void Bu::CsvWriter::writeLine( const StrArray &aStrs ) | 37 | void Bu::CsvWriter::writeLine( const StrArray &aStrs ) |
38 | { | 38 | { |
39 | Bu::String sBuf; | 39 | Bu::String sBuf; |
40 | for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) | 40 | for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( i != aStrs.begin() ) | 42 | if( i != aStrs.begin() ) |
43 | sBuf += ","; | 43 | sBuf += ","; |
44 | sBuf += sEncode( *i ); | 44 | sBuf += sEncode( *i ); |
45 | } | 45 | } |
46 | sBuf += "\n"; | 46 | sBuf += "\n"; |
47 | 47 | ||
48 | sOut.write( sBuf ); | 48 | sOut.write( sBuf ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) | 51 | Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) |
52 | { | 52 | { |
53 | if( sIn.find('\"') || sIn.find(',') ) | 53 | if( sIn.find('\"') || sIn.find(',') ) |
54 | { | 54 | { |
55 | Bu::String sOut = "\""; | 55 | Bu::String sOut = "\""; |
56 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) | 56 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) |
57 | { | 57 | { |
58 | if( *i == '\"' ) | 58 | if( *i == '\"' ) |
59 | sOut += "\"\""; | 59 | sOut += "\"\""; |
60 | else | 60 | else |
61 | sOut += *i; | 61 | sOut += *i; |
62 | } | 62 | } |
63 | sOut += '\"'; | 63 | sOut += '\"'; |
64 | return sOut; | 64 | return sOut; |
65 | } | 65 | } |
66 | return sIn; | 66 | return sIn; |
67 | } | 67 | } |
68 | 68 | ||
69 | Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) | 69 | Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) |
70 | { | 70 | { |
71 | Bu::String sOut = ""; | 71 | Bu::String sOut = ""; |
72 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) | 72 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) |
73 | { | 73 | { |
74 | if( *i == ',' ) | 74 | if( *i == ',' ) |
75 | sOut += "\\,"; | 75 | sOut += "\\,"; |
76 | else | 76 | else |
77 | sOut += *i; | 77 | sOut += *i; |
78 | } | 78 | } |
79 | return sOut; | 79 | return sOut; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/src/stable/csvwriter.h b/src/stable/csvwriter.h index bae1e1d..233f4ed 100644 --- a/src/stable/csvwriter.h +++ b/src/stable/csvwriter.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | typedef Bu::Array<Bu::String> StrArray; | 18 | typedef Bu::Array<Bu::String> StrArray; |
19 | 19 | ||
20 | class CsvWriter | 20 | class CsvWriter |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | typedef Bu::Signal1<Bu::String, const Bu::String &> EncodeSignal; | 23 | typedef Bu::Signal1<Bu::String, const Bu::String &> EncodeSignal; |
24 | enum Style | 24 | enum Style |
25 | { | 25 | { |
26 | styleExcel, ///< Excel style quotes around things that need em | 26 | styleExcel, ///< Excel style quotes around things that need em |
27 | styleC ///< Escape things that need it C-style | 27 | styleC ///< Escape things that need it C-style |
28 | }; | 28 | }; |
29 | 29 | ||
30 | CsvWriter( Stream &sOut, Style eStyle=styleExcel ); | 30 | CsvWriter( Stream &sOut, Style eStyle=styleExcel ); |
31 | CsvWriter( Stream &sOut, EncodeSignal sEncode ); | 31 | CsvWriter( Stream &sOut, EncodeSignal sEncode ); |
32 | virtual ~CsvWriter(); | 32 | virtual ~CsvWriter(); |
33 | 33 | ||
34 | void writeLine( const StrArray &aStrs ); | 34 | void writeLine( const StrArray &aStrs ); |
35 | 35 | ||
36 | private: | 36 | private: |
37 | Stream &sOut; | 37 | Stream &sOut; |
38 | EncodeSignal sEncode; | 38 | EncodeSignal sEncode; |
39 | 39 | ||
40 | static Bu::String encodeExcel( const Bu::String &sIn ); | 40 | static Bu::String encodeExcel( const Bu::String &sIn ); |
41 | static Bu::String encodeC( const Bu::String &sIn ); | 41 | static Bu::String encodeC( const Bu::String &sIn ); |
42 | }; | 42 | }; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/deflate.cpp b/src/stable/deflate.cpp index b7e1804..57aa4aa 100644 --- a/src/stable/deflate.cpp +++ b/src/stable/deflate.cpp | |||
@@ -15,239 +15,239 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : | 17 | Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ), | 21 | sTotalOut( 0 ), |
22 | eFmt( eFmt ), | 22 | eFmt( eFmt ), |
23 | bEos( false ) | 23 | bEos( false ) |
24 | { | 24 | { |
25 | TRACE( nCompression ); | 25 | TRACE( nCompression ); |
26 | start(); | 26 | start(); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Deflate::~Deflate() | 29 | Bu::Deflate::~Deflate() |
30 | { | 30 | { |
31 | TRACE(); | 31 | TRACE(); |
32 | stop(); | 32 | stop(); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Deflate::start() | 35 | void Bu::Deflate::start() |
36 | { | 36 | { |
37 | TRACE(); | 37 | TRACE(); |
38 | prState = new z_stream; | 38 | prState = new z_stream; |
39 | pState->zalloc = NULL; | 39 | pState->zalloc = NULL; |
40 | pState->zfree = NULL; | 40 | pState->zfree = NULL; |
41 | pState->opaque = NULL; | 41 | pState->opaque = NULL; |
42 | pState->state = NULL; | 42 | pState->state = NULL; |
43 | 43 | ||
44 | nBufSize = 64*1024; | 44 | nBufSize = 64*1024; |
45 | pBuf = new char[nBufSize]; | 45 | pBuf = new char[nBufSize]; |
46 | } | 46 | } |
47 | 47 | ||
48 | Bu::size Bu::Deflate::stop() | 48 | Bu::size Bu::Deflate::stop() |
49 | { | 49 | { |
50 | TRACE(); | 50 | TRACE(); |
51 | if( pState && pState->state ) | 51 | if( pState && pState->state ) |
52 | { | 52 | { |
53 | if( bReading ) | 53 | if( bReading ) |
54 | { | 54 | { |
55 | inflateEnd( pState ); | 55 | inflateEnd( pState ); |
56 | delete[] pBuf; | 56 | delete[] pBuf; |
57 | pBuf = NULL; | 57 | pBuf = NULL; |
58 | delete pState; | 58 | delete pState; |
59 | prState = NULL; | 59 | prState = NULL; |
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | else | 62 | else |
63 | { | 63 | { |
64 | for(;;) | 64 | for(;;) |
65 | { | 65 | { |
66 | pState->next_in = NULL; | 66 | pState->next_in = NULL; |
67 | pState->avail_in = 0; | 67 | pState->avail_in = 0; |
68 | pState->avail_out = nBufSize; | 68 | pState->avail_out = nBufSize; |
69 | pState->next_out = (Bytef *)pBuf; | 69 | pState->next_out = (Bytef *)pBuf; |
70 | int res = deflate( pState, Z_FINISH ); | 70 | int res = deflate( pState, Z_FINISH ); |
71 | if( pState->avail_out < nBufSize ) | 71 | if( pState->avail_out < nBufSize ) |
72 | { | 72 | { |
73 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 73 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
74 | } | 74 | } |
75 | if( res == Z_STREAM_END ) | 75 | if( res == Z_STREAM_END ) |
76 | break; | 76 | break; |
77 | } | 77 | } |
78 | deflateEnd( pState ); | 78 | deflateEnd( pState ); |
79 | delete[] pBuf; | 79 | delete[] pBuf; |
80 | pBuf = NULL; | 80 | pBuf = NULL; |
81 | delete pState; | 81 | delete pState; |
82 | prState = NULL; | 82 | prState = NULL; |
83 | return sTotalOut; | 83 | return sTotalOut; |
84 | } | 84 | } |
85 | } | 85 | } |
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | void Bu::Deflate::zError( int code ) | 89 | void Bu::Deflate::zError( int code ) |
90 | { | 90 | { |
91 | TRACE( code ); | 91 | TRACE( code ); |
92 | switch( code ) | 92 | switch( code ) |
93 | { | 93 | { |
94 | case Z_OK: | 94 | case Z_OK: |
95 | case Z_STREAM_END: | 95 | case Z_STREAM_END: |
96 | case Z_NEED_DICT: | 96 | case Z_NEED_DICT: |
97 | return; | 97 | return; |
98 | 98 | ||
99 | case Z_ERRNO: | 99 | case Z_ERRNO: |
100 | throw ExceptionBase("Deflate: Errno - %s", pState->msg ); | 100 | throw ExceptionBase("Deflate: Errno - %s", pState->msg ); |
101 | 101 | ||
102 | case Z_STREAM_ERROR: | 102 | case Z_STREAM_ERROR: |
103 | throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); | 103 | throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); |
104 | 104 | ||
105 | case Z_DATA_ERROR: | 105 | case Z_DATA_ERROR: |
106 | throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); | 106 | throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); |
107 | 107 | ||
108 | case Z_MEM_ERROR: | 108 | case Z_MEM_ERROR: |
109 | throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); | 109 | throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); |
110 | 110 | ||
111 | case Z_BUF_ERROR: | 111 | case Z_BUF_ERROR: |
112 | throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); | 112 | throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); |
113 | 113 | ||
114 | case Z_VERSION_ERROR: | 114 | case Z_VERSION_ERROR: |
115 | throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); | 115 | throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); |
116 | 116 | ||
117 | default: | 117 | default: |
118 | throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); | 118 | throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); |
119 | 119 | ||
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) | 123 | Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) |
124 | { | 124 | { |
125 | TRACE( pData, nBytes ); | 125 | TRACE( pData, nBytes ); |
126 | if( nBytes <= 0 ) | 126 | if( nBytes <= 0 ) |
127 | return 0; | 127 | return 0; |
128 | if( !pState->state ) | 128 | if( !pState->state ) |
129 | { | 129 | { |
130 | bReading = true; | 130 | bReading = true; |
131 | if( eFmt&AutoDetect ) | 131 | if( eFmt&AutoDetect ) |
132 | inflateInit2( pState, 32+15 ); // Auto-detect, large window | 132 | inflateInit2( pState, 32+15 ); // Auto-detect, large window |
133 | else if( eFmt == Raw ) | 133 | else if( eFmt == Raw ) |
134 | inflateInit2( pState, -15 ); // Raw | 134 | inflateInit2( pState, -15 ); // Raw |
135 | else if( eFmt == Zlib ) | 135 | else if( eFmt == Zlib ) |
136 | inflateInit2( pState, 15 ); // Zlib | 136 | inflateInit2( pState, 15 ); // Zlib |
137 | else if( eFmt == Gzip ) | 137 | else if( eFmt == Gzip ) |
138 | inflateInit2( pState, 16+15 ); // GZip | 138 | inflateInit2( pState, 16+15 ); // GZip |
139 | else | 139 | else |
140 | throw Bu::ExceptionBase("Format mode for deflate read."); | 140 | throw Bu::ExceptionBase("Format mode for deflate read."); |
141 | pState->next_in = (Bytef *)pBuf; | 141 | pState->next_in = (Bytef *)pBuf; |
142 | pState->avail_in = 0; | 142 | pState->avail_in = 0; |
143 | } | 143 | } |
144 | if( bReading == false ) | 144 | if( bReading == false ) |
145 | throw ExceptionBase("This deflate filter is in writing mode, you can't read."); | 145 | throw ExceptionBase("This deflate filter is in writing mode, you can't read."); |
146 | 146 | ||
147 | int nRead = 0; | 147 | int nRead = 0; |
148 | int nReadTotal = pState->total_out; | 148 | int nReadTotal = pState->total_out; |
149 | pState->next_out = (Bytef *)pData; | 149 | pState->next_out = (Bytef *)pData; |
150 | pState->avail_out = nBytes; | 150 | pState->avail_out = nBytes; |
151 | for(;;) | 151 | for(;;) |
152 | { | 152 | { |
153 | int ret = inflate( pState, Z_NO_FLUSH ); | 153 | int ret = inflate( pState, Z_NO_FLUSH ); |
154 | nReadTotal += nRead-pState->avail_out; | 154 | nReadTotal += nRead-pState->avail_out; |
155 | 155 | ||
156 | if( ret == Z_STREAM_END ) | 156 | if( ret == Z_STREAM_END ) |
157 | { | 157 | { |
158 | bEos = true; | 158 | bEos = true; |
159 | if( pState->avail_in > 0 ) | 159 | if( pState->avail_in > 0 ) |
160 | { | 160 | { |
161 | if( rNext.isSeekable() ) | 161 | if( rNext.isSeekable() ) |
162 | { | 162 | { |
163 | rNext.seek( -pState->avail_in ); | 163 | rNext.seek( -pState->avail_in ); |
164 | } | 164 | } |
165 | } | 165 | } |
166 | return nBytes-pState->avail_out; | 166 | return nBytes-pState->avail_out; |
167 | } | 167 | } |
168 | if( ret != Z_BUF_ERROR ) | 168 | if( ret != Z_BUF_ERROR ) |
169 | zError( ret ); | 169 | zError( ret ); |
170 | 170 | ||
171 | if( pState->avail_out ) | 171 | if( pState->avail_out ) |
172 | { | 172 | { |
173 | if( pState->avail_in == 0 ) | 173 | if( pState->avail_in == 0 ) |
174 | { | 174 | { |
175 | nRead = rNext.read( pBuf, nBufSize ); | 175 | nRead = rNext.read( pBuf, nBufSize ); |
176 | if( nRead == 0 && rNext.isEos() ) | 176 | if( nRead == 0 && rNext.isEos() ) |
177 | { | 177 | { |
178 | throw Bu::ExceptionBase("Premature end of underlying " | 178 | throw Bu::ExceptionBase("Premature end of underlying " |
179 | "stream found reading deflate stream."); | 179 | "stream found reading deflate stream."); |
180 | } | 180 | } |
181 | pState->next_in = (Bytef *)pBuf; | 181 | pState->next_in = (Bytef *)pBuf; |
182 | pState->avail_in = nRead; | 182 | pState->avail_in = nRead; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | else | 185 | else |
186 | { | 186 | { |
187 | return nBytes-pState->avail_out; | 187 | return nBytes-pState->avail_out; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) | 193 | Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) |
194 | { | 194 | { |
195 | TRACE( pData, nBytes ); | 195 | TRACE( pData, nBytes ); |
196 | if( nBytes <= 0 ) | 196 | if( nBytes <= 0 ) |
197 | return 0; | 197 | return 0; |
198 | if( !pState->state ) | 198 | if( !pState->state ) |
199 | { | 199 | { |
200 | bReading = false; | 200 | bReading = false; |
201 | int iFmt = eFmt&Gzip; | 201 | int iFmt = eFmt&Gzip; |
202 | if( iFmt == Raw ) | 202 | if( iFmt == Raw ) |
203 | deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, | 203 | deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, |
204 | Z_DEFAULT_STRATEGY ); | 204 | Z_DEFAULT_STRATEGY ); |
205 | else if( iFmt == Zlib ) | 205 | else if( iFmt == Zlib ) |
206 | deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, | 206 | deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, |
207 | Z_DEFAULT_STRATEGY ); | 207 | Z_DEFAULT_STRATEGY ); |
208 | else if( iFmt == Gzip ) | 208 | else if( iFmt == Gzip ) |
209 | deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, | 209 | deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, |
210 | Z_DEFAULT_STRATEGY ); | 210 | Z_DEFAULT_STRATEGY ); |
211 | else | 211 | else |
212 | throw Bu::ExceptionBase("Invalid format for deflate."); | 212 | throw Bu::ExceptionBase("Invalid format for deflate."); |
213 | } | 213 | } |
214 | if( bReading == true ) | 214 | if( bReading == true ) |
215 | throw ExceptionBase("This deflate filter is in reading mode, you can't write."); | 215 | throw ExceptionBase("This deflate filter is in reading mode, you can't write."); |
216 | 216 | ||
217 | pState->next_in = (Bytef *)pData; | 217 | pState->next_in = (Bytef *)pData; |
218 | pState->avail_in = nBytes; | 218 | pState->avail_in = nBytes; |
219 | for(;;) | 219 | for(;;) |
220 | { | 220 | { |
221 | pState->avail_out = nBufSize; | 221 | pState->avail_out = nBufSize; |
222 | pState->next_out = (Bytef *)pBuf; | 222 | pState->next_out = (Bytef *)pBuf; |
223 | 223 | ||
224 | zError( deflate( pState, Z_NO_FLUSH ) ); | 224 | zError( deflate( pState, Z_NO_FLUSH ) ); |
225 | 225 | ||
226 | if( pState->avail_out < nBufSize ) | 226 | if( pState->avail_out < nBufSize ) |
227 | { | 227 | { |
228 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 228 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
229 | } | 229 | } |
230 | if( pState->avail_in == 0 ) | 230 | if( pState->avail_in == 0 ) |
231 | break; | 231 | break; |
232 | } | 232 | } |
233 | 233 | ||
234 | return nBytes; | 234 | return nBytes; |
235 | } | 235 | } |
236 | 236 | ||
237 | bool Bu::Deflate::isOpen() | 237 | bool Bu::Deflate::isOpen() |
238 | { | 238 | { |
239 | TRACE(); | 239 | TRACE(); |
240 | return (pState != NULL && pState->state != NULL); | 240 | return (pState != NULL && pState->state != NULL); |
241 | } | 241 | } |
242 | 242 | ||
243 | bool Bu::Deflate::isEos() | 243 | bool Bu::Deflate::isEos() |
244 | { | 244 | { |
245 | TRACE(); | 245 | TRACE(); |
246 | return bEos; | 246 | return bEos; |
247 | } | 247 | } |
248 | 248 | ||
249 | Bu::size Bu::Deflate::getCompressedSize() | 249 | Bu::size Bu::Deflate::getCompressedSize() |
250 | { | 250 | { |
251 | return sTotalOut; | 251 | return sTotalOut; |
252 | } | 252 | } |
253 | 253 | ||
diff --git a/src/stable/deflate.h b/src/stable/deflate.h index 114b173..2ccd53f 100644 --- a/src/stable/deflate.h +++ b/src/stable/deflate.h | |||
@@ -14,53 +14,53 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and | 18 | * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and |
19 | * gzip stream types. By default it will autodetect the input type and | 19 | * gzip stream types. By default it will autodetect the input type and |
20 | * encode into a raw deflate stream. | 20 | * encode into a raw deflate stream. |
21 | * | 21 | * |
22 | *@ingroup Streams | 22 | *@ingroup Streams |
23 | *@ingroup Compression | 23 | *@ingroup Compression |
24 | */ | 24 | */ |
25 | class Deflate : public Bu::Filter | 25 | class Deflate : public Bu::Filter |
26 | { | 26 | { |
27 | public: | 27 | public: |
28 | enum Format | 28 | enum Format |
29 | { | 29 | { |
30 | Raw = 0x01, | 30 | Raw = 0x01, |
31 | Zlib = 0x02, | 31 | Zlib = 0x02, |
32 | Gzip = 0x03, | 32 | Gzip = 0x03, |
33 | AutoDetect = 0x04, | 33 | AutoDetect = 0x04, |
34 | 34 | ||
35 | AutoRaw = 0x04|0x01, | 35 | AutoRaw = 0x04|0x01, |
36 | AutoZlib = 0x04|0x02, | 36 | AutoZlib = 0x04|0x02, |
37 | AutoGzip = 0x04|0x03 | 37 | AutoGzip = 0x04|0x03 |
38 | }; | 38 | }; |
39 | 39 | ||
40 | Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); | 40 | Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); |
41 | virtual ~Deflate(); | 41 | virtual ~Deflate(); |
42 | 42 | ||
43 | virtual void start(); | 43 | virtual void start(); |
44 | virtual Bu::size stop(); | 44 | virtual Bu::size stop(); |
45 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 45 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
46 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 46 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
47 | 47 | ||
48 | virtual bool isOpen(); | 48 | virtual bool isOpen(); |
49 | virtual bool isEos(); | 49 | virtual bool isEos(); |
50 | 50 | ||
51 | Bu::size getCompressedSize(); | 51 | Bu::size getCompressedSize(); |
52 | 52 | ||
53 | private: | 53 | private: |
54 | void zError( int code ); | 54 | void zError( int code ); |
55 | void *prState; | 55 | void *prState; |
56 | bool bReading; | 56 | bool bReading; |
57 | int nCompression; | 57 | int nCompression; |
58 | char *pBuf; | 58 | char *pBuf; |
59 | uint32_t nBufSize; | 59 | uint32_t nBufSize; |
60 | Bu::size sTotalOut; | 60 | Bu::size sTotalOut; |
61 | Format eFmt; | 61 | Format eFmt; |
62 | bool bEos; | 62 | bool bEos; |
63 | }; | 63 | }; |
64 | } | 64 | } |
65 | 65 | ||
66 | #endif | 66 | #endif |
diff --git a/src/stable/exceptionbase.cpp b/src/stable/exceptionbase.cpp index 87e7127..22f338f 100644 --- a/src/stable/exceptionbase.cpp +++ b/src/stable/exceptionbase.cpp | |||
@@ -11,83 +11,83 @@ | |||
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | 12 | ||
13 | Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : | 13 | Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : |
14 | nErrorCode( 0 ), | 14 | nErrorCode( 0 ), |
15 | sWhat( NULL ) | 15 | sWhat( NULL ) |
16 | { | 16 | { |
17 | va_list ap; | 17 | va_list ap; |
18 | 18 | ||
19 | va_start(ap, lpFormat); | 19 | va_start(ap, lpFormat); |
20 | setWhat( lpFormat, ap ); | 20 | setWhat( lpFormat, ap ); |
21 | va_end(ap); | 21 | va_end(ap); |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : | 24 | Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : |
25 | nErrorCode( nCode ), | 25 | nErrorCode( nCode ), |
26 | sWhat( NULL ) | 26 | sWhat( NULL ) |
27 | { | 27 | { |
28 | va_list ap; | 28 | va_list ap; |
29 | 29 | ||
30 | va_start(ap, lpFormat); | 30 | va_start(ap, lpFormat); |
31 | setWhat( lpFormat, ap ); | 31 | setWhat( lpFormat, ap ); |
32 | va_end(ap); | 32 | va_end(ap); |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : | 35 | Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : |
36 | nErrorCode( nCode ), | 36 | nErrorCode( nCode ), |
37 | sWhat( NULL ) | 37 | sWhat( NULL ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : | 41 | Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : |
42 | std::exception( e ), | 42 | std::exception( e ), |
43 | nErrorCode( e.nErrorCode ), | 43 | nErrorCode( e.nErrorCode ), |
44 | sWhat( NULL ) | 44 | sWhat( NULL ) |
45 | { | 45 | { |
46 | setWhat( e.sWhat ); | 46 | setWhat( e.sWhat ); |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::ExceptionBase::~ExceptionBase() throw() | 49 | Bu::ExceptionBase::~ExceptionBase() throw() |
50 | { | 50 | { |
51 | delete[] sWhat; | 51 | delete[] sWhat; |
52 | sWhat = NULL; | 52 | sWhat = NULL; |
53 | } | 53 | } |
54 | 54 | ||
55 | void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) | 55 | void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) |
56 | { | 56 | { |
57 | if( sWhat ) delete[] sWhat; | 57 | if( sWhat ) delete[] sWhat; |
58 | int nSize; | 58 | int nSize; |
59 | 59 | ||
60 | va_list vargs2; | 60 | va_list vargs2; |
61 | va_copy( vargs2, vargs ); | 61 | va_copy( vargs2, vargs ); |
62 | nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); | 62 | nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); |
63 | va_end( vargs2 ); | 63 | va_end( vargs2 ); |
64 | sWhat = new char[nSize+1]; | 64 | sWhat = new char[nSize+1]; |
65 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); | 65 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); |
66 | } | 66 | } |
67 | 67 | ||
68 | void Bu::ExceptionBase::setWhat( const char *lpText ) | 68 | void Bu::ExceptionBase::setWhat( const char *lpText ) |
69 | { | 69 | { |
70 | if( sWhat ) delete[] sWhat; | 70 | if( sWhat ) delete[] sWhat; |
71 | int nSize; | 71 | int nSize; |
72 | 72 | ||
73 | nSize = strlen( lpText ); | 73 | nSize = strlen( lpText ); |
74 | sWhat = new char[nSize+1]; | 74 | sWhat = new char[nSize+1]; |
75 | strcpy( sWhat, lpText ); | 75 | strcpy( sWhat, lpText ); |
76 | } | 76 | } |
77 | 77 | ||
78 | const char *Bu::ExceptionBase::what() const throw() | 78 | const char *Bu::ExceptionBase::what() const throw() |
79 | { | 79 | { |
80 | return sWhat; | 80 | return sWhat; |
81 | } | 81 | } |
82 | 82 | ||
83 | int Bu::ExceptionBase::getErrorCode() | 83 | int Bu::ExceptionBase::getErrorCode() |
84 | { | 84 | { |
85 | return nErrorCode; | 85 | return nErrorCode; |
86 | } | 86 | } |
87 | 87 | ||
88 | Bu::UnsupportedException::UnsupportedException() throw() : | 88 | Bu::UnsupportedException::UnsupportedException() throw() : |
89 | ExceptionBase( 0 ) | 89 | ExceptionBase( 0 ) |
90 | { | 90 | { |
91 | setWhat("An unsupperted operation was attempted."); | 91 | setWhat("An unsupperted operation was attempted."); |
92 | } | 92 | } |
93 | 93 | ||
diff --git a/src/stable/exceptionbase.h b/src/stable/exceptionbase.h index 9e6c72d..8f651b7 100644 --- a/src/stable/exceptionbase.h +++ b/src/stable/exceptionbase.h | |||
@@ -18,173 +18,173 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | /** | 21 | /** |
22 | * A generalized Exception base class. This is nice for making general and | 22 | * A generalized Exception base class. This is nice for making general and |
23 | * flexible child classes that can create new error code classes. | 23 | * flexible child classes that can create new error code classes. |
24 | * | 24 | * |
25 | * In order to create your own exception class use these two lines. | 25 | * In order to create your own exception class use these two lines. |
26 | * | 26 | * |
27 | * in your header: subExceptionDecl( NewClassName ); | 27 | * in your header: subExceptionDecl( NewClassName ); |
28 | * | 28 | * |
29 | * in your source: subExcpetienDef( NewClassName ); | 29 | * in your source: subExcpetienDef( NewClassName ); |
30 | */ | 30 | */ |
31 | class ExceptionBase : public std::exception | 31 | class ExceptionBase : public std::exception |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | /** | 34 | /** |
35 | * Construct an exception with an error code of zero, but with a | 35 | * Construct an exception with an error code of zero, but with a |
36 | * description. The use of this is not reccomended most of the time, | 36 | * description. The use of this is not reccomended most of the time, |
37 | * it's generally best to include an error code with the exception so | 37 | * it's generally best to include an error code with the exception so |
38 | * your program can handle the exception in a better way. | 38 | * your program can handle the exception in a better way. |
39 | * @param sFormat The format of the text. See printf for more info. | 39 | * @param sFormat The format of the text. See printf for more info. |
40 | */ | 40 | */ |
41 | ExceptionBase( const char *sFormat, ... ) throw(); | 41 | ExceptionBase( const char *sFormat, ... ) throw(); |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * | 44 | * |
45 | * @param nCode | 45 | * @param nCode |
46 | * @param sFormat | 46 | * @param sFormat |
47 | */ | 47 | */ |
48 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); | 48 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * | 51 | * |
52 | * @param nCode | 52 | * @param nCode |
53 | * @return | 53 | * @return |
54 | */ | 54 | */ |
55 | ExceptionBase( int nCode=0 ) throw(); | 55 | ExceptionBase( int nCode=0 ) throw(); |
56 | 56 | ||
57 | ExceptionBase( const ExceptionBase &e ) throw (); | 57 | ExceptionBase( const ExceptionBase &e ) throw (); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * | 60 | * |
61 | * @return | 61 | * @return |
62 | */ | 62 | */ |
63 | virtual ~ExceptionBase() throw(); | 63 | virtual ~ExceptionBase() throw(); |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * | 66 | * |
67 | * @return | 67 | * @return |
68 | */ | 68 | */ |
69 | virtual const char *what() const throw(); | 69 | virtual const char *what() const throw(); |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * | 72 | * |
73 | * @return | 73 | * @return |
74 | */ | 74 | */ |
75 | int getErrorCode(); | 75 | int getErrorCode(); |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * | 78 | * |
79 | * @param lpFormat | 79 | * @param lpFormat |
80 | * @param vargs | 80 | * @param vargs |
81 | */ | 81 | */ |
82 | void setWhat( const char *lpFormat, va_list &vargs ); | 82 | void setWhat( const char *lpFormat, va_list &vargs ); |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * | 85 | * |
86 | * @param lpText | 86 | * @param lpText |
87 | */ | 87 | */ |
88 | void setWhat( const char *lpText ); | 88 | void setWhat( const char *lpText ); |
89 | 89 | ||
90 | private: | 90 | private: |
91 | int nErrorCode; /**< The code for the error that occured. */ | 91 | int nErrorCode; /**< The code for the error that occured. */ |
92 | char *sWhat; /**< The text string telling people what went wrong. */ | 92 | char *sWhat; /**< The text string telling people what went wrong. */ |
93 | }; | 93 | }; |
94 | } | 94 | } |
95 | 95 | ||
96 | #define subExceptionDecl( name ) \ | 96 | #define subExceptionDecl( name ) \ |
97 | class name : public Bu::ExceptionBase \ | 97 | class name : public Bu::ExceptionBase \ |
98 | { \ | 98 | { \ |
99 | public: \ | 99 | public: \ |
100 | name( const char *sFormat, ... ) throw (); \ | 100 | name( const char *sFormat, ... ) throw (); \ |
101 | name( int nCode, const char *sFormat, ... ) throw(); \ | 101 | name( int nCode, const char *sFormat, ... ) throw(); \ |
102 | name( int nCode=0 ) throw (); \ | 102 | name( int nCode=0 ) throw (); \ |
103 | name( const name &e ) throw (); \ | 103 | name( const name &e ) throw (); \ |
104 | }; | 104 | }; |
105 | 105 | ||
106 | #define subExceptionDeclChild( name, parent ) \ | 106 | #define subExceptionDeclChild( name, parent ) \ |
107 | class name : public parent \ | 107 | class name : public parent \ |
108 | { \ | 108 | { \ |
109 | public: \ | 109 | public: \ |
110 | name( const char *sFormat, ... ) throw (); \ | 110 | name( const char *sFormat, ... ) throw (); \ |
111 | name( int nCode, const char *sFormat, ... ) throw(); \ | 111 | name( int nCode, const char *sFormat, ... ) throw(); \ |
112 | name( int nCode=0 ) throw (); \ | 112 | name( int nCode=0 ) throw (); \ |
113 | name( const name &e ) throw (); \ | 113 | name( const name &e ) throw (); \ |
114 | }; | 114 | }; |
115 | 115 | ||
116 | #define subExceptionDeclBegin( name ) \ | 116 | #define subExceptionDeclBegin( name ) \ |
117 | class name : public Bu::ExceptionBase \ | 117 | class name : public Bu::ExceptionBase \ |
118 | { \ | 118 | { \ |
119 | public: \ | 119 | public: \ |
120 | name( const char *sFormat, ... ) throw (); \ | 120 | name( const char *sFormat, ... ) throw (); \ |
121 | name( int nCode, const char *sFormat, ... ) throw(); \ | 121 | name( int nCode, const char *sFormat, ... ) throw(); \ |
122 | name( int nCode=0 ) throw (); \ | 122 | name( int nCode=0 ) throw (); \ |
123 | name( const name &e ) throw (); | 123 | name( const name &e ) throw (); |
124 | 124 | ||
125 | #define subExceptionDeclEnd() \ | 125 | #define subExceptionDeclEnd() \ |
126 | }; | 126 | }; |
127 | 127 | ||
128 | #define subExceptionDef( name ) \ | 128 | #define subExceptionDef( name ) \ |
129 | name::name( const char *lpFormat, ... ) throw() : \ | 129 | name::name( const char *lpFormat, ... ) throw() : \ |
130 | ExceptionBase( 0 ) \ | 130 | ExceptionBase( 0 ) \ |
131 | { \ | 131 | { \ |
132 | va_list ap; \ | 132 | va_list ap; \ |
133 | va_start( ap, lpFormat ); \ | 133 | va_start( ap, lpFormat ); \ |
134 | setWhat( lpFormat, ap ); \ | 134 | setWhat( lpFormat, ap ); \ |
135 | va_end( ap ); \ | 135 | va_end( ap ); \ |
136 | } \ | 136 | } \ |
137 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | 137 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ |
138 | ExceptionBase( nCode ) \ | 138 | ExceptionBase( nCode ) \ |
139 | { \ | 139 | { \ |
140 | va_list ap; \ | 140 | va_list ap; \ |
141 | va_start( ap, lpFormat ); \ | 141 | va_start( ap, lpFormat ); \ |
142 | setWhat( lpFormat, ap ); \ | 142 | setWhat( lpFormat, ap ); \ |
143 | va_end( ap ); \ | 143 | va_end( ap ); \ |
144 | } \ | 144 | } \ |
145 | name::name( int nCode ) throw() : \ | 145 | name::name( int nCode ) throw() : \ |
146 | ExceptionBase( nCode ) \ | 146 | ExceptionBase( nCode ) \ |
147 | { \ | 147 | { \ |
148 | } \ | 148 | } \ |
149 | name::name( const name &e ) throw() : \ | 149 | name::name( const name &e ) throw() : \ |
150 | ExceptionBase( e ) \ | 150 | ExceptionBase( e ) \ |
151 | { \ | 151 | { \ |
152 | } | 152 | } |
153 | 153 | ||
154 | #define subExceptionDefChild( name, parent ) \ | 154 | #define subExceptionDefChild( name, parent ) \ |
155 | name::name( const char *lpFormat, ... ) throw() : \ | 155 | name::name( const char *lpFormat, ... ) throw() : \ |
156 | parent( 0 ) \ | 156 | parent( 0 ) \ |
157 | { \ | 157 | { \ |
158 | va_list ap; \ | 158 | va_list ap; \ |
159 | va_start( ap, lpFormat ); \ | 159 | va_start( ap, lpFormat ); \ |
160 | setWhat( lpFormat, ap ); \ | 160 | setWhat( lpFormat, ap ); \ |
161 | va_end( ap ); \ | 161 | va_end( ap ); \ |
162 | } \ | 162 | } \ |
163 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | 163 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ |
164 | parent( nCode ) \ | 164 | parent( nCode ) \ |
165 | { \ | 165 | { \ |
166 | va_list ap; \ | 166 | va_list ap; \ |
167 | va_start( ap, lpFormat ); \ | 167 | va_start( ap, lpFormat ); \ |
168 | setWhat( lpFormat, ap ); \ | 168 | setWhat( lpFormat, ap ); \ |
169 | va_end( ap ); \ | 169 | va_end( ap ); \ |
170 | } \ | 170 | } \ |
171 | name::name( int nCode ) throw() : \ | 171 | name::name( int nCode ) throw() : \ |
172 | parent( nCode ) \ | 172 | parent( nCode ) \ |
173 | { \ | 173 | { \ |
174 | } \ | 174 | } \ |
175 | name::name( const name &e ) throw() : \ | 175 | name::name( const name &e ) throw() : \ |
176 | ExceptionBase( e ) \ | 176 | ExceptionBase( e ) \ |
177 | { \ | 177 | { \ |
178 | } | 178 | } |
179 | 179 | ||
180 | namespace Bu | 180 | namespace Bu |
181 | { | 181 | { |
182 | // Exceptions that are so general they could be used anywhere go here. | 182 | // Exceptions that are so general they could be used anywhere go here. |
183 | class UnsupportedException : public Bu::ExceptionBase | 183 | class UnsupportedException : public Bu::ExceptionBase |
184 | { | 184 | { |
185 | public: | 185 | public: |
186 | UnsupportedException() throw (); | 186 | UnsupportedException() throw (); |
187 | }; | 187 | }; |
188 | } | 188 | } |
189 | 189 | ||
190 | #endif | 190 | #endif |
diff --git a/src/stable/extratypes.h b/src/stable/extratypes.h index 2961920..3549529 100644 --- a/src/stable/extratypes.h +++ b/src/stable/extratypes.h | |||
@@ -19,11 +19,11 @@ | |||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | #ifdef USE_64BIT_IO | 21 | #ifdef USE_64BIT_IO |
22 | typedef int64_t size; | 22 | typedef int64_t size; |
23 | typedef uint64_t usize; | 23 | typedef uint64_t usize; |
24 | #else | 24 | #else |
25 | typedef int32_t size; | 25 | typedef int32_t size; |
26 | typedef uint32_t usize; | 26 | typedef uint32_t usize; |
27 | #endif | 27 | #endif |
28 | }; | 28 | }; |
29 | 29 | ||
diff --git a/src/stable/file.cpp b/src/stable/file.cpp index 14e4f3c..7ae2484 100644 --- a/src/stable/file.cpp +++ b/src/stable/file.cpp | |||
@@ -19,298 +19,298 @@ | |||
19 | namespace Bu { subExceptionDef( FileException ) } | 19 | namespace Bu { subExceptionDef( FileException ) } |
20 | 20 | ||
21 | Bu::File::File( const Bu::String &sName, int iFlags ) : | 21 | Bu::File::File( const Bu::String &sName, int iFlags ) : |
22 | fd( -1 ), | 22 | fd( -1 ), |
23 | bEos( true ) | 23 | bEos( true ) |
24 | { | 24 | { |
25 | #ifdef USE_64BIT_IO | 25 | #ifdef USE_64BIT_IO |
26 | fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); | 26 | fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); |
27 | #else | 27 | #else |
28 | fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); | 28 | fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); |
29 | #endif | 29 | #endif |
30 | if( fd < 0 ) | 30 | if( fd < 0 ) |
31 | { | 31 | { |
32 | throw Bu::FileException( errno, "%s: %s", | 32 | throw Bu::FileException( errno, "%s: %s", |
33 | strerror(errno), sName.getStr() ); | 33 | strerror(errno), sName.getStr() ); |
34 | } | 34 | } |
35 | bEos = false; | 35 | bEos = false; |
36 | } | 36 | } |
37 | 37 | ||
38 | Bu::File::File( int fd ) : | 38 | Bu::File::File( int fd ) : |
39 | fd( fd ) | 39 | fd( fd ) |
40 | { | 40 | { |
41 | bEos = false; | 41 | bEos = false; |
42 | } | 42 | } |
43 | 43 | ||
44 | Bu::File::~File() | 44 | Bu::File::~File() |
45 | { | 45 | { |
46 | close(); | 46 | close(); |
47 | } | 47 | } |
48 | 48 | ||
49 | void Bu::File::close() | 49 | void Bu::File::close() |
50 | { | 50 | { |
51 | if( fd >= 0 ) | 51 | if( fd >= 0 ) |
52 | { | 52 | { |
53 | if( ::close( fd ) ) | 53 | if( ::close( fd ) ) |
54 | { | 54 | { |
55 | throw Bu::FileException( errno, "%s", | 55 | throw Bu::FileException( errno, "%s", |
56 | strerror(errno) ); | 56 | strerror(errno) ); |
57 | } | 57 | } |
58 | fd = -1; | 58 | fd = -1; |
59 | bEos = true; | 59 | bEos = true; |
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
63 | Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) | 63 | Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) |
64 | { | 64 | { |
65 | if( fd < 0 ) | 65 | if( fd < 0 ) |
66 | throw FileException("File not open."); | 66 | throw FileException("File not open."); |
67 | 67 | ||
68 | Bu::size iRead = ::read( fd, pBuf, nBytes ); | 68 | Bu::size iRead = ::read( fd, pBuf, nBytes ); |
69 | if( iRead == 0 ) | 69 | if( iRead == 0 ) |
70 | bEos = true; | 70 | bEos = true; |
71 | else if( iRead == -1 && errno == EAGAIN ) | 71 | else if( iRead == -1 && errno == EAGAIN ) |
72 | return 0; | 72 | return 0; |
73 | else if( iRead < 0 ) | 73 | else if( iRead < 0 ) |
74 | throw FileException( errno, "%s", strerror( errno ) ); | 74 | throw FileException( errno, "%s", strerror( errno ) ); |
75 | return iRead; | 75 | return iRead; |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) | 78 | Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) |
79 | { | 79 | { |
80 | if( fd < 0 ) | 80 | if( fd < 0 ) |
81 | throw FileException("File not open."); | 81 | throw FileException("File not open."); |
82 | 82 | ||
83 | Bu::size iWrote = ::write( fd, pBuf, nBytes ); | 83 | Bu::size iWrote = ::write( fd, pBuf, nBytes ); |
84 | if( iWrote < 0 ) | 84 | if( iWrote < 0 ) |
85 | throw FileException( errno, "%s", strerror( errno ) ); | 85 | throw FileException( errno, "%s", strerror( errno ) ); |
86 | return iWrote; | 86 | return iWrote; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::size Bu::File::tell() | 89 | Bu::size Bu::File::tell() |
90 | { | 90 | { |
91 | if( fd < 0 ) | 91 | if( fd < 0 ) |
92 | throw FileException("File not open."); | 92 | throw FileException("File not open."); |
93 | 93 | ||
94 | #ifdef USE_64BIT_IO | 94 | #ifdef USE_64BIT_IO |
95 | return lseek64( fd, 0, SEEK_CUR ); | 95 | return lseek64( fd, 0, SEEK_CUR ); |
96 | #else | 96 | #else |
97 | return lseek( fd, 0, SEEK_CUR ); | 97 | return lseek( fd, 0, SEEK_CUR ); |
98 | #endif | 98 | #endif |
99 | } | 99 | } |
100 | 100 | ||
101 | void Bu::File::seek( Bu::size offset ) | 101 | void Bu::File::seek( Bu::size offset ) |
102 | { | 102 | { |
103 | if( fd < 0 ) | 103 | if( fd < 0 ) |
104 | throw FileException("File not open."); | 104 | throw FileException("File not open."); |
105 | 105 | ||
106 | #ifdef USE_64BIT_IO | 106 | #ifdef USE_64BIT_IO |
107 | lseek64( fd, offset, SEEK_CUR ); | 107 | lseek64( fd, offset, SEEK_CUR ); |
108 | #else | 108 | #else |
109 | lseek( fd, offset, SEEK_CUR ); | 109 | lseek( fd, offset, SEEK_CUR ); |
110 | #endif | 110 | #endif |
111 | bEos = false; | 111 | bEos = false; |
112 | } | 112 | } |
113 | 113 | ||
114 | void Bu::File::setPos( Bu::size pos ) | 114 | void Bu::File::setPos( Bu::size pos ) |
115 | { | 115 | { |
116 | if( fd < 0 ) | 116 | if( fd < 0 ) |
117 | throw FileException("File not open."); | 117 | throw FileException("File not open."); |
118 | 118 | ||
119 | #ifdef USE_64BIT_IO | 119 | #ifdef USE_64BIT_IO |
120 | lseek64( fd, pos, SEEK_SET ); | 120 | lseek64( fd, pos, SEEK_SET ); |
121 | #else | 121 | #else |
122 | lseek( fd, pos, SEEK_SET ); | 122 | lseek( fd, pos, SEEK_SET ); |
123 | #endif | 123 | #endif |
124 | bEos = false; | 124 | bEos = false; |
125 | } | 125 | } |
126 | 126 | ||
127 | void Bu::File::setPosEnd( Bu::size pos ) | 127 | void Bu::File::setPosEnd( Bu::size pos ) |
128 | { | 128 | { |
129 | if( fd < 0 ) | 129 | if( fd < 0 ) |
130 | throw FileException("File not open."); | 130 | throw FileException("File not open."); |
131 | 131 | ||
132 | lseek64( fd, pos, SEEK_END ); | 132 | lseek64( fd, pos, SEEK_END ); |
133 | bEos = false; | 133 | bEos = false; |
134 | } | 134 | } |
135 | 135 | ||
136 | bool Bu::File::isEos() | 136 | bool Bu::File::isEos() |
137 | { | 137 | { |
138 | return bEos; | 138 | return bEos; |
139 | } | 139 | } |
140 | 140 | ||
141 | bool Bu::File::canRead() | 141 | bool Bu::File::canRead() |
142 | { | 142 | { |
143 | #ifdef WIN32 | 143 | #ifdef WIN32 |
144 | return true; | 144 | return true; |
145 | #else | 145 | #else |
146 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; | 146 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; |
147 | if( iMode == O_RDONLY || iMode == O_RDWR ) | 147 | if( iMode == O_RDONLY || iMode == O_RDWR ) |
148 | return true; | 148 | return true; |
149 | return false; | 149 | return false; |
150 | #endif | 150 | #endif |
151 | } | 151 | } |
152 | 152 | ||
153 | bool Bu::File::canWrite() | 153 | bool Bu::File::canWrite() |
154 | { | 154 | { |
155 | #ifdef WIN32 | 155 | #ifdef WIN32 |
156 | return true; | 156 | return true; |
157 | #else | 157 | #else |
158 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; | 158 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; |
159 | if( iMode == O_WRONLY || iMode == O_RDWR ) | 159 | if( iMode == O_WRONLY || iMode == O_RDWR ) |
160 | return true; | 160 | return true; |
161 | return false; | 161 | return false; |
162 | #endif | 162 | #endif |
163 | } | 163 | } |
164 | 164 | ||
165 | bool Bu::File::isReadable() | 165 | bool Bu::File::isReadable() |
166 | { | 166 | { |
167 | return true; | 167 | return true; |
168 | } | 168 | } |
169 | 169 | ||
170 | bool Bu::File::isWritable() | 170 | bool Bu::File::isWritable() |
171 | { | 171 | { |
172 | return true; | 172 | return true; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool Bu::File::isSeekable() | 175 | bool Bu::File::isSeekable() |
176 | { | 176 | { |
177 | return true; | 177 | return true; |
178 | } | 178 | } |
179 | 179 | ||
180 | bool Bu::File::isBlocking() | 180 | bool Bu::File::isBlocking() |
181 | { | 181 | { |
182 | return true; | 182 | return true; |
183 | } | 183 | } |
184 | 184 | ||
185 | void Bu::File::setBlocking( bool bBlocking ) | 185 | void Bu::File::setBlocking( bool bBlocking ) |
186 | { | 186 | { |
187 | #ifdef WIN32 | 187 | #ifdef WIN32 |
188 | fprintf(stderr, "STUB: Bu::File::setBlocking\n"); | 188 | fprintf(stderr, "STUB: Bu::File::setBlocking\n"); |
189 | #else | 189 | #else |
190 | if( bBlocking ) | 190 | if( bBlocking ) |
191 | fcntl( | 191 | fcntl( |
192 | fd, | 192 | fd, |
193 | F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) | 193 | F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) |
194 | ); | 194 | ); |
195 | else | 195 | else |
196 | fcntl( | 196 | fcntl( |
197 | fd, | 197 | fd, |
198 | F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK | 198 | F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK |
199 | ); | 199 | ); |
200 | #endif | 200 | #endif |
201 | } | 201 | } |
202 | 202 | ||
203 | Bu::File Bu::File::tempFile( Bu::String &sName ) | 203 | Bu::File Bu::File::tempFile( Bu::String &sName ) |
204 | { | 204 | { |
205 | int iXes; | 205 | int iXes; |
206 | for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) | 206 | for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) |
207 | { | 207 | { |
208 | if( sName[iXes] != 'X' ) | 208 | if( sName[iXes] != 'X' ) |
209 | break; | 209 | break; |
210 | } | 210 | } |
211 | iXes++; | 211 | iXes++; |
212 | if( iXes == sName.getSize() ) | 212 | if( iXes == sName.getSize() ) |
213 | throw Bu::ExceptionBase("Invalid temporary filename template."); | 213 | throw Bu::ExceptionBase("Invalid temporary filename template."); |
214 | for( int iter = 0; iter < 1000; iter++ ) | 214 | for( int iter = 0; iter < 1000; iter++ ) |
215 | { | 215 | { |
216 | for( int j = iXes; j < sName.getSize(); j++ ) | 216 | for( int j = iXes; j < sName.getSize(); j++ ) |
217 | { | 217 | { |
218 | uint32_t iX = Bu::Random::rand(); | 218 | uint32_t iX = Bu::Random::rand(); |
219 | sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); | 219 | sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); |
220 | } | 220 | } |
221 | 221 | ||
222 | try | 222 | try |
223 | { | 223 | { |
224 | return Bu::File( sName, Bu::File::Read|Bu::File::Write | 224 | return Bu::File( sName, Bu::File::Read|Bu::File::Write |
225 | |Bu::File::Create|Bu::File::Exclusive ); | 225 | |Bu::File::Create|Bu::File::Exclusive ); |
226 | } catch(...) { } | 226 | } catch(...) { } |
227 | } | 227 | } |
228 | throw Bu::FileException("Failed to create unique temporary file after 1000" | 228 | throw Bu::FileException("Failed to create unique temporary file after 1000" |
229 | " iterations."); | 229 | " iterations."); |
230 | } | 230 | } |
231 | 231 | ||
232 | void Bu::File::setSize( Bu::size iSize ) | 232 | void Bu::File::setSize( Bu::size iSize ) |
233 | { | 233 | { |
234 | #ifdef WIN32 | 234 | #ifdef WIN32 |
235 | chsize( fd, iSize ); | 235 | chsize( fd, iSize ); |
236 | #else | 236 | #else |
237 | ftruncate( fd, iSize ); | 237 | ftruncate( fd, iSize ); |
238 | #endif | 238 | #endif |
239 | } | 239 | } |
240 | 240 | ||
241 | Bu::size Bu::File::getSize() const | 241 | Bu::size Bu::File::getSize() const |
242 | { | 242 | { |
243 | struct stat st; | 243 | struct stat st; |
244 | fstat( fd, &st ); | 244 | fstat( fd, &st ); |
245 | return st.st_size; | 245 | return st.st_size; |
246 | } | 246 | } |
247 | 247 | ||
248 | Bu::size Bu::File::getBlockSize() const | 248 | Bu::size Bu::File::getBlockSize() const |
249 | { | 249 | { |
250 | #ifdef WIN32 | 250 | #ifdef WIN32 |
251 | return 4096; | 251 | return 4096; |
252 | #else | 252 | #else |
253 | struct stat st; | 253 | struct stat st; |
254 | fstat( fd, &st ); | 254 | fstat( fd, &st ); |
255 | return st.st_blksize; | 255 | return st.st_blksize; |
256 | #endif | 256 | #endif |
257 | } | 257 | } |
258 | 258 | ||
259 | Bu::String Bu::File::getLocation() const | 259 | Bu::String Bu::File::getLocation() const |
260 | { | 260 | { |
261 | return "to be implemented"; | 261 | return "to be implemented"; |
262 | } | 262 | } |
263 | 263 | ||
264 | #ifndef WIN32 | 264 | #ifndef WIN32 |
265 | void Bu::File::chmod( mode_t t ) | 265 | void Bu::File::chmod( mode_t t ) |
266 | { | 266 | { |
267 | fchmod( fd, t ); | 267 | fchmod( fd, t ); |
268 | } | 268 | } |
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | void Bu::File::flush() | 271 | void Bu::File::flush() |
272 | { | 272 | { |
273 | // There is no flushing with direct I/O... | 273 | // There is no flushing with direct I/O... |
274 | //fflush( fh ); | 274 | //fflush( fh ); |
275 | } | 275 | } |
276 | 276 | ||
277 | bool Bu::File::isOpen() | 277 | bool Bu::File::isOpen() |
278 | { | 278 | { |
279 | return (fd > -1); | 279 | return (fd > -1); |
280 | } | 280 | } |
281 | 281 | ||
282 | int Bu::File::getPosixFlags( int iFlags ) | 282 | int Bu::File::getPosixFlags( int iFlags ) |
283 | { | 283 | { |
284 | int iRet = 0; | 284 | int iRet = 0; |
285 | switch( (iFlags&ReadWrite) ) | 285 | switch( (iFlags&ReadWrite) ) |
286 | { | 286 | { |
287 | // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so | 287 | // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so |
288 | // lets be proper and use the right value in the right place. | 288 | // lets be proper and use the right value in the right place. |
289 | case Read: iRet = O_RDONLY; break; | 289 | case Read: iRet = O_RDONLY; break; |
290 | case Write: iRet = O_WRONLY; break; | 290 | case Write: iRet = O_WRONLY; break; |
291 | case ReadWrite: iRet = O_RDWR; break; | 291 | case ReadWrite: iRet = O_RDWR; break; |
292 | default: | 292 | default: |
293 | throw FileException( | 293 | throw FileException( |
294 | "You must specify Read, Write, or both when opening a file."); | 294 | "You must specify Read, Write, or both when opening a file."); |
295 | } | 295 | } |
296 | 296 | ||
297 | if( (iFlags&Create) ) | 297 | if( (iFlags&Create) ) |
298 | iRet |= O_CREAT; | 298 | iRet |= O_CREAT; |
299 | if( (iFlags&Append) ) | 299 | if( (iFlags&Append) ) |
300 | iRet |= O_APPEND; | 300 | iRet |= O_APPEND; |
301 | if( (iFlags&Truncate) ) | 301 | if( (iFlags&Truncate) ) |
302 | iRet |= O_TRUNC; | 302 | iRet |= O_TRUNC; |
303 | #ifndef WIN32 | 303 | #ifndef WIN32 |
304 | if( (iFlags&NonBlock) ) | 304 | if( (iFlags&NonBlock) ) |
305 | iRet |= O_NONBLOCK; | 305 | iRet |= O_NONBLOCK; |
306 | #endif | 306 | #endif |
307 | if( (iFlags&Exclusive) == Exclusive ) | 307 | if( (iFlags&Exclusive) == Exclusive ) |
308 | iRet |= O_EXCL; | 308 | iRet |= O_EXCL; |
309 | 309 | ||
310 | #ifdef O_BINARY | 310 | #ifdef O_BINARY |
311 | iRet |= O_BINARY; | 311 | iRet |= O_BINARY; |
312 | #endif | 312 | #endif |
313 | 313 | ||
314 | return iRet; | 314 | return iRet; |
315 | } | 315 | } |
316 | 316 | ||
diff --git a/src/stable/file.h b/src/stable/file.h index eaf2974..2ecb27e 100644 --- a/src/stable/file.h +++ b/src/stable/file.h | |||
@@ -17,90 +17,90 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( FileException ); | 20 | subExceptionDecl( FileException ); |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * A file stream. | 23 | * A file stream. |
24 | *@ingroup Streams | 24 | *@ingroup Streams |
25 | */ | 25 | */ |
26 | class File : public Bu::Stream | 26 | class File : public Bu::Stream |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | File( const Bu::String &sName, int iFlags ); | 29 | File( const Bu::String &sName, int iFlags ); |
30 | File( int fd ); | 30 | File( int fd ); |
31 | virtual ~File(); | 31 | virtual ~File(); |
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 | // Flags | 58 | // Flags |
59 | Read = 0x01, ///< Open file for reading | 59 | Read = 0x01, ///< Open file for reading |
60 | Write = 0x02, ///< Open file for writing | 60 | Write = 0x02, ///< Open file for writing |
61 | Create = 0x04, ///< Create file if it doesn't exist | 61 | Create = 0x04, ///< Create file if it doesn't exist |
62 | Truncate = 0x08, ///< Truncate file if it does exist | 62 | Truncate = 0x08, ///< Truncate file if it does exist |
63 | Append = 0x10, ///< Always append on every write | 63 | Append = 0x10, ///< Always append on every write |
64 | NonBlock = 0x20, ///< Open file in non-blocking mode | 64 | NonBlock = 0x20, ///< Open file in non-blocking mode |
65 | Exclusive = 0x44, ///< Create file, if it exists then fail | 65 | Exclusive = 0x44, ///< Create file, if it exists then fail |
66 | 66 | ||
67 | // Helpful mixes | 67 | // Helpful mixes |
68 | ReadWrite = 0x03, ///< Open for reading and writing | 68 | ReadWrite = 0x03, ///< Open for reading and writing |
69 | WriteNew = 0x0E ///< Create a file (or truncate) for writing. | 69 | WriteNew = 0x0E ///< Create a file (or truncate) for writing. |
70 | /// Same as Write|Create|Truncate | 70 | /// Same as Write|Create|Truncate |
71 | }; | 71 | }; |
72 | 72 | ||
73 | virtual void setSize( Bu::size iSize ); | 73 | virtual void setSize( Bu::size iSize ); |
74 | 74 | ||
75 | virtual size getSize() const; | 75 | virtual size getSize() const; |
76 | virtual size getBlockSize() const; | 76 | virtual size getBlockSize() const; |
77 | virtual Bu::String getLocation() const; | 77 | virtual Bu::String getLocation() const; |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * Create a temp file and return its handle. The file is opened | 80 | * Create a temp file and return its handle. The file is opened |
81 | * Read/Write. | 81 | * Read/Write. |
82 | *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" | 82 | *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" |
83 | * It will alter your (sName) setting the 'X's to random | 83 | * It will alter your (sName) setting the 'X's to random |
84 | * characters. | 84 | * characters. |
85 | *@returns (Bu::File) A file object representing your temp file. | 85 | *@returns (Bu::File) A file object representing your temp file. |
86 | */ | 86 | */ |
87 | static Bu::File tempFile( Bu::String &sName ); | 87 | static Bu::File tempFile( Bu::String &sName ); |
88 | 88 | ||
89 | #ifndef WIN32 | 89 | #ifndef WIN32 |
90 | /** | 90 | /** |
91 | * Change the file access permissions. | 91 | * Change the file access permissions. |
92 | *@param t (mode_t) The new file access permissions. | 92 | *@param t (mode_t) The new file access permissions. |
93 | */ | 93 | */ |
94 | void chmod( mode_t t ); | 94 | void chmod( mode_t t ); |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | private: | 97 | private: |
98 | int getPosixFlags( int iFlags ); | 98 | int getPosixFlags( int iFlags ); |
99 | 99 | ||
100 | private: | 100 | private: |
101 | int fd; | 101 | int fd; |
102 | bool bEos; | 102 | bool bEos; |
103 | }; | 103 | }; |
104 | } | 104 | } |
105 | 105 | ||
106 | #endif | 106 | #endif |
diff --git a/src/stable/filter.cpp b/src/stable/filter.cpp index 9c1d66f..e7929e7 100644 --- a/src/stable/filter.cpp +++ b/src/stable/filter.cpp | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "bu/filter.h" | 8 | #include "bu/filter.h" |
9 | 9 | ||
10 | Bu::Filter::Filter( Bu::Stream &rNext ) : | 10 | Bu::Filter::Filter( Bu::Stream &rNext ) : |
11 | rNext( rNext ) | 11 | rNext( rNext ) |
12 | { | 12 | { |
13 | } | 13 | } |
14 | 14 | ||
@@ -18,73 +18,73 @@ Bu::Filter::~Filter() | |||
18 | 18 | ||
19 | void Bu::Filter::close() | 19 | void Bu::Filter::close() |
20 | { | 20 | { |
21 | stop(); | 21 | stop(); |
22 | rNext.close(); | 22 | rNext.close(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::size Bu::Filter::tell() | 25 | Bu::size Bu::Filter::tell() |
26 | { | 26 | { |
27 | return rNext.tell(); | 27 | return rNext.tell(); |
28 | } | 28 | } |
29 | 29 | ||
30 | void Bu::Filter::seek( Bu::size offset ) | 30 | void Bu::Filter::seek( Bu::size offset ) |
31 | { | 31 | { |
32 | rNext.seek( offset ); | 32 | rNext.seek( offset ); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Filter::setPos( Bu::size pos ) | 35 | void Bu::Filter::setPos( Bu::size pos ) |
36 | { | 36 | { |
37 | rNext.setPos( pos ); | 37 | rNext.setPos( pos ); |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::Filter::setPosEnd( Bu::size pos ) | 40 | void Bu::Filter::setPosEnd( Bu::size pos ) |
41 | { | 41 | { |
42 | rNext.setPosEnd( pos ); | 42 | rNext.setPosEnd( pos ); |
43 | } | 43 | } |
44 | 44 | ||
45 | bool Bu::Filter::isEos() | 45 | bool Bu::Filter::isEos() |
46 | { | 46 | { |
47 | return rNext.isEos(); | 47 | return rNext.isEos(); |
48 | } | 48 | } |
49 | 49 | ||
50 | bool Bu::Filter::isOpen() | 50 | bool Bu::Filter::isOpen() |
51 | { | 51 | { |
52 | return rNext.isOpen(); | 52 | return rNext.isOpen(); |
53 | } | 53 | } |
54 | 54 | ||
55 | bool Bu::Filter::canRead() | 55 | bool Bu::Filter::canRead() |
56 | { | 56 | { |
57 | return rNext.canRead(); | 57 | return rNext.canRead(); |
58 | } | 58 | } |
59 | 59 | ||
60 | bool Bu::Filter::canWrite() | 60 | bool Bu::Filter::canWrite() |
61 | { | 61 | { |
62 | return rNext.canWrite(); | 62 | return rNext.canWrite(); |
63 | } | 63 | } |
64 | 64 | ||
65 | bool Bu::Filter::isReadable() | 65 | bool Bu::Filter::isReadable() |
66 | { | 66 | { |
67 | return rNext.isReadable(); | 67 | return rNext.isReadable(); |
68 | } | 68 | } |
69 | 69 | ||
70 | bool Bu::Filter::isWritable() | 70 | bool Bu::Filter::isWritable() |
71 | { | 71 | { |
72 | return rNext.isWritable(); | 72 | return rNext.isWritable(); |
73 | } | 73 | } |
74 | 74 | ||
75 | bool Bu::Filter::isSeekable() | 75 | bool Bu::Filter::isSeekable() |
76 | { | 76 | { |
77 | return rNext.isSeekable(); | 77 | return rNext.isSeekable(); |
78 | } | 78 | } |
79 | 79 | ||
80 | bool Bu::Filter::isBlocking() | 80 | bool Bu::Filter::isBlocking() |
81 | { | 81 | { |
82 | return rNext.isBlocking(); | 82 | return rNext.isBlocking(); |
83 | } | 83 | } |
84 | 84 | ||
85 | void Bu::Filter::setBlocking( bool bBlocking ) | 85 | void Bu::Filter::setBlocking( bool bBlocking ) |
86 | { | 86 | { |
87 | rNext.setBlocking( bBlocking ); | 87 | rNext.setBlocking( bBlocking ); |
88 | } | 88 | } |
89 | 89 | ||
90 | void Bu::Filter::setSize( Bu::size ) | 90 | void Bu::Filter::setSize( Bu::size ) |
@@ -93,21 +93,21 @@ void Bu::Filter::setSize( Bu::size ) | |||
93 | 93 | ||
94 | void Bu::Filter::flush() | 94 | void Bu::Filter::flush() |
95 | { | 95 | { |
96 | rNext.flush(); | 96 | rNext.flush(); |
97 | } | 97 | } |
98 | 98 | ||
99 | Bu::size Bu::Filter::getSize() const | 99 | Bu::size Bu::Filter::getSize() const |
100 | { | 100 | { |
101 | return rNext.getSize(); | 101 | return rNext.getSize(); |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::size Bu::Filter::getBlockSize() const | 104 | Bu::size Bu::Filter::getBlockSize() const |
105 | { | 105 | { |
106 | return rNext.getBlockSize(); | 106 | return rNext.getBlockSize(); |
107 | } | 107 | } |
108 | 108 | ||
109 | Bu::String Bu::Filter::getLocation() const | 109 | Bu::String Bu::Filter::getLocation() const |
110 | { | 110 | { |
111 | return rNext.getLocation(); | 111 | return rNext.getLocation(); |
112 | } | 112 | } |
113 | 113 | ||
diff --git a/src/stable/filter.h b/src/stable/filter.h index 3e1c7d8..49a6664 100644 --- a/src/stable/filter.h +++ b/src/stable/filter.h | |||
@@ -14,70 +14,70 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Data filter base class. Each data filter should contain a read and write | 18 | * Data filter base class. Each data filter should contain a read and write |
19 | * section. Effectively, the write applies the filter, the read un-applies | 19 | * section. Effectively, the write applies the filter, the read un-applies |
20 | * the filter, if possible. For example, BZip2 is a filter that compresses | 20 | * the filter, if possible. For example, BZip2 is a filter that compresses |
21 | * on write and decompresses on read. All bi-directional filters should | 21 | * on write and decompresses on read. All bi-directional filters should |
22 | * follow: x == read( write( x ) ) (byte-for-byte comparison) | 22 | * follow: x == read( write( x ) ) (byte-for-byte comparison) |
23 | * | 23 | * |
24 | * Also, all returned buffers should be owned by the filter, and deleted | 24 | * Also, all returned buffers should be owned by the filter, and deleted |
25 | * when the filter is deleted. This means that the output of a read or | 25 | * when the filter is deleted. This means that the output of a read or |
26 | * write operation must be used before the next call to read or write or the | 26 | * write operation must be used before the next call to read or write or the |
27 | * data will be destroyed. Also, the internal buffer may be changed or | 27 | * data will be destroyed. Also, the internal buffer may be changed or |
28 | * recreated between calls, so always get a new pointer from a call to | 28 | * recreated between calls, so always get a new pointer from a call to |
29 | * read or write. | 29 | * read or write. |
30 | * | 30 | * |
31 | * The close function can also return data, so make sure to check for it, | 31 | * The close function can also return data, so make sure to check for it, |
32 | * many filters such as compression filters will buffer data until they have | 32 | * many filters such as compression filters will buffer data until they have |
33 | * enough to create a compression block, in these cases the leftover data | 33 | * enough to create a compression block, in these cases the leftover data |
34 | * will be returned by close. | 34 | * will be returned by close. |
35 | *@ingroup Streams | 35 | *@ingroup Streams |
36 | */ | 36 | */ |
37 | class Filter : public Bu::Stream | 37 | class Filter : public Bu::Stream |
38 | { | 38 | { |
39 | public: | 39 | public: |
40 | Filter( Bu::Stream &rNext ); | 40 | Filter( Bu::Stream &rNext ); |
41 | virtual ~Filter(); | 41 | virtual ~Filter(); |
42 | 42 | ||
43 | virtual void start()=0; | 43 | virtual void start()=0; |
44 | virtual Bu::size stop()=0; | 44 | virtual Bu::size stop()=0; |
45 | virtual void close(); | 45 | virtual void close(); |
46 | virtual Bu::size tell(); | 46 | virtual Bu::size tell(); |
47 | virtual void seek( Bu::size offset ); | 47 | virtual void seek( Bu::size offset ); |
48 | virtual void setPos( Bu::size pos ); | 48 | virtual void setPos( Bu::size pos ); |
49 | virtual void setPosEnd( Bu::size pos ); | 49 | virtual void setPosEnd( Bu::size pos ); |
50 | virtual bool isEos(); | 50 | virtual bool isEos(); |
51 | virtual bool isOpen(); | 51 | virtual bool isOpen(); |
52 | 52 | ||
53 | virtual void flush(); | 53 | virtual void flush(); |
54 | 54 | ||
55 | virtual bool canRead(); | 55 | virtual bool canRead(); |
56 | virtual bool canWrite(); | 56 | virtual bool canWrite(); |
57 | 57 | ||
58 | virtual bool isReadable(); | 58 | virtual bool isReadable(); |
59 | virtual bool isWritable(); | 59 | virtual bool isWritable(); |
60 | virtual bool isSeekable(); | 60 | virtual bool isSeekable(); |
61 | 61 | ||
62 | virtual bool isBlocking(); | 62 | virtual bool isBlocking(); |
63 | virtual void setBlocking( bool bBlocking=true ); | 63 | virtual void setBlocking( bool bBlocking=true ); |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Most filters won't re-implement this, it doesn't make a lot of sense | 66 | * Most filters won't re-implement this, it doesn't make a lot of sense |
67 | * for filters, in general. | 67 | * for filters, in general. |
68 | */ | 68 | */ |
69 | virtual void setSize( Bu::size iSize ); | 69 | virtual void setSize( Bu::size iSize ); |
70 | 70 | ||
71 | virtual size getSize() const; | 71 | virtual size getSize() const; |
72 | virtual size getBlockSize() const; | 72 | virtual size getBlockSize() const; |
73 | virtual Bu::String getLocation() const; | 73 | virtual Bu::String getLocation() const; |
74 | 74 | ||
75 | protected: | 75 | protected: |
76 | Bu::Stream &rNext; | 76 | Bu::Stream &rNext; |
77 | 77 | ||
78 | private: | 78 | private: |
79 | 79 | ||
80 | }; | 80 | }; |
81 | } | 81 | } |
82 | 82 | ||
83 | #endif | 83 | #endif |
diff --git a/src/stable/fmt.h b/src/stable/fmt.h index bcc5240..9ecaf80 100644 --- a/src/stable/fmt.h +++ b/src/stable/fmt.h | |||
@@ -3,92 +3,92 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | typedef struct Fmt | 6 | typedef struct Fmt |
7 | { | 7 | { |
8 | enum Alignment | 8 | enum Alignment |
9 | { | 9 | { |
10 | Left = 0, | 10 | Left = 0, |
11 | Center = 1, | 11 | Center = 1, |
12 | Right = 2 | 12 | Right = 2 |
13 | }; | 13 | }; |
14 | Fmt() : | 14 | Fmt() : |
15 | uMinWidth( 0 ), | 15 | uMinWidth( 0 ), |
16 | cFillChar(' '), | 16 | cFillChar(' '), |
17 | uRadix( 10 ), | 17 | uRadix( 10 ), |
18 | uAlign( Right ), | 18 | uAlign( Right ), |
19 | bPlus( false ), | 19 | bPlus( false ), |
20 | bCaps( false ), | 20 | bCaps( false ), |
21 | bTokenize( true ) | 21 | bTokenize( true ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Fmt( unsigned int uMinWidth, unsigned int uRadix=10, | 25 | Fmt( unsigned int uMinWidth, unsigned int uRadix=10, |
26 | Alignment a=Right, bool bPlus=false, bool bCaps=true, | 26 | Alignment a=Right, bool bPlus=false, bool bCaps=true, |
27 | char cFill=' ') : | 27 | char cFill=' ') : |
28 | uMinWidth( uMinWidth ), | 28 | uMinWidth( uMinWidth ), |
29 | cFillChar(cFill), | 29 | cFillChar(cFill), |
30 | uRadix( uRadix ), | 30 | uRadix( uRadix ), |
31 | uAlign( a ), | 31 | uAlign( a ), |
32 | bPlus( bPlus ), | 32 | bPlus( bPlus ), |
33 | bCaps( bCaps ), | 33 | bCaps( bCaps ), |
34 | bTokenize( true ) | 34 | bTokenize( true ) |
35 | { | 35 | { |
36 | } | 36 | } |
37 | Fmt( unsigned int uMinWidth, Alignment a, | 37 | Fmt( unsigned int uMinWidth, Alignment a, |
38 | unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, | 38 | unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, |
39 | char cFill=' ') : | 39 | char cFill=' ') : |
40 | uMinWidth( uMinWidth ), | 40 | uMinWidth( uMinWidth ), |
41 | cFillChar(cFill), | 41 | cFillChar(cFill), |
42 | uRadix( uRadix ), | 42 | uRadix( uRadix ), |
43 | uAlign( a ), | 43 | uAlign( a ), |
44 | bPlus( bPlus ), | 44 | bPlus( bPlus ), |
45 | bCaps( bCaps ), | 45 | bCaps( bCaps ), |
46 | bTokenize( true ) | 46 | bTokenize( true ) |
47 | { | 47 | { |
48 | } | 48 | } |
49 | 49 | ||
50 | static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) | 50 | static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) |
51 | { | 51 | { |
52 | return Fmt( uWidth, 16, Right, false, bCaps, '0' ); | 52 | return Fmt( uWidth, 16, Right, false, bCaps, '0' ); |
53 | } | 53 | } |
54 | 54 | ||
55 | static Fmt oct( unsigned int uWidth=0 ) | 55 | static Fmt oct( unsigned int uWidth=0 ) |
56 | { | 56 | { |
57 | return Fmt( uWidth, 8, Right, false, false, '0' ); | 57 | return Fmt( uWidth, 8, Right, false, false, '0' ); |
58 | } | 58 | } |
59 | 59 | ||
60 | static Fmt bin( unsigned int uWidth=0 ) | 60 | static Fmt bin( unsigned int uWidth=0 ) |
61 | { | 61 | { |
62 | return Fmt( uWidth, 1, Right, false, false, '0' ); | 62 | return Fmt( uWidth, 1, Right, false, false, '0' ); |
63 | } | 63 | } |
64 | 64 | ||
65 | static Fmt ptr( bool bCaps=true ) | 65 | static Fmt ptr( bool bCaps=true ) |
66 | { | 66 | { |
67 | return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); | 67 | return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); |
68 | } | 68 | } |
69 | 69 | ||
70 | Fmt &width( unsigned int uWidth ); | 70 | Fmt &width( unsigned int uWidth ); |
71 | Fmt &fill( char cFill='0' ); | 71 | Fmt &fill( char cFill='0' ); |
72 | Fmt &radix( unsigned int uRadix ); | 72 | Fmt &radix( unsigned int uRadix ); |
73 | Fmt &align( Alignment eAlign ); | 73 | Fmt &align( Alignment eAlign ); |
74 | Fmt &plus( bool bPlus=true ); | 74 | Fmt &plus( bool bPlus=true ); |
75 | Fmt &caps( bool bCaps=true ); | 75 | Fmt &caps( bool bCaps=true ); |
76 | Fmt &upper(); | 76 | Fmt &upper(); |
77 | Fmt &lower(); | 77 | Fmt &lower(); |
78 | Fmt &tokenize( bool bTokenize=true ); | 78 | Fmt &tokenize( bool bTokenize=true ); |
79 | 79 | ||
80 | Fmt &left(); | 80 | Fmt &left(); |
81 | Fmt &right(); | 81 | Fmt &right(); |
82 | Fmt ¢er(); | 82 | Fmt ¢er(); |
83 | 83 | ||
84 | unsigned char uMinWidth; | 84 | unsigned char uMinWidth; |
85 | char cFillChar; | 85 | char cFillChar; |
86 | unsigned short uRadix : 6; | 86 | unsigned short uRadix : 6; |
87 | unsigned short uAlign : 2; | 87 | unsigned short uAlign : 2; |
88 | unsigned short bPlus : 1; | 88 | unsigned short bPlus : 1; |
89 | unsigned short bCaps : 1; | 89 | unsigned short bCaps : 1; |
90 | unsigned short bTokenize : 1; | 90 | unsigned short bTokenize : 1; |
91 | } Fmt; | 91 | } Fmt; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | #endif | 94 | #endif |
diff --git a/src/stable/formatter.cpp b/src/stable/formatter.cpp index a04f7a6..9a42c99 100644 --- a/src/stable/formatter.cpp +++ b/src/stable/formatter.cpp | |||
@@ -12,54 +12,54 @@ | |||
12 | 12 | ||
13 | template<> float Bu::tlog( float x ) | 13 | template<> float Bu::tlog( float x ) |
14 | { | 14 | { |
15 | return logf( x ); | 15 | return logf( x ); |
16 | } | 16 | } |
17 | 17 | ||
18 | template<> double Bu::tlog( double x ) | 18 | template<> double Bu::tlog( double x ) |
19 | { | 19 | { |
20 | return log( x ); | 20 | return log( x ); |
21 | } | 21 | } |
22 | 22 | ||
23 | template<> long double Bu::tlog( long double x ) | 23 | template<> long double Bu::tlog( long double x ) |
24 | { | 24 | { |
25 | return logl( x ); | 25 | return logl( x ); |
26 | } | 26 | } |
27 | 27 | ||
28 | template<> float Bu::tfloor( float x ) | 28 | template<> float Bu::tfloor( float x ) |
29 | { | 29 | { |
30 | return floorf( x ); | 30 | return floorf( x ); |
31 | } | 31 | } |
32 | 32 | ||
33 | template<> double Bu::tfloor( double x ) | 33 | template<> double Bu::tfloor( double x ) |
34 | { | 34 | { |
35 | return floor( x ); | 35 | return floor( x ); |
36 | } | 36 | } |
37 | 37 | ||
38 | template<> long double Bu::tfloor( long double x ) | 38 | template<> long double Bu::tfloor( long double x ) |
39 | { | 39 | { |
40 | return floorl( x ); | 40 | return floorl( x ); |
41 | } | 41 | } |
42 | 42 | ||
43 | template<> float Bu::tpow( float x, float y ) | 43 | template<> float Bu::tpow( float x, float y ) |
44 | { | 44 | { |
45 | return powf( x, y ); | 45 | return powf( x, y ); |
46 | } | 46 | } |
47 | 47 | ||
48 | template<> double Bu::tpow( double x, double y ) | 48 | template<> double Bu::tpow( double x, double y ) |
49 | { | 49 | { |
50 | return pow( x, y ); | 50 | return pow( x, y ); |
51 | } | 51 | } |
52 | 52 | ||
53 | template<> long double Bu::tpow( long double x, long double y ) | 53 | template<> long double Bu::tpow( long double x, long double y ) |
54 | { | 54 | { |
55 | return powl( x, y ); | 55 | return powl( x, y ); |
56 | } | 56 | } |
57 | 57 | ||
58 | Bu::Formatter::Formatter( Stream &rStream ) : | 58 | Bu::Formatter::Formatter( Stream &rStream ) : |
59 | rStream( rStream ), | 59 | rStream( rStream ), |
60 | bTempFmt( false ), | 60 | bTempFmt( false ), |
61 | uIndent( 0 ), | 61 | uIndent( 0 ), |
62 | cIndent( '\t' ) | 62 | cIndent( '\t' ) |
63 | { | 63 | { |
64 | } | 64 | } |
65 | 65 | ||
@@ -69,491 +69,491 @@ Bu::Formatter::~Formatter() | |||
69 | 69 | ||
70 | void Bu::Formatter::write( const Bu::String &sStr ) | 70 | void Bu::Formatter::write( const Bu::String &sStr ) |
71 | { | 71 | { |
72 | rStream.write( sStr ); | 72 | rStream.write( sStr ); |
73 | } | 73 | } |
74 | 74 | ||
75 | void Bu::Formatter::write( const void *sStr, int iLen ) | 75 | void Bu::Formatter::write( const void *sStr, int iLen ) |
76 | { | 76 | { |
77 | rStream.write( sStr, iLen ); | 77 | rStream.write( sStr, iLen ); |
78 | } | 78 | } |
79 | 79 | ||
80 | void Bu::Formatter::writeAligned( const Bu::String &sStr ) | 80 | void Bu::Formatter::writeAligned( const Bu::String &sStr ) |
81 | { | 81 | { |
82 | int iLen = sStr.getSize(); | 82 | int iLen = sStr.getSize(); |
83 | if( iLen > fLast.uMinWidth ) | 83 | if( iLen > fLast.uMinWidth ) |
84 | { | 84 | { |
85 | write( sStr ); | 85 | write( sStr ); |
86 | } | 86 | } |
87 | else | 87 | else |
88 | { | 88 | { |
89 | int iRem = fLast.uMinWidth - iLen; | 89 | int iRem = fLast.uMinWidth - iLen; |
90 | switch( fLast.uAlign ) | 90 | switch( fLast.uAlign ) |
91 | { | 91 | { |
92 | case Fmt::Right: | 92 | case Fmt::Right: |
93 | for( int k = 0; k < iRem; k++ ) | 93 | for( int k = 0; k < iRem; k++ ) |
94 | write( &fLast.cFillChar, 1 ); | 94 | write( &fLast.cFillChar, 1 ); |
95 | write( sStr ); | 95 | write( sStr ); |
96 | break; | 96 | break; |
97 | 97 | ||
98 | case Fmt::Center: | 98 | case Fmt::Center: |
99 | { | 99 | { |
100 | int iHlf = iRem/2; | 100 | int iHlf = iRem/2; |
101 | for( int k = 0; k < iHlf; k++ ) | 101 | for( int k = 0; k < iHlf; k++ ) |
102 | write( &fLast.cFillChar, 1 ); | 102 | write( &fLast.cFillChar, 1 ); |
103 | write( sStr ); | 103 | write( sStr ); |
104 | iHlf = iRem-iHlf;; | 104 | iHlf = iRem-iHlf;; |
105 | for( int k = 0; k < iHlf; k++ ) | 105 | for( int k = 0; k < iHlf; k++ ) |
106 | write( &fLast.cFillChar, 1 ); | 106 | write( &fLast.cFillChar, 1 ); |
107 | } | 107 | } |
108 | break; | 108 | break; |
109 | 109 | ||
110 | case Fmt::Left: | 110 | case Fmt::Left: |
111 | write( sStr ); | 111 | write( sStr ); |
112 | for( int k = 0; k < iRem; k++ ) | 112 | for( int k = 0; k < iRem; k++ ) |
113 | write( &fLast.cFillChar, 1 ); | 113 | write( &fLast.cFillChar, 1 ); |
114 | break; | 114 | break; |
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | usedFormat(); | 118 | usedFormat(); |
119 | } | 119 | } |
120 | 120 | ||
121 | void Bu::Formatter::writeAligned( const char *sStr, int iLen ) | 121 | void Bu::Formatter::writeAligned( const char *sStr, int iLen ) |
122 | { | 122 | { |
123 | if( iLen > fLast.uMinWidth ) | 123 | if( iLen > fLast.uMinWidth ) |
124 | { | 124 | { |
125 | write( sStr, iLen ); | 125 | write( sStr, iLen ); |
126 | } | 126 | } |
127 | else | 127 | else |
128 | { | 128 | { |
129 | int iRem = fLast.uMinWidth - iLen; | 129 | int iRem = fLast.uMinWidth - iLen; |
130 | switch( fLast.uAlign ) | 130 | switch( fLast.uAlign ) |
131 | { | 131 | { |
132 | case Fmt::Right: | 132 | case Fmt::Right: |
133 | for( int k = 0; k < iRem; k++ ) | 133 | for( int k = 0; k < iRem; k++ ) |
134 | write( &fLast.cFillChar, 1 ); | 134 | write( &fLast.cFillChar, 1 ); |
135 | write( sStr, iLen ); | 135 | write( sStr, iLen ); |
136 | break; | 136 | break; |
137 | 137 | ||
138 | case Fmt::Center: | 138 | case Fmt::Center: |
139 | { | 139 | { |
140 | int iHlf = iRem/2; | 140 | int iHlf = iRem/2; |
141 | for( int k = 0; k < iHlf; k++ ) | 141 | for( int k = 0; k < iHlf; k++ ) |
142 | write( &fLast.cFillChar, 1 ); | 142 | write( &fLast.cFillChar, 1 ); |
143 | write( sStr, iLen ); | 143 | write( sStr, iLen ); |
144 | iHlf = iRem-iHlf;; | 144 | iHlf = iRem-iHlf;; |
145 | for( int k = 0; k < iHlf; k++ ) | 145 | for( int k = 0; k < iHlf; k++ ) |
146 | write( &fLast.cFillChar, 1 ); | 146 | write( &fLast.cFillChar, 1 ); |
147 | } | 147 | } |
148 | break; | 148 | break; |
149 | 149 | ||
150 | case Fmt::Left: | 150 | case Fmt::Left: |
151 | write( sStr, iLen ); | 151 | write( sStr, iLen ); |
152 | for( int k = 0; k < iRem; k++ ) | 152 | for( int k = 0; k < iRem; k++ ) |
153 | write( &fLast.cFillChar, 1 ); | 153 | write( &fLast.cFillChar, 1 ); |
154 | break; | 154 | break; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | usedFormat(); | 158 | usedFormat(); |
159 | } | 159 | } |
160 | 160 | ||
161 | void Bu::Formatter::read( void *sStr, int iLen ) | 161 | void Bu::Formatter::read( void *sStr, int iLen ) |
162 | { | 162 | { |
163 | rStream.read( sStr, iLen ); | 163 | rStream.read( sStr, iLen ); |
164 | } | 164 | } |
165 | 165 | ||
166 | Bu::String Bu::Formatter::readToken() | 166 | Bu::String Bu::Formatter::readToken() |
167 | { | 167 | { |
168 | Bu::String sRet; | 168 | Bu::String sRet; |
169 | if( fLast.bTokenize ) | 169 | if( fLast.bTokenize ) |
170 | { | 170 | { |
171 | for(;;) | 171 | for(;;) |
172 | { | 172 | { |
173 | char buf; | 173 | char buf; |
174 | int iRead = rStream.read( &buf, 1 ); | 174 | int iRead = rStream.read( &buf, 1 ); |
175 | if( iRead == 0 ) | 175 | if( iRead == 0 ) |
176 | return sRet; | 176 | return sRet; |
177 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) | 177 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) |
178 | continue; | 178 | continue; |
179 | else | 179 | else |
180 | { | 180 | { |
181 | sRet += buf; | 181 | sRet += buf; |
182 | break; | 182 | break; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | for(;;) | 185 | for(;;) |
186 | { | 186 | { |
187 | char buf; | 187 | char buf; |
188 | int iRead = rStream.read( &buf, 1 ); | 188 | int iRead = rStream.read( &buf, 1 ); |
189 | if( iRead == 0 ) | 189 | if( iRead == 0 ) |
190 | return sRet; | 190 | return sRet; |
191 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) | 191 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) |
192 | return sRet; | 192 | return sRet; |
193 | else | 193 | else |
194 | sRet += buf; | 194 | sRet += buf; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | else | 197 | else |
198 | { | 198 | { |
199 | for(;;) | 199 | for(;;) |
200 | { | 200 | { |
201 | char buf; | 201 | char buf; |
202 | int iRead = rStream.read( &buf, 1 ); | 202 | int iRead = rStream.read( &buf, 1 ); |
203 | if( iRead == 0 ) | 203 | if( iRead == 0 ) |
204 | return sRet; | 204 | return sRet; |
205 | else | 205 | else |
206 | sRet += buf; | 206 | sRet += buf; |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | void Bu::Formatter::incIndent() | 211 | void Bu::Formatter::incIndent() |
212 | { | 212 | { |
213 | if( uIndent < 0xFFU ) | 213 | if( uIndent < 0xFFU ) |
214 | uIndent++; | 214 | uIndent++; |
215 | } | 215 | } |
216 | 216 | ||
217 | void Bu::Formatter::decIndent() | 217 | void Bu::Formatter::decIndent() |
218 | { | 218 | { |
219 | if( uIndent > 0 ) | 219 | if( uIndent > 0 ) |
220 | uIndent--; | 220 | uIndent--; |
221 | } | 221 | } |
222 | 222 | ||
223 | void Bu::Formatter::setIndent( uint8_t uLevel ) | 223 | void Bu::Formatter::setIndent( uint8_t uLevel ) |
224 | { | 224 | { |
225 | uIndent = uLevel; | 225 | uIndent = uLevel; |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::Formatter::clearIndent() | 228 | void Bu::Formatter::clearIndent() |
229 | { | 229 | { |
230 | uIndent = 0; | 230 | uIndent = 0; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::Formatter::setIndentChar( char cIndent ) | 233 | void Bu::Formatter::setIndentChar( char cIndent ) |
234 | { | 234 | { |
235 | this->cIndent = cIndent; | 235 | this->cIndent = cIndent; |
236 | } | 236 | } |
237 | 237 | ||
238 | void Bu::Formatter::doFlush() | 238 | void Bu::Formatter::doFlush() |
239 | { | 239 | { |
240 | rStream.flush(); | 240 | rStream.flush(); |
241 | } | 241 | } |
242 | 242 | ||
243 | Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) | 243 | Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) |
244 | { | 244 | { |
245 | this->uMinWidth = uWidth; | 245 | this->uMinWidth = uWidth; |
246 | return *this; | 246 | return *this; |
247 | } | 247 | } |
248 | 248 | ||
249 | Bu::Fmt &Bu::Fmt::fill( char cFill ) | 249 | Bu::Fmt &Bu::Fmt::fill( char cFill ) |
250 | { | 250 | { |
251 | this->cFillChar = (unsigned char)cFill; | 251 | this->cFillChar = (unsigned char)cFill; |
252 | return *this; | 252 | return *this; |
253 | } | 253 | } |
254 | 254 | ||
255 | Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) | 255 | Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) |
256 | { | 256 | { |
257 | this->uRadix = uRadix; | 257 | this->uRadix = uRadix; |
258 | return *this; | 258 | return *this; |
259 | } | 259 | } |
260 | 260 | ||
261 | Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) | 261 | Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) |
262 | { | 262 | { |
263 | this->uAlign = eAlign; | 263 | this->uAlign = eAlign; |
264 | return *this; | 264 | return *this; |
265 | } | 265 | } |
266 | 266 | ||
267 | Bu::Fmt &Bu::Fmt::left() | 267 | Bu::Fmt &Bu::Fmt::left() |
268 | { | 268 | { |
269 | this->uAlign = Fmt::Left; | 269 | this->uAlign = Fmt::Left; |
270 | return *this; | 270 | return *this; |
271 | } | 271 | } |
272 | 272 | ||
273 | Bu::Fmt &Bu::Fmt::center() | 273 | Bu::Fmt &Bu::Fmt::center() |
274 | { | 274 | { |
275 | this->uAlign = Fmt::Center; | 275 | this->uAlign = Fmt::Center; |
276 | return *this; | 276 | return *this; |
277 | } | 277 | } |
278 | 278 | ||
279 | Bu::Fmt &Bu::Fmt::right() | 279 | Bu::Fmt &Bu::Fmt::right() |
280 | { | 280 | { |
281 | this->uAlign = Fmt::Right; | 281 | this->uAlign = Fmt::Right; |
282 | return *this; | 282 | return *this; |
283 | } | 283 | } |
284 | 284 | ||
285 | Bu::Fmt &Bu::Fmt::plus( bool bPlus ) | 285 | Bu::Fmt &Bu::Fmt::plus( bool bPlus ) |
286 | { | 286 | { |
287 | this->bPlus = bPlus; | 287 | this->bPlus = bPlus; |
288 | return *this; | 288 | return *this; |
289 | } | 289 | } |
290 | 290 | ||
291 | Bu::Fmt &Bu::Fmt::caps( bool bCaps ) | 291 | Bu::Fmt &Bu::Fmt::caps( bool bCaps ) |
292 | { | 292 | { |
293 | this->bCaps = bCaps; | 293 | this->bCaps = bCaps; |
294 | return *this; | 294 | return *this; |
295 | } | 295 | } |
296 | 296 | ||
297 | Bu::Fmt &Bu::Fmt::upper() | 297 | Bu::Fmt &Bu::Fmt::upper() |
298 | { | 298 | { |
299 | this->bCaps = true; | 299 | this->bCaps = true; |
300 | return *this; | 300 | return *this; |
301 | } | 301 | } |
302 | 302 | ||
303 | Bu::Fmt &Bu::Fmt::lower() | 303 | Bu::Fmt &Bu::Fmt::lower() |
304 | { | 304 | { |
305 | this->bCaps = false; | 305 | this->bCaps = false; |
306 | return *this; | 306 | return *this; |
307 | } | 307 | } |
308 | 308 | ||
309 | Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) | 309 | Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) |
310 | { | 310 | { |
311 | this->bTokenize = bTokenize; | 311 | this->bTokenize = bTokenize; |
312 | return *this; | 312 | return *this; |
313 | } | 313 | } |
314 | 314 | ||
315 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) | 315 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) |
316 | { | 316 | { |
317 | f.setTempFormat( fmt ); | 317 | f.setTempFormat( fmt ); |
318 | return f; | 318 | return f; |
319 | } | 319 | } |
320 | 320 | ||
321 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) | 321 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) |
322 | { | 322 | { |
323 | switch( s ) | 323 | switch( s ) |
324 | { | 324 | { |
325 | case Formatter::nl: | 325 | case Formatter::nl: |
326 | { | 326 | { |
327 | #ifdef WIN32 | 327 | #ifdef WIN32 |
328 | f.write("\r\n", 2 ); | 328 | f.write("\r\n", 2 ); |
329 | #else | 329 | #else |
330 | f.write("\n", 1 ); | 330 | f.write("\n", 1 ); |
331 | #endif | 331 | #endif |
332 | char ci = f.getIndentChar(); | 332 | char ci = f.getIndentChar(); |
333 | for( int j = 0; j < f.getIndent(); j++ ) | 333 | for( int j = 0; j < f.getIndent(); j++ ) |
334 | f.write( &ci, 1 ); | 334 | f.write( &ci, 1 ); |
335 | f.doFlush(); | 335 | f.doFlush(); |
336 | } | 336 | } |
337 | break; | 337 | break; |
338 | 338 | ||
339 | case Formatter::flush: | 339 | case Formatter::flush: |
340 | f.doFlush(); | 340 | f.doFlush(); |
341 | break; | 341 | break; |
342 | } | 342 | } |
343 | return f; | 343 | return f; |
344 | } | 344 | } |
345 | 345 | ||
346 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) | 346 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) |
347 | { | 347 | { |
348 | f.writeAligned( sStr, strlen( sStr ) ); | 348 | f.writeAligned( sStr, strlen( sStr ) ); |
349 | return f; | 349 | return f; |
350 | } | 350 | } |
351 | 351 | ||
352 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) | 352 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) |
353 | { | 353 | { |
354 | f.writeAligned( sStr, strlen( sStr ) ); | 354 | f.writeAligned( sStr, strlen( sStr ) ); |
355 | return f; | 355 | return f; |
356 | } | 356 | } |
357 | 357 | ||
358 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) | 358 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) |
359 | { | 359 | { |
360 | f.writeAligned( sStr ); | 360 | f.writeAligned( sStr ); |
361 | return f; | 361 | return f; |
362 | } | 362 | } |
363 | 363 | ||
364 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) | 364 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) |
365 | { | 365 | { |
366 | f.ifmt<signed char>( c ); | 366 | f.ifmt<signed char>( c ); |
367 | //f.write( (char *)&c, 1 ); | 367 | //f.write( (char *)&c, 1 ); |
368 | return f; | 368 | return f; |
369 | } | 369 | } |
370 | 370 | ||
371 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) | 371 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) |
372 | { | 372 | { |
373 | f.write( (char *)&c, 1 ); | 373 | f.write( (char *)&c, 1 ); |
374 | return f; | 374 | return f; |
375 | } | 375 | } |
376 | 376 | ||
377 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) | 377 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) |
378 | { | 378 | { |
379 | f.ufmt<unsigned char>( c ); | 379 | f.ufmt<unsigned char>( c ); |
380 | //f.write( (char *)&c, 1 ); | 380 | //f.write( (char *)&c, 1 ); |
381 | return f; | 381 | return f; |
382 | } | 382 | } |
383 | 383 | ||
384 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) | 384 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) |
385 | { | 385 | { |
386 | f.ifmt<signed short>( i ); | 386 | f.ifmt<signed short>( i ); |
387 | return f; | 387 | return f; |
388 | } | 388 | } |
389 | 389 | ||
390 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) | 390 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) |
391 | { | 391 | { |
392 | f.ufmt<unsigned short>( i ); | 392 | f.ufmt<unsigned short>( i ); |
393 | return f; | 393 | return f; |
394 | } | 394 | } |
395 | 395 | ||
396 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) | 396 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) |
397 | { | 397 | { |
398 | f.ifmt<signed int>( i ); | 398 | f.ifmt<signed int>( i ); |
399 | return f; | 399 | return f; |
400 | } | 400 | } |
401 | 401 | ||
402 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) | 402 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) |
403 | { | 403 | { |
404 | f.ufmt<unsigned int>( i ); | 404 | f.ufmt<unsigned int>( i ); |
405 | return f; | 405 | return f; |
406 | } | 406 | } |
407 | 407 | ||
408 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) | 408 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) |
409 | { | 409 | { |
410 | f.ifmt<signed long>( i ); | 410 | f.ifmt<signed long>( i ); |
411 | return f; | 411 | return f; |
412 | } | 412 | } |
413 | 413 | ||
414 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) | 414 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) |
415 | { | 415 | { |
416 | f.ufmt<unsigned long>( i ); | 416 | f.ufmt<unsigned long>( i ); |
417 | return f; | 417 | return f; |
418 | } | 418 | } |
419 | 419 | ||
420 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) | 420 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) |
421 | { | 421 | { |
422 | f.ifmt<signed long long>( i ); | 422 | f.ifmt<signed long long>( i ); |
423 | return f; | 423 | return f; |
424 | } | 424 | } |
425 | 425 | ||
426 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) | 426 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) |
427 | { | 427 | { |
428 | f.ufmt<unsigned long long>( i ); | 428 | f.ufmt<unsigned long long>( i ); |
429 | return f; | 429 | return f; |
430 | } | 430 | } |
431 | 431 | ||
432 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) | 432 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) |
433 | { | 433 | { |
434 | f.ffmt<float>( flt ); | 434 | f.ffmt<float>( flt ); |
435 | return f; | 435 | return f; |
436 | } | 436 | } |
437 | 437 | ||
438 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) | 438 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) |
439 | { | 439 | { |
440 | f.ffmt<double>( flt ); | 440 | f.ffmt<double>( flt ); |
441 | return f; | 441 | return f; |
442 | } | 442 | } |
443 | 443 | ||
444 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) | 444 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) |
445 | { | 445 | { |
446 | f.ffmt<long double>( flt ); | 446 | f.ffmt<long double>( flt ); |
447 | return f; | 447 | return f; |
448 | } | 448 | } |
449 | 449 | ||
450 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) | 450 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) |
451 | { | 451 | { |
452 | f.writeAligned( b?("true"):("false") ); | 452 | f.writeAligned( b?("true"):("false") ); |
453 | return f; | 453 | return f; |
454 | } | 454 | } |
455 | 455 | ||
456 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) | 456 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) |
457 | { | 457 | { |
458 | sStr = f.readToken(); | 458 | sStr = f.readToken(); |
459 | return f; | 459 | return f; |
460 | } | 460 | } |
461 | 461 | ||
462 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) | 462 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) |
463 | { | 463 | { |
464 | f.read( &c, 1 ); | 464 | f.read( &c, 1 ); |
465 | return f; | 465 | return f; |
466 | } | 466 | } |
467 | 467 | ||
468 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) | 468 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) |
469 | { | 469 | { |
470 | f.read( &c, 1 ); | 470 | f.read( &c, 1 ); |
471 | return f; | 471 | return f; |
472 | } | 472 | } |
473 | 473 | ||
474 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) | 474 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) |
475 | { | 475 | { |
476 | f.read( &c, 1 ); | 476 | f.read( &c, 1 ); |
477 | return f; | 477 | return f; |
478 | } | 478 | } |
479 | 479 | ||
480 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) | 480 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) |
481 | { | 481 | { |
482 | f.iparse( i, f.readToken() ); | 482 | f.iparse( i, f.readToken() ); |
483 | return f; | 483 | return f; |
484 | } | 484 | } |
485 | 485 | ||
486 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) | 486 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) |
487 | { | 487 | { |
488 | f.uparse( i, f.readToken() ); | 488 | f.uparse( i, f.readToken() ); |
489 | return f; | 489 | return f; |
490 | } | 490 | } |
491 | 491 | ||
492 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) | 492 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) |
493 | { | 493 | { |
494 | f.iparse( i, f.readToken() ); | 494 | f.iparse( i, f.readToken() ); |
495 | return f; | 495 | return f; |
496 | } | 496 | } |
497 | 497 | ||
498 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) | 498 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) |
499 | { | 499 | { |
500 | f.uparse( i, f.readToken() ); | 500 | f.uparse( i, f.readToken() ); |
501 | return f; | 501 | return f; |
502 | } | 502 | } |
503 | 503 | ||
504 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) | 504 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) |
505 | { | 505 | { |
506 | f.iparse( i, f.readToken() ); | 506 | f.iparse( i, f.readToken() ); |
507 | return f; | 507 | return f; |
508 | } | 508 | } |
509 | 509 | ||
510 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) | 510 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) |
511 | { | 511 | { |
512 | f.uparse( i, f.readToken() ); | 512 | f.uparse( i, f.readToken() ); |
513 | return f; | 513 | return f; |
514 | } | 514 | } |
515 | 515 | ||
516 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) | 516 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) |
517 | { | 517 | { |
518 | f.iparse( i, f.readToken() ); | 518 | f.iparse( i, f.readToken() ); |
519 | return f; | 519 | return f; |
520 | } | 520 | } |
521 | 521 | ||
522 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) | 522 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) |
523 | { | 523 | { |
524 | f.uparse( i, f.readToken() ); | 524 | f.uparse( i, f.readToken() ); |
525 | return f; | 525 | return f; |
526 | } | 526 | } |
527 | 527 | ||
528 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) | 528 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) |
529 | { | 529 | { |
530 | f.fparse( flt, f.readToken() ); | 530 | f.fparse( flt, f.readToken() ); |
531 | return f; | 531 | return f; |
532 | } | 532 | } |
533 | 533 | ||
534 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) | 534 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) |
535 | { | 535 | { |
536 | f.fparse( flt, f.readToken() ); | 536 | f.fparse( flt, f.readToken() ); |
537 | return f; | 537 | return f; |
538 | } | 538 | } |
539 | 539 | ||
540 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) | 540 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) |
541 | { | 541 | { |
542 | f.fparse( flt, f.readToken() ); | 542 | f.fparse( flt, f.readToken() ); |
543 | return f; | 543 | return f; |
544 | } | 544 | } |
545 | 545 | ||
546 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) | 546 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) |
547 | { | 547 | { |
548 | Bu::String sStr = f.readToken(); | 548 | Bu::String sStr = f.readToken(); |
549 | if( !sStr.isSet() ) | 549 | if( !sStr.isSet() ) |
550 | return f; | 550 | return f; |
551 | char c = *sStr.begin(); | 551 | char c = *sStr.begin(); |
552 | if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) | 552 | if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) |
553 | b = true; | 553 | b = true; |
554 | else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) | 554 | else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) |
555 | b = false; | 555 | b = false; |
556 | 556 | ||
557 | return f; | 557 | return f; |
558 | } | 558 | } |
559 | 559 | ||
diff --git a/src/stable/formatter.h b/src/stable/formatter.h index d92a53b..94794b5 100644 --- a/src/stable/formatter.h +++ b/src/stable/formatter.h | |||
@@ -15,292 +15,292 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | class Stream; | 18 | class Stream; |
19 | 19 | ||
20 | template<typename t> t tlog( t x ); | 20 | template<typename t> t tlog( t x ); |
21 | template<> float tlog( float x ); | 21 | template<> float tlog( float x ); |
22 | template<> double tlog( double x ); | 22 | template<> double tlog( double x ); |
23 | template<> long double tlog( long double x ); | 23 | template<> long double tlog( long double x ); |
24 | 24 | ||
25 | template<typename t> t tfloor( t x ); | 25 | template<typename t> t tfloor( t x ); |
26 | template<> float tfloor( float x ); | 26 | template<> float tfloor( float x ); |
27 | template<> double tfloor( double x ); | 27 | template<> double tfloor( double x ); |
28 | template<> long double tfloor( long double x ); | 28 | template<> long double tfloor( long double x ); |
29 | 29 | ||
30 | template<typename t> t tpow( t x, t y ); | 30 | template<typename t> t tpow( t x, t y ); |
31 | template<> float tpow( float x, float y ); | 31 | template<> float tpow( float x, float y ); |
32 | template<> double tpow( double x, double y ); | 32 | template<> double tpow( double x, double y ); |
33 | template<> long double tpow( long double x, long double y ); | 33 | template<> long double tpow( long double x, long double y ); |
34 | 34 | ||
35 | class Formatter | 35 | class Formatter |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | Formatter( Stream &rStream ); | 38 | Formatter( Stream &rStream ); |
39 | virtual ~Formatter(); | 39 | virtual ~Formatter(); |
40 | 40 | ||
41 | void write( const Bu::String &sStr ); | 41 | void write( const Bu::String &sStr ); |
42 | void write( const void *sStr, int iLen ); | 42 | void write( const void *sStr, int iLen ); |
43 | void writeAligned( const Bu::String &sStr ); | 43 | void writeAligned( const Bu::String &sStr ); |
44 | void writeAligned( const char *sStr, int iLen ); | 44 | void writeAligned( const char *sStr, int iLen ); |
45 | 45 | ||
46 | void read( void *sStr, int iLen ); | 46 | void read( void *sStr, int iLen ); |
47 | Bu::String readToken(); | 47 | Bu::String readToken(); |
48 | 48 | ||
49 | void incIndent(); | 49 | void incIndent(); |
50 | void decIndent(); | 50 | void decIndent(); |
51 | void setIndent( uint8_t uLevel ); | 51 | void setIndent( uint8_t uLevel ); |
52 | void clearIndent(); | 52 | void clearIndent(); |
53 | uint8_t getIndent() const { return uIndent; } | 53 | uint8_t getIndent() const { return uIndent; } |
54 | void setIndentChar( char cIndent ); | 54 | void setIndentChar( char cIndent ); |
55 | char getIndentChar() const { return cIndent; } | 55 | char getIndentChar() const { return cIndent; } |
56 | 56 | ||
57 | void setFormat( const Fmt &f ) | 57 | void setFormat( const Fmt &f ) |
58 | { | 58 | { |
59 | fLast = f; | 59 | fLast = f; |
60 | bTempFmt = false; | 60 | bTempFmt = false; |
61 | } | 61 | } |
62 | 62 | ||
63 | void setTempFormat( const Fmt &f ) | 63 | void setTempFormat( const Fmt &f ) |
64 | { | 64 | { |
65 | fLast = f; | 65 | fLast = f; |
66 | bTempFmt = true; | 66 | bTempFmt = true; |
67 | } | 67 | } |
68 | 68 | ||
69 | void usedFormat() | 69 | void usedFormat() |
70 | { | 70 | { |
71 | if( bTempFmt ) | 71 | if( bTempFmt ) |
72 | fLast = Fmt(); | 72 | fLast = Fmt(); |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename type> | 75 | template<typename type> |
76 | void ifmt( type i ) | 76 | void ifmt( type i ) |
77 | { | 77 | { |
78 | // This code is taken from Nango, hopefully we can make it better. | 78 | // This code is taken from Nango, hopefully we can make it better. |
79 | bool bNeg = i<0; | 79 | bool bNeg = i<0; |
80 | char cBase = fLast.bCaps?'A':'a'; | 80 | char cBase = fLast.bCaps?'A':'a'; |
81 | char buf[sizeof(type)*8+1]; | 81 | char buf[sizeof(type)*8+1]; |
82 | if( bNeg ) i = -i; | 82 | if( bNeg ) i = -i; |
83 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 83 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
84 | { | 84 | { |
85 | usedFormat(); | 85 | usedFormat(); |
86 | return; | 86 | return; |
87 | } | 87 | } |
88 | 88 | ||
89 | for( int j = sizeof(type)*8; j >= 0; j-- ) | 89 | for( int j = sizeof(type)*8; j >= 0; j-- ) |
90 | { | 90 | { |
91 | int c = i%fLast.uRadix; | 91 | int c = i%fLast.uRadix; |
92 | i /= fLast.uRadix; | 92 | i /= fLast.uRadix; |
93 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | 93 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); |
94 | if( i == 0 ) | 94 | if( i == 0 ) |
95 | { | 95 | { |
96 | if( bNeg ) buf[--j] = '-'; | 96 | if( bNeg ) buf[--j] = '-'; |
97 | else if( fLast.bPlus ) buf[--j] = '+'; | 97 | else if( fLast.bPlus ) buf[--j] = '+'; |
98 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | 98 | writeAligned( buf+j, sizeof(type)*8-j+1 ); |
99 | 99 | ||
100 | return; | 100 | return; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | usedFormat(); | 103 | usedFormat(); |
104 | } | 104 | } |
105 | 105 | ||
106 | template<typename type> | 106 | template<typename type> |
107 | void ufmt( type i ) | 107 | void ufmt( type i ) |
108 | { | 108 | { |
109 | // This code is taken from Nango, hopefully we can make it better. | 109 | // This code is taken from Nango, hopefully we can make it better. |
110 | char buf[sizeof(type)*8+1]; | 110 | char buf[sizeof(type)*8+1]; |
111 | char cBase = fLast.bCaps?'A':'a'; | 111 | char cBase = fLast.bCaps?'A':'a'; |
112 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 112 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
113 | { | 113 | { |
114 | usedFormat(); | 114 | usedFormat(); |
115 | return; | 115 | return; |
116 | } | 116 | } |
117 | 117 | ||
118 | for( int j = sizeof(type)*8; j >= 0; j-- ) | 118 | for( int j = sizeof(type)*8; j >= 0; j-- ) |
119 | { | 119 | { |
120 | int c = i%fLast.uRadix; | 120 | int c = i%fLast.uRadix; |
121 | i /= fLast.uRadix; | 121 | i /= fLast.uRadix; |
122 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | 122 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); |
123 | if( i == 0 ) | 123 | if( i == 0 ) |
124 | { | 124 | { |
125 | if( fLast.bPlus ) buf[--j] = '+'; | 125 | if( fLast.bPlus ) buf[--j] = '+'; |
126 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | 126 | writeAligned( buf+j, sizeof(type)*8-j+1 ); |
127 | 127 | ||
128 | return; | 128 | return; |
129 | } | 129 | } |
130 | } | 130 | } |
131 | usedFormat(); | 131 | usedFormat(); |
132 | } | 132 | } |
133 | 133 | ||
134 | template<typename type> | 134 | template<typename type> |
135 | void ffmt( type f ) | 135 | void ffmt( type f ) |
136 | { | 136 | { |
137 | Bu::String fTmp; | 137 | Bu::String fTmp; |
138 | char cBase = fLast.bCaps?'A':'a'; | 138 | char cBase = fLast.bCaps?'A':'a'; |
139 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 139 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
140 | { | 140 | { |
141 | usedFormat(); | 141 | usedFormat(); |
142 | return; | 142 | return; |
143 | } | 143 | } |
144 | 144 | ||
145 | if( signbit(f) ) | 145 | if( signbit(f) ) |
146 | { | 146 | { |
147 | f = -f; | 147 | f = -f; |
148 | fTmp += "-"; | 148 | fTmp += "-"; |
149 | } | 149 | } |
150 | int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); | 150 | int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); |
151 | f /= tpow( (type)fLast.uRadix, (type)iScale ); | 151 | f /= tpow( (type)fLast.uRadix, (type)iScale ); |
152 | 152 | ||
153 | if( iScale < 0 ) | 153 | if( iScale < 0 ) |
154 | { | 154 | { |
155 | fTmp += "0."; | 155 | fTmp += "0."; |
156 | for( int j = 1; j < -iScale; j++ ) | 156 | for( int j = 1; j < -iScale; j++ ) |
157 | fTmp += '0'; | 157 | fTmp += '0'; |
158 | } | 158 | } |
159 | int c = f; | 159 | int c = f; |
160 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | 160 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); |
161 | f -= (int)f; | 161 | f -= (int)f; |
162 | int j; | 162 | int j; |
163 | for( j = 0; j < 8 && f; j++ ) | 163 | for( j = 0; j < 8 && f; j++ ) |
164 | { | 164 | { |
165 | if( iScale - j == 0 ) | 165 | if( iScale - j == 0 ) |
166 | fTmp += '.'; | 166 | fTmp += '.'; |
167 | f = f*fLast.uRadix; | 167 | f = f*fLast.uRadix; |
168 | int c = f; | 168 | int c = f; |
169 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | 169 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); |
170 | f -= (int)f; | 170 | f -= (int)f; |
171 | } | 171 | } |
172 | if( iScale >= j ) | 172 | if( iScale >= j ) |
173 | { | 173 | { |
174 | for( int k = j; k < iScale; k++ ) | 174 | for( int k = j; k < iScale; k++ ) |
175 | fTmp += '0'; | 175 | fTmp += '0'; |
176 | fTmp += ".0"; | 176 | fTmp += ".0"; |
177 | } | 177 | } |
178 | 178 | ||
179 | writeAligned( fTmp ); | 179 | writeAligned( fTmp ); |
180 | usedFormat(); | 180 | usedFormat(); |
181 | } | 181 | } |
182 | 182 | ||
183 | template<typename type> | 183 | template<typename type> |
184 | void iparse( type &i, const Bu::String &sBuf ) | 184 | void iparse( type &i, const Bu::String &sBuf ) |
185 | { | 185 | { |
186 | if( !sBuf.isSet() ) | 186 | if( !sBuf.isSet() ) |
187 | return; | 187 | return; |
188 | if( sBuf[0] != '+' && sBuf[0] != '-' && | 188 | if( sBuf[0] != '+' && sBuf[0] != '-' && |
189 | (sBuf[0] < '0' && sBuf[0] > '9') ) | 189 | (sBuf[0] < '0' && sBuf[0] > '9') ) |
190 | return; | 190 | return; |
191 | int j = 1; | 191 | int j = 1; |
192 | int iMax = sBuf.getSize(); | 192 | int iMax = sBuf.getSize(); |
193 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | 193 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } |
194 | i = 0; | 194 | i = 0; |
195 | type iPos = 1; | 195 | type iPos = 1; |
196 | for(j--; j >= 0; j-- ) | 196 | for(j--; j >= 0; j-- ) |
197 | { | 197 | { |
198 | if( sBuf[j] == '+' || sBuf[j] == '-' ) | 198 | if( sBuf[j] == '+' || sBuf[j] == '-' ) |
199 | continue; | 199 | continue; |
200 | i += (sBuf[j]-'0')*iPos; | 200 | i += (sBuf[j]-'0')*iPos; |
201 | iPos *= fLast.uRadix; | 201 | iPos *= fLast.uRadix; |
202 | } | 202 | } |
203 | if( sBuf[0] == '-' ) | 203 | if( sBuf[0] == '-' ) |
204 | i = -i; | 204 | i = -i; |
205 | 205 | ||
206 | usedFormat(); | 206 | usedFormat(); |
207 | } | 207 | } |
208 | 208 | ||
209 | template<typename type> | 209 | template<typename type> |
210 | void uparse( type &i, const Bu::String &sBuf ) | 210 | void uparse( type &i, const Bu::String &sBuf ) |
211 | { | 211 | { |
212 | if( !sBuf.isSet() ) | 212 | if( !sBuf.isSet() ) |
213 | return; | 213 | return; |
214 | if( sBuf[0] != '+' && | 214 | if( sBuf[0] != '+' && |
215 | (sBuf[0] < '0' && sBuf[0] > '9') ) | 215 | (sBuf[0] < '0' && sBuf[0] > '9') ) |
216 | return; | 216 | return; |
217 | int j = 1; | 217 | int j = 1; |
218 | int iMax = sBuf.getSize(); | 218 | int iMax = sBuf.getSize(); |
219 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | 219 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } |
220 | i = 0; | 220 | i = 0; |
221 | type iPos = 1; | 221 | type iPos = 1; |
222 | for(j--; j >= 0; j-- ) | 222 | for(j--; j >= 0; j-- ) |
223 | { | 223 | { |
224 | if( sBuf[j] == '+' ) | 224 | if( sBuf[j] == '+' ) |
225 | continue; | 225 | continue; |
226 | i += (sBuf[j]-'0')*iPos; | 226 | i += (sBuf[j]-'0')*iPos; |
227 | iPos *= fLast.uRadix; | 227 | iPos *= fLast.uRadix; |
228 | } | 228 | } |
229 | 229 | ||
230 | usedFormat(); | 230 | usedFormat(); |
231 | } | 231 | } |
232 | 232 | ||
233 | template<typename type> | 233 | template<typename type> |
234 | void fparse( type &f, const Bu::String &sBuf ) | 234 | void fparse( type &f, const Bu::String &sBuf ) |
235 | { | 235 | { |
236 | double fIn; | 236 | double fIn; |
237 | sscanf( sBuf.getStr(), "%lf", &fIn ); | 237 | sscanf( sBuf.getStr(), "%lf", &fIn ); |
238 | f = fIn; | 238 | f = fIn; |
239 | usedFormat(); | 239 | usedFormat(); |
240 | } | 240 | } |
241 | 241 | ||
242 | enum Special | 242 | enum Special |
243 | { | 243 | { |
244 | nl, | 244 | nl, |
245 | flush | 245 | flush |
246 | }; | 246 | }; |
247 | 247 | ||
248 | void doFlush(); | 248 | void doFlush(); |
249 | 249 | ||
250 | Stream &getStream() { return rStream; } | 250 | Stream &getStream() { return rStream; } |
251 | operator Stream&() { return rStream; } | 251 | operator Stream&() { return rStream; } |
252 | 252 | ||
253 | private: | 253 | private: |
254 | Stream &rStream; | 254 | Stream &rStream; |
255 | Fmt fLast; | 255 | Fmt fLast; |
256 | bool bTempFmt; | 256 | bool bTempFmt; |
257 | uint8_t uIndent; | 257 | uint8_t uIndent; |
258 | char cIndent; | 258 | char cIndent; |
259 | }; | 259 | }; |
260 | 260 | ||
261 | Formatter &operator<<( Formatter &f, const Fmt &fmt ); | 261 | Formatter &operator<<( Formatter &f, const Fmt &fmt ); |
262 | Formatter &operator<<( Formatter &f, Formatter::Special s ); | 262 | Formatter &operator<<( Formatter &f, Formatter::Special s ); |
263 | Formatter &operator<<( Formatter &f, const char *sStr ); | 263 | Formatter &operator<<( Formatter &f, const char *sStr ); |
264 | Formatter &operator<<( Formatter &f, char *sStr ); | 264 | Formatter &operator<<( Formatter &f, char *sStr ); |
265 | Formatter &operator<<( Formatter &f, const Bu::String &sStr ); | 265 | Formatter &operator<<( Formatter &f, const Bu::String &sStr ); |
266 | Formatter &operator<<( Formatter &f, signed char c ); | 266 | Formatter &operator<<( Formatter &f, signed char c ); |
267 | Formatter &operator<<( Formatter &f, char c ); | 267 | Formatter &operator<<( Formatter &f, char c ); |
268 | Formatter &operator<<( Formatter &f, unsigned char c ); | 268 | Formatter &operator<<( Formatter &f, unsigned char c ); |
269 | Formatter &operator<<( Formatter &f, signed short i ); | 269 | Formatter &operator<<( Formatter &f, signed short i ); |
270 | Formatter &operator<<( Formatter &f, unsigned short i ); | 270 | Formatter &operator<<( Formatter &f, unsigned short i ); |
271 | Formatter &operator<<( Formatter &f, signed int i ); | 271 | Formatter &operator<<( Formatter &f, signed int i ); |
272 | Formatter &operator<<( Formatter &f, unsigned int i ); | 272 | Formatter &operator<<( Formatter &f, unsigned int i ); |
273 | Formatter &operator<<( Formatter &f, signed long i ); | 273 | Formatter &operator<<( Formatter &f, signed long i ); |
274 | Formatter &operator<<( Formatter &f, unsigned long i ); | 274 | Formatter &operator<<( Formatter &f, unsigned long i ); |
275 | Formatter &operator<<( Formatter &f, signed long long i ); | 275 | Formatter &operator<<( Formatter &f, signed long long i ); |
276 | Formatter &operator<<( Formatter &f, unsigned long long i ); | 276 | Formatter &operator<<( Formatter &f, unsigned long long i ); |
277 | Formatter &operator<<( Formatter &f, float flt ); | 277 | Formatter &operator<<( Formatter &f, float flt ); |
278 | Formatter &operator<<( Formatter &f, double flt ); | 278 | Formatter &operator<<( Formatter &f, double flt ); |
279 | Formatter &operator<<( Formatter &f, long double flt ); | 279 | Formatter &operator<<( Formatter &f, long double flt ); |
280 | Formatter &operator<<( Formatter &f, bool b ); | 280 | Formatter &operator<<( Formatter &f, bool b ); |
281 | 281 | ||
282 | Formatter &operator>>( Formatter &f, Bu::String &sStr ); | 282 | Formatter &operator>>( Formatter &f, Bu::String &sStr ); |
283 | Formatter &operator>>( Formatter &f, signed char &c ); | 283 | Formatter &operator>>( Formatter &f, signed char &c ); |
284 | Formatter &operator>>( Formatter &f, char &c ); | 284 | Formatter &operator>>( Formatter &f, char &c ); |
285 | Formatter &operator>>( Formatter &f, unsigned char &c ); | 285 | Formatter &operator>>( Formatter &f, unsigned char &c ); |
286 | Formatter &operator>>( Formatter &f, signed short &i ); | 286 | Formatter &operator>>( Formatter &f, signed short &i ); |
287 | Formatter &operator>>( Formatter &f, unsigned short &i ); | 287 | Formatter &operator>>( Formatter &f, unsigned short &i ); |
288 | Formatter &operator>>( Formatter &f, signed int &i ); | 288 | Formatter &operator>>( Formatter &f, signed int &i ); |
289 | Formatter &operator>>( Formatter &f, unsigned int &i ); | 289 | Formatter &operator>>( Formatter &f, unsigned int &i ); |
290 | Formatter &operator>>( Formatter &f, signed long &i ); | 290 | Formatter &operator>>( Formatter &f, signed long &i ); |
291 | Formatter &operator>>( Formatter &f, unsigned long &i ); | 291 | Formatter &operator>>( Formatter &f, unsigned long &i ); |
292 | Formatter &operator>>( Formatter &f, signed long long &i ); | 292 | Formatter &operator>>( Formatter &f, signed long long &i ); |
293 | Formatter &operator>>( Formatter &f, unsigned long long &i ); | 293 | Formatter &operator>>( Formatter &f, unsigned long long &i ); |
294 | Formatter &operator>>( Formatter &f, float &flt ); | 294 | Formatter &operator>>( Formatter &f, float &flt ); |
295 | Formatter &operator>>( Formatter &f, double &flt ); | 295 | Formatter &operator>>( Formatter &f, double &flt ); |
296 | Formatter &operator>>( Formatter &f, long double &flt ); | 296 | Formatter &operator>>( Formatter &f, long double &flt ); |
297 | Formatter &operator>>( Formatter &f, bool &b ); | 297 | Formatter &operator>>( Formatter &f, bool &b ); |
298 | 298 | ||
299 | template<typename type> | 299 | template<typename type> |
300 | Formatter &operator<<( Formatter &f, const type *p ) | 300 | Formatter &operator<<( Formatter &f, const type *p ) |
301 | { | 301 | { |
302 | return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); | 302 | return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); |
303 | } | 303 | } |
304 | }; | 304 | }; |
305 | 305 | ||
306 | #endif | 306 | #endif |
diff --git a/src/stable/formula.cpp b/src/stable/formula.cpp index 6bc2c58..c5ba1ae 100644 --- a/src/stable/formula.cpp +++ b/src/stable/formula.cpp | |||
@@ -9,6 +9,6 @@ | |||
9 | 9 | ||
10 | namespace Bu | 10 | namespace Bu |
11 | { | 11 | { |
12 | subExceptionDef( FormulaException ); | 12 | subExceptionDef( FormulaException ); |
13 | } | 13 | } |
14 | 14 | ||
diff --git a/src/stable/formula.h b/src/stable/formula.h index 36a0398..b12afd6 100644 --- a/src/stable/formula.h +++ b/src/stable/formula.h | |||
@@ -21,410 +21,410 @@ | |||
21 | 21 | ||
22 | namespace Bu | 22 | namespace Bu |
23 | { | 23 | { |
24 | subExceptionDecl( FormulaException ); | 24 | subExceptionDecl( FormulaException ); |
25 | /** | 25 | /** |
26 | * Implements a very simple formula parser that allows use of variables and | 26 | * Implements a very simple formula parser that allows use of variables and |
27 | * custom functions. This is based on a simple calculator-type parser that | 27 | * custom functions. This is based on a simple calculator-type parser that |
28 | * executes as it processes, accounting for operator precedence and | 28 | * executes as it processes, accounting for operator precedence and |
29 | * grouping. | 29 | * grouping. |
30 | * | 30 | * |
31 | * prec = precision, a type to use for all math (except binary ops) | 31 | * prec = precision, a type to use for all math (except binary ops) |
32 | * bin = binary type, a type to hard cast all data to for binary ops | 32 | * bin = binary type, a type to hard cast all data to for binary ops |
33 | */ | 33 | */ |
34 | template<typename prec, typename bin=uint32_t> | 34 | template<typename prec, typename bin=uint32_t> |
35 | class Formula | 35 | class Formula |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | class Func | 38 | class Func |
39 | { | 39 | { |
40 | public: | 40 | public: |
41 | virtual prec operator()( prec )=0; | 41 | virtual prec operator()( prec )=0; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | typedef Hash<Bu::String, prec> varHash; | 44 | typedef Hash<Bu::String, prec> varHash; |
45 | typedef Hash<Bu::String, Func *> funcHash; | 45 | typedef Hash<Bu::String, Func *> funcHash; |
46 | 46 | ||
47 | Formula() | 47 | Formula() |
48 | { | 48 | { |
49 | } | 49 | } |
50 | 50 | ||
51 | virtual ~Formula() | 51 | virtual ~Formula() |
52 | { | 52 | { |
53 | for( typename funcHash::iterator i = hFunc.begin(); | 53 | for( typename funcHash::iterator i = hFunc.begin(); |
54 | i != hFunc.end(); i++ ) | 54 | i != hFunc.end(); i++ ) |
55 | { | 55 | { |
56 | delete (*i); | 56 | delete (*i); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | prec run( const Bu::String &sFormulaSrc ) | 60 | prec run( const Bu::String &sFormulaSrc ) |
61 | { | 61 | { |
62 | if( sFormulaSrc.isEmpty() ) | 62 | if( sFormulaSrc.isEmpty() ) |
63 | throw FormulaException("Empty formula, nothing to do."); | 63 | throw FormulaException("Empty formula, nothing to do."); |
64 | try | 64 | try |
65 | { | 65 | { |
66 | const char *sFormula = sFormulaSrc.getStr(); | 66 | const char *sFormula = sFormulaSrc.getStr(); |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | uint8_t tNum = nextToken( &sFormula ); | 69 | uint8_t tNum = nextToken( &sFormula ); |
70 | if( tNum == symSubtract ) | 70 | if( tNum == symSubtract ) |
71 | { | 71 | { |
72 | sOper.push( symNegate ); | 72 | sOper.push( symNegate ); |
73 | continue; | 73 | continue; |
74 | } | 74 | } |
75 | else if( tNum == symNot ) | 75 | else if( tNum == symNot ) |
76 | { | 76 | { |
77 | sOper.push( symNot ); | 77 | sOper.push( symNot ); |
78 | continue; | 78 | continue; |
79 | } | 79 | } |
80 | else if( tNum == symOpenParen ) | 80 | else if( tNum == symOpenParen ) |
81 | { | 81 | { |
82 | sOper.push( tNum ); | 82 | sOper.push( tNum ); |
83 | continue; | 83 | continue; |
84 | } | 84 | } |
85 | else if( tNum == symFunction ) | 85 | else if( tNum == symFunction ) |
86 | { | 86 | { |
87 | sOper.push( symFunction ); | 87 | sOper.push( symFunction ); |
88 | continue; | 88 | continue; |
89 | } | 89 | } |
90 | else if( tNum == symEOS ) | 90 | else if( tNum == symEOS ) |
91 | { | 91 | { |
92 | throw Bu::FormulaException( | 92 | throw Bu::FormulaException( |
93 | "Cannot end with an operator."); | 93 | "Cannot end with an operator."); |
94 | } | 94 | } |
95 | 95 | ||
96 | oppart: uint8_t tOpr = nextToken( &sFormula ); | 96 | oppart: uint8_t tOpr = nextToken( &sFormula ); |
97 | if( tOpr == symEOS ) | 97 | if( tOpr == symEOS ) |
98 | { | 98 | { |
99 | reduce(); | 99 | reduce(); |
100 | prec ret = sValue.top(); | 100 | prec ret = sValue.top(); |
101 | sValue.clear(); | 101 | sValue.clear(); |
102 | sFunc.clear(); | 102 | sFunc.clear(); |
103 | sOper.clear(); | 103 | sOper.clear(); |
104 | return ret; | 104 | return ret; |
105 | } | 105 | } |
106 | if( !sOper.isEmpty() && getPrec( sOper.top() ) > | 106 | if( !sOper.isEmpty() && getPrec( sOper.top() ) > |
107 | getPrec( tOpr ) ) | 107 | getPrec( tOpr ) ) |
108 | { | 108 | { |
109 | reduce(); | 109 | reduce(); |
110 | } | 110 | } |
111 | if( tOpr != symCloseParen ) | 111 | if( tOpr != symCloseParen ) |
112 | { | 112 | { |
113 | sOper.push( tOpr ); | 113 | sOper.push( tOpr ); |
114 | } | 114 | } |
115 | else | 115 | else |
116 | { | 116 | { |
117 | reduce( true ); | 117 | reduce( true ); |
118 | goto oppart; | 118 | goto oppart; |
119 | } | 119 | } |
120 | } | 120 | } |
121 | } | 121 | } |
122 | catch( ... ) | 122 | catch( ... ) |
123 | { | 123 | { |
124 | sValue.clear(); | 124 | sValue.clear(); |
125 | sFunc.clear(); | 125 | sFunc.clear(); |
126 | sOper.clear(); | 126 | sOper.clear(); |
127 | throw; | 127 | throw; |
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | varHash hVars; | 131 | varHash hVars; |
132 | funcHash hFunc; | 132 | funcHash hFunc; |
133 | 133 | ||
134 | private: | 134 | private: |
135 | enum | 135 | enum |
136 | { | 136 | { |
137 | symEOS, | 137 | symEOS, |
138 | symAdd, | 138 | symAdd, |
139 | symSubtract, | 139 | symSubtract, |
140 | symMultiply, | 140 | symMultiply, |
141 | symDivide, | 141 | symDivide, |
142 | symOpenParen, | 142 | symOpenParen, |
143 | symCloseParen, | 143 | symCloseParen, |
144 | symNumber, | 144 | symNumber, |
145 | symVariable, | 145 | symVariable, |
146 | symFunction, | 146 | symFunction, |
147 | symExponent, | 147 | symExponent, |
148 | symNegate, | 148 | symNegate, |
149 | symModulus, | 149 | symModulus, |
150 | 150 | ||
151 | symAnd, | 151 | symAnd, |
152 | symOr, | 152 | symOr, |
153 | symXor, | 153 | symXor, |
154 | symNot | 154 | symNot |
155 | }; | 155 | }; |
156 | 156 | ||
157 | typedef uint8_t symType; | 157 | typedef uint8_t symType; |
158 | 158 | ||
159 | Bu::Stack<symType> sOper; | 159 | Bu::Stack<symType> sOper; |
160 | Bu::Stack<prec> sValue; | 160 | Bu::Stack<prec> sValue; |
161 | Bu::Stack<Bu::String> sFunc; | 161 | Bu::Stack<Bu::String> sFunc; |
162 | 162 | ||
163 | private: | 163 | private: |
164 | symType getPrec( symType nOper ) | 164 | symType getPrec( symType nOper ) |
165 | { | 165 | { |
166 | switch( nOper ) | 166 | switch( nOper ) |
167 | { | 167 | { |
168 | case symNumber: | 168 | case symNumber: |
169 | case symVariable: | 169 | case symVariable: |
170 | case symOpenParen: | 170 | case symOpenParen: |
171 | case symCloseParen: | 171 | case symCloseParen: |
172 | return 0; | 172 | return 0; |
173 | 173 | ||
174 | case symAdd: | 174 | case symAdd: |
175 | case symSubtract: | 175 | case symSubtract: |
176 | return 1; | 176 | return 1; |
177 | 177 | ||
178 | case symMultiply: | 178 | case symMultiply: |
179 | case symDivide: | 179 | case symDivide: |
180 | case symModulus: | 180 | case symModulus: |
181 | return 2; | 181 | return 2; |
182 | 182 | ||
183 | case symAnd: | 183 | case symAnd: |
184 | case symOr: | 184 | case symOr: |
185 | case symXor: | 185 | case symXor: |
186 | return 2; | 186 | return 2; |
187 | 187 | ||
188 | case symExponent: | 188 | case symExponent: |
189 | case symNot: | 189 | case symNot: |
190 | case symNegate: | 190 | case symNegate: |
191 | case symFunction: | 191 | case symFunction: |
192 | return 3; | 192 | return 3; |
193 | 193 | ||
194 | default: | 194 | default: |
195 | return 0; | 195 | return 0; |
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | symType nextToken( const char **sBuf ) | 199 | symType nextToken( const char **sBuf ) |
200 | { | 200 | { |
201 | for(;;) | 201 | for(;;) |
202 | { | 202 | { |
203 | char cbuf = **sBuf; | 203 | char cbuf = **sBuf; |
204 | ++(*sBuf); | 204 | ++(*sBuf); |
205 | switch( cbuf ) | 205 | switch( cbuf ) |
206 | { | 206 | { |
207 | case '+': | 207 | case '+': |
208 | return symAdd; | 208 | return symAdd; |
209 | 209 | ||
210 | case '-': | 210 | case '-': |
211 | return symSubtract; | 211 | return symSubtract; |
212 | 212 | ||
213 | case '*': | 213 | case '*': |
214 | return symMultiply; | 214 | return symMultiply; |
215 | 215 | ||
216 | case '/': | 216 | case '/': |
217 | return symDivide; | 217 | return symDivide; |
218 | 218 | ||
219 | case '^': | 219 | case '^': |
220 | return symExponent; | 220 | return symExponent; |
221 | 221 | ||
222 | case '%': | 222 | case '%': |
223 | return symModulus; | 223 | return symModulus; |
224 | 224 | ||
225 | case '(': | 225 | case '(': |
226 | return symOpenParen; | 226 | return symOpenParen; |
227 | 227 | ||
228 | case ')': | 228 | case ')': |
229 | return symCloseParen; | 229 | return symCloseParen; |
230 | 230 | ||
231 | case '|': | 231 | case '|': |
232 | return symOr; | 232 | return symOr; |
233 | 233 | ||
234 | case '&': | 234 | case '&': |
235 | return symAnd; | 235 | return symAnd; |
236 | 236 | ||
237 | case '#': | 237 | case '#': |
238 | return symXor; | 238 | return symXor; |
239 | 239 | ||
240 | case '~': | 240 | case '~': |
241 | return symNot; | 241 | return symNot; |
242 | 242 | ||
243 | case ' ': | 243 | case ' ': |
244 | case '\t': | 244 | case '\t': |
245 | case '\n': | 245 | case '\n': |
246 | case '\r': | 246 | case '\r': |
247 | break; | 247 | break; |
248 | 248 | ||
249 | case '\0': | 249 | case '\0': |
250 | return symEOS; | 250 | return symEOS; |
251 | 251 | ||
252 | default: | 252 | default: |
253 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) | 253 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) |
254 | { | 254 | { |
255 | char num[50]={cbuf}; | 255 | char num[50]={cbuf}; |
256 | int nPos = 1; | 256 | int nPos = 1; |
257 | bool bDot = false; | 257 | bool bDot = false; |
258 | 258 | ||
259 | for(;;) | 259 | for(;;) |
260 | { | 260 | { |
261 | cbuf = **sBuf; | 261 | cbuf = **sBuf; |
262 | if( cbuf == '.' ) | 262 | if( cbuf == '.' ) |
263 | { | 263 | { |
264 | if( bDot == false ) | 264 | if( bDot == false ) |
265 | bDot = true; | 265 | bDot = true; |
266 | else | 266 | else |
267 | throw FormulaException( | 267 | throw FormulaException( |
268 | "Numbers cannot have more than one " | 268 | "Numbers cannot have more than one " |
269 | ". in them." | 269 | ". in them." |
270 | ); | 270 | ); |
271 | } | 271 | } |
272 | if( cbuf == '.' || | 272 | if( cbuf == '.' || |
273 | (cbuf >= '0' && cbuf <= '9') ) | 273 | (cbuf >= '0' && cbuf <= '9') ) |
274 | { | 274 | { |
275 | num[nPos++] = cbuf; | 275 | num[nPos++] = cbuf; |
276 | } | 276 | } |
277 | else | 277 | else |
278 | { | 278 | { |
279 | num[nPos] = '\0'; | 279 | num[nPos] = '\0'; |
280 | sValue.push( | 280 | sValue.push( |
281 | static_cast<prec>( | 281 | static_cast<prec>( |
282 | strtod( num, NULL ) | 282 | strtod( num, NULL ) |
283 | ) | 283 | ) |
284 | ); | 284 | ); |
285 | return symNumber; | 285 | return symNumber; |
286 | } | 286 | } |
287 | ++(*sBuf); | 287 | ++(*sBuf); |
288 | } | 288 | } |
289 | } | 289 | } |
290 | else if( (cbuf >= 'a' && cbuf <= 'z') || | 290 | else if( (cbuf >= 'a' && cbuf <= 'z') || |
291 | (cbuf >= 'A' && cbuf <= 'Z') || | 291 | (cbuf >= 'A' && cbuf <= 'Z') || |
292 | (cbuf == '_') ) | 292 | (cbuf == '_') ) |
293 | { | 293 | { |
294 | char tok[50]={cbuf}; | 294 | char tok[50]={cbuf}; |
295 | int nPos = 1; | 295 | int nPos = 1; |
296 | 296 | ||
297 | for(;;) | 297 | for(;;) |
298 | { | 298 | { |
299 | cbuf = **sBuf; | 299 | cbuf = **sBuf; |
300 | if( (cbuf >= 'a' && cbuf <= 'z') || | 300 | if( (cbuf >= 'a' && cbuf <= 'z') || |
301 | (cbuf >= 'A' && cbuf <= 'Z') || | 301 | (cbuf >= 'A' && cbuf <= 'Z') || |
302 | (cbuf >= '0' && cbuf <= '9') || | 302 | (cbuf >= '0' && cbuf <= '9') || |
303 | cbuf == '_' || cbuf == '.' || cbuf == ':' ) | 303 | cbuf == '_' || cbuf == '.' || cbuf == ':' ) |
304 | { | 304 | { |
305 | tok[nPos++] = cbuf; | 305 | tok[nPos++] = cbuf; |
306 | } | 306 | } |
307 | else | 307 | else |
308 | { | 308 | { |
309 | tok[nPos] = '\0'; | 309 | tok[nPos] = '\0'; |
310 | if( hVars.has( tok ) ) | 310 | if( hVars.has( tok ) ) |
311 | { | 311 | { |
312 | sValue.push( hVars[tok] ); | 312 | sValue.push( hVars[tok] ); |
313 | return symNumber; | 313 | return symNumber; |
314 | } | 314 | } |
315 | else if( hFunc.has( tok ) ) | 315 | else if( hFunc.has( tok ) ) |
316 | { | 316 | { |
317 | sFunc.push( tok ); | 317 | sFunc.push( tok ); |
318 | return symFunction; | 318 | return symFunction; |
319 | } | 319 | } |
320 | else | 320 | else |
321 | { | 321 | { |
322 | throw FormulaException( | 322 | throw FormulaException( |
323 | "No variable or function named " | 323 | "No variable or function named " |
324 | "\"%s\" exists.", | 324 | "\"%s\" exists.", |
325 | tok | 325 | tok |
326 | ); | 326 | ); |
327 | } | 327 | } |
328 | } | 328 | } |
329 | ++(*sBuf); | 329 | ++(*sBuf); |
330 | } | 330 | } |
331 | } | 331 | } |
332 | break; | 332 | break; |
333 | } | 333 | } |
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
337 | void reduce( bool bCloseParen = false ) | 337 | void reduce( bool bCloseParen = false ) |
338 | { | 338 | { |
339 | while( !sOper.isEmpty() ) | 339 | while( !sOper.isEmpty() ) |
340 | { | 340 | { |
341 | uint8_t nOpr = sOper.top(); | 341 | uint8_t nOpr = sOper.top(); |
342 | if( nOpr == symOpenParen ) | 342 | if( nOpr == symOpenParen ) |
343 | { | 343 | { |
344 | if( bCloseParen == true ) | 344 | if( bCloseParen == true ) |
345 | sOper.pop(); | 345 | sOper.pop(); |
346 | return; | 346 | return; |
347 | } | 347 | } |
348 | sOper.pop(); | 348 | sOper.pop(); |
349 | 349 | ||
350 | prec dTop = sValue.top(); | 350 | prec dTop = sValue.top(); |
351 | sValue.pop(); | 351 | sValue.pop(); |
352 | 352 | ||
353 | switch( nOpr ) | 353 | switch( nOpr ) |
354 | { | 354 | { |
355 | case symAdd: | 355 | case symAdd: |
356 | sValue.top() += dTop; | 356 | sValue.top() += dTop; |
357 | break; | 357 | break; |
358 | 358 | ||
359 | case symSubtract: | 359 | case symSubtract: |
360 | sValue.top() -= dTop; | 360 | sValue.top() -= dTop; |
361 | break; | 361 | break; |
362 | 362 | ||
363 | case symMultiply: | 363 | case symMultiply: |
364 | sValue.top() *= dTop; | 364 | sValue.top() *= dTop; |
365 | break; | 365 | break; |
366 | 366 | ||
367 | case symDivide: | 367 | case symDivide: |
368 | sValue.top() /= dTop; | 368 | sValue.top() /= dTop; |
369 | break; | 369 | break; |
370 | 370 | ||
371 | case symExponent: | 371 | case symExponent: |
372 | sValue.top() = static_cast<prec>( | 372 | sValue.top() = static_cast<prec>( |
373 | pow( sValue.top(), dTop ) | 373 | pow( sValue.top(), dTop ) |
374 | ); | 374 | ); |
375 | break; | 375 | break; |
376 | 376 | ||
377 | case symModulus: | 377 | case symModulus: |
378 | sValue.top() = static_cast<prec>( | 378 | sValue.top() = static_cast<prec>( |
379 | fmod( sValue.top(), dTop ) | 379 | fmod( sValue.top(), dTop ) |
380 | ); | 380 | ); |
381 | break; | 381 | break; |
382 | 382 | ||
383 | case symOr: | 383 | case symOr: |
384 | sValue.top() = static_cast<prec>( | 384 | sValue.top() = static_cast<prec>( |
385 | static_cast<bin>(sValue.top()) | | 385 | static_cast<bin>(sValue.top()) | |
386 | static_cast<bin>(dTop) | 386 | static_cast<bin>(dTop) |
387 | ); | 387 | ); |
388 | break; | 388 | break; |
389 | 389 | ||
390 | case symAnd: | 390 | case symAnd: |
391 | sValue.top() = static_cast<prec>( | 391 | sValue.top() = static_cast<prec>( |
392 | static_cast<bin>(sValue.top()) & | 392 | static_cast<bin>(sValue.top()) & |
393 | static_cast<bin>(dTop) | 393 | static_cast<bin>(dTop) |
394 | ); | 394 | ); |
395 | break; | 395 | break; |
396 | 396 | ||
397 | case symXor: | 397 | case symXor: |
398 | sValue.top() = static_cast<prec>( | 398 | sValue.top() = static_cast<prec>( |
399 | static_cast<bin>(sValue.top()) ^ | 399 | static_cast<bin>(sValue.top()) ^ |
400 | static_cast<bin>(dTop) | 400 | static_cast<bin>(dTop) |
401 | ); | 401 | ); |
402 | break; | 402 | break; |
403 | 403 | ||
404 | case symFunction: | 404 | case symFunction: |
405 | sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); | 405 | sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); |
406 | break; | 406 | break; |
407 | 407 | ||
408 | case symNegate: | 408 | case symNegate: |
409 | sValue.push( -dTop ); | 409 | sValue.push( -dTop ); |
410 | break; | 410 | break; |
411 | 411 | ||
412 | case symNot: | 412 | case symNot: |
413 | sValue.push( static_cast<prec>( | 413 | sValue.push( static_cast<prec>( |
414 | ~static_cast<bin>(dTop) | 414 | ~static_cast<bin>(dTop) |
415 | ) ); | 415 | ) ); |
416 | break; | 416 | break; |
417 | } | 417 | } |
418 | } | 418 | } |
419 | 419 | ||
420 | if( bCloseParen == true ) | 420 | if( bCloseParen == true ) |
421 | { | 421 | { |
422 | throw FormulaException( | 422 | throw FormulaException( |
423 | "Close-paren found without matching open-paren." | 423 | "Close-paren found without matching open-paren." |
424 | ); | 424 | ); |
425 | } | 425 | } |
426 | } | 426 | } |
427 | }; | 427 | }; |
428 | } | 428 | } |
429 | 429 | ||
430 | #endif | 430 | #endif |
diff --git a/src/stable/hash.cpp b/src/stable/hash.cpp index f44104b..85a13c7 100644 --- a/src/stable/hash.cpp +++ b/src/stable/hash.cpp | |||
@@ -12,58 +12,58 @@ namespace Bu { subExceptionDef( HashException ) } | |||
12 | template<> | 12 | template<> |
13 | uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) | 13 | uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) |
14 | { | 14 | { |
15 | if (k == NULL) | 15 | if (k == NULL) |
16 | { | 16 | { |
17 | return 0; | 17 | return 0; |
18 | } | 18 | } |
19 | 19 | ||
20 | unsigned long int nPos = 0; | 20 | unsigned long int nPos = 0; |
21 | for( const char *s = k; *s; s++ ) | 21 | for( const char *s = k; *s; s++ ) |
22 | { | 22 | { |
23 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 23 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
24 | } | 24 | } |
25 | 25 | ||
26 | return nPos; | 26 | return nPos; |
27 | } | 27 | } |
28 | 28 | ||
29 | template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) | 29 | template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) |
30 | { | 30 | { |
31 | if( a == b ) | 31 | if( a == b ) |
32 | return true; | 32 | return true; |
33 | 33 | ||
34 | for(int j=0; a[j] == b[j]; j++ ) | 34 | for(int j=0; a[j] == b[j]; j++ ) |
35 | if( a[j] == '\0' ) | 35 | if( a[j] == '\0' ) |
36 | return true; | 36 | return true; |
37 | 37 | ||
38 | return false; | 38 | return false; |
39 | } | 39 | } |
40 | 40 | ||
41 | template<> | 41 | template<> |
42 | uint32_t Bu::__calcHashCode<char *>( char * const &k ) | 42 | uint32_t Bu::__calcHashCode<char *>( char * const &k ) |
43 | { | 43 | { |
44 | if (k == NULL) | 44 | if (k == NULL) |
45 | { | 45 | { |
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | unsigned long int nPos = 0; | 49 | unsigned long int nPos = 0; |
50 | for( const char *s = k; *s; s++ ) | 50 | for( const char *s = k; *s; s++ ) |
51 | { | 51 | { |
52 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 52 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
53 | } | 53 | } |
54 | 54 | ||
55 | return nPos; | 55 | return nPos; |
56 | } | 56 | } |
57 | 57 | ||
58 | template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) | 58 | template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) |
59 | { | 59 | { |
60 | if( a == b ) | 60 | if( a == b ) |
61 | return true; | 61 | return true; |
62 | 62 | ||
63 | for(int j=0; a[j] == b[j]; j++ ) | 63 | for(int j=0; a[j] == b[j]; j++ ) |
64 | if( a[j] == '\0' ) | 64 | if( a[j] == '\0' ) |
65 | return true; | 65 | return true; |
66 | 66 | ||
67 | return false; | 67 | return false; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/src/stable/hash.h b/src/stable/hash.h index 86f189e..1574a1c 100644 --- a/src/stable/hash.h +++ b/src/stable/hash.h | |||
@@ -17,1311 +17,1311 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( HashException ) | 20 | subExceptionDecl( HashException ) |
21 | 21 | ||
22 | enum eHashException | 22 | enum eHashException |
23 | { | 23 | { |
24 | excodeNotFilled | 24 | excodeNotFilled |
25 | }; | 25 | }; |
26 | 26 | ||
27 | template<typename T> | 27 | template<typename T> |
28 | uint32_t __calcHashCode( const T &k ); | 28 | uint32_t __calcHashCode( const T &k ); |
29 | 29 | ||
30 | template<typename T> | 30 | template<typename T> |
31 | bool __cmpHashKeys( const T &a, const T &b ); | 31 | bool __cmpHashKeys( const T &a, const T &b ); |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Default functor used to compute the size of hash tables. This version | 34 | * Default functor used to compute the size of hash tables. This version |
35 | * effectively doubles the size of the table when space is low, ensuring | 35 | * effectively doubles the size of the table when space is low, ensuring |
36 | * that you always wind up with an odd number for the table size. A | 36 | * that you always wind up with an odd number for the table size. A |
37 | * better but slower option is to always find the next prime number that's | 37 | * better but slower option is to always find the next prime number that's |
38 | * above double your current table size, but that has the potential to be | 38 | * above double your current table size, but that has the potential to be |
39 | * slower. | 39 | * slower. |
40 | */ | 40 | */ |
41 | struct __calcNextTSize_fast | 41 | struct __calcNextTSize_fast |
42 | { | 42 | { |
43 | uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, | 43 | uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, |
44 | uint32_t nDeleted ) const | 44 | uint32_t nDeleted ) const |
45 | { | 45 | { |
46 | // This frist case will allow hashtables that are mostly deleted | 46 | // This frist case will allow hashtables that are mostly deleted |
47 | // items to reset to small allocations | 47 | // items to reset to small allocations |
48 | if( nFilled-nDeleted <= nCapacity/4 ) | 48 | if( nFilled-nDeleted <= nCapacity/4 ) |
49 | { | 49 | { |
50 | nCapacity = 11; | 50 | nCapacity = 11; |
51 | while( nCapacity < nFilled*5/4 ) | 51 | while( nCapacity < nFilled*5/4 ) |
52 | nCapacity = nCapacity*2+1; | 52 | nCapacity = nCapacity*2+1; |
53 | return nCapacity; | 53 | return nCapacity; |
54 | } | 54 | } |
55 | // This will hopefully prevent hash tables from growing needlessly | 55 | // This will hopefully prevent hash tables from growing needlessly |
56 | if( nFilled-nDeleted <= nCapacity/2 ) | 56 | if( nFilled-nDeleted <= nCapacity/2 ) |
57 | { | 57 | { |
58 | if( nDeleted == 0 ) | 58 | if( nDeleted == 0 ) |
59 | return nCapacity/4*5+1; // Grow just a little | 59 | return nCapacity/4*5+1; // Grow just a little |
60 | else | 60 | else |
61 | return nCapacity; // We're going to delete things | 61 | return nCapacity; // We're going to delete things |
62 | } | 62 | } |
63 | // Otherwise, just increase the capacity | 63 | // Otherwise, just increase the capacity |
64 | return nCapacity*2+1; | 64 | return nCapacity*2+1; |
65 | } | 65 | } |
66 | }; | 66 | }; |
67 | 67 | ||
68 | template<typename totype> | 68 | template<typename totype> |
69 | int bitsTo( int iCount ) | 69 | int bitsTo( int iCount ) |
70 | { | 70 | { |
71 | return ( (iCount/(sizeof(totype)*8)) | 71 | return ( (iCount/(sizeof(totype)*8)) |
72 | + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); | 72 | + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename key, typename value, typename sizecalc, typename keyalloc, | 75 | template<typename key, typename value, typename sizecalc, typename keyalloc, |
76 | typename valuealloc, typename challoc> | 76 | typename valuealloc, typename challoc> |
77 | class Hash; | 77 | class Hash; |
78 | 78 | ||
79 | /** @cond DEVEL */ | 79 | /** @cond DEVEL */ |
80 | template<typename key, typename value, typename sizecalc, typename keyalloc, | 80 | template<typename key, typename value, typename sizecalc, typename keyalloc, |
81 | typename valuealloc, typename challoc > | 81 | typename valuealloc, typename challoc > |
82 | class HashCore | 82 | class HashCore |
83 | { | 83 | { |
84 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 84 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
85 | friend class SharedCore< | 85 | friend class SharedCore< |
86 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, | 86 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, |
87 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> | 87 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> |
88 | >; | 88 | >; |
89 | private: | 89 | private: |
90 | HashCore() : | 90 | HashCore() : |
91 | nCapacity( 0 ), | 91 | nCapacity( 0 ), |
92 | nFilled( 0 ), | 92 | nFilled( 0 ), |
93 | nDeleted( 0 ), | 93 | nDeleted( 0 ), |
94 | bFilled( NULL ), | 94 | bFilled( NULL ), |
95 | bDeleted( NULL ), | 95 | bDeleted( NULL ), |
96 | aKeys( NULL ), | 96 | aKeys( NULL ), |
97 | aValues( NULL ), | 97 | aValues( NULL ), |
98 | aHashCodes( NULL ) | 98 | aHashCodes( NULL ) |
99 | { | 99 | { |
100 | } | 100 | } |
101 | 101 | ||
102 | virtual ~HashCore() | 102 | virtual ~HashCore() |
103 | { | 103 | { |
104 | clear(); | 104 | clear(); |
105 | } | 105 | } |
106 | 106 | ||
107 | void init() | 107 | void init() |
108 | { | 108 | { |
109 | if( nCapacity > 0 ) | 109 | if( nCapacity > 0 ) |
110 | return; | 110 | return; |
111 | 111 | ||
112 | nCapacity = 11; | 112 | nCapacity = 11; |
113 | nKeysSize = bitsTo<uint32_t>( nCapacity ); | 113 | nKeysSize = bitsTo<uint32_t>( nCapacity ); |
114 | bFilled = ca.allocate( nKeysSize ); | 114 | bFilled = ca.allocate( nKeysSize ); |
115 | bDeleted = ca.allocate( nKeysSize ); | 115 | bDeleted = ca.allocate( nKeysSize ); |
116 | clearBits(); | 116 | clearBits(); |
117 | 117 | ||
118 | aHashCodes = ca.allocate( nCapacity ); | 118 | aHashCodes = ca.allocate( nCapacity ); |
119 | aKeys = ka.allocate( nCapacity ); | 119 | aKeys = ka.allocate( nCapacity ); |
120 | aValues = va.allocate( nCapacity ); | 120 | aValues = va.allocate( nCapacity ); |
121 | } | 121 | } |
122 | 122 | ||
123 | void clearBits() | 123 | void clearBits() |
124 | { | 124 | { |
125 | if( nCapacity == 0 ) | 125 | if( nCapacity == 0 ) |
126 | return; | 126 | return; |
127 | 127 | ||
128 | for( uint32_t j = 0; j < nKeysSize; j++ ) | 128 | for( uint32_t j = 0; j < nKeysSize; j++ ) |
129 | { | 129 | { |
130 | bFilled[j] = bDeleted[j] = 0; | 130 | bFilled[j] = bDeleted[j] = 0; |
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) | 134 | void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) |
135 | { | 135 | { |
136 | init(); | 136 | init(); |
137 | 137 | ||
138 | bFilled[loc/32] |= (1<<(loc%32)); | 138 | bFilled[loc/32] |= (1<<(loc%32)); |
139 | va.construct( &aValues[loc], v ); | 139 | va.construct( &aValues[loc], v ); |
140 | ka.construct( &aKeys[loc], k ); | 140 | ka.construct( &aKeys[loc], k ); |
141 | aHashCodes[loc] = hash; | 141 | aHashCodes[loc] = hash; |
142 | nFilled++; | 142 | nFilled++; |
143 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 143 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
144 | // nFilled, nDeleted, nCapacity ); | 144 | // nFilled, nDeleted, nCapacity ); |
145 | } | 145 | } |
146 | 146 | ||
147 | void _erase( uint32_t loc ) | 147 | void _erase( uint32_t loc ) |
148 | { | 148 | { |
149 | if( nCapacity == 0 ) | 149 | if( nCapacity == 0 ) |
150 | return; | 150 | return; |
151 | 151 | ||
152 | bDeleted[loc/32] |= (1<<(loc%32)); | 152 | bDeleted[loc/32] |= (1<<(loc%32)); |
153 | va.destroy( &aValues[loc] ); | 153 | va.destroy( &aValues[loc] ); |
154 | ka.destroy( &aKeys[loc] ); | 154 | ka.destroy( &aKeys[loc] ); |
155 | nDeleted++; | 155 | nDeleted++; |
156 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 156 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
157 | // nFilled, nDeleted, nCapacity ); | 157 | // nFilled, nDeleted, nCapacity ); |
158 | } | 158 | } |
159 | 159 | ||
160 | key &getKeyAtPos( uint32_t nPos ) | 160 | key &getKeyAtPos( uint32_t nPos ) |
161 | { | 161 | { |
162 | if( nPos >= nCapacity ) | 162 | if( nPos >= nCapacity ) |
163 | throw HashException("Referenced position invalid."); | 163 | throw HashException("Referenced position invalid."); |
164 | return aKeys[nPos]; | 164 | return aKeys[nPos]; |
165 | } | 165 | } |
166 | 166 | ||
167 | const key &getKeyAtPos( uint32_t nPos ) const | 167 | const key &getKeyAtPos( uint32_t nPos ) const |
168 | { | 168 | { |
169 | if( nPos >= nCapacity ) | 169 | if( nPos >= nCapacity ) |
170 | throw HashException("Referenced position invalid."); | 170 | throw HashException("Referenced position invalid."); |
171 | return aKeys[nPos]; | 171 | return aKeys[nPos]; |
172 | } | 172 | } |
173 | 173 | ||
174 | value &getValueAtPos( uint32_t nPos ) | 174 | value &getValueAtPos( uint32_t nPos ) |
175 | { | 175 | { |
176 | if( nPos >= nCapacity ) | 176 | if( nPos >= nCapacity ) |
177 | throw HashException("Referenced position invalid."); | 177 | throw HashException("Referenced position invalid."); |
178 | return aValues[nPos]; | 178 | return aValues[nPos]; |
179 | } | 179 | } |
180 | 180 | ||
181 | const value &getValueAtPos( uint32_t nPos ) const | 181 | const value &getValueAtPos( uint32_t nPos ) const |
182 | { | 182 | { |
183 | if( nPos >= nCapacity ) | 183 | if( nPos >= nCapacity ) |
184 | throw HashException("Referenced position invalid."); | 184 | throw HashException("Referenced position invalid."); |
185 | return aValues[nPos]; | 185 | return aValues[nPos]; |
186 | } | 186 | } |
187 | 187 | ||
188 | uint32_t getFirstPos( bool &bFinished ) const | 188 | uint32_t getFirstPos( bool &bFinished ) const |
189 | { | 189 | { |
190 | for( uint32_t j = 0; j < nCapacity; j++ ) | 190 | for( uint32_t j = 0; j < nCapacity; j++ ) |
191 | { | 191 | { |
192 | if( isFilled( j ) ) | 192 | if( isFilled( j ) ) |
193 | if( !isDeleted( j ) ) | 193 | if( !isDeleted( j ) ) |
194 | return j; | 194 | return j; |
195 | } | 195 | } |
196 | 196 | ||
197 | bFinished = true; | 197 | bFinished = true; |
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const | 201 | uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const |
202 | { | 202 | { |
203 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) | 203 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) |
204 | { | 204 | { |
205 | if( isFilled( j ) ) | 205 | if( isFilled( j ) ) |
206 | if( !isDeleted( j ) ) | 206 | if( !isDeleted( j ) ) |
207 | return j; | 207 | return j; |
208 | } | 208 | } |
209 | 209 | ||
210 | bFinished = true; | 210 | bFinished = true; |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | 213 | ||
214 | uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) | 214 | uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) |
215 | { | 215 | { |
216 | init(); | 216 | init(); |
217 | 217 | ||
218 | uint32_t nCur = hash%nCapacity; | 218 | uint32_t nCur = hash%nCapacity; |
219 | 219 | ||
220 | // First we scan to see if the key is already there, abort if we | 220 | // First we scan to see if the key is already there, abort if we |
221 | // run out of probing room, or we find a non-filled entry | 221 | // run out of probing room, or we find a non-filled entry |
222 | int8_t j; | 222 | int8_t j; |
223 | for( j = 0; | 223 | for( j = 0; |
224 | isFilled( nCur ) && j < 32; | 224 | isFilled( nCur ) && j < 32; |
225 | nCur = (nCur + (1<<j))%nCapacity, j++ | 225 | nCur = (nCur + (1<<j))%nCapacity, j++ |
226 | ) | 226 | ) |
227 | { | 227 | { |
228 | // Is this the same hash code we were looking for? | 228 | // Is this the same hash code we were looking for? |
229 | if( hash == aHashCodes[nCur] ) | 229 | if( hash == aHashCodes[nCur] ) |
230 | { | 230 | { |
231 | // Skip over deleted entries. Deleted entries are also filled, | 231 | // Skip over deleted entries. Deleted entries are also filled, |
232 | // so we only have to do this check here. | 232 | // so we only have to do this check here. |
233 | if( isDeleted( nCur ) ) | 233 | if( isDeleted( nCur ) ) |
234 | continue; | 234 | continue; |
235 | 235 | ||
236 | // Is it really the same key? (for safety) | 236 | // Is it really the same key? (for safety) |
237 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | 237 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) |
238 | { | 238 | { |
239 | bFill = true; | 239 | bFill = true; |
240 | return nCur; | 240 | return nCur; |
241 | } | 241 | } |
242 | } | 242 | } |
243 | } | 243 | } |
244 | 244 | ||
245 | // This is our insurance, if the table is full, then go ahead and | 245 | // This is our insurance, if the table is full, then go ahead and |
246 | // rehash, then try again. | 246 | // rehash, then try again. |
247 | if( (isFilled( nCur ) || j == 32) && rehash == true ) | 247 | if( (isFilled( nCur ) || j == 32) && rehash == true ) |
248 | { | 248 | { |
249 | reHash( szCalc( nCapacity, nFilled, nDeleted ) ); | 249 | reHash( szCalc( nCapacity, nFilled, nDeleted ) ); |
250 | 250 | ||
251 | // This is potentially dangerous, and could cause an infinite loop. | 251 | // This is potentially dangerous, and could cause an infinite loop. |
252 | // Be careful writing probe, eh? | 252 | // Be careful writing probe, eh? |
253 | return probe( hash, k, bFill ); | 253 | return probe( hash, k, bFill ); |
254 | } | 254 | } |
255 | 255 | ||
256 | bFill = false; | 256 | bFill = false; |
257 | return nCur; | 257 | return nCur; |
258 | } | 258 | } |
259 | 259 | ||
260 | uint32_t probe( uint32_t hash, key k, bool &bFill ) const | 260 | uint32_t probe( uint32_t hash, key k, bool &bFill ) const |
261 | { | 261 | { |
262 | if( nCapacity == 0 ) | 262 | if( nCapacity == 0 ) |
263 | throw Bu::ExceptionBase("Probe in empty hash table."); | 263 | throw Bu::ExceptionBase("Probe in empty hash table."); |
264 | 264 | ||
265 | uint32_t nCur = hash%nCapacity; | 265 | uint32_t nCur = hash%nCapacity; |
266 | 266 | ||
267 | // First we scan to see if the key is already there, abort if we | 267 | // First we scan to see if the key is already there, abort if we |
268 | // run out of probing room, or we find a non-filled entry | 268 | // run out of probing room, or we find a non-filled entry |
269 | for( int8_t j = 0; | 269 | for( int8_t j = 0; |
270 | isFilled( nCur ) && j < 32; | 270 | isFilled( nCur ) && j < 32; |
271 | nCur = (nCur + (1<<j))%nCapacity, j++ | 271 | nCur = (nCur + (1<<j))%nCapacity, j++ |
272 | ) | 272 | ) |
273 | { | 273 | { |
274 | // Is this the same hash code we were looking for? | 274 | // Is this the same hash code we were looking for? |
275 | if( hash == aHashCodes[nCur] ) | 275 | if( hash == aHashCodes[nCur] ) |
276 | { | 276 | { |
277 | // Skip over deleted entries. Deleted entries are also filled, | 277 | // Skip over deleted entries. Deleted entries are also filled, |
278 | // so we only have to do this check here. | 278 | // so we only have to do this check here. |
279 | if( isDeleted( nCur ) ) | 279 | if( isDeleted( nCur ) ) |
280 | continue; | 280 | continue; |
281 | 281 | ||
282 | // Is it really the same key? (for safety) | 282 | // Is it really the same key? (for safety) |
283 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | 283 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) |
284 | { | 284 | { |
285 | bFill = true; | 285 | bFill = true; |
286 | return nCur; | 286 | return nCur; |
287 | } | 287 | } |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
291 | bFill = false; | 291 | bFill = false; |
292 | return nCur; | 292 | return nCur; |
293 | } | 293 | } |
294 | 294 | ||
295 | void insert( const key &k, const value &v ) | 295 | void insert( const key &k, const value &v ) |
296 | { | 296 | { |
297 | uint32_t hash = __calcHashCode( k ); | 297 | uint32_t hash = __calcHashCode( k ); |
298 | bool bFill; | 298 | bool bFill; |
299 | uint32_t nPos = probe( hash, k, bFill ); | 299 | uint32_t nPos = probe( hash, k, bFill ); |
300 | 300 | ||
301 | if( bFill ) | 301 | if( bFill ) |
302 | { | 302 | { |
303 | va.destroy( &aValues[nPos] ); | 303 | va.destroy( &aValues[nPos] ); |
304 | va.construct( &aValues[nPos], v ); | 304 | va.construct( &aValues[nPos], v ); |
305 | } | 305 | } |
306 | else | 306 | else |
307 | { | 307 | { |
308 | fill( nPos, k, v, hash ); | 308 | fill( nPos, k, v, hash ); |
309 | } | 309 | } |
310 | } | 310 | } |
311 | 311 | ||
312 | void reHash( uint32_t nNewSize ) | 312 | void reHash( uint32_t nNewSize ) |
313 | { | 313 | { |
314 | //printf("--rehash: %d --> %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); | 314 | //printf("--rehash: %d --> %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); |
315 | //printf("---REHASH---"); | 315 | //printf("---REHASH---"); |
316 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 316 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
317 | // nFilled, nDeleted, nCapacity ); | 317 | // nFilled, nDeleted, nCapacity ); |
318 | 318 | ||
319 | // Save all the old data | 319 | // Save all the old data |
320 | uint32_t nOldCapacity = nCapacity; | 320 | uint32_t nOldCapacity = nCapacity; |
321 | uint32_t *bOldFilled = bFilled; | 321 | uint32_t *bOldFilled = bFilled; |
322 | uint32_t *aOldHashCodes = aHashCodes; | 322 | uint32_t *aOldHashCodes = aHashCodes; |
323 | uint32_t nOldKeysSize = nKeysSize; | 323 | uint32_t nOldKeysSize = nKeysSize; |
324 | uint32_t *bOldDeleted = bDeleted; | 324 | uint32_t *bOldDeleted = bDeleted; |
325 | value *aOldValues = aValues; | 325 | value *aOldValues = aValues; |
326 | key *aOldKeys = aKeys; | 326 | key *aOldKeys = aKeys; |
327 | 327 | ||
328 | // Calculate new sizes | 328 | // Calculate new sizes |
329 | nCapacity = nNewSize; | 329 | nCapacity = nNewSize; |
330 | nKeysSize = bitsTo<uint32_t>( nCapacity ); | 330 | nKeysSize = bitsTo<uint32_t>( nCapacity ); |
331 | 331 | ||
332 | // Allocate new memory + prep | 332 | // Allocate new memory + prep |
333 | bFilled = ca.allocate( nKeysSize ); | 333 | bFilled = ca.allocate( nKeysSize ); |
334 | bDeleted = ca.allocate( nKeysSize ); | 334 | bDeleted = ca.allocate( nKeysSize ); |
335 | clearBits(); | 335 | clearBits(); |
336 | 336 | ||
337 | aHashCodes = ca.allocate( nCapacity ); | 337 | aHashCodes = ca.allocate( nCapacity ); |
338 | aKeys = ka.allocate( nCapacity ); | 338 | aKeys = ka.allocate( nCapacity ); |
339 | aValues = va.allocate( nCapacity ); | 339 | aValues = va.allocate( nCapacity ); |
340 | 340 | ||
341 | nDeleted = nFilled = 0; | 341 | nDeleted = nFilled = 0; |
342 | 342 | ||
343 | // Re-insert all of the old data (except deleted items) | 343 | // Re-insert all of the old data (except deleted items) |
344 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | 344 | for( uint32_t j = 0; j < nOldCapacity; j++ ) |
345 | { | 345 | { |
346 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | 346 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && |
347 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | 347 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) |
348 | { | 348 | { |
349 | insert( aOldKeys[j], aOldValues[j] ); | 349 | insert( aOldKeys[j], aOldValues[j] ); |
350 | } | 350 | } |
351 | } | 351 | } |
352 | 352 | ||
353 | // Delete all of the old data | 353 | // Delete all of the old data |
354 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | 354 | for( uint32_t j = 0; j < nOldCapacity; j++ ) |
355 | { | 355 | { |
356 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | 356 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && |
357 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | 357 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) |
358 | { | 358 | { |
359 | va.destroy( &aOldValues[j] ); | 359 | va.destroy( &aOldValues[j] ); |
360 | ka.destroy( &aOldKeys[j] ); | 360 | ka.destroy( &aOldKeys[j] ); |
361 | } | 361 | } |
362 | } | 362 | } |
363 | va.deallocate( aOldValues, nOldCapacity ); | 363 | va.deallocate( aOldValues, nOldCapacity ); |
364 | ka.deallocate( aOldKeys, nOldCapacity ); | 364 | ka.deallocate( aOldKeys, nOldCapacity ); |
365 | ca.deallocate( bOldFilled, nOldKeysSize ); | 365 | ca.deallocate( bOldFilled, nOldKeysSize ); |
366 | ca.deallocate( bOldDeleted, nOldKeysSize ); | 366 | ca.deallocate( bOldDeleted, nOldKeysSize ); |
367 | ca.deallocate( aOldHashCodes, nOldCapacity ); | 367 | ca.deallocate( aOldHashCodes, nOldCapacity ); |
368 | } | 368 | } |
369 | 369 | ||
370 | bool isFilled( uint32_t loc ) const | 370 | bool isFilled( uint32_t loc ) const |
371 | { | 371 | { |
372 | if( loc >= nCapacity ) | 372 | if( loc >= nCapacity ) |
373 | throw HashException("Referenced position invalid."); | 373 | throw HashException("Referenced position invalid."); |
374 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; | 374 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; |
375 | } | 375 | } |
376 | 376 | ||
377 | bool isDeleted( uint32_t loc ) const | 377 | bool isDeleted( uint32_t loc ) const |
378 | { | 378 | { |
379 | if( loc >= nCapacity ) | 379 | if( loc >= nCapacity ) |
380 | throw HashException("Referenced position invalid."); | 380 | throw HashException("Referenced position invalid."); |
381 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; | 381 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; |
382 | } | 382 | } |
383 | 383 | ||
384 | void clear() | 384 | void clear() |
385 | { | 385 | { |
386 | for( uint32_t j = 0; j < nCapacity; j++ ) | 386 | for( uint32_t j = 0; j < nCapacity; j++ ) |
387 | { | 387 | { |
388 | if( isFilled( j ) ) | 388 | if( isFilled( j ) ) |
389 | if( !isDeleted( j ) ) | 389 | if( !isDeleted( j ) ) |
390 | { | 390 | { |
391 | va.destroy( &aValues[j] ); | 391 | va.destroy( &aValues[j] ); |
392 | ka.destroy( &aKeys[j] ); | 392 | ka.destroy( &aKeys[j] ); |
393 | } | 393 | } |
394 | } | 394 | } |
395 | va.deallocate( aValues, nCapacity ); | 395 | va.deallocate( aValues, nCapacity ); |
396 | ka.deallocate( aKeys, nCapacity ); | 396 | ka.deallocate( aKeys, nCapacity ); |
397 | ca.deallocate( bFilled, nKeysSize ); | 397 | ca.deallocate( bFilled, nKeysSize ); |
398 | ca.deallocate( bDeleted, nKeysSize ); | 398 | ca.deallocate( bDeleted, nKeysSize ); |
399 | ca.deallocate( aHashCodes, nCapacity ); | 399 | ca.deallocate( aHashCodes, nCapacity ); |
400 | 400 | ||
401 | bFilled = NULL; | 401 | bFilled = NULL; |
402 | bDeleted = NULL; | 402 | bDeleted = NULL; |
403 | aKeys = NULL; | 403 | aKeys = NULL; |
404 | aValues = NULL; | 404 | aValues = NULL; |
405 | aHashCodes = NULL; | 405 | aHashCodes = NULL; |
406 | 406 | ||
407 | nCapacity = 0; | 407 | nCapacity = 0; |
408 | nFilled = 0; | 408 | nFilled = 0; |
409 | nDeleted = 0; | 409 | nDeleted = 0; |
410 | } | 410 | } |
411 | 411 | ||
412 | uint32_t nCapacity; | 412 | uint32_t nCapacity; |
413 | uint32_t nFilled; | 413 | uint32_t nFilled; |
414 | uint32_t nDeleted; | 414 | uint32_t nDeleted; |
415 | uint32_t *bFilled; | 415 | uint32_t *bFilled; |
416 | uint32_t *bDeleted; | 416 | uint32_t *bDeleted; |
417 | uint32_t nKeysSize; | 417 | uint32_t nKeysSize; |
418 | key *aKeys; | 418 | key *aKeys; |
419 | value *aValues; | 419 | value *aValues; |
420 | uint32_t *aHashCodes; | 420 | uint32_t *aHashCodes; |
421 | valuealloc va; | 421 | valuealloc va; |
422 | keyalloc ka; | 422 | keyalloc ka; |
423 | challoc ca; | 423 | challoc ca; |
424 | sizecalc szCalc; | 424 | sizecalc szCalc; |
425 | }; | 425 | }; |
426 | /** @endcond */ | 426 | /** @endcond */ |
427 | 427 | ||
428 | /** | 428 | /** |
429 | * Libbu++ Template Hash Table. This is your average hash table, that uses | 429 | * Libbu++ Template Hash Table. This is your average hash table, that uses |
430 | * template functions in order to do fast, efficient, generalized hashing. | 430 | * template functions in order to do fast, efficient, generalized hashing. |
431 | * It's pretty easy to use, and works well with all other libbu++ types so | 431 | * It's pretty easy to use, and works well with all other libbu++ types so |
432 | * far. | 432 | * far. |
433 | * | 433 | * |
434 | * In order to use it, I recommend the following for all basic usage: | 434 | * In order to use it, I recommend the following for all basic usage: |
435 | *@code | 435 | *@code |
436 | // Define a Hash typedef with strings as keys and ints as values. | 436 | // Define a Hash typedef with strings as keys and ints as values. |
437 | typedef Bu::Hash<Bu::String, int> StrIntHash; | 437 | typedef Bu::Hash<Bu::String, int> StrIntHash; |
438 | 438 | ||
439 | // Create one | 439 | // Create one |
440 | StrIntHash hInts; | 440 | StrIntHash hInts; |
441 | 441 | ||
442 | // Insert some integers | 442 | // Insert some integers |
443 | hInts["one"] = 1; | 443 | hInts["one"] = 1; |
444 | hInts["forty-two"] = 42; | 444 | hInts["forty-two"] = 42; |
445 | hInts.insert("forty two", 42 ); | 445 | hInts.insert("forty two", 42 ); |
446 | 446 | ||
447 | // Get values out of the hash, the last two options are the most explicit, | 447 | // Get values out of the hash, the last two options are the most explicit, |
448 | // and must be used if the hash's value type does not match what you're | 448 | // and must be used if the hash's value type does not match what you're |
449 | // comparing to exactly. | 449 | // comparing to exactly. |
450 | if( hInts["one"] == 1 ) doSomething(); | 450 | if( hInts["one"] == 1 ) doSomething(); |
451 | if( hInts["forty-two"].value() == 42 ) doSomething(); | 451 | if( hInts["forty-two"].value() == 42 ) doSomething(); |
452 | if( hInts.get("forty two") == 42 ) doSomething(); | 452 | if( hInts.get("forty two") == 42 ) doSomething(); |
453 | 453 | ||
454 | // Iterate through the Hash | 454 | // Iterate through the Hash |
455 | for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) | 455 | for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) |
456 | { | 456 | { |
457 | // i.getValue() works too | 457 | // i.getValue() works too |
458 | print("'%s' = %d\n", i.getKey().getStr(), (*i) ); | 458 | print("'%s' = %d\n", i.getKey().getStr(), (*i) ); |
459 | } | 459 | } |
460 | 460 | ||
461 | @endcode | 461 | @endcode |
462 | *@param key (typename) The datatype of the hashtable keys | 462 | *@param key (typename) The datatype of the hashtable keys |
463 | *@param value (typename) The datatype of the hashtable data | 463 | *@param value (typename) The datatype of the hashtable data |
464 | *@param sizecalc (typename) Functor to compute new table size on rehash | 464 | *@param sizecalc (typename) Functor to compute new table size on rehash |
465 | *@param keyalloc (typename) Memory allocator for hashtable keys | 465 | *@param keyalloc (typename) Memory allocator for hashtable keys |
466 | *@param valuealloc (typename) Memory allocator for hashtable values | 466 | *@param valuealloc (typename) Memory allocator for hashtable values |
467 | *@param challoc (typename) Byte allocator for bitflags | 467 | *@param challoc (typename) Byte allocator for bitflags |
468 | *@ingroup Containers | 468 | *@ingroup Containers |
469 | */ | 469 | */ |
470 | template<typename key, typename value, | 470 | template<typename key, typename value, |
471 | typename sizecalc = __calcNextTSize_fast, | 471 | typename sizecalc = __calcNextTSize_fast, |
472 | typename keyalloc = std::allocator<key>, | 472 | typename keyalloc = std::allocator<key>, |
473 | typename valuealloc = std::allocator<value>, | 473 | typename valuealloc = std::allocator<value>, |
474 | typename challoc = std::allocator<uint32_t> | 474 | typename challoc = std::allocator<uint32_t> |
475 | > | 475 | > |
476 | class Hash : public SharedCore< | 476 | class Hash : public SharedCore< |
477 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, | 477 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, |
478 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> | 478 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> |
479 | > | 479 | > |
480 | { | 480 | { |
481 | private: | 481 | private: |
482 | typedef class HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> Core; | 482 | typedef class HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> Core; |
483 | typedef class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> MyType; | 483 | typedef class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> MyType; |
484 | protected: | 484 | protected: |
485 | using SharedCore<MyType, Core>::core; | 485 | using SharedCore<MyType, Core>::core; |
486 | using SharedCore<MyType, Core>::_hardCopy; | 486 | using SharedCore<MyType, Core>::_hardCopy; |
487 | using SharedCore<MyType, Core>::_resetCore; | 487 | using SharedCore<MyType, Core>::_resetCore; |
488 | using SharedCore<MyType, Core>::_allocateCore; | 488 | using SharedCore<MyType, Core>::_allocateCore; |
489 | 489 | ||
490 | public: | 490 | public: |
491 | Hash() | 491 | Hash() |
492 | { | 492 | { |
493 | } | 493 | } |
494 | 494 | ||
495 | Hash( const MyType &src ) : | 495 | Hash( const MyType &src ) : |
496 | SharedCore<MyType, Core >( src ) | 496 | SharedCore<MyType, Core >( src ) |
497 | { | 497 | { |
498 | } | 498 | } |
499 | 499 | ||
500 | virtual ~Hash() | 500 | virtual ~Hash() |
501 | { | 501 | { |
502 | } | 502 | } |
503 | 503 | ||
504 | /** | 504 | /** |
505 | * Get the current hash table capacity. (Changes at re-hash) | 505 | * Get the current hash table capacity. (Changes at re-hash) |
506 | *@returns (uint32_t) The current capacity. | 506 | *@returns (uint32_t) The current capacity. |
507 | */ | 507 | */ |
508 | uint32_t getCapacity() const | 508 | uint32_t getCapacity() const |
509 | { | 509 | { |
510 | return core->nCapacity; | 510 | return core->nCapacity; |
511 | } | 511 | } |
512 | 512 | ||
513 | /** | 513 | /** |
514 | * Get the number of hash locations spoken for. (Including | 514 | * Get the number of hash locations spoken for. (Including |
515 | * not-yet-cleaned-up deleted items.) | 515 | * not-yet-cleaned-up deleted items.) |
516 | *@returns (uint32_t) The current fill state. | 516 | *@returns (uint32_t) The current fill state. |
517 | */ | 517 | */ |
518 | uint32_t getFill() const | 518 | uint32_t getFill() const |
519 | { | 519 | { |
520 | return core->nFilled; | 520 | return core->nFilled; |
521 | } | 521 | } |
522 | 522 | ||
523 | /** | 523 | /** |
524 | * Get the number of items stored in the hash table. | 524 | * Get the number of items stored in the hash table. |
525 | *@returns (uint32_t) The number of items stored in the hash table. | 525 | *@returns (uint32_t) The number of items stored in the hash table. |
526 | */ | 526 | */ |
527 | uint32_t getSize() const | 527 | uint32_t getSize() const |
528 | { | 528 | { |
529 | return core->nFilled-core->nDeleted; | 529 | return core->nFilled-core->nDeleted; |
530 | } | 530 | } |
531 | 531 | ||
532 | bool isEmpty() const | 532 | bool isEmpty() const |
533 | { | 533 | { |
534 | return (core->nFilled-core->nDeleted) == 0; | 534 | return (core->nFilled-core->nDeleted) == 0; |
535 | } | 535 | } |
536 | 536 | ||
537 | /** | 537 | /** |
538 | * Get the number of items which have been deleted, but not yet | 538 | * Get the number of items which have been deleted, but not yet |
539 | * cleaned up. | 539 | * cleaned up. |
540 | *@returns (uint32_t) The number of deleted items. | 540 | *@returns (uint32_t) The number of deleted items. |
541 | */ | 541 | */ |
542 | uint32_t getDeleted() const | 542 | uint32_t getDeleted() const |
543 | { | 543 | { |
544 | return core->nDeleted; | 544 | return core->nDeleted; |
545 | } | 545 | } |
546 | 546 | ||
547 | struct HashProxy | 547 | struct HashProxy |
548 | { | 548 | { |
549 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 549 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
550 | private: | 550 | private: |
551 | HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : | 551 | HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : |
552 | hsh( h ), | 552 | hsh( h ), |
553 | pKey( k ), | 553 | pKey( k ), |
554 | nPos( nPos ), | 554 | nPos( nPos ), |
555 | hash( hash ), | 555 | hash( hash ), |
556 | bFilled( false ) | 556 | bFilled( false ) |
557 | { | 557 | { |
558 | } | 558 | } |
559 | 559 | ||
560 | HashProxy( MyType &h, uint32_t nPos, value *pValue ) : | 560 | HashProxy( MyType &h, uint32_t nPos, value *pValue ) : |
561 | hsh( h ), | 561 | hsh( h ), |
562 | nPos( nPos ), | 562 | nPos( nPos ), |
563 | pValue( pValue ), | 563 | pValue( pValue ), |
564 | bFilled( true ) | 564 | bFilled( true ) |
565 | { | 565 | { |
566 | } | 566 | } |
567 | 567 | ||
568 | MyType &hsh; | 568 | MyType &hsh; |
569 | const key *pKey; | 569 | const key *pKey; |
570 | uint32_t nPos; | 570 | uint32_t nPos; |
571 | value *pValue; | 571 | value *pValue; |
572 | uint32_t hash; | 572 | uint32_t hash; |
573 | bool bFilled; | 573 | bool bFilled; |
574 | 574 | ||
575 | public: | 575 | public: |
576 | /** | 576 | /** |
577 | * Cast operator for HashProxy. | 577 | * Cast operator for HashProxy. |
578 | *@returns (value_type &) The value the HashProxy is pointing to. | 578 | *@returns (value_type &) The value the HashProxy is pointing to. |
579 | */ | 579 | */ |
580 | operator value &() | 580 | operator value &() |
581 | { | 581 | { |
582 | if( bFilled == false ) | 582 | if( bFilled == false ) |
583 | throw HashException( | 583 | throw HashException( |
584 | excodeNotFilled, | 584 | excodeNotFilled, |
585 | "No data associated with that key." | 585 | "No data associated with that key." |
586 | ); | 586 | ); |
587 | return *pValue; | 587 | return *pValue; |
588 | } | 588 | } |
589 | 589 | ||
590 | /** | 590 | /** |
591 | * Direct function for retrieving a value out of the HashProxy. | 591 | * Direct function for retrieving a value out of the HashProxy. |
592 | *@returns (value_type &) The value pointed to by this HashProxy. | 592 | *@returns (value_type &) The value pointed to by this HashProxy. |
593 | */ | 593 | */ |
594 | value &getValue() | 594 | value &getValue() |
595 | { | 595 | { |
596 | if( bFilled == false ) | 596 | if( bFilled == false ) |
597 | throw HashException( | 597 | throw HashException( |
598 | excodeNotFilled, | 598 | excodeNotFilled, |
599 | "No data associated with that key." | 599 | "No data associated with that key." |
600 | ); | 600 | ); |
601 | return *pValue; | 601 | return *pValue; |
602 | } | 602 | } |
603 | 603 | ||
604 | /** | 604 | /** |
605 | * Whether this HashProxy points to something real or not. | 605 | * Whether this HashProxy points to something real or not. |
606 | */ | 606 | */ |
607 | bool isFilled() | 607 | bool isFilled() |
608 | { | 608 | { |
609 | return bFilled; | 609 | return bFilled; |
610 | } | 610 | } |
611 | 611 | ||
612 | /** | 612 | /** |
613 | * Erase the data pointed to by this HashProxy. | 613 | * Erase the data pointed to by this HashProxy. |
614 | */ | 614 | */ |
615 | void erase() | 615 | void erase() |
616 | { | 616 | { |
617 | if( bFilled ) | 617 | if( bFilled ) |
618 | { | 618 | { |
619 | hsh.core->_erase( nPos ); | 619 | hsh.core->_erase( nPos ); |
620 | } | 620 | } |
621 | } | 621 | } |
622 | 622 | ||
623 | /** | 623 | /** |
624 | * Assign data to this point in the hash table. | 624 | * Assign data to this point in the hash table. |
625 | *@param nval (value_type) the data to assign. | 625 | *@param nval (value_type) the data to assign. |
626 | */ | 626 | */ |
627 | value operator=( value nval ) | 627 | value operator=( value nval ) |
628 | { | 628 | { |
629 | if( bFilled ) | 629 | if( bFilled ) |
630 | { | 630 | { |
631 | hsh.core->va.destroy( &hsh.core->aValues[nPos] ); | 631 | hsh.core->va.destroy( &hsh.core->aValues[nPos] ); |
632 | hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); | 632 | hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); |
633 | } | 633 | } |
634 | else | 634 | else |
635 | { | 635 | { |
636 | hsh.core->fill( nPos, *pKey, nval, hash ); | 636 | hsh.core->fill( nPos, *pKey, nval, hash ); |
637 | } | 637 | } |
638 | 638 | ||
639 | return nval; | 639 | return nval; |
640 | } | 640 | } |
641 | 641 | ||
642 | /** | 642 | /** |
643 | * Pointer extraction operator. Access to members of data pointed to | 643 | * Pointer extraction operator. Access to members of data pointed to |
644 | * by HashProxy. | 644 | * by HashProxy. |
645 | *@returns (value_type *) | 645 | *@returns (value_type *) |
646 | */ | 646 | */ |
647 | value *operator->() | 647 | value *operator->() |
648 | { | 648 | { |
649 | if( bFilled == false ) | 649 | if( bFilled == false ) |
650 | throw HashException( | 650 | throw HashException( |
651 | excodeNotFilled, | 651 | excodeNotFilled, |
652 | "No data associated with that key." | 652 | "No data associated with that key." |
653 | ); | 653 | ); |
654 | return pValue; | 654 | return pValue; |
655 | } | 655 | } |
656 | }; | 656 | }; |
657 | 657 | ||
658 | /** | 658 | /** |
659 | * Hash table index operator | 659 | * Hash table index operator |
660 | *@param k (key_type) Key of data to be retrieved. | 660 | *@param k (key_type) Key of data to be retrieved. |
661 | *@returns (HashProxy) Proxy pointing to the data. | 661 | *@returns (HashProxy) Proxy pointing to the data. |
662 | */ | 662 | */ |
663 | HashProxy operator[]( const key &k ) | 663 | HashProxy operator[]( const key &k ) |
664 | { | 664 | { |
665 | _hardCopy(); | 665 | _hardCopy(); |
666 | 666 | ||
667 | uint32_t hash = __calcHashCode( k ); | 667 | uint32_t hash = __calcHashCode( k ); |
668 | bool bFill; | 668 | bool bFill; |
669 | uint32_t nPos = core->probe( hash, k, bFill ); | 669 | uint32_t nPos = core->probe( hash, k, bFill ); |
670 | 670 | ||
671 | if( bFill ) | 671 | if( bFill ) |
672 | { | 672 | { |
673 | return HashProxy( *this, nPos, &core->aValues[nPos] ); | 673 | return HashProxy( *this, nPos, &core->aValues[nPos] ); |
674 | } | 674 | } |
675 | else | 675 | else |
676 | { | 676 | { |
677 | return HashProxy( *this, &k, nPos, hash ); | 677 | return HashProxy( *this, &k, nPos, hash ); |
678 | } | 678 | } |
679 | } | 679 | } |
680 | 680 | ||
681 | /** | 681 | /** |
682 | * Insert a value (v) under key (k) into the hash table | 682 | * Insert a value (v) under key (k) into the hash table |
683 | *@param k (key_type) Key to list the value under. | 683 | *@param k (key_type) Key to list the value under. |
684 | *@param v (value_type) Value to store in the hash table. | 684 | *@param v (value_type) Value to store in the hash table. |
685 | */ | 685 | */ |
686 | void insert( const key &k, const value &v ) | 686 | void insert( const key &k, const value &v ) |
687 | { | 687 | { |
688 | _hardCopy(); | 688 | _hardCopy(); |
689 | 689 | ||
690 | core->insert( k, v ); | 690 | core->insert( k, v ); |
691 | } | 691 | } |
692 | 692 | ||
693 | /** | 693 | /** |
694 | * Remove a value from the hash table. | 694 | * Remove a value from the hash table. |
695 | *@param k (key_type) The data under this key will be erased. | 695 | *@param k (key_type) The data under this key will be erased. |
696 | */ | 696 | */ |
697 | void erase( const key &k ) | 697 | void erase( const key &k ) |
698 | { | 698 | { |
699 | _hardCopy(); | 699 | _hardCopy(); |
700 | 700 | ||
701 | uint32_t hash = __calcHashCode( k ); | 701 | uint32_t hash = __calcHashCode( k ); |
702 | bool bFill; | 702 | bool bFill; |
703 | uint32_t nPos = core->probe( hash, k, bFill ); | 703 | uint32_t nPos = core->probe( hash, k, bFill ); |
704 | 704 | ||
705 | if( bFill ) | 705 | if( bFill ) |
706 | { | 706 | { |
707 | core->_erase( nPos ); | 707 | core->_erase( nPos ); |
708 | } | 708 | } |
709 | } | 709 | } |
710 | 710 | ||
711 | struct iterator; | 711 | struct iterator; |
712 | 712 | ||
713 | /** | 713 | /** |
714 | * Remove a value from the hash pointed to from an iterator. | 714 | * Remove a value from the hash pointed to from an iterator. |
715 | *@param i (iterator &) The data to be erased. | 715 | *@param i (iterator &) The data to be erased. |
716 | */ | 716 | */ |
717 | void erase( struct iterator &i ) | 717 | void erase( struct iterator &i ) |
718 | { | 718 | { |
719 | if( this != i.hsh ) | 719 | if( this != i.hsh ) |
720 | throw HashException("This iterator didn't come from this Hash."); | 720 | throw HashException("This iterator didn't come from this Hash."); |
721 | 721 | ||
722 | _hardCopy(); | 722 | _hardCopy(); |
723 | 723 | ||
724 | if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) | 724 | if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) |
725 | { | 725 | { |
726 | core->_erase( i.nPos ); | 726 | core->_erase( i.nPos ); |
727 | } | 727 | } |
728 | } | 728 | } |
729 | 729 | ||
730 | /** | 730 | /** |
731 | * Remove all data from the hash table. | 731 | * Remove all data from the hash table. |
732 | */ | 732 | */ |
733 | virtual void clear() | 733 | virtual void clear() |
734 | { | 734 | { |
735 | _resetCore(); | 735 | _resetCore(); |
736 | } | 736 | } |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * Get an item of data from the hash table. | 739 | * Get an item of data from the hash table. |
740 | *@param k (key_type) Key pointing to the data to be retrieved. | 740 | *@param k (key_type) Key pointing to the data to be retrieved. |
741 | *@returns (value_type &) The data pointed to by (k). | 741 | *@returns (value_type &) The data pointed to by (k). |
742 | */ | 742 | */ |
743 | value &get( const key &k ) | 743 | value &get( const key &k ) |
744 | { | 744 | { |
745 | _hardCopy(); | 745 | _hardCopy(); |
746 | 746 | ||
747 | uint32_t hash = __calcHashCode( k ); | 747 | uint32_t hash = __calcHashCode( k ); |
748 | bool bFill; | 748 | bool bFill; |
749 | uint32_t nPos = core->probe( hash, k, bFill, false ); | 749 | uint32_t nPos = core->probe( hash, k, bFill, false ); |
750 | 750 | ||
751 | if( bFill ) | 751 | if( bFill ) |
752 | { | 752 | { |
753 | return core->aValues[nPos]; | 753 | return core->aValues[nPos]; |
754 | } | 754 | } |
755 | else | 755 | else |
756 | { | 756 | { |
757 | throw HashException( | 757 | throw HashException( |
758 | excodeNotFilled, | 758 | excodeNotFilled, |
759 | "No data associated with that key." | 759 | "No data associated with that key." |
760 | ); | 760 | ); |
761 | } | 761 | } |
762 | } | 762 | } |
763 | 763 | ||
764 | /** | 764 | /** |
765 | * Get a const item of data from the hash table. | 765 | * Get a const item of data from the hash table. |
766 | *@param k (key_type) Key pointing to the data to be retrieved. | 766 | *@param k (key_type) Key pointing to the data to be retrieved. |
767 | *@returns (const value_type &) A const version of the data pointed | 767 | *@returns (const value_type &) A const version of the data pointed |
768 | * to by (k). | 768 | * to by (k). |
769 | */ | 769 | */ |
770 | const value &get( const key &k ) const | 770 | const value &get( const key &k ) const |
771 | { | 771 | { |
772 | uint32_t hash = __calcHashCode( k ); | 772 | uint32_t hash = __calcHashCode( k ); |
773 | bool bFill; | 773 | bool bFill; |
774 | uint32_t nPos = core->probe( hash, k, bFill ); | 774 | uint32_t nPos = core->probe( hash, k, bFill ); |
775 | 775 | ||
776 | if( bFill ) | 776 | if( bFill ) |
777 | { | 777 | { |
778 | return core->aValues[nPos]; | 778 | return core->aValues[nPos]; |
779 | } | 779 | } |
780 | else | 780 | else |
781 | { | 781 | { |
782 | throw HashException( | 782 | throw HashException( |
783 | excodeNotFilled, | 783 | excodeNotFilled, |
784 | "No data associated with that key." | 784 | "No data associated with that key." |
785 | ); | 785 | ); |
786 | } | 786 | } |
787 | } | 787 | } |
788 | 788 | ||
789 | /** | 789 | /** |
790 | * Does the hash table contain an item under key (k). | 790 | * Does the hash table contain an item under key (k). |
791 | *@param k (key_type) The key to check. | 791 | *@param k (key_type) The key to check. |
792 | *@returns (bool) Whether there was an item in the hash under key (k). | 792 | *@returns (bool) Whether there was an item in the hash under key (k). |
793 | */ | 793 | */ |
794 | bool has( const key &k ) const | 794 | bool has( const key &k ) const |
795 | { | 795 | { |
796 | bool bFill; | 796 | bool bFill; |
797 | core->probe( __calcHashCode( k ), k, bFill ); | 797 | core->probe( __calcHashCode( k ), k, bFill ); |
798 | 798 | ||
799 | return bFill; | 799 | return bFill; |
800 | } | 800 | } |
801 | 801 | ||
802 | /** | 802 | /** |
803 | * Iteration structure for iterating through the hash. | 803 | * Iteration structure for iterating through the hash. |
804 | */ | 804 | */ |
805 | typedef struct iterator | 805 | typedef struct iterator |
806 | { | 806 | { |
807 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 807 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
808 | private: | 808 | private: |
809 | iterator( MyType *hsh ) : | 809 | iterator( MyType *hsh ) : |
810 | hsh( hsh ), | 810 | hsh( hsh ), |
811 | nPos( 0 ), | 811 | nPos( 0 ), |
812 | bFinished( false ) | 812 | bFinished( false ) |
813 | { | 813 | { |
814 | nPos = hsh->core->getFirstPos( bFinished ); | 814 | nPos = hsh->core->getFirstPos( bFinished ); |
815 | } | 815 | } |
816 | 816 | ||
817 | iterator( MyType *hsh, bool bDone ) : | 817 | iterator( MyType *hsh, bool bDone ) : |
818 | hsh( hsh ), | 818 | hsh( hsh ), |
819 | nPos( 0 ), | 819 | nPos( 0 ), |
820 | bFinished( bDone ) | 820 | bFinished( bDone ) |
821 | { | 821 | { |
822 | } | 822 | } |
823 | 823 | ||
824 | MyType *hsh; | 824 | MyType *hsh; |
825 | uint32_t nPos; | 825 | uint32_t nPos; |
826 | bool bFinished; | 826 | bool bFinished; |
827 | 827 | ||
828 | public: | 828 | public: |
829 | iterator( const iterator &i ) : | 829 | iterator( const iterator &i ) : |
830 | hsh( i.hsh ), | 830 | hsh( i.hsh ), |
831 | nPos( i.nPos ), | 831 | nPos( i.nPos ), |
832 | bFinished( i.bFinished ) | 832 | bFinished( i.bFinished ) |
833 | { | 833 | { |
834 | } | 834 | } |
835 | 835 | ||
836 | iterator() : | 836 | iterator() : |
837 | hsh( NULL ), | 837 | hsh( NULL ), |
838 | nPos( NULL ), | 838 | nPos( NULL ), |
839 | bFinished( true ) | 839 | bFinished( true ) |
840 | { | 840 | { |
841 | } | 841 | } |
842 | 842 | ||
843 | bool isValid() const | 843 | bool isValid() const |
844 | { | 844 | { |
845 | return !bFinished; | 845 | return !bFinished; |
846 | } | 846 | } |
847 | 847 | ||
848 | operator bool() const | 848 | operator bool() const |
849 | { | 849 | { |
850 | return !bFinished; | 850 | return !bFinished; |
851 | } | 851 | } |
852 | 852 | ||
853 | /** | 853 | /** |
854 | * Iterator incrementation operator. Move the iterator forward. | 854 | * Iterator incrementation operator. Move the iterator forward. |
855 | */ | 855 | */ |
856 | iterator operator++( int ) | 856 | iterator operator++( int ) |
857 | { | 857 | { |
858 | if( bFinished == false ) | 858 | if( bFinished == false ) |
859 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 859 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
860 | 860 | ||
861 | return *this; | 861 | return *this; |
862 | } | 862 | } |
863 | 863 | ||
864 | /** | 864 | /** |
865 | * Iterator incrementation operator. Move the iterator forward. | 865 | * Iterator incrementation operator. Move the iterator forward. |
866 | */ | 866 | */ |
867 | iterator operator++() | 867 | iterator operator++() |
868 | { | 868 | { |
869 | if( bFinished == false ) | 869 | if( bFinished == false ) |
870 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 870 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
871 | 871 | ||
872 | return *this; | 872 | return *this; |
873 | } | 873 | } |
874 | 874 | ||
875 | /** | 875 | /** |
876 | * Iterator equality comparison operator. Iterators the same? | 876 | * Iterator equality comparison operator. Iterators the same? |
877 | */ | 877 | */ |
878 | bool operator==( const iterator &oth ) const | 878 | bool operator==( const iterator &oth ) const |
879 | { | 879 | { |
880 | if( bFinished != oth.bFinished ) | 880 | if( bFinished != oth.bFinished ) |
881 | return false; | 881 | return false; |
882 | if( bFinished == true ) | 882 | if( bFinished == true ) |
883 | { | 883 | { |
884 | return true; | 884 | return true; |
885 | } | 885 | } |
886 | else | 886 | else |
887 | { | 887 | { |
888 | if( oth.nPos == nPos ) | 888 | if( oth.nPos == nPos ) |
889 | return true; | 889 | return true; |
890 | return false; | 890 | return false; |
891 | } | 891 | } |
892 | } | 892 | } |
893 | 893 | ||
894 | /** | 894 | /** |
895 | * Iterator not equality comparison operator. Not the same? | 895 | * Iterator not equality comparison operator. Not the same? |
896 | */ | 896 | */ |
897 | bool operator!=( const iterator &oth ) const | 897 | bool operator!=( const iterator &oth ) const |
898 | { | 898 | { |
899 | return !(*this == oth ); | 899 | return !(*this == oth ); |
900 | } | 900 | } |
901 | 901 | ||
902 | /** | 902 | /** |
903 | * Iterator assignment operator. | 903 | * Iterator assignment operator. |
904 | */ | 904 | */ |
905 | iterator operator=( const iterator &oth ) | 905 | iterator operator=( const iterator &oth ) |
906 | { | 906 | { |
907 | hsh = oth.hsh; | 907 | hsh = oth.hsh; |
908 | nPos = oth.nPos; | 908 | nPos = oth.nPos; |
909 | bFinished = oth.bFinished; | 909 | bFinished = oth.bFinished; |
910 | return *this; | 910 | return *this; |
911 | } | 911 | } |
912 | 912 | ||
913 | /** | 913 | /** |
914 | * Iterator dereference operator... err.. get the value | 914 | * Iterator dereference operator... err.. get the value |
915 | *@returns (value_type &) The value behind this iterator. | 915 | *@returns (value_type &) The value behind this iterator. |
916 | */ | 916 | */ |
917 | value &operator *() | 917 | value &operator *() |
918 | { | 918 | { |
919 | hsh->_hardCopy(); | 919 | hsh->_hardCopy(); |
920 | return hsh->core->getValueAtPos( nPos ); | 920 | return hsh->core->getValueAtPos( nPos ); |
921 | } | 921 | } |
922 | 922 | ||
923 | const value &operator *() const | 923 | const value &operator *() const |
924 | { | 924 | { |
925 | return hsh->core->getValueAtPos( nPos ); | 925 | return hsh->core->getValueAtPos( nPos ); |
926 | } | 926 | } |
927 | 927 | ||
928 | /** | 928 | /** |
929 | * Get the key behind this iterator. | 929 | * Get the key behind this iterator. |
930 | *@returns (key_type &) The key behind this iterator. | 930 | *@returns (key_type &) The key behind this iterator. |
931 | */ | 931 | */ |
932 | const key &getKey() const | 932 | const key &getKey() const |
933 | { | 933 | { |
934 | return hsh->core->getKeyAtPos( nPos ); | 934 | return hsh->core->getKeyAtPos( nPos ); |
935 | } | 935 | } |
936 | 936 | ||
937 | /** | 937 | /** |
938 | * Get the value behind this iterator. | 938 | * Get the value behind this iterator. |
939 | *@returns (value_type &) The value behind this iterator. | 939 | *@returns (value_type &) The value behind this iterator. |
940 | */ | 940 | */ |
941 | value &getValue() | 941 | value &getValue() |
942 | { | 942 | { |
943 | hsh->_hardCopy(); | 943 | hsh->_hardCopy(); |
944 | return hsh->core->getValueAtPos( nPos ); | 944 | return hsh->core->getValueAtPos( nPos ); |
945 | } | 945 | } |
946 | 946 | ||
947 | /** | 947 | /** |
948 | * Get the value behind this iterator. | 948 | * Get the value behind this iterator. |
949 | *@returns (value_type &) The value behind this iterator. | 949 | *@returns (value_type &) The value behind this iterator. |
950 | */ | 950 | */ |
951 | const value &getValue() const | 951 | const value &getValue() const |
952 | { | 952 | { |
953 | return hsh->core->getValueAtPos( nPos ); | 953 | return hsh->core->getValueAtPos( nPos ); |
954 | } | 954 | } |
955 | } iterator; | 955 | } iterator; |
956 | 956 | ||
957 | /** | 957 | /** |
958 | * Iteration structure for iterating through the hash (const). | 958 | * Iteration structure for iterating through the hash (const). |
959 | */ | 959 | */ |
960 | typedef struct const_iterator | 960 | typedef struct const_iterator |
961 | { | 961 | { |
962 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 962 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
963 | private: | 963 | private: |
964 | const_iterator( const MyType *hsh ) : | 964 | const_iterator( const MyType *hsh ) : |
965 | hsh( hsh ), | 965 | hsh( hsh ), |
966 | nPos( 0 ), | 966 | nPos( 0 ), |
967 | bFinished( false ) | 967 | bFinished( false ) |
968 | { | 968 | { |
969 | nPos = hsh->core->getFirstPos( bFinished ); | 969 | nPos = hsh->core->getFirstPos( bFinished ); |
970 | } | 970 | } |
971 | 971 | ||
972 | const_iterator( const MyType *hsh, bool bDone ) : | 972 | const_iterator( const MyType *hsh, bool bDone ) : |
973 | hsh( hsh ), | 973 | hsh( hsh ), |
974 | nPos( 0 ), | 974 | nPos( 0 ), |
975 | bFinished( bDone ) | 975 | bFinished( bDone ) |
976 | { | 976 | { |
977 | } | 977 | } |
978 | 978 | ||
979 | const MyType *hsh; | 979 | const MyType *hsh; |
980 | uint32_t nPos; | 980 | uint32_t nPos; |
981 | bool bFinished; | 981 | bool bFinished; |
982 | 982 | ||
983 | public: | 983 | public: |
984 | const_iterator() : | 984 | const_iterator() : |
985 | hsh( NULL ), | 985 | hsh( NULL ), |
986 | nPos( 0 ), | 986 | nPos( 0 ), |
987 | bFinished( true ) | 987 | bFinished( true ) |
988 | { | 988 | { |
989 | } | 989 | } |
990 | 990 | ||
991 | const_iterator( const const_iterator &src ) : | 991 | const_iterator( const const_iterator &src ) : |
992 | hsh( src.hsh ), | 992 | hsh( src.hsh ), |
993 | nPos( src.nPos ), | 993 | nPos( src.nPos ), |
994 | bFinished( src.bFinished ) | 994 | bFinished( src.bFinished ) |
995 | { | 995 | { |
996 | } | 996 | } |
997 | 997 | ||
998 | const_iterator( const iterator &src ) : | 998 | const_iterator( const iterator &src ) : |
999 | hsh( src.hsh ), | 999 | hsh( src.hsh ), |
1000 | nPos( src.nPos ), | 1000 | nPos( src.nPos ), |
1001 | bFinished( src.bFinished ) | 1001 | bFinished( src.bFinished ) |
1002 | { | 1002 | { |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | bool isValid() const | 1005 | bool isValid() const |
1006 | { | 1006 | { |
1007 | return !bFinished; | 1007 | return !bFinished; |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | operator bool() const | 1010 | operator bool() const |
1011 | { | 1011 | { |
1012 | return !bFinished; | 1012 | return !bFinished; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | /** | 1015 | /** |
1016 | * Iterator incrementation operator. Move the iterator forward. | 1016 | * Iterator incrementation operator. Move the iterator forward. |
1017 | */ | 1017 | */ |
1018 | const_iterator operator++( int ) | 1018 | const_iterator operator++( int ) |
1019 | { | 1019 | { |
1020 | if( bFinished == false ) | 1020 | if( bFinished == false ) |
1021 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 1021 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
1022 | 1022 | ||
1023 | return *this; | 1023 | return *this; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | /** | 1026 | /** |
1027 | * Iterator incrementation operator. Move the iterator forward. | 1027 | * Iterator incrementation operator. Move the iterator forward. |
1028 | */ | 1028 | */ |
1029 | const_iterator operator++() | 1029 | const_iterator operator++() |
1030 | { | 1030 | { |
1031 | if( bFinished == false ) | 1031 | if( bFinished == false ) |
1032 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 1032 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
1033 | 1033 | ||
1034 | return *this; | 1034 | return *this; |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | /** | 1037 | /** |
1038 | * Iterator equality comparison operator. Iterators the same? | 1038 | * Iterator equality comparison operator. Iterators the same? |
1039 | */ | 1039 | */ |
1040 | bool operator==( const const_iterator &oth ) const | 1040 | bool operator==( const const_iterator &oth ) const |
1041 | { | 1041 | { |
1042 | if( bFinished != oth.bFinished ) | 1042 | if( bFinished != oth.bFinished ) |
1043 | return false; | 1043 | return false; |
1044 | if( bFinished == true ) | 1044 | if( bFinished == true ) |
1045 | { | 1045 | { |
1046 | return true; | 1046 | return true; |
1047 | } | 1047 | } |
1048 | else | 1048 | else |
1049 | { | 1049 | { |
1050 | if( oth.nPos == nPos ) | 1050 | if( oth.nPos == nPos ) |
1051 | return true; | 1051 | return true; |
1052 | return false; | 1052 | return false; |
1053 | } | 1053 | } |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | /** | 1056 | /** |
1057 | * Iterator not equality comparison operator. Not the same? | 1057 | * Iterator not equality comparison operator. Not the same? |
1058 | */ | 1058 | */ |
1059 | bool operator!=( const const_iterator &oth ) const | 1059 | bool operator!=( const const_iterator &oth ) const |
1060 | { | 1060 | { |
1061 | return !(*this == oth ); | 1061 | return !(*this == oth ); |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | /** | 1064 | /** |
1065 | * Iterator assignment operator. | 1065 | * Iterator assignment operator. |
1066 | */ | 1066 | */ |
1067 | const_iterator operator=( const const_iterator &oth ) | 1067 | const_iterator operator=( const const_iterator &oth ) |
1068 | { | 1068 | { |
1069 | hsh = oth.hsh; | 1069 | hsh = oth.hsh; |
1070 | nPos = oth.nPos; | 1070 | nPos = oth.nPos; |
1071 | bFinished = oth.bFinished; | 1071 | bFinished = oth.bFinished; |
1072 | return *this; | 1072 | return *this; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | /** | 1075 | /** |
1076 | * Iterator dereference operator... err.. get the value | 1076 | * Iterator dereference operator... err.. get the value |
1077 | *@returns (value_type &) The value behind this iterator. | 1077 | *@returns (value_type &) The value behind this iterator. |
1078 | */ | 1078 | */ |
1079 | const value &operator *() const | 1079 | const value &operator *() const |
1080 | { | 1080 | { |
1081 | return hsh->core->getValueAtPos( nPos ); | 1081 | return hsh->core->getValueAtPos( nPos ); |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | /** | 1084 | /** |
1085 | * Get the key behind this iterator. | 1085 | * Get the key behind this iterator. |
1086 | *@returns (key_type &) The key behind this iterator. | 1086 | *@returns (key_type &) The key behind this iterator. |
1087 | */ | 1087 | */ |
1088 | const key &getKey() const | 1088 | const key &getKey() const |
1089 | { | 1089 | { |
1090 | return hsh->core->getKeyAtPos( nPos ); | 1090 | return hsh->core->getKeyAtPos( nPos ); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /** | 1093 | /** |
1094 | * Get the value behind this iterator. | 1094 | * Get the value behind this iterator. |
1095 | *@returns (value_type &) The value behind this iterator. | 1095 | *@returns (value_type &) The value behind this iterator. |
1096 | */ | 1096 | */ |
1097 | const value &getValue() const | 1097 | const value &getValue() const |
1098 | { | 1098 | { |
1099 | return hsh->core->getValueAtPos( nPos ); | 1099 | return hsh->core->getValueAtPos( nPos ); |
1100 | } | 1100 | } |
1101 | } const_iterator; | 1101 | } const_iterator; |
1102 | 1102 | ||
1103 | /** | 1103 | /** |
1104 | * Get an iterator pointing to the first item in the hash table. | 1104 | * Get an iterator pointing to the first item in the hash table. |
1105 | *@returns (iterator) An iterator pointing to the first item in the | 1105 | *@returns (iterator) An iterator pointing to the first item in the |
1106 | * hash table. | 1106 | * hash table. |
1107 | */ | 1107 | */ |
1108 | iterator begin() | 1108 | iterator begin() |
1109 | { | 1109 | { |
1110 | return iterator( this ); | 1110 | return iterator( this ); |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | const_iterator begin() const | 1113 | const_iterator begin() const |
1114 | { | 1114 | { |
1115 | return const_iterator( this ); | 1115 | return const_iterator( this ); |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /** | 1118 | /** |
1119 | * Get an iterator pointing to a point just past the last item in the | 1119 | * Get an iterator pointing to a point just past the last item in the |
1120 | * hash table. | 1120 | * hash table. |
1121 | *@returns (iterator) An iterator pointing to a point just past the | 1121 | *@returns (iterator) An iterator pointing to a point just past the |
1122 | * last item in the hash table. | 1122 | * last item in the hash table. |
1123 | */ | 1123 | */ |
1124 | iterator end() | 1124 | iterator end() |
1125 | { | 1125 | { |
1126 | return iterator( this, true ); | 1126 | return iterator( this, true ); |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | const_iterator end() const | 1129 | const_iterator end() const |
1130 | { | 1130 | { |
1131 | return const_iterator( this, true ); | 1131 | return const_iterator( this, true ); |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | /** | 1134 | /** |
1135 | * Get a list of all the keys in the hash table. | 1135 | * Get a list of all the keys in the hash table. |
1136 | *@returns (std::list<key_type>) The list of keys in the hash table. | 1136 | *@returns (std::list<key_type>) The list of keys in the hash table. |
1137 | */ | 1137 | */ |
1138 | Bu::List<key> getKeys() const | 1138 | Bu::List<key> getKeys() const |
1139 | { | 1139 | { |
1140 | Bu::List<key> lKeys; | 1140 | Bu::List<key> lKeys; |
1141 | 1141 | ||
1142 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1142 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1143 | { | 1143 | { |
1144 | if( core->isFilled( j ) ) | 1144 | if( core->isFilled( j ) ) |
1145 | { | 1145 | { |
1146 | if( !core->isDeleted( j ) ) | 1146 | if( !core->isDeleted( j ) ) |
1147 | { | 1147 | { |
1148 | lKeys.append( core->aKeys[j] ); | 1148 | lKeys.append( core->aKeys[j] ); |
1149 | } | 1149 | } |
1150 | } | 1150 | } |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | return lKeys; | 1153 | return lKeys; |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | Bu::List<value> getValues() const | 1156 | Bu::List<value> getValues() const |
1157 | { | 1157 | { |
1158 | Bu::List<value> lValues; | 1158 | Bu::List<value> lValues; |
1159 | 1159 | ||
1160 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1160 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1161 | { | 1161 | { |
1162 | if( core->isFilled( j ) ) | 1162 | if( core->isFilled( j ) ) |
1163 | { | 1163 | { |
1164 | if( !core->isDeleted( j ) ) | 1164 | if( !core->isDeleted( j ) ) |
1165 | { | 1165 | { |
1166 | lValues.append( core->aValues[j] ); | 1166 | lValues.append( core->aValues[j] ); |
1167 | } | 1167 | } |
1168 | } | 1168 | } |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | return lValues; | 1171 | return lValues; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | bool operator==( const MyType &rhs ) const | 1174 | bool operator==( const MyType &rhs ) const |
1175 | { | 1175 | { |
1176 | if( this == &rhs ) | 1176 | if( this == &rhs ) |
1177 | return true; | 1177 | return true; |
1178 | if( core == rhs.core ) | 1178 | if( core == rhs.core ) |
1179 | return true; | 1179 | return true; |
1180 | if( core == NULL || rhs.core == NULL ) | 1180 | if( core == NULL || rhs.core == NULL ) |
1181 | return false; | 1181 | return false; |
1182 | if( getSize() != rhs.getSize() ) | 1182 | if( getSize() != rhs.getSize() ) |
1183 | return false; | 1183 | return false; |
1184 | 1184 | ||
1185 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1185 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1186 | { | 1186 | { |
1187 | if( core->isFilled( j ) ) | 1187 | if( core->isFilled( j ) ) |
1188 | { | 1188 | { |
1189 | if( !core->isDeleted( j ) ) | 1189 | if( !core->isDeleted( j ) ) |
1190 | { | 1190 | { |
1191 | // Check to see if this key is in the other hash | 1191 | // Check to see if this key is in the other hash |
1192 | if( rhs.has( core->aKeys[j] ) ) | 1192 | if( rhs.has( core->aKeys[j] ) ) |
1193 | { | 1193 | { |
1194 | if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) | 1194 | if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) |
1195 | { | 1195 | { |
1196 | return false; | 1196 | return false; |
1197 | } | 1197 | } |
1198 | } | 1198 | } |
1199 | else | 1199 | else |
1200 | { | 1200 | { |
1201 | return false; | 1201 | return false; |
1202 | } | 1202 | } |
1203 | } | 1203 | } |
1204 | } | 1204 | } |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | return true; | 1207 | return true; |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | bool operator!=( const MyType &rhs ) const | 1210 | bool operator!=( const MyType &rhs ) const |
1211 | { | 1211 | { |
1212 | return !(*this == rhs); | 1212 | return !(*this == rhs); |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | MyType &operator+=( const MyType &rhs ) | 1215 | MyType &operator+=( const MyType &rhs ) |
1216 | { | 1216 | { |
1217 | if( this == &rhs ) | 1217 | if( this == &rhs ) |
1218 | return *this; | 1218 | return *this; |
1219 | if( core == rhs.core ) | 1219 | if( core == rhs.core ) |
1220 | return *this; | 1220 | return *this; |
1221 | if( core == NULL || rhs.core == NULL ) | 1221 | if( core == NULL || rhs.core == NULL ) |
1222 | return *this; | 1222 | return *this; |
1223 | 1223 | ||
1224 | for( const_iterator i = rhs.begin(); i; i++ ) | 1224 | for( const_iterator i = rhs.begin(); i; i++ ) |
1225 | insert( i.getKey(), i.getValue() ); | 1225 | insert( i.getKey(), i.getValue() ); |
1226 | 1226 | ||
1227 | return *this; | 1227 | return *this; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | protected: | 1230 | protected: |
1231 | virtual Core *_copyCore( Core *src ) | 1231 | virtual Core *_copyCore( Core *src ) |
1232 | { | 1232 | { |
1233 | Core *pRet = _allocateCore(); | 1233 | Core *pRet = _allocateCore(); |
1234 | 1234 | ||
1235 | pRet->nFilled = 0; | 1235 | pRet->nFilled = 0; |
1236 | pRet->nDeleted = 0; | 1236 | pRet->nDeleted = 0; |
1237 | pRet->nCapacity = src->nCapacity; | 1237 | pRet->nCapacity = src->nCapacity; |
1238 | pRet->nKeysSize = bitsTo<uint32_t>( pRet->nCapacity ); | 1238 | pRet->nKeysSize = bitsTo<uint32_t>( pRet->nCapacity ); |
1239 | pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); | 1239 | pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); |
1240 | pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); | 1240 | pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); |
1241 | pRet->clearBits(); | 1241 | pRet->clearBits(); |
1242 | 1242 | ||
1243 | pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); | 1243 | pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); |
1244 | pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); | 1244 | pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); |
1245 | pRet->aValues = pRet->va.allocate( pRet->nCapacity ); | 1245 | pRet->aValues = pRet->va.allocate( pRet->nCapacity ); |
1246 | 1246 | ||
1247 | for( uint32_t j = 0; j < src->nCapacity; j++ ) | 1247 | for( uint32_t j = 0; j < src->nCapacity; j++ ) |
1248 | { | 1248 | { |
1249 | if( src->isFilled( j ) && !src->isDeleted( j ) ) | 1249 | if( src->isFilled( j ) && !src->isDeleted( j ) ) |
1250 | { | 1250 | { |
1251 | pRet->insert( src->aKeys[j], src->aValues[j] ); | 1251 | pRet->insert( src->aKeys[j], src->aValues[j] ); |
1252 | } | 1252 | } |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | return pRet; | 1255 | return pRet; |
1256 | } | 1256 | } |
1257 | }; | 1257 | }; |
1258 | 1258 | ||
1259 | template<typename T> uint32_t __calcHashCode( const T &k ) | 1259 | template<typename T> uint32_t __calcHashCode( const T &k ) |
1260 | { | 1260 | { |
1261 | return static_cast<uint32_t>( k ); | 1261 | return static_cast<uint32_t>( k ); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | template<typename T> bool __cmpHashKeys( const T &a, const T &b ) | 1264 | template<typename T> bool __cmpHashKeys( const T &a, const T &b ) |
1265 | { | 1265 | { |
1266 | return (a == b); | 1266 | return (a == b); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); | 1269 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); |
1270 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); | 1270 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); |
1271 | 1271 | ||
1272 | template<> uint32_t __calcHashCode<char *>( char * const &k ); | 1272 | template<> uint32_t __calcHashCode<char *>( char * const &k ); |
1273 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); | 1273 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); |
1274 | 1274 | ||
1275 | class Formatter; | 1275 | class Formatter; |
1276 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 1276 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
1277 | Formatter &operator<<( Formatter &rOut, signed char c ); | 1277 | Formatter &operator<<( Formatter &rOut, signed char c ); |
1278 | template<typename key, typename value> | 1278 | template<typename key, typename value> |
1279 | Formatter &operator<<( Formatter &f, const Bu::Hash<key, value> &l ) | 1279 | Formatter &operator<<( Formatter &f, const Bu::Hash<key, value> &l ) |
1280 | { | 1280 | { |
1281 | f << '{'; | 1281 | f << '{'; |
1282 | for( typename Bu::Hash<key,value>::const_iterator i = l.begin(); i; i++ ) | 1282 | for( typename Bu::Hash<key,value>::const_iterator i = l.begin(); i; i++ ) |
1283 | { | 1283 | { |
1284 | if( i != l.begin() ) | 1284 | if( i != l.begin() ) |
1285 | f << ", "; | 1285 | f << ", "; |
1286 | f << i.getKey() << ": " << i.getValue(); | 1286 | f << i.getKey() << ": " << i.getValue(); |
1287 | } | 1287 | } |
1288 | f << '}'; | 1288 | f << '}'; |
1289 | 1289 | ||
1290 | return f; | 1290 | return f; |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | template<typename key, typename value, typename a, typename b, | 1293 | template<typename key, typename value, typename a, typename b, |
1294 | typename c, typename d> | 1294 | typename c, typename d> |
1295 | ArchiveBase &operator<<( ArchiveBase &ar, const Hash<key,value,a,b,c,d> &h ) | 1295 | ArchiveBase &operator<<( ArchiveBase &ar, const Hash<key,value,a,b,c,d> &h ) |
1296 | { | 1296 | { |
1297 | long iSize = h.getSize(); | 1297 | long iSize = h.getSize(); |
1298 | ar << iSize; | 1298 | ar << iSize; |
1299 | for( typename Hash<key,value,a,b,c,d>::const_iterator i = h.begin(); i != h.end(); i++ ) | 1299 | for( typename Hash<key,value,a,b,c,d>::const_iterator i = h.begin(); i != h.end(); i++ ) |
1300 | { | 1300 | { |
1301 | ar << (i.getKey()); | 1301 | ar << (i.getKey()); |
1302 | ar << (i.getValue()); | 1302 | ar << (i.getValue()); |
1303 | } | 1303 | } |
1304 | 1304 | ||
1305 | return ar; | 1305 | return ar; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | template<typename key, typename value, typename a, typename b, | 1308 | template<typename key, typename value, typename a, typename b, |
1309 | typename c, typename d> | 1309 | typename c, typename d> |
1310 | ArchiveBase &operator>>( ArchiveBase &ar, Hash<key,value,a,b,c,d> &h ) | 1310 | ArchiveBase &operator>>( ArchiveBase &ar, Hash<key,value,a,b,c,d> &h ) |
1311 | { | 1311 | { |
1312 | h.clear(); | 1312 | h.clear(); |
1313 | long nSize; | 1313 | long nSize; |
1314 | ar >> nSize; | 1314 | ar >> nSize; |
1315 | 1315 | ||
1316 | for( long j = 0; j < nSize; j++ ) | 1316 | for( long j = 0; j < nSize; j++ ) |
1317 | { | 1317 | { |
1318 | key k; value v; | 1318 | key k; value v; |
1319 | ar >> k >> v; | 1319 | ar >> k >> v; |
1320 | h.insert( k, v ); | 1320 | h.insert( k, v ); |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | return ar; | 1323 | return ar; |
1324 | } | 1324 | } |
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | #endif | 1327 | #endif |
diff --git a/src/stable/heap.h b/src/stable/heap.h index a813f92..5033618 100644 --- a/src/stable/heap.h +++ b/src/stable/heap.h | |||
@@ -17,596 +17,596 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( HeapException ); | 20 | subExceptionDecl( HeapException ); |
21 | 21 | ||
22 | template<typename item, typename cmpfunc, typename itemalloc> | 22 | template<typename item, typename cmpfunc, typename itemalloc> |
23 | class Heap; | 23 | class Heap; |
24 | 24 | ||
25 | /** @cond DEVEL */ | 25 | /** @cond DEVEL */ |
26 | template<typename item, typename cmpfunc, typename itemalloc> | 26 | template<typename item, typename cmpfunc, typename itemalloc> |
27 | class HeapCore | 27 | class HeapCore |
28 | { | 28 | { |
29 | friend class Heap<item, cmpfunc, itemalloc>; | 29 | friend class Heap<item, cmpfunc, itemalloc>; |
30 | friend class SharedCore< | 30 | friend class SharedCore< |
31 | Heap<item, cmpfunc, itemalloc>, HeapCore<item, cmpfunc, itemalloc> | 31 | Heap<item, cmpfunc, itemalloc>, HeapCore<item, cmpfunc, itemalloc> |
32 | >; | 32 | >; |
33 | private: | 33 | private: |
34 | HeapCore() : | 34 | HeapCore() : |
35 | iSize( 0 ), | 35 | iSize( 0 ), |
36 | iFill( 0 ), | 36 | iFill( 0 ), |
37 | aItem( NULL ) | 37 | aItem( NULL ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | virtual ~HeapCore() | 41 | virtual ~HeapCore() |
42 | { | 42 | { |
43 | clear(); | 43 | clear(); |
44 | } | 44 | } |
45 | 45 | ||
46 | void init() | 46 | void init() |
47 | { | 47 | { |
48 | if( iSize > 0 ) | 48 | if( iSize > 0 ) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | iSize = 7; | 51 | iSize = 7; |
52 | iFill = 0; | 52 | iFill = 0; |
53 | aItem = ia.allocate( iSize ); | 53 | aItem = ia.allocate( iSize ); |
54 | } | 54 | } |
55 | 55 | ||
56 | void init( int iCap ) | 56 | void init( int iCap ) |
57 | { | 57 | { |
58 | if( iSize > 0 ) | 58 | if( iSize > 0 ) |
59 | return; | 59 | return; |
60 | 60 | ||
61 | for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } | 61 | for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } |
62 | iFill = 0; | 62 | iFill = 0; |
63 | aItem = ia.allocate( iSize ); | 63 | aItem = ia.allocate( iSize ); |
64 | } | 64 | } |
65 | 65 | ||
66 | void clear() | 66 | void clear() |
67 | { | 67 | { |
68 | if( iSize == 0 ) | 68 | if( iSize == 0 ) |
69 | return; | 69 | return; |
70 | 70 | ||
71 | for( int j = 0; j < iFill; j++ ) | 71 | for( int j = 0; j < iFill; j++ ) |
72 | ia.destroy( &aItem[j] ); | 72 | ia.destroy( &aItem[j] ); |
73 | ia.deallocate( aItem, iSize ); | 73 | ia.deallocate( aItem, iSize ); |
74 | aItem = NULL; | 74 | aItem = NULL; |
75 | iSize = 0; | 75 | iSize = 0; |
76 | iFill = 0; | 76 | iFill = 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | void upSize() | 79 | void upSize() |
80 | { | 80 | { |
81 | if( iSize == 0 ) | 81 | if( iSize == 0 ) |
82 | { | 82 | { |
83 | init(); | 83 | init(); |
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | item *aNewItems = ia.allocate( iSize*2+1 ); | 87 | item *aNewItems = ia.allocate( iSize*2+1 ); |
88 | // | 88 | // |
89 | // We cannot use a memcopy here because we don't know what kind | 89 | // We cannot use a memcopy here because we don't know what kind |
90 | // of datastructures are being used, we have to copy them one at | 90 | // of datastructures are being used, we have to copy them one at |
91 | // a time. | 91 | // a time. |
92 | // | 92 | // |
93 | for( int j = 0; j < iFill; j++ ) | 93 | for( int j = 0; j < iFill; j++ ) |
94 | { | 94 | { |
95 | ia.construct( &aNewItems[j], aItem[j] ); | 95 | ia.construct( &aNewItems[j], aItem[j] ); |
96 | ia.destroy( &aItem[j] ); | 96 | ia.destroy( &aItem[j] ); |
97 | } | 97 | } |
98 | ia.deallocate( aItem, iSize ); | 98 | ia.deallocate( aItem, iSize ); |
99 | aItem = aNewItems; | 99 | aItem = aNewItems; |
100 | iSize = iSize*2+1; | 100 | iSize = iSize*2+1; |
101 | } | 101 | } |
102 | 102 | ||
103 | virtual void enqueue( const item &it ) | 103 | virtual void enqueue( const item &it ) |
104 | { | 104 | { |
105 | item i = it; // TODO: This is a silly workaround, put the i item | 105 | item i = it; // TODO: This is a silly workaround, put the i item |
106 | // at the end. | 106 | // at the end. |
107 | if( iFill+1 >= iSize ) | 107 | if( iFill+1 >= iSize ) |
108 | upSize(); | 108 | upSize(); |
109 | 109 | ||
110 | for( int j = 0; j < iFill; ) | 110 | for( int j = 0; j < iFill; ) |
111 | { | 111 | { |
112 | if( cmp( i, aItem[j] ) ) | 112 | if( cmp( i, aItem[j] ) ) |
113 | { | 113 | { |
114 | Bu::swap( i, aItem[j] ); | 114 | Bu::swap( i, aItem[j] ); |
115 | } | 115 | } |
116 | 116 | ||
117 | if( j*2+1 >= iFill ) | 117 | if( j*2+1 >= iFill ) |
118 | break; | 118 | break; |
119 | if( cmp( i, aItem[j*2+1] ) ) | 119 | if( cmp( i, aItem[j*2+1] ) ) |
120 | { | 120 | { |
121 | j = j*2+1; | 121 | j = j*2+1; |
122 | } | 122 | } |
123 | else | 123 | else |
124 | { | 124 | { |
125 | j = j*2+2; | 125 | j = j*2+2; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | ia.construct( &aItem[iFill], i ); | 128 | ia.construct( &aItem[iFill], i ); |
129 | if( iFill > 0 ) | 129 | if( iFill > 0 ) |
130 | { | 130 | { |
131 | for( int j = iFill; j >= 0; ) | 131 | for( int j = iFill; j >= 0; ) |
132 | { | 132 | { |
133 | int k = (j-1)/2; | 133 | int k = (j-1)/2; |
134 | if( j == k ) | 134 | if( j == k ) |
135 | break; | 135 | break; |
136 | if( cmp( aItem[k], aItem[j] ) ) | 136 | if( cmp( aItem[k], aItem[j] ) ) |
137 | break; | 137 | break; |
138 | 138 | ||
139 | Bu::swap( aItem[k], aItem[j] ); | 139 | Bu::swap( aItem[k], aItem[j] ); |
140 | j = k; | 140 | j = k; |
141 | } | 141 | } |
142 | } | 142 | } |
143 | iFill++; | 143 | iFill++; |
144 | } | 144 | } |
145 | 145 | ||
146 | virtual item dequeue() | 146 | virtual item dequeue() |
147 | { | 147 | { |
148 | if( iFill == 0 ) | 148 | if( iFill == 0 ) |
149 | throw HeapException("Heap empty."); | 149 | throw HeapException("Heap empty."); |
150 | item iRet = aItem[0]; | 150 | item iRet = aItem[0]; |
151 | int j; | 151 | int j; |
152 | for( j = 0; j < iFill; ) | 152 | for( j = 0; j < iFill; ) |
153 | { | 153 | { |
154 | int k = j*2+1; | 154 | int k = j*2+1; |
155 | if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) | 155 | if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) |
156 | { | 156 | { |
157 | if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) | 157 | if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) |
158 | break; | 158 | break; |
159 | aItem[j] = aItem[k+1]; | 159 | aItem[j] = aItem[k+1]; |
160 | j = k+1; | 160 | j = k+1; |
161 | } | 161 | } |
162 | else if( k < iFill ) | 162 | else if( k < iFill ) |
163 | { | 163 | { |
164 | if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) | 164 | if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) |
165 | break; | 165 | break; |
166 | aItem[j] = aItem[k]; | 166 | aItem[j] = aItem[k]; |
167 | j = k; | 167 | j = k; |
168 | } | 168 | } |
169 | else | 169 | else |
170 | break; | 170 | break; |
171 | } | 171 | } |
172 | if( j < iFill-1 ) | 172 | if( j < iFill-1 ) |
173 | aItem[j] = aItem[iFill-1]; | 173 | aItem[j] = aItem[iFill-1]; |
174 | ia.destroy( &aItem[iFill-1] ); | 174 | ia.destroy( &aItem[iFill-1] ); |
175 | iFill--; | 175 | iFill--; |
176 | 176 | ||
177 | return iRet; | 177 | return iRet; |
178 | } | 178 | } |
179 | 179 | ||
180 | private: | 180 | private: |
181 | int iSize; | 181 | int iSize; |
182 | int iFill; | 182 | int iFill; |
183 | item *aItem; | 183 | item *aItem; |
184 | cmpfunc cmp; | 184 | cmpfunc cmp; |
185 | itemalloc ia; | 185 | itemalloc ia; |
186 | }; | 186 | }; |
187 | /** @endcond */ | 187 | /** @endcond */ |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * A priority queue that allows for an unlimited number of priorities. All | 190 | * A priority queue that allows for an unlimited number of priorities. All |
191 | * objects enqueued must support less-than-comparison. Then every time an | 191 | * objects enqueued must support less-than-comparison. Then every time an |
192 | * item is dequeued it is always the least item in the heap. The heap | 192 | * item is dequeued it is always the least item in the heap. The heap |
193 | * operates using a binary tree for storage, which allows most operations | 193 | * operates using a binary tree for storage, which allows most operations |
194 | * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins | 194 | * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins |
195 | * whereas peeking is constant time. | 195 | * whereas peeking is constant time. |
196 | * | 196 | * |
197 | * This heap implementation allows iterating, however please note that any | 197 | * This heap implementation allows iterating, however please note that any |
198 | * enqueue or dequeue operation will invalidate the iterator and make it | 198 | * enqueue or dequeue operation will invalidate the iterator and make it |
199 | * unusable (if it still works, you shouldn't trust the results). Also, | 199 | * unusable (if it still works, you shouldn't trust the results). Also, |
200 | * the items are not stored in memory in order, they are optomized into a | 200 | * the items are not stored in memory in order, they are optomized into a |
201 | * tree. This means that the items will be in effectively random order | 201 | * tree. This means that the items will be in effectively random order |
202 | * while iterating through them, and the order cannot be trusted. Also, | 202 | * while iterating through them, and the order cannot be trusted. Also, |
203 | * modifying an item in the heap will not cause that item to be re-sorted. | 203 | * modifying an item in the heap will not cause that item to be re-sorted. |
204 | * If you want to change the position of an item in the heap you will have | 204 | * If you want to change the position of an item in the heap you will have |
205 | * to dequeue every item before it, dequeue that item, change it, and | 205 | * to dequeue every item before it, dequeue that item, change it, and |
206 | * re-enqueue all of the items removed. | 206 | * re-enqueue all of the items removed. |
207 | */ | 207 | */ |
208 | template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> > | 208 | template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> > |
209 | class Heap : public Queue<item>, public SharedCore< | 209 | class Heap : public Queue<item>, public SharedCore< |
210 | Heap<item, cmpfunc, itemalloc>, | 210 | Heap<item, cmpfunc, itemalloc>, |
211 | HeapCore<item, cmpfunc, itemalloc> | 211 | HeapCore<item, cmpfunc, itemalloc> |
212 | > | 212 | > |
213 | { | 213 | { |
214 | private: | 214 | private: |
215 | typedef class Heap<item,cmpfunc,itemalloc> MyType; | 215 | typedef class Heap<item,cmpfunc,itemalloc> MyType; |
216 | typedef class HeapCore<item,cmpfunc,itemalloc> Core; | 216 | typedef class HeapCore<item,cmpfunc,itemalloc> Core; |
217 | 217 | ||
218 | protected: | 218 | protected: |
219 | using SharedCore<MyType, Core>::core; | 219 | using SharedCore<MyType, Core>::core; |
220 | using SharedCore<MyType, Core>::_hardCopy; | 220 | using SharedCore<MyType, Core>::_hardCopy; |
221 | using SharedCore<MyType, Core>::_resetCore; | 221 | using SharedCore<MyType, Core>::_resetCore; |
222 | using SharedCore<MyType, Core>::_allocateCore; | 222 | using SharedCore<MyType, Core>::_allocateCore; |
223 | 223 | ||
224 | public: | 224 | public: |
225 | Heap() | 225 | Heap() |
226 | { | 226 | { |
227 | } | 227 | } |
228 | 228 | ||
229 | Heap( cmpfunc cmpin ) | 229 | Heap( cmpfunc cmpin ) |
230 | { | 230 | { |
231 | core->cmp = cmpin; | 231 | core->cmp = cmpin; |
232 | } | 232 | } |
233 | 233 | ||
234 | Heap( int iInitialCapacity ) | 234 | Heap( int iInitialCapacity ) |
235 | { | 235 | { |
236 | core->init( iInitialCapacity ); | 236 | core->init( iInitialCapacity ); |
237 | } | 237 | } |
238 | 238 | ||
239 | Heap( cmpfunc cmpin, int iInitialCapacity ) | 239 | Heap( cmpfunc cmpin, int iInitialCapacity ) |
240 | { | 240 | { |
241 | core->cmp = cmpin; | 241 | core->cmp = cmpin; |
242 | core->init( iInitialCapacity ); | 242 | core->init( iInitialCapacity ); |
243 | } | 243 | } |
244 | 244 | ||
245 | Heap( const MyType &rSrc ) : | 245 | Heap( const MyType &rSrc ) : |
246 | SharedCore<MyType, Core>( rSrc ) | 246 | SharedCore<MyType, Core>( rSrc ) |
247 | { | 247 | { |
248 | } | 248 | } |
249 | 249 | ||
250 | virtual ~Heap() | 250 | virtual ~Heap() |
251 | { | 251 | { |
252 | } | 252 | } |
253 | 253 | ||
254 | virtual void enqueue( const item &it ) | 254 | virtual void enqueue( const item &it ) |
255 | { | 255 | { |
256 | _hardCopy(); | 256 | _hardCopy(); |
257 | 257 | ||
258 | core->enqueue( it ); | 258 | core->enqueue( it ); |
259 | } | 259 | } |
260 | 260 | ||
261 | virtual item &peek() | 261 | virtual item &peek() |
262 | { | 262 | { |
263 | _hardCopy(); | 263 | _hardCopy(); |
264 | 264 | ||
265 | if( core->iFill == 0 ) | 265 | if( core->iFill == 0 ) |
266 | throw HeapException("Heap empty."); | 266 | throw HeapException("Heap empty."); |
267 | return core->aItem[0]; | 267 | return core->aItem[0]; |
268 | } | 268 | } |
269 | 269 | ||
270 | virtual const item &peek() const | 270 | virtual const item &peek() const |
271 | { | 271 | { |
272 | if( core->iFill == 0 ) | 272 | if( core->iFill == 0 ) |
273 | throw HeapException("Heap empty."); | 273 | throw HeapException("Heap empty."); |
274 | return core->aItem[0]; | 274 | return core->aItem[0]; |
275 | } | 275 | } |
276 | 276 | ||
277 | virtual item dequeue() | 277 | virtual item dequeue() |
278 | { | 278 | { |
279 | _hardCopy(); | 279 | _hardCopy(); |
280 | 280 | ||
281 | return core->dequeue(); | 281 | return core->dequeue(); |
282 | } | 282 | } |
283 | 283 | ||
284 | virtual bool isEmpty() const | 284 | virtual bool isEmpty() const |
285 | { | 285 | { |
286 | return (core->iFill==0); | 286 | return (core->iFill==0); |
287 | } | 287 | } |
288 | 288 | ||
289 | virtual int getSize() const | 289 | virtual int getSize() const |
290 | { | 290 | { |
291 | return core->iFill; | 291 | return core->iFill; |
292 | } | 292 | } |
293 | 293 | ||
294 | class iterator | 294 | class iterator |
295 | { | 295 | { |
296 | friend class const_iterator; | 296 | friend class const_iterator; |
297 | friend class Heap<item, cmpfunc, itemalloc>; | 297 | friend class Heap<item, cmpfunc, itemalloc>; |
298 | private: | 298 | private: |
299 | Heap<item, cmpfunc, itemalloc> *pHeap; | 299 | Heap<item, cmpfunc, itemalloc> *pHeap; |
300 | int iIndex; | 300 | int iIndex; |
301 | 301 | ||
302 | iterator( Heap<item, cmpfunc, itemalloc> *pHeap, int iIndex ) : | 302 | iterator( Heap<item, cmpfunc, itemalloc> *pHeap, int iIndex ) : |
303 | pHeap( pHeap ), iIndex( iIndex ) | 303 | pHeap( pHeap ), iIndex( iIndex ) |
304 | { | 304 | { |
305 | } | 305 | } |
306 | 306 | ||
307 | void checkValid() | 307 | void checkValid() |
308 | { | 308 | { |
309 | if( pHeap == NULL ) | 309 | if( pHeap == NULL ) |
310 | throw Bu::ExceptionBase("Iterator not initialized."); | 310 | throw Bu::ExceptionBase("Iterator not initialized."); |
311 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) | 311 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) |
312 | throw Bu::ExceptionBase("Iterator out of bounds."); | 312 | throw Bu::ExceptionBase("Iterator out of bounds."); |
313 | } | 313 | } |
314 | 314 | ||
315 | public: | 315 | public: |
316 | iterator() : | 316 | iterator() : |
317 | pHeap( NULL ), | 317 | pHeap( NULL ), |
318 | iIndex( -1 ) | 318 | iIndex( -1 ) |
319 | { | 319 | { |
320 | } | 320 | } |
321 | 321 | ||
322 | iterator( const iterator &i ) : | 322 | iterator( const iterator &i ) : |
323 | pHeap( i.pHeap ), | 323 | pHeap( i.pHeap ), |
324 | iIndex( i.iIndex ) | 324 | iIndex( i.iIndex ) |
325 | { | 325 | { |
326 | } | 326 | } |
327 | 327 | ||
328 | bool operator==( const iterator &oth ) const | 328 | bool operator==( const iterator &oth ) const |
329 | { | 329 | { |
330 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); | 330 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); |
331 | } | 331 | } |
332 | 332 | ||
333 | bool operator!=( const iterator &oth ) const | 333 | bool operator!=( const iterator &oth ) const |
334 | { | 334 | { |
335 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); | 335 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); |
336 | } | 336 | } |
337 | 337 | ||
338 | item &operator*() | 338 | item &operator*() |
339 | { | 339 | { |
340 | pHeap->_hardCopy(); | 340 | pHeap->_hardCopy(); |
341 | 341 | ||
342 | return pHeap->core->aItem[iIndex]; | 342 | return pHeap->core->aItem[iIndex]; |
343 | } | 343 | } |
344 | 344 | ||
345 | item *operator->() | 345 | item *operator->() |
346 | { | 346 | { |
347 | pHeap->_hardCopy(); | 347 | pHeap->_hardCopy(); |
348 | 348 | ||
349 | return &(pHeap->core->aItem[iIndex]); | 349 | return &(pHeap->core->aItem[iIndex]); |
350 | } | 350 | } |
351 | 351 | ||
352 | iterator &operator++() | 352 | iterator &operator++() |
353 | { | 353 | { |
354 | checkValid(); | 354 | checkValid(); |
355 | iIndex++; | 355 | iIndex++; |
356 | if( iIndex >= pHeap->iFill ) | 356 | if( iIndex >= pHeap->iFill ) |
357 | iIndex = -1; | 357 | iIndex = -1; |
358 | 358 | ||
359 | return *this; | 359 | return *this; |
360 | } | 360 | } |
361 | 361 | ||
362 | iterator &operator--() | 362 | iterator &operator--() |
363 | { | 363 | { |
364 | checkValid(); | 364 | checkValid(); |
365 | iIndex--; | 365 | iIndex--; |
366 | 366 | ||
367 | return *this; | 367 | return *this; |
368 | } | 368 | } |
369 | 369 | ||
370 | iterator &operator++( int ) | 370 | iterator &operator++( int ) |
371 | { | 371 | { |
372 | checkValid(); | 372 | checkValid(); |
373 | iIndex++; | 373 | iIndex++; |
374 | if( iIndex >= pHeap->core->iFill ) | 374 | if( iIndex >= pHeap->core->iFill ) |
375 | iIndex = -1; | 375 | iIndex = -1; |
376 | 376 | ||
377 | return *this; | 377 | return *this; |
378 | } | 378 | } |
379 | 379 | ||
380 | iterator &operator--( int ) | 380 | iterator &operator--( int ) |
381 | { | 381 | { |
382 | checkValid(); | 382 | checkValid(); |
383 | iIndex--; | 383 | iIndex--; |
384 | 384 | ||
385 | return *this; | 385 | return *this; |
386 | } | 386 | } |
387 | 387 | ||
388 | iterator operator+( int iDelta ) | 388 | iterator operator+( int iDelta ) |
389 | { | 389 | { |
390 | checkValid(); | 390 | checkValid(); |
391 | iterator ret( *this ); | 391 | iterator ret( *this ); |
392 | ret.iIndex += iDelta; | 392 | ret.iIndex += iDelta; |
393 | if( ret.iIndex >= pHeap->core->iFill ) | 393 | if( ret.iIndex >= pHeap->core->iFill ) |
394 | ret.iIndex = -1; | 394 | ret.iIndex = -1; |
395 | return ret; | 395 | return ret; |
396 | } | 396 | } |
397 | 397 | ||
398 | iterator operator-( int iDelta ) | 398 | iterator operator-( int iDelta ) |
399 | { | 399 | { |
400 | checkValid(); | 400 | checkValid(); |
401 | iterator ret( *this ); | 401 | iterator ret( *this ); |
402 | ret.iIndex -= iDelta; | 402 | ret.iIndex -= iDelta; |
403 | if( ret.iIndex < 0 ) | 403 | if( ret.iIndex < 0 ) |
404 | ret.iIndex = -1; | 404 | ret.iIndex = -1; |
405 | return ret; | 405 | return ret; |
406 | } | 406 | } |
407 | 407 | ||
408 | operator bool() const | 408 | operator bool() const |
409 | { | 409 | { |
410 | return iIndex != -1; | 410 | return iIndex != -1; |
411 | } | 411 | } |
412 | 412 | ||
413 | bool isValid() const | 413 | bool isValid() const |
414 | { | 414 | { |
415 | return iIndex != -1; | 415 | return iIndex != -1; |
416 | } | 416 | } |
417 | 417 | ||
418 | iterator &operator=( const iterator &oth ) | 418 | iterator &operator=( const iterator &oth ) |
419 | { | 419 | { |
420 | pHeap = oth.pHeap; | 420 | pHeap = oth.pHeap; |
421 | iIndex = oth.iIndex; | 421 | iIndex = oth.iIndex; |
422 | } | 422 | } |
423 | }; | 423 | }; |
424 | 424 | ||
425 | class const_iterator | 425 | class const_iterator |
426 | { | 426 | { |
427 | friend class Heap<item, cmpfunc, itemalloc>; | 427 | friend class Heap<item, cmpfunc, itemalloc>; |
428 | private: | 428 | private: |
429 | Heap<item, cmpfunc, itemalloc> *pHeap; | 429 | Heap<item, cmpfunc, itemalloc> *pHeap; |
430 | int iIndex; | 430 | int iIndex; |
431 | 431 | ||
432 | const_iterator( Heap<item, cmpfunc, itemalloc> *pHeap, | 432 | const_iterator( Heap<item, cmpfunc, itemalloc> *pHeap, |
433 | int iIndex ) : | 433 | int iIndex ) : |
434 | pHeap( pHeap ), iIndex( iIndex ) | 434 | pHeap( pHeap ), iIndex( iIndex ) |
435 | { | 435 | { |
436 | } | 436 | } |
437 | 437 | ||
438 | void checkValid() | 438 | void checkValid() |
439 | { | 439 | { |
440 | if( pHeap == NULL ) | 440 | if( pHeap == NULL ) |
441 | throw Bu::ExceptionBase("Iterator not initialized."); | 441 | throw Bu::ExceptionBase("Iterator not initialized."); |
442 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) | 442 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) |
443 | throw Bu::ExceptionBase("Iterator out of bounds."); | 443 | throw Bu::ExceptionBase("Iterator out of bounds."); |
444 | } | 444 | } |
445 | 445 | ||
446 | public: | 446 | public: |
447 | const_iterator() : | 447 | const_iterator() : |
448 | pHeap( NULL ), | 448 | pHeap( NULL ), |
449 | iIndex( -1 ) | 449 | iIndex( -1 ) |
450 | { | 450 | { |
451 | } | 451 | } |
452 | 452 | ||
453 | const_iterator( const const_iterator &i ) : | 453 | const_iterator( const const_iterator &i ) : |
454 | pHeap( i.pHeap ), | 454 | pHeap( i.pHeap ), |
455 | iIndex( i.iIndex ) | 455 | iIndex( i.iIndex ) |
456 | { | 456 | { |
457 | } | 457 | } |
458 | 458 | ||
459 | const_iterator( const iterator &i ) : | 459 | const_iterator( const iterator &i ) : |
460 | pHeap( i.pHeap ), | 460 | pHeap( i.pHeap ), |
461 | iIndex( i.iIndex ) | 461 | iIndex( i.iIndex ) |
462 | { | 462 | { |
463 | } | 463 | } |
464 | 464 | ||
465 | bool operator==( const const_iterator &oth ) const | 465 | bool operator==( const const_iterator &oth ) const |
466 | { | 466 | { |
467 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); | 467 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); |
468 | } | 468 | } |
469 | 469 | ||
470 | bool operator!=( const const_iterator &oth ) const | 470 | bool operator!=( const const_iterator &oth ) const |
471 | { | 471 | { |
472 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); | 472 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); |
473 | } | 473 | } |
474 | 474 | ||
475 | const item &operator*() | 475 | const item &operator*() |
476 | { | 476 | { |
477 | pHeap->_hardCopy(); | 477 | pHeap->_hardCopy(); |
478 | 478 | ||
479 | return pHeap->core->aItem[iIndex]; | 479 | return pHeap->core->aItem[iIndex]; |
480 | } | 480 | } |
481 | 481 | ||
482 | const item *operator->() | 482 | const item *operator->() |
483 | { | 483 | { |
484 | pHeap->_hardCopy(); | 484 | pHeap->_hardCopy(); |
485 | 485 | ||
486 | return &(pHeap->core->aItem[iIndex]); | 486 | return &(pHeap->core->aItem[iIndex]); |
487 | } | 487 | } |
488 | 488 | ||
489 | const_iterator &operator++() | 489 | const_iterator &operator++() |
490 | { | 490 | { |
491 | checkValid(); | 491 | checkValid(); |
492 | iIndex++; | 492 | iIndex++; |
493 | if( iIndex >= pHeap->core->iFill ) | 493 | if( iIndex >= pHeap->core->iFill ) |
494 | iIndex = -1; | 494 | iIndex = -1; |
495 | 495 | ||
496 | return *this; | 496 | return *this; |
497 | } | 497 | } |
498 | 498 | ||
499 | const_iterator &operator--() | 499 | const_iterator &operator--() |
500 | { | 500 | { |
501 | checkValid(); | 501 | checkValid(); |
502 | iIndex--; | 502 | iIndex--; |
503 | 503 | ||
504 | return *this; | 504 | return *this; |
505 | } | 505 | } |
506 | 506 | ||
507 | const_iterator &operator++( int ) | 507 | const_iterator &operator++( int ) |
508 | { | 508 | { |
509 | checkValid(); | 509 | checkValid(); |
510 | iIndex++; | 510 | iIndex++; |
511 | if( iIndex >= pHeap->core->iFill ) | 511 | if( iIndex >= pHeap->core->iFill ) |
512 | iIndex = -1; | 512 | iIndex = -1; |
513 | 513 | ||
514 | return *this; | 514 | return *this; |
515 | } | 515 | } |
516 | 516 | ||
517 | const_iterator &operator--( int ) | 517 | const_iterator &operator--( int ) |
518 | { | 518 | { |
519 | checkValid(); | 519 | checkValid(); |
520 | iIndex--; | 520 | iIndex--; |
521 | 521 | ||
522 | return *this; | 522 | return *this; |
523 | } | 523 | } |
524 | 524 | ||
525 | const_iterator operator+( int iDelta ) | 525 | const_iterator operator+( int iDelta ) |
526 | { | 526 | { |
527 | checkValid(); | 527 | checkValid(); |
528 | const_iterator ret( *this ); | 528 | const_iterator ret( *this ); |
529 | ret.iIndex += iDelta; | 529 | ret.iIndex += iDelta; |
530 | if( ret.iIndex >= pHeap->iFill ) | 530 | if( ret.iIndex >= pHeap->iFill ) |
531 | ret.iIndex = -1; | 531 | ret.iIndex = -1; |
532 | return ret; | 532 | return ret; |
533 | } | 533 | } |
534 | 534 | ||
535 | const_iterator operator-( int iDelta ) | 535 | const_iterator operator-( int iDelta ) |
536 | { | 536 | { |
537 | checkValid(); | 537 | checkValid(); |
538 | const_iterator ret( *this ); | 538 | const_iterator ret( *this ); |
539 | ret.iIndex -= iDelta; | 539 | ret.iIndex -= iDelta; |
540 | if( ret.iIndex < 0 ) | 540 | if( ret.iIndex < 0 ) |
541 | ret.iIndex = -1; | 541 | ret.iIndex = -1; |
542 | return ret; | 542 | return ret; |
543 | } | 543 | } |
544 | 544 | ||
545 | operator bool() const | 545 | operator bool() const |
546 | { | 546 | { |
547 | return iIndex != -1; | 547 | return iIndex != -1; |
548 | } | 548 | } |
549 | 549 | ||
550 | bool isValid() const | 550 | bool isValid() const |
551 | { | 551 | { |
552 | return iIndex != -1; | 552 | return iIndex != -1; |
553 | } | 553 | } |
554 | 554 | ||
555 | const_iterator &operator=( const const_iterator &oth ) | 555 | const_iterator &operator=( const const_iterator &oth ) |
556 | { | 556 | { |
557 | pHeap = oth.pHeap; | 557 | pHeap = oth.pHeap; |
558 | iIndex = oth.iIndex; | 558 | iIndex = oth.iIndex; |
559 | } | 559 | } |
560 | 560 | ||
561 | const_iterator &operator=( const iterator &oth ) | 561 | const_iterator &operator=( const iterator &oth ) |
562 | { | 562 | { |
563 | pHeap = oth.pHeap; | 563 | pHeap = oth.pHeap; |
564 | iIndex = oth.iIndex; | 564 | iIndex = oth.iIndex; |
565 | } | 565 | } |
566 | }; | 566 | }; |
567 | 567 | ||
568 | iterator begin() | 568 | iterator begin() |
569 | { | 569 | { |
570 | if( core->iFill == 0 ) | 570 | if( core->iFill == 0 ) |
571 | return end(); | 571 | return end(); |
572 | return iterator( this, 0 ); | 572 | return iterator( this, 0 ); |
573 | } | 573 | } |
574 | 574 | ||
575 | const_iterator begin() const | 575 | const_iterator begin() const |
576 | { | 576 | { |
577 | if( core->iFill == 0 ) | 577 | if( core->iFill == 0 ) |
578 | return end(); | 578 | return end(); |
579 | return const_iterator( this, 0 ); | 579 | return const_iterator( this, 0 ); |
580 | } | 580 | } |
581 | 581 | ||
582 | iterator end() | 582 | iterator end() |
583 | { | 583 | { |
584 | return iterator( this, -1 ); | 584 | return iterator( this, -1 ); |
585 | } | 585 | } |
586 | 586 | ||
587 | const_iterator end() const | 587 | const_iterator end() const |
588 | { | 588 | { |
589 | return const_iterator( this, -1 ); | 589 | return const_iterator( this, -1 ); |
590 | } | 590 | } |
591 | 591 | ||
592 | 592 | ||
593 | protected: | 593 | protected: |
594 | virtual Core *_copyCore( Core *src ) | 594 | virtual Core *_copyCore( Core *src ) |
595 | { | 595 | { |
596 | Core *pRet = _allocateCore(); | 596 | Core *pRet = _allocateCore(); |
597 | 597 | ||
598 | pRet->iSize = src->iSize; | 598 | pRet->iSize = src->iSize; |
599 | pRet->iFill = src->iFill; | 599 | pRet->iFill = src->iFill; |
600 | pRet->cmp = src->cmp; | 600 | pRet->cmp = src->cmp; |
601 | pRet->aItem = pRet->ia.allocate( pRet->iSize ); | 601 | pRet->aItem = pRet->ia.allocate( pRet->iSize ); |
602 | for( int j = 0; j < pRet->iFill; j++ ) | 602 | for( int j = 0; j < pRet->iFill; j++ ) |
603 | { | 603 | { |
604 | pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); | 604 | pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); |
605 | } | 605 | } |
606 | 606 | ||
607 | return pRet; | 607 | return pRet; |
608 | } | 608 | } |
609 | }; | 609 | }; |
610 | }; | 610 | }; |
611 | 611 | ||
612 | #endif | 612 | #endif |
diff --git a/src/stable/hex.cpp b/src/stable/hex.cpp index 3e6a22e..45679b5 100644 --- a/src/stable/hex.cpp +++ b/src/stable/hex.cpp | |||
@@ -8,11 +8,11 @@ | |||
8 | #include "bu/hex.h" | 8 | #include "bu/hex.h" |
9 | 9 | ||
10 | Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : | 10 | Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | iChunk( iChunk ), | 12 | iChunk( iChunk ), |
13 | iPos( 0 ), | 13 | iPos( 0 ), |
14 | iIn( 0 ), | 14 | iIn( 0 ), |
15 | sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") | 15 | sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") |
16 | { | 16 | { |
17 | } | 17 | } |
18 | 18 | ||
@@ -22,48 +22,48 @@ Bu::Hex::~Hex() | |||
22 | 22 | ||
23 | void Bu::Hex::start() | 23 | void Bu::Hex::start() |
24 | { | 24 | { |
25 | iPos = iIn = 0; | 25 | iPos = iIn = 0; |
26 | } | 26 | } |
27 | 27 | ||
28 | Bu::size Bu::Hex::stop() | 28 | Bu::size Bu::Hex::stop() |
29 | { | 29 | { |
30 | return iPos; | 30 | return iPos; |
31 | } | 31 | } |
32 | 32 | ||
33 | Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) | 33 | Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) |
34 | { | 34 | { |
35 | Bu::size j; | 35 | Bu::size j; |
36 | uint8_t *puBuf = (uint8_t *)pBuf; | 36 | uint8_t *puBuf = (uint8_t *)pBuf; |
37 | for( j = 0; j < iBytes; j++ ) | 37 | for( j = 0; j < iBytes; j++ ) |
38 | { | 38 | { |
39 | for(; iIn < 2; iIn++ ) | 39 | for(; iIn < 2; iIn++ ) |
40 | { | 40 | { |
41 | if( rNext.read( &cIn[iIn], 1 ) == 0 ) | 41 | if( rNext.read( &cIn[iIn], 1 ) == 0 ) |
42 | return j; | 42 | return j; |
43 | if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || | 43 | if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || |
44 | cIn[iIn] == '\n' || cIn[iIn] == '\r' ) | 44 | cIn[iIn] == '\n' || cIn[iIn] == '\r' ) |
45 | iIn--; | 45 | iIn--; |
46 | } | 46 | } |
47 | #define chr2nibble( c ) ((c>='0'&&c<='9')?(c-'0'):((c|0x60)-'a'+10)) | 47 | #define chr2nibble( c ) ((c>='0'&&c<='9')?(c-'0'):((c|0x60)-'a'+10)) |
48 | puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); | 48 | puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); |
49 | iIn = 0; | 49 | iIn = 0; |
50 | } | 50 | } |
51 | return j; | 51 | return j; |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) | 54 | Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) |
55 | { | 55 | { |
56 | char cOut[2]; | 56 | char cOut[2]; |
57 | uint8_t *puBuf = (uint8_t *)pBuf; | 57 | uint8_t *puBuf = (uint8_t *)pBuf; |
58 | for( Bu::size j = 0; j < iBytes; j++ ) | 58 | for( Bu::size j = 0; j < iBytes; j++ ) |
59 | { | 59 | { |
60 | cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; | 60 | cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; |
61 | cOut[1] = sChrs[(puBuf[j]&0x0f)]; | 61 | cOut[1] = sChrs[(puBuf[j]&0x0f)]; |
62 | if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) | 62 | if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) |
63 | rNext.write(" ", 1 ); | 63 | rNext.write(" ", 1 ); |
64 | rNext.write( cOut, 2 ); | 64 | rNext.write( cOut, 2 ); |
65 | iPos++; | 65 | iPos++; |
66 | } | 66 | } |
67 | return iBytes; | 67 | return iBytes; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/src/stable/hex.h b/src/stable/hex.h index a89e93d..c010173 100644 --- a/src/stable/hex.h +++ b/src/stable/hex.h | |||
@@ -12,46 +12,46 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * This very simple filter encodes to/decodes from hex encoded string data. | 16 | * This very simple filter encodes to/decodes from hex encoded string data. |
17 | * The primary use of this filter is in debugging, use it with | 17 | * The primary use of this filter is in debugging, use it with |
18 | * Bu::encodeStr to easily create hex dumps of string data, even other raw | 18 | * Bu::encodeStr to easily create hex dumps of string data, even other raw |
19 | * structures. | 19 | * structures. |
20 | * | 20 | * |
21 | *@code | 21 | *@code |
22 | Bu::println("Hexdump: " + Bu::encodeStr<Bu::Hex>("Test data ;)") ); | 22 | Bu::println("Hexdump: " + Bu::encodeStr<Bu::Hex>("Test data ;)") ); |
23 | @endcode | 23 | @endcode |
24 | * Or... | 24 | * Or... |
25 | *@code | 25 | *@code |
26 | complex_struct data; | 26 | complex_struct data; |
27 | ... | 27 | ... |
28 | Bu::println("Hexdump: " + | 28 | Bu::println("Hexdump: " + |
29 | Bu::encodeStr<Bu::Hex>( | 29 | Bu::encodeStr<Bu::Hex>( |
30 | Bu::String( &data, sizeof(data) ) | 30 | Bu::String( &data, sizeof(data) ) |
31 | ) | 31 | ) |
32 | ); | 32 | ); |
33 | @endcode | 33 | @endcode |
34 | **/ | 34 | **/ |
35 | class Hex : public Bu::Filter | 35 | class Hex : public Bu::Filter |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); | 38 | Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); |
39 | virtual ~Hex(); | 39 | virtual ~Hex(); |
40 | 40 | ||
41 | virtual void start(); | 41 | virtual void start(); |
42 | virtual Bu::size stop(); | 42 | virtual Bu::size stop(); |
43 | 43 | ||
44 | virtual Bu::size read( void *pBuf, Bu::size iBytes ); | 44 | virtual Bu::size read( void *pBuf, Bu::size iBytes ); |
45 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ); | 45 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ); |
46 | using Bu::Stream::write; | 46 | using Bu::Stream::write; |
47 | 47 | ||
48 | private: | 48 | private: |
49 | int iChunk; | 49 | int iChunk; |
50 | Bu::size iPos; | 50 | Bu::size iPos; |
51 | char cIn[2]; | 51 | char cIn[2]; |
52 | int iIn; | 52 | int iIn; |
53 | const char *sChrs; | 53 | const char *sChrs; |
54 | }; | 54 | }; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #endif | 57 | #endif |
diff --git a/src/stable/list.h b/src/stable/list.h index 4f9d4aa..b7fb1d1 100644 --- a/src/stable/list.h +++ b/src/stable/list.h | |||
@@ -16,1022 +16,1022 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** @cond DEVEL */ | 19 | /** @cond DEVEL */ |
20 | template<typename value> | 20 | template<typename value> |
21 | struct ListLink | 21 | struct ListLink |
22 | { | 22 | { |
23 | value *pValue; | 23 | value *pValue; |
24 | ListLink *pNext; | 24 | ListLink *pNext; |
25 | ListLink *pPrev; | 25 | ListLink *pPrev; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | template<typename value, typename valuealloc, typename linkalloc> | 28 | template<typename value, typename valuealloc, typename linkalloc> |
29 | class List; | 29 | class List; |
30 | 30 | ||
31 | template<typename value, typename valuealloc, typename linkalloc> | 31 | template<typename value, typename valuealloc, typename linkalloc> |
32 | struct ListCore | 32 | struct ListCore |
33 | { | 33 | { |
34 | friend class List<value, valuealloc, linkalloc>; | 34 | friend class List<value, valuealloc, linkalloc>; |
35 | friend class SharedCore< | 35 | friend class SharedCore< |
36 | List<value, valuealloc, linkalloc>, | 36 | List<value, valuealloc, linkalloc>, |
37 | ListCore<value, valuealloc, linkalloc> | 37 | ListCore<value, valuealloc, linkalloc> |
38 | >; | 38 | >; |
39 | private: | 39 | private: |
40 | typedef struct ListLink<value> Link; | 40 | typedef struct ListLink<value> Link; |
41 | ListCore() : | 41 | ListCore() : |
42 | pFirst( NULL ), | 42 | pFirst( NULL ), |
43 | pLast( NULL ), | 43 | pLast( NULL ), |
44 | nSize( 0 ) | 44 | nSize( 0 ) |
45 | { } | 45 | { } |
46 | 46 | ||
47 | virtual ~ListCore() | 47 | virtual ~ListCore() |
48 | { | 48 | { |
49 | clear(); | 49 | clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | Link *pFirst; | 52 | Link *pFirst; |
53 | Link *pLast; | 53 | Link *pLast; |
54 | long nSize; | 54 | long nSize; |
55 | linkalloc la; | 55 | linkalloc la; |
56 | valuealloc va; | 56 | valuealloc va; |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Append a value to the list. | 59 | * Append a value to the list. |
60 | *@param v (const value_type &) The value to append. | 60 | *@param v (const value_type &) The value to append. |
61 | */ | 61 | */ |
62 | Link *append( const value &v ) | 62 | Link *append( const value &v ) |
63 | { | 63 | { |
64 | Link *pNew = la.allocate( 1 ); | 64 | Link *pNew = la.allocate( 1 ); |
65 | pNew->pValue = va.allocate( 1 ); | 65 | pNew->pValue = va.allocate( 1 ); |
66 | va.construct( pNew->pValue, v ); | 66 | va.construct( pNew->pValue, v ); |
67 | nSize++; | 67 | nSize++; |
68 | if( pFirst == NULL ) | 68 | if( pFirst == NULL ) |
69 | { | 69 | { |
70 | // Empty list | 70 | // Empty list |
71 | pFirst = pLast = pNew; | 71 | pFirst = pLast = pNew; |
72 | pNew->pNext = pNew->pPrev = NULL; | 72 | pNew->pNext = pNew->pPrev = NULL; |
73 | } | 73 | } |
74 | else | 74 | else |
75 | { | 75 | { |
76 | pNew->pNext = NULL; | 76 | pNew->pNext = NULL; |
77 | pNew->pPrev = pLast; | 77 | pNew->pPrev = pLast; |
78 | pLast->pNext = pNew; | 78 | pLast->pNext = pNew; |
79 | pLast = pNew; | 79 | pLast = pNew; |
80 | } | 80 | } |
81 | return pNew; | 81 | return pNew; |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Prepend a value to the list. | 85 | * Prepend a value to the list. |
86 | *@param v (const value_type &) The value to prepend. | 86 | *@param v (const value_type &) The value to prepend. |
87 | */ | 87 | */ |
88 | Link *prepend( const value &v ) | 88 | Link *prepend( const value &v ) |
89 | { | 89 | { |
90 | Link *pNew = la.allocate( 1 ); | 90 | Link *pNew = la.allocate( 1 ); |
91 | pNew->pValue = va.allocate( 1 ); | 91 | pNew->pValue = va.allocate( 1 ); |
92 | va.construct( pNew->pValue, v ); | 92 | va.construct( pNew->pValue, v ); |
93 | nSize++; | 93 | nSize++; |
94 | if( pFirst == NULL ) | 94 | if( pFirst == NULL ) |
95 | { | 95 | { |
96 | // Empty list | 96 | // Empty list |
97 | pFirst = pLast = pNew; | 97 | pFirst = pLast = pNew; |
98 | pNew->pNext = pNew->pPrev = NULL; | 98 | pNew->pNext = pNew->pPrev = NULL; |
99 | } | 99 | } |
100 | else | 100 | else |
101 | { | 101 | { |
102 | pNew->pNext = pFirst; | 102 | pNew->pNext = pFirst; |
103 | pNew->pPrev = NULL; | 103 | pNew->pPrev = NULL; |
104 | pFirst->pPrev = pNew; | 104 | pFirst->pPrev = pNew; |
105 | pFirst = pNew; | 105 | pFirst = pNew; |
106 | } | 106 | } |
107 | return pNew; | 107 | return pNew; |
108 | } | 108 | } |
109 | 109 | ||
110 | void clear() | 110 | void clear() |
111 | { | 111 | { |
112 | Link *pCur = pFirst; | 112 | Link *pCur = pFirst; |
113 | for(;;) | 113 | for(;;) |
114 | { | 114 | { |
115 | if( pCur == NULL ) break; | 115 | if( pCur == NULL ) break; |
116 | va.destroy( pCur->pValue ); | 116 | va.destroy( pCur->pValue ); |
117 | va.deallocate( pCur->pValue, 1 ); | 117 | va.deallocate( pCur->pValue, 1 ); |
118 | Link *pTmp = pCur->pNext; | 118 | Link *pTmp = pCur->pNext; |
119 | la.destroy( pCur ); | 119 | la.destroy( pCur ); |
120 | la.deallocate( pCur, 1 ); | 120 | la.deallocate( pCur, 1 ); |
121 | pCur = pTmp; | 121 | pCur = pTmp; |
122 | } | 122 | } |
123 | pFirst = pLast = NULL; | 123 | pFirst = pLast = NULL; |
124 | nSize = 0; | 124 | nSize = 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | Link *insert( Link *pLink, const value &v ) | 127 | Link *insert( Link *pLink, const value &v ) |
128 | { | 128 | { |
129 | Link *pAfter = pLink; | 129 | Link *pAfter = pLink; |
130 | if( pAfter == NULL ) | 130 | if( pAfter == NULL ) |
131 | { | 131 | { |
132 | return append( v ); | 132 | return append( v ); |
133 | } | 133 | } |
134 | Link *pPrev = pAfter->pPrev; | 134 | Link *pPrev = pAfter->pPrev; |
135 | if( pPrev == NULL ) | 135 | if( pPrev == NULL ) |
136 | { | 136 | { |
137 | return prepend( v ); | 137 | return prepend( v ); |
138 | } | 138 | } |
139 | 139 | ||
140 | Link *pNew = la.allocate( 1 ); | 140 | Link *pNew = la.allocate( 1 ); |
141 | pNew->pValue = va.allocate( 1 ); | 141 | pNew->pValue = va.allocate( 1 ); |
142 | va.construct( pNew->pValue, v ); | 142 | va.construct( pNew->pValue, v ); |
143 | nSize++; | 143 | nSize++; |
144 | 144 | ||
145 | pNew->pNext = pAfter; | 145 | pNew->pNext = pAfter; |
146 | pNew->pPrev = pPrev; | 146 | pNew->pPrev = pPrev; |
147 | pAfter->pPrev = pNew; | 147 | pAfter->pPrev = pNew; |
148 | pPrev->pNext = pNew; | 148 | pPrev->pNext = pNew; |
149 | 149 | ||
150 | return pNew; | 150 | return pNew; |
151 | } | 151 | } |
152 | 152 | ||
153 | /** | 153 | /** |
154 | * Erase an item from the list. | 154 | * Erase an item from the list. |
155 | *@param i (iterator) The item to erase. | 155 | *@param i (iterator) The item to erase. |
156 | */ | 156 | */ |
157 | void erase( Link *pLink ) | 157 | void erase( Link *pLink ) |
158 | { | 158 | { |
159 | Link *pCur = pLink; | 159 | Link *pCur = pLink; |
160 | if( pCur == NULL ) return; | 160 | if( pCur == NULL ) return; |
161 | Link *pPrev = pCur->pPrev; | 161 | Link *pPrev = pCur->pPrev; |
162 | if( pPrev == NULL ) | 162 | if( pPrev == NULL ) |
163 | { | 163 | { |
164 | va.destroy( pCur->pValue ); | 164 | va.destroy( pCur->pValue ); |
165 | va.deallocate( pCur->pValue, 1 ); | 165 | va.deallocate( pCur->pValue, 1 ); |
166 | pFirst = pCur->pNext; | 166 | pFirst = pCur->pNext; |
167 | la.destroy( pCur ); | 167 | la.destroy( pCur ); |
168 | la.deallocate( pCur, 1 ); | 168 | la.deallocate( pCur, 1 ); |
169 | if( pFirst == NULL ) | 169 | if( pFirst == NULL ) |
170 | pLast = NULL; | 170 | pLast = NULL; |
171 | else | 171 | else |
172 | pFirst->pPrev = NULL; | 172 | pFirst->pPrev = NULL; |
173 | nSize--; | 173 | nSize--; |
174 | } | 174 | } |
175 | else | 175 | else |
176 | { | 176 | { |
177 | va.destroy( pCur->pValue ); | 177 | va.destroy( pCur->pValue ); |
178 | va.deallocate( pCur->pValue, 1 ); | 178 | va.deallocate( pCur->pValue, 1 ); |
179 | Link *pTmp = pCur->pNext; | 179 | Link *pTmp = pCur->pNext; |
180 | la.destroy( pCur ); | 180 | la.destroy( pCur ); |
181 | la.deallocate( pCur, 1 ); | 181 | la.deallocate( pCur, 1 ); |
182 | pPrev->pNext = pTmp; | 182 | pPrev->pNext = pTmp; |
183 | if( pTmp != NULL ) | 183 | if( pTmp != NULL ) |
184 | pTmp->pPrev = pPrev; | 184 | pTmp->pPrev = pPrev; |
185 | else | 185 | else |
186 | pLast = pPrev; | 186 | pLast = pPrev; |
187 | nSize--; | 187 | nSize--; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | }; | 190 | }; |
191 | /** @endcond */ | 191 | /** @endcond */ |
192 | 192 | ||
193 | /** | 193 | /** |
194 | * Linked list template container. This class is similar to the stl list | 194 | * Linked list template container. This class is similar to the stl list |
195 | * class except for a few minor changes. First, when const, all | 195 | * class except for a few minor changes. First, when const, all |
196 | * members are only accessable const. Second, erasing a location does not | 196 | * members are only accessable const. Second, erasing a location does not |
197 | * invalidate the iterator used, it simply points to the next valid | 197 | * invalidate the iterator used, it simply points to the next valid |
198 | * location, or end() if there are no more. Other iterators pointing to | 198 | * location, or end() if there are no more. Other iterators pointing to |
199 | * the deleted record will, of course, no longer be valid. | 199 | * the deleted record will, of course, no longer be valid. |
200 | * | 200 | * |
201 | *@param value (typename) The type of data to store in your list | 201 | *@param value (typename) The type of data to store in your list |
202 | *@param valuealloc (typename) Memory Allocator for your value type | 202 | *@param valuealloc (typename) Memory Allocator for your value type |
203 | *@param linkalloc (typename) Memory Allocator for the list links. | 203 | *@param linkalloc (typename) Memory Allocator for the list links. |
204 | *@extends SharedCore | 204 | *@extends SharedCore |
205 | *@ingroup Containers | 205 | *@ingroup Containers |
206 | */ | 206 | */ |
207 | template<typename value, typename valuealloc=std::allocator<value>, | 207 | template<typename value, typename valuealloc=std::allocator<value>, |
208 | typename linkalloc=std::allocator<struct ListLink<value> > > | 208 | typename linkalloc=std::allocator<struct ListLink<value> > > |
209 | class List /** @cond */ : public SharedCore< | 209 | class List /** @cond */ : public SharedCore< |
210 | List<value, valuealloc, linkalloc>, | 210 | List<value, valuealloc, linkalloc>, |
211 | ListCore<value, valuealloc, linkalloc> | 211 | ListCore<value, valuealloc, linkalloc> |
212 | > /** @endcond */ | 212 | > /** @endcond */ |
213 | { | 213 | { |
214 | private: | 214 | private: |
215 | typedef struct ListLink<value> Link; | 215 | typedef struct ListLink<value> Link; |
216 | typedef class List<value, valuealloc, linkalloc> MyType; | 216 | typedef class List<value, valuealloc, linkalloc> MyType; |
217 | typedef struct ListCore<value, valuealloc, linkalloc> Core; | 217 | typedef struct ListCore<value, valuealloc, linkalloc> Core; |
218 | 218 | ||
219 | protected: | 219 | protected: |
220 | using SharedCore<MyType, Core>::core; | 220 | using SharedCore<MyType, Core>::core; |
221 | using SharedCore<MyType, Core>::_hardCopy; | 221 | using SharedCore<MyType, Core>::_hardCopy; |
222 | using SharedCore<MyType, Core>::_allocateCore; | 222 | using SharedCore<MyType, Core>::_allocateCore; |
223 | 223 | ||
224 | public: | 224 | public: |
225 | struct const_iterator; | 225 | struct const_iterator; |
226 | struct iterator; | 226 | struct iterator; |
227 | 227 | ||
228 | List() | 228 | List() |
229 | { | 229 | { |
230 | } | 230 | } |
231 | 231 | ||
232 | List( const MyType &src ) : | 232 | List( const MyType &src ) : |
233 | SharedCore<MyType, Core >( src ) | 233 | SharedCore<MyType, Core >( src ) |
234 | { | 234 | { |
235 | } | 235 | } |
236 | 236 | ||
237 | List( const value &v ) | 237 | List( const value &v ) |
238 | { | 238 | { |
239 | append( v ); | 239 | append( v ); |
240 | } | 240 | } |
241 | 241 | ||
242 | ~List() | 242 | ~List() |
243 | { | 243 | { |
244 | } | 244 | } |
245 | 245 | ||
246 | MyType &operator+=( const value &v ) | 246 | MyType &operator+=( const value &v ) |
247 | { | 247 | { |
248 | _hardCopy(); | 248 | _hardCopy(); |
249 | append( v ); | 249 | append( v ); |
250 | return *this; | 250 | return *this; |
251 | } | 251 | } |
252 | 252 | ||
253 | MyType &operator+=( const MyType &src ) | 253 | MyType &operator+=( const MyType &src ) |
254 | { | 254 | { |
255 | _hardCopy(); | 255 | _hardCopy(); |
256 | append( src ); | 256 | append( src ); |
257 | return *this; | 257 | return *this; |
258 | } | 258 | } |
259 | 259 | ||
260 | MyType operator+( const MyType &src ) | 260 | MyType operator+( const MyType &src ) |
261 | { | 261 | { |
262 | MyType lNew( *this ); | 262 | MyType lNew( *this ); |
263 | lNew += src; | 263 | lNew += src; |
264 | return lNew; | 264 | return lNew; |
265 | } | 265 | } |
266 | 266 | ||
267 | bool operator==( const MyType &rhs ) const | 267 | bool operator==( const MyType &rhs ) const |
268 | { | 268 | { |
269 | if( getSize() != rhs.getSize() ) | 269 | if( getSize() != rhs.getSize() ) |
270 | return false; | 270 | return false; |
271 | 271 | ||
272 | for( typename MyType::const_iterator a = begin(), b = rhs.begin(); | 272 | for( typename MyType::const_iterator a = begin(), b = rhs.begin(); |
273 | a; a++, b++ ) | 273 | a; a++, b++ ) |
274 | { | 274 | { |
275 | if( *a != *b ) | 275 | if( *a != *b ) |
276 | return false; | 276 | return false; |
277 | } | 277 | } |
278 | 278 | ||
279 | return true; | 279 | return true; |
280 | } | 280 | } |
281 | 281 | ||
282 | bool operator!=( const MyType &rhs ) const | 282 | bool operator!=( const MyType &rhs ) const |
283 | { | 283 | { |
284 | return !(*this == rhs); | 284 | return !(*this == rhs); |
285 | } | 285 | } |
286 | 286 | ||
287 | /** | 287 | /** |
288 | * Clear the data from the list. | 288 | * Clear the data from the list. |
289 | */ | 289 | */ |
290 | void clear() | 290 | void clear() |
291 | { | 291 | { |
292 | _hardCopy(); | 292 | _hardCopy(); |
293 | core->clear(); | 293 | core->clear(); |
294 | } | 294 | } |
295 | 295 | ||
296 | MyType &enqueue( const value &v ) | 296 | MyType &enqueue( const value &v ) |
297 | { | 297 | { |
298 | _hardCopy(); | 298 | _hardCopy(); |
299 | append( v ); | 299 | append( v ); |
300 | 300 | ||
301 | return *this; | 301 | return *this; |
302 | } | 302 | } |
303 | 303 | ||
304 | value dequeue() | 304 | value dequeue() |
305 | { | 305 | { |
306 | // _hardCopy(); erase will call this for me | 306 | // _hardCopy(); erase will call this for me |
307 | value v = *core->pFirst->pValue; | 307 | value v = *core->pFirst->pValue; |
308 | 308 | ||
309 | erase( begin() ); | 309 | erase( begin() ); |
310 | 310 | ||
311 | return v; | 311 | return v; |
312 | } | 312 | } |
313 | 313 | ||
314 | MyType &push( const value &v ) | 314 | MyType &push( const value &v ) |
315 | { | 315 | { |
316 | _hardCopy(); | 316 | _hardCopy(); |
317 | prepend( v ); | 317 | prepend( v ); |
318 | 318 | ||
319 | return *this; | 319 | return *this; |
320 | } | 320 | } |
321 | 321 | ||
322 | MyType &pop() | 322 | MyType &pop() |
323 | { | 323 | { |
324 | _hardCopy(); | 324 | _hardCopy(); |
325 | erase( begin() ); | 325 | erase( begin() ); |
326 | 326 | ||
327 | return *this; | 327 | return *this; |
328 | } | 328 | } |
329 | 329 | ||
330 | value peekPop() | 330 | value peekPop() |
331 | { | 331 | { |
332 | value v = first(); | 332 | value v = first(); |
333 | pop(); | 333 | pop(); |
334 | return v; | 334 | return v; |
335 | } | 335 | } |
336 | 336 | ||
337 | value &peek() | 337 | value &peek() |
338 | { | 338 | { |
339 | return first(); | 339 | return first(); |
340 | } | 340 | } |
341 | 341 | ||
342 | /** | 342 | /** |
343 | * Append a value to the list. | 343 | * Append a value to the list. |
344 | *@param v (const value_type &) The value to append. | 344 | *@param v (const value_type &) The value to append. |
345 | */ | 345 | */ |
346 | MyType &append( const value &v ) | 346 | MyType &append( const value &v ) |
347 | { | 347 | { |
348 | _hardCopy(); | 348 | _hardCopy(); |
349 | core->append( v ); | 349 | core->append( v ); |
350 | 350 | ||
351 | return *this; | 351 | return *this; |
352 | } | 352 | } |
353 | 353 | ||
354 | MyType &append( const MyType &rSrc ) | 354 | MyType &append( const MyType &rSrc ) |
355 | { | 355 | { |
356 | _hardCopy(); | 356 | _hardCopy(); |
357 | for( typename MyType::const_iterator i = rSrc.begin(); | 357 | for( typename MyType::const_iterator i = rSrc.begin(); |
358 | i != rSrc.end(); i++ ) | 358 | i != rSrc.end(); i++ ) |
359 | { | 359 | { |
360 | core->append( *i ); | 360 | core->append( *i ); |
361 | } | 361 | } |
362 | 362 | ||
363 | return *this; | 363 | return *this; |
364 | } | 364 | } |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * Prepend a value to the list. | 367 | * Prepend a value to the list. |
368 | *@param v (const value_type &) The value to prepend. | 368 | *@param v (const value_type &) The value to prepend. |
369 | */ | 369 | */ |
370 | MyType &prepend( const value &v ) | 370 | MyType &prepend( const value &v ) |
371 | { | 371 | { |
372 | _hardCopy(); | 372 | _hardCopy(); |
373 | core->prepend( v ); | 373 | core->prepend( v ); |
374 | 374 | ||
375 | return *this; | 375 | return *this; |
376 | } | 376 | } |
377 | 377 | ||
378 | /** | 378 | /** |
379 | * Prepend another list to the front of this one. This will prepend | 379 | * Prepend another list to the front of this one. This will prepend |
380 | * the rSrc list in reverse order...I may fix that later. | 380 | * the rSrc list in reverse order...I may fix that later. |
381 | */ | 381 | */ |
382 | MyType &prepend( const MyType &rSrc ) | 382 | MyType &prepend( const MyType &rSrc ) |
383 | { | 383 | { |
384 | _hardCopy(); | 384 | _hardCopy(); |
385 | for( typename MyType::const_iterator i = rSrc.begin(); | 385 | for( typename MyType::const_iterator i = rSrc.begin(); |
386 | i != rSrc.end(); i++ ) | 386 | i != rSrc.end(); i++ ) |
387 | { | 387 | { |
388 | core->prepend( *i ); | 388 | core->prepend( *i ); |
389 | } | 389 | } |
390 | 390 | ||
391 | return *this; | 391 | return *this; |
392 | } | 392 | } |
393 | 393 | ||
394 | MyType &insert( MyType::iterator &i, const value &v ) | 394 | MyType &insert( MyType::iterator &i, const value &v ) |
395 | { | 395 | { |
396 | _hardCopy(); | 396 | _hardCopy(); |
397 | 397 | ||
398 | core->insert( i.pLink, v ); | 398 | core->insert( i.pLink, v ); |
399 | 399 | ||
400 | return *this; | 400 | return *this; |
401 | } | 401 | } |
402 | 402 | ||
403 | template<typename cmptype> | 403 | template<typename cmptype> |
404 | void sort( cmptype cmp ) | 404 | void sort( cmptype cmp ) |
405 | { | 405 | { |
406 | Heap<value, cmptype, valuealloc> hSort( cmp, getSize() ); | 406 | Heap<value, cmptype, valuealloc> hSort( cmp, getSize() ); |
407 | for( typename MyType::iterator i = begin(); i; i++ ) | 407 | for( typename MyType::iterator i = begin(); i; i++ ) |
408 | { | 408 | { |
409 | hSort.enqueue( *i ); | 409 | hSort.enqueue( *i ); |
410 | } | 410 | } |
411 | clear(); | 411 | clear(); |
412 | while( !hSort.isEmpty() ) | 412 | while( !hSort.isEmpty() ) |
413 | { | 413 | { |
414 | append( hSort.dequeue() ); | 414 | append( hSort.dequeue() ); |
415 | } | 415 | } |
416 | } | 416 | } |
417 | 417 | ||
418 | void sort() | 418 | void sort() |
419 | { | 419 | { |
420 | sort<__basicLTCmp<value> >(); | 420 | sort<__basicLTCmp<value> >(); |
421 | } | 421 | } |
422 | 422 | ||
423 | template<typename cmptype> | 423 | template<typename cmptype> |
424 | void sort() | 424 | void sort() |
425 | { | 425 | { |
426 | Heap<value, cmptype, valuealloc> hSort( getSize() ); | 426 | Heap<value, cmptype, valuealloc> hSort( getSize() ); |
427 | for( typename MyType::iterator i = begin(); i; i++ ) | 427 | for( typename MyType::iterator i = begin(); i; i++ ) |
428 | { | 428 | { |
429 | hSort.enqueue( *i ); | 429 | hSort.enqueue( *i ); |
430 | } | 430 | } |
431 | clear(); | 431 | clear(); |
432 | while( !hSort.isEmpty() ) | 432 | while( !hSort.isEmpty() ) |
433 | { | 433 | { |
434 | append( hSort.dequeue() ); | 434 | append( hSort.dequeue() ); |
435 | } | 435 | } |
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
439 | * Insert a new item in sort order by searching for the first item that | 439 | * Insert a new item in sort order by searching for the first item that |
440 | * is larger and inserting this before it, or at the end if none are | 440 | * is larger and inserting this before it, or at the end if none are |
441 | * larger. If this is the only function used to insert data in the | 441 | * larger. If this is the only function used to insert data in the |
442 | * List all items will be sorted. To use this, the value type must | 442 | * List all items will be sorted. To use this, the value type must |
443 | * support the > operator. | 443 | * support the > operator. |
444 | */ | 444 | */ |
445 | template<typename cmptype> | 445 | template<typename cmptype> |
446 | iterator insertSorted( cmptype cmp, const value &v ) | 446 | iterator insertSorted( cmptype cmp, const value &v ) |
447 | { | 447 | { |
448 | _hardCopy(); | 448 | _hardCopy(); |
449 | if( core->pFirst == NULL ) | 449 | if( core->pFirst == NULL ) |
450 | { | 450 | { |
451 | // Empty list | 451 | // Empty list |
452 | return iterator( core->append( v ) ); | 452 | return iterator( core->append( v ) ); |
453 | } | 453 | } |
454 | else | 454 | else |
455 | { | 455 | { |
456 | Link *pCur = core->pFirst; | 456 | Link *pCur = core->pFirst; |
457 | for(;;) | 457 | for(;;) |
458 | { | 458 | { |
459 | if( cmp( v, *(pCur->pValue)) ) | 459 | if( cmp( v, *(pCur->pValue)) ) |
460 | { | 460 | { |
461 | return iterator( core->insert( pCur, v ) ); | 461 | return iterator( core->insert( pCur, v ) ); |
462 | } | 462 | } |
463 | pCur = pCur->pNext; | 463 | pCur = pCur->pNext; |
464 | if( pCur == NULL ) | 464 | if( pCur == NULL ) |
465 | { | 465 | { |
466 | return iterator( core->append( v ) ); | 466 | return iterator( core->append( v ) ); |
467 | } | 467 | } |
468 | } | 468 | } |
469 | } | 469 | } |
470 | } | 470 | } |
471 | 471 | ||
472 | iterator insertSorted( const value &v ) | 472 | iterator insertSorted( const value &v ) |
473 | { | 473 | { |
474 | return insertSorted<__basicLTCmp<value> >( v ); | 474 | return insertSorted<__basicLTCmp<value> >( v ); |
475 | } | 475 | } |
476 | 476 | ||
477 | template<typename cmptype> | 477 | template<typename cmptype> |
478 | iterator insertSorted( const value &v ) | 478 | iterator insertSorted( const value &v ) |
479 | { | 479 | { |
480 | cmptype cmp; | 480 | cmptype cmp; |
481 | return insertSorted( cmp, v ); | 481 | return insertSorted( cmp, v ); |
482 | } | 482 | } |
483 | 483 | ||
484 | /** | 484 | /** |
485 | * An iterator to iterate through your list. | 485 | * An iterator to iterate through your list. |
486 | */ | 486 | */ |
487 | typedef struct iterator | 487 | typedef struct iterator |
488 | { | 488 | { |
489 | friend struct const_iterator; | 489 | friend struct const_iterator; |
490 | friend class List<value, valuealloc, linkalloc>; | 490 | friend class List<value, valuealloc, linkalloc>; |
491 | private: | 491 | private: |
492 | Link *pLink; | 492 | Link *pLink; |
493 | 493 | ||
494 | iterator( Link *pLink ) : | 494 | iterator( Link *pLink ) : |
495 | pLink( pLink ) | 495 | pLink( pLink ) |
496 | { | 496 | { |
497 | } | 497 | } |
498 | 498 | ||
499 | public: | 499 | public: |
500 | iterator() : | 500 | iterator() : |
501 | pLink( NULL ) | 501 | pLink( NULL ) |
502 | { | 502 | { |
503 | } | 503 | } |
504 | 504 | ||
505 | iterator( const iterator &i ) : | 505 | iterator( const iterator &i ) : |
506 | pLink( i.pLink ) | 506 | pLink( i.pLink ) |
507 | { | 507 | { |
508 | } | 508 | } |
509 | 509 | ||
510 | /** | 510 | /** |
511 | * Equals comparison operator. | 511 | * Equals comparison operator. |
512 | *@param oth (const iterator &) The iterator to compare to. | 512 | *@param oth (const iterator &) The iterator to compare to. |
513 | *@returns (bool) Are they equal? | 513 | *@returns (bool) Are they equal? |
514 | */ | 514 | */ |
515 | bool operator==( const iterator &oth ) const | 515 | bool operator==( const iterator &oth ) const |
516 | { | 516 | { |
517 | return ( pLink == oth.pLink ); | 517 | return ( pLink == oth.pLink ); |
518 | } | 518 | } |
519 | 519 | ||
520 | /** | 520 | /** |
521 | * Equals comparison operator. | 521 | * Equals comparison operator. |
522 | *@param pOth (const Link *) The link to compare to. | 522 | *@param pOth (const Link *) The link to compare to. |
523 | *@returns (bool) Are they equal? | 523 | *@returns (bool) Are they equal? |
524 | */ | 524 | */ |
525 | bool operator==( const Link *pOth ) const | 525 | bool operator==( const Link *pOth ) const |
526 | { | 526 | { |
527 | return ( pLink == pOth ); | 527 | return ( pLink == pOth ); |
528 | } | 528 | } |
529 | 529 | ||
530 | /** | 530 | /** |
531 | * Not equals comparison operator. | 531 | * Not equals comparison operator. |
532 | *@param oth (const iterator &) The iterator to compare to. | 532 | *@param oth (const iterator &) The iterator to compare to. |
533 | *@returns (bool) Are they not equal? | 533 | *@returns (bool) Are they not equal? |
534 | */ | 534 | */ |
535 | bool operator!=( const iterator &oth ) const | 535 | bool operator!=( const iterator &oth ) const |
536 | { | 536 | { |
537 | return ( pLink != oth.pLink ); | 537 | return ( pLink != oth.pLink ); |
538 | } | 538 | } |
539 | 539 | ||
540 | /** | 540 | /** |
541 | * Not equals comparison operator. | 541 | * Not equals comparison operator. |
542 | *@param pOth (const Link *) The link to compare to. | 542 | *@param pOth (const Link *) The link to compare to. |
543 | *@returns (bool) Are they not equal? | 543 | *@returns (bool) Are they not equal? |
544 | */ | 544 | */ |
545 | bool operator!=( const Link *pOth ) const | 545 | bool operator!=( const Link *pOth ) const |
546 | { | 546 | { |
547 | return ( pLink != pOth ); | 547 | return ( pLink != pOth ); |
548 | } | 548 | } |
549 | 549 | ||
550 | /** | 550 | /** |
551 | * Dereference operator. | 551 | * Dereference operator. |
552 | *@returns (value_type &) The value. | 552 | *@returns (value_type &) The value. |
553 | */ | 553 | */ |
554 | value &operator*() | 554 | value &operator*() |
555 | { | 555 | { |
556 | return *(pLink->pValue); | 556 | return *(pLink->pValue); |
557 | } | 557 | } |
558 | 558 | ||
559 | /** | 559 | /** |
560 | * Pointer access operator. | 560 | * Pointer access operator. |
561 | *@returns (value_type *) A pointer to the value. | 561 | *@returns (value_type *) A pointer to the value. |
562 | */ | 562 | */ |
563 | value *operator->() | 563 | value *operator->() |
564 | { | 564 | { |
565 | return pLink->pValue; | 565 | return pLink->pValue; |
566 | } | 566 | } |
567 | 567 | ||
568 | iterator &operator++() | 568 | iterator &operator++() |
569 | { | 569 | { |
570 | if( pLink == NULL ) | 570 | if( pLink == NULL ) |
571 | throw Bu::ExceptionBase( | 571 | throw Bu::ExceptionBase( |
572 | "Attempt to iterate past end of list."); | 572 | "Attempt to iterate past end of list."); |
573 | pLink = pLink->pNext; | 573 | pLink = pLink->pNext; |
574 | return *this; | 574 | return *this; |
575 | } | 575 | } |
576 | 576 | ||
577 | iterator &operator--() | 577 | iterator &operator--() |
578 | { | 578 | { |
579 | if( pLink == NULL ) | 579 | if( pLink == NULL ) |
580 | throw Bu::ExceptionBase( | 580 | throw Bu::ExceptionBase( |
581 | "Attempt to iterate past begining of list."); | 581 | "Attempt to iterate past begining of list."); |
582 | pLink = pLink->pPrev; | 582 | pLink = pLink->pPrev; |
583 | return *this; | 583 | return *this; |
584 | } | 584 | } |
585 | 585 | ||
586 | iterator &operator++( int ) | 586 | iterator &operator++( int ) |
587 | { | 587 | { |
588 | if( pLink == NULL ) | 588 | if( pLink == NULL ) |
589 | throw Bu::ExceptionBase( | 589 | throw Bu::ExceptionBase( |
590 | "Attempt to iterate past end of list."); | 590 | "Attempt to iterate past end of list."); |
591 | pLink = pLink->pNext; | 591 | pLink = pLink->pNext; |
592 | return *this; | 592 | return *this; |
593 | } | 593 | } |
594 | 594 | ||
595 | iterator &operator--( int ) | 595 | iterator &operator--( int ) |
596 | { | 596 | { |
597 | if( pLink == NULL ) | 597 | if( pLink == NULL ) |
598 | throw Bu::ExceptionBase( | 598 | throw Bu::ExceptionBase( |
599 | "Attempt to iterate past begining of list."); | 599 | "Attempt to iterate past begining of list."); |
600 | pLink = pLink->pPrev; | 600 | pLink = pLink->pPrev; |
601 | return *this; | 601 | return *this; |
602 | } | 602 | } |
603 | 603 | ||
604 | iterator operator+( int iDelta ) | 604 | iterator operator+( int iDelta ) |
605 | { | 605 | { |
606 | iterator ret( *this ); | 606 | iterator ret( *this ); |
607 | for( int j = 0; j < iDelta; j++ ) | 607 | for( int j = 0; j < iDelta; j++ ) |
608 | { | 608 | { |
609 | if( ret.pLink == NULL ) | 609 | if( ret.pLink == NULL ) |
610 | throw Bu::ExceptionBase( | 610 | throw Bu::ExceptionBase( |
611 | "Attempt to iterate past begining of list."); | 611 | "Attempt to iterate past begining of list."); |
612 | ret.pLink = ret.pLink->pNext; | 612 | ret.pLink = ret.pLink->pNext; |
613 | } | 613 | } |
614 | return ret; | 614 | return ret; |
615 | } | 615 | } |
616 | 616 | ||
617 | iterator operator-( int iDelta ) | 617 | iterator operator-( int iDelta ) |
618 | { | 618 | { |
619 | iterator ret( *this ); | 619 | iterator ret( *this ); |
620 | for( int j = 0; j < iDelta; j++ ) | 620 | for( int j = 0; j < iDelta; j++ ) |
621 | { | 621 | { |
622 | if( ret.pLink == NULL ) | 622 | if( ret.pLink == NULL ) |
623 | throw Bu::ExceptionBase( | 623 | throw Bu::ExceptionBase( |
624 | "Attempt to iterate past begining of list."); | 624 | "Attempt to iterate past begining of list."); |
625 | ret.pLink = ret.pLink->pPrev; | 625 | ret.pLink = ret.pLink->pPrev; |
626 | } | 626 | } |
627 | return ret; | 627 | return ret; |
628 | } | 628 | } |
629 | 629 | ||
630 | operator bool() | 630 | operator bool() |
631 | { | 631 | { |
632 | return pLink != NULL; | 632 | return pLink != NULL; |
633 | } | 633 | } |
634 | 634 | ||
635 | bool isValid() | 635 | bool isValid() |
636 | { | 636 | { |
637 | return pLink != NULL; | 637 | return pLink != NULL; |
638 | } | 638 | } |
639 | 639 | ||
640 | /** | 640 | /** |
641 | * Assignment operator. | 641 | * Assignment operator. |
642 | *@param oth (const iterator &) The other iterator to set this | 642 | *@param oth (const iterator &) The other iterator to set this |
643 | * one to. | 643 | * one to. |
644 | */ | 644 | */ |
645 | iterator &operator=( const iterator &oth ) | 645 | iterator &operator=( const iterator &oth ) |
646 | { | 646 | { |
647 | pLink = oth.pLink; | 647 | pLink = oth.pLink; |
648 | return *this; | 648 | return *this; |
649 | } | 649 | } |
650 | } iterator; | 650 | } iterator; |
651 | 651 | ||
652 | /** | 652 | /** |
653 | *@see iterator | 653 | *@see iterator |
654 | */ | 654 | */ |
655 | typedef struct const_iterator | 655 | typedef struct const_iterator |
656 | { | 656 | { |
657 | friend class List<value, valuealloc, linkalloc>; | 657 | friend class List<value, valuealloc, linkalloc>; |
658 | private: | 658 | private: |
659 | Link *pLink; | 659 | Link *pLink; |
660 | 660 | ||
661 | const_iterator( Link *pLink ) : | 661 | const_iterator( Link *pLink ) : |
662 | pLink( pLink ) | 662 | pLink( pLink ) |
663 | { | 663 | { |
664 | } | 664 | } |
665 | 665 | ||
666 | public: | 666 | public: |
667 | const_iterator() : | 667 | const_iterator() : |
668 | pLink( NULL ) | 668 | pLink( NULL ) |
669 | { | 669 | { |
670 | } | 670 | } |
671 | 671 | ||
672 | const_iterator( const iterator &i ) : | 672 | const_iterator( const iterator &i ) : |
673 | pLink( i.pLink ) | 673 | pLink( i.pLink ) |
674 | { | 674 | { |
675 | } | 675 | } |
676 | 676 | ||
677 | bool operator==( const const_iterator &oth ) const | 677 | bool operator==( const const_iterator &oth ) const |
678 | { | 678 | { |
679 | return ( pLink == oth.pLink ); | 679 | return ( pLink == oth.pLink ); |
680 | } | 680 | } |
681 | 681 | ||
682 | bool operator==( const Link *pOth ) const | 682 | bool operator==( const Link *pOth ) const |
683 | { | 683 | { |
684 | return ( pLink == pOth ); | 684 | return ( pLink == pOth ); |
685 | } | 685 | } |
686 | 686 | ||
687 | bool operator!=( const const_iterator &oth ) const | 687 | bool operator!=( const const_iterator &oth ) const |
688 | { | 688 | { |
689 | return ( pLink != oth.pLink ); | 689 | return ( pLink != oth.pLink ); |
690 | } | 690 | } |
691 | 691 | ||
692 | bool operator!=( const Link *pOth ) const | 692 | bool operator!=( const Link *pOth ) const |
693 | { | 693 | { |
694 | return ( pLink != pOth ); | 694 | return ( pLink != pOth ); |
695 | } | 695 | } |
696 | 696 | ||
697 | const value &operator*() | 697 | const value &operator*() |
698 | { | 698 | { |
699 | return *(pLink->pValue); | 699 | return *(pLink->pValue); |
700 | } | 700 | } |
701 | 701 | ||
702 | const value *operator->() | 702 | const value *operator->() |
703 | { | 703 | { |
704 | return pLink->pValue; | 704 | return pLink->pValue; |
705 | } | 705 | } |
706 | 706 | ||
707 | const_iterator &operator++() | 707 | const_iterator &operator++() |
708 | { | 708 | { |
709 | if( pLink == NULL ) | 709 | if( pLink == NULL ) |
710 | throw Bu::ExceptionBase( | 710 | throw Bu::ExceptionBase( |
711 | "Attempt to iterate past end of list."); | 711 | "Attempt to iterate past end of list."); |
712 | pLink = pLink->pNext; | 712 | pLink = pLink->pNext; |
713 | return *this; | 713 | return *this; |
714 | } | 714 | } |
715 | 715 | ||
716 | const_iterator &operator--() | 716 | const_iterator &operator--() |
717 | { | 717 | { |
718 | if( pLink == NULL ) | 718 | if( pLink == NULL ) |
719 | throw Bu::ExceptionBase( | 719 | throw Bu::ExceptionBase( |
720 | "Attempt to iterate past begining of list."); | 720 | "Attempt to iterate past begining of list."); |
721 | pLink = pLink->pPrev; | 721 | pLink = pLink->pPrev; |
722 | return *this; | 722 | return *this; |
723 | } | 723 | } |
724 | 724 | ||
725 | const_iterator &operator++( int ) | 725 | const_iterator &operator++( int ) |
726 | { | 726 | { |
727 | if( pLink == NULL ) | 727 | if( pLink == NULL ) |
728 | throw Bu::ExceptionBase( | 728 | throw Bu::ExceptionBase( |
729 | "Attempt to iterate past end of list."); | 729 | "Attempt to iterate past end of list."); |
730 | pLink = pLink->pNext; | 730 | pLink = pLink->pNext; |
731 | return *this; | 731 | return *this; |
732 | } | 732 | } |
733 | 733 | ||
734 | const_iterator &operator--( int ) | 734 | const_iterator &operator--( int ) |
735 | { | 735 | { |
736 | if( pLink == NULL ) | 736 | if( pLink == NULL ) |
737 | throw Bu::ExceptionBase( | 737 | throw Bu::ExceptionBase( |
738 | "Attempt to iterate past begining of list."); | 738 | "Attempt to iterate past begining of list."); |
739 | pLink = pLink->pPrev; | 739 | pLink = pLink->pPrev; |
740 | return *this; | 740 | return *this; |
741 | } | 741 | } |
742 | 742 | ||
743 | const_iterator operator+( int iDelta ) | 743 | const_iterator operator+( int iDelta ) |
744 | { | 744 | { |
745 | const_iterator ret( *this ); | 745 | const_iterator ret( *this ); |
746 | for( int j = 0; j < iDelta; j++ ) | 746 | for( int j = 0; j < iDelta; j++ ) |
747 | { | 747 | { |
748 | if( ret.pLink == NULL ) | 748 | if( ret.pLink == NULL ) |
749 | throw Bu::ExceptionBase( | 749 | throw Bu::ExceptionBase( |
750 | "Attempt to iterate past begining of list."); | 750 | "Attempt to iterate past begining of list."); |
751 | ret.pLink = ret.pLink->pNext; | 751 | ret.pLink = ret.pLink->pNext; |
752 | } | 752 | } |
753 | return ret; | 753 | return ret; |
754 | } | 754 | } |
755 | 755 | ||
756 | const_iterator operator-( int iDelta ) | 756 | const_iterator operator-( int iDelta ) |
757 | { | 757 | { |
758 | const_iterator ret( *this ); | 758 | const_iterator ret( *this ); |
759 | for( int j = 0; j < iDelta; j++ ) | 759 | for( int j = 0; j < iDelta; j++ ) |
760 | { | 760 | { |
761 | if( ret.pLink == NULL ) | 761 | if( ret.pLink == NULL ) |
762 | throw Bu::ExceptionBase( | 762 | throw Bu::ExceptionBase( |
763 | "Attempt to iterate past begining of list."); | 763 | "Attempt to iterate past begining of list."); |
764 | ret.pLink = ret.pLink->pPrev; | 764 | ret.pLink = ret.pLink->pPrev; |
765 | } | 765 | } |
766 | return ret; | 766 | return ret; |
767 | } | 767 | } |
768 | 768 | ||
769 | const_iterator &operator=( const iterator &oth ) | 769 | const_iterator &operator=( const iterator &oth ) |
770 | { | 770 | { |
771 | pLink = oth.pLink; | 771 | pLink = oth.pLink; |
772 | return *this; | 772 | return *this; |
773 | } | 773 | } |
774 | 774 | ||
775 | const_iterator &operator=( const const_iterator &oth ) | 775 | const_iterator &operator=( const const_iterator &oth ) |
776 | { | 776 | { |
777 | pLink = oth.pLink; | 777 | pLink = oth.pLink; |
778 | return *this; | 778 | return *this; |
779 | } | 779 | } |
780 | 780 | ||
781 | operator bool() | 781 | operator bool() |
782 | { | 782 | { |
783 | return pLink != NULL; | 783 | return pLink != NULL; |
784 | } | 784 | } |
785 | 785 | ||
786 | bool isValid() | 786 | bool isValid() |
787 | { | 787 | { |
788 | return pLink != NULL; | 788 | return pLink != NULL; |
789 | } | 789 | } |
790 | } const_iterator; | 790 | } const_iterator; |
791 | 791 | ||
792 | /** | 792 | /** |
793 | * Get an iterator pointing to the first item in the list. | 793 | * Get an iterator pointing to the first item in the list. |
794 | *@returns (iterator) | 794 | *@returns (iterator) |
795 | */ | 795 | */ |
796 | iterator begin() | 796 | iterator begin() |
797 | { | 797 | { |
798 | _hardCopy(); | 798 | _hardCopy(); |
799 | return iterator( core->pFirst ); | 799 | return iterator( core->pFirst ); |
800 | } | 800 | } |
801 | 801 | ||
802 | /** | 802 | /** |
803 | * Get a const iterator pointing to the first item in the list. | 803 | * Get a const iterator pointing to the first item in the list. |
804 | *@returns (const const_iterator) | 804 | *@returns (const const_iterator) |
805 | */ | 805 | */ |
806 | const_iterator begin() const | 806 | const_iterator begin() const |
807 | { | 807 | { |
808 | return const_iterator( core->pFirst ); | 808 | return const_iterator( core->pFirst ); |
809 | } | 809 | } |
810 | 810 | ||
811 | /** | 811 | /** |
812 | * Get an iterator pointing to a place just past the last item in | 812 | * Get an iterator pointing to a place just past the last item in |
813 | * the list. | 813 | * the list. |
814 | *@returns (const Link *) | 814 | *@returns (const Link *) |
815 | */ | 815 | */ |
816 | const iterator end() | 816 | const iterator end() |
817 | { | 817 | { |
818 | return iterator( NULL ); | 818 | return iterator( NULL ); |
819 | } | 819 | } |
820 | 820 | ||
821 | /** | 821 | /** |
822 | * Get an iterator pointing to a place just past the last item in | 822 | * Get an iterator pointing to a place just past the last item in |
823 | * the list. | 823 | * the list. |
824 | *@returns (const Link *) | 824 | *@returns (const Link *) |
825 | */ | 825 | */ |
826 | const const_iterator end() const | 826 | const const_iterator end() const |
827 | { | 827 | { |
828 | return const_iterator( NULL ); | 828 | return const_iterator( NULL ); |
829 | } | 829 | } |
830 | 830 | ||
831 | /** | 831 | /** |
832 | * Erase an item from the list. | 832 | * Erase an item from the list. |
833 | *@param i (iterator) The item to erase. | 833 | *@param i (iterator) The item to erase. |
834 | */ | 834 | */ |
835 | MyType &erase( iterator i ) | 835 | MyType &erase( iterator i ) |
836 | { | 836 | { |
837 | _hardCopy(); | 837 | _hardCopy(); |
838 | core->erase( i.pLink ); | 838 | core->erase( i.pLink ); |
839 | 839 | ||
840 | return *this; | 840 | return *this; |
841 | } | 841 | } |
842 | 842 | ||
843 | /** | 843 | /** |
844 | * Erase an item from the list. | 844 | * Erase an item from the list. |
845 | *@param i (iterator) The item to erase. | 845 | *@param i (iterator) The item to erase. |
846 | */ | 846 | */ |
847 | MyType &erase( const_iterator i ) | 847 | MyType &erase( const_iterator i ) |
848 | { | 848 | { |
849 | _hardCopy(); | 849 | _hardCopy(); |
850 | core->erase( i.pLink ); | 850 | core->erase( i.pLink ); |
851 | 851 | ||
852 | return *this; | 852 | return *this; |
853 | } | 853 | } |
854 | 854 | ||
855 | /** | 855 | /** |
856 | * Erase an item from the list if you already know the item. | 856 | * Erase an item from the list if you already know the item. |
857 | *@param v The item to find and erase. | 857 | *@param v The item to find and erase. |
858 | */ | 858 | */ |
859 | MyType &erase( const value &v ) | 859 | MyType &erase( const value &v ) |
860 | { | 860 | { |
861 | for( const_iterator i = begin(); i != end(); i++ ) | 861 | for( const_iterator i = begin(); i != end(); i++ ) |
862 | { | 862 | { |
863 | if( (*i) == v ) | 863 | if( (*i) == v ) |
864 | { | 864 | { |
865 | erase( i ); | 865 | erase( i ); |
866 | return *this; | 866 | return *this; |
867 | } | 867 | } |
868 | } | 868 | } |
869 | 869 | ||
870 | return *this; | 870 | return *this; |
871 | } | 871 | } |
872 | 872 | ||
873 | /** | 873 | /** |
874 | * Erases the first item in the list, identical to pop, but better for | 874 | * Erases the first item in the list, identical to pop, but better for |
875 | * lists that aren't built as stacks, since you know where it will be | 875 | * lists that aren't built as stacks, since you know where it will be |
876 | * erasing from. | 876 | * erasing from. |
877 | */ | 877 | */ |
878 | MyType &eraseFirst() | 878 | MyType &eraseFirst() |
879 | { | 879 | { |
880 | _hardCopy(); | 880 | _hardCopy(); |
881 | erase( begin() ); | 881 | erase( begin() ); |
882 | 882 | ||
883 | return *this; | 883 | return *this; |
884 | } | 884 | } |
885 | 885 | ||
886 | /** | 886 | /** |
887 | * Erases the last item in the list. | 887 | * Erases the last item in the list. |
888 | */ | 888 | */ |
889 | MyType &eraseLast() | 889 | MyType &eraseLast() |
890 | { | 890 | { |
891 | _hardCopy(); | 891 | _hardCopy(); |
892 | core->erase( core->pLast ); | 892 | core->erase( core->pLast ); |
893 | 893 | ||
894 | return *this; | 894 | return *this; |
895 | } | 895 | } |
896 | 896 | ||
897 | iterator find( const value &v ) | 897 | iterator find( const value &v ) |
898 | { | 898 | { |
899 | for( iterator i = begin(); i; i++ ) | 899 | for( iterator i = begin(); i; i++ ) |
900 | { | 900 | { |
901 | if( (*i) == v ) | 901 | if( (*i) == v ) |
902 | return i; | 902 | return i; |
903 | } | 903 | } |
904 | 904 | ||
905 | return end(); | 905 | return end(); |
906 | } | 906 | } |
907 | 907 | ||
908 | const_iterator find( const value &v ) const | 908 | const_iterator find( const value &v ) const |
909 | { | 909 | { |
910 | for( const_iterator i = begin(); i; i++ ) | 910 | for( const_iterator i = begin(); i; i++ ) |
911 | { | 911 | { |
912 | if( (*i) == v ) | 912 | if( (*i) == v ) |
913 | return i; | 913 | return i; |
914 | } | 914 | } |
915 | 915 | ||
916 | return end(); | 916 | return end(); |
917 | } | 917 | } |
918 | 918 | ||
919 | /** | 919 | /** |
920 | * Get the current size of the list. | 920 | * Get the current size of the list. |
921 | *@returns (int) The current size of the list. | 921 | *@returns (int) The current size of the list. |
922 | */ | 922 | */ |
923 | long getSize() const | 923 | long getSize() const |
924 | { | 924 | { |
925 | return core->nSize; | 925 | return core->nSize; |
926 | } | 926 | } |
927 | 927 | ||
928 | /** | 928 | /** |
929 | * Get the first item in the list. | 929 | * Get the first item in the list. |
930 | *@returns (value_type &) The first item in the list. | 930 | *@returns (value_type &) The first item in the list. |
931 | */ | 931 | */ |
932 | value &first() | 932 | value &first() |
933 | { | 933 | { |
934 | if( core->pFirst->pValue == NULL ) | 934 | if( core->pFirst->pValue == NULL ) |
935 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); | 935 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); |
936 | _hardCopy(); | 936 | _hardCopy(); |
937 | return *core->pFirst->pValue; | 937 | return *core->pFirst->pValue; |
938 | } | 938 | } |
939 | 939 | ||
940 | /** | 940 | /** |
941 | * Get the first item in the list. | 941 | * Get the first item in the list. |
942 | *@returns (const value_type &) The first item in the list. | 942 | *@returns (const value_type &) The first item in the list. |
943 | */ | 943 | */ |
944 | const value &first() const | 944 | const value &first() const |
945 | { | 945 | { |
946 | if( core->pFirst->pValue == NULL ) | 946 | if( core->pFirst->pValue == NULL ) |
947 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); | 947 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); |
948 | return *core->pFirst->pValue; | 948 | return *core->pFirst->pValue; |
949 | } | 949 | } |
950 | 950 | ||
951 | /** | 951 | /** |
952 | * Get the last item in the list. | 952 | * Get the last item in the list. |
953 | *@returns (value_type &) The last item in the list. | 953 | *@returns (value_type &) The last item in the list. |
954 | */ | 954 | */ |
955 | value &last() | 955 | value &last() |
956 | { | 956 | { |
957 | _hardCopy(); | 957 | _hardCopy(); |
958 | return *core->pLast->pValue; | 958 | return *core->pLast->pValue; |
959 | } | 959 | } |
960 | 960 | ||
961 | /** | 961 | /** |
962 | * Get the last item in the list. | 962 | * Get the last item in the list. |
963 | *@returns (const value_type &) The last item in the list. | 963 | *@returns (const value_type &) The last item in the list. |
964 | */ | 964 | */ |
965 | const value &last() const | 965 | const value &last() const |
966 | { | 966 | { |
967 | return *core->pLast->pValue; | 967 | return *core->pLast->pValue; |
968 | } | 968 | } |
969 | 969 | ||
970 | bool isEmpty() const | 970 | bool isEmpty() const |
971 | { | 971 | { |
972 | return (core->nSize == 0); | 972 | return (core->nSize == 0); |
973 | } | 973 | } |
974 | 974 | ||
975 | protected: | 975 | protected: |
976 | virtual Core *_copyCore( Core *src ) | 976 | virtual Core *_copyCore( Core *src ) |
977 | { | 977 | { |
978 | Core *pRet = _allocateCore(); | 978 | Core *pRet = _allocateCore(); |
979 | for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) | 979 | for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) |
980 | { | 980 | { |
981 | pRet->append( *pCur->pValue ); | 981 | pRet->append( *pCur->pValue ); |
982 | } | 982 | } |
983 | return pRet; | 983 | return pRet; |
984 | } | 984 | } |
985 | 985 | ||
986 | private: | 986 | private: |
987 | }; | 987 | }; |
988 | 988 | ||
989 | class Formatter; | 989 | class Formatter; |
990 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 990 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
991 | Formatter &operator<<( Formatter &rOut, signed char c ); | 991 | Formatter &operator<<( Formatter &rOut, signed char c ); |
992 | template<typename a, typename b, typename c> | 992 | template<typename a, typename b, typename c> |
993 | Formatter &operator<<( Formatter &f, const Bu::List<a,b,c> &l ) | 993 | Formatter &operator<<( Formatter &f, const Bu::List<a,b,c> &l ) |
994 | { | 994 | { |
995 | f << '['; | 995 | f << '['; |
996 | for( typename Bu::List<a,b,c>::const_iterator i = l.begin(); i; i++ ) | 996 | for( typename Bu::List<a,b,c>::const_iterator i = l.begin(); i; i++ ) |
997 | { | 997 | { |
998 | if( i != l.begin() ) | 998 | if( i != l.begin() ) |
999 | f << ", "; | 999 | f << ", "; |
1000 | f << *i; | 1000 | f << *i; |
1001 | } | 1001 | } |
1002 | f << ']'; | 1002 | f << ']'; |
1003 | 1003 | ||
1004 | return f; | 1004 | return f; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | template<typename value, typename a, typename b> | 1007 | template<typename value, typename a, typename b> |
1008 | ArchiveBase &operator<<( ArchiveBase &ar, const List<value,a,b> &h ) | 1008 | ArchiveBase &operator<<( ArchiveBase &ar, const List<value,a,b> &h ) |
1009 | { | 1009 | { |
1010 | ar << h.getSize(); | 1010 | ar << h.getSize(); |
1011 | for( typename List<value>::const_iterator i = h.begin(); i != h.end(); i++ ) | 1011 | for( typename List<value>::const_iterator i = h.begin(); i != h.end(); i++ ) |
1012 | { | 1012 | { |
1013 | ar << (*i); | 1013 | ar << (*i); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | return ar; | 1016 | return ar; |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | template<typename value, typename a, typename b> | 1019 | template<typename value, typename a, typename b> |
1020 | ArchiveBase &operator>>( ArchiveBase &ar, List<value,a,b> &h ) | 1020 | ArchiveBase &operator>>( ArchiveBase &ar, List<value,a,b> &h ) |
1021 | { | 1021 | { |
1022 | h.clear(); | 1022 | h.clear(); |
1023 | long nSize; | 1023 | long nSize; |
1024 | ar >> nSize; | 1024 | ar >> nSize; |
1025 | 1025 | ||
1026 | for( long j = 0; j < nSize; j++ ) | 1026 | for( long j = 0; j < nSize; j++ ) |
1027 | { | 1027 | { |
1028 | value v; | 1028 | value v; |
1029 | ar >> v; | 1029 | ar >> v; |
1030 | h.append( v ); | 1030 | h.append( v ); |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | return ar; | 1033 | return ar; |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | } | 1036 | } |
1037 | 1037 | ||
diff --git a/src/stable/logger.cpp b/src/stable/logger.cpp index fa0987e..7d49193 100644 --- a/src/stable/logger.cpp +++ b/src/stable/logger.cpp | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | Bu::Logger::Logger() | 15 | Bu::Logger::Logger() |
16 | { | 16 | { |
17 | setFormat("%t"); | 17 | setFormat("%t"); |
18 | } | 18 | } |
19 | 19 | ||
20 | Bu::Logger::~Logger() | 20 | Bu::Logger::~Logger() |
@@ -24,186 +24,186 @@ Bu::Logger::~Logger() | |||
24 | void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) | 24 | void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) |
25 | { | 25 | { |
26 | #ifndef WIN32 | 26 | #ifndef WIN32 |
27 | if( (nLevel&nLevelMask) == 0 ) | 27 | if( (nLevel&nLevelMask) == 0 ) |
28 | return; | 28 | return; |
29 | 29 | ||
30 | va_list ap; | 30 | va_list ap; |
31 | va_start( ap, sFormat ); | 31 | va_start( ap, sFormat ); |
32 | char *text; | 32 | char *text; |
33 | if( vasprintf( &text, sFormat, ap ) < 0 ) | 33 | if( vasprintf( &text, sFormat, ap ) < 0 ) |
34 | { | 34 | { |
35 | printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); | 35 | printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); |
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | va_end(ap); | 38 | va_end(ap); |
39 | 39 | ||
40 | time_t t = time(NULL); | 40 | time_t t = time(NULL); |
41 | 41 | ||
42 | char *line = NULL; | 42 | char *line = NULL; |
43 | struct tm *pTime; | 43 | struct tm *pTime; |
44 | pTime = localtime( &t ); | 44 | pTime = localtime( &t ); |
45 | if ( asprintf( | 45 | if ( asprintf( |
46 | &line, | 46 | &line, |
47 | sLogFormat.getStr(), | 47 | sLogFormat.getStr(), |
48 | pTime->tm_year+1900, | 48 | pTime->tm_year+1900, |
49 | pTime->tm_mon+1, | 49 | pTime->tm_mon+1, |
50 | pTime->tm_mday, | 50 | pTime->tm_mday, |
51 | pTime->tm_hour, | 51 | pTime->tm_hour, |
52 | pTime->tm_min, | 52 | pTime->tm_min, |
53 | pTime->tm_sec, | 53 | pTime->tm_sec, |
54 | nLevel, | 54 | nLevel, |
55 | sFile, | 55 | sFile, |
56 | nLine, | 56 | nLine, |
57 | text, | 57 | text, |
58 | sFunction | 58 | sFunction |
59 | ) < 0 ) | 59 | ) < 0 ) |
60 | { | 60 | { |
61 | //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); | 61 | //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); |
62 | return; | 62 | return; |
63 | } | 63 | } |
64 | write( fileno(stdout), line, strlen(line) ); | 64 | write( fileno(stdout), line, strlen(line) ); |
65 | free( text ); | 65 | free( text ); |
66 | free( line ); | 66 | free( line ); |
67 | #else | 67 | #else |
68 | #warning Bu::Logger::log IS A STUB for WIN32!!!! | 68 | #warning Bu::Logger::log IS A STUB for WIN32!!!! |
69 | #endif | 69 | #endif |
70 | } | 70 | } |
71 | 71 | ||
72 | void Bu::Logger::setFormat( const Bu::String &str ) | 72 | void Bu::Logger::setFormat( const Bu::String &str ) |
73 | { | 73 | { |
74 | sLogFormat = ""; | 74 | sLogFormat = ""; |
75 | 75 | ||
76 | static char fmts[][4]={ | 76 | static char fmts[][4]={ |
77 | {'y', 'd', '0', '1'}, | 77 | {'y', 'd', '0', '1'}, |
78 | {'m', 'd', '0', '2'}, | 78 | {'m', 'd', '0', '2'}, |
79 | {'d', 'd', '0', '3'}, | 79 | {'d', 'd', '0', '3'}, |
80 | {'h', 'd', '0', '4'}, | 80 | {'h', 'd', '0', '4'}, |
81 | {'M', 'd', '0', '5'}, | 81 | {'M', 'd', '0', '5'}, |
82 | {'s', 'd', '0', '6'}, | 82 | {'s', 'd', '0', '6'}, |
83 | {'L', 'd', '0', '7'}, | 83 | {'L', 'd', '0', '7'}, |
84 | {'f', 's', '0', '8'}, | 84 | {'f', 's', '0', '8'}, |
85 | {'l', 'd', '0', '9'}, | 85 | {'l', 'd', '0', '9'}, |
86 | {'t', 's', '1', '0'}, | 86 | {'t', 's', '1', '0'}, |
87 | {'F', 's', '1', '1'}, | 87 | {'F', 's', '1', '1'}, |
88 | {'\0', '\0', '\0', '\0'}, | 88 | {'\0', '\0', '\0', '\0'}, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | for( const char *s = str.getStr(); *s; s++ ) | 91 | for( const char *s = str.getStr(); *s; s++ ) |
92 | { | 92 | { |
93 | if( *s == '%' ) | 93 | if( *s == '%' ) |
94 | { | 94 | { |
95 | sLogFormat += '%'; | 95 | sLogFormat += '%'; |
96 | Bu::String sBuf; | 96 | Bu::String sBuf; |
97 | for(;;) | 97 | for(;;) |
98 | { | 98 | { |
99 | s++; | 99 | s++; |
100 | int l; | 100 | int l; |
101 | for( l = 0;; l++ ) | 101 | for( l = 0;; l++ ) |
102 | { | 102 | { |
103 | if( fmts[l][0] == '\0' ) | 103 | if( fmts[l][0] == '\0' ) |
104 | { | 104 | { |
105 | sBuf += *s; | 105 | sBuf += *s; |
106 | break; | 106 | break; |
107 | } | 107 | } |
108 | else if( *s == fmts[l][0] ) | 108 | else if( *s == fmts[l][0] ) |
109 | { | 109 | { |
110 | sLogFormat += fmts[l][2]; | 110 | sLogFormat += fmts[l][2]; |
111 | sLogFormat += fmts[l][3]; | 111 | sLogFormat += fmts[l][3]; |
112 | sLogFormat += '$'; | 112 | sLogFormat += '$'; |
113 | sLogFormat += sBuf; | 113 | sLogFormat += sBuf; |
114 | sLogFormat += fmts[l][1]; | 114 | sLogFormat += fmts[l][1]; |
115 | break; | 115 | break; |
116 | } | 116 | } |
117 | } | 117 | } |
118 | if( fmts[l][0] != '\0' ) | 118 | if( fmts[l][0] != '\0' ) |
119 | break; | 119 | break; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | else | 122 | else |
123 | { | 123 | { |
124 | sLogFormat += *s; | 124 | sLogFormat += *s; |
125 | } | 125 | } |
126 | } | 126 | } |
127 | sLogFormat += '\n'; | 127 | sLogFormat += '\n'; |
128 | 128 | ||
129 | //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); | 129 | //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); |
130 | } | 130 | } |
131 | 131 | ||
132 | void Bu::Logger::setMask( uint32_t n ) | 132 | void Bu::Logger::setMask( uint32_t n ) |
133 | { | 133 | { |
134 | nLevelMask = n; | 134 | nLevelMask = n; |
135 | } | 135 | } |
136 | 136 | ||
137 | uint32_t Bu::Logger::getMask() | 137 | uint32_t Bu::Logger::getMask() |
138 | { | 138 | { |
139 | return nLevelMask; | 139 | return nLevelMask; |
140 | } | 140 | } |
141 | 141 | ||
142 | void Bu::Logger::setLevel( uint32_t n ) | 142 | void Bu::Logger::setLevel( uint32_t n ) |
143 | { | 143 | { |
144 | int j; | 144 | int j; |
145 | for( j = 31; j > 0; j-- ) | 145 | for( j = 31; j > 0; j-- ) |
146 | { | 146 | { |
147 | if( (n&(1<<j)) ) | 147 | if( (n&(1<<j)) ) |
148 | { | 148 | { |
149 | for(; j >= 0; j-- ) | 149 | for(; j >= 0; j-- ) |
150 | { | 150 | { |
151 | n |= (1<<j); | 151 | n |= (1<<j); |
152 | } | 152 | } |
153 | nLevelMask = n; | 153 | nLevelMask = n; |
154 | return; | 154 | return; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | void Bu::Logger::hexDump( uint32_t nLevel, const char *sFile, | 159 | void Bu::Logger::hexDump( uint32_t nLevel, const char *sFile, |
160 | const char *sFunction, int nLine, const void *pDataV, long nDataLen, | 160 | const char *sFunction, int nLine, const void *pDataV, long nDataLen, |
161 | const char *lpName ) | 161 | const char *lpName ) |
162 | { | 162 | { |
163 | if( (nLevel&nLevelMask) == 0 ) | 163 | if( (nLevel&nLevelMask) == 0 ) |
164 | return; | 164 | return; |
165 | 165 | ||
166 | log( nLevel, sFile, sFunction, nLine, "Displaying %ld bytes of %s.", nDataLen, lpName ); | 166 | log( nLevel, sFile, sFunction, nLine, "Displaying %ld bytes of %s.", nDataLen, lpName ); |
167 | const unsigned char *pData = (const unsigned char *)pDataV; | 167 | const unsigned char *pData = (const unsigned char *)pDataV; |
168 | int j = 0; | 168 | int j = 0; |
169 | Bu::String sBorder; | 169 | Bu::String sBorder; |
170 | for( int l = 0; l < 8*3+2*8+2+5; l++ ) sBorder += ((l!=11&&l!=37)?("-"):("+")); | 170 | for( int l = 0; l < 8*3+2*8+2+5; l++ ) sBorder += ((l!=11&&l!=37)?("-"):("+")); |
171 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); | 171 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); |
172 | Bu::String sLine; | 172 | Bu::String sLine; |
173 | for(;;) | 173 | for(;;) |
174 | { | 174 | { |
175 | { | 175 | { |
176 | char buf[16]; | 176 | char buf[16]; |
177 | sprintf( buf, "%010d | ", j ); | 177 | sprintf( buf, "%010d | ", j ); |
178 | sLine += buf; | 178 | sLine += buf; |
179 | } | 179 | } |
180 | int kmax = 8; | 180 | int kmax = 8; |
181 | if( nDataLen-j < 8 ) kmax = nDataLen-j; | 181 | if( nDataLen-j < 8 ) kmax = nDataLen-j; |
182 | for(int k = 0; k < 8; k++ ) | 182 | for(int k = 0; k < 8; k++ ) |
183 | { | 183 | { |
184 | if( k < kmax ) | 184 | if( k < kmax ) |
185 | { | 185 | { |
186 | char buf[4]; | 186 | char buf[4]; |
187 | sprintf( buf, "%02X ", (int)((unsigned char)pData[j+k]) ); | 187 | sprintf( buf, "%02X ", (int)((unsigned char)pData[j+k]) ); |
188 | sLine += buf; | 188 | sLine += buf; |
189 | } | 189 | } |
190 | else | 190 | else |
191 | { | 191 | { |
192 | sLine += "-- "; | 192 | sLine += "-- "; |
193 | } | 193 | } |
194 | } | 194 | } |
195 | sLine += "| "; | 195 | sLine += "| "; |
196 | for(int k = 0; k < kmax; k++ ) | 196 | for(int k = 0; k < kmax; k++ ) |
197 | { | 197 | { |
198 | char buf[3]; | 198 | char buf[3]; |
199 | sprintf( buf, "%c", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); | 199 | sprintf( buf, "%c", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); |
200 | sLine += buf; | 200 | sLine += buf; |
201 | } | 201 | } |
202 | log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); | 202 | log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); |
203 | sLine = ""; | 203 | sLine = ""; |
204 | j += kmax; | 204 | j += kmax; |
205 | if( j >= nDataLen ) break; | 205 | if( j >= nDataLen ) break; |
206 | } | 206 | } |
207 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); | 207 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); |
208 | } | 208 | } |
209 | 209 | ||
diff --git a/src/stable/logger.h b/src/stable/logger.h index 198ffa2..bcc5a83 100644 --- a/src/stable/logger.h +++ b/src/stable/logger.h | |||
@@ -13,82 +13,82 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * Simple logging facility. All output goes straight to stdout, unlike the | 17 | * Simple logging facility. All output goes straight to stdout, unlike the |
18 | * old multi-log system. Generally we expect any program complex enough to | 18 | * old multi-log system. Generally we expect any program complex enough to |
19 | * want to use this will have other facilities for processing the logging | 19 | * want to use this will have other facilities for processing the logging |
20 | * output, but if we need it we can add other output methods. | 20 | * output, but if we need it we can add other output methods. |
21 | * | 21 | * |
22 | * Currently implemented as a singleton to avoid clutter with globals, you | 22 | * Currently implemented as a singleton to avoid clutter with globals, you |
23 | * generally never want to use the logging system directly, it's annoying. | 23 | * generally never want to use the logging system directly, it's annoying. |
24 | * Instead use the handy macros lineLog, setLogMask, setLogFormat, and | 24 | * Instead use the handy macros lineLog, setLogMask, setLogFormat, and |
25 | * setLogLevel. They do all the real work for you. | 25 | * setLogLevel. They do all the real work for you. |
26 | * | 26 | * |
27 | * In the log format, you can specify extra information that will be written | 27 | * In the log format, you can specify extra information that will be written |
28 | * to the log with every message, and extras in printf style. Use %X flags | 28 | * to the log with every message, and extras in printf style. Use %X flags |
29 | * where X is one of the following: | 29 | * where X is one of the following: |
30 | * - L - Logging level of the log message (not the current mask) | 30 | * - L - Logging level of the log message (not the current mask) |
31 | * - y - Full year | 31 | * - y - Full year |
32 | * - m - Month | 32 | * - m - Month |
33 | * - d - Day of month | 33 | * - d - Day of month |
34 | * - h - Hour (24-hour format) | 34 | * - h - Hour (24-hour format) |
35 | * - M - Minutes | 35 | * - M - Minutes |
36 | * - s - Seconds | 36 | * - s - Seconds |
37 | * - f - Source file | 37 | * - f - Source file |
38 | * - l - Line number | 38 | * - l - Line number |
39 | * - F - function name | 39 | * - F - function name |
40 | * - t - Text of message (usually important) | 40 | * - t - Text of message (usually important) |
41 | * | 41 | * |
42 | * You can include anything extra that you would like, a newline will always | 42 | * You can include anything extra that you would like, a newline will always |
43 | * be added automatically, so no need to worry about that. You can also | 43 | * be added automatically, so no need to worry about that. You can also |
44 | * include any extra printf style formatting that you would like, for | 44 | * include any extra printf style formatting that you would like, for |
45 | * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. | 45 | * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. |
46 | * | 46 | * |
47 | * It's generally handy to create an enum of values you use as levels during | 47 | * It's generally handy to create an enum of values you use as levels during |
48 | * program execution (such as error, warning, info, debug, etc). These | 48 | * program execution (such as error, warning, info, debug, etc). These |
49 | * levels should be treated as bitflags, and the most desirable messages, | 49 | * levels should be treated as bitflags, and the most desirable messages, |
50 | * i.e. serious errors and the like should be low order (0x01), and the much | 50 | * i.e. serious errors and the like should be low order (0x01), and the much |
51 | * less desirable messages, like debugging info, should be higher order | 51 | * less desirable messages, like debugging info, should be higher order |
52 | * (0xF0). During operation you can then set either an explicit mask, | 52 | * (0xF0). During operation you can then set either an explicit mask, |
53 | * selecting just the levels that you would like to see printed, or set the | 53 | * selecting just the levels that you would like to see printed, or set the |
54 | * mask using the setLevel helper function, which simulates verbosity | 54 | * mask using the setLevel helper function, which simulates verbosity |
55 | * levels, enabling every flag lower order than the highest order set bit | 55 | * levels, enabling every flag lower order than the highest order set bit |
56 | * passed. I.E. if you had the following enumerated levels: | 56 | * passed. I.E. if you had the following enumerated levels: |
57 | * | 57 | * |
58 | *@code | 58 | *@code |
59 | enum { | 59 | enum { |
60 | logError = 0x01, | 60 | logError = 0x01, |
61 | logWarning = 0x02, | 61 | logWarning = 0x02, |
62 | logInfo = 0x04, | 62 | logInfo = 0x04, |
63 | logDebug = 0x08 | 63 | logDebug = 0x08 |
64 | }; | 64 | }; |
65 | @endcode | 65 | @endcode |
66 | * And you set the mask with setMask( logInfo ) the only messages you would | 66 | * And you set the mask with setMask( logInfo ) the only messages you would |
67 | * see are the ones catagorized logInfo. However, if you used | 67 | * see are the ones catagorized logInfo. However, if you used |
68 | * setLevel( logInfo ) then you would see logInfo, logWarning, and logError | 68 | * setLevel( logInfo ) then you would see logInfo, logWarning, and logError |
69 | * type messages, since they are lower order. | 69 | * type messages, since they are lower order. |
70 | */ | 70 | */ |
71 | class Logger : public Bu::Singleton<Bu::Logger> | 71 | class Logger : public Bu::Singleton<Bu::Logger> |
72 | { | 72 | { |
73 | friend class Bu::Singleton<Bu::Logger>; | 73 | friend class Bu::Singleton<Bu::Logger>; |
74 | private: | 74 | private: |
75 | Logger(); | 75 | Logger(); |
76 | virtual ~Logger(); | 76 | virtual ~Logger(); |
77 | 77 | ||
78 | public: | 78 | public: |
79 | void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); | 79 | void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); |
80 | 80 | ||
81 | void setFormat( const Bu::String &str ); | 81 | void setFormat( const Bu::String &str ); |
82 | void setMask( uint32_t n ); | 82 | void setMask( uint32_t n ); |
83 | void setLevel( uint32_t n ); | 83 | void setLevel( uint32_t n ); |
84 | uint32_t getMask(); | 84 | uint32_t getMask(); |
85 | 85 | ||
86 | void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); | 86 | void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); |
87 | 87 | ||
88 | private: | 88 | private: |
89 | Bu::String sLogFormat; | 89 | Bu::String sLogFormat; |
90 | uint32_t nLevelMask; | 90 | uint32_t nLevelMask; |
91 | }; | 91 | }; |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
@@ -97,29 +97,29 @@ namespace Bu | |||
97 | * file, line number, and function. | 97 | * file, line number, and function. |
98 | */ | 98 | */ |
99 | #define lineLog( nLevel, sFrmt, ...) \ | 99 | #define lineLog( nLevel, sFrmt, ...) \ |
100 | Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) | 100 | Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) |
101 | 101 | ||
102 | #define logHexDump( nLevel, pData, iSize, sName ) \ | 102 | #define logHexDump( nLevel, pData, iSize, sName ) \ |
103 | Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) | 103 | Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) |
104 | 104 | ||
105 | /** | 105 | /** |
106 | * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for | 106 | * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for |
107 | * details. | 107 | * details. |
108 | */ | 108 | */ |
109 | #define setLogMask( nLevel ) \ | 109 | #define setLogMask( nLevel ) \ |
110 | Bu::Logger::getInstance().setMask( nLevel ) | 110 | Bu::Logger::getInstance().setMask( nLevel ) |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * Set the Bu::Logger format. See Bu::Logger::setFormat for details. | 113 | * Set the Bu::Logger format. See Bu::Logger::setFormat for details. |
114 | */ | 114 | */ |
115 | #define setLogFormat( sFrmt ) \ | 115 | #define setLogFormat( sFrmt ) \ |
116 | Bu::Logger::getInstance().setFormat( sFrmt ) | 116 | Bu::Logger::getInstance().setFormat( sFrmt ) |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel | 119 | * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel |
120 | * for details. | 120 | * for details. |
121 | */ | 121 | */ |
122 | #define setLogLevel( nLevel ) \ | 122 | #define setLogLevel( nLevel ) \ |
123 | Bu::Logger::getInstance().setLevel( nLevel ) | 123 | Bu::Logger::getInstance().setLevel( nLevel ) |
124 | 124 | ||
125 | #endif | 125 | #endif |
diff --git a/src/stable/lzma.cpp b/src/stable/lzma.cpp index 9df8f57..9ec2ce0 100644 --- a/src/stable/lzma.cpp +++ b/src/stable/lzma.cpp | |||
@@ -15,234 +15,234 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : | 17 | Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ), | 21 | sTotalOut( 0 ), |
22 | eFmt( eFmt ), | 22 | eFmt( eFmt ), |
23 | bEos( false ) | 23 | bEos( false ) |
24 | { | 24 | { |
25 | TRACE( nCompression ); | 25 | TRACE( nCompression ); |
26 | start(); | 26 | start(); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Lzma::~Lzma() | 29 | Bu::Lzma::~Lzma() |
30 | { | 30 | { |
31 | TRACE(); | 31 | TRACE(); |
32 | stop(); | 32 | stop(); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Lzma::start() | 35 | void Bu::Lzma::start() |
36 | { | 36 | { |
37 | TRACE(); | 37 | TRACE(); |
38 | nBufSize = 64*1024; | 38 | nBufSize = 64*1024; |
39 | pBuf = new char[nBufSize]; | 39 | pBuf = new char[nBufSize]; |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::size Bu::Lzma::stop() | 42 | Bu::size Bu::Lzma::stop() |
43 | { | 43 | { |
44 | TRACE(); | 44 | TRACE(); |
45 | if( pState ) | 45 | if( pState ) |
46 | { | 46 | { |
47 | if( bReading ) | 47 | if( bReading ) |
48 | { | 48 | { |
49 | lzma_end( pState ); | 49 | lzma_end( pState ); |
50 | delete[] pBuf; | 50 | delete[] pBuf; |
51 | pBuf = NULL; | 51 | pBuf = NULL; |
52 | delete pState; | 52 | delete pState; |
53 | prState = NULL; | 53 | prState = NULL; |
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | else | 56 | else |
57 | { | 57 | { |
58 | for(;;) | 58 | for(;;) |
59 | { | 59 | { |
60 | pState->next_in = NULL; | 60 | pState->next_in = NULL; |
61 | pState->avail_in = 0; | 61 | pState->avail_in = 0; |
62 | pState->avail_out = nBufSize; | 62 | pState->avail_out = nBufSize; |
63 | pState->next_out = (uint8_t *)pBuf; | 63 | pState->next_out = (uint8_t *)pBuf; |
64 | int res = lzma_code( pState, LZMA_FINISH ); | 64 | int res = lzma_code( pState, LZMA_FINISH ); |
65 | if( pState->avail_out < nBufSize ) | 65 | if( pState->avail_out < nBufSize ) |
66 | { | 66 | { |
67 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 67 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
68 | } | 68 | } |
69 | if( res == LZMA_STREAM_END ) | 69 | if( res == LZMA_STREAM_END ) |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | lzma_end( pState ); | 72 | lzma_end( pState ); |
73 | delete[] pBuf; | 73 | delete[] pBuf; |
74 | pBuf = NULL; | 74 | pBuf = NULL; |
75 | delete pState; | 75 | delete pState; |
76 | prState = NULL; | 76 | prState = NULL; |
77 | return sTotalOut; | 77 | return sTotalOut; |
78 | } | 78 | } |
79 | } | 79 | } |
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::Lzma::lzmaError( int code ) | 83 | void Bu::Lzma::lzmaError( int code ) |
84 | { | 84 | { |
85 | TRACE( code ); | 85 | TRACE( code ); |
86 | switch( code ) | 86 | switch( code ) |
87 | { | 87 | { |
88 | case LZMA_OK: | 88 | case LZMA_OK: |
89 | case LZMA_STREAM_END: | 89 | case LZMA_STREAM_END: |
90 | case LZMA_NO_CHECK: | 90 | case LZMA_NO_CHECK: |
91 | case LZMA_UNSUPPORTED_CHECK: | 91 | case LZMA_UNSUPPORTED_CHECK: |
92 | break; | 92 | break; |
93 | 93 | ||
94 | case LZMA_MEM_ERROR: | 94 | case LZMA_MEM_ERROR: |
95 | throw ExceptionBase("Lzma: Memory allocation error."); | 95 | throw ExceptionBase("Lzma: Memory allocation error."); |
96 | 96 | ||
97 | case LZMA_MEMLIMIT_ERROR: | 97 | case LZMA_MEMLIMIT_ERROR: |
98 | throw ExceptionBase("Lzma: Memory usage limit was reached."); | 98 | throw ExceptionBase("Lzma: Memory usage limit was reached."); |
99 | 99 | ||
100 | case LZMA_FORMAT_ERROR: | 100 | case LZMA_FORMAT_ERROR: |
101 | throw ExceptionBase("Lzma: File format not recognized."); | 101 | throw ExceptionBase("Lzma: File format not recognized."); |
102 | 102 | ||
103 | case LZMA_OPTIONS_ERROR: | 103 | case LZMA_OPTIONS_ERROR: |
104 | throw ExceptionBase("Lzma: Invalid or unsupported options."); | 104 | throw ExceptionBase("Lzma: Invalid or unsupported options."); |
105 | 105 | ||
106 | case LZMA_DATA_ERROR: | 106 | case LZMA_DATA_ERROR: |
107 | throw ExceptionBase("Lzma: Data is corrupt."); | 107 | throw ExceptionBase("Lzma: Data is corrupt."); |
108 | 108 | ||
109 | case LZMA_BUF_ERROR: | 109 | case LZMA_BUF_ERROR: |
110 | throw ExceptionBase("Lzma: No progress is possible."); | 110 | throw ExceptionBase("Lzma: No progress is possible."); |
111 | 111 | ||
112 | case LZMA_PROG_ERROR: | 112 | case LZMA_PROG_ERROR: |
113 | throw ExceptionBase("Lzma: Programming error."); | 113 | throw ExceptionBase("Lzma: Programming error."); |
114 | 114 | ||
115 | default: | 115 | default: |
116 | throw ExceptionBase("Lzma: Unknown error encountered." ); | 116 | throw ExceptionBase("Lzma: Unknown error encountered." ); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) | 120 | Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) |
121 | { | 121 | { |
122 | TRACE( pData, nBytes ); | 122 | TRACE( pData, nBytes ); |
123 | if( !pState ) | 123 | if( !pState ) |
124 | { | 124 | { |
125 | prState = new ::lzma_stream; | 125 | prState = new ::lzma_stream; |
126 | lzma_stream zEmpty = LZMA_STREAM_INIT; | 126 | lzma_stream zEmpty = LZMA_STREAM_INIT; |
127 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); | 127 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); |
128 | 128 | ||
129 | bReading = true; | 129 | bReading = true; |
130 | lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); | 130 | lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); |
131 | pState->next_in = (uint8_t *)pBuf; | 131 | pState->next_in = (uint8_t *)pBuf; |
132 | pState->avail_in = 0; | 132 | pState->avail_in = 0; |
133 | } | 133 | } |
134 | if( bReading == false ) | 134 | if( bReading == false ) |
135 | throw ExceptionBase("This lzma filter is in writing mode, you can't read."); | 135 | throw ExceptionBase("This lzma filter is in writing mode, you can't read."); |
136 | 136 | ||
137 | int nRead = 0; | 137 | int nRead = 0; |
138 | int nReadTotal = pState->total_out; | 138 | int nReadTotal = pState->total_out; |
139 | pState->next_out = (uint8_t *)pData; | 139 | pState->next_out = (uint8_t *)pData; |
140 | pState->avail_out = nBytes; | 140 | pState->avail_out = nBytes; |
141 | for(;;) | 141 | for(;;) |
142 | { | 142 | { |
143 | int ret = lzma_code( pState, LZMA_RUN ); | 143 | int ret = lzma_code( pState, LZMA_RUN ); |
144 | // printf("inflate returned %d; avail in=%d, out=%d\n", ret, | 144 | // printf("inflate returned %d; avail in=%d, out=%d\n", ret, |
145 | // pState->avail_in, pState->avail_out ); | 145 | // pState->avail_in, pState->avail_out ); |
146 | 146 | ||
147 | nReadTotal += nRead-pState->avail_out; | 147 | nReadTotal += nRead-pState->avail_out; |
148 | 148 | ||
149 | if( ret == LZMA_STREAM_END ) | 149 | if( ret == LZMA_STREAM_END ) |
150 | { | 150 | { |
151 | bEos = true; | 151 | bEos = true; |
152 | if( pState->avail_in > 0 ) | 152 | if( pState->avail_in > 0 ) |
153 | { | 153 | { |
154 | if( rNext.isSeekable() ) | 154 | if( rNext.isSeekable() ) |
155 | { | 155 | { |
156 | rNext.seek( -pState->avail_in ); | 156 | rNext.seek( -pState->avail_in ); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | return nBytes-pState->avail_out; | 159 | return nBytes-pState->avail_out; |
160 | } | 160 | } |
161 | // if( ret != LZMA_BUF_ERROR ) | 161 | // if( ret != LZMA_BUF_ERROR ) |
162 | lzmaError( ret ); | 162 | lzmaError( ret ); |
163 | 163 | ||
164 | if( pState->avail_out ) | 164 | if( pState->avail_out ) |
165 | { | 165 | { |
166 | if( pState->avail_in == 0 ) | 166 | if( pState->avail_in == 0 ) |
167 | { | 167 | { |
168 | nRead = rNext.read( pBuf, nBufSize ); | 168 | nRead = rNext.read( pBuf, nBufSize ); |
169 | if( nRead == 0 && rNext.isEos() ) | 169 | if( nRead == 0 && rNext.isEos() ) |
170 | { | 170 | { |
171 | throw Bu::ExceptionBase("Premature end of underlying " | 171 | throw Bu::ExceptionBase("Premature end of underlying " |
172 | "stream found reading deflate stream."); | 172 | "stream found reading deflate stream."); |
173 | } | 173 | } |
174 | pState->next_in = (uint8_t *)pBuf; | 174 | pState->next_in = (uint8_t *)pBuf; |
175 | pState->avail_in = nRead; | 175 | pState->avail_in = nRead; |
176 | } | 176 | } |
177 | } | 177 | } |
178 | else | 178 | else |
179 | { | 179 | { |
180 | return nBytes-pState->avail_out; | 180 | return nBytes-pState->avail_out; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | return 0; | 183 | return 0; |
184 | } | 184 | } |
185 | 185 | ||
186 | Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) | 186 | Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) |
187 | { | 187 | { |
188 | TRACE( pData, nBytes ); | 188 | TRACE( pData, nBytes ); |
189 | if( !pState ) | 189 | if( !pState ) |
190 | { | 190 | { |
191 | prState = new ::lzma_stream; | 191 | prState = new ::lzma_stream; |
192 | lzma_stream zEmpty = LZMA_STREAM_INIT; | 192 | lzma_stream zEmpty = LZMA_STREAM_INIT; |
193 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); | 193 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); |
194 | 194 | ||
195 | bReading = false; | 195 | bReading = false; |
196 | if( eFmt == Xz ) | 196 | if( eFmt == Xz ) |
197 | lzmaError( | 197 | lzmaError( |
198 | lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) | 198 | lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) |
199 | ); | 199 | ); |
200 | else if( eFmt == LzmaAlone ) | 200 | else if( eFmt == LzmaAlone ) |
201 | { | 201 | { |
202 | lzma_options_lzma opt; | 202 | lzma_options_lzma opt; |
203 | lzma_lzma_preset( &opt, nCompression ); | 203 | lzma_lzma_preset( &opt, nCompression ); |
204 | lzmaError( lzma_alone_encoder( pState, &opt ) ); | 204 | lzmaError( lzma_alone_encoder( pState, &opt ) ); |
205 | } | 205 | } |
206 | else | 206 | else |
207 | throw Bu::ExceptionBase("Invalid format for lzma."); | 207 | throw Bu::ExceptionBase("Invalid format for lzma."); |
208 | } | 208 | } |
209 | if( bReading == true ) | 209 | if( bReading == true ) |
210 | throw ExceptionBase("This lzma filter is in reading mode, you can't write."); | 210 | throw ExceptionBase("This lzma filter is in reading mode, you can't write."); |
211 | 211 | ||
212 | pState->next_in = (uint8_t *)pData; | 212 | pState->next_in = (uint8_t *)pData; |
213 | pState->avail_in = nBytes; | 213 | pState->avail_in = nBytes; |
214 | for(;;) | 214 | for(;;) |
215 | { | 215 | { |
216 | pState->avail_out = nBufSize; | 216 | pState->avail_out = nBufSize; |
217 | pState->next_out = (uint8_t *)pBuf; | 217 | pState->next_out = (uint8_t *)pBuf; |
218 | 218 | ||
219 | lzmaError( lzma_code( pState, LZMA_RUN ) ); | 219 | lzmaError( lzma_code( pState, LZMA_RUN ) ); |
220 | 220 | ||
221 | if( pState->avail_out < nBufSize ) | 221 | if( pState->avail_out < nBufSize ) |
222 | { | 222 | { |
223 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 223 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
224 | } | 224 | } |
225 | if( pState->avail_in == 0 ) | 225 | if( pState->avail_in == 0 ) |
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | 228 | ||
229 | return nBytes; | 229 | return nBytes; |
230 | } | 230 | } |
231 | 231 | ||
232 | bool Bu::Lzma::isOpen() | 232 | bool Bu::Lzma::isOpen() |
233 | { | 233 | { |
234 | TRACE(); | 234 | TRACE(); |
235 | return (pState != NULL); | 235 | return (pState != NULL); |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::Lzma::isEos() | 238 | bool Bu::Lzma::isEos() |
239 | { | 239 | { |
240 | TRACE(); | 240 | TRACE(); |
241 | return bEos; | 241 | return bEos; |
242 | } | 242 | } |
243 | 243 | ||
244 | Bu::size Bu::Lzma::getCompressedSize() | 244 | Bu::size Bu::Lzma::getCompressedSize() |
245 | { | 245 | { |
246 | return sTotalOut; | 246 | return sTotalOut; |
247 | } | 247 | } |
248 | 248 | ||
diff --git a/src/stable/lzma.h b/src/stable/lzma.h index 7118a6b..40963cc 100644 --- a/src/stable/lzma.h +++ b/src/stable/lzma.h | |||
@@ -14,46 +14,46 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as | 18 | * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as |
19 | * well as the newer LZMA2 (xz) format. This uses .xz by default. | 19 | * well as the newer LZMA2 (xz) format. This uses .xz by default. |
20 | * | 20 | * |
21 | *@ingroup Streams | 21 | *@ingroup Streams |
22 | *@ingroup Compression | 22 | *@ingroup Compression |
23 | */ | 23 | */ |
24 | class Lzma : public Bu::Filter | 24 | class Lzma : public Bu::Filter |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | enum Format | 27 | enum Format |
28 | { | 28 | { |
29 | Xz = 0x01, | 29 | Xz = 0x01, |
30 | LzmaAlone = 0x02, | 30 | LzmaAlone = 0x02, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); | 33 | Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); |
34 | virtual ~Lzma(); | 34 | virtual ~Lzma(); |
35 | 35 | ||
36 | virtual void start(); | 36 | virtual void start(); |
37 | virtual Bu::size stop(); | 37 | virtual Bu::size stop(); |
38 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 38 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
39 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 39 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
40 | 40 | ||
41 | virtual bool isOpen(); | 41 | virtual bool isOpen(); |
42 | virtual bool isEos(); | 42 | virtual bool isEos(); |
43 | 43 | ||
44 | Bu::size getCompressedSize(); | 44 | Bu::size getCompressedSize(); |
45 | 45 | ||
46 | private: | 46 | private: |
47 | void lzmaError( int code ); | 47 | void lzmaError( int code ); |
48 | void *prState; | 48 | void *prState; |
49 | bool bReading; | 49 | bool bReading; |
50 | int nCompression; | 50 | int nCompression; |
51 | char *pBuf; | 51 | char *pBuf; |
52 | uint32_t nBufSize; | 52 | uint32_t nBufSize; |
53 | Bu::size sTotalOut; | 53 | Bu::size sTotalOut; |
54 | Format eFmt; | 54 | Format eFmt; |
55 | bool bEos; | 55 | bool bEos; |
56 | }; | 56 | }; |
57 | } | 57 | } |
58 | 58 | ||
59 | #endif | 59 | #endif |
diff --git a/src/stable/md5.cpp b/src/stable/md5.cpp index c1d993f..e62cbf4 100644 --- a/src/stable/md5.cpp +++ b/src/stable/md5.cpp | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | Bu::Md5::Md5() | 20 | Bu::Md5::Md5() |
21 | { | 21 | { |
22 | reset(); | 22 | reset(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::Md5::~Md5() | 25 | Bu::Md5::~Md5() |
@@ -28,15 +28,15 @@ Bu::Md5::~Md5() | |||
28 | 28 | ||
29 | void Bu::Md5::reset() | 29 | void Bu::Md5::reset() |
30 | { | 30 | { |
31 | // These are the magic seed numbers... | 31 | // These are the magic seed numbers... |
32 | 32 | ||
33 | sum[0] = 0x67452301U; | 33 | sum[0] = 0x67452301U; |
34 | sum[1] = 0xEFCDAB89U; | 34 | sum[1] = 0xEFCDAB89U; |
35 | sum[2] = 0x98BADCFEU; | 35 | sum[2] = 0x98BADCFEU; |
36 | sum[3] = 0x10325476U; | 36 | sum[3] = 0x10325476U; |
37 | 37 | ||
38 | uBits[0] = 0; | 38 | uBits[0] = 0; |
39 | uBits[1] = 0; | 39 | uBits[1] = 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) | 42 | void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -45,102 +45,102 @@ void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) | |||
45 | 45 | ||
46 | void Bu::Md5::addData( const void *sVData, int iSize ) | 46 | void Bu::Md5::addData( const void *sVData, int iSize ) |
47 | { | 47 | { |
48 | const char *sData = (const char *)sVData; | 48 | const char *sData = (const char *)sVData; |
49 | uint32_t t; | 49 | uint32_t t; |
50 | 50 | ||
51 | t = uBits[0]; | 51 | t = uBits[0]; |
52 | if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) | 52 | if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) |
53 | uBits[1]++; | 53 | uBits[1]++; |
54 | uBits[1] += iSize >> 29; | 54 | uBits[1] += iSize >> 29; |
55 | 55 | ||
56 | t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ | 56 | t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ |
57 | 57 | ||
58 | /* Handle any leading odd-sized chunks */ | 58 | /* Handle any leading odd-sized chunks */ |
59 | if( t ) | 59 | if( t ) |
60 | { | 60 | { |
61 | unsigned char *p = (unsigned char *) inbuf + t; | 61 | unsigned char *p = (unsigned char *) inbuf + t; |
62 | 62 | ||
63 | t = 64 - t; | 63 | t = 64 - t; |
64 | if( (uint32_t)iSize < t ) { | 64 | if( (uint32_t)iSize < t ) { |
65 | memcpy( p, sData, iSize ); | 65 | memcpy( p, sData, iSize ); |
66 | return; | 66 | return; |
67 | } | 67 | } |
68 | memcpy( p, sData, t ); | 68 | memcpy( p, sData, t ); |
69 | toLittleEndian( inbuf, 16 ); | 69 | toLittleEndian( inbuf, 16 ); |
70 | compBlock( sum, (uint32_t *)inbuf ); | 70 | compBlock( sum, (uint32_t *)inbuf ); |
71 | sData += t; | 71 | sData += t; |
72 | iSize -= t; | 72 | iSize -= t; |
73 | } | 73 | } |
74 | 74 | ||
75 | /* Process data in 64-byte chunks */ | 75 | /* Process data in 64-byte chunks */ |
76 | while( iSize >= 64 ) | 76 | while( iSize >= 64 ) |
77 | { | 77 | { |
78 | memcpy( inbuf, sData, 64 ); | 78 | memcpy( inbuf, sData, 64 ); |
79 | toLittleEndian( inbuf, 16 ); | 79 | toLittleEndian( inbuf, 16 ); |
80 | compBlock( sum, (uint32_t *)inbuf ); | 80 | compBlock( sum, (uint32_t *)inbuf ); |
81 | sData += 64; | 81 | sData += 64; |
82 | iSize -= 64; | 82 | iSize -= 64; |
83 | } | 83 | } |
84 | 84 | ||
85 | /* Handle any remaining bytes of data. */ | 85 | /* Handle any remaining bytes of data. */ |
86 | memcpy( inbuf, sData, iSize ); | 86 | memcpy( inbuf, sData, iSize ); |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::String Bu::Md5::getResult() | 89 | Bu::String Bu::Md5::getResult() |
90 | { | 90 | { |
91 | uint32_t lsum[4]; | 91 | uint32_t lsum[4]; |
92 | compCap( lsum ); | 92 | compCap( lsum ); |
93 | return Bu::String( (const char *)lsum, 4*4 ); | 93 | return Bu::String( (const char *)lsum, 4*4 ); |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::Md5::writeResult( Bu::Stream &sOut ) | 96 | void Bu::Md5::writeResult( Bu::Stream &sOut ) |
97 | { | 97 | { |
98 | uint32_t lsum[4]; | 98 | uint32_t lsum[4]; |
99 | compCap( lsum ); | 99 | compCap( lsum ); |
100 | sOut.write( lsum, 4*4 ); | 100 | sOut.write( lsum, 4*4 ); |
101 | } | 101 | } |
102 | 102 | ||
103 | void Bu::Md5::compCap( uint32_t *sumout ) | 103 | void Bu::Md5::compCap( uint32_t *sumout ) |
104 | { | 104 | { |
105 | uint8_t tmpbuf[64]; | 105 | uint8_t tmpbuf[64]; |
106 | memcpy( sumout, sum, 4*4 ); | 106 | memcpy( sumout, sum, 4*4 ); |
107 | memcpy( tmpbuf, inbuf, 64 ); | 107 | memcpy( tmpbuf, inbuf, 64 ); |
108 | 108 | ||
109 | uint32_t count; | 109 | uint32_t count; |
110 | uint8_t *p; | 110 | uint8_t *p; |
111 | 111 | ||
112 | /* Compute number of bytes mod 64 */ | 112 | /* Compute number of bytes mod 64 */ |
113 | count = (uBits[0] >> 3) & 0x3F; | 113 | count = (uBits[0] >> 3) & 0x3F; |
114 | 114 | ||
115 | /* Set the first char of padding to 0x80. This is safe since there is | 115 | /* Set the first char of padding to 0x80. This is safe since there is |
116 | always at least one byte free */ | 116 | always at least one byte free */ |
117 | p = tmpbuf + count; | 117 | p = tmpbuf + count; |
118 | *p++ = 0x80; | 118 | *p++ = 0x80; |
119 | 119 | ||
120 | /* Bytes of padding needed to make 64 bytes */ | 120 | /* Bytes of padding needed to make 64 bytes */ |
121 | count = 64 - 1 - count; | 121 | count = 64 - 1 - count; |
122 | 122 | ||
123 | /* Pad out to 56 mod 64 */ | 123 | /* Pad out to 56 mod 64 */ |
124 | if (count < 8) { | 124 | if (count < 8) { |
125 | /* Two lots of padding: Pad the first block to 64 bytes */ | 125 | /* Two lots of padding: Pad the first block to 64 bytes */ |
126 | memset( p, 0, count ); | 126 | memset( p, 0, count ); |
127 | toLittleEndian( tmpbuf, 16 ); | 127 | toLittleEndian( tmpbuf, 16 ); |
128 | compBlock( sumout, (uint32_t *)tmpbuf ); | 128 | compBlock( sumout, (uint32_t *)tmpbuf ); |
129 | 129 | ||
130 | /* Now fill the next block with 56 bytes */ | 130 | /* Now fill the next block with 56 bytes */ |
131 | memset( tmpbuf, 0, 56); | 131 | memset( tmpbuf, 0, 56); |
132 | } else { | 132 | } else { |
133 | /* Pad block to 56 bytes */ | 133 | /* Pad block to 56 bytes */ |
134 | memset( p, 0, count - 8); | 134 | memset( p, 0, count - 8); |
135 | } | 135 | } |
136 | toLittleEndian( tmpbuf, 14 ); | 136 | toLittleEndian( tmpbuf, 14 ); |
137 | 137 | ||
138 | /* Append length in bits and transform */ | 138 | /* Append length in bits and transform */ |
139 | ((uint32_t *) tmpbuf)[14] = uBits[0]; | 139 | ((uint32_t *) tmpbuf)[14] = uBits[0]; |
140 | ((uint32_t *) tmpbuf)[15] = uBits[1]; | 140 | ((uint32_t *) tmpbuf)[15] = uBits[1]; |
141 | 141 | ||
142 | compBlock( sumout, (uint32_t *)tmpbuf ); | 142 | compBlock( sumout, (uint32_t *)tmpbuf ); |
143 | toLittleEndian((unsigned char *)sumout, 4); | 143 | toLittleEndian((unsigned char *)sumout, 4); |
144 | } | 144 | } |
145 | 145 | ||
146 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | 146 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
@@ -150,15 +150,15 @@ void Bu::Md5::compCap( uint32_t *sumout ) | |||
150 | 150 | ||
151 | /* This is the central step in the MD5 algorithm. */ | 151 | /* This is the central step in the MD5 algorithm. */ |
152 | #define MD5STEP(f, w, x, y, z, data, s) \ | 152 | #define MD5STEP(f, w, x, y, z, data, s) \ |
153 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | 153 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) |
154 | 154 | ||
155 | void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) | 155 | void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) |
156 | { | 156 | { |
157 | register uint32_t a, b, c, d; | 157 | register uint32_t a, b, c, d; |
158 | a = lsum[0]; | 158 | a = lsum[0]; |
159 | b = lsum[1]; | 159 | b = lsum[1]; |
160 | c = lsum[2]; | 160 | c = lsum[2]; |
161 | d = lsum[3]; | 161 | d = lsum[3]; |
162 | 162 | ||
163 | MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7); | 163 | MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7); |
164 | MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12); | 164 | MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12); |
@@ -228,19 +228,19 @@ void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) | |||
228 | MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15); | 228 | MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15); |
229 | MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21); | 229 | MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21); |
230 | 230 | ||
231 | lsum[0] += a; | 231 | lsum[0] += a; |
232 | lsum[1] += b; | 232 | lsum[1] += b; |
233 | lsum[2] += c; | 233 | lsum[2] += c; |
234 | lsum[3] += d; | 234 | lsum[3] += d; |
235 | } | 235 | } |
236 | 236 | ||
237 | void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) | 237 | void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) |
238 | { | 238 | { |
239 | uint32_t t; | 239 | uint32_t t; |
240 | do { | 240 | do { |
241 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | | 241 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | |
242 | ((unsigned) buf[1] << 8 | buf[0]); | 242 | ((unsigned) buf[1] << 8 | buf[0]); |
243 | *(uint32_t *) buf = t; | 243 | *(uint32_t *) buf = t; |
244 | buf += 4; | 244 | buf += 4; |
245 | } while( --count ); | 245 | } while( --count ); |
246 | } | 246 | } |
diff --git a/src/stable/md5.h b/src/stable/md5.h index cb7d396..8845082 100644 --- a/src/stable/md5.h +++ b/src/stable/md5.h | |||
@@ -12,43 +12,43 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Class for easily calculating MD5 sums of just about any data. | 16 | * Class for easily calculating MD5 sums of just about any data. |
17 | * This code is based on some public domain code written by Colin Plumb in | 17 | * This code is based on some public domain code written by Colin Plumb in |
18 | * 1993. | 18 | * 1993. |
19 | *@author Mike Buland | 19 | *@author Mike Buland |
20 | */ | 20 | */ |
21 | class Md5 : public Bu::CryptoHash | 21 | class Md5 : public Bu::CryptoHash |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | /** Build an MD5 sum builder. */ | 24 | /** Build an MD5 sum builder. */ |
25 | Md5(); | 25 | Md5(); |
26 | 26 | ||
27 | /** Deconstruct */ | 27 | /** Deconstruct */ |
28 | virtual ~Md5(); | 28 | virtual ~Md5(); |
29 | 29 | ||
30 | virtual void reset(); | 30 | virtual void reset(); |
31 | virtual void setSalt( const Bu::String &sSalt ); | 31 | virtual void setSalt( const Bu::String &sSalt ); |
32 | virtual void addData( const void *sData, int iSize ); | 32 | virtual void addData( const void *sData, int iSize ); |
33 | using Bu::CryptoHash::addData; | 33 | using Bu::CryptoHash::addData; |
34 | virtual String getResult(); | 34 | virtual String getResult(); |
35 | virtual void writeResult( Bu::Stream &sOut ); | 35 | virtual void writeResult( Bu::Stream &sOut ); |
36 | 36 | ||
37 | private: | 37 | private: |
38 | /** | 38 | /** |
39 | * Compute one block of input data. | 39 | * Compute one block of input data. |
40 | */ | 40 | */ |
41 | void compBlock( uint32_t *lsum, uint32_t *x ); | 41 | void compBlock( uint32_t *lsum, uint32_t *x ); |
42 | void compCap( uint32_t *sumout ); | 42 | void compCap( uint32_t *sumout ); |
43 | 43 | ||
44 | void _addData( uint8_t *target, int &iCurFill, const void *sData, | 44 | void _addData( uint8_t *target, int &iCurFill, const void *sData, |
45 | int iSize ); | 45 | int iSize ); |
46 | void _toLittleEndian( uint8_t *buf, uint32_t count ); | 46 | void _toLittleEndian( uint8_t *buf, uint32_t count ); |
47 | 47 | ||
48 | uint8_t inbuf[64]; | 48 | uint8_t inbuf[64]; |
49 | uint32_t sum[4]; | 49 | uint32_t sum[4]; |
50 | uint32_t uBits[2]; | 50 | uint32_t uBits[2]; |
51 | }; | 51 | }; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #endif | 54 | #endif |
diff --git a/src/stable/membuf.cpp b/src/stable/membuf.cpp index dea9a0e..4d6e8e6 100644 --- a/src/stable/membuf.cpp +++ b/src/stable/membuf.cpp | |||
@@ -10,13 +10,13 @@ | |||
10 | using namespace Bu; | 10 | using namespace Bu; |
11 | 11 | ||
12 | Bu::MemBuf::MemBuf() : | 12 | Bu::MemBuf::MemBuf() : |
13 | nPos( 0 ) | 13 | nPos( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::MemBuf::MemBuf( const Bu::String &str ) : | 17 | Bu::MemBuf::MemBuf( const Bu::String &str ) : |
18 | sBuf( str ), | 18 | sBuf( str ), |
19 | nPos( 0 ) | 19 | nPos( 0 ) |
20 | { | 20 | { |
21 | } | 21 | } |
22 | 22 | ||
@@ -30,76 +30,76 @@ void Bu::MemBuf::close() | |||
30 | 30 | ||
31 | size Bu::MemBuf::read( void *pBuf, size nBytes ) | 31 | size Bu::MemBuf::read( void *pBuf, size nBytes ) |
32 | { | 32 | { |
33 | if( (size)sBuf.getSize()-(size)nPos < nBytes ) | 33 | if( (size)sBuf.getSize()-(size)nPos < nBytes ) |
34 | nBytes = sBuf.getSize()-nPos; | 34 | nBytes = sBuf.getSize()-nPos; |
35 | 35 | ||
36 | memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); | 36 | memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); |
37 | nPos += nBytes; | 37 | nPos += nBytes; |
38 | 38 | ||
39 | return nBytes; | 39 | return nBytes; |
40 | } | 40 | } |
41 | 41 | ||
42 | size Bu::MemBuf::write( const void *pBuf, size nBytes ) | 42 | size Bu::MemBuf::write( const void *pBuf, size nBytes ) |
43 | { | 43 | { |
44 | if( nPos == sBuf.getSize() ) | 44 | if( nPos == sBuf.getSize() ) |
45 | { | 45 | { |
46 | // Easiest, just append the data. | 46 | // Easiest, just append the data. |
47 | sBuf.append( (const char *)pBuf, nBytes ); | 47 | sBuf.append( (const char *)pBuf, nBytes ); |
48 | nPos += nBytes; | 48 | nPos += nBytes; |
49 | return nBytes; | 49 | return nBytes; |
50 | } | 50 | } |
51 | else | 51 | else |
52 | { | 52 | { |
53 | // Trickier, we must do this in two parts, overwrite, then append | 53 | // Trickier, we must do this in two parts, overwrite, then append |
54 | // Frist, overwrite. | 54 | // Frist, overwrite. |
55 | size iOver = sBuf.getSize() - nPos; | 55 | size iOver = sBuf.getSize() - nPos; |
56 | if( iOver > nBytes ) | 56 | if( iOver > nBytes ) |
57 | iOver = nBytes; | 57 | iOver = nBytes; |
58 | memcpy( sBuf.getStr()+nPos, pBuf, iOver ); | 58 | memcpy( sBuf.getStr()+nPos, pBuf, iOver ); |
59 | // Then append | 59 | // Then append |
60 | if( iOver < nBytes ) | 60 | if( iOver < nBytes ) |
61 | { | 61 | { |
62 | sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); | 62 | sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); |
63 | } | 63 | } |
64 | nPos += nBytes; | 64 | nPos += nBytes; |
65 | return nBytes; | 65 | return nBytes; |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | size Bu::MemBuf::tell() | 69 | size Bu::MemBuf::tell() |
70 | { | 70 | { |
71 | return nPos; | 71 | return nPos; |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::MemBuf::seek( size offset ) | 74 | void Bu::MemBuf::seek( size offset ) |
75 | { | 75 | { |
76 | nPos += offset; | 76 | nPos += offset; |
77 | if( nPos < 0 ) nPos = 0; | 77 | if( nPos < 0 ) nPos = 0; |
78 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 78 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
79 | } | 79 | } |
80 | 80 | ||
81 | void Bu::MemBuf::setPos( size pos ) | 81 | void Bu::MemBuf::setPos( size pos ) |
82 | { | 82 | { |
83 | nPos = pos; | 83 | nPos = pos; |
84 | if( nPos < 0 ) nPos = 0; | 84 | if( nPos < 0 ) nPos = 0; |
85 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 85 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
86 | } | 86 | } |
87 | 87 | ||
88 | void Bu::MemBuf::setPosEnd( size pos ) | 88 | void Bu::MemBuf::setPosEnd( size pos ) |
89 | { | 89 | { |
90 | nPos = sBuf.getSize()-pos; | 90 | nPos = sBuf.getSize()-pos; |
91 | if( nPos < 0 ) nPos = 0; | 91 | if( nPos < 0 ) nPos = 0; |
92 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 92 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::MemBuf::isEos() | 95 | bool Bu::MemBuf::isEos() |
96 | { | 96 | { |
97 | return (nPos == sBuf.getSize()); | 97 | return (nPos == sBuf.getSize()); |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::MemBuf::isOpen() | 100 | bool Bu::MemBuf::isOpen() |
101 | { | 101 | { |
102 | return true; | 102 | return true; |
103 | } | 103 | } |
104 | 104 | ||
105 | void Bu::MemBuf::flush() | 105 | void Bu::MemBuf::flush() |
@@ -108,32 +108,32 @@ void Bu::MemBuf::flush() | |||
108 | 108 | ||
109 | bool Bu::MemBuf::canRead() | 109 | bool Bu::MemBuf::canRead() |
110 | { | 110 | { |
111 | return !isEos(); | 111 | return !isEos(); |
112 | } | 112 | } |
113 | 113 | ||
114 | bool Bu::MemBuf::canWrite() | 114 | bool Bu::MemBuf::canWrite() |
115 | { | 115 | { |
116 | return true; | 116 | return true; |
117 | } | 117 | } |
118 | 118 | ||
119 | bool Bu::MemBuf::isReadable() | 119 | bool Bu::MemBuf::isReadable() |
120 | { | 120 | { |
121 | return true; | 121 | return true; |
122 | } | 122 | } |
123 | 123 | ||
124 | bool Bu::MemBuf::isWritable() | 124 | bool Bu::MemBuf::isWritable() |
125 | { | 125 | { |
126 | return true; | 126 | return true; |
127 | } | 127 | } |
128 | 128 | ||
129 | bool Bu::MemBuf::isSeekable() | 129 | bool Bu::MemBuf::isSeekable() |
130 | { | 130 | { |
131 | return true; | 131 | return true; |
132 | } | 132 | } |
133 | 133 | ||
134 | bool Bu::MemBuf::isBlocking() | 134 | bool Bu::MemBuf::isBlocking() |
135 | { | 135 | { |
136 | return true; | 136 | return true; |
137 | } | 137 | } |
138 | 138 | ||
139 | void Bu::MemBuf::setBlocking( bool ) | 139 | void Bu::MemBuf::setBlocking( bool ) |
@@ -142,36 +142,36 @@ void Bu::MemBuf::setBlocking( bool ) | |||
142 | 142 | ||
143 | void Bu::MemBuf::setSize( size iSize ) | 143 | void Bu::MemBuf::setSize( size iSize ) |
144 | { | 144 | { |
145 | if( iSize < 0 ) | 145 | if( iSize < 0 ) |
146 | iSize = 0; | 146 | iSize = 0; |
147 | sBuf.setSize( iSize ); | 147 | sBuf.setSize( iSize ); |
148 | if( nPos > iSize ) | 148 | if( nPos > iSize ) |
149 | nPos = iSize; | 149 | nPos = iSize; |
150 | } | 150 | } |
151 | 151 | ||
152 | Bu::size Bu::MemBuf::getSize() const | 152 | Bu::size Bu::MemBuf::getSize() const |
153 | { | 153 | { |
154 | return sBuf.getSize(); | 154 | return sBuf.getSize(); |
155 | } | 155 | } |
156 | 156 | ||
157 | Bu::size Bu::MemBuf::getBlockSize() const | 157 | Bu::size Bu::MemBuf::getBlockSize() const |
158 | { | 158 | { |
159 | return sBuf.getSize(); | 159 | return sBuf.getSize(); |
160 | } | 160 | } |
161 | 161 | ||
162 | Bu::String Bu::MemBuf::getLocation() const | 162 | Bu::String Bu::MemBuf::getLocation() const |
163 | { | 163 | { |
164 | return ""; | 164 | return ""; |
165 | } | 165 | } |
166 | 166 | ||
167 | Bu::String &Bu::MemBuf::getString() | 167 | Bu::String &Bu::MemBuf::getString() |
168 | { | 168 | { |
169 | return sBuf; | 169 | return sBuf; |
170 | } | 170 | } |
171 | 171 | ||
172 | void Bu::MemBuf::setString( const Bu::String &sNewData ) | 172 | void Bu::MemBuf::setString( const Bu::String &sNewData ) |
173 | { | 173 | { |
174 | sBuf = sNewData; | 174 | sBuf = sNewData; |
175 | nPos = 0; | 175 | nPos = 0; |
176 | } | 176 | } |
177 | 177 | ||
diff --git a/src/stable/membuf.h b/src/stable/membuf.h index f016974..f36e0bc 100644 --- a/src/stable/membuf.h +++ b/src/stable/membuf.h | |||
@@ -16,53 +16,53 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * A memory buffer stream. This provides a read/write stream in memory that | 20 | * A memory buffer stream. This provides a read/write stream in memory that |
21 | * works exactly like a file stream...only in memory. You can seed the | 21 | * works exactly like a file stream...only in memory. You can seed the |
22 | * memory buffer with a Bu::String of your own, or start with an empty one. | 22 | * memory buffer with a Bu::String of your own, or start with an empty one. |
23 | * Due to Bu::String using Bu::SharedCore starting with a string will not | 23 | * Due to Bu::String using Bu::SharedCore starting with a string will not |
24 | * necesarilly cause the MemBuf to make a copy of your memory, but if you're | 24 | * necesarilly cause the MemBuf to make a copy of your memory, but if you're |
25 | * sure you're not going to need to change the stream then use StaticMemBuf. | 25 | * sure you're not going to need to change the stream then use StaticMemBuf. |
26 | *@ingroup Streams | 26 | *@ingroup Streams |
27 | */ | 27 | */ |
28 | class MemBuf : public Stream | 28 | class MemBuf : public Stream |
29 | { | 29 | { |
30 | public: | 30 | public: |
31 | MemBuf(); | 31 | MemBuf(); |
32 | MemBuf( const Bu::String &str ); | 32 | MemBuf( const Bu::String &str ); |
33 | virtual ~MemBuf(); | 33 | virtual ~MemBuf(); |
34 | 34 | ||
35 | virtual void close(); | 35 | virtual void close(); |
36 | virtual size read( void *pBuf, size iBytes ); | 36 | virtual size read( void *pBuf, size iBytes ); |
37 | 37 | ||
38 | virtual size write( const void *pBuf, size iBytes ); | 38 | virtual size write( const void *pBuf, size iBytes ); |
39 | using Stream::write; | 39 | using Stream::write; |
40 | virtual size tell(); | 40 | virtual size tell(); |
41 | virtual void seek( size offset ); | 41 | virtual void seek( size offset ); |
42 | virtual void setPos( size pos ); | 42 | virtual void setPos( size pos ); |
43 | virtual void setPosEnd( size pos ); | 43 | virtual void setPosEnd( size pos ); |
44 | virtual bool isEos(); | 44 | virtual bool isEos(); |
45 | virtual bool isOpen(); | 45 | virtual bool isOpen(); |
46 | virtual void flush(); | 46 | virtual void flush(); |
47 | virtual bool canRead(); | 47 | virtual bool canRead(); |
48 | virtual bool canWrite(); | 48 | virtual bool canWrite(); |
49 | virtual bool isReadable(); | 49 | virtual bool isReadable(); |
50 | virtual bool isWritable(); | 50 | virtual bool isWritable(); |
51 | virtual bool isSeekable(); | 51 | virtual bool isSeekable(); |
52 | virtual bool isBlocking(); | 52 | virtual bool isBlocking(); |
53 | virtual void setBlocking( bool bBlocking=true ); | 53 | virtual void setBlocking( bool bBlocking=true ); |
54 | virtual void setSize( size iSize ); | 54 | virtual void setSize( size iSize ); |
55 | virtual size getSize() const; | 55 | virtual size getSize() const; |
56 | virtual size getBlockSize() const; | 56 | virtual size getBlockSize() const; |
57 | virtual Bu::String getLocation() const; | 57 | virtual Bu::String getLocation() const; |
58 | 58 | ||
59 | Bu::String &getString(); | 59 | Bu::String &getString(); |
60 | void setString( const Bu::String &sNewData ); | 60 | void setString( const Bu::String &sNewData ); |
61 | 61 | ||
62 | private: | 62 | private: |
63 | Bu::String sBuf; | 63 | Bu::String sBuf; |
64 | size nPos; | 64 | size nPos; |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/minicron.cpp b/src/stable/minicron.cpp index 87296ae..c83cd44 100644 --- a/src/stable/minicron.cpp +++ b/src/stable/minicron.cpp | |||
@@ -11,260 +11,260 @@ | |||
11 | #include <time.h> | 11 | #include <time.h> |
12 | 12 | ||
13 | Bu::MiniCron::MiniCron() : | 13 | Bu::MiniCron::MiniCron() : |
14 | jidNext( 1 ) | 14 | jidNext( 1 ) |
15 | { | 15 | { |
16 | } | 16 | } |
17 | 17 | ||
18 | Bu::MiniCron::~MiniCron() | 18 | Bu::MiniCron::~MiniCron() |
19 | { | 19 | { |
20 | while( !hJobs.isEmpty() ) | 20 | while( !hJobs.isEmpty() ) |
21 | { | 21 | { |
22 | delete hJobs.dequeue(); | 22 | delete hJobs.dequeue(); |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
26 | bool Bu::MiniCron::hasJobs() | 26 | bool Bu::MiniCron::hasJobs() |
27 | { | 27 | { |
28 | return !hJobs.isEmpty(); | 28 | return !hJobs.isEmpty(); |
29 | } | 29 | } |
30 | 30 | ||
31 | time_t Bu::MiniCron::getNextRun() | 31 | time_t Bu::MiniCron::getNextRun() |
32 | { | 32 | { |
33 | if( hasJobs() ) | 33 | if( hasJobs() ) |
34 | return hJobs.peek()->getNextRun(); | 34 | return hJobs.peek()->getNextRun(); |
35 | return -1; | 35 | return -1; |
36 | } | 36 | } |
37 | 37 | ||
38 | time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) | 38 | time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) |
39 | { | 39 | { |
40 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) | 40 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( (*i)->getId() == jid ) | 42 | if( (*i)->getId() == jid ) |
43 | { | 43 | { |
44 | return (*i)->getNextRunTime(); | 44 | return (*i)->getNextRunTime(); |
45 | } | 45 | } |
46 | } | 46 | } |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
49 | 49 | ||
50 | void Bu::MiniCron::poll() | 50 | void Bu::MiniCron::poll() |
51 | { | 51 | { |
52 | time_t tNow = time( NULL ); | 52 | time_t tNow = time( NULL ); |
53 | 53 | ||
54 | while( !hJobs.isEmpty() ) | 54 | while( !hJobs.isEmpty() ) |
55 | { | 55 | { |
56 | if( hJobs.peek()->getNextRun() <= tNow ) | 56 | if( hJobs.peek()->getNextRun() <= tNow ) |
57 | { | 57 | { |
58 | Job *pJob = hJobs.dequeue(); | 58 | Job *pJob = hJobs.dequeue(); |
59 | pJob->run(); | 59 | pJob->run(); |
60 | if( pJob->bContinue ) | 60 | if( pJob->bContinue ) |
61 | { | 61 | { |
62 | hJobs.enqueue( pJob ); | 62 | hJobs.enqueue( pJob ); |
63 | } | 63 | } |
64 | else | 64 | else |
65 | { | 65 | { |
66 | delete pJob; | 66 | delete pJob; |
67 | } | 67 | } |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | break; | 71 | break; |
72 | } | 72 | } |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, | 76 | Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, |
77 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) | 77 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) |
78 | { | 78 | { |
79 | JobId jid = jidNext++; | 79 | JobId jid = jidNext++; |
80 | Job *pJob = new Job( sName, jid ); | 80 | Job *pJob = new Job( sName, jid ); |
81 | pJob->sigJob = sigJob; | 81 | pJob->sigJob = sigJob; |
82 | pJob->pTimer = t.clone(); | 82 | pJob->pTimer = t.clone(); |
83 | pJob->tNextRun = pJob->pTimer->nextTime(); | 83 | pJob->tNextRun = pJob->pTimer->nextTime(); |
84 | hJobs.enqueue( pJob ); | 84 | hJobs.enqueue( pJob ); |
85 | 85 | ||
86 | return jid; | 86 | return jid; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, | 89 | Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, |
90 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) | 90 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) |
91 | { | 91 | { |
92 | JobId jid = jidNext++; | 92 | JobId jid = jidNext++; |
93 | Job *pJob = new Job( sName, jid, false ); | 93 | Job *pJob = new Job( sName, jid, false ); |
94 | pJob->sigJob = sigJob; | 94 | pJob->sigJob = sigJob; |
95 | pJob->pTimer = t.clone(); | 95 | pJob->pTimer = t.clone(); |
96 | pJob->tNextRun = pJob->pTimer->nextTime(); | 96 | pJob->tNextRun = pJob->pTimer->nextTime(); |
97 | hJobs.enqueue( pJob ); | 97 | hJobs.enqueue( pJob ); |
98 | 98 | ||
99 | return jid; | 99 | return jid; |
100 | } | 100 | } |
101 | 101 | ||
102 | void Bu::MiniCron::removeJob( JobId jid ) | 102 | void Bu::MiniCron::removeJob( JobId jid ) |
103 | { | 103 | { |
104 | Bu::List<Job *> lJobs; | 104 | Bu::List<Job *> lJobs; |
105 | while( !hJobs.isEmpty() ) | 105 | while( !hJobs.isEmpty() ) |
106 | { | 106 | { |
107 | Job *pJob = hJobs.dequeue(); | 107 | Job *pJob = hJobs.dequeue(); |
108 | if( pJob->getId() == jid ) | 108 | if( pJob->getId() == jid ) |
109 | { | 109 | { |
110 | delete pJob; | 110 | delete pJob; |
111 | } | 111 | } |
112 | else | 112 | else |
113 | lJobs.append( pJob ); | 113 | lJobs.append( pJob ); |
114 | } | 114 | } |
115 | 115 | ||
116 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 116 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
117 | { | 117 | { |
118 | hJobs.enqueue( *i ); | 118 | hJobs.enqueue( *i ); |
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) | 122 | void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) |
123 | { | 123 | { |
124 | Bu::List<Job *> lJobs; | 124 | Bu::List<Job *> lJobs; |
125 | while( !hJobs.isEmpty() ) | 125 | while( !hJobs.isEmpty() ) |
126 | { | 126 | { |
127 | Job *pJob = hJobs.dequeue(); | 127 | Job *pJob = hJobs.dequeue(); |
128 | if( pJob->getId() == jid ) | 128 | if( pJob->getId() == jid ) |
129 | { | 129 | { |
130 | pJob->run( bReschedule ); | 130 | pJob->run( bReschedule ); |
131 | if( !pJob->bContinue ) | 131 | if( !pJob->bContinue ) |
132 | { | 132 | { |
133 | delete pJob; | 133 | delete pJob; |
134 | break; | 134 | break; |
135 | } | 135 | } |
136 | lJobs.append( pJob ); | 136 | lJobs.append( pJob ); |
137 | break; | 137 | break; |
138 | } | 138 | } |
139 | lJobs.append( pJob ); | 139 | lJobs.append( pJob ); |
140 | } | 140 | } |
141 | 141 | ||
142 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 142 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
143 | { | 143 | { |
144 | hJobs.enqueue( *i ); | 144 | hJobs.enqueue( *i ); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) | 148 | void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) |
149 | { | 149 | { |
150 | Bu::List<Job *> lJobs; | 150 | Bu::List<Job *> lJobs; |
151 | while( !hJobs.isEmpty() ) | 151 | while( !hJobs.isEmpty() ) |
152 | { | 152 | { |
153 | Job *pJob = hJobs.dequeue(); | 153 | Job *pJob = hJobs.dequeue(); |
154 | if( pJob->getName() == sName ) | 154 | if( pJob->getName() == sName ) |
155 | { | 155 | { |
156 | pJob->run( bReschedule ); | 156 | pJob->run( bReschedule ); |
157 | if( !pJob->bContinue ) | 157 | if( !pJob->bContinue ) |
158 | { | 158 | { |
159 | delete pJob; | 159 | delete pJob; |
160 | break; | 160 | break; |
161 | } | 161 | } |
162 | lJobs.append( pJob ); | 162 | lJobs.append( pJob ); |
163 | break; | 163 | break; |
164 | } | 164 | } |
165 | lJobs.append( pJob ); | 165 | lJobs.append( pJob ); |
166 | } | 166 | } |
167 | 167 | ||
168 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 168 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
169 | { | 169 | { |
170 | hJobs.enqueue( *i ); | 170 | hJobs.enqueue( *i ); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() | 174 | Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() |
175 | { | 175 | { |
176 | JobInfoList lRet; | 176 | JobInfoList lRet; |
177 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) | 177 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) |
178 | { | 178 | { |
179 | lRet.append( | 179 | lRet.append( |
180 | JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) | 180 | JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) |
181 | ); | 181 | ); |
182 | } | 182 | } |
183 | lRet.sort(); | 183 | lRet.sort(); |
184 | return lRet; | 184 | return lRet; |
185 | } | 185 | } |
186 | 186 | ||
187 | Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : | 187 | Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : |
188 | sName( sName ), | 188 | sName( sName ), |
189 | pTimer( NULL ), | 189 | pTimer( NULL ), |
190 | bContinue( bRepeat ), | 190 | bContinue( bRepeat ), |
191 | jid( jid ), | 191 | jid( jid ), |
192 | tAdded( time( NULL ) ), | 192 | tAdded( time( NULL ) ), |
193 | iRunCount( 0 ) | 193 | iRunCount( 0 ) |
194 | { | 194 | { |
195 | } | 195 | } |
196 | 196 | ||
197 | Bu::MiniCron::Job::~Job() | 197 | Bu::MiniCron::Job::~Job() |
198 | { | 198 | { |
199 | delete pTimer; | 199 | delete pTimer; |
200 | pTimer = NULL; | 200 | pTimer = NULL; |
201 | } | 201 | } |
202 | 202 | ||
203 | void Bu::MiniCron::Job::run( bool bReschedule ) | 203 | void Bu::MiniCron::Job::run( bool bReschedule ) |
204 | { | 204 | { |
205 | iRunCount++; | 205 | iRunCount++; |
206 | if( bReschedule ) | 206 | if( bReschedule ) |
207 | tNextRun = pTimer->nextTime(); | 207 | tNextRun = pTimer->nextTime(); |
208 | sigJob( *this ); | 208 | sigJob( *this ); |
209 | } | 209 | } |
210 | 210 | ||
211 | time_t Bu::MiniCron::Job::getNextRun() const | 211 | time_t Bu::MiniCron::Job::getNextRun() const |
212 | { | 212 | { |
213 | return tNextRun; | 213 | return tNextRun; |
214 | } | 214 | } |
215 | 215 | ||
216 | void Bu::MiniCron::Job::calcNextRun() | 216 | void Bu::MiniCron::Job::calcNextRun() |
217 | { | 217 | { |
218 | if( pTimer ) | 218 | if( pTimer ) |
219 | tNextRun = pTimer->nextTime(); | 219 | tNextRun = pTimer->nextTime(); |
220 | } | 220 | } |
221 | 221 | ||
222 | void Bu::MiniCron::Job::setTimer( const Timer &t ) | 222 | void Bu::MiniCron::Job::setTimer( const Timer &t ) |
223 | { | 223 | { |
224 | delete pTimer; | 224 | delete pTimer; |
225 | pTimer = t.clone(); | 225 | pTimer = t.clone(); |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::MiniCron::Job::stop() | 228 | void Bu::MiniCron::Job::stop() |
229 | { | 229 | { |
230 | bContinue = false; | 230 | bContinue = false; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::MiniCron::Job::resume() | 233 | void Bu::MiniCron::Job::resume() |
234 | { | 234 | { |
235 | bContinue = true; | 235 | bContinue = true; |
236 | } | 236 | } |
237 | 237 | ||
238 | Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const | 238 | Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const |
239 | { | 239 | { |
240 | return jid; | 240 | return jid; |
241 | } | 241 | } |
242 | 242 | ||
243 | time_t Bu::MiniCron::Job::getTimeCreated() const | 243 | time_t Bu::MiniCron::Job::getTimeCreated() const |
244 | { | 244 | { |
245 | return tAdded; | 245 | return tAdded; |
246 | } | 246 | } |
247 | 247 | ||
248 | int Bu::MiniCron::Job::getRunCount() const | 248 | int Bu::MiniCron::Job::getRunCount() const |
249 | { | 249 | { |
250 | return iRunCount; | 250 | return iRunCount; |
251 | } | 251 | } |
252 | 252 | ||
253 | time_t Bu::MiniCron::Job::getNextRunTime() const | 253 | time_t Bu::MiniCron::Job::getNextRunTime() const |
254 | { | 254 | { |
255 | return tNextRun; | 255 | return tNextRun; |
256 | } | 256 | } |
257 | 257 | ||
258 | Bu::String Bu::MiniCron::Job::getName() const | 258 | Bu::String Bu::MiniCron::Job::getName() const |
259 | { | 259 | { |
260 | return sName; | 260 | return sName; |
261 | } | 261 | } |
262 | 262 | ||
263 | Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, | 263 | Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, |
264 | time_t tNext ) : | 264 | time_t tNext ) : |
265 | sName( sName ), | 265 | sName( sName ), |
266 | jid( jid ), | 266 | jid( jid ), |
267 | tNext( tNext ) | 267 | tNext( tNext ) |
268 | { | 268 | { |
269 | } | 269 | } |
270 | 270 | ||
@@ -274,7 +274,7 @@ Bu::MiniCron::JobInfo::~JobInfo() | |||
274 | 274 | ||
275 | bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const | 275 | bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const |
276 | { | 276 | { |
277 | return jid < rhs.jid; | 277 | return jid < rhs.jid; |
278 | } | 278 | } |
279 | 279 | ||
280 | Bu::MiniCron::Timer::Timer() | 280 | Bu::MiniCron::Timer::Timer() |
@@ -286,8 +286,8 @@ Bu::MiniCron::Timer::~Timer() | |||
286 | } | 286 | } |
287 | 287 | ||
288 | Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : | 288 | Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : |
289 | tNext( tFirst ), | 289 | tNext( tFirst ), |
290 | tInterval( tInterval ) | 290 | tInterval( tInterval ) |
291 | { | 291 | { |
292 | } | 292 | } |
293 | 293 | ||
@@ -297,14 +297,14 @@ Bu::MiniCron::TimerInterval::~TimerInterval() | |||
297 | 297 | ||
298 | time_t Bu::MiniCron::TimerInterval::nextTime() | 298 | time_t Bu::MiniCron::TimerInterval::nextTime() |
299 | { | 299 | { |
300 | time_t tRet = tNext; | 300 | time_t tRet = tNext; |
301 | tNext += tInterval; | 301 | tNext += tInterval; |
302 | return tRet; | 302 | return tRet; |
303 | } | 303 | } |
304 | 304 | ||
305 | Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : | 305 | Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : |
306 | tLast( -1 ), | 306 | tLast( -1 ), |
307 | sSpec( s ) | 307 | sSpec( s ) |
308 | { | 308 | { |
309 | } | 309 | } |
310 | 310 | ||
@@ -314,164 +314,164 @@ Bu::MiniCron::TimerBasic::~TimerBasic() | |||
314 | 314 | ||
315 | time_t Bu::MiniCron::TimerBasic::nextTime() | 315 | time_t Bu::MiniCron::TimerBasic::nextTime() |
316 | { | 316 | { |
317 | if( tLast == -1 ) | 317 | if( tLast == -1 ) |
318 | tLast = time( NULL ); | 318 | tLast = time( NULL ); |
319 | 319 | ||
320 | Bu::String::const_iterator i = sSpec.begin(); | 320 | Bu::String::const_iterator i = sSpec.begin(); |
321 | switch( lex( i ) ) | 321 | switch( lex( i ) ) |
322 | { | 322 | { |
323 | case tokDaily: | 323 | case tokDaily: |
324 | { | 324 | { |
325 | int iHour = lexInt( i ); | 325 | int iHour = lexInt( i ); |
326 | int iMin = lexInt( i ); | 326 | int iMin = lexInt( i ); |
327 | 327 | ||
328 | struct tm t; | 328 | struct tm t; |
329 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 329 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
330 | if( iHour < t.tm_hour || | 330 | if( iHour < t.tm_hour || |
331 | (iHour == t.tm_hour && iMin <= t.tm_min) ) | 331 | (iHour == t.tm_hour && iMin <= t.tm_min) ) |
332 | { | 332 | { |
333 | t.tm_mday++; | 333 | t.tm_mday++; |
334 | } | 334 | } |
335 | t.tm_hour = iHour; | 335 | t.tm_hour = iHour; |
336 | t.tm_min = iMin; | 336 | t.tm_min = iMin; |
337 | t.tm_sec = 0; | 337 | t.tm_sec = 0; |
338 | tLast = mktime( &t ); | 338 | tLast = mktime( &t ); |
339 | } | 339 | } |
340 | break; | 340 | break; |
341 | 341 | ||
342 | case tokHourly: | 342 | case tokHourly: |
343 | { | 343 | { |
344 | int iMin = lexInt( i ); | 344 | int iMin = lexInt( i ); |
345 | 345 | ||
346 | struct tm t; | 346 | struct tm t; |
347 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 347 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
348 | if( iMin <= t.tm_min ) | 348 | if( iMin <= t.tm_min ) |
349 | t.tm_hour++; | 349 | t.tm_hour++; |
350 | t.tm_min = iMin; | 350 | t.tm_min = iMin; |
351 | t.tm_sec = 0; | 351 | t.tm_sec = 0; |
352 | tLast = mktime( &t ); | 352 | tLast = mktime( &t ); |
353 | } | 353 | } |
354 | break; | 354 | break; |
355 | 355 | ||
356 | case tokWeekly: | 356 | case tokWeekly: |
357 | { | 357 | { |
358 | int iDay = lexInt( i ); | 358 | int iDay = lexInt( i ); |
359 | int iHour = lexInt( i ); | 359 | int iHour = lexInt( i ); |
360 | int iMin = lexInt( i ); | 360 | int iMin = lexInt( i ); |
361 | 361 | ||
362 | struct tm t; | 362 | struct tm t; |
363 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 363 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
364 | if( iDay < t.tm_wday || | 364 | if( iDay < t.tm_wday || |
365 | (iDay == t.tm_wday && iHour < t.tm_hour) || | 365 | (iDay == t.tm_wday && iHour < t.tm_hour) || |
366 | (iDay == t.tm_wday && iHour == t.tm_hour | 366 | (iDay == t.tm_wday && iHour == t.tm_hour |
367 | && iMin <= t.tm_min) ) | 367 | && iMin <= t.tm_min) ) |
368 | { | 368 | { |
369 | if( iDay <= t.tm_wday ) | 369 | if( iDay <= t.tm_wday ) |
370 | t.tm_mday += 7 - (t.tm_wday-iDay); | 370 | t.tm_mday += 7 - (t.tm_wday-iDay); |
371 | else | 371 | else |
372 | t.tm_mday += 7 - (iDay-t.tm_wday); | 372 | t.tm_mday += 7 - (iDay-t.tm_wday); |
373 | } | 373 | } |
374 | else | 374 | else |
375 | { | 375 | { |
376 | t.tm_mday += (iDay-t.tm_wday); | 376 | t.tm_mday += (iDay-t.tm_wday); |
377 | } | 377 | } |
378 | t.tm_hour = iHour; | 378 | t.tm_hour = iHour; |
379 | t.tm_min = iMin; | 379 | t.tm_min = iMin; |
380 | t.tm_sec = 0; | 380 | t.tm_sec = 0; |
381 | tLast = mktime( &t ); | 381 | tLast = mktime( &t ); |
382 | } | 382 | } |
383 | break; | 383 | break; |
384 | 384 | ||
385 | case tokMonthly: | 385 | case tokMonthly: |
386 | break; | 386 | break; |
387 | 387 | ||
388 | case tokYearly: | 388 | case tokYearly: |
389 | break; | 389 | break; |
390 | 390 | ||
391 | default: | 391 | default: |
392 | break; | 392 | break; |
393 | } | 393 | } |
394 | 394 | ||
395 | return tLast; | 395 | return tLast; |
396 | } | 396 | } |
397 | 397 | ||
398 | Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( | 398 | Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( |
399 | Bu::String::const_iterator &i ) | 399 | Bu::String::const_iterator &i ) |
400 | { | 400 | { |
401 | if( !i ) | 401 | if( !i ) |
402 | { | 402 | { |
403 | return tokEos; | 403 | return tokEos; |
404 | } | 404 | } |
405 | 405 | ||
406 | Bu::String::const_iterator b = i; | 406 | Bu::String::const_iterator b = i; |
407 | 407 | ||
408 | for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } | 408 | for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } |
409 | for(; b && *b != ' ' && *b != '\t'; b++ ) { } | 409 | for(; b && *b != ' ' && *b != '\t'; b++ ) { } |
410 | 410 | ||
411 | Bu::String sTok( i, b ); | 411 | Bu::String sTok( i, b ); |
412 | i = b; | 412 | i = b; |
413 | 413 | ||
414 | if( sTok == "daily" ) | 414 | if( sTok == "daily" ) |
415 | return tokDaily; | 415 | return tokDaily; |
416 | else if( sTok == "hourly" ) | 416 | else if( sTok == "hourly" ) |
417 | return tokHourly; | 417 | return tokHourly; |
418 | else if( sTok == "weekly" ) | 418 | else if( sTok == "weekly" ) |
419 | return tokWeekly; | 419 | return tokWeekly; |
420 | else if( sTok == "monthly" ) | 420 | else if( sTok == "monthly" ) |
421 | return tokMonthly; | 421 | return tokMonthly; |
422 | else if( sTok == "yearly" ) | 422 | else if( sTok == "yearly" ) |
423 | return tokYearly; | 423 | return tokYearly; |
424 | else if( sTok == "sun" ) | 424 | else if( sTok == "sun" ) |
425 | { | 425 | { |
426 | iVal = 0; | 426 | iVal = 0; |
427 | return valInt; | 427 | return valInt; |
428 | } | 428 | } |
429 | else if( sTok == "mon" ) | 429 | else if( sTok == "mon" ) |
430 | { | 430 | { |
431 | iVal = 1; | 431 | iVal = 1; |
432 | return valInt; | 432 | return valInt; |
433 | } | 433 | } |
434 | else if( sTok == "tue" ) | 434 | else if( sTok == "tue" ) |
435 | { | 435 | { |
436 | iVal = 2; | 436 | iVal = 2; |
437 | return valInt; | 437 | return valInt; |
438 | } | 438 | } |
439 | else if( sTok == "wed" ) | 439 | else if( sTok == "wed" ) |
440 | { | 440 | { |
441 | iVal = 3; | 441 | iVal = 3; |
442 | return valInt; | 442 | return valInt; |
443 | } | 443 | } |
444 | else if( sTok == "thu" ) | 444 | else if( sTok == "thu" ) |
445 | { | 445 | { |
446 | iVal = 4; | 446 | iVal = 4; |
447 | return valInt; | 447 | return valInt; |
448 | } | 448 | } |
449 | else if( sTok == "fri" ) | 449 | else if( sTok == "fri" ) |
450 | { | 450 | { |
451 | iVal = 5; | 451 | iVal = 5; |
452 | return valInt; | 452 | return valInt; |
453 | } | 453 | } |
454 | else if( sTok == "sat" ) | 454 | else if( sTok == "sat" ) |
455 | { | 455 | { |
456 | iVal = 6; | 456 | iVal = 6; |
457 | return valInt; | 457 | return valInt; |
458 | } | 458 | } |
459 | else if( sTok[0] >= '0' && sTok[0] <= '9' ) | 459 | else if( sTok[0] >= '0' && sTok[0] <= '9' ) |
460 | { | 460 | { |
461 | iVal = strtol( sTok.getStr(), NULL, 0 ); | 461 | iVal = strtol( sTok.getStr(), NULL, 0 ); |
462 | return valInt; | 462 | return valInt; |
463 | } | 463 | } |
464 | 464 | ||
465 | return tokErr; | 465 | return tokErr; |
466 | } | 466 | } |
467 | 467 | ||
468 | int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) | 468 | int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) |
469 | { | 469 | { |
470 | Token t = lex( i ); | 470 | Token t = lex( i ); |
471 | if( t == tokEos ) | 471 | if( t == tokEos ) |
472 | return 0; | 472 | return 0; |
473 | if( t != valInt ) | 473 | if( t != valInt ) |
474 | throw Bu::ExceptionBase("Expected int, got something else."); | 474 | throw Bu::ExceptionBase("Expected int, got something else."); |
475 | return iVal; | 475 | return iVal; |
476 | } | 476 | } |
477 | 477 | ||
diff --git a/src/stable/minicron.h b/src/stable/minicron.h index 53e5156..953b82a 100644 --- a/src/stable/minicron.h +++ b/src/stable/minicron.h | |||
@@ -16,321 +16,321 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * A simple cron like system designed to be embedded in any program. This | 20 | * A simple cron like system designed to be embedded in any program. This |
21 | * class creates a simple cron system that can run any number of jobs at | 21 | * class creates a simple cron system that can run any number of jobs at |
22 | * customizable intervals or schedules. It does not support some of the | 22 | * customizable intervals or schedules. It does not support some of the |
23 | * more complex scheduling that some cron systems can do such as load | 23 | * more complex scheduling that some cron systems can do such as load |
24 | * balancing directly, but this could be done on the job side. | 24 | * balancing directly, but this could be done on the job side. |
25 | * | 25 | * |
26 | * This system is synchronous, it does not use any threads on it's own, but | 26 | * This system is synchronous, it does not use any threads on it's own, but |
27 | * it is threadsafe, so a cron thread could be created if desired. | 27 | * it is threadsafe, so a cron thread could be created if desired. |
28 | * | 28 | * |
29 | * The operation is fairly simple, jobs can be added at any time, and use | 29 | * The operation is fairly simple, jobs can be added at any time, and use |
30 | * any timer they would like, even custom timers. When it is time for a | 30 | * any timer they would like, even custom timers. When it is time for a |
31 | * job to be run it signals the slot provided when the job was added. Every | 31 | * job to be run it signals the slot provided when the job was added. Every |
32 | * job slot recieves a handle to the job object so that it may control it's | 32 | * job slot recieves a handle to the job object so that it may control it's |
33 | * own lifetime and get information about itself. In addition, every job | 33 | * own lifetime and get information about itself. In addition, every job |
34 | * is assigned a unique ID that can be used to control it's operation | 34 | * is assigned a unique ID that can be used to control it's operation |
35 | * at any time. | 35 | * at any time. |
36 | * | 36 | * |
37 | * By default a job will continually reschedule itself after being run | 37 | * By default a job will continually reschedule itself after being run |
38 | * unless it calls stop() on it's job object, it is removed using | 38 | * unless it calls stop() on it's job object, it is removed using |
39 | * removeJob() on the cron object, or it is added with addJobOnce. | 39 | * removeJob() on the cron object, or it is added with addJobOnce. |
40 | * | 40 | * |
41 | *@todo A minor change to the job execution system could allow a Timer to | 41 | *@todo A minor change to the job execution system could allow a Timer to |
42 | * defer or reschedule execution instead of the job executing. This would, | 42 | * defer or reschedule execution instead of the job executing. This would, |
43 | * in effect, allow us to do every type of interesting scheduling that | 43 | * in effect, allow us to do every type of interesting scheduling that |
44 | * systems like fcron offer, including time constrained load-balanced | 44 | * systems like fcron offer, including time constrained load-balanced |
45 | * execution. | 45 | * execution. |
46 | */ | 46 | */ |
47 | class MiniCron | 47 | class MiniCron |
48 | { | 48 | { |
49 | public: | 49 | public: |
50 | class Job; | 50 | class Job; |
51 | class Timer; | 51 | class Timer; |
52 | typedef Bu::Signal1<void, Bu::MiniCron::Job &> CronSignal; | 52 | typedef Bu::Signal1<void, Bu::MiniCron::Job &> CronSignal; |
53 | typedef int JobId; | 53 | typedef int JobId; |
54 | 54 | ||
55 | MiniCron(); | 55 | MiniCron(); |
56 | virtual ~MiniCron(); | 56 | virtual ~MiniCron(); |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Tells you if there are jobs registered in the MiniCron. | 59 | * Tells you if there are jobs registered in the MiniCron. |
60 | *@returns true if there are jobs, false otherwise. | 60 | *@returns true if there are jobs, false otherwise. |
61 | */ | 61 | */ |
62 | virtual bool hasJobs(); | 62 | virtual bool hasJobs(); |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * If there are jobs, tells you the time the next one will execute. | 65 | * If there are jobs, tells you the time the next one will execute. |
66 | *@returns The timestamp that the next job will execute at. | 66 | *@returns The timestamp that the next job will execute at. |
67 | */ | 67 | */ |
68 | virtual time_t getNextRun(); | 68 | virtual time_t getNextRun(); |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Tells you the time the job matching jid will run next. | 71 | * Tells you the time the job matching jid will run next. |
72 | *@returns The timestamp that the job jid will next run. | 72 | *@returns The timestamp that the job jid will next run. |
73 | */ | 73 | */ |
74 | virtual time_t getNextRun( JobId jid ); | 74 | virtual time_t getNextRun( JobId jid ); |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * Call this regularly to execute all jobs that should be executed. | 77 | * Call this regularly to execute all jobs that should be executed. |
78 | * This will loop until all jobs who's run time match the current time | 78 | * This will loop until all jobs who's run time match the current time |
79 | * or are below the current time (we've missed them). | 79 | * or are below the current time (we've missed them). |
80 | * If there is nothing to run, the runtime of this funcion is constant, | 80 | * If there is nothing to run, the runtime of this funcion is constant, |
81 | * it is very fast. Otherwise it executes at log(N) per job run, | 81 | * it is very fast. Otherwise it executes at log(N) per job run, |
82 | * O(N*log(N)). | 82 | * O(N*log(N)). |
83 | */ | 83 | */ |
84 | virtual void poll(); | 84 | virtual void poll(); |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * Add a job for repeated scheduling. Pass in a slot to signal, and a | 87 | * Add a job for repeated scheduling. Pass in a slot to signal, and a |
88 | * Timer object to use to do the scheduling. This function returns a | 88 | * Timer object to use to do the scheduling. This function returns a |
89 | * JobId which can be used at a later time to control the execution of | 89 | * JobId which can be used at a later time to control the execution of |
90 | * the job. | 90 | * the job. |
91 | */ | 91 | */ |
92 | virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, | 92 | virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, |
93 | const Timer &t ); | 93 | const Timer &t ); |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * Add a job for one time scheduling. Pass in a slot to signal, and a | 96 | * Add a job for one time scheduling. Pass in a slot to signal, and a |
97 | * Timer object to use to schodule the one run of this job. This | 97 | * Timer object to use to schodule the one run of this job. This |
98 | * function returns a JobId which can be used at a later time to control | 98 | * function returns a JobId which can be used at a later time to control |
99 | * the execution of the job. | 99 | * the execution of the job. |
100 | */ | 100 | */ |
101 | virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, | 101 | virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, |
102 | const Timer &t ); | 102 | const Timer &t ); |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * Remove a job, preventing all future runs of the job. If there is no | 105 | * Remove a job, preventing all future runs of the job. If there is no |
106 | * job matching the given JobId then nothing will happen. However, this | 106 | * job matching the given JobId then nothing will happen. However, this |
107 | * function is relatively expensive compared to the others in this class | 107 | * function is relatively expensive compared to the others in this class |
108 | * and has a worse case runtime of 2*N*log(N), still not that bad, and | 108 | * and has a worse case runtime of 2*N*log(N), still not that bad, and |
109 | * a O(N*log(N)). | 109 | * a O(N*log(N)). |
110 | */ | 110 | */ |
111 | virtual void removeJob( JobId jid ); | 111 | virtual void removeJob( JobId jid ); |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Executes the job specified right now. If bReschedule is true then | 114 | * Executes the job specified right now. If bReschedule is true then |
115 | * the job is then removed from the queue and rescheduled as though | 115 | * the job is then removed from the queue and rescheduled as though |
116 | * it's time had come naturally to be run. Otherwise, it's run without | 116 | * it's time had come naturally to be run. Otherwise, it's run without |
117 | * interrupting the normal schedule. | 117 | * interrupting the normal schedule. |
118 | */ | 118 | */ |
119 | virtual void runJob( JobId jid, bool bReschedule=false ); | 119 | virtual void runJob( JobId jid, bool bReschedule=false ); |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * Executes the job specified right now. If bReschedule is true then | 122 | * Executes the job specified right now. If bReschedule is true then |
123 | * the job is then removed from the queue and rescheduled as though | 123 | * the job is then removed from the queue and rescheduled as though |
124 | * it's time had come naturally to be run. Otherwise, it's run without | 124 | * it's time had come naturally to be run. Otherwise, it's run without |
125 | * interrupting the normal schedule. | 125 | * interrupting the normal schedule. |
126 | */ | 126 | */ |
127 | virtual void runJob( const Bu::String &sName, bool bReschedule=false ); | 127 | virtual void runJob( const Bu::String &sName, bool bReschedule=false ); |
128 | 128 | ||
129 | class JobInfo | 129 | class JobInfo |
130 | { | 130 | { |
131 | public: | 131 | public: |
132 | JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); | 132 | JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); |
133 | virtual ~JobInfo(); | 133 | virtual ~JobInfo(); |
134 | 134 | ||
135 | bool operator<( const JobInfo &rhs ) const; | 135 | bool operator<( const JobInfo &rhs ) const; |
136 | 136 | ||
137 | Bu::String sName; | 137 | Bu::String sName; |
138 | JobId jid; | 138 | JobId jid; |
139 | time_t tNext; | 139 | time_t tNext; |
140 | }; | 140 | }; |
141 | typedef Bu::List<JobInfo> JobInfoList; | 141 | typedef Bu::List<JobInfo> JobInfoList; |
142 | 142 | ||
143 | JobInfoList getJobInfo(); | 143 | JobInfoList getJobInfo(); |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * The baseclass for timer/schedulers for MiniCron jobs. Classes that | 146 | * The baseclass for timer/schedulers for MiniCron jobs. Classes that |
147 | * inherit from this are used to determine when jobs will run and at | 147 | * inherit from this are used to determine when jobs will run and at |
148 | * what interval. | 148 | * what interval. |
149 | */ | 149 | */ |
150 | class Timer | 150 | class Timer |
151 | { | 151 | { |
152 | public: | 152 | public: |
153 | Timer(); | 153 | Timer(); |
154 | virtual ~Timer(); | 154 | virtual ~Timer(); |
155 | 155 | ||
156 | /** | 156 | /** |
157 | * Called by MiniCron when each job is run to determine the next | 157 | * Called by MiniCron when each job is run to determine the next |
158 | * time that a job should be run. When a job is run, this function | 158 | * time that a job should be run. When a job is run, this function |
159 | * is actually called before the job is executed again so that the | 159 | * is actually called before the job is executed again so that the |
160 | * job can tell when the next time it will be run will be. | 160 | * job can tell when the next time it will be run will be. |
161 | */ | 161 | */ |
162 | virtual time_t nextTime()=0; | 162 | virtual time_t nextTime()=0; |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * This function should return a copy of the child class. | 165 | * This function should return a copy of the child class. |
166 | */ | 166 | */ |
167 | virtual Timer *clone() const = 0; | 167 | virtual Timer *clone() const = 0; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * Execute the job every tInterval seconds, also you can delay the | 171 | * Execute the job every tInterval seconds, also you can delay the |
172 | * first run by a different amount of time from the job's creation. | 172 | * first run by a different amount of time from the job's creation. |
173 | */ | 173 | */ |
174 | class TimerInterval : public Timer | 174 | class TimerInterval : public Timer |
175 | { | 175 | { |
176 | public: | 176 | public: |
177 | TimerInterval( time_t tFirst, time_t tInterval ); | 177 | TimerInterval( time_t tFirst, time_t tInterval ); |
178 | virtual ~TimerInterval(); | 178 | virtual ~TimerInterval(); |
179 | 179 | ||
180 | virtual time_t nextTime(); | 180 | virtual time_t nextTime(); |
181 | virtual Timer *clone() const | 181 | virtual Timer *clone() const |
182 | { return new TimerInterval( *this ); } | 182 | { return new TimerInterval( *this ); } |
183 | private: | 183 | private: |
184 | time_t tNext; | 184 | time_t tNext; |
185 | time_t tInterval; | 185 | time_t tInterval; |
186 | }; | 186 | }; |
187 | 187 | ||
188 | /** | 188 | /** |
189 | * A much more general timer class that can be used for much more | 189 | * A much more general timer class that can be used for much more |
190 | * "cron-like" functionality. The constructor takes a string that | 190 | * "cron-like" functionality. The constructor takes a string that |
191 | * describes the times that the job should be run. At the moment the | 191 | * describes the times that the job should be run. At the moment the |
192 | * following schemes are understood: | 192 | * following schemes are understood: |
193 | * | 193 | * |
194 | * "daily [hour] [minute]" | 194 | * "daily [hour] [minute]" |
195 | * "hourly [minute]" | 195 | * "hourly [minute]" |
196 | * "weekly [day] [hour] [minute]" | 196 | * "weekly [day] [hour] [minute]" |
197 | * | 197 | * |
198 | * In these examples each word in [brackets] represents a number that | 198 | * In these examples each word in [brackets] represents a number that |
199 | * matches the data type in the brackets. [day] is the number of days | 199 | * matches the data type in the brackets. [day] is the number of days |
200 | * since sunday, 0-6. You can also use lowercase three character | 200 | * since sunday, 0-6. You can also use lowercase three character |
201 | * abbreviations for the day names. | 201 | * abbreviations for the day names. |
202 | * | 202 | * |
203 | * Many more forms follow. | 203 | * Many more forms follow. |
204 | */ | 204 | */ |
205 | class TimerBasic : public Timer | 205 | class TimerBasic : public Timer |
206 | { | 206 | { |
207 | public: | 207 | public: |
208 | TimerBasic( const Bu::String &s ); | 208 | TimerBasic( const Bu::String &s ); |
209 | virtual ~TimerBasic(); | 209 | virtual ~TimerBasic(); |
210 | 210 | ||
211 | virtual time_t nextTime(); | 211 | virtual time_t nextTime(); |
212 | virtual Timer *clone() const | 212 | virtual Timer *clone() const |
213 | { return new TimerBasic( *this ); } | 213 | { return new TimerBasic( *this ); } |
214 | 214 | ||
215 | private: | 215 | private: |
216 | enum Token | 216 | enum Token |
217 | { | 217 | { |
218 | tokDaily, | 218 | tokDaily, |
219 | tokHourly, | 219 | tokHourly, |
220 | tokWeekly, | 220 | tokWeekly, |
221 | tokMonthly, | 221 | tokMonthly, |
222 | tokYearly, | 222 | tokYearly, |
223 | valInt, | 223 | valInt, |
224 | tokErr, | 224 | tokErr, |
225 | tokEos | 225 | tokEos |
226 | }; | 226 | }; |
227 | Token lex( Bu::String::const_iterator &i ); | 227 | Token lex( Bu::String::const_iterator &i ); |
228 | int lexInt( Bu::String::const_iterator &i ); | 228 | int lexInt( Bu::String::const_iterator &i ); |
229 | int iVal; //< A temp variable for parsing. | 229 | int iVal; //< A temp variable for parsing. |
230 | time_t tLast; | 230 | time_t tLast; |
231 | Bu::String sSpec; | 231 | Bu::String sSpec; |
232 | }; | 232 | }; |
233 | 233 | ||
234 | /** | 234 | /** |
235 | * Represents a MiniCron Job. This class is used for both internal | 235 | * Represents a MiniCron Job. This class is used for both internal |
236 | * job management as well as job slot interaction and control. Objects | 236 | * job management as well as job slot interaction and control. Objects |
237 | * of this class are passed into the slots that are signaled when a job | 237 | * of this class are passed into the slots that are signaled when a job |
238 | * is executed. | 238 | * is executed. |
239 | */ | 239 | */ |
240 | class Job | 240 | class Job |
241 | { | 241 | { |
242 | friend class Bu::MiniCron; | 242 | friend class Bu::MiniCron; |
243 | private: | 243 | private: |
244 | Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); | 244 | Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); |
245 | virtual ~Job(); | 245 | virtual ~Job(); |
246 | 246 | ||
247 | public: | 247 | public: |
248 | 248 | ||
249 | /** | 249 | /** |
250 | * Execute this job once, increment the runcount and schedule the | 250 | * Execute this job once, increment the runcount and schedule the |
251 | * next occurance of it. | 251 | * next occurance of it. |
252 | */ | 252 | */ |
253 | void run( bool bReschedule=true ); | 253 | void run( bool bReschedule=true ); |
254 | 254 | ||
255 | /** | 255 | /** |
256 | * Get the time this job will next run. | 256 | * Get the time this job will next run. |
257 | */ | 257 | */ |
258 | time_t getNextRun() const; | 258 | time_t getNextRun() const; |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * Compute the time this job will next run. | 261 | * Compute the time this job will next run. |
262 | */ | 262 | */ |
263 | void calcNextRun(); | 263 | void calcNextRun(); |
264 | 264 | ||
265 | /** | 265 | /** |
266 | * Replace the current job timer with a new one, this will trigger | 266 | * Replace the current job timer with a new one, this will trigger |
267 | * a re-schedule. | 267 | * a re-schedule. |
268 | */ | 268 | */ |
269 | void setTimer( const Timer &t ); | 269 | void setTimer( const Timer &t ); |
270 | 270 | ||
271 | /** | 271 | /** |
272 | * Stop execution of this job, never execute this job again. | 272 | * Stop execution of this job, never execute this job again. |
273 | */ | 273 | */ |
274 | void stop(); | 274 | void stop(); |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * Undo a previous stop. This will cause a job that has been | 277 | * Undo a previous stop. This will cause a job that has been |
278 | * stopped or even added with addJobOnce to be set for repeated | 278 | * stopped or even added with addJobOnce to be set for repeated |
279 | * scheduling. | 279 | * scheduling. |
280 | */ | 280 | */ |
281 | void resume(); | 281 | void resume(); |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * Get the unique ID of this job. | 284 | * Get the unique ID of this job. |
285 | */ | 285 | */ |
286 | JobId getId() const; | 286 | JobId getId() const; |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * Get the timestamp this job was created. | 289 | * Get the timestamp this job was created. |
290 | */ | 290 | */ |
291 | time_t getTimeCreated() const; | 291 | time_t getTimeCreated() const; |
292 | 292 | ||
293 | /** | 293 | /** |
294 | * Get the current run count of this job, how many times it has been | 294 | * Get the current run count of this job, how many times it has been |
295 | * executed. This is incremented before the slot is signaled. | 295 | * executed. This is incremented before the slot is signaled. |
296 | */ | 296 | */ |
297 | int getRunCount() const; | 297 | int getRunCount() const; |
298 | 298 | ||
299 | /** | 299 | /** |
300 | * Get the next time that this job will be run. Certain timers may | 300 | * Get the next time that this job will be run. Certain timers may |
301 | * have the ability to delay job executions, so this is the earliest | 301 | * have the ability to delay job executions, so this is the earliest |
302 | * time that the job may run. | 302 | * time that the job may run. |
303 | */ | 303 | */ |
304 | time_t getNextRunTime() const; | 304 | time_t getNextRunTime() const; |
305 | 305 | ||
306 | /** | 306 | /** |
307 | * Gets the name that was set when the job was created. | 307 | * Gets the name that was set when the job was created. |
308 | */ | 308 | */ |
309 | Bu::String getName() const; | 309 | Bu::String getName() const; |
310 | 310 | ||
311 | private: | 311 | private: |
312 | Bu::String sName; | 312 | Bu::String sName; |
313 | CronSignal sigJob; | 313 | CronSignal sigJob; |
314 | time_t tNextRun; | 314 | time_t tNextRun; |
315 | Timer *pTimer; | 315 | Timer *pTimer; |
316 | bool bContinue; | 316 | bool bContinue; |
317 | JobId jid; | 317 | JobId jid; |
318 | time_t tAdded; | 318 | time_t tAdded; |
319 | int iRunCount; | 319 | int iRunCount; |
320 | }; | 320 | }; |
321 | 321 | ||
322 | private: | 322 | private: |
323 | struct JobPtrCmp | 323 | struct JobPtrCmp |
324 | { | 324 | { |
325 | bool operator()( const Job *pLeft, const Job *pRight ) | 325 | bool operator()( const Job *pLeft, const Job *pRight ) |
326 | { | 326 | { |
327 | return pLeft->tNextRun < pRight->tNextRun; | 327 | return pLeft->tNextRun < pRight->tNextRun; |
328 | } | 328 | } |
329 | }; | 329 | }; |
330 | typedef Bu::Heap<Job *, JobPtrCmp> JobHeap; | 330 | typedef Bu::Heap<Job *, JobPtrCmp> JobHeap; |
331 | JobHeap hJobs; | 331 | JobHeap hJobs; |
332 | JobId jidNext; | 332 | JobId jidNext; |
333 | }; | 333 | }; |
334 | }; | 334 | }; |
335 | 335 | ||
336 | #endif | 336 | #endif |
diff --git a/src/stable/multiserver.cpp b/src/stable/multiserver.cpp index 8856117..bb1cacc 100644 --- a/src/stable/multiserver.cpp +++ b/src/stable/multiserver.cpp | |||
@@ -20,36 +20,36 @@ Bu::MultiServer::~MultiServer() | |||
20 | } | 20 | } |
21 | 21 | ||
22 | void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, | 22 | void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, |
23 | int nPoolSize ) | 23 | int nPoolSize ) |
24 | { | 24 | { |
25 | hProtos[iPort] = proc; | 25 | hProtos[iPort] = proc; |
26 | addPort( iPort, nPoolSize ); | 26 | addPort( iPort, nPoolSize ); |
27 | } | 27 | } |
28 | 28 | ||
29 | void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, | 29 | void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, |
30 | int iPort, int nPoolSize ) | 30 | int iPort, int nPoolSize ) |
31 | { | 31 | { |
32 | hProtos[iPort] = proc; | 32 | hProtos[iPort] = proc; |
33 | addPort( sAddr, iPort, nPoolSize ); | 33 | addPort( sAddr, iPort, nPoolSize ); |
34 | } | 34 | } |
35 | 35 | ||
36 | void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) | 36 | void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) |
37 | { | 37 | { |
38 | pClient->setProtocol( hProtos.get( nPort )() ); | 38 | pClient->setProtocol( hProtos.get( nPort )() ); |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) | 41 | void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) |
42 | { | 42 | { |
43 | delete pClient->getProtocol(); | 43 | delete pClient->getProtocol(); |
44 | } | 44 | } |
45 | 45 | ||
46 | void Bu::MultiServer::shutdown() | 46 | void Bu::MultiServer::shutdown() |
47 | { | 47 | { |
48 | Bu::Server::shutdown(); | 48 | Bu::Server::shutdown(); |
49 | } | 49 | } |
50 | 50 | ||
51 | void Bu::MultiServer::tick() | 51 | void Bu::MultiServer::tick() |
52 | { | 52 | { |
53 | Bu::Server::tick(); | 53 | Bu::Server::tick(); |
54 | } | 54 | } |
55 | 55 | ||
diff --git a/src/stable/multiserver.h b/src/stable/multiserver.h index b2f633a..8a49bbd 100644 --- a/src/stable/multiserver.h +++ b/src/stable/multiserver.h | |||
@@ -13,45 +13,45 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class Protocol; | 16 | class Protocol; |
17 | class Client; | 17 | class Client; |
18 | 18 | ||
19 | template<class T> | 19 | template<class T> |
20 | Protocol *genProtocol() | 20 | Protocol *genProtocol() |
21 | { | 21 | { |
22 | return new T; | 22 | return new T; |
23 | } | 23 | } |
24 | 24 | ||
25 | class MultiServer : protected Server | 25 | class MultiServer : protected Server |
26 | { | 26 | { |
27 | public: | 27 | public: |
28 | MultiServer(); | 28 | MultiServer(); |
29 | virtual ~MultiServer(); | 29 | virtual ~MultiServer(); |
30 | 30 | ||
31 | void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); | 31 | void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); |
32 | void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, | 32 | void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, |
33 | int nPoolSize=40 ); | 33 | int nPoolSize=40 ); |
34 | 34 | ||
35 | void scan() | 35 | void scan() |
36 | { | 36 | { |
37 | Server::scan(); | 37 | Server::scan(); |
38 | } | 38 | } |
39 | 39 | ||
40 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) | 40 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) |
41 | { | 41 | { |
42 | Server::setTimeout( nTimeoutSec, nTimeoutUSec ); | 42 | Server::setTimeout( nTimeoutSec, nTimeoutUSec ); |
43 | } | 43 | } |
44 | 44 | ||
45 | virtual void onNewConnection( Client *pClient, int nPort ); | 45 | virtual void onNewConnection( Client *pClient, int nPort ); |
46 | virtual void onClosedConnection( Client *pClient ); | 46 | virtual void onClosedConnection( Client *pClient ); |
47 | 47 | ||
48 | void shutdown(); | 48 | void shutdown(); |
49 | 49 | ||
50 | void tick(); | 50 | void tick(); |
51 | 51 | ||
52 | private: | 52 | private: |
53 | Bu::Hash<int, Protocol *(*)()> hProtos; | 53 | Bu::Hash<int, Protocol *(*)()> hProtos; |
54 | }; | 54 | }; |
55 | } | 55 | } |
56 | 56 | ||
57 | #endif | 57 | #endif |
diff --git a/src/stable/mutex.cpp b/src/stable/mutex.cpp index 947364c..0391d7a 100644 --- a/src/stable/mutex.cpp +++ b/src/stable/mutex.cpp | |||
@@ -9,26 +9,26 @@ | |||
9 | 9 | ||
10 | Bu::Mutex::Mutex() | 10 | Bu::Mutex::Mutex() |
11 | { | 11 | { |
12 | pthread_mutex_init( &mutex, NULL ); | 12 | pthread_mutex_init( &mutex, NULL ); |
13 | } | 13 | } |
14 | 14 | ||
15 | Bu::Mutex::~Mutex() | 15 | Bu::Mutex::~Mutex() |
16 | { | 16 | { |
17 | pthread_mutex_destroy( &mutex ); | 17 | pthread_mutex_destroy( &mutex ); |
18 | } | 18 | } |
19 | 19 | ||
20 | int Bu::Mutex::lock() | 20 | int Bu::Mutex::lock() |
21 | { | 21 | { |
22 | return pthread_mutex_lock( &mutex ); | 22 | return pthread_mutex_lock( &mutex ); |
23 | } | 23 | } |
24 | 24 | ||
25 | int Bu::Mutex::unlock() | 25 | int Bu::Mutex::unlock() |
26 | { | 26 | { |
27 | return pthread_mutex_unlock( &mutex ); | 27 | return pthread_mutex_unlock( &mutex ); |
28 | } | 28 | } |
29 | 29 | ||
30 | int Bu::Mutex::trylock() | 30 | int Bu::Mutex::trylock() |
31 | { | 31 | { |
32 | return pthread_mutex_trylock( &mutex ); | 32 | return pthread_mutex_trylock( &mutex ); |
33 | } | 33 | } |
34 | 34 | ||
diff --git a/src/stable/mutex.h b/src/stable/mutex.h index 1898118..23963e3 100644 --- a/src/stable/mutex.h +++ b/src/stable/mutex.h | |||
@@ -12,57 +12,57 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Simple mutex wrapper. Currently this doesn't do anything extra for you | 16 | * Simple mutex wrapper. Currently this doesn't do anything extra for you |
17 | * except keep all of the functionality together in an OO sorta' way and | 17 | * except keep all of the functionality together in an OO sorta' way and |
18 | * keep you from having to worry about cleaning up your mutexes properly, | 18 | * keep you from having to worry about cleaning up your mutexes properly, |
19 | * or initing them. | 19 | * or initing them. |
20 | *@ingroup Threading | 20 | *@ingroup Threading |
21 | */ | 21 | */ |
22 | class Mutex | 22 | class Mutex |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | /** | 25 | /** |
26 | * Create an unlocked mutex. | 26 | * Create an unlocked mutex. |
27 | */ | 27 | */ |
28 | Mutex(); | 28 | Mutex(); |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Destroy a mutex. This can only be done when a mutex is unlocked. | 31 | * Destroy a mutex. This can only be done when a mutex is unlocked. |
32 | * Failure to unlock before destroying a mutex object could cause it to | 32 | * Failure to unlock before destroying a mutex object could cause it to |
33 | * wait for the mutex to unlock, the odds of which are usually farily | 33 | * wait for the mutex to unlock, the odds of which are usually farily |
34 | * low at deconstruction time. | 34 | * low at deconstruction time. |
35 | */ | 35 | */ |
36 | ~Mutex(); | 36 | ~Mutex(); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Lock the mutex. This causes all future calls to lock on this | 39 | * Lock the mutex. This causes all future calls to lock on this |
40 | * instance of mutex to block until the first thread that called mutex | 40 | * instance of mutex to block until the first thread that called mutex |
41 | * unlocks it. At that point the next thread that called lock will get | 41 | * unlocks it. At that point the next thread that called lock will get |
42 | * a chance to go to work. Because of the nature of a mutex lock it is | 42 | * a chance to go to work. Because of the nature of a mutex lock it is |
43 | * a very bad idea to do any kind of serious or rather time consuming | 43 | * a very bad idea to do any kind of serious or rather time consuming |
44 | * computation within a locked section. This can cause thread-deadlock | 44 | * computation within a locked section. This can cause thread-deadlock |
45 | * and your program may hang. | 45 | * and your program may hang. |
46 | */ | 46 | */ |
47 | int lock(); | 47 | int lock(); |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * Unlock the mutex. This allows the next thread that asked for a lock | 50 | * Unlock the mutex. This allows the next thread that asked for a lock |
51 | * to lock the mutex and continue with execution. | 51 | * to lock the mutex and continue with execution. |
52 | */ | 52 | */ |
53 | int unlock(); | 53 | int unlock(); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Try to lock the mutex. This is the option to go with if you cannot | 56 | * Try to lock the mutex. This is the option to go with if you cannot |
57 | * avoid putting lengthy operations within a locked section. trylock | 57 | * avoid putting lengthy operations within a locked section. trylock |
58 | * will attempt to lock the mutex, if the mutex is already locked this | 58 | * will attempt to lock the mutex, if the mutex is already locked this |
59 | * function returns immediately with an error code. | 59 | * function returns immediately with an error code. |
60 | */ | 60 | */ |
61 | int trylock(); | 61 | int trylock(); |
62 | 62 | ||
63 | protected: | 63 | protected: |
64 | pthread_mutex_t mutex; /**< The internal mutex reference. */ | 64 | pthread_mutex_t mutex; /**< The internal mutex reference. */ |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/mutexlocker.cpp b/src/stable/mutexlocker.cpp index 90b730e..c8465a3 100644 --- a/src/stable/mutexlocker.cpp +++ b/src/stable/mutexlocker.cpp | |||
@@ -2,23 +2,23 @@ | |||
2 | #include "bu/mutex.h" | 2 | #include "bu/mutex.h" |
3 | 3 | ||
4 | Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : | 4 | Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : |
5 | mu( mu ) | 5 | mu( mu ) |
6 | { | 6 | { |
7 | mu.lock(); | 7 | mu.lock(); |
8 | } | 8 | } |
9 | 9 | ||
10 | Bu::MutexLocker::~MutexLocker() | 10 | Bu::MutexLocker::~MutexLocker() |
11 | { | 11 | { |
12 | mu.unlock(); | 12 | mu.unlock(); |
13 | } | 13 | } |
14 | 14 | ||
15 | void Bu::MutexLocker::unlock() | 15 | void Bu::MutexLocker::unlock() |
16 | { | 16 | { |
17 | mu.unlock(); | 17 | mu.unlock(); |
18 | } | 18 | } |
19 | 19 | ||
20 | void Bu::MutexLocker::relock() | 20 | void Bu::MutexLocker::relock() |
21 | { | 21 | { |
22 | mu.lock(); | 22 | mu.lock(); |
23 | } | 23 | } |
24 | 24 | ||
diff --git a/src/stable/mutexlocker.h b/src/stable/mutexlocker.h index 7c3c97e..30e71e6 100644 --- a/src/stable/mutexlocker.h +++ b/src/stable/mutexlocker.h | |||
@@ -3,19 +3,19 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | class Mutex; | 6 | class Mutex; |
7 | class MutexLocker | 7 | class MutexLocker |
8 | { | 8 | { |
9 | public: | 9 | public: |
10 | MutexLocker( Mutex &mu ); | 10 | MutexLocker( Mutex &mu ); |
11 | virtual ~MutexLocker(); | 11 | virtual ~MutexLocker(); |
12 | 12 | ||
13 | void unlock(); | 13 | void unlock(); |
14 | void relock(); | 14 | void relock(); |
15 | 15 | ||
16 | private: | 16 | private: |
17 | Mutex μ | 17 | Mutex μ |
18 | }; | 18 | }; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | #endif | 21 | #endif |
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp index 4be82f0..2a6a725 100644 --- a/src/stable/myriad.cpp +++ b/src/stable/myriad.cpp | |||
@@ -16,720 +16,720 @@ | |||
16 | using Bu::sio; | 16 | using Bu::sio; |
17 | using Bu::Fmt; | 17 | using Bu::Fmt; |
18 | 18 | ||
19 | #define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") | 19 | #define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") |
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | subExceptionDef( MyriadException ) | 23 | subExceptionDef( MyriadException ) |
24 | template<typename t> t blkDiv( t total, t block ) { | 24 | template<typename t> t blkDiv( t total, t block ) { |
25 | return (total/block)+((total%block==0)?(0):(1)); | 25 | return (total/block)+((total%block==0)?(0):(1)); |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : | 29 | Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : |
30 | sStore( sStore ), | 30 | sStore( sStore ), |
31 | iBlockSize( iBlockSize ), | 31 | iBlockSize( iBlockSize ), |
32 | iBlocks( 0 ), | 32 | iBlocks( 0 ), |
33 | iUsed( 0 ), | 33 | iUsed( 0 ), |
34 | bHeaderChanged( false ) | 34 | bHeaderChanged( false ) |
35 | { | 35 | { |
36 | try | 36 | try |
37 | { | 37 | { |
38 | initialize(); | 38 | initialize(); |
39 | } | 39 | } |
40 | catch( Bu::MyriadException &e ) | 40 | catch( Bu::MyriadException &e ) |
41 | { | 41 | { |
42 | if( e.getErrorCode() == MyriadException::emptyStream ) | 42 | if( e.getErrorCode() == MyriadException::emptyStream ) |
43 | { | 43 | { |
44 | initialize( iBlockSize, iPreallocate ); | 44 | initialize( iBlockSize, iPreallocate ); |
45 | } | 45 | } |
46 | else | 46 | else |
47 | { | 47 | { |
48 | throw; | 48 | throw; |
49 | } | 49 | } |
50 | } | 50 | } |
51 | } | 51 | } |
52 | 52 | ||
53 | Bu::Myriad::~Myriad() | 53 | Bu::Myriad::~Myriad() |
54 | { | 54 | { |
55 | mActiveBlocks.lock(); | 55 | mActiveBlocks.lock(); |
56 | if( !hActiveBlocks.isEmpty() ) | 56 | if( !hActiveBlocks.isEmpty() ) |
57 | { | 57 | { |
58 | sio << "Bu::Myriad::~Myriad(): Error: There are " | 58 | sio << "Bu::Myriad::~Myriad(): Error: There are " |
59 | << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; | 59 | << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; |
60 | } | 60 | } |
61 | mActiveBlocks.unlock(); | 61 | mActiveBlocks.unlock(); |
62 | sync(); | 62 | sync(); |
63 | 63 | ||
64 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 64 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
65 | { | 65 | { |
66 | delete *i; | 66 | delete *i; |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | void Bu::Myriad::sync() | 70 | void Bu::Myriad::sync() |
71 | { | 71 | { |
72 | updateHeader(); | 72 | updateHeader(); |
73 | 73 | ||
74 | mActiveBlocks.lock(); | 74 | mActiveBlocks.lock(); |
75 | for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) | 75 | for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) |
76 | { | 76 | { |
77 | if( (*i)->bChanged ) | 77 | if( (*i)->bChanged ) |
78 | { | 78 | { |
79 | syncBlock( *i ); | 79 | syncBlock( *i ); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | mActiveBlocks.unlock(); | 82 | mActiveBlocks.unlock(); |
83 | } | 83 | } |
84 | 84 | ||
85 | void Bu::Myriad::initialize() | 85 | void Bu::Myriad::initialize() |
86 | { | 86 | { |
87 | MutexLocker mLock( mHeader ); | 87 | MutexLocker mLock( mHeader ); |
88 | lFreeBlocks.clear(); | 88 | lFreeBlocks.clear(); |
89 | sStore.setPosEnd( 0 ); | 89 | sStore.setPosEnd( 0 ); |
90 | Bu::size iSize = sStore.tell(); | 90 | Bu::size iSize = sStore.tell(); |
91 | sStore.setPos( 0 ); | 91 | sStore.setPos( 0 ); |
92 | 92 | ||
93 | unsigned char buf[4]; | 93 | unsigned char buf[4]; |
94 | if( sStore.read( buf, 4 ) < 4 ) | 94 | if( sStore.read( buf, 4 ) < 4 ) |
95 | throw MyriadException( MyriadException::emptyStream, | 95 | throw MyriadException( MyriadException::emptyStream, |
96 | "Input stream appears to be empty."); | 96 | "Input stream appears to be empty."); |
97 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | 97 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) |
98 | { | 98 | { |
99 | throw MyriadException( MyriadException::invalidFormat, | 99 | throw MyriadException( MyriadException::invalidFormat, |
100 | "Stream does not appear to be a valid Myriad format."); | 100 | "Stream does not appear to be a valid Myriad format."); |
101 | } | 101 | } |
102 | sStore.read( buf, 2 ); | 102 | sStore.read( buf, 2 ); |
103 | if( buf[0] != 1 ) | 103 | if( buf[0] != 1 ) |
104 | throw MyriadException( MyriadException::badVersion, | 104 | throw MyriadException( MyriadException::badVersion, |
105 | "We can only handle version 1 for now."); | 105 | "We can only handle version 1 for now."); |
106 | if( buf[1] != 32 ) | 106 | if( buf[1] != 32 ) |
107 | throw MyriadException( MyriadException::invalidWordSize, | 107 | throw MyriadException( MyriadException::invalidWordSize, |
108 | "We can only handle 32-bit words at the moment."); | 108 | "We can only handle 32-bit words at the moment."); |
109 | sStore.read( &iBlockSize, 4 ); | 109 | sStore.read( &iBlockSize, 4 ); |
110 | int iStreams; | 110 | int iStreams; |
111 | sStore.read( &iStreams, 4 ); | 111 | sStore.read( &iStreams, 4 ); |
112 | 112 | ||
113 | iBlocks = iSize/iBlockSize; | 113 | iBlocks = iSize/iBlockSize; |
114 | //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize | 114 | //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize |
115 | // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; | 115 | // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; |
116 | 116 | ||
117 | int iHeaderSize = 14 + 8 + 4; | 117 | int iHeaderSize = 14 + 8 + 4; |
118 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); | 118 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); |
119 | 119 | ||
120 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | 120 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) |
121 | { | 121 | { |
122 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | 122 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); |
123 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | 123 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; |
124 | } | 124 | } |
125 | 125 | ||
126 | //sio << "Myriad: iHeaderSize=" << iHeaderSize | 126 | //sio << "Myriad: iHeaderSize=" << iHeaderSize |
127 | // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | 127 | // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; |
128 | 128 | ||
129 | Stream *pFakeHdr = new Stream; | 129 | Stream *pFakeHdr = new Stream; |
130 | pFakeHdr->iId = 0; | 130 | pFakeHdr->iId = 0; |
131 | pFakeHdr->iSize = iHeaderSize; | 131 | pFakeHdr->iSize = iHeaderSize; |
132 | for( int j = 0; j < iHeaderBlocks; j++ ) | 132 | for( int j = 0; j < iHeaderBlocks; j++ ) |
133 | { | 133 | { |
134 | pFakeHdr->aBlocks.append( j ); | 134 | pFakeHdr->aBlocks.append( j ); |
135 | } | 135 | } |
136 | 136 | ||
137 | // sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize | 137 | // sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize |
138 | // << ")" << sio.nl; | 138 | // << ")" << sio.nl; |
139 | Bu::BitString bsBlockUsed( iBlocks, false ); | 139 | Bu::BitString bsBlockUsed( iBlocks, false ); |
140 | bsBlockUsed.clear(); | 140 | bsBlockUsed.clear(); |
141 | 141 | ||
142 | // bool bCanSkip = false; // Can skip around, post initial header stream i/o | 142 | // bool bCanSkip = false; // Can skip around, post initial header stream i/o |
143 | MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); | 143 | MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); |
144 | pIn->setPos( sStore.tell() ); | 144 | pIn->setPos( sStore.tell() ); |
145 | for( int j = 0; j < iStreams; j++ ) | 145 | for( int j = 0; j < iStreams; j++ ) |
146 | { | 146 | { |
147 | aStreams.append( new Stream() ); | 147 | aStreams.append( new Stream() ); |
148 | Stream &s = *aStreams[j]; | 148 | Stream &s = *aStreams[j]; |
149 | pIn->read( &s.iId, 4 ); | 149 | pIn->read( &s.iId, 4 ); |
150 | pIn->read( &s.iSize, 4 ); | 150 | pIn->read( &s.iSize, 4 ); |
151 | int iSBlocks = blkDiv(s.iSize, iBlockSize); | 151 | int iSBlocks = blkDiv(s.iSize, iBlockSize); |
152 | // sio << "Myriad: - Stream::iId=" << s.iId | 152 | // sio << "Myriad: - Stream::iId=" << s.iId |
153 | // << ", Stream::iSize=" << s.iSize | 153 | // << ", Stream::iSize=" << s.iSize |
154 | // << ", Stream::aBlocks=" << iSBlocks | 154 | // << ", Stream::aBlocks=" << iSBlocks |
155 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; | 155 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; |
156 | for( int k = 0; k < iSBlocks; k++ ) | 156 | for( int k = 0; k < iSBlocks; k++ ) |
157 | { | 157 | { |
158 | int iBId; | 158 | int iBId; |
159 | pIn->read( &iBId, 4 ); | 159 | pIn->read( &iBId, 4 ); |
160 | // sio << "Myriad: - iBId=" << iBId | 160 | // sio << "Myriad: - iBId=" << iBId |
161 | // << ", iStartPos=" << iBId*iBlockSize | 161 | // << ", iStartPos=" << iBId*iBlockSize |
162 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; | 162 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; |
163 | s.aBlocks.append( iBId ); | 163 | s.aBlocks.append( iBId ); |
164 | bsBlockUsed.setBit( iBId ); | 164 | bsBlockUsed.setBit( iBId ); |
165 | iUsed++; | 165 | iUsed++; |
166 | if( (j == 0 && k == iHeaderBlocks-1) ) | 166 | if( (j == 0 && k == iHeaderBlocks-1) ) |
167 | { | 167 | { |
168 | // sio << "Myriad: - End of prepartition, unlocking skipping." | 168 | // sio << "Myriad: - End of prepartition, unlocking skipping." |
169 | // << sio.nl; | 169 | // << sio.nl; |
170 | // bCanSkip = true; | 170 | // bCanSkip = true; |
171 | MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); | 171 | MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); |
172 | // sio << "Myriad - Position = " << pIn->tell() << sio.nl; | 172 | // sio << "Myriad - Position = " << pIn->tell() << sio.nl; |
173 | pTmp->setPos( pIn->tell() ); | 173 | pTmp->setPos( pIn->tell() ); |
174 | delete pIn; | 174 | delete pIn; |
175 | delete pFakeHdr; | 175 | delete pFakeHdr; |
176 | pIn = pTmp; | 176 | pIn = pTmp; |
177 | } | 177 | } |
178 | } | 178 | } |
179 | } | 179 | } |
180 | delete pIn; | 180 | delete pIn; |
181 | 181 | ||
182 | for( int j = 0; j < iBlocks; j++ ) | 182 | for( int j = 0; j < iBlocks; j++ ) |
183 | { | 183 | { |
184 | if( bsBlockUsed.getBit( j ) == false ) | 184 | if( bsBlockUsed.getBit( j ) == false ) |
185 | { | 185 | { |
186 | // sio << "Preinitialized block " << j << " is free." << sio.nl; | 186 | // sio << "Preinitialized block " << j << " is free." << sio.nl; |
187 | lFreeBlocks.append( j ); | 187 | lFreeBlocks.append( j ); |
188 | } | 188 | } |
189 | } | 189 | } |
190 | // sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; | 190 | // sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; |
191 | } | 191 | } |
192 | 192 | ||
193 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) | 193 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) |
194 | { | 194 | { |
195 | MutexLocker mLock( mHeader ); | 195 | MutexLocker mLock( mHeader ); |
196 | lFreeBlocks.clear(); | 196 | lFreeBlocks.clear(); |
197 | 197 | ||
198 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 198 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
199 | { | 199 | { |
200 | delete *i; | 200 | delete *i; |
201 | } | 201 | } |
202 | aStreams.clear(); | 202 | aStreams.clear(); |
203 | iUsed = 0; | 203 | iUsed = 0; |
204 | 204 | ||
205 | int iHeaderSize = 14 + 8 + 4; | 205 | int iHeaderSize = 14 + 8 + 4; |
206 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); | 206 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); |
207 | char cBuf = 1; | 207 | char cBuf = 1; |
208 | int iBuf = 0; | 208 | int iBuf = 0; |
209 | 209 | ||
210 | Stream *pStr = new Stream; | 210 | Stream *pStr = new Stream; |
211 | pStr->iId = 0; | 211 | pStr->iId = 0; |
212 | 212 | ||
213 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | 213 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) |
214 | { | 214 | { |
215 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | 215 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); |
216 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | 216 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; |
217 | } | 217 | } |
218 | 218 | ||
219 | iPreAllocate += iHeaderBlocks; | 219 | iPreAllocate += iHeaderBlocks; |
220 | 220 | ||
221 | //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" | 221 | //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" |
222 | // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | 222 | // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; |
223 | 223 | ||
224 | // bsBlockUsed.setSize( iPreAllocate, true ); | 224 | // bsBlockUsed.setSize( iPreAllocate, true ); |
225 | iUsed++; | 225 | iUsed++; |
226 | 226 | ||
227 | char *pBlock = new char[iBlockSize]; | 227 | char *pBlock = new char[iBlockSize]; |
228 | memset( pBlock, 0, iBlockSize ); | 228 | memset( pBlock, 0, iBlockSize ); |
229 | for( int j = 0; j < iPreAllocate; j++ ) | 229 | for( int j = 0; j < iPreAllocate; j++ ) |
230 | { | 230 | { |
231 | sStore.write( pBlock, iBlockSize ); | 231 | sStore.write( pBlock, iBlockSize ); |
232 | } | 232 | } |
233 | delete[] (char *)pBlock; | 233 | delete[] (char *)pBlock; |
234 | 234 | ||
235 | sStore.setPos( 0 ); | 235 | sStore.setPos( 0 ); |
236 | 236 | ||
237 | // Magic number | 237 | // Magic number |
238 | sStore.write( Myriad_MAGIC_CODE, 4 ); | 238 | sStore.write( Myriad_MAGIC_CODE, 4 ); |
239 | 239 | ||
240 | // Version (0) | 240 | // Version (0) |
241 | sStore.write( &cBuf, 1 ); | 241 | sStore.write( &cBuf, 1 ); |
242 | 242 | ||
243 | // Bits per int | 243 | // Bits per int |
244 | cBuf = 32; | 244 | cBuf = 32; |
245 | sStore.write( &cBuf, 1 ); | 245 | sStore.write( &cBuf, 1 ); |
246 | 246 | ||
247 | // The size of each block | 247 | // The size of each block |
248 | sStore.write( &iBlockSize, 4 ); | 248 | sStore.write( &iBlockSize, 4 ); |
249 | 249 | ||
250 | iBuf = 1; | 250 | iBuf = 1; |
251 | // The number of streams | 251 | // The number of streams |
252 | sStore.write( &iBuf, 4 ); | 252 | sStore.write( &iBuf, 4 ); |
253 | 253 | ||
254 | // Stream header | 254 | // Stream header |
255 | iBuf = 0; | 255 | iBuf = 0; |
256 | sStore.write( &iBuf, 4 ); | 256 | sStore.write( &iBuf, 4 ); |
257 | sStore.write( &iHeaderSize, 4 ); | 257 | sStore.write( &iHeaderSize, 4 ); |
258 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) | 258 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) |
259 | { | 259 | { |
260 | sStore.write( &iBuf, 4 ); | 260 | sStore.write( &iBuf, 4 ); |
261 | } | 261 | } |
262 | 262 | ||
263 | this->iBlockSize = iBlockSize; | 263 | this->iBlockSize = iBlockSize; |
264 | this->iBlocks = iPreAllocate; | 264 | this->iBlocks = iPreAllocate; |
265 | 265 | ||
266 | pStr->iSize = sStore.tell(); | 266 | pStr->iSize = sStore.tell(); |
267 | // sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; | 267 | // sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; |
268 | 268 | ||
269 | pStr->iSize = iHeaderSize; | 269 | pStr->iSize = iHeaderSize; |
270 | for( int j = 0; j < iHeaderBlocks; j++ ) | 270 | for( int j = 0; j < iHeaderBlocks; j++ ) |
271 | { | 271 | { |
272 | // sio << "Started block " << j << " is header." << sio.nl; | 272 | // sio << "Started block " << j << " is header." << sio.nl; |
273 | pStr->aBlocks.append( j ); | 273 | pStr->aBlocks.append( j ); |
274 | // bsBlockUsed.setBit( j ); | 274 | // bsBlockUsed.setBit( j ); |
275 | iUsed++; | 275 | iUsed++; |
276 | } | 276 | } |
277 | for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) | 277 | for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) |
278 | { | 278 | { |
279 | // sio << "Started block " << j << " is free." << sio.nl; | 279 | // sio << "Started block " << j << " is free." << sio.nl; |
280 | lFreeBlocks.append( j ); | 280 | lFreeBlocks.append( j ); |
281 | } | 281 | } |
282 | 282 | ||
283 | aStreams.append( pStr ); | 283 | aStreams.append( pStr ); |
284 | 284 | ||
285 | //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; | 285 | //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; |
286 | 286 | ||
287 | bHeaderChanged = true; | 287 | bHeaderChanged = true; |
288 | //hStreams.insert( 0, BlockArray( 0 ) ); | 288 | //hStreams.insert( 0, BlockArray( 0 ) ); |
289 | } | 289 | } |
290 | 290 | ||
291 | void Bu::Myriad::updateHeader() | 291 | void Bu::Myriad::updateHeader() |
292 | { | 292 | { |
293 | MutexLocker mLock( mHeader ); | 293 | MutexLocker mLock( mHeader ); |
294 | 294 | ||
295 | if( bHeaderChanged == false ) | 295 | if( bHeaderChanged == false ) |
296 | return; | 296 | return; |
297 | if( !sStore.canWrite() ) | 297 | if( !sStore.canWrite() ) |
298 | return; | 298 | return; |
299 | 299 | ||
300 | char cBuf; | 300 | char cBuf; |
301 | int iBuf; | 301 | int iBuf; |
302 | 302 | ||
303 | //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 303 | //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
304 | //{ | 304 | //{ |
305 | // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; | 305 | // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; |
306 | //} | 306 | //} |
307 | 307 | ||
308 | // Compute the new size of the header. | 308 | // Compute the new size of the header. |
309 | int iHeaderSize = 14 + 8*aStreams.getSize(); | 309 | int iHeaderSize = 14 + 8*aStreams.getSize(); |
310 | // sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() | 310 | // sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() |
311 | // << sio.nl; | 311 | // << sio.nl; |
312 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 312 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
313 | { | 313 | { |
314 | iHeaderSize += 4*(*i)->aBlocks.getSize(); | 314 | iHeaderSize += 4*(*i)->aBlocks.getSize(); |
315 | // sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " | 315 | // sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " |
316 | // << (*i)->aBlocks.getSize() << sio.nl; | 316 | // << (*i)->aBlocks.getSize() << sio.nl; |
317 | } | 317 | } |
318 | int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); | 318 | int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); |
319 | while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) | 319 | while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) |
320 | { | 320 | { |
321 | int iBlock = findEmptyBlock(); | 321 | int iBlock = findEmptyBlock(); |
322 | // sio << "Myriad: updateHeader: Appending block " << iBlock | 322 | // sio << "Myriad: updateHeader: Appending block " << iBlock |
323 | // << " to header." << sio.nl; | 323 | // << " to header." << sio.nl; |
324 | aStreams[0]->aBlocks.append( iBlock ); | 324 | aStreams[0]->aBlocks.append( iBlock ); |
325 | // bsBlockUsed.setBit( iBlock ); | 325 | // bsBlockUsed.setBit( iBlock ); |
326 | iUsed++; | 326 | iUsed++; |
327 | iHeaderSize += 4; | 327 | iHeaderSize += 4; |
328 | iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); | 328 | iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); |
329 | } | 329 | } |
330 | aStreams[0]->iSize = iHeaderSize; | 330 | aStreams[0]->iSize = iHeaderSize; |
331 | // sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize | 331 | // sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize |
332 | // << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" | 332 | // << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" |
333 | // << aStreams[0]->aBlocks.getSize() << sio.nl; | 333 | // << aStreams[0]->aBlocks.getSize() << sio.nl; |
334 | 334 | ||
335 | MyriadStream sHdr( *this, aStreams[0] ); | 335 | MyriadStream sHdr( *this, aStreams[0] ); |
336 | sHdr.write( Myriad_MAGIC_CODE, 4 ); | 336 | sHdr.write( Myriad_MAGIC_CODE, 4 ); |
337 | 337 | ||
338 | // Version (1) | 338 | // Version (1) |
339 | cBuf = 1; | 339 | cBuf = 1; |
340 | sHdr.write( &cBuf, 1 ); | 340 | sHdr.write( &cBuf, 1 ); |
341 | 341 | ||
342 | // Bits per int | 342 | // Bits per int |
343 | cBuf = 32; | 343 | cBuf = 32; |
344 | sHdr.write( &cBuf, 1 ); | 344 | sHdr.write( &cBuf, 1 ); |
345 | 345 | ||
346 | // The size of each block | 346 | // The size of each block |
347 | sHdr.write( &iBlockSize, 4 ); | 347 | sHdr.write( &iBlockSize, 4 ); |
348 | 348 | ||
349 | iBuf = aStreams.getSize(); | 349 | iBuf = aStreams.getSize(); |
350 | // The number of streams | 350 | // The number of streams |
351 | sHdr.write( &iBuf, 4 ); | 351 | sHdr.write( &iBuf, 4 ); |
352 | 352 | ||
353 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 353 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
354 | { | 354 | { |
355 | sHdr.write( &(*i)->iId, 4 ); | 355 | sHdr.write( &(*i)->iId, 4 ); |
356 | sHdr.write( &(*i)->iSize, 4 ); | 356 | sHdr.write( &(*i)->iSize, 4 ); |
357 | int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); | 357 | int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); |
358 | // for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) | 358 | // for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) |
359 | for( int j = 0; j < iUsedBlocks; j++ ) | 359 | for( int j = 0; j < iUsedBlocks; j++ ) |
360 | { | 360 | { |
361 | sHdr.write( &(*i)->aBlocks[j], 4 ); | 361 | sHdr.write( &(*i)->aBlocks[j], 4 ); |
362 | } | 362 | } |
363 | } | 363 | } |
364 | 364 | ||
365 | bHeaderChanged = false; | 365 | bHeaderChanged = false; |
366 | } | 366 | } |
367 | 367 | ||
368 | int Bu::Myriad::createStream( int iPreAllocate ) | 368 | int Bu::Myriad::createStream( int iPreAllocate ) |
369 | { | 369 | { |
370 | MutexLocker mLock( mHeader ); | 370 | MutexLocker mLock( mHeader ); |
371 | 371 | ||
372 | Stream *pStr = new Stream(); | 372 | Stream *pStr = new Stream(); |
373 | pStr->iId = aStreams.last()->iId+1; | 373 | pStr->iId = aStreams.last()->iId+1; |
374 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | 374 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" |
375 | // << iPreAllocate << sio.nl; | 375 | // << iPreAllocate << sio.nl; |
376 | pStr->iSize = 0; | 376 | pStr->iSize = 0; |
377 | aStreams.append( pStr ); | 377 | aStreams.append( pStr ); |
378 | 378 | ||
379 | for( int j = 0; j < iPreAllocate; j++ ) | 379 | for( int j = 0; j < iPreAllocate; j++ ) |
380 | { | 380 | { |
381 | int iFreeBlock = findEmptyBlock(); | 381 | int iFreeBlock = findEmptyBlock(); |
382 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; | 382 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; |
383 | pStr->aBlocks.append( iFreeBlock ); | 383 | pStr->aBlocks.append( iFreeBlock ); |
384 | // bsBlockUsed.setBit( iFreeBlock ); | 384 | // bsBlockUsed.setBit( iFreeBlock ); |
385 | iUsed++; | 385 | iUsed++; |
386 | } | 386 | } |
387 | 387 | ||
388 | bHeaderChanged = true; | 388 | bHeaderChanged = true; |
389 | 389 | ||
390 | return pStr->iId; | 390 | return pStr->iId; |
391 | } | 391 | } |
392 | 392 | ||
393 | int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) | 393 | int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) |
394 | { | 394 | { |
395 | MutexLocker mLock( mHeader ); | 395 | MutexLocker mLock( mHeader ); |
396 | 396 | ||
397 | try | 397 | try |
398 | { | 398 | { |
399 | findStream( iId ); | 399 | findStream( iId ); |
400 | throw MyriadException( MyriadException::streamExists, | 400 | throw MyriadException( MyriadException::streamExists, |
401 | "There is already a stream with the given id."); | 401 | "There is already a stream with the given id."); |
402 | } | 402 | } |
403 | catch( MyriadException &e ) | 403 | catch( MyriadException &e ) |
404 | { | 404 | { |
405 | Stream *pStr = new Stream(); | 405 | Stream *pStr = new Stream(); |
406 | pStr->iId = iId; | 406 | pStr->iId = iId; |
407 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | 407 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" |
408 | // << iPreAllocate << sio.nl; | 408 | // << iPreAllocate << sio.nl; |
409 | pStr->iSize = 0; | 409 | pStr->iSize = 0; |
410 | if( aStreams.last()->iId < iId ) | 410 | if( aStreams.last()->iId < iId ) |
411 | { | 411 | { |
412 | aStreams.append( pStr ); | 412 | aStreams.append( pStr ); |
413 | } | 413 | } |
414 | else | 414 | else |
415 | { | 415 | { |
416 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 416 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
417 | { | 417 | { |
418 | if( (*i)->iId > iId ) | 418 | if( (*i)->iId > iId ) |
419 | { | 419 | { |
420 | aStreams.insert( i, pStr ); | 420 | aStreams.insert( i, pStr ); |
421 | break; | 421 | break; |
422 | } | 422 | } |
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | for( int j = 0; j < iPreAllocate; j++ ) | 426 | for( int j = 0; j < iPreAllocate; j++ ) |
427 | { | 427 | { |
428 | int iFreeBlock = findEmptyBlock(); | 428 | int iFreeBlock = findEmptyBlock(); |
429 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; | 429 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; |
430 | pStr->aBlocks.append( iFreeBlock ); | 430 | pStr->aBlocks.append( iFreeBlock ); |
431 | // bsBlockUsed.setBit( iFreeBlock ); | 431 | // bsBlockUsed.setBit( iFreeBlock ); |
432 | iUsed++; | 432 | iUsed++; |
433 | } | 433 | } |
434 | 434 | ||
435 | bHeaderChanged = true; | 435 | bHeaderChanged = true; |
436 | 436 | ||
437 | return pStr->iId; | 437 | return pStr->iId; |
438 | } | 438 | } |
439 | } | 439 | } |
440 | 440 | ||
441 | int Bu::Myriad::findEmptyBlock() | 441 | int Bu::Myriad::findEmptyBlock() |
442 | { | 442 | { |
443 | bHeaderChanged = true; | 443 | bHeaderChanged = true; |
444 | 444 | ||
445 | if( lFreeBlocks.isEmpty() ) | 445 | if( lFreeBlocks.isEmpty() ) |
446 | { | 446 | { |
447 | sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); | 447 | sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); |
448 | return iBlocks++; | 448 | return iBlocks++; |
449 | } | 449 | } |
450 | else | 450 | else |
451 | { | 451 | { |
452 | return lFreeBlocks.dequeue(); | 452 | return lFreeBlocks.dequeue(); |
453 | } | 453 | } |
454 | } | 454 | } |
455 | 455 | ||
456 | void Bu::Myriad::deleteStream( int iId ) | 456 | void Bu::Myriad::deleteStream( int iId ) |
457 | { | 457 | { |
458 | MutexLocker mLock( mHeader ); | 458 | MutexLocker mLock( mHeader ); |
459 | 459 | ||
460 | if( iId < 0 ) | 460 | if( iId < 0 ) |
461 | throw MyriadException( MyriadException::invalidStreamId, | 461 | throw MyriadException( MyriadException::invalidStreamId, |
462 | "Invalid stream id."); | 462 | "Invalid stream id."); |
463 | if( iId == 0 ) | 463 | if( iId == 0 ) |
464 | throw MyriadException( MyriadException::protectedStream, | 464 | throw MyriadException( MyriadException::protectedStream, |
465 | "You cannot delete stream zero, it is protected."); | 465 | "You cannot delete stream zero, it is protected."); |
466 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 466 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
467 | { | 467 | { |
468 | if( (*i)->iId == iId ) | 468 | if( (*i)->iId == iId ) |
469 | { | 469 | { |
470 | Stream *pStream = *i; | 470 | Stream *pStream = *i; |
471 | for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) | 471 | for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) |
472 | { | 472 | { |
473 | lFreeBlocks.append( *j ); | 473 | lFreeBlocks.append( *j ); |
474 | // bsBlockUsed.setBit( *j, false ); | 474 | // bsBlockUsed.setBit( *j, false ); |
475 | iUsed--; | 475 | iUsed--; |
476 | } | 476 | } |
477 | aStreams.erase( i ); | 477 | aStreams.erase( i ); |
478 | bHeaderChanged = true; | 478 | bHeaderChanged = true; |
479 | delete pStream; | 479 | delete pStream; |
480 | return; | 480 | return; |
481 | } | 481 | } |
482 | } | 482 | } |
483 | } | 483 | } |
484 | 484 | ||
485 | Bu::Array<int> Bu::Myriad::getStreamIds() | 485 | Bu::Array<int> Bu::Myriad::getStreamIds() |
486 | { | 486 | { |
487 | MutexLocker mLock( mHeader ); | 487 | MutexLocker mLock( mHeader ); |
488 | 488 | ||
489 | Bu::Array<int> aRet( aStreams.getSize() ); | 489 | Bu::Array<int> aRet( aStreams.getSize() ); |
490 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 490 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
491 | { | 491 | { |
492 | aRet.append( (*i)->iId ); | 492 | aRet.append( (*i)->iId ); |
493 | } | 493 | } |
494 | 494 | ||
495 | return aRet; | 495 | return aRet; |
496 | } | 496 | } |
497 | 497 | ||
498 | int Bu::Myriad::getStreamSize( int iId ) | 498 | int Bu::Myriad::getStreamSize( int iId ) |
499 | { | 499 | { |
500 | MutexLocker mLock( mHeader ); | 500 | MutexLocker mLock( mHeader ); |
501 | 501 | ||
502 | return findStream( iId )->iSize; | 502 | return findStream( iId )->iSize; |
503 | } | 503 | } |
504 | 504 | ||
505 | bool Bu::Myriad::hasStream( int iId ) | 505 | bool Bu::Myriad::hasStream( int iId ) |
506 | { | 506 | { |
507 | MutexLocker mLock( mHeader ); | 507 | MutexLocker mLock( mHeader ); |
508 | 508 | ||
509 | try | 509 | try |
510 | { | 510 | { |
511 | findStream( iId ); | 511 | findStream( iId ); |
512 | return true; | 512 | return true; |
513 | }catch(...) | 513 | }catch(...) |
514 | { | 514 | { |
515 | return false; | 515 | return false; |
516 | } | 516 | } |
517 | } | 517 | } |
518 | 518 | ||
519 | Bu::MyriadStream Bu::Myriad::openStream( int iId ) | 519 | Bu::MyriadStream Bu::Myriad::openStream( int iId ) |
520 | { | 520 | { |
521 | MutexLocker mLock( mHeader ); | 521 | MutexLocker mLock( mHeader ); |
522 | 522 | ||
523 | //sio << "Myriad: Request to open stream: " << iId << sio.nl; | 523 | //sio << "Myriad: Request to open stream: " << iId << sio.nl; |
524 | return MyriadStream( *this, findStream( iId ) ); | 524 | return MyriadStream( *this, findStream( iId ) ); |
525 | } | 525 | } |
526 | 526 | ||
527 | int Bu::Myriad::getNumStreams() | 527 | int Bu::Myriad::getNumStreams() |
528 | { | 528 | { |
529 | MutexLocker mLock( mHeader ); | 529 | MutexLocker mLock( mHeader ); |
530 | 530 | ||
531 | return aStreams.getSize(); | 531 | return aStreams.getSize(); |
532 | } | 532 | } |
533 | 533 | ||
534 | int Bu::Myriad::getBlockSize() | 534 | int Bu::Myriad::getBlockSize() |
535 | { | 535 | { |
536 | return iBlockSize; | 536 | return iBlockSize; |
537 | } | 537 | } |
538 | 538 | ||
539 | int Bu::Myriad::getNumBlocks() | 539 | int Bu::Myriad::getNumBlocks() |
540 | { | 540 | { |
541 | return iBlocks; | 541 | return iBlocks; |
542 | } | 542 | } |
543 | 543 | ||
544 | int Bu::Myriad::getNumUsedBlocks() | 544 | int Bu::Myriad::getNumUsedBlocks() |
545 | { | 545 | { |
546 | return iUsed; | 546 | return iUsed; |
547 | } | 547 | } |
548 | 548 | ||
549 | Bu::size Bu::Myriad::getTotalUsedBytes() | 549 | Bu::size Bu::Myriad::getTotalUsedBytes() |
550 | { | 550 | { |
551 | MutexLocker mLock( mHeader ); | 551 | MutexLocker mLock( mHeader ); |
552 | 552 | ||
553 | Bu::size iTotalSize = 0; | 553 | Bu::size iTotalSize = 0; |
554 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 554 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
555 | { | 555 | { |
556 | iTotalSize += (*i)->iSize; | 556 | iTotalSize += (*i)->iSize; |
557 | } | 557 | } |
558 | return iTotalSize; | 558 | return iTotalSize; |
559 | } | 559 | } |
560 | 560 | ||
561 | Bu::size Bu::Myriad::getTotalUnusedBytes() | 561 | Bu::size Bu::Myriad::getTotalUnusedBytes() |
562 | { | 562 | { |
563 | MutexLocker mLock( mHeader ); | 563 | MutexLocker mLock( mHeader ); |
564 | 564 | ||
565 | Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; | 565 | Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; |
566 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 566 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
567 | { | 567 | { |
568 | iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); | 568 | iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); |
569 | } | 569 | } |
570 | return iTotalSize; | 570 | return iTotalSize; |
571 | } | 571 | } |
572 | 572 | ||
573 | Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) | 573 | Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) |
574 | { | 574 | { |
575 | MutexLocker mLock( mHeader ); | 575 | MutexLocker mLock( mHeader ); |
576 | 576 | ||
577 | Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; | 577 | Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; |
578 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 578 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
579 | { | 579 | { |
580 | iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); | 580 | iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); |
581 | } | 581 | } |
582 | return iTotalSize; | 582 | return iTotalSize; |
583 | } | 583 | } |
584 | 584 | ||
585 | Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) | 585 | Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) |
586 | { | 586 | { |
587 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 587 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
588 | { | 588 | { |
589 | if( (*i)->iId == iId ) | 589 | if( (*i)->iId == iId ) |
590 | return *i; | 590 | return *i; |
591 | } | 591 | } |
592 | 592 | ||
593 | throw MyriadException( MyriadException::noSuchStream, | 593 | throw MyriadException( MyriadException::noSuchStream, |
594 | "The requested stream doesn't exist and cannot be opened." ); | 594 | "The requested stream doesn't exist and cannot be opened." ); |
595 | 595 | ||
596 | return NULL; | 596 | return NULL; |
597 | } | 597 | } |
598 | 598 | ||
599 | Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) | 599 | Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) |
600 | { | 600 | { |
601 | // sio << "Myriad: Reading block " << iBlock << ", bytes " | 601 | // sio << "Myriad: Reading block " << iBlock << ", bytes " |
602 | // << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; | 602 | // << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; |
603 | Block *pBlock = new Block; | 603 | Block *pBlock = new Block; |
604 | pBlock->pData = new char[iBlockSize]; | 604 | pBlock->pData = new char[iBlockSize]; |
605 | sStore.setPos( iBlockSize * (Bu::size)iBlock ); | 605 | sStore.setPos( iBlockSize * (Bu::size)iBlock ); |
606 | sStore.read( pBlock->pData, iBlockSize ); | 606 | sStore.read( pBlock->pData, iBlockSize ); |
607 | pBlock->bChanged = false; | 607 | pBlock->bChanged = false; |
608 | pBlock->iBlockIndex = iBlock; | 608 | pBlock->iBlockIndex = iBlock; |
609 | 609 | ||
610 | mActiveBlocks.lock(); | 610 | mActiveBlocks.lock(); |
611 | hActiveBlocks.insert( iBlock, pBlock ); | 611 | hActiveBlocks.insert( iBlock, pBlock ); |
612 | mActiveBlocks.unlock(); | 612 | mActiveBlocks.unlock(); |
613 | 613 | ||
614 | return pBlock; | 614 | return pBlock; |
615 | } | 615 | } |
616 | 616 | ||
617 | void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) | 617 | void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) |
618 | { | 618 | { |
619 | if( pBlock == NULL ) | 619 | if( pBlock == NULL ) |
620 | return; | 620 | return; |
621 | // sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; | 621 | // sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; |
622 | syncBlock( pBlock ); | 622 | syncBlock( pBlock ); |
623 | mActiveBlocks.lock(); | 623 | mActiveBlocks.lock(); |
624 | hActiveBlocks.erase( pBlock->iBlockIndex ); | 624 | hActiveBlocks.erase( pBlock->iBlockIndex ); |
625 | mActiveBlocks.unlock(); | 625 | mActiveBlocks.unlock(); |
626 | 626 | ||
627 | delete[] pBlock->pData; | 627 | delete[] pBlock->pData; |
628 | delete pBlock; | 628 | delete pBlock; |
629 | } | 629 | } |
630 | 630 | ||
631 | void Bu::Myriad::syncBlock( Block *pBlock ) | 631 | void Bu::Myriad::syncBlock( Block *pBlock ) |
632 | { | 632 | { |
633 | if( pBlock->bChanged ) | 633 | if( pBlock->bChanged ) |
634 | { | 634 | { |
635 | // sio << "Myriad: - Block changed, writing back to stream." << sio.nl; | 635 | // sio << "Myriad: - Block changed, writing back to stream." << sio.nl; |
636 | sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); | 636 | sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); |
637 | sStore.write( pBlock->pData, iBlockSize ); | 637 | sStore.write( pBlock->pData, iBlockSize ); |
638 | pBlock->bChanged = false; | 638 | pBlock->bChanged = false; |
639 | } | 639 | } |
640 | } | 640 | } |
641 | 641 | ||
642 | int Bu::Myriad::streamAddBlock( Stream *pStream ) | 642 | int Bu::Myriad::streamAddBlock( Stream *pStream ) |
643 | { | 643 | { |
644 | MutexLocker mLock( mHeader ); | 644 | MutexLocker mLock( mHeader ); |
645 | 645 | ||
646 | int iBlock = findEmptyBlock(); | 646 | int iBlock = findEmptyBlock(); |
647 | pStream->aBlocks.append( iBlock ); | 647 | pStream->aBlocks.append( iBlock ); |
648 | // bsBlockUsed.setBit( iBlock ); | 648 | // bsBlockUsed.setBit( iBlock ); |
649 | // bHeaderChanged = true; | 649 | // bHeaderChanged = true; |
650 | iUsed++; | 650 | iUsed++; |
651 | return iBlock; | 651 | return iBlock; |
652 | } | 652 | } |
653 | 653 | ||
654 | void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) | 654 | void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) |
655 | { | 655 | { |
656 | MutexLocker mLock( mHeader ); | 656 | MutexLocker mLock( mHeader ); |
657 | 657 | ||
658 | if( pStream->iSize == iSize ) | 658 | if( pStream->iSize == iSize ) |
659 | { | 659 | { |
660 | return; | 660 | return; |
661 | } | 661 | } |
662 | else if( pStream->iSize > iSize ) | 662 | else if( pStream->iSize > iSize ) |
663 | { | 663 | { |
664 | // Shrink | 664 | // Shrink |
665 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; | 665 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; |
666 | iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) | 666 | iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) |
667 | { | 667 | { |
668 | // if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) | 668 | // if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) |
669 | iUsed--; | 669 | iUsed--; |
670 | // else | 670 | // else |
671 | // sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; | 671 | // sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; |
672 | lFreeBlocks.enqueue( pStream->aBlocks.last() ); | 672 | lFreeBlocks.enqueue( pStream->aBlocks.last() ); |
673 | // bsBlockUsed.setBit( pStream->aBlocks.last(), false ); | 673 | // bsBlockUsed.setBit( pStream->aBlocks.last(), false ); |
674 | pStream->aBlocks.eraseLast(); | 674 | pStream->aBlocks.eraseLast(); |
675 | } | 675 | } |
676 | pStream->iSize = iSize; | 676 | pStream->iSize = iSize; |
677 | bHeaderChanged = true; | 677 | bHeaderChanged = true; |
678 | } | 678 | } |
679 | else | 679 | else |
680 | { | 680 | { |
681 | // Grow | 681 | // Grow |
682 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; | 682 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; |
683 | iNewSize < iSize; iNewSize += iBlockSize ) | 683 | iNewSize < iSize; iNewSize += iBlockSize ) |
684 | { | 684 | { |
685 | //streamAddBlock( pStream ); | 685 | //streamAddBlock( pStream ); |
686 | int iBlock = findEmptyBlock(); | 686 | int iBlock = findEmptyBlock(); |
687 | pStream->aBlocks.append( iBlock ); | 687 | pStream->aBlocks.append( iBlock ); |
688 | // bsBlockUsed.setBit( iBlock ); | 688 | // bsBlockUsed.setBit( iBlock ); |
689 | // bHeaderChanged = true; | 689 | // bHeaderChanged = true; |
690 | iUsed++; | 690 | iUsed++; |
691 | } | 691 | } |
692 | pStream->iSize = iSize; | 692 | pStream->iSize = iSize; |
693 | bHeaderChanged = true; | 693 | bHeaderChanged = true; |
694 | } | 694 | } |
695 | } | 695 | } |
696 | 696 | ||
697 | void Bu::Myriad::headerChanged() | 697 | void Bu::Myriad::headerChanged() |
698 | { | 698 | { |
699 | bHeaderChanged = true; | 699 | bHeaderChanged = true; |
700 | } | 700 | } |
701 | 701 | ||
702 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) | 702 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) |
703 | { | 703 | { |
704 | uint8_t uTmp; | 704 | uint8_t uTmp; |
705 | 705 | ||
706 | return isMyriad( sStore, uTmp ); | 706 | return isMyriad( sStore, uTmp ); |
707 | } | 707 | } |
708 | 708 | ||
709 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) | 709 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) |
710 | { | 710 | { |
711 | sStore.setPos( 0 ); | 711 | sStore.setPos( 0 ); |
712 | 712 | ||
713 | unsigned char buf[4]; | 713 | unsigned char buf[4]; |
714 | if( sStore.read( buf, 4 ) < 4 ) | 714 | if( sStore.read( buf, 4 ) < 4 ) |
715 | throw MyriadException( MyriadException::emptyStream, | 715 | throw MyriadException( MyriadException::emptyStream, |
716 | "Input stream appears to be empty."); | 716 | "Input stream appears to be empty."); |
717 | sStore.read( &uTmp, 1 ); | 717 | sStore.read( &uTmp, 1 ); |
718 | sStore.setPos( 0 ); | 718 | sStore.setPos( 0 ); |
719 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | 719 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) |
720 | { | 720 | { |
721 | return false; | 721 | return false; |
722 | } | 722 | } |
723 | return true; | 723 | return true; |
724 | } | 724 | } |
725 | 725 | ||
726 | const Bu::BitString Bu::Myriad::getBlocksUsed() const | 726 | const Bu::BitString Bu::Myriad::getBlocksUsed() const |
727 | { | 727 | { |
728 | Bu::BitString bs( iBlocks, false ); | 728 | Bu::BitString bs( iBlocks, false ); |
729 | for( int j = 0; j < iBlocks; j++ ) | 729 | for( int j = 0; j < iBlocks; j++ ) |
730 | bs.setBit( j ); | 730 | bs.setBit( j ); |
731 | for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) | 731 | for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) |
732 | bs.setBit( *i, false ); | 732 | bs.setBit( *i, false ); |
733 | return bs; | 733 | return bs; |
734 | } | 734 | } |
735 | 735 | ||
diff --git a/src/stable/myriad.h b/src/stable/myriad.h index 6b1db41..4bfd88e 100644 --- a/src/stable/myriad.h +++ b/src/stable/myriad.h | |||
@@ -18,219 +18,219 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | class Stream; | 21 | class Stream; |
22 | class MyriadStream; | 22 | class MyriadStream; |
23 | 23 | ||
24 | subExceptionDeclBegin( MyriadException ) | 24 | subExceptionDeclBegin( MyriadException ) |
25 | enum | 25 | enum |
26 | { | 26 | { |
27 | emptyStream, | 27 | emptyStream, |
28 | invalidFormat, | 28 | invalidFormat, |
29 | badVersion, | 29 | badVersion, |
30 | invalidWordSize, | 30 | invalidWordSize, |
31 | noSuchStream, | 31 | noSuchStream, |
32 | streamExists, | 32 | streamExists, |
33 | invalidStreamId, | 33 | invalidStreamId, |
34 | protectedStream | 34 | protectedStream |
35 | }; | 35 | }; |
36 | subExceptionDeclEnd(); | 36 | subExceptionDeclEnd(); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Myriad block-allocated stream multiplexing system. This is a system for | 39 | * Myriad block-allocated stream multiplexing system. This is a system for |
40 | * creating streams that contain other streams in a flexible and lightweight | 40 | * creating streams that contain other streams in a flexible and lightweight |
41 | * manner. Basically, you can create a file (or any other stream) that can | 41 | * manner. Basically, you can create a file (or any other stream) that can |
42 | * store any number of flexible, growing streams. The streams within the | 42 | * store any number of flexible, growing streams. The streams within the |
43 | * Myriad stream are automatically numbered, not named. This works more | 43 | * Myriad stream are automatically numbered, not named. This works more |
44 | * or less like a filesystem, but without the extra layer for managing | 44 | * or less like a filesystem, but without the extra layer for managing |
45 | * file and directory links. This would actually be very easy to add | 45 | * file and directory links. This would actually be very easy to add |
46 | * on top of Myriad, but is not required. | 46 | * on top of Myriad, but is not required. |
47 | * | 47 | * |
48 | * Header format is as follows: | 48 | * Header format is as follows: |
49 | * | 49 | * |
50 | * MMMMvBssssSSSS* | 50 | * MMMMvBssssSSSS* |
51 | * M = Magic number (0AD3FA84) | 51 | * M = Magic number (0AD3FA84) |
52 | * v = version number | 52 | * v = version number |
53 | * B = Bits per int | 53 | * B = Bits per int |
54 | * s = Blocksize in bytes | 54 | * s = Blocksize in bytes |
55 | * S = Number of Streams | 55 | * S = Number of Streams |
56 | * | 56 | * |
57 | * The * represents the Stream headers, one per stream, as follows: | 57 | * The * represents the Stream headers, one per stream, as follows: |
58 | * IIIIssss$ | 58 | * IIIIssss$ |
59 | * I = Id number of the stream | 59 | * I = Id number of the stream |
60 | * s = size of stream in bytes | 60 | * s = size of stream in bytes |
61 | * | 61 | * |
62 | * The $ represents the Block headers, one per used block, as follows: | 62 | * The $ represents the Block headers, one per used block, as follows: |
63 | * IIII | 63 | * IIII |
64 | * I = Index of the block | 64 | * I = Index of the block |
65 | * | 65 | * |
66 | * The stream/block data is interleaved in the header, so all blocks stored | 66 | * The stream/block data is interleaved in the header, so all blocks stored |
67 | * with one stream are together. The block headers are in order, and the | 67 | * with one stream are together. The block headers are in order, and the |
68 | * data in them is required to be "solid" you cannot fill partial blocks | 68 | * data in them is required to be "solid" you cannot fill partial blocks |
69 | * mid-way through a stream. | 69 | * mid-way through a stream. |
70 | * | 70 | * |
71 | * The initial block starts with the nids header, and is both the zero block | 71 | * The initial block starts with the nids header, and is both the zero block |
72 | * and the zero stream. For now, the minimum block size is the size needed | 72 | * and the zero stream. For now, the minimum block size is the size needed |
73 | * to store the base header, the zero stream header, and the first two | 73 | * to store the base header, the zero stream header, and the first two |
74 | * blocks of the zero stream, so 30 bytes. Since it's reccomended to use | 74 | * blocks of the zero stream, so 30 bytes. Since it's reccomended to use |
75 | * a size that will fit evenly into filesystem blocks, then a size of 32 is | 75 | * a size that will fit evenly into filesystem blocks, then a size of 32 is |
76 | * probably the smallest reccomended size because all powers of two equal | 76 | * probably the smallest reccomended size because all powers of two equal |
77 | * to or greater than 32 are evenly divisible by 32. | 77 | * to or greater than 32 are evenly divisible by 32. |
78 | * | 78 | * |
79 | * I have had a thought that if the block size were smaller than 42 bytes | 79 | * I have had a thought that if the block size were smaller than 42 bytes |
80 | * the header would consume the first N blocks where N * block size is | 80 | * the header would consume the first N blocks where N * block size is |
81 | * enough space to house the initial header, the first stream header, and | 81 | * enough space to house the initial header, the first stream header, and |
82 | * the first N block headers. This, of course, causes you to hit an | 82 | * the first N block headers. This, of course, causes you to hit an |
83 | * infinite header if the block size is small enough. | 83 | * infinite header if the block size is small enough. |
84 | */ | 84 | */ |
85 | class Myriad | 85 | class Myriad |
86 | { | 86 | { |
87 | friend class MyriadStream; | 87 | friend class MyriadStream; |
88 | public: | 88 | public: |
89 | /** | 89 | /** |
90 | * Create a Myriad object that uses the given stream to store data. | 90 | * Create a Myriad object that uses the given stream to store data. |
91 | * This stream must be random access. The block size and preallocate | 91 | * This stream must be random access. The block size and preallocate |
92 | * values passed in are values that will be used if the given stream | 92 | * values passed in are values that will be used if the given stream |
93 | * is empty. In that case the stream will be "formatted" for myriad | 93 | * is empty. In that case the stream will be "formatted" for myriad |
94 | * with the specified block size. If there is already a viable Myriad | 94 | * with the specified block size. If there is already a viable Myriad |
95 | * format present in the stream, then the blocksize and preallocate | 95 | * format present in the stream, then the blocksize and preallocate |
96 | * values will be ignored and the values from the stream will be used | 96 | * values will be ignored and the values from the stream will be used |
97 | * instead. If the stream doesn't appear to be Myriad formatted an | 97 | * instead. If the stream doesn't appear to be Myriad formatted an |
98 | * exception will be thrown. | 98 | * exception will be thrown. |
99 | */ | 99 | */ |
100 | Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); | 100 | Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); |
101 | virtual ~Myriad(); | 101 | virtual ~Myriad(); |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Destroy whatever data may be in the base stream and create a new | 104 | * Destroy whatever data may be in the base stream and create a new |
105 | * Myriad system there with the given blocksize. Use this with care, | 105 | * Myriad system there with the given blocksize. Use this with care, |
106 | * it will destroy anything that was already in the stream, and | 106 | * it will destroy anything that was already in the stream, and |
107 | * generally, should not ever have to be used. | 107 | * generally, should not ever have to be used. |
108 | */ | 108 | */ |
109 | void initialize( int iBlockSize, int iPreAllocate=1 ); | 109 | void initialize( int iBlockSize, int iPreAllocate=1 ); |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * Create a new stream within the Myriad system. The ID of the new | 112 | * Create a new stream within the Myriad system. The ID of the new |
113 | * stream is returned. | 113 | * stream is returned. |
114 | */ | 114 | */ |
115 | int createStream( int iPreAllocate=1 ); | 115 | int createStream( int iPreAllocate=1 ); |
116 | 116 | ||
117 | /** | 117 | /** |
118 | * Create a new stream within the Myriad system with a given id. The | 118 | * Create a new stream within the Myriad system with a given id. The |
119 | * id that you provide will be the new id of the stream unless it's | 119 | * id that you provide will be the new id of the stream unless it's |
120 | * already used, in which case an error is thrown. This is primarilly | 120 | * already used, in which case an error is thrown. This is primarilly |
121 | * useful when copying an old Myriad file into a new one. | 121 | * useful when copying an old Myriad file into a new one. |
122 | */ | 122 | */ |
123 | int createStreamWithId( int iId, int iPreAllocate=1 ); | 123 | int createStreamWithId( int iId, int iPreAllocate=1 ); |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * Delete a stream that's already within the Myriad. | 126 | * Delete a stream that's already within the Myriad. |
127 | */ | 127 | */ |
128 | void deleteStream( int iId ); | 128 | void deleteStream( int iId ); |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * Return a new Stream object assosiated with the given stream ID. | 131 | * Return a new Stream object assosiated with the given stream ID. |
132 | */ | 132 | */ |
133 | MyriadStream openStream( int iId ); | 133 | MyriadStream openStream( int iId ); |
134 | 134 | ||
135 | Bu::Array<int> getStreamIds(); | 135 | Bu::Array<int> getStreamIds(); |
136 | int getStreamSize( int iId ); | 136 | int getStreamSize( int iId ); |
137 | bool hasStream( int iId ); | 137 | bool hasStream( int iId ); |
138 | 138 | ||
139 | int getNumStreams(); | 139 | int getNumStreams(); |
140 | int getBlockSize(); | 140 | int getBlockSize(); |
141 | int getNumBlocks(); | 141 | int getNumBlocks(); |
142 | int getNumUsedBlocks(); | 142 | int getNumUsedBlocks(); |
143 | Bu::size getTotalUsedBytes(); | 143 | Bu::size getTotalUsedBytes(); |
144 | Bu::size getTotalUnusedBytes(); | 144 | Bu::size getTotalUnusedBytes(); |
145 | Bu::size getTotalUnusedBytes( int iFakeBlockSize ); | 145 | Bu::size getTotalUnusedBytes( int iFakeBlockSize ); |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * Syncronize the header data, etc. with the storage stream. It's not | 148 | * Syncronize the header data, etc. with the storage stream. It's not |
149 | * a bad idea to call this periodically. | 149 | * a bad idea to call this periodically. |
150 | */ | 150 | */ |
151 | void sync(); | 151 | void sync(); |
152 | 152 | ||
153 | /** | 153 | /** |
154 | * Read the first few bytes from the given stream and return true/false | 154 | * Read the first few bytes from the given stream and return true/false |
155 | * depending on weather or not it's a Myriad stream. This will throw | 155 | * depending on weather or not it's a Myriad stream. This will throw |
156 | * an exception if the stream is empty, or is not random access. | 156 | * an exception if the stream is empty, or is not random access. |
157 | */ | 157 | */ |
158 | static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); | 158 | static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Read the first few bytes from the given stream and return true/false | 161 | * Read the first few bytes from the given stream and return true/false |
162 | * depending on weather or not it's a Myriad stream. This will throw | 162 | * depending on weather or not it's a Myriad stream. This will throw |
163 | * an exception if the stream is empty, or is not random access. | 163 | * an exception if the stream is empty, or is not random access. |
164 | */ | 164 | */ |
165 | static bool isMyriad( Bu::Stream &sStore ); | 165 | static bool isMyriad( Bu::Stream &sStore ); |
166 | 166 | ||
167 | const Bu::BitString getBlocksUsed() const; | 167 | const Bu::BitString getBlocksUsed() const; |
168 | 168 | ||
169 | private: | 169 | private: |
170 | /** | 170 | /** |
171 | * Initialize this object based on the data already in the assosiated | 171 | * Initialize this object based on the data already in the assosiated |
172 | * stream. This will be called automatically for you if you forget, | 172 | * stream. This will be called automatically for you if you forget, |
173 | * but if you want to pre-initialize for some reason, just call this | 173 | * but if you want to pre-initialize for some reason, just call this |
174 | * once before you actually start doing anything with your Myriad. | 174 | * once before you actually start doing anything with your Myriad. |
175 | */ | 175 | */ |
176 | void initialize(); | 176 | void initialize(); |
177 | 177 | ||
178 | enum | 178 | enum |
179 | { | 179 | { |
180 | blockUnused = 0xFFFFFFFFUL | 180 | blockUnused = 0xFFFFFFFFUL |
181 | }; | 181 | }; |
182 | 182 | ||
183 | typedef Bu::Array<int> BlockArray; | 183 | typedef Bu::Array<int> BlockArray; |
184 | class Stream | 184 | class Stream |
185 | { | 185 | { |
186 | public: | 186 | public: |
187 | int iId; | 187 | int iId; |
188 | int iSize; | 188 | int iSize; |
189 | BlockArray aBlocks; | 189 | BlockArray aBlocks; |
190 | }; | 190 | }; |
191 | typedef Bu::Array<Stream *> StreamArray; | 191 | typedef Bu::Array<Stream *> StreamArray; |
192 | 192 | ||
193 | class Block | 193 | class Block |
194 | { | 194 | { |
195 | public: | 195 | public: |
196 | char *pData; | 196 | char *pData; |
197 | bool bChanged; | 197 | bool bChanged; |
198 | int iBlockIndex; | 198 | int iBlockIndex; |
199 | }; | 199 | }; |
200 | 200 | ||
201 | void updateHeader(); | 201 | void updateHeader(); |
202 | int findEmptyBlock(); | 202 | int findEmptyBlock(); |
203 | 203 | ||
204 | /** | 204 | /** |
205 | *@todo Change this to use a binary search, it's nicer. | 205 | *@todo Change this to use a binary search, it's nicer. |
206 | */ | 206 | */ |
207 | Stream *findStream( int iId ); | 207 | Stream *findStream( int iId ); |
208 | 208 | ||
209 | Block *getBlock( int iBlock ); | 209 | Block *getBlock( int iBlock ); |
210 | void releaseBlock( Block *pBlock ); | 210 | void releaseBlock( Block *pBlock ); |
211 | void syncBlock( Block *pBlock ); | 211 | void syncBlock( Block *pBlock ); |
212 | 212 | ||
213 | int streamAddBlock( Stream *pStream ); | 213 | int streamAddBlock( Stream *pStream ); |
214 | void setStreamSize( Stream *pStream, long iSize ); | 214 | void setStreamSize( Stream *pStream, long iSize ); |
215 | 215 | ||
216 | void headerChanged(); | 216 | void headerChanged(); |
217 | 217 | ||
218 | private: | 218 | private: |
219 | Bu::Stream &sStore; | 219 | Bu::Stream &sStore; |
220 | int iBlockSize; | 220 | int iBlockSize; |
221 | int iBlocks; | 221 | int iBlocks; |
222 | int iUsed; | 222 | int iUsed; |
223 | typedef Bu::List<int> IndexList; | 223 | typedef Bu::List<int> IndexList; |
224 | IndexList lFreeBlocks; | 224 | IndexList lFreeBlocks; |
225 | // Bu::BitString bsBlockUsed; | 225 | // Bu::BitString bsBlockUsed; |
226 | StreamArray aStreams; | 226 | StreamArray aStreams; |
227 | typedef Bu::Hash<int, Block *> BlockHash; | 227 | typedef Bu::Hash<int, Block *> BlockHash; |
228 | BlockHash hActiveBlocks; | 228 | BlockHash hActiveBlocks; |
229 | bool bHeaderChanged; | 229 | bool bHeaderChanged; |
230 | 230 | ||
231 | Bu::Mutex mHeader; | 231 | Bu::Mutex mHeader; |
232 | Bu::Mutex mActiveBlocks; | 232 | Bu::Mutex mActiveBlocks; |
233 | }; | 233 | }; |
234 | }; | 234 | }; |
235 | 235 | ||
236 | #endif | 236 | #endif |
diff --git a/src/stable/myriadstream.cpp b/src/stable/myriadstream.cpp index 58d3936..c33445a 100644 --- a/src/stable/myriadstream.cpp +++ b/src/stable/myriadstream.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include <string.h> | 10 | #include <string.h> |
11 | 11 | ||
12 | // #define MYRIAD_STREAM_DEBUG 1 | 12 | // #define MYRIAD_STREAM_DEBUG 1 |
13 | 13 | ||
14 | #ifdef MYRIAD_STREAM_DEBUG | 14 | #ifdef MYRIAD_STREAM_DEBUG |
15 | #include "bu/sio.h" | 15 | #include "bu/sio.h" |
@@ -19,27 +19,27 @@ using Bu::Fmt; | |||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, | 21 | Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, |
22 | Bu::Myriad::Stream *pStream ) : | 22 | Bu::Myriad::Stream *pStream ) : |
23 | rMyriad( rMyriad ), | 23 | rMyriad( rMyriad ), |
24 | pStream( pStream ), | 24 | pStream( pStream ), |
25 | pCurBlock( NULL ), | 25 | pCurBlock( NULL ), |
26 | iPos( 0 ) | 26 | iPos( 0 ) |
27 | { | 27 | { |
28 | #ifdef MYRIAD_STREAM_DEBUG | 28 | #ifdef MYRIAD_STREAM_DEBUG |
29 | sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" | 29 | sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" |
30 | << pStream->iSize << sio.nl; | 30 | << pStream->iSize << sio.nl; |
31 | #endif | 31 | #endif |
32 | //pCurBlock = rMyriad.newBlock(); | 32 | //pCurBlock = rMyriad.newBlock(); |
33 | //rMyriad.getBlock( uStream, pCurBlock ); | 33 | //rMyriad.getBlock( uStream, pCurBlock ); |
34 | //uSize = pCurBlock->uBytesUsed; | 34 | //uSize = pCurBlock->uBytesUsed; |
35 | } | 35 | } |
36 | 36 | ||
37 | Bu::MyriadStream::~MyriadStream() | 37 | Bu::MyriadStream::~MyriadStream() |
38 | { | 38 | { |
39 | if( pCurBlock ) | 39 | if( pCurBlock ) |
40 | rMyriad.releaseBlock( pCurBlock ); | 40 | rMyriad.releaseBlock( pCurBlock ); |
41 | //rMyriad.updateStreamSize( uStream, uSize ); | 41 | //rMyriad.updateStreamSize( uStream, uSize ); |
42 | //rMyriad.deleteBlock( pCurBlock ); | 42 | //rMyriad.deleteBlock( pCurBlock ); |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::MyriadStream::close() | 45 | void Bu::MyriadStream::close() |
@@ -49,200 +49,200 @@ void Bu::MyriadStream::close() | |||
49 | Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) | 49 | Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) |
50 | { | 50 | { |
51 | #ifdef MYRIAD_STREAM_DEBUG | 51 | #ifdef MYRIAD_STREAM_DEBUG |
52 | sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." | 52 | sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." |
53 | << sio.nl; | 53 | << sio.nl; |
54 | #endif | 54 | #endif |
55 | if( nBytes > (Bu::size)pStream->iSize-iPos ) | 55 | if( nBytes > (Bu::size)pStream->iSize-iPos ) |
56 | nBytes = pStream->iSize-iPos; | 56 | nBytes = pStream->iSize-iPos; |
57 | if( nBytes <= 0 ) | 57 | if( nBytes <= 0 ) |
58 | return 0; | 58 | return 0; |
59 | int iLeft = nBytes; | 59 | int iLeft = nBytes; |
60 | #ifdef MYRIAD_STREAM_DEBUG | 60 | #ifdef MYRIAD_STREAM_DEBUG |
61 | sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." | 61 | sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." |
62 | << sio.nl; | 62 | << sio.nl; |
63 | #endif | 63 | #endif |
64 | if( pCurBlock == NULL ) | 64 | if( pCurBlock == NULL ) |
65 | { | 65 | { |
66 | #ifdef MYRIAD_STREAM_DEBUG | 66 | #ifdef MYRIAD_STREAM_DEBUG |
67 | sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." | 67 | sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." |
68 | << sio.nl; | 68 | << sio.nl; |
69 | #endif | 69 | #endif |
70 | pCurBlock = rMyriad.getBlock( | 70 | pCurBlock = rMyriad.getBlock( |
71 | pStream->aBlocks[iPos/rMyriad.iBlockSize] | 71 | pStream->aBlocks[iPos/rMyriad.iBlockSize] |
72 | ); | 72 | ); |
73 | } | 73 | } |
74 | while( iLeft > 0 ) | 74 | while( iLeft > 0 ) |
75 | { | 75 | { |
76 | int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; | 76 | int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; |
77 | if( pCurBlock->iBlockIndex != iCurBlock ) | 77 | if( pCurBlock->iBlockIndex != iCurBlock ) |
78 | { | 78 | { |
79 | #ifdef MYRIAD_STREAM_DEBUG | 79 | #ifdef MYRIAD_STREAM_DEBUG |
80 | sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." | 80 | sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." |
81 | << sio.nl; | 81 | << sio.nl; |
82 | #endif | 82 | #endif |
83 | rMyriad.releaseBlock( pCurBlock ); | 83 | rMyriad.releaseBlock( pCurBlock ); |
84 | pCurBlock = rMyriad.getBlock( iCurBlock ); | 84 | pCurBlock = rMyriad.getBlock( iCurBlock ); |
85 | } | 85 | } |
86 | 86 | ||
87 | int iAmnt = Bu::buMin( | 87 | int iAmnt = Bu::buMin( |
88 | Bu::buMin( | 88 | Bu::buMin( |
89 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 89 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
90 | iLeft | 90 | iLeft |
91 | ), | 91 | ), |
92 | pStream->iSize-iPos | 92 | pStream->iSize-iPos |
93 | ); | 93 | ); |
94 | #ifdef MYRIAD_STREAM_DEBUG | 94 | #ifdef MYRIAD_STREAM_DEBUG |
95 | sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " | 95 | sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " |
96 | << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" | 96 | << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" |
97 | << iAmnt | 97 | << iAmnt |
98 | << ", " << iLeft << "b left." << sio.nl; | 98 | << ", " << iLeft << "b left." << sio.nl; |
99 | #endif | 99 | #endif |
100 | memcpy( | 100 | memcpy( |
101 | pBuf, | 101 | pBuf, |
102 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 102 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
103 | iAmnt | 103 | iAmnt |
104 | ); | 104 | ); |
105 | iPos += iAmnt; | 105 | iPos += iAmnt; |
106 | pBuf = &((char *)pBuf)[iAmnt]; | 106 | pBuf = &((char *)pBuf)[iAmnt]; |
107 | iLeft -= iAmnt; | 107 | iLeft -= iAmnt; |
108 | } | 108 | } |
109 | return nBytes; | 109 | return nBytes; |
110 | } | 110 | } |
111 | 111 | ||
112 | Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) | 112 | Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) |
113 | { | 113 | { |
114 | if( nBytes <= 0 ) | 114 | if( nBytes <= 0 ) |
115 | return 0; | 115 | return 0; |
116 | 116 | ||
117 | #ifdef MYRIAD_STREAM_DEBUG | 117 | #ifdef MYRIAD_STREAM_DEBUG |
118 | sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." | 118 | sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." |
119 | << sio.nl; | 119 | << sio.nl; |
120 | #endif | 120 | #endif |
121 | if( nBytes <= 0 ) | 121 | if( nBytes <= 0 ) |
122 | return 0; | 122 | return 0; |
123 | int iLeft = nBytes; | 123 | int iLeft = nBytes; |
124 | /* | 124 | /* |
125 | if( pCurBlock == NULL ) | 125 | if( pCurBlock == NULL ) |
126 | { | 126 | { |
127 | #ifdef MYRIAD_STREAM_DEBUG | 127 | #ifdef MYRIAD_STREAM_DEBUG |
128 | sio << "MyriadStream: write: No block loaded, loading initial block." | 128 | sio << "MyriadStream: write: No block loaded, loading initial block." |
129 | << sio.nl; | 129 | << sio.nl; |
130 | #endif | 130 | #endif |
131 | pCurBlock = rMyriad.getBlock( | 131 | pCurBlock = rMyriad.getBlock( |
132 | pStream->aBlocks[iPos/rMyriad.iBlockSize] | 132 | pStream->aBlocks[iPos/rMyriad.iBlockSize] |
133 | ); | 133 | ); |
134 | }*/ | 134 | }*/ |
135 | 135 | ||
136 | while( iLeft > 0 ) | 136 | while( iLeft > 0 ) |
137 | { | 137 | { |
138 | int iCurBlock; | 138 | int iCurBlock; |
139 | if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) | 139 | if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) |
140 | { | 140 | { |
141 | iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; | 141 | iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; |
142 | } | 142 | } |
143 | else | 143 | else |
144 | { | 144 | { |
145 | iCurBlock = rMyriad.streamAddBlock( pStream ); | 145 | iCurBlock = rMyriad.streamAddBlock( pStream ); |
146 | #ifdef MYRIAD_STREAM_DEBUG | 146 | #ifdef MYRIAD_STREAM_DEBUG |
147 | sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " | 147 | sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " |
148 | << iCurBlock << "." << sio.nl; | 148 | << iCurBlock << "." << sio.nl; |
149 | 149 | ||
150 | #endif | 150 | #endif |
151 | } | 151 | } |
152 | if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) | 152 | if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) |
153 | { | 153 | { |
154 | #ifdef MYRIAD_STREAM_DEBUG | 154 | #ifdef MYRIAD_STREAM_DEBUG |
155 | sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." | 155 | sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." |
156 | << sio.nl; | 156 | << sio.nl; |
157 | #endif | 157 | #endif |
158 | rMyriad.releaseBlock( pCurBlock ); | 158 | rMyriad.releaseBlock( pCurBlock ); |
159 | pCurBlock = rMyriad.getBlock( iCurBlock ); | 159 | pCurBlock = rMyriad.getBlock( iCurBlock ); |
160 | } | 160 | } |
161 | pCurBlock->bChanged = true; | 161 | pCurBlock->bChanged = true; |
162 | 162 | ||
163 | // There are two main writing modes when it comes down to it. | 163 | // There are two main writing modes when it comes down to it. |
164 | // Overwrite mode and append mode. Append is what pretty much always | 164 | // Overwrite mode and append mode. Append is what pretty much always |
165 | // happens when creating a new stream. | 165 | // happens when creating a new stream. |
166 | if( iPos < pStream->iSize ) | 166 | if( iPos < pStream->iSize ) |
167 | { | 167 | { |
168 | int iAmnt = Bu::buMin( | 168 | int iAmnt = Bu::buMin( |
169 | Bu::buMin( | 169 | Bu::buMin( |
170 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 170 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
171 | iLeft | 171 | iLeft |
172 | ), | 172 | ), |
173 | pStream->iSize-iPos | 173 | pStream->iSize-iPos |
174 | ); | 174 | ); |
175 | #ifdef MYRIAD_STREAM_DEBUG | 175 | #ifdef MYRIAD_STREAM_DEBUG |
176 | sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " | 176 | sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " |
177 | << (iPos%rMyriad.iBlockSize) << "+" | 177 | << (iPos%rMyriad.iBlockSize) << "+" |
178 | << iAmnt | 178 | << iAmnt |
179 | << ", " << iLeft << "b left." << sio.nl; | 179 | << ", " << iLeft << "b left." << sio.nl; |
180 | #endif | 180 | #endif |
181 | memcpy( | 181 | memcpy( |
182 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 182 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
183 | pBuf, | 183 | pBuf, |
184 | iAmnt | 184 | iAmnt |
185 | ); | 185 | ); |
186 | iPos += iAmnt; | 186 | iPos += iAmnt; |
187 | pBuf = &((char *)pBuf)[iAmnt]; | 187 | pBuf = &((char *)pBuf)[iAmnt]; |
188 | iLeft -= iAmnt; | 188 | iLeft -= iAmnt; |
189 | } | 189 | } |
190 | else | 190 | else |
191 | { | 191 | { |
192 | int iAmnt = Bu::buMin( | 192 | int iAmnt = Bu::buMin( |
193 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 193 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
194 | iLeft | 194 | iLeft |
195 | ); | 195 | ); |
196 | #ifdef MYRIAD_STREAM_DEBUG | 196 | #ifdef MYRIAD_STREAM_DEBUG |
197 | sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " | 197 | sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " |
198 | << (iPos%rMyriad.iBlockSize) << "+" | 198 | << (iPos%rMyriad.iBlockSize) << "+" |
199 | << iAmnt | 199 | << iAmnt |
200 | << ", " << iLeft << "b left." << sio.nl; | 200 | << ", " << iLeft << "b left." << sio.nl; |
201 | #endif | 201 | #endif |
202 | memcpy( | 202 | memcpy( |
203 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 203 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
204 | pBuf, | 204 | pBuf, |
205 | iAmnt | 205 | iAmnt |
206 | ); | 206 | ); |
207 | iPos += iAmnt; | 207 | iPos += iAmnt; |
208 | pStream->iSize += iAmnt; | 208 | pStream->iSize += iAmnt; |
209 | rMyriad.headerChanged(); | 209 | rMyriad.headerChanged(); |
210 | pBuf = &((char *)pBuf)[iAmnt]; | 210 | pBuf = &((char *)pBuf)[iAmnt]; |
211 | iLeft -= iAmnt; | 211 | iLeft -= iAmnt; |
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | return nBytes; | 215 | return nBytes; |
216 | } | 216 | } |
217 | 217 | ||
218 | Bu::size Bu::MyriadStream::tell() | 218 | Bu::size Bu::MyriadStream::tell() |
219 | { | 219 | { |
220 | return iPos; | 220 | return iPos; |
221 | } | 221 | } |
222 | 222 | ||
223 | void Bu::MyriadStream::seek( Bu::size offset ) | 223 | void Bu::MyriadStream::seek( Bu::size offset ) |
224 | { | 224 | { |
225 | iPos += offset; | 225 | iPos += offset; |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::MyriadStream::setPos( Bu::size pos ) | 228 | void Bu::MyriadStream::setPos( Bu::size pos ) |
229 | { | 229 | { |
230 | iPos = pos; | 230 | iPos = pos; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::MyriadStream::setPosEnd( Bu::size pos ) | 233 | void Bu::MyriadStream::setPosEnd( Bu::size pos ) |
234 | { | 234 | { |
235 | iPos = pStream->iSize-pos; | 235 | iPos = pStream->iSize-pos; |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::MyriadStream::isEos() | 238 | bool Bu::MyriadStream::isEos() |
239 | { | 239 | { |
240 | return iPos >= pStream->iSize; | 240 | return iPos >= pStream->iSize; |
241 | } | 241 | } |
242 | 242 | ||
243 | bool Bu::MyriadStream::isOpen() | 243 | bool Bu::MyriadStream::isOpen() |
244 | { | 244 | { |
245 | return true; | 245 | return true; |
246 | } | 246 | } |
247 | 247 | ||
248 | void Bu::MyriadStream::flush() | 248 | void Bu::MyriadStream::flush() |
@@ -251,32 +251,32 @@ void Bu::MyriadStream::flush() | |||
251 | 251 | ||
252 | bool Bu::MyriadStream::canRead() | 252 | bool Bu::MyriadStream::canRead() |
253 | { | 253 | { |
254 | return true; | 254 | return true; |
255 | } | 255 | } |
256 | 256 | ||
257 | bool Bu::MyriadStream::canWrite() | 257 | bool Bu::MyriadStream::canWrite() |
258 | { | 258 | { |
259 | return true; | 259 | return true; |
260 | } | 260 | } |
261 | 261 | ||
262 | bool Bu::MyriadStream::isReadable() | 262 | bool Bu::MyriadStream::isReadable() |
263 | { | 263 | { |
264 | return true; | 264 | return true; |
265 | } | 265 | } |
266 | 266 | ||
267 | bool Bu::MyriadStream::isWritable() | 267 | bool Bu::MyriadStream::isWritable() |
268 | { | 268 | { |
269 | return true; | 269 | return true; |
270 | } | 270 | } |
271 | 271 | ||
272 | bool Bu::MyriadStream::isSeekable() | 272 | bool Bu::MyriadStream::isSeekable() |
273 | { | 273 | { |
274 | return true; | 274 | return true; |
275 | } | 275 | } |
276 | 276 | ||
277 | bool Bu::MyriadStream::isBlocking() | 277 | bool Bu::MyriadStream::isBlocking() |
278 | { | 278 | { |
279 | return true; | 279 | return true; |
280 | } | 280 | } |
281 | 281 | ||
282 | void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) | 282 | void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) |
@@ -285,25 +285,25 @@ void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) | |||
285 | 285 | ||
286 | void Bu::MyriadStream::setSize( Bu::size iSize ) | 286 | void Bu::MyriadStream::setSize( Bu::size iSize ) |
287 | { | 287 | { |
288 | if( iSize < 0 ) | 288 | if( iSize < 0 ) |
289 | iSize = 0; | 289 | iSize = 0; |
290 | rMyriad.setStreamSize( pStream, iSize ); | 290 | rMyriad.setStreamSize( pStream, iSize ); |
291 | if( iPos > iSize ) | 291 | if( iPos > iSize ) |
292 | iPos = iSize; | 292 | iPos = iSize; |
293 | } | 293 | } |
294 | 294 | ||
295 | Bu::size Bu::MyriadStream::getSize() const | 295 | Bu::size Bu::MyriadStream::getSize() const |
296 | { | 296 | { |
297 | return pStream->iSize; | 297 | return pStream->iSize; |
298 | } | 298 | } |
299 | 299 | ||
300 | Bu::size Bu::MyriadStream::getBlockSize() const | 300 | Bu::size Bu::MyriadStream::getBlockSize() const |
301 | { | 301 | { |
302 | return rMyriad.getBlockSize(); | 302 | return rMyriad.getBlockSize(); |
303 | } | 303 | } |
304 | 304 | ||
305 | Bu::String Bu::MyriadStream::getLocation() const | 305 | Bu::String Bu::MyriadStream::getLocation() const |
306 | { | 306 | { |
307 | return Bu::String("%1").arg( pStream->iId ); | 307 | return Bu::String("%1").arg( pStream->iId ); |
308 | } | 308 | } |
309 | 309 | ||
diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h index 7cc2fc0..fe7453f 100644 --- a/src/stable/myriadstream.h +++ b/src/stable/myriadstream.h | |||
@@ -13,49 +13,49 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class MyriadStream : public Bu::Stream | 16 | class MyriadStream : public Bu::Stream |
17 | { | 17 | { |
18 | friend class Myriad; | 18 | friend class Myriad; |
19 | private: | 19 | private: |
20 | /** | 20 | /** |
21 | * These can only be created by the Myriad class. | 21 | * These can only be created by the Myriad class. |
22 | */ | 22 | */ |
23 | MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); | 23 | MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); |
24 | 24 | ||
25 | public: | 25 | public: |
26 | virtual ~MyriadStream(); | 26 | virtual ~MyriadStream(); |
27 | 27 | ||
28 | virtual void close(); | 28 | virtual void close(); |
29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
31 | using Stream::write; | 31 | using Stream::write; |
32 | virtual Bu::size tell(); | 32 | virtual Bu::size tell(); |
33 | virtual void seek( Bu::size offset ); | 33 | virtual void seek( Bu::size offset ); |
34 | virtual void setPos( Bu::size pos ); | 34 | virtual void setPos( Bu::size pos ); |
35 | virtual void setPosEnd( Bu::size pos ); | 35 | virtual void setPosEnd( Bu::size pos ); |
36 | virtual bool isEos(); | 36 | virtual bool isEos(); |
37 | virtual bool isOpen(); | 37 | virtual bool isOpen(); |
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | virtual bool canRead(); | 39 | virtual bool canRead(); |
40 | virtual bool canWrite(); | 40 | virtual bool canWrite(); |
41 | virtual bool isReadable(); | 41 | virtual bool isReadable(); |
42 | virtual bool isWritable(); | 42 | virtual bool isWritable(); |
43 | virtual bool isSeekable(); | 43 | virtual bool isSeekable(); |
44 | virtual bool isBlocking(); | 44 | virtual bool isBlocking(); |
45 | virtual void setBlocking( bool bBlocking=true ); | 45 | virtual void setBlocking( bool bBlocking=true ); |
46 | virtual void setSize( Bu::size iSize ); | 46 | virtual void setSize( Bu::size iSize ); |
47 | 47 | ||
48 | virtual size getSize() const; | 48 | virtual size getSize() const; |
49 | virtual size getBlockSize() const; | 49 | virtual size getBlockSize() const; |
50 | virtual Bu::String getLocation() const; | 50 | virtual Bu::String getLocation() const; |
51 | 51 | ||
52 | private: | 52 | private: |
53 | Myriad &rMyriad; | 53 | Myriad &rMyriad; |
54 | Myriad::Stream *pStream; | 54 | Myriad::Stream *pStream; |
55 | Myriad::Block *pCurBlock; | 55 | Myriad::Block *pCurBlock; |
56 | int iBlockSize; | 56 | int iBlockSize; |
57 | int iPos; | 57 | int iPos; |
58 | }; | 58 | }; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | #endif | 61 | #endif |
diff --git a/src/stable/nullstream.cpp b/src/stable/nullstream.cpp index 0dcede2..5f568b9 100644 --- a/src/stable/nullstream.cpp +++ b/src/stable/nullstream.cpp | |||
@@ -8,8 +8,8 @@ | |||
8 | #include "bu/nullstream.h" | 8 | #include "bu/nullstream.h" |
9 | 9 | ||
10 | Bu::NullStream::NullStream() : | 10 | Bu::NullStream::NullStream() : |
11 | sRead( 0 ), | 11 | sRead( 0 ), |
12 | sWrote( 0 ) | 12 | sWrote( 0 ) |
13 | { | 13 | { |
14 | } | 14 | } |
15 | 15 | ||
@@ -19,31 +19,31 @@ Bu::NullStream::~NullStream() | |||
19 | 19 | ||
20 | void Bu::NullStream::close() | 20 | void Bu::NullStream::close() |
21 | { | 21 | { |
22 | sRead = sWrote = 0; | 22 | sRead = sWrote = 0; |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) | 25 | Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) |
26 | { | 26 | { |
27 | memset( pBuf, 0, nBytes ); | 27 | memset( pBuf, 0, nBytes ); |
28 | sRead += nBytes; | 28 | sRead += nBytes; |
29 | return nBytes; | 29 | return nBytes; |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::String Bu::NullStream::readLine() | 32 | Bu::String Bu::NullStream::readLine() |
33 | { | 33 | { |
34 | sRead++; | 34 | sRead++; |
35 | return Bu::String("\0", 1 ); | 35 | return Bu::String("\0", 1 ); |
36 | } | 36 | } |
37 | 37 | ||
38 | Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) | 38 | Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) |
39 | { | 39 | { |
40 | sWrote += nBytes; | 40 | sWrote += nBytes; |
41 | return nBytes; | 41 | return nBytes; |
42 | } | 42 | } |
43 | 43 | ||
44 | Bu::size Bu::NullStream::tell() | 44 | Bu::size Bu::NullStream::tell() |
45 | { | 45 | { |
46 | return sRead + sWrote; | 46 | return sRead + sWrote; |
47 | } | 47 | } |
48 | 48 | ||
49 | void Bu::NullStream::seek( Bu::size ) | 49 | void Bu::NullStream::seek( Bu::size ) |
@@ -60,12 +60,12 @@ void Bu::NullStream::setPosEnd( Bu::size ) | |||
60 | 60 | ||
61 | bool Bu::NullStream::isEos() | 61 | bool Bu::NullStream::isEos() |
62 | { | 62 | { |
63 | return false; | 63 | return false; |
64 | } | 64 | } |
65 | 65 | ||
66 | bool Bu::NullStream::isOpen() | 66 | bool Bu::NullStream::isOpen() |
67 | { | 67 | { |
68 | return true; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | void Bu::NullStream::flush() | 71 | void Bu::NullStream::flush() |
@@ -74,32 +74,32 @@ void Bu::NullStream::flush() | |||
74 | 74 | ||
75 | bool Bu::NullStream::canRead() | 75 | bool Bu::NullStream::canRead() |
76 | { | 76 | { |
77 | return true; | 77 | return true; |
78 | } | 78 | } |
79 | 79 | ||
80 | bool Bu::NullStream::canWrite() | 80 | bool Bu::NullStream::canWrite() |
81 | { | 81 | { |
82 | return true; | 82 | return true; |
83 | } | 83 | } |
84 | 84 | ||
85 | bool Bu::NullStream::isReadable() | 85 | bool Bu::NullStream::isReadable() |
86 | { | 86 | { |
87 | return true; | 87 | return true; |
88 | } | 88 | } |
89 | 89 | ||
90 | bool Bu::NullStream::isWritable() | 90 | bool Bu::NullStream::isWritable() |
91 | { | 91 | { |
92 | return true; | 92 | return true; |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::NullStream::isSeekable() | 95 | bool Bu::NullStream::isSeekable() |
96 | { | 96 | { |
97 | return false; | 97 | return false; |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::NullStream::isBlocking() | 100 | bool Bu::NullStream::isBlocking() |
101 | { | 101 | { |
102 | return true; | 102 | return true; |
103 | } | 103 | } |
104 | 104 | ||
105 | void Bu::NullStream::setBlocking( bool ) | 105 | void Bu::NullStream::setBlocking( bool ) |
@@ -112,16 +112,16 @@ void Bu::NullStream::setSize( Bu::size ) | |||
112 | 112 | ||
113 | Bu::size Bu::NullStream::getSize() const | 113 | Bu::size Bu::NullStream::getSize() const |
114 | { | 114 | { |
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | Bu::size Bu::NullStream::getBlockSize() const | 118 | Bu::size Bu::NullStream::getBlockSize() const |
119 | { | 119 | { |
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | Bu::String Bu::NullStream::getLocation() const | 123 | Bu::String Bu::NullStream::getLocation() const |
124 | { | 124 | { |
125 | return ""; | 125 | return ""; |
126 | } | 126 | } |
127 | 127 | ||
diff --git a/src/stable/nullstream.h b/src/stable/nullstream.h index 034b0c5..a8b24e3 100644 --- a/src/stable/nullstream.h +++ b/src/stable/nullstream.h | |||
@@ -12,56 +12,56 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Works a lot like /dev/null on *nix style systems. This class allows | 16 | * Works a lot like /dev/null on *nix style systems. This class allows |
17 | * infinite reading and writing. All operatorns "succeed" even if they | 17 | * infinite reading and writing. All operatorns "succeed" even if they |
18 | * don't seem to do anything. This is great for testing writing code or | 18 | * don't seem to do anything. This is great for testing writing code or |
19 | * doing dry runs. When reading, it will produce NULL bytes, so any | 19 | * doing dry runs. When reading, it will produce NULL bytes, so any |
20 | * application that would like the ability to produce null streams as a | 20 | * application that would like the ability to produce null streams as a |
21 | * snap-in replacement for any other Bu::Stream, this is the right option. | 21 | * snap-in replacement for any other Bu::Stream, this is the right option. |
22 | * | 22 | * |
23 | * As an added feature, the NullStream will track how many bytes it was | 23 | * As an added feature, the NullStream will track how many bytes it was |
24 | * asked to read and write, allowing you to use it to determine how many | 24 | * asked to read and write, allowing you to use it to determine how many |
25 | * bytes a write opretion would use without actually writing anything. | 25 | * bytes a write opretion would use without actually writing anything. |
26 | */ | 26 | */ |
27 | class NullStream : public Bu::Stream | 27 | class NullStream : public Bu::Stream |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | NullStream(); | 30 | NullStream(); |
31 | virtual ~NullStream(); | 31 | virtual ~NullStream(); |
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::String readLine(); | 35 | virtual Bu::String readLine(); |
36 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 36 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
37 | using Bu::Stream::write; | 37 | using Bu::Stream::write; |
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 | virtual void flush(); | 44 | virtual void flush(); |
45 | virtual bool canRead(); | 45 | virtual bool canRead(); |
46 | virtual bool canWrite(); | 46 | virtual bool canWrite(); |
47 | virtual bool isReadable(); | 47 | virtual bool isReadable(); |
48 | virtual bool isWritable(); | 48 | virtual bool isWritable(); |
49 | virtual bool isSeekable(); | 49 | virtual bool isSeekable(); |
50 | virtual bool isBlocking(); | 50 | virtual bool isBlocking(); |
51 | virtual void setBlocking( bool bBlocking=true ); | 51 | virtual void setBlocking( bool bBlocking=true ); |
52 | virtual void setSize( Bu::size iSize ); | 52 | virtual void setSize( Bu::size iSize ); |
53 | 53 | ||
54 | virtual size getSize() const; | 54 | virtual size getSize() const; |
55 | virtual size getBlockSize() const; | 55 | virtual size getBlockSize() const; |
56 | virtual Bu::String getLocation() const; | 56 | virtual Bu::String getLocation() const; |
57 | 57 | ||
58 | Bu::size getBytesRead() { return sRead; } | 58 | Bu::size getBytesRead() { return sRead; } |
59 | Bu::size getByetsWritten() { return sWrote; } | 59 | Bu::size getByetsWritten() { return sWrote; } |
60 | 60 | ||
61 | private: | 61 | private: |
62 | Bu::size sRead; | 62 | Bu::size sRead; |
63 | Bu::size sWrote; | 63 | Bu::size sWrote; |
64 | }; | 64 | }; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #endif | 67 | #endif |
diff --git a/src/stable/optparser.cpp b/src/stable/optparser.cpp index 10a8fb6..aca36a2 100644 --- a/src/stable/optparser.cpp +++ b/src/stable/optparser.cpp | |||
@@ -21,168 +21,168 @@ Bu::OptParser::~OptParser() | |||
21 | 21 | ||
22 | void Bu::OptParser::parse( int argc, char **argv ) | 22 | void Bu::OptParser::parse( int argc, char **argv ) |
23 | { | 23 | { |
24 | for( int j = 1; j < argc; j++ ) | 24 | for( int j = 1; j < argc; j++ ) |
25 | { | 25 | { |
26 | if( argv[j][0] == '-' ) | 26 | if( argv[j][0] == '-' ) |
27 | { | 27 | { |
28 | // Now we're on to something, which kind is it? | 28 | // Now we're on to something, which kind is it? |
29 | if( argv[j][1] == '-' ) | 29 | if( argv[j][1] == '-' ) |
30 | { | 30 | { |
31 | int iEPos; | 31 | int iEPos; |
32 | for( iEPos = 2; argv[j][iEPos] != '\0' && | 32 | for( iEPos = 2; argv[j][iEPos] != '\0' && |
33 | argv[j][iEPos] != '='; iEPos++ ) { } | 33 | argv[j][iEPos] != '='; iEPos++ ) { } |
34 | 34 | ||
35 | Bu::String sOpt; | 35 | Bu::String sOpt; |
36 | int iCount = argc-j; | 36 | int iCount = argc-j; |
37 | Bu::String sExtraParam; | 37 | Bu::String sExtraParam; |
38 | if( argv[j][iEPos] == '=' ) | 38 | if( argv[j][iEPos] == '=' ) |
39 | { | 39 | { |
40 | sOpt.set( argv[j]+2, iEPos-2 ); | 40 | sOpt.set( argv[j]+2, iEPos-2 ); |
41 | iCount++; | 41 | iCount++; |
42 | sExtraParam.set( argv[j]+iEPos+1 ); | 42 | sExtraParam.set( argv[j]+iEPos+1 ); |
43 | } | 43 | } |
44 | else | 44 | else |
45 | { | 45 | { |
46 | sOpt.set( argv[j]+2 ); | 46 | sOpt.set( argv[j]+2 ); |
47 | } | 47 | } |
48 | if( !hlOption.has( sOpt ) ) | 48 | if( !hlOption.has( sOpt ) ) |
49 | { | 49 | { |
50 | optionError( "--" + sOpt ); | 50 | optionError( "--" + sOpt ); |
51 | } | 51 | } |
52 | else | 52 | else |
53 | { | 53 | { |
54 | // Long param, cool, that's easy, first search for = | 54 | // Long param, cool, that's easy, first search for = |
55 | Option *pOpt = hlOption.get( sOpt ); | 55 | Option *pOpt = hlOption.get( sOpt ); |
56 | if( pOpt->sUsed ) | 56 | if( pOpt->sUsed ) |
57 | { | 57 | { |
58 | Bu::StrArray aParams( iCount ); | 58 | Bu::StrArray aParams( iCount ); |
59 | aParams.append( sOpt ); | 59 | aParams.append( sOpt ); |
60 | if( sExtraParam.isSet() ) | 60 | if( sExtraParam.isSet() ) |
61 | { | 61 | { |
62 | aParams.append( argv[j]+iEPos+1 ); | 62 | aParams.append( argv[j]+iEPos+1 ); |
63 | } | 63 | } |
64 | for( int k = j+1; k < argc; k++ ) | 64 | for( int k = j+1; k < argc; k++ ) |
65 | { | 65 | { |
66 | aParams.append( argv[k] ); | 66 | aParams.append( argv[k] ); |
67 | } | 67 | } |
68 | j += pOpt->sUsed( aParams ); | 68 | j += pOpt->sUsed( aParams ); |
69 | } | 69 | } |
70 | else if( pOpt->pProxy ) | 70 | else if( pOpt->pProxy ) |
71 | { | 71 | { |
72 | if( pOpt->sOverride.isSet() ) | 72 | if( pOpt->sOverride.isSet() ) |
73 | { | 73 | { |
74 | pOpt->pProxy->setValue( pOpt->sOverride ); | 74 | pOpt->pProxy->setValue( pOpt->sOverride ); |
75 | } | 75 | } |
76 | else if( sExtraParam.isSet() ) | 76 | else if( sExtraParam.isSet() ) |
77 | { | 77 | { |
78 | pOpt->pProxy->setValueFromStr( sExtraParam ); | 78 | pOpt->pProxy->setValueFromStr( sExtraParam ); |
79 | } | 79 | } |
80 | else if( argv[j+1] != '\0' ) | 80 | else if( argv[j+1] != '\0' ) |
81 | { | 81 | { |
82 | pOpt->pProxy->setValueFromStr( argv[j+1] ); | 82 | pOpt->pProxy->setValueFromStr( argv[j+1] ); |
83 | j++; | 83 | j++; |
84 | } | 84 | } |
85 | } | 85 | } |
86 | } | 86 | } |
87 | } | 87 | } |
88 | else | 88 | else |
89 | { | 89 | { |
90 | int iCPos; | 90 | int iCPos; |
91 | for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) | 91 | for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) |
92 | { | 92 | { |
93 | if( !hsOption.has( argv[j][iCPos] ) ) | 93 | if( !hsOption.has( argv[j][iCPos] ) ) |
94 | { | 94 | { |
95 | Bu::String sOpt("-"); | 95 | Bu::String sOpt("-"); |
96 | sOpt += argv[j][iCPos]; | 96 | sOpt += argv[j][iCPos]; |
97 | optionError( sOpt ); | 97 | optionError( sOpt ); |
98 | } | 98 | } |
99 | else | 99 | else |
100 | { | 100 | { |
101 | Option *pOpt = hsOption.get( argv[j][iCPos] ); | 101 | Option *pOpt = hsOption.get( argv[j][iCPos] ); |
102 | char buf[2] = {argv[j][iCPos], '\0'}; | 102 | char buf[2] = {argv[j][iCPos], '\0'}; |
103 | if( pOpt->sUsed ) | 103 | if( pOpt->sUsed ) |
104 | { | 104 | { |
105 | Bu::StrArray aParams( argc-j+1 ); | 105 | Bu::StrArray aParams( argc-j+1 ); |
106 | aParams.append( buf ); | 106 | aParams.append( buf ); |
107 | int iMod = 0; | 107 | int iMod = 0; |
108 | if( argv[j][iCPos+1] != '\0' ) | 108 | if( argv[j][iCPos+1] != '\0' ) |
109 | { | 109 | { |
110 | aParams.append( argv[j]+iCPos+1 ); | 110 | aParams.append( argv[j]+iCPos+1 ); |
111 | iMod = -1; | 111 | iMod = -1; |
112 | } | 112 | } |
113 | for( int k = j+1; k < argc; k++ ) | 113 | for( int k = j+1; k < argc; k++ ) |
114 | { | 114 | { |
115 | aParams.append( argv[k] ); | 115 | aParams.append( argv[k] ); |
116 | } | 116 | } |
117 | int iUsed = pOpt->sUsed( aParams ); | 117 | int iUsed = pOpt->sUsed( aParams ); |
118 | if( iUsed > 0 ) | 118 | if( iUsed > 0 ) |
119 | { | 119 | { |
120 | j += iUsed + iMod; | 120 | j += iUsed + iMod; |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | } | 123 | } |
124 | else if( pOpt->pProxy ) | 124 | else if( pOpt->pProxy ) |
125 | { | 125 | { |
126 | if( pOpt->sOverride.isSet() ) | 126 | if( pOpt->sOverride.isSet() ) |
127 | { | 127 | { |
128 | pOpt->pProxy->setValue( pOpt->sOverride ); | 128 | pOpt->pProxy->setValue( pOpt->sOverride ); |
129 | } | 129 | } |
130 | else if( argv[j][iCPos+1] != '\0' ) | 130 | else if( argv[j][iCPos+1] != '\0' ) |
131 | { | 131 | { |
132 | pOpt->pProxy->setValueFromStr( | 132 | pOpt->pProxy->setValueFromStr( |
133 | argv[j]+iCPos+1 | 133 | argv[j]+iCPos+1 |
134 | ); | 134 | ); |
135 | break; | 135 | break; |
136 | } | 136 | } |
137 | else if( argv[j+1] ) | 137 | else if( argv[j+1] ) |
138 | { | 138 | { |
139 | pOpt->pProxy->setValueFromStr( | 139 | pOpt->pProxy->setValueFromStr( |
140 | argv[j+1] | 140 | argv[j+1] |
141 | ); | 141 | ); |
142 | j++; | 142 | j++; |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | } | 146 | } |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | else | 150 | else |
151 | { | 151 | { |
152 | if( !sNonOption ) | 152 | if( !sNonOption ) |
153 | { | 153 | { |
154 | optionError( argv[j] ); | 154 | optionError( argv[j] ); |
155 | } | 155 | } |
156 | else | 156 | else |
157 | { | 157 | { |
158 | int iCount = argc-j; | 158 | int iCount = argc-j; |
159 | Bu::StrArray aParams( iCount ); | 159 | Bu::StrArray aParams( iCount ); |
160 | for( int k = j; k < argc; k++ ) | 160 | for( int k = j; k < argc; k++ ) |
161 | { | 161 | { |
162 | aParams.append( argv[k] ); | 162 | aParams.append( argv[k] ); |
163 | } | 163 | } |
164 | j += sNonOption( aParams ); | 164 | j += sNonOption( aParams ); |
165 | } | 165 | } |
166 | } | 166 | } |
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | void Bu::OptParser::parse( const Bu::String &sLine ) | 170 | void Bu::OptParser::parse( const Bu::String &sLine ) |
171 | { | 171 | { |
172 | Bu::String sCmd = sLine.clone(); | 172 | Bu::String sCmd = sLine.clone(); |
173 | int iParams = 0; | 173 | int iParams = 0; |
174 | bool bInGap = true; | 174 | bool bInGap = true; |
175 | bool bInQuote = false; | 175 | bool bInQuote = false; |
176 | for( Bu::String::iterator i = sCmd.begin(); i; i++ ) | 176 | for( Bu::String::iterator i = sCmd.begin(); i; i++ ) |
177 | { | 177 | { |
178 | if( bInQuote == false && (*i == ' ' || *i == '\t') ) | 178 | if( bInQuote == false && (*i == ' ' || *i == '\t') ) |
179 | { | 179 | { |
180 | if( bInGap == false ) | 180 | if( bInGap == false ) |
181 | { | 181 | { |
182 | bInGap = true; | 182 | bInGap = true; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | else if( *i == '"' ) | 185 | else if( *i == '"' ) |
186 | { | 186 | { |
187 | bInQuote = !bInQuote; | 187 | bInQuote = !bInQuote; |
188 | } | 188 | } |
@@ -211,242 +211,242 @@ void Bu::OptParser::parse( const Bu::String &sLine ) | |||
211 | } | 211 | } |
212 | } | 212 | } |
213 | else if( *i == '"' ) | 213 | else if( *i == '"' ) |
214 | { | 214 | { |
215 | bInQuote = !bInQuote; | 215 | bInQuote = !bInQuote; |
216 | } | 216 | } |
217 | else | 217 | else |
218 | { | 218 | { |
219 | if( bInGap ) | 219 | if( bInGap ) |
220 | { | 220 | { |
221 | asParam[iParams++] = i; | 221 | asParam[iParams++] = i; |
222 | bInGap = false; | 222 | bInGap = false; |
223 | } | 223 | } |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | parse( iParams, asParam ); | 227 | parse( iParams, asParam ); |
228 | 228 | ||
229 | delete[] asParam; | 229 | delete[] asParam; |
230 | } | 230 | } |
231 | 231 | ||
232 | void Bu::OptParser::addOption( const Option &opt ) | 232 | void Bu::OptParser::addOption( const Option &opt ) |
233 | { | 233 | { |
234 | lOption.append( opt ); | 234 | lOption.append( opt ); |
235 | if( opt.cOpt != '\0' ) | 235 | if( opt.cOpt != '\0' ) |
236 | hsOption.insert( opt.cOpt, &lOption.last() ); | 236 | hsOption.insert( opt.cOpt, &lOption.last() ); |
237 | if( opt.sOpt.isSet() ) | 237 | if( opt.sOpt.isSet() ) |
238 | hlOption.insert( opt.sOpt, &lOption.last() ); | 238 | hlOption.insert( opt.sOpt, &lOption.last() ); |
239 | } | 239 | } |
240 | 240 | ||
241 | void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) | 241 | void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) |
242 | { | 242 | { |
243 | hsOption.get( cOpt )->sOverride = sOverride; | 243 | hsOption.get( cOpt )->sOverride = sOverride; |
244 | } | 244 | } |
245 | 245 | ||
246 | void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) | 246 | void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) |
247 | { | 247 | { |
248 | hlOption.get( sOpt )->sOverride = sOverride; | 248 | hlOption.get( sOpt )->sOverride = sOverride; |
249 | } | 249 | } |
250 | 250 | ||
251 | void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) | 251 | void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) |
252 | { | 252 | { |
253 | hlOption.get( sOpt )->sHelpDefault = sTxt; | 253 | hlOption.get( sOpt )->sHelpDefault = sTxt; |
254 | } | 254 | } |
255 | 255 | ||
256 | void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) | 256 | void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) |
257 | { | 257 | { |
258 | Option o; | 258 | Option o; |
259 | o.sUsed = slot( this, &OptParser::optHelp ); | 259 | o.sUsed = slot( this, &OptParser::optHelp ); |
260 | o.cOpt = c; | 260 | o.cOpt = c; |
261 | o.sOpt = s; | 261 | o.sOpt = s; |
262 | o.sHelp = sHelp; | 262 | o.sHelp = sHelp; |
263 | addOption( o ); | 263 | addOption( o ); |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) | 266 | void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) |
267 | { | 267 | { |
268 | Banner b; | 268 | Banner b; |
269 | b.sText = sText; | 269 | b.sText = sText; |
270 | b.bFormatted = bFormatted; | 270 | b.bFormatted = bFormatted; |
271 | if( lOption.getSize() > 0 ) | 271 | if( lOption.getSize() > 0 ) |
272 | { | 272 | { |
273 | for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } | 273 | for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } |
274 | } | 274 | } |
275 | lBanner.append( b ); | 275 | lBanner.append( b ); |
276 | } | 276 | } |
277 | 277 | ||
278 | int Bu::OptParser::optHelp( StrArray /*aParams*/ ) | 278 | int Bu::OptParser::optHelp( StrArray /*aParams*/ ) |
279 | { | 279 | { |
280 | bool bHasShort = false; | 280 | bool bHasShort = false; |
281 | int iMaxWidth = 0; | 281 | int iMaxWidth = 0; |
282 | int iScrWidth = 80; | 282 | int iScrWidth = 80; |
283 | char *env = getenv("COLUMNS"); | 283 | char *env = getenv("COLUMNS"); |
284 | if( env ) | 284 | if( env ) |
285 | iScrWidth = strtol( env, NULL, 10 ); | 285 | iScrWidth = strtol( env, NULL, 10 ); |
286 | for( OptionList::iterator i = lOption.begin(); i; i++ ) | 286 | for( OptionList::iterator i = lOption.begin(); i; i++ ) |
287 | { | 287 | { |
288 | if( (*i).cOpt != '\0' ) | 288 | if( (*i).cOpt != '\0' ) |
289 | bHasShort = true; | 289 | bHasShort = true; |
290 | int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); | 290 | int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); |
291 | if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) | 291 | if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) |
292 | iMaxWidth = lOptSize; | 292 | iMaxWidth = lOptSize; |
293 | } | 293 | } |
294 | int iIndent = 4; | 294 | int iIndent = 4; |
295 | if( bHasShort ) | 295 | if( bHasShort ) |
296 | iIndent += 4; | 296 | iIndent += 4; |
297 | if( iMaxWidth > 0 ) | 297 | if( iMaxWidth > 0 ) |
298 | iIndent += 4 + iMaxWidth; | 298 | iIndent += 4 + iMaxWidth; |
299 | 299 | ||
300 | BannerList::iterator iBanner; | 300 | BannerList::iterator iBanner; |
301 | for( iBanner = lBanner.begin(); iBanner; iBanner++ ) | 301 | for( iBanner = lBanner.begin(); iBanner; iBanner++ ) |
302 | { | 302 | { |
303 | if( (*iBanner).iAfter ) | 303 | if( (*iBanner).iAfter ) |
304 | break; | 304 | break; |
305 | 305 | ||
306 | if( (*iBanner).bFormatted ) | 306 | if( (*iBanner).bFormatted ) |
307 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); | 307 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); |
308 | else | 308 | else |
309 | sio << (*iBanner).sText; | 309 | sio << (*iBanner).sText; |
310 | sio << sio.nl; | 310 | sio << sio.nl; |
311 | } | 311 | } |
312 | for( OptionList::iterator i = lOption.begin(); i; i++ ) | 312 | for( OptionList::iterator i = lOption.begin(); i; i++ ) |
313 | { | 313 | { |
314 | sio << " "; | 314 | sio << " "; |
315 | if( bHasShort ) | 315 | if( bHasShort ) |
316 | { | 316 | { |
317 | if( (*i).cOpt == '\0' ) | 317 | if( (*i).cOpt == '\0' ) |
318 | sio << " "; | 318 | sio << " "; |
319 | else | 319 | else |
320 | sio << "-" << (*i).cOpt; | 320 | sio << "-" << (*i).cOpt; |
321 | sio << " "; | 321 | sio << " "; |
322 | } | 322 | } |
323 | if( iMaxWidth > 0 ) | 323 | if( iMaxWidth > 0 ) |
324 | { | 324 | { |
325 | if( (*i).sOpt.isSet() ) | 325 | if( (*i).sOpt.isSet() ) |
326 | { | 326 | { |
327 | sio << "--" << Fmt(iMaxWidth, Fmt::Left) | 327 | sio << "--" << Fmt(iMaxWidth, Fmt::Left) |
328 | << (*i).sOpt + (*i).sHelpDefault; | 328 | << (*i).sOpt + (*i).sHelpDefault; |
329 | } | 329 | } |
330 | else | 330 | else |
331 | { | 331 | { |
332 | sio << " " << Fmt(iMaxWidth) << ""; | 332 | sio << " " << Fmt(iMaxWidth) << ""; |
333 | } | 333 | } |
334 | sio << " "; | 334 | sio << " "; |
335 | } | 335 | } |
336 | sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); | 336 | sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); |
337 | sio << sio.nl; | 337 | sio << sio.nl; |
338 | 338 | ||
339 | for( ; iBanner; iBanner++ ) | 339 | for( ; iBanner; iBanner++ ) |
340 | { | 340 | { |
341 | if( (*iBanner).iAfter != i ) | 341 | if( (*iBanner).iAfter != i ) |
342 | break; | 342 | break; |
343 | 343 | ||
344 | if( (*iBanner).bFormatted ) | 344 | if( (*iBanner).bFormatted ) |
345 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); | 345 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); |
346 | else | 346 | else |
347 | sio << (*iBanner).sText; | 347 | sio << (*iBanner).sText; |
348 | sio << sio.nl; | 348 | sio << sio.nl; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | exit( 0 ); | 351 | exit( 0 ); |
352 | return 0; | 352 | return 0; |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::OptParser::optionError( const Bu::String &sOption ) | 355 | void Bu::OptParser::optionError( const Bu::String &sOption ) |
356 | { | 356 | { |
357 | sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; | 357 | sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; |
358 | exit( 1 ); | 358 | exit( 1 ); |
359 | } | 359 | } |
360 | 360 | ||
361 | void Bu::OptParser::setNonOption( OptionSignal sSignal ) | 361 | void Bu::OptParser::setNonOption( OptionSignal sSignal ) |
362 | { | 362 | { |
363 | sNonOption = sSignal; | 363 | sNonOption = sSignal; |
364 | } | 364 | } |
365 | 365 | ||
366 | Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, | 366 | Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, |
367 | int iIndent ) | 367 | int iIndent ) |
368 | { | 368 | { |
369 | Bu::String sOut; | 369 | Bu::String sOut; |
370 | Bu::String sIndent; | 370 | Bu::String sIndent; |
371 | for( int j = 0; j < iIndent; j++ ) | 371 | for( int j = 0; j < iIndent; j++ ) |
372 | sIndent.append(" ", 1); | 372 | sIndent.append(" ", 1); |
373 | bool bFirst = true; | 373 | bool bFirst = true; |
374 | int iSpaceCount = 0; | 374 | int iSpaceCount = 0; |
375 | bool bSpace = false; | 375 | bool bSpace = false; |
376 | int iPrevLineLen; | 376 | int iPrevLineLen; |
377 | int iLineLen = 0; | 377 | int iLineLen = 0; |
378 | Bu::String::const_iterator iLastSpace, iStart; | 378 | Bu::String::const_iterator iLastSpace, iStart; |
379 | for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) | 379 | for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) |
380 | { | 380 | { |
381 | if( *i == ' ' ) | 381 | if( *i == ' ' ) |
382 | { | 382 | { |
383 | if( bSpace == false ) | 383 | if( bSpace == false ) |
384 | { | 384 | { |
385 | iLastSpace = i; | 385 | iLastSpace = i; |
386 | iSpaceCount++; | 386 | iSpaceCount++; |
387 | bSpace = true; | 387 | bSpace = true; |
388 | iPrevLineLen = iLineLen; | 388 | iPrevLineLen = iLineLen; |
389 | } | 389 | } |
390 | } | 390 | } |
391 | else | 391 | else |
392 | { | 392 | { |
393 | bSpace = false; | 393 | bSpace = false; |
394 | } | 394 | } |
395 | iLineLen++; | 395 | iLineLen++; |
396 | 396 | ||
397 | if( iLineLen >= iWidth ) | 397 | if( iLineLen >= iWidth ) |
398 | { | 398 | { |
399 | iSpaceCount--; | 399 | iSpaceCount--; |
400 | if( bFirst == true ) | 400 | if( bFirst == true ) |
401 | bFirst = false; | 401 | bFirst = false; |
402 | else | 402 | else |
403 | sOut += sIndent; | 403 | sOut += sIndent; |
404 | int iExtraSpaces = iWidth-iPrevLineLen; | 404 | int iExtraSpaces = iWidth-iPrevLineLen; |
405 | bSpace = false; | 405 | bSpace = false; |
406 | float fFill = 0.0; | 406 | float fFill = 0.0; |
407 | int iSubSpaceCount = 0; | 407 | int iSubSpaceCount = 0; |
408 | float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); | 408 | float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); |
409 | for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) | 409 | for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) |
410 | { | 410 | { |
411 | sOut += *k; | 411 | sOut += *k; |
412 | if( *k == ' ' ) | 412 | if( *k == ' ' ) |
413 | { | 413 | { |
414 | if( bSpace == false && iExtraSpaces > 0 ) | 414 | if( bSpace == false && iExtraSpaces > 0 ) |
415 | { | 415 | { |
416 | bSpace = true; | 416 | bSpace = true; |
417 | fFill += fAdd; | 417 | fFill += fAdd; |
418 | iSubSpaceCount++; | 418 | iSubSpaceCount++; |
419 | for( int sp = 0; sp < (int)(fFill); sp++ ) | 419 | for( int sp = 0; sp < (int)(fFill); sp++ ) |
420 | { | 420 | { |
421 | sOut += ' '; | 421 | sOut += ' '; |
422 | iExtraSpaces--; | 422 | iExtraSpaces--; |
423 | } | 423 | } |
424 | fFill -= (int)fFill; | 424 | fFill -= (int)fFill; |
425 | if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) | 425 | if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) |
426 | { | 426 | { |
427 | for(; iExtraSpaces > 0; iExtraSpaces-- ) | 427 | for(; iExtraSpaces > 0; iExtraSpaces-- ) |
428 | { | 428 | { |
429 | sOut += ' '; | 429 | sOut += ' '; |
430 | } | 430 | } |
431 | } | 431 | } |
432 | } | 432 | } |
433 | } | 433 | } |
434 | else | 434 | else |
435 | bSpace = false; | 435 | bSpace = false; |
436 | } | 436 | } |
437 | //sOut.append( iStart, iLastSpace ); | 437 | //sOut.append( iStart, iLastSpace ); |
438 | sOut.append("\n"); | 438 | sOut.append("\n"); |
439 | for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } | 439 | for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } |
440 | iStart = i = iLastSpace; | 440 | iStart = i = iLastSpace; |
441 | bSpace = false; | 441 | bSpace = false; |
442 | iLineLen = 1; | 442 | iLineLen = 1; |
443 | iSpaceCount = 0; | 443 | iSpaceCount = 0; |
444 | } | 444 | } |
445 | } | 445 | } |
446 | if( !bFirst ) | 446 | if( !bFirst ) |
447 | sOut += sIndent; | 447 | sOut += sIndent; |
448 | sOut.append( iStart ); | 448 | sOut.append( iStart ); |
449 | return sOut; | 449 | return sOut; |
450 | } | 450 | } |
451 | 451 | ||
452 | 452 | ||
@@ -467,26 +467,26 @@ Bu::OptParser::_ValueProxy::~_ValueProxy() | |||
467 | // | 467 | // |
468 | 468 | ||
469 | Bu::OptParser::Option::Option() : | 469 | Bu::OptParser::Option::Option() : |
470 | cOpt( '\0' ), | 470 | cOpt( '\0' ), |
471 | pProxy( NULL ) | 471 | pProxy( NULL ) |
472 | { | 472 | { |
473 | } | 473 | } |
474 | 474 | ||
475 | Bu::OptParser::Option::Option( const Option &rSrc ) : | 475 | Bu::OptParser::Option::Option( const Option &rSrc ) : |
476 | cOpt( rSrc.cOpt ), | 476 | cOpt( rSrc.cOpt ), |
477 | sOpt( rSrc.sOpt ), | 477 | sOpt( rSrc.sOpt ), |
478 | sHelp( rSrc.sHelp ), | 478 | sHelp( rSrc.sHelp ), |
479 | sUsed( rSrc.sUsed ), | 479 | sUsed( rSrc.sUsed ), |
480 | pProxy( NULL ), | 480 | pProxy( NULL ), |
481 | sOverride( rSrc.sOverride ) | 481 | sOverride( rSrc.sOverride ) |
482 | { | 482 | { |
483 | if( rSrc.pProxy ) | 483 | if( rSrc.pProxy ) |
484 | pProxy = rSrc.pProxy->clone(); | 484 | pProxy = rSrc.pProxy->clone(); |
485 | } | 485 | } |
486 | 486 | ||
487 | Bu::OptParser::Option::~Option() | 487 | Bu::OptParser::Option::~Option() |
488 | { | 488 | { |
489 | delete pProxy; | 489 | delete pProxy; |
490 | pProxy = NULL; | 490 | pProxy = NULL; |
491 | } | 491 | } |
492 | 492 | ||
diff --git a/src/stable/optparser.h b/src/stable/optparser.h index 2da93c9..412f262 100644 --- a/src/stable/optparser.h +++ b/src/stable/optparser.h | |||
@@ -19,205 +19,205 @@ | |||
19 | 19 | ||
20 | namespace Bu | 20 | namespace Bu |
21 | { | 21 | { |
22 | typedef Bu::Array<Bu::String> StrArray; | 22 | typedef Bu::Array<Bu::String> StrArray; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * POSIX/Gnu style command line parser. Handles long and short options in | 25 | * POSIX/Gnu style command line parser. Handles long and short options in |
26 | * a variety of fun and useful ways, along with singal based callbacks and | 26 | * a variety of fun and useful ways, along with singal based callbacks and |
27 | * automatic variable setting. It's pretty easy to use, and very flexible. | 27 | * automatic variable setting. It's pretty easy to use, and very flexible. |
28 | * | 28 | * |
29 | * OptParser supports it's own builtin help mechanism which automatically | 29 | * OptParser supports it's own builtin help mechanism which automatically |
30 | * enumerates the available options and their help in a well formatted and | 30 | * enumerates the available options and their help in a well formatted and |
31 | * easy to read way, automatically formatting your help text per option and | 31 | * easy to read way, automatically formatting your help text per option and |
32 | * allows for addition "help banners" which can be placed wherever you | 32 | * allows for addition "help banners" which can be placed wherever you |
33 | * would like. | 33 | * would like. |
34 | */ | 34 | */ |
35 | class OptParser | 35 | class OptParser |
36 | { | 36 | { |
37 | private: | 37 | private: |
38 | class _ValueProxy | 38 | class _ValueProxy |
39 | { | 39 | { |
40 | public: | 40 | public: |
41 | _ValueProxy(); | 41 | _ValueProxy(); |
42 | virtual ~_ValueProxy(); | 42 | virtual ~_ValueProxy(); |
43 | 43 | ||
44 | virtual void setValueFromStr( const Bu::String & )=0; | 44 | virtual void setValueFromStr( const Bu::String & )=0; |
45 | virtual void setValue( const Bu::Variant &vVar )=0; | 45 | virtual void setValue( const Bu::Variant &vVar )=0; |
46 | virtual _ValueProxy *clone()=0; | 46 | virtual _ValueProxy *clone()=0; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | template<typename ptype> | 49 | template<typename ptype> |
50 | class ValueProxy : public _ValueProxy | 50 | class ValueProxy : public _ValueProxy |
51 | { | 51 | { |
52 | public: | 52 | public: |
53 | ValueProxy( ptype &v ) : | 53 | ValueProxy( ptype &v ) : |
54 | v( v ) | 54 | v( v ) |
55 | { | 55 | { |
56 | } | 56 | } |
57 | 57 | ||
58 | virtual ~ValueProxy() | 58 | virtual ~ValueProxy() |
59 | { | 59 | { |
60 | } | 60 | } |
61 | 61 | ||
62 | virtual void setValueFromStr( const Bu::String &sVal ) | 62 | virtual void setValueFromStr( const Bu::String &sVal ) |
63 | { | 63 | { |
64 | Bu::MemBuf mb( sVal ); | 64 | Bu::MemBuf mb( sVal ); |
65 | Bu::Formatter f( mb ); | 65 | Bu::Formatter f( mb ); |
66 | f << Bu::Fmt().tokenize( false ); | 66 | f << Bu::Fmt().tokenize( false ); |
67 | f >> v; | 67 | f >> v; |
68 | } | 68 | } |
69 | 69 | ||
70 | virtual void setValue( const Bu::Variant &vVar ) | 70 | virtual void setValue( const Bu::Variant &vVar ) |
71 | { | 71 | { |
72 | if( vVar.getType() == typeid(ptype) ) | 72 | if( vVar.getType() == typeid(ptype) ) |
73 | { | 73 | { |
74 | v = vVar.get<ptype>(); | 74 | v = vVar.get<ptype>(); |
75 | } | 75 | } |
76 | else if( vVar.getType() == typeid(Bu::String) ) | 76 | else if( vVar.getType() == typeid(Bu::String) ) |
77 | { | 77 | { |
78 | setValueFromStr( vVar.get<Bu::String>() ); | 78 | setValueFromStr( vVar.get<Bu::String>() ); |
79 | } | 79 | } |
80 | else | 80 | else |
81 | { | 81 | { |
82 | Bu::MemBuf mb; | 82 | Bu::MemBuf mb; |
83 | Bu::Formatter f( mb ); | 83 | Bu::Formatter f( mb ); |
84 | // f << vVar; | 84 | // f << vVar; |
85 | setValueFromStr( mb.getString() ); | 85 | setValueFromStr( mb.getString() ); |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | virtual _ValueProxy *clone() | 89 | virtual _ValueProxy *clone() |
90 | { | 90 | { |
91 | return new ValueProxy<ptype>( v ); | 91 | return new ValueProxy<ptype>( v ); |
92 | } | 92 | } |
93 | 93 | ||
94 | private: | 94 | private: |
95 | ptype &v; | 95 | ptype &v; |
96 | }; | 96 | }; |
97 | 97 | ||
98 | public: | 98 | public: |
99 | typedef Signal1<int, StrArray> OptionSignal; | 99 | typedef Signal1<int, StrArray> OptionSignal; |
100 | class Option | 100 | class Option |
101 | { | 101 | { |
102 | public: | 102 | public: |
103 | Option(); | 103 | Option(); |
104 | Option( const Option &rSrc ); | 104 | Option( const Option &rSrc ); |
105 | virtual ~Option(); | 105 | virtual ~Option(); |
106 | 106 | ||
107 | char cOpt; | 107 | char cOpt; |
108 | Bu::String sOpt; | 108 | Bu::String sOpt; |
109 | Bu::String sHelp; | 109 | Bu::String sHelp; |
110 | OptionSignal sUsed; | 110 | OptionSignal sUsed; |
111 | _ValueProxy *pProxy; | 111 | _ValueProxy *pProxy; |
112 | Bu::Variant sOverride; | 112 | Bu::Variant sOverride; |
113 | Bu::String sHelpDefault; | 113 | Bu::String sHelpDefault; |
114 | }; | 114 | }; |
115 | 115 | ||
116 | private: | 116 | private: |
117 | typedef Bu::List<Option> OptionList; | 117 | typedef Bu::List<Option> OptionList; |
118 | typedef Bu::Hash<char, Option *> ShortOptionHash; | 118 | typedef Bu::Hash<char, Option *> ShortOptionHash; |
119 | typedef Bu::Hash<Bu::String, Option *> LongOptionHash; | 119 | typedef Bu::Hash<Bu::String, Option *> LongOptionHash; |
120 | 120 | ||
121 | class Banner | 121 | class Banner |
122 | { | 122 | { |
123 | public: | 123 | public: |
124 | Bu::String sText; | 124 | Bu::String sText; |
125 | bool bFormatted; | 125 | bool bFormatted; |
126 | OptionList::const_iterator iAfter; | 126 | OptionList::const_iterator iAfter; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | typedef Bu::List<Banner> BannerList; | 129 | typedef Bu::List<Banner> BannerList; |
130 | 130 | ||
131 | public: | 131 | public: |
132 | OptParser(); | 132 | OptParser(); |
133 | virtual ~OptParser(); | 133 | virtual ~OptParser(); |
134 | 134 | ||
135 | void parse( int argc, char **argv ); | 135 | void parse( int argc, char **argv ); |
136 | void parse( const Bu::String &sLine ); | 136 | void parse( const Bu::String &sLine ); |
137 | 137 | ||
138 | void addOption( const Option &opt ); | 138 | void addOption( const Option &opt ); |
139 | 139 | ||
140 | template<typename vtype> | 140 | template<typename vtype> |
141 | void addOption( vtype &var, char cOpt, const Bu::String &sOpt, | 141 | void addOption( vtype &var, char cOpt, const Bu::String &sOpt, |
142 | const Bu::String &sHelp ) | 142 | const Bu::String &sHelp ) |
143 | { | 143 | { |
144 | Option o; | 144 | Option o; |
145 | o.cOpt = cOpt; | 145 | o.cOpt = cOpt; |
146 | o.sOpt = sOpt; | 146 | o.sOpt = sOpt; |
147 | o.pProxy = new ValueProxy<vtype>( var ); | 147 | o.pProxy = new ValueProxy<vtype>( var ); |
148 | o.sHelp = sHelp; | 148 | o.sHelp = sHelp; |
149 | addOption( o ); | 149 | addOption( o ); |
150 | } | 150 | } |
151 | 151 | ||
152 | template<typename vtype> | 152 | template<typename vtype> |
153 | void addOption( vtype &var, const Bu::String &sOpt, | 153 | void addOption( vtype &var, const Bu::String &sOpt, |
154 | const Bu::String &sHelp ) | 154 | const Bu::String &sHelp ) |
155 | { | 155 | { |
156 | addOption( var, '\0', sOpt, sHelp ); | 156 | addOption( var, '\0', sOpt, sHelp ); |
157 | } | 157 | } |
158 | 158 | ||
159 | template<typename vtype> | 159 | template<typename vtype> |
160 | void addOption( vtype &var, char cOpt, const Bu::String &sHelp ) | 160 | void addOption( vtype &var, char cOpt, const Bu::String &sHelp ) |
161 | { | 161 | { |
162 | addOption( var, cOpt, "", sHelp ); | 162 | addOption( var, cOpt, "", sHelp ); |
163 | } | 163 | } |
164 | 164 | ||
165 | void addOption( OptionSignal sUsed, char cOpt, const Bu::String &sOpt, | 165 | void addOption( OptionSignal sUsed, char cOpt, const Bu::String &sOpt, |
166 | const Bu::String &sHelp ) | 166 | const Bu::String &sHelp ) |
167 | { | 167 | { |
168 | Option o; | 168 | Option o; |
169 | o.cOpt = cOpt; | 169 | o.cOpt = cOpt; |
170 | o.sOpt = sOpt; | 170 | o.sOpt = sOpt; |
171 | o.sUsed = sUsed; | 171 | o.sUsed = sUsed; |
172 | o.sHelp = sHelp; | 172 | o.sHelp = sHelp; |
173 | addOption( o ); | 173 | addOption( o ); |
174 | } | 174 | } |
175 | 175 | ||
176 | void addOption( OptionSignal sUsed, const Bu::String &sOpt, | 176 | void addOption( OptionSignal sUsed, const Bu::String &sOpt, |
177 | const Bu::String &sHelp ) | 177 | const Bu::String &sHelp ) |
178 | { | 178 | { |
179 | addOption( sUsed, '\0', sOpt, sHelp ); | 179 | addOption( sUsed, '\0', sOpt, sHelp ); |
180 | } | 180 | } |
181 | 181 | ||
182 | void addOption( OptionSignal sUsed, char cOpt, | 182 | void addOption( OptionSignal sUsed, char cOpt, |
183 | const Bu::String &sHelp ) | 183 | const Bu::String &sHelp ) |
184 | { | 184 | { |
185 | addOption( sUsed, cOpt, "", sHelp ); | 185 | addOption( sUsed, cOpt, "", sHelp ); |
186 | } | 186 | } |
187 | 187 | ||
188 | void setOverride( char cOpt, const Bu::Variant &sOverride ); | 188 | void setOverride( char cOpt, const Bu::Variant &sOverride ); |
189 | void setOverride( const Bu::String &sOpt, | 189 | void setOverride( const Bu::String &sOpt, |
190 | const Bu::Variant &sOverride ); | 190 | const Bu::Variant &sOverride ); |
191 | 191 | ||
192 | void setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ); | 192 | void setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ); |
193 | 193 | ||
194 | void addHelpOption( char c='h', const Bu::String &s="help", | 194 | void addHelpOption( char c='h', const Bu::String &s="help", |
195 | const Bu::String &sHelp="This help." ); | 195 | const Bu::String &sHelp="This help." ); |
196 | void addHelpBanner( const Bu::String &sText, bool bFormatted=true ); | 196 | void addHelpBanner( const Bu::String &sText, bool bFormatted=true ); |
197 | 197 | ||
198 | int optHelp( StrArray aParams ); | 198 | int optHelp( StrArray aParams ); |
199 | 199 | ||
200 | /** | 200 | /** |
201 | * This function is called when an unrecognized option is found, the | 201 | * This function is called when an unrecognized option is found, the |
202 | * default behaviour is to print an error to stdout and exit( 1 ), if | 202 | * default behaviour is to print an error to stdout and exit( 1 ), if |
203 | * you want to do something different, just override this function. | 203 | * you want to do something different, just override this function. |
204 | * This is also called by default when something is found that hasn't | 204 | * This is also called by default when something is found that hasn't |
205 | * been handled by an option, and isn't an option (starts with - or --). | 205 | * been handled by an option, and isn't an option (starts with - or --). |
206 | * To change this behaviour call | 206 | * To change this behaviour call |
207 | */ | 207 | */ |
208 | virtual void optionError( const Bu::String &sOption ); | 208 | virtual void optionError( const Bu::String &sOption ); |
209 | 209 | ||
210 | void setNonOption( OptionSignal sSignal ); | 210 | void setNonOption( OptionSignal sSignal ); |
211 | 211 | ||
212 | private: | 212 | private: |
213 | Bu::String format( const Bu::String &sIn, int iWidth, int iIndent ); | 213 | Bu::String format( const Bu::String &sIn, int iWidth, int iIndent ); |
214 | 214 | ||
215 | OptionList lOption; | 215 | OptionList lOption; |
216 | ShortOptionHash hsOption; | 216 | ShortOptionHash hsOption; |
217 | LongOptionHash hlOption; | 217 | LongOptionHash hlOption; |
218 | BannerList lBanner; | 218 | BannerList lBanner; |
219 | OptionSignal sNonOption; | 219 | OptionSignal sNonOption; |
220 | }; | 220 | }; |
221 | }; | 221 | }; |
222 | 222 | ||
223 | #endif | 223 | #endif |
diff --git a/src/stable/pearsonhash.cpp b/src/stable/pearsonhash.cpp index d4e82df..6f58470 100644 --- a/src/stable/pearsonhash.cpp +++ b/src/stable/pearsonhash.cpp | |||
@@ -9,28 +9,28 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | uint8_t Bu::PearsonHash::aSBox[] = { | 11 | uint8_t Bu::PearsonHash::aSBox[] = { |
12 | 251, 175, 119, 215, 81, 14, 79, 191, 103, 49, 181, 143, 186, 157, 0, | 12 | 251, 175, 119, 215, 81, 14, 79, 191, 103, 49, 181, 143, 186, 157, 0, |
13 | 232, 31, 32, 55, 60, 152, 58, 17, 237, 174, 70, 160, 144, 220, 90, 57, | 13 | 232, 31, 32, 55, 60, 152, 58, 17, 237, 174, 70, 160, 144, 220, 90, 57, |
14 | 223, 59, 3, 18, 140, 111, 166, 203, 196, 134, 243, 124, 95, 222, 179, | 14 | 223, 59, 3, 18, 140, 111, 166, 203, 196, 134, 243, 124, 95, 222, 179, |
15 | 197, 65, 180, 48, 36, 15, 107, 46, 233, 130, 165, 30, 123, 161, 209, 23, | 15 | 197, 65, 180, 48, 36, 15, 107, 46, 233, 130, 165, 30, 123, 161, 209, 23, |
16 | 97, 16, 40, 91, 219, 61, 100, 10, 210, 109, 250, 127, 22, 138, 29, 108, | 16 | 97, 16, 40, 91, 219, 61, 100, 10, 210, 109, 250, 127, 22, 138, 29, 108, |
17 | 244, 67, 207, 9, 178, 204, 74, 98, 126, 249, 167, 116, 34, 77, 193, | 17 | 244, 67, 207, 9, 178, 204, 74, 98, 126, 249, 167, 116, 34, 77, 193, |
18 | 200, 121, 5, 20, 113, 71, 35, 128, 13, 182, 94, 25, 226, 227, 199, 75, | 18 | 200, 121, 5, 20, 113, 71, 35, 128, 13, 182, 94, 25, 226, 227, 199, 75, |
19 | 27, 41, 245, 230, 224, 43, 225, 177, 26, 155, 150, 212, 142, 218, 115, | 19 | 27, 41, 245, 230, 224, 43, 225, 177, 26, 155, 150, 212, 142, 218, 115, |
20 | 241, 73, 88, 105, 39, 114, 62, 255, 192, 201, 145, 214, 168, 158, 221, | 20 | 241, 73, 88, 105, 39, 114, 62, 255, 192, 201, 145, 214, 168, 158, 221, |
21 | 148, 154, 122, 12, 84, 82, 163, 44, 139, 228, 236, 205, 242, 217, 11, | 21 | 148, 154, 122, 12, 84, 82, 163, 44, 139, 228, 236, 205, 242, 217, 11, |
22 | 187, 146, 159, 64, 86, 239, 195, 42, 106, 198, 118, 112, 184, 172, 87, | 22 | 187, 146, 159, 64, 86, 239, 195, 42, 106, 198, 118, 112, 184, 172, 87, |
23 | 2, 173, 117, 176, 229, 247, 253, 137, 185, 99, 164, 102, 147, 45, 66, | 23 | 2, 173, 117, 176, 229, 247, 253, 137, 185, 99, 164, 102, 147, 45, 66, |
24 | 231, 52, 141, 211, 194, 206, 246, 238, 56, 110, 78, 248, 63, 240, 189, | 24 | 231, 52, 141, 211, 194, 206, 246, 238, 56, 110, 78, 248, 63, 240, 189, |
25 | 93, 92, 51, 53, 183, 19, 171, 72, 50, 33, 104, 101, 69, 8, 252, 83, 120, | 25 | 93, 92, 51, 53, 183, 19, 171, 72, 50, 33, 104, 101, 69, 8, 252, 83, 120, |
26 | 76, 135, 85, 54, 202, 125, 188, 213, 96, 235, 136, 208, 162, 129, 190, | 26 | 76, 135, 85, 54, 202, 125, 188, 213, 96, 235, 136, 208, 162, 129, 190, |
27 | 132, 156, 38, 47, 1, 7, 254, 24, 4, 216, 131, 89, 21, 28, 133, 37, 153, | 27 | 132, 156, 38, 47, 1, 7, 254, 24, 4, 216, 131, 89, 21, 28, 133, 37, 153, |
28 | 149, 80, 170, 68, 6, 169, 234, 151 | 28 | 149, 80, 170, 68, 6, 169, 234, 151 |
29 | }; | 29 | }; |
30 | 30 | ||
31 | Bu::PearsonHash::PearsonHash() | 31 | Bu::PearsonHash::PearsonHash() |
32 | { | 32 | { |
33 | reset(); | 33 | reset(); |
34 | } | 34 | } |
35 | 35 | ||
36 | Bu::PearsonHash::~PearsonHash() | 36 | Bu::PearsonHash::~PearsonHash() |
@@ -39,7 +39,7 @@ Bu::PearsonHash::~PearsonHash() | |||
39 | 39 | ||
40 | void Bu::PearsonHash::reset() | 40 | void Bu::PearsonHash::reset() |
41 | { | 41 | { |
42 | iValue = 0; | 42 | iValue = 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) | 45 | void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -48,19 +48,19 @@ void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) | |||
48 | 48 | ||
49 | void Bu::PearsonHash::addData( const void *sData, int iSize ) | 49 | void Bu::PearsonHash::addData( const void *sData, int iSize ) |
50 | { | 50 | { |
51 | for( int j = 0; j < iSize; j++ ) | 51 | for( int j = 0; j < iSize; j++ ) |
52 | { | 52 | { |
53 | iValue = aSBox[ iValue^((unsigned char *)sData)[j] ]; | 53 | iValue = aSBox[ iValue^((unsigned char *)sData)[j] ]; |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::String Bu::PearsonHash::getResult() | 57 | Bu::String Bu::PearsonHash::getResult() |
58 | { | 58 | { |
59 | return Bu::String((char)iValue); | 59 | return Bu::String((char)iValue); |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::PearsonHash::writeResult( Stream &sOut ) | 62 | void Bu::PearsonHash::writeResult( Stream &sOut ) |
63 | { | 63 | { |
64 | sOut.write( &iValue, 1 ); | 64 | sOut.write( &iValue, 1 ); |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/src/stable/pearsonhash.h b/src/stable/pearsonhash.h index ca377c1..ece1d40 100644 --- a/src/stable/pearsonhash.h +++ b/src/stable/pearsonhash.h | |||
@@ -12,35 +12,35 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A pearson hash is a non-cryptographically secure hashing function that | 16 | * A pearson hash is a non-cryptographically secure hashing function that |
17 | * is very light on resources, very fast, and produces a single byte | 17 | * is very light on resources, very fast, and produces a single byte |
18 | * as it's output. It is strongly dependant on every byte in the input, | 18 | * as it's output. It is strongly dependant on every byte in the input, |
19 | * which means that it's a good choice for adding to short messages to | 19 | * which means that it's a good choice for adding to short messages to |
20 | * ensure that the contents of the messages are unchanged. | 20 | * ensure that the contents of the messages are unchanged. |
21 | * | 21 | * |
22 | * Pearson hash is named for it's inventor Peter K. Pearson who described | 22 | * Pearson hash is named for it's inventor Peter K. Pearson who described |
23 | * it in his article "Fast hashing of variable-length text strings" | 23 | * it in his article "Fast hashing of variable-length text strings" |
24 | * published in 1990 by ACM. I haven't read it, because you have to pay to | 24 | * published in 1990 by ACM. I haven't read it, because you have to pay to |
25 | * get a copy :-P | 25 | * get a copy :-P |
26 | */ | 26 | */ |
27 | class PearsonHash : public Bu::CryptoHash | 27 | class PearsonHash : public Bu::CryptoHash |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | PearsonHash(); | 30 | PearsonHash(); |
31 | virtual ~PearsonHash(); | 31 | virtual ~PearsonHash(); |
32 | 32 | ||
33 | virtual void reset(); | 33 | virtual void reset(); |
34 | virtual void setSalt( const Bu::String &sSalt ); | 34 | virtual void setSalt( const Bu::String &sSalt ); |
35 | virtual void addData( const void *sData, int iSize ); | 35 | virtual void addData( const void *sData, int iSize ); |
36 | using Bu::CryptoHash::addData; | 36 | using Bu::CryptoHash::addData; |
37 | virtual String getResult(); | 37 | virtual String getResult(); |
38 | virtual void writeResult( Stream &sOut ); | 38 | virtual void writeResult( Stream &sOut ); |
39 | 39 | ||
40 | private: | 40 | private: |
41 | static uint8_t aSBox[256]; | 41 | static uint8_t aSBox[256]; |
42 | uint8_t iValue; | 42 | uint8_t iValue; |
43 | }; | 43 | }; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | #endif | 46 | #endif |
diff --git a/src/stable/plugger.h b/src/stable/plugger.h index d9eaf34..424613f 100644 --- a/src/stable/plugger.h +++ b/src/stable/plugger.h | |||
@@ -24,59 +24,59 @@ | |||
24 | 24 | ||
25 | namespace Bu | 25 | namespace Bu |
26 | { | 26 | { |
27 | subExceptionDecl( PluginException ); | 27 | subExceptionDecl( PluginException ); |
28 | 28 | ||
29 | typedef struct PluginInfo | 29 | typedef struct PluginInfo |
30 | { | 30 | { |
31 | const char *sID; | 31 | const char *sID; |
32 | const char *sAuthor; | 32 | const char *sAuthor; |
33 | unsigned short nVersion; | 33 | unsigned short nVersion; |
34 | unsigned short nRevision; | 34 | unsigned short nRevision; |
35 | void *(*createPlugin)(); | 35 | void *(*createPlugin)(); |
36 | void (*destroyPlugin)( void * ); | 36 | void (*destroyPlugin)( void * ); |
37 | } PluginInfo; | 37 | } PluginInfo; |
38 | 38 | ||
39 | typedef struct PluginReg | 39 | typedef struct PluginReg |
40 | { | 40 | { |
41 | bool bBuiltin; | 41 | bool bBuiltin; |
42 | #ifdef WIN32 | 42 | #ifdef WIN32 |
43 | HMODULE dlHandle; | 43 | HMODULE dlHandle; |
44 | #else | 44 | #else |
45 | void *dlHandle; | 45 | void *dlHandle; |
46 | #endif | 46 | #endif |
47 | PluginInfo *pInfo; | 47 | PluginInfo *pInfo; |
48 | } PluginReg; | 48 | } PluginReg; |
49 | 49 | ||
50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ | 50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ |
51 | extern "C" { \ | 51 | extern "C" { \ |
52 | baseclass *create ##classname() \ | 52 | baseclass *create ##classname() \ |
53 | { \ | 53 | { \ |
54 | return new classname(); \ | 54 | return new classname(); \ |
55 | } \ | 55 | } \ |
56 | void destroy ##classname( baseclass *pCls ) \ | 56 | void destroy ##classname( baseclass *pCls ) \ |
57 | { \ | 57 | { \ |
58 | delete pCls; \ | 58 | delete pCls; \ |
59 | } \ | 59 | } \ |
60 | Bu::PluginInfo classname = { \ | 60 | Bu::PluginInfo classname = { \ |
61 | #classname, name, ver, rev, \ | 61 | #classname, name, ver, rev, \ |
62 | create ##classname, destroy ##classname }; \ | 62 | create ##classname, destroy ##classname }; \ |
63 | } | 63 | } |
64 | 64 | ||
65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ | 65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ |
66 | extern "C" { \ | 66 | extern "C" { \ |
67 | baseclass *create ##classname() \ | 67 | baseclass *create ##classname() \ |
68 | { \ | 68 | { \ |
69 | return new classname(); \ | 69 | return new classname(); \ |
70 | } \ | 70 | } \ |
71 | void destroy ##classname( baseclass *pCls ) \ | 71 | void destroy ##classname( baseclass *pCls ) \ |
72 | { \ | 72 | { \ |
73 | delete pCls; \ | 73 | delete pCls; \ |
74 | } \ | 74 | } \ |
75 | Bu::PluginInfo pluginname = { \ | 75 | Bu::PluginInfo pluginname = { \ |
76 | #pluginname, name, ver, rev, \ | 76 | #pluginname, name, ver, rev, \ |
77 | (void *(*)())(create ##classname), \ | 77 | (void *(*)())(create ##classname), \ |
78 | (void (*)( void * ))(destroy ##classname) }; \ | 78 | (void (*)( void * ))(destroy ##classname) }; \ |
79 | } | 79 | } |
80 | 80 | ||
81 | // | 81 | // |
82 | // This is probably the main interface to use, I'll describe it some here... | 82 | // This is probably the main interface to use, I'll describe it some here... |
@@ -93,197 +93,197 @@ namespace Bu | |||
93 | // rev - an integer revision number for the plugin | 93 | // rev - an integer revision number for the plugin |
94 | // | 94 | // |
95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ | 95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ |
96 | extern "C" { \ | 96 | extern "C" { \ |
97 | baseclass *create ##classname() \ | 97 | baseclass *create ##classname() \ |
98 | { \ | 98 | { \ |
99 | return new classname(); \ | 99 | return new classname(); \ |
100 | } \ | 100 | } \ |
101 | void destroy ##classname( baseclass *pCls ) \ | 101 | void destroy ##classname( baseclass *pCls ) \ |
102 | { \ | 102 | { \ |
103 | delete pCls; \ | 103 | delete pCls; \ |
104 | } \ | 104 | } \ |
105 | Bu::PluginInfo structname = { \ | 105 | Bu::PluginInfo structname = { \ |
106 | #pluginname, name, ver, rev, \ | 106 | #pluginname, name, ver, rev, \ |
107 | (void *(*)())(create ##classname), \ | 107 | (void *(*)())(create ##classname), \ |
108 | (void (*)( void * ))(destroy ##classname) }; \ | 108 | (void (*)( void * ))(destroy ##classname) }; \ |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * A complete dynamic plugin manager system. This will allow you to design | 112 | * A complete dynamic plugin manager system. This will allow you to design |
113 | * and use plugins that are compiled into your program and dynamically | 113 | * and use plugins that are compiled into your program and dynamically |
114 | * linked to your program interchangably. It works on windows and on *nix | 114 | * linked to your program interchangably. It works on windows and on *nix |
115 | * and bsd type systems (anything that supports dlopen). Basically you | 115 | * and bsd type systems (anything that supports dlopen). Basically you |
116 | * create a base class that will be the basic interface of your plugins. | 116 | * create a base class that will be the basic interface of your plugins. |
117 | * Then you create some classes that inherit from it, and use the | 117 | * Then you create some classes that inherit from it, and use the |
118 | * PluginInterface3 macro to create the required data structures for it. | 118 | * PluginInterface3 macro to create the required data structures for it. |
119 | * | 119 | * |
120 | * Once you have plugins you can create a Plugger, by passing in the base | 120 | * Once you have plugins you can create a Plugger, by passing in the base |
121 | * class as it's template parameter. Once it's created, you can register | 121 | * class as it's template parameter. Once it's created, you can register |
122 | * plugins. To register a plugin that is builtin, you just need to pass | 122 | * plugins. To register a plugin that is builtin, you just need to pass |
123 | * a pointer to it's interface structure to the registerBuiltinPlugin | 123 | * a pointer to it's interface structure to the registerBuiltinPlugin |
124 | * function. To register a plugin that is in a shared object or dll file | 124 | * function. To register a plugin that is in a shared object or dll file |
125 | * you just pass the filename (with path, probably), and the name of the | 125 | * you just pass the filename (with path, probably), and the name of the |
126 | * structure to load and you're all set. | 126 | * structure to load and you're all set. |
127 | * | 127 | * |
128 | * To instantiate an object from a plugin simply call instantiate with the | 128 | * To instantiate an object from a plugin simply call instantiate with the |
129 | * name of the plugin as specified in the interface macro. To destroy an | 129 | * name of the plugin as specified in the interface macro. To destroy an |
130 | * object crated with the plugger do not delete it, instead pass it into | 130 | * object crated with the plugger do not delete it, instead pass it into |
131 | * Plugger's destroy function. | 131 | * Plugger's destroy function. |
132 | * | 132 | * |
133 | * Any objects not destroyed when the plugger is deleted will be destroyed | 133 | * Any objects not destroyed when the plugger is deleted will be destroyed |
134 | * automatically. | 134 | * automatically. |
135 | * | 135 | * |
136 | * It is important to note that some systems (linux at least) partition off | 136 | * It is important to note that some systems (linux at least) partition off |
137 | * the memory allocated by objects linked in at run time into a seperate | 137 | * the memory allocated by objects linked in at run time into a seperate |
138 | * segment that, while it can be accessed by the main program, cannot be | 138 | * segment that, while it can be accessed by the main program, cannot be |
139 | * safely or reliably freed by the main program. With that in mind it is | 139 | * safely or reliably freed by the main program. With that in mind it is |
140 | * a good idea to free all memory allocated by a plugin object in the plugin | 140 | * a good idea to free all memory allocated by a plugin object in the plugin |
141 | * object and not allow the calling program to delete it. | 141 | * object and not allow the calling program to delete it. |
142 | */ | 142 | */ |
143 | template<class T> | 143 | template<class T> |
144 | class Plugger | 144 | class Plugger |
145 | { | 145 | { |
146 | public: | 146 | public: |
147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; | 147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; |
148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; | 148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; |
149 | 149 | ||
150 | public: | 150 | public: |
151 | Plugger() | 151 | Plugger() |
152 | { | 152 | { |
153 | } | 153 | } |
154 | 154 | ||
155 | virtual ~Plugger() | 155 | virtual ~Plugger() |
156 | { | 156 | { |
157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) | 157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) |
158 | { | 158 | { |
159 | T *pPlug = (T *)i.getKey(); | 159 | T *pPlug = (T *)i.getKey(); |
160 | PluginReg *pReg = (PluginReg *)*i; | 160 | PluginReg *pReg = (PluginReg *)*i; |
161 | pReg->pInfo->destroyPlugin( pPlug ); | 161 | pReg->pInfo->destroyPlugin( pPlug ); |
162 | } | 162 | } |
163 | 163 | ||
164 | for( PluginHash::iterator i = hPlugin.begin(); | 164 | for( PluginHash::iterator i = hPlugin.begin(); |
165 | i != hPlugin.end(); i++ ) | 165 | i != hPlugin.end(); i++ ) |
166 | { | 166 | { |
167 | if( (*i)->bBuiltin == false ) | 167 | if( (*i)->bBuiltin == false ) |
168 | { | 168 | { |
169 | #ifdef WIN32 | 169 | #ifdef WIN32 |
170 | FreeLibrary( (*i)->dlHandle ); | 170 | FreeLibrary( (*i)->dlHandle ); |
171 | #else | 171 | #else |
172 | dlclose( (*i)->dlHandle ); | 172 | dlclose( (*i)->dlHandle ); |
173 | #endif | 173 | #endif |
174 | } | 174 | } |
175 | delete (*i); | 175 | delete (*i); |
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | void registerBuiltinPlugin( PluginInfo *pInfo ) | 179 | void registerBuiltinPlugin( PluginInfo *pInfo ) |
180 | { | 180 | { |
181 | PluginReg *pReg = new PluginReg; | 181 | PluginReg *pReg = new PluginReg; |
182 | pReg->bBuiltin = true; | 182 | pReg->bBuiltin = true; |
183 | pReg->pInfo = pInfo; | 183 | pReg->pInfo = pInfo; |
184 | hPlugin.insert( pInfo->sID, pReg ); | 184 | hPlugin.insert( pInfo->sID, pReg ); |
185 | } | 185 | } |
186 | 186 | ||
187 | void registerExternalPlugin( const Bu::String &sFName, | 187 | void registerExternalPlugin( const Bu::String &sFName, |
188 | const Bu::String &sPluginName ) | 188 | const Bu::String &sPluginName ) |
189 | { | 189 | { |
190 | PluginReg *pReg; | 190 | PluginReg *pReg; |
191 | if( hPlugin.has( sPluginName ) ) | 191 | if( hPlugin.has( sPluginName ) ) |
192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " | 192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " |
193 | "loaded.", sPluginName.getStr() ); | 193 | "loaded.", sPluginName.getStr() ); |
194 | 194 | ||
195 | pReg = new PluginReg; | 195 | pReg = new PluginReg; |
196 | 196 | ||
197 | pReg->bBuiltin = false; | 197 | pReg->bBuiltin = false; |
198 | #ifdef WIN32 | 198 | #ifdef WIN32 |
199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); | 199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); |
200 | if( pReg->dlHandle == NULL ) | 200 | if( pReg->dlHandle == NULL ) |
201 | { | 201 | { |
202 | throw PluginException( 1, "Error opening %s: %s", | 202 | throw PluginException( 1, "Error opening %s: %s", |
203 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 203 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
204 | } | 204 | } |
205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, | 205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, |
206 | sPluginName.getStr() ); | 206 | sPluginName.getStr() ); |
207 | if( pReg->pInfo == NULL ) | 207 | if( pReg->pInfo == NULL ) |
208 | { | 208 | { |
209 | throw PluginException( 2, "Error mapping %s: %s", | 209 | throw PluginException( 2, "Error mapping %s: %s", |
210 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 210 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
211 | } | 211 | } |
212 | #else | 212 | #else |
213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); | 213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); |
214 | if( pReg->dlHandle == NULL ) | 214 | if( pReg->dlHandle == NULL ) |
215 | { | 215 | { |
216 | throw PluginException( 1, "Error opening %s: %s", | 216 | throw PluginException( 1, "Error opening %s: %s", |
217 | sFName.getStr(), dlerror() ); | 217 | sFName.getStr(), dlerror() ); |
218 | } | 218 | } |
219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, | 219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, |
220 | sPluginName.getStr() ); | 220 | sPluginName.getStr() ); |
221 | if( pReg->pInfo == NULL ) | 221 | if( pReg->pInfo == NULL ) |
222 | { | 222 | { |
223 | throw PluginException( 2, "Error mapping %s: %s", | 223 | throw PluginException( 2, "Error mapping %s: %s", |
224 | sFName.getStr(), dlerror() ); | 224 | sFName.getStr(), dlerror() ); |
225 | } | 225 | } |
226 | #endif | 226 | #endif |
227 | hPlugin.insert( pReg->pInfo->sID, pReg ); | 227 | hPlugin.insert( pReg->pInfo->sID, pReg ); |
228 | } | 228 | } |
229 | 229 | ||
230 | T *instantiate( const Bu::String &lpName ) | 230 | T *instantiate( const Bu::String &lpName ) |
231 | { | 231 | { |
232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; | 232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; |
233 | if( pReg == NULL ) | 233 | if( pReg == NULL ) |
234 | return NULL; | 234 | return NULL; |
235 | 235 | ||
236 | T *p = (T *)pReg->pInfo->createPlugin(); | 236 | T *p = (T *)pReg->pInfo->createPlugin(); |
237 | hObj.insert( (ptrdiff_t)p, pReg ); | 237 | hObj.insert( (ptrdiff_t)p, pReg ); |
238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); | 238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); |
239 | 239 | ||
240 | return p; | 240 | return p; |
241 | } | 241 | } |
242 | 242 | ||
243 | bool hasPlugin( const Bu::String &lpName ) | 243 | bool hasPlugin( const Bu::String &lpName ) |
244 | { | 244 | { |
245 | return hPlugin.has( lpName ); | 245 | return hPlugin.has( lpName ); |
246 | } | 246 | } |
247 | 247 | ||
248 | void destroy( T *pPlug ) | 248 | void destroy( T *pPlug ) |
249 | { | 249 | { |
250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); | 250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); |
251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); | 251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); |
252 | if( pReg == NULL ) | 252 | if( pReg == NULL ) |
253 | return; | 253 | return; |
254 | 254 | ||
255 | pReg->pInfo->destroyPlugin( pPlug ); | 255 | pReg->pInfo->destroyPlugin( pPlug ); |
256 | 256 | ||
257 | hObj.erase( (ptrdiff_t)pPlug ); | 257 | hObj.erase( (ptrdiff_t)pPlug ); |
258 | } | 258 | } |
259 | 259 | ||
260 | void unloadAll() | 260 | void unloadAll() |
261 | { | 261 | { |
262 | for( PluginHash::iterator i = hPlugin.begin(); | 262 | for( PluginHash::iterator i = hPlugin.begin(); |
263 | i != hPlugin.end(); i++ ) | 263 | i != hPlugin.end(); i++ ) |
264 | { | 264 | { |
265 | if( (*i)->bBuiltin == false ) | 265 | if( (*i)->bBuiltin == false ) |
266 | { | 266 | { |
267 | #ifdef WIN32 | 267 | #ifdef WIN32 |
268 | FreeLibrary( (*i)->dlHandle ); | 268 | FreeLibrary( (*i)->dlHandle ); |
269 | #else | 269 | #else |
270 | dlclose( (*i)->dlHandle ); | 270 | dlclose( (*i)->dlHandle ); |
271 | #endif | 271 | #endif |
272 | } | 272 | } |
273 | delete (*i); | 273 | delete (*i); |
274 | } | 274 | } |
275 | hPlugin.clear(); | 275 | hPlugin.clear(); |
276 | } | 276 | } |
277 | 277 | ||
278 | Bu::List<Bu::String> getPluginList() | 278 | Bu::List<Bu::String> getPluginList() |
279 | { | 279 | { |
280 | return hPlugin.getKeys(); | 280 | return hPlugin.getKeys(); |
281 | } | 281 | } |
282 | 282 | ||
283 | private: | 283 | private: |
284 | PluginHash hPlugin; | 284 | PluginHash hPlugin; |
285 | InstHash hObj; | 285 | InstHash hObj; |
286 | }; | 286 | }; |
287 | } | 287 | } |
288 | 288 | ||
289 | #endif | 289 | #endif |
diff --git a/src/stable/process.cpp b/src/stable/process.cpp index a1adb23..a88ee7c 100644 --- a/src/stable/process.cpp +++ b/src/stable/process.cpp | |||
@@ -27,422 +27,422 @@ | |||
27 | 27 | ||
28 | Bu::Process::ProcData::ProcData() : | 28 | Bu::Process::ProcData::ProcData() : |
29 | #ifdef WIN32 | 29 | #ifdef WIN32 |
30 | hStdIn( NULL ), | 30 | hStdIn( NULL ), |
31 | hStdOut( NULL ), | 31 | hStdOut( NULL ), |
32 | hStdErr( NULL ) | 32 | hStdErr( NULL ) |
33 | #else | 33 | #else |
34 | iStdIn( -1 ), | 34 | iStdIn( -1 ), |
35 | iStdOut( -1 ), | 35 | iStdOut( -1 ), |
36 | iStdErr( -1 ) | 36 | iStdErr( -1 ) |
37 | #endif | 37 | #endif |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | 41 | ||
42 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | 42 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : |
43 | iProcStatus( 0 ), | 43 | iProcStatus( 0 ), |
44 | bBlocking( true ), | 44 | bBlocking( true ), |
45 | bStdOutEos( true ), | 45 | bStdOutEos( true ), |
46 | bStdErrEos( true ) | 46 | bStdErrEos( true ) |
47 | { | 47 | { |
48 | gexec( eFlags, sName, argv ); | 48 | gexec( eFlags, sName, argv ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : | 51 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : |
52 | iProcStatus( 0 ), | 52 | iProcStatus( 0 ), |
53 | bBlocking( true ), | 53 | bBlocking( true ), |
54 | bStdOutEos( true ), | 54 | bStdOutEos( true ), |
55 | bStdErrEos( true ) | 55 | bStdErrEos( true ) |
56 | { | 56 | { |
57 | int iCnt = 0; | 57 | int iCnt = 0; |
58 | va_list ap; | 58 | va_list ap; |
59 | va_start( ap, argv ); | 59 | va_start( ap, argv ); |
60 | for(; va_arg( ap, const char *); iCnt++ ) { } | 60 | for(; va_arg( ap, const char *); iCnt++ ) { } |
61 | va_end( ap ); | 61 | va_end( ap ); |
62 | 62 | ||
63 | char const **list = new char const *[iCnt+2]; | 63 | char const **list = new char const *[iCnt+2]; |
64 | va_start( ap, argv ); | 64 | va_start( ap, argv ); |
65 | list[0] = argv; | 65 | list[0] = argv; |
66 | for( int j = 1; j <= iCnt; j++ ) | 66 | for( int j = 1; j <= iCnt; j++ ) |
67 | { | 67 | { |
68 | list[j] = va_arg( ap, const char *); | 68 | list[j] = va_arg( ap, const char *); |
69 | } | 69 | } |
70 | list[iCnt+1] = NULL; | 70 | list[iCnt+1] = NULL; |
71 | va_end( ap ); | 71 | va_end( ap ); |
72 | 72 | ||
73 | gexec( eFlags, sName, (char *const *)list ); | 73 | gexec( eFlags, sName, (char *const *)list ); |
74 | delete[] list; | 74 | delete[] list; |
75 | } | 75 | } |
76 | 76 | ||
77 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : | 77 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : |
78 | iProcStatus( 0 ), | 78 | iProcStatus( 0 ), |
79 | bBlocking( true ), | 79 | bBlocking( true ), |
80 | bStdOutEos( true ), | 80 | bStdOutEos( true ), |
81 | bStdErrEos( true ), | 81 | bStdErrEos( true ), |
82 | opt( opt ) | 82 | opt( opt ) |
83 | { | 83 | { |
84 | gexec( eFlags, sName, argv ); | 84 | gexec( eFlags, sName, argv ); |
85 | } | 85 | } |
86 | 86 | ||
87 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : | 87 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : |
88 | iProcStatus( 0 ), | 88 | iProcStatus( 0 ), |
89 | bBlocking( true ), | 89 | bBlocking( true ), |
90 | bStdOutEos( true ), | 90 | bStdOutEos( true ), |
91 | bStdErrEos( true ), | 91 | bStdErrEos( true ), |
92 | opt( opt ) | 92 | opt( opt ) |
93 | { | 93 | { |
94 | int iCnt = 0; | 94 | int iCnt = 0; |
95 | va_list ap; | 95 | va_list ap; |
96 | va_start( ap, argv ); | 96 | va_start( ap, argv ); |
97 | for(; va_arg( ap, const char *); iCnt++ ) { } | 97 | for(; va_arg( ap, const char *); iCnt++ ) { } |
98 | va_end( ap ); | 98 | va_end( ap ); |
99 | 99 | ||
100 | char const **list = new char const *[iCnt+2]; | 100 | char const **list = new char const *[iCnt+2]; |
101 | va_start( ap, argv ); | 101 | va_start( ap, argv ); |
102 | list[0] = argv; | 102 | list[0] = argv; |
103 | for( int j = 1; j <= iCnt; j++ ) | 103 | for( int j = 1; j <= iCnt; j++ ) |
104 | { | 104 | { |
105 | list[j] = va_arg( ap, const char *); | 105 | list[j] = va_arg( ap, const char *); |
106 | } | 106 | } |
107 | list[iCnt+1] = NULL; | 107 | list[iCnt+1] = NULL; |
108 | va_end( ap ); | 108 | va_end( ap ); |
109 | 109 | ||
110 | gexec( eFlags, sName, (char *const *)list ); | 110 | gexec( eFlags, sName, (char *const *)list ); |
111 | delete[] list; | 111 | delete[] list; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::Process::~Process() | 114 | Bu::Process::~Process() |
115 | { | 115 | { |
116 | close(); | 116 | close(); |
117 | } | 117 | } |
118 | 118 | ||
119 | void Bu::Process::wait() | 119 | void Bu::Process::wait() |
120 | { | 120 | { |
121 | close(); | 121 | close(); |
122 | } | 122 | } |
123 | 123 | ||
124 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | 124 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) |
125 | { | 125 | { |
126 | #ifdef WIN32 | 126 | #ifdef WIN32 |
127 | bStdErrEos = true; | 127 | bStdErrEos = true; |
128 | SECURITY_ATTRIBUTES saAttr; | 128 | SECURITY_ATTRIBUTES saAttr; |
129 | HANDLE hChildStd_IN_Rd; | 129 | HANDLE hChildStd_IN_Rd; |
130 | HANDLE hChildStd_IN_Wr; | 130 | HANDLE hChildStd_IN_Wr; |
131 | HANDLE hChildStd_OUT_Rd; | 131 | HANDLE hChildStd_OUT_Rd; |
132 | HANDLE hChildStd_OUT_Wr; | 132 | HANDLE hChildStd_OUT_Wr; |
133 | PROCESS_INFORMATION piProcInfo; | 133 | PROCESS_INFORMATION piProcInfo; |
134 | 134 | ||
135 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | 135 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); |
136 | saAttr.bInheritHandle = TRUE; | 136 | saAttr.bInheritHandle = TRUE; |
137 | saAttr.lpSecurityDescriptor = NULL; | 137 | saAttr.lpSecurityDescriptor = NULL; |
138 | 138 | ||
139 | // Create a pipe for the child process's STDOUT. | 139 | // Create a pipe for the child process's STDOUT. |
140 | if ( ! CreatePipe( | 140 | if ( ! CreatePipe( |
141 | &hChildStd_OUT_Rd, | 141 | &hChildStd_OUT_Rd, |
142 | &hChildStd_OUT_Wr, | 142 | &hChildStd_OUT_Wr, |
143 | &saAttr, 0) ) | 143 | &saAttr, 0) ) |
144 | throw "StdoutRd CreatePipe"; | 144 | throw "StdoutRd CreatePipe"; |
145 | 145 | ||
146 | // Ensure the read handle to the pipe for STDOUT is not inherited. | 146 | // Ensure the read handle to the pipe for STDOUT is not inherited. |
147 | if ( ! SetHandleInformation( | 147 | if ( ! SetHandleInformation( |
148 | hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) | 148 | hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) |
149 | throw "Stdout SetHandleInformation"; | 149 | throw "Stdout SetHandleInformation"; |
150 | 150 | ||
151 | // Create a pipe for the child process's STDIN. | 151 | // Create a pipe for the child process's STDIN. |
152 | if (! CreatePipe( | 152 | if (! CreatePipe( |
153 | &hChildStd_IN_Rd, | 153 | &hChildStd_IN_Rd, |
154 | &hChildStd_IN_Wr, | 154 | &hChildStd_IN_Wr, |
155 | &saAttr, 0)) | 155 | &saAttr, 0)) |
156 | throw "Stdin CreatePipe"; | 156 | throw "Stdin CreatePipe"; |
157 | 157 | ||
158 | // Ensure the write handle to the pipe for STDIN is not inherited. | 158 | // Ensure the write handle to the pipe for STDIN is not inherited. |
159 | if ( ! SetHandleInformation( | 159 | if ( ! SetHandleInformation( |
160 | hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) | 160 | hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) |
161 | throw "Stdin SetHandleInformation"; | 161 | throw "Stdin SetHandleInformation"; |
162 | 162 | ||
163 | //TCHAR szCmdline[] = TEXT( sName ); | 163 | //TCHAR szCmdline[] = TEXT( sName ); |
164 | //PROCESS_INFORMATION pd.piProcInfo; | 164 | //PROCESS_INFORMATION pd.piProcInfo; |
165 | STARTUPINFO siStartInfo; | 165 | STARTUPINFO siStartInfo; |
166 | BOOL bSuccess = FALSE; | 166 | BOOL bSuccess = FALSE; |
167 | 167 | ||
168 | // Set up members of the PROCESS_INFORMATION structure. | 168 | // Set up members of the PROCESS_INFORMATION structure. |
169 | ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); | 169 | ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); |
170 | 170 | ||
171 | // Set up members of the STARTUPINFO structure. | 171 | // Set up members of the STARTUPINFO structure. |
172 | // This structure specifies the STDIN and STDOUT handles for redirection. | 172 | // This structure specifies the STDIN and STDOUT handles for redirection. |
173 | ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); | 173 | ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); |
174 | siStartInfo.cb = sizeof(STARTUPINFO); | 174 | siStartInfo.cb = sizeof(STARTUPINFO); |
175 | siStartInfo.hStdError = hChildStd_OUT_Wr; | 175 | siStartInfo.hStdError = hChildStd_OUT_Wr; |
176 | siStartInfo.hStdOutput = hChildStd_OUT_Wr; | 176 | siStartInfo.hStdOutput = hChildStd_OUT_Wr; |
177 | siStartInfo.hStdInput = hChildStd_IN_Rd; | 177 | siStartInfo.hStdInput = hChildStd_IN_Rd; |
178 | siStartInfo.dwFlags |= STARTF_USESTDHANDLES; | 178 | siStartInfo.dwFlags |= STARTF_USESTDHANDLES; |
179 | 179 | ||
180 | Bu::String sCmd; | 180 | Bu::String sCmd; |
181 | for( char *const *arg = argv; *arg; arg++ ) | 181 | for( char *const *arg = argv; *arg; arg++ ) |
182 | { | 182 | { |
183 | if( arg != argv ) | 183 | if( arg != argv ) |
184 | sCmd += " "; | 184 | sCmd += " "; |
185 | sCmd += *arg; | 185 | sCmd += *arg; |
186 | } | 186 | } |
187 | 187 | ||
188 | // Create the child process. | 188 | // Create the child process. |
189 | bSuccess = CreateProcessA( | 189 | bSuccess = CreateProcessA( |
190 | sName, //sName, //module name | 190 | sName, //sName, //module name |
191 | sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line | 191 | sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line |
192 | NULL, // process security attributes | 192 | NULL, // process security attributes |
193 | NULL, // primary thread security attributes | 193 | NULL, // primary thread security attributes |
194 | TRUE, // handles are inherited | 194 | TRUE, // handles are inherited |
195 | CREATE_NO_WINDOW, // creation flags | 195 | CREATE_NO_WINDOW, // creation flags |
196 | NULL, // use parent's environment | 196 | NULL, // use parent's environment |
197 | NULL, // use parent's current directory | 197 | NULL, // use parent's current directory |
198 | &siStartInfo, // STARTUPINFO pointer | 198 | &siStartInfo, // STARTUPINFO pointer |
199 | &piProcInfo ); // receives PROCESS_INFORMATION | 199 | &piProcInfo ); // receives PROCESS_INFORMATION |
200 | 200 | ||
201 | // If an error occurs, exit the application. | 201 | // If an error occurs, exit the application. |
202 | if ( ! bSuccess ) | 202 | if ( ! bSuccess ) |
203 | { | 203 | { |
204 | throw Bu::ExceptionBase("Error spawning child process."); | 204 | throw Bu::ExceptionBase("Error spawning child process."); |
205 | return; | 205 | return; |
206 | } | 206 | } |
207 | else | 207 | else |
208 | { | 208 | { |
209 | // Close handles to the child process and its primary thread. | 209 | // Close handles to the child process and its primary thread. |
210 | // Some applications might keep these handles to monitor the status | 210 | // Some applications might keep these handles to monitor the status |
211 | // of the child process, for example. | 211 | // of the child process, for example. |
212 | 212 | ||
213 | //CloseHandle(pData->pd.piProcInfo.hProcess); | 213 | //CloseHandle(pData->pd.piProcInfo.hProcess); |
214 | CloseHandle(piProcInfo.hThread); | 214 | CloseHandle(piProcInfo.hThread); |
215 | pd.hProcess = piProcInfo.hProcess; | 215 | pd.hProcess = piProcInfo.hProcess; |
216 | 216 | ||
217 | // Close the ends we can't use | 217 | // Close the ends we can't use |
218 | CloseHandle( hChildStd_OUT_Wr ); | 218 | CloseHandle( hChildStd_OUT_Wr ); |
219 | CloseHandle( hChildStd_IN_Rd ); | 219 | CloseHandle( hChildStd_IN_Rd ); |
220 | pd.hStdIn = hChildStd_IN_Wr; | 220 | pd.hStdIn = hChildStd_IN_Wr; |
221 | pd.hStdOut = hChildStd_OUT_Rd; | 221 | pd.hStdOut = hChildStd_OUT_Rd; |
222 | } | 222 | } |
223 | #else | 223 | #else |
224 | int iaStdIn[2]; | 224 | int iaStdIn[2]; |
225 | int iaStdOut[2]; | 225 | int iaStdOut[2]; |
226 | int iaStdErr[2]; | 226 | int iaStdErr[2]; |
227 | pipe( iaStdIn ); | 227 | pipe( iaStdIn ); |
228 | if( eFlags & StdOut ) | 228 | if( eFlags & StdOut ) |
229 | { | 229 | { |
230 | pipe( iaStdOut ); | 230 | pipe( iaStdOut ); |
231 | pd.iStdOut = iaStdOut[0]; | 231 | pd.iStdOut = iaStdOut[0]; |
232 | bStdOutEos = false; | 232 | bStdOutEos = false; |
233 | } | 233 | } |
234 | if( eFlags & StdErr ) | 234 | if( eFlags & StdErr ) |
235 | { | 235 | { |
236 | pipe( iaStdErr ); | 236 | pipe( iaStdErr ); |
237 | pd.iStdErr = iaStdErr[0]; | 237 | pd.iStdErr = iaStdErr[0]; |
238 | bStdErrEos = false; | 238 | bStdErrEos = false; |
239 | } | 239 | } |
240 | 240 | ||
241 | pd.iStdIn = iaStdIn[1]; | 241 | pd.iStdIn = iaStdIn[1]; |
242 | 242 | ||
243 | // fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 243 | // fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
244 | 244 | ||
245 | pd.iPid = fork(); | 245 | pd.iPid = fork(); |
246 | if( pd.iPid == 0 ) | 246 | if( pd.iPid == 0 ) |
247 | { | 247 | { |
248 | ::close( iaStdIn[1] ); | 248 | ::close( iaStdIn[1] ); |
249 | dup2( iaStdIn[0], 0 ); | 249 | dup2( iaStdIn[0], 0 ); |
250 | if( eFlags & StdOut ) | 250 | if( eFlags & StdOut ) |
251 | { | 251 | { |
252 | ::close( iaStdOut[0] ); | 252 | ::close( iaStdOut[0] ); |
253 | dup2( iaStdOut[1], 1 ); | 253 | dup2( iaStdOut[1], 1 ); |
254 | } | 254 | } |
255 | if( eFlags & StdErr ) | 255 | if( eFlags & StdErr ) |
256 | { | 256 | { |
257 | ::close( iaStdErr[0] ); | 257 | ::close( iaStdErr[0] ); |
258 | dup2( iaStdErr[1], 2 ); | 258 | dup2( iaStdErr[1], 2 ); |
259 | } | 259 | } |
260 | if( (opt.eFlags&Options::SetGid) ) | 260 | if( (opt.eFlags&Options::SetGid) ) |
261 | { | 261 | { |
262 | setgid( opt.iGid ); | 262 | setgid( opt.iGid ); |
263 | } | 263 | } |
264 | if( (opt.eFlags&Options::SetUid) ) | 264 | if( (opt.eFlags&Options::SetUid) ) |
265 | { | 265 | { |
266 | setuid( opt.iUid ); | 266 | setuid( opt.iUid ); |
267 | } | 267 | } |
268 | execvp( sName, argv ); | 268 | execvp( sName, argv ); |
269 | throw Bu::ExceptionBase("Hey, execvp failed!"); | 269 | throw Bu::ExceptionBase("Hey, execvp failed!"); |
270 | } | 270 | } |
271 | ::close( iaStdIn[0] ); | 271 | ::close( iaStdIn[0] ); |
272 | if( eFlags & StdOut ) | 272 | if( eFlags & StdOut ) |
273 | ::close( iaStdOut[1] ); | 273 | ::close( iaStdOut[1] ); |
274 | if( eFlags & StdErr ) | 274 | if( eFlags & StdErr ) |
275 | ::close( iaStdErr[1] ); | 275 | ::close( iaStdErr[1] ); |
276 | #endif | 276 | #endif |
277 | } | 277 | } |
278 | 278 | ||
279 | void Bu::Process::close() | 279 | void Bu::Process::close() |
280 | { | 280 | { |
281 | #ifdef WIN32 | 281 | #ifdef WIN32 |
282 | if( pd.hStdIn ) | 282 | if( pd.hStdIn ) |
283 | { | 283 | { |
284 | CloseHandle( pd.hStdIn ); | 284 | CloseHandle( pd.hStdIn ); |
285 | CloseHandle( pd.hStdOut ); | 285 | CloseHandle( pd.hStdOut ); |
286 | 286 | ||
287 | pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; | 287 | pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; |
288 | 288 | ||
289 | if( !TerminateProcess(pd.hProcess, 1) ) | 289 | if( !TerminateProcess(pd.hProcess, 1) ) |
290 | { | 290 | { |
291 | throw Bu::ExceptionBase("Error closing process."); | 291 | throw Bu::ExceptionBase("Error closing process."); |
292 | } | 292 | } |
293 | 293 | ||
294 | GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus ); | 294 | GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus ); |
295 | 295 | ||
296 | CloseHandle( pd.hProcess ); | 296 | CloseHandle( pd.hProcess ); |
297 | pd.hProcess = NULL; | 297 | pd.hProcess = NULL; |
298 | } | 298 | } |
299 | #else | 299 | #else |
300 | if( pd.iPid ) | 300 | if( pd.iPid ) |
301 | { | 301 | { |
302 | if( pd.iStdIn > -1 ) | 302 | if( pd.iStdIn > -1 ) |
303 | ::close( pd.iStdIn ); | 303 | ::close( pd.iStdIn ); |
304 | if( pd.iStdOut > -1 ) | 304 | if( pd.iStdOut > -1 ) |
305 | ::close( pd.iStdOut ); | 305 | ::close( pd.iStdOut ); |
306 | if( pd.iStdErr > -1 ) | 306 | if( pd.iStdErr > -1 ) |
307 | ::close( pd.iStdErr ); | 307 | ::close( pd.iStdErr ); |
308 | waitpid( pd.iPid, &iProcStatus, 0 ); | 308 | waitpid( pd.iPid, &iProcStatus, 0 ); |
309 | pd.iPid = 0; | 309 | pd.iPid = 0; |
310 | } | 310 | } |
311 | #endif | 311 | #endif |
312 | } | 312 | } |
313 | 313 | ||
314 | void Bu::Process::closeStdIn() | 314 | void Bu::Process::closeStdIn() |
315 | { | 315 | { |
316 | #ifdef WIN32 | 316 | #ifdef WIN32 |
317 | CloseHandle( pd.hStdIn ); | 317 | CloseHandle( pd.hStdIn ); |
318 | pd.hStdIn = NULL; | 318 | pd.hStdIn = NULL; |
319 | #else | 319 | #else |
320 | ::close( pd.iStdIn ); | 320 | ::close( pd.iStdIn ); |
321 | pd.iStdIn = -1; | 321 | pd.iStdIn = -1; |
322 | #endif | 322 | #endif |
323 | } | 323 | } |
324 | 324 | ||
325 | void Bu::Process::closeStdOut() | 325 | void Bu::Process::closeStdOut() |
326 | { | 326 | { |
327 | #ifdef WIN32 | 327 | #ifdef WIN32 |
328 | CloseHandle( pd.hStdOut ); | 328 | CloseHandle( pd.hStdOut ); |
329 | pd.hStdOut = NULL; | 329 | pd.hStdOut = NULL; |
330 | #else | 330 | #else |
331 | ::close( pd.iStdOut ); | 331 | ::close( pd.iStdOut ); |
332 | pd.iStdOut = -1; | 332 | pd.iStdOut = -1; |
333 | #endif | 333 | #endif |
334 | } | 334 | } |
335 | 335 | ||
336 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) | 336 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) |
337 | { | 337 | { |
338 | #ifdef WIN32 | 338 | #ifdef WIN32 |
339 | DWORD dwRead; | 339 | DWORD dwRead; |
340 | DWORD lExitCode; | 340 | DWORD lExitCode; |
341 | BOOL bSuccess = FALSE; | 341 | BOOL bSuccess = FALSE; |
342 | DWORD dwLen = (DWORD) nBytes; | 342 | DWORD dwLen = (DWORD) nBytes; |
343 | bSuccess = ReadFile( | 343 | bSuccess = ReadFile( |
344 | pd.hStdOut, (char *) pBuf, | 344 | pd.hStdOut, (char *) pBuf, |
345 | dwLen, &dwRead, NULL); | 345 | dwLen, &dwRead, NULL); |
346 | // if( dwRead < dwLen ) | 346 | // if( dwRead < dwLen ) |
347 | { | 347 | { |
348 | bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode ); | 348 | bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode ); |
349 | if( lExitCode != STILL_ACTIVE ) | 349 | if( lExitCode != STILL_ACTIVE ) |
350 | { | 350 | { |
351 | bStdOutEos = true; | 351 | bStdOutEos = true; |
352 | } | 352 | } |
353 | } | 353 | } |
354 | return (int32_t) dwRead; | 354 | return (int32_t) dwRead; |
355 | #else | 355 | #else |
356 | if( bStdOutEos ) | 356 | if( bStdOutEos ) |
357 | return 0; | 357 | return 0; |
358 | fd_set rfds; | 358 | fd_set rfds; |
359 | FD_ZERO( &rfds ); | 359 | FD_ZERO( &rfds ); |
360 | FD_SET( pd.iStdOut, &rfds ); | 360 | FD_SET( pd.iStdOut, &rfds ); |
361 | struct timeval tv = {0, 0}; | 361 | struct timeval tv = {0, 0}; |
362 | if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) | 362 | if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) |
363 | throw Bu::ExceptionBase( strerror( errno ) ); | 363 | throw Bu::ExceptionBase( strerror( errno ) ); |
364 | if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) | 364 | if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) |
365 | { | 365 | { |
366 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); | 366 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); |
367 | if( nRead == 0 ) | 367 | if( nRead == 0 ) |
368 | { | 368 | { |
369 | bStdOutEos = true; | 369 | bStdOutEos = true; |
370 | checkClose(); | 370 | checkClose(); |
371 | return 0; | 371 | return 0; |
372 | } | 372 | } |
373 | if( nRead < 0 ) | 373 | if( nRead < 0 ) |
374 | { | 374 | { |
375 | if( errno == EAGAIN ) | 375 | if( errno == EAGAIN ) |
376 | return 0; | 376 | return 0; |
377 | throw Bu::ExceptionBase( strerror( errno ) ); | 377 | throw Bu::ExceptionBase( strerror( errno ) ); |
378 | } | 378 | } |
379 | return nRead; | 379 | return nRead; |
380 | } | 380 | } |
381 | return 0; | 381 | return 0; |
382 | #endif | 382 | #endif |
383 | } | 383 | } |
384 | 384 | ||
385 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) | 385 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) |
386 | { | 386 | { |
387 | #ifdef WIN32 | 387 | #ifdef WIN32 |
388 | if( !pd.hStdErr ) | 388 | if( !pd.hStdErr ) |
389 | return 0; | 389 | return 0; |
390 | DWORD dwRead; | 390 | DWORD dwRead; |
391 | BOOL bSuccess = FALSE; | 391 | BOOL bSuccess = FALSE; |
392 | DWORD dwLen = (DWORD) nBytes; | 392 | DWORD dwLen = (DWORD) nBytes; |
393 | bSuccess = ReadFile( | 393 | bSuccess = ReadFile( |
394 | pd.hStdErr, (char *) pBuf, | 394 | pd.hStdErr, (char *) pBuf, |
395 | dwLen, &dwRead, NULL); | 395 | dwLen, &dwRead, NULL); |
396 | return (int32_t) dwRead; | 396 | return (int32_t) dwRead; |
397 | #else | 397 | #else |
398 | if( bStdErrEos ) | 398 | if( bStdErrEos ) |
399 | return 0; | 399 | return 0; |
400 | fd_set rfds; | 400 | fd_set rfds; |
401 | FD_ZERO( &rfds ); | 401 | FD_ZERO( &rfds ); |
402 | FD_SET( pd.iStdErr, &rfds ); | 402 | FD_SET( pd.iStdErr, &rfds ); |
403 | struct timeval tv = {0, 0}; | 403 | struct timeval tv = {0, 0}; |
404 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) | 404 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) |
405 | throw Bu::ExceptionBase( strerror( errno ) ); | 405 | throw Bu::ExceptionBase( strerror( errno ) ); |
406 | if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) | 406 | if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) |
407 | { | 407 | { |
408 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); | 408 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); |
409 | if( nRead == 0 ) | 409 | if( nRead == 0 ) |
410 | { | 410 | { |
411 | bStdErrEos = true; | 411 | bStdErrEos = true; |
412 | checkClose(); | 412 | checkClose(); |
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | if( nRead < 0 ) | 415 | if( nRead < 0 ) |
416 | { | 416 | { |
417 | if( errno == EAGAIN ) | 417 | if( errno == EAGAIN ) |
418 | return 0; | 418 | return 0; |
419 | throw Bu::ExceptionBase( strerror( errno ) ); | 419 | throw Bu::ExceptionBase( strerror( errno ) ); |
420 | } | 420 | } |
421 | return nRead; | 421 | return nRead; |
422 | } | 422 | } |
423 | return 0; | 423 | return 0; |
424 | #endif | 424 | #endif |
425 | } | 425 | } |
426 | 426 | ||
427 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) | 427 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) |
428 | { | 428 | { |
429 | #ifdef WIN32 | 429 | #ifdef WIN32 |
430 | DWORD dwWritten; | 430 | DWORD dwWritten; |
431 | BOOL bSuccess = FALSE; | 431 | BOOL bSuccess = FALSE; |
432 | DWORD dwLen = (DWORD) nBytes; | 432 | DWORD dwLen = (DWORD) nBytes; |
433 | bSuccess = WriteFile( | 433 | bSuccess = WriteFile( |
434 | pd.hStdIn, (const char *) pBuf, | 434 | pd.hStdIn, (const char *) pBuf, |
435 | dwLen, &dwWritten, NULL ); | 435 | dwLen, &dwWritten, NULL ); |
436 | FlushFileBuffers( pd.hStdIn ); | 436 | FlushFileBuffers( pd.hStdIn ); |
437 | return (int32_t) dwWritten; | 437 | return (int32_t) dwWritten; |
438 | #else | 438 | #else |
439 | return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); | 439 | return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); |
440 | #endif | 440 | #endif |
441 | } | 441 | } |
442 | 442 | ||
443 | Bu::size Bu::Process::tell() | 443 | Bu::size Bu::Process::tell() |
444 | { | 444 | { |
445 | return 0; | 445 | return 0; |
446 | } | 446 | } |
447 | 447 | ||
448 | void Bu::Process::seek( Bu::size ) | 448 | void Bu::Process::seek( Bu::size ) |
@@ -460,15 +460,15 @@ void Bu::Process::setPosEnd( Bu::size ) | |||
460 | bool Bu::Process::isEos() | 460 | bool Bu::Process::isEos() |
461 | { | 461 | { |
462 | #ifdef WIN32 | 462 | #ifdef WIN32 |
463 | return (pd.hProcess == NULL); | 463 | return (pd.hProcess == NULL); |
464 | #else | 464 | #else |
465 | return (pd.iPid == 0); | 465 | return (pd.iPid == 0); |
466 | #endif | 466 | #endif |
467 | } | 467 | } |
468 | 468 | ||
469 | bool Bu::Process::isOpen() | 469 | bool Bu::Process::isOpen() |
470 | { | 470 | { |
471 | return !isEos(); | 471 | return !isEos(); |
472 | } | 472 | } |
473 | 473 | ||
474 | void Bu::Process::flush() | 474 | void Bu::Process::flush() |
@@ -477,53 +477,53 @@ void Bu::Process::flush() | |||
477 | 477 | ||
478 | bool Bu::Process::canRead() | 478 | bool Bu::Process::canRead() |
479 | { | 479 | { |
480 | return true; | 480 | return true; |
481 | } | 481 | } |
482 | 482 | ||
483 | bool Bu::Process::canWrite() | 483 | bool Bu::Process::canWrite() |
484 | { | 484 | { |
485 | return true; | 485 | return true; |
486 | } | 486 | } |
487 | 487 | ||
488 | bool Bu::Process::isReadable() | 488 | bool Bu::Process::isReadable() |
489 | { | 489 | { |
490 | return true; | 490 | return true; |
491 | } | 491 | } |
492 | 492 | ||
493 | bool Bu::Process::isWritable() | 493 | bool Bu::Process::isWritable() |
494 | { | 494 | { |
495 | return true; | 495 | return true; |
496 | } | 496 | } |
497 | 497 | ||
498 | bool Bu::Process::isSeekable() | 498 | bool Bu::Process::isSeekable() |
499 | { | 499 | { |
500 | return false; | 500 | return false; |
501 | } | 501 | } |
502 | 502 | ||
503 | bool Bu::Process::isBlocking() | 503 | bool Bu::Process::isBlocking() |
504 | { | 504 | { |
505 | return true; | 505 | return true; |
506 | } | 506 | } |
507 | 507 | ||
508 | void Bu::Process::setBlocking( bool bBlocking ) | 508 | void Bu::Process::setBlocking( bool bBlocking ) |
509 | { | 509 | { |
510 | #ifdef WIN32 | 510 | #ifdef WIN32 |
511 | #else | 511 | #else |
512 | if( bBlocking ) | 512 | if( bBlocking ) |
513 | { | 513 | { |
514 | if( !bStdOutEos ) | 514 | if( !bStdOutEos ) |
515 | fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); | 515 | fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); |
516 | if( !bStdErrEos ) | 516 | if( !bStdErrEos ) |
517 | fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); | 517 | fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); |
518 | } | 518 | } |
519 | else | 519 | else |
520 | { | 520 | { |
521 | if( !bStdOutEos ) | 521 | if( !bStdOutEos ) |
522 | fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 522 | fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
523 | if( !bStdErrEos ) | 523 | if( !bStdErrEos ) |
524 | fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); | 524 | fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); |
525 | } | 525 | } |
526 | this->bBlocking = bBlocking; | 526 | this->bBlocking = bBlocking; |
527 | #endif | 527 | #endif |
528 | } | 528 | } |
529 | 529 | ||
@@ -533,128 +533,128 @@ void Bu::Process::setSize( Bu::size ) | |||
533 | 533 | ||
534 | Bu::size Bu::Process::getBlockSize() const | 534 | Bu::size Bu::Process::getBlockSize() const |
535 | { | 535 | { |
536 | return 0; | 536 | return 0; |
537 | } | 537 | } |
538 | 538 | ||
539 | Bu::size Bu::Process::getSize() const | 539 | Bu::size Bu::Process::getSize() const |
540 | { | 540 | { |
541 | return 0; | 541 | return 0; |
542 | } | 542 | } |
543 | 543 | ||
544 | Bu::String Bu::Process::getLocation() const | 544 | Bu::String Bu::Process::getLocation() const |
545 | { | 545 | { |
546 | return ""; | 546 | return ""; |
547 | } | 547 | } |
548 | 548 | ||
549 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) | 549 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) |
550 | { | 550 | { |
551 | #ifdef WIN32 | 551 | #ifdef WIN32 |
552 | #else | 552 | #else |
553 | fd_set rfds; | 553 | fd_set rfds; |
554 | FD_ZERO( &rfds ); | 554 | FD_ZERO( &rfds ); |
555 | if( !bStdOutEos ) | 555 | if( !bStdOutEos ) |
556 | FD_SET( pd.iStdOut, &rfds ); | 556 | FD_SET( pd.iStdOut, &rfds ); |
557 | if( !bStdErrEos ) | 557 | if( !bStdErrEos ) |
558 | FD_SET( pd.iStdErr, &rfds ); | 558 | FD_SET( pd.iStdErr, &rfds ); |
559 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) | 559 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) |
560 | throw Bu::ExceptionBase( strerror( errno ) ); | 560 | throw Bu::ExceptionBase( strerror( errno ) ); |
561 | 561 | ||
562 | if( FD_ISSET( pd.iStdOut, &rfds ) ) | 562 | if( FD_ISSET( pd.iStdOut, &rfds ) ) |
563 | bStdOut = true; | 563 | bStdOut = true; |
564 | else | 564 | else |
565 | bStdOut = false; | 565 | bStdOut = false; |
566 | 566 | ||
567 | if( FD_ISSET( pd.iStdErr, &rfds ) ) | 567 | if( FD_ISSET( pd.iStdErr, &rfds ) ) |
568 | bStdErr = true; | 568 | bStdErr = true; |
569 | else | 569 | else |
570 | bStdErr = false; | 570 | bStdErr = false; |
571 | #endif | 571 | #endif |
572 | } | 572 | } |
573 | 573 | ||
574 | bool Bu::Process::isRunning() | 574 | bool Bu::Process::isRunning() |
575 | { | 575 | { |
576 | #ifdef WIN32 | 576 | #ifdef WIN32 |
577 | DWORD lExitCode; | 577 | DWORD lExitCode; |
578 | GetExitCodeProcess( pd.hProcess, &lExitCode ); | 578 | GetExitCodeProcess( pd.hProcess, &lExitCode ); |
579 | if( lExitCode != STILL_ACTIVE ) | 579 | if( lExitCode != STILL_ACTIVE ) |
580 | checkClose(); | 580 | checkClose(); |
581 | #else | 581 | #else |
582 | if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) | 582 | if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) |
583 | checkClose(); | 583 | checkClose(); |
584 | #endif | 584 | #endif |
585 | return isOpen(); | 585 | return isOpen(); |
586 | } | 586 | } |
587 | 587 | ||
588 | void Bu::Process::ignoreStdErr() | 588 | void Bu::Process::ignoreStdErr() |
589 | { | 589 | { |
590 | #ifdef WIN32 | 590 | #ifdef WIN32 |
591 | #else | 591 | #else |
592 | if( pd.iStdErr == -1 ) | 592 | if( pd.iStdErr == -1 ) |
593 | return; | 593 | return; |
594 | ::close( pd.iStdErr ); | 594 | ::close( pd.iStdErr ); |
595 | pd.iStdErr = -1; | 595 | pd.iStdErr = -1; |
596 | bStdErrEos = true; | 596 | bStdErrEos = true; |
597 | #endif | 597 | #endif |
598 | } | 598 | } |
599 | 599 | ||
600 | pid_t Bu::Process::getPid() | 600 | pid_t Bu::Process::getPid() |
601 | { | 601 | { |
602 | #ifdef WIN32 | 602 | #ifdef WIN32 |
603 | return 0; | 603 | return 0; |
604 | #else | 604 | #else |
605 | return pd.iPid; | 605 | return pd.iPid; |
606 | #endif | 606 | #endif |
607 | } | 607 | } |
608 | 608 | ||
609 | bool Bu::Process::childExited() | 609 | bool Bu::Process::childExited() |
610 | { | 610 | { |
611 | #ifdef WIN32 | 611 | #ifdef WIN32 |
612 | return pd.hProcess != NULL; | 612 | return pd.hProcess != NULL; |
613 | #else | 613 | #else |
614 | return WIFEXITED( iProcStatus ); | 614 | return WIFEXITED( iProcStatus ); |
615 | #endif | 615 | #endif |
616 | } | 616 | } |
617 | 617 | ||
618 | int Bu::Process::childExitStatus() | 618 | int Bu::Process::childExitStatus() |
619 | { | 619 | { |
620 | #ifdef WIN32 | 620 | #ifdef WIN32 |
621 | return iProcStatus; | 621 | return iProcStatus; |
622 | #else | 622 | #else |
623 | return WEXITSTATUS( iProcStatus ); | 623 | return WEXITSTATUS( iProcStatus ); |
624 | #endif | 624 | #endif |
625 | } | 625 | } |
626 | 626 | ||
627 | bool Bu::Process::childSignaled() | 627 | bool Bu::Process::childSignaled() |
628 | { | 628 | { |
629 | #ifdef WIN32 | 629 | #ifdef WIN32 |
630 | return false; | 630 | return false; |
631 | #else | 631 | #else |
632 | return WIFSIGNALED( iProcStatus ); | 632 | return WIFSIGNALED( iProcStatus ); |
633 | #endif | 633 | #endif |
634 | } | 634 | } |
635 | 635 | ||
636 | int Bu::Process::childSignal() | 636 | int Bu::Process::childSignal() |
637 | { | 637 | { |
638 | #ifdef WIN32 | 638 | #ifdef WIN32 |
639 | return 0; | 639 | return 0; |
640 | #else | 640 | #else |
641 | return WTERMSIG( iProcStatus ); | 641 | return WTERMSIG( iProcStatus ); |
642 | #endif | 642 | #endif |
643 | } | 643 | } |
644 | 644 | ||
645 | bool Bu::Process::childCoreDumped() | 645 | bool Bu::Process::childCoreDumped() |
646 | { | 646 | { |
647 | #ifdef WIN32 | 647 | #ifdef WIN32 |
648 | return false; | 648 | return false; |
649 | #else | 649 | #else |
650 | return WCOREDUMP( iProcStatus ); | 650 | return WCOREDUMP( iProcStatus ); |
651 | #endif | 651 | #endif |
652 | } | 652 | } |
653 | 653 | ||
654 | void Bu::Process::checkClose() | 654 | void Bu::Process::checkClose() |
655 | { | 655 | { |
656 | if( bStdOutEos && bStdErrEos ) | 656 | if( bStdOutEos && bStdErrEos ) |
657 | { | 657 | { |
658 | close(); | 658 | close(); |
659 | } | 659 | } |
660 | } | 660 | } |
diff --git a/src/stable/process.h b/src/stable/process.h index 904606a..72b686a 100644 --- a/src/stable/process.h +++ b/src/stable/process.h | |||
@@ -16,151 +16,151 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Runs a program and attaches streams to it's stdin, stdout, and stderr. | 20 | * Runs a program and attaches streams to it's stdin, stdout, and stderr. |
21 | * Reading from a Bu::Process will read from the program's standard output, | 21 | * Reading from a Bu::Process will read from the program's standard output, |
22 | * writing to a Bu::Process will write to the program's standard input. | 22 | * writing to a Bu::Process will write to the program's standard input. |
23 | */ | 23 | */ |
24 | class Process : public Bu::Stream | 24 | class Process : public Bu::Stream |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | enum Flags | 27 | enum Flags |
28 | { | 28 | { |
29 | None = 0x00, | 29 | None = 0x00, |
30 | StdOut = 0x01, | 30 | StdOut = 0x01, |
31 | StdErr = 0x02, | 31 | StdErr = 0x02, |
32 | Both = 0x03 | 32 | Both = 0x03 |
33 | }; | 33 | }; |
34 | 34 | ||
35 | public: | 35 | public: |
36 | class Options | 36 | class Options |
37 | { | 37 | { |
38 | public: | 38 | public: |
39 | enum OptFlags | 39 | enum OptFlags |
40 | { | 40 | { |
41 | None = 0x00, | 41 | None = 0x00, |
42 | SetUid = 0x01, | 42 | SetUid = 0x01, |
43 | SetGid = 0x02, | 43 | SetGid = 0x02, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | Options() : eFlags( None ) {} | 46 | Options() : eFlags( None ) {} |
47 | 47 | ||
48 | int eFlags; | 48 | int eFlags; |
49 | int iUid; | 49 | int iUid; |
50 | int iGid; | 50 | int iGid; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | Process( Flags eFlags, const char *sName, char *const argv[] ); | 53 | Process( Flags eFlags, const char *sName, char *const argv[] ); |
54 | Process( Flags eFlags, const char *sName, const char *argv, ...); | 54 | Process( Flags eFlags, const char *sName, const char *argv, ...); |
55 | Process( Flags eFlags, const Options &opt, const char *sName, char *const argv[] ); | 55 | Process( Flags eFlags, const Options &opt, const char *sName, char *const argv[] ); |
56 | Process( Flags eFlags, const Options &opt, const char *sName, const char *argv, ...); | 56 | Process( Flags eFlags, const Options &opt, const char *sName, const char *argv, ...); |
57 | virtual ~Process(); | 57 | virtual ~Process(); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * Waits until the process exits. This blocks the caller until the | 60 | * Waits until the process exits. This blocks the caller until the |
61 | * child process terminates. | 61 | * child process terminates. |
62 | */ | 62 | */ |
63 | void wait(); | 63 | void wait(); |
64 | 64 | ||
65 | virtual void close(); | 65 | virtual void close(); |
66 | virtual void closeStdIn(); | 66 | virtual void closeStdIn(); |
67 | virtual void closeStdOut(); | 67 | virtual void closeStdOut(); |
68 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 68 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
69 | virtual Bu::size readErr( void *pBuf, Bu::size nBytes ); | 69 | virtual Bu::size readErr( void *pBuf, Bu::size nBytes ); |
70 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 70 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
71 | using Stream::write; | 71 | using Stream::write; |
72 | 72 | ||
73 | virtual Bu::size tell(); | 73 | virtual Bu::size tell(); |
74 | virtual void seek( Bu::size offset ); | 74 | virtual void seek( Bu::size offset ); |
75 | virtual void setPos( Bu::size pos ); | 75 | virtual void setPos( Bu::size pos ); |
76 | virtual void setPosEnd( Bu::size pos ); | 76 | virtual void setPosEnd( Bu::size pos ); |
77 | virtual bool isEos(); | 77 | virtual bool isEos(); |
78 | virtual bool isOpen(); | 78 | virtual bool isOpen(); |
79 | 79 | ||
80 | virtual void flush(); | 80 | virtual void flush(); |
81 | 81 | ||
82 | virtual bool canRead(); | 82 | virtual bool canRead(); |
83 | virtual bool canWrite(); | 83 | virtual bool canWrite(); |
84 | 84 | ||
85 | virtual bool isReadable(); | 85 | virtual bool isReadable(); |
86 | virtual bool isWritable(); | 86 | virtual bool isWritable(); |
87 | virtual bool isSeekable(); | 87 | virtual bool isSeekable(); |
88 | 88 | ||
89 | virtual bool isBlocking(); | 89 | virtual bool isBlocking(); |
90 | virtual void setBlocking( bool bBlocking=true ); | 90 | virtual void setBlocking( bool bBlocking=true ); |
91 | 91 | ||
92 | virtual void setSize( Bu::size iSize ); | 92 | virtual void setSize( Bu::size iSize ); |
93 | 93 | ||
94 | virtual size getBlockSize() const; | 94 | virtual size getBlockSize() const; |
95 | virtual size getSize() const; | 95 | virtual size getSize() const; |
96 | virtual Bu::String getLocation() const; | 96 | virtual Bu::String getLocation() const; |
97 | 97 | ||
98 | void select( bool &bStdOut, bool &bStdErr ); | 98 | void select( bool &bStdOut, bool &bStdErr ); |
99 | 99 | ||
100 | bool isRunning(); | 100 | bool isRunning(); |
101 | void ignoreStdErr(); | 101 | void ignoreStdErr(); |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Returns the pid of the child process, or zero if there is no | 104 | * Returns the pid of the child process, or zero if there is no |
105 | * currently running child. Note that a read operation must be | 105 | * currently running child. Note that a read operation must be |
106 | * performed in order to discover that the child has ended. | 106 | * performed in order to discover that the child has ended. |
107 | */ | 107 | */ |
108 | pid_t getPid(); | 108 | pid_t getPid(); |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * Returns true if the child exited normally (by calling exit or | 111 | * Returns true if the child exited normally (by calling exit or |
112 | * returning from main). | 112 | * returning from main). |
113 | */ | 113 | */ |
114 | bool childExited(); | 114 | bool childExited(); |
115 | 115 | ||
116 | /** | 116 | /** |
117 | * Returns the 8 bit integer value returned from the child program if | 117 | * Returns the 8 bit integer value returned from the child program if |
118 | * childExited returned true. | 118 | * childExited returned true. |
119 | */ | 119 | */ |
120 | int childExitStatus(); | 120 | int childExitStatus(); |
121 | 121 | ||
122 | /** | 122 | /** |
123 | * Returns true if the child exited because of a signal. | 123 | * Returns true if the child exited because of a signal. |
124 | */ | 124 | */ |
125 | bool childSignaled(); | 125 | bool childSignaled(); |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * Returns the signal ID if the childSignaled return true. | 128 | * Returns the signal ID if the childSignaled return true. |
129 | */ | 129 | */ |
130 | int childSignal(); | 130 | int childSignal(); |
131 | 131 | ||
132 | /** | 132 | /** |
133 | * Returns true if the child left a core dump behind when it exited. | 133 | * Returns true if the child left a core dump behind when it exited. |
134 | */ | 134 | */ |
135 | bool childCoreDumped(); | 135 | bool childCoreDumped(); |
136 | 136 | ||
137 | private: | 137 | private: |
138 | class ProcData | 138 | class ProcData |
139 | { | 139 | { |
140 | public: | 140 | public: |
141 | ProcData(); | 141 | ProcData(); |
142 | #ifdef WIN32 | 142 | #ifdef WIN32 |
143 | void *hStdIn; | 143 | void *hStdIn; |
144 | void *hStdOut; | 144 | void *hStdOut; |
145 | void *hStdErr; | 145 | void *hStdErr; |
146 | void *hProcess; | 146 | void *hProcess; |
147 | #else | 147 | #else |
148 | int iStdIn; | 148 | int iStdIn; |
149 | int iStdOut; | 149 | int iStdOut; |
150 | int iStdErr; | 150 | int iStdErr; |
151 | pid_t iPid; | 151 | pid_t iPid; |
152 | #endif | 152 | #endif |
153 | }; | 153 | }; |
154 | ProcData pd; | 154 | ProcData pd; |
155 | int iProcStatus; | 155 | int iProcStatus; |
156 | bool bBlocking; | 156 | bool bBlocking; |
157 | bool bStdOutEos; | 157 | bool bStdOutEos; |
158 | bool bStdErrEos; | 158 | bool bStdErrEos; |
159 | 159 | ||
160 | void gexec( Flags eFlags, const char *sName, char *const argv[] ); | 160 | void gexec( Flags eFlags, const char *sName, char *const argv[] ); |
161 | void checkClose(); | 161 | void checkClose(); |
162 | Options opt; | 162 | Options opt; |
163 | }; | 163 | }; |
164 | } | 164 | } |
165 | 165 | ||
166 | #endif | 166 | #endif |
diff --git a/src/stable/protocol.h b/src/stable/protocol.h index 1a02143..4e121d9 100644 --- a/src/stable/protocol.h +++ b/src/stable/protocol.h | |||
@@ -14,25 +14,25 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Client; | 17 | class Client; |
18 | 18 | ||
19 | /** | 19 | /** |
20 | *@ingroup Serving | 20 | *@ingroup Serving |
21 | */ | 21 | */ |
22 | class Protocol | 22 | class Protocol |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Protocol(); | 25 | Protocol(); |
26 | virtual ~Protocol(); | 26 | virtual ~Protocol(); |
27 | 27 | ||
28 | virtual void onNewConnection( Bu::Client *pClient ); | 28 | virtual void onNewConnection( Bu::Client *pClient ); |
29 | virtual void onNewData( Bu::Client *pClient ); | 29 | virtual void onNewData( Bu::Client *pClient ); |
30 | virtual void onMessage( Bu::Client *pClient, const Bu::String &sMsg ); | 30 | virtual void onMessage( Bu::Client *pClient, const Bu::String &sMsg ); |
31 | virtual void onTick( Bu::Client *pClient ); | 31 | virtual void onTick( Bu::Client *pClient ); |
32 | 32 | ||
33 | private: | 33 | private: |
34 | 34 | ||
35 | }; | 35 | }; |
36 | } | 36 | } |
37 | 37 | ||
38 | #endif | 38 | #endif |
diff --git a/src/stable/protocolhttp.cpp b/src/stable/protocolhttp.cpp index ea1a86e..352f7c7 100644 --- a/src/stable/protocolhttp.cpp +++ b/src/stable/protocolhttp.cpp | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <dirent.h> | 8 | #include <dirent.h> |
9 | 9 | ||
10 | #ifndef WIN32 | 10 | #ifndef WIN32 |
11 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #include <errno.h> | 14 | #include <errno.h> |
@@ -32,9 +32,9 @@ Bu::ProtocolHttp::~ProtocolHttp() | |||
32 | 32 | ||
33 | void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) | 33 | void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) |
34 | { | 34 | { |
35 | this->pClient = pClient; | 35 | this->pClient = pClient; |
36 | 36 | ||
37 | iState = 0; | 37 | iState = 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | #define SDB( i ) (void)0 | 40 | #define SDB( i ) (void)0 |
@@ -42,196 +42,196 @@ void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) | |||
42 | 42 | ||
43 | void Bu::ProtocolHttp::onNewData( Bu::Client *pClient ) | 43 | void Bu::ProtocolHttp::onNewData( Bu::Client *pClient ) |
44 | { | 44 | { |
45 | /* logHexDump( | 45 | /* logHexDump( |
46 | 1, | 46 | 1, |
47 | pClient->getInput().getStr(), | 47 | pClient->getInput().getStr(), |
48 | pClient->getInput().getSize(), | 48 | pClient->getInput().getSize(), |
49 | "input" | 49 | "input" |
50 | );*/ | 50 | );*/ |
51 | 51 | ||
52 | for(;;) | 52 | for(;;) |
53 | { | 53 | { |
54 | Bu::String sToken; | 54 | Bu::String sToken; |
55 | TokenType tt = getToken( sToken ); | 55 | TokenType tt = getToken( sToken ); |
56 | 56 | ||
57 | if( tt == ttOutOfData ) | 57 | if( tt == ttOutOfData ) |
58 | return; | 58 | return; |
59 | 59 | ||
60 | switch( iState ) | 60 | switch( iState ) |
61 | { | 61 | { |
62 | case 0: // Start token, should be "method" (get, put, etc) | 62 | case 0: // Start token, should be "method" (get, put, etc) |
63 | SDB( 0 ); | 63 | SDB( 0 ); |
64 | sMethod = sToken; | 64 | sMethod = sToken; |
65 | iState = 1; | 65 | iState = 1; |
66 | break; | 66 | break; |
67 | 67 | ||
68 | case 1: // The path requested | 68 | case 1: // The path requested |
69 | SDB( 1 ); | 69 | SDB( 1 ); |
70 | sPath = sToken; | 70 | sPath = sToken; |
71 | iState = 2; | 71 | iState = 2; |
72 | break; | 72 | break; |
73 | 73 | ||
74 | case 2: // The protocol name and version | 74 | case 2: // The protocol name and version |
75 | SDB( 2 ); | 75 | SDB( 2 ); |
76 | if( strncmp( sToken.getStr(), "HTTP/", 5 ) ) | 76 | if( strncmp( sToken.getStr(), "HTTP/", 5 ) ) |
77 | { | 77 | { |
78 | pClient->disconnect(); | 78 | pClient->disconnect(); |
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | else | 81 | else |
82 | { | 82 | { |
83 | char *s, *s2; | 83 | char *s, *s2; |
84 | s = sToken.getStr()+5; | 84 | s = sToken.getStr()+5; |
85 | iMajor = strtol( s, &s2, 10 ); | 85 | iMajor = strtol( s, &s2, 10 ); |
86 | iMinor = strtol( s2+1, NULL, 10 ); | 86 | iMinor = strtol( s2+1, NULL, 10 ); |
87 | iState = 3; | 87 | iState = 3; |
88 | } | 88 | } |
89 | break; | 89 | break; |
90 | 90 | ||
91 | case 3: // End of initial header, now comes mime-style blocks. | 91 | case 3: // End of initial header, now comes mime-style blocks. |
92 | SDB( 3 ); | 92 | SDB( 3 ); |
93 | if( tt == ttNewline ) | 93 | if( tt == ttNewline ) |
94 | { | 94 | { |
95 | iState = 10; | 95 | iState = 10; |
96 | } | 96 | } |
97 | else if( tt == ttDoubleNewline ) | 97 | else if( tt == ttDoubleNewline ) |
98 | { | 98 | { |
99 | earlyResponse(); | 99 | earlyResponse(); |
100 | } | 100 | } |
101 | else | 101 | else |
102 | { | 102 | { |
103 | pClient->disconnect(); | 103 | pClient->disconnect(); |
104 | return; | 104 | return; |
105 | } | 105 | } |
106 | break; | 106 | break; |
107 | 107 | ||
108 | case 10: // HTTP-Message (skipped for now...) | 108 | case 10: // HTTP-Message (skipped for now...) |
109 | SDB( 10 ); | 109 | SDB( 10 ); |
110 | if( tt == ttString ) | 110 | if( tt == ttString ) |
111 | { | 111 | { |
112 | iState = 11; | 112 | iState = 11; |
113 | } | 113 | } |
114 | else | 114 | else |
115 | { | 115 | { |
116 | pClient->disconnect(); | 116 | pClient->disconnect(); |
117 | } | 117 | } |
118 | break; | 118 | break; |
119 | 119 | ||
120 | case 11: // Should be a colon... | 120 | case 11: // Should be a colon... |
121 | SDB( 11 ); | 121 | SDB( 11 ); |
122 | if( tt == ttSeperator && sToken == ":" ) | 122 | if( tt == ttSeperator && sToken == ":" ) |
123 | { | 123 | { |
124 | iState = 12; | 124 | iState = 12; |
125 | } | 125 | } |
126 | else | 126 | else |
127 | { | 127 | { |
128 | pClient->disconnect(); | 128 | pClient->disconnect(); |
129 | } | 129 | } |
130 | break; | 130 | break; |
131 | 131 | ||
132 | case 12: | 132 | case 12: |
133 | SDB( 12 ); | 133 | SDB( 12 ); |
134 | if( tt == ttNewline ) | 134 | if( tt == ttNewline ) |
135 | { | 135 | { |
136 | iState = 10; | 136 | iState = 10; |
137 | } | 137 | } |
138 | if( tt == ttDoubleNewline ) | 138 | if( tt == ttDoubleNewline ) |
139 | { | 139 | { |
140 | earlyResponse(); | 140 | earlyResponse(); |
141 | } | 141 | } |
142 | break; | 142 | break; |
143 | 143 | ||
144 | case 20: | 144 | case 20: |
145 | SDB( 20 ); | 145 | SDB( 20 ); |
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | Bu::ProtocolHttp::TokenType Bu::ProtocolHttp::getToken( Bu::String &line ) | 151 | Bu::ProtocolHttp::TokenType Bu::ProtocolHttp::getToken( Bu::String &line ) |
152 | { | 152 | { |
153 | char s; | 153 | char s; |
154 | int jmax = pClient->getInputSize(); | 154 | int jmax = pClient->getInputSize(); |
155 | bool bNonWS = false; | 155 | bool bNonWS = false; |
156 | 156 | ||
157 | for( int j = 0; j < jmax; j++ ) | 157 | for( int j = 0; j < jmax; j++ ) |
158 | { | 158 | { |
159 | pClient->peek( &s, 1, j ); | 159 | pClient->peek( &s, 1, j ); |
160 | if( iState > 2 && isSeperator( s ) ) | 160 | if( iState > 2 && isSeperator( s ) ) |
161 | { | 161 | { |
162 | if( j == 0 ) | 162 | if( j == 0 ) |
163 | { | 163 | { |
164 | line += s; | 164 | line += s; |
165 | pClient->seek( 1 ); | 165 | pClient->seek( 1 ); |
166 | return ttSeperator; | 166 | return ttSeperator; |
167 | } | 167 | } |
168 | else | 168 | else |
169 | { | 169 | { |
170 | pClient->seek( j ); | 170 | pClient->seek( j ); |
171 | return ttString; | 171 | return ttString; |
172 | } | 172 | } |
173 | } | 173 | } |
174 | else if( isWS( s ) ) | 174 | else if( isWS( s ) ) |
175 | { | 175 | { |
176 | if( bNonWS ) | 176 | if( bNonWS ) |
177 | { | 177 | { |
178 | pClient->seek( j ); | 178 | pClient->seek( j ); |
179 | return ttString; | 179 | return ttString; |
180 | } | 180 | } |
181 | } | 181 | } |
182 | else if( s == CR ) | 182 | else if( s == CR ) |
183 | { | 183 | { |
184 | if( pClient->getInputSize() < 4 ) | 184 | if( pClient->getInputSize() < 4 ) |
185 | return ttOutOfData; | 185 | return ttOutOfData; |
186 | 186 | ||
187 | char ss[3]; | 187 | char ss[3]; |
188 | pClient->peek( ss, 3, j+1 ); | 188 | pClient->peek( ss, 3, j+1 ); |
189 | if( ss[0] == LF && ss[1] != ' ' && ss[1] != '\t' ) | 189 | if( ss[0] == LF && ss[1] != ' ' && ss[1] != '\t' ) |
190 | { | 190 | { |
191 | if( bNonWS ) | 191 | if( bNonWS ) |
192 | { | 192 | { |
193 | pClient->seek( j ); | 193 | pClient->seek( j ); |
194 | return ttString; | 194 | return ttString; |
195 | } | 195 | } |
196 | else if( ss[1] == CR && ss[2] == LF ) | 196 | else if( ss[1] == CR && ss[2] == LF ) |
197 | { | 197 | { |
198 | pClient->seek( 4 ); | 198 | pClient->seek( 4 ); |
199 | return ttDoubleNewline; | 199 | return ttDoubleNewline; |
200 | } | 200 | } |
201 | else | 201 | else |
202 | { | 202 | { |
203 | pClient->seek( 2 ); | 203 | pClient->seek( 2 ); |
204 | return ttNewline; | 204 | return ttNewline; |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | j += 2; | 208 | j += 2; |
209 | if( bNonWS ) | 209 | if( bNonWS ) |
210 | { | 210 | { |
211 | pClient->seek( j ); | 211 | pClient->seek( j ); |
212 | return ttString; | 212 | return ttString; |
213 | } | 213 | } |
214 | } | 214 | } |
215 | else | 215 | else |
216 | { | 216 | { |
217 | line += s; | 217 | line += s; |
218 | bNonWS = true; | 218 | bNonWS = true; |
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | return ttOutOfData; | 222 | return ttOutOfData; |
223 | } | 223 | } |
224 | 224 | ||
225 | bool Bu::ProtocolHttp::isWS( char buf ) | 225 | bool Bu::ProtocolHttp::isWS( char buf ) |
226 | { | 226 | { |
227 | return (buf == ' ' || buf == '\t'); | 227 | return (buf == ' ' || buf == '\t'); |
228 | } | 228 | } |
229 | 229 | ||
230 | bool Bu::ProtocolHttp::isSeperator( char buf ) | 230 | bool Bu::ProtocolHttp::isSeperator( char buf ) |
231 | { | 231 | { |
232 | return (buf == '(' || buf == ')' || buf == '<' || buf == '>' || | 232 | return (buf == '(' || buf == ')' || buf == '<' || buf == '>' || |
233 | buf == '@' || buf == ',' || buf == ';' || buf == ':' || | 233 | buf == '@' || buf == ',' || buf == ';' || buf == ':' || |
234 | buf == '\\' || buf == '\"' || buf == '/' || buf == '[' || | 234 | buf == '\\' || buf == '\"' || buf == '/' || buf == '[' || |
235 | buf == ']' || buf == '?' || buf == '=' || buf == '{' || | 235 | buf == ']' || buf == '?' || buf == '=' || buf == '{' || |
236 | buf == '}' ); | 236 | buf == '}' ); |
237 | } | 237 | } |
diff --git a/src/stable/protocolhttp.h b/src/stable/protocolhttp.h index 87dc49b..51ca58c 100644 --- a/src/stable/protocolhttp.h +++ b/src/stable/protocolhttp.h | |||
@@ -18,89 +18,89 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | /** | 21 | /** |
22 | * An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text | 22 | * An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text |
23 | * Transfer Protocol, and that the Protocol part is redundant, but in this | 23 | * Transfer Protocol, and that the Protocol part is redundant, but in this |
24 | * case the word Protocol is refering to the Libbu++ construct Bu::Protocol, | 24 | * case the word Protocol is refering to the Libbu++ construct Bu::Protocol, |
25 | * and not a means of encoding conversations. Anyway, this class represents | 25 | * and not a means of encoding conversations. Anyway, this class represents |
26 | * a general HTTP server processor. Every time a request comes in it calls | 26 | * a general HTTP server processor. Every time a request comes in it calls |
27 | * the onRequest function in a subclass with the method and URI that were | 27 | * the onRequest function in a subclass with the method and URI that were |
28 | * requested. The sub-class can then do whatever it needs to to send back | 28 | * requested. The sub-class can then do whatever it needs to to send back |
29 | * a response. | 29 | * a response. |
30 | *@ingroup Serving | 30 | *@ingroup Serving |
31 | */ | 31 | */ |
32 | class ProtocolHttp : public Protocol | 32 | class ProtocolHttp : public Protocol |
33 | { | 33 | { |
34 | public: /* Types */ | 34 | public: /* Types */ |
35 | typedef Bu::List<Bu::String> TokenList; | 35 | typedef Bu::List<Bu::String> TokenList; |
36 | 36 | ||
37 | public: /* Interface */ | 37 | public: /* Interface */ |
38 | ProtocolHttp(); | 38 | ProtocolHttp(); |
39 | virtual ~ProtocolHttp(); | 39 | virtual ~ProtocolHttp(); |
40 | 40 | ||
41 | virtual void onNewConnection( Bu::Client *pClient ); | 41 | virtual void onNewConnection( Bu::Client *pClient ); |
42 | virtual void onNewData( Bu::Client *pClient ); | 42 | virtual void onNewData( Bu::Client *pClient ); |
43 | 43 | ||
44 | virtual void onRequest( | 44 | virtual void onRequest( |
45 | const Bu::String &sMethod, const Bu::String &sPath )=0; | 45 | const Bu::String &sMethod, const Bu::String &sPath )=0; |
46 | 46 | ||
47 | class Response | 47 | class Response |
48 | { | 48 | { |
49 | friend class Bu::ProtocolHttp; | 49 | friend class Bu::ProtocolHttp; |
50 | public: | 50 | public: |
51 | Response( int iCode ); | 51 | Response( int iCode ); |
52 | Response( int iCode, const Bu::String &sReason ); | 52 | Response( int iCode, const Bu::String &sReason ); |
53 | virtual ~Response(); | 53 | virtual ~Response(); |
54 | 54 | ||
55 | void setHeader( const Bu::String &sKey, const Bu::String &sVal ); | 55 | void setHeader( const Bu::String &sKey, const Bu::String &sVal ); |
56 | void setContent( const Bu::String &sCont ); | 56 | void setContent( const Bu::String &sCont ); |
57 | 57 | ||
58 | private: | 58 | private: |
59 | int iCode; | 59 | int iCode; |
60 | Bu::String sReason; | 60 | Bu::String sReason; |
61 | typedef Bu::Hash<Bu::String,Bu::String> StringHash; | 61 | typedef Bu::Hash<Bu::String,Bu::String> StringHash; |
62 | StringHash hHeaders; | 62 | StringHash hHeaders; |
63 | Bu::String sContent; | 63 | Bu::String sContent; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | void sendResponse( const Response &rRes ); | 66 | void sendResponse( const Response &rRes ); |
67 | 67 | ||
68 | private: | 68 | private: |
69 | enum TokenType | 69 | enum TokenType |
70 | { | 70 | { |
71 | ttOutOfData, | 71 | ttOutOfData, |
72 | ttString, | 72 | ttString, |
73 | ttNewline, | 73 | ttNewline, |
74 | ttDoubleNewline, | 74 | ttDoubleNewline, |
75 | ttSeperator | 75 | ttSeperator |
76 | }; | 76 | }; |
77 | /** | 77 | /** |
78 | * Read an HTTP line, this is up to the first CRLF that isn't followed | 78 | * Read an HTTP line, this is up to the first CRLF that isn't followed |
79 | * by a continuation character, converting it to one line as it reads. | 79 | * by a continuation character, converting it to one line as it reads. |
80 | *@param line All data read will be appended to line, even if no | 80 | *@param line All data read will be appended to line, even if no |
81 | * end-of-line is read. | 81 | * end-of-line is read. |
82 | *@returns True if an end-of-line is read and the line should be | 82 | *@returns True if an end-of-line is read and the line should be |
83 | * processed, false if the end-of-line has not been reached, and more | 83 | * processed, false if the end-of-line has not been reached, and more |
84 | * data needs to be read before this operation can continue. | 84 | * data needs to be read before this operation can continue. |
85 | */ | 85 | */ |
86 | TokenType getToken( Bu::String &line ); | 86 | TokenType getToken( Bu::String &line ); |
87 | bool isWS( char buf ); | 87 | bool isWS( char buf ); |
88 | bool isSeperator( char buf ); | 88 | bool isSeperator( char buf ); |
89 | 89 | ||
90 | void earlyResponse(); | 90 | void earlyResponse(); |
91 | void lateResponse(); | 91 | void lateResponse(); |
92 | 92 | ||
93 | private: /* state */ | 93 | private: /* state */ |
94 | Bu::Client *pClient; | 94 | Bu::Client *pClient; |
95 | TokenList lTokens; | 95 | TokenList lTokens; |
96 | 96 | ||
97 | int iState; | 97 | int iState; |
98 | 98 | ||
99 | Bu::String sMethod; | 99 | Bu::String sMethod; |
100 | Bu::String sPath; | 100 | Bu::String sPath; |
101 | int iMajor; | 101 | int iMajor; |
102 | int iMinor; | 102 | int iMinor; |
103 | }; | 103 | }; |
104 | } | 104 | } |
105 | 105 | ||
106 | #endif | 106 | #endif |
diff --git a/src/stable/protocoltelnet.cpp b/src/stable/protocoltelnet.cpp index aed23be..d5465d1 100644 --- a/src/stable/protocoltelnet.cpp +++ b/src/stable/protocoltelnet.cpp | |||
@@ -11,53 +11,53 @@ | |||
11 | /* We apparently at least want defs for the lower 13, not sure we care about | 11 | /* We apparently at least want defs for the lower 13, not sure we care about |
12 | * the rest of the chars, maybe escape. | 12 | * the rest of the chars, maybe escape. |
13 | */ | 13 | */ |
14 | #define CH_NUL '\x00' /* NUL */ | 14 | #define CH_NUL '\x00' /* NUL */ |
15 | #define CH_SOH '\x01' /* Start Of Heading */ | 15 | #define CH_SOH '\x01' /* Start Of Heading */ |
16 | #define CH_STX '\x02' /* Start of Text */ | 16 | #define CH_STX '\x02' /* Start of Text */ |
17 | #define CH_ETX '\x03' /* End of Text */ | 17 | #define CH_ETX '\x03' /* End of Text */ |
18 | #define CH_EOT '\x04' /* End of transmission */ | 18 | #define CH_EOT '\x04' /* End of transmission */ |
19 | #define CH_ENQ '\x05' /* Enquiery */ | 19 | #define CH_ENQ '\x05' /* Enquiery */ |
20 | #define CH_ACK '\x06' /* Acknowledge */ | 20 | #define CH_ACK '\x06' /* Acknowledge */ |
21 | #define CH_BEL '\x07' /* Bell */ | 21 | #define CH_BEL '\x07' /* Bell */ |
22 | #define CH_BS '\x08' /* Backspace */ | 22 | #define CH_BS '\x08' /* Backspace */ |
23 | #define CH_TAB '\x09' /* Horizontal Tab */ | 23 | #define CH_TAB '\x09' /* Horizontal Tab */ |
24 | #define CH_LF '\x0A' /* NL Line feed, new line */ | 24 | #define CH_LF '\x0A' /* NL Line feed, new line */ |
25 | #define CH_VT '\x0B' /* Vertical Tab */ | 25 | #define CH_VT '\x0B' /* Vertical Tab */ |
26 | #define CH_FF '\x0C' /* Form feed, new page */ | 26 | #define CH_FF '\x0C' /* Form feed, new page */ |
27 | #define CH_CR '\x0D' /* Carriage return */ | 27 | #define CH_CR '\x0D' /* Carriage return */ |
28 | #define CH_ESC '\x1B' /* Escape */ | 28 | #define CH_ESC '\x1B' /* Escape */ |
29 | #define CH_DEL '\x7F' /* Delete */ | 29 | #define CH_DEL '\x7F' /* Delete */ |
30 | 30 | ||
31 | #define CODE_SE '\xf0' /* End of subnegotiation params. */ | 31 | #define CODE_SE '\xf0' /* End of subnegotiation params. */ |
32 | #define CODE_NOP '\xf1' /* No operation (keep-alive). */ | 32 | #define CODE_NOP '\xf1' /* No operation (keep-alive). */ |
33 | #define CODE_DM '\xf2' /* Datastream side of a Synch. */ | 33 | #define CODE_DM '\xf2' /* Datastream side of a Synch. */ |
34 | #define CODE_BRK '\xf3' /* Break character. */ | 34 | #define CODE_BRK '\xf3' /* Break character. */ |
35 | #define CODE_IP '\xf4' /* Interrupt Process character. */ | 35 | #define CODE_IP '\xf4' /* Interrupt Process character. */ |
36 | #define CODE_AO '\xf5' /* Abort Output character. */ | 36 | #define CODE_AO '\xf5' /* Abort Output character. */ |
37 | #define CODE_AYT '\xf6' /* Are You There? character. */ | 37 | #define CODE_AYT '\xf6' /* Are You There? character. */ |
38 | #define CODE_EC '\xf7' /* Erase Character character. */ | 38 | #define CODE_EC '\xf7' /* Erase Character character. */ |
39 | #define CODE_EL '\xf8' /* Erase Line character. */ | 39 | #define CODE_EL '\xf8' /* Erase Line character. */ |
40 | #define CODE_GA '\xf9' /* Go Ahead signal. */ | 40 | #define CODE_GA '\xf9' /* Go Ahead signal. */ |
41 | #define CODE_SB '\xfa' /* Begin subnegotiation options. */ | 41 | #define CODE_SB '\xfa' /* Begin subnegotiation options. */ |
42 | #define CODE_WILL '\xfb' /* Desire to do something. */ | 42 | #define CODE_WILL '\xfb' /* Desire to do something. */ |
43 | #define CODE_WONT '\xfc' /* Refuse to perform. */ | 43 | #define CODE_WONT '\xfc' /* Refuse to perform. */ |
44 | #define CODE_DO '\xfd' /* Request option. */ | 44 | #define CODE_DO '\xfd' /* Request option. */ |
45 | #define CODE_DONT '\xfe' /* Demand a stop. */ | 45 | #define CODE_DONT '\xfe' /* Demand a stop. */ |
46 | 46 | ||
47 | #define CODE_IAC '\xff' /* Interpret-As-Command. */ | 47 | #define CODE_IAC '\xff' /* Interpret-As-Command. */ |
48 | 48 | ||
49 | #define OPT_BINARY '\x00' /* Binary mode (file transfers?). */ | 49 | #define OPT_BINARY '\x00' /* Binary mode (file transfers?). */ |
50 | #define OPT_ECHO '\x01' /* (local) Echo mode. */ | 50 | #define OPT_ECHO '\x01' /* (local) Echo mode. */ |
51 | #define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */ | 51 | #define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */ |
52 | #define OPT_STATUS '\x05' /* Allow status messages. */ | 52 | #define OPT_STATUS '\x05' /* Allow status messages. */ |
53 | #define OPT_TIMING '\x06' /* Place a timing mark in the code. */ | 53 | #define OPT_TIMING '\x06' /* Place a timing mark in the code. */ |
54 | #define OPT_EXASCII '\x11' /* Extended ASCII. */ | 54 | #define OPT_EXASCII '\x11' /* Extended ASCII. */ |
55 | #define OPT_LOGOUT '\x12' /* Logout. */ | 55 | #define OPT_LOGOUT '\x12' /* Logout. */ |
56 | #define OPT_TTYPE '\x18' /* Terminal Type. */ | 56 | #define OPT_TTYPE '\x18' /* Terminal Type. */ |
57 | #define OPT_NAWS '\x1f' /* Negotiate about window size. */ | 57 | #define OPT_NAWS '\x1f' /* Negotiate about window size. */ |
58 | #define OPT_TSPEED '\x20' /* Terminal Speed. */ | 58 | #define OPT_TSPEED '\x20' /* Terminal Speed. */ |
59 | #define OPT_NEWENV '\x27' /* New Environment Option. */ | 59 | #define OPT_NEWENV '\x27' /* New Environment Option. */ |
60 | #define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */ | 60 | #define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */ |
61 | 61 | ||
62 | #ifndef __TELNET_DEBUG | 62 | #ifndef __TELNET_DEBUG |
63 | # define printCode( a ) (void)0 | 63 | # define printCode( a ) (void)0 |
@@ -65,12 +65,12 @@ | |||
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | Bu::ProtocolTelnet::ProtocolTelnet() : | 67 | Bu::ProtocolTelnet::ProtocolTelnet() : |
68 | oBinary( *this, OPT_BINARY ), | 68 | oBinary( *this, OPT_BINARY ), |
69 | oEcho( *this, OPT_ECHO ), | 69 | oEcho( *this, OPT_ECHO ), |
70 | oNAWS( *this, OPT_NAWS ), | 70 | oNAWS( *this, OPT_NAWS ), |
71 | oSuppressGA(*this, OPT_SUPGA ), | 71 | oSuppressGA(*this, OPT_SUPGA ), |
72 | bCanonical( true ), | 72 | bCanonical( true ), |
73 | bSubOpt( false ) | 73 | bSubOpt( false ) |
74 | { | 74 | { |
75 | } | 75 | } |
76 | 76 | ||
@@ -80,439 +80,439 @@ Bu::ProtocolTelnet::~ProtocolTelnet() | |||
80 | 80 | ||
81 | void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) | 81 | void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) |
82 | { | 82 | { |
83 | this->pClient = pClient; | 83 | this->pClient = pClient; |
84 | } | 84 | } |
85 | 85 | ||
86 | void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) | 86 | void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) |
87 | { | 87 | { |
88 | char bc; | 88 | char bc; |
89 | int iLeft; | 89 | int iLeft; |
90 | while( (iLeft = pClient->getInputSize()) ) | 90 | while( (iLeft = pClient->getInputSize()) ) |
91 | { | 91 | { |
92 | if( bSubOpt ) | 92 | if( bSubOpt ) |
93 | { | 93 | { |
94 | pClient->peek( &bc, 1 ); | 94 | pClient->peek( &bc, 1 ); |
95 | if( bc == CODE_IAC ) | 95 | if( bc == CODE_IAC ) |
96 | { | 96 | { |
97 | if( iLeft <= 1 ) return; | 97 | if( iLeft <= 1 ) return; |
98 | char bc2; | 98 | char bc2; |
99 | printCode( CODE_IAC ); | 99 | printCode( CODE_IAC ); |
100 | pClient->peek( &bc2, 1, 1 ); | 100 | pClient->peek( &bc2, 1, 1 ); |
101 | printCode( bc2 ); | 101 | printCode( bc2 ); |
102 | if( bc2 == CODE_SE ) | 102 | if( bc2 == CODE_SE ) |
103 | { | 103 | { |
104 | bSubOpt = false; | 104 | bSubOpt = false; |
105 | onSubOpt(); | 105 | onSubOpt(); |
106 | } | 106 | } |
107 | else if( bc2 == CODE_IAC ) | 107 | else if( bc2 == CODE_IAC ) |
108 | { | 108 | { |
109 | sSubBuf += CODE_IAC; | 109 | sSubBuf += CODE_IAC; |
110 | } | 110 | } |
111 | else | 111 | else |
112 | { | 112 | { |
113 | // Error of some sort. | 113 | // Error of some sort. |
114 | } | 114 | } |
115 | pClient->seek( 1 ); | 115 | pClient->seek( 1 ); |
116 | } | 116 | } |
117 | else | 117 | else |
118 | { | 118 | { |
119 | sSubBuf += bc; | 119 | sSubBuf += bc; |
120 | } | 120 | } |
121 | pClient->seek( 1 ); | 121 | pClient->seek( 1 ); |
122 | } | 122 | } |
123 | else | 123 | else |
124 | { | 124 | { |
125 | pClient->peek( &bc, 1 ); | 125 | pClient->peek( &bc, 1 ); |
126 | if( bc == CODE_IAC ) | 126 | if( bc == CODE_IAC ) |
127 | { | 127 | { |
128 | if( iLeft <= 1 ) return; | 128 | if( iLeft <= 1 ) return; |
129 | char bc2; | 129 | char bc2; |
130 | pClient->peek( &bc2, 1, 1 ); | 130 | pClient->peek( &bc2, 1, 1 ); |
131 | printCode( bc ); | 131 | printCode( bc ); |
132 | printCode( bc2 ); | 132 | printCode( bc2 ); |
133 | 133 | ||
134 | switch( bc2 ) | 134 | switch( bc2 ) |
135 | { | 135 | { |
136 | case CODE_WILL: | 136 | case CODE_WILL: |
137 | if( iLeft <= 2 ) return; | 137 | if( iLeft <= 2 ) return; |
138 | { | 138 | { |
139 | char bc3; | 139 | char bc3; |
140 | pClient->peek( &bc3, 1, 2 ); | 140 | pClient->peek( &bc3, 1, 2 ); |
141 | pClient->seek( 1 ); | 141 | pClient->seek( 1 ); |
142 | printOpt( bc3 ); | 142 | printOpt( bc3 ); |
143 | onWill( bc3 ); | 143 | onWill( bc3 ); |
144 | } | 144 | } |
145 | break; | 145 | break; |
146 | 146 | ||
147 | case CODE_WONT: | 147 | case CODE_WONT: |
148 | if( iLeft <= 2 ) return; | 148 | if( iLeft <= 2 ) return; |
149 | { | 149 | { |
150 | char bc3; | 150 | char bc3; |
151 | pClient->peek( &bc3, 1, 2 ); | 151 | pClient->peek( &bc3, 1, 2 ); |
152 | pClient->seek( 1 ); | 152 | pClient->seek( 1 ); |
153 | printOpt( bc3 ); | 153 | printOpt( bc3 ); |
154 | onWont( bc3 ); | 154 | onWont( bc3 ); |
155 | } | 155 | } |
156 | break; | 156 | break; |
157 | 157 | ||
158 | case CODE_DO: | 158 | case CODE_DO: |
159 | if( iLeft <= 2 ) return; | 159 | if( iLeft <= 2 ) return; |
160 | { | 160 | { |
161 | char bc3; | 161 | char bc3; |
162 | pClient->peek( &bc3, 1, 2 ); | 162 | pClient->peek( &bc3, 1, 2 ); |
163 | pClient->seek( 1 ); | 163 | pClient->seek( 1 ); |
164 | printOpt( bc3 ); | 164 | printOpt( bc3 ); |
165 | onDo( bc3 ); | 165 | onDo( bc3 ); |
166 | } | 166 | } |
167 | break; | 167 | break; |
168 | 168 | ||
169 | case CODE_DONT: | 169 | case CODE_DONT: |
170 | if( iLeft <= 2 ) return; | 170 | if( iLeft <= 2 ) return; |
171 | { | 171 | { |
172 | char bc3; | 172 | char bc3; |
173 | pClient->peek( &bc3, 1, 2 ); | 173 | pClient->peek( &bc3, 1, 2 ); |
174 | pClient->seek( 1 ); | 174 | pClient->seek( 1 ); |
175 | printOpt( bc3 ); | 175 | printOpt( bc3 ); |
176 | onDont( bc3 ); | 176 | onDont( bc3 ); |
177 | } | 177 | } |
178 | break; | 178 | break; |
179 | 179 | ||
180 | case CODE_SB: | 180 | case CODE_SB: |
181 | if( iLeft <= 2 ) return; | 181 | if( iLeft <= 2 ) return; |
182 | { | 182 | { |
183 | pClient->peek( &cSubOpt, 1, 2 ); | 183 | pClient->peek( &cSubOpt, 1, 2 ); |
184 | pClient->seek( 1 ); | 184 | pClient->seek( 1 ); |
185 | printOpt( cSubOpt ); | 185 | printOpt( cSubOpt ); |
186 | bSubOpt = true; | 186 | bSubOpt = true; |
187 | } | 187 | } |
188 | break; | 188 | break; |
189 | 189 | ||
190 | case CODE_IAC: | 190 | case CODE_IAC: |
191 | sDataBuf += CODE_IAC; | 191 | sDataBuf += CODE_IAC; |
192 | printCode( CODE_IAC ); | 192 | printCode( CODE_IAC ); |
193 | break; | 193 | break; |
194 | } | 194 | } |
195 | pClient->seek( 1 ); | 195 | pClient->seek( 1 ); |
196 | #ifdef __TELNET_DEBUG | 196 | #ifdef __TELNET_DEBUG |
197 | printf("\n"); | 197 | printf("\n"); |
198 | #endif | 198 | #endif |
199 | } | 199 | } |
200 | else if( bc == CODE_SB ) | 200 | else if( bc == CODE_SB ) |
201 | { | 201 | { |
202 | } | 202 | } |
203 | else | 203 | else |
204 | { | 204 | { |
205 | // This is where control code handling goes | 205 | // This is where control code handling goes |
206 | // Also, possibly, character code conversion, although I'm not | 206 | // Also, possibly, character code conversion, although I'm not |
207 | // sure that really matters anymore, go ASCII/UTF-8 | 207 | // sure that really matters anymore, go ASCII/UTF-8 |
208 | if( bCanonical ) | 208 | if( bCanonical ) |
209 | { | 209 | { |
210 | if( bc < 0x20 || bc >= CH_DEL ) | 210 | if( bc < 0x20 || bc >= CH_DEL ) |
211 | { | 211 | { |
212 | if( bc == CH_CR ) | 212 | if( bc == CH_CR ) |
213 | { | 213 | { |
214 | if( iLeft <= 1 ) return; | 214 | if( iLeft <= 1 ) return; |
215 | char bc2; | 215 | char bc2; |
216 | pClient->peek( &bc2, 1, 1 ); | 216 | pClient->peek( &bc2, 1, 1 ); |
217 | if( bc2 == CH_NUL || bc2 == CH_LF ) | 217 | if( bc2 == CH_NUL || bc2 == CH_LF ) |
218 | { | 218 | { |
219 | onCtlChar( bc ); | 219 | onCtlChar( bc ); |
220 | gotLine( sDataBuf ); | 220 | gotLine( sDataBuf ); |
221 | sDataBuf.clear(); | 221 | sDataBuf.clear(); |
222 | } | 222 | } |
223 | pClient->seek( 1 ); | 223 | pClient->seek( 1 ); |
224 | } | 224 | } |
225 | else | 225 | else |
226 | { | 226 | { |
227 | onCtlChar( bc ); | 227 | onCtlChar( bc ); |
228 | } | 228 | } |
229 | } | 229 | } |
230 | else | 230 | else |
231 | { | 231 | { |
232 | sDataBuf += bc; | 232 | sDataBuf += bc; |
233 | if( oEcho.isLocalSet() ) | 233 | if( oEcho.isLocalSet() ) |
234 | { | 234 | { |
235 | pClient->write( &bc, 1 ); | 235 | pClient->write( &bc, 1 ); |
236 | #ifdef __TELNET_DEBUG | 236 | #ifdef __TELNET_DEBUG |
237 | printf("%c", bc ); | 237 | printf("%c", bc ); |
238 | fflush( stdout ); | 238 | fflush( stdout ); |
239 | #endif | 239 | #endif |
240 | } | 240 | } |
241 | } | 241 | } |
242 | } | 242 | } |
243 | else | 243 | else |
244 | { | 244 | { |
245 | sDataBuf += bc; | 245 | sDataBuf += bc; |
246 | if( oEcho.isLocalSet() ) | 246 | if( oEcho.isLocalSet() ) |
247 | { | 247 | { |
248 | pClient->write( &bc, 1 ); | 248 | pClient->write( &bc, 1 ); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | } | 251 | } |
252 | pClient->seek( 1 ); | 252 | pClient->seek( 1 ); |
253 | } | 253 | } |
254 | } | 254 | } |
255 | 255 | ||
256 | // It's true, this code will not be executed if we only have half of an | 256 | // It's true, this code will not be executed if we only have half of an |
257 | // IAC code or multibyte escape sequence or something, but then again, it | 257 | // IAC code or multibyte escape sequence or something, but then again, it |
258 | // shouldn't be called then, and really, shouldn't be, it'll be called soon | 258 | // shouldn't be called then, and really, shouldn't be, it'll be called soon |
259 | // enough, when we get the rest of that code. | 259 | // enough, when we get the rest of that code. |
260 | if( !bCanonical ) | 260 | if( !bCanonical ) |
261 | { | 261 | { |
262 | gotData( sDataBuf ); | 262 | gotData( sDataBuf ); |
263 | } | 263 | } |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::ProtocolTelnet::setCanonical( bool bCon ) | 266 | void Bu::ProtocolTelnet::setCanonical( bool bCon ) |
267 | { | 267 | { |
268 | bCanonical = bCon; | 268 | bCanonical = bCon; |
269 | } | 269 | } |
270 | 270 | ||
271 | bool Bu::ProtocolTelnet::isCanonical() | 271 | bool Bu::ProtocolTelnet::isCanonical() |
272 | { | 272 | { |
273 | return bCanonical; | 273 | return bCanonical; |
274 | } | 274 | } |
275 | 275 | ||
276 | void Bu::ProtocolTelnet::write( const Bu::String &sData ) | 276 | void Bu::ProtocolTelnet::write( const Bu::String &sData ) |
277 | { | 277 | { |
278 | write( sData.getStr(), sData.getSize() ); | 278 | write( sData.getStr(), sData.getSize() ); |
279 | } | 279 | } |
280 | 280 | ||
281 | void Bu::ProtocolTelnet::write( const char *pData, int iSize ) | 281 | void Bu::ProtocolTelnet::write( const char *pData, int iSize ) |
282 | { | 282 | { |
283 | int iLast = 0, j; | 283 | int iLast = 0, j; |
284 | for( j = iLast; j < iSize; j++ ) | 284 | for( j = iLast; j < iSize; j++ ) |
285 | { | 285 | { |
286 | if( pData[j] == '\n' ) | 286 | if( pData[j] == '\n' ) |
287 | { | 287 | { |
288 | if( j+1 >= iSize || | 288 | if( j+1 >= iSize || |
289 | (pData[j+1] != '\r' && pData[j+1] != '\0') ) | 289 | (pData[j+1] != '\r' && pData[j+1] != '\0') ) |
290 | { | 290 | { |
291 | pClient->write( pData+iLast, j-iLast ); | 291 | pClient->write( pData+iLast, j-iLast ); |
292 | pClient->write( "\n\r", 2 ); | 292 | pClient->write( "\n\r", 2 ); |
293 | iLast = j+1; | 293 | iLast = j+1; |
294 | } | 294 | } |
295 | else | 295 | else |
296 | { | 296 | { |
297 | j++; | 297 | j++; |
298 | } | 298 | } |
299 | } | 299 | } |
300 | } | 300 | } |
301 | if( j > iLast ) | 301 | if( j > iLast ) |
302 | { | 302 | { |
303 | pClient->write( pData+iLast, iSize-iLast ); | 303 | pClient->write( pData+iLast, iSize-iLast ); |
304 | } | 304 | } |
305 | //pClient->write( pData, iSize ); | 305 | //pClient->write( pData, iSize ); |
306 | } | 306 | } |
307 | 307 | ||
308 | void Bu::ProtocolTelnet::write( char cData ) | 308 | void Bu::ProtocolTelnet::write( char cData ) |
309 | { | 309 | { |
310 | write( &cData, 1 ); | 310 | write( &cData, 1 ); |
311 | } | 311 | } |
312 | 312 | ||
313 | void Bu::ProtocolTelnet::onWill( char cCode ) | 313 | void Bu::ProtocolTelnet::onWill( char cCode ) |
314 | { | 314 | { |
315 | try | 315 | try |
316 | { | 316 | { |
317 | Option *pOpt = hOpts[cCode]; | 317 | Option *pOpt = hOpts[cCode]; |
318 | if( pOpt->isRemoteEnabled() ) | 318 | if( pOpt->isRemoteEnabled() ) |
319 | { | 319 | { |
320 | pOpt->fOpts |= Option::fRemoteIs; | 320 | pOpt->fOpts |= Option::fRemoteIs; |
321 | char buf[3] = { CODE_IAC, CODE_DO, cCode }; | 321 | char buf[3] = { CODE_IAC, CODE_DO, cCode }; |
322 | pClient->write( buf, 3 ); | 322 | pClient->write( buf, 3 ); |
323 | } | 323 | } |
324 | else | 324 | else |
325 | { | 325 | { |
326 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 326 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
327 | pClient->write( buf, 3 ); | 327 | pClient->write( buf, 3 ); |
328 | } | 328 | } |
329 | 329 | ||
330 | } | 330 | } |
331 | catch( Bu::HashException &e ) | 331 | catch( Bu::HashException &e ) |
332 | { | 332 | { |
333 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 333 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
334 | pClient->write( buf, 3 ); | 334 | pClient->write( buf, 3 ); |
335 | } | 335 | } |
336 | } | 336 | } |
337 | 337 | ||
338 | void Bu::ProtocolTelnet::onWont( char cCode ) | 338 | void Bu::ProtocolTelnet::onWont( char cCode ) |
339 | { | 339 | { |
340 | try | 340 | try |
341 | { | 341 | { |
342 | Option *pOpt = hOpts[cCode]; | 342 | Option *pOpt = hOpts[cCode]; |
343 | 343 | ||
344 | pOpt->fOpts &= ~Option::fRemoteIs; | 344 | pOpt->fOpts &= ~Option::fRemoteIs; |
345 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 345 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
346 | pClient->write( buf, 3 ); | 346 | pClient->write( buf, 3 ); |
347 | } | 347 | } |
348 | catch( Bu::HashException &e ) | 348 | catch( Bu::HashException &e ) |
349 | { | 349 | { |
350 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 350 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
351 | pClient->write( buf, 3 ); | 351 | pClient->write( buf, 3 ); |
352 | } | 352 | } |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::ProtocolTelnet::onDo( char cCode ) | 355 | void Bu::ProtocolTelnet::onDo( char cCode ) |
356 | { | 356 | { |
357 | try | 357 | try |
358 | { | 358 | { |
359 | Option *pOpt = hOpts[cCode]; | 359 | Option *pOpt = hOpts[cCode]; |
360 | if( pOpt->isLocalEnabled() ) | 360 | if( pOpt->isLocalEnabled() ) |
361 | { | 361 | { |
362 | pOpt->fOpts |= Option::fLocalIs; | 362 | pOpt->fOpts |= Option::fLocalIs; |
363 | char buf[3] = { CODE_IAC, CODE_WILL, cCode }; | 363 | char buf[3] = { CODE_IAC, CODE_WILL, cCode }; |
364 | pClient->write( buf, 3 ); | 364 | pClient->write( buf, 3 ); |
365 | } | 365 | } |
366 | else | 366 | else |
367 | { | 367 | { |
368 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; | 368 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; |
369 | pClient->write( buf, 3 ); | 369 | pClient->write( buf, 3 ); |
370 | } | 370 | } |
371 | 371 | ||
372 | } | 372 | } |
373 | catch( Bu::HashException &e ) | 373 | catch( Bu::HashException &e ) |
374 | { | 374 | { |
375 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; | 375 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; |
376 | pClient->write( buf, 3 ); | 376 | pClient->write( buf, 3 ); |
377 | } | 377 | } |
378 | } | 378 | } |
379 | 379 | ||
380 | void Bu::ProtocolTelnet::onDont( char cCode ) | 380 | void Bu::ProtocolTelnet::onDont( char cCode ) |
381 | { | 381 | { |
382 | try | 382 | try |
383 | { | 383 | { |
384 | Option *pOpt = hOpts[cCode]; | 384 | Option *pOpt = hOpts[cCode]; |
385 | 385 | ||
386 | pOpt->fOpts &= ~Option::fLocalIs; | 386 | pOpt->fOpts &= ~Option::fLocalIs; |
387 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 387 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
388 | pClient->write( buf, 3 ); | 388 | pClient->write( buf, 3 ); |
389 | } | 389 | } |
390 | catch( Bu::HashException &e ) | 390 | catch( Bu::HashException &e ) |
391 | { | 391 | { |
392 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 392 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
393 | pClient->write( buf, 3 ); | 393 | pClient->write( buf, 3 ); |
394 | } | 394 | } |
395 | } | 395 | } |
396 | 396 | ||
397 | void Bu::ProtocolTelnet::onSubOpt() | 397 | void Bu::ProtocolTelnet::onSubOpt() |
398 | { | 398 | { |
399 | switch( cSubOpt ) | 399 | switch( cSubOpt ) |
400 | { | 400 | { |
401 | case OPT_NAWS: | 401 | case OPT_NAWS: |
402 | { | 402 | { |
403 | uint16_t iWidth, iHeight; | 403 | uint16_t iWidth, iHeight; |
404 | ((char *)&iWidth)[1] = sSubBuf[0]; | 404 | ((char *)&iWidth)[1] = sSubBuf[0]; |
405 | ((char *)&iWidth)[0] = sSubBuf[1]; | 405 | ((char *)&iWidth)[0] = sSubBuf[1]; |
406 | ((char *)&iHeight)[1] = sSubBuf[2]; | 406 | ((char *)&iHeight)[1] = sSubBuf[2]; |
407 | ((char *)&iHeight)[0] = sSubBuf[3]; | 407 | ((char *)&iHeight)[0] = sSubBuf[3]; |
408 | onSubNAWS( iWidth, iHeight ); | 408 | onSubNAWS( iWidth, iHeight ); |
409 | } | 409 | } |
410 | break; | 410 | break; |
411 | 411 | ||
412 | default: | 412 | default: |
413 | onSubUnknown( cSubOpt, sSubBuf ); | 413 | onSubUnknown( cSubOpt, sSubBuf ); |
414 | break; | 414 | break; |
415 | } | 415 | } |
416 | 416 | ||
417 | sSubBuf.clear(); | 417 | sSubBuf.clear(); |
418 | } | 418 | } |
419 | 419 | ||
420 | void Bu::ProtocolTelnet::onCtlChar( char cChr ) | 420 | void Bu::ProtocolTelnet::onCtlChar( char cChr ) |
421 | { | 421 | { |
422 | #ifdef __TELNET_DEBUG | 422 | #ifdef __TELNET_DEBUG |
423 | switch( cChr ) | 423 | switch( cChr ) |
424 | { | 424 | { |
425 | case CH_NUL: printf("NUL "); break; | 425 | case CH_NUL: printf("NUL "); break; |
426 | case CH_SOH: printf("SOH "); break; | 426 | case CH_SOH: printf("SOH "); break; |
427 | case CH_STX: printf("STX "); break; | 427 | case CH_STX: printf("STX "); break; |
428 | case CH_ETX: printf("ETX "); break; | 428 | case CH_ETX: printf("ETX "); break; |
429 | case CH_EOT: printf("EOT "); break; | 429 | case CH_EOT: printf("EOT "); break; |
430 | case CH_ENQ: printf("ENQ "); break; | 430 | case CH_ENQ: printf("ENQ "); break; |
431 | case CH_ACK: printf("ACK "); break; | 431 | case CH_ACK: printf("ACK "); break; |
432 | case CH_BEL: printf("BEL "); break; | 432 | case CH_BEL: printf("BEL "); break; |
433 | case CH_BS: printf("BS "); break; | 433 | case CH_BS: printf("BS "); break; |
434 | case CH_TAB: printf("TAB "); break; | 434 | case CH_TAB: printf("TAB "); break; |
435 | case CH_LF: printf("LF "); break; | 435 | case CH_LF: printf("LF "); break; |
436 | case CH_VT: printf("VT "); break; | 436 | case CH_VT: printf("VT "); break; |
437 | case CH_FF: printf("FF "); break; | 437 | case CH_FF: printf("FF "); break; |
438 | case CH_CR: printf("CR "); break; | 438 | case CH_CR: printf("CR "); break; |
439 | case CH_ESC: printf("ESC "); break; | 439 | case CH_ESC: printf("ESC "); break; |
440 | case CH_DEL: printf("DEL "); break; | 440 | case CH_DEL: printf("DEL "); break; |
441 | default: printf("!![%02x] ", cChr ); break; | 441 | default: printf("!![%02x] ", cChr ); break; |
442 | } | 442 | } |
443 | fflush( stdout ); | 443 | fflush( stdout ); |
444 | #endif | 444 | #endif |
445 | 445 | ||
446 | switch( cChr ) | 446 | switch( cChr ) |
447 | { | 447 | { |
448 | case CH_DEL: | 448 | case CH_DEL: |
449 | { | 449 | { |
450 | if( sDataBuf.getSize() > 0 ) | 450 | if( sDataBuf.getSize() > 0 ) |
451 | { | 451 | { |
452 | sDataBuf.resize( sDataBuf.getSize()-1 ); | 452 | sDataBuf.resize( sDataBuf.getSize()-1 ); |
453 | char buf[3] = { CH_BS, ' ', CH_BS }; | 453 | char buf[3] = { CH_BS, ' ', CH_BS }; |
454 | pClient->write( buf, 3 ); | 454 | pClient->write( buf, 3 ); |
455 | } | 455 | } |
456 | } | 456 | } |
457 | break; | 457 | break; |
458 | 458 | ||
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | #ifdef __TELNET_DEBUG | 462 | #ifdef __TELNET_DEBUG |
463 | void Bu::ProtocolTelnet::printCode( char cCode ) | 463 | void Bu::ProtocolTelnet::printCode( char cCode ) |
464 | { | 464 | { |
465 | switch( cCode ) | 465 | switch( cCode ) |
466 | { | 466 | { |
467 | case CODE_SE: printf("SE "); break; | 467 | case CODE_SE: printf("SE "); break; |
468 | case CODE_NOP: printf("NOP "); break; | 468 | case CODE_NOP: printf("NOP "); break; |
469 | case CODE_DM: printf("DM "); break; | 469 | case CODE_DM: printf("DM "); break; |
470 | case CODE_BRK: printf("BRK "); break; | 470 | case CODE_BRK: printf("BRK "); break; |
471 | case CODE_IP: printf("IP "); break; | 471 | case CODE_IP: printf("IP "); break; |
472 | case CODE_AO: printf("AO "); break; | 472 | case CODE_AO: printf("AO "); break; |
473 | case CODE_AYT: printf("AYT "); break; | 473 | case CODE_AYT: printf("AYT "); break; |
474 | case CODE_EC: printf("EC "); break; | 474 | case CODE_EC: printf("EC "); break; |
475 | case CODE_EL: printf("EL "); break; | 475 | case CODE_EL: printf("EL "); break; |
476 | case CODE_GA: printf("GA "); break; | 476 | case CODE_GA: printf("GA "); break; |
477 | case CODE_SB: printf("SB "); break; | 477 | case CODE_SB: printf("SB "); break; |
478 | case CODE_WILL: printf("WILL "); break; | 478 | case CODE_WILL: printf("WILL "); break; |
479 | case CODE_WONT: printf("WONT "); break; | 479 | case CODE_WONT: printf("WONT "); break; |
480 | case CODE_DO: printf("DO "); break; | 480 | case CODE_DO: printf("DO "); break; |
481 | case CODE_DONT: printf("DONT "); break; | 481 | case CODE_DONT: printf("DONT "); break; |
482 | case CODE_IAC: printf("IAC "); break; | 482 | case CODE_IAC: printf("IAC "); break; |
483 | default: printf("??%02x ", cCode ); break; | 483 | default: printf("??%02x ", cCode ); break; |
484 | } | 484 | } |
485 | fflush( stdout ); | 485 | fflush( stdout ); |
486 | } | 486 | } |
487 | 487 | ||
488 | void Bu::ProtocolTelnet::printOpt( char cOpt ) | 488 | void Bu::ProtocolTelnet::printOpt( char cOpt ) |
489 | { | 489 | { |
490 | switch( cOpt ) | 490 | switch( cOpt ) |
491 | { | 491 | { |
492 | case OPT_BINARY: printf("BINARY "); break; | 492 | case OPT_BINARY: printf("BINARY "); break; |
493 | case OPT_ECHO: printf("ECHO "); break; | 493 | case OPT_ECHO: printf("ECHO "); break; |
494 | case OPT_SUPGA: printf("SUPGA "); break; | 494 | case OPT_SUPGA: printf("SUPGA "); break; |
495 | case OPT_STATUS: printf("STATUS "); break; | 495 | case OPT_STATUS: printf("STATUS "); break; |
496 | case OPT_TIMING: printf("TIMING "); break; | 496 | case OPT_TIMING: printf("TIMING "); break; |
497 | case OPT_EXASCII: printf("EXASCII "); break; | 497 | case OPT_EXASCII: printf("EXASCII "); break; |
498 | case OPT_LOGOUT: printf("LOGOUT "); break; | 498 | case OPT_LOGOUT: printf("LOGOUT "); break; |
499 | case OPT_TTYPE: printf("TTYPE "); break; | 499 | case OPT_TTYPE: printf("TTYPE "); break; |
500 | case OPT_NAWS: printf("NAWS "); break; | 500 | case OPT_NAWS: printf("NAWS "); break; |
501 | case OPT_TSPEED: printf("TSPEED "); break; | 501 | case OPT_TSPEED: printf("TSPEED "); break; |
502 | case OPT_NEWENV: printf("NEWENV "); break; | 502 | case OPT_NEWENV: printf("NEWENV "); break; |
503 | case OPT_EXOPL: printf("EXOPL "); break; | 503 | case OPT_EXOPL: printf("EXOPL "); break; |
504 | default: printf("??%02x ", cOpt); break; | 504 | default: printf("??%02x ", cOpt); break; |
505 | } | 505 | } |
506 | fflush( stdout ); | 506 | fflush( stdout ); |
507 | } | 507 | } |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : | 510 | Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : |
511 | rPT( rPT ), | 511 | rPT( rPT ), |
512 | fOpts( 0 ), | 512 | fOpts( 0 ), |
513 | cCode( cCode ) | 513 | cCode( cCode ) |
514 | { | 514 | { |
515 | rPT.hOpts.insert( cCode, this ); | 515 | rPT.hOpts.insert( cCode, this ); |
516 | } | 516 | } |
517 | 517 | ||
518 | Bu::ProtocolTelnet::Option::~Option() | 518 | Bu::ProtocolTelnet::Option::~Option() |
@@ -521,100 +521,100 @@ Bu::ProtocolTelnet::Option::~Option() | |||
521 | 521 | ||
522 | void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) | 522 | void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) |
523 | { | 523 | { |
524 | if( bSet == (bool)(!(fOpts&fLocalCant)) ) return; | 524 | if( bSet == (bool)(!(fOpts&fLocalCant)) ) return; |
525 | 525 | ||
526 | if( bSet ) | 526 | if( bSet ) |
527 | fOpts &= ~fLocalCant; | 527 | fOpts &= ~fLocalCant; |
528 | else | 528 | else |
529 | fOpts |= fLocalCant; | 529 | fOpts |= fLocalCant; |
530 | } | 530 | } |
531 | 531 | ||
532 | void Bu::ProtocolTelnet::Option::localSet( bool bSet ) | 532 | void Bu::ProtocolTelnet::Option::localSet( bool bSet ) |
533 | { | 533 | { |
534 | if( bSet == (bool)(fOpts&fLocalIs) ) return; | 534 | if( bSet == (bool)(fOpts&fLocalIs) ) return; |
535 | 535 | ||
536 | char buf[3] = { CODE_IAC, 0, cCode }; | 536 | char buf[3] = { CODE_IAC, 0, cCode }; |
537 | 537 | ||
538 | if( bSet ) | 538 | if( bSet ) |
539 | { | 539 | { |
540 | buf[1] = CODE_WILL; | 540 | buf[1] = CODE_WILL; |
541 | rPT.pClient->write( buf, 3 ); | 541 | rPT.pClient->write( buf, 3 ); |
542 | #ifdef __TELNET_DEBUG | 542 | #ifdef __TELNET_DEBUG |
543 | printf("<= "); | 543 | printf("<= "); |
544 | rPT.printCode( buf[0] ); | 544 | rPT.printCode( buf[0] ); |
545 | rPT.printCode( buf[1] ); | 545 | rPT.printCode( buf[1] ); |
546 | rPT.printOpt( buf[2] ); | 546 | rPT.printOpt( buf[2] ); |
547 | printf("\n"); | 547 | printf("\n"); |
548 | #endif | 548 | #endif |
549 | } | 549 | } |
550 | else | 550 | else |
551 | { | 551 | { |
552 | buf[1] = CODE_WONT; | 552 | buf[1] = CODE_WONT; |
553 | rPT.pClient->write( buf, 3 ); | 553 | rPT.pClient->write( buf, 3 ); |
554 | #ifdef __TELNET_DEBUG | 554 | #ifdef __TELNET_DEBUG |
555 | printf("<= "); | 555 | printf("<= "); |
556 | rPT.printCode( buf[0] ); | 556 | rPT.printCode( buf[0] ); |
557 | rPT.printCode( buf[1] ); | 557 | rPT.printCode( buf[1] ); |
558 | rPT.printOpt( buf[2] ); | 558 | rPT.printOpt( buf[2] ); |
559 | printf("\n"); | 559 | printf("\n"); |
560 | #endif | 560 | #endif |
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | bool Bu::ProtocolTelnet::Option::isLocalEnabled() | 564 | bool Bu::ProtocolTelnet::Option::isLocalEnabled() |
565 | { | 565 | { |
566 | return (bool)(!(fOpts&fLocalCant)); | 566 | return (bool)(!(fOpts&fLocalCant)); |
567 | } | 567 | } |
568 | 568 | ||
569 | bool Bu::ProtocolTelnet::Option::isLocalSet() | 569 | bool Bu::ProtocolTelnet::Option::isLocalSet() |
570 | { | 570 | { |
571 | return (bool)(fOpts&fLocalIs); | 571 | return (bool)(fOpts&fLocalIs); |
572 | } | 572 | } |
573 | 573 | ||
574 | void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) | 574 | void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) |
575 | { | 575 | { |
576 | return; | 576 | return; |
577 | } | 577 | } |
578 | 578 | ||
579 | void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) | 579 | void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) |
580 | { | 580 | { |
581 | //if( bSet == (bool)(fOpts&fRemoteIs) ) return; | 581 | //if( bSet == (bool)(fOpts&fRemoteIs) ) return; |
582 | 582 | ||
583 | char buf[3] = { CODE_IAC, 0, cCode }; | 583 | char buf[3] = { CODE_IAC, 0, cCode }; |
584 | 584 | ||
585 | if( bSet ) | 585 | if( bSet ) |
586 | { | 586 | { |
587 | buf[1] = CODE_DO; | 587 | buf[1] = CODE_DO; |
588 | rPT.pClient->write( buf, 3 ); | 588 | rPT.pClient->write( buf, 3 ); |
589 | #ifdef __TELNET_DEBUG | 589 | #ifdef __TELNET_DEBUG |
590 | printf("<= "); | 590 | printf("<= "); |
591 | rPT.printCode( buf[0] ); | 591 | rPT.printCode( buf[0] ); |
592 | rPT.printCode( buf[1] ); | 592 | rPT.printCode( buf[1] ); |
593 | rPT.printOpt( buf[2] ); | 593 | rPT.printOpt( buf[2] ); |
594 | printf("\n"); | 594 | printf("\n"); |
595 | #endif | 595 | #endif |
596 | } | 596 | } |
597 | else | 597 | else |
598 | { | 598 | { |
599 | buf[1] = CODE_DONT; | 599 | buf[1] = CODE_DONT; |
600 | rPT.pClient->write( buf, 3 ); | 600 | rPT.pClient->write( buf, 3 ); |
601 | #ifdef __TELNET_DEBUG | 601 | #ifdef __TELNET_DEBUG |
602 | printf("<= "); | 602 | printf("<= "); |
603 | rPT.printCode( buf[0] ); | 603 | rPT.printCode( buf[0] ); |
604 | rPT.printCode( buf[1] ); | 604 | rPT.printCode( buf[1] ); |
605 | rPT.printOpt( buf[2] ); | 605 | rPT.printOpt( buf[2] ); |
606 | printf("\n"); | 606 | printf("\n"); |
607 | #endif | 607 | #endif |
608 | } | 608 | } |
609 | } | 609 | } |
610 | 610 | ||
611 | bool Bu::ProtocolTelnet::Option::isRemoteEnabled() | 611 | bool Bu::ProtocolTelnet::Option::isRemoteEnabled() |
612 | { | 612 | { |
613 | return (bool)(!(fOpts&fRemoteCant)); | 613 | return (bool)(!(fOpts&fRemoteCant)); |
614 | } | 614 | } |
615 | 615 | ||
616 | bool Bu::ProtocolTelnet::Option::isRemoteSet() | 616 | bool Bu::ProtocolTelnet::Option::isRemoteSet() |
617 | { | 617 | { |
618 | return (bool)(fOpts&fRemoteIs); | 618 | return (bool)(fOpts&fRemoteIs); |
619 | } | 619 | } |
620 | 620 | ||
diff --git a/src/stable/protocoltelnet.h b/src/stable/protocoltelnet.h index 9a13496..b212303 100644 --- a/src/stable/protocoltelnet.h +++ b/src/stable/protocoltelnet.h | |||
@@ -16,205 +16,205 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Telnet Protocol handler. This attempts to provide useful and general | 20 | * Telnet Protocol handler. This attempts to provide useful and general |
21 | * support for most of the most commonly used Telnet extensions in a simple | 21 | * support for most of the most commonly used Telnet extensions in a simple |
22 | * and easy to use way. The Option variables control the settings that can | 22 | * and easy to use way. The Option variables control the settings that can |
23 | * be used on the line, and control which virtual "callbacks" will be called | 23 | * be used on the line, and control which virtual "callbacks" will be called |
24 | * when different events happen. | 24 | * when different events happen. |
25 | * | 25 | * |
26 | * To setup initial values and to disable any options you wish override the | 26 | * To setup initial values and to disable any options you wish override the |
27 | * onNewConnection function in your own class, like this: | 27 | * onNewConnection function in your own class, like this: |
28 | *@code | 28 | *@code |
29 | class MyTelnet : public Bu::ProtocolTelnet | 29 | class MyTelnet : public Bu::ProtocolTelnet |
30 | { | 30 | { |
31 | public: | 31 | public: |
32 | ... | 32 | ... |
33 | 33 | ||
34 | virtual void onNewConnection( class Bu::Client *pClient ) | 34 | virtual void onNewConnection( class Bu::Client *pClient ) |
35 | { | 35 | { |
36 | // Call the parent class' onNewConnection to get everything all | 36 | // Call the parent class' onNewConnection to get everything all |
37 | // set up. | 37 | // set up. |
38 | Bu::ProtocolTelnet::onNewConnection( pClient ); | 38 | Bu::ProtocolTelnet::onNewConnection( pClient ); |
39 | 39 | ||
40 | // These functions disable the option to send files via telnet, | 40 | // These functions disable the option to send files via telnet, |
41 | // disabling the remote option means that we won't accept this | 41 | // disabling the remote option means that we won't accept this |
42 | // option (binary data being sent to us) from the client. | 42 | // option (binary data being sent to us) from the client. |
43 | // | 43 | // |
44 | // Disabling the local option means that the client cannot ask us | 44 | // Disabling the local option means that the client cannot ask us |
45 | // to send them binary data. | 45 | // to send them binary data. |
46 | oBinary.enableRemote( false ); | 46 | oBinary.enableRemote( false ); |
47 | oBinary.enableLocal( false ); | 47 | oBinary.enableLocal( false ); |
48 | 48 | ||
49 | // This requests that the client send us window size updates | 49 | // This requests that the client send us window size updates |
50 | // whenever the size of their window changes, and an initial set to | 50 | // whenever the size of their window changes, and an initial set to |
51 | // boot. | 51 | // boot. |
52 | // | 52 | // |
53 | // To see if this option is set later, try oNAWS.isRemoteSet(), but | 53 | // To see if this option is set later, try oNAWS.isRemoteSet(), but |
54 | // wait a little while, asking immediatly will always return false, | 54 | // wait a little while, asking immediatly will always return false, |
55 | // since the remote side has yet to receive our request. | 55 | // since the remote side has yet to receive our request. |
56 | oNAWS.remoteSet(); | 56 | oNAWS.remoteSet(); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | @endcode | 59 | @endcode |
60 | * | 60 | * |
61 | *@ingroup Serving | 61 | *@ingroup Serving |
62 | */ | 62 | */ |
63 | class ProtocolTelnet : public Protocol | 63 | class ProtocolTelnet : public Protocol |
64 | { | 64 | { |
65 | public: | 65 | public: |
66 | ProtocolTelnet(); | 66 | ProtocolTelnet(); |
67 | virtual ~ProtocolTelnet(); | 67 | virtual ~ProtocolTelnet(); |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * If you override this function in a child class, make sure to call | 70 | * If you override this function in a child class, make sure to call |
71 | * this version of it as the very first thing that you do, before you | 71 | * this version of it as the very first thing that you do, before you |
72 | * set any options. See the example in the class docs. | 72 | * set any options. See the example in the class docs. |
73 | */ | 73 | */ |
74 | virtual void onNewConnection( class Bu::Client *pClient ); | 74 | virtual void onNewConnection( class Bu::Client *pClient ); |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * You should never override this function unless you really, really | 77 | * You should never override this function unless you really, really |
78 | * know what you're doing. If you want to get data after each line | 78 | * know what you're doing. If you want to get data after each line |
79 | * entered (in canonical mode) or after any data arrives (non canonical | 79 | * entered (in canonical mode) or after any data arrives (non canonical |
80 | * mode) then override the gotLine and gotData functions, respectively. | 80 | * mode) then override the gotLine and gotData functions, respectively. |
81 | */ | 81 | */ |
82 | virtual void onNewData( class Bu::Client *pClient ); | 82 | virtual void onNewData( class Bu::Client *pClient ); |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Override this function to be notified of lines being submitted by | 85 | * Override this function to be notified of lines being submitted by |
86 | * the client. This function is only called in canonical mode, after | 86 | * the client. This function is only called in canonical mode, after |
87 | * all edits are performed on the data. In this mode weather you use | 87 | * all edits are performed on the data. In this mode weather you use |
88 | * the line or not, the data will be cleared from the buffer when this | 88 | * the line or not, the data will be cleared from the buffer when this |
89 | * function returns, any changes made to the buffer will be destroyed. | 89 | * function returns, any changes made to the buffer will be destroyed. |
90 | */ | 90 | */ |
91 | virtual void gotLine( Bu::String & /*sLine*/ ){}; | 91 | virtual void gotLine( Bu::String & /*sLine*/ ){}; |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * Override this function to be notified of any new data that comes in | 94 | * Override this function to be notified of any new data that comes in |
95 | * from the client. This function is only called in non-canonical mode, | 95 | * from the client. This function is only called in non-canonical mode, |
96 | * and includes all raw data minus telnet control codes and ansi | 96 | * and includes all raw data minus telnet control codes and ansi |
97 | * escape sequences. In this mode control of the buffer is up to the | 97 | * escape sequences. In this mode control of the buffer is up to the |
98 | * child class in this function, the buffer will never be cleared unless | 98 | * child class in this function, the buffer will never be cleared unless |
99 | * it happens in this function's override. | 99 | * it happens in this function's override. |
100 | */ | 100 | */ |
101 | virtual void gotData( Bu::String & /*sData*/ ){}; | 101 | virtual void gotData( Bu::String & /*sData*/ ){}; |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Using this function to enable or disable canonical mode only affects | 104 | * Using this function to enable or disable canonical mode only affects |
105 | * the way the data is processed and which virtual functions are called | 105 | * the way the data is processed and which virtual functions are called |
106 | * during processing. It does not affect options set locally or | 106 | * during processing. It does not affect options set locally or |
107 | * remotely. Setting this to false will enable char-at-a-time mode, | 107 | * remotely. Setting this to false will enable char-at-a-time mode, |
108 | * effectively disabling internal line-editing code. Characters | 108 | * effectively disabling internal line-editing code. Characters |
109 | * such as backspace that are detected will not be handled and will be | 109 | * such as backspace that are detected will not be handled and will be |
110 | * sent to the user override. The subclass will also be notified every | 110 | * sent to the user override. The subclass will also be notified every |
111 | * time new data is available, not just whole lines. | 111 | * time new data is available, not just whole lines. |
112 | * | 112 | * |
113 | * When set to true (the default), line editing control codes will be | 113 | * When set to true (the default), line editing control codes will be |
114 | * interpreted and used, and the subclass will only be notified when | 114 | * interpreted and used, and the subclass will only be notified when |
115 | * complete lines are available in the buffer. | 115 | * complete lines are available in the buffer. |
116 | */ | 116 | */ |
117 | void setCanonical( bool bCon=true ); | 117 | void setCanonical( bool bCon=true ); |
118 | bool isCanonical(); | 118 | bool isCanonical(); |
119 | 119 | ||
120 | void write( const Bu::String &sData ); | 120 | void write( const Bu::String &sData ); |
121 | void write( const char *pData, int iSize ); | 121 | void write( const char *pData, int iSize ); |
122 | void write( char cData ); | 122 | void write( char cData ); |
123 | 123 | ||
124 | const Bu::String &getBuffer() { return sDataBuf; } | 124 | const Bu::String &getBuffer() { return sDataBuf; } |
125 | 125 | ||
126 | public: | 126 | public: |
127 | /** | 127 | /** |
128 | * If you wish to know the current dimensions of the client window, | 128 | * If you wish to know the current dimensions of the client window, |
129 | * override this function, it will be called whenever the size changes. | 129 | * override this function, it will be called whenever the size changes. |
130 | */ | 130 | */ |
131 | virtual void onSubNAWS( uint16_t /*iWidth*/, uint16_t /*iHeight*/ ){}; | 131 | virtual void onSubNAWS( uint16_t /*iWidth*/, uint16_t /*iHeight*/ ){}; |
132 | 132 | ||
133 | /** | 133 | /** |
134 | * This function is called whenever an unknown sub negotiation option is | 134 | * This function is called whenever an unknown sub negotiation option is |
135 | * sent over the line. This doesn't mean that it's malformatted, it | 135 | * sent over the line. This doesn't mean that it's malformatted, it |
136 | * just means that this class doesn't support that option yet, but you | 136 | * just means that this class doesn't support that option yet, but you |
137 | * can handle it yourself if you'd like. Feel free to change the | 137 | * can handle it yourself if you'd like. Feel free to change the |
138 | * sSubBuf, it will be cleared as soon as this function returns anyway. | 138 | * sSubBuf, it will be cleared as soon as this function returns anyway. |
139 | */ | 139 | */ |
140 | virtual void onSubUnknown( char /*cSubOpt*/, | 140 | virtual void onSubUnknown( char /*cSubOpt*/, |
141 | Bu::String & /*sSubBuf*/ ){}; | 141 | Bu::String & /*sSubBuf*/ ){}; |
142 | 142 | ||
143 | private: | 143 | private: |
144 | /** | 144 | /** |
145 | * Represents a basic telnet option, either on or off, no parameters. | 145 | * Represents a basic telnet option, either on or off, no parameters. |
146 | * Each Option can negotiate effectively on it's own, and has two | 146 | * Each Option can negotiate effectively on it's own, and has two |
147 | * parameters in each of two classes. Both local and remote can be | 147 | * parameters in each of two classes. Both local and remote can be |
148 | * enabled/disabled and set/unset. Enabled represents the ability to | 148 | * enabled/disabled and set/unset. Enabled represents the ability to |
149 | * set the option, disabling an option should also unset it. Set or | 149 | * set the option, disabling an option should also unset it. Set or |
150 | * unset represent wether the option is being used, if it is allowed. | 150 | * unset represent wether the option is being used, if it is allowed. |
151 | */ | 151 | */ |
152 | class Option | 152 | class Option |
153 | { | 153 | { |
154 | friend class Bu::ProtocolTelnet; | 154 | friend class Bu::ProtocolTelnet; |
155 | private: | 155 | private: |
156 | Option( ProtocolTelnet &rPT, char cCode ); | 156 | Option( ProtocolTelnet &rPT, char cCode ); |
157 | virtual ~Option(); | 157 | virtual ~Option(); |
158 | 158 | ||
159 | public: | 159 | public: |
160 | void localEnable( bool bSet=true ); | 160 | void localEnable( bool bSet=true ); |
161 | void localSet( bool bSet=true ); | 161 | void localSet( bool bSet=true ); |
162 | 162 | ||
163 | bool isLocalEnabled(); | 163 | bool isLocalEnabled(); |
164 | bool isLocalSet(); | 164 | bool isLocalSet(); |
165 | 165 | ||
166 | void remoteEnable( bool bSet=true ); | 166 | void remoteEnable( bool bSet=true ); |
167 | void remoteSet( bool bSet=true ); | 167 | void remoteSet( bool bSet=true ); |
168 | 168 | ||
169 | bool isRemoteEnabled(); | 169 | bool isRemoteEnabled(); |
170 | bool isRemoteSet(); | 170 | bool isRemoteSet(); |
171 | 171 | ||
172 | private: | 172 | private: |
173 | enum | 173 | enum |
174 | { | 174 | { |
175 | fLocalCant = 0x01, /**< Local can't/won't allow option. */ | 175 | fLocalCant = 0x01, /**< Local can't/won't allow option. */ |
176 | fLocalIs = 0x02, /**< Local is using option. */ | 176 | fLocalIs = 0x02, /**< Local is using option. */ |
177 | fRemoteCant = 0x04, /**< Remote can't/won't allow option. */ | 177 | fRemoteCant = 0x04, /**< Remote can't/won't allow option. */ |
178 | fRemoteIs = 0x08 /**< Remote is using option. */ | 178 | fRemoteIs = 0x08 /**< Remote is using option. */ |
179 | }; | 179 | }; |
180 | 180 | ||
181 | ProtocolTelnet &rPT; | 181 | ProtocolTelnet &rPT; |
182 | char fOpts; | 182 | char fOpts; |
183 | char cCode; | 183 | char cCode; |
184 | }; | 184 | }; |
185 | friend class Bu::ProtocolTelnet::Option; | 185 | friend class Bu::ProtocolTelnet::Option; |
186 | 186 | ||
187 | Hash<char, Option *> hOpts; | 187 | Hash<char, Option *> hOpts; |
188 | 188 | ||
189 | public: | 189 | public: |
190 | Option oBinary; | 190 | Option oBinary; |
191 | Option oEcho; | 191 | Option oEcho; |
192 | Option oNAWS; | 192 | Option oNAWS; |
193 | Option oSuppressGA; | 193 | Option oSuppressGA; |
194 | 194 | ||
195 | private: | 195 | private: |
196 | void onWill( char cCode ); | 196 | void onWill( char cCode ); |
197 | void onWont( char cCode ); | 197 | void onWont( char cCode ); |
198 | void onDo( char cCode ); | 198 | void onDo( char cCode ); |
199 | void onDont( char cCode ); | 199 | void onDont( char cCode ); |
200 | void onSubOpt(); | 200 | void onSubOpt(); |
201 | void onCtlChar( char cChr ); | 201 | void onCtlChar( char cChr ); |
202 | 202 | ||
203 | #ifdef __TELNET_DEBUG | 203 | #ifdef __TELNET_DEBUG |
204 | void printCode( char cCode ); | 204 | void printCode( char cCode ); |
205 | void printOpt( char cOpt ); | 205 | void printOpt( char cOpt ); |
206 | #endif | 206 | #endif |
207 | 207 | ||
208 | private: | 208 | private: |
209 | Client *pClient; | 209 | Client *pClient; |
210 | 210 | ||
211 | Bu::String sDataBuf; /**< Buffer for regular line data. */ | 211 | Bu::String sDataBuf; /**< Buffer for regular line data. */ |
212 | Bu::String sSubBuf; /**< Buffer for subnegotiation data. */ | 212 | Bu::String sSubBuf; /**< Buffer for subnegotiation data. */ |
213 | char cSubOpt; /**< Which suboption are we processing. */ | 213 | char cSubOpt; /**< Which suboption are we processing. */ |
214 | 214 | ||
215 | bool bCanonical; /**< Are we canonicalizing incoming data? */ | 215 | bool bCanonical; /**< Are we canonicalizing incoming data? */ |
216 | bool bSubOpt; /**< Are we processing a suboption right now? */ | 216 | bool bSubOpt; /**< Are we processing a suboption right now? */ |
217 | }; | 217 | }; |
218 | } | 218 | } |
219 | 219 | ||
220 | #endif | 220 | #endif |
diff --git a/src/stable/queue.h b/src/stable/queue.h index a5f41e9..213d508 100644 --- a/src/stable/queue.h +++ b/src/stable/queue.h | |||
@@ -10,31 +10,31 @@ | |||
10 | 10 | ||
11 | namespace Bu | 11 | namespace Bu |
12 | { | 12 | { |
13 | /** | 13 | /** |
14 | * Queue abstract baseclass | 14 | * Queue abstract baseclass |
15 | */ | 15 | */ |
16 | template<typename value> | 16 | template<typename value> |
17 | class Queue | 17 | class Queue |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | Queue() | 20 | Queue() |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
24 | virtual ~Queue() | 24 | virtual ~Queue() |
25 | { | 25 | { |
26 | } | 26 | } |
27 | 27 | ||
28 | virtual void enqueue( const value &i )=0; | 28 | virtual void enqueue( const value &i )=0; |
29 | virtual value dequeue()=0; | 29 | virtual value dequeue()=0; |
30 | virtual value &peek()=0; | 30 | virtual value &peek()=0; |
31 | virtual const value &peek() const=0; | 31 | virtual const value &peek() const=0; |
32 | virtual bool isEmpty() const=0; | 32 | virtual bool isEmpty() const=0; |
33 | virtual int getSize() const=0; | 33 | virtual int getSize() const=0; |
34 | 34 | ||
35 | private: | 35 | private: |
36 | 36 | ||
37 | }; | 37 | }; |
38 | } | 38 | } |
39 | 39 | ||
40 | #endif | 40 | #endif |
diff --git a/src/stable/queuebuf.cpp b/src/stable/queuebuf.cpp index 8a3397f..2d49684 100644 --- a/src/stable/queuebuf.cpp +++ b/src/stable/queuebuf.cpp | |||
@@ -11,181 +11,181 @@ | |||
11 | using Bu::sio; | 11 | using Bu::sio; |
12 | 12 | ||
13 | Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : | 13 | Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : |
14 | iBlockSize( iBlockSize ), | 14 | iBlockSize( iBlockSize ), |
15 | iReadOffset( 0 ), | 15 | iReadOffset( 0 ), |
16 | iWriteOffset( 0 ), | 16 | iWriteOffset( 0 ), |
17 | iTotalSize( 0 ) | 17 | iTotalSize( 0 ) |
18 | { | 18 | { |
19 | } | 19 | } |
20 | 20 | ||
21 | Bu::QueueBuf::~QueueBuf() | 21 | Bu::QueueBuf::~QueueBuf() |
22 | { | 22 | { |
23 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) | 23 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) |
24 | delete[] *i; | 24 | delete[] *i; |
25 | } | 25 | } |
26 | 26 | ||
27 | void Bu::QueueBuf::close() | 27 | void Bu::QueueBuf::close() |
28 | { | 28 | { |
29 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) | 29 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) |
30 | delete[] *i; | 30 | delete[] *i; |
31 | lBlocks.clear(); | 31 | lBlocks.clear(); |
32 | iReadOffset = iWriteOffset = iTotalSize = 0; | 32 | iReadOffset = iWriteOffset = iTotalSize = 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) | 35 | Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) |
36 | { | 36 | { |
37 | if( nBytes <= 0 ) | 37 | if( nBytes <= 0 ) |
38 | return 0; | 38 | return 0; |
39 | 39 | ||
40 | if( lBlocks.isEmpty() ) | 40 | if( lBlocks.isEmpty() ) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | Bu::size iLeft = nBytes; | 43 | Bu::size iLeft = nBytes; |
44 | char *pBuf = (char *)pRawBuf; | 44 | char *pBuf = (char *)pRawBuf; |
45 | 45 | ||
46 | while( iLeft > 0 && iTotalSize > 0 ) | 46 | while( iLeft > 0 && iTotalSize > 0 ) |
47 | { | 47 | { |
48 | if( iReadOffset == iBlockSize ) | 48 | if( iReadOffset == iBlockSize ) |
49 | { | 49 | { |
50 | removeBlock(); | 50 | removeBlock(); |
51 | if( lBlocks.isEmpty() ) | 51 | if( lBlocks.isEmpty() ) |
52 | { | 52 | { |
53 | return nBytes-iLeft; | 53 | return nBytes-iLeft; |
54 | } | 54 | } |
55 | iReadOffset = 0; | 55 | iReadOffset = 0; |
56 | } | 56 | } |
57 | char *pBlock = lBlocks.first(); | 57 | char *pBlock = lBlocks.first(); |
58 | Bu::size iCopy = iBlockSize-iReadOffset; | 58 | Bu::size iCopy = iBlockSize-iReadOffset; |
59 | if( iLeft < iCopy ) | 59 | if( iLeft < iCopy ) |
60 | iCopy = iLeft; | 60 | iCopy = iLeft; |
61 | if( iTotalSize < iCopy ) | 61 | if( iTotalSize < iCopy ) |
62 | iCopy = iTotalSize; | 62 | iCopy = iTotalSize; |
63 | memcpy( pBuf, pBlock+iReadOffset, iCopy ); | 63 | memcpy( pBuf, pBlock+iReadOffset, iCopy ); |
64 | iReadOffset += iCopy; | 64 | iReadOffset += iCopy; |
65 | iLeft -= iCopy; | 65 | iLeft -= iCopy; |
66 | pBuf += iCopy; | 66 | pBuf += iCopy; |
67 | iTotalSize -= iCopy; | 67 | iTotalSize -= iCopy; |
68 | // sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; | 68 | // sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; |
69 | } | 69 | } |
70 | 70 | ||
71 | return nBytes - iLeft; | 71 | return nBytes - iLeft; |
72 | } | 72 | } |
73 | 73 | ||
74 | Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) | 74 | Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) |
75 | { | 75 | { |
76 | return peek( pBuf, nBytes, 0 ); | 76 | return peek( pBuf, nBytes, 0 ); |
77 | } | 77 | } |
78 | 78 | ||
79 | Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) | 79 | Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) |
80 | { | 80 | { |
81 | if( nBytes <= 0 ) | 81 | if( nBytes <= 0 ) |
82 | return 0; | 82 | return 0; |
83 | 83 | ||
84 | if( lBlocks.isEmpty() ) | 84 | if( lBlocks.isEmpty() ) |
85 | return 0; | 85 | return 0; |
86 | 86 | ||
87 | Bu::size iLeft = nBytes; | 87 | Bu::size iLeft = nBytes; |
88 | char *pBuf = (char *)pRawBuf; | 88 | char *pBuf = (char *)pRawBuf; |
89 | 89 | ||
90 | int iTmpReadOffset = iReadOffset + nSkip; | 90 | int iTmpReadOffset = iReadOffset + nSkip; |
91 | Bu::size iTmpRemSize = iTotalSize; | 91 | Bu::size iTmpRemSize = iTotalSize; |
92 | BlockList::iterator iBlock = lBlocks.begin(); | 92 | BlockList::iterator iBlock = lBlocks.begin(); |
93 | while( iTmpReadOffset > iBlockSize ) | 93 | while( iTmpReadOffset > iBlockSize ) |
94 | { | 94 | { |
95 | iTmpReadOffset -= iBlockSize; | 95 | iTmpReadOffset -= iBlockSize; |
96 | iBlock++; | 96 | iBlock++; |
97 | } | 97 | } |
98 | while( iLeft > 0 && iTmpRemSize > 0 ) | 98 | while( iLeft > 0 && iTmpRemSize > 0 ) |
99 | { | 99 | { |
100 | if( iTmpReadOffset == iBlockSize ) | 100 | if( iTmpReadOffset == iBlockSize ) |
101 | { | 101 | { |
102 | iBlock++; | 102 | iBlock++; |
103 | if( iBlock == lBlocks.end() ) | 103 | if( iBlock == lBlocks.end() ) |
104 | { | 104 | { |
105 | return nBytes-iLeft; | 105 | return nBytes-iLeft; |
106 | } | 106 | } |
107 | iTmpReadOffset = 0; | 107 | iTmpReadOffset = 0; |
108 | } | 108 | } |
109 | char *pBlock = *iBlock; | 109 | char *pBlock = *iBlock; |
110 | Bu::size iCopy = iBlockSize-iTmpReadOffset; | 110 | Bu::size iCopy = iBlockSize-iTmpReadOffset; |
111 | if( iLeft < iCopy ) | 111 | if( iLeft < iCopy ) |
112 | iCopy = iLeft; | 112 | iCopy = iLeft; |
113 | if( iTmpRemSize < iCopy ) | 113 | if( iTmpRemSize < iCopy ) |
114 | iCopy = iTmpRemSize; | 114 | iCopy = iTmpRemSize; |
115 | memcpy( pBuf, pBlock+iTmpReadOffset, iCopy ); | 115 | memcpy( pBuf, pBlock+iTmpReadOffset, iCopy ); |
116 | iTmpReadOffset += iCopy; | 116 | iTmpReadOffset += iCopy; |
117 | iLeft -= iCopy; | 117 | iLeft -= iCopy; |
118 | pBuf += iCopy; | 118 | pBuf += iCopy; |
119 | iTmpRemSize -= iCopy; | 119 | iTmpRemSize -= iCopy; |
120 | // sio << "Read (peek) " << iCopy << " bytes, new temp size: " | 120 | // sio << "Read (peek) " << iCopy << " bytes, new temp size: " |
121 | // << iTmpRemSize << sio.nl; | 121 | // << iTmpRemSize << sio.nl; |
122 | } | 122 | } |
123 | 123 | ||
124 | return nBytes - iLeft; | 124 | return nBytes - iLeft; |
125 | } | 125 | } |
126 | 126 | ||
127 | Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) | 127 | Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) |
128 | { | 128 | { |
129 | if( nBytes <= 0 ) | 129 | if( nBytes <= 0 ) |
130 | return 0; | 130 | return 0; |
131 | 131 | ||
132 | if( lBlocks.isEmpty() ) | 132 | if( lBlocks.isEmpty() ) |
133 | { | 133 | { |
134 | addBlock(); | 134 | addBlock(); |
135 | iWriteOffset = 0; | 135 | iWriteOffset = 0; |
136 | } | 136 | } |
137 | Bu::size iLeft = nBytes; | 137 | Bu::size iLeft = nBytes; |
138 | const char *pBuf = (const char *)pRawBuf; | 138 | const char *pBuf = (const char *)pRawBuf; |
139 | 139 | ||
140 | while( iLeft > 0 ) | 140 | while( iLeft > 0 ) |
141 | { | 141 | { |
142 | if( iWriteOffset == iBlockSize ) | 142 | if( iWriteOffset == iBlockSize ) |
143 | { | 143 | { |
144 | addBlock(); | 144 | addBlock(); |
145 | iWriteOffset = 0; | 145 | iWriteOffset = 0; |
146 | } | 146 | } |
147 | char *pBlock = lBlocks.last(); | 147 | char *pBlock = lBlocks.last(); |
148 | Bu::size iCopy = iBlockSize-iWriteOffset; | 148 | Bu::size iCopy = iBlockSize-iWriteOffset; |
149 | if( iLeft < iCopy ) | 149 | if( iLeft < iCopy ) |
150 | iCopy = iLeft; | 150 | iCopy = iLeft; |
151 | memcpy( pBlock+iWriteOffset, pBuf, iCopy ); | 151 | memcpy( pBlock+iWriteOffset, pBuf, iCopy ); |
152 | iWriteOffset += iCopy; | 152 | iWriteOffset += iCopy; |
153 | iLeft -= iCopy; | 153 | iLeft -= iCopy; |
154 | pBuf += iCopy; | 154 | pBuf += iCopy; |
155 | iTotalSize += iCopy; | 155 | iTotalSize += iCopy; |
156 | // sio << "Wrote " << iCopy << " bytes, new size: " << iTotalSize | 156 | // sio << "Wrote " << iCopy << " bytes, new size: " << iTotalSize |
157 | // << sio.nl; | 157 | // << sio.nl; |
158 | } | 158 | } |
159 | 159 | ||
160 | return nBytes; | 160 | return nBytes; |
161 | } | 161 | } |
162 | 162 | ||
163 | Bu::size Bu::QueueBuf::tell() | 163 | Bu::size Bu::QueueBuf::tell() |
164 | { | 164 | { |
165 | return -1; | 165 | return -1; |
166 | } | 166 | } |
167 | 167 | ||
168 | void Bu::QueueBuf::seek( Bu::size iAmnt ) | 168 | void Bu::QueueBuf::seek( Bu::size iAmnt ) |
169 | { | 169 | { |
170 | if( iAmnt <= 0 ) | 170 | if( iAmnt <= 0 ) |
171 | return; | 171 | return; |
172 | 172 | ||
173 | if( (Bu::size)iAmnt >= iTotalSize ) | 173 | if( (Bu::size)iAmnt >= iTotalSize ) |
174 | { | 174 | { |
175 | // sio << "seek: clear all data (" << iAmnt << ">=" << iTotalSize | 175 | // sio << "seek: clear all data (" << iAmnt << ">=" << iTotalSize |
176 | // << ")." << sio.nl; | 176 | // << ")." << sio.nl; |
177 | close(); | 177 | close(); |
178 | return; | 178 | return; |
179 | } | 179 | } |
180 | 180 | ||
181 | iReadOffset += iAmnt; | 181 | iReadOffset += iAmnt; |
182 | iTotalSize -= iAmnt; | 182 | iTotalSize -= iAmnt; |
183 | while( iReadOffset >= iBlockSize ) | 183 | while( iReadOffset >= iBlockSize ) |
184 | { | 184 | { |
185 | removeBlock(); | 185 | removeBlock(); |
186 | iReadOffset -= iBlockSize; | 186 | iReadOffset -= iBlockSize; |
187 | // sio << "seek: removal step (" << iReadOffset << ")" << sio.nl; | 187 | // sio << "seek: removal step (" << iReadOffset << ")" << sio.nl; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | void Bu::QueueBuf::setPos( Bu::size ) | 191 | void Bu::QueueBuf::setPos( Bu::size ) |
@@ -198,12 +198,12 @@ void Bu::QueueBuf::setPosEnd( Bu::size ) | |||
198 | 198 | ||
199 | bool Bu::QueueBuf::isEos() | 199 | bool Bu::QueueBuf::isEos() |
200 | { | 200 | { |
201 | return iTotalSize == 0; | 201 | return iTotalSize == 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | bool Bu::QueueBuf::isOpen() | 204 | bool Bu::QueueBuf::isOpen() |
205 | { | 205 | { |
206 | return true; | 206 | return true; |
207 | } | 207 | } |
208 | 208 | ||
209 | void Bu::QueueBuf::flush() | 209 | void Bu::QueueBuf::flush() |
@@ -212,32 +212,32 @@ void Bu::QueueBuf::flush() | |||
212 | 212 | ||
213 | bool Bu::QueueBuf::canRead() | 213 | bool Bu::QueueBuf::canRead() |
214 | { | 214 | { |
215 | return iTotalSize > 0; | 215 | return iTotalSize > 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | bool Bu::QueueBuf::canWrite() | 218 | bool Bu::QueueBuf::canWrite() |
219 | { | 219 | { |
220 | return true; | 220 | return true; |
221 | } | 221 | } |
222 | 222 | ||
223 | bool Bu::QueueBuf::isReadable() | 223 | bool Bu::QueueBuf::isReadable() |
224 | { | 224 | { |
225 | return true; | 225 | return true; |
226 | } | 226 | } |
227 | 227 | ||
228 | bool Bu::QueueBuf::isWritable() | 228 | bool Bu::QueueBuf::isWritable() |
229 | { | 229 | { |
230 | return true; | 230 | return true; |
231 | } | 231 | } |
232 | 232 | ||
233 | bool Bu::QueueBuf::isSeekable() | 233 | bool Bu::QueueBuf::isSeekable() |
234 | { | 234 | { |
235 | return false; | 235 | return false; |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::QueueBuf::isBlocking() | 238 | bool Bu::QueueBuf::isBlocking() |
239 | { | 239 | { |
240 | return false; | 240 | return false; |
241 | } | 241 | } |
242 | 242 | ||
243 | void Bu::QueueBuf::setBlocking( bool ) | 243 | void Bu::QueueBuf::setBlocking( bool ) |
@@ -250,29 +250,29 @@ void Bu::QueueBuf::setSize( Bu::size ) | |||
250 | 250 | ||
251 | Bu::size Bu::QueueBuf::getSize() const | 251 | Bu::size Bu::QueueBuf::getSize() const |
252 | { | 252 | { |
253 | return iTotalSize; | 253 | return iTotalSize; |
254 | } | 254 | } |
255 | 255 | ||
256 | Bu::size Bu::QueueBuf::getBlockSize() const | 256 | Bu::size Bu::QueueBuf::getBlockSize() const |
257 | { | 257 | { |
258 | return iBlockSize; | 258 | return iBlockSize; |
259 | } | 259 | } |
260 | 260 | ||
261 | Bu::String Bu::QueueBuf::getLocation() const | 261 | Bu::String Bu::QueueBuf::getLocation() const |
262 | { | 262 | { |
263 | return ""; | 263 | return ""; |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::QueueBuf::addBlock() | 266 | void Bu::QueueBuf::addBlock() |
267 | { | 267 | { |
268 | lBlocks.append( new char[iBlockSize] ); | 268 | lBlocks.append( new char[iBlockSize] ); |
269 | // sio << "Added new block." << sio.nl; | 269 | // sio << "Added new block." << sio.nl; |
270 | } | 270 | } |
271 | 271 | ||
272 | void Bu::QueueBuf::removeBlock() | 272 | void Bu::QueueBuf::removeBlock() |
273 | { | 273 | { |
274 | delete[] lBlocks.first(); | 274 | delete[] lBlocks.first(); |
275 | lBlocks.erase( lBlocks.begin() ); | 275 | lBlocks.erase( lBlocks.begin() ); |
276 | // sio << "Removed block." << sio.nl; | 276 | // sio << "Removed block." << sio.nl; |
277 | } | 277 | } |
278 | 278 | ||
diff --git a/src/stable/queuebuf.h b/src/stable/queuebuf.h index 6e2a075..60aa115 100644 --- a/src/stable/queuebuf.h +++ b/src/stable/queuebuf.h | |||
@@ -12,55 +12,55 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A queuing buffer stream class. All data written to this class is | 16 | * A queuing buffer stream class. All data written to this class is |
17 | * appended to it, there is no stored position. All data read is read | 17 | * appended to it, there is no stored position. All data read is read |
18 | * from the begining and then thrown away. It operates by using a linked | 18 | * from the begining and then thrown away. It operates by using a linked |
19 | * list of small buffers, and deallocating or reusing them when it can. | 19 | * list of small buffers, and deallocating or reusing them when it can. |
20 | */ | 20 | */ |
21 | class QueueBuf : public Bu::Stream | 21 | class QueueBuf : public Bu::Stream |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | QueueBuf( int iBlockSize=256 ); | 24 | QueueBuf( int iBlockSize=256 ); |
25 | virtual ~QueueBuf(); | 25 | virtual ~QueueBuf(); |
26 | 26 | ||
27 | virtual void close(); | 27 | virtual void close(); |
28 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 28 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
29 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); | 29 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); |
30 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); | 30 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); |
31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size tell(); | 32 | virtual Bu::size tell(); |
33 | virtual void seek( Bu::size offset ); | 33 | virtual void seek( Bu::size offset ); |
34 | virtual void setPos( Bu::size pos ); | 34 | virtual void setPos( Bu::size pos ); |
35 | virtual void setPosEnd( Bu::size pos ); | 35 | virtual void setPosEnd( Bu::size pos ); |
36 | virtual bool isEos(); | 36 | virtual bool isEos(); |
37 | virtual bool isOpen(); | 37 | virtual bool isOpen(); |
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | virtual bool canRead(); | 39 | virtual bool canRead(); |
40 | virtual bool canWrite(); | 40 | virtual bool canWrite(); |
41 | virtual bool isReadable(); | 41 | virtual bool isReadable(); |
42 | virtual bool isWritable(); | 42 | virtual bool isWritable(); |
43 | virtual bool isSeekable(); | 43 | virtual bool isSeekable(); |
44 | virtual bool isBlocking(); | 44 | virtual bool isBlocking(); |
45 | virtual void setBlocking( bool bBlocking=true ); | 45 | virtual void setBlocking( bool bBlocking=true ); |
46 | virtual void setSize( Bu::size iSize ); | 46 | virtual void setSize( Bu::size iSize ); |
47 | 47 | ||
48 | virtual size getSize() const; | 48 | virtual size getSize() const; |
49 | virtual size getBlockSize() const; | 49 | virtual size getBlockSize() const; |
50 | virtual Bu::String getLocation() const; | 50 | virtual Bu::String getLocation() const; |
51 | 51 | ||
52 | private: | 52 | private: |
53 | void addBlock(); | 53 | void addBlock(); |
54 | void removeBlock(); | 54 | void removeBlock(); |
55 | 55 | ||
56 | private: | 56 | private: |
57 | int iBlockSize; | 57 | int iBlockSize; |
58 | int iReadOffset; | 58 | int iReadOffset; |
59 | int iWriteOffset; | 59 | int iWriteOffset; |
60 | Bu::size iTotalSize; | 60 | Bu::size iTotalSize; |
61 | typedef Bu::List<char *> BlockList; | 61 | typedef Bu::List<char *> BlockList; |
62 | BlockList lBlocks; | 62 | BlockList lBlocks; |
63 | }; | 63 | }; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | #endif | 66 | #endif |
diff --git a/src/stable/random.cpp b/src/stable/random.cpp index 63416bf..6dca782 100644 --- a/src/stable/random.cpp +++ b/src/stable/random.cpp | |||
@@ -9,39 +9,39 @@ | |||
9 | #include "bu/randombasic.h" | 9 | #include "bu/randombasic.h" |
10 | 10 | ||
11 | Bu::Random::Random() : | 11 | Bu::Random::Random() : |
12 | pGen( NULL ) | 12 | pGen( NULL ) |
13 | { | 13 | { |
14 | pGen = new RandomBasic(); | 14 | pGen = new RandomBasic(); |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::Random::~Random() | 17 | Bu::Random::~Random() |
18 | { | 18 | { |
19 | delete pGen; | 19 | delete pGen; |
20 | pGen = NULL; | 20 | pGen = NULL; |
21 | } | 21 | } |
22 | 22 | ||
23 | void Bu::Random::seed( int32_t iSeed ) | 23 | void Bu::Random::seed( int32_t iSeed ) |
24 | { | 24 | { |
25 | getInstance().pGen->seed( iSeed ); | 25 | getInstance().pGen->seed( iSeed ); |
26 | } | 26 | } |
27 | 27 | ||
28 | int32_t Bu::Random::rand() | 28 | int32_t Bu::Random::rand() |
29 | { | 29 | { |
30 | return getInstance().pGen->rand(); | 30 | return getInstance().pGen->rand(); |
31 | } | 31 | } |
32 | 32 | ||
33 | int32_t Bu::Random::rand( int32_t iMax ) | 33 | int32_t Bu::Random::rand( int32_t iMax ) |
34 | { | 34 | { |
35 | return getInstance().pGen->rand( iMax ); | 35 | return getInstance().pGen->rand( iMax ); |
36 | } | 36 | } |
37 | 37 | ||
38 | int32_t Bu::Random::rand( int32_t iMin, int32_t iMax ) | 38 | int32_t Bu::Random::rand( int32_t iMin, int32_t iMax ) |
39 | { | 39 | { |
40 | return getInstance().pGen->rand( iMin, iMax ); | 40 | return getInstance().pGen->rand( iMin, iMax ); |
41 | } | 41 | } |
42 | 42 | ||
43 | double Bu::Random::randNorm() | 43 | double Bu::Random::randNorm() |
44 | { | 44 | { |
45 | return getInstance().pGen->randNorm(); | 45 | return getInstance().pGen->randNorm(); |
46 | } | 46 | } |
47 | 47 | ||
diff --git a/src/stable/random.h b/src/stable/random.h index 43b8917..7989188 100644 --- a/src/stable/random.h +++ b/src/stable/random.h | |||
@@ -12,50 +12,50 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class RandomBase; | 15 | class RandomBase; |
16 | class Random : public Bu::Singleton<Bu::Random> | 16 | class Random : public Bu::Singleton<Bu::Random> |
17 | { | 17 | { |
18 | friend class Bu::Singleton<Bu::Random>; | 18 | friend class Bu::Singleton<Bu::Random>; |
19 | private: | 19 | private: |
20 | Random(); | 20 | Random(); |
21 | virtual ~Random(); | 21 | virtual ~Random(); |
22 | 22 | ||
23 | public: | 23 | public: |
24 | template<typename cl> | 24 | template<typename cl> |
25 | static void setGenerator() | 25 | static void setGenerator() |
26 | { | 26 | { |
27 | delete getInstance().pGen; | 27 | delete getInstance().pGen; |
28 | getInstance().pGen = new cl(); | 28 | getInstance().pGen = new cl(); |
29 | } | 29 | } |
30 | 30 | ||
31 | template<typename cl, typename t1> | 31 | template<typename cl, typename t1> |
32 | static void setGenerator( t1 p1 ) | 32 | static void setGenerator( t1 p1 ) |
33 | { | 33 | { |
34 | delete getInstance().pGen; | 34 | delete getInstance().pGen; |
35 | getInstance().pGen = new cl( p1 ); | 35 | getInstance().pGen = new cl( p1 ); |
36 | } | 36 | } |
37 | 37 | ||
38 | template<typename cl, typename t1, typename t2> | 38 | template<typename cl, typename t1, typename t2> |
39 | static void setGenerator( t1 p1, t2 p2 ) | 39 | static void setGenerator( t1 p1, t2 p2 ) |
40 | { | 40 | { |
41 | delete getInstance().pGen; | 41 | delete getInstance().pGen; |
42 | getInstance().pGen = new cl( p1, p2 ); | 42 | getInstance().pGen = new cl( p1, p2 ); |
43 | } | 43 | } |
44 | 44 | ||
45 | RandomBase &getGenerator() { return *pGen; } | 45 | RandomBase &getGenerator() { return *pGen; } |
46 | 46 | ||
47 | static void seed( int32_t iSeed ); | 47 | static void seed( int32_t iSeed ); |
48 | static int32_t rand(); | 48 | static int32_t rand(); |
49 | static int32_t rand( int32_t iMax ); | 49 | static int32_t rand( int32_t iMax ); |
50 | static int32_t rand( int32_t iMin, int32_t iMax ); | 50 | static int32_t rand( int32_t iMin, int32_t iMax ); |
51 | static double randNorm(); | 51 | static double randNorm(); |
52 | 52 | ||
53 | private: | 53 | private: |
54 | void checkInit(); | 54 | void checkInit(); |
55 | 55 | ||
56 | private: | 56 | private: |
57 | Bu::RandomBase *pGen; | 57 | Bu::RandomBase *pGen; |
58 | }; | 58 | }; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | #endif | 61 | #endif |
diff --git a/src/stable/randombase.h b/src/stable/randombase.h index d33bb99..946284f 100644 --- a/src/stable/randombase.h +++ b/src/stable/randombase.h | |||
@@ -11,25 +11,25 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomBase | 14 | class RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomBase(); | 17 | RandomBase(); |
18 | virtual ~RandomBase(); | 18 | virtual ~RandomBase(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed )=0; | 20 | virtual void seed( int32_t iSeed )=0; |
21 | virtual int32_t rand()=0; | 21 | virtual int32_t rand()=0; |
22 | virtual inline int32_t rand( int32_t iMax ) { | 22 | virtual inline int32_t rand( int32_t iMax ) { |
23 | return rand( 0, iMax ); | 23 | return rand( 0, iMax ); |
24 | } | 24 | } |
25 | virtual inline int32_t rand( int32_t iMin, int32_t iMax ) { | 25 | virtual inline int32_t rand( int32_t iMin, int32_t iMax ) { |
26 | return iMin+(randNorm()*(iMax-iMin)); | 26 | return iMin+(randNorm()*(iMax-iMin)); |
27 | } | 27 | } |
28 | virtual inline double randNorm() { | 28 | virtual inline double randNorm() { |
29 | return (((uint32_t)rand())&0xfffffffeul)*0x1.00000001p-32; | 29 | return (((uint32_t)rand())&0xfffffffeul)*0x1.00000001p-32; |
30 | // return (((uint32_t)rand())&0xfffffffeul)/(double)(0xfffffffful); | 30 | // return (((uint32_t)rand())&0xfffffffeul)/(double)(0xfffffffful); |
31 | } | 31 | } |
32 | }; | 32 | }; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #endif | 35 | #endif |
diff --git a/src/stable/randombasic.cpp b/src/stable/randombasic.cpp index 89e2780..e253b70 100644 --- a/src/stable/randombasic.cpp +++ b/src/stable/randombasic.cpp | |||
@@ -8,9 +8,9 @@ | |||
8 | #include "bu/randombasic.h" | 8 | #include "bu/randombasic.h" |
9 | 9 | ||
10 | Bu::RandomBasic::RandomBasic() : | 10 | Bu::RandomBasic::RandomBasic() : |
11 | a( 6364136223846793005ll ), | 11 | a( 6364136223846793005ll ), |
12 | c( 1442695040888963407ll ), | 12 | c( 1442695040888963407ll ), |
13 | x( 0 ) | 13 | x( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,12 +20,12 @@ Bu::RandomBasic::~RandomBasic() | |||
20 | 20 | ||
21 | void Bu::RandomBasic::seed( int32_t iSeed ) | 21 | void Bu::RandomBasic::seed( int32_t iSeed ) |
22 | { | 22 | { |
23 | c = iSeed; | 23 | c = iSeed; |
24 | } | 24 | } |
25 | 25 | ||
26 | int32_t Bu::RandomBasic::rand() | 26 | int32_t Bu::RandomBasic::rand() |
27 | { | 27 | { |
28 | x = (a*x + c); | 28 | x = (a*x + c); |
29 | return (int32_t)x; | 29 | return (int32_t)x; |
30 | } | 30 | } |
31 | 31 | ||
diff --git a/src/stable/randombasic.h b/src/stable/randombasic.h index a53e16f..4d1c2f8 100644 --- a/src/stable/randombasic.h +++ b/src/stable/randombasic.h | |||
@@ -11,19 +11,19 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomBasic : public RandomBase | 14 | class RandomBasic : public RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomBasic(); | 17 | RandomBasic(); |
18 | virtual ~RandomBasic(); | 18 | virtual ~RandomBasic(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed ); | 20 | virtual void seed( int32_t iSeed ); |
21 | 21 | ||
22 | virtual int32_t rand(); | 22 | virtual int32_t rand(); |
23 | 23 | ||
24 | private: | 24 | private: |
25 | int64_t a, c, x; | 25 | int64_t a, c, x; |
26 | }; | 26 | }; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/randomcmwc.cpp b/src/stable/randomcmwc.cpp index 9f68982..1d4a913 100644 --- a/src/stable/randomcmwc.cpp +++ b/src/stable/randomcmwc.cpp | |||
@@ -12,52 +12,52 @@ | |||
12 | #define PHI 0x9e3779b9 | 12 | #define PHI 0x9e3779b9 |
13 | 13 | ||
14 | Bu::RandomCmwc::RandomCmwc() : | 14 | Bu::RandomCmwc::RandomCmwc() : |
15 | q( 0 ), | 15 | q( 0 ), |
16 | c( 362436 ) | 16 | c( 362436 ) |
17 | { | 17 | { |
18 | q = new uint32_t[4096]; | 18 | q = new uint32_t[4096]; |
19 | } | 19 | } |
20 | 20 | ||
21 | Bu::RandomCmwc::~RandomCmwc() | 21 | Bu::RandomCmwc::~RandomCmwc() |
22 | { | 22 | { |
23 | delete[] q; | 23 | delete[] q; |
24 | } | 24 | } |
25 | 25 | ||
26 | void Bu::RandomCmwc::seed( int32_t iSeed ) | 26 | void Bu::RandomCmwc::seed( int32_t iSeed ) |
27 | { | 27 | { |
28 | i = 4095; | 28 | i = 4095; |
29 | c = 362436; | 29 | c = 362436; |
30 | 30 | ||
31 | Bu::RandomBasic rb; | 31 | Bu::RandomBasic rb; |
32 | rb.seed( iSeed ); | 32 | rb.seed( iSeed ); |
33 | 33 | ||
34 | for( int j = 0; j < 4096; j++ ) | 34 | for( int j = 0; j < 4096; j++ ) |
35 | q[j] = rb.rand(); | 35 | q[j] = rb.rand(); |
36 | 36 | ||
37 | c = rb.rand(); | 37 | c = rb.rand(); |
38 | 38 | ||
39 | return; | 39 | return; |
40 | q[0] = (uint32_t)rb.rand(); | 40 | q[0] = (uint32_t)rb.rand(); |
41 | q[1] = (uint32_t)rb.rand() + PHI; | 41 | q[1] = (uint32_t)rb.rand() + PHI; |
42 | q[2] = (uint32_t)rb.rand() + PHI + PHI; | 42 | q[2] = (uint32_t)rb.rand() + PHI + PHI; |
43 | 43 | ||
44 | for (int j = 3; j < 4096; j++) | 44 | for (int j = 3; j < 4096; j++) |
45 | q[j] = q[j - 3] ^ q[j - 2] ^ PHI ^ j; | 45 | q[j] = q[j - 3] ^ q[j - 2] ^ PHI ^ j; |
46 | } | 46 | } |
47 | 47 | ||
48 | int32_t Bu::RandomCmwc::rand() | 48 | int32_t Bu::RandomCmwc::rand() |
49 | { | 49 | { |
50 | uint64_t t, a = 18782LL; | 50 | uint64_t t, a = 18782LL; |
51 | uint32_t x, r = 0xfffffffe; | 51 | uint32_t x, r = 0xfffffffe; |
52 | i = (i + 1) & 4095; | 52 | i = (i + 1) & 4095; |
53 | t = a * q[i] + c; | 53 | t = a * q[i] + c; |
54 | c = (t >> 32); | 54 | c = (t >> 32); |
55 | x = t + c; | 55 | x = t + c; |
56 | if( x < c ) | 56 | if( x < c ) |
57 | { | 57 | { |
58 | x++; | 58 | x++; |
59 | c++; | 59 | c++; |
60 | } | 60 | } |
61 | return (q[i] = r - x); | 61 | return (q[i] = r - x); |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/src/stable/randomcmwc.h b/src/stable/randomcmwc.h index fff891b..547b5bb 100644 --- a/src/stable/randomcmwc.h +++ b/src/stable/randomcmwc.h | |||
@@ -11,19 +11,19 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomCmwc : public RandomBase | 14 | class RandomCmwc : public RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomCmwc(); | 17 | RandomCmwc(); |
18 | virtual ~RandomCmwc(); | 18 | virtual ~RandomCmwc(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed ); | 20 | virtual void seed( int32_t iSeed ); |
21 | 21 | ||
22 | virtual int32_t rand(); | 22 | virtual int32_t rand(); |
23 | 23 | ||
24 | private: | 24 | private: |
25 | uint32_t *q, c, i; | 25 | uint32_t *q, c, i; |
26 | }; | 26 | }; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/randomsystem.cpp b/src/stable/randomsystem.cpp index 0501587..68c69d5 100644 --- a/src/stable/randomsystem.cpp +++ b/src/stable/randomsystem.cpp | |||
@@ -2,39 +2,39 @@ | |||
2 | #include "bu/file.h" | 2 | #include "bu/file.h" |
3 | 3 | ||
4 | Bu::RandomSystem::RandomSystem( Type eType ) : | 4 | Bu::RandomSystem::RandomSystem( Type eType ) : |
5 | eType( eType ), | 5 | eType( eType ), |
6 | pSrc( 0 ) | 6 | pSrc( 0 ) |
7 | { | 7 | { |
8 | switch( eType ) | 8 | switch( eType ) |
9 | { | 9 | { |
10 | case Bu::RandomSystem::Fast: | 10 | case Bu::RandomSystem::Fast: |
11 | pSrc = new Bu::File("/dev/urandom", Bu::File::Read ); | 11 | pSrc = new Bu::File("/dev/urandom", Bu::File::Read ); |
12 | break; | 12 | break; |
13 | 13 | ||
14 | case Bu::RandomSystem::Good: | 14 | case Bu::RandomSystem::Good: |
15 | pSrc = new Bu::File("/dev/random", Bu::File::Read ); | 15 | pSrc = new Bu::File("/dev/random", Bu::File::Read ); |
16 | break; | 16 | break; |
17 | } | 17 | } |
18 | } | 18 | } |
19 | 19 | ||
20 | Bu::RandomSystem::~RandomSystem() | 20 | Bu::RandomSystem::~RandomSystem() |
21 | { | 21 | { |
22 | delete pSrc; | 22 | delete pSrc; |
23 | } | 23 | } |
24 | 24 | ||
25 | void Bu::RandomSystem::seed( int32_t /*iSeed*/ ) | 25 | void Bu::RandomSystem::seed( int32_t /*iSeed*/ ) |
26 | { | 26 | { |
27 | // Seed really has no effect here... | 27 | // Seed really has no effect here... |
28 | // on linux, if we were root, we could write data to random/urandom to | 28 | // on linux, if we were root, we could write data to random/urandom to |
29 | // perturb the data, but it's not necesarry | 29 | // perturb the data, but it's not necesarry |
30 | } | 30 | } |
31 | 31 | ||
32 | int32_t Bu::RandomSystem::rand() | 32 | int32_t Bu::RandomSystem::rand() |
33 | { | 33 | { |
34 | if( !pSrc ) | 34 | if( !pSrc ) |
35 | throw Bu::ExceptionBase("Not initialized"); | 35 | throw Bu::ExceptionBase("Not initialized"); |
36 | int32_t i; | 36 | int32_t i; |
37 | pSrc->read( &i, sizeof(int32_t) ); | 37 | pSrc->read( &i, sizeof(int32_t) ); |
38 | return i; | 38 | return i; |
39 | } | 39 | } |
40 | 40 | ||
diff --git a/src/stable/randomsystem.h b/src/stable/randomsystem.h index 7106d58..63b40f3 100644 --- a/src/stable/randomsystem.h +++ b/src/stable/randomsystem.h | |||
@@ -11,27 +11,27 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class File; | 14 | class File; |
15 | class RandomSystem : public RandomBase | 15 | class RandomSystem : public RandomBase |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | enum Type | 18 | enum Type |
19 | { | 19 | { |
20 | Fast, | 20 | Fast, |
21 | Good | 21 | Good |
22 | }; | 22 | }; |
23 | 23 | ||
24 | RandomSystem( Type eType=Fast ); | 24 | RandomSystem( Type eType=Fast ); |
25 | virtual ~RandomSystem(); | 25 | virtual ~RandomSystem(); |
26 | 26 | ||
27 | virtual void seed( int32_t iSeed ); | 27 | virtual void seed( int32_t iSeed ); |
28 | 28 | ||
29 | virtual int32_t rand(); | 29 | virtual int32_t rand(); |
30 | 30 | ||
31 | private: | 31 | private: |
32 | Type eType; | 32 | Type eType; |
33 | File *pSrc; | 33 | File *pSrc; |
34 | }; | 34 | }; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | #endif | 37 | #endif |
diff --git a/src/stable/ringbuffer.h b/src/stable/ringbuffer.h index 79c5a15..39d053e 100644 --- a/src/stable/ringbuffer.h +++ b/src/stable/ringbuffer.h | |||
@@ -15,237 +15,237 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | template<typename value, typename valuealloc> class RingBuffer; | 18 | template<typename value, typename valuealloc> class RingBuffer; |
19 | 19 | ||
20 | /** @cond DEVEL */ | 20 | /** @cond DEVEL */ |
21 | template<typename value, typename valuealloc> | 21 | template<typename value, typename valuealloc> |
22 | class RingBufferCore | 22 | class RingBufferCore |
23 | { | 23 | { |
24 | friend class RingBuffer<value, valuealloc>; | 24 | friend class RingBuffer<value, valuealloc>; |
25 | friend class SharedCore<RingBuffer<value, valuealloc>, | 25 | friend class SharedCore<RingBuffer<value, valuealloc>, |
26 | RingBufferCore<value, valuealloc> >; | 26 | RingBufferCore<value, valuealloc> >; |
27 | private: | 27 | private: |
28 | RingBufferCore() : | 28 | RingBufferCore() : |
29 | iCapacity( 0 ), | 29 | iCapacity( 0 ), |
30 | iStart( -1 ), | 30 | iStart( -1 ), |
31 | iEnd( -2 ), | 31 | iEnd( -2 ), |
32 | aData( NULL ) | 32 | aData( NULL ) |
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
36 | virtual ~RingBufferCore() | 36 | virtual ~RingBufferCore() |
37 | { | 37 | { |
38 | clear(); | 38 | clear(); |
39 | } | 39 | } |
40 | 40 | ||
41 | void init( int iNewCapacity ) | 41 | void init( int iNewCapacity ) |
42 | { | 42 | { |
43 | if( iCapacity > 0 ) | 43 | if( iCapacity > 0 ) |
44 | return; | 44 | return; |
45 | 45 | ||
46 | iCapacity = iNewCapacity; | 46 | iCapacity = iNewCapacity; |
47 | iStart = -1; | 47 | iStart = -1; |
48 | iEnd = -2; | 48 | iEnd = -2; |
49 | aData = va.allocate( iCapacity ); | 49 | aData = va.allocate( iCapacity ); |
50 | } | 50 | } |
51 | 51 | ||
52 | void clear() | 52 | void clear() |
53 | { | 53 | { |
54 | for( int j = iStart; j < iEnd; j=(j+1%iCapacity) ) | 54 | for( int j = iStart; j < iEnd; j=(j+1%iCapacity) ) |
55 | { | 55 | { |
56 | va.destroy( &aData[j] ); | 56 | va.destroy( &aData[j] ); |
57 | } | 57 | } |
58 | va.deallocate( aData, iCapacity ); | 58 | va.deallocate( aData, iCapacity ); |
59 | aData = NULL; | 59 | aData = NULL; |
60 | iCapacity = 0; | 60 | iCapacity = 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | void enqueue( const value &v ) | 63 | void enqueue( const value &v ) |
64 | { | 64 | { |
65 | if( iStart == -1 ) | 65 | if( iStart == -1 ) |
66 | { | 66 | { |
67 | iStart = 0; | 67 | iStart = 0; |
68 | iEnd = 1; | 68 | iEnd = 1; |
69 | va.construct( &aData[0], v ); | 69 | va.construct( &aData[0], v ); |
70 | return; | 70 | return; |
71 | } | 71 | } |
72 | else if( iStart == iEnd ) | 72 | else if( iStart == iEnd ) |
73 | { | 73 | { |
74 | // The ringbuffer is full | 74 | // The ringbuffer is full |
75 | dequeue(); | 75 | dequeue(); |
76 | } | 76 | } |
77 | va.construct( &aData[iEnd], v ); | 77 | va.construct( &aData[iEnd], v ); |
78 | iEnd = (iEnd+1)%iCapacity; | 78 | iEnd = (iEnd+1)%iCapacity; |
79 | } | 79 | } |
80 | 80 | ||
81 | value dequeue() | 81 | value dequeue() |
82 | { | 82 | { |
83 | if( iStart == -1 ) | 83 | if( iStart == -1 ) |
84 | { | 84 | { |
85 | throw ExceptionBase("No data"); | 85 | throw ExceptionBase("No data"); |
86 | } | 86 | } |
87 | else | 87 | else |
88 | { | 88 | { |
89 | value &v = aData[iStart]; | 89 | value &v = aData[iStart]; |
90 | va.destroy( &aData[iStart] ); | 90 | va.destroy( &aData[iStart] ); |
91 | iStart = (iStart+1)%iCapacity; | 91 | iStart = (iStart+1)%iCapacity; |
92 | if( iStart == iEnd ) | 92 | if( iStart == iEnd ) |
93 | { | 93 | { |
94 | iStart = -1; | 94 | iStart = -1; |
95 | iEnd = -2; | 95 | iEnd = -2; |
96 | } | 96 | } |
97 | return v; | 97 | return v; |
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | value &get( int iIndex ) | 101 | value &get( int iIndex ) |
102 | { | 102 | { |
103 | return aData[(iIndex+iStart)%iCapacity]; | 103 | return aData[(iIndex+iStart)%iCapacity]; |
104 | } | 104 | } |
105 | 105 | ||
106 | value &first() | 106 | value &first() |
107 | { | 107 | { |
108 | return aData[iStart]; | 108 | return aData[iStart]; |
109 | } | 109 | } |
110 | 110 | ||
111 | value &last() | 111 | value &last() |
112 | { | 112 | { |
113 | return aData[(iEnd-1+iCapacity)%iCapacity]; | 113 | return aData[(iEnd-1+iCapacity)%iCapacity]; |
114 | } | 114 | } |
115 | 115 | ||
116 | int getSize() | 116 | int getSize() |
117 | { | 117 | { |
118 | if( iStart < 0 ) | 118 | if( iStart < 0 ) |
119 | return 0; | 119 | return 0; |
120 | if( iEnd == iStart ) | 120 | if( iEnd == iStart ) |
121 | return iCapacity; | 121 | return iCapacity; |
122 | if( iEnd < iStart ) | 122 | if( iEnd < iStart ) |
123 | return iEnd-iStart; | 123 | return iEnd-iStart; |
124 | return iCapacity-(iEnd-iStart); | 124 | return iCapacity-(iEnd-iStart); |
125 | } | 125 | } |
126 | 126 | ||
127 | int iCapacity; | 127 | int iCapacity; |
128 | int iStart, iEnd; | 128 | int iStart, iEnd; |
129 | value *aData; | 129 | value *aData; |
130 | valuealloc va; | 130 | valuealloc va; |
131 | }; | 131 | }; |
132 | /** @endcond */ | 132 | /** @endcond */ |
133 | 133 | ||
134 | /** | 134 | /** |
135 | *@ingroup Containers | 135 | *@ingroup Containers |
136 | */ | 136 | */ |
137 | template<typename value, typename valuealloc=std::allocator<value> > | 137 | template<typename value, typename valuealloc=std::allocator<value> > |
138 | class RingBuffer : public Queue<value>, public SharedCore< | 138 | class RingBuffer : public Queue<value>, public SharedCore< |
139 | RingBuffer<value, valuealloc>, | 139 | RingBuffer<value, valuealloc>, |
140 | RingBufferCore<value, valuealloc> | 140 | RingBufferCore<value, valuealloc> |
141 | > | 141 | > |
142 | { | 142 | { |
143 | private: | 143 | private: |
144 | typedef RingBuffer<value, valuealloc> MyType; | 144 | typedef RingBuffer<value, valuealloc> MyType; |
145 | typedef RingBufferCore<value, valuealloc> Core; | 145 | typedef RingBufferCore<value, valuealloc> Core; |
146 | 146 | ||
147 | protected: | 147 | protected: |
148 | using SharedCore<MyType, Core>::core; | 148 | using SharedCore<MyType, Core>::core; |
149 | using SharedCore<MyType, Core>::_hardCopy; | 149 | using SharedCore<MyType, Core>::_hardCopy; |
150 | using SharedCore<MyType, Core>::_allocateCore; | 150 | using SharedCore<MyType, Core>::_allocateCore; |
151 | 151 | ||
152 | public: | 152 | public: |
153 | RingBuffer( int iCapacity ) | 153 | RingBuffer( int iCapacity ) |
154 | { | 154 | { |
155 | core->init( iCapacity ); | 155 | core->init( iCapacity ); |
156 | } | 156 | } |
157 | 157 | ||
158 | RingBuffer( const RingBuffer &rSrc ) : | 158 | RingBuffer( const RingBuffer &rSrc ) : |
159 | SharedCore<MyType, Core>( rSrc ) | 159 | SharedCore<MyType, Core>( rSrc ) |
160 | { | 160 | { |
161 | } | 161 | } |
162 | 162 | ||
163 | virtual ~RingBuffer() | 163 | virtual ~RingBuffer() |
164 | { | 164 | { |
165 | } | 165 | } |
166 | 166 | ||
167 | int getCapacity() const | 167 | int getCapacity() const |
168 | { | 168 | { |
169 | return core->iCapacity; | 169 | return core->iCapacity; |
170 | } | 170 | } |
171 | 171 | ||
172 | bool isFilled() const | 172 | bool isFilled() const |
173 | { | 173 | { |
174 | return (core->iStart == core->iEnd); | 174 | return (core->iStart == core->iEnd); |
175 | } | 175 | } |
176 | 176 | ||
177 | bool isEmpty() const | 177 | bool isEmpty() const |
178 | { | 178 | { |
179 | return (core->iStart == -1); | 179 | return (core->iStart == -1); |
180 | } | 180 | } |
181 | 181 | ||
182 | virtual void enqueue( const value &v ) | 182 | virtual void enqueue( const value &v ) |
183 | { | 183 | { |
184 | _hardCopy(); | 184 | _hardCopy(); |
185 | 185 | ||
186 | core->enqueue( v ); | 186 | core->enqueue( v ); |
187 | } | 187 | } |
188 | 188 | ||
189 | virtual value dequeue() | 189 | virtual value dequeue() |
190 | { | 190 | { |
191 | _hardCopy(); | 191 | _hardCopy(); |
192 | 192 | ||
193 | return core->dequeue(); | 193 | return core->dequeue(); |
194 | } | 194 | } |
195 | 195 | ||
196 | virtual int getSize() const | 196 | virtual int getSize() const |
197 | { | 197 | { |
198 | return core->getSize(); | 198 | return core->getSize(); |
199 | } | 199 | } |
200 | 200 | ||
201 | virtual value &peek() | 201 | virtual value &peek() |
202 | { | 202 | { |
203 | _hardCopy(); | 203 | _hardCopy(); |
204 | 204 | ||
205 | return core->get( 0 ); | 205 | return core->get( 0 ); |
206 | } | 206 | } |
207 | 207 | ||
208 | virtual const value &peek() const | 208 | virtual const value &peek() const |
209 | { | 209 | { |
210 | return core->get( 0 ); | 210 | return core->get( 0 ); |
211 | } | 211 | } |
212 | 212 | ||
213 | virtual value &first() | 213 | virtual value &first() |
214 | { | 214 | { |
215 | _hardCopy(); | 215 | _hardCopy(); |
216 | 216 | ||
217 | return core->first(); | 217 | return core->first(); |
218 | } | 218 | } |
219 | 219 | ||
220 | virtual value &last() | 220 | virtual value &last() |
221 | { | 221 | { |
222 | _hardCopy(); | 222 | _hardCopy(); |
223 | 223 | ||
224 | return core->last(); | 224 | return core->last(); |
225 | } | 225 | } |
226 | 226 | ||
227 | value &operator[]( int iIndex ) | 227 | value &operator[]( int iIndex ) |
228 | { | 228 | { |
229 | _hardCopy(); | 229 | _hardCopy(); |
230 | 230 | ||
231 | return core->get( iIndex ); | 231 | return core->get( iIndex ); |
232 | } | 232 | } |
233 | 233 | ||
234 | protected: | 234 | protected: |
235 | virtual Core *_copyCore( Core *src ) | 235 | virtual Core *_copyCore( Core *src ) |
236 | { | 236 | { |
237 | Core *pRet = _allocateCore(); | 237 | Core *pRet = _allocateCore(); |
238 | 238 | ||
239 | pRet->init( src->iCapacity ); | 239 | pRet->init( src->iCapacity ); |
240 | int iSize = src->getSize(); | 240 | int iSize = src->getSize(); |
241 | for( int j = 0; j < iSize; j++ ) | 241 | for( int j = 0; j < iSize; j++ ) |
242 | { | 242 | { |
243 | pRet->enqueue( src->get( j ) ); | 243 | pRet->enqueue( src->get( j ) ); |
244 | } | 244 | } |
245 | 245 | ||
246 | return pRet; | 246 | return pRet; |
247 | } | 247 | } |
248 | }; | 248 | }; |
249 | } | 249 | } |
250 | 250 | ||
251 | #endif | 251 | #endif |
diff --git a/src/stable/server.cpp b/src/stable/server.cpp index 39ff7bb..e6c256e 100644 --- a/src/stable/server.cpp +++ b/src/stable/server.cpp | |||
@@ -14,138 +14,138 @@ | |||
14 | #include "bu/config.h" | 14 | #include "bu/config.h" |
15 | 15 | ||
16 | Bu::Server::Server() : | 16 | Bu::Server::Server() : |
17 | nTimeoutSec( 0 ), | 17 | nTimeoutSec( 0 ), |
18 | nTimeoutUSec( 0 ), | 18 | nTimeoutUSec( 0 ), |
19 | bAutoTick( false ) | 19 | bAutoTick( false ) |
20 | { | 20 | { |
21 | FD_ZERO( &fdActive ); | 21 | FD_ZERO( &fdActive ); |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::Server::~Server() | 24 | Bu::Server::~Server() |
25 | { | 25 | { |
26 | shutdown(); | 26 | shutdown(); |
27 | } | 27 | } |
28 | 28 | ||
29 | void Bu::Server::addPort( int nPort, int nPoolSize ) | 29 | void Bu::Server::addPort( int nPort, int nPoolSize ) |
30 | { | 30 | { |
31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); | 31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); |
32 | socket_t nSocket = s->getSocket(); | 32 | socket_t nSocket = s->getSocket(); |
33 | FD_SET( nSocket, &fdActive ); | 33 | FD_SET( nSocket, &fdActive ); |
34 | hServers.insert( nSocket, s ); | 34 | hServers.insert( nSocket, s ); |
35 | } | 35 | } |
36 | 36 | ||
37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) | 37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) |
38 | { | 38 | { |
39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); | 39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); |
40 | socket_t nSocket = s->getSocket(); | 40 | socket_t nSocket = s->getSocket(); |
41 | FD_SET( nSocket, &fdActive ); | 41 | FD_SET( nSocket, &fdActive ); |
42 | hServers.insert( nSocket, s ); | 42 | hServers.insert( nSocket, s ); |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) | 45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) |
46 | { | 46 | { |
47 | this->nTimeoutSec = nTimeoutSec; | 47 | this->nTimeoutSec = nTimeoutSec; |
48 | this->nTimeoutUSec = nTimeoutUSec; | 48 | this->nTimeoutUSec = nTimeoutUSec; |
49 | } | 49 | } |
50 | 50 | ||
51 | void Bu::Server::scan() | 51 | void Bu::Server::scan() |
52 | { | 52 | { |
53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; | 53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; |
54 | 54 | ||
55 | fd_set fdRead = fdActive; | 55 | fd_set fdRead = fdActive; |
56 | fd_set fdWrite /* = fdActive*/; | 56 | fd_set fdWrite /* = fdActive*/; |
57 | fd_set fdException = fdActive; | 57 | fd_set fdException = fdActive; |
58 | 58 | ||
59 | FD_ZERO( &fdWrite ); | 59 | FD_ZERO( &fdWrite ); |
60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
61 | { | 61 | { |
62 | if( (*i)->hasOutput() ) | 62 | if( (*i)->hasOutput() ) |
63 | FD_SET( i.getKey(), &fdWrite ); | 63 | FD_SET( i.getKey(), &fdWrite ); |
64 | } | 64 | } |
65 | 65 | ||
66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, | 66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, |
67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) | 67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) |
68 | { | 68 | { |
69 | throw ExceptionBase("Error attempting to scan open connections."); | 69 | throw ExceptionBase("Error attempting to scan open connections."); |
70 | } | 70 | } |
71 | 71 | ||
72 | for( int j = 0; j < FD_SETSIZE; j++ ) | 72 | for( int j = 0; j < FD_SETSIZE; j++ ) |
73 | { | 73 | { |
74 | if( FD_ISSET( j, &fdRead ) ) | 74 | if( FD_ISSET( j, &fdRead ) ) |
75 | { | 75 | { |
76 | if( hServers.has( j ) ) | 76 | if( hServers.has( j ) ) |
77 | { | 77 | { |
78 | TcpServerSocket *pSrv = hServers.get( j ); | 78 | TcpServerSocket *pSrv = hServers.get( j ); |
79 | addClient( pSrv->accept(), pSrv->getPort() ); | 79 | addClient( pSrv->accept(), pSrv->getPort() ); |
80 | } | 80 | } |
81 | else | 81 | else |
82 | { | 82 | { |
83 | Client *pClient = hClients.get( j ); | 83 | Client *pClient = hClients.get( j ); |
84 | pClient->processInput(); | 84 | pClient->processInput(); |
85 | if( !pClient->isOpen() ) | 85 | if( !pClient->isOpen() ) |
86 | { | 86 | { |
87 | closeClient( j ); | 87 | closeClient( j ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | } | 90 | } |
91 | if( FD_ISSET( j, &fdWrite ) ) | 91 | if( FD_ISSET( j, &fdWrite ) ) |
92 | { | 92 | { |
93 | try | 93 | try |
94 | { | 94 | { |
95 | Client *pClient = hClients.get( j ); | 95 | Client *pClient = hClients.get( j ); |
96 | try | 96 | try |
97 | { | 97 | { |
98 | pClient->processOutput(); | 98 | pClient->processOutput(); |
99 | } | 99 | } |
100 | catch( Bu::TcpSocketException &e ) | 100 | catch( Bu::TcpSocketException &e ) |
101 | { | 101 | { |
102 | closeClient( j ); | 102 | closeClient( j ); |
103 | } | 103 | } |
104 | } | 104 | } |
105 | catch( Bu::HashException &e ) | 105 | catch( Bu::HashException &e ) |
106 | { | 106 | { |
107 | // Do nothing, I guess, the client is already dead... | 107 | // Do nothing, I guess, the client is already dead... |
108 | // TODO: Someday, we may want to handle this more graceully. | 108 | // TODO: Someday, we may want to handle this more graceully. |
109 | } | 109 | } |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | Bu::List<int> lDelete; | 113 | Bu::List<int> lDelete; |
114 | // Now we just try to write all the pending data on all the sockets. | 114 | // Now we just try to write all the pending data on all the sockets. |
115 | // this could be done better eventually, if we care about the socket | 115 | // this could be done better eventually, if we care about the socket |
116 | // wanting to accept writes (using a select). | 116 | // wanting to accept writes (using a select). |
117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
118 | { | 118 | { |
119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) | 119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) |
120 | { | 120 | { |
121 | lDelete.append( i.getKey() ); | 121 | lDelete.append( i.getKey() ); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) | 125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) |
126 | { | 126 | { |
127 | closeClient( *i ); | 127 | closeClient( *i ); |
128 | } | 128 | } |
129 | 129 | ||
130 | if( bAutoTick ) | 130 | if( bAutoTick ) |
131 | tick(); | 131 | tick(); |
132 | } | 132 | } |
133 | 133 | ||
134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) | 134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) |
135 | { | 135 | { |
136 | FD_SET( nSocket, &fdActive ); | 136 | FD_SET( nSocket, &fdActive ); |
137 | 137 | ||
138 | Client *c = new Client( | 138 | Client *c = new Client( |
139 | new Bu::TcpSocket( nSocket ), | 139 | new Bu::TcpSocket( nSocket ), |
140 | new SrvClientLinkFactory() | 140 | new SrvClientLinkFactory() |
141 | ); | 141 | ); |
142 | hClients.insert( nSocket, c ); | 142 | hClients.insert( nSocket, c ); |
143 | 143 | ||
144 | onNewConnection( c, nPort ); | 144 | onNewConnection( c, nPort ); |
145 | } | 145 | } |
146 | 146 | ||
147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : | 147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : |
148 | pClient( pClient ) | 148 | pClient( pClient ) |
149 | { | 149 | { |
150 | } | 150 | } |
151 | 151 | ||
@@ -155,7 +155,7 @@ Bu::Server::SrvClientLink::~SrvClientLink() | |||
155 | 155 | ||
156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) | 156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) |
157 | { | 157 | { |
158 | pClient->onMessage( sMsg ); | 158 | pClient->onMessage( sMsg ); |
159 | } | 159 | } |
160 | 160 | ||
161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() | 161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() |
@@ -167,48 +167,48 @@ Bu::Server::SrvClientLinkFactory::~SrvClientLinkFactory() | |||
167 | } | 167 | } |
168 | 168 | ||
169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( | 169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( |
170 | Bu::Client *pClient ) | 170 | Bu::Client *pClient ) |
171 | { | 171 | { |
172 | return new SrvClientLink( pClient ); | 172 | return new SrvClientLink( pClient ); |
173 | } | 173 | } |
174 | 174 | ||
175 | void Bu::Server::setAutoTick( bool bEnable ) | 175 | void Bu::Server::setAutoTick( bool bEnable ) |
176 | { | 176 | { |
177 | bAutoTick = bEnable; | 177 | bAutoTick = bEnable; |
178 | } | 178 | } |
179 | 179 | ||
180 | void Bu::Server::tick() | 180 | void Bu::Server::tick() |
181 | { | 181 | { |
182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
183 | { | 183 | { |
184 | (*i)->tick(); | 184 | (*i)->tick(); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | void Bu::Server::shutdown() | 188 | void Bu::Server::shutdown() |
189 | { | 189 | { |
190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) | 190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) |
191 | { | 191 | { |
192 | delete *i; | 192 | delete *i; |
193 | } | 193 | } |
194 | 194 | ||
195 | hServers.clear(); | 195 | hServers.clear(); |
196 | 196 | ||
197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
198 | { | 198 | { |
199 | closeClient( i.getKey() ); | 199 | closeClient( i.getKey() ); |
200 | } | 200 | } |
201 | 201 | ||
202 | hClients.clear(); | 202 | hClients.clear(); |
203 | } | 203 | } |
204 | 204 | ||
205 | void Bu::Server::closeClient( socket_t iSocket ) | 205 | void Bu::Server::closeClient( socket_t iSocket ) |
206 | { | 206 | { |
207 | Bu::Client *pClient = hClients.get( iSocket ); | 207 | Bu::Client *pClient = hClients.get( iSocket ); |
208 | onClosedConnection( pClient ); | 208 | onClosedConnection( pClient ); |
209 | pClient->close(); | 209 | pClient->close(); |
210 | hClients.erase( iSocket ); | 210 | hClients.erase( iSocket ); |
211 | FD_CLR( iSocket, &fdActive ); | 211 | FD_CLR( iSocket, &fdActive ); |
212 | delete pClient; | 212 | delete pClient; |
213 | } | 213 | } |
214 | 214 | ||
diff --git a/src/stable/server.h b/src/stable/server.h index 5a414d9..05ec018 100644 --- a/src/stable/server.h +++ b/src/stable/server.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" |
@@ -25,90 +25,90 @@ | |||
25 | 25 | ||
26 | namespace Bu | 26 | namespace Bu |
27 | { | 27 | { |
28 | class TcpServerSocket; | 28 | class TcpServerSocket; |
29 | class TcpSocket; | 29 | class TcpSocket; |
30 | class Client; | 30 | class Client; |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * Core of a network server. This class is distinct from a ServerSocket in | 33 | * Core of a network server. This class is distinct from a ServerSocket in |
34 | * that a ServerSocket is one listening socket, nothing more. Socket will | 34 | * that a ServerSocket is one listening socket, nothing more. Socket will |
35 | * manage a pool of both ServerSockets and connected Sockets along with | 35 | * manage a pool of both ServerSockets and connected Sockets along with |
36 | * their protocols and buffers. | 36 | * their protocols and buffers. |
37 | * | 37 | * |
38 | * To start serving on a new port, use the addPort functions. Each call to | 38 | * To start serving on a new port, use the addPort functions. Each call to |
39 | * addPort creates a new ServerSocket, starts it listening, and adds it to | 39 | * addPort creates a new ServerSocket, starts it listening, and adds it to |
40 | * the server pool. | 40 | * the server pool. |
41 | * | 41 | * |
42 | * All of the real work is done by scan, which will wait for up | 42 | * All of the real work is done by scan, which will wait for up |
43 | * to the timeout set by setTimeout before returning if there is no data | 43 | * to the timeout set by setTimeout before returning if there is no data |
44 | * pending. scan should probably be called in some sort of tight | 44 | * pending. scan should probably be called in some sort of tight |
45 | * loop, possibly in it's own thread, or in the main control loop. | 45 | * loop, possibly in it's own thread, or in the main control loop. |
46 | * | 46 | * |
47 | * In order to use a Server you must subclass it and implement the pure | 47 | * In order to use a Server you must subclass it and implement the pure |
48 | * virtual functions. These allow you to receive notification of events | 48 | * virtual functions. These allow you to receive notification of events |
49 | * happening within the server itself, and actually makes it useful. | 49 | * happening within the server itself, and actually makes it useful. |
50 | *@ingroup Serving | 50 | *@ingroup Serving |
51 | */ | 51 | */ |
52 | class Server | 52 | class Server |
53 | { | 53 | { |
54 | public: | 54 | public: |
55 | Server(); | 55 | Server(); |
56 | virtual ~Server(); | 56 | virtual ~Server(); |
57 | 57 | ||
58 | #ifdef WIN32 | 58 | #ifdef WIN32 |
59 | typedef unsigned int socket_t; | 59 | typedef unsigned int socket_t; |
60 | #else | 60 | #else |
61 | typedef int socket_t; | 61 | typedef int socket_t; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | void addPort( int nPort, int nPoolSize=40 ); | 64 | void addPort( int nPort, int nPoolSize=40 ); |
65 | void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); | 65 | void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); |
66 | 66 | ||
67 | virtual void scan(); | 67 | virtual void scan(); |
68 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); | 68 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); |
69 | 69 | ||
70 | void addClient( socket_t nSocket, int nPort ); | 70 | void addClient( socket_t nSocket, int nPort ); |
71 | 71 | ||
72 | void setAutoTick( bool bEnable=true ); | 72 | void setAutoTick( bool bEnable=true ); |
73 | void tick(); | 73 | void tick(); |
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 | void shutdown(); | 78 | void shutdown(); |
79 | 79 | ||
80 | private: | 80 | private: |
81 | void closeClient( socket_t iSocket ); | 81 | void closeClient( socket_t iSocket ); |
82 | class SrvClientLink : public Bu::ClientLink | 82 | class SrvClientLink : public Bu::ClientLink |
83 | { | 83 | { |
84 | public: | 84 | public: |
85 | SrvClientLink( Bu::Client *pClient ); | 85 | SrvClientLink( Bu::Client *pClient ); |
86 | virtual ~SrvClientLink(); | 86 | virtual ~SrvClientLink(); |
87 | 87 | ||
88 | virtual void sendMessage( const Bu::String &sMsg ); | 88 | virtual void sendMessage( const Bu::String &sMsg ); |
89 | 89 | ||
90 | private: | 90 | private: |
91 | Bu::Client *pClient; | 91 | Bu::Client *pClient; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | class SrvClientLinkFactory : public Bu::ClientLinkFactory | 94 | class SrvClientLinkFactory : public Bu::ClientLinkFactory |
95 | { | 95 | { |
96 | public: | 96 | public: |
97 | SrvClientLinkFactory(); | 97 | SrvClientLinkFactory(); |
98 | virtual ~SrvClientLinkFactory(); | 98 | virtual ~SrvClientLinkFactory(); |
99 | 99 | ||
100 | virtual Bu::ClientLink *createLink( Bu::Client *pClient ); | 100 | virtual Bu::ClientLink *createLink( Bu::Client *pClient ); |
101 | }; | 101 | }; |
102 | 102 | ||
103 | int nTimeoutSec; | 103 | int nTimeoutSec; |
104 | int nTimeoutUSec; | 104 | int nTimeoutUSec; |
105 | fd_set fdActive; | 105 | fd_set fdActive; |
106 | typedef Hash<socket_t,TcpServerSocket *> SrvHash; | 106 | typedef Hash<socket_t,TcpServerSocket *> SrvHash; |
107 | SrvHash hServers; | 107 | SrvHash hServers; |
108 | typedef Hash<socket_t,Client *> ClientHash; | 108 | typedef Hash<socket_t,Client *> ClientHash; |
109 | ClientHash hClients; | 109 | ClientHash hClients; |
110 | bool bAutoTick; | 110 | bool bAutoTick; |
111 | }; | 111 | }; |
112 | } | 112 | } |
113 | 113 | ||
114 | #endif | 114 | #endif |
diff --git a/src/stable/sha1.cpp b/src/stable/sha1.cpp index e6a85cc..30e5dc8 100644 --- a/src/stable/sha1.cpp +++ b/src/stable/sha1.cpp | |||
@@ -12,15 +12,15 @@ | |||
12 | #include "bu/sha1.h" | 12 | #include "bu/sha1.h" |
13 | 13 | ||
14 | Bu::Sha1::Sha1() : | 14 | Bu::Sha1::Sha1() : |
15 | uH0( 0x67452301 ), | 15 | uH0( 0x67452301 ), |
16 | uH1( 0xefcdab89 ), | 16 | uH1( 0xefcdab89 ), |
17 | uH2( 0x98badcfe ), | 17 | uH2( 0x98badcfe ), |
18 | uH3( 0x10325476 ), | 18 | uH3( 0x10325476 ), |
19 | uH4( 0xc3d2e1f0 ), | 19 | uH4( 0xc3d2e1f0 ), |
20 | iUnprocessedBytes( 0 ), | 20 | iUnprocessedBytes( 0 ), |
21 | uTotalBytes( 0 ) | 21 | uTotalBytes( 0 ) |
22 | { | 22 | { |
23 | reset(); | 23 | reset(); |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::Sha1::~Sha1() | 26 | Bu::Sha1::~Sha1() |
@@ -29,13 +29,13 @@ Bu::Sha1::~Sha1() | |||
29 | 29 | ||
30 | void Bu::Sha1::reset() | 30 | void Bu::Sha1::reset() |
31 | { | 31 | { |
32 | uH0 = 0x67452301; | 32 | uH0 = 0x67452301; |
33 | uH1 = 0xefcdab89; | 33 | uH1 = 0xefcdab89; |
34 | uH2 = 0x98badcfe; | 34 | uH2 = 0x98badcfe; |
35 | uH3 = 0x10325476; | 35 | uH3 = 0x10325476; |
36 | uH4 = 0xc3d2e1f0; | 36 | uH4 = 0xc3d2e1f0; |
37 | iUnprocessedBytes = 0; | 37 | iUnprocessedBytes = 0; |
38 | uTotalBytes = 0; | 38 | uTotalBytes = 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) | 41 | void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -44,151 +44,151 @@ void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) | |||
44 | 44 | ||
45 | void Bu::Sha1::addData( const void *sDataRaw, int iSize ) | 45 | void Bu::Sha1::addData( const void *sDataRaw, int iSize ) |
46 | { | 46 | { |
47 | const unsigned char *sData = (const unsigned char *)sDataRaw; | 47 | const unsigned char *sData = (const unsigned char *)sDataRaw; |
48 | // add these bytes to the running total | 48 | // add these bytes to the running total |
49 | uTotalBytes += iSize; | 49 | uTotalBytes += iSize; |
50 | 50 | ||
51 | // repeat until all data is processed | 51 | // repeat until all data is processed |
52 | while( iSize > 0 ) | 52 | while( iSize > 0 ) |
53 | { | 53 | { |
54 | // number of bytes required to complete block | 54 | // number of bytes required to complete block |
55 | int iNeeded = 64 - iUnprocessedBytes; | 55 | int iNeeded = 64 - iUnprocessedBytes; |
56 | 56 | ||
57 | // number of bytes to copy (use smaller of two) | 57 | // number of bytes to copy (use smaller of two) |
58 | int iToCopy = (iSize < iNeeded) ? iSize : iNeeded; | 58 | int iToCopy = (iSize < iNeeded) ? iSize : iNeeded; |
59 | 59 | ||
60 | // Copy the bytes | 60 | // Copy the bytes |
61 | memcpy( uBytes + iUnprocessedBytes, sData, iToCopy ); | 61 | memcpy( uBytes + iUnprocessedBytes, sData, iToCopy ); |
62 | 62 | ||
63 | // Bytes have been copied | 63 | // Bytes have been copied |
64 | iSize -= iToCopy; | 64 | iSize -= iToCopy; |
65 | sData += iToCopy; | 65 | sData += iToCopy; |
66 | iUnprocessedBytes += iToCopy; | 66 | iUnprocessedBytes += iToCopy; |
67 | 67 | ||
68 | // there is a full block | 68 | // there is a full block |
69 | if( iUnprocessedBytes == 64 ) | 69 | if( iUnprocessedBytes == 64 ) |
70 | { | 70 | { |
71 | process(); | 71 | process(); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::String Bu::Sha1::getResult() | 76 | Bu::String Bu::Sha1::getResult() |
77 | { | 77 | { |
78 | // save the message size | 78 | // save the message size |
79 | uint32_t totalBitsL = uTotalBytes << 3; | 79 | uint32_t totalBitsL = uTotalBytes << 3; |
80 | uint32_t totalBitsH = uTotalBytes >> 29; | 80 | uint32_t totalBitsH = uTotalBytes >> 29; |
81 | 81 | ||
82 | // add 0x80 to the message | 82 | // add 0x80 to the message |
83 | addData( "\x80", 1 ); | 83 | addData( "\x80", 1 ); |
84 | 84 | ||
85 | unsigned char footer[64] = { | 85 | unsigned char footer[64] = { |
86 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 86 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
87 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 87 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
88 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 88 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
90 | 90 | ||
91 | // block has no room for 8-byte filesize, so finish it | 91 | // block has no room for 8-byte filesize, so finish it |
92 | if( iUnprocessedBytes > 56 ) | 92 | if( iUnprocessedBytes > 56 ) |
93 | addData( (char*)footer, 64 - iUnprocessedBytes); | 93 | addData( (char*)footer, 64 - iUnprocessedBytes); |
94 | 94 | ||
95 | // how many zeros do we need | 95 | // how many zeros do we need |
96 | int iNeededZeros = 56 - iUnprocessedBytes; | 96 | int iNeededZeros = 56 - iUnprocessedBytes; |
97 | 97 | ||
98 | // store file size (in bits) in big-endian format | 98 | // store file size (in bits) in big-endian format |
99 | toBigEndian( totalBitsH, footer + iNeededZeros ); | 99 | toBigEndian( totalBitsH, footer + iNeededZeros ); |
100 | toBigEndian( totalBitsL, footer + iNeededZeros + 4 ); | 100 | toBigEndian( totalBitsL, footer + iNeededZeros + 4 ); |
101 | 101 | ||
102 | // finish the final block | 102 | // finish the final block |
103 | addData( (char*)footer, iNeededZeros + 8 ); | 103 | addData( (char*)footer, iNeededZeros + 8 ); |
104 | 104 | ||
105 | Bu::String sRet( 20 ); | 105 | Bu::String sRet( 20 ); |
106 | 106 | ||
107 | unsigned char *digest = (unsigned char *)sRet.getStr(); | 107 | unsigned char *digest = (unsigned char *)sRet.getStr(); |
108 | 108 | ||
109 | // copy the digest bytes | 109 | // copy the digest bytes |
110 | toBigEndian( uH0, digest ); | 110 | toBigEndian( uH0, digest ); |
111 | toBigEndian( uH1, digest + 4 ); | 111 | toBigEndian( uH1, digest + 4 ); |
112 | toBigEndian( uH2, digest + 8 ); | 112 | toBigEndian( uH2, digest + 8 ); |
113 | toBigEndian( uH3, digest + 12 ); | 113 | toBigEndian( uH3, digest + 12 ); |
114 | toBigEndian( uH4, digest + 16 ); | 114 | toBigEndian( uH4, digest + 16 ); |
115 | 115 | ||
116 | // return the digest | 116 | // return the digest |
117 | return sRet; | 117 | return sRet; |
118 | } | 118 | } |
119 | 119 | ||
120 | void Bu::Sha1::writeResult( Bu::Stream &sOut ) | 120 | void Bu::Sha1::writeResult( Bu::Stream &sOut ) |
121 | { | 121 | { |
122 | sOut.write( getResult() ); | 122 | sOut.write( getResult() ); |
123 | } | 123 | } |
124 | 124 | ||
125 | void Bu::Sha1::process() | 125 | void Bu::Sha1::process() |
126 | { | 126 | { |
127 | int t; | 127 | int t; |
128 | uint32_t a, b, c, d, e, K, f, W[80]; | 128 | uint32_t a, b, c, d, e, K, f, W[80]; |
129 | 129 | ||
130 | // starting values | 130 | // starting values |
131 | a = uH0; | 131 | a = uH0; |
132 | b = uH1; | 132 | b = uH1; |
133 | c = uH2; | 133 | c = uH2; |
134 | d = uH3; | 134 | d = uH3; |
135 | e = uH4; | 135 | e = uH4; |
136 | 136 | ||
137 | // copy and expand the message block | 137 | // copy and expand the message block |
138 | for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24) | 138 | for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24) |
139 | +(uBytes[t*4 + 1] << 16) | 139 | +(uBytes[t*4 + 1] << 16) |
140 | +(uBytes[t*4 + 2] << 8) | 140 | +(uBytes[t*4 + 2] << 8) |
141 | + uBytes[t*4 + 3]; | 141 | + uBytes[t*4 + 3]; |
142 | for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); | 142 | for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); |
143 | 143 | ||
144 | /* main loop */ | 144 | /* main loop */ |
145 | uint32_t temp; | 145 | uint32_t temp; |
146 | for( t = 0; t < 80; t++ ) | 146 | for( t = 0; t < 80; t++ ) |
147 | { | 147 | { |
148 | if( t < 20 ) { | 148 | if( t < 20 ) { |
149 | K = 0x5a827999; | 149 | K = 0x5a827999; |
150 | f = (b & c) | ((~b) & d); | 150 | f = (b & c) | ((~b) & d); |
151 | } else if( t < 40 ) { | 151 | } else if( t < 40 ) { |
152 | K = 0x6ed9eba1; | 152 | K = 0x6ed9eba1; |
153 | f = b ^ c ^ d; | 153 | f = b ^ c ^ d; |
154 | } else if( t < 60 ) { | 154 | } else if( t < 60 ) { |
155 | K = 0x8f1bbcdc; | 155 | K = 0x8f1bbcdc; |
156 | f = (b & c) | (b & d) | (c & d); | 156 | f = (b & c) | (b & d) | (c & d); |
157 | } else { | 157 | } else { |
158 | K = 0xca62c1d6; | 158 | K = 0xca62c1d6; |
159 | f = b ^ c ^ d; | 159 | f = b ^ c ^ d; |
160 | } | 160 | } |
161 | temp = lrot(a,5) + f + e + W[t] + K; | 161 | temp = lrot(a,5) + f + e + W[t] + K; |
162 | e = d; | 162 | e = d; |
163 | d = c; | 163 | d = c; |
164 | c = lrot(b,30); | 164 | c = lrot(b,30); |
165 | b = a; | 165 | b = a; |
166 | a = temp; | 166 | a = temp; |
167 | //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); | 167 | //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* add variables */ | 170 | /* add variables */ |
171 | uH0 += a; | 171 | uH0 += a; |
172 | uH1 += b; | 172 | uH1 += b; |
173 | uH2 += c; | 173 | uH2 += c; |
174 | uH3 += d; | 174 | uH3 += d; |
175 | uH4 += e; | 175 | uH4 += e; |
176 | 176 | ||
177 | //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); | 177 | //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); |
178 | /* all bytes have been processed */ | 178 | /* all bytes have been processed */ |
179 | iUnprocessedBytes = 0; | 179 | iUnprocessedBytes = 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) | 182 | uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) |
183 | { | 183 | { |
184 | return (x<<bits) | (x>>(32 - bits)); | 184 | return (x<<bits) | (x>>(32 - bits)); |
185 | } | 185 | } |
186 | 186 | ||
187 | void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) | 187 | void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) |
188 | { | 188 | { |
189 | byte[0] = (unsigned char)(num>>24); | 189 | byte[0] = (unsigned char)(num>>24); |
190 | byte[1] = (unsigned char)(num>>16); | 190 | byte[1] = (unsigned char)(num>>16); |
191 | byte[2] = (unsigned char)(num>>8); | 191 | byte[2] = (unsigned char)(num>>8); |
192 | byte[3] = (unsigned char)num; | 192 | byte[3] = (unsigned char)num; |
193 | } | 193 | } |
194 | 194 | ||
diff --git a/src/stable/sha1.h b/src/stable/sha1.h index e861f94..f882473 100644 --- a/src/stable/sha1.h +++ b/src/stable/sha1.h | |||
@@ -13,41 +13,41 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * Calculates SHA-1 sums. This is based strongly on code from Michael D. | 17 | * Calculates SHA-1 sums. This is based strongly on code from Michael D. |
18 | * Leonhard who released his code under the terms of the MIT license, | 18 | * Leonhard who released his code under the terms of the MIT license, |
19 | * thank you! Check out his website http://tamale.net he has a lot of | 19 | * thank you! Check out his website http://tamale.net he has a lot of |
20 | * cool stuff there. | 20 | * cool stuff there. |
21 | */ | 21 | */ |
22 | class Sha1 : public CryptoHash | 22 | class Sha1 : public CryptoHash |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Sha1(); | 25 | Sha1(); |
26 | virtual ~Sha1(); | 26 | virtual ~Sha1(); |
27 | 27 | ||
28 | virtual void reset(); | 28 | virtual void reset(); |
29 | virtual void setSalt( const Bu::String &sSalt ); | 29 | virtual void setSalt( const Bu::String &sSalt ); |
30 | virtual void addData( const void *sData, int iSize ); | 30 | virtual void addData( const void *sData, int iSize ); |
31 | using CryptoHash::addData; | 31 | using CryptoHash::addData; |
32 | virtual String getResult(); | 32 | virtual String getResult(); |
33 | virtual void writeResult( Stream &sOut ); | 33 | virtual void writeResult( Stream &sOut ); |
34 | 34 | ||
35 | void update( const char* data, int num ); | 35 | void update( const char* data, int num ); |
36 | unsigned char* getDigest(); | 36 | unsigned char* getDigest(); |
37 | 37 | ||
38 | // utility methods | 38 | // utility methods |
39 | 39 | ||
40 | private: | 40 | private: |
41 | static uint32_t lrot( uint32_t x, int bits ); | 41 | static uint32_t lrot( uint32_t x, int bits ); |
42 | static void toBigEndian( uint32_t in, unsigned char* out ); | 42 | static void toBigEndian( uint32_t in, unsigned char* out ); |
43 | void process(); | 43 | void process(); |
44 | 44 | ||
45 | private: | 45 | private: |
46 | uint32_t uH0, uH1, uH2, uH3, uH4; | 46 | uint32_t uH0, uH1, uH2, uH3, uH4; |
47 | unsigned char uBytes[64]; | 47 | unsigned char uBytes[64]; |
48 | int iUnprocessedBytes; | 48 | int iUnprocessedBytes; |
49 | uint32_t uTotalBytes; | 49 | uint32_t uTotalBytes; |
50 | }; | 50 | }; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | #endif | 53 | #endif |
diff --git a/src/stable/sharedcore.h b/src/stable/sharedcore.h index f000077..f8b9d4e 100644 --- a/src/stable/sharedcore.h +++ b/src/stable/sharedcore.h | |||
@@ -15,176 +15,176 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * A mechanism for creating classes that perform lazy copies. The concept | 19 | * A mechanism for creating classes that perform lazy copies. The concept |
20 | * behind this is that instead of copying a large object when it is assigned | 20 | * behind this is that instead of copying a large object when it is assigned |
21 | * or passed into a copy constructor we simply copy a pointer internally. | 21 | * or passed into a copy constructor we simply copy a pointer internally. |
22 | * The assumption is that many times when an object is passed by value we | 22 | * The assumption is that many times when an object is passed by value we |
23 | * don't really want to keep the object around, we want the recipient to | 23 | * don't really want to keep the object around, we want the recipient to |
24 | * take ownership without allocating a new object. This allows that to | 24 | * take ownership without allocating a new object. This allows that to |
25 | * happen. | 25 | * happen. |
26 | * | 26 | * |
27 | * When used properly this makes object copying essentially free (O(1), | 27 | * When used properly this makes object copying essentially free (O(1), |
28 | * that is) and performs the actual copy when a user tries to modify the | 28 | * that is) and performs the actual copy when a user tries to modify the |
29 | * object. | 29 | * object. |
30 | * | 30 | * |
31 | * For example, lets look at something like the getKeys function in | 31 | * For example, lets look at something like the getKeys function in |
32 | * Bu::Hash. When this function is called it creates a Bu::List of | 32 | * Bu::Hash. When this function is called it creates a Bu::List of |
33 | * appropriate type, fills it with keys, and returns it. This is a good | 33 | * appropriate type, fills it with keys, and returns it. This is a good |
34 | * way for this function to behave, there may be additional issues if the | 34 | * way for this function to behave, there may be additional issues if the |
35 | * List object were allocated with new and not on the stack. However, | 35 | * List object were allocated with new and not on the stack. However, |
36 | * returning the List at the end of the function could potentially take | 36 | * returning the List at the end of the function could potentially take |
37 | * a very long time depending on the size of the list and the type of the | 37 | * a very long time depending on the size of the list and the type of the |
38 | * key. In this case the getKeys function doesn't want ownership of the | 38 | * key. In this case the getKeys function doesn't want ownership of the |
39 | * List object, and when it returns it, it's local copy will be destroyed. | 39 | * List object, and when it returns it, it's local copy will be destroyed. |
40 | * | 40 | * |
41 | * However, List inherits from SharedCore, which means that when it is | 41 | * However, List inherits from SharedCore, which means that when it is |
42 | * returned all we do is copy a pointer to the "core" of the list, which | 42 | * returned all we do is copy a pointer to the "core" of the list, which |
43 | * is a very fast operatorion. For a brief moment, before anyone can do | 43 | * is a very fast operatorion. For a brief moment, before anyone can do |
44 | * anything else, there are two objects referencing the core of that single | 44 | * anything else, there are two objects referencing the core of that single |
45 | * list. However, the getKeys() function will destroy it's local copy | 45 | * list. However, the getKeys() function will destroy it's local copy |
46 | * before the calling function can use it's new copy. That means that by | 46 | * before the calling function can use it's new copy. That means that by |
47 | * the time the calling function can use it's new List of keys it is the | 47 | * the time the calling function can use it's new List of keys it is the |
48 | * only one with a reference to the core, and no copy will need to happen. | 48 | * only one with a reference to the core, and no copy will need to happen. |
49 | * | 49 | * |
50 | * Using SharedCore on your own classes is fairly straight forward. There | 50 | * Using SharedCore on your own classes is fairly straight forward. There |
51 | * are only a couple of steps. First, break the class into two classes. | 51 | * are only a couple of steps. First, break the class into two classes. |
52 | * Move every variable from the original class (generally everything that's | 52 | * Move every variable from the original class (generally everything that's |
53 | * private) into the new class. Then make the original class inherit from | 53 | * private) into the new class. Then make the original class inherit from |
54 | * SharedCore. The SharedCore template takes 2 parameters, first is the | 54 | * SharedCore. The SharedCore template takes 2 parameters, first is the |
55 | * class it's inheriting from, second is the new core class. Now, in your | 55 | * class it's inheriting from, second is the new core class. Now, in your |
56 | * original class you will have one class variable, a pointer named core. | 56 | * original class you will have one class variable, a pointer named core. |
57 | * All of your original variables will be accessable through core. The next | 57 | * All of your original variables will be accessable through core. The next |
58 | * step is to access everything you used to through core, and to find | 58 | * step is to access everything you used to through core, and to find |
59 | * every function that may change data in the core. At the top of every | 59 | * every function that may change data in the core. At the top of every |
60 | * function that may change data you want to call _hardCopy(). | 60 | * function that may change data you want to call _hardCopy(). |
61 | * | 61 | * |
62 | * That's more or less it. A more detailed guide will be written soon. | 62 | * That's more or less it. A more detailed guide will be written soon. |
63 | * @todo Write a guide for this. | 63 | * @todo Write a guide for this. |
64 | */ | 64 | */ |
65 | template<typename Shell, typename Core> | 65 | template<typename Shell, typename Core> |
66 | class SharedCore | 66 | class SharedCore |
67 | { | 67 | { |
68 | typedef class SharedCore<Shell, Core> _SharedType; | 68 | typedef class SharedCore<Shell, Core> _SharedType; |
69 | public: | 69 | public: |
70 | SharedCore() : | 70 | SharedCore() : |
71 | core( NULL ), | 71 | core( NULL ), |
72 | iRefCount( NULL ) | 72 | iRefCount( NULL ) |
73 | { | 73 | { |
74 | core = _allocateCore(); | 74 | core = _allocateCore(); |
75 | iRefCount = new int(1); | 75 | iRefCount = new int(1); |
76 | } | 76 | } |
77 | 77 | ||
78 | SharedCore( const _SharedType &rSrc ) : | 78 | SharedCore( const _SharedType &rSrc ) : |
79 | core( NULL ), | 79 | core( NULL ), |
80 | iRefCount( NULL ) | 80 | iRefCount( NULL ) |
81 | { | 81 | { |
82 | _softCopy( rSrc ); | 82 | _softCopy( rSrc ); |
83 | } | 83 | } |
84 | 84 | ||
85 | virtual ~SharedCore() | 85 | virtual ~SharedCore() |
86 | { | 86 | { |
87 | _deref(); | 87 | _deref(); |
88 | } | 88 | } |
89 | 89 | ||
90 | SharedCore &operator=( const SharedCore &rhs ) | 90 | SharedCore &operator=( const SharedCore &rhs ) |
91 | { | 91 | { |
92 | if( core == rhs.core ) | 92 | if( core == rhs.core ) |
93 | return *this; | 93 | return *this; |
94 | 94 | ||
95 | _softCopy( rhs ); | 95 | _softCopy( rhs ); |
96 | return *this; | 96 | return *this; |
97 | } | 97 | } |
98 | 98 | ||
99 | int getRefCount() const | 99 | int getRefCount() const |
100 | { | 100 | { |
101 | return *iRefCount; | 101 | return *iRefCount; |
102 | } | 102 | } |
103 | 103 | ||
104 | Shell clone() const | 104 | Shell clone() const |
105 | { | 105 | { |
106 | Shell s( dynamic_cast<const Shell &>(*this) ); | 106 | Shell s( dynamic_cast<const Shell &>(*this) ); |
107 | s._hardCopy(); | 107 | s._hardCopy(); |
108 | return s; | 108 | return s; |
109 | } | 109 | } |
110 | 110 | ||
111 | bool isCoreShared( const Shell &rOther ) const | 111 | bool isCoreShared( const Shell &rOther ) const |
112 | { | 112 | { |
113 | return rOther.core == core; | 113 | return rOther.core == core; |
114 | } | 114 | } |
115 | 115 | ||
116 | protected: | 116 | protected: |
117 | Core *core; | 117 | Core *core; |
118 | void _hardCopy() | 118 | void _hardCopy() |
119 | { | 119 | { |
120 | if( !core || !iRefCount ) | 120 | if( !core || !iRefCount ) |
121 | return; | 121 | return; |
122 | if( (*iRefCount) == 1 ) | 122 | if( (*iRefCount) == 1 ) |
123 | return; | 123 | return; |
124 | Core *copy = _copyCore( core ); | 124 | Core *copy = _copyCore( core ); |
125 | _deref(); | 125 | _deref(); |
126 | core = copy; | 126 | core = copy; |
127 | iRefCount = new int( 1 ); | 127 | iRefCount = new int( 1 ); |
128 | } | 128 | } |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * Reset core acts like a hard copy, except instead of providing a | 131 | * Reset core acts like a hard copy, except instead of providing a |
132 | * standalone copy of the shared core, it provides a brand new core. | 132 | * standalone copy of the shared core, it provides a brand new core. |
133 | * | 133 | * |
134 | * Very useful in functions used to reset the state of an object. | 134 | * Very useful in functions used to reset the state of an object. |
135 | */ | 135 | */ |
136 | void _resetCore() | 136 | void _resetCore() |
137 | { | 137 | { |
138 | if( core ) | 138 | if( core ) |
139 | _deref(); | 139 | _deref(); |
140 | core = _allocateCore(); | 140 | core = _allocateCore(); |
141 | iRefCount = new int( 1 ); | 141 | iRefCount = new int( 1 ); |
142 | } | 142 | } |
143 | 143 | ||
144 | virtual Core *_allocateCore() | 144 | virtual Core *_allocateCore() |
145 | { | 145 | { |
146 | return new Core(); | 146 | return new Core(); |
147 | } | 147 | } |
148 | 148 | ||
149 | virtual Core *_copyCore( Core *pSrc ) | 149 | virtual Core *_copyCore( Core *pSrc ) |
150 | { | 150 | { |
151 | return new Core( *pSrc ); | 151 | return new Core( *pSrc ); |
152 | } | 152 | } |
153 | 153 | ||
154 | virtual void _deallocateCore( Core *pSrc ) | 154 | virtual void _deallocateCore( Core *pSrc ) |
155 | { | 155 | { |
156 | delete pSrc; | 156 | delete pSrc; |
157 | } | 157 | } |
158 | 158 | ||
159 | private: | 159 | private: |
160 | void _deref() | 160 | void _deref() |
161 | { | 161 | { |
162 | if( (--(*iRefCount)) == 0 ) | 162 | if( (--(*iRefCount)) == 0 ) |
163 | { | 163 | { |
164 | _deallocateCore( core ); | 164 | _deallocateCore( core ); |
165 | delete iRefCount; | 165 | delete iRefCount; |
166 | } | 166 | } |
167 | core = NULL; | 167 | core = NULL; |
168 | iRefCount = NULL; | 168 | iRefCount = NULL; |
169 | } | 169 | } |
170 | 170 | ||
171 | void _incRefCount() | 171 | void _incRefCount() |
172 | { | 172 | { |
173 | if( iRefCount && core ) | 173 | if( iRefCount && core ) |
174 | ++(*iRefCount); | 174 | ++(*iRefCount); |
175 | } | 175 | } |
176 | 176 | ||
177 | void _softCopy( const _SharedType &rSrc ) | 177 | void _softCopy( const _SharedType &rSrc ) |
178 | { | 178 | { |
179 | if( core ) | 179 | if( core ) |
180 | _deref(); | 180 | _deref(); |
181 | core = rSrc.core; | 181 | core = rSrc.core; |
182 | iRefCount = rSrc.iRefCount; | 182 | iRefCount = rSrc.iRefCount; |
183 | _incRefCount(); | 183 | _incRefCount(); |
184 | } | 184 | } |
185 | 185 | ||
186 | int *iRefCount; | 186 | int *iRefCount; |
187 | }; | 187 | }; |
188 | }; | 188 | }; |
189 | 189 | ||
190 | #undef fin | 190 | #undef fin |
diff --git a/src/stable/singleton.h b/src/stable/singleton.h index 6fe2777..27d907d 100644 --- a/src/stable/singleton.h +++ b/src/stable/singleton.h | |||
@@ -12,57 +12,57 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Provides singleton functionality in a modular sort of way. Make this the | 16 | * Provides singleton functionality in a modular sort of way. Make this the |
17 | * base class of any other class and you immediately gain singleton | 17 | * base class of any other class and you immediately gain singleton |
18 | * functionality. Be sure to make your constructor and various functions use | 18 | * functionality. Be sure to make your constructor and various functions use |
19 | * intellegent scoping. Cleanup and instantiation are performed automatically | 19 | * intellegent scoping. Cleanup and instantiation are performed automatically |
20 | * for you at first use and program exit. There are two things that you must | 20 | * for you at first use and program exit. There are two things that you must |
21 | * do when using this template, first is to inherit from it with the name of | 21 | * do when using this template, first is to inherit from it with the name of |
22 | * your class filling in for T and then make this class a friend of your class. | 22 | * your class filling in for T and then make this class a friend of your class. |
23 | *@code | 23 | *@code |
24 | * // Making the Single Singleton: | 24 | * // Making the Single Singleton: |
25 | * class Single : public Singleton<Single> | 25 | * class Single : public Singleton<Single> |
26 | * { | 26 | * { |
27 | * friend class Singleton<Single>; | 27 | * friend class Singleton<Single>; |
28 | * protected: | 28 | * protected: |
29 | * Single(); | 29 | * Single(); |
30 | * ... | 30 | * ... |
31 | * }; | 31 | * }; |
32 | @endcode | 32 | @endcode |
33 | * You can still add public functions and variables to your new Singleton child | 33 | * You can still add public functions and variables to your new Singleton child |
34 | * class, but your constructor should be protected (hence the need for the | 34 | * class, but your constructor should be protected (hence the need for the |
35 | * friend decleration). | 35 | * friend decleration). |
36 | */ | 36 | */ |
37 | template <class T> | 37 | template <class T> |
38 | class Singleton | 38 | class Singleton |
39 | { | 39 | { |
40 | protected: | 40 | protected: |
41 | /** | 41 | /** |
42 | * Private constructor. This constructor is empty but has a body so that | 42 | * Private constructor. This constructor is empty but has a body so that |
43 | * you can make your own override of it. Be sure that you're override is | 43 | * you can make your own override of it. Be sure that you're override is |
44 | * also protected. | 44 | * also protected. |
45 | */ | 45 | */ |
46 | Singleton() {}; | 46 | Singleton() {}; |
47 | 47 | ||
48 | private: | 48 | private: |
49 | /** | 49 | /** |
50 | * Copy constructor, defined so that you could write your own as well. | 50 | * Copy constructor, defined so that you could write your own as well. |
51 | */ | 51 | */ |
52 | Singleton( const Singleton& ); | 52 | Singleton( const Singleton& ); |
53 | 53 | ||
54 | public: | 54 | public: |
55 | /** | 55 | /** |
56 | * Get a handle to the contained instance of the contained class. It is | 56 | * Get a handle to the contained instance of the contained class. It is |
57 | * a reference. | 57 | * a reference. |
58 | *@returns A reference to the contained object. | 58 | *@returns A reference to the contained object. |
59 | */ | 59 | */ |
60 | static T &getInstance() | 60 | static T &getInstance() |
61 | { | 61 | { |
62 | static T i; | 62 | static T i; |
63 | return i; | 63 | return i; |
64 | } | 64 | } |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/sio.cpp b/src/stable/sio.cpp index 6a650ed..1ea30c2 100644 --- a/src/stable/sio.cpp +++ b/src/stable/sio.cpp | |||
@@ -16,51 +16,51 @@ Bu::Formatter Bu::serr( Bu::serrRaw ); | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class PrintEndAction : public Bu::String::FormatProxyEndAction | 19 | class PrintEndAction : public Bu::String::FormatProxyEndAction |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | PrintEndAction( Bu::Stream &s, bool bEndLn ) : | 22 | PrintEndAction( Bu::Stream &s, bool bEndLn ) : |
23 | s( s ), | 23 | s( s ), |
24 | bEndLn( bEndLn ) | 24 | bEndLn( bEndLn ) |
25 | { | 25 | { |
26 | } | 26 | } |
27 | 27 | ||
28 | virtual ~PrintEndAction() | 28 | virtual ~PrintEndAction() |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | virtual void operator()( const Bu::String &sFinal ) | 32 | virtual void operator()( const Bu::String &sFinal ) |
33 | { | 33 | { |
34 | s.write( sFinal.getStr(), sFinal.getSize() ); | 34 | s.write( sFinal.getStr(), sFinal.getSize() ); |
35 | if( bEndLn ) | 35 | if( bEndLn ) |
36 | { | 36 | { |
37 | s.write("\n", 1); | 37 | s.write("\n", 1); |
38 | s.flush(); | 38 | s.flush(); |
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::Stream &s; | 42 | Bu::Stream &s; |
43 | bool bEndLn; | 43 | bool bEndLn; |
44 | }; | 44 | }; |
45 | } | 45 | } |
46 | 46 | ||
47 | Bu::String::FormatProxy Bu::print( Bu::Stream &s, const Bu::String &str ) | 47 | Bu::String::FormatProxy Bu::print( Bu::Stream &s, const Bu::String &str ) |
48 | { | 48 | { |
49 | return str.format( new Bu::PrintEndAction( s, false ) ); | 49 | return str.format( new Bu::PrintEndAction( s, false ) ); |
50 | } | 50 | } |
51 | 51 | ||
52 | Bu::String::FormatProxy Bu::print( const Bu::String &str ) | 52 | Bu::String::FormatProxy Bu::print( const Bu::String &str ) |
53 | { | 53 | { |
54 | return print( sioRaw, str ); | 54 | return print( sioRaw, str ); |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::String::FormatProxy Bu::println( Bu::Stream &s, const Bu::String &str ) | 57 | Bu::String::FormatProxy Bu::println( Bu::Stream &s, const Bu::String &str ) |
58 | { | 58 | { |
59 | return str.format( new Bu::PrintEndAction( s, true ) ); | 59 | return str.format( new Bu::PrintEndAction( s, true ) ); |
60 | } | 60 | } |
61 | 61 | ||
62 | Bu::String::FormatProxy Bu::println( const Bu::String &str ) | 62 | Bu::String::FormatProxy Bu::println( const Bu::String &str ) |
63 | { | 63 | { |
64 | return println( sioRaw, str ); | 64 | return println( sioRaw, str ); |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/src/stable/sio.h b/src/stable/sio.h index 2d4a104..ddaea1b 100644 --- a/src/stable/sio.h +++ b/src/stable/sio.h | |||
@@ -12,18 +12,18 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class StreamStack; | 15 | class StreamStack; |
16 | 16 | ||
17 | extern Bu::StreamStack sioRaw; | 17 | extern Bu::StreamStack sioRaw; |
18 | extern Bu::Formatter sio; | 18 | extern Bu::Formatter sio; |
19 | extern Bu::StreamStack serrRaw; | 19 | extern Bu::StreamStack serrRaw; |
20 | extern Bu::Formatter serr; | 20 | extern Bu::Formatter serr; |
21 | 21 | ||
22 | Bu::String::FormatProxy print( Bu::Stream &s, const Bu::String &str ); | 22 | Bu::String::FormatProxy print( Bu::Stream &s, const Bu::String &str ); |
23 | Bu::String::FormatProxy print( const Bu::String &str ); | 23 | Bu::String::FormatProxy print( const Bu::String &str ); |
24 | 24 | ||
25 | Bu::String::FormatProxy println( Bu::Stream &s, const Bu::String &str ); | 25 | Bu::String::FormatProxy println( Bu::Stream &s, const Bu::String &str ); |
26 | Bu::String::FormatProxy println( const Bu::String &str ); | 26 | Bu::String::FormatProxy println( const Bu::String &str ); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/sptr.h b/src/stable/sptr.h index 58ea223..6a9c340 100644 --- a/src/stable/sptr.h +++ b/src/stable/sptr.h | |||
@@ -13,217 +13,217 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | template<typename T> class SPtr; | 16 | template<typename T> class SPtr; |
17 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ); | 17 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ); |
18 | 18 | ||
19 | /** | 19 | /** |
20 | *@ingroup Containers | 20 | *@ingroup Containers |
21 | */ | 21 | */ |
22 | template<typename T> | 22 | template<typename T> |
23 | class SPtr | 23 | class SPtr |
24 | { | 24 | { |
25 | template<typename Tb, typename Ta> | 25 | template<typename Tb, typename Ta> |
26 | friend SPtr<Tb> SPtrCast( SPtr<Ta> pt ); | 26 | friend SPtr<Tb> SPtrCast( SPtr<Ta> pt ); |
27 | public: | 27 | public: |
28 | SPtr() : | 28 | SPtr() : |
29 | pRefCnt( NULL ), | 29 | pRefCnt( NULL ), |
30 | pData( NULL ) | 30 | pData( NULL ) |
31 | { | 31 | { |
32 | } | 32 | } |
33 | 33 | ||
34 | ~SPtr() | 34 | ~SPtr() |
35 | { | 35 | { |
36 | decCount(); | 36 | decCount(); |
37 | } | 37 | } |
38 | 38 | ||
39 | SPtr( const SPtr<T> &src ) : | 39 | SPtr( const SPtr<T> &src ) : |
40 | pRefCnt( src.pRefCnt ), | 40 | pRefCnt( src.pRefCnt ), |
41 | pData( src.pData ) | 41 | pData( src.pData ) |
42 | { | 42 | { |
43 | if( pRefCnt ) | 43 | if( pRefCnt ) |
44 | (*pRefCnt) += 1; | 44 | (*pRefCnt) += 1; |
45 | } | 45 | } |
46 | 46 | ||
47 | SPtr( T *pSrc ) : | 47 | SPtr( T *pSrc ) : |
48 | pRefCnt( NULL ), | 48 | pRefCnt( NULL ), |
49 | pData( pSrc ) | 49 | pData( pSrc ) |
50 | { | 50 | { |
51 | if( pData ) | 51 | if( pData ) |
52 | { | 52 | { |
53 | pRefCnt = new int32_t; | 53 | pRefCnt = new int32_t; |
54 | (*pRefCnt) = 1; | 54 | (*pRefCnt) = 1; |
55 | } | 55 | } |
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Get the number of references to this pointer. | 59 | * Get the number of references to this pointer. |
60 | *@returns (int32_t) The number of references to this pointer. | 60 | *@returns (int32_t) The number of references to this pointer. |
61 | */ | 61 | */ |
62 | int32_t getRefCount() const | 62 | int32_t getRefCount() const |
63 | { | 63 | { |
64 | return *pRefCnt; | 64 | return *pRefCnt; |
65 | } | 65 | } |
66 | 66 | ||
67 | void clear() | 67 | void clear() |
68 | { | 68 | { |
69 | decCount(); | 69 | decCount(); |
70 | pRefCnt = NULL; | 70 | pRefCnt = NULL; |
71 | pData = NULL; | 71 | pData = NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * Pointer access operator. | 75 | * Pointer access operator. |
76 | *@returns (const T *) | 76 | *@returns (const T *) |
77 | */ | 77 | */ |
78 | const T *operator->() const | 78 | const T *operator->() const |
79 | { | 79 | { |
80 | return pData; | 80 | return pData; |
81 | } | 81 | } |
82 | 82 | ||
83 | /** | 83 | /** |
84 | * Dereference operator. | 84 | * Dereference operator. |
85 | *@returns (const T &) The value at the end of the pointer. | 85 | *@returns (const T &) The value at the end of the pointer. |
86 | */ | 86 | */ |
87 | const T &operator*() const | 87 | const T &operator*() const |
88 | { | 88 | { |
89 | return *pData; | 89 | return *pData; |
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * Pointer access operator. | 93 | * Pointer access operator. |
94 | *@returns (T *) | 94 | *@returns (T *) |
95 | */ | 95 | */ |
96 | T *operator->() | 96 | T *operator->() |
97 | { | 97 | { |
98 | return pData; | 98 | return pData; |
99 | } | 99 | } |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * Dereference operator. | 102 | * Dereference operator. |
103 | *@returns (T &) The value at the end of the pointer. | 103 | *@returns (T &) The value at the end of the pointer. |
104 | */ | 104 | */ |
105 | T &operator*() | 105 | T &operator*() |
106 | { | 106 | { |
107 | return *pData; | 107 | return *pData; |
108 | } | 108 | } |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * Assignment operator. | 111 | * Assignment operator. |
112 | *@param src (const SPtr<T> &) | 112 | *@param src (const SPtr<T> &) |
113 | */ | 113 | */ |
114 | SPtr<T> operator=( const SPtr<T> &src ) | 114 | SPtr<T> operator=( const SPtr<T> &src ) |
115 | { | 115 | { |
116 | decCount(); | 116 | decCount(); |
117 | pRefCnt = src.pRefCnt; | 117 | pRefCnt = src.pRefCnt; |
118 | pData = src.pData; | 118 | pData = src.pData; |
119 | if( pRefCnt ) | 119 | if( pRefCnt ) |
120 | (*pRefCnt) += 1; | 120 | (*pRefCnt) += 1; |
121 | 121 | ||
122 | return *this; | 122 | return *this; |
123 | } | 123 | } |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * Assignment operator. | 126 | * Assignment operator. |
127 | *@param src (const SPtr<T> &) | 127 | *@param src (const SPtr<T> &) |
128 | */ | 128 | */ |
129 | const SPtr<T> operator=( const SPtr<T> &src ) const | 129 | const SPtr<T> operator=( const SPtr<T> &src ) const |
130 | { | 130 | { |
131 | decCount(); | 131 | decCount(); |
132 | pRefCnt = src.pRefCnt; | 132 | pRefCnt = src.pRefCnt; |
133 | pData = src.pData; | 133 | pData = src.pData; |
134 | if( pRefCnt ) | 134 | if( pRefCnt ) |
135 | (*pRefCnt) += 1; | 135 | (*pRefCnt) += 1; |
136 | 136 | ||
137 | return *this; | 137 | return *this; |
138 | } | 138 | } |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * Equals comparison operator. | 141 | * Equals comparison operator. |
142 | *@param src (const SPtr<T> &) The SPtr to compare to. | 142 | *@param src (const SPtr<T> &) The SPtr to compare to. |
143 | *@returns (bool) Are the equal? | 143 | *@returns (bool) Are the equal? |
144 | */ | 144 | */ |
145 | bool operator==( const SPtr<T> &src ) const | 145 | bool operator==( const SPtr<T> &src ) const |
146 | { | 146 | { |
147 | return pData == src.pData; | 147 | return pData == src.pData; |
148 | } | 148 | } |
149 | 149 | ||
150 | /** | 150 | /** |
151 | * Equals comparison operator. | 151 | * Equals comparison operator. |
152 | *@param src (const T *) The pointer to compare to. | 152 | *@param src (const T *) The pointer to compare to. |
153 | *@returns (bool) Are the equal? | 153 | *@returns (bool) Are the equal? |
154 | */ | 154 | */ |
155 | bool operator==( const T *src ) const | 155 | bool operator==( const T *src ) const |
156 | { | 156 | { |
157 | return pData == src; | 157 | return pData == src; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Not equals comparison operator. | 161 | * Not equals comparison operator. |
162 | *@param src (const SPtr<T> &) The SPtr to compare to. | 162 | *@param src (const SPtr<T> &) The SPtr to compare to. |
163 | *@returns (bool) Are the equal? | 163 | *@returns (bool) Are the equal? |
164 | */ | 164 | */ |
165 | bool operator!=( const SPtr<T> &src ) const | 165 | bool operator!=( const SPtr<T> &src ) const |
166 | { | 166 | { |
167 | return !(pData == src.pData); | 167 | return !(pData == src.pData); |
168 | } | 168 | } |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * Not equals comparison operator. | 171 | * Not equals comparison operator. |
172 | *@param src (const T *) The pointer to compare to. | 172 | *@param src (const T *) The pointer to compare to. |
173 | *@returns (bool) Are the equal? | 173 | *@returns (bool) Are the equal? |
174 | */ | 174 | */ |
175 | bool operator!=( const T *src ) const | 175 | bool operator!=( const T *src ) const |
176 | { | 176 | { |
177 | return !(pData == src); | 177 | return !(pData == src); |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * Boolean cast operator. Do we have a pointer? | 181 | * Boolean cast operator. Do we have a pointer? |
182 | */ | 182 | */ |
183 | operator bool() const | 183 | operator bool() const |
184 | { | 184 | { |
185 | return pRefCnt != NULL; | 185 | return pRefCnt != NULL; |
186 | } | 186 | } |
187 | 187 | ||
188 | /** | 188 | /** |
189 | * Do we have a pointer? | 189 | * Do we have a pointer? |
190 | *@returns (bool) Do we have a pointer? | 190 | *@returns (bool) Do we have a pointer? |
191 | */ | 191 | */ |
192 | bool isSet() const | 192 | bool isSet() const |
193 | { | 193 | { |
194 | return pRefCnt != NULL; | 194 | return pRefCnt != NULL; |
195 | } | 195 | } |
196 | 196 | ||
197 | private: | 197 | private: |
198 | void decCount() const | 198 | void decCount() const |
199 | { | 199 | { |
200 | if( pRefCnt ) | 200 | if( pRefCnt ) |
201 | { | 201 | { |
202 | (*pRefCnt) -= 1; | 202 | (*pRefCnt) -= 1; |
203 | //printf("Decrementing ref-count to %d\n", *pRefCnt ); | 203 | //printf("Decrementing ref-count to %d\n", *pRefCnt ); |
204 | if( (*pRefCnt) == 0 ) | 204 | if( (*pRefCnt) == 0 ) |
205 | { | 205 | { |
206 | delete pRefCnt; | 206 | delete pRefCnt; |
207 | delete pData; | 207 | delete pData; |
208 | pRefCnt = NULL; | 208 | pRefCnt = NULL; |
209 | pData = NULL; | 209 | pData = NULL; |
210 | } | 210 | } |
211 | } | 211 | } |
212 | } | 212 | } |
213 | 213 | ||
214 | mutable int32_t *pRefCnt; | 214 | mutable int32_t *pRefCnt; |
215 | mutable T *pData; | 215 | mutable T *pData; |
216 | }; | 216 | }; |
217 | 217 | ||
218 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ) | 218 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ) |
219 | { | 219 | { |
220 | SPtr<Tb> ret; | 220 | SPtr<Tb> ret; |
221 | ret.pRefCnt = src.pRefCnt; | 221 | ret.pRefCnt = src.pRefCnt; |
222 | ret.pData = dynamic_cast<Tb *>(src.pData); | 222 | ret.pData = dynamic_cast<Tb *>(src.pData); |
223 | if( ret.pRefCnt ) | 223 | if( ret.pRefCnt ) |
224 | (*(ret.pRefCnt)) += 1; | 224 | (*(ret.pRefCnt)) += 1; |
225 | return ret; | 225 | return ret; |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | #endif | 229 | #endif |
diff --git a/src/stable/stack.h b/src/stable/stack.h index f60907d..6b5f65a 100644 --- a/src/stable/stack.h +++ b/src/stable/stack.h | |||
@@ -13,73 +13,73 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | template<typename value, typename valuealloc=std::allocator<value> > | 16 | template<typename value, typename valuealloc=std::allocator<value> > |
17 | class Stack | 17 | class Stack |
18 | { | 18 | { |
19 | private: | 19 | private: |
20 | typedef struct Chunk | 20 | typedef struct Chunk |
21 | { | 21 | { |
22 | value *pValue; | 22 | value *pValue; |
23 | Chunk *pPrev; | 23 | Chunk *pPrev; |
24 | } Chunk; | 24 | } Chunk; |
25 | public: | 25 | public: |
26 | Stack() : | 26 | Stack() : |
27 | pTop( NULL ) | 27 | pTop( NULL ) |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
31 | virtual ~Stack() | 31 | virtual ~Stack() |
32 | { | 32 | { |
33 | } | 33 | } |
34 | 34 | ||
35 | void push( const value &v ) | 35 | void push( const value &v ) |
36 | { | 36 | { |
37 | Chunk *pChnk = new Chunk; | 37 | Chunk *pChnk = new Chunk; |
38 | pChnk->pValue = va.allocate( 1 ); | 38 | pChnk->pValue = va.allocate( 1 ); |
39 | va.construct( pChnk->pValue, v ); | 39 | va.construct( pChnk->pValue, v ); |
40 | pChnk->pPrev = pTop; | 40 | pChnk->pPrev = pTop; |
41 | pTop = pChnk; | 41 | pTop = pChnk; |
42 | } | 42 | } |
43 | 43 | ||
44 | value &peek() | 44 | value &peek() |
45 | { | 45 | { |
46 | return *pTop->pValue; | 46 | return *pTop->pValue; |
47 | } | 47 | } |
48 | 48 | ||
49 | value &top() | 49 | value &top() |
50 | { | 50 | { |
51 | return *pTop->pValue; | 51 | return *pTop->pValue; |
52 | } | 52 | } |
53 | 53 | ||
54 | value pop() | 54 | value pop() |
55 | { | 55 | { |
56 | value ret( *pTop->pValue ); | 56 | value ret( *pTop->pValue ); |
57 | 57 | ||
58 | Chunk *pChnk = pTop; | 58 | Chunk *pChnk = pTop; |
59 | pTop = pTop->pPrev; | 59 | pTop = pTop->pPrev; |
60 | 60 | ||
61 | va.destroy( pChnk->pValue ); | 61 | va.destroy( pChnk->pValue ); |
62 | va.deallocate( pChnk->pValue, 1 ); | 62 | va.deallocate( pChnk->pValue, 1 ); |
63 | delete pChnk; | 63 | delete pChnk; |
64 | 64 | ||
65 | return ret; | 65 | return ret; |
66 | } | 66 | } |
67 | 67 | ||
68 | void clear() | 68 | void clear() |
69 | { | 69 | { |
70 | while( !isEmpty() ) | 70 | while( !isEmpty() ) |
71 | pop(); | 71 | pop(); |
72 | } | 72 | } |
73 | 73 | ||
74 | bool isEmpty() | 74 | bool isEmpty() |
75 | { | 75 | { |
76 | return pTop == NULL; | 76 | return pTop == NULL; |
77 | } | 77 | } |
78 | 78 | ||
79 | private: | 79 | private: |
80 | Chunk *pTop; | 80 | Chunk *pTop; |
81 | valuealloc va; | 81 | valuealloc va; |
82 | }; | 82 | }; |
83 | } | 83 | } |
84 | 84 | ||
85 | #endif | 85 | #endif |
diff --git a/src/stable/staticmembuf.cpp b/src/stable/staticmembuf.cpp index d470916..43f098b 100644 --- a/src/stable/staticmembuf.cpp +++ b/src/stable/staticmembuf.cpp | |||
@@ -10,9 +10,9 @@ | |||
10 | using namespace Bu; | 10 | using namespace Bu; |
11 | 11 | ||
12 | Bu::StaticMemBuf::StaticMemBuf( const void *pData, size iSize ) : | 12 | Bu::StaticMemBuf::StaticMemBuf( const void *pData, size iSize ) : |
13 | pData( pData ), | 13 | pData( pData ), |
14 | iSize( iSize ), | 14 | iSize( iSize ), |
15 | nPos( 0 ) | 15 | nPos( 0 ) |
16 | { | 16 | { |
17 | } | 17 | } |
18 | 18 | ||
@@ -26,54 +26,54 @@ void Bu::StaticMemBuf::close() | |||
26 | 26 | ||
27 | size Bu::StaticMemBuf::read( void *pBuf, size nBytes ) | 27 | size Bu::StaticMemBuf::read( void *pBuf, size nBytes ) |
28 | { | 28 | { |
29 | if( iSize-nPos < nBytes ) | 29 | if( iSize-nPos < nBytes ) |
30 | nBytes = iSize-nPos; | 30 | nBytes = iSize-nPos; |
31 | 31 | ||
32 | memcpy( pBuf, ((char *)pData)+nPos, nBytes ); | 32 | memcpy( pBuf, ((char *)pData)+nPos, nBytes ); |
33 | nPos += nBytes; | 33 | nPos += nBytes; |
34 | 34 | ||
35 | return nBytes; | 35 | return nBytes; |
36 | } | 36 | } |
37 | 37 | ||
38 | size Bu::StaticMemBuf::write( const void *, size ) | 38 | size Bu::StaticMemBuf::write( const void *, size ) |
39 | { | 39 | { |
40 | return -1; | 40 | return -1; |
41 | } | 41 | } |
42 | 42 | ||
43 | size Bu::StaticMemBuf::tell() | 43 | size Bu::StaticMemBuf::tell() |
44 | { | 44 | { |
45 | return nPos; | 45 | return nPos; |
46 | } | 46 | } |
47 | 47 | ||
48 | void Bu::StaticMemBuf::seek( size offset ) | 48 | void Bu::StaticMemBuf::seek( size offset ) |
49 | { | 49 | { |
50 | nPos += offset; | 50 | nPos += offset; |
51 | if( nPos < 0 ) nPos = 0; | 51 | if( nPos < 0 ) nPos = 0; |
52 | else if( nPos > iSize ) nPos = iSize; | 52 | else if( nPos > iSize ) nPos = iSize; |
53 | } | 53 | } |
54 | 54 | ||
55 | void Bu::StaticMemBuf::setPos( size pos ) | 55 | void Bu::StaticMemBuf::setPos( size pos ) |
56 | { | 56 | { |
57 | nPos = pos; | 57 | nPos = pos; |
58 | if( nPos < 0 ) nPos = 0; | 58 | if( nPos < 0 ) nPos = 0; |
59 | else if( nPos > iSize ) nPos = iSize; | 59 | else if( nPos > iSize ) nPos = iSize; |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::StaticMemBuf::setPosEnd( size pos ) | 62 | void Bu::StaticMemBuf::setPosEnd( size pos ) |
63 | { | 63 | { |
64 | nPos = iSize-pos; | 64 | nPos = iSize-pos; |
65 | if( nPos < 0 ) nPos = 0; | 65 | if( nPos < 0 ) nPos = 0; |
66 | else if( nPos > iSize ) nPos = iSize; | 66 | else if( nPos > iSize ) nPos = iSize; |
67 | } | 67 | } |
68 | 68 | ||
69 | bool Bu::StaticMemBuf::isEos() | 69 | bool Bu::StaticMemBuf::isEos() |
70 | { | 70 | { |
71 | return (nPos == iSize); | 71 | return (nPos == iSize); |
72 | } | 72 | } |
73 | 73 | ||
74 | bool Bu::StaticMemBuf::isOpen() | 74 | bool Bu::StaticMemBuf::isOpen() |
75 | { | 75 | { |
76 | return true; | 76 | return true; |
77 | } | 77 | } |
78 | 78 | ||
79 | void Bu::StaticMemBuf::flush() | 79 | void Bu::StaticMemBuf::flush() |
@@ -82,32 +82,32 @@ void Bu::StaticMemBuf::flush() | |||
82 | 82 | ||
83 | bool Bu::StaticMemBuf::canRead() | 83 | bool Bu::StaticMemBuf::canRead() |
84 | { | 84 | { |
85 | return !isEos(); | 85 | return !isEos(); |
86 | } | 86 | } |
87 | 87 | ||
88 | bool Bu::StaticMemBuf::canWrite() | 88 | bool Bu::StaticMemBuf::canWrite() |
89 | { | 89 | { |
90 | return false; | 90 | return false; |
91 | } | 91 | } |
92 | 92 | ||
93 | bool Bu::StaticMemBuf::isReadable() | 93 | bool Bu::StaticMemBuf::isReadable() |
94 | { | 94 | { |
95 | return true; | 95 | return true; |
96 | } | 96 | } |
97 | 97 | ||
98 | bool Bu::StaticMemBuf::isWritable() | 98 | bool Bu::StaticMemBuf::isWritable() |
99 | { | 99 | { |
100 | return false; | 100 | return false; |
101 | } | 101 | } |
102 | 102 | ||
103 | bool Bu::StaticMemBuf::isSeekable() | 103 | bool Bu::StaticMemBuf::isSeekable() |
104 | { | 104 | { |
105 | return true; | 105 | return true; |
106 | } | 106 | } |
107 | 107 | ||
108 | bool Bu::StaticMemBuf::isBlocking() | 108 | bool Bu::StaticMemBuf::isBlocking() |
109 | { | 109 | { |
110 | return true; | 110 | return true; |
111 | } | 111 | } |
112 | 112 | ||
113 | void Bu::StaticMemBuf::setBlocking( bool ) | 113 | void Bu::StaticMemBuf::setBlocking( bool ) |
@@ -120,16 +120,16 @@ void Bu::StaticMemBuf::setSize( size ) | |||
120 | 120 | ||
121 | Bu::size Bu::StaticMemBuf::getSize() const | 121 | Bu::size Bu::StaticMemBuf::getSize() const |
122 | { | 122 | { |
123 | return iSize; | 123 | return iSize; |
124 | } | 124 | } |
125 | 125 | ||
126 | Bu::size Bu::StaticMemBuf::getBlockSize() const | 126 | Bu::size Bu::StaticMemBuf::getBlockSize() const |
127 | { | 127 | { |
128 | return iSize; | 128 | return iSize; |
129 | } | 129 | } |
130 | 130 | ||
131 | Bu::String Bu::StaticMemBuf::getLocation() const | 131 | Bu::String Bu::StaticMemBuf::getLocation() const |
132 | { | 132 | { |
133 | return ""; | 133 | return ""; |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/src/stable/staticmembuf.h b/src/stable/staticmembuf.h index 332e27d..2be05a0 100644 --- a/src/stable/staticmembuf.h +++ b/src/stable/staticmembuf.h | |||
@@ -15,51 +15,51 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * An immutable, read-only memory buffer. Construct this buffer around a | 19 | * An immutable, read-only memory buffer. Construct this buffer around a |
20 | * block of raw memory, provide the length of the block, and you can read | 20 | * block of raw memory, provide the length of the block, and you can read |
21 | * from that block via this class as though it were a normal stream. | 21 | * from that block via this class as though it were a normal stream. |
22 | * | 22 | * |
23 | * Use this class instead of MemBuf when you have a string already, and | 23 | * Use this class instead of MemBuf when you have a string already, and |
24 | * don't need to change it. MemBuf will make a copy of your string for | 24 | * don't need to change it. MemBuf will make a copy of your string for |
25 | * it's own use (often) and this will not (ever). | 25 | * it's own use (often) and this will not (ever). |
26 | *@ingroup Streams | 26 | *@ingroup Streams |
27 | */ | 27 | */ |
28 | class StaticMemBuf : public Stream | 28 | class StaticMemBuf : public Stream |
29 | { | 29 | { |
30 | public: | 30 | public: |
31 | StaticMemBuf( const void *pData, size iSize ); | 31 | StaticMemBuf( const void *pData, size iSize ); |
32 | virtual ~StaticMemBuf(); | 32 | virtual ~StaticMemBuf(); |
33 | 33 | ||
34 | virtual void close(); | 34 | virtual void close(); |
35 | virtual size read( void *pBuf, size iBytes ); | 35 | virtual size read( void *pBuf, size iBytes ); |
36 | 36 | ||
37 | virtual size write( const void *pBuf, size iBytes ); | 37 | virtual size write( const void *pBuf, size iBytes ); |
38 | using Stream::write; | 38 | using Stream::write; |
39 | virtual size tell(); | 39 | virtual size tell(); |
40 | virtual void seek( size offset ); | 40 | virtual void seek( size offset ); |
41 | virtual void setPos( size pos ); | 41 | virtual void setPos( size pos ); |
42 | virtual void setPosEnd( size pos ); | 42 | virtual void setPosEnd( size pos ); |
43 | virtual bool isEos(); | 43 | virtual bool isEos(); |
44 | virtual bool isOpen(); | 44 | virtual bool isOpen(); |
45 | virtual void flush(); | 45 | virtual void flush(); |
46 | virtual bool canRead(); | 46 | virtual bool canRead(); |
47 | virtual bool canWrite(); | 47 | virtual bool canWrite(); |
48 | virtual bool isReadable(); | 48 | virtual bool isReadable(); |
49 | virtual bool isWritable(); | 49 | virtual bool isWritable(); |
50 | virtual bool isSeekable(); | 50 | virtual bool isSeekable(); |
51 | virtual bool isBlocking(); | 51 | virtual bool isBlocking(); |
52 | virtual void setBlocking( bool bBlocking=true ); | 52 | virtual void setBlocking( bool bBlocking=true ); |
53 | virtual void setSize( size iSize ); | 53 | virtual void setSize( size iSize ); |
54 | virtual size getSize() const; | 54 | virtual size getSize() const; |
55 | virtual size getBlockSize() const; | 55 | virtual size getBlockSize() const; |
56 | virtual Bu::String getLocation() const; | 56 | virtual Bu::String getLocation() const; |
57 | 57 | ||
58 | private: | 58 | private: |
59 | const void *pData; | 59 | const void *pData; |
60 | size iSize; | 60 | size iSize; |
61 | size nPos; | 61 | size nPos; |
62 | }; | 62 | }; |
63 | } | 63 | } |
64 | 64 | ||
65 | #endif | 65 | #endif |
diff --git a/src/stable/stdstream.cpp b/src/stable/stdstream.cpp index 25ad8d4..9cd216d 100644 --- a/src/stable/stdstream.cpp +++ b/src/stable/stdstream.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | #include "bu/stdstream.h" | 9 | #include "bu/stdstream.h" |
10 | 10 | ||
11 | Bu::StdStream::StdStream( OutMode eOut ) : | 11 | Bu::StdStream::StdStream( OutMode eOut ) : |
12 | eOut( eOut ) | 12 | eOut( eOut ) |
13 | { | 13 | { |
14 | } | 14 | } |
15 | 15 | ||
@@ -23,17 +23,17 @@ void Bu::StdStream::close() | |||
23 | 23 | ||
24 | Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes ) | 24 | Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes ) |
25 | { | 25 | { |
26 | return fread( pBuf, 1, nBytes, stdin ); | 26 | return fread( pBuf, 1, nBytes, stdin ); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes ) | 29 | Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes ) |
30 | { | 30 | { |
31 | return fwrite( pBuf, 1, nBytes, eOut==StdOut?stdout:stderr ); | 31 | return fwrite( pBuf, 1, nBytes, eOut==StdOut?stdout:stderr ); |
32 | } | 32 | } |
33 | 33 | ||
34 | Bu::size Bu::StdStream::tell() | 34 | Bu::size Bu::StdStream::tell() |
35 | { | 35 | { |
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | void Bu::StdStream::seek( Bu::size ) | 39 | void Bu::StdStream::seek( Bu::size ) |
@@ -50,47 +50,47 @@ void Bu::StdStream::setPosEnd( Bu::size ) | |||
50 | 50 | ||
51 | bool Bu::StdStream::isEos() | 51 | bool Bu::StdStream::isEos() |
52 | { | 52 | { |
53 | return false; | 53 | return false; |
54 | } | 54 | } |
55 | 55 | ||
56 | bool Bu::StdStream::isOpen() | 56 | bool Bu::StdStream::isOpen() |
57 | { | 57 | { |
58 | return true; | 58 | return true; |
59 | } | 59 | } |
60 | 60 | ||
61 | void Bu::StdStream::flush() | 61 | void Bu::StdStream::flush() |
62 | { | 62 | { |
63 | fflush( eOut==StdOut?stdout:stderr ); | 63 | fflush( eOut==StdOut?stdout:stderr ); |
64 | } | 64 | } |
65 | 65 | ||
66 | bool Bu::StdStream::canRead() | 66 | bool Bu::StdStream::canRead() |
67 | { | 67 | { |
68 | return true; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | bool Bu::StdStream::canWrite() | 71 | bool Bu::StdStream::canWrite() |
72 | { | 72 | { |
73 | return true; | 73 | return true; |
74 | } | 74 | } |
75 | 75 | ||
76 | bool Bu::StdStream::isReadable() | 76 | bool Bu::StdStream::isReadable() |
77 | { | 77 | { |
78 | return true; | 78 | return true; |
79 | } | 79 | } |
80 | 80 | ||
81 | bool Bu::StdStream::isWritable() | 81 | bool Bu::StdStream::isWritable() |
82 | { | 82 | { |
83 | return true; | 83 | return true; |
84 | } | 84 | } |
85 | 85 | ||
86 | bool Bu::StdStream::isSeekable() | 86 | bool Bu::StdStream::isSeekable() |
87 | { | 87 | { |
88 | return false; | 88 | return false; |
89 | } | 89 | } |
90 | 90 | ||
91 | bool Bu::StdStream::isBlocking() | 91 | bool Bu::StdStream::isBlocking() |
92 | { | 92 | { |
93 | return true; | 93 | return true; |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::StdStream::setBlocking( bool ) | 96 | void Bu::StdStream::setBlocking( bool ) |
@@ -103,16 +103,16 @@ void Bu::StdStream::setSize( Bu::size ) | |||
103 | 103 | ||
104 | Bu::size Bu::StdStream::getSize() const | 104 | Bu::size Bu::StdStream::getSize() const |
105 | { | 105 | { |
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | Bu::size Bu::StdStream::getBlockSize() const | 109 | Bu::size Bu::StdStream::getBlockSize() const |
110 | { | 110 | { |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::String Bu::StdStream::getLocation() const | 114 | Bu::String Bu::StdStream::getLocation() const |
115 | { | 115 | { |
116 | return ""; | 116 | return ""; |
117 | } | 117 | } |
118 | 118 | ||
diff --git a/src/stable/stdstream.h b/src/stable/stdstream.h index d71d95d..80c0fab 100644 --- a/src/stable/stdstream.h +++ b/src/stable/stdstream.h | |||
@@ -13,46 +13,46 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | *@ingroup Streams | 17 | *@ingroup Streams |
18 | */ | 18 | */ |
19 | class StdStream : public Stream | 19 | class StdStream : public Stream |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | enum OutMode | 22 | enum OutMode |
23 | { | 23 | { |
24 | StdOut, | 24 | StdOut, |
25 | StdError | 25 | StdError |
26 | }; | 26 | }; |
27 | StdStream( OutMode eOut=StdOut ); | 27 | StdStream( OutMode eOut=StdOut ); |
28 | virtual ~StdStream(); | 28 | virtual ~StdStream(); |
29 | 29 | ||
30 | virtual void close(); | 30 | virtual void close(); |
31 | virtual size read( void *pBuf, size nBytes ); | 31 | virtual size read( void *pBuf, size nBytes ); |
32 | virtual size write( const void *pBuf, size nBytes ); | 32 | virtual size write( const void *pBuf, size nBytes ); |
33 | using Stream::write; | 33 | using Stream::write; |
34 | virtual size tell(); | 34 | virtual size tell(); |
35 | virtual void seek( size offset ); | 35 | virtual void seek( size offset ); |
36 | virtual void setPos( size pos ); | 36 | virtual void setPos( size pos ); |
37 | virtual void setPosEnd( size pos ); | 37 | virtual void setPosEnd( size pos ); |
38 | virtual bool isEos(); | 38 | virtual bool isEos(); |
39 | virtual bool isOpen(); | 39 | virtual bool isOpen(); |
40 | virtual void flush(); | 40 | virtual void flush(); |
41 | virtual bool canRead(); | 41 | virtual bool canRead(); |
42 | virtual bool canWrite(); | 42 | virtual bool canWrite(); |
43 | virtual bool isReadable(); | 43 | virtual bool isReadable(); |
44 | virtual bool isWritable(); | 44 | virtual bool isWritable(); |
45 | virtual bool isSeekable(); | 45 | virtual bool isSeekable(); |
46 | virtual bool isBlocking(); | 46 | virtual bool isBlocking(); |
47 | virtual void setBlocking( bool bBlocking=true ); | 47 | virtual void setBlocking( bool bBlocking=true ); |
48 | virtual void setSize( size iSize ); | 48 | virtual void setSize( size iSize ); |
49 | virtual size getSize() const; | 49 | virtual size getSize() const; |
50 | virtual size getBlockSize() const; | 50 | virtual size getBlockSize() const; |
51 | virtual Bu::String getLocation() const; | 51 | virtual Bu::String getLocation() const; |
52 | 52 | ||
53 | private: | 53 | private: |
54 | OutMode eOut; | 54 | OutMode eOut; |
55 | }; | 55 | }; |
56 | } | 56 | } |
57 | 57 | ||
58 | #endif | 58 | #endif |
diff --git a/src/stable/stream.cpp b/src/stable/stream.cpp index 23a7f0f..551d657 100644 --- a/src/stable/stream.cpp +++ b/src/stable/stream.cpp | |||
@@ -17,37 +17,37 @@ Bu::Stream::~Stream() | |||
17 | 17 | ||
18 | Bu::String Bu::Stream::readLine() | 18 | Bu::String Bu::Stream::readLine() |
19 | { | 19 | { |
20 | Bu::String sRet; | 20 | Bu::String sRet; |
21 | 21 | ||
22 | for(;;) | 22 | for(;;) |
23 | { | 23 | { |
24 | char s; | 24 | char s; |
25 | if( read( &s, 1 ) == 0 ) | 25 | if( read( &s, 1 ) == 0 ) |
26 | return sRet; | 26 | return sRet; |
27 | if( s == '\n' || s == '\r' ) | 27 | if( s == '\n' || s == '\r' ) |
28 | return sRet; | 28 | return sRet; |
29 | sRet.append( s ); | 29 | sRet.append( s ); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | Bu::String Bu::Stream::readAll() | 33 | Bu::String Bu::Stream::readAll() |
34 | { | 34 | { |
35 | Bu::String sRet; | 35 | Bu::String sRet; |
36 | char buf[4096]; | 36 | char buf[4096]; |
37 | 37 | ||
38 | while( !isEos() ) | 38 | while( !isEos() ) |
39 | { | 39 | { |
40 | int iRead = read( buf, 4096 ); | 40 | int iRead = read( buf, 4096 ); |
41 | if( iRead == 0 ) | 41 | if( iRead == 0 ) |
42 | return sRet; | 42 | return sRet; |
43 | sRet.append( buf, iRead ); | 43 | sRet.append( buf, iRead ); |
44 | } | 44 | } |
45 | 45 | ||
46 | return sRet; | 46 | return sRet; |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::size Bu::Stream::write( const Bu::String &sBuf ) | 49 | Bu::size Bu::Stream::write( const Bu::String &sBuf ) |
50 | { | 50 | { |
51 | return write( sBuf.getStr(), sBuf.getSize() ); | 51 | return write( sBuf.getStr(), sBuf.getSize() ); |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/src/stable/stream.h b/src/stable/stream.h index 21e090e..a76e5fd 100644 --- a/src/stable/stream.h +++ b/src/stable/stream.h | |||
@@ -17,189 +17,189 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /** | 20 | /** |
21 | * The basis for a completely general data transport mechanism. Anything | 21 | * The basis for a completely general data transport mechanism. Anything |
22 | * that inherits from this should provide at least the basic read and/or | 22 | * that inherits from this should provide at least the basic read and/or |
23 | * write functions, and very probably the close function. Any functions | 23 | * write functions, and very probably the close function. Any functions |
24 | * that aren't supported should throw an exception if called. | 24 | * that aren't supported should throw an exception if called. |
25 | * | 25 | * |
26 | * The constructor of a child class should pretty much universally be used | 26 | * The constructor of a child class should pretty much universally be used |
27 | * to open the stream. I can't think of anything that should require an | 27 | * to open the stream. I can't think of anything that should require an |
28 | * exception. | 28 | * exception. |
29 | *@ingroup Streams | 29 | *@ingroup Streams |
30 | */ | 30 | */ |
31 | class Stream | 31 | class Stream |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | Stream(); | 34 | Stream(); |
35 | virtual ~Stream(); | 35 | virtual ~Stream(); |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * Close the stream. | 38 | * Close the stream. |
39 | */ | 39 | */ |
40 | virtual void close() = 0; | 40 | virtual void close() = 0; |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * Read data from the stream into a buffer. | 43 | * Read data from the stream into a buffer. |
44 | *@param pBuf (void *) Buffer which will be filled. | 44 | *@param pBuf (void *) Buffer which will be filled. |
45 | *@param nBytes (size_t) Max data to read. | 45 | *@param nBytes (size_t) Max data to read. |
46 | *@returns (size_t) Amount of data read. | 46 | *@returns (size_t) Amount of data read. |
47 | */ | 47 | */ |
48 | virtual size read( void *pBuf, size iBytes ) = 0; | 48 | virtual size read( void *pBuf, size iBytes ) = 0; |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Attempts to read a complete line from the stream. This will stop | 51 | * Attempts to read a complete line from the stream. This will stop |
52 | * reading when it has reached the end of the stream, or runs out of | 52 | * reading when it has reached the end of the stream, or runs out of |
53 | * data in a non-blocking stream. | 53 | * data in a non-blocking stream. |
54 | *@returns The line read, not including newline character. | 54 | *@returns The line read, not including newline character. |
55 | */ | 55 | */ |
56 | virtual Bu::String readLine(); | 56 | virtual Bu::String readLine(); |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Reads all data from the current position onward until isEos returns | 59 | * Reads all data from the current position onward until isEos returns |
60 | * true and returns it as a Bu::String. This will also return if no | 60 | * true and returns it as a Bu::String. This will also return if no |
61 | * data is available and the stream is in non-blocking mode. This | 61 | * data is available and the stream is in non-blocking mode. This |
62 | * function is intended for very particular circumstances and is often | 62 | * function is intended for very particular circumstances and is often |
63 | * not the most efficient way to access the data that you would like. | 63 | * not the most efficient way to access the data that you would like. |
64 | *@returns The entire stream contents. | 64 | *@returns The entire stream contents. |
65 | */ | 65 | */ |
66 | virtual Bu::String readAll(); | 66 | virtual Bu::String readAll(); |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * Write data to the stream. | 69 | * Write data to the stream. |
70 | *@param pBuf (const void *) The data to be written. | 70 | *@param pBuf (const void *) The data to be written. |
71 | *@param nBytes (size_t) Amount of data to write from pBuf. | 71 | *@param nBytes (size_t) Amount of data to write from pBuf. |
72 | *@returns (size_t) Amount of data actually written. | 72 | *@returns (size_t) Amount of data actually written. |
73 | */ | 73 | */ |
74 | virtual size write( const void *pBuf, size iBytes ) = 0; | 74 | virtual size write( const void *pBuf, size iBytes ) = 0; |
75 | 75 | ||
76 | virtual size write( const Bu::String &sBuf ); | 76 | virtual size write( const Bu::String &sBuf ); |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * Get the current position in the stream. | 79 | * Get the current position in the stream. |
80 | *@returns (long) The current position in the stream. | 80 | *@returns (long) The current position in the stream. |
81 | */ | 81 | */ |
82 | virtual size tell() = 0; | 82 | virtual size tell() = 0; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Seek to a position in the stream relative to the current position. | 85 | * Seek to a position in the stream relative to the current position. |
86 | *@param offset (long) Offset from current position to seek to. | 86 | *@param offset (long) Offset from current position to seek to. |
87 | */ | 87 | */ |
88 | virtual void seek( size offset ) = 0; | 88 | virtual void seek( size offset ) = 0; |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * Set position in the stream relative to the start of the stream. | 91 | * Set position in the stream relative to the start of the stream. |
92 | *@param pos (long) The position. | 92 | *@param pos (long) The position. |
93 | */ | 93 | */ |
94 | virtual void setPos( size pos ) = 0; | 94 | virtual void setPos( size pos ) = 0; |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * Set position in the stream relative to the end of the stream. | 97 | * Set position in the stream relative to the end of the stream. |
98 | *@param pos (long) The position. | 98 | *@param pos (long) The position. |
99 | */ | 99 | */ |
100 | virtual void setPosEnd( size pos ) = 0; | 100 | virtual void setPosEnd( size pos ) = 0; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Are we at the end of the stream? | 103 | * Are we at the end of the stream? |
104 | *@returns (bool) Are we at the end of the stream? | 104 | *@returns (bool) Are we at the end of the stream? |
105 | */ | 105 | */ |
106 | virtual bool isEos() = 0; | 106 | virtual bool isEos() = 0; |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * Is the stream open? | 109 | * Is the stream open? |
110 | *@returns (bool) Is the stream open? | 110 | *@returns (bool) Is the stream open? |
111 | */ | 111 | */ |
112 | virtual bool isOpen() = 0; | 112 | virtual bool isOpen() = 0; |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * Flush any data still held in buffers. | 115 | * Flush any data still held in buffers. |
116 | */ | 116 | */ |
117 | virtual void flush() = 0; | 117 | virtual void flush() = 0; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * In non-blocking streams this indicates if a read operation will | 120 | * In non-blocking streams this indicates if a read operation will |
121 | * return data at the moment or not. In blocking streams this should | 121 | * return data at the moment or not. In blocking streams this should |
122 | * return the same value as isEos(). | 122 | * return the same value as isEos(). |
123 | */ | 123 | */ |
124 | virtual bool canRead() = 0; | 124 | virtual bool canRead() = 0; |
125 | 125 | ||
126 | /** | 126 | /** |
127 | * In non-blocking streams this indicates if a write operation will | 127 | * In non-blocking streams this indicates if a write operation will |
128 | * actually write one or more bytes. In some cases writing is not | 128 | * actually write one or more bytes. In some cases writing is not |
129 | * allowed (e.g. internal buffers are full) temporarilly. In blocking | 129 | * allowed (e.g. internal buffers are full) temporarilly. In blocking |
130 | * streams this should return the same value as isWritable. | 130 | * streams this should return the same value as isWritable. |
131 | */ | 131 | */ |
132 | virtual bool canWrite() = 0; | 132 | virtual bool canWrite() = 0; |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * Indicates if the stream is capable of read operations. This does not | 135 | * Indicates if the stream is capable of read operations. This does not |
136 | * indicate if such operations will return useful data, see canRead for | 136 | * indicate if such operations will return useful data, see canRead for |
137 | * that. | 137 | * that. |
138 | */ | 138 | */ |
139 | virtual bool isReadable() = 0; | 139 | virtual bool isReadable() = 0; |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * Indicates if the stream is capable of write operations. This does | 142 | * Indicates if the stream is capable of write operations. This does |
143 | * not indicate if such operations will succeed or fail, see canWrite | 143 | * not indicate if such operations will succeed or fail, see canWrite |
144 | * for that. | 144 | * for that. |
145 | */ | 145 | */ |
146 | virtual bool isWritable() = 0; | 146 | virtual bool isWritable() = 0; |
147 | 147 | ||
148 | /** | 148 | /** |
149 | * Indicates if the stream is capable of seek operations. This is | 149 | * Indicates if the stream is capable of seek operations. This is |
150 | * generally false for non-blocking streams. Some buffered streams may | 150 | * generally false for non-blocking streams. Some buffered streams may |
151 | * support limited in-buffer seeking. | 151 | * support limited in-buffer seeking. |
152 | */ | 152 | */ |
153 | virtual bool isSeekable() = 0; | 153 | virtual bool isSeekable() = 0; |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * Are we currently set to block mode? | 156 | * Are we currently set to block mode? |
157 | *@returns (bool) | 157 | *@returns (bool) |
158 | */ | 158 | */ |
159 | virtual bool isBlocking() = 0; | 159 | virtual bool isBlocking() = 0; |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * Set stream to blocking or non-blocking mode. | 162 | * Set stream to blocking or non-blocking mode. |
163 | *@param bBlocking (bool) Whether we should block or not. | 163 | *@param bBlocking (bool) Whether we should block or not. |
164 | */ | 164 | */ |
165 | virtual void setBlocking( bool bBlocking=true ) = 0; | 165 | virtual void setBlocking( bool bBlocking=true ) = 0; |
166 | 166 | ||
167 | /** | 167 | /** |
168 | * Set the size of the stream, this does not apply to many types of | 168 | * Set the size of the stream, this does not apply to many types of |
169 | * streams. For those that it does apply to, data will be added or | 169 | * streams. For those that it does apply to, data will be added or |
170 | * removed from the end of the stream, but the content of the added | 170 | * removed from the end of the stream, but the content of the added |
171 | * data is undefined. | 171 | * data is undefined. |
172 | */ | 172 | */ |
173 | virtual void setSize( size iSize ) = 0; | 173 | virtual void setSize( size iSize ) = 0; |
174 | 174 | ||
175 | /** | 175 | /** |
176 | * Returns the size of the stream if the stream can have a size. For | 176 | * Returns the size of the stream if the stream can have a size. For |
177 | * streams that do not (sockets, pipes, etc.) this should throw an | 177 | * streams that do not (sockets, pipes, etc.) this should throw an |
178 | * unsupported exception. | 178 | * unsupported exception. |
179 | */ | 179 | */ |
180 | virtual size getSize() const = 0; | 180 | virtual size getSize() const = 0; |
181 | 181 | ||
182 | /** | 182 | /** |
183 | * Returns the block-size of the stream, if it has one. This should | 183 | * Returns the block-size of the stream, if it has one. This should |
184 | * throw an unsupported exception. In some cases the block size | 184 | * throw an unsupported exception. In some cases the block size |
185 | * returned will not represent quite the same thing, for example, | 185 | * returned will not represent quite the same thing, for example, |
186 | * sockets will return their MTU, while files will return the | 186 | * sockets will return their MTU, while files will return the |
187 | * filesystem's block size, and memory buffers will throw an exception. | 187 | * filesystem's block size, and memory buffers will throw an exception. |
188 | */ | 188 | */ |
189 | virtual size getBlockSize() const = 0; | 189 | virtual size getBlockSize() const = 0; |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * If possible, this returns a string that can be used to describe how | 192 | * If possible, this returns a string that can be used to describe how |
193 | * to access the open stream. Not all streams support this, such as | 193 | * to access the open stream. Not all streams support this, such as |
194 | * MemBuf, but for files it may give you a path to a file, for a socket | 194 | * MemBuf, but for files it may give you a path to a file, for a socket |
195 | * it may give you an ip address, etc. If it isn't supported, an empty | 195 | * it may give you an ip address, etc. If it isn't supported, an empty |
196 | * string may be returned. | 196 | * string may be returned. |
197 | */ | 197 | */ |
198 | virtual Bu::String getLocation() const = 0; | 198 | virtual Bu::String getLocation() const = 0; |
199 | 199 | ||
200 | private: | 200 | private: |
201 | 201 | ||
202 | }; | 202 | }; |
203 | } | 203 | } |
204 | 204 | ||
205 | #endif | 205 | #endif |
diff --git a/src/stable/streamstack.cpp b/src/stable/streamstack.cpp index 47ae5c0..deafbcf 100644 --- a/src/stable/streamstack.cpp +++ b/src/stable/streamstack.cpp | |||
@@ -13,222 +13,222 @@ Bu::StreamStack::StreamStack() | |||
13 | 13 | ||
14 | Bu::StreamStack::StreamStack( Bu::Stream *pStream ) | 14 | Bu::StreamStack::StreamStack( Bu::Stream *pStream ) |
15 | { | 15 | { |
16 | lFilts.prepend( pStream ); | 16 | lFilts.prepend( pStream ); |
17 | } | 17 | } |
18 | 18 | ||
19 | Bu::StreamStack::~StreamStack() | 19 | Bu::StreamStack::~StreamStack() |
20 | { | 20 | { |
21 | clear(); | 21 | clear(); |
22 | } | 22 | } |
23 | 23 | ||
24 | bool Bu::StreamStack::isEmpty() | 24 | bool Bu::StreamStack::isEmpty() |
25 | { | 25 | { |
26 | return lFilts.isEmpty(); | 26 | return lFilts.isEmpty(); |
27 | } | 27 | } |
28 | 28 | ||
29 | bool Bu::StreamStack::hasStream() | 29 | bool Bu::StreamStack::hasStream() |
30 | { | 30 | { |
31 | return !lFilts.isEmpty(); | 31 | return !lFilts.isEmpty(); |
32 | } | 32 | } |
33 | 33 | ||
34 | void Bu::StreamStack::setStream( Bu::Stream *pStream ) | 34 | void Bu::StreamStack::setStream( Bu::Stream *pStream ) |
35 | { | 35 | { |
36 | if( !lFilts.isEmpty() ) | 36 | if( !lFilts.isEmpty() ) |
37 | throw Bu::ExceptionBase("There is already a stream set."); | 37 | throw Bu::ExceptionBase("There is already a stream set."); |
38 | 38 | ||
39 | lFilts.prepend( pStream ); | 39 | lFilts.prepend( pStream ); |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::StreamStack::clear() | 42 | void Bu::StreamStack::clear() |
43 | { | 43 | { |
44 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 44 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
45 | { | 45 | { |
46 | delete *i; | 46 | delete *i; |
47 | } | 47 | } |
48 | 48 | ||
49 | lFilts.clear(); | 49 | lFilts.clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | void Bu::StreamStack::popFilter() | 52 | void Bu::StreamStack::popFilter() |
53 | { | 53 | { |
54 | if( lFilts.isEmpty() ) | 54 | if( lFilts.isEmpty() ) |
55 | return; | 55 | return; |
56 | 56 | ||
57 | delete lFilts.first(); | 57 | delete lFilts.first(); |
58 | lFilts.erase( lFilts.begin() ); | 58 | lFilts.erase( lFilts.begin() ); |
59 | } | 59 | } |
60 | 60 | ||
61 | Bu::Stream *Bu::StreamStack::getTop() | 61 | Bu::Stream *Bu::StreamStack::getTop() |
62 | { | 62 | { |
63 | checkStack(); | 63 | checkStack(); |
64 | 64 | ||
65 | return lFilts.first(); | 65 | return lFilts.first(); |
66 | } | 66 | } |
67 | 67 | ||
68 | Bu::Stream *Bu::StreamStack::getStream() | 68 | Bu::Stream *Bu::StreamStack::getStream() |
69 | { | 69 | { |
70 | checkStack(); | 70 | checkStack(); |
71 | 71 | ||
72 | return lFilts.last(); | 72 | return lFilts.last(); |
73 | } | 73 | } |
74 | 74 | ||
75 | void Bu::StreamStack::close() | 75 | void Bu::StreamStack::close() |
76 | { | 76 | { |
77 | checkStack(); | 77 | checkStack(); |
78 | 78 | ||
79 | lFilts.first()->close(); | 79 | lFilts.first()->close(); |
80 | } | 80 | } |
81 | 81 | ||
82 | Bu::size Bu::StreamStack::read( void *pBuf, Bu::size nBytes ) | 82 | Bu::size Bu::StreamStack::read( void *pBuf, Bu::size nBytes ) |
83 | { | 83 | { |
84 | checkStack(); | 84 | checkStack(); |
85 | 85 | ||
86 | return lFilts.first()->read( pBuf, nBytes ); | 86 | return lFilts.first()->read( pBuf, nBytes ); |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::size Bu::StreamStack::write( const void *pBuf, Bu::size nBytes ) | 89 | Bu::size Bu::StreamStack::write( const void *pBuf, Bu::size nBytes ) |
90 | { | 90 | { |
91 | checkStack(); | 91 | checkStack(); |
92 | 92 | ||
93 | return lFilts.first()->write( pBuf, nBytes ); | 93 | return lFilts.first()->write( pBuf, nBytes ); |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::StreamStack::write( const Bu::String &sBuf ) | 96 | Bu::size Bu::StreamStack::write( const Bu::String &sBuf ) |
97 | { | 97 | { |
98 | checkStack(); | 98 | checkStack(); |
99 | 99 | ||
100 | return lFilts.first()->write( sBuf ); | 100 | return lFilts.first()->write( sBuf ); |
101 | } | 101 | } |
102 | 102 | ||
103 | Bu::size Bu::StreamStack::tell() | 103 | Bu::size Bu::StreamStack::tell() |
104 | { | 104 | { |
105 | checkStack(); | 105 | checkStack(); |
106 | 106 | ||
107 | return lFilts.first()->tell(); | 107 | return lFilts.first()->tell(); |
108 | } | 108 | } |
109 | 109 | ||
110 | void Bu::StreamStack::seek( Bu::size offset ) | 110 | void Bu::StreamStack::seek( Bu::size offset ) |
111 | { | 111 | { |
112 | checkStack(); | 112 | checkStack(); |
113 | 113 | ||
114 | lFilts.first()->seek( offset ); | 114 | lFilts.first()->seek( offset ); |
115 | } | 115 | } |
116 | 116 | ||
117 | void Bu::StreamStack::setPos( Bu::size pos ) | 117 | void Bu::StreamStack::setPos( Bu::size pos ) |
118 | { | 118 | { |
119 | checkStack(); | 119 | checkStack(); |
120 | 120 | ||
121 | lFilts.first()->setPos( pos ); | 121 | lFilts.first()->setPos( pos ); |
122 | } | 122 | } |
123 | 123 | ||
124 | void Bu::StreamStack::setPosEnd( Bu::size pos ) | 124 | void Bu::StreamStack::setPosEnd( Bu::size pos ) |
125 | { | 125 | { |
126 | checkStack(); | 126 | checkStack(); |
127 | 127 | ||
128 | lFilts.first()->setPosEnd( pos ); | 128 | lFilts.first()->setPosEnd( pos ); |
129 | } | 129 | } |
130 | 130 | ||
131 | bool Bu::StreamStack::isEos() | 131 | bool Bu::StreamStack::isEos() |
132 | { | 132 | { |
133 | checkStack(); | 133 | checkStack(); |
134 | 134 | ||
135 | return lFilts.first()->isEos(); | 135 | return lFilts.first()->isEos(); |
136 | } | 136 | } |
137 | 137 | ||
138 | bool Bu::StreamStack::isOpen() | 138 | bool Bu::StreamStack::isOpen() |
139 | { | 139 | { |
140 | checkStack(); | 140 | checkStack(); |
141 | 141 | ||
142 | return lFilts.first()->isOpen(); | 142 | return lFilts.first()->isOpen(); |
143 | } | 143 | } |
144 | 144 | ||
145 | void Bu::StreamStack::flush() | 145 | void Bu::StreamStack::flush() |
146 | { | 146 | { |
147 | checkStack(); | 147 | checkStack(); |
148 | 148 | ||
149 | lFilts.first()->flush(); | 149 | lFilts.first()->flush(); |
150 | } | 150 | } |
151 | 151 | ||
152 | bool Bu::StreamStack::canRead() | 152 | bool Bu::StreamStack::canRead() |
153 | { | 153 | { |
154 | checkStack(); | 154 | checkStack(); |
155 | 155 | ||
156 | return lFilts.first()->canRead(); | 156 | return lFilts.first()->canRead(); |
157 | } | 157 | } |
158 | 158 | ||
159 | bool Bu::StreamStack::canWrite() | 159 | bool Bu::StreamStack::canWrite() |
160 | { | 160 | { |
161 | checkStack(); | 161 | checkStack(); |
162 | 162 | ||
163 | return lFilts.first()->canWrite(); | 163 | return lFilts.first()->canWrite(); |
164 | } | 164 | } |
165 | 165 | ||
166 | bool Bu::StreamStack::isReadable() | 166 | bool Bu::StreamStack::isReadable() |
167 | { | 167 | { |
168 | checkStack(); | 168 | checkStack(); |
169 | 169 | ||
170 | return lFilts.first()->isReadable(); | 170 | return lFilts.first()->isReadable(); |
171 | } | 171 | } |
172 | 172 | ||
173 | bool Bu::StreamStack::isWritable() | 173 | bool Bu::StreamStack::isWritable() |
174 | { | 174 | { |
175 | checkStack(); | 175 | checkStack(); |
176 | 176 | ||
177 | return lFilts.first()->isWritable(); | 177 | return lFilts.first()->isWritable(); |
178 | } | 178 | } |
179 | 179 | ||
180 | bool Bu::StreamStack::isSeekable() | 180 | bool Bu::StreamStack::isSeekable() |
181 | { | 181 | { |
182 | checkStack(); | 182 | checkStack(); |
183 | 183 | ||
184 | return lFilts.first()->isSeekable(); | 184 | return lFilts.first()->isSeekable(); |
185 | } | 185 | } |
186 | 186 | ||
187 | bool Bu::StreamStack::isBlocking() | 187 | bool Bu::StreamStack::isBlocking() |
188 | { | 188 | { |
189 | checkStack(); | 189 | checkStack(); |
190 | 190 | ||
191 | return lFilts.first()->isBlocking(); | 191 | return lFilts.first()->isBlocking(); |
192 | } | 192 | } |
193 | 193 | ||
194 | void Bu::StreamStack::setBlocking( bool bBlocking ) | 194 | void Bu::StreamStack::setBlocking( bool bBlocking ) |
195 | { | 195 | { |
196 | checkStack(); | 196 | checkStack(); |
197 | 197 | ||
198 | lFilts.first()->setBlocking( bBlocking ); | 198 | lFilts.first()->setBlocking( bBlocking ); |
199 | } | 199 | } |
200 | 200 | ||
201 | void Bu::StreamStack::setSize( Bu::size iSize ) | 201 | void Bu::StreamStack::setSize( Bu::size iSize ) |
202 | { | 202 | { |
203 | checkStack(); | 203 | checkStack(); |
204 | 204 | ||
205 | lFilts.first()->setSize( iSize ); | 205 | lFilts.first()->setSize( iSize ); |
206 | } | 206 | } |
207 | 207 | ||
208 | Bu::size Bu::StreamStack::getSize() const | 208 | Bu::size Bu::StreamStack::getSize() const |
209 | { | 209 | { |
210 | checkStack(); | 210 | checkStack(); |
211 | 211 | ||
212 | return lFilts.first()->getSize(); | 212 | return lFilts.first()->getSize(); |
213 | } | 213 | } |
214 | 214 | ||
215 | Bu::size Bu::StreamStack::getBlockSize() const | 215 | Bu::size Bu::StreamStack::getBlockSize() const |
216 | { | 216 | { |
217 | checkStack(); | 217 | checkStack(); |
218 | 218 | ||
219 | return lFilts.first()->getBlockSize(); | 219 | return lFilts.first()->getBlockSize(); |
220 | } | 220 | } |
221 | 221 | ||
222 | Bu::String Bu::StreamStack::getLocation() const | 222 | Bu::String Bu::StreamStack::getLocation() const |
223 | { | 223 | { |
224 | checkStack(); | 224 | checkStack(); |
225 | 225 | ||
226 | return lFilts.first()->getLocation(); | 226 | return lFilts.first()->getLocation(); |
227 | } | 227 | } |
228 | 228 | ||
229 | inline void Bu::StreamStack::checkStack() const | 229 | inline void Bu::StreamStack::checkStack() const |
230 | { | 230 | { |
231 | if( lFilts.isEmpty() ) | 231 | if( lFilts.isEmpty() ) |
232 | throw Bu::ExceptionBase("StreamStack is empty."); | 232 | throw Bu::ExceptionBase("StreamStack is empty."); |
233 | } | 233 | } |
234 | 234 | ||
diff --git a/src/stable/streamstack.h b/src/stable/streamstack.h index 36c2e11..06a3214 100644 --- a/src/stable/streamstack.h +++ b/src/stable/streamstack.h | |||
@@ -14,131 +14,131 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class StreamStack : public Bu::Stream | 17 | class StreamStack : public Bu::Stream |
18 | { | 18 | { |
19 | private: | 19 | private: |
20 | typedef Bu::List<Bu::Stream *> FilterList; | 20 | typedef Bu::List<Bu::Stream *> FilterList; |
21 | 21 | ||
22 | public: | 22 | public: |
23 | StreamStack(); | 23 | StreamStack(); |
24 | StreamStack( Bu::Stream *pStream ); | 24 | StreamStack( Bu::Stream *pStream ); |
25 | virtual ~StreamStack(); | 25 | virtual ~StreamStack(); |
26 | 26 | ||
27 | bool isEmpty(); | 27 | bool isEmpty(); |
28 | bool hasStream(); | 28 | bool hasStream(); |
29 | void setStream( Bu::Stream *pStream ); | 29 | void setStream( Bu::Stream *pStream ); |
30 | 30 | ||
31 | void clear(); | 31 | void clear(); |
32 | void popFilter(); | 32 | void popFilter(); |
33 | Bu::Stream *getTop(); | 33 | Bu::Stream *getTop(); |
34 | 34 | ||
35 | Bu::Stream *getStream(); | 35 | Bu::Stream *getStream(); |
36 | 36 | ||
37 | template<typename filter> | 37 | template<typename filter> |
38 | Bu::Stream *findFilter() | 38 | Bu::Stream *findFilter() |
39 | { | 39 | { |
40 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 40 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( typeid(**i) == typeid( filter ) ) | 42 | if( typeid(**i) == typeid( filter ) ) |
43 | { | 43 | { |
44 | return *i; | 44 | return *i; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | throw Bu::ExceptionBase("Filter not found."); | 48 | throw Bu::ExceptionBase("Filter not found."); |
49 | } | 49 | } |
50 | 50 | ||
51 | template<typename filter> | 51 | template<typename filter> |
52 | void pushFilter() | 52 | void pushFilter() |
53 | { | 53 | { |
54 | checkStack(); | 54 | checkStack(); |
55 | 55 | ||
56 | filter *pFlt = new filter( *lFilts.first() ); | 56 | filter *pFlt = new filter( *lFilts.first() ); |
57 | lFilts.prepend( pFlt ); | 57 | lFilts.prepend( pFlt ); |
58 | } | 58 | } |
59 | 59 | ||
60 | template<typename filter, typename p1t> | 60 | template<typename filter, typename p1t> |
61 | void pushFilter( p1t p1 ) | 61 | void pushFilter( p1t p1 ) |
62 | { | 62 | { |
63 | checkStack(); | 63 | checkStack(); |
64 | 64 | ||
65 | filter *pFlt = new filter( *lFilts.first(), p1 ); | 65 | filter *pFlt = new filter( *lFilts.first(), p1 ); |
66 | lFilts.prepend( pFlt ); | 66 | lFilts.prepend( pFlt ); |
67 | } | 67 | } |
68 | 68 | ||
69 | template<typename filter, typename p1t, typename p2t> | 69 | template<typename filter, typename p1t, typename p2t> |
70 | void pushFilter( p1t p1, p2t p2 ) | 70 | void pushFilter( p1t p1, p2t p2 ) |
71 | { | 71 | { |
72 | checkStack(); | 72 | checkStack(); |
73 | 73 | ||
74 | filter *pFlt = new filter( *lFilts.first(), p1, p2 ); | 74 | filter *pFlt = new filter( *lFilts.first(), p1, p2 ); |
75 | lFilts.prepend( pFlt ); | 75 | lFilts.prepend( pFlt ); |
76 | } | 76 | } |
77 | 77 | ||
78 | template<typename filter, typename p1t, typename p2t, typename p3t> | 78 | template<typename filter, typename p1t, typename p2t, typename p3t> |
79 | void pushFilter( p1t p1, p2t p2, p3t p3 ) | 79 | void pushFilter( p1t p1, p2t p2, p3t p3 ) |
80 | { | 80 | { |
81 | checkStack(); | 81 | checkStack(); |
82 | 82 | ||
83 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 ); | 83 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 ); |
84 | lFilts.prepend( pFlt ); | 84 | lFilts.prepend( pFlt ); |
85 | } | 85 | } |
86 | 86 | ||
87 | template<typename filter, typename p1t, typename p2t, typename p3t, | 87 | template<typename filter, typename p1t, typename p2t, typename p3t, |
88 | typename p4t> | 88 | typename p4t> |
89 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 ) | 89 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 ) |
90 | { | 90 | { |
91 | checkStack(); | 91 | checkStack(); |
92 | 92 | ||
93 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 ); | 93 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 ); |
94 | lFilts.prepend( pFlt ); | 94 | lFilts.prepend( pFlt ); |
95 | } | 95 | } |
96 | 96 | ||
97 | template<typename filter, typename p1t, typename p2t, typename p3t, | 97 | template<typename filter, typename p1t, typename p2t, typename p3t, |
98 | typename p4t, typename p5t> | 98 | typename p4t, typename p5t> |
99 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 99 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
100 | { | 100 | { |
101 | checkStack(); | 101 | checkStack(); |
102 | 102 | ||
103 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 ); | 103 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 ); |
104 | lFilts.prepend( pFlt ); | 104 | lFilts.prepend( pFlt ); |
105 | } | 105 | } |
106 | 106 | ||
107 | // | 107 | // |
108 | // Everything below here merely passes on the call to the top of the | 108 | // Everything below here merely passes on the call to the top of the |
109 | // stream stack. | 109 | // stream stack. |
110 | // | 110 | // |
111 | 111 | ||
112 | virtual void close(); | 112 | virtual void close(); |
113 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 113 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
114 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 114 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
115 | 115 | ||
116 | virtual Bu::size write( const Bu::String &sBuf ); | 116 | virtual Bu::size write( const Bu::String &sBuf ); |
117 | virtual Bu::size tell(); | 117 | virtual Bu::size tell(); |
118 | virtual void seek( Bu::size offset ); | 118 | virtual void seek( Bu::size offset ); |
119 | virtual void setPos( Bu::size pos ); | 119 | virtual void setPos( Bu::size pos ); |
120 | virtual void setPosEnd( Bu::size pos ); | 120 | virtual void setPosEnd( Bu::size pos ); |
121 | virtual bool isEos(); | 121 | virtual bool isEos(); |
122 | virtual bool isOpen(); | 122 | virtual bool isOpen(); |
123 | virtual void flush(); | 123 | virtual void flush(); |
124 | virtual bool canRead(); | 124 | virtual bool canRead(); |
125 | virtual bool canWrite(); | 125 | virtual bool canWrite(); |
126 | virtual bool isReadable(); | 126 | virtual bool isReadable(); |
127 | virtual bool isWritable(); | 127 | virtual bool isWritable(); |
128 | virtual bool isSeekable(); | 128 | virtual bool isSeekable(); |
129 | virtual bool isBlocking(); | 129 | virtual bool isBlocking(); |
130 | virtual void setBlocking( bool bBlocking=true ); | 130 | virtual void setBlocking( bool bBlocking=true ); |
131 | virtual void setSize( Bu::size iSize ); | 131 | virtual void setSize( Bu::size iSize ); |
132 | virtual size getSize() const; | 132 | virtual size getSize() const; |
133 | virtual size getBlockSize() const; | 133 | virtual size getBlockSize() const; |
134 | virtual Bu::String getLocation() const; | 134 | virtual Bu::String getLocation() const; |
135 | 135 | ||
136 | private: | 136 | private: |
137 | void checkStack() const; | 137 | void checkStack() const; |
138 | 138 | ||
139 | private: | 139 | private: |
140 | FilterList lFilts; | 140 | FilterList lFilts; |
141 | }; | 141 | }; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | #endif | 144 | #endif |
diff --git a/src/stable/strfilter.h b/src/stable/strfilter.h index 8da0a3f..c910574 100644 --- a/src/stable/strfilter.h +++ b/src/stable/strfilter.h | |||
@@ -6,119 +6,119 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | // | 9 | // |
10 | // Encoders | 10 | // Encoders |
11 | // | 11 | // |
12 | template<typename tFilter> | 12 | template<typename tFilter> |
13 | Bu::String encodeStr( const Bu::String &sIn ) | 13 | Bu::String encodeStr( const Bu::String &sIn ) |
14 | { | 14 | { |
15 | Bu::MemBuf mb; | 15 | Bu::MemBuf mb; |
16 | { | 16 | { |
17 | tFilter fEnc( mb ); | 17 | tFilter fEnc( mb ); |
18 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 18 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
19 | } | 19 | } |
20 | return mb.getString(); | 20 | return mb.getString(); |
21 | } | 21 | } |
22 | 22 | ||
23 | template<typename tFilter, typename p1t> | 23 | template<typename tFilter, typename p1t> |
24 | Bu::String encodeStr( const Bu::String &sIn, p1t p1 ) | 24 | Bu::String encodeStr( const Bu::String &sIn, p1t p1 ) |
25 | { | 25 | { |
26 | Bu::MemBuf mb; | 26 | Bu::MemBuf mb; |
27 | { | 27 | { |
28 | tFilter fEnc( mb, p1 ); | 28 | tFilter fEnc( mb, p1 ); |
29 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 29 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
30 | } | 30 | } |
31 | return mb.getString(); | 31 | return mb.getString(); |
32 | } | 32 | } |
33 | 33 | ||
34 | template<typename tFilter, typename p1t, typename p2t> | 34 | template<typename tFilter, typename p1t, typename p2t> |
35 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) | 35 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) |
36 | { | 36 | { |
37 | Bu::MemBuf mb; | 37 | Bu::MemBuf mb; |
38 | { | 38 | { |
39 | tFilter fEnc( mb, p1, p2 ); | 39 | tFilter fEnc( mb, p1, p2 ); |
40 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 40 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
41 | } | 41 | } |
42 | return mb.getString(); | 42 | return mb.getString(); |
43 | } | 43 | } |
44 | 44 | ||
45 | template<typename tFilter, typename p1t, typename p2t, typename p3t> | 45 | template<typename tFilter, typename p1t, typename p2t, typename p3t> |
46 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) | 46 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) |
47 | { | 47 | { |
48 | Bu::MemBuf mb; | 48 | Bu::MemBuf mb; |
49 | { | 49 | { |
50 | tFilter fEnc( mb, p1, p2 ); | 50 | tFilter fEnc( mb, p1, p2 ); |
51 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 51 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
52 | } | 52 | } |
53 | return mb.getString(); | 53 | return mb.getString(); |
54 | } | 54 | } |
55 | 55 | ||
56 | // | 56 | // |
57 | // Decoders | 57 | // Decoders |
58 | // | 58 | // |
59 | template<typename tFilter> | 59 | template<typename tFilter> |
60 | Bu::String decodeStr( const Bu::String &sIn ) | 60 | Bu::String decodeStr( const Bu::String &sIn ) |
61 | { | 61 | { |
62 | Bu::MemBuf mb( sIn ); | 62 | Bu::MemBuf mb( sIn ); |
63 | tFilter fDec( mb ); | 63 | tFilter fDec( mb ); |
64 | char buf[1024]; | 64 | char buf[1024]; |
65 | String sRet; | 65 | String sRet; |
66 | for(;;) | 66 | for(;;) |
67 | { | 67 | { |
68 | int iRead = fDec.read( buf, 1024 ); | 68 | int iRead = fDec.read( buf, 1024 ); |
69 | if( iRead == 0 ) | 69 | if( iRead == 0 ) |
70 | return sRet; | 70 | return sRet; |
71 | sRet.append( buf, iRead ); | 71 | sRet.append( buf, iRead ); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename tFilter, typename p1t> | 75 | template<typename tFilter, typename p1t> |
76 | Bu::String decodeStr( const Bu::String &sIn, p1t p1 ) | 76 | Bu::String decodeStr( const Bu::String &sIn, p1t p1 ) |
77 | { | 77 | { |
78 | Bu::MemBuf mb( sIn ); | 78 | Bu::MemBuf mb( sIn ); |
79 | tFilter fDec( mb, p1 ); | 79 | tFilter fDec( mb, p1 ); |
80 | char buf[1024]; | 80 | char buf[1024]; |
81 | String sRet; | 81 | String sRet; |
82 | for(;;) | 82 | for(;;) |
83 | { | 83 | { |
84 | int iRead = fDec.read( buf, 1024 ); | 84 | int iRead = fDec.read( buf, 1024 ); |
85 | if( iRead == 0 ) | 85 | if( iRead == 0 ) |
86 | return sRet; | 86 | return sRet; |
87 | sRet.append( buf, iRead ); | 87 | sRet.append( buf, iRead ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
91 | template<typename tFilter, typename p1t, typename p2t> | 91 | template<typename tFilter, typename p1t, typename p2t> |
92 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) | 92 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) |
93 | { | 93 | { |
94 | Bu::MemBuf mb( sIn ); | 94 | Bu::MemBuf mb( sIn ); |
95 | tFilter fDec( mb, p1, p2 ); | 95 | tFilter fDec( mb, p1, p2 ); |
96 | char buf[1024]; | 96 | char buf[1024]; |
97 | String sRet; | 97 | String sRet; |
98 | for(;;) | 98 | for(;;) |
99 | { | 99 | { |
100 | int iRead = fDec.read( buf, 1024 ); | 100 | int iRead = fDec.read( buf, 1024 ); |
101 | if( iRead == 0 ) | 101 | if( iRead == 0 ) |
102 | return sRet; | 102 | return sRet; |
103 | sRet.append( buf, iRead ); | 103 | sRet.append( buf, iRead ); |
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | template<typename tFilter, typename p1t, typename p2t, typename p3t> | 107 | template<typename tFilter, typename p1t, typename p2t, typename p3t> |
108 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) | 108 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) |
109 | { | 109 | { |
110 | Bu::MemBuf mb( sIn ); | 110 | Bu::MemBuf mb( sIn ); |
111 | tFilter fDec( mb, p1, p2, p3 ); | 111 | tFilter fDec( mb, p1, p2, p3 ); |
112 | char buf[1024]; | 112 | char buf[1024]; |
113 | String sRet; | 113 | String sRet; |
114 | for(;;) | 114 | for(;;) |
115 | { | 115 | { |
116 | int iRead = fDec.read( buf, 1024 ); | 116 | int iRead = fDec.read( buf, 1024 ); |
117 | if( iRead == 0 ) | 117 | if( iRead == 0 ) |
118 | return sRet; | 118 | return sRet; |
119 | sRet.append( buf, iRead ); | 119 | sRet.append( buf, iRead ); |
120 | } | 120 | } |
121 | } | 121 | } |
122 | }; | 122 | }; |
123 | 123 | ||
124 | #endif | 124 | #endif |
diff --git a/src/stable/string.cpp b/src/stable/string.cpp index dd484fd..d073ec6 100644 --- a/src/stable/string.cpp +++ b/src/stable/string.cpp | |||
@@ -14,117 +14,117 @@ | |||
14 | #include "bu/formatter.h" | 14 | #include "bu/formatter.h" |
15 | #include <stdlib.h> | 15 | #include <stdlib.h> |
16 | 16 | ||
17 | #define nMinSize (256) | 17 | #define nMinSize (256) |
18 | 18 | ||
19 | Bu::StringCore::StringCore() : | 19 | Bu::StringCore::StringCore() : |
20 | nLength( 0 ), | 20 | nLength( 0 ), |
21 | pFirst( NULL ), | 21 | pFirst( NULL ), |
22 | pLast( NULL ) | 22 | pLast( NULL ) |
23 | { | 23 | { |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::StringCore::StringCore( const StringCore &rSrc ) : | 26 | Bu::StringCore::StringCore( const StringCore &rSrc ) : |
27 | nLength( rSrc.nLength ), | 27 | nLength( rSrc.nLength ), |
28 | pFirst( NULL ), | 28 | pFirst( NULL ), |
29 | pLast( NULL ) | 29 | pLast( NULL ) |
30 | { | 30 | { |
31 | if( rSrc.pFirst == NULL || rSrc.nLength == 0 ) | 31 | if( rSrc.pFirst == NULL || rSrc.nLength == 0 ) |
32 | { | 32 | { |
33 | pFirst = pLast = NULL; | 33 | pFirst = pLast = NULL; |
34 | } | 34 | } |
35 | else | 35 | else |
36 | { | 36 | { |
37 | pFirst = pLast = newChunk( nLength ); | 37 | pFirst = pLast = newChunk( nLength ); |
38 | Chunk *pLink = rSrc.pFirst; | 38 | Chunk *pLink = rSrc.pFirst; |
39 | int iPos = 0; | 39 | int iPos = 0; |
40 | while( pLink != NULL ) | 40 | while( pLink != NULL ) |
41 | { | 41 | { |
42 | memcpy( pFirst->pData+iPos, pLink->pData, pLink->nLength ); | 42 | memcpy( pFirst->pData+iPos, pLink->pData, pLink->nLength ); |
43 | iPos += pLink->nLength; | 43 | iPos += pLink->nLength; |
44 | pLink = pLink->pNext; | 44 | pLink = pLink->pNext; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::StringCore::~StringCore() | 49 | Bu::StringCore::~StringCore() |
50 | { | 50 | { |
51 | clear(); | 51 | clear(); |
52 | } | 52 | } |
53 | 53 | ||
54 | void Bu::StringCore::clear() const | 54 | void Bu::StringCore::clear() const |
55 | { | 55 | { |
56 | if( pFirst == NULL ) | 56 | if( pFirst == NULL ) |
57 | return; | 57 | return; |
58 | 58 | ||
59 | Chunk *i = pFirst; | 59 | Chunk *i = pFirst; |
60 | for(;;) | 60 | for(;;) |
61 | { | 61 | { |
62 | Chunk *n = i->pNext; | 62 | Chunk *n = i->pNext; |
63 | delete[] i->pData; | 63 | delete[] i->pData; |
64 | delete i; | 64 | delete i; |
65 | if( n == NULL ) | 65 | if( n == NULL ) |
66 | break; | 66 | break; |
67 | i = n; | 67 | i = n; |
68 | } | 68 | } |
69 | pFirst = pLast = NULL; | 69 | pFirst = pLast = NULL; |
70 | nLength = 0; | 70 | nLength = 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | Bu::StringCore::Chunk *Bu::StringCore::newChunk() const | 73 | Bu::StringCore::Chunk *Bu::StringCore::newChunk() const |
74 | { | 74 | { |
75 | Chunk *pNew = new Chunk; | 75 | Chunk *pNew = new Chunk; |
76 | pNew->pNext = NULL; | 76 | pNew->pNext = NULL; |
77 | return pNew; | 77 | return pNew; |
78 | } | 78 | } |
79 | 79 | ||
80 | Bu::StringCore::Chunk *Bu::StringCore::newChunk( long nLen ) const | 80 | Bu::StringCore::Chunk *Bu::StringCore::newChunk( long nLen ) const |
81 | { | 81 | { |
82 | Chunk *pNew = new Chunk; | 82 | Chunk *pNew = new Chunk; |
83 | pNew->pNext = NULL; | 83 | pNew->pNext = NULL; |
84 | pNew->nLength = nLen; | 84 | pNew->nLength = nLen; |
85 | pNew->pData = new char[(nLen<nMinSize)?(nMinSize):(nLen)+1]; | 85 | pNew->pData = new char[(nLen<nMinSize)?(nMinSize):(nLen)+1]; |
86 | pNew->pData[nLen] = (char)0; | 86 | pNew->pData[nLen] = (char)0; |
87 | return pNew; | 87 | return pNew; |
88 | } | 88 | } |
89 | 89 | ||
90 | Bu::StringCore::Chunk *Bu::StringCore::copyChunk( | 90 | Bu::StringCore::Chunk *Bu::StringCore::copyChunk( |
91 | Bu::StringCore::Chunk *pSrc ) const | 91 | Bu::StringCore::Chunk *pSrc ) const |
92 | { | 92 | { |
93 | Chunk *pNew = new Chunk; | 93 | Chunk *pNew = new Chunk; |
94 | pNew->pNext = pSrc->pNext; | 94 | pNew->pNext = pSrc->pNext; |
95 | pNew->nLength = pSrc->nLength; | 95 | pNew->nLength = pSrc->nLength; |
96 | pNew->pData = new char[ | 96 | pNew->pData = new char[ |
97 | (pNew->nLength<nMinSize)?(nMinSize):(pNew->nLength)+1 | 97 | (pNew->nLength<nMinSize)?(nMinSize):(pNew->nLength)+1 |
98 | ]; | 98 | ]; |
99 | memcpy( pNew->pData, pSrc->pData, pSrc->nLength ); | 99 | memcpy( pNew->pData, pSrc->pData, pSrc->nLength ); |
100 | pNew->pData[pNew->nLength] = (char)0; | 100 | pNew->pData[pNew->nLength] = (char)0; |
101 | return pNew; | 101 | return pNew; |
102 | } | 102 | } |
103 | 103 | ||
104 | void Bu::StringCore::appendChunk( Bu::StringCore::Chunk *pNewChunk ) | 104 | void Bu::StringCore::appendChunk( Bu::StringCore::Chunk *pNewChunk ) |
105 | { | 105 | { |
106 | if( pFirst == NULL ) | 106 | if( pFirst == NULL ) |
107 | pLast = pFirst = pNewChunk; | 107 | pLast = pFirst = pNewChunk; |
108 | else | 108 | else |
109 | { | 109 | { |
110 | pLast->pNext = pNewChunk; | 110 | pLast->pNext = pNewChunk; |
111 | pLast = pNewChunk; | 111 | pLast = pNewChunk; |
112 | } | 112 | } |
113 | 113 | ||
114 | nLength += pNewChunk->nLength; | 114 | nLength += pNewChunk->nLength; |
115 | } | 115 | } |
116 | 116 | ||
117 | void Bu::StringCore::prependChunk( Bu::StringCore::Chunk *pNewChunk ) | 117 | void Bu::StringCore::prependChunk( Bu::StringCore::Chunk *pNewChunk ) |
118 | { | 118 | { |
119 | if( pFirst == NULL ) | 119 | if( pFirst == NULL ) |
120 | pLast = pFirst = pNewChunk; | 120 | pLast = pFirst = pNewChunk; |
121 | else | 121 | else |
122 | { | 122 | { |
123 | pNewChunk->pNext = pFirst; | 123 | pNewChunk->pNext = pFirst; |
124 | pFirst = pNewChunk; | 124 | pFirst = pNewChunk; |
125 | } | 125 | } |
126 | 126 | ||
127 | nLength += pNewChunk->nLength; | 127 | nLength += pNewChunk->nLength; |
128 | } | 128 | } |
129 | 129 | ||
130 | Bu::String::String() | 130 | Bu::String::String() |
@@ -133,44 +133,44 @@ Bu::String::String() | |||
133 | 133 | ||
134 | Bu::String::String( const char *pData ) | 134 | Bu::String::String( const char *pData ) |
135 | { | 135 | { |
136 | append( pData ); | 136 | append( pData ); |
137 | } | 137 | } |
138 | 138 | ||
139 | Bu::String::String( const char *pData, long nLength ) | 139 | Bu::String::String( const char *pData, long nLength ) |
140 | { | 140 | { |
141 | append( pData, nLength ); | 141 | append( pData, nLength ); |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::String::String( const Bu::String &rSrc ) : | 144 | Bu::String::String( const Bu::String &rSrc ) : |
145 | Bu::SharedCore<Bu::String, Bu::StringCore>( rSrc ) | 145 | Bu::SharedCore<Bu::String, Bu::StringCore>( rSrc ) |
146 | { | 146 | { |
147 | } | 147 | } |
148 | 148 | ||
149 | Bu::String::String( const Bu::String &rSrc, long nLength ) | 149 | Bu::String::String( const Bu::String &rSrc, long nLength ) |
150 | { | 150 | { |
151 | append( rSrc, nLength ); | 151 | append( rSrc, nLength ); |
152 | } | 152 | } |
153 | 153 | ||
154 | Bu::String::String( const Bu::String &rSrc, long nStart, long nLength ) | 154 | Bu::String::String( const Bu::String &rSrc, long nStart, long nLength ) |
155 | { | 155 | { |
156 | append( rSrc, nStart, nLength ); | 156 | append( rSrc, nStart, nLength ); |
157 | } | 157 | } |
158 | 158 | ||
159 | Bu::String::String( long nSize ) | 159 | Bu::String::String( long nSize ) |
160 | { | 160 | { |
161 | core->pFirst = core->pLast = core->newChunk( nSize ); | 161 | core->pFirst = core->pLast = core->newChunk( nSize ); |
162 | core->nLength = nSize; | 162 | core->nLength = nSize; |
163 | } | 163 | } |
164 | 164 | ||
165 | Bu::String::String( const Bu::String::const_iterator &s ) | 165 | Bu::String::String( const Bu::String::const_iterator &s ) |
166 | { | 166 | { |
167 | append( s ); | 167 | append( s ); |
168 | } | 168 | } |
169 | 169 | ||
170 | Bu::String::String( const Bu::String::const_iterator &s, | 170 | Bu::String::String( const Bu::String::const_iterator &s, |
171 | const Bu::String::const_iterator &e ) | 171 | const Bu::String::const_iterator &e ) |
172 | { | 172 | { |
173 | append( s, e ); | 173 | append( s, e ); |
174 | } | 174 | } |
175 | 175 | ||
176 | Bu::String::~String() | 176 | Bu::String::~String() |
@@ -179,1049 +179,1049 @@ Bu::String::~String() | |||
179 | 179 | ||
180 | void Bu::String::append( const char *pData ) | 180 | void Bu::String::append( const char *pData ) |
181 | { | 181 | { |
182 | if( !pData ) return; | 182 | if( !pData ) return; |
183 | long nLen; | 183 | long nLen; |
184 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } | 184 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } |
185 | 185 | ||
186 | append( pData, 0, nLen ); | 186 | append( pData, 0, nLen ); |
187 | } | 187 | } |
188 | 188 | ||
189 | void Bu::String::append( const char *pData, long nLen ) | 189 | void Bu::String::append( const char *pData, long nLen ) |
190 | { | 190 | { |
191 | append( pData, 0, nLen ); | 191 | append( pData, 0, nLen ); |
192 | } | 192 | } |
193 | 193 | ||
194 | void Bu::String::append( const char *pData, long nStart, long nLen ) | 194 | void Bu::String::append( const char *pData, long nStart, long nLen ) |
195 | { | 195 | { |
196 | if( !pData ) return; | 196 | if( !pData ) return; |
197 | if( nLen <= 0 ) | 197 | if( nLen <= 0 ) |
198 | return; | 198 | return; |
199 | 199 | ||
200 | pData += nStart; | 200 | pData += nStart; |
201 | 201 | ||
202 | _hardCopy(); | 202 | _hardCopy(); |
203 | 203 | ||
204 | if( core->pLast && core->pLast->nLength < nMinSize ) | 204 | if( core->pLast && core->pLast->nLength < nMinSize ) |
205 | { | 205 | { |
206 | int nAmnt = nMinSize - core->pLast->nLength; | 206 | int nAmnt = nMinSize - core->pLast->nLength; |
207 | if( nAmnt > nLen ) | 207 | if( nAmnt > nLen ) |
208 | nAmnt = nLen; | 208 | nAmnt = nLen; |
209 | memcpy( | 209 | memcpy( |
210 | core->pLast->pData+core->pLast->nLength, | 210 | core->pLast->pData+core->pLast->nLength, |
211 | pData, | 211 | pData, |
212 | nAmnt | 212 | nAmnt |
213 | ); | 213 | ); |
214 | pData += nAmnt; | 214 | pData += nAmnt; |
215 | core->pLast->nLength += nAmnt; | 215 | core->pLast->nLength += nAmnt; |
216 | nLen -= nAmnt; | 216 | nLen -= nAmnt; |
217 | core->nLength += nAmnt; | 217 | core->nLength += nAmnt; |
218 | } | 218 | } |
219 | 219 | ||
220 | if( nLen > 0 ) | 220 | if( nLen > 0 ) |
221 | { | 221 | { |
222 | Chunk *pNew = core->newChunk( nLen ); | 222 | Chunk *pNew = core->newChunk( nLen ); |
223 | memcpy( pNew->pData, pData, nLen ); | 223 | memcpy( pNew->pData, pData, nLen ); |
224 | core->appendChunk( pNew ); | 224 | core->appendChunk( pNew ); |
225 | // core->nLength += nLen; | 225 | // core->nLength += nLen; |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | void Bu::String::append( const char &cData ) | 229 | void Bu::String::append( const char &cData ) |
230 | { | 230 | { |
231 | if( core->pLast && core->pLast->nLength < nMinSize ) | 231 | if( core->pLast && core->pLast->nLength < nMinSize ) |
232 | { | 232 | { |
233 | _hardCopy(); | 233 | _hardCopy(); |
234 | core->pLast->pData[core->pLast->nLength] = cData; | 234 | core->pLast->pData[core->pLast->nLength] = cData; |
235 | ++core->pLast->nLength; ++core->nLength; | 235 | ++core->pLast->nLength; ++core->nLength; |
236 | // pLast->pData[pLast->nLength] = (char)0; | 236 | // pLast->pData[pLast->nLength] = (char)0; |
237 | } | 237 | } |
238 | else | 238 | else |
239 | { | 239 | { |
240 | append( &cData, 1 ); | 240 | append( &cData, 1 ); |
241 | } | 241 | } |
242 | } | 242 | } |
243 | 243 | ||
244 | void Bu::String::append( const String & sData ) | 244 | void Bu::String::append( const String & sData ) |
245 | { | 245 | { |
246 | append( sData.getStr(), 0, sData.getSize() ); | 246 | append( sData.getStr(), 0, sData.getSize() ); |
247 | } | 247 | } |
248 | 248 | ||
249 | void Bu::String::append( const String & sData, long nLen ) | 249 | void Bu::String::append( const String & sData, long nLen ) |
250 | { | 250 | { |
251 | append( sData.getStr(), 0, nLen ); | 251 | append( sData.getStr(), 0, nLen ); |
252 | } | 252 | } |
253 | 253 | ||
254 | void Bu::String::append( const String & sData, long nStart, long nLen ) | 254 | void Bu::String::append( const String & sData, long nStart, long nLen ) |
255 | { | 255 | { |
256 | if( nLen < 0 ) | 256 | if( nLen < 0 ) |
257 | nLen = sData.getSize() - nStart; | 257 | nLen = sData.getSize() - nStart; |
258 | append( sData.getStr(), nStart, nLen ); | 258 | append( sData.getStr(), nStart, nLen ); |
259 | } | 259 | } |
260 | 260 | ||
261 | void Bu::String::append( const const_iterator &s ) | 261 | void Bu::String::append( const const_iterator &s ) |
262 | { | 262 | { |
263 | if( !s.isValid() ) | 263 | if( !s.isValid() ) |
264 | return; | 264 | return; |
265 | Chunk *pSrc = s.pChunk; | 265 | Chunk *pSrc = s.pChunk; |
266 | 266 | ||
267 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); | 267 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); |
268 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | 268 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); |
269 | 269 | ||
270 | _hardCopy(); | 270 | _hardCopy(); |
271 | core->appendChunk( pNew ); | 271 | core->appendChunk( pNew ); |
272 | 272 | ||
273 | while( (pSrc = pSrc->pNext) ) | 273 | while( (pSrc = pSrc->pNext) ) |
274 | { | 274 | { |
275 | core->appendChunk( core->copyChunk( pSrc ) ); | 275 | core->appendChunk( core->copyChunk( pSrc ) ); |
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
279 | void Bu::String::append( const iterator &s ) | 279 | void Bu::String::append( const iterator &s ) |
280 | { | 280 | { |
281 | append( const_iterator( s ) ); | 281 | append( const_iterator( s ) ); |
282 | } | 282 | } |
283 | 283 | ||
284 | void Bu::String::append( const const_iterator &s, const const_iterator &e ) | 284 | void Bu::String::append( const const_iterator &s, const const_iterator &e ) |
285 | { | 285 | { |
286 | if( !s.isValid() ) | 286 | if( !s.isValid() ) |
287 | return; | 287 | return; |
288 | if( !e.isValid() ) | 288 | if( !e.isValid() ) |
289 | { | 289 | { |
290 | append( s ); | 290 | append( s ); |
291 | return; | 291 | return; |
292 | } | 292 | } |
293 | _hardCopy(); | 293 | _hardCopy(); |
294 | if( s.pChunk == e.pChunk ) | 294 | if( s.pChunk == e.pChunk ) |
295 | { | 295 | { |
296 | // Simple case, they're the same chunk | 296 | // Simple case, they're the same chunk |
297 | Chunk *pNew = core->newChunk( e.iPos-s.iPos ); | 297 | Chunk *pNew = core->newChunk( e.iPos-s.iPos ); |
298 | memcpy( pNew->pData, s.pChunk->pData+s.iPos, e.iPos-s.iPos ); | 298 | memcpy( pNew->pData, s.pChunk->pData+s.iPos, e.iPos-s.iPos ); |
299 | core->appendChunk( pNew ); | 299 | core->appendChunk( pNew ); |
300 | } | 300 | } |
301 | else | 301 | else |
302 | { | 302 | { |
303 | // A little trickier, scan the blocks... | 303 | // A little trickier, scan the blocks... |
304 | Chunk *pSrc = s.pChunk; | 304 | Chunk *pSrc = s.pChunk; |
305 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); | 305 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); |
306 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | 306 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); |
307 | core->appendChunk( pNew ); | 307 | core->appendChunk( pNew ); |
308 | 308 | ||
309 | while( (pSrc = pSrc->pNext) != e.pChunk ) | 309 | while( (pSrc = pSrc->pNext) != e.pChunk ) |
310 | { | 310 | { |
311 | core->appendChunk( core->copyChunk( pSrc ) ); | 311 | core->appendChunk( core->copyChunk( pSrc ) ); |
312 | } | 312 | } |
313 | 313 | ||
314 | pNew = core->newChunk( e.iPos ); | 314 | pNew = core->newChunk( e.iPos ); |
315 | memcpy( pNew->pData, pSrc->pData, e.iPos ); | 315 | memcpy( pNew->pData, pSrc->pData, e.iPos ); |
316 | core->appendChunk( pNew ); | 316 | core->appendChunk( pNew ); |
317 | } | 317 | } |
318 | } | 318 | } |
319 | 319 | ||
320 | void Bu::String::prepend( const String & sData ) | 320 | void Bu::String::prepend( const String & sData ) |
321 | { | 321 | { |
322 | prepend( sData.getStr(), sData.getSize() ); | 322 | prepend( sData.getStr(), sData.getSize() ); |
323 | } | 323 | } |
324 | 324 | ||
325 | void Bu::String::prepend( const char *pData ) | 325 | void Bu::String::prepend( const char *pData ) |
326 | { | 326 | { |
327 | if( pData == NULL ) | 327 | if( pData == NULL ) |
328 | return; | 328 | return; |
329 | 329 | ||
330 | _hardCopy(); | 330 | _hardCopy(); |
331 | long nLen; | 331 | long nLen; |
332 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } | 332 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } |
333 | 333 | ||
334 | Chunk *pNew = core->newChunk( nLen ); | 334 | Chunk *pNew = core->newChunk( nLen ); |
335 | memcpy( pNew->pData, pData, nLen ); | 335 | memcpy( pNew->pData, pData, nLen ); |
336 | 336 | ||
337 | core->prependChunk( pNew ); | 337 | core->prependChunk( pNew ); |
338 | } | 338 | } |
339 | 339 | ||
340 | void Bu::String::prepend( const char *pData, long nLen ) | 340 | void Bu::String::prepend( const char *pData, long nLen ) |
341 | { | 341 | { |
342 | Chunk *pNew = core->newChunk( nLen ); | 342 | Chunk *pNew = core->newChunk( nLen ); |
343 | 343 | ||
344 | memcpy( pNew->pData, pData, nLen ); | 344 | memcpy( pNew->pData, pData, nLen ); |
345 | 345 | ||
346 | _hardCopy(); | 346 | _hardCopy(); |
347 | core->prependChunk( pNew ); | 347 | core->prependChunk( pNew ); |
348 | } | 348 | } |
349 | 349 | ||
350 | void Bu::String::prepend( const char c ) | 350 | void Bu::String::prepend( const char c ) |
351 | { | 351 | { |
352 | prepend( &c, 1 ); | 352 | prepend( &c, 1 ); |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::String::insert( long nPos, const char *pData, long nLen ) | 355 | void Bu::String::insert( long nPos, const char *pData, long nLen ) |
356 | { | 356 | { |
357 | if( nLen <= 0 ) | 357 | if( nLen <= 0 ) |
358 | return; | 358 | return; |
359 | if( nPos <= 0 ) | 359 | if( nPos <= 0 ) |
360 | { | 360 | { |
361 | prepend( pData, nLen ); | 361 | prepend( pData, nLen ); |
362 | } | 362 | } |
363 | else if( nPos >= core->nLength ) | 363 | else if( nPos >= core->nLength ) |
364 | { | 364 | { |
365 | append( pData, nLen ); | 365 | append( pData, nLen ); |
366 | } | 366 | } |
367 | else | 367 | else |
368 | { | 368 | { |
369 | // If we're going to flatten anyway, might as well for everyone | 369 | // If we're going to flatten anyway, might as well for everyone |
370 | flatten(); | 370 | flatten(); |
371 | _hardCopy(); | 371 | _hardCopy(); |
372 | Chunk *p1 = core->newChunk( nPos ); | 372 | Chunk *p1 = core->newChunk( nPos ); |
373 | Chunk *p2 = core->newChunk( nLen ); | 373 | Chunk *p2 = core->newChunk( nLen ); |
374 | Chunk *p3 = core->newChunk( core->nLength-nPos ); | 374 | Chunk *p3 = core->newChunk( core->nLength-nPos ); |
375 | memcpy( p1->pData, core->pFirst->pData, nPos ); | 375 | memcpy( p1->pData, core->pFirst->pData, nPos ); |
376 | memcpy( p2->pData, pData, nLen ); | 376 | memcpy( p2->pData, pData, nLen ); |
377 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); | 377 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); |
378 | core->clear(); | 378 | core->clear(); |
379 | core->appendChunk( p1 ); | 379 | core->appendChunk( p1 ); |
380 | core->appendChunk( p2 ); | 380 | core->appendChunk( p2 ); |
381 | core->appendChunk( p3 ); | 381 | core->appendChunk( p3 ); |
382 | } | 382 | } |
383 | } | 383 | } |
384 | 384 | ||
385 | void Bu::String::insert( long nPos, const String &str ) | 385 | void Bu::String::insert( long nPos, const String &str ) |
386 | { | 386 | { |
387 | if( nPos <= 0 ) | 387 | if( nPos <= 0 ) |
388 | { | 388 | { |
389 | prepend( str ); | 389 | prepend( str ); |
390 | } | 390 | } |
391 | else if( nPos >= core->nLength ) | 391 | else if( nPos >= core->nLength ) |
392 | { | 392 | { |
393 | append( str ); | 393 | append( str ); |
394 | } | 394 | } |
395 | else | 395 | else |
396 | { | 396 | { |
397 | flatten(); | 397 | flatten(); |
398 | _hardCopy(); | 398 | _hardCopy(); |
399 | Chunk *p1 = core->newChunk( nPos ); | 399 | Chunk *p1 = core->newChunk( nPos ); |
400 | Chunk *p3 = core->newChunk( core->nLength-nPos ); | 400 | Chunk *p3 = core->newChunk( core->nLength-nPos ); |
401 | memcpy( p1->pData, core->pFirst->pData, nPos ); | 401 | memcpy( p1->pData, core->pFirst->pData, nPos ); |
402 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); | 402 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); |
403 | core->clear(); | 403 | core->clear(); |
404 | core->appendChunk( p1 ); | 404 | core->appendChunk( p1 ); |
405 | for( Chunk *pChnk = str.core->pFirst; pChnk; | 405 | for( Chunk *pChnk = str.core->pFirst; pChnk; |
406 | pChnk = pChnk->pNext ) | 406 | pChnk = pChnk->pNext ) |
407 | { | 407 | { |
408 | core->appendChunk( core->copyChunk( pChnk ) ); | 408 | core->appendChunk( core->copyChunk( pChnk ) ); |
409 | } | 409 | } |
410 | 410 | ||
411 | core->appendChunk( p3 ); | 411 | core->appendChunk( p3 ); |
412 | } | 412 | } |
413 | } | 413 | } |
414 | 414 | ||
415 | void Bu::String::insert( long nPos, const char *pData ) | 415 | void Bu::String::insert( long nPos, const char *pData ) |
416 | { | 416 | { |
417 | insert( nPos, pData, strlen( pData ) ); | 417 | insert( nPos, pData, strlen( pData ) ); |
418 | } | 418 | } |
419 | 419 | ||
420 | void Bu::String::remove( long nPos, long nLen ) | 420 | void Bu::String::remove( long nPos, long nLen ) |
421 | { | 421 | { |
422 | if( nLen <= 0 || nPos < 0 || nPos >= core->nLength ) | 422 | if( nLen <= 0 || nPos < 0 || nPos >= core->nLength ) |
423 | return; | 423 | return; |
424 | if( nLen > core->nLength-nPos ) | 424 | if( nLen > core->nLength-nPos ) |
425 | nLen = core->nLength-nPos; | 425 | nLen = core->nLength-nPos; |
426 | flatten(); | 426 | flatten(); |
427 | _hardCopy(); | 427 | _hardCopy(); |
428 | memmove( core->pFirst->pData+nPos, core->pFirst->pData+nPos+nLen, core->nLength-nPos-nLen+1 ); | 428 | memmove( core->pFirst->pData+nPos, core->pFirst->pData+nPos+nLen, core->nLength-nPos-nLen+1 ); |
429 | core->nLength -= nLen; | 429 | core->nLength -= nLen; |
430 | core->pFirst->nLength -= nLen; | 430 | core->pFirst->nLength -= nLen; |
431 | } | 431 | } |
432 | 432 | ||
433 | void Bu::String::clear() | 433 | void Bu::String::clear() |
434 | { | 434 | { |
435 | _hardCopy(); | 435 | _hardCopy(); |
436 | core->clear(); | 436 | core->clear(); |
437 | } | 437 | } |
438 | 438 | ||
439 | Bu::String Bu::String::replace( const Bu::String &fnd, | 439 | Bu::String Bu::String::replace( const Bu::String &fnd, |
440 | const Bu::String &rep ) const | 440 | const Bu::String &rep ) const |
441 | { | 441 | { |
442 | String out; | 442 | String out; |
443 | const_iterator o = begin(); | 443 | const_iterator o = begin(); |
444 | while( true ) | 444 | while( true ) |
445 | { | 445 | { |
446 | const_iterator i = o.find( fnd, fnd.getSize() ); | 446 | const_iterator i = o.find( fnd, fnd.getSize() ); |
447 | if( !i ) | 447 | if( !i ) |
448 | { | 448 | { |
449 | out.append( o ); | 449 | out.append( o ); |
450 | return out; | 450 | return out; |
451 | } | 451 | } |
452 | else | 452 | else |
453 | { | 453 | { |
454 | out.append( o, i ); | 454 | out.append( o, i ); |
455 | out.append( rep ); | 455 | out.append( rep ); |
456 | o = i; | 456 | o = i; |
457 | o += fnd.getSize(); | 457 | o += fnd.getSize(); |
458 | } | 458 | } |
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | void Bu::String::resize( long nNewSize ) | 462 | void Bu::String::resize( long nNewSize ) |
463 | { | 463 | { |
464 | if( core->nLength == nNewSize ) | 464 | if( core->nLength == nNewSize ) |
465 | return; | 465 | return; |
466 | if( nNewSize < 0 ) | 466 | if( nNewSize < 0 ) |
467 | nNewSize = 0; | 467 | nNewSize = 0; |
468 | 468 | ||
469 | flatten(); | 469 | flatten(); |
470 | _hardCopy(); | 470 | _hardCopy(); |
471 | 471 | ||
472 | // TODO: This is bad | 472 | // TODO: This is bad |
473 | 473 | ||
474 | Chunk *pNew = core->newChunk( nNewSize ); | 474 | Chunk *pNew = core->newChunk( nNewSize ); |
475 | long nNewLen = (nNewSize<core->nLength)?(nNewSize):(core->nLength); | 475 | long nNewLen = (nNewSize<core->nLength)?(nNewSize):(core->nLength); |
476 | if( core->nLength > 0 ) | 476 | if( core->nLength > 0 ) |
477 | { | 477 | { |
478 | memcpy( pNew->pData, core->pFirst->pData, nNewLen ); | 478 | memcpy( pNew->pData, core->pFirst->pData, nNewLen ); |
479 | delete[] core->pFirst->pData; | 479 | delete[] core->pFirst->pData; |
480 | delete core->pFirst; | 480 | delete core->pFirst; |
481 | } | 481 | } |
482 | pNew->pData[nNewLen] = (char)0; | 482 | pNew->pData[nNewLen] = (char)0; |
483 | core->pFirst = core->pLast = pNew; | 483 | core->pFirst = core->pLast = pNew; |
484 | core->nLength = nNewSize; | 484 | core->nLength = nNewSize; |
485 | } | 485 | } |
486 | 486 | ||
487 | long Bu::String::getSize() const | 487 | long Bu::String::getSize() const |
488 | { | 488 | { |
489 | return core->nLength; | 489 | return core->nLength; |
490 | } | 490 | } |
491 | 491 | ||
492 | char *Bu::String::getStr() | 492 | char *Bu::String::getStr() |
493 | { | 493 | { |
494 | if( core->pFirst == NULL || core->nLength == 0 ) | 494 | if( core->pFirst == NULL || core->nLength == 0 ) |
495 | return (char *)""; | 495 | return (char *)""; |
496 | 496 | ||
497 | flatten(); | 497 | flatten(); |
498 | _hardCopy(); | 498 | _hardCopy(); |
499 | core->pFirst->pData[core->nLength] = (char)0; | 499 | core->pFirst->pData[core->nLength] = (char)0; |
500 | return core->pFirst->pData; | 500 | return core->pFirst->pData; |
501 | } | 501 | } |
502 | 502 | ||
503 | const char *Bu::String::getStr() const | 503 | const char *Bu::String::getStr() const |
504 | { | 504 | { |
505 | if( core->pFirst == NULL || core->nLength == 0 ) | 505 | if( core->pFirst == NULL || core->nLength == 0 ) |
506 | return (char *)""; | 506 | return (char *)""; |
507 | 507 | ||
508 | flatten(); | 508 | flatten(); |
509 | core->pFirst->pData[core->nLength] = (char)0; | 509 | core->pFirst->pData[core->nLength] = (char)0; |
510 | return core->pFirst->pData; | 510 | return core->pFirst->pData; |
511 | } | 511 | } |
512 | 512 | ||
513 | const char *Bu::String::getConstStr() const | 513 | const char *Bu::String::getConstStr() const |
514 | { | 514 | { |
515 | return getStr(); | 515 | return getStr(); |
516 | } | 516 | } |
517 | 517 | ||
518 | Bu::String Bu::String::getSubStrIdx( long iStart, long iSize ) const | 518 | Bu::String Bu::String::getSubStrIdx( long iStart, long iSize ) const |
519 | { | 519 | { |
520 | if( iStart < 0 ) | 520 | if( iStart < 0 ) |
521 | iStart = 0; | 521 | iStart = 0; |
522 | if( iStart >= core->nLength ) | 522 | if( iStart >= core->nLength ) |
523 | return (const char[]){(char)0}; | 523 | return (const char[]){(char)0}; |
524 | if( iSize < 0 ) | 524 | if( iSize < 0 ) |
525 | iSize = core->nLength; | 525 | iSize = core->nLength; |
526 | if( iStart+iSize > core->nLength ) | 526 | if( iStart+iSize > core->nLength ) |
527 | iSize = core->nLength-iStart; | 527 | iSize = core->nLength-iStart; |
528 | if( iSize == 0 ) | 528 | if( iSize == 0 ) |
529 | return (const char[]){(char)0}; | 529 | return (const char[]){(char)0}; |
530 | 530 | ||
531 | flatten(); | 531 | flatten(); |
532 | String ret( core->pFirst->pData+iStart, iSize ); | 532 | String ret( core->pFirst->pData+iStart, iSize ); |
533 | return ret; | 533 | return ret; |
534 | } | 534 | } |
535 | 535 | ||
536 | Bu::String Bu::String::getSubStr( const_iterator iBegin, | 536 | Bu::String Bu::String::getSubStr( const_iterator iBegin, |
537 | const_iterator iEnd ) const | 537 | const_iterator iEnd ) const |
538 | { | 538 | { |
539 | if( !iBegin.isValid() ) | 539 | if( !iBegin.isValid() ) |
540 | return String(); | 540 | return String(); |
541 | if( iBegin.pChunk == iEnd.pChunk ) | 541 | if( iBegin.pChunk == iEnd.pChunk ) |
542 | { | 542 | { |
543 | return String( iBegin.pChunk->pData+iBegin.iPos, | 543 | return String( iBegin.pChunk->pData+iBegin.iPos, |
544 | iEnd.iPos-iBegin.iPos ); | 544 | iEnd.iPos-iBegin.iPos ); |
545 | } | 545 | } |
546 | else if( !iEnd.isValid() ) | 546 | else if( !iEnd.isValid() ) |
547 | { | 547 | { |
548 | String ret; | 548 | String ret; |
549 | ret.append( | 549 | ret.append( |
550 | iBegin.pChunk->pData+iBegin.iPos, | 550 | iBegin.pChunk->pData+iBegin.iPos, |
551 | iBegin.pChunk->nLength-iBegin.iPos | 551 | iBegin.pChunk->nLength-iBegin.iPos |
552 | ); | 552 | ); |
553 | for( Chunk *pCur = iBegin.pChunk->pNext; | 553 | for( Chunk *pCur = iBegin.pChunk->pNext; |
554 | pCur; pCur = pCur->pNext ) | 554 | pCur; pCur = pCur->pNext ) |
555 | { | 555 | { |
556 | ret.append( pCur->pData, pCur->nLength ); | 556 | ret.append( pCur->pData, pCur->nLength ); |
557 | } | 557 | } |
558 | return ret; | 558 | return ret; |
559 | } | 559 | } |
560 | else | 560 | else |
561 | { | 561 | { |
562 | String ret; | 562 | String ret; |
563 | ret.append( | 563 | ret.append( |
564 | iBegin.pChunk->pData+iBegin.iPos, | 564 | iBegin.pChunk->pData+iBegin.iPos, |
565 | iBegin.pChunk->nLength-iBegin.iPos | 565 | iBegin.pChunk->nLength-iBegin.iPos |
566 | ); | 566 | ); |
567 | for( Chunk *pCur = iBegin.pChunk->pNext; | 567 | for( Chunk *pCur = iBegin.pChunk->pNext; |
568 | pCur != iEnd.pChunk; pCur = pCur->pNext ) | 568 | pCur != iEnd.pChunk; pCur = pCur->pNext ) |
569 | { | 569 | { |
570 | ret.append( pCur->pData, pCur->nLength ); | 570 | ret.append( pCur->pData, pCur->nLength ); |
571 | } | 571 | } |
572 | ret.append( | 572 | ret.append( |
573 | iEnd.pChunk->pData, | 573 | iEnd.pChunk->pData, |
574 | iEnd.iPos | 574 | iEnd.iPos |
575 | ); | 575 | ); |
576 | return ret; | 576 | return ret; |
577 | } | 577 | } |
578 | } | 578 | } |
579 | 579 | ||
580 | Bu::StringList Bu::String::split( const char c ) const | 580 | Bu::StringList Bu::String::split( const char c ) const |
581 | { | 581 | { |
582 | Bu::StringList ret; | 582 | Bu::StringList ret; |
583 | const_iterator l, r; | 583 | const_iterator l, r; |
584 | l = begin(); | 584 | l = begin(); |
585 | for(r=l; l;) | 585 | for(r=l; l;) |
586 | { | 586 | { |
587 | for( r = l; r && r != c; r++ ) { } | 587 | for( r = l; r && r != c; r++ ) { } |
588 | ret.append( String( l, r ) ); | 588 | ret.append( String( l, r ) ); |
589 | l = r; | 589 | l = r; |
590 | l++; | 590 | l++; |
591 | } | 591 | } |
592 | return ret; | 592 | return ret; |
593 | } | 593 | } |
594 | 594 | ||
595 | Bu::String &Bu::String::operator+=( const char *pData ) | 595 | Bu::String &Bu::String::operator+=( const char *pData ) |
596 | { | 596 | { |
597 | append( pData ); | 597 | append( pData ); |
598 | 598 | ||
599 | return (*this); | 599 | return (*this); |
600 | } | 600 | } |
601 | 601 | ||
602 | Bu::String &Bu::String::operator+=( const Bu::String &rSrc ) | 602 | Bu::String &Bu::String::operator+=( const Bu::String &rSrc ) |
603 | { | 603 | { |
604 | append( rSrc ); | 604 | append( rSrc ); |
605 | 605 | ||
606 | return (*this); | 606 | return (*this); |
607 | } | 607 | } |
608 | 608 | ||
609 | Bu::String &Bu::String::operator+=( const Bu::String::const_iterator &i ) | 609 | Bu::String &Bu::String::operator+=( const Bu::String::const_iterator &i ) |
610 | { | 610 | { |
611 | append( i, i+1 ); | 611 | append( i, i+1 ); |
612 | 612 | ||
613 | return (*this); | 613 | return (*this); |
614 | } | 614 | } |
615 | 615 | ||
616 | Bu::String &Bu::String::operator+=( const char cData ) | 616 | Bu::String &Bu::String::operator+=( const char cData ) |
617 | { | 617 | { |
618 | if( core->pLast && core->pLast->nLength < nMinSize ) | 618 | if( core->pLast && core->pLast->nLength < nMinSize ) |
619 | { | 619 | { |
620 | _hardCopy(); | 620 | _hardCopy(); |
621 | core->pLast->pData[core->pLast->nLength] = cData; | 621 | core->pLast->pData[core->pLast->nLength] = cData; |
622 | ++core->pLast->nLength; ++core->nLength; | 622 | ++core->pLast->nLength; ++core->nLength; |
623 | // pLast->pData[pLast->nLength] = (char)0; | 623 | // pLast->pData[pLast->nLength] = (char)0; |
624 | } | 624 | } |
625 | else | 625 | else |
626 | { | 626 | { |
627 | append( &cData, 1 ); | 627 | append( &cData, 1 ); |
628 | } | 628 | } |
629 | //append( pData ); | 629 | //append( pData ); |
630 | 630 | ||
631 | return (*this); | 631 | return (*this); |
632 | } | 632 | } |
633 | 633 | ||
634 | Bu::String &Bu::String::operator=( const char *pData ) | 634 | Bu::String &Bu::String::operator=( const char *pData ) |
635 | { | 635 | { |
636 | set( pData ); | 636 | set( pData ); |
637 | 637 | ||
638 | return (*this); | 638 | return (*this); |
639 | } | 639 | } |
640 | 640 | ||
641 | Bu::String Bu::String::operator+( const Bu::String &rRight ) const | 641 | Bu::String Bu::String::operator+( const Bu::String &rRight ) const |
642 | { | 642 | { |
643 | String ret( *this ); | 643 | String ret( *this ); |
644 | ret.append( rRight ); | 644 | ret.append( rRight ); |
645 | return ret; | 645 | return ret; |
646 | } | 646 | } |
647 | 647 | ||
648 | Bu::String Bu::String::operator+( const char *pRight ) const | 648 | Bu::String Bu::String::operator+( const char *pRight ) const |
649 | { | 649 | { |
650 | String ret( *this ); | 650 | String ret( *this ); |
651 | ret.append( pRight ); | 651 | ret.append( pRight ); |
652 | return ret; | 652 | return ret; |
653 | } | 653 | } |
654 | 654 | ||
655 | Bu::String Bu::String::operator+( char *pRight ) const | 655 | Bu::String Bu::String::operator+( char *pRight ) const |
656 | { | 656 | { |
657 | String ret( *this ); | 657 | String ret( *this ); |
658 | ret.append( pRight ); | 658 | ret.append( pRight ); |
659 | return ret; | 659 | return ret; |
660 | } | 660 | } |
661 | 661 | ||
662 | void Bu::String::set( const char *pData ) | 662 | void Bu::String::set( const char *pData ) |
663 | { | 663 | { |
664 | clear(); | 664 | clear(); |
665 | append( pData ); | 665 | append( pData ); |
666 | } | 666 | } |
667 | 667 | ||
668 | void Bu::String::set( const char *pData, long nSize ) | 668 | void Bu::String::set( const char *pData, long nSize ) |
669 | { | 669 | { |
670 | clear(); | 670 | clear(); |
671 | append( pData, nSize ); | 671 | append( pData, nSize ); |
672 | } | 672 | } |
673 | 673 | ||
674 | void Bu::String::set( const char *pData, long nStart, long nSize ) | 674 | void Bu::String::set( const char *pData, long nStart, long nSize ) |
675 | { | 675 | { |
676 | clear(); | 676 | clear(); |
677 | append( pData, nStart, nSize ); | 677 | append( pData, nStart, nSize ); |
678 | } | 678 | } |
679 | 679 | ||
680 | void Bu::String::set( const String &rData ) | 680 | void Bu::String::set( const String &rData ) |
681 | { | 681 | { |
682 | clear(); | 682 | clear(); |
683 | append( rData ); | 683 | append( rData ); |
684 | } | 684 | } |
685 | 685 | ||
686 | void Bu::String::set( const String &rData, long nSize ) | 686 | void Bu::String::set( const String &rData, long nSize ) |
687 | { | 687 | { |
688 | clear(); | 688 | clear(); |
689 | append( rData, nSize ); | 689 | append( rData, nSize ); |
690 | } | 690 | } |
691 | 691 | ||
692 | void Bu::String::set( const String &rData, long nStart, long nSize ) | 692 | void Bu::String::set( const String &rData, long nStart, long nSize ) |
693 | { | 693 | { |
694 | clear(); | 694 | clear(); |
695 | append( rData, nStart, nSize ); | 695 | append( rData, nStart, nSize ); |
696 | } | 696 | } |
697 | 697 | ||
698 | void Bu::String::set( const_iterator s ) | 698 | void Bu::String::set( const_iterator s ) |
699 | { | 699 | { |
700 | clear(); | 700 | clear(); |
701 | append( s ); | 701 | append( s ); |
702 | } | 702 | } |
703 | 703 | ||
704 | void Bu::String::set( const_iterator s, const_iterator e ) | 704 | void Bu::String::set( const_iterator s, const_iterator e ) |
705 | { | 705 | { |
706 | clear(); | 706 | clear(); |
707 | append( s, e ); | 707 | append( s, e ); |
708 | } | 708 | } |
709 | 709 | ||
710 | void Bu::String::setSize( long iSize ) | 710 | void Bu::String::setSize( long iSize ) |
711 | { | 711 | { |
712 | _hardCopy(); | 712 | _hardCopy(); |
713 | core->clear(); | 713 | core->clear(); |
714 | core->appendChunk( core->newChunk( iSize ) ); | 714 | core->appendChunk( core->newChunk( iSize ) ); |
715 | } | 715 | } |
716 | 716 | ||
717 | bool Bu::String::operator==( const char *pData ) const | 717 | bool Bu::String::operator==( const char *pData ) const |
718 | { | 718 | { |
719 | if( core->pFirst == NULL || core->nLength == 0 ) { | 719 | if( core->pFirst == NULL || core->nLength == 0 ) { |
720 | if( pData == NULL ) | 720 | if( pData == NULL ) |
721 | return true; | 721 | return true; |
722 | if( pData[0] == (char)0 ) | 722 | if( pData[0] == (char)0 ) |
723 | return true; | 723 | return true; |
724 | return false; | 724 | return false; |
725 | } | 725 | } |
726 | 726 | ||
727 | flatten(); | 727 | flatten(); |
728 | core->pFirst->pData[core->nLength] = (char)0; | 728 | core->pFirst->pData[core->nLength] = (char)0; |
729 | const char *a = pData; | 729 | const char *a = pData; |
730 | char *b = core->pFirst->pData; | 730 | char *b = core->pFirst->pData; |
731 | for( long j = 0; *a!=(char)0 || *b!=(char)0; j++, a++, b++ ) | 731 | for( long j = 0; *a!=(char)0 || *b!=(char)0; j++, a++, b++ ) |
732 | { | 732 | { |
733 | if( *a != *b ) | 733 | if( *a != *b ) |
734 | return false; | 734 | return false; |
735 | if( *a == (char)0 && j < core->nLength ) | 735 | if( *a == (char)0 && j < core->nLength ) |
736 | return false; | 736 | return false; |
737 | } | 737 | } |
738 | 738 | ||
739 | return true; | 739 | return true; |
740 | } | 740 | } |
741 | 741 | ||
742 | bool Bu::String::operator==( const String &pData ) const | 742 | bool Bu::String::operator==( const String &pData ) const |
743 | { | 743 | { |
744 | if( core == pData.core ) | 744 | if( core == pData.core ) |
745 | return true; | 745 | return true; |
746 | if( core->pFirst == pData.core->pFirst ) | 746 | if( core->pFirst == pData.core->pFirst ) |
747 | return true; | 747 | return true; |
748 | if( (core->nLength == 0 && pData.core->nLength == 0) ) | 748 | if( (core->nLength == 0 && pData.core->nLength == 0) ) |
749 | return true; | 749 | return true; |
750 | if( core->nLength != pData.core->nLength ) | 750 | if( core->nLength != pData.core->nLength ) |
751 | return false; | 751 | return false; |
752 | if( pData.core->pFirst == NULL || core->pFirst == NULL ) | 752 | if( pData.core->pFirst == NULL || core->pFirst == NULL ) |
753 | return false; | 753 | return false; |
754 | 754 | ||
755 | flatten(); | 755 | flatten(); |
756 | pData.flatten(); | 756 | pData.flatten(); |
757 | const char *a = pData.core->pFirst->pData; | 757 | const char *a = pData.core->pFirst->pData; |
758 | char *b = core->pFirst->pData; | 758 | char *b = core->pFirst->pData; |
759 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 759 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
760 | { | 760 | { |
761 | if( *a != *b ) | 761 | if( *a != *b ) |
762 | return false; | 762 | return false; |
763 | } | 763 | } |
764 | 764 | ||
765 | return true; | 765 | return true; |
766 | } | 766 | } |
767 | 767 | ||
768 | bool Bu::String::operator!=(const char *pData ) const | 768 | bool Bu::String::operator!=(const char *pData ) const |
769 | { | 769 | { |
770 | return !(*this == pData); | 770 | return !(*this == pData); |
771 | } | 771 | } |
772 | 772 | ||
773 | bool Bu::String::operator!=(const String &pData ) const | 773 | bool Bu::String::operator!=(const String &pData ) const |
774 | { | 774 | { |
775 | return !(*this == pData); | 775 | return !(*this == pData); |
776 | } | 776 | } |
777 | 777 | ||
778 | bool Bu::String::operator<(const String &pData ) const | 778 | bool Bu::String::operator<(const String &pData ) const |
779 | { | 779 | { |
780 | flatten(); | 780 | flatten(); |
781 | pData.flatten(); | 781 | pData.flatten(); |
782 | 782 | ||
783 | const char *a = core->pFirst->pData; | 783 | const char *a = core->pFirst->pData; |
784 | char *b = pData.core->pFirst->pData; | 784 | char *b = pData.core->pFirst->pData; |
785 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 785 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
786 | { | 786 | { |
787 | if( *a != *b ) | 787 | if( *a != *b ) |
788 | return *a < *b; | 788 | return *a < *b; |
789 | } | 789 | } |
790 | 790 | ||
791 | return false; | 791 | return false; |
792 | } | 792 | } |
793 | 793 | ||
794 | bool Bu::String::operator<=(const String &pData ) const | 794 | bool Bu::String::operator<=(const String &pData ) const |
795 | { | 795 | { |
796 | flatten(); | 796 | flatten(); |
797 | pData.flatten(); | 797 | pData.flatten(); |
798 | 798 | ||
799 | const char *a = core->pFirst->pData; | 799 | const char *a = core->pFirst->pData; |
800 | char *b = pData.core->pFirst->pData; | 800 | char *b = pData.core->pFirst->pData; |
801 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 801 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
802 | { | 802 | { |
803 | if( *a != *b ) | 803 | if( *a != *b ) |
804 | return *a < *b; | 804 | return *a < *b; |
805 | } | 805 | } |
806 | 806 | ||
807 | return true; | 807 | return true; |
808 | } | 808 | } |
809 | 809 | ||
810 | bool Bu::String::operator>(const String &pData ) const | 810 | bool Bu::String::operator>(const String &pData ) const |
811 | { | 811 | { |
812 | flatten(); | 812 | flatten(); |
813 | pData.flatten(); | 813 | pData.flatten(); |
814 | 814 | ||
815 | const char *a = core->pFirst->pData; | 815 | const char *a = core->pFirst->pData; |
816 | char *b = pData.core->pFirst->pData; | 816 | char *b = pData.core->pFirst->pData; |
817 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 817 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
818 | { | 818 | { |
819 | if( *a != *b ) | 819 | if( *a != *b ) |
820 | return *a > *b; | 820 | return *a > *b; |
821 | } | 821 | } |
822 | 822 | ||
823 | return false; | 823 | return false; |
824 | } | 824 | } |
825 | 825 | ||
826 | bool Bu::String::operator>=(const String &pData ) const | 826 | bool Bu::String::operator>=(const String &pData ) const |
827 | { | 827 | { |
828 | flatten(); | 828 | flatten(); |
829 | pData.flatten(); | 829 | pData.flatten(); |
830 | 830 | ||
831 | const char *a = core->pFirst->pData; | 831 | const char *a = core->pFirst->pData; |
832 | char *b = pData.core->pFirst->pData; | 832 | char *b = pData.core->pFirst->pData; |
833 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 833 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
834 | { | 834 | { |
835 | if( *a != *b ) | 835 | if( *a != *b ) |
836 | return *a > *b; | 836 | return *a > *b; |
837 | } | 837 | } |
838 | 838 | ||
839 | return true; | 839 | return true; |
840 | } | 840 | } |
841 | 841 | ||
842 | char &Bu::String::operator[]( long nIndex ) | 842 | char &Bu::String::operator[]( long nIndex ) |
843 | { | 843 | { |
844 | if( nIndex < 0 || nIndex >= core->nLength ) | 844 | if( nIndex < 0 || nIndex >= core->nLength ) |
845 | throw Bu::ExceptionBase("Index out of range."); | 845 | throw Bu::ExceptionBase("Index out of range."); |
846 | flatten(); | 846 | flatten(); |
847 | _hardCopy(); | 847 | _hardCopy(); |
848 | 848 | ||
849 | return core->pFirst->pData[nIndex]; | 849 | return core->pFirst->pData[nIndex]; |
850 | } | 850 | } |
851 | 851 | ||
852 | const char &Bu::String::operator[]( long nIndex ) const | 852 | const char &Bu::String::operator[]( long nIndex ) const |
853 | { | 853 | { |
854 | if( nIndex < 0 || nIndex >= core->nLength ) | 854 | if( nIndex < 0 || nIndex >= core->nLength ) |
855 | throw Bu::ExceptionBase("Index out of range."); | 855 | throw Bu::ExceptionBase("Index out of range."); |
856 | flatten(); | 856 | flatten(); |
857 | 857 | ||
858 | return core->pFirst->pData[nIndex]; | 858 | return core->pFirst->pData[nIndex]; |
859 | } | 859 | } |
860 | 860 | ||
861 | bool Bu::String::isSet() const | 861 | bool Bu::String::isSet() const |
862 | { | 862 | { |
863 | return (core->pFirst != NULL); | 863 | return (core->pFirst != NULL); |
864 | } | 864 | } |
865 | 865 | ||
866 | bool Bu::String::compareSub( const char *pData, long nIndex, long nLen ) const | 866 | bool Bu::String::compareSub( const char *pData, long nIndex, long nLen ) const |
867 | { | 867 | { |
868 | if( core->pFirst == NULL || core->nLength == 0 ) { | 868 | if( core->pFirst == NULL || core->nLength == 0 ) { |
869 | if( pData == NULL ) | 869 | if( pData == NULL ) |
870 | return true; | 870 | return true; |
871 | if( nLen == 0 ) | 871 | if( nLen == 0 ) |
872 | return true; | 872 | return true; |
873 | if( pData[0] == (char)0 ) | 873 | if( pData[0] == (char)0 ) |
874 | return true; | 874 | return true; |
875 | return false; | 875 | return false; |
876 | } | 876 | } |
877 | if( nIndex+nLen > core->nLength ) | 877 | if( nIndex+nLen > core->nLength ) |
878 | return false; | 878 | return false; |
879 | 879 | ||
880 | flatten(); | 880 | flatten(); |
881 | core->pFirst->pData[core->nLength] = (char)0; | 881 | core->pFirst->pData[core->nLength] = (char)0; |
882 | const char *a = pData; | 882 | const char *a = pData; |
883 | char *b = core->pFirst->pData+nIndex; | 883 | char *b = core->pFirst->pData+nIndex; |
884 | for( long j = 0; j < nLen; j++, a++, b++ ) | 884 | for( long j = 0; j < nLen; j++, a++, b++ ) |
885 | { | 885 | { |
886 | if( *a != *b ) | 886 | if( *a != *b ) |
887 | return false; | 887 | return false; |
888 | if( *a == (char)0 && j < core->nLength ) | 888 | if( *a == (char)0 && j < core->nLength ) |
889 | return false; | 889 | return false; |
890 | } | 890 | } |
891 | 891 | ||
892 | return true; | 892 | return true; |
893 | } | 893 | } |
894 | 894 | ||
895 | bool Bu::String::compareSub( const String &rData, long nIndex, long nLen ) const | 895 | bool Bu::String::compareSub( const String &rData, long nIndex, long nLen ) const |
896 | { | 896 | { |
897 | if( core->pFirst == NULL || core->nLength == 0 || rData.core->pFirst == NULL || rData.core->nLength == 0 ) | 897 | if( core->pFirst == NULL || core->nLength == 0 || rData.core->pFirst == NULL || rData.core->nLength == 0 ) |
898 | return false; | 898 | return false; |
899 | if( nLen < 0 ) | 899 | if( nLen < 0 ) |
900 | nLen = rData.core->nLength; | 900 | nLen = rData.core->nLength; |
901 | if( nIndex+nLen > core->nLength ) | 901 | if( nIndex+nLen > core->nLength ) |
902 | return false; | 902 | return false; |
903 | 903 | ||
904 | flatten(); | 904 | flatten(); |
905 | rData.flatten(); | 905 | rData.flatten(); |
906 | const char *a = rData.core->pFirst->pData; | 906 | const char *a = rData.core->pFirst->pData; |
907 | char *b = core->pFirst->pData + nIndex; | 907 | char *b = core->pFirst->pData + nIndex; |
908 | for( long j = 0; j < nLen; j++, a++, b++ ) | 908 | for( long j = 0; j < nLen; j++, a++, b++ ) |
909 | { | 909 | { |
910 | if( *a != *b ) | 910 | if( *a != *b ) |
911 | return false; | 911 | return false; |
912 | } | 912 | } |
913 | 913 | ||
914 | return true; | 914 | return true; |
915 | } | 915 | } |
916 | 916 | ||
917 | bool Bu::String::isWS( long nIndex ) const | 917 | bool Bu::String::isWS( long nIndex ) const |
918 | { | 918 | { |
919 | flatten(); | 919 | flatten(); |
920 | 920 | ||
921 | return core->pFirst->pData[nIndex]==' ' || core->pFirst->pData[nIndex]=='\t' | 921 | return core->pFirst->pData[nIndex]==' ' || core->pFirst->pData[nIndex]=='\t' |
922 | || core->pFirst->pData[nIndex]=='\r' || core->pFirst->pData[nIndex]=='\n'; | 922 | || core->pFirst->pData[nIndex]=='\r' || core->pFirst->pData[nIndex]=='\n'; |
923 | } | 923 | } |
924 | 924 | ||
925 | bool Bu::String::isAlpha( long nIndex ) const | 925 | bool Bu::String::isAlpha( long nIndex ) const |
926 | { | 926 | { |
927 | flatten(); | 927 | flatten(); |
928 | 928 | ||
929 | return (core->pFirst->pData[nIndex] >= 'a' && core->pFirst->pData[nIndex] <= 'z') | 929 | return (core->pFirst->pData[nIndex] >= 'a' && core->pFirst->pData[nIndex] <= 'z') |
930 | || (core->pFirst->pData[nIndex] >= 'A' && core->pFirst->pData[nIndex] <= 'Z'); | 930 | || (core->pFirst->pData[nIndex] >= 'A' && core->pFirst->pData[nIndex] <= 'Z'); |
931 | } | 931 | } |
932 | 932 | ||
933 | Bu::String Bu::String::toLower() const | 933 | Bu::String Bu::String::toLower() const |
934 | { | 934 | { |
935 | Bu::String sRet = *this; | 935 | Bu::String sRet = *this; |
936 | 936 | ||
937 | sRet.flatten(); | 937 | sRet.flatten(); |
938 | sRet._hardCopy(); | 938 | sRet._hardCopy(); |
939 | 939 | ||
940 | for( long j = 0; j < sRet.core->nLength; j++ ) | 940 | for( long j = 0; j < sRet.core->nLength; j++ ) |
941 | { | 941 | { |
942 | if( sRet.core->pFirst->pData[j] >= 'A' && | 942 | if( sRet.core->pFirst->pData[j] >= 'A' && |
943 | sRet.core->pFirst->pData[j] <= 'Z' ) | 943 | sRet.core->pFirst->pData[j] <= 'Z' ) |
944 | sRet.core->pFirst->pData[j] -= 'A'-'a'; | 944 | sRet.core->pFirst->pData[j] -= 'A'-'a'; |
945 | } | 945 | } |
946 | 946 | ||
947 | return sRet; | 947 | return sRet; |
948 | } | 948 | } |
949 | 949 | ||
950 | Bu::String Bu::String::toUpper() const | 950 | Bu::String Bu::String::toUpper() const |
951 | { | 951 | { |
952 | Bu::String sRet = *this; | 952 | Bu::String sRet = *this; |
953 | 953 | ||
954 | sRet.flatten(); | 954 | sRet.flatten(); |
955 | sRet._hardCopy(); | 955 | sRet._hardCopy(); |
956 | 956 | ||
957 | for( long j = 0; j < sRet.core->nLength; j++ ) | 957 | for( long j = 0; j < sRet.core->nLength; j++ ) |
958 | { | 958 | { |
959 | if( sRet.core->pFirst->pData[j] >= 'a' && | 959 | if( sRet.core->pFirst->pData[j] >= 'a' && |
960 | sRet.core->pFirst->pData[j] <= 'z' ) | 960 | sRet.core->pFirst->pData[j] <= 'z' ) |
961 | sRet.core->pFirst->pData[j] += 'A'-'a'; | 961 | sRet.core->pFirst->pData[j] += 'A'-'a'; |
962 | } | 962 | } |
963 | 963 | ||
964 | return sRet; | 964 | return sRet; |
965 | } | 965 | } |
966 | 966 | ||
967 | Bu::String::const_iterator Bu::String::find( const char cChar, | 967 | Bu::String::const_iterator Bu::String::find( const char cChar, |
968 | Bu::String::const_iterator iStart ) const | 968 | Bu::String::const_iterator iStart ) const |
969 | { | 969 | { |
970 | if( !iStart ) iStart = begin(); | 970 | if( !iStart ) iStart = begin(); |
971 | for( ; iStart; iStart++ ) | 971 | for( ; iStart; iStart++ ) |
972 | { | 972 | { |
973 | if( cChar == *iStart ) | 973 | if( cChar == *iStart ) |
974 | return iStart; | 974 | return iStart; |
975 | } | 975 | } |
976 | return end(); | 976 | return end(); |
977 | } | 977 | } |
978 | 978 | ||
979 | Bu::String::const_iterator Bu::String::find( const char *sText, int nLen, | 979 | Bu::String::const_iterator Bu::String::find( const char *sText, int nLen, |
980 | Bu::String::const_iterator iStart ) const | 980 | Bu::String::const_iterator iStart ) const |
981 | { | 981 | { |
982 | if( !iStart ) iStart = begin(); | 982 | if( !iStart ) iStart = begin(); |
983 | for( ; iStart; iStart++ ) | 983 | for( ; iStart; iStart++ ) |
984 | { | 984 | { |
985 | if( iStart.compare( sText, nLen ) ) | 985 | if( iStart.compare( sText, nLen ) ) |
986 | return iStart; | 986 | return iStart; |
987 | } | 987 | } |
988 | return end(); | 988 | return end(); |
989 | } | 989 | } |
990 | 990 | ||
991 | Bu::String::const_iterator Bu::String::find( const String &rStr, | 991 | Bu::String::const_iterator Bu::String::find( const String &rStr, |
992 | Bu::String::const_iterator iStart ) const | 992 | Bu::String::const_iterator iStart ) const |
993 | { | 993 | { |
994 | if( !iStart ) iStart = begin(); | 994 | if( !iStart ) iStart = begin(); |
995 | for( ; iStart; iStart++ ) | 995 | for( ; iStart; iStart++ ) |
996 | { | 996 | { |
997 | if( iStart.compare( rStr ) ) | 997 | if( iStart.compare( rStr ) ) |
998 | return iStart; | 998 | return iStart; |
999 | } | 999 | } |
1000 | return end(); | 1000 | return end(); |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | Bu::String::const_iterator Bu::String::find( const String &rStr, int nLen, | 1003 | Bu::String::const_iterator Bu::String::find( const String &rStr, int nLen, |
1004 | Bu::String::const_iterator iStart ) const | 1004 | Bu::String::const_iterator iStart ) const |
1005 | { | 1005 | { |
1006 | if( !iStart ) iStart = begin(); | 1006 | if( !iStart ) iStart = begin(); |
1007 | for( ; iStart; iStart++ ) | 1007 | for( ; iStart; iStart++ ) |
1008 | { | 1008 | { |
1009 | if( iStart.compare( rStr, nLen ) ) | 1009 | if( iStart.compare( rStr, nLen ) ) |
1010 | return iStart; | 1010 | return iStart; |
1011 | } | 1011 | } |
1012 | return end(); | 1012 | return end(); |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | Bu::String::iterator Bu::String::find( const char cChar, | 1015 | Bu::String::iterator Bu::String::find( const char cChar, |
1016 | Bu::String::const_iterator iStart ) | 1016 | Bu::String::const_iterator iStart ) |
1017 | { | 1017 | { |
1018 | if( !iStart ) iStart = begin(); | 1018 | if( !iStart ) iStart = begin(); |
1019 | for( ; iStart; iStart++ ) | 1019 | for( ; iStart; iStart++ ) |
1020 | { | 1020 | { |
1021 | if( cChar == *iStart ) | 1021 | if( cChar == *iStart ) |
1022 | return iterator( iStart.pChunk, iStart.iPos ); | 1022 | return iterator( iStart.pChunk, iStart.iPos ); |
1023 | } | 1023 | } |
1024 | return end(); | 1024 | return end(); |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | Bu::String::iterator Bu::String::find( const char *sText, int nLen, | 1027 | Bu::String::iterator Bu::String::find( const char *sText, int nLen, |
1028 | Bu::String::const_iterator iStart ) | 1028 | Bu::String::const_iterator iStart ) |
1029 | { | 1029 | { |
1030 | if( !iStart ) iStart = begin(); | 1030 | if( !iStart ) iStart = begin(); |
1031 | for( ; iStart; iStart++ ) | 1031 | for( ; iStart; iStart++ ) |
1032 | { | 1032 | { |
1033 | if( iStart.compare( sText, nLen ) ) | 1033 | if( iStart.compare( sText, nLen ) ) |
1034 | return iterator( iStart.pChunk, iStart.iPos ); | 1034 | return iterator( iStart.pChunk, iStart.iPos ); |
1035 | } | 1035 | } |
1036 | return end(); | 1036 | return end(); |
1037 | } | 1037 | } |
1038 | 1038 | ||
1039 | Bu::String::iterator Bu::String::find( const String &rStr, | 1039 | Bu::String::iterator Bu::String::find( const String &rStr, |
1040 | Bu::String::const_iterator iStart ) | 1040 | Bu::String::const_iterator iStart ) |
1041 | { | 1041 | { |
1042 | if( !iStart ) iStart = begin(); | 1042 | if( !iStart ) iStart = begin(); |
1043 | for( ; iStart; iStart++ ) | 1043 | for( ; iStart; iStart++ ) |
1044 | { | 1044 | { |
1045 | if( iStart.compare( rStr ) ) | 1045 | if( iStart.compare( rStr ) ) |
1046 | return iterator( iStart.pChunk, iStart.iPos ); | 1046 | return iterator( iStart.pChunk, iStart.iPos ); |
1047 | } | 1047 | } |
1048 | return end(); | 1048 | return end(); |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | Bu::String::iterator Bu::String::find( const String &rStr, int nLen, | 1051 | Bu::String::iterator Bu::String::find( const String &rStr, int nLen, |
1052 | Bu::String::const_iterator iStart ) | 1052 | Bu::String::const_iterator iStart ) |
1053 | { | 1053 | { |
1054 | if( !iStart ) iStart = begin(); | 1054 | if( !iStart ) iStart = begin(); |
1055 | for( ; iStart; iStart++ ) | 1055 | for( ; iStart; iStart++ ) |
1056 | { | 1056 | { |
1057 | if( iStart.compare( rStr, nLen ) ) | 1057 | if( iStart.compare( rStr, nLen ) ) |
1058 | return iterator( iStart.pChunk, iStart.iPos ); | 1058 | return iterator( iStart.pChunk, iStart.iPos ); |
1059 | } | 1059 | } |
1060 | return end(); | 1060 | return end(); |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | long Bu::String::findIdx( const char cChar, long iStart ) const | 1063 | long Bu::String::findIdx( const char cChar, long iStart ) const |
1064 | { | 1064 | { |
1065 | flatten(); | 1065 | flatten(); |
1066 | for( long j = iStart; j < core->pFirst->nLength; j++ ) | 1066 | for( long j = iStart; j < core->pFirst->nLength; j++ ) |
1067 | { | 1067 | { |
1068 | if( core->pFirst->pData[j] == cChar ) | 1068 | if( core->pFirst->pData[j] == cChar ) |
1069 | return j; | 1069 | return j; |
1070 | } | 1070 | } |
1071 | return -1; | 1071 | return -1; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | long Bu::String::findIdx( const char *sText, long iStart ) const | 1074 | long Bu::String::findIdx( const char *sText, long iStart ) const |
1075 | { | 1075 | { |
1076 | long nTLen = strlen( sText ); | 1076 | long nTLen = strlen( sText ); |
1077 | flatten(); | 1077 | flatten(); |
1078 | for( long j = iStart; j < core->pFirst->nLength-nTLen; j++ ) | 1078 | for( long j = iStart; j < core->pFirst->nLength-nTLen; j++ ) |
1079 | { | 1079 | { |
1080 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) | 1080 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) |
1081 | return j; | 1081 | return j; |
1082 | } | 1082 | } |
1083 | return -1; | 1083 | return -1; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | long Bu::String::rfindIdx( const char *sText ) const | 1086 | long Bu::String::rfindIdx( const char *sText ) const |
1087 | { | 1087 | { |
1088 | long nTLen = strlen( sText ); | 1088 | long nTLen = strlen( sText ); |
1089 | flatten(); | 1089 | flatten(); |
1090 | for( long j = core->pFirst->nLength-nTLen-1; j >= 0; j-- ) | 1090 | for( long j = core->pFirst->nLength-nTLen-1; j >= 0; j-- ) |
1091 | { | 1091 | { |
1092 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) | 1092 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) |
1093 | return j; | 1093 | return j; |
1094 | } | 1094 | } |
1095 | return -1; | 1095 | return -1; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | void Bu::String::trimFront( long nAmnt ) | 1098 | void Bu::String::trimFront( long nAmnt ) |
1099 | { | 1099 | { |
1100 | long nNewLen = core->nLength - nAmnt; | 1100 | long nNewLen = core->nLength - nAmnt; |
1101 | flatten(); | 1101 | flatten(); |
1102 | Chunk *pNew = core->newChunk( nNewLen ); | 1102 | Chunk *pNew = core->newChunk( nNewLen ); |
1103 | memcpy( pNew->pData, core->pFirst->pData+nAmnt, nNewLen ); | 1103 | memcpy( pNew->pData, core->pFirst->pData+nAmnt, nNewLen ); |
1104 | _hardCopy(); | 1104 | _hardCopy(); |
1105 | core->clear(); | 1105 | core->clear(); |
1106 | core->appendChunk( pNew ); | 1106 | core->appendChunk( pNew ); |
1107 | } | 1107 | } |
1108 | /* | 1108 | /* |
1109 | void Bu::String::trimBack( char c ) | 1109 | void Bu::String::trimBack( char c ) |
1110 | { | 1110 | { |
1111 | if( core->pFirst == NULL || core->nLength == 0 ) | 1111 | if( core->pFirst == NULL || core->nLength == 0 ) |
1112 | return; | 1112 | return; |
1113 | flatten(); | 1113 | flatten(); |
1114 | for( ; core->pFirst->nLength > 0 && | 1114 | for( ; core->pFirst->nLength > 0 && |
1115 | core->pFirst->pData[core->pFirst->nLength-1] == c; | 1115 | core->pFirst->pData[core->pFirst->nLength-1] == c; |
1116 | core->pFirst->nLength--, core->nLength-- ) { } | 1116 | core->pFirst->nLength--, core->nLength-- ) { } |
1117 | } | 1117 | } |
1118 | */ | 1118 | */ |
1119 | void Bu::String::trimBack( long iAmnt ) | 1119 | void Bu::String::trimBack( long iAmnt ) |
1120 | { | 1120 | { |
1121 | if( iAmnt < 0 ) | 1121 | if( iAmnt < 0 ) |
1122 | return; | 1122 | return; |
1123 | if( core->nLength - iAmnt < 0 ) | 1123 | if( core->nLength - iAmnt < 0 ) |
1124 | { | 1124 | { |
1125 | clear(); | 1125 | clear(); |
1126 | return; | 1126 | return; |
1127 | } | 1127 | } |
1128 | if( core->pFirst == NULL || core->nLength == 0 ) | 1128 | if( core->pFirst == NULL || core->nLength == 0 ) |
1129 | return; | 1129 | return; |
1130 | 1130 | ||
1131 | flatten(); | 1131 | flatten(); |
1132 | core->pFirst->nLength -= iAmnt; | 1132 | core->pFirst->nLength -= iAmnt; |
1133 | core->nLength -= iAmnt; | 1133 | core->nLength -= iAmnt; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | Bu::String Bu::String::trimWhitespace() const | 1136 | Bu::String Bu::String::trimWhitespace() const |
1137 | { | 1137 | { |
1138 | if( core->nLength == 0 ) | 1138 | if( core->nLength == 0 ) |
1139 | return ""; | 1139 | return ""; |
1140 | const_iterator i = begin(); | 1140 | const_iterator i = begin(); |
1141 | for( ; i && (*i == ' ' || *i == '\t' || *i == '\n' || *i == '\r'); i++ ) { } | 1141 | for( ; i && (*i == ' ' || *i == '\t' || *i == '\n' || *i == '\r'); i++ ) { } |
1142 | if( !i ) | 1142 | if( !i ) |
1143 | return ""; | 1143 | return ""; |
1144 | 1144 | ||
1145 | const_iterator e = i; | 1145 | const_iterator e = i; |
1146 | for( ; e; e++ ) | 1146 | for( ; e; e++ ) |
1147 | { | 1147 | { |
1148 | if( *e == ' ' || *e == '\t' || *e == '\n' || *e == '\r' ) | 1148 | if( *e == ' ' || *e == '\t' || *e == '\n' || *e == '\r' ) |
1149 | { | 1149 | { |
1150 | const_iterator t = e; | 1150 | const_iterator t = e; |
1151 | for( ; t && (*t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'); t++ ) { } | 1151 | for( ; t && (*t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'); t++ ) { } |
1152 | if( t ) | 1152 | if( t ) |
1153 | { | 1153 | { |
1154 | e = t; | 1154 | e = t; |
1155 | } | 1155 | } |
1156 | else | 1156 | else |
1157 | { | 1157 | { |
1158 | break; | 1158 | break; |
1159 | } | 1159 | } |
1160 | } | 1160 | } |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | return Bu::String( i, e ); | 1163 | return Bu::String( i, e ); |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | Bu::String::iterator Bu::String::begin() | 1166 | Bu::String::iterator Bu::String::begin() |
1167 | { | 1167 | { |
1168 | if( core->nLength == 0 ) | 1168 | if( core->nLength == 0 ) |
1169 | return iterator( NULL, 0 ); | 1169 | return iterator( NULL, 0 ); |
1170 | return iterator( core->pFirst, 0 ); | 1170 | return iterator( core->pFirst, 0 ); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | Bu::String::const_iterator Bu::String::begin() const | 1173 | Bu::String::const_iterator Bu::String::begin() const |
1174 | { | 1174 | { |
1175 | if( core->nLength == 0 ) | 1175 | if( core->nLength == 0 ) |
1176 | return const_iterator( NULL, 0 ); | 1176 | return const_iterator( NULL, 0 ); |
1177 | return iterator( core->pFirst, 0 ); | 1177 | return iterator( core->pFirst, 0 ); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | Bu::String::iterator Bu::String::end() | 1180 | Bu::String::iterator Bu::String::end() |
1181 | { | 1181 | { |
1182 | return iterator( NULL, 0 ); | 1182 | return iterator( NULL, 0 ); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | Bu::String::const_iterator Bu::String::end() const | 1185 | Bu::String::const_iterator Bu::String::end() const |
1186 | { | 1186 | { |
1187 | return const_iterator( NULL, 0 ); | 1187 | return const_iterator( NULL, 0 ); |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | bool Bu::String::isEmpty() const | 1190 | bool Bu::String::isEmpty() const |
1191 | { | 1191 | { |
1192 | if( core->nLength == 0 ) | 1192 | if( core->nLength == 0 ) |
1193 | return true; | 1193 | return true; |
1194 | return false; | 1194 | return false; |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | void Bu::String::flatten() const | 1197 | void Bu::String::flatten() const |
1198 | { | 1198 | { |
1199 | if( isFlat() ) | 1199 | if( isFlat() ) |
1200 | return; | 1200 | return; |
1201 | 1201 | ||
1202 | if( core->pFirst == NULL || core->nLength == 0 ) | 1202 | if( core->pFirst == NULL || core->nLength == 0 ) |
1203 | return; | 1203 | return; |
1204 | 1204 | ||
1205 | Chunk *pNew = core->newChunk( core->nLength ); | 1205 | Chunk *pNew = core->newChunk( core->nLength ); |
1206 | char *pos = pNew->pData; | 1206 | char *pos = pNew->pData; |
1207 | Chunk *i = core->pFirst; | 1207 | Chunk *i = core->pFirst; |
1208 | for(;;) | 1208 | for(;;) |
1209 | { | 1209 | { |
1210 | memcpy( pos, i->pData, i->nLength ); | 1210 | memcpy( pos, i->pData, i->nLength ); |
1211 | pos += i->nLength; | 1211 | pos += i->nLength; |
1212 | i = i->pNext; | 1212 | i = i->pNext; |
1213 | if( i == NULL ) | 1213 | if( i == NULL ) |
1214 | break; | 1214 | break; |
1215 | } | 1215 | } |
1216 | core->clear(); | 1216 | core->clear(); |
1217 | 1217 | ||
1218 | core->pLast = core->pFirst = pNew; | 1218 | core->pLast = core->pFirst = pNew; |
1219 | core->nLength = pNew->nLength; | 1219 | core->nLength = pNew->nLength; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | bool Bu::String::isFlat() const | 1222 | bool Bu::String::isFlat() const |
1223 | { | 1223 | { |
1224 | return (core->pFirst == core->pLast); | 1224 | return (core->pFirst == core->pLast); |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | // | 1227 | // |
@@ -1229,98 +1229,98 @@ bool Bu::String::isFlat() const | |||
1229 | // | 1229 | // |
1230 | 1230 | ||
1231 | Bu::String::FormatProxy::FormatProxy( const String &rFmt, | 1231 | Bu::String::FormatProxy::FormatProxy( const String &rFmt, |
1232 | String::FormatProxyEndAction *pAct ) : | 1232 | String::FormatProxyEndAction *pAct ) : |
1233 | rFmt( rFmt ), | 1233 | rFmt( rFmt ), |
1234 | pAct( pAct ), | 1234 | pAct( pAct ), |
1235 | bOpen( true ) | 1235 | bOpen( true ) |
1236 | { | 1236 | { |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | Bu::String::FormatProxy::~FormatProxy() | 1239 | Bu::String::FormatProxy::~FormatProxy() |
1240 | { | 1240 | { |
1241 | if( pAct && bOpen ) | 1241 | if( pAct && bOpen ) |
1242 | end(); | 1242 | end(); |
1243 | 1243 | ||
1244 | delete pAct; | 1244 | delete pAct; |
1245 | } | 1245 | } |
1246 | 1246 | ||
1247 | Bu::String Bu::String::FormatProxy::end() const | 1247 | Bu::String Bu::String::FormatProxy::end() const |
1248 | { | 1248 | { |
1249 | int iCount = lArgs.getSize(); | 1249 | int iCount = lArgs.getSize(); |
1250 | ArgList::const_iterator *aArg = | 1250 | ArgList::const_iterator *aArg = |
1251 | new ArgList::const_iterator[iCount]; | 1251 | new ArgList::const_iterator[iCount]; |
1252 | { | 1252 | { |
1253 | int j = 0; | 1253 | int j = 0; |
1254 | for( ArgList::const_iterator i = lArgs.begin(); | 1254 | for( ArgList::const_iterator i = lArgs.begin(); |
1255 | i; i++, j++ ) | 1255 | i; i++, j++ ) |
1256 | { | 1256 | { |
1257 | aArg[j] = i; | 1257 | aArg[j] = i; |
1258 | } | 1258 | } |
1259 | } | 1259 | } |
1260 | Bu::MemBuf mbOut; | 1260 | Bu::MemBuf mbOut; |
1261 | Bu::Formatter f( mbOut ); | 1261 | Bu::Formatter f( mbOut ); |
1262 | for( String::const_iterator s = rFmt.begin(); s; ) | 1262 | for( String::const_iterator s = rFmt.begin(); s; ) |
1263 | { | 1263 | { |
1264 | if( *s == '%' ) | 1264 | if( *s == '%' ) |
1265 | { | 1265 | { |
1266 | s++; | 1266 | s++; |
1267 | if( *s == '%' ) | 1267 | if( *s == '%' ) |
1268 | f << *s; | 1268 | f << *s; |
1269 | else | 1269 | else |
1270 | { | 1270 | { |
1271 | String sNum; | 1271 | String sNum; |
1272 | if( *s == '{' ) | 1272 | if( *s == '{' ) |
1273 | { | 1273 | { |
1274 | s++; | 1274 | s++; |
1275 | while( s && *s >= '0' && *s <= '9' ) | 1275 | while( s && *s >= '0' && *s <= '9' ) |
1276 | { | 1276 | { |
1277 | sNum += *s; | 1277 | sNum += *s; |
1278 | s++; | 1278 | s++; |
1279 | } | 1279 | } |
1280 | if( !s || *s != '}' ) | 1280 | if( !s || *s != '}' ) |
1281 | { | 1281 | { |
1282 | delete[] aArg; | 1282 | delete[] aArg; |
1283 | throw Bu::ExceptionBase( | 1283 | throw Bu::ExceptionBase( |
1284 | "Argument started with a '{' but terminated " | 1284 | "Argument started with a '{' but terminated " |
1285 | "with a '%c' instead of '}'.", *s ); | 1285 | "with a '%c' instead of '}'.", *s ); |
1286 | } | 1286 | } |
1287 | s++; | 1287 | s++; |
1288 | } | 1288 | } |
1289 | else | 1289 | else |
1290 | { | 1290 | { |
1291 | while( s && *s >= '0' && *s <= '9' ) | 1291 | while( s && *s >= '0' && *s <= '9' ) |
1292 | { | 1292 | { |
1293 | sNum += *s; | 1293 | sNum += *s; |
1294 | s++; | 1294 | s++; |
1295 | } | 1295 | } |
1296 | } | 1296 | } |
1297 | int iIndex = strtol( sNum.getStr(), 0, 10 )-1; | 1297 | int iIndex = strtol( sNum.getStr(), 0, 10 )-1; |
1298 | if( iIndex < 0 || iIndex >= iCount ) | 1298 | if( iIndex < 0 || iIndex >= iCount ) |
1299 | { | 1299 | { |
1300 | delete[] aArg; | 1300 | delete[] aArg; |
1301 | throw Bu::ExceptionBase( | 1301 | throw Bu::ExceptionBase( |
1302 | "Argument index %d is outside of " | 1302 | "Argument index %d is outside of " |
1303 | "valid range (1-%d).", iIndex+1, iCount | 1303 | "valid range (1-%d).", iIndex+1, iCount |
1304 | ); | 1304 | ); |
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | f << (*aArg[iIndex]).format << (*aArg[iIndex]).value; | 1307 | f << (*aArg[iIndex]).format << (*aArg[iIndex]).value; |
1308 | continue; | 1308 | continue; |
1309 | } | 1309 | } |
1310 | } | 1310 | } |
1311 | else | 1311 | else |
1312 | { | 1312 | { |
1313 | f << *s; | 1313 | f << *s; |
1314 | } | 1314 | } |
1315 | s++; | 1315 | s++; |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | bOpen = false; | 1318 | bOpen = false; |
1319 | delete[] aArg; | 1319 | delete[] aArg; |
1320 | 1320 | ||
1321 | if( pAct ) | 1321 | if( pAct ) |
1322 | (*pAct)( mbOut.getString() ); | 1322 | (*pAct)( mbOut.getString() ); |
1323 | return mbOut.getString(); | 1323 | return mbOut.getString(); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | 1326 | ||
@@ -1371,131 +1371,131 @@ Bu::String Bu::String::FormatProxy::end() const | |||
1371 | 1371 | ||
1372 | template<> uint32_t Bu::__calcHashCode<Bu::String>( const Bu::String &k ) | 1372 | template<> uint32_t Bu::__calcHashCode<Bu::String>( const Bu::String &k ) |
1373 | { | 1373 | { |
1374 | long j, sz = k.getSize(); | 1374 | long j, sz = k.getSize(); |
1375 | const char *s = k.getStr(); | 1375 | const char *s = k.getStr(); |
1376 | 1376 | ||
1377 | long nPos = 0; | 1377 | long nPos = 0; |
1378 | for( j = 0; j < sz; j++, s++ ) | 1378 | for( j = 0; j < sz; j++, s++ ) |
1379 | { | 1379 | { |
1380 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 1380 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | return nPos; | 1383 | return nPos; |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | template<> bool Bu::__cmpHashKeys<Bu::String>( | 1386 | template<> bool Bu::__cmpHashKeys<Bu::String>( |
1387 | const Bu::String &a, const Bu::String &b ) | 1387 | const Bu::String &a, const Bu::String &b ) |
1388 | { | 1388 | { |
1389 | return a == b; | 1389 | return a == b; |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | template<> void Bu::__tracer_format<Bu::String>( const Bu::String &v ) | 1392 | template<> void Bu::__tracer_format<Bu::String>( const Bu::String &v ) |
1393 | { | 1393 | { |
1394 | printf("(%ld)\"%s\"", v.getSize(), v.getStr() ); | 1394 | printf("(%ld)\"%s\"", v.getSize(), v.getStr() ); |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | bool &Bu::operator<<( bool &dst, const Bu::String &sIn ) | 1397 | bool &Bu::operator<<( bool &dst, const Bu::String &sIn ) |
1398 | { | 1398 | { |
1399 | if( sIn == "true" || sIn == "yes" || sIn == "t" ) | 1399 | if( sIn == "true" || sIn == "yes" || sIn == "t" ) |
1400 | dst = true; | 1400 | dst = true; |
1401 | else | 1401 | else |
1402 | dst = false; | 1402 | dst = false; |
1403 | 1403 | ||
1404 | return dst; | 1404 | return dst; |
1405 | } | 1405 | } |
1406 | 1406 | ||
1407 | uint8_t &Bu::operator<<( uint8_t &dst, const Bu::String &sIn ) | 1407 | uint8_t &Bu::operator<<( uint8_t &dst, const Bu::String &sIn ) |
1408 | { | 1408 | { |
1409 | sscanf( sIn.getStr(), "%hhu", &dst ); | 1409 | sscanf( sIn.getStr(), "%hhu", &dst ); |
1410 | return dst; | 1410 | return dst; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | int8_t &Bu::operator<<( int8_t &dst, const Bu::String &sIn ) | 1413 | int8_t &Bu::operator<<( int8_t &dst, const Bu::String &sIn ) |
1414 | { | 1414 | { |
1415 | sscanf( sIn.getStr(), "%hhd", &dst ); | 1415 | sscanf( sIn.getStr(), "%hhd", &dst ); |
1416 | return dst; | 1416 | return dst; |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | char &Bu::operator<<( char &dst, const Bu::String &sIn ) | 1419 | char &Bu::operator<<( char &dst, const Bu::String &sIn ) |
1420 | { | 1420 | { |
1421 | sscanf( sIn.getStr(), "%hhd", &dst ); | 1421 | sscanf( sIn.getStr(), "%hhd", &dst ); |
1422 | return dst; | 1422 | return dst; |
1423 | } | 1423 | } |
1424 | 1424 | ||
1425 | uint16_t &Bu::operator<<( uint16_t &dst, const Bu::String &sIn ) | 1425 | uint16_t &Bu::operator<<( uint16_t &dst, const Bu::String &sIn ) |
1426 | { | 1426 | { |
1427 | sscanf( sIn.getStr(), "%hu", &dst ); | 1427 | sscanf( sIn.getStr(), "%hu", &dst ); |
1428 | return dst; | 1428 | return dst; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | int16_t &Bu::operator<<( int16_t &dst, const Bu::String &sIn ) | 1431 | int16_t &Bu::operator<<( int16_t &dst, const Bu::String &sIn ) |
1432 | { | 1432 | { |
1433 | sscanf( sIn.getStr(), "%hd", &dst ); | 1433 | sscanf( sIn.getStr(), "%hd", &dst ); |
1434 | return dst; | 1434 | return dst; |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | uint32_t &Bu::operator<<( uint32_t &dst, const Bu::String &sIn ) | 1437 | uint32_t &Bu::operator<<( uint32_t &dst, const Bu::String &sIn ) |
1438 | { | 1438 | { |
1439 | sscanf( sIn.getStr(), "%u", &dst ); | 1439 | sscanf( sIn.getStr(), "%u", &dst ); |
1440 | return dst; | 1440 | return dst; |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | int32_t &Bu::operator<<( int32_t &dst, const Bu::String &sIn ) | 1443 | int32_t &Bu::operator<<( int32_t &dst, const Bu::String &sIn ) |
1444 | { | 1444 | { |
1445 | sscanf( sIn.getStr(), "%d", &dst ); | 1445 | sscanf( sIn.getStr(), "%d", &dst ); |
1446 | return dst; | 1446 | return dst; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | uint64_t &Bu::operator<<( uint64_t &dst, const Bu::String &sIn ) | 1449 | uint64_t &Bu::operator<<( uint64_t &dst, const Bu::String &sIn ) |
1450 | { | 1450 | { |
1451 | sscanf( sIn.getStr(), "%llu", &dst ); | 1451 | sscanf( sIn.getStr(), "%llu", &dst ); |
1452 | return dst; | 1452 | return dst; |
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | int64_t &Bu::operator<<( int64_t &dst, const Bu::String &sIn ) | 1455 | int64_t &Bu::operator<<( int64_t &dst, const Bu::String &sIn ) |
1456 | { | 1456 | { |
1457 | sscanf( sIn.getStr(), "%lld", &dst ); | 1457 | sscanf( sIn.getStr(), "%lld", &dst ); |
1458 | return dst; | 1458 | return dst; |
1459 | } | 1459 | } |
1460 | 1460 | ||
1461 | float &Bu::operator<<( float &dst, const Bu::String &sIn ) | 1461 | float &Bu::operator<<( float &dst, const Bu::String &sIn ) |
1462 | { | 1462 | { |
1463 | sscanf( sIn.getStr(), "%f", &dst ); | 1463 | sscanf( sIn.getStr(), "%f", &dst ); |
1464 | return dst; | 1464 | return dst; |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | double &Bu::operator<<( double &dst, const Bu::String &sIn ) | 1467 | double &Bu::operator<<( double &dst, const Bu::String &sIn ) |
1468 | { | 1468 | { |
1469 | sscanf( sIn.getStr(), "%lf", &dst ); | 1469 | sscanf( sIn.getStr(), "%lf", &dst ); |
1470 | return dst; | 1470 | return dst; |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | long double &Bu::operator<<( long double &dst, const Bu::String &sIn ) | 1473 | long double &Bu::operator<<( long double &dst, const Bu::String &sIn ) |
1474 | { | 1474 | { |
1475 | sscanf( sIn.getStr(), "%Lf", &dst ); | 1475 | sscanf( sIn.getStr(), "%Lf", &dst ); |
1476 | return dst; | 1476 | return dst; |
1477 | } | 1477 | } |
1478 | 1478 | ||
1479 | Bu::String &Bu::operator<<( Bu::String &dst, const Bu::String &sIn ) | 1479 | Bu::String &Bu::operator<<( Bu::String &dst, const Bu::String &sIn ) |
1480 | { | 1480 | { |
1481 | dst = sIn; | 1481 | dst = sIn; |
1482 | return dst; | 1482 | return dst; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::String &s ) | 1485 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::String &s ) |
1486 | { | 1486 | { |
1487 | long n = s.getSize(); | 1487 | long n = s.getSize(); |
1488 | ar << n; | 1488 | ar << n; |
1489 | ar.write( s.getConstStr(), n ); | 1489 | ar.write( s.getConstStr(), n ); |
1490 | return ar; | 1490 | return ar; |
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::String &s ) | 1493 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::String &s ) |
1494 | { | 1494 | { |
1495 | long n; | 1495 | long n; |
1496 | ar >> n; | 1496 | ar >> n; |
1497 | s.setSize( n ); | 1497 | s.setSize( n ); |
1498 | ar.read( s.getStr(), n ); | 1498 | ar.read( s.getStr(), n ); |
1499 | return ar; | 1499 | return ar; |
1500 | } | 1500 | } |
1501 | 1501 | ||
diff --git a/src/stable/string.h b/src/stable/string.h index 197821d..3be5bb9 100644 --- a/src/stable/string.h +++ b/src/stable/string.h | |||
@@ -22,1055 +22,1055 @@ | |||
22 | 22 | ||
23 | namespace Bu | 23 | namespace Bu |
24 | { | 24 | { |
25 | class String; | 25 | class String; |
26 | class MemBuf; | 26 | class MemBuf; |
27 | 27 | ||
28 | /** @cond DEVEL */ | 28 | /** @cond DEVEL */ |
29 | class StringCore | 29 | class StringCore |
30 | { | 30 | { |
31 | friend class String; | 31 | friend class String; |
32 | friend class SharedCore<String, StringCore>; | 32 | friend class SharedCore<String, StringCore>; |
33 | private: | 33 | private: |
34 | struct Chunk | 34 | struct Chunk |
35 | { | 35 | { |
36 | long nLength; | 36 | long nLength; |
37 | char *pData; | 37 | char *pData; |
38 | Chunk *pNext; | 38 | Chunk *pNext; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | StringCore(); | 41 | StringCore(); |
42 | StringCore( const StringCore &rSrc ); | 42 | StringCore( const StringCore &rSrc ); |
43 | virtual ~StringCore(); | 43 | virtual ~StringCore(); |
44 | 44 | ||
45 | mutable long nLength; | 45 | mutable long nLength; |
46 | mutable Chunk *pFirst; | 46 | mutable Chunk *pFirst; |
47 | mutable Chunk *pLast; | 47 | mutable Chunk *pLast; |
48 | 48 | ||
49 | void clear() const; | 49 | void clear() const; |
50 | Chunk *newChunk() const; | 50 | Chunk *newChunk() const; |
51 | Chunk *newChunk( long nLen ) const; | 51 | Chunk *newChunk( long nLen ) const; |
52 | Chunk *copyChunk( Chunk *pSrc ) const; | 52 | Chunk *copyChunk( Chunk *pSrc ) const; |
53 | void appendChunk( Chunk *pNewChunk ); | 53 | void appendChunk( Chunk *pNewChunk ); |
54 | void prependChunk( Chunk *pNewChunk ); | 54 | void prependChunk( Chunk *pNewChunk ); |
55 | }; | 55 | }; |
56 | /** @endcond */ | 56 | /** @endcond */ |
57 | 57 | ||
58 | /** | 58 | /** |
59 | */ | 59 | */ |
60 | class String : public SharedCore<String, StringCore> | 60 | class String : public SharedCore<String, StringCore> |
61 | { | 61 | { |
62 | protected: | 62 | protected: |
63 | using SharedCore<String, StringCore >::core; | 63 | using SharedCore<String, StringCore >::core; |
64 | using SharedCore<String, StringCore >::_hardCopy; | 64 | using SharedCore<String, StringCore >::_hardCopy; |
65 | 65 | ||
66 | private: | 66 | private: |
67 | typedef StringCore::Chunk Chunk; | 67 | typedef StringCore::Chunk Chunk; |
68 | 68 | ||
69 | public: // Iterators | 69 | public: // Iterators |
70 | struct iterator; | 70 | struct iterator; |
71 | typedef struct const_iterator | 71 | typedef struct const_iterator |
72 | { | 72 | { |
73 | friend class String; | 73 | friend class String; |
74 | friend struct iterator; | 74 | friend struct iterator; |
75 | private: | 75 | private: |
76 | const_iterator( Chunk *pChunk, int iPos ) : | 76 | const_iterator( Chunk *pChunk, int iPos ) : |
77 | pChunk( pChunk ), | 77 | pChunk( pChunk ), |
78 | iPos( iPos ) | 78 | iPos( iPos ) |
79 | { | 79 | { |
80 | } | 80 | } |
81 | 81 | ||
82 | Chunk *pChunk; | 82 | Chunk *pChunk; |
83 | int iPos; | 83 | int iPos; |
84 | 84 | ||
85 | public: | 85 | public: |
86 | const_iterator( const const_iterator &i ) : | 86 | const_iterator( const const_iterator &i ) : |
87 | pChunk( i.pChunk ), | 87 | pChunk( i.pChunk ), |
88 | iPos( i.iPos ) | 88 | iPos( i.iPos ) |
89 | { | 89 | { |
90 | } | 90 | } |
91 | 91 | ||
92 | const_iterator( const struct iterator &i ) : | 92 | const_iterator( const struct iterator &i ) : |
93 | pChunk( i.pChunk ), | 93 | pChunk( i.pChunk ), |
94 | iPos( i.iPos ) | 94 | iPos( i.iPos ) |
95 | { | 95 | { |
96 | } | 96 | } |
97 | 97 | ||
98 | const_iterator() : | 98 | const_iterator() : |
99 | pChunk( NULL ), | 99 | pChunk( NULL ), |
100 | iPos( 0 ) | 100 | iPos( 0 ) |
101 | { | 101 | { |
102 | } | 102 | } |
103 | 103 | ||
104 | bool operator==( const const_iterator &i ) const | 104 | bool operator==( const const_iterator &i ) const |
105 | { | 105 | { |
106 | return pChunk == i.pChunk && iPos == i.iPos; | 106 | return pChunk == i.pChunk && iPos == i.iPos; |
107 | } | 107 | } |
108 | 108 | ||
109 | bool operator!=( const const_iterator &i ) const | 109 | bool operator!=( const const_iterator &i ) const |
110 | { | 110 | { |
111 | return !(*this == i); | 111 | return !(*this == i); |
112 | } | 112 | } |
113 | 113 | ||
114 | const_iterator &operator=( const const_iterator &i ) | 114 | const_iterator &operator=( const const_iterator &i ) |
115 | { | 115 | { |
116 | pChunk = i.pChunk; | 116 | pChunk = i.pChunk; |
117 | iPos = i.iPos; | 117 | iPos = i.iPos; |
118 | return *this; | 118 | return *this; |
119 | } | 119 | } |
120 | 120 | ||
121 | const_iterator &operator=( const iterator &i ) | 121 | const_iterator &operator=( const iterator &i ) |
122 | { | 122 | { |
123 | pChunk = i.pChunk; | 123 | pChunk = i.pChunk; |
124 | iPos = i.iPos; | 124 | iPos = i.iPos; |
125 | return *this; | 125 | return *this; |
126 | } | 126 | } |
127 | 127 | ||
128 | const_iterator &operator++() | 128 | const_iterator &operator++() |
129 | { | 129 | { |
130 | if( !pChunk ) return *this; | 130 | if( !pChunk ) return *this; |
131 | iPos++; | 131 | iPos++; |
132 | if( iPos >= pChunk->nLength ) | 132 | if( iPos >= pChunk->nLength ) |
133 | { | 133 | { |
134 | iPos = 0; | 134 | iPos = 0; |
135 | pChunk = pChunk->pNext; | 135 | pChunk = pChunk->pNext; |
136 | } | 136 | } |
137 | return *this; | 137 | return *this; |
138 | } | 138 | } |
139 | 139 | ||
140 | const_iterator &operator++( int ) | 140 | const_iterator &operator++( int ) |
141 | { | 141 | { |
142 | if( !pChunk ) return *this; | 142 | if( !pChunk ) return *this; |
143 | iPos++; | 143 | iPos++; |
144 | if( iPos >= pChunk->nLength ) | 144 | if( iPos >= pChunk->nLength ) |
145 | { | 145 | { |
146 | iPos = 0; | 146 | iPos = 0; |
147 | pChunk = pChunk->pNext; | 147 | pChunk = pChunk->pNext; |
148 | } | 148 | } |
149 | return *this; | 149 | return *this; |
150 | } | 150 | } |
151 | 151 | ||
152 | const_iterator &operator+=( int iAmnt ) | 152 | const_iterator &operator+=( int iAmnt ) |
153 | { | 153 | { |
154 | if( !pChunk ) return *this; | 154 | if( !pChunk ) return *this; |
155 | iPos += iAmnt; | 155 | iPos += iAmnt; |
156 | while( iPos >= pChunk->nLength ) | 156 | while( iPos >= pChunk->nLength ) |
157 | { | 157 | { |
158 | iPos -= pChunk->nLength; | 158 | iPos -= pChunk->nLength; |
159 | pChunk = pChunk->pNext; | 159 | pChunk = pChunk->pNext; |
160 | if( pChunk == NULL ) | 160 | if( pChunk == NULL ) |
161 | break; | 161 | break; |
162 | } | 162 | } |
163 | return *this; | 163 | return *this; |
164 | } | 164 | } |
165 | 165 | ||
166 | const_iterator operator+( int iAmnt ) const | 166 | const_iterator operator+( int iAmnt ) const |
167 | { | 167 | { |
168 | if( !pChunk ) return *this; | 168 | if( !pChunk ) return *this; |
169 | const_iterator ret( *this ); | 169 | const_iterator ret( *this ); |
170 | ret += iAmnt; | 170 | ret += iAmnt; |
171 | return ret; | 171 | return ret; |
172 | } | 172 | } |
173 | 173 | ||
174 | const char &operator *() const | 174 | const char &operator *() const |
175 | { | 175 | { |
176 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid const_iterator."); | 176 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid const_iterator."); |
177 | return pChunk->pData[iPos]; | 177 | return pChunk->pData[iPos]; |
178 | } | 178 | } |
179 | 179 | ||
180 | bool operator==( const char &c ) const | 180 | bool operator==( const char &c ) const |
181 | { | 181 | { |
182 | if( !pChunk ) return false; | 182 | if( !pChunk ) return false; |
183 | return pChunk->pData[iPos] == c; | 183 | return pChunk->pData[iPos] == c; |
184 | } | 184 | } |
185 | 185 | ||
186 | bool operator!=( const char &c ) const | 186 | bool operator!=( const char &c ) const |
187 | { | 187 | { |
188 | if( !pChunk ) return false; | 188 | if( !pChunk ) return false; |
189 | return pChunk->pData[iPos] != c; | 189 | return pChunk->pData[iPos] != c; |
190 | } | 190 | } |
191 | 191 | ||
192 | operator bool() const | 192 | operator bool() const |
193 | { | 193 | { |
194 | return pChunk != NULL; | 194 | return pChunk != NULL; |
195 | } | 195 | } |
196 | 196 | ||
197 | bool isValid() const | 197 | bool isValid() const |
198 | { | 198 | { |
199 | return pChunk != NULL; | 199 | return pChunk != NULL; |
200 | } | 200 | } |
201 | 201 | ||
202 | bool compare( const const_iterator &c ) const | 202 | bool compare( const const_iterator &c ) const |
203 | { | 203 | { |
204 | const_iterator a = *this; | 204 | const_iterator a = *this; |
205 | const_iterator b = c; | 205 | const_iterator b = c; |
206 | if( a == b ) | 206 | if( a == b ) |
207 | return true; | 207 | return true; |
208 | for(; a && b; a++, b++ ) | 208 | for(; a && b; a++, b++ ) |
209 | { | 209 | { |
210 | if( *a != *b ) | 210 | if( *a != *b ) |
211 | return false; | 211 | return false; |
212 | } | 212 | } |
213 | if( (bool)a != (bool)b ) | 213 | if( (bool)a != (bool)b ) |
214 | return false; | 214 | return false; |
215 | return true; | 215 | return true; |
216 | } | 216 | } |
217 | 217 | ||
218 | bool compare( const const_iterator &c, int nLen ) const | 218 | bool compare( const const_iterator &c, int nLen ) const |
219 | { | 219 | { |
220 | const_iterator a = *this; | 220 | const_iterator a = *this; |
221 | const_iterator b = c; | 221 | const_iterator b = c; |
222 | if( a == b ) | 222 | if( a == b ) |
223 | return true; | 223 | return true; |
224 | for(int j = 0; j < nLen; a++, b++, j++ ) | 224 | for(int j = 0; j < nLen; a++, b++, j++ ) |
225 | { | 225 | { |
226 | if( !a || !b || *a != *b ) | 226 | if( !a || !b || *a != *b ) |
227 | return false; | 227 | return false; |
228 | } | 228 | } |
229 | return true; | 229 | return true; |
230 | } | 230 | } |
231 | 231 | ||
232 | bool compare( const char *c ) const | 232 | bool compare( const char *c ) const |
233 | { | 233 | { |
234 | if( !pChunk ) return false; | 234 | if( !pChunk ) return false; |
235 | const_iterator a = *this; | 235 | const_iterator a = *this; |
236 | for(; a && *c; a++, c++ ) | 236 | for(; a && *c; a++, c++ ) |
237 | { | 237 | { |
238 | if( *a != *c ) | 238 | if( *a != *c ) |
239 | return false; | 239 | return false; |
240 | } | 240 | } |
241 | if( a.isValid() != (*c!=(char)0) ) | 241 | if( a.isValid() != (*c!=(char)0) ) |
242 | return false; | 242 | return false; |
243 | return true; | 243 | return true; |
244 | } | 244 | } |
245 | 245 | ||
246 | bool compare( const char *c, int nLen ) const | 246 | bool compare( const char *c, int nLen ) const |
247 | { | 247 | { |
248 | if( !pChunk ) return false; | 248 | if( !pChunk ) return false; |
249 | const_iterator a = *this; | 249 | const_iterator a = *this; |
250 | int j = 0; | 250 | int j = 0; |
251 | for(; a && j < nLen; a++, c++, j++ ) | 251 | for(; a && j < nLen; a++, c++, j++ ) |
252 | { | 252 | { |
253 | if( *a != *c ) | 253 | if( *a != *c ) |
254 | return false; | 254 | return false; |
255 | } | 255 | } |
256 | if( j < nLen ) | 256 | if( j < nLen ) |
257 | return false; | 257 | return false; |
258 | return true; | 258 | return true; |
259 | } | 259 | } |
260 | 260 | ||
261 | bool compare( const String &s ) const | 261 | bool compare( const String &s ) const |
262 | { | 262 | { |
263 | if( !pChunk ) return false; | 263 | if( !pChunk ) return false; |
264 | return compare( s.begin() ); | 264 | return compare( s.begin() ); |
265 | } | 265 | } |
266 | 266 | ||
267 | bool compare( const String &s, int nLen ) const | 267 | bool compare( const String &s, int nLen ) const |
268 | { | 268 | { |
269 | if( !pChunk ) return false; | 269 | if( !pChunk ) return false; |
270 | return compare( s.begin(), nLen ); | 270 | return compare( s.begin(), nLen ); |
271 | } | 271 | } |
272 | 272 | ||
273 | const_iterator find( const char c ) const | 273 | const_iterator find( const char c ) const |
274 | { | 274 | { |
275 | for( const_iterator i = *this; i; i++ ) | 275 | for( const_iterator i = *this; i; i++ ) |
276 | { | 276 | { |
277 | if( *i == c ) | 277 | if( *i == c ) |
278 | return i; | 278 | return i; |
279 | } | 279 | } |
280 | return const_iterator( NULL, 0 ); | 280 | return const_iterator( NULL, 0 ); |
281 | } | 281 | } |
282 | 282 | ||
283 | const_iterator find( const char *pStr, int nLen ) const | 283 | const_iterator find( const char *pStr, int nLen ) const |
284 | { | 284 | { |
285 | for( const_iterator i = *this; i; i++ ) | 285 | for( const_iterator i = *this; i; i++ ) |
286 | { | 286 | { |
287 | if( i.compare( pStr, nLen ) ) | 287 | if( i.compare( pStr, nLen ) ) |
288 | return i; | 288 | return i; |
289 | } | 289 | } |
290 | return const_iterator( NULL, 0 ); | 290 | return const_iterator( NULL, 0 ); |
291 | } | 291 | } |
292 | 292 | ||
293 | const_iterator find( const String &s ) const | 293 | const_iterator find( const String &s ) const |
294 | { | 294 | { |
295 | for( const_iterator i = *this; i; i++ ) | 295 | for( const_iterator i = *this; i; i++ ) |
296 | { | 296 | { |
297 | if( i.compare( s ) ) | 297 | if( i.compare( s ) ) |
298 | return i; | 298 | return i; |
299 | } | 299 | } |
300 | return const_iterator( NULL, 0 ); | 300 | return const_iterator( NULL, 0 ); |
301 | } | 301 | } |
302 | 302 | ||
303 | const_iterator find( const String &s, int nLen ) const | 303 | const_iterator find( const String &s, int nLen ) const |
304 | { | 304 | { |
305 | for( const_iterator i = *this; i; i++ ) | 305 | for( const_iterator i = *this; i; i++ ) |
306 | { | 306 | { |
307 | if( i.compare( s, nLen ) ) | 307 | if( i.compare( s, nLen ) ) |
308 | return i; | 308 | return i; |
309 | } | 309 | } |
310 | return const_iterator( NULL, 0 ); | 310 | return const_iterator( NULL, 0 ); |
311 | } | 311 | } |
312 | } const_iterator; | 312 | } const_iterator; |
313 | 313 | ||
314 | typedef struct iterator | 314 | typedef struct iterator |
315 | { | 315 | { |
316 | friend class String; | 316 | friend class String; |
317 | friend struct const_iterator; | 317 | friend struct const_iterator; |
318 | private: | 318 | private: |
319 | iterator( Chunk *pChunk, int iPos ) : | 319 | iterator( Chunk *pChunk, int iPos ) : |
320 | pChunk( pChunk ), | 320 | pChunk( pChunk ), |
321 | iPos( iPos ) | 321 | iPos( iPos ) |
322 | { | 322 | { |
323 | } | 323 | } |
324 | 324 | ||
325 | Chunk *pChunk; | 325 | Chunk *pChunk; |
326 | int iPos; | 326 | int iPos; |
327 | 327 | ||
328 | public: | 328 | public: |
329 | iterator( const iterator &i ) : | 329 | iterator( const iterator &i ) : |
330 | pChunk( i.pChunk ), | 330 | pChunk( i.pChunk ), |
331 | iPos( i.iPos ) | 331 | iPos( i.iPos ) |
332 | { | 332 | { |
333 | } | 333 | } |
334 | 334 | ||
335 | iterator() : | 335 | iterator() : |
336 | pChunk( NULL ), | 336 | pChunk( NULL ), |
337 | iPos( 0 ) | 337 | iPos( 0 ) |
338 | { | 338 | { |
339 | } | 339 | } |
340 | 340 | ||
341 | operator const_iterator() const | 341 | operator const_iterator() const |
342 | { | 342 | { |
343 | return const_iterator( pChunk, iPos ); | 343 | return const_iterator( pChunk, iPos ); |
344 | } | 344 | } |
345 | 345 | ||
346 | bool operator==( const iterator &i ) const | 346 | bool operator==( const iterator &i ) const |
347 | { | 347 | { |
348 | return pChunk == i.pChunk && iPos == i.iPos; | 348 | return pChunk == i.pChunk && iPos == i.iPos; |
349 | } | 349 | } |
350 | 350 | ||
351 | bool operator!=( const iterator &i ) const | 351 | bool operator!=( const iterator &i ) const |
352 | { | 352 | { |
353 | return !(*this == i); | 353 | return !(*this == i); |
354 | } | 354 | } |
355 | 355 | ||
356 | iterator &operator=( const iterator &i ) | 356 | iterator &operator=( const iterator &i ) |
357 | { | 357 | { |
358 | pChunk = i.pChunk; | 358 | pChunk = i.pChunk; |
359 | iPos = i.iPos; | 359 | iPos = i.iPos; |
360 | return *this; | 360 | return *this; |
361 | } | 361 | } |
362 | 362 | ||
363 | iterator &operator++() | 363 | iterator &operator++() |
364 | { | 364 | { |
365 | if( !pChunk ) return *this; | 365 | if( !pChunk ) return *this; |
366 | iPos++; | 366 | iPos++; |
367 | if( iPos >= pChunk->nLength ) | 367 | if( iPos >= pChunk->nLength ) |
368 | { | 368 | { |
369 | iPos = 0; | 369 | iPos = 0; |
370 | pChunk = pChunk->pNext; | 370 | pChunk = pChunk->pNext; |
371 | } | 371 | } |
372 | return *this; | 372 | return *this; |
373 | } | 373 | } |
374 | 374 | ||
375 | iterator &operator++( int ) | 375 | iterator &operator++( int ) |
376 | { | 376 | { |
377 | if( !pChunk ) return *this; | 377 | if( !pChunk ) return *this; |
378 | iPos++; | 378 | iPos++; |
379 | if( iPos >= pChunk->nLength ) | 379 | if( iPos >= pChunk->nLength ) |
380 | { | 380 | { |
381 | iPos = 0; | 381 | iPos = 0; |
382 | pChunk = pChunk->pNext; | 382 | pChunk = pChunk->pNext; |
383 | } | 383 | } |
384 | return *this; | 384 | return *this; |
385 | } | 385 | } |
386 | 386 | ||
387 | iterator &operator+=( int iAmnt ) | 387 | iterator &operator+=( int iAmnt ) |
388 | { | 388 | { |
389 | if( !pChunk ) return *this; | 389 | if( !pChunk ) return *this; |
390 | iPos += iAmnt; | 390 | iPos += iAmnt; |
391 | while( iPos >= pChunk->nLength ) | 391 | while( iPos >= pChunk->nLength ) |
392 | { | 392 | { |
393 | iPos -= pChunk->nLength; | 393 | iPos -= pChunk->nLength; |
394 | pChunk = pChunk->pNext; | 394 | pChunk = pChunk->pNext; |
395 | if( pChunk == NULL ) | 395 | if( pChunk == NULL ) |
396 | break; | 396 | break; |
397 | } | 397 | } |
398 | return *this; | 398 | return *this; |
399 | } | 399 | } |
400 | 400 | ||
401 | iterator operator+( int iAmnt ) const | 401 | iterator operator+( int iAmnt ) const |
402 | { | 402 | { |
403 | if( !pChunk ) return *this; | 403 | if( !pChunk ) return *this; |
404 | iterator ret( *this ); | 404 | iterator ret( *this ); |
405 | ret += iAmnt; | 405 | ret += iAmnt; |
406 | return ret; | 406 | return ret; |
407 | } | 407 | } |
408 | 408 | ||
409 | char &operator*() | 409 | char &operator*() |
410 | { | 410 | { |
411 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 411 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
412 | return pChunk->pData[iPos]; | 412 | return pChunk->pData[iPos]; |
413 | } | 413 | } |
414 | 414 | ||
415 | const char &operator*() const | 415 | const char &operator*() const |
416 | { | 416 | { |
417 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 417 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
418 | return pChunk->pData[iPos]; | 418 | return pChunk->pData[iPos]; |
419 | } | 419 | } |
420 | 420 | ||
421 | bool operator==( const char &c ) const | 421 | bool operator==( const char &c ) const |
422 | { | 422 | { |
423 | if( !pChunk ) return false; | 423 | if( !pChunk ) return false; |
424 | return pChunk->pData[iPos] == c; | 424 | return pChunk->pData[iPos] == c; |
425 | } | 425 | } |
426 | 426 | ||
427 | bool operator!=( const char &c ) const | 427 | bool operator!=( const char &c ) const |
428 | { | 428 | { |
429 | if( !pChunk ) return false; | 429 | if( !pChunk ) return false; |
430 | return pChunk->pData[iPos] != c; | 430 | return pChunk->pData[iPos] != c; |
431 | } | 431 | } |
432 | 432 | ||
433 | iterator &operator=( const char &c ) | 433 | iterator &operator=( const char &c ) |
434 | { | 434 | { |
435 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 435 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
436 | pChunk->pData[iPos] = c; | 436 | pChunk->pData[iPos] = c; |
437 | return *this; | 437 | return *this; |
438 | } | 438 | } |
439 | 439 | ||
440 | operator bool() const | 440 | operator bool() const |
441 | { | 441 | { |
442 | return pChunk != NULL; | 442 | return pChunk != NULL; |
443 | } | 443 | } |
444 | 444 | ||
445 | bool isValid() const | 445 | bool isValid() const |
446 | { | 446 | { |
447 | return pChunk != NULL; | 447 | return pChunk != NULL; |
448 | } | 448 | } |
449 | 449 | ||
450 | bool compare( const const_iterator &c ) const | 450 | bool compare( const const_iterator &c ) const |
451 | { | 451 | { |
452 | const_iterator a( *this ); | 452 | const_iterator a( *this ); |
453 | const_iterator b = c; | 453 | const_iterator b = c; |
454 | if( a == b ) | 454 | if( a == b ) |
455 | return true; | 455 | return true; |
456 | for(; a && b; a++, b++ ) | 456 | for(; a && b; a++, b++ ) |
457 | { | 457 | { |
458 | if( *a != *b ) | 458 | if( *a != *b ) |
459 | return false; | 459 | return false; |
460 | } | 460 | } |
461 | if( (bool)a != (bool)b ) | 461 | if( (bool)a != (bool)b ) |
462 | return false; | 462 | return false; |
463 | return true; | 463 | return true; |
464 | } | 464 | } |
465 | 465 | ||
466 | bool compare( const const_iterator &c, int nLen ) const | 466 | bool compare( const const_iterator &c, int nLen ) const |
467 | { | 467 | { |
468 | const_iterator a( *this ); | 468 | const_iterator a( *this ); |
469 | const_iterator b = c; | 469 | const_iterator b = c; |
470 | if( a == b ) | 470 | if( a == b ) |
471 | return true; | 471 | return true; |
472 | for(int j = 0; j < nLen; a++, b++, j++ ) | 472 | for(int j = 0; j < nLen; a++, b++, j++ ) |
473 | { | 473 | { |
474 | if( !a || !b || *a != *b ) | 474 | if( !a || !b || *a != *b ) |
475 | return false; | 475 | return false; |
476 | } | 476 | } |
477 | return true; | 477 | return true; |
478 | } | 478 | } |
479 | 479 | ||
480 | bool compare( const char *c ) const | 480 | bool compare( const char *c ) const |
481 | { | 481 | { |
482 | if( !pChunk ) return false; | 482 | if( !pChunk ) return false; |
483 | iterator a = *this; | 483 | iterator a = *this; |
484 | for(; a && *c; a++, c++ ) | 484 | for(; a && *c; a++, c++ ) |
485 | { | 485 | { |
486 | if( *a != *c ) | 486 | if( *a != *c ) |
487 | return false; | 487 | return false; |
488 | } | 488 | } |
489 | if( a.isValid() != (*c!=(char)0) ) | 489 | if( a.isValid() != (*c!=(char)0) ) |
490 | return false; | 490 | return false; |
491 | return true; | 491 | return true; |
492 | } | 492 | } |
493 | 493 | ||
494 | bool compare( const char *c, int nLen ) const | 494 | bool compare( const char *c, int nLen ) const |
495 | { | 495 | { |
496 | if( !pChunk ) return false; | 496 | if( !pChunk ) return false; |
497 | iterator a = *this; | 497 | iterator a = *this; |
498 | int j = 0; | 498 | int j = 0; |
499 | for(; a && j < nLen; a++, c++, j++ ) | 499 | for(; a && j < nLen; a++, c++, j++ ) |
500 | { | 500 | { |
501 | if( *a != *c ) | 501 | if( *a != *c ) |
502 | return false; | 502 | return false; |
503 | } | 503 | } |
504 | if( j < nLen ) | 504 | if( j < nLen ) |
505 | return false; | 505 | return false; |
506 | return true; | 506 | return true; |
507 | } | 507 | } |
508 | 508 | ||
509 | bool compare( const String &s ) const | 509 | bool compare( const String &s ) const |
510 | { | 510 | { |
511 | if( !pChunk ) return false; | 511 | if( !pChunk ) return false; |
512 | return compare( s.begin() ); | 512 | return compare( s.begin() ); |
513 | } | 513 | } |
514 | 514 | ||
515 | bool compare( const String &s, int nLen ) const | 515 | bool compare( const String &s, int nLen ) const |
516 | { | 516 | { |
517 | if( !pChunk ) return false; | 517 | if( !pChunk ) return false; |
518 | return compare( s.begin(), nLen ); | 518 | return compare( s.begin(), nLen ); |
519 | } | 519 | } |
520 | 520 | ||
521 | iterator find( const char c ) const | 521 | iterator find( const char c ) const |
522 | { | 522 | { |
523 | for( iterator i = *this; i; i++ ) | 523 | for( iterator i = *this; i; i++ ) |
524 | { | 524 | { |
525 | if( *i == c ) | 525 | if( *i == c ) |
526 | return i; | 526 | return i; |
527 | } | 527 | } |
528 | return iterator( NULL, 0 ); | 528 | return iterator( NULL, 0 ); |
529 | } | 529 | } |
530 | 530 | ||
531 | iterator find( const char *pStr, int nLen ) const | 531 | iterator find( const char *pStr, int nLen ) const |
532 | { | 532 | { |
533 | for( iterator i = *this; i; i++ ) | 533 | for( iterator i = *this; i; i++ ) |
534 | { | 534 | { |
535 | if( i.compare( pStr, nLen ) ) | 535 | if( i.compare( pStr, nLen ) ) |
536 | return i; | 536 | return i; |
537 | } | 537 | } |
538 | return iterator( NULL, 0 ); | 538 | return iterator( NULL, 0 ); |
539 | } | 539 | } |
540 | 540 | ||
541 | iterator find( const String &s ) const | 541 | iterator find( const String &s ) const |
542 | { | 542 | { |
543 | for( iterator i = *this; i; i++ ) | 543 | for( iterator i = *this; i; i++ ) |
544 | { | 544 | { |
545 | if( i.compare( s ) ) | 545 | if( i.compare( s ) ) |
546 | return i; | 546 | return i; |
547 | } | 547 | } |
548 | return iterator( NULL, 0 ); | 548 | return iterator( NULL, 0 ); |
549 | } | 549 | } |
550 | 550 | ||
551 | iterator find( const String &s, int nLen ) const | 551 | iterator find( const String &s, int nLen ) const |
552 | { | 552 | { |
553 | for( iterator i = *this; i; i++ ) | 553 | for( iterator i = *this; i; i++ ) |
554 | { | 554 | { |
555 | if( i.compare( s, nLen ) ) | 555 | if( i.compare( s, nLen ) ) |
556 | return i; | 556 | return i; |
557 | } | 557 | } |
558 | return iterator( NULL, 0 ); | 558 | return iterator( NULL, 0 ); |
559 | } | 559 | } |
560 | } iterator; | 560 | } iterator; |
561 | 561 | ||
562 | public: | 562 | public: |
563 | String(); | 563 | String(); |
564 | String( const char *pData ); | 564 | String( const char *pData ); |
565 | String( const char *pData, long nLength ); | 565 | String( const char *pData, long nLength ); |
566 | String( const String &rSrc ); | 566 | String( const String &rSrc ); |
567 | String( const String &rSrc, long nLength ); | 567 | String( const String &rSrc, long nLength ); |
568 | String( const String &rSrc, long nStart, long nLength ); | 568 | String( const String &rSrc, long nStart, long nLength ); |
569 | String( long nSize ); | 569 | String( long nSize ); |
570 | String( const const_iterator &s ); | 570 | String( const const_iterator &s ); |
571 | String( const const_iterator &s, const const_iterator &e ); | 571 | String( const const_iterator &s, const const_iterator &e ); |
572 | virtual ~String(); | 572 | virtual ~String(); |
573 | 573 | ||
574 | /** | 574 | /** |
575 | * Append data to your string. | 575 | * Append data to your string. |
576 | *@param pData (const char *) The data to append. | 576 | *@param pData (const char *) The data to append. |
577 | */ | 577 | */ |
578 | void append( const char *pData ); | 578 | void append( const char *pData ); |
579 | 579 | ||
580 | /** | 580 | /** |
581 | * Append data to your string. | 581 | * Append data to your string. |
582 | *@param pData (const char *) The data to append. | 582 | *@param pData (const char *) The data to append. |
583 | *@param nLen (long) The length of the data to append. | 583 | *@param nLen (long) The length of the data to append. |
584 | */ | 584 | */ |
585 | void append( const char *pData, long nLen ); | 585 | void append( const char *pData, long nLen ); |
586 | 586 | ||
587 | /** | 587 | /** |
588 | * Append data to your string. | 588 | * Append data to your string. |
589 | *@param pData (const char *) The data to append. | 589 | *@param pData (const char *) The data to append. |
590 | *@param nStart (long) The start position to copy from. | 590 | *@param nStart (long) The start position to copy from. |
591 | *@param nLen (long) The length of the data to append. | 591 | *@param nLen (long) The length of the data to append. |
592 | */ | 592 | */ |
593 | void append( const char *pData, long nStart, long nLen ); | 593 | void append( const char *pData, long nStart, long nLen ); |
594 | 594 | ||
595 | /** | 595 | /** |
596 | * Append a single char to your string. | 596 | * Append a single char to your string. |
597 | *@param cData (const char &) The character to append. | 597 | *@param cData (const char &) The character to append. |
598 | */ | 598 | */ |
599 | void append( const char &cData ); | 599 | void append( const char &cData ); |
600 | 600 | ||
601 | /** | 601 | /** |
602 | * Append another String to this one. | 602 | * Append another String to this one. |
603 | *@param sData (String &) The String to append. | 603 | *@param sData (String &) The String to append. |
604 | *@todo This function can be made much faster by not using getStr() | 604 | *@todo This function can be made much faster by not using getStr() |
605 | */ | 605 | */ |
606 | void append( const String & sData ); | 606 | void append( const String & sData ); |
607 | 607 | ||
608 | /** | 608 | /** |
609 | * Append another String to this one. | 609 | * Append another String to this one. |
610 | *@param sData (String &) The String to append. | 610 | *@param sData (String &) The String to append. |
611 | *@param nLen How much data to append. | 611 | *@param nLen How much data to append. |
612 | *@todo This function can be made much faster by not using getStr() | 612 | *@todo This function can be made much faster by not using getStr() |
613 | */ | 613 | */ |
614 | void append( const String & sData, long nLen ); | 614 | void append( const String & sData, long nLen ); |
615 | 615 | ||
616 | /** | 616 | /** |
617 | * Append another String to this one. | 617 | * Append another String to this one. |
618 | *@param sData (String &) The String to append. | 618 | *@param sData (String &) The String to append. |
619 | *@param nStart Start position in sData to start copying from. | 619 | *@param nStart Start position in sData to start copying from. |
620 | *@param nLen How much data to append. | 620 | *@param nLen How much data to append. |
621 | *@todo This function can be made much faster by not using getStr() | 621 | *@todo This function can be made much faster by not using getStr() |
622 | */ | 622 | */ |
623 | void append( const String & sData, long nStart, long nLen ); | 623 | void append( const String & sData, long nStart, long nLen ); |
624 | 624 | ||
625 | /** | 625 | /** |
626 | * Append data to this String using the passed in iterator as a base. | 626 | * Append data to this String using the passed in iterator as a base. |
627 | * The iterator is const, it is not changed. | 627 | * The iterator is const, it is not changed. |
628 | *@param s Iterator from any compatible String to copy data from. | 628 | *@param s Iterator from any compatible String to copy data from. |
629 | */ | 629 | */ |
630 | void append( const const_iterator &s ); | 630 | void append( const const_iterator &s ); |
631 | 631 | ||
632 | /** | 632 | /** |
633 | * Append data to this String using the passed in iterator as a base. | 633 | * Append data to this String using the passed in iterator as a base. |
634 | * The iterator is const, it is not changed. | 634 | * The iterator is const, it is not changed. |
635 | *@param s Iterator from any compatible String to copy data from. | 635 | *@param s Iterator from any compatible String to copy data from. |
636 | */ | 636 | */ |
637 | void append( const iterator &s ); | 637 | void append( const iterator &s ); |
638 | 638 | ||
639 | /** | 639 | /** |
640 | * Append data to this String using the passed in iterator as a base, | 640 | * Append data to this String using the passed in iterator as a base, |
641 | * and copy data until the ending iterator is reached. The character | 641 | * and copy data until the ending iterator is reached. The character |
642 | * at the ending iterator is not copied. | 642 | * at the ending iterator is not copied. |
643 | * The iterators are const, they are not changed. | 643 | * The iterators are const, they are not changed. |
644 | *@param s Iterator from any compatible String to copy data from. | 644 | *@param s Iterator from any compatible String to copy data from. |
645 | *@param e Iterator to stop copying at. | 645 | *@param e Iterator to stop copying at. |
646 | */ | 646 | */ |
647 | void append( const const_iterator &s, const const_iterator &e ); | 647 | void append( const const_iterator &s, const const_iterator &e ); |
648 | 648 | ||
649 | /** | 649 | /** |
650 | * Prepend another String to this one. | 650 | * Prepend another String to this one. |
651 | *@param sData (String &) The String to prepend. | 651 | *@param sData (String &) The String to prepend. |
652 | *@todo This function can be made much faster by not using getStr() | 652 | *@todo This function can be made much faster by not using getStr() |
653 | */ | 653 | */ |
654 | void prepend( const String & sData ); | 654 | void prepend( const String & sData ); |
655 | 655 | ||
656 | /** | 656 | /** |
657 | * Prepend data to your string. | 657 | * Prepend data to your string. |
658 | *@param pData (const char *) The data to prepend. | 658 | *@param pData (const char *) The data to prepend. |
659 | */ | 659 | */ |
660 | void prepend( const char *pData ); | 660 | void prepend( const char *pData ); |
661 | 661 | ||
662 | /** | 662 | /** |
663 | * Prepend data to your string. | 663 | * Prepend data to your string. |
664 | *@param pData (const char *) The data to prepend. | 664 | *@param pData (const char *) The data to prepend. |
665 | *@param nLen (long) The length of the data to prepend. | 665 | *@param nLen (long) The length of the data to prepend. |
666 | */ | 666 | */ |
667 | void prepend( const char *pData, long nLen ); | 667 | void prepend( const char *pData, long nLen ); |
668 | 668 | ||
669 | void prepend( const char c ); | 669 | void prepend( const char c ); |
670 | 670 | ||
671 | /** | 671 | /** |
672 | * Insert pData before byte nPos, that is, the first byte of pData will | 672 | * Insert pData before byte nPos, that is, the first byte of pData will |
673 | * start at nPos. This could probably be made faster by avoiding | 673 | * start at nPos. This could probably be made faster by avoiding |
674 | * flattening. | 674 | * flattening. |
675 | */ | 675 | */ |
676 | void insert( long nPos, const char *pData, long nLen ); | 676 | void insert( long nPos, const char *pData, long nLen ); |
677 | 677 | ||
678 | void insert( long nPos, const String &str ); | 678 | void insert( long nPos, const String &str ); |
679 | 679 | ||
680 | /** | 680 | /** |
681 | *@todo This function shouldn't use strlen, we should add our own to | 681 | *@todo This function shouldn't use strlen, we should add our own to |
682 | * this class, one that can be overridden in a specific implementation. | 682 | * this class, one that can be overridden in a specific implementation. |
683 | */ | 683 | */ |
684 | void insert( long nPos, const char *pData ); | 684 | void insert( long nPos, const char *pData ); |
685 | 685 | ||
686 | void remove( long nPos, long nLen ); | 686 | void remove( long nPos, long nLen ); |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * Clear all data from the string. | 689 | * Clear all data from the string. |
690 | */ | 690 | */ |
691 | void clear(); | 691 | void clear(); |
692 | 692 | ||
693 | String replace( const String &fnd, const String &rep ) const; | 693 | String replace( const String &fnd, const String &rep ) const; |
694 | 694 | ||
695 | /** | 695 | /** |
696 | * Force the string to resize | 696 | * Force the string to resize |
697 | *@param nNewSize (long) The new size of the string. | 697 | *@param nNewSize (long) The new size of the string. |
698 | */ | 698 | */ |
699 | void resize( long nNewSize ); | 699 | void resize( long nNewSize ); |
700 | 700 | ||
701 | /** | 701 | /** |
702 | * Get the current size of the string. | 702 | * Get the current size of the string. |
703 | *@returns (long) The current size of the string. | 703 | *@returns (long) The current size of the string. |
704 | */ | 704 | */ |
705 | long getSize() const; | 705 | long getSize() const; |
706 | 706 | ||
707 | /** | 707 | /** |
708 | * Get a pointer to the string array. | 708 | * Get a pointer to the string array. |
709 | *@returns (char *) The string data. | 709 | *@returns (char *) The string data. |
710 | */ | 710 | */ |
711 | char *getStr(); | 711 | char *getStr(); |
712 | 712 | ||
713 | /** | 713 | /** |
714 | * Get a const pointer to the string array. | 714 | * Get a const pointer to the string array. |
715 | *@returns (const char *) The string data. | 715 | *@returns (const char *) The string data. |
716 | */ | 716 | */ |
717 | const char *getStr() const; | 717 | const char *getStr() const; |
718 | 718 | ||
719 | /** | 719 | /** |
720 | * A convinience function, this one won't cause as much work as the | 720 | * A convinience function, this one won't cause as much work as the |
721 | * non-const getStr, so if you're not changing the data, consider it. | 721 | * non-const getStr, so if you're not changing the data, consider it. |
722 | */ | 722 | */ |
723 | const char *getConstStr() const; | 723 | const char *getConstStr() const; |
724 | 724 | ||
725 | String getSubStrIdx( long iStart, long iSize=-1 ) const; | 725 | String getSubStrIdx( long iStart, long iSize=-1 ) const; |
726 | 726 | ||
727 | String getSubStr( const_iterator iBegin, | 727 | String getSubStr( const_iterator iBegin, |
728 | const_iterator iEnd=String::const_iterator() ) const; | 728 | const_iterator iEnd=String::const_iterator() ) const; |
729 | 729 | ||
730 | Bu::List<String> split( const char c ) const; | 730 | Bu::List<String> split( const char c ) const; |
731 | 731 | ||
732 | /** | 732 | /** |
733 | * Plus equals operator for String. | 733 | * Plus equals operator for String. |
734 | *@param pData (const char *) The data to append to your String. | 734 | *@param pData (const char *) The data to append to your String. |
735 | */ | 735 | */ |
736 | String &operator+=( const char *pData ); | 736 | String &operator+=( const char *pData ); |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * Plus equals operator for String. | 739 | * Plus equals operator for String. |
740 | *@param rSrc (const String &) The String to append to your String. | 740 | *@param rSrc (const String &) The String to append to your String. |
741 | */ | 741 | */ |
742 | String &operator+=( const String &rSrc ); | 742 | String &operator+=( const String &rSrc ); |
743 | 743 | ||
744 | String &operator+=( const String::const_iterator &i ); | 744 | String &operator+=( const String::const_iterator &i ); |
745 | 745 | ||
746 | /** | 746 | /** |
747 | * Plus equals operator for String. | 747 | * Plus equals operator for String. |
748 | *@param cData (const char) The character to append to your String. | 748 | *@param cData (const char) The character to append to your String. |
749 | */ | 749 | */ |
750 | String &operator+=( const char cData ); | 750 | String &operator+=( const char cData ); |
751 | 751 | ||
752 | /** | 752 | /** |
753 | * Assignment operator. | 753 | * Assignment operator. |
754 | *@param pData (const char *) The character array to append to your | 754 | *@param pData (const char *) The character array to append to your |
755 | * String. | 755 | * String. |
756 | */ | 756 | */ |
757 | String &operator=( const char *pData ); | 757 | String &operator=( const char *pData ); |
758 | 758 | ||
759 | String operator+( const String &rRight ) const; | 759 | String operator+( const String &rRight ) const; |
760 | 760 | ||
761 | String operator+( const char *pRight ) const; | 761 | String operator+( const char *pRight ) const; |
762 | 762 | ||
763 | String operator+( char *pRight ) const; | 763 | String operator+( char *pRight ) const; |
764 | 764 | ||
765 | /** | 765 | /** |
766 | * Reset your String to this character array. | 766 | * Reset your String to this character array. |
767 | *@param pData (const char *) The character array to set your String to. | 767 | *@param pData (const char *) The character array to set your String to. |
768 | */ | 768 | */ |
769 | void set( const char *pData ); | 769 | void set( const char *pData ); |
770 | 770 | ||
771 | /** | 771 | /** |
772 | * Reset your String to this character array. | 772 | * Reset your String to this character array. |
773 | *@param pData (const char *) The character array to set your String to. | 773 | *@param pData (const char *) The character array to set your String to. |
774 | *@param nSize (long) The length of the inputted character array. | 774 | *@param nSize (long) The length of the inputted character array. |
775 | */ | 775 | */ |
776 | void set( const char *pData, long nSize ); | 776 | void set( const char *pData, long nSize ); |
777 | 777 | ||
778 | void set( const char *pData, long nStart, long nSize ); | 778 | void set( const char *pData, long nStart, long nSize ); |
779 | 779 | ||
780 | void set( const String &rData ); | 780 | void set( const String &rData ); |
781 | 781 | ||
782 | void set( const String &rData, long nSize ); | 782 | void set( const String &rData, long nSize ); |
783 | 783 | ||
784 | void set( const String &rData, long nStart, long nSize ); | 784 | void set( const String &rData, long nStart, long nSize ); |
785 | 785 | ||
786 | void set( const_iterator s ); | 786 | void set( const_iterator s ); |
787 | 787 | ||
788 | void set( const_iterator s, const_iterator e ); | 788 | void set( const_iterator s, const_iterator e ); |
789 | 789 | ||
790 | /** | 790 | /** |
791 | * Resize the string, possibly to make room for a copy. At the moment | 791 | * Resize the string, possibly to make room for a copy. At the moment |
792 | * this operation *is* destructive. What was in the string will in no | 792 | * this operation *is* destructive. What was in the string will in no |
793 | * way be preserved. This is, however, very fast. If you want to | 793 | * way be preserved. This is, however, very fast. If you want to |
794 | * keep your data check out resize. | 794 | * keep your data check out resize. |
795 | *@param iSize the new size in bytes. The string is guranteed to have | 795 | *@param iSize the new size in bytes. The string is guranteed to have |
796 | * at least this much contiguous space available when done. | 796 | * at least this much contiguous space available when done. |
797 | */ | 797 | */ |
798 | void setSize( long iSize ); | 798 | void setSize( long iSize ); |
799 | 799 | ||
800 | /** | 800 | /** |
801 | * Equals comparison operator. | 801 | * Equals comparison operator. |
802 | *@param pData (const char *) The character array to compare your String | 802 | *@param pData (const char *) The character array to compare your String |
803 | * to. | 803 | * to. |
804 | */ | 804 | */ |
805 | bool operator==( const char *pData ) const; | 805 | bool operator==( const char *pData ) const; |
806 | 806 | ||
807 | /** | 807 | /** |
808 | * Equals comparison operator. | 808 | * Equals comparison operator. |
809 | *@param pData (const String &) The String to compare your String to. | 809 | *@param pData (const String &) The String to compare your String to. |
810 | */ | 810 | */ |
811 | bool operator==( const String &pData ) const; | 811 | bool operator==( const String &pData ) const; |
812 | 812 | ||
813 | /** | 813 | /** |
814 | * Not equals comparison operator. | 814 | * Not equals comparison operator. |
815 | *@param pData (const char *) The character array to compare your String | 815 | *@param pData (const char *) The character array to compare your String |
816 | * to. | 816 | * to. |
817 | */ | 817 | */ |
818 | bool operator!=(const char *pData ) const; | 818 | bool operator!=(const char *pData ) const; |
819 | 819 | ||
820 | /** | 820 | /** |
821 | * Not equals comparison operator. | 821 | * Not equals comparison operator. |
822 | *@param pData (const String &) The String to compare your String to. | 822 | *@param pData (const String &) The String to compare your String to. |
823 | */ | 823 | */ |
824 | bool operator!=(const String &pData ) const; | 824 | bool operator!=(const String &pData ) const; |
825 | 825 | ||
826 | bool operator<(const String &pData ) const; | 826 | bool operator<(const String &pData ) const; |
827 | 827 | ||
828 | bool operator<=(const String &pData ) const; | 828 | bool operator<=(const String &pData ) const; |
829 | 829 | ||
830 | bool operator>(const String &pData ) const; | 830 | bool operator>(const String &pData ) const; |
831 | 831 | ||
832 | bool operator>=(const String &pData ) const; | 832 | bool operator>=(const String &pData ) const; |
833 | 833 | ||
834 | /** | 834 | /** |
835 | * Indexing operator | 835 | * Indexing operator |
836 | *@param nIndex (long) The index of the character you want. | 836 | *@param nIndex (long) The index of the character you want. |
837 | *@returns (char &) The character at position (nIndex). | 837 | *@returns (char &) The character at position (nIndex). |
838 | */ | 838 | */ |
839 | char &operator[]( long nIndex ); | 839 | char &operator[]( long nIndex ); |
840 | 840 | ||
841 | /** | 841 | /** |
842 | * Const indexing operator | 842 | * Const indexing operator |
843 | *@param nIndex (long) The index of the character you want. | 843 | *@param nIndex (long) The index of the character you want. |
844 | *@returns (const char &) The character at position (nIndex). | 844 | *@returns (const char &) The character at position (nIndex). |
845 | */ | 845 | */ |
846 | const char &operator[]( long nIndex ) const; | 846 | const char &operator[]( long nIndex ) const; |
847 | 847 | ||
848 | bool isSet() const; | 848 | bool isSet() const; |
849 | 849 | ||
850 | bool compareSub( const char *pData, long nIndex, long nLen ) const; | 850 | bool compareSub( const char *pData, long nIndex, long nLen ) const; |
851 | 851 | ||
852 | bool compareSub( const String &rData, long nIndex, long nLen ) const; | 852 | bool compareSub( const String &rData, long nIndex, long nLen ) const; |
853 | 853 | ||
854 | /** | 854 | /** |
855 | * Is the character at index (nIndex) white space? | 855 | * Is the character at index (nIndex) white space? |
856 | *@param nIndex (long) The index of the character you want to check. | 856 | *@param nIndex (long) The index of the character you want to check. |
857 | *@returns (bool) Is it white space? | 857 | *@returns (bool) Is it white space? |
858 | */ | 858 | */ |
859 | bool isWS( long nIndex ) const; | 859 | bool isWS( long nIndex ) const; |
860 | 860 | ||
861 | /** | 861 | /** |
862 | * Is the character at index (nIndex) a letter? | 862 | * Is the character at index (nIndex) a letter? |
863 | *@param nIndex (long) The index of the character you want to check. | 863 | *@param nIndex (long) The index of the character you want to check. |
864 | *@returns (bool) Is it a letter? | 864 | *@returns (bool) Is it a letter? |
865 | */ | 865 | */ |
866 | bool isAlpha( long nIndex ) const; | 866 | bool isAlpha( long nIndex ) const; |
867 | 867 | ||
868 | /** | 868 | /** |
869 | * Convert your alpha characters to lower case. | 869 | * Convert your alpha characters to lower case. |
870 | */ | 870 | */ |
871 | String toLower() const; | 871 | String toLower() const; |
872 | 872 | ||
873 | /** | 873 | /** |
874 | * Convert your alpha characters to upper case. | 874 | * Convert your alpha characters to upper case. |
875 | */ | 875 | */ |
876 | String toUpper() const; | 876 | String toUpper() const; |
877 | 877 | ||
878 | const_iterator find( const char cChar, | 878 | const_iterator find( const char cChar, |
879 | const_iterator iStart=const_iterator() ) const; | 879 | const_iterator iStart=const_iterator() ) const; |
880 | 880 | ||
881 | const_iterator find( const char *sText, int nLen, | 881 | const_iterator find( const char *sText, int nLen, |
882 | const_iterator iStart=const_iterator() ) const; | 882 | const_iterator iStart=const_iterator() ) const; |
883 | 883 | ||
884 | const_iterator find( const String &rStr, | 884 | const_iterator find( const String &rStr, |
885 | const_iterator iStart=const_iterator() ) const; | 885 | const_iterator iStart=const_iterator() ) const; |
886 | 886 | ||
887 | const_iterator find( const String &rStr, int nLen, | 887 | const_iterator find( const String &rStr, int nLen, |
888 | const_iterator iStart=const_iterator() ) const; | 888 | const_iterator iStart=const_iterator() ) const; |
889 | 889 | ||
890 | iterator find( const char cChar, | 890 | iterator find( const char cChar, |
891 | const_iterator iStart=const_iterator() ); | 891 | const_iterator iStart=const_iterator() ); |
892 | 892 | ||
893 | iterator find( const char *sText, int nLen, | 893 | iterator find( const char *sText, int nLen, |
894 | const_iterator iStart=const_iterator() ); | 894 | const_iterator iStart=const_iterator() ); |
895 | 895 | ||
896 | iterator find( const String &rStr, | 896 | iterator find( const String &rStr, |
897 | const_iterator iStart=const_iterator() ); | 897 | const_iterator iStart=const_iterator() ); |
898 | 898 | ||
899 | iterator find( const String &rStr, int nLen, | 899 | iterator find( const String &rStr, int nLen, |
900 | const_iterator iStart=const_iterator() ); | 900 | const_iterator iStart=const_iterator() ); |
901 | 901 | ||
902 | /** | 902 | /** |
903 | * Find the index of the first occurrance of cChar | 903 | * Find the index of the first occurrance of cChar |
904 | *@param cChar The character to search for. | 904 | *@param cChar The character to search for. |
905 | *@param iStart The position in the string to start searching from. | 905 | *@param iStart The position in the string to start searching from. |
906 | *@returns (long) The index of the first occurrance. -1 for not found. | 906 | *@returns (long) The index of the first occurrance. -1 for not found. |
907 | */ | 907 | */ |
908 | long findIdx( const char cChar, long iStart=0 ) const; | 908 | long findIdx( const char cChar, long iStart=0 ) const; |
909 | 909 | ||
910 | /** | 910 | /** |
911 | * Find the index of the first occurrance of sText | 911 | * Find the index of the first occurrance of sText |
912 | *@param sText The null-terminated string to search for. | 912 | *@param sText The null-terminated string to search for. |
913 | *@param iStart The position in the string to start searching from. | 913 | *@param iStart The position in the string to start searching from. |
914 | *@returns The index of the first occurrance. -1 for not found. | 914 | *@returns The index of the first occurrance. -1 for not found. |
915 | */ | 915 | */ |
916 | long findIdx( const char *sText, long iStart=0 ) const; | 916 | long findIdx( const char *sText, long iStart=0 ) const; |
917 | 917 | ||
918 | /** | 918 | /** |
919 | * Do a reverse search for (sText) | 919 | * Do a reverse search for (sText) |
920 | *@param sText (const char *) The string to search for. | 920 | *@param sText (const char *) The string to search for. |
921 | *@returns (long) The index of the last occurrance. -1 for not found. | 921 | *@returns (long) The index of the last occurrance. -1 for not found. |
922 | */ | 922 | */ |
923 | long rfindIdx( const char *sText ) const; | 923 | long rfindIdx( const char *sText ) const; |
924 | 924 | ||
925 | /** | 925 | /** |
926 | * Remove nAmnt bytes from the front of the string. This function | 926 | * Remove nAmnt bytes from the front of the string. This function |
927 | * operates in O(n) time and should be used sparingly. | 927 | * operates in O(n) time and should be used sparingly. |
928 | */ | 928 | */ |
929 | void trimFront( long nAmnt ); | 929 | void trimFront( long nAmnt ); |
930 | 930 | ||
931 | void trimBack( long iAmnt ); | 931 | void trimBack( long iAmnt ); |
932 | 932 | ||
933 | Bu::String trimWhitespace() const; | 933 | Bu::String trimWhitespace() const; |
934 | 934 | ||
935 | iterator begin(); | 935 | iterator begin(); |
936 | 936 | ||
937 | const_iterator begin() const; | 937 | const_iterator begin() const; |
938 | 938 | ||
939 | iterator end(); | 939 | iterator end(); |
940 | 940 | ||
941 | const_iterator end() const; | 941 | const_iterator end() const; |
942 | 942 | ||
943 | bool isEmpty() const; | 943 | bool isEmpty() const; |
944 | 944 | ||
945 | private: | 945 | private: |
946 | void flatten() const; | 946 | void flatten() const; |
947 | bool isFlat() const; | 947 | bool isFlat() const; |
948 | 948 | ||
949 | public: | 949 | public: |
950 | class FormatProxyEndAction | 950 | class FormatProxyEndAction |
951 | { | 951 | { |
952 | public: | 952 | public: |
953 | virtual ~FormatProxyEndAction() { }; | 953 | virtual ~FormatProxyEndAction() { }; |
954 | virtual void operator()( const Bu::String &sFinal )=0; | 954 | virtual void operator()( const Bu::String &sFinal )=0; |
955 | }; | 955 | }; |
956 | 956 | ||
957 | class FormatProxy | 957 | class FormatProxy |
958 | { | 958 | { |
959 | friend class Bu::String; | 959 | friend class Bu::String; |
960 | private: | 960 | private: |
961 | FormatProxy( const String &rFmt, FormatProxyEndAction *pAct=NULL ); | 961 | FormatProxy( const String &rFmt, FormatProxyEndAction *pAct=NULL ); |
962 | 962 | ||
963 | public: | 963 | public: |
964 | virtual ~FormatProxy(); | 964 | virtual ~FormatProxy(); |
965 | template<typename T> | 965 | template<typename T> |
966 | FormatProxy &arg( const T &x ) | 966 | FormatProxy &arg( const T &x ) |
967 | { | 967 | { |
968 | lArgs.append( Arg( x ) ); | 968 | lArgs.append( Arg( x ) ); |
969 | 969 | ||
970 | return *this; | 970 | return *this; |
971 | } | 971 | } |
972 | 972 | ||
973 | template<typename T> | 973 | template<typename T> |
974 | FormatProxy &arg( const T &x, const Bu::Fmt &f ) | 974 | FormatProxy &arg( const T &x, const Bu::Fmt &f ) |
975 | { | 975 | { |
976 | lArgs.append( Arg( x, f ) ); | 976 | lArgs.append( Arg( x, f ) ); |
977 | 977 | ||
978 | return *this; | 978 | return *this; |
979 | } | 979 | } |
980 | 980 | ||
981 | String end() const; | 981 | String end() const; |
982 | operator String() const { return end(); } | 982 | operator String() const { return end(); } |
983 | 983 | ||
984 | private: | 984 | private: |
985 | const String &rFmt; | 985 | const String &rFmt; |
986 | class Arg | 986 | class Arg |
987 | { | 987 | { |
988 | public: | 988 | public: |
989 | template<typename T> | 989 | template<typename T> |
990 | Arg( const T &v ) : | 990 | Arg( const T &v ) : |
991 | value( v ) | 991 | value( v ) |
992 | { | 992 | { |
993 | } | 993 | } |
994 | 994 | ||
995 | template<typename T> | 995 | template<typename T> |
996 | Arg( const T &v, const Bu::Fmt &f ) : | 996 | Arg( const T &v, const Bu::Fmt &f ) : |
997 | value( v ), | 997 | value( v ), |
998 | format( f ) | 998 | format( f ) |
999 | { | 999 | { |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | Bu::Variant value; | 1002 | Bu::Variant value; |
1003 | Bu::Fmt format; | 1003 | Bu::Fmt format; |
1004 | }; | 1004 | }; |
1005 | typedef Bu::List<Arg> ArgList; | 1005 | typedef Bu::List<Arg> ArgList; |
1006 | ArgList lArgs; | 1006 | ArgList lArgs; |
1007 | FormatProxyEndAction *pAct; | 1007 | FormatProxyEndAction *pAct; |
1008 | mutable bool bOpen; | 1008 | mutable bool bOpen; |
1009 | }; | 1009 | }; |
1010 | 1010 | ||
1011 | public: | 1011 | public: |
1012 | template<typename ArgType> | 1012 | template<typename ArgType> |
1013 | FormatProxy arg( const ArgType &x ) const | 1013 | FormatProxy arg( const ArgType &x ) const |
1014 | { | 1014 | { |
1015 | return FormatProxy( *this ).arg( x ); | 1015 | return FormatProxy( *this ).arg( x ); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | template<typename ArgType> | 1018 | template<typename ArgType> |
1019 | FormatProxy arg( const ArgType &x, const Bu::Fmt &f ) const | 1019 | FormatProxy arg( const ArgType &x, const Bu::Fmt &f ) const |
1020 | { | 1020 | { |
1021 | return FormatProxy( *this ).arg( x, f ); | 1021 | return FormatProxy( *this ).arg( x, f ); |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | FormatProxy format() const | 1024 | FormatProxy format() const |
1025 | { | 1025 | { |
1026 | return FormatProxy( *this ); | 1026 | return FormatProxy( *this ); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | FormatProxy format( FormatProxyEndAction *pEndAction ) const | 1029 | FormatProxy format( FormatProxyEndAction *pEndAction ) const |
1030 | { | 1030 | { |
1031 | return FormatProxy( *this, pEndAction ); | 1031 | return FormatProxy( *this, pEndAction ); |
1032 | } | 1032 | } |
1033 | }; | 1033 | }; |
1034 | 1034 | ||
1035 | template<class T> String operator+( const T *pLeft, const String &rRight ) | 1035 | template<class T> String operator+( const T *pLeft, const String &rRight ) |
1036 | { | 1036 | { |
1037 | Bu::String ret( pLeft ); | 1037 | Bu::String ret( pLeft ); |
1038 | ret.append( rRight ); | 1038 | ret.append( rRight ); |
1039 | return ret; | 1039 | return ret; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | ArchiveBase &operator<<( ArchiveBase &ar, const String &s ); | 1042 | ArchiveBase &operator<<( ArchiveBase &ar, const String &s ); |
1043 | ArchiveBase &operator>>( ArchiveBase &ar, String &s ); | 1043 | ArchiveBase &operator>>( ArchiveBase &ar, String &s ); |
1044 | 1044 | ||
1045 | template<typename T> | 1045 | template<typename T> |
1046 | uint32_t __calcHashCode( const T &k ); | 1046 | uint32_t __calcHashCode( const T &k ); |
1047 | 1047 | ||
1048 | template<typename T> | 1048 | template<typename T> |
1049 | bool __cmpHashKeys( const T &a, const T &b ); | 1049 | bool __cmpHashKeys( const T &a, const T &b ); |
1050 | 1050 | ||
1051 | template<> uint32_t __calcHashCode<String>( const String &k ); | 1051 | template<> uint32_t __calcHashCode<String>( const String &k ); |
1052 | template<> bool __cmpHashKeys<String>( | 1052 | template<> bool __cmpHashKeys<String>( |
1053 | const String &a, const String &b ); | 1053 | const String &a, const String &b ); |
1054 | 1054 | ||
1055 | template<typename t> void __tracer_format( const t &v ); | 1055 | template<typename t> void __tracer_format( const t &v ); |
1056 | template<> void __tracer_format<String>( const String &v ); | 1056 | template<> void __tracer_format<String>( const String &v ); |
1057 | 1057 | ||
1058 | bool &operator<<( bool &dst, const String &sIn ); | 1058 | bool &operator<<( bool &dst, const String &sIn ); |
1059 | uint8_t &operator<<( uint8_t &dst, const String &sIn ); | 1059 | uint8_t &operator<<( uint8_t &dst, const String &sIn ); |
1060 | int8_t &operator<<( int8_t &dst, const String &sIn ); | 1060 | int8_t &operator<<( int8_t &dst, const String &sIn ); |
1061 | char &operator<<( char &dst, const String &sIn ); | 1061 | char &operator<<( char &dst, const String &sIn ); |
1062 | uint16_t &operator<<( uint16_t &dst, const String &sIn ); | 1062 | uint16_t &operator<<( uint16_t &dst, const String &sIn ); |
1063 | int16_t &operator<<( int16_t &dst, const String &sIn ); | 1063 | int16_t &operator<<( int16_t &dst, const String &sIn ); |
1064 | uint32_t &operator<<( uint32_t &dst, const String &sIn ); | 1064 | uint32_t &operator<<( uint32_t &dst, const String &sIn ); |
1065 | int32_t &operator<<( int32_t &dst, const String &sIn ); | 1065 | int32_t &operator<<( int32_t &dst, const String &sIn ); |
1066 | uint64_t &operator<<( uint64_t &dst, const String &sIn ); | 1066 | uint64_t &operator<<( uint64_t &dst, const String &sIn ); |
1067 | int64_t &operator<<( int64_t &dst, const String &sIn ); | 1067 | int64_t &operator<<( int64_t &dst, const String &sIn ); |
1068 | float &operator<<( float &dst, const String &sIn ); | 1068 | float &operator<<( float &dst, const String &sIn ); |
1069 | double &operator<<( double &dst, const String &sIn ); | 1069 | double &operator<<( double &dst, const String &sIn ); |
1070 | long double &operator<<( long double &dst, const String &sIn ); | 1070 | long double &operator<<( long double &dst, const String &sIn ); |
1071 | Bu::String &operator<<( Bu::String &dst, const String &sIn ); | 1071 | Bu::String &operator<<( Bu::String &dst, const String &sIn ); |
1072 | 1072 | ||
1073 | typedef Bu::List<String> StringList; | 1073 | typedef Bu::List<String> StringList; |
1074 | }; | 1074 | }; |
1075 | 1075 | ||
1076 | #endif | 1076 | #endif |
diff --git a/src/stable/substream.cpp b/src/stable/substream.cpp index 7e3729b..c55dc04 100644 --- a/src/stable/substream.cpp +++ b/src/stable/substream.cpp | |||
@@ -8,12 +8,12 @@ | |||
8 | #include "bu/substream.h" | 8 | #include "bu/substream.h" |
9 | 9 | ||
10 | Bu::SubStream::SubStream( Bu::Stream &rNext, Bu::size iSize ) : | 10 | Bu::SubStream::SubStream( Bu::Stream &rNext, Bu::size iSize ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | iStart( 0 ), | 12 | iStart( 0 ), |
13 | iPos( 0 ), | 13 | iPos( 0 ), |
14 | iSize( iSize ) | 14 | iSize( iSize ) |
15 | { | 15 | { |
16 | iStart = rNext.tell(); | 16 | iStart = rNext.tell(); |
17 | } | 17 | } |
18 | 18 | ||
19 | Bu::SubStream::~SubStream() | 19 | Bu::SubStream::~SubStream() |
@@ -22,88 +22,88 @@ Bu::SubStream::~SubStream() | |||
22 | 22 | ||
23 | Bu::size Bu::SubStream::read( void *pBuf, Bu::size nBytes ) | 23 | Bu::size Bu::SubStream::read( void *pBuf, Bu::size nBytes ) |
24 | { | 24 | { |
25 | if( (Bu::size)nBytes > iSize-iPos ) | 25 | if( (Bu::size)nBytes > iSize-iPos ) |
26 | nBytes = iSize-iPos; | 26 | nBytes = iSize-iPos; |
27 | nBytes = rNext.read( pBuf, nBytes ); | 27 | nBytes = rNext.read( pBuf, nBytes ); |
28 | iPos += nBytes; | 28 | iPos += nBytes; |
29 | return nBytes; | 29 | return nBytes; |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::size Bu::SubStream::write( const void *pBuf, Bu::size nBytes ) | 32 | Bu::size Bu::SubStream::write( const void *pBuf, Bu::size nBytes ) |
33 | { | 33 | { |
34 | if( (Bu::size)nBytes > iSize-iPos ) | 34 | if( (Bu::size)nBytes > iSize-iPos ) |
35 | nBytes = iSize-iPos; | 35 | nBytes = iSize-iPos; |
36 | nBytes = rNext.write( pBuf, nBytes ); | 36 | nBytes = rNext.write( pBuf, nBytes ); |
37 | iPos += nBytes; | 37 | iPos += nBytes; |
38 | return nBytes; | 38 | return nBytes; |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::SubStream::start() | 41 | void Bu::SubStream::start() |
42 | { | 42 | { |
43 | // doesn't mean anything... | 43 | // doesn't mean anything... |
44 | } | 44 | } |
45 | 45 | ||
46 | Bu::size Bu::SubStream::stop() | 46 | Bu::size Bu::SubStream::stop() |
47 | { | 47 | { |
48 | // doesn't mean anything... | 48 | // doesn't mean anything... |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | void Bu::SubStream::close() | 52 | void Bu::SubStream::close() |
53 | { | 53 | { |
54 | // don't do anything? maybe... | 54 | // don't do anything? maybe... |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::size Bu::SubStream::tell() | 57 | Bu::size Bu::SubStream::tell() |
58 | { | 58 | { |
59 | return iPos; | 59 | return iPos; |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::SubStream::seek( Bu::size offset ) | 62 | void Bu::SubStream::seek( Bu::size offset ) |
63 | { | 63 | { |
64 | if( iPos+offset < 0 ) | 64 | if( iPos+offset < 0 ) |
65 | offset = -iPos; | 65 | offset = -iPos; |
66 | else if( iPos+offset > iSize ) | 66 | else if( iPos+offset > iSize ) |
67 | offset = iSize-iPos; | 67 | offset = iSize-iPos; |
68 | rNext.seek( offset ); | 68 | rNext.seek( offset ); |
69 | iPos += offset; | 69 | iPos += offset; |
70 | } | 70 | } |
71 | 71 | ||
72 | void Bu::SubStream::setPos( Bu::size pos ) | 72 | void Bu::SubStream::setPos( Bu::size pos ) |
73 | { | 73 | { |
74 | if( pos < 0 ) | 74 | if( pos < 0 ) |
75 | pos = 0; | 75 | pos = 0; |
76 | else if( pos > iSize ) | 76 | else if( pos > iSize ) |
77 | pos = iSize; | 77 | pos = iSize; |
78 | iPos = pos; | 78 | iPos = pos; |
79 | pos += iStart; | 79 | pos += iStart; |
80 | rNext.setPos( pos ); | 80 | rNext.setPos( pos ); |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::SubStream::setPosEnd( Bu::size pos ) | 83 | void Bu::SubStream::setPosEnd( Bu::size pos ) |
84 | { | 84 | { |
85 | if( iSize-pos < 0 ) | 85 | if( iSize-pos < 0 ) |
86 | pos = 0; | 86 | pos = 0; |
87 | else if( iSize-pos > iSize ) | 87 | else if( iSize-pos > iSize ) |
88 | pos = iSize; | 88 | pos = iSize; |
89 | else | 89 | else |
90 | pos = iSize-pos; | 90 | pos = iSize-pos; |
91 | iPos = pos; | 91 | iPos = pos; |
92 | rNext.setPos( iStart+pos ); | 92 | rNext.setPos( iStart+pos ); |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::SubStream::isEos() | 95 | bool Bu::SubStream::isEos() |
96 | { | 96 | { |
97 | return rNext.isEos() || iPos == iSize; | 97 | return rNext.isEos() || iPos == iSize; |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::SubStream::canRead() | 100 | bool Bu::SubStream::canRead() |
101 | { | 101 | { |
102 | return rNext.canRead() && (iPos < iSize); | 102 | return rNext.canRead() && (iPos < iSize); |
103 | } | 103 | } |
104 | 104 | ||
105 | bool Bu::SubStream::canWrite() | 105 | bool Bu::SubStream::canWrite() |
106 | { | 106 | { |
107 | return rNext.canWrite() && (iPos < iSize); | 107 | return rNext.canWrite() && (iPos < iSize); |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/src/stable/substream.h b/src/stable/substream.h index 5905043..f79ed0b 100644 --- a/src/stable/substream.h +++ b/src/stable/substream.h | |||
@@ -12,52 +12,52 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Creates a sub-stream of a given stream. This allows you to read and | 16 | * Creates a sub-stream of a given stream. This allows you to read and |
17 | * write safely to a section of another stream, keeping all data within | 17 | * write safely to a section of another stream, keeping all data within |
18 | * the given bounds. The substream acts exactly like a top level stream | 18 | * the given bounds. The substream acts exactly like a top level stream |
19 | * when you reach the bounds of either the containing stream or the | 19 | * when you reach the bounds of either the containing stream or the |
20 | * artificial bounds of the substream, except that unlike many stream types, | 20 | * artificial bounds of the substream, except that unlike many stream types, |
21 | * when writing you cannot move beyond the bounds of the substream. Reads, | 21 | * when writing you cannot move beyond the bounds of the substream. Reads, |
22 | * on the other hand, work exactly the same way, returning less data than | 22 | * on the other hand, work exactly the same way, returning less data than |
23 | * requested when the end of the stream is reached. | 23 | * requested when the end of the stream is reached. |
24 | * | 24 | * |
25 | * The substream always begins at the current position in the base stream, | 25 | * The substream always begins at the current position in the base stream, |
26 | * if you would like to skip some data first, simply seek. | 26 | * if you would like to skip some data first, simply seek. |
27 | * | 27 | * |
28 | * The substream class is safe to use with all blocking and non-blocking | 28 | * The substream class is safe to use with all blocking and non-blocking |
29 | * base streams, including sockets, however it can have unpredictable | 29 | * base streams, including sockets, however it can have unpredictable |
30 | * results when used on a buffering stream that may read more data than | 30 | * results when used on a buffering stream that may read more data than |
31 | * requested in order to complete a request such as the buffer or bzip2 | 31 | * requested in order to complete a request such as the buffer or bzip2 |
32 | * filters. | 32 | * filters. |
33 | */ | 33 | */ |
34 | class SubStream : public Bu::Filter | 34 | class SubStream : public Bu::Filter |
35 | { | 35 | { |
36 | public: | 36 | public: |
37 | SubStream( Bu::Stream &rNext, Bu::size iSize ); | 37 | SubStream( Bu::Stream &rNext, Bu::size iSize ); |
38 | virtual ~SubStream(); | 38 | virtual ~SubStream(); |
39 | 39 | ||
40 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 40 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
41 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 41 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
42 | using Bu::Stream::write; | 42 | using Bu::Stream::write; |
43 | 43 | ||
44 | virtual void start(); | 44 | virtual void start(); |
45 | virtual Bu::size stop(); | 45 | virtual Bu::size stop(); |
46 | virtual void close(); | 46 | virtual void close(); |
47 | virtual Bu::size tell(); | 47 | virtual Bu::size tell(); |
48 | virtual void seek( Bu::size offset ); | 48 | virtual void seek( Bu::size offset ); |
49 | virtual void setPos( Bu::size pos ); | 49 | virtual void setPos( Bu::size pos ); |
50 | virtual void setPosEnd( Bu::size pos ); | 50 | virtual void setPosEnd( Bu::size pos ); |
51 | virtual bool isEos(); | 51 | virtual bool isEos(); |
52 | 52 | ||
53 | virtual bool canRead(); | 53 | virtual bool canRead(); |
54 | virtual bool canWrite(); | 54 | virtual bool canWrite(); |
55 | 55 | ||
56 | protected: | 56 | protected: |
57 | Bu::size iStart; | 57 | Bu::size iStart; |
58 | Bu::size iPos; | 58 | Bu::size iPos; |
59 | Bu::size iSize; | 59 | Bu::size iSize; |
60 | }; | 60 | }; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #endif | 63 | #endif |
diff --git a/src/stable/synchroatom.h b/src/stable/synchroatom.h index 2822b20..1d996b6 100644 --- a/src/stable/synchroatom.h +++ b/src/stable/synchroatom.h | |||
@@ -14,50 +14,50 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * A thread-safe wrapper class. | 18 | * A thread-safe wrapper class. |
19 | *@ingroup Threading | 19 | *@ingroup Threading |
20 | */ | 20 | */ |
21 | template <class T> | 21 | template <class T> |
22 | class SynchroAtom | 22 | class SynchroAtom |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | /** | 25 | /** |
26 | * Construct an empty queue. | 26 | * Construct an empty queue. |
27 | */ | 27 | */ |
28 | SynchroAtom() | 28 | SynchroAtom() |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | SynchroAtom( const T &src ) : | 32 | SynchroAtom( const T &src ) : |
33 | data( src ) | 33 | data( src ) |
34 | { | 34 | { |
35 | } | 35 | } |
36 | 36 | ||
37 | ~SynchroAtom() | 37 | ~SynchroAtom() |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | T get() | 41 | T get() |
42 | { | 42 | { |
43 | mOperate.lock(); | 43 | mOperate.lock(); |
44 | T ret = data; | 44 | T ret = data; |
45 | mOperate.unlock(); | 45 | mOperate.unlock(); |
46 | return ret; | 46 | return ret; |
47 | } | 47 | } |
48 | 48 | ||
49 | void set( const T &val ) | 49 | void set( const T &val ) |
50 | { | 50 | { |
51 | mOperate.lock(); | 51 | mOperate.lock(); |
52 | data = val; | 52 | data = val; |
53 | mOperate.unlock(); | 53 | mOperate.unlock(); |
54 | } | 54 | } |
55 | 55 | ||
56 | private: | 56 | private: |
57 | T data; | 57 | T data; |
58 | 58 | ||
59 | Mutex mOperate; /**< The master mutex, used on all operations. */ | 59 | Mutex mOperate; /**< The master mutex, used on all operations. */ |
60 | }; | 60 | }; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #endif | 63 | #endif |
diff --git a/src/stable/synchrocounter.h b/src/stable/synchrocounter.h index ef86445..17de890 100644 --- a/src/stable/synchrocounter.h +++ b/src/stable/synchrocounter.h | |||
@@ -12,38 +12,38 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A simple thread-safe counter class. This is handy for assigning unique | 16 | * A simple thread-safe counter class. This is handy for assigning unique |
17 | * IDs to objects that are being created in different threads. | 17 | * IDs to objects that are being created in different threads. |
18 | *@ingroup Threading Containers | 18 | *@ingroup Threading Containers |
19 | */ | 19 | */ |
20 | template <class T> | 20 | template <class T> |
21 | class SynchroCounter | 21 | class SynchroCounter |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | SynchroCounter() : | 24 | SynchroCounter() : |
25 | tCounter( 0 ) | 25 | tCounter( 0 ) |
26 | { | 26 | { |
27 | } | 27 | } |
28 | 28 | ||
29 | virtual ~SynchroCounter() | 29 | virtual ~SynchroCounter() |
30 | { | 30 | { |
31 | } | 31 | } |
32 | 32 | ||
33 | T next() | 33 | T next() |
34 | { | 34 | { |
35 | mOperate.lock(); | 35 | mOperate.lock(); |
36 | T tRet = tCounter; | 36 | T tRet = tCounter; |
37 | tCounter++; | 37 | tCounter++; |
38 | mOperate.unlock(); | 38 | mOperate.unlock(); |
39 | 39 | ||
40 | return tRet; | 40 | return tRet; |
41 | } | 41 | } |
42 | 42 | ||
43 | private: | 43 | private: |
44 | T tCounter; /**< The counter itself. */ | 44 | T tCounter; /**< The counter itself. */ |
45 | Mutex mOperate; /**< The master mutex, used on all operations. */ | 45 | Mutex mOperate; /**< The master mutex, used on all operations. */ |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/synchroheap.h b/src/stable/synchroheap.h index 9448625..f5216bf 100644 --- a/src/stable/synchroheap.h +++ b/src/stable/synchroheap.h | |||
@@ -14,137 +14,137 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | template<typename item, typename cmpfunc=__basicLTCmp<item>, | 17 | template<typename item, typename cmpfunc=__basicLTCmp<item>, |
18 | typename itemalloc=std::allocator<item> > | 18 | typename itemalloc=std::allocator<item> > |
19 | class SynchroHeap | 19 | class SynchroHeap |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | SynchroHeap() | 22 | SynchroHeap() |
23 | { | 23 | { |
24 | } | 24 | } |
25 | 25 | ||
26 | virtual ~SynchroHeap() | 26 | virtual ~SynchroHeap() |
27 | { | 27 | { |
28 | } | 28 | } |
29 | 29 | ||
30 | void enqueue( item i ) | 30 | void enqueue( item i ) |
31 | { | 31 | { |
32 | imData.lock(); | 32 | imData.lock(); |
33 | hData.enqueue( i ); | 33 | hData.enqueue( i ); |
34 | icBlock.signal(); | 34 | icBlock.signal(); |
35 | imData.unlock(); | 35 | imData.unlock(); |
36 | } | 36 | } |
37 | 37 | ||
38 | item dequeue( bool bBlock=false ) | 38 | item dequeue( bool bBlock=false ) |
39 | { | 39 | { |
40 | imData.lock(); | 40 | imData.lock(); |
41 | if( hData.isEmpty() ) | 41 | if( hData.isEmpty() ) |
42 | { | 42 | { |
43 | imData.unlock(); | 43 | imData.unlock(); |
44 | 44 | ||
45 | if( bBlock ) | 45 | if( bBlock ) |
46 | { | 46 | { |
47 | icBlock.lock(); | 47 | icBlock.lock(); |
48 | 48 | ||
49 | while( hData.isEmpty() ) | 49 | while( hData.isEmpty() ) |
50 | icBlock.wait(); | 50 | icBlock.wait(); |
51 | 51 | ||
52 | imData.lock(); | 52 | imData.lock(); |
53 | try | 53 | try |
54 | { | 54 | { |
55 | item iRet = hData.dequeue(); | 55 | item iRet = hData.dequeue(); |
56 | imData.unlock(); | 56 | imData.unlock(); |
57 | icBlock.unlock(); | 57 | icBlock.unlock(); |
58 | return iRet; | 58 | return iRet; |
59 | } | 59 | } |
60 | catch(...) | 60 | catch(...) |
61 | { | 61 | { |
62 | imData.unlock(); | 62 | imData.unlock(); |
63 | icBlock.unlock(); | 63 | icBlock.unlock(); |
64 | throw; | 64 | throw; |
65 | } | 65 | } |
66 | } | 66 | } |
67 | throw HeapException("Heap empty."); | 67 | throw HeapException("Heap empty."); |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | try | 71 | try |
72 | { | 72 | { |
73 | item iRet = hData.dequeue(); | 73 | item iRet = hData.dequeue(); |
74 | imData.unlock(); | 74 | imData.unlock(); |
75 | return iRet; | 75 | return iRet; |
76 | } | 76 | } |
77 | catch(...) | 77 | catch(...) |
78 | { | 78 | { |
79 | imData.unlock(); | 79 | imData.unlock(); |
80 | throw; | 80 | throw; |
81 | } | 81 | } |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | item dequeue( int iSec, int iUSec ) | 85 | item dequeue( int iSec, int iUSec ) |
86 | { | 86 | { |
87 | imData.lock(); | 87 | imData.lock(); |
88 | if( hData.isEmpty() ) | 88 | if( hData.isEmpty() ) |
89 | { | 89 | { |
90 | imData.unlock(); | 90 | imData.unlock(); |
91 | 91 | ||
92 | icBlock.lock(); | 92 | icBlock.lock(); |
93 | 93 | ||
94 | icBlock.wait( iSec, iUSec ); | 94 | icBlock.wait( iSec, iUSec ); |
95 | 95 | ||
96 | imData.lock(); | 96 | imData.lock(); |
97 | try | 97 | try |
98 | { | 98 | { |
99 | item iRet = hData.dequeue(); | 99 | item iRet = hData.dequeue(); |
100 | imData.unlock(); | 100 | imData.unlock(); |
101 | icBlock.unlock(); | 101 | icBlock.unlock(); |
102 | return iRet; | 102 | return iRet; |
103 | } | 103 | } |
104 | catch(...) | 104 | catch(...) |
105 | { | 105 | { |
106 | imData.unlock(); | 106 | imData.unlock(); |
107 | icBlock.unlock(); | 107 | icBlock.unlock(); |
108 | throw; | 108 | throw; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | else | 111 | else |
112 | { | 112 | { |
113 | try | 113 | try |
114 | { | 114 | { |
115 | item iRet = hData.dequeue(); | 115 | item iRet = hData.dequeue(); |
116 | imData.unlock(); | 116 | imData.unlock(); |
117 | return iRet; | 117 | return iRet; |
118 | } | 118 | } |
119 | catch(...) | 119 | catch(...) |
120 | { | 120 | { |
121 | imData.unlock(); | 121 | imData.unlock(); |
122 | throw; | 122 | throw; |
123 | } | 123 | } |
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | bool isEmpty() | 127 | bool isEmpty() |
128 | { | 128 | { |
129 | imData.lock(); | 129 | imData.lock(); |
130 | bool bRet = hData.isEmpty(); | 130 | bool bRet = hData.isEmpty(); |
131 | imData.unlock(); | 131 | imData.unlock(); |
132 | return bRet; | 132 | return bRet; |
133 | } | 133 | } |
134 | 134 | ||
135 | int getSize() | 135 | int getSize() |
136 | { | 136 | { |
137 | imData.lock(); | 137 | imData.lock(); |
138 | int iRet = hData.getSize(); | 138 | int iRet = hData.getSize(); |
139 | imData.unlock(); | 139 | imData.unlock(); |
140 | return iRet; | 140 | return iRet; |
141 | } | 141 | } |
142 | 142 | ||
143 | private: | 143 | private: |
144 | Heap< item, cmpfunc, itemalloc > hData; | 144 | Heap< item, cmpfunc, itemalloc > hData; |
145 | Mutex imData; | 145 | Mutex imData; |
146 | Condition icBlock; | 146 | Condition icBlock; |
147 | }; | 147 | }; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | #endif | 150 | #endif |
diff --git a/src/stable/synchroqueue.h b/src/stable/synchroqueue.h index 1c16e15..8dbedba 100644 --- a/src/stable/synchroqueue.h +++ b/src/stable/synchroqueue.h | |||
@@ -15,233 +15,233 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * A thread-safe queue class. This class is a very simple queue with some | 19 | * A thread-safe queue class. This class is a very simple queue with some |
20 | * cool extra functionality for use with the Synchro system. The main extra | 20 | * cool extra functionality for use with the Synchro system. The main extra |
21 | * that it provides is the option to either dequeue without blocking, with | 21 | * that it provides is the option to either dequeue without blocking, with |
22 | * infinite blocking, or with timed blocking, which will return a value if | 22 | * infinite blocking, or with timed blocking, which will return a value if |
23 | * something is enqueued within the specified time limit, or NULL if the | 23 | * something is enqueued within the specified time limit, or NULL if the |
24 | * time limit is exceded. | 24 | * time limit is exceded. |
25 | *@ingroup Threading Containers | 25 | *@ingroup Threading Containers |
26 | */ | 26 | */ |
27 | template <class T> | 27 | template <class T> |
28 | class SynchroQueue | 28 | class SynchroQueue |
29 | { | 29 | { |
30 | private: | 30 | private: |
31 | /** | 31 | /** |
32 | * Helper struct. Keeps track of linked-list items for the queue data. | 32 | * Helper struct. Keeps track of linked-list items for the queue data. |
33 | */ | 33 | */ |
34 | typedef struct Item | 34 | typedef struct Item |
35 | { | 35 | { |
36 | T pData; | 36 | T pData; |
37 | Item *pNext; | 37 | Item *pNext; |
38 | } Item; | 38 | } Item; |
39 | 39 | ||
40 | public: | 40 | public: |
41 | /** | 41 | /** |
42 | * Construct an empty queue. | 42 | * Construct an empty queue. |
43 | */ | 43 | */ |
44 | SynchroQueue() : | 44 | SynchroQueue() : |
45 | pStart( NULL ), | 45 | pStart( NULL ), |
46 | pEnd( NULL ), | 46 | pEnd( NULL ), |
47 | nSize( 0 ) | 47 | nSize( 0 ) |
48 | { | 48 | { |
49 | } | 49 | } |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * Destroy the queue. This function will simply free all contained | 52 | * Destroy the queue. This function will simply free all contained |
53 | * structures. If you stored pointers in the queue, this will lose the | 53 | * structures. If you stored pointers in the queue, this will lose the |
54 | * pointers without cleaning up the memory they pointed to. Make sure | 54 | * pointers without cleaning up the memory they pointed to. Make sure |
55 | * you're queue is empty before allowing it to be destroyed! | 55 | * you're queue is empty before allowing it to be destroyed! |
56 | */ | 56 | */ |
57 | ~SynchroQueue() | 57 | ~SynchroQueue() |
58 | { | 58 | { |
59 | cBlock.lock(); | 59 | cBlock.lock(); |
60 | Item *pCur = pStart; | 60 | Item *pCur = pStart; |
61 | while( pCur ) | 61 | while( pCur ) |
62 | { | 62 | { |
63 | Item *pTmp = pCur->pNext; | 63 | Item *pTmp = pCur->pNext; |
64 | delete pCur; | 64 | delete pCur; |
65 | pCur = pTmp; | 65 | pCur = pTmp; |
66 | } | 66 | } |
67 | cBlock.unlock(); | 67 | cBlock.unlock(); |
68 | } | 68 | } |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Enqueue a pieces of data. The new data will go at the end of the | 71 | * Enqueue a pieces of data. The new data will go at the end of the |
72 | * queue, and unless another piece of data is enqueued, will be the | 72 | * queue, and unless another piece of data is enqueued, will be the |
73 | * last piece of data to be dequeued. | 73 | * last piece of data to be dequeued. |
74 | *@param pData The data to enqueue. If this is not a primitive data | 74 | *@param pData The data to enqueue. If this is not a primitive data |
75 | * type it's probably best to use a pointer type. | 75 | * type it's probably best to use a pointer type. |
76 | */ | 76 | */ |
77 | void enqueue( T pData ) | 77 | void enqueue( T pData ) |
78 | { | 78 | { |
79 | cBlock.lock(); | 79 | cBlock.lock(); |
80 | 80 | ||
81 | if( pStart == NULL ) | 81 | if( pStart == NULL ) |
82 | { | 82 | { |
83 | pStart = pEnd = new Item; | 83 | pStart = pEnd = new Item; |
84 | pStart->pData = pData; | 84 | pStart->pData = pData; |
85 | pStart->pNext = NULL; | 85 | pStart->pNext = NULL; |
86 | nSize++; | 86 | nSize++; |
87 | } | 87 | } |
88 | else | 88 | else |
89 | { | 89 | { |
90 | pEnd->pNext = new Item; | 90 | pEnd->pNext = new Item; |
91 | pEnd = pEnd->pNext; | 91 | pEnd = pEnd->pNext; |
92 | pEnd->pData = pData; | 92 | pEnd->pData = pData; |
93 | pEnd->pNext = NULL; | 93 | pEnd->pNext = NULL; |
94 | nSize++; | 94 | nSize++; |
95 | } | 95 | } |
96 | 96 | ||
97 | cBlock.signal(); | 97 | cBlock.signal(); |
98 | 98 | ||
99 | cBlock.unlock(); | 99 | cBlock.unlock(); |
100 | } | 100 | } |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Dequeue the first item from the queue. This function can operate in | 103 | * Dequeue the first item from the queue. This function can operate in |
104 | * two different modes, blocking and non-blocking. In non-blocking | 104 | * two different modes, blocking and non-blocking. In non-blocking |
105 | * mode it will return immediately weather there was data in the queue | 105 | * mode it will return immediately weather there was data in the queue |
106 | * or not. If there was data it will remove it from the queue and | 106 | * or not. If there was data it will remove it from the queue and |
107 | * return it to the caller. | 107 | * return it to the caller. |
108 | * | 108 | * |
109 | * In blocking mode it will block forever wating for data to be | 109 | * In blocking mode it will block forever wating for data to be |
110 | * enqueued. When data finally is enqueued this function will return | 110 | * enqueued. When data finally is enqueued this function will return |
111 | * immediately with the new data. The only way this function should | 111 | * immediately with the new data. The only way this function should |
112 | * ever return a null in blocking mode is if the calling thread was | 112 | * ever return a null in blocking mode is if the calling thread was |
113 | * cancelled. It's probably a good idea to check for NULL return | 113 | * cancelled. It's probably a good idea to check for NULL return |
114 | * values even if you use blocking, just to be on the safe side. | 114 | * values even if you use blocking, just to be on the safe side. |
115 | *@param bBlock Set to true to enable blocking, leave as false to work | 115 | *@param bBlock Set to true to enable blocking, leave as false to work |
116 | * in non-blocking mode. | 116 | * in non-blocking mode. |
117 | *@returns The next piece of data in the queue, or NULL if no data was | 117 | *@returns The next piece of data in the queue, or NULL if no data was |
118 | * in the queue. | 118 | * in the queue. |
119 | */ | 119 | */ |
120 | T dequeue( bool bBlock=false ) | 120 | T dequeue( bool bBlock=false ) |
121 | { | 121 | { |
122 | cBlock.lock(); | 122 | cBlock.lock(); |
123 | if( pStart == NULL ) | 123 | if( pStart == NULL ) |
124 | { | 124 | { |
125 | if( bBlock ) | 125 | if( bBlock ) |
126 | { | 126 | { |
127 | cBlock.wait(); | 127 | cBlock.wait(); |
128 | 128 | ||
129 | if( pStart == NULL ) | 129 | if( pStart == NULL ) |
130 | { | 130 | { |
131 | cBlock.unlock(); | 131 | cBlock.unlock(); |
132 | return NULL; | 132 | return NULL; |
133 | } | 133 | } |
134 | T pTmp = pStart->pData; | 134 | T pTmp = pStart->pData; |
135 | Item *pDel = pStart; | 135 | Item *pDel = pStart; |
136 | pStart = pStart->pNext; | 136 | pStart = pStart->pNext; |
137 | delete pDel; | 137 | delete pDel; |
138 | nSize--; | 138 | nSize--; |
139 | 139 | ||
140 | cBlock.unlock(); | 140 | cBlock.unlock(); |
141 | return pTmp; | 141 | return pTmp; |
142 | 142 | ||
143 | } | 143 | } |
144 | 144 | ||
145 | cBlock.unlock(); | 145 | cBlock.unlock(); |
146 | return NULL; | 146 | return NULL; |
147 | } | 147 | } |
148 | else | 148 | else |
149 | { | 149 | { |
150 | T pTmp = pStart->pData; | 150 | T pTmp = pStart->pData; |
151 | Item *pDel = pStart; | 151 | Item *pDel = pStart; |
152 | pStart = pStart->pNext; | 152 | pStart = pStart->pNext; |
153 | delete pDel; | 153 | delete pDel; |
154 | nSize--; | 154 | nSize--; |
155 | 155 | ||
156 | cBlock.unlock(); | 156 | cBlock.unlock(); |
157 | return pTmp; | 157 | return pTmp; |
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * Operates just like the other dequeue function in blocking mode with | 162 | * Operates just like the other dequeue function in blocking mode with |
163 | * one twist. This function will block for at most nSec seconds and | 163 | * one twist. This function will block for at most nSec seconds and |
164 | * nUSec micro-seconds. If the timer is up and no data is available, | 164 | * nUSec micro-seconds. If the timer is up and no data is available, |
165 | * this will just return NULL. If data is enqueued before the timeout | 165 | * this will just return NULL. If data is enqueued before the timeout |
166 | * expires, it will dequeue and exit immediately. | 166 | * expires, it will dequeue and exit immediately. |
167 | *@param nSec The number of seconds to wait, max. | 167 | *@param nSec The number of seconds to wait, max. |
168 | *@param nUSec The number of micro-seconds to wait, max. | 168 | *@param nUSec The number of micro-seconds to wait, max. |
169 | *@returns The next piece of data in the queue, or NULL if the timeout | 169 | *@returns The next piece of data in the queue, or NULL if the timeout |
170 | * was exceeded. | 170 | * was exceeded. |
171 | */ | 171 | */ |
172 | T dequeue( int nSec, int nUSec ) | 172 | T dequeue( int nSec, int nUSec ) |
173 | { | 173 | { |
174 | cBlock.lock(); | 174 | cBlock.lock(); |
175 | if( pStart == NULL ) | 175 | if( pStart == NULL ) |
176 | { | 176 | { |
177 | cBlock.wait( nSec, nUSec ); | 177 | cBlock.wait( nSec, nUSec ); |
178 | 178 | ||
179 | if( pStart == NULL ) | 179 | if( pStart == NULL ) |
180 | { | 180 | { |
181 | cBlock.unlock(); | 181 | cBlock.unlock(); |
182 | return NULL; | 182 | return NULL; |
183 | } | 183 | } |
184 | 184 | ||
185 | T pTmp = pStart->pData; | 185 | T pTmp = pStart->pData; |
186 | Item *pDel = pStart; | 186 | Item *pDel = pStart; |
187 | pStart = pStart->pNext; | 187 | pStart = pStart->pNext; |
188 | delete pDel; | 188 | delete pDel; |
189 | nSize--; | 189 | nSize--; |
190 | 190 | ||
191 | cBlock.unlock(); | 191 | cBlock.unlock(); |
192 | return pTmp; | 192 | return pTmp; |
193 | } | 193 | } |
194 | else | 194 | else |
195 | { | 195 | { |
196 | T pTmp = pStart->pData; | 196 | T pTmp = pStart->pData; |
197 | Item *pDel = pStart; | 197 | Item *pDel = pStart; |
198 | pStart = pStart->pNext; | 198 | pStart = pStart->pNext; |
199 | delete pDel; | 199 | delete pDel; |
200 | nSize--; | 200 | nSize--; |
201 | 201 | ||
202 | cBlock.unlock(); | 202 | cBlock.unlock(); |
203 | return pTmp; | 203 | return pTmp; |
204 | } | 204 | } |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * Checks to see if the queue has data in it or not. Note that there | 208 | * Checks to see if the queue has data in it or not. Note that there |
209 | * is no function to determine the length of the queue. This data | 209 | * is no function to determine the length of the queue. This data |
210 | * isn't kept track of. If you really need to know, fix this. | 210 | * isn't kept track of. If you really need to know, fix this. |
211 | *@returns True if the queue is empty, false if it has data in it. | 211 | *@returns True if the queue is empty, false if it has data in it. |
212 | */ | 212 | */ |
213 | bool isEmpty() | 213 | bool isEmpty() |
214 | { | 214 | { |
215 | cBlock.lock(); | 215 | cBlock.lock(); |
216 | bool bEmpty = (pStart == NULL ); | 216 | bool bEmpty = (pStart == NULL ); |
217 | cBlock.unlock(); | 217 | cBlock.unlock(); |
218 | 218 | ||
219 | return bEmpty; | 219 | return bEmpty; |
220 | } | 220 | } |
221 | 221 | ||
222 | long getSize() | 222 | long getSize() |
223 | { | 223 | { |
224 | cBlock.lock(); | 224 | cBlock.lock(); |
225 | long nRet = nSize; | 225 | long nRet = nSize; |
226 | cBlock.unlock(); | 226 | cBlock.unlock(); |
227 | 227 | ||
228 | return nRet; | 228 | return nRet; |
229 | } | 229 | } |
230 | 230 | ||
231 | void unblockAll() | 231 | void unblockAll() |
232 | { | 232 | { |
233 | cBlock.lock(); | 233 | cBlock.lock(); |
234 | cBlock.broadcast(); | 234 | cBlock.broadcast(); |
235 | cBlock.unlock(); | 235 | cBlock.unlock(); |
236 | } | 236 | } |
237 | 237 | ||
238 | private: | 238 | private: |
239 | Item *pStart; /**< The start of the queue, the next element to dequeue. */ | 239 | Item *pStart; /**< The start of the queue, the next element to dequeue. */ |
240 | Item *pEnd; /**< The end of the queue, the last element to dequeue. */ | 240 | Item *pEnd; /**< The end of the queue, the last element to dequeue. */ |
241 | long nSize; /**< The number of items in the queue. */ | 241 | long nSize; /**< The number of items in the queue. */ |
242 | 242 | ||
243 | Condition cBlock; /**< The condition for blocking dequeues. */ | 243 | Condition cBlock; /**< The condition for blocking dequeues. */ |
244 | }; | 244 | }; |
245 | } | 245 | } |
246 | 246 | ||
247 | #endif | 247 | #endif |
diff --git a/src/stable/tafcomment.cpp b/src/stable/tafcomment.cpp index ceda8e3..5168685 100644 --- a/src/stable/tafcomment.cpp +++ b/src/stable/tafcomment.cpp | |||
@@ -8,16 +8,16 @@ | |||
8 | #include "bu/tafcomment.h" | 8 | #include "bu/tafcomment.h" |
9 | 9 | ||
10 | Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : | 10 | Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : |
11 | TafNode( typeComment ), | 11 | TafNode( typeComment ), |
12 | sText( rSrc.sText ), | 12 | sText( rSrc.sText ), |
13 | bEOL( rSrc.bEOL ) | 13 | bEOL( rSrc.bEOL ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::TafComment::TafComment( const Bu::String &sText, bool bEOL ) : | 17 | Bu::TafComment::TafComment( const Bu::String &sText, bool bEOL ) : |
18 | TafNode( typeComment ), | 18 | TafNode( typeComment ), |
19 | sText( sText ), | 19 | sText( sText ), |
20 | bEOL( bEOL ) | 20 | bEOL( bEOL ) |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
@@ -27,11 +27,11 @@ Bu::TafComment::~TafComment() | |||
27 | 27 | ||
28 | const Bu::String &Bu::TafComment::getText() const | 28 | const Bu::String &Bu::TafComment::getText() const |
29 | { | 29 | { |
30 | return sText; | 30 | return sText; |
31 | } | 31 | } |
32 | 32 | ||
33 | bool Bu::TafComment::isEOLStyle() const | 33 | bool Bu::TafComment::isEOLStyle() const |
34 | { | 34 | { |
35 | return bEOL; | 35 | return bEOL; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/src/stable/tafcomment.h b/src/stable/tafcomment.h index 80c6399..2f403e7 100644 --- a/src/stable/tafcomment.h +++ b/src/stable/tafcomment.h | |||
@@ -13,24 +13,24 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * | 17 | * |
18 | *@ingroup Taf | 18 | *@ingroup Taf |
19 | */ | 19 | */ |
20 | class TafComment : public TafNode | 20 | class TafComment : public TafNode |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | TafComment( const Bu::TafComment &rSrc ); | 23 | TafComment( const Bu::TafComment &rSrc ); |
24 | TafComment( const Bu::String &sText, bool bEOL=false ); | 24 | TafComment( const Bu::String &sText, bool bEOL=false ); |
25 | virtual ~TafComment(); | 25 | virtual ~TafComment(); |
26 | 26 | ||
27 | const Bu::String &getText() const; | 27 | const Bu::String &getText() const; |
28 | bool isEOLStyle() const; | 28 | bool isEOLStyle() const; |
29 | 29 | ||
30 | private: | 30 | private: |
31 | Bu::String sText; | 31 | Bu::String sText; |
32 | bool bEOL; | 32 | bool bEOL; |
33 | }; | 33 | }; |
34 | } | 34 | } |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/src/stable/tafgroup.cpp b/src/stable/tafgroup.cpp index 27af09e..7e15b26 100644 --- a/src/stable/tafgroup.cpp +++ b/src/stable/tafgroup.cpp | |||
@@ -10,215 +10,215 @@ | |||
10 | #include "bu/tafcomment.h" | 10 | #include "bu/tafcomment.h" |
11 | 11 | ||
12 | Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : | 12 | Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : |
13 | TafNode( typeGroup ), | 13 | TafNode( typeGroup ), |
14 | sName( rSrc.sName ) | 14 | sName( rSrc.sName ) |
15 | { | 15 | { |
16 | for( NodeList::const_iterator i = rSrc.lChildren.begin(); i; i++ ) | 16 | for( NodeList::const_iterator i = rSrc.lChildren.begin(); i; i++ ) |
17 | { | 17 | { |
18 | switch( (*i)->getType() ) | 18 | switch( (*i)->getType() ) |
19 | { | 19 | { |
20 | case typeGroup: | 20 | case typeGroup: |
21 | addChild( new TafGroup( *dynamic_cast<const TafGroup *>(*i) ) ); | 21 | addChild( new TafGroup( *dynamic_cast<const TafGroup *>(*i) ) ); |
22 | break; | 22 | break; |
23 | 23 | ||
24 | case typeProperty: | 24 | case typeProperty: |
25 | addChild( new TafProperty( *dynamic_cast<const TafProperty *>(*i) ) ); | 25 | addChild( new TafProperty( *dynamic_cast<const TafProperty *>(*i) ) ); |
26 | break; | 26 | break; |
27 | 27 | ||
28 | case typeComment: | 28 | case typeComment: |
29 | addChild( new TafComment( *dynamic_cast<const TafComment *>(*i) ) ); | 29 | addChild( new TafComment( *dynamic_cast<const TafComment *>(*i) ) ); |
30 | break; | 30 | break; |
31 | } | 31 | } |
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::TafGroup::TafGroup( const Bu::String &sName ) : | 35 | Bu::TafGroup::TafGroup( const Bu::String &sName ) : |
36 | TafNode( typeGroup ), | 36 | TafNode( typeGroup ), |
37 | sName( sName ) | 37 | sName( sName ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | Bu::TafGroup::~TafGroup() | 41 | Bu::TafGroup::~TafGroup() |
42 | { | 42 | { |
43 | for( NodeList::iterator i = lChildren.begin(); i != lChildren.end(); i++ ) | 43 | for( NodeList::iterator i = lChildren.begin(); i != lChildren.end(); i++ ) |
44 | { | 44 | { |
45 | delete (*i); | 45 | delete (*i); |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | const Bu::String &Bu::TafGroup::getName() const | 49 | const Bu::String &Bu::TafGroup::getName() const |
50 | { | 50 | { |
51 | return sName; | 51 | return sName; |
52 | } | 52 | } |
53 | 53 | ||
54 | void Bu::TafGroup::setName( const Bu::String &sName ) | 54 | void Bu::TafGroup::setName( const Bu::String &sName ) |
55 | { | 55 | { |
56 | this->sName = sName; | 56 | this->sName = sName; |
57 | } | 57 | } |
58 | 58 | ||
59 | Bu::TafNode *Bu::TafGroup::addChild( Bu::TafNode *pNode ) | 59 | Bu::TafNode *Bu::TafGroup::addChild( Bu::TafNode *pNode ) |
60 | { | 60 | { |
61 | switch( pNode->getType() ) | 61 | switch( pNode->getType() ) |
62 | { | 62 | { |
63 | case typeGroup: | 63 | case typeGroup: |
64 | addChild( (Bu::TafGroup *)pNode ); | 64 | addChild( (Bu::TafGroup *)pNode ); |
65 | break; | 65 | break; |
66 | 66 | ||
67 | case typeProperty: | 67 | case typeProperty: |
68 | addChild( (Bu::TafProperty *)pNode ); | 68 | addChild( (Bu::TafProperty *)pNode ); |
69 | break; | 69 | break; |
70 | 70 | ||
71 | case typeComment: | 71 | case typeComment: |
72 | addChild( (Bu::TafComment *)pNode ); | 72 | addChild( (Bu::TafComment *)pNode ); |
73 | break; | 73 | break; |
74 | } | 74 | } |
75 | 75 | ||
76 | return pNode; | 76 | return pNode; |
77 | } | 77 | } |
78 | 78 | ||
79 | Bu::TafGroup *Bu::TafGroup::addChild( TafGroup *pNode ) | 79 | Bu::TafGroup *Bu::TafGroup::addChild( TafGroup *pNode ) |
80 | { | 80 | { |
81 | TafGroup *pGroup = (TafGroup *)pNode; | 81 | TafGroup *pGroup = (TafGroup *)pNode; |
82 | if( !hChildren.has( pGroup->getName() ) ) | 82 | if( !hChildren.has( pGroup->getName() ) ) |
83 | hChildren.insert( pGroup->getName(), GroupList() ); | 83 | hChildren.insert( pGroup->getName(), GroupList() ); |
84 | hChildren.get( pGroup->getName() ).append( pGroup ); | 84 | hChildren.get( pGroup->getName() ).append( pGroup ); |
85 | lChildren.append( pNode ); | 85 | lChildren.append( pNode ); |
86 | return pNode; | 86 | return pNode; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::TafProperty *Bu::TafGroup::addChild( TafProperty *pNode ) | 89 | Bu::TafProperty *Bu::TafGroup::addChild( TafProperty *pNode ) |
90 | { | 90 | { |
91 | TafProperty *pProperty = (TafProperty *)pNode; | 91 | TafProperty *pProperty = (TafProperty *)pNode; |
92 | if( !hProp.has( pProperty->getName() ) ) | 92 | if( !hProp.has( pProperty->getName() ) ) |
93 | hProp.insert( pProperty->getName(), PropList() ); | 93 | hProp.insert( pProperty->getName(), PropList() ); |
94 | hProp.get( pProperty->getName() ).append( pProperty->getValue() ); | 94 | hProp.get( pProperty->getName() ).append( pProperty->getValue() ); |
95 | lChildren.append( pNode ); | 95 | lChildren.append( pNode ); |
96 | return pNode; | 96 | return pNode; |
97 | } | 97 | } |
98 | 98 | ||
99 | Bu::TafComment *Bu::TafGroup::addChild( TafComment *pNode ) | 99 | Bu::TafComment *Bu::TafGroup::addChild( TafComment *pNode ) |
100 | { | 100 | { |
101 | lChildren.append( pNode ); | 101 | lChildren.append( pNode ); |
102 | return pNode; | 102 | return pNode; |
103 | } | 103 | } |
104 | 104 | ||
105 | Bu::TafGroup *Bu::TafGroup::addGroup( const Bu::String &sName ) | 105 | Bu::TafGroup *Bu::TafGroup::addGroup( const Bu::String &sName ) |
106 | { | 106 | { |
107 | return addChild( new TafGroup( sName ) ); | 107 | return addChild( new TafGroup( sName ) ); |
108 | } | 108 | } |
109 | 109 | ||
110 | Bu::TafProperty *Bu::TafGroup::addProperty( | 110 | Bu::TafProperty *Bu::TafGroup::addProperty( |
111 | const Bu::String &sName, const Bu::String &sValue ) | 111 | const Bu::String &sName, const Bu::String &sValue ) |
112 | { | 112 | { |
113 | return addChild( new TafProperty( sName, sValue ) ); | 113 | return addChild( new TafProperty( sName, sValue ) ); |
114 | } | 114 | } |
115 | 115 | ||
116 | bool Bu::TafGroup::hasChild( const Bu::String &sName ) const | 116 | bool Bu::TafGroup::hasChild( const Bu::String &sName ) const |
117 | { | 117 | { |
118 | return hChildren.has( sName ); | 118 | return hChildren.has( sName ); |
119 | } | 119 | } |
120 | 120 | ||
121 | const Bu::TafGroup::GroupList &Bu::TafGroup::getChildren( const Bu::String &sName ) const | 121 | const Bu::TafGroup::GroupList &Bu::TafGroup::getChildren( const Bu::String &sName ) const |
122 | { | 122 | { |
123 | try { | 123 | try { |
124 | return hChildren.get( sName ); | 124 | return hChildren.get( sName ); |
125 | } catch( Bu::HashException &e ) | 125 | } catch( Bu::HashException &e ) |
126 | { | 126 | { |
127 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", | 127 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", |
128 | this->sName.getStr(), sName.getStr() ); | 128 | this->sName.getStr(), sName.getStr() ); |
129 | } | 129 | } |
130 | } | 130 | } |
131 | 131 | ||
132 | const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const | 132 | const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const |
133 | { | 133 | { |
134 | return lChildren; | 134 | return lChildren; |
135 | } | 135 | } |
136 | 136 | ||
137 | const Bu::TafGroup *Bu::TafGroup::getChild( const Bu::String &sName ) const | 137 | const Bu::TafGroup *Bu::TafGroup::getChild( const Bu::String &sName ) const |
138 | { | 138 | { |
139 | try { | 139 | try { |
140 | return hChildren.get( sName ).first(); | 140 | return hChildren.get( sName ).first(); |
141 | } catch( Bu::HashException &e ) | 141 | } catch( Bu::HashException &e ) |
142 | { | 142 | { |
143 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", | 143 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", |
144 | this->sName.getStr(), sName.getStr() ); | 144 | this->sName.getStr(), sName.getStr() ); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const | 148 | bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const |
149 | { | 149 | { |
150 | return hProp.has( sName ); | 150 | return hProp.has( sName ); |
151 | } | 151 | } |
152 | 152 | ||
153 | const Bu::TafGroup::PropList &Bu::TafGroup::getProperties( const Bu::String &sName ) const | 153 | const Bu::TafGroup::PropList &Bu::TafGroup::getProperties( const Bu::String &sName ) const |
154 | { | 154 | { |
155 | try { | 155 | try { |
156 | return hProp.get( sName ); | 156 | return hProp.get( sName ); |
157 | } catch( Bu::HashException &e ) | 157 | } catch( Bu::HashException &e ) |
158 | { | 158 | { |
159 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", | 159 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", |
160 | this->sName.getStr(), sName.getStr() ); | 160 | this->sName.getStr(), sName.getStr() ); |
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName ) const | 164 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName ) const |
165 | { | 165 | { |
166 | try { | 166 | try { |
167 | return hProp.get( sName ).first(); | 167 | return hProp.get( sName ).first(); |
168 | } catch( Bu::HashException &e ) | 168 | } catch( Bu::HashException &e ) |
169 | { | 169 | { |
170 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", | 170 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", |
171 | this->sName.getStr(), sName.getStr() ); | 171 | this->sName.getStr(), sName.getStr() ); |
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName, | 175 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName, |
176 | const Bu::String &sDef ) const | 176 | const Bu::String &sDef ) const |
177 | { | 177 | { |
178 | try | 178 | try |
179 | { | 179 | { |
180 | return hProp.get( sName ).first(); | 180 | return hProp.get( sName ).first(); |
181 | } | 181 | } |
182 | catch( Bu::HashException &e ) | 182 | catch( Bu::HashException &e ) |
183 | { | 183 | { |
184 | return sDef; | 184 | return sDef; |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( | 188 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( |
189 | const Bu::String &sPath ) const | 189 | const Bu::String &sPath ) const |
190 | { | 190 | { |
191 | return getChildByPath( sPath.split('/') ); | 191 | return getChildByPath( sPath.split('/') ); |
192 | } | 192 | } |
193 | 193 | ||
194 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const | 194 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const |
195 | { | 195 | { |
196 | const Bu::TafGroup *cur = this; | 196 | const Bu::TafGroup *cur = this; |
197 | 197 | ||
198 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) | 198 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) |
199 | { | 199 | { |
200 | cur = cur->getChild( *i ); | 200 | cur = cur->getChild( *i ); |
201 | } | 201 | } |
202 | 202 | ||
203 | return cur; | 203 | return cur; |
204 | } | 204 | } |
205 | 205 | ||
206 | const Bu::String &Bu::TafGroup::getByPath( const Bu::String &sPath ) const | 206 | const Bu::String &Bu::TafGroup::getByPath( const Bu::String &sPath ) const |
207 | { | 207 | { |
208 | return getByPath( sPath.split('/') ); | 208 | return getByPath( sPath.split('/') ); |
209 | } | 209 | } |
210 | 210 | ||
211 | const Bu::String &Bu::TafGroup::getByPath( Bu::StrList lPath ) const | 211 | const Bu::String &Bu::TafGroup::getByPath( Bu::StrList lPath ) const |
212 | { | 212 | { |
213 | const Bu::TafGroup *cur = this; | 213 | const Bu::TafGroup *cur = this; |
214 | 214 | ||
215 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) | 215 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) |
216 | { | 216 | { |
217 | if( !(i+1) ) | 217 | if( !(i+1) ) |
218 | break; | 218 | break; |
219 | cur = cur->getChild( *i ); | 219 | cur = cur->getChild( *i ); |
220 | } | 220 | } |
221 | 221 | ||
222 | return cur->getProperty( lPath.last() ); | 222 | return cur->getProperty( lPath.last() ); |
223 | } | 223 | } |
224 | 224 | ||
diff --git a/src/stable/tafgroup.h b/src/stable/tafgroup.h index 3f52ab3..a22059e 100644 --- a/src/stable/tafgroup.h +++ b/src/stable/tafgroup.h | |||
@@ -16,56 +16,56 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | typedef Bu::List<Bu::String> StrList; | 19 | typedef Bu::List<Bu::String> StrList; |
20 | class TafProperty; | 20 | class TafProperty; |
21 | class TafComment; | 21 | class TafComment; |
22 | /** | 22 | /** |
23 | * | 23 | * |
24 | *@ingroup Taf | 24 | *@ingroup Taf |
25 | */ | 25 | */ |
26 | class TafGroup : public TafNode | 26 | class TafGroup : public TafNode |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | typedef Bu::List<Bu::String> PropList; | 29 | typedef Bu::List<Bu::String> PropList; |
30 | typedef Bu::Hash<Bu::String, PropList> PropHash; | 30 | typedef Bu::Hash<Bu::String, PropList> PropHash; |
31 | typedef Bu::List<class Bu::TafGroup *> GroupList; | 31 | typedef Bu::List<class Bu::TafGroup *> GroupList; |
32 | typedef Bu::Hash<Bu::String, GroupList> GroupHash; | 32 | typedef Bu::Hash<Bu::String, GroupList> GroupHash; |
33 | typedef Bu::List<class Bu::TafNode *> NodeList; | 33 | typedef Bu::List<class Bu::TafNode *> NodeList; |
34 | 34 | ||
35 | TafGroup( const TafGroup &rSrc ); | 35 | TafGroup( const TafGroup &rSrc ); |
36 | TafGroup( const Bu::String &sName ); | 36 | TafGroup( const Bu::String &sName ); |
37 | virtual ~TafGroup(); | 37 | virtual ~TafGroup(); |
38 | 38 | ||
39 | const Bu::String &getName() const; | 39 | const Bu::String &getName() const; |
40 | void setName( const Bu::String &sName ); | 40 | void setName( const Bu::String &sName ); |
41 | 41 | ||
42 | bool hasProperty( const Bu::String &sName ) const; | 42 | bool hasProperty( const Bu::String &sName ) const; |
43 | const Bu::String &getProperty( const Bu::String &sName ) const; | 43 | const Bu::String &getProperty( const Bu::String &sName ) const; |
44 | const Bu::String &getProperty( const Bu::String &sName, | 44 | const Bu::String &getProperty( const Bu::String &sName, |
45 | const Bu::String &sDef ) const; | 45 | const Bu::String &sDef ) const; |
46 | const PropList &getProperties( const Bu::String &sName ) const; | 46 | const PropList &getProperties( const Bu::String &sName ) const; |
47 | bool hasChild( const Bu::String &sName ) const; | 47 | bool hasChild( const Bu::String &sName ) const; |
48 | const TafGroup *getChild( const Bu::String &sName ) const; | 48 | const TafGroup *getChild( const Bu::String &sName ) const; |
49 | const GroupList &getChildren( const Bu::String &sName ) const; | 49 | const GroupList &getChildren( const Bu::String &sName ) const; |
50 | TafNode *addChild( TafNode *pNode ); | 50 | TafNode *addChild( TafNode *pNode ); |
51 | TafGroup *addChild( TafGroup *pNode ); | 51 | TafGroup *addChild( TafGroup *pNode ); |
52 | TafProperty *addChild( TafProperty *pNode ); | 52 | TafProperty *addChild( TafProperty *pNode ); |
53 | TafComment *addChild( TafComment *pNode ); | 53 | TafComment *addChild( TafComment *pNode ); |
54 | TafGroup *addGroup( const Bu::String &sName ); | 54 | TafGroup *addGroup( const Bu::String &sName ); |
55 | TafProperty *addProperty( | 55 | TafProperty *addProperty( |
56 | const Bu::String &sName, const Bu::String &sValue ); | 56 | const Bu::String &sName, const Bu::String &sValue ); |
57 | const NodeList &getChildren() const; | 57 | const NodeList &getChildren() const; |
58 | const TafGroup *getChildByPath( const Bu::String &sPath ) const; | 58 | const TafGroup *getChildByPath( const Bu::String &sPath ) const; |
59 | const TafGroup *getChildByPath( StrList lPath ) const; | 59 | const TafGroup *getChildByPath( StrList lPath ) const; |
60 | const Bu::String &getByPath( const Bu::String &sPath ) const; | 60 | const Bu::String &getByPath( const Bu::String &sPath ) const; |
61 | const Bu::String &getByPath( StrList lPath ) const; | 61 | const Bu::String &getByPath( StrList lPath ) const; |
62 | 62 | ||
63 | private: | 63 | private: |
64 | Bu::String sName; | 64 | Bu::String sName; |
65 | PropHash hProp; | 65 | PropHash hProp; |
66 | GroupHash hChildren; | 66 | GroupHash hChildren; |
67 | NodeList lChildren; | 67 | NodeList lChildren; |
68 | }; | 68 | }; |
69 | } | 69 | } |
70 | 70 | ||
71 | #endif | 71 | #endif |
diff --git a/src/stable/tafnode.cpp b/src/stable/tafnode.cpp index 630bcce..10ba89a 100644 --- a/src/stable/tafnode.cpp +++ b/src/stable/tafnode.cpp | |||
@@ -10,7 +10,7 @@ | |||
10 | namespace Bu { subExceptionDef( TafException ) } | 10 | namespace Bu { subExceptionDef( TafException ) } |
11 | 11 | ||
12 | Bu::TafNode::TafNode( NodeType eType ) : | 12 | Bu::TafNode::TafNode( NodeType eType ) : |
13 | eType( eType ) | 13 | eType( eType ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,6 +20,6 @@ Bu::TafNode::~TafNode() | |||
20 | 20 | ||
21 | Bu::TafNode::NodeType Bu::TafNode::getType() const | 21 | Bu::TafNode::NodeType Bu::TafNode::getType() const |
22 | { | 22 | { |
23 | return eType; | 23 | return eType; |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/src/stable/tafnode.h b/src/stable/tafnode.h index 9c0e0b9..923ee24 100644 --- a/src/stable/tafnode.h +++ b/src/stable/tafnode.h | |||
@@ -15,30 +15,30 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( TafException ); | 18 | subExceptionDecl( TafException ); |
19 | /** | 19 | /** |
20 | * | 20 | * |
21 | *@ingroup Taf | 21 | *@ingroup Taf |
22 | */ | 22 | */ |
23 | class TafNode | 23 | class TafNode |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | enum NodeType | 26 | enum NodeType |
27 | { | 27 | { |
28 | typeGroup, | 28 | typeGroup, |
29 | typeProperty, | 29 | typeProperty, |
30 | typeComment | 30 | typeComment |
31 | }; | 31 | }; |
32 | 32 | ||
33 | public: | 33 | public: |
34 | TafNode( NodeType eType ); | 34 | TafNode( NodeType eType ); |
35 | virtual ~TafNode(); | 35 | virtual ~TafNode(); |
36 | 36 | ||
37 | NodeType getType() const; | 37 | NodeType getType() const; |
38 | 38 | ||
39 | private: | 39 | private: |
40 | NodeType eType; | 40 | NodeType eType; |
41 | }; | 41 | }; |
42 | } | 42 | } |
43 | 43 | ||
44 | #endif | 44 | #endif |
diff --git a/src/stable/tafproperty.cpp b/src/stable/tafproperty.cpp index 017b294..2b3e338 100644 --- a/src/stable/tafproperty.cpp +++ b/src/stable/tafproperty.cpp | |||
@@ -8,16 +8,16 @@ | |||
8 | #include "bu/tafproperty.h" | 8 | #include "bu/tafproperty.h" |
9 | 9 | ||
10 | Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : | 10 | Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : |
11 | TafNode( typeProperty ), | 11 | TafNode( typeProperty ), |
12 | sName( rSrc.sName ), | 12 | sName( rSrc.sName ), |
13 | sValue( rSrc.sValue ) | 13 | sValue( rSrc.sValue ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::TafProperty::TafProperty( const Bu::String &sName, const Bu::String &sValue ) : | 17 | Bu::TafProperty::TafProperty( const Bu::String &sName, const Bu::String &sValue ) : |
18 | TafNode( typeProperty ), | 18 | TafNode( typeProperty ), |
19 | sName( sName ), | 19 | sName( sName ), |
20 | sValue( sValue ) | 20 | sValue( sValue ) |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
@@ -27,11 +27,11 @@ Bu::TafProperty::~TafProperty() | |||
27 | 27 | ||
28 | const Bu::String &Bu::TafProperty::getName() const | 28 | const Bu::String &Bu::TafProperty::getName() const |
29 | { | 29 | { |
30 | return sName; | 30 | return sName; |
31 | } | 31 | } |
32 | 32 | ||
33 | const Bu::String &Bu::TafProperty::getValue() const | 33 | const Bu::String &Bu::TafProperty::getValue() const |
34 | { | 34 | { |
35 | return sValue; | 35 | return sValue; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/src/stable/tafproperty.h b/src/stable/tafproperty.h index b7c6983..b9834e1 100644 --- a/src/stable/tafproperty.h +++ b/src/stable/tafproperty.h | |||
@@ -13,24 +13,24 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * | 17 | * |
18 | *@ingroup Taf | 18 | *@ingroup Taf |
19 | */ | 19 | */ |
20 | class TafProperty : public TafNode | 20 | class TafProperty : public TafNode |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | TafProperty( const Bu::TafProperty &rSrc ); | 23 | TafProperty( const Bu::TafProperty &rSrc ); |
24 | TafProperty( const Bu::String &sName, const Bu::String &sValue ); | 24 | TafProperty( const Bu::String &sName, const Bu::String &sValue ); |
25 | virtual ~TafProperty(); | 25 | virtual ~TafProperty(); |
26 | 26 | ||
27 | const Bu::String &getName() const; | 27 | const Bu::String &getName() const; |
28 | const Bu::String &getValue() const; | 28 | const Bu::String &getValue() const; |
29 | 29 | ||
30 | private: | 30 | private: |
31 | Bu::String sName; | 31 | Bu::String sName; |
32 | Bu::String sValue; | 32 | Bu::String sValue; |
33 | }; | 33 | }; |
34 | } | 34 | } |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/src/stable/tafreader.cpp b/src/stable/tafreader.cpp index fb17aea..f21505e 100644 --- a/src/stable/tafreader.cpp +++ b/src/stable/tafreader.cpp | |||
@@ -14,12 +14,12 @@ | |||
14 | using namespace Bu; | 14 | using namespace Bu; |
15 | 15 | ||
16 | Bu::TafReader::TafReader( Bu::Stream &sIn ) : | 16 | Bu::TafReader::TafReader( Bu::Stream &sIn ) : |
17 | c( 0 ), | 17 | c( 0 ), |
18 | la( 0 ), | 18 | la( 0 ), |
19 | sIn( sIn ), | 19 | sIn( sIn ), |
20 | iLine( 1 ), iCol( -1 ) | 20 | iLine( 1 ), iCol( -1 ) |
21 | { | 21 | { |
22 | next(); next(); | 22 | next(); next(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::TafReader::~TafReader() | 25 | Bu::TafReader::~TafReader() |
@@ -29,122 +29,122 @@ Bu::TafReader::~TafReader() | |||
29 | 29 | ||
30 | Bu::TafGroup *Bu::TafReader::readGroup() | 30 | Bu::TafGroup *Bu::TafReader::readGroup() |
31 | { | 31 | { |
32 | ws(); | 32 | ws(); |
33 | if( c != '{' ) | 33 | if( c != '{' ) |
34 | throw TafException("%d:%d: Expected '{' got '%c'.", iLine, iCol, c ); | 34 | throw TafException("%d:%d: Expected '{' got '%c'.", iLine, iCol, c ); |
35 | next(); | 35 | next(); |
36 | ws(); | 36 | ws(); |
37 | String sName = readStr(); | 37 | String sName = readStr(); |
38 | TafGroup *pGroup = new TafGroup( sName ); | 38 | TafGroup *pGroup = new TafGroup( sName ); |
39 | try | 39 | try |
40 | { | 40 | { |
41 | ws(); | 41 | ws(); |
42 | if( c != ':' ) | 42 | if( c != ':' ) |
43 | throw TafException("%d:%d: Expected ':' got '%c'.", | 43 | throw TafException("%d:%d: Expected ':' got '%c'.", |
44 | iLine, iCol, c ); | 44 | iLine, iCol, c ); |
45 | next(); | 45 | next(); |
46 | //printf("Node[%s]:\n", sName.getStr() ); | 46 | //printf("Node[%s]:\n", sName.getStr() ); |
47 | 47 | ||
48 | groupContent( pGroup ); | 48 | groupContent( pGroup ); |
49 | 49 | ||
50 | if( c != '}' ) | 50 | if( c != '}' ) |
51 | throw TafException("%d:%d: Expected '}' got '%c'.", | 51 | throw TafException("%d:%d: Expected '}' got '%c'.", |
52 | iLine, iCol, c ); | 52 | iLine, iCol, c ); |
53 | 53 | ||
54 | //next(); | 54 | //next(); |
55 | 55 | ||
56 | return pGroup; | 56 | return pGroup; |
57 | } | 57 | } |
58 | catch(...) | 58 | catch(...) |
59 | { | 59 | { |
60 | delete pGroup; | 60 | delete pGroup; |
61 | throw; | 61 | throw; |
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | void Bu::TafReader::groupContent( Bu::TafGroup *pGroup ) | 65 | void Bu::TafReader::groupContent( Bu::TafGroup *pGroup ) |
66 | { | 66 | { |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | ws(); | 69 | ws(); |
70 | if( c == '{' ) | 70 | if( c == '{' ) |
71 | { | 71 | { |
72 | pGroup->addChild( readGroup() ); | 72 | pGroup->addChild( readGroup() ); |
73 | next(); | 73 | next(); |
74 | } | 74 | } |
75 | else if( c == '}' ) | 75 | else if( c == '}' ) |
76 | return; | 76 | return; |
77 | else if( c == '/' && la == '*' ) | 77 | else if( c == '/' && la == '*' ) |
78 | pGroup->addChild( readComment() ); | 78 | pGroup->addChild( readComment() ); |
79 | else if( c == '/' && la == '/' ) | 79 | else if( c == '/' && la == '/' ) |
80 | pGroup->addChild( readComment( true ) ); | 80 | pGroup->addChild( readComment( true ) ); |
81 | else if( c == ':' ) | 81 | else if( c == ':' ) |
82 | throw TafException("%d:%d: Encountered stray ':' in taf stream.", | 82 | throw TafException("%d:%d: Encountered stray ':' in taf stream.", |
83 | iLine, iCol ); | 83 | iLine, iCol ); |
84 | else | 84 | else |
85 | pGroup->addChild( readProperty() ); | 85 | pGroup->addChild( readProperty() ); |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::TafProperty *Bu::TafReader::readProperty() | 89 | Bu::TafProperty *Bu::TafReader::readProperty() |
90 | { | 90 | { |
91 | String sName = readStr(); | 91 | String sName = readStr(); |
92 | ws(); | 92 | ws(); |
93 | if( c != '=' ) | 93 | if( c != '=' ) |
94 | { | 94 | { |
95 | //printf(" %s (true)\n", sName.getStr() ); | 95 | //printf(" %s (true)\n", sName.getStr() ); |
96 | return new Bu::TafProperty( "", sName ); | 96 | return new Bu::TafProperty( "", sName ); |
97 | } | 97 | } |
98 | next(); | 98 | next(); |
99 | String sValue = readStr(); | 99 | String sValue = readStr(); |
100 | return new Bu::TafProperty( sName, sValue ); | 100 | return new Bu::TafProperty( sName, sValue ); |
101 | //printf(" %s = %s\n", sName.getStr(), sValue.getStr() ); | 101 | //printf(" %s = %s\n", sName.getStr(), sValue.getStr() ); |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::TafComment *Bu::TafReader::readComment( bool bEOL ) | 104 | Bu::TafComment *Bu::TafReader::readComment( bool bEOL ) |
105 | { | 105 | { |
106 | String sCmnt; | 106 | String sCmnt; |
107 | next(); | 107 | next(); |
108 | if( bEOL ) | 108 | if( bEOL ) |
109 | { | 109 | { |
110 | for(;;) | 110 | for(;;) |
111 | { | 111 | { |
112 | next(); | 112 | next(); |
113 | if( c == '\n' && la == '\r' ) | 113 | if( c == '\n' && la == '\r' ) |
114 | { | 114 | { |
115 | next(); next(); | 115 | next(); next(); |
116 | break; | 116 | break; |
117 | } | 117 | } |
118 | else if( c == '\n' || c == '\r' ) | 118 | else if( c == '\n' || c == '\r' ) |
119 | { | 119 | { |
120 | next(); | 120 | next(); |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | sCmnt += c; | 123 | sCmnt += c; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | else | 126 | else |
127 | { | 127 | { |
128 | for(;;) | 128 | for(;;) |
129 | { | 129 | { |
130 | next(); | 130 | next(); |
131 | if( c == '*' && la == '/' ) | 131 | if( c == '*' && la == '/' ) |
132 | { | 132 | { |
133 | next(); next(); | 133 | next(); next(); |
134 | break; | 134 | break; |
135 | } | 135 | } |
136 | sCmnt += c; | 136 | sCmnt += c; |
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | return new TafComment( sCmnt, bEOL ); | 140 | return new TafComment( sCmnt, bEOL ); |
141 | } | 141 | } |
142 | 142 | ||
143 | Bu::String Bu::TafReader::readStr() | 143 | Bu::String Bu::TafReader::readStr() |
144 | { | 144 | { |
145 | ws(); | 145 | ws(); |
146 | String s; | 146 | String s; |
147 | if( c == '"' ) | 147 | if( c == '"' ) |
148 | { | 148 | { |
149 | next(); | 149 | next(); |
150 | for(;;) | 150 | for(;;) |
@@ -162,7 +162,7 @@ Bu::String Bu::TafReader::readStr() | |||
162 | c = (unsigned char)strtol( code, NULL, 16 ); | 162 | c = (unsigned char)strtol( code, NULL, 16 ); |
163 | } | 163 | } |
164 | else if( c == '"' ) | 164 | else if( c == '"' ) |
165 | c = '"'; | 165 | c = '"'; |
166 | else if( c == '\\' ) | 166 | else if( c == '\\' ) |
167 | c = '\\'; | 167 | c = '\\'; |
168 | else if( c == 'n' ) | 168 | else if( c == 'n' ) |
@@ -174,79 +174,79 @@ Bu::String Bu::TafReader::readStr() | |||
174 | iLine, iCol, c ); | 174 | iLine, iCol, c ); |
175 | } | 175 | } |
176 | else if( c == '"' ) | 176 | else if( c == '"' ) |
177 | break; | 177 | break; |
178 | s += c; | 178 | s += c; |
179 | next(); | 179 | next(); |
180 | } | 180 | } |
181 | next(); | 181 | next(); |
182 | } | 182 | } |
183 | else | 183 | else |
184 | { | 184 | { |
185 | for(;;) | 185 | for(;;) |
186 | { | 186 | { |
187 | if( isws() || c == '}' || c == '{' || c == ':' || c == '=' ) | 187 | if( isws() || c == '}' || c == '{' || c == ':' || c == '=' ) |
188 | break; | 188 | break; |
189 | s += c; | 189 | s += c; |
190 | next(); | 190 | next(); |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
194 | return s; | 194 | return s; |
195 | } | 195 | } |
196 | 196 | ||
197 | void Bu::TafReader::ws() | 197 | void Bu::TafReader::ws() |
198 | { | 198 | { |
199 | for(;;) | 199 | for(;;) |
200 | { | 200 | { |
201 | if( !isws() ) | 201 | if( !isws() ) |
202 | return; | 202 | return; |
203 | 203 | ||
204 | next(); | 204 | next(); |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | bool Bu::TafReader::isws() | 208 | bool Bu::TafReader::isws() |
209 | { | 209 | { |
210 | return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); | 210 | return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); |
211 | } | 211 | } |
212 | 212 | ||
213 | void Bu::TafReader::next() | 213 | void Bu::TafReader::next() |
214 | { | 214 | { |
215 | if( c == '\n' ) | 215 | if( c == '\n' ) |
216 | { | 216 | { |
217 | iLine++; | 217 | iLine++; |
218 | iCol = 1; | 218 | iCol = 1; |
219 | } | 219 | } |
220 | else | 220 | else |
221 | iCol++; | 221 | iCol++; |
222 | if( c == '}' ) | 222 | if( c == '}' ) |
223 | { | 223 | { |
224 | rawread( &c ); | 224 | rawread( &c ); |
225 | if( c != '}' ) | 225 | if( c != '}' ) |
226 | rawread( &la ); | 226 | rawread( &la ); |
227 | } | 227 | } |
228 | else | 228 | else |
229 | { | 229 | { |
230 | c = la; | 230 | c = la; |
231 | if( c != '}' ) | 231 | if( c != '}' ) |
232 | rawread( &la ); | 232 | rawread( &la ); |
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | void Bu::TafReader::rawread( char *c ) | 236 | void Bu::TafReader::rawread( char *c ) |
237 | { | 237 | { |
238 | if( sIn.read( c, 1 ) < 1 ) | 238 | if( sIn.read( c, 1 ) < 1 ) |
239 | { | 239 | { |
240 | if( sIn.isEos() ) | 240 | if( sIn.isEos() ) |
241 | { | 241 | { |
242 | throw TafException("%d:%d: Premature end of stream.", | 242 | throw TafException("%d:%d: Premature end of stream.", |
243 | iLine, iCol, c ); | 243 | iLine, iCol, c ); |
244 | } | 244 | } |
245 | else | 245 | else |
246 | { | 246 | { |
247 | throw TafException("%d:%d: No data read, but not end of stream?", | 247 | throw TafException("%d:%d: No data read, but not end of stream?", |
248 | iLine, iCol, c ); | 248 | iLine, iCol, c ); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | } | 251 | } |
252 | 252 | ||
diff --git a/src/stable/tafreader.h b/src/stable/tafreader.h index 0cf00a9..b3ced1b 100644 --- a/src/stable/tafreader.h +++ b/src/stable/tafreader.h | |||
@@ -13,37 +13,37 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class TafNode; | 16 | class TafNode; |
17 | class TafGroup; | 17 | class TafGroup; |
18 | class TafProperty; | 18 | class TafProperty; |
19 | class TafComment; | 19 | class TafComment; |
20 | class Stream; | 20 | class Stream; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * | 23 | * |
24 | *@ingroup Taf | 24 | *@ingroup Taf |
25 | */ | 25 | */ |
26 | class TafReader | 26 | class TafReader |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | TafReader( Bu::Stream &sIn ); | 29 | TafReader( Bu::Stream &sIn ); |
30 | virtual ~TafReader(); | 30 | virtual ~TafReader(); |
31 | 31 | ||
32 | Bu::TafGroup *readGroup(); | 32 | Bu::TafGroup *readGroup(); |
33 | 33 | ||
34 | private: | 34 | private: |
35 | void groupContent( Bu::TafGroup *pNode ); | 35 | void groupContent( Bu::TafGroup *pNode ); |
36 | Bu::TafProperty *readProperty(); | 36 | Bu::TafProperty *readProperty(); |
37 | Bu::TafComment *readComment( bool bEOL=false ); | 37 | Bu::TafComment *readComment( bool bEOL=false ); |
38 | void ws(); | 38 | void ws(); |
39 | bool isws(); | 39 | bool isws(); |
40 | void next(); | 40 | void next(); |
41 | Bu::String readStr(); | 41 | Bu::String readStr(); |
42 | void rawread( char *c ); | 42 | void rawread( char *c ); |
43 | char c, la; | 43 | char c, la; |
44 | Bu::Stream &sIn; | 44 | Bu::Stream &sIn; |
45 | int iLine, iCol; | 45 | int iLine, iCol; |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/tafwriter.cpp b/src/stable/tafwriter.cpp index 00d9f68..f17a237 100644 --- a/src/stable/tafwriter.cpp +++ b/src/stable/tafwriter.cpp | |||
@@ -9,8 +9,8 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : | 11 | Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : |
12 | sOut( sOut ), | 12 | sOut( sOut ), |
13 | iDepth( 0 ) | 13 | iDepth( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,81 +20,81 @@ Bu::TafWriter::~TafWriter() | |||
20 | 20 | ||
21 | void Bu::TafWriter::ident() | 21 | void Bu::TafWriter::ident() |
22 | { | 22 | { |
23 | for( int j = 0; j < iDepth; j++ ) | 23 | for( int j = 0; j < iDepth; j++ ) |
24 | sOut.write(" ", 4 ); | 24 | sOut.write(" ", 4 ); |
25 | } | 25 | } |
26 | 26 | ||
27 | void Bu::TafWriter::writeGroup( const Bu::TafGroup *pRoot ) | 27 | void Bu::TafWriter::writeGroup( const Bu::TafGroup *pRoot ) |
28 | { | 28 | { |
29 | ident(); | 29 | ident(); |
30 | sOut.write("{", 1 ); | 30 | sOut.write("{", 1 ); |
31 | if( pRoot->getName().isSet() ) | 31 | if( pRoot->getName().isSet() ) |
32 | writeString( pRoot->getName() ); | 32 | writeString( pRoot->getName() ); |
33 | sOut.write(":\n", 2 ); | 33 | sOut.write(":\n", 2 ); |
34 | iDepth++; | 34 | iDepth++; |
35 | const Bu::TafGroup::NodeList &nl = pRoot->getChildren(); | 35 | const Bu::TafGroup::NodeList &nl = pRoot->getChildren(); |
36 | for( Bu::TafGroup::NodeList::const_iterator i = nl.begin(); i != nl.end(); i++ ) | 36 | for( Bu::TafGroup::NodeList::const_iterator i = nl.begin(); i != nl.end(); i++ ) |
37 | { | 37 | { |
38 | switch( (*i)->getType() ) | 38 | switch( (*i)->getType() ) |
39 | { | 39 | { |
40 | case Bu::TafNode::typeGroup: | 40 | case Bu::TafNode::typeGroup: |
41 | writeGroup( (Bu::TafGroup *)(*i) ); | 41 | writeGroup( (Bu::TafGroup *)(*i) ); |
42 | break; | 42 | break; |
43 | 43 | ||
44 | case Bu::TafNode::typeProperty: | 44 | case Bu::TafNode::typeProperty: |
45 | writeProperty( (Bu::TafProperty *)(*i) ); | 45 | writeProperty( (Bu::TafProperty *)(*i) ); |
46 | break; | 46 | break; |
47 | 47 | ||
48 | case Bu::TafNode::typeComment: | 48 | case Bu::TafNode::typeComment: |
49 | writeComment( (Bu::TafComment *)(*i) ); | 49 | writeComment( (Bu::TafComment *)(*i) ); |
50 | break; | 50 | break; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | iDepth--; | 53 | iDepth--; |
54 | ident(); | 54 | ident(); |
55 | sOut.write("}\n", 2 ); | 55 | sOut.write("}\n", 2 ); |
56 | } | 56 | } |
57 | 57 | ||
58 | void Bu::TafWriter::writeProperty( const Bu::TafProperty *pProp ) | 58 | void Bu::TafWriter::writeProperty( const Bu::TafProperty *pProp ) |
59 | { | 59 | { |
60 | ident(); | 60 | ident(); |
61 | if( !pProp->getName().isEmpty() ) | 61 | if( !pProp->getName().isEmpty() ) |
62 | { | 62 | { |
63 | writeString( pProp->getName() ); | 63 | writeString( pProp->getName() ); |
64 | sOut.write("=", 1 ); | 64 | sOut.write("=", 1 ); |
65 | writeString( pProp->getValue() ); | 65 | writeString( pProp->getValue() ); |
66 | } | 66 | } |
67 | else | 67 | else |
68 | { | 68 | { |
69 | writeString( pProp->getValue() ); | 69 | writeString( pProp->getValue() ); |
70 | } | 70 | } |
71 | sOut.write("\n", 1 ); | 71 | sOut.write("\n", 1 ); |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::TafWriter::writeComment( const Bu::TafComment *pComment ) | 74 | void Bu::TafWriter::writeComment( const Bu::TafComment *pComment ) |
75 | { | 75 | { |
76 | ident(); | 76 | ident(); |
77 | if( pComment->isEOLStyle() ) | 77 | if( pComment->isEOLStyle() ) |
78 | { | 78 | { |
79 | sOut.write("//", 2 ); | 79 | sOut.write("//", 2 ); |
80 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); | 80 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); |
81 | sOut.write("\n", 1 ); | 81 | sOut.write("\n", 1 ); |
82 | } | 82 | } |
83 | else | 83 | else |
84 | { | 84 | { |
85 | sOut.write("/*", 2 ); | 85 | sOut.write("/*", 2 ); |
86 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); | 86 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); |
87 | sOut.write("*/ ", 3 ); | 87 | sOut.write("*/ ", 3 ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
91 | void Bu::TafWriter::writeString( const Bu::String &str ) | 91 | void Bu::TafWriter::writeString( const Bu::String &str ) |
92 | { | 92 | { |
93 | sOut.write("\"", 1 ); | 93 | sOut.write("\"", 1 ); |
94 | for( Bu::String::const_iterator s = str.begin(); s != str.end(); s++ ) | 94 | for( Bu::String::const_iterator s = str.begin(); s != str.end(); s++ ) |
95 | { | 95 | { |
96 | if( *s == '\"' ) | 96 | if( *s == '\"' ) |
97 | sOut.write("\\\"", 2 ); | 97 | sOut.write("\\\"", 2 ); |
98 | else if( *s == '\\' ) | 98 | else if( *s == '\\' ) |
99 | sOut.write("\\\\", 2 ); | 99 | sOut.write("\\\\", 2 ); |
100 | else if( *s < 32 || *s > 126 ) | 100 | else if( *s < 32 || *s > 126 ) |
diff --git a/src/stable/tafwriter.h b/src/stable/tafwriter.h index 7e43d64..48787ab 100644 --- a/src/stable/tafwriter.h +++ b/src/stable/tafwriter.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | class TafNode; | 18 | class TafNode; |
19 | class TafGroup; | 19 | class TafGroup; |
20 | class TafProperty; | 20 | class TafProperty; |
21 | class TafComment; | 21 | class TafComment; |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * | 24 | * |
25 | *@ingroup Taf | 25 | *@ingroup Taf |
26 | */ | 26 | */ |
27 | class TafWriter | 27 | class TafWriter |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | TafWriter( Bu::Stream &sOut ); | 30 | TafWriter( Bu::Stream &sOut ); |
31 | virtual ~TafWriter(); | 31 | virtual ~TafWriter(); |
32 | 32 | ||
33 | void writeGroup( const Bu::TafGroup *pRoot ); | 33 | void writeGroup( const Bu::TafGroup *pRoot ); |
34 | 34 | ||
35 | private: | 35 | private: |
36 | void writeProperty( const Bu::TafProperty *pProp ); | 36 | void writeProperty( const Bu::TafProperty *pProp ); |
37 | void writeComment( const Bu::TafComment *pComment ); | 37 | void writeComment( const Bu::TafComment *pComment ); |
38 | void writeString( const Bu::String &str ); | 38 | void writeString( const Bu::String &str ); |
39 | void ident(); | 39 | void ident(); |
40 | Bu::Stream &sOut; | 40 | Bu::Stream &sOut; |
41 | int iDepth; | 41 | int iDepth; |
42 | }; | 42 | }; |
43 | } | 43 | } |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/tcpserversocket.cpp b/src/stable/tcpserversocket.cpp index 91da199..aed7699 100644 --- a/src/stable/tcpserversocket.cpp +++ b/src/stable/tcpserversocket.cpp | |||
@@ -28,230 +28,230 @@ | |||
28 | namespace Bu { subExceptionDef( TcpServerSocketException ) } | 28 | namespace Bu { subExceptionDef( TcpServerSocketException ) } |
29 | 29 | ||
30 | Bu::TcpServerSocket::TcpServerSocket( int nPort, int nPoolSize ) : | 30 | Bu::TcpServerSocket::TcpServerSocket( int nPort, int nPoolSize ) : |
31 | nPort( nPort ) | 31 | nPort( nPort ) |
32 | { | 32 | { |
33 | #ifdef WIN32 | 33 | #ifdef WIN32 |
34 | Bu::Winsock2::getInstance(); | 34 | Bu::Winsock2::getInstance(); |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | /* Create the socket and set it up to accept connections. */ | 37 | /* Create the socket and set it up to accept connections. */ |
38 | struct sockaddr_in name; | 38 | struct sockaddr_in name; |
39 | 39 | ||
40 | /* Give the socket a name. */ | 40 | /* Give the socket a name. */ |
41 | name.sin_family = AF_INET; | 41 | name.sin_family = AF_INET; |
42 | name.sin_port = bu_htons( nPort ); | 42 | name.sin_port = bu_htons( nPort ); |
43 | 43 | ||
44 | // I think this specifies who we will accept connections from, | 44 | // I think this specifies who we will accept connections from, |
45 | // a good thing to make configurable later on | 45 | // a good thing to make configurable later on |
46 | name.sin_addr.s_addr = bu_htonl( INADDR_ANY ); | 46 | name.sin_addr.s_addr = bu_htonl( INADDR_ANY ); |
47 | 47 | ||
48 | startServer( name, nPoolSize ); | 48 | startServer( name, nPoolSize ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::TcpServerSocket::TcpServerSocket(const String &sAddr,int nPort, int nPoolSize) : | 51 | Bu::TcpServerSocket::TcpServerSocket(const String &sAddr,int nPort, int nPoolSize) : |
52 | nPort( nPort ) | 52 | nPort( nPort ) |
53 | { | 53 | { |
54 | #ifdef WIN32 | 54 | #ifdef WIN32 |
55 | Bu::Winsock2::getInstance(); | 55 | Bu::Winsock2::getInstance(); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | /* Create the socket and set it up to accept connections. */ | 58 | /* Create the socket and set it up to accept connections. */ |
59 | struct sockaddr_in name; | 59 | struct sockaddr_in name; |
60 | 60 | ||
61 | /* Give the socket a name. */ | 61 | /* Give the socket a name. */ |
62 | name.sin_family = AF_INET; | 62 | name.sin_family = AF_INET; |
63 | 63 | ||
64 | name.sin_port = bu_htons( nPort ); | 64 | name.sin_port = bu_htons( nPort ); |
65 | 65 | ||
66 | #ifdef WIN32 | 66 | #ifdef WIN32 |
67 | name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() ); | 67 | name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() ); |
68 | #else | 68 | #else |
69 | inet_aton( sAddr.getStr(), &name.sin_addr ); | 69 | inet_aton( sAddr.getStr(), &name.sin_addr ); |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | startServer( name, nPoolSize ); | 72 | startServer( name, nPoolSize ); |
73 | } | 73 | } |
74 | 74 | ||
75 | Bu::TcpServerSocket::TcpServerSocket( socket_t nServer, bool bInit, int nPoolSize ) : | 75 | Bu::TcpServerSocket::TcpServerSocket( socket_t nServer, bool bInit, int nPoolSize ) : |
76 | nServer( nServer ), | 76 | nServer( nServer ), |
77 | nPort( 0 ) | 77 | nPort( 0 ) |
78 | { | 78 | { |
79 | #ifdef WIN32 | 79 | #ifdef WIN32 |
80 | Bu::Winsock2::getInstance(); | 80 | Bu::Winsock2::getInstance(); |
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | if( bInit ) | 83 | if( bInit ) |
84 | { | 84 | { |
85 | struct sockaddr name; | 85 | struct sockaddr name; |
86 | socklen_t namelen = sizeof(name); | 86 | socklen_t namelen = sizeof(name); |
87 | getpeername( nServer, &name, &namelen ); | 87 | getpeername( nServer, &name, &namelen ); |
88 | 88 | ||
89 | initServer( *((sockaddr_in *)&name), nPoolSize ); | 89 | initServer( *((sockaddr_in *)&name), nPoolSize ); |
90 | } | 90 | } |
91 | else | 91 | else |
92 | { | 92 | { |
93 | FD_ZERO( &fdActive ); | 93 | FD_ZERO( &fdActive ); |
94 | FD_SET( nServer, &fdActive ); | 94 | FD_SET( nServer, &fdActive ); |
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | Bu::TcpServerSocket::TcpServerSocket( const TcpServerSocket &rSrc ) | 98 | Bu::TcpServerSocket::TcpServerSocket( const TcpServerSocket &rSrc ) |
99 | { | 99 | { |
100 | #ifdef WIN32 | 100 | #ifdef WIN32 |
101 | Bu::Winsock2::getInstance(); | 101 | Bu::Winsock2::getInstance(); |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | nServer = dup( rSrc.nServer ); | 104 | nServer = dup( rSrc.nServer ); |
105 | nPort = rSrc.nPort; | 105 | nPort = rSrc.nPort; |
106 | FD_ZERO( &fdActive ); | 106 | FD_ZERO( &fdActive ); |
107 | FD_SET( nServer, &fdActive ); | 107 | FD_SET( nServer, &fdActive ); |
108 | } | 108 | } |
109 | 109 | ||
110 | Bu::TcpServerSocket::~TcpServerSocket() | 110 | Bu::TcpServerSocket::~TcpServerSocket() |
111 | { | 111 | { |
112 | #ifdef WIN32 | 112 | #ifdef WIN32 |
113 | if( nServer != INVALID_SOCKET ) | 113 | if( nServer != INVALID_SOCKET ) |
114 | #else | 114 | #else |
115 | if( nServer > -1 ) | 115 | if( nServer > -1 ) |
116 | #endif | 116 | #endif |
117 | ::close( nServer ); | 117 | ::close( nServer ); |
118 | } | 118 | } |
119 | 119 | ||
120 | void Bu::TcpServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) | 120 | void Bu::TcpServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) |
121 | { | 121 | { |
122 | /* Create the socket. */ | 122 | /* Create the socket. */ |
123 | nServer = bu_socket( PF_INET, SOCK_STREAM, 0 ); | 123 | nServer = bu_socket( PF_INET, SOCK_STREAM, 0 ); |
124 | 124 | ||
125 | #ifdef WIN32 | 125 | #ifdef WIN32 |
126 | if( nServer == INVALID_SOCKET ) | 126 | if( nServer == INVALID_SOCKET ) |
127 | #else | 127 | #else |
128 | if( nServer < 0 ) | 128 | if( nServer < 0 ) |
129 | #endif | 129 | #endif |
130 | { | 130 | { |
131 | throw Bu::TcpServerSocketException("Couldn't create a listen socket."); | 131 | throw Bu::TcpServerSocketException("Couldn't create a listen socket."); |
132 | } | 132 | } |
133 | 133 | ||
134 | int opt = 1; | 134 | int opt = 1; |
135 | bu_setsockopt( | 135 | bu_setsockopt( |
136 | nServer, | 136 | nServer, |
137 | SOL_SOCKET, | 137 | SOL_SOCKET, |
138 | SO_REUSEADDR, | 138 | SO_REUSEADDR, |
139 | (char *)&opt, | 139 | (char *)&opt, |
140 | sizeof( opt ) | 140 | sizeof( opt ) |
141 | ); | 141 | ); |
142 | 142 | ||
143 | initServer( name, nPoolSize ); | 143 | initServer( name, nPoolSize ); |
144 | } | 144 | } |
145 | 145 | ||
146 | void Bu::TcpServerSocket::initServer( struct sockaddr_in &name, int nPoolSize ) | 146 | void Bu::TcpServerSocket::initServer( struct sockaddr_in &name, int nPoolSize ) |
147 | { | 147 | { |
148 | if( bu_bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) | 148 | if( bu_bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) |
149 | { | 149 | { |
150 | throw Bu::TcpServerSocketException("Couldn't bind to the listen socket."); | 150 | throw Bu::TcpServerSocketException("Couldn't bind to the listen socket."); |
151 | } | 151 | } |
152 | 152 | ||
153 | if( bu_listen( nServer, nPoolSize ) < 0 ) | 153 | if( bu_listen( nServer, nPoolSize ) < 0 ) |
154 | { | 154 | { |
155 | throw Bu::TcpServerSocketException( | 155 | throw Bu::TcpServerSocketException( |
156 | "Couldn't begin listening to the server socket." | 156 | "Couldn't begin listening to the server socket." |
157 | ); | 157 | ); |
158 | } | 158 | } |
159 | 159 | ||
160 | FD_ZERO( &fdActive ); | 160 | FD_ZERO( &fdActive ); |
161 | /* Initialize the set of active sockets. */ | 161 | /* Initialize the set of active sockets. */ |
162 | FD_SET( nServer, &fdActive ); | 162 | FD_SET( nServer, &fdActive ); |
163 | } | 163 | } |
164 | 164 | ||
165 | int Bu::TcpServerSocket::getSocket() | 165 | int Bu::TcpServerSocket::getSocket() |
166 | { | 166 | { |
167 | return nServer; | 167 | return nServer; |
168 | } | 168 | } |
169 | 169 | ||
170 | int Bu::TcpServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) | 170 | int Bu::TcpServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) |
171 | { | 171 | { |
172 | fd_set fdRead = fdActive; | 172 | fd_set fdRead = fdActive; |
173 | 173 | ||
174 | struct timeval xT; | 174 | struct timeval xT; |
175 | 175 | ||
176 | xT.tv_sec = nTimeoutSec; | 176 | xT.tv_sec = nTimeoutSec; |
177 | xT.tv_usec = nTimeoutUSec; | 177 | xT.tv_usec = nTimeoutUSec; |
178 | 178 | ||
179 | if( TEMP_FAILURE_RETRY( | 179 | if( TEMP_FAILURE_RETRY( |
180 | bu_select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) | 180 | bu_select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) |
181 | { | 181 | { |
182 | throw Bu::TcpServerSocketException( | 182 | throw Bu::TcpServerSocketException( |
183 | "Error scanning for new connections: %s", strerror( errno ) | 183 | "Error scanning for new connections: %s", strerror( errno ) |
184 | ); | 184 | ); |
185 | } | 185 | } |
186 | 186 | ||
187 | if( FD_ISSET( nServer, &fdRead ) ) | 187 | if( FD_ISSET( nServer, &fdRead ) ) |
188 | { | 188 | { |
189 | struct sockaddr_in clientname; | 189 | struct sockaddr_in clientname; |
190 | socklen_t size; | 190 | socklen_t size; |
191 | int nClient; | 191 | int nClient; |
192 | 192 | ||
193 | size = sizeof( clientname ); | 193 | size = sizeof( clientname ); |
194 | #ifdef WIN32 | 194 | #ifdef WIN32 |
195 | nClient = bu_accept( nServer, (struct sockaddr *)&clientname, &size); | 195 | nClient = bu_accept( nServer, (struct sockaddr *)&clientname, &size); |
196 | #else /* not-WIN32 */ | 196 | #else /* not-WIN32 */ |
197 | #ifdef __CYGWIN__ | 197 | #ifdef __CYGWIN__ |
198 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, | 198 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, |
199 | (int *)&size | 199 | (int *)&size |
200 | ); | 200 | ); |
201 | #else /* not-cygwin */ | 201 | #else /* not-cygwin */ |
202 | #ifdef __APPLE__ | 202 | #ifdef __APPLE__ |
203 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, (socklen_t*)&size ); | 203 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, (socklen_t*)&size ); |
204 | #else /* linux */ | 204 | #else /* linux */ |
205 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); | 205 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); |
206 | #endif /* __APPLE__ */ | 206 | #endif /* __APPLE__ */ |
207 | #endif /* __CYGWIN__ */ | 207 | #endif /* __CYGWIN__ */ |
208 | #endif /* WIN32 */ | 208 | #endif /* WIN32 */ |
209 | if( nClient < 0 ) | 209 | if( nClient < 0 ) |
210 | { | 210 | { |
211 | throw Bu::TcpServerSocketException( | 211 | throw Bu::TcpServerSocketException( |
212 | "Error accepting a new connection: %s", strerror( errno ) | 212 | "Error accepting a new connection: %s", strerror( errno ) |
213 | ); | 213 | ); |
214 | } | 214 | } |
215 | 215 | ||
216 | #ifndef WIN32 | 216 | #ifndef WIN32 |
217 | char tmpa[20]; | 217 | char tmpa[20]; |
218 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); | 218 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); |
219 | //"New connection from host %s, port %hd.", | 219 | //"New connection from host %s, port %hd.", |
220 | // tmpa, ntohs (clientname.sin_port) ); | 220 | // tmpa, ntohs (clientname.sin_port) ); |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | { | 223 | { |
224 | #ifndef WIN32 | 224 | #ifndef WIN32 |
225 | int flags; | 225 | int flags; |
226 | flags = fcntl( nClient, F_GETFL, 0 ); | 226 | flags = fcntl( nClient, F_GETFL, 0 ); |
227 | flags |= O_NONBLOCK; | 227 | flags |= O_NONBLOCK; |
228 | if( fcntl( nClient, F_SETFL, flags ) < 0) | 228 | if( fcntl( nClient, F_SETFL, flags ) < 0) |
229 | { | 229 | { |
230 | throw Bu::TcpServerSocketException( | 230 | throw Bu::TcpServerSocketException( |
231 | "Error setting option on client socket: %s", | 231 | "Error setting option on client socket: %s", |
232 | strerror( errno ) | 232 | strerror( errno ) |
233 | ); | 233 | ); |
234 | } | 234 | } |
235 | #else | 235 | #else |
236 | //------------------------- | 236 | //------------------------- |
237 | // Set the socket I/O mode: In this case FIONBIO | 237 | // Set the socket I/O mode: In this case FIONBIO |
238 | // enables or disables the blocking mode for the | 238 | // enables or disables the blocking mode for the |
239 | // socket based on the numerical value of iMode. | 239 | // socket based on the numerical value of iMode. |
240 | // If iMode = 0, blocking is enabled; | 240 | // If iMode = 0, blocking is enabled; |
241 | // If iMode != 0, non-blocking mode is enabled. | 241 | // If iMode != 0, non-blocking mode is enabled. |
242 | u_long iMode = 1; | 242 | u_long iMode = 1; |
243 | bu_ioctlsocket(nClient, FIONBIO, &iMode); | 243 | bu_ioctlsocket(nClient, FIONBIO, &iMode); |
244 | #endif | 244 | #endif |
245 | } | 245 | } |
246 | 246 | ||
247 | return nClient; | 247 | return nClient; |
248 | } | 248 | } |
249 | 249 | ||
250 | return -1; | 250 | return -1; |
251 | } | 251 | } |
252 | 252 | ||
253 | int Bu::TcpServerSocket::getPort() | 253 | int Bu::TcpServerSocket::getPort() |
254 | { | 254 | { |
255 | return nPort; | 255 | return nPort; |
256 | } | 256 | } |
257 | 257 | ||
diff --git a/src/stable/tcpserversocket.h b/src/stable/tcpserversocket.h index 9776668..fd1d547 100644 --- a/src/stable/tcpserversocket.h +++ b/src/stable/tcpserversocket.h | |||
@@ -20,46 +20,46 @@ | |||
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | subExceptionDecl( TcpServerSocketException ); | 23 | subExceptionDecl( TcpServerSocketException ); |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * A single tcp/ip server socket. When created the server socket will bind | 26 | * A single tcp/ip server socket. When created the server socket will bind |
27 | * to the specified interface and port, and immediately begin listening for | 27 | * to the specified interface and port, and immediately begin listening for |
28 | * connections. When connections come in they are pooled by the networking | 28 | * connections. When connections come in they are pooled by the networking |
29 | * drivers in the kernel until they are accepted, this means that failure | 29 | * drivers in the kernel until they are accepted, this means that failure |
30 | * to keep space in the connection pool will result in connection refusals. | 30 | * to keep space in the connection pool will result in connection refusals. |
31 | * | 31 | * |
32 | * Although the accept function returns an integral file descriptor, it is | 32 | * Although the accept function returns an integral file descriptor, it is |
33 | * designed to be used with the Socket class. | 33 | * designed to be used with the Socket class. |
34 | * | 34 | * |
35 | *@ingroup Serving | 35 | *@ingroup Serving |
36 | */ | 36 | */ |
37 | class TcpServerSocket | 37 | class TcpServerSocket |
38 | { | 38 | { |
39 | public: | 39 | public: |
40 | #ifdef WIN32 | 40 | #ifdef WIN32 |
41 | typedef unsigned int socket_t; | 41 | typedef unsigned int socket_t; |
42 | #else | 42 | #else |
43 | typedef int socket_t; | 43 | typedef int socket_t; |
44 | #endif | 44 | #endif |
45 | TcpServerSocket( int nPort, int nPoolSize=40 ); | 45 | TcpServerSocket( int nPort, int nPoolSize=40 ); |
46 | TcpServerSocket( const String &sAddr, int nPort, int nPoolSize=40 ); | 46 | TcpServerSocket( const String &sAddr, int nPort, int nPoolSize=40 ); |
47 | TcpServerSocket( socket_t nSocket, bool bInit, int nPoolSize=40 ); | 47 | TcpServerSocket( socket_t nSocket, bool bInit, int nPoolSize=40 ); |
48 | TcpServerSocket( const TcpServerSocket &rSrc ); | 48 | TcpServerSocket( const TcpServerSocket &rSrc ); |
49 | virtual ~TcpServerSocket(); | 49 | virtual ~TcpServerSocket(); |
50 | 50 | ||
51 | int accept( int nTimeoutSec=0, int nTimeoutUSec=0 ); | 51 | int accept( int nTimeoutSec=0, int nTimeoutUSec=0 ); |
52 | int getSocket(); | 52 | int getSocket(); |
53 | int getPort(); | 53 | int getPort(); |
54 | 54 | ||
55 | private: | 55 | private: |
56 | void startServer( struct sockaddr_in &name, int nPoolSize ); | 56 | void startServer( struct sockaddr_in &name, int nPoolSize ); |
57 | void initServer( struct sockaddr_in &name, int nPoolSize ); | 57 | void initServer( struct sockaddr_in &name, int nPoolSize ); |
58 | 58 | ||
59 | fd_set fdActive; | 59 | fd_set fdActive; |
60 | socket_t nServer; | 60 | socket_t nServer; |
61 | int nPort; | 61 | int nPort; |
62 | }; | 62 | }; |
63 | } | 63 | } |
64 | 64 | ||
65 | #endif | 65 | #endif |
diff --git a/src/stable/tcpsocket.cpp b/src/stable/tcpsocket.cpp index fa79a36..b77f439 100644 --- a/src/stable/tcpsocket.cpp +++ b/src/stable/tcpsocket.cpp | |||
@@ -32,392 +32,392 @@ | |||
32 | namespace Bu { subExceptionDef( TcpSocketException ) } | 32 | namespace Bu { subExceptionDef( TcpSocketException ) } |
33 | 33 | ||
34 | Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : | 34 | Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : |
35 | nTcpSocket( nTcpSocket ), | 35 | nTcpSocket( nTcpSocket ), |
36 | bActive( true ), | 36 | bActive( true ), |
37 | bBlocking( true ) | 37 | bBlocking( true ) |
38 | { | 38 | { |
39 | #ifdef WIN32 | 39 | #ifdef WIN32 |
40 | Bu::Winsock2::getInstance(); | 40 | Bu::Winsock2::getInstance(); |
41 | #endif | 41 | #endif |
42 | setAddress(); | 42 | setAddress(); |
43 | } | 43 | } |
44 | 44 | ||
45 | Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, | 45 | Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, |
46 | bool bBlocking ) : | 46 | bool bBlocking ) : |
47 | nTcpSocket( 0 ), | 47 | nTcpSocket( 0 ), |
48 | bActive( false ), | 48 | bActive( false ), |
49 | bBlocking( true ) | 49 | bBlocking( true ) |
50 | { | 50 | { |
51 | #ifdef WIN32 | 51 | #ifdef WIN32 |
52 | Bu::Winsock2::getInstance(); | 52 | Bu::Winsock2::getInstance(); |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* Create the socket. */ | 55 | /* Create the socket. */ |
56 | nTcpSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); | 56 | nTcpSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); |
57 | 57 | ||
58 | #ifdef WIN32 | 58 | #ifdef WIN32 |
59 | if( nTcpSocket == INVALID_SOCKET ) | 59 | if( nTcpSocket == INVALID_SOCKET ) |
60 | #else | 60 | #else |
61 | if( nTcpSocket < 0 ) | 61 | if( nTcpSocket < 0 ) |
62 | #endif | 62 | #endif |
63 | { | 63 | { |
64 | throw ExceptionBase("Couldn't create socket.\n"); | 64 | throw ExceptionBase("Couldn't create socket.\n"); |
65 | } | 65 | } |
66 | 66 | ||
67 | setBlocking( false ); | 67 | setBlocking( false ); |
68 | 68 | ||
69 | /* Connect to the server. */ | 69 | /* Connect to the server. */ |
70 | //printf("Resolving hostname (%s)...\n", sAddr ); | 70 | //printf("Resolving hostname (%s)...\n", sAddr ); |
71 | { | 71 | { |
72 | struct addrinfo *pAddr = NULL; | 72 | struct addrinfo *pAddr = NULL; |
73 | struct addrinfo aiHints; | 73 | struct addrinfo aiHints; |
74 | memset( &aiHints, 0, sizeof(addrinfo) ); | 74 | memset( &aiHints, 0, sizeof(addrinfo) ); |
75 | aiHints.ai_flags = AI_CANONNAME; | 75 | aiHints.ai_flags = AI_CANONNAME; |
76 | aiHints.ai_family = AF_INET; | 76 | aiHints.ai_family = AF_INET; |
77 | aiHints.ai_socktype = SOCK_STREAM; | 77 | aiHints.ai_socktype = SOCK_STREAM; |
78 | char ibuf[10]; | 78 | char ibuf[10]; |
79 | sprintf( ibuf, "%d", nPort ); | 79 | sprintf( ibuf, "%d", nPort ); |
80 | 80 | ||
81 | int ret; | 81 | int ret; |
82 | if( (ret = bu_getaddrinfo( | 82 | if( (ret = bu_getaddrinfo( |
83 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) | 83 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) |
84 | { | 84 | { |
85 | close(); | 85 | close(); |
86 | throw Bu::TcpSocketException("Couldn't resolve hostname %s (%s).\n", | 86 | throw Bu::TcpSocketException("Couldn't resolve hostname %s (%s).\n", |
87 | sAddr.getStr(), bu_gai_strerror(ret)); | 87 | sAddr.getStr(), bu_gai_strerror(ret)); |
88 | } | 88 | } |
89 | 89 | ||
90 | bu_connect( | 90 | bu_connect( |
91 | nTcpSocket, | 91 | nTcpSocket, |
92 | pAddr->ai_addr, | 92 | pAddr->ai_addr, |
93 | pAddr->ai_addrlen | 93 | pAddr->ai_addrlen |
94 | ); | 94 | ); |
95 | 95 | ||
96 | sAddress = pAddr->ai_canonname; | 96 | sAddress = pAddr->ai_canonname; |
97 | 97 | ||
98 | bu_freeaddrinfo( pAddr ); | 98 | bu_freeaddrinfo( pAddr ); |
99 | } | 99 | } |
100 | 100 | ||
101 | bActive = true; | 101 | bActive = true; |
102 | 102 | ||
103 | if( nTimeout > 0 ) | 103 | if( nTimeout > 0 ) |
104 | { | 104 | { |
105 | fd_set rfds, wfds, efds; | 105 | fd_set rfds, wfds, efds; |
106 | int retval; | 106 | int retval; |
107 | 107 | ||
108 | FD_ZERO(&rfds); | 108 | FD_ZERO(&rfds); |
109 | FD_SET(nTcpSocket, &rfds); | 109 | FD_SET(nTcpSocket, &rfds); |
110 | FD_ZERO(&wfds); | 110 | FD_ZERO(&wfds); |
111 | FD_SET(nTcpSocket, &wfds); | 111 | FD_SET(nTcpSocket, &wfds); |
112 | FD_ZERO(&efds); | 112 | FD_ZERO(&efds); |
113 | FD_SET(nTcpSocket, &efds); | 113 | FD_SET(nTcpSocket, &efds); |
114 | 114 | ||
115 | struct timeval tv; | 115 | struct timeval tv; |
116 | tv.tv_sec = nTimeout; | 116 | tv.tv_sec = nTimeout; |
117 | tv.tv_usec = 0; | 117 | tv.tv_usec = 0; |
118 | 118 | ||
119 | retval = bu_select( nTcpSocket+1, &rfds, &wfds, &efds, &tv ); | 119 | retval = bu_select( nTcpSocket+1, &rfds, &wfds, &efds, &tv ); |
120 | 120 | ||
121 | if( retval == 0 ) | 121 | if( retval == 0 ) |
122 | { | 122 | { |
123 | close(); | 123 | close(); |
124 | throw ExceptionBase("Connection timeout.\n"); | 124 | throw ExceptionBase("Connection timeout.\n"); |
125 | } | 125 | } |
126 | read( NULL, 0 ); // See if we can get any errors out of the way early. | 126 | read( NULL, 0 ); // See if we can get any errors out of the way early. |
127 | } | 127 | } |
128 | 128 | ||
129 | if( bBlocking ) | 129 | if( bBlocking ) |
130 | setBlocking( bBlocking ); | 130 | setBlocking( bBlocking ); |
131 | } | 131 | } |
132 | 132 | ||
133 | Bu::TcpSocket::~TcpSocket() | 133 | Bu::TcpSocket::~TcpSocket() |
134 | { | 134 | { |
135 | close(); | 135 | close(); |
136 | } | 136 | } |
137 | 137 | ||
138 | void Bu::TcpSocket::close() | 138 | void Bu::TcpSocket::close() |
139 | { | 139 | { |
140 | if( bActive ) | 140 | if( bActive ) |
141 | { | 141 | { |
142 | #ifndef WIN32 | 142 | #ifndef WIN32 |
143 | fsync( nTcpSocket ); | 143 | fsync( nTcpSocket ); |
144 | #endif | 144 | #endif |
145 | #ifdef WIN32 | 145 | #ifdef WIN32 |
146 | #ifndef SHUT_RDWR | 146 | #ifndef SHUT_RDWR |
147 | #define SHUT_RDWR (SD_BOTH) | 147 | #define SHUT_RDWR (SD_BOTH) |
148 | #endif | 148 | #endif |
149 | #endif | 149 | #endif |
150 | bu_shutdown( nTcpSocket, SHUT_RDWR ); | 150 | bu_shutdown( nTcpSocket, SHUT_RDWR ); |
151 | ::close( nTcpSocket ); | 151 | ::close( nTcpSocket ); |
152 | } | 152 | } |
153 | bActive = false; | 153 | bActive = false; |
154 | } | 154 | } |
155 | 155 | ||
156 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) | 156 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) |
157 | { | 157 | { |
158 | fd_set rfds; | 158 | fd_set rfds; |
159 | FD_ZERO(&rfds); | 159 | FD_ZERO(&rfds); |
160 | FD_SET(nTcpSocket, &rfds); | 160 | FD_SET(nTcpSocket, &rfds); |
161 | struct timeval tv = {0, 0}; | 161 | struct timeval tv = {0, 0}; |
162 | if( bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) | 162 | if( bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) |
163 | { | 163 | { |
164 | int iErr = errno; | 164 | int iErr = errno; |
165 | close(); | 165 | close(); |
166 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | 166 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); |
167 | } | 167 | } |
168 | if( FD_ISSET( nTcpSocket, &rfds ) || bBlocking ) | 168 | if( FD_ISSET( nTcpSocket, &rfds ) || bBlocking ) |
169 | { | 169 | { |
170 | int nRead = TEMP_FAILURE_RETRY( | 170 | int nRead = TEMP_FAILURE_RETRY( |
171 | bu_recv( nTcpSocket, (char *) pBuf, nBytes, 0 ) ); | 171 | bu_recv( nTcpSocket, (char *) pBuf, nBytes, 0 ) ); |
172 | if( nRead == 0 && nBytes > 0 ) | 172 | if( nRead == 0 && nBytes > 0 ) |
173 | { | 173 | { |
174 | close(); | 174 | close(); |
175 | throw TcpSocketException( TcpSocketException::cClosed, "TcpSocket closed."); | 175 | throw TcpSocketException( TcpSocketException::cClosed, "TcpSocket closed."); |
176 | } | 176 | } |
177 | if( nRead < 0 ) | 177 | if( nRead < 0 ) |
178 | { | 178 | { |
179 | #ifdef WIN32 | 179 | #ifdef WIN32 |
180 | int iWSAError = bu_WSAGetLastError(); | 180 | int iWSAError = bu_WSAGetLastError(); |
181 | if( iWSAError == WSAEWOULDBLOCK ) | 181 | if( iWSAError == WSAEWOULDBLOCK ) |
182 | return 0; | 182 | return 0; |
183 | #else | 183 | #else |
184 | if( errno == ENETRESET || errno == ECONNRESET ) | 184 | if( errno == ENETRESET || errno == ECONNRESET ) |
185 | { | 185 | { |
186 | close(); | 186 | close(); |
187 | throw TcpSocketException( TcpSocketException::cClosed, | 187 | throw TcpSocketException( TcpSocketException::cClosed, |
188 | strerror(errno) ); | 188 | strerror(errno) ); |
189 | } | 189 | } |
190 | if( errno == EAGAIN ) | 190 | if( errno == EAGAIN ) |
191 | return 0; | 191 | return 0; |
192 | int iErr = errno; | 192 | int iErr = errno; |
193 | close(); | 193 | close(); |
194 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | 194 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); |
195 | #endif | 195 | #endif |
196 | } | 196 | } |
197 | return nRead; | 197 | return nRead; |
198 | } | 198 | } |
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | 201 | ||
202 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, | 202 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, |
203 | uint32_t nSec, uint32_t nUSec ) | 203 | uint32_t nSec, uint32_t nUSec ) |
204 | { | 204 | { |
205 | struct timeval tv; | 205 | struct timeval tv; |
206 | Bu::size nRead = 0; | 206 | Bu::size nRead = 0; |
207 | 207 | ||
208 | fd_set rfds; | 208 | fd_set rfds; |
209 | FD_ZERO(&rfds); | 209 | FD_ZERO(&rfds); |
210 | FD_SET(nTcpSocket, &rfds); | 210 | FD_SET(nTcpSocket, &rfds); |
211 | 211 | ||
212 | #ifdef WIN32 | 212 | #ifdef WIN32 |
213 | DWORD dwStart = GetTickCount(); | 213 | DWORD dwStart = GetTickCount(); |
214 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | 214 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); |
215 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | 215 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; |
216 | #else | 216 | #else |
217 | struct timeval nt, ct; | 217 | struct timeval nt, ct; |
218 | gettimeofday( &nt, NULL ); | 218 | gettimeofday( &nt, NULL ); |
219 | nt.tv_sec += nSec; | 219 | nt.tv_sec += nSec; |
220 | nt.tv_usec += nUSec; | 220 | nt.tv_usec += nUSec; |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | for(;;) | 223 | for(;;) |
224 | { | 224 | { |
225 | tv.tv_sec = nSec; | 225 | tv.tv_sec = nSec; |
226 | tv.tv_usec = nUSec; | 226 | tv.tv_usec = nUSec; |
227 | bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | 227 | bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); |
228 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); | 228 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); |
229 | if( nRead >= nBytes ) | 229 | if( nRead >= nBytes ) |
230 | break; | 230 | break; |
231 | #ifdef WIN32 | 231 | #ifdef WIN32 |
232 | DWORD dwNow = GetTickCount(); | 232 | DWORD dwNow = GetTickCount(); |
233 | if( dwNow > dwEnd ) | 233 | if( dwNow > dwEnd ) |
234 | break; | 234 | break; |
235 | #else | 235 | #else |
236 | gettimeofday( &ct, NULL ); | 236 | gettimeofday( &ct, NULL ); |
237 | if( (ct.tv_sec > nt.tv_sec) || | 237 | if( (ct.tv_sec > nt.tv_sec) || |
238 | (ct.tv_sec == nt.tv_sec && | 238 | (ct.tv_sec == nt.tv_sec && |
239 | ct.tv_usec >= nt.tv_usec) ) | 239 | ct.tv_usec >= nt.tv_usec) ) |
240 | break; | 240 | break; |
241 | #endif | 241 | #endif |
242 | } | 242 | } |
243 | return nRead; | 243 | return nRead; |
244 | } | 244 | } |
245 | 245 | ||
246 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) | 246 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) |
247 | { | 247 | { |
248 | //#ifdef WIN32 | 248 | //#ifdef WIN32 |
249 | int nWrote = TEMP_FAILURE_RETRY( | 249 | int nWrote = TEMP_FAILURE_RETRY( |
250 | bu_send( nTcpSocket, (const char *) pBuf, nBytes, 0 ) ); | 250 | bu_send( nTcpSocket, (const char *) pBuf, nBytes, 0 ) ); |
251 | //#else | 251 | //#else |
252 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nTcpSocket, pBuf, nBytes ) ); | 252 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nTcpSocket, pBuf, nBytes ) ); |
253 | //#endif | 253 | //#endif |
254 | if( nWrote < 0 ) | 254 | if( nWrote < 0 ) |
255 | { | 255 | { |
256 | #ifdef WIN32 | 256 | #ifdef WIN32 |
257 | int iWSAError = bu_WSAGetLastError(); | 257 | int iWSAError = bu_WSAGetLastError(); |
258 | if( iWSAError == WSAEWOULDBLOCK ) | 258 | if( iWSAError == WSAEWOULDBLOCK ) |
259 | return 0; | 259 | return 0; |
260 | #else | 260 | #else |
261 | if( errno == EAGAIN ) return 0; | 261 | if( errno == EAGAIN ) return 0; |
262 | #endif | 262 | #endif |
263 | throw TcpSocketException( TcpSocketException::cWrite, strerror(errno) ); | 263 | throw TcpSocketException( TcpSocketException::cWrite, strerror(errno) ); |
264 | } | 264 | } |
265 | return nWrote; | 265 | return nWrote; |
266 | } | 266 | } |
267 | 267 | ||
268 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) | 268 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) |
269 | { | 269 | { |
270 | struct timeval tv; | 270 | struct timeval tv; |
271 | Bu::size nWrote = 0; | 271 | Bu::size nWrote = 0; |
272 | 272 | ||
273 | fd_set wfds; | 273 | fd_set wfds; |
274 | FD_ZERO(&wfds); | 274 | FD_ZERO(&wfds); |
275 | FD_SET(nTcpSocket, &wfds); | 275 | FD_SET(nTcpSocket, &wfds); |
276 | 276 | ||
277 | #ifdef WIN32 | 277 | #ifdef WIN32 |
278 | DWORD dwStart = GetTickCount(); | 278 | DWORD dwStart = GetTickCount(); |
279 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | 279 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); |
280 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | 280 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; |
281 | #else | 281 | #else |
282 | struct timeval nt, ct; | 282 | struct timeval nt, ct; |
283 | gettimeofday( &nt, NULL ); | 283 | gettimeofday( &nt, NULL ); |
284 | nt.tv_sec += nSec; | 284 | nt.tv_sec += nSec; |
285 | nt.tv_usec += nUSec; | 285 | nt.tv_usec += nUSec; |
286 | #endif | 286 | #endif |
287 | 287 | ||
288 | for(;;) | 288 | for(;;) |
289 | { | 289 | { |
290 | tv.tv_sec = nSec; | 290 | tv.tv_sec = nSec; |
291 | tv.tv_usec = nUSec; | 291 | tv.tv_usec = nUSec; |
292 | bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | 292 | bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); |
293 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); | 293 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); |
294 | if( nWrote >= nBytes ) | 294 | if( nWrote >= nBytes ) |
295 | break; | 295 | break; |
296 | #ifdef WIN32 | 296 | #ifdef WIN32 |
297 | DWORD dwNow = GetTickCount(); | 297 | DWORD dwNow = GetTickCount(); |
298 | if( dwNow > dwEnd ) | 298 | if( dwNow > dwEnd ) |
299 | break; | 299 | break; |
300 | #else | 300 | #else |
301 | gettimeofday( &ct, NULL ); | 301 | gettimeofday( &ct, NULL ); |
302 | if( (ct.tv_sec > nt.tv_sec) || | 302 | if( (ct.tv_sec > nt.tv_sec) || |
303 | (ct.tv_sec == nt.tv_sec && | 303 | (ct.tv_sec == nt.tv_sec && |
304 | ct.tv_usec >= nt.tv_usec) ) | 304 | ct.tv_usec >= nt.tv_usec) ) |
305 | break; | 305 | break; |
306 | #endif | 306 | #endif |
307 | } | 307 | } |
308 | return nWrote; | 308 | return nWrote; |
309 | } | 309 | } |
310 | 310 | ||
311 | Bu::size Bu::TcpSocket::tell() | 311 | Bu::size Bu::TcpSocket::tell() |
312 | { | 312 | { |
313 | throw UnsupportedException(); | 313 | throw UnsupportedException(); |
314 | } | 314 | } |
315 | 315 | ||
316 | void Bu::TcpSocket::seek( Bu::size ) | 316 | void Bu::TcpSocket::seek( Bu::size ) |
317 | { | 317 | { |
318 | throw UnsupportedException(); | 318 | throw UnsupportedException(); |
319 | } | 319 | } |
320 | 320 | ||
321 | void Bu::TcpSocket::setPos( Bu::size ) | 321 | void Bu::TcpSocket::setPos( Bu::size ) |
322 | { | 322 | { |
323 | throw UnsupportedException(); | 323 | throw UnsupportedException(); |
324 | } | 324 | } |
325 | 325 | ||
326 | void Bu::TcpSocket::setPosEnd( Bu::size ) | 326 | void Bu::TcpSocket::setPosEnd( Bu::size ) |
327 | { | 327 | { |
328 | throw UnsupportedException(); | 328 | throw UnsupportedException(); |
329 | } | 329 | } |
330 | 330 | ||
331 | bool Bu::TcpSocket::isEos() | 331 | bool Bu::TcpSocket::isEos() |
332 | { | 332 | { |
333 | return !bActive; | 333 | return !bActive; |
334 | } | 334 | } |
335 | 335 | ||
336 | bool Bu::TcpSocket::canRead() | 336 | bool Bu::TcpSocket::canRead() |
337 | { | 337 | { |
338 | fd_set rfds; | 338 | fd_set rfds; |
339 | FD_ZERO(&rfds); | 339 | FD_ZERO(&rfds); |
340 | FD_SET(nTcpSocket, &rfds); | 340 | FD_SET(nTcpSocket, &rfds); |
341 | struct timeval tv = { 0, 0 }; | 341 | struct timeval tv = { 0, 0 }; |
342 | int retval = bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | 342 | int retval = bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); |
343 | if( retval == -1 ) | 343 | if( retval == -1 ) |
344 | throw TcpSocketException( | 344 | throw TcpSocketException( |
345 | TcpSocketException::cBadRead, | 345 | TcpSocketException::cBadRead, |
346 | "Bad Read error" | 346 | "Bad Read error" |
347 | ); | 347 | ); |
348 | 348 | ||
349 | if( !FD_ISSET( nTcpSocket, &rfds ) ) | 349 | if( !FD_ISSET( nTcpSocket, &rfds ) ) |
350 | return false; | 350 | return false; |
351 | return true; | 351 | return true; |
352 | } | 352 | } |
353 | 353 | ||
354 | bool Bu::TcpSocket::canWrite() | 354 | bool Bu::TcpSocket::canWrite() |
355 | { | 355 | { |
356 | fd_set wfds; | 356 | fd_set wfds; |
357 | FD_ZERO(&wfds); | 357 | FD_ZERO(&wfds); |
358 | FD_SET(nTcpSocket, &wfds); | 358 | FD_SET(nTcpSocket, &wfds); |
359 | struct timeval tv = { 0, 0 }; | 359 | struct timeval tv = { 0, 0 }; |
360 | int retval = bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | 360 | int retval = bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); |
361 | if( retval == -1 ) | 361 | if( retval == -1 ) |
362 | throw TcpSocketException( | 362 | throw TcpSocketException( |
363 | TcpSocketException::cBadRead, | 363 | TcpSocketException::cBadRead, |
364 | "Bad Read error" | 364 | "Bad Read error" |
365 | ); | 365 | ); |
366 | if( !FD_ISSET( nTcpSocket, &wfds ) ) | 366 | if( !FD_ISSET( nTcpSocket, &wfds ) ) |
367 | return false; | 367 | return false; |
368 | return true; | 368 | return true; |
369 | } | 369 | } |
370 | 370 | ||
371 | bool Bu::TcpSocket::isReadable() | 371 | bool Bu::TcpSocket::isReadable() |
372 | { | 372 | { |
373 | return true; | 373 | return true; |
374 | } | 374 | } |
375 | 375 | ||
376 | bool Bu::TcpSocket::isWritable() | 376 | bool Bu::TcpSocket::isWritable() |
377 | { | 377 | { |
378 | return true; | 378 | return true; |
379 | } | 379 | } |
380 | 380 | ||
381 | bool Bu::TcpSocket::isSeekable() | 381 | bool Bu::TcpSocket::isSeekable() |
382 | { | 382 | { |
383 | return false; | 383 | return false; |
384 | } | 384 | } |
385 | 385 | ||
386 | bool Bu::TcpSocket::isBlocking() | 386 | bool Bu::TcpSocket::isBlocking() |
387 | { | 387 | { |
388 | #ifndef WIN32 | 388 | #ifndef WIN32 |
389 | return ((fcntl( nTcpSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK); | 389 | return ((fcntl( nTcpSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK); |
390 | #else | 390 | #else |
391 | return false; | 391 | return false; |
392 | #endif | 392 | #endif |
393 | } | 393 | } |
394 | 394 | ||
395 | void Bu::TcpSocket::setBlocking( bool bBlocking ) | 395 | void Bu::TcpSocket::setBlocking( bool bBlocking ) |
396 | { | 396 | { |
397 | this->bBlocking = bBlocking; | 397 | this->bBlocking = bBlocking; |
398 | #ifndef WIN32 | 398 | #ifndef WIN32 |
399 | if( bBlocking ) | 399 | if( bBlocking ) |
400 | { | 400 | { |
401 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); | 401 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); |
402 | } | 402 | } |
403 | else | 403 | else |
404 | { | 404 | { |
405 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); | 405 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); |
406 | } | 406 | } |
407 | #else | 407 | #else |
408 | u_long iMode; | 408 | u_long iMode; |
409 | if( bBlocking ) | 409 | if( bBlocking ) |
410 | iMode = 0; | 410 | iMode = 0; |
411 | else | 411 | else |
412 | iMode = 1; | 412 | iMode = 1; |
413 | //------------------------- | 413 | //------------------------- |
414 | // Set the socket I/O mode: In this case FIONBIO | 414 | // Set the socket I/O mode: In this case FIONBIO |
415 | // enables or disables the blocking mode for the | 415 | // enables or disables the blocking mode for the |
416 | // socket based on the numerical value of iMode. | 416 | // socket based on the numerical value of iMode. |
417 | // If iMode = 0, blocking is enabled; | 417 | // If iMode = 0, blocking is enabled; |
418 | // If iMode != 0, non-blocking mode is enabled. | 418 | // If iMode != 0, non-blocking mode is enabled. |
419 | bu_ioctlsocket(nTcpSocket, FIONBIO, &iMode); | 419 | bu_ioctlsocket(nTcpSocket, FIONBIO, &iMode); |
420 | #endif | 420 | #endif |
421 | } | 421 | } |
422 | 422 | ||
423 | void Bu::TcpSocket::setSize( Bu::size ) | 423 | void Bu::TcpSocket::setSize( Bu::size ) |
@@ -430,53 +430,53 @@ void Bu::TcpSocket::flush() | |||
430 | 430 | ||
431 | bool Bu::TcpSocket::isOpen() | 431 | bool Bu::TcpSocket::isOpen() |
432 | { | 432 | { |
433 | return bActive; | 433 | return bActive; |
434 | } | 434 | } |
435 | 435 | ||
436 | void Bu::TcpSocket::setAddress() | 436 | void Bu::TcpSocket::setAddress() |
437 | { | 437 | { |
438 | struct sockaddr_in addr; | 438 | struct sockaddr_in addr; |
439 | socklen_t len = sizeof(addr); | 439 | socklen_t len = sizeof(addr); |
440 | addr.sin_family = AF_INET; | 440 | addr.sin_family = AF_INET; |
441 | bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); | 441 | bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); |
442 | sAddress = bu_inet_ntoa( addr.sin_addr ); | 442 | sAddress = bu_inet_ntoa( addr.sin_addr ); |
443 | } | 443 | } |
444 | 444 | ||
445 | Bu::String Bu::TcpSocket::getAddress() const | 445 | Bu::String Bu::TcpSocket::getAddress() const |
446 | { | 446 | { |
447 | return sAddress; | 447 | return sAddress; |
448 | } | 448 | } |
449 | 449 | ||
450 | Bu::TcpSocket::operator Bu::TcpSocket::handle() const | 450 | Bu::TcpSocket::operator Bu::TcpSocket::handle() const |
451 | { | 451 | { |
452 | return nTcpSocket; | 452 | return nTcpSocket; |
453 | } | 453 | } |
454 | 454 | ||
455 | Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const | 455 | Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const |
456 | { | 456 | { |
457 | return nTcpSocket; | 457 | return nTcpSocket; |
458 | } | 458 | } |
459 | 459 | ||
460 | Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() | 460 | Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() |
461 | { | 461 | { |
462 | handle nRet = nTcpSocket; | 462 | handle nRet = nTcpSocket; |
463 | bActive = false; | 463 | bActive = false; |
464 | nTcpSocket = 0; | 464 | nTcpSocket = 0; |
465 | return nRet; | 465 | return nRet; |
466 | } | 466 | } |
467 | 467 | ||
468 | Bu::size Bu::TcpSocket::getSize() const | 468 | Bu::size Bu::TcpSocket::getSize() const |
469 | { | 469 | { |
470 | throw UnsupportedException(); | 470 | throw UnsupportedException(); |
471 | } | 471 | } |
472 | 472 | ||
473 | Bu::size Bu::TcpSocket::getBlockSize() const | 473 | Bu::size Bu::TcpSocket::getBlockSize() const |
474 | { | 474 | { |
475 | return 1500; //TODO: Fix this, it's stupid. | 475 | return 1500; //TODO: Fix this, it's stupid. |
476 | } | 476 | } |
477 | 477 | ||
478 | Bu::String Bu::TcpSocket::getLocation() const | 478 | Bu::String Bu::TcpSocket::getLocation() const |
479 | { | 479 | { |
480 | return getAddress(); | 480 | return getAddress(); |
481 | } | 481 | } |
482 | 482 | ||
diff --git a/src/stable/tcpsocket.h b/src/stable/tcpsocket.h index 92b3c1f..16eca12 100644 --- a/src/stable/tcpsocket.h +++ b/src/stable/tcpsocket.h | |||
@@ -17,110 +17,110 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDeclBegin( TcpSocketException ); | 20 | subExceptionDeclBegin( TcpSocketException ); |
21 | enum { | 21 | enum { |
22 | cRead, | 22 | cRead, |
23 | cWrite, | 23 | cWrite, |
24 | cBadRead, | 24 | cBadRead, |
25 | cClosed, | 25 | cClosed, |
26 | cTimeout | 26 | cTimeout |
27 | }; | 27 | }; |
28 | subExceptionDeclEnd(); | 28 | subExceptionDeclEnd(); |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Network socket stream class. This class provides a mechanism for | 31 | * Network socket stream class. This class provides a mechanism for |
32 | * communicating over a network using TCP/IP. It will provide other low | 32 | * communicating over a network using TCP/IP. It will provide other low |
33 | * level protocol and addressing support later on, but for now it's just | 33 | * level protocol and addressing support later on, but for now it's just |
34 | * standard STREAM TCP/IP sockets. | 34 | * standard STREAM TCP/IP sockets. |
35 | * | 35 | * |
36 | * Unlike system sockets, these sockets are opened by default in | 36 | * Unlike system sockets, these sockets are opened by default in |
37 | * non-blocking mode, you can specify your own timeout for opening a socket, | 37 | * non-blocking mode, you can specify your own timeout for opening a socket, |
38 | * and a number of non-fatal error messages have been automatically handled | 38 | * and a number of non-fatal error messages have been automatically handled |
39 | * and treated as standard no-data-available-yet situations on read. | 39 | * and treated as standard no-data-available-yet situations on read. |
40 | * | 40 | * |
41 | * Please note that there is a condition that will occur eventually (at | 41 | * Please note that there is a condition that will occur eventually (at |
42 | * least on *nix systems) that will trigger a SIGPIPE condition. This | 42 | * least on *nix systems) that will trigger a SIGPIPE condition. This |
43 | * will terminate your program immediately unless handled properly. Most | 43 | * will terminate your program immediately unless handled properly. Most |
44 | * people doing any connections with TcpSocket will want to put this in | 44 | * people doing any connections with TcpSocket will want to put this in |
45 | * their program somewhere before they use it: | 45 | * their program somewhere before they use it: |
46 | *@code | 46 | *@code |
47 | #include <signal.h> | 47 | #include <signal.h> |
48 | ... | 48 | ... |
49 | ... | 49 | ... |
50 | ... | 50 | ... |
51 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::TcpSocket | 51 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::TcpSocket |
52 | @endcode | 52 | @endcode |
53 | * When this is done, Bu::TcpSocket will simply throw a broken pipe | 53 | * When this is done, Bu::TcpSocket will simply throw a broken pipe |
54 | * exception just like every other error condition, allowing your program | 54 | * exception just like every other error condition, allowing your program |
55 | * to handle it sanely. | 55 | * to handle it sanely. |
56 | * | 56 | * |
57 | *@ingroup Serving | 57 | *@ingroup Serving |
58 | *@ingroup Streams | 58 | *@ingroup Streams |
59 | */ | 59 | */ |
60 | class TcpSocket : public Stream | 60 | class TcpSocket : public Stream |
61 | { | 61 | { |
62 | public: | 62 | public: |
63 | #ifdef WIN32 | 63 | #ifdef WIN32 |
64 | typedef unsigned int handle; | 64 | typedef unsigned int handle; |
65 | #else | 65 | #else |
66 | typedef int handle; | 66 | typedef int handle; |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | TcpSocket( handle nTcpSocket ); | 69 | TcpSocket( handle nTcpSocket ); |
70 | TcpSocket( const String &sAddr, int nPort, int nTimeout=30, | 70 | TcpSocket( const String &sAddr, int nPort, int nTimeout=30, |
71 | bool bBlocking=true ); | 71 | bool bBlocking=true ); |
72 | virtual ~TcpSocket(); | 72 | virtual ~TcpSocket(); |
73 | 73 | ||
74 | virtual void close(); | 74 | virtual void close(); |
75 | virtual size read( void *pBuf, size nBytes ); | 75 | virtual size read( void *pBuf, size nBytes ); |
76 | virtual size read( void *pBuf, size nBytes, | 76 | virtual size read( void *pBuf, size nBytes, |
77 | uint32_t nSec, uint32_t nUSec=0 ); | 77 | uint32_t nSec, uint32_t nUSec=0 ); |
78 | virtual size write( const void *pBuf, size nBytes ); | 78 | virtual size write( const void *pBuf, size nBytes ); |
79 | virtual size write( const void *pBuf, size nBytes, | 79 | virtual size write( const void *pBuf, size nBytes, |
80 | uint32_t nSec, uint32_t nUSec=0 ); | 80 | uint32_t nSec, uint32_t nUSec=0 ); |
81 | using Stream::write; | 81 | using Stream::write; |
82 | 82 | ||
83 | virtual size tell(); | 83 | virtual size tell(); |
84 | virtual void seek( size offset ); | 84 | virtual void seek( size offset ); |
85 | virtual void setPos( size pos ); | 85 | virtual void setPos( size pos ); |
86 | virtual void setPosEnd( size pos ); | 86 | virtual void setPosEnd( size pos ); |
87 | virtual bool isEos(); | 87 | virtual bool isEos(); |
88 | virtual bool isOpen(); | 88 | virtual bool isOpen(); |
89 | 89 | ||
90 | virtual void flush(); | 90 | virtual void flush(); |
91 | 91 | ||
92 | virtual bool canRead(); | 92 | virtual bool canRead(); |
93 | virtual bool canWrite(); | 93 | virtual bool canWrite(); |
94 | 94 | ||
95 | virtual bool isReadable(); | 95 | virtual bool isReadable(); |
96 | virtual bool isWritable(); | 96 | virtual bool isWritable(); |
97 | virtual bool isSeekable(); | 97 | virtual bool isSeekable(); |
98 | 98 | ||
99 | virtual bool isBlocking(); | 99 | virtual bool isBlocking(); |
100 | virtual void setBlocking( bool bBlocking=true ); | 100 | virtual void setBlocking( bool bBlocking=true ); |
101 | 101 | ||
102 | virtual void setSize( size iSize ); | 102 | virtual void setSize( size iSize ); |
103 | 103 | ||
104 | Bu::String getAddress() const; | 104 | Bu::String getAddress() const; |
105 | operator handle() const; | 105 | operator handle() const; |
106 | 106 | ||
107 | handle getHandle() const; | 107 | handle getHandle() const; |
108 | handle takeHandle(); | 108 | handle takeHandle(); |
109 | 109 | ||
110 | virtual size getSize() const; | 110 | virtual size getSize() const; |
111 | virtual size getBlockSize() const; | 111 | virtual size getBlockSize() const; |
112 | virtual Bu::String getLocation() const; | 112 | virtual Bu::String getLocation() const; |
113 | 113 | ||
114 | private: | 114 | private: |
115 | void setAddress(); | 115 | void setAddress(); |
116 | 116 | ||
117 | handle nTcpSocket; | 117 | handle nTcpSocket; |
118 | 118 | ||
119 | bool bActive; | 119 | bool bActive; |
120 | bool bBlocking; | 120 | bool bBlocking; |
121 | String sReadBuf; | 121 | String sReadBuf; |
122 | String sAddress; | 122 | String sAddress; |
123 | }; | 123 | }; |
124 | } | 124 | } |
125 | 125 | ||
126 | #endif | 126 | #endif |
diff --git a/src/stable/thread.cpp b/src/stable/thread.cpp index 30443e6..ddb7ff5 100644 --- a/src/stable/thread.cpp +++ b/src/stable/thread.cpp | |||
@@ -10,7 +10,7 @@ | |||
10 | namespace Bu { subExceptionDef( ThreadException ); } | 10 | namespace Bu { subExceptionDef( ThreadException ); } |
11 | 11 | ||
12 | Bu::ThreadId::ThreadId( pthread_t tId ) : | 12 | Bu::ThreadId::ThreadId( pthread_t tId ) : |
13 | tId( tId ) | 13 | tId( tId ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,12 +20,12 @@ Bu::ThreadId::ThreadId() | |||
20 | 20 | ||
21 | bool Bu::ThreadId::operator==( const Bu::ThreadId &rhs ) | 21 | bool Bu::ThreadId::operator==( const Bu::ThreadId &rhs ) |
22 | { | 22 | { |
23 | return pthread_equal( tId, rhs.tId ); | 23 | return pthread_equal( tId, rhs.tId ); |
24 | } | 24 | } |
25 | 25 | ||
26 | bool Bu::ThreadId::operator!=( const ThreadId &rhs ) | 26 | bool Bu::ThreadId::operator!=( const ThreadId &rhs ) |
27 | { | 27 | { |
28 | return !pthread_equal( tId, rhs.tId ); | 28 | return !pthread_equal( tId, rhs.tId ); |
29 | } | 29 | } |
30 | 30 | ||
31 | Bu::Thread::Thread() | 31 | Bu::Thread::Thread() |
@@ -38,45 +38,45 @@ Bu::Thread::~Thread() | |||
38 | 38 | ||
39 | Bu::ThreadId Bu::Thread::currentThread() | 39 | Bu::ThreadId Bu::Thread::currentThread() |
40 | { | 40 | { |
41 | return ThreadId( pthread_self() ); | 41 | return ThreadId( pthread_self() ); |
42 | } | 42 | } |
43 | 43 | ||
44 | bool Bu::Thread::start() | 44 | bool Bu::Thread::start() |
45 | { | 45 | { |
46 | if( pthread_create( &ptHandle, NULL, threadRunner, this ) ) | 46 | if( pthread_create( &ptHandle, NULL, threadRunner, this ) ) |
47 | { | 47 | { |
48 | throw Bu::ThreadException("Could not start thread."); | 48 | throw Bu::ThreadException("Could not start thread."); |
49 | } | 49 | } |
50 | 50 | ||
51 | return true; | 51 | return true; |
52 | } | 52 | } |
53 | 53 | ||
54 | bool Bu::Thread::stop() | 54 | bool Bu::Thread::stop() |
55 | { | 55 | { |
56 | pthread_cancel( ptHandle ); | 56 | pthread_cancel( ptHandle ); |
57 | 57 | ||
58 | return true; | 58 | return true; |
59 | } | 59 | } |
60 | 60 | ||
61 | void *Bu::Thread::threadRunner( void *pThread ) | 61 | void *Bu::Thread::threadRunner( void *pThread ) |
62 | { | 62 | { |
63 | ((Thread *)pThread)->run(); | 63 | ((Thread *)pThread)->run(); |
64 | pthread_exit( NULL ); | 64 | pthread_exit( NULL ); |
65 | return NULL; | 65 | return NULL; |
66 | } | 66 | } |
67 | 67 | ||
68 | bool Bu::Thread::join() | 68 | bool Bu::Thread::join() |
69 | { | 69 | { |
70 | pthread_join( ptHandle, NULL ); | 70 | pthread_join( ptHandle, NULL ); |
71 | return true; | 71 | return true; |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::Thread::yield() | 74 | void Bu::Thread::yield() |
75 | { | 75 | { |
76 | #ifndef WIN32 | 76 | #ifndef WIN32 |
77 | pthread_yield(); | 77 | pthread_yield(); |
78 | #else | 78 | #else |
79 | sched_yield(); | 79 | sched_yield(); |
80 | #endif | 80 | #endif |
81 | } | 81 | } |
82 | 82 | ||
diff --git a/src/stable/thread.h b/src/stable/thread.h index ae07665..ca3ab9f 100644 --- a/src/stable/thread.h +++ b/src/stable/thread.h | |||
@@ -15,120 +15,120 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( ThreadException ); | 18 | subExceptionDecl( ThreadException ); |
19 | class ThreadId | 19 | class ThreadId |
20 | { | 20 | { |
21 | friend class Thread; | 21 | friend class Thread; |
22 | private: | 22 | private: |
23 | ThreadId( pthread_t tId ); | 23 | ThreadId( pthread_t tId ); |
24 | 24 | ||
25 | public: | 25 | public: |
26 | ThreadId(); | 26 | ThreadId(); |
27 | 27 | ||
28 | bool operator==( const ThreadId &rhs ); | 28 | bool operator==( const ThreadId &rhs ); |
29 | bool operator!=( const ThreadId &rhs ); | 29 | bool operator!=( const ThreadId &rhs ); |
30 | 30 | ||
31 | private: | 31 | private: |
32 | pthread_t tId; | 32 | pthread_t tId; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Simple thread class. This wraps the basic pthread (posix threads) | 36 | * Simple thread class. This wraps the basic pthread (posix threads) |
37 | * system in an object oriented sort of way. It allows you to create a | 37 | * system in an object oriented sort of way. It allows you to create a |
38 | * class with standard member variables and callable functions that can be | 38 | * class with standard member variables and callable functions that can be |
39 | * run in it's own thread, one per class instance. | 39 | * run in it's own thread, one per class instance. |
40 | *@ingroup Threading | 40 | *@ingroup Threading |
41 | */ | 41 | */ |
42 | class Thread | 42 | class Thread |
43 | { | 43 | { |
44 | public: | 44 | public: |
45 | /** | 45 | /** |
46 | * Construct an Thread thread. | 46 | * Construct an Thread thread. |
47 | */ | 47 | */ |
48 | Thread(); | 48 | Thread(); |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Destroy an Thread thread. | 51 | * Destroy an Thread thread. |
52 | */ | 52 | */ |
53 | virtual ~Thread(); | 53 | virtual ~Thread(); |
54 | 54 | ||
55 | static ThreadId currentThread(); | 55 | static ThreadId currentThread(); |
56 | ThreadId getId() { return ThreadId( ptHandle ); } | 56 | ThreadId getId() { return ThreadId( ptHandle ); } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Begin thread execution. This will call the overridden run function, | 59 | * Begin thread execution. This will call the overridden run function, |
60 | * which will simply execute in it's own thread until the function | 60 | * which will simply execute in it's own thread until the function |
61 | * exits, the thread is killed, or the thread is cancelled (optionally). | 61 | * exits, the thread is killed, or the thread is cancelled (optionally). |
62 | * The thread started in this manner has access to all of it's class | 62 | * The thread started in this manner has access to all of it's class |
63 | * variables, but be sure to protect possible multiple-access with | 63 | * variables, but be sure to protect possible multiple-access with |
64 | * ThreadMutex objects. | 64 | * ThreadMutex objects. |
65 | * @returns True if starting the thread was successful. False if | 65 | * @returns True if starting the thread was successful. False if |
66 | * something went wrong and the thread has not started. | 66 | * something went wrong and the thread has not started. |
67 | */ | 67 | */ |
68 | bool start(); | 68 | bool start(); |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Forcibly kill a thread. This is not generally considered a good | 71 | * Forcibly kill a thread. This is not generally considered a good |
72 | * thing to do, but in those rare cases you need it, it's invaluable. | 72 | * thing to do, but in those rare cases you need it, it's invaluable. |
73 | * The problem with stopping (or killing) a thread is that it stops it | 73 | * The problem with stopping (or killing) a thread is that it stops it |
74 | * the moment you call stop, no matter what it's doing. The object | 74 | * the moment you call stop, no matter what it's doing. The object |
75 | * oriented approach to this will help clean up any class variables | 75 | * oriented approach to this will help clean up any class variables |
76 | * that were used, but anything not managed as a member variable will | 76 | * that were used, but anything not managed as a member variable will |
77 | * probably create a memory leak type of situation. Instead of stop, | 77 | * probably create a memory leak type of situation. Instead of stop, |
78 | * consider using cancel, which can be handled by the running thread in | 78 | * consider using cancel, which can be handled by the running thread in |
79 | * a graceful manner. | 79 | * a graceful manner. |
80 | *@returns True if the thread was stopped, false otherwise. When this | 80 | *@returns True if the thread was stopped, false otherwise. When this |
81 | * function returns the thread may not have stopped, to ensure that the | 81 | * function returns the thread may not have stopped, to ensure that the |
82 | * thread has really stopped, call join. | 82 | * thread has really stopped, call join. |
83 | */ | 83 | */ |
84 | bool stop(); | 84 | bool stop(); |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * Join the thread in action. This function performs what is commonly | 87 | * Join the thread in action. This function performs what is commonly |
88 | * called a thread join. That is that it effectively makes the calling | 88 | * called a thread join. That is that it effectively makes the calling |
89 | * thread an the Thread thread contained in the called object one in the | 89 | * thread an the Thread thread contained in the called object one in the |
90 | * same, and pauses the calling thread until the called thread exits. | 90 | * same, and pauses the calling thread until the called thread exits. |
91 | * That is, when called from, say, your main(), mythread.join() will | 91 | * That is, when called from, say, your main(), mythread.join() will |
92 | * not return until the thread mythread has exited. This is very handy | 92 | * not return until the thread mythread has exited. This is very handy |
93 | * at the end of programs to ensure all of your data was cleaned up. | 93 | * at the end of programs to ensure all of your data was cleaned up. |
94 | *@returns True if the thread was joined, false if the thread couldn't | 94 | *@returns True if the thread was joined, false if the thread couldn't |
95 | * be joined, usually because it isn't running to begin with. | 95 | * be joined, usually because it isn't running to begin with. |
96 | */ | 96 | */ |
97 | bool join(); | 97 | bool join(); |
98 | 98 | ||
99 | private: | 99 | private: |
100 | pthread_t ptHandle; /**< Internal handle to the posix thread. */ | 100 | pthread_t ptHandle; /**< Internal handle to the posix thread. */ |
101 | 101 | ||
102 | protected: | 102 | protected: |
103 | /** | 103 | /** |
104 | * The workhorse of the Thread class. This is the function that will | 104 | * The workhorse of the Thread class. This is the function that will |
105 | * run in the thread, when this function exits the thread dies and is | 105 | * run in the thread, when this function exits the thread dies and is |
106 | * cleaned up by the system. Make sure to read up on Bu::Mutex, | 106 | * cleaned up by the system. Make sure to read up on Bu::Mutex, |
107 | * Bu::Condition, and the Bu::Synchro* classes to see how to control | 107 | * Bu::Condition, and the Bu::Synchro* classes to see how to control |
108 | * and protect everything you do in a safe way within this function. | 108 | * and protect everything you do in a safe way within this function. |
109 | *@returns I'm not sure right now, but this is the posix standard form. | 109 | *@returns I'm not sure right now, but this is the posix standard form. |
110 | */ | 110 | */ |
111 | virtual void run()=0; | 111 | virtual void run()=0; |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Gives up some cpu-time in the currently running thread. If a thread | 114 | * Gives up some cpu-time in the currently running thread. If a thread |
115 | * is working hard, but you want to give other threads on the system | 115 | * is working hard, but you want to give other threads on the system |
116 | * some time to do some work, call yield. | 116 | * some time to do some work, call yield. |
117 | */ | 117 | */ |
118 | void yield(); | 118 | void yield(); |
119 | 119 | ||
120 | private: | 120 | private: |
121 | /** | 121 | /** |
122 | * This is the hidden-heart of the thread system. While run is what the | 122 | * This is the hidden-heart of the thread system. While run is what the |
123 | * user gets to override, and everything said about it is true, this is | 123 | * user gets to override, and everything said about it is true, this is |
124 | * the function that actually makes up the thread, it simply calls the | 124 | * the function that actually makes up the thread, it simply calls the |
125 | * run member function in an OO-friendly way. This is what allows us to | 125 | * run member function in an OO-friendly way. This is what allows us to |
126 | * use member variables from within the thread itself. | 126 | * use member variables from within the thread itself. |
127 | *@param pThread Should always be this. | 127 | *@param pThread Should always be this. |
128 | *@returns This is specified by posix, I'm not sure yet. | 128 | *@returns This is specified by posix, I'm not sure yet. |
129 | */ | 129 | */ |
130 | static void *threadRunner( void *pThread ); | 130 | static void *threadRunner( void *pThread ); |
131 | }; | 131 | }; |
132 | } | 132 | } |
133 | 133 | ||
134 | #endif | 134 | #endif |
diff --git a/src/stable/trace.cpp b/src/stable/trace.cpp index c072fd9..2b3b863 100644 --- a/src/stable/trace.cpp +++ b/src/stable/trace.cpp | |||
@@ -9,59 +9,59 @@ | |||
9 | 9 | ||
10 | void Bu::__tracer( const char *pf ) | 10 | void Bu::__tracer( const char *pf ) |
11 | { | 11 | { |
12 | printf("trace: %s\n", pf ); | 12 | printf("trace: %s\n", pf ); |
13 | } | 13 | } |
14 | 14 | ||
15 | template<> void Bu::__tracer_format<float>( const float &v ) | 15 | template<> void Bu::__tracer_format<float>( const float &v ) |
16 | { | 16 | { |
17 | printf("%f", v ); | 17 | printf("%f", v ); |
18 | } | 18 | } |
19 | 19 | ||
20 | template<> void Bu::__tracer_format<double>( const double &v ) | 20 | template<> void Bu::__tracer_format<double>( const double &v ) |
21 | { | 21 | { |
22 | printf("%f", v ); | 22 | printf("%f", v ); |
23 | } | 23 | } |
24 | 24 | ||
25 | template<> void Bu::__tracer_format<void *>( void * const &v ) | 25 | template<> void Bu::__tracer_format<void *>( void * const &v ) |
26 | { | 26 | { |
27 | printf("0x%08X", (ptrdiff_t)v ); | 27 | printf("0x%08X", (ptrdiff_t)v ); |
28 | } | 28 | } |
29 | 29 | ||
30 | template<> void Bu::__tracer_format<char *>( char * const &v ) | 30 | template<> void Bu::__tracer_format<char *>( char * const &v ) |
31 | { | 31 | { |
32 | printf("\"%s\"", v ); | 32 | printf("\"%s\"", v ); |
33 | } | 33 | } |
34 | 34 | ||
35 | template<> void Bu::__tracer_format<char **>( char ** const &v ) | 35 | template<> void Bu::__tracer_format<char **>( char ** const &v ) |
36 | { | 36 | { |
37 | printf("["); | 37 | printf("["); |
38 | for( int j = 0; v[j]; j++ ) | 38 | for( int j = 0; v[j]; j++ ) |
39 | { | 39 | { |
40 | if( j > 0 ) | 40 | if( j > 0 ) |
41 | printf(", "); | 41 | printf(", "); |
42 | printf("\"%s\"", v[j] ); | 42 | printf("\"%s\"", v[j] ); |
43 | } | 43 | } |
44 | printf("]"); | 44 | printf("]"); |
45 | } | 45 | } |
46 | 46 | ||
47 | template<> void Bu::__tracer_format<void const *>( void const * const &v ) | 47 | template<> void Bu::__tracer_format<void const *>( void const * const &v ) |
48 | { | 48 | { |
49 | printf("0x%08X", (ptrdiff_t)v ); | 49 | printf("0x%08X", (ptrdiff_t)v ); |
50 | } | 50 | } |
51 | 51 | ||
52 | template<> void Bu::__tracer_format<char const *>( char const * const &v ) | 52 | template<> void Bu::__tracer_format<char const *>( char const * const &v ) |
53 | { | 53 | { |
54 | printf("\"%s\"", v ); | 54 | printf("\"%s\"", v ); |
55 | } | 55 | } |
56 | 56 | ||
57 | template<> void Bu::__tracer_format<char const **>( char const ** const &v ) | 57 | template<> void Bu::__tracer_format<char const **>( char const ** const &v ) |
58 | { | 58 | { |
59 | printf("["); | 59 | printf("["); |
60 | for( int j = 0; v[j]; j++ ) | 60 | for( int j = 0; v[j]; j++ ) |
61 | { | 61 | { |
62 | if( j > 0 ) | 62 | if( j > 0 ) |
63 | printf(", "); | 63 | printf(", "); |
64 | printf("\"%s\"", v[j] ); | 64 | printf("\"%s\"", v[j] ); |
65 | } | 65 | } |
66 | printf("]"); | 66 | printf("]"); |
67 | } | 67 | } |
diff --git a/src/stable/trace.h b/src/stable/trace.h index da67f03..d47df9c 100644 --- a/src/stable/trace.h +++ b/src/stable/trace.h | |||
@@ -17,165 +17,165 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /* template<typename t> void __tracer_format( t &v ) | 20 | /* template<typename t> void __tracer_format( t &v ) |
21 | { | 21 | { |
22 | __tracer_format( *const_cast<const t *>(&v) ); | 22 | __tracer_format( *const_cast<const t *>(&v) ); |
23 | } | 23 | } |
24 | */ | 24 | */ |
25 | template<typename t> void __tracer_format( const t &v ) | 25 | template<typename t> void __tracer_format( const t &v ) |
26 | { | 26 | { |
27 | Bu::sio << v; | 27 | Bu::sio << v; |
28 | } | 28 | } |
29 | 29 | ||
30 | void __tracer( const char *pf ); | 30 | void __tracer( const char *pf ); |
31 | 31 | ||
32 | #define looper( vv ) \ | 32 | #define looper( vv ) \ |
33 | for( ; *n; n++ ) \ | 33 | for( ; *n; n++ ) \ |
34 | { \ | 34 | { \ |
35 | if( bInBracket == true ) \ | 35 | if( bInBracket == true ) \ |
36 | { \ | 36 | { \ |
37 | if( *n == '>' ) \ | 37 | if( *n == '>' ) \ |
38 | bInBracket = false; \ | 38 | bInBracket = false; \ |
39 | } \ | 39 | } \ |
40 | else if( *n == ',' || *n == ')' ) \ | 40 | else if( *n == ',' || *n == ')' ) \ |
41 | { \ | 41 | { \ |
42 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, 1, stdout ); \ | 42 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, 1, stdout ); \ |
43 | fwrite("=", 1, 1, stdout); \ | 43 | fwrite("=", 1, 1, stdout); \ |
44 | __tracer_format( vv ); \ | 44 | __tracer_format( vv ); \ |
45 | s = n; \ | 45 | s = n; \ |
46 | n++; \ | 46 | n++; \ |
47 | break; \ | 47 | break; \ |
48 | } \ | 48 | } \ |
49 | else if( *n == '<' ) \ | 49 | else if( *n == '<' ) \ |
50 | { \ | 50 | { \ |
51 | bInBracket = true; \ | 51 | bInBracket = true; \ |
52 | } \ | 52 | } \ |
53 | } (void)0 | 53 | } (void)0 |
54 | 54 | ||
55 | template<typename t1> void __tracer( const char *pf, t1 &v1 ) | 55 | template<typename t1> void __tracer( const char *pf, t1 &v1 ) |
56 | { | 56 | { |
57 | printf("trace: "); | 57 | printf("trace: "); |
58 | const char *s = pf; | 58 | const char *s = pf; |
59 | const char *n = pf; | 59 | const char *n = pf; |
60 | bool bInBracket = false; | 60 | bool bInBracket = false; |
61 | looper( v1 ); | 61 | looper( v1 ); |
62 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 62 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
63 | fwrite( "\n", 1, 1, stdout ); | 63 | fwrite( "\n", 1, 1, stdout ); |
64 | fflush( stdout ); | 64 | fflush( stdout ); |
65 | } | 65 | } |
66 | 66 | ||
67 | template<typename t1, typename t2> void __tracer( const char *pf, | 67 | template<typename t1, typename t2> void __tracer( const char *pf, |
68 | t1 &v1, t2 &v2 ) | 68 | t1 &v1, t2 &v2 ) |
69 | { | 69 | { |
70 | printf("trace: "); | 70 | printf("trace: "); |
71 | const char *s = pf; | 71 | const char *s = pf; |
72 | const char *n = pf; | 72 | const char *n = pf; |
73 | bool bInBracket = false; | 73 | bool bInBracket = false; |
74 | looper( v1 ); | 74 | looper( v1 ); |
75 | looper( v2 ); | 75 | looper( v2 ); |
76 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 76 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
77 | fwrite( "\n", 1, 1, stdout ); | 77 | fwrite( "\n", 1, 1, stdout ); |
78 | fflush( stdout ); | 78 | fflush( stdout ); |
79 | } | 79 | } |
80 | 80 | ||
81 | template<typename t1, typename t2, typename t3> | 81 | template<typename t1, typename t2, typename t3> |
82 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3 ) | 82 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3 ) |
83 | { | 83 | { |
84 | printf("trace: "); | 84 | printf("trace: "); |
85 | const char *s = pf; | 85 | const char *s = pf; |
86 | const char *n = pf; | 86 | const char *n = pf; |
87 | bool bInBracket = false; | 87 | bool bInBracket = false; |
88 | looper( v1 ); | 88 | looper( v1 ); |
89 | looper( v2 ); | 89 | looper( v2 ); |
90 | looper( v3 ); | 90 | looper( v3 ); |
91 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 91 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
92 | fwrite( "\n", 1, 1, stdout ); | 92 | fwrite( "\n", 1, 1, stdout ); |
93 | fflush( stdout ); | 93 | fflush( stdout ); |
94 | } | 94 | } |
95 | 95 | ||
96 | template<typename t1, typename t2, typename t3, typename t4> | 96 | template<typename t1, typename t2, typename t3, typename t4> |
97 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4 ) | 97 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4 ) |
98 | { | 98 | { |
99 | printf("trace: "); | 99 | printf("trace: "); |
100 | const char *s = pf; | 100 | const char *s = pf; |
101 | const char *n = pf; | 101 | const char *n = pf; |
102 | bool bInBracket = false; | 102 | bool bInBracket = false; |
103 | looper( v1 ); | 103 | looper( v1 ); |
104 | looper( v2 ); | 104 | looper( v2 ); |
105 | looper( v3 ); | 105 | looper( v3 ); |
106 | looper( v4 ); | 106 | looper( v4 ); |
107 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 107 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
108 | fwrite( "\n", 1, 1, stdout ); | 108 | fwrite( "\n", 1, 1, stdout ); |
109 | fflush( stdout ); | 109 | fflush( stdout ); |
110 | } | 110 | } |
111 | 111 | ||
112 | template<typename t1, typename t2, typename t3, typename t4, typename t5> | 112 | template<typename t1, typename t2, typename t3, typename t4, typename t5> |
113 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5 ) | 113 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5 ) |
114 | { | 114 | { |
115 | printf("trace: "); | 115 | printf("trace: "); |
116 | const char *s = pf; | 116 | const char *s = pf; |
117 | const char *n = pf; | 117 | const char *n = pf; |
118 | bool bInBracket = false; | 118 | bool bInBracket = false; |
119 | looper( v1 ); | 119 | looper( v1 ); |
120 | looper( v2 ); | 120 | looper( v2 ); |
121 | looper( v3 ); | 121 | looper( v3 ); |
122 | looper( v4 ); | 122 | looper( v4 ); |
123 | looper( v5 ); | 123 | looper( v5 ); |
124 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 124 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
125 | fwrite( "\n", 1, 1, stdout ); | 125 | fwrite( "\n", 1, 1, stdout ); |
126 | fflush( stdout ); | 126 | fflush( stdout ); |
127 | } | 127 | } |
128 | 128 | ||
129 | template<typename t1, typename t2, typename t3, typename t4, typename t5, | 129 | template<typename t1, typename t2, typename t3, typename t4, typename t5, |
130 | typename t6> | 130 | typename t6> |
131 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, | 131 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, |
132 | t6 &v6) | 132 | t6 &v6) |
133 | { | 133 | { |
134 | printf("trace: "); | 134 | printf("trace: "); |
135 | const char *s = pf; | 135 | const char *s = pf; |
136 | const char *n = pf; | 136 | const char *n = pf; |
137 | bool bInBracket = false; | 137 | bool bInBracket = false; |
138 | looper( v1 ); | 138 | looper( v1 ); |
139 | looper( v2 ); | 139 | looper( v2 ); |
140 | looper( v3 ); | 140 | looper( v3 ); |
141 | looper( v4 ); | 141 | looper( v4 ); |
142 | looper( v5 ); | 142 | looper( v5 ); |
143 | looper( v6 ); | 143 | looper( v6 ); |
144 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 144 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
145 | fwrite( "\n", 1, 1, stdout ); | 145 | fwrite( "\n", 1, 1, stdout ); |
146 | fflush( stdout ); | 146 | fflush( stdout ); |
147 | } | 147 | } |
148 | 148 | ||
149 | template<typename t1, typename t2, typename t3, typename t4, typename t5, | 149 | template<typename t1, typename t2, typename t3, typename t4, typename t5, |
150 | typename t6, typename t7> | 150 | typename t6, typename t7> |
151 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, | 151 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, |
152 | t6 &v6, t7 &v7 ) | 152 | t6 &v6, t7 &v7 ) |
153 | { | 153 | { |
154 | printf("trace: "); | 154 | printf("trace: "); |
155 | const char *s = pf; | 155 | const char *s = pf; |
156 | const char *n = pf; | 156 | const char *n = pf; |
157 | bool bInBracket = false; | 157 | bool bInBracket = false; |
158 | looper( v1 ); | 158 | looper( v1 ); |
159 | looper( v2 ); | 159 | looper( v2 ); |
160 | looper( v3 ); | 160 | looper( v3 ); |
161 | looper( v4 ); | 161 | looper( v4 ); |
162 | looper( v5 ); | 162 | looper( v5 ); |
163 | looper( v6 ); | 163 | looper( v6 ); |
164 | looper( v7 ); | 164 | looper( v7 ); |
165 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 165 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
166 | fwrite( "\n", 1, 1, stdout ); | 166 | fwrite( "\n", 1, 1, stdout ); |
167 | fflush( stdout ); | 167 | fflush( stdout ); |
168 | } | 168 | } |
169 | #undef looper | 169 | #undef looper |
170 | 170 | ||
171 | template<> void __tracer_format<float>( const float &v ); | 171 | template<> void __tracer_format<float>( const float &v ); |
172 | template<> void __tracer_format<double>( const double &v ); | 172 | template<> void __tracer_format<double>( const double &v ); |
173 | template<> void __tracer_format<void *>( void * const &v ); | 173 | template<> void __tracer_format<void *>( void * const &v ); |
174 | template<> void __tracer_format<char *>( char * const &v ); | 174 | template<> void __tracer_format<char *>( char * const &v ); |
175 | template<> void __tracer_format<char **>( char ** const &v ); | 175 | template<> void __tracer_format<char **>( char ** const &v ); |
176 | template<> void __tracer_format<void const *>( void const * const &v ); | 176 | template<> void __tracer_format<void const *>( void const * const &v ); |
177 | template<> void __tracer_format<char const *>( char const * const &v ); | 177 | template<> void __tracer_format<char const *>( char const * const &v ); |
178 | template<> void __tracer_format<char const **>( char const ** const &v ); | 178 | template<> void __tracer_format<char const **>( char const ** const &v ); |
179 | } | 179 | } |
180 | 180 | ||
181 | #ifdef BU_TRACE | 181 | #ifdef BU_TRACE |
diff --git a/src/stable/unitsuite.cpp b/src/stable/unitsuite.cpp index b6057d0..e0606e6 100644 --- a/src/stable/unitsuite.cpp +++ b/src/stable/unitsuite.cpp | |||
@@ -17,14 +17,14 @@ using namespace Bu; | |||
17 | #include <unistd.h> | 17 | #include <unistd.h> |
18 | 18 | ||
19 | Bu::UnitSuite::UnitSuite() : | 19 | Bu::UnitSuite::UnitSuite() : |
20 | iOptions( 0 ), | 20 | iOptions( 0 ), |
21 | iNameWidth( 0 ) | 21 | iNameWidth( 0 ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::UnitSuite::UnitSuite( int iOptions ) : | 25 | Bu::UnitSuite::UnitSuite( int iOptions ) : |
26 | iOptions( iOptions ), | 26 | iOptions( iOptions ), |
27 | iNameWidth( 0 ) | 27 | iNameWidth( 0 ) |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
@@ -34,240 +34,240 @@ Bu::UnitSuite::~UnitSuite() | |||
34 | 34 | ||
35 | int Bu::UnitSuite::run( int argc, char *argv[] ) | 35 | int Bu::UnitSuite::run( int argc, char *argv[] ) |
36 | { | 36 | { |
37 | bool bCleanup = true; | 37 | bool bCleanup = true; |
38 | OptParser p; | 38 | OptParser p; |
39 | p.addOption( Bu::slot( this, &Bu::UnitSuite::onListCases ), 'l', "list", | 39 | p.addOption( Bu::slot( this, &Bu::UnitSuite::onListCases ), 'l', "list", |
40 | "List available test cases." ); | 40 | "List available test cases." ); |
41 | p.addOption( bCleanup, "no-cleanup", "Don't erase temp files."); | 41 | p.addOption( bCleanup, "no-cleanup", "Don't erase temp files."); |
42 | p.setOverride( "no-cleanup", false ); | 42 | p.setOverride( "no-cleanup", false ); |
43 | p.setNonOption( Bu::slot( this, &Bu::UnitSuite::onAddTest ) ); | 43 | p.setNonOption( Bu::slot( this, &Bu::UnitSuite::onAddTest ) ); |
44 | p.addHelpOption(); | 44 | p.addHelpOption(); |
45 | p.parse( argc, argv ); | 45 | p.parse( argc, argv ); |
46 | 46 | ||
47 | if( !hSelTests.isEmpty() ) | 47 | if( !hSelTests.isEmpty() ) |
48 | { | 48 | { |
49 | TestList lSub; | 49 | TestList lSub; |
50 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) | 50 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) |
51 | { | 51 | { |
52 | if( hSelTests.has( (*i).sName ) ) | 52 | if( hSelTests.has( (*i).sName ) ) |
53 | lSub.append( *i ); | 53 | lSub.append( *i ); |
54 | } | 54 | } |
55 | 55 | ||
56 | lTests = lSub; | 56 | lTests = lSub; |
57 | } | 57 | } |
58 | 58 | ||
59 | int iEPass = 0; | 59 | int iEPass = 0; |
60 | int iEFail = 0; | 60 | int iEFail = 0; |
61 | int iUPass = 0; | 61 | int iUPass = 0; |
62 | int iUFail = 0; | 62 | int iUFail = 0; |
63 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) | 63 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) |
64 | { | 64 | { |
65 | sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName | 65 | sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName |
66 | << sio.flush; | 66 | << sio.flush; |
67 | try | 67 | try |
68 | { | 68 | { |
69 | iStepCount = -1; | 69 | iStepCount = -1; |
70 | iProgress = 0; | 70 | iProgress = 0; |
71 | (this->*(i->fTest))(); | 71 | (this->*(i->fTest))(); |
72 | switch( i->eExpect ) | 72 | switch( i->eExpect ) |
73 | { | 73 | { |
74 | case expectPass: | 74 | case expectPass: |
75 | sio << "pass." << sio.nl; | 75 | sio << "pass." << sio.nl; |
76 | iEPass++; | 76 | iEPass++; |
77 | break; | 77 | break; |
78 | 78 | ||
79 | case expectFail: | 79 | case expectFail: |
80 | sio << "unexpected pass." << sio.nl; | 80 | sio << "unexpected pass." << sio.nl; |
81 | iUPass++; | 81 | iUPass++; |
82 | break; | 82 | break; |
83 | } | 83 | } |
84 | } | 84 | } |
85 | catch( Failed &e ) | 85 | catch( Failed &e ) |
86 | { | 86 | { |
87 | switch( i->eExpect ) | 87 | switch( i->eExpect ) |
88 | { | 88 | { |
89 | case expectPass: | 89 | case expectPass: |
90 | sio << "unexpected "; | 90 | sio << "unexpected "; |
91 | iUFail++; | 91 | iUFail++; |
92 | break; | 92 | break; |
93 | 93 | ||
94 | case expectFail: | 94 | case expectFail: |
95 | sio << "expected "; | 95 | sio << "expected "; |
96 | iEFail++; | 96 | iEFail++; |
97 | break; | 97 | break; |
98 | } | 98 | } |
99 | if( e.bFile ) | 99 | if( e.bFile ) |
100 | { | 100 | { |
101 | sio << "fail in unitTest(" << e.str << "). (" << e.sFile | 101 | sio << "fail in unitTest(" << e.str << "). (" << e.sFile |
102 | << ":" << e.nLine << ")." << sio.nl; | 102 | << ":" << e.nLine << ")." << sio.nl; |
103 | } | 103 | } |
104 | else | 104 | else |
105 | { | 105 | { |
106 | sio << "fail in unitTest(" << e.str << ")." << sio.nl; | 106 | sio << "fail in unitTest(" << e.str << ")." << sio.nl; |
107 | } | 107 | } |
108 | 108 | ||
109 | if( (iOptions & optStopOnError) ) | 109 | if( (iOptions & optStopOnError) ) |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | catch( std::exception &e ) | 112 | catch( std::exception &e ) |
113 | { | 113 | { |
114 | switch( i->eExpect ) | 114 | switch( i->eExpect ) |
115 | { | 115 | { |
116 | case expectPass: | 116 | case expectPass: |
117 | sio << "unexpected "; | 117 | sio << "unexpected "; |
118 | iUFail++; | 118 | iUFail++; |
119 | break; | 119 | break; |
120 | 120 | ||
121 | case expectFail: | 121 | case expectFail: |
122 | sio << "expected "; | 122 | sio << "expected "; |
123 | iEFail++; | 123 | iEFail++; |
124 | break; | 124 | break; |
125 | } | 125 | } |
126 | sio << "fail with unknown exception. what: " << e.what() << sio.nl; | 126 | sio << "fail with unknown exception. what: " << e.what() << sio.nl; |
127 | 127 | ||
128 | if( (iOptions & optStopOnError) ) | 128 | if( (iOptions & optStopOnError) ) |
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
131 | catch( ... ) | 131 | catch( ... ) |
132 | { | 132 | { |
133 | switch( i->eExpect ) | 133 | switch( i->eExpect ) |
134 | { | 134 | { |
135 | case expectPass: | 135 | case expectPass: |
136 | sio << "unexpected "; | 136 | sio << "unexpected "; |
137 | iUFail++; | 137 | iUFail++; |
138 | break; | 138 | break; |
139 | 139 | ||
140 | case expectFail: | 140 | case expectFail: |
141 | sio << "expected "; | 141 | sio << "expected "; |
142 | iEFail++; | 142 | iEFail++; |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | sio << "fail with external exception." << sio.nl; | 145 | sio << "fail with external exception." << sio.nl; |
146 | 146 | ||
147 | if( (iOptions & optStopOnError) ) | 147 | if( (iOptions & optStopOnError) ) |
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | } | 150 | } |
151 | 151 | ||
152 | sio << sio.nl | 152 | sio << sio.nl |
153 | << "Report:" << sio.nl | 153 | << "Report:" << sio.nl |
154 | << "\tTotal tests run: " << lTests.getSize() << sio.nl | 154 | << "\tTotal tests run: " << lTests.getSize() << sio.nl |
155 | << "\tExpected passes: " << iEPass << sio.nl | 155 | << "\tExpected passes: " << iEPass << sio.nl |
156 | << "\tExpected failures: " << iEFail << sio.nl | 156 | << "\tExpected failures: " << iEFail << sio.nl |
157 | << "\tUnexpected passes: " << iUPass << sio.nl | 157 | << "\tUnexpected passes: " << iUPass << sio.nl |
158 | << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; | 158 | << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; |
159 | if( iUPass == 0 && iUFail == 0 ) | 159 | if( iUPass == 0 && iUFail == 0 ) |
160 | sio << "\tNothing unexpected." << sio.nl << sio.nl; | 160 | sio << "\tNothing unexpected." << sio.nl << sio.nl; |
161 | 161 | ||
162 | if( bCleanup ) | 162 | if( bCleanup ) |
163 | { | 163 | { |
164 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) | 164 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) |
165 | { | 165 | { |
166 | unlink( (*i).getStr() ); | 166 | unlink( (*i).getStr() ); |
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | Bu::File Bu::UnitSuite::tempFile( Bu::String &sFileName ) | 173 | Bu::File Bu::UnitSuite::tempFile( Bu::String &sFileName ) |
174 | { | 174 | { |
175 | Bu::File f = Bu::File::tempFile( sFileName ); | 175 | Bu::File f = Bu::File::tempFile( sFileName ); |
176 | lFileCleanup.append( sFileName ); | 176 | lFileCleanup.append( sFileName ); |
177 | return f; | 177 | return f; |
178 | } | 178 | } |
179 | 179 | ||
180 | void Bu::UnitSuite::add( Test fTest, const Bu::String &sName, Expect e ) | 180 | void Bu::UnitSuite::add( Test fTest, const Bu::String &sName, Expect e ) |
181 | { | 181 | { |
182 | TestInfo ti; | 182 | TestInfo ti; |
183 | ti.sName = sName; | 183 | ti.sName = sName; |
184 | ti.eExpect = e; | 184 | ti.eExpect = e; |
185 | long index = ti.sName.rfindIdx("::"); | 185 | long index = ti.sName.rfindIdx("::"); |
186 | if( index != -1 ) | 186 | if( index != -1 ) |
187 | { | 187 | { |
188 | String tmp = sSuiteName; | 188 | String tmp = sSuiteName; |
189 | tmp += ti.sName.getStr()+index; | 189 | tmp += ti.sName.getStr()+index; |
190 | ti.sName = tmp; | 190 | ti.sName = tmp; |
191 | } | 191 | } |
192 | ti.fTest = fTest; | 192 | ti.fTest = fTest; |
193 | lTests.append( ti ); | 193 | lTests.append( ti ); |
194 | if( iNameWidth < ti.sName.getSize() ) | 194 | if( iNameWidth < ti.sName.getSize() ) |
195 | iNameWidth = ti.sName.getSize(); | 195 | iNameWidth = ti.sName.getSize(); |
196 | } | 196 | } |
197 | 197 | ||
198 | void Bu::UnitSuite::setName( const String &sName ) | 198 | void Bu::UnitSuite::setName( const String &sName ) |
199 | { | 199 | { |
200 | sSuiteName = sName; | 200 | sSuiteName = sName; |
201 | } | 201 | } |
202 | 202 | ||
203 | void Bu::UnitSuite::dispProgress() | 203 | void Bu::UnitSuite::dispProgress() |
204 | { | 204 | { |
205 | if( tLastUpdate == time( NULL ) ) | 205 | if( tLastUpdate == time( NULL ) ) |
206 | return; | 206 | return; |
207 | sio << Fmt(3) << (iProgress*100/iStepCount) << "%" << "\b\b\b\b" | 207 | sio << Fmt(3) << (iProgress*100/iStepCount) << "%" << "\b\b\b\b" |
208 | << sio.flush; | 208 | << sio.flush; |
209 | tLastUpdate = time( NULL ); | 209 | tLastUpdate = time( NULL ); |
210 | } | 210 | } |
211 | 211 | ||
212 | void Bu::UnitSuite::setStepCount( int iSteps ) | 212 | void Bu::UnitSuite::setStepCount( int iSteps ) |
213 | { | 213 | { |
214 | iStepCount = iSteps; | 214 | iStepCount = iSteps; |
215 | if( iStepCount < 0 ) | 215 | if( iStepCount < 0 ) |
216 | return; | 216 | return; |
217 | tLastUpdate = 0; | 217 | tLastUpdate = 0; |
218 | dispProgress(); | 218 | dispProgress(); |
219 | } | 219 | } |
220 | 220 | ||
221 | void Bu::UnitSuite::incProgress( int iAmnt ) | 221 | void Bu::UnitSuite::incProgress( int iAmnt ) |
222 | { | 222 | { |
223 | iProgress += iAmnt; | 223 | iProgress += iAmnt; |
224 | if( iProgress < 0 ) | 224 | if( iProgress < 0 ) |
225 | iProgress = 0; | 225 | iProgress = 0; |
226 | if( iProgress > iStepCount ) | 226 | if( iProgress > iStepCount ) |
227 | iProgress = iStepCount; | 227 | iProgress = iStepCount; |
228 | dispProgress(); | 228 | dispProgress(); |
229 | } | 229 | } |
230 | 230 | ||
231 | void Bu::UnitSuite::setProgress( int iAmnt ) | 231 | void Bu::UnitSuite::setProgress( int iAmnt ) |
232 | { | 232 | { |
233 | iProgress = iAmnt; | 233 | iProgress = iAmnt; |
234 | if( iProgress < 0 ) | 234 | if( iProgress < 0 ) |
235 | iProgress = 0; | 235 | iProgress = 0; |
236 | if( iProgress > iStepCount ) | 236 | if( iProgress > iStepCount ) |
237 | iProgress = iStepCount; | 237 | iProgress = iStepCount; |
238 | dispProgress(); | 238 | dispProgress(); |
239 | } | 239 | } |
240 | 240 | ||
241 | int Bu::UnitSuite::onListCases( StrArray ) | 241 | int Bu::UnitSuite::onListCases( StrArray ) |
242 | { | 242 | { |
243 | sio << "Test cases:" << sio.nl; | 243 | sio << "Test cases:" << sio.nl; |
244 | for( TestList::iterator i = lTests.begin(); i; i++ ) | 244 | for( TestList::iterator i = lTests.begin(); i; i++ ) |
245 | { | 245 | { |
246 | sio << "\t- " << Fmt( iNameWidth, 10, Fmt::Left ) << (*i).sName << " " | 246 | sio << "\t- " << Fmt( iNameWidth, 10, Fmt::Left ) << (*i).sName << " " |
247 | << (*i).eExpect << sio.nl; | 247 | << (*i).eExpect << sio.nl; |
248 | } | 248 | } |
249 | sio << sio.nl; | 249 | sio << sio.nl; |
250 | exit( 0 ); | 250 | exit( 0 ); |
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
254 | int Bu::UnitSuite::onAddTest( StrArray aParam ) | 254 | int Bu::UnitSuite::onAddTest( StrArray aParam ) |
255 | { | 255 | { |
256 | hSelTests.insert( aParam[0], true ); | 256 | hSelTests.insert( aParam[0], true ); |
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
260 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ) | 260 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ) |
261 | { | 261 | { |
262 | switch( e ) | 262 | switch( e ) |
263 | { | 263 | { |
264 | case Bu::UnitSuite::expectPass: | 264 | case Bu::UnitSuite::expectPass: |
265 | return f << "expect pass"; | 265 | return f << "expect pass"; |
266 | 266 | ||
267 | case Bu::UnitSuite::expectFail: | 267 | case Bu::UnitSuite::expectFail: |
268 | return f << "expect fail"; | 268 | return f << "expect fail"; |
269 | } | 269 | } |
270 | 270 | ||
271 | return f << "**error**"; | 271 | return f << "**error**"; |
272 | } | 272 | } |
273 | 273 | ||
diff --git a/src/stable/unitsuite.h b/src/stable/unitsuite.h index 3442753..46a0773 100644 --- a/src/stable/unitsuite.h +++ b/src/stable/unitsuite.h | |||
@@ -17,126 +17,126 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /** | 20 | /** |
21 | * Provides a unit testing framework. This is pretty easy to use, probably | 21 | * Provides a unit testing framework. This is pretty easy to use, probably |
22 | * the best way to get started is to use ch to generate a template, or use | 22 | * the best way to get started is to use ch to generate a template, or use |
23 | * the code below with appropriate tweaks: | 23 | * the code below with appropriate tweaks: |
24 | *@code | 24 | *@code |
25 | * #include "unitsuite.h" | 25 | * #include "unitsuite.h" |
26 | * | 26 | * |
27 | * class Unit : public Bu::UnitSuite | 27 | * class Unit : public Bu::UnitSuite |
28 | * { | 28 | * { |
29 | * public: | 29 | * public: |
30 | * Unit() | 30 | * Unit() |
31 | * { | 31 | * { |
32 | * setName("Example"); | 32 | * setName("Example"); |
33 | * addTest( Unit::test ); | 33 | * addTest( Unit::test ); |
34 | * } | 34 | * } |
35 | * | 35 | * |
36 | * virtual ~Unit() { } | 36 | * virtual ~Unit() { } |
37 | * | 37 | * |
38 | * // | 38 | * // |
39 | * // Tests go here | 39 | * // Tests go here |
40 | * // | 40 | * // |
41 | * void test() | 41 | * void test() |
42 | * { | 42 | * { |
43 | * unitTest( 1 == 1 ); | 43 | * unitTest( 1 == 1 ); |
44 | * } | 44 | * } |
45 | * }; | 45 | * }; |
46 | * | 46 | * |
47 | * int main( int argc, char *argv[] ) | 47 | * int main( int argc, char *argv[] ) |
48 | * { | 48 | * { |
49 | * return Unit().run( argc, argv ); | 49 | * return Unit().run( argc, argv ); |
50 | * } | 50 | * } |
51 | * | 51 | * |
52 | @endcode | 52 | @endcode |
53 | * The main function can contain other things, but using this one exactly | 53 | * The main function can contain other things, but using this one exactly |
54 | * makes all of the test suites work exactly the same. Using the optional | 54 | * makes all of the test suites work exactly the same. Using the optional |
55 | * setName at the top of the constructor replaces the class name with the | 55 | * setName at the top of the constructor replaces the class name with the |
56 | * chosen name when printing out stats and info. | 56 | * chosen name when printing out stats and info. |
57 | */ | 57 | */ |
58 | class UnitSuite | 58 | class UnitSuite |
59 | { | 59 | { |
60 | public: | 60 | public: |
61 | UnitSuite(); | 61 | UnitSuite(); |
62 | UnitSuite( int iOptions ); | 62 | UnitSuite( int iOptions ); |
63 | virtual ~UnitSuite(); | 63 | virtual ~UnitSuite(); |
64 | 64 | ||
65 | int run( int argc=0, char *argv[]=NULL ); | 65 | int run( int argc=0, char *argv[]=NULL ); |
66 | 66 | ||
67 | Bu::File tempFile( Bu::String &sFileName ); | 67 | Bu::File tempFile( Bu::String &sFileName ); |
68 | 68 | ||
69 | typedef void (UnitSuite::*Test)(); | 69 | typedef void (UnitSuite::*Test)(); |
70 | 70 | ||
71 | class Failed | 71 | class Failed |
72 | { | 72 | { |
73 | public: | 73 | public: |
74 | Failed() : str(""), bFile( false ) { } | 74 | Failed() : str(""), bFile( false ) { } |
75 | Failed( const String &s ) : str( s ), bFile( false ) { } | 75 | Failed( const String &s ) : str( s ), bFile( false ) { } |
76 | Failed( const String &s, const String &sFile, int nLine ) : | 76 | Failed( const String &s, const String &sFile, int nLine ) : |
77 | str( s ), sFile( sFile ), nLine( nLine ), bFile( true ) { } | 77 | str( s ), sFile( sFile ), nLine( nLine ), bFile( true ) { } |
78 | 78 | ||
79 | String str; | 79 | String str; |
80 | String sFile; | 80 | String sFile; |
81 | int nLine; | 81 | int nLine; |
82 | bool bFile; | 82 | bool bFile; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | enum | 85 | enum |
86 | { | 86 | { |
87 | optStopOnError = 0x000001 | 87 | optStopOnError = 0x000001 |
88 | }; | 88 | }; |
89 | 89 | ||
90 | enum Expect | 90 | enum Expect |
91 | { | 91 | { |
92 | expectPass, | 92 | expectPass, |
93 | expectFail | 93 | expectFail |
94 | }; | 94 | }; |
95 | 95 | ||
96 | protected: | 96 | protected: |
97 | void add( Test fTest, const Bu::String &sName, Expect e=expectPass ); | 97 | void add( Test fTest, const Bu::String &sName, Expect e=expectPass ); |
98 | void setName( const String &sName ); | 98 | void setName( const String &sName ); |
99 | 99 | ||
100 | void dispProgress(); | 100 | void dispProgress(); |
101 | void setStepCount( int iSteps ); | 101 | void setStepCount( int iSteps ); |
102 | void incProgress( int iAmnt = 1 ); | 102 | void incProgress( int iAmnt = 1 ); |
103 | void setProgress( int iAmnt ); | 103 | void setProgress( int iAmnt ); |
104 | 104 | ||
105 | private: | 105 | private: |
106 | int onListCases( Bu::Array<Bu::String> aParam ); | 106 | int onListCases( Bu::Array<Bu::String> aParam ); |
107 | int onAddTest( Bu::Array<Bu::String> aParam ); | 107 | int onAddTest( Bu::Array<Bu::String> aParam ); |
108 | 108 | ||
109 | private: | 109 | private: |
110 | typedef struct TestInfo | 110 | typedef struct TestInfo |
111 | { | 111 | { |
112 | String sName; | 112 | String sName; |
113 | Test fTest; | 113 | Test fTest; |
114 | Expect eExpect; | 114 | Expect eExpect; |
115 | } TestInfo; | 115 | } TestInfo; |
116 | 116 | ||
117 | typedef Bu::List<TestInfo> TestList; | 117 | typedef Bu::List<TestInfo> TestList; |
118 | TestList lTests; | 118 | TestList lTests; |
119 | String sSuiteName; | 119 | String sSuiteName; |
120 | 120 | ||
121 | int iOptions; | 121 | int iOptions; |
122 | 122 | ||
123 | typedef Bu::List<Bu::String> StrList; | 123 | typedef Bu::List<Bu::String> StrList; |
124 | StrList lFileCleanup; | 124 | StrList lFileCleanup; |
125 | int iNameWidth; | 125 | int iNameWidth; |
126 | int iStepCount; | 126 | int iStepCount; |
127 | int iProgress; | 127 | int iProgress; |
128 | time_t tLastUpdate; | 128 | time_t tLastUpdate; |
129 | 129 | ||
130 | Bu::Hash<Bu::String, bool> hSelTests; | 130 | Bu::Hash<Bu::String, bool> hSelTests; |
131 | }; | 131 | }; |
132 | 132 | ||
133 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); | 133 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); |
134 | } | 134 | } |
135 | 135 | ||
136 | #define addTest( fn ) add( static_cast<Bu::UnitSuite::Test>(&fn), #fn ) | 136 | #define addTest( fn ) add( static_cast<Bu::UnitSuite::Test>(&fn), #fn ) |
137 | #define unitTest( tst ) if( !(tst) ) \ | 137 | #define unitTest( tst ) if( !(tst) ) \ |
138 | { \ | 138 | { \ |
139 | throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ | 139 | throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ |
140 | } else (void)0 | 140 | } else (void)0 |
141 | #define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) | 141 | #define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) |
142 | 142 | ||
diff --git a/src/stable/util.cpp b/src/stable/util.cpp index b42e040..ff9901b 100644 --- a/src/stable/util.cpp +++ b/src/stable/util.cpp | |||
@@ -9,57 +9,57 @@ | |||
9 | 9 | ||
10 | int Bu::getDaysInMonth( int iMonth, int iYear ) | 10 | int Bu::getDaysInMonth( int iMonth, int iYear ) |
11 | { | 11 | { |
12 | if( iMonth > 11 ) | 12 | if( iMonth > 11 ) |
13 | { | 13 | { |
14 | iYear += iMonth/12; | 14 | iYear += iMonth/12; |
15 | iMonth = iMonth%12; | 15 | iMonth = iMonth%12; |
16 | } | 16 | } |
17 | switch( iMonth ) | 17 | switch( iMonth ) |
18 | { | 18 | { |
19 | case 0: | 19 | case 0: |
20 | case 2: | 20 | case 2: |
21 | case 4: | 21 | case 4: |
22 | case 6: | 22 | case 6: |
23 | case 7: | 23 | case 7: |
24 | case 9: | 24 | case 9: |
25 | case 11: | 25 | case 11: |
26 | return 31; | 26 | return 31; |
27 | break; | 27 | break; |
28 | 28 | ||
29 | case 3: | 29 | case 3: |
30 | case 5: | 30 | case 5: |
31 | case 8: | 31 | case 8: |
32 | case 10: | 32 | case 10: |
33 | return 30; | 33 | return 30; |
34 | break; | 34 | break; |
35 | 35 | ||
36 | case 1: | 36 | case 1: |
37 | if( iYear%400 == 0 ) | 37 | if( iYear%400 == 0 ) |
38 | return 29; | 38 | return 29; |
39 | if( iYear%100 == 0 ) | 39 | if( iYear%100 == 0 ) |
40 | return 28; | 40 | return 28; |
41 | if( iYear%4 == 0 ) | 41 | if( iYear%4 == 0 ) |
42 | return 29; | 42 | return 29; |
43 | return 28; | 43 | return 28; |
44 | break; | 44 | break; |
45 | 45 | ||
46 | default: | 46 | default: |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
49 | } | 49 | } |
50 | void Bu::memcpy( void *pDest, const void *pSrc, size_t iBytes ) | 50 | void Bu::memcpy( void *pDest, const void *pSrc, size_t iBytes ) |
51 | { | 51 | { |
52 | #ifdef VALTEST | 52 | #ifdef VALTEST |
53 | const char *src = (const char *)pSrc; | 53 | const char *src = (const char *)pSrc; |
54 | char *dest = (char *)pDest; | 54 | char *dest = (char *)pDest; |
55 | for( int j = 0; j < count; j++ ) | 55 | for( int j = 0; j < count; j++ ) |
56 | { | 56 | { |
57 | *dest = *src; | 57 | *dest = *src; |
58 | dest++; | 58 | dest++; |
59 | src++; | 59 | src++; |
60 | } | 60 | } |
61 | #else | 61 | #else |
62 | ::memcpy( pDest, pSrc, iBytes ); | 62 | ::memcpy( pDest, pSrc, iBytes ); |
63 | #endif | 63 | #endif |
64 | } | 64 | } |
65 | 65 | ||
diff --git a/src/stable/util.h b/src/stable/util.h index 4514281..ab9cd08 100644 --- a/src/stable/util.h +++ b/src/stable/util.h | |||
@@ -25,158 +25,158 @@ | |||
25 | 25 | ||
26 | namespace Bu | 26 | namespace Bu |
27 | { | 27 | { |
28 | /** | 28 | /** |
29 | * Swap the value of two variables, uses references, so it's pretty safe. | 29 | * Swap the value of two variables, uses references, so it's pretty safe. |
30 | * Objects passed in must support a basic assignemnt operator (=); | 30 | * Objects passed in must support a basic assignemnt operator (=); |
31 | *@param a Variable to recieve the value of parameter b | 31 | *@param a Variable to recieve the value of parameter b |
32 | *@param b Variable to recieve the value of parameter a | 32 | *@param b Variable to recieve the value of parameter a |
33 | */ | 33 | */ |
34 | template<typename item> | 34 | template<typename item> |
35 | void swap( item &a, item &b ) | 35 | void swap( item &a, item &b ) |
36 | { | 36 | { |
37 | item tmp = a; | 37 | item tmp = a; |
38 | a = b; | 38 | a = b; |
39 | b = tmp; | 39 | b = tmp; |
40 | } | 40 | } |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * Finds the lesser of the two objects, objects passed in must be | 43 | * Finds the lesser of the two objects, objects passed in must be |
44 | * less-than-comparable. | 44 | * less-than-comparable. |
45 | *@param a A value to test. | 45 | *@param a A value to test. |
46 | *@param b Another value to test. | 46 | *@param b Another value to test. |
47 | *@returns A reference to the lesser of a or b. | 47 | *@returns A reference to the lesser of a or b. |
48 | */ | 48 | */ |
49 | template<typename item> | 49 | template<typename item> |
50 | const item &buMin( const item &a, const item &b ) | 50 | const item &buMin( const item &a, const item &b ) |
51 | { | 51 | { |
52 | return a<b?a:b; | 52 | return a<b?a:b; |
53 | } | 53 | } |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Finds the lesser of the two objects, objects passed in must be | 56 | * Finds the lesser of the two objects, objects passed in must be |
57 | * less-than-comparable. | 57 | * less-than-comparable. |
58 | *@param a A value to test. | 58 | *@param a A value to test. |
59 | *@param b Another value to test. | 59 | *@param b Another value to test. |
60 | *@returns A reference to the lesser of a or b. | 60 | *@returns A reference to the lesser of a or b. |
61 | */ | 61 | */ |
62 | template<typename item> | 62 | template<typename item> |
63 | item &buMin( item &a, item &b ) | 63 | item &buMin( item &a, item &b ) |
64 | { | 64 | { |
65 | return a<b?a:b; | 65 | return a<b?a:b; |
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * Finds the greater of the two objects, objects passed in must be | 69 | * Finds the greater of the two objects, objects passed in must be |
70 | * less-than-comparable. | 70 | * less-than-comparable. |
71 | *@param a A value to test. | 71 | *@param a A value to test. |
72 | *@param b Another value to test. | 72 | *@param b Another value to test. |
73 | *@returns A reference to the greater of a or b. | 73 | *@returns A reference to the greater of a or b. |
74 | */ | 74 | */ |
75 | template<typename item> | 75 | template<typename item> |
76 | const item &buMax( const item &a, const item &b ) | 76 | const item &buMax( const item &a, const item &b ) |
77 | { | 77 | { |
78 | return b<a?a:b; | 78 | return b<a?a:b; |
79 | } | 79 | } |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * Finds the greater of the two objects, objects passed in must be | 82 | * Finds the greater of the two objects, objects passed in must be |
83 | * less-than-comparable. | 83 | * less-than-comparable. |
84 | *@param a A value to test. | 84 | *@param a A value to test. |
85 | *@param b Another value to test. | 85 | *@param b Another value to test. |
86 | *@returns A reference to the greater of a or b. | 86 | *@returns A reference to the greater of a or b. |
87 | */ | 87 | */ |
88 | template<typename item> | 88 | template<typename item> |
89 | item &buMax( item &a, item &b ) | 89 | item &buMax( item &a, item &b ) |
90 | { | 90 | { |
91 | return b<a?a:b; | 91 | return b<a?a:b; |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * Given three objects this finds the one between the other two. | 95 | * Given three objects this finds the one between the other two. |
96 | *@param a A value to test. | 96 | *@param a A value to test. |
97 | *@param b Another value to test. | 97 | *@param b Another value to test. |
98 | *@param c Yet another value to test. | 98 | *@param c Yet another value to test. |
99 | *@returns A reference to the mid-value of a, b, and c. | 99 | *@returns A reference to the mid-value of a, b, and c. |
100 | */ | 100 | */ |
101 | template<typename item> | 101 | template<typename item> |
102 | const item &buMid( const item &a, const item &b, const item &c ) | 102 | const item &buMid( const item &a, const item &b, const item &c ) |
103 | { | 103 | { |
104 | return buMin( buMax( a, b ), c ); | 104 | return buMin( buMax( a, b ), c ); |
105 | } | 105 | } |
106 | 106 | ||
107 | /** | 107 | /** |
108 | * Given three objects this finds the one between the other two. | 108 | * Given three objects this finds the one between the other two. |
109 | *@param a A value to test. | 109 | *@param a A value to test. |
110 | *@param b Another value to test. | 110 | *@param b Another value to test. |
111 | *@param c Yet another value to test. | 111 | *@param c Yet another value to test. |
112 | *@returns A reference to the mid-value of a, b, and c. | 112 | *@returns A reference to the mid-value of a, b, and c. |
113 | */ | 113 | */ |
114 | template<typename item> | 114 | template<typename item> |
115 | item &buMid( item &a, item &b, item &c ) | 115 | item &buMid( item &a, item &b, item &c ) |
116 | { | 116 | { |
117 | return buMin( buMax( a, b ), c ); | 117 | return buMin( buMax( a, b ), c ); |
118 | } | 118 | } |
119 | 119 | ||
120 | // | 120 | // |
121 | // Basic comparison functors | 121 | // Basic comparison functors |
122 | // | 122 | // |
123 | /** | 123 | /** |
124 | * Simple less-than comparison functor. Objects being used should be | 124 | * Simple less-than comparison functor. Objects being used should be |
125 | * less-than-comparable. | 125 | * less-than-comparable. |
126 | */ | 126 | */ |
127 | template<typename item> | 127 | template<typename item> |
128 | struct __basicLTCmp | 128 | struct __basicLTCmp |
129 | { | 129 | { |
130 | bool operator()( const item &a, const item &b ) | 130 | bool operator()( const item &a, const item &b ) |
131 | { | 131 | { |
132 | return a < b; | 132 | return a < b; |
133 | } | 133 | } |
134 | }; | 134 | }; |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * Simple greater-than comparison functor. Objects being used should be | 137 | * Simple greater-than comparison functor. Objects being used should be |
138 | * greater-than-comparable. | 138 | * greater-than-comparable. |
139 | */ | 139 | */ |
140 | template<typename item> | 140 | template<typename item> |
141 | struct __basicGTCmp | 141 | struct __basicGTCmp |
142 | { | 142 | { |
143 | bool operator()( const item &a, const item &b ) | 143 | bool operator()( const item &a, const item &b ) |
144 | { | 144 | { |
145 | return a > b; | 145 | return a > b; |
146 | } | 146 | } |
147 | }; | 147 | }; |
148 | 148 | ||
149 | /** | 149 | /** |
150 | * As __basicLTCmp but dereferences the passed in pointers before comparing. | 150 | * As __basicLTCmp but dereferences the passed in pointers before comparing. |
151 | */ | 151 | */ |
152 | template<typename item> | 152 | template<typename item> |
153 | struct __basicPtrLTCmp | 153 | struct __basicPtrLTCmp |
154 | { | 154 | { |
155 | bool operator()( const item &a, const item &b ) | 155 | bool operator()( const item &a, const item &b ) |
156 | { | 156 | { |
157 | return *a < *b; | 157 | return *a < *b; |
158 | } | 158 | } |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * As __basicGTCmp but dereferences the passed in pointers before comparing. | 162 | * As __basicGTCmp but dereferences the passed in pointers before comparing. |
163 | */ | 163 | */ |
164 | template<typename item> | 164 | template<typename item> |
165 | struct __basicPtrGTCmp | 165 | struct __basicPtrGTCmp |
166 | { | 166 | { |
167 | bool operator()( const item &a, const item &b ) | 167 | bool operator()( const item &a, const item &b ) |
168 | { | 168 | { |
169 | return *a > *b; | 169 | return *a > *b; |
170 | } | 170 | } |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /** | 173 | /** |
174 | * Get the number of days in the month in the gregorian calendar, taking | 174 | * Get the number of days in the month in the gregorian calendar, taking |
175 | * leap years into account. | 175 | * leap years into account. |
176 | */ | 176 | */ |
177 | int getDaysInMonth( int iMonth, int iYear ); | 177 | int getDaysInMonth( int iMonth, int iYear ); |
178 | 178 | ||
179 | void memcpy( void *pDest, const void *pSrc, size_t iBytes ); | 179 | void memcpy( void *pDest, const void *pSrc, size_t iBytes ); |
180 | }; | 180 | }; |
181 | 181 | ||
182 | #endif | 182 | #endif |
diff --git a/src/stable/variant.cpp b/src/stable/variant.cpp index 674ae04..d724fa7 100644 --- a/src/stable/variant.cpp +++ b/src/stable/variant.cpp | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | Formatter &operator<<( Formatter &f, const String &s ); | 14 | Formatter &operator<<( Formatter &f, const String &s ); |
15 | }; | 15 | }; |
16 | 16 | ||
17 | Bu::VariantTypeRoot::VariantTypeRoot() | 17 | Bu::VariantTypeRoot::VariantTypeRoot() |
@@ -23,84 +23,84 @@ Bu::VariantTypeRoot::~VariantTypeRoot() | |||
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::Variant::Variant() : | 25 | Bu::Variant::Variant() : |
26 | pCore( NULL ) | 26 | pCore( NULL ) |
27 | { | 27 | { |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::Variant::Variant( const Variant &v ) : | 30 | Bu::Variant::Variant( const Variant &v ) : |
31 | pCore( NULL ) | 31 | pCore( NULL ) |
32 | { | 32 | { |
33 | if( v.pCore ) | 33 | if( v.pCore ) |
34 | { | 34 | { |
35 | pCore = v.pCore->clone(); | 35 | pCore = v.pCore->clone(); |
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | Bu::Variant::Variant( const char *t ) : | 39 | Bu::Variant::Variant( const char *t ) : |
40 | pCore( NULL ) | 40 | pCore( NULL ) |
41 | { | 41 | { |
42 | set( Bu::String( t ) ); | 42 | set( Bu::String( t ) ); |
43 | } | 43 | } |
44 | 44 | ||
45 | Bu::Variant::~Variant() | 45 | Bu::Variant::~Variant() |
46 | { | 46 | { |
47 | if( pCore ) | 47 | if( pCore ) |
48 | { | 48 | { |
49 | delete pCore; | 49 | delete pCore; |
50 | pCore = NULL; | 50 | pCore = NULL; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::String Bu::Variant::toString() const | 54 | Bu::String Bu::Variant::toString() const |
55 | { | 55 | { |
56 | if( getType() == typeid( Bu::String ) ) | 56 | if( getType() == typeid( Bu::String ) ) |
57 | { | 57 | { |
58 | return get<Bu::String>(); | 58 | return get<Bu::String>(); |
59 | } | 59 | } |
60 | else | 60 | else |
61 | { | 61 | { |
62 | Bu::MemBuf mb; | 62 | Bu::MemBuf mb; |
63 | Bu::Formatter f( mb ); | 63 | Bu::Formatter f( mb ); |
64 | f << *this; | 64 | f << *this; |
65 | return mb.getString(); | 65 | return mb.getString(); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | bool Bu::Variant::isSet() const | 69 | bool Bu::Variant::isSet() const |
70 | { | 70 | { |
71 | return pCore != NULL; | 71 | return pCore != NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | const std::type_info &Bu::Variant::getType() const | 74 | const std::type_info &Bu::Variant::getType() const |
75 | { | 75 | { |
76 | if( !pCore ) | 76 | if( !pCore ) |
77 | { | 77 | { |
78 | throw Bu::ExceptionBase("No data!"); | 78 | throw Bu::ExceptionBase("No data!"); |
79 | } | 79 | } |
80 | return pCore->getType(); | 80 | return pCore->getType(); |
81 | } | 81 | } |
82 | 82 | ||
83 | Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs ) | 83 | Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs ) |
84 | { | 84 | { |
85 | if( pCore ) | 85 | if( pCore ) |
86 | { | 86 | { |
87 | delete pCore; | 87 | delete pCore; |
88 | pCore = NULL; | 88 | pCore = NULL; |
89 | } | 89 | } |
90 | if( rhs.pCore ) | 90 | if( rhs.pCore ) |
91 | { | 91 | { |
92 | pCore = rhs.pCore->clone(); | 92 | pCore = rhs.pCore->clone(); |
93 | } | 93 | } |
94 | 94 | ||
95 | return *this; | 95 | return *this; |
96 | } | 96 | } |
97 | 97 | ||
98 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v ) | 98 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v ) |
99 | { | 99 | { |
100 | if( !v.pCore ) | 100 | if( !v.pCore ) |
101 | return f << "(null)"; | 101 | return f << "(null)"; |
102 | 102 | ||
103 | v.pCore->format( f ); | 103 | v.pCore->format( f ); |
104 | return f; | 104 | return f; |
105 | } | 105 | } |
106 | 106 | ||
diff --git a/src/stable/variant.h b/src/stable/variant.h index 6837954..227e246 100644 --- a/src/stable/variant.h +++ b/src/stable/variant.h | |||
@@ -20,217 +20,217 @@ | |||
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | class String; | 23 | class String; |
24 | class Formatter; | 24 | class Formatter; |
25 | class Variant; | 25 | class Variant; |
26 | /** @cond DEVEL */ | 26 | /** @cond DEVEL */ |
27 | template<class t> class VariantType; | 27 | template<class t> class VariantType; |
28 | 28 | ||
29 | class VariantTypeRoot | 29 | class VariantTypeRoot |
30 | { | 30 | { |
31 | public: | 31 | public: |
32 | VariantTypeRoot(); | 32 | VariantTypeRoot(); |
33 | virtual ~VariantTypeRoot(); | 33 | virtual ~VariantTypeRoot(); |
34 | 34 | ||
35 | virtual const std::type_info &getType() const=0; | 35 | virtual const std::type_info &getType() const=0; |
36 | virtual VariantTypeRoot *clone() const=0; | 36 | virtual VariantTypeRoot *clone() const=0; |
37 | virtual void format( Bu::Formatter &f ) const=0; | 37 | virtual void format( Bu::Formatter &f ) const=0; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | template<class t> | 40 | template<class t> |
41 | class VariantType : public VariantTypeRoot | 41 | class VariantType : public VariantTypeRoot |
42 | { | 42 | { |
43 | friend class Variant; | 43 | friend class Variant; |
44 | private: | 44 | private: |
45 | VariantType() | 45 | VariantType() |
46 | { | 46 | { |
47 | } | 47 | } |
48 | 48 | ||
49 | VariantType( const t &d ) : | 49 | VariantType( const t &d ) : |
50 | data( d ) | 50 | data( d ) |
51 | { | 51 | { |
52 | } | 52 | } |
53 | 53 | ||
54 | VariantType( const VariantType<t> &vt ) : | 54 | VariantType( const VariantType<t> &vt ) : |
55 | data( vt.data ) | 55 | data( vt.data ) |
56 | { | 56 | { |
57 | } | 57 | } |
58 | 58 | ||
59 | virtual ~VariantType() | 59 | virtual ~VariantType() |
60 | { | 60 | { |
61 | } | 61 | } |
62 | 62 | ||
63 | public: | 63 | public: |
64 | t &getData() | 64 | t &getData() |
65 | { | 65 | { |
66 | return data; | 66 | return data; |
67 | } | 67 | } |
68 | 68 | ||
69 | const t &getData() const | 69 | const t &getData() const |
70 | { | 70 | { |
71 | return data; | 71 | return data; |
72 | } | 72 | } |
73 | 73 | ||
74 | virtual void format( Formatter &f ) const | 74 | virtual void format( Formatter &f ) const |
75 | { | 75 | { |
76 | f << data; | 76 | f << data; |
77 | } | 77 | } |
78 | 78 | ||
79 | virtual const std::type_info &getType() const | 79 | virtual const std::type_info &getType() const |
80 | { | 80 | { |
81 | return typeid( data ); | 81 | return typeid( data ); |
82 | } | 82 | } |
83 | 83 | ||
84 | VariantType<t> operator=( const t &rhs ) | 84 | VariantType<t> operator=( const t &rhs ) |
85 | { | 85 | { |
86 | data = rhs; | 86 | data = rhs; |
87 | 87 | ||
88 | return *this; | 88 | return *this; |
89 | } | 89 | } |
90 | 90 | ||
91 | virtual VariantTypeRoot *clone() const | 91 | virtual VariantTypeRoot *clone() const |
92 | { | 92 | { |
93 | return new VariantType<t>( *this ); | 93 | return new VariantType<t>( *this ); |
94 | } | 94 | } |
95 | 95 | ||
96 | private: | 96 | private: |
97 | t data; | 97 | t data; |
98 | }; | 98 | }; |
99 | /** @endcond */ | 99 | /** @endcond */ |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * Store any data type and access it safely. Variant gives you a way to | 102 | * Store any data type and access it safely. Variant gives you a way to |
103 | * pass arbitrary data types around without having to worry about what | 103 | * pass arbitrary data types around without having to worry about what |
104 | * type a variable is. It allows code to be easily extended and to manage | 104 | * type a variable is. It allows code to be easily extended and to manage |
105 | * data without having to know what type it is ahead of time. | 105 | * data without having to know what type it is ahead of time. |
106 | * | 106 | * |
107 | * Because of the generic method that this class was implemented it may seem | 107 | * Because of the generic method that this class was implemented it may seem |
108 | * to have some drawbacks compared to other Variant classes you may have | 108 | * to have some drawbacks compared to other Variant classes you may have |
109 | * seen, however it is fairly easy to get it to do just about anything you | 109 | * seen, however it is fairly easy to get it to do just about anything you |
110 | * may need. It is also very low overhead. On most compilers the class | 110 | * may need. It is also very low overhead. On most compilers the class |
111 | * itself has only 3 words of overhead + the size of the variable you store | 111 | * itself has only 3 words of overhead + the size of the variable you store |
112 | * in it. And, since many parts of it are templatized they can often be | 112 | * in it. And, since many parts of it are templatized they can often be |
113 | * optimized quite a bit. | 113 | * optimized quite a bit. |
114 | */ | 114 | */ |
115 | class Variant | 115 | class Variant |
116 | { | 116 | { |
117 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); | 117 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); |
118 | public: | 118 | public: |
119 | Variant(); | 119 | Variant(); |
120 | Variant( const Variant &v ); | 120 | Variant( const Variant &v ); |
121 | Variant( const char *t ); | 121 | Variant( const char *t ); |
122 | template<class t> | 122 | template<class t> |
123 | Variant( const t &v ) : | 123 | Variant( const t &v ) : |
124 | pCore( new VariantType<t>() ) | 124 | pCore( new VariantType<t>() ) |
125 | { | 125 | { |
126 | (*dynamic_cast<VariantType<t> *>(pCore)) = v; | 126 | (*dynamic_cast<VariantType<t> *>(pCore)) = v; |
127 | } | 127 | } |
128 | virtual ~Variant(); | 128 | virtual ~Variant(); |
129 | 129 | ||
130 | Bu::String toString() const; | 130 | Bu::String toString() const; |
131 | bool isSet() const; | 131 | bool isSet() const; |
132 | const std::type_info &getType() const; | 132 | const std::type_info &getType() const; |
133 | 133 | ||
134 | Variant &operator=( const Variant &rhs ); | 134 | Variant &operator=( const Variant &rhs ); |
135 | 135 | ||
136 | template<class t> | 136 | template<class t> |
137 | Variant &operator=( const t &rhs ) | 137 | Variant &operator=( const t &rhs ) |
138 | { | 138 | { |
139 | if( pCore ) // && pCore->getType() != typeid(t) ) | 139 | if( pCore ) // && pCore->getType() != typeid(t) ) |
140 | { | 140 | { |
141 | delete pCore; | 141 | delete pCore; |
142 | pCore = NULL; | 142 | pCore = NULL; |
143 | } | 143 | } |
144 | pCore = new VariantType<t>(); | 144 | pCore = new VariantType<t>(); |
145 | (*dynamic_cast<VariantType<t> *>(pCore)) = rhs; | 145 | (*dynamic_cast<VariantType<t> *>(pCore)) = rhs; |
146 | return *this; | 146 | return *this; |
147 | } | 147 | } |
148 | 148 | ||
149 | template<class t> | 149 | template<class t> |
150 | t &get() | 150 | t &get() |
151 | { | 151 | { |
152 | if( !pCore ) | 152 | if( !pCore ) |
153 | { | 153 | { |
154 | throw Bu::ExceptionBase("No data!"); | 154 | throw Bu::ExceptionBase("No data!"); |
155 | } | 155 | } |
156 | if( pCore->getType() != typeid(t) ) | 156 | if( pCore->getType() != typeid(t) ) |
157 | { | 157 | { |
158 | throw Bu::ExceptionBase("Invalid type conversion."); | 158 | throw Bu::ExceptionBase("Invalid type conversion."); |
159 | } | 159 | } |
160 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 160 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
161 | } | 161 | } |
162 | 162 | ||
163 | template<class t> | 163 | template<class t> |
164 | t &get() const | 164 | t &get() const |
165 | { | 165 | { |
166 | if( !pCore ) | 166 | if( !pCore ) |
167 | { | 167 | { |
168 | throw Bu::ExceptionBase("No data!"); | 168 | throw Bu::ExceptionBase("No data!"); |
169 | } | 169 | } |
170 | if( pCore->getType() != typeid(t) ) | 170 | if( pCore->getType() != typeid(t) ) |
171 | { | 171 | { |
172 | throw Bu::ExceptionBase("Invalid type conversion."); | 172 | throw Bu::ExceptionBase("Invalid type conversion."); |
173 | } | 173 | } |
174 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 174 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
175 | } | 175 | } |
176 | 176 | ||
177 | template<class t> | 177 | template<class t> |
178 | void set( const t &val ) | 178 | void set( const t &val ) |
179 | { | 179 | { |
180 | if( pCore && pCore->getType() != typeid(t) ) | 180 | if( pCore && pCore->getType() != typeid(t) ) |
181 | { | 181 | { |
182 | delete pCore; | 182 | delete pCore; |
183 | pCore = NULL; | 183 | pCore = NULL; |
184 | } | 184 | } |
185 | pCore = new VariantType<t>(); | 185 | pCore = new VariantType<t>(); |
186 | (*dynamic_cast<VariantType<t> *>(pCore)) = val; | 186 | (*dynamic_cast<VariantType<t> *>(pCore)) = val; |
187 | } | 187 | } |
188 | 188 | ||
189 | template<class t> | 189 | template<class t> |
190 | bool isType() const | 190 | bool isType() const |
191 | { | 191 | { |
192 | return pCore->getType() == typeid(t); | 192 | return pCore->getType() == typeid(t); |
193 | } | 193 | } |
194 | 194 | ||
195 | template<class t> | 195 | template<class t> |
196 | operator t() | 196 | operator t() |
197 | { | 197 | { |
198 | if( !pCore ) | 198 | if( !pCore ) |
199 | { | 199 | { |
200 | throw Bu::ExceptionBase("No data!"); | 200 | throw Bu::ExceptionBase("No data!"); |
201 | } | 201 | } |
202 | if( pCore->getType() != typeid(t) ) | 202 | if( pCore->getType() != typeid(t) ) |
203 | { | 203 | { |
204 | throw Bu::ExceptionBase("Invalid type conversion."); | 204 | throw Bu::ExceptionBase("Invalid type conversion."); |
205 | } | 205 | } |
206 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 206 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
207 | } | 207 | } |
208 | 208 | ||
209 | template<class t> | 209 | template<class t> |
210 | operator t() const | 210 | operator t() const |
211 | { | 211 | { |
212 | if( !pCore ) | 212 | if( !pCore ) |
213 | { | 213 | { |
214 | throw Bu::ExceptionBase("No data!"); | 214 | throw Bu::ExceptionBase("No data!"); |
215 | } | 215 | } |
216 | if( pCore->getType() != typeid(t) ) | 216 | if( pCore->getType() != typeid(t) ) |
217 | { | 217 | { |
218 | throw Bu::ExceptionBase("Invalid type conversion."); | 218 | throw Bu::ExceptionBase("Invalid type conversion."); |
219 | } | 219 | } |
220 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 220 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
221 | } | 221 | } |
222 | 222 | ||
223 | private: | 223 | private: |
224 | VariantTypeRoot *pCore; | 224 | VariantTypeRoot *pCore; |
225 | }; | 225 | }; |
226 | /* | 226 | /* |
227 | template<class t> | 227 | template<class t> |
228 | Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt ) | 228 | Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt ) |
229 | { | 229 | { |
230 | return f << vt.getData; | 230 | return f << vt.getData; |
231 | }*/ | 231 | }*/ |
232 | 232 | ||
233 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); | 233 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); |
234 | }; | 234 | }; |
235 | 235 | ||
236 | #endif | 236 | #endif |
diff --git a/src/tests/base64.cpp b/src/tests/base64.cpp index 1e1892d..640118a 100644 --- a/src/tests/base64.cpp +++ b/src/tests/base64.cpp | |||
@@ -11,73 +11,73 @@ | |||
11 | 11 | ||
12 | int main( int argc, char *argv[] ) | 12 | int main( int argc, char *argv[] ) |
13 | { | 13 | { |
14 | argc--,argv++; | 14 | argc--,argv++; |
15 | 15 | ||
16 | if( argc < 3 ) | 16 | if( argc < 3 ) |
17 | return 0; | 17 | return 0; |
18 | 18 | ||
19 | if( argv[0][0] == 'e' ) | 19 | if( argv[0][0] == 'e' ) |
20 | { | 20 | { |
21 | argv++; | 21 | argv++; |
22 | Bu::File fIn( argv[0], Bu::File::Read ); | 22 | Bu::File fIn( argv[0], Bu::File::Read ); |
23 | Bu::File fOut( argv[1], Bu::File::WriteNew ); | 23 | Bu::File fOut( argv[1], Bu::File::WriteNew ); |
24 | Bu::Base64 bOut( fOut ); | 24 | Bu::Base64 bOut( fOut ); |
25 | 25 | ||
26 | char buf[900]; | 26 | char buf[900]; |
27 | for(;;) | 27 | for(;;) |
28 | { | 28 | { |
29 | int iRead = fIn.read( buf, 900 ); | 29 | int iRead = fIn.read( buf, 900 ); |
30 | bOut.write( buf, iRead ); | 30 | bOut.write( buf, iRead ); |
31 | if( iRead < 900 ) | 31 | if( iRead < 900 ) |
32 | break; | 32 | break; |
33 | } | 33 | } |
34 | } | 34 | } |
35 | else if( argv[0][0] == 'd' ) | 35 | else if( argv[0][0] == 'd' ) |
36 | { | 36 | { |
37 | argv++; | 37 | argv++; |
38 | Bu::File fIn( argv[0], Bu::File::Read ); | 38 | Bu::File fIn( argv[0], Bu::File::Read ); |
39 | Bu::File fOut( argv[1], Bu::File::WriteNew ); | 39 | Bu::File fOut( argv[1], Bu::File::WriteNew ); |
40 | Bu::Base64 bIn( fIn ); | 40 | Bu::Base64 bIn( fIn ); |
41 | 41 | ||
42 | char buf[1024]; | 42 | char buf[1024]; |
43 | for(;;) | 43 | for(;;) |
44 | { | 44 | { |
45 | int iRead = bIn.read( buf, 1024 ); | 45 | int iRead = bIn.read( buf, 1024 ); |
46 | printf("Read %d bytes.\n", iRead ); | 46 | printf("Read %d bytes.\n", iRead ); |
47 | fOut.write( buf, iRead ); | 47 | fOut.write( buf, iRead ); |
48 | if( iRead == 0 ) | 48 | if( iRead == 0 ) |
49 | break; | 49 | break; |
50 | } | 50 | } |
51 | } | 51 | } |
52 | else if( argv[0][0] == 'D' ) | 52 | else if( argv[0][0] == 'D' ) |
53 | { | 53 | { |
54 | argv++; | 54 | argv++; |
55 | Bu::MemBuf mIn; | 55 | Bu::MemBuf mIn; |
56 | { | 56 | { |
57 | Bu::File fIn( argv[0], Bu::File::Read ); | 57 | Bu::File fIn( argv[0], Bu::File::Read ); |
58 | char buf[1024]; | 58 | char buf[1024]; |
59 | for(;;) | 59 | for(;;) |
60 | { | 60 | { |
61 | int iRead = fIn.read( buf, 1024 ); | 61 | int iRead = fIn.read( buf, 1024 ); |
62 | mIn.write( buf, iRead ); | 62 | mIn.write( buf, iRead ); |
63 | if( iRead < 1024 ) | 63 | if( iRead < 1024 ) |
64 | break; | 64 | break; |
65 | } | 65 | } |
66 | mIn.setPos( 0 ); | 66 | mIn.setPos( 0 ); |
67 | } | 67 | } |
68 | Bu::File fOut( argv[1], Bu::File::WriteNew ); | 68 | Bu::File fOut( argv[1], Bu::File::WriteNew ); |
69 | Bu::Base64 bIn( mIn ); | 69 | Bu::Base64 bIn( mIn ); |
70 | 70 | ||
71 | char buf[1024]; | 71 | char buf[1024]; |
72 | for(;;) | 72 | for(;;) |
73 | { | 73 | { |
74 | int iRead = bIn.read( buf, 1024 ); | 74 | int iRead = bIn.read( buf, 1024 ); |
75 | printf("Read %d bytes.\n", iRead ); | 75 | printf("Read %d bytes.\n", iRead ); |
76 | fOut.write( buf, iRead ); | 76 | fOut.write( buf, iRead ); |
77 | if( iRead == 0 ) | 77 | if( iRead == 0 ) |
78 | break; | 78 | break; |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
diff --git a/src/tests/bigmyriad.cpp b/src/tests/bigmyriad.cpp index 6661bf1..9af301c 100644 --- a/src/tests/bigmyriad.cpp +++ b/src/tests/bigmyriad.cpp | |||
@@ -4,22 +4,22 @@ | |||
4 | 4 | ||
5 | int main() | 5 | int main() |
6 | { | 6 | { |
7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); | 7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); |
8 | Bu::Myriad m( f, 2048 ); | 8 | Bu::Myriad m( f, 2048 ); |
9 | 9 | ||
10 | char *buf = new char[1024*1024*10]; | 10 | char *buf = new char[1024*1024*10]; |
11 | memset( buf, 0, 1024*1024*10 ); | 11 | memset( buf, 0, 1024*1024*10 ); |
12 | 12 | ||
13 | for( int j = 0; j < 250; j++ ) | 13 | for( int j = 0; j < 250; j++ ) |
14 | { | 14 | { |
15 | m.openStream( m.createStream() ).write( buf, 1024*1024*10 ); | 15 | m.openStream( m.createStream() ).write( buf, 1024*1024*10 ); |
16 | // m.sync(); | 16 | // m.sync(); |
17 | printf("\r%03d%%", (j+1)*100/250 ); | 17 | printf("\r%03d%%", (j+1)*100/250 ); |
18 | fflush( stdout ); | 18 | fflush( stdout ); |
19 | } | 19 | } |
20 | 20 | ||
21 | printf("\n\n"); | 21 | printf("\n\n"); |
22 | 22 | ||
23 | return 0; | 23 | return 0; |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/src/tests/blowfish.cpp b/src/tests/blowfish.cpp index 7c175d4..c0aba30 100644 --- a/src/tests/blowfish.cpp +++ b/src/tests/blowfish.cpp | |||
@@ -56,72 +56,72 @@ static const char *testdat[34][3] ={ | |||
56 | 56 | ||
57 | int main( int argc, char *argv[] ) | 57 | int main( int argc, char *argv[] ) |
58 | { | 58 | { |
59 | MemBuf mb; | 59 | MemBuf mb; |
60 | { | 60 | { |
61 | BlowfishEcb bf( mb ); | 61 | BlowfishEcb bf( mb ); |
62 | bf.setPassword( "01234567" ); | 62 | bf.setPassword( "01234567" ); |
63 | for( int j = 0; j < 4; j++ ) | 63 | for( int j = 0; j < 4; j++ ) |
64 | { | 64 | { |
65 | bf.write("this is a test!!"+j, 1 ); | 65 | bf.write("this is a test!!"+j, 1 ); |
66 | } | 66 | } |
67 | bf.write("this is a test!!"+4, 12 ); | 67 | bf.write("this is a test!!"+4, 12 ); |
68 | } | 68 | } |
69 | mb.setPos( 0 ); | 69 | mb.setPos( 0 ); |
70 | BlowfishEcb bf( mb ); | 70 | BlowfishEcb bf( mb ); |
71 | bf.setPassword( "01234567" ); | 71 | bf.setPassword( "01234567" ); |
72 | for( int j = 0; j < 3; j++ ) | 72 | for( int j = 0; j < 3; j++ ) |
73 | { | 73 | { |
74 | char c; | 74 | char c; |
75 | bf.read( &c, 1 ); | 75 | bf.read( &c, 1 ); |
76 | sio << "char: '" << c << "'" << sio.nl; | 76 | sio << "char: '" << c << "'" << sio.nl; |
77 | } | 77 | } |
78 | 78 | ||
79 | char buf[100]; | 79 | char buf[100]; |
80 | int iR = bf.read( buf, 100 ); | 80 | int iR = bf.read( buf, 100 ); |
81 | buf[iR] = '\0'; | 81 | buf[iR] = '\0'; |
82 | sio << "Got(" << iR << ") = '" << buf << "'" << sio.nl; | 82 | sio << "Got(" << iR << ") = '" << buf << "'" << sio.nl; |
83 | 83 | ||
84 | return 0; | 84 | return 0; |
85 | 85 | ||
86 | for( int j = 0; j < 34; j++ ) | 86 | for( int j = 0; j < 34; j++ ) |
87 | { | 87 | { |
88 | MemBuf mb; | 88 | MemBuf mb; |
89 | BlowfishEcb bf( mb ); | 89 | BlowfishEcb bf( mb ); |
90 | bf.setPassword( decodeStr<Hex>( testdat[j][0] ) ); | 90 | bf.setPassword( decodeStr<Hex>( testdat[j][0] ) ); |
91 | bf.write( decodeStr<Hex>( testdat[j][1] ) ); | 91 | bf.write( decodeStr<Hex>( testdat[j][1] ) ); |
92 | sio << "Test " << j << ": " << (mb.getString() == decodeStr<Hex>( testdat[j][2] )) << " (" << encodeStr<Hex>( mb.getString(), true ) << " == " << testdat[j][2] << ")" << sio.nl; | 92 | sio << "Test " << j << ": " << (mb.getString() == decodeStr<Hex>( testdat[j][2] )) << " (" << encodeStr<Hex>( mb.getString(), true ) << " == " << testdat[j][2] << ")" << sio.nl; |
93 | 93 | ||
94 | mb.setPos( 0 ); | 94 | mb.setPos( 0 ); |
95 | BlowfishEcb bf2( mb ); | 95 | BlowfishEcb bf2( mb ); |
96 | bf2.setPassword( decodeStr<Hex>( testdat[j][0] ) ); | 96 | bf2.setPassword( decodeStr<Hex>( testdat[j][0] ) ); |
97 | char buf[8]; | 97 | char buf[8]; |
98 | bf2.read( buf, 8 ); | 98 | bf2.read( buf, 8 ); |
99 | 99 | ||
100 | sio << " - Back: " << (Bu::String(testdat[j][1]) == encodeStr<Hex>(String(buf,8),true)) << sio.nl; | 100 | sio << " - Back: " << (Bu::String(testdat[j][1]) == encodeStr<Hex>(String(buf,8),true)) << sio.nl; |
101 | } | 101 | } |
102 | 102 | ||
103 | { | 103 | { |
104 | File fIn("data.plain", File::Read ); | 104 | File fIn("data.plain", File::Read ); |
105 | File fOut("data.crypt", File::WriteNew ); | 105 | File fOut("data.crypt", File::WriteNew ); |
106 | 106 | ||
107 | BlowfishOfb bOut( fOut ); | 107 | BlowfishOfb bOut( fOut ); |
108 | bOut.setIv("01234567"); | 108 | bOut.setIv("01234567"); |
109 | bOut.setPassword("abcdefghijklmnop"); | 109 | bOut.setPassword("abcdefghijklmnop"); |
110 | bOut.write( fIn.readAll() ); | 110 | bOut.write( fIn.readAll() ); |
111 | } | 111 | } |
112 | { | 112 | { |
113 | File fIn("data.java", File::Read ); | 113 | File fIn("data.java", File::Read ); |
114 | File fOut("data.stuff", File::WriteNew ); | 114 | File fOut("data.stuff", File::WriteNew ); |
115 | 115 | ||
116 | BlowfishOfb bIn( fIn ); | 116 | BlowfishOfb bIn( fIn ); |
117 | bIn.setIv("01234567"); | 117 | bIn.setIv("01234567"); |
118 | bIn.setPassword("abcdefghijklmnop"); | 118 | bIn.setPassword("abcdefghijklmnop"); |
119 | char buf[64]; | 119 | char buf[64]; |
120 | bIn.read( buf, 64 ); | 120 | bIn.read( buf, 64 ); |
121 | fOut.write( buf, 64 ); | 121 | fOut.write( buf, 64 ); |
122 | sio << sio.nl << "All done." << sio.nl; | 122 | sio << sio.nl << "All done." << sio.nl; |
123 | } | 123 | } |
124 | 124 | ||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
diff --git a/src/tests/bnfcompile.cpp b/src/tests/bnfcompile.cpp index af7a0eb..40d410d 100644 --- a/src/tests/bnfcompile.cpp +++ b/src/tests/bnfcompile.cpp | |||
@@ -15,408 +15,408 @@ using namespace Bu; | |||
15 | 15 | ||
16 | enum TokenType | 16 | enum TokenType |
17 | { | 17 | { |
18 | tokIdentifier, | 18 | tokIdentifier, |
19 | tokColon, | 19 | tokColon, |
20 | tokOr, | 20 | tokOr, |
21 | tokSemiColon, | 21 | tokSemiColon, |
22 | tokTokens, | 22 | tokTokens, |
23 | tokEquals, | 23 | tokEquals, |
24 | tokOpenCurly, | 24 | tokOpenCurly, |
25 | tokCloseCurly, | 25 | tokCloseCurly, |
26 | tokOpenSquare, | 26 | tokOpenSquare, |
27 | tokCloseSquare, | 27 | tokCloseSquare, |
28 | 28 | ||
29 | tokEos=-1 | 29 | tokEos=-1 |
30 | }; | 30 | }; |
31 | 31 | ||
32 | class BnfLexer : public Lexer | 32 | class BnfLexer : public Lexer |
33 | { | 33 | { |
34 | public: | 34 | public: |
35 | BnfLexer( Stream &rSrc ) : | 35 | BnfLexer( Stream &rSrc ) : |
36 | rSrc( rSrc ) | 36 | rSrc( rSrc ) |
37 | { | 37 | { |
38 | } | 38 | } |
39 | 39 | ||
40 | virtual ~BnfLexer() | 40 | virtual ~BnfLexer() |
41 | { | 41 | { |
42 | } | 42 | } |
43 | 43 | ||
44 | virtual Token *nextToken() | 44 | virtual Token *nextToken() |
45 | { | 45 | { |
46 | char cBuf; | 46 | char cBuf; |
47 | 47 | ||
48 | for(;;) | 48 | for(;;) |
49 | { | 49 | { |
50 | if( qbIn.getSize() == 0 ) | 50 | if( qbIn.getSize() == 0 ) |
51 | { | 51 | { |
52 | char buf[4096]; | 52 | char buf[4096]; |
53 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); | 53 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); |
54 | 54 | ||
55 | if( rSrc.isEos() && qbIn.getSize() == 0 ) | 55 | if( rSrc.isEos() && qbIn.getSize() == 0 ) |
56 | return new Token( tokEos ); | 56 | return new Token( tokEos ); |
57 | } | 57 | } |
58 | qbIn.peek( &cBuf, 1 ); | 58 | qbIn.peek( &cBuf, 1 ); |
59 | if( (cBuf >= 'a' && cBuf <= 'z') || | 59 | if( (cBuf >= 'a' && cBuf <= 'z') || |
60 | (cBuf >= 'A' && cBuf <= 'Z') || | 60 | (cBuf >= 'A' && cBuf <= 'Z') || |
61 | (cBuf >= '0' && cBuf <= '9') || | 61 | (cBuf >= '0' && cBuf <= '9') || |
62 | cBuf == '_' ) | 62 | cBuf == '_' ) |
63 | { | 63 | { |
64 | sBuf.append( cBuf ); | 64 | sBuf.append( cBuf ); |
65 | qbIn.seek( 1 ); | 65 | qbIn.seek( 1 ); |
66 | } | 66 | } |
67 | else if( sBuf.isSet() ) | 67 | else if( sBuf.isSet() ) |
68 | { | 68 | { |
69 | if( sBuf == "tokens" ) | 69 | if( sBuf == "tokens" ) |
70 | { | 70 | { |
71 | sBuf.clear(); | 71 | sBuf.clear(); |
72 | return new Token( tokTokens ); | 72 | return new Token( tokTokens ); |
73 | } | 73 | } |
74 | else | 74 | else |
75 | { | 75 | { |
76 | Token *pRet = new Token( tokIdentifier, sBuf ); | 76 | Token *pRet = new Token( tokIdentifier, sBuf ); |
77 | sBuf.clear(); | 77 | sBuf.clear(); |
78 | return pRet; | 78 | return pRet; |
79 | } | 79 | } |
80 | } | 80 | } |
81 | else | 81 | else |
82 | { | 82 | { |
83 | switch( cBuf ) | 83 | switch( cBuf ) |
84 | { | 84 | { |
85 | case ' ': | 85 | case ' ': |
86 | case '\t': | 86 | case '\t': |
87 | case '\n': | 87 | case '\n': |
88 | case '\r': | 88 | case '\r': |
89 | qbIn.seek( 1 ); | 89 | qbIn.seek( 1 ); |
90 | continue; | 90 | continue; |
91 | 91 | ||
92 | case ':': | 92 | case ':': |
93 | qbIn.seek( 1 ); | 93 | qbIn.seek( 1 ); |
94 | return new Token( tokColon ); | 94 | return new Token( tokColon ); |
95 | 95 | ||
96 | case ';': | 96 | case ';': |
97 | qbIn.seek( 1 ); | 97 | qbIn.seek( 1 ); |
98 | return new Token( tokSemiColon ); | 98 | return new Token( tokSemiColon ); |
99 | 99 | ||
100 | case '|': | 100 | case '|': |
101 | qbIn.seek( 1 ); | 101 | qbIn.seek( 1 ); |
102 | return new Token( tokOr ); | 102 | return new Token( tokOr ); |
103 | 103 | ||
104 | case '=': | 104 | case '=': |
105 | qbIn.seek( 1 ); | 105 | qbIn.seek( 1 ); |
106 | return new Token( tokEquals ); | 106 | return new Token( tokEquals ); |
107 | 107 | ||
108 | case '[': | 108 | case '[': |
109 | qbIn.seek( 1 ); | 109 | qbIn.seek( 1 ); |
110 | return new Token( tokOpenSquare ); | 110 | return new Token( tokOpenSquare ); |
111 | 111 | ||
112 | case ']': | 112 | case ']': |
113 | qbIn.seek( 1 ); | 113 | qbIn.seek( 1 ); |
114 | return new Token( tokCloseSquare ); | 114 | return new Token( tokCloseSquare ); |
115 | 115 | ||
116 | case '{': | 116 | case '{': |
117 | qbIn.seek( 1 ); | 117 | qbIn.seek( 1 ); |
118 | return new Token( tokOpenCurly ); | 118 | return new Token( tokOpenCurly ); |
119 | 119 | ||
120 | case '}': | 120 | case '}': |
121 | qbIn.seek( 1 ); | 121 | qbIn.seek( 1 ); |
122 | return new Token( tokCloseCurly ); | 122 | return new Token( tokCloseCurly ); |
123 | 123 | ||
124 | default: | 124 | default: |
125 | throw ExceptionBase("Unexpected character '%c'.", | 125 | throw ExceptionBase("Unexpected character '%c'.", |
126 | cBuf ); | 126 | cBuf ); |
127 | break; | 127 | break; |
128 | } | 128 | } |
129 | } | 129 | } |
130 | } | 130 | } |
131 | } | 131 | } |
132 | 132 | ||
133 | virtual String tokenToString( const Token &t ) | 133 | virtual String tokenToString( const Token &t ) |
134 | { | 134 | { |
135 | switch( (TokenType)t.iToken ) | 135 | switch( (TokenType)t.iToken ) |
136 | { | 136 | { |
137 | case tokIdentifier: return "tokIdentifier"; | 137 | case tokIdentifier: return "tokIdentifier"; |
138 | case tokColon: return "tokColon"; | 138 | case tokColon: return "tokColon"; |
139 | case tokOr: return "tokOr"; | 139 | case tokOr: return "tokOr"; |
140 | case tokSemiColon: return "tokSemiColon"; | 140 | case tokSemiColon: return "tokSemiColon"; |
141 | case tokTokens: return "tokTokens"; | 141 | case tokTokens: return "tokTokens"; |
142 | case tokEquals: return "tokEquals"; | 142 | case tokEquals: return "tokEquals"; |
143 | case tokOpenCurly: return "tokOpenCurly"; | 143 | case tokOpenCurly: return "tokOpenCurly"; |
144 | case tokCloseCurly: return "tokCloseCurly"; | 144 | case tokCloseCurly: return "tokCloseCurly"; |
145 | case tokOpenSquare: return "tokOpenSquare"; | 145 | case tokOpenSquare: return "tokOpenSquare"; |
146 | case tokCloseSquare: return "tokCloseSquare"; | 146 | case tokCloseSquare: return "tokCloseSquare"; |
147 | case tokEos: return "tokEos"; | 147 | case tokEos: return "tokEos"; |
148 | } | 148 | } |
149 | 149 | ||
150 | return "???"; | 150 | return "???"; |
151 | } | 151 | } |
152 | 152 | ||
153 | private: | 153 | private: |
154 | Stream &rSrc; | 154 | Stream &rSrc; |
155 | QueueBuf qbIn; | 155 | QueueBuf qbIn; |
156 | String sBuf; | 156 | String sBuf; |
157 | }; | 157 | }; |
158 | 158 | ||
159 | class BnfParser | 159 | class BnfParser |
160 | { | 160 | { |
161 | public: | 161 | public: |
162 | BnfParser( BnfLexer &l ) : | 162 | BnfParser( BnfLexer &l ) : |
163 | l( l ), | 163 | l( l ), |
164 | pCur( NULL ), | 164 | pCur( NULL ), |
165 | iLastToken( 0 ) | 165 | iLastToken( 0 ) |
166 | { | 166 | { |
167 | } | 167 | } |
168 | 168 | ||
169 | virtual ~BnfParser() | 169 | virtual ~BnfParser() |
170 | { | 170 | { |
171 | delete pCur; | 171 | delete pCur; |
172 | pCur = NULL; | 172 | pCur = NULL; |
173 | } | 173 | } |
174 | 174 | ||
175 | void parse() | 175 | void parse() |
176 | { | 176 | { |
177 | for(;;) | 177 | for(;;) |
178 | { | 178 | { |
179 | next(); | 179 | next(); |
180 | switch( pCur->iToken ) | 180 | switch( pCur->iToken ) |
181 | { | 181 | { |
182 | case tokTokens: | 182 | case tokTokens: |
183 | tokens(); | 183 | tokens(); |
184 | break; | 184 | break; |
185 | 185 | ||
186 | case tokIdentifier: | 186 | case tokIdentifier: |
187 | nonTerminal(); | 187 | nonTerminal(); |
188 | break; | 188 | break; |
189 | 189 | ||
190 | case tokEos: | 190 | case tokEos: |
191 | return; | 191 | return; |
192 | break; | 192 | break; |
193 | 193 | ||
194 | default: | 194 | default: |
195 | tokenError("tokTokens, tokIdentifier, or tokEos"); | 195 | tokenError("tokTokens, tokIdentifier, or tokEos"); |
196 | } | 196 | } |
197 | } | 197 | } |
198 | } | 198 | } |
199 | 199 | ||
200 | private: | 200 | private: |
201 | void tokens() | 201 | void tokens() |
202 | { | 202 | { |
203 | next(); | 203 | next(); |
204 | if( pCur->iToken != tokEquals ) | 204 | if( pCur->iToken != tokEquals ) |
205 | tokenError("tokEquals"); | 205 | tokenError("tokEquals"); |
206 | for(;;) | 206 | for(;;) |
207 | { | 207 | { |
208 | next(); | 208 | next(); |
209 | if( pCur->iToken == tokIdentifier ) | 209 | if( pCur->iToken == tokIdentifier ) |
210 | { | 210 | { |
211 | hTokens.insert( pCur->vExtra.get<Bu::String>(), ++iLastToken ); | 211 | hTokens.insert( pCur->vExtra.get<Bu::String>(), ++iLastToken ); |
212 | sio << "Added token[" << iLastToken << "]: " | 212 | sio << "Added token[" << iLastToken << "]: " |
213 | << pCur->vExtra.get<Bu::String>() << sio.nl; | 213 | << pCur->vExtra.get<Bu::String>() << sio.nl; |
214 | } | 214 | } |
215 | else if( pCur->iToken == tokSemiColon ) | 215 | else if( pCur->iToken == tokSemiColon ) |
216 | break; | 216 | break; |
217 | else | 217 | else |
218 | tokenError("tokIdentifier or tokSemiColon"); | 218 | tokenError("tokIdentifier or tokSemiColon"); |
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | void nonTerminal() | 222 | void nonTerminal() |
223 | { | 223 | { |
224 | Bu::String sNtName = pCur->vExtra.get<Bu::String>(); | 224 | Bu::String sNtName = pCur->vExtra.get<Bu::String>(); |
225 | Parser::NonTerminal nt; | 225 | Parser::NonTerminal nt; |
226 | p.addNonTerminal( sNtName ); | 226 | p.addNonTerminal( sNtName ); |
227 | sio.incIndent(); | 227 | sio.incIndent(); |
228 | sio << "Created non-terminal: " << sNtName << sio.nl; | 228 | sio << "Created non-terminal: " << sNtName << sio.nl; |
229 | 229 | ||
230 | next(); | 230 | next(); |
231 | if( pCur->iToken != tokColon ) | 231 | if( pCur->iToken != tokColon ) |
232 | tokenError("tokColon"); | 232 | tokenError("tokColon"); |
233 | production( nt ); | 233 | production( nt ); |
234 | for(;;) | 234 | for(;;) |
235 | { | 235 | { |
236 | switch( pCur->iToken ) | 236 | switch( pCur->iToken ) |
237 | { | 237 | { |
238 | case tokOr: | 238 | case tokOr: |
239 | production( nt ); | 239 | production( nt ); |
240 | break; | 240 | break; |
241 | 241 | ||
242 | case tokSemiColon: | 242 | case tokSemiColon: |
243 | p.setNonTerminal( sNtName, nt ); | 243 | p.setNonTerminal( sNtName, nt ); |
244 | sio.decIndent(); | 244 | sio.decIndent(); |
245 | sio << "Closing non-terminal." << sio.nl; | 245 | sio << "Closing non-terminal." << sio.nl; |
246 | return; | 246 | return; |
247 | 247 | ||
248 | default: | 248 | default: |
249 | tokenError("tkOr or tokSemiColon"); | 249 | tokenError("tkOr or tokSemiColon"); |
250 | break; | 250 | break; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | } | 253 | } |
254 | 254 | ||
255 | void production( Parser::NonTerminal &nt ) | 255 | void production( Parser::NonTerminal &nt ) |
256 | { | 256 | { |
257 | sio.incIndent(); | 257 | sio.incIndent(); |
258 | sio << "Adding new production:" << sio.nl; | 258 | sio << "Adding new production:" << sio.nl; |
259 | Parser::Production pr; | 259 | Parser::Production pr; |
260 | bool bAnything = false; | 260 | bool bAnything = false; |
261 | for(;;) | 261 | for(;;) |
262 | { | 262 | { |
263 | next(); | 263 | next(); |
264 | switch( pCur->iToken ) | 264 | switch( pCur->iToken ) |
265 | { | 265 | { |
266 | case tokIdentifier: | 266 | case tokIdentifier: |
267 | { | 267 | { |
268 | const Bu::String &sName = | 268 | const Bu::String &sName = |
269 | pCur->vExtra.get<Bu::String>(); | 269 | pCur->vExtra.get<Bu::String>(); |
270 | if( hTokens.has( sName ) ) | 270 | if( hTokens.has( sName ) ) |
271 | { | 271 | { |
272 | pr.append( | 272 | pr.append( |
273 | Parser::State( | 273 | Parser::State( |
274 | Parser::State::typeTerminal, | 274 | Parser::State::typeTerminal, |
275 | hTokens.get( sName ) | 275 | hTokens.get( sName ) |
276 | ) | 276 | ) |
277 | ); | 277 | ); |
278 | sio << "Added terminal " << sName << sio.nl; | 278 | sio << "Added terminal " << sName << sio.nl; |
279 | } | 279 | } |
280 | else | 280 | else |
281 | { | 281 | { |
282 | if( !p.hasNonTerminal( sName ) ) | 282 | if( !p.hasNonTerminal( sName ) ) |
283 | { | 283 | { |
284 | p.addNonTerminal( sName ); | 284 | p.addNonTerminal( sName ); |
285 | } | 285 | } |
286 | pr.append( | 286 | pr.append( |
287 | Parser::State( | 287 | Parser::State( |
288 | Parser::State::typeNonTerminal, | 288 | Parser::State::typeNonTerminal, |
289 | p.getNonTerminalId( sName ) | 289 | p.getNonTerminalId( sName ) |
290 | ) | 290 | ) |
291 | ); | 291 | ); |
292 | sio << "Added non-terminal " << sName << sio.nl; | 292 | sio << "Added non-terminal " << sName << sio.nl; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | break; | 295 | break; |
296 | 296 | ||
297 | case tokOpenSquare: | 297 | case tokOpenSquare: |
298 | { | 298 | { |
299 | next(); | 299 | next(); |
300 | if( pCur->iToken != tokIdentifier ) | 300 | if( pCur->iToken != tokIdentifier ) |
301 | tokenError("tokIdentifier"); | 301 | tokenError("tokIdentifier"); |
302 | Bu::String sName = | 302 | Bu::String sName = |
303 | pCur->vExtra.get<Bu::String>(); | 303 | pCur->vExtra.get<Bu::String>(); |
304 | next(); | 304 | next(); |
305 | if( pCur->iToken != tokCloseSquare ) | 305 | if( pCur->iToken != tokCloseSquare ) |
306 | tokenError("tokCloseSquare"); | 306 | tokenError("tokCloseSquare"); |
307 | 307 | ||
308 | if( !hTokens.has( sName ) ) | 308 | if( !hTokens.has( sName ) ) |
309 | throw ExceptionBase("Only token names may be " | 309 | throw ExceptionBase("Only token names may be " |
310 | "enclosed in square brackets."); | 310 | "enclosed in square brackets."); |
311 | 311 | ||
312 | pr.append( | 312 | pr.append( |
313 | Parser::State( | 313 | Parser::State( |
314 | Parser::State::typeTerminalPush, | 314 | Parser::State::typeTerminalPush, |
315 | hTokens.get( sName ) | 315 | hTokens.get( sName ) |
316 | ) | 316 | ) |
317 | ); | 317 | ); |
318 | sio << "Added terminal-push " << sName << sio.nl; | 318 | sio << "Added terminal-push " << sName << sio.nl; |
319 | } | 319 | } |
320 | break; | 320 | break; |
321 | 321 | ||
322 | case tokOpenCurly: | 322 | case tokOpenCurly: |
323 | { | 323 | { |
324 | next(); | 324 | next(); |
325 | if( pCur->iToken != tokIdentifier ) | 325 | if( pCur->iToken != tokIdentifier ) |
326 | tokenError("tokIdentifier"); | 326 | tokenError("tokIdentifier"); |
327 | Bu::String sName = | 327 | Bu::String sName = |
328 | pCur->vExtra.get<Bu::String>(); | 328 | pCur->vExtra.get<Bu::String>(); |
329 | next(); | 329 | next(); |
330 | if( pCur->iToken != tokCloseCurly ) | 330 | if( pCur->iToken != tokCloseCurly ) |
331 | tokenError("tokCloseCurly"); | 331 | tokenError("tokCloseCurly"); |
332 | 332 | ||
333 | if( !p.hasReduction( sName ) ) | 333 | if( !p.hasReduction( sName ) ) |
334 | p.addReduction( sName ); | 334 | p.addReduction( sName ); |
335 | 335 | ||
336 | pr.append( | 336 | pr.append( |
337 | Parser::State( | 337 | Parser::State( |
338 | Parser::State::typeReduction, | 338 | Parser::State::typeReduction, |
339 | p.getReductionId( sName ) | 339 | p.getReductionId( sName ) |
340 | ) | 340 | ) |
341 | ); | 341 | ); |
342 | sio << "Added reduction " << sName << sio.nl; | 342 | sio << "Added reduction " << sName << sio.nl; |
343 | } | 343 | } |
344 | break; | 344 | break; |
345 | 345 | ||
346 | case tokOr: | 346 | case tokOr: |
347 | case tokSemiColon: | 347 | case tokSemiColon: |
348 | if( bAnything ) | 348 | if( bAnything ) |
349 | { | 349 | { |
350 | nt.addProduction( pr ); | 350 | nt.addProduction( pr ); |
351 | sio.decIndent(); | 351 | sio.decIndent(); |
352 | sio << "Closing production." << sio.nl; | 352 | sio << "Closing production." << sio.nl; |
353 | } | 353 | } |
354 | else | 354 | else |
355 | { | 355 | { |
356 | nt.setCanSkip(); | 356 | nt.setCanSkip(); |
357 | sio.decIndent(); | 357 | sio.decIndent(); |
358 | sio << "Closing empty production." << sio.nl; | 358 | sio << "Closing empty production." << sio.nl; |
359 | } | 359 | } |
360 | return; | 360 | return; |
361 | 361 | ||
362 | default: | 362 | default: |
363 | tokenError("tokIdentifier, tokOpenSquare, tokOr, " | 363 | tokenError("tokIdentifier, tokOpenSquare, tokOr, " |
364 | "tokOpenCurly, or tokSemiColon"); | 364 | "tokOpenCurly, or tokSemiColon"); |
365 | } | 365 | } |
366 | } | 366 | } |
367 | } | 367 | } |
368 | 368 | ||
369 | private: | 369 | private: |
370 | void next() | 370 | void next() |
371 | { | 371 | { |
372 | delete pCur; | 372 | delete pCur; |
373 | pCur = l.nextToken(); | 373 | pCur = l.nextToken(); |
374 | } | 374 | } |
375 | 375 | ||
376 | void tokenError( const String &s ) | 376 | void tokenError( const String &s ) |
377 | { | 377 | { |
378 | throw ExceptionBase( ("Expected " + s + " but found " | 378 | throw ExceptionBase( ("Expected " + s + " but found " |
379 | + l.tokenToString( *pCur ) + ".").getStr() ); | 379 | + l.tokenToString( *pCur ) + ".").getStr() ); |
380 | } | 380 | } |
381 | 381 | ||
382 | private: | 382 | private: |
383 | typedef Bu::Hash<Bu::String, int> TokenHash; | 383 | typedef Bu::Hash<Bu::String, int> TokenHash; |
384 | TokenHash hTokens; | 384 | TokenHash hTokens; |
385 | BnfLexer &l; | 385 | BnfLexer &l; |
386 | BnfLexer::Token *pCur; | 386 | BnfLexer::Token *pCur; |
387 | int iLastToken; | 387 | int iLastToken; |
388 | Parser p; | 388 | Parser p; |
389 | }; | 389 | }; |
390 | 390 | ||
391 | int main( int argc, char *argv[] ) | 391 | int main( int argc, char *argv[] ) |
392 | { | 392 | { |
393 | if( argc < 2 ) | 393 | if( argc < 2 ) |
394 | { | 394 | { |
395 | println("Provide an input filename as the first parameter."); | 395 | println("Provide an input filename as the first parameter."); |
396 | return 0; | 396 | return 0; |
397 | } | 397 | } |
398 | File fIn( argv[1], File::Read ); | 398 | File fIn( argv[1], File::Read ); |
399 | 399 | ||
400 | BnfLexer bl( fIn ); | 400 | BnfLexer bl( fIn ); |
401 | BnfParser parser( bl ); | 401 | BnfParser parser( bl ); |
402 | 402 | ||
403 | parser.parse(); | 403 | parser.parse(); |
404 | 404 | ||
405 | /* | 405 | /* |
406 | for(;;) | 406 | for(;;) |
407 | { | 407 | { |
408 | Lexer::Token *pTok = bl.nextToken(); | 408 | Lexer::Token *pTok = bl.nextToken(); |
409 | sio << bl.tokenToString(*pTok); | 409 | sio << bl.tokenToString(*pTok); |
410 | if( pTok->vExtra.isSet() ) | 410 | if( pTok->vExtra.isSet() ) |
411 | { | 411 | { |
412 | sio << " - " << pTok->vExtra; | 412 | sio << " - " << pTok->vExtra; |
413 | } | 413 | } |
414 | sio << sio.nl; | 414 | sio << sio.nl; |
415 | if( pTok->iToken == tokEos ) | 415 | if( pTok->iToken == tokEos ) |
416 | break; | 416 | break; |
417 | } | 417 | } |
418 | */ | 418 | */ |
419 | 419 | ||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
diff --git a/src/tests/bzip2.cpp b/src/tests/bzip2.cpp index 1b6fc2f..26bb9bd 100644 --- a/src/tests/bzip2.cpp +++ b/src/tests/bzip2.cpp | |||
@@ -10,27 +10,27 @@ | |||
10 | 10 | ||
11 | int main( int argc, char *argv[] ) | 11 | int main( int argc, char *argv[] ) |
12 | { | 12 | { |
13 | if( argc < 3 ) | 13 | if( argc < 3 ) |
14 | { | 14 | { |
15 | printf("usage: %s <in> <out>\n", argv[0] ); | 15 | printf("usage: %s <in> <out>\n", argv[0] ); |
16 | return -1; | 16 | return -1; |
17 | } | 17 | } |
18 | 18 | ||
19 | char buf[1024]; | 19 | char buf[1024]; |
20 | size_t nRead; | 20 | size_t nRead; |
21 | 21 | ||
22 | Bu::File fin( argv[1], Bu::File::Read ); | 22 | Bu::File fin( argv[1], Bu::File::Read ); |
23 | 23 | ||
24 | Bu::File f( argv[2], Bu::File::WriteNew ); | 24 | Bu::File f( argv[2], Bu::File::WriteNew ); |
25 | Bu::BZip2 bz2( f ); | 25 | Bu::BZip2 bz2( f ); |
26 | 26 | ||
27 | for(;;) | 27 | for(;;) |
28 | { | 28 | { |
29 | nRead = fin.read( buf, 1024 ); | 29 | nRead = fin.read( buf, 1024 ); |
30 | if( nRead > 0 ) | 30 | if( nRead > 0 ) |
31 | bz2.write( buf, nRead ); | 31 | bz2.write( buf, nRead ); |
32 | if( fin.isEos() ) | 32 | if( fin.isEos() ) |
33 | break; | 33 | break; |
34 | } | 34 | } |
35 | } | 35 | } |
36 | 36 | ||
diff --git a/src/tests/deflate.cpp b/src/tests/deflate.cpp index 8290ed5..89640e1 100644 --- a/src/tests/deflate.cpp +++ b/src/tests/deflate.cpp | |||
@@ -10,44 +10,44 @@ | |||
10 | 10 | ||
11 | int main( int argc, char *argv[] ) | 11 | int main( int argc, char *argv[] ) |
12 | { | 12 | { |
13 | if( argc < 3 ) | 13 | if( argc < 3 ) |
14 | { | 14 | { |
15 | printf("usage: %s <in> <out>\n", argv[0] ); | 15 | printf("usage: %s <in> <out>\n", argv[0] ); |
16 | return -1; | 16 | return -1; |
17 | } | 17 | } |
18 | 18 | ||
19 | char buf[1024]; | 19 | char buf[1024]; |
20 | size_t nRead; | 20 | size_t nRead; |
21 | 21 | ||
22 | /* | 22 | /* |
23 | Bu::File fin( argv[1], Bu::File::Read ); | 23 | Bu::File fin( argv[1], Bu::File::Read ); |
24 | fin.seek( 4 ); | 24 | fin.seek( 4 ); |
25 | Bu::Deflate def( fin ); | 25 | Bu::Deflate def( fin ); |
26 | 26 | ||
27 | Bu::File f( argv[2], Bu::File::WriteNew ); | 27 | Bu::File f( argv[2], Bu::File::WriteNew ); |
28 | 28 | ||
29 | for(;;) | 29 | for(;;) |
30 | { | 30 | { |
31 | nRead = def.read( buf, 1024 ); | 31 | nRead = def.read( buf, 1024 ); |
32 | if( nRead > 0 ) | 32 | if( nRead > 0 ) |
33 | f.write( buf, nRead ); | 33 | f.write( buf, nRead ); |
34 | if( def.isEos() ) | 34 | if( def.isEos() ) |
35 | break; | 35 | break; |
36 | } | 36 | } |
37 | */ | 37 | */ |
38 | 38 | ||
39 | Bu::File fin( argv[1], Bu::File::Read ); | 39 | Bu::File fin( argv[1], Bu::File::Read ); |
40 | 40 | ||
41 | Bu::File f( argv[2], Bu::File::WriteNew ); | 41 | Bu::File f( argv[2], Bu::File::WriteNew ); |
42 | Bu::Deflate def( f, 9, Bu::Deflate::Gzip ); | 42 | Bu::Deflate def( f, 9, Bu::Deflate::Gzip ); |
43 | 43 | ||
44 | for(;;) | 44 | for(;;) |
45 | { | 45 | { |
46 | nRead = fin.read( buf, 1024 ); | 46 | nRead = fin.read( buf, 1024 ); |
47 | if( nRead > 0 ) | 47 | if( nRead > 0 ) |
48 | def.write( buf, nRead ); | 48 | def.write( buf, nRead ); |
49 | if( fin.isEos() ) | 49 | if( fin.isEos() ) |
50 | break; | 50 | break; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/src/tests/lzma.cpp b/src/tests/lzma.cpp index 596c396..7d4d1eb 100644 --- a/src/tests/lzma.cpp +++ b/src/tests/lzma.cpp | |||
@@ -10,44 +10,44 @@ | |||
10 | 10 | ||
11 | int main( int argc, char *argv[] ) | 11 | int main( int argc, char *argv[] ) |
12 | { | 12 | { |
13 | if( argc < 3 ) | 13 | if( argc < 3 ) |
14 | { | 14 | { |
15 | printf("usage: %s <in> <out>\n", argv[0] ); | 15 | printf("usage: %s <in> <out>\n", argv[0] ); |
16 | return -1; | 16 | return -1; |
17 | } | 17 | } |
18 | 18 | ||
19 | char buf[1024]; | 19 | char buf[1024]; |
20 | size_t nRead; | 20 | size_t nRead; |
21 | 21 | ||
22 | /* | 22 | /* |
23 | Bu::File fin( argv[1], Bu::File::Read ); | 23 | Bu::File fin( argv[1], Bu::File::Read ); |
24 | fin.seek( 4 ); | 24 | fin.seek( 4 ); |
25 | Bu::Deflate def( fin ); | 25 | Bu::Deflate def( fin ); |
26 | 26 | ||
27 | Bu::File f( argv[2], Bu::File::WriteNew ); | 27 | Bu::File f( argv[2], Bu::File::WriteNew ); |
28 | 28 | ||
29 | for(;;) | 29 | for(;;) |
30 | { | 30 | { |
31 | nRead = def.read( buf, 1024 ); | 31 | nRead = def.read( buf, 1024 ); |
32 | if( nRead > 0 ) | 32 | if( nRead > 0 ) |
33 | f.write( buf, nRead ); | 33 | f.write( buf, nRead ); |
34 | if( def.isEos() ) | 34 | if( def.isEos() ) |
35 | break; | 35 | break; |
36 | } | 36 | } |
37 | */ | 37 | */ |
38 | 38 | ||
39 | Bu::File fin( argv[1], Bu::File::Read ); | 39 | Bu::File fin( argv[1], Bu::File::Read ); |
40 | 40 | ||
41 | Bu::File f( argv[2], Bu::File::WriteNew ); | 41 | Bu::File f( argv[2], Bu::File::WriteNew ); |
42 | Bu::Lzma def( f, 9 ); | 42 | Bu::Lzma def( f, 9 ); |
43 | 43 | ||
44 | for(;;) | 44 | for(;;) |
45 | { | 45 | { |
46 | nRead = fin.read( buf, 1024 ); | 46 | nRead = fin.read( buf, 1024 ); |
47 | if( nRead > 0 ) | 47 | if( nRead > 0 ) |
48 | def.write( buf, nRead ); | 48 | def.write( buf, nRead ); |
49 | if( fin.isEos() ) | 49 | if( fin.isEos() ) |
50 | break; | 50 | break; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/src/tests/myriadfs.cpp b/src/tests/myriadfs.cpp index f57f02d..cb6c6c3 100644 --- a/src/tests/myriadfs.cpp +++ b/src/tests/myriadfs.cpp | |||
@@ -8,41 +8,41 @@ using namespace Bu; | |||
8 | 8 | ||
9 | int main() | 9 | int main() |
10 | { | 10 | { |
11 | // Bu::MemBuf mb; | 11 | // Bu::MemBuf mb; |
12 | Bu::File mb("store.myr", File::Read|File::Write|File::Create ); | 12 | Bu::File mb("store.myr", File::Read|File::Write|File::Create ); |
13 | Bu::MyriadFs mfs( mb, 512 ); | 13 | Bu::MyriadFs mfs( mb, 512 ); |
14 | 14 | ||
15 | sio << "Creating dirs..." << sio.nl; | 15 | sio << "Creating dirs..." << sio.nl; |
16 | mfs.create("/etc", Bu::MyriadFs::typeDir|0755 ); | 16 | mfs.create("/etc", Bu::MyriadFs::typeDir|0755 ); |
17 | mfs.create("/dev", Bu::MyriadFs::typeDir|0755 ); | 17 | mfs.create("/dev", Bu::MyriadFs::typeDir|0755 ); |
18 | mfs.create("/usr", Bu::MyriadFs::typeDir|0755 ); | 18 | mfs.create("/usr", Bu::MyriadFs::typeDir|0755 ); |
19 | 19 | ||
20 | mfs.create("/dev/null", Bu::MyriadFs::typeChrDev|0666, 1, 3 ); | 20 | mfs.create("/dev/null", Bu::MyriadFs::typeChrDev|0666, 1, 3 ); |
21 | mfs.create("/dev/zero", Bu::MyriadFs::typeChrDev|0666, 1, 5 ); | 21 | mfs.create("/dev/zero", Bu::MyriadFs::typeChrDev|0666, 1, 5 ); |
22 | mfs.create("/dev/sda", Bu::MyriadFs::typeBlkDev|0660, 8, 0 ); | 22 | mfs.create("/dev/sda", Bu::MyriadFs::typeBlkDev|0660, 8, 0 ); |
23 | 23 | ||
24 | sio << "Creating files..." << sio.nl; | 24 | sio << "Creating files..." << sio.nl; |
25 | { | 25 | { |
26 | Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); | 26 | Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); |
27 | ms.write("world!"); | 27 | ms.write("world!"); |
28 | } | 28 | } |
29 | { | 29 | { |
30 | Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); | 30 | Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); |
31 | ms.write("world, again!"); | 31 | ms.write("world, again!"); |
32 | } | 32 | } |
33 | 33 | ||
34 | sio << "Reading files..." << sio.nl; | 34 | sio << "Reading files..." << sio.nl; |
35 | { | 35 | { |
36 | Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); | 36 | Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); |
37 | char buf[512]; | 37 | char buf[512]; |
38 | buf[ms.read( buf, 512 )] = '\0'; | 38 | buf[ms.read( buf, 512 )] = '\0'; |
39 | sio << "read: '" << buf << "'" << sio.nl; | 39 | sio << "read: '" << buf << "'" << sio.nl; |
40 | } | 40 | } |
41 | { | 41 | { |
42 | Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); | 42 | Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); |
43 | char buf[512]; | 43 | char buf[512]; |
44 | buf[ms.read( buf, 512 )] = '\0'; | 44 | buf[ms.read( buf, 512 )] = '\0'; |
45 | sio << "read: '" << buf << "'" << sio.nl; | 45 | sio << "read: '" << buf << "'" << sio.nl; |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
diff --git a/src/tests/optparser.cpp b/src/tests/optparser.cpp index 772cebc..05e5168 100644 --- a/src/tests/optparser.cpp +++ b/src/tests/optparser.cpp | |||
@@ -12,82 +12,82 @@ using namespace Bu; | |||
12 | class Opts : public Bu::OptParser | 12 | class Opts : public Bu::OptParser |
13 | { | 13 | { |
14 | public: | 14 | public: |
15 | Opts() : | 15 | Opts() : |
16 | iBob( 542 ), | 16 | iBob( 542 ), |
17 | bVal( false ) | 17 | bVal( false ) |
18 | { | 18 | { |
19 | addHelpBanner("optparser - Test some option things..."); | 19 | addHelpBanner("optparser - Test some option things..."); |
20 | 20 | ||
21 | addHelpBanner("\nThis section represents options that actually have " | 21 | addHelpBanner("\nThis section represents options that actually have " |
22 | "callbacks, or in the case of the new system, signals/slots. They " | 22 | "callbacks, or in the case of the new system, signals/slots. They " |
23 | "all take parameters, but if they return 0 then it will be as " | 23 | "all take parameters, but if they return 0 then it will be as " |
24 | "though they hadn't and the next thing will be processed normally.", | 24 | "though they hadn't and the next thing will be processed normally.", |
25 | true | 25 | true |
26 | ); | 26 | ); |
27 | addOption( slot( this, &Opts::yesparam ), 'x', "things", | 27 | addOption( slot( this, &Opts::yesparam ), 'x', "things", |
28 | "This is the first test parameter. It calls a function, and " | 28 | "This is the first test parameter. It calls a function, and " |
29 | "takes a parameter." | 29 | "takes a parameter." |
30 | ); | 30 | ); |
31 | addOption( slot( this, &Opts::noparam ), 'y', "stuff", | 31 | addOption( slot( this, &Opts::noparam ), 'y', "stuff", |
32 | "This is the second test parameter. It does not take " | 32 | "This is the second test parameter. It does not take " |
33 | "parameters. However, I do want to make this part much longer to " | 33 | "parameters. However, I do want to make this part much longer to " |
34 | "see how it looks when you add way too much text to one of these " | 34 | "see how it looks when you add way too much text to one of these " |
35 | "things. It can't really be that bad, right?" | 35 | "things. It can't really be that bad, right?" |
36 | ); | 36 | ); |
37 | 37 | ||
38 | addHelpBanner("\nThis section represents options with no callback or " | 38 | addHelpBanner("\nThis section represents options with no callback or " |
39 | "signal, but do have a variable to update. They use the Formatter " | 39 | "signal, but do have a variable to update. They use the Formatter " |
40 | "system and therefore it's very, very flexible. Any data type " | 40 | "system and therefore it's very, very flexible. Any data type " |
41 | "you can read with a formatter you can set via parameter.", | 41 | "you can read with a formatter you can set via parameter.", |
42 | true | 42 | true |
43 | ); | 43 | ); |
44 | addOption( sVar, 's', "str", "Set a variable, see what it does."); | 44 | addOption( sVar, 's', "str", "Set a variable, see what it does."); |
45 | addOption( bVal, 'b', "bool", "It's a thing."); | 45 | addOption( bVal, 'b', "bool", "It's a thing."); |
46 | addOption( iBob, "bob", "Change iBob to whatever you want."); | 46 | addOption( iBob, "bob", "Change iBob to whatever you want."); |
47 | addOption( dBob, 'd', "Change dBob to whatever you want."); | 47 | addOption( dBob, 'd', "Change dBob to whatever you want."); |
48 | 48 | ||
49 | setOverride("str", "Bob!"); | 49 | setOverride("str", "Bob!"); |
50 | setHelpDefault("bob", "=542"); | 50 | setHelpDefault("bob", "=542"); |
51 | setOverride("bool", true ); | 51 | setOverride("bool", true ); |
52 | 52 | ||
53 | addHelpOption(); | 53 | addHelpOption(); |
54 | 54 | ||
55 | setNonOption( slot( this, &Opts::nonOption ) ); | 55 | setNonOption( slot( this, &Opts::nonOption ) ); |
56 | } | 56 | } |
57 | 57 | ||
58 | int yesparam( StrArray aParams ) | 58 | int yesparam( StrArray aParams ) |
59 | { | 59 | { |
60 | sio << " - yesparam" << aParams << sio.nl; | 60 | sio << " - yesparam" << aParams << sio.nl; |
61 | return 1; | 61 | return 1; |
62 | } | 62 | } |
63 | 63 | ||
64 | int noparam( StrArray aParams ) | 64 | int noparam( StrArray aParams ) |
65 | { | 65 | { |
66 | sio << " - noparam" << aParams << sio.nl; | 66 | sio << " - noparam" << aParams << sio.nl; |
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | int nonOption( StrArray aParams ) | 70 | int nonOption( StrArray aParams ) |
71 | { | 71 | { |
72 | sio << " - nonOption" << aParams << sio.nl; | 72 | sio << " - nonOption" << aParams << sio.nl; |
73 | return aParams.getSize()-1; | 73 | return aParams.getSize()-1; |
74 | } | 74 | } |
75 | 75 | ||
76 | int iBob; | 76 | int iBob; |
77 | float dBob; | 77 | float dBob; |
78 | Bu::String sVar; | 78 | Bu::String sVar; |
79 | bool bVal; | 79 | bool bVal; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | int main( int argc, char *argv[] ) | 82 | int main( int argc, char *argv[] ) |
83 | { | 83 | { |
84 | Opts o; | 84 | Opts o; |
85 | 85 | ||
86 | o.parse( argc, argv ); | 86 | o.parse( argc, argv ); |
87 | 87 | ||
88 | sio << "sVar = \"" << o.sVar << "\"" << sio.nl; | 88 | sio << "sVar = \"" << o.sVar << "\"" << sio.nl; |
89 | sio << "iBob = " << o.iBob << sio.nl; | 89 | sio << "iBob = " << o.iBob << sio.nl; |
90 | sio << "dBob = " << o.dBob << sio.nl; | 90 | sio << "dBob = " << o.dBob << sio.nl; |
91 | sio << "bVal = " << o.bVal << sio.nl; | 91 | sio << "bVal = " << o.bVal << sio.nl; |
92 | } | 92 | } |
93 | 93 | ||
diff --git a/src/tests/parser.cpp b/src/tests/parser.cpp index af53bc8..6ad722f 100644 --- a/src/tests/parser.cpp +++ b/src/tests/parser.cpp | |||
@@ -16,185 +16,185 @@ using namespace Bu; | |||
16 | 16 | ||
17 | enum Tok | 17 | enum Tok |
18 | { | 18 | { |
19 | tokNumber, | 19 | tokNumber, |
20 | tokPlus, | 20 | tokPlus, |
21 | tokMinus, | 21 | tokMinus, |
22 | tokDivide, | 22 | tokDivide, |
23 | tokMultiply, | 23 | tokMultiply, |
24 | tokOpenParen, | 24 | tokOpenParen, |
25 | tokCloseParen, | 25 | tokCloseParen, |
26 | tokCompute, | 26 | tokCompute, |
27 | tokEndOfInput=-1 | 27 | tokEndOfInput=-1 |
28 | }; | 28 | }; |
29 | 29 | ||
30 | Bu::Formatter &operator<<( Bu::Formatter &f, Tok e ) | 30 | Bu::Formatter &operator<<( Bu::Formatter &f, Tok e ) |
31 | { | 31 | { |
32 | switch( e ) | 32 | switch( e ) |
33 | { | 33 | { |
34 | case tokNumber: return f << "tokNumber"; | 34 | case tokNumber: return f << "tokNumber"; |
35 | case tokPlus: return f << "tokPlus"; | 35 | case tokPlus: return f << "tokPlus"; |
36 | case tokMinus: return f << "tokMinus"; | 36 | case tokMinus: return f << "tokMinus"; |
37 | case tokDivide: return f << "tokDivide"; | 37 | case tokDivide: return f << "tokDivide"; |
38 | case tokMultiply: return f << "tokMultiply"; | 38 | case tokMultiply: return f << "tokMultiply"; |
39 | case tokOpenParen: return f << "tokOpenParen"; | 39 | case tokOpenParen: return f << "tokOpenParen"; |
40 | case tokCloseParen: return f << "tokCloseParen"; | 40 | case tokCloseParen: return f << "tokCloseParen"; |
41 | case tokCompute: return f << "tokCompute"; | 41 | case tokCompute: return f << "tokCompute"; |
42 | case tokEndOfInput: return f << "tokEndOfInput"; | 42 | case tokEndOfInput: return f << "tokEndOfInput"; |
43 | } | 43 | } |
44 | 44 | ||
45 | return f << "***error***"; | 45 | return f << "***error***"; |
46 | } | 46 | } |
47 | 47 | ||
48 | class MathLexer : public Lexer | 48 | class MathLexer : public Lexer |
49 | { | 49 | { |
50 | public: | 50 | public: |
51 | MathLexer( Bu::Stream &rSrc ) : | 51 | MathLexer( Bu::Stream &rSrc ) : |
52 | rSrc( rSrc ) | 52 | rSrc( rSrc ) |
53 | { | 53 | { |
54 | } | 54 | } |
55 | 55 | ||
56 | virtual ~MathLexer() | 56 | virtual ~MathLexer() |
57 | { | 57 | { |
58 | } | 58 | } |
59 | 59 | ||
60 | enum TokenTypes | 60 | enum TokenTypes |
61 | { | 61 | { |
62 | tokStuff | 62 | tokStuff |
63 | }; | 63 | }; |
64 | 64 | ||
65 | virtual Token *nextToken() | 65 | virtual Token *nextToken() |
66 | { | 66 | { |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | if( qbIn.getSize() == 0 ) | 69 | if( qbIn.getSize() == 0 ) |
70 | { | 70 | { |
71 | char buf[4096]; | 71 | char buf[4096]; |
72 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); | 72 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); |
73 | 73 | ||
74 | if( rSrc.isEos() && qbIn.getSize() == 0 ) | 74 | if( rSrc.isEos() && qbIn.getSize() == 0 ) |
75 | return new Token( tokEndOfInput ); | 75 | return new Token( tokEndOfInput ); |
76 | } | 76 | } |
77 | 77 | ||
78 | char b; | 78 | char b; |
79 | qbIn.peek( &b, 1 ); | 79 | qbIn.peek( &b, 1 ); |
80 | switch( b ) | 80 | switch( b ) |
81 | { | 81 | { |
82 | case '+': | 82 | case '+': |
83 | qbIn.seek( 1 ); | 83 | qbIn.seek( 1 ); |
84 | return new Token( tokPlus ); | 84 | return new Token( tokPlus ); |
85 | 85 | ||
86 | case '-': | 86 | case '-': |
87 | qbIn.seek( 1 ); | 87 | qbIn.seek( 1 ); |
88 | return new Token( tokMinus ); | 88 | return new Token( tokMinus ); |
89 | 89 | ||
90 | case '/': | 90 | case '/': |
91 | qbIn.seek( 1 ); | 91 | qbIn.seek( 1 ); |
92 | return new Token( tokDivide ); | 92 | return new Token( tokDivide ); |
93 | 93 | ||
94 | case '*': | 94 | case '*': |
95 | qbIn.seek( 1 ); | 95 | qbIn.seek( 1 ); |
96 | return new Token( tokMultiply ); | 96 | return new Token( tokMultiply ); |
97 | 97 | ||
98 | case ' ': | 98 | case ' ': |
99 | case '\t': | 99 | case '\t': |
100 | case '\n': | 100 | case '\n': |
101 | qbIn.seek( 1 ); | 101 | qbIn.seek( 1 ); |
102 | break; | 102 | break; |
103 | 103 | ||
104 | case '=': | 104 | case '=': |
105 | qbIn.seek( 1 ); | 105 | qbIn.seek( 1 ); |
106 | return new Token( tokCompute ); | 106 | return new Token( tokCompute ); |
107 | 107 | ||
108 | case '(': | 108 | case '(': |
109 | qbIn.seek( 1 ); | 109 | qbIn.seek( 1 ); |
110 | return new Token( tokOpenParen ); | 110 | return new Token( tokOpenParen ); |
111 | 111 | ||
112 | case ')': | 112 | case ')': |
113 | qbIn.seek( 1 ); | 113 | qbIn.seek( 1 ); |
114 | return new Token( tokCloseParen ); | 114 | return new Token( tokCloseParen ); |
115 | 115 | ||
116 | case '.': | 116 | case '.': |
117 | case '0': | 117 | case '0': |
118 | case '1': | 118 | case '1': |
119 | case '2': | 119 | case '2': |
120 | case '3': | 120 | case '3': |
121 | case '4': | 121 | case '4': |
122 | case '5': | 122 | case '5': |
123 | case '6': | 123 | case '6': |
124 | case '7': | 124 | case '7': |
125 | case '8': | 125 | case '8': |
126 | case '9': | 126 | case '9': |
127 | { | 127 | { |
128 | Bu::String sTmp; | 128 | Bu::String sTmp; |
129 | sTmp += b; | 129 | sTmp += b; |
130 | qbIn.seek( 1 ); | 130 | qbIn.seek( 1 ); |
131 | for(;;) | 131 | for(;;) |
132 | { | 132 | { |
133 | qbIn.peek( &b, 1 ); | 133 | qbIn.peek( &b, 1 ); |
134 | if( b != '.' && (b < '0' || b > '9') ) | 134 | if( b != '.' && (b < '0' || b > '9') ) |
135 | { | 135 | { |
136 | sio << "!! Convert '" << sTmp << "' to " | 136 | sio << "!! Convert '" << sTmp << "' to " |
137 | << strtod( sTmp.getStr(), NULL ) << sio.nl; | 137 | << strtod( sTmp.getStr(), NULL ) << sio.nl; |
138 | return new Token( | 138 | return new Token( |
139 | tokNumber, strtod( sTmp.getStr(), NULL ) | 139 | tokNumber, strtod( sTmp.getStr(), NULL ) |
140 | ); | 140 | ); |
141 | } | 141 | } |
142 | qbIn.seek( 1 ); | 142 | qbIn.seek( 1 ); |
143 | sTmp += b; | 143 | sTmp += b; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | break; | 146 | break; |
147 | 147 | ||
148 | default: | 148 | default: |
149 | throw Bu::ExceptionBase("Unexpected character '%c'.", b ); | 149 | throw Bu::ExceptionBase("Unexpected character '%c'.", b ); |
150 | } | 150 | } |
151 | } | 151 | } |
152 | } | 152 | } |
153 | 153 | ||
154 | private: | 154 | private: |
155 | Bu::Stream &rSrc; | 155 | Bu::Stream &rSrc; |
156 | QueueBuf qbIn; | 156 | QueueBuf qbIn; |
157 | }; | 157 | }; |
158 | 158 | ||
159 | void redAdd( Bu::Parser &p ) | 159 | void redAdd( Bu::Parser &p ) |
160 | { | 160 | { |
161 | Lexer::Token *a = p.popToken(); | 161 | Lexer::Token *a = p.popToken(); |
162 | Lexer::Token *b = p.popToken(); | 162 | Lexer::Token *b = p.popToken(); |
163 | 163 | ||
164 | sio << "Add! " << b->vExtra.get<double>() << " + " | 164 | sio << "Add! " << b->vExtra.get<double>() << " + " |
165 | << a->vExtra.get<double>() << sio.nl; | 165 | << a->vExtra.get<double>() << sio.nl; |
166 | 166 | ||
167 | Lexer::Token *c = new Lexer::Token( tokNumber, | 167 | Lexer::Token *c = new Lexer::Token( tokNumber, |
168 | b->vExtra.get<double>() + a->vExtra.get<double>() | 168 | b->vExtra.get<double>() + a->vExtra.get<double>() |
169 | ); | 169 | ); |
170 | p.pushToken( c ); | 170 | p.pushToken( c ); |
171 | 171 | ||
172 | delete a; | 172 | delete a; |
173 | delete b; | 173 | delete b; |
174 | } | 174 | } |
175 | 175 | ||
176 | void redSubtract( Bu::Parser &p ) | 176 | void redSubtract( Bu::Parser &p ) |
177 | { | 177 | { |
178 | Lexer::Token *a = p.popToken(); | 178 | Lexer::Token *a = p.popToken(); |
179 | Lexer::Token *b = p.popToken(); | 179 | Lexer::Token *b = p.popToken(); |
180 | 180 | ||
181 | sio << "Subtract! " << b->vExtra.get<double>() << " - " | 181 | sio << "Subtract! " << b->vExtra.get<double>() << " - " |
182 | << a->vExtra.get<double>() << sio.nl; | 182 | << a->vExtra.get<double>() << sio.nl; |
183 | 183 | ||
184 | Lexer::Token *c = new Lexer::Token( tokNumber, | 184 | Lexer::Token *c = new Lexer::Token( tokNumber, |
185 | b->vExtra.get<double>() - a->vExtra.get<double>() | 185 | b->vExtra.get<double>() - a->vExtra.get<double>() |
186 | ); | 186 | ); |
187 | p.pushToken( c ); | 187 | p.pushToken( c ); |
188 | 188 | ||
189 | delete a; | 189 | delete a; |
190 | delete b; | 190 | delete b; |
191 | } | 191 | } |
192 | 192 | ||
193 | void redPrint( Bu::Parser &p ) | 193 | void redPrint( Bu::Parser &p ) |
194 | { | 194 | { |
195 | Lexer::Token *a = p.popToken(); | 195 | Lexer::Token *a = p.popToken(); |
196 | sio << "Print! = " << a->vExtra.get<double>() << sio.nl; | 196 | sio << "Print! = " << a->vExtra.get<double>() << sio.nl; |
197 | delete a; | 197 | delete a; |
198 | } | 198 | } |
199 | 199 | ||
200 | /* Basic grammer example: | 200 | /* Basic grammer example: |
@@ -227,143 +227,143 @@ void redPrint( Bu::Parser &p ) | |||
227 | 227 | ||
228 | int main( int argc, char *argv[] ) | 228 | int main( int argc, char *argv[] ) |
229 | { | 229 | { |
230 | if( argc < 2 ) | 230 | if( argc < 2 ) |
231 | { | 231 | { |
232 | println("Provide an input filename as the first parameter."); | 232 | println("Provide an input filename as the first parameter."); |
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | File fIn( argv[1], File::Read ); | 235 | File fIn( argv[1], File::Read ); |
236 | 236 | ||
237 | Parser p; | 237 | Parser p; |
238 | 238 | ||
239 | p.addNonTerminal("expr"); | 239 | p.addNonTerminal("expr"); |
240 | p.addNonTerminal("expr-sub1"); | 240 | p.addNonTerminal("expr-sub1"); |
241 | p.addNonTerminal("expr-sub2"); | 241 | p.addNonTerminal("expr-sub2"); |
242 | { | 242 | { |
243 | Parser::NonTerminal nt; | 243 | Parser::NonTerminal nt; |
244 | nt.addProduction( | 244 | nt.addProduction( |
245 | Parser::Production( | 245 | Parser::Production( |
246 | Parser::State( | 246 | Parser::State( |
247 | Parser::State::typeTerminal, | 247 | Parser::State::typeTerminal, |
248 | tokPlus | 248 | tokPlus |
249 | ) | 249 | ) |
250 | ).append( | 250 | ).append( |
251 | Parser::State( | 251 | Parser::State( |
252 | Parser::State::typeNonTerminal, | 252 | Parser::State::typeNonTerminal, |
253 | p.getNonTerminalId("expr") | 253 | p.getNonTerminalId("expr") |
254 | ) | 254 | ) |
255 | ).append( | 255 | ).append( |
256 | Parser::State( | 256 | Parser::State( |
257 | Parser::State::typeReduction, | 257 | Parser::State::typeReduction, |
258 | p.addReduction("add") | 258 | p.addReduction("add") |
259 | ) | 259 | ) |
260 | ) | 260 | ) |
261 | ); | 261 | ); |
262 | nt.addProduction( | 262 | nt.addProduction( |
263 | Parser::Production( | 263 | Parser::Production( |
264 | Parser::State( | 264 | Parser::State( |
265 | Parser::State::typeTerminal, | 265 | Parser::State::typeTerminal, |
266 | tokMinus | 266 | tokMinus |
267 | ) | 267 | ) |
268 | ).append( | 268 | ).append( |
269 | Parser::State( | 269 | Parser::State( |
270 | Parser::State::typeNonTerminal, | 270 | Parser::State::typeNonTerminal, |
271 | p.getNonTerminalId("expr") | 271 | p.getNonTerminalId("expr") |
272 | ) | 272 | ) |
273 | ).append( | 273 | ).append( |
274 | Parser::State( | 274 | Parser::State( |
275 | Parser::State::typeReduction, | 275 | Parser::State::typeReduction, |
276 | p.addReduction("subtract") | 276 | p.addReduction("subtract") |
277 | ) | 277 | ) |
278 | ) | 278 | ) |
279 | ); | 279 | ); |
280 | nt.addProduction( | 280 | nt.addProduction( |
281 | Parser::Production( | 281 | Parser::Production( |
282 | ) | 282 | ) |
283 | ); | 283 | ); |
284 | nt.setCanSkip(); | 284 | nt.setCanSkip(); |
285 | p.setNonTerminal("expr-sub2", nt ); | 285 | p.setNonTerminal("expr-sub2", nt ); |
286 | } | 286 | } |
287 | { | 287 | { |
288 | Parser::NonTerminal nt; | 288 | Parser::NonTerminal nt; |
289 | nt.addProduction( | 289 | nt.addProduction( |
290 | Parser::Production( | 290 | Parser::Production( |
291 | Parser::State( | 291 | Parser::State( |
292 | Parser::State::typeTerminalPush, | 292 | Parser::State::typeTerminalPush, |
293 | tokNumber | 293 | tokNumber |
294 | ) | 294 | ) |
295 | ) | 295 | ) |
296 | ); | 296 | ); |
297 | nt.addProduction( | 297 | nt.addProduction( |
298 | Parser::Production( | 298 | Parser::Production( |
299 | Parser::State( | 299 | Parser::State( |
300 | Parser::State::typeTerminal, | 300 | Parser::State::typeTerminal, |
301 | tokOpenParen | 301 | tokOpenParen |
302 | ) | 302 | ) |
303 | ).append( | 303 | ).append( |
304 | Parser::State( | 304 | Parser::State( |
305 | Parser::State::typeNonTerminal, | 305 | Parser::State::typeNonTerminal, |
306 | p.getNonTerminalId("expr") | 306 | p.getNonTerminalId("expr") |
307 | ) | 307 | ) |
308 | ).append( | 308 | ).append( |
309 | Parser::State( | 309 | Parser::State( |
310 | Parser::State::typeTerminal, | 310 | Parser::State::typeTerminal, |
311 | tokCloseParen | 311 | tokCloseParen |
312 | ) | 312 | ) |
313 | ) | 313 | ) |
314 | ); | 314 | ); |
315 | p.setNonTerminal("expr-sub1", nt ); | 315 | p.setNonTerminal("expr-sub1", nt ); |
316 | } | 316 | } |
317 | { | 317 | { |
318 | Parser::NonTerminal nt; | 318 | Parser::NonTerminal nt; |
319 | nt.addProduction( | 319 | nt.addProduction( |
320 | Parser::Production( | 320 | Parser::Production( |
321 | Parser::State( | 321 | Parser::State( |
322 | Parser::State::typeNonTerminal, | 322 | Parser::State::typeNonTerminal, |
323 | p.getNonTerminalId("expr-sub1") | 323 | p.getNonTerminalId("expr-sub1") |
324 | ) | 324 | ) |
325 | ).append( | 325 | ).append( |
326 | Parser::State( | 326 | Parser::State( |
327 | Parser::State::typeNonTerminal, | 327 | Parser::State::typeNonTerminal, |
328 | p.getNonTerminalId("expr-sub2") | 328 | p.getNonTerminalId("expr-sub2") |
329 | ) | 329 | ) |
330 | ) | 330 | ) |
331 | ); | 331 | ); |
332 | p.setNonTerminal("expr", nt ); | 332 | p.setNonTerminal("expr", nt ); |
333 | } | 333 | } |
334 | { | 334 | { |
335 | Parser::NonTerminal nt; | 335 | Parser::NonTerminal nt; |
336 | nt.addProduction( | 336 | nt.addProduction( |
337 | Parser::Production( | 337 | Parser::Production( |
338 | Parser::State( | 338 | Parser::State( |
339 | Parser::State::typeNonTerminal, | 339 | Parser::State::typeNonTerminal, |
340 | p.getNonTerminalId("expr") | 340 | p.getNonTerminalId("expr") |
341 | ) | 341 | ) |
342 | ).append( | 342 | ).append( |
343 | Parser::State( | 343 | Parser::State( |
344 | Parser::State::typeTerminal, | 344 | Parser::State::typeTerminal, |
345 | tokCompute | 345 | tokCompute |
346 | ) | 346 | ) |
347 | ).append( | 347 | ).append( |
348 | Parser::State( | 348 | Parser::State( |
349 | Parser::State::typeReduction, | 349 | Parser::State::typeReduction, |
350 | p.addReduction("print") | 350 | p.addReduction("print") |
351 | ) | 351 | ) |
352 | ) | 352 | ) |
353 | ); | 353 | ); |
354 | p.addNonTerminal("input", nt ); | 354 | p.addNonTerminal("input", nt ); |
355 | } | 355 | } |
356 | 356 | ||
357 | p.setRootNonTerminal("input"); | 357 | p.setRootNonTerminal("input"); |
358 | 358 | ||
359 | p.setReduction("add", Bu::slot( &redAdd ) ); | 359 | p.setReduction("add", Bu::slot( &redAdd ) ); |
360 | p.setReduction("subtract", Bu::slot( &redSubtract ) ); | 360 | p.setReduction("subtract", Bu::slot( &redSubtract ) ); |
361 | p.setReduction("print", Bu::slot( &redPrint ) ); | 361 | p.setReduction("print", Bu::slot( &redPrint ) ); |
362 | 362 | ||
363 | p.pushLexer( new MathLexer( fIn ) ); | 363 | p.pushLexer( new MathLexer( fIn ) ); |
364 | 364 | ||
365 | p.parse(); | 365 | p.parse(); |
366 | 366 | ||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
diff --git a/src/tests/print.cpp b/src/tests/print.cpp index c6fe053..bee8cf8 100644 --- a/src/tests/print.cpp +++ b/src/tests/print.cpp | |||
@@ -2,30 +2,30 @@ | |||
2 | 2 | ||
3 | int upper() | 3 | int upper() |
4 | { | 4 | { |
5 | static int iVal = 1; | 5 | static int iVal = 1; |
6 | return iVal++; | 6 | return iVal++; |
7 | } | 7 | } |
8 | 8 | ||
9 | int main() | 9 | int main() |
10 | { | 10 | { |
11 | Bu::print("hello there %1!\n").arg("Bob"); | 11 | Bu::print("hello there %1!\n").arg("Bob"); |
12 | 12 | ||
13 | Bu::println("This is %1 crazy, like %2 times over!"). | 13 | Bu::println("This is %1 crazy, like %2 times over!"). |
14 | arg("totally").arg( 47.2 ).end(); | 14 | arg("totally").arg( 47.2 ).end(); |
15 | Bu::println("This is unsubstituted?"); | 15 | Bu::println("This is unsubstituted?"); |
16 | 16 | ||
17 | Bu::serr << "This is error text." << Bu::serr.nl; | 17 | Bu::serr << "This is error text." << Bu::serr.nl; |
18 | Bu::println( Bu::serr, "This is also error text?"); | 18 | Bu::println( Bu::serr, "This is also error text?"); |
19 | 19 | ||
20 | Bu::println("This is %{1}000 - %{1}.").arg( 34, Bu::Fmt().width(10).fill('0') ); | 20 | Bu::println("This is %{1}000 - %{1}.").arg( 34, Bu::Fmt().width(10).fill('0') ); |
21 | 21 | ||
22 | Bu::String s = Bu::String("hello %1").arg("bob %1").end().toLower().arg("yo"); | 22 | Bu::String s = Bu::String("hello %1").arg("bob %1").end().toLower().arg("yo"); |
23 | 23 | ||
24 | Bu::println( s ); | 24 | Bu::println( s ); |
25 | Bu::println("Hello %%1"); | 25 | Bu::println("Hello %%1"); |
26 | 26 | ||
27 | Bu::println("Nums: %1, %2, %3, %4, %5, %6").arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ); | 27 | Bu::println("Nums: %1, %2, %3, %4, %5, %6").arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ).arg( upper() ); |
28 | 28 | ||
29 | return 0; | 29 | return 0; |
30 | } | 30 | } |
31 | 31 | ||
diff --git a/src/tests/random.cpp b/src/tests/random.cpp index 3799803..e48c543 100644 --- a/src/tests/random.cpp +++ b/src/tests/random.cpp | |||
@@ -9,41 +9,41 @@ using namespace Bu; | |||
9 | template<typename T> | 9 | template<typename T> |
10 | void coverage() | 10 | void coverage() |
11 | { | 11 | { |
12 | T rand; | 12 | T rand; |
13 | rand.seed( time( NULL ) ); | 13 | rand.seed( time( NULL ) ); |
14 | 14 | ||
15 | uint32_t uBucket[78]; | 15 | uint32_t uBucket[78]; |
16 | memset( uBucket, 0, sizeof(uint32_t)*78 ); | 16 | memset( uBucket, 0, sizeof(uint32_t)*78 ); |
17 | 17 | ||
18 | for( int j = 0; j < 1000000; j++ ) | 18 | for( int j = 0; j < 1000000; j++ ) |
19 | { | 19 | { |
20 | uBucket[(int)(((uint32_t)rand.rand())/(double)(0xfffffffful)*78+0.5)]++; | 20 | uBucket[(int)(((uint32_t)rand.rand())/(double)(0xfffffffful)*78+0.5)]++; |
21 | } | 21 | } |
22 | 22 | ||
23 | uint32_t uMax = 0; | 23 | uint32_t uMax = 0; |
24 | for( int j = 0; j < 78; j++ ) | 24 | for( int j = 0; j < 78; j++ ) |
25 | { | 25 | { |
26 | if( uMax < uBucket[j] ) | 26 | if( uMax < uBucket[j] ) |
27 | uMax = uBucket[j]; | 27 | uMax = uBucket[j]; |
28 | } | 28 | } |
29 | 29 | ||
30 | for( int y = 20; y >= 1; y-- ) | 30 | for( int y = 20; y >= 1; y-- ) |
31 | { | 31 | { |
32 | uint32_t iT = (uint32_t)((y/20.0)*uMax); | 32 | uint32_t iT = (uint32_t)((y/20.0)*uMax); |
33 | for( int x = 0; x < 78; x++ ) | 33 | for( int x = 0; x < 78; x++ ) |
34 | { | 34 | { |
35 | sio << ((iT<=uBucket[x])?"#":" "); | 35 | sio << ((iT<=uBucket[x])?"#":" "); |
36 | } | 36 | } |
37 | sio << sio.nl; | 37 | sio << sio.nl; |
38 | } | 38 | } |
39 | } | 39 | } |
40 | 40 | ||
41 | int main() | 41 | int main() |
42 | { | 42 | { |
43 | coverage<RandomBasic>(); | 43 | coverage<RandomBasic>(); |
44 | coverage<RandomCmwc>(); | 44 | coverage<RandomCmwc>(); |
45 | coverage<RandomSystem>(); | 45 | coverage<RandomSystem>(); |
46 | 46 | ||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/src/tests/regex.cpp b/src/tests/regex.cpp index 82c3466..7e4188e 100644 --- a/src/tests/regex.cpp +++ b/src/tests/regex.cpp | |||
@@ -6,35 +6,35 @@ using namespace Bu; | |||
6 | 6 | ||
7 | void compile( const Bu::String &s, Bu::RegExEngine<char> &ree ) | 7 | void compile( const Bu::String &s, Bu::RegExEngine<char> &ree ) |
8 | { | 8 | { |
9 | int iRoot = ree.addState(); | 9 | int iRoot = ree.addState(); |
10 | int iCur = iRoot; | 10 | int iCur = iRoot; |
11 | for( Bu::String::const_iterator i = s.begin(); i; i++ ) | 11 | for( Bu::String::const_iterator i = s.begin(); i; i++ ) |
12 | { | 12 | { |
13 | int iNext = -1; | 13 | int iNext = -1; |
14 | if( i+1 ) | 14 | if( i+1 ) |
15 | iNext = ree.addState(); | 15 | iNext = ree.addState(); |
16 | ree.addCompletion( iCur, *i, *i, iNext ); | 16 | ree.addCompletion( iCur, *i, *i, iNext ); |
17 | iCur = iNext; | 17 | iCur = iNext; |
18 | } | 18 | } |
19 | } | 19 | } |
20 | 20 | ||
21 | int main() | 21 | int main() |
22 | { | 22 | { |
23 | Bu::String sRegEx("abcd"); | 23 | Bu::String sRegEx("abcd"); |
24 | Bu::String sMatch("abcdefg"); | 24 | Bu::String sMatch("abcdefg"); |
25 | 25 | ||
26 | Bu::RegExEngine<char> ree; | 26 | Bu::RegExEngine<char> ree; |
27 | 27 | ||
28 | compile( sRegEx, ree ); | 28 | compile( sRegEx, ree ); |
29 | 29 | ||
30 | bool bRet; | 30 | bool bRet; |
31 | int iSize, iCompletion; | 31 | int iSize, iCompletion; |
32 | bRet = ree.match( sMatch, iSize, iCompletion ); | 32 | bRet = ree.match( sMatch, iSize, iCompletion ); |
33 | 33 | ||
34 | sio << "Matched: " << bRet << sio.nl | 34 | sio << "Matched: " << bRet << sio.nl |
35 | << "Size: " << iSize << sio.nl | 35 | << "Size: " << iSize << sio.nl |
36 | << "Completion: " << iCompletion << sio.nl; | 36 | << "Completion: " << iCompletion << sio.nl; |
37 | 37 | ||
38 | return 0; | 38 | return 0; |
39 | } | 39 | } |
40 | 40 | ||
diff --git a/src/tests/settings.cpp b/src/tests/settings.cpp index 2caa015..cf998ed 100644 --- a/src/tests/settings.cpp +++ b/src/tests/settings.cpp | |||
@@ -5,14 +5,14 @@ using namespace Bu; | |||
5 | 5 | ||
6 | int main() | 6 | int main() |
7 | { | 7 | { |
8 | Bu::Settings s("Xagasoft", "Settings"); | 8 | Bu::Settings s("Xagasoft", "Settings"); |
9 | 9 | ||
10 | sio << s.get("Something", "BAD").get() << sio.nl; | 10 | sio << s.get("Something", "BAD").get() << sio.nl; |
11 | sio << s.get("general/path", "BAD").get() << sio.nl; | 11 | sio << s.get("general/path", "BAD").get() << sio.nl; |
12 | sio << s.get("general/magic", "BAD").get() << sio.nl; | 12 | sio << s.get("general/magic", "BAD").get() << sio.nl; |
13 | 13 | ||
14 | s.set("Something", "bob"); | 14 | s.set("Something", "bob"); |
15 | s.set("general/path", "E:\\Place"); | 15 | s.set("general/path", "E:\\Place"); |
16 | 16 | ||
17 | } | 17 | } |
18 | 18 | ||
diff --git a/src/tests/synchroqueue.cpp b/src/tests/synchroqueue.cpp index 980a4a3..9e8c787 100644 --- a/src/tests/synchroqueue.cpp +++ b/src/tests/synchroqueue.cpp | |||
@@ -5,14 +5,14 @@ | |||
5 | class Thing | 5 | class Thing |
6 | { | 6 | { |
7 | public: | 7 | public: |
8 | Thing( int x ) : | 8 | Thing( int x ) : |
9 | x( x ), | 9 | x( x ), |
10 | y( 0 ) | 10 | y( 0 ) |
11 | { | 11 | { |
12 | } | 12 | } |
13 | 13 | ||
14 | int x; | 14 | int x; |
15 | int y; | 15 | int y; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | typedef Bu::SynchroQueue<Thing *> ThingQueue; | 18 | typedef Bu::SynchroQueue<Thing *> ThingQueue; |
@@ -23,109 +23,109 @@ Bu::Condition cWorkDone; | |||
23 | 23 | ||
24 | void workDone() | 24 | void workDone() |
25 | { | 25 | { |
26 | mWorkDone.lock(); | 26 | mWorkDone.lock(); |
27 | iWorkDone--; | 27 | iWorkDone--; |
28 | if( iWorkDone == 0 ) | 28 | if( iWorkDone == 0 ) |
29 | { | 29 | { |
30 | mWorkDone.unlock(); | 30 | mWorkDone.unlock(); |
31 | cWorkDone.lock(); | 31 | cWorkDone.lock(); |
32 | cWorkDone.signal(); | 32 | cWorkDone.signal(); |
33 | cWorkDone.unlock(); | 33 | cWorkDone.unlock(); |
34 | return; | 34 | return; |
35 | } | 35 | } |
36 | mWorkDone.unlock(); | 36 | mWorkDone.unlock(); |
37 | } | 37 | } |
38 | 38 | ||
39 | class ThingEater : public Bu::Thread | 39 | class ThingEater : public Bu::Thread |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | ThingEater( ThingQueue &qThing ) : | 42 | ThingEater( ThingQueue &qThing ) : |
43 | qThing( qThing ) | 43 | qThing( qThing ) |
44 | { | 44 | { |
45 | } | 45 | } |
46 | 46 | ||
47 | bool bRunning; | 47 | bool bRunning; |
48 | 48 | ||
49 | void setRunning( bool b ) | 49 | void setRunning( bool b ) |
50 | { | 50 | { |
51 | mRunning.lock(); | 51 | mRunning.lock(); |
52 | bRunning = b; | 52 | bRunning = b; |
53 | mRunning.unlock(); | 53 | mRunning.unlock(); |
54 | } | 54 | } |
55 | 55 | ||
56 | bool isRunning() | 56 | bool isRunning() |
57 | { | 57 | { |
58 | mRunning.lock(); | 58 | mRunning.lock(); |
59 | bool b = bRunning; | 59 | bool b = bRunning; |
60 | mRunning.unlock(); | 60 | mRunning.unlock(); |
61 | return b; | 61 | return b; |
62 | } | 62 | } |
63 | 63 | ||
64 | protected: | 64 | protected: |
65 | virtual void run() | 65 | virtual void run() |
66 | { | 66 | { |
67 | setRunning( true ); | 67 | setRunning( true ); |
68 | while( isRunning() ) | 68 | while( isRunning() ) |
69 | { | 69 | { |
70 | Thing *pThing = qThing.dequeue( 0, 250000 ); | 70 | Thing *pThing = qThing.dequeue( 0, 250000 ); |
71 | if( pThing == NULL ) | 71 | if( pThing == NULL ) |
72 | continue; | 72 | continue; |
73 | 73 | ||
74 | pThing->y = pThing->x*2; | 74 | pThing->y = pThing->x*2; |
75 | usleep( 10000 ); | 75 | usleep( 10000 ); |
76 | 76 | ||
77 | workDone(); | 77 | workDone(); |
78 | } | 78 | } |
79 | } | 79 | } |
80 | 80 | ||
81 | ThingQueue &qThing; | 81 | ThingQueue &qThing; |
82 | Bu::Mutex mRunning; | 82 | Bu::Mutex mRunning; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | typedef Bu::List<ThingEater *> ThingEaterList; | 85 | typedef Bu::List<ThingEater *> ThingEaterList; |
86 | 86 | ||
87 | int main() | 87 | int main() |
88 | { | 88 | { |
89 | ThingQueue qThing; | 89 | ThingQueue qThing; |
90 | ThingEaterList lEater; | 90 | ThingEaterList lEater; |
91 | 91 | ||
92 | mWorkDone.lock(); | 92 | mWorkDone.lock(); |
93 | iWorkDone = 1000; | 93 | iWorkDone = 1000; |
94 | mWorkDone.unlock(); | 94 | mWorkDone.unlock(); |
95 | 95 | ||
96 | for( int j = 0; j < 5; j++ ) | 96 | for( int j = 0; j < 5; j++ ) |
97 | lEater.append( new ThingEater( qThing ) ); | 97 | lEater.append( new ThingEater( qThing ) ); |
98 | 98 | ||
99 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) | 99 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) |
100 | (*i)->start(); | 100 | (*i)->start(); |
101 | 101 | ||
102 | for( int j = 0; j < 1000; j++ ) | 102 | for( int j = 0; j < 1000; j++ ) |
103 | { | 103 | { |
104 | qThing.enqueue( new Thing( j ) ); | 104 | qThing.enqueue( new Thing( j ) ); |
105 | } | 105 | } |
106 | 106 | ||
107 | mWorkDone.lock(); | 107 | mWorkDone.lock(); |
108 | mWorkDone.unlock(); | 108 | mWorkDone.unlock(); |
109 | cWorkDone.lock(); | 109 | cWorkDone.lock(); |
110 | for(;;) | 110 | for(;;) |
111 | { | 111 | { |
112 | mWorkDone.lock(); | 112 | mWorkDone.lock(); |
113 | if( iWorkDone == 0 ) | 113 | if( iWorkDone == 0 ) |
114 | { | 114 | { |
115 | mWorkDone.unlock(); | 115 | mWorkDone.unlock(); |
116 | break; | 116 | break; |
117 | } | 117 | } |
118 | mWorkDone.unlock(); | 118 | mWorkDone.unlock(); |
119 | cWorkDone.wait(); | 119 | cWorkDone.wait(); |
120 | } | 120 | } |
121 | cWorkDone.unlock(); | 121 | cWorkDone.unlock(); |
122 | 122 | ||
123 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) | 123 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) |
124 | (*i)->setRunning( false ); | 124 | (*i)->setRunning( false ); |
125 | 125 | ||
126 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) | 126 | for( ThingEaterList::iterator i = lEater.begin(); i; i++ ) |
127 | (*i)->join(); | 127 | (*i)->join(); |
128 | 128 | ||
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
131 | 131 | ||
diff --git a/src/tests/taf.cpp b/src/tests/taf.cpp index e4354f7..0ba551f 100644 --- a/src/tests/taf.cpp +++ b/src/tests/taf.cpp | |||
@@ -10,35 +10,35 @@ | |||
10 | 10 | ||
11 | int main( int argc, char *argv[] ) | 11 | int main( int argc, char *argv[] ) |
12 | { | 12 | { |
13 | if( argc == 1 ) | 13 | if( argc == 1 ) |
14 | { | 14 | { |
15 | Bu::File f("test.taf", Bu::File::Read ); | 15 | Bu::File f("test.taf", Bu::File::Read ); |
16 | Bu::TafReader tr( f ); | 16 | Bu::TafReader tr( f ); |
17 | 17 | ||
18 | Bu::TafGroup *pGroup = tr.readGroup(); | 18 | Bu::TafGroup *pGroup = tr.readGroup(); |
19 | 19 | ||
20 | { | 20 | { |
21 | Bu::File fo("out.taf", Bu::File::Write|Bu::File::Create ); | 21 | Bu::File fo("out.taf", Bu::File::Write|Bu::File::Create ); |
22 | Bu::TafWriter tw( fo ); | 22 | Bu::TafWriter tw( fo ); |
23 | tw.writeGroup( pGroup ); | 23 | tw.writeGroup( pGroup ); |
24 | } | 24 | } |
25 | 25 | ||
26 | delete pGroup; | 26 | delete pGroup; |
27 | } | 27 | } |
28 | else if( argc == 3 ) | 28 | else if( argc == 3 ) |
29 | { | 29 | { |
30 | Bu::File f( argv[1], Bu::File::Read ); | 30 | Bu::File f( argv[1], Bu::File::Read ); |
31 | Bu::TafReader tr( f ); | 31 | Bu::TafReader tr( f ); |
32 | 32 | ||
33 | Bu::TafGroup *pGroup = tr.readGroup(); | 33 | Bu::TafGroup *pGroup = tr.readGroup(); |
34 | 34 | ||
35 | { | 35 | { |
36 | Bu::File fo( argv[2], Bu::File::Write|Bu::File::Create ); | 36 | Bu::File fo( argv[2], Bu::File::Write|Bu::File::Create ); |
37 | Bu::TafWriter tw( fo ); | 37 | Bu::TafWriter tw( fo ); |
38 | tw.writeGroup( pGroup ); | 38 | tw.writeGroup( pGroup ); |
39 | } | 39 | } |
40 | 40 | ||
41 | delete pGroup; | 41 | delete pGroup; |
42 | } | 42 | } |
43 | } | 43 | } |
44 | 44 | ||
diff --git a/src/tests/threadid.cpp b/src/tests/threadid.cpp index 9ff99df..dfea504 100644 --- a/src/tests/threadid.cpp +++ b/src/tests/threadid.cpp | |||
@@ -9,64 +9,64 @@ using namespace Bu; | |||
9 | class CopyThing | 9 | class CopyThing |
10 | { | 10 | { |
11 | public: | 11 | public: |
12 | CopyThing() | 12 | CopyThing() |
13 | { | 13 | { |
14 | TRACE(); | 14 | TRACE(); |
15 | tidHome = Thread::currentThread(); | 15 | tidHome = Thread::currentThread(); |
16 | } | 16 | } |
17 | 17 | ||
18 | CopyThing( const CopyThing &rSrc ) | 18 | CopyThing( const CopyThing &rSrc ) |
19 | { | 19 | { |
20 | TRACE(); | 20 | TRACE(); |
21 | tidHome = Thread::currentThread(); | 21 | tidHome = Thread::currentThread(); |
22 | sio << "Same thread? " << (tidHome == rSrc.tidHome) << sio.nl; | 22 | sio << "Same thread? " << (tidHome == rSrc.tidHome) << sio.nl; |
23 | } | 23 | } |
24 | 24 | ||
25 | void doThings() | 25 | void doThings() |
26 | { | 26 | { |
27 | TRACE(); | 27 | TRACE(); |
28 | if( tidHome != Thread::currentThread() ) | 28 | if( tidHome != Thread::currentThread() ) |
29 | sio << "Different threads, hard copy here." << sio.nl; | 29 | sio << "Different threads, hard copy here." << sio.nl; |
30 | else | 30 | else |
31 | sio << "Same thread, everything is cool." << sio.nl; | 31 | sio << "Same thread, everything is cool." << sio.nl; |
32 | } | 32 | } |
33 | 33 | ||
34 | private: | 34 | private: |
35 | ThreadId tidHome; | 35 | ThreadId tidHome; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | class SubThread : public Thread | 38 | class SubThread : public Thread |
39 | { | 39 | { |
40 | public: | 40 | public: |
41 | SubThread( CopyThing &src ) : | 41 | SubThread( CopyThing &src ) : |
42 | src( src ) | 42 | src( src ) |
43 | { | 43 | { |
44 | src.doThings(); | 44 | src.doThings(); |
45 | } | 45 | } |
46 | 46 | ||
47 | protected: | 47 | protected: |
48 | void run() | 48 | void run() |
49 | { | 49 | { |
50 | src.doThings(); | 50 | src.doThings(); |
51 | sio << "run-Child is me? " << (getId() == Thread::currentThread()) << sio.nl; | 51 | sio << "run-Child is me? " << (getId() == Thread::currentThread()) << sio.nl; |
52 | } | 52 | } |
53 | 53 | ||
54 | private: | 54 | private: |
55 | CopyThing src; | 55 | CopyThing src; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | int main( int argc, char *argv[] ) | 58 | int main( int argc, char *argv[] ) |
59 | { | 59 | { |
60 | CopyThing a; | 60 | CopyThing a; |
61 | 61 | ||
62 | SubThread st( a ); | 62 | SubThread st( a ); |
63 | st.start(); | 63 | st.start(); |
64 | 64 | ||
65 | sio << "Child is me? " << (st.getId() == Thread::currentThread()) << sio.nl; | 65 | sio << "Child is me? " << (st.getId() == Thread::currentThread()) << sio.nl; |
66 | 66 | ||
67 | st.join(); | 67 | st.join(); |
68 | 68 | ||
69 | 69 | ||
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
72 | 72 | ||
diff --git a/src/tests/utf.cpp b/src/tests/utf.cpp index 923b611..40d4194 100644 --- a/src/tests/utf.cpp +++ b/src/tests/utf.cpp | |||
@@ -7,65 +7,65 @@ using namespace Bu; | |||
7 | 7 | ||
8 | int main() | 8 | int main() |
9 | { | 9 | { |
10 | sio << "Code: " << Bu::__calcHashCode( Bu::UtfString("Hello there") ) | 10 | sio << "Code: " << Bu::__calcHashCode( Bu::UtfString("Hello there") ) |
11 | << sio.nl; | 11 | << sio.nl; |
12 | 12 | ||
13 | Bu::File fIn("utf8.in", Bu::File::Read ); | 13 | Bu::File fIn("utf8.in", Bu::File::Read ); |
14 | Bu::String sUtf8; | 14 | Bu::String sUtf8; |
15 | char buf[4096]; | 15 | char buf[4096]; |
16 | while( !fIn.isEos() ) | 16 | while( !fIn.isEos() ) |
17 | { | 17 | { |
18 | int iAmnt = fIn.read( buf, 4096 ); | 18 | int iAmnt = fIn.read( buf, 4096 ); |
19 | sUtf8.append( buf, iAmnt ); | 19 | sUtf8.append( buf, iAmnt ); |
20 | } | 20 | } |
21 | Bu::UtfString us( sUtf8, Bu::UtfString::Utf8 ); | 21 | Bu::UtfString us( sUtf8, Bu::UtfString::Utf8 ); |
22 | us.debug(); | 22 | us.debug(); |
23 | { | 23 | { |
24 | Bu::File fOut("utf8.out", Bu::File::WriteNew ); | 24 | Bu::File fOut("utf8.out", Bu::File::WriteNew ); |
25 | us.write( fOut, Bu::UtfString::Utf8 ); | 25 | us.write( fOut, Bu::UtfString::Utf8 ); |
26 | } | 26 | } |
27 | { | 27 | { |
28 | Bu::File fOut("utf16.out", Bu::File::WriteNew ); | 28 | Bu::File fOut("utf16.out", Bu::File::WriteNew ); |
29 | us.write( fOut, Bu::UtfString::Utf16 ); | 29 | us.write( fOut, Bu::UtfString::Utf16 ); |
30 | } | 30 | } |
31 | { | 31 | { |
32 | Bu::File fOut("utf16le.out", Bu::File::WriteNew ); | 32 | Bu::File fOut("utf16le.out", Bu::File::WriteNew ); |
33 | us.write( fOut, Bu::UtfString::Utf16le ); | 33 | us.write( fOut, Bu::UtfString::Utf16le ); |
34 | } | 34 | } |
35 | { | 35 | { |
36 | Bu::File fOut("utf16be.out", Bu::File::WriteNew ); | 36 | Bu::File fOut("utf16be.out", Bu::File::WriteNew ); |
37 | us.write( fOut, Bu::UtfString::Utf16be ); | 37 | us.write( fOut, Bu::UtfString::Utf16be ); |
38 | } | 38 | } |
39 | { | 39 | { |
40 | Bu::File fOut("utf32.out", Bu::File::WriteNew ); | 40 | Bu::File fOut("utf32.out", Bu::File::WriteNew ); |
41 | us.write( fOut, Bu::UtfString::Utf32 ); | 41 | us.write( fOut, Bu::UtfString::Utf32 ); |
42 | } | 42 | } |
43 | { | 43 | { |
44 | Bu::File fOut("utf32le.out", Bu::File::WriteNew ); | 44 | Bu::File fOut("utf32le.out", Bu::File::WriteNew ); |
45 | us.write( fOut, Bu::UtfString::Utf32le ); | 45 | us.write( fOut, Bu::UtfString::Utf32le ); |
46 | } | 46 | } |
47 | { | 47 | { |
48 | Bu::File fOut("utf32be.out", Bu::File::WriteNew ); | 48 | Bu::File fOut("utf32be.out", Bu::File::WriteNew ); |
49 | us.write( fOut, Bu::UtfString::Utf32be ); | 49 | us.write( fOut, Bu::UtfString::Utf32be ); |
50 | } | 50 | } |
51 | 51 | ||
52 | /* | 52 | /* |
53 | argc--, argv++; | 53 | argc--, argv++; |
54 | 54 | ||
55 | for( char **sFile = argv; *sFile; sFile++ ) | 55 | for( char **sFile = argv; *sFile; sFile++ ) |
56 | { | 56 | { |
57 | Bu::File fIn( *sFile, Bu::File::Read ); | 57 | Bu::File fIn( *sFile, Bu::File::Read ); |
58 | Bu::String sUtf8; | 58 | Bu::String sUtf8; |
59 | char buf[4096]; | 59 | char buf[4096]; |
60 | while( !fIn.isEos() ) | 60 | while( !fIn.isEos() ) |
61 | { | 61 | { |
62 | int iAmnt = fIn.read( buf, 4096 ); | 62 | int iAmnt = fIn.read( buf, 4096 ); |
63 | sUtf8.append( buf, iAmnt ); | 63 | sUtf8.append( buf, iAmnt ); |
64 | } | 64 | } |
65 | Bu::UtfString us( sUtf8, Bu::UtfString::Utf16 ); | 65 | Bu::UtfString us( sUtf8, Bu::UtfString::Utf16 ); |
66 | 66 | ||
67 | us.debug(); | 67 | us.debug(); |
68 | } | 68 | } |
69 | */ | 69 | */ |
70 | } | 70 | } |
71 | 71 | ||
diff --git a/src/tests/uuid.cpp b/src/tests/uuid.cpp index d612ad5..152ba26 100644 --- a/src/tests/uuid.cpp +++ b/src/tests/uuid.cpp | |||
@@ -12,11 +12,11 @@ using namespace Bu; | |||
12 | 12 | ||
13 | int main() | 13 | int main() |
14 | { | 14 | { |
15 | Uuid i = Uuid::gen(); | 15 | Uuid i = Uuid::gen(); |
16 | 16 | ||
17 | sio << i.toString() << sio.nl; | 17 | sio << i.toString() << sio.nl; |
18 | sio << "Version: " << i.getVersion() << sio.nl; | 18 | sio << "Version: " << i.getVersion() << sio.nl; |
19 | 19 | ||
20 | return 0; | 20 | return 0; |
21 | } | 21 | } |
22 | 22 | ||
diff --git a/src/tools/bin2cpp.cpp b/src/tools/bin2cpp.cpp index 0b822f0..4214b34 100644 --- a/src/tools/bin2cpp.cpp +++ b/src/tools/bin2cpp.cpp | |||
@@ -16,244 +16,244 @@ using namespace Bu; | |||
16 | class Options : public OptParser | 16 | class Options : public OptParser |
17 | { | 17 | { |
18 | public: | 18 | public: |
19 | Options( int argc, char *argv[] ) : | 19 | Options( int argc, char *argv[] ) : |
20 | sClass("Datafiles") | 20 | sClass("Datafiles") |
21 | { | 21 | { |
22 | addHelpBanner("bin2cpp - convert files into executable-embeddable C++ code.\n"); | 22 | addHelpBanner("bin2cpp - convert files into executable-embeddable C++ code.\n"); |
23 | addHelpBanner("Each file in the input is loaded, filtered according to your options, and written as stack allocated, static variables in a generated class. You can then access the files as though they were on disk through that class."); | 23 | addHelpBanner("Each file in the input is loaded, filtered according to your options, and written as stack allocated, static variables in a generated class. You can then access the files as though they were on disk through that class."); |
24 | addHelpBanner("\nUsage: bin2cpp [options] [input1] [input2] [...] [inputN]"); | 24 | addHelpBanner("\nUsage: bin2cpp [options] [input1] [input2] [...] [inputN]"); |
25 | addHelpBanner( " Or: bin2cpp -s <taf spec file>\n"); | 25 | addHelpBanner( " Or: bin2cpp -s <taf spec file>\n"); |
26 | addOption( sClass, 'c', "Class name [default=\"Datafiles\"]"); | 26 | addOption( sClass, 'c', "Class name [default=\"Datafiles\"]"); |
27 | addOption( sOutBase, 'o', "Output base filename [defaults to classname]"); | 27 | addOption( sOutBase, 'o', "Output base filename [defaults to classname]"); |
28 | addOption( sOutDir, 'd', "Output directory [defaults to current dir]"); | 28 | addOption( sOutDir, 'd', "Output directory [defaults to current dir]"); |
29 | addOption( slot(this, &Options::addFilter), 'f', "Add filter: deflate, bzip2, lzma, base64, hex"); | 29 | addOption( slot(this, &Options::addFilter), 'f', "Add filter: deflate, bzip2, lzma, base64, hex"); |
30 | addOption( sSpecFile, 's', "Use the specified spec file instead of providing options on the command line. If you use this option all others are ignored."); | 30 | addOption( sSpecFile, 's', "Use the specified spec file instead of providing options on the command line. If you use this option all others are ignored."); |
31 | setNonOption( slot(this, &Options::addInput) ); | 31 | setNonOption( slot(this, &Options::addInput) ); |
32 | addHelpOption(); | 32 | addHelpOption(); |
33 | 33 | ||
34 | parse( argc, argv ); | 34 | parse( argc, argv ); |
35 | 35 | ||
36 | if( !sOutBase.isSet() ) | 36 | if( !sOutBase.isSet() ) |
37 | sOutBase = sClass.toLower(); | 37 | sOutBase = sClass.toLower(); |
38 | if( sOutDir.isSet() ) | 38 | if( sOutDir.isSet() ) |
39 | sOutDir += "/"; | 39 | sOutDir += "/"; |
40 | } | 40 | } |
41 | 41 | ||
42 | virtual ~Options() | 42 | virtual ~Options() |
43 | { | 43 | { |
44 | } | 44 | } |
45 | 45 | ||
46 | int addFilter( Bu::StrArray aArgs ) | 46 | int addFilter( Bu::StrArray aArgs ) |
47 | { | 47 | { |
48 | slFilter.append( aArgs[1] ); | 48 | slFilter.append( aArgs[1] ); |
49 | return 1; | 49 | return 1; |
50 | } | 50 | } |
51 | 51 | ||
52 | int addInput( Bu::StrArray aArgs ) | 52 | int addInput( Bu::StrArray aArgs ) |
53 | { | 53 | { |
54 | slInput.append( aArgs[0] ); | 54 | slInput.append( aArgs[0] ); |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | Bu::String sClass; | 58 | Bu::String sClass; |
59 | Bu::String sOutBase; | 59 | Bu::String sOutBase; |
60 | Bu::String sOutDir; | 60 | Bu::String sOutDir; |
61 | Bu::StringList slInput; | 61 | Bu::StringList slInput; |
62 | Bu::StringList slFilter; | 62 | Bu::StringList slFilter; |
63 | Bu::String sSpecFile; | 63 | Bu::String sSpecFile; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | int main( int argc, char *argv[] ) | 66 | int main( int argc, char *argv[] ) |
67 | { | 67 | { |
68 | Options opt( argc, argv ); | 68 | Options opt( argc, argv ); |
69 | 69 | ||
70 | if( !opt.sSpecFile.isEmpty() ) | 70 | if( !opt.sSpecFile.isEmpty() ) |
71 | { | 71 | { |
72 | Bu::File fTaf( opt.sSpecFile, Bu::File::Read ); | 72 | Bu::File fTaf( opt.sSpecFile, Bu::File::Read ); |
73 | Bu::TafReader rTaf( fTaf ); | 73 | Bu::TafReader rTaf( fTaf ); |
74 | Bu::TafGroup *pRoot = rTaf.readGroup(); | 74 | Bu::TafGroup *pRoot = rTaf.readGroup(); |
75 | 75 | ||
76 | if( pRoot == NULL || pRoot->getName() != "bin2cpp" ) | 76 | if( pRoot == NULL || pRoot->getName() != "bin2cpp" ) |
77 | { | 77 | { |
78 | sio << "Specfied spec file does not appear to be a bin2cpp taf " | 78 | sio << "Specfied spec file does not appear to be a bin2cpp taf " |
79 | "specifications file." << sio.nl; | 79 | "specifications file." << sio.nl; |
80 | return 5; | 80 | return 5; |
81 | } | 81 | } |
82 | 82 | ||
83 | opt.sOutBase = opt.sClass = pRoot->getProperty("class"); | 83 | opt.sOutBase = opt.sClass = pRoot->getProperty("class"); |
84 | if( pRoot->hasProperty("output") ) | 84 | if( pRoot->hasProperty("output") ) |
85 | opt.sOutBase = pRoot->getProperty("output"); | 85 | opt.sOutBase = pRoot->getProperty("output"); |
86 | opt.sOutDir = pRoot->getProperty("dir", ".") + "/"; | 86 | opt.sOutDir = pRoot->getProperty("dir", ".") + "/"; |
87 | 87 | ||
88 | delete pRoot; | 88 | delete pRoot; |
89 | } | 89 | } |
90 | 90 | ||
91 | File fHdrOut( opt.sOutDir + opt.sOutBase + ".h", File::WriteNew ); | 91 | File fHdrOut( opt.sOutDir + opt.sOutBase + ".h", File::WriteNew ); |
92 | File fSrcOut( opt.sOutDir + opt.sOutBase + ".cpp", File::WriteNew ); | 92 | File fSrcOut( opt.sOutDir + opt.sOutBase + ".cpp", File::WriteNew ); |
93 | 93 | ||
94 | Bu::Hash<char, bool> hFilters; | 94 | Bu::Hash<char, bool> hFilters; |
95 | 95 | ||
96 | Formatter fHdr( fHdrOut ); | 96 | Formatter fHdr( fHdrOut ); |
97 | Formatter fSrc( fSrcOut ); | 97 | Formatter fSrc( fSrcOut ); |
98 | fHdr << "#ifndef BIN2CPP_" << opt.sClass.toUpper() << "_H" << fHdr.nl | 98 | fHdr << "#ifndef BIN2CPP_" << opt.sClass.toUpper() << "_H" << fHdr.nl |
99 | << "#define BIN2CPP_" << opt.sClass.toUpper() << "_H" << fHdr.nl << fHdr.nl | 99 | << "#define BIN2CPP_" << opt.sClass.toUpper() << "_H" << fHdr.nl << fHdr.nl |
100 | << "#include <bu/string.h>" << fHdr.nl | 100 | << "#include <bu/string.h>" << fHdr.nl |
101 | << "#include <bu/streamstack.h>" << fHdr.nl | 101 | << "#include <bu/streamstack.h>" << fHdr.nl |
102 | << fHdr.nl | 102 | << fHdr.nl |
103 | << "class " << opt.sClass << fHdr.nl | 103 | << "class " << opt.sClass << fHdr.nl |
104 | << "{" << fHdr.nl | 104 | << "{" << fHdr.nl |
105 | << "public:" << fHdr.nl | 105 | << "public:" << fHdr.nl |
106 | << "\tclass File { public: int iSize; const char *data; const char *flt; };" << fHdr.nl << fHdr.nl | 106 | << "\tclass File { public: int iSize; const char *data; const char *flt; };" << fHdr.nl << fHdr.nl |
107 | << "\tstatic const File &getFile( const Bu::String &sName );" << fHdr.nl | 107 | << "\tstatic const File &getFile( const Bu::String &sName );" << fHdr.nl |
108 | << "\tstatic Bu::StreamStack *open( const Bu::String &sName );" << fHdr.nl | 108 | << "\tstatic Bu::StreamStack *open( const Bu::String &sName );" << fHdr.nl |
109 | << "\tstatic Bu::StreamStack *openRaw( const Bu::String &sName );" << fHdr.nl | 109 | << "\tstatic Bu::StreamStack *openRaw( const Bu::String &sName );" << fHdr.nl |
110 | << "\tstatic Bu::String getString( const Bu::String &sName );" << fHdr.nl | 110 | << "\tstatic Bu::String getString( const Bu::String &sName );" << fHdr.nl |
111 | << "\tstatic Bu::String getStringRaw( const Bu::String &sName );" << fHdr.nl | 111 | << "\tstatic Bu::String getStringRaw( const Bu::String &sName );" << fHdr.nl |
112 | << fHdr.nl; | 112 | << fHdr.nl; |
113 | fHdr << "public:" << fHdr.nl | 113 | fHdr << "public:" << fHdr.nl |
114 | << "\tstatic const File aFile[];" << fHdr.nl | 114 | << "\tstatic const File aFile[];" << fHdr.nl |
115 | << "};" << fHdr.nl << fHdr.nl; | 115 | << "};" << fHdr.nl << fHdr.nl; |
116 | fHdr << "#endif"; | 116 | fHdr << "#endif"; |
117 | 117 | ||
118 | fSrc << "#include \"" << opt.sOutBase << ".h\"" << fSrc.nl | 118 | fSrc << "#include \"" << opt.sOutBase << ".h\"" << fSrc.nl |
119 | << "#include <bu/deflate.h>" << fSrc.nl | 119 | << "#include <bu/deflate.h>" << fSrc.nl |
120 | << "#include <bu/bzip2.h>" << fSrc.nl | 120 | << "#include <bu/bzip2.h>" << fSrc.nl |
121 | << "#include <bu/base64.h>" << fSrc.nl | 121 | << "#include <bu/base64.h>" << fSrc.nl |
122 | << "#include <bu/lzma.h>" << fSrc.nl | 122 | << "#include <bu/lzma.h>" << fSrc.nl |
123 | << "#include <bu/hex.h>" << fSrc.nl | 123 | << "#include <bu/hex.h>" << fSrc.nl |
124 | << "#include <bu/strfilter.h>" << fSrc.nl | 124 | << "#include <bu/strfilter.h>" << fSrc.nl |
125 | << "#include <bu/staticmembuf.h>" << fSrc.nl << fSrc.nl | 125 | << "#include <bu/staticmembuf.h>" << fSrc.nl << fSrc.nl |
126 | << "const " << opt.sClass << "::File " << opt.sClass << "::aFile[] = {" << fSrc.nl; | 126 | << "const " << opt.sClass << "::File " << opt.sClass << "::aFile[] = {" << fSrc.nl; |
127 | 127 | ||
128 | for( Bu::StringList::iterator i = opt.slInput.begin(); i; i++ ) | 128 | for( Bu::StringList::iterator i = opt.slInput.begin(); i; i++ ) |
129 | { | 129 | { |
130 | File fIn( *i, File::Read ); | 130 | File fIn( *i, File::Read ); |
131 | Bu::String sDat; | 131 | Bu::String sDat; |
132 | char buf[1024]; | 132 | char buf[1024]; |
133 | while( !fIn.isEos() ) | 133 | while( !fIn.isEos() ) |
134 | { | 134 | { |
135 | sDat.append( buf, fIn.read( buf, 1024 ) ); | 135 | sDat.append( buf, fIn.read( buf, 1024 ) ); |
136 | } | 136 | } |
137 | 137 | ||
138 | Bu::String sFltDesc; | 138 | Bu::String sFltDesc; |
139 | for( Bu::StringList::iterator f = opt.slFilter.begin(); f; f++ ) | 139 | for( Bu::StringList::iterator f = opt.slFilter.begin(); f; f++ ) |
140 | { | 140 | { |
141 | if( *f == "deflate" ) | 141 | if( *f == "deflate" ) |
142 | { | 142 | { |
143 | sDat = encodeStr<Deflate>( sDat ); | 143 | sDat = encodeStr<Deflate>( sDat ); |
144 | sFltDesc.prepend("d"); | 144 | sFltDesc.prepend("d"); |
145 | hFilters.insert('d', true ); | 145 | hFilters.insert('d', true ); |
146 | } | 146 | } |
147 | else if( *f == "bzip2" ) | 147 | else if( *f == "bzip2" ) |
148 | { | 148 | { |
149 | sDat = encodeStr<BZip2>( sDat ); | 149 | sDat = encodeStr<BZip2>( sDat ); |
150 | sFltDesc.prepend("b"); | 150 | sFltDesc.prepend("b"); |
151 | hFilters.insert('b', true ); | 151 | hFilters.insert('b', true ); |
152 | } | 152 | } |
153 | else if( *f == "lzma" ) | 153 | else if( *f == "lzma" ) |
154 | { | 154 | { |
155 | sDat = encodeStr<Lzma>( sDat ); | 155 | sDat = encodeStr<Lzma>( sDat ); |
156 | sFltDesc.prepend("l"); | 156 | sFltDesc.prepend("l"); |
157 | hFilters.insert('l', true ); | 157 | hFilters.insert('l', true ); |
158 | } | 158 | } |
159 | else if( *f == "base64" ) | 159 | else if( *f == "base64" ) |
160 | { | 160 | { |
161 | sDat = encodeStr<Base64>( sDat ); | 161 | sDat = encodeStr<Base64>( sDat ); |
162 | sFltDesc.prepend("6"); | 162 | sFltDesc.prepend("6"); |
163 | hFilters.insert('6', true ); | 163 | hFilters.insert('6', true ); |
164 | } | 164 | } |
165 | else if( *f == "hex" ) | 165 | else if( *f == "hex" ) |
166 | { | 166 | { |
167 | sDat = encodeStr<Hex>( sDat ); | 167 | sDat = encodeStr<Hex>( sDat ); |
168 | sFltDesc.prepend("h"); | 168 | sFltDesc.prepend("h"); |
169 | hFilters.insert('h', true ); | 169 | hFilters.insert('h', true ); |
170 | } | 170 | } |
171 | else | 171 | else |
172 | { | 172 | { |
173 | sio << "No known filter named " << *f << sio.nl; | 173 | sio << "No known filter named " << *f << sio.nl; |
174 | return 1; | 174 | return 1; |
175 | } | 175 | } |
176 | } | 176 | } |
177 | 177 | ||
178 | fSrc << " {" << sDat.getSize() << ", \""; | 178 | fSrc << " {" << sDat.getSize() << ", \""; |
179 | 179 | ||
180 | for( Bu::String::iterator j = sDat.begin(); j; j++ ) | 180 | for( Bu::String::iterator j = sDat.begin(); j; j++ ) |
181 | { | 181 | { |
182 | fSrc << "\\x" << Fmt::hex() << (unsigned char)*j; | 182 | fSrc << "\\x" << Fmt::hex() << (unsigned char)*j; |
183 | } | 183 | } |
184 | fSrc << "\", \"" << sFltDesc << "\"}," << fSrc.nl; | 184 | fSrc << "\", \"" << sFltDesc << "\"}," << fSrc.nl; |
185 | } | 185 | } |
186 | fSrc << "};" << fSrc.nl << fSrc.nl; | 186 | fSrc << "};" << fSrc.nl << fSrc.nl; |
187 | 187 | ||
188 | fSrc << "const " << opt.sClass << "::File &" << opt.sClass << "::getFile( const Bu::String &sName )" | 188 | fSrc << "const " << opt.sClass << "::File &" << opt.sClass << "::getFile( const Bu::String &sName )" |
189 | << fSrc.nl | 189 | << fSrc.nl |
190 | << "{" << fSrc.nl | 190 | << "{" << fSrc.nl |
191 | << "\tswitch( Bu::__calcHashCode( sName ) )" << fSrc.nl | 191 | << "\tswitch( Bu::__calcHashCode( sName ) )" << fSrc.nl |
192 | << "\t{" << fSrc.nl; | 192 | << "\t{" << fSrc.nl; |
193 | 193 | ||
194 | int idx = 0; | 194 | int idx = 0; |
195 | for( Bu::StringList::iterator i = opt.slInput.begin(); i; i++ ) | 195 | for( Bu::StringList::iterator i = opt.slInput.begin(); i; i++ ) |
196 | { | 196 | { |
197 | fSrc << "\t\tcase " << Bu::__calcHashCode( *i ) << "UL:" << fSrc.nl | 197 | fSrc << "\t\tcase " << Bu::__calcHashCode( *i ) << "UL:" << fSrc.nl |
198 | << "\t\t\treturn aFile[" << idx << "];" << fSrc.nl; | 198 | << "\t\t\treturn aFile[" << idx << "];" << fSrc.nl; |
199 | idx++; | 199 | idx++; |
200 | } | 200 | } |
201 | fSrc << "\t}" << fSrc.nl | 201 | fSrc << "\t}" << fSrc.nl |
202 | << "\tthrow Bu::ExceptionBase(\"No file matching \\\"%s\\\" found.\", sName.getStr() );" << fSrc.nl | 202 | << "\tthrow Bu::ExceptionBase(\"No file matching \\\"%s\\\" found.\", sName.getStr() );" << fSrc.nl |
203 | << "}" << fSrc.nl << fSrc.nl; | 203 | << "}" << fSrc.nl << fSrc.nl; |
204 | 204 | ||
205 | fSrc << "Bu::StreamStack *" << opt.sClass << "::open( const Bu::String &sName )" << fSrc.nl | 205 | fSrc << "Bu::StreamStack *" << opt.sClass << "::open( const Bu::String &sName )" << fSrc.nl |
206 | << "{" << fSrc.nl | 206 | << "{" << fSrc.nl |
207 | << "\tconst File &f = getFile( sName );" << fSrc.nl | 207 | << "\tconst File &f = getFile( sName );" << fSrc.nl |
208 | << "\tBu::StreamStack *s = new Bu::StreamStack( new Bu::StaticMemBuf( f.data, f.iSize ) );" << fSrc.nl; | 208 | << "\tBu::StreamStack *s = new Bu::StreamStack( new Bu::StaticMemBuf( f.data, f.iSize ) );" << fSrc.nl; |
209 | 209 | ||
210 | if( !hFilters.isEmpty() ) | 210 | if( !hFilters.isEmpty() ) |
211 | { | 211 | { |
212 | fSrc << "\tfor( const char *t = f.flt; *t; t++ )" << fSrc.nl | 212 | fSrc << "\tfor( const char *t = f.flt; *t; t++ )" << fSrc.nl |
213 | << "\t{" << fSrc.nl | 213 | << "\t{" << fSrc.nl |
214 | << "\t\tswitch( *t )" << fSrc.nl | 214 | << "\t\tswitch( *t )" << fSrc.nl |
215 | << "\t\t{" << fSrc.nl; | 215 | << "\t\t{" << fSrc.nl; |
216 | if( hFilters.has('d') ) | 216 | if( hFilters.has('d') ) |
217 | fSrc << "\t\t\tcase 'd': s->pushFilter<Bu::Deflate>(); break;" << fSrc.nl; | 217 | fSrc << "\t\t\tcase 'd': s->pushFilter<Bu::Deflate>(); break;" << fSrc.nl; |
218 | if( hFilters.has('b') ) | 218 | if( hFilters.has('b') ) |
219 | fSrc << "\t\t\tcase 'b': s->pushFilter<Bu::BZip2>(); break;" << fSrc.nl; | 219 | fSrc << "\t\t\tcase 'b': s->pushFilter<Bu::BZip2>(); break;" << fSrc.nl; |
220 | if( hFilters.has('l') ) | 220 | if( hFilters.has('l') ) |
221 | fSrc << "\t\t\tcase 'l': s->pushFilter<Bu::Lzma>(); break;" << fSrc.nl; | 221 | fSrc << "\t\t\tcase 'l': s->pushFilter<Bu::Lzma>(); break;" << fSrc.nl; |
222 | if( hFilters.has('6') ) | 222 | if( hFilters.has('6') ) |
223 | fSrc << "\t\t\tcase '6': s->pushFilter<Bu::Base64>(); break;" << fSrc.nl; | 223 | fSrc << "\t\t\tcase '6': s->pushFilter<Bu::Base64>(); break;" << fSrc.nl; |
224 | if( hFilters.has('h') ) | 224 | if( hFilters.has('h') ) |
225 | fSrc << "\t\t\tcase 'h': s->pushFilter<Bu::Hex>(); break;" << fSrc.nl; | 225 | fSrc << "\t\t\tcase 'h': s->pushFilter<Bu::Hex>(); break;" << fSrc.nl; |
226 | fSrc << "\t\t}" << fSrc.nl | 226 | fSrc << "\t\t}" << fSrc.nl |
227 | << "\t}" << fSrc.nl; | 227 | << "\t}" << fSrc.nl; |
228 | } | 228 | } |
229 | fSrc << "\treturn s;" << fSrc.nl | 229 | fSrc << "\treturn s;" << fSrc.nl |
230 | << "}" << fSrc.nl << fSrc.nl; | 230 | << "}" << fSrc.nl << fSrc.nl; |
231 | 231 | ||
232 | fSrc << "Bu::StreamStack *" << opt.sClass << "::openRaw( const Bu::String &sName )" << fSrc.nl | 232 | fSrc << "Bu::StreamStack *" << opt.sClass << "::openRaw( const Bu::String &sName )" << fSrc.nl |
233 | << "{" << fSrc.nl | 233 | << "{" << fSrc.nl |
234 | << "\tconst File &f = getFile( sName );" << fSrc.nl | 234 | << "\tconst File &f = getFile( sName );" << fSrc.nl |
235 | << "\treturn new Bu::StreamStack( new Bu::StaticMemBuf( f.data, f.iSize ) );" << fSrc.nl | 235 | << "\treturn new Bu::StreamStack( new Bu::StaticMemBuf( f.data, f.iSize ) );" << fSrc.nl |
236 | << "}" << fSrc.nl << fSrc.nl; | 236 | << "}" << fSrc.nl << fSrc.nl; |
237 | 237 | ||
238 | fSrc << "Bu::String " << opt.sClass << "::getString( const Bu::String &sName )" << fSrc.nl | 238 | fSrc << "Bu::String " << opt.sClass << "::getString( const Bu::String &sName )" << fSrc.nl |
239 | << "{" << fSrc.nl | 239 | << "{" << fSrc.nl |
240 | << "\tBu::StreamStack *ss = open( sName );" << fSrc.nl | 240 | << "\tBu::StreamStack *ss = open( sName );" << fSrc.nl |
241 | << "\tBu::String s;" << fSrc.nl | 241 | << "\tBu::String s;" << fSrc.nl |
242 | << "\tchar buf[1024];" << fSrc.nl | 242 | << "\tchar buf[1024];" << fSrc.nl |
243 | << "\twhile( !ss->isEos() )" << fSrc.nl | 243 | << "\twhile( !ss->isEos() )" << fSrc.nl |
244 | << "\t{" << fSrc.nl | 244 | << "\t{" << fSrc.nl |
245 | << "\t\ts.append( buf, ss->read( buf, 1024 ) );" << fSrc.nl | 245 | << "\t\ts.append( buf, ss->read( buf, 1024 ) );" << fSrc.nl |
246 | << "\t}" << fSrc.nl | 246 | << "\t}" << fSrc.nl |
247 | << "\tdelete ss;" << fSrc.nl | 247 | << "\tdelete ss;" << fSrc.nl |
248 | << "\treturn s;" << fSrc.nl | 248 | << "\treturn s;" << fSrc.nl |
249 | << "}" << fSrc.nl << fSrc.nl; | 249 | << "}" << fSrc.nl << fSrc.nl; |
250 | 250 | ||
251 | fSrc << "Bu::String " << opt.sClass << "::getStringRaw( const Bu::String &sName )" << fSrc.nl | 251 | fSrc << "Bu::String " << opt.sClass << "::getStringRaw( const Bu::String &sName )" << fSrc.nl |
252 | << "{" << fSrc.nl | 252 | << "{" << fSrc.nl |
253 | << "\tconst File &f = getFile( sName );" << fSrc.nl | 253 | << "\tconst File &f = getFile( sName );" << fSrc.nl |
254 | << "\treturn Bu::String( f.data, f.iSize );" << fSrc.nl | 254 | << "\treturn Bu::String( f.data, f.iSize );" << fSrc.nl |
255 | << "}" << fSrc.nl << fSrc.nl; | 255 | << "}" << fSrc.nl << fSrc.nl; |
256 | 256 | ||
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
diff --git a/src/tools/mkunit.cpp b/src/tools/mkunit.cpp index d634feb..96deb6b 100644 --- a/src/tools/mkunit.cpp +++ b/src/tools/mkunit.cpp | |||
@@ -17,236 +17,236 @@ using namespace Bu; | |||
17 | class Test | 17 | class Test |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | Test() : | 20 | Test() : |
21 | bExpectPass( true ) | 21 | bExpectPass( true ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::String sName; | 25 | Bu::String sName; |
26 | bool bExpectPass; | 26 | bool bExpectPass; |
27 | }; | 27 | }; |
28 | typedef Bu::List<Test> TestList; | 28 | typedef Bu::List<Test> TestList; |
29 | 29 | ||
30 | class Suite | 30 | class Suite |
31 | { | 31 | { |
32 | public: | 32 | public: |
33 | Bu::String sName; | 33 | Bu::String sName; |
34 | TestList lTest; | 34 | TestList lTest; |
35 | }; | 35 | }; |
36 | //typedef Bu::List<Suite> SuiteList; | 36 | //typedef Bu::List<Suite> SuiteList; |
37 | 37 | ||
38 | enum TokType | 38 | enum TokType |
39 | { | 39 | { |
40 | tokFluff, | 40 | tokFluff, |
41 | tokSuite, | 41 | tokSuite, |
42 | tokTest, | 42 | tokTest, |
43 | tokChar, | 43 | tokChar, |
44 | tokBlock, | 44 | tokBlock, |
45 | tokEof | 45 | tokEof |
46 | }; | 46 | }; |
47 | 47 | ||
48 | Bu::Formatter &operator<<( Bu::Formatter &f, TokType t ) | 48 | Bu::Formatter &operator<<( Bu::Formatter &f, TokType t ) |
49 | { | 49 | { |
50 | switch( t ) | 50 | switch( t ) |
51 | { | 51 | { |
52 | case tokFluff: return f << "tokFluff"; | 52 | case tokFluff: return f << "tokFluff"; |
53 | case tokSuite: return f << "tokSuite"; | 53 | case tokSuite: return f << "tokSuite"; |
54 | case tokTest: return f << "tokTest"; | 54 | case tokTest: return f << "tokTest"; |
55 | case tokChar: return f << "tokChar"; | 55 | case tokChar: return f << "tokChar"; |
56 | case tokBlock: return f << "tokBlock"; | 56 | case tokBlock: return f << "tokBlock"; |
57 | case tokEof: return f << "tokEof"; | 57 | case tokEof: return f << "tokEof"; |
58 | } | 58 | } |
59 | 59 | ||
60 | return f; | 60 | return f; |
61 | } | 61 | } |
62 | 62 | ||
63 | Bu::Formatter &operator<<( Bu::Formatter &f, const Test &t ) | 63 | Bu::Formatter &operator<<( Bu::Formatter &f, const Test &t ) |
64 | { | 64 | { |
65 | return f << "{" << t.sName << ", bExpectPass=" << t.bExpectPass << "}"; | 65 | return f << "{" << t.sName << ", bExpectPass=" << t.bExpectPass << "}"; |
66 | } | 66 | } |
67 | 67 | ||
68 | Bu::Formatter &operator<<( Bu::Formatter &f, const Suite &s ) | 68 | Bu::Formatter &operator<<( Bu::Formatter &f, const Suite &s ) |
69 | { | 69 | { |
70 | return f << "Suite[" << s.sName << "] = " << s.lTest << f.nl; | 70 | return f << "Suite[" << s.sName << "] = " << s.lTest << f.nl; |
71 | } | 71 | } |
72 | 72 | ||
73 | class Parser | 73 | class Parser |
74 | { | 74 | { |
75 | public: | 75 | public: |
76 | Parser( const Bu::String &sFile ) : | 76 | Parser( const Bu::String &sFile ) : |
77 | sIn( sFile ), | 77 | sIn( sFile ), |
78 | fIn( sFile, File::Read ), | 78 | fIn( sFile, File::Read ), |
79 | bIn( fIn ), | 79 | bIn( fIn ), |
80 | cBuf( 0 ), | 80 | cBuf( 0 ), |
81 | bAvail( false ), | 81 | bAvail( false ), |
82 | eMode( mRoot ), | 82 | eMode( mRoot ), |
83 | iLine( 1 ), | 83 | iLine( 1 ), |
84 | iChar( 0 ), | 84 | iChar( 0 ), |
85 | iDepth( 0 ) | 85 | iDepth( 0 ) |
86 | { | 86 | { |
87 | } | 87 | } |
88 | 88 | ||
89 | char nextChar() | 89 | char nextChar() |
90 | { | 90 | { |
91 | if( bAvail ) | 91 | if( bAvail ) |
92 | return cBuf; | 92 | return cBuf; |
93 | 93 | ||
94 | if( bIn.read( &cBuf, 1 ) < 1 ) | 94 | if( bIn.read( &cBuf, 1 ) < 1 ) |
95 | throw Bu::ExceptionBase("End of stream"); | 95 | throw Bu::ExceptionBase("End of stream"); |
96 | bAvail = true; | 96 | bAvail = true; |
97 | 97 | ||
98 | if( cBuf == '\n' ) | 98 | if( cBuf == '\n' ) |
99 | { | 99 | { |
100 | iLine++; | 100 | iLine++; |
101 | iChar = 0; | 101 | iChar = 0; |
102 | } | 102 | } |
103 | else | 103 | else |
104 | iChar++; | 104 | iChar++; |
105 | 105 | ||
106 | return cBuf; | 106 | return cBuf; |
107 | } | 107 | } |
108 | 108 | ||
109 | TokType nextToken( Variant &v, Bu::String &sWsOut, int &iLineStart, | 109 | TokType nextToken( Variant &v, Bu::String &sWsOut, int &iLineStart, |
110 | int &iCharStart ) | 110 | int &iCharStart ) |
111 | { | 111 | { |
112 | Bu::String sTok, sWs; | 112 | Bu::String sTok, sWs; |
113 | 113 | ||
114 | char buf; | 114 | char buf; |
115 | try | 115 | try |
116 | { | 116 | { |
117 | buf = nextChar(); | 117 | buf = nextChar(); |
118 | } | 118 | } |
119 | catch(...) | 119 | catch(...) |
120 | { | 120 | { |
121 | return tokEof; | 121 | return tokEof; |
122 | } | 122 | } |
123 | 123 | ||
124 | for(;;) | 124 | for(;;) |
125 | { | 125 | { |
126 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) | 126 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) |
127 | { | 127 | { |
128 | sWs += buf; | 128 | sWs += buf; |
129 | bAvail = false; | 129 | bAvail = false; |
130 | } | 130 | } |
131 | else | 131 | else |
132 | break; | 132 | break; |
133 | 133 | ||
134 | try | 134 | try |
135 | { | 135 | { |
136 | buf = nextChar(); | 136 | buf = nextChar(); |
137 | } | 137 | } |
138 | catch(...) | 138 | catch(...) |
139 | { | 139 | { |
140 | sWsOut = sWs; | 140 | sWsOut = sWs; |
141 | return tokEof; | 141 | return tokEof; |
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | sWsOut = sWs; | 145 | sWsOut = sWs; |
146 | 146 | ||
147 | iLineStart = iLine; | 147 | iLineStart = iLine; |
148 | iCharStart = iChar; | 148 | iCharStart = iChar; |
149 | bool bInStr = false; | 149 | bool bInStr = false; |
150 | bool bDblStr; | 150 | bool bDblStr; |
151 | 151 | ||
152 | for(;;) | 152 | for(;;) |
153 | { | 153 | { |
154 | switch( eMode ) | 154 | switch( eMode ) |
155 | { | 155 | { |
156 | case mRoot: | 156 | case mRoot: |
157 | if( buf == ' ' || buf == '\t' || buf == '\n' | 157 | if( buf == ' ' || buf == '\t' || buf == '\n' |
158 | || buf == '\r' ) | 158 | || buf == '\r' ) |
159 | { | 159 | { |
160 | if( sTok == "suite" ) | 160 | if( sTok == "suite" ) |
161 | return tokSuite; | 161 | return tokSuite; |
162 | else | 162 | else |
163 | { | 163 | { |
164 | v = sTok; | 164 | v = sTok; |
165 | return tokFluff; | 165 | return tokFluff; |
166 | } | 166 | } |
167 | } | 167 | } |
168 | else if( buf == '(' || buf == ')' || buf == '{' | 168 | else if( buf == '(' || buf == ')' || buf == '{' |
169 | || buf == '}' || buf == ';' ) | 169 | || buf == '}' || buf == ';' ) |
170 | { | 170 | { |
171 | if( sTok.getSize() == 0 ) | 171 | if( sTok.getSize() == 0 ) |
172 | { | 172 | { |
173 | bAvail = false; | 173 | bAvail = false; |
174 | v = buf; | 174 | v = buf; |
175 | return tokChar; | 175 | return tokChar; |
176 | } | 176 | } |
177 | else | 177 | else |
178 | { | 178 | { |
179 | v = sTok; | 179 | v = sTok; |
180 | return tokFluff; | 180 | return tokFluff; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | else | 183 | else |
184 | { | 184 | { |
185 | sTok += buf; | 185 | sTok += buf; |
186 | bAvail = false; | 186 | bAvail = false; |
187 | } | 187 | } |
188 | break; | 188 | break; |
189 | 189 | ||
190 | case mSuite: | 190 | case mSuite: |
191 | if( buf == ' ' || buf == '\t' || buf == '\n' | 191 | if( buf == ' ' || buf == '\t' || buf == '\n' |
192 | || buf == '\r' ) | 192 | || buf == '\r' ) |
193 | { | 193 | { |
194 | if( sTok == "test" ) | 194 | if( sTok == "test" ) |
195 | return tokTest; | 195 | return tokTest; |
196 | else | 196 | else |
197 | { | 197 | { |
198 | v = sTok; | 198 | v = sTok; |
199 | return tokFluff; | 199 | return tokFluff; |
200 | } | 200 | } |
201 | } | 201 | } |
202 | else if( buf == '(' || buf == ')' | 202 | else if( buf == '(' || buf == ')' |
203 | || buf == '}' || buf == ';' ) | 203 | || buf == '}' || buf == ';' ) |
204 | { | 204 | { |
205 | if( sTok.getSize() == 0 ) | 205 | if( sTok.getSize() == 0 ) |
206 | { | 206 | { |
207 | bAvail = false; | 207 | bAvail = false; |
208 | v = buf; | 208 | v = buf; |
209 | return tokChar; | 209 | return tokChar; |
210 | } | 210 | } |
211 | else | 211 | else |
212 | { | 212 | { |
213 | v = sTok; | 213 | v = sTok; |
214 | return tokFluff; | 214 | return tokFluff; |
215 | } | 215 | } |
216 | } | 216 | } |
217 | else if( buf == '{' ) | 217 | else if( buf == '{' ) |
218 | { | 218 | { |
219 | if( sTok.getSize() > 0 ) | 219 | if( sTok.getSize() > 0 ) |
220 | { | 220 | { |
221 | v = sTok; | 221 | v = sTok; |
222 | return tokFluff; | 222 | return tokFluff; |
223 | } | 223 | } |
224 | else | 224 | else |
225 | { | 225 | { |
226 | sTok += buf; | 226 | sTok += buf; |
227 | bAvail = false; | 227 | bAvail = false; |
228 | eMode = mBlock; | 228 | eMode = mBlock; |
229 | iDepth = 1; | 229 | iDepth = 1; |
230 | } | 230 | } |
231 | } | 231 | } |
232 | else | 232 | else |
233 | { | 233 | { |
234 | sTok += buf; | 234 | sTok += buf; |
235 | bAvail = false; | 235 | bAvail = false; |
236 | } | 236 | } |
237 | break; | 237 | break; |
238 | 238 | ||
239 | case mBlock: | 239 | case mBlock: |
240 | if( bInStr ) | 240 | if( bInStr ) |
241 | { | 241 | { |
242 | if( buf == '\\' ) | 242 | if( buf == '\\' ) |
243 | { | 243 | { |
244 | sTok += buf; | 244 | sTok += buf; |
245 | bAvail = false; | 245 | bAvail = false; |
246 | sTok += nextChar(); | 246 | sTok += nextChar(); |
247 | bAvail = false; | 247 | bAvail = false; |
248 | } | 248 | } |
249 | else if( bDblStr == true && buf == '\"' ) | 249 | else if( bDblStr == true && buf == '\"' ) |
250 | { | 250 | { |
251 | sTok += buf; | 251 | sTok += buf; |
252 | bAvail = false; | 252 | bAvail = false; |
@@ -267,295 +267,295 @@ public: | |||
267 | else | 267 | else |
268 | { | 268 | { |
269 | if( buf == '\"' ) | 269 | if( buf == '\"' ) |
270 | { | 270 | { |
271 | bInStr = true; | 271 | bInStr = true; |
272 | bDblStr = true; | 272 | bDblStr = true; |
273 | sTok += buf; | 273 | sTok += buf; |
274 | bAvail = false; | 274 | bAvail = false; |
275 | } | 275 | } |
276 | else if( buf == '\'' ) | 276 | else if( buf == '\'' ) |
277 | { | 277 | { |
278 | bInStr = true; | 278 | bInStr = true; |
279 | bDblStr = false; | 279 | bDblStr = false; |
280 | sTok += buf; | 280 | sTok += buf; |
281 | bAvail = false; | 281 | bAvail = false; |
282 | } | 282 | } |
283 | else if( buf == '}' ) | 283 | else if( buf == '}' ) |
284 | { | 284 | { |
285 | sTok += buf; | 285 | sTok += buf; |
286 | bAvail = false; | 286 | bAvail = false; |
287 | iDepth--; | 287 | iDepth--; |
288 | if( iDepth == 0 ) | 288 | if( iDepth == 0 ) |
289 | { | 289 | { |
290 | v = sTok; | 290 | v = sTok; |
291 | eMode = mSuite; | 291 | eMode = mSuite; |
292 | return tokBlock; | 292 | return tokBlock; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | else if( buf == '{' ) | 295 | else if( buf == '{' ) |
296 | { | 296 | { |
297 | sTok += buf; | 297 | sTok += buf; |
298 | bAvail = false; | 298 | bAvail = false; |
299 | iDepth++; | 299 | iDepth++; |
300 | } | 300 | } |
301 | else | 301 | else |
302 | { | 302 | { |
303 | sTok += buf; | 303 | sTok += buf; |
304 | bAvail = false; | 304 | bAvail = false; |
305 | } | 305 | } |
306 | } | 306 | } |
307 | break; | 307 | break; |
308 | } | 308 | } |
309 | 309 | ||
310 | buf = nextChar(); | 310 | buf = nextChar(); |
311 | } | 311 | } |
312 | } | 312 | } |
313 | 313 | ||
314 | void firstPass() | 314 | void firstPass() |
315 | { | 315 | { |
316 | Variant v; | 316 | Variant v; |
317 | Bu::String sWs; | 317 | Bu::String sWs; |
318 | int iL, iC; | 318 | int iL, iC; |
319 | for(;;) | 319 | for(;;) |
320 | { | 320 | { |
321 | TokType t = nextToken( v, sWs, iL, iC ); | 321 | TokType t = nextToken( v, sWs, iL, iC ); |
322 | if( t == tokEof ) | 322 | if( t == tokEof ) |
323 | return; | 323 | return; |
324 | switch( eMode ) | 324 | switch( eMode ) |
325 | { | 325 | { |
326 | case mRoot: | 326 | case mRoot: |
327 | if( t == tokSuite ) | 327 | if( t == tokSuite ) |
328 | { | 328 | { |
329 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) | 329 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) |
330 | throw Bu::ExceptionBase("%d:%d: Expected string " | 330 | throw Bu::ExceptionBase("%d:%d: Expected string " |
331 | "following suite.", iL, iC ); | 331 | "following suite.", iL, iC ); |
332 | s.sName = v.get<Bu::String>(); | 332 | s.sName = v.get<Bu::String>(); |
333 | if( nextToken( v, sWs, iL, iC ) != tokChar || | 333 | if( nextToken( v, sWs, iL, iC ) != tokChar || |
334 | v.get<char>() != '{' ) | 334 | v.get<char>() != '{' ) |
335 | throw Bu::ExceptionBase("%d:%d: Expected {, got " | 335 | throw Bu::ExceptionBase("%d:%d: Expected {, got " |
336 | "'%s'", iL, iC, v.toString().getStr() ); | 336 | "'%s'", iL, iC, v.toString().getStr() ); |
337 | eMode = mSuite; | 337 | eMode = mSuite; |
338 | } | 338 | } |
339 | break; | 339 | break; |
340 | 340 | ||
341 | case mSuite: | 341 | case mSuite: |
342 | switch( t ) | 342 | switch( t ) |
343 | { | 343 | { |
344 | case tokFluff: | 344 | case tokFluff: |
345 | break; | 345 | break; |
346 | 346 | ||
347 | case tokBlock: | 347 | case tokBlock: |
348 | break; | 348 | break; |
349 | 349 | ||
350 | case tokTest: | 350 | case tokTest: |
351 | { | 351 | { |
352 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) | 352 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) |
353 | throw Bu::ExceptionBase("%d:%d: Expected " | 353 | throw Bu::ExceptionBase("%d:%d: Expected " |
354 | "string following test.", iL, iC ); | 354 | "string following test.", iL, iC ); |
355 | Test t; | 355 | Test t; |
356 | t.sName = v.get<Bu::String>(); | 356 | t.sName = v.get<Bu::String>(); |
357 | if( nextToken( v, sWs, iL, iC ) != tokBlock ) | 357 | if( nextToken( v, sWs, iL, iC ) != tokBlock ) |
358 | throw Bu::ExceptionBase("%d:%d: Expected " | 358 | throw Bu::ExceptionBase("%d:%d: Expected " |
359 | "{...} block.", | 359 | "{...} block.", |
360 | iL, iC ); | 360 | iL, iC ); |
361 | s.lTest.append( t ); | 361 | s.lTest.append( t ); |
362 | } | 362 | } |
363 | break; | 363 | break; |
364 | 364 | ||
365 | case tokChar: | 365 | case tokChar: |
366 | if( v.get<char>() == '}' ) | 366 | if( v.get<char>() == '}' ) |
367 | { | 367 | { |
368 | eMode = mRoot; | 368 | eMode = mRoot; |
369 | } | 369 | } |
370 | else | 370 | else |
371 | { | 371 | { |
372 | } | 372 | } |
373 | break; | 373 | break; |
374 | 374 | ||
375 | default: | 375 | default: |
376 | sio << iL << ":" << iC << ": Unexpected " | 376 | sio << iL << ":" << iC << ": Unexpected " |
377 | << t << " found." << sio.nl; | 377 | << t << " found." << sio.nl; |
378 | return; | 378 | return; |
379 | break; | 379 | break; |
380 | } | 380 | } |
381 | break; | 381 | break; |
382 | 382 | ||
383 | default: | 383 | default: |
384 | sio << "???" << sio.nl; | 384 | sio << "???" << sio.nl; |
385 | break; | 385 | break; |
386 | } | 386 | } |
387 | } | 387 | } |
388 | } | 388 | } |
389 | 389 | ||
390 | void secondPass( const Bu::String &sOut ) | 390 | void secondPass( const Bu::String &sOut ) |
391 | { | 391 | { |
392 | File fOut( sOut, File::WriteNew ); | 392 | File fOut( sOut, File::WriteNew ); |
393 | Formatter f( fOut ); | 393 | Formatter f( fOut ); |
394 | fIn.setPos( 0 ); | 394 | fIn.setPos( 0 ); |
395 | bIn.stop(); | 395 | bIn.stop(); |
396 | bIn.start(); | 396 | bIn.start(); |
397 | bAvail = false; | 397 | bAvail = false; |
398 | eMode = mRoot; | 398 | eMode = mRoot; |
399 | iLine = 1; | 399 | iLine = 1; |
400 | iChar = 0; | 400 | iChar = 0; |
401 | bool bHasIncluded = false; | 401 | bool bHasIncluded = false; |
402 | 402 | ||
403 | Bu::String sWs; | 403 | Bu::String sWs; |
404 | Variant v; | 404 | Variant v; |
405 | int iL, iC; | 405 | int iL, iC; |
406 | for(;;) | 406 | for(;;) |
407 | { | 407 | { |
408 | TokType t = nextToken( v, sWs, iL, iC ); | 408 | TokType t = nextToken( v, sWs, iL, iC ); |
409 | switch( eMode ) | 409 | switch( eMode ) |
410 | { | 410 | { |
411 | case mRoot: | 411 | case mRoot: |
412 | if( t == tokSuite ) | 412 | if( t == tokSuite ) |
413 | { | 413 | { |
414 | fOut.write( sWs ); | 414 | fOut.write( sWs ); |
415 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) | 415 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) |
416 | throw Bu::ExceptionBase("%d:%d: Expected string " | 416 | throw Bu::ExceptionBase("%d:%d: Expected string " |
417 | "following suite.", iL, iC ); | 417 | "following suite.", iL, iC ); |
418 | s.sName = v.get<Bu::String>(); | 418 | s.sName = v.get<Bu::String>(); |
419 | if( nextToken( v, sWs, iL, iC ) != tokChar || | 419 | if( nextToken( v, sWs, iL, iC ) != tokChar || |
420 | v.get<char>() != '{' ) | 420 | v.get<char>() != '{' ) |
421 | throw Bu::ExceptionBase("%d:%d: Expected {", | 421 | throw Bu::ExceptionBase("%d:%d: Expected {", |
422 | iL, iC ); | 422 | iL, iC ); |
423 | eMode = mSuite; | 423 | eMode = mSuite; |
424 | 424 | ||
425 | if( bHasIncluded == false ) | 425 | if( bHasIncluded == false ) |
426 | { | 426 | { |
427 | fOut.write("#include <bu/unitsuite.h>\n"); | 427 | fOut.write("#include <bu/unitsuite.h>\n"); |
428 | bHasIncluded = true; | 428 | bHasIncluded = true; |
429 | } | 429 | } |
430 | 430 | ||
431 | Bu::String sClass = "_UnitSuite_" + s.sName; | 431 | Bu::String sClass = "_UnitSuite_" + s.sName; |
432 | f << "class " << sClass | 432 | f << "class " << sClass |
433 | << " : public Bu::UnitSuite" << f.nl | 433 | << " : public Bu::UnitSuite" << f.nl |
434 | << "{" << f.nl << "public:" << f.nl | 434 | << "{" << f.nl << "public:" << f.nl |
435 | << "\t" << sClass << "()" << f.nl | 435 | << "\t" << sClass << "()" << f.nl |
436 | << "\t{" << f.nl | 436 | << "\t{" << f.nl |
437 | << "\t\tsetName(\"" << s.sName << "\");" << f.nl; | 437 | << "\t\tsetName(\"" << s.sName << "\");" << f.nl; |
438 | for( TestList::iterator i = s.lTest.begin(); i; i++ ) | 438 | for( TestList::iterator i = s.lTest.begin(); i; i++ ) |
439 | { | 439 | { |
440 | f << "\t\tadd( static_cast<Bu::UnitSuite::Test>(" | 440 | f << "\t\tadd( static_cast<Bu::UnitSuite::Test>(" |
441 | "&" << sClass << "::" << (*i).sName << "), \"" | 441 | "&" << sClass << "::" << (*i).sName << "), \"" |
442 | << (*i).sName << "\", Bu::UnitSuite::" | 442 | << (*i).sName << "\", Bu::UnitSuite::" |
443 | "expectPass );" << f.nl; | 443 | "expectPass );" << f.nl; |
444 | } | 444 | } |
445 | f << "\t}" << f.nl << f.nl | 445 | f << "\t}" << f.nl << f.nl |
446 | << "\tvirtual ~" << sClass << "() { }" << f.nl | 446 | << "\tvirtual ~" << sClass << "() { }" << f.nl |
447 | << f.nl; | 447 | << f.nl; |
448 | } | 448 | } |
449 | else if( t == tokEof ) | 449 | else if( t == tokEof ) |
450 | { | 450 | { |
451 | Bu::String sClass = "_UnitSuite_" + s.sName; | 451 | Bu::String sClass = "_UnitSuite_" + s.sName; |
452 | f << sWs << f.nl << "int main( int argc, char *argv[] )" | 452 | f << sWs << f.nl << "int main( int argc, char *argv[] )" |
453 | << f.nl << "{" << f.nl << "\treturn " << sClass | 453 | << f.nl << "{" << f.nl << "\treturn " << sClass |
454 | << "().run( argc, argv );" << f.nl << "}" << f.nl; | 454 | << "().run( argc, argv );" << f.nl << "}" << f.nl; |
455 | } | 455 | } |
456 | else | 456 | else |
457 | { | 457 | { |
458 | fOut.write( sWs ); | 458 | fOut.write( sWs ); |
459 | f << v; | 459 | f << v; |
460 | } | 460 | } |
461 | break; | 461 | break; |
462 | 462 | ||
463 | case mSuite: | 463 | case mSuite: |
464 | switch( t ) | 464 | switch( t ) |
465 | { | 465 | { |
466 | case tokFluff: | 466 | case tokFluff: |
467 | fOut.write( sWs ); | 467 | fOut.write( sWs ); |
468 | fOut.write( v.get<Bu::String>() ); | 468 | fOut.write( v.get<Bu::String>() ); |
469 | break; | 469 | break; |
470 | 470 | ||
471 | case tokTest: | 471 | case tokTest: |
472 | { | 472 | { |
473 | fOut.write( sWs ); | 473 | fOut.write( sWs ); |
474 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) | 474 | if( nextToken( v, sWs, iL, iC ) != tokFluff ) |
475 | throw Bu::ExceptionBase("%d:%d: Expected " | 475 | throw Bu::ExceptionBase("%d:%d: Expected " |
476 | "string following test.", iL, iC ); | 476 | "string following test.", iL, iC ); |
477 | Test t; | 477 | Test t; |
478 | t.sName = v.get<Bu::String>(); | 478 | t.sName = v.get<Bu::String>(); |
479 | if( nextToken( v, sWs, iL, iC ) != tokBlock ) | 479 | if( nextToken( v, sWs, iL, iC ) != tokBlock ) |
480 | throw Bu::ExceptionBase("%d:%d: Expected " | 480 | throw Bu::ExceptionBase("%d:%d: Expected " |
481 | "{...} block.", | 481 | "{...} block.", |
482 | iL, iC ); | 482 | iL, iC ); |
483 | 483 | ||
484 | f << "\tvoid " << t.sName << "()" | 484 | f << "\tvoid " << t.sName << "()" |
485 | << f.nl << "#line " << iL | 485 | << f.nl << "#line " << iL |
486 | << " \"" << sIn << "\"" << f.nl | 486 | << " \"" << sIn << "\"" << f.nl |
487 | << v << f.nl; | 487 | << v << f.nl; |
488 | } | 488 | } |
489 | break; | 489 | break; |
490 | 490 | ||
491 | case tokChar: | 491 | case tokChar: |
492 | if( v.get<char>() == '}' ) | 492 | if( v.get<char>() == '}' ) |
493 | { | 493 | { |
494 | f << "};" << f.nl << f.nl; | 494 | f << "};" << f.nl << f.nl; |
495 | eMode = mRoot; | 495 | eMode = mRoot; |
496 | } | 496 | } |
497 | else | 497 | else |
498 | { | 498 | { |
499 | char buf = v.get<char>(); | 499 | char buf = v.get<char>(); |
500 | fOut.write( sWs ); | 500 | fOut.write( sWs ); |
501 | fOut.write( &buf, 1 ); | 501 | fOut.write( &buf, 1 ); |
502 | } | 502 | } |
503 | break; | 503 | break; |
504 | 504 | ||
505 | case tokBlock: | 505 | case tokBlock: |
506 | fOut.write( sWs ); | 506 | fOut.write( sWs ); |
507 | f << f.nl << "#line " << iL << " \"" << sIn | 507 | f << f.nl << "#line " << iL << " \"" << sIn |
508 | << "\"" << f.nl; | 508 | << "\"" << f.nl; |
509 | fOut.write( v.get<Bu::String>() ); | 509 | fOut.write( v.get<Bu::String>() ); |
510 | 510 | ||
511 | break; | 511 | break; |
512 | 512 | ||
513 | default: | 513 | default: |
514 | sio << iL << ":" << iC << ": Unexpected " | 514 | sio << iL << ":" << iC << ": Unexpected " |
515 | << t << " found." << sio.nl; | 515 | << t << " found." << sio.nl; |
516 | return; | 516 | return; |
517 | break; | 517 | break; |
518 | } | 518 | } |
519 | break; | 519 | break; |
520 | 520 | ||
521 | default: | 521 | default: |
522 | sio << "???" << sio.nl; | 522 | sio << "???" << sio.nl; |
523 | break; | 523 | break; |
524 | } | 524 | } |
525 | if( t == tokEof ) | 525 | if( t == tokEof ) |
526 | return; | 526 | return; |
527 | } | 527 | } |
528 | } | 528 | } |
529 | 529 | ||
530 | private: | 530 | private: |
531 | Bu::String sIn; | 531 | Bu::String sIn; |
532 | File fIn; | 532 | File fIn; |
533 | Buffer bIn; | 533 | Buffer bIn; |
534 | char cBuf; | 534 | char cBuf; |
535 | bool bAvail; | 535 | bool bAvail; |
536 | enum Mode | 536 | enum Mode |
537 | { | 537 | { |
538 | mRoot, | 538 | mRoot, |
539 | mSuite, | 539 | mSuite, |
540 | mBlock | 540 | mBlock |
541 | }; | 541 | }; |
542 | Mode eMode; | 542 | Mode eMode; |
543 | int iLine, iChar; | 543 | int iLine, iChar; |
544 | int iDepth; | 544 | int iDepth; |
545 | Suite s; | 545 | Suite s; |
546 | }; | 546 | }; |
547 | 547 | ||
548 | int main( int argc, char *argv[] ) | 548 | int main( int argc, char *argv[] ) |
549 | { | 549 | { |
550 | if( argc < 3 ) | 550 | if( argc < 3 ) |
551 | { | 551 | { |
552 | sio << "Too few parameters." << sio.nl; | 552 | sio << "Too few parameters." << sio.nl; |
553 | return 0; | 553 | return 0; |
554 | } | 554 | } |
555 | Parser p( argv[1] ); | 555 | Parser p( argv[1] ); |
556 | 556 | ||
557 | p.firstPass(); | 557 | p.firstPass(); |
558 | 558 | ||
559 | p.secondPass( argv[2] ); | 559 | p.secondPass( argv[2] ); |
560 | } | 560 | } |
561 | 561 | ||
diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp index 7cab628..8a288b0 100644 --- a/src/tools/myriad.cpp +++ b/src/tools/myriad.cpp | |||
@@ -17,237 +17,237 @@ using namespace Bu; | |||
17 | 17 | ||
18 | enum Mode | 18 | enum Mode |
19 | { | 19 | { |
20 | modeCreate, | 20 | modeCreate, |
21 | modeInfo, | 21 | modeInfo, |
22 | modeStreamNew, | 22 | modeStreamNew, |
23 | modeStreamDump, | 23 | modeStreamDump, |
24 | modeStreamPut, | 24 | modeStreamPut, |
25 | modeStreamGet, | 25 | modeStreamGet, |
26 | 26 | ||
27 | modeNone | 27 | modeNone |
28 | }; | 28 | }; |
29 | 29 | ||
30 | class Options : public OptParser | 30 | class Options : public OptParser |
31 | { | 31 | { |
32 | public: | 32 | public: |
33 | Options( int argc, char *argv[] ) : | 33 | Options( int argc, char *argv[] ) : |
34 | eMode( modeNone ), | 34 | eMode( modeNone ), |
35 | iBlockSize( 64 ), | 35 | iBlockSize( 64 ), |
36 | iPreallocate( 0 ), | 36 | iPreallocate( 0 ), |
37 | iStream( 0 ) | 37 | iStream( 0 ) |
38 | { | 38 | { |
39 | addHelpBanner("Mode of operation:"); | 39 | addHelpBanner("Mode of operation:"); |
40 | addOption( eMode, 'c', "create", | 40 | addOption( eMode, 'c', "create", |
41 | "Create a new Myriad file." ); | 41 | "Create a new Myriad file." ); |
42 | addOption( eMode, 'i', "info", | 42 | addOption( eMode, 'i', "info", |
43 | "Display some info about a Myriad file." ); | 43 | "Display some info about a Myriad file." ); |
44 | addOption( eMode, 'n', "new", | 44 | addOption( eMode, 'n', "new", |
45 | "Create a new sub-stream in a Myriad file."); | 45 | "Create a new sub-stream in a Myriad file."); |
46 | addOption( eMode, 'd', "dump", | 46 | addOption( eMode, 'd', "dump", |
47 | "Display a hexdump of a stream from a Myriad file."); | 47 | "Display a hexdump of a stream from a Myriad file."); |
48 | addOption( eMode, "get", | 48 | addOption( eMode, "get", |
49 | "Get a file out of a Myriad stream (use --dst)."); | 49 | "Get a file out of a Myriad stream (use --dst)."); |
50 | addOption( eMode, "put", | 50 | addOption( eMode, "put", |
51 | "Put a file into a Myriad stream (usr --src)."); | 51 | "Put a file into a Myriad stream (usr --src)."); |
52 | addHelpOption(); | 52 | addHelpOption(); |
53 | 53 | ||
54 | addHelpBanner("\nGeneral options:"); | 54 | addHelpBanner("\nGeneral options:"); |
55 | addOption( iBlockSize, 'b', "block-size", "Set the block size." ); | 55 | addOption( iBlockSize, 'b', "block-size", "Set the block size." ); |
56 | addOption( iPreallocate, 'p', "preallocate", | 56 | addOption( iPreallocate, 'p', "preallocate", |
57 | "Number of blocks to preallocate." ); | 57 | "Number of blocks to preallocate." ); |
58 | addOption( sFile, 'f', "file", "Set the Myriad filename." ); | 58 | addOption( sFile, 'f', "file", "Set the Myriad filename." ); |
59 | addOption( iStream, 's', "stream", "Substream to work with."); | 59 | addOption( iStream, 's', "stream", "Substream to work with."); |
60 | addOption( sSrc, "src", "Source file for copying into a Myriad file."); | 60 | addOption( sSrc, "src", "Source file for copying into a Myriad file."); |
61 | addOption( sDst, "dst", | 61 | addOption( sDst, "dst", |
62 | "Destination file for copying out of a Myriad file."); | 62 | "Destination file for copying out of a Myriad file."); |
63 | 63 | ||
64 | setOverride( "create", modeCreate ); | 64 | setOverride( "create", modeCreate ); |
65 | setOverride( "info", modeInfo ); | 65 | setOverride( "info", modeInfo ); |
66 | setOverride( "new", modeStreamNew ); | 66 | setOverride( "new", modeStreamNew ); |
67 | setOverride( "dump", modeStreamDump ); | 67 | setOverride( "dump", modeStreamDump ); |
68 | setOverride( "put", modeStreamPut ); | 68 | setOverride( "put", modeStreamPut ); |
69 | setOverride( "get", modeStreamGet ); | 69 | setOverride( "get", modeStreamGet ); |
70 | 70 | ||
71 | parse( argc, argv ); | 71 | parse( argc, argv ); |
72 | } | 72 | } |
73 | 73 | ||
74 | Mode eMode; | 74 | Mode eMode; |
75 | int iBlockSize; | 75 | int iBlockSize; |
76 | int iPreallocate; | 76 | int iPreallocate; |
77 | int iStream; | 77 | int iStream; |
78 | Bu::String sFile; | 78 | Bu::String sFile; |
79 | Bu::String sSrc; | 79 | Bu::String sSrc; |
80 | Bu::String sDst; | 80 | Bu::String sDst; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | Bu::Formatter &operator>>( Bu::Formatter &f, Mode & /*e*/ ) | 83 | Bu::Formatter &operator>>( Bu::Formatter &f, Mode & /*e*/ ) |
84 | { | 84 | { |
85 | sio << "Uh oh, the formatter was called..." << sio.nl; | 85 | sio << "Uh oh, the formatter was called..." << sio.nl; |
86 | return f; | 86 | return f; |
87 | } | 87 | } |
88 | 88 | ||
89 | int main( int argc, char *argv[] ) | 89 | int main( int argc, char *argv[] ) |
90 | { | 90 | { |
91 | Options opts( argc, argv ); | 91 | Options opts( argc, argv ); |
92 | 92 | ||
93 | switch( opts.eMode ) | 93 | switch( opts.eMode ) |
94 | { | 94 | { |
95 | case modeCreate: | 95 | case modeCreate: |
96 | if( !opts.sFile.isSet() ) | 96 | if( !opts.sFile.isSet() ) |
97 | { | 97 | { |
98 | sio << "Please specify a file to create." << sio.nl; | 98 | sio << "Please specify a file to create." << sio.nl; |
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | else | 101 | else |
102 | { | 102 | { |
103 | File fOut( opts.sFile, File::WriteNew|File::Read ); | 103 | File fOut( opts.sFile, File::WriteNew|File::Read ); |
104 | Myriad m( fOut, opts.iBlockSize, opts.iPreallocate ); | 104 | Myriad m( fOut, opts.iBlockSize, opts.iPreallocate ); |
105 | } | 105 | } |
106 | break; | 106 | break; |
107 | 107 | ||
108 | case modeInfo: | 108 | case modeInfo: |
109 | if( !opts.sFile.isSet() ) | 109 | if( !opts.sFile.isSet() ) |
110 | { | 110 | { |
111 | sio << "Please specify a file to display info about." << sio.nl; | 111 | sio << "Please specify a file to display info about." << sio.nl; |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | else | 114 | else |
115 | { | 115 | { |
116 | File fIn( opts.sFile, File::Read ); | 116 | File fIn( opts.sFile, File::Read ); |
117 | Myriad m( fIn ); | 117 | Myriad m( fIn ); |
118 | sio << "Myriad info:" << sio.nl | 118 | sio << "Myriad info:" << sio.nl |
119 | << " Block size: " << m.getBlockSize() << sio.nl | 119 | << " Block size: " << m.getBlockSize() << sio.nl |
120 | << " Block count: " << m.getNumBlocks() << sio.nl | 120 | << " Block count: " << m.getNumBlocks() << sio.nl |
121 | << " Blocks used: " << m.getNumUsedBlocks() << " (" | 121 | << " Blocks used: " << m.getNumUsedBlocks() << " (" |
122 | << m.getNumUsedBlocks()*100/m.getNumBlocks() << "%)" | 122 | << m.getNumUsedBlocks()*100/m.getNumBlocks() << "%)" |
123 | << sio.nl | 123 | << sio.nl |
124 | << " Stream count: " << m.getNumStreams() << sio.nl | 124 | << " Stream count: " << m.getNumStreams() << sio.nl |
125 | << " Used space: " << m.getTotalUsedBytes() << sio.nl | 125 | << " Used space: " << m.getTotalUsedBytes() << sio.nl |
126 | << " Unused space: " << m.getTotalUnusedBytes() << sio.nl | 126 | << " Unused space: " << m.getTotalUnusedBytes() << sio.nl |
127 | << " % of files: " << (double)(m.getNumBlocks()*m.getBlockSize())/(double)(m.getTotalUsedBytes() + m.getTotalUnusedBytes( 4096 ))*100.0 << sio.nl; | 127 | << " % of files: " << (double)(m.getNumBlocks()*m.getBlockSize())/(double)(m.getTotalUsedBytes() + m.getTotalUnusedBytes( 4096 ))*100.0 << sio.nl; |
128 | /* Bu::Array<int> aStreams = m.getStreamIds(); | 128 | /* Bu::Array<int> aStreams = m.getStreamIds(); |
129 | sio << " Stream info:" << sio.nl; | 129 | sio << " Stream info:" << sio.nl; |
130 | for( Bu::Array<int>::iterator i = aStreams.begin(); i; i++ ) | 130 | for( Bu::Array<int>::iterator i = aStreams.begin(); i; i++ ) |
131 | { | 131 | { |
132 | sio << " " << Fmt(4) << *i << ") " | 132 | sio << " " << Fmt(4) << *i << ") " |
133 | << m.getStreamSize( *i ) << "b" << sio.nl; | 133 | << m.getStreamSize( *i ) << "b" << sio.nl; |
134 | } */ | 134 | } */ |
135 | } | 135 | } |
136 | break; | 136 | break; |
137 | 137 | ||
138 | case modeStreamNew: | 138 | case modeStreamNew: |
139 | if( !opts.sFile.isSet() ) | 139 | if( !opts.sFile.isSet() ) |
140 | { | 140 | { |
141 | sio << "Please specify a file manipulate." << sio.nl; | 141 | sio << "Please specify a file manipulate." << sio.nl; |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | else | 144 | else |
145 | { | 145 | { |
146 | File fOut( opts.sFile, File::Write|File::Read ); | 146 | File fOut( opts.sFile, File::Write|File::Read ); |
147 | Myriad m( fOut ); | 147 | Myriad m( fOut ); |
148 | m.createStream( opts.iPreallocate ); | 148 | m.createStream( opts.iPreallocate ); |
149 | } | 149 | } |
150 | break; | 150 | break; |
151 | 151 | ||
152 | case modeStreamDump: | 152 | case modeStreamDump: |
153 | if( !opts.sFile.isSet() ) | 153 | if( !opts.sFile.isSet() ) |
154 | { | 154 | { |
155 | sio << "Please specify a file to manipulate." << sio.nl; | 155 | sio << "Please specify a file to manipulate." << sio.nl; |
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | else | 158 | else |
159 | { | 159 | { |
160 | File fOut( opts.sFile, File::Read ); | 160 | File fOut( opts.sFile, File::Read ); |
161 | Myriad m( fOut ); | 161 | Myriad m( fOut ); |
162 | MyriadStream s = m.openStream( opts.iStream ); | 162 | MyriadStream s = m.openStream( opts.iStream ); |
163 | sio << "Stream " << opts.iStream << ":" << sio.nl; | 163 | sio << "Stream " << opts.iStream << ":" << sio.nl; |
164 | char buf[8]; | 164 | char buf[8]; |
165 | int iPos = 0; | 165 | int iPos = 0; |
166 | while( !s.isEos() ) | 166 | while( !s.isEos() ) |
167 | { | 167 | { |
168 | size_t sAmnt = s.read( buf, 8 ); | 168 | size_t sAmnt = s.read( buf, 8 ); |
169 | sio << Fmt(5) << iPos << ": "; | 169 | sio << Fmt(5) << iPos << ": "; |
170 | iPos += sAmnt; | 170 | iPos += sAmnt; |
171 | for( size_t j = 0; j < sAmnt; j++ ) | 171 | for( size_t j = 0; j < sAmnt; j++ ) |
172 | { | 172 | { |
173 | sio << Fmt::hex(2) << (int)((unsigned char)buf[j]) | 173 | sio << Fmt::hex(2) << (int)((unsigned char)buf[j]) |
174 | << " "; | 174 | << " "; |
175 | } | 175 | } |
176 | for( size_t j = sAmnt; j < 8; j++ ) | 176 | for( size_t j = sAmnt; j < 8; j++ ) |
177 | { | 177 | { |
178 | sio << "-- "; | 178 | sio << "-- "; |
179 | } | 179 | } |
180 | sio << "| "; | 180 | sio << "| "; |
181 | for( size_t j = 0; j < sAmnt; j++ ) | 181 | for( size_t j = 0; j < sAmnt; j++ ) |
182 | { | 182 | { |
183 | if( buf[j] >= 32 && buf[j] <= 126 ) | 183 | if( buf[j] >= 32 && buf[j] <= 126 ) |
184 | sio << buf[j] << " "; | 184 | sio << buf[j] << " "; |
185 | else | 185 | else |
186 | sio << " "; | 186 | sio << " "; |
187 | } | 187 | } |
188 | sio << sio.nl; | 188 | sio << sio.nl; |
189 | } | 189 | } |
190 | sio << "Position: " << s.tell() << ", isEos()=" << s.isEos() | 190 | sio << "Position: " << s.tell() << ", isEos()=" << s.isEos() |
191 | << sio.nl; | 191 | << sio.nl; |
192 | } | 192 | } |
193 | break; | 193 | break; |
194 | 194 | ||
195 | case modeStreamPut: | 195 | case modeStreamPut: |
196 | if( !opts.sFile.isSet() ) | 196 | if( !opts.sFile.isSet() ) |
197 | { | 197 | { |
198 | sio << "Please specify a file manipulate." << sio.nl; | 198 | sio << "Please specify a file manipulate." << sio.nl; |
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | else if( !opts.sSrc.isSet() ) | 201 | else if( !opts.sSrc.isSet() ) |
202 | { | 202 | { |
203 | sio << "Please specify a source file to read." << sio.nl; | 203 | sio << "Please specify a source file to read." << sio.nl; |
204 | } | 204 | } |
205 | else | 205 | else |
206 | { | 206 | { |
207 | File fOut( opts.sFile, File::Write|File::Read ); | 207 | File fOut( opts.sFile, File::Write|File::Read ); |
208 | Myriad m( fOut ); | 208 | Myriad m( fOut ); |
209 | MyriadStream sOut = m.openStream( | 209 | MyriadStream sOut = m.openStream( |
210 | m.createStream( opts.iPreallocate ) | 210 | m.createStream( opts.iPreallocate ) |
211 | ); | 211 | ); |
212 | File fIn( opts.sSrc, File::Read ); | 212 | File fIn( opts.sSrc, File::Read ); |
213 | char buf[1024]; | 213 | char buf[1024]; |
214 | while( !fIn.isEos() ) | 214 | while( !fIn.isEos() ) |
215 | { | 215 | { |
216 | sOut.write( buf, fIn.read( buf, 1024 ) ); | 216 | sOut.write( buf, fIn.read( buf, 1024 ) ); |
217 | } | 217 | } |
218 | } | 218 | } |
219 | break; | 219 | break; |
220 | 220 | ||
221 | case modeStreamGet: | 221 | case modeStreamGet: |
222 | if( !opts.sFile.isSet() ) | 222 | if( !opts.sFile.isSet() ) |
223 | { | 223 | { |
224 | sio << "Please specify a file manipulate." << sio.nl; | 224 | sio << "Please specify a file manipulate." << sio.nl; |
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | else if( !opts.sDst.isSet() ) | 227 | else if( !opts.sDst.isSet() ) |
228 | { | 228 | { |
229 | sio << "Please specify a destination file to write." << sio.nl; | 229 | sio << "Please specify a destination file to write." << sio.nl; |
230 | } | 230 | } |
231 | else | 231 | else |
232 | { | 232 | { |
233 | File fIn( opts.sFile, File::Write|File::Read ); | 233 | File fIn( opts.sFile, File::Write|File::Read ); |
234 | Myriad m( fIn ); | 234 | Myriad m( fIn ); |
235 | MyriadStream sIn = m.openStream( opts.iStream ); | 235 | MyriadStream sIn = m.openStream( opts.iStream ); |
236 | File fOut( opts.sDst, File::Write|File::Create|File::Truncate ); | 236 | File fOut( opts.sDst, File::Write|File::Create|File::Truncate ); |
237 | char buf[1024]; | 237 | char buf[1024]; |
238 | while( !sIn.isEos() ) | 238 | while( !sIn.isEos() ) |
239 | { | 239 | { |
240 | fOut.write( buf, sIn.read( buf, 1024 ) ); | 240 | fOut.write( buf, sIn.read( buf, 1024 ) ); |
241 | } | 241 | } |
242 | } | 242 | } |
243 | break; | 243 | break; |
244 | 244 | ||
245 | case modeNone: | 245 | case modeNone: |
246 | sio << "Please select a mode, for more info, try --help." | 246 | sio << "Please select a mode, for more info, try --help." |
247 | << sio.nl << sio.nl; | 247 | << sio.nl << sio.nl; |
248 | break; | 248 | break; |
249 | } | 249 | } |
250 | 250 | ||
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
diff --git a/src/tools/viewcsv.cpp b/src/tools/viewcsv.cpp index 5009ea8..328cafc 100644 --- a/src/tools/viewcsv.cpp +++ b/src/tools/viewcsv.cpp | |||
@@ -20,33 +20,33 @@ using namespace Bu; | |||
20 | class Options : public Bu::OptParser | 20 | class Options : public Bu::OptParser |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | Options( int argc, char *argv[] ) : | 23 | Options( int argc, char *argv[] ) : |
24 | bHeader( true ) | 24 | bHeader( true ) |
25 | { | 25 | { |
26 | addOption( bHeader, "no-header", | 26 | addOption( bHeader, "no-header", |
27 | "Don't use the first line as a header row. This behaviour can " | 27 | "Don't use the first line as a header row. This behaviour can " |
28 | "also be toggled while running with 'h'." ); | 28 | "also be toggled while running with 'h'." ); |
29 | setNonOption( slot( this, &Options::onNonOption ) ); | 29 | setNonOption( slot( this, &Options::onNonOption ) ); |
30 | addHelpOption(); | 30 | addHelpOption(); |
31 | 31 | ||
32 | setOverride( "no-header", "true" ); | 32 | setOverride( "no-header", "true" ); |
33 | parse( argc, argv ); | 33 | parse( argc, argv ); |
34 | } | 34 | } |
35 | 35 | ||
36 | virtual ~Options() | 36 | virtual ~Options() |
37 | { | 37 | { |
38 | } | 38 | } |
39 | 39 | ||
40 | int onNonOption( StrArray aParams ) | 40 | int onNonOption( StrArray aParams ) |
41 | { | 41 | { |
42 | //sio << aParams << sio.nl; | 42 | //sio << aParams << sio.nl; |
43 | sFileIn = aParams[0]; | 43 | sFileIn = aParams[0]; |
44 | 44 | ||
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | Bu::String sFileIn; | 48 | Bu::String sFileIn; |
49 | bool bHeader; | 49 | bool bHeader; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | typedef Bu::Array<StrArray> StrGrid; | 52 | typedef Bu::Array<StrArray> StrGrid; |
@@ -54,421 +54,421 @@ typedef Bu::Array<int> IntArray; | |||
54 | class CsvDoc | 54 | class CsvDoc |
55 | { | 55 | { |
56 | public: | 56 | public: |
57 | CsvDoc() : | 57 | CsvDoc() : |
58 | iMaxCols( 0 ) | 58 | iMaxCols( 0 ) |
59 | { | 59 | { |
60 | } | 60 | } |
61 | 61 | ||
62 | virtual ~CsvDoc() | 62 | virtual ~CsvDoc() |
63 | { | 63 | { |
64 | } | 64 | } |
65 | 65 | ||
66 | void addRow( StrArray aStr ) | 66 | void addRow( StrArray aStr ) |
67 | { | 67 | { |
68 | sgData.append( aStr ); | 68 | sgData.append( aStr ); |
69 | if( iMaxCols < aStr.getSize() ) | 69 | if( iMaxCols < aStr.getSize() ) |
70 | iMaxCols = aStr.getSize(); | 70 | iMaxCols = aStr.getSize(); |
71 | while( aWidths.getSize() < iMaxCols ) | 71 | while( aWidths.getSize() < iMaxCols ) |
72 | { | 72 | { |
73 | aWidths.append( 0 ); | 73 | aWidths.append( 0 ); |
74 | } | 74 | } |
75 | for( int j = 0; j < aStr.getSize(); j++ ) | 75 | for( int j = 0; j < aStr.getSize(); j++ ) |
76 | { | 76 | { |
77 | if( aWidths[j] < aStr[j].getSize() ) | 77 | if( aWidths[j] < aStr[j].getSize() ) |
78 | aWidths[j] = aStr[j].getSize(); | 78 | aWidths[j] = aStr[j].getSize(); |
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | int iMaxCols; | 82 | int iMaxCols; |
83 | StrGrid sgData; | 83 | StrGrid sgData; |
84 | IntArray aWidths; | 84 | IntArray aWidths; |
85 | }; | 85 | }; |
86 | 86 | ||
87 | class CsvView | 87 | class CsvView |
88 | { | 88 | { |
89 | public: | 89 | public: |
90 | CsvView( CsvDoc &doc ) : | 90 | CsvView( CsvDoc &doc ) : |
91 | doc( doc ), | 91 | doc( doc ), |
92 | iXOff( 0 ), | 92 | iXOff( 0 ), |
93 | iYOff( 0 ), | 93 | iYOff( 0 ), |
94 | bHeaderRow( false ) | 94 | bHeaderRow( false ) |
95 | { | 95 | { |
96 | } | 96 | } |
97 | 97 | ||
98 | virtual ~CsvView() | 98 | virtual ~CsvView() |
99 | { | 99 | { |
100 | } | 100 | } |
101 | 101 | ||
102 | void render() | 102 | void render() |
103 | { | 103 | { |
104 | erase(); | 104 | erase(); |
105 | int maxx, maxy; | 105 | int maxx, maxy; |
106 | getmaxyx( stdscr, maxy, maxx ); | 106 | getmaxyx( stdscr, maxy, maxx ); |
107 | 107 | ||
108 | int iRows = buMin( (int)doc.sgData.getSize(), maxy-((bHeaderRow)?(4):(3)) ); | 108 | int iRows = buMin( (int)doc.sgData.getSize(), maxy-((bHeaderRow)?(4):(3)) ); |
109 | int iCols = buMin( doc.iMaxCols, (int)maxx-1 ); | 109 | int iCols = buMin( doc.iMaxCols, (int)maxx-1 ); |
110 | 110 | ||
111 | int iHdrHeight = 1; | 111 | int iHdrHeight = 1; |
112 | if( bHeaderRow ) | 112 | if( bHeaderRow ) |
113 | iHdrHeight++; | 113 | iHdrHeight++; |
114 | 114 | ||
115 | // Draw the headers | 115 | // Draw the headers |
116 | for( int iRow = 0; iRow < iRows; iRow++ ) | 116 | for( int iRow = 0; iRow < iRows; iRow++ ) |
117 | { | 117 | { |
118 | if( iRow+iYOff >= doc.sgData.getSize() ) | 118 | if( iRow+iYOff >= doc.sgData.getSize() ) |
119 | break; | 119 | break; |
120 | char buf[6]; | 120 | char buf[6]; |
121 | snprintf( buf, 6, "%5d", iRow+iYOff ); | 121 | snprintf( buf, 6, "%5d", iRow+iYOff ); |
122 | mvaddnstr( iRow+iHdrHeight+1, 0, buf, 5 ); | 122 | mvaddnstr( iRow+iHdrHeight+1, 0, buf, 5 ); |
123 | mvaddch( iRow+iHdrHeight+1, 6, ACS_VLINE ); | 123 | mvaddch( iRow+iHdrHeight+1, 6, ACS_VLINE ); |
124 | } | 124 | } |
125 | int iXPos = 6; | 125 | int iXPos = 6; |
126 | try | 126 | try |
127 | { | 127 | { |
128 | for( int iCol = 0; iCol < iCols; iCol++ ) | 128 | for( int iCol = 0; iCol < iCols; iCol++ ) |
129 | { | 129 | { |
130 | if( iXPos >= maxx ) | 130 | if( iXPos >= maxx ) |
131 | break; | 131 | break; |
132 | int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); | 132 | int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); |
133 | char buf[6]; | 133 | char buf[6]; |
134 | snprintf( buf, 6, "%d", iCol+iXOff ); | 134 | snprintf( buf, 6, "%d", iCol+iXOff ); |
135 | mvaddch( 0, iXPos, ACS_VLINE ); | 135 | mvaddch( 0, iXPos, ACS_VLINE ); |
136 | mvaddch( iHdrHeight, iXPos, ACS_PLUS ); | 136 | mvaddch( iHdrHeight, iXPos, ACS_PLUS ); |
137 | mvaddnstr( 0, iXPos+1, buf, 5 ); | 137 | mvaddnstr( 0, iXPos+1, buf, 5 ); |
138 | if( bHeaderRow ) | 138 | if( bHeaderRow ) |
139 | { | 139 | { |
140 | mvaddnstr( | 140 | mvaddnstr( |
141 | 1, iXPos+1, doc.sgData[0][iCol+iXOff].getStr(), iWidth | 141 | 1, iXPos+1, doc.sgData[0][iCol+iXOff].getStr(), iWidth |
142 | ); | 142 | ); |
143 | mvaddch( 1, iXPos, ACS_VLINE ); | 143 | mvaddch( 1, iXPos, ACS_VLINE ); |
144 | } | 144 | } |
145 | for( int j = 0; j < iWidth; j++ ) | 145 | for( int j = 0; j < iWidth; j++ ) |
146 | { | 146 | { |
147 | mvaddch( iHdrHeight, iXPos+j+1, ACS_HLINE ); | 147 | mvaddch( iHdrHeight, iXPos+j+1, ACS_HLINE ); |
148 | } | 148 | } |
149 | iXPos += iWidth+1; | 149 | iXPos += iWidth+1; |
150 | } | 150 | } |
151 | } | 151 | } |
152 | catch(...) { } | 152 | catch(...) { } |
153 | for( int j = 0; j < 6; j++ ) | 153 | for( int j = 0; j < 6; j++ ) |
154 | { | 154 | { |
155 | mvaddch( iHdrHeight, j, ACS_HLINE ); | 155 | mvaddch( iHdrHeight, j, ACS_HLINE ); |
156 | } | 156 | } |
157 | 157 | ||
158 | // Draw some data | 158 | // Draw some data |
159 | for( int iRow = 0; iRow < iRows; iRow++ ) | 159 | for( int iRow = 0; iRow < iRows; iRow++ ) |
160 | { | 160 | { |
161 | try | 161 | try |
162 | { | 162 | { |
163 | int iXPos = 6; | 163 | int iXPos = 6; |
164 | for( int iCol = 0; iCol < iCols; iCol++ ) | 164 | for( int iCol = 0; iCol < iCols; iCol++ ) |
165 | { | 165 | { |
166 | if( iXPos >= maxx ) | 166 | if( iXPos >= maxx ) |
167 | break; | 167 | break; |
168 | int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); | 168 | int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); |
169 | mvaddch( iRow+iHdrHeight+1, iXPos, ACS_VLINE ); | 169 | mvaddch( iRow+iHdrHeight+1, iXPos, ACS_VLINE ); |
170 | mvaddnstr( iRow+iHdrHeight+1, iXPos+1, | 170 | mvaddnstr( iRow+iHdrHeight+1, iXPos+1, |
171 | doc.sgData[iRow+iYOff][iCol+iXOff].getStr(), iWidth ); | 171 | doc.sgData[iRow+iYOff][iCol+iXOff].getStr(), iWidth ); |
172 | iXPos += iWidth+1; | 172 | iXPos += iWidth+1; |
173 | } | 173 | } |
174 | } catch(...) { } | 174 | } catch(...) { } |
175 | } | 175 | } |
176 | 176 | ||
177 | attron( A_REVERSE ); | 177 | attron( A_REVERSE ); |
178 | for( int j = 0; j < maxx; j++ ) | 178 | for( int j = 0; j < maxx; j++ ) |
179 | { | 179 | { |
180 | mvaddch( maxy-1, j, ' ' ); | 180 | mvaddch( maxy-1, j, ' ' ); |
181 | } | 181 | } |
182 | mvaddstr( maxy-1, 1, "q) quit h) toggle header row" ); | 182 | mvaddstr( maxy-1, 1, "q) quit h) toggle header row" ); |
183 | char buf[30]; | 183 | char buf[30]; |
184 | int iWidth = sprintf( buf, "[%dx%ld]", | 184 | int iWidth = sprintf( buf, "[%dx%ld]", |
185 | doc.iMaxCols, doc.sgData.getSize() | 185 | doc.iMaxCols, doc.sgData.getSize() |
186 | ); | 186 | ); |
187 | mvaddstr( maxy-1, maxx-iWidth-1, buf ); | 187 | mvaddstr( maxy-1, maxx-iWidth-1, buf ); |
188 | attroff( A_REVERSE ); | 188 | attroff( A_REVERSE ); |
189 | } | 189 | } |
190 | 190 | ||
191 | void move( int iX, int iY ) | 191 | void move( int iX, int iY ) |
192 | { | 192 | { |
193 | iXOff += iX; | 193 | iXOff += iX; |
194 | iYOff += iY; | 194 | iYOff += iY; |
195 | if( iXOff < 0 ) | 195 | if( iXOff < 0 ) |
196 | iXOff = 0; | 196 | iXOff = 0; |
197 | 197 | ||
198 | if( bHeaderRow ) | 198 | if( bHeaderRow ) |
199 | { | 199 | { |
200 | if( iYOff < 1 ) | 200 | if( iYOff < 1 ) |
201 | iYOff = 1; | 201 | iYOff = 1; |
202 | } | 202 | } |
203 | else | 203 | else |
204 | { | 204 | { |
205 | if( iYOff < 0 ) | 205 | if( iYOff < 0 ) |
206 | iYOff = 0; | 206 | iYOff = 0; |
207 | } | 207 | } |
208 | 208 | ||
209 | if( iYOff >= doc.sgData.getSize() ) | 209 | if( iYOff >= doc.sgData.getSize() ) |
210 | iYOff = doc.sgData.getSize()-1; | 210 | iYOff = doc.sgData.getSize()-1; |
211 | 211 | ||
212 | if( iXOff >= doc.iMaxCols ) | 212 | if( iXOff >= doc.iMaxCols ) |
213 | iXOff = doc.iMaxCols-1; | 213 | iXOff = doc.iMaxCols-1; |
214 | } | 214 | } |
215 | 215 | ||
216 | void pageDown() | 216 | void pageDown() |
217 | { | 217 | { |
218 | int maxx, maxy; | 218 | int maxx, maxy; |
219 | getmaxyx( stdscr, maxy, maxx ); | 219 | getmaxyx( stdscr, maxy, maxx ); |
220 | move( 0, maxy-((bHeaderRow)?(4):(3)) ); | 220 | move( 0, maxy-((bHeaderRow)?(4):(3)) ); |
221 | } | 221 | } |
222 | 222 | ||
223 | void pageUp() | 223 | void pageUp() |
224 | { | 224 | { |
225 | int maxx, maxy; | 225 | int maxx, maxy; |
226 | getmaxyx( stdscr, maxy, maxx ); | 226 | getmaxyx( stdscr, maxy, maxx ); |
227 | move( 0, -(maxy-((bHeaderRow)?(4):(3))) ); | 227 | move( 0, -(maxy-((bHeaderRow)?(4):(3))) ); |
228 | } | 228 | } |
229 | 229 | ||
230 | void home() | 230 | void home() |
231 | { | 231 | { |
232 | iYOff = 0; | 232 | iYOff = 0; |
233 | if( bHeaderRow ) iYOff++; | 233 | if( bHeaderRow ) iYOff++; |
234 | } | 234 | } |
235 | 235 | ||
236 | void end() | 236 | void end() |
237 | { | 237 | { |
238 | iYOff = doc.sgData.getSize()-1; | 238 | iYOff = doc.sgData.getSize()-1; |
239 | } | 239 | } |
240 | 240 | ||
241 | void setHeaderRow( bool bOn ) | 241 | void setHeaderRow( bool bOn ) |
242 | { | 242 | { |
243 | if( bHeaderRow == bOn ) | 243 | if( bHeaderRow == bOn ) |
244 | return; | 244 | return; |
245 | 245 | ||
246 | bHeaderRow = bOn; | 246 | bHeaderRow = bOn; |
247 | move( 0, ((bOn)?(1):(-1)) ); | 247 | move( 0, ((bOn)?(1):(-1)) ); |
248 | } | 248 | } |
249 | 249 | ||
250 | void toggleHeaderRow() | 250 | void toggleHeaderRow() |
251 | { | 251 | { |
252 | setHeaderRow( !bHeaderRow ); | 252 | setHeaderRow( !bHeaderRow ); |
253 | } | 253 | } |
254 | 254 | ||
255 | Bu::String prompt( const Bu::String &sPrompt ) | 255 | Bu::String prompt( const Bu::String &sPrompt ) |
256 | { | 256 | { |
257 | int maxx, maxy; | 257 | int maxx, maxy; |
258 | Bu::String sStr; | 258 | Bu::String sStr; |
259 | 259 | ||
260 | RegEx re( sPrompt ); | 260 | RegEx re( sPrompt ); |
261 | 261 | ||
262 | curs_set( 1 ); | 262 | curs_set( 1 ); |
263 | for(;;) | 263 | for(;;) |
264 | { | 264 | { |
265 | getmaxyx( stdscr, maxy, maxx ); | 265 | getmaxyx( stdscr, maxy, maxx ); |
266 | for( int j = 0; j < maxx; j++ ) | 266 | for( int j = 0; j < maxx; j++ ) |
267 | { | 267 | { |
268 | mvaddch( maxy-1, j, ' ' ); | 268 | mvaddch( maxy-1, j, ' ' ); |
269 | } | 269 | } |
270 | mvaddstr( maxy-1, 0, sPrompt.getStr() ); | 270 | mvaddstr( maxy-1, 0, sPrompt.getStr() ); |
271 | 271 | ||
272 | mvaddstr( maxy-1, sPrompt.getSize(), sStr.getStr() ); | 272 | mvaddstr( maxy-1, sPrompt.getSize(), sStr.getStr() ); |
273 | 273 | ||
274 | int iCh = getch(); | 274 | int iCh = getch(); |
275 | switch( iCh ) | 275 | switch( iCh ) |
276 | { | 276 | { |
277 | case '\n': | 277 | case '\n': |
278 | case '\r': | 278 | case '\r': |
279 | case KEY_ENTER: | 279 | case KEY_ENTER: |
280 | curs_set( 0 ); | 280 | curs_set( 0 ); |
281 | return sStr; | 281 | return sStr; |
282 | break; | 282 | break; |
283 | 283 | ||
284 | case KEY_BACKSPACE: | 284 | case KEY_BACKSPACE: |
285 | if( sStr.getSize() > 0 ) | 285 | if( sStr.getSize() > 0 ) |
286 | sStr.resize( sStr.getSize()-1 ); | 286 | sStr.resize( sStr.getSize()-1 ); |
287 | break; | 287 | break; |
288 | 288 | ||
289 | default: | 289 | default: |
290 | if( iCh < 127 ) | 290 | if( iCh < 127 ) |
291 | sStr += (char)iCh; | 291 | sStr += (char)iCh; |
292 | break; | 292 | break; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
297 | void resetCaret() | 297 | void resetCaret() |
298 | { | 298 | { |
299 | sysCaret.reset(); | 299 | sysCaret.reset(); |
300 | } | 300 | } |
301 | 301 | ||
302 | void findNext( const Bu::String &sTerm ) | 302 | void findNext( const Bu::String &sTerm ) |
303 | { | 303 | { |
304 | RegEx re( sTerm ); | 304 | RegEx re( sTerm ); |
305 | 305 | ||
306 | int y = sysCaret.iRow; | 306 | int y = sysCaret.iRow; |
307 | if( y < 0 ) | 307 | if( y < 0 ) |
308 | y = 0; | 308 | y = 0; |
309 | int x = sysCaret.iCol+1; | 309 | int x = sysCaret.iCol+1; |
310 | for( ; y < doc.sgData.getSize(); y++ ) | 310 | for( ; y < doc.sgData.getSize(); y++ ) |
311 | { | 311 | { |
312 | StrArray &aRow = doc.sgData[y]; | 312 | StrArray &aRow = doc.sgData[y]; |
313 | for( ; x < aRow.getSize(); x++ ) | 313 | for( ; x < aRow.getSize(); x++ ) |
314 | { | 314 | { |
315 | if( re.execute( aRow[x] ) ) //aRow[x].find( sTerm ) ) | 315 | if( re.execute( aRow[x] ) ) //aRow[x].find( sTerm ) ) |
316 | { | 316 | { |
317 | sysCaret.iRow = y; | 317 | sysCaret.iRow = y; |
318 | sysCaret.iCol = x; | 318 | sysCaret.iCol = x; |
319 | scrollToCaret(); | 319 | scrollToCaret(); |
320 | return; | 320 | return; |
321 | } | 321 | } |
322 | } | 322 | } |
323 | x = 0; | 323 | x = 0; |
324 | } | 324 | } |
325 | } | 325 | } |
326 | 326 | ||
327 | void scrollToCaret() | 327 | void scrollToCaret() |
328 | { | 328 | { |
329 | iXOff = sysCaret.iCol; | 329 | iXOff = sysCaret.iCol; |
330 | iYOff = sysCaret.iRow; | 330 | iYOff = sysCaret.iRow; |
331 | } | 331 | } |
332 | 332 | ||
333 | CsvDoc &doc; | 333 | CsvDoc &doc; |
334 | int iXOff; | 334 | int iXOff; |
335 | int iYOff; | 335 | int iYOff; |
336 | bool bHeaderRow; | 336 | bool bHeaderRow; |
337 | 337 | ||
338 | class Caret | 338 | class Caret |
339 | { | 339 | { |
340 | public: | 340 | public: |
341 | Caret() : | 341 | Caret() : |
342 | iRow( -1 ), | 342 | iRow( -1 ), |
343 | iCol( -1 ) | 343 | iCol( -1 ) |
344 | { | 344 | { |
345 | } | 345 | } |
346 | 346 | ||
347 | virtual ~Caret() | 347 | virtual ~Caret() |
348 | { | 348 | { |
349 | } | 349 | } |
350 | 350 | ||
351 | 351 | ||
352 | void reset() | 352 | void reset() |
353 | { | 353 | { |
354 | iRow = iCol = -1; | 354 | iRow = iCol = -1; |
355 | } | 355 | } |
356 | 356 | ||
357 | bool isSet() | 357 | bool isSet() |
358 | { | 358 | { |
359 | if( iRow < 0 || iCol < 0 ) | 359 | if( iRow < 0 || iCol < 0 ) |
360 | return false; | 360 | return false; |
361 | return true; | 361 | return true; |
362 | } | 362 | } |
363 | 363 | ||
364 | int iRow; | 364 | int iRow; |
365 | int iCol; | 365 | int iCol; |
366 | }; | 366 | }; |
367 | 367 | ||
368 | Caret sysCaret; | 368 | Caret sysCaret; |
369 | }; | 369 | }; |
370 | 370 | ||
371 | int main( int argc, char *argv[] ) | 371 | int main( int argc, char *argv[] ) |
372 | { | 372 | { |
373 | Options opt( argc, argv ); | 373 | Options opt( argc, argv ); |
374 | 374 | ||
375 | if( !opt.sFileIn.isSet() ) | 375 | if( !opt.sFileIn.isSet() ) |
376 | { | 376 | { |
377 | sio << "No file specified." << sio.nl; | 377 | sio << "No file specified." << sio.nl; |
378 | return 1; | 378 | return 1; |
379 | } | 379 | } |
380 | 380 | ||
381 | CsvDoc doc; | 381 | CsvDoc doc; |
382 | { | 382 | { |
383 | File fIn( opt.sFileIn, File::Read ); | 383 | File fIn( opt.sFileIn, File::Read ); |
384 | NewLine nlIn( fIn ); | 384 | NewLine nlIn( fIn ); |
385 | Buffer bIn( nlIn ); | 385 | Buffer bIn( nlIn ); |
386 | CsvReader cr( bIn ); | 386 | CsvReader cr( bIn ); |
387 | 387 | ||
388 | while( !fIn.isEos() ) | 388 | while( !fIn.isEos() ) |
389 | { | 389 | { |
390 | StrArray sa = cr.readLine(); | 390 | StrArray sa = cr.readLine(); |
391 | if( fIn.isEos() ) | 391 | if( fIn.isEos() ) |
392 | break; | 392 | break; |
393 | doc.addRow( sa ); | 393 | doc.addRow( sa ); |
394 | } | 394 | } |
395 | } | 395 | } |
396 | 396 | ||
397 | initscr(); | 397 | initscr(); |
398 | cbreak(); | 398 | cbreak(); |
399 | noecho(); | 399 | noecho(); |
400 | nonl(); | 400 | nonl(); |
401 | intrflush( stdscr, FALSE ); | 401 | intrflush( stdscr, FALSE ); |
402 | keypad( stdscr, TRUE ); | 402 | keypad( stdscr, TRUE ); |
403 | curs_set( 0 ); | 403 | curs_set( 0 ); |
404 | 404 | ||
405 | CsvView view( doc ); | 405 | CsvView view( doc ); |
406 | view.setHeaderRow( opt.bHeader ); | 406 | view.setHeaderRow( opt.bHeader ); |
407 | 407 | ||
408 | Bu::String sSearchTerm; | 408 | Bu::String sSearchTerm; |
409 | 409 | ||
410 | bool bRun = true; | 410 | bool bRun = true; |
411 | do | 411 | do |
412 | { | 412 | { |
413 | view.render(); | 413 | view.render(); |
414 | 414 | ||
415 | int ch = getch(); | 415 | int ch = getch(); |
416 | switch( ch ) | 416 | switch( ch ) |
417 | { | 417 | { |
418 | case 'q': | 418 | case 'q': |
419 | bRun = false; | 419 | bRun = false; |
420 | break; | 420 | break; |
421 | 421 | ||
422 | case KEY_DOWN: | 422 | case KEY_DOWN: |
423 | view.move( 0, 1 ); | 423 | view.move( 0, 1 ); |
424 | break; | 424 | break; |
425 | 425 | ||
426 | case KEY_UP: | 426 | case KEY_UP: |
427 | view.move( 0, -1 ); | 427 | view.move( 0, -1 ); |
428 | break; | 428 | break; |
429 | 429 | ||
430 | case KEY_LEFT: | 430 | case KEY_LEFT: |
431 | view.move( -1, 0 ); | 431 | view.move( -1, 0 ); |
432 | break; | 432 | break; |
433 | 433 | ||
434 | case KEY_RIGHT: | 434 | case KEY_RIGHT: |
435 | view.move( 1, 0 ); | 435 | view.move( 1, 0 ); |
436 | break; | 436 | break; |
437 | 437 | ||
438 | case KEY_NPAGE: | 438 | case KEY_NPAGE: |
439 | view.pageDown(); | 439 | view.pageDown(); |
440 | break; | 440 | break; |
441 | 441 | ||
442 | case KEY_PPAGE: | 442 | case KEY_PPAGE: |
443 | view.pageUp(); | 443 | view.pageUp(); |
444 | break; | 444 | break; |
445 | 445 | ||
446 | case KEY_HOME: | 446 | case KEY_HOME: |
447 | view.home(); | 447 | view.home(); |
448 | break; | 448 | break; |
449 | 449 | ||
450 | case KEY_END: | 450 | case KEY_END: |
451 | view.end(); | 451 | view.end(); |
452 | break; | 452 | break; |
453 | 453 | ||
454 | case '/': | 454 | case '/': |
455 | sSearchTerm = view.prompt("find: "); | 455 | sSearchTerm = view.prompt("find: "); |
456 | view.resetCaret(); | 456 | view.resetCaret(); |
457 | view.findNext( sSearchTerm ); | 457 | view.findNext( sSearchTerm ); |
458 | break; | 458 | break; |
459 | 459 | ||
460 | case 'n': | 460 | case 'n': |
461 | view.findNext( sSearchTerm ); | 461 | view.findNext( sSearchTerm ); |
462 | break; | 462 | break; |
463 | 463 | ||
464 | case 'h': | 464 | case 'h': |
465 | view.toggleHeaderRow(); | 465 | view.toggleHeaderRow(); |
466 | break; | 466 | break; |
467 | } | 467 | } |
468 | } while( bRun ); | 468 | } while( bRun ); |
469 | 469 | ||
470 | endwin(); | 470 | endwin(); |
471 | 471 | ||
472 | return 0; | 472 | return 0; |
473 | } | 473 | } |
474 | 474 | ||
diff --git a/src/unit/archive.unit b/src/unit/archive.unit index 359f380..d0427a5 100644 --- a/src/unit/archive.unit +++ b/src/unit/archive.unit | |||
@@ -14,183 +14,183 @@ using namespace Bu; | |||
14 | 14 | ||
15 | suite Archive | 15 | suite Archive |
16 | { | 16 | { |
17 | test primitives | 17 | test primitives |
18 | { | 18 | { |
19 | MemBuf mb; | 19 | MemBuf mb; |
20 | { | 20 | { |
21 | Archive ar( mb, Archive::save ); | 21 | Archive ar( mb, Archive::save ); |
22 | ar << (int8_t)1; | 22 | ar << (int8_t)1; |
23 | ar << (uint8_t)2; | 23 | ar << (uint8_t)2; |
24 | ar << (int16_t)3; | 24 | ar << (int16_t)3; |
25 | ar << (uint16_t)4; | 25 | ar << (uint16_t)4; |
26 | ar << (int32_t)5; | 26 | ar << (int32_t)5; |
27 | ar << (uint32_t)6; | 27 | ar << (uint32_t)6; |
28 | ar << (int64_t)7; | 28 | ar << (int64_t)7; |
29 | ar << (uint64_t)8; | 29 | ar << (uint64_t)8; |
30 | ar << (char)9; | 30 | ar << (char)9; |
31 | ar << (unsigned char)10; | 31 | ar << (unsigned char)10; |
32 | ar << (short)11; | 32 | ar << (short)11; |
33 | ar << (unsigned short)12; | 33 | ar << (unsigned short)12; |
34 | ar << (int)13; | 34 | ar << (int)13; |
35 | ar << (unsigned int)14; | 35 | ar << (unsigned int)14; |
36 | ar << (long)15; | 36 | ar << (long)15; |
37 | ar << (unsigned long)16; | 37 | ar << (unsigned long)16; |
38 | ar << (long long)17; | 38 | ar << (long long)17; |
39 | ar << (unsigned long long)18; | 39 | ar << (unsigned long long)18; |
40 | ar.close(); | 40 | ar.close(); |
41 | } | 41 | } |
42 | mb.setPos( 0 ); | 42 | mb.setPos( 0 ); |
43 | { | 43 | { |
44 | Archive ar( mb, Archive::load ); | 44 | Archive ar( mb, Archive::load ); |
45 | int8_t p1; | 45 | int8_t p1; |
46 | uint8_t p2; | 46 | uint8_t p2; |
47 | int16_t p3; | 47 | int16_t p3; |
48 | uint16_t p4; | 48 | uint16_t p4; |
49 | int32_t p5; | 49 | int32_t p5; |
50 | uint32_t p6; | 50 | uint32_t p6; |
51 | int64_t p7; | 51 | int64_t p7; |
52 | uint64_t p8; | 52 | uint64_t p8; |
53 | char p9; | 53 | char p9; |
54 | unsigned char p10; | 54 | unsigned char p10; |
55 | short p11; | 55 | short p11; |
56 | unsigned short p12; | 56 | unsigned short p12; |
57 | int p13; | 57 | int p13; |
58 | unsigned int p14; | 58 | unsigned int p14; |
59 | long p15; | 59 | long p15; |
60 | unsigned long p16; | 60 | unsigned long p16; |
61 | long long p17; | 61 | long long p17; |
62 | unsigned long long p18; | 62 | unsigned long long p18; |
63 | ar >> p1; | 63 | ar >> p1; |
64 | ar >> p2; | 64 | ar >> p2; |
65 | ar >> p3; | 65 | ar >> p3; |
66 | ar >> p4; | 66 | ar >> p4; |
67 | ar >> p5; | 67 | ar >> p5; |
68 | ar >> p6; | 68 | ar >> p6; |
69 | ar >> p7; | 69 | ar >> p7; |
70 | ar >> p8; | 70 | ar >> p8; |
71 | ar >> p9; | 71 | ar >> p9; |
72 | ar >> p10; | 72 | ar >> p10; |
73 | ar >> p11; | 73 | ar >> p11; |
74 | ar >> p12; | 74 | ar >> p12; |
75 | ar >> p13; | 75 | ar >> p13; |
76 | ar >> p14; | 76 | ar >> p14; |
77 | ar >> p15; | 77 | ar >> p15; |
78 | ar >> p16; | 78 | ar >> p16; |
79 | ar >> p17; | 79 | ar >> p17; |
80 | ar >> p18; | 80 | ar >> p18; |
81 | unitTest( p1 == 1 ); | 81 | unitTest( p1 == 1 ); |
82 | unitTest( p2 == 2 ); | 82 | unitTest( p2 == 2 ); |
83 | unitTest( p3 == 3 ); | 83 | unitTest( p3 == 3 ); |
84 | unitTest( p4 == 4 ); | 84 | unitTest( p4 == 4 ); |
85 | unitTest( p5 == 5 ); | 85 | unitTest( p5 == 5 ); |
86 | unitTest( p6 == 6 ); | 86 | unitTest( p6 == 6 ); |
87 | unitTest( p7 == 7 ); | 87 | unitTest( p7 == 7 ); |
88 | unitTest( p8 == 8 ); | 88 | unitTest( p8 == 8 ); |
89 | unitTest( p9 == 9 ); | 89 | unitTest( p9 == 9 ); |
90 | unitTest( p10 == 10 ); | 90 | unitTest( p10 == 10 ); |
91 | unitTest( p11 == 11 ); | 91 | unitTest( p11 == 11 ); |
92 | unitTest( p12 == 12 ); | 92 | unitTest( p12 == 12 ); |
93 | unitTest( p13 == 13 ); | 93 | unitTest( p13 == 13 ); |
94 | unitTest( p14 == 14 ); | 94 | unitTest( p14 == 14 ); |
95 | unitTest( p15 == 15 ); | 95 | unitTest( p15 == 15 ); |
96 | unitTest( p16 == 16 ); | 96 | unitTest( p16 == 16 ); |
97 | unitTest( p17 == 17 ); | 97 | unitTest( p17 == 17 ); |
98 | unitTest( p18 == 18 ); | 98 | unitTest( p18 == 18 ); |
99 | ar.close(); | 99 | ar.close(); |
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | test containers1 | 103 | test containers1 |
104 | { | 104 | { |
105 | MemBuf mb; | 105 | MemBuf mb; |
106 | { | 106 | { |
107 | Archive ar( mb, Archive::save ); | 107 | Archive ar( mb, Archive::save ); |
108 | String sStr("This is a test string."); | 108 | String sStr("This is a test string."); |
109 | List<int> lList; | 109 | List<int> lList; |
110 | lList.append( 10 ); | 110 | lList.append( 10 ); |
111 | lList.append( 20 ); | 111 | lList.append( 20 ); |
112 | lList.append( 30 ); | 112 | lList.append( 30 ); |
113 | lList.append( 40 ); | 113 | lList.append( 40 ); |
114 | ar << sStr; | 114 | ar << sStr; |
115 | ar << lList; | 115 | ar << lList; |
116 | ar.close(); | 116 | ar.close(); |
117 | } | 117 | } |
118 | mb.setPos( 0 ); | 118 | mb.setPos( 0 ); |
119 | { | 119 | { |
120 | Archive ar( mb, Archive::load ); | 120 | Archive ar( mb, Archive::load ); |
121 | String sStr; | 121 | String sStr; |
122 | List<int> lList; | 122 | List<int> lList; |
123 | ar >> sStr; | 123 | ar >> sStr; |
124 | ar >> lList; | 124 | ar >> lList; |
125 | unitTest( sStr == "This is a test string." ); | 125 | unitTest( sStr == "This is a test string." ); |
126 | unitTest( lList.getSize() == 4 ); | 126 | unitTest( lList.getSize() == 4 ); |
127 | List<int>::iterator i = lList.begin(); | 127 | List<int>::iterator i = lList.begin(); |
128 | unitTest( *i == 10 ); i++; | 128 | unitTest( *i == 10 ); i++; |
129 | unitTest( *i == 20 ); i++; | 129 | unitTest( *i == 20 ); i++; |
130 | unitTest( *i == 30 ); i++; | 130 | unitTest( *i == 30 ); i++; |
131 | unitTest( *i == 40 ); | 131 | unitTest( *i == 40 ); |
132 | ar.close(); | 132 | ar.close(); |
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | test containers2 | 136 | test containers2 |
137 | { | 137 | { |
138 | MemBuf mb; | 138 | MemBuf mb; |
139 | { | 139 | { |
140 | Archive ar( mb, Archive::save ); | 140 | Archive ar( mb, Archive::save ); |
141 | String sStr("This is a test string."); | 141 | String sStr("This is a test string."); |
142 | Array<int> lArray; | 142 | Array<int> lArray; |
143 | lArray.append( 10 ); | 143 | lArray.append( 10 ); |
144 | lArray.append( 20 ); | 144 | lArray.append( 20 ); |
145 | lArray.append( 30 ); | 145 | lArray.append( 30 ); |
146 | lArray.append( 40 ); | 146 | lArray.append( 40 ); |
147 | ar << sStr; | 147 | ar << sStr; |
148 | ar << lArray; | 148 | ar << lArray; |
149 | ar.close(); | 149 | ar.close(); |
150 | } | 150 | } |
151 | mb.setPos( 0 ); | 151 | mb.setPos( 0 ); |
152 | { | 152 | { |
153 | Archive ar( mb, Archive::load ); | 153 | Archive ar( mb, Archive::load ); |
154 | String sStr; | 154 | String sStr; |
155 | Array<int> lArray; | 155 | Array<int> lArray; |
156 | ar >> sStr; | 156 | ar >> sStr; |
157 | ar >> lArray; | 157 | ar >> lArray; |
158 | unitTest( sStr == "This is a test string." ); | 158 | unitTest( sStr == "This is a test string." ); |
159 | unitTest( lArray.getSize() == 4 ); | 159 | unitTest( lArray.getSize() == 4 ); |
160 | Array<int>::iterator i = lArray.begin(); | 160 | Array<int>::iterator i = lArray.begin(); |
161 | unitTest( *i == 10 ); i++; | 161 | unitTest( *i == 10 ); i++; |
162 | unitTest( *i == 20 ); i++; | 162 | unitTest( *i == 20 ); i++; |
163 | unitTest( *i == 30 ); i++; | 163 | unitTest( *i == 30 ); i++; |
164 | unitTest( *i == 40 ); | 164 | unitTest( *i == 40 ); |
165 | ar.close(); | 165 | ar.close(); |
166 | } | 166 | } |
167 | } | 167 | } |
168 | 168 | ||
169 | test containers3 | 169 | test containers3 |
170 | { | 170 | { |
171 | MemBuf mb; | 171 | MemBuf mb; |
172 | { | 172 | { |
173 | Archive ar( mb, Archive::save ); | 173 | Archive ar( mb, Archive::save ); |
174 | Array<String> lArray; | 174 | Array<String> lArray; |
175 | lArray.append( "10" ); | 175 | lArray.append( "10" ); |
176 | lArray.append( "20" ); | 176 | lArray.append( "20" ); |
177 | lArray.append( "30" ); | 177 | lArray.append( "30" ); |
178 | lArray.append( "40" ); | 178 | lArray.append( "40" ); |
179 | ar << lArray; | 179 | ar << lArray; |
180 | ar.close(); | 180 | ar.close(); |
181 | } | 181 | } |
182 | mb.setPos( 0 ); | 182 | mb.setPos( 0 ); |
183 | { | 183 | { |
184 | Archive ar( mb, Archive::load ); | 184 | Archive ar( mb, Archive::load ); |
185 | Array<String> lArray; | 185 | Array<String> lArray; |
186 | ar >> lArray; | 186 | ar >> lArray; |
187 | unitTest( lArray.getSize() == 4 ); | 187 | unitTest( lArray.getSize() == 4 ); |
188 | Array<String>::iterator i = lArray.begin(); | 188 | Array<String>::iterator i = lArray.begin(); |
189 | unitTest( *i == "10" ); i++; | 189 | unitTest( *i == "10" ); i++; |
190 | unitTest( *i == "20" ); i++; | 190 | unitTest( *i == "20" ); i++; |
191 | unitTest( *i == "30" ); i++; | 191 | unitTest( *i == "30" ); i++; |
192 | unitTest( *i == "40" ); | 192 | unitTest( *i == "40" ); |
193 | ar.close(); | 193 | ar.close(); |
194 | } | 194 | } |
195 | } | 195 | } |
196 | } | 196 | } |
diff --git a/src/unit/array.unit b/src/unit/array.unit index 6e985d8..ca85b4d 100644 --- a/src/unit/array.unit +++ b/src/unit/array.unit | |||
@@ -14,91 +14,91 @@ using Bu::sio; | |||
14 | 14 | ||
15 | suite Array | 15 | suite Array |
16 | { | 16 | { |
17 | test general | 17 | test general |
18 | { | 18 | { |
19 | Bu::Array<int> ai; | 19 | Bu::Array<int> ai; |
20 | 20 | ||
21 | ai.append( 5 ); | 21 | ai.append( 5 ); |
22 | ai.append( 10 ); | 22 | ai.append( 10 ); |
23 | unitTest( ai.getSize() == 2 ); | 23 | unitTest( ai.getSize() == 2 ); |
24 | unitTest( ai.getCapacity() == 10 ); | 24 | unitTest( ai.getCapacity() == 10 ); |
25 | unitTest( ai[0] == 5 ); | 25 | unitTest( ai[0] == 5 ); |
26 | unitTest( ai[1] == 10 ); | 26 | unitTest( ai[1] == 10 ); |
27 | } | 27 | } |
28 | 28 | ||
29 | test iterate1 | 29 | test iterate1 |
30 | { | 30 | { |
31 | Bu::Array<int> ai; | 31 | Bu::Array<int> ai; |
32 | for( int j = 0; j < 10; j++ ) | 32 | for( int j = 0; j < 10; j++ ) |
33 | ai.append( j ); | 33 | ai.append( j ); |
34 | 34 | ||
35 | int j = 0; | 35 | int j = 0; |
36 | for( Bu::Array<int>::iterator i = ai.begin(); i != ai.end(); i++ ) | 36 | for( Bu::Array<int>::iterator i = ai.begin(); i != ai.end(); i++ ) |
37 | unitTest( (*i) == j++ ); | 37 | unitTest( (*i) == j++ ); |
38 | unitTest( j == 10 ); | 38 | unitTest( j == 10 ); |
39 | 39 | ||
40 | const Bu::Array<int> &ci = ai; | 40 | const Bu::Array<int> &ci = ai; |
41 | j = 0; | 41 | j = 0; |
42 | for( Bu::Array<int>::const_iterator i = ci.begin(); i; i++ ) | 42 | for( Bu::Array<int>::const_iterator i = ci.begin(); i; i++ ) |
43 | unitTest( (*i) == j++ ); | 43 | unitTest( (*i) == j++ ); |
44 | unitTest( j == 10 ); | 44 | unitTest( j == 10 ); |
45 | } | 45 | } |
46 | 46 | ||
47 | test iterate2 | 47 | test iterate2 |
48 | { | 48 | { |
49 | Bu::Array<int> ai; | 49 | Bu::Array<int> ai; |
50 | for( Bu::Array<int>::iterator i = ai.begin(); i != ai.end(); i++ ) | 50 | for( Bu::Array<int>::iterator i = ai.begin(); i != ai.end(); i++ ) |
51 | unitFailed("Empty lists shouldn't be iterated through."); | 51 | unitFailed("Empty lists shouldn't be iterated through."); |
52 | for( Bu::Array<int>::iterator i = ai.begin(); i; i++ ) | 52 | for( Bu::Array<int>::iterator i = ai.begin(); i; i++ ) |
53 | unitFailed("Empty lists shouldn't be iterated through."); | 53 | unitFailed("Empty lists shouldn't be iterated through."); |
54 | } | 54 | } |
55 | 55 | ||
56 | test copy | 56 | test copy |
57 | { | 57 | { |
58 | typedef Bu::Hash<Bu::String, Bu::String> StrHash; | 58 | typedef Bu::Hash<Bu::String, Bu::String> StrHash; |
59 | typedef Bu::Array<StrHash> StrHashArray; | 59 | typedef Bu::Array<StrHash> StrHashArray; |
60 | 60 | ||
61 | StrHash h1; | 61 | StrHash h1; |
62 | h1["Hi"] = "Yo"; | 62 | h1["Hi"] = "Yo"; |
63 | h1["Bye"] = "Later"; | 63 | h1["Bye"] = "Later"; |
64 | 64 | ||
65 | StrHash h2; | 65 | StrHash h2; |
66 | h2["Test"] = "Bloop"; | 66 | h2["Test"] = "Bloop"; |
67 | h2["Foo"] = "ooF"; | 67 | h2["Foo"] = "ooF"; |
68 | 68 | ||
69 | StrHashArray a1; | 69 | StrHashArray a1; |
70 | a1.append( h1 ); | 70 | a1.append( h1 ); |
71 | a1.append( h2 ); | 71 | a1.append( h2 ); |
72 | 72 | ||
73 | StrHashArray a2(a1); | 73 | StrHashArray a2(a1); |
74 | 74 | ||
75 | unitTest( a2[0].get("Hi") == "Yo" ); | 75 | unitTest( a2[0].get("Hi") == "Yo" ); |
76 | unitTest( a2[0].get("Bye") == "Later" ); | 76 | unitTest( a2[0].get("Bye") == "Later" ); |
77 | unitTest( a2[1].get("Test") == "Bloop" ); | 77 | unitTest( a2[1].get("Test") == "Bloop" ); |
78 | unitTest( a2[1].get("Foo") == "ooF" ); | 78 | unitTest( a2[1].get("Foo") == "ooF" ); |
79 | 79 | ||
80 | StrHashArray a3; | 80 | StrHashArray a3; |
81 | a3 = a1; | 81 | a3 = a1; |
82 | 82 | ||
83 | unitTest( a3[0].get("Hi") == "Yo" ); | 83 | unitTest( a3[0].get("Hi") == "Yo" ); |
84 | unitTest( a3[0].get("Bye") == "Later" ); | 84 | unitTest( a3[0].get("Bye") == "Later" ); |
85 | unitTest( a3[1].get("Test") == "Bloop" ); | 85 | unitTest( a3[1].get("Test") == "Bloop" ); |
86 | unitTest( a3[1].get("Foo") == "ooF" ); | 86 | unitTest( a3[1].get("Foo") == "ooF" ); |
87 | } | 87 | } |
88 | 88 | ||
89 | test insert | 89 | test insert |
90 | { | 90 | { |
91 | Bu::Array<int> aInts; | 91 | Bu::Array<int> aInts; |
92 | aInts.insert( aInts.end(), 4 ); | 92 | aInts.insert( aInts.end(), 4 ); |
93 | aInts.insert( aInts.begin(), 1 ); | 93 | aInts.insert( aInts.begin(), 1 ); |
94 | aInts.insert( aInts.end(), 5 ); | 94 | aInts.insert( aInts.end(), 5 ); |
95 | aInts.insert( aInts.begin()+1, 3 ); | 95 | aInts.insert( aInts.begin()+1, 3 ); |
96 | aInts.insert( aInts.begin()+1, 2 ); | 96 | aInts.insert( aInts.begin()+1, 2 ); |
97 | aInts.insert( aInts.begin(), 0 ); | 97 | aInts.insert( aInts.begin(), 0 ); |
98 | 98 | ||
99 | for( int j = 0; j < 6; j++ ) | 99 | for( int j = 0; j < 6; j++ ) |
100 | { | 100 | { |
101 | unitTest( aInts[j] == j ); | 101 | unitTest( aInts[j] == j ); |
102 | } | 102 | } |
103 | } | 103 | } |
104 | } | 104 | } |
diff --git a/src/unit/base64.unit b/src/unit/base64.unit index 5266b48..bd5bc97 100644 --- a/src/unit/base64.unit +++ b/src/unit/base64.unit | |||
@@ -11,18 +11,18 @@ | |||
11 | 11 | ||
12 | suite MemBuf | 12 | suite MemBuf |
13 | { | 13 | { |
14 | test decode01 | 14 | test decode01 |
15 | { | 15 | { |
16 | unitTest( Bu::decodeStr<Bu::Base64>("RnVu") == "Fun" ); | 16 | unitTest( Bu::decodeStr<Bu::Base64>("RnVu") == "Fun" ); |
17 | unitTest( Bu::decodeStr<Bu::Base64>("V2hhdA==") == "What" ); | 17 | unitTest( Bu::decodeStr<Bu::Base64>("V2hhdA==") == "What" ); |
18 | unitTest( Bu::decodeStr<Bu::Base64>("SGVsbG8=") == "Hello" ); | 18 | unitTest( Bu::decodeStr<Bu::Base64>("SGVsbG8=") == "Hello" ); |
19 | } | 19 | } |
20 | 20 | ||
21 | test encode01 | 21 | test encode01 |
22 | { | 22 | { |
23 | unitTest( Bu::decodeStr<Bu::Base64>("R n V u") == "Fun" ); | 23 | unitTest( Bu::decodeStr<Bu::Base64>("R n V u") == "Fun" ); |
24 | unitTest( Bu::decodeStr<Bu::Base64>("V2\n\n\thh dA==") == "What" ); | 24 | unitTest( Bu::decodeStr<Bu::Base64>("V2\n\n\thh dA==") == "What" ); |
25 | unitTest( Bu::decodeStr<Bu::Base64>("\n\n\t\t SGV\r\ns\tbG8\n=") == "Hello" ); | 25 | unitTest( Bu::decodeStr<Bu::Base64>("\n\n\t\t SGV\r\ns\tbG8\n=") == "Hello" ); |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
diff --git a/src/unit/blowfish.unit b/src/unit/blowfish.unit index abab63d..1b4ca18 100644 --- a/src/unit/blowfish.unit +++ b/src/unit/blowfish.unit | |||
@@ -50,29 +50,29 @@ static const char *testdat[34][3] ={ | |||
50 | 50 | ||
51 | suite Blowfish | 51 | suite Blowfish |
52 | { | 52 | { |
53 | test standard | 53 | test standard |
54 | { | 54 | { |
55 | for( int j = 0; j < 34; j++ ) | 55 | for( int j = 0; j < 34; j++ ) |
56 | { | 56 | { |
57 | Bu::MemBuf mb; | 57 | Bu::MemBuf mb; |
58 | Bu::BlowfishEcb bf( mb ); | 58 | Bu::BlowfishEcb bf( mb ); |
59 | bf.setPassword( Bu::decodeStr<Bu::Hex>( testdat[j][0] ) ); | 59 | bf.setPassword( Bu::decodeStr<Bu::Hex>( testdat[j][0] ) ); |
60 | bf.write( Bu::decodeStr<Bu::Hex>( testdat[j][1] ) ); | 60 | bf.write( Bu::decodeStr<Bu::Hex>( testdat[j][1] ) ); |
61 | unitTest( | 61 | unitTest( |
62 | mb.getString() == Bu::decodeStr<Bu::Hex>( testdat[j][2] ) | 62 | mb.getString() == Bu::decodeStr<Bu::Hex>( testdat[j][2] ) |
63 | ); | 63 | ); |
64 | 64 | ||
65 | mb.setPos( 0 ); | 65 | mb.setPos( 0 ); |
66 | Bu::BlowfishEcb bf2( mb ); | 66 | Bu::BlowfishEcb bf2( mb ); |
67 | bf2.setPassword( Bu::decodeStr<Bu::Hex>( testdat[j][0] ) ); | 67 | bf2.setPassword( Bu::decodeStr<Bu::Hex>( testdat[j][0] ) ); |
68 | char buf[8]; | 68 | char buf[8]; |
69 | bf2.read( buf, 8 ); | 69 | bf2.read( buf, 8 ); |
70 | 70 | ||
71 | unitTest( | 71 | unitTest( |
72 | Bu::String(testdat[j][1]) == | 72 | Bu::String(testdat[j][1]) == |
73 | Bu::encodeStr<Bu::Hex>(Bu::String(buf,8),true) | 73 | Bu::encodeStr<Bu::Hex>(Bu::String(buf,8),true) |
74 | ); | 74 | ); |
75 | } | 75 | } |
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
diff --git a/src/unit/buffer.unit b/src/unit/buffer.unit index 8bfdc3d..8613c5b 100644 --- a/src/unit/buffer.unit +++ b/src/unit/buffer.unit | |||
@@ -12,16 +12,16 @@ | |||
12 | 12 | ||
13 | suite Buffer | 13 | suite Buffer |
14 | { | 14 | { |
15 | test emptyFile | 15 | test emptyFile |
16 | { | 16 | { |
17 | Bu::String sTmp("empty-XXXXXX"); | 17 | Bu::String sTmp("empty-XXXXXX"); |
18 | Bu::File fEmpty = tempFile(sTmp); | 18 | Bu::File fEmpty = tempFile(sTmp); |
19 | Bu::Buffer buf( fEmpty ); | 19 | Bu::Buffer buf( fEmpty ); |
20 | 20 | ||
21 | unitTest( buf.isEos() == false ); | 21 | unitTest( buf.isEos() == false ); |
22 | Bu::String sLine = buf.readLine(); | 22 | Bu::String sLine = buf.readLine(); |
23 | unitTest( sLine == "" ); | 23 | unitTest( sLine == "" ); |
24 | unitTest( fEmpty.isEos() == true ); | 24 | unitTest( fEmpty.isEos() == true ); |
25 | unitTest( buf.isEos() == true ); | 25 | unitTest( buf.isEos() == true ); |
26 | } | 26 | } |
27 | } | 27 | } |
diff --git a/src/unit/file.unit b/src/unit/file.unit index 7140d03..c0358ac 100644 --- a/src/unit/file.unit +++ b/src/unit/file.unit | |||
@@ -14,87 +14,87 @@ | |||
14 | 14 | ||
15 | suite File | 15 | suite File |
16 | { | 16 | { |
17 | test writeFull | 17 | test writeFull |
18 | { | 18 | { |
19 | Bu::File sf("testfile1", Bu::File::WriteNew ); | 19 | Bu::File sf("testfile1", Bu::File::WriteNew ); |
20 | for( int c = 0; c < 256; c++ ) | 20 | for( int c = 0; c < 256; c++ ) |
21 | { | 21 | { |
22 | unsigned char ch = (unsigned char)c; | 22 | unsigned char ch = (unsigned char)c; |
23 | sf.write( &ch, 1 ); | 23 | sf.write( &ch, 1 ); |
24 | unitTest( sf.tell() == c+1 ); | 24 | unitTest( sf.tell() == c+1 ); |
25 | } | 25 | } |
26 | //unitTest( sf.canRead() == false ); | 26 | //unitTest( sf.canRead() == false ); |
27 | //unitTest( sf.canWrite() == true ); | 27 | //unitTest( sf.canWrite() == true ); |
28 | //unitTest( sf.canSeek() == true ); | 28 | //unitTest( sf.canSeek() == true ); |
29 | sf.close(); | 29 | sf.close(); |
30 | struct stat sdat; | 30 | struct stat sdat; |
31 | stat("testfile1", &sdat ); | 31 | stat("testfile1", &sdat ); |
32 | unitTest( sdat.st_size == 256 ); | 32 | unitTest( sdat.st_size == 256 ); |
33 | } | 33 | } |
34 | 34 | ||
35 | test readBlocks | 35 | test readBlocks |
36 | { | 36 | { |
37 | Bu::File sf("testfile1", Bu::File::Read ); | 37 | Bu::File sf("testfile1", Bu::File::Read ); |
38 | unsigned char buf[50]; | 38 | unsigned char buf[50]; |
39 | size_t total = 0; | 39 | size_t total = 0; |
40 | for(;;) | 40 | for(;;) |
41 | { | 41 | { |
42 | size_t s = sf.read( buf, 50 ); | 42 | size_t s = sf.read( buf, 50 ); |
43 | for( size_t c = 0; c < s; c++ ) | 43 | for( size_t c = 0; c < s; c++ ) |
44 | { | 44 | { |
45 | unitTest( buf[c] == (unsigned char)(c+total) ); | 45 | unitTest( buf[c] == (unsigned char)(c+total) ); |
46 | } | 46 | } |
47 | total += s; | 47 | total += s; |
48 | if( s < 50 ) | 48 | if( s < 50 ) |
49 | { | 49 | { |
50 | unitTest( total == 256 ); | 50 | unitTest( total == 256 ); |
51 | unitTest( sf.isEos() == false ); | 51 | unitTest( sf.isEos() == false ); |
52 | unitTest( sf.read( buf, 1 ) == 0 ); | 52 | unitTest( sf.read( buf, 1 ) == 0 ); |
53 | unitTest( sf.isEos() == true ); | 53 | unitTest( sf.isEos() == true ); |
54 | // EOS is only set when an attempt to read past the end of | 54 | // EOS is only set when an attempt to read past the end of |
55 | // the stream is made, not when a short block is returned. | 55 | // the stream is made, not when a short block is returned. |
56 | break; | 56 | break; |
57 | } | 57 | } |
58 | } | 58 | } |
59 | sf.close(); | 59 | sf.close(); |
60 | } | 60 | } |
61 | 61 | ||
62 | test readError1 | 62 | test readError1 |
63 | { | 63 | { |
64 | try | 64 | try |
65 | { | 65 | { |
66 | Bu::File sf("doesn'texist", Bu::File::Read ); | 66 | Bu::File sf("doesn'texist", Bu::File::Read ); |
67 | unitFailed("No exception thrown"); | 67 | unitFailed("No exception thrown"); |
68 | } | 68 | } |
69 | catch( Bu::FileException &e ) | 69 | catch( Bu::FileException &e ) |
70 | { | 70 | { |
71 | return; | 71 | return; |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | test readError2 | 75 | test readError2 |
76 | { | 76 | { |
77 | Bu::File sf("testfile1", Bu::File::Read ); | 77 | Bu::File sf("testfile1", Bu::File::Read ); |
78 | char buf[256]; | 78 | char buf[256]; |
79 | int r = sf.read( buf, 256 ); | 79 | int r = sf.read( buf, 256 ); |
80 | unitTest( r == 256 ); | 80 | unitTest( r == 256 ); |
81 | // You have to read past the end to set the EOS flag. | 81 | // You have to read past the end to set the EOS flag. |
82 | unitTest( sf.isEos() == false ); | 82 | unitTest( sf.isEos() == false ); |
83 | try | 83 | try |
84 | { | 84 | { |
85 | if( sf.read( buf, 5 ) > 0 ) | 85 | if( sf.read( buf, 5 ) > 0 ) |
86 | { | 86 | { |
87 | unitFailed("Non-zero read result"); | 87 | unitFailed("Non-zero read result"); |
88 | } | 88 | } |
89 | else | 89 | else |
90 | { | 90 | { |
91 | sf.close(); | 91 | sf.close(); |
92 | } | 92 | } |
93 | } | 93 | } |
94 | catch( Bu::FileException &e ) | 94 | catch( Bu::FileException &e ) |
95 | { | 95 | { |
96 | sf.close(); | 96 | sf.close(); |
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | } | 99 | } |
100 | } | 100 | } |
diff --git a/src/unit/hash.unit b/src/unit/hash.unit index 3abc6a5..e30c62b 100644 --- a/src/unit/hash.unit +++ b/src/unit/hash.unit | |||
@@ -19,193 +19,193 @@ typedef Bu::Hash<int, Bu::String> IntStrHash; | |||
19 | 19 | ||
20 | suite Hash | 20 | suite Hash |
21 | { | 21 | { |
22 | test probe1 | 22 | test probe1 |
23 | { | 23 | { |
24 | StrIntHash h; | 24 | StrIntHash h; |
25 | char buf[20]; | 25 | char buf[20]; |
26 | for(int i=1;i<10000;i++) | 26 | for(int i=1;i<10000;i++) |
27 | { | 27 | { |
28 | sprintf(buf,"%d",i); | 28 | sprintf(buf,"%d",i); |
29 | Bu::String sTmp(buf); | 29 | Bu::String sTmp(buf); |
30 | h[sTmp] = i; | 30 | h[sTmp] = i; |
31 | unitTest( h.has(sTmp) ); | 31 | unitTest( h.has(sTmp) ); |
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | test insert1 | 35 | test insert1 |
36 | { | 36 | { |
37 | StrIntHash h; | 37 | StrIntHash h; |
38 | h["Hi"] = 42; | 38 | h["Hi"] = 42; |
39 | unitTest( h["Hi"] == 42 ); | 39 | unitTest( h["Hi"] == 42 ); |
40 | } | 40 | } |
41 | 41 | ||
42 | test insert2 | 42 | test insert2 |
43 | { | 43 | { |
44 | StrStrHash h; | 44 | StrStrHash h; |
45 | h["Hi"] = "Yo"; | 45 | h["Hi"] = "Yo"; |
46 | h["Bye"] = "Later"; | 46 | h["Bye"] = "Later"; |
47 | unitTest( h["Hi"].getValue() == "Yo" ); | 47 | unitTest( h["Hi"].getValue() == "Yo" ); |
48 | 48 | ||
49 | StrStrHash h2(h); | 49 | StrStrHash h2(h); |
50 | unitTest( h2["Hi"].getValue() == "Yo" ); | 50 | unitTest( h2["Hi"].getValue() == "Yo" ); |
51 | unitTest( h2["Bye"].getValue() == "Later" ); | 51 | unitTest( h2["Bye"].getValue() == "Later" ); |
52 | 52 | ||
53 | StrStrHash h3; | 53 | StrStrHash h3; |
54 | h3 = h; | 54 | h3 = h; |
55 | unitTest( h3["Hi"].getValue() == "Yo" ); | 55 | unitTest( h3["Hi"].getValue() == "Yo" ); |
56 | unitTest( h3["Bye"].getValue() == "Later" ); | 56 | unitTest( h3["Bye"].getValue() == "Later" ); |
57 | } | 57 | } |
58 | 58 | ||
59 | test insert3 | 59 | test insert3 |
60 | { | 60 | { |
61 | IntStrHash h; | 61 | IntStrHash h; |
62 | 62 | ||
63 | for( unsigned int i=1; i<50; i++ ) | 63 | for( unsigned int i=1; i<50; i++ ) |
64 | { | 64 | { |
65 | h[i] = "testing"; | 65 | h[i] = "testing"; |
66 | unitTest( h.getSize() == i ); | 66 | unitTest( h.getSize() == i ); |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | test erase1 | 70 | test erase1 |
71 | { | 71 | { |
72 | StrIntHash h; | 72 | StrIntHash h; |
73 | h.insert("Number 1", 1 ); | 73 | h.insert("Number 1", 1 ); |
74 | h.insert("Number 2", 2 ); | 74 | h.insert("Number 2", 2 ); |
75 | h.insert("Number 3", 3 ); | 75 | h.insert("Number 3", 3 ); |
76 | h.erase("Number 2"); | 76 | h.erase("Number 2"); |
77 | h.get("Number 3"); | 77 | h.get("Number 3"); |
78 | try { | 78 | try { |
79 | h.get("Number 2"); | 79 | h.get("Number 2"); |
80 | unitFailed("h.get(\"Number 2\") should have thrown an exception."); | 80 | unitFailed("h.get(\"Number 2\") should have thrown an exception."); |
81 | } catch( Bu::HashException &e ) { } | 81 | } catch( Bu::HashException &e ) { } |
82 | 82 | ||
83 | /* printf("\n"); | 83 | /* printf("\n"); |
84 | for( StrIntHash::iterator i = h.begin(); i != h.end(); i++ ) | 84 | for( StrIntHash::iterator i = h.begin(); i != h.end(); i++ ) |
85 | { | 85 | { |
86 | printf(" - \"%s\" = %d\n", i.getKey().getStr(), i.getValue() ); | 86 | printf(" - \"%s\" = %d\n", i.getKey().getStr(), i.getValue() ); |
87 | } */ | 87 | } */ |
88 | } | 88 | } |
89 | 89 | ||
90 | test copy | 90 | test copy |
91 | { | 91 | { |
92 | StrIntHash h; | 92 | StrIntHash h; |
93 | h.insert("hello", 55 ); | 93 | h.insert("hello", 55 ); |
94 | h.insert("goodbye", -1812 ); | 94 | h.insert("goodbye", -1812 ); |
95 | 95 | ||
96 | StrIntHash h2 = h; | 96 | StrIntHash h2 = h; |
97 | unitTest( h2.isCoreShared( h ) ); | 97 | unitTest( h2.isCoreShared( h ) ); |
98 | 98 | ||
99 | StrIntHash h3 = h.clone(); | 99 | StrIntHash h3 = h.clone(); |
100 | unitTest( !h3.isCoreShared( h ) ); | 100 | unitTest( !h3.isCoreShared( h ) ); |
101 | } | 101 | } |
102 | 102 | ||
103 | test reHashSpecial | 103 | test reHashSpecial |
104 | { | 104 | { |
105 | IntStrHash hTest; | 105 | IntStrHash hTest; |
106 | 106 | ||
107 | setStepCount( 1000000 ); | 107 | setStepCount( 1000000 ); |
108 | for( int i=0; i<1000000; ++i ) | 108 | for( int i=0; i<1000000; ++i ) |
109 | { | 109 | { |
110 | char buf[40]; snprintf(buf,40,"num%d",i); | 110 | char buf[40]; snprintf(buf,40,"num%d",i); |
111 | incProgress(); | 111 | incProgress(); |
112 | 112 | ||
113 | if( ((double)random()/(double)RAND_MAX)<.01 ) | 113 | if( ((double)random()/(double)RAND_MAX)<.01 ) |
114 | { | 114 | { |
115 | //printf("ERASE: %d (%s)\n",i%64,buf); | 115 | //printf("ERASE: %d (%s)\n",i%64,buf); |
116 | hTest.erase(i%64); | 116 | hTest.erase(i%64); |
117 | } | 117 | } |
118 | else | 118 | else |
119 | { | 119 | { |
120 | hTest[i%64]=buf; | 120 | hTest[i%64]=buf; |
121 | } | 121 | } |
122 | 122 | ||
123 | /*printf("(%d) size: %u fill: %u cap:%u\n", | 123 | /*printf("(%d) size: %u fill: %u cap:%u\n", |
124 | i, | 124 | i, |
125 | hTest.getSize(), | 125 | hTest.getSize(), |
126 | hTest.getFill(), | 126 | hTest.getFill(), |
127 | hTest.getCapacity() | 127 | hTest.getCapacity() |
128 | );*/ | 128 | );*/ |
129 | } | 129 | } |
130 | } | 130 | } |
131 | 131 | ||
132 | test stress | 132 | test stress |
133 | { | 133 | { |
134 | srandom(time(NULL)); | 134 | srandom(time(NULL)); |
135 | 135 | ||
136 | IntStrHash hTest; | 136 | IntStrHash hTest; |
137 | IntStrHash hReUse; | 137 | IntStrHash hReUse; |
138 | setStepCount( 100000 ); | 138 | setStepCount( 100000 ); |
139 | 139 | ||
140 | for( int i=0; i<100000; ++i ) | 140 | for( int i=0; i<100000; ++i ) |
141 | { | 141 | { |
142 | char buf[40]; snprintf(buf,40,"num%d",i); | 142 | char buf[40]; snprintf(buf,40,"num%d",i); |
143 | hTest[i] = buf; | 143 | hTest[i] = buf; |
144 | incProgress(); | 144 | incProgress(); |
145 | 145 | ||
146 | 146 | ||
147 | if( ((double)random()/(double)RAND_MAX)<.01 ) | 147 | if( ((double)random()/(double)RAND_MAX)<.01 ) |
148 | { | 148 | { |
149 | Bu::List<int> lKeys = hReUse.getKeys(); | 149 | Bu::List<int> lKeys = hReUse.getKeys(); |
150 | Bu::List<int>::const_iterator it = lKeys.begin(); | 150 | Bu::List<int>::const_iterator it = lKeys.begin(); |
151 | int iIdx = (int)(((double)random()/(double)RAND_MAX) | 151 | int iIdx = (int)(((double)random()/(double)RAND_MAX) |
152 | *lKeys.getSize()); | 152 | *lKeys.getSize()); |
153 | for( int l=0; it; ++it, ++l ) | 153 | for( int l=0; it; ++it, ++l ) |
154 | { | 154 | { |
155 | if( l==iIdx ) | 155 | if( l==iIdx ) |
156 | { | 156 | { |
157 | int iVal = *it; | 157 | int iVal = *it; |
158 | hReUse.erase( *it ); | 158 | hReUse.erase( *it ); |
159 | char buf[40]; snprintf(buf,40,"num%d",iVal); | 159 | char buf[40]; snprintf(buf,40,"num%d",iVal); |
160 | hTest[i] = buf; | 160 | hTest[i] = buf; |
161 | //printf("re-use: %s\n",buf); | 161 | //printf("re-use: %s\n",buf); |
162 | } | 162 | } |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | /*printf("(%s) size: %u fill: %u cap:%u\n", | 166 | /*printf("(%s) size: %u fill: %u cap:%u\n", |
167 | buf, | 167 | buf, |
168 | hTest.getSize(), | 168 | hTest.getSize(), |
169 | hTest.getFill(), | 169 | hTest.getFill(), |
170 | hTest.getCapacity() | 170 | hTest.getCapacity() |
171 | );*/ | 171 | );*/ |
172 | 172 | ||
173 | if( ((double)random()/(double)RAND_MAX)<.3 ) | 173 | if( ((double)random()/(double)RAND_MAX)<.3 ) |
174 | { | 174 | { |
175 | Bu::List<int> lKeys = hTest.getKeys(); | 175 | Bu::List<int> lKeys = hTest.getKeys(); |
176 | int iIdx = (int)(((double)random()/(double)RAND_MAX) | 176 | int iIdx = (int)(((double)random()/(double)RAND_MAX) |
177 | *lKeys.getSize()); | 177 | *lKeys.getSize()); |
178 | Bu::List<int>::const_iterator it = lKeys.begin(); | 178 | Bu::List<int>::const_iterator it = lKeys.begin(); |
179 | for( int k=0; it; ++it, ++k ) | 179 | for( int k=0; it; ++it, ++k ) |
180 | { | 180 | { |
181 | if( k == iIdx ) | 181 | if( k == iIdx ) |
182 | { | 182 | { |
183 | hReUse.insert(*it,"yo"); | 183 | hReUse.insert(*it,"yo"); |
184 | hTest.erase( *it ); | 184 | hTest.erase( *it ); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | if( hTest.getSize() > 100 ) | 189 | if( hTest.getSize() > 100 ) |
190 | { | 190 | { |
191 | int iK = (int)(((double)random()/(double)RAND_MAX)*50)+10; | 191 | int iK = (int)(((double)random()/(double)RAND_MAX)*50)+10; |
192 | for( int j=0; j<iK; ++j ) | 192 | for( int j=0; j<iK; ++j ) |
193 | { | 193 | { |
194 | Bu::List<int> lKeys = hTest.getKeys(); | 194 | Bu::List<int> lKeys = hTest.getKeys(); |
195 | int iIdx = (int)(((double)random()/(double)RAND_MAX) | 195 | int iIdx = (int)(((double)random()/(double)RAND_MAX) |
196 | *lKeys.getSize()); | 196 | *lKeys.getSize()); |
197 | Bu::List<int>::const_iterator it = lKeys.begin(); | 197 | Bu::List<int>::const_iterator it = lKeys.begin(); |
198 | for( int k=0; it; ++it, ++k ) | 198 | for( int k=0; it; ++it, ++k ) |
199 | { | 199 | { |
200 | if( k == iIdx ) | 200 | if( k == iIdx ) |
201 | { | 201 | { |
202 | hReUse.insert(*it,"yo"); | 202 | hReUse.insert(*it,"yo"); |
203 | hTest.erase( *it ); | 203 | hTest.erase( *it ); |
204 | break; | 204 | break; |
205 | } | 205 | } |
206 | } | 206 | } |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
210 | } | 210 | } |
211 | } | 211 | } |
diff --git a/src/unit/list.unit b/src/unit/list.unit index ec92fd5..0b60e43 100644 --- a/src/unit/list.unit +++ b/src/unit/list.unit | |||
@@ -13,136 +13,136 @@ typedef Bu::List<int> IntList; | |||
13 | 13 | ||
14 | suite List | 14 | suite List |
15 | { | 15 | { |
16 | test append | 16 | test append |
17 | { | 17 | { |
18 | IntList lst; | 18 | IntList lst; |
19 | for( int j = 0; j < 50; j++ ) | 19 | for( int j = 0; j < 50; j++ ) |
20 | { | 20 | { |
21 | lst.append( j ); | 21 | lst.append( j ); |
22 | } | 22 | } |
23 | int j = 0; | 23 | int j = 0; |
24 | for( IntList::iterator i = lst.begin(); i; i++, j++ ) | 24 | for( IntList::iterator i = lst.begin(); i; i++, j++ ) |
25 | { | 25 | { |
26 | unitTest( *i == j ); | 26 | unitTest( *i == j ); |
27 | } | 27 | } |
28 | } | 28 | } |
29 | 29 | ||
30 | test prepend | 30 | test prepend |
31 | { | 31 | { |
32 | IntList lst; | 32 | IntList lst; |
33 | for( int j = 0; j < 50; j++ ) | 33 | for( int j = 0; j < 50; j++ ) |
34 | { | 34 | { |
35 | lst.prepend( j ); | 35 | lst.prepend( j ); |
36 | } | 36 | } |
37 | int j = 49; | 37 | int j = 49; |
38 | for( IntList::iterator i = lst.begin(); i; i++, j-- ) | 38 | for( IntList::iterator i = lst.begin(); i; i++, j-- ) |
39 | { | 39 | { |
40 | unitTest( *i == j ); | 40 | unitTest( *i == j ); |
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | test copy | 44 | test copy |
45 | { | 45 | { |
46 | IntList lst; | 46 | IntList lst; |
47 | int j; | 47 | int j; |
48 | for( j = 0; j < 50; j++ ) | 48 | for( j = 0; j < 50; j++ ) |
49 | { | 49 | { |
50 | lst.append( j ); | 50 | lst.append( j ); |
51 | } | 51 | } |
52 | IntList lst2 = lst; | 52 | IntList lst2 = lst; |
53 | 53 | ||
54 | j = 0; | 54 | j = 0; |
55 | for( IntList::iterator i = lst2.begin(); i; i++, j++ ) | 55 | for( IntList::iterator i = lst2.begin(); i; i++, j++ ) |
56 | { | 56 | { |
57 | unitTest( *i == j ); | 57 | unitTest( *i == j ); |
58 | } | 58 | } |
59 | lst2.clear(); | 59 | lst2.clear(); |
60 | lst2 = lst; | 60 | lst2 = lst; |
61 | 61 | ||
62 | j = 0; | 62 | j = 0; |
63 | for( IntList::iterator i = lst2.begin(); i; i++, j++ ) | 63 | for( IntList::iterator i = lst2.begin(); i; i++, j++ ) |
64 | { | 64 | { |
65 | unitTest( *i == j ); | 65 | unitTest( *i == j ); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | test sort1 | 69 | test sort1 |
70 | { | 70 | { |
71 | IntList lst; | 71 | IntList lst; |
72 | 72 | ||
73 | lst.insertSorted( 5 ); | 73 | lst.insertSorted( 5 ); |
74 | lst.insertSorted( 1 ); | 74 | lst.insertSorted( 1 ); |
75 | lst.insertSorted( 10 ); | 75 | lst.insertSorted( 10 ); |
76 | lst.insertSorted( 3 ); | 76 | lst.insertSorted( 3 ); |
77 | 77 | ||
78 | unitTest( lst == IntList(1).append(3).append(5).append(10) ); | 78 | unitTest( lst == IntList(1).append(3).append(5).append(10) ); |
79 | } | 79 | } |
80 | 80 | ||
81 | test sort2 | 81 | test sort2 |
82 | { | 82 | { |
83 | IntList lst; | 83 | IntList lst; |
84 | 84 | ||
85 | lst.insertSorted<Bu::__basicGTCmp<int> >( 5 ); | 85 | lst.insertSorted<Bu::__basicGTCmp<int> >( 5 ); |
86 | lst.insertSorted<Bu::__basicGTCmp<int> >( 1 ); | 86 | lst.insertSorted<Bu::__basicGTCmp<int> >( 1 ); |
87 | lst.insertSorted<Bu::__basicGTCmp<int> >( 10 ); | 87 | lst.insertSorted<Bu::__basicGTCmp<int> >( 10 ); |
88 | lst.insertSorted<Bu::__basicGTCmp<int> >( 3 ); | 88 | lst.insertSorted<Bu::__basicGTCmp<int> >( 3 ); |
89 | 89 | ||
90 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); | 90 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); |
91 | } | 91 | } |
92 | 92 | ||
93 | test sort3 | 93 | test sort3 |
94 | { | 94 | { |
95 | IntList lst; | 95 | IntList lst; |
96 | Bu::__basicGTCmp<int> cmp; | 96 | Bu::__basicGTCmp<int> cmp; |
97 | 97 | ||
98 | lst.insertSorted( cmp, 5 ); | 98 | lst.insertSorted( cmp, 5 ); |
99 | lst.insertSorted( cmp, 1 ); | 99 | lst.insertSorted( cmp, 1 ); |
100 | lst.insertSorted( cmp, 10 ); | 100 | lst.insertSorted( cmp, 10 ); |
101 | lst.insertSorted( cmp, 3 ); | 101 | lst.insertSorted( cmp, 3 ); |
102 | 102 | ||
103 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); | 103 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); |
104 | } | 104 | } |
105 | 105 | ||
106 | test sort4 | 106 | test sort4 |
107 | { | 107 | { |
108 | IntList lst; | 108 | IntList lst; |
109 | 109 | ||
110 | lst.append( 5 ); | 110 | lst.append( 5 ); |
111 | lst.append( 1 ); | 111 | lst.append( 1 ); |
112 | lst.append( 10 ); | 112 | lst.append( 10 ); |
113 | lst.append( 3 ); | 113 | lst.append( 3 ); |
114 | 114 | ||
115 | lst.sort(); | 115 | lst.sort(); |
116 | 116 | ||
117 | unitTest( lst == IntList(1).append(3).append(5).append(10) ); | 117 | unitTest( lst == IntList(1).append(3).append(5).append(10) ); |
118 | } | 118 | } |
119 | 119 | ||
120 | test sort5 | 120 | test sort5 |
121 | { | 121 | { |
122 | IntList lst; | 122 | IntList lst; |
123 | 123 | ||
124 | lst.append( 5 ); | 124 | lst.append( 5 ); |
125 | lst.append( 1 ); | 125 | lst.append( 1 ); |
126 | lst.append( 10 ); | 126 | lst.append( 10 ); |
127 | lst.append( 3 ); | 127 | lst.append( 3 ); |
128 | 128 | ||
129 | lst.sort<Bu::__basicGTCmp<int> >(); | 129 | lst.sort<Bu::__basicGTCmp<int> >(); |
130 | 130 | ||
131 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); | 131 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); |
132 | } | 132 | } |
133 | 133 | ||
134 | test sort6 | 134 | test sort6 |
135 | { | 135 | { |
136 | IntList lst; | 136 | IntList lst; |
137 | 137 | ||
138 | lst.append( 5 ); | 138 | lst.append( 5 ); |
139 | lst.append( 1 ); | 139 | lst.append( 1 ); |
140 | lst.append( 10 ); | 140 | lst.append( 10 ); |
141 | lst.append( 3 ); | 141 | lst.append( 3 ); |
142 | 142 | ||
143 | Bu::__basicGTCmp<int> x; | 143 | Bu::__basicGTCmp<int> x; |
144 | lst.sort( x ); | 144 | lst.sort( x ); |
145 | 145 | ||
146 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); | 146 | unitTest( lst == IntList(10).append(5).append(3).append(1) ); |
147 | } | 147 | } |
148 | } | 148 | } |
diff --git a/src/unit/md5.unit b/src/unit/md5.unit index 248aaaf..aaba113 100644 --- a/src/unit/md5.unit +++ b/src/unit/md5.unit | |||
@@ -12,71 +12,71 @@ | |||
12 | 12 | ||
13 | suite Md5 | 13 | suite Md5 |
14 | { | 14 | { |
15 | test basics | 15 | test basics |
16 | { | 16 | { |
17 | #define tryStr( a, b ) \ | 17 | #define tryStr( a, b ) \ |
18 | { Bu::Md5 m; m.addData(a); unitTest( m.getHexResult() == b ); } (void)0 | 18 | { Bu::Md5 m; m.addData(a); unitTest( m.getHexResult() == b ); } (void)0 |
19 | tryStr("", "d41d8cd98f00b204e9800998ecf8427e"); | 19 | tryStr("", "d41d8cd98f00b204e9800998ecf8427e"); |
20 | tryStr("a", "0cc175b9c0f1b6a831c399e269772661"); | 20 | tryStr("a", "0cc175b9c0f1b6a831c399e269772661"); |
21 | tryStr("abc", "900150983cd24fb0d6963f7d28e17f72"); | 21 | tryStr("abc", "900150983cd24fb0d6963f7d28e17f72"); |
22 | tryStr("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); | 22 | tryStr("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); |
23 | tryStr("abcdefghijklmnopqrstuvwxyz", | 23 | tryStr("abcdefghijklmnopqrstuvwxyz", |
24 | "c3fcd3d76192e4007dfb496cca67e13b"); | 24 | "c3fcd3d76192e4007dfb496cca67e13b"); |
25 | tryStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", | 25 | tryStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", |
26 | "d174ab98d277d9f5a5611c2c9f419d9f"); | 26 | "d174ab98d277d9f5a5611c2c9f419d9f"); |
27 | tryStr("12345678901234567890123456789012345" | 27 | tryStr("12345678901234567890123456789012345" |
28 | "678901234567890123456789012345678901234567890", | 28 | "678901234567890123456789012345678901234567890", |
29 | "57edf4a22be3c955ac49da2e2107b67a"); | 29 | "57edf4a22be3c955ac49da2e2107b67a"); |
30 | } | 30 | } |
31 | 31 | ||
32 | test twoChunks | 32 | test twoChunks |
33 | { | 33 | { |
34 | Bu::Md5 m; | 34 | Bu::Md5 m; |
35 | m.addData("12345678901234567890123456789012345"); | 35 | m.addData("12345678901234567890123456789012345"); |
36 | m.addData("678901234567890123456789012345678901234567890"); | 36 | m.addData("678901234567890123456789012345678901234567890"); |
37 | unitTest( m.getHexResult() == "57edf4a22be3c955ac49da2e2107b67a" ); | 37 | unitTest( m.getHexResult() == "57edf4a22be3c955ac49da2e2107b67a" ); |
38 | } | 38 | } |
39 | 39 | ||
40 | test biggerBlocks | 40 | test biggerBlocks |
41 | { | 41 | { |
42 | const char *sums[33] = { | 42 | const char *sums[33] = { |
43 | "75fcf199abe516903321095a588b938d", | 43 | "75fcf199abe516903321095a588b938d", |
44 | "e26a863c96d6bdba6601175aedaae108", | 44 | "e26a863c96d6bdba6601175aedaae108", |
45 | "2b207fdcb222078d3ebfeb8d5e7c9315", | 45 | "2b207fdcb222078d3ebfeb8d5e7c9315", |
46 | "b08683aaa465add72cc2b43ae42f4f70", | 46 | "b08683aaa465add72cc2b43ae42f4f70", |
47 | "638bb73963b2d925771c3579ccb5e879", | 47 | "638bb73963b2d925771c3579ccb5e879", |
48 | "c727bd4b48a88e3df5924a2604de0790", | 48 | "c727bd4b48a88e3df5924a2604de0790", |
49 | "f33d21203c80490f7342e5853c5550eb", | 49 | "f33d21203c80490f7342e5853c5550eb", |
50 | "db449faca66a177aae59b1e36a19d053", | 50 | "db449faca66a177aae59b1e36a19d053", |
51 | "c800d429afb5f5c820f75c2c94e2e2bb", | 51 | "c800d429afb5f5c820f75c2c94e2e2bb", |
52 | "43b79c70b9a6a11e823ffbfa0f45a4db", | 52 | "43b79c70b9a6a11e823ffbfa0f45a4db", |
53 | "0177ffc483cf598ae3966b3a5ae00c8c", | 53 | "0177ffc483cf598ae3966b3a5ae00c8c", |
54 | "1a68fdf4b17a3820d48d101e9355a818" | 54 | "1a68fdf4b17a3820d48d101e9355a818" |
55 | }; | 55 | }; |
56 | 56 | ||
57 | char block[128]; | 57 | char block[128]; |
58 | for( int i = 0; i < 128; i++ ) | 58 | for( int i = 0; i < 128; i++ ) |
59 | block[i] = i*2; | 59 | block[i] = i*2; |
60 | 60 | ||
61 | const char **curSum = sums; | 61 | const char **curSum = sums; |
62 | for( int j = 1; j < 4096; j*=2 ) | 62 | for( int j = 1; j < 4096; j*=2 ) |
63 | { | 63 | { |
64 | /* | 64 | /* |
65 | Bu::File fOut("temp", Bu::File::WriteNew ); | 65 | Bu::File fOut("temp", Bu::File::WriteNew ); |
66 | for( int b = 0; b < j; b++ ) | 66 | for( int b = 0; b < j; b++ ) |
67 | { | 67 | { |
68 | fOut.write( block, 128 ); | 68 | fOut.write( block, 128 ); |
69 | } | 69 | } |
70 | fOut.close(); | 70 | fOut.close(); |
71 | system("md5sum -b temp"); | 71 | system("md5sum -b temp"); |
72 | */ | 72 | */ |
73 | Bu::Md5 m; | 73 | Bu::Md5 m; |
74 | for( int b = 0; b < j; b++ ) | 74 | for( int b = 0; b < j; b++ ) |
75 | { | 75 | { |
76 | m.addData( block, 128 ); | 76 | m.addData( block, 128 ); |
77 | } | 77 | } |
78 | unitTest( m.getHexResult() == *curSum ); | 78 | unitTest( m.getHexResult() == *curSum ); |
79 | curSum++; | 79 | curSum++; |
80 | } | 80 | } |
81 | } | 81 | } |
82 | } | 82 | } |
diff --git a/src/unit/membuf.unit b/src/unit/membuf.unit index 37ea77e..e5ee073 100644 --- a/src/unit/membuf.unit +++ b/src/unit/membuf.unit | |||
@@ -10,37 +10,37 @@ | |||
10 | 10 | ||
11 | suite MemBuf | 11 | suite MemBuf |
12 | { | 12 | { |
13 | test testWriteRead01 | 13 | test testWriteRead01 |
14 | { | 14 | { |
15 | Bu::MemBuf mb; | 15 | Bu::MemBuf mb; |
16 | unitTest( mb.write("ab", 2 ) == 2 ); | 16 | unitTest( mb.write("ab", 2 ) == 2 ); |
17 | unitTest( mb.write("cde", 3 ) == 3 ); | 17 | unitTest( mb.write("cde", 3 ) == 3 ); |
18 | unitTest( mb.write("FG", 2 ) == 2 ); | 18 | unitTest( mb.write("FG", 2 ) == 2 ); |
19 | 19 | ||
20 | mb.setPos( 0 ); | 20 | mb.setPos( 0 ); |
21 | 21 | ||
22 | char buf[8]; | 22 | char buf[8]; |
23 | buf[7] = '\0'; | 23 | buf[7] = '\0'; |
24 | unitTest( mb.read( buf, 7 ) == 7 ); | 24 | unitTest( mb.read( buf, 7 ) == 7 ); |
25 | unitTest( !strncmp( buf, "abcdeFG", 7 ) ); | 25 | unitTest( !strncmp( buf, "abcdeFG", 7 ) ); |
26 | unitTest( mb.read( buf, 7 ) == 0 ); | 26 | unitTest( mb.read( buf, 7 ) == 0 ); |
27 | mb.seek( -3 ); | 27 | mb.seek( -3 ); |
28 | unitTest( mb.read( buf, 7 ) == 3 ); | 28 | unitTest( mb.read( buf, 7 ) == 3 ); |
29 | unitTest( !strncmp( buf, "eFG", 3 ) ); | 29 | unitTest( !strncmp( buf, "eFG", 3 ) ); |
30 | } | 30 | } |
31 | 31 | ||
32 | test testOverwrite1 | 32 | test testOverwrite1 |
33 | { | 33 | { |
34 | Bu::MemBuf mb; | 34 | Bu::MemBuf mb; |
35 | unitTest( mb.write("0123456789") == 10 ); | 35 | unitTest( mb.write("0123456789") == 10 ); |
36 | mb.setPos( 4 ); | 36 | mb.setPos( 4 ); |
37 | unitTest( mb.write("-5-") == 3 ); | 37 | unitTest( mb.write("-5-") == 3 ); |
38 | mb.setPos( 9 ); | 38 | mb.setPos( 9 ); |
39 | mb.write("Hey!!!"); | 39 | mb.write("Hey!!!"); |
40 | unitTest( mb.tell() == 15 ); | 40 | unitTest( mb.tell() == 15 ); |
41 | char buf[50]; | 41 | char buf[50]; |
42 | mb.setPos( 0 ); | 42 | mb.setPos( 0 ); |
43 | buf[mb.read( buf, 50 )] = '\0'; | 43 | buf[mb.read( buf, 50 )] = '\0'; |
44 | unitTest( !strcmp( buf, "0123-5-78Hey!!!" ) ); | 44 | unitTest( !strcmp( buf, "0123-5-78Hey!!!" ) ); |
45 | } | 45 | } |
46 | } | 46 | } |
diff --git a/src/unit/myriad.unit b/src/unit/myriad.unit index 8c96f79..4960f38 100644 --- a/src/unit/myriad.unit +++ b/src/unit/myriad.unit | |||
@@ -26,360 +26,360 @@ class VerifyObject | |||
26 | friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ); | 26 | friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ); |
27 | friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ); | 27 | friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ); |
28 | public: | 28 | public: |
29 | VerifyObject( int iUnits ) : | 29 | VerifyObject( int iUnits ) : |
30 | iUnits( iUnits ), | 30 | iUnits( iUnits ), |
31 | iBytesWritten( 0 ) | 31 | iBytesWritten( 0 ) |
32 | { | 32 | { |
33 | } | 33 | } |
34 | 34 | ||
35 | virtual ~VerifyObject() | 35 | virtual ~VerifyObject() |
36 | { | 36 | { |
37 | } | 37 | } |
38 | 38 | ||
39 | int getBytesWritten() | 39 | int getBytesWritten() |
40 | { | 40 | { |
41 | return iBytesWritten; | 41 | return iBytesWritten; |
42 | } | 42 | } |
43 | 43 | ||
44 | private: | 44 | private: |
45 | int iUnits; | 45 | int iUnits; |
46 | mutable int iBytesWritten; | 46 | mutable int iBytesWritten; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ) | 49 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ) |
50 | { | 50 | { |
51 | Md5 sum; | 51 | Md5 sum; |
52 | ar << vo.iUnits; | 52 | ar << vo.iUnits; |
53 | vo.iBytesWritten = 4; | 53 | vo.iBytesWritten = 4; |
54 | sum.addData( &vo.iUnits, 4 ); | 54 | sum.addData( &vo.iUnits, 4 ); |
55 | for( int j = 0; j < vo.iUnits; j++ ) | 55 | for( int j = 0; j < vo.iUnits; j++ ) |
56 | { | 56 | { |
57 | int iRand = random()%128; | 57 | int iRand = random()%128; |
58 | // ar << iRand; | 58 | // ar << iRand; |
59 | Bu::String sDat( iRand ); | 59 | Bu::String sDat( iRand ); |
60 | for( int j = 0; j < iRand; j++ ) | 60 | for( int j = 0; j < iRand; j++ ) |
61 | sDat[j] = (char)((uint8_t)(random()%256)); | 61 | sDat[j] = (char)((uint8_t)(random()%256)); |
62 | ar << sDat; | 62 | ar << sDat; |
63 | sum.addData( &iRand, 4 ); | 63 | sum.addData( &iRand, 4 ); |
64 | sum.addData( sDat.getStr(), iRand ); | 64 | sum.addData( sDat.getStr(), iRand ); |
65 | vo.iBytesWritten += 4 + iRand; | 65 | vo.iBytesWritten += 4 + iRand; |
66 | } | 66 | } |
67 | Bu::String sRes = sum.getResult(); | 67 | Bu::String sRes = sum.getResult(); |
68 | ar << sRes; | 68 | ar << sRes; |
69 | vo.iBytesWritten += 4 + sRes.getSize(); | 69 | vo.iBytesWritten += 4 + sRes.getSize(); |
70 | return ar; | 70 | return ar; |
71 | } | 71 | } |
72 | 72 | ||
73 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ) | 73 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ) |
74 | { | 74 | { |
75 | Md5 sum; | 75 | Md5 sum; |
76 | ar >> vo.iUnits; | 76 | ar >> vo.iUnits; |
77 | sum.addData( &vo.iUnits, 4 ); | 77 | sum.addData( &vo.iUnits, 4 ); |
78 | for( int j = 0; j < vo.iUnits; j++ ) | 78 | for( int j = 0; j < vo.iUnits; j++ ) |
79 | { | 79 | { |
80 | int iRand; | 80 | int iRand; |
81 | // ar >> iRand; | 81 | // ar >> iRand; |
82 | Bu::String sStr; | 82 | Bu::String sStr; |
83 | ar >> sStr; | 83 | ar >> sStr; |
84 | iRand = sStr.getSize(); | 84 | iRand = sStr.getSize(); |
85 | sum.addData( &iRand, 4 ); | 85 | sum.addData( &iRand, 4 ); |
86 | sum.addData( sStr.getStr(), iRand ); | 86 | sum.addData( sStr.getStr(), iRand ); |
87 | } | 87 | } |
88 | Bu::String sSum; | 88 | Bu::String sSum; |
89 | ar >> sSum; | 89 | ar >> sSum; |
90 | unitTest( sSum == sum.getResult() ); | 90 | unitTest( sSum == sum.getResult() ); |
91 | int iTooMuch; | 91 | int iTooMuch; |
92 | try | 92 | try |
93 | { | 93 | { |
94 | ar >> iTooMuch; | 94 | ar >> iTooMuch; |
95 | unitFailed("should have thrown an exception."); | 95 | unitFailed("should have thrown an exception."); |
96 | } | 96 | } |
97 | catch( Bu::ExceptionBase &e ) | 97 | catch( Bu::ExceptionBase &e ) |
98 | { | 98 | { |
99 | } | 99 | } |
100 | return ar; | 100 | return ar; |
101 | } | 101 | } |
102 | 102 | ||
103 | suite Myriad | 103 | suite Myriad |
104 | { | 104 | { |
105 | test setSize | 105 | test setSize |
106 | { | 106 | { |
107 | String sFileName("myriad-XXXXXXX"); | 107 | String sFileName("myriad-XXXXXXX"); |
108 | 108 | ||
109 | File fMyriad = tempFile( sFileName ); | 109 | File fMyriad = tempFile( sFileName ); |
110 | Myriad m( fMyriad, 32 ); | 110 | Myriad m( fMyriad, 32 ); |
111 | 111 | ||
112 | MyriadStream ms = m.openStream( m.createStream() ); | 112 | MyriadStream ms = m.openStream( m.createStream() ); |
113 | ms.setSize( 150 ); | 113 | ms.setSize( 150 ); |
114 | ms.setPos( 145 ); | 114 | ms.setPos( 145 ); |
115 | char stuff[10]; | 115 | char stuff[10]; |
116 | unitTest( ms.read( stuff, 10 ) == 5 ); | 116 | unitTest( ms.read( stuff, 10 ) == 5 ); |
117 | 117 | ||
118 | ms.setSize( 12 ); | 118 | ms.setSize( 12 ); |
119 | unitTest( ms.read( stuff, 10 ) == 0 ); | 119 | unitTest( ms.read( stuff, 10 ) == 0 ); |
120 | unitTest( ms.write( "hello", 5 ) == 5 ); | 120 | unitTest( ms.write( "hello", 5 ) == 5 ); |
121 | unitTest( ms.tell() == 17 ); | 121 | unitTest( ms.tell() == 17 ); |
122 | 122 | ||
123 | ms.setSize( 500 ); | 123 | ms.setSize( 500 ); |
124 | unitTest( ms.tell() == 17 ); | 124 | unitTest( ms.tell() == 17 ); |
125 | } | 125 | } |
126 | 126 | ||
127 | void addBlock( Stream &s, bool bAppend=true ) | 127 | void addBlock( Stream &s, bool bAppend=true ) |
128 | { | 128 | { |
129 | if( bAppend ) | 129 | if( bAppend ) |
130 | s.setPosEnd( 0 ); | 130 | s.setPosEnd( 0 ); |
131 | int iSize = (random()%1016)+8; | 131 | int iSize = (random()%1016)+8; |
132 | s.write( &iSize, 4 ); | 132 | s.write( &iSize, 4 ); |
133 | char *buf = new char[iSize-8]; | 133 | char *buf = new char[iSize-8]; |
134 | for( int j = 0; j < iSize-8; j++ ) | 134 | for( int j = 0; j < iSize-8; j++ ) |
135 | { | 135 | { |
136 | buf[j] = (j+iSize)%256; | 136 | buf[j] = (j+iSize)%256; |
137 | } | 137 | } |
138 | if( random()%2 == 0 ) | 138 | if( random()%2 == 0 ) |
139 | { | 139 | { |
140 | s.write( buf, iSize-8 ); | 140 | s.write( buf, iSize-8 ); |
141 | } | 141 | } |
142 | else | 142 | else |
143 | { | 143 | { |
144 | for( int j = 0; j < iSize-8; ) | 144 | for( int j = 0; j < iSize-8; ) |
145 | { | 145 | { |
146 | int iAmnt = (random()%8)+1; | 146 | int iAmnt = (random()%8)+1; |
147 | if( iAmnt+j > iSize-8 ) | 147 | if( iAmnt+j > iSize-8 ) |
148 | iAmnt = iSize-8-j; | 148 | iAmnt = iSize-8-j; |
149 | iAmnt = s.write( buf+j, iAmnt ); | 149 | iAmnt = s.write( buf+j, iAmnt ); |
150 | j += iAmnt; | 150 | j += iAmnt; |
151 | } | 151 | } |
152 | } | 152 | } |
153 | delete[] buf; | 153 | delete[] buf; |
154 | iSize = ~iSize; | 154 | iSize = ~iSize; |
155 | s.write( &iSize, 4 ); | 155 | s.write( &iSize, 4 ); |
156 | } | 156 | } |
157 | 157 | ||
158 | void verifyBlock( Stream &s ) | 158 | void verifyBlock( Stream &s ) |
159 | { | 159 | { |
160 | int iSize, iInv; | 160 | int iSize, iInv; |
161 | if( s.read( &iSize, 4 ) == 0 ) | 161 | if( s.read( &iSize, 4 ) == 0 ) |
162 | return; | 162 | return; |
163 | if( iSize < 8 || iSize > 1024 ) | 163 | if( iSize < 8 || iSize > 1024 ) |
164 | throw ExceptionBase("Read bad data, %d", iSize ); | 164 | throw ExceptionBase("Read bad data, %d", iSize ); |
165 | char *buf = new char[iSize-8]; | 165 | char *buf = new char[iSize-8]; |
166 | if( s.read( buf, iSize-8 ) < (size_t)iSize-8 ) | 166 | if( s.read( buf, iSize-8 ) < (size_t)iSize-8 ) |
167 | { | 167 | { |
168 | delete[] buf; | 168 | delete[] buf; |
169 | throw ExceptionBase("Block failed verify (insuffient block data)."); | 169 | throw ExceptionBase("Block failed verify (insuffient block data)."); |
170 | } | 170 | } |
171 | for( int j = 0; j < iSize-8; j++ ) | 171 | for( int j = 0; j < iSize-8; j++ ) |
172 | { | 172 | { |
173 | if( buf[j] != (char)((j+iSize)%256) ) | 173 | if( buf[j] != (char)((j+iSize)%256) ) |
174 | { | 174 | { |
175 | char b = buf[j]; | 175 | char b = buf[j]; |
176 | delete[] buf; | 176 | delete[] buf; |
177 | throw ExceptionBase("Block failed computed data verify " | 177 | throw ExceptionBase("Block failed computed data verify " |
178 | "(%02X==%02X).", b, (char)((j+iSize)%256) ); | 178 | "(%02X==%02X).", b, (char)((j+iSize)%256) ); |
179 | } | 179 | } |
180 | } | 180 | } |
181 | delete[] buf; | 181 | delete[] buf; |
182 | if( s.read( &iInv, 4 ) < 4 ) | 182 | if( s.read( &iInv, 4 ) < 4 ) |
183 | throw ExceptionBase("Block failed verify (insufficient data)."); | 183 | throw ExceptionBase("Block failed verify (insufficient data)."); |
184 | if( iInv != ~iSize ) | 184 | if( iInv != ~iSize ) |
185 | throw ExceptionBase("Block failed inversion verify."); | 185 | throw ExceptionBase("Block failed inversion verify."); |
186 | } | 186 | } |
187 | 187 | ||
188 | void verifyStream( Stream &s ) | 188 | void verifyStream( Stream &s ) |
189 | { | 189 | { |
190 | s.setPos( 0 ); | 190 | s.setPos( 0 ); |
191 | while( !s.isEos() ) | 191 | while( !s.isEos() ) |
192 | verifyBlock( s ); | 192 | verifyBlock( s ); |
193 | } | 193 | } |
194 | 194 | ||
195 | test stressGrow | 195 | test stressGrow |
196 | { | 196 | { |
197 | String sFileName("myriad-XXXXXXX"); | 197 | String sFileName("myriad-XXXXXXX"); |
198 | 198 | ||
199 | File fMyriad = tempFile( sFileName ); | 199 | File fMyriad = tempFile( sFileName ); |
200 | Myriad m( fMyriad ); | 200 | Myriad m( fMyriad ); |
201 | m.initialize( 64 ); | 201 | m.initialize( 64 ); |
202 | 202 | ||
203 | Array<int> aStreams; | 203 | Array<int> aStreams; |
204 | for( int j = 0; j < 5; j++ ) | 204 | for( int j = 0; j < 5; j++ ) |
205 | { | 205 | { |
206 | aStreams.append( m.createStream() ); | 206 | aStreams.append( m.createStream() ); |
207 | } | 207 | } |
208 | 208 | ||
209 | srandom( 512 ); | 209 | srandom( 512 ); |
210 | 210 | ||
211 | for( int j = 0; j < 2500; j++ ) | 211 | for( int j = 0; j < 2500; j++ ) |
212 | { | 212 | { |
213 | switch( random()%5 ) | 213 | switch( random()%5 ) |
214 | { | 214 | { |
215 | case 0: | 215 | case 0: |
216 | aStreams.append( m.createStream() ); | 216 | aStreams.append( m.createStream() ); |
217 | break; | 217 | break; |
218 | 218 | ||
219 | case 1: | 219 | case 1: |
220 | if( aStreams.getSize() > 0 ) | 220 | if( aStreams.getSize() > 0 ) |
221 | { | 221 | { |
222 | int iStream = random()%aStreams.getSize(); | 222 | int iStream = random()%aStreams.getSize(); |
223 | { | 223 | { |
224 | MyriadStream ms = m.openStream( aStreams[iStream] ); | 224 | MyriadStream ms = m.openStream( aStreams[iStream] ); |
225 | verifyStream( ms ); | 225 | verifyStream( ms ); |
226 | } | 226 | } |
227 | m.deleteStream( aStreams[iStream] ); | 227 | m.deleteStream( aStreams[iStream] ); |
228 | Array<int>::iterator i = aStreams.begin(); | 228 | Array<int>::iterator i = aStreams.begin(); |
229 | for( int k = 0; k < iStream; k++ ) | 229 | for( int k = 0; k < iStream; k++ ) |
230 | i++; | 230 | i++; |
231 | aStreams.erase( i ); | 231 | aStreams.erase( i ); |
232 | } | 232 | } |
233 | break; | 233 | break; |
234 | 234 | ||
235 | default: | 235 | default: |
236 | if( aStreams.getSize() == 0 ) | 236 | if( aStreams.getSize() == 0 ) |
237 | { | 237 | { |
238 | aStreams.append( m.createStream() ); | 238 | aStreams.append( m.createStream() ); |
239 | } | 239 | } |
240 | { | 240 | { |
241 | int iStream = random()%aStreams.getSize(); | 241 | int iStream = random()%aStreams.getSize(); |
242 | MyriadStream ms = m.openStream( aStreams[iStream] ); | 242 | MyriadStream ms = m.openStream( aStreams[iStream] ); |
243 | addBlock( ms ); | 243 | addBlock( ms ); |
244 | verifyStream( ms ); | 244 | verifyStream( ms ); |
245 | } | 245 | } |
246 | break; | 246 | break; |
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | for( Array<int>::iterator i = aStreams.begin(); i; i++ ) | 250 | for( Array<int>::iterator i = aStreams.begin(); i; i++ ) |
251 | { | 251 | { |
252 | MyriadStream ms = m.openStream( *i ); | 252 | MyriadStream ms = m.openStream( *i ); |
253 | verifyStream( ms ); | 253 | verifyStream( ms ); |
254 | } | 254 | } |
255 | } | 255 | } |
256 | 256 | ||
257 | test stressTruncate | 257 | test stressTruncate |
258 | { | 258 | { |
259 | String sFileName("myriad-XXXXXXX"); | 259 | String sFileName("myriad-XXXXXXX"); |
260 | 260 | ||
261 | File fMyriad = tempFile( sFileName ); | 261 | File fMyriad = tempFile( sFileName ); |
262 | Myriad m( fMyriad ); | 262 | Myriad m( fMyriad ); |
263 | m.initialize( 128 ); | 263 | m.initialize( 128 ); |
264 | 264 | ||
265 | Array<int> aStream; | 265 | Array<int> aStream; |
266 | 266 | ||
267 | for( int j = 0; j < 5; j++ ) | 267 | for( int j = 0; j < 5; j++ ) |
268 | { | 268 | { |
269 | aStream.append( m.createStream() ); | 269 | aStream.append( m.createStream() ); |
270 | } | 270 | } |
271 | 271 | ||
272 | srandom( 1024 ); | 272 | srandom( 1024 ); |
273 | 273 | ||
274 | char b; | 274 | char b; |
275 | for( int iter = 0; iter < 2500; iter++ ) | 275 | for( int iter = 0; iter < 2500; iter++ ) |
276 | { | 276 | { |
277 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) | 277 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) |
278 | { | 278 | { |
279 | MyriadStream ms = m.openStream( *i ); | 279 | MyriadStream ms = m.openStream( *i ); |
280 | addBlock( ms, false ); | 280 | addBlock( ms, false ); |
281 | ms.setSize( ms.tell() ); | 281 | ms.setSize( ms.tell() ); |
282 | unitTest( ms.read( &b, 1 ) == 0 ); | 282 | unitTest( ms.read( &b, 1 ) == 0 ); |
283 | ms.setPos( 0 ); | 283 | ms.setPos( 0 ); |
284 | verifyBlock( ms ); | 284 | verifyBlock( ms ); |
285 | unitTest( ms.read( &b, 1 ) == 0 ); | 285 | unitTest( ms.read( &b, 1 ) == 0 ); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | test stressTruncate2 | 290 | test stressTruncate2 |
291 | { | 291 | { |
292 | String sFileName("myriad-XXXXXXX"); | 292 | String sFileName("myriad-XXXXXXX"); |
293 | 293 | ||
294 | Array<int> aStream; | 294 | Array<int> aStream; |
295 | 295 | ||
296 | setStepCount( 5*2500 + 5 ); | 296 | setStepCount( 5*2500 + 5 ); |
297 | 297 | ||
298 | { | 298 | { |
299 | File fMyriad = tempFile( sFileName ); | 299 | File fMyriad = tempFile( sFileName ); |
300 | Myriad m( fMyriad, 128 ); | 300 | Myriad m( fMyriad, 128 ); |
301 | 301 | ||
302 | for( int j = 0; j < 5; j++ ) | 302 | for( int j = 0; j < 5; j++ ) |
303 | { | 303 | { |
304 | aStream.append( m.createStream() ); | 304 | aStream.append( m.createStream() ); |
305 | incProgress(); | 305 | incProgress(); |
306 | } | 306 | } |
307 | } | 307 | } |
308 | 308 | ||
309 | srandom( 1024 ); | 309 | srandom( 1024 ); |
310 | 310 | ||
311 | char b; | 311 | char b; |
312 | for( int iter = 0; iter < 2500; iter++ ) | 312 | for( int iter = 0; iter < 2500; iter++ ) |
313 | { | 313 | { |
314 | File fMyriad( sFileName, File::ReadWrite ); | 314 | File fMyriad( sFileName, File::ReadWrite ); |
315 | Myriad m( fMyriad ); | 315 | Myriad m( fMyriad ); |
316 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) | 316 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) |
317 | { | 317 | { |
318 | MyriadStream ms = m.openStream( *i ); | 318 | MyriadStream ms = m.openStream( *i ); |
319 | addBlock( ms, false ); | 319 | addBlock( ms, false ); |
320 | ms.setSize( ms.tell() ); | 320 | ms.setSize( ms.tell() ); |
321 | unitTest( ms.read( &b, 1 ) == 0 ); | 321 | unitTest( ms.read( &b, 1 ) == 0 ); |
322 | ms.setPos( 0 ); | 322 | ms.setPos( 0 ); |
323 | verifyBlock( ms ); | 323 | verifyBlock( ms ); |
324 | unitTest( ms.read( &b, 1 ) == 0 ); | 324 | unitTest( ms.read( &b, 1 ) == 0 ); |
325 | incProgress(); | 325 | incProgress(); |
326 | } | 326 | } |
327 | } | 327 | } |
328 | } | 328 | } |
329 | 329 | ||
330 | test stressArchive | 330 | test stressArchive |
331 | { | 331 | { |
332 | String sFileName("myriad-XXXXXX"); | 332 | String sFileName("myriad-XXXXXX"); |
333 | Array<int> aStream; | 333 | Array<int> aStream; |
334 | 334 | ||
335 | srandom( 2096 ); | 335 | srandom( 2096 ); |
336 | 336 | ||
337 | setStepCount( 15*250 + 15 ); | 337 | setStepCount( 15*250 + 15 ); |
338 | 338 | ||
339 | { | 339 | { |
340 | File fMyriad = tempFile( sFileName ); | 340 | File fMyriad = tempFile( sFileName ); |
341 | Myriad m( fMyriad, 1024 ); | 341 | Myriad m( fMyriad, 1024 ); |
342 | 342 | ||
343 | for( int j = 0; j < 15; j++ ) | 343 | for( int j = 0; j < 15; j++ ) |
344 | { | 344 | { |
345 | int iStream = m.createStream(); | 345 | int iStream = m.createStream(); |
346 | aStream.append( iStream ); | 346 | aStream.append( iStream ); |
347 | VerifyObject vo( random()%1024 ); | 347 | VerifyObject vo( random()%1024 ); |
348 | { | 348 | { |
349 | MyriadStream ms = m.openStream( iStream ); | 349 | MyriadStream ms = m.openStream( iStream ); |
350 | Archive ar( ms, Archive::save ); | 350 | Archive ar( ms, Archive::save ); |
351 | ar << vo; | 351 | ar << vo; |
352 | unitTest( ms.tell() == vo.getBytesWritten() ); | 352 | unitTest( ms.tell() == vo.getBytesWritten() ); |
353 | ms.setSize( ms.tell() ); | 353 | ms.setSize( ms.tell() ); |
354 | } | 354 | } |
355 | unitTest( m.getStreamSize( iStream ) == vo.getBytesWritten() ); | 355 | unitTest( m.getStreamSize( iStream ) == vo.getBytesWritten() ); |
356 | incProgress(); | 356 | incProgress(); |
357 | } | 357 | } |
358 | } | 358 | } |
359 | 359 | ||
360 | for( int iter = 0; iter < 250; iter++ ) | 360 | for( int iter = 0; iter < 250; iter++ ) |
361 | { | 361 | { |
362 | File fMyriad( sFileName, File::ReadWrite ); | 362 | File fMyriad( sFileName, File::ReadWrite ); |
363 | Myriad m( fMyriad ); | 363 | Myriad m( fMyriad ); |
364 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) | 364 | for( Array<int>::iterator i = aStream.begin(); i; i++ ) |
365 | { | 365 | { |
366 | VerifyObject vo( random()%1024 ); | 366 | VerifyObject vo( random()%1024 ); |
367 | { | 367 | { |
368 | MyriadStream ms = m.openStream( *i ); | 368 | MyriadStream ms = m.openStream( *i ); |
369 | Archive ar( ms, Archive::load ); | 369 | Archive ar( ms, Archive::load ); |
370 | ar >> vo; | 370 | ar >> vo; |
371 | } | 371 | } |
372 | { | 372 | { |
373 | MyriadStream ms = m.openStream( *i ); | 373 | MyriadStream ms = m.openStream( *i ); |
374 | Archive ar( ms, Archive::save ); | 374 | Archive ar( ms, Archive::save ); |
375 | ar << vo; | 375 | ar << vo; |
376 | unitTest( ms.tell() == vo.getBytesWritten() ); | 376 | unitTest( ms.tell() == vo.getBytesWritten() ); |
377 | ms.setSize( ms.tell() ); | 377 | ms.setSize( ms.tell() ); |
378 | } | 378 | } |
379 | unitTest( m.getStreamSize( *i ) == vo.getBytesWritten() ); | 379 | unitTest( m.getStreamSize( *i ) == vo.getBytesWritten() ); |
380 | incProgress(); | 380 | incProgress(); |
381 | } | 381 | } |
382 | } | 382 | } |
383 | } | 383 | } |
384 | } | 384 | } |
385 | 385 | ||
diff --git a/src/unit/queuebuf.unit b/src/unit/queuebuf.unit index 553d9fc..bc55a04 100644 --- a/src/unit/queuebuf.unit +++ b/src/unit/queuebuf.unit | |||
@@ -16,89 +16,89 @@ | |||
16 | 16 | ||
17 | suite QueueBuf | 17 | suite QueueBuf |
18 | { | 18 | { |
19 | test testBasic01 | 19 | test testBasic01 |
20 | { | 20 | { |
21 | Bu::QueueBuf qb; | 21 | Bu::QueueBuf qb; |
22 | unitTest( qb.write("ab", 2 ) == 2 ); | 22 | unitTest( qb.write("ab", 2 ) == 2 ); |
23 | unitTest( qb.write("cde", 3 ) == 3 ); | 23 | unitTest( qb.write("cde", 3 ) == 3 ); |
24 | unitTest( qb.write("FG", 2 ) == 2 ); | 24 | unitTest( qb.write("FG", 2 ) == 2 ); |
25 | 25 | ||
26 | char buf[8]; | 26 | char buf[8]; |
27 | buf[7] = '\0'; | 27 | buf[7] = '\0'; |
28 | unitTest( qb.read( buf, 7 ) == 7 ); | 28 | unitTest( qb.read( buf, 7 ) == 7 ); |
29 | unitTest( !strncmp( buf, "abcdeFG", 7 ) ); | 29 | unitTest( !strncmp( buf, "abcdeFG", 7 ) ); |
30 | unitTest( qb.read( buf, 7 ) == 0 ); | 30 | unitTest( qb.read( buf, 7 ) == 0 ); |
31 | } | 31 | } |
32 | 32 | ||
33 | void QBUF_RANDSTR( Bu::String &fill, unsigned int iSize ) | 33 | void QBUF_RANDSTR( Bu::String &fill, unsigned int iSize ) |
34 | { | 34 | { |
35 | char c; | 35 | char c; |
36 | for( unsigned int i=0; i<iSize; ++i ) | 36 | for( unsigned int i=0; i<iSize; ++i ) |
37 | { | 37 | { |
38 | c = RNDCHR; | 38 | c = RNDCHR; |
39 | fill.append(&c,1); | 39 | fill.append(&c,1); |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | test testAmounts | 43 | test testAmounts |
44 | { | 44 | { |
45 | srandom(time(NULL)); | 45 | srandom(time(NULL)); |
46 | Bu::QueueBuf qb; | 46 | Bu::QueueBuf qb; |
47 | Bu::String sTmp; | 47 | Bu::String sTmp; |
48 | char buf[4096]; | 48 | char buf[4096]; |
49 | 49 | ||
50 | for( int i=0; i<200; ++i ) | 50 | for( int i=0; i<200; ++i ) |
51 | { | 51 | { |
52 | unsigned int iAmt = (int)RNDCHR+128; | 52 | unsigned int iAmt = (int)RNDCHR+128; |
53 | sTmp.clear(); | 53 | sTmp.clear(); |
54 | QBUF_RANDSTR( sTmp, iAmt ); | 54 | QBUF_RANDSTR( sTmp, iAmt ); |
55 | unitTest( qb.write( sTmp.getStr(), sTmp.getSize() ) == | 55 | unitTest( qb.write( sTmp.getStr(), sTmp.getSize() ) == |
56 | (uint32_t)sTmp.getSize() ); | 56 | (uint32_t)sTmp.getSize() ); |
57 | size_t iRead = qb.read( buf, 4096 ); | 57 | size_t iRead = qb.read( buf, 4096 ); |
58 | unitTest( iRead == iAmt ); | 58 | unitTest( iRead == iAmt ); |
59 | } | 59 | } |
60 | } | 60 | } |
61 | 61 | ||
62 | void QBUF_HEXOUT( const char *s, int iSize ) | 62 | void QBUF_HEXOUT( const char *s, int iSize ) |
63 | { | 63 | { |
64 | for( int i=0; i<iSize; ++i ) | 64 | for( int i=0; i<iSize; ++i ) |
65 | printf("%02x",(int)(uint8_t)s[i]); | 65 | printf("%02x",(int)(uint8_t)s[i]); |
66 | } | 66 | } |
67 | 67 | ||
68 | void QBUF_HASH( Bu::String &fill, const char *s, int iSize ) | 68 | void QBUF_HASH( Bu::String &fill, const char *s, int iSize ) |
69 | { | 69 | { |
70 | Bu::Md5 hash; | 70 | Bu::Md5 hash; |
71 | hash.reset(); | 71 | hash.reset(); |
72 | hash.addData( s, iSize ); | 72 | hash.addData( s, iSize ); |
73 | const Bu::String &sTmp = hash.getResult(); | 73 | const Bu::String &sTmp = hash.getResult(); |
74 | fill.append( sTmp.getStr(), 16 ); | 74 | fill.append( sTmp.getStr(), 16 ); |
75 | } | 75 | } |
76 | 76 | ||
77 | test testRandomData | 77 | test testRandomData |
78 | { | 78 | { |
79 | srandom(time(NULL)); | 79 | srandom(time(NULL)); |
80 | Bu::QueueBuf qb; | 80 | Bu::QueueBuf qb; |
81 | Bu::String sTmp; | 81 | Bu::String sTmp; |
82 | Bu::String sTmp2; | 82 | Bu::String sTmp2; |
83 | char buf[4096]; | 83 | char buf[4096]; |
84 | 84 | ||
85 | for( int i=0; i<200; ++i ) | 85 | for( int i=0; i<200; ++i ) |
86 | { | 86 | { |
87 | uint32_t iAmt = (uint32_t)RNDCHR+128; | 87 | uint32_t iAmt = (uint32_t)RNDCHR+128; |
88 | sTmp.clear(); | 88 | sTmp.clear(); |
89 | sTmp.append( (const char *)&iAmt, 4 ); | 89 | sTmp.append( (const char *)&iAmt, 4 ); |
90 | QBUF_RANDSTR( sTmp, iAmt ); | 90 | QBUF_RANDSTR( sTmp, iAmt ); |
91 | sTmp2.clear(); | 91 | sTmp2.clear(); |
92 | QBUF_HASH( sTmp2, sTmp.getStr()+4, iAmt ); | 92 | QBUF_HASH( sTmp2, sTmp.getStr()+4, iAmt ); |
93 | sTmp.append( sTmp2 ); | 93 | sTmp.append( sTmp2 ); |
94 | unitTest( qb.write( sTmp.getStr(), sTmp.getSize() ) == | 94 | unitTest( qb.write( sTmp.getStr(), sTmp.getSize() ) == |
95 | (uint32_t)sTmp.getSize() ); | 95 | (uint32_t)sTmp.getSize() ); |
96 | size_t iRead = qb.read( buf, 4096 ); | 96 | size_t iRead = qb.read( buf, 4096 ); |
97 | uint32_t iGotSize = *((uint32_t *)buf); | 97 | uint32_t iGotSize = *((uint32_t *)buf); |
98 | unitTest( iRead == iGotSize+4+16 ); | 98 | unitTest( iRead == iGotSize+4+16 ); |
99 | sTmp2.clear(); | 99 | sTmp2.clear(); |
100 | QBUF_HASH( sTmp2, buf+4, iGotSize ); | 100 | QBUF_HASH( sTmp2, buf+4, iGotSize ); |
101 | unitTest( !strncmp(sTmp2.getStr(),buf+4+iGotSize,16) ); | 101 | unitTest( !strncmp(sTmp2.getStr(),buf+4+iGotSize,16) ); |
102 | } | 102 | } |
103 | } | 103 | } |
104 | } | 104 | } |
diff --git a/src/unit/sha1.unit b/src/unit/sha1.unit index d91b4c3..1151cfb 100644 --- a/src/unit/sha1.unit +++ b/src/unit/sha1.unit | |||
@@ -12,65 +12,65 @@ | |||
12 | 12 | ||
13 | suite Sha1 | 13 | suite Sha1 |
14 | { | 14 | { |
15 | test basics | 15 | test basics |
16 | { | 16 | { |
17 | #define tryStr( a, b ) \ | 17 | #define tryStr( a, b ) \ |
18 | { Bu::Sha1 m; m.addData(a); unitTest( m.getHexResult() == b ); } (void)0 | 18 | { Bu::Sha1 m; m.addData(a); unitTest( m.getHexResult() == b ); } (void)0 |
19 | tryStr("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); | 19 | tryStr("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); |
20 | tryStr("The quick brown fox jumps over the lazy dog", | 20 | tryStr("The quick brown fox jumps over the lazy dog", |
21 | "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); | 21 | "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); |
22 | tryStr("The quick brown fox jumps over the lazy cog", | 22 | tryStr("The quick brown fox jumps over the lazy cog", |
23 | "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"); | 23 | "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"); |
24 | } | 24 | } |
25 | 25 | ||
26 | test twoChunks | 26 | test twoChunks |
27 | { | 27 | { |
28 | Bu::Sha1 m; | 28 | Bu::Sha1 m; |
29 | m.addData("The quick brown fo"); | 29 | m.addData("The quick brown fo"); |
30 | m.addData("x jumps over the lazy dog"); | 30 | m.addData("x jumps over the lazy dog"); |
31 | unitTest( m.getHexResult() == "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" ); | 31 | unitTest( m.getHexResult() == "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" ); |
32 | } | 32 | } |
33 | 33 | ||
34 | test biggerBlocks | 34 | test biggerBlocks |
35 | { | 35 | { |
36 | const char *sums[41] = { | 36 | const char *sums[41] = { |
37 | "2356aab95478d8e3c2c918e36f383e46d06154c7", | 37 | "2356aab95478d8e3c2c918e36f383e46d06154c7", |
38 | "e3f663240c185a95111c4e00e20865dfbda390aa", | 38 | "e3f663240c185a95111c4e00e20865dfbda390aa", |
39 | "3f21881040b42f44476b610b6d2191f72afc1cb5", | 39 | "3f21881040b42f44476b610b6d2191f72afc1cb5", |
40 | "493fe9da6de598c52ea56962b15ccc4405a8dfda", | 40 | "493fe9da6de598c52ea56962b15ccc4405a8dfda", |
41 | "4684ff568f7c1198a258eb04d88209f4feab4e05", | 41 | "4684ff568f7c1198a258eb04d88209f4feab4e05", |
42 | "614101c1c164b8b6099f63165ea01078cbb6c77f", | 42 | "614101c1c164b8b6099f63165ea01078cbb6c77f", |
43 | "393f1c1a9f6384653029ab807756e85a13147029", | 43 | "393f1c1a9f6384653029ab807756e85a13147029", |
44 | "fd66443d68f8b0508b4f125f2cff1192bfc01913", | 44 | "fd66443d68f8b0508b4f125f2cff1192bfc01913", |
45 | "1ef66120e530731194554bb2cd51293779a0bcc7", | 45 | "1ef66120e530731194554bb2cd51293779a0bcc7", |
46 | "d77e0eda0037f51b0b6c197371c5fd801cc0eede", | 46 | "d77e0eda0037f51b0b6c197371c5fd801cc0eede", |
47 | "ce8b579bd3aa2ccac2e0205f52a8ed03777117ac", | 47 | "ce8b579bd3aa2ccac2e0205f52a8ed03777117ac", |
48 | "d9e9d7fc411de2f89329ab758dc8f4302f80ff23" | 48 | "d9e9d7fc411de2f89329ab758dc8f4302f80ff23" |
49 | }; | 49 | }; |
50 | 50 | ||
51 | char block[128]; | 51 | char block[128]; |
52 | for( int i = 0; i < 128; i++ ) | 52 | for( int i = 0; i < 128; i++ ) |
53 | block[i] = i*2; | 53 | block[i] = i*2; |
54 | 54 | ||
55 | const char **curSum = sums; | 55 | const char **curSum = sums; |
56 | for( int j = 1; j < 4096; j*=2 ) | 56 | for( int j = 1; j < 4096; j*=2 ) |
57 | { | 57 | { |
58 | /* | 58 | /* |
59 | Bu::File fOut("temp", Bu::File::WriteNew ); | 59 | Bu::File fOut("temp", Bu::File::WriteNew ); |
60 | for( int b = 0; b < j; b++ ) | 60 | for( int b = 0; b < j; b++ ) |
61 | { | 61 | { |
62 | fOut.write( block, 128 ); | 62 | fOut.write( block, 128 ); |
63 | } | 63 | } |
64 | fOut.close(); | 64 | fOut.close(); |
65 | system("sha1sum -b temp"); | 65 | system("sha1sum -b temp"); |
66 | */ | 66 | */ |
67 | Bu::Sha1 m; | 67 | Bu::Sha1 m; |
68 | for( int b = 0; b < j; b++ ) | 68 | for( int b = 0; b < j; b++ ) |
69 | { | 69 | { |
70 | m.addData( block, 128 ); | 70 | m.addData( block, 128 ); |
71 | } | 71 | } |
72 | unitTest( m.getHexResult() == *curSum ); | 72 | unitTest( m.getHexResult() == *curSum ); |
73 | curSum++; | 73 | curSum++; |
74 | } | 74 | } |
75 | } | 75 | } |
76 | } | 76 | } |
diff --git a/src/unit/string.unit b/src/unit/string.unit index 4ea878e..ddd89a6 100644 --- a/src/unit/string.unit +++ b/src/unit/string.unit | |||
@@ -12,580 +12,580 @@ | |||
12 | 12 | ||
13 | suite String | 13 | suite String |
14 | { | 14 | { |
15 | test compare1 | 15 | test compare1 |
16 | { | 16 | { |
17 | Bu::String b("Bob"); | 17 | Bu::String b("Bob"); |
18 | unitTest( !(b == "Bobo") ); | 18 | unitTest( !(b == "Bobo") ); |
19 | unitTest( b == "Bob" ); | 19 | unitTest( b == "Bob" ); |
20 | } | 20 | } |
21 | 21 | ||
22 | test compare2 | 22 | test compare2 |
23 | { | 23 | { |
24 | Bu::String b("Bobo"); | 24 | Bu::String b("Bobo"); |
25 | unitTest( !(b == "Bob") ); | 25 | unitTest( !(b == "Bob") ); |
26 | unitTest( b == "Bobo" ); | 26 | unitTest( b == "Bobo" ); |
27 | } | 27 | } |
28 | 28 | ||
29 | test appendSingle | 29 | test appendSingle |
30 | { | 30 | { |
31 | Bu::String b; | 31 | Bu::String b; |
32 | for( char l = 'a'; l < 'g'; l++ ) | 32 | for( char l = 'a'; l < 'g'; l++ ) |
33 | b += l; | 33 | b += l; |
34 | unitTest( b == "abcdef" ); | 34 | unitTest( b == "abcdef" ); |
35 | unitTest( strcmp( b.getStr(), "abcdef" ) == 0 ); | 35 | unitTest( strcmp( b.getStr(), "abcdef" ) == 0 ); |
36 | } | 36 | } |
37 | 37 | ||
38 | test shared1 | 38 | test shared1 |
39 | { | 39 | { |
40 | Bu::String a("Hey there"); | 40 | Bu::String a("Hey there"); |
41 | Bu::String b( a ); | 41 | Bu::String b( a ); |
42 | unitTest( a.getConstStr() == b.getConstStr() ); | 42 | unitTest( a.getConstStr() == b.getConstStr() ); |
43 | b += " guy"; | 43 | b += " guy"; |
44 | unitTest( a.getConstStr() != b.getConstStr() ); | 44 | unitTest( a.getConstStr() != b.getConstStr() ); |
45 | a = b; | 45 | a = b; |
46 | unitTest( a.getConstStr() == b.getConstStr() ); | 46 | unitTest( a.getConstStr() == b.getConstStr() ); |
47 | } | 47 | } |
48 | 48 | ||
49 | test insert | 49 | test insert |
50 | { | 50 | { |
51 | Bu::String a("abcd"); | 51 | Bu::String a("abcd"); |
52 | a.insert( 2, "-!-", 3 ); | 52 | a.insert( 2, "-!-", 3 ); |
53 | unitTest( a == "ab-!-cd" ); | 53 | unitTest( a == "ab-!-cd" ); |
54 | 54 | ||
55 | a.insert( 0, "!!", 2 ); | 55 | a.insert( 0, "!!", 2 ); |
56 | unitTest( a == "!!ab-!-cd" ); | 56 | unitTest( a == "!!ab-!-cd" ); |
57 | 57 | ||
58 | a.insert( -10, "789", 3 ); | 58 | a.insert( -10, "789", 3 ); |
59 | unitTest( a == "789!!ab-!-cd" ); | 59 | unitTest( a == "789!!ab-!-cd" ); |
60 | 60 | ||
61 | a.insert( 12, "89", 2 ); | 61 | a.insert( 12, "89", 2 ); |
62 | unitTest( a == "789!!ab-!-cd89" ); | 62 | unitTest( a == "789!!ab-!-cd89" ); |
63 | 63 | ||
64 | a.insert( 1203, "12", 2 ); | 64 | a.insert( 1203, "12", 2 ); |
65 | unitTest( a == "789!!ab-!-cd8912" ); | 65 | unitTest( a == "789!!ab-!-cd8912" ); |
66 | } | 66 | } |
67 | 67 | ||
68 | test remove | 68 | test remove |
69 | { | 69 | { |
70 | Bu::String a("abHEYcd"); | 70 | Bu::String a("abHEYcd"); |
71 | a.remove( 2, 3 ); | 71 | a.remove( 2, 3 ); |
72 | unitTest( a == "abcd" ); | 72 | unitTest( a == "abcd" ); |
73 | a.remove( 2, 5 ); | 73 | a.remove( 2, 5 ); |
74 | unitTest( a == "ab" ); | 74 | unitTest( a == "ab" ); |
75 | a += "cdefghijklmnop"; | 75 | a += "cdefghijklmnop"; |
76 | a.remove( 5, 1 ); | 76 | a.remove( 5, 1 ); |
77 | unitTest( a == "abcdeghijklmnop" ); | 77 | unitTest( a == "abcdeghijklmnop" ); |
78 | } | 78 | } |
79 | 79 | ||
80 | test add1 | 80 | test add1 |
81 | { | 81 | { |
82 | Bu::String a("hi there"); | 82 | Bu::String a("hi there"); |
83 | Bu::String b(", yeah!"); | 83 | Bu::String b(", yeah!"); |
84 | Bu::String c = a + b; | 84 | Bu::String c = a + b; |
85 | 85 | ||
86 | unitTest( c == "hi there, yeah!" ); | 86 | unitTest( c == "hi there, yeah!" ); |
87 | } | 87 | } |
88 | 88 | ||
89 | test add2 | 89 | test add2 |
90 | { | 90 | { |
91 | Bu::String a("hi there"); | 91 | Bu::String a("hi there"); |
92 | Bu::String c = a + ", yeah!"; | 92 | Bu::String c = a + ", yeah!"; |
93 | 93 | ||
94 | unitTest( c == "hi there, yeah!" ); | 94 | unitTest( c == "hi there, yeah!" ); |
95 | } | 95 | } |
96 | 96 | ||
97 | test add3 | 97 | test add3 |
98 | { | 98 | { |
99 | Bu::String a("hi there"); | 99 | Bu::String a("hi there"); |
100 | Bu::String b(", yeah!"); | 100 | Bu::String b(", yeah!"); |
101 | Bu::String c = a + ", Mr. Man" + b; | 101 | Bu::String c = a + ", Mr. Man" + b; |
102 | 102 | ||
103 | unitTest( c == "hi there, Mr. Man, yeah!" ); | 103 | unitTest( c == "hi there, Mr. Man, yeah!" ); |
104 | } | 104 | } |
105 | 105 | ||
106 | test add4 | 106 | test add4 |
107 | { | 107 | { |
108 | Bu::String b(", yeah!"); | 108 | Bu::String b(", yeah!"); |
109 | Bu::String c = "hi there" + b; | 109 | Bu::String c = "hi there" + b; |
110 | 110 | ||
111 | unitTest( c == "hi there, yeah!" ); | 111 | unitTest( c == "hi there, yeah!" ); |
112 | } | 112 | } |
113 | 113 | ||
114 | test add5 | 114 | test add5 |
115 | { | 115 | { |
116 | Bu::String b; | 116 | Bu::String b; |
117 | Bu::String c = "sup?"; | 117 | Bu::String c = "sup?"; |
118 | b += "hey, " + c; | 118 | b += "hey, " + c; |
119 | 119 | ||
120 | unitTest( b == "hey, sup?" ); | 120 | unitTest( b == "hey, sup?" ); |
121 | } | 121 | } |
122 | 122 | ||
123 | test add6 | 123 | test add6 |
124 | { | 124 | { |
125 | Bu::String a("Hello"); | 125 | Bu::String a("Hello"); |
126 | char b[256] = {"Dude"}; | 126 | char b[256] = {"Dude"}; |
127 | Bu::String c = a + "/" + b; | 127 | Bu::String c = a + "/" + b; |
128 | 128 | ||
129 | unitTest( c == "Hello/Dude" ); | 129 | unitTest( c == "Hello/Dude" ); |
130 | } | 130 | } |
131 | 131 | ||
132 | test add7 | 132 | test add7 |
133 | { | 133 | { |
134 | const Bu::String a("hello "); | 134 | const Bu::String a("hello "); |
135 | Bu::String b(" how "); | 135 | Bu::String b(" how "); |
136 | unitTest( a == "hello " ); | 136 | unitTest( a == "hello " ); |
137 | unitTest( a + "dude" == "hello dude" ); | 137 | unitTest( a + "dude" == "hello dude" ); |
138 | unitTest( a + "dude" + b + "are you?" == "hello dude how are you?" ); | 138 | unitTest( a + "dude" + b + "are you?" == "hello dude how are you?" ); |
139 | } | 139 | } |
140 | 140 | ||
141 | test subStr1 | 141 | test subStr1 |
142 | { | 142 | { |
143 | Bu::String a("abcdefghijklmnop"); | 143 | Bu::String a("abcdefghijklmnop"); |
144 | Bu::String::iterator i = a.find('f'); | 144 | Bu::String::iterator i = a.find('f'); |
145 | unitTest( a.getSubStr( i, Bu::String::iterator() ) == "fghijklmnop" ); | 145 | unitTest( a.getSubStr( i, Bu::String::iterator() ) == "fghijklmnop" ); |
146 | Bu::String::iterator j = i.find('l'); | 146 | Bu::String::iterator j = i.find('l'); |
147 | unitTest( a.getSubStr( i, j ) == "fghijk" ); | 147 | unitTest( a.getSubStr( i, j ) == "fghijk" ); |
148 | } | 148 | } |
149 | 149 | ||
150 | test compareSub1 | 150 | test compareSub1 |
151 | { | 151 | { |
152 | Bu::String a("just a string."); | 152 | Bu::String a("just a string."); |
153 | unitTest( a.compareSub("a ", 5, 2) == true ); | 153 | unitTest( a.compareSub("a ", 5, 2) == true ); |
154 | unitTest( a.compareSub("string.aoeu", 7, 11 ) == false ); | 154 | unitTest( a.compareSub("string.aoeu", 7, 11 ) == false ); |
155 | unitTest( a.compareSub("string.aoeu", 7, 3 ) == true ); | 155 | unitTest( a.compareSub("string.aoeu", 7, 3 ) == true ); |
156 | } | 156 | } |
157 | 157 | ||
158 | test compareSub2 | 158 | test compareSub2 |
159 | { | 159 | { |
160 | Bu::String a("just a string."); | 160 | Bu::String a("just a string."); |
161 | unitTest( a.compareSub(Bu::String("a "), 5, 2) == true ); | 161 | unitTest( a.compareSub(Bu::String("a "), 5, 2) == true ); |
162 | unitTest( a.compareSub(Bu::String("string.aoeu"), 7, 11 ) == false ); | 162 | unitTest( a.compareSub(Bu::String("string.aoeu"), 7, 11 ) == false ); |
163 | unitTest( a.compareSub(Bu::String("string.aoeu"), 7, 3 ) == true ); | 163 | unitTest( a.compareSub(Bu::String("string.aoeu"), 7, 3 ) == true ); |
164 | } | 164 | } |
165 | 165 | ||
166 | test iterator1 | 166 | test iterator1 |
167 | { | 167 | { |
168 | Bu::String a("This is a test."); | 168 | Bu::String a("This is a test."); |
169 | Bu::String b; | 169 | Bu::String b; |
170 | for( Bu::String::iterator i = a.begin(); i; i++ ) | 170 | for( Bu::String::iterator i = a.begin(); i; i++ ) |
171 | { | 171 | { |
172 | b += *i; | 172 | b += *i; |
173 | } | 173 | } |
174 | unitTest( a == b ); | 174 | unitTest( a == b ); |
175 | } | 175 | } |
176 | 176 | ||
177 | test iteratorCompare1 | 177 | test iteratorCompare1 |
178 | { | 178 | { |
179 | Bu::String a("This is a test."); | 179 | Bu::String a("This is a test."); |
180 | Bu::String b("--This is a test."); | 180 | Bu::String b("--This is a test."); |
181 | Bu::String::iterator ai = a.begin(); | 181 | Bu::String::iterator ai = a.begin(); |
182 | Bu::String::iterator bi = b.begin(); | 182 | Bu::String::iterator bi = b.begin(); |
183 | unitTest( ai.compare( bi ) == false ); | 183 | unitTest( ai.compare( bi ) == false ); |
184 | unitTest( bi.compare( ai ) == false ); | 184 | unitTest( bi.compare( ai ) == false ); |
185 | bi++; bi++; | 185 | bi++; bi++; |
186 | unitTest( ai.compare( bi ) == true ); | 186 | unitTest( ai.compare( bi ) == true ); |
187 | unitTest( bi.compare( ai ) == true ); | 187 | unitTest( bi.compare( ai ) == true ); |
188 | b += "hi"; | 188 | b += "hi"; |
189 | unitTest( ai.compare( bi ) == false ); | 189 | unitTest( ai.compare( bi ) == false ); |
190 | unitTest( bi.compare( ai ) == false ); | 190 | unitTest( bi.compare( ai ) == false ); |
191 | } | 191 | } |
192 | 192 | ||
193 | test iteratorCompare2 | 193 | test iteratorCompare2 |
194 | { | 194 | { |
195 | Bu::String a("1234honour"); | 195 | Bu::String a("1234honour"); |
196 | Bu::String b("--1234ueje"); | 196 | Bu::String b("--1234ueje"); |
197 | Bu::String::iterator ai = a.begin(); | 197 | Bu::String::iterator ai = a.begin(); |
198 | Bu::String::iterator bi = b.begin(); | 198 | Bu::String::iterator bi = b.begin(); |
199 | unitTest( ai.compare( bi, 4 ) == false ); | 199 | unitTest( ai.compare( bi, 4 ) == false ); |
200 | unitTest( bi.compare( ai, 4 ) == false ); | 200 | unitTest( bi.compare( ai, 4 ) == false ); |
201 | bi++; bi++; | 201 | bi++; bi++; |
202 | unitTest( ai.compare( bi, 4 ) == true ); | 202 | unitTest( ai.compare( bi, 4 ) == true ); |
203 | unitTest( bi.compare( ai, 4 ) == true ); | 203 | unitTest( bi.compare( ai, 4 ) == true ); |
204 | unitTest( ai.compare( bi, 5 ) == false ); | 204 | unitTest( ai.compare( bi, 5 ) == false ); |
205 | unitTest( bi.compare( ai, 5 ) == false ); | 205 | unitTest( bi.compare( ai, 5 ) == false ); |
206 | 206 | ||
207 | a = "fell"; | 207 | a = "fell"; |
208 | b = "-felloo"; | 208 | b = "-felloo"; |
209 | ai = a.begin(); | 209 | ai = a.begin(); |
210 | bi = b.begin()+1; | 210 | bi = b.begin()+1; |
211 | unitTest( ai.compare( bi, 4 ) == true ); | 211 | unitTest( ai.compare( bi, 4 ) == true ); |
212 | ai++; | 212 | ai++; |
213 | bi++; | 213 | bi++; |
214 | unitTest( ai.compare( bi, 4 ) == false ); | 214 | unitTest( ai.compare( bi, 4 ) == false ); |
215 | } | 215 | } |
216 | 216 | ||
217 | test iteratorCompare3 | 217 | test iteratorCompare3 |
218 | { | 218 | { |
219 | Bu::String a("1234aoeu"); | 219 | Bu::String a("1234aoeu"); |
220 | Bu::String::iterator ai = a.begin(); | 220 | Bu::String::iterator ai = a.begin(); |
221 | unitTest( ai.compare("1234") == false ); | 221 | unitTest( ai.compare("1234") == false ); |
222 | unitTest( ai.compare("1234aoeu") == true ); | 222 | unitTest( ai.compare("1234aoeu") == true ); |
223 | unitTest( ai.compare("1234aoeuee") == false ); | 223 | unitTest( ai.compare("1234aoeuee") == false ); |
224 | ai += 4; | 224 | ai += 4; |
225 | unitTest( ai.compare("aoeu") == true ); | 225 | unitTest( ai.compare("aoeu") == true ); |
226 | unitTest( ai.compare("aoeubo") == false ); | 226 | unitTest( ai.compare("aoeubo") == false ); |
227 | unitTest( ai.compare("aoe") == false ); | 227 | unitTest( ai.compare("aoe") == false ); |
228 | unitTest( ai.compare("wrong") == false ); | 228 | unitTest( ai.compare("wrong") == false ); |
229 | unitTest( ai.compare("boeu") == false ); | 229 | unitTest( ai.compare("boeu") == false ); |
230 | } | 230 | } |
231 | 231 | ||
232 | test iteratorCompare4 | 232 | test iteratorCompare4 |
233 | { | 233 | { |
234 | Bu::String a("1234aoeu"); | 234 | Bu::String a("1234aoeu"); |
235 | Bu::String::iterator ai = a.begin(); | 235 | Bu::String::iterator ai = a.begin(); |
236 | unitTest( ai.compare("1234", 4) == true ); | 236 | unitTest( ai.compare("1234", 4) == true ); |
237 | unitTest( ai.compare("1234aoeu", 8) == true ); | 237 | unitTest( ai.compare("1234aoeu", 8) == true ); |
238 | unitTest( ai.compare("1234aoeuee", 10) == false ); | 238 | unitTest( ai.compare("1234aoeuee", 10) == false ); |
239 | } | 239 | } |
240 | 240 | ||
241 | test iteratorCompare5 | 241 | test iteratorCompare5 |
242 | { | 242 | { |
243 | Bu::String a("1234aoeu"); | 243 | Bu::String a("1234aoeu"); |
244 | Bu::String b("34ao"); | 244 | Bu::String b("34ao"); |
245 | Bu::String::iterator ai = a.begin(); | 245 | Bu::String::iterator ai = a.begin(); |
246 | unitTest( ai.compare( b ) == false ); | 246 | unitTest( ai.compare( b ) == false ); |
247 | ai += 2; | 247 | ai += 2; |
248 | unitTest( ai.compare( b ) == false ); | 248 | unitTest( ai.compare( b ) == false ); |
249 | b = "oeu"; | 249 | b = "oeu"; |
250 | ai += 3; | 250 | ai += 3; |
251 | unitTest( ai.compare( b ) == true ); | 251 | unitTest( ai.compare( b ) == true ); |
252 | b += "boo"; | 252 | b += "boo"; |
253 | unitTest( ai.compare( b ) == false ); | 253 | unitTest( ai.compare( b ) == false ); |
254 | } | 254 | } |
255 | 255 | ||
256 | test iteratorCompare6 | 256 | test iteratorCompare6 |
257 | { | 257 | { |
258 | Bu::String a("1234aoeu"); | 258 | Bu::String a("1234aoeu"); |
259 | Bu::String::iterator ai = a.begin(); | 259 | Bu::String::iterator ai = a.begin(); |
260 | unitTest( ai.compare( Bu::String("1234"), 4) == true ); | 260 | unitTest( ai.compare( Bu::String("1234"), 4) == true ); |
261 | unitTest( ai.compare( Bu::String("1234aoeu"), 8) == true ); | 261 | unitTest( ai.compare( Bu::String("1234aoeu"), 8) == true ); |
262 | unitTest( ai.compare( Bu::String("1234aoeuee"), 10) == false ); | 262 | unitTest( ai.compare( Bu::String("1234aoeuee"), 10) == false ); |
263 | } | 263 | } |
264 | 264 | ||
265 | test const_iteratorCompare1 | 265 | test const_iteratorCompare1 |
266 | { | 266 | { |
267 | Bu::String a("This is a test."); | 267 | Bu::String a("This is a test."); |
268 | Bu::String b("--This is a test."); | 268 | Bu::String b("--This is a test."); |
269 | Bu::String::const_iterator ai = a.begin(); | 269 | Bu::String::const_iterator ai = a.begin(); |
270 | Bu::String::const_iterator bi = b.begin(); | 270 | Bu::String::const_iterator bi = b.begin(); |
271 | unitTest( ai.compare( bi ) == false ); | 271 | unitTest( ai.compare( bi ) == false ); |
272 | unitTest( bi.compare( ai ) == false ); | 272 | unitTest( bi.compare( ai ) == false ); |
273 | bi++; bi++; | 273 | bi++; bi++; |
274 | unitTest( ai.compare( bi ) == true ); | 274 | unitTest( ai.compare( bi ) == true ); |
275 | unitTest( bi.compare( ai ) == true ); | 275 | unitTest( bi.compare( ai ) == true ); |
276 | b += "hi"; | 276 | b += "hi"; |
277 | unitTest( ai.compare( bi ) == false ); | 277 | unitTest( ai.compare( bi ) == false ); |
278 | unitTest( bi.compare( ai ) == false ); | 278 | unitTest( bi.compare( ai ) == false ); |
279 | } | 279 | } |
280 | 280 | ||
281 | test const_iteratorCompare2 | 281 | test const_iteratorCompare2 |
282 | { | 282 | { |
283 | Bu::String a("1234honour"); | 283 | Bu::String a("1234honour"); |
284 | Bu::String b("--1234ueje"); | 284 | Bu::String b("--1234ueje"); |
285 | Bu::String::const_iterator ai = a.begin(); | 285 | Bu::String::const_iterator ai = a.begin(); |
286 | Bu::String::const_iterator bi = b.begin(); | 286 | Bu::String::const_iterator bi = b.begin(); |
287 | unitTest( ai.compare( bi, 4 ) == false ); | 287 | unitTest( ai.compare( bi, 4 ) == false ); |
288 | unitTest( bi.compare( ai, 4 ) == false ); | 288 | unitTest( bi.compare( ai, 4 ) == false ); |
289 | bi++; bi++; | 289 | bi++; bi++; |
290 | unitTest( ai.compare( bi, 4 ) == true ); | 290 | unitTest( ai.compare( bi, 4 ) == true ); |
291 | unitTest( bi.compare( ai, 4 ) == true ); | 291 | unitTest( bi.compare( ai, 4 ) == true ); |
292 | unitTest( ai.compare( bi, 5 ) == false ); | 292 | unitTest( ai.compare( bi, 5 ) == false ); |
293 | unitTest( bi.compare( ai, 5 ) == false ); | 293 | unitTest( bi.compare( ai, 5 ) == false ); |
294 | 294 | ||
295 | a = "fell"; | 295 | a = "fell"; |
296 | b = "-felloo"; | 296 | b = "-felloo"; |
297 | ai = a.begin(); | 297 | ai = a.begin(); |
298 | bi = b.begin()+1; | 298 | bi = b.begin()+1; |
299 | unitTest( ai.compare( bi, 4 ) == true ); | 299 | unitTest( ai.compare( bi, 4 ) == true ); |
300 | ai++; | 300 | ai++; |
301 | bi++; | 301 | bi++; |
302 | unitTest( ai.compare( bi, 4 ) == false ); | 302 | unitTest( ai.compare( bi, 4 ) == false ); |
303 | } | 303 | } |
304 | 304 | ||
305 | test const_iteratorCompare3 | 305 | test const_iteratorCompare3 |
306 | { | 306 | { |
307 | Bu::String a("1234aoeu"); | 307 | Bu::String a("1234aoeu"); |
308 | Bu::String::const_iterator ai = a.begin(); | 308 | Bu::String::const_iterator ai = a.begin(); |
309 | unitTest( ai.compare("1234") == false ); | 309 | unitTest( ai.compare("1234") == false ); |
310 | unitTest( ai.compare("1234aoeu") == true ); | 310 | unitTest( ai.compare("1234aoeu") == true ); |
311 | unitTest( ai.compare("1234aoeuee") == false ); | 311 | unitTest( ai.compare("1234aoeuee") == false ); |
312 | ai += 4; | 312 | ai += 4; |
313 | unitTest( ai.compare("aoeu") == true ); | 313 | unitTest( ai.compare("aoeu") == true ); |
314 | unitTest( ai.compare("aoeubo") == false ); | 314 | unitTest( ai.compare("aoeubo") == false ); |
315 | unitTest( ai.compare("aoe") == false ); | 315 | unitTest( ai.compare("aoe") == false ); |
316 | unitTest( ai.compare("wrong") == false ); | 316 | unitTest( ai.compare("wrong") == false ); |
317 | unitTest( ai.compare("boeu") == false ); | 317 | unitTest( ai.compare("boeu") == false ); |
318 | } | 318 | } |
319 | 319 | ||
320 | test const_iteratorCompare4 | 320 | test const_iteratorCompare4 |
321 | { | 321 | { |
322 | Bu::String a("1234aoeu"); | 322 | Bu::String a("1234aoeu"); |
323 | Bu::String::const_iterator ai = a.begin(); | 323 | Bu::String::const_iterator ai = a.begin(); |
324 | unitTest( ai.compare("1234", 4) == true ); | 324 | unitTest( ai.compare("1234", 4) == true ); |
325 | unitTest( ai.compare("1234aoeu", 8) == true ); | 325 | unitTest( ai.compare("1234aoeu", 8) == true ); |
326 | unitTest( ai.compare("1234aoeuee", 10) == false ); | 326 | unitTest( ai.compare("1234aoeuee", 10) == false ); |
327 | } | 327 | } |
328 | 328 | ||
329 | test const_iteratorCompare5 | 329 | test const_iteratorCompare5 |
330 | { | 330 | { |
331 | Bu::String a("1234aoeu"); | 331 | Bu::String a("1234aoeu"); |
332 | Bu::String b("34ao"); | 332 | Bu::String b("34ao"); |
333 | Bu::String::const_iterator ai = a.begin(); | 333 | Bu::String::const_iterator ai = a.begin(); |
334 | unitTest( ai.compare( b ) == false ); | 334 | unitTest( ai.compare( b ) == false ); |
335 | ai += 2; | 335 | ai += 2; |
336 | unitTest( ai.compare( b ) == false ); | 336 | unitTest( ai.compare( b ) == false ); |
337 | b = "oeu"; | 337 | b = "oeu"; |
338 | ai += 3; | 338 | ai += 3; |
339 | unitTest( ai.compare( b ) == true ); | 339 | unitTest( ai.compare( b ) == true ); |
340 | b += "boo"; | 340 | b += "boo"; |
341 | unitTest( ai.compare( b ) == false ); | 341 | unitTest( ai.compare( b ) == false ); |
342 | } | 342 | } |
343 | 343 | ||
344 | test const_iteratorCompare6 | 344 | test const_iteratorCompare6 |
345 | { | 345 | { |
346 | Bu::String a("1234aoeu"); | 346 | Bu::String a("1234aoeu"); |
347 | Bu::String::const_iterator ai = a.begin(); | 347 | Bu::String::const_iterator ai = a.begin(); |
348 | unitTest( ai.compare( Bu::String("1234"), 4) == true ); | 348 | unitTest( ai.compare( Bu::String("1234"), 4) == true ); |
349 | unitTest( ai.compare( Bu::String("1234aoeu"), 8) == true ); | 349 | unitTest( ai.compare( Bu::String("1234aoeu"), 8) == true ); |
350 | unitTest( ai.compare( Bu::String("1234aoeuee"), 10) == false ); | 350 | unitTest( ai.compare( Bu::String("1234aoeuee"), 10) == false ); |
351 | } | 351 | } |
352 | 352 | ||
353 | test iteratorAppend1 | 353 | test iteratorAppend1 |
354 | { | 354 | { |
355 | Bu::String a("just ->this part"); | 355 | Bu::String a("just ->this part"); |
356 | Bu::String b; | 356 | Bu::String b; |
357 | Bu::String::iterator s = a.begin(); | 357 | Bu::String::iterator s = a.begin(); |
358 | for(; s; s++ ) | 358 | for(; s; s++ ) |
359 | { | 359 | { |
360 | if( *s == '>' ) | 360 | if( *s == '>' ) |
361 | { | 361 | { |
362 | s++; | 362 | s++; |
363 | b.set( s ); | 363 | b.set( s ); |
364 | break; | 364 | break; |
365 | } | 365 | } |
366 | } | 366 | } |
367 | unitTest( b == "this part" ); | 367 | unitTest( b == "this part" ); |
368 | 368 | ||
369 | b.append( s ); | 369 | b.append( s ); |
370 | 370 | ||
371 | Bu::String c; | 371 | Bu::String c; |
372 | c.set( b.begin() ); | 372 | c.set( b.begin() ); |
373 | 373 | ||
374 | // This is here because the comparison operator used to cause flattening. | 374 | // This is here because the comparison operator used to cause flattening. |
375 | unitTest( b == "this partthis part" ); | 375 | unitTest( b == "this partthis part" ); |
376 | unitTest( c == b ); | 376 | unitTest( c == b ); |
377 | } | 377 | } |
378 | 378 | ||
379 | test iteratorAppend2 | 379 | test iteratorAppend2 |
380 | { | 380 | { |
381 | Bu::String a("just [this] part"); | 381 | Bu::String a("just [this] part"); |
382 | Bu::String b; | 382 | Bu::String b; |
383 | Bu::String::iterator s = a.begin(); | 383 | Bu::String::iterator s = a.begin(); |
384 | for(; s; s++ ) | 384 | for(; s; s++ ) |
385 | { | 385 | { |
386 | if( *s == '[' ) | 386 | if( *s == '[' ) |
387 | { | 387 | { |
388 | s++; | 388 | s++; |
389 | break; | 389 | break; |
390 | } | 390 | } |
391 | } | 391 | } |
392 | Bu::String::iterator e = s; | 392 | Bu::String::iterator e = s; |
393 | for(; e; e++ ) | 393 | for(; e; e++ ) |
394 | { | 394 | { |
395 | if( *e == ']' ) | 395 | if( *e == ']' ) |
396 | { | 396 | { |
397 | b.set( s, e ); | 397 | b.set( s, e ); |
398 | break; | 398 | break; |
399 | } | 399 | } |
400 | } | 400 | } |
401 | unitTest( b == "this" ); | 401 | unitTest( b == "this" ); |
402 | 402 | ||
403 | b.append( s, e ); | 403 | b.append( s, e ); |
404 | 404 | ||
405 | for( Bu::String::iterator i = b.begin(); i;) | 405 | for( Bu::String::iterator i = b.begin(); i;) |
406 | { | 406 | { |
407 | Bu::String::iterator k = i; | 407 | Bu::String::iterator k = i; |
408 | k++; | 408 | k++; |
409 | if( !k ) | 409 | if( !k ) |
410 | { | 410 | { |
411 | b.append( b.begin(), i ); | 411 | b.append( b.begin(), i ); |
412 | break; | 412 | break; |
413 | } | 413 | } |
414 | i = k; | 414 | i = k; |
415 | } | 415 | } |
416 | Bu::String l; | 416 | Bu::String l; |
417 | l.set( b.begin() ); | 417 | l.set( b.begin() ); |
418 | unitTest( l == "thisthisthisthi" ); | 418 | unitTest( l == "thisthisthisthi" ); |
419 | for( Bu::String::iterator i = b.begin(); i;) | 419 | for( Bu::String::iterator i = b.begin(); i;) |
420 | { | 420 | { |
421 | Bu::String::iterator k = i; | 421 | Bu::String::iterator k = i; |
422 | k++; | 422 | k++; |
423 | if( !k ) | 423 | if( !k ) |
424 | { | 424 | { |
425 | b.append( b.begin(), i ); | 425 | b.append( b.begin(), i ); |
426 | break; | 426 | break; |
427 | } | 427 | } |
428 | i = k; | 428 | i = k; |
429 | } | 429 | } |
430 | l.set( b.begin() ); | 430 | l.set( b.begin() ); |
431 | unitTest( l == "thisthisthisthithisthisthisth" ); | 431 | unitTest( l == "thisthisthisthithisthisthisth" ); |
432 | } | 432 | } |
433 | 433 | ||
434 | test isSet1 | 434 | test isSet1 |
435 | { | 435 | { |
436 | Bu::String bob; | 436 | Bu::String bob; |
437 | 437 | ||
438 | unitTest( bob.isSet() == false ); | 438 | unitTest( bob.isSet() == false ); |
439 | bob = "something"; | 439 | bob = "something"; |
440 | unitTest( bob.isSet() == true ); | 440 | unitTest( bob.isSet() == true ); |
441 | bob = ""; | 441 | bob = ""; |
442 | unitTest( bob.isSet() == false ); | 442 | unitTest( bob.isSet() == false ); |
443 | } | 443 | } |
444 | 444 | ||
445 | test swap1 | 445 | test swap1 |
446 | { | 446 | { |
447 | Bu::String a, b; | 447 | Bu::String a, b; |
448 | a = "Goodbye"; | 448 | a = "Goodbye"; |
449 | b = "Hello"; | 449 | b = "Hello"; |
450 | Bu::swap( a, b ); | 450 | Bu::swap( a, b ); |
451 | unitTest( a == "Hello" ); | 451 | unitTest( a == "Hello" ); |
452 | unitTest( b == "Goodbye" ); | 452 | unitTest( b == "Goodbye" ); |
453 | } | 453 | } |
454 | 454 | ||
455 | test swap2 | 455 | test swap2 |
456 | { | 456 | { |
457 | Bu::String a, b; | 457 | Bu::String a, b; |
458 | a = "Goodbye"; | 458 | a = "Goodbye"; |
459 | b = "Hello"; | 459 | b = "Hello"; |
460 | std::swap( a, b ); | 460 | std::swap( a, b ); |
461 | unitTest( a == "Hello" ); | 461 | unitTest( a == "Hello" ); |
462 | unitTest( b == "Goodbye" ); | 462 | unitTest( b == "Goodbye" ); |
463 | } | 463 | } |
464 | 464 | ||
465 | test replace1 | 465 | test replace1 |
466 | { | 466 | { |
467 | Bu::String a; | 467 | Bu::String a; |
468 | a = "This is a test."; | 468 | a = "This is a test."; |
469 | unitTest( a.replace("i", "ooo") == "Thooos ooos a test." ); | 469 | unitTest( a.replace("i", "ooo") == "Thooos ooos a test." ); |
470 | } | 470 | } |
471 | 471 | ||
472 | test replace2 | 472 | test replace2 |
473 | { | 473 | { |
474 | Bu::String a; | 474 | Bu::String a; |
475 | a = "aaaboostuffb"; | 475 | a = "aaaboostuffb"; |
476 | unitTest( a.replace("boo", "/") == "aaa/stuffb" ); | 476 | unitTest( a.replace("boo", "/") == "aaa/stuffb" ); |
477 | } | 477 | } |
478 | 478 | ||
479 | test coreDerefBug1 | 479 | test coreDerefBug1 |
480 | { | 480 | { |
481 | Bu::String a, b; | 481 | Bu::String a, b; |
482 | a = "bob"; | 482 | a = "bob"; |
483 | a.setSize( 0 ); | 483 | a.setSize( 0 ); |
484 | b = a; | 484 | b = a; |
485 | b.getStr(); | 485 | b.getStr(); |
486 | } | 486 | } |
487 | 487 | ||
488 | test padding1 | 488 | test padding1 |
489 | { | 489 | { |
490 | Bu::String a; | 490 | Bu::String a; |
491 | a.append('a'); | 491 | a.append('a'); |
492 | a.append('b'); | 492 | a.append('b'); |
493 | a.append('c'); | 493 | a.append('c'); |
494 | a.append("hello"); | 494 | a.append("hello"); |
495 | a.clear(); | 495 | a.clear(); |
496 | } | 496 | } |
497 | 497 | ||
498 | test padding2 | 498 | test padding2 |
499 | { | 499 | { |
500 | Bu::String src("It's all sorts of things"); | 500 | Bu::String src("It's all sorts of things"); |
501 | Bu::String::const_iterator i = src.find('a'); | 501 | Bu::String::const_iterator i = src.find('a'); |
502 | Bu::String::const_iterator j = src.find('f'); | 502 | Bu::String::const_iterator j = src.find('f'); |
503 | Bu::String a, b; | 503 | Bu::String a, b; |
504 | a.append( i ); | 504 | a.append( i ); |
505 | i += 2; | 505 | i += 2; |
506 | a.append( i, j ); | 506 | a.append( i, j ); |
507 | a.append('a'); | 507 | a.append('a'); |
508 | a.append('b'); | 508 | a.append('b'); |
509 | a.append('c'); | 509 | a.append('c'); |
510 | a.append("hello"); | 510 | a.append("hello"); |
511 | a.append( src ); | 511 | a.append( src ); |
512 | b = a; | 512 | b = a; |
513 | a.clear(); | 513 | a.clear(); |
514 | } | 514 | } |
515 | 515 | ||
516 | test append | 516 | test append |
517 | { | 517 | { |
518 | // This is the byte sequence that caused += to die | 518 | // This is the byte sequence that caused += to die |
519 | // 03 F0 9C A4 F5 8A C8 CA 0E | 519 | // 03 F0 9C A4 F5 8A C8 CA 0E |
520 | uint8_t b; | 520 | uint8_t b; |
521 | Bu::String m1; | 521 | Bu::String m1; |
522 | b = 0x03; m1 += (char)b; | 522 | b = 0x03; m1 += (char)b; |
523 | b = 0xF0; m1 += (char)b; | 523 | b = 0xF0; m1 += (char)b; |
524 | b = 0x9C; m1 += (char)b; | 524 | b = 0x9C; m1 += (char)b; |
525 | b = 0xA4; m1 += (char)b; | 525 | b = 0xA4; m1 += (char)b; |
526 | b = 0xF5; m1 += (char)b; | 526 | b = 0xF5; m1 += (char)b; |
527 | b = 0x8A; m1 += (char)b; | 527 | b = 0x8A; m1 += (char)b; |
528 | b = 0xC8; m1 += (char)b; | 528 | b = 0xC8; m1 += (char)b; |
529 | b = 0xCA; m1 += (char)b; | 529 | b = 0xCA; m1 += (char)b; |
530 | b = 0x0E; m1 += (char)b; | 530 | b = 0x0E; m1 += (char)b; |
531 | 531 | ||
532 | Bu::String m2; | 532 | Bu::String m2; |
533 | b = 0x03; m2.append( (const char *)&b, 1 ); | 533 | b = 0x03; m2.append( (const char *)&b, 1 ); |
534 | b = 0xF0; m2.append( (const char *)&b, 1 ); | 534 | b = 0xF0; m2.append( (const char *)&b, 1 ); |
535 | b = 0x9C; m2.append( (const char *)&b, 1 ); | 535 | b = 0x9C; m2.append( (const char *)&b, 1 ); |
536 | b = 0xA4; m2.append( (const char *)&b, 1 ); | 536 | b = 0xA4; m2.append( (const char *)&b, 1 ); |
537 | b = 0xF5; m2.append( (const char *)&b, 1 ); | 537 | b = 0xF5; m2.append( (const char *)&b, 1 ); |
538 | b = 0x8A; m2.append( (const char *)&b, 1 ); | 538 | b = 0x8A; m2.append( (const char *)&b, 1 ); |
539 | b = 0xC8; m2.append( (const char *)&b, 1 ); | 539 | b = 0xC8; m2.append( (const char *)&b, 1 ); |
540 | b = 0xCA; m2.append( (const char *)&b, 1 ); | 540 | b = 0xCA; m2.append( (const char *)&b, 1 ); |
541 | b = 0x0E; m2.append( (const char *)&b, 1 ); | 541 | b = 0x0E; m2.append( (const char *)&b, 1 ); |
542 | 542 | ||
543 | unitTest( m1 == m2 ); | 543 | unitTest( m1 == m2 ); |
544 | unitTest( m1 == "\x03\xF0\x9C\xA4\xF5\x8A\xC8\xCA\x0E" ); | 544 | unitTest( m1 == "\x03\xF0\x9C\xA4\xF5\x8A\xC8\xCA\x0E" ); |
545 | } | 545 | } |
546 | 546 | ||
547 | test toUpper1 | 547 | test toUpper1 |
548 | { | 548 | { |
549 | Bu::String s1("HeLlO ThErE, HoW ArE YoU DoInG?"); | 549 | Bu::String s1("HeLlO ThErE, HoW ArE YoU DoInG?"); |
550 | unitTest( s1.toUpper() == "HELLO THERE, HOW ARE YOU DOING?" ); | 550 | unitTest( s1.toUpper() == "HELLO THERE, HOW ARE YOU DOING?" ); |
551 | unitTest( s1 == "HeLlO ThErE, HoW ArE YoU DoInG?" ); | 551 | unitTest( s1 == "HeLlO ThErE, HoW ArE YoU DoInG?" ); |
552 | } | 552 | } |
553 | 553 | ||
554 | test toLower1 | 554 | test toLower1 |
555 | { | 555 | { |
556 | Bu::String s1("HeLlO ThErE, HoW ArE YoU DoInG?"); | 556 | Bu::String s1("HeLlO ThErE, HoW ArE YoU DoInG?"); |
557 | unitTest( s1.toLower() == "hello there, how are you doing?" ); | 557 | unitTest( s1.toLower() == "hello there, how are you doing?" ); |
558 | unitTest( s1 == "HeLlO ThErE, HoW ArE YoU DoInG?" ); | 558 | unitTest( s1 == "HeLlO ThErE, HoW ArE YoU DoInG?" ); |
559 | } | 559 | } |
560 | 560 | ||
561 | test trimWhitespace1 | 561 | test trimWhitespace1 |
562 | { | 562 | { |
563 | unitTest( Bu::String("Hello there").trimWhitespace() | 563 | unitTest( Bu::String("Hello there").trimWhitespace() |
564 | == "Hello there" ); | 564 | == "Hello there" ); |
565 | unitTest( Bu::String(" \t\r\r\nHello there").trimWhitespace() | 565 | unitTest( Bu::String(" \t\r\r\nHello there").trimWhitespace() |
566 | == "Hello there" ); | 566 | == "Hello there" ); |
567 | unitTest( Bu::String("Hello there \r\n\n\t\t ").trimWhitespace() | 567 | unitTest( Bu::String("Hello there \r\n\n\t\t ").trimWhitespace() |
568 | == "Hello there" ); | 568 | == "Hello there" ); |
569 | unitTest( Bu::String(" \tHello there\r\n \t").trimWhitespace() | 569 | unitTest( Bu::String(" \tHello there\r\n \t").trimWhitespace() |
570 | == "Hello there" ); | 570 | == "Hello there" ); |
571 | unitTest( Bu::String(" \t\t\r\n").trimWhitespace() == "" ); | 571 | unitTest( Bu::String(" \t\t\r\n").trimWhitespace() == "" ); |
572 | unitTest( Bu::String().trimWhitespace() == "" ); | 572 | unitTest( Bu::String().trimWhitespace() == "" ); |
573 | unitTest( Bu::String(" \tHello \t\t\r\nthere\r\n \t").trimWhitespace() | 573 | unitTest( Bu::String(" \tHello \t\t\r\nthere\r\n \t").trimWhitespace() |
574 | == "Hello \t\t\r\nthere" ); | 574 | == "Hello \t\t\r\nthere" ); |
575 | } | 575 | } |
576 | 576 | ||
577 | test format1 | 577 | test format1 |
578 | { | 578 | { |
579 | unitTest( (Bu::String)Bu::String("%1").arg( 12, Bu::Fmt().width(3) ) == " 12" ); | 579 | unitTest( (Bu::String)Bu::String("%1").arg( 12, Bu::Fmt().width(3) ) == " 12" ); |
580 | unitTest( (Bu::String)Bu::String("%1 %2").arg("IQ").arg(4, Bu::Fmt().plus()) == "IQ +4" ); | 580 | unitTest( (Bu::String)Bu::String("%1 %2").arg("IQ").arg(4, Bu::Fmt().plus()) == "IQ +4" ); |
581 | unitTest( (Bu::String)Bu::String("%1%2").arg("IQ").arg(4, Bu::Fmt().plus()) == "IQ+4" ); | 581 | unitTest( (Bu::String)Bu::String("%1%2").arg("IQ").arg(4, Bu::Fmt().plus()) == "IQ+4" ); |
582 | unitTest( (Bu::String)Bu::String("Sup #%1-Guy!").arg( 1 ) == "Sup #1-Guy!" ); | 582 | unitTest( (Bu::String)Bu::String("Sup #%1-Guy!").arg( 1 ) == "Sup #1-Guy!" ); |
583 | } | 583 | } |
584 | 584 | ||
585 | test format2 | 585 | test format2 |
586 | { | 586 | { |
587 | unitTest( Bu::String("0x%{1}00").arg( 75, Bu::Fmt::hex() ).end() == "0x4B00" ); | 587 | unitTest( Bu::String("0x%{1}00").arg( 75, Bu::Fmt::hex() ).end() == "0x4B00" ); |
588 | } | 588 | } |
589 | } | 589 | } |
590 | // 03F09CA4F58AC8CA0E80F0D9D409D0A60700A192270004BC3A99E91D0001034F544603362E35013103313130019CA4F58AC8CA0E0002830800002C4200008AC200EBF7D9D4090127BB010000E3 | 590 | // 03F09CA4F58AC8CA0E80F0D9D409D0A60700A192270004BC3A99E91D0001034F544603362E35013103313130019CA4F58AC8CA0E0002830800002C4200008AC200EBF7D9D4090127BB010000E3 |
591 | // | 591 | // |
diff --git a/src/unit/substream.unit b/src/unit/substream.unit index c66238d..b0d1407 100644 --- a/src/unit/substream.unit +++ b/src/unit/substream.unit | |||
@@ -11,42 +11,42 @@ | |||
11 | 11 | ||
12 | suite SubStream | 12 | suite SubStream |
13 | { | 13 | { |
14 | test testRead01 | 14 | test testRead01 |
15 | { | 15 | { |
16 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); | 16 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); |
17 | mb.seek( 4 ); | 17 | mb.seek( 4 ); |
18 | Bu::SubStream ss( mb, 10 ); | 18 | Bu::SubStream ss( mb, 10 ); |
19 | unitTest( ss.readLine() == "efghijklmn" ); | 19 | unitTest( ss.readLine() == "efghijklmn" ); |
20 | } | 20 | } |
21 | 21 | ||
22 | test testRead02 | 22 | test testRead02 |
23 | { | 23 | { |
24 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); | 24 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); |
25 | mb.seek( 4 ); | 25 | mb.seek( 4 ); |
26 | Bu::SubStream ss( mb, 10 ); | 26 | Bu::SubStream ss( mb, 10 ); |
27 | char buf[8]; | 27 | char buf[8]; |
28 | size_t iRead = ss.read( buf, 8 ); | 28 | size_t iRead = ss.read( buf, 8 ); |
29 | unitTest( iRead == 8 ); | 29 | unitTest( iRead == 8 ); |
30 | unitTest( strncmp( buf, "efghijkl", 8 ) == 0 ); | 30 | unitTest( strncmp( buf, "efghijkl", 8 ) == 0 ); |
31 | unitTest( !ss.isEos() ); | 31 | unitTest( !ss.isEos() ); |
32 | iRead = ss.read( buf, 8 ); | 32 | iRead = ss.read( buf, 8 ); |
33 | unitTest( iRead == 2 ); | 33 | unitTest( iRead == 2 ); |
34 | unitTest( strncmp( buf, "mn", 2 ) == 0 ); | 34 | unitTest( strncmp( buf, "mn", 2 ) == 0 ); |
35 | unitTest( ss.isEos() ); | 35 | unitTest( ss.isEos() ); |
36 | } | 36 | } |
37 | 37 | ||
38 | test testRead03 | 38 | test testRead03 |
39 | { | 39 | { |
40 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); | 40 | Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz"); |
41 | mb.seek( 20 ); | 41 | mb.seek( 20 ); |
42 | Bu::SubStream ss( mb, 10 ); | 42 | Bu::SubStream ss( mb, 10 ); |
43 | char buf[8]; | 43 | char buf[8]; |
44 | size_t iRead = ss.read( buf, 8 ); | 44 | size_t iRead = ss.read( buf, 8 ); |
45 | unitTest( iRead == 6 ); | 45 | unitTest( iRead == 6 ); |
46 | unitTest( strncmp( buf, "uvwxyz", 6 ) == 0 ); | 46 | unitTest( strncmp( buf, "uvwxyz", 6 ) == 0 ); |
47 | unitTest( ss.isEos() ); | 47 | unitTest( ss.isEos() ); |
48 | iRead = ss.read( buf, 8 ); | 48 | iRead = ss.read( buf, 8 ); |
49 | unitTest( iRead == 0 ); | 49 | unitTest( iRead == 0 ); |
50 | unitTest( ss.isEos() ); | 50 | unitTest( ss.isEos() ); |
51 | } | 51 | } |
52 | } | 52 | } |
diff --git a/src/unit/taf.unit b/src/unit/taf.unit index 12e93c2..47605ee 100644 --- a/src/unit/taf.unit +++ b/src/unit/taf.unit | |||
@@ -15,64 +15,64 @@ | |||
15 | 15 | ||
16 | suite Taf | 16 | suite Taf |
17 | { | 17 | { |
18 | test read1 | 18 | test read1 |
19 | { | 19 | { |
20 | #define FN_TMP ("/tmp/tmpXXXXXXXX") | 20 | #define FN_TMP ("/tmp/tmpXXXXXXXX") |
21 | Bu::String sFnTmp(FN_TMP); | 21 | Bu::String sFnTmp(FN_TMP); |
22 | Bu::File fOut = Bu::File::tempFile( sFnTmp ); | 22 | Bu::File fOut = Bu::File::tempFile( sFnTmp ); |
23 | const char *data = | 23 | const char *data = |
24 | "{test: name=\"Bob\"}" | 24 | "{test: name=\"Bob\"}" |
25 | ; | 25 | ; |
26 | fOut.write(data,strlen(data)); | 26 | fOut.write(data,strlen(data)); |
27 | fOut.close(); | 27 | fOut.close(); |
28 | 28 | ||
29 | Bu::File fIn(sFnTmp.getStr(), Bu::File::Read ); | 29 | Bu::File fIn(sFnTmp.getStr(), Bu::File::Read ); |
30 | Bu::TafReader tr(fIn); | 30 | Bu::TafReader tr(fIn); |
31 | 31 | ||
32 | Bu::TafGroup *tn = tr.readGroup(); | 32 | Bu::TafGroup *tn = tr.readGroup(); |
33 | unitTest( !strcmp("Bob", tn->getProperty("name").getStr()) ); | 33 | unitTest( !strcmp("Bob", tn->getProperty("name").getStr()) ); |
34 | delete tn; | 34 | delete tn; |
35 | 35 | ||
36 | unlink(sFnTmp.getStr()); | 36 | unlink(sFnTmp.getStr()); |
37 | #undef FN_TMP | 37 | #undef FN_TMP |
38 | } | 38 | } |
39 | 39 | ||
40 | test encode1 | 40 | test encode1 |
41 | { | 41 | { |
42 | Bu::MemBuf mb; | 42 | Bu::MemBuf mb; |
43 | Bu::TafWriter tw( mb ); | 43 | Bu::TafWriter tw( mb ); |
44 | 44 | ||
45 | Bu::TafGroup g("Test data"); | 45 | Bu::TafGroup g("Test data"); |
46 | Bu::String sData( 256 ); | 46 | Bu::String sData( 256 ); |
47 | for( int j = 0; j < 256; j++ ) | 47 | for( int j = 0; j < 256; j++ ) |
48 | sData[j] = (unsigned char)j; | 48 | sData[j] = (unsigned char)j; |
49 | g.addChild( new Bu::TafProperty("Encoded", sData) ); | 49 | g.addChild( new Bu::TafProperty("Encoded", sData) ); |
50 | tw.writeGroup( &g ); | 50 | tw.writeGroup( &g ); |
51 | 51 | ||
52 | static const char *cmpdata = "{\"Test data\":\n \"Encoded\"=\"" | 52 | static const char *cmpdata = "{\"Test data\":\n \"Encoded\"=\"" |
53 | "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07" | 53 | "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07" |
54 | "\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F" | 54 | "\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F" |
55 | "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17" | 55 | "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17" |
56 | "\\x18\\x19\\x1A\\x1B\\x1C\\x1D\\x1E\\x1F" | 56 | "\\x18\\x19\\x1A\\x1B\\x1C\\x1D\\x1E\\x1F" |
57 | " !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCD" | 57 | " !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCD" |
58 | "EFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghi" | 58 | "EFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghi" |
59 | "jklmnopqrstuvwxyz{|}~\\x7F" | 59 | "jklmnopqrstuvwxyz{|}~\\x7F" |
60 | "\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87" | 60 | "\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87" |
61 | "\\x88\\x89\\x8A\\x8B\\x8C\\x8D\\x8E\\x8F" | 61 | "\\x88\\x89\\x8A\\x8B\\x8C\\x8D\\x8E\\x8F" |
62 | "\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97" | 62 | "\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97" |
63 | "\\x98\\x99\\x9A\\x9B\\x9C\\x9D\\x9E\\x9F" | 63 | "\\x98\\x99\\x9A\\x9B\\x9C\\x9D\\x9E\\x9F" |
64 | "\\xA0\\xA1\\xA2\\xA3\\xA4\\xA5\\xA6\\xA7" | 64 | "\\xA0\\xA1\\xA2\\xA3\\xA4\\xA5\\xA6\\xA7" |
65 | "\\xA8\\xA9\\xAA\\xAB\\xAC\\xAD\\xAE\\xAF" | 65 | "\\xA8\\xA9\\xAA\\xAB\\xAC\\xAD\\xAE\\xAF" |
66 | "\\xB0\\xB1\\xB2\\xB3\\xB4\\xB5\\xB6\\xB7" | 66 | "\\xB0\\xB1\\xB2\\xB3\\xB4\\xB5\\xB6\\xB7" |
67 | "\\xB8\\xB9\\xBA\\xBB\\xBC\\xBD\\xBE\\xBF" | 67 | "\\xB8\\xB9\\xBA\\xBB\\xBC\\xBD\\xBE\\xBF" |
68 | "\\xC0\\xC1\\xC2\\xC3\\xC4\\xC5\\xC6\\xC7" | 68 | "\\xC0\\xC1\\xC2\\xC3\\xC4\\xC5\\xC6\\xC7" |
69 | "\\xC8\\xC9\\xCA\\xCB\\xCC\\xCD\\xCE\\xCF" | 69 | "\\xC8\\xC9\\xCA\\xCB\\xCC\\xCD\\xCE\\xCF" |
70 | "\\xD0\\xD1\\xD2\\xD3\\xD4\\xD5\\xD6\\xD7" | 70 | "\\xD0\\xD1\\xD2\\xD3\\xD4\\xD5\\xD6\\xD7" |
71 | "\\xD8\\xD9\\xDA\\xDB\\xDC\\xDD\\xDE\\xDF" | 71 | "\\xD8\\xD9\\xDA\\xDB\\xDC\\xDD\\xDE\\xDF" |
72 | "\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7" | 72 | "\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7" |
73 | "\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF" | 73 | "\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF" |
74 | "\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7" | 74 | "\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7" |
75 | "\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF\"\n}\n"; | 75 | "\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF\"\n}\n"; |
76 | unitTest( mb.getString() == cmpdata ); | 76 | unitTest( mb.getString() == cmpdata ); |
77 | mb.setPos( 0 ); | 77 | mb.setPos( 0 ); |
78 | Bu::TafReader tr( mb ); | 78 | Bu::TafReader tr( mb ); |
diff --git a/src/unit/variant.unit b/src/unit/variant.unit index 684bea1..68c7be5 100644 --- a/src/unit/variant.unit +++ b/src/unit/variant.unit | |||
@@ -16,46 +16,46 @@ using namespace Bu; | |||
16 | 16 | ||
17 | Bu::String mkastring() | 17 | Bu::String mkastring() |
18 | { | 18 | { |
19 | Bu::String a = "s"; | 19 | Bu::String a = "s"; |
20 | a += "tu"; | 20 | a += "tu"; |
21 | a += "f"; | 21 | a += "f"; |
22 | a += "f"; | 22 | a += "f"; |
23 | return a; | 23 | return a; |
24 | } | 24 | } |
25 | 25 | ||
26 | suite Variant | 26 | suite Variant |
27 | { | 27 | { |
28 | test construction | 28 | test construction |
29 | { | 29 | { |
30 | Bu::Variant v( 55 ); | 30 | Bu::Variant v( 55 ); |
31 | v.get<int>(); | 31 | v.get<int>(); |
32 | 32 | ||
33 | Bu::Variant v2( v ); | 33 | Bu::Variant v2( v ); |
34 | v2.get<int>(); | 34 | v2.get<int>(); |
35 | } | 35 | } |
36 | 36 | ||
37 | test formatting | 37 | test formatting |
38 | { | 38 | { |
39 | Bu::Variant v("hello"); | 39 | Bu::Variant v("hello"); |
40 | Bu::MemBuf mb; | 40 | Bu::MemBuf mb; |
41 | Bu::Formatter f( mb ); | 41 | Bu::Formatter f( mb ); |
42 | f << v; | 42 | f << v; |
43 | unitTest( mb.getString() == v.get<Bu::String>() ); | 43 | unitTest( mb.getString() == v.get<Bu::String>() ); |
44 | } | 44 | } |
45 | 45 | ||
46 | test stringForamtting | 46 | test stringForamtting |
47 | { | 47 | { |
48 | Bu::String s1; | 48 | Bu::String s1; |
49 | s1 = "hello"; | 49 | s1 = "hello"; |
50 | int32_t i1, i2; | 50 | int32_t i1, i2; |
51 | i1 = 32; | 51 | i1 = 32; |
52 | i2 = 0; | 52 | i2 = 0; |
53 | Bu::String out = Bu::String("%1-%2-%3-%4.odp"). | 53 | Bu::String out = Bu::String("%1-%2-%3-%4.odp"). |
54 | arg( s1.getStr() ). | 54 | arg( s1.getStr() ). |
55 | arg( mkastring().getStr() ). | 55 | arg( mkastring().getStr() ). |
56 | arg( i1, Fmt(2).fill('0') ). | 56 | arg( i1, Fmt(2).fill('0') ). |
57 | arg( i2, Fmt(2).fill('0') ); | 57 | arg( i2, Fmt(2).fill('0') ); |
58 | // sio << sio.nl << out << sio.nl; | 58 | // sio << sio.nl << out << sio.nl; |
59 | unitTest( out == "hello-stuff-32-00.odp" ); | 59 | unitTest( out == "hello-stuff-32-00.odp" ); |
60 | } | 60 | } |
61 | } | 61 | } |
diff --git a/src/unit/xml.unit b/src/unit/xml.unit index 0db21c1..57e1c1c 100644 --- a/src/unit/xml.unit +++ b/src/unit/xml.unit | |||
@@ -12,10 +12,10 @@ | |||
12 | 12 | ||
13 | suite Xml | 13 | suite Xml |
14 | { | 14 | { |
15 | test declaration | 15 | test declaration |
16 | { | 16 | { |
17 | Bu::String sXml("<?xml ?> <hi />"); | 17 | Bu::String sXml("<?xml ?> <hi />"); |
18 | Bu::MemBuf buf( sXml ); | 18 | Bu::MemBuf buf( sXml ); |
19 | Bu::XmlReader xr( buf ); | 19 | Bu::XmlReader xr( buf ); |
20 | } | 20 | } |
21 | } | 21 | } |
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 |