aboutsummaryrefslogtreecommitdiff
path: root/src/stable
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
150 files changed, 18694 insertions, 18694 deletions
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