aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2012-11-05 22:41:51 +0000
committerMike Buland <eichlan@xagasoft.com>2012-11-05 22:41:51 +0000
commitec05778d5718a7912e506764d443a78d6a6179e3 (patch)
tree78a9a01532180030c095acefc45763f07c14edb8
parentb20414ac1fe80a71a90601f4cd1767fa7014a9ba (diff)
downloadlibbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.gz
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.bz2
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.xz
libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.zip
Converted tabs to spaces with tabconv.
-rw-r--r--autoconfig.cpp128
-rw-r--r--default.bld318
-rw-r--r--mingw.bld110
-rw-r--r--misc/heap.cpp188
-rw-r--r--pregen/signals.h2290
-rw-r--r--src/compat/win32.cpp134
-rw-r--r--src/compat/win32.h104
-rw-r--r--src/config.h6
-rw-r--r--src/experimental/blowfish.h874
-rw-r--r--src/experimental/cache.h828
-rw-r--r--src/experimental/cachecalc.h88
-rw-r--r--src/experimental/cachestore.h52
-rw-r--r--src/experimental/cachestorefiles.h358
-rw-r--r--src/experimental/cachestoremyriad.h270
-rw-r--r--src/experimental/cipher.h218
-rw-r--r--src/experimental/ciphermodecbc.h86
-rw-r--r--src/experimental/ciphermodecfb.h84
-rw-r--r--src/experimental/ciphermodeecb.h44
-rw-r--r--src/experimental/ciphermodeofb.h90
-rw-r--r--src/experimental/dir.h16
-rw-r--r--src/experimental/fastcgi.cpp592
-rw-r--r--src/experimental/fastcgi.h224
-rw-r--r--src/experimental/filesystem.h30
-rw-r--r--src/experimental/httpget.cpp48
-rw-r--r--src/experimental/httpget.h72
-rw-r--r--src/experimental/lexer.cpp16
-rw-r--r--src/experimental/lexer.h82
-rw-r--r--src/experimental/parser.cpp342
-rw-r--r--src/experimental/parser.h218
-rw-r--r--src/experimental/regex.cpp94
-rw-r--r--src/experimental/regex.h46
-rw-r--r--src/experimental/regexengine.h260
-rw-r--r--src/experimental/xmlreader.cpp250
-rw-r--r--src/experimental/xmlreader.h76
-rw-r--r--src/extra/myriadfs.cpp500
-rw-r--r--src/stable/archival.cpp12
-rw-r--r--src/stable/archival.h66
-rw-r--r--src/stable/archive.cpp76
-rw-r--r--src/stable/archive.h216
-rw-r--r--src/stable/archivebase.cpp120
-rw-r--r--src/stable/archivebase.h106
-rw-r--r--src/stable/array.h1382
-rw-r--r--src/stable/atom.h254
-rw-r--r--src/stable/base64.cpp346
-rw-r--r--src/stable/base64.h82
-rw-r--r--src/stable/buffer.cpp250
-rw-r--r--src/stable/buffer.h82
-rw-r--r--src/stable/bzip2.cpp344
-rw-r--r--src/stable/bzip2.h60
-rw-r--r--src/stable/client.cpp220
-rw-r--r--src/stable/client.h224
-rw-r--r--src/stable/clientlink.h14
-rw-r--r--src/stable/clientlinkfactory.h18
-rw-r--r--src/stable/condition.cpp28
-rw-r--r--src/stable/condition.h130
-rw-r--r--src/stable/conduit.cpp240
-rw-r--r--src/stable/conduit.h80
-rw-r--r--src/stable/crypt.cpp38
-rw-r--r--src/stable/crypt.h4
-rw-r--r--src/stable/cryptohash.cpp26
-rw-r--r--src/stable/cryptohash.h28
-rw-r--r--src/stable/csvreader.cpp118
-rw-r--r--src/stable/csvreader.h52
-rw-r--r--src/stable/csvwriter.cpp76
-rw-r--r--src/stable/csvwriter.h52
-rw-r--r--src/stable/deflate.cpp380
-rw-r--r--src/stable/deflate.h82
-rw-r--r--src/stable/exceptionbase.cpp76
-rw-r--r--src/stable/exceptionbase.h304
-rw-r--r--src/stable/extratypes.h8
-rw-r--r--src/stable/file.cpp298
-rw-r--r--src/stable/file.h158
-rw-r--r--src/stable/filter.cpp40
-rw-r--r--src/stable/filter.h110
-rw-r--r--src/stable/fmt.h158
-rw-r--r--src/stable/formatter.cpp516
-rw-r--r--src/stable/formatter.h572
-rw-r--r--src/stable/formula.cpp2
-rw-r--r--src/stable/formula.h808
-rw-r--r--src/stable/hash.cpp68
-rw-r--r--src/stable/hash.h2610
-rw-r--r--src/stable/heap.h1180
-rw-r--r--src/stable/hex.cpp70
-rw-r--r--src/stable/hex.h74
-rw-r--r--src/stable/list.h2032
-rw-r--r--src/stable/logger.cpp312
-rw-r--r--src/stable/logger.h154
-rw-r--r--src/stable/lzma.cpp368
-rw-r--r--src/stable/lzma.h80
-rw-r--r--src/stable/md5.cpp218
-rw-r--r--src/stable/md5.h74
-rw-r--r--src/stable/membuf.cpp122
-rw-r--r--src/stable/membuf.h86
-rw-r--r--src/stable/minicron.cpp622
-rw-r--r--src/stable/minicron.h630
-rw-r--r--src/stable/multiserver.cpp20
-rw-r--r--src/stable/multiserver.h78
-rw-r--r--src/stable/mutex.cpp10
-rw-r--r--src/stable/mutex.h94
-rw-r--r--src/stable/mutexlocker.cpp10
-rw-r--r--src/stable/mutexlocker.h22
-rw-r--r--src/stable/myriad.cpp1130
-rw-r--r--src/stable/myriad.h426
-rw-r--r--src/stable/myriadstream.cpp344
-rw-r--r--src/stable/myriadstream.h86
-rw-r--r--src/stable/nullstream.cpp44
-rw-r--r--src/stable/nullstream.h92
-rw-r--r--src/stable/optparser.cpp732
-rw-r--r--src/stable/optparser.h398
-rw-r--r--src/stable/pearsonhash.cpp50
-rw-r--r--src/stable/pearsonhash.h54
-rw-r--r--src/stable/plugger.h420
-rw-r--r--src/stable/process.cpp820
-rw-r--r--src/stable/process.h284
-rw-r--r--src/stable/protocol.h30
-rw-r--r--src/stable/protocolhttp.cpp362
-rw-r--r--src/stable/protocolhttp.h146
-rw-r--r--src/stable/protocoltelnet.cpp942
-rw-r--r--src/stable/protocoltelnet.h386
-rw-r--r--src/stable/queue.h42
-rw-r--r--src/stable/queuebuf.cpp316
-rw-r--r--src/stable/queuebuf.h90
-rw-r--r--src/stable/random.cpp18
-rw-r--r--src/stable/random.h88
-rw-r--r--src/stable/randombase.h36
-rw-r--r--src/stable/randombasic.cpp12
-rw-r--r--src/stable/randombasic.h20
-rw-r--r--src/stable/randomcmwc.cpp58
-rw-r--r--src/stable/randomcmwc.h20
-rw-r--r--src/stable/randomsystem.cpp40
-rw-r--r--src/stable/randomsystem.h34
-rw-r--r--src/stable/ringbuffer.h462
-rw-r--r--src/stable/server.cpp252
-rw-r--r--src/stable/server.h138
-rw-r--r--src/stable/sha1.cpp282
-rw-r--r--src/stable/sha1.h70
-rw-r--r--src/stable/sharedcore.h340
-rw-r--r--src/stable/singleton.h98
-rw-r--r--src/stable/sio.cpp54
-rw-r--r--src/stable/sio.h18
-rw-r--r--src/stable/sptr.h422
-rw-r--r--src/stable/stack.h116
-rw-r--r--src/stable/staticmembuf.cpp62
-rw-r--r--src/stable/staticmembuf.h84
-rw-r--r--src/stable/stdstream.cpp32
-rw-r--r--src/stable/stdstream.h78
-rw-r--r--src/stable/stream.cpp48
-rw-r--r--src/stable/stream.h366
-rw-r--r--src/stable/streamstack.cpp134
-rw-r--r--src/stable/streamstack.h250
-rw-r--r--src/stable/strfilter.h218
-rw-r--r--src/stable/string.cpp1778
-rw-r--r--src/stable/string.h2098
-rw-r--r--src/stable/substream.cpp88
-rw-r--r--src/stable/substream.h92
-rw-r--r--src/stable/synchroatom.h88
-rw-r--r--src/stable/synchrocounter.h58
-rw-r--r--src/stable/synchroheap.h262
-rw-r--r--src/stable/synchroqueue.h454
-rw-r--r--src/stable/tafcomment.cpp16
-rw-r--r--src/stable/tafcomment.h32
-rw-r--r--src/stable/tafgroup.cpp224
-rw-r--r--src/stable/tafgroup.h92
-rw-r--r--src/stable/tafnode.cpp4
-rw-r--r--src/stable/tafnode.h42
-rw-r--r--src/stable/tafproperty.cpp16
-rw-r--r--src/stable/tafproperty.h32
-rw-r--r--src/stable/tafreader.cpp326
-rw-r--r--src/stable/tafreader.h56
-rw-r--r--src/stable/tafwriter.cpp112
-rw-r--r--src/stable/tafwriter.h52
-rw-r--r--src/stable/tcpserversocket.cpp278
-rw-r--r--src/stable/tcpserversocket.h66
-rw-r--r--src/stable/tcpsocket.cpp554
-rw-r--r--src/stable/tcpsocket.h200
-rw-r--r--src/stable/thread.cpp36
-rw-r--r--src/stable/thread.h228
-rw-r--r--src/stable/trace.cpp46
-rw-r--r--src/stable/trace.h310
-rw-r--r--src/stable/unitsuite.cpp394
-rw-r--r--src/stable/unitsuite.h230
-rw-r--r--src/stable/util.cpp86
-rw-r--r--src/stable/util.h294
-rw-r--r--src/stable/variant.cpp92
-rw-r--r--src/stable/variant.h418
-rw-r--r--src/tests/base64.cpp126
-rw-r--r--src/tests/bigmyriad.cpp26
-rw-r--r--src/tests/blowfish.cpp118
-rw-r--r--src/tests/bnfcompile.cpp750
-rw-r--r--src/tests/bzip2.cpp38
-rw-r--r--src/tests/deflate.cpp78
-rw-r--r--src/tests/lzma.cpp78
-rw-r--r--src/tests/myriadfs.cpp64
-rw-r--r--src/tests/optparser.cpp126
-rw-r--r--src/tests/parser.cpp576
-rw-r--r--src/tests/print.cpp28
-rw-r--r--src/tests/random.cpp62
-rw-r--r--src/tests/regex.cpp42
-rw-r--r--src/tests/settings.cpp12
-rw-r--r--src/tests/synchroqueue.cpp198
-rw-r--r--src/tests/taf.cpp52
-rw-r--r--src/tests/threadid.cpp78
-rw-r--r--src/tests/utf.cpp112
-rw-r--r--src/tests/uuid.cpp8
-rw-r--r--src/tools/bin2cpp.cpp414
-rw-r--r--src/tools/mkunit.cpp962
-rw-r--r--src/tools/myriad.cpp438
-rw-r--r--src/tools/viewcsv.cpp868
-rw-r--r--src/unit/archive.unit352
-rw-r--r--src/unit/array.unit174
-rw-r--r--src/unit/base64.unit24
-rw-r--r--src/unit/blowfish.unit44
-rw-r--r--src/unit/buffer.unit22
-rw-r--r--src/unit/file.unit160
-rw-r--r--src/unit/hash.unit378
-rw-r--r--src/unit/list.unit264
-rw-r--r--src/unit/md5.unit124
-rw-r--r--src/unit/membuf.unit60
-rw-r--r--src/unit/myriad.unit678
-rw-r--r--src/unit/queuebuf.unit154
-rw-r--r--src/unit/sha1.unit112
-rw-r--r--src/unit/string.unit1148
-rw-r--r--src/unit/substream.unit72
-rw-r--r--src/unit/taf.unit94
-rw-r--r--src/unit/variant.unit70
-rw-r--r--src/unit/xml.unit12
-rw-r--r--src/unstable/bitstring.cpp660
-rw-r--r--src/unstable/bitstring.h412
-rw-r--r--src/unstable/fifo.cpp118
-rw-r--r--src/unstable/fifo.h80
-rw-r--r--src/unstable/itoserver.cpp312
-rw-r--r--src/unstable/itoserver.h224
-rw-r--r--src/unstable/minimacro.cpp252
-rw-r--r--src/unstable/minimacro.h212
-rw-r--r--src/unstable/myriadfs.cpp1078
-rw-r--r--src/unstable/myriadfs.h368
-rw-r--r--src/unstable/newline.cpp66
-rw-r--r--src/unstable/newline.h42
-rw-r--r--src/unstable/settings.cpp44
-rw-r--r--src/unstable/settings.h46
-rw-r--r--src/unstable/settingsdriver.h32
-rw-r--r--src/unstable/settingsdriverini.cpp258
-rw-r--r--src/unstable/settingsdriverini.h30
-rw-r--r--src/unstable/settingsdriverregistry.cpp116
-rw-r--r--src/unstable/settingsdriverregistry.h24
-rw-r--r--src/unstable/settingsdrivertaf.cpp148
-rw-r--r--src/unstable/settingsdrivertaf.h34
-rw-r--r--src/unstable/udpsocket.cpp216
-rw-r--r--src/unstable/udpsocket.h92
-rw-r--r--src/unstable/url.cpp378
-rw-r--r--src/unstable/url.h114
-rw-r--r--src/unstable/utfstring.cpp842
-rw-r--r--src/unstable/utfstring.h482
-rw-r--r--src/unstable/uuid.cpp150
-rw-r--r--src/unstable/uuid.h84
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
9bool testCpp( const char *prog ) 9bool 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
16void detectEndianness() 16void 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
41int main( int argc, char *argv[] ) 41int 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
20action "default" 20action "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
26action "pkg" 26action "pkg"
27{ 27{
28 build: targets("pkg"); 28 build: targets("pkg");
29} 29}
30 30
31action "all" 31action "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
37action "unit" 37action "unit"
38{ 38{
39 build: targets("unit tests"); 39 build: targets("unit tests");
40} 40}
41 41
42action "myriadfs" 42action "myriadfs"
43{ 43{
44 build: "myriadfs"; 44 build: "myriadfs";
45} 45}
46 46
47target ["src/autoconfig.h", "src/version.h"] 47target ["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
57target "src/version.h" 57target "src/version.h"
58{ 58{
59 input ".svn"; 59 input ".svn";
60} 60}
61 61
62target "src/signals.h" 62target "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
72target "autoconfig" 72target "autoconfig"
73{ 73{
74 rule "exe"; 74 rule "exe";
75 input "autoconfig.cpp"; 75 input "autoconfig.cpp";
76} 76}
77 77
78for base in ["stable", "unstable", "experimental"] do 78for 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
93target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] 93target ["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
105target files("src/compat/*.h").replace("src/", "bu/") 105target 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
117target "header-links" 117target "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
127target "libbu++.a" 127target "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
139target files("src/tools/*.cpp").replace("src/tools/","").replace(".cpp","") 139target 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
149target "viewcsv" 149target "viewcsv"
150{ 150{
151 LDFLAGS += "-lncurses"; 151 LDFLAGS += "-lncurses";
152} 152}
153 153
154target ["myriad", "myriadfs", "tests/myriad", "tests/myriadfs", "unit/myriad", "tests/bigmyriad", "tests/synchroqueue"] 154target ["myriad", "myriadfs", "tests/myriad", "tests/myriadfs", "unit/myriad", "tests/bigmyriad", "tests/synchroqueue"]
155{ 155{
156 LDFLAGS += "-lpthread"; 156 LDFLAGS += "-lpthread";
157} 157}
158 158
159target files("src/extra/*.cpp").replace("src/extra/","").replace(".cpp","") 159target 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//
174target "src/extra/myriadfs.o" 174target "src/extra/myriadfs.o"
175{ 175{
176 CXXFLAGS += "-D_FILE_OFFSET_BITS=64"; 176 CXXFLAGS += "-D_FILE_OFFSET_BITS=64";
177} 177}
178 178
179target "myriadfs" 179target "myriadfs"
180{ 180{
181 LDFLAGS += "-lfuse"; 181 LDFLAGS += "-lfuse";
182} 182}
183 183
184target "bin2cpp" 184target "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
193target files("src/tests/*.cpp").replace("src/","").replace(".cpp","") 193target 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
205target ["tests/bzip2", "tests/streamstack"] 205target ["tests/bzip2", "tests/streamstack"]
206{ 206{
207 LDFLAGS += "-lbz2"; 207 LDFLAGS += "-lbz2";
208} 208}
209 209
210target ["tests/deflate", "tests/enc"] 210target ["tests/deflate", "tests/enc"]
211{ 211{
212 LDFLAGS += "-lz"; 212 LDFLAGS += "-lz";
213} 213}
214 214
215target ["tests/lzma"] 215target ["tests/lzma"]
216{ 216{
217 LDFLAGS += "-llzma"; 217 LDFLAGS += "-llzma";
218} 218}
219 219
220target ["tests/threadid"] 220target ["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
229target files("src/unit/*.unit").replace("src/","").replace(".unit","") 229target 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
239PKG_BASE = "libbu++-$(cat version)-r$(svnversion "-n").tar"; 239PKG_BASE = "libbu++-$(cat version)-r$(svnversion "-n").tar";
240 240
241target PKG_BASE 241target 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
279target PKG_BASE + ".gz" 279target 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
290target PKG_BASE + ".bz2" 290target 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
301target PKG_BASE + ".xz" 301target 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
312rule "tarball" 312rule "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
323rule "unit" 323rule "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
diff --git a/mingw.bld b/mingw.bld
index fe2f763..6339df9 100644
--- a/mingw.bld
+++ b/mingw.bld
@@ -13,90 +13,90 @@ CXXFLAGS += "-ggdb -W -Wall";
13 13
14action "default" 14action "default"
15{ 15{
16 build: [targets("header-links"), "libbu++win.a"]; 16 build: [targets("header-links"), "libbu++win.a"];
17} 17}
18 18
19for base in ["stable", "unstable", "experimental"] do 19for 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}
33target files("src/compat/*.h").replace("src/", "bu/") 33target 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}
43target ["bu/config.h", "bu/autoconfig.h", "bu/version.h", "bu/signals.h"] 43target ["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
55target "libbu++win.a" 55target "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
63target ["src/stable/lzma.win_o", "src/experimental/cachestorefiles.win_o", "src/experimental/regex.win_o"] 63target ["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
71function cppToWinObj() 71function 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
84rule "lib" 84rule "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
93rule "wincpp" 93rule "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
4void printHeap( int *aiHeap, int iHeapFill ) 4void 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
27void heapPush( int iNum, int *aiHeap, int &iHeapFill ) 27void 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
64int heapPop( int *aiHeap, int &iHeapFill ) 64int 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
89int main( int argc, char *argv[] ) 89int 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
14namespace Bu 14namespace 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
15char Bu::Winsock2::scode[32]; 15char Bu::Winsock2::scode[32];
16 16
@@ -33,133 +33,133 @@ deffunc( getpeername );
33deffunc( setsockopt ); 33deffunc( setsockopt );
34deffunc( bind ); 34deffunc( bind );
35deffunc( listen ); 35deffunc( listen );
36deffunc( accept ); 36deffunc( accept );
37deffunc( recv ); 37deffunc( recv );
38deffunc( send ); 38deffunc( send );
39deffunc( __WSAFDIsSet ); 39deffunc( __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
49Bu::Winsock2::Winsock2() 49Bu::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
80Bu::Winsock2::~Winsock2() 80Bu::Winsock2::~Winsock2()
81{ 81{
82 Bu::Winsock2::WSACleanup(); 82 Bu::Winsock2::WSACleanup();
83 FreeLibrary( Ws2_32 ); 83 FreeLibrary( Ws2_32 );
84} 84}
85 85
86char *Bu::Winsock2::gai_strerror( int iCode ) 86char *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
92int Bu::Winsock2::WSAStartup( WORD a, LPWSADATA b ) { 92int 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}
95int Bu::Winsock2::WSACleanup( ) { 95int Bu::Winsock2::WSACleanup( ) {
96 return (*Bu::Winsock2::_fnptr_WSACleanup)(); 96 return (*Bu::Winsock2::_fnptr_WSACleanup)();
97} 97}
98int Bu::Winsock2::WSAGetLastError( ) { 98int Bu::Winsock2::WSAGetLastError( ) {
99 return (*Bu::Winsock2::_fnptr_WSAGetLastError)(); 99 return (*Bu::Winsock2::_fnptr_WSAGetLastError)();
100} 100}
101char * Bu::Winsock2::inet_ntoa( struct in_addr a ) { 101char * 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}
104unsigned long Bu::Winsock2::inet_addr( const char *s_in ) { 104unsigned 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}
107int Bu::Winsock2::select( int a, fd_set *b, fd_set *c, fd_set *d, 107int 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}
111SOCKET Bu::Winsock2::socket( int domain, int type, int protocol ) { 111SOCKET 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}
114int Bu::Winsock2::shutdown( SOCKET s, int how ) { 114int 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}
117int Bu::Winsock2::ioctlsocket( SOCKET s, long cmd, u_long *argp ) { 117int 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}
120u_short Bu::Winsock2::htons( u_short in ) { 120u_short Bu::Winsock2::htons( u_short in ) {
121 return (*Bu::Winsock2::_fnptr_htons)( in ); 121 return (*Bu::Winsock2::_fnptr_htons)( in );
122} 122}
123u_long Bu::Winsock2::htonl( u_long in ) { 123u_long Bu::Winsock2::htonl( u_long in ) {
124 return (*Bu::Winsock2::_fnptr_htonl)( in ); 124 return (*Bu::Winsock2::_fnptr_htonl)( in );
125} 125}
126struct hostent * Bu::Winsock2::gethostbyname( const char *name ) { 126struct hostent * Bu::Winsock2::gethostbyname( const char *name ) {
127 return (*Bu::Winsock2::_fnptr_gethostbyname)( name ); 127 return (*Bu::Winsock2::_fnptr_gethostbyname)( name );
128} 128}
129void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) { 129void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) {
130 return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai ); 130 return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai );
131} 131}
132int Bu::Winsock2::getaddrinfo( const char *a, const char *b, 132int 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}
136int Bu::Winsock2::connect( SOCKET s, const struct sockaddr *a, int b ) { 136int 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}
139int Bu::Winsock2::getpeername( SOCKET s, struct sockaddr *a, int *b ) { 139int 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}
142int Bu::Winsock2::setsockopt( SOCKET s, int a, int b, 142int 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}
146int Bu::Winsock2::bind( SOCKET s, const struct sockaddr *a, int b ) { 146int 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}
149int Bu::Winsock2::listen( SOCKET s, int backlog ) { 149int 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}
152SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) { 152SOCKET 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}
155int Bu::Winsock2::recv( SOCKET s, char *buf, int len, int flags ) { 155int 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}
158int Bu::Winsock2::send( SOCKET s, const char *buf, int len, int flags ) { 158int 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}
161int Bu::Winsock2::__WSAFDIsSet( SOCKET s, fd_set *set ) { 161int 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
165Bu::String Bu::getLastWinError() 165Bu::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
45namespace Bu 45namespace 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
30namespace Bu 30namespace 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
19namespace Bu 19namespace 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
15namespace Bu 15namespace 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
13namespace Bu 13namespace 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
24namespace Bu 24namespace 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
19namespace Bu 19namespace 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
14namespace Bu 14namespace 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
7namespace Bu 7namespace 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
7namespace Bu 7namespace 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
4namespace Bu 4namespace 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
7namespace Bu 7namespace 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
7namespace Bu 7namespace 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;
21using Bu::Fmt; 21using Bu::Fmt;
22 22
23Bu::FastCgi::FastCgi() : 23Bu::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
30Bu::FastCgi::FastCgi( int iPort ) : 30Bu::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
37Bu::FastCgi::~FastCgi() 37Bu::FastCgi::~FastCgi()
@@ -41,332 +41,332 @@ Bu::FastCgi::~FastCgi()
41bool Bu::FastCgi::isEmbedded() 41bool 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
67void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::Record &r ) 67void 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
77void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::Record r ) 77void 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
85void Bu::FastCgi::read( Bu::TcpSocket &s, Bu::FastCgi::BeginRequestBody &b ) 85void 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
91void Bu::FastCgi::write( Bu::TcpSocket &s, Bu::FastCgi::EndRequestBody b ) 91void 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
97uint32_t Bu::FastCgi::readLen( Bu::TcpSocket &s, uint16_t &uRead ) 97uint32_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
110void Bu::FastCgi::readPair( Bu::TcpSocket &s, StrHash &hParams, uint16_t &uRead ) 110void 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
134bool Bu::FastCgi::hasChannel( int iChan ) 134bool 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
143Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::FastCgi::Record &r ) 143Bu::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
155void Bu::FastCgi::run() 155void 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
17namespace Bu 17namespace 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
4namespace Bu 4namespace 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
10Bu::HttpGet::HttpGet( const Bu::Url &uSrc, const Bu::String &sMethod ) : 10Bu::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
18Bu::HttpGet::~HttpGet() 18Bu::HttpGet::~HttpGet()
@@ -25,28 +25,28 @@ void Bu::HttpGet::close()
25 25
26void Bu::HttpGet::get() 26void 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
37Bu::size Bu::HttpGet::read( void * /*pBuf*/, Bu::size /*nBytes*/ ) 37Bu::size Bu::HttpGet::read( void * /*pBuf*/, Bu::size /*nBytes*/ )
38{ 38{
39 return 0; 39 return 0;
40} 40}
41 41
42Bu::size Bu::HttpGet::write( const void * /*pBuf*/, Bu::size /*nBytes*/ ) 42Bu::size Bu::HttpGet::write( const void * /*pBuf*/, Bu::size /*nBytes*/ )
43{ 43{
44 return 0; 44 return 0;
45} 45}
46 46
47Bu::size Bu::HttpGet::tell() 47Bu::size Bu::HttpGet::tell()
48{ 48{
49 return 0; 49 return 0;
50} 50}
51 51
52void Bu::HttpGet::seek( Bu::size ) 52void Bu::HttpGet::seek( Bu::size )
@@ -63,12 +63,12 @@ void Bu::HttpGet::setPosEnd( Bu::size )
63 63
64bool Bu::HttpGet::isEos() 64bool Bu::HttpGet::isEos()
65{ 65{
66 return false; 66 return false;
67} 67}
68 68
69bool Bu::HttpGet::isOpen() 69bool Bu::HttpGet::isOpen()
70{ 70{
71 return true; 71 return true;
72} 72}
73 73
74void Bu::HttpGet::flush() 74void Bu::HttpGet::flush()
@@ -77,32 +77,32 @@ void Bu::HttpGet::flush()
77 77
78bool Bu::HttpGet::canRead() 78bool Bu::HttpGet::canRead()
79{ 79{
80 return true; 80 return true;
81} 81}
82 82
83bool Bu::HttpGet::canWrite() 83bool Bu::HttpGet::canWrite()
84{ 84{
85 return false; 85 return false;
86} 86}
87 87
88bool Bu::HttpGet::isReadable() 88bool Bu::HttpGet::isReadable()
89{ 89{
90 return true; 90 return true;
91} 91}
92 92
93bool Bu::HttpGet::isWritable() 93bool Bu::HttpGet::isWritable()
94{ 94{
95 return false; 95 return false;
96} 96}
97 97
98bool Bu::HttpGet::isSeekable() 98bool Bu::HttpGet::isSeekable()
99{ 99{
100 return false; 100 return false;
101} 101}
102 102
103bool Bu::HttpGet::isBlocking() 103bool Bu::HttpGet::isBlocking()
104{ 104{
105 return true; 105 return true;
106} 106}
107 107
108void Bu::HttpGet::setBlocking( bool /*bBlocking*/ ) 108void Bu::HttpGet::setBlocking( bool /*bBlocking*/ )
@@ -111,16 +111,16 @@ void Bu::HttpGet::setBlocking( bool /*bBlocking*/ )
111 111
112Bu::size Bu::HttpGet::getSize() const 112Bu::size Bu::HttpGet::getSize() const
113{ 113{
114 return 0; 114 return 0;
115} 115}
116 116
117Bu::size Bu::HttpGet::getBlockSize() const 117Bu::size Bu::HttpGet::getBlockSize() const
118{ 118{
119 return 0; 119 return 0;
120} 120}
121 121
122Bu::String Bu::HttpGet::getLocation() const 122Bu::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
17namespace Bu 17namespace 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
20Bu::Lexer::Token::Token() : 20Bu::Lexer::Token::Token() :
21 iToken( -1 ) 21 iToken( -1 )
22{ 22{
23} 23}
24 24
25Bu::Lexer::Token::Token( Bu::Lexer::TokenType iToken ) : 25Bu::Lexer::Token::Token( Bu::Lexer::TokenType iToken ) :
26 iToken( iToken ) 26 iToken( iToken )
27{ 27{
28} 28}
29 29
30Bu::String Bu::Lexer::tokenToString( const Bu::Lexer::Token &t ) 30Bu::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
13namespace Bu 13namespace 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
22void Bu::Parser::pushLexer( Lexer *pLex ) 22void Bu::Parser::pushLexer( Lexer *pLex )
23{ 23{
24 sLexer.push( pLex ); 24 sLexer.push( pLex );
25} 25}
26 26
27void Bu::Parser::popLexer() 27void Bu::Parser::popLexer()
28{ 28{
29 delete sLexer.peekPop(); 29 delete sLexer.peekPop();
30} 30}
31 31
32Lexer::Token *Bu::Parser::popToken() 32Lexer::Token *Bu::Parser::popToken()
33{ 33{
34 return sToken.peekPop(); 34 return sToken.peekPop();
35} 35}
36 36
37void Bu::Parser::pushToken( Lexer::Token *pTok ) 37void Bu::Parser::pushToken( Lexer::Token *pTok )
38{ 38{
39 sToken.push( pTok ); 39 sToken.push( pTok );
40} 40}
41 41
42void Bu::Parser::parse() 42void 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
108bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) 108bool 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
160void Bu::Parser::advanceState() 160void 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
177void Bu::Parser::setRootNonTerminal( int iRoot ) 177void Bu::Parser::setRootNonTerminal( int iRoot )
178{ 178{
179 iRootNonTerminal = iRoot; 179 iRootNonTerminal = iRoot;
180} 180}
181 181
182void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) 182void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot )
183{ 183{
184 setRootNonTerminal( hNonTerminalName.get( sRoot ) ); 184 setRootNonTerminal( hNonTerminalName.get( sRoot ) );
185} 185}
186 186
187int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) 187int 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
196int Bu::Parser::addNonTerminal( const Bu::String &sName ) 196int 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
205void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) 205void 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
210int Bu::Parser::getNonTerminalId( const Bu::String &sName ) 210int Bu::Parser::getNonTerminalId( const Bu::String &sName )
211{ 211{
212 return hNonTerminalName.get( sName ); 212 return hNonTerminalName.get( sName );
213} 213}
214 214
215bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) 215bool Bu::Parser::hasNonTerminal( const Bu::String &sName )
216{ 216{
217 return hNonTerminalName.has( sName ); 217 return hNonTerminalName.has( sName );
218} 218}
219 219
220int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) 220int 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
228int Bu::Parser::addReduction( const Bu::String &sName ) 228int 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
236void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) 236void 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
241int Bu::Parser::getReductionId( const Bu::String &sName ) 241int Bu::Parser::getReductionId( const Bu::String &sName )
242{ 242{
243 return hReductionName.get( sName ); 243 return hReductionName.get( sName );
244} 244}
245 245
246bool Bu::Parser::hasReduction( const Bu::String &sName ) 246bool 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
255Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : 255Bu::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
269Bu::Parser::NonTerminal::NonTerminal() : 269Bu::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
278void Bu::Parser::NonTerminal::addProduction( Production p ) 278void Bu::Parser::NonTerminal::addProduction( Production p )
279{ 279{
280 lProduction.append( p ); 280 lProduction.append( p );
281} 281}
282 282
283void Bu::Parser::NonTerminal::setCanSkip() 283void Bu::Parser::NonTerminal::setCanSkip()
284{ 284{
285 bCanSkip = true; 285 bCanSkip = true;
286} 286}
287 287
288Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) 288Bu::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
307Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) 307Bu::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
19namespace Bu 19namespace 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 };
130Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ); 130Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t );
131Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::Parser::State &s ); 131Bu::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
15Bu::RegEx::RegEx() : 15Bu::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
22Bu::RegEx::RegEx( const Bu::String &sSrc ) : 22Bu::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
30Bu::RegEx::~RegEx() 30Bu::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
40void Bu::RegEx::compile( const Bu::String &sSrc ) 40void 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
68int Bu::RegEx::getNumSubStrings() 68int Bu::RegEx::getNumSubStrings()
69{ 69{
70 return nSubStr; 70 return nSubStr;
71} 71}
72 72
73bool Bu::RegEx::execute( const Bu::String &sSrc ) 73bool 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
81void Bu::RegEx::getSubStringRange( int nIndex, int &iStart, int &iEnd ) 81void 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
87Bu::String Bu::RegEx::getSubString( int nIndex ) 87Bu::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
15namespace Bu 15namespace 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
8namespace Bu 8namespace 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 @@
11namespace Bu { subExceptionDef( XmlException ) } 11namespace Bu { subExceptionDef( XmlException ) }
12 12
13Bu::XmlReader::XmlReader( Stream &rInput ) : 13Bu::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
23Bu::XmlReader::~XmlReader() 23Bu::XmlReader::~XmlReader()
@@ -26,148 +26,148 @@ Bu::XmlReader::~XmlReader()
26 26
27void Bu::XmlReader::fillBuffer() 27void 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
36void Bu::XmlReader::cleanupBuffer( int iUsed ) 36void 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
55int Bu::XmlReader::nextToken() 55int 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
148void Bu::XmlReader::error( const char *sMessage ) 148void 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
154void Bu::XmlReader::stDocument() 154void Bu::XmlReader::stDocument()
155{ 155{
156 stProlog(); 156 stProlog();
157} 157}
158 158
159void Bu::XmlReader::stProlog() 159void Bu::XmlReader::stProlog()
160{ 160{
161 stXmlDecl(); 161 stXmlDecl();
162} 162}
163 163
164void Bu::XmlReader::stXmlDecl() 164void 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
14namespace Bu 14namespace 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
30extern "C" { 30extern "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
18Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) 18Bu::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
24Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) 24Bu::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
30Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) 30Bu::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
13namespace Bu 13namespace 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
14Bu::Archive::Archive( Stream &rStream, bool bLoading ) : 14Bu::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
25void Bu::Archive::write( const void *pData, size_t nSize ) 25void 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
33void Bu::Archive::read( void *pData, size_t nSize ) 33void 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
42void Bu::Archive::close() 42void Bu::Archive::close()
43{ 43{
44 rStream.close(); 44 rStream.close();
45} 45}
46 46
47bool Bu::Archive::isLoading() 47bool Bu::Archive::isLoading()
48{ 48{
49 return bLoading; 49 return bLoading;
50} 50}
51 51
52uint32_t Bu::Archive::getID( const void *ptr ) 52uint32_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
60void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) 60void 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
74void Bu::Archive::readID( const void *ptr, uint32_t id ) 74void 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
17namespace Bu 17namespace 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
18Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) 18Bu::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
24Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) 24Bu::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
30Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) 30Bu::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
36Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) 36Bu::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
42Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) 42Bu::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
48Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) 48Bu::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
54Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) 54Bu::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
60Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) 60Bu::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
66Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) 66Bu::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
72Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) 72Bu::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
78Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) 78Bu::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
84Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) 84Bu::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
90Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) 90Bu::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
96Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) 96Bu::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
102Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) 102Bu::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
108Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) 108Bu::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
114Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) 114Bu::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
120Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) 120Bu::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
126Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) 126Bu::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
132Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) 132Bu::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
138Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) 138Bu::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
144Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) 144Bu::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
150Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) 150Bu::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
156Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) 156Bu::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
162Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) 162Bu::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
168Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) 168Bu::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
174Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) 174Bu::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
180Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) 180Bu::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
186Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) 186Bu::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
192Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) 192Bu::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
14namespace Bu 14namespace 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
16namespace Bu 16namespace 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
16namespace Bu 16namespace 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 @@
10namespace Bu { subExceptionDef( Base64Exception ) } 10namespace Bu { subExceptionDef( Base64Exception ) }
11 11
12const char Bu::Base64::tblEnc[65] = { 12const char Bu::Base64::tblEnc[65] = {
13 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 13 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
14}; 14};
15 15
16Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : 16Bu::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
60Bu::Base64::~Base64() 60Bu::Base64::~Base64()
61{ 61{
62 stop(); 62 stop();
63} 63}
64 64
65void Bu::Base64::start() 65void Bu::Base64::start()
66{ 66{
67 iCurChunk = 0; 67 iCurChunk = 0;
68} 68}
69 69
70Bu::size Bu::Base64::stop() 70Bu::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
104Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) 104Bu::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
174Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) 174Bu::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
208bool Bu::Base64::isOpen() 208bool Bu::Base64::isOpen()
209{ 209{
210 return true; 210 return true;
211} 211}
212 212
213bool Bu::Base64::isEos() 213bool 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
14namespace Bu 14namespace 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
10Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : 10Bu::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
26Bu::Buffer::~Buffer() 26Bu::Buffer::~Buffer()
27{ 27{
28 flush(); 28 flush();
29 delete[] sReadBuf; 29 delete[] sReadBuf;
30 delete[] sWriteBuf; 30 delete[] sWriteBuf;
31} 31}
32 32
33void Bu::Buffer::start() 33void Bu::Buffer::start()
@@ -36,135 +36,135 @@ void Bu::Buffer::start()
36 36
37Bu::size Bu::Buffer::stop() 37Bu::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
44void Bu::Buffer::fillReadBuf() 44void 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
55Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) 55Bu::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
96Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) 96Bu::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
147void Bu::Buffer::flush() 147void 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
166bool Bu::Buffer::isEos() 166bool 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
13namespace Bu 13namespace 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 @@
15using namespace Bu; 15using namespace Bu;
16 16
17Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : 17Bu::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
27Bu::BZip2::~BZip2() 27Bu::BZip2::~BZip2()
28{ 28{
29 TRACE(); 29 TRACE();
30 stop(); 30 stop();
31} 31}
32 32
33void Bu::BZip2::start() 33void 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
47Bu::size Bu::BZip2::stop() 47Bu::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
92void Bu::BZip2::bzError( int code ) 92void 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
136Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) 136Bu::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
194Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) 194Bu::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
226bool Bu::BZip2::isOpen() 226bool Bu::BZip2::isOpen()
227{ 227{
228 TRACE(); 228 TRACE();
229 return (pState->state != NULL); 229 return (pState->state != NULL);
230} 230}
231 231
232Bu::size Bu::BZip2::getCompressedSize() 232Bu::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
15namespace Bu 15namespace 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
19Bu::Client::Client( Bu::TcpSocket *pSocket, 19Bu::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
30Bu::Client::~Client() 30Bu::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
40void Bu::Client::processInput() 40void 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
83void Bu::Client::processOutput() 83void 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
96void Bu::Client::setProtocol( Protocol *pProto ) 96void 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
102Bu::Protocol *Bu::Client::getProtocol() 102Bu::Protocol *Bu::Client::getProtocol()
103{ 103{
104 return pProto; 104 return pProto;
105} 105}
106 106
107void Bu::Client::clearProtocol() 107void Bu::Client::clearProtocol()
108{ 108{
109 pProto = NULL; 109 pProto = NULL;
110} 110}
111/* 111/*
112Bu::String &Bu::Client::getInput() 112Bu::String &Bu::Client::getInput()
113{ 113{
114 return sReadBuf; 114 return sReadBuf;
115} 115}
116 116
117Bu::String &Bu::Client::getOutput() 117Bu::String &Bu::Client::getOutput()
118{ 118{
119 return sWriteBuf; 119 return sWriteBuf;
120} 120}
121*/ 121*/
122 122
123bool Bu::Client::isOpen() 123bool 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
129Bu::size Bu::Client::write( const Bu::String &sData ) 129Bu::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
134Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) 134Bu::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
139Bu::size Bu::Client::write( int8_t nData ) 139Bu::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
144Bu::size Bu::Client::write( int16_t nData ) 144Bu::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
149Bu::size Bu::Client::write( int32_t nData ) 149Bu::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
154Bu::size Bu::Client::write( int64_t nData ) 154Bu::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
159Bu::size Bu::Client::write( uint8_t nData ) 159Bu::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
164Bu::size Bu::Client::write( uint16_t nData ) 164Bu::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
169Bu::size Bu::Client::write( uint32_t nData ) 169Bu::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
174Bu::size Bu::Client::write( uint64_t nData ) 174Bu::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
179Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) 179Bu::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
184Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) 184Bu::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
189Bu::size Bu::Client::getInputSize() 189Bu::size Bu::Client::getInputSize()
190{ 190{
191 return qbRead.getSize(); 191 return qbRead.getSize();
192} 192}
193 193
194Bu::size Bu::Client::getOutputSize() 194Bu::size Bu::Client::getOutputSize()
195{ 195{
196 return qbWrite.getSize(); 196 return qbWrite.getSize();
197} 197}
198 198
199const Bu::TcpSocket *Bu::Client::getSocket() const 199const Bu::TcpSocket *Bu::Client::getSocket() const
200{ 200{
201 return pSocket; 201 return pSocket;
202} 202}
203 203
204void Bu::Client::disconnect() 204void Bu::Client::disconnect()
205{ 205{
206 bWantsDisconnect = true; 206 bWantsDisconnect = true;
207} 207}
208 208
209bool Bu::Client::wantsDisconnect() 209bool Bu::Client::wantsDisconnect()
210{ 210{
211 return bWantsDisconnect; 211 return bWantsDisconnect;
212} 212}
213 213
214void Bu::Client::close() 214void Bu::Client::close()
215{ 215{
216 pTopStream->close(); 216 pTopStream->close();
217} 217}
218 218
219Bu::ClientLink *Bu::Client::getLink() 219Bu::ClientLink *Bu::Client::getLink()
220{ 220{
221 return pfLink->createLink( this ); 221 return pfLink->createLink( this );
222} 222}
223 223
224void Bu::Client::onMessage( const Bu::String &sMsg ) 224void 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
230void Bu::Client::tick() 230void Bu::Client::tick()
231{ 231{
232 if( pProto ) 232 if( pProto )
233 pProto->onTick( this ); 233 pProto->onTick( this );
234} 234}
235 235
236Bu::size Bu::Client::tell() 236Bu::size Bu::Client::tell()
237{ 237{
238 return 0; 238 return 0;
239} 239}
240 240
241void Bu::Client::seek( Bu::size offset ) 241void Bu::Client::seek( Bu::size offset )
242{ 242{
243 return qbRead.seek( offset ); 243 return qbRead.seek( offset );
244} 244}
245 245
246void Bu::Client::setPos( Bu::size ) 246void Bu::Client::setPos( Bu::size )
247{ 247{
248 throw Bu::ExceptionBase(); 248 throw Bu::ExceptionBase();
249} 249}
250 250
251void Bu::Client::setPosEnd( Bu::size ) 251void Bu::Client::setPosEnd( Bu::size )
252{ 252{
253 throw Bu::ExceptionBase(); 253 throw Bu::ExceptionBase();
254} 254}
255 255
256bool Bu::Client::isEos() 256bool Bu::Client::isEos()
257{ 257{
258 return true; 258 return true;
259} 259}
260 260
261void Bu::Client::flush() 261void Bu::Client::flush()
262{ 262{
263 processOutput(); 263 processOutput();
264} 264}
265 265
266bool Bu::Client::canRead() 266bool Bu::Client::canRead()
267{ 267{
268 return qbRead.getSize() > 0; 268 return qbRead.getSize() > 0;
269} 269}
270 270
271bool Bu::Client::canWrite() 271bool Bu::Client::canWrite()
272{ 272{
273 return true; 273 return true;
274} 274}
275 275
276bool Bu::Client::isReadable() 276bool Bu::Client::isReadable()
277{ 277{
278 return true; 278 return true;
279} 279}
280 280
281bool Bu::Client::isWritable() 281bool Bu::Client::isWritable()
282{ 282{
283 return true; 283 return true;
284} 284}
285 285
286bool Bu::Client::isSeekable() 286bool Bu::Client::isSeekable()
287{ 287{
288 return false; 288 return false;
289} 289}
290 290
291bool Bu::Client::isBlocking() 291bool Bu::Client::isBlocking()
292{ 292{
293 return false; 293 return false;
294} 294}
295 295
296void Bu::Client::setBlocking( bool ) 296void Bu::Client::setBlocking( bool )
297{ 297{
298 throw Bu::ExceptionBase(); 298 throw Bu::ExceptionBase();
299} 299}
300 300
301void Bu::Client::setSize( Bu::size ) 301void Bu::Client::setSize( Bu::size )
302{ 302{
303 throw Bu::ExceptionBase(); 303 throw Bu::ExceptionBase();
304} 304}
305 305
306Bu::size Bu::Client::getSize() const 306Bu::size Bu::Client::getSize() const
307{ 307{
308 return 0; 308 return 0;
309} 309}
310 310
311Bu::size Bu::Client::getBlockSize() const 311Bu::size Bu::Client::getBlockSize() const
312{ 312{
313 return pSocket->getBlockSize(); 313 return pSocket->getBlockSize();
314} 314}
315 315
316Bu::String Bu::Client::getLocation() const 316Bu::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
17namespace Bu 17namespace 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
13namespace Bu 13namespace 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
11namespace Bu 11namespace 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
12Bu::Condition::Condition() 12Bu::Condition::Condition()
13{ 13{
14 pthread_cond_init( &cond, NULL ); 14 pthread_cond_init( &cond, NULL );
15} 15}
16 16
17Bu::Condition::~Condition() 17Bu::Condition::~Condition()
18{ 18{
19 pthread_cond_destroy( &cond ); 19 pthread_cond_destroy( &cond );
20} 20}
21 21
22int Bu::Condition::wait() 22int Bu::Condition::wait()
23{ 23{
24 return pthread_cond_wait( &cond, &mutex ); 24 return pthread_cond_wait( &cond, &mutex );
25} 25}
26 26
27int Bu::Condition::wait( int nSec, int nUSec ) 27int 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
40int Bu::Condition::signal() 40int Bu::Condition::signal()
41{ 41{
42 return pthread_cond_signal( &cond ); 42 return pthread_cond_signal( &cond );
43} 43}
44 44
45int Bu::Condition::broadcast() 45int 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
15namespace Bu 15namespace 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
10Bu::Conduit::Conduit( int iBlockSize ) : 10Bu::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
21void Bu::Conduit::close() 21void 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>
32Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) 32Bu::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
78Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) 78Bu::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
87Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) 87Bu::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
96Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) 96Bu::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
111Bu::size Bu::Conduit::tell() 111Bu::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
119void Bu::Conduit::seek( Bu::size ) 119void Bu::Conduit::seek( Bu::size )
@@ -130,18 +130,18 @@ void Bu::Conduit::setPosEnd( Bu::size )
130 130
131bool Bu::Conduit::isEos() 131bool 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
139bool Bu::Conduit::isOpen() 139bool 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
147void Bu::Conduit::flush() 147void Bu::Conduit::flush()
@@ -150,57 +150,57 @@ void Bu::Conduit::flush()
150 150
151bool Bu::Conduit::canRead() 151bool 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
159bool Bu::Conduit::canWrite() 159bool 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
167bool Bu::Conduit::isReadable() 167bool 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
175bool Bu::Conduit::isWritable() 175bool 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
183bool Bu::Conduit::isSeekable() 183bool 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
191bool Bu::Conduit::isBlocking() 191bool 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
199void Bu::Conduit::setBlocking( bool bBlocking ) 199void 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
206void Bu::Conduit::setSize( Bu::size ) 206void Bu::Conduit::setSize( Bu::size )
@@ -209,25 +209,25 @@ void Bu::Conduit::setSize( Bu::size )
209 209
210Bu::size Bu::Conduit::getSize() const 210Bu::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
218Bu::size Bu::Conduit::getBlockSize() const 218Bu::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
226Bu::String Bu::Conduit::getLocation() const 226Bu::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
17namespace Bu 17namespace 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
14Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) 14Bu::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
32Bu::String Bu::cryptPass( const Bu::String &sPass ) 32Bu::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
13namespace Bu 13namespace 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
18void Bu::CryptoHash::addData( const Bu::String &sData ) 18void 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
23Bu::String Bu::CryptoHash::getHexResult() 23Bu::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
13namespace Bu 13namespace 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 @@
12using namespace Bu; 12using namespace Bu;
13 13
14Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : 14Bu::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
29Bu::CsvReader::CsvReader( Bu::Stream &sIn, 29Bu::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
40Bu::StrArray Bu::CsvReader::readLine() 40Bu::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
76Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) 76Bu::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
15namespace Bu 15namespace 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
11Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : 11Bu::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
26Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, 26Bu::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
37void Bu::CsvWriter::writeLine( const StrArray &aStrs ) 37void 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
51Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) 51Bu::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
69Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) 69Bu::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
15namespace Bu 15namespace 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 @@
15using namespace Bu; 15using namespace Bu;
16 16
17Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : 17Bu::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
29Bu::Deflate::~Deflate() 29Bu::Deflate::~Deflate()
30{ 30{
31 TRACE(); 31 TRACE();
32 stop(); 32 stop();
33} 33}
34 34
35void Bu::Deflate::start() 35void 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
48Bu::size Bu::Deflate::stop() 48Bu::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
89void Bu::Deflate::zError( int code ) 89void 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
123Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) 123Bu::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
193Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) 193Bu::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
237bool Bu::Deflate::isOpen() 237bool 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
243bool Bu::Deflate::isEos() 243bool Bu::Deflate::isEos()
244{ 244{
245 TRACE(); 245 TRACE();
246 return bEos; 246 return bEos;
247} 247}
248 248
249Bu::size Bu::Deflate::getCompressedSize() 249Bu::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
15namespace Bu 15namespace 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
13Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : 13Bu::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
24Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : 24Bu::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
35Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : 35Bu::ExceptionBase::ExceptionBase( int nCode ) throw() :
36 nErrorCode( nCode ), 36 nErrorCode( nCode ),
37 sWhat( NULL ) 37 sWhat( NULL )
38{ 38{
39} 39}
40 40
41Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : 41Bu::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
49Bu::ExceptionBase::~ExceptionBase() throw() 49Bu::ExceptionBase::~ExceptionBase() throw()
50{ 50{
51 delete[] sWhat; 51 delete[] sWhat;
52 sWhat = NULL; 52 sWhat = NULL;
53} 53}
54 54
55void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) 55void 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
68void Bu::ExceptionBase::setWhat( const char *lpText ) 68void 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
78const char *Bu::ExceptionBase::what() const throw() 78const char *Bu::ExceptionBase::what() const throw()
79{ 79{
80 return sWhat; 80 return sWhat;
81} 81}
82 82
83int Bu::ExceptionBase::getErrorCode() 83int Bu::ExceptionBase::getErrorCode()
84{ 84{
85 return nErrorCode; 85 return nErrorCode;
86} 86}
87 87
88Bu::UnsupportedException::UnsupportedException() throw() : 88Bu::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
19namespace Bu 19namespace 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 ) \
97class name : public Bu::ExceptionBase \ 97class 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 ) \
107class name : public parent \ 107class 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 ) \
117class name : public Bu::ExceptionBase \ 117class 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 ) \
129name::name( const char *lpFormat, ... ) throw() : \ 129name::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} \
137name::name( int nCode, const char *lpFormat, ... ) throw() : \ 137name::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} \
145name::name( int nCode ) throw() : \ 145name::name( int nCode ) throw() : \
146 ExceptionBase( nCode ) \ 146 ExceptionBase( nCode ) \
147{ \ 147{ \
148} \ 148} \
149name::name( const name &e ) throw() : \ 149name::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 ) \
155name::name( const char *lpFormat, ... ) throw() : \ 155name::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} \
163name::name( int nCode, const char *lpFormat, ... ) throw() : \ 163name::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} \
171name::name( int nCode ) throw() : \ 171name::name( int nCode ) throw() : \
172 parent( nCode ) \ 172 parent( nCode ) \
173{ \ 173{ \
174} \ 174} \
175name::name( const name &e ) throw() : \ 175name::name( const name &e ) throw() : \
176 ExceptionBase( e ) \ 176 ExceptionBase( e ) \
177{ \ 177{ \
178} 178}
179 179
180namespace Bu 180namespace 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 @@
19namespace Bu 19namespace 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 @@
19namespace Bu { subExceptionDef( FileException ) } 19namespace Bu { subExceptionDef( FileException ) }
20 20
21Bu::File::File( const Bu::String &sName, int iFlags ) : 21Bu::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
38Bu::File::File( int fd ) : 38Bu::File::File( int fd ) :
39 fd( fd ) 39 fd( fd )
40{ 40{
41 bEos = false; 41 bEos = false;
42} 42}
43 43
44Bu::File::~File() 44Bu::File::~File()
45{ 45{
46 close(); 46 close();
47} 47}
48 48
49void Bu::File::close() 49void 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
63Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) 63Bu::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
78Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) 78Bu::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
89Bu::size Bu::File::tell() 89Bu::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
101void Bu::File::seek( Bu::size offset ) 101void 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
114void Bu::File::setPos( Bu::size pos ) 114void 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
127void Bu::File::setPosEnd( Bu::size pos ) 127void 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
136bool Bu::File::isEos() 136bool Bu::File::isEos()
137{ 137{
138 return bEos; 138 return bEos;
139} 139}
140 140
141bool Bu::File::canRead() 141bool 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
153bool Bu::File::canWrite() 153bool 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
165bool Bu::File::isReadable() 165bool Bu::File::isReadable()
166{ 166{
167 return true; 167 return true;
168} 168}
169 169
170bool Bu::File::isWritable() 170bool Bu::File::isWritable()
171{ 171{
172 return true; 172 return true;
173} 173}
174 174
175bool Bu::File::isSeekable() 175bool Bu::File::isSeekable()
176{ 176{
177 return true; 177 return true;
178} 178}
179 179
180bool Bu::File::isBlocking() 180bool Bu::File::isBlocking()
181{ 181{
182 return true; 182 return true;
183} 183}
184 184
185void Bu::File::setBlocking( bool bBlocking ) 185void 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
203Bu::File Bu::File::tempFile( Bu::String &sName ) 203Bu::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
232void Bu::File::setSize( Bu::size iSize ) 232void 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
241Bu::size Bu::File::getSize() const 241Bu::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
248Bu::size Bu::File::getBlockSize() const 248Bu::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
259Bu::String Bu::File::getLocation() const 259Bu::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
265void Bu::File::chmod( mode_t t ) 265void Bu::File::chmod( mode_t t )
266{ 266{
267 fchmod( fd, t ); 267 fchmod( fd, t );
268} 268}
269#endif 269#endif
270 270
271void Bu::File::flush() 271void 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
277bool Bu::File::isOpen() 277bool Bu::File::isOpen()
278{ 278{
279 return (fd > -1); 279 return (fd > -1);
280} 280}
281 281
282int Bu::File::getPosixFlags( int iFlags ) 282int 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
18namespace Bu 18namespace 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
10Bu::Filter::Filter( Bu::Stream &rNext ) : 10Bu::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
19void Bu::Filter::close() 19void Bu::Filter::close()
20{ 20{
21 stop(); 21 stop();
22 rNext.close(); 22 rNext.close();
23} 23}
24 24
25Bu::size Bu::Filter::tell() 25Bu::size Bu::Filter::tell()
26{ 26{
27 return rNext.tell(); 27 return rNext.tell();
28} 28}
29 29
30void Bu::Filter::seek( Bu::size offset ) 30void Bu::Filter::seek( Bu::size offset )
31{ 31{
32 rNext.seek( offset ); 32 rNext.seek( offset );
33} 33}
34 34
35void Bu::Filter::setPos( Bu::size pos ) 35void Bu::Filter::setPos( Bu::size pos )
36{ 36{
37 rNext.setPos( pos ); 37 rNext.setPos( pos );
38} 38}
39 39
40void Bu::Filter::setPosEnd( Bu::size pos ) 40void Bu::Filter::setPosEnd( Bu::size pos )
41{ 41{
42 rNext.setPosEnd( pos ); 42 rNext.setPosEnd( pos );
43} 43}
44 44
45bool Bu::Filter::isEos() 45bool Bu::Filter::isEos()
46{ 46{
47 return rNext.isEos(); 47 return rNext.isEos();
48} 48}
49 49
50bool Bu::Filter::isOpen() 50bool Bu::Filter::isOpen()
51{ 51{
52 return rNext.isOpen(); 52 return rNext.isOpen();
53} 53}
54 54
55bool Bu::Filter::canRead() 55bool Bu::Filter::canRead()
56{ 56{
57 return rNext.canRead(); 57 return rNext.canRead();
58} 58}
59 59
60bool Bu::Filter::canWrite() 60bool Bu::Filter::canWrite()
61{ 61{
62 return rNext.canWrite(); 62 return rNext.canWrite();
63} 63}
64 64
65bool Bu::Filter::isReadable() 65bool Bu::Filter::isReadable()
66{ 66{
67 return rNext.isReadable(); 67 return rNext.isReadable();
68} 68}
69 69
70bool Bu::Filter::isWritable() 70bool Bu::Filter::isWritable()
71{ 71{
72 return rNext.isWritable(); 72 return rNext.isWritable();
73} 73}
74 74
75bool Bu::Filter::isSeekable() 75bool Bu::Filter::isSeekable()
76{ 76{
77 return rNext.isSeekable(); 77 return rNext.isSeekable();
78} 78}
79 79
80bool Bu::Filter::isBlocking() 80bool Bu::Filter::isBlocking()
81{ 81{
82 return rNext.isBlocking(); 82 return rNext.isBlocking();
83} 83}
84 84
85void Bu::Filter::setBlocking( bool bBlocking ) 85void Bu::Filter::setBlocking( bool bBlocking )
86{ 86{
87 rNext.setBlocking( bBlocking ); 87 rNext.setBlocking( bBlocking );
88} 88}
89 89
90void Bu::Filter::setSize( Bu::size ) 90void Bu::Filter::setSize( Bu::size )
@@ -93,21 +93,21 @@ void Bu::Filter::setSize( Bu::size )
93 93
94void Bu::Filter::flush() 94void Bu::Filter::flush()
95{ 95{
96 rNext.flush(); 96 rNext.flush();
97} 97}
98 98
99Bu::size Bu::Filter::getSize() const 99Bu::size Bu::Filter::getSize() const
100{ 100{
101 return rNext.getSize(); 101 return rNext.getSize();
102} 102}
103 103
104Bu::size Bu::Filter::getBlockSize() const 104Bu::size Bu::Filter::getBlockSize() const
105{ 105{
106 return rNext.getBlockSize(); 106 return rNext.getBlockSize();
107} 107}
108 108
109Bu::String Bu::Filter::getLocation() const 109Bu::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
15namespace Bu 15namespace 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
4namespace Bu 4namespace 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 &center(); 82 Fmt &center();
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
13template<> float Bu::tlog( float x ) 13template<> float Bu::tlog( float x )
14{ 14{
15 return logf( x ); 15 return logf( x );
16} 16}
17 17
18template<> double Bu::tlog( double x ) 18template<> double Bu::tlog( double x )
19{ 19{
20 return log( x ); 20 return log( x );
21} 21}
22 22
23template<> long double Bu::tlog( long double x ) 23template<> long double Bu::tlog( long double x )
24{ 24{
25 return logl( x ); 25 return logl( x );
26} 26}
27 27
28template<> float Bu::tfloor( float x ) 28template<> float Bu::tfloor( float x )
29{ 29{
30 return floorf( x ); 30 return floorf( x );
31} 31}
32 32
33template<> double Bu::tfloor( double x ) 33template<> double Bu::tfloor( double x )
34{ 34{
35 return floor( x ); 35 return floor( x );
36} 36}
37 37
38template<> long double Bu::tfloor( long double x ) 38template<> long double Bu::tfloor( long double x )
39{ 39{
40 return floorl( x ); 40 return floorl( x );
41} 41}
42 42
43template<> float Bu::tpow( float x, float y ) 43template<> float Bu::tpow( float x, float y )
44{ 44{
45 return powf( x, y ); 45 return powf( x, y );
46} 46}
47 47
48template<> double Bu::tpow( double x, double y ) 48template<> double Bu::tpow( double x, double y )
49{ 49{
50 return pow( x, y ); 50 return pow( x, y );
51} 51}
52 52
53template<> long double Bu::tpow( long double x, long double y ) 53template<> 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
58Bu::Formatter::Formatter( Stream &rStream ) : 58Bu::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
70void Bu::Formatter::write( const Bu::String &sStr ) 70void Bu::Formatter::write( const Bu::String &sStr )
71{ 71{
72 rStream.write( sStr ); 72 rStream.write( sStr );
73} 73}
74 74
75void Bu::Formatter::write( const void *sStr, int iLen ) 75void Bu::Formatter::write( const void *sStr, int iLen )
76{ 76{
77 rStream.write( sStr, iLen ); 77 rStream.write( sStr, iLen );
78} 78}
79 79
80void Bu::Formatter::writeAligned( const Bu::String &sStr ) 80void 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
121void Bu::Formatter::writeAligned( const char *sStr, int iLen ) 121void 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
161void Bu::Formatter::read( void *sStr, int iLen ) 161void Bu::Formatter::read( void *sStr, int iLen )
162{ 162{
163 rStream.read( sStr, iLen ); 163 rStream.read( sStr, iLen );
164} 164}
165 165
166Bu::String Bu::Formatter::readToken() 166Bu::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
211void Bu::Formatter::incIndent() 211void Bu::Formatter::incIndent()
212{ 212{
213 if( uIndent < 0xFFU ) 213 if( uIndent < 0xFFU )
214 uIndent++; 214 uIndent++;
215} 215}
216 216
217void Bu::Formatter::decIndent() 217void Bu::Formatter::decIndent()
218{ 218{
219 if( uIndent > 0 ) 219 if( uIndent > 0 )
220 uIndent--; 220 uIndent--;
221} 221}
222 222
223void Bu::Formatter::setIndent( uint8_t uLevel ) 223void Bu::Formatter::setIndent( uint8_t uLevel )
224{ 224{
225 uIndent = uLevel; 225 uIndent = uLevel;
226} 226}
227 227
228void Bu::Formatter::clearIndent() 228void Bu::Formatter::clearIndent()
229{ 229{
230 uIndent = 0; 230 uIndent = 0;
231} 231}
232 232
233void Bu::Formatter::setIndentChar( char cIndent ) 233void Bu::Formatter::setIndentChar( char cIndent )
234{ 234{
235 this->cIndent = cIndent; 235 this->cIndent = cIndent;
236} 236}
237 237
238void Bu::Formatter::doFlush() 238void Bu::Formatter::doFlush()
239{ 239{
240 rStream.flush(); 240 rStream.flush();
241} 241}
242 242
243Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) 243Bu::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
249Bu::Fmt &Bu::Fmt::fill( char cFill ) 249Bu::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
255Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) 255Bu::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
261Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) 261Bu::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
267Bu::Fmt &Bu::Fmt::left() 267Bu::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
273Bu::Fmt &Bu::Fmt::center() 273Bu::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
279Bu::Fmt &Bu::Fmt::right() 279Bu::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
285Bu::Fmt &Bu::Fmt::plus( bool bPlus ) 285Bu::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
291Bu::Fmt &Bu::Fmt::caps( bool bCaps ) 291Bu::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
297Bu::Fmt &Bu::Fmt::upper() 297Bu::Fmt &Bu::Fmt::upper()
298{ 298{
299 this->bCaps = true; 299 this->bCaps = true;
300 return *this; 300 return *this;
301} 301}
302 302
303Bu::Fmt &Bu::Fmt::lower() 303Bu::Fmt &Bu::Fmt::lower()
304{ 304{
305 this->bCaps = false; 305 this->bCaps = false;
306 return *this; 306 return *this;
307} 307}
308 308
309Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) 309Bu::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
315Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) 315Bu::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
321Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) 321Bu::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
346Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) 346Bu::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
352Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) 352Bu::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
358Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) 358Bu::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
364Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) 364Bu::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
371Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) 371Bu::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
377Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) 377Bu::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
384Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) 384Bu::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
390Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) 390Bu::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
396Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) 396Bu::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
402Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) 402Bu::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
408Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) 408Bu::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
414Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) 414Bu::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
420Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) 420Bu::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
426Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) 426Bu::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
432Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) 432Bu::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
438Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) 438Bu::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
444Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) 444Bu::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
450Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) 450Bu::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
456Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) 456Bu::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
462Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) 462Bu::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
468Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) 468Bu::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
474Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) 474Bu::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
480Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) 480Bu::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
486Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) 486Bu::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
492Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) 492Bu::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
498Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) 498Bu::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
504Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) 504Bu::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
510Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) 510Bu::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
516Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) 516Bu::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
522Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) 522Bu::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
528Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) 528Bu::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
534Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) 534Bu::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
540Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) 540Bu::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
546Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) 546Bu::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
16namespace Bu 16namespace 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
10namespace Bu 10namespace 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
22namespace Bu 22namespace 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 ) }
12template<> 12template<>
13uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) 13uint32_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
29template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) 29template<> 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
41template<> 41template<>
42uint32_t Bu::__calcHashCode<char *>( char * const &k ) 42uint32_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
58template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) 58template<> 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
18namespace Bu 18namespace 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
18namespace Bu 18namespace 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
10Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : 10Bu::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
23void Bu::Hex::start() 23void Bu::Hex::start()
24{ 24{
25 iPos = iIn = 0; 25 iPos = iIn = 0;
26} 26}
27 27
28Bu::size Bu::Hex::stop() 28Bu::size Bu::Hex::stop()
29{ 29{
30 return iPos; 30 return iPos;
31} 31}
32 32
33Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) 33Bu::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
54Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) 54Bu::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
13namespace Bu 13namespace 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
17namespace Bu 17namespace 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
15Bu::Logger::Logger() 15Bu::Logger::Logger()
16{ 16{
17 setFormat("%t"); 17 setFormat("%t");
18} 18}
19 19
20Bu::Logger::~Logger() 20Bu::Logger::~Logger()
@@ -24,186 +24,186 @@ Bu::Logger::~Logger()
24void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) 24void 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
72void Bu::Logger::setFormat( const Bu::String &str ) 72void 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
132void Bu::Logger::setMask( uint32_t n ) 132void Bu::Logger::setMask( uint32_t n )
133{ 133{
134 nLevelMask = n; 134 nLevelMask = n;
135} 135}
136 136
137uint32_t Bu::Logger::getMask() 137uint32_t Bu::Logger::getMask()
138{ 138{
139 return nLevelMask; 139 return nLevelMask;
140} 140}
141 141
142void Bu::Logger::setLevel( uint32_t n ) 142void 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
159void Bu::Logger::hexDump( uint32_t nLevel, const char *sFile, 159void 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
14namespace Bu 14namespace 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 @@
15using namespace Bu; 15using namespace Bu;
16 16
17Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : 17Bu::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
29Bu::Lzma::~Lzma() 29Bu::Lzma::~Lzma()
30{ 30{
31 TRACE(); 31 TRACE();
32 stop(); 32 stop();
33} 33}
34 34
35void Bu::Lzma::start() 35void 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
42Bu::size Bu::Lzma::stop() 42Bu::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
83void Bu::Lzma::lzmaError( int code ) 83void 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
120Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) 120Bu::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
186Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) 186Bu::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
232bool Bu::Lzma::isOpen() 232bool Bu::Lzma::isOpen()
233{ 233{
234 TRACE(); 234 TRACE();
235 return (pState != NULL); 235 return (pState != NULL);
236} 236}
237 237
238bool Bu::Lzma::isEos() 238bool Bu::Lzma::isEos()
239{ 239{
240 TRACE(); 240 TRACE();
241 return bEos; 241 return bEos;
242} 242}
243 243
244Bu::size Bu::Lzma::getCompressedSize() 244Bu::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
15namespace Bu 15namespace 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
20Bu::Md5::Md5() 20Bu::Md5::Md5()
21{ 21{
22 reset(); 22 reset();
23} 23}
24 24
25Bu::Md5::~Md5() 25Bu::Md5::~Md5()
@@ -28,15 +28,15 @@ Bu::Md5::~Md5()
28 28
29void Bu::Md5::reset() 29void 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
42void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) 42void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ )
@@ -45,102 +45,102 @@ void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ )
45 45
46void Bu::Md5::addData( const void *sVData, int iSize ) 46void 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
89Bu::String Bu::Md5::getResult() 89Bu::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
96void Bu::Md5::writeResult( Bu::Stream &sOut ) 96void 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
103void Bu::Md5::compCap( uint32_t *sumout ) 103void 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
155void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) 155void 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
237void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) 237void 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
13namespace Bu 13namespace 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 @@
10using namespace Bu; 10using namespace Bu;
11 11
12Bu::MemBuf::MemBuf() : 12Bu::MemBuf::MemBuf() :
13 nPos( 0 ) 13 nPos( 0 )
14{ 14{
15} 15}
16 16
17Bu::MemBuf::MemBuf( const Bu::String &str ) : 17Bu::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
31size Bu::MemBuf::read( void *pBuf, size nBytes ) 31size 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
42size Bu::MemBuf::write( const void *pBuf, size nBytes ) 42size 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
69size Bu::MemBuf::tell() 69size Bu::MemBuf::tell()
70{ 70{
71 return nPos; 71 return nPos;
72} 72}
73 73
74void Bu::MemBuf::seek( size offset ) 74void 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
81void Bu::MemBuf::setPos( size pos ) 81void 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
88void Bu::MemBuf::setPosEnd( size pos ) 88void 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
95bool Bu::MemBuf::isEos() 95bool Bu::MemBuf::isEos()
96{ 96{
97 return (nPos == sBuf.getSize()); 97 return (nPos == sBuf.getSize());
98} 98}
99 99
100bool Bu::MemBuf::isOpen() 100bool Bu::MemBuf::isOpen()
101{ 101{
102 return true; 102 return true;
103} 103}
104 104
105void Bu::MemBuf::flush() 105void Bu::MemBuf::flush()
@@ -108,32 +108,32 @@ void Bu::MemBuf::flush()
108 108
109bool Bu::MemBuf::canRead() 109bool Bu::MemBuf::canRead()
110{ 110{
111 return !isEos(); 111 return !isEos();
112} 112}
113 113
114bool Bu::MemBuf::canWrite() 114bool Bu::MemBuf::canWrite()
115{ 115{
116 return true; 116 return true;
117} 117}
118 118
119bool Bu::MemBuf::isReadable() 119bool Bu::MemBuf::isReadable()
120{ 120{
121 return true; 121 return true;
122} 122}
123 123
124bool Bu::MemBuf::isWritable() 124bool Bu::MemBuf::isWritable()
125{ 125{
126 return true; 126 return true;
127} 127}
128 128
129bool Bu::MemBuf::isSeekable() 129bool Bu::MemBuf::isSeekable()
130{ 130{
131 return true; 131 return true;
132} 132}
133 133
134bool Bu::MemBuf::isBlocking() 134bool Bu::MemBuf::isBlocking()
135{ 135{
136 return true; 136 return true;
137} 137}
138 138
139void Bu::MemBuf::setBlocking( bool ) 139void Bu::MemBuf::setBlocking( bool )
@@ -142,36 +142,36 @@ void Bu::MemBuf::setBlocking( bool )
142 142
143void Bu::MemBuf::setSize( size iSize ) 143void 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
152Bu::size Bu::MemBuf::getSize() const 152Bu::size Bu::MemBuf::getSize() const
153{ 153{
154 return sBuf.getSize(); 154 return sBuf.getSize();
155} 155}
156 156
157Bu::size Bu::MemBuf::getBlockSize() const 157Bu::size Bu::MemBuf::getBlockSize() const
158{ 158{
159 return sBuf.getSize(); 159 return sBuf.getSize();
160} 160}
161 161
162Bu::String Bu::MemBuf::getLocation() const 162Bu::String Bu::MemBuf::getLocation() const
163{ 163{
164 return ""; 164 return "";
165} 165}
166 166
167Bu::String &Bu::MemBuf::getString() 167Bu::String &Bu::MemBuf::getString()
168{ 168{
169 return sBuf; 169 return sBuf;
170} 170}
171 171
172void Bu::MemBuf::setString( const Bu::String &sNewData ) 172void 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
17namespace Bu 17namespace 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
13Bu::MiniCron::MiniCron() : 13Bu::MiniCron::MiniCron() :
14 jidNext( 1 ) 14 jidNext( 1 )
15{ 15{
16} 16}
17 17
18Bu::MiniCron::~MiniCron() 18Bu::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
26bool Bu::MiniCron::hasJobs() 26bool Bu::MiniCron::hasJobs()
27{ 27{
28 return !hJobs.isEmpty(); 28 return !hJobs.isEmpty();
29} 29}
30 30
31time_t Bu::MiniCron::getNextRun() 31time_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
38time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) 38time_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
50void Bu::MiniCron::poll() 50void 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
76Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, 76Bu::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
89Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, 89Bu::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
102void Bu::MiniCron::removeJob( JobId jid ) 102void 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
122void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) 122void 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
148void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) 148void 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
174Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() 174Bu::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
187Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : 187Bu::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
197Bu::MiniCron::Job::~Job() 197Bu::MiniCron::Job::~Job()
198{ 198{
199 delete pTimer; 199 delete pTimer;
200 pTimer = NULL; 200 pTimer = NULL;
201} 201}
202 202
203void Bu::MiniCron::Job::run( bool bReschedule ) 203void 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
211time_t Bu::MiniCron::Job::getNextRun() const 211time_t Bu::MiniCron::Job::getNextRun() const
212{ 212{
213 return tNextRun; 213 return tNextRun;
214} 214}
215 215
216void Bu::MiniCron::Job::calcNextRun() 216void Bu::MiniCron::Job::calcNextRun()
217{ 217{
218 if( pTimer ) 218 if( pTimer )
219 tNextRun = pTimer->nextTime(); 219 tNextRun = pTimer->nextTime();
220} 220}
221 221
222void Bu::MiniCron::Job::setTimer( const Timer &t ) 222void 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
228void Bu::MiniCron::Job::stop() 228void Bu::MiniCron::Job::stop()
229{ 229{
230 bContinue = false; 230 bContinue = false;
231} 231}
232 232
233void Bu::MiniCron::Job::resume() 233void Bu::MiniCron::Job::resume()
234{ 234{
235 bContinue = true; 235 bContinue = true;
236} 236}
237 237
238Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const 238Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const
239{ 239{
240 return jid; 240 return jid;
241} 241}
242 242
243time_t Bu::MiniCron::Job::getTimeCreated() const 243time_t Bu::MiniCron::Job::getTimeCreated() const
244{ 244{
245 return tAdded; 245 return tAdded;
246} 246}
247 247
248int Bu::MiniCron::Job::getRunCount() const 248int Bu::MiniCron::Job::getRunCount() const
249{ 249{
250 return iRunCount; 250 return iRunCount;
251} 251}
252 252
253time_t Bu::MiniCron::Job::getNextRunTime() const 253time_t Bu::MiniCron::Job::getNextRunTime() const
254{ 254{
255 return tNextRun; 255 return tNextRun;
256} 256}
257 257
258Bu::String Bu::MiniCron::Job::getName() const 258Bu::String Bu::MiniCron::Job::getName() const
259{ 259{
260 return sName; 260 return sName;
261} 261}
262 262
263Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, 263Bu::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
275bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const 275bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const
276{ 276{
277 return jid < rhs.jid; 277 return jid < rhs.jid;
278} 278}
279 279
280Bu::MiniCron::Timer::Timer() 280Bu::MiniCron::Timer::Timer()
@@ -286,8 +286,8 @@ Bu::MiniCron::Timer::~Timer()
286} 286}
287 287
288Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : 288Bu::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
298time_t Bu::MiniCron::TimerInterval::nextTime() 298time_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
305Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : 305Bu::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
315time_t Bu::MiniCron::TimerBasic::nextTime() 315time_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
398Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( 398Bu::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
468int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) 468int 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
17namespace Bu 17namespace 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
22void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, 22void 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
29void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, 29void 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
36void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) 36void 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
41void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) 41void Bu::MultiServer::onClosedConnection( Bu::Client *pClient )
42{ 42{
43 delete pClient->getProtocol(); 43 delete pClient->getProtocol();
44} 44}
45 45
46void Bu::MultiServer::shutdown() 46void Bu::MultiServer::shutdown()
47{ 47{
48 Bu::Server::shutdown(); 48 Bu::Server::shutdown();
49} 49}
50 50
51void Bu::MultiServer::tick() 51void 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
14namespace Bu 14namespace 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
10Bu::Mutex::Mutex() 10Bu::Mutex::Mutex()
11{ 11{
12 pthread_mutex_init( &mutex, NULL ); 12 pthread_mutex_init( &mutex, NULL );
13} 13}
14 14
15Bu::Mutex::~Mutex() 15Bu::Mutex::~Mutex()
16{ 16{
17 pthread_mutex_destroy( &mutex ); 17 pthread_mutex_destroy( &mutex );
18} 18}
19 19
20int Bu::Mutex::lock() 20int Bu::Mutex::lock()
21{ 21{
22 return pthread_mutex_lock( &mutex ); 22 return pthread_mutex_lock( &mutex );
23} 23}
24 24
25int Bu::Mutex::unlock() 25int Bu::Mutex::unlock()
26{ 26{
27 return pthread_mutex_unlock( &mutex ); 27 return pthread_mutex_unlock( &mutex );
28} 28}
29 29
30int Bu::Mutex::trylock() 30int 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
13namespace Bu 13namespace 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
4Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : 4Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) :
5 mu( mu ) 5 mu( mu )
6{ 6{
7 mu.lock(); 7 mu.lock();
8} 8}
9 9
10Bu::MutexLocker::~MutexLocker() 10Bu::MutexLocker::~MutexLocker()
11{ 11{
12 mu.unlock(); 12 mu.unlock();
13} 13}
14 14
15void Bu::MutexLocker::unlock() 15void Bu::MutexLocker::unlock()
16{ 16{
17 mu.unlock(); 17 mu.unlock();
18} 18}
19 19
20void Bu::MutexLocker::relock() 20void 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
4namespace Bu 4namespace 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 &mu; 17 Mutex &mu;
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 @@
16using Bu::sio; 16using Bu::sio;
17using Bu::Fmt; 17using 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
21namespace Bu 21namespace 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
29Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : 29Bu::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
53Bu::Myriad::~Myriad() 53Bu::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
70void Bu::Myriad::sync() 70void 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
85void Bu::Myriad::initialize() 85void 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
193void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) 193void 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
291void Bu::Myriad::updateHeader() 291void 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
368int Bu::Myriad::createStream( int iPreAllocate ) 368int 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
393int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) 393int 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
441int Bu::Myriad::findEmptyBlock() 441int 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
456void Bu::Myriad::deleteStream( int iId ) 456void 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
485Bu::Array<int> Bu::Myriad::getStreamIds() 485Bu::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
498int Bu::Myriad::getStreamSize( int iId ) 498int 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
505bool Bu::Myriad::hasStream( int iId ) 505bool 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
519Bu::MyriadStream Bu::Myriad::openStream( int iId ) 519Bu::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
527int Bu::Myriad::getNumStreams() 527int 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
534int Bu::Myriad::getBlockSize() 534int Bu::Myriad::getBlockSize()
535{ 535{
536 return iBlockSize; 536 return iBlockSize;
537} 537}
538 538
539int Bu::Myriad::getNumBlocks() 539int Bu::Myriad::getNumBlocks()
540{ 540{
541 return iBlocks; 541 return iBlocks;
542} 542}
543 543
544int Bu::Myriad::getNumUsedBlocks() 544int Bu::Myriad::getNumUsedBlocks()
545{ 545{
546 return iUsed; 546 return iUsed;
547} 547}
548 548
549Bu::size Bu::Myriad::getTotalUsedBytes() 549Bu::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
561Bu::size Bu::Myriad::getTotalUnusedBytes() 561Bu::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
573Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) 573Bu::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
585Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) 585Bu::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
599Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) 599Bu::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
617void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) 617void 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
631void Bu::Myriad::syncBlock( Block *pBlock ) 631void 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
642int Bu::Myriad::streamAddBlock( Stream *pStream ) 642int 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
654void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) 654void 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
697void Bu::Myriad::headerChanged() 697void Bu::Myriad::headerChanged()
698{ 698{
699 bHeaderChanged = true; 699 bHeaderChanged = true;
700} 700}
701 701
702bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) 702bool 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
709bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) 709bool 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
726const Bu::BitString Bu::Myriad::getBlocksUsed() const 726const 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
19namespace Bu 19namespace 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
21Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, 21Bu::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
37Bu::MyriadStream::~MyriadStream() 37Bu::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
45void Bu::MyriadStream::close() 45void Bu::MyriadStream::close()
@@ -49,200 +49,200 @@ void Bu::MyriadStream::close()
49Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) 49Bu::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
112Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) 112Bu::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
218Bu::size Bu::MyriadStream::tell() 218Bu::size Bu::MyriadStream::tell()
219{ 219{
220 return iPos; 220 return iPos;
221} 221}
222 222
223void Bu::MyriadStream::seek( Bu::size offset ) 223void Bu::MyriadStream::seek( Bu::size offset )
224{ 224{
225 iPos += offset; 225 iPos += offset;
226} 226}
227 227
228void Bu::MyriadStream::setPos( Bu::size pos ) 228void Bu::MyriadStream::setPos( Bu::size pos )
229{ 229{
230 iPos = pos; 230 iPos = pos;
231} 231}
232 232
233void Bu::MyriadStream::setPosEnd( Bu::size pos ) 233void Bu::MyriadStream::setPosEnd( Bu::size pos )
234{ 234{
235 iPos = pStream->iSize-pos; 235 iPos = pStream->iSize-pos;
236} 236}
237 237
238bool Bu::MyriadStream::isEos() 238bool Bu::MyriadStream::isEos()
239{ 239{
240 return iPos >= pStream->iSize; 240 return iPos >= pStream->iSize;
241} 241}
242 242
243bool Bu::MyriadStream::isOpen() 243bool Bu::MyriadStream::isOpen()
244{ 244{
245 return true; 245 return true;
246} 246}
247 247
248void Bu::MyriadStream::flush() 248void Bu::MyriadStream::flush()
@@ -251,32 +251,32 @@ void Bu::MyriadStream::flush()
251 251
252bool Bu::MyriadStream::canRead() 252bool Bu::MyriadStream::canRead()
253{ 253{
254 return true; 254 return true;
255} 255}
256 256
257bool Bu::MyriadStream::canWrite() 257bool Bu::MyriadStream::canWrite()
258{ 258{
259 return true; 259 return true;
260} 260}
261 261
262bool Bu::MyriadStream::isReadable() 262bool Bu::MyriadStream::isReadable()
263{ 263{
264 return true; 264 return true;
265} 265}
266 266
267bool Bu::MyriadStream::isWritable() 267bool Bu::MyriadStream::isWritable()
268{ 268{
269 return true; 269 return true;
270} 270}
271 271
272bool Bu::MyriadStream::isSeekable() 272bool Bu::MyriadStream::isSeekable()
273{ 273{
274 return true; 274 return true;
275} 275}
276 276
277bool Bu::MyriadStream::isBlocking() 277bool Bu::MyriadStream::isBlocking()
278{ 278{
279 return true; 279 return true;
280} 280}
281 281
282void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) 282void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ )
@@ -285,25 +285,25 @@ void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ )
285 285
286void Bu::MyriadStream::setSize( Bu::size iSize ) 286void 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
295Bu::size Bu::MyriadStream::getSize() const 295Bu::size Bu::MyriadStream::getSize() const
296{ 296{
297 return pStream->iSize; 297 return pStream->iSize;
298} 298}
299 299
300Bu::size Bu::MyriadStream::getBlockSize() const 300Bu::size Bu::MyriadStream::getBlockSize() const
301{ 301{
302 return rMyriad.getBlockSize(); 302 return rMyriad.getBlockSize();
303} 303}
304 304
305Bu::String Bu::MyriadStream::getLocation() const 305Bu::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
14namespace Bu 14namespace 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
10Bu::NullStream::NullStream() : 10Bu::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
20void Bu::NullStream::close() 20void Bu::NullStream::close()
21{ 21{
22 sRead = sWrote = 0; 22 sRead = sWrote = 0;
23} 23}
24 24
25Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) 25Bu::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
32Bu::String Bu::NullStream::readLine() 32Bu::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
38Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) 38Bu::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
44Bu::size Bu::NullStream::tell() 44Bu::size Bu::NullStream::tell()
45{ 45{
46 return sRead + sWrote; 46 return sRead + sWrote;
47} 47}
48 48
49void Bu::NullStream::seek( Bu::size ) 49void Bu::NullStream::seek( Bu::size )
@@ -60,12 +60,12 @@ void Bu::NullStream::setPosEnd( Bu::size )
60 60
61bool Bu::NullStream::isEos() 61bool Bu::NullStream::isEos()
62{ 62{
63 return false; 63 return false;
64} 64}
65 65
66bool Bu::NullStream::isOpen() 66bool Bu::NullStream::isOpen()
67{ 67{
68 return true; 68 return true;
69} 69}
70 70
71void Bu::NullStream::flush() 71void Bu::NullStream::flush()
@@ -74,32 +74,32 @@ void Bu::NullStream::flush()
74 74
75bool Bu::NullStream::canRead() 75bool Bu::NullStream::canRead()
76{ 76{
77 return true; 77 return true;
78} 78}
79 79
80bool Bu::NullStream::canWrite() 80bool Bu::NullStream::canWrite()
81{ 81{
82 return true; 82 return true;
83} 83}
84 84
85bool Bu::NullStream::isReadable() 85bool Bu::NullStream::isReadable()
86{ 86{
87 return true; 87 return true;
88} 88}
89 89
90bool Bu::NullStream::isWritable() 90bool Bu::NullStream::isWritable()
91{ 91{
92 return true; 92 return true;
93} 93}
94 94
95bool Bu::NullStream::isSeekable() 95bool Bu::NullStream::isSeekable()
96{ 96{
97 return false; 97 return false;
98} 98}
99 99
100bool Bu::NullStream::isBlocking() 100bool Bu::NullStream::isBlocking()
101{ 101{
102 return true; 102 return true;
103} 103}
104 104
105void Bu::NullStream::setBlocking( bool ) 105void Bu::NullStream::setBlocking( bool )
@@ -112,16 +112,16 @@ void Bu::NullStream::setSize( Bu::size )
112 112
113Bu::size Bu::NullStream::getSize() const 113Bu::size Bu::NullStream::getSize() const
114{ 114{
115 return 0; 115 return 0;
116} 116}
117 117
118Bu::size Bu::NullStream::getBlockSize() const 118Bu::size Bu::NullStream::getBlockSize() const
119{ 119{
120 return 0; 120 return 0;
121} 121}
122 122
123Bu::String Bu::NullStream::getLocation() const 123Bu::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
13namespace Bu 13namespace 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
22void Bu::OptParser::parse( int argc, char **argv ) 22void 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
170void Bu::OptParser::parse( const Bu::String &sLine ) 170void 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
232void Bu::OptParser::addOption( const Option &opt ) 232void 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
241void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) 241void 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
246void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) 246void 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
251void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) 251void 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
256void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) 256void 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
266void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) 266void 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
278int Bu::OptParser::optHelp( StrArray /*aParams*/ ) 278int 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
355void Bu::OptParser::optionError( const Bu::String &sOption ) 355void 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
361void Bu::OptParser::setNonOption( OptionSignal sSignal ) 361void Bu::OptParser::setNonOption( OptionSignal sSignal )
362{ 362{
363 sNonOption = sSignal; 363 sNonOption = sSignal;
364} 364}
365 365
366Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, 366Bu::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
469Bu::OptParser::Option::Option() : 469Bu::OptParser::Option::Option() :
470 cOpt( '\0' ), 470 cOpt( '\0' ),
471 pProxy( NULL ) 471 pProxy( NULL )
472{ 472{
473} 473}
474 474
475Bu::OptParser::Option::Option( const Option &rSrc ) : 475Bu::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
487Bu::OptParser::Option::~Option() 487Bu::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
20namespace Bu 20namespace 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
11uint8_t Bu::PearsonHash::aSBox[] = { 11uint8_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
31Bu::PearsonHash::PearsonHash() 31Bu::PearsonHash::PearsonHash()
32{ 32{
33 reset(); 33 reset();
34} 34}
35 35
36Bu::PearsonHash::~PearsonHash() 36Bu::PearsonHash::~PearsonHash()
@@ -39,7 +39,7 @@ Bu::PearsonHash::~PearsonHash()
39 39
40void Bu::PearsonHash::reset() 40void Bu::PearsonHash::reset()
41{ 41{
42 iValue = 0; 42 iValue = 0;
43} 43}
44 44
45void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) 45void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ )
@@ -48,19 +48,19 @@ void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ )
48 48
49void Bu::PearsonHash::addData( const void *sData, int iSize ) 49void 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
57Bu::String Bu::PearsonHash::getResult() 57Bu::String Bu::PearsonHash::getResult()
58{ 58{
59 return Bu::String((char)iValue); 59 return Bu::String((char)iValue);
60} 60}
61 61
62void Bu::PearsonHash::writeResult( Stream &sOut ) 62void 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
13namespace Bu 13namespace 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
25namespace Bu 25namespace 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
28Bu::Process::ProcData::ProcData() : 28Bu::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
42Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : 42Bu::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
51Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : 51Bu::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
77Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : 77Bu::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
87Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : 87Bu::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
114Bu::Process::~Process() 114Bu::Process::~Process()
115{ 115{
116 close(); 116 close();
117} 117}
118 118
119void Bu::Process::wait() 119void Bu::Process::wait()
120{ 120{
121 close(); 121 close();
122} 122}
123 123
124void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) 124void 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
279void Bu::Process::close() 279void 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
314void Bu::Process::closeStdIn() 314void 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
325void Bu::Process::closeStdOut() 325void 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
336Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) 336Bu::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
385Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) 385Bu::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
427Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) 427Bu::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
443Bu::size Bu::Process::tell() 443Bu::size Bu::Process::tell()
444{ 444{
445 return 0; 445 return 0;
446} 446}
447 447
448void Bu::Process::seek( Bu::size ) 448void Bu::Process::seek( Bu::size )
@@ -460,15 +460,15 @@ void Bu::Process::setPosEnd( Bu::size )
460bool Bu::Process::isEos() 460bool 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
469bool Bu::Process::isOpen() 469bool Bu::Process::isOpen()
470{ 470{
471 return !isEos(); 471 return !isEos();
472} 472}
473 473
474void Bu::Process::flush() 474void Bu::Process::flush()
@@ -477,53 +477,53 @@ void Bu::Process::flush()
477 477
478bool Bu::Process::canRead() 478bool Bu::Process::canRead()
479{ 479{
480 return true; 480 return true;
481} 481}
482 482
483bool Bu::Process::canWrite() 483bool Bu::Process::canWrite()
484{ 484{
485 return true; 485 return true;
486} 486}
487 487
488bool Bu::Process::isReadable() 488bool Bu::Process::isReadable()
489{ 489{
490 return true; 490 return true;
491} 491}
492 492
493bool Bu::Process::isWritable() 493bool Bu::Process::isWritable()
494{ 494{
495 return true; 495 return true;
496} 496}
497 497
498bool Bu::Process::isSeekable() 498bool Bu::Process::isSeekable()
499{ 499{
500 return false; 500 return false;
501} 501}
502 502
503bool Bu::Process::isBlocking() 503bool Bu::Process::isBlocking()
504{ 504{
505 return true; 505 return true;
506} 506}
507 507
508void Bu::Process::setBlocking( bool bBlocking ) 508void 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
534Bu::size Bu::Process::getBlockSize() const 534Bu::size Bu::Process::getBlockSize() const
535{ 535{
536 return 0; 536 return 0;
537} 537}
538 538
539Bu::size Bu::Process::getSize() const 539Bu::size Bu::Process::getSize() const
540{ 540{
541 return 0; 541 return 0;
542} 542}
543 543
544Bu::String Bu::Process::getLocation() const 544Bu::String Bu::Process::getLocation() const
545{ 545{
546 return ""; 546 return "";
547} 547}
548 548
549void Bu::Process::select( bool &bStdOut, bool &bStdErr ) 549void 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
574bool Bu::Process::isRunning() 574bool 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
588void Bu::Process::ignoreStdErr() 588void 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
600pid_t Bu::Process::getPid() 600pid_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
609bool Bu::Process::childExited() 609bool 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
618int Bu::Process::childExitStatus() 618int 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
627bool Bu::Process::childSignaled() 627bool 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
636int Bu::Process::childSignal() 636int 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
645bool Bu::Process::childCoreDumped() 645bool 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
654void Bu::Process::checkClose() 654void 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
17namespace Bu 17namespace 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
15namespace Bu 15namespace 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
33void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) 33void 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
43void Bu::ProtocolHttp::onNewData( Bu::Client *pClient ) 43void 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
151Bu::ProtocolHttp::TokenType Bu::ProtocolHttp::getToken( Bu::String &line ) 151Bu::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
225bool Bu::ProtocolHttp::isWS( char buf ) 225bool Bu::ProtocolHttp::isWS( char buf )
226{ 226{
227 return (buf == ' ' || buf == '\t'); 227 return (buf == ' ' || buf == '\t');
228} 228}
229 229
230bool Bu::ProtocolHttp::isSeperator( char buf ) 230bool 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
19namespace Bu 19namespace 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
67Bu::ProtocolTelnet::ProtocolTelnet() : 67Bu::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
81void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) 81void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient )
82{ 82{
83 this->pClient = pClient; 83 this->pClient = pClient;
84} 84}
85 85
86void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) 86void 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
266void Bu::ProtocolTelnet::setCanonical( bool bCon ) 266void Bu::ProtocolTelnet::setCanonical( bool bCon )
267{ 267{
268 bCanonical = bCon; 268 bCanonical = bCon;
269} 269}
270 270
271bool Bu::ProtocolTelnet::isCanonical() 271bool Bu::ProtocolTelnet::isCanonical()
272{ 272{
273 return bCanonical; 273 return bCanonical;
274} 274}
275 275
276void Bu::ProtocolTelnet::write( const Bu::String &sData ) 276void 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
281void Bu::ProtocolTelnet::write( const char *pData, int iSize ) 281void 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
308void Bu::ProtocolTelnet::write( char cData ) 308void Bu::ProtocolTelnet::write( char cData )
309{ 309{
310 write( &cData, 1 ); 310 write( &cData, 1 );
311} 311}
312 312
313void Bu::ProtocolTelnet::onWill( char cCode ) 313void 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
338void Bu::ProtocolTelnet::onWont( char cCode ) 338void 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
355void Bu::ProtocolTelnet::onDo( char cCode ) 355void 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
380void Bu::ProtocolTelnet::onDont( char cCode ) 380void 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
397void Bu::ProtocolTelnet::onSubOpt() 397void 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
420void Bu::ProtocolTelnet::onCtlChar( char cChr ) 420void 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
463void Bu::ProtocolTelnet::printCode( char cCode ) 463void 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
488void Bu::ProtocolTelnet::printOpt( char cOpt ) 488void 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
510Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : 510Bu::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
518Bu::ProtocolTelnet::Option::~Option() 518Bu::ProtocolTelnet::Option::~Option()
@@ -521,100 +521,100 @@ Bu::ProtocolTelnet::Option::~Option()
521 521
522void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) 522void 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
532void Bu::ProtocolTelnet::Option::localSet( bool bSet ) 532void 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
564bool Bu::ProtocolTelnet::Option::isLocalEnabled() 564bool Bu::ProtocolTelnet::Option::isLocalEnabled()
565{ 565{
566 return (bool)(!(fOpts&fLocalCant)); 566 return (bool)(!(fOpts&fLocalCant));
567} 567}
568 568
569bool Bu::ProtocolTelnet::Option::isLocalSet() 569bool Bu::ProtocolTelnet::Option::isLocalSet()
570{ 570{
571 return (bool)(fOpts&fLocalIs); 571 return (bool)(fOpts&fLocalIs);
572} 572}
573 573
574void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) 574void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ )
575{ 575{
576 return; 576 return;
577} 577}
578 578
579void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) 579void 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
611bool Bu::ProtocolTelnet::Option::isRemoteEnabled() 611bool Bu::ProtocolTelnet::Option::isRemoteEnabled()
612{ 612{
613 return (bool)(!(fOpts&fRemoteCant)); 613 return (bool)(!(fOpts&fRemoteCant));
614} 614}
615 615
616bool Bu::ProtocolTelnet::Option::isRemoteSet() 616bool 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
17namespace Bu 17namespace 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
11namespace Bu 11namespace 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 @@
11using Bu::sio; 11using Bu::sio;
12 12
13Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : 13Bu::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
21Bu::QueueBuf::~QueueBuf() 21Bu::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
27void Bu::QueueBuf::close() 27void 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
35Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) 35Bu::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
74Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) 74Bu::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
79Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) 79Bu::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
127Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) 127Bu::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
163Bu::size Bu::QueueBuf::tell() 163Bu::size Bu::QueueBuf::tell()
164{ 164{
165 return -1; 165 return -1;
166} 166}
167 167
168void Bu::QueueBuf::seek( Bu::size iAmnt ) 168void 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
191void Bu::QueueBuf::setPos( Bu::size ) 191void Bu::QueueBuf::setPos( Bu::size )
@@ -198,12 +198,12 @@ void Bu::QueueBuf::setPosEnd( Bu::size )
198 198
199bool Bu::QueueBuf::isEos() 199bool Bu::QueueBuf::isEos()
200{ 200{
201 return iTotalSize == 0; 201 return iTotalSize == 0;
202} 202}
203 203
204bool Bu::QueueBuf::isOpen() 204bool Bu::QueueBuf::isOpen()
205{ 205{
206 return true; 206 return true;
207} 207}
208 208
209void Bu::QueueBuf::flush() 209void Bu::QueueBuf::flush()
@@ -212,32 +212,32 @@ void Bu::QueueBuf::flush()
212 212
213bool Bu::QueueBuf::canRead() 213bool Bu::QueueBuf::canRead()
214{ 214{
215 return iTotalSize > 0; 215 return iTotalSize > 0;
216} 216}
217 217
218bool Bu::QueueBuf::canWrite() 218bool Bu::QueueBuf::canWrite()
219{ 219{
220 return true; 220 return true;
221} 221}
222 222
223bool Bu::QueueBuf::isReadable() 223bool Bu::QueueBuf::isReadable()
224{ 224{
225 return true; 225 return true;
226} 226}
227 227
228bool Bu::QueueBuf::isWritable() 228bool Bu::QueueBuf::isWritable()
229{ 229{
230 return true; 230 return true;
231} 231}
232 232
233bool Bu::QueueBuf::isSeekable() 233bool Bu::QueueBuf::isSeekable()
234{ 234{
235 return false; 235 return false;
236} 236}
237 237
238bool Bu::QueueBuf::isBlocking() 238bool Bu::QueueBuf::isBlocking()
239{ 239{
240 return false; 240 return false;
241} 241}
242 242
243void Bu::QueueBuf::setBlocking( bool ) 243void Bu::QueueBuf::setBlocking( bool )
@@ -250,29 +250,29 @@ void Bu::QueueBuf::setSize( Bu::size )
250 250
251Bu::size Bu::QueueBuf::getSize() const 251Bu::size Bu::QueueBuf::getSize() const
252{ 252{
253 return iTotalSize; 253 return iTotalSize;
254} 254}
255 255
256Bu::size Bu::QueueBuf::getBlockSize() const 256Bu::size Bu::QueueBuf::getBlockSize() const
257{ 257{
258 return iBlockSize; 258 return iBlockSize;
259} 259}
260 260
261Bu::String Bu::QueueBuf::getLocation() const 261Bu::String Bu::QueueBuf::getLocation() const
262{ 262{
263 return ""; 263 return "";
264} 264}
265 265
266void Bu::QueueBuf::addBlock() 266void 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
272void Bu::QueueBuf::removeBlock() 272void 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
13namespace Bu 13namespace 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
11Bu::Random::Random() : 11Bu::Random::Random() :
12 pGen( NULL ) 12 pGen( NULL )
13{ 13{
14 pGen = new RandomBasic(); 14 pGen = new RandomBasic();
15} 15}
16 16
17Bu::Random::~Random() 17Bu::Random::~Random()
18{ 18{
19 delete pGen; 19 delete pGen;
20 pGen = NULL; 20 pGen = NULL;
21} 21}
22 22
23void Bu::Random::seed( int32_t iSeed ) 23void Bu::Random::seed( int32_t iSeed )
24{ 24{
25 getInstance().pGen->seed( iSeed ); 25 getInstance().pGen->seed( iSeed );
26} 26}
27 27
28int32_t Bu::Random::rand() 28int32_t Bu::Random::rand()
29{ 29{
30 return getInstance().pGen->rand(); 30 return getInstance().pGen->rand();
31} 31}
32 32
33int32_t Bu::Random::rand( int32_t iMax ) 33int32_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
38int32_t Bu::Random::rand( int32_t iMin, int32_t iMax ) 38int32_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
43double Bu::Random::randNorm() 43double 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
13namespace Bu 13namespace 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
12namespace Bu 12namespace 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
10Bu::RandomBasic::RandomBasic() : 10Bu::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
21void Bu::RandomBasic::seed( int32_t iSeed ) 21void Bu::RandomBasic::seed( int32_t iSeed )
22{ 22{
23 c = iSeed; 23 c = iSeed;
24} 24}
25 25
26int32_t Bu::RandomBasic::rand() 26int32_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
12namespace Bu 12namespace 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
14Bu::RandomCmwc::RandomCmwc() : 14Bu::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
21Bu::RandomCmwc::~RandomCmwc() 21Bu::RandomCmwc::~RandomCmwc()
22{ 22{
23 delete[] q; 23 delete[] q;
24} 24}
25 25
26void Bu::RandomCmwc::seed( int32_t iSeed ) 26void 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
48int32_t Bu::RandomCmwc::rand() 48int32_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
12namespace Bu 12namespace 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
4Bu::RandomSystem::RandomSystem( Type eType ) : 4Bu::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
20Bu::RandomSystem::~RandomSystem() 20Bu::RandomSystem::~RandomSystem()
21{ 21{
22 delete pSrc; 22 delete pSrc;
23} 23}
24 24
25void Bu::RandomSystem::seed( int32_t /*iSeed*/ ) 25void 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
32int32_t Bu::RandomSystem::rand() 32int32_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
12namespace Bu 12namespace 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
16namespace Bu 16namespace 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
16Bu::Server::Server() : 16Bu::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
24Bu::Server::~Server() 24Bu::Server::~Server()
25{ 25{
26 shutdown(); 26 shutdown();
27} 27}
28 28
29void Bu::Server::addPort( int nPort, int nPoolSize ) 29void 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
37void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) 37void 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
45void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) 45void 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
51void Bu::Server::scan() 51void 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
134void Bu::Server::addClient( socket_t nSocket, int nPort ) 134void 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
147Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : 147Bu::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
156void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) 156void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg )
157{ 157{
158 pClient->onMessage( sMsg ); 158 pClient->onMessage( sMsg );
159} 159}
160 160
161Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() 161Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory()
@@ -167,48 +167,48 @@ Bu::Server::SrvClientLinkFactory::~SrvClientLinkFactory()
167} 167}
168 168
169Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( 169Bu::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
175void Bu::Server::setAutoTick( bool bEnable ) 175void Bu::Server::setAutoTick( bool bEnable )
176{ 176{
177 bAutoTick = bEnable; 177 bAutoTick = bEnable;
178} 178}
179 179
180void Bu::Server::tick() 180void 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
188void Bu::Server::shutdown() 188void 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
205void Bu::Server::closeClient( socket_t iSocket ) 205void 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
26namespace Bu 26namespace 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
14Bu::Sha1::Sha1() : 14Bu::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
26Bu::Sha1::~Sha1() 26Bu::Sha1::~Sha1()
@@ -29,13 +29,13 @@ Bu::Sha1::~Sha1()
29 29
30void Bu::Sha1::reset() 30void 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
41void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) 41void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ )
@@ -44,151 +44,151 @@ void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ )
44 44
45void Bu::Sha1::addData( const void *sDataRaw, int iSize ) 45void 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
76Bu::String Bu::Sha1::getResult() 76Bu::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
120void Bu::Sha1::writeResult( Bu::Stream &sOut ) 120void Bu::Sha1::writeResult( Bu::Stream &sOut )
121{ 121{
122 sOut.write( getResult() ); 122 sOut.write( getResult() );
123} 123}
124 124
125void Bu::Sha1::process() 125void 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
182uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) 182uint32_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
187void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) 187void 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
14namespace Bu 14namespace 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
16namespace Bu 16namespace 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
13namespace Bu 13namespace 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
17namespace Bu 17namespace 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
47Bu::String::FormatProxy Bu::print( Bu::Stream &s, const Bu::String &str ) 47Bu::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
52Bu::String::FormatProxy Bu::print( const Bu::String &str ) 52Bu::String::FormatProxy Bu::print( const Bu::String &str )
53{ 53{
54 return print( sioRaw, str ); 54 return print( sioRaw, str );
55} 55}
56 56
57Bu::String::FormatProxy Bu::println( Bu::Stream &s, const Bu::String &str ) 57Bu::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
62Bu::String::FormatProxy Bu::println( const Bu::String &str ) 62Bu::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
13namespace Bu 13namespace 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
14namespace Bu 14namespace 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
14namespace Bu 14namespace 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 @@
10using namespace Bu; 10using namespace Bu;
11 11
12Bu::StaticMemBuf::StaticMemBuf( const void *pData, size iSize ) : 12Bu::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
27size Bu::StaticMemBuf::read( void *pBuf, size nBytes ) 27size 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
38size Bu::StaticMemBuf::write( const void *, size ) 38size Bu::StaticMemBuf::write( const void *, size )
39{ 39{
40 return -1; 40 return -1;
41} 41}
42 42
43size Bu::StaticMemBuf::tell() 43size Bu::StaticMemBuf::tell()
44{ 44{
45 return nPos; 45 return nPos;
46} 46}
47 47
48void Bu::StaticMemBuf::seek( size offset ) 48void 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
55void Bu::StaticMemBuf::setPos( size pos ) 55void 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
62void Bu::StaticMemBuf::setPosEnd( size pos ) 62void 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
69bool Bu::StaticMemBuf::isEos() 69bool Bu::StaticMemBuf::isEos()
70{ 70{
71 return (nPos == iSize); 71 return (nPos == iSize);
72} 72}
73 73
74bool Bu::StaticMemBuf::isOpen() 74bool Bu::StaticMemBuf::isOpen()
75{ 75{
76 return true; 76 return true;
77} 77}
78 78
79void Bu::StaticMemBuf::flush() 79void Bu::StaticMemBuf::flush()
@@ -82,32 +82,32 @@ void Bu::StaticMemBuf::flush()
82 82
83bool Bu::StaticMemBuf::canRead() 83bool Bu::StaticMemBuf::canRead()
84{ 84{
85 return !isEos(); 85 return !isEos();
86} 86}
87 87
88bool Bu::StaticMemBuf::canWrite() 88bool Bu::StaticMemBuf::canWrite()
89{ 89{
90 return false; 90 return false;
91} 91}
92 92
93bool Bu::StaticMemBuf::isReadable() 93bool Bu::StaticMemBuf::isReadable()
94{ 94{
95 return true; 95 return true;
96} 96}
97 97
98bool Bu::StaticMemBuf::isWritable() 98bool Bu::StaticMemBuf::isWritable()
99{ 99{
100 return false; 100 return false;
101} 101}
102 102
103bool Bu::StaticMemBuf::isSeekable() 103bool Bu::StaticMemBuf::isSeekable()
104{ 104{
105 return true; 105 return true;
106} 106}
107 107
108bool Bu::StaticMemBuf::isBlocking() 108bool Bu::StaticMemBuf::isBlocking()
109{ 109{
110 return true; 110 return true;
111} 111}
112 112
113void Bu::StaticMemBuf::setBlocking( bool ) 113void Bu::StaticMemBuf::setBlocking( bool )
@@ -120,16 +120,16 @@ void Bu::StaticMemBuf::setSize( size )
120 120
121Bu::size Bu::StaticMemBuf::getSize() const 121Bu::size Bu::StaticMemBuf::getSize() const
122{ 122{
123 return iSize; 123 return iSize;
124} 124}
125 125
126Bu::size Bu::StaticMemBuf::getBlockSize() const 126Bu::size Bu::StaticMemBuf::getBlockSize() const
127{ 127{
128 return iSize; 128 return iSize;
129} 129}
130 130
131Bu::String Bu::StaticMemBuf::getLocation() const 131Bu::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
16namespace Bu 16namespace 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
11Bu::StdStream::StdStream( OutMode eOut ) : 11Bu::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
24Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes ) 24Bu::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
29Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes ) 29Bu::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
34Bu::size Bu::StdStream::tell() 34Bu::size Bu::StdStream::tell()
35{ 35{
36 return 0; 36 return 0;
37} 37}
38 38
39void Bu::StdStream::seek( Bu::size ) 39void Bu::StdStream::seek( Bu::size )
@@ -50,47 +50,47 @@ void Bu::StdStream::setPosEnd( Bu::size )
50 50
51bool Bu::StdStream::isEos() 51bool Bu::StdStream::isEos()
52{ 52{
53 return false; 53 return false;
54} 54}
55 55
56bool Bu::StdStream::isOpen() 56bool Bu::StdStream::isOpen()
57{ 57{
58 return true; 58 return true;
59} 59}
60 60
61void Bu::StdStream::flush() 61void Bu::StdStream::flush()
62{ 62{
63 fflush( eOut==StdOut?stdout:stderr ); 63 fflush( eOut==StdOut?stdout:stderr );
64} 64}
65 65
66bool Bu::StdStream::canRead() 66bool Bu::StdStream::canRead()
67{ 67{
68 return true; 68 return true;
69} 69}
70 70
71bool Bu::StdStream::canWrite() 71bool Bu::StdStream::canWrite()
72{ 72{
73 return true; 73 return true;
74} 74}
75 75
76bool Bu::StdStream::isReadable() 76bool Bu::StdStream::isReadable()
77{ 77{
78 return true; 78 return true;
79} 79}
80 80
81bool Bu::StdStream::isWritable() 81bool Bu::StdStream::isWritable()
82{ 82{
83 return true; 83 return true;
84} 84}
85 85
86bool Bu::StdStream::isSeekable() 86bool Bu::StdStream::isSeekable()
87{ 87{
88 return false; 88 return false;
89} 89}
90 90
91bool Bu::StdStream::isBlocking() 91bool Bu::StdStream::isBlocking()
92{ 92{
93 return true; 93 return true;
94} 94}
95 95
96void Bu::StdStream::setBlocking( bool ) 96void Bu::StdStream::setBlocking( bool )
@@ -103,16 +103,16 @@ void Bu::StdStream::setSize( Bu::size )
103 103
104Bu::size Bu::StdStream::getSize() const 104Bu::size Bu::StdStream::getSize() const
105{ 105{
106 return 0; 106 return 0;
107} 107}
108 108
109Bu::size Bu::StdStream::getBlockSize() const 109Bu::size Bu::StdStream::getBlockSize() const
110{ 110{
111 return 0; 111 return 0;
112} 112}
113 113
114Bu::String Bu::StdStream::getLocation() const 114Bu::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
14namespace Bu 14namespace 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
18Bu::String Bu::Stream::readLine() 18Bu::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
33Bu::String Bu::Stream::readAll() 33Bu::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
49Bu::size Bu::Stream::write( const Bu::String &sBuf ) 49Bu::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
18namespace Bu 18namespace 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
14Bu::StreamStack::StreamStack( Bu::Stream *pStream ) 14Bu::StreamStack::StreamStack( Bu::Stream *pStream )
15{ 15{
16 lFilts.prepend( pStream ); 16 lFilts.prepend( pStream );
17} 17}
18 18
19Bu::StreamStack::~StreamStack() 19Bu::StreamStack::~StreamStack()
20{ 20{
21 clear(); 21 clear();
22} 22}
23 23
24bool Bu::StreamStack::isEmpty() 24bool Bu::StreamStack::isEmpty()
25{ 25{
26 return lFilts.isEmpty(); 26 return lFilts.isEmpty();
27} 27}
28 28
29bool Bu::StreamStack::hasStream() 29bool Bu::StreamStack::hasStream()
30{ 30{
31 return !lFilts.isEmpty(); 31 return !lFilts.isEmpty();
32} 32}
33 33
34void Bu::StreamStack::setStream( Bu::Stream *pStream ) 34void 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
42void Bu::StreamStack::clear() 42void 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
52void Bu::StreamStack::popFilter() 52void 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
61Bu::Stream *Bu::StreamStack::getTop() 61Bu::Stream *Bu::StreamStack::getTop()
62{ 62{
63 checkStack(); 63 checkStack();
64 64
65 return lFilts.first(); 65 return lFilts.first();
66} 66}
67 67
68Bu::Stream *Bu::StreamStack::getStream() 68Bu::Stream *Bu::StreamStack::getStream()
69{ 69{
70 checkStack(); 70 checkStack();
71 71
72 return lFilts.last(); 72 return lFilts.last();
73} 73}
74 74
75void Bu::StreamStack::close() 75void Bu::StreamStack::close()
76{ 76{
77 checkStack(); 77 checkStack();
78 78
79 lFilts.first()->close(); 79 lFilts.first()->close();
80} 80}
81 81
82Bu::size Bu::StreamStack::read( void *pBuf, Bu::size nBytes ) 82Bu::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
89Bu::size Bu::StreamStack::write( const void *pBuf, Bu::size nBytes ) 89Bu::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
96Bu::size Bu::StreamStack::write( const Bu::String &sBuf ) 96Bu::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
103Bu::size Bu::StreamStack::tell() 103Bu::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
110void Bu::StreamStack::seek( Bu::size offset ) 110void 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
117void Bu::StreamStack::setPos( Bu::size pos ) 117void 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
124void Bu::StreamStack::setPosEnd( Bu::size pos ) 124void 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
131bool Bu::StreamStack::isEos() 131bool 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
138bool Bu::StreamStack::isOpen() 138bool 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
145void Bu::StreamStack::flush() 145void Bu::StreamStack::flush()
146{ 146{
147 checkStack(); 147 checkStack();
148 148
149 lFilts.first()->flush(); 149 lFilts.first()->flush();
150} 150}
151 151
152bool Bu::StreamStack::canRead() 152bool 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
159bool Bu::StreamStack::canWrite() 159bool 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
166bool Bu::StreamStack::isReadable() 166bool 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
173bool Bu::StreamStack::isWritable() 173bool 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
180bool Bu::StreamStack::isSeekable() 180bool 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
187bool Bu::StreamStack::isBlocking() 187bool 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
194void Bu::StreamStack::setBlocking( bool bBlocking ) 194void 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
201void Bu::StreamStack::setSize( Bu::size iSize ) 201void 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
208Bu::size Bu::StreamStack::getSize() const 208Bu::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
215Bu::size Bu::StreamStack::getBlockSize() const 215Bu::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
222Bu::String Bu::StreamStack::getLocation() const 222Bu::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
229inline void Bu::StreamStack::checkStack() const 229inline 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
15namespace Bu 15namespace 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
7namespace Bu 7namespace 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
19Bu::StringCore::StringCore() : 19Bu::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
26Bu::StringCore::StringCore( const StringCore &rSrc ) : 26Bu::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
49Bu::StringCore::~StringCore() 49Bu::StringCore::~StringCore()
50{ 50{
51 clear(); 51 clear();
52} 52}
53 53
54void Bu::StringCore::clear() const 54void 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
73Bu::StringCore::Chunk *Bu::StringCore::newChunk() const 73Bu::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
80Bu::StringCore::Chunk *Bu::StringCore::newChunk( long nLen ) const 80Bu::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
90Bu::StringCore::Chunk *Bu::StringCore::copyChunk( 90Bu::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
104void Bu::StringCore::appendChunk( Bu::StringCore::Chunk *pNewChunk ) 104void 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
117void Bu::StringCore::prependChunk( Bu::StringCore::Chunk *pNewChunk ) 117void 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
130Bu::String::String() 130Bu::String::String()
@@ -133,44 +133,44 @@ Bu::String::String()
133 133
134Bu::String::String( const char *pData ) 134Bu::String::String( const char *pData )
135{ 135{
136 append( pData ); 136 append( pData );
137} 137}
138 138
139Bu::String::String( const char *pData, long nLength ) 139Bu::String::String( const char *pData, long nLength )
140{ 140{
141 append( pData, nLength ); 141 append( pData, nLength );
142} 142}
143 143
144Bu::String::String( const Bu::String &rSrc ) : 144Bu::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
149Bu::String::String( const Bu::String &rSrc, long nLength ) 149Bu::String::String( const Bu::String &rSrc, long nLength )
150{ 150{
151 append( rSrc, nLength ); 151 append( rSrc, nLength );
152} 152}
153 153
154Bu::String::String( const Bu::String &rSrc, long nStart, long nLength ) 154Bu::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
159Bu::String::String( long nSize ) 159Bu::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
165Bu::String::String( const Bu::String::const_iterator &s ) 165Bu::String::String( const Bu::String::const_iterator &s )
166{ 166{
167 append( s ); 167 append( s );
168} 168}
169 169
170Bu::String::String( const Bu::String::const_iterator &s, 170Bu::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
176Bu::String::~String() 176Bu::String::~String()
@@ -179,1049 +179,1049 @@ Bu::String::~String()
179 179
180void Bu::String::append( const char *pData ) 180void 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
189void Bu::String::append( const char *pData, long nLen ) 189void Bu::String::append( const char *pData, long nLen )
190{ 190{
191 append( pData, 0, nLen ); 191 append( pData, 0, nLen );
192} 192}
193 193
194void Bu::String::append( const char *pData, long nStart, long nLen ) 194void 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
229void Bu::String::append( const char &cData ) 229void 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
244void Bu::String::append( const String & sData ) 244void 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
249void Bu::String::append( const String & sData, long nLen ) 249void 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
254void Bu::String::append( const String & sData, long nStart, long nLen ) 254void 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
261void Bu::String::append( const const_iterator &s ) 261void 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
279void Bu::String::append( const iterator &s ) 279void Bu::String::append( const iterator &s )
280{ 280{
281 append( const_iterator( s ) ); 281 append( const_iterator( s ) );
282} 282}
283 283
284void Bu::String::append( const const_iterator &s, const const_iterator &e ) 284void 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
320void Bu::String::prepend( const String & sData ) 320void Bu::String::prepend( const String & sData )
321{ 321{
322 prepend( sData.getStr(), sData.getSize() ); 322 prepend( sData.getStr(), sData.getSize() );
323} 323}
324 324
325void Bu::String::prepend( const char *pData ) 325void 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
340void Bu::String::prepend( const char *pData, long nLen ) 340void 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
350void Bu::String::prepend( const char c ) 350void Bu::String::prepend( const char c )
351{ 351{
352 prepend( &c, 1 ); 352 prepend( &c, 1 );
353} 353}
354 354
355void Bu::String::insert( long nPos, const char *pData, long nLen ) 355void 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
385void Bu::String::insert( long nPos, const String &str ) 385void 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
415void Bu::String::insert( long nPos, const char *pData ) 415void 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
420void Bu::String::remove( long nPos, long nLen ) 420void 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
433void Bu::String::clear() 433void Bu::String::clear()
434{ 434{
435 _hardCopy(); 435 _hardCopy();
436 core->clear(); 436 core->clear();
437} 437}
438 438
439Bu::String Bu::String::replace( const Bu::String &fnd, 439Bu::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
462void Bu::String::resize( long nNewSize ) 462void 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
487long Bu::String::getSize() const 487long Bu::String::getSize() const
488{ 488{
489 return core->nLength; 489 return core->nLength;
490} 490}
491 491
492char *Bu::String::getStr() 492char *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
503const char *Bu::String::getStr() const 503const 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
513const char *Bu::String::getConstStr() const 513const char *Bu::String::getConstStr() const
514{ 514{
515 return getStr(); 515 return getStr();
516} 516}
517 517
518Bu::String Bu::String::getSubStrIdx( long iStart, long iSize ) const 518Bu::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
536Bu::String Bu::String::getSubStr( const_iterator iBegin, 536Bu::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
580Bu::StringList Bu::String::split( const char c ) const 580Bu::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
595Bu::String &Bu::String::operator+=( const char *pData ) 595Bu::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
602Bu::String &Bu::String::operator+=( const Bu::String &rSrc ) 602Bu::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
609Bu::String &Bu::String::operator+=( const Bu::String::const_iterator &i ) 609Bu::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
616Bu::String &Bu::String::operator+=( const char cData ) 616Bu::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
634Bu::String &Bu::String::operator=( const char *pData ) 634Bu::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
641Bu::String Bu::String::operator+( const Bu::String &rRight ) const 641Bu::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
648Bu::String Bu::String::operator+( const char *pRight ) const 648Bu::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
655Bu::String Bu::String::operator+( char *pRight ) const 655Bu::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
662void Bu::String::set( const char *pData ) 662void Bu::String::set( const char *pData )
663{ 663{
664 clear(); 664 clear();
665 append( pData ); 665 append( pData );
666} 666}
667 667
668void Bu::String::set( const char *pData, long nSize ) 668void 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
674void Bu::String::set( const char *pData, long nStart, long nSize ) 674void 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
680void Bu::String::set( const String &rData ) 680void Bu::String::set( const String &rData )
681{ 681{
682 clear(); 682 clear();
683 append( rData ); 683 append( rData );
684} 684}
685 685
686void Bu::String::set( const String &rData, long nSize ) 686void 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
692void Bu::String::set( const String &rData, long nStart, long nSize ) 692void 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
698void Bu::String::set( const_iterator s ) 698void Bu::String::set( const_iterator s )
699{ 699{
700 clear(); 700 clear();
701 append( s ); 701 append( s );
702} 702}
703 703
704void Bu::String::set( const_iterator s, const_iterator e ) 704void 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
710void Bu::String::setSize( long iSize ) 710void 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
717bool Bu::String::operator==( const char *pData ) const 717bool 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
742bool Bu::String::operator==( const String &pData ) const 742bool 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
768bool Bu::String::operator!=(const char *pData ) const 768bool Bu::String::operator!=(const char *pData ) const
769{ 769{
770 return !(*this == pData); 770 return !(*this == pData);
771} 771}
772 772
773bool Bu::String::operator!=(const String &pData ) const 773bool Bu::String::operator!=(const String &pData ) const
774{ 774{
775 return !(*this == pData); 775 return !(*this == pData);
776} 776}
777 777
778bool Bu::String::operator<(const String &pData ) const 778bool 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
794bool Bu::String::operator<=(const String &pData ) const 794bool 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
810bool Bu::String::operator>(const String &pData ) const 810bool 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
826bool Bu::String::operator>=(const String &pData ) const 826bool 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
842char &Bu::String::operator[]( long nIndex ) 842char &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
852const char &Bu::String::operator[]( long nIndex ) const 852const 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
861bool Bu::String::isSet() const 861bool Bu::String::isSet() const
862{ 862{
863 return (core->pFirst != NULL); 863 return (core->pFirst != NULL);
864} 864}
865 865
866bool Bu::String::compareSub( const char *pData, long nIndex, long nLen ) const 866bool 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
895bool Bu::String::compareSub( const String &rData, long nIndex, long nLen ) const 895bool 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
917bool Bu::String::isWS( long nIndex ) const 917bool 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
925bool Bu::String::isAlpha( long nIndex ) const 925bool 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
933Bu::String Bu::String::toLower() const 933Bu::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
950Bu::String Bu::String::toUpper() const 950Bu::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
967Bu::String::const_iterator Bu::String::find( const char cChar, 967Bu::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
979Bu::String::const_iterator Bu::String::find( const char *sText, int nLen, 979Bu::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
991Bu::String::const_iterator Bu::String::find( const String &rStr, 991Bu::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
1003Bu::String::const_iterator Bu::String::find( const String &rStr, int nLen, 1003Bu::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
1015Bu::String::iterator Bu::String::find( const char cChar, 1015Bu::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
1027Bu::String::iterator Bu::String::find( const char *sText, int nLen, 1027Bu::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
1039Bu::String::iterator Bu::String::find( const String &rStr, 1039Bu::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
1051Bu::String::iterator Bu::String::find( const String &rStr, int nLen, 1051Bu::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
1063long Bu::String::findIdx( const char cChar, long iStart ) const 1063long 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
1074long Bu::String::findIdx( const char *sText, long iStart ) const 1074long 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
1086long Bu::String::rfindIdx( const char *sText ) const 1086long 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
1098void Bu::String::trimFront( long nAmnt ) 1098void 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/*
1109void Bu::String::trimBack( char c ) 1109void 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*/
1119void Bu::String::trimBack( long iAmnt ) 1119void 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
1136Bu::String Bu::String::trimWhitespace() const 1136Bu::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
1166Bu::String::iterator Bu::String::begin() 1166Bu::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
1173Bu::String::const_iterator Bu::String::begin() const 1173Bu::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
1180Bu::String::iterator Bu::String::end() 1180Bu::String::iterator Bu::String::end()
1181{ 1181{
1182 return iterator( NULL, 0 ); 1182 return iterator( NULL, 0 );
1183} 1183}
1184 1184
1185Bu::String::const_iterator Bu::String::end() const 1185Bu::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
1190bool Bu::String::isEmpty() const 1190bool 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
1197void Bu::String::flatten() const 1197void 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
1222bool Bu::String::isFlat() const 1222bool 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
1231Bu::String::FormatProxy::FormatProxy( const String &rFmt, 1231Bu::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
1239Bu::String::FormatProxy::~FormatProxy() 1239Bu::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
1247Bu::String Bu::String::FormatProxy::end() const 1247Bu::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
1372template<> uint32_t Bu::__calcHashCode<Bu::String>( const Bu::String &k ) 1372template<> 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
1386template<> bool Bu::__cmpHashKeys<Bu::String>( 1386template<> 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
1392template<> void Bu::__tracer_format<Bu::String>( const Bu::String &v ) 1392template<> 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
1397bool &Bu::operator<<( bool &dst, const Bu::String &sIn ) 1397bool &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
1407uint8_t &Bu::operator<<( uint8_t &dst, const Bu::String &sIn ) 1407uint8_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
1413int8_t &Bu::operator<<( int8_t &dst, const Bu::String &sIn ) 1413int8_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
1419char &Bu::operator<<( char &dst, const Bu::String &sIn ) 1419char &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
1425uint16_t &Bu::operator<<( uint16_t &dst, const Bu::String &sIn ) 1425uint16_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
1431int16_t &Bu::operator<<( int16_t &dst, const Bu::String &sIn ) 1431int16_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
1437uint32_t &Bu::operator<<( uint32_t &dst, const Bu::String &sIn ) 1437uint32_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
1443int32_t &Bu::operator<<( int32_t &dst, const Bu::String &sIn ) 1443int32_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
1449uint64_t &Bu::operator<<( uint64_t &dst, const Bu::String &sIn ) 1449uint64_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
1455int64_t &Bu::operator<<( int64_t &dst, const Bu::String &sIn ) 1455int64_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
1461float &Bu::operator<<( float &dst, const Bu::String &sIn ) 1461float &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
1467double &Bu::operator<<( double &dst, const Bu::String &sIn ) 1467double &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
1473long double &Bu::operator<<( long double &dst, const Bu::String &sIn ) 1473long 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
1479Bu::String &Bu::operator<<( Bu::String &dst, const Bu::String &sIn ) 1479Bu::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
1485Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::String &s ) 1485Bu::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
1493Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::String &s ) 1493Bu::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
23namespace Bu 23namespace 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
10Bu::SubStream::SubStream( Bu::Stream &rNext, Bu::size iSize ) : 10Bu::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
19Bu::SubStream::~SubStream() 19Bu::SubStream::~SubStream()
@@ -22,88 +22,88 @@ Bu::SubStream::~SubStream()
22 22
23Bu::size Bu::SubStream::read( void *pBuf, Bu::size nBytes ) 23Bu::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
32Bu::size Bu::SubStream::write( const void *pBuf, Bu::size nBytes ) 32Bu::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
41void Bu::SubStream::start() 41void Bu::SubStream::start()
42{ 42{
43 // doesn't mean anything... 43 // doesn't mean anything...
44} 44}
45 45
46Bu::size Bu::SubStream::stop() 46Bu::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
52void Bu::SubStream::close() 52void Bu::SubStream::close()
53{ 53{
54 // don't do anything? maybe... 54 // don't do anything? maybe...
55} 55}
56 56
57Bu::size Bu::SubStream::tell() 57Bu::size Bu::SubStream::tell()
58{ 58{
59 return iPos; 59 return iPos;
60} 60}
61 61
62void Bu::SubStream::seek( Bu::size offset ) 62void 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
72void Bu::SubStream::setPos( Bu::size pos ) 72void 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
83void Bu::SubStream::setPosEnd( Bu::size pos ) 83void 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
95bool Bu::SubStream::isEos() 95bool Bu::SubStream::isEos()
96{ 96{
97 return rNext.isEos() || iPos == iSize; 97 return rNext.isEos() || iPos == iSize;
98} 98}
99 99
100bool Bu::SubStream::canRead() 100bool Bu::SubStream::canRead()
101{ 101{
102 return rNext.canRead() && (iPos < iSize); 102 return rNext.canRead() && (iPos < iSize);
103} 103}
104 104
105bool Bu::SubStream::canWrite() 105bool 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
13namespace Bu 13namespace 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
15namespace Bu 15namespace 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
13namespace Bu 13namespace 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
15namespace Bu 15namespace 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
16namespace Bu 16namespace 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
10Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : 10Bu::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
17Bu::TafComment::TafComment( const Bu::String &sText, bool bEOL ) : 17Bu::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
28const Bu::String &Bu::TafComment::getText() const 28const Bu::String &Bu::TafComment::getText() const
29{ 29{
30 return sText; 30 return sText;
31} 31}
32 32
33bool Bu::TafComment::isEOLStyle() const 33bool 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
14namespace Bu 14namespace 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
12Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : 12Bu::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
35Bu::TafGroup::TafGroup( const Bu::String &sName ) : 35Bu::TafGroup::TafGroup( const Bu::String &sName ) :
36 TafNode( typeGroup ), 36 TafNode( typeGroup ),
37 sName( sName ) 37 sName( sName )
38{ 38{
39} 39}
40 40
41Bu::TafGroup::~TafGroup() 41Bu::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
49const Bu::String &Bu::TafGroup::getName() const 49const Bu::String &Bu::TafGroup::getName() const
50{ 50{
51 return sName; 51 return sName;
52} 52}
53 53
54void Bu::TafGroup::setName( const Bu::String &sName ) 54void Bu::TafGroup::setName( const Bu::String &sName )
55{ 55{
56 this->sName = sName; 56 this->sName = sName;
57} 57}
58 58
59Bu::TafNode *Bu::TafGroup::addChild( Bu::TafNode *pNode ) 59Bu::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
79Bu::TafGroup *Bu::TafGroup::addChild( TafGroup *pNode ) 79Bu::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
89Bu::TafProperty *Bu::TafGroup::addChild( TafProperty *pNode ) 89Bu::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
99Bu::TafComment *Bu::TafGroup::addChild( TafComment *pNode ) 99Bu::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
105Bu::TafGroup *Bu::TafGroup::addGroup( const Bu::String &sName ) 105Bu::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
110Bu::TafProperty *Bu::TafGroup::addProperty( 110Bu::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
116bool Bu::TafGroup::hasChild( const Bu::String &sName ) const 116bool Bu::TafGroup::hasChild( const Bu::String &sName ) const
117{ 117{
118 return hChildren.has( sName ); 118 return hChildren.has( sName );
119} 119}
120 120
121const Bu::TafGroup::GroupList &Bu::TafGroup::getChildren( const Bu::String &sName ) const 121const 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
132const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const 132const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const
133{ 133{
134 return lChildren; 134 return lChildren;
135} 135}
136 136
137const Bu::TafGroup *Bu::TafGroup::getChild( const Bu::String &sName ) const 137const 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
148bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const 148bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const
149{ 149{
150 return hProp.has( sName ); 150 return hProp.has( sName );
151} 151}
152 152
153const Bu::TafGroup::PropList &Bu::TafGroup::getProperties( const Bu::String &sName ) const 153const 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
164const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName ) const 164const 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
175const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName, 175const 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
188const Bu::TafGroup *Bu::TafGroup::getChildByPath( 188const 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
194const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const 194const 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
206const Bu::String &Bu::TafGroup::getByPath( const Bu::String &sPath ) const 206const 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
211const Bu::String &Bu::TafGroup::getByPath( Bu::StrList lPath ) const 211const 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
17namespace Bu 17namespace 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 @@
10namespace Bu { subExceptionDef( TafException ) } 10namespace Bu { subExceptionDef( TafException ) }
11 11
12Bu::TafNode::TafNode( NodeType eType ) : 12Bu::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
21Bu::TafNode::NodeType Bu::TafNode::getType() const 21Bu::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
16namespace Bu 16namespace 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
10Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : 10Bu::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
17Bu::TafProperty::TafProperty( const Bu::String &sName, const Bu::String &sValue ) : 17Bu::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
28const Bu::String &Bu::TafProperty::getName() const 28const Bu::String &Bu::TafProperty::getName() const
29{ 29{
30 return sName; 30 return sName;
31} 31}
32 32
33const Bu::String &Bu::TafProperty::getValue() const 33const 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
14namespace Bu 14namespace 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 @@
14using namespace Bu; 14using namespace Bu;
15 15
16Bu::TafReader::TafReader( Bu::Stream &sIn ) : 16Bu::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
25Bu::TafReader::~TafReader() 25Bu::TafReader::~TafReader()
@@ -29,122 +29,122 @@ Bu::TafReader::~TafReader()
29 29
30Bu::TafGroup *Bu::TafReader::readGroup() 30Bu::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
65void Bu::TafReader::groupContent( Bu::TafGroup *pGroup ) 65void 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
89Bu::TafProperty *Bu::TafReader::readProperty() 89Bu::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
104Bu::TafComment *Bu::TafReader::readComment( bool bEOL ) 104Bu::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
143Bu::String Bu::TafReader::readStr() 143Bu::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
197void Bu::TafReader::ws() 197void 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
208bool Bu::TafReader::isws() 208bool 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
213void Bu::TafReader::next() 213void 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
236void Bu::TafReader::rawread( char *c ) 236void 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
14namespace Bu 14namespace 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
11Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : 11Bu::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
21void Bu::TafWriter::ident() 21void 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
27void Bu::TafWriter::writeGroup( const Bu::TafGroup *pRoot ) 27void 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
58void Bu::TafWriter::writeProperty( const Bu::TafProperty *pProp ) 58void 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
74void Bu::TafWriter::writeComment( const Bu::TafComment *pComment ) 74void 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
91void Bu::TafWriter::writeString( const Bu::String &str ) 91void 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
15namespace Bu 15namespace 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 @@
28namespace Bu { subExceptionDef( TcpServerSocketException ) } 28namespace Bu { subExceptionDef( TcpServerSocketException ) }
29 29
30Bu::TcpServerSocket::TcpServerSocket( int nPort, int nPoolSize ) : 30Bu::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
51Bu::TcpServerSocket::TcpServerSocket(const String &sAddr,int nPort, int nPoolSize) : 51Bu::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
75Bu::TcpServerSocket::TcpServerSocket( socket_t nServer, bool bInit, int nPoolSize ) : 75Bu::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
98Bu::TcpServerSocket::TcpServerSocket( const TcpServerSocket &rSrc ) 98Bu::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
110Bu::TcpServerSocket::~TcpServerSocket() 110Bu::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
120void Bu::TcpServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) 120void 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
146void Bu::TcpServerSocket::initServer( struct sockaddr_in &name, int nPoolSize ) 146void 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
165int Bu::TcpServerSocket::getSocket() 165int Bu::TcpServerSocket::getSocket()
166{ 166{
167 return nServer; 167 return nServer;
168} 168}
169 169
170int Bu::TcpServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) 170int 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
253int Bu::TcpServerSocket::getPort() 253int 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
21namespace Bu 21namespace 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 @@
32namespace Bu { subExceptionDef( TcpSocketException ) } 32namespace Bu { subExceptionDef( TcpSocketException ) }
33 33
34Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : 34Bu::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
45Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, 45Bu::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
133Bu::TcpSocket::~TcpSocket() 133Bu::TcpSocket::~TcpSocket()
134{ 134{
135 close(); 135 close();
136} 136}
137 137
138void Bu::TcpSocket::close() 138void 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
156Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) 156Bu::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
202Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, 202Bu::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
246Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) 246Bu::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
268Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) 268Bu::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
311Bu::size Bu::TcpSocket::tell() 311Bu::size Bu::TcpSocket::tell()
312{ 312{
313 throw UnsupportedException(); 313 throw UnsupportedException();
314} 314}
315 315
316void Bu::TcpSocket::seek( Bu::size ) 316void Bu::TcpSocket::seek( Bu::size )
317{ 317{
318 throw UnsupportedException(); 318 throw UnsupportedException();
319} 319}
320 320
321void Bu::TcpSocket::setPos( Bu::size ) 321void Bu::TcpSocket::setPos( Bu::size )
322{ 322{
323 throw UnsupportedException(); 323 throw UnsupportedException();
324} 324}
325 325
326void Bu::TcpSocket::setPosEnd( Bu::size ) 326void Bu::TcpSocket::setPosEnd( Bu::size )
327{ 327{
328 throw UnsupportedException(); 328 throw UnsupportedException();
329} 329}
330 330
331bool Bu::TcpSocket::isEos() 331bool Bu::TcpSocket::isEos()
332{ 332{
333 return !bActive; 333 return !bActive;
334} 334}
335 335
336bool Bu::TcpSocket::canRead() 336bool 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
354bool Bu::TcpSocket::canWrite() 354bool 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
371bool Bu::TcpSocket::isReadable() 371bool Bu::TcpSocket::isReadable()
372{ 372{
373 return true; 373 return true;
374} 374}
375 375
376bool Bu::TcpSocket::isWritable() 376bool Bu::TcpSocket::isWritable()
377{ 377{
378 return true; 378 return true;
379} 379}
380 380
381bool Bu::TcpSocket::isSeekable() 381bool Bu::TcpSocket::isSeekable()
382{ 382{
383 return false; 383 return false;
384} 384}
385 385
386bool Bu::TcpSocket::isBlocking() 386bool 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
395void Bu::TcpSocket::setBlocking( bool bBlocking ) 395void 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
423void Bu::TcpSocket::setSize( Bu::size ) 423void Bu::TcpSocket::setSize( Bu::size )
@@ -430,53 +430,53 @@ void Bu::TcpSocket::flush()
430 430
431bool Bu::TcpSocket::isOpen() 431bool Bu::TcpSocket::isOpen()
432{ 432{
433 return bActive; 433 return bActive;
434} 434}
435 435
436void Bu::TcpSocket::setAddress() 436void 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
445Bu::String Bu::TcpSocket::getAddress() const 445Bu::String Bu::TcpSocket::getAddress() const
446{ 446{
447 return sAddress; 447 return sAddress;
448} 448}
449 449
450Bu::TcpSocket::operator Bu::TcpSocket::handle() const 450Bu::TcpSocket::operator Bu::TcpSocket::handle() const
451{ 451{
452 return nTcpSocket; 452 return nTcpSocket;
453} 453}
454 454
455Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const 455Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const
456{ 456{
457 return nTcpSocket; 457 return nTcpSocket;
458} 458}
459 459
460Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() 460Bu::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
468Bu::size Bu::TcpSocket::getSize() const 468Bu::size Bu::TcpSocket::getSize() const
469{ 469{
470 throw UnsupportedException(); 470 throw UnsupportedException();
471} 471}
472 472
473Bu::size Bu::TcpSocket::getBlockSize() const 473Bu::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
478Bu::String Bu::TcpSocket::getLocation() const 478Bu::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
18namespace Bu 18namespace 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 @@
10namespace Bu { subExceptionDef( ThreadException ); } 10namespace Bu { subExceptionDef( ThreadException ); }
11 11
12Bu::ThreadId::ThreadId( pthread_t tId ) : 12Bu::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
21bool Bu::ThreadId::operator==( const Bu::ThreadId &rhs ) 21bool 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
26bool Bu::ThreadId::operator!=( const ThreadId &rhs ) 26bool 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
31Bu::Thread::Thread() 31Bu::Thread::Thread()
@@ -38,45 +38,45 @@ Bu::Thread::~Thread()
38 38
39Bu::ThreadId Bu::Thread::currentThread() 39Bu::ThreadId Bu::Thread::currentThread()
40{ 40{
41 return ThreadId( pthread_self() ); 41 return ThreadId( pthread_self() );
42} 42}
43 43
44bool Bu::Thread::start() 44bool 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
54bool Bu::Thread::stop() 54bool 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
61void *Bu::Thread::threadRunner( void *pThread ) 61void *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
68bool Bu::Thread::join() 68bool 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
74void Bu::Thread::yield() 74void 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
16namespace Bu 16namespace 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
10void Bu::__tracer( const char *pf ) 10void Bu::__tracer( const char *pf )
11{ 11{
12 printf("trace: %s\n", pf ); 12 printf("trace: %s\n", pf );
13} 13}
14 14
15template<> void Bu::__tracer_format<float>( const float &v ) 15template<> void Bu::__tracer_format<float>( const float &v )
16{ 16{
17 printf("%f", v ); 17 printf("%f", v );
18} 18}
19 19
20template<> void Bu::__tracer_format<double>( const double &v ) 20template<> void Bu::__tracer_format<double>( const double &v )
21{ 21{
22 printf("%f", v ); 22 printf("%f", v );
23} 23}
24 24
25template<> void Bu::__tracer_format<void *>( void * const &v ) 25template<> 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
30template<> void Bu::__tracer_format<char *>( char * const &v ) 30template<> void Bu::__tracer_format<char *>( char * const &v )
31{ 31{
32 printf("\"%s\"", v ); 32 printf("\"%s\"", v );
33} 33}
34 34
35template<> void Bu::__tracer_format<char **>( char ** const &v ) 35template<> 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
47template<> void Bu::__tracer_format<void const *>( void const * const &v ) 47template<> 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
52template<> void Bu::__tracer_format<char const *>( char const * const &v ) 52template<> void Bu::__tracer_format<char const *>( char const * const &v )
53{ 53{
54 printf("\"%s\"", v ); 54 printf("\"%s\"", v );
55} 55}
56 56
57template<> void Bu::__tracer_format<char const **>( char const ** const &v ) 57template<> 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
18namespace Bu 18namespace 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
19Bu::UnitSuite::UnitSuite() : 19Bu::UnitSuite::UnitSuite() :
20 iOptions( 0 ), 20 iOptions( 0 ),
21 iNameWidth( 0 ) 21 iNameWidth( 0 )
22{ 22{
23} 23}
24 24
25Bu::UnitSuite::UnitSuite( int iOptions ) : 25Bu::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
35int Bu::UnitSuite::run( int argc, char *argv[] ) 35int 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
173Bu::File Bu::UnitSuite::tempFile( Bu::String &sFileName ) 173Bu::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
180void Bu::UnitSuite::add( Test fTest, const Bu::String &sName, Expect e ) 180void 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
198void Bu::UnitSuite::setName( const String &sName ) 198void Bu::UnitSuite::setName( const String &sName )
199{ 199{
200 sSuiteName = sName; 200 sSuiteName = sName;
201} 201}
202 202
203void Bu::UnitSuite::dispProgress() 203void 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
212void Bu::UnitSuite::setStepCount( int iSteps ) 212void 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
221void Bu::UnitSuite::incProgress( int iAmnt ) 221void 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
231void Bu::UnitSuite::setProgress( int iAmnt ) 231void 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
241int Bu::UnitSuite::onListCases( StrArray ) 241int 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
254int Bu::UnitSuite::onAddTest( StrArray aParam ) 254int 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
260Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ) 260Bu::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
18namespace Bu 18namespace 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
133Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); 133Bu::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
10int Bu::getDaysInMonth( int iMonth, int iYear ) 10int 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}
50void Bu::memcpy( void *pDest, const void *pSrc, size_t iBytes ) 50void 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
26namespace Bu 26namespace 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
12namespace Bu 12namespace Bu
13{ 13{
14 Formatter &operator<<( Formatter &f, const String &s ); 14 Formatter &operator<<( Formatter &f, const String &s );
15}; 15};
16 16
17Bu::VariantTypeRoot::VariantTypeRoot() 17Bu::VariantTypeRoot::VariantTypeRoot()
@@ -23,84 +23,84 @@ Bu::VariantTypeRoot::~VariantTypeRoot()
23} 23}
24 24
25Bu::Variant::Variant() : 25Bu::Variant::Variant() :
26 pCore( NULL ) 26 pCore( NULL )
27{ 27{
28} 28}
29 29
30Bu::Variant::Variant( const Variant &v ) : 30Bu::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
39Bu::Variant::Variant( const char *t ) : 39Bu::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
45Bu::Variant::~Variant() 45Bu::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
54Bu::String Bu::Variant::toString() const 54Bu::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
69bool Bu::Variant::isSet() const 69bool Bu::Variant::isSet() const
70{ 70{
71 return pCore != NULL; 71 return pCore != NULL;
72} 72}
73 73
74const std::type_info &Bu::Variant::getType() const 74const 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
83Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs ) 83Bu::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
98Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v ) 98Bu::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
21namespace Bu 21namespace 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
12int main( int argc, char *argv[] ) 12int 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
5int main() 5int 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
57int main( int argc, char *argv[] ) 57int 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
16enum TokenType 16enum 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
32class BnfLexer : public Lexer 32class BnfLexer : public Lexer
33{ 33{
34public: 34public:
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
153private: 153private:
154 Stream &rSrc; 154 Stream &rSrc;
155 QueueBuf qbIn; 155 QueueBuf qbIn;
156 String sBuf; 156 String sBuf;
157}; 157};
158 158
159class BnfParser 159class BnfParser
160{ 160{
161public: 161public:
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
200private: 200private:
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
369private: 369private:
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
382private: 382private:
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
391int main( int argc, char *argv[] ) 391int 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
11int main( int argc, char *argv[] ) 11int 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
11int main( int argc, char *argv[] ) 11int 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
11int main( int argc, char *argv[] ) 11int 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
9int main() 9int 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;
12class Opts : public Bu::OptParser 12class Opts : public Bu::OptParser
13{ 13{
14public: 14public:
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
82int main( int argc, char *argv[] ) 82int 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
17enum Tok 17enum 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
30Bu::Formatter &operator<<( Bu::Formatter &f, Tok e ) 30Bu::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
48class MathLexer : public Lexer 48class MathLexer : public Lexer
49{ 49{
50public: 50public:
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
154private: 154private:
155 Bu::Stream &rSrc; 155 Bu::Stream &rSrc;
156 QueueBuf qbIn; 156 QueueBuf qbIn;
157}; 157};
158 158
159void redAdd( Bu::Parser &p ) 159void 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
176void redSubtract( Bu::Parser &p ) 176void 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
193void redPrint( Bu::Parser &p ) 193void 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
228int main( int argc, char *argv[] ) 228int 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
3int upper() 3int upper()
4{ 4{
5 static int iVal = 1; 5 static int iVal = 1;
6 return iVal++; 6 return iVal++;
7} 7}
8 8
9int main() 9int 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;
9template<typename T> 9template<typename T>
10void coverage() 10void 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
41int main() 41int 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
7void compile( const Bu::String &s, Bu::RegExEngine<char> &ree ) 7void 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
21int main() 21int 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
6int main() 6int 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 @@
5class Thing 5class Thing
6{ 6{
7public: 7public:
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
18typedef Bu::SynchroQueue<Thing *> ThingQueue; 18typedef Bu::SynchroQueue<Thing *> ThingQueue;
@@ -23,109 +23,109 @@ Bu::Condition cWorkDone;
23 23
24void workDone() 24void 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
39class ThingEater : public Bu::Thread 39class ThingEater : public Bu::Thread
40{ 40{
41public: 41public:
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
64protected: 64protected:
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
85typedef Bu::List<ThingEater *> ThingEaterList; 85typedef Bu::List<ThingEater *> ThingEaterList;
86 86
87int main() 87int 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
11int main( int argc, char *argv[] ) 11int 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;
9class CopyThing 9class CopyThing
10{ 10{
11public: 11public:
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
34private: 34private:
35 ThreadId tidHome; 35 ThreadId tidHome;
36}; 36};
37 37
38class SubThread : public Thread 38class SubThread : public Thread
39{ 39{
40public: 40public:
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
47protected: 47protected:
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
54private: 54private:
55 CopyThing src; 55 CopyThing src;
56}; 56};
57 57
58int main( int argc, char *argv[] ) 58int 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
8int main() 8int 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
13int main() 13int 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;
16class Options : public OptParser 16class Options : public OptParser
17{ 17{
18public: 18public:
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
66int main( int argc, char *argv[] ) 66int 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;
17class Test 17class Test
18{ 18{
19public: 19public:
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};
28typedef Bu::List<Test> TestList; 28typedef Bu::List<Test> TestList;
29 29
30class Suite 30class Suite
31{ 31{
32public: 32public:
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
38enum TokType 38enum 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
48Bu::Formatter &operator<<( Bu::Formatter &f, TokType t ) 48Bu::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
63Bu::Formatter &operator<<( Bu::Formatter &f, const Test &t ) 63Bu::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
68Bu::Formatter &operator<<( Bu::Formatter &f, const Suite &s ) 68Bu::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
73class Parser 73class Parser
74{ 74{
75public: 75public:
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
530private: 530private:
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
548int main( int argc, char *argv[] ) 548int 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
18enum Mode 18enum 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
30class Options : public OptParser 30class Options : public OptParser
31{ 31{
32public: 32public:
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
83Bu::Formatter &operator>>( Bu::Formatter &f, Mode & /*e*/ ) 83Bu::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
89int main( int argc, char *argv[] ) 89int 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;
20class Options : public Bu::OptParser 20class Options : public Bu::OptParser
21{ 21{
22public: 22public:
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
52typedef Bu::Array<StrArray> StrGrid; 52typedef Bu::Array<StrArray> StrGrid;
@@ -54,421 +54,421 @@ typedef Bu::Array<int> IntArray;
54class CsvDoc 54class CsvDoc
55{ 55{
56public: 56public:
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
87class CsvView 87class CsvView
88{ 88{
89public: 89public:
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
371int main( int argc, char *argv[] ) 371int 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
15suite Archive 15suite 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
15suite Array 15suite 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
12suite MemBuf 12suite 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
51suite Blowfish 51suite 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
13suite Buffer 13suite 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
15suite File 15suite 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
20suite Hash 20suite 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
14suite List 14suite 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
13suite Md5 13suite 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
11suite MemBuf 11suite 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
26friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ); 26friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo );
27friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ); 27friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo );
28public: 28public:
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
44private: 44private:
45 int iUnits; 45 int iUnits;
46 mutable int iBytesWritten; 46 mutable int iBytesWritten;
47}; 47};
48 48
49Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo ) 49Bu::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
73Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo ) 73Bu::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
103suite Myriad 103suite 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
17suite QueueBuf 17suite 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
13suite Sha1 13suite 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
13suite String 13suite 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
12suite SubStream 12suite 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
16suite Taf 16suite 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
17Bu::String mkastring() 17Bu::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
26suite Variant 26suite 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
13suite Xml 13suite 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
17Bu::BitString::BitString() 17Bu::BitString::BitString()
18{ 18{
19 caData = NULL; 19 caData = NULL;
20 cTopByteMask = 0; 20 cTopByteMask = 0;
21 iBits = iBytes = 0; 21 iBits = iBytes = 0;
22} 22}
23 23
24Bu::BitString::BitString( const Bu::BitString &xSrc ) 24Bu::BitString::BitString( const Bu::BitString &xSrc )
25{ 25{
26 iBits = xSrc.iBits; 26 iBits = xSrc.iBits;
27 iBytes = xSrc.iBytes; 27 iBytes = xSrc.iBytes;
28 cTopByteMask = xSrc.cTopByteMask; 28 cTopByteMask = xSrc.cTopByteMask;
29 caData = new unsigned char[iBytes]; 29 caData = new unsigned char[iBytes];
30 memcpy( caData, xSrc.caData, iBytes ); 30 memcpy( caData, xSrc.caData, iBytes );
31 31
32 fixup(); 32 fixup();
33} 33}
34 34
35Bu::BitString::BitString( long iNewBits, bool bFillRandomly ) 35Bu::BitString::BitString( long iNewBits, bool bFillRandomly )
36{ 36{
37 long j; 37 long j;
38 iBits = iNewBits; 38 iBits = iNewBits;
39 iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0)); 39 iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0));
40 caData = new unsigned char[iBytes]; 40 caData = new unsigned char[iBytes];
41 41
42 setMask(); 42 setMask();
43 43
44 if( bFillRandomly ) 44 if( bFillRandomly )
45 { 45 {
46 // rand() only returns a value up to RAND_MAX (0x7FFF on my system) so 46 // rand() only returns a value up to RAND_MAX (0x7FFF on my system) so
47 // I'll just use the low order byte) 47 // I'll just use the low order byte)
48 for( j = 0; j < iBytes; j++ ) 48 for( j = 0; j < iBytes; j++ )
49 { 49 {
50 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF); 50 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF);
51 } 51 }
52 } 52 }
53 else 53 else
54 { 54 {
55 clear(); 55 clear();
56 } 56 }
57 57
58 fixup(); 58 fixup();
59} 59}
60 60
61Bu::BitString::~BitString() 61Bu::BitString::~BitString()
62{ 62{
63 if( caData != NULL ) delete[] caData; 63 if( caData != NULL ) delete[] caData;
64} 64}
65 65
66Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc ) 66Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc )
67{ 67{
68 if( caData != NULL ) 68 if( caData != NULL )
69 { 69 {
70 delete[] caData; 70 delete[] caData;
71 } 71 }
72 iBits = xSrc.iBits; 72 iBits = xSrc.iBits;
73 iBytes = xSrc.iBytes; 73 iBytes = xSrc.iBytes;
74 cTopByteMask = xSrc.cTopByteMask; 74 cTopByteMask = xSrc.cTopByteMask;
75 caData = new unsigned char[iBytes]; 75 caData = new unsigned char[iBytes];
76 memcpy( caData, xSrc.caData, iBytes ); 76 memcpy( caData, xSrc.caData, iBytes );
77 77
78 fixup(); 78 fixup();
79 79
80 return *this; 80 return *this;
81} 81}
82 82
83Bu::BitString Bu::BitString::operator~() 83Bu::BitString Bu::BitString::operator~()
84{ 84{
85 Bu::BitString xRet( *this ); 85 Bu::BitString xRet( *this );
86 86
87 for( int j = 0; j < xRet.iBytes; j++ ) 87 for( int j = 0; j < xRet.iBytes; j++ )
88 { 88 {
89 xRet.caData[j] = ~xRet.caData[j]; 89 xRet.caData[j] = ~xRet.caData[j];
90 } 90 }
91 91
92 xRet.fixup(); 92 xRet.fixup();
93 93
94 return xRet; 94 return xRet;
95} 95}
96 96
97Bu::BitString Bu::BitString::operator<<( const long iAmt ) 97Bu::BitString Bu::BitString::operator<<( const long iAmt )
98{ 98{
99 if( iAmt == 0 ) 99 if( iAmt == 0 )
100 { 100 {
101 return (*this); 101 return (*this);
102 } 102 }
103 //int iByteShift = iAmt/8; 103 //int iByteShift = iAmt/8;
104 104
105 Bu::BitString xSub( getSize() ); 105 Bu::BitString xSub( getSize() );
106 106
107 long shft = (iAmt%8); 107 long shft = (iAmt%8);
108 long base = (iAmt/8); 108 long base = (iAmt/8);
109 unsigned char lowmask=0; 109 unsigned char lowmask=0;
110 for( long j = 0; j < 8-shft; j++ ) 110 for( long j = 0; j < 8-shft; j++ )
111 { 111 {
112 lowmask |= (1<<j); 112 lowmask |= (1<<j);
113 } 113 }
114 for( long j = 0; j < xSub.iBytes; j++ ) 114 for( long j = 0; j < xSub.iBytes; j++ )
115 { 115 {
116 xSub.caData[base+j] = ((caData[j]>>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask)); 116 xSub.caData[base+j] = ((caData[j]>>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask));
117 } 117 }
118 xSub.fixup(); 118 xSub.fixup();
119 119
120 return xSub; 120 return xSub;
121} 121}
122 122
123Bu::BitString Bu::BitString::operator>>( const long iAmt ) 123Bu::BitString Bu::BitString::operator>>( const long iAmt )
124{ 124{
125 if( iAmt == 0 ) 125 if( iAmt == 0 )
126 { 126 {
127 return (*this); 127 return (*this);
128 } 128 }
129 return (*this); 129 return (*this);
130} 130}
131 131
132void Bu::BitString::shiftLeft( long iAmt ) 132void Bu::BitString::shiftLeft( long iAmt )
133{ 133{
134 if( iAmt == 0 ) 134 if( iAmt == 0 )
135 { 135 {
136 return; 136 return;
137 } 137 }
138 else if( iAmt < 0 ) 138 else if( iAmt < 0 )
139 { 139 {
140 shiftRight( -iAmt ); 140 shiftRight( -iAmt );
141 return; 141 return;
142 } 142 }
143 143
144 long iByteShift = iAmt/8; 144 long iByteShift = iAmt/8;
145 long iBitShift = iAmt%8; 145 long iBitShift = iAmt%8;
146 146
147 long j; 147 long j;
148 for( j = iBytes-1; j >= 0; j-- ) 148 for( j = iBytes-1; j >= 0; j-- )
149 { 149 {
150 caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<<iBitShift))) | (((j-iByteShift-1)<0)?(0):((caData[j-iByteShift-1]>>(8-iBitShift)))); 150 caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<<iBitShift))) | (((j-iByteShift-1)<0)?(0):((caData[j-iByteShift-1]>>(8-iBitShift))));
151 } 151 }
152 152
153 fixup(); 153 fixup();
154} 154}
155 155
156void Bu::BitString::shiftRight( long iAmt ) 156void Bu::BitString::shiftRight( long iAmt )
157{ 157{
158 if( iAmt == 0 ) 158 if( iAmt == 0 )
159 { 159 {
160 return; 160 return;
161 } 161 }
162 else if( iAmt < 0 ) 162 else if( iAmt < 0 )
163 { 163 {
164 shiftLeft( -iAmt ); 164 shiftLeft( -iAmt );
165 return; 165 return;
166 } 166 }
167 167
168 long iByteShift = iAmt/8; 168 long iByteShift = iAmt/8;
169 long iBitShift = iAmt%8; 169 long iBitShift = iAmt%8;
170 170
171 long j; 171 long j;
172 for( j = 0; j < iBytes; j++ ) 172 for( j = 0; j < iBytes; j++ )
173 { 173 {
174 caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift)))); 174 caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift))));
175 } 175 }
176 176
177 fixup(); 177 fixup();
178} 178}
179/* 179/*
180long Bu::BitString::bitsToBytes( long iBits ) 180long Bu::BitString::bitsToBytes( long iBits )
181{ 181{
182 return (iBits/8)+((iBits%8)?(1):(0)); 182 return (iBits/8)+((iBits%8)?(1):(0));
183} 183}
184*/ 184*/
185void Bu::BitString::fixup() 185void Bu::BitString::fixup()
186{ 186{
187 if( caData != NULL ) 187 if( caData != NULL )
188 { 188 {
189 caData[iBytes-1] &= cTopByteMask; 189 caData[iBytes-1] &= cTopByteMask;
190 } 190 }
191} 191}
192 192
193void Bu::BitString::setBit( long iBit, bool bBitState ) 193void Bu::BitString::setBit( long iBit, bool bBitState )
194{ 194{
195 if( iBit < 0 || iBit >= iBits ) 195 if( iBit < 0 || iBit >= iBits )
196 throw Bu::ExceptionBase("bit out of range: %d in (0-%d)", iBit, iBits ); 196 throw Bu::ExceptionBase("bit out of range: %d in (0-%d)", iBit, iBits );
197 if( bBitState ) 197 if( bBitState )
198 { 198 {
199 caData[iBit/8] |= (1<<(iBit%8)); 199 caData[iBit/8] |= (1<<(iBit%8));
200 } 200 }
201 else 201 else
202 { 202 {
203 caData[iBit/8] &= ~(1<<(iBit%8)); 203 caData[iBit/8] &= ~(1<<(iBit%8));
204 } 204 }
205} 205}
206 206
207void Bu::BitString::flipBit( long iBit ) 207void Bu::BitString::flipBit( long iBit )
208{ 208{
209 caData[iBit/8] ^= (1<<(iBit%8)); 209 caData[iBit/8] ^= (1<<(iBit%8));
210} 210}
211 211
212bool Bu::BitString::getBit( long iBit ) 212bool Bu::BitString::getBit( long iBit )
213{ 213{
214 if( iBit >= iBits || iBit < 0 ) return false; 214 if( iBit >= iBits || iBit < 0 ) return false;
215 if( (caData[iBit/8] & (1<<(iBit%8))) == 0 ) 215 if( (caData[iBit/8] & (1<<(iBit%8))) == 0 )
216 { 216 {
217 return false; 217 return false;
218 } 218 }
219 return true; 219 return true;
220} 220}
221 221
222long Bu::BitString::getBitLength() 222long Bu::BitString::getBitLength()
223{ 223{
224 return iBits; 224 return iBits;
225} 225}
226 226
227long Bu::BitString::getSize() 227long Bu::BitString::getSize()
228{ 228{
229 return iBits; 229 return iBits;
230} 230}
231 231
232class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper ) 232class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper )
233{ 233{
234 if( iUpper == 0 || iUpper < iLower ) iUpper = iBits; 234 if( iUpper == 0 || iUpper < iLower ) iUpper = iBits;
235 235
236 Bu::BitString xSub( iUpper-iLower+1 ); 236 Bu::BitString xSub( iUpper-iLower+1 );
237 237
238 long shft = (iLower%8); 238 long shft = (iLower%8);
239 long base = (iLower/8); 239 long base = (iLower/8);
240 unsigned char lowmask=0; 240 unsigned char lowmask=0;
241 for( long j = 0; j < 8-shft; j++ ) 241 for( long j = 0; j < 8-shft; j++ )
242 { 242 {
243 lowmask |= (1<<j); 243 lowmask |= (1<<j);
244 } 244 }
245 for( long j = 0; j < xSub.iBytes; j++ ) 245 for( long j = 0; j < xSub.iBytes; j++ )
246 { 246 {
247 xSub.caData[j] = ((caData[base+j]>>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask)); 247 xSub.caData[j] = ((caData[base+j]>>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask));
248 } 248 }
249 xSub.fixup(); 249 xSub.fixup();
250 250
251 return xSub; 251 return xSub;
252} 252}
253 253
254long Bu::BitString::toLong( long iStart, long iSize ) 254long Bu::BitString::toLong( long iStart, long iSize )
255{ 255{
256 if( iSize < 1 ) iSize = 1; 256 if( iSize < 1 ) iSize = 1;
257 if( iSize > 32 ) iSize = 32; 257 if( iSize > 32 ) iSize = 32;
258 if( iStart < 0 ) return 0; 258 if( iStart < 0 ) return 0;
259 if( iStart+iSize > getSize() ) return 0; 259 if( iStart+iSize > getSize() ) return 0;
260 260
261 Bu::BitString tmpo; 261 Bu::BitString tmpo;
262 tmpo = getSubString( iStart, iStart+iSize-1 ); 262 tmpo = getSubString( iStart, iStart+iSize-1 );
263 long x = *((long *)tmpo.caData); 263 long x = *((long *)tmpo.caData);
264 264
265 return x; 265 return x;
266} 266}
267/* 267/*
268std::string Bu::BitString::toString( bool bAddSpacers ) 268std::string Bu::BitString::toString( bool bAddSpacers )
269{ 269{
270 long iSz = iBits; 270 long iSz = iBits;
271 if( bAddSpacers ) 271 if( bAddSpacers )
272 { 272 {
273 iSz += (iBits/8); 273 iSz += (iBits/8);
274 if( iBits%8 == 0 ) iSz--; 274 if( iBits%8 == 0 ) iSz--;
275 } 275 }
276 std::string xStr; 276 std::string xStr;
277 277
278 int bw=0; 278 int bw=0;
279 int of=0; 279 int of=0;
280 for( int j = iBits-1; j >= 0; j-- ) 280 for( int j = iBits-1; j >= 0; j-- )
281 { 281 {
282 if( getBit( j ) ) 282 if( getBit( j ) )
283 { 283 {
284 xStr += '1'; 284 xStr += '1';
285 } 285 }
286 else 286 else
287 { 287 {
288 xStr += '0'; 288 xStr += '0';
289 } 289 }
290 290
291 if( bAddSpacers ) 291 if( bAddSpacers )
292 { 292 {
293 bw++; 293 bw++;
294 if( bw >= 8 && j < iBits-1 ) 294 if( bw >= 8 && j < iBits-1 )
295 { 295 {
296 bw = 0; 296 bw = 0;
297 of++; 297 of++;
298 xStr += ' '; 298 xStr += ' ';
299 } 299 }
300 } 300 }
301 } 301 }
302 302
303 return xStr; 303 return xStr;
304} 304}
305*/ 305*/
306void Bu::BitString::clear() 306void Bu::BitString::clear()
307{ 307{
308 if( caData != NULL ) 308 if( caData != NULL )
309 { 309 {
310 memset( caData, 0, iBytes ); 310 memset( caData, 0, iBytes );
311 } 311 }
312} 312}
313 313
314bool Bu::BitString::setBitLength( long iLength, bool bClear ) 314bool Bu::BitString::setBitLength( long iLength, bool bClear )
315{ 315{
316 return setSize( iLength, bClear ); 316 return setSize( iLength, bClear );
317} 317}
318 318
319bool Bu::BitString::setSize( long iLength, bool bClear ) 319bool Bu::BitString::setSize( long iLength, bool bClear )
320{ 320{
321 // First, if there's nothing, then allocate an empty one. 321 // First, if there's nothing, then allocate an empty one.
322 if( caData == NULL ) 322 if( caData == NULL )
323 { 323 {
324 iBits = iLength; 324 iBits = iLength;
325 iBytes = bitsToBytes( iLength ); 325 iBytes = bitsToBytes( iLength );
326 caData = new unsigned char[iBytes]; 326 caData = new unsigned char[iBytes];
327 memset( caData, 0, iBytes ); 327 memset( caData, 0, iBytes );
328 return true; 328 return true;
329 } 329 }
330 330
331 // If the new length is the same as the old, don't do anything, but do 331 // If the new length is the same as the old, don't do anything, but do
332 // check to see if we should still clear the data. 332 // check to see if we should still clear the data.
333 if( iBits != iLength ) 333 if( iBits != iLength )
334 { 334 {
335 // Ok, we are changing the number if bits, but are we changing the 335 // Ok, we are changing the number if bits, but are we changing the
336 // number of bytes? 336 // number of bytes?
337 long iNewBytes = bitsToBytes( iLength ); 337 long iNewBytes = bitsToBytes( iLength );
338 if( iBytes == iNewBytes ) 338 if( iBytes == iNewBytes )
339 { 339 {
340 // No? That makes life easier 340 // No? That makes life easier
341 iBits = iLength; 341 iBits = iLength;
342 setMask(); 342 setMask();
343 if( bClear ) 343 if( bClear )
344 { 344 {
345 clear(); 345 clear();
346 } 346 }
347 } 347 }
348 else 348 else
349 { 349 {
350 // Ok, reallocate and copy... 350 // Ok, reallocate and copy...
351 iBits = iLength; 351 iBits = iLength;
352// long iNewBytes = bitsToBytes( iLength ); 352// long iNewBytes = bitsToBytes( iLength );
353 if( bClear ) 353 if( bClear )
354 { 354 {
355 delete[] caData; 355 delete[] caData;
356 caData = new unsigned char[iNewBytes]; 356 caData = new unsigned char[iNewBytes];
357 memset( caData, 0, iNewBytes ); 357 memset( caData, 0, iNewBytes );
358 } 358 }
359 else 359 else
360 { 360 {
361 unsigned char *tmp = caData; 361 unsigned char *tmp = caData;
362 caData = new unsigned char[iNewBytes]; 362 caData = new unsigned char[iNewBytes];
363 if( iNewBytes < iBytes ) 363 if( iNewBytes < iBytes )
364 { 364 {
365 memcpy( caData, tmp, iNewBytes ); 365 memcpy( caData, tmp, iNewBytes );
366 } 366 }
367 else 367 else
368 { 368 {
369 memcpy( caData, tmp, iBytes ); 369 memcpy( caData, tmp, iBytes );
370 } 370 }
371 delete[] tmp; 371 delete[] tmp;
372 } 372 }
373 iBytes = iNewBytes; 373 iBytes = iNewBytes;
374 374
375 setMask(); 375 setMask();
376 } 376 }
377 377
378 } 378 }
379 else if( bClear ) 379 else if( bClear )
380 { 380 {
381 clear(); 381 clear();
382 } 382 }
383 383
384 return true; 384 return true;
385} 385}
386 386
387void Bu::BitString::setMask() 387void Bu::BitString::setMask()
388{ 388{
389 // This can either mean that there are a multiple of eight bits or 389 // This can either mean that there are a multiple of eight bits or
390 // zero, if there are zero you're an idiot (zero can't happen, because 390 // zero, if there are zero you're an idiot (zero can't happen, because
391 // we would allocate an extra byte and never use it) 391 // we would allocate an extra byte and never use it)
392 if( (iBits%8 == 0) ) 392 if( (iBits%8 == 0) )
393 { 393 {
394 cTopByteMask = 0xFF; 394 cTopByteMask = 0xFF;
395 } 395 }
396 else 396 else
397 { 397 {
398 cTopByteMask = 0; 398 cTopByteMask = 0;
399 for( long j = 0; j < (iBits%8); j++ ) 399 for( long j = 0; j < (iBits%8); j++ )
400 { 400 {
401 cTopByteMask |= (1<<j); 401 cTopByteMask |= (1<<j);
402 } 402 }
403 } 403 }
404} 404}
405 405
406void Bu::BitString::randomize() 406void Bu::BitString::randomize()
407{ 407{
408 if( caData != NULL ) 408 if( caData != NULL )
409 { 409 {
410 for( int j = 0; j < iBytes; j++ ) 410 for( int j = 0; j < iBytes; j++ )
411 { 411 {
412 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF); 412 caData[j] = (unsigned char)(Bu::Random::rand() & 0xFF);
413 } 413 }
414 fixup(); 414 fixup();
415 } 415 }
416} 416}
417 417
418void Bu::BitString::invert() 418void Bu::BitString::invert()
419{ 419{
420 if( caData != NULL ) 420 if( caData != NULL )
421 { 421 {
422 for( long j = 0; j < iBytes; j++ ) 422 for( long j = 0; j < iBytes; j++ )
423 { 423 {
424 caData[j] = ~caData[j]; 424 caData[j] = ~caData[j];
425 } 425 }
426 fixup(); 426 fixup();
427 } 427 }
428} 428}
429 429
430long Bu::BitString::getHighestOrderBitPos() 430long Bu::BitString::getHighestOrderBitPos()
431{ 431{
432 for( long j = iBits-1; j >= 0; j-- ) 432 for( long j = iBits-1; j >= 0; j-- )
433 { 433 {
434 if( getBit( j ) ) 434 if( getBit( j ) )
435 { 435 {
436 return j; 436 return j;
437 } 437 }
438 } 438 }
439 439
440 return -1; 440 return -1;
441} 441}
442 442
443Bu::String Bu::BitString::toString() 443Bu::String Bu::BitString::toString()
444{ 444{
445 Bu::String sRet; 445 Bu::String sRet;
446 for( int j = iBits-1; j >= 0; j-- ) 446 for( int j = iBits-1; j >= 0; j-- )
447 sRet.append( getBit( j )?'1':'0' ); 447 sRet.append( getBit( j )?'1':'0' );
448 return sRet; 448 return sRet;
449} 449}
450 450
451/* 451/*
452bool Bu::BitString::writeToFile( FILE *fh ) 452bool Bu::BitString::writeToFile( FILE *fh )
453{ 453{
454 fwrite( &iBits, sizeof(long), 1, fh ); 454 fwrite( &iBits, sizeof(long), 1, fh );
455 fwrite( caData, sizeof(char), iBytes, fh ); 455 fwrite( caData, sizeof(char), iBytes, fh );
456 456
457 return true; 457 return true;
458} 458}
459 459
460bool Bu::BitString::readFromFile( FILE *fh ) 460bool Bu::BitString::readFromFile( FILE *fh )
461{ 461{
462 fread( &iBits, sizeof(long), 1, fh ); 462 fread( &iBits, sizeof(long), 1, fh );
463 463
464 iBytes = bitsToBytes( iBits ); 464 iBytes = bitsToBytes( iBits );
465 if( caData ) delete[] caData; 465 if( caData ) delete[] caData;
466 caData = new unsigned char[iBytes]; 466 caData = new unsigned char[iBytes];
467 467
468 fread( caData, sizeof(char), iBytes, fh ); 468 fread( caData, sizeof(char), iBytes, fh );
469 469
470 setMask(); 470 setMask();
471 471
472 fixup(); 472 fixup();
473 473
474 return true; 474 return true;
475}*/ 475}*/
diff --git a/src/unstable/bitstring.h b/src/unstable/bitstring.h
index fd34402..ea884f6 100644
--- a/src/unstable/bitstring.h
+++ b/src/unstable/bitstring.h
@@ -13,212 +13,212 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 /** 16 /**
17 * Manages an arbitrarily sized string of bits, and allows basic interaction 17 * Manages an arbitrarily sized string of bits, and allows basic interaction
18 * with them. This includes basic non-mathematical bitwise operations such 18 * with them. This includes basic non-mathematical bitwise operations such
19 * as setting and testing bits, shifting the string, inversion and a few 19 * as setting and testing bits, shifting the string, inversion and a few
20 * extras like randomization. On linux systems this takes advantage of long 20 * extras like randomization. On linux systems this takes advantage of long
21 * longs giving you a maximum size of about 2tb per string. 21 * longs giving you a maximum size of about 2tb per string.
22 * 22 *
23 * For more general and mathematical type interaction see BitStringInt. 23 * For more general and mathematical type interaction see BitStringInt.
24 * 24 *
25 */ 25 */
26 class BitString 26 class BitString
27 { 27 {
28 public: 28 public:
29 /** 29 /**
30 * Constructs a blank and basic BitString. This is actually useful 30 * Constructs a blank and basic BitString. This is actually useful
31 * since you can resize BitStrings at will, and even retain the data 31 * since you can resize BitStrings at will, and even retain the data
32 * that was in them. 32 * that was in them.
33 */ 33 */
34 BitString(); 34 BitString();
35 35
36 /** 36 /**
37 * Constructs a BitString object as a copy of another BitString. This 37 * Constructs a BitString object as a copy of another BitString. This
38 * is a standard copy constructor and produces an exact duplicate of 38 * is a standard copy constructor and produces an exact duplicate of
39 * the original BitString object. 39 * the original BitString object.
40 *@param xSrc Source BitString to copy data from. 40 *@param xSrc Source BitString to copy data from.
41 */ 41 */
42 BitString( const BitString &xSrc ); 42 BitString( const BitString &xSrc );
43 43
44 /** 44 /**
45 * Constructs a BitString with length iBits and optionally fills it with 45 * Constructs a BitString with length iBits and optionally fills it with
46 * random data. The default setting, to not fill randomly, will produce 46 * random data. The default setting, to not fill randomly, will produce
47 * a blank (all zeros) string of the specified size. 47 * a blank (all zeros) string of the specified size.
48 *@param iBits The length of the new BitString in bits. 48 *@param iBits The length of the new BitString in bits.
49 *@param bFillRandomly Wether or not to randomize this BitString. 49 *@param bFillRandomly Wether or not to randomize this BitString.
50 */ 50 */
51 BitString( long iBits, bool bFillRandomly=false ); 51 BitString( long iBits, bool bFillRandomly=false );
52 52
53 /** 53 /**
54 * Virtual deconstructor for the BitString. Takes care of cleanup for 54 * Virtual deconstructor for the BitString. Takes care of cleanup for
55 * you. What more do you really want to know? 55 * you. What more do you really want to know?
56 */ 56 */
57 virtual ~BitString(); 57 virtual ~BitString();
58 58
59 // basic interaction 59 // basic interaction
60 /** 60 /**
61 * Sets a bit in the BitString. In it's normal mode it will always turn 61 * Sets a bit in the BitString. In it's normal mode it will always turn
62 * the given bit on, to clear a bit set bBitState to false instead of 62 * the given bit on, to clear a bit set bBitState to false instead of
63 * true. This operation runs in O(1). 63 * true. This operation runs in O(1).
64 *@param iBit The zero-based index of the bit to modify. 64 *@param iBit The zero-based index of the bit to modify.
65 *@param bBitState Set to true to set the bit to 1, set to false to set 65 *@param bBitState Set to true to set the bit to 1, set to false to set
66 * the bit to 0. 66 * the bit to 0.
67 */ 67 */
68 void setBit( long iBit, bool bBitState=true ); 68 void setBit( long iBit, bool bBitState=true );
69 69
70 /** 70 /**
71 * Reverses the state of the given bit. This will set the given bit 71 * Reverses the state of the given bit. This will set the given bit
72 * to a 1 if it was 0, and to 0 if it was 1. This operation runs in 72 * to a 1 if it was 0, and to 0 if it was 1. This operation runs in
73 * O(1), and it should be noted that using this is marginally faster 73 * O(1), and it should be noted that using this is marginally faster
74 * than doing the test and flip yourself with getBit and setBit since 74 * than doing the test and flip yourself with getBit and setBit since
75 * it uses a bitwise not operation and doesn't actually test the bit 75 * it uses a bitwise not operation and doesn't actually test the bit
76 * itself. 76 * itself.
77 *@param iBit The index of the bit to flip. 77 *@param iBit The index of the bit to flip.
78 */ 78 */
79 void flipBit( long iBit ); 79 void flipBit( long iBit );
80 80
81 /** 81 /**
82 * Gets the state of the given bit. This follows the standard 82 * Gets the state of the given bit. This follows the standard
83 * convention used so far, a returned value of true means the bit in 83 * convention used so far, a returned value of true means the bit in
84 * question is 1, and a value of flase means the bit is 0. All bits 84 * question is 1, and a value of flase means the bit is 0. All bits
85 * out of range of the BitString are treated as off, but are 85 * out of range of the BitString are treated as off, but are
86 * "accessable" in that this does not produce any kind of error 86 * "accessable" in that this does not produce any kind of error
87 * message. This is intentional. This operation runs in O(1). 87 * message. This is intentional. This operation runs in O(1).
88 *@param iBit The index of the bit to test. 88 *@param iBit The index of the bit to test.
89 *@returns True for a 1, false for a 0. 89 *@returns True for a 1, false for a 0.
90 */ 90 */
91 bool getBit( long iBit ); 91 bool getBit( long iBit );
92 92
93 /** 93 /**
94 * Inverts the entire BitString, in effect this calls flipBit on every 94 * Inverts the entire BitString, in effect this calls flipBit on every
95 * bit in the string but is faster since it can operate on whole bytes 95 * bit in the string but is faster since it can operate on whole bytes
96 * at a time instead of individual bits. This operation runs in O(N). 96 * at a time instead of individual bits. This operation runs in O(N).
97 */ 97 */
98 void invert(); 98 void invert();
99 99
100 /** 100 /**
101 * Returns the number of bits allocated in this BitString. This 101 * Returns the number of bits allocated in this BitString. This
102 * operation runs in O(1) time since this value is cached and not 102 * operation runs in O(1) time since this value is cached and not
103 * computed. 103 * computed.
104 *@returns The number of bits allocated in this BitString. 104 *@returns The number of bits allocated in this BitString.
105 */ 105 */
106 DEPRECATED 106 DEPRECATED
107 long getBitLength(); 107 long getBitLength();
108 108
109 long getSize(); 109 long getSize();
110 110
111 /** 111 /**
112 * Sets the entire BitString to zeros, but it does it very quickly. 112 * Sets the entire BitString to zeros, but it does it very quickly.
113 * This operation runs in O(N). 113 * This operation runs in O(N).
114 */ 114 */
115 void clear(); 115 void clear();
116 116
117 /** 117 /**
118 * Gets another BitString that is autonomous of the current one 118 * Gets another BitString that is autonomous of the current one
119 * (contains a copy of the memory, not a pointer) and contains a subset 119 * (contains a copy of the memory, not a pointer) and contains a subset
120 * of the data in the current BitString. This is an inclusive 120 * of the data in the current BitString. This is an inclusive
121 * operation, so grabbing bits 0-5 will give you 6 bits. This is based 121 * operation, so grabbing bits 0-5 will give you 6 bits. This is based
122 * on a very tricky bit-shifting algorithm and runs very quickly, in 122 * on a very tricky bit-shifting algorithm and runs very quickly, in
123 * O(N) time. Passing in a value of zero for iUpper, or any value for 123 * O(N) time. Passing in a value of zero for iUpper, or any value for
124 * iUpper that is less than iLower will set iUpper equal to the number 124 * iUpper that is less than iLower will set iUpper equal to the number
125 * of bits in the BitString. 125 * of bits in the BitString.
126 *@param iLower The first bit in the current string, will be the first 126 *@param iLower The first bit in the current string, will be the first
127 * bit (0 index) in the new sub string. 127 * bit (0 index) in the new sub string.
128 *@param iUpper The last bit in the current string, will be the last 128 *@param iUpper The last bit in the current string, will be the last
129 * bit in the new sub string. iUpper is included in the sub string. 129 * bit in the new sub string. iUpper is included in the sub string.
130 *@returns A new BitString object ready to be used. Please note that 130 *@returns A new BitString object ready to be used. Please note that
131 * managing this new object is up to whomever calls this function. 131 * managing this new object is up to whomever calls this function.
132 */ 132 */
133 class BitString getSubString( long iLower, long iUpper ); 133 class BitString getSubString( long iLower, long iUpper );
134 134
135 /** 135 /**
136 * Sets the number of bits in the BitString, allocating more memory if 136 * Sets the number of bits in the BitString, allocating more memory if
137 * necesarry, or freeing extra if able. The default operation of this 137 * necesarry, or freeing extra if able. The default operation of this
138 * function clears all data in the BitString while resizing it. If you 138 * function clears all data in the BitString while resizing it. If you
139 * would like to keep as much of the data that you had in your BitString 139 * would like to keep as much of the data that you had in your BitString
140 * as possible, then set bClear to false, and any data that will fit 140 * as possible, then set bClear to false, and any data that will fit
141 * into the new BitString length will be retained. If increasing the 141 * into the new BitString length will be retained. If increasing the
142 * number of bits, the new bits will come into existance cleared (set 142 * number of bits, the new bits will come into existance cleared (set
143 * to 0). 143 * to 0).
144 *@param iLength The number of bits to set the BitString to. 144 *@param iLength The number of bits to set the BitString to.
145 *@param bClear When true, all data is eradicated and zeroed, when set 145 *@param bClear When true, all data is eradicated and zeroed, when set
146 * to false an effort is made to retain the existing data. 146 * to false an effort is made to retain the existing data.
147 *@returns true on success, false on failure. 147 *@returns true on success, false on failure.
148 */ 148 */
149 DEPRECATED 149 DEPRECATED
150 bool setBitLength( long iLength, bool bClear=true ); 150 bool setBitLength( long iLength, bool bClear=true );
151 bool setSize( long iLength, bool bClear=true ); 151 bool setSize( long iLength, bool bClear=true );
152 152
153 /** 153 /**
154 * Randomize the entire BitString, one bit at a time. This is actually 154 * Randomize the entire BitString, one bit at a time. This is actually
155 * the function called by the constructor when the user selects initial 155 * the function called by the constructor when the user selects initial
156 * randomization. This function uses the system random() function, so 156 * randomization. This function uses the system random() function, so
157 * srandom may be used to effect this process at will. 157 * srandom may be used to effect this process at will.
158 */ 158 */
159 void randomize(); 159 void randomize();
160 160
161 /** 161 /**
162 * Operates exactly like <<. All data in the BitString is shifted to 162 * Operates exactly like <<. All data in the BitString is shifted to
163 * the left by some number of bits, any data pushed off the edge of the 163 * the left by some number of bits, any data pushed off the edge of the
164 * BitString is lost, and all new data coming in will be zeroed. 164 * BitString is lost, and all new data coming in will be zeroed.
165 * Using a negative value in the shiftLeft function will turn it into 165 * Using a negative value in the shiftLeft function will turn it into
166 * the shiftRight function. 166 * the shiftRight function.
167 *@param iAmt The number of bit positions to shift all data. 167 *@param iAmt The number of bit positions to shift all data.
168 */ 168 */
169 void shiftLeft( long iAmt ); // just like << 169 void shiftLeft( long iAmt ); // just like <<
170 170
171 /** 171 /**
172 * Operates exactly like >>. All data in the BitString is shifted to 172 * Operates exactly like >>. All data in the BitString is shifted to
173 * the right by some number of bits, any data pushed off the edge of the 173 * the right by some number of bits, any data pushed off the edge of the
174 * BitString is lost, and all new data coming in will be zeroed. 174 * BitString is lost, and all new data coming in will be zeroed.
175 * Using a negative value in the shiftRight function will turn it into 175 * Using a negative value in the shiftRight function will turn it into
176 * the shiftLeft function. 176 * the shiftLeft function.
177 *@param iAmt The number of bit positions to shift all data. 177 *@param iAmt The number of bit positions to shift all data.
178 */ 178 */
179 void shiftRight( long iAmt ); // just like >> 179 void shiftRight( long iAmt ); // just like >>
180 180
181 /** 181 /**
182 * Searches through the BitString and returns the index of the highest 182 * Searches through the BitString and returns the index of the highest
183 * order bit position (the highest index) with an on bit (a bit set to 183 * order bit position (the highest index) with an on bit (a bit set to
184 * 1). This is a handy helper function and rather faster than calling 184 * 1). This is a handy helper function and rather faster than calling
185 * getBit() over and over again. 185 * getBit() over and over again.
186 *@returns The index of the highest indexed on bit. 186 *@returns The index of the highest indexed on bit.
187 */ 187 */
188 long getHighestOrderBitPos(); 188 long getHighestOrderBitPos();
189 189
190 // Conversion 190 // Conversion
191 /** 191 /**
192 * Convert a block of data (no more than 32 bits) to a primitive long 192 * Convert a block of data (no more than 32 bits) to a primitive long
193 * type. 193 * type.
194 * This is done in a little bit interesting way, so it may not always be 194 * This is done in a little bit interesting way, so it may not always be
195 * the fastest way to access the data that you want, although it will 195 * the fastest way to access the data that you want, although it will
196 * always ensure that the long that is written makes numerical sense, as 196 * always ensure that the long that is written makes numerical sense, as
197 * we write numbers, regaurdless of platform. 197 * we write numbers, regaurdless of platform.
198 *@param iStart The first bit in the BitString to include in the long 198 *@param iStart The first bit in the BitString to include in the long
199 *@param iSize THe number of bits to include, if this value is set over 199 *@param iSize THe number of bits to include, if this value is set over
200 * 32 it will be automatically truncated to, or however many bits there 200 * 32 it will be automatically truncated to, or however many bits there
201 * are in a long in your system. 201 * are in a long in your system.
202 *@returns A long converted from your raw BitString data. 202 *@returns A long converted from your raw BitString data.
203 */ 203 */
204 long toLong( long iStart = 0, long iSize = 32 ); 204 long toLong( long iStart = 0, long iSize = 32 );
205 205
206 Bu::String toString(); 206 Bu::String toString();
207 207
208 //operators 208 //operators
209 BitString &operator=( const BitString &xSrc ); 209 BitString &operator=( const BitString &xSrc );
210 BitString operator~(); 210 BitString operator~();
211 BitString operator<<( const long iAmt ); 211 BitString operator<<( const long iAmt );
212 BitString operator>>( const long iAmt ); 212 BitString operator>>( const long iAmt );
213 213
214 private: 214 private:
215 void fixup(); 215 void fixup();
216 void setMask(); 216 void setMask();
217 unsigned char *caData; 217 unsigned char *caData;
218 long iBits; 218 long iBits;
219 long iBytes; 219 long iBytes;
220 unsigned char cTopByteMask; 220 unsigned char cTopByteMask;
221 }; 221 };
222}; 222};
223 223
224#endif 224#endif
diff --git a/src/unstable/fifo.cpp b/src/unstable/fifo.cpp
index 6f327df..4b4a2bf 100644
--- a/src/unstable/fifo.cpp
+++ b/src/unstable/fifo.cpp
@@ -17,75 +17,75 @@
17namespace Bu { subExceptionDef( FifoException ) } 17namespace Bu { subExceptionDef( FifoException ) }
18 18
19Bu::Fifo::Fifo( const Bu::String &sName, int iFlags, mode_t mAcc ) : 19Bu::Fifo::Fifo( const Bu::String &sName, int iFlags, mode_t mAcc ) :
20 iFlags( iFlags ), 20 iFlags( iFlags ),
21 iIn( -1 ), 21 iIn( -1 ),
22 iOut( -1 ) 22 iOut( -1 )
23{ 23{
24#ifndef WIN32 24#ifndef WIN32
25 if( iFlags&Create ) 25 if( iFlags&Create )
26 { 26 {
27 if( mkfifo( sName.getStr(), mAcc ) ) 27 if( mkfifo( sName.getStr(), mAcc ) )
28 { 28 {
29 throw FifoException("Error creating fifo: %s\n", strerror( errno ) ); 29 throw FifoException("Error creating fifo: %s\n", strerror( errno ) );
30 } 30 }
31 } 31 }
32 if( iFlags&Read ) 32 if( iFlags&Read )
33 { 33 {
34 iIn = ::open( 34 iIn = ::open(
35 sName.getStr(), 35 sName.getStr(),
36 O_RDONLY|((iFlags&NonBlock)?O_NONBLOCK:0) 36 O_RDONLY|((iFlags&NonBlock)?O_NONBLOCK:0)
37 ); 37 );
38 } 38 }
39 if( iFlags&Write ) 39 if( iFlags&Write )
40 { 40 {
41 iOut = ::open( 41 iOut = ::open(
42 sName.getStr(), 42 sName.getStr(),
43 O_WRONLY 43 O_WRONLY
44 ); 44 );
45 } 45 }
46#else 46#else
47 #warning Bu::Fifo::Fifo IS A STUB for WIN32!!!! 47 #warning Bu::Fifo::Fifo IS A STUB for WIN32!!!!
48#endif 48#endif
49} 49}
50 50
51Bu::Fifo::~Fifo() 51Bu::Fifo::~Fifo()
52{ 52{
53 close(); 53 close();
54} 54}
55 55
56void Bu::Fifo::close() 56void Bu::Fifo::close()
57{ 57{
58 if( iIn > -1 ) 58 if( iIn > -1 )
59 { 59 {
60 ::close( iIn ); 60 ::close( iIn );
61 iIn = -1; 61 iIn = -1;
62 } 62 }
63 if( iOut > -1 ) 63 if( iOut > -1 )
64 { 64 {
65 ::close( iOut ); 65 ::close( iOut );
66 iOut = -1; 66 iOut = -1;
67 } 67 }
68} 68}
69 69
70Bu::size Bu::Fifo::read( void *pBuf, Bu::size nBytes ) 70Bu::size Bu::Fifo::read( void *pBuf, Bu::size nBytes )
71{ 71{
72 if( iIn < 0 ) 72 if( iIn < 0 )
73 throw FifoException("Fifo not open for reading."); 73 throw FifoException("Fifo not open for reading.");
74 74
75 return TEMP_FAILURE_RETRY( ::read( iIn, pBuf, nBytes ) ); 75 return TEMP_FAILURE_RETRY( ::read( iIn, pBuf, nBytes ) );
76} 76}
77 77
78Bu::size Bu::Fifo::write( const void *pBuf, Bu::size nBytes ) 78Bu::size Bu::Fifo::write( const void *pBuf, Bu::size nBytes )
79{ 79{
80 if( iOut < 0 ) 80 if( iOut < 0 )
81 throw FifoException("Fifo not open for writing."); 81 throw FifoException("Fifo not open for writing.");
82 82
83 return TEMP_FAILURE_RETRY( ::write( iOut, pBuf, nBytes ) ); 83 return TEMP_FAILURE_RETRY( ::write( iOut, pBuf, nBytes ) );
84} 84}
85 85
86Bu::size Bu::Fifo::tell() 86Bu::size Bu::Fifo::tell()
87{ 87{
88 return -1; 88 return -1;
89} 89}
90 90
91void Bu::Fifo::seek( Bu::size ) 91void Bu::Fifo::seek( Bu::size )
@@ -102,53 +102,53 @@ void Bu::Fifo::setPosEnd( Bu::size )
102 102
103bool Bu::Fifo::isEos() 103bool Bu::Fifo::isEos()
104{ 104{
105 return false; 105 return false;
106} 106}
107 107
108bool Bu::Fifo::canRead() 108bool Bu::Fifo::canRead()
109{ 109{
110 return (iIn>-1); 110 return (iIn>-1);
111} 111}
112 112
113bool Bu::Fifo::canWrite() 113bool Bu::Fifo::canWrite()
114{ 114{
115 return (iOut>-1); 115 return (iOut>-1);
116} 116}
117 117
118bool Bu::Fifo::isReadable() 118bool Bu::Fifo::isReadable()
119{ 119{
120 return (iIn>-1); 120 return (iIn>-1);
121} 121}
122 122
123bool Bu::Fifo::isWritable() 123bool Bu::Fifo::isWritable()
124{ 124{
125 return (iOut>-1); 125 return (iOut>-1);
126} 126}
127 127
128bool Bu::Fifo::isSeekable() 128bool Bu::Fifo::isSeekable()
129{ 129{
130 return false; 130 return false;
131} 131}
132 132
133bool Bu::Fifo::isBlocking() 133bool Bu::Fifo::isBlocking()
134{ 134{
135#ifndef WIN32 135#ifndef WIN32
136 return ((fcntl( iIn, F_GETFL, 0 )&O_NONBLOCK) == O_NONBLOCK); 136 return ((fcntl( iIn, F_GETFL, 0 )&O_NONBLOCK) == O_NONBLOCK);
137#else 137#else
138 #warning Bu::Fifo::isBlocking IS A STUB for WIN32!!!! 138 #warning Bu::Fifo::isBlocking IS A STUB for WIN32!!!!
139#endif 139#endif
140} 140}
141 141
142void Bu::Fifo::setBlocking( bool bBlocking ) 142void Bu::Fifo::setBlocking( bool bBlocking )
143{ 143{
144#ifndef WIN32 144#ifndef WIN32
145 if( bBlocking ) 145 if( bBlocking )
146 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )&(~O_NONBLOCK) ); 146 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )&(~O_NONBLOCK) );
147 else 147 else
148 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )|O_NONBLOCK ); 148 fcntl( iIn, F_SETFL, fcntl( iIn, F_GETFL, 0 )|O_NONBLOCK );
149#else 149#else
150 #warning Bu::Fifo::setBlocking IS A STUB for WIN32!!!! 150 #warning Bu::Fifo::setBlocking IS A STUB for WIN32!!!!
151#endif 151#endif
152} 152}
153 153
154void Bu::Fifo::flush() 154void Bu::Fifo::flush()
@@ -157,6 +157,6 @@ void Bu::Fifo::flush()
157 157
158bool Bu::Fifo::isOpen() 158bool Bu::Fifo::isOpen()
159{ 159{
160 return (iIn > -1) || (iOut > -1); 160 return (iIn > -1) || (iOut > -1);
161} 161}
162 162
diff --git a/src/unstable/fifo.h b/src/unstable/fifo.h
index ea32f04..3d9192a 100644
--- a/src/unstable/fifo.h
+++ b/src/unstable/fifo.h
@@ -18,55 +18,55 @@
18 18
19namespace Bu 19namespace Bu
20{ 20{
21 subExceptionDecl( FifoException ); 21 subExceptionDecl( FifoException );
22 22
23 /** 23 /**
24 * A fifo stream. 24 * A fifo stream.
25 *@ingroup Streams 25 *@ingroup Streams
26 */ 26 */
27 class Fifo : public Bu::Stream 27 class Fifo : public Bu::Stream
28 { 28 {
29 public: 29 public:
30 Fifo( const Bu::String &sName, int iFlags, mode_t mAcc=-1 ); 30 Fifo( const Bu::String &sName, int iFlags, mode_t mAcc=-1 );
31 virtual ~Fifo(); 31 virtual ~Fifo();
32 32
33 virtual void close(); 33 virtual void close();
34 virtual Bu::size read( void *pBuf, Bu::size nBytes ); 34 virtual Bu::size read( void *pBuf, Bu::size nBytes );
35 virtual Bu::size write( const void *pBuf, Bu::size nBytes ); 35 virtual Bu::size write( const void *pBuf, Bu::size nBytes );
36 using Stream::write; 36 using Stream::write;
37 37
38 virtual Bu::size tell(); 38 virtual Bu::size tell();
39 virtual void seek( Bu::size offset ); 39 virtual void seek( Bu::size offset );
40 virtual void setPos( Bu::size pos ); 40 virtual void setPos( Bu::size pos );
41 virtual void setPosEnd( Bu::size pos ); 41 virtual void setPosEnd( Bu::size pos );
42 virtual bool isEos(); 42 virtual bool isEos();
43 virtual bool isOpen(); 43 virtual bool isOpen();
44 44
45 virtual void flush(); 45 virtual void flush();
46 46
47 virtual bool canRead(); 47 virtual bool canRead();
48 virtual bool canWrite(); 48 virtual bool canWrite();
49 49
50 virtual bool isReadable(); 50 virtual bool isReadable();
51 virtual bool isWritable(); 51 virtual bool isWritable();
52 virtual bool isSeekable(); 52 virtual bool isSeekable();
53 53
54 virtual bool isBlocking(); 54 virtual bool isBlocking();
55 virtual void setBlocking( bool bBlocking=true ); 55 virtual void setBlocking( bool bBlocking=true );
56 56
57 enum { 57 enum {
58 Read = 0x01, 58 Read = 0x01,
59 Write = 0x02, 59 Write = 0x02,
60 Create = 0x04, 60 Create = 0x04,
61 Delete = 0x08, 61 Delete = 0x08,
62 NonBlock = 0x10 62 NonBlock = 0x10
63 }; 63 };
64 64
65 private: 65 private:
66 int iFlags; 66 int iFlags;
67 int iIn; 67 int iIn;
68 int iOut; 68 int iOut;
69 }; 69 };
70} 70}
71 71
72#endif 72#endif
diff --git a/src/unstable/itoserver.cpp b/src/unstable/itoserver.cpp
index 7dbce6c..103bf90 100644
--- a/src/unstable/itoserver.cpp
+++ b/src/unstable/itoserver.cpp
@@ -13,121 +13,121 @@
13#include "bu/tcpsocket.h" 13#include "bu/tcpsocket.h"
14 14
15Bu::ItoServer::ItoServer() : 15Bu::ItoServer::ItoServer() :
16 nTimeoutSec( 1 ), 16 nTimeoutSec( 1 ),
17 nTimeoutUSec( 0 ) 17 nTimeoutUSec( 0 )
18{ 18{
19 FD_ZERO( &fdActive ); 19 FD_ZERO( &fdActive );
20} 20}
21 21
22Bu::ItoServer::~ItoServer() 22Bu::ItoServer::~ItoServer()
23{ 23{
24 while( !qClientCleanup.isEmpty() ) 24 while( !qClientCleanup.isEmpty() )
25 { 25 {
26 ItoClient *pCli = qClientCleanup.dequeue(); 26 ItoClient *pCli = qClientCleanup.dequeue();
27 pCli->join(); 27 pCli->join();
28 delete pCli; 28 delete pCli;
29 } 29 }
30 // TODO: Make sure here that each client has shutdown it's socket, and 30 // TODO: Make sure here that each client has shutdown it's socket, and
31 // maybe even written any extra data, we could put a timelimit on this... 31 // maybe even written any extra data, we could put a timelimit on this...
32 // anyway, it's not as clean as it could be right now. 32 // anyway, it's not as clean as it could be right now.
33 for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) 33 for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ )
34 { 34 {
35 ItoClient *pCli = (*i); 35 ItoClient *pCli = (*i);
36 pCli->join(); 36 pCli->join();
37 delete pCli; 37 delete pCli;
38 } 38 }
39} 39}
40 40
41void Bu::ItoServer::addPort( int nPort, int nPoolSize ) 41void Bu::ItoServer::addPort( int nPort, int nPoolSize )
42{ 42{
43 TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); 43 TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize );
44 socket_t nSocket = s->getSocket(); 44 socket_t nSocket = s->getSocket();
45 FD_SET( nSocket, &fdActive ); 45 FD_SET( nSocket, &fdActive );
46 hServers.insert( nSocket, s ); 46 hServers.insert( nSocket, s );
47} 47}
48 48
49void Bu::ItoServer::addPort( const String &sAddr, int nPort, int nPoolSize ) 49void Bu::ItoServer::addPort( const String &sAddr, int nPort, int nPoolSize )
50{ 50{
51 TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); 51 TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize );
52 socket_t nSocket = s->getSocket(); 52 socket_t nSocket = s->getSocket();
53 FD_SET( nSocket, &fdActive ); 53 FD_SET( nSocket, &fdActive );
54 hServers.insert( nSocket, s ); 54 hServers.insert( nSocket, s );
55} 55}
56 56
57void Bu::ItoServer::setTimeout( int nTimeoutSec, int nTimeoutUSec ) 57void Bu::ItoServer::setTimeout( int nTimeoutSec, int nTimeoutUSec )
58{ 58{
59 this->nTimeoutSec = nTimeoutSec; 59 this->nTimeoutSec = nTimeoutSec;
60 this->nTimeoutUSec = nTimeoutUSec; 60 this->nTimeoutUSec = nTimeoutUSec;
61} 61}
62 62
63void Bu::ItoServer::addClient( socket_t nSocket, int nPort ) 63void Bu::ItoServer::addClient( socket_t nSocket, int nPort )
64{ 64{
65 ItoClient *pC = new ItoClient( *this, nSocket, nPort, nTimeoutSec, 65 ItoClient *pC = new ItoClient( *this, nSocket, nPort, nTimeoutSec,
66 nTimeoutUSec ); 66 nTimeoutUSec );
67 67
68 imClients.lock(); 68 imClients.lock();
69 hClients.insert( nSocket, pC ); 69 hClients.insert( nSocket, pC );
70 imClients.unlock(); 70 imClients.unlock();
71 71
72 pC->start(); 72 pC->start();
73} 73}
74 74
75void Bu::ItoServer::run() 75void Bu::ItoServer::run()
76{ 76{
77 for(;;) 77 for(;;)
78 { 78 {
79 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; 79 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec };
80 80
81 fd_set fdRead = fdActive; 81 fd_set fdRead = fdActive;
82 //fd_set fdWrite = fdActive; 82 //fd_set fdWrite = fdActive;
83 fd_set fdException = fdActive; 83 fd_set fdException = fdActive;
84 84
85 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, NULL, &fdException, &xTimeout ) ) < 0 ) 85 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, NULL, &fdException, &xTimeout ) ) < 0 )
86 { 86 {
87 throw ExceptionBase("Error attempting to scan open connections."); 87 throw ExceptionBase("Error attempting to scan open connections.");
88 } 88 }
89 89
90 for( ServerHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) 90 for( ServerHash::iterator i = hServers.begin(); i != hServers.end(); i++ )
91 { 91 {
92 if( FD_ISSET( i.getKey(), &fdRead ) ) 92 if( FD_ISSET( i.getKey(), &fdRead ) )
93 { 93 {
94 TcpServerSocket *pSrv = i.getValue(); 94 TcpServerSocket *pSrv = i.getValue();
95 addClient( pSrv->accept(), pSrv->getPort() ); 95 addClient( pSrv->accept(), pSrv->getPort() );
96 } 96 }
97 } 97 }
98 98
99 while( !qClientCleanup.isEmpty() ) 99 while( !qClientCleanup.isEmpty() )
100 { 100 {
101 ItoClient *pCli = qClientCleanup.dequeue(); 101 ItoClient *pCli = qClientCleanup.dequeue();
102 pCli->join(); 102 pCli->join();
103 delete pCli; 103 delete pCli;
104 } 104 }
105 } 105 }
106} 106}
107 107
108void Bu::ItoServer::clientCleanup( socket_t iSocket ) 108void Bu::ItoServer::clientCleanup( socket_t iSocket )
109{ 109{
110 imClients.lock(); 110 imClients.lock();
111 ItoClient *pCli = hClients.get( iSocket ); 111 ItoClient *pCli = hClients.get( iSocket );
112 imClients.unlock(); 112 imClients.unlock();
113 qClientCleanup.enqueue( pCli ); 113 qClientCleanup.enqueue( pCli );
114} 114}
115 115
116Bu::ItoServer::ItoClient::ItoClient( ItoServer &rSrv, Bu::ItoServer::socket_t iSocket, int iPort, 116Bu::ItoServer::ItoClient::ItoClient( ItoServer &rSrv, Bu::ItoServer::socket_t iSocket, int iPort,
117 int nTimeoutSec, int nTimeoutUSec ) : 117 int nTimeoutSec, int nTimeoutUSec ) :
118 rSrv( rSrv ), 118 rSrv( rSrv ),
119 iSocket( iSocket ), 119 iSocket( iSocket ),
120 iPort( iPort ), 120 iPort( iPort ),
121 nTimeoutSec( nTimeoutSec ), 121 nTimeoutSec( nTimeoutSec ),
122 nTimeoutUSec( nTimeoutUSec ) 122 nTimeoutUSec( nTimeoutUSec )
123{ 123{
124 FD_ZERO( &fdActive ); 124 FD_ZERO( &fdActive );
125 FD_SET( iSocket, &fdActive ); 125 FD_SET( iSocket, &fdActive );
126 126
127 pClient = new Client( 127 pClient = new Client(
128 new Bu::TcpSocket( iSocket ), 128 new Bu::TcpSocket( iSocket ),
129 new SrvClientLinkFactory( rSrv ) 129 new SrvClientLinkFactory( rSrv )
130 ); 130 );
131} 131}
132 132
133Bu::ItoServer::ItoClient::~ItoClient() 133Bu::ItoServer::ItoClient::~ItoClient()
@@ -136,67 +136,67 @@ Bu::ItoServer::ItoClient::~ItoClient()
136 136
137void Bu::ItoServer::ItoClient::run() 137void Bu::ItoServer::ItoClient::run()
138{ 138{
139 imProto.lock(); 139 imProto.lock();
140 rSrv.onNewConnection( pClient, iPort ); 140 rSrv.onNewConnection( pClient, iPort );
141 pClient->processOutput(); 141 pClient->processOutput();
142 imProto.unlock(); 142 imProto.unlock();
143 143
144 for(;;) 144 for(;;)
145 { 145 {
146 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; 146 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec };
147 147
148 fd_set fdRead = fdActive; 148 fd_set fdRead = fdActive;
149 fd_set fdWrite; 149 fd_set fdWrite;
150 fd_set fdException = fdActive; 150 fd_set fdException = fdActive;
151 151
152 FD_ZERO( &fdWrite ); 152 FD_ZERO( &fdWrite );
153 if( pClient->hasOutput() ) 153 if( pClient->hasOutput() )
154 FD_SET( iSocket, &fdWrite ); 154 FD_SET( iSocket, &fdWrite );
155 155
156 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, 156 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE,
157 &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) 157 &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 )
158 { 158 {
159 throw ExceptionBase("Error attempting to scan open connections."); 159 throw ExceptionBase("Error attempting to scan open connections.");
160 } 160 }
161 161
162 while( !qMsg.isEmpty() ) 162 while( !qMsg.isEmpty() )
163 { 163 {
164 imProto.lock(); 164 imProto.lock();
165 Bu::String *pMsg = qMsg.dequeue(); 165 Bu::String *pMsg = qMsg.dequeue();
166 pClient->onMessage( *pMsg ); 166 pClient->onMessage( *pMsg );
167 delete pMsg; 167 delete pMsg;
168 pClient->processOutput(); 168 pClient->processOutput();
169 imProto.unlock(); 169 imProto.unlock();
170 } 170 }
171 171
172 if( FD_ISSET( iSocket, &fdRead ) ) 172 if( FD_ISSET( iSocket, &fdRead ) )
173 { 173 {
174 imProto.lock(); 174 imProto.lock();
175 pClient->processInput(); 175 pClient->processInput();
176 imProto.unlock(); 176 imProto.unlock();
177 if( !pClient->isOpen() ) 177 if( !pClient->isOpen() )
178 { 178 {
179 imProto.lock(); 179 imProto.lock();
180 rSrv.onClosedConnection( pClient ); 180 rSrv.onClosedConnection( pClient );
181 imProto.unlock(); 181 imProto.unlock();
182 182
183 rSrv.clientCleanup( iSocket ); 183 rSrv.clientCleanup( iSocket );
184 184
185 return; 185 return;
186 } 186 }
187 } 187 }
188 188
189 if( FD_ISSET( iSocket, &fdWrite ) ) 189 if( FD_ISSET( iSocket, &fdWrite ) )
190 { 190 {
191 imProto.lock(); 191 imProto.lock();
192 pClient->processOutput(); 192 pClient->processOutput();
193 imProto.unlock(); 193 imProto.unlock();
194 } 194 }
195 } 195 }
196} 196}
197 197
198Bu::ItoServer::SrvClientLink::SrvClientLink( ItoClient *pClient ) : 198Bu::ItoServer::SrvClientLink::SrvClientLink( ItoClient *pClient ) :
199 pClient( pClient ) 199 pClient( pClient )
200{ 200{
201} 201}
202 202
@@ -206,22 +206,22 @@ Bu::ItoServer::SrvClientLink::~SrvClientLink()
206 206
207void Bu::ItoServer::SrvClientLink::sendMessage( const Bu::String &sMsg ) 207void Bu::ItoServer::SrvClientLink::sendMessage( const Bu::String &sMsg )
208{ 208{
209 if( !pClient->imProto.trylock() ) 209 if( !pClient->imProto.trylock() )
210 { 210 {
211 pClient->pClient->onMessage( sMsg ); 211 pClient->pClient->onMessage( sMsg );
212 pClient->pClient->processOutput(); 212 pClient->pClient->processOutput();
213 pClient->imProto.unlock(); 213 pClient->imProto.unlock();
214 } 214 }
215 else 215 else
216 { 216 {
217 Bu::String *pMsg = new Bu::String( sMsg ); 217 Bu::String *pMsg = new Bu::String( sMsg );
218 pClient->qMsg.enqueue( pMsg ); 218 pClient->qMsg.enqueue( pMsg );
219 } 219 }
220} 220}
221 221
222Bu::ItoServer::SrvClientLinkFactory::SrvClientLinkFactory( 222Bu::ItoServer::SrvClientLinkFactory::SrvClientLinkFactory(
223 Bu::ItoServer &rSrv ) : 223 Bu::ItoServer &rSrv ) :
224 rSrv( rSrv ) 224 rSrv( rSrv )
225{ 225{
226} 226}
227 227
@@ -230,12 +230,12 @@ Bu::ItoServer::SrvClientLinkFactory::~SrvClientLinkFactory()
230} 230}
231 231
232Bu::ClientLink *Bu::ItoServer::SrvClientLinkFactory::createLink( 232Bu::ClientLink *Bu::ItoServer::SrvClientLinkFactory::createLink(
233 Bu::Client *pClient ) 233 Bu::Client *pClient )
234{ 234{
235 rSrv.imClients.lock(); 235 rSrv.imClients.lock();
236 ItoClient *pCli = rSrv.hClients.get( *pClient->getSocket() ); 236 ItoClient *pCli = rSrv.hClients.get( *pClient->getSocket() );
237 rSrv.imClients.unlock(); 237 rSrv.imClients.unlock();
238 238
239 return new SrvClientLink( pCli ); 239 return new SrvClientLink( pCli );
240} 240}
241 241
diff --git a/src/unstable/itoserver.h b/src/unstable/itoserver.h
index 6a0df56..34f0fb1 100644
--- a/src/unstable/itoserver.h
+++ b/src/unstable/itoserver.h
@@ -11,7 +11,7 @@
11#include <stdint.h> 11#include <stdint.h>
12 12
13#ifndef WIN32 13#ifndef WIN32
14 #include <sys/select.h> 14 #include <sys/select.h>
15#endif 15#endif
16 16
17#include "bu/string.h" 17#include "bu/string.h"
@@ -26,122 +26,122 @@
26 26
27namespace Bu 27namespace Bu
28{ 28{
29 class TcpServerSocket; 29 class TcpServerSocket;
30 class TcpSocket; 30 class TcpSocket;
31 class Client; 31 class Client;
32 32
33 /** 33 /**
34 * Core of a network server. This class is distinct from a ServerSocket in 34 * Core of a network server. This class is distinct from a ServerSocket in
35 * that a ServerSocket is one listening socket, nothing more. Socket will 35 * that a ServerSocket is one listening socket, nothing more. Socket will
36 * manage a pool of both ServerSockets and connected Sockets along with 36 * manage a pool of both ServerSockets and connected Sockets along with
37 * their protocols and buffers. 37 * their protocols and buffers.
38 * 38 *
39 * To start serving on a new port, use the addPort functions. Each call to 39 * To start serving on a new port, use the addPort functions. Each call to
40 * addPort creates a new ServerSocket, starts it listening, and adds it to 40 * addPort creates a new ServerSocket, starts it listening, and adds it to
41 * the server pool. 41 * the server pool.
42 * 42 *
43 * All of the real work is done by scan, which will wait for up 43 * All of the real work is done by scan, which will wait for up
44 * to the timeout set by setTimeout before returning if there is no data 44 * to the timeout set by setTimeout before returning if there is no data
45 * pending. scan should probably be called in some sort of tight 45 * pending. scan should probably be called in some sort of tight
46 * loop, possibly in it's own thread, or in the main control loop. 46 * loop, possibly in it's own thread, or in the main control loop.
47 * 47 *
48 * In order to use a Server you must subclass it and implement the pure 48 * In order to use a Server you must subclass it and implement the pure
49 * virtual functions. These allow you to receive notification of events 49 * virtual functions. These allow you to receive notification of events
50 * happening within the server itself, and actually makes it useful. 50 * happening within the server itself, and actually makes it useful.
51 *@ingroup Threading Serving 51 *@ingroup Threading Serving
52 */ 52 */
53 class ItoServer : public Thread 53 class ItoServer : public Thread
54 { 54 {
55 friend class ItoClient; 55 friend class ItoClient;
56 friend class SrvClientLinkFactory; 56 friend class SrvClientLinkFactory;
57 public: 57 public:
58 ItoServer(); 58 ItoServer();
59 virtual ~ItoServer(); 59 virtual ~ItoServer();
60 60
61#ifdef WIN32 61#ifdef WIN32
62 typedef unsigned int socket_t; 62 typedef unsigned int socket_t;
63#else 63#else
64 typedef int socket_t; 64 typedef int socket_t;
65#endif 65#endif
66 66
67 void addPort( int nPort, int nPoolSize=40 ); 67 void addPort( int nPort, int nPoolSize=40 );
68 void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); 68 void addPort( const String &sAddr, int nPort, int nPoolSize=40 );
69 69
70 //void scan(); 70 //void scan();
71 void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); 71 void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 );
72 72
73 void addClient( socket_t nSocket, int nPort ); 73 void addClient( socket_t nSocket, int nPort );
74 74
75 virtual void onNewConnection( Client *pClient, int nPort )=0; 75 virtual void onNewConnection( Client *pClient, int nPort )=0;
76 virtual void onClosedConnection( Client *pClient )=0; 76 virtual void onClosedConnection( Client *pClient )=0;
77 77
78 protected: 78 protected:
79 virtual void run(); 79 virtual void run();
80 80
81 private: 81 private:
82 class SrvClientLink; 82 class SrvClientLink;
83 class ItoClient : public Thread 83 class ItoClient : public Thread
84 { 84 {
85 friend class Bu::ItoServer::SrvClientLink; 85 friend class Bu::ItoServer::SrvClientLink;
86 public: 86 public:
87 ItoClient( ItoServer &rSrv, socket_t nSocket, int nPort, 87 ItoClient( ItoServer &rSrv, socket_t nSocket, int nPort,
88 int nTimeoutSec, int nTimeoutUSec ); 88 int nTimeoutSec, int nTimeoutUSec );
89 virtual ~ItoClient(); 89 virtual ~ItoClient();
90 90
91 typedef SynchroQueue<Bu::String *> StringQueue; 91 typedef SynchroQueue<Bu::String *> StringQueue;
92 StringQueue qMsg; 92 StringQueue qMsg;
93 93
94 protected: 94 protected:
95 virtual void run(); 95 virtual void run();
96 96
97 private: 97 private:
98 ItoServer &rSrv; 98 ItoServer &rSrv;
99 Client *pClient; 99 Client *pClient;
100 fd_set fdActive; 100 fd_set fdActive;
101 socket_t iSocket; 101 socket_t iSocket;
102 int iPort; 102 int iPort;
103 int nTimeoutSec; 103 int nTimeoutSec;
104 int nTimeoutUSec; 104 int nTimeoutUSec;
105 Mutex imProto; 105 Mutex imProto;
106 }; 106 };
107 107
108 class SrvClientLink : public Bu::ClientLink 108 class SrvClientLink : public Bu::ClientLink
109 { 109 {
110 public: 110 public:
111 SrvClientLink( ItoClient *pClient ); 111 SrvClientLink( ItoClient *pClient );
112 virtual ~SrvClientLink(); 112 virtual ~SrvClientLink();
113 113
114 virtual void sendMessage( const Bu::String &sMsg ); 114 virtual void sendMessage( const Bu::String &sMsg );
115 115
116 private: 116 private:
117 ItoClient *pClient; 117 ItoClient *pClient;
118 }; 118 };
119 119
120 class SrvClientLinkFactory : public Bu::ClientLinkFactory 120 class SrvClientLinkFactory : public Bu::ClientLinkFactory
121 { 121 {
122 public: 122 public:
123 SrvClientLinkFactory( ItoServer &rSrv ); 123 SrvClientLinkFactory( ItoServer &rSrv );
124 virtual ~SrvClientLinkFactory(); 124 virtual ~SrvClientLinkFactory();
125 125
126 virtual Bu::ClientLink *createLink( Bu::Client *pClient ); 126 virtual Bu::ClientLink *createLink( Bu::Client *pClient );
127 127
128 private: 128 private:
129 ItoServer &rSrv; 129 ItoServer &rSrv;
130 }; 130 };
131 131
132 int nTimeoutSec; 132 int nTimeoutSec;
133 int nTimeoutUSec; 133 int nTimeoutUSec;
134 fd_set fdActive; 134 fd_set fdActive;
135 typedef Hash<socket_t,TcpServerSocket *> ServerHash; 135 typedef Hash<socket_t,TcpServerSocket *> ServerHash;
136 ServerHash hServers; 136 ServerHash hServers;
137 typedef Hash<socket_t,ItoClient *> ClientHash; 137 typedef Hash<socket_t,ItoClient *> ClientHash;
138 typedef SynchroQueue<ItoClient *> ClientQueue; 138 typedef SynchroQueue<ItoClient *> ClientQueue;
139 ClientHash hClients; 139 ClientHash hClients;
140 ClientQueue qClientCleanup; 140 ClientQueue qClientCleanup;
141 Mutex imClients; 141 Mutex imClients;
142 142
143 void clientCleanup( socket_t iSocket ); 143 void clientCleanup( socket_t iSocket );
144 }; 144 };
145} 145}
146 146
147#endif 147#endif
diff --git a/src/unstable/minimacro.cpp b/src/unstable/minimacro.cpp
index ff12267..72178ad 100644
--- a/src/unstable/minimacro.cpp
+++ b/src/unstable/minimacro.cpp
@@ -9,16 +9,16 @@
9 9
10Bu::MiniMacro::MiniMacro() 10Bu::MiniMacro::MiniMacro()
11{ 11{
12 hFuncs.insert("toupper", new FuncToUpper() ); 12 hFuncs.insert("toupper", new FuncToUpper() );
13 hFuncs.insert("tolower", new FuncToLower() ); 13 hFuncs.insert("tolower", new FuncToLower() );
14} 14}
15 15
16Bu::MiniMacro::MiniMacro( const StrHash &sVarSrc ) 16Bu::MiniMacro::MiniMacro( const StrHash &sVarSrc )
17{ 17{
18 for( StrHash::const_iterator i = sVarSrc.begin(); i != sVarSrc.end(); i++ ) 18 for( StrHash::const_iterator i = sVarSrc.begin(); i != sVarSrc.end(); i++ )
19 { 19 {
20 addVar( i.getKey(), i.getValue() ); 20 addVar( i.getKey(), i.getValue() );
21 } 21 }
22} 22}
23 23
24Bu::MiniMacro::~MiniMacro() 24Bu::MiniMacro::~MiniMacro()
@@ -27,161 +27,161 @@ Bu::MiniMacro::~MiniMacro()
27 27
28Bu::String Bu::MiniMacro::parse( const Bu::String &sIn ) 28Bu::String Bu::MiniMacro::parse( const Bu::String &sIn )
29{ 29{
30 bContinue = true; 30 bContinue = true;
31 Bu::String sOut; 31 Bu::String sOut;
32 for( sCur = sIn.getStr(); *sCur && bContinue; sCur++ ) 32 for( sCur = sIn.getStr(); *sCur && bContinue; sCur++ )
33 { 33 {
34 if( *sCur == '{' ) 34 if( *sCur == '{' )
35 { 35 {
36 switch( sCur[1] ) 36 switch( sCur[1] )
37 { 37 {
38 case '=': 38 case '=':
39 sCur += 2; 39 sCur += 2;
40 sOut += parseRepl(); 40 sOut += parseRepl();
41 break; 41 break;
42 42
43 case '?': 43 case '?':
44 sCur += 2; 44 sCur += 2;
45 sOut += parseCond(); 45 sOut += parseCond();
46 break; 46 break;
47 47
48 case ':': 48 case ':':
49 sCur += 2; 49 sCur += 2;
50 sOut += parseCmd(); 50 sOut += parseCmd();
51 break; 51 break;
52 52
53 default: 53 default:
54 sOut += *sCur; 54 sOut += *sCur;
55 continue; 55 continue;
56 } 56 }
57 } 57 }
58 else 58 else
59 { 59 {
60 sOut += *sCur; 60 sOut += *sCur;
61 } 61 }
62 } 62 }
63 63
64 iLastPos = (ptrdiff_t)sCur - (ptrdiff_t)sIn.getStr(); 64 iLastPos = (ptrdiff_t)sCur - (ptrdiff_t)sIn.getStr();
65 65
66 return sOut; 66 return sOut;
67} 67}
68 68
69Bu::String Bu::MiniMacro::parseRepl() 69Bu::String Bu::MiniMacro::parseRepl()
70{ 70{
71 Bu::String sOut; 71 Bu::String sOut;
72 bool bIsFirst = true; 72 bool bIsFirst = true;
73 for( const char *sNext = sCur;;) 73 for( const char *sNext = sCur;;)
74 { 74 {
75 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { } 75 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { }
76 if( *sNext == '\0' ) 76 if( *sNext == '\0' )
77 break; 77 break;
78 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur ); 78 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur );
79 if( bIsFirst ) 79 if( bIsFirst )
80 { 80 {
81 sOut = hVars[sName]; 81 sOut = hVars[sName];
82 bIsFirst = false; 82 bIsFirst = false;
83 //printf("Variable: \"%s\"\n", sName.getStr() ); 83 //printf("Variable: \"%s\"\n", sName.getStr() );
84 } 84 }
85 else 85 else
86 { 86 {
87 sOut = callFunc( sOut, sName ); 87 sOut = callFunc( sOut, sName );
88 //printf("Filter: \"%s\"\n", sName.getStr() ); 88 //printf("Filter: \"%s\"\n", sName.getStr() );
89 } 89 }
90 if( *sNext == '}' ) 90 if( *sNext == '}' )
91 { 91 {
92 sCur = sNext; 92 sCur = sNext;
93 break; 93 break;
94 } 94 }
95 else if( *sNext == ':' ) 95 else if( *sNext == ':' )
96 { 96 {
97 } 97 }
98 sNext++; 98 sNext++;
99 sCur = sNext; 99 sCur = sNext;
100 } 100 }
101 return sOut; 101 return sOut;
102} 102}
103 103
104Bu::String Bu::MiniMacro::parseCond() 104Bu::String Bu::MiniMacro::parseCond()
105{ 105{
106 Bu::String sOut; 106 Bu::String sOut;
107 //printf("%20s\n", sCur ); 107 //printf("%20s\n", sCur );
108 return sOut; 108 return sOut;
109} 109}
110 110
111Bu::String Bu::MiniMacro::parseCmd() 111Bu::String Bu::MiniMacro::parseCmd()
112{ 112{
113 Bu::String sOut; 113 Bu::String sOut;
114 const char *sNext = sCur; 114 const char *sNext = sCur;
115 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { } 115 for(; *sNext != ':' && *sNext != '}' && *sNext != '\0'; sNext++ ) { }
116 if( *sNext != '\0' ) 116 if( *sNext != '\0' )
117 { 117 {
118 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur ); 118 Bu::String sName( sCur, (ptrdiff_t)sNext-(ptrdiff_t)sCur );
119 if( sName == "end" ) 119 if( sName == "end" )
120 { 120 {
121 sCur = sNext; 121 sCur = sNext;
122 bContinue = false; 122 bContinue = false;
123 return sOut; 123 return sOut;
124 } 124 }
125 else 125 else
126 { 126 {
127 throw Bu::ExceptionBase("Unknown command '%s'.", 127 throw Bu::ExceptionBase("Unknown command '%s'.",
128 sName.getStr() 128 sName.getStr()
129 ); 129 );
130 } 130 }
131 } 131 }
132 else 132 else
133 { 133 {
134 //printf("Uh...?\n"); 134 //printf("Uh...?\n");
135 } 135 }
136 136
137 //printf("%20s\n", sCur ); 137 //printf("%20s\n", sCur );
138 return sOut; 138 return sOut;
139} 139}
140 140
141Bu::String Bu::MiniMacro::callFunc( 141Bu::String Bu::MiniMacro::callFunc(
142 const Bu::String &sIn, const Bu::String &sFunc ) 142 const Bu::String &sIn, const Bu::String &sFunc )
143{ 143{
144 int i = sFunc.findIdx('('); 144 int i = sFunc.findIdx('(');
145 if( i < 0 ) 145 if( i < 0 )
146 throw Bu::ExceptionBase("That doesn't look like a function call"); 146 throw Bu::ExceptionBase("That doesn't look like a function call");
147 Bu::String sName( sFunc.getStr(), i ); 147 Bu::String sName( sFunc.getStr(), i );
148 StrList lsParams; 148 StrList lsParams;
149 for( const char *s = sFunc.getStr()+i+1; *s && *s != ')'; s++ ) 149 for( const char *s = sFunc.getStr()+i+1; *s && *s != ')'; s++ )
150 { 150 {
151 for(; *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'; s++ ) { } 151 for(; *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'; s++ ) { }
152 const char *sNext; 152 const char *sNext;
153 for( sNext = s; *sNext && *sNext != ')' && *sNext != ','; sNext++ ) { } 153 for( sNext = s; *sNext && *sNext != ')' && *sNext != ','; sNext++ ) { }
154 Bu::String p( s, (ptrdiff_t)sNext-(ptrdiff_t)s ); 154 Bu::String p( s, (ptrdiff_t)sNext-(ptrdiff_t)s );
155 lsParams.append( p ); 155 lsParams.append( p );
156 sNext++; 156 sNext++;
157 s = sNext; 157 s = sNext;
158 } 158 }
159 return hFuncs.get( sName )->call( sIn, lsParams ); 159 return hFuncs.get( sName )->call( sIn, lsParams );
160} 160}
161 161
162void Bu::MiniMacro::addVar( 162void Bu::MiniMacro::addVar(
163 const Bu::String &sName, const Bu::String &sValue ) 163 const Bu::String &sName, const Bu::String &sValue )
164{ 164{
165 hVars.insert( sName, sValue ); 165 hVars.insert( sName, sValue );
166} 166}
167 167
168bool Bu::MiniMacro::hasVar( const Bu::String &sName ) 168bool Bu::MiniMacro::hasVar( const Bu::String &sName )
169{ 169{
170 return hVars.has( sName ); 170 return hVars.has( sName );
171} 171}
172 172
173const Bu::String &Bu::MiniMacro::getVar( const Bu::String &sName ) 173const Bu::String &Bu::MiniMacro::getVar( const Bu::String &sName )
174{ 174{
175 return hVars.get( sName ); 175 return hVars.get( sName );
176} 176}
177 177
178const Bu::StrHash &Bu::MiniMacro::getVars() 178const Bu::StrHash &Bu::MiniMacro::getVars()
179{ 179{
180 return hVars; 180 return hVars;
181} 181}
182 182
183int Bu::MiniMacro::getPosition() 183int Bu::MiniMacro::getPosition()
184{ 184{
185 return iLastPos; 185 return iLastPos;
186} 186}
187 187
diff --git a/src/unstable/minimacro.h b/src/unstable/minimacro.h
index dc38891..1c33ea4 100644
--- a/src/unstable/minimacro.h
+++ b/src/unstable/minimacro.h
@@ -13,118 +13,118 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 typedef Bu::Hash<Bu::String, Bu::String> StrHash; 16 typedef Bu::Hash<Bu::String, Bu::String> StrHash;
17 /** 17 /**
18 * A processor for Libbu++ brand Mini Macros. These are really simple, but 18 * A processor for Libbu++ brand Mini Macros. These are really simple, but
19 * still fairly flexible. It's mainly text replacement, but with a few 19 * still fairly flexible. It's mainly text replacement, but with a few
20 * extras like filter functions and conditional text segments. So far we 20 * extras like filter functions and conditional text segments. So far we
21 * don't support loops or anything, I'm not sure we ever will. 21 * don't support loops or anything, I'm not sure we ever will.
22 * 22 *
23 * Anatomy of a mini macro: 23 * Anatomy of a mini macro:
24 * - Every macro begins with a two character code, the first character is 24 * - Every macro begins with a two character code, the first character is
25 * always '{', the second character determines the operation to perform. 25 * always '{', the second character determines the operation to perform.
26 * - If the '{' is followed by a character that is not valid it is not 26 * - If the '{' is followed by a character that is not valid it is not
27 * considered for expansion and the characters are copied to the output. 27 * considered for expansion and the characters are copied to the output.
28 * - Every macro ends with a closing '}' 28 * - Every macro ends with a closing '}'
29 * - Macro types: 29 * - Macro types:
30 * - '=': variable replacement. The '=' is immediatley followed by the 30 * - '=': variable replacement. The '=' is immediatley followed by the
31 * name of the variable to replace, then any number of optional filter 31 * name of the variable to replace, then any number of optional filter
32 * segments. 32 * segments.
33 * - '?': conditional text. The '?' is immediately followed by the 33 * - '?': conditional text. The '?' is immediately followed by the
34 * variable to test. This works two ways, the variable can be alone, in 34 * variable to test. This works two ways, the variable can be alone, in
35 * which case it's existance is tested, or it can be followed by a "=" 35 * which case it's existance is tested, or it can be followed by a "="
36 * and a string to compare to. This is then followed by a text segment 36 * and a string to compare to. This is then followed by a text segment
37 * that will be used if the test is true, and an optional text segment 37 * that will be used if the test is true, and an optional text segment
38 * to be used if the test is false. 38 * to be used if the test is false.
39 * - ':': command. The ':' is immediately followed by a command string, 39 * - ':': command. The ':' is immediately followed by a command string,
40 * of which there's only one right now, but that's ok. These are not 40 * of which there's only one right now, but that's ok. These are not
41 * put into the output stream, but instead mark something for the 41 * put into the output stream, but instead mark something for the
42 * parser. Currently supported: 42 * parser. Currently supported:
43 * - {:end}: end of parsing, stop here, also make note of how many input 43 * - {:end}: end of parsing, stop here, also make note of how many input
44 * characters were used. 44 * characters were used.
45 * - Segments: 45 * - Segments:
46 * - Each segment is seperated by a colon. 46 * - Each segment is seperated by a colon.
47 * - Filter segments give the name of the filter, followed by 47 * - Filter segments give the name of the filter, followed by
48 * parenthesies. Parameters may be provided within the parenthesies. 48 * parenthesies. Parameters may be provided within the parenthesies.
49 * - Text segments should always be quoted, but may contain any characters 49 * - Text segments should always be quoted, but may contain any characters
50 * within the quotes, backslash is used as per C/ANSI/ISO standard. 50 * within the quotes, backslash is used as per C/ANSI/ISO standard.
51 * You can also quote any text using [' '] instead of quotes, which 51 * You can also quote any text using [' '] instead of quotes, which
52 * allows for nested strings. The [' token is only recognised within 52 * allows for nested strings. The [' token is only recognised within
53 * a macro. 53 * a macro.
54 * 54 *
55 *@verbatim 55 *@verbatim
56 {=name:tolower()} 56 {=name:tolower()}
57 {=name:ccsplit("_"):toupper()} 57 {=name:ccsplit("_"):toupper()}
58 {?name:"name exists and is {=name}"} 58 {?name:"name exists and is {=name}"}
59 {?name:"{=name}":"no name!"} 59 {?name:"{=name}":"no name!"}
60 {?name="bob":"You're named bob!":"Who are you? I only know bob..."} 60 {?name="bob":"You're named bob!":"Who are you? I only know bob..."}
61 @endverbatim 61 @endverbatim
62 */ 62 */
63 class MiniMacro 63 class MiniMacro
64 { 64 {
65 public: 65 public:
66 MiniMacro(); 66 MiniMacro();
67 MiniMacro( const StrHash &sVarSrc ); 67 MiniMacro( const StrHash &sVarSrc );
68 virtual ~MiniMacro(); 68 virtual ~MiniMacro();
69 69
70 Bu::String parse( const Bu::String &sIn ); 70 Bu::String parse( const Bu::String &sIn );
71 void addVar( const Bu::String &sName, const Bu::String &sValue ); 71 void addVar( const Bu::String &sName, const Bu::String &sValue );
72 bool hasVar( const Bu::String &sName ); 72 bool hasVar( const Bu::String &sName );
73 const Bu::String &getVar( const Bu::String &sName ); 73 const Bu::String &getVar( const Bu::String &sName );
74 const StrHash &getVars(); 74 const StrHash &getVars();
75 int getPosition(); 75 int getPosition();
76 76
77 private: 77 private:
78 const char *sCur; 78 const char *sCur;
79 Bu::String parseRepl(); 79 Bu::String parseRepl();
80 Bu::String parseCond(); 80 Bu::String parseCond();
81 Bu::String parseCmd(); 81 Bu::String parseCmd();
82 Bu::String callFunc( 82 Bu::String callFunc(
83 const Bu::String &sIn, const Bu::String &sFunc ); 83 const Bu::String &sIn, const Bu::String &sFunc );
84 84
85 StrHash hVars; 85 StrHash hVars;
86 bool bContinue; 86 bool bContinue;
87 int iLastPos; 87 int iLastPos;
88 88
89 public: 89 public:
90 typedef Bu::List<Bu::String> StrList; 90 typedef Bu::List<Bu::String> StrList;
91 class Func 91 class Func
92 { 92 {
93 public: 93 public:
94 Func(){} 94 Func(){}
95 virtual ~Func(){} 95 virtual ~Func(){}
96 virtual Bu::String call( 96 virtual Bu::String call(
97 const Bu::String &sIn, StrList &lsParam )=0; 97 const Bu::String &sIn, StrList &lsParam )=0;
98 }; 98 };
99 99
100 class FuncToUpper : public Func 100 class FuncToUpper : public Func
101 { 101 {
102 public: 102 public:
103 FuncToUpper(){} 103 FuncToUpper(){}
104 virtual ~FuncToUpper(){} 104 virtual ~FuncToUpper(){}
105 virtual Bu::String call( 105 virtual Bu::String call(
106 const Bu::String &sIn, StrList & ) 106 const Bu::String &sIn, StrList & )
107 { 107 {
108 return sIn.toUpper(); 108 return sIn.toUpper();
109 } 109 }
110 }; 110 };
111 111
112 class FuncToLower : public Func 112 class FuncToLower : public Func
113 { 113 {
114 public: 114 public:
115 FuncToLower(){} 115 FuncToLower(){}
116 virtual ~FuncToLower(){} 116 virtual ~FuncToLower(){}
117 virtual Bu::String call( 117 virtual Bu::String call(
118 const Bu::String &sIn, StrList & ) 118 const Bu::String &sIn, StrList & )
119 { 119 {
120 return sIn.toLower(); 120 return sIn.toLower();
121 } 121 }
122 }; 122 };
123 123
124 private: 124 private:
125 typedef Bu::Hash<Bu::String,class Func *> FuncHash; 125 typedef Bu::Hash<Bu::String,class Func *> FuncHash;
126 FuncHash hFuncs; 126 FuncHash hFuncs;
127 }; 127 };
128}; 128};
129 129
130#endif 130#endif
diff --git a/src/unstable/myriadfs.cpp b/src/unstable/myriadfs.cpp
index 6ed176d..3680c3f 100644
--- a/src/unstable/myriadfs.cpp
+++ b/src/unstable/myriadfs.cpp
@@ -19,686 +19,686 @@ using Bu::Fmt;
19 19
20namespace Bu { subExceptionDef( MyriadFsException ) } 20namespace Bu { subExceptionDef( MyriadFsException ) }
21 21
22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39") 22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39")
23 23
24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : 24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) :
25 rStore( rStore ), 25 rStore( rStore ),
26 mStore( rStore, iBlockSize ), 26 mStore( rStore, iBlockSize ),
27 iUser( 0 ), 27 iUser( 0 ),
28 iGroup( 0 ) 28 iGroup( 0 )
29{ 29{
30#ifndef WIN32 30#ifndef WIN32
31 iUser = getuid(); 31 iUser = getuid();
32 iGroup = getgid(); 32 iGroup = getgid();
33#endif 33#endif
34 34
35 if( mStore.hasStream( 1 ) ) 35 if( mStore.hasStream( 1 ) )
36 { 36 {
37 // Check to see if this is a MyriadFs stream. 37 // Check to see if this is a MyriadFs stream.
38 Bu::MyriadStream ms = mStore.openStream( 1 ); 38 Bu::MyriadStream ms = mStore.openStream( 1 );
39 char sMagic[4]; 39 char sMagic[4];
40 if( ms.read( sMagic, 4 ) < 4 ) 40 if( ms.read( sMagic, 4 ) < 4 )
41 throw MyriadFsException("The provided stream does not appear to be " 41 throw MyriadFsException("The provided stream does not appear to be "
42 "a MyriadFs stream."); 42 "a MyriadFs stream.");
43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) ) 43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) )
44 throw MyriadFsException("The provided stream does not appear to be " 44 throw MyriadFsException("The provided stream does not appear to be "
45 "a MyriadFs stream."); 45 "a MyriadFs stream.");
46 46
47 int8_t iVer; 47 int8_t iVer;
48 ms.read( &iVer, 1 ); 48 ms.read( &iVer, 1 );
49 49
50 int32_t iNumNodes; 50 int32_t iNumNodes;
51 ms.read( &iNumNodes, 4 ); 51 ms.read( &iNumNodes, 4 );
52 for( int32_t j = 0; j < iNumNodes; j++ ) 52 for( int32_t j = 0; j < iNumNodes; j++ )
53 { 53 {
54 int32_t iNode; 54 int32_t iNode;
55 int32_t iPos; 55 int32_t iPos;
56 ms.read( &iNode, 4 ); 56 ms.read( &iNode, 4 );
57 ms.read( &iPos, 4 ); 57 ms.read( &iPos, 4 );
58 hNodeIndex.insert( iNode, iPos ); 58 hNodeIndex.insert( iNode, iPos );
59 } 59 }
60 } 60 }
61 else 61 else
62 { 62 {
63 // Create initial header stream 63 // Create initial header stream
64 { 64 {
65 mStore.createStream( 1 ); 65 mStore.createStream( 1 );
66 Bu::MyriadStream ms = mStore.openStream( 1 ); 66 Bu::MyriadStream ms = mStore.openStream( 1 );
67 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 67 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
68 int8_t iVer = 1; 68 int8_t iVer = 1;
69 int32_t iTmp = 1; 69 int32_t iTmp = 1;
70 ms.write( &iVer, 1 ); 70 ms.write( &iVer, 1 );
71 ms.write( &iTmp, 4 ); // iNumNodes 71 ms.write( &iTmp, 4 ); // iNumNodes
72 iTmp = 0; 72 iTmp = 0;
73 ms.write( &iTmp, 4 ); // iInode 73 ms.write( &iTmp, 4 ); // iInode
74 ms.write( &iTmp, 4 ); // iPosition 74 ms.write( &iTmp, 4 ); // iPosition
75 hNodeIndex.insert( 0, 0 ); 75 hNodeIndex.insert( 0, 0 );
76 } 76 }
77 77
78 // Create initial inode stream, with one root node. 78 // Create initial inode stream, with one root node.
79 { 79 {
80 mStore.createStream( 2 ); 80 mStore.createStream( 2 );
81 Bu::MyriadStream ms = mStore.openStream( 2 ); 81 Bu::MyriadStream ms = mStore.openStream( 2 );
82 RawStat rs; 82 RawStat rs;
83 rs.iNode = 0; 83 rs.iNode = 0;
84 rs.iUser = iUser; 84 rs.iUser = iUser;
85 rs.iGroup = iGroup; 85 rs.iGroup = iGroup;
86 rs.uPerms = 0755|typeDir; 86 rs.uPerms = 0755|typeDir;
87 rs.iLinks = 1; 87 rs.iLinks = 1;
88 rs.uStreamIndex = 3; 88 rs.uStreamIndex = 3;
89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL); 89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL);
90 ms.write( &rs, sizeof(RawStat) ); 90 ms.write( &rs, sizeof(RawStat) );
91 } 91 }
92 92
93 // Create inode 0's storage stream. 93 // Create inode 0's storage stream.
94 { 94 {
95 mStore.createStream( 3 ); 95 mStore.createStream( 3 );
96 Bu::MyriadStream ms = mStore.openStream( 3 ); 96 Bu::MyriadStream ms = mStore.openStream( 3 );
97 int32_t iTmp32 = 0; 97 int32_t iTmp32 = 0;
98 ms.write( &iTmp32, 4 ); // iChildCount 98 ms.write( &iTmp32, 4 ); // iChildCount
99 } 99 }
100 } 100 }
101} 101}
102 102
103Bu::MyriadFs::~MyriadFs() 103Bu::MyriadFs::~MyriadFs()
104{ 104{
105 writeHeader(); 105 writeHeader();
106} 106}
107 107
108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) 108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf )
109{ 109{
110 int32_t iParent; 110 int32_t iParent;
111 int32_t iNode = lookupInode( sPath, iParent ); 111 int32_t iNode = lookupInode( sPath, iParent );
112 Bu::MyriadStream is = mStore.openStream( 2 ); 112 Bu::MyriadStream is = mStore.openStream( 2 );
113 stat( iNode, rBuf, is ); 113 stat( iNode, rBuf, is );
114} 114}
115 115
116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/, 116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/,
117 uint16_t uPerms ) 117 uint16_t uPerms )
118{ 118{
119 int32_t iParent = -1; 119 int32_t iParent = -1;
120 int32_t iNode; 120 int32_t iNode;
121 try 121 try
122 { 122 {
123 iNode = lookupInode( sPath, iParent ); 123 iNode = lookupInode( sPath, iParent );
124 sio << "File found." << sio.nl; 124 sio << "File found." << sio.nl;
125 // The file was found 125 // The file was found
126 return openByInode( iNode ); 126 return openByInode( iNode );
127 } 127 }
128 catch( Bu::MyriadFsException &e ) 128 catch( Bu::MyriadFsException &e )
129 { 129 {
130 if( iParent < 0 ) 130 if( iParent < 0 )
131 throw; 131 throw;
132 132
133 // This means that an intermediate path component couldn't be found 133 // This means that an intermediate path component couldn't be found
134 if( e.getErrorCode() == 1 ) 134 if( e.getErrorCode() == 1 )
135 throw; 135 throw;
136 136
137 // The file wasn't found, but the path leading up to it was. 137 // The file wasn't found, but the path leading up to it was.
138 // first, figure out the final path element... 138 // first, figure out the final path element...
139 Bu::String sName = filePart( sPath ); 139 Bu::String sName = filePart( sPath );
140 sio << "End filename: " << sName << sio.nl; 140 sio << "End filename: " << sName << sio.nl;
141 sio << "Parent inode: " << iParent << sio.nl; 141 sio << "Parent inode: " << iParent << sio.nl;
142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 ); 142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 );
143 sio << "New iNode: " << iNode << sio.nl; 143 sio << "New iNode: " << iNode << sio.nl;
144 return openByInode( iNode ); 144 return openByInode( iNode );
145 } 145 }
146} 146}
147 147
148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms ) 148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms )
149{ 149{
150 create( sPath, iPerms, 0 ); 150 create( sPath, iPerms, 0 );
151} 151}
152 152
153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
154 uint16_t iDevHi, uint16_t iDevLo ) 154 uint16_t iDevHi, uint16_t iDevLo )
155{ 155{
156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo ); 156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo );
157} 157}
158 158
159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
160 uint32_t uSpecial ) 160 uint32_t uSpecial )
161{ 161{
162 int32_t iParent = -1; 162 int32_t iParent = -1;
163 int32_t iNode; 163 int32_t iNode;
164 try 164 try
165 { 165 {
166 iNode = lookupInode( sPath, iParent ); 166 iNode = lookupInode( sPath, iParent );
167 sio << "File found." << sio.nl; 167 sio << "File found." << sio.nl;
168 // The file was found 168 // The file was found
169 throw Bu::MyriadFsException("Path already exists."); 169 throw Bu::MyriadFsException("Path already exists.");
170 } 170 }
171 catch( Bu::MyriadFsException &e ) 171 catch( Bu::MyriadFsException &e )
172 { 172 {
173 if( iParent < 0 ) 173 if( iParent < 0 )
174 throw; 174 throw;
175 175
176 // This means that an intermediate path component couldn't be found 176 // This means that an intermediate path component couldn't be found
177 if( e.getErrorCode() == 1 ) 177 if( e.getErrorCode() == 1 )
178 throw; 178 throw;
179 179
180 // The file wasn't found, but the path leading up to it was. 180 // The file wasn't found, but the path leading up to it was.
181 // first, figure out the final path element... 181 // first, figure out the final path element...
182 Bu::String sName = filePart( sPath ); 182 Bu::String sName = filePart( sPath );
183 sio << "End filename: " << sName << sio.nl; 183 sio << "End filename: " << sName << sio.nl;
184 sio << "Parent inode: " << iParent << sio.nl; 184 sio << "Parent inode: " << iParent << sio.nl;
185 iNode = create( iParent, sName, iPerms, uSpecial ); 185 iNode = create( iParent, sName, iPerms, uSpecial );
186 sio << "New iNode: " << iNode << sio.nl; 186 sio << "New iNode: " << iNode << sio.nl;
187 } 187 }
188} 188}
189 189
190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) 190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms )
191{ 191{
192 create( sPath, (iPerms&permMask)|typeDir, 0 ); 192 create( sPath, (iPerms&permMask)|typeDir, 0 );
193} 193}
194 194
195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget, 195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget,
196 const Bu::String &sPath ) 196 const Bu::String &sPath )
197{ 197{
198 int32_t iParent = -1; 198 int32_t iParent = -1;
199 int32_t iNode; 199 int32_t iNode;
200 try 200 try
201 { 201 {
202 iNode = lookupInode( sPath, iParent ); 202 iNode = lookupInode( sPath, iParent );
203 throw Bu::MyriadFsException("Path already exists."); 203 throw Bu::MyriadFsException("Path already exists.");
204 } 204 }
205 catch( Bu::MyriadFsException &e ) 205 catch( Bu::MyriadFsException &e )
206 { 206 {
207 if( iParent < 0 ) 207 if( iParent < 0 )
208 throw; 208 throw;
209 209
210 // This means that an intermediate path component couldn't be found 210 // This means that an intermediate path component couldn't be found
211 if( e.getErrorCode() == 1 ) 211 if( e.getErrorCode() == 1 )
212 throw; 212 throw;
213 213
214 // The file wasn't found, but the path leading up to it was. 214 // The file wasn't found, but the path leading up to it was.
215 // first, figure out the final path element... 215 // first, figure out the final path element...
216 Bu::String sName = filePart( sPath ); 216 Bu::String sName = filePart( sPath );
217 sio << "End filename: " << sName << sio.nl; 217 sio << "End filename: " << sName << sio.nl;
218 sio << "Parent inode: " << iParent << sio.nl; 218 sio << "Parent inode: " << iParent << sio.nl;
219 iNode = create( iParent, sName, 0777|typeSymLink, 0 ); 219 iNode = create( iParent, sName, 0777|typeSymLink, 0 );
220 sio << "New iNode: " << iNode << sio.nl; 220 sio << "New iNode: " << iNode << sio.nl;
221 MyriadStream ms = openByInode( iNode ); 221 MyriadStream ms = openByInode( iNode );
222 ms.write( sTarget ); 222 ms.write( sTarget );
223 } 223 }
224} 224}
225 225
226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget, 226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget,
227 const Bu::String &sPath ) 227 const Bu::String &sPath )
228{ 228{
229 int32_t iParent = -1; 229 int32_t iParent = -1;
230 int32_t iNode; 230 int32_t iNode;
231 231
232 iNode = lookupInode( sTarget, iParent ); 232 iNode = lookupInode( sTarget, iParent );
233 233
234 try 234 try
235 { 235 {
236 lookupInode( sPath, iParent ); 236 lookupInode( sPath, iParent );
237 throw Bu::MyriadFsException("Path already exists."); 237 throw Bu::MyriadFsException("Path already exists.");
238 } 238 }
239 catch( Bu::MyriadFsException &e ) 239 catch( Bu::MyriadFsException &e )
240 { 240 {
241 if( iParent < 0 ) 241 if( iParent < 0 )
242 throw; 242 throw;
243 243
244 // This means that an intermediate path component couldn't be found 244 // This means that an intermediate path component couldn't be found
245 if( e.getErrorCode() == 1 ) 245 if( e.getErrorCode() == 1 )
246 throw; 246 throw;
247 247
248 // The file wasn't found, but the path leading up to it was. 248 // The file wasn't found, but the path leading up to it was.
249 // first, figure out the final path element... 249 // first, figure out the final path element...
250 Bu::String sName = filePart( sPath ); 250 Bu::String sName = filePart( sPath );
251 sio << "End filename: " << sName << sio.nl; 251 sio << "End filename: " << sName << sio.nl;
252 sio << "Parent inode: " << iParent << sio.nl; 252 sio << "Parent inode: " << iParent << sio.nl;
253 addToDir( iParent, iNode, sName ); 253 addToDir( iParent, iNode, sName );
254 MyriadStream is = mStore.openStream( 2 ); 254 MyriadStream is = mStore.openStream( 2 );
255 RawStat rs; 255 RawStat rs;
256 readInode( iNode, rs, is ); 256 readInode( iNode, rs, is );
257 rs.iLinks++; 257 rs.iLinks++;
258 writeInode( rs, is ); 258 writeInode( rs, is );
259 } 259 }
260} 260}
261 261
262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath ) 262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath )
263{ 263{
264 int32_t iParent = -1; 264 int32_t iParent = -1;
265 int32_t iNode; 265 int32_t iNode;
266 iNode = lookupInode( sPath, iParent ); 266 iNode = lookupInode( sPath, iParent );
267 MyriadStream ms = openByInode( iNode ); 267 MyriadStream ms = openByInode( iNode );
268 Bu::String sRet; 268 Bu::String sRet;
269 sRet.setSize( ms.getSize() ); 269 sRet.setSize( ms.getSize() );
270 ms.read( sRet.getStr(), ms.getSize() ); 270 ms.read( sRet.getStr(), ms.getSize() );
271 return sRet; 271 return sRet;
272} 272}
273 273
274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) 274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath )
275{ 275{
276 int32_t iParent = -1; 276 int32_t iParent = -1;
277 int32_t iNode = lookupInode( sPath, iParent ); 277 int32_t iNode = lookupInode( sPath, iParent );
278 return readDir( iNode ); 278 return readDir( iNode );
279} 279}
280 280
281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime, 281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime,
282 int64_t iMTime ) 282 int64_t iMTime )
283{ 283{
284 int32_t iParent = -1; 284 int32_t iParent = -1;
285 int32_t iNode; 285 int32_t iNode;
286 286
287 iNode = lookupInode( sPath, iParent ); 287 iNode = lookupInode( sPath, iParent );
288 288
289 setTimes( iNode, iATime, iMTime ); 289 setTimes( iNode, iATime, iMTime );
290} 290}
291 291
292void Bu::MyriadFs::unlink( const Bu::String &sPath ) 292void Bu::MyriadFs::unlink( const Bu::String &sPath )
293{ 293{
294 int32_t iParent = -1; 294 int32_t iParent = -1;
295// int32_t iNode; 295// int32_t iNode;
296 296
297 /*iNode =*/ lookupInode( sPath, iParent ); 297 /*iNode =*/ lookupInode( sPath, iParent );
298 298
299 Dir lDir = readDir( iParent ); 299 Dir lDir = readDir( iParent );
300 300
301 Bu::String sName = filePart( sPath ); 301 Bu::String sName = filePart( sPath );
302 302
303 for( Dir::iterator i = lDir.begin(); i; i++ ) 303 for( Dir::iterator i = lDir.begin(); i; i++ )
304 { 304 {
305 if( sName == (*i).sName ) 305 if( sName == (*i).sName )
306 { 306 {
307 RawStat rs; 307 RawStat rs;
308 readInode( (*i).iNode, rs ); 308 readInode( (*i).iNode, rs );
309 if( (rs.uPerms&typeMask) == typeDir ) 309 if( (rs.uPerms&typeMask) == typeDir )
310 { 310 {
311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex ); 311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex );
312 int32_t iCount; 312 int32_t iCount;
313 msDir.read( &iCount, 4 ); 313 msDir.read( &iCount, 4 );
314 if( iCount > 0 ) 314 if( iCount > 0 )
315 { 315 {
316 throw Bu::MyriadFsException("Directory not empty."); 316 throw Bu::MyriadFsException("Directory not empty.");
317 } 317 }
318 } 318 }
319 if( --rs.iLinks == 0 ) 319 if( --rs.iLinks == 0 )
320 { 320 {
321 destroyNode( (*i).iNode ); 321 destroyNode( (*i).iNode );
322 } 322 }
323 else 323 else
324 { 324 {
325 writeInode( rs ); 325 writeInode( rs );
326 } 326 }
327 lDir.erase( i ); 327 lDir.erase( i );
328 break; 328 break;
329 } 329 }
330 } 330 }
331 331
332 Bu::MyriadStream ms = openByInode( iParent ); 332 Bu::MyriadStream ms = openByInode( iParent );
333 int32_t iNumChildren = lDir.getSize(); 333 int32_t iNumChildren = lDir.getSize();
334 ms.write( &iNumChildren, 4 ); 334 ms.write( &iNumChildren, 4 );
335 for( Dir::iterator i = lDir.begin(); i; i++ ) 335 for( Dir::iterator i = lDir.begin(); i; i++ )
336 { 336 {
337 ms.write( &(*i).iNode, 4 ); 337 ms.write( &(*i).iNode, 4 );
338 uint8_t iSize = (*i).sName.getSize(); 338 uint8_t iSize = (*i).sName.getSize();
339 ms.write( &iSize, 1 ); 339 ms.write( &iSize, 1 );
340 ms.write( (*i).sName.getStr(), iSize ); 340 ms.write( (*i).sName.getStr(), iSize );
341 } 341 }
342 ms.setSize( ms.tell() ); 342 ms.setSize( ms.tell() );
343} 343}
344 344
345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize ) 345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize )
346{ 346{
347 int32_t iParent = -1; 347 int32_t iParent = -1;
348 int32_t iNode; 348 int32_t iNode;
349 iNode = lookupInode( sPath, iParent ); 349 iNode = lookupInode( sPath, iParent );
350 MyriadStream ms = openByInode( iNode ); 350 MyriadStream ms = openByInode( iNode );
351 ms.setSize( iSize ); 351 ms.setSize( iSize );
352} 352}
353 353
354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo ) 354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo )
355{ 355{
356 mkHardLink( sFrom, sTo ); 356 mkHardLink( sFrom, sTo );
357 unlink( sFrom ); 357 unlink( sFrom );
358} 358}
359 359
360dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) 360dev_t Bu::MyriadFs::devToSys( uint32_t uDev )
361{ 361{
362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); 362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF));
363} 363}
364 364
365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev ) 365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev )
366{ 366{
367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF); 367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF);
368} 368}
369 369
370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) 370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent )
371{ 371{
372 if( sPath == "/" ) 372 if( sPath == "/" )
373 { 373 {
374 return 0; 374 return 0;
375 } 375 }
376 if( sPath[0] == '/' ) 376 if( sPath[0] == '/' )
377 { 377 {
378 // Absolute lookup 378 // Absolute lookup
379 return lookupInode( sPath.begin()+1, 0, iParent ); 379 return lookupInode( sPath.begin()+1, 0, iParent );
380 } 380 }
381 else 381 else
382 { 382 {
383 // Relative lookup 383 // Relative lookup
384 throw Bu::ExceptionBase( 384 throw Bu::ExceptionBase(
385 "Relative lookups in MyriadFs are not working yet."); 385 "Relative lookups in MyriadFs are not working yet.");
386 } 386 }
387} 387}
388 388
389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, 389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart,
390 int32_t iNode, int32_t &iParent ) 390 int32_t iNode, int32_t &iParent )
391{ 391{
392 iParent = iNode; 392 iParent = iNode;
393 393
394 Bu::String::const_iterator iEnd = iStart.find('/'); 394 Bu::String::const_iterator iEnd = iStart.find('/');
395 Bu::String sTok( iStart, iEnd ); 395 Bu::String sTok( iStart, iEnd );
396 396
397// sio << "Direcotry component: " << sTok << sio.nl; 397// sio << "Direcotry component: " << sTok << sio.nl;
398 398
399 Dir lDir = readDir( iNode ); 399 Dir lDir = readDir( iNode );
400 400
401 for( Dir::iterator i = lDir.begin(); i; i++ ) 401 for( Dir::iterator i = lDir.begin(); i; i++ )
402 { 402 {
403 if( (*i).sName == sTok ) 403 if( (*i).sName == sTok )
404 { 404 {
405 // We found an item 405 // We found an item
406 if( !iEnd ) 406 if( !iEnd )
407 { 407 {
408 // It's the last one in the requested path, return it 408 // It's the last one in the requested path, return it
409 return (*i).iNode; 409 return (*i).iNode;
410 } 410 }
411 else 411 else
412 { 412 {
413 // Not the last one in our path, double check it's a dir 413 // Not the last one in our path, double check it's a dir
414 if( ((*i).uPerms&typeMask) == typeDir ) 414 if( ((*i).uPerms&typeMask) == typeDir )
415 { 415 {
416 return lookupInode( iEnd+1, (*i).iNode, iParent ); 416 return lookupInode( iEnd+1, (*i).iNode, iParent );
417 } 417 }
418 else 418 else
419 { 419 {
420 iParent = -1; 420 iParent = -1;
421 throw Bu::MyriadFsException( 421 throw Bu::MyriadFsException(
422 "Element '%s' in given path is not a directory.", 422 "Element '%s' in given path is not a directory.",
423 sTok.getStr() ); 423 sTok.getStr() );
424 } 424 }
425 } 425 }
426 } 426 }
427 } 427 }
428 428
429 if( iEnd ) 429 if( iEnd )
430 throw Bu::MyriadFsException( 1, "Path not found"); 430 throw Bu::MyriadFsException( 1, "Path not found");
431 else 431 else
432 throw Bu::MyriadFsException( 2, "Path not found"); 432 throw Bu::MyriadFsException( 2, "Path not found");
433} 433}
434 434
435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ) 435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs )
436{ 436{
437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) ); 437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) );
438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
439 throw Bu::MyriadFsException("Filesystem corruption detected."); 439 throw Bu::MyriadFsException("Filesystem corruption detected.");
440 if( rs.iNode != iNode ) 440 if( rs.iNode != iNode )
441 throw Bu::MyriadFsException("Filesystem corruption detected."); 441 throw Bu::MyriadFsException("Filesystem corruption detected.");
442} 442}
443 443
444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs ) 444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs )
445{ 445{
446 MyriadStream ms = mStore.openStream( 2 ); 446 MyriadStream ms = mStore.openStream( 2 );
447 readInode( iNode, rs, ms ); 447 readInode( iNode, rs, ms );
448} 448}
449 449
450void Bu::MyriadFs::writeInode( const RawStat &rs, 450void Bu::MyriadFs::writeInode( const RawStat &rs,
451 MyriadStream &rOs ) 451 MyriadStream &rOs )
452{ 452{
453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) ); 453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) );
454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) ); 454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) );
455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
456 throw Bu::MyriadFsException("Error writing inode to header stream."); 456 throw Bu::MyriadFsException("Error writing inode to header stream.");
457} 457}
458 458
459void Bu::MyriadFs::writeInode( const RawStat &rs ) 459void Bu::MyriadFs::writeInode( const RawStat &rs )
460{ 460{
461 MyriadStream ms = mStore.openStream( 2 ); 461 MyriadStream ms = mStore.openStream( 2 );
462 writeInode( rs, ms ); 462 writeInode( rs, ms );
463} 463}
464 464
465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) 465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode )
466{ 466{
467 Bu::MyriadStream ms = openByInode( iNode ); 467 Bu::MyriadStream ms = openByInode( iNode );
468 int32_t iNumChildren = 0; 468 int32_t iNumChildren = 0;
469 ms.read( &iNumChildren, 4 ); 469 ms.read( &iNumChildren, 4 );
470 470
471 Bu::MyriadStream is = mStore.openStream( 2 ); 471 Bu::MyriadStream is = mStore.openStream( 2 );
472 Dir lDir; 472 Dir lDir;
473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl; 473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl;
474 for( int32_t j = 0; j < iNumChildren; j++ ) 474 for( int32_t j = 0; j < iNumChildren; j++ )
475 { 475 {
476 int32_t iChildNode; 476 int32_t iChildNode;
477 ms.read( &iChildNode, 4 ); 477 ms.read( &iChildNode, 4 );
478 Stat s; 478 Stat s;
479 stat( iChildNode, s, is ); 479 stat( iChildNode, s, is );
480 uint8_t uLen; 480 uint8_t uLen;
481 ms.read( &uLen, 1 ); 481 ms.read( &uLen, 1 );
482 s.sName.setSize( uLen ); 482 s.sName.setSize( uLen );
483 ms.read( s.sName.getStr(), uLen ); 483 ms.read( s.sName.getStr(), uLen );
484 lDir.append( s ); 484 lDir.append( s );
485 485
486// sio << " " << s.sName << sio.nl; 486// sio << " " << s.sName << sio.nl;
487 } 487 }
488 488
489 return lDir; 489 return lDir;
490} 490}
491 491
492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) 492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode )
493{ 493{
494 RawStat rs; 494 RawStat rs;
495 readInode( iNode, rs ); 495 readInode( iNode, rs );
496 switch( (rs.uPerms&typeMask) ) 496 switch( (rs.uPerms&typeMask) )
497 { 497 {
498 case typeDir: 498 case typeDir:
499 case typeSymLink: 499 case typeSymLink:
500 case typeRegFile: 500 case typeRegFile:
501 return mStore.openStream( rs.uStreamIndex ); 501 return mStore.openStream( rs.uStreamIndex );
502 502
503 default: 503 default:
504 throw Bu::MyriadFsException( 504 throw Bu::MyriadFsException(
505 "inode incorrect type for low-level openByInode."); 505 "inode incorrect type for low-level openByInode.");
506 } 506 }
507} 507}
508 508
509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode, 509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode,
510 const Bu::String &sName ) 510 const Bu::String &sName )
511{ 511{
512 if( sName.getSize() > 255 ) 512 if( sName.getSize() > 255 )
513 { 513 {
514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes."); 514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes.");
515 } 515 }
516 Bu::MyriadStream ms = openByInode( iDir ); 516 Bu::MyriadStream ms = openByInode( iDir );
517 int32_t iNumChildren = 0; 517 int32_t iNumChildren = 0;
518 ms.read( &iNumChildren, 4 ); 518 ms.read( &iNumChildren, 4 );
519 iNumChildren++; 519 iNumChildren++;
520 ms.setPos( 0 ); 520 ms.setPos( 0 );
521 ms.write( &iNumChildren, 4 ); 521 ms.write( &iNumChildren, 4 );
522 ms.setPosEnd( 0 ); 522 ms.setPosEnd( 0 );
523 ms.write( &iNode, 4 ); 523 ms.write( &iNode, 4 );
524 uint8_t uLen = sName.getSize(); 524 uint8_t uLen = sName.getSize();
525 ms.write( &uLen, 1 ); 525 ms.write( &uLen, 1 );
526 ms.write( sName.getStr(), uLen ); 526 ms.write( sName.getStr(), uLen );
527} 527}
528 528
529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, 529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName,
530 uint16_t uPerms, uint32_t uSpecial ) 530 uint16_t uPerms, uint32_t uSpecial )
531{ 531{
532 int32_t iNode = allocInode( uPerms, uSpecial ); 532 int32_t iNode = allocInode( uPerms, uSpecial );
533 addToDir( iParent, iNode, sName ); 533 addToDir( iParent, iNode, sName );
534 return iNode; 534 return iNode;
535} 535}
536 536
537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) 537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
538{ 538{
539 int32_t iNode = 0; 539 int32_t iNode = 0;
540 for(; iNode < 0xfffffff; iNode++ ) 540 for(; iNode < 0xfffffff; iNode++ )
541 { 541 {
542 if( !hNodeIndex.has( iNode ) ) 542 if( !hNodeIndex.has( iNode ) )
543 { 543 {
544 hNodeIndex.insert( iNode, hNodeIndex.getSize() ); 544 hNodeIndex.insert( iNode, hNodeIndex.getSize() );
545 RawStat rs; 545 RawStat rs;
546 rs.iNode = iNode; 546 rs.iNode = iNode;
547 rs.iUser = iUser; 547 rs.iUser = iUser;
548 rs.iGroup = iGroup; 548 rs.iGroup = iGroup;
549 rs.uPerms = uPerms; 549 rs.uPerms = uPerms;
550 rs.iLinks = 1; 550 rs.iLinks = 1;
551 switch( (uPerms&typeMask) ) 551 switch( (uPerms&typeMask) )
552 { 552 {
553 case typeRegFile: 553 case typeRegFile:
554 case typeSymLink: 554 case typeSymLink:
555 rs.uStreamIndex = mStore.createStream(); 555 rs.uStreamIndex = mStore.createStream();
556 break; 556 break;
557 557
558 case typeDir: 558 case typeDir:
559 rs.uStreamIndex = mStore.createStream(); 559 rs.uStreamIndex = mStore.createStream();
560 sio << "Creating directory node, storage: " 560 sio << "Creating directory node, storage: "
561 << rs.uStreamIndex << sio.nl; 561 << rs.uStreamIndex << sio.nl;
562 { 562 {
563 Bu::MyriadStream msDir = mStore.openStream( 563 Bu::MyriadStream msDir = mStore.openStream(
564 rs.uStreamIndex 564 rs.uStreamIndex
565 ); 565 );
566 uint32_t uSize = 0; 566 uint32_t uSize = 0;
567 msDir.write( &uSize, 4 ); 567 msDir.write( &uSize, 4 );
568 } 568 }
569 break; 569 break;
570 570
571 case typeChrDev: 571 case typeChrDev:
572 case typeBlkDev: 572 case typeBlkDev:
573 rs.uStreamIndex = uSpecial; 573 rs.uStreamIndex = uSpecial;
574 break; 574 break;
575 575
576 default: 576 default:
577 rs.uStreamIndex = 0; 577 rs.uStreamIndex = 0;
578 break; 578 break;
579 } 579 }
580 rs.iATime = time(NULL); 580 rs.iATime = time(NULL);
581 rs.iMTime = time(NULL); 581 rs.iMTime = time(NULL);
582 rs.iCTime = time(NULL); 582 rs.iCTime = time(NULL);
583 writeInode( rs ); 583 writeInode( rs );
584 584
585 return iNode; 585 return iNode;
586 } 586 }
587 } 587 }
588 588
589 throw Bu::MyriadFsException( 589 throw Bu::MyriadFsException(
590 "No inode could be allocated. You've run out!"); 590 "No inode could be allocated. You've run out!");
591} 591}
592 592
593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) 593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs )
594{ 594{
595 RawStat rs; 595 RawStat rs;
596 readInode( iNode, rs, rIs ); 596 readInode( iNode, rs, rIs );
597 rBuf.iNode = iNode; 597 rBuf.iNode = iNode;
598 rBuf.iUser = rs.iUser; 598 rBuf.iUser = rs.iUser;
599 rBuf.iGroup = rs.iGroup; 599 rBuf.iGroup = rs.iGroup;
600 rBuf.uPerms = rs.uPerms; 600 rBuf.uPerms = rs.uPerms;
601 rBuf.iLinks = rs.iLinks; 601 rBuf.iLinks = rs.iLinks;
602 rBuf.iATime = rs.iATime; 602 rBuf.iATime = rs.iATime;
603 rBuf.iMTime = rs.iMTime; 603 rBuf.iMTime = rs.iMTime;
604 rBuf.iCTime = rs.iCTime; 604 rBuf.iCTime = rs.iCTime;
605 rBuf.uDev = 0; 605 rBuf.uDev = 0;
606 rBuf.iSize = 0; 606 rBuf.iSize = 0;
607 switch( (rBuf.uPerms&typeMask) ) 607 switch( (rBuf.uPerms&typeMask) )
608 { 608 {
609 case typeRegFile: 609 case typeRegFile:
610 case typeSymLink: 610 case typeSymLink:
611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex ); 611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex );
612 break; 612 break;
613 613
614 case typeChrDev: 614 case typeChrDev:
615 case typeBlkDev: 615 case typeBlkDev:
616 rBuf.uDev = rs.uStreamIndex; 616 rBuf.uDev = rs.uStreamIndex;
617 break; 617 break;
618 618
619 default: 619 default:
620 rBuf.iSize = 0; 620 rBuf.iSize = 0;
621 break; 621 break;
622 } 622 }
623} 623}
624 624
625void Bu::MyriadFs::writeHeader() 625void Bu::MyriadFs::writeHeader()
626{ 626{
627 Bu::MyriadStream ms = mStore.openStream( 1 ); 627 Bu::MyriadStream ms = mStore.openStream( 1 );
628 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 628 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
629 int8_t iVer = 1; 629 int8_t iVer = 1;
630 int32_t iNumNodes = hNodeIndex.getSize(); 630 int32_t iNumNodes = hNodeIndex.getSize();
631 ms.write( &iVer, 1 ); 631 ms.write( &iVer, 1 );
632 ms.write( &iNumNodes, 4 ); // iNumNodes 632 ms.write( &iNumNodes, 4 ); // iNumNodes
633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ ) 633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ )
634 { 634 {
635 int32_t iNode = i.getKey(); 635 int32_t iNode = i.getKey();
636 int32_t iPosition = i.getValue(); 636 int32_t iPosition = i.getValue();
637 ms.write( &iNode, 4 ); 637 ms.write( &iNode, 4 );
638 ms.write( &iPosition, 4 ); 638 ms.write( &iPosition, 4 );
639 } 639 }
640 640
641 // Truncate the stream afterwards so we don't use up too much space. 641 // Truncate the stream afterwards so we don't use up too much space.
642 ms.setSize( ms.tell() ); 642 ms.setSize( ms.tell() );
643} 643}
644 644
645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ) 645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime )
646{ 646{
647 RawStat rs; 647 RawStat rs;
648 Bu::MyriadStream is = mStore.openStream( 2 ); 648 Bu::MyriadStream is = mStore.openStream( 2 );
649 649
650 readInode( iNode, rs, is ); 650 readInode( iNode, rs, is );
651 rs.iATime = iATime; 651 rs.iATime = iATime;
652 rs.iMTime = iMTime; 652 rs.iMTime = iMTime;
653 writeInode( rs, is ); 653 writeInode( rs, is );
654} 654}
655 655
656void Bu::MyriadFs::destroyNode( int32_t iNode ) 656void Bu::MyriadFs::destroyNode( int32_t iNode )
657{ 657{
658 if( iNode == 0 ) 658 if( iNode == 0 )
659 throw Bu::MyriadFsException("You cannot destroy the root."); 659 throw Bu::MyriadFsException("You cannot destroy the root.");
660 660
661 Bu::MyriadStream is = mStore.openStream( 2 ); 661 Bu::MyriadStream is = mStore.openStream( 2 );
662 662
663 // This will be overwritten with the last node 663 // This will be overwritten with the last node
664 uint32_t iPosition = hNodeIndex.get( iNode ); 664 uint32_t iPosition = hNodeIndex.get( iNode );
665 RawStat rsOld; 665 RawStat rsOld;
666 readInode( iNode, rsOld, is ); 666 readInode( iNode, rsOld, is );
667 switch( (rsOld.uPerms&typeMask) ) 667 switch( (rsOld.uPerms&typeMask) )
668 { 668 {
669 case typeRegFile: 669 case typeRegFile:
670 case typeDir: 670 case typeDir:
671 case typeSymLink: 671 case typeSymLink:
672 mStore.deleteStream( rsOld.uStreamIndex ); 672 mStore.deleteStream( rsOld.uStreamIndex );
673 break; 673 break;
674 } 674 }
675 675
676 hNodeIndex.erase( iNode ); 676 hNodeIndex.erase( iNode );
677 677
678 // Read the last node, can't use the helpers, because we don't know the 678 // Read the last node, can't use the helpers, because we don't know the
679 // iNode yet. 679 // iNode yet.
680 if( iPosition != hNodeIndex.getSize() ) 680 if( iPosition != hNodeIndex.getSize() )
681 { 681 {
682 // If this is the last node, then we don't need to do anything, but 682 // If this is the last node, then we don't need to do anything, but
683 // this case handles what to do if we aren't on the last node 683 // this case handles what to do if we aren't on the last node
684 RawStat rs; 684 RawStat rs;
685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) ); 685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) );
686 is.read( &rs, sizeof(RawStat) ); 686 is.read( &rs, sizeof(RawStat) );
687 687
688 hNodeIndex.get( rs.iNode ) = iPosition; 688 hNodeIndex.get( rs.iNode ) = iPosition;
689 writeInode( rs, is ); 689 writeInode( rs, is );
690 } 690 }
691 691
692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) ); 692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) );
693} 693}
694 694
695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath ) 695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath )
696{ 696{
697 Bu::String::const_iterator iStart = sPath.begin(); 697 Bu::String::const_iterator iStart = sPath.begin();
698 if( *iStart == '/' ) 698 if( *iStart == '/' )
699 iStart++; 699 iStart++;
700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; 700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
701 iStart = iEnd+1, iEnd = iStart.find('/') ) { } 701 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
702 return Bu::String( iStart, sPath.end() ); 702 return Bu::String( iStart, sPath.end() );
703} 703}
704 704
diff --git a/src/unstable/myriadfs.h b/src/unstable/myriadfs.h
index 126be7a..dfb051b 100644
--- a/src/unstable/myriadfs.h
+++ b/src/unstable/myriadfs.h
@@ -14,190 +14,190 @@
14 14
15namespace Bu 15namespace Bu
16{ 16{
17 class Stream; 17 class Stream;
18 18
19 subExceptionDecl( MyriadFsException ); 19 subExceptionDecl( MyriadFsException );
20 20
21 /** 21 /**
22 * A POSIX compliant, node based filesystem built on top of Myriad. 22 * A POSIX compliant, node based filesystem built on top of Myriad.
23 * 23 *
24 * A header is placed into stream 1. 24 * A header is placed into stream 1.
25 * Header format: 25 * Header format:
26 * int32_t iMagicHeader (A7188B39) 26 * int32_t iMagicHeader (A7188B39)
27 * int8_t iVersion (1) 27 * int8_t iVersion (1)
28 * int32_t iNumNodes 28 * int32_t iNumNodes
29 * NodeLookup[iNumNodes] nNode 29 * NodeLookup[iNumNodes] nNode
30 * 30 *
31 * Node lookup: 31 * Node lookup:
32 * int32_t iInode 32 * int32_t iInode
33 * int32_t iPosition 33 * int32_t iPosition
34 * 34 *
35 * The node headers or inode structures have a base size of 44 bytes. 35 * The node headers or inode structures have a base size of 44 bytes.
36 * The name is stored in the directory format. 36 * The name is stored in the directory format.
37 * Basic node header format: 37 * Basic node header format:
38 * int32_t iNode 38 * int32_t iNode
39 * int32_t iUser 39 * int32_t iUser
40 * int32_t iGroup 40 * int32_t iGroup
41 * uint16_t uPerms 41 * uint16_t uPerms
42 * int16_t iLinks 42 * int16_t iLinks
43 * uint32_t uStreamIndex 43 * uint32_t uStreamIndex
44 * int64_t iATime 44 * int64_t iATime
45 * int64_t iMTime 45 * int64_t iMTime
46 * int64_t iCTime 46 * int64_t iCTime
47 * 47 *
48 * Some types get special formats for their assosiated data stream, or 48 * Some types get special formats for their assosiated data stream, or
49 * other special considerations, here's a list: 49 * other special considerations, here's a list:
50 * 50 *
51 * - typeFifo: No stream, uStreamIndex unused (probably) 51 * - typeFifo: No stream, uStreamIndex unused (probably)
52 * - typeChrDev: No stream, uStreamIndex is device hi/lo 52 * - typeChrDev: No stream, uStreamIndex is device hi/lo
53 * - typeDir: The stream contains a directory contents listing, described 53 * - typeDir: The stream contains a directory contents listing, described
54 * below 54 * below
55 * - typeBlkDev: No stream, uStreamIndex is device hi/lo 55 * - typeBlkDev: No stream, uStreamIndex is device hi/lo
56 * - typeRegFile: The stream is the file data 56 * - typeRegFile: The stream is the file data
57 * - typeSymLink: The stream is the destination of the symlink 57 * - typeSymLink: The stream is the destination of the symlink
58 * - typeSocket: No steram, uStreamIndex unused (probably) 58 * - typeSocket: No steram, uStreamIndex unused (probably)
59 * 59 *
60 * Directory streams have this simple listing format. They contain a list 60 * Directory streams have this simple listing format. They contain a list
61 * of all child elements, with no particular order at the moment. The . and 61 * of all child elements, with no particular order at the moment. The . and
62 * .. entries are not listed, they are implicit: 62 * .. entries are not listed, they are implicit:
63 * int32_t iNumNodes 63 * int32_t iNumNodes
64 * NodeTable[iNumNodes] nChildren 64 * NodeTable[iNumNodes] nChildren
65 * 65 *
66 * NodeTable: 66 * NodeTable:
67 * int32_t iInode 67 * int32_t iInode
68 * uint8_t uNameSize 68 * uint8_t uNameSize
69 * char[uNameSize] sName 69 * char[uNameSize] sName
70 */ 70 */
71 class MyriadFs 71 class MyriadFs
72 { 72 {
73 public: 73 public:
74 MyriadFs( Bu::Stream &rStore, int iBlockSize=512 ); 74 MyriadFs( Bu::Stream &rStore, int iBlockSize=512 );
75 virtual ~MyriadFs(); 75 virtual ~MyriadFs();
76 76
77 enum 77 enum
78 { 78 {
79 permOthX = 0000001, 79 permOthX = 0000001,
80 permOthW = 0000002, 80 permOthW = 0000002,
81 permOthR = 0000004, 81 permOthR = 0000004,
82 permGrpX = 0000010, 82 permGrpX = 0000010,
83 permGrpW = 0000020, 83 permGrpW = 0000020,
84 permGrpR = 0000040, 84 permGrpR = 0000040,
85 permUsrX = 0000100, 85 permUsrX = 0000100,
86 permUsrW = 0000200, 86 permUsrW = 0000200,
87 permUsrR = 0000400, 87 permUsrR = 0000400,
88 permSticky = 0001000, 88 permSticky = 0001000,
89 permSetGid = 0002000, 89 permSetGid = 0002000,
90 permSetUid = 0004000, 90 permSetUid = 0004000,
91 permMask = 0007777, 91 permMask = 0007777,
92 typeFifo = 0010000, 92 typeFifo = 0010000,
93 typeChrDev = 0020000, 93 typeChrDev = 0020000,
94 typeDir = 0040000, 94 typeDir = 0040000,
95 typeBlkDev = 0060000, 95 typeBlkDev = 0060000,
96 typeRegFile = 0100000, 96 typeRegFile = 0100000,
97 typeSymLink = 0120000, 97 typeSymLink = 0120000,
98 typeSocket = 0140000, 98 typeSocket = 0140000,
99 typeMask = 0170000 99 typeMask = 0170000
100 }; 100 };
101 101
102 enum 102 enum
103 { 103 {
104 Read = 0x01, ///< Open file for reading 104 Read = 0x01, ///< Open file for reading
105 Write = 0x02, ///< Open file for writing 105 Write = 0x02, ///< Open file for writing
106 Create = 0x04, ///< Create file if it doesn't exist 106 Create = 0x04, ///< Create file if it doesn't exist
107 Truncate = 0x08, ///< Truncate file if it does exist 107 Truncate = 0x08, ///< Truncate file if it does exist
108 Append = 0x10, ///< Always append on every write 108 Append = 0x10, ///< Always append on every write
109 NonBlock = 0x20, ///< Open file in non-blocking mode 109 NonBlock = 0x20, ///< Open file in non-blocking mode
110 Exclusive = 0x44, ///< Create file, if it exists then fail 110 Exclusive = 0x44, ///< Create file, if it exists then fail
111 111
112 // Helpful mixes 112 // Helpful mixes
113 ReadWrite = 0x03, ///< Open for reading and writing 113 ReadWrite = 0x03, ///< Open for reading and writing
114 WriteNew = 0x0E ///< Create a file (or truncate) for writing. 114 WriteNew = 0x0E ///< Create a file (or truncate) for writing.
115 /// Same as Write|Create|Truncate 115 /// Same as Write|Create|Truncate
116 }; 116 };
117 117
118 class Stat 118 class Stat
119 { 119 {
120 public: 120 public:
121 int32_t iNode; 121 int32_t iNode;
122 int32_t iUser; 122 int32_t iUser;
123 int32_t iGroup; 123 int32_t iGroup;
124 uint16_t uPerms; 124 uint16_t uPerms;
125 int16_t iLinks; 125 int16_t iLinks;
126 int64_t iATime; 126 int64_t iATime;
127 int64_t iMTime; 127 int64_t iMTime;
128 int64_t iCTime; 128 int64_t iCTime;
129 int32_t iSize; 129 int32_t iSize;
130 uint32_t uDev; 130 uint32_t uDev;
131 Bu::String sName; 131 Bu::String sName;
132 }; 132 };
133 typedef Bu::List<Stat> Dir; 133 typedef Bu::List<Stat> Dir;
134 134
135 void stat( const Bu::String &sPath, Stat &rBuf ); 135 void stat( const Bu::String &sPath, Stat &rBuf );
136 MyriadStream open( const Bu::String &sPath, int iMode, 136 MyriadStream open( const Bu::String &sPath, int iMode,
137 uint16_t uPerms=0664 ); 137 uint16_t uPerms=0664 );
138 void create( const Bu::String &sPath, uint16_t iPerms ); 138 void create( const Bu::String &sPath, uint16_t iPerms );
139 void create( const Bu::String &sPath, uint16_t iPerms, 139 void create( const Bu::String &sPath, uint16_t iPerms,
140 uint16_t iDevHi, uint16_t iDevLo ); 140 uint16_t iDevHi, uint16_t iDevLo );
141 void create( const Bu::String &sPath, uint16_t iPerms, 141 void create( const Bu::String &sPath, uint16_t iPerms,
142 uint32_t uSpecial ); 142 uint32_t uSpecial );
143 void mkDir( const Bu::String &sPath, uint16_t iPerms ); 143 void mkDir( const Bu::String &sPath, uint16_t iPerms );
144 void mkSymLink( const Bu::String &sTarget, const Bu::String &sPath ); 144 void mkSymLink( const Bu::String &sTarget, const Bu::String &sPath );
145 void mkHardLink( const Bu::String &sTarget, const Bu::String &sPath ); 145 void mkHardLink( const Bu::String &sTarget, const Bu::String &sPath );
146 Bu::String readSymLink( const Bu::String &sPath ); 146 Bu::String readSymLink( const Bu::String &sPath );
147 Dir readDir( const Bu::String &sPath ); 147 Dir readDir( const Bu::String &sPath );
148 void setTimes( const Bu::String &sPath, int64_t iATime, 148 void setTimes( const Bu::String &sPath, int64_t iATime,
149 int64_t iMTime ); 149 int64_t iMTime );
150 void unlink( const Bu::String &sPath ); 150 void unlink( const Bu::String &sPath );
151 void setFileSize( const Bu::String &sPath, int32_t iSize ); 151 void setFileSize( const Bu::String &sPath, int32_t iSize );
152 void rename( const Bu::String &sFrom, const Bu::String &sTo ); 152 void rename( const Bu::String &sFrom, const Bu::String &sTo );
153 153
154 static dev_t devToSys( uint32_t uDev ); 154 static dev_t devToSys( uint32_t uDev );
155 static uint32_t sysToDev( dev_t uDev ); 155 static uint32_t sysToDev( dev_t uDev );
156 156
157 private: 157 private:
158 class RawStat 158 class RawStat
159 { 159 {
160 public: 160 public:
161 int32_t iNode; 161 int32_t iNode;
162 int32_t iUser; 162 int32_t iUser;
163 int32_t iGroup; 163 int32_t iGroup;
164 uint16_t uPerms; 164 uint16_t uPerms;
165 int16_t iLinks; 165 int16_t iLinks;
166 uint32_t uStreamIndex; 166 uint32_t uStreamIndex;
167 int64_t iATime; 167 int64_t iATime;
168 int64_t iMTime; 168 int64_t iMTime;
169 int64_t iCTime; 169 int64_t iCTime;
170 }; 170 };
171 typedef Bu::Hash<int32_t, int32_t> NodeIndex; 171 typedef Bu::Hash<int32_t, int32_t> NodeIndex;
172 172
173 private: 173 private:
174 int32_t lookupInode( const Bu::String &sPath, int32_t &iParent ); 174 int32_t lookupInode( const Bu::String &sPath, int32_t &iParent );
175 int32_t lookupInode( Bu::String::const_iterator iStart, 175 int32_t lookupInode( Bu::String::const_iterator iStart,
176 int32_t iNode, int32_t &iParent ); 176 int32_t iNode, int32_t &iParent );
177 void readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ); 177 void readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs );
178 void readInode( int32_t iNode, RawStat &rs ); 178 void readInode( int32_t iNode, RawStat &rs );
179 void writeInode( const RawStat &rs ); 179 void writeInode( const RawStat &rs );
180 void writeInode( const RawStat &rs, MyriadStream &rOs ); 180 void writeInode( const RawStat &rs, MyriadStream &rOs );
181 Dir readDir( int32_t iNode ); 181 Dir readDir( int32_t iNode );
182 MyriadStream openByInode( int32_t iNode ); 182 MyriadStream openByInode( int32_t iNode );
183 void addToDir( int32_t iDir, int32_t iNode, const Bu::String &sName ); 183 void addToDir( int32_t iDir, int32_t iNode, const Bu::String &sName );
184 int32_t create( int32_t iParent, const Bu::String &sName, 184 int32_t create( int32_t iParent, const Bu::String &sName,
185 uint16_t uPerms, uint32_t uSpecial ); 185 uint16_t uPerms, uint32_t uSpecial );
186 int32_t allocInode( uint16_t uPerms, uint32_t uSpecial ); 186 int32_t allocInode( uint16_t uPerms, uint32_t uSpecial );
187 void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ); 187 void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs );
188 void writeHeader(); 188 void writeHeader();
189 void setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ); 189 void setTimes( int32_t iNode, int64_t iATime, int64_t iMTime );
190 void destroyNode( int32_t iNode ); 190 void destroyNode( int32_t iNode );
191 191
192 Bu::String filePart( const Bu::String &sPath ); 192 Bu::String filePart( const Bu::String &sPath );
193 193
194 private: 194 private:
195 Bu::Stream &rStore; 195 Bu::Stream &rStore;
196 Bu::Myriad mStore; 196 Bu::Myriad mStore;
197 NodeIndex hNodeIndex; 197 NodeIndex hNodeIndex;
198 int32_t iUser; 198 int32_t iUser;
199 int32_t iGroup; 199 int32_t iGroup;
200 }; 200 };
201}; 201};
202 202
203#endif 203#endif
diff --git a/src/unstable/newline.cpp b/src/unstable/newline.cpp
index c7eb94c..50a4d4e 100644
--- a/src/unstable/newline.cpp
+++ b/src/unstable/newline.cpp
@@ -8,8 +8,8 @@
8#include "bu/newline.h" 8#include "bu/newline.h"
9 9
10Bu::NewLine::NewLine( Bu::Stream &rNext ) : 10Bu::NewLine::NewLine( Bu::Stream &rNext ) :
11 Bu::Filter( rNext ), 11 Bu::Filter( rNext ),
12 bExChar( false ) 12 bExChar( false )
13{ 13{
14} 14}
15 15
@@ -23,46 +23,46 @@ void Bu::NewLine::start()
23 23
24Bu::size Bu::NewLine::stop() 24Bu::size Bu::NewLine::stop()
25{ 25{
26 return 0; 26 return 0;
27} 27}
28 28
29Bu::size Bu::NewLine::read( void *pBufV, Bu::size iAmnt ) 29Bu::size Bu::NewLine::read( void *pBufV, Bu::size iAmnt )
30{ 30{
31 Bu::size iTotal = 0; 31 Bu::size iTotal = 0;
32 Bu::size iOffset = 0; 32 Bu::size iOffset = 0;
33 Bu::size iRead = rNext.read( pBufV, iAmnt ); 33 Bu::size iRead = rNext.read( pBufV, iAmnt );
34 char *pBuf = (char *)pBufV; 34 char *pBuf = (char *)pBufV;
35 35
36 for( Bu::size i = 0; i < iRead; i++ ) 36 for( Bu::size i = 0; i < iRead; i++ )
37 { 37 {
38 if( pBuf[i] == '\r' ) 38 if( pBuf[i] == '\r' )
39 { 39 {
40 pBuf[i+iOffset] = '\n'; 40 pBuf[i+iOffset] = '\n';
41 if( pBuf[i+1] == '\n' ) 41 if( pBuf[i+1] == '\n' )
42 { 42 {
43 iOffset--; 43 iOffset--;
44 } 44 }
45 } 45 }
46 else if( pBuf[i] == '\n' ) 46 else if( pBuf[i] == '\n' )
47 { 47 {
48 pBuf[i+iOffset] = '\n'; 48 pBuf[i+iOffset] = '\n';
49 if( pBuf[i+1] == '\r' ) 49 if( pBuf[i+1] == '\r' )
50 { 50 {
51 iOffset--; 51 iOffset--;
52 } 52 }
53 } 53 }
54 else if( iOffset ) 54 else if( iOffset )
55 { 55 {
56 pBuf[i+iOffset] = pBuf[i]; 56 pBuf[i+iOffset] = pBuf[i];
57 } 57 }
58 } 58 }
59 59
60 iTotal += iRead + iOffset; 60 iTotal += iRead + iOffset;
61 return iTotal; 61 return iTotal;
62} 62}
63 63
64Bu::size Bu::NewLine::write( const void *, Bu::size ) 64Bu::size Bu::NewLine::write( const void *, Bu::size )
65{ 65{
66 return 0; 66 return 0;
67} 67}
68 68
diff --git a/src/unstable/newline.h b/src/unstable/newline.h
index 417f8cc..1597dc6 100644
--- a/src/unstable/newline.h
+++ b/src/unstable/newline.h
@@ -12,30 +12,30 @@
12 12
13namespace Bu 13namespace Bu
14{ 14{
15 /** 15 /**
16 * Converts new-line characters from any standard convention into linefeeds 16 * Converts new-line characters from any standard convention into linefeeds
17 * (\\n) on reading, and converts them to either your OS's standard or a 17 * (\\n) on reading, and converts them to either your OS's standard or a
18 * specified standard, depending on how you construct the class. 18 * specified standard, depending on how you construct the class.
19 * 19 *
20 * If you're reading in a text file, then this filter is practically 20 * If you're reading in a text file, then this filter is practically
21 * required. 21 * required.
22 */ 22 */
23 class NewLine : public Bu::Filter 23 class NewLine : public Bu::Filter
24 { 24 {
25 public: 25 public:
26 NewLine( Bu::Stream &rNext ); 26 NewLine( Bu::Stream &rNext );
27 virtual ~NewLine(); 27 virtual ~NewLine();
28 28
29 virtual void start(); 29 virtual void start();
30 virtual Bu::size stop(); 30 virtual Bu::size stop();
31 31
32 virtual Bu::size read( void *pBuf, Bu::size iAmnt ); 32 virtual Bu::size read( void *pBuf, Bu::size iAmnt );
33 virtual Bu::size write( const void *pBuf, Bu::size iAmnt ); 33 virtual Bu::size write( const void *pBuf, Bu::size iAmnt );
34 34
35 private: 35 private:
36 bool bExChar; 36 bool bExChar;
37 char cExChar; 37 char cExChar;
38 }; 38 };
39}; 39};
40 40
41#endif 41#endif
diff --git a/src/unstable/settings.cpp b/src/unstable/settings.cpp
index b812b60..ced8c97 100644
--- a/src/unstable/settings.cpp
+++ b/src/unstable/settings.cpp
@@ -5,46 +5,46 @@
5#include "bu/settingsdriverini.h" 5#include "bu/settingsdriverini.h"
6 6
7Bu::Settings::Settings( const Bu::UtfString &sCompany, 7Bu::Settings::Settings( const Bu::UtfString &sCompany,
8 const Bu::UtfString &sProduct, Bu::Settings::Driver eDriver ) : 8 const Bu::UtfString &sProduct, Bu::Settings::Driver eDriver ) :
9 sCompany( sCompany ), 9 sCompany( sCompany ),
10 sProduct( sProduct ), 10 sProduct( sProduct ),
11 pDriver( NULL ) 11 pDriver( NULL )
12{ 12{
13 switch( eDriver ) 13 switch( eDriver )
14 { 14 {
15 case DriverNative: 15 case DriverNative:
16#if defined( WIN32 ) 16#if defined( WIN32 )
17 pDriver = new Bu::SettingsDriverRegistry(); 17 pDriver = new Bu::SettingsDriverRegistry();
18#else 18#else
19 pDriver = new Bu::SettingsDriverIni(); 19 pDriver = new Bu::SettingsDriverIni();
20#endif 20#endif
21 break; 21 break;
22 22
23 case DriverTaf: 23 case DriverTaf:
24 pDriver = new Bu::SettingsDriverTaf(); 24 pDriver = new Bu::SettingsDriverTaf();
25 break; 25 break;
26 26
27 case DriverIni: 27 case DriverIni:
28 pDriver = new Bu::SettingsDriverIni(); 28 pDriver = new Bu::SettingsDriverIni();
29 break; 29 break;
30 } 30 }
31 31
32 pDriver->init( sCompany, sProduct ); 32 pDriver->init( sCompany, sProduct );
33} 33}
34 34
35Bu::Settings::~Settings() 35Bu::Settings::~Settings()
36{ 36{
37 delete pDriver; 37 delete pDriver;
38} 38}
39 39
40void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 40void Bu::Settings::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
41{ 41{
42 pDriver->set( sKey, sValue ); 42 pDriver->set( sKey, sValue );
43} 43}
44 44
45Bu::UtfString Bu::Settings::get( const Bu::UtfString &sKey, 45Bu::UtfString Bu::Settings::get( const Bu::UtfString &sKey,
46 const Bu::UtfString &sValue ) 46 const Bu::UtfString &sValue )
47{ 47{
48 return pDriver->get( sKey, sValue ); 48 return pDriver->get( sKey, sValue );
49} 49}
50 50
diff --git a/src/unstable/settings.h b/src/unstable/settings.h
index c1d0e1c..80d3049 100644
--- a/src/unstable/settings.h
+++ b/src/unstable/settings.h
@@ -5,31 +5,31 @@
5 5
6namespace Bu 6namespace Bu
7{ 7{
8 /** 8 /**
9 * Simple access to configuration data. Provides a consistant, cross 9 * Simple access to configuration data. Provides a consistant, cross
10 * platform interface to configuration data using native storage. 10 * platform interface to configuration data using native storage.
11 */ 11 */
12 class Settings 12 class Settings
13 { 13 {
14 public: 14 public:
15 enum Driver 15 enum Driver
16 { 16 {
17 DriverNative, 17 DriverNative,
18 DriverTaf, 18 DriverTaf,
19 DriverIni 19 DriverIni
20 }; 20 };
21 Settings( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct, 21 Settings( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct,
22 Driver driver=DriverNative ); 22 Driver driver=DriverNative );
23 virtual ~Settings(); 23 virtual ~Settings();
24 24
25 void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 25 void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
26 Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue=Bu::UtfString() ); 26 Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue=Bu::UtfString() );
27 27
28 private: 28 private:
29 Bu::UtfString sCompany; 29 Bu::UtfString sCompany;
30 Bu::UtfString sProduct; 30 Bu::UtfString sProduct;
31 class SettingsDriver *pDriver; 31 class SettingsDriver *pDriver;
32 }; 32 };
33}; 33};
34 34
35#endif 35#endif
diff --git a/src/unstable/settingsdriver.h b/src/unstable/settingsdriver.h
index 47b7d9d..4dfe09c 100644
--- a/src/unstable/settingsdriver.h
+++ b/src/unstable/settingsdriver.h
@@ -5,24 +5,24 @@
5 5
6namespace Bu 6namespace Bu
7{ 7{
8 class Settings; 8 class Settings;
9 9
10 /** 10 /**
11 * Base class for i/o interfaces for Bu::Settings. By subclassing this you 11 * Base class for i/o interfaces for Bu::Settings. By subclassing this you
12 * can provide custom storage for application settings. 12 * can provide custom storage for application settings.
13 */ 13 */
14 class SettingsDriver 14 class SettingsDriver
15 { 15 {
16 friend class Bu::Settings; 16 friend class Bu::Settings;
17 public: 17 public:
18 SettingsDriver(); 18 SettingsDriver();
19 virtual ~SettingsDriver(); 19 virtual ~SettingsDriver();
20 20
21 protected: 21 protected:
22 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )=0; 22 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )=0;
23 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0; 23 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0;
24 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0; 24 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )=0;
25 }; 25 };
26}; 26};
27 27
28#endif 28#endif
diff --git a/src/unstable/settingsdriverini.cpp b/src/unstable/settingsdriverini.cpp
index 90debcb..31bc146 100644
--- a/src/unstable/settingsdriverini.cpp
+++ b/src/unstable/settingsdriverini.cpp
@@ -15,146 +15,146 @@ Bu::SettingsDriverIni::SettingsDriverIni()
15 15
16Bu::SettingsDriverIni::~SettingsDriverIni() 16Bu::SettingsDriverIni::~SettingsDriverIni()
17{ 17{
18 Bu::File fOut( sPath, Bu::File::WriteNew ); 18 Bu::File fOut( sPath, Bu::File::WriteNew );
19 Bu::Buffer bOut( fOut ); 19 Bu::Buffer bOut( fOut );
20 Bu::Formatter f( bOut ); 20 Bu::Formatter f( bOut );
21 21
22 for( GroupHash::iterator i = hGroup.begin(); i; i++ ) 22 for( GroupHash::iterator i = hGroup.begin(); i; i++ )
23 { 23 {
24 f << "[" << i.getKey().get() << "]" << f.nl; 24 f << "[" << i.getKey().get() << "]" << f.nl;
25 for( StrHash::iterator k = (*i).begin(); k; k++ ) 25 for( StrHash::iterator k = (*i).begin(); k; k++ )
26 { 26 {
27 f << k.getKey().get() << " = " << k.getValue().get() << f.nl; 27 f << k.getKey().get() << " = " << k.getValue().get() << f.nl;
28 } 28 }
29 f << f.nl; 29 f << f.nl;
30 } 30 }
31} 31}
32 32
33void Bu::SettingsDriverIni::init( const Bu::UtfString &sCompany, 33void Bu::SettingsDriverIni::init( const Bu::UtfString &sCompany,
34 const Bu::UtfString &sProduct ) 34 const Bu::UtfString &sProduct )
35{ 35{
36 Bu::UtfString us( getenv("HOME") ); 36 Bu::UtfString us( getenv("HOME") );
37 us += "/.config/"; 37 us += "/.config/";
38 us += sCompany; 38 us += sCompany;
39 us += "/"; 39 us += "/";
40 us += sProduct; 40 us += sProduct;
41 sPath = us.get(); 41 sPath = us.get();
42 try 42 try
43 { 43 {
44 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create ); 44 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create );
45 Bu::Buffer bIn( fIn ); 45 Bu::Buffer bIn( fIn );
46 StrHash hKeys; 46 StrHash hKeys;
47 Bu::String sGroup; 47 Bu::String sGroup;
48 bool bStart = true; 48 bool bStart = true;
49 while( !bIn.isEos() ) 49 while( !bIn.isEos() )
50 { 50 {
51 Bu::String sIn = bIn.readLine(); 51 Bu::String sIn = bIn.readLine();
52 if( sIn.isEmpty() ) 52 if( sIn.isEmpty() )
53 continue; 53 continue;
54 if( sIn[0] == '[' ) 54 if( sIn[0] == '[' )
55 { 55 {
56 if( bStart != true ) 56 if( bStart != true )
57 { 57 {
58 hGroup.insert( sGroup, hKeys ); 58 hGroup.insert( sGroup, hKeys );
59 hKeys.clear(); 59 hKeys.clear();
60 } 60 }
61 sGroup = Bu::String( sIn.begin()+1, sIn.find(']') ); 61 sGroup = Bu::String( sIn.begin()+1, sIn.find(']') );
62 bStart = false; 62 bStart = false;
63 } 63 }
64 else 64 else
65 { 65 {
66 Bu::String::iterator i = sIn.find('='); 66 Bu::String::iterator i = sIn.find('=');
67 if( !i ) 67 if( !i )
68 continue; 68 continue;
69 69
70 hKeys.insert( Bu::String( sIn.begin(), i ).trimWhitespace(), 70 hKeys.insert( Bu::String( sIn.begin(), i ).trimWhitespace(),
71 Bu::String( i+1, sIn.end() ).trimWhitespace() ); 71 Bu::String( i+1, sIn.end() ).trimWhitespace() );
72 } 72 }
73 } 73 }
74 hGroup.insert( sGroup, hKeys ); 74 hGroup.insert( sGroup, hKeys );
75 } 75 }
76 catch(...) 76 catch(...)
77 { 77 {
78 } 78 }
79} 79}
80 80
81void Bu::SettingsDriverIni::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 81void Bu::SettingsDriverIni::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
82{ 82{
83 Bu::String suKey = sKey.get(); 83 Bu::String suKey = sKey.get();
84 Bu::String::iterator i = suKey.find('/'); 84 Bu::String::iterator i = suKey.find('/');
85 Bu::UtfString sGrp; 85 Bu::UtfString sGrp;
86 Bu::UtfString sId; 86 Bu::UtfString sId;
87 if( !i ) 87 if( !i )
88 { 88 {
89 sGrp = ""; 89 sGrp = "";
90 sId = sKey; 90 sId = sKey;
91 } 91 }
92 else 92 else
93 { 93 {
94 Bu::String::iterator in; 94 Bu::String::iterator in;
95 for(;;) 95 for(;;)
96 { 96 {
97 in = i; 97 in = i;
98 i = (in + 1).find('/'); 98 i = (in + 1).find('/');
99 if( !i ) 99 if( !i )
100 break; 100 break;
101 } 101 }
102 102
103 sGrp.set( Bu::String( suKey.begin(), in ) ); 103 sGrp.set( Bu::String( suKey.begin(), in ) );
104 sId.set( Bu::String( in+1, suKey.end() ) ); 104 sId.set( Bu::String( in+1, suKey.end() ) );
105 } 105 }
106 106
107// sio << "Group: " << sGrp.get() << sio.nl 107// sio << "Group: " << sGrp.get() << sio.nl
108// << "Key: " << sId.get() << sio.nl; 108// << "Key: " << sId.get() << sio.nl;
109 109
110 if( !hGroup.has( sGrp ) ) 110 if( !hGroup.has( sGrp ) )
111 { 111 {
112 StrHash hVal; 112 StrHash hVal;
113 hVal.insert( sId, sValue ); 113 hVal.insert( sId, sValue );
114 hGroup.insert( sGrp, hVal ); 114 hGroup.insert( sGrp, hVal );
115 } 115 }
116 else 116 else
117 { 117 {
118 hGroup.get( sGrp ).insert( sId, sValue ); 118 hGroup.get( sGrp ).insert( sId, sValue );
119 } 119 }
120} 120}
121 121
122Bu::UtfString Bu::SettingsDriverIni::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 122Bu::UtfString Bu::SettingsDriverIni::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
123{ 123{
124 Bu::String suKey = sKey.get(); 124 Bu::String suKey = sKey.get();
125 Bu::String::iterator i = suKey.find('/'); 125 Bu::String::iterator i = suKey.find('/');
126 Bu::UtfString sGrp; 126 Bu::UtfString sGrp;
127 Bu::UtfString sId; 127 Bu::UtfString sId;
128 if( !i ) 128 if( !i )
129 { 129 {
130 sGrp = ""; 130 sGrp = "";
131 sId = sKey; 131 sId = sKey;
132 } 132 }
133 else 133 else
134 { 134 {
135 Bu::String::iterator in; 135 Bu::String::iterator in;
136 for(;;) 136 for(;;)
137 { 137 {
138 in = i; 138 in = i;
139 i = (in + 1).find('/'); 139 i = (in + 1).find('/');
140 if( !i ) 140 if( !i )
141 break; 141 break;
142 } 142 }
143 143
144 sGrp.set( Bu::String( suKey.begin(), in ) ); 144 sGrp.set( Bu::String( suKey.begin(), in ) );
145 sId.set( Bu::String( in+1, suKey.end() ) ); 145 sId.set( Bu::String( in+1, suKey.end() ) );
146 } 146 }
147 147
148// sio << "Group: " << sGrp.get() << sio.nl 148// sio << "Group: " << sGrp.get() << sio.nl
149// << "Key: " << sId.get() << sio.nl; 149// << "Key: " << sId.get() << sio.nl;
150 150
151 try 151 try
152 { 152 {
153 return hGroup.get( sGrp ).get( sId ); 153 return hGroup.get( sGrp ).get( sId );
154 } 154 }
155 catch(...) 155 catch(...)
156 { 156 {
157 return sValue; 157 return sValue;
158 } 158 }
159} 159}
160 160
diff --git a/src/unstable/settingsdriverini.h b/src/unstable/settingsdriverini.h
index c3942d6..bd3097d 100644
--- a/src/unstable/settingsdriverini.h
+++ b/src/unstable/settingsdriverini.h
@@ -7,23 +7,23 @@
7 7
8namespace Bu 8namespace Bu
9{ 9{
10 class SettingsDriverIni : public SettingsDriver 10 class SettingsDriverIni : public SettingsDriver
11 { 11 {
12 public: 12 public:
13 SettingsDriverIni(); 13 SettingsDriverIni();
14 virtual ~SettingsDriverIni(); 14 virtual ~SettingsDriverIni();
15 15
16 protected: 16 protected:
17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
20 20
21 private: 21 private:
22 Bu::String sPath; 22 Bu::String sPath;
23 typedef Bu::Hash<Bu::UtfString, Bu::UtfString> StrHash; 23 typedef Bu::Hash<Bu::UtfString, Bu::UtfString> StrHash;
24 typedef Bu::Hash<Bu::UtfString, StrHash> GroupHash; 24 typedef Bu::Hash<Bu::UtfString, StrHash> GroupHash;
25 GroupHash hGroup; 25 GroupHash hGroup;
26 }; 26 };
27}; 27};
28 28
29#endif 29#endif
diff --git a/src/unstable/settingsdriverregistry.cpp b/src/unstable/settingsdriverregistry.cpp
index 89eda7b..983f48e 100644
--- a/src/unstable/settingsdriverregistry.cpp
+++ b/src/unstable/settingsdriverregistry.cpp
@@ -12,80 +12,80 @@ Bu::SettingsDriverRegistry::SettingsDriverRegistry()
12 12
13Bu::SettingsDriverRegistry::~SettingsDriverRegistry() 13Bu::SettingsDriverRegistry::~SettingsDriverRegistry()
14{ 14{
15 RegCloseKey( *phKey ); 15 RegCloseKey( *phKey );
16} 16}
17 17
18void Bu::SettingsDriverRegistry::init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ) 18void Bu::SettingsDriverRegistry::init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct )
19{ 19{
20 Bu::UtfString us("Software\\"); 20 Bu::UtfString us("Software\\");
21 us += sCompany; 21 us += sCompany;
22 us += "\\"; 22 us += "\\";
23 us += sProduct; 23 us += sProduct;
24 rphKey = new HKEY; 24 rphKey = new HKEY;
25 RegCreateKeyExA( HKEY_CURRENT_USER, us.get().getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, phKey, NULL ); 25 RegCreateKeyExA( HKEY_CURRENT_USER, us.get().getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, phKey, NULL );
26} 26}
27 27
28void Bu::SettingsDriverRegistry::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 28void Bu::SettingsDriverRegistry::set( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
29{ 29{
30 Bu::StringList lPath = sKey.get().split('/'); 30 Bu::StringList lPath = sKey.get().split('/');
31 Bu::StringList::iterator i = lPath.begin(); 31 Bu::StringList::iterator i = lPath.begin();
32 Bu::StringList::iterator in; 32 Bu::StringList::iterator in;
33 33
34 Bu::String sPKey; 34 Bu::String sPKey;
35 for(; i;) 35 for(; i;)
36 { 36 {
37 in = i; 37 in = i;
38 in++; 38 in++;
39 if( in ) 39 if( in )
40 { 40 {
41 if( !sPKey.isEmpty() ) 41 if( !sPKey.isEmpty() )
42 sPKey += "\\"; 42 sPKey += "\\";
43 sPKey += *i; 43 sPKey += *i;
44 } 44 }
45 i = in; 45 i = in;
46 } 46 }
47 47
48 HKEY key; 48 HKEY key;
49 RegCreateKeyExA( *phKey, sPKey.getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); 49 RegCreateKeyExA( *phKey, sPKey.getStr(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
50 Bu::String sTmp = sValue.get(); 50 Bu::String sTmp = sValue.get();
51 RegSetValueExA( key, lPath.last().getStr(), 0, REG_SZ, (BYTE *)sTmp.getStr(), sTmp.getSize()+1 ); 51 RegSetValueExA( key, lPath.last().getStr(), 0, REG_SZ, (BYTE *)sTmp.getStr(), sTmp.getSize()+1 );
52 RegCloseKey( key ); 52 RegCloseKey( key );
53} 53}
54 54
55Bu::UtfString Bu::SettingsDriverRegistry::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ) 55Bu::UtfString Bu::SettingsDriverRegistry::get( const Bu::UtfString &sKey, const Bu::UtfString &sValue )
56{ 56{
57 Bu::StringList lPath = sKey.get().split('/'); 57 Bu::StringList lPath = sKey.get().split('/');
58 Bu::StringList::iterator i = lPath.begin(); 58 Bu::StringList::iterator i = lPath.begin();
59 Bu::StringList::iterator in; 59 Bu::StringList::iterator in;
60 60
61 Bu::String sPKey; 61 Bu::String sPKey;
62 for(; i;) 62 for(; i;)
63 { 63 {
64 in = i; 64 in = i;
65 in++; 65 in++;
66 if( in ) 66 if( in )
67 { 67 {
68 if( !sPKey.isEmpty() ) 68 if( !sPKey.isEmpty() )
69 sPKey += "\\"; 69 sPKey += "\\";
70 sPKey += *i; 70 sPKey += *i;
71 } 71 }
72 i = in; 72 i = in;
73 } 73 }
74 74
75 HKEY key; 75 HKEY key;
76 if( RegOpenKeyExA( *phKey, sPKey.getStr(), 0, KEY_ALL_ACCESS, &key ) 76 if( RegOpenKeyExA( *phKey, sPKey.getStr(), 0, KEY_ALL_ACCESS, &key )
77 != ERROR_SUCCESS ) 77 != ERROR_SUCCESS )
78 return sValue; 78 return sValue;
79 char buf[4096]; 79 char buf[4096];
80 DWORD iRet = 4096; 80 DWORD iRet = 4096;
81 if( RegQueryValueEx( key, lPath.last().getStr(), NULL, NULL, (BYTE *)buf, &iRet ) != ERROR_SUCCESS ) 81 if( RegQueryValueEx( key, lPath.last().getStr(), NULL, NULL, (BYTE *)buf, &iRet ) != ERROR_SUCCESS )
82 { 82 {
83 RegCloseKey( key ); 83 RegCloseKey( key );
84 return sValue; 84 return sValue;
85 } 85 }
86 RegCloseKey( key ); 86 RegCloseKey( key );
87 87
88 return Bu::UtfString( Bu::String( buf, iRet ) ); 88 return Bu::UtfString( Bu::String( buf, iRet ) );
89} 89}
90 90
91#endif 91#endif
diff --git a/src/unstable/settingsdriverregistry.h b/src/unstable/settingsdriverregistry.h
index 2d718d2..d1a2896 100644
--- a/src/unstable/settingsdriverregistry.h
+++ b/src/unstable/settingsdriverregistry.h
@@ -7,20 +7,20 @@
7 7
8namespace Bu 8namespace Bu
9{ 9{
10 class SettingsDriverRegistry : public SettingsDriver 10 class SettingsDriverRegistry : public SettingsDriver
11 { 11 {
12 public: 12 public:
13 SettingsDriverRegistry(); 13 SettingsDriverRegistry();
14 virtual ~SettingsDriverRegistry(); 14 virtual ~SettingsDriverRegistry();
15 15
16 protected: 16 protected:
17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 17 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 18 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 19 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
20 20
21 private: 21 private:
22 void *rphKey; 22 void *rphKey;
23 }; 23 };
24}; 24};
25 25
26#endif 26#endif
diff --git a/src/unstable/settingsdrivertaf.cpp b/src/unstable/settingsdrivertaf.cpp
index 8cbcbc5..3fd61b3 100644
--- a/src/unstable/settingsdrivertaf.cpp
+++ b/src/unstable/settingsdrivertaf.cpp
@@ -6,97 +6,97 @@
6#include <stdlib.h> 6#include <stdlib.h>
7 7
8Bu::SettingsDriverTaf::SettingsDriverTaf() : 8Bu::SettingsDriverTaf::SettingsDriverTaf() :
9 pRoot( NULL ) 9 pRoot( NULL )
10{ 10{
11} 11}
12 12
13Bu::SettingsDriverTaf::~SettingsDriverTaf() 13Bu::SettingsDriverTaf::~SettingsDriverTaf()
14{ 14{
15 if( !pRoot ) 15 if( !pRoot )
16 return; 16 return;
17 17
18 Bu::File fOut( sPath, Bu::File::WriteNew ); 18 Bu::File fOut( sPath, Bu::File::WriteNew );
19 Bu::TafWriter tw( fOut ); 19 Bu::TafWriter tw( fOut );
20 tw.writeGroup( pRoot ); 20 tw.writeGroup( pRoot );
21 delete pRoot; 21 delete pRoot;
22} 22}
23 23
24void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany, 24void Bu::SettingsDriverTaf::init( const Bu::UtfString &sCompany,
25 const Bu::UtfString &sProduct ) 25 const Bu::UtfString &sProduct )
26{ 26{
27 Bu::UtfString us( getenv("HOME") ); 27 Bu::UtfString us( getenv("HOME") );
28 us += "/.config/"; 28 us += "/.config/";
29 us += sCompany; 29 us += sCompany;
30 us += "/"; 30 us += "/";
31 us += sProduct; 31 us += sProduct;
32 sPath = us.get(); 32 sPath = us.get();
33 try 33 try
34 { 34 {
35 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create ); 35 Bu::File fIn( sPath, Bu::File::Read|Bu::File::Create );
36 Bu::TafReader tr( fIn ); 36 Bu::TafReader tr( fIn );
37 pRoot = tr.readGroup(); 37 pRoot = tr.readGroup();
38 } 38 }
39 catch(...) 39 catch(...)
40 { 40 {
41 } 41 }
42 if( !pRoot ) 42 if( !pRoot )
43 { 43 {
44 pRoot = new Bu::TafGroup( sProduct.get() ); 44 pRoot = new Bu::TafGroup( sProduct.get() );
45 } 45 }
46} 46}
47 47
48void Bu::SettingsDriverTaf::set( const Bu::UtfString &sKey, 48void Bu::SettingsDriverTaf::set( const Bu::UtfString &sKey,
49 const Bu::UtfString &sValue ) 49 const Bu::UtfString &sValue )
50{ 50{
51 Bu::StringList lPath = sKey.get().split('/'); 51 Bu::StringList lPath = sKey.get().split('/');
52 Bu::StringList::iterator i = lPath.begin(); 52 Bu::StringList::iterator i = lPath.begin();
53 Bu::StringList::iterator in; 53 Bu::StringList::iterator in;
54 Bu::TafGroup *pGrp = pRoot; 54 Bu::TafGroup *pGrp = pRoot;
55 for(; i;) 55 for(; i;)
56 { 56 {
57 in = i; 57 in = i;
58 in++; 58 in++;
59 if( in ) 59 if( in )
60 { 60 {
61 if( pGrp->hasChild( *i ) ) 61 if( pGrp->hasChild( *i ) )
62 pGrp = (Bu::TafGroup *)pGrp->getChild( *i ); 62 pGrp = (Bu::TafGroup *)pGrp->getChild( *i );
63 else 63 else
64 pGrp = pGrp->addGroup( *i ); 64 pGrp = pGrp->addGroup( *i );
65 } 65 }
66 else 66 else
67 { 67 {
68 pGrp->addProperty( *i, sValue.get() ); 68 pGrp->addProperty( *i, sValue.get() );
69 } 69 }
70 i = in; 70 i = in;
71 } 71 }
72} 72}
73 73
74Bu::UtfString Bu::SettingsDriverTaf::get( const Bu::UtfString &sKey, 74Bu::UtfString Bu::SettingsDriverTaf::get( const Bu::UtfString &sKey,
75 const Bu::UtfString &sValue ) 75 const Bu::UtfString &sValue )
76{ 76{
77 Bu::StringList lPath = sKey.get().split('/'); 77 Bu::StringList lPath = sKey.get().split('/');
78 Bu::StringList::iterator i = lPath.begin(); 78 Bu::StringList::iterator i = lPath.begin();
79 Bu::StringList::iterator in; 79 Bu::StringList::iterator in;
80 Bu::TafGroup *pGrp = pRoot; 80 Bu::TafGroup *pGrp = pRoot;
81 for(; i;) 81 for(; i;)
82 { 82 {
83 in = i; 83 in = i;
84 in++; 84 in++;
85 if( in ) 85 if( in )
86 { 86 {
87 if( pGrp->hasChild( *i ) ) 87 if( pGrp->hasChild( *i ) )
88 pGrp = (Bu::TafGroup *)pGrp->getChild( *i ); 88 pGrp = (Bu::TafGroup *)pGrp->getChild( *i );
89 else 89 else
90 return sValue; 90 return sValue;
91 } 91 }
92 else 92 else
93 { 93 {
94 if( pGrp->hasProperty( *i ) ) 94 if( pGrp->hasProperty( *i ) )
95 return pGrp->getProperty( *i ); 95 return pGrp->getProperty( *i );
96 else 96 else
97 return sValue; 97 return sValue;
98 } 98 }
99 i = in; 99 i = in;
100 } 100 }
101} 101}
102 102
diff --git a/src/unstable/settingsdrivertaf.h b/src/unstable/settingsdrivertaf.h
index b5f8b07..28b5f5c 100644
--- a/src/unstable/settingsdrivertaf.h
+++ b/src/unstable/settingsdrivertaf.h
@@ -6,26 +6,26 @@
6 6
7namespace Bu 7namespace Bu
8{ 8{
9 class TafGroup; 9 class TafGroup;
10 10
11 /** 11 /**
12 * The taf driver is flawed until I fix taf editing, I've been meaning to... 12 * The taf driver is flawed until I fix taf editing, I've been meaning to...
13 */ 13 */
14 class SettingsDriverTaf : public SettingsDriver 14 class SettingsDriverTaf : public SettingsDriver
15 { 15 {
16 public: 16 public:
17 SettingsDriverTaf(); 17 SettingsDriverTaf();
18 virtual ~SettingsDriverTaf(); 18 virtual ~SettingsDriverTaf();
19 19
20 protected: 20 protected:
21 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct ); 21 virtual void init( const Bu::UtfString &sCompany, const Bu::UtfString &sProduct );
22 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 22 virtual void set( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
23 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue ); 23 virtual Bu::UtfString get( const Bu::UtfString &sKey, const Bu::UtfString &sValue );
24 24
25 private: 25 private:
26 Bu::String sPath; 26 Bu::String sPath;
27 class Bu::TafGroup *pRoot; 27 class Bu::TafGroup *pRoot;
28 }; 28 };
29}; 29};
30 30
31#endif 31#endif
diff --git a/src/unstable/udpsocket.cpp b/src/unstable/udpsocket.cpp
index f554165..141c2cf 100644
--- a/src/unstable/udpsocket.cpp
+++ b/src/unstable/udpsocket.cpp
@@ -24,135 +24,135 @@ namespace Bu { subExceptionDef( UdpSocketException ) }
24#define saTarget ( *((struct sockaddr_in *)paTarget) ) 24#define saTarget ( *((struct sockaddr_in *)paTarget) )
25 25
26Bu::UdpSocket::UdpSocket( int iUdpSocket ) : 26Bu::UdpSocket::UdpSocket( int iUdpSocket ) :
27 iUdpSocket( iUdpSocket ), 27 iUdpSocket( iUdpSocket ),
28 paTarget( NULL ), 28 paTarget( NULL ),
29 bBound( false ) 29 bBound( false )
30{ 30{
31} 31}
32 32
33Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) : 33Bu::UdpSocket::UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ) :
34 iUdpSocket( 0 ), 34 iUdpSocket( 0 ),
35 paTarget( NULL ), 35 paTarget( NULL ),
36 bBound( false ) 36 bBound( false )
37{ 37{
38 iUdpSocket = socket( PF_INET, SOCK_DGRAM, 0 ); 38 iUdpSocket = socket( PF_INET, SOCK_DGRAM, 0 );
39 if( iUdpSocket < 0 ) 39 if( iUdpSocket < 0 )
40 { 40 {
41 throw UdpSocketException("Couldn't open udp socket: %s", 41 throw UdpSocketException("Couldn't open udp socket: %s",
42 strerror( errno ) 42 strerror( errno )
43 ); 43 );
44 } 44 }
45 45
46 if( (iFlags&Broadcast) ) 46 if( (iFlags&Broadcast) )
47 { 47 {
48 int broadcast = 1; 48 int broadcast = 1;
49 if( (setsockopt( iUdpSocket, SOL_SOCKET, SO_BROADCAST, 49 if( (setsockopt( iUdpSocket, SOL_SOCKET, SO_BROADCAST,
50 &broadcast, sizeof(broadcast) )) == -1) 50 &broadcast, sizeof(broadcast) )) == -1)
51 { 51 {
52 throw UdpSocketException("Couldn't set udp socket to broadcast: %s", 52 throw UdpSocketException("Couldn't set udp socket to broadcast: %s",
53 strerror( errno ) 53 strerror( errno )
54 ); 54 );
55 } 55 }
56 } 56 }
57 57
58 paTarget = new struct sockaddr_in; 58 paTarget = new struct sockaddr_in;
59 saTarget.sin_family = AF_INET; 59 saTarget.sin_family = AF_INET;
60 saTarget.sin_port = htons( iPort ); 60 saTarget.sin_port = htons( iPort );
61 saTarget.sin_addr.s_addr = inet_addr( sAddr.getStr() ); // INADDR_ANY; 61 saTarget.sin_addr.s_addr = inet_addr( sAddr.getStr() ); // INADDR_ANY;
62 memset( saTarget.sin_zero, '\0', sizeof(saTarget.sin_zero) ); 62 memset( saTarget.sin_zero, '\0', sizeof(saTarget.sin_zero) );
63 63
64 if( (iFlags&Read) ) 64 if( (iFlags&Read) )
65 { 65 {
66 if( bind( iUdpSocket, (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ) 66 if( bind( iUdpSocket, (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) )
67 == -1 ) 67 == -1 )
68 { 68 {
69 throw UdpSocketException("Couldn't bind port to udp socket: %s", 69 throw UdpSocketException("Couldn't bind port to udp socket: %s",
70 strerror( errno ) 70 strerror( errno )
71 ); 71 );
72 } 72 }
73 bBound = true; 73 bBound = true;
74 } 74 }
75} 75}
76 76
77Bu::UdpSocket::~UdpSocket() 77Bu::UdpSocket::~UdpSocket()
78{ 78{
79 close(); 79 close();
80 delete (struct sockaddr_in *)paTarget; 80 delete (struct sockaddr_in *)paTarget;
81 paTarget = NULL; 81 paTarget = NULL;
82} 82}
83 83
84Bu::String Bu::UdpSocket::addrToStr( const addr &a ) 84Bu::String Bu::UdpSocket::addrToStr( const addr &a )
85{ 85{
86 return Bu::String("%1.%2.%3.%4"). 86 return Bu::String("%1.%2.%3.%4").
87 arg( (a&0xff) ). 87 arg( (a&0xff) ).
88 arg( (a&0xff00)>>8 ). 88 arg( (a&0xff00)>>8 ).
89 arg( (a&0xff0000)>>16 ). 89 arg( (a&0xff0000)>>16 ).
90 arg( (a&0xff000000)>>24 ); 90 arg( (a&0xff000000)>>24 );
91} 91}
92 92
93void Bu::UdpSocket::close() 93void Bu::UdpSocket::close()
94{ 94{
95 ::close( iUdpSocket ); 95 ::close( iUdpSocket );
96} 96}
97 97
98Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes ) 98Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes )
99{ 99{
100 return recv( iUdpSocket, pBuf, nBytes, 0 ); 100 return recv( iUdpSocket, pBuf, nBytes, 0 );
101} 101}
102 102
103Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes, 103Bu::size Bu::UdpSocket::read( void *pBuf, Bu::size nBytes,
104 Bu::UdpSocket::addr &aHost, int &iPort ) 104 Bu::UdpSocket::addr &aHost, int &iPort )
105{ 105{
106 sockaddr_in name; 106 sockaddr_in name;
107 socklen_t size = sizeof(name); 107 socklen_t size = sizeof(name);
108 Bu::size ret = recvfrom( iUdpSocket, pBuf, nBytes, 0, 108 Bu::size ret = recvfrom( iUdpSocket, pBuf, nBytes, 0,
109 (struct sockaddr *)&name, &size ); 109 (struct sockaddr *)&name, &size );
110 aHost = name.sin_addr.s_addr; 110 aHost = name.sin_addr.s_addr;
111 iPort = ntohs(name.sin_port); 111 iPort = ntohs(name.sin_port);
112 return ret; 112 return ret;
113} 113}
114 114
115Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes ) 115Bu::size Bu::UdpSocket::write( const void *pBuf, Bu::size nBytes )
116{ 116{
117 if( bBound ) 117 if( bBound )
118 { 118 {
119 return sendto( iUdpSocket, pBuf, nBytes, 0, NULL, 0 ); 119 return sendto( iUdpSocket, pBuf, nBytes, 0, NULL, 0 );
120 } 120 }
121 else 121 else
122 { 122 {
123 return sendto( iUdpSocket, pBuf, nBytes, 0, 123 return sendto( iUdpSocket, pBuf, nBytes, 0,
124 (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) ); 124 (struct sockaddr*)paTarget, sizeof(struct sockaddr_in) );
125 } 125 }
126} 126}
127 127
128Bu::size Bu::UdpSocket::tell() 128Bu::size Bu::UdpSocket::tell()
129{ 129{
130 throw Bu::UnsupportedException(); 130 throw Bu::UnsupportedException();
131} 131}
132 132
133void Bu::UdpSocket::seek( Bu::size ) 133void Bu::UdpSocket::seek( Bu::size )
134{ 134{
135 throw Bu::UnsupportedException(); 135 throw Bu::UnsupportedException();
136} 136}
137 137
138void Bu::UdpSocket::setPos( Bu::size ) 138void Bu::UdpSocket::setPos( Bu::size )
139{ 139{
140 throw Bu::UnsupportedException(); 140 throw Bu::UnsupportedException();
141} 141}
142 142
143void Bu::UdpSocket::setPosEnd( Bu::size ) 143void Bu::UdpSocket::setPosEnd( Bu::size )
144{ 144{
145 throw Bu::UnsupportedException(); 145 throw Bu::UnsupportedException();
146} 146}
147 147
148bool Bu::UdpSocket::isEos() 148bool Bu::UdpSocket::isEos()
149{ 149{
150 return false; 150 return false;
151} 151}
152 152
153bool Bu::UdpSocket::isOpen() 153bool Bu::UdpSocket::isOpen()
154{ 154{
155 return true; 155 return true;
156} 156}
157 157
158void Bu::UdpSocket::flush() 158void Bu::UdpSocket::flush()
@@ -161,79 +161,79 @@ void Bu::UdpSocket::flush()
161 161
162bool Bu::UdpSocket::canRead() 162bool Bu::UdpSocket::canRead()
163{ 163{
164 return bBound; 164 return bBound;
165} 165}
166 166
167bool Bu::UdpSocket::canWrite() 167bool Bu::UdpSocket::canWrite()
168{ 168{
169 return true; 169 return true;
170} 170}
171 171
172bool Bu::UdpSocket::isReadable() 172bool Bu::UdpSocket::isReadable()
173{ 173{
174 return bBound; 174 return bBound;
175} 175}
176 176
177bool Bu::UdpSocket::isWritable() 177bool Bu::UdpSocket::isWritable()
178{ 178{
179 return true; 179 return true;
180} 180}
181 181
182bool Bu::UdpSocket::isSeekable() 182bool Bu::UdpSocket::isSeekable()
183{ 183{
184 return false; 184 return false;
185} 185}
186 186
187bool Bu::UdpSocket::isBlocking() 187bool Bu::UdpSocket::isBlocking()
188{ 188{
189 return true; 189 return true;
190} 190}
191 191
192void Bu::UdpSocket::setBlocking( bool bBlocking ) 192void Bu::UdpSocket::setBlocking( bool bBlocking )
193{ 193{
194#ifndef WIN32 194#ifndef WIN32
195 if( bBlocking ) 195 if( bBlocking )
196 { 196 {
197 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); 197 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) );
198 } 198 }
199 else 199 else
200 { 200 {
201 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) | O_NONBLOCK ); 201 fcntl( iUdpSocket, F_SETFL, fcntl( iUdpSocket, F_GETFL, 0 ) | O_NONBLOCK );
202 } 202 }
203#else 203#else
204 u_long iMode; 204 u_long iMode;
205 if( bBlocking ) 205 if( bBlocking )
206 iMode = 0; 206 iMode = 0;
207 else 207 else
208 iMode = 1; 208 iMode = 1;
209 //------------------------- 209 //-------------------------
210 // Set the socket I/O mode: In this case FIONBIO 210 // Set the socket I/O mode: In this case FIONBIO
211 // enables or disables the blocking mode for the 211 // enables or disables the blocking mode for the
212 // socket based on the numerical value of iMode. 212 // socket based on the numerical value of iMode.
213 // If iMode = 0, blocking is enabled; 213 // If iMode = 0, blocking is enabled;
214 // If iMode != 0, non-blocking mode is enabled. 214 // If iMode != 0, non-blocking mode is enabled.
215 bu_ioctlsocket(iUdpSocket, FIONBIO, &iMode); 215 bu_ioctlsocket(iUdpSocket, FIONBIO, &iMode);
216#endif 216#endif
217} 217}
218 218
219void Bu::UdpSocket::setSize( Bu::size ) 219void Bu::UdpSocket::setSize( Bu::size )
220{ 220{
221 throw Bu::UnsupportedException(); 221 throw Bu::UnsupportedException();
222} 222}
223 223
224Bu::size Bu::UdpSocket::getSize() const 224Bu::size Bu::UdpSocket::getSize() const
225{ 225{
226 throw Bu::UnsupportedException(); 226 throw Bu::UnsupportedException();
227} 227}
228 228
229Bu::size Bu::UdpSocket::getBlockSize() const 229Bu::size Bu::UdpSocket::getBlockSize() const
230{ 230{
231 return 1500; 231 return 1500;
232} 232}
233 233
234Bu::String Bu::UdpSocket::getLocation() const 234Bu::String Bu::UdpSocket::getLocation() const
235{ 235{
236 throw Bu::UnsupportedException(); 236 throw Bu::UnsupportedException();
237} 237}
238 238
239#endif 239#endif
diff --git a/src/unstable/udpsocket.h b/src/unstable/udpsocket.h
index 8f8630a..569a6fb 100644
--- a/src/unstable/udpsocket.h
+++ b/src/unstable/udpsocket.h
@@ -15,68 +15,68 @@
15 15
16namespace Bu 16namespace Bu
17{ 17{
18 subExceptionDecl( UdpSocketException ); 18 subExceptionDecl( UdpSocketException );
19 19
20 class UdpSocket : public Stream 20 class UdpSocket : public Stream
21 { 21 {
22 public: 22 public:
23 UdpSocket( int iUdpSocket ); 23 UdpSocket( int iUdpSocket );
24 UdpSocket( const Bu::String &sAddr, int iPort, int iFlags ); 24 UdpSocket( const Bu::String &sAddr, int iPort, int iFlags );
25 virtual ~UdpSocket(); 25 virtual ~UdpSocket();
26 26
27 typedef uint32_t addr; 27 typedef uint32_t addr;
28 28
29 static Bu::String addrToStr( const addr &a ); 29 static Bu::String addrToStr( const addr &a );
30 30
31 virtual void close(); 31 virtual void close();
32 virtual Bu::size read( void *pBuf, Bu::size nBytes ); 32 virtual Bu::size read( void *pBuf, Bu::size nBytes );
33 virtual Bu::size read( void *pBuf, Bu::size nBytes, 33 virtual Bu::size read( void *pBuf, Bu::size nBytes,
34 addr &sHost, int &iPort ); 34 addr &sHost, int &iPort );
35 virtual Bu::size write( const void *pBuf, Bu::size nBytes ); 35 virtual Bu::size write( const void *pBuf, Bu::size nBytes );
36 using Stream::write; 36 using Stream::write;
37 37
38 virtual Bu::size tell(); 38 virtual Bu::size tell();
39 virtual void seek( Bu::size offset ); 39 virtual void seek( Bu::size offset );
40 virtual void setPos( Bu::size pos ); 40 virtual void setPos( Bu::size pos );
41 virtual void setPosEnd( Bu::size pos ); 41 virtual void setPosEnd( Bu::size pos );
42 virtual bool isEos(); 42 virtual bool isEos();
43 virtual bool isOpen(); 43 virtual bool isOpen();
44 44
45 virtual void flush(); 45 virtual void flush();
46 46
47 virtual bool canRead(); 47 virtual bool canRead();
48 virtual bool canWrite(); 48 virtual bool canWrite();
49 49
50 virtual bool isReadable(); 50 virtual bool isReadable();
51 virtual bool isWritable(); 51 virtual bool isWritable();
52 virtual bool isSeekable(); 52 virtual bool isSeekable();
53 53
54 virtual bool isBlocking(); 54 virtual bool isBlocking();
55 virtual void setBlocking( bool bBlocking=true ); 55 virtual void setBlocking( bool bBlocking=true );
56 56
57 virtual void setSize( Bu::size iSize ); 57 virtual void setSize( Bu::size iSize );
58 58
59 enum { 59 enum {
60 // Flags 60 // Flags
61 Read = 0x01, ///< Open udp socket for reading 61 Read = 0x01, ///< Open udp socket for reading
62 Write = 0x02, ///< Open udp socket for writing 62 Write = 0x02, ///< Open udp socket for writing
63 ReadWrite = 0x03, ///< Open for both read and write 63 ReadWrite = 0x03, ///< Open for both read and write
64 Broadcast = 0x04, ///< Open for broadcast 64 Broadcast = 0x04, ///< Open for broadcast
65 }; 65 };
66 66
67 virtual size getSize() const; 67 virtual size getSize() const;
68 virtual size getBlockSize() const; 68 virtual size getBlockSize() const;
69 virtual Bu::String getLocation() const; 69 virtual Bu::String getLocation() const;
70 70
71 private: 71 private:
72#ifdef WIN32 72#ifdef WIN32
73 unsigned int iUdpSocket; 73 unsigned int iUdpSocket;
74#else 74#else
75 int iUdpSocket; 75 int iUdpSocket;
76#endif 76#endif
77 void *paTarget; 77 void *paTarget;
78 bool bBound; 78 bool bBound;
79 }; 79 };
80}; 80};
81 81
82#endif 82#endif
diff --git a/src/unstable/url.cpp b/src/unstable/url.cpp
index 3c9da4b..75131af 100644
--- a/src/unstable/url.cpp
+++ b/src/unstable/url.cpp
@@ -13,8 +13,8 @@
13#include <stdlib.h> 13#include <stdlib.h>
14 14
15char Bu::Url::hexcode[] = { 15char Bu::Url::hexcode[] = {
16 '0', '1', '2', '3', '4', '5', '6', '7', 16 '0', '1', '2', '3', '4', '5', '6', '7',
17 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 17 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
18}; 18};
19 19
20Bu::Url::Url() 20Bu::Url::Url()
@@ -23,7 +23,7 @@ Bu::Url::Url()
23 23
24Bu::Url::Url( const Bu::String &sUrl ) 24Bu::Url::Url( const Bu::String &sUrl )
25{ 25{
26 parseUrl( sUrl ); 26 parseUrl( sUrl );
27} 27}
28 28
29Bu::Url::~Url() 29Bu::Url::~Url()
@@ -32,254 +32,254 @@ Bu::Url::~Url()
32 32
33void Bu::Url::parseUrl( const Bu::String &sUrl ) 33void Bu::Url::parseUrl( const Bu::String &sUrl )
34{ 34{
35 clear(); 35 clear();
36 36
37 Bu::String::const_iterator i = sUrl.begin(); 37 Bu::String::const_iterator i = sUrl.begin();
38 parseProtocol( i ); 38 parseProtocol( i );
39 parseUserPass( i ); 39 parseUserPass( i );
40 parseHost( i ); 40 parseHost( i );
41 parsePath( i ); 41 parsePath( i );
42} 42}
43 43
44Bu::String Bu::Url::decode( const Bu::String &sStr ) 44Bu::String Bu::Url::decode( const Bu::String &sStr )
45{ 45{
46 Bu::String sRet; 46 Bu::String sRet;
47 char buf[3] = {0, 0, 0}; 47 char buf[3] = {0, 0, 0};
48 for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) 48 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
49 { 49 {
50 if( *i == '+' ) 50 if( *i == '+' )
51 { 51 {
52 sRet += ' '; 52 sRet += ' ';
53 } 53 }
54 else if( *i == '%' ) 54 else if( *i == '%' )
55 { 55 {
56 i++; 56 i++;
57 buf[0] = *i; 57 buf[0] = *i;
58 i++; 58 i++;
59 buf[1] = *i; 59 buf[1] = *i;
60 sRet += (char)((unsigned char)strtol( buf, NULL, 16 )); 60 sRet += (char)((unsigned char)strtol( buf, NULL, 16 ));
61 } 61 }
62 else 62 else
63 { 63 {
64 sRet += *i; 64 sRet += *i;
65 } 65 }
66 } 66 }
67 return sRet; 67 return sRet;
68} 68}
69 69
70Bu::String Bu::Url::encode( const Bu::String &sStr ) 70Bu::String Bu::Url::encode( const Bu::String &sStr )
71{ 71{
72 Bu::String sRet; 72 Bu::String sRet;
73 for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) 73 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
74 { 74 {
75 if( *i == ' ' ) 75 if( *i == ' ' )
76 { 76 {
77 sRet += '+'; 77 sRet += '+';
78 } 78 }
79 else if( 79 else if(
80 (*i >= 'A' && *i <= 'Z') || 80 (*i >= 'A' && *i <= 'Z') ||
81 (*i >= 'a' && *i <= 'z') || 81 (*i >= 'a' && *i <= 'z') ||
82 (*i >= '0' && *i <= '9') || 82 (*i >= '0' && *i <= '9') ||
83 (*i == '-' || *i == '_' || *i == '.' || *i == '~') 83 (*i == '-' || *i == '_' || *i == '.' || *i == '~')
84 ) 84 )
85 { 85 {
86 sRet += *i; 86 sRet += *i;
87 } 87 }
88 else 88 else
89 { 89 {
90 unsigned char b = *i; 90 unsigned char b = *i;
91 sRet += '%'; 91 sRet += '%';
92 sRet += hexcode[(b>>4)&0xF]; 92 sRet += hexcode[(b>>4)&0xF];
93 sRet += hexcode[b&0xF]; 93 sRet += hexcode[b&0xF];
94 } 94 }
95 } 95 }
96 return sRet; 96 return sRet;
97} 97}
98 98
99void Bu::Url::parseProtocol( Bu::String::const_iterator &i ) 99void Bu::Url::parseProtocol( Bu::String::const_iterator &i )
100{ 100{
101 Bu::String::const_iterator s = i.find("://", 3); 101 Bu::String::const_iterator s = i.find("://", 3);
102 if( !s ) 102 if( !s )
103 throw Bu::ExceptionBase("No :// in url"); 103 throw Bu::ExceptionBase("No :// in url");
104 Bu::String sTmp( i, s ); 104 Bu::String sTmp( i, s );
105 setProtocol( sTmp ); 105 setProtocol( sTmp );
106 i = s + 3; 106 i = s + 3;
107} 107}
108 108
109void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort ) 109void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort )
110{ 110{
111 sProtocol = sNewProto; 111 sProtocol = sNewProto;
112#ifndef WIN32 112#ifndef WIN32
113 if( bAutoSetPort ) 113 if( bAutoSetPort )
114 { 114 {
115 struct servent *se = getservbyname( sProtocol.getStr(), "tcp" ); 115 struct servent *se = getservbyname( sProtocol.getStr(), "tcp" );
116 if( se ) 116 if( se )
117 { 117 {
118 iPort = ntohs( se->s_port ); 118 iPort = ntohs( se->s_port );
119 } 119 }
120 } 120 }
121#endif 121#endif
122} 122}
123 123
124void Bu::Url::parseUserPass( Bu::String::const_iterator &i ) 124void Bu::Url::parseUserPass( Bu::String::const_iterator &i )
125{ 125{
126 Bu::String::const_iterator s = i.find('@'); 126 Bu::String::const_iterator s = i.find('@');
127 if( !s ) 127 if( !s )
128 return; 128 return;
129 129
130 Bu::String::const_iterator p = i.find(':'); 130 Bu::String::const_iterator p = i.find(':');
131 if( p ) 131 if( p )
132 { 132 {
133 sUser.set( i, p ); 133 sUser.set( i, p );
134 sPass.set( p+1, s ); 134 sPass.set( p+1, s );
135 } 135 }
136 else 136 else
137 { 137 {
138 sUser.set( i, s ); 138 sUser.set( i, s );
139 } 139 }
140 140
141 i = s + 1; 141 i = s + 1;
142} 142}
143 143
144void Bu::Url::parseHost( Bu::String::const_iterator &i ) 144void Bu::Url::parseHost( Bu::String::const_iterator &i )
145{ 145{
146 Bu::String::const_iterator s = i; 146 Bu::String::const_iterator s = i;
147 for( ; s && *s != '/'; s++ ) 147 for( ; s && *s != '/'; s++ )
148 { 148 {
149 if( *s == ':' ) 149 if( *s == ':' )
150 { 150 {
151 sHost.set( i, s ); 151 sHost.set( i, s );
152 i = s + 1; 152 i = s + 1;
153 s = i.find('/'); 153 s = i.find('/');
154 Bu::String sPort( i, s ); 154 Bu::String sPort( i, s );
155 iPort = strtol( sPort.getStr(), NULL, 10 ); 155 iPort = strtol( sPort.getStr(), NULL, 10 );
156 i = s; 156 i = s;
157 return; 157 return;
158 } 158 }
159 } 159 }
160 sHost.set( i, s ); 160 sHost.set( i, s );
161 i = s; 161 i = s;
162} 162}
163 163
164void Bu::Url::parsePath( const Bu::String &sPath ) 164void Bu::Url::parsePath( const Bu::String &sPath )
165{ 165{
166 Bu::String::const_iterator i = sPath.begin(); 166 Bu::String::const_iterator i = sPath.begin();
167 parsePath( i ); 167 parsePath( i );
168} 168}
169 169
170void Bu::Url::parsePath( Bu::String::const_iterator &i ) 170void Bu::Url::parsePath( Bu::String::const_iterator &i )
171{ 171{
172 if( i ) 172 if( i )
173 { 173 {
174 Bu::String::const_iterator s = i.find('?'); 174 Bu::String::const_iterator s = i.find('?');
175 sPath.set( i, s ); 175 sPath.set( i, s );
176 i = s + 1; 176 i = s + 1;
177 if( s ) 177 if( s )
178 { 178 {
179 parseParams( i ); 179 parseParams( i );
180 } 180 }
181 } 181 }
182 else 182 else
183 { 183 {
184 sPath = "/"; 184 sPath = "/";
185 } 185 }
186} 186}
187 187
188void Bu::Url::parseParams( const Bu::String &sQuery ) 188void Bu::Url::parseParams( const Bu::String &sQuery )
189{ 189{
190 Bu::String::const_iterator i = sQuery.begin(); 190 Bu::String::const_iterator i = sQuery.begin();
191 parseParams( i ); 191 parseParams( i );
192} 192}
193 193
194void Bu::Url::parseParams( Bu::String::const_iterator &i ) 194void Bu::Url::parseParams( Bu::String::const_iterator &i )
195{ 195{
196 bool bName = true; 196 bool bName = true;
197 Bu::String sName, sValue; 197 Bu::String sName, sValue;
198 for( Bu::String::const_iterator s = i; s; s++ ) 198 for( Bu::String::const_iterator s = i; s; s++ )
199 { 199 {
200 if( bName ) 200 if( bName )
201 { 201 {
202 if( *s == '&' ) 202 if( *s == '&' )
203 { 203 {
204 sName.set( i, s ); 204 sName.set( i, s );
205 sValue.clear(); 205 sValue.clear();
206 i = s + 1; 206 i = s + 1;
207 addParam( decode( sName ), decode( sValue ) ); 207 addParam( decode( sName ), decode( sValue ) );
208 } 208 }
209 else if( *s == '=' ) 209 else if( *s == '=' )
210 { 210 {
211 sName.set( i, s ); 211 sName.set( i, s );
212 i = s + 1; 212 i = s + 1;
213 bName = false; 213 bName = false;
214 } 214 }
215 } 215 }
216 else 216 else
217 { 217 {
218 if( *s == '&' ) 218 if( *s == '&' )
219 { 219 {
220 sValue.set( i, s ); 220 sValue.set( i, s );
221 i = s + 1; 221 i = s + 1;
222 bName = true; 222 bName = true;
223 addParam( decode( sName ), decode( sValue ) ); 223 addParam( decode( sName ), decode( sValue ) );
224 } 224 }
225 } 225 }
226 } 226 }
227 if( i ) 227 if( i )
228 { 228 {
229 if( bName ) 229 if( bName )
230 { 230 {
231 sName.set( i ); 231 sName.set( i );
232 sValue.clear(); 232 sValue.clear();
233 } 233 }
234 else 234 else
235 { 235 {
236 sValue.set( i ); 236 sValue.set( i );
237 } 237 }
238 addParam( decode( sName ), decode( sValue ) ); 238 addParam( decode( sName ), decode( sValue ) );
239 } 239 }
240} 240}
241 241
242void Bu::Url::addParam( const Bu::String &n, const Bu::String &v ) 242void Bu::Url::addParam( const Bu::String &n, const Bu::String &v )
243{ 243{
244 lParam.append( Param( n, v ) ); 244 lParam.append( Param( n, v ) );
245} 245}
246 246
247void Bu::Url::clear() 247void Bu::Url::clear()
248{ 248{
249 sProtocol.clear(); 249 sProtocol.clear();
250 sUser.clear(); 250 sUser.clear();
251 sPass.clear(); 251 sPass.clear();
252 sHost.clear(); 252 sHost.clear();
253 sPath.clear(); 253 sPath.clear();
254 iPort.clear(); 254 iPort.clear();
255} 255}
256 256
257Bu::String Bu::Url::getFullPath() const 257Bu::String Bu::Url::getFullPath() const
258{ 258{
259 Bu::String sBuf = sPath; 259 Bu::String sBuf = sPath;
260 if( !lParam.isEmpty() ) 260 if( !lParam.isEmpty() )
261 { 261 {
262 for( ParamList::const_iterator i = lParam.begin(); i; i++ ) 262 for( ParamList::const_iterator i = lParam.begin(); i; i++ )
263 { 263 {
264 if( i == lParam.begin() ) 264 if( i == lParam.begin() )
265 sBuf += "?"; 265 sBuf += "?";
266 else 266 else
267 sBuf += "&"; 267 sBuf += "&";
268 268
269 sBuf += encode( (*i).sName ); 269 sBuf += encode( (*i).sName );
270 if( !(*i).sValue.isEmpty() ) 270 if( !(*i).sValue.isEmpty() )
271 { 271 {
272 sBuf += "=" + encode( (*i).sValue ); 272 sBuf += "=" + encode( (*i).sValue );
273 } 273 }
274 } 274 }
275 } 275 }
276 276
277 return sBuf; 277 return sBuf;
278} 278}
279 279
280Bu::String Bu::Url::getUrl() const 280Bu::String Bu::Url::getUrl() const
281{ 281{
282 Bu::String sBuf = sProtocol + "://" + sHost + getFullPath(); 282 Bu::String sBuf = sProtocol + "://" + sHost + getFullPath();
283 return sBuf; 283 return sBuf;
284} 284}
285 285
diff --git a/src/unstable/url.h b/src/unstable/url.h
index 34a335d..3edf94b 100644
--- a/src/unstable/url.h
+++ b/src/unstable/url.h
@@ -13,73 +13,73 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class Url 16 class Url
17 { 17 {
18 public: 18 public:
19 typedef struct Param 19 typedef struct Param
20 { 20 {
21 Param() { } 21 Param() { }
22 Param( const Param &r ) : sName( r.sName ), sValue( r.sValue ) { } 22 Param( const Param &r ) : sName( r.sName ), sValue( r.sValue ) { }
23 Param( const Bu::String &n, const Bu::String &v ) : 23 Param( const Bu::String &n, const Bu::String &v ) :
24 sName( n ), sValue( v ) { } 24 sName( n ), sValue( v ) { }
25 Bu::String sName; 25 Bu::String sName;
26 Bu::String sValue; 26 Bu::String sValue;
27 } Param; 27 } Param;
28 typedef Bu::List<Param> ParamList; 28 typedef Bu::List<Param> ParamList;
29 29
30 public: 30 public:
31 Url(); 31 Url();
32 Url( const Bu::String &sUrl ); 32 Url( const Bu::String &sUrl );
33 virtual ~Url(); 33 virtual ~Url();
34 34
35 void parseUrl( const Bu::String &sUrl ); 35 void parseUrl( const Bu::String &sUrl );
36 void parseParams( const Bu::String &sQuery ); 36 void parseParams( const Bu::String &sQuery );
37 void parseParams( Bu::String::const_iterator &i ); 37 void parseParams( Bu::String::const_iterator &i );
38 void parsePath( const Bu::String &sPath ); 38 void parsePath( const Bu::String &sPath );
39 void parsePath( Bu::String::const_iterator &i ); 39 void parsePath( Bu::String::const_iterator &i );
40 void clear(); 40 void clear();
41 41
42 Bu::String getUrl() const; 42 Bu::String getUrl() const;
43 Bu::String getFullPath() const; 43 Bu::String getFullPath() const;
44 44
45 const Bu::String &getProtocol() const { return sProtocol; } 45 const Bu::String &getProtocol() const { return sProtocol; }
46 const Bu::String &getUser() const { return sUser; } 46 const Bu::String &getUser() const { return sUser; }
47 const Bu::String &getPass() const { return sPass; } 47 const Bu::String &getPass() const { return sPass; }
48 const Bu::String &getHost() const { return sHost; } 48 const Bu::String &getHost() const { return sHost; }
49 const Bu::String &getPath() const { return sPath; } 49 const Bu::String &getPath() const { return sPath; }
50 int getPort() const { return iPort; } 50 int getPort() const { return iPort; }
51 ParamList::const_iterator getParamBegin() const 51 ParamList::const_iterator getParamBegin() const
52 { return lParam.begin(); } 52 { return lParam.begin(); }
53 53
54 void setProtocol( const Bu::String &sNewHost, bool bAutoSetPort=true ); 54 void setProtocol( const Bu::String &sNewHost, bool bAutoSetPort=true );
55 void setUser( const Bu::String &s ) { sUser = s; } 55 void setUser( const Bu::String &s ) { sUser = s; }
56 void setPass( const Bu::String &s ) { sPass = s; } 56 void setPass( const Bu::String &s ) { sPass = s; }
57 void setHost( const Bu::String &s ) { sHost = s; } 57 void setHost( const Bu::String &s ) { sHost = s; }
58 void setPath( const Bu::String &s ) { sPath = s; } 58 void setPath( const Bu::String &s ) { sPath = s; }
59 void setPort( int i ) { iPort = i; } 59 void setPort( int i ) { iPort = i; }
60 void addParam( const Bu::String &n, const Bu::String &v ); 60 void addParam( const Bu::String &n, const Bu::String &v );
61 61
62 bool hasPort() const { return iPort.has(); } 62 bool hasPort() const { return iPort.has(); }
63 63
64 static Bu::String decode( const Bu::String &sStr ); 64 static Bu::String decode( const Bu::String &sStr );
65 static Bu::String encode( const Bu::String &sStr ); 65 static Bu::String encode( const Bu::String &sStr );
66 66
67 private: // Parsing code 67 private: // Parsing code
68 void parseProtocol( Bu::String::const_iterator &i ); 68 void parseProtocol( Bu::String::const_iterator &i );
69 void parseUserPass( Bu::String::const_iterator &i ); 69 void parseUserPass( Bu::String::const_iterator &i );
70 void parseHost( Bu::String::const_iterator &i ); 70 void parseHost( Bu::String::const_iterator &i );
71 71
72 private: 72 private:
73 Bu::String sProtocol; 73 Bu::String sProtocol;
74 Bu::String sUser; 74 Bu::String sUser;
75 Bu::String sPass; 75 Bu::String sPass;
76 Bu::String sHost; 76 Bu::String sHost;
77 Bu::String sPath; 77 Bu::String sPath;
78 Bu::Atom<int> iPort; 78 Bu::Atom<int> iPort;
79 ParamList lParam; 79 ParamList lParam;
80 80
81 static char hexcode[16]; 81 static char hexcode[16];
82 }; 82 };
83}; 83};
84 84
85#endif 85#endif
diff --git a/src/unstable/utfstring.cpp b/src/unstable/utfstring.cpp
index 9fe2d02..421d5fb 100644
--- a/src/unstable/utfstring.cpp
+++ b/src/unstable/utfstring.cpp
@@ -20,12 +20,12 @@ Bu::UtfString::UtfString()
20 20
21Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc ) 21Bu::UtfString::UtfString( const Bu::String &sInput, Encoding eEnc )
22{ 22{
23 set( sInput, eEnc ); 23 set( sInput, eEnc );
24} 24}
25 25
26Bu::UtfString::UtfString( const char *sInput, Encoding eEnc ) 26Bu::UtfString::UtfString( const char *sInput, Encoding eEnc )
27{ 27{
28 set( sInput, eEnc ); 28 set( sInput, eEnc );
29} 29}
30 30
31Bu::UtfString::~UtfString() 31Bu::UtfString::~UtfString()
@@ -34,340 +34,340 @@ Bu::UtfString::~UtfString()
34 34
35Bu::UtfString::iterator Bu::UtfString::begin() 35Bu::UtfString::iterator Bu::UtfString::begin()
36{ 36{
37 return Bu::UtfString::iterator( this, 0 ); 37 return Bu::UtfString::iterator( this, 0 );
38} 38}
39 39
40Bu::UtfString::const_iterator Bu::UtfString::begin() const 40Bu::UtfString::const_iterator Bu::UtfString::begin() const
41{ 41{
42 return Bu::UtfString::const_iterator( this, 0 ); 42 return Bu::UtfString::const_iterator( this, 0 );
43} 43}
44 44
45void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc ) 45void Bu::UtfString::set( const Bu::String &sInput, Encoding eEnc )
46{ 46{
47 switch( eEnc ) 47 switch( eEnc )
48 { 48 {
49 case Utf8: 49 case Utf8:
50 setUtf8( sInput ); 50 setUtf8( sInput );
51 break; 51 break;
52 52
53 case Utf16: 53 case Utf16:
54 setUtf16( sInput ); 54 setUtf16( sInput );
55 break; 55 break;
56 56
57 case Utf16be: 57 case Utf16be:
58 setUtf16be( sInput ); 58 setUtf16be( sInput );
59 break; 59 break;
60 60
61 case Utf16le: 61 case Utf16le:
62 setUtf16le( sInput ); 62 setUtf16le( sInput );
63 break; 63 break;
64 64
65 case Utf32: 65 case Utf32:
66 setUtf32( sInput ); 66 setUtf32( sInput );
67 break; 67 break;
68 68
69 case Utf32be: 69 case Utf32be:
70 setUtf32be( sInput ); 70 setUtf32be( sInput );
71 break; 71 break;
72 72
73 case Utf32le: 73 case Utf32le:
74 setUtf32le( sInput ); 74 setUtf32le( sInput );
75 break; 75 break;
76 76
77 case Ucs2: 77 case Ucs2:
78 throw Bu::ExceptionBase("Ucs2 not supported yet."); 78 throw Bu::ExceptionBase("Ucs2 not supported yet.");
79 break; 79 break;
80 80
81 case Ucs4: 81 case Ucs4:
82 throw Bu::ExceptionBase("Ucs4 not supported yet."); 82 throw Bu::ExceptionBase("Ucs4 not supported yet.");
83 break; 83 break;
84 84
85 case GuessEncoding: 85 case GuessEncoding:
86 throw Bu::ExceptionBase("Guessing mode not supported yet."); 86 throw Bu::ExceptionBase("Guessing mode not supported yet.");
87 break; 87 break;
88 } 88 }
89} 89}
90 90
91void Bu::UtfString::append( UtfChar ch ) 91void Bu::UtfString::append( UtfChar ch )
92{ 92{
93 if( ch >= 0x10000 ) 93 if( ch >= 0x10000 )
94 { 94 {
95 ch -= 0x10000; 95 ch -= 0x10000;
96 append16( ((ch>>10)&0x3FF)| 0xD800u ); 96 append16( ((ch>>10)&0x3FF)| 0xD800u );
97 append16( (ch&0x3FF)| 0xDC00u ); 97 append16( (ch&0x3FF)| 0xDC00u );
98 } 98 }
99 else 99 else
100 { 100 {
101 append16( (uint16_t)(ch) ); 101 append16( (uint16_t)(ch) );
102 } 102 }
103} 103}
104 104
105void Bu::UtfString::append( const UtfString &rSrc ) 105void Bu::UtfString::append( const UtfString &rSrc )
106{ 106{
107 aData.append( rSrc.aData ); 107 aData.append( rSrc.aData );
108 iRawLen += rSrc.iRawLen; 108 iRawLen += rSrc.iRawLen;
109 iCharLen += rSrc.iCharLen; 109 iCharLen += rSrc.iCharLen;
110} 110}
111 111
112void Bu::UtfString::setUtf8( const Bu::String &sInput ) 112void Bu::UtfString::setUtf8( const Bu::String &sInput )
113{ 113{
114 static uint8_t lmask[8] = { 114 static uint8_t lmask[8] = {
115 0x00, 115 0x00,
116 0x01, 116 0x01,
117 0x03, 117 0x03,
118 0x07, 118 0x07,
119 0x0f, 119 0x0f,
120 0x1f, 120 0x1f,
121 0x3f, 121 0x3f,
122 0x7f 122 0x7f
123 }; 123 };
124 for( Bu::String::const_iterator i = sInput.begin(); i; i++ ) 124 for( Bu::String::const_iterator i = sInput.begin(); i; i++ )
125 { 125 {
126 if( ((int)(uint8_t)*i)&0x80 ) 126 if( ((int)(uint8_t)*i)&0x80 )
127 { 127 {
128 int iBytes = 1; 128 int iBytes = 1;
129 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { } 129 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { }
130 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1)); 130 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1));
131 for( iBytes--; iBytes >= 1; iBytes-- ) 131 for( iBytes--; iBytes >= 1; iBytes-- )
132 { 132 {
133 i++; 133 i++;
134 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1)); 134 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1));
135 } 135 }
136 append( uPt ); 136 append( uPt );
137 } 137 }
138 else 138 else
139 { 139 {
140 append( (Bu::UtfChar)(*i) ); 140 append( (Bu::UtfChar)(*i) );
141 } 141 }
142 } 142 }
143} 143}
144 144
145void Bu::UtfString::setUtf16( const Bu::String &sInput ) 145void Bu::UtfString::setUtf16( const Bu::String &sInput )
146{ 146{
147// Bu::String::const_iterator i = sInput.begin(); 147// Bu::String::const_iterator i = sInput.begin();
148 if( (uint8_t)*sInput.begin() == 0xFF && 148 if( (uint8_t)*sInput.begin() == 0xFF &&
149 (uint8_t)*(sInput.begin()+1) == 0xFE ) 149 (uint8_t)*(sInput.begin()+1) == 0xFE )
150 { 150 {
151 setUtf16le( sInput ); 151 setUtf16le( sInput );
152 return; 152 return;
153 } 153 }
154 setUtf16be( sInput ); 154 setUtf16be( sInput );
155} 155}
156 156
157void Bu::UtfString::setUtf16be( const Bu::String &sInput ) 157void Bu::UtfString::setUtf16be( const Bu::String &sInput )
158{ 158{
159 Bu::String::const_iterator i = sInput.begin(); 159 Bu::String::const_iterator i = sInput.begin();
160 if( (uint8_t)*sInput.begin() == 0xFE && 160 if( (uint8_t)*sInput.begin() == 0xFE &&
161 (uint8_t)*(sInput.begin()+1) == 0xFF ) 161 (uint8_t)*(sInput.begin()+1) == 0xFF )
162 162
163 { 163 {
164 i += 2; 164 i += 2;
165 sio << "Verified big endian." << sio.nl; 165 sio << "Verified big endian." << sio.nl;
166 } 166 }
167 else 167 else
168 { 168 {
169 sio << "Assuming big endian." << sio.nl; 169 sio << "Assuming big endian." << sio.nl;
170 } 170 }
171 uint16_t hi, lo; 171 uint16_t hi, lo;
172 for( ; i; i++ ) 172 for( ; i; i++ )
173 { 173 {
174 hi = (((uint8_t)*i)<<8) | ((uint8_t)*(++i)); 174 hi = (((uint8_t)*i)<<8) | ((uint8_t)*(++i));
175 append16( hi ); 175 append16( hi );
176 if( (hi&0xD800u) == 0xD800u ) 176 if( (hi&0xD800u) == 0xD800u )
177 { 177 {
178 lo = (((uint8_t)*(++i))<<8) | ((uint8_t)*(++i)); 178 lo = (((uint8_t)*(++i))<<8) | ((uint8_t)*(++i));
179 append16( lo ); 179 append16( lo );
180 } 180 }
181 } 181 }
182} 182}
183 183
184void Bu::UtfString::setUtf16le( const Bu::String &sInput ) 184void Bu::UtfString::setUtf16le( const Bu::String &sInput )
185{ 185{
186 Bu::String::const_iterator i = sInput.begin(); 186 Bu::String::const_iterator i = sInput.begin();
187 if( (uint8_t)*sInput.begin() == 0xFF && 187 if( (uint8_t)*sInput.begin() == 0xFF &&
188 (uint8_t)*(sInput.begin()+1) == 0xFE ) 188 (uint8_t)*(sInput.begin()+1) == 0xFE )
189 { 189 {
190 i += 2; 190 i += 2;
191 sio << "Verified little endian." << sio.nl; 191 sio << "Verified little endian." << sio.nl;
192 } 192 }
193 else 193 else
194 { 194 {
195 sio << "Assuming little endian." << sio.nl; 195 sio << "Assuming little endian." << sio.nl;
196 } 196 }
197 uint16_t hi, lo; 197 uint16_t hi, lo;
198 for( ; i; i++ ) 198 for( ; i; i++ )
199 { 199 {
200 hi = (((uint8_t)*i)) | ((uint8_t)*(++i)<<8); 200 hi = (((uint8_t)*i)) | ((uint8_t)*(++i)<<8);
201 append16( hi ); 201 append16( hi );
202 if( (hi&0xD800u) == 0xD800u ) 202 if( (hi&0xD800u) == 0xD800u )
203 { 203 {
204 lo = (((uint8_t)*(++i))) | ((uint8_t)*(++i)<<8); 204 lo = (((uint8_t)*(++i))) | ((uint8_t)*(++i)<<8);
205 append16( lo ); 205 append16( lo );
206 } 206 }
207 } 207 }
208} 208}
209 209
210void Bu::UtfString::setUtf32( const Bu::String &sInput ) 210void Bu::UtfString::setUtf32( const Bu::String &sInput )
211{ 211{
212 Bu::String::const_iterator i = sInput.begin(); 212 Bu::String::const_iterator i = sInput.begin();
213 if( (uint8_t)*i == 0x00 && 213 if( (uint8_t)*i == 0x00 &&
214 (uint8_t)*(++i) == 0x00 && 214 (uint8_t)*(++i) == 0x00 &&
215 (uint8_t)*(++i) == 0xFF && 215 (uint8_t)*(++i) == 0xFF &&
216 (uint8_t)*(++i) == 0xFE ) 216 (uint8_t)*(++i) == 0xFE )
217 { 217 {
218 setUtf32le( sInput ); 218 setUtf32le( sInput );
219 return; 219 return;
220 } 220 }
221 setUtf32be( sInput ); 221 setUtf32be( sInput );
222} 222}
223 223
224void Bu::UtfString::setUtf32be( const Bu::String &sInput ) 224void Bu::UtfString::setUtf32be( const Bu::String &sInput )
225{ 225{
226 Bu::String::const_iterator i = sInput.begin(); 226 Bu::String::const_iterator i = sInput.begin();
227 if( (uint8_t)*i == 0x00 && 227 if( (uint8_t)*i == 0x00 &&
228 (uint8_t)*(++i) == 0x00 && 228 (uint8_t)*(++i) == 0x00 &&
229 (uint8_t)*(++i) == 0xFE && 229 (uint8_t)*(++i) == 0xFE &&
230 (uint8_t)*(++i) == 0xFF ) 230 (uint8_t)*(++i) == 0xFF )
231 { 231 {
232 i++; 232 i++;
233 sio << "Verified big endian." << sio.nl; 233 sio << "Verified big endian." << sio.nl;
234 } 234 }
235 else 235 else
236 { 236 {
237 i = sInput.begin(); 237 i = sInput.begin();
238 sio << "Assuming big endian." << sio.nl; 238 sio << "Assuming big endian." << sio.nl;
239 } 239 }
240 for( ; i; i++ ) 240 for( ; i; i++ )
241 { 241 {
242 append( (((uint8_t)*i)<<24) | 242 append( (((uint8_t)*i)<<24) |
243 (((uint8_t)*(++i))<<16) | 243 (((uint8_t)*(++i))<<16) |
244 (((uint8_t)*(++i))<<8) | 244 (((uint8_t)*(++i))<<8) |
245 ((uint8_t)*(++i)) 245 ((uint8_t)*(++i))
246 ); 246 );
247 } 247 }
248} 248}
249 249
250void Bu::UtfString::setUtf32le( const Bu::String &sInput ) 250void Bu::UtfString::setUtf32le( const Bu::String &sInput )
251{ 251{
252 Bu::String::const_iterator i = sInput.begin(); 252 Bu::String::const_iterator i = sInput.begin();
253 if( (uint8_t)*i == 0x00 && 253 if( (uint8_t)*i == 0x00 &&
254 (uint8_t)*(++i) == 0x00 && 254 (uint8_t)*(++i) == 0x00 &&
255 (uint8_t)*(++i) == 0xFF && 255 (uint8_t)*(++i) == 0xFF &&
256 (uint8_t)*(++i) == 0xFE ) 256 (uint8_t)*(++i) == 0xFE )
257 { 257 {
258 i++; 258 i++;
259 sio << "Verified little endian." << sio.nl; 259 sio << "Verified little endian." << sio.nl;
260 } 260 }
261 else 261 else
262 { 262 {
263 i = sInput.begin(); 263 i = sInput.begin();
264 sio << "Assuming little endian." << sio.nl; 264 sio << "Assuming little endian." << sio.nl;
265 } 265 }
266 for( ; i; i++ ) 266 for( ; i; i++ )
267 { 267 {
268 append( ((uint8_t)*i) | 268 append( ((uint8_t)*i) |
269 (((uint8_t)*(++i))<<8) | 269 (((uint8_t)*(++i))<<8) |
270 (((uint8_t)*(++i))<<16) | 270 (((uint8_t)*(++i))<<16) |
271 (((uint8_t)*(++i))<<24) 271 (((uint8_t)*(++i))<<24)
272 ); 272 );
273 } 273 }
274} 274}
275 275
276void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const 276void Bu::UtfString::write( Bu::Stream &sOut, Encoding eEnc ) const
277{ 277{
278 switch( eEnc ) 278 switch( eEnc )
279 { 279 {
280 case Utf8: 280 case Utf8:
281 writeUtf8( sOut ); 281 writeUtf8( sOut );
282 break; 282 break;
283 283
284 case Utf16: 284 case Utf16:
285// writeUtf16( sOut ); 285// writeUtf16( sOut );
286// break; 286// break;
287 287
288 case Utf16be: 288 case Utf16be:
289 writeUtf16be( sOut ); 289 writeUtf16be( sOut );
290 break; 290 break;
291 291
292 case Utf16le: 292 case Utf16le:
293 writeUtf16le( sOut ); 293 writeUtf16le( sOut );
294 break; 294 break;
295 295
296 case Utf32: 296 case Utf32:
297// writeUtf32( sOut ); 297// writeUtf32( sOut );
298// break; 298// break;
299 299
300 case Utf32be: 300 case Utf32be:
301 writeUtf32be( sOut ); 301 writeUtf32be( sOut );
302 break; 302 break;
303 303
304 case Utf32le: 304 case Utf32le:
305 writeUtf32le( sOut ); 305 writeUtf32le( sOut );
306 break; 306 break;
307 307
308 case Ucs2: 308 case Ucs2:
309 throw Bu::ExceptionBase("Ucs2 not supported yet."); 309 throw Bu::ExceptionBase("Ucs2 not supported yet.");
310 break; 310 break;
311 311
312 case Ucs4: 312 case Ucs4:
313 throw Bu::ExceptionBase("Ucs4 not supported yet."); 313 throw Bu::ExceptionBase("Ucs4 not supported yet.");
314 break; 314 break;
315 315
316 case GuessEncoding: 316 case GuessEncoding:
317 throw Bu::ExceptionBase( 317 throw Bu::ExceptionBase(
318 "GuessEncoding is incompatible with encoding."); 318 "GuessEncoding is incompatible with encoding.");
319 break; 319 break;
320 320
321 } 321 }
322} 322}
323 323
324void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const 324void Bu::UtfString::writeUtf8( Bu::Stream &sOut ) const
325{ 325{
326 int iPos = 0; 326 int iPos = 0;
327 while( iPos < aData.getSize() ) 327 while( iPos < aData.getSize() )
328 { 328 {
329 uint8_t uByte; 329 uint8_t uByte;
330 Bu::UtfChar chr = nextChar( iPos ); 330 Bu::UtfChar chr = nextChar( iPos );
331 if( chr >= 0x010000 ) 331 if( chr >= 0x010000 )
332 { 332 {
333 // Four bytes 333 // Four bytes
334 // 111 111111 111111 111111 334 // 111 111111 111111 111111
335 uByte = (chr>>18)|0xF0; 335 uByte = (chr>>18)|0xF0;
336 sOut.write( &uByte, 1 ); 336 sOut.write( &uByte, 1 );
337 uByte = ((chr>>12)&0x3F)|0x80; 337 uByte = ((chr>>12)&0x3F)|0x80;
338 sOut.write( &uByte, 1 ); 338 sOut.write( &uByte, 1 );
339 uByte = ((chr>>6)&0x3F)|0x80; 339 uByte = ((chr>>6)&0x3F)|0x80;
340 sOut.write( &uByte, 1 ); 340 sOut.write( &uByte, 1 );
341 uByte = (chr&0x3F)|0x80; 341 uByte = (chr&0x3F)|0x80;
342 sOut.write( &uByte, 1 ); 342 sOut.write( &uByte, 1 );
343 } 343 }
344 else if( chr >= 0x800 ) 344 else if( chr >= 0x800 )
345 { 345 {
346 // Three bytes 346 // Three bytes
347 // 1111 111111 111111 347 // 1111 111111 111111
348 uByte = (chr>>12)|0xE0; 348 uByte = (chr>>12)|0xE0;
349 sOut.write( &uByte, 1 ); 349 sOut.write( &uByte, 1 );
350 uByte = ((chr>>6)&0x3F)|0x80; 350 uByte = ((chr>>6)&0x3F)|0x80;
351 sOut.write( &uByte, 1 ); 351 sOut.write( &uByte, 1 );
352 uByte = (chr&0x3F)|0x80; 352 uByte = (chr&0x3F)|0x80;
353 sOut.write( &uByte, 1 ); 353 sOut.write( &uByte, 1 );
354 } 354 }
355 else if( chr >= 0x80 ) 355 else if( chr >= 0x80 )
356 { 356 {
357 // Two bytes 357 // Two bytes
358 // 11111 111111 358 // 11111 111111
359 uByte = (chr>>6)|0xC0; 359 uByte = (chr>>6)|0xC0;
360 sOut.write( &uByte, 1 ); 360 sOut.write( &uByte, 1 );
361 uByte = (chr&0x3F)|0x80; 361 uByte = (chr&0x3F)|0x80;
362 sOut.write( &uByte, 1 ); 362 sOut.write( &uByte, 1 );
363 } 363 }
364 else 364 else
365 { 365 {
366 // One byte 366 // One byte
367 uByte = chr; 367 uByte = chr;
368 sOut.write( &uByte, 1 ); 368 sOut.write( &uByte, 1 );
369 } 369 }
370 } 370 }
371} 371}
372/* 372/*
373void Bu::UtfString::writeUtf16( Bu::Stream &sOut ) 373void Bu::UtfString::writeUtf16( Bu::Stream &sOut )
@@ -377,228 +377,228 @@ void Bu::UtfString::writeUtf16( Bu::Stream &sOut )
377void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const 377void Bu::UtfString::writeUtf16be( Bu::Stream &sOut ) const
378{ 378{
379#if BYTE_ORDER == BIG_ENDIAN 379#if BYTE_ORDER == BIG_ENDIAN
380 uint16_t iTmp = 0xFEFF; // Byte Order Marker 380 uint16_t iTmp = 0xFEFF; // Byte Order Marker
381 sOut.write( &iTmp, 2 ); 381 sOut.write( &iTmp, 2 );
382 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 382 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
383 { 383 {
384 iTmp = *i; 384 iTmp = *i;
385 sOut.write( &iTmp, 2 ); 385 sOut.write( &iTmp, 2 );
386 } 386 }
387#else 387#else
388 uint16_t iTmp = 0xFEFF; // Byte Order Marker 388 uint16_t iTmp = 0xFEFF; // Byte Order Marker
389 iTmp = (iTmp>>8) | (iTmp<<8); 389 iTmp = (iTmp>>8) | (iTmp<<8);
390 sOut.write( &iTmp, 2 ); 390 sOut.write( &iTmp, 2 );
391 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 391 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
392 { 392 {
393 iTmp = *i; 393 iTmp = *i;
394 iTmp = (iTmp>>8) | (iTmp<<8); 394 iTmp = (iTmp>>8) | (iTmp<<8);
395 sOut.write( &iTmp, 2 ); 395 sOut.write( &iTmp, 2 );
396 } 396 }
397#endif 397#endif
398} 398}
399 399
400void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const 400void Bu::UtfString::writeUtf16le( Bu::Stream &sOut ) const
401{ 401{
402#if BYTE_ORDER == LITTLE_ENDIAN 402#if BYTE_ORDER == LITTLE_ENDIAN
403 uint16_t iTmp = 0xFEFF; // Byte Order Marker 403 uint16_t iTmp = 0xFEFF; // Byte Order Marker
404 sOut.write( &iTmp, 2 ); 404 sOut.write( &iTmp, 2 );
405 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 405 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
406 { 406 {
407 iTmp = *i; 407 iTmp = *i;
408 sOut.write( &iTmp, 2 ); 408 sOut.write( &iTmp, 2 );
409 } 409 }
410#else 410#else
411 uint16_t iTmp = 0xFEFF; // Byte Order Marker 411 uint16_t iTmp = 0xFEFF; // Byte Order Marker
412 iTmp = (iTmp>>8) | (iTmp<<8); 412 iTmp = (iTmp>>8) | (iTmp<<8);
413 sOut.write( &iTmp, 2 ); 413 sOut.write( &iTmp, 2 );
414 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ ) 414 for( Array<uint16_t>::const_iterator i = aData.begin(); i; i++ )
415 { 415 {
416 iTmp = *i; 416 iTmp = *i;
417 iTmp = (iTmp>>8) | (iTmp<<8); 417 iTmp = (iTmp>>8) | (iTmp<<8);
418 sOut.write( &iTmp, 2 ); 418 sOut.write( &iTmp, 2 );
419 } 419 }
420#endif 420#endif
421} 421}
422 422
423void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const 423void Bu::UtfString::writeUtf32be( Bu::Stream &sOut ) const
424{ 424{
425#if BYTE_ORDER == BIG_ENDIAN 425#if BYTE_ORDER == BIG_ENDIAN
426 uint32_t iTmp = 0xFEFF; // Byte Order Marker 426 uint32_t iTmp = 0xFEFF; // Byte Order Marker
427 sOut.write( &iTmp, 4 ); 427 sOut.write( &iTmp, 4 );
428 int i = 0; 428 int i = 0;
429 while( i < aData.getSize() ) 429 while( i < aData.getSize() )
430 { 430 {
431 iTmp = nextChar( i ); 431 iTmp = nextChar( i );
432 sOut.write( &iTmp, 4 ); 432 sOut.write( &iTmp, 4 );
433 } 433 }
434#else 434#else
435 uint32_t iTmp = 0xFEFF; // Byte Order Marker 435 uint32_t iTmp = 0xFEFF; // Byte Order Marker
436 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 436 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
437 sOut.write( &iTmp, 4 ); 437 sOut.write( &iTmp, 4 );
438 int i = 0; 438 int i = 0;
439 while( i < aData.getSize() ) 439 while( i < aData.getSize() )
440 { 440 {
441 iTmp = nextChar( i ); 441 iTmp = nextChar( i );
442 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 442 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
443 sOut.write( &iTmp, 4 ); 443 sOut.write( &iTmp, 4 );
444 } 444 }
445#endif 445#endif
446} 446}
447 447
448void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const 448void Bu::UtfString::writeUtf32le( Bu::Stream &sOut ) const
449{ 449{
450#if BYTE_ORDER == LITTLE_ENDIAN 450#if BYTE_ORDER == LITTLE_ENDIAN
451 uint32_t iTmp = 0xFEFF; // Byte Order Marker 451 uint32_t iTmp = 0xFEFF; // Byte Order Marker
452 sOut.write( &iTmp, 4 ); 452 sOut.write( &iTmp, 4 );
453 int i = 0; 453 int i = 0;
454 while( i < aData.getSize() ) 454 while( i < aData.getSize() )
455 { 455 {
456 iTmp = nextChar( i ); 456 iTmp = nextChar( i );
457 sOut.write( &iTmp, 4 ); 457 sOut.write( &iTmp, 4 );
458 } 458 }
459#else 459#else
460 uint32_t iTmp = 0xFEFF; // Byte Order Marker 460 uint32_t iTmp = 0xFEFF; // Byte Order Marker
461 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 461 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
462 sOut.write( &iTmp, 4 ); 462 sOut.write( &iTmp, 4 );
463 int i = 0; 463 int i = 0;
464 while( i < aData.getSize() ) 464 while( i < aData.getSize() )
465 { 465 {
466 iTmp = nextChar( i ); 466 iTmp = nextChar( i );
467 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8); 467 iTmp = (iTmp>>24)|(iTmp<<24)|((iTmp&0xff0000)>>8)|((iTmp&0xff00)<<8);
468 sOut.write( &iTmp, 4 ); 468 sOut.write( &iTmp, 4 );
469 } 469 }
470#endif 470#endif
471} 471}
472 472
473Bu::UtfChar Bu::UtfString::get( int iIndex ) const 473Bu::UtfChar Bu::UtfString::get( int iIndex ) const
474{ 474{
475 return nextChar( iIndex ); 475 return nextChar( iIndex );
476} 476}
477 477
478Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const 478Bu::UtfChar Bu::UtfString::nextChar( int &iIndex ) const
479{ 479{
480 Bu::UtfChar i = aData[iIndex++]; 480 Bu::UtfChar i = aData[iIndex++];
481 switch( i&0xFC00 ) 481 switch( i&0xFC00 )
482 { 482 {
483 case 0xD800: 483 case 0xD800:
484 return (((i&0x3FF)<<10) | ((aData[iIndex++]&0x3FF)))+0x10000; 484 return (((i&0x3FF)<<10) | ((aData[iIndex++]&0x3FF)))+0x10000;
485 485
486 case 0xDC00: 486 case 0xDC00:
487 return (((aData[iIndex-2]&0x3FF)<<10) | ((i&0x3FF)))+0x10000; 487 return (((aData[iIndex-2]&0x3FF)<<10) | ((i&0x3FF)))+0x10000;
488 488
489 default: 489 default:
490 return i; 490 return i;
491 } 491 }
492} 492}
493 493
494bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const 494bool Bu::UtfString::operator==( const Bu::UtfString &rhs ) const
495{ 495{
496 return aData == rhs.aData; 496 return aData == rhs.aData;
497} 497}
498 498
499Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs ) 499Bu::UtfString &Bu::UtfString::operator+=( const Bu::UtfString &rhs )
500{ 500{
501 append( rhs ); 501 append( rhs );
502 return *this; 502 return *this;
503} 503}
504 504
505Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs ) 505Bu::UtfString &Bu::UtfString::operator+=( const UtfChar &rhs )
506{ 506{
507 append( rhs ); 507 append( rhs );
508 return *this; 508 return *this;
509} 509}
510 510
511Bu::String Bu::UtfString::get( Encoding eEnc ) const 511Bu::String Bu::UtfString::get( Encoding eEnc ) const
512{ 512{
513 Bu::MemBuf mb; 513 Bu::MemBuf mb;
514 write( mb, eEnc ); 514 write( mb, eEnc );
515 return mb.getString(); 515 return mb.getString();
516} 516}
517 517
518void Bu::UtfString::debug() const 518void Bu::UtfString::debug() const
519{ 519{
520 sio << "Raw Utf16: "; 520 sio << "Raw Utf16: ";
521 for( int i = 0; i < aData.getSize(); i++ ) 521 for( int i = 0; i < aData.getSize(); i++ )
522 { 522 {
523 if( i > 0 ) 523 if( i > 0 )
524 sio << ", "; 524 sio << ", ";
525 sio << "0x" << Fmt::hex() << aData[i]; 525 sio << "0x" << Fmt::hex() << aData[i];
526 } 526 }
527 sio << sio.nl; 527 sio << sio.nl;
528 sio << "Code Points: "; 528 sio << "Code Points: ";
529 for( int i = 0; i < aData.getSize(); i++ ) 529 for( int i = 0; i < aData.getSize(); i++ )
530 { 530 {
531 if( i > 0 ) 531 if( i > 0 )
532 sio << ", "; 532 sio << ", ";
533 sio << "0x" << Fmt::hex() << nextChar( i ); 533 sio << "0x" << Fmt::hex() << nextChar( i );
534 } 534 }
535 sio << sio.nl; 535 sio << sio.nl;
536} 536}
537/* 537/*
538void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 ) 538void Bu::UtfString::debugUtf8( const Bu::String &sUtf8 )
539{ 539{
540 static uint8_t lmask[8] = { 540 static uint8_t lmask[8] = {
541 0x00, 541 0x00,
542 0x01, 542 0x01,
543 0x03, 543 0x03,
544 0x07, 544 0x07,
545 0x0f, 545 0x0f,
546 0x1f, 546 0x1f,
547 0x3f, 547 0x3f,
548 0x7f 548 0x7f
549 }; 549 };
550 for( Bu::String::const_iterator i = sUtf8.begin(); i; i++ ) 550 for( Bu::String::const_iterator i = sUtf8.begin(); i; i++ )
551 { 551 {
552 if( i != sUtf8.begin() ) 552 if( i != sUtf8.begin() )
553 sio << ", "; 553 sio << ", ";
554 if( ((int)(uint8_t)*i)&0x80 ) 554 if( ((int)(uint8_t)*i)&0x80 )
555 { 555 {
556// sio << "Flag byte: " << Bu::Fmt().radix(2).width(8).fill('0') 556// sio << "Flag byte: " << Bu::Fmt().radix(2).width(8).fill('0')
557// << (int)(uint8_t)*i << sio.nl; 557// << (int)(uint8_t)*i << sio.nl;
558 int iBytes = 1; 558 int iBytes = 1;
559 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { } 559 for(; (((uint8_t)(*i))<<iBytes)&0x80; iBytes++ ) { }
560// sio << "iBytes = " << iBytes << sio.nl; 560// sio << "iBytes = " << iBytes << sio.nl;
561 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1)); 561 Bu::UtfChar uPt = ((*i) & lmask[7-iBytes])<<(6*(iBytes-1));
562// sio << "mask: " << Bu::Fmt().radix(2).width(8).fill('0') 562// sio << "mask: " << Bu::Fmt().radix(2).width(8).fill('0')
563// << (int)lmask[7-iBytes] << sio.nl; 563// << (int)lmask[7-iBytes] << sio.nl;
564 for( iBytes--; iBytes >= 1; iBytes-- ) 564 for( iBytes--; iBytes >= 1; iBytes-- )
565 { 565 {
566// sio << "iBytes = " << iBytes << ", shift = " << (6*(iBytes-1)) 566// sio << "iBytes = " << iBytes << ", shift = " << (6*(iBytes-1))
567// << sio.nl; 567// << sio.nl;
568// sio << "next: " << Bu::Fmt().radix(2).width(8).fill('0') 568// sio << "next: " << Bu::Fmt().radix(2).width(8).fill('0')
569// << (int)(uint8_t)*i << sio.nl 569// << (int)(uint8_t)*i << sio.nl
570// << "mask: " << Bu::Fmt().radix(2).width(8).fill('0') 570// << "mask: " << Bu::Fmt().radix(2).width(8).fill('0')
571// << (int)lmask[6] << sio.nl; 571// << (int)lmask[6] << sio.nl;
572 i++; 572 i++;
573 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1)); 573 uPt |= ((*i)&lmask[6])<<(6*(iBytes-1));
574 } 574 }
575 sio << uPt; 575 sio << uPt;
576// sio << " (" << Bu::Fmt( 8, 2 ).fill('0') 576// sio << " (" << Bu::Fmt( 8, 2 ).fill('0')
577// << uPt << ")"; 577// << uPt << ")";
578 } 578 }
579 else 579 else
580 { 580 {
581 sio << (int)((uint8_t)*i); 581 sio << (int)((uint8_t)*i);
582 } 582 }
583 } 583 }
584 sio << sio.nl; 584 sio << sio.nl;
585} 585}
586*/ 586*/
587 587
588template<> uint32_t Bu::__calcHashCode<Bu::UtfString>( const Bu::UtfString &k ) 588template<> uint32_t Bu::__calcHashCode<Bu::UtfString>( const Bu::UtfString &k )
589{ 589{
590 uint32_t uCode = 0; 590 uint32_t uCode = 0;
591 591
592 for( Bu::UtfString::const_iterator i = k.begin(); i; i++ ) 592 for( Bu::UtfString::const_iterator i = k.begin(); i; i++ )
593 { 593 {
594 uCode = *i + (uCode<<6) + (uCode<<16) - uCode; 594 uCode = *i + (uCode<<6) + (uCode<<16) - uCode;
595 } 595 }
596 596
597 return uCode; 597 return uCode;
598} 598}
599 599
600template<> bool Bu::__cmpHashKeys<Bu::UtfString>( 600template<> bool Bu::__cmpHashKeys<Bu::UtfString>(
601 const Bu::UtfString &a, const Bu::UtfString &b ) 601 const Bu::UtfString &a, const Bu::UtfString &b )
602{ 602{
603 return a == b; 603 return a == b;
604} 604}
diff --git a/src/unstable/utfstring.h b/src/unstable/utfstring.h
index 1bd4cce..560faae 100644
--- a/src/unstable/utfstring.h
+++ b/src/unstable/utfstring.h
@@ -13,247 +13,247 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class String; 16 class String;
17 class Stream; 17 class Stream;
18 18
19 /** 19 /**
20 * UtfChar isn't actually a character, unicode specifies "code points" not 20 * UtfChar isn't actually a character, unicode specifies "code points" not
21 * characters. The main reason for this is that not all code points define 21 * characters. The main reason for this is that not all code points define
22 * usable characters. Some control text directionality, some apply 22 * usable characters. Some control text directionality, some apply
23 * properties to other code points which are characters. However, most of 23 * properties to other code points which are characters. However, most of
24 * these distinctions are only important when implementing displays that 24 * these distinctions are only important when implementing displays that
25 * comply with the Unicode standard fully. 25 * comply with the Unicode standard fully.
26 */ 26 */
27 typedef uint32_t UtfChar; 27 typedef uint32_t UtfChar;
28 28
29 /** 29 /**
30 * A unicode string. This class represents a string of unicode code points. 30 * A unicode string. This class represents a string of unicode code points.
31 * Every character in unicode can be represented with 21 bits, but we don't 31 * Every character in unicode can be represented with 21 bits, but we don't
32 * have a datatype that's 24 bits long, so we return all code points as a 32 * have a datatype that's 24 bits long, so we return all code points as a
33 * 32 bit unsigned value represented by Bu::UtfChar. However, the UtfString 33 * 32 bit unsigned value represented by Bu::UtfChar. However, the UtfString
34 * class, for efficiency purposes doesn't store 32 bit values internally. 34 * class, for efficiency purposes doesn't store 32 bit values internally.
35 * It represents all code points in the native utf16 encodeng. This means 35 * It represents all code points in the native utf16 encodeng. This means
36 * that it may be very difficult to quickly determine the length of a 36 * that it may be very difficult to quickly determine the length of a
37 * UtfString in code points. Unlike many Unicode handling systems, this 37 * UtfString in code points. Unlike many Unicode handling systems, this
38 * one actually works with complete code points. When using this class you 38 * one actually works with complete code points. When using this class you
39 * don't ever have to know about the inner workings of the different 39 * don't ever have to know about the inner workings of the different
40 * encoding schemes. All of the data is dealt with as whole code points. 40 * encoding schemes. All of the data is dealt with as whole code points.
41 * 41 *
42 * As an aside, this means that when encoding a UtfString to a Utf16 42 * As an aside, this means that when encoding a UtfString to a Utf16
43 * encoding that matches your archetecture this operation will be very 43 * encoding that matches your archetecture this operation will be very
44 * fast since it will effectively be a raw dump of the internal data 44 * fast since it will effectively be a raw dump of the internal data
45 * structures. However, it is highly reccomended that you DO NOT use the 45 * structures. However, it is highly reccomended that you DO NOT use the
46 * little endian encodings if you can possibly avoid it. They are not 46 * little endian encodings if you can possibly avoid it. They are not
47 * reccomended by the Unicode Consortium and are mainly supported as a 47 * reccomended by the Unicode Consortium and are mainly supported as a
48 * means of communicating with other systems that encode their data 48 * means of communicating with other systems that encode their data
49 * incorrectly. That said, whenever UtfString encodes the contained string 49 * incorrectly. That said, whenever UtfString encodes the contained string
50 * it always includes a BOM at the begining (the byte order marker) so that 50 * it always includes a BOM at the begining (the byte order marker) so that
51 * proper byte order can be easily determined by the program reading the 51 * proper byte order can be easily determined by the program reading the
52 * data. 52 * data.
53 * 53 *
54 *@todo Investigate http://www.unicode.org/reports/tr6/ for compression. 54 *@todo Investigate http://www.unicode.org/reports/tr6/ for compression.
55 */ 55 */
56 class UtfString 56 class UtfString
57 { 57 {
58 public: 58 public:
59 enum Encoding 59 enum Encoding
60 { 60 {
61 Utf8, 61 Utf8,
62 Utf16, 62 Utf16,
63 Utf16be, 63 Utf16be,
64 Utf16le, 64 Utf16le,
65 Utf32, 65 Utf32,
66 Utf32be, 66 Utf32be,
67 Utf32le, 67 Utf32le,
68 Ucs2, 68 Ucs2,
69 Ucs4, 69 Ucs4,
70 GuessEncoding 70 GuessEncoding
71 }; 71 };
72 72
73 UtfString(); 73 UtfString();
74 UtfString( const Bu::String &sInput, Encoding eEnc=Utf8 ); 74 UtfString( const Bu::String &sInput, Encoding eEnc=Utf8 );
75 UtfString( const char *sInput, Encoding eEnc=Utf8 ); 75 UtfString( const char *sInput, Encoding eEnc=Utf8 );
76 virtual ~UtfString(); 76 virtual ~UtfString();
77 77
78 class iterator 78 class iterator
79 { 79 {
80 friend class UtfString; 80 friend class UtfString;
81 private: 81 private:
82 iterator( UtfString *pSrc, int iCodePos ) : 82 iterator( UtfString *pSrc, int iCodePos ) :
83 pSrc( pSrc ), iCodePos( iCodePos ) 83 pSrc( pSrc ), iCodePos( iCodePos )
84 { 84 {
85 } 85 }
86 86
87 public: 87 public:
88 iterator() : 88 iterator() :
89 pSrc( NULL ), iCodePos( 0 ) 89 pSrc( NULL ), iCodePos( 0 )
90 { 90 {
91 } 91 }
92 92
93 UtfChar operator*() 93 UtfChar operator*()
94 { 94 {
95 if( !pSrc ) 95 if( !pSrc )
96 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); 96 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced.");
97 return pSrc->get( iCodePos ); 97 return pSrc->get( iCodePos );
98 } 98 }
99 99
100 iterator operator++() 100 iterator operator++()
101 { 101 {
102 pSrc->nextChar( iCodePos ); 102 pSrc->nextChar( iCodePos );
103 return *this; 103 return *this;
104 } 104 }
105 105
106 iterator operator++( int ) 106 iterator operator++( int )
107 { 107 {
108 pSrc->nextChar( iCodePos ); 108 pSrc->nextChar( iCodePos );
109 return *this; 109 return *this;
110 } 110 }
111 111
112 operator bool() const 112 operator bool() const
113 { 113 {
114 return iCodePos < pSrc->aData.getSize(); 114 return iCodePos < pSrc->aData.getSize();
115 } 115 }
116 116
117 private: 117 private:
118 UtfString *pSrc; 118 UtfString *pSrc;
119 int iCodePos; 119 int iCodePos;
120 }; 120 };
121 121
122 class const_iterator 122 class const_iterator
123 { 123 {
124 friend class UtfString; 124 friend class UtfString;
125 private: 125 private:
126 const_iterator( const UtfString *pSrc, int iCodePos ) : 126 const_iterator( const UtfString *pSrc, int iCodePos ) :
127 pSrc( pSrc ), iCodePos( iCodePos ) 127 pSrc( pSrc ), iCodePos( iCodePos )
128 { 128 {
129 } 129 }
130 130
131 public: 131 public:
132 const_iterator() : 132 const_iterator() :
133 pSrc( NULL ), iCodePos( 0 ) 133 pSrc( NULL ), iCodePos( 0 )
134 { 134 {
135 } 135 }
136 136
137 UtfChar operator*() 137 UtfChar operator*()
138 { 138 {
139 if( !pSrc ) 139 if( !pSrc )
140 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced."); 140 throw Bu::ExceptionBase("invalid UtfString::iterator dereferenced.");
141 return pSrc->get( iCodePos ); 141 return pSrc->get( iCodePos );
142 } 142 }
143 143
144 const_iterator operator++() 144 const_iterator operator++()
145 { 145 {
146 pSrc->nextChar( iCodePos ); 146 pSrc->nextChar( iCodePos );
147 return *this; 147 return *this;
148 } 148 }
149 149
150 const_iterator operator++( int ) 150 const_iterator operator++( int )
151 { 151 {
152 pSrc->nextChar( iCodePos ); 152 pSrc->nextChar( iCodePos );
153 return *this; 153 return *this;
154 } 154 }
155 155
156 operator bool() const 156 operator bool() const
157 { 157 {
158 return iCodePos < pSrc->aData.getSize(); 158 return iCodePos < pSrc->aData.getSize();
159 } 159 }
160 160
161 private: 161 private:
162 const UtfString *pSrc; 162 const UtfString *pSrc;
163 int iCodePos; 163 int iCodePos;
164 }; 164 };
165 165
166 iterator begin(); 166 iterator begin();
167 const_iterator begin() const; 167 const_iterator begin() const;
168 168
169 /** 169 /**
170 * Append a UtfChar (A unicode code point) to the string. This can be 170 * Append a UtfChar (A unicode code point) to the string. This can be
171 * any valid code point, and is just the value of the code point, no 171 * any valid code point, and is just the value of the code point, no
172 * encoding necessary. 172 * encoding necessary.
173 */ 173 */
174 void append( UtfChar ch ); 174 void append( UtfChar ch );
175 175
176 void append( const UtfString &rSrc ); 176 void append( const UtfString &rSrc );
177 177
178 /** 178 /**
179 * Set the value of the entire string based on the given input and 179 * Set the value of the entire string based on the given input and
180 * encoding. The default encoding is Utf8, which is compatible with 180 * encoding. The default encoding is Utf8, which is compatible with
181 * 7-bit ascii, so it's a great choice for setting UtfStrings from 181 * 7-bit ascii, so it's a great choice for setting UtfStrings from
182 * string literals in code. 182 * string literals in code.
183 */ 183 */
184 void set( const Bu::String &sInput, Encoding eEnc=Utf8 ); 184 void set( const Bu::String &sInput, Encoding eEnc=Utf8 );
185 185
186 /** 186 /**
187 * This encodes the UtfString in the given encoding and outputs it to 187 * This encodes the UtfString in the given encoding and outputs it to
188 * the provided stream. all Utf16 and Utf32 encodings will have the 188 * the provided stream. all Utf16 and Utf32 encodings will have the
189 * correct BOM (byte order marker) at the begining. 189 * correct BOM (byte order marker) at the begining.
190 */ 190 */
191 void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ) const; 191 void write( Bu::Stream &sOut, Encoding eEnc=Utf8 ) const;
192 192
193 /** 193 /**
194 * This encodes the UtfString in the given encoding and returns it as 194 * This encodes the UtfString in the given encoding and returns it as
195 * a binary Bu::String. Like write, this also includes the proper BOM 195 * a binary Bu::String. Like write, this also includes the proper BOM
196 * at the begining. 196 * at the begining.
197 */ 197 */
198 Bu::String get( Encoding eEnc=Utf8 ) const; 198 Bu::String get( Encoding eEnc=Utf8 ) const;
199 199
200 void debug() const; 200 void debug() const;
201 201
202 /** 202 /**
203 * This may or may not stick around, given an index, this returns a 203 * This may or may not stick around, given an index, this returns a
204 * codepoint, however there isn't necesarilly a 1:1 ratio between 204 * codepoint, however there isn't necesarilly a 1:1 ratio between
205 * indexes and code points. 205 * indexes and code points.
206 */ 206 */
207 UtfChar get( int iIndex ) const; 207 UtfChar get( int iIndex ) const;
208 208
209 /** 209 /**
210 * This is what to use if you want to iterate through a section of the 210 * This is what to use if you want to iterate through a section of the
211 * UtfString and you want to use a numerical index. In most cases it 211 * UtfString and you want to use a numerical index. In most cases it
212 * will be much easier to use an iterator, though. Given an index this 212 * will be much easier to use an iterator, though. Given an index this
213 * will return the codepoint at that position and increment iIndex an 213 * will return the codepoint at that position and increment iIndex an
214 * appropriate amount for it to point to the next code point. 214 * appropriate amount for it to point to the next code point.
215 */ 215 */
216 UtfChar nextChar( int &iIndex ) const; 216 UtfChar nextChar( int &iIndex ) const;
217 217
218 bool operator==( const Bu::UtfString &rhs ) const; 218 bool operator==( const Bu::UtfString &rhs ) const;
219 UtfString &operator+=( const Bu::UtfString &rhs ); 219 UtfString &operator+=( const Bu::UtfString &rhs );
220 UtfString &operator+=( const UtfChar &rhs ); 220 UtfString &operator+=( const UtfChar &rhs );
221 221
222 private: 222 private:
223 void append16( uint16_t i ) { aData.append( i ); } 223 void append16( uint16_t i ) { aData.append( i ); }
224 224
225 void setUtf8( const Bu::String &sInput ); 225 void setUtf8( const Bu::String &sInput );
226 void setUtf16( const Bu::String &sInput ); 226 void setUtf16( const Bu::String &sInput );
227 void setUtf16be( const Bu::String &sInput ); 227 void setUtf16be( const Bu::String &sInput );
228 void setUtf16le( const Bu::String &sInput ); 228 void setUtf16le( const Bu::String &sInput );
229 void setUtf32( const Bu::String &sInput ); 229 void setUtf32( const Bu::String &sInput );
230 void setUtf32be( const Bu::String &sInput ); 230 void setUtf32be( const Bu::String &sInput );
231 void setUtf32le( const Bu::String &sInput ); 231 void setUtf32le( const Bu::String &sInput );
232 232
233 void writeUtf8( Bu::Stream &sOut ) const; 233 void writeUtf8( Bu::Stream &sOut ) const;
234 void writeUtf16be( Bu::Stream &sOut ) const; 234 void writeUtf16be( Bu::Stream &sOut ) const;
235 void writeUtf16le( Bu::Stream &sOut ) const; 235 void writeUtf16le( Bu::Stream &sOut ) const;
236 void writeUtf32be( Bu::Stream &sOut ) const; 236 void writeUtf32be( Bu::Stream &sOut ) const;
237 void writeUtf32le( Bu::Stream &sOut ) const; 237 void writeUtf32le( Bu::Stream &sOut ) const;
238 238
239 private: 239 private:
240 Bu::Array<uint16_t> aData; 240 Bu::Array<uint16_t> aData;
241 int iRawLen; 241 int iRawLen;
242 int iCharLen; 242 int iCharLen;
243 }; 243 };
244 244
245 // 245 //
246 // Hash support 246 // Hash support
247 // 247 //
248 template<typename T> 248 template<typename T>
249 uint32_t __calcHashCode( const T &k ); 249 uint32_t __calcHashCode( const T &k );
250 250
251 template<typename T> 251 template<typename T>
252 bool __cmpHashKeys( const T &a, const T &b ); 252 bool __cmpHashKeys( const T &a, const T &b );
253 253
254 template<> uint32_t __calcHashCode<UtfString>( const UtfString &k ); 254 template<> uint32_t __calcHashCode<UtfString>( const UtfString &k );
255 template<> bool __cmpHashKeys<UtfString>( 255 template<> bool __cmpHashKeys<UtfString>(
256 const UtfString &a, const UtfString &b ); 256 const UtfString &a, const UtfString &b );
257}; 257};
258 258
259#endif 259#endif
diff --git a/src/unstable/uuid.cpp b/src/unstable/uuid.cpp
index aef8bc0..5400f8f 100644
--- a/src/unstable/uuid.cpp
+++ b/src/unstable/uuid.cpp
@@ -18,25 +18,25 @@
18 18
19Bu::Uuid::Uuid() 19Bu::Uuid::Uuid()
20{ 20{
21 clear(); 21 clear();
22} 22}
23 23
24Bu::Uuid::Uuid( const Uuid &src ) 24Bu::Uuid::Uuid( const Uuid &src )
25{ 25{
26 memcpy( data, src.data, 16 ); 26 memcpy( data, src.data, 16 );
27} 27}
28 28
29Bu::Uuid::Uuid( const Bu::String &sSrc ) 29Bu::Uuid::Uuid( const Bu::String &sSrc )
30{ 30{
31 if( sSrc.getSize() == 16 ) 31 if( sSrc.getSize() == 16 )
32 { 32 {
33 memcpy( data, sSrc.getStr(), 16 ); 33 memcpy( data, sSrc.getStr(), 16 );
34 } 34 }
35 else if( sSrc.getSize() == 36 ) 35 else if( sSrc.getSize() == 36 )
36 { 36 {
37 // Parse it 37 // Parse it
38 set( sSrc ); 38 set( sSrc );
39 } 39 }
40} 40}
41 41
42Bu::Uuid::~Uuid() 42Bu::Uuid::~Uuid()
@@ -45,130 +45,130 @@ Bu::Uuid::~Uuid()
45 45
46Bu::String Bu::Uuid::toRawString() const 46Bu::String Bu::Uuid::toRawString() const
47{ 47{
48 return Bu::String( (char *)data, 16 ); 48 return Bu::String( (char *)data, 16 );
49} 49}
50 50
51Bu::String Bu::Uuid::toString() const 51Bu::String Bu::Uuid::toString() const
52{ 52{
53 Bu::MemBuf mb; 53 Bu::MemBuf mb;
54 Bu::Formatter f( mb ); 54 Bu::Formatter f( mb );
55 55
56 for( int j = 0; j < 16; j++ ) 56 for( int j = 0; j < 16; j++ )
57 { 57 {
58 if( j == 4 || j == 6 || j == 8 || j == 10 ) 58 if( j == 4 || j == 6 || j == 8 || j == 10 )
59 f << '-'; 59 f << '-';
60 f << Bu::Fmt::hex(2).caps(false) << (unsigned int)data[j]; 60 f << Bu::Fmt::hex(2).caps(false) << (unsigned int)data[j];
61 } 61 }
62 62
63 return mb.getString(); 63 return mb.getString();
64} 64}
65 65
66Bu::String Bu::Uuid::toUrn() const 66Bu::String Bu::Uuid::toUrn() const
67{ 67{
68 return "urn:uuid:" + toString(); 68 return "urn:uuid:" + toString();
69} 69}
70 70
71int Bu::Uuid::getVersion() 71int Bu::Uuid::getVersion()
72{ 72{
73 return (data[6]&((8|4|2|1)<<4))>>4; 73 return (data[6]&((8|4|2|1)<<4))>>4;
74} 74}
75 75
76#define msb( i ) (1<<(7-i)) 76#define msb( i ) (1<<(7-i))
77 77
78void Bu::Uuid::clear() 78void Bu::Uuid::clear()
79{ 79{
80 data[7] = msb(0); 80 data[7] = msb(0);
81} 81}
82 82
83Bu::Uuid Bu::Uuid::generate( Bu::Uuid::Type eType ) 83Bu::Uuid Bu::Uuid::generate( Bu::Uuid::Type eType )
84{ 84{
85 switch( eType ) 85 switch( eType )
86 { 86 {
87 case Version1: 87 case Version1:
88 case Version2: 88 case Version2:
89 case Version3: 89 case Version3:
90 case Version4: 90 case Version4:
91 case Version5: 91 case Version5:
92 default: 92 default:
93 case System: 93 case System:
94#if defined(linux) 94#if defined(linux)
95 Bu::File fIn( "/proc/sys/kernel/random/uuid", Bu::File::Read ); 95 Bu::File fIn( "/proc/sys/kernel/random/uuid", Bu::File::Read );
96 char dat[36]; 96 char dat[36];
97 fIn.read( dat, 36 ); 97 fIn.read( dat, 36 );
98 Uuid id; 98 Uuid id;
99 id.set( dat ); 99 id.set( dat );
100 return id; 100 return id;
101#elif defined(WIN32) 101#elif defined(WIN32)
102 UUID uuid; 102 UUID uuid;
103 UuidCreate( &uuid ); 103 UuidCreate( &uuid );
104 Uuid id; 104 Uuid id;
105 id.data[0] = ((unsigned char *)&uuid.Data1)[3]; 105 id.data[0] = ((unsigned char *)&uuid.Data1)[3];
106 id.data[1] = ((unsigned char *)&uuid.Data1)[2]; 106 id.data[1] = ((unsigned char *)&uuid.Data1)[2];
107 id.data[2] = ((unsigned char *)&uuid.Data1)[1]; 107 id.data[2] = ((unsigned char *)&uuid.Data1)[1];
108 id.data[3] = ((unsigned char *)&uuid.Data1)[0]; 108 id.data[3] = ((unsigned char *)&uuid.Data1)[0];
109 id.data[4] = ((unsigned char *)&uuid.Data2)[1]; 109 id.data[4] = ((unsigned char *)&uuid.Data2)[1];
110 id.data[5] = ((unsigned char *)&uuid.Data2)[0]; 110 id.data[5] = ((unsigned char *)&uuid.Data2)[0];
111 id.data[6] = ((unsigned char *)&uuid.Data3)[1]; 111 id.data[6] = ((unsigned char *)&uuid.Data3)[1];
112 id.data[7] = ((unsigned char *)&uuid.Data3)[0]; 112 id.data[7] = ((unsigned char *)&uuid.Data3)[0];
113 memcpy( id.data+8, uuid.Data4, 8 ); 113 memcpy( id.data+8, uuid.Data4, 8 );
114 114
115 return id; 115 return id;
116#else 116#else
117# error We should be using one of the other fallbacks, but your platform is not supported yet. Sorry. 117# error We should be using one of the other fallbacks, but your platform is not supported yet. Sorry.
118#endif 118#endif
119 } 119 }
120} 120}
121 121
122void Bu::Uuid::set( const Bu::String &sSrc ) 122void Bu::Uuid::set( const Bu::String &sSrc )
123{ 123{
124 const char *dat = sSrc.getStr(); 124 const char *dat = sSrc.getStr();
125 int iNibble = 0; 125 int iNibble = 0;
126 memset( data, 0, 16 ); 126 memset( data, 0, 16 );
127 for( int j = 0; j < 36; j++ ) 127 for( int j = 0; j < 36; j++ )
128 { 128 {
129 if( dat[j] == '-' ) 129 if( dat[j] == '-' )
130 continue; 130 continue;
131 unsigned char c = (dat[j]>='0'&&dat[j]<='9')?(dat[j]-'0'):(dat[j]-'a'+10); 131 unsigned char c = (dat[j]>='0'&&dat[j]<='9')?(dat[j]-'0'):(dat[j]-'a'+10);
132 data[iNibble/2] |= (iNibble%2==0)?(c<<4):(c); 132 data[iNibble/2] |= (iNibble%2==0)?(c<<4):(c);
133 iNibble++; 133 iNibble++;
134 } 134 }
135} 135}
136 136
137bool Bu::Uuid::operator==( const Uuid &rhs ) const 137bool Bu::Uuid::operator==( const Uuid &rhs ) const
138{ 138{
139 return memcmp( data, rhs.data, 16 ) == 0; 139 return memcmp( data, rhs.data, 16 ) == 0;
140} 140}
141 141
142bool Bu::Uuid::operator!=( const Uuid &rhs ) const 142bool Bu::Uuid::operator!=( const Uuid &rhs ) const
143{ 143{
144 return !(*this == rhs); 144 return !(*this == rhs);
145} 145}
146 146
147Bu::Uuid &Bu::Uuid::operator=( const Uuid &rhs ) 147Bu::Uuid &Bu::Uuid::operator=( const Uuid &rhs )
148{ 148{
149 memcpy( data, rhs.data, 16 ); 149 memcpy( data, rhs.data, 16 );
150 return *this; 150 return *this;
151} 151}
152 152
153template<> uint32_t Bu::__calcHashCode<Bu::Uuid>( const Bu::Uuid &k ) 153template<> uint32_t Bu::__calcHashCode<Bu::Uuid>( const Bu::Uuid &k )
154{ 154{
155 return __calcHashCode<String>( k.toRawString() ); 155 return __calcHashCode<String>( k.toRawString() );
156} 156}
157 157
158template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid &b ) 158template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid &b )
159{ 159{
160 return a == b; 160 return a == b;
161} 161}
162 162
163Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u ) 163Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u )
164{ 164{
165 ar.read( u.data, 16 ); 165 ar.read( u.data, 16 );
166 return ar; 166 return ar;
167} 167}
168 168
169Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u ) 169Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u )
170{ 170{
171 ar.write( u.data, 16 ); 171 ar.write( u.data, 16 );
172 return ar; 172 return ar;
173} 173}
174 174
diff --git a/src/unstable/uuid.h b/src/unstable/uuid.h
index bb3d608..ecc142d 100644
--- a/src/unstable/uuid.h
+++ b/src/unstable/uuid.h
@@ -13,59 +13,59 @@
13 13
14namespace Bu 14namespace Bu
15{ 15{
16 class Uuid 16 class Uuid
17 { 17 {
18 friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); 18 friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u );
19 friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); 19 friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u );
20 public: 20 public:
21 Uuid(); 21 Uuid();
22 Uuid( const Uuid &src ); 22 Uuid( const Uuid &src );
23 Uuid( const Bu::String &sSrc ); 23 Uuid( const Bu::String &sSrc );
24 virtual ~Uuid(); 24 virtual ~Uuid();
25 25
26 Bu::String toRawString() const; 26 Bu::String toRawString() const;
27 Bu::String toString() const; 27 Bu::String toString() const;
28 Bu::String toUrn() const; 28 Bu::String toUrn() const;
29 29
30 enum Type 30 enum Type
31 { 31 {
32 System, 32 System,
33 Version1, 33 Version1,
34 Version2, 34 Version2,
35 Version3, 35 Version3,
36 Version4, 36 Version4,
37 Version5, 37 Version5,
38 }; 38 };
39 39
40 int getVersion(); 40 int getVersion();
41 41
42 static Uuid generate( Type eType = System ); 42 static Uuid generate( Type eType = System );
43 DEPRECATED static Uuid gen() { return generate(); } 43 DEPRECATED static Uuid gen() { return generate(); }
44 44
45 void clear(); 45 void clear();
46 void set( const Bu::String &sSrc ); 46 void set( const Bu::String &sSrc );
47 47
48 bool operator==( const Uuid &rhs ) const; 48 bool operator==( const Uuid &rhs ) const;
49 bool operator!=( const Uuid &rhs ) const; 49 bool operator!=( const Uuid &rhs ) const;
50 Uuid &operator=( const Bu::String &rhs ) { set( rhs ); return *this; } 50 Uuid &operator=( const Bu::String &rhs ) { set( rhs ); return *this; }
51 Uuid &operator=( const Uuid &rhs ); 51 Uuid &operator=( const Uuid &rhs );
52 52
53 private: 53 private:
54 unsigned char data[16]; 54 unsigned char data[16];
55 }; 55 };
56 56
57 template<typename T> 57 template<typename T>
58 uint32_t __calcHashCode( const T &k ); 58 uint32_t __calcHashCode( const T &k );
59 59
60 template<typename T> 60 template<typename T>
61 bool __cmpHashKeys( const T &a, const T &b ); 61 bool __cmpHashKeys( const T &a, const T &b );
62 62
63 template<> uint32_t __calcHashCode<Uuid>( const Uuid &k ); 63 template<> uint32_t __calcHashCode<Uuid>( const Uuid &k );
64 template<> bool __cmpHashKeys<Uuid>( 64 template<> bool __cmpHashKeys<Uuid>(
65 const Uuid &a, const Uuid &b ); 65 const Uuid &a, const Uuid &b );
66 66
67 Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); 67 Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u );
68 Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); 68 Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u );
69}; 69};
70 70
71#endif 71#endif