diff options
Diffstat (limited to 'src/stable')
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 | ||
18 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) | 18 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, const Bu::Archival &p) |
19 | { | 19 | { |
20 | const_cast<Bu::Archival &>(p).archive( s ); | 20 | const_cast<Bu::Archival &>(p).archive( s ); |
21 | return s; | 21 | return s; |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) | 24 | Bu::ArchiveBase &Bu::operator<<(Bu::ArchiveBase &s, Bu::Archival &p) |
25 | { | 25 | { |
26 | p.archive( s ); | 26 | p.archive( s ); |
27 | return s; | 27 | return s; |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) | 30 | Bu::ArchiveBase &Bu::operator>>(Bu::ArchiveBase &s, Bu::Archival &p) |
31 | { | 31 | { |
32 | p.archive( s ); | 32 | p.archive( s ); |
33 | return s; | 33 | return s; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/src/stable/archival.h b/src/stable/archival.h index 664bc98..78faffb 100644 --- a/src/stable/archival.h +++ b/src/stable/archival.h | |||
@@ -12,40 +12,40 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * The base class for any class you want to archive. Simply include this as | 16 | * The base class for any class you want to archive. Simply include this as |
17 | * a base class, implement the purely virtual archive function and you've | 17 | * a base class, implement the purely virtual archive function and you've |
18 | * got an easily archiveable class. | 18 | * got an easily archiveable class. |
19 | * | 19 | * |
20 | * Archival: "of or pertaining to archives or valuable records; contained | 20 | * Archival: "of or pertaining to archives or valuable records; contained |
21 | * in or comprising such archives or records." | 21 | * in or comprising such archives or records." |
22 | */ | 22 | */ |
23 | class Archival | 23 | class Archival |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | /** | 26 | /** |
27 | * Does nothing, here for completeness. | 27 | * Does nothing, here for completeness. |
28 | */ | 28 | */ |
29 | Archival(); | 29 | Archival(); |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Here to ensure the deconstructor is virtual. | 32 | * Here to ensure the deconstructor is virtual. |
33 | */ | 33 | */ |
34 | virtual ~Archival(); | 34 | virtual ~Archival(); |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * This is the main workhorse of the archive system, just override and | 37 | * This is the main workhorse of the archive system, just override and |
38 | * you've got a archiveable class. A reference to the Archive | 38 | * you've got a archiveable class. A reference to the Archive |
39 | * used is passed in as your only parameter, query it to discover if | 39 | * used is passed in as your only parameter, query it to discover if |
40 | * you are loading or saving. | 40 | * you are loading or saving. |
41 | * @param ar A reference to the Archive object to use. | 41 | * @param ar A reference to the Archive object to use. |
42 | */ | 42 | */ |
43 | virtual void archive( class ArchiveBase &ar )=0; | 43 | virtual void archive( class ArchiveBase &ar )=0; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); | 46 | ArchiveBase &operator<<(ArchiveBase &, const class Bu::Archival &); |
47 | ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); | 47 | ArchiveBase &operator<<(ArchiveBase &, class Bu::Archival &); |
48 | ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); | 48 | ArchiveBase &operator>>(ArchiveBase &, class Bu::Archival &); |
49 | 49 | ||
50 | } | 50 | } |
51 | 51 | ||
diff --git a/src/stable/archive.cpp b/src/stable/archive.cpp index 13480e1..3769e0e 100644 --- a/src/stable/archive.cpp +++ b/src/stable/archive.cpp | |||
@@ -12,9 +12,9 @@ | |||
12 | #include "bu/sio.h" | 12 | #include "bu/sio.h" |
13 | 13 | ||
14 | Bu::Archive::Archive( Stream &rStream, bool bLoading ) : | 14 | Bu::Archive::Archive( Stream &rStream, bool bLoading ) : |
15 | bLoading( bLoading ), | 15 | bLoading( bLoading ), |
16 | rStream( rStream ), | 16 | rStream( rStream ), |
17 | nNextID( 1 ) | 17 | nNextID( 1 ) |
18 | { | 18 | { |
19 | } | 19 | } |
20 | 20 | ||
@@ -24,66 +24,66 @@ Bu::Archive::~Archive() | |||
24 | 24 | ||
25 | void Bu::Archive::write( const void *pData, size_t nSize ) | 25 | void Bu::Archive::write( const void *pData, size_t nSize ) |
26 | { | 26 | { |
27 | if( nSize == 0 || pData == NULL ) | 27 | if( nSize == 0 || pData == NULL ) |
28 | return; | 28 | return; |
29 | 29 | ||
30 | rStream.write( (const char *)pData, nSize ); | 30 | rStream.write( (const char *)pData, nSize ); |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::Archive::read( void *pData, size_t nSize ) | 33 | void Bu::Archive::read( void *pData, size_t nSize ) |
34 | { | 34 | { |
35 | if( nSize == 0 || pData == NULL ) | 35 | if( nSize == 0 || pData == NULL ) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) | 38 | if( (size_t)rStream.read( (char *)pData, nSize ) < nSize ) |
39 | throw Bu::ExceptionBase("Insufficient data to unarchive object."); | 39 | throw Bu::ExceptionBase("Insufficient data to unarchive object."); |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::Archive::close() | 42 | void Bu::Archive::close() |
43 | { | 43 | { |
44 | rStream.close(); | 44 | rStream.close(); |
45 | } | 45 | } |
46 | 46 | ||
47 | bool Bu::Archive::isLoading() | 47 | bool Bu::Archive::isLoading() |
48 | { | 48 | { |
49 | return bLoading; | 49 | return bLoading; |
50 | } | 50 | } |
51 | 51 | ||
52 | uint32_t Bu::Archive::getID( const void *ptr ) | 52 | uint32_t Bu::Archive::getID( const void *ptr ) |
53 | { | 53 | { |
54 | if( hPtrID.has( (ptrdiff_t)ptr ) ) | 54 | if( hPtrID.has( (ptrdiff_t)ptr ) ) |
55 | return hPtrID.get( (ptrdiff_t)ptr ); | 55 | return hPtrID.get( (ptrdiff_t)ptr ); |
56 | hPtrID.insert( (ptrdiff_t)ptr, nNextID ); | 56 | hPtrID.insert( (ptrdiff_t)ptr, nNextID ); |
57 | return nNextID++; | 57 | return nNextID++; |
58 | } | 58 | } |
59 | 59 | ||
60 | void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) | 60 | void Bu::Archive::assocPtrID( void **ptr, uint32_t id ) |
61 | { | 61 | { |
62 | if( hPtrID.has( id ) ) | 62 | if( hPtrID.has( id ) ) |
63 | { | 63 | { |
64 | *ptr = (void *)hPtrID.get( id ); | 64 | *ptr = (void *)hPtrID.get( id ); |
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | if( !hPtrDest.has( id ) ) | 68 | if( !hPtrDest.has( id ) ) |
69 | hPtrDest.insert( id, List<void **>() ); | 69 | hPtrDest.insert( id, List<void **>() ); |
70 | 70 | ||
71 | hPtrDest[id].getValue().append( ptr ); | 71 | hPtrDest[id].getValue().append( ptr ); |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::Archive::readID( const void *ptr, uint32_t id ) | 74 | void Bu::Archive::readID( const void *ptr, uint32_t id ) |
75 | { | 75 | { |
76 | hPtrID.insert( id, (ptrdiff_t)ptr ); | 76 | hPtrID.insert( id, (ptrdiff_t)ptr ); |
77 | 77 | ||
78 | if( hPtrDest.has( id ) ) | 78 | if( hPtrDest.has( id ) ) |
79 | { | 79 | { |
80 | Bu::List<void **> &l = hPtrDest.get( id ); | 80 | Bu::List<void **> &l = hPtrDest.get( id ); |
81 | for( Bu::List<void **>::iterator i = l.begin(); i != l.end(); i++ ) | 81 | for( Bu::List<void **>::iterator i = l.begin(); i != l.end(); i++ ) |
82 | { | 82 | { |
83 | *(*i) = (void *)ptr; | 83 | *(*i) = (void *)ptr; |
84 | } | 84 | } |
85 | 85 | ||
86 | hPtrDest.erase( id ); | 86 | hPtrDest.erase( id ); |
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
diff --git a/src/stable/archive.h b/src/stable/archive.h index 9716bb1..f98402d 100644 --- a/src/stable/archive.h +++ b/src/stable/archive.h | |||
@@ -16,123 +16,123 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class Archival; | 19 | class Archival; |
20 | class Stream; | 20 | class Stream; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * Provides a framework for serialization of objects and primitives. The | 23 | * Provides a framework for serialization of objects and primitives. The |
24 | * archive will handle any basic primitive, a few special types, like char * | 24 | * archive will handle any basic primitive, a few special types, like char * |
25 | * strings, as well as STL classes and anything that inherits from the | 25 | * strings, as well as STL classes and anything that inherits from the |
26 | * Archival class. Each Archive operates on a Stream, so you can send the | 26 | * Archival class. Each Archive operates on a Stream, so you can send the |
27 | * data using an Archive almost anywhere. | 27 | * data using an Archive almost anywhere. |
28 | * | 28 | * |
29 | * In order to use an Archive to store something to a file, try something | 29 | * In order to use an Archive to store something to a file, try something |
30 | * like: | 30 | * like: |
31 | *@code | 31 | *@code |
32 | * File sOut("output", "wb"); // This is a stream subclass | 32 | * File sOut("output", "wb"); // This is a stream subclass |
33 | * Archive ar( sOut, Archive::save ); | 33 | * Archive ar( sOut, Archive::save ); |
34 | * ar << myClass; | 34 | * ar << myClass; |
35 | @endcode | 35 | @endcode |
36 | * In this example myClass is any class that inherits from Archival. When | 36 | * In this example myClass is any class that inherits from Archival. When |
37 | * the storage operator is called, the Archival::archive() function in the | 37 | * the storage operator is called, the Archival::archive() function in the |
38 | * myClass object is called with a reference to the Archive. This can be | 38 | * myClass object is called with a reference to the Archive. This can be |
39 | * handled in one of two ways: | 39 | * handled in one of two ways: |
40 | *@code | 40 | *@code |
41 | * void MyClass::archive( Archive &ar ) | 41 | * void MyClass::archive( Archive &ar ) |
42 | * { | 42 | * { |
43 | * ar && sName && nAge && sJob; | 43 | * ar && sName && nAge && sJob; |
44 | * } | 44 | * } |
45 | @endcode | 45 | @endcode |
46 | * Here we don't worry about weather we're loading or saving by using the | 46 | * Here we don't worry about weather we're loading or saving by using the |
47 | * smart && operator. This allows us to write very consistent, very simple | 47 | * smart && operator. This allows us to write very consistent, very simple |
48 | * archive functions that really do a lot of work. If we wanted to do | 48 | * archive functions that really do a lot of work. If we wanted to do |
49 | * something different in the case of loading or saving we would do: | 49 | * something different in the case of loading or saving we would do: |
50 | *@code | 50 | *@code |
51 | * void MyClass::archive( Archive &ar ) | 51 | * void MyClass::archive( Archive &ar ) |
52 | * { | 52 | * { |
53 | * if( ar.isLoading() ) | 53 | * if( ar.isLoading() ) |
54 | * { | 54 | * { |
55 | * ar >> sName >> nAge >> sJob; | 55 | * ar >> sName >> nAge >> sJob; |
56 | * } else | 56 | * } else |
57 | * { | 57 | * { |
58 | * ar << sName << nAge << sJob; | 58 | * ar << sName << nAge << sJob; |
59 | * } | 59 | * } |
60 | * } | 60 | * } |
61 | @endcode | 61 | @endcode |
62 | * Archive currently does not provide facility to make fully portable | 62 | * Archive currently does not provide facility to make fully portable |
63 | * archives. For example, it will not convert between endianness for you, | 63 | * archives. For example, it will not convert between endianness for you, |
64 | * nor will it take into account differences between primitive sizes on | 64 | * nor will it take into account differences between primitive sizes on |
65 | * different platforms. This, at the moment, is up to the user to ensure. | 65 | * different platforms. This, at the moment, is up to the user to ensure. |
66 | * One way of dealing with the latter problem is to make sure and use | 66 | * One way of dealing with the latter problem is to make sure and use |
67 | * explicit primitive types from the stdint.h header, i.e. int32_t. | 67 | * explicit primitive types from the stdint.h header, i.e. int32_t. |
68 | */ | 68 | */ |
69 | class Archive : public ArchiveBase | 69 | class Archive : public ArchiveBase |
70 | { | 70 | { |
71 | private: | 71 | private: |
72 | bool bLoading; | 72 | bool bLoading; |
73 | public: | 73 | public: |
74 | bool isLoading(); | 74 | bool isLoading(); |
75 | 75 | ||
76 | enum | 76 | enum |
77 | { | 77 | { |
78 | load = true, | 78 | load = true, |
79 | save = false | 79 | save = false |
80 | }; | 80 | }; |
81 | 81 | ||
82 | Archive( Stream &rStream, bool bLoading ); | 82 | Archive( Stream &rStream, bool bLoading ); |
83 | virtual ~Archive(); | 83 | virtual ~Archive(); |
84 | virtual void close(); | 84 | virtual void close(); |
85 | 85 | ||
86 | virtual void write( const void *pData, size_t iSize ); | 86 | virtual void write( const void *pData, size_t iSize ); |
87 | virtual void read( void *pData, size_t iSize ); | 87 | virtual void read( void *pData, size_t iSize ); |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * For storage, get an ID for the pointer to the object you're going to | 90 | * For storage, get an ID for the pointer to the object you're going to |
91 | * write. | 91 | * write. |
92 | */ | 92 | */ |
93 | uint32_t getID( const void *ptr ); | 93 | uint32_t getID( const void *ptr ); |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * For loading. Assosiates an empty pointer with an id. When you wind | 96 | * For loading. Assosiates an empty pointer with an id. When you wind |
97 | * up loading an id reference to a pointer for an object that may or | 97 | * up loading an id reference to a pointer for an object that may or |
98 | * may not have loaded yet, call this with the id, if it has been loaded | 98 | * may not have loaded yet, call this with the id, if it has been loaded |
99 | * already, you'll immediately get a pointer, if not, it will write one | 99 | * already, you'll immediately get a pointer, if not, it will write one |
100 | * for you when the time comes. | 100 | * for you when the time comes. |
101 | */ | 101 | */ |
102 | void assocPtrID( void **ptr, uint32_t id ); | 102 | void assocPtrID( void **ptr, uint32_t id ); |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * For loading. Call this when you load an object that other things may | 105 | * For loading. Call this when you load an object that other things may |
106 | * have pointers to. It will assosiate every pointer that's been | 106 | * have pointers to. It will assosiate every pointer that's been |
107 | * registered with assocPtrID to the pointer passed in, and id passed | 107 | * registered with assocPtrID to the pointer passed in, and id passed |
108 | * in. It will also set things up so future calls to assocPtrID will | 108 | * in. It will also set things up so future calls to assocPtrID will |
109 | * automatically succeed immediately. | 109 | * automatically succeed immediately. |
110 | */ | 110 | */ |
111 | void readID( const void *ptr, uint32_t id ); | 111 | void readID( const void *ptr, uint32_t id ); |
112 | 112 | ||
113 | template<typename t> | 113 | template<typename t> |
114 | void setProp( const Bu::String &sId, const t &val ) | 114 | void setProp( const Bu::String &sId, const t &val ) |
115 | { | 115 | { |
116 | if( !hProps.has( sId ) ) | 116 | if( !hProps.has( sId ) ) |
117 | { | 117 | { |
118 | hProps.insert( sId, Variant() ); | 118 | hProps.insert( sId, Variant() ); |
119 | } | 119 | } |
120 | hProps.get( sId ) = val; | 120 | hProps.get( sId ) = val; |
121 | } | 121 | } |
122 | 122 | ||
123 | template<typename t> | 123 | template<typename t> |
124 | t getProp( const Bu::String &sId ) | 124 | t getProp( const Bu::String &sId ) |
125 | { | 125 | { |
126 | return hProps.get( sId ); | 126 | return hProps.get( sId ); |
127 | } | 127 | } |
128 | 128 | ||
129 | private: | 129 | private: |
130 | Stream &rStream; | 130 | Stream &rStream; |
131 | uint32_t nNextID; | 131 | uint32_t nNextID; |
132 | Hash<uint32_t,uint32_t> hPtrID; | 132 | Hash<uint32_t,uint32_t> hPtrID; |
133 | Hash<uint32_t,List<void **> > hPtrDest; | 133 | Hash<uint32_t,List<void **> > hPtrDest; |
134 | Hash<Bu::String, Variant> hProps; | 134 | Hash<Bu::String, Variant> hProps; |
135 | }; | 135 | }; |
136 | } | 136 | } |
137 | 137 | ||
138 | #endif | 138 | #endif |
diff --git a/src/stable/archivebase.cpp b/src/stable/archivebase.cpp index dcf08f4..d0d22ce 100644 --- a/src/stable/archivebase.cpp +++ b/src/stable/archivebase.cpp | |||
@@ -17,181 +17,181 @@ Bu::ArchiveBase::~ArchiveBase() | |||
17 | 17 | ||
18 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) | 18 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, bool p) |
19 | { | 19 | { |
20 | ar.write( &p, sizeof(p) ); | 20 | ar.write( &p, sizeof(p) ); |
21 | return ar; | 21 | return ar; |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) | 24 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, char p) |
25 | { | 25 | { |
26 | ar.write( &p, sizeof(p) ); | 26 | ar.write( &p, sizeof(p) ); |
27 | return ar; | 27 | return ar; |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) | 30 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed char p) |
31 | { | 31 | { |
32 | ar.write( &p, sizeof(p) ); | 32 | ar.write( &p, sizeof(p) ); |
33 | return ar; | 33 | return ar; |
34 | } | 34 | } |
35 | 35 | ||
36 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) | 36 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned char p) |
37 | { | 37 | { |
38 | ar.write( &p, sizeof(p) ); | 38 | ar.write( &p, sizeof(p) ); |
39 | return ar; | 39 | return ar; |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) | 42 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed short p) |
43 | { | 43 | { |
44 | ar.write( &p, sizeof(p) ); | 44 | ar.write( &p, sizeof(p) ); |
45 | return ar; | 45 | return ar; |
46 | } | 46 | } |
47 | 47 | ||
48 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) | 48 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned short p) |
49 | { | 49 | { |
50 | ar.write( &p, sizeof(p) ); | 50 | ar.write( &p, sizeof(p) ); |
51 | return ar; | 51 | return ar; |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) | 54 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed int p) |
55 | { | 55 | { |
56 | ar.write( &p, sizeof(p) ); | 56 | ar.write( &p, sizeof(p) ); |
57 | return ar; | 57 | return ar; |
58 | } | 58 | } |
59 | 59 | ||
60 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) | 60 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned int p) |
61 | { | 61 | { |
62 | ar.write( &p, sizeof(p) ); | 62 | ar.write( &p, sizeof(p) ); |
63 | return ar; | 63 | return ar; |
64 | } | 64 | } |
65 | 65 | ||
66 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) | 66 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long p) |
67 | { | 67 | { |
68 | ar.write( &p, sizeof(p) ); | 68 | ar.write( &p, sizeof(p) ); |
69 | return ar; | 69 | return ar; |
70 | } | 70 | } |
71 | 71 | ||
72 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) | 72 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long p) |
73 | { | 73 | { |
74 | ar.write( &p, sizeof(p) ); | 74 | ar.write( &p, sizeof(p) ); |
75 | return ar; | 75 | return ar; |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) | 78 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, signed long long p) |
79 | { | 79 | { |
80 | ar.write( &p, sizeof(p) ); | 80 | ar.write( &p, sizeof(p) ); |
81 | return ar; | 81 | return ar; |
82 | } | 82 | } |
83 | 83 | ||
84 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) | 84 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, unsigned long long p) |
85 | { | 85 | { |
86 | ar.write( &p, sizeof(p) ); | 86 | ar.write( &p, sizeof(p) ); |
87 | return ar; | 87 | return ar; |
88 | } | 88 | } |
89 | 89 | ||
90 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) | 90 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, float p) |
91 | { | 91 | { |
92 | ar.write( &p, sizeof(p) ); | 92 | ar.write( &p, sizeof(p) ); |
93 | return ar; | 93 | return ar; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) | 96 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, double p) |
97 | { | 97 | { |
98 | ar.write( &p, sizeof(p) ); | 98 | ar.write( &p, sizeof(p) ); |
99 | return ar; | 99 | return ar; |
100 | } | 100 | } |
101 | 101 | ||
102 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) | 102 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, long double p) |
103 | { | 103 | { |
104 | ar.write( &p, sizeof(p) ); | 104 | ar.write( &p, sizeof(p) ); |
105 | return ar; | 105 | return ar; |
106 | } | 106 | } |
107 | 107 | ||
108 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) | 108 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, bool &p) |
109 | { | 109 | { |
110 | ar.read( &p, sizeof(p) ); | 110 | ar.read( &p, sizeof(p) ); |
111 | return ar; | 111 | return ar; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) | 114 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, char &p) |
115 | { | 115 | { |
116 | ar.read( &p, sizeof(p) ); | 116 | ar.read( &p, sizeof(p) ); |
117 | return ar; | 117 | return ar; |
118 | } | 118 | } |
119 | 119 | ||
120 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) | 120 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed char &p) |
121 | { | 121 | { |
122 | ar.read( &p, sizeof(p) ); | 122 | ar.read( &p, sizeof(p) ); |
123 | return ar; | 123 | return ar; |
124 | } | 124 | } |
125 | 125 | ||
126 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) | 126 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned char &p) |
127 | { | 127 | { |
128 | ar.read( &p, sizeof(p) ); | 128 | ar.read( &p, sizeof(p) ); |
129 | return ar; | 129 | return ar; |
130 | } | 130 | } |
131 | 131 | ||
132 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) | 132 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed short &p) |
133 | { | 133 | { |
134 | ar.read( &p, sizeof(p) ); | 134 | ar.read( &p, sizeof(p) ); |
135 | return ar; | 135 | return ar; |
136 | } | 136 | } |
137 | 137 | ||
138 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) | 138 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned short &p) |
139 | { | 139 | { |
140 | ar.read( &p, sizeof(p) ); | 140 | ar.read( &p, sizeof(p) ); |
141 | return ar; | 141 | return ar; |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) | 144 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed int &p) |
145 | { | 145 | { |
146 | ar.read( &p, sizeof(p) ); | 146 | ar.read( &p, sizeof(p) ); |
147 | return ar; | 147 | return ar; |
148 | } | 148 | } |
149 | 149 | ||
150 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) | 150 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned int &p) |
151 | { | 151 | { |
152 | ar.read( &p, sizeof(p) ); | 152 | ar.read( &p, sizeof(p) ); |
153 | return ar; | 153 | return ar; |
154 | } | 154 | } |
155 | 155 | ||
156 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) | 156 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long &p) |
157 | { | 157 | { |
158 | ar.read( &p, sizeof(p) ); | 158 | ar.read( &p, sizeof(p) ); |
159 | return ar; | 159 | return ar; |
160 | } | 160 | } |
161 | 161 | ||
162 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) | 162 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long &p) |
163 | { | 163 | { |
164 | ar.read( &p, sizeof(p) ); | 164 | ar.read( &p, sizeof(p) ); |
165 | return ar; | 165 | return ar; |
166 | } | 166 | } |
167 | 167 | ||
168 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) | 168 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, signed long long &p) |
169 | { | 169 | { |
170 | ar.read( &p, sizeof(p) ); | 170 | ar.read( &p, sizeof(p) ); |
171 | return ar; | 171 | return ar; |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) | 174 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, unsigned long long &p) |
175 | { | 175 | { |
176 | ar.read( &p, sizeof(p) ); | 176 | ar.read( &p, sizeof(p) ); |
177 | return ar; | 177 | return ar; |
178 | } | 178 | } |
179 | 179 | ||
180 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) | 180 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, float &p) |
181 | { | 181 | { |
182 | ar.read( &p, sizeof(p) ); | 182 | ar.read( &p, sizeof(p) ); |
183 | return ar; | 183 | return ar; |
184 | } | 184 | } |
185 | 185 | ||
186 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) | 186 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, double &p) |
187 | { | 187 | { |
188 | ar.read( &p, sizeof(p) ); | 188 | ar.read( &p, sizeof(p) ); |
189 | return ar; | 189 | return ar; |
190 | } | 190 | } |
191 | 191 | ||
192 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) | 192 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, long double &p) |
193 | { | 193 | { |
194 | ar.read( &p, sizeof(p) ); | 194 | ar.read( &p, sizeof(p) ); |
195 | return ar; | 195 | return ar; |
196 | } | 196 | } |
197 | 197 | ||
diff --git a/src/stable/archivebase.h b/src/stable/archivebase.h index 34ec1af..3f9e30f 100644 --- a/src/stable/archivebase.h +++ b/src/stable/archivebase.h | |||
@@ -13,63 +13,63 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class ArchiveBase | 16 | class ArchiveBase |
17 | { | 17 | { |
18 | public: | 18 | public: |
19 | ArchiveBase(); | 19 | ArchiveBase(); |
20 | virtual ~ArchiveBase(); | 20 | virtual ~ArchiveBase(); |
21 | 21 | ||
22 | virtual void close()=0; | 22 | virtual void close()=0; |
23 | virtual void write( const void *pData, size_t iLength )=0; | 23 | virtual void write( const void *pData, size_t iLength )=0; |
24 | virtual void read( void *pData, size_t iLength )=0; | 24 | virtual void read( void *pData, size_t iLength )=0; |
25 | virtual bool isLoading()=0; | 25 | virtual bool isLoading()=0; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | template<typename T> ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) | 28 | template<typename T> ArchiveBase &operator&&( ArchiveBase &ar, T &dat ) |
29 | { | 29 | { |
30 | if( ar.isLoading() ) | 30 | if( ar.isLoading() ) |
31 | { | 31 | { |
32 | return ar >> dat; | 32 | return ar >> dat; |
33 | } | 33 | } |
34 | else | 34 | else |
35 | { | 35 | { |
36 | return ar << dat; | 36 | return ar << dat; |
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | ArchiveBase &operator<<( ArchiveBase &ar, bool p ); | 40 | ArchiveBase &operator<<( ArchiveBase &ar, bool p ); |
41 | ArchiveBase &operator<<( ArchiveBase &ar, char p ); | 41 | ArchiveBase &operator<<( ArchiveBase &ar, char p ); |
42 | ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); | 42 | ArchiveBase &operator<<( ArchiveBase &ar, signed char p ); |
43 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); | 43 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned char p ); |
44 | ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); | 44 | ArchiveBase &operator<<( ArchiveBase &ar, signed short p ); |
45 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); | 45 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned short p ); |
46 | ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); | 46 | ArchiveBase &operator<<( ArchiveBase &ar, signed int p ); |
47 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); | 47 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned int p ); |
48 | ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); | 48 | ArchiveBase &operator<<( ArchiveBase &ar, signed long p ); |
49 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); | 49 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long p ); |
50 | ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); | 50 | ArchiveBase &operator<<( ArchiveBase &ar, signed long long p ); |
51 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); | 51 | ArchiveBase &operator<<( ArchiveBase &ar, unsigned long long p ); |
52 | ArchiveBase &operator<<( ArchiveBase &ar, float p ); | 52 | ArchiveBase &operator<<( ArchiveBase &ar, float p ); |
53 | ArchiveBase &operator<<( ArchiveBase &ar, double p ); | 53 | ArchiveBase &operator<<( ArchiveBase &ar, double p ); |
54 | ArchiveBase &operator<<( ArchiveBase &ar, long double p ); | 54 | ArchiveBase &operator<<( ArchiveBase &ar, long double p ); |
55 | 55 | ||
56 | ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); | 56 | ArchiveBase &operator>>( ArchiveBase &ar, bool &p ); |
57 | ArchiveBase &operator>>( ArchiveBase &ar, char &p ); | 57 | ArchiveBase &operator>>( ArchiveBase &ar, char &p ); |
58 | ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); | 58 | ArchiveBase &operator>>( ArchiveBase &ar, signed char &p ); |
59 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); | 59 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned char &p ); |
60 | ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); | 60 | ArchiveBase &operator>>( ArchiveBase &ar, signed short &p ); |
61 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); | 61 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned short &p ); |
62 | ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); | 62 | ArchiveBase &operator>>( ArchiveBase &ar, signed int &p ); |
63 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); | 63 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned int &p ); |
64 | ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); | 64 | ArchiveBase &operator>>( ArchiveBase &ar, signed long &p ); |
65 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); | 65 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long &p ); |
66 | ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); | 66 | ArchiveBase &operator>>( ArchiveBase &ar, signed long long &p ); |
67 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); | 67 | ArchiveBase &operator>>( ArchiveBase &ar, unsigned long long &p ); |
68 | ArchiveBase &operator>>( ArchiveBase &ar, float &p ); | 68 | ArchiveBase &operator>>( ArchiveBase &ar, float &p ); |
69 | ArchiveBase &operator>>( ArchiveBase &ar, double &p ); | 69 | ArchiveBase &operator>>( ArchiveBase &ar, double &p ); |
70 | ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); | 70 | ArchiveBase &operator>>( ArchiveBase &ar, long double &p ); |
71 | 71 | ||
72 | 72 | ||
73 | }; | 73 | }; |
74 | 74 | ||
75 | #endif | 75 | #endif |
diff --git a/src/stable/array.h b/src/stable/array.h index f765e75..324c9ac 100644 --- a/src/stable/array.h +++ b/src/stable/array.h | |||
@@ -15,697 +15,697 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( ArrayException ) | 18 | subExceptionDecl( ArrayException ) |
19 | 19 | ||
20 | template<typename value, int inc, typename valuealloc> | 20 | template<typename value, int inc, typename valuealloc> |
21 | class Array; | 21 | class Array; |
22 | 22 | ||
23 | /** @cond DEVEL */ | 23 | /** @cond DEVEL */ |
24 | template<typename value, int inc, typename valuealloc> | 24 | template<typename value, int inc, typename valuealloc> |
25 | class ArrayCore | 25 | class ArrayCore |
26 | { | 26 | { |
27 | friend class Array<value, inc, valuealloc>; | 27 | friend class Array<value, inc, valuealloc>; |
28 | friend class SharedCore< | 28 | friend class SharedCore< |
29 | Array<value, inc, valuealloc>, | 29 | Array<value, inc, valuealloc>, |
30 | ArrayCore<value, inc, valuealloc> | 30 | ArrayCore<value, inc, valuealloc> |
31 | >; | 31 | >; |
32 | private: | 32 | private: |
33 | ArrayCore() : | 33 | ArrayCore() : |
34 | pData( NULL ), | 34 | pData( NULL ), |
35 | iSize( 0 ), | 35 | iSize( 0 ), |
36 | iCapacity( 0 ) | 36 | iCapacity( 0 ) |
37 | { } | 37 | { } |
38 | 38 | ||
39 | void setCapacity( int iNewLen ) | 39 | void setCapacity( int iNewLen ) |
40 | { | 40 | { |
41 | //clear(); | 41 | //clear(); |
42 | //iCapacity = iCapacity; | 42 | //iCapacity = iCapacity; |
43 | //pData = va.allocate( iCapacity ); | 43 | //pData = va.allocate( iCapacity ); |
44 | if( iNewLen <= iCapacity ) return; | 44 | if( iNewLen <= iCapacity ) return; |
45 | value *pNewData = va.allocate( iNewLen ); | 45 | value *pNewData = va.allocate( iNewLen ); |
46 | if( pData ) | 46 | if( pData ) |
47 | { | 47 | { |
48 | for( int j = 0; j < iSize; j++ ) | 48 | for( int j = 0; j < iSize; j++ ) |
49 | { | 49 | { |
50 | va.construct( &pNewData[j], pData[j] ); | 50 | va.construct( &pNewData[j], pData[j] ); |
51 | va.destroy( &pData[j] ); | 51 | va.destroy( &pData[j] ); |
52 | } | 52 | } |
53 | va.deallocate( pData, iCapacity ); | 53 | va.deallocate( pData, iCapacity ); |
54 | } | 54 | } |
55 | pData = pNewData; | 55 | pData = pNewData; |
56 | iCapacity = iNewLen; | 56 | iCapacity = iNewLen; |
57 | } | 57 | } |
58 | 58 | ||
59 | virtual ~ArrayCore() | 59 | virtual ~ArrayCore() |
60 | { | 60 | { |
61 | clear(); | 61 | clear(); |
62 | } | 62 | } |
63 | 63 | ||
64 | void clear() | 64 | void clear() |
65 | { | 65 | { |
66 | if( pData ) | 66 | if( pData ) |
67 | { | 67 | { |
68 | for( int j = 0; j < iSize; j++ ) | 68 | for( int j = 0; j < iSize; j++ ) |
69 | { | 69 | { |
70 | va.destroy( &pData[j] ); | 70 | va.destroy( &pData[j] ); |
71 | } | 71 | } |
72 | va.deallocate( pData, iCapacity ); | 72 | va.deallocate( pData, iCapacity ); |
73 | pData = NULL; | 73 | pData = NULL; |
74 | } | 74 | } |
75 | iSize = 0; | 75 | iSize = 0; |
76 | iCapacity = 0; | 76 | iCapacity = 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | void erase( int iPos ) | 79 | void erase( int iPos ) |
80 | { | 80 | { |
81 | for( int j = iPos; j < iSize; j++ ) | 81 | for( int j = iPos; j < iSize; j++ ) |
82 | { | 82 | { |
83 | va.destroy( &pData[j] ); | 83 | va.destroy( &pData[j] ); |
84 | if( j == iSize-1 ) | 84 | if( j == iSize-1 ) |
85 | { | 85 | { |
86 | iSize--; | 86 | iSize--; |
87 | return; | 87 | return; |
88 | } | 88 | } |
89 | va.construct( &pData[j], pData[j+1] ); | 89 | va.construct( &pData[j], pData[j+1] ); |
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | void swapErase( int iPos ) | 93 | void swapErase( int iPos ) |
94 | { | 94 | { |
95 | if( iPos == iSize-1 ) | 95 | if( iPos == iSize-1 ) |
96 | { | 96 | { |
97 | erase( iPos ); | 97 | erase( iPos ); |
98 | return; | 98 | return; |
99 | } | 99 | } |
100 | va.destroy( &pData[iPos] ); | 100 | va.destroy( &pData[iPos] ); |
101 | va.construct( &pData[iPos], pData[iSize-1] ); | 101 | va.construct( &pData[iPos], pData[iSize-1] ); |
102 | va.destroy( &pData[iSize-1] ); | 102 | va.destroy( &pData[iSize-1] ); |
103 | iSize--; | 103 | iSize--; |
104 | } | 104 | } |
105 | 105 | ||
106 | valuealloc va; | 106 | valuealloc va; |
107 | value *pData; | 107 | value *pData; |
108 | long iSize; | 108 | long iSize; |
109 | long iCapacity; | 109 | long iCapacity; |
110 | }; | 110 | }; |
111 | /** @endcond */ | 111 | /** @endcond */ |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Array type container, just like a normal array only flexible and keeps | 114 | * Array type container, just like a normal array only flexible and keeps |
115 | * track of your memory for you. | 115 | * track of your memory for you. |
116 | * | 116 | * |
117 | *@param value (typename) The type of data to store in your list | 117 | *@param value (typename) The type of data to store in your list |
118 | *@param valuealloc (typename) Memory Allocator for your value type | 118 | *@param valuealloc (typename) Memory Allocator for your value type |
119 | *@param linkalloc (typename) Memory Allocator for the list links. | 119 | *@param linkalloc (typename) Memory Allocator for the list links. |
120 | *@ingroup Containers | 120 | *@ingroup Containers |
121 | */ | 121 | */ |
122 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > | 122 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > |
123 | class Array : public SharedCore< | 123 | class Array : public SharedCore< |
124 | Array<value, inc, valuealloc>, | 124 | Array<value, inc, valuealloc>, |
125 | ArrayCore<value, inc, valuealloc> | 125 | ArrayCore<value, inc, valuealloc> |
126 | > | 126 | > |
127 | { | 127 | { |
128 | private: | 128 | private: |
129 | typedef class Array<value, inc, valuealloc> MyType; | 129 | typedef class Array<value, inc, valuealloc> MyType; |
130 | typedef class ArrayCore<value, inc, valuealloc> Core; | 130 | typedef class ArrayCore<value, inc, valuealloc> Core; |
131 | 131 | ||
132 | protected: | 132 | protected: |
133 | using SharedCore<MyType, Core>::core; | 133 | using SharedCore<MyType, Core>::core; |
134 | using SharedCore<MyType, Core>::_hardCopy; | 134 | using SharedCore<MyType, Core>::_hardCopy; |
135 | using SharedCore<MyType, Core>::_resetCore; | 135 | using SharedCore<MyType, Core>::_resetCore; |
136 | using SharedCore<MyType, Core>::_allocateCore; | 136 | using SharedCore<MyType, Core>::_allocateCore; |
137 | 137 | ||
138 | public: | 138 | public: |
139 | struct const_iterator; | 139 | struct const_iterator; |
140 | struct iterator; | 140 | struct iterator; |
141 | 141 | ||
142 | Array() | 142 | Array() |
143 | { | 143 | { |
144 | } | 144 | } |
145 | 145 | ||
146 | Array( const MyType &src ) : | 146 | Array( const MyType &src ) : |
147 | SharedCore<MyType, Core >( src ) | 147 | SharedCore<MyType, Core >( src ) |
148 | { | 148 | { |
149 | } | 149 | } |
150 | 150 | ||
151 | Array( long iSetCap ) | 151 | Array( long iSetCap ) |
152 | { | 152 | { |
153 | setCapacity( iSetCap ); | 153 | setCapacity( iSetCap ); |
154 | } | 154 | } |
155 | 155 | ||
156 | ~Array() | 156 | ~Array() |
157 | { | 157 | { |
158 | } | 158 | } |
159 | 159 | ||
160 | bool operator==( const MyType &src ) const | 160 | bool operator==( const MyType &src ) const |
161 | { | 161 | { |
162 | if( core == src.core ) | 162 | if( core == src.core ) |
163 | return true; | 163 | return true; |
164 | if( core->iSize != src.core->iSize ) | 164 | if( core->iSize != src.core->iSize ) |
165 | return false; | 165 | return false; |
166 | 166 | ||
167 | for( int j = 0; j < core->iSize; j++ ) | 167 | for( int j = 0; j < core->iSize; j++ ) |
168 | { | 168 | { |
169 | if( core->pData[j] != src.core->pData[j] ) | 169 | if( core->pData[j] != src.core->pData[j] ) |
170 | return false; | 170 | return false; |
171 | } | 171 | } |
172 | return true; | 172 | return true; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool operator!=( const MyType &src ) const | 175 | bool operator!=( const MyType &src ) const |
176 | { | 176 | { |
177 | return !(*this == src); | 177 | return !(*this == src); |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * Clear the array. | 181 | * Clear the array. |
182 | */ | 182 | */ |
183 | void clear() | 183 | void clear() |
184 | { | 184 | { |
185 | _resetCore(); | 185 | _resetCore(); |
186 | } | 186 | } |
187 | 187 | ||
188 | MyType &append( const value &rVal ) | 188 | MyType &append( const value &rVal ) |
189 | { | 189 | { |
190 | _hardCopy(); | 190 | _hardCopy(); |
191 | if( core->iSize == core->iCapacity ) | 191 | if( core->iSize == core->iCapacity ) |
192 | { | 192 | { |
193 | core->setCapacity( core->iCapacity + inc ); | 193 | core->setCapacity( core->iCapacity + inc ); |
194 | } | 194 | } |
195 | 195 | ||
196 | core->va.construct( &core->pData[core->iSize++], rVal ); | 196 | core->va.construct( &core->pData[core->iSize++], rVal ); |
197 | 197 | ||
198 | return *this; | 198 | return *this; |
199 | } | 199 | } |
200 | 200 | ||
201 | MyType &append( const MyType &rVal ) | 201 | MyType &append( const MyType &rVal ) |
202 | { | 202 | { |
203 | _hardCopy(); | 203 | _hardCopy(); |
204 | 204 | ||
205 | if( core->iSize + rVal.core->iSize > core->iCapacity ) | 205 | if( core->iSize + rVal.core->iSize > core->iCapacity ) |
206 | { | 206 | { |
207 | core->setCapacity( core->iSize + rVal.core->iSize + inc ); | 207 | core->setCapacity( core->iSize + rVal.core->iSize + inc ); |
208 | } | 208 | } |
209 | 209 | ||
210 | for( int j = 0; j < rVal.core->iSize; j++ ) | 210 | for( int j = 0; j < rVal.core->iSize; j++ ) |
211 | { | 211 | { |
212 | core->va.construct( | 212 | core->va.construct( |
213 | &core->pData[core->iSize++], | 213 | &core->pData[core->iSize++], |
214 | rVal.core->pData[j] | 214 | rVal.core->pData[j] |
215 | ); | 215 | ); |
216 | } | 216 | } |
217 | 217 | ||
218 | return *this; | 218 | return *this; |
219 | } | 219 | } |
220 | 220 | ||
221 | //operator | 221 | //operator |
222 | value &operator[]( long iIndex ) | 222 | value &operator[]( long iIndex ) |
223 | { | 223 | { |
224 | _hardCopy(); | 224 | _hardCopy(); |
225 | if( iIndex < 0 || iIndex >= core->iSize ) | 225 | if( iIndex < 0 || iIndex >= core->iSize ) |
226 | throw ArrayException( | 226 | throw ArrayException( |
227 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 227 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
228 | 228 | ||
229 | return core->pData[iIndex]; | 229 | return core->pData[iIndex]; |
230 | } | 230 | } |
231 | 231 | ||
232 | const value &operator[]( long iIndex ) const | 232 | const value &operator[]( long iIndex ) const |
233 | { | 233 | { |
234 | if( iIndex < 0 || iIndex >= core->iSize ) | 234 | if( iIndex < 0 || iIndex >= core->iSize ) |
235 | throw ArrayException( | 235 | throw ArrayException( |
236 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 236 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
237 | 237 | ||
238 | return core->pData[iIndex]; | 238 | return core->pData[iIndex]; |
239 | } | 239 | } |
240 | 240 | ||
241 | value &get( long iIndex ) | 241 | value &get( long iIndex ) |
242 | { | 242 | { |
243 | _hardCopy(); | 243 | _hardCopy(); |
244 | if( iIndex < 0 || iIndex >= core->iSize ) | 244 | if( iIndex < 0 || iIndex >= core->iSize ) |
245 | throw ArrayException( | 245 | throw ArrayException( |
246 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 246 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
247 | 247 | ||
248 | return core->pData[iIndex]; | 248 | return core->pData[iIndex]; |
249 | } | 249 | } |
250 | 250 | ||
251 | const value &get( long iIndex ) const | 251 | const value &get( long iIndex ) const |
252 | { | 252 | { |
253 | if( iIndex < 0 || iIndex >= core->iSize ) | 253 | if( iIndex < 0 || iIndex >= core->iSize ) |
254 | throw ArrayException( | 254 | throw ArrayException( |
255 | "Index %d out of range 0:%d", iIndex, core->iSize ); | 255 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
256 | 256 | ||
257 | return core->pData[iIndex]; | 257 | return core->pData[iIndex]; |
258 | } | 258 | } |
259 | 259 | ||
260 | value &first() | 260 | value &first() |
261 | { | 261 | { |
262 | _hardCopy(); | 262 | _hardCopy(); |
263 | return core->pData[0]; | 263 | return core->pData[0]; |
264 | } | 264 | } |
265 | 265 | ||
266 | const value &first() const | 266 | const value &first() const |
267 | { | 267 | { |
268 | return core->pData[0]; | 268 | return core->pData[0]; |
269 | } | 269 | } |
270 | 270 | ||
271 | value &last() | 271 | value &last() |
272 | { | 272 | { |
273 | _hardCopy(); | 273 | _hardCopy(); |
274 | return core->pData[core->iSize-1]; | 274 | return core->pData[core->iSize-1]; |
275 | } | 275 | } |
276 | 276 | ||
277 | const value &last() const | 277 | const value &last() const |
278 | { | 278 | { |
279 | return core->pData[core->iSize-1]; | 279 | return core->pData[core->iSize-1]; |
280 | } | 280 | } |
281 | 281 | ||
282 | /** | 282 | /** |
283 | * Returns true if the array is empty. The capacity has no bearing on | 283 | * Returns true if the array is empty. The capacity has no bearing on |
284 | * this, only the size. | 284 | * this, only the size. |
285 | */ | 285 | */ |
286 | bool isEmpty() const | 286 | bool isEmpty() const |
287 | { | 287 | { |
288 | return core->iSize==0; | 288 | return core->iSize==0; |
289 | } | 289 | } |
290 | 290 | ||
291 | /** | 291 | /** |
292 | * Get the current size of the array. | 292 | * Get the current size of the array. |
293 | *@returns The current size of the array. | 293 | *@returns The current size of the array. |
294 | */ | 294 | */ |
295 | long getSize() const | 295 | long getSize() const |
296 | { | 296 | { |
297 | return core->iSize; | 297 | return core->iSize; |
298 | } | 298 | } |
299 | 299 | ||
300 | /** | 300 | /** |
301 | * Get the capacity of the array. This number will grow as data is | 301 | * Get the capacity of the array. This number will grow as data is |
302 | * added, and is mainly for the curious, it doesn't really determine | 302 | * added, and is mainly for the curious, it doesn't really determine |
303 | * much for the end user. | 303 | * much for the end user. |
304 | *@returns The current capacity of the array. | 304 | *@returns The current capacity of the array. |
305 | */ | 305 | */ |
306 | long getCapacity() const | 306 | long getCapacity() const |
307 | { | 307 | { |
308 | return core->iCapacity; | 308 | return core->iCapacity; |
309 | } | 309 | } |
310 | 310 | ||
311 | /** | 311 | /** |
312 | * Change the capacity of the array, very useful if you know you'll be | 312 | * Change the capacity of the array, very useful if you know you'll be |
313 | * adding a large amount of already counted items to the array, makes | 313 | * adding a large amount of already counted items to the array, makes |
314 | * the appending much faster afterwords. | 314 | * the appending much faster afterwords. |
315 | *@param iNewLen The new capacity of the array. | 315 | *@param iNewLen The new capacity of the array. |
316 | *@todo Set this up so it can reduce the size of the array as well as | 316 | *@todo Set this up so it can reduce the size of the array as well as |
317 | * make it bigger. | 317 | * make it bigger. |
318 | */ | 318 | */ |
319 | void setCapacity( long iNewLen ) | 319 | void setCapacity( long iNewLen ) |
320 | { | 320 | { |
321 | _hardCopy(); | 321 | _hardCopy(); |
322 | core->setCapacity( iNewLen ); | 322 | core->setCapacity( iNewLen ); |
323 | } | 323 | } |
324 | 324 | ||
325 | typedef struct iterator | 325 | typedef struct iterator |
326 | { | 326 | { |
327 | friend class Array<value, inc, valuealloc>; | 327 | friend class Array<value, inc, valuealloc>; |
328 | private: | 328 | private: |
329 | iterator( MyType &src, long iPos=0 ) : | 329 | iterator( MyType &src, long iPos=0 ) : |
330 | src( src ), | 330 | src( src ), |
331 | iPos( iPos ) | 331 | iPos( iPos ) |
332 | { | 332 | { |
333 | if( this->iPos >= src.getSize() ) | 333 | if( this->iPos >= src.getSize() ) |
334 | this->iPos = -1; | 334 | this->iPos = -1; |
335 | } | 335 | } |
336 | 336 | ||
337 | MyType &src; | 337 | MyType &src; |
338 | long iPos; | 338 | long iPos; |
339 | 339 | ||
340 | public: | 340 | public: |
341 | iterator operator++( int ) | 341 | iterator operator++( int ) |
342 | { | 342 | { |
343 | if( iPos < 0 ) | 343 | if( iPos < 0 ) |
344 | throw ArrayException( | 344 | throw ArrayException( |
345 | "Cannot increment iterator past end of array."); | 345 | "Cannot increment iterator past end of array."); |
346 | iPos++; | 346 | iPos++; |
347 | if( iPos >= src.getSize() ) | 347 | if( iPos >= src.getSize() ) |
348 | iPos = -1; | 348 | iPos = -1; |
349 | return *this; | 349 | return *this; |
350 | } | 350 | } |
351 | 351 | ||
352 | iterator operator++() | 352 | iterator operator++() |
353 | { | 353 | { |
354 | if( iPos >= 0 ) | 354 | if( iPos >= 0 ) |
355 | iPos++; | 355 | iPos++; |
356 | if( iPos >= src.getSize() ) | 356 | if( iPos >= src.getSize() ) |
357 | iPos = -1; | 357 | iPos = -1; |
358 | return *this; | 358 | return *this; |
359 | } | 359 | } |
360 | 360 | ||
361 | iterator operator+( int iAmnt ) | 361 | iterator operator+( int iAmnt ) |
362 | { | 362 | { |
363 | if( iPos < 0 ) | 363 | if( iPos < 0 ) |
364 | throw ArrayException( | 364 | throw ArrayException( |
365 | "Cannot increment iterator past end of array."); | 365 | "Cannot increment iterator past end of array."); |
366 | iPos += iAmnt; | 366 | iPos += iAmnt; |
367 | if( iPos >= src.getSize() ) | 367 | if( iPos >= src.getSize() ) |
368 | iPos = -1; | 368 | iPos = -1; |
369 | return *this; | 369 | return *this; |
370 | } | 370 | } |
371 | 371 | ||
372 | iterator operator--( int ) | 372 | iterator operator--( int ) |
373 | { | 373 | { |
374 | if( iPos < 0 ) | 374 | if( iPos < 0 ) |
375 | throw ArrayException( | 375 | throw ArrayException( |
376 | "Cannot increment iterator past end of array."); | 376 | "Cannot increment iterator past end of array."); |
377 | iPos--; | 377 | iPos--; |
378 | if( iPos < 0 ) | 378 | if( iPos < 0 ) |
379 | iPos = -1; | 379 | iPos = -1; |
380 | return *this; | 380 | return *this; |
381 | } | 381 | } |
382 | 382 | ||
383 | iterator operator--() | 383 | iterator operator--() |
384 | { | 384 | { |
385 | if( iPos < src.getSize() ) | 385 | if( iPos < src.getSize() ) |
386 | iPos--; | 386 | iPos--; |
387 | if( iPos <= 0 ) | 387 | if( iPos <= 0 ) |
388 | iPos = -1; | 388 | iPos = -1; |
389 | return *this; | 389 | return *this; |
390 | } | 390 | } |
391 | 391 | ||
392 | iterator operator-( int iAmnt ) | 392 | iterator operator-( int iAmnt ) |
393 | { | 393 | { |
394 | if( iPos < src.getSize() ) | 394 | if( iPos < src.getSize() ) |
395 | iPos -= iAmnt; | 395 | iPos -= iAmnt; |
396 | if( iPos <= 0 ) | 396 | if( iPos <= 0 ) |
397 | iPos = -1; | 397 | iPos = -1; |
398 | return *this; | 398 | return *this; |
399 | } | 399 | } |
400 | 400 | ||
401 | bool operator==( const iterator &oth ) const | 401 | bool operator==( const iterator &oth ) const |
402 | { | 402 | { |
403 | return iPos == oth.iPos; | 403 | return iPos == oth.iPos; |
404 | } | 404 | } |
405 | 405 | ||
406 | bool operator!=( const iterator &oth ) const | 406 | bool operator!=( const iterator &oth ) const |
407 | { | 407 | { |
408 | return iPos != oth.iPos; | 408 | return iPos != oth.iPos; |
409 | } | 409 | } |
410 | 410 | ||
411 | iterator operator=( const iterator &oth ) | 411 | iterator operator=( const iterator &oth ) |
412 | { | 412 | { |
413 | if( &src != &oth.src ) | 413 | if( &src != &oth.src ) |
414 | throw ArrayException( | 414 | throw ArrayException( |
415 | "Cannot mix iterators from different array objects."); | 415 | "Cannot mix iterators from different array objects."); |
416 | iPos = oth.iPos; | 416 | iPos = oth.iPos; |
417 | } | 417 | } |
418 | 418 | ||
419 | value &operator*() | 419 | value &operator*() |
420 | { | 420 | { |
421 | if( iPos < 0 ) | 421 | if( iPos < 0 ) |
422 | throw ArrayException( | 422 | throw ArrayException( |
423 | "Cannot dereference finished iterator."); | 423 | "Cannot dereference finished iterator."); |
424 | return src[iPos]; | 424 | return src[iPos]; |
425 | } | 425 | } |
426 | 426 | ||
427 | long getIndex() const | 427 | long getIndex() const |
428 | { | 428 | { |
429 | return iPos; | 429 | return iPos; |
430 | } | 430 | } |
431 | 431 | ||
432 | operator bool() const | 432 | operator bool() const |
433 | { | 433 | { |
434 | return iPos >= 0; | 434 | return iPos >= 0; |
435 | } | 435 | } |
436 | 436 | ||
437 | bool isValid() const | 437 | bool isValid() const |
438 | { | 438 | { |
439 | return iPos >= 0; | 439 | return iPos >= 0; |
440 | } | 440 | } |
441 | } iterator; | 441 | } iterator; |
442 | 442 | ||
443 | typedef struct const_iterator | 443 | typedef struct const_iterator |
444 | { | 444 | { |
445 | friend class Array<value, inc, valuealloc>; | 445 | friend class Array<value, inc, valuealloc>; |
446 | private: | 446 | private: |
447 | const_iterator( const MyType &src, long iPos=0 ) : | 447 | const_iterator( const MyType &src, long iPos=0 ) : |
448 | src( src ), | 448 | src( src ), |
449 | iPos( iPos ) | 449 | iPos( iPos ) |
450 | { | 450 | { |
451 | if( this->iPos >= src.getSize() ) | 451 | if( this->iPos >= src.getSize() ) |
452 | this->iPos = -1; | 452 | this->iPos = -1; |
453 | } | 453 | } |
454 | 454 | ||
455 | const MyType &src; | 455 | const MyType &src; |
456 | long iPos; | 456 | long iPos; |
457 | 457 | ||
458 | public: | 458 | public: |
459 | const_iterator( iterator &rSrc ) : | 459 | const_iterator( iterator &rSrc ) : |
460 | src( rSrc.src ), | 460 | src( rSrc.src ), |
461 | iPos( rSrc.iPos ) | 461 | iPos( rSrc.iPos ) |
462 | { | 462 | { |
463 | } | 463 | } |
464 | const_iterator operator++( int ) | 464 | const_iterator operator++( int ) |
465 | { | 465 | { |
466 | if( iPos < 0 ) | 466 | if( iPos < 0 ) |
467 | throw ArrayException( | 467 | throw ArrayException( |
468 | "Cannot increment iterator past end of array."); | 468 | "Cannot increment iterator past end of array."); |
469 | iPos++; | 469 | iPos++; |
470 | if( iPos >= src.getSize() ) | 470 | if( iPos >= src.getSize() ) |
471 | iPos = -1; | 471 | iPos = -1; |
472 | return *this; | 472 | return *this; |
473 | } | 473 | } |
474 | 474 | ||
475 | const_iterator operator++() | 475 | const_iterator operator++() |
476 | { | 476 | { |
477 | if( iPos >= 0 ) | 477 | if( iPos >= 0 ) |
478 | iPos++; | 478 | iPos++; |
479 | if( iPos >= src.getSize() ) | 479 | if( iPos >= src.getSize() ) |
480 | iPos = -1; | 480 | iPos = -1; |
481 | return *this; | 481 | return *this; |
482 | } | 482 | } |
483 | 483 | ||
484 | const_iterator operator--( int ) | 484 | const_iterator operator--( int ) |
485 | { | 485 | { |
486 | if( iPos < 0 ) | 486 | if( iPos < 0 ) |
487 | throw ArrayException( | 487 | throw ArrayException( |
488 | "Cannot increment iterator past end of array."); | 488 | "Cannot increment iterator past end of array."); |
489 | iPos--; | 489 | iPos--; |
490 | if( iPos < 0 ) | 490 | if( iPos < 0 ) |
491 | iPos = -1; | 491 | iPos = -1; |
492 | return *this; | 492 | return *this; |
493 | } | 493 | } |
494 | 494 | ||
495 | const_iterator operator--() | 495 | const_iterator operator--() |
496 | { | 496 | { |
497 | if( iPos < src.getSize() ) | 497 | if( iPos < src.getSize() ) |
498 | iPos--; | 498 | iPos--; |
499 | if( iPos <= 0 ) | 499 | if( iPos <= 0 ) |
500 | iPos = -1; | 500 | iPos = -1; |
501 | return *this; | 501 | return *this; |
502 | } | 502 | } |
503 | 503 | ||
504 | bool operator==( const const_iterator &oth ) const | 504 | bool operator==( const const_iterator &oth ) const |
505 | { | 505 | { |
506 | return iPos == oth.iPos; | 506 | return iPos == oth.iPos; |
507 | } | 507 | } |
508 | 508 | ||
509 | bool operator!=( const const_iterator &oth ) const | 509 | bool operator!=( const const_iterator &oth ) const |
510 | { | 510 | { |
511 | return iPos != oth.iPos; | 511 | return iPos != oth.iPos; |
512 | } | 512 | } |
513 | 513 | ||
514 | const_iterator operator=( const const_iterator &oth ) | 514 | const_iterator operator=( const const_iterator &oth ) |
515 | { | 515 | { |
516 | if( &src != &oth.src ) | 516 | if( &src != &oth.src ) |
517 | throw ArrayException( | 517 | throw ArrayException( |
518 | "Cannot mix iterators from different array objects."); | 518 | "Cannot mix iterators from different array objects."); |
519 | iPos = oth.iPos; | 519 | iPos = oth.iPos; |
520 | } | 520 | } |
521 | 521 | ||
522 | const value &operator*() const | 522 | const value &operator*() const |
523 | { | 523 | { |
524 | if( iPos < 0 ) | 524 | if( iPos < 0 ) |
525 | throw ArrayException( | 525 | throw ArrayException( |
526 | "Cannot dereference finished iterator."); | 526 | "Cannot dereference finished iterator."); |
527 | return src[iPos]; | 527 | return src[iPos]; |
528 | } | 528 | } |
529 | 529 | ||
530 | long getIndex() const | 530 | long getIndex() const |
531 | { | 531 | { |
532 | return iPos; | 532 | return iPos; |
533 | } | 533 | } |
534 | 534 | ||
535 | operator bool() const | 535 | operator bool() const |
536 | { | 536 | { |
537 | return iPos >= 0; | 537 | return iPos >= 0; |
538 | } | 538 | } |
539 | 539 | ||
540 | bool isValid() const | 540 | bool isValid() const |
541 | { | 541 | { |
542 | return iPos >= 0; | 542 | return iPos >= 0; |
543 | } | 543 | } |
544 | } const_iterator; | 544 | } const_iterator; |
545 | 545 | ||
546 | iterator begin() | 546 | iterator begin() |
547 | { | 547 | { |
548 | return iterator( *this ); | 548 | return iterator( *this ); |
549 | } | 549 | } |
550 | 550 | ||
551 | const_iterator begin() const | 551 | const_iterator begin() const |
552 | { | 552 | { |
553 | return const_iterator( *this ); | 553 | return const_iterator( *this ); |
554 | } | 554 | } |
555 | 555 | ||
556 | iterator end() | 556 | iterator end() |
557 | { | 557 | { |
558 | return iterator( *this, -1 ); | 558 | return iterator( *this, -1 ); |
559 | } | 559 | } |
560 | 560 | ||
561 | const_iterator end() const | 561 | const_iterator end() const |
562 | { | 562 | { |
563 | return const_iterator( *this, -1 ); | 563 | return const_iterator( *this, -1 ); |
564 | } | 564 | } |
565 | 565 | ||
566 | MyType &insert( iterator i, const value &rVal ) | 566 | MyType &insert( iterator i, const value &rVal ) |
567 | { | 567 | { |
568 | if( i.iPos == -1 ) | 568 | if( i.iPos == -1 ) |
569 | { | 569 | { |
570 | append( rVal ); | 570 | append( rVal ); |
571 | return *this; | 571 | return *this; |
572 | } | 572 | } |
573 | 573 | ||
574 | _hardCopy(); | 574 | _hardCopy(); |
575 | if( core->iSize == core->iCapacity ) | 575 | if( core->iSize == core->iCapacity ) |
576 | { | 576 | { |
577 | core->setCapacity( core->iCapacity + inc ); | 577 | core->setCapacity( core->iCapacity + inc ); |
578 | } | 578 | } |
579 | core->iSize++; | 579 | core->iSize++; |
580 | 580 | ||
581 | core->va.construct( | 581 | core->va.construct( |
582 | &core->pData[core->iSize-1], | 582 | &core->pData[core->iSize-1], |
583 | core->pData[core->iSize-2] | 583 | core->pData[core->iSize-2] |
584 | ); | 584 | ); |
585 | for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) | 585 | for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) |
586 | { | 586 | { |
587 | core->va.destroy( &core->pData[iPos] ); | 587 | core->va.destroy( &core->pData[iPos] ); |
588 | core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); | 588 | core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); |
589 | } | 589 | } |
590 | core->va.destroy( &core->pData[i.iPos] ); | 590 | core->va.destroy( &core->pData[i.iPos] ); |
591 | core->va.construct( &core->pData[i.iPos], rVal ); | 591 | core->va.construct( &core->pData[i.iPos], rVal ); |
592 | 592 | ||
593 | return *this; | 593 | return *this; |
594 | } | 594 | } |
595 | 595 | ||
596 | /** | 596 | /** |
597 | * If order is important, use this. It will delete the suggested item | 597 | * If order is important, use this. It will delete the suggested item |
598 | * and move the rest of the data up a spot. This is a time O(n) | 598 | * and move the rest of the data up a spot. This is a time O(n) |
599 | * operation. If the order isn't important, check swapErase | 599 | * operation. If the order isn't important, check swapErase |
600 | */ | 600 | */ |
601 | void erase( iterator i ) | 601 | void erase( iterator i ) |
602 | { | 602 | { |
603 | _hardCopy(); | 603 | _hardCopy(); |
604 | core->erase( i.iPos ); | 604 | core->erase( i.iPos ); |
605 | } | 605 | } |
606 | 606 | ||
607 | void erase( const value &v ) | 607 | void erase( const value &v ) |
608 | { | 608 | { |
609 | _hardCopy(); | 609 | _hardCopy(); |
610 | for( int j = 0; j < core->iSize; j++ ) | 610 | for( int j = 0; j < core->iSize; j++ ) |
611 | { | 611 | { |
612 | if( core->pData[j] == v ) | 612 | if( core->pData[j] == v ) |
613 | { | 613 | { |
614 | core->erase( j ); | 614 | core->erase( j ); |
615 | return; | 615 | return; |
616 | } | 616 | } |
617 | } | 617 | } |
618 | } | 618 | } |
619 | 619 | ||
620 | void eraseLast() | 620 | void eraseLast() |
621 | { | 621 | { |
622 | _hardCopy(); | 622 | _hardCopy(); |
623 | core->erase( core->iSize-1 ); | 623 | core->erase( core->iSize-1 ); |
624 | } | 624 | } |
625 | 625 | ||
626 | void eraseFirst() | 626 | void eraseFirst() |
627 | { | 627 | { |
628 | _hardCopy(); | 628 | _hardCopy(); |
629 | core->erase( 0 ); | 629 | core->erase( 0 ); |
630 | } | 630 | } |
631 | 631 | ||
632 | /** | 632 | /** |
633 | * In order to make swapErase faster, what it does is swap the given | 633 | * In order to make swapErase faster, what it does is swap the given |
634 | * item in the array with the last item, then make the array shorter | 634 | * item in the array with the last item, then make the array shorter |
635 | * by one. It changes the order of the elements in the array, so it | 635 | * by one. It changes the order of the elements in the array, so it |
636 | * should be used carefully, but it is time O(1) instead of O(n) like | 636 | * should be used carefully, but it is time O(1) instead of O(n) like |
637 | * erase. | 637 | * erase. |
638 | */ | 638 | */ |
639 | void swapErase( iterator i ) | 639 | void swapErase( iterator i ) |
640 | { | 640 | { |
641 | _hardCopy(); | 641 | _hardCopy(); |
642 | core->swapErase( i.iPos ); | 642 | core->swapErase( i.iPos ); |
643 | } | 643 | } |
644 | 644 | ||
645 | protected: | 645 | protected: |
646 | virtual Core *_copyCore( Core *src ) | 646 | virtual Core *_copyCore( Core *src ) |
647 | { | 647 | { |
648 | Core *pRet = _allocateCore(); | 648 | Core *pRet = _allocateCore(); |
649 | pRet->setCapacity( src->iCapacity ); | 649 | pRet->setCapacity( src->iCapacity ); |
650 | pRet->iSize = src->iSize; | 650 | pRet->iSize = src->iSize; |
651 | for( int j = 0; j < src->iSize; j++ ) | 651 | for( int j = 0; j < src->iSize; j++ ) |
652 | { | 652 | { |
653 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); | 653 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); |
654 | } | 654 | } |
655 | return pRet; | 655 | return pRet; |
656 | } | 656 | } |
657 | 657 | ||
658 | private: | 658 | private: |
659 | }; | 659 | }; |
660 | 660 | ||
661 | class Formatter; | 661 | class Formatter; |
662 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 662 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
663 | Formatter &operator<<( Formatter &rOut, signed char c ); | 663 | Formatter &operator<<( Formatter &rOut, signed char c ); |
664 | template<typename value> | 664 | template<typename value> |
665 | Formatter &operator<<( Formatter &f, const Bu::Array<value> &a ) | 665 | Formatter &operator<<( Formatter &f, const Bu::Array<value> &a ) |
666 | { | 666 | { |
667 | f << '['; | 667 | f << '['; |
668 | for( typename Bu::Array<value>::const_iterator i = a.begin(); i; i++ ) | 668 | for( typename Bu::Array<value>::const_iterator i = a.begin(); i; i++ ) |
669 | { | 669 | { |
670 | if( i != a.begin() ) | 670 | if( i != a.begin() ) |
671 | f << ", "; | 671 | f << ", "; |
672 | f << *i; | 672 | f << *i; |
673 | } | 673 | } |
674 | f << ']'; | 674 | f << ']'; |
675 | 675 | ||
676 | return f; | 676 | return f; |
677 | } | 677 | } |
678 | 678 | ||
679 | template<typename value, int inc, typename valuealloc> | 679 | template<typename value, int inc, typename valuealloc> |
680 | ArchiveBase &operator<<( ArchiveBase &ar, | 680 | ArchiveBase &operator<<( ArchiveBase &ar, |
681 | const Array<value, inc, valuealloc> &h ) | 681 | const Array<value, inc, valuealloc> &h ) |
682 | { | 682 | { |
683 | ar << h.getSize(); | 683 | ar << h.getSize(); |
684 | for( typename Array<value, inc, valuealloc>::const_iterator i = | 684 | for( typename Array<value, inc, valuealloc>::const_iterator i = |
685 | h.begin(); i != h.end(); i++ ) | 685 | h.begin(); i != h.end(); i++ ) |
686 | { | 686 | { |
687 | ar << (*i); | 687 | ar << (*i); |
688 | } | 688 | } |
689 | 689 | ||
690 | return ar; | 690 | return ar; |
691 | } | 691 | } |
692 | 692 | ||
693 | template<typename value, int inc, typename valuealloc> | 693 | template<typename value, int inc, typename valuealloc> |
694 | ArchiveBase &operator>>(ArchiveBase &ar, Array<value, inc, valuealloc> &h ) | 694 | ArchiveBase &operator>>(ArchiveBase &ar, Array<value, inc, valuealloc> &h ) |
695 | { | 695 | { |
696 | h.clear(); | 696 | h.clear(); |
697 | long nSize; | 697 | long nSize; |
698 | ar >> nSize; | 698 | ar >> nSize; |
699 | 699 | ||
700 | h.setCapacity( nSize ); | 700 | h.setCapacity( nSize ); |
701 | for( long j = 0; j < nSize; j++ ) | 701 | for( long j = 0; j < nSize; j++ ) |
702 | { | 702 | { |
703 | value v; | 703 | value v; |
704 | ar >> v; | 704 | ar >> v; |
705 | h.append( v ); | 705 | h.append( v ); |
706 | } | 706 | } |
707 | return ar; | 707 | return ar; |
708 | } | 708 | } |
709 | 709 | ||
710 | } | 710 | } |
711 | 711 | ||
diff --git a/src/stable/atom.h b/src/stable/atom.h index 105c29a..9679ab6 100644 --- a/src/stable/atom.h +++ b/src/stable/atom.h | |||
@@ -15,133 +15,133 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * | 19 | * |
20 | *@ingroup Containers | 20 | *@ingroup Containers |
21 | */ | 21 | */ |
22 | template <typename t, typename talloc=std::allocator<t> > | 22 | template <typename t, typename talloc=std::allocator<t> > |
23 | class Atom | 23 | class Atom |
24 | { | 24 | { |
25 | private: | 25 | private: |
26 | typedef struct Atom<t, talloc> MyType; | 26 | typedef struct Atom<t, talloc> MyType; |
27 | 27 | ||
28 | public: | 28 | public: |
29 | Atom() : | 29 | Atom() : |
30 | pData( NULL ) | 30 | pData( NULL ) |
31 | { | 31 | { |
32 | } | 32 | } |
33 | 33 | ||
34 | Atom( const MyType &oth ) : | 34 | Atom( const MyType &oth ) : |
35 | pData( NULL ) | 35 | pData( NULL ) |
36 | { | 36 | { |
37 | if( oth.pData ) | 37 | if( oth.pData ) |
38 | set( *oth.pData ); | 38 | set( *oth.pData ); |
39 | } | 39 | } |
40 | 40 | ||
41 | Atom( const t &oth ) : | 41 | Atom( const t &oth ) : |
42 | pData( NULL ) | 42 | pData( NULL ) |
43 | { | 43 | { |
44 | set( oth ); | 44 | set( oth ); |
45 | } | 45 | } |
46 | 46 | ||
47 | virtual ~Atom() | 47 | virtual ~Atom() |
48 | { | 48 | { |
49 | clear(); | 49 | clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | bool has() const | 52 | bool has() const |
53 | { | 53 | { |
54 | return (pData != NULL); | 54 | return (pData != NULL); |
55 | } | 55 | } |
56 | 56 | ||
57 | void set( const t &val ) | 57 | void set( const t &val ) |
58 | { | 58 | { |
59 | clear(); | 59 | clear(); |
60 | pData = ta.allocate( 1 ); | 60 | pData = ta.allocate( 1 ); |
61 | ta.construct( pData, val ); | 61 | ta.construct( pData, val ); |
62 | } | 62 | } |
63 | 63 | ||
64 | t &get() | 64 | t &get() |
65 | { | 65 | { |
66 | if( !pData ) | 66 | if( !pData ) |
67 | throw Bu::ExceptionBase("Not set"); | 67 | throw Bu::ExceptionBase("Not set"); |
68 | return *pData; | 68 | return *pData; |
69 | } | 69 | } |
70 | 70 | ||
71 | const t &get() const | 71 | const t &get() const |
72 | { | 72 | { |
73 | if( !pData ) | 73 | if( !pData ) |
74 | throw Bu::ExceptionBase("Not set"); | 74 | throw Bu::ExceptionBase("Not set"); |
75 | return *pData; | 75 | return *pData; |
76 | } | 76 | } |
77 | 77 | ||
78 | void clear() | 78 | void clear() |
79 | { | 79 | { |
80 | if( pData ) | 80 | if( pData ) |
81 | { | 81 | { |
82 | ta.destroy( pData ); | 82 | ta.destroy( pData ); |
83 | ta.deallocate( pData, 1 ); | 83 | ta.deallocate( pData, 1 ); |
84 | pData = NULL; | 84 | pData = NULL; |
85 | } | 85 | } |
86 | } | 86 | } |
87 | 87 | ||
88 | operator const t &() const | 88 | operator const t &() const |
89 | { | 89 | { |
90 | if( !pData ) | 90 | if( !pData ) |
91 | throw Bu::ExceptionBase("Not set"); | 91 | throw Bu::ExceptionBase("Not set"); |
92 | return *pData; | 92 | return *pData; |
93 | } | 93 | } |
94 | 94 | ||
95 | operator t &() | 95 | operator t &() |
96 | { | 96 | { |
97 | if( !pData ) | 97 | if( !pData ) |
98 | throw Bu::ExceptionBase("Not set"); | 98 | throw Bu::ExceptionBase("Not set"); |
99 | return *pData; | 99 | return *pData; |
100 | } | 100 | } |
101 | 101 | ||
102 | MyType &operator =( const t &oth ) | 102 | MyType &operator =( const t &oth ) |
103 | { | 103 | { |
104 | set( oth ); | 104 | set( oth ); |
105 | 105 | ||
106 | return *this; | 106 | return *this; |
107 | } | 107 | } |
108 | 108 | ||
109 | MyType &operator =( const MyType &oth ) | 109 | MyType &operator =( const MyType &oth ) |
110 | { | 110 | { |
111 | if( oth.pData ) | 111 | if( oth.pData ) |
112 | set( *oth.pData ); | 112 | set( *oth.pData ); |
113 | 113 | ||
114 | return *this; | 114 | return *this; |
115 | } | 115 | } |
116 | 116 | ||
117 | bool operator ==( const MyType &oth ) | 117 | bool operator ==( const MyType &oth ) |
118 | { | 118 | { |
119 | return (*pData) == (*oth.pData); | 119 | return (*pData) == (*oth.pData); |
120 | } | 120 | } |
121 | 121 | ||
122 | bool operator ==( const t &oth ) | 122 | bool operator ==( const t &oth ) |
123 | { | 123 | { |
124 | return (*pData) == oth; | 124 | return (*pData) == oth; |
125 | } | 125 | } |
126 | 126 | ||
127 | t *operator ->() | 127 | t *operator ->() |
128 | { | 128 | { |
129 | if( !pData ) | 129 | if( !pData ) |
130 | throw Bu::ExceptionBase("Not set"); | 130 | throw Bu::ExceptionBase("Not set"); |
131 | return pData; | 131 | return pData; |
132 | } | 132 | } |
133 | 133 | ||
134 | t &operator *() | 134 | t &operator *() |
135 | { | 135 | { |
136 | if( !pData ) | 136 | if( !pData ) |
137 | throw Bu::ExceptionBase("Not set"); | 137 | throw Bu::ExceptionBase("Not set"); |
138 | return *pData; | 138 | return *pData; |
139 | } | 139 | } |
140 | 140 | ||
141 | private: | 141 | private: |
142 | t *pData; | 142 | t *pData; |
143 | talloc ta; | 143 | talloc ta; |
144 | }; | 144 | }; |
145 | } | 145 | } |
146 | 146 | ||
147 | #endif | 147 | #endif |
diff --git a/src/stable/base64.cpp b/src/stable/base64.cpp index 5ace999..2dc123f 100644 --- a/src/stable/base64.cpp +++ b/src/stable/base64.cpp | |||
@@ -10,210 +10,210 @@ | |||
10 | namespace Bu { subExceptionDef( Base64Exception ) } | 10 | namespace Bu { subExceptionDef( Base64Exception ) } |
11 | 11 | ||
12 | const char Bu::Base64::tblEnc[65] = { | 12 | const char Bu::Base64::tblEnc[65] = { |
13 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | 13 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" |
14 | }; | 14 | }; |
15 | 15 | ||
16 | Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : | 16 | Bu::Base64::Base64( Bu::Stream &rNext, int iChunkSize ) : |
17 | Bu::Filter( rNext ), | 17 | Bu::Filter( rNext ), |
18 | iBPos( 0 ), | 18 | iBPos( 0 ), |
19 | iBuf( 0 ), | 19 | iBuf( 0 ), |
20 | iRPos( 0 ), | 20 | iRPos( 0 ), |
21 | iChars( 0 ), | 21 | iChars( 0 ), |
22 | bEosIn( false ), | 22 | bEosIn( false ), |
23 | iTotalIn( 0 ), | 23 | iTotalIn( 0 ), |
24 | iTotalOut( 0 ), | 24 | iTotalOut( 0 ), |
25 | eMode( Nothing ), | 25 | eMode( Nothing ), |
26 | iChunkSize( iChunkSize ), | 26 | iChunkSize( iChunkSize ), |
27 | iCurChunk( 0 ) | 27 | iCurChunk( 0 ) |
28 | { | 28 | { |
29 | start(); | 29 | start(); |
30 | 30 | ||
31 | memset( tblDec, 0, 80 ); | 31 | memset( tblDec, 0, 80 ); |
32 | for( int j = 0; j < 64; j++ ) | 32 | for( int j = 0; j < 64; j++ ) |
33 | { | 33 | { |
34 | tblDec[tblEnc[j]-'+'] = j; | 34 | tblDec[tblEnc[j]-'+'] = j; |
35 | // printf("'%c' = %d\n", tblEnc[j], j ); | 35 | // printf("'%c' = %d\n", tblEnc[j], j ); |
36 | } | 36 | } |
37 | /* | 37 | /* |
38 | for( int j = 0; j < 64; j++ ) | 38 | for( int j = 0; j < 64; j++ ) |
39 | { | 39 | { |
40 | printf("'%c' = '%c' (%d = %d)\n", | 40 | printf("'%c' = '%c' (%d = %d)\n", |
41 | tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], | 41 | tblEnc[j], tblEnc[tblDec[tblEnc[j]-'+']], |
42 | j, tblDec[tblEnc[j]-'+'] ); | 42 | j, tblDec[tblEnc[j]-'+'] ); |
43 | }*/ | 43 | }*/ |
44 | 44 | ||
45 | // The following is used to compute the table size for the decoding table. | 45 | // The following is used to compute the table size for the decoding table. |
46 | /* | 46 | /* |
47 | char low='A', high='A'; | 47 | char low='A', high='A'; |
48 | for( int j = 0; j < 64; j++ ) | 48 | for( int j = 0; j < 64; j++ ) |
49 | { | 49 | { |
50 | if( tblEnc[j] < low ) | 50 | if( tblEnc[j] < low ) |
51 | low = tblEnc[j]; | 51 | low = tblEnc[j]; |
52 | if( tblEnc[j] > high ) | 52 | if( tblEnc[j] > high ) |
53 | high = tblEnc[j]; | 53 | high = tblEnc[j]; |
54 | } | 54 | } |
55 | 55 | ||
56 | printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); | 56 | printf("'%c' - '%c' (%d - %d) (%d)\n", low, high, low, high, high-low ); |
57 | */ | 57 | */ |
58 | } | 58 | } |
59 | 59 | ||
60 | Bu::Base64::~Base64() | 60 | Bu::Base64::~Base64() |
61 | { | 61 | { |
62 | stop(); | 62 | stop(); |
63 | } | 63 | } |
64 | 64 | ||
65 | void Bu::Base64::start() | 65 | void Bu::Base64::start() |
66 | { | 66 | { |
67 | iCurChunk = 0; | 67 | iCurChunk = 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | Bu::size Bu::Base64::stop() | 70 | Bu::size Bu::Base64::stop() |
71 | { | 71 | { |
72 | if( eMode == Encode ) | 72 | if( eMode == Encode ) |
73 | { | 73 | { |
74 | char outBuf[4]; | 74 | char outBuf[4]; |
75 | int iBUsed = 4-(3-iBPos); | 75 | int iBUsed = 4-(3-iBPos); |
76 | if( iBPos == 0 ) | 76 | if( iBPos == 0 ) |
77 | return iTotalOut; | 77 | return iTotalOut; |
78 | for( int k = 0; k < 4; k++ ) | 78 | for( int k = 0; k < 4; k++ ) |
79 | { | 79 | { |
80 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; | 80 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; |
81 | } | 81 | } |
82 | for( int k = iBUsed; k < 4; k++ ) | 82 | for( int k = iBUsed; k < 4; k++ ) |
83 | { | 83 | { |
84 | outBuf[k] = '='; | 84 | outBuf[k] = '='; |
85 | } | 85 | } |
86 | iCurChunk += 4; | 86 | iCurChunk += 4; |
87 | if( iChunkSize && iCurChunk >= iChunkSize ) | 87 | if( iChunkSize && iCurChunk >= iChunkSize ) |
88 | { | 88 | { |
89 | iCurChunk = iCurChunk-iChunkSize; | 89 | iCurChunk = iCurChunk-iChunkSize; |
90 | iTotalOut += rNext.write( outBuf, 4-iCurChunk ); | 90 | iTotalOut += rNext.write( outBuf, 4-iCurChunk ); |
91 | iTotalOut += rNext.write("\r\n", 2 ); | 91 | iTotalOut += rNext.write("\r\n", 2 ); |
92 | iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); | 92 | iTotalOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); |
93 | } | 93 | } |
94 | else | 94 | else |
95 | iTotalOut += rNext.write( outBuf, 4 ); | 95 | iTotalOut += rNext.write( outBuf, 4 ); |
96 | return iTotalOut; | 96 | return iTotalOut; |
97 | } | 97 | } |
98 | else | 98 | else |
99 | { | 99 | { |
100 | return iTotalIn; | 100 | return iTotalIn; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) | 104 | Bu::size Bu::Base64::read( void *pBuf, Bu::size nBytes ) |
105 | { | 105 | { |
106 | if( eMode == Encode ) | 106 | if( eMode == Encode ) |
107 | throw Bu::Base64Exception("Cannot read from an output stream."); | 107 | throw Bu::Base64Exception("Cannot read from an output stream."); |
108 | eMode = Decode; | 108 | eMode = Decode; |
109 | 109 | ||
110 | if( bEosIn == true && iRPos == iChars ) | 110 | if( bEosIn == true && iRPos == iChars ) |
111 | return 0; | 111 | return 0; |
112 | Bu::size sIn = 0; | 112 | Bu::size sIn = 0; |
113 | char buf[4]; | 113 | char buf[4]; |
114 | while( sIn < nBytes ) | 114 | while( sIn < nBytes ) |
115 | { | 115 | { |
116 | for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) | 116 | for(; iRPos < iChars && sIn < nBytes; iRPos++, sIn++ ) |
117 | { | 117 | { |
118 | ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; | 118 | ((unsigned char *)pBuf)[sIn] = (iBuf>>(8*(2-iRPos)))&0xFF; |
119 | } | 119 | } |
120 | if( iRPos == iChars ) | 120 | if( iRPos == iChars ) |
121 | { | 121 | { |
122 | if( bEosIn == true ) | 122 | if( bEosIn == true ) |
123 | return sIn; | 123 | return sIn; |
124 | else | 124 | else |
125 | iRPos = 0; | 125 | iRPos = 0; |
126 | } | 126 | } |
127 | else if( sIn == nBytes ) | 127 | else if( sIn == nBytes ) |
128 | return sIn; | 128 | return sIn; |
129 | //if( rNext.read( buf, 4 ) == 0 ) | 129 | //if( rNext.read( buf, 4 ) == 0 ) |
130 | // return sIn; | 130 | // return sIn; |
131 | for( int j = 0; j < 4; j++ ) | 131 | for( int j = 0; j < 4; j++ ) |
132 | { | 132 | { |
133 | if( rNext.read( &buf[j], 1 ) == 0 ) | 133 | if( rNext.read( &buf[j], 1 ) == 0 ) |
134 | { | 134 | { |
135 | if( rNext.isEos() ) | 135 | if( rNext.isEos() ) |
136 | { | 136 | { |
137 | if( iRPos == 0 ) | 137 | if( iRPos == 0 ) |
138 | iRPos = iChars; | 138 | iRPos = iChars; |
139 | bEosIn = true; | 139 | bEosIn = true; |
140 | if( j != 0 ) | 140 | if( j != 0 ) |
141 | { | 141 | { |
142 | throw Base64Exception( | 142 | throw Base64Exception( |
143 | "Premature end of stream detected while " | 143 | "Premature end of stream detected while " |
144 | "decoding Base64 data." | 144 | "decoding Base64 data." |
145 | ); | 145 | ); |
146 | } | 146 | } |
147 | } | 147 | } |
148 | return sIn; | 148 | return sIn; |
149 | } | 149 | } |
150 | if( buf[j] == ' ' || buf[j] == '\t' || | 150 | if( buf[j] == ' ' || buf[j] == '\t' || |
151 | buf[j] == '\n' || buf[j] == '\r' ) | 151 | buf[j] == '\n' || buf[j] == '\r' ) |
152 | { | 152 | { |
153 | j--; | 153 | j--; |
154 | } | 154 | } |
155 | } | 155 | } |
156 | iChars = 3; | 156 | iChars = 3; |
157 | iBuf = 0; | 157 | iBuf = 0; |
158 | for( int j = 0; j < 4; j++ ) | 158 | for( int j = 0; j < 4; j++ ) |
159 | { | 159 | { |
160 | if( buf[j] == '=' ) | 160 | if( buf[j] == '=' ) |
161 | { | 161 | { |
162 | iChars--; | 162 | iChars--; |
163 | bEosIn = true; | 163 | bEosIn = true; |
164 | } | 164 | } |
165 | else | 165 | else |
166 | iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); | 166 | iBuf |= (tblDec[buf[j]-'+']&0x3f)<<((3-j)*6); |
167 | //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); | 167 | //printf("%d: %06X (%02X)\n", j, iBuf, (tblDec[buf[j]-'+']&0x3f) ); |
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | return sIn; | 171 | return sIn; |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) | 174 | Bu::size Bu::Base64::write( const void *pBuf, Bu::size nBytes ) |
175 | { | 175 | { |
176 | if( eMode == Decode ) | 176 | if( eMode == Decode ) |
177 | throw Bu::Base64Exception("Cannot write to an input stream."); | 177 | throw Bu::Base64Exception("Cannot write to an input stream."); |
178 | eMode = Encode; | 178 | eMode = Encode; |
179 | 179 | ||
180 | Bu::size sOut = 0; | 180 | Bu::size sOut = 0; |
181 | char outBuf[4]; | 181 | char outBuf[4]; |
182 | for( Bu::size j = 0; j < nBytes; j++ ) | 182 | for( Bu::size j = 0; j < nBytes; j++ ) |
183 | { | 183 | { |
184 | iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); | 184 | iBuf |= (((uint8_t *)pBuf)[j])<<((2-iBPos++)*8); |
185 | if( iBPos == 3 ) | 185 | if( iBPos == 3 ) |
186 | { | 186 | { |
187 | for( int k = 0; k < 4; k++ ) | 187 | for( int k = 0; k < 4; k++ ) |
188 | { | 188 | { |
189 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; | 189 | outBuf[3-k] = tblEnc[(iBuf>>(6*k))&0x3f]; |
190 | } | 190 | } |
191 | iCurChunk += 4; | 191 | iCurChunk += 4; |
192 | if( iChunkSize && iCurChunk >= iChunkSize ) | 192 | if( iChunkSize && iCurChunk >= iChunkSize ) |
193 | { | 193 | { |
194 | iCurChunk = iCurChunk-iChunkSize; | 194 | iCurChunk = iCurChunk-iChunkSize; |
195 | sOut += rNext.write( outBuf, 4-iCurChunk ); | 195 | sOut += rNext.write( outBuf, 4-iCurChunk ); |
196 | sOut += rNext.write("\r\n", 2 ); | 196 | sOut += rNext.write("\r\n", 2 ); |
197 | sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); | 197 | sOut += rNext.write( outBuf+(4-iCurChunk), iCurChunk ); |
198 | } | 198 | } |
199 | else | 199 | else |
200 | sOut += rNext.write( outBuf, 4 ); | 200 | sOut += rNext.write( outBuf, 4 ); |
201 | iBPos = iBuf = 0; | 201 | iBPos = iBuf = 0; |
202 | } | 202 | } |
203 | } | 203 | } |
204 | iTotalOut += sOut; | 204 | iTotalOut += sOut; |
205 | return sOut; | 205 | return sOut; |
206 | } | 206 | } |
207 | 207 | ||
208 | bool Bu::Base64::isOpen() | 208 | bool Bu::Base64::isOpen() |
209 | { | 209 | { |
210 | return true; | 210 | return true; |
211 | } | 211 | } |
212 | 212 | ||
213 | bool Bu::Base64::isEos() | 213 | bool Bu::Base64::isEos() |
214 | { | 214 | { |
215 | if( bEosIn == true && iRPos == iChars ) | 215 | if( bEosIn == true && iRPos == iChars ) |
216 | return true; | 216 | return true; |
217 | return false; | 217 | return false; |
218 | } | 218 | } |
219 | 219 | ||
diff --git a/src/stable/base64.h b/src/stable/base64.h index b10aaeb..695a5ea 100644 --- a/src/stable/base64.h +++ b/src/stable/base64.h | |||
@@ -13,47 +13,47 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | subExceptionDecl( Base64Exception ); | 16 | subExceptionDecl( Base64Exception ); |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * | 19 | * |
20 | *@ingroup Streams | 20 | *@ingroup Streams |
21 | */ | 21 | */ |
22 | class Base64 : public Bu::Filter | 22 | class Base64 : public Bu::Filter |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Base64( Bu::Stream &rNext, int iChunkSize=0 ); | 25 | Base64( Bu::Stream &rNext, int iChunkSize=0 ); |
26 | virtual ~Base64(); | 26 | virtual ~Base64(); |
27 | 27 | ||
28 | virtual void start(); | 28 | virtual void start(); |
29 | virtual Bu::size stop(); | 29 | virtual Bu::size stop(); |
30 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 30 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
32 | 32 | ||
33 | virtual bool isOpen(); | 33 | virtual bool isOpen(); |
34 | 34 | ||
35 | virtual bool isEos(); | 35 | virtual bool isEos(); |
36 | 36 | ||
37 | private: | 37 | private: |
38 | int iBPos; | 38 | int iBPos; |
39 | int iBuf; | 39 | int iBuf; |
40 | int iRPos; | 40 | int iRPos; |
41 | int iChars; | 41 | int iChars; |
42 | bool bEosIn; | 42 | bool bEosIn; |
43 | Bu::size iTotalIn; | 43 | Bu::size iTotalIn; |
44 | Bu::size iTotalOut; | 44 | Bu::size iTotalOut; |
45 | static const char tblEnc[65]; | 45 | static const char tblEnc[65]; |
46 | char tblDec[80]; | 46 | char tblDec[80]; |
47 | enum Mode | 47 | enum Mode |
48 | { | 48 | { |
49 | Nothing = 0x00, | 49 | Nothing = 0x00, |
50 | Encode = 0x01, | 50 | Encode = 0x01, |
51 | Decode = 0x02, | 51 | Decode = 0x02, |
52 | }; | 52 | }; |
53 | Mode eMode; | 53 | Mode eMode; |
54 | int iChunkSize; | 54 | int iChunkSize; |
55 | int iCurChunk; | 55 | int iCurChunk; |
56 | }; | 56 | }; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | #endif | 59 | #endif |
diff --git a/src/stable/buffer.cpp b/src/stable/buffer.cpp index 16c3e2f..c787499 100644 --- a/src/stable/buffer.cpp +++ b/src/stable/buffer.cpp | |||
@@ -8,26 +8,26 @@ | |||
8 | #include "bu/buffer.h" | 8 | #include "bu/buffer.h" |
9 | 9 | ||
10 | Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : | 10 | Bu::Buffer::Buffer( Bu::Stream &rNext, int iWhat, int iBufSize ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | sSoFar( 0 ), | 12 | sSoFar( 0 ), |
13 | iBufSize( iBufSize ), | 13 | iBufSize( iBufSize ), |
14 | sReadBuf( NULL ), | 14 | sReadBuf( NULL ), |
15 | sWriteBuf( NULL ), | 15 | sWriteBuf( NULL ), |
16 | iReadBufFill( 0 ), | 16 | iReadBufFill( 0 ), |
17 | iReadPos( 0 ), | 17 | iReadPos( 0 ), |
18 | iWriteBufFill( 0 ), | 18 | iWriteBufFill( 0 ), |
19 | iWritePos( 0 ), | 19 | iWritePos( 0 ), |
20 | iWhat( iWhat ) | 20 | iWhat( iWhat ) |
21 | { | 21 | { |
22 | sReadBuf = new char[iBufSize]; | 22 | sReadBuf = new char[iBufSize]; |
23 | sWriteBuf = new char[iBufSize]; | 23 | sWriteBuf = new char[iBufSize]; |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::Buffer::~Buffer() | 26 | Bu::Buffer::~Buffer() |
27 | { | 27 | { |
28 | flush(); | 28 | flush(); |
29 | delete[] sReadBuf; | 29 | delete[] sReadBuf; |
30 | delete[] sWriteBuf; | 30 | delete[] sWriteBuf; |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::Buffer::start() | 33 | void Bu::Buffer::start() |
@@ -36,135 +36,135 @@ void Bu::Buffer::start() | |||
36 | 36 | ||
37 | Bu::size Bu::Buffer::stop() | 37 | Bu::size Bu::Buffer::stop() |
38 | { | 38 | { |
39 | flush(); | 39 | flush(); |
40 | iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; | 40 | iReadBufFill = iReadPos = iWriteBufFill = iWritePos = 0; |
41 | return sSoFar; | 41 | return sSoFar; |
42 | } | 42 | } |
43 | 43 | ||
44 | void Bu::Buffer::fillReadBuf() | 44 | void Bu::Buffer::fillReadBuf() |
45 | { | 45 | { |
46 | if( iReadBufFill+iReadPos < iBufSize ) | 46 | if( iReadBufFill+iReadPos < iBufSize ) |
47 | { | 47 | { |
48 | iReadBufFill += rNext.read( | 48 | iReadBufFill += rNext.read( |
49 | sReadBuf+iReadPos+iReadBufFill, | 49 | sReadBuf+iReadPos+iReadBufFill, |
50 | iBufSize-iReadBufFill-iReadPos | 50 | iBufSize-iReadBufFill-iReadPos |
51 | ); | 51 | ); |
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) | 55 | Bu::size Bu::Buffer::read( void *pBuf, Bu::size nBytes ) |
56 | { | 56 | { |
57 | if( (iWhat&Read) == 0 ) | 57 | if( (iWhat&Read) == 0 ) |
58 | return rNext.read( pBuf, nBytes ); | 58 | return rNext.read( pBuf, nBytes ); |
59 | 59 | ||
60 | if( nBytes <= 0 ) | 60 | if( nBytes <= 0 ) |
61 | { | 61 | { |
62 | fillReadBuf(); | 62 | fillReadBuf(); |
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | Bu::size nTotRead = 0; | 66 | Bu::size nTotRead = 0; |
67 | // fillReadBuf(); | 67 | // fillReadBuf(); |
68 | 68 | ||
69 | do | 69 | do |
70 | { | 70 | { |
71 | int iAmnt = nBytes-nTotRead; | 71 | int iAmnt = nBytes-nTotRead; |
72 | if( iAmnt > iReadBufFill ) | 72 | if( iAmnt > iReadBufFill ) |
73 | { | 73 | { |
74 | iAmnt = iReadBufFill; | 74 | iAmnt = iReadBufFill; |
75 | } | 75 | } |
76 | if( iAmnt > 0 ) | 76 | if( iAmnt > 0 ) |
77 | { | 77 | { |
78 | memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); | 78 | memcpy( ((char *)pBuf)+nTotRead, sReadBuf+iReadPos, iAmnt ); |
79 | iReadPos += iAmnt; | 79 | iReadPos += iAmnt; |
80 | nTotRead += iAmnt; | 80 | nTotRead += iAmnt; |
81 | iReadBufFill -= iAmnt; | 81 | iReadBufFill -= iAmnt; |
82 | } | 82 | } |
83 | if( iReadBufFill == 0 ) | 83 | if( iReadBufFill == 0 ) |
84 | { | 84 | { |
85 | iReadPos = 0; | 85 | iReadPos = 0; |
86 | fillReadBuf(); | 86 | fillReadBuf(); |
87 | } | 87 | } |
88 | } | 88 | } |
89 | while( nTotRead < nBytes && iReadBufFill > 0 ); | 89 | while( nTotRead < nBytes && iReadBufFill > 0 ); |
90 | 90 | ||
91 | //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); | 91 | //printf("Buffer: %db returned, %db remain in buffer.\n", nTotRead, iReadBufFill ); |
92 | 92 | ||
93 | return nTotRead; | 93 | return nTotRead; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) | 96 | Bu::size Bu::Buffer::write( const void *pBuf, Bu::size nBytes ) |
97 | { | 97 | { |
98 | if( (iWhat&Write) == 0 ) | 98 | if( (iWhat&Write) == 0 ) |
99 | return rNext.write( pBuf, nBytes ); | 99 | return rNext.write( pBuf, nBytes ); |
100 | 100 | ||
101 | Bu::size nTotWrote = 0; | 101 | Bu::size nTotWrote = 0; |
102 | 102 | ||
103 | do | 103 | do |
104 | { | 104 | { |
105 | int iAmnt = nBytes-nTotWrote; | 105 | int iAmnt = nBytes-nTotWrote; |
106 | if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) | 106 | if( iAmnt > iBufSize-iWritePos-iWriteBufFill ) |
107 | { | 107 | { |
108 | iAmnt = iBufSize-iWritePos-iWriteBufFill; | 108 | iAmnt = iBufSize-iWritePos-iWriteBufFill; |
109 | } | 109 | } |
110 | if( iAmnt > 0 ) | 110 | if( iAmnt > 0 ) |
111 | { | 111 | { |
112 | memcpy( | 112 | memcpy( |
113 | sWriteBuf+iWritePos+iWriteBufFill, | 113 | sWriteBuf+iWritePos+iWriteBufFill, |
114 | ((char *)pBuf)+nTotWrote, | 114 | ((char *)pBuf)+nTotWrote, |
115 | iAmnt | 115 | iAmnt |
116 | ); | 116 | ); |
117 | nTotWrote += iAmnt; | 117 | nTotWrote += iAmnt; |
118 | iWriteBufFill += iAmnt; | 118 | iWriteBufFill += iAmnt; |
119 | //printf("Buffer: Moved %db to write buffer, %db filled now.\n", | 119 | //printf("Buffer: Moved %db to write buffer, %db filled now.\n", |
120 | //iAmnt, iWriteBufFill ); | 120 | //iAmnt, iWriteBufFill ); |
121 | } | 121 | } |
122 | while( iWritePos+iWriteBufFill == iBufSize ) | 122 | while( iWritePos+iWriteBufFill == iBufSize ) |
123 | { | 123 | { |
124 | //printf("iWritePos = %d\n", iWritePos ); | 124 | //printf("iWritePos = %d\n", iWritePos ); |
125 | int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); | 125 | int iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); |
126 | //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); | 126 | //printf("Buffer: Wrote %db from buffer to stream, %db filled now.\n", iWr, iWriteBufFill-iWr ); |
127 | if( iWr == 0 ) | 127 | if( iWr == 0 ) |
128 | { | 128 | { |
129 | return nTotWrote; | 129 | return nTotWrote; |
130 | } | 130 | } |
131 | else if( iWr == iWriteBufFill ) | 131 | else if( iWr == iWriteBufFill ) |
132 | { | 132 | { |
133 | iWritePos = iWriteBufFill = 0; | 133 | iWritePos = iWriteBufFill = 0; |
134 | } | 134 | } |
135 | else | 135 | else |
136 | { | 136 | { |
137 | iWritePos += iWr; | 137 | iWritePos += iWr; |
138 | iWriteBufFill -= iWr; | 138 | iWriteBufFill -= iWr; |
139 | } | 139 | } |
140 | } | 140 | } |
141 | } | 141 | } |
142 | while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); | 142 | while( nTotWrote < nBytes && iWriteBufFill < iBufSize+iWritePos ); |
143 | 143 | ||
144 | return nTotWrote; | 144 | return nTotWrote; |
145 | } | 145 | } |
146 | 146 | ||
147 | void Bu::Buffer::flush() | 147 | void Bu::Buffer::flush() |
148 | { | 148 | { |
149 | if( (iWhat&Write) == 0 ) | 149 | if( (iWhat&Write) == 0 ) |
150 | return rNext.flush(); | 150 | return rNext.flush(); |
151 | 151 | ||
152 | if( iWriteBufFill > 0 ) | 152 | if( iWriteBufFill > 0 ) |
153 | { | 153 | { |
154 | //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); | 154 | //printf("Buffer: Flushing remaining data, %db.\n", iWriteBufFill ); |
155 | int iWr = 0; | 155 | int iWr = 0; |
156 | do | 156 | do |
157 | { | 157 | { |
158 | iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); | 158 | iWr = rNext.write( sWriteBuf+iWritePos, iWriteBufFill ); |
159 | //printf("Buffer: %db written to stream.\n", iWr ); | 159 | //printf("Buffer: %db written to stream.\n", iWr ); |
160 | iWritePos += iWr; | 160 | iWritePos += iWr; |
161 | iWriteBufFill -= iWr; | 161 | iWriteBufFill -= iWr; |
162 | } while( iWriteBufFill > 0 && iWr > 0 ); | 162 | } while( iWriteBufFill > 0 && iWr > 0 ); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | bool Bu::Buffer::isEos() | 166 | bool Bu::Buffer::isEos() |
167 | { | 167 | { |
168 | return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); | 168 | return (iReadPos >= (iReadBufFill-1)) && (rNext.isEos()); |
169 | } | 169 | } |
170 | 170 | ||
diff --git a/src/stable/buffer.h b/src/stable/buffer.h index a8303fa..21a5812 100644 --- a/src/stable/buffer.h +++ b/src/stable/buffer.h | |||
@@ -12,47 +12,47 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class Buffer : public Bu::Filter | 15 | class Buffer : public Bu::Filter |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); | 18 | Buffer( Bu::Stream &rNext, int iWhat=Both, int iBufSize=4096 ); |
19 | virtual ~Buffer(); | 19 | virtual ~Buffer(); |
20 | 20 | ||
21 | enum | 21 | enum |
22 | { | 22 | { |
23 | Write = 1, | 23 | Write = 1, |
24 | Read = 2, | 24 | Read = 2, |
25 | Both = 3 | 25 | Both = 3 |
26 | }; | 26 | }; |
27 | 27 | ||
28 | virtual void start(); | 28 | virtual void start(); |
29 | virtual Bu::size stop(); | 29 | virtual Bu::size stop(); |
30 | 30 | ||
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
33 | using Stream::write; | 33 | using Stream::write; |
34 | 34 | ||
35 | Bu::size getReadFill() { return iReadBufFill; } | 35 | Bu::size getReadFill() { return iReadBufFill; } |
36 | bool isWritePending() { return iWriteBufFill > 0; } | 36 | bool isWritePending() { return iWriteBufFill > 0; } |
37 | 37 | ||
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | 39 | ||
40 | virtual bool isEos(); | 40 | virtual bool isEos(); |
41 | 41 | ||
42 | private: | 42 | private: |
43 | void fillReadBuf(); | 43 | void fillReadBuf(); |
44 | 44 | ||
45 | private: | 45 | private: |
46 | Bu::size sSoFar; | 46 | Bu::size sSoFar; |
47 | int iBufSize; | 47 | int iBufSize; |
48 | char *sReadBuf; | 48 | char *sReadBuf; |
49 | char *sWriteBuf; | 49 | char *sWriteBuf; |
50 | int iReadBufFill; | 50 | int iReadBufFill; |
51 | int iReadPos; | 51 | int iReadPos; |
52 | int iWriteBufFill; | 52 | int iWriteBufFill; |
53 | int iWritePos; | 53 | int iWritePos; |
54 | int iWhat; | 54 | int iWhat; |
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | #endif | 58 | #endif |
diff --git a/src/stable/bzip2.cpp b/src/stable/bzip2.cpp index 11b8873..5e660d0 100644 --- a/src/stable/bzip2.cpp +++ b/src/stable/bzip2.cpp | |||
@@ -15,222 +15,222 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : | 17 | Bu::BZip2::BZip2( Bu::Stream &rNext, int nCompression ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ) | 21 | sTotalOut( 0 ) |
22 | { | 22 | { |
23 | TRACE( nCompression ); | 23 | TRACE( nCompression ); |
24 | start(); | 24 | start(); |
25 | } | 25 | } |
26 | 26 | ||
27 | Bu::BZip2::~BZip2() | 27 | Bu::BZip2::~BZip2() |
28 | { | 28 | { |
29 | TRACE(); | 29 | TRACE(); |
30 | stop(); | 30 | stop(); |
31 | } | 31 | } |
32 | 32 | ||
33 | void Bu::BZip2::start() | 33 | void Bu::BZip2::start() |
34 | { | 34 | { |
35 | TRACE(); | 35 | TRACE(); |
36 | 36 | ||
37 | prState = new bz_stream; | 37 | prState = new bz_stream; |
38 | pState->state = NULL; | 38 | pState->state = NULL; |
39 | pState->bzalloc = NULL; | 39 | pState->bzalloc = NULL; |
40 | pState->bzfree = NULL; | 40 | pState->bzfree = NULL; |
41 | pState->opaque = NULL; | 41 | pState->opaque = NULL; |
42 | 42 | ||
43 | nBufSize = 64*1024; | 43 | nBufSize = 64*1024; |
44 | pBuf = new char[nBufSize]; | 44 | pBuf = new char[nBufSize]; |
45 | } | 45 | } |
46 | 46 | ||
47 | Bu::size Bu::BZip2::stop() | 47 | Bu::size Bu::BZip2::stop() |
48 | { | 48 | { |
49 | TRACE(); | 49 | TRACE(); |
50 | if( !pState ) | 50 | if( !pState ) |
51 | return 0; | 51 | return 0; |
52 | 52 | ||
53 | if( pState->state ) | 53 | if( pState->state ) |
54 | { | 54 | { |
55 | if( bReading ) | 55 | if( bReading ) |
56 | { | 56 | { |
57 | BZ2_bzDecompressEnd( pState ); | 57 | BZ2_bzDecompressEnd( pState ); |
58 | delete[] pBuf; | 58 | delete[] pBuf; |
59 | pBuf = NULL; | 59 | pBuf = NULL; |
60 | delete pState; | 60 | delete pState; |
61 | prState = NULL; | 61 | prState = NULL; |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | else | 64 | else |
65 | { | 65 | { |
66 | // Bu::size sTotal = 0; | 66 | // Bu::size sTotal = 0; |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | pState->next_in = NULL; | 69 | pState->next_in = NULL; |
70 | pState->avail_in = 0; | 70 | pState->avail_in = 0; |
71 | pState->avail_out = nBufSize; | 71 | pState->avail_out = nBufSize; |
72 | pState->next_out = pBuf; | 72 | pState->next_out = pBuf; |
73 | int res = BZ2_bzCompress( pState, BZ_FINISH ); | 73 | int res = BZ2_bzCompress( pState, BZ_FINISH ); |
74 | if( pState->avail_out < nBufSize ) | 74 | if( pState->avail_out < nBufSize ) |
75 | { | 75 | { |
76 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 76 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
77 | } | 77 | } |
78 | if( res == BZ_STREAM_END ) | 78 | if( res == BZ_STREAM_END ) |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | BZ2_bzCompressEnd( pState ); | 81 | BZ2_bzCompressEnd( pState ); |
82 | delete[] pBuf; | 82 | delete[] pBuf; |
83 | pBuf = NULL; | 83 | pBuf = NULL; |
84 | delete pState; | 84 | delete pState; |
85 | prState = NULL; | 85 | prState = NULL; |
86 | return sTotalOut; | 86 | return sTotalOut; |
87 | } | 87 | } |
88 | } | 88 | } |
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | void Bu::BZip2::bzError( int code ) | 92 | void Bu::BZip2::bzError( int code ) |
93 | { | 93 | { |
94 | TRACE( code ); | 94 | TRACE( code ); |
95 | switch( code ) | 95 | switch( code ) |
96 | { | 96 | { |
97 | case BZ_OK: | 97 | case BZ_OK: |
98 | case BZ_RUN_OK: | 98 | case BZ_RUN_OK: |
99 | case BZ_FLUSH_OK: | 99 | case BZ_FLUSH_OK: |
100 | case BZ_FINISH_OK: | 100 | case BZ_FINISH_OK: |
101 | return; | 101 | return; |
102 | 102 | ||
103 | case BZ_CONFIG_ERROR: | 103 | case BZ_CONFIG_ERROR: |
104 | throw ExceptionBase("BZip2: Library configured improperly, reinstall."); | 104 | throw ExceptionBase("BZip2: Library configured improperly, reinstall."); |
105 | 105 | ||
106 | case BZ_SEQUENCE_ERROR: | 106 | case BZ_SEQUENCE_ERROR: |
107 | throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); | 107 | throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); |
108 | 108 | ||
109 | case BZ_PARAM_ERROR: | 109 | case BZ_PARAM_ERROR: |
110 | throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); | 110 | throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); |
111 | 111 | ||
112 | case BZ_MEM_ERROR: | 112 | case BZ_MEM_ERROR: |
113 | throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); | 113 | throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); |
114 | 114 | ||
115 | case BZ_DATA_ERROR: | 115 | case BZ_DATA_ERROR: |
116 | throw ExceptionBase("BZip2: Data was corrupted before decompression."); | 116 | throw ExceptionBase("BZip2: Data was corrupted before decompression."); |
117 | 117 | ||
118 | case BZ_DATA_ERROR_MAGIC: | 118 | case BZ_DATA_ERROR_MAGIC: |
119 | throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); | 119 | throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); |
120 | 120 | ||
121 | case BZ_IO_ERROR: | 121 | case BZ_IO_ERROR: |
122 | throw ExceptionBase("BZip2: File couldn't be read from / written to."); | 122 | throw ExceptionBase("BZip2: File couldn't be read from / written to."); |
123 | 123 | ||
124 | case BZ_UNEXPECTED_EOF: | 124 | case BZ_UNEXPECTED_EOF: |
125 | throw ExceptionBase("BZip2: End of file encountered before end of stream."); | 125 | throw ExceptionBase("BZip2: End of file encountered before end of stream."); |
126 | 126 | ||
127 | case BZ_OUTBUFF_FULL: | 127 | case BZ_OUTBUFF_FULL: |
128 | throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); | 128 | throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); |
129 | 129 | ||
130 | default: | 130 | default: |
131 | throw ExceptionBase("BZip2: Unknown error encountered."); | 131 | throw ExceptionBase("BZip2: Unknown error encountered."); |
132 | 132 | ||
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) | 136 | Bu::size Bu::BZip2::read( void *pData, Bu::size nBytes ) |
137 | { | 137 | { |
138 | TRACE( pData, nBytes ); | 138 | TRACE( pData, nBytes ); |
139 | if( !pState->state ) | 139 | if( !pState->state ) |
140 | { | 140 | { |
141 | bReading = true; | 141 | bReading = true; |
142 | BZ2_bzDecompressInit( pState, 0, 0 ); | 142 | BZ2_bzDecompressInit( pState, 0, 0 ); |
143 | pState->next_in = pBuf; | 143 | pState->next_in = pBuf; |
144 | pState->avail_in = 0; | 144 | pState->avail_in = 0; |
145 | } | 145 | } |
146 | if( bReading == false ) | 146 | if( bReading == false ) |
147 | throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); | 147 | throw ExceptionBase("This bzip2 filter is in writing mode, you can't read."); |
148 | 148 | ||
149 | int nRead = 0; | 149 | int nRead = 0; |
150 | int nReadTotal = pState->total_out_lo32; | 150 | int nReadTotal = pState->total_out_lo32; |
151 | pState->next_out = (char *)pData; | 151 | pState->next_out = (char *)pData; |
152 | pState->avail_out = nBytes; | 152 | pState->avail_out = nBytes; |
153 | for(;;) | 153 | for(;;) |
154 | { | 154 | { |
155 | int ret = BZ2_bzDecompress( pState ); | 155 | int ret = BZ2_bzDecompress( pState ); |
156 | 156 | ||
157 | nReadTotal += nRead-pState->avail_out; | 157 | nReadTotal += nRead-pState->avail_out; |
158 | 158 | ||
159 | if( ret == BZ_STREAM_END ) | 159 | if( ret == BZ_STREAM_END ) |
160 | { | 160 | { |
161 | if( pState->avail_in > 0 ) | 161 | if( pState->avail_in > 0 ) |
162 | { | 162 | { |
163 | if( rNext.isSeekable() ) | 163 | if( rNext.isSeekable() ) |
164 | { | 164 | { |
165 | rNext.seek( -(Bu::size)pState->avail_in ); | 165 | rNext.seek( -(Bu::size)pState->avail_in ); |
166 | } | 166 | } |
167 | } | 167 | } |
168 | return nBytes-pState->avail_out; | 168 | return nBytes-pState->avail_out; |
169 | } | 169 | } |
170 | bzError( ret ); | 170 | bzError( ret ); |
171 | 171 | ||
172 | if( pState->avail_out ) | 172 | if( pState->avail_out ) |
173 | { | 173 | { |
174 | if( pState->avail_in == 0 ) | 174 | if( pState->avail_in == 0 ) |
175 | { | 175 | { |
176 | nRead = rNext.read( pBuf, nBufSize ); | 176 | nRead = rNext.read( pBuf, nBufSize ); |
177 | if( nRead == 0 && rNext.isEos() ) | 177 | if( nRead == 0 && rNext.isEos() ) |
178 | { | 178 | { |
179 | throw Bu::ExceptionBase("Premature end of underlying " | 179 | throw Bu::ExceptionBase("Premature end of underlying " |
180 | "stream found reading bzip2 stream."); | 180 | "stream found reading bzip2 stream."); |
181 | } | 181 | } |
182 | pState->next_in = pBuf; | 182 | pState->next_in = pBuf; |
183 | pState->avail_in = nRead; | 183 | pState->avail_in = nRead; |
184 | } | 184 | } |
185 | } | 185 | } |
186 | else | 186 | else |
187 | { | 187 | { |
188 | return nBytes-pState->avail_out; | 188 | return nBytes-pState->avail_out; |
189 | } | 189 | } |
190 | } | 190 | } |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | 193 | ||
194 | Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) | 194 | Bu::size Bu::BZip2::write( const void *pData, Bu::size nBytes ) |
195 | { | 195 | { |
196 | TRACE( pData, nBytes ); | 196 | TRACE( pData, nBytes ); |
197 | if( !pState->state ) | 197 | if( !pState->state ) |
198 | { | 198 | { |
199 | bReading = false; | 199 | bReading = false; |
200 | BZ2_bzCompressInit( pState, nCompression, 0, 30 ); | 200 | BZ2_bzCompressInit( pState, nCompression, 0, 30 ); |
201 | } | 201 | } |
202 | if( bReading == true ) | 202 | if( bReading == true ) |
203 | throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); | 203 | throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); |
204 | 204 | ||
205 | // Bu::size sTotalOut = 0; | 205 | // Bu::size sTotalOut = 0; |
206 | pState->next_in = (char *)pData; | 206 | pState->next_in = (char *)pData; |
207 | pState->avail_in = nBytes; | 207 | pState->avail_in = nBytes; |
208 | for(;;) | 208 | for(;;) |
209 | { | 209 | { |
210 | pState->avail_out = nBufSize; | 210 | pState->avail_out = nBufSize; |
211 | pState->next_out = pBuf; | 211 | pState->next_out = pBuf; |
212 | 212 | ||
213 | bzError( BZ2_bzCompress( pState, BZ_RUN ) ); | 213 | bzError( BZ2_bzCompress( pState, BZ_RUN ) ); |
214 | 214 | ||
215 | if( pState->avail_out < nBufSize ) | 215 | if( pState->avail_out < nBufSize ) |
216 | { | 216 | { |
217 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 217 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
218 | } | 218 | } |
219 | if( pState->avail_in == 0 ) | 219 | if( pState->avail_in == 0 ) |
220 | break; | 220 | break; |
221 | } | 221 | } |
222 | 222 | ||
223 | return nBytes; | 223 | return nBytes; |
224 | } | 224 | } |
225 | 225 | ||
226 | bool Bu::BZip2::isOpen() | 226 | bool Bu::BZip2::isOpen() |
227 | { | 227 | { |
228 | TRACE(); | 228 | TRACE(); |
229 | return (pState->state != NULL); | 229 | return (pState->state != NULL); |
230 | } | 230 | } |
231 | 231 | ||
232 | Bu::size Bu::BZip2::getCompressedSize() | 232 | Bu::size Bu::BZip2::getCompressedSize() |
233 | { | 233 | { |
234 | return sTotalOut; | 234 | return sTotalOut; |
235 | } | 235 | } |
236 | 236 | ||
diff --git a/src/stable/bzip2.h b/src/stable/bzip2.h index d92dd2f..d53f325 100644 --- a/src/stable/bzip2.h +++ b/src/stable/bzip2.h | |||
@@ -14,36 +14,36 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides BZip2 type compression and decompression. | 18 | * Provides BZip2 type compression and decompression. |
19 | * | 19 | * |
20 | *@ingroup Streams | 20 | *@ingroup Streams |
21 | *@ingroup Compression | 21 | *@ingroup Compression |
22 | */ | 22 | */ |
23 | class BZip2 : public Bu::Filter | 23 | class BZip2 : public Bu::Filter |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | BZip2( Bu::Stream &rNext, int nCompression=9 ); | 26 | BZip2( Bu::Stream &rNext, int nCompression=9 ); |
27 | virtual ~BZip2(); | 27 | virtual ~BZip2(); |
28 | 28 | ||
29 | virtual void start(); | 29 | virtual void start(); |
30 | virtual Bu::size stop(); | 30 | virtual Bu::size stop(); |
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
33 | 33 | ||
34 | virtual bool isOpen(); | 34 | virtual bool isOpen(); |
35 | 35 | ||
36 | Bu::size getCompressedSize(); | 36 | Bu::size getCompressedSize(); |
37 | 37 | ||
38 | private: | 38 | private: |
39 | void bzError( int code ); | 39 | void bzError( int code ); |
40 | void *prState; | 40 | void *prState; |
41 | bool bReading; | 41 | bool bReading; |
42 | int nCompression; | 42 | int nCompression; |
43 | char *pBuf; | 43 | char *pBuf; |
44 | uint32_t nBufSize; | 44 | uint32_t nBufSize; |
45 | Bu::size sTotalOut; | 45 | Bu::size sTotalOut; |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/client.cpp b/src/stable/client.cpp index 7ae10f7..f5cc75f 100644 --- a/src/stable/client.cpp +++ b/src/stable/client.cpp | |||
@@ -14,307 +14,307 @@ | |||
14 | #include "bu/clientlinkfactory.h" | 14 | #include "bu/clientlinkfactory.h" |
15 | 15 | ||
16 | /** Read buffer size. */ | 16 | /** Read buffer size. */ |
17 | #define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess | 17 | #define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess |
18 | 18 | ||
19 | Bu::Client::Client( Bu::TcpSocket *pSocket, | 19 | Bu::Client::Client( Bu::TcpSocket *pSocket, |
20 | class Bu::ClientLinkFactory *pfLink ) : | 20 | class Bu::ClientLinkFactory *pfLink ) : |
21 | pTopStream( pSocket ), | 21 | pTopStream( pSocket ), |
22 | pSocket( pSocket ), | 22 | pSocket( pSocket ), |
23 | pProto( NULL ), | 23 | pProto( NULL ), |
24 | bWantsDisconnect( false ), | 24 | bWantsDisconnect( false ), |
25 | pfLink( pfLink ) | 25 | pfLink( pfLink ) |
26 | { | 26 | { |
27 | lFilts.prepend( pSocket ); | 27 | lFilts.prepend( pSocket ); |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::Client::~Client() | 30 | Bu::Client::~Client() |
31 | { | 31 | { |
32 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 32 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
33 | { | 33 | { |
34 | delete *i; | 34 | delete *i; |
35 | } | 35 | } |
36 | pTopStream = pSocket = NULL; | 36 | pTopStream = pSocket = NULL; |
37 | delete pfLink; | 37 | delete pfLink; |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::Client::processInput() | 40 | void Bu::Client::processInput() |
41 | { | 41 | { |
42 | char buf[RBS]; | 42 | char buf[RBS]; |
43 | Bu::size nRead, nTotal=0; | 43 | Bu::size nRead, nTotal=0; |
44 | 44 | ||
45 | for(;;) | 45 | for(;;) |
46 | { | 46 | { |
47 | try | 47 | try |
48 | { | 48 | { |
49 | nRead = pTopStream->read( buf, RBS ); | 49 | nRead = pTopStream->read( buf, RBS ); |
50 | 50 | ||
51 | if( nRead == 0 ) | 51 | if( nRead == 0 ) |
52 | { | 52 | { |
53 | break; | 53 | break; |
54 | } | 54 | } |
55 | else | 55 | else |
56 | { | 56 | { |
57 | nTotal += nRead; | 57 | nTotal += nRead; |
58 | qbRead.write( buf, nRead ); | 58 | qbRead.write( buf, nRead ); |
59 | if( !pTopStream->canRead() ) | 59 | if( !pTopStream->canRead() ) |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | } | 62 | } |
63 | catch( Bu::TcpSocketException &e ) | 63 | catch( Bu::TcpSocketException &e ) |
64 | { | 64 | { |
65 | pTopStream->close(); | 65 | pTopStream->close(); |
66 | bWantsDisconnect = true; | 66 | bWantsDisconnect = true; |
67 | break; | 67 | break; |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | if( nTotal == 0 ) | 71 | if( nTotal == 0 ) |
72 | { | 72 | { |
73 | pTopStream->close(); | 73 | pTopStream->close(); |
74 | bWantsDisconnect = true; | 74 | bWantsDisconnect = true; |
75 | } | 75 | } |
76 | 76 | ||
77 | if( pProto && nTotal ) | 77 | if( pProto && nTotal ) |
78 | { | 78 | { |
79 | pProto->onNewData( this ); | 79 | pProto->onNewData( this ); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::Client::processOutput() | 83 | void Bu::Client::processOutput() |
84 | { | 84 | { |
85 | char buf[RBS]; | 85 | char buf[RBS]; |
86 | if( qbWrite.getSize() > 0 ) | 86 | if( qbWrite.getSize() > 0 ) |
87 | { | 87 | { |
88 | int nAmnt = RBS; | 88 | int nAmnt = RBS; |
89 | nAmnt = qbWrite.peek( buf, nAmnt ); | 89 | nAmnt = qbWrite.peek( buf, nAmnt ); |
90 | int nReal = pTopStream->write( buf, nAmnt ); | 90 | int nReal = pTopStream->write( buf, nAmnt ); |
91 | qbWrite.seek( nReal ); | 91 | qbWrite.seek( nReal ); |
92 | pTopStream->flush(); | 92 | pTopStream->flush(); |
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::Client::setProtocol( Protocol *pProto ) | 96 | void Bu::Client::setProtocol( Protocol *pProto ) |
97 | { | 97 | { |
98 | this->pProto = pProto; | 98 | this->pProto = pProto; |
99 | this->pProto->onNewConnection( this ); | 99 | this->pProto->onNewConnection( this ); |
100 | } | 100 | } |
101 | 101 | ||
102 | Bu::Protocol *Bu::Client::getProtocol() | 102 | Bu::Protocol *Bu::Client::getProtocol() |
103 | { | 103 | { |
104 | return pProto; | 104 | return pProto; |
105 | } | 105 | } |
106 | 106 | ||
107 | void Bu::Client::clearProtocol() | 107 | void Bu::Client::clearProtocol() |
108 | { | 108 | { |
109 | pProto = NULL; | 109 | pProto = NULL; |
110 | } | 110 | } |
111 | /* | 111 | /* |
112 | Bu::String &Bu::Client::getInput() | 112 | Bu::String &Bu::Client::getInput() |
113 | { | 113 | { |
114 | return sReadBuf; | 114 | return sReadBuf; |
115 | } | 115 | } |
116 | 116 | ||
117 | Bu::String &Bu::Client::getOutput() | 117 | Bu::String &Bu::Client::getOutput() |
118 | { | 118 | { |
119 | return sWriteBuf; | 119 | return sWriteBuf; |
120 | } | 120 | } |
121 | */ | 121 | */ |
122 | 122 | ||
123 | bool Bu::Client::isOpen() | 123 | bool Bu::Client::isOpen() |
124 | { | 124 | { |
125 | if( !pTopStream ) return false; | 125 | if( !pTopStream ) return false; |
126 | return pTopStream->isOpen(); | 126 | return pTopStream->isOpen(); |
127 | } | 127 | } |
128 | 128 | ||
129 | Bu::size Bu::Client::write( const Bu::String &sData ) | 129 | Bu::size Bu::Client::write( const Bu::String &sData ) |
130 | { | 130 | { |
131 | return qbWrite.write( sData.getStr(), sData.getSize() ); | 131 | return qbWrite.write( sData.getStr(), sData.getSize() ); |
132 | } | 132 | } |
133 | 133 | ||
134 | Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) | 134 | Bu::size Bu::Client::write( const void *pData, Bu::size nBytes ) |
135 | { | 135 | { |
136 | return qbWrite.write( pData, nBytes ); | 136 | return qbWrite.write( pData, nBytes ); |
137 | } | 137 | } |
138 | 138 | ||
139 | Bu::size Bu::Client::write( int8_t nData ) | 139 | Bu::size Bu::Client::write( int8_t nData ) |
140 | { | 140 | { |
141 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 141 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::size Bu::Client::write( int16_t nData ) | 144 | Bu::size Bu::Client::write( int16_t nData ) |
145 | { | 145 | { |
146 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 146 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
147 | } | 147 | } |
148 | 148 | ||
149 | Bu::size Bu::Client::write( int32_t nData ) | 149 | Bu::size Bu::Client::write( int32_t nData ) |
150 | { | 150 | { |
151 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 151 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
152 | } | 152 | } |
153 | 153 | ||
154 | Bu::size Bu::Client::write( int64_t nData ) | 154 | Bu::size Bu::Client::write( int64_t nData ) |
155 | { | 155 | { |
156 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 156 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
157 | } | 157 | } |
158 | 158 | ||
159 | Bu::size Bu::Client::write( uint8_t nData ) | 159 | Bu::size Bu::Client::write( uint8_t nData ) |
160 | { | 160 | { |
161 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 161 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
162 | } | 162 | } |
163 | 163 | ||
164 | Bu::size Bu::Client::write( uint16_t nData ) | 164 | Bu::size Bu::Client::write( uint16_t nData ) |
165 | { | 165 | { |
166 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 166 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
167 | } | 167 | } |
168 | 168 | ||
169 | Bu::size Bu::Client::write( uint32_t nData ) | 169 | Bu::size Bu::Client::write( uint32_t nData ) |
170 | { | 170 | { |
171 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 171 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::size Bu::Client::write( uint64_t nData ) | 174 | Bu::size Bu::Client::write( uint64_t nData ) |
175 | { | 175 | { |
176 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); | 176 | return qbWrite.write( (const char *)&nData, sizeof(nData) ); |
177 | } | 177 | } |
178 | 178 | ||
179 | Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) | 179 | Bu::size Bu::Client::read( void *pData, Bu::size nBytes ) |
180 | { | 180 | { |
181 | return qbRead.read( pData, nBytes ); | 181 | return qbRead.read( pData, nBytes ); |
182 | } | 182 | } |
183 | 183 | ||
184 | Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) | 184 | Bu::size Bu::Client::peek( void *pData, int nBytes, int nOffset ) |
185 | { | 185 | { |
186 | return qbRead.peek( pData, nBytes, nOffset ); | 186 | return qbRead.peek( pData, nBytes, nOffset ); |
187 | } | 187 | } |
188 | 188 | ||
189 | Bu::size Bu::Client::getInputSize() | 189 | Bu::size Bu::Client::getInputSize() |
190 | { | 190 | { |
191 | return qbRead.getSize(); | 191 | return qbRead.getSize(); |
192 | } | 192 | } |
193 | 193 | ||
194 | Bu::size Bu::Client::getOutputSize() | 194 | Bu::size Bu::Client::getOutputSize() |
195 | { | 195 | { |
196 | return qbWrite.getSize(); | 196 | return qbWrite.getSize(); |
197 | } | 197 | } |
198 | 198 | ||
199 | const Bu::TcpSocket *Bu::Client::getSocket() const | 199 | const Bu::TcpSocket *Bu::Client::getSocket() const |
200 | { | 200 | { |
201 | return pSocket; | 201 | return pSocket; |
202 | } | 202 | } |
203 | 203 | ||
204 | void Bu::Client::disconnect() | 204 | void Bu::Client::disconnect() |
205 | { | 205 | { |
206 | bWantsDisconnect = true; | 206 | bWantsDisconnect = true; |
207 | } | 207 | } |
208 | 208 | ||
209 | bool Bu::Client::wantsDisconnect() | 209 | bool Bu::Client::wantsDisconnect() |
210 | { | 210 | { |
211 | return bWantsDisconnect; | 211 | return bWantsDisconnect; |
212 | } | 212 | } |
213 | 213 | ||
214 | void Bu::Client::close() | 214 | void Bu::Client::close() |
215 | { | 215 | { |
216 | pTopStream->close(); | 216 | pTopStream->close(); |
217 | } | 217 | } |
218 | 218 | ||
219 | Bu::ClientLink *Bu::Client::getLink() | 219 | Bu::ClientLink *Bu::Client::getLink() |
220 | { | 220 | { |
221 | return pfLink->createLink( this ); | 221 | return pfLink->createLink( this ); |
222 | } | 222 | } |
223 | 223 | ||
224 | void Bu::Client::onMessage( const Bu::String &sMsg ) | 224 | void Bu::Client::onMessage( const Bu::String &sMsg ) |
225 | { | 225 | { |
226 | if( pProto ) | 226 | if( pProto ) |
227 | pProto->onMessage( this, sMsg ); | 227 | pProto->onMessage( this, sMsg ); |
228 | } | 228 | } |
229 | 229 | ||
230 | void Bu::Client::tick() | 230 | void Bu::Client::tick() |
231 | { | 231 | { |
232 | if( pProto ) | 232 | if( pProto ) |
233 | pProto->onTick( this ); | 233 | pProto->onTick( this ); |
234 | } | 234 | } |
235 | 235 | ||
236 | Bu::size Bu::Client::tell() | 236 | Bu::size Bu::Client::tell() |
237 | { | 237 | { |
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | void Bu::Client::seek( Bu::size offset ) | 241 | void Bu::Client::seek( Bu::size offset ) |
242 | { | 242 | { |
243 | return qbRead.seek( offset ); | 243 | return qbRead.seek( offset ); |
244 | } | 244 | } |
245 | 245 | ||
246 | void Bu::Client::setPos( Bu::size ) | 246 | void Bu::Client::setPos( Bu::size ) |
247 | { | 247 | { |
248 | throw Bu::ExceptionBase(); | 248 | throw Bu::ExceptionBase(); |
249 | } | 249 | } |
250 | 250 | ||
251 | void Bu::Client::setPosEnd( Bu::size ) | 251 | void Bu::Client::setPosEnd( Bu::size ) |
252 | { | 252 | { |
253 | throw Bu::ExceptionBase(); | 253 | throw Bu::ExceptionBase(); |
254 | } | 254 | } |
255 | 255 | ||
256 | bool Bu::Client::isEos() | 256 | bool Bu::Client::isEos() |
257 | { | 257 | { |
258 | return true; | 258 | return true; |
259 | } | 259 | } |
260 | 260 | ||
261 | void Bu::Client::flush() | 261 | void Bu::Client::flush() |
262 | { | 262 | { |
263 | processOutput(); | 263 | processOutput(); |
264 | } | 264 | } |
265 | 265 | ||
266 | bool Bu::Client::canRead() | 266 | bool Bu::Client::canRead() |
267 | { | 267 | { |
268 | return qbRead.getSize() > 0; | 268 | return qbRead.getSize() > 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | bool Bu::Client::canWrite() | 271 | bool Bu::Client::canWrite() |
272 | { | 272 | { |
273 | return true; | 273 | return true; |
274 | } | 274 | } |
275 | 275 | ||
276 | bool Bu::Client::isReadable() | 276 | bool Bu::Client::isReadable() |
277 | { | 277 | { |
278 | return true; | 278 | return true; |
279 | } | 279 | } |
280 | 280 | ||
281 | bool Bu::Client::isWritable() | 281 | bool Bu::Client::isWritable() |
282 | { | 282 | { |
283 | return true; | 283 | return true; |
284 | } | 284 | } |
285 | 285 | ||
286 | bool Bu::Client::isSeekable() | 286 | bool Bu::Client::isSeekable() |
287 | { | 287 | { |
288 | return false; | 288 | return false; |
289 | } | 289 | } |
290 | 290 | ||
291 | bool Bu::Client::isBlocking() | 291 | bool Bu::Client::isBlocking() |
292 | { | 292 | { |
293 | return false; | 293 | return false; |
294 | } | 294 | } |
295 | 295 | ||
296 | void Bu::Client::setBlocking( bool ) | 296 | void Bu::Client::setBlocking( bool ) |
297 | { | 297 | { |
298 | throw Bu::ExceptionBase(); | 298 | throw Bu::ExceptionBase(); |
299 | } | 299 | } |
300 | 300 | ||
301 | void Bu::Client::setSize( Bu::size ) | 301 | void Bu::Client::setSize( Bu::size ) |
302 | { | 302 | { |
303 | throw Bu::ExceptionBase(); | 303 | throw Bu::ExceptionBase(); |
304 | } | 304 | } |
305 | 305 | ||
306 | Bu::size Bu::Client::getSize() const | 306 | Bu::size Bu::Client::getSize() const |
307 | { | 307 | { |
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | Bu::size Bu::Client::getBlockSize() const | 311 | Bu::size Bu::Client::getBlockSize() const |
312 | { | 312 | { |
313 | return pSocket->getBlockSize(); | 313 | return pSocket->getBlockSize(); |
314 | } | 314 | } |
315 | 315 | ||
316 | Bu::String Bu::Client::getLocation() const | 316 | Bu::String Bu::Client::getLocation() const |
317 | { | 317 | { |
318 | return pSocket->getLocation(); | 318 | return pSocket->getLocation(); |
319 | } | 319 | } |
320 | 320 | ||
diff --git a/src/stable/client.h b/src/stable/client.h index 6bd41af..cacc8aa 100644 --- a/src/stable/client.h +++ b/src/stable/client.h | |||
@@ -16,118 +16,118 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class Protocol; | 19 | class Protocol; |
20 | class Stream; | 20 | class Stream; |
21 | class TcpSocket; | 21 | class TcpSocket; |
22 | class ClientLinkFactory; | 22 | class ClientLinkFactory; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | *@ingroup Serving | 25 | *@ingroup Serving |
26 | */ | 26 | */ |
27 | class Client : public Bu::Stream | 27 | class Client : public Bu::Stream |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); | 30 | Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); |
31 | virtual ~Client(); | 31 | virtual ~Client(); |
32 | 32 | ||
33 | void processInput(); | 33 | void processInput(); |
34 | void processOutput(); | 34 | void processOutput(); |
35 | 35 | ||
36 | //Bu::String &getInput(); | 36 | //Bu::String &getInput(); |
37 | //Bu::String &getOutput(); | 37 | //Bu::String &getOutput(); |
38 | Bu::size write( const Bu::String &sData ); | 38 | Bu::size write( const Bu::String &sData ); |
39 | Bu::size write( const void *pData, Bu::size nBytes ); | 39 | Bu::size write( const void *pData, Bu::size nBytes ); |
40 | Bu::size write( int8_t nData ); | 40 | Bu::size write( int8_t nData ); |
41 | Bu::size write( int16_t nData ); | 41 | Bu::size write( int16_t nData ); |
42 | Bu::size write( int32_t nData ); | 42 | Bu::size write( int32_t nData ); |
43 | Bu::size write( int64_t nData ); | 43 | Bu::size write( int64_t nData ); |
44 | Bu::size write( uint8_t nData ); | 44 | Bu::size write( uint8_t nData ); |
45 | Bu::size write( uint16_t nData ); | 45 | Bu::size write( uint16_t nData ); |
46 | Bu::size write( uint32_t nData ); | 46 | Bu::size write( uint32_t nData ); |
47 | Bu::size write( uint64_t nData ); | 47 | Bu::size write( uint64_t nData ); |
48 | Bu::size read( void *pData, Bu::size nBytes ); | 48 | Bu::size read( void *pData, Bu::size nBytes ); |
49 | Bu::size peek( void *pData, int nBytes, int nOffset=0 ); | 49 | Bu::size peek( void *pData, int nBytes, int nOffset=0 ); |
50 | // void seek( int nBytes ); | 50 | // void seek( int nBytes ); |
51 | Bu::size getInputSize(); | 51 | Bu::size getInputSize(); |
52 | Bu::size getOutputSize(); | 52 | Bu::size getOutputSize(); |
53 | 53 | ||
54 | void setProtocol( Protocol *pProto ); | 54 | void setProtocol( Protocol *pProto ); |
55 | Bu::Protocol *getProtocol(); | 55 | Bu::Protocol *getProtocol(); |
56 | void clearProtocol(); | 56 | void clearProtocol(); |
57 | 57 | ||
58 | bool isOpen(); | 58 | bool isOpen(); |
59 | void close(); | 59 | void close(); |
60 | void tick(); | 60 | void tick(); |
61 | 61 | ||
62 | const Bu::TcpSocket *getSocket() const; | 62 | const Bu::TcpSocket *getSocket() const; |
63 | 63 | ||
64 | void disconnect(); | 64 | void disconnect(); |
65 | bool wantsDisconnect(); | 65 | bool wantsDisconnect(); |
66 | 66 | ||
67 | class ClientLink *getLink(); | 67 | class ClientLink *getLink(); |
68 | 68 | ||
69 | void onMessage( const Bu::String &sMsg ); | 69 | void onMessage( const Bu::String &sMsg ); |
70 | 70 | ||
71 | bool hasOutput() { return qbWrite.getSize() > 0; } | 71 | bool hasOutput() { return qbWrite.getSize() > 0; } |
72 | bool hasInput() { return qbRead.getSize() > 0; } | 72 | bool hasInput() { return qbRead.getSize() > 0; } |
73 | 73 | ||
74 | template<typename filter> | 74 | template<typename filter> |
75 | void pushFilter() | 75 | void pushFilter() |
76 | { | 76 | { |
77 | filter *pFlt = new filter( *pTopStream ); | 77 | filter *pFlt = new filter( *pTopStream ); |
78 | pTopStream = pFlt; | 78 | pTopStream = pFlt; |
79 | lFilts.prepend( pFlt ); | 79 | lFilts.prepend( pFlt ); |
80 | } | 80 | } |
81 | 81 | ||
82 | template<typename filter, typename p1t> | 82 | template<typename filter, typename p1t> |
83 | void pushFilter( p1t p1 ) | 83 | void pushFilter( p1t p1 ) |
84 | { | 84 | { |
85 | filter *pFlt = new filter( *pTopStream, p1 ); | 85 | filter *pFlt = new filter( *pTopStream, p1 ); |
86 | pTopStream = pFlt; | 86 | pTopStream = pFlt; |
87 | lFilts.prepend( pFlt ); | 87 | lFilts.prepend( pFlt ); |
88 | } | 88 | } |
89 | 89 | ||
90 | template<typename filter, typename p1t, typename p2t> | 90 | template<typename filter, typename p1t, typename p2t> |
91 | void pushFilter( p1t p1, p2t p2 ) | 91 | void pushFilter( p1t p1, p2t p2 ) |
92 | { | 92 | { |
93 | filter *pFlt = new filter( *pTopStream, p1, p2 ); | 93 | filter *pFlt = new filter( *pTopStream, p1, p2 ); |
94 | pTopStream = pFlt; | 94 | pTopStream = pFlt; |
95 | lFilts.prepend( pFlt ); | 95 | lFilts.prepend( pFlt ); |
96 | } | 96 | } |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * These are required to qualify as a stream, I dunno how many will | 99 | * These are required to qualify as a stream, I dunno how many will |
100 | * be implemented. | 100 | * be implemented. |
101 | */ | 101 | */ |
102 | virtual Bu::size tell(); | 102 | virtual Bu::size tell(); |
103 | virtual void seek( Bu::size offset ); | 103 | virtual void seek( Bu::size offset ); |
104 | virtual void setPos( Bu::size pos ); | 104 | virtual void setPos( Bu::size pos ); |
105 | virtual void setPosEnd( Bu::size pos ); | 105 | virtual void setPosEnd( Bu::size pos ); |
106 | virtual bool isEos(); | 106 | virtual bool isEos(); |
107 | virtual void flush(); | 107 | virtual void flush(); |
108 | virtual bool canRead(); | 108 | virtual bool canRead(); |
109 | virtual bool canWrite(); | 109 | virtual bool canWrite(); |
110 | virtual bool isReadable(); | 110 | virtual bool isReadable(); |
111 | virtual bool isWritable(); | 111 | virtual bool isWritable(); |
112 | virtual bool isSeekable(); | 112 | virtual bool isSeekable(); |
113 | virtual bool isBlocking(); | 113 | virtual bool isBlocking(); |
114 | virtual void setBlocking( bool bBlocking=true ); | 114 | virtual void setBlocking( bool bBlocking=true ); |
115 | virtual void setSize( Bu::size iSize ); | 115 | virtual void setSize( Bu::size iSize ); |
116 | virtual size getSize() const; | 116 | virtual size getSize() const; |
117 | virtual size getBlockSize() const; | 117 | virtual size getBlockSize() const; |
118 | virtual Bu::String getLocation() const; | 118 | virtual Bu::String getLocation() const; |
119 | 119 | ||
120 | private: | 120 | private: |
121 | typedef Bu::List<Bu::Stream *> FilterList; | 121 | typedef Bu::List<Bu::Stream *> FilterList; |
122 | FilterList lFilts; | 122 | FilterList lFilts; |
123 | Bu::Stream *pTopStream; | 123 | Bu::Stream *pTopStream; |
124 | Bu::TcpSocket *pSocket; | 124 | Bu::TcpSocket *pSocket; |
125 | Bu::Protocol *pProto; | 125 | Bu::Protocol *pProto; |
126 | Bu::QueueBuf qbRead; | 126 | Bu::QueueBuf qbRead; |
127 | Bu::QueueBuf qbWrite; | 127 | Bu::QueueBuf qbWrite; |
128 | bool bWantsDisconnect; | 128 | bool bWantsDisconnect; |
129 | class Bu::ClientLinkFactory *pfLink; | 129 | class Bu::ClientLinkFactory *pfLink; |
130 | }; | 130 | }; |
131 | } | 131 | } |
132 | 132 | ||
133 | #endif | 133 | #endif |
diff --git a/src/stable/clientlink.h b/src/stable/clientlink.h index b5cd74d..d822c93 100644 --- a/src/stable/clientlink.h +++ b/src/stable/clientlink.h | |||
@@ -12,14 +12,14 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class ClientLink | 15 | class ClientLink |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | ClientLink(); | 18 | ClientLink(); |
19 | virtual ~ClientLink(); | 19 | virtual ~ClientLink(); |
20 | 20 | ||
21 | virtual void sendMessage( const Bu::String &sMsg )=0; | 21 | virtual void sendMessage( const Bu::String &sMsg )=0; |
22 | }; | 22 | }; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #endif | 25 | #endif |
diff --git a/src/stable/clientlinkfactory.h b/src/stable/clientlinkfactory.h index b1b7670..bd64f6b 100644 --- a/src/stable/clientlinkfactory.h +++ b/src/stable/clientlinkfactory.h | |||
@@ -10,17 +10,17 @@ | |||
10 | 10 | ||
11 | namespace Bu | 11 | namespace Bu |
12 | { | 12 | { |
13 | class Client; | 13 | class Client; |
14 | class ClientLink; | 14 | class ClientLink; |
15 | 15 | ||
16 | class ClientLinkFactory | 16 | class ClientLinkFactory |
17 | { | 17 | { |
18 | public: | 18 | public: |
19 | ClientLinkFactory(); | 19 | ClientLinkFactory(); |
20 | virtual ~ClientLinkFactory(); | 20 | virtual ~ClientLinkFactory(); |
21 | 21 | ||
22 | virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; | 22 | virtual Bu::ClientLink *createLink( Bu::Client *pClient )=0; |
23 | }; | 23 | }; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | #endif | 26 | #endif |
diff --git a/src/stable/condition.cpp b/src/stable/condition.cpp index 79af262..f02eca7 100644 --- a/src/stable/condition.cpp +++ b/src/stable/condition.cpp | |||
@@ -11,39 +11,39 @@ | |||
11 | 11 | ||
12 | Bu::Condition::Condition() | 12 | Bu::Condition::Condition() |
13 | { | 13 | { |
14 | pthread_cond_init( &cond, NULL ); | 14 | pthread_cond_init( &cond, NULL ); |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::Condition::~Condition() | 17 | Bu::Condition::~Condition() |
18 | { | 18 | { |
19 | pthread_cond_destroy( &cond ); | 19 | pthread_cond_destroy( &cond ); |
20 | } | 20 | } |
21 | 21 | ||
22 | int Bu::Condition::wait() | 22 | int Bu::Condition::wait() |
23 | { | 23 | { |
24 | return pthread_cond_wait( &cond, &mutex ); | 24 | return pthread_cond_wait( &cond, &mutex ); |
25 | } | 25 | } |
26 | 26 | ||
27 | int Bu::Condition::wait( int nSec, int nUSec ) | 27 | int Bu::Condition::wait( int nSec, int nUSec ) |
28 | { | 28 | { |
29 | struct timeval now; | 29 | struct timeval now; |
30 | struct timespec timeout; | 30 | struct timespec timeout; |
31 | struct timezone tz; | 31 | struct timezone tz; |
32 | 32 | ||
33 | gettimeofday( &now, &tz ); | 33 | gettimeofday( &now, &tz ); |
34 | timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); | 34 | timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); |
35 | timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; | 35 | timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; |
36 | 36 | ||
37 | return pthread_cond_timedwait( &cond, &mutex, &timeout ); | 37 | return pthread_cond_timedwait( &cond, &mutex, &timeout ); |
38 | } | 38 | } |
39 | 39 | ||
40 | int Bu::Condition::signal() | 40 | int Bu::Condition::signal() |
41 | { | 41 | { |
42 | return pthread_cond_signal( &cond ); | 42 | return pthread_cond_signal( &cond ); |
43 | } | 43 | } |
44 | 44 | ||
45 | int Bu::Condition::broadcast() | 45 | int Bu::Condition::broadcast() |
46 | { | 46 | { |
47 | return pthread_cond_broadcast( &cond ); | 47 | return pthread_cond_broadcast( &cond ); |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/src/stable/condition.h b/src/stable/condition.h index 2c27720..53eb9ff 100644 --- a/src/stable/condition.h +++ b/src/stable/condition.h | |||
@@ -14,77 +14,77 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Ito condition. This is a fairly simple condition mechanism. As you may | 18 | * Ito condition. This is a fairly simple condition mechanism. As you may |
19 | * notice this class inherits from the Mutex class, this is because all | 19 | * notice this class inherits from the Mutex class, this is because all |
20 | * conditions must be within a locked block. The standard usage of a | 20 | * conditions must be within a locked block. The standard usage of a |
21 | * condition is to pause one thread, perhaps indefinately, until another | 21 | * condition is to pause one thread, perhaps indefinately, until another |
22 | * thread signals that it is alright to procede. | 22 | * thread signals that it is alright to procede. |
23 | * <br> | 23 | * <br> |
24 | * Standard usage for the thread that wants to wait is as follows: | 24 | * Standard usage for the thread that wants to wait is as follows: |
25 | * <pre> | 25 | * <pre> |
26 | * Condition cond; | 26 | * Condition cond; |
27 | * ... // Perform setup and enter your run loop | 27 | * ... // Perform setup and enter your run loop |
28 | * cond.lock(); | 28 | * cond.lock(); |
29 | * while( !isFinished() ) // Could be anything you're waiting for | 29 | * while( !isFinished() ) // Could be anything you're waiting for |
30 | * cond.wait(); | 30 | * cond.wait(); |
31 | * ... // Take care of what you have to. | 31 | * ... // Take care of what you have to. |
32 | * cond.unlock(); | 32 | * cond.unlock(); |
33 | * </pre> | 33 | * </pre> |
34 | * The usage for the triggering thread is much simpler, when it needs to | 34 | * The usage for the triggering thread is much simpler, when it needs to |
35 | * tell the others that it's time to grab some data it calls either signal | 35 | * tell the others that it's time to grab some data it calls either signal |
36 | * or broadcast. See both of those functions for the difference. | 36 | * or broadcast. See both of those functions for the difference. |
37 | *@ingroup Threading | 37 | *@ingroup Threading |
38 | */ | 38 | */ |
39 | class Condition : public Mutex | 39 | class Condition : public Mutex |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | /** | 42 | /** |
43 | * Create a condition. | 43 | * Create a condition. |
44 | */ | 44 | */ |
45 | Condition(); | 45 | Condition(); |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Destroy a condition. | 48 | * Destroy a condition. |
49 | */ | 49 | */ |
50 | ~Condition(); | 50 | ~Condition(); |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Wait forever, or until signalled. This has to be called from within | 53 | * Wait forever, or until signalled. This has to be called from within |
54 | * a locked section, i.e. before calling this this object's lock | 54 | * a locked section, i.e. before calling this this object's lock |
55 | * function should be called. | 55 | * function should be called. |
56 | */ | 56 | */ |
57 | int wait(); | 57 | int wait(); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * Wait for a maximum of nSec seconds and nUSec micro-seconds or until | 60 | * Wait for a maximum of nSec seconds and nUSec micro-seconds or until |
61 | * signalled. This is a little more friendly function if you want to | 61 | * signalled. This is a little more friendly function if you want to |
62 | * perform other operations in the thrad loop that calls this function. | 62 | * perform other operations in the thrad loop that calls this function. |
63 | * Like the other wait function, this must be inside a locked section. | 63 | * Like the other wait function, this must be inside a locked section. |
64 | *@param nSec The seconds to wait. | 64 | *@param nSec The seconds to wait. |
65 | *@param nUSec the micro-seconds to wait. | 65 | *@param nUSec the micro-seconds to wait. |
66 | */ | 66 | */ |
67 | int wait( int nSec, int nUSec ); | 67 | int wait( int nSec, int nUSec ); |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * Notify the next thread waiting on this condition that they can go | 70 | * Notify the next thread waiting on this condition that they can go |
71 | * ahead. This only signals one thread, the next one in the condition | 71 | * ahead. This only signals one thread, the next one in the condition |
72 | * queue, that it is safe to procede with whatever operation was being | 72 | * queue, that it is safe to procede with whatever operation was being |
73 | * waited on. | 73 | * waited on. |
74 | */ | 74 | */ |
75 | int signal(); | 75 | int signal(); |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Notify all threads waiting on this condition that they can go ahead | 78 | * Notify all threads waiting on this condition that they can go ahead |
79 | * now. This function is slower than signal, but more effective in | 79 | * now. This function is slower than signal, but more effective in |
80 | * certain situations where you may not know how many threads should be | 80 | * certain situations where you may not know how many threads should be |
81 | * activated. | 81 | * activated. |
82 | */ | 82 | */ |
83 | int broadcast(); | 83 | int broadcast(); |
84 | 84 | ||
85 | private: | 85 | private: |
86 | pthread_cond_t cond; /**< Internal condition reference. */ | 86 | pthread_cond_t cond; /**< Internal condition reference. */ |
87 | }; | 87 | }; |
88 | } | 88 | } |
89 | 89 | ||
90 | #endif | 90 | #endif |
diff --git a/src/stable/conduit.cpp b/src/stable/conduit.cpp index 8f5eba5..4c2fda6 100644 --- a/src/stable/conduit.cpp +++ b/src/stable/conduit.cpp | |||
@@ -8,9 +8,9 @@ | |||
8 | #include "bu/conduit.h" | 8 | #include "bu/conduit.h" |
9 | 9 | ||
10 | Bu::Conduit::Conduit( int iBlockSize ) : | 10 | Bu::Conduit::Conduit( int iBlockSize ) : |
11 | qb( iBlockSize ), | 11 | qb( iBlockSize ), |
12 | bBlocking( true ), | 12 | bBlocking( true ), |
13 | bOpen( true ) | 13 | bOpen( true ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,100 +20,100 @@ Bu::Conduit::~Conduit() | |||
20 | 20 | ||
21 | void Bu::Conduit::close() | 21 | void Bu::Conduit::close() |
22 | { | 22 | { |
23 | im.lock(); | 23 | im.lock(); |
24 | // qb.close(); | 24 | // qb.close(); |
25 | bOpen = false; | 25 | bOpen = false; |
26 | 26 | ||
27 | cBlock.signal(); | 27 | cBlock.signal(); |
28 | im.unlock(); | 28 | im.unlock(); |
29 | } | 29 | } |
30 | 30 | ||
31 | #include <stdio.h> | 31 | #include <stdio.h> |
32 | Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) | 32 | Bu::size Bu::Conduit::read( void *pBuf, Bu::size nBytes ) |
33 | { | 33 | { |
34 | if( !isOpen() ) | 34 | if( !isOpen() ) |
35 | { | 35 | { |
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | im.lock(); | 38 | im.lock(); |
39 | if( bBlocking ) | 39 | if( bBlocking ) |
40 | { | 40 | { |
41 | im.unlock(); | 41 | im.unlock(); |
42 | cBlock.lock(); | 42 | cBlock.lock(); |
43 | for(;;) | 43 | for(;;) |
44 | { | 44 | { |
45 | im.lock(); | 45 | im.lock(); |
46 | if( qb.getSize() == 0 && bOpen == false ) | 46 | if( qb.getSize() == 0 && bOpen == false ) |
47 | { | 47 | { |
48 | im.unlock(); | 48 | im.unlock(); |
49 | cBlock.unlock(); | 49 | cBlock.unlock(); |
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | else if( qb.getSize() > 0 ) | 52 | else if( qb.getSize() > 0 ) |
53 | { | 53 | { |
54 | im.unlock(); | 54 | im.unlock(); |
55 | break; | 55 | break; |
56 | } | 56 | } |
57 | im.unlock(); | 57 | im.unlock(); |
58 | 58 | ||
59 | cBlock.wait(); | 59 | cBlock.wait(); |
60 | } | 60 | } |
61 | 61 | ||
62 | im.lock(); | 62 | im.lock(); |
63 | Bu::size iRet = qb.read( pBuf, nBytes ); | 63 | Bu::size iRet = qb.read( pBuf, nBytes ); |
64 | im.unlock(); | 64 | im.unlock(); |
65 | 65 | ||
66 | cBlock.unlock(); | 66 | cBlock.unlock(); |
67 | return iRet; | 67 | return iRet; |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | Bu::size iRet = qb.read( pBuf, nBytes ); | 71 | Bu::size iRet = qb.read( pBuf, nBytes ); |
72 | im.unlock(); | 72 | im.unlock(); |
73 | 73 | ||
74 | return iRet; | 74 | return iRet; |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) | 78 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes ) |
79 | { | 79 | { |
80 | im.lock(); | 80 | im.lock(); |
81 | Bu::size iRet = qb.peek( pBuf, nBytes ); | 81 | Bu::size iRet = qb.peek( pBuf, nBytes ); |
82 | im.unlock(); | 82 | im.unlock(); |
83 | 83 | ||
84 | return iRet; | 84 | return iRet; |
85 | } | 85 | } |
86 | 86 | ||
87 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) | 87 | Bu::size Bu::Conduit::peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ) |
88 | { | 88 | { |
89 | im.lock(); | 89 | im.lock(); |
90 | Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); | 90 | Bu::size iRet = qb.peek( pBuf, nBytes, nSkip ); |
91 | im.unlock(); | 91 | im.unlock(); |
92 | 92 | ||
93 | return iRet; | 93 | return iRet; |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) | 96 | Bu::size Bu::Conduit::write( const void *pBuf, Bu::size nBytes ) |
97 | { | 97 | { |
98 | im.lock(); | 98 | im.lock(); |
99 | if( bOpen == false ) | 99 | if( bOpen == false ) |
100 | { | 100 | { |
101 | im.unlock(); | 101 | im.unlock(); |
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | Bu::size sRet = qb.write( pBuf, nBytes ); | 104 | Bu::size sRet = qb.write( pBuf, nBytes ); |
105 | cBlock.signal(); | 105 | cBlock.signal(); |
106 | im.unlock(); | 106 | im.unlock(); |
107 | 107 | ||
108 | return sRet; | 108 | return sRet; |
109 | } | 109 | } |
110 | 110 | ||
111 | Bu::size Bu::Conduit::tell() | 111 | Bu::size Bu::Conduit::tell() |
112 | { | 112 | { |
113 | im.lock(); | 113 | im.lock(); |
114 | Bu::size sRet = qb.tell(); | 114 | Bu::size sRet = qb.tell(); |
115 | im.unlock(); | 115 | im.unlock(); |
116 | return sRet; | 116 | return sRet; |
117 | } | 117 | } |
118 | 118 | ||
119 | void Bu::Conduit::seek( Bu::size ) | 119 | void Bu::Conduit::seek( Bu::size ) |
@@ -130,18 +130,18 @@ void Bu::Conduit::setPosEnd( Bu::size ) | |||
130 | 130 | ||
131 | bool Bu::Conduit::isEos() | 131 | bool Bu::Conduit::isEos() |
132 | { | 132 | { |
133 | im.lock(); | 133 | im.lock(); |
134 | bool bRet = qb.isEos(); | 134 | bool bRet = qb.isEos(); |
135 | im.unlock(); | 135 | im.unlock(); |
136 | return bRet; | 136 | return bRet; |
137 | } | 137 | } |
138 | 138 | ||
139 | bool Bu::Conduit::isOpen() | 139 | bool Bu::Conduit::isOpen() |
140 | { | 140 | { |
141 | im.lock(); | 141 | im.lock(); |
142 | bool bRet = bOpen || (qb.getSize() > 0); | 142 | bool bRet = bOpen || (qb.getSize() > 0); |
143 | im.unlock(); | 143 | im.unlock(); |
144 | return bRet; | 144 | return bRet; |
145 | } | 145 | } |
146 | 146 | ||
147 | void Bu::Conduit::flush() | 147 | void Bu::Conduit::flush() |
@@ -150,57 +150,57 @@ void Bu::Conduit::flush() | |||
150 | 150 | ||
151 | bool Bu::Conduit::canRead() | 151 | bool Bu::Conduit::canRead() |
152 | { | 152 | { |
153 | im.lock(); | 153 | im.lock(); |
154 | bool bRet = qb.canRead(); | 154 | bool bRet = qb.canRead(); |
155 | im.unlock(); | 155 | im.unlock(); |
156 | return bRet; | 156 | return bRet; |
157 | } | 157 | } |
158 | 158 | ||
159 | bool Bu::Conduit::canWrite() | 159 | bool Bu::Conduit::canWrite() |
160 | { | 160 | { |
161 | im.lock(); | 161 | im.lock(); |
162 | bool bRet = qb.canWrite(); | 162 | bool bRet = qb.canWrite(); |
163 | im.unlock(); | 163 | im.unlock(); |
164 | return bRet; | 164 | return bRet; |
165 | } | 165 | } |
166 | 166 | ||
167 | bool Bu::Conduit::isReadable() | 167 | bool Bu::Conduit::isReadable() |
168 | { | 168 | { |
169 | im.lock(); | 169 | im.lock(); |
170 | bool bRet = qb.isReadable(); | 170 | bool bRet = qb.isReadable(); |
171 | im.unlock(); | 171 | im.unlock(); |
172 | return bRet; | 172 | return bRet; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool Bu::Conduit::isWritable() | 175 | bool Bu::Conduit::isWritable() |
176 | { | 176 | { |
177 | im.lock(); | 177 | im.lock(); |
178 | bool bRet = qb.isWritable(); | 178 | bool bRet = qb.isWritable(); |
179 | im.unlock(); | 179 | im.unlock(); |
180 | return bRet; | 180 | return bRet; |
181 | } | 181 | } |
182 | 182 | ||
183 | bool Bu::Conduit::isSeekable() | 183 | bool Bu::Conduit::isSeekable() |
184 | { | 184 | { |
185 | im.lock(); | 185 | im.lock(); |
186 | bool bRet = qb.isSeekable(); | 186 | bool bRet = qb.isSeekable(); |
187 | im.unlock(); | 187 | im.unlock(); |
188 | return bRet; | 188 | return bRet; |
189 | } | 189 | } |
190 | 190 | ||
191 | bool Bu::Conduit::isBlocking() | 191 | bool Bu::Conduit::isBlocking() |
192 | { | 192 | { |
193 | im.lock(); | 193 | im.lock(); |
194 | bool bRet = bBlocking; | 194 | bool bRet = bBlocking; |
195 | im.unlock(); | 195 | im.unlock(); |
196 | return bRet; | 196 | return bRet; |
197 | } | 197 | } |
198 | 198 | ||
199 | void Bu::Conduit::setBlocking( bool bBlocking ) | 199 | void Bu::Conduit::setBlocking( bool bBlocking ) |
200 | { | 200 | { |
201 | im.lock(); | 201 | im.lock(); |
202 | this->bBlocking = bBlocking; | 202 | this->bBlocking = bBlocking; |
203 | im.unlock(); | 203 | im.unlock(); |
204 | } | 204 | } |
205 | 205 | ||
206 | void Bu::Conduit::setSize( Bu::size ) | 206 | void Bu::Conduit::setSize( Bu::size ) |
@@ -209,25 +209,25 @@ void Bu::Conduit::setSize( Bu::size ) | |||
209 | 209 | ||
210 | Bu::size Bu::Conduit::getSize() const | 210 | Bu::size Bu::Conduit::getSize() const |
211 | { | 211 | { |
212 | im.lock(); | 212 | im.lock(); |
213 | Bu::size sRet = qb.getSize(); | 213 | Bu::size sRet = qb.getSize(); |
214 | im.unlock(); | 214 | im.unlock(); |
215 | return sRet; | 215 | return sRet; |
216 | } | 216 | } |
217 | 217 | ||
218 | Bu::size Bu::Conduit::getBlockSize() const | 218 | Bu::size Bu::Conduit::getBlockSize() const |
219 | { | 219 | { |
220 | im.lock(); | 220 | im.lock(); |
221 | Bu::size sRet = qb.getBlockSize(); | 221 | Bu::size sRet = qb.getBlockSize(); |
222 | im.unlock(); | 222 | im.unlock(); |
223 | return sRet; | 223 | return sRet; |
224 | } | 224 | } |
225 | 225 | ||
226 | Bu::String Bu::Conduit::getLocation() const | 226 | Bu::String Bu::Conduit::getLocation() const |
227 | { | 227 | { |
228 | im.lock(); | 228 | im.lock(); |
229 | Bu::String sRet = qb.getLocation(); | 229 | Bu::String sRet = qb.getLocation(); |
230 | im.unlock(); | 230 | im.unlock(); |
231 | return sRet; | 231 | return sRet; |
232 | } | 232 | } |
233 | 233 | ||
diff --git a/src/stable/conduit.h b/src/stable/conduit.h index a1959a9..78d24eb 100644 --- a/src/stable/conduit.h +++ b/src/stable/conduit.h | |||
@@ -16,49 +16,49 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Simple inter-thread communication stream. This acts like a pair of | 20 | * Simple inter-thread communication stream. This acts like a pair of |
21 | * pipes for stream communication between any two things, but without the | 21 | * pipes for stream communication between any two things, but without the |
22 | * use of pipes, making this a bad choice for IPC. | 22 | * use of pipes, making this a bad choice for IPC. |
23 | */ | 23 | */ |
24 | class Conduit : public Stream | 24 | class Conduit : public Stream |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | Conduit( int iBlockSize=256 ); | 27 | Conduit( int iBlockSize=256 ); |
28 | virtual ~Conduit(); | 28 | virtual ~Conduit(); |
29 | 29 | ||
30 | virtual void close(); | 30 | virtual void close(); |
31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); | 32 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); |
33 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); | 33 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); |
34 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 34 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
35 | virtual Bu::size tell(); | 35 | virtual Bu::size tell(); |
36 | virtual void seek( Bu::size offset ); | 36 | virtual void seek( Bu::size offset ); |
37 | virtual void setPos( Bu::size pos ); | 37 | virtual void setPos( Bu::size pos ); |
38 | virtual void setPosEnd( Bu::size pos ); | 38 | virtual void setPosEnd( Bu::size pos ); |
39 | virtual bool isEos(); | 39 | virtual bool isEos(); |
40 | virtual bool isOpen(); | 40 | virtual bool isOpen(); |
41 | virtual void flush(); | 41 | virtual void flush(); |
42 | virtual bool canRead(); | 42 | virtual bool canRead(); |
43 | virtual bool canWrite(); | 43 | virtual bool canWrite(); |
44 | virtual bool isReadable(); | 44 | virtual bool isReadable(); |
45 | virtual bool isWritable(); | 45 | virtual bool isWritable(); |
46 | virtual bool isSeekable(); | 46 | virtual bool isSeekable(); |
47 | virtual bool isBlocking(); | 47 | virtual bool isBlocking(); |
48 | virtual void setBlocking( bool bBlocking=true ); | 48 | virtual void setBlocking( bool bBlocking=true ); |
49 | virtual void setSize( Bu::size iSize ); | 49 | virtual void setSize( Bu::size iSize ); |
50 | 50 | ||
51 | virtual size getSize() const; | 51 | virtual size getSize() const; |
52 | virtual size getBlockSize() const; | 52 | virtual size getBlockSize() const; |
53 | virtual Bu::String getLocation() const; | 53 | virtual Bu::String getLocation() const; |
54 | 54 | ||
55 | private: | 55 | private: |
56 | QueueBuf qb; | 56 | QueueBuf qb; |
57 | mutable Mutex im; | 57 | mutable Mutex im; |
58 | Condition cBlock; | 58 | Condition cBlock; |
59 | bool bBlocking; | 59 | bool bBlocking; |
60 | bool bOpen; | 60 | bool bOpen; |
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #endif | 64 | #endif |
diff --git a/src/stable/crypt.cpp b/src/stable/crypt.cpp index 3f7fc83..2915cf4 100644 --- a/src/stable/crypt.cpp +++ b/src/stable/crypt.cpp | |||
@@ -13,35 +13,35 @@ | |||
13 | 13 | ||
14 | Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) | 14 | Bu::String Bu::cryptPass( const Bu::String &sPass, const Bu::String &sSalt ) |
15 | { | 15 | { |
16 | Bu::Md5 md5; | 16 | Bu::Md5 md5; |
17 | Bu::MemBuf mbOut; | 17 | Bu::MemBuf mbOut; |
18 | Bu::Base64 b64Out( mbOut ); | 18 | Bu::Base64 b64Out( mbOut ); |
19 | 19 | ||
20 | Bu::String::const_iterator i = sSalt.find('$'); | 20 | Bu::String::const_iterator i = sSalt.find('$'); |
21 | Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); | 21 | Bu::String sSaltSml = sSalt.getSubStr( sSalt.begin(), i ); |
22 | 22 | ||
23 | md5.addData( sPass ); | 23 | md5.addData( sPass ); |
24 | md5.addData( sSaltSml ); | 24 | md5.addData( sSaltSml ); |
25 | md5.writeResult( b64Out ); | 25 | md5.writeResult( b64Out ); |
26 | 26 | ||
27 | b64Out.stop(); | 27 | b64Out.stop(); |
28 | 28 | ||
29 | return sSaltSml + "$" + mbOut.getString(); | 29 | return sSaltSml + "$" + mbOut.getString(); |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::String Bu::cryptPass( const Bu::String &sPass ) | 32 | Bu::String Bu::cryptPass( const Bu::String &sPass ) |
33 | { | 33 | { |
34 | Bu::MemBuf mbSalt; | 34 | Bu::MemBuf mbSalt; |
35 | Bu::Base64 b64Salt( mbSalt ); | 35 | Bu::Base64 b64Salt( mbSalt ); |
36 | Bu::File fRand("/dev/urandom", Bu::File::Read ); | 36 | Bu::File fRand("/dev/urandom", Bu::File::Read ); |
37 | 37 | ||
38 | #define STR 6 | 38 | #define STR 6 |
39 | char buf[STR]; | 39 | char buf[STR]; |
40 | fRand.read( buf, STR ); | 40 | fRand.read( buf, STR ); |
41 | b64Salt.write( buf, STR ); | 41 | b64Salt.write( buf, STR ); |
42 | 42 | ||
43 | b64Salt.stop(); | 43 | b64Salt.stop(); |
44 | 44 | ||
45 | return cryptPass( sPass, mbSalt.getString() ); | 45 | return cryptPass( sPass, mbSalt.getString() ); |
46 | } | 46 | } |
47 | 47 | ||
diff --git a/src/stable/crypt.h b/src/stable/crypt.h index 14adc3a..5093610 100644 --- a/src/stable/crypt.h +++ b/src/stable/crypt.h | |||
@@ -12,8 +12,8 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); | 15 | String cryptPass( const Bu::String &sPass, const Bu::String &sSalt ); |
16 | String cryptPass( const Bu::String &sPass ); | 16 | String cryptPass( const Bu::String &sPass ); |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #endif | 19 | #endif |
diff --git a/src/stable/cryptohash.cpp b/src/stable/cryptohash.cpp index dda734c..99a7d92 100644 --- a/src/stable/cryptohash.cpp +++ b/src/stable/cryptohash.cpp | |||
@@ -17,22 +17,22 @@ Bu::CryptoHash::~CryptoHash() | |||
17 | 17 | ||
18 | void Bu::CryptoHash::addData( const Bu::String &sData ) | 18 | void Bu::CryptoHash::addData( const Bu::String &sData ) |
19 | { | 19 | { |
20 | addData( sData.getStr(), sData.getSize() ); | 20 | addData( sData.getStr(), sData.getSize() ); |
21 | } | 21 | } |
22 | 22 | ||
23 | Bu::String Bu::CryptoHash::getHexResult() | 23 | Bu::String Bu::CryptoHash::getHexResult() |
24 | { | 24 | { |
25 | Bu::String sResult = getResult(); | 25 | Bu::String sResult = getResult(); |
26 | Bu::String sRet( 2*sResult.getSize() ); | 26 | Bu::String sRet( 2*sResult.getSize() ); |
27 | static const char hex_tab[] = {"0123456789abcdef"}; | 27 | static const char hex_tab[] = {"0123456789abcdef"}; |
28 | 28 | ||
29 | int k = 0; | 29 | int k = 0; |
30 | for( int i = 0; i < sResult.getSize(); i++ ) | 30 | for( int i = 0; i < sResult.getSize(); i++ ) |
31 | { | 31 | { |
32 | sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; | 32 | sRet[k++] = hex_tab[(((unsigned char)sResult[i])>>4) & 0xF]; |
33 | sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; | 33 | sRet[k++] = hex_tab[((unsigned char)sResult[i]) & 0xF]; |
34 | } | 34 | } |
35 | 35 | ||
36 | return sRet; | 36 | return sRet; |
37 | } | 37 | } |
38 | 38 | ||
diff --git a/src/stable/cryptohash.h b/src/stable/cryptohash.h index 3f13b05..a943590 100644 --- a/src/stable/cryptohash.h +++ b/src/stable/cryptohash.h | |||
@@ -12,22 +12,22 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class Stream; | 15 | class Stream; |
16 | 16 | ||
17 | class CryptoHash | 17 | class CryptoHash |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | CryptoHash(); | 20 | CryptoHash(); |
21 | virtual ~CryptoHash(); | 21 | virtual ~CryptoHash(); |
22 | 22 | ||
23 | virtual void reset() = 0; | 23 | virtual void reset() = 0; |
24 | virtual void setSalt( const Bu::String &sSalt ) = 0; | 24 | virtual void setSalt( const Bu::String &sSalt ) = 0; |
25 | virtual void addData( const void *sData, int iSize ) = 0; | 25 | virtual void addData( const void *sData, int iSize ) = 0; |
26 | virtual void addData( const Bu::String &sData ); | 26 | virtual void addData( const Bu::String &sData ); |
27 | virtual String getResult() = 0; | 27 | virtual String getResult() = 0; |
28 | virtual void writeResult( Stream &sOut ) = 0; | 28 | virtual void writeResult( Stream &sOut ) = 0; |
29 | virtual Bu::String getHexResult(); | 29 | virtual Bu::String getHexResult(); |
30 | }; | 30 | }; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #endif | 33 | #endif |
diff --git a/src/stable/csvreader.cpp b/src/stable/csvreader.cpp index ddc68f0..c27c8ee 100644 --- a/src/stable/csvreader.cpp +++ b/src/stable/csvreader.cpp | |||
@@ -12,24 +12,24 @@ | |||
12 | using namespace Bu; | 12 | using namespace Bu; |
13 | 13 | ||
14 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : | 14 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, Bu::CsvReader::Style eStyle ) : |
15 | sIn( sIn ) | 15 | sIn( sIn ) |
16 | { | 16 | { |
17 | switch( eStyle ) | 17 | switch( eStyle ) |
18 | { | 18 | { |
19 | case styleExcel: | 19 | case styleExcel: |
20 | sDecode = Bu::slot( &decodeExcel ); | 20 | sDecode = Bu::slot( &decodeExcel ); |
21 | break; | 21 | break; |
22 | 22 | ||
23 | case styleC: | 23 | case styleC: |
24 | sDecode = Bu::slot( &decodeC ); | 24 | sDecode = Bu::slot( &decodeC ); |
25 | break; | 25 | break; |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, | 29 | Bu::CsvReader::CsvReader( Bu::Stream &sIn, |
30 | Bu::CsvReader::DecodeSignal sDecode ) : | 30 | Bu::CsvReader::DecodeSignal sDecode ) : |
31 | sIn( sIn ), | 31 | sIn( sIn ), |
32 | sDecode( sDecode ) | 32 | sDecode( sDecode ) |
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
@@ -39,61 +39,61 @@ Bu::CsvReader::~CsvReader() | |||
39 | 39 | ||
40 | Bu::StrArray Bu::CsvReader::readLine() | 40 | Bu::StrArray Bu::CsvReader::readLine() |
41 | { | 41 | { |
42 | Bu::StrArray aVals; | 42 | Bu::StrArray aVals; |
43 | 43 | ||
44 | Bu::String sLine = sIn.readLine(); | 44 | Bu::String sLine = sIn.readLine(); |
45 | 45 | ||
46 | if( !sLine.isSet() ) | 46 | if( !sLine.isSet() ) |
47 | return Bu::StrArray(); | 47 | return Bu::StrArray(); |
48 | 48 | ||
49 | Bu::String::iterator i = sLine.begin(); | 49 | Bu::String::iterator i = sLine.begin(); |
50 | 50 | ||
51 | aVals.append( sDecode( i ) ); | 51 | aVals.append( sDecode( i ) ); |
52 | 52 | ||
53 | while( i ) | 53 | while( i ) |
54 | { | 54 | { |
55 | if( *i == ',' ) | 55 | if( *i == ',' ) |
56 | { | 56 | { |
57 | i++; | 57 | i++; |
58 | if( !i ) | 58 | if( !i ) |
59 | { | 59 | { |
60 | aVals.append(""); | 60 | aVals.append(""); |
61 | break; | 61 | break; |
62 | } | 62 | } |
63 | aVals.append( sDecode( i ) ); | 63 | aVals.append( sDecode( i ) ); |
64 | } | 64 | } |
65 | else | 65 | else |
66 | { | 66 | { |
67 | // Blanks and stuff? | 67 | // Blanks and stuff? |
68 | sio << "Out of bound: '" << *i << "'" << sio.nl; | 68 | sio << "Out of bound: '" << *i << "'" << sio.nl; |
69 | i++; | 69 | i++; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | return aVals; | 73 | return aVals; |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) | 76 | Bu::String Bu::CsvReader::decodeExcel( Bu::String::iterator &i ) |
77 | { | 77 | { |
78 | Bu::String sRet; | 78 | Bu::String sRet; |
79 | 79 | ||
80 | for(; i && (*i == ' ' || *i == '\t'); i++ ) { } | 80 | for(; i && (*i == ' ' || *i == '\t'); i++ ) { } |
81 | 81 | ||
82 | if( !i ) | 82 | if( !i ) |
83 | return sRet; | 83 | return sRet; |
84 | 84 | ||
85 | if( *i == '\"' ) | 85 | if( *i == '\"' ) |
86 | { | 86 | { |
87 | for( i++ ; i; i++ ) | 87 | for( i++ ; i; i++ ) |
88 | { | 88 | { |
89 | if( *i == '\"' ) | 89 | if( *i == '\"' ) |
90 | { | 90 | { |
91 | i++; | 91 | i++; |
92 | if( !i ) | 92 | if( !i ) |
93 | { | 93 | { |
94 | return sRet; | 94 | return sRet; |
95 | } | 95 | } |
96 | else if( *i == '\"' ) | 96 | else if( *i == '\"' ) |
97 | { | 97 | { |
98 | sRet += *i; | 98 | sRet += *i; |
99 | } | 99 | } |
diff --git a/src/stable/csvreader.h b/src/stable/csvreader.h index 6825da3..cb2a560 100644 --- a/src/stable/csvreader.h +++ b/src/stable/csvreader.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | typedef Bu::Array<Bu::String> StrArray; | 18 | typedef Bu::Array<Bu::String> StrArray; |
19 | 19 | ||
20 | class CsvReader | 20 | class CsvReader |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | typedef Bu::Signal1<Bu::String, Bu::String::iterator &> DecodeSignal; | 23 | typedef Bu::Signal1<Bu::String, Bu::String::iterator &> DecodeSignal; |
24 | enum Style | 24 | enum Style |
25 | { | 25 | { |
26 | styleExcel, ///< Excel style quotes around things that need em | 26 | styleExcel, ///< Excel style quotes around things that need em |
27 | styleC ///< Escape things that need it C-style | 27 | styleC ///< Escape things that need it C-style |
28 | }; | 28 | }; |
29 | 29 | ||
30 | CsvReader( Stream &sIn, Style eStyle=styleExcel ); | 30 | CsvReader( Stream &sIn, Style eStyle=styleExcel ); |
31 | CsvReader( Stream &sIn, DecodeSignal sDecode ); | 31 | CsvReader( Stream &sIn, DecodeSignal sDecode ); |
32 | virtual ~CsvReader(); | 32 | virtual ~CsvReader(); |
33 | 33 | ||
34 | StrArray readLine(); | 34 | StrArray readLine(); |
35 | 35 | ||
36 | private: | 36 | private: |
37 | Stream &sIn; | 37 | Stream &sIn; |
38 | DecodeSignal sDecode; | 38 | DecodeSignal sDecode; |
39 | 39 | ||
40 | static Bu::String decodeExcel( Bu::String::iterator &i ); | 40 | static Bu::String decodeExcel( Bu::String::iterator &i ); |
41 | static Bu::String decodeC( Bu::String::iterator &i ); | 41 | static Bu::String decodeC( Bu::String::iterator &i ); |
42 | }; | 42 | }; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/csvwriter.cpp b/src/stable/csvwriter.cpp index a89b309..8b51115 100644 --- a/src/stable/csvwriter.cpp +++ b/src/stable/csvwriter.cpp | |||
@@ -9,24 +9,24 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : | 11 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, Bu::CsvWriter::Style eStyle ) : |
12 | sOut( sOut ) | 12 | sOut( sOut ) |
13 | { | 13 | { |
14 | switch( eStyle ) | 14 | switch( eStyle ) |
15 | { | 15 | { |
16 | case styleExcel: | 16 | case styleExcel: |
17 | sEncode = Bu::slot( &encodeExcel ); | 17 | sEncode = Bu::slot( &encodeExcel ); |
18 | break; | 18 | break; |
19 | 19 | ||
20 | case styleC: | 20 | case styleC: |
21 | sEncode = Bu::slot( &encodeExcel ); | 21 | sEncode = Bu::slot( &encodeExcel ); |
22 | break; | 22 | break; |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, | 26 | Bu::CsvWriter::CsvWriter( Bu::Stream &sOut, |
27 | Bu::CsvWriter::EncodeSignal sEncode ) : | 27 | Bu::CsvWriter::EncodeSignal sEncode ) : |
28 | sOut( sOut ), | 28 | sOut( sOut ), |
29 | sEncode( sEncode ) | 29 | sEncode( sEncode ) |
30 | { | 30 | { |
31 | } | 31 | } |
32 | 32 | ||
@@ -36,46 +36,46 @@ Bu::CsvWriter::~CsvWriter() | |||
36 | 36 | ||
37 | void Bu::CsvWriter::writeLine( const StrArray &aStrs ) | 37 | void Bu::CsvWriter::writeLine( const StrArray &aStrs ) |
38 | { | 38 | { |
39 | Bu::String sBuf; | 39 | Bu::String sBuf; |
40 | for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) | 40 | for( StrArray::const_iterator i = aStrs.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( i != aStrs.begin() ) | 42 | if( i != aStrs.begin() ) |
43 | sBuf += ","; | 43 | sBuf += ","; |
44 | sBuf += sEncode( *i ); | 44 | sBuf += sEncode( *i ); |
45 | } | 45 | } |
46 | sBuf += "\n"; | 46 | sBuf += "\n"; |
47 | 47 | ||
48 | sOut.write( sBuf ); | 48 | sOut.write( sBuf ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) | 51 | Bu::String Bu::CsvWriter::encodeExcel( const Bu::String &sIn ) |
52 | { | 52 | { |
53 | if( sIn.find('\"') || sIn.find(',') ) | 53 | if( sIn.find('\"') || sIn.find(',') ) |
54 | { | 54 | { |
55 | Bu::String sOut = "\""; | 55 | Bu::String sOut = "\""; |
56 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) | 56 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) |
57 | { | 57 | { |
58 | if( *i == '\"' ) | 58 | if( *i == '\"' ) |
59 | sOut += "\"\""; | 59 | sOut += "\"\""; |
60 | else | 60 | else |
61 | sOut += *i; | 61 | sOut += *i; |
62 | } | 62 | } |
63 | sOut += '\"'; | 63 | sOut += '\"'; |
64 | return sOut; | 64 | return sOut; |
65 | } | 65 | } |
66 | return sIn; | 66 | return sIn; |
67 | } | 67 | } |
68 | 68 | ||
69 | Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) | 69 | Bu::String Bu::CsvWriter::encodeC( const Bu::String &sIn ) |
70 | { | 70 | { |
71 | Bu::String sOut = ""; | 71 | Bu::String sOut = ""; |
72 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) | 72 | for( Bu::String::const_iterator i = sIn.begin(); i; i++ ) |
73 | { | 73 | { |
74 | if( *i == ',' ) | 74 | if( *i == ',' ) |
75 | sOut += "\\,"; | 75 | sOut += "\\,"; |
76 | else | 76 | else |
77 | sOut += *i; | 77 | sOut += *i; |
78 | } | 78 | } |
79 | return sOut; | 79 | return sOut; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/src/stable/csvwriter.h b/src/stable/csvwriter.h index bae1e1d..233f4ed 100644 --- a/src/stable/csvwriter.h +++ b/src/stable/csvwriter.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | typedef Bu::Array<Bu::String> StrArray; | 18 | typedef Bu::Array<Bu::String> StrArray; |
19 | 19 | ||
20 | class CsvWriter | 20 | class CsvWriter |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | typedef Bu::Signal1<Bu::String, const Bu::String &> EncodeSignal; | 23 | typedef Bu::Signal1<Bu::String, const Bu::String &> EncodeSignal; |
24 | enum Style | 24 | enum Style |
25 | { | 25 | { |
26 | styleExcel, ///< Excel style quotes around things that need em | 26 | styleExcel, ///< Excel style quotes around things that need em |
27 | styleC ///< Escape things that need it C-style | 27 | styleC ///< Escape things that need it C-style |
28 | }; | 28 | }; |
29 | 29 | ||
30 | CsvWriter( Stream &sOut, Style eStyle=styleExcel ); | 30 | CsvWriter( Stream &sOut, Style eStyle=styleExcel ); |
31 | CsvWriter( Stream &sOut, EncodeSignal sEncode ); | 31 | CsvWriter( Stream &sOut, EncodeSignal sEncode ); |
32 | virtual ~CsvWriter(); | 32 | virtual ~CsvWriter(); |
33 | 33 | ||
34 | void writeLine( const StrArray &aStrs ); | 34 | void writeLine( const StrArray &aStrs ); |
35 | 35 | ||
36 | private: | 36 | private: |
37 | Stream &sOut; | 37 | Stream &sOut; |
38 | EncodeSignal sEncode; | 38 | EncodeSignal sEncode; |
39 | 39 | ||
40 | static Bu::String encodeExcel( const Bu::String &sIn ); | 40 | static Bu::String encodeExcel( const Bu::String &sIn ); |
41 | static Bu::String encodeC( const Bu::String &sIn ); | 41 | static Bu::String encodeC( const Bu::String &sIn ); |
42 | }; | 42 | }; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/deflate.cpp b/src/stable/deflate.cpp index b7e1804..57aa4aa 100644 --- a/src/stable/deflate.cpp +++ b/src/stable/deflate.cpp | |||
@@ -15,239 +15,239 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : | 17 | Bu::Deflate::Deflate( Bu::Stream &rNext, int nCompression, Format eFmt ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ), | 21 | sTotalOut( 0 ), |
22 | eFmt( eFmt ), | 22 | eFmt( eFmt ), |
23 | bEos( false ) | 23 | bEos( false ) |
24 | { | 24 | { |
25 | TRACE( nCompression ); | 25 | TRACE( nCompression ); |
26 | start(); | 26 | start(); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Deflate::~Deflate() | 29 | Bu::Deflate::~Deflate() |
30 | { | 30 | { |
31 | TRACE(); | 31 | TRACE(); |
32 | stop(); | 32 | stop(); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Deflate::start() | 35 | void Bu::Deflate::start() |
36 | { | 36 | { |
37 | TRACE(); | 37 | TRACE(); |
38 | prState = new z_stream; | 38 | prState = new z_stream; |
39 | pState->zalloc = NULL; | 39 | pState->zalloc = NULL; |
40 | pState->zfree = NULL; | 40 | pState->zfree = NULL; |
41 | pState->opaque = NULL; | 41 | pState->opaque = NULL; |
42 | pState->state = NULL; | 42 | pState->state = NULL; |
43 | 43 | ||
44 | nBufSize = 64*1024; | 44 | nBufSize = 64*1024; |
45 | pBuf = new char[nBufSize]; | 45 | pBuf = new char[nBufSize]; |
46 | } | 46 | } |
47 | 47 | ||
48 | Bu::size Bu::Deflate::stop() | 48 | Bu::size Bu::Deflate::stop() |
49 | { | 49 | { |
50 | TRACE(); | 50 | TRACE(); |
51 | if( pState && pState->state ) | 51 | if( pState && pState->state ) |
52 | { | 52 | { |
53 | if( bReading ) | 53 | if( bReading ) |
54 | { | 54 | { |
55 | inflateEnd( pState ); | 55 | inflateEnd( pState ); |
56 | delete[] pBuf; | 56 | delete[] pBuf; |
57 | pBuf = NULL; | 57 | pBuf = NULL; |
58 | delete pState; | 58 | delete pState; |
59 | prState = NULL; | 59 | prState = NULL; |
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | else | 62 | else |
63 | { | 63 | { |
64 | for(;;) | 64 | for(;;) |
65 | { | 65 | { |
66 | pState->next_in = NULL; | 66 | pState->next_in = NULL; |
67 | pState->avail_in = 0; | 67 | pState->avail_in = 0; |
68 | pState->avail_out = nBufSize; | 68 | pState->avail_out = nBufSize; |
69 | pState->next_out = (Bytef *)pBuf; | 69 | pState->next_out = (Bytef *)pBuf; |
70 | int res = deflate( pState, Z_FINISH ); | 70 | int res = deflate( pState, Z_FINISH ); |
71 | if( pState->avail_out < nBufSize ) | 71 | if( pState->avail_out < nBufSize ) |
72 | { | 72 | { |
73 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 73 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
74 | } | 74 | } |
75 | if( res == Z_STREAM_END ) | 75 | if( res == Z_STREAM_END ) |
76 | break; | 76 | break; |
77 | } | 77 | } |
78 | deflateEnd( pState ); | 78 | deflateEnd( pState ); |
79 | delete[] pBuf; | 79 | delete[] pBuf; |
80 | pBuf = NULL; | 80 | pBuf = NULL; |
81 | delete pState; | 81 | delete pState; |
82 | prState = NULL; | 82 | prState = NULL; |
83 | return sTotalOut; | 83 | return sTotalOut; |
84 | } | 84 | } |
85 | } | 85 | } |
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | void Bu::Deflate::zError( int code ) | 89 | void Bu::Deflate::zError( int code ) |
90 | { | 90 | { |
91 | TRACE( code ); | 91 | TRACE( code ); |
92 | switch( code ) | 92 | switch( code ) |
93 | { | 93 | { |
94 | case Z_OK: | 94 | case Z_OK: |
95 | case Z_STREAM_END: | 95 | case Z_STREAM_END: |
96 | case Z_NEED_DICT: | 96 | case Z_NEED_DICT: |
97 | return; | 97 | return; |
98 | 98 | ||
99 | case Z_ERRNO: | 99 | case Z_ERRNO: |
100 | throw ExceptionBase("Deflate: Errno - %s", pState->msg ); | 100 | throw ExceptionBase("Deflate: Errno - %s", pState->msg ); |
101 | 101 | ||
102 | case Z_STREAM_ERROR: | 102 | case Z_STREAM_ERROR: |
103 | throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); | 103 | throw ExceptionBase("Deflate: Stream Error - %s", pState->msg ); |
104 | 104 | ||
105 | case Z_DATA_ERROR: | 105 | case Z_DATA_ERROR: |
106 | throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); | 106 | throw ExceptionBase("Deflate: Data Error - %s", pState->msg ); |
107 | 107 | ||
108 | case Z_MEM_ERROR: | 108 | case Z_MEM_ERROR: |
109 | throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); | 109 | throw ExceptionBase("Deflate: Mem Error - %s", pState->msg ); |
110 | 110 | ||
111 | case Z_BUF_ERROR: | 111 | case Z_BUF_ERROR: |
112 | throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); | 112 | throw ExceptionBase("Deflate: Buf Error - %s", pState->msg ); |
113 | 113 | ||
114 | case Z_VERSION_ERROR: | 114 | case Z_VERSION_ERROR: |
115 | throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); | 115 | throw ExceptionBase("Deflate: Version Error - %s", pState->msg ); |
116 | 116 | ||
117 | default: | 117 | default: |
118 | throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); | 118 | throw ExceptionBase("Deflate: Unknown error encountered - %s.", pState->msg ); |
119 | 119 | ||
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) | 123 | Bu::size Bu::Deflate::read( void *pData, Bu::size nBytes ) |
124 | { | 124 | { |
125 | TRACE( pData, nBytes ); | 125 | TRACE( pData, nBytes ); |
126 | if( nBytes <= 0 ) | 126 | if( nBytes <= 0 ) |
127 | return 0; | 127 | return 0; |
128 | if( !pState->state ) | 128 | if( !pState->state ) |
129 | { | 129 | { |
130 | bReading = true; | 130 | bReading = true; |
131 | if( eFmt&AutoDetect ) | 131 | if( eFmt&AutoDetect ) |
132 | inflateInit2( pState, 32+15 ); // Auto-detect, large window | 132 | inflateInit2( pState, 32+15 ); // Auto-detect, large window |
133 | else if( eFmt == Raw ) | 133 | else if( eFmt == Raw ) |
134 | inflateInit2( pState, -15 ); // Raw | 134 | inflateInit2( pState, -15 ); // Raw |
135 | else if( eFmt == Zlib ) | 135 | else if( eFmt == Zlib ) |
136 | inflateInit2( pState, 15 ); // Zlib | 136 | inflateInit2( pState, 15 ); // Zlib |
137 | else if( eFmt == Gzip ) | 137 | else if( eFmt == Gzip ) |
138 | inflateInit2( pState, 16+15 ); // GZip | 138 | inflateInit2( pState, 16+15 ); // GZip |
139 | else | 139 | else |
140 | throw Bu::ExceptionBase("Format mode for deflate read."); | 140 | throw Bu::ExceptionBase("Format mode for deflate read."); |
141 | pState->next_in = (Bytef *)pBuf; | 141 | pState->next_in = (Bytef *)pBuf; |
142 | pState->avail_in = 0; | 142 | pState->avail_in = 0; |
143 | } | 143 | } |
144 | if( bReading == false ) | 144 | if( bReading == false ) |
145 | throw ExceptionBase("This deflate filter is in writing mode, you can't read."); | 145 | throw ExceptionBase("This deflate filter is in writing mode, you can't read."); |
146 | 146 | ||
147 | int nRead = 0; | 147 | int nRead = 0; |
148 | int nReadTotal = pState->total_out; | 148 | int nReadTotal = pState->total_out; |
149 | pState->next_out = (Bytef *)pData; | 149 | pState->next_out = (Bytef *)pData; |
150 | pState->avail_out = nBytes; | 150 | pState->avail_out = nBytes; |
151 | for(;;) | 151 | for(;;) |
152 | { | 152 | { |
153 | int ret = inflate( pState, Z_NO_FLUSH ); | 153 | int ret = inflate( pState, Z_NO_FLUSH ); |
154 | nReadTotal += nRead-pState->avail_out; | 154 | nReadTotal += nRead-pState->avail_out; |
155 | 155 | ||
156 | if( ret == Z_STREAM_END ) | 156 | if( ret == Z_STREAM_END ) |
157 | { | 157 | { |
158 | bEos = true; | 158 | bEos = true; |
159 | if( pState->avail_in > 0 ) | 159 | if( pState->avail_in > 0 ) |
160 | { | 160 | { |
161 | if( rNext.isSeekable() ) | 161 | if( rNext.isSeekable() ) |
162 | { | 162 | { |
163 | rNext.seek( -pState->avail_in ); | 163 | rNext.seek( -pState->avail_in ); |
164 | } | 164 | } |
165 | } | 165 | } |
166 | return nBytes-pState->avail_out; | 166 | return nBytes-pState->avail_out; |
167 | } | 167 | } |
168 | if( ret != Z_BUF_ERROR ) | 168 | if( ret != Z_BUF_ERROR ) |
169 | zError( ret ); | 169 | zError( ret ); |
170 | 170 | ||
171 | if( pState->avail_out ) | 171 | if( pState->avail_out ) |
172 | { | 172 | { |
173 | if( pState->avail_in == 0 ) | 173 | if( pState->avail_in == 0 ) |
174 | { | 174 | { |
175 | nRead = rNext.read( pBuf, nBufSize ); | 175 | nRead = rNext.read( pBuf, nBufSize ); |
176 | if( nRead == 0 && rNext.isEos() ) | 176 | if( nRead == 0 && rNext.isEos() ) |
177 | { | 177 | { |
178 | throw Bu::ExceptionBase("Premature end of underlying " | 178 | throw Bu::ExceptionBase("Premature end of underlying " |
179 | "stream found reading deflate stream."); | 179 | "stream found reading deflate stream."); |
180 | } | 180 | } |
181 | pState->next_in = (Bytef *)pBuf; | 181 | pState->next_in = (Bytef *)pBuf; |
182 | pState->avail_in = nRead; | 182 | pState->avail_in = nRead; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | else | 185 | else |
186 | { | 186 | { |
187 | return nBytes-pState->avail_out; | 187 | return nBytes-pState->avail_out; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) | 193 | Bu::size Bu::Deflate::write( const void *pData, Bu::size nBytes ) |
194 | { | 194 | { |
195 | TRACE( pData, nBytes ); | 195 | TRACE( pData, nBytes ); |
196 | if( nBytes <= 0 ) | 196 | if( nBytes <= 0 ) |
197 | return 0; | 197 | return 0; |
198 | if( !pState->state ) | 198 | if( !pState->state ) |
199 | { | 199 | { |
200 | bReading = false; | 200 | bReading = false; |
201 | int iFmt = eFmt&Gzip; | 201 | int iFmt = eFmt&Gzip; |
202 | if( iFmt == Raw ) | 202 | if( iFmt == Raw ) |
203 | deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, | 203 | deflateInit2( pState, nCompression, Z_DEFLATED, -15, 9, |
204 | Z_DEFAULT_STRATEGY ); | 204 | Z_DEFAULT_STRATEGY ); |
205 | else if( iFmt == Zlib ) | 205 | else if( iFmt == Zlib ) |
206 | deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, | 206 | deflateInit2( pState, nCompression, Z_DEFLATED, 15, 9, |
207 | Z_DEFAULT_STRATEGY ); | 207 | Z_DEFAULT_STRATEGY ); |
208 | else if( iFmt == Gzip ) | 208 | else if( iFmt == Gzip ) |
209 | deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, | 209 | deflateInit2( pState, nCompression, Z_DEFLATED, 16+15, 9, |
210 | Z_DEFAULT_STRATEGY ); | 210 | Z_DEFAULT_STRATEGY ); |
211 | else | 211 | else |
212 | throw Bu::ExceptionBase("Invalid format for deflate."); | 212 | throw Bu::ExceptionBase("Invalid format for deflate."); |
213 | } | 213 | } |
214 | if( bReading == true ) | 214 | if( bReading == true ) |
215 | throw ExceptionBase("This deflate filter is in reading mode, you can't write."); | 215 | throw ExceptionBase("This deflate filter is in reading mode, you can't write."); |
216 | 216 | ||
217 | pState->next_in = (Bytef *)pData; | 217 | pState->next_in = (Bytef *)pData; |
218 | pState->avail_in = nBytes; | 218 | pState->avail_in = nBytes; |
219 | for(;;) | 219 | for(;;) |
220 | { | 220 | { |
221 | pState->avail_out = nBufSize; | 221 | pState->avail_out = nBufSize; |
222 | pState->next_out = (Bytef *)pBuf; | 222 | pState->next_out = (Bytef *)pBuf; |
223 | 223 | ||
224 | zError( deflate( pState, Z_NO_FLUSH ) ); | 224 | zError( deflate( pState, Z_NO_FLUSH ) ); |
225 | 225 | ||
226 | if( pState->avail_out < nBufSize ) | 226 | if( pState->avail_out < nBufSize ) |
227 | { | 227 | { |
228 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 228 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
229 | } | 229 | } |
230 | if( pState->avail_in == 0 ) | 230 | if( pState->avail_in == 0 ) |
231 | break; | 231 | break; |
232 | } | 232 | } |
233 | 233 | ||
234 | return nBytes; | 234 | return nBytes; |
235 | } | 235 | } |
236 | 236 | ||
237 | bool Bu::Deflate::isOpen() | 237 | bool Bu::Deflate::isOpen() |
238 | { | 238 | { |
239 | TRACE(); | 239 | TRACE(); |
240 | return (pState != NULL && pState->state != NULL); | 240 | return (pState != NULL && pState->state != NULL); |
241 | } | 241 | } |
242 | 242 | ||
243 | bool Bu::Deflate::isEos() | 243 | bool Bu::Deflate::isEos() |
244 | { | 244 | { |
245 | TRACE(); | 245 | TRACE(); |
246 | return bEos; | 246 | return bEos; |
247 | } | 247 | } |
248 | 248 | ||
249 | Bu::size Bu::Deflate::getCompressedSize() | 249 | Bu::size Bu::Deflate::getCompressedSize() |
250 | { | 250 | { |
251 | return sTotalOut; | 251 | return sTotalOut; |
252 | } | 252 | } |
253 | 253 | ||
diff --git a/src/stable/deflate.h b/src/stable/deflate.h index 114b173..2ccd53f 100644 --- a/src/stable/deflate.h +++ b/src/stable/deflate.h | |||
@@ -14,53 +14,53 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and | 18 | * Provides Deflate (LZ77) support via zlib. This provides zlib, raw, and |
19 | * gzip stream types. By default it will autodetect the input type and | 19 | * gzip stream types. By default it will autodetect the input type and |
20 | * encode into a raw deflate stream. | 20 | * encode into a raw deflate stream. |
21 | * | 21 | * |
22 | *@ingroup Streams | 22 | *@ingroup Streams |
23 | *@ingroup Compression | 23 | *@ingroup Compression |
24 | */ | 24 | */ |
25 | class Deflate : public Bu::Filter | 25 | class Deflate : public Bu::Filter |
26 | { | 26 | { |
27 | public: | 27 | public: |
28 | enum Format | 28 | enum Format |
29 | { | 29 | { |
30 | Raw = 0x01, | 30 | Raw = 0x01, |
31 | Zlib = 0x02, | 31 | Zlib = 0x02, |
32 | Gzip = 0x03, | 32 | Gzip = 0x03, |
33 | AutoDetect = 0x04, | 33 | AutoDetect = 0x04, |
34 | 34 | ||
35 | AutoRaw = 0x04|0x01, | 35 | AutoRaw = 0x04|0x01, |
36 | AutoZlib = 0x04|0x02, | 36 | AutoZlib = 0x04|0x02, |
37 | AutoGzip = 0x04|0x03 | 37 | AutoGzip = 0x04|0x03 |
38 | }; | 38 | }; |
39 | 39 | ||
40 | Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); | 40 | Deflate( Bu::Stream &rNext, int nCompression=-1, Format eFmt=AutoZlib ); |
41 | virtual ~Deflate(); | 41 | virtual ~Deflate(); |
42 | 42 | ||
43 | virtual void start(); | 43 | virtual void start(); |
44 | virtual Bu::size stop(); | 44 | virtual Bu::size stop(); |
45 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 45 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
46 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 46 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
47 | 47 | ||
48 | virtual bool isOpen(); | 48 | virtual bool isOpen(); |
49 | virtual bool isEos(); | 49 | virtual bool isEos(); |
50 | 50 | ||
51 | Bu::size getCompressedSize(); | 51 | Bu::size getCompressedSize(); |
52 | 52 | ||
53 | private: | 53 | private: |
54 | void zError( int code ); | 54 | void zError( int code ); |
55 | void *prState; | 55 | void *prState; |
56 | bool bReading; | 56 | bool bReading; |
57 | int nCompression; | 57 | int nCompression; |
58 | char *pBuf; | 58 | char *pBuf; |
59 | uint32_t nBufSize; | 59 | uint32_t nBufSize; |
60 | Bu::size sTotalOut; | 60 | Bu::size sTotalOut; |
61 | Format eFmt; | 61 | Format eFmt; |
62 | bool bEos; | 62 | bool bEos; |
63 | }; | 63 | }; |
64 | } | 64 | } |
65 | 65 | ||
66 | #endif | 66 | #endif |
diff --git a/src/stable/exceptionbase.cpp b/src/stable/exceptionbase.cpp index 87e7127..22f338f 100644 --- a/src/stable/exceptionbase.cpp +++ b/src/stable/exceptionbase.cpp | |||
@@ -11,83 +11,83 @@ | |||
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | 12 | ||
13 | Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : | 13 | Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : |
14 | nErrorCode( 0 ), | 14 | nErrorCode( 0 ), |
15 | sWhat( NULL ) | 15 | sWhat( NULL ) |
16 | { | 16 | { |
17 | va_list ap; | 17 | va_list ap; |
18 | 18 | ||
19 | va_start(ap, lpFormat); | 19 | va_start(ap, lpFormat); |
20 | setWhat( lpFormat, ap ); | 20 | setWhat( lpFormat, ap ); |
21 | va_end(ap); | 21 | va_end(ap); |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : | 24 | Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : |
25 | nErrorCode( nCode ), | 25 | nErrorCode( nCode ), |
26 | sWhat( NULL ) | 26 | sWhat( NULL ) |
27 | { | 27 | { |
28 | va_list ap; | 28 | va_list ap; |
29 | 29 | ||
30 | va_start(ap, lpFormat); | 30 | va_start(ap, lpFormat); |
31 | setWhat( lpFormat, ap ); | 31 | setWhat( lpFormat, ap ); |
32 | va_end(ap); | 32 | va_end(ap); |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : | 35 | Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : |
36 | nErrorCode( nCode ), | 36 | nErrorCode( nCode ), |
37 | sWhat( NULL ) | 37 | sWhat( NULL ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : | 41 | Bu::ExceptionBase::ExceptionBase( const ExceptionBase &e ) throw () : |
42 | std::exception( e ), | 42 | std::exception( e ), |
43 | nErrorCode( e.nErrorCode ), | 43 | nErrorCode( e.nErrorCode ), |
44 | sWhat( NULL ) | 44 | sWhat( NULL ) |
45 | { | 45 | { |
46 | setWhat( e.sWhat ); | 46 | setWhat( e.sWhat ); |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::ExceptionBase::~ExceptionBase() throw() | 49 | Bu::ExceptionBase::~ExceptionBase() throw() |
50 | { | 50 | { |
51 | delete[] sWhat; | 51 | delete[] sWhat; |
52 | sWhat = NULL; | 52 | sWhat = NULL; |
53 | } | 53 | } |
54 | 54 | ||
55 | void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) | 55 | void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) |
56 | { | 56 | { |
57 | if( sWhat ) delete[] sWhat; | 57 | if( sWhat ) delete[] sWhat; |
58 | int nSize; | 58 | int nSize; |
59 | 59 | ||
60 | va_list vargs2; | 60 | va_list vargs2; |
61 | va_copy( vargs2, vargs ); | 61 | va_copy( vargs2, vargs ); |
62 | nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); | 62 | nSize = vsnprintf( NULL, 0, lpFormat, vargs2 ); |
63 | va_end( vargs2 ); | 63 | va_end( vargs2 ); |
64 | sWhat = new char[nSize+1]; | 64 | sWhat = new char[nSize+1]; |
65 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); | 65 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); |
66 | } | 66 | } |
67 | 67 | ||
68 | void Bu::ExceptionBase::setWhat( const char *lpText ) | 68 | void Bu::ExceptionBase::setWhat( const char *lpText ) |
69 | { | 69 | { |
70 | if( sWhat ) delete[] sWhat; | 70 | if( sWhat ) delete[] sWhat; |
71 | int nSize; | 71 | int nSize; |
72 | 72 | ||
73 | nSize = strlen( lpText ); | 73 | nSize = strlen( lpText ); |
74 | sWhat = new char[nSize+1]; | 74 | sWhat = new char[nSize+1]; |
75 | strcpy( sWhat, lpText ); | 75 | strcpy( sWhat, lpText ); |
76 | } | 76 | } |
77 | 77 | ||
78 | const char *Bu::ExceptionBase::what() const throw() | 78 | const char *Bu::ExceptionBase::what() const throw() |
79 | { | 79 | { |
80 | return sWhat; | 80 | return sWhat; |
81 | } | 81 | } |
82 | 82 | ||
83 | int Bu::ExceptionBase::getErrorCode() | 83 | int Bu::ExceptionBase::getErrorCode() |
84 | { | 84 | { |
85 | return nErrorCode; | 85 | return nErrorCode; |
86 | } | 86 | } |
87 | 87 | ||
88 | Bu::UnsupportedException::UnsupportedException() throw() : | 88 | Bu::UnsupportedException::UnsupportedException() throw() : |
89 | ExceptionBase( 0 ) | 89 | ExceptionBase( 0 ) |
90 | { | 90 | { |
91 | setWhat("An unsupperted operation was attempted."); | 91 | setWhat("An unsupperted operation was attempted."); |
92 | } | 92 | } |
93 | 93 | ||
diff --git a/src/stable/exceptionbase.h b/src/stable/exceptionbase.h index 9e6c72d..8f651b7 100644 --- a/src/stable/exceptionbase.h +++ b/src/stable/exceptionbase.h | |||
@@ -18,173 +18,173 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | /** | 21 | /** |
22 | * A generalized Exception base class. This is nice for making general and | 22 | * A generalized Exception base class. This is nice for making general and |
23 | * flexible child classes that can create new error code classes. | 23 | * flexible child classes that can create new error code classes. |
24 | * | 24 | * |
25 | * In order to create your own exception class use these two lines. | 25 | * In order to create your own exception class use these two lines. |
26 | * | 26 | * |
27 | * in your header: subExceptionDecl( NewClassName ); | 27 | * in your header: subExceptionDecl( NewClassName ); |
28 | * | 28 | * |
29 | * in your source: subExcpetienDef( NewClassName ); | 29 | * in your source: subExcpetienDef( NewClassName ); |
30 | */ | 30 | */ |
31 | class ExceptionBase : public std::exception | 31 | class ExceptionBase : public std::exception |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | /** | 34 | /** |
35 | * Construct an exception with an error code of zero, but with a | 35 | * Construct an exception with an error code of zero, but with a |
36 | * description. The use of this is not reccomended most of the time, | 36 | * description. The use of this is not reccomended most of the time, |
37 | * it's generally best to include an error code with the exception so | 37 | * it's generally best to include an error code with the exception so |
38 | * your program can handle the exception in a better way. | 38 | * your program can handle the exception in a better way. |
39 | * @param sFormat The format of the text. See printf for more info. | 39 | * @param sFormat The format of the text. See printf for more info. |
40 | */ | 40 | */ |
41 | ExceptionBase( const char *sFormat, ... ) throw(); | 41 | ExceptionBase( const char *sFormat, ... ) throw(); |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * | 44 | * |
45 | * @param nCode | 45 | * @param nCode |
46 | * @param sFormat | 46 | * @param sFormat |
47 | */ | 47 | */ |
48 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); | 48 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * | 51 | * |
52 | * @param nCode | 52 | * @param nCode |
53 | * @return | 53 | * @return |
54 | */ | 54 | */ |
55 | ExceptionBase( int nCode=0 ) throw(); | 55 | ExceptionBase( int nCode=0 ) throw(); |
56 | 56 | ||
57 | ExceptionBase( const ExceptionBase &e ) throw (); | 57 | ExceptionBase( const ExceptionBase &e ) throw (); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * | 60 | * |
61 | * @return | 61 | * @return |
62 | */ | 62 | */ |
63 | virtual ~ExceptionBase() throw(); | 63 | virtual ~ExceptionBase() throw(); |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * | 66 | * |
67 | * @return | 67 | * @return |
68 | */ | 68 | */ |
69 | virtual const char *what() const throw(); | 69 | virtual const char *what() const throw(); |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * | 72 | * |
73 | * @return | 73 | * @return |
74 | */ | 74 | */ |
75 | int getErrorCode(); | 75 | int getErrorCode(); |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * | 78 | * |
79 | * @param lpFormat | 79 | * @param lpFormat |
80 | * @param vargs | 80 | * @param vargs |
81 | */ | 81 | */ |
82 | void setWhat( const char *lpFormat, va_list &vargs ); | 82 | void setWhat( const char *lpFormat, va_list &vargs ); |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * | 85 | * |
86 | * @param lpText | 86 | * @param lpText |
87 | */ | 87 | */ |
88 | void setWhat( const char *lpText ); | 88 | void setWhat( const char *lpText ); |
89 | 89 | ||
90 | private: | 90 | private: |
91 | int nErrorCode; /**< The code for the error that occured. */ | 91 | int nErrorCode; /**< The code for the error that occured. */ |
92 | char *sWhat; /**< The text string telling people what went wrong. */ | 92 | char *sWhat; /**< The text string telling people what went wrong. */ |
93 | }; | 93 | }; |
94 | } | 94 | } |
95 | 95 | ||
96 | #define subExceptionDecl( name ) \ | 96 | #define subExceptionDecl( name ) \ |
97 | class name : public Bu::ExceptionBase \ | 97 | class name : public Bu::ExceptionBase \ |
98 | { \ | 98 | { \ |
99 | public: \ | 99 | public: \ |
100 | name( const char *sFormat, ... ) throw (); \ | 100 | name( const char *sFormat, ... ) throw (); \ |
101 | name( int nCode, const char *sFormat, ... ) throw(); \ | 101 | name( int nCode, const char *sFormat, ... ) throw(); \ |
102 | name( int nCode=0 ) throw (); \ | 102 | name( int nCode=0 ) throw (); \ |
103 | name( const name &e ) throw (); \ | 103 | name( const name &e ) throw (); \ |
104 | }; | 104 | }; |
105 | 105 | ||
106 | #define subExceptionDeclChild( name, parent ) \ | 106 | #define subExceptionDeclChild( name, parent ) \ |
107 | class name : public parent \ | 107 | class name : public parent \ |
108 | { \ | 108 | { \ |
109 | public: \ | 109 | public: \ |
110 | name( const char *sFormat, ... ) throw (); \ | 110 | name( const char *sFormat, ... ) throw (); \ |
111 | name( int nCode, const char *sFormat, ... ) throw(); \ | 111 | name( int nCode, const char *sFormat, ... ) throw(); \ |
112 | name( int nCode=0 ) throw (); \ | 112 | name( int nCode=0 ) throw (); \ |
113 | name( const name &e ) throw (); \ | 113 | name( const name &e ) throw (); \ |
114 | }; | 114 | }; |
115 | 115 | ||
116 | #define subExceptionDeclBegin( name ) \ | 116 | #define subExceptionDeclBegin( name ) \ |
117 | class name : public Bu::ExceptionBase \ | 117 | class name : public Bu::ExceptionBase \ |
118 | { \ | 118 | { \ |
119 | public: \ | 119 | public: \ |
120 | name( const char *sFormat, ... ) throw (); \ | 120 | name( const char *sFormat, ... ) throw (); \ |
121 | name( int nCode, const char *sFormat, ... ) throw(); \ | 121 | name( int nCode, const char *sFormat, ... ) throw(); \ |
122 | name( int nCode=0 ) throw (); \ | 122 | name( int nCode=0 ) throw (); \ |
123 | name( const name &e ) throw (); | 123 | name( const name &e ) throw (); |
124 | 124 | ||
125 | #define subExceptionDeclEnd() \ | 125 | #define subExceptionDeclEnd() \ |
126 | }; | 126 | }; |
127 | 127 | ||
128 | #define subExceptionDef( name ) \ | 128 | #define subExceptionDef( name ) \ |
129 | name::name( const char *lpFormat, ... ) throw() : \ | 129 | name::name( const char *lpFormat, ... ) throw() : \ |
130 | ExceptionBase( 0 ) \ | 130 | ExceptionBase( 0 ) \ |
131 | { \ | 131 | { \ |
132 | va_list ap; \ | 132 | va_list ap; \ |
133 | va_start( ap, lpFormat ); \ | 133 | va_start( ap, lpFormat ); \ |
134 | setWhat( lpFormat, ap ); \ | 134 | setWhat( lpFormat, ap ); \ |
135 | va_end( ap ); \ | 135 | va_end( ap ); \ |
136 | } \ | 136 | } \ |
137 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | 137 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ |
138 | ExceptionBase( nCode ) \ | 138 | ExceptionBase( nCode ) \ |
139 | { \ | 139 | { \ |
140 | va_list ap; \ | 140 | va_list ap; \ |
141 | va_start( ap, lpFormat ); \ | 141 | va_start( ap, lpFormat ); \ |
142 | setWhat( lpFormat, ap ); \ | 142 | setWhat( lpFormat, ap ); \ |
143 | va_end( ap ); \ | 143 | va_end( ap ); \ |
144 | } \ | 144 | } \ |
145 | name::name( int nCode ) throw() : \ | 145 | name::name( int nCode ) throw() : \ |
146 | ExceptionBase( nCode ) \ | 146 | ExceptionBase( nCode ) \ |
147 | { \ | 147 | { \ |
148 | } \ | 148 | } \ |
149 | name::name( const name &e ) throw() : \ | 149 | name::name( const name &e ) throw() : \ |
150 | ExceptionBase( e ) \ | 150 | ExceptionBase( e ) \ |
151 | { \ | 151 | { \ |
152 | } | 152 | } |
153 | 153 | ||
154 | #define subExceptionDefChild( name, parent ) \ | 154 | #define subExceptionDefChild( name, parent ) \ |
155 | name::name( const char *lpFormat, ... ) throw() : \ | 155 | name::name( const char *lpFormat, ... ) throw() : \ |
156 | parent( 0 ) \ | 156 | parent( 0 ) \ |
157 | { \ | 157 | { \ |
158 | va_list ap; \ | 158 | va_list ap; \ |
159 | va_start( ap, lpFormat ); \ | 159 | va_start( ap, lpFormat ); \ |
160 | setWhat( lpFormat, ap ); \ | 160 | setWhat( lpFormat, ap ); \ |
161 | va_end( ap ); \ | 161 | va_end( ap ); \ |
162 | } \ | 162 | } \ |
163 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | 163 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ |
164 | parent( nCode ) \ | 164 | parent( nCode ) \ |
165 | { \ | 165 | { \ |
166 | va_list ap; \ | 166 | va_list ap; \ |
167 | va_start( ap, lpFormat ); \ | 167 | va_start( ap, lpFormat ); \ |
168 | setWhat( lpFormat, ap ); \ | 168 | setWhat( lpFormat, ap ); \ |
169 | va_end( ap ); \ | 169 | va_end( ap ); \ |
170 | } \ | 170 | } \ |
171 | name::name( int nCode ) throw() : \ | 171 | name::name( int nCode ) throw() : \ |
172 | parent( nCode ) \ | 172 | parent( nCode ) \ |
173 | { \ | 173 | { \ |
174 | } \ | 174 | } \ |
175 | name::name( const name &e ) throw() : \ | 175 | name::name( const name &e ) throw() : \ |
176 | ExceptionBase( e ) \ | 176 | ExceptionBase( e ) \ |
177 | { \ | 177 | { \ |
178 | } | 178 | } |
179 | 179 | ||
180 | namespace Bu | 180 | namespace Bu |
181 | { | 181 | { |
182 | // Exceptions that are so general they could be used anywhere go here. | 182 | // Exceptions that are so general they could be used anywhere go here. |
183 | class UnsupportedException : public Bu::ExceptionBase | 183 | class UnsupportedException : public Bu::ExceptionBase |
184 | { | 184 | { |
185 | public: | 185 | public: |
186 | UnsupportedException() throw (); | 186 | UnsupportedException() throw (); |
187 | }; | 187 | }; |
188 | } | 188 | } |
189 | 189 | ||
190 | #endif | 190 | #endif |
diff --git a/src/stable/extratypes.h b/src/stable/extratypes.h index 2961920..3549529 100644 --- a/src/stable/extratypes.h +++ b/src/stable/extratypes.h | |||
@@ -19,11 +19,11 @@ | |||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | #ifdef USE_64BIT_IO | 21 | #ifdef USE_64BIT_IO |
22 | typedef int64_t size; | 22 | typedef int64_t size; |
23 | typedef uint64_t usize; | 23 | typedef uint64_t usize; |
24 | #else | 24 | #else |
25 | typedef int32_t size; | 25 | typedef int32_t size; |
26 | typedef uint32_t usize; | 26 | typedef uint32_t usize; |
27 | #endif | 27 | #endif |
28 | }; | 28 | }; |
29 | 29 | ||
diff --git a/src/stable/file.cpp b/src/stable/file.cpp index 14e4f3c..7ae2484 100644 --- a/src/stable/file.cpp +++ b/src/stable/file.cpp | |||
@@ -19,298 +19,298 @@ | |||
19 | namespace Bu { subExceptionDef( FileException ) } | 19 | namespace Bu { subExceptionDef( FileException ) } |
20 | 20 | ||
21 | Bu::File::File( const Bu::String &sName, int iFlags ) : | 21 | Bu::File::File( const Bu::String &sName, int iFlags ) : |
22 | fd( -1 ), | 22 | fd( -1 ), |
23 | bEos( true ) | 23 | bEos( true ) |
24 | { | 24 | { |
25 | #ifdef USE_64BIT_IO | 25 | #ifdef USE_64BIT_IO |
26 | fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); | 26 | fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 ); |
27 | #else | 27 | #else |
28 | fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); | 28 | fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 ); |
29 | #endif | 29 | #endif |
30 | if( fd < 0 ) | 30 | if( fd < 0 ) |
31 | { | 31 | { |
32 | throw Bu::FileException( errno, "%s: %s", | 32 | throw Bu::FileException( errno, "%s: %s", |
33 | strerror(errno), sName.getStr() ); | 33 | strerror(errno), sName.getStr() ); |
34 | } | 34 | } |
35 | bEos = false; | 35 | bEos = false; |
36 | } | 36 | } |
37 | 37 | ||
38 | Bu::File::File( int fd ) : | 38 | Bu::File::File( int fd ) : |
39 | fd( fd ) | 39 | fd( fd ) |
40 | { | 40 | { |
41 | bEos = false; | 41 | bEos = false; |
42 | } | 42 | } |
43 | 43 | ||
44 | Bu::File::~File() | 44 | Bu::File::~File() |
45 | { | 45 | { |
46 | close(); | 46 | close(); |
47 | } | 47 | } |
48 | 48 | ||
49 | void Bu::File::close() | 49 | void Bu::File::close() |
50 | { | 50 | { |
51 | if( fd >= 0 ) | 51 | if( fd >= 0 ) |
52 | { | 52 | { |
53 | if( ::close( fd ) ) | 53 | if( ::close( fd ) ) |
54 | { | 54 | { |
55 | throw Bu::FileException( errno, "%s", | 55 | throw Bu::FileException( errno, "%s", |
56 | strerror(errno) ); | 56 | strerror(errno) ); |
57 | } | 57 | } |
58 | fd = -1; | 58 | fd = -1; |
59 | bEos = true; | 59 | bEos = true; |
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
63 | Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) | 63 | Bu::size Bu::File::read( void *pBuf, Bu::size nBytes ) |
64 | { | 64 | { |
65 | if( fd < 0 ) | 65 | if( fd < 0 ) |
66 | throw FileException("File not open."); | 66 | throw FileException("File not open."); |
67 | 67 | ||
68 | Bu::size iRead = ::read( fd, pBuf, nBytes ); | 68 | Bu::size iRead = ::read( fd, pBuf, nBytes ); |
69 | if( iRead == 0 ) | 69 | if( iRead == 0 ) |
70 | bEos = true; | 70 | bEos = true; |
71 | else if( iRead == -1 && errno == EAGAIN ) | 71 | else if( iRead == -1 && errno == EAGAIN ) |
72 | return 0; | 72 | return 0; |
73 | else if( iRead < 0 ) | 73 | else if( iRead < 0 ) |
74 | throw FileException( errno, "%s", strerror( errno ) ); | 74 | throw FileException( errno, "%s", strerror( errno ) ); |
75 | return iRead; | 75 | return iRead; |
76 | } | 76 | } |
77 | 77 | ||
78 | Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) | 78 | Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes ) |
79 | { | 79 | { |
80 | if( fd < 0 ) | 80 | if( fd < 0 ) |
81 | throw FileException("File not open."); | 81 | throw FileException("File not open."); |
82 | 82 | ||
83 | Bu::size iWrote = ::write( fd, pBuf, nBytes ); | 83 | Bu::size iWrote = ::write( fd, pBuf, nBytes ); |
84 | if( iWrote < 0 ) | 84 | if( iWrote < 0 ) |
85 | throw FileException( errno, "%s", strerror( errno ) ); | 85 | throw FileException( errno, "%s", strerror( errno ) ); |
86 | return iWrote; | 86 | return iWrote; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::size Bu::File::tell() | 89 | Bu::size Bu::File::tell() |
90 | { | 90 | { |
91 | if( fd < 0 ) | 91 | if( fd < 0 ) |
92 | throw FileException("File not open."); | 92 | throw FileException("File not open."); |
93 | 93 | ||
94 | #ifdef USE_64BIT_IO | 94 | #ifdef USE_64BIT_IO |
95 | return lseek64( fd, 0, SEEK_CUR ); | 95 | return lseek64( fd, 0, SEEK_CUR ); |
96 | #else | 96 | #else |
97 | return lseek( fd, 0, SEEK_CUR ); | 97 | return lseek( fd, 0, SEEK_CUR ); |
98 | #endif | 98 | #endif |
99 | } | 99 | } |
100 | 100 | ||
101 | void Bu::File::seek( Bu::size offset ) | 101 | void Bu::File::seek( Bu::size offset ) |
102 | { | 102 | { |
103 | if( fd < 0 ) | 103 | if( fd < 0 ) |
104 | throw FileException("File not open."); | 104 | throw FileException("File not open."); |
105 | 105 | ||
106 | #ifdef USE_64BIT_IO | 106 | #ifdef USE_64BIT_IO |
107 | lseek64( fd, offset, SEEK_CUR ); | 107 | lseek64( fd, offset, SEEK_CUR ); |
108 | #else | 108 | #else |
109 | lseek( fd, offset, SEEK_CUR ); | 109 | lseek( fd, offset, SEEK_CUR ); |
110 | #endif | 110 | #endif |
111 | bEos = false; | 111 | bEos = false; |
112 | } | 112 | } |
113 | 113 | ||
114 | void Bu::File::setPos( Bu::size pos ) | 114 | void Bu::File::setPos( Bu::size pos ) |
115 | { | 115 | { |
116 | if( fd < 0 ) | 116 | if( fd < 0 ) |
117 | throw FileException("File not open."); | 117 | throw FileException("File not open."); |
118 | 118 | ||
119 | #ifdef USE_64BIT_IO | 119 | #ifdef USE_64BIT_IO |
120 | lseek64( fd, pos, SEEK_SET ); | 120 | lseek64( fd, pos, SEEK_SET ); |
121 | #else | 121 | #else |
122 | lseek( fd, pos, SEEK_SET ); | 122 | lseek( fd, pos, SEEK_SET ); |
123 | #endif | 123 | #endif |
124 | bEos = false; | 124 | bEos = false; |
125 | } | 125 | } |
126 | 126 | ||
127 | void Bu::File::setPosEnd( Bu::size pos ) | 127 | void Bu::File::setPosEnd( Bu::size pos ) |
128 | { | 128 | { |
129 | if( fd < 0 ) | 129 | if( fd < 0 ) |
130 | throw FileException("File not open."); | 130 | throw FileException("File not open."); |
131 | 131 | ||
132 | lseek64( fd, pos, SEEK_END ); | 132 | lseek64( fd, pos, SEEK_END ); |
133 | bEos = false; | 133 | bEos = false; |
134 | } | 134 | } |
135 | 135 | ||
136 | bool Bu::File::isEos() | 136 | bool Bu::File::isEos() |
137 | { | 137 | { |
138 | return bEos; | 138 | return bEos; |
139 | } | 139 | } |
140 | 140 | ||
141 | bool Bu::File::canRead() | 141 | bool Bu::File::canRead() |
142 | { | 142 | { |
143 | #ifdef WIN32 | 143 | #ifdef WIN32 |
144 | return true; | 144 | return true; |
145 | #else | 145 | #else |
146 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; | 146 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; |
147 | if( iMode == O_RDONLY || iMode == O_RDWR ) | 147 | if( iMode == O_RDONLY || iMode == O_RDWR ) |
148 | return true; | 148 | return true; |
149 | return false; | 149 | return false; |
150 | #endif | 150 | #endif |
151 | } | 151 | } |
152 | 152 | ||
153 | bool Bu::File::canWrite() | 153 | bool Bu::File::canWrite() |
154 | { | 154 | { |
155 | #ifdef WIN32 | 155 | #ifdef WIN32 |
156 | return true; | 156 | return true; |
157 | #else | 157 | #else |
158 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; | 158 | int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE; |
159 | if( iMode == O_WRONLY || iMode == O_RDWR ) | 159 | if( iMode == O_WRONLY || iMode == O_RDWR ) |
160 | return true; | 160 | return true; |
161 | return false; | 161 | return false; |
162 | #endif | 162 | #endif |
163 | } | 163 | } |
164 | 164 | ||
165 | bool Bu::File::isReadable() | 165 | bool Bu::File::isReadable() |
166 | { | 166 | { |
167 | return true; | 167 | return true; |
168 | } | 168 | } |
169 | 169 | ||
170 | bool Bu::File::isWritable() | 170 | bool Bu::File::isWritable() |
171 | { | 171 | { |
172 | return true; | 172 | return true; |
173 | } | 173 | } |
174 | 174 | ||
175 | bool Bu::File::isSeekable() | 175 | bool Bu::File::isSeekable() |
176 | { | 176 | { |
177 | return true; | 177 | return true; |
178 | } | 178 | } |
179 | 179 | ||
180 | bool Bu::File::isBlocking() | 180 | bool Bu::File::isBlocking() |
181 | { | 181 | { |
182 | return true; | 182 | return true; |
183 | } | 183 | } |
184 | 184 | ||
185 | void Bu::File::setBlocking( bool bBlocking ) | 185 | void Bu::File::setBlocking( bool bBlocking ) |
186 | { | 186 | { |
187 | #ifdef WIN32 | 187 | #ifdef WIN32 |
188 | fprintf(stderr, "STUB: Bu::File::setBlocking\n"); | 188 | fprintf(stderr, "STUB: Bu::File::setBlocking\n"); |
189 | #else | 189 | #else |
190 | if( bBlocking ) | 190 | if( bBlocking ) |
191 | fcntl( | 191 | fcntl( |
192 | fd, | 192 | fd, |
193 | F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) | 193 | F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) |
194 | ); | 194 | ); |
195 | else | 195 | else |
196 | fcntl( | 196 | fcntl( |
197 | fd, | 197 | fd, |
198 | F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK | 198 | F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK |
199 | ); | 199 | ); |
200 | #endif | 200 | #endif |
201 | } | 201 | } |
202 | 202 | ||
203 | Bu::File Bu::File::tempFile( Bu::String &sName ) | 203 | Bu::File Bu::File::tempFile( Bu::String &sName ) |
204 | { | 204 | { |
205 | int iXes; | 205 | int iXes; |
206 | for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) | 206 | for( iXes = sName.getSize()-1; iXes >= 0; iXes-- ) |
207 | { | 207 | { |
208 | if( sName[iXes] != 'X' ) | 208 | if( sName[iXes] != 'X' ) |
209 | break; | 209 | break; |
210 | } | 210 | } |
211 | iXes++; | 211 | iXes++; |
212 | if( iXes == sName.getSize() ) | 212 | if( iXes == sName.getSize() ) |
213 | throw Bu::ExceptionBase("Invalid temporary filename template."); | 213 | throw Bu::ExceptionBase("Invalid temporary filename template."); |
214 | for( int iter = 0; iter < 1000; iter++ ) | 214 | for( int iter = 0; iter < 1000; iter++ ) |
215 | { | 215 | { |
216 | for( int j = iXes; j < sName.getSize(); j++ ) | 216 | for( int j = iXes; j < sName.getSize(); j++ ) |
217 | { | 217 | { |
218 | uint32_t iX = Bu::Random::rand(); | 218 | uint32_t iX = Bu::Random::rand(); |
219 | sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); | 219 | sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0)); |
220 | } | 220 | } |
221 | 221 | ||
222 | try | 222 | try |
223 | { | 223 | { |
224 | return Bu::File( sName, Bu::File::Read|Bu::File::Write | 224 | return Bu::File( sName, Bu::File::Read|Bu::File::Write |
225 | |Bu::File::Create|Bu::File::Exclusive ); | 225 | |Bu::File::Create|Bu::File::Exclusive ); |
226 | } catch(...) { } | 226 | } catch(...) { } |
227 | } | 227 | } |
228 | throw Bu::FileException("Failed to create unique temporary file after 1000" | 228 | throw Bu::FileException("Failed to create unique temporary file after 1000" |
229 | " iterations."); | 229 | " iterations."); |
230 | } | 230 | } |
231 | 231 | ||
232 | void Bu::File::setSize( Bu::size iSize ) | 232 | void Bu::File::setSize( Bu::size iSize ) |
233 | { | 233 | { |
234 | #ifdef WIN32 | 234 | #ifdef WIN32 |
235 | chsize( fd, iSize ); | 235 | chsize( fd, iSize ); |
236 | #else | 236 | #else |
237 | ftruncate( fd, iSize ); | 237 | ftruncate( fd, iSize ); |
238 | #endif | 238 | #endif |
239 | } | 239 | } |
240 | 240 | ||
241 | Bu::size Bu::File::getSize() const | 241 | Bu::size Bu::File::getSize() const |
242 | { | 242 | { |
243 | struct stat st; | 243 | struct stat st; |
244 | fstat( fd, &st ); | 244 | fstat( fd, &st ); |
245 | return st.st_size; | 245 | return st.st_size; |
246 | } | 246 | } |
247 | 247 | ||
248 | Bu::size Bu::File::getBlockSize() const | 248 | Bu::size Bu::File::getBlockSize() const |
249 | { | 249 | { |
250 | #ifdef WIN32 | 250 | #ifdef WIN32 |
251 | return 4096; | 251 | return 4096; |
252 | #else | 252 | #else |
253 | struct stat st; | 253 | struct stat st; |
254 | fstat( fd, &st ); | 254 | fstat( fd, &st ); |
255 | return st.st_blksize; | 255 | return st.st_blksize; |
256 | #endif | 256 | #endif |
257 | } | 257 | } |
258 | 258 | ||
259 | Bu::String Bu::File::getLocation() const | 259 | Bu::String Bu::File::getLocation() const |
260 | { | 260 | { |
261 | return "to be implemented"; | 261 | return "to be implemented"; |
262 | } | 262 | } |
263 | 263 | ||
264 | #ifndef WIN32 | 264 | #ifndef WIN32 |
265 | void Bu::File::chmod( mode_t t ) | 265 | void Bu::File::chmod( mode_t t ) |
266 | { | 266 | { |
267 | fchmod( fd, t ); | 267 | fchmod( fd, t ); |
268 | } | 268 | } |
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | void Bu::File::flush() | 271 | void Bu::File::flush() |
272 | { | 272 | { |
273 | // There is no flushing with direct I/O... | 273 | // There is no flushing with direct I/O... |
274 | //fflush( fh ); | 274 | //fflush( fh ); |
275 | } | 275 | } |
276 | 276 | ||
277 | bool Bu::File::isOpen() | 277 | bool Bu::File::isOpen() |
278 | { | 278 | { |
279 | return (fd > -1); | 279 | return (fd > -1); |
280 | } | 280 | } |
281 | 281 | ||
282 | int Bu::File::getPosixFlags( int iFlags ) | 282 | int Bu::File::getPosixFlags( int iFlags ) |
283 | { | 283 | { |
284 | int iRet = 0; | 284 | int iRet = 0; |
285 | switch( (iFlags&ReadWrite) ) | 285 | switch( (iFlags&ReadWrite) ) |
286 | { | 286 | { |
287 | // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so | 287 | // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so |
288 | // lets be proper and use the right value in the right place. | 288 | // lets be proper and use the right value in the right place. |
289 | case Read: iRet = O_RDONLY; break; | 289 | case Read: iRet = O_RDONLY; break; |
290 | case Write: iRet = O_WRONLY; break; | 290 | case Write: iRet = O_WRONLY; break; |
291 | case ReadWrite: iRet = O_RDWR; break; | 291 | case ReadWrite: iRet = O_RDWR; break; |
292 | default: | 292 | default: |
293 | throw FileException( | 293 | throw FileException( |
294 | "You must specify Read, Write, or both when opening a file."); | 294 | "You must specify Read, Write, or both when opening a file."); |
295 | } | 295 | } |
296 | 296 | ||
297 | if( (iFlags&Create) ) | 297 | if( (iFlags&Create) ) |
298 | iRet |= O_CREAT; | 298 | iRet |= O_CREAT; |
299 | if( (iFlags&Append) ) | 299 | if( (iFlags&Append) ) |
300 | iRet |= O_APPEND; | 300 | iRet |= O_APPEND; |
301 | if( (iFlags&Truncate) ) | 301 | if( (iFlags&Truncate) ) |
302 | iRet |= O_TRUNC; | 302 | iRet |= O_TRUNC; |
303 | #ifndef WIN32 | 303 | #ifndef WIN32 |
304 | if( (iFlags&NonBlock) ) | 304 | if( (iFlags&NonBlock) ) |
305 | iRet |= O_NONBLOCK; | 305 | iRet |= O_NONBLOCK; |
306 | #endif | 306 | #endif |
307 | if( (iFlags&Exclusive) == Exclusive ) | 307 | if( (iFlags&Exclusive) == Exclusive ) |
308 | iRet |= O_EXCL; | 308 | iRet |= O_EXCL; |
309 | 309 | ||
310 | #ifdef O_BINARY | 310 | #ifdef O_BINARY |
311 | iRet |= O_BINARY; | 311 | iRet |= O_BINARY; |
312 | #endif | 312 | #endif |
313 | 313 | ||
314 | return iRet; | 314 | return iRet; |
315 | } | 315 | } |
316 | 316 | ||
diff --git a/src/stable/file.h b/src/stable/file.h index eaf2974..2ecb27e 100644 --- a/src/stable/file.h +++ b/src/stable/file.h | |||
@@ -17,90 +17,90 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( FileException ); | 20 | subExceptionDecl( FileException ); |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * A file stream. | 23 | * A file stream. |
24 | *@ingroup Streams | 24 | *@ingroup Streams |
25 | */ | 25 | */ |
26 | class File : public Bu::Stream | 26 | class File : public Bu::Stream |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | File( const Bu::String &sName, int iFlags ); | 29 | File( const Bu::String &sName, int iFlags ); |
30 | File( int fd ); | 30 | File( int fd ); |
31 | virtual ~File(); | 31 | virtual ~File(); |
32 | 32 | ||
33 | virtual void close(); | 33 | virtual void close(); |
34 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 34 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
35 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 35 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
36 | using Stream::write; | 36 | using Stream::write; |
37 | 37 | ||
38 | virtual Bu::size tell(); | 38 | virtual Bu::size tell(); |
39 | virtual void seek( Bu::size offset ); | 39 | virtual void seek( Bu::size offset ); |
40 | virtual void setPos( Bu::size pos ); | 40 | virtual void setPos( Bu::size pos ); |
41 | virtual void setPosEnd( Bu::size pos ); | 41 | virtual void setPosEnd( Bu::size pos ); |
42 | virtual bool isEos(); | 42 | virtual bool isEos(); |
43 | virtual bool isOpen(); | 43 | virtual bool isOpen(); |
44 | 44 | ||
45 | virtual void flush(); | 45 | virtual void flush(); |
46 | 46 | ||
47 | virtual bool canRead(); | 47 | virtual bool canRead(); |
48 | virtual bool canWrite(); | 48 | virtual bool canWrite(); |
49 | 49 | ||
50 | virtual bool isReadable(); | 50 | virtual bool isReadable(); |
51 | virtual bool isWritable(); | 51 | virtual bool isWritable(); |
52 | virtual bool isSeekable(); | 52 | virtual bool isSeekable(); |
53 | 53 | ||
54 | virtual bool isBlocking(); | 54 | virtual bool isBlocking(); |
55 | virtual void setBlocking( bool bBlocking=true ); | 55 | virtual void setBlocking( bool bBlocking=true ); |
56 | 56 | ||
57 | enum { | 57 | enum { |
58 | // Flags | 58 | // Flags |
59 | Read = 0x01, ///< Open file for reading | 59 | Read = 0x01, ///< Open file for reading |
60 | Write = 0x02, ///< Open file for writing | 60 | Write = 0x02, ///< Open file for writing |
61 | Create = 0x04, ///< Create file if it doesn't exist | 61 | Create = 0x04, ///< Create file if it doesn't exist |
62 | Truncate = 0x08, ///< Truncate file if it does exist | 62 | Truncate = 0x08, ///< Truncate file if it does exist |
63 | Append = 0x10, ///< Always append on every write | 63 | Append = 0x10, ///< Always append on every write |
64 | NonBlock = 0x20, ///< Open file in non-blocking mode | 64 | NonBlock = 0x20, ///< Open file in non-blocking mode |
65 | Exclusive = 0x44, ///< Create file, if it exists then fail | 65 | Exclusive = 0x44, ///< Create file, if it exists then fail |
66 | 66 | ||
67 | // Helpful mixes | 67 | // Helpful mixes |
68 | ReadWrite = 0x03, ///< Open for reading and writing | 68 | ReadWrite = 0x03, ///< Open for reading and writing |
69 | WriteNew = 0x0E ///< Create a file (or truncate) for writing. | 69 | WriteNew = 0x0E ///< Create a file (or truncate) for writing. |
70 | /// Same as Write|Create|Truncate | 70 | /// Same as Write|Create|Truncate |
71 | }; | 71 | }; |
72 | 72 | ||
73 | virtual void setSize( Bu::size iSize ); | 73 | virtual void setSize( Bu::size iSize ); |
74 | 74 | ||
75 | virtual size getSize() const; | 75 | virtual size getSize() const; |
76 | virtual size getBlockSize() const; | 76 | virtual size getBlockSize() const; |
77 | virtual Bu::String getLocation() const; | 77 | virtual Bu::String getLocation() const; |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * Create a temp file and return its handle. The file is opened | 80 | * Create a temp file and return its handle. The file is opened |
81 | * Read/Write. | 81 | * Read/Write. |
82 | *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" | 82 | *@param sName (Bu::String) Give in the form: "/tmp/tmpfileXXXXXXXX" |
83 | * It will alter your (sName) setting the 'X's to random | 83 | * It will alter your (sName) setting the 'X's to random |
84 | * characters. | 84 | * characters. |
85 | *@returns (Bu::File) A file object representing your temp file. | 85 | *@returns (Bu::File) A file object representing your temp file. |
86 | */ | 86 | */ |
87 | static Bu::File tempFile( Bu::String &sName ); | 87 | static Bu::File tempFile( Bu::String &sName ); |
88 | 88 | ||
89 | #ifndef WIN32 | 89 | #ifndef WIN32 |
90 | /** | 90 | /** |
91 | * Change the file access permissions. | 91 | * Change the file access permissions. |
92 | *@param t (mode_t) The new file access permissions. | 92 | *@param t (mode_t) The new file access permissions. |
93 | */ | 93 | */ |
94 | void chmod( mode_t t ); | 94 | void chmod( mode_t t ); |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | private: | 97 | private: |
98 | int getPosixFlags( int iFlags ); | 98 | int getPosixFlags( int iFlags ); |
99 | 99 | ||
100 | private: | 100 | private: |
101 | int fd; | 101 | int fd; |
102 | bool bEos; | 102 | bool bEos; |
103 | }; | 103 | }; |
104 | } | 104 | } |
105 | 105 | ||
106 | #endif | 106 | #endif |
diff --git a/src/stable/filter.cpp b/src/stable/filter.cpp index 9c1d66f..e7929e7 100644 --- a/src/stable/filter.cpp +++ b/src/stable/filter.cpp | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "bu/filter.h" | 8 | #include "bu/filter.h" |
9 | 9 | ||
10 | Bu::Filter::Filter( Bu::Stream &rNext ) : | 10 | Bu::Filter::Filter( Bu::Stream &rNext ) : |
11 | rNext( rNext ) | 11 | rNext( rNext ) |
12 | { | 12 | { |
13 | } | 13 | } |
14 | 14 | ||
@@ -18,73 +18,73 @@ Bu::Filter::~Filter() | |||
18 | 18 | ||
19 | void Bu::Filter::close() | 19 | void Bu::Filter::close() |
20 | { | 20 | { |
21 | stop(); | 21 | stop(); |
22 | rNext.close(); | 22 | rNext.close(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::size Bu::Filter::tell() | 25 | Bu::size Bu::Filter::tell() |
26 | { | 26 | { |
27 | return rNext.tell(); | 27 | return rNext.tell(); |
28 | } | 28 | } |
29 | 29 | ||
30 | void Bu::Filter::seek( Bu::size offset ) | 30 | void Bu::Filter::seek( Bu::size offset ) |
31 | { | 31 | { |
32 | rNext.seek( offset ); | 32 | rNext.seek( offset ); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Filter::setPos( Bu::size pos ) | 35 | void Bu::Filter::setPos( Bu::size pos ) |
36 | { | 36 | { |
37 | rNext.setPos( pos ); | 37 | rNext.setPos( pos ); |
38 | } | 38 | } |
39 | 39 | ||
40 | void Bu::Filter::setPosEnd( Bu::size pos ) | 40 | void Bu::Filter::setPosEnd( Bu::size pos ) |
41 | { | 41 | { |
42 | rNext.setPosEnd( pos ); | 42 | rNext.setPosEnd( pos ); |
43 | } | 43 | } |
44 | 44 | ||
45 | bool Bu::Filter::isEos() | 45 | bool Bu::Filter::isEos() |
46 | { | 46 | { |
47 | return rNext.isEos(); | 47 | return rNext.isEos(); |
48 | } | 48 | } |
49 | 49 | ||
50 | bool Bu::Filter::isOpen() | 50 | bool Bu::Filter::isOpen() |
51 | { | 51 | { |
52 | return rNext.isOpen(); | 52 | return rNext.isOpen(); |
53 | } | 53 | } |
54 | 54 | ||
55 | bool Bu::Filter::canRead() | 55 | bool Bu::Filter::canRead() |
56 | { | 56 | { |
57 | return rNext.canRead(); | 57 | return rNext.canRead(); |
58 | } | 58 | } |
59 | 59 | ||
60 | bool Bu::Filter::canWrite() | 60 | bool Bu::Filter::canWrite() |
61 | { | 61 | { |
62 | return rNext.canWrite(); | 62 | return rNext.canWrite(); |
63 | } | 63 | } |
64 | 64 | ||
65 | bool Bu::Filter::isReadable() | 65 | bool Bu::Filter::isReadable() |
66 | { | 66 | { |
67 | return rNext.isReadable(); | 67 | return rNext.isReadable(); |
68 | } | 68 | } |
69 | 69 | ||
70 | bool Bu::Filter::isWritable() | 70 | bool Bu::Filter::isWritable() |
71 | { | 71 | { |
72 | return rNext.isWritable(); | 72 | return rNext.isWritable(); |
73 | } | 73 | } |
74 | 74 | ||
75 | bool Bu::Filter::isSeekable() | 75 | bool Bu::Filter::isSeekable() |
76 | { | 76 | { |
77 | return rNext.isSeekable(); | 77 | return rNext.isSeekable(); |
78 | } | 78 | } |
79 | 79 | ||
80 | bool Bu::Filter::isBlocking() | 80 | bool Bu::Filter::isBlocking() |
81 | { | 81 | { |
82 | return rNext.isBlocking(); | 82 | return rNext.isBlocking(); |
83 | } | 83 | } |
84 | 84 | ||
85 | void Bu::Filter::setBlocking( bool bBlocking ) | 85 | void Bu::Filter::setBlocking( bool bBlocking ) |
86 | { | 86 | { |
87 | rNext.setBlocking( bBlocking ); | 87 | rNext.setBlocking( bBlocking ); |
88 | } | 88 | } |
89 | 89 | ||
90 | void Bu::Filter::setSize( Bu::size ) | 90 | void Bu::Filter::setSize( Bu::size ) |
@@ -93,21 +93,21 @@ void Bu::Filter::setSize( Bu::size ) | |||
93 | 93 | ||
94 | void Bu::Filter::flush() | 94 | void Bu::Filter::flush() |
95 | { | 95 | { |
96 | rNext.flush(); | 96 | rNext.flush(); |
97 | } | 97 | } |
98 | 98 | ||
99 | Bu::size Bu::Filter::getSize() const | 99 | Bu::size Bu::Filter::getSize() const |
100 | { | 100 | { |
101 | return rNext.getSize(); | 101 | return rNext.getSize(); |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::size Bu::Filter::getBlockSize() const | 104 | Bu::size Bu::Filter::getBlockSize() const |
105 | { | 105 | { |
106 | return rNext.getBlockSize(); | 106 | return rNext.getBlockSize(); |
107 | } | 107 | } |
108 | 108 | ||
109 | Bu::String Bu::Filter::getLocation() const | 109 | Bu::String Bu::Filter::getLocation() const |
110 | { | 110 | { |
111 | return rNext.getLocation(); | 111 | return rNext.getLocation(); |
112 | } | 112 | } |
113 | 113 | ||
diff --git a/src/stable/filter.h b/src/stable/filter.h index 3e1c7d8..49a6664 100644 --- a/src/stable/filter.h +++ b/src/stable/filter.h | |||
@@ -14,70 +14,70 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Data filter base class. Each data filter should contain a read and write | 18 | * Data filter base class. Each data filter should contain a read and write |
19 | * section. Effectively, the write applies the filter, the read un-applies | 19 | * section. Effectively, the write applies the filter, the read un-applies |
20 | * the filter, if possible. For example, BZip2 is a filter that compresses | 20 | * the filter, if possible. For example, BZip2 is a filter that compresses |
21 | * on write and decompresses on read. All bi-directional filters should | 21 | * on write and decompresses on read. All bi-directional filters should |
22 | * follow: x == read( write( x ) ) (byte-for-byte comparison) | 22 | * follow: x == read( write( x ) ) (byte-for-byte comparison) |
23 | * | 23 | * |
24 | * Also, all returned buffers should be owned by the filter, and deleted | 24 | * Also, all returned buffers should be owned by the filter, and deleted |
25 | * when the filter is deleted. This means that the output of a read or | 25 | * when the filter is deleted. This means that the output of a read or |
26 | * write operation must be used before the next call to read or write or the | 26 | * write operation must be used before the next call to read or write or the |
27 | * data will be destroyed. Also, the internal buffer may be changed or | 27 | * data will be destroyed. Also, the internal buffer may be changed or |
28 | * recreated between calls, so always get a new pointer from a call to | 28 | * recreated between calls, so always get a new pointer from a call to |
29 | * read or write. | 29 | * read or write. |
30 | * | 30 | * |
31 | * The close function can also return data, so make sure to check for it, | 31 | * The close function can also return data, so make sure to check for it, |
32 | * many filters such as compression filters will buffer data until they have | 32 | * many filters such as compression filters will buffer data until they have |
33 | * enough to create a compression block, in these cases the leftover data | 33 | * enough to create a compression block, in these cases the leftover data |
34 | * will be returned by close. | 34 | * will be returned by close. |
35 | *@ingroup Streams | 35 | *@ingroup Streams |
36 | */ | 36 | */ |
37 | class Filter : public Bu::Stream | 37 | class Filter : public Bu::Stream |
38 | { | 38 | { |
39 | public: | 39 | public: |
40 | Filter( Bu::Stream &rNext ); | 40 | Filter( Bu::Stream &rNext ); |
41 | virtual ~Filter(); | 41 | virtual ~Filter(); |
42 | 42 | ||
43 | virtual void start()=0; | 43 | virtual void start()=0; |
44 | virtual Bu::size stop()=0; | 44 | virtual Bu::size stop()=0; |
45 | virtual void close(); | 45 | virtual void close(); |
46 | virtual Bu::size tell(); | 46 | virtual Bu::size tell(); |
47 | virtual void seek( Bu::size offset ); | 47 | virtual void seek( Bu::size offset ); |
48 | virtual void setPos( Bu::size pos ); | 48 | virtual void setPos( Bu::size pos ); |
49 | virtual void setPosEnd( Bu::size pos ); | 49 | virtual void setPosEnd( Bu::size pos ); |
50 | virtual bool isEos(); | 50 | virtual bool isEos(); |
51 | virtual bool isOpen(); | 51 | virtual bool isOpen(); |
52 | 52 | ||
53 | virtual void flush(); | 53 | virtual void flush(); |
54 | 54 | ||
55 | virtual bool canRead(); | 55 | virtual bool canRead(); |
56 | virtual bool canWrite(); | 56 | virtual bool canWrite(); |
57 | 57 | ||
58 | virtual bool isReadable(); | 58 | virtual bool isReadable(); |
59 | virtual bool isWritable(); | 59 | virtual bool isWritable(); |
60 | virtual bool isSeekable(); | 60 | virtual bool isSeekable(); |
61 | 61 | ||
62 | virtual bool isBlocking(); | 62 | virtual bool isBlocking(); |
63 | virtual void setBlocking( bool bBlocking=true ); | 63 | virtual void setBlocking( bool bBlocking=true ); |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Most filters won't re-implement this, it doesn't make a lot of sense | 66 | * Most filters won't re-implement this, it doesn't make a lot of sense |
67 | * for filters, in general. | 67 | * for filters, in general. |
68 | */ | 68 | */ |
69 | virtual void setSize( Bu::size iSize ); | 69 | virtual void setSize( Bu::size iSize ); |
70 | 70 | ||
71 | virtual size getSize() const; | 71 | virtual size getSize() const; |
72 | virtual size getBlockSize() const; | 72 | virtual size getBlockSize() const; |
73 | virtual Bu::String getLocation() const; | 73 | virtual Bu::String getLocation() const; |
74 | 74 | ||
75 | protected: | 75 | protected: |
76 | Bu::Stream &rNext; | 76 | Bu::Stream &rNext; |
77 | 77 | ||
78 | private: | 78 | private: |
79 | 79 | ||
80 | }; | 80 | }; |
81 | } | 81 | } |
82 | 82 | ||
83 | #endif | 83 | #endif |
diff --git a/src/stable/fmt.h b/src/stable/fmt.h index bcc5240..9ecaf80 100644 --- a/src/stable/fmt.h +++ b/src/stable/fmt.h | |||
@@ -3,92 +3,92 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | typedef struct Fmt | 6 | typedef struct Fmt |
7 | { | 7 | { |
8 | enum Alignment | 8 | enum Alignment |
9 | { | 9 | { |
10 | Left = 0, | 10 | Left = 0, |
11 | Center = 1, | 11 | Center = 1, |
12 | Right = 2 | 12 | Right = 2 |
13 | }; | 13 | }; |
14 | Fmt() : | 14 | Fmt() : |
15 | uMinWidth( 0 ), | 15 | uMinWidth( 0 ), |
16 | cFillChar(' '), | 16 | cFillChar(' '), |
17 | uRadix( 10 ), | 17 | uRadix( 10 ), |
18 | uAlign( Right ), | 18 | uAlign( Right ), |
19 | bPlus( false ), | 19 | bPlus( false ), |
20 | bCaps( false ), | 20 | bCaps( false ), |
21 | bTokenize( true ) | 21 | bTokenize( true ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Fmt( unsigned int uMinWidth, unsigned int uRadix=10, | 25 | Fmt( unsigned int uMinWidth, unsigned int uRadix=10, |
26 | Alignment a=Right, bool bPlus=false, bool bCaps=true, | 26 | Alignment a=Right, bool bPlus=false, bool bCaps=true, |
27 | char cFill=' ') : | 27 | char cFill=' ') : |
28 | uMinWidth( uMinWidth ), | 28 | uMinWidth( uMinWidth ), |
29 | cFillChar(cFill), | 29 | cFillChar(cFill), |
30 | uRadix( uRadix ), | 30 | uRadix( uRadix ), |
31 | uAlign( a ), | 31 | uAlign( a ), |
32 | bPlus( bPlus ), | 32 | bPlus( bPlus ), |
33 | bCaps( bCaps ), | 33 | bCaps( bCaps ), |
34 | bTokenize( true ) | 34 | bTokenize( true ) |
35 | { | 35 | { |
36 | } | 36 | } |
37 | Fmt( unsigned int uMinWidth, Alignment a, | 37 | Fmt( unsigned int uMinWidth, Alignment a, |
38 | unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, | 38 | unsigned int uRadix=10, bool bPlus=false, bool bCaps=true, |
39 | char cFill=' ') : | 39 | char cFill=' ') : |
40 | uMinWidth( uMinWidth ), | 40 | uMinWidth( uMinWidth ), |
41 | cFillChar(cFill), | 41 | cFillChar(cFill), |
42 | uRadix( uRadix ), | 42 | uRadix( uRadix ), |
43 | uAlign( a ), | 43 | uAlign( a ), |
44 | bPlus( bPlus ), | 44 | bPlus( bPlus ), |
45 | bCaps( bCaps ), | 45 | bCaps( bCaps ), |
46 | bTokenize( true ) | 46 | bTokenize( true ) |
47 | { | 47 | { |
48 | } | 48 | } |
49 | 49 | ||
50 | static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) | 50 | static Fmt hex( unsigned int uWidth=0, bool bCaps=false ) |
51 | { | 51 | { |
52 | return Fmt( uWidth, 16, Right, false, bCaps, '0' ); | 52 | return Fmt( uWidth, 16, Right, false, bCaps, '0' ); |
53 | } | 53 | } |
54 | 54 | ||
55 | static Fmt oct( unsigned int uWidth=0 ) | 55 | static Fmt oct( unsigned int uWidth=0 ) |
56 | { | 56 | { |
57 | return Fmt( uWidth, 8, Right, false, false, '0' ); | 57 | return Fmt( uWidth, 8, Right, false, false, '0' ); |
58 | } | 58 | } |
59 | 59 | ||
60 | static Fmt bin( unsigned int uWidth=0 ) | 60 | static Fmt bin( unsigned int uWidth=0 ) |
61 | { | 61 | { |
62 | return Fmt( uWidth, 1, Right, false, false, '0' ); | 62 | return Fmt( uWidth, 1, Right, false, false, '0' ); |
63 | } | 63 | } |
64 | 64 | ||
65 | static Fmt ptr( bool bCaps=true ) | 65 | static Fmt ptr( bool bCaps=true ) |
66 | { | 66 | { |
67 | return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); | 67 | return Fmt( sizeof(ptrdiff_t)*2, 16, Right, false, bCaps, '0' ); |
68 | } | 68 | } |
69 | 69 | ||
70 | Fmt &width( unsigned int uWidth ); | 70 | Fmt &width( unsigned int uWidth ); |
71 | Fmt &fill( char cFill='0' ); | 71 | Fmt &fill( char cFill='0' ); |
72 | Fmt &radix( unsigned int uRadix ); | 72 | Fmt &radix( unsigned int uRadix ); |
73 | Fmt &align( Alignment eAlign ); | 73 | Fmt &align( Alignment eAlign ); |
74 | Fmt &plus( bool bPlus=true ); | 74 | Fmt &plus( bool bPlus=true ); |
75 | Fmt &caps( bool bCaps=true ); | 75 | Fmt &caps( bool bCaps=true ); |
76 | Fmt &upper(); | 76 | Fmt &upper(); |
77 | Fmt &lower(); | 77 | Fmt &lower(); |
78 | Fmt &tokenize( bool bTokenize=true ); | 78 | Fmt &tokenize( bool bTokenize=true ); |
79 | 79 | ||
80 | Fmt &left(); | 80 | Fmt &left(); |
81 | Fmt &right(); | 81 | Fmt &right(); |
82 | Fmt ¢er(); | 82 | Fmt ¢er(); |
83 | 83 | ||
84 | unsigned char uMinWidth; | 84 | unsigned char uMinWidth; |
85 | char cFillChar; | 85 | char cFillChar; |
86 | unsigned short uRadix : 6; | 86 | unsigned short uRadix : 6; |
87 | unsigned short uAlign : 2; | 87 | unsigned short uAlign : 2; |
88 | unsigned short bPlus : 1; | 88 | unsigned short bPlus : 1; |
89 | unsigned short bCaps : 1; | 89 | unsigned short bCaps : 1; |
90 | unsigned short bTokenize : 1; | 90 | unsigned short bTokenize : 1; |
91 | } Fmt; | 91 | } Fmt; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | #endif | 94 | #endif |
diff --git a/src/stable/formatter.cpp b/src/stable/formatter.cpp index a04f7a6..9a42c99 100644 --- a/src/stable/formatter.cpp +++ b/src/stable/formatter.cpp | |||
@@ -12,54 +12,54 @@ | |||
12 | 12 | ||
13 | template<> float Bu::tlog( float x ) | 13 | template<> float Bu::tlog( float x ) |
14 | { | 14 | { |
15 | return logf( x ); | 15 | return logf( x ); |
16 | } | 16 | } |
17 | 17 | ||
18 | template<> double Bu::tlog( double x ) | 18 | template<> double Bu::tlog( double x ) |
19 | { | 19 | { |
20 | return log( x ); | 20 | return log( x ); |
21 | } | 21 | } |
22 | 22 | ||
23 | template<> long double Bu::tlog( long double x ) | 23 | template<> long double Bu::tlog( long double x ) |
24 | { | 24 | { |
25 | return logl( x ); | 25 | return logl( x ); |
26 | } | 26 | } |
27 | 27 | ||
28 | template<> float Bu::tfloor( float x ) | 28 | template<> float Bu::tfloor( float x ) |
29 | { | 29 | { |
30 | return floorf( x ); | 30 | return floorf( x ); |
31 | } | 31 | } |
32 | 32 | ||
33 | template<> double Bu::tfloor( double x ) | 33 | template<> double Bu::tfloor( double x ) |
34 | { | 34 | { |
35 | return floor( x ); | 35 | return floor( x ); |
36 | } | 36 | } |
37 | 37 | ||
38 | template<> long double Bu::tfloor( long double x ) | 38 | template<> long double Bu::tfloor( long double x ) |
39 | { | 39 | { |
40 | return floorl( x ); | 40 | return floorl( x ); |
41 | } | 41 | } |
42 | 42 | ||
43 | template<> float Bu::tpow( float x, float y ) | 43 | template<> float Bu::tpow( float x, float y ) |
44 | { | 44 | { |
45 | return powf( x, y ); | 45 | return powf( x, y ); |
46 | } | 46 | } |
47 | 47 | ||
48 | template<> double Bu::tpow( double x, double y ) | 48 | template<> double Bu::tpow( double x, double y ) |
49 | { | 49 | { |
50 | return pow( x, y ); | 50 | return pow( x, y ); |
51 | } | 51 | } |
52 | 52 | ||
53 | template<> long double Bu::tpow( long double x, long double y ) | 53 | template<> long double Bu::tpow( long double x, long double y ) |
54 | { | 54 | { |
55 | return powl( x, y ); | 55 | return powl( x, y ); |
56 | } | 56 | } |
57 | 57 | ||
58 | Bu::Formatter::Formatter( Stream &rStream ) : | 58 | Bu::Formatter::Formatter( Stream &rStream ) : |
59 | rStream( rStream ), | 59 | rStream( rStream ), |
60 | bTempFmt( false ), | 60 | bTempFmt( false ), |
61 | uIndent( 0 ), | 61 | uIndent( 0 ), |
62 | cIndent( '\t' ) | 62 | cIndent( '\t' ) |
63 | { | 63 | { |
64 | } | 64 | } |
65 | 65 | ||
@@ -69,491 +69,491 @@ Bu::Formatter::~Formatter() | |||
69 | 69 | ||
70 | void Bu::Formatter::write( const Bu::String &sStr ) | 70 | void Bu::Formatter::write( const Bu::String &sStr ) |
71 | { | 71 | { |
72 | rStream.write( sStr ); | 72 | rStream.write( sStr ); |
73 | } | 73 | } |
74 | 74 | ||
75 | void Bu::Formatter::write( const void *sStr, int iLen ) | 75 | void Bu::Formatter::write( const void *sStr, int iLen ) |
76 | { | 76 | { |
77 | rStream.write( sStr, iLen ); | 77 | rStream.write( sStr, iLen ); |
78 | } | 78 | } |
79 | 79 | ||
80 | void Bu::Formatter::writeAligned( const Bu::String &sStr ) | 80 | void Bu::Formatter::writeAligned( const Bu::String &sStr ) |
81 | { | 81 | { |
82 | int iLen = sStr.getSize(); | 82 | int iLen = sStr.getSize(); |
83 | if( iLen > fLast.uMinWidth ) | 83 | if( iLen > fLast.uMinWidth ) |
84 | { | 84 | { |
85 | write( sStr ); | 85 | write( sStr ); |
86 | } | 86 | } |
87 | else | 87 | else |
88 | { | 88 | { |
89 | int iRem = fLast.uMinWidth - iLen; | 89 | int iRem = fLast.uMinWidth - iLen; |
90 | switch( fLast.uAlign ) | 90 | switch( fLast.uAlign ) |
91 | { | 91 | { |
92 | case Fmt::Right: | 92 | case Fmt::Right: |
93 | for( int k = 0; k < iRem; k++ ) | 93 | for( int k = 0; k < iRem; k++ ) |
94 | write( &fLast.cFillChar, 1 ); | 94 | write( &fLast.cFillChar, 1 ); |
95 | write( sStr ); | 95 | write( sStr ); |
96 | break; | 96 | break; |
97 | 97 | ||
98 | case Fmt::Center: | 98 | case Fmt::Center: |
99 | { | 99 | { |
100 | int iHlf = iRem/2; | 100 | int iHlf = iRem/2; |
101 | for( int k = 0; k < iHlf; k++ ) | 101 | for( int k = 0; k < iHlf; k++ ) |
102 | write( &fLast.cFillChar, 1 ); | 102 | write( &fLast.cFillChar, 1 ); |
103 | write( sStr ); | 103 | write( sStr ); |
104 | iHlf = iRem-iHlf;; | 104 | iHlf = iRem-iHlf;; |
105 | for( int k = 0; k < iHlf; k++ ) | 105 | for( int k = 0; k < iHlf; k++ ) |
106 | write( &fLast.cFillChar, 1 ); | 106 | write( &fLast.cFillChar, 1 ); |
107 | } | 107 | } |
108 | break; | 108 | break; |
109 | 109 | ||
110 | case Fmt::Left: | 110 | case Fmt::Left: |
111 | write( sStr ); | 111 | write( sStr ); |
112 | for( int k = 0; k < iRem; k++ ) | 112 | for( int k = 0; k < iRem; k++ ) |
113 | write( &fLast.cFillChar, 1 ); | 113 | write( &fLast.cFillChar, 1 ); |
114 | break; | 114 | break; |
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | usedFormat(); | 118 | usedFormat(); |
119 | } | 119 | } |
120 | 120 | ||
121 | void Bu::Formatter::writeAligned( const char *sStr, int iLen ) | 121 | void Bu::Formatter::writeAligned( const char *sStr, int iLen ) |
122 | { | 122 | { |
123 | if( iLen > fLast.uMinWidth ) | 123 | if( iLen > fLast.uMinWidth ) |
124 | { | 124 | { |
125 | write( sStr, iLen ); | 125 | write( sStr, iLen ); |
126 | } | 126 | } |
127 | else | 127 | else |
128 | { | 128 | { |
129 | int iRem = fLast.uMinWidth - iLen; | 129 | int iRem = fLast.uMinWidth - iLen; |
130 | switch( fLast.uAlign ) | 130 | switch( fLast.uAlign ) |
131 | { | 131 | { |
132 | case Fmt::Right: | 132 | case Fmt::Right: |
133 | for( int k = 0; k < iRem; k++ ) | 133 | for( int k = 0; k < iRem; k++ ) |
134 | write( &fLast.cFillChar, 1 ); | 134 | write( &fLast.cFillChar, 1 ); |
135 | write( sStr, iLen ); | 135 | write( sStr, iLen ); |
136 | break; | 136 | break; |
137 | 137 | ||
138 | case Fmt::Center: | 138 | case Fmt::Center: |
139 | { | 139 | { |
140 | int iHlf = iRem/2; | 140 | int iHlf = iRem/2; |
141 | for( int k = 0; k < iHlf; k++ ) | 141 | for( int k = 0; k < iHlf; k++ ) |
142 | write( &fLast.cFillChar, 1 ); | 142 | write( &fLast.cFillChar, 1 ); |
143 | write( sStr, iLen ); | 143 | write( sStr, iLen ); |
144 | iHlf = iRem-iHlf;; | 144 | iHlf = iRem-iHlf;; |
145 | for( int k = 0; k < iHlf; k++ ) | 145 | for( int k = 0; k < iHlf; k++ ) |
146 | write( &fLast.cFillChar, 1 ); | 146 | write( &fLast.cFillChar, 1 ); |
147 | } | 147 | } |
148 | break; | 148 | break; |
149 | 149 | ||
150 | case Fmt::Left: | 150 | case Fmt::Left: |
151 | write( sStr, iLen ); | 151 | write( sStr, iLen ); |
152 | for( int k = 0; k < iRem; k++ ) | 152 | for( int k = 0; k < iRem; k++ ) |
153 | write( &fLast.cFillChar, 1 ); | 153 | write( &fLast.cFillChar, 1 ); |
154 | break; | 154 | break; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | usedFormat(); | 158 | usedFormat(); |
159 | } | 159 | } |
160 | 160 | ||
161 | void Bu::Formatter::read( void *sStr, int iLen ) | 161 | void Bu::Formatter::read( void *sStr, int iLen ) |
162 | { | 162 | { |
163 | rStream.read( sStr, iLen ); | 163 | rStream.read( sStr, iLen ); |
164 | } | 164 | } |
165 | 165 | ||
166 | Bu::String Bu::Formatter::readToken() | 166 | Bu::String Bu::Formatter::readToken() |
167 | { | 167 | { |
168 | Bu::String sRet; | 168 | Bu::String sRet; |
169 | if( fLast.bTokenize ) | 169 | if( fLast.bTokenize ) |
170 | { | 170 | { |
171 | for(;;) | 171 | for(;;) |
172 | { | 172 | { |
173 | char buf; | 173 | char buf; |
174 | int iRead = rStream.read( &buf, 1 ); | 174 | int iRead = rStream.read( &buf, 1 ); |
175 | if( iRead == 0 ) | 175 | if( iRead == 0 ) |
176 | return sRet; | 176 | return sRet; |
177 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) | 177 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) |
178 | continue; | 178 | continue; |
179 | else | 179 | else |
180 | { | 180 | { |
181 | sRet += buf; | 181 | sRet += buf; |
182 | break; | 182 | break; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | for(;;) | 185 | for(;;) |
186 | { | 186 | { |
187 | char buf; | 187 | char buf; |
188 | int iRead = rStream.read( &buf, 1 ); | 188 | int iRead = rStream.read( &buf, 1 ); |
189 | if( iRead == 0 ) | 189 | if( iRead == 0 ) |
190 | return sRet; | 190 | return sRet; |
191 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) | 191 | if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) |
192 | return sRet; | 192 | return sRet; |
193 | else | 193 | else |
194 | sRet += buf; | 194 | sRet += buf; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | else | 197 | else |
198 | { | 198 | { |
199 | for(;;) | 199 | for(;;) |
200 | { | 200 | { |
201 | char buf; | 201 | char buf; |
202 | int iRead = rStream.read( &buf, 1 ); | 202 | int iRead = rStream.read( &buf, 1 ); |
203 | if( iRead == 0 ) | 203 | if( iRead == 0 ) |
204 | return sRet; | 204 | return sRet; |
205 | else | 205 | else |
206 | sRet += buf; | 206 | sRet += buf; |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | void Bu::Formatter::incIndent() | 211 | void Bu::Formatter::incIndent() |
212 | { | 212 | { |
213 | if( uIndent < 0xFFU ) | 213 | if( uIndent < 0xFFU ) |
214 | uIndent++; | 214 | uIndent++; |
215 | } | 215 | } |
216 | 216 | ||
217 | void Bu::Formatter::decIndent() | 217 | void Bu::Formatter::decIndent() |
218 | { | 218 | { |
219 | if( uIndent > 0 ) | 219 | if( uIndent > 0 ) |
220 | uIndent--; | 220 | uIndent--; |
221 | } | 221 | } |
222 | 222 | ||
223 | void Bu::Formatter::setIndent( uint8_t uLevel ) | 223 | void Bu::Formatter::setIndent( uint8_t uLevel ) |
224 | { | 224 | { |
225 | uIndent = uLevel; | 225 | uIndent = uLevel; |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::Formatter::clearIndent() | 228 | void Bu::Formatter::clearIndent() |
229 | { | 229 | { |
230 | uIndent = 0; | 230 | uIndent = 0; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::Formatter::setIndentChar( char cIndent ) | 233 | void Bu::Formatter::setIndentChar( char cIndent ) |
234 | { | 234 | { |
235 | this->cIndent = cIndent; | 235 | this->cIndent = cIndent; |
236 | } | 236 | } |
237 | 237 | ||
238 | void Bu::Formatter::doFlush() | 238 | void Bu::Formatter::doFlush() |
239 | { | 239 | { |
240 | rStream.flush(); | 240 | rStream.flush(); |
241 | } | 241 | } |
242 | 242 | ||
243 | Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) | 243 | Bu::Fmt &Bu::Fmt::width( unsigned int uWidth ) |
244 | { | 244 | { |
245 | this->uMinWidth = uWidth; | 245 | this->uMinWidth = uWidth; |
246 | return *this; | 246 | return *this; |
247 | } | 247 | } |
248 | 248 | ||
249 | Bu::Fmt &Bu::Fmt::fill( char cFill ) | 249 | Bu::Fmt &Bu::Fmt::fill( char cFill ) |
250 | { | 250 | { |
251 | this->cFillChar = (unsigned char)cFill; | 251 | this->cFillChar = (unsigned char)cFill; |
252 | return *this; | 252 | return *this; |
253 | } | 253 | } |
254 | 254 | ||
255 | Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) | 255 | Bu::Fmt &Bu::Fmt::radix( unsigned int uRadix ) |
256 | { | 256 | { |
257 | this->uRadix = uRadix; | 257 | this->uRadix = uRadix; |
258 | return *this; | 258 | return *this; |
259 | } | 259 | } |
260 | 260 | ||
261 | Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) | 261 | Bu::Fmt &Bu::Fmt::align( Alignment eAlign ) |
262 | { | 262 | { |
263 | this->uAlign = eAlign; | 263 | this->uAlign = eAlign; |
264 | return *this; | 264 | return *this; |
265 | } | 265 | } |
266 | 266 | ||
267 | Bu::Fmt &Bu::Fmt::left() | 267 | Bu::Fmt &Bu::Fmt::left() |
268 | { | 268 | { |
269 | this->uAlign = Fmt::Left; | 269 | this->uAlign = Fmt::Left; |
270 | return *this; | 270 | return *this; |
271 | } | 271 | } |
272 | 272 | ||
273 | Bu::Fmt &Bu::Fmt::center() | 273 | Bu::Fmt &Bu::Fmt::center() |
274 | { | 274 | { |
275 | this->uAlign = Fmt::Center; | 275 | this->uAlign = Fmt::Center; |
276 | return *this; | 276 | return *this; |
277 | } | 277 | } |
278 | 278 | ||
279 | Bu::Fmt &Bu::Fmt::right() | 279 | Bu::Fmt &Bu::Fmt::right() |
280 | { | 280 | { |
281 | this->uAlign = Fmt::Right; | 281 | this->uAlign = Fmt::Right; |
282 | return *this; | 282 | return *this; |
283 | } | 283 | } |
284 | 284 | ||
285 | Bu::Fmt &Bu::Fmt::plus( bool bPlus ) | 285 | Bu::Fmt &Bu::Fmt::plus( bool bPlus ) |
286 | { | 286 | { |
287 | this->bPlus = bPlus; | 287 | this->bPlus = bPlus; |
288 | return *this; | 288 | return *this; |
289 | } | 289 | } |
290 | 290 | ||
291 | Bu::Fmt &Bu::Fmt::caps( bool bCaps ) | 291 | Bu::Fmt &Bu::Fmt::caps( bool bCaps ) |
292 | { | 292 | { |
293 | this->bCaps = bCaps; | 293 | this->bCaps = bCaps; |
294 | return *this; | 294 | return *this; |
295 | } | 295 | } |
296 | 296 | ||
297 | Bu::Fmt &Bu::Fmt::upper() | 297 | Bu::Fmt &Bu::Fmt::upper() |
298 | { | 298 | { |
299 | this->bCaps = true; | 299 | this->bCaps = true; |
300 | return *this; | 300 | return *this; |
301 | } | 301 | } |
302 | 302 | ||
303 | Bu::Fmt &Bu::Fmt::lower() | 303 | Bu::Fmt &Bu::Fmt::lower() |
304 | { | 304 | { |
305 | this->bCaps = false; | 305 | this->bCaps = false; |
306 | return *this; | 306 | return *this; |
307 | } | 307 | } |
308 | 308 | ||
309 | Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) | 309 | Bu::Fmt &Bu::Fmt::tokenize( bool bTokenize ) |
310 | { | 310 | { |
311 | this->bTokenize = bTokenize; | 311 | this->bTokenize = bTokenize; |
312 | return *this; | 312 | return *this; |
313 | } | 313 | } |
314 | 314 | ||
315 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) | 315 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Fmt &fmt ) |
316 | { | 316 | { |
317 | f.setTempFormat( fmt ); | 317 | f.setTempFormat( fmt ); |
318 | return f; | 318 | return f; |
319 | } | 319 | } |
320 | 320 | ||
321 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) | 321 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Formatter::Special s ) |
322 | { | 322 | { |
323 | switch( s ) | 323 | switch( s ) |
324 | { | 324 | { |
325 | case Formatter::nl: | 325 | case Formatter::nl: |
326 | { | 326 | { |
327 | #ifdef WIN32 | 327 | #ifdef WIN32 |
328 | f.write("\r\n", 2 ); | 328 | f.write("\r\n", 2 ); |
329 | #else | 329 | #else |
330 | f.write("\n", 1 ); | 330 | f.write("\n", 1 ); |
331 | #endif | 331 | #endif |
332 | char ci = f.getIndentChar(); | 332 | char ci = f.getIndentChar(); |
333 | for( int j = 0; j < f.getIndent(); j++ ) | 333 | for( int j = 0; j < f.getIndent(); j++ ) |
334 | f.write( &ci, 1 ); | 334 | f.write( &ci, 1 ); |
335 | f.doFlush(); | 335 | f.doFlush(); |
336 | } | 336 | } |
337 | break; | 337 | break; |
338 | 338 | ||
339 | case Formatter::flush: | 339 | case Formatter::flush: |
340 | f.doFlush(); | 340 | f.doFlush(); |
341 | break; | 341 | break; |
342 | } | 342 | } |
343 | return f; | 343 | return f; |
344 | } | 344 | } |
345 | 345 | ||
346 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) | 346 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const char *sStr ) |
347 | { | 347 | { |
348 | f.writeAligned( sStr, strlen( sStr ) ); | 348 | f.writeAligned( sStr, strlen( sStr ) ); |
349 | return f; | 349 | return f; |
350 | } | 350 | } |
351 | 351 | ||
352 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) | 352 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char *sStr ) |
353 | { | 353 | { |
354 | f.writeAligned( sStr, strlen( sStr ) ); | 354 | f.writeAligned( sStr, strlen( sStr ) ); |
355 | return f; | 355 | return f; |
356 | } | 356 | } |
357 | 357 | ||
358 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) | 358 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::String &sStr ) |
359 | { | 359 | { |
360 | f.writeAligned( sStr ); | 360 | f.writeAligned( sStr ); |
361 | return f; | 361 | return f; |
362 | } | 362 | } |
363 | 363 | ||
364 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) | 364 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed char c ) |
365 | { | 365 | { |
366 | f.ifmt<signed char>( c ); | 366 | f.ifmt<signed char>( c ); |
367 | //f.write( (char *)&c, 1 ); | 367 | //f.write( (char *)&c, 1 ); |
368 | return f; | 368 | return f; |
369 | } | 369 | } |
370 | 370 | ||
371 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) | 371 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, char c ) |
372 | { | 372 | { |
373 | f.write( (char *)&c, 1 ); | 373 | f.write( (char *)&c, 1 ); |
374 | return f; | 374 | return f; |
375 | } | 375 | } |
376 | 376 | ||
377 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) | 377 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned char c ) |
378 | { | 378 | { |
379 | f.ufmt<unsigned char>( c ); | 379 | f.ufmt<unsigned char>( c ); |
380 | //f.write( (char *)&c, 1 ); | 380 | //f.write( (char *)&c, 1 ); |
381 | return f; | 381 | return f; |
382 | } | 382 | } |
383 | 383 | ||
384 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) | 384 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed short i ) |
385 | { | 385 | { |
386 | f.ifmt<signed short>( i ); | 386 | f.ifmt<signed short>( i ); |
387 | return f; | 387 | return f; |
388 | } | 388 | } |
389 | 389 | ||
390 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) | 390 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned short i ) |
391 | { | 391 | { |
392 | f.ufmt<unsigned short>( i ); | 392 | f.ufmt<unsigned short>( i ); |
393 | return f; | 393 | return f; |
394 | } | 394 | } |
395 | 395 | ||
396 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) | 396 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed int i ) |
397 | { | 397 | { |
398 | f.ifmt<signed int>( i ); | 398 | f.ifmt<signed int>( i ); |
399 | return f; | 399 | return f; |
400 | } | 400 | } |
401 | 401 | ||
402 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) | 402 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned int i ) |
403 | { | 403 | { |
404 | f.ufmt<unsigned int>( i ); | 404 | f.ufmt<unsigned int>( i ); |
405 | return f; | 405 | return f; |
406 | } | 406 | } |
407 | 407 | ||
408 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) | 408 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long i ) |
409 | { | 409 | { |
410 | f.ifmt<signed long>( i ); | 410 | f.ifmt<signed long>( i ); |
411 | return f; | 411 | return f; |
412 | } | 412 | } |
413 | 413 | ||
414 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) | 414 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long i ) |
415 | { | 415 | { |
416 | f.ufmt<unsigned long>( i ); | 416 | f.ufmt<unsigned long>( i ); |
417 | return f; | 417 | return f; |
418 | } | 418 | } |
419 | 419 | ||
420 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) | 420 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, signed long long i ) |
421 | { | 421 | { |
422 | f.ifmt<signed long long>( i ); | 422 | f.ifmt<signed long long>( i ); |
423 | return f; | 423 | return f; |
424 | } | 424 | } |
425 | 425 | ||
426 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) | 426 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, unsigned long long i ) |
427 | { | 427 | { |
428 | f.ufmt<unsigned long long>( i ); | 428 | f.ufmt<unsigned long long>( i ); |
429 | return f; | 429 | return f; |
430 | } | 430 | } |
431 | 431 | ||
432 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) | 432 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, float flt ) |
433 | { | 433 | { |
434 | f.ffmt<float>( flt ); | 434 | f.ffmt<float>( flt ); |
435 | return f; | 435 | return f; |
436 | } | 436 | } |
437 | 437 | ||
438 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) | 438 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, double flt ) |
439 | { | 439 | { |
440 | f.ffmt<double>( flt ); | 440 | f.ffmt<double>( flt ); |
441 | return f; | 441 | return f; |
442 | } | 442 | } |
443 | 443 | ||
444 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) | 444 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, long double flt ) |
445 | { | 445 | { |
446 | f.ffmt<long double>( flt ); | 446 | f.ffmt<long double>( flt ); |
447 | return f; | 447 | return f; |
448 | } | 448 | } |
449 | 449 | ||
450 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) | 450 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, bool b ) |
451 | { | 451 | { |
452 | f.writeAligned( b?("true"):("false") ); | 452 | f.writeAligned( b?("true"):("false") ); |
453 | return f; | 453 | return f; |
454 | } | 454 | } |
455 | 455 | ||
456 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) | 456 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, Bu::String &sStr ) |
457 | { | 457 | { |
458 | sStr = f.readToken(); | 458 | sStr = f.readToken(); |
459 | return f; | 459 | return f; |
460 | } | 460 | } |
461 | 461 | ||
462 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) | 462 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed char &c ) |
463 | { | 463 | { |
464 | f.read( &c, 1 ); | 464 | f.read( &c, 1 ); |
465 | return f; | 465 | return f; |
466 | } | 466 | } |
467 | 467 | ||
468 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) | 468 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, char &c ) |
469 | { | 469 | { |
470 | f.read( &c, 1 ); | 470 | f.read( &c, 1 ); |
471 | return f; | 471 | return f; |
472 | } | 472 | } |
473 | 473 | ||
474 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) | 474 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned char &c ) |
475 | { | 475 | { |
476 | f.read( &c, 1 ); | 476 | f.read( &c, 1 ); |
477 | return f; | 477 | return f; |
478 | } | 478 | } |
479 | 479 | ||
480 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) | 480 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed short &i ) |
481 | { | 481 | { |
482 | f.iparse( i, f.readToken() ); | 482 | f.iparse( i, f.readToken() ); |
483 | return f; | 483 | return f; |
484 | } | 484 | } |
485 | 485 | ||
486 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) | 486 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned short &i ) |
487 | { | 487 | { |
488 | f.uparse( i, f.readToken() ); | 488 | f.uparse( i, f.readToken() ); |
489 | return f; | 489 | return f; |
490 | } | 490 | } |
491 | 491 | ||
492 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) | 492 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed int &i ) |
493 | { | 493 | { |
494 | f.iparse( i, f.readToken() ); | 494 | f.iparse( i, f.readToken() ); |
495 | return f; | 495 | return f; |
496 | } | 496 | } |
497 | 497 | ||
498 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) | 498 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned int &i ) |
499 | { | 499 | { |
500 | f.uparse( i, f.readToken() ); | 500 | f.uparse( i, f.readToken() ); |
501 | return f; | 501 | return f; |
502 | } | 502 | } |
503 | 503 | ||
504 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) | 504 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long &i ) |
505 | { | 505 | { |
506 | f.iparse( i, f.readToken() ); | 506 | f.iparse( i, f.readToken() ); |
507 | return f; | 507 | return f; |
508 | } | 508 | } |
509 | 509 | ||
510 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) | 510 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long &i ) |
511 | { | 511 | { |
512 | f.uparse( i, f.readToken() ); | 512 | f.uparse( i, f.readToken() ); |
513 | return f; | 513 | return f; |
514 | } | 514 | } |
515 | 515 | ||
516 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) | 516 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, signed long long &i ) |
517 | { | 517 | { |
518 | f.iparse( i, f.readToken() ); | 518 | f.iparse( i, f.readToken() ); |
519 | return f; | 519 | return f; |
520 | } | 520 | } |
521 | 521 | ||
522 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) | 522 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, unsigned long long &i ) |
523 | { | 523 | { |
524 | f.uparse( i, f.readToken() ); | 524 | f.uparse( i, f.readToken() ); |
525 | return f; | 525 | return f; |
526 | } | 526 | } |
527 | 527 | ||
528 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) | 528 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, float &flt ) |
529 | { | 529 | { |
530 | f.fparse( flt, f.readToken() ); | 530 | f.fparse( flt, f.readToken() ); |
531 | return f; | 531 | return f; |
532 | } | 532 | } |
533 | 533 | ||
534 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) | 534 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, double &flt ) |
535 | { | 535 | { |
536 | f.fparse( flt, f.readToken() ); | 536 | f.fparse( flt, f.readToken() ); |
537 | return f; | 537 | return f; |
538 | } | 538 | } |
539 | 539 | ||
540 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) | 540 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, long double &flt ) |
541 | { | 541 | { |
542 | f.fparse( flt, f.readToken() ); | 542 | f.fparse( flt, f.readToken() ); |
543 | return f; | 543 | return f; |
544 | } | 544 | } |
545 | 545 | ||
546 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) | 546 | Bu::Formatter &Bu::operator>>( Bu::Formatter &f, bool &b ) |
547 | { | 547 | { |
548 | Bu::String sStr = f.readToken(); | 548 | Bu::String sStr = f.readToken(); |
549 | if( !sStr.isSet() ) | 549 | if( !sStr.isSet() ) |
550 | return f; | 550 | return f; |
551 | char c = *sStr.begin(); | 551 | char c = *sStr.begin(); |
552 | if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) | 552 | if( c == 'y' || c == 'Y' || c == 't' || c == 'T' ) |
553 | b = true; | 553 | b = true; |
554 | else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) | 554 | else if( c == 'n' || c == 'N' || c == 'f' || c == 'F' ) |
555 | b = false; | 555 | b = false; |
556 | 556 | ||
557 | return f; | 557 | return f; |
558 | } | 558 | } |
559 | 559 | ||
diff --git a/src/stable/formatter.h b/src/stable/formatter.h index d92a53b..94794b5 100644 --- a/src/stable/formatter.h +++ b/src/stable/formatter.h | |||
@@ -15,292 +15,292 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | class Stream; | 18 | class Stream; |
19 | 19 | ||
20 | template<typename t> t tlog( t x ); | 20 | template<typename t> t tlog( t x ); |
21 | template<> float tlog( float x ); | 21 | template<> float tlog( float x ); |
22 | template<> double tlog( double x ); | 22 | template<> double tlog( double x ); |
23 | template<> long double tlog( long double x ); | 23 | template<> long double tlog( long double x ); |
24 | 24 | ||
25 | template<typename t> t tfloor( t x ); | 25 | template<typename t> t tfloor( t x ); |
26 | template<> float tfloor( float x ); | 26 | template<> float tfloor( float x ); |
27 | template<> double tfloor( double x ); | 27 | template<> double tfloor( double x ); |
28 | template<> long double tfloor( long double x ); | 28 | template<> long double tfloor( long double x ); |
29 | 29 | ||
30 | template<typename t> t tpow( t x, t y ); | 30 | template<typename t> t tpow( t x, t y ); |
31 | template<> float tpow( float x, float y ); | 31 | template<> float tpow( float x, float y ); |
32 | template<> double tpow( double x, double y ); | 32 | template<> double tpow( double x, double y ); |
33 | template<> long double tpow( long double x, long double y ); | 33 | template<> long double tpow( long double x, long double y ); |
34 | 34 | ||
35 | class Formatter | 35 | class Formatter |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | Formatter( Stream &rStream ); | 38 | Formatter( Stream &rStream ); |
39 | virtual ~Formatter(); | 39 | virtual ~Formatter(); |
40 | 40 | ||
41 | void write( const Bu::String &sStr ); | 41 | void write( const Bu::String &sStr ); |
42 | void write( const void *sStr, int iLen ); | 42 | void write( const void *sStr, int iLen ); |
43 | void writeAligned( const Bu::String &sStr ); | 43 | void writeAligned( const Bu::String &sStr ); |
44 | void writeAligned( const char *sStr, int iLen ); | 44 | void writeAligned( const char *sStr, int iLen ); |
45 | 45 | ||
46 | void read( void *sStr, int iLen ); | 46 | void read( void *sStr, int iLen ); |
47 | Bu::String readToken(); | 47 | Bu::String readToken(); |
48 | 48 | ||
49 | void incIndent(); | 49 | void incIndent(); |
50 | void decIndent(); | 50 | void decIndent(); |
51 | void setIndent( uint8_t uLevel ); | 51 | void setIndent( uint8_t uLevel ); |
52 | void clearIndent(); | 52 | void clearIndent(); |
53 | uint8_t getIndent() const { return uIndent; } | 53 | uint8_t getIndent() const { return uIndent; } |
54 | void setIndentChar( char cIndent ); | 54 | void setIndentChar( char cIndent ); |
55 | char getIndentChar() const { return cIndent; } | 55 | char getIndentChar() const { return cIndent; } |
56 | 56 | ||
57 | void setFormat( const Fmt &f ) | 57 | void setFormat( const Fmt &f ) |
58 | { | 58 | { |
59 | fLast = f; | 59 | fLast = f; |
60 | bTempFmt = false; | 60 | bTempFmt = false; |
61 | } | 61 | } |
62 | 62 | ||
63 | void setTempFormat( const Fmt &f ) | 63 | void setTempFormat( const Fmt &f ) |
64 | { | 64 | { |
65 | fLast = f; | 65 | fLast = f; |
66 | bTempFmt = true; | 66 | bTempFmt = true; |
67 | } | 67 | } |
68 | 68 | ||
69 | void usedFormat() | 69 | void usedFormat() |
70 | { | 70 | { |
71 | if( bTempFmt ) | 71 | if( bTempFmt ) |
72 | fLast = Fmt(); | 72 | fLast = Fmt(); |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename type> | 75 | template<typename type> |
76 | void ifmt( type i ) | 76 | void ifmt( type i ) |
77 | { | 77 | { |
78 | // This code is taken from Nango, hopefully we can make it better. | 78 | // This code is taken from Nango, hopefully we can make it better. |
79 | bool bNeg = i<0; | 79 | bool bNeg = i<0; |
80 | char cBase = fLast.bCaps?'A':'a'; | 80 | char cBase = fLast.bCaps?'A':'a'; |
81 | char buf[sizeof(type)*8+1]; | 81 | char buf[sizeof(type)*8+1]; |
82 | if( bNeg ) i = -i; | 82 | if( bNeg ) i = -i; |
83 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 83 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
84 | { | 84 | { |
85 | usedFormat(); | 85 | usedFormat(); |
86 | return; | 86 | return; |
87 | } | 87 | } |
88 | 88 | ||
89 | for( int j = sizeof(type)*8; j >= 0; j-- ) | 89 | for( int j = sizeof(type)*8; j >= 0; j-- ) |
90 | { | 90 | { |
91 | int c = i%fLast.uRadix; | 91 | int c = i%fLast.uRadix; |
92 | i /= fLast.uRadix; | 92 | i /= fLast.uRadix; |
93 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | 93 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); |
94 | if( i == 0 ) | 94 | if( i == 0 ) |
95 | { | 95 | { |
96 | if( bNeg ) buf[--j] = '-'; | 96 | if( bNeg ) buf[--j] = '-'; |
97 | else if( fLast.bPlus ) buf[--j] = '+'; | 97 | else if( fLast.bPlus ) buf[--j] = '+'; |
98 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | 98 | writeAligned( buf+j, sizeof(type)*8-j+1 ); |
99 | 99 | ||
100 | return; | 100 | return; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | usedFormat(); | 103 | usedFormat(); |
104 | } | 104 | } |
105 | 105 | ||
106 | template<typename type> | 106 | template<typename type> |
107 | void ufmt( type i ) | 107 | void ufmt( type i ) |
108 | { | 108 | { |
109 | // This code is taken from Nango, hopefully we can make it better. | 109 | // This code is taken from Nango, hopefully we can make it better. |
110 | char buf[sizeof(type)*8+1]; | 110 | char buf[sizeof(type)*8+1]; |
111 | char cBase = fLast.bCaps?'A':'a'; | 111 | char cBase = fLast.bCaps?'A':'a'; |
112 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 112 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
113 | { | 113 | { |
114 | usedFormat(); | 114 | usedFormat(); |
115 | return; | 115 | return; |
116 | } | 116 | } |
117 | 117 | ||
118 | for( int j = sizeof(type)*8; j >= 0; j-- ) | 118 | for( int j = sizeof(type)*8; j >= 0; j-- ) |
119 | { | 119 | { |
120 | int c = i%fLast.uRadix; | 120 | int c = i%fLast.uRadix; |
121 | i /= fLast.uRadix; | 121 | i /= fLast.uRadix; |
122 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | 122 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); |
123 | if( i == 0 ) | 123 | if( i == 0 ) |
124 | { | 124 | { |
125 | if( fLast.bPlus ) buf[--j] = '+'; | 125 | if( fLast.bPlus ) buf[--j] = '+'; |
126 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | 126 | writeAligned( buf+j, sizeof(type)*8-j+1 ); |
127 | 127 | ||
128 | return; | 128 | return; |
129 | } | 129 | } |
130 | } | 130 | } |
131 | usedFormat(); | 131 | usedFormat(); |
132 | } | 132 | } |
133 | 133 | ||
134 | template<typename type> | 134 | template<typename type> |
135 | void ffmt( type f ) | 135 | void ffmt( type f ) |
136 | { | 136 | { |
137 | Bu::String fTmp; | 137 | Bu::String fTmp; |
138 | char cBase = fLast.bCaps?'A':'a'; | 138 | char cBase = fLast.bCaps?'A':'a'; |
139 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | 139 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) |
140 | { | 140 | { |
141 | usedFormat(); | 141 | usedFormat(); |
142 | return; | 142 | return; |
143 | } | 143 | } |
144 | 144 | ||
145 | if( signbit(f) ) | 145 | if( signbit(f) ) |
146 | { | 146 | { |
147 | f = -f; | 147 | f = -f; |
148 | fTmp += "-"; | 148 | fTmp += "-"; |
149 | } | 149 | } |
150 | int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); | 150 | int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); |
151 | f /= tpow( (type)fLast.uRadix, (type)iScale ); | 151 | f /= tpow( (type)fLast.uRadix, (type)iScale ); |
152 | 152 | ||
153 | if( iScale < 0 ) | 153 | if( iScale < 0 ) |
154 | { | 154 | { |
155 | fTmp += "0."; | 155 | fTmp += "0."; |
156 | for( int j = 1; j < -iScale; j++ ) | 156 | for( int j = 1; j < -iScale; j++ ) |
157 | fTmp += '0'; | 157 | fTmp += '0'; |
158 | } | 158 | } |
159 | int c = f; | 159 | int c = f; |
160 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | 160 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); |
161 | f -= (int)f; | 161 | f -= (int)f; |
162 | int j; | 162 | int j; |
163 | for( j = 0; j < 8 && f; j++ ) | 163 | for( j = 0; j < 8 && f; j++ ) |
164 | { | 164 | { |
165 | if( iScale - j == 0 ) | 165 | if( iScale - j == 0 ) |
166 | fTmp += '.'; | 166 | fTmp += '.'; |
167 | f = f*fLast.uRadix; | 167 | f = f*fLast.uRadix; |
168 | int c = f; | 168 | int c = f; |
169 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | 169 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); |
170 | f -= (int)f; | 170 | f -= (int)f; |
171 | } | 171 | } |
172 | if( iScale >= j ) | 172 | if( iScale >= j ) |
173 | { | 173 | { |
174 | for( int k = j; k < iScale; k++ ) | 174 | for( int k = j; k < iScale; k++ ) |
175 | fTmp += '0'; | 175 | fTmp += '0'; |
176 | fTmp += ".0"; | 176 | fTmp += ".0"; |
177 | } | 177 | } |
178 | 178 | ||
179 | writeAligned( fTmp ); | 179 | writeAligned( fTmp ); |
180 | usedFormat(); | 180 | usedFormat(); |
181 | } | 181 | } |
182 | 182 | ||
183 | template<typename type> | 183 | template<typename type> |
184 | void iparse( type &i, const Bu::String &sBuf ) | 184 | void iparse( type &i, const Bu::String &sBuf ) |
185 | { | 185 | { |
186 | if( !sBuf.isSet() ) | 186 | if( !sBuf.isSet() ) |
187 | return; | 187 | return; |
188 | if( sBuf[0] != '+' && sBuf[0] != '-' && | 188 | if( sBuf[0] != '+' && sBuf[0] != '-' && |
189 | (sBuf[0] < '0' && sBuf[0] > '9') ) | 189 | (sBuf[0] < '0' && sBuf[0] > '9') ) |
190 | return; | 190 | return; |
191 | int j = 1; | 191 | int j = 1; |
192 | int iMax = sBuf.getSize(); | 192 | int iMax = sBuf.getSize(); |
193 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | 193 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } |
194 | i = 0; | 194 | i = 0; |
195 | type iPos = 1; | 195 | type iPos = 1; |
196 | for(j--; j >= 0; j-- ) | 196 | for(j--; j >= 0; j-- ) |
197 | { | 197 | { |
198 | if( sBuf[j] == '+' || sBuf[j] == '-' ) | 198 | if( sBuf[j] == '+' || sBuf[j] == '-' ) |
199 | continue; | 199 | continue; |
200 | i += (sBuf[j]-'0')*iPos; | 200 | i += (sBuf[j]-'0')*iPos; |
201 | iPos *= fLast.uRadix; | 201 | iPos *= fLast.uRadix; |
202 | } | 202 | } |
203 | if( sBuf[0] == '-' ) | 203 | if( sBuf[0] == '-' ) |
204 | i = -i; | 204 | i = -i; |
205 | 205 | ||
206 | usedFormat(); | 206 | usedFormat(); |
207 | } | 207 | } |
208 | 208 | ||
209 | template<typename type> | 209 | template<typename type> |
210 | void uparse( type &i, const Bu::String &sBuf ) | 210 | void uparse( type &i, const Bu::String &sBuf ) |
211 | { | 211 | { |
212 | if( !sBuf.isSet() ) | 212 | if( !sBuf.isSet() ) |
213 | return; | 213 | return; |
214 | if( sBuf[0] != '+' && | 214 | if( sBuf[0] != '+' && |
215 | (sBuf[0] < '0' && sBuf[0] > '9') ) | 215 | (sBuf[0] < '0' && sBuf[0] > '9') ) |
216 | return; | 216 | return; |
217 | int j = 1; | 217 | int j = 1; |
218 | int iMax = sBuf.getSize(); | 218 | int iMax = sBuf.getSize(); |
219 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | 219 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } |
220 | i = 0; | 220 | i = 0; |
221 | type iPos = 1; | 221 | type iPos = 1; |
222 | for(j--; j >= 0; j-- ) | 222 | for(j--; j >= 0; j-- ) |
223 | { | 223 | { |
224 | if( sBuf[j] == '+' ) | 224 | if( sBuf[j] == '+' ) |
225 | continue; | 225 | continue; |
226 | i += (sBuf[j]-'0')*iPos; | 226 | i += (sBuf[j]-'0')*iPos; |
227 | iPos *= fLast.uRadix; | 227 | iPos *= fLast.uRadix; |
228 | } | 228 | } |
229 | 229 | ||
230 | usedFormat(); | 230 | usedFormat(); |
231 | } | 231 | } |
232 | 232 | ||
233 | template<typename type> | 233 | template<typename type> |
234 | void fparse( type &f, const Bu::String &sBuf ) | 234 | void fparse( type &f, const Bu::String &sBuf ) |
235 | { | 235 | { |
236 | double fIn; | 236 | double fIn; |
237 | sscanf( sBuf.getStr(), "%lf", &fIn ); | 237 | sscanf( sBuf.getStr(), "%lf", &fIn ); |
238 | f = fIn; | 238 | f = fIn; |
239 | usedFormat(); | 239 | usedFormat(); |
240 | } | 240 | } |
241 | 241 | ||
242 | enum Special | 242 | enum Special |
243 | { | 243 | { |
244 | nl, | 244 | nl, |
245 | flush | 245 | flush |
246 | }; | 246 | }; |
247 | 247 | ||
248 | void doFlush(); | 248 | void doFlush(); |
249 | 249 | ||
250 | Stream &getStream() { return rStream; } | 250 | Stream &getStream() { return rStream; } |
251 | operator Stream&() { return rStream; } | 251 | operator Stream&() { return rStream; } |
252 | 252 | ||
253 | private: | 253 | private: |
254 | Stream &rStream; | 254 | Stream &rStream; |
255 | Fmt fLast; | 255 | Fmt fLast; |
256 | bool bTempFmt; | 256 | bool bTempFmt; |
257 | uint8_t uIndent; | 257 | uint8_t uIndent; |
258 | char cIndent; | 258 | char cIndent; |
259 | }; | 259 | }; |
260 | 260 | ||
261 | Formatter &operator<<( Formatter &f, const Fmt &fmt ); | 261 | Formatter &operator<<( Formatter &f, const Fmt &fmt ); |
262 | Formatter &operator<<( Formatter &f, Formatter::Special s ); | 262 | Formatter &operator<<( Formatter &f, Formatter::Special s ); |
263 | Formatter &operator<<( Formatter &f, const char *sStr ); | 263 | Formatter &operator<<( Formatter &f, const char *sStr ); |
264 | Formatter &operator<<( Formatter &f, char *sStr ); | 264 | Formatter &operator<<( Formatter &f, char *sStr ); |
265 | Formatter &operator<<( Formatter &f, const Bu::String &sStr ); | 265 | Formatter &operator<<( Formatter &f, const Bu::String &sStr ); |
266 | Formatter &operator<<( Formatter &f, signed char c ); | 266 | Formatter &operator<<( Formatter &f, signed char c ); |
267 | Formatter &operator<<( Formatter &f, char c ); | 267 | Formatter &operator<<( Formatter &f, char c ); |
268 | Formatter &operator<<( Formatter &f, unsigned char c ); | 268 | Formatter &operator<<( Formatter &f, unsigned char c ); |
269 | Formatter &operator<<( Formatter &f, signed short i ); | 269 | Formatter &operator<<( Formatter &f, signed short i ); |
270 | Formatter &operator<<( Formatter &f, unsigned short i ); | 270 | Formatter &operator<<( Formatter &f, unsigned short i ); |
271 | Formatter &operator<<( Formatter &f, signed int i ); | 271 | Formatter &operator<<( Formatter &f, signed int i ); |
272 | Formatter &operator<<( Formatter &f, unsigned int i ); | 272 | Formatter &operator<<( Formatter &f, unsigned int i ); |
273 | Formatter &operator<<( Formatter &f, signed long i ); | 273 | Formatter &operator<<( Formatter &f, signed long i ); |
274 | Formatter &operator<<( Formatter &f, unsigned long i ); | 274 | Formatter &operator<<( Formatter &f, unsigned long i ); |
275 | Formatter &operator<<( Formatter &f, signed long long i ); | 275 | Formatter &operator<<( Formatter &f, signed long long i ); |
276 | Formatter &operator<<( Formatter &f, unsigned long long i ); | 276 | Formatter &operator<<( Formatter &f, unsigned long long i ); |
277 | Formatter &operator<<( Formatter &f, float flt ); | 277 | Formatter &operator<<( Formatter &f, float flt ); |
278 | Formatter &operator<<( Formatter &f, double flt ); | 278 | Formatter &operator<<( Formatter &f, double flt ); |
279 | Formatter &operator<<( Formatter &f, long double flt ); | 279 | Formatter &operator<<( Formatter &f, long double flt ); |
280 | Formatter &operator<<( Formatter &f, bool b ); | 280 | Formatter &operator<<( Formatter &f, bool b ); |
281 | 281 | ||
282 | Formatter &operator>>( Formatter &f, Bu::String &sStr ); | 282 | Formatter &operator>>( Formatter &f, Bu::String &sStr ); |
283 | Formatter &operator>>( Formatter &f, signed char &c ); | 283 | Formatter &operator>>( Formatter &f, signed char &c ); |
284 | Formatter &operator>>( Formatter &f, char &c ); | 284 | Formatter &operator>>( Formatter &f, char &c ); |
285 | Formatter &operator>>( Formatter &f, unsigned char &c ); | 285 | Formatter &operator>>( Formatter &f, unsigned char &c ); |
286 | Formatter &operator>>( Formatter &f, signed short &i ); | 286 | Formatter &operator>>( Formatter &f, signed short &i ); |
287 | Formatter &operator>>( Formatter &f, unsigned short &i ); | 287 | Formatter &operator>>( Formatter &f, unsigned short &i ); |
288 | Formatter &operator>>( Formatter &f, signed int &i ); | 288 | Formatter &operator>>( Formatter &f, signed int &i ); |
289 | Formatter &operator>>( Formatter &f, unsigned int &i ); | 289 | Formatter &operator>>( Formatter &f, unsigned int &i ); |
290 | Formatter &operator>>( Formatter &f, signed long &i ); | 290 | Formatter &operator>>( Formatter &f, signed long &i ); |
291 | Formatter &operator>>( Formatter &f, unsigned long &i ); | 291 | Formatter &operator>>( Formatter &f, unsigned long &i ); |
292 | Formatter &operator>>( Formatter &f, signed long long &i ); | 292 | Formatter &operator>>( Formatter &f, signed long long &i ); |
293 | Formatter &operator>>( Formatter &f, unsigned long long &i ); | 293 | Formatter &operator>>( Formatter &f, unsigned long long &i ); |
294 | Formatter &operator>>( Formatter &f, float &flt ); | 294 | Formatter &operator>>( Formatter &f, float &flt ); |
295 | Formatter &operator>>( Formatter &f, double &flt ); | 295 | Formatter &operator>>( Formatter &f, double &flt ); |
296 | Formatter &operator>>( Formatter &f, long double &flt ); | 296 | Formatter &operator>>( Formatter &f, long double &flt ); |
297 | Formatter &operator>>( Formatter &f, bool &b ); | 297 | Formatter &operator>>( Formatter &f, bool &b ); |
298 | 298 | ||
299 | template<typename type> | 299 | template<typename type> |
300 | Formatter &operator<<( Formatter &f, const type *p ) | 300 | Formatter &operator<<( Formatter &f, const type *p ) |
301 | { | 301 | { |
302 | return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); | 302 | return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); |
303 | } | 303 | } |
304 | }; | 304 | }; |
305 | 305 | ||
306 | #endif | 306 | #endif |
diff --git a/src/stable/formula.cpp b/src/stable/formula.cpp index 6bc2c58..c5ba1ae 100644 --- a/src/stable/formula.cpp +++ b/src/stable/formula.cpp | |||
@@ -9,6 +9,6 @@ | |||
9 | 9 | ||
10 | namespace Bu | 10 | namespace Bu |
11 | { | 11 | { |
12 | subExceptionDef( FormulaException ); | 12 | subExceptionDef( FormulaException ); |
13 | } | 13 | } |
14 | 14 | ||
diff --git a/src/stable/formula.h b/src/stable/formula.h index 36a0398..b12afd6 100644 --- a/src/stable/formula.h +++ b/src/stable/formula.h | |||
@@ -21,410 +21,410 @@ | |||
21 | 21 | ||
22 | namespace Bu | 22 | namespace Bu |
23 | { | 23 | { |
24 | subExceptionDecl( FormulaException ); | 24 | subExceptionDecl( FormulaException ); |
25 | /** | 25 | /** |
26 | * Implements a very simple formula parser that allows use of variables and | 26 | * Implements a very simple formula parser that allows use of variables and |
27 | * custom functions. This is based on a simple calculator-type parser that | 27 | * custom functions. This is based on a simple calculator-type parser that |
28 | * executes as it processes, accounting for operator precedence and | 28 | * executes as it processes, accounting for operator precedence and |
29 | * grouping. | 29 | * grouping. |
30 | * | 30 | * |
31 | * prec = precision, a type to use for all math (except binary ops) | 31 | * prec = precision, a type to use for all math (except binary ops) |
32 | * bin = binary type, a type to hard cast all data to for binary ops | 32 | * bin = binary type, a type to hard cast all data to for binary ops |
33 | */ | 33 | */ |
34 | template<typename prec, typename bin=uint32_t> | 34 | template<typename prec, typename bin=uint32_t> |
35 | class Formula | 35 | class Formula |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | class Func | 38 | class Func |
39 | { | 39 | { |
40 | public: | 40 | public: |
41 | virtual prec operator()( prec )=0; | 41 | virtual prec operator()( prec )=0; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | typedef Hash<Bu::String, prec> varHash; | 44 | typedef Hash<Bu::String, prec> varHash; |
45 | typedef Hash<Bu::String, Func *> funcHash; | 45 | typedef Hash<Bu::String, Func *> funcHash; |
46 | 46 | ||
47 | Formula() | 47 | Formula() |
48 | { | 48 | { |
49 | } | 49 | } |
50 | 50 | ||
51 | virtual ~Formula() | 51 | virtual ~Formula() |
52 | { | 52 | { |
53 | for( typename funcHash::iterator i = hFunc.begin(); | 53 | for( typename funcHash::iterator i = hFunc.begin(); |
54 | i != hFunc.end(); i++ ) | 54 | i != hFunc.end(); i++ ) |
55 | { | 55 | { |
56 | delete (*i); | 56 | delete (*i); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | prec run( const Bu::String &sFormulaSrc ) | 60 | prec run( const Bu::String &sFormulaSrc ) |
61 | { | 61 | { |
62 | if( sFormulaSrc.isEmpty() ) | 62 | if( sFormulaSrc.isEmpty() ) |
63 | throw FormulaException("Empty formula, nothing to do."); | 63 | throw FormulaException("Empty formula, nothing to do."); |
64 | try | 64 | try |
65 | { | 65 | { |
66 | const char *sFormula = sFormulaSrc.getStr(); | 66 | const char *sFormula = sFormulaSrc.getStr(); |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | uint8_t tNum = nextToken( &sFormula ); | 69 | uint8_t tNum = nextToken( &sFormula ); |
70 | if( tNum == symSubtract ) | 70 | if( tNum == symSubtract ) |
71 | { | 71 | { |
72 | sOper.push( symNegate ); | 72 | sOper.push( symNegate ); |
73 | continue; | 73 | continue; |
74 | } | 74 | } |
75 | else if( tNum == symNot ) | 75 | else if( tNum == symNot ) |
76 | { | 76 | { |
77 | sOper.push( symNot ); | 77 | sOper.push( symNot ); |
78 | continue; | 78 | continue; |
79 | } | 79 | } |
80 | else if( tNum == symOpenParen ) | 80 | else if( tNum == symOpenParen ) |
81 | { | 81 | { |
82 | sOper.push( tNum ); | 82 | sOper.push( tNum ); |
83 | continue; | 83 | continue; |
84 | } | 84 | } |
85 | else if( tNum == symFunction ) | 85 | else if( tNum == symFunction ) |
86 | { | 86 | { |
87 | sOper.push( symFunction ); | 87 | sOper.push( symFunction ); |
88 | continue; | 88 | continue; |
89 | } | 89 | } |
90 | else if( tNum == symEOS ) | 90 | else if( tNum == symEOS ) |
91 | { | 91 | { |
92 | throw Bu::FormulaException( | 92 | throw Bu::FormulaException( |
93 | "Cannot end with an operator."); | 93 | "Cannot end with an operator."); |
94 | } | 94 | } |
95 | 95 | ||
96 | oppart: uint8_t tOpr = nextToken( &sFormula ); | 96 | oppart: uint8_t tOpr = nextToken( &sFormula ); |
97 | if( tOpr == symEOS ) | 97 | if( tOpr == symEOS ) |
98 | { | 98 | { |
99 | reduce(); | 99 | reduce(); |
100 | prec ret = sValue.top(); | 100 | prec ret = sValue.top(); |
101 | sValue.clear(); | 101 | sValue.clear(); |
102 | sFunc.clear(); | 102 | sFunc.clear(); |
103 | sOper.clear(); | 103 | sOper.clear(); |
104 | return ret; | 104 | return ret; |
105 | } | 105 | } |
106 | if( !sOper.isEmpty() && getPrec( sOper.top() ) > | 106 | if( !sOper.isEmpty() && getPrec( sOper.top() ) > |
107 | getPrec( tOpr ) ) | 107 | getPrec( tOpr ) ) |
108 | { | 108 | { |
109 | reduce(); | 109 | reduce(); |
110 | } | 110 | } |
111 | if( tOpr != symCloseParen ) | 111 | if( tOpr != symCloseParen ) |
112 | { | 112 | { |
113 | sOper.push( tOpr ); | 113 | sOper.push( tOpr ); |
114 | } | 114 | } |
115 | else | 115 | else |
116 | { | 116 | { |
117 | reduce( true ); | 117 | reduce( true ); |
118 | goto oppart; | 118 | goto oppart; |
119 | } | 119 | } |
120 | } | 120 | } |
121 | } | 121 | } |
122 | catch( ... ) | 122 | catch( ... ) |
123 | { | 123 | { |
124 | sValue.clear(); | 124 | sValue.clear(); |
125 | sFunc.clear(); | 125 | sFunc.clear(); |
126 | sOper.clear(); | 126 | sOper.clear(); |
127 | throw; | 127 | throw; |
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | varHash hVars; | 131 | varHash hVars; |
132 | funcHash hFunc; | 132 | funcHash hFunc; |
133 | 133 | ||
134 | private: | 134 | private: |
135 | enum | 135 | enum |
136 | { | 136 | { |
137 | symEOS, | 137 | symEOS, |
138 | symAdd, | 138 | symAdd, |
139 | symSubtract, | 139 | symSubtract, |
140 | symMultiply, | 140 | symMultiply, |
141 | symDivide, | 141 | symDivide, |
142 | symOpenParen, | 142 | symOpenParen, |
143 | symCloseParen, | 143 | symCloseParen, |
144 | symNumber, | 144 | symNumber, |
145 | symVariable, | 145 | symVariable, |
146 | symFunction, | 146 | symFunction, |
147 | symExponent, | 147 | symExponent, |
148 | symNegate, | 148 | symNegate, |
149 | symModulus, | 149 | symModulus, |
150 | 150 | ||
151 | symAnd, | 151 | symAnd, |
152 | symOr, | 152 | symOr, |
153 | symXor, | 153 | symXor, |
154 | symNot | 154 | symNot |
155 | }; | 155 | }; |
156 | 156 | ||
157 | typedef uint8_t symType; | 157 | typedef uint8_t symType; |
158 | 158 | ||
159 | Bu::Stack<symType> sOper; | 159 | Bu::Stack<symType> sOper; |
160 | Bu::Stack<prec> sValue; | 160 | Bu::Stack<prec> sValue; |
161 | Bu::Stack<Bu::String> sFunc; | 161 | Bu::Stack<Bu::String> sFunc; |
162 | 162 | ||
163 | private: | 163 | private: |
164 | symType getPrec( symType nOper ) | 164 | symType getPrec( symType nOper ) |
165 | { | 165 | { |
166 | switch( nOper ) | 166 | switch( nOper ) |
167 | { | 167 | { |
168 | case symNumber: | 168 | case symNumber: |
169 | case symVariable: | 169 | case symVariable: |
170 | case symOpenParen: | 170 | case symOpenParen: |
171 | case symCloseParen: | 171 | case symCloseParen: |
172 | return 0; | 172 | return 0; |
173 | 173 | ||
174 | case symAdd: | 174 | case symAdd: |
175 | case symSubtract: | 175 | case symSubtract: |
176 | return 1; | 176 | return 1; |
177 | 177 | ||
178 | case symMultiply: | 178 | case symMultiply: |
179 | case symDivide: | 179 | case symDivide: |
180 | case symModulus: | 180 | case symModulus: |
181 | return 2; | 181 | return 2; |
182 | 182 | ||
183 | case symAnd: | 183 | case symAnd: |
184 | case symOr: | 184 | case symOr: |
185 | case symXor: | 185 | case symXor: |
186 | return 2; | 186 | return 2; |
187 | 187 | ||
188 | case symExponent: | 188 | case symExponent: |
189 | case symNot: | 189 | case symNot: |
190 | case symNegate: | 190 | case symNegate: |
191 | case symFunction: | 191 | case symFunction: |
192 | return 3; | 192 | return 3; |
193 | 193 | ||
194 | default: | 194 | default: |
195 | return 0; | 195 | return 0; |
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | symType nextToken( const char **sBuf ) | 199 | symType nextToken( const char **sBuf ) |
200 | { | 200 | { |
201 | for(;;) | 201 | for(;;) |
202 | { | 202 | { |
203 | char cbuf = **sBuf; | 203 | char cbuf = **sBuf; |
204 | ++(*sBuf); | 204 | ++(*sBuf); |
205 | switch( cbuf ) | 205 | switch( cbuf ) |
206 | { | 206 | { |
207 | case '+': | 207 | case '+': |
208 | return symAdd; | 208 | return symAdd; |
209 | 209 | ||
210 | case '-': | 210 | case '-': |
211 | return symSubtract; | 211 | return symSubtract; |
212 | 212 | ||
213 | case '*': | 213 | case '*': |
214 | return symMultiply; | 214 | return symMultiply; |
215 | 215 | ||
216 | case '/': | 216 | case '/': |
217 | return symDivide; | 217 | return symDivide; |
218 | 218 | ||
219 | case '^': | 219 | case '^': |
220 | return symExponent; | 220 | return symExponent; |
221 | 221 | ||
222 | case '%': | 222 | case '%': |
223 | return symModulus; | 223 | return symModulus; |
224 | 224 | ||
225 | case '(': | 225 | case '(': |
226 | return symOpenParen; | 226 | return symOpenParen; |
227 | 227 | ||
228 | case ')': | 228 | case ')': |
229 | return symCloseParen; | 229 | return symCloseParen; |
230 | 230 | ||
231 | case '|': | 231 | case '|': |
232 | return symOr; | 232 | return symOr; |
233 | 233 | ||
234 | case '&': | 234 | case '&': |
235 | return symAnd; | 235 | return symAnd; |
236 | 236 | ||
237 | case '#': | 237 | case '#': |
238 | return symXor; | 238 | return symXor; |
239 | 239 | ||
240 | case '~': | 240 | case '~': |
241 | return symNot; | 241 | return symNot; |
242 | 242 | ||
243 | case ' ': | 243 | case ' ': |
244 | case '\t': | 244 | case '\t': |
245 | case '\n': | 245 | case '\n': |
246 | case '\r': | 246 | case '\r': |
247 | break; | 247 | break; |
248 | 248 | ||
249 | case '\0': | 249 | case '\0': |
250 | return symEOS; | 250 | return symEOS; |
251 | 251 | ||
252 | default: | 252 | default: |
253 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) | 253 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) |
254 | { | 254 | { |
255 | char num[50]={cbuf}; | 255 | char num[50]={cbuf}; |
256 | int nPos = 1; | 256 | int nPos = 1; |
257 | bool bDot = false; | 257 | bool bDot = false; |
258 | 258 | ||
259 | for(;;) | 259 | for(;;) |
260 | { | 260 | { |
261 | cbuf = **sBuf; | 261 | cbuf = **sBuf; |
262 | if( cbuf == '.' ) | 262 | if( cbuf == '.' ) |
263 | { | 263 | { |
264 | if( bDot == false ) | 264 | if( bDot == false ) |
265 | bDot = true; | 265 | bDot = true; |
266 | else | 266 | else |
267 | throw FormulaException( | 267 | throw FormulaException( |
268 | "Numbers cannot have more than one " | 268 | "Numbers cannot have more than one " |
269 | ". in them." | 269 | ". in them." |
270 | ); | 270 | ); |
271 | } | 271 | } |
272 | if( cbuf == '.' || | 272 | if( cbuf == '.' || |
273 | (cbuf >= '0' && cbuf <= '9') ) | 273 | (cbuf >= '0' && cbuf <= '9') ) |
274 | { | 274 | { |
275 | num[nPos++] = cbuf; | 275 | num[nPos++] = cbuf; |
276 | } | 276 | } |
277 | else | 277 | else |
278 | { | 278 | { |
279 | num[nPos] = '\0'; | 279 | num[nPos] = '\0'; |
280 | sValue.push( | 280 | sValue.push( |
281 | static_cast<prec>( | 281 | static_cast<prec>( |
282 | strtod( num, NULL ) | 282 | strtod( num, NULL ) |
283 | ) | 283 | ) |
284 | ); | 284 | ); |
285 | return symNumber; | 285 | return symNumber; |
286 | } | 286 | } |
287 | ++(*sBuf); | 287 | ++(*sBuf); |
288 | } | 288 | } |
289 | } | 289 | } |
290 | else if( (cbuf >= 'a' && cbuf <= 'z') || | 290 | else if( (cbuf >= 'a' && cbuf <= 'z') || |
291 | (cbuf >= 'A' && cbuf <= 'Z') || | 291 | (cbuf >= 'A' && cbuf <= 'Z') || |
292 | (cbuf == '_') ) | 292 | (cbuf == '_') ) |
293 | { | 293 | { |
294 | char tok[50]={cbuf}; | 294 | char tok[50]={cbuf}; |
295 | int nPos = 1; | 295 | int nPos = 1; |
296 | 296 | ||
297 | for(;;) | 297 | for(;;) |
298 | { | 298 | { |
299 | cbuf = **sBuf; | 299 | cbuf = **sBuf; |
300 | if( (cbuf >= 'a' && cbuf <= 'z') || | 300 | if( (cbuf >= 'a' && cbuf <= 'z') || |
301 | (cbuf >= 'A' && cbuf <= 'Z') || | 301 | (cbuf >= 'A' && cbuf <= 'Z') || |
302 | (cbuf >= '0' && cbuf <= '9') || | 302 | (cbuf >= '0' && cbuf <= '9') || |
303 | cbuf == '_' || cbuf == '.' || cbuf == ':' ) | 303 | cbuf == '_' || cbuf == '.' || cbuf == ':' ) |
304 | { | 304 | { |
305 | tok[nPos++] = cbuf; | 305 | tok[nPos++] = cbuf; |
306 | } | 306 | } |
307 | else | 307 | else |
308 | { | 308 | { |
309 | tok[nPos] = '\0'; | 309 | tok[nPos] = '\0'; |
310 | if( hVars.has( tok ) ) | 310 | if( hVars.has( tok ) ) |
311 | { | 311 | { |
312 | sValue.push( hVars[tok] ); | 312 | sValue.push( hVars[tok] ); |
313 | return symNumber; | 313 | return symNumber; |
314 | } | 314 | } |
315 | else if( hFunc.has( tok ) ) | 315 | else if( hFunc.has( tok ) ) |
316 | { | 316 | { |
317 | sFunc.push( tok ); | 317 | sFunc.push( tok ); |
318 | return symFunction; | 318 | return symFunction; |
319 | } | 319 | } |
320 | else | 320 | else |
321 | { | 321 | { |
322 | throw FormulaException( | 322 | throw FormulaException( |
323 | "No variable or function named " | 323 | "No variable or function named " |
324 | "\"%s\" exists.", | 324 | "\"%s\" exists.", |
325 | tok | 325 | tok |
326 | ); | 326 | ); |
327 | } | 327 | } |
328 | } | 328 | } |
329 | ++(*sBuf); | 329 | ++(*sBuf); |
330 | } | 330 | } |
331 | } | 331 | } |
332 | break; | 332 | break; |
333 | } | 333 | } |
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
337 | void reduce( bool bCloseParen = false ) | 337 | void reduce( bool bCloseParen = false ) |
338 | { | 338 | { |
339 | while( !sOper.isEmpty() ) | 339 | while( !sOper.isEmpty() ) |
340 | { | 340 | { |
341 | uint8_t nOpr = sOper.top(); | 341 | uint8_t nOpr = sOper.top(); |
342 | if( nOpr == symOpenParen ) | 342 | if( nOpr == symOpenParen ) |
343 | { | 343 | { |
344 | if( bCloseParen == true ) | 344 | if( bCloseParen == true ) |
345 | sOper.pop(); | 345 | sOper.pop(); |
346 | return; | 346 | return; |
347 | } | 347 | } |
348 | sOper.pop(); | 348 | sOper.pop(); |
349 | 349 | ||
350 | prec dTop = sValue.top(); | 350 | prec dTop = sValue.top(); |
351 | sValue.pop(); | 351 | sValue.pop(); |
352 | 352 | ||
353 | switch( nOpr ) | 353 | switch( nOpr ) |
354 | { | 354 | { |
355 | case symAdd: | 355 | case symAdd: |
356 | sValue.top() += dTop; | 356 | sValue.top() += dTop; |
357 | break; | 357 | break; |
358 | 358 | ||
359 | case symSubtract: | 359 | case symSubtract: |
360 | sValue.top() -= dTop; | 360 | sValue.top() -= dTop; |
361 | break; | 361 | break; |
362 | 362 | ||
363 | case symMultiply: | 363 | case symMultiply: |
364 | sValue.top() *= dTop; | 364 | sValue.top() *= dTop; |
365 | break; | 365 | break; |
366 | 366 | ||
367 | case symDivide: | 367 | case symDivide: |
368 | sValue.top() /= dTop; | 368 | sValue.top() /= dTop; |
369 | break; | 369 | break; |
370 | 370 | ||
371 | case symExponent: | 371 | case symExponent: |
372 | sValue.top() = static_cast<prec>( | 372 | sValue.top() = static_cast<prec>( |
373 | pow( sValue.top(), dTop ) | 373 | pow( sValue.top(), dTop ) |
374 | ); | 374 | ); |
375 | break; | 375 | break; |
376 | 376 | ||
377 | case symModulus: | 377 | case symModulus: |
378 | sValue.top() = static_cast<prec>( | 378 | sValue.top() = static_cast<prec>( |
379 | fmod( sValue.top(), dTop ) | 379 | fmod( sValue.top(), dTop ) |
380 | ); | 380 | ); |
381 | break; | 381 | break; |
382 | 382 | ||
383 | case symOr: | 383 | case symOr: |
384 | sValue.top() = static_cast<prec>( | 384 | sValue.top() = static_cast<prec>( |
385 | static_cast<bin>(sValue.top()) | | 385 | static_cast<bin>(sValue.top()) | |
386 | static_cast<bin>(dTop) | 386 | static_cast<bin>(dTop) |
387 | ); | 387 | ); |
388 | break; | 388 | break; |
389 | 389 | ||
390 | case symAnd: | 390 | case symAnd: |
391 | sValue.top() = static_cast<prec>( | 391 | sValue.top() = static_cast<prec>( |
392 | static_cast<bin>(sValue.top()) & | 392 | static_cast<bin>(sValue.top()) & |
393 | static_cast<bin>(dTop) | 393 | static_cast<bin>(dTop) |
394 | ); | 394 | ); |
395 | break; | 395 | break; |
396 | 396 | ||
397 | case symXor: | 397 | case symXor: |
398 | sValue.top() = static_cast<prec>( | 398 | sValue.top() = static_cast<prec>( |
399 | static_cast<bin>(sValue.top()) ^ | 399 | static_cast<bin>(sValue.top()) ^ |
400 | static_cast<bin>(dTop) | 400 | static_cast<bin>(dTop) |
401 | ); | 401 | ); |
402 | break; | 402 | break; |
403 | 403 | ||
404 | case symFunction: | 404 | case symFunction: |
405 | sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); | 405 | sValue.push( (*hFunc.get( sFunc.pop() ))( dTop ) ); |
406 | break; | 406 | break; |
407 | 407 | ||
408 | case symNegate: | 408 | case symNegate: |
409 | sValue.push( -dTop ); | 409 | sValue.push( -dTop ); |
410 | break; | 410 | break; |
411 | 411 | ||
412 | case symNot: | 412 | case symNot: |
413 | sValue.push( static_cast<prec>( | 413 | sValue.push( static_cast<prec>( |
414 | ~static_cast<bin>(dTop) | 414 | ~static_cast<bin>(dTop) |
415 | ) ); | 415 | ) ); |
416 | break; | 416 | break; |
417 | } | 417 | } |
418 | } | 418 | } |
419 | 419 | ||
420 | if( bCloseParen == true ) | 420 | if( bCloseParen == true ) |
421 | { | 421 | { |
422 | throw FormulaException( | 422 | throw FormulaException( |
423 | "Close-paren found without matching open-paren." | 423 | "Close-paren found without matching open-paren." |
424 | ); | 424 | ); |
425 | } | 425 | } |
426 | } | 426 | } |
427 | }; | 427 | }; |
428 | } | 428 | } |
429 | 429 | ||
430 | #endif | 430 | #endif |
diff --git a/src/stable/hash.cpp b/src/stable/hash.cpp index f44104b..85a13c7 100644 --- a/src/stable/hash.cpp +++ b/src/stable/hash.cpp | |||
@@ -12,58 +12,58 @@ namespace Bu { subExceptionDef( HashException ) } | |||
12 | template<> | 12 | template<> |
13 | uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) | 13 | uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) |
14 | { | 14 | { |
15 | if (k == NULL) | 15 | if (k == NULL) |
16 | { | 16 | { |
17 | return 0; | 17 | return 0; |
18 | } | 18 | } |
19 | 19 | ||
20 | unsigned long int nPos = 0; | 20 | unsigned long int nPos = 0; |
21 | for( const char *s = k; *s; s++ ) | 21 | for( const char *s = k; *s; s++ ) |
22 | { | 22 | { |
23 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 23 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
24 | } | 24 | } |
25 | 25 | ||
26 | return nPos; | 26 | return nPos; |
27 | } | 27 | } |
28 | 28 | ||
29 | template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) | 29 | template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) |
30 | { | 30 | { |
31 | if( a == b ) | 31 | if( a == b ) |
32 | return true; | 32 | return true; |
33 | 33 | ||
34 | for(int j=0; a[j] == b[j]; j++ ) | 34 | for(int j=0; a[j] == b[j]; j++ ) |
35 | if( a[j] == '\0' ) | 35 | if( a[j] == '\0' ) |
36 | return true; | 36 | return true; |
37 | 37 | ||
38 | return false; | 38 | return false; |
39 | } | 39 | } |
40 | 40 | ||
41 | template<> | 41 | template<> |
42 | uint32_t Bu::__calcHashCode<char *>( char * const &k ) | 42 | uint32_t Bu::__calcHashCode<char *>( char * const &k ) |
43 | { | 43 | { |
44 | if (k == NULL) | 44 | if (k == NULL) |
45 | { | 45 | { |
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | unsigned long int nPos = 0; | 49 | unsigned long int nPos = 0; |
50 | for( const char *s = k; *s; s++ ) | 50 | for( const char *s = k; *s; s++ ) |
51 | { | 51 | { |
52 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 52 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
53 | } | 53 | } |
54 | 54 | ||
55 | return nPos; | 55 | return nPos; |
56 | } | 56 | } |
57 | 57 | ||
58 | template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) | 58 | template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) |
59 | { | 59 | { |
60 | if( a == b ) | 60 | if( a == b ) |
61 | return true; | 61 | return true; |
62 | 62 | ||
63 | for(int j=0; a[j] == b[j]; j++ ) | 63 | for(int j=0; a[j] == b[j]; j++ ) |
64 | if( a[j] == '\0' ) | 64 | if( a[j] == '\0' ) |
65 | return true; | 65 | return true; |
66 | 66 | ||
67 | return false; | 67 | return false; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/src/stable/hash.h b/src/stable/hash.h index 86f189e..1574a1c 100644 --- a/src/stable/hash.h +++ b/src/stable/hash.h | |||
@@ -17,1311 +17,1311 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( HashException ) | 20 | subExceptionDecl( HashException ) |
21 | 21 | ||
22 | enum eHashException | 22 | enum eHashException |
23 | { | 23 | { |
24 | excodeNotFilled | 24 | excodeNotFilled |
25 | }; | 25 | }; |
26 | 26 | ||
27 | template<typename T> | 27 | template<typename T> |
28 | uint32_t __calcHashCode( const T &k ); | 28 | uint32_t __calcHashCode( const T &k ); |
29 | 29 | ||
30 | template<typename T> | 30 | template<typename T> |
31 | bool __cmpHashKeys( const T &a, const T &b ); | 31 | bool __cmpHashKeys( const T &a, const T &b ); |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Default functor used to compute the size of hash tables. This version | 34 | * Default functor used to compute the size of hash tables. This version |
35 | * effectively doubles the size of the table when space is low, ensuring | 35 | * effectively doubles the size of the table when space is low, ensuring |
36 | * that you always wind up with an odd number for the table size. A | 36 | * that you always wind up with an odd number for the table size. A |
37 | * better but slower option is to always find the next prime number that's | 37 | * better but slower option is to always find the next prime number that's |
38 | * above double your current table size, but that has the potential to be | 38 | * above double your current table size, but that has the potential to be |
39 | * slower. | 39 | * slower. |
40 | */ | 40 | */ |
41 | struct __calcNextTSize_fast | 41 | struct __calcNextTSize_fast |
42 | { | 42 | { |
43 | uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, | 43 | uint32_t operator()( uint32_t nCapacity, uint32_t nFilled, |
44 | uint32_t nDeleted ) const | 44 | uint32_t nDeleted ) const |
45 | { | 45 | { |
46 | // This frist case will allow hashtables that are mostly deleted | 46 | // This frist case will allow hashtables that are mostly deleted |
47 | // items to reset to small allocations | 47 | // items to reset to small allocations |
48 | if( nFilled-nDeleted <= nCapacity/4 ) | 48 | if( nFilled-nDeleted <= nCapacity/4 ) |
49 | { | 49 | { |
50 | nCapacity = 11; | 50 | nCapacity = 11; |
51 | while( nCapacity < nFilled*5/4 ) | 51 | while( nCapacity < nFilled*5/4 ) |
52 | nCapacity = nCapacity*2+1; | 52 | nCapacity = nCapacity*2+1; |
53 | return nCapacity; | 53 | return nCapacity; |
54 | } | 54 | } |
55 | // This will hopefully prevent hash tables from growing needlessly | 55 | // This will hopefully prevent hash tables from growing needlessly |
56 | if( nFilled-nDeleted <= nCapacity/2 ) | 56 | if( nFilled-nDeleted <= nCapacity/2 ) |
57 | { | 57 | { |
58 | if( nDeleted == 0 ) | 58 | if( nDeleted == 0 ) |
59 | return nCapacity/4*5+1; // Grow just a little | 59 | return nCapacity/4*5+1; // Grow just a little |
60 | else | 60 | else |
61 | return nCapacity; // We're going to delete things | 61 | return nCapacity; // We're going to delete things |
62 | } | 62 | } |
63 | // Otherwise, just increase the capacity | 63 | // Otherwise, just increase the capacity |
64 | return nCapacity*2+1; | 64 | return nCapacity*2+1; |
65 | } | 65 | } |
66 | }; | 66 | }; |
67 | 67 | ||
68 | template<typename totype> | 68 | template<typename totype> |
69 | int bitsTo( int iCount ) | 69 | int bitsTo( int iCount ) |
70 | { | 70 | { |
71 | return ( (iCount/(sizeof(totype)*8)) | 71 | return ( (iCount/(sizeof(totype)*8)) |
72 | + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); | 72 | + (iCount%(sizeof(totype)*8)>0 ? 1 : 0)); |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename key, typename value, typename sizecalc, typename keyalloc, | 75 | template<typename key, typename value, typename sizecalc, typename keyalloc, |
76 | typename valuealloc, typename challoc> | 76 | typename valuealloc, typename challoc> |
77 | class Hash; | 77 | class Hash; |
78 | 78 | ||
79 | /** @cond DEVEL */ | 79 | /** @cond DEVEL */ |
80 | template<typename key, typename value, typename sizecalc, typename keyalloc, | 80 | template<typename key, typename value, typename sizecalc, typename keyalloc, |
81 | typename valuealloc, typename challoc > | 81 | typename valuealloc, typename challoc > |
82 | class HashCore | 82 | class HashCore |
83 | { | 83 | { |
84 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 84 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
85 | friend class SharedCore< | 85 | friend class SharedCore< |
86 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, | 86 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, |
87 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> | 87 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> |
88 | >; | 88 | >; |
89 | private: | 89 | private: |
90 | HashCore() : | 90 | HashCore() : |
91 | nCapacity( 0 ), | 91 | nCapacity( 0 ), |
92 | nFilled( 0 ), | 92 | nFilled( 0 ), |
93 | nDeleted( 0 ), | 93 | nDeleted( 0 ), |
94 | bFilled( NULL ), | 94 | bFilled( NULL ), |
95 | bDeleted( NULL ), | 95 | bDeleted( NULL ), |
96 | aKeys( NULL ), | 96 | aKeys( NULL ), |
97 | aValues( NULL ), | 97 | aValues( NULL ), |
98 | aHashCodes( NULL ) | 98 | aHashCodes( NULL ) |
99 | { | 99 | { |
100 | } | 100 | } |
101 | 101 | ||
102 | virtual ~HashCore() | 102 | virtual ~HashCore() |
103 | { | 103 | { |
104 | clear(); | 104 | clear(); |
105 | } | 105 | } |
106 | 106 | ||
107 | void init() | 107 | void init() |
108 | { | 108 | { |
109 | if( nCapacity > 0 ) | 109 | if( nCapacity > 0 ) |
110 | return; | 110 | return; |
111 | 111 | ||
112 | nCapacity = 11; | 112 | nCapacity = 11; |
113 | nKeysSize = bitsTo<uint32_t>( nCapacity ); | 113 | nKeysSize = bitsTo<uint32_t>( nCapacity ); |
114 | bFilled = ca.allocate( nKeysSize ); | 114 | bFilled = ca.allocate( nKeysSize ); |
115 | bDeleted = ca.allocate( nKeysSize ); | 115 | bDeleted = ca.allocate( nKeysSize ); |
116 | clearBits(); | 116 | clearBits(); |
117 | 117 | ||
118 | aHashCodes = ca.allocate( nCapacity ); | 118 | aHashCodes = ca.allocate( nCapacity ); |
119 | aKeys = ka.allocate( nCapacity ); | 119 | aKeys = ka.allocate( nCapacity ); |
120 | aValues = va.allocate( nCapacity ); | 120 | aValues = va.allocate( nCapacity ); |
121 | } | 121 | } |
122 | 122 | ||
123 | void clearBits() | 123 | void clearBits() |
124 | { | 124 | { |
125 | if( nCapacity == 0 ) | 125 | if( nCapacity == 0 ) |
126 | return; | 126 | return; |
127 | 127 | ||
128 | for( uint32_t j = 0; j < nKeysSize; j++ ) | 128 | for( uint32_t j = 0; j < nKeysSize; j++ ) |
129 | { | 129 | { |
130 | bFilled[j] = bDeleted[j] = 0; | 130 | bFilled[j] = bDeleted[j] = 0; |
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) | 134 | void fill( uint32_t loc, const key &k, const value &v, uint32_t hash ) |
135 | { | 135 | { |
136 | init(); | 136 | init(); |
137 | 137 | ||
138 | bFilled[loc/32] |= (1<<(loc%32)); | 138 | bFilled[loc/32] |= (1<<(loc%32)); |
139 | va.construct( &aValues[loc], v ); | 139 | va.construct( &aValues[loc], v ); |
140 | ka.construct( &aKeys[loc], k ); | 140 | ka.construct( &aKeys[loc], k ); |
141 | aHashCodes[loc] = hash; | 141 | aHashCodes[loc] = hash; |
142 | nFilled++; | 142 | nFilled++; |
143 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 143 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
144 | // nFilled, nDeleted, nCapacity ); | 144 | // nFilled, nDeleted, nCapacity ); |
145 | } | 145 | } |
146 | 146 | ||
147 | void _erase( uint32_t loc ) | 147 | void _erase( uint32_t loc ) |
148 | { | 148 | { |
149 | if( nCapacity == 0 ) | 149 | if( nCapacity == 0 ) |
150 | return; | 150 | return; |
151 | 151 | ||
152 | bDeleted[loc/32] |= (1<<(loc%32)); | 152 | bDeleted[loc/32] |= (1<<(loc%32)); |
153 | va.destroy( &aValues[loc] ); | 153 | va.destroy( &aValues[loc] ); |
154 | ka.destroy( &aKeys[loc] ); | 154 | ka.destroy( &aKeys[loc] ); |
155 | nDeleted++; | 155 | nDeleted++; |
156 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 156 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
157 | // nFilled, nDeleted, nCapacity ); | 157 | // nFilled, nDeleted, nCapacity ); |
158 | } | 158 | } |
159 | 159 | ||
160 | key &getKeyAtPos( uint32_t nPos ) | 160 | key &getKeyAtPos( uint32_t nPos ) |
161 | { | 161 | { |
162 | if( nPos >= nCapacity ) | 162 | if( nPos >= nCapacity ) |
163 | throw HashException("Referenced position invalid."); | 163 | throw HashException("Referenced position invalid."); |
164 | return aKeys[nPos]; | 164 | return aKeys[nPos]; |
165 | } | 165 | } |
166 | 166 | ||
167 | const key &getKeyAtPos( uint32_t nPos ) const | 167 | const key &getKeyAtPos( uint32_t nPos ) const |
168 | { | 168 | { |
169 | if( nPos >= nCapacity ) | 169 | if( nPos >= nCapacity ) |
170 | throw HashException("Referenced position invalid."); | 170 | throw HashException("Referenced position invalid."); |
171 | return aKeys[nPos]; | 171 | return aKeys[nPos]; |
172 | } | 172 | } |
173 | 173 | ||
174 | value &getValueAtPos( uint32_t nPos ) | 174 | value &getValueAtPos( uint32_t nPos ) |
175 | { | 175 | { |
176 | if( nPos >= nCapacity ) | 176 | if( nPos >= nCapacity ) |
177 | throw HashException("Referenced position invalid."); | 177 | throw HashException("Referenced position invalid."); |
178 | return aValues[nPos]; | 178 | return aValues[nPos]; |
179 | } | 179 | } |
180 | 180 | ||
181 | const value &getValueAtPos( uint32_t nPos ) const | 181 | const value &getValueAtPos( uint32_t nPos ) const |
182 | { | 182 | { |
183 | if( nPos >= nCapacity ) | 183 | if( nPos >= nCapacity ) |
184 | throw HashException("Referenced position invalid."); | 184 | throw HashException("Referenced position invalid."); |
185 | return aValues[nPos]; | 185 | return aValues[nPos]; |
186 | } | 186 | } |
187 | 187 | ||
188 | uint32_t getFirstPos( bool &bFinished ) const | 188 | uint32_t getFirstPos( bool &bFinished ) const |
189 | { | 189 | { |
190 | for( uint32_t j = 0; j < nCapacity; j++ ) | 190 | for( uint32_t j = 0; j < nCapacity; j++ ) |
191 | { | 191 | { |
192 | if( isFilled( j ) ) | 192 | if( isFilled( j ) ) |
193 | if( !isDeleted( j ) ) | 193 | if( !isDeleted( j ) ) |
194 | return j; | 194 | return j; |
195 | } | 195 | } |
196 | 196 | ||
197 | bFinished = true; | 197 | bFinished = true; |
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const | 201 | uint32_t getNextPos( uint32_t nPos, bool &bFinished ) const |
202 | { | 202 | { |
203 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) | 203 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) |
204 | { | 204 | { |
205 | if( isFilled( j ) ) | 205 | if( isFilled( j ) ) |
206 | if( !isDeleted( j ) ) | 206 | if( !isDeleted( j ) ) |
207 | return j; | 207 | return j; |
208 | } | 208 | } |
209 | 209 | ||
210 | bFinished = true; | 210 | bFinished = true; |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | 213 | ||
214 | uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) | 214 | uint32_t probe( uint32_t hash, const key &k, bool &bFill, bool rehash=true ) |
215 | { | 215 | { |
216 | init(); | 216 | init(); |
217 | 217 | ||
218 | uint32_t nCur = hash%nCapacity; | 218 | uint32_t nCur = hash%nCapacity; |
219 | 219 | ||
220 | // First we scan to see if the key is already there, abort if we | 220 | // First we scan to see if the key is already there, abort if we |
221 | // run out of probing room, or we find a non-filled entry | 221 | // run out of probing room, or we find a non-filled entry |
222 | int8_t j; | 222 | int8_t j; |
223 | for( j = 0; | 223 | for( j = 0; |
224 | isFilled( nCur ) && j < 32; | 224 | isFilled( nCur ) && j < 32; |
225 | nCur = (nCur + (1<<j))%nCapacity, j++ | 225 | nCur = (nCur + (1<<j))%nCapacity, j++ |
226 | ) | 226 | ) |
227 | { | 227 | { |
228 | // Is this the same hash code we were looking for? | 228 | // Is this the same hash code we were looking for? |
229 | if( hash == aHashCodes[nCur] ) | 229 | if( hash == aHashCodes[nCur] ) |
230 | { | 230 | { |
231 | // Skip over deleted entries. Deleted entries are also filled, | 231 | // Skip over deleted entries. Deleted entries are also filled, |
232 | // so we only have to do this check here. | 232 | // so we only have to do this check here. |
233 | if( isDeleted( nCur ) ) | 233 | if( isDeleted( nCur ) ) |
234 | continue; | 234 | continue; |
235 | 235 | ||
236 | // Is it really the same key? (for safety) | 236 | // Is it really the same key? (for safety) |
237 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | 237 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) |
238 | { | 238 | { |
239 | bFill = true; | 239 | bFill = true; |
240 | return nCur; | 240 | return nCur; |
241 | } | 241 | } |
242 | } | 242 | } |
243 | } | 243 | } |
244 | 244 | ||
245 | // This is our insurance, if the table is full, then go ahead and | 245 | // This is our insurance, if the table is full, then go ahead and |
246 | // rehash, then try again. | 246 | // rehash, then try again. |
247 | if( (isFilled( nCur ) || j == 32) && rehash == true ) | 247 | if( (isFilled( nCur ) || j == 32) && rehash == true ) |
248 | { | 248 | { |
249 | reHash( szCalc( nCapacity, nFilled, nDeleted ) ); | 249 | reHash( szCalc( nCapacity, nFilled, nDeleted ) ); |
250 | 250 | ||
251 | // This is potentially dangerous, and could cause an infinite loop. | 251 | // This is potentially dangerous, and could cause an infinite loop. |
252 | // Be careful writing probe, eh? | 252 | // Be careful writing probe, eh? |
253 | return probe( hash, k, bFill ); | 253 | return probe( hash, k, bFill ); |
254 | } | 254 | } |
255 | 255 | ||
256 | bFill = false; | 256 | bFill = false; |
257 | return nCur; | 257 | return nCur; |
258 | } | 258 | } |
259 | 259 | ||
260 | uint32_t probe( uint32_t hash, key k, bool &bFill ) const | 260 | uint32_t probe( uint32_t hash, key k, bool &bFill ) const |
261 | { | 261 | { |
262 | if( nCapacity == 0 ) | 262 | if( nCapacity == 0 ) |
263 | throw Bu::ExceptionBase("Probe in empty hash table."); | 263 | throw Bu::ExceptionBase("Probe in empty hash table."); |
264 | 264 | ||
265 | uint32_t nCur = hash%nCapacity; | 265 | uint32_t nCur = hash%nCapacity; |
266 | 266 | ||
267 | // First we scan to see if the key is already there, abort if we | 267 | // First we scan to see if the key is already there, abort if we |
268 | // run out of probing room, or we find a non-filled entry | 268 | // run out of probing room, or we find a non-filled entry |
269 | for( int8_t j = 0; | 269 | for( int8_t j = 0; |
270 | isFilled( nCur ) && j < 32; | 270 | isFilled( nCur ) && j < 32; |
271 | nCur = (nCur + (1<<j))%nCapacity, j++ | 271 | nCur = (nCur + (1<<j))%nCapacity, j++ |
272 | ) | 272 | ) |
273 | { | 273 | { |
274 | // Is this the same hash code we were looking for? | 274 | // Is this the same hash code we were looking for? |
275 | if( hash == aHashCodes[nCur] ) | 275 | if( hash == aHashCodes[nCur] ) |
276 | { | 276 | { |
277 | // Skip over deleted entries. Deleted entries are also filled, | 277 | // Skip over deleted entries. Deleted entries are also filled, |
278 | // so we only have to do this check here. | 278 | // so we only have to do this check here. |
279 | if( isDeleted( nCur ) ) | 279 | if( isDeleted( nCur ) ) |
280 | continue; | 280 | continue; |
281 | 281 | ||
282 | // Is it really the same key? (for safety) | 282 | // Is it really the same key? (for safety) |
283 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | 283 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) |
284 | { | 284 | { |
285 | bFill = true; | 285 | bFill = true; |
286 | return nCur; | 286 | return nCur; |
287 | } | 287 | } |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
291 | bFill = false; | 291 | bFill = false; |
292 | return nCur; | 292 | return nCur; |
293 | } | 293 | } |
294 | 294 | ||
295 | void insert( const key &k, const value &v ) | 295 | void insert( const key &k, const value &v ) |
296 | { | 296 | { |
297 | uint32_t hash = __calcHashCode( k ); | 297 | uint32_t hash = __calcHashCode( k ); |
298 | bool bFill; | 298 | bool bFill; |
299 | uint32_t nPos = probe( hash, k, bFill ); | 299 | uint32_t nPos = probe( hash, k, bFill ); |
300 | 300 | ||
301 | if( bFill ) | 301 | if( bFill ) |
302 | { | 302 | { |
303 | va.destroy( &aValues[nPos] ); | 303 | va.destroy( &aValues[nPos] ); |
304 | va.construct( &aValues[nPos], v ); | 304 | va.construct( &aValues[nPos], v ); |
305 | } | 305 | } |
306 | else | 306 | else |
307 | { | 307 | { |
308 | fill( nPos, k, v, hash ); | 308 | fill( nPos, k, v, hash ); |
309 | } | 309 | } |
310 | } | 310 | } |
311 | 311 | ||
312 | void reHash( uint32_t nNewSize ) | 312 | void reHash( uint32_t nNewSize ) |
313 | { | 313 | { |
314 | //printf("--rehash: %d --> %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); | 314 | //printf("--rehash: %d --> %d (%d, %d)\n", nCapacity, nNewSize, nFilled, nDeleted ); |
315 | //printf("---REHASH---"); | 315 | //printf("---REHASH---"); |
316 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | 316 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", |
317 | // nFilled, nDeleted, nCapacity ); | 317 | // nFilled, nDeleted, nCapacity ); |
318 | 318 | ||
319 | // Save all the old data | 319 | // Save all the old data |
320 | uint32_t nOldCapacity = nCapacity; | 320 | uint32_t nOldCapacity = nCapacity; |
321 | uint32_t *bOldFilled = bFilled; | 321 | uint32_t *bOldFilled = bFilled; |
322 | uint32_t *aOldHashCodes = aHashCodes; | 322 | uint32_t *aOldHashCodes = aHashCodes; |
323 | uint32_t nOldKeysSize = nKeysSize; | 323 | uint32_t nOldKeysSize = nKeysSize; |
324 | uint32_t *bOldDeleted = bDeleted; | 324 | uint32_t *bOldDeleted = bDeleted; |
325 | value *aOldValues = aValues; | 325 | value *aOldValues = aValues; |
326 | key *aOldKeys = aKeys; | 326 | key *aOldKeys = aKeys; |
327 | 327 | ||
328 | // Calculate new sizes | 328 | // Calculate new sizes |
329 | nCapacity = nNewSize; | 329 | nCapacity = nNewSize; |
330 | nKeysSize = bitsTo<uint32_t>( nCapacity ); | 330 | nKeysSize = bitsTo<uint32_t>( nCapacity ); |
331 | 331 | ||
332 | // Allocate new memory + prep | 332 | // Allocate new memory + prep |
333 | bFilled = ca.allocate( nKeysSize ); | 333 | bFilled = ca.allocate( nKeysSize ); |
334 | bDeleted = ca.allocate( nKeysSize ); | 334 | bDeleted = ca.allocate( nKeysSize ); |
335 | clearBits(); | 335 | clearBits(); |
336 | 336 | ||
337 | aHashCodes = ca.allocate( nCapacity ); | 337 | aHashCodes = ca.allocate( nCapacity ); |
338 | aKeys = ka.allocate( nCapacity ); | 338 | aKeys = ka.allocate( nCapacity ); |
339 | aValues = va.allocate( nCapacity ); | 339 | aValues = va.allocate( nCapacity ); |
340 | 340 | ||
341 | nDeleted = nFilled = 0; | 341 | nDeleted = nFilled = 0; |
342 | 342 | ||
343 | // Re-insert all of the old data (except deleted items) | 343 | // Re-insert all of the old data (except deleted items) |
344 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | 344 | for( uint32_t j = 0; j < nOldCapacity; j++ ) |
345 | { | 345 | { |
346 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | 346 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && |
347 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | 347 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) |
348 | { | 348 | { |
349 | insert( aOldKeys[j], aOldValues[j] ); | 349 | insert( aOldKeys[j], aOldValues[j] ); |
350 | } | 350 | } |
351 | } | 351 | } |
352 | 352 | ||
353 | // Delete all of the old data | 353 | // Delete all of the old data |
354 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | 354 | for( uint32_t j = 0; j < nOldCapacity; j++ ) |
355 | { | 355 | { |
356 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | 356 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && |
357 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | 357 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) |
358 | { | 358 | { |
359 | va.destroy( &aOldValues[j] ); | 359 | va.destroy( &aOldValues[j] ); |
360 | ka.destroy( &aOldKeys[j] ); | 360 | ka.destroy( &aOldKeys[j] ); |
361 | } | 361 | } |
362 | } | 362 | } |
363 | va.deallocate( aOldValues, nOldCapacity ); | 363 | va.deallocate( aOldValues, nOldCapacity ); |
364 | ka.deallocate( aOldKeys, nOldCapacity ); | 364 | ka.deallocate( aOldKeys, nOldCapacity ); |
365 | ca.deallocate( bOldFilled, nOldKeysSize ); | 365 | ca.deallocate( bOldFilled, nOldKeysSize ); |
366 | ca.deallocate( bOldDeleted, nOldKeysSize ); | 366 | ca.deallocate( bOldDeleted, nOldKeysSize ); |
367 | ca.deallocate( aOldHashCodes, nOldCapacity ); | 367 | ca.deallocate( aOldHashCodes, nOldCapacity ); |
368 | } | 368 | } |
369 | 369 | ||
370 | bool isFilled( uint32_t loc ) const | 370 | bool isFilled( uint32_t loc ) const |
371 | { | 371 | { |
372 | if( loc >= nCapacity ) | 372 | if( loc >= nCapacity ) |
373 | throw HashException("Referenced position invalid."); | 373 | throw HashException("Referenced position invalid."); |
374 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; | 374 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; |
375 | } | 375 | } |
376 | 376 | ||
377 | bool isDeleted( uint32_t loc ) const | 377 | bool isDeleted( uint32_t loc ) const |
378 | { | 378 | { |
379 | if( loc >= nCapacity ) | 379 | if( loc >= nCapacity ) |
380 | throw HashException("Referenced position invalid."); | 380 | throw HashException("Referenced position invalid."); |
381 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; | 381 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; |
382 | } | 382 | } |
383 | 383 | ||
384 | void clear() | 384 | void clear() |
385 | { | 385 | { |
386 | for( uint32_t j = 0; j < nCapacity; j++ ) | 386 | for( uint32_t j = 0; j < nCapacity; j++ ) |
387 | { | 387 | { |
388 | if( isFilled( j ) ) | 388 | if( isFilled( j ) ) |
389 | if( !isDeleted( j ) ) | 389 | if( !isDeleted( j ) ) |
390 | { | 390 | { |
391 | va.destroy( &aValues[j] ); | 391 | va.destroy( &aValues[j] ); |
392 | ka.destroy( &aKeys[j] ); | 392 | ka.destroy( &aKeys[j] ); |
393 | } | 393 | } |
394 | } | 394 | } |
395 | va.deallocate( aValues, nCapacity ); | 395 | va.deallocate( aValues, nCapacity ); |
396 | ka.deallocate( aKeys, nCapacity ); | 396 | ka.deallocate( aKeys, nCapacity ); |
397 | ca.deallocate( bFilled, nKeysSize ); | 397 | ca.deallocate( bFilled, nKeysSize ); |
398 | ca.deallocate( bDeleted, nKeysSize ); | 398 | ca.deallocate( bDeleted, nKeysSize ); |
399 | ca.deallocate( aHashCodes, nCapacity ); | 399 | ca.deallocate( aHashCodes, nCapacity ); |
400 | 400 | ||
401 | bFilled = NULL; | 401 | bFilled = NULL; |
402 | bDeleted = NULL; | 402 | bDeleted = NULL; |
403 | aKeys = NULL; | 403 | aKeys = NULL; |
404 | aValues = NULL; | 404 | aValues = NULL; |
405 | aHashCodes = NULL; | 405 | aHashCodes = NULL; |
406 | 406 | ||
407 | nCapacity = 0; | 407 | nCapacity = 0; |
408 | nFilled = 0; | 408 | nFilled = 0; |
409 | nDeleted = 0; | 409 | nDeleted = 0; |
410 | } | 410 | } |
411 | 411 | ||
412 | uint32_t nCapacity; | 412 | uint32_t nCapacity; |
413 | uint32_t nFilled; | 413 | uint32_t nFilled; |
414 | uint32_t nDeleted; | 414 | uint32_t nDeleted; |
415 | uint32_t *bFilled; | 415 | uint32_t *bFilled; |
416 | uint32_t *bDeleted; | 416 | uint32_t *bDeleted; |
417 | uint32_t nKeysSize; | 417 | uint32_t nKeysSize; |
418 | key *aKeys; | 418 | key *aKeys; |
419 | value *aValues; | 419 | value *aValues; |
420 | uint32_t *aHashCodes; | 420 | uint32_t *aHashCodes; |
421 | valuealloc va; | 421 | valuealloc va; |
422 | keyalloc ka; | 422 | keyalloc ka; |
423 | challoc ca; | 423 | challoc ca; |
424 | sizecalc szCalc; | 424 | sizecalc szCalc; |
425 | }; | 425 | }; |
426 | /** @endcond */ | 426 | /** @endcond */ |
427 | 427 | ||
428 | /** | 428 | /** |
429 | * Libbu++ Template Hash Table. This is your average hash table, that uses | 429 | * Libbu++ Template Hash Table. This is your average hash table, that uses |
430 | * template functions in order to do fast, efficient, generalized hashing. | 430 | * template functions in order to do fast, efficient, generalized hashing. |
431 | * It's pretty easy to use, and works well with all other libbu++ types so | 431 | * It's pretty easy to use, and works well with all other libbu++ types so |
432 | * far. | 432 | * far. |
433 | * | 433 | * |
434 | * In order to use it, I recommend the following for all basic usage: | 434 | * In order to use it, I recommend the following for all basic usage: |
435 | *@code | 435 | *@code |
436 | // Define a Hash typedef with strings as keys and ints as values. | 436 | // Define a Hash typedef with strings as keys and ints as values. |
437 | typedef Bu::Hash<Bu::String, int> StrIntHash; | 437 | typedef Bu::Hash<Bu::String, int> StrIntHash; |
438 | 438 | ||
439 | // Create one | 439 | // Create one |
440 | StrIntHash hInts; | 440 | StrIntHash hInts; |
441 | 441 | ||
442 | // Insert some integers | 442 | // Insert some integers |
443 | hInts["one"] = 1; | 443 | hInts["one"] = 1; |
444 | hInts["forty-two"] = 42; | 444 | hInts["forty-two"] = 42; |
445 | hInts.insert("forty two", 42 ); | 445 | hInts.insert("forty two", 42 ); |
446 | 446 | ||
447 | // Get values out of the hash, the last two options are the most explicit, | 447 | // Get values out of the hash, the last two options are the most explicit, |
448 | // and must be used if the hash's value type does not match what you're | 448 | // and must be used if the hash's value type does not match what you're |
449 | // comparing to exactly. | 449 | // comparing to exactly. |
450 | if( hInts["one"] == 1 ) doSomething(); | 450 | if( hInts["one"] == 1 ) doSomething(); |
451 | if( hInts["forty-two"].value() == 42 ) doSomething(); | 451 | if( hInts["forty-two"].value() == 42 ) doSomething(); |
452 | if( hInts.get("forty two") == 42 ) doSomething(); | 452 | if( hInts.get("forty two") == 42 ) doSomething(); |
453 | 453 | ||
454 | // Iterate through the Hash | 454 | // Iterate through the Hash |
455 | for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) | 455 | for( StrIntHash::iterator i = hInts.begin(); i != hInts.end(); i++ ) |
456 | { | 456 | { |
457 | // i.getValue() works too | 457 | // i.getValue() works too |
458 | print("'%s' = %d\n", i.getKey().getStr(), (*i) ); | 458 | print("'%s' = %d\n", i.getKey().getStr(), (*i) ); |
459 | } | 459 | } |
460 | 460 | ||
461 | @endcode | 461 | @endcode |
462 | *@param key (typename) The datatype of the hashtable keys | 462 | *@param key (typename) The datatype of the hashtable keys |
463 | *@param value (typename) The datatype of the hashtable data | 463 | *@param value (typename) The datatype of the hashtable data |
464 | *@param sizecalc (typename) Functor to compute new table size on rehash | 464 | *@param sizecalc (typename) Functor to compute new table size on rehash |
465 | *@param keyalloc (typename) Memory allocator for hashtable keys | 465 | *@param keyalloc (typename) Memory allocator for hashtable keys |
466 | *@param valuealloc (typename) Memory allocator for hashtable values | 466 | *@param valuealloc (typename) Memory allocator for hashtable values |
467 | *@param challoc (typename) Byte allocator for bitflags | 467 | *@param challoc (typename) Byte allocator for bitflags |
468 | *@ingroup Containers | 468 | *@ingroup Containers |
469 | */ | 469 | */ |
470 | template<typename key, typename value, | 470 | template<typename key, typename value, |
471 | typename sizecalc = __calcNextTSize_fast, | 471 | typename sizecalc = __calcNextTSize_fast, |
472 | typename keyalloc = std::allocator<key>, | 472 | typename keyalloc = std::allocator<key>, |
473 | typename valuealloc = std::allocator<value>, | 473 | typename valuealloc = std::allocator<value>, |
474 | typename challoc = std::allocator<uint32_t> | 474 | typename challoc = std::allocator<uint32_t> |
475 | > | 475 | > |
476 | class Hash : public SharedCore< | 476 | class Hash : public SharedCore< |
477 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, | 477 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>, |
478 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> | 478 | HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> |
479 | > | 479 | > |
480 | { | 480 | { |
481 | private: | 481 | private: |
482 | typedef class HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> Core; | 482 | typedef class HashCore<key, value, sizecalc, keyalloc, valuealloc, challoc> Core; |
483 | typedef class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> MyType; | 483 | typedef class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> MyType; |
484 | protected: | 484 | protected: |
485 | using SharedCore<MyType, Core>::core; | 485 | using SharedCore<MyType, Core>::core; |
486 | using SharedCore<MyType, Core>::_hardCopy; | 486 | using SharedCore<MyType, Core>::_hardCopy; |
487 | using SharedCore<MyType, Core>::_resetCore; | 487 | using SharedCore<MyType, Core>::_resetCore; |
488 | using SharedCore<MyType, Core>::_allocateCore; | 488 | using SharedCore<MyType, Core>::_allocateCore; |
489 | 489 | ||
490 | public: | 490 | public: |
491 | Hash() | 491 | Hash() |
492 | { | 492 | { |
493 | } | 493 | } |
494 | 494 | ||
495 | Hash( const MyType &src ) : | 495 | Hash( const MyType &src ) : |
496 | SharedCore<MyType, Core >( src ) | 496 | SharedCore<MyType, Core >( src ) |
497 | { | 497 | { |
498 | } | 498 | } |
499 | 499 | ||
500 | virtual ~Hash() | 500 | virtual ~Hash() |
501 | { | 501 | { |
502 | } | 502 | } |
503 | 503 | ||
504 | /** | 504 | /** |
505 | * Get the current hash table capacity. (Changes at re-hash) | 505 | * Get the current hash table capacity. (Changes at re-hash) |
506 | *@returns (uint32_t) The current capacity. | 506 | *@returns (uint32_t) The current capacity. |
507 | */ | 507 | */ |
508 | uint32_t getCapacity() const | 508 | uint32_t getCapacity() const |
509 | { | 509 | { |
510 | return core->nCapacity; | 510 | return core->nCapacity; |
511 | } | 511 | } |
512 | 512 | ||
513 | /** | 513 | /** |
514 | * Get the number of hash locations spoken for. (Including | 514 | * Get the number of hash locations spoken for. (Including |
515 | * not-yet-cleaned-up deleted items.) | 515 | * not-yet-cleaned-up deleted items.) |
516 | *@returns (uint32_t) The current fill state. | 516 | *@returns (uint32_t) The current fill state. |
517 | */ | 517 | */ |
518 | uint32_t getFill() const | 518 | uint32_t getFill() const |
519 | { | 519 | { |
520 | return core->nFilled; | 520 | return core->nFilled; |
521 | } | 521 | } |
522 | 522 | ||
523 | /** | 523 | /** |
524 | * Get the number of items stored in the hash table. | 524 | * Get the number of items stored in the hash table. |
525 | *@returns (uint32_t) The number of items stored in the hash table. | 525 | *@returns (uint32_t) The number of items stored in the hash table. |
526 | */ | 526 | */ |
527 | uint32_t getSize() const | 527 | uint32_t getSize() const |
528 | { | 528 | { |
529 | return core->nFilled-core->nDeleted; | 529 | return core->nFilled-core->nDeleted; |
530 | } | 530 | } |
531 | 531 | ||
532 | bool isEmpty() const | 532 | bool isEmpty() const |
533 | { | 533 | { |
534 | return (core->nFilled-core->nDeleted) == 0; | 534 | return (core->nFilled-core->nDeleted) == 0; |
535 | } | 535 | } |
536 | 536 | ||
537 | /** | 537 | /** |
538 | * Get the number of items which have been deleted, but not yet | 538 | * Get the number of items which have been deleted, but not yet |
539 | * cleaned up. | 539 | * cleaned up. |
540 | *@returns (uint32_t) The number of deleted items. | 540 | *@returns (uint32_t) The number of deleted items. |
541 | */ | 541 | */ |
542 | uint32_t getDeleted() const | 542 | uint32_t getDeleted() const |
543 | { | 543 | { |
544 | return core->nDeleted; | 544 | return core->nDeleted; |
545 | } | 545 | } |
546 | 546 | ||
547 | struct HashProxy | 547 | struct HashProxy |
548 | { | 548 | { |
549 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 549 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
550 | private: | 550 | private: |
551 | HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : | 551 | HashProxy( MyType &h, const key *k, uint32_t nPos, uint32_t hash ) : |
552 | hsh( h ), | 552 | hsh( h ), |
553 | pKey( k ), | 553 | pKey( k ), |
554 | nPos( nPos ), | 554 | nPos( nPos ), |
555 | hash( hash ), | 555 | hash( hash ), |
556 | bFilled( false ) | 556 | bFilled( false ) |
557 | { | 557 | { |
558 | } | 558 | } |
559 | 559 | ||
560 | HashProxy( MyType &h, uint32_t nPos, value *pValue ) : | 560 | HashProxy( MyType &h, uint32_t nPos, value *pValue ) : |
561 | hsh( h ), | 561 | hsh( h ), |
562 | nPos( nPos ), | 562 | nPos( nPos ), |
563 | pValue( pValue ), | 563 | pValue( pValue ), |
564 | bFilled( true ) | 564 | bFilled( true ) |
565 | { | 565 | { |
566 | } | 566 | } |
567 | 567 | ||
568 | MyType &hsh; | 568 | MyType &hsh; |
569 | const key *pKey; | 569 | const key *pKey; |
570 | uint32_t nPos; | 570 | uint32_t nPos; |
571 | value *pValue; | 571 | value *pValue; |
572 | uint32_t hash; | 572 | uint32_t hash; |
573 | bool bFilled; | 573 | bool bFilled; |
574 | 574 | ||
575 | public: | 575 | public: |
576 | /** | 576 | /** |
577 | * Cast operator for HashProxy. | 577 | * Cast operator for HashProxy. |
578 | *@returns (value_type &) The value the HashProxy is pointing to. | 578 | *@returns (value_type &) The value the HashProxy is pointing to. |
579 | */ | 579 | */ |
580 | operator value &() | 580 | operator value &() |
581 | { | 581 | { |
582 | if( bFilled == false ) | 582 | if( bFilled == false ) |
583 | throw HashException( | 583 | throw HashException( |
584 | excodeNotFilled, | 584 | excodeNotFilled, |
585 | "No data associated with that key." | 585 | "No data associated with that key." |
586 | ); | 586 | ); |
587 | return *pValue; | 587 | return *pValue; |
588 | } | 588 | } |
589 | 589 | ||
590 | /** | 590 | /** |
591 | * Direct function for retrieving a value out of the HashProxy. | 591 | * Direct function for retrieving a value out of the HashProxy. |
592 | *@returns (value_type &) The value pointed to by this HashProxy. | 592 | *@returns (value_type &) The value pointed to by this HashProxy. |
593 | */ | 593 | */ |
594 | value &getValue() | 594 | value &getValue() |
595 | { | 595 | { |
596 | if( bFilled == false ) | 596 | if( bFilled == false ) |
597 | throw HashException( | 597 | throw HashException( |
598 | excodeNotFilled, | 598 | excodeNotFilled, |
599 | "No data associated with that key." | 599 | "No data associated with that key." |
600 | ); | 600 | ); |
601 | return *pValue; | 601 | return *pValue; |
602 | } | 602 | } |
603 | 603 | ||
604 | /** | 604 | /** |
605 | * Whether this HashProxy points to something real or not. | 605 | * Whether this HashProxy points to something real or not. |
606 | */ | 606 | */ |
607 | bool isFilled() | 607 | bool isFilled() |
608 | { | 608 | { |
609 | return bFilled; | 609 | return bFilled; |
610 | } | 610 | } |
611 | 611 | ||
612 | /** | 612 | /** |
613 | * Erase the data pointed to by this HashProxy. | 613 | * Erase the data pointed to by this HashProxy. |
614 | */ | 614 | */ |
615 | void erase() | 615 | void erase() |
616 | { | 616 | { |
617 | if( bFilled ) | 617 | if( bFilled ) |
618 | { | 618 | { |
619 | hsh.core->_erase( nPos ); | 619 | hsh.core->_erase( nPos ); |
620 | } | 620 | } |
621 | } | 621 | } |
622 | 622 | ||
623 | /** | 623 | /** |
624 | * Assign data to this point in the hash table. | 624 | * Assign data to this point in the hash table. |
625 | *@param nval (value_type) the data to assign. | 625 | *@param nval (value_type) the data to assign. |
626 | */ | 626 | */ |
627 | value operator=( value nval ) | 627 | value operator=( value nval ) |
628 | { | 628 | { |
629 | if( bFilled ) | 629 | if( bFilled ) |
630 | { | 630 | { |
631 | hsh.core->va.destroy( &hsh.core->aValues[nPos] ); | 631 | hsh.core->va.destroy( &hsh.core->aValues[nPos] ); |
632 | hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); | 632 | hsh.core->va.construct( &hsh.core->aValues[nPos], nval ); |
633 | } | 633 | } |
634 | else | 634 | else |
635 | { | 635 | { |
636 | hsh.core->fill( nPos, *pKey, nval, hash ); | 636 | hsh.core->fill( nPos, *pKey, nval, hash ); |
637 | } | 637 | } |
638 | 638 | ||
639 | return nval; | 639 | return nval; |
640 | } | 640 | } |
641 | 641 | ||
642 | /** | 642 | /** |
643 | * Pointer extraction operator. Access to members of data pointed to | 643 | * Pointer extraction operator. Access to members of data pointed to |
644 | * by HashProxy. | 644 | * by HashProxy. |
645 | *@returns (value_type *) | 645 | *@returns (value_type *) |
646 | */ | 646 | */ |
647 | value *operator->() | 647 | value *operator->() |
648 | { | 648 | { |
649 | if( bFilled == false ) | 649 | if( bFilled == false ) |
650 | throw HashException( | 650 | throw HashException( |
651 | excodeNotFilled, | 651 | excodeNotFilled, |
652 | "No data associated with that key." | 652 | "No data associated with that key." |
653 | ); | 653 | ); |
654 | return pValue; | 654 | return pValue; |
655 | } | 655 | } |
656 | }; | 656 | }; |
657 | 657 | ||
658 | /** | 658 | /** |
659 | * Hash table index operator | 659 | * Hash table index operator |
660 | *@param k (key_type) Key of data to be retrieved. | 660 | *@param k (key_type) Key of data to be retrieved. |
661 | *@returns (HashProxy) Proxy pointing to the data. | 661 | *@returns (HashProxy) Proxy pointing to the data. |
662 | */ | 662 | */ |
663 | HashProxy operator[]( const key &k ) | 663 | HashProxy operator[]( const key &k ) |
664 | { | 664 | { |
665 | _hardCopy(); | 665 | _hardCopy(); |
666 | 666 | ||
667 | uint32_t hash = __calcHashCode( k ); | 667 | uint32_t hash = __calcHashCode( k ); |
668 | bool bFill; | 668 | bool bFill; |
669 | uint32_t nPos = core->probe( hash, k, bFill ); | 669 | uint32_t nPos = core->probe( hash, k, bFill ); |
670 | 670 | ||
671 | if( bFill ) | 671 | if( bFill ) |
672 | { | 672 | { |
673 | return HashProxy( *this, nPos, &core->aValues[nPos] ); | 673 | return HashProxy( *this, nPos, &core->aValues[nPos] ); |
674 | } | 674 | } |
675 | else | 675 | else |
676 | { | 676 | { |
677 | return HashProxy( *this, &k, nPos, hash ); | 677 | return HashProxy( *this, &k, nPos, hash ); |
678 | } | 678 | } |
679 | } | 679 | } |
680 | 680 | ||
681 | /** | 681 | /** |
682 | * Insert a value (v) under key (k) into the hash table | 682 | * Insert a value (v) under key (k) into the hash table |
683 | *@param k (key_type) Key to list the value under. | 683 | *@param k (key_type) Key to list the value under. |
684 | *@param v (value_type) Value to store in the hash table. | 684 | *@param v (value_type) Value to store in the hash table. |
685 | */ | 685 | */ |
686 | void insert( const key &k, const value &v ) | 686 | void insert( const key &k, const value &v ) |
687 | { | 687 | { |
688 | _hardCopy(); | 688 | _hardCopy(); |
689 | 689 | ||
690 | core->insert( k, v ); | 690 | core->insert( k, v ); |
691 | } | 691 | } |
692 | 692 | ||
693 | /** | 693 | /** |
694 | * Remove a value from the hash table. | 694 | * Remove a value from the hash table. |
695 | *@param k (key_type) The data under this key will be erased. | 695 | *@param k (key_type) The data under this key will be erased. |
696 | */ | 696 | */ |
697 | void erase( const key &k ) | 697 | void erase( const key &k ) |
698 | { | 698 | { |
699 | _hardCopy(); | 699 | _hardCopy(); |
700 | 700 | ||
701 | uint32_t hash = __calcHashCode( k ); | 701 | uint32_t hash = __calcHashCode( k ); |
702 | bool bFill; | 702 | bool bFill; |
703 | uint32_t nPos = core->probe( hash, k, bFill ); | 703 | uint32_t nPos = core->probe( hash, k, bFill ); |
704 | 704 | ||
705 | if( bFill ) | 705 | if( bFill ) |
706 | { | 706 | { |
707 | core->_erase( nPos ); | 707 | core->_erase( nPos ); |
708 | } | 708 | } |
709 | } | 709 | } |
710 | 710 | ||
711 | struct iterator; | 711 | struct iterator; |
712 | 712 | ||
713 | /** | 713 | /** |
714 | * Remove a value from the hash pointed to from an iterator. | 714 | * Remove a value from the hash pointed to from an iterator. |
715 | *@param i (iterator &) The data to be erased. | 715 | *@param i (iterator &) The data to be erased. |
716 | */ | 716 | */ |
717 | void erase( struct iterator &i ) | 717 | void erase( struct iterator &i ) |
718 | { | 718 | { |
719 | if( this != i.hsh ) | 719 | if( this != i.hsh ) |
720 | throw HashException("This iterator didn't come from this Hash."); | 720 | throw HashException("This iterator didn't come from this Hash."); |
721 | 721 | ||
722 | _hardCopy(); | 722 | _hardCopy(); |
723 | 723 | ||
724 | if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) | 724 | if( core->isFilled( i.nPos ) && !core->isDeleted( i.nPos ) ) |
725 | { | 725 | { |
726 | core->_erase( i.nPos ); | 726 | core->_erase( i.nPos ); |
727 | } | 727 | } |
728 | } | 728 | } |
729 | 729 | ||
730 | /** | 730 | /** |
731 | * Remove all data from the hash table. | 731 | * Remove all data from the hash table. |
732 | */ | 732 | */ |
733 | virtual void clear() | 733 | virtual void clear() |
734 | { | 734 | { |
735 | _resetCore(); | 735 | _resetCore(); |
736 | } | 736 | } |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * Get an item of data from the hash table. | 739 | * Get an item of data from the hash table. |
740 | *@param k (key_type) Key pointing to the data to be retrieved. | 740 | *@param k (key_type) Key pointing to the data to be retrieved. |
741 | *@returns (value_type &) The data pointed to by (k). | 741 | *@returns (value_type &) The data pointed to by (k). |
742 | */ | 742 | */ |
743 | value &get( const key &k ) | 743 | value &get( const key &k ) |
744 | { | 744 | { |
745 | _hardCopy(); | 745 | _hardCopy(); |
746 | 746 | ||
747 | uint32_t hash = __calcHashCode( k ); | 747 | uint32_t hash = __calcHashCode( k ); |
748 | bool bFill; | 748 | bool bFill; |
749 | uint32_t nPos = core->probe( hash, k, bFill, false ); | 749 | uint32_t nPos = core->probe( hash, k, bFill, false ); |
750 | 750 | ||
751 | if( bFill ) | 751 | if( bFill ) |
752 | { | 752 | { |
753 | return core->aValues[nPos]; | 753 | return core->aValues[nPos]; |
754 | } | 754 | } |
755 | else | 755 | else |
756 | { | 756 | { |
757 | throw HashException( | 757 | throw HashException( |
758 | excodeNotFilled, | 758 | excodeNotFilled, |
759 | "No data associated with that key." | 759 | "No data associated with that key." |
760 | ); | 760 | ); |
761 | } | 761 | } |
762 | } | 762 | } |
763 | 763 | ||
764 | /** | 764 | /** |
765 | * Get a const item of data from the hash table. | 765 | * Get a const item of data from the hash table. |
766 | *@param k (key_type) Key pointing to the data to be retrieved. | 766 | *@param k (key_type) Key pointing to the data to be retrieved. |
767 | *@returns (const value_type &) A const version of the data pointed | 767 | *@returns (const value_type &) A const version of the data pointed |
768 | * to by (k). | 768 | * to by (k). |
769 | */ | 769 | */ |
770 | const value &get( const key &k ) const | 770 | const value &get( const key &k ) const |
771 | { | 771 | { |
772 | uint32_t hash = __calcHashCode( k ); | 772 | uint32_t hash = __calcHashCode( k ); |
773 | bool bFill; | 773 | bool bFill; |
774 | uint32_t nPos = core->probe( hash, k, bFill ); | 774 | uint32_t nPos = core->probe( hash, k, bFill ); |
775 | 775 | ||
776 | if( bFill ) | 776 | if( bFill ) |
777 | { | 777 | { |
778 | return core->aValues[nPos]; | 778 | return core->aValues[nPos]; |
779 | } | 779 | } |
780 | else | 780 | else |
781 | { | 781 | { |
782 | throw HashException( | 782 | throw HashException( |
783 | excodeNotFilled, | 783 | excodeNotFilled, |
784 | "No data associated with that key." | 784 | "No data associated with that key." |
785 | ); | 785 | ); |
786 | } | 786 | } |
787 | } | 787 | } |
788 | 788 | ||
789 | /** | 789 | /** |
790 | * Does the hash table contain an item under key (k). | 790 | * Does the hash table contain an item under key (k). |
791 | *@param k (key_type) The key to check. | 791 | *@param k (key_type) The key to check. |
792 | *@returns (bool) Whether there was an item in the hash under key (k). | 792 | *@returns (bool) Whether there was an item in the hash under key (k). |
793 | */ | 793 | */ |
794 | bool has( const key &k ) const | 794 | bool has( const key &k ) const |
795 | { | 795 | { |
796 | bool bFill; | 796 | bool bFill; |
797 | core->probe( __calcHashCode( k ), k, bFill ); | 797 | core->probe( __calcHashCode( k ), k, bFill ); |
798 | 798 | ||
799 | return bFill; | 799 | return bFill; |
800 | } | 800 | } |
801 | 801 | ||
802 | /** | 802 | /** |
803 | * Iteration structure for iterating through the hash. | 803 | * Iteration structure for iterating through the hash. |
804 | */ | 804 | */ |
805 | typedef struct iterator | 805 | typedef struct iterator |
806 | { | 806 | { |
807 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 807 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
808 | private: | 808 | private: |
809 | iterator( MyType *hsh ) : | 809 | iterator( MyType *hsh ) : |
810 | hsh( hsh ), | 810 | hsh( hsh ), |
811 | nPos( 0 ), | 811 | nPos( 0 ), |
812 | bFinished( false ) | 812 | bFinished( false ) |
813 | { | 813 | { |
814 | nPos = hsh->core->getFirstPos( bFinished ); | 814 | nPos = hsh->core->getFirstPos( bFinished ); |
815 | } | 815 | } |
816 | 816 | ||
817 | iterator( MyType *hsh, bool bDone ) : | 817 | iterator( MyType *hsh, bool bDone ) : |
818 | hsh( hsh ), | 818 | hsh( hsh ), |
819 | nPos( 0 ), | 819 | nPos( 0 ), |
820 | bFinished( bDone ) | 820 | bFinished( bDone ) |
821 | { | 821 | { |
822 | } | 822 | } |
823 | 823 | ||
824 | MyType *hsh; | 824 | MyType *hsh; |
825 | uint32_t nPos; | 825 | uint32_t nPos; |
826 | bool bFinished; | 826 | bool bFinished; |
827 | 827 | ||
828 | public: | 828 | public: |
829 | iterator( const iterator &i ) : | 829 | iterator( const iterator &i ) : |
830 | hsh( i.hsh ), | 830 | hsh( i.hsh ), |
831 | nPos( i.nPos ), | 831 | nPos( i.nPos ), |
832 | bFinished( i.bFinished ) | 832 | bFinished( i.bFinished ) |
833 | { | 833 | { |
834 | } | 834 | } |
835 | 835 | ||
836 | iterator() : | 836 | iterator() : |
837 | hsh( NULL ), | 837 | hsh( NULL ), |
838 | nPos( NULL ), | 838 | nPos( NULL ), |
839 | bFinished( true ) | 839 | bFinished( true ) |
840 | { | 840 | { |
841 | } | 841 | } |
842 | 842 | ||
843 | bool isValid() const | 843 | bool isValid() const |
844 | { | 844 | { |
845 | return !bFinished; | 845 | return !bFinished; |
846 | } | 846 | } |
847 | 847 | ||
848 | operator bool() const | 848 | operator bool() const |
849 | { | 849 | { |
850 | return !bFinished; | 850 | return !bFinished; |
851 | } | 851 | } |
852 | 852 | ||
853 | /** | 853 | /** |
854 | * Iterator incrementation operator. Move the iterator forward. | 854 | * Iterator incrementation operator. Move the iterator forward. |
855 | */ | 855 | */ |
856 | iterator operator++( int ) | 856 | iterator operator++( int ) |
857 | { | 857 | { |
858 | if( bFinished == false ) | 858 | if( bFinished == false ) |
859 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 859 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
860 | 860 | ||
861 | return *this; | 861 | return *this; |
862 | } | 862 | } |
863 | 863 | ||
864 | /** | 864 | /** |
865 | * Iterator incrementation operator. Move the iterator forward. | 865 | * Iterator incrementation operator. Move the iterator forward. |
866 | */ | 866 | */ |
867 | iterator operator++() | 867 | iterator operator++() |
868 | { | 868 | { |
869 | if( bFinished == false ) | 869 | if( bFinished == false ) |
870 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 870 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
871 | 871 | ||
872 | return *this; | 872 | return *this; |
873 | } | 873 | } |
874 | 874 | ||
875 | /** | 875 | /** |
876 | * Iterator equality comparison operator. Iterators the same? | 876 | * Iterator equality comparison operator. Iterators the same? |
877 | */ | 877 | */ |
878 | bool operator==( const iterator &oth ) const | 878 | bool operator==( const iterator &oth ) const |
879 | { | 879 | { |
880 | if( bFinished != oth.bFinished ) | 880 | if( bFinished != oth.bFinished ) |
881 | return false; | 881 | return false; |
882 | if( bFinished == true ) | 882 | if( bFinished == true ) |
883 | { | 883 | { |
884 | return true; | 884 | return true; |
885 | } | 885 | } |
886 | else | 886 | else |
887 | { | 887 | { |
888 | if( oth.nPos == nPos ) | 888 | if( oth.nPos == nPos ) |
889 | return true; | 889 | return true; |
890 | return false; | 890 | return false; |
891 | } | 891 | } |
892 | } | 892 | } |
893 | 893 | ||
894 | /** | 894 | /** |
895 | * Iterator not equality comparison operator. Not the same? | 895 | * Iterator not equality comparison operator. Not the same? |
896 | */ | 896 | */ |
897 | bool operator!=( const iterator &oth ) const | 897 | bool operator!=( const iterator &oth ) const |
898 | { | 898 | { |
899 | return !(*this == oth ); | 899 | return !(*this == oth ); |
900 | } | 900 | } |
901 | 901 | ||
902 | /** | 902 | /** |
903 | * Iterator assignment operator. | 903 | * Iterator assignment operator. |
904 | */ | 904 | */ |
905 | iterator operator=( const iterator &oth ) | 905 | iterator operator=( const iterator &oth ) |
906 | { | 906 | { |
907 | hsh = oth.hsh; | 907 | hsh = oth.hsh; |
908 | nPos = oth.nPos; | 908 | nPos = oth.nPos; |
909 | bFinished = oth.bFinished; | 909 | bFinished = oth.bFinished; |
910 | return *this; | 910 | return *this; |
911 | } | 911 | } |
912 | 912 | ||
913 | /** | 913 | /** |
914 | * Iterator dereference operator... err.. get the value | 914 | * Iterator dereference operator... err.. get the value |
915 | *@returns (value_type &) The value behind this iterator. | 915 | *@returns (value_type &) The value behind this iterator. |
916 | */ | 916 | */ |
917 | value &operator *() | 917 | value &operator *() |
918 | { | 918 | { |
919 | hsh->_hardCopy(); | 919 | hsh->_hardCopy(); |
920 | return hsh->core->getValueAtPos( nPos ); | 920 | return hsh->core->getValueAtPos( nPos ); |
921 | } | 921 | } |
922 | 922 | ||
923 | const value &operator *() const | 923 | const value &operator *() const |
924 | { | 924 | { |
925 | return hsh->core->getValueAtPos( nPos ); | 925 | return hsh->core->getValueAtPos( nPos ); |
926 | } | 926 | } |
927 | 927 | ||
928 | /** | 928 | /** |
929 | * Get the key behind this iterator. | 929 | * Get the key behind this iterator. |
930 | *@returns (key_type &) The key behind this iterator. | 930 | *@returns (key_type &) The key behind this iterator. |
931 | */ | 931 | */ |
932 | const key &getKey() const | 932 | const key &getKey() const |
933 | { | 933 | { |
934 | return hsh->core->getKeyAtPos( nPos ); | 934 | return hsh->core->getKeyAtPos( nPos ); |
935 | } | 935 | } |
936 | 936 | ||
937 | /** | 937 | /** |
938 | * Get the value behind this iterator. | 938 | * Get the value behind this iterator. |
939 | *@returns (value_type &) The value behind this iterator. | 939 | *@returns (value_type &) The value behind this iterator. |
940 | */ | 940 | */ |
941 | value &getValue() | 941 | value &getValue() |
942 | { | 942 | { |
943 | hsh->_hardCopy(); | 943 | hsh->_hardCopy(); |
944 | return hsh->core->getValueAtPos( nPos ); | 944 | return hsh->core->getValueAtPos( nPos ); |
945 | } | 945 | } |
946 | 946 | ||
947 | /** | 947 | /** |
948 | * Get the value behind this iterator. | 948 | * Get the value behind this iterator. |
949 | *@returns (value_type &) The value behind this iterator. | 949 | *@returns (value_type &) The value behind this iterator. |
950 | */ | 950 | */ |
951 | const value &getValue() const | 951 | const value &getValue() const |
952 | { | 952 | { |
953 | return hsh->core->getValueAtPos( nPos ); | 953 | return hsh->core->getValueAtPos( nPos ); |
954 | } | 954 | } |
955 | } iterator; | 955 | } iterator; |
956 | 956 | ||
957 | /** | 957 | /** |
958 | * Iteration structure for iterating through the hash (const). | 958 | * Iteration structure for iterating through the hash (const). |
959 | */ | 959 | */ |
960 | typedef struct const_iterator | 960 | typedef struct const_iterator |
961 | { | 961 | { |
962 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | 962 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; |
963 | private: | 963 | private: |
964 | const_iterator( const MyType *hsh ) : | 964 | const_iterator( const MyType *hsh ) : |
965 | hsh( hsh ), | 965 | hsh( hsh ), |
966 | nPos( 0 ), | 966 | nPos( 0 ), |
967 | bFinished( false ) | 967 | bFinished( false ) |
968 | { | 968 | { |
969 | nPos = hsh->core->getFirstPos( bFinished ); | 969 | nPos = hsh->core->getFirstPos( bFinished ); |
970 | } | 970 | } |
971 | 971 | ||
972 | const_iterator( const MyType *hsh, bool bDone ) : | 972 | const_iterator( const MyType *hsh, bool bDone ) : |
973 | hsh( hsh ), | 973 | hsh( hsh ), |
974 | nPos( 0 ), | 974 | nPos( 0 ), |
975 | bFinished( bDone ) | 975 | bFinished( bDone ) |
976 | { | 976 | { |
977 | } | 977 | } |
978 | 978 | ||
979 | const MyType *hsh; | 979 | const MyType *hsh; |
980 | uint32_t nPos; | 980 | uint32_t nPos; |
981 | bool bFinished; | 981 | bool bFinished; |
982 | 982 | ||
983 | public: | 983 | public: |
984 | const_iterator() : | 984 | const_iterator() : |
985 | hsh( NULL ), | 985 | hsh( NULL ), |
986 | nPos( 0 ), | 986 | nPos( 0 ), |
987 | bFinished( true ) | 987 | bFinished( true ) |
988 | { | 988 | { |
989 | } | 989 | } |
990 | 990 | ||
991 | const_iterator( const const_iterator &src ) : | 991 | const_iterator( const const_iterator &src ) : |
992 | hsh( src.hsh ), | 992 | hsh( src.hsh ), |
993 | nPos( src.nPos ), | 993 | nPos( src.nPos ), |
994 | bFinished( src.bFinished ) | 994 | bFinished( src.bFinished ) |
995 | { | 995 | { |
996 | } | 996 | } |
997 | 997 | ||
998 | const_iterator( const iterator &src ) : | 998 | const_iterator( const iterator &src ) : |
999 | hsh( src.hsh ), | 999 | hsh( src.hsh ), |
1000 | nPos( src.nPos ), | 1000 | nPos( src.nPos ), |
1001 | bFinished( src.bFinished ) | 1001 | bFinished( src.bFinished ) |
1002 | { | 1002 | { |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | bool isValid() const | 1005 | bool isValid() const |
1006 | { | 1006 | { |
1007 | return !bFinished; | 1007 | return !bFinished; |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | operator bool() const | 1010 | operator bool() const |
1011 | { | 1011 | { |
1012 | return !bFinished; | 1012 | return !bFinished; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | /** | 1015 | /** |
1016 | * Iterator incrementation operator. Move the iterator forward. | 1016 | * Iterator incrementation operator. Move the iterator forward. |
1017 | */ | 1017 | */ |
1018 | const_iterator operator++( int ) | 1018 | const_iterator operator++( int ) |
1019 | { | 1019 | { |
1020 | if( bFinished == false ) | 1020 | if( bFinished == false ) |
1021 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 1021 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
1022 | 1022 | ||
1023 | return *this; | 1023 | return *this; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | /** | 1026 | /** |
1027 | * Iterator incrementation operator. Move the iterator forward. | 1027 | * Iterator incrementation operator. Move the iterator forward. |
1028 | */ | 1028 | */ |
1029 | const_iterator operator++() | 1029 | const_iterator operator++() |
1030 | { | 1030 | { |
1031 | if( bFinished == false ) | 1031 | if( bFinished == false ) |
1032 | nPos = hsh->core->getNextPos( nPos, bFinished ); | 1032 | nPos = hsh->core->getNextPos( nPos, bFinished ); |
1033 | 1033 | ||
1034 | return *this; | 1034 | return *this; |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | /** | 1037 | /** |
1038 | * Iterator equality comparison operator. Iterators the same? | 1038 | * Iterator equality comparison operator. Iterators the same? |
1039 | */ | 1039 | */ |
1040 | bool operator==( const const_iterator &oth ) const | 1040 | bool operator==( const const_iterator &oth ) const |
1041 | { | 1041 | { |
1042 | if( bFinished != oth.bFinished ) | 1042 | if( bFinished != oth.bFinished ) |
1043 | return false; | 1043 | return false; |
1044 | if( bFinished == true ) | 1044 | if( bFinished == true ) |
1045 | { | 1045 | { |
1046 | return true; | 1046 | return true; |
1047 | } | 1047 | } |
1048 | else | 1048 | else |
1049 | { | 1049 | { |
1050 | if( oth.nPos == nPos ) | 1050 | if( oth.nPos == nPos ) |
1051 | return true; | 1051 | return true; |
1052 | return false; | 1052 | return false; |
1053 | } | 1053 | } |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | /** | 1056 | /** |
1057 | * Iterator not equality comparison operator. Not the same? | 1057 | * Iterator not equality comparison operator. Not the same? |
1058 | */ | 1058 | */ |
1059 | bool operator!=( const const_iterator &oth ) const | 1059 | bool operator!=( const const_iterator &oth ) const |
1060 | { | 1060 | { |
1061 | return !(*this == oth ); | 1061 | return !(*this == oth ); |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | /** | 1064 | /** |
1065 | * Iterator assignment operator. | 1065 | * Iterator assignment operator. |
1066 | */ | 1066 | */ |
1067 | const_iterator operator=( const const_iterator &oth ) | 1067 | const_iterator operator=( const const_iterator &oth ) |
1068 | { | 1068 | { |
1069 | hsh = oth.hsh; | 1069 | hsh = oth.hsh; |
1070 | nPos = oth.nPos; | 1070 | nPos = oth.nPos; |
1071 | bFinished = oth.bFinished; | 1071 | bFinished = oth.bFinished; |
1072 | return *this; | 1072 | return *this; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | /** | 1075 | /** |
1076 | * Iterator dereference operator... err.. get the value | 1076 | * Iterator dereference operator... err.. get the value |
1077 | *@returns (value_type &) The value behind this iterator. | 1077 | *@returns (value_type &) The value behind this iterator. |
1078 | */ | 1078 | */ |
1079 | const value &operator *() const | 1079 | const value &operator *() const |
1080 | { | 1080 | { |
1081 | return hsh->core->getValueAtPos( nPos ); | 1081 | return hsh->core->getValueAtPos( nPos ); |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | /** | 1084 | /** |
1085 | * Get the key behind this iterator. | 1085 | * Get the key behind this iterator. |
1086 | *@returns (key_type &) The key behind this iterator. | 1086 | *@returns (key_type &) The key behind this iterator. |
1087 | */ | 1087 | */ |
1088 | const key &getKey() const | 1088 | const key &getKey() const |
1089 | { | 1089 | { |
1090 | return hsh->core->getKeyAtPos( nPos ); | 1090 | return hsh->core->getKeyAtPos( nPos ); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /** | 1093 | /** |
1094 | * Get the value behind this iterator. | 1094 | * Get the value behind this iterator. |
1095 | *@returns (value_type &) The value behind this iterator. | 1095 | *@returns (value_type &) The value behind this iterator. |
1096 | */ | 1096 | */ |
1097 | const value &getValue() const | 1097 | const value &getValue() const |
1098 | { | 1098 | { |
1099 | return hsh->core->getValueAtPos( nPos ); | 1099 | return hsh->core->getValueAtPos( nPos ); |
1100 | } | 1100 | } |
1101 | } const_iterator; | 1101 | } const_iterator; |
1102 | 1102 | ||
1103 | /** | 1103 | /** |
1104 | * Get an iterator pointing to the first item in the hash table. | 1104 | * Get an iterator pointing to the first item in the hash table. |
1105 | *@returns (iterator) An iterator pointing to the first item in the | 1105 | *@returns (iterator) An iterator pointing to the first item in the |
1106 | * hash table. | 1106 | * hash table. |
1107 | */ | 1107 | */ |
1108 | iterator begin() | 1108 | iterator begin() |
1109 | { | 1109 | { |
1110 | return iterator( this ); | 1110 | return iterator( this ); |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | const_iterator begin() const | 1113 | const_iterator begin() const |
1114 | { | 1114 | { |
1115 | return const_iterator( this ); | 1115 | return const_iterator( this ); |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /** | 1118 | /** |
1119 | * Get an iterator pointing to a point just past the last item in the | 1119 | * Get an iterator pointing to a point just past the last item in the |
1120 | * hash table. | 1120 | * hash table. |
1121 | *@returns (iterator) An iterator pointing to a point just past the | 1121 | *@returns (iterator) An iterator pointing to a point just past the |
1122 | * last item in the hash table. | 1122 | * last item in the hash table. |
1123 | */ | 1123 | */ |
1124 | iterator end() | 1124 | iterator end() |
1125 | { | 1125 | { |
1126 | return iterator( this, true ); | 1126 | return iterator( this, true ); |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | const_iterator end() const | 1129 | const_iterator end() const |
1130 | { | 1130 | { |
1131 | return const_iterator( this, true ); | 1131 | return const_iterator( this, true ); |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | /** | 1134 | /** |
1135 | * Get a list of all the keys in the hash table. | 1135 | * Get a list of all the keys in the hash table. |
1136 | *@returns (std::list<key_type>) The list of keys in the hash table. | 1136 | *@returns (std::list<key_type>) The list of keys in the hash table. |
1137 | */ | 1137 | */ |
1138 | Bu::List<key> getKeys() const | 1138 | Bu::List<key> getKeys() const |
1139 | { | 1139 | { |
1140 | Bu::List<key> lKeys; | 1140 | Bu::List<key> lKeys; |
1141 | 1141 | ||
1142 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1142 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1143 | { | 1143 | { |
1144 | if( core->isFilled( j ) ) | 1144 | if( core->isFilled( j ) ) |
1145 | { | 1145 | { |
1146 | if( !core->isDeleted( j ) ) | 1146 | if( !core->isDeleted( j ) ) |
1147 | { | 1147 | { |
1148 | lKeys.append( core->aKeys[j] ); | 1148 | lKeys.append( core->aKeys[j] ); |
1149 | } | 1149 | } |
1150 | } | 1150 | } |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | return lKeys; | 1153 | return lKeys; |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | Bu::List<value> getValues() const | 1156 | Bu::List<value> getValues() const |
1157 | { | 1157 | { |
1158 | Bu::List<value> lValues; | 1158 | Bu::List<value> lValues; |
1159 | 1159 | ||
1160 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1160 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1161 | { | 1161 | { |
1162 | if( core->isFilled( j ) ) | 1162 | if( core->isFilled( j ) ) |
1163 | { | 1163 | { |
1164 | if( !core->isDeleted( j ) ) | 1164 | if( !core->isDeleted( j ) ) |
1165 | { | 1165 | { |
1166 | lValues.append( core->aValues[j] ); | 1166 | lValues.append( core->aValues[j] ); |
1167 | } | 1167 | } |
1168 | } | 1168 | } |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | return lValues; | 1171 | return lValues; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | bool operator==( const MyType &rhs ) const | 1174 | bool operator==( const MyType &rhs ) const |
1175 | { | 1175 | { |
1176 | if( this == &rhs ) | 1176 | if( this == &rhs ) |
1177 | return true; | 1177 | return true; |
1178 | if( core == rhs.core ) | 1178 | if( core == rhs.core ) |
1179 | return true; | 1179 | return true; |
1180 | if( core == NULL || rhs.core == NULL ) | 1180 | if( core == NULL || rhs.core == NULL ) |
1181 | return false; | 1181 | return false; |
1182 | if( getSize() != rhs.getSize() ) | 1182 | if( getSize() != rhs.getSize() ) |
1183 | return false; | 1183 | return false; |
1184 | 1184 | ||
1185 | for( uint32_t j = 0; j < core->nCapacity; j++ ) | 1185 | for( uint32_t j = 0; j < core->nCapacity; j++ ) |
1186 | { | 1186 | { |
1187 | if( core->isFilled( j ) ) | 1187 | if( core->isFilled( j ) ) |
1188 | { | 1188 | { |
1189 | if( !core->isDeleted( j ) ) | 1189 | if( !core->isDeleted( j ) ) |
1190 | { | 1190 | { |
1191 | // Check to see if this key is in the other hash | 1191 | // Check to see if this key is in the other hash |
1192 | if( rhs.has( core->aKeys[j] ) ) | 1192 | if( rhs.has( core->aKeys[j] ) ) |
1193 | { | 1193 | { |
1194 | if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) | 1194 | if( !(core->aValues[j] == rhs.get( core->aKeys[j]) ) ) |
1195 | { | 1195 | { |
1196 | return false; | 1196 | return false; |
1197 | } | 1197 | } |
1198 | } | 1198 | } |
1199 | else | 1199 | else |
1200 | { | 1200 | { |
1201 | return false; | 1201 | return false; |
1202 | } | 1202 | } |
1203 | } | 1203 | } |
1204 | } | 1204 | } |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | return true; | 1207 | return true; |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | bool operator!=( const MyType &rhs ) const | 1210 | bool operator!=( const MyType &rhs ) const |
1211 | { | 1211 | { |
1212 | return !(*this == rhs); | 1212 | return !(*this == rhs); |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | MyType &operator+=( const MyType &rhs ) | 1215 | MyType &operator+=( const MyType &rhs ) |
1216 | { | 1216 | { |
1217 | if( this == &rhs ) | 1217 | if( this == &rhs ) |
1218 | return *this; | 1218 | return *this; |
1219 | if( core == rhs.core ) | 1219 | if( core == rhs.core ) |
1220 | return *this; | 1220 | return *this; |
1221 | if( core == NULL || rhs.core == NULL ) | 1221 | if( core == NULL || rhs.core == NULL ) |
1222 | return *this; | 1222 | return *this; |
1223 | 1223 | ||
1224 | for( const_iterator i = rhs.begin(); i; i++ ) | 1224 | for( const_iterator i = rhs.begin(); i; i++ ) |
1225 | insert( i.getKey(), i.getValue() ); | 1225 | insert( i.getKey(), i.getValue() ); |
1226 | 1226 | ||
1227 | return *this; | 1227 | return *this; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | protected: | 1230 | protected: |
1231 | virtual Core *_copyCore( Core *src ) | 1231 | virtual Core *_copyCore( Core *src ) |
1232 | { | 1232 | { |
1233 | Core *pRet = _allocateCore(); | 1233 | Core *pRet = _allocateCore(); |
1234 | 1234 | ||
1235 | pRet->nFilled = 0; | 1235 | pRet->nFilled = 0; |
1236 | pRet->nDeleted = 0; | 1236 | pRet->nDeleted = 0; |
1237 | pRet->nCapacity = src->nCapacity; | 1237 | pRet->nCapacity = src->nCapacity; |
1238 | pRet->nKeysSize = bitsTo<uint32_t>( pRet->nCapacity ); | 1238 | pRet->nKeysSize = bitsTo<uint32_t>( pRet->nCapacity ); |
1239 | pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); | 1239 | pRet->bFilled = pRet->ca.allocate( pRet->nKeysSize ); |
1240 | pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); | 1240 | pRet->bDeleted = pRet->ca.allocate( pRet->nKeysSize ); |
1241 | pRet->clearBits(); | 1241 | pRet->clearBits(); |
1242 | 1242 | ||
1243 | pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); | 1243 | pRet->aHashCodes = pRet->ca.allocate( pRet->nCapacity ); |
1244 | pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); | 1244 | pRet->aKeys = pRet->ka.allocate( pRet->nCapacity ); |
1245 | pRet->aValues = pRet->va.allocate( pRet->nCapacity ); | 1245 | pRet->aValues = pRet->va.allocate( pRet->nCapacity ); |
1246 | 1246 | ||
1247 | for( uint32_t j = 0; j < src->nCapacity; j++ ) | 1247 | for( uint32_t j = 0; j < src->nCapacity; j++ ) |
1248 | { | 1248 | { |
1249 | if( src->isFilled( j ) && !src->isDeleted( j ) ) | 1249 | if( src->isFilled( j ) && !src->isDeleted( j ) ) |
1250 | { | 1250 | { |
1251 | pRet->insert( src->aKeys[j], src->aValues[j] ); | 1251 | pRet->insert( src->aKeys[j], src->aValues[j] ); |
1252 | } | 1252 | } |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | return pRet; | 1255 | return pRet; |
1256 | } | 1256 | } |
1257 | }; | 1257 | }; |
1258 | 1258 | ||
1259 | template<typename T> uint32_t __calcHashCode( const T &k ) | 1259 | template<typename T> uint32_t __calcHashCode( const T &k ) |
1260 | { | 1260 | { |
1261 | return static_cast<uint32_t>( k ); | 1261 | return static_cast<uint32_t>( k ); |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | template<typename T> bool __cmpHashKeys( const T &a, const T &b ) | 1264 | template<typename T> bool __cmpHashKeys( const T &a, const T &b ) |
1265 | { | 1265 | { |
1266 | return (a == b); | 1266 | return (a == b); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); | 1269 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); |
1270 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); | 1270 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); |
1271 | 1271 | ||
1272 | template<> uint32_t __calcHashCode<char *>( char * const &k ); | 1272 | template<> uint32_t __calcHashCode<char *>( char * const &k ); |
1273 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); | 1273 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); |
1274 | 1274 | ||
1275 | class Formatter; | 1275 | class Formatter; |
1276 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 1276 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
1277 | Formatter &operator<<( Formatter &rOut, signed char c ); | 1277 | Formatter &operator<<( Formatter &rOut, signed char c ); |
1278 | template<typename key, typename value> | 1278 | template<typename key, typename value> |
1279 | Formatter &operator<<( Formatter &f, const Bu::Hash<key, value> &l ) | 1279 | Formatter &operator<<( Formatter &f, const Bu::Hash<key, value> &l ) |
1280 | { | 1280 | { |
1281 | f << '{'; | 1281 | f << '{'; |
1282 | for( typename Bu::Hash<key,value>::const_iterator i = l.begin(); i; i++ ) | 1282 | for( typename Bu::Hash<key,value>::const_iterator i = l.begin(); i; i++ ) |
1283 | { | 1283 | { |
1284 | if( i != l.begin() ) | 1284 | if( i != l.begin() ) |
1285 | f << ", "; | 1285 | f << ", "; |
1286 | f << i.getKey() << ": " << i.getValue(); | 1286 | f << i.getKey() << ": " << i.getValue(); |
1287 | } | 1287 | } |
1288 | f << '}'; | 1288 | f << '}'; |
1289 | 1289 | ||
1290 | return f; | 1290 | return f; |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | template<typename key, typename value, typename a, typename b, | 1293 | template<typename key, typename value, typename a, typename b, |
1294 | typename c, typename d> | 1294 | typename c, typename d> |
1295 | ArchiveBase &operator<<( ArchiveBase &ar, const Hash<key,value,a,b,c,d> &h ) | 1295 | ArchiveBase &operator<<( ArchiveBase &ar, const Hash<key,value,a,b,c,d> &h ) |
1296 | { | 1296 | { |
1297 | long iSize = h.getSize(); | 1297 | long iSize = h.getSize(); |
1298 | ar << iSize; | 1298 | ar << iSize; |
1299 | for( typename Hash<key,value,a,b,c,d>::const_iterator i = h.begin(); i != h.end(); i++ ) | 1299 | for( typename Hash<key,value,a,b,c,d>::const_iterator i = h.begin(); i != h.end(); i++ ) |
1300 | { | 1300 | { |
1301 | ar << (i.getKey()); | 1301 | ar << (i.getKey()); |
1302 | ar << (i.getValue()); | 1302 | ar << (i.getValue()); |
1303 | } | 1303 | } |
1304 | 1304 | ||
1305 | return ar; | 1305 | return ar; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | template<typename key, typename value, typename a, typename b, | 1308 | template<typename key, typename value, typename a, typename b, |
1309 | typename c, typename d> | 1309 | typename c, typename d> |
1310 | ArchiveBase &operator>>( ArchiveBase &ar, Hash<key,value,a,b,c,d> &h ) | 1310 | ArchiveBase &operator>>( ArchiveBase &ar, Hash<key,value,a,b,c,d> &h ) |
1311 | { | 1311 | { |
1312 | h.clear(); | 1312 | h.clear(); |
1313 | long nSize; | 1313 | long nSize; |
1314 | ar >> nSize; | 1314 | ar >> nSize; |
1315 | 1315 | ||
1316 | for( long j = 0; j < nSize; j++ ) | 1316 | for( long j = 0; j < nSize; j++ ) |
1317 | { | 1317 | { |
1318 | key k; value v; | 1318 | key k; value v; |
1319 | ar >> k >> v; | 1319 | ar >> k >> v; |
1320 | h.insert( k, v ); | 1320 | h.insert( k, v ); |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | return ar; | 1323 | return ar; |
1324 | } | 1324 | } |
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | #endif | 1327 | #endif |
diff --git a/src/stable/heap.h b/src/stable/heap.h index a813f92..5033618 100644 --- a/src/stable/heap.h +++ b/src/stable/heap.h | |||
@@ -17,596 +17,596 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDecl( HeapException ); | 20 | subExceptionDecl( HeapException ); |
21 | 21 | ||
22 | template<typename item, typename cmpfunc, typename itemalloc> | 22 | template<typename item, typename cmpfunc, typename itemalloc> |
23 | class Heap; | 23 | class Heap; |
24 | 24 | ||
25 | /** @cond DEVEL */ | 25 | /** @cond DEVEL */ |
26 | template<typename item, typename cmpfunc, typename itemalloc> | 26 | template<typename item, typename cmpfunc, typename itemalloc> |
27 | class HeapCore | 27 | class HeapCore |
28 | { | 28 | { |
29 | friend class Heap<item, cmpfunc, itemalloc>; | 29 | friend class Heap<item, cmpfunc, itemalloc>; |
30 | friend class SharedCore< | 30 | friend class SharedCore< |
31 | Heap<item, cmpfunc, itemalloc>, HeapCore<item, cmpfunc, itemalloc> | 31 | Heap<item, cmpfunc, itemalloc>, HeapCore<item, cmpfunc, itemalloc> |
32 | >; | 32 | >; |
33 | private: | 33 | private: |
34 | HeapCore() : | 34 | HeapCore() : |
35 | iSize( 0 ), | 35 | iSize( 0 ), |
36 | iFill( 0 ), | 36 | iFill( 0 ), |
37 | aItem( NULL ) | 37 | aItem( NULL ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | virtual ~HeapCore() | 41 | virtual ~HeapCore() |
42 | { | 42 | { |
43 | clear(); | 43 | clear(); |
44 | } | 44 | } |
45 | 45 | ||
46 | void init() | 46 | void init() |
47 | { | 47 | { |
48 | if( iSize > 0 ) | 48 | if( iSize > 0 ) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | iSize = 7; | 51 | iSize = 7; |
52 | iFill = 0; | 52 | iFill = 0; |
53 | aItem = ia.allocate( iSize ); | 53 | aItem = ia.allocate( iSize ); |
54 | } | 54 | } |
55 | 55 | ||
56 | void init( int iCap ) | 56 | void init( int iCap ) |
57 | { | 57 | { |
58 | if( iSize > 0 ) | 58 | if( iSize > 0 ) |
59 | return; | 59 | return; |
60 | 60 | ||
61 | for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } | 61 | for( iSize = 1; iSize < iCap; iSize=iSize*2+1 ) { } |
62 | iFill = 0; | 62 | iFill = 0; |
63 | aItem = ia.allocate( iSize ); | 63 | aItem = ia.allocate( iSize ); |
64 | } | 64 | } |
65 | 65 | ||
66 | void clear() | 66 | void clear() |
67 | { | 67 | { |
68 | if( iSize == 0 ) | 68 | if( iSize == 0 ) |
69 | return; | 69 | return; |
70 | 70 | ||
71 | for( int j = 0; j < iFill; j++ ) | 71 | for( int j = 0; j < iFill; j++ ) |
72 | ia.destroy( &aItem[j] ); | 72 | ia.destroy( &aItem[j] ); |
73 | ia.deallocate( aItem, iSize ); | 73 | ia.deallocate( aItem, iSize ); |
74 | aItem = NULL; | 74 | aItem = NULL; |
75 | iSize = 0; | 75 | iSize = 0; |
76 | iFill = 0; | 76 | iFill = 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | void upSize() | 79 | void upSize() |
80 | { | 80 | { |
81 | if( iSize == 0 ) | 81 | if( iSize == 0 ) |
82 | { | 82 | { |
83 | init(); | 83 | init(); |
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | item *aNewItems = ia.allocate( iSize*2+1 ); | 87 | item *aNewItems = ia.allocate( iSize*2+1 ); |
88 | // | 88 | // |
89 | // We cannot use a memcopy here because we don't know what kind | 89 | // We cannot use a memcopy here because we don't know what kind |
90 | // of datastructures are being used, we have to copy them one at | 90 | // of datastructures are being used, we have to copy them one at |
91 | // a time. | 91 | // a time. |
92 | // | 92 | // |
93 | for( int j = 0; j < iFill; j++ ) | 93 | for( int j = 0; j < iFill; j++ ) |
94 | { | 94 | { |
95 | ia.construct( &aNewItems[j], aItem[j] ); | 95 | ia.construct( &aNewItems[j], aItem[j] ); |
96 | ia.destroy( &aItem[j] ); | 96 | ia.destroy( &aItem[j] ); |
97 | } | 97 | } |
98 | ia.deallocate( aItem, iSize ); | 98 | ia.deallocate( aItem, iSize ); |
99 | aItem = aNewItems; | 99 | aItem = aNewItems; |
100 | iSize = iSize*2+1; | 100 | iSize = iSize*2+1; |
101 | } | 101 | } |
102 | 102 | ||
103 | virtual void enqueue( const item &it ) | 103 | virtual void enqueue( const item &it ) |
104 | { | 104 | { |
105 | item i = it; // TODO: This is a silly workaround, put the i item | 105 | item i = it; // TODO: This is a silly workaround, put the i item |
106 | // at the end. | 106 | // at the end. |
107 | if( iFill+1 >= iSize ) | 107 | if( iFill+1 >= iSize ) |
108 | upSize(); | 108 | upSize(); |
109 | 109 | ||
110 | for( int j = 0; j < iFill; ) | 110 | for( int j = 0; j < iFill; ) |
111 | { | 111 | { |
112 | if( cmp( i, aItem[j] ) ) | 112 | if( cmp( i, aItem[j] ) ) |
113 | { | 113 | { |
114 | Bu::swap( i, aItem[j] ); | 114 | Bu::swap( i, aItem[j] ); |
115 | } | 115 | } |
116 | 116 | ||
117 | if( j*2+1 >= iFill ) | 117 | if( j*2+1 >= iFill ) |
118 | break; | 118 | break; |
119 | if( cmp( i, aItem[j*2+1] ) ) | 119 | if( cmp( i, aItem[j*2+1] ) ) |
120 | { | 120 | { |
121 | j = j*2+1; | 121 | j = j*2+1; |
122 | } | 122 | } |
123 | else | 123 | else |
124 | { | 124 | { |
125 | j = j*2+2; | 125 | j = j*2+2; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | ia.construct( &aItem[iFill], i ); | 128 | ia.construct( &aItem[iFill], i ); |
129 | if( iFill > 0 ) | 129 | if( iFill > 0 ) |
130 | { | 130 | { |
131 | for( int j = iFill; j >= 0; ) | 131 | for( int j = iFill; j >= 0; ) |
132 | { | 132 | { |
133 | int k = (j-1)/2; | 133 | int k = (j-1)/2; |
134 | if( j == k ) | 134 | if( j == k ) |
135 | break; | 135 | break; |
136 | if( cmp( aItem[k], aItem[j] ) ) | 136 | if( cmp( aItem[k], aItem[j] ) ) |
137 | break; | 137 | break; |
138 | 138 | ||
139 | Bu::swap( aItem[k], aItem[j] ); | 139 | Bu::swap( aItem[k], aItem[j] ); |
140 | j = k; | 140 | j = k; |
141 | } | 141 | } |
142 | } | 142 | } |
143 | iFill++; | 143 | iFill++; |
144 | } | 144 | } |
145 | 145 | ||
146 | virtual item dequeue() | 146 | virtual item dequeue() |
147 | { | 147 | { |
148 | if( iFill == 0 ) | 148 | if( iFill == 0 ) |
149 | throw HeapException("Heap empty."); | 149 | throw HeapException("Heap empty."); |
150 | item iRet = aItem[0]; | 150 | item iRet = aItem[0]; |
151 | int j; | 151 | int j; |
152 | for( j = 0; j < iFill; ) | 152 | for( j = 0; j < iFill; ) |
153 | { | 153 | { |
154 | int k = j*2+1; | 154 | int k = j*2+1; |
155 | if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) | 155 | if( k+1 < iFill && cmp( aItem[k+1], aItem[k] ) ) |
156 | { | 156 | { |
157 | if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) | 157 | if( k+1 < iFill-1 && cmp( aItem[iFill-1], aItem[k+1] ) ) |
158 | break; | 158 | break; |
159 | aItem[j] = aItem[k+1]; | 159 | aItem[j] = aItem[k+1]; |
160 | j = k+1; | 160 | j = k+1; |
161 | } | 161 | } |
162 | else if( k < iFill ) | 162 | else if( k < iFill ) |
163 | { | 163 | { |
164 | if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) | 164 | if( k < iFill-1 && cmp( aItem[iFill-1], aItem[k] ) ) |
165 | break; | 165 | break; |
166 | aItem[j] = aItem[k]; | 166 | aItem[j] = aItem[k]; |
167 | j = k; | 167 | j = k; |
168 | } | 168 | } |
169 | else | 169 | else |
170 | break; | 170 | break; |
171 | } | 171 | } |
172 | if( j < iFill-1 ) | 172 | if( j < iFill-1 ) |
173 | aItem[j] = aItem[iFill-1]; | 173 | aItem[j] = aItem[iFill-1]; |
174 | ia.destroy( &aItem[iFill-1] ); | 174 | ia.destroy( &aItem[iFill-1] ); |
175 | iFill--; | 175 | iFill--; |
176 | 176 | ||
177 | return iRet; | 177 | return iRet; |
178 | } | 178 | } |
179 | 179 | ||
180 | private: | 180 | private: |
181 | int iSize; | 181 | int iSize; |
182 | int iFill; | 182 | int iFill; |
183 | item *aItem; | 183 | item *aItem; |
184 | cmpfunc cmp; | 184 | cmpfunc cmp; |
185 | itemalloc ia; | 185 | itemalloc ia; |
186 | }; | 186 | }; |
187 | /** @endcond */ | 187 | /** @endcond */ |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * A priority queue that allows for an unlimited number of priorities. All | 190 | * A priority queue that allows for an unlimited number of priorities. All |
191 | * objects enqueued must support less-than-comparison. Then every time an | 191 | * objects enqueued must support less-than-comparison. Then every time an |
192 | * item is dequeued it is always the least item in the heap. The heap | 192 | * item is dequeued it is always the least item in the heap. The heap |
193 | * operates using a binary tree for storage, which allows most operations | 193 | * operates using a binary tree for storage, which allows most operations |
194 | * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins | 194 | * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins |
195 | * whereas peeking is constant time. | 195 | * whereas peeking is constant time. |
196 | * | 196 | * |
197 | * This heap implementation allows iterating, however please note that any | 197 | * This heap implementation allows iterating, however please note that any |
198 | * enqueue or dequeue operation will invalidate the iterator and make it | 198 | * enqueue or dequeue operation will invalidate the iterator and make it |
199 | * unusable (if it still works, you shouldn't trust the results). Also, | 199 | * unusable (if it still works, you shouldn't trust the results). Also, |
200 | * the items are not stored in memory in order, they are optomized into a | 200 | * the items are not stored in memory in order, they are optomized into a |
201 | * tree. This means that the items will be in effectively random order | 201 | * tree. This means that the items will be in effectively random order |
202 | * while iterating through them, and the order cannot be trusted. Also, | 202 | * while iterating through them, and the order cannot be trusted. Also, |
203 | * modifying an item in the heap will not cause that item to be re-sorted. | 203 | * modifying an item in the heap will not cause that item to be re-sorted. |
204 | * If you want to change the position of an item in the heap you will have | 204 | * If you want to change the position of an item in the heap you will have |
205 | * to dequeue every item before it, dequeue that item, change it, and | 205 | * to dequeue every item before it, dequeue that item, change it, and |
206 | * re-enqueue all of the items removed. | 206 | * re-enqueue all of the items removed. |
207 | */ | 207 | */ |
208 | template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> > | 208 | template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> > |
209 | class Heap : public Queue<item>, public SharedCore< | 209 | class Heap : public Queue<item>, public SharedCore< |
210 | Heap<item, cmpfunc, itemalloc>, | 210 | Heap<item, cmpfunc, itemalloc>, |
211 | HeapCore<item, cmpfunc, itemalloc> | 211 | HeapCore<item, cmpfunc, itemalloc> |
212 | > | 212 | > |
213 | { | 213 | { |
214 | private: | 214 | private: |
215 | typedef class Heap<item,cmpfunc,itemalloc> MyType; | 215 | typedef class Heap<item,cmpfunc,itemalloc> MyType; |
216 | typedef class HeapCore<item,cmpfunc,itemalloc> Core; | 216 | typedef class HeapCore<item,cmpfunc,itemalloc> Core; |
217 | 217 | ||
218 | protected: | 218 | protected: |
219 | using SharedCore<MyType, Core>::core; | 219 | using SharedCore<MyType, Core>::core; |
220 | using SharedCore<MyType, Core>::_hardCopy; | 220 | using SharedCore<MyType, Core>::_hardCopy; |
221 | using SharedCore<MyType, Core>::_resetCore; | 221 | using SharedCore<MyType, Core>::_resetCore; |
222 | using SharedCore<MyType, Core>::_allocateCore; | 222 | using SharedCore<MyType, Core>::_allocateCore; |
223 | 223 | ||
224 | public: | 224 | public: |
225 | Heap() | 225 | Heap() |
226 | { | 226 | { |
227 | } | 227 | } |
228 | 228 | ||
229 | Heap( cmpfunc cmpin ) | 229 | Heap( cmpfunc cmpin ) |
230 | { | 230 | { |
231 | core->cmp = cmpin; | 231 | core->cmp = cmpin; |
232 | } | 232 | } |
233 | 233 | ||
234 | Heap( int iInitialCapacity ) | 234 | Heap( int iInitialCapacity ) |
235 | { | 235 | { |
236 | core->init( iInitialCapacity ); | 236 | core->init( iInitialCapacity ); |
237 | } | 237 | } |
238 | 238 | ||
239 | Heap( cmpfunc cmpin, int iInitialCapacity ) | 239 | Heap( cmpfunc cmpin, int iInitialCapacity ) |
240 | { | 240 | { |
241 | core->cmp = cmpin; | 241 | core->cmp = cmpin; |
242 | core->init( iInitialCapacity ); | 242 | core->init( iInitialCapacity ); |
243 | } | 243 | } |
244 | 244 | ||
245 | Heap( const MyType &rSrc ) : | 245 | Heap( const MyType &rSrc ) : |
246 | SharedCore<MyType, Core>( rSrc ) | 246 | SharedCore<MyType, Core>( rSrc ) |
247 | { | 247 | { |
248 | } | 248 | } |
249 | 249 | ||
250 | virtual ~Heap() | 250 | virtual ~Heap() |
251 | { | 251 | { |
252 | } | 252 | } |
253 | 253 | ||
254 | virtual void enqueue( const item &it ) | 254 | virtual void enqueue( const item &it ) |
255 | { | 255 | { |
256 | _hardCopy(); | 256 | _hardCopy(); |
257 | 257 | ||
258 | core->enqueue( it ); | 258 | core->enqueue( it ); |
259 | } | 259 | } |
260 | 260 | ||
261 | virtual item &peek() | 261 | virtual item &peek() |
262 | { | 262 | { |
263 | _hardCopy(); | 263 | _hardCopy(); |
264 | 264 | ||
265 | if( core->iFill == 0 ) | 265 | if( core->iFill == 0 ) |
266 | throw HeapException("Heap empty."); | 266 | throw HeapException("Heap empty."); |
267 | return core->aItem[0]; | 267 | return core->aItem[0]; |
268 | } | 268 | } |
269 | 269 | ||
270 | virtual const item &peek() const | 270 | virtual const item &peek() const |
271 | { | 271 | { |
272 | if( core->iFill == 0 ) | 272 | if( core->iFill == 0 ) |
273 | throw HeapException("Heap empty."); | 273 | throw HeapException("Heap empty."); |
274 | return core->aItem[0]; | 274 | return core->aItem[0]; |
275 | } | 275 | } |
276 | 276 | ||
277 | virtual item dequeue() | 277 | virtual item dequeue() |
278 | { | 278 | { |
279 | _hardCopy(); | 279 | _hardCopy(); |
280 | 280 | ||
281 | return core->dequeue(); | 281 | return core->dequeue(); |
282 | } | 282 | } |
283 | 283 | ||
284 | virtual bool isEmpty() const | 284 | virtual bool isEmpty() const |
285 | { | 285 | { |
286 | return (core->iFill==0); | 286 | return (core->iFill==0); |
287 | } | 287 | } |
288 | 288 | ||
289 | virtual int getSize() const | 289 | virtual int getSize() const |
290 | { | 290 | { |
291 | return core->iFill; | 291 | return core->iFill; |
292 | } | 292 | } |
293 | 293 | ||
294 | class iterator | 294 | class iterator |
295 | { | 295 | { |
296 | friend class const_iterator; | 296 | friend class const_iterator; |
297 | friend class Heap<item, cmpfunc, itemalloc>; | 297 | friend class Heap<item, cmpfunc, itemalloc>; |
298 | private: | 298 | private: |
299 | Heap<item, cmpfunc, itemalloc> *pHeap; | 299 | Heap<item, cmpfunc, itemalloc> *pHeap; |
300 | int iIndex; | 300 | int iIndex; |
301 | 301 | ||
302 | iterator( Heap<item, cmpfunc, itemalloc> *pHeap, int iIndex ) : | 302 | iterator( Heap<item, cmpfunc, itemalloc> *pHeap, int iIndex ) : |
303 | pHeap( pHeap ), iIndex( iIndex ) | 303 | pHeap( pHeap ), iIndex( iIndex ) |
304 | { | 304 | { |
305 | } | 305 | } |
306 | 306 | ||
307 | void checkValid() | 307 | void checkValid() |
308 | { | 308 | { |
309 | if( pHeap == NULL ) | 309 | if( pHeap == NULL ) |
310 | throw Bu::ExceptionBase("Iterator not initialized."); | 310 | throw Bu::ExceptionBase("Iterator not initialized."); |
311 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) | 311 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) |
312 | throw Bu::ExceptionBase("Iterator out of bounds."); | 312 | throw Bu::ExceptionBase("Iterator out of bounds."); |
313 | } | 313 | } |
314 | 314 | ||
315 | public: | 315 | public: |
316 | iterator() : | 316 | iterator() : |
317 | pHeap( NULL ), | 317 | pHeap( NULL ), |
318 | iIndex( -1 ) | 318 | iIndex( -1 ) |
319 | { | 319 | { |
320 | } | 320 | } |
321 | 321 | ||
322 | iterator( const iterator &i ) : | 322 | iterator( const iterator &i ) : |
323 | pHeap( i.pHeap ), | 323 | pHeap( i.pHeap ), |
324 | iIndex( i.iIndex ) | 324 | iIndex( i.iIndex ) |
325 | { | 325 | { |
326 | } | 326 | } |
327 | 327 | ||
328 | bool operator==( const iterator &oth ) const | 328 | bool operator==( const iterator &oth ) const |
329 | { | 329 | { |
330 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); | 330 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); |
331 | } | 331 | } |
332 | 332 | ||
333 | bool operator!=( const iterator &oth ) const | 333 | bool operator!=( const iterator &oth ) const |
334 | { | 334 | { |
335 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); | 335 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); |
336 | } | 336 | } |
337 | 337 | ||
338 | item &operator*() | 338 | item &operator*() |
339 | { | 339 | { |
340 | pHeap->_hardCopy(); | 340 | pHeap->_hardCopy(); |
341 | 341 | ||
342 | return pHeap->core->aItem[iIndex]; | 342 | return pHeap->core->aItem[iIndex]; |
343 | } | 343 | } |
344 | 344 | ||
345 | item *operator->() | 345 | item *operator->() |
346 | { | 346 | { |
347 | pHeap->_hardCopy(); | 347 | pHeap->_hardCopy(); |
348 | 348 | ||
349 | return &(pHeap->core->aItem[iIndex]); | 349 | return &(pHeap->core->aItem[iIndex]); |
350 | } | 350 | } |
351 | 351 | ||
352 | iterator &operator++() | 352 | iterator &operator++() |
353 | { | 353 | { |
354 | checkValid(); | 354 | checkValid(); |
355 | iIndex++; | 355 | iIndex++; |
356 | if( iIndex >= pHeap->iFill ) | 356 | if( iIndex >= pHeap->iFill ) |
357 | iIndex = -1; | 357 | iIndex = -1; |
358 | 358 | ||
359 | return *this; | 359 | return *this; |
360 | } | 360 | } |
361 | 361 | ||
362 | iterator &operator--() | 362 | iterator &operator--() |
363 | { | 363 | { |
364 | checkValid(); | 364 | checkValid(); |
365 | iIndex--; | 365 | iIndex--; |
366 | 366 | ||
367 | return *this; | 367 | return *this; |
368 | } | 368 | } |
369 | 369 | ||
370 | iterator &operator++( int ) | 370 | iterator &operator++( int ) |
371 | { | 371 | { |
372 | checkValid(); | 372 | checkValid(); |
373 | iIndex++; | 373 | iIndex++; |
374 | if( iIndex >= pHeap->core->iFill ) | 374 | if( iIndex >= pHeap->core->iFill ) |
375 | iIndex = -1; | 375 | iIndex = -1; |
376 | 376 | ||
377 | return *this; | 377 | return *this; |
378 | } | 378 | } |
379 | 379 | ||
380 | iterator &operator--( int ) | 380 | iterator &operator--( int ) |
381 | { | 381 | { |
382 | checkValid(); | 382 | checkValid(); |
383 | iIndex--; | 383 | iIndex--; |
384 | 384 | ||
385 | return *this; | 385 | return *this; |
386 | } | 386 | } |
387 | 387 | ||
388 | iterator operator+( int iDelta ) | 388 | iterator operator+( int iDelta ) |
389 | { | 389 | { |
390 | checkValid(); | 390 | checkValid(); |
391 | iterator ret( *this ); | 391 | iterator ret( *this ); |
392 | ret.iIndex += iDelta; | 392 | ret.iIndex += iDelta; |
393 | if( ret.iIndex >= pHeap->core->iFill ) | 393 | if( ret.iIndex >= pHeap->core->iFill ) |
394 | ret.iIndex = -1; | 394 | ret.iIndex = -1; |
395 | return ret; | 395 | return ret; |
396 | } | 396 | } |
397 | 397 | ||
398 | iterator operator-( int iDelta ) | 398 | iterator operator-( int iDelta ) |
399 | { | 399 | { |
400 | checkValid(); | 400 | checkValid(); |
401 | iterator ret( *this ); | 401 | iterator ret( *this ); |
402 | ret.iIndex -= iDelta; | 402 | ret.iIndex -= iDelta; |
403 | if( ret.iIndex < 0 ) | 403 | if( ret.iIndex < 0 ) |
404 | ret.iIndex = -1; | 404 | ret.iIndex = -1; |
405 | return ret; | 405 | return ret; |
406 | } | 406 | } |
407 | 407 | ||
408 | operator bool() const | 408 | operator bool() const |
409 | { | 409 | { |
410 | return iIndex != -1; | 410 | return iIndex != -1; |
411 | } | 411 | } |
412 | 412 | ||
413 | bool isValid() const | 413 | bool isValid() const |
414 | { | 414 | { |
415 | return iIndex != -1; | 415 | return iIndex != -1; |
416 | } | 416 | } |
417 | 417 | ||
418 | iterator &operator=( const iterator &oth ) | 418 | iterator &operator=( const iterator &oth ) |
419 | { | 419 | { |
420 | pHeap = oth.pHeap; | 420 | pHeap = oth.pHeap; |
421 | iIndex = oth.iIndex; | 421 | iIndex = oth.iIndex; |
422 | } | 422 | } |
423 | }; | 423 | }; |
424 | 424 | ||
425 | class const_iterator | 425 | class const_iterator |
426 | { | 426 | { |
427 | friend class Heap<item, cmpfunc, itemalloc>; | 427 | friend class Heap<item, cmpfunc, itemalloc>; |
428 | private: | 428 | private: |
429 | Heap<item, cmpfunc, itemalloc> *pHeap; | 429 | Heap<item, cmpfunc, itemalloc> *pHeap; |
430 | int iIndex; | 430 | int iIndex; |
431 | 431 | ||
432 | const_iterator( Heap<item, cmpfunc, itemalloc> *pHeap, | 432 | const_iterator( Heap<item, cmpfunc, itemalloc> *pHeap, |
433 | int iIndex ) : | 433 | int iIndex ) : |
434 | pHeap( pHeap ), iIndex( iIndex ) | 434 | pHeap( pHeap ), iIndex( iIndex ) |
435 | { | 435 | { |
436 | } | 436 | } |
437 | 437 | ||
438 | void checkValid() | 438 | void checkValid() |
439 | { | 439 | { |
440 | if( pHeap == NULL ) | 440 | if( pHeap == NULL ) |
441 | throw Bu::ExceptionBase("Iterator not initialized."); | 441 | throw Bu::ExceptionBase("Iterator not initialized."); |
442 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) | 442 | if( iIndex < 0 || iIndex >= pHeap->core->iFill ) |
443 | throw Bu::ExceptionBase("Iterator out of bounds."); | 443 | throw Bu::ExceptionBase("Iterator out of bounds."); |
444 | } | 444 | } |
445 | 445 | ||
446 | public: | 446 | public: |
447 | const_iterator() : | 447 | const_iterator() : |
448 | pHeap( NULL ), | 448 | pHeap( NULL ), |
449 | iIndex( -1 ) | 449 | iIndex( -1 ) |
450 | { | 450 | { |
451 | } | 451 | } |
452 | 452 | ||
453 | const_iterator( const const_iterator &i ) : | 453 | const_iterator( const const_iterator &i ) : |
454 | pHeap( i.pHeap ), | 454 | pHeap( i.pHeap ), |
455 | iIndex( i.iIndex ) | 455 | iIndex( i.iIndex ) |
456 | { | 456 | { |
457 | } | 457 | } |
458 | 458 | ||
459 | const_iterator( const iterator &i ) : | 459 | const_iterator( const iterator &i ) : |
460 | pHeap( i.pHeap ), | 460 | pHeap( i.pHeap ), |
461 | iIndex( i.iIndex ) | 461 | iIndex( i.iIndex ) |
462 | { | 462 | { |
463 | } | 463 | } |
464 | 464 | ||
465 | bool operator==( const const_iterator &oth ) const | 465 | bool operator==( const const_iterator &oth ) const |
466 | { | 466 | { |
467 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); | 467 | return (oth.pHeap == pHeap) && (oth.iIndex == iIndex); |
468 | } | 468 | } |
469 | 469 | ||
470 | bool operator!=( const const_iterator &oth ) const | 470 | bool operator!=( const const_iterator &oth ) const |
471 | { | 471 | { |
472 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); | 472 | return (oth.pHeap != pHeap) || (oth.iIndex != iIndex); |
473 | } | 473 | } |
474 | 474 | ||
475 | const item &operator*() | 475 | const item &operator*() |
476 | { | 476 | { |
477 | pHeap->_hardCopy(); | 477 | pHeap->_hardCopy(); |
478 | 478 | ||
479 | return pHeap->core->aItem[iIndex]; | 479 | return pHeap->core->aItem[iIndex]; |
480 | } | 480 | } |
481 | 481 | ||
482 | const item *operator->() | 482 | const item *operator->() |
483 | { | 483 | { |
484 | pHeap->_hardCopy(); | 484 | pHeap->_hardCopy(); |
485 | 485 | ||
486 | return &(pHeap->core->aItem[iIndex]); | 486 | return &(pHeap->core->aItem[iIndex]); |
487 | } | 487 | } |
488 | 488 | ||
489 | const_iterator &operator++() | 489 | const_iterator &operator++() |
490 | { | 490 | { |
491 | checkValid(); | 491 | checkValid(); |
492 | iIndex++; | 492 | iIndex++; |
493 | if( iIndex >= pHeap->core->iFill ) | 493 | if( iIndex >= pHeap->core->iFill ) |
494 | iIndex = -1; | 494 | iIndex = -1; |
495 | 495 | ||
496 | return *this; | 496 | return *this; |
497 | } | 497 | } |
498 | 498 | ||
499 | const_iterator &operator--() | 499 | const_iterator &operator--() |
500 | { | 500 | { |
501 | checkValid(); | 501 | checkValid(); |
502 | iIndex--; | 502 | iIndex--; |
503 | 503 | ||
504 | return *this; | 504 | return *this; |
505 | } | 505 | } |
506 | 506 | ||
507 | const_iterator &operator++( int ) | 507 | const_iterator &operator++( int ) |
508 | { | 508 | { |
509 | checkValid(); | 509 | checkValid(); |
510 | iIndex++; | 510 | iIndex++; |
511 | if( iIndex >= pHeap->core->iFill ) | 511 | if( iIndex >= pHeap->core->iFill ) |
512 | iIndex = -1; | 512 | iIndex = -1; |
513 | 513 | ||
514 | return *this; | 514 | return *this; |
515 | } | 515 | } |
516 | 516 | ||
517 | const_iterator &operator--( int ) | 517 | const_iterator &operator--( int ) |
518 | { | 518 | { |
519 | checkValid(); | 519 | checkValid(); |
520 | iIndex--; | 520 | iIndex--; |
521 | 521 | ||
522 | return *this; | 522 | return *this; |
523 | } | 523 | } |
524 | 524 | ||
525 | const_iterator operator+( int iDelta ) | 525 | const_iterator operator+( int iDelta ) |
526 | { | 526 | { |
527 | checkValid(); | 527 | checkValid(); |
528 | const_iterator ret( *this ); | 528 | const_iterator ret( *this ); |
529 | ret.iIndex += iDelta; | 529 | ret.iIndex += iDelta; |
530 | if( ret.iIndex >= pHeap->iFill ) | 530 | if( ret.iIndex >= pHeap->iFill ) |
531 | ret.iIndex = -1; | 531 | ret.iIndex = -1; |
532 | return ret; | 532 | return ret; |
533 | } | 533 | } |
534 | 534 | ||
535 | const_iterator operator-( int iDelta ) | 535 | const_iterator operator-( int iDelta ) |
536 | { | 536 | { |
537 | checkValid(); | 537 | checkValid(); |
538 | const_iterator ret( *this ); | 538 | const_iterator ret( *this ); |
539 | ret.iIndex -= iDelta; | 539 | ret.iIndex -= iDelta; |
540 | if( ret.iIndex < 0 ) | 540 | if( ret.iIndex < 0 ) |
541 | ret.iIndex = -1; | 541 | ret.iIndex = -1; |
542 | return ret; | 542 | return ret; |
543 | } | 543 | } |
544 | 544 | ||
545 | operator bool() const | 545 | operator bool() const |
546 | { | 546 | { |
547 | return iIndex != -1; | 547 | return iIndex != -1; |
548 | } | 548 | } |
549 | 549 | ||
550 | bool isValid() const | 550 | bool isValid() const |
551 | { | 551 | { |
552 | return iIndex != -1; | 552 | return iIndex != -1; |
553 | } | 553 | } |
554 | 554 | ||
555 | const_iterator &operator=( const const_iterator &oth ) | 555 | const_iterator &operator=( const const_iterator &oth ) |
556 | { | 556 | { |
557 | pHeap = oth.pHeap; | 557 | pHeap = oth.pHeap; |
558 | iIndex = oth.iIndex; | 558 | iIndex = oth.iIndex; |
559 | } | 559 | } |
560 | 560 | ||
561 | const_iterator &operator=( const iterator &oth ) | 561 | const_iterator &operator=( const iterator &oth ) |
562 | { | 562 | { |
563 | pHeap = oth.pHeap; | 563 | pHeap = oth.pHeap; |
564 | iIndex = oth.iIndex; | 564 | iIndex = oth.iIndex; |
565 | } | 565 | } |
566 | }; | 566 | }; |
567 | 567 | ||
568 | iterator begin() | 568 | iterator begin() |
569 | { | 569 | { |
570 | if( core->iFill == 0 ) | 570 | if( core->iFill == 0 ) |
571 | return end(); | 571 | return end(); |
572 | return iterator( this, 0 ); | 572 | return iterator( this, 0 ); |
573 | } | 573 | } |
574 | 574 | ||
575 | const_iterator begin() const | 575 | const_iterator begin() const |
576 | { | 576 | { |
577 | if( core->iFill == 0 ) | 577 | if( core->iFill == 0 ) |
578 | return end(); | 578 | return end(); |
579 | return const_iterator( this, 0 ); | 579 | return const_iterator( this, 0 ); |
580 | } | 580 | } |
581 | 581 | ||
582 | iterator end() | 582 | iterator end() |
583 | { | 583 | { |
584 | return iterator( this, -1 ); | 584 | return iterator( this, -1 ); |
585 | } | 585 | } |
586 | 586 | ||
587 | const_iterator end() const | 587 | const_iterator end() const |
588 | { | 588 | { |
589 | return const_iterator( this, -1 ); | 589 | return const_iterator( this, -1 ); |
590 | } | 590 | } |
591 | 591 | ||
592 | 592 | ||
593 | protected: | 593 | protected: |
594 | virtual Core *_copyCore( Core *src ) | 594 | virtual Core *_copyCore( Core *src ) |
595 | { | 595 | { |
596 | Core *pRet = _allocateCore(); | 596 | Core *pRet = _allocateCore(); |
597 | 597 | ||
598 | pRet->iSize = src->iSize; | 598 | pRet->iSize = src->iSize; |
599 | pRet->iFill = src->iFill; | 599 | pRet->iFill = src->iFill; |
600 | pRet->cmp = src->cmp; | 600 | pRet->cmp = src->cmp; |
601 | pRet->aItem = pRet->ia.allocate( pRet->iSize ); | 601 | pRet->aItem = pRet->ia.allocate( pRet->iSize ); |
602 | for( int j = 0; j < pRet->iFill; j++ ) | 602 | for( int j = 0; j < pRet->iFill; j++ ) |
603 | { | 603 | { |
604 | pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); | 604 | pRet->ia.construct( &pRet->aItem[j], src->aItem[j] ); |
605 | } | 605 | } |
606 | 606 | ||
607 | return pRet; | 607 | return pRet; |
608 | } | 608 | } |
609 | }; | 609 | }; |
610 | }; | 610 | }; |
611 | 611 | ||
612 | #endif | 612 | #endif |
diff --git a/src/stable/hex.cpp b/src/stable/hex.cpp index 3e6a22e..45679b5 100644 --- a/src/stable/hex.cpp +++ b/src/stable/hex.cpp | |||
@@ -8,11 +8,11 @@ | |||
8 | #include "bu/hex.h" | 8 | #include "bu/hex.h" |
9 | 9 | ||
10 | Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : | 10 | Bu::Hex::Hex( Bu::Stream &rNext, bool bUpperCase, int iChunk ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | iChunk( iChunk ), | 12 | iChunk( iChunk ), |
13 | iPos( 0 ), | 13 | iPos( 0 ), |
14 | iIn( 0 ), | 14 | iIn( 0 ), |
15 | sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") | 15 | sChrs(bUpperCase?"0123456789ABCDEF":"0123456789abcdef") |
16 | { | 16 | { |
17 | } | 17 | } |
18 | 18 | ||
@@ -22,48 +22,48 @@ Bu::Hex::~Hex() | |||
22 | 22 | ||
23 | void Bu::Hex::start() | 23 | void Bu::Hex::start() |
24 | { | 24 | { |
25 | iPos = iIn = 0; | 25 | iPos = iIn = 0; |
26 | } | 26 | } |
27 | 27 | ||
28 | Bu::size Bu::Hex::stop() | 28 | Bu::size Bu::Hex::stop() |
29 | { | 29 | { |
30 | return iPos; | 30 | return iPos; |
31 | } | 31 | } |
32 | 32 | ||
33 | Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) | 33 | Bu::size Bu::Hex::read( void *pBuf, Bu::size iBytes ) |
34 | { | 34 | { |
35 | Bu::size j; | 35 | Bu::size j; |
36 | uint8_t *puBuf = (uint8_t *)pBuf; | 36 | uint8_t *puBuf = (uint8_t *)pBuf; |
37 | for( j = 0; j < iBytes; j++ ) | 37 | for( j = 0; j < iBytes; j++ ) |
38 | { | 38 | { |
39 | for(; iIn < 2; iIn++ ) | 39 | for(; iIn < 2; iIn++ ) |
40 | { | 40 | { |
41 | if( rNext.read( &cIn[iIn], 1 ) == 0 ) | 41 | if( rNext.read( &cIn[iIn], 1 ) == 0 ) |
42 | return j; | 42 | return j; |
43 | if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || | 43 | if( cIn[iIn] == ' ' || cIn[iIn] == '\t' || |
44 | cIn[iIn] == '\n' || cIn[iIn] == '\r' ) | 44 | cIn[iIn] == '\n' || cIn[iIn] == '\r' ) |
45 | iIn--; | 45 | iIn--; |
46 | } | 46 | } |
47 | #define chr2nibble( c ) ((c>='0'&&c<='9')?(c-'0'):((c|0x60)-'a'+10)) | 47 | #define chr2nibble( c ) ((c>='0'&&c<='9')?(c-'0'):((c|0x60)-'a'+10)) |
48 | puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); | 48 | puBuf[j] = ((chr2nibble(cIn[0])<<4)|chr2nibble(cIn[1])); |
49 | iIn = 0; | 49 | iIn = 0; |
50 | } | 50 | } |
51 | return j; | 51 | return j; |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) | 54 | Bu::size Bu::Hex::write( const void *pBuf, Bu::size iBytes ) |
55 | { | 55 | { |
56 | char cOut[2]; | 56 | char cOut[2]; |
57 | uint8_t *puBuf = (uint8_t *)pBuf; | 57 | uint8_t *puBuf = (uint8_t *)pBuf; |
58 | for( Bu::size j = 0; j < iBytes; j++ ) | 58 | for( Bu::size j = 0; j < iBytes; j++ ) |
59 | { | 59 | { |
60 | cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; | 60 | cOut[0] = sChrs[(puBuf[j]&0xf0)>>4]; |
61 | cOut[1] = sChrs[(puBuf[j]&0x0f)]; | 61 | cOut[1] = sChrs[(puBuf[j]&0x0f)]; |
62 | if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) | 62 | if( iChunk > 0 && iPos%iChunk == 0 && iPos>0 ) |
63 | rNext.write(" ", 1 ); | 63 | rNext.write(" ", 1 ); |
64 | rNext.write( cOut, 2 ); | 64 | rNext.write( cOut, 2 ); |
65 | iPos++; | 65 | iPos++; |
66 | } | 66 | } |
67 | return iBytes; | 67 | return iBytes; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/src/stable/hex.h b/src/stable/hex.h index a89e93d..c010173 100644 --- a/src/stable/hex.h +++ b/src/stable/hex.h | |||
@@ -12,46 +12,46 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * This very simple filter encodes to/decodes from hex encoded string data. | 16 | * This very simple filter encodes to/decodes from hex encoded string data. |
17 | * The primary use of this filter is in debugging, use it with | 17 | * The primary use of this filter is in debugging, use it with |
18 | * Bu::encodeStr to easily create hex dumps of string data, even other raw | 18 | * Bu::encodeStr to easily create hex dumps of string data, even other raw |
19 | * structures. | 19 | * structures. |
20 | * | 20 | * |
21 | *@code | 21 | *@code |
22 | Bu::println("Hexdump: " + Bu::encodeStr<Bu::Hex>("Test data ;)") ); | 22 | Bu::println("Hexdump: " + Bu::encodeStr<Bu::Hex>("Test data ;)") ); |
23 | @endcode | 23 | @endcode |
24 | * Or... | 24 | * Or... |
25 | *@code | 25 | *@code |
26 | complex_struct data; | 26 | complex_struct data; |
27 | ... | 27 | ... |
28 | Bu::println("Hexdump: " + | 28 | Bu::println("Hexdump: " + |
29 | Bu::encodeStr<Bu::Hex>( | 29 | Bu::encodeStr<Bu::Hex>( |
30 | Bu::String( &data, sizeof(data) ) | 30 | Bu::String( &data, sizeof(data) ) |
31 | ) | 31 | ) |
32 | ); | 32 | ); |
33 | @endcode | 33 | @endcode |
34 | **/ | 34 | **/ |
35 | class Hex : public Bu::Filter | 35 | class Hex : public Bu::Filter |
36 | { | 36 | { |
37 | public: | 37 | public: |
38 | Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); | 38 | Hex( Bu::Stream &rNext, bool bUpperCase=false, int iChunk=-1 ); |
39 | virtual ~Hex(); | 39 | virtual ~Hex(); |
40 | 40 | ||
41 | virtual void start(); | 41 | virtual void start(); |
42 | virtual Bu::size stop(); | 42 | virtual Bu::size stop(); |
43 | 43 | ||
44 | virtual Bu::size read( void *pBuf, Bu::size iBytes ); | 44 | virtual Bu::size read( void *pBuf, Bu::size iBytes ); |
45 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ); | 45 | virtual Bu::size write( const void *pBuf, Bu::size iBytes ); |
46 | using Bu::Stream::write; | 46 | using Bu::Stream::write; |
47 | 47 | ||
48 | private: | 48 | private: |
49 | int iChunk; | 49 | int iChunk; |
50 | Bu::size iPos; | 50 | Bu::size iPos; |
51 | char cIn[2]; | 51 | char cIn[2]; |
52 | int iIn; | 52 | int iIn; |
53 | const char *sChrs; | 53 | const char *sChrs; |
54 | }; | 54 | }; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #endif | 57 | #endif |
diff --git a/src/stable/list.h b/src/stable/list.h index 4f9d4aa..b7fb1d1 100644 --- a/src/stable/list.h +++ b/src/stable/list.h | |||
@@ -16,1022 +16,1022 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** @cond DEVEL */ | 19 | /** @cond DEVEL */ |
20 | template<typename value> | 20 | template<typename value> |
21 | struct ListLink | 21 | struct ListLink |
22 | { | 22 | { |
23 | value *pValue; | 23 | value *pValue; |
24 | ListLink *pNext; | 24 | ListLink *pNext; |
25 | ListLink *pPrev; | 25 | ListLink *pPrev; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | template<typename value, typename valuealloc, typename linkalloc> | 28 | template<typename value, typename valuealloc, typename linkalloc> |
29 | class List; | 29 | class List; |
30 | 30 | ||
31 | template<typename value, typename valuealloc, typename linkalloc> | 31 | template<typename value, typename valuealloc, typename linkalloc> |
32 | struct ListCore | 32 | struct ListCore |
33 | { | 33 | { |
34 | friend class List<value, valuealloc, linkalloc>; | 34 | friend class List<value, valuealloc, linkalloc>; |
35 | friend class SharedCore< | 35 | friend class SharedCore< |
36 | List<value, valuealloc, linkalloc>, | 36 | List<value, valuealloc, linkalloc>, |
37 | ListCore<value, valuealloc, linkalloc> | 37 | ListCore<value, valuealloc, linkalloc> |
38 | >; | 38 | >; |
39 | private: | 39 | private: |
40 | typedef struct ListLink<value> Link; | 40 | typedef struct ListLink<value> Link; |
41 | ListCore() : | 41 | ListCore() : |
42 | pFirst( NULL ), | 42 | pFirst( NULL ), |
43 | pLast( NULL ), | 43 | pLast( NULL ), |
44 | nSize( 0 ) | 44 | nSize( 0 ) |
45 | { } | 45 | { } |
46 | 46 | ||
47 | virtual ~ListCore() | 47 | virtual ~ListCore() |
48 | { | 48 | { |
49 | clear(); | 49 | clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | Link *pFirst; | 52 | Link *pFirst; |
53 | Link *pLast; | 53 | Link *pLast; |
54 | long nSize; | 54 | long nSize; |
55 | linkalloc la; | 55 | linkalloc la; |
56 | valuealloc va; | 56 | valuealloc va; |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Append a value to the list. | 59 | * Append a value to the list. |
60 | *@param v (const value_type &) The value to append. | 60 | *@param v (const value_type &) The value to append. |
61 | */ | 61 | */ |
62 | Link *append( const value &v ) | 62 | Link *append( const value &v ) |
63 | { | 63 | { |
64 | Link *pNew = la.allocate( 1 ); | 64 | Link *pNew = la.allocate( 1 ); |
65 | pNew->pValue = va.allocate( 1 ); | 65 | pNew->pValue = va.allocate( 1 ); |
66 | va.construct( pNew->pValue, v ); | 66 | va.construct( pNew->pValue, v ); |
67 | nSize++; | 67 | nSize++; |
68 | if( pFirst == NULL ) | 68 | if( pFirst == NULL ) |
69 | { | 69 | { |
70 | // Empty list | 70 | // Empty list |
71 | pFirst = pLast = pNew; | 71 | pFirst = pLast = pNew; |
72 | pNew->pNext = pNew->pPrev = NULL; | 72 | pNew->pNext = pNew->pPrev = NULL; |
73 | } | 73 | } |
74 | else | 74 | else |
75 | { | 75 | { |
76 | pNew->pNext = NULL; | 76 | pNew->pNext = NULL; |
77 | pNew->pPrev = pLast; | 77 | pNew->pPrev = pLast; |
78 | pLast->pNext = pNew; | 78 | pLast->pNext = pNew; |
79 | pLast = pNew; | 79 | pLast = pNew; |
80 | } | 80 | } |
81 | return pNew; | 81 | return pNew; |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Prepend a value to the list. | 85 | * Prepend a value to the list. |
86 | *@param v (const value_type &) The value to prepend. | 86 | *@param v (const value_type &) The value to prepend. |
87 | */ | 87 | */ |
88 | Link *prepend( const value &v ) | 88 | Link *prepend( const value &v ) |
89 | { | 89 | { |
90 | Link *pNew = la.allocate( 1 ); | 90 | Link *pNew = la.allocate( 1 ); |
91 | pNew->pValue = va.allocate( 1 ); | 91 | pNew->pValue = va.allocate( 1 ); |
92 | va.construct( pNew->pValue, v ); | 92 | va.construct( pNew->pValue, v ); |
93 | nSize++; | 93 | nSize++; |
94 | if( pFirst == NULL ) | 94 | if( pFirst == NULL ) |
95 | { | 95 | { |
96 | // Empty list | 96 | // Empty list |
97 | pFirst = pLast = pNew; | 97 | pFirst = pLast = pNew; |
98 | pNew->pNext = pNew->pPrev = NULL; | 98 | pNew->pNext = pNew->pPrev = NULL; |
99 | } | 99 | } |
100 | else | 100 | else |
101 | { | 101 | { |
102 | pNew->pNext = pFirst; | 102 | pNew->pNext = pFirst; |
103 | pNew->pPrev = NULL; | 103 | pNew->pPrev = NULL; |
104 | pFirst->pPrev = pNew; | 104 | pFirst->pPrev = pNew; |
105 | pFirst = pNew; | 105 | pFirst = pNew; |
106 | } | 106 | } |
107 | return pNew; | 107 | return pNew; |
108 | } | 108 | } |
109 | 109 | ||
110 | void clear() | 110 | void clear() |
111 | { | 111 | { |
112 | Link *pCur = pFirst; | 112 | Link *pCur = pFirst; |
113 | for(;;) | 113 | for(;;) |
114 | { | 114 | { |
115 | if( pCur == NULL ) break; | 115 | if( pCur == NULL ) break; |
116 | va.destroy( pCur->pValue ); | 116 | va.destroy( pCur->pValue ); |
117 | va.deallocate( pCur->pValue, 1 ); | 117 | va.deallocate( pCur->pValue, 1 ); |
118 | Link *pTmp = pCur->pNext; | 118 | Link *pTmp = pCur->pNext; |
119 | la.destroy( pCur ); | 119 | la.destroy( pCur ); |
120 | la.deallocate( pCur, 1 ); | 120 | la.deallocate( pCur, 1 ); |
121 | pCur = pTmp; | 121 | pCur = pTmp; |
122 | } | 122 | } |
123 | pFirst = pLast = NULL; | 123 | pFirst = pLast = NULL; |
124 | nSize = 0; | 124 | nSize = 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | Link *insert( Link *pLink, const value &v ) | 127 | Link *insert( Link *pLink, const value &v ) |
128 | { | 128 | { |
129 | Link *pAfter = pLink; | 129 | Link *pAfter = pLink; |
130 | if( pAfter == NULL ) | 130 | if( pAfter == NULL ) |
131 | { | 131 | { |
132 | return append( v ); | 132 | return append( v ); |
133 | } | 133 | } |
134 | Link *pPrev = pAfter->pPrev; | 134 | Link *pPrev = pAfter->pPrev; |
135 | if( pPrev == NULL ) | 135 | if( pPrev == NULL ) |
136 | { | 136 | { |
137 | return prepend( v ); | 137 | return prepend( v ); |
138 | } | 138 | } |
139 | 139 | ||
140 | Link *pNew = la.allocate( 1 ); | 140 | Link *pNew = la.allocate( 1 ); |
141 | pNew->pValue = va.allocate( 1 ); | 141 | pNew->pValue = va.allocate( 1 ); |
142 | va.construct( pNew->pValue, v ); | 142 | va.construct( pNew->pValue, v ); |
143 | nSize++; | 143 | nSize++; |
144 | 144 | ||
145 | pNew->pNext = pAfter; | 145 | pNew->pNext = pAfter; |
146 | pNew->pPrev = pPrev; | 146 | pNew->pPrev = pPrev; |
147 | pAfter->pPrev = pNew; | 147 | pAfter->pPrev = pNew; |
148 | pPrev->pNext = pNew; | 148 | pPrev->pNext = pNew; |
149 | 149 | ||
150 | return pNew; | 150 | return pNew; |
151 | } | 151 | } |
152 | 152 | ||
153 | /** | 153 | /** |
154 | * Erase an item from the list. | 154 | * Erase an item from the list. |
155 | *@param i (iterator) The item to erase. | 155 | *@param i (iterator) The item to erase. |
156 | */ | 156 | */ |
157 | void erase( Link *pLink ) | 157 | void erase( Link *pLink ) |
158 | { | 158 | { |
159 | Link *pCur = pLink; | 159 | Link *pCur = pLink; |
160 | if( pCur == NULL ) return; | 160 | if( pCur == NULL ) return; |
161 | Link *pPrev = pCur->pPrev; | 161 | Link *pPrev = pCur->pPrev; |
162 | if( pPrev == NULL ) | 162 | if( pPrev == NULL ) |
163 | { | 163 | { |
164 | va.destroy( pCur->pValue ); | 164 | va.destroy( pCur->pValue ); |
165 | va.deallocate( pCur->pValue, 1 ); | 165 | va.deallocate( pCur->pValue, 1 ); |
166 | pFirst = pCur->pNext; | 166 | pFirst = pCur->pNext; |
167 | la.destroy( pCur ); | 167 | la.destroy( pCur ); |
168 | la.deallocate( pCur, 1 ); | 168 | la.deallocate( pCur, 1 ); |
169 | if( pFirst == NULL ) | 169 | if( pFirst == NULL ) |
170 | pLast = NULL; | 170 | pLast = NULL; |
171 | else | 171 | else |
172 | pFirst->pPrev = NULL; | 172 | pFirst->pPrev = NULL; |
173 | nSize--; | 173 | nSize--; |
174 | } | 174 | } |
175 | else | 175 | else |
176 | { | 176 | { |
177 | va.destroy( pCur->pValue ); | 177 | va.destroy( pCur->pValue ); |
178 | va.deallocate( pCur->pValue, 1 ); | 178 | va.deallocate( pCur->pValue, 1 ); |
179 | Link *pTmp = pCur->pNext; | 179 | Link *pTmp = pCur->pNext; |
180 | la.destroy( pCur ); | 180 | la.destroy( pCur ); |
181 | la.deallocate( pCur, 1 ); | 181 | la.deallocate( pCur, 1 ); |
182 | pPrev->pNext = pTmp; | 182 | pPrev->pNext = pTmp; |
183 | if( pTmp != NULL ) | 183 | if( pTmp != NULL ) |
184 | pTmp->pPrev = pPrev; | 184 | pTmp->pPrev = pPrev; |
185 | else | 185 | else |
186 | pLast = pPrev; | 186 | pLast = pPrev; |
187 | nSize--; | 187 | nSize--; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | }; | 190 | }; |
191 | /** @endcond */ | 191 | /** @endcond */ |
192 | 192 | ||
193 | /** | 193 | /** |
194 | * Linked list template container. This class is similar to the stl list | 194 | * Linked list template container. This class is similar to the stl list |
195 | * class except for a few minor changes. First, when const, all | 195 | * class except for a few minor changes. First, when const, all |
196 | * members are only accessable const. Second, erasing a location does not | 196 | * members are only accessable const. Second, erasing a location does not |
197 | * invalidate the iterator used, it simply points to the next valid | 197 | * invalidate the iterator used, it simply points to the next valid |
198 | * location, or end() if there are no more. Other iterators pointing to | 198 | * location, or end() if there are no more. Other iterators pointing to |
199 | * the deleted record will, of course, no longer be valid. | 199 | * the deleted record will, of course, no longer be valid. |
200 | * | 200 | * |
201 | *@param value (typename) The type of data to store in your list | 201 | *@param value (typename) The type of data to store in your list |
202 | *@param valuealloc (typename) Memory Allocator for your value type | 202 | *@param valuealloc (typename) Memory Allocator for your value type |
203 | *@param linkalloc (typename) Memory Allocator for the list links. | 203 | *@param linkalloc (typename) Memory Allocator for the list links. |
204 | *@extends SharedCore | 204 | *@extends SharedCore |
205 | *@ingroup Containers | 205 | *@ingroup Containers |
206 | */ | 206 | */ |
207 | template<typename value, typename valuealloc=std::allocator<value>, | 207 | template<typename value, typename valuealloc=std::allocator<value>, |
208 | typename linkalloc=std::allocator<struct ListLink<value> > > | 208 | typename linkalloc=std::allocator<struct ListLink<value> > > |
209 | class List /** @cond */ : public SharedCore< | 209 | class List /** @cond */ : public SharedCore< |
210 | List<value, valuealloc, linkalloc>, | 210 | List<value, valuealloc, linkalloc>, |
211 | ListCore<value, valuealloc, linkalloc> | 211 | ListCore<value, valuealloc, linkalloc> |
212 | > /** @endcond */ | 212 | > /** @endcond */ |
213 | { | 213 | { |
214 | private: | 214 | private: |
215 | typedef struct ListLink<value> Link; | 215 | typedef struct ListLink<value> Link; |
216 | typedef class List<value, valuealloc, linkalloc> MyType; | 216 | typedef class List<value, valuealloc, linkalloc> MyType; |
217 | typedef struct ListCore<value, valuealloc, linkalloc> Core; | 217 | typedef struct ListCore<value, valuealloc, linkalloc> Core; |
218 | 218 | ||
219 | protected: | 219 | protected: |
220 | using SharedCore<MyType, Core>::core; | 220 | using SharedCore<MyType, Core>::core; |
221 | using SharedCore<MyType, Core>::_hardCopy; | 221 | using SharedCore<MyType, Core>::_hardCopy; |
222 | using SharedCore<MyType, Core>::_allocateCore; | 222 | using SharedCore<MyType, Core>::_allocateCore; |
223 | 223 | ||
224 | public: | 224 | public: |
225 | struct const_iterator; | 225 | struct const_iterator; |
226 | struct iterator; | 226 | struct iterator; |
227 | 227 | ||
228 | List() | 228 | List() |
229 | { | 229 | { |
230 | } | 230 | } |
231 | 231 | ||
232 | List( const MyType &src ) : | 232 | List( const MyType &src ) : |
233 | SharedCore<MyType, Core >( src ) | 233 | SharedCore<MyType, Core >( src ) |
234 | { | 234 | { |
235 | } | 235 | } |
236 | 236 | ||
237 | List( const value &v ) | 237 | List( const value &v ) |
238 | { | 238 | { |
239 | append( v ); | 239 | append( v ); |
240 | } | 240 | } |
241 | 241 | ||
242 | ~List() | 242 | ~List() |
243 | { | 243 | { |
244 | } | 244 | } |
245 | 245 | ||
246 | MyType &operator+=( const value &v ) | 246 | MyType &operator+=( const value &v ) |
247 | { | 247 | { |
248 | _hardCopy(); | 248 | _hardCopy(); |
249 | append( v ); | 249 | append( v ); |
250 | return *this; | 250 | return *this; |
251 | } | 251 | } |
252 | 252 | ||
253 | MyType &operator+=( const MyType &src ) | 253 | MyType &operator+=( const MyType &src ) |
254 | { | 254 | { |
255 | _hardCopy(); | 255 | _hardCopy(); |
256 | append( src ); | 256 | append( src ); |
257 | return *this; | 257 | return *this; |
258 | } | 258 | } |
259 | 259 | ||
260 | MyType operator+( const MyType &src ) | 260 | MyType operator+( const MyType &src ) |
261 | { | 261 | { |
262 | MyType lNew( *this ); | 262 | MyType lNew( *this ); |
263 | lNew += src; | 263 | lNew += src; |
264 | return lNew; | 264 | return lNew; |
265 | } | 265 | } |
266 | 266 | ||
267 | bool operator==( const MyType &rhs ) const | 267 | bool operator==( const MyType &rhs ) const |
268 | { | 268 | { |
269 | if( getSize() != rhs.getSize() ) | 269 | if( getSize() != rhs.getSize() ) |
270 | return false; | 270 | return false; |
271 | 271 | ||
272 | for( typename MyType::const_iterator a = begin(), b = rhs.begin(); | 272 | for( typename MyType::const_iterator a = begin(), b = rhs.begin(); |
273 | a; a++, b++ ) | 273 | a; a++, b++ ) |
274 | { | 274 | { |
275 | if( *a != *b ) | 275 | if( *a != *b ) |
276 | return false; | 276 | return false; |
277 | } | 277 | } |
278 | 278 | ||
279 | return true; | 279 | return true; |
280 | } | 280 | } |
281 | 281 | ||
282 | bool operator!=( const MyType &rhs ) const | 282 | bool operator!=( const MyType &rhs ) const |
283 | { | 283 | { |
284 | return !(*this == rhs); | 284 | return !(*this == rhs); |
285 | } | 285 | } |
286 | 286 | ||
287 | /** | 287 | /** |
288 | * Clear the data from the list. | 288 | * Clear the data from the list. |
289 | */ | 289 | */ |
290 | void clear() | 290 | void clear() |
291 | { | 291 | { |
292 | _hardCopy(); | 292 | _hardCopy(); |
293 | core->clear(); | 293 | core->clear(); |
294 | } | 294 | } |
295 | 295 | ||
296 | MyType &enqueue( const value &v ) | 296 | MyType &enqueue( const value &v ) |
297 | { | 297 | { |
298 | _hardCopy(); | 298 | _hardCopy(); |
299 | append( v ); | 299 | append( v ); |
300 | 300 | ||
301 | return *this; | 301 | return *this; |
302 | } | 302 | } |
303 | 303 | ||
304 | value dequeue() | 304 | value dequeue() |
305 | { | 305 | { |
306 | // _hardCopy(); erase will call this for me | 306 | // _hardCopy(); erase will call this for me |
307 | value v = *core->pFirst->pValue; | 307 | value v = *core->pFirst->pValue; |
308 | 308 | ||
309 | erase( begin() ); | 309 | erase( begin() ); |
310 | 310 | ||
311 | return v; | 311 | return v; |
312 | } | 312 | } |
313 | 313 | ||
314 | MyType &push( const value &v ) | 314 | MyType &push( const value &v ) |
315 | { | 315 | { |
316 | _hardCopy(); | 316 | _hardCopy(); |
317 | prepend( v ); | 317 | prepend( v ); |
318 | 318 | ||
319 | return *this; | 319 | return *this; |
320 | } | 320 | } |
321 | 321 | ||
322 | MyType &pop() | 322 | MyType &pop() |
323 | { | 323 | { |
324 | _hardCopy(); | 324 | _hardCopy(); |
325 | erase( begin() ); | 325 | erase( begin() ); |
326 | 326 | ||
327 | return *this; | 327 | return *this; |
328 | } | 328 | } |
329 | 329 | ||
330 | value peekPop() | 330 | value peekPop() |
331 | { | 331 | { |
332 | value v = first(); | 332 | value v = first(); |
333 | pop(); | 333 | pop(); |
334 | return v; | 334 | return v; |
335 | } | 335 | } |
336 | 336 | ||
337 | value &peek() | 337 | value &peek() |
338 | { | 338 | { |
339 | return first(); | 339 | return first(); |
340 | } | 340 | } |
341 | 341 | ||
342 | /** | 342 | /** |
343 | * Append a value to the list. | 343 | * Append a value to the list. |
344 | *@param v (const value_type &) The value to append. | 344 | *@param v (const value_type &) The value to append. |
345 | */ | 345 | */ |
346 | MyType &append( const value &v ) | 346 | MyType &append( const value &v ) |
347 | { | 347 | { |
348 | _hardCopy(); | 348 | _hardCopy(); |
349 | core->append( v ); | 349 | core->append( v ); |
350 | 350 | ||
351 | return *this; | 351 | return *this; |
352 | } | 352 | } |
353 | 353 | ||
354 | MyType &append( const MyType &rSrc ) | 354 | MyType &append( const MyType &rSrc ) |
355 | { | 355 | { |
356 | _hardCopy(); | 356 | _hardCopy(); |
357 | for( typename MyType::const_iterator i = rSrc.begin(); | 357 | for( typename MyType::const_iterator i = rSrc.begin(); |
358 | i != rSrc.end(); i++ ) | 358 | i != rSrc.end(); i++ ) |
359 | { | 359 | { |
360 | core->append( *i ); | 360 | core->append( *i ); |
361 | } | 361 | } |
362 | 362 | ||
363 | return *this; | 363 | return *this; |
364 | } | 364 | } |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * Prepend a value to the list. | 367 | * Prepend a value to the list. |
368 | *@param v (const value_type &) The value to prepend. | 368 | *@param v (const value_type &) The value to prepend. |
369 | */ | 369 | */ |
370 | MyType &prepend( const value &v ) | 370 | MyType &prepend( const value &v ) |
371 | { | 371 | { |
372 | _hardCopy(); | 372 | _hardCopy(); |
373 | core->prepend( v ); | 373 | core->prepend( v ); |
374 | 374 | ||
375 | return *this; | 375 | return *this; |
376 | } | 376 | } |
377 | 377 | ||
378 | /** | 378 | /** |
379 | * Prepend another list to the front of this one. This will prepend | 379 | * Prepend another list to the front of this one. This will prepend |
380 | * the rSrc list in reverse order...I may fix that later. | 380 | * the rSrc list in reverse order...I may fix that later. |
381 | */ | 381 | */ |
382 | MyType &prepend( const MyType &rSrc ) | 382 | MyType &prepend( const MyType &rSrc ) |
383 | { | 383 | { |
384 | _hardCopy(); | 384 | _hardCopy(); |
385 | for( typename MyType::const_iterator i = rSrc.begin(); | 385 | for( typename MyType::const_iterator i = rSrc.begin(); |
386 | i != rSrc.end(); i++ ) | 386 | i != rSrc.end(); i++ ) |
387 | { | 387 | { |
388 | core->prepend( *i ); | 388 | core->prepend( *i ); |
389 | } | 389 | } |
390 | 390 | ||
391 | return *this; | 391 | return *this; |
392 | } | 392 | } |
393 | 393 | ||
394 | MyType &insert( MyType::iterator &i, const value &v ) | 394 | MyType &insert( MyType::iterator &i, const value &v ) |
395 | { | 395 | { |
396 | _hardCopy(); | 396 | _hardCopy(); |
397 | 397 | ||
398 | core->insert( i.pLink, v ); | 398 | core->insert( i.pLink, v ); |
399 | 399 | ||
400 | return *this; | 400 | return *this; |
401 | } | 401 | } |
402 | 402 | ||
403 | template<typename cmptype> | 403 | template<typename cmptype> |
404 | void sort( cmptype cmp ) | 404 | void sort( cmptype cmp ) |
405 | { | 405 | { |
406 | Heap<value, cmptype, valuealloc> hSort( cmp, getSize() ); | 406 | Heap<value, cmptype, valuealloc> hSort( cmp, getSize() ); |
407 | for( typename MyType::iterator i = begin(); i; i++ ) | 407 | for( typename MyType::iterator i = begin(); i; i++ ) |
408 | { | 408 | { |
409 | hSort.enqueue( *i ); | 409 | hSort.enqueue( *i ); |
410 | } | 410 | } |
411 | clear(); | 411 | clear(); |
412 | while( !hSort.isEmpty() ) | 412 | while( !hSort.isEmpty() ) |
413 | { | 413 | { |
414 | append( hSort.dequeue() ); | 414 | append( hSort.dequeue() ); |
415 | } | 415 | } |
416 | } | 416 | } |
417 | 417 | ||
418 | void sort() | 418 | void sort() |
419 | { | 419 | { |
420 | sort<__basicLTCmp<value> >(); | 420 | sort<__basicLTCmp<value> >(); |
421 | } | 421 | } |
422 | 422 | ||
423 | template<typename cmptype> | 423 | template<typename cmptype> |
424 | void sort() | 424 | void sort() |
425 | { | 425 | { |
426 | Heap<value, cmptype, valuealloc> hSort( getSize() ); | 426 | Heap<value, cmptype, valuealloc> hSort( getSize() ); |
427 | for( typename MyType::iterator i = begin(); i; i++ ) | 427 | for( typename MyType::iterator i = begin(); i; i++ ) |
428 | { | 428 | { |
429 | hSort.enqueue( *i ); | 429 | hSort.enqueue( *i ); |
430 | } | 430 | } |
431 | clear(); | 431 | clear(); |
432 | while( !hSort.isEmpty() ) | 432 | while( !hSort.isEmpty() ) |
433 | { | 433 | { |
434 | append( hSort.dequeue() ); | 434 | append( hSort.dequeue() ); |
435 | } | 435 | } |
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
439 | * Insert a new item in sort order by searching for the first item that | 439 | * Insert a new item in sort order by searching for the first item that |
440 | * is larger and inserting this before it, or at the end if none are | 440 | * is larger and inserting this before it, or at the end if none are |
441 | * larger. If this is the only function used to insert data in the | 441 | * larger. If this is the only function used to insert data in the |
442 | * List all items will be sorted. To use this, the value type must | 442 | * List all items will be sorted. To use this, the value type must |
443 | * support the > operator. | 443 | * support the > operator. |
444 | */ | 444 | */ |
445 | template<typename cmptype> | 445 | template<typename cmptype> |
446 | iterator insertSorted( cmptype cmp, const value &v ) | 446 | iterator insertSorted( cmptype cmp, const value &v ) |
447 | { | 447 | { |
448 | _hardCopy(); | 448 | _hardCopy(); |
449 | if( core->pFirst == NULL ) | 449 | if( core->pFirst == NULL ) |
450 | { | 450 | { |
451 | // Empty list | 451 | // Empty list |
452 | return iterator( core->append( v ) ); | 452 | return iterator( core->append( v ) ); |
453 | } | 453 | } |
454 | else | 454 | else |
455 | { | 455 | { |
456 | Link *pCur = core->pFirst; | 456 | Link *pCur = core->pFirst; |
457 | for(;;) | 457 | for(;;) |
458 | { | 458 | { |
459 | if( cmp( v, *(pCur->pValue)) ) | 459 | if( cmp( v, *(pCur->pValue)) ) |
460 | { | 460 | { |
461 | return iterator( core->insert( pCur, v ) ); | 461 | return iterator( core->insert( pCur, v ) ); |
462 | } | 462 | } |
463 | pCur = pCur->pNext; | 463 | pCur = pCur->pNext; |
464 | if( pCur == NULL ) | 464 | if( pCur == NULL ) |
465 | { | 465 | { |
466 | return iterator( core->append( v ) ); | 466 | return iterator( core->append( v ) ); |
467 | } | 467 | } |
468 | } | 468 | } |
469 | } | 469 | } |
470 | } | 470 | } |
471 | 471 | ||
472 | iterator insertSorted( const value &v ) | 472 | iterator insertSorted( const value &v ) |
473 | { | 473 | { |
474 | return insertSorted<__basicLTCmp<value> >( v ); | 474 | return insertSorted<__basicLTCmp<value> >( v ); |
475 | } | 475 | } |
476 | 476 | ||
477 | template<typename cmptype> | 477 | template<typename cmptype> |
478 | iterator insertSorted( const value &v ) | 478 | iterator insertSorted( const value &v ) |
479 | { | 479 | { |
480 | cmptype cmp; | 480 | cmptype cmp; |
481 | return insertSorted( cmp, v ); | 481 | return insertSorted( cmp, v ); |
482 | } | 482 | } |
483 | 483 | ||
484 | /** | 484 | /** |
485 | * An iterator to iterate through your list. | 485 | * An iterator to iterate through your list. |
486 | */ | 486 | */ |
487 | typedef struct iterator | 487 | typedef struct iterator |
488 | { | 488 | { |
489 | friend struct const_iterator; | 489 | friend struct const_iterator; |
490 | friend class List<value, valuealloc, linkalloc>; | 490 | friend class List<value, valuealloc, linkalloc>; |
491 | private: | 491 | private: |
492 | Link *pLink; | 492 | Link *pLink; |
493 | 493 | ||
494 | iterator( Link *pLink ) : | 494 | iterator( Link *pLink ) : |
495 | pLink( pLink ) | 495 | pLink( pLink ) |
496 | { | 496 | { |
497 | } | 497 | } |
498 | 498 | ||
499 | public: | 499 | public: |
500 | iterator() : | 500 | iterator() : |
501 | pLink( NULL ) | 501 | pLink( NULL ) |
502 | { | 502 | { |
503 | } | 503 | } |
504 | 504 | ||
505 | iterator( const iterator &i ) : | 505 | iterator( const iterator &i ) : |
506 | pLink( i.pLink ) | 506 | pLink( i.pLink ) |
507 | { | 507 | { |
508 | } | 508 | } |
509 | 509 | ||
510 | /** | 510 | /** |
511 | * Equals comparison operator. | 511 | * Equals comparison operator. |
512 | *@param oth (const iterator &) The iterator to compare to. | 512 | *@param oth (const iterator &) The iterator to compare to. |
513 | *@returns (bool) Are they equal? | 513 | *@returns (bool) Are they equal? |
514 | */ | 514 | */ |
515 | bool operator==( const iterator &oth ) const | 515 | bool operator==( const iterator &oth ) const |
516 | { | 516 | { |
517 | return ( pLink == oth.pLink ); | 517 | return ( pLink == oth.pLink ); |
518 | } | 518 | } |
519 | 519 | ||
520 | /** | 520 | /** |
521 | * Equals comparison operator. | 521 | * Equals comparison operator. |
522 | *@param pOth (const Link *) The link to compare to. | 522 | *@param pOth (const Link *) The link to compare to. |
523 | *@returns (bool) Are they equal? | 523 | *@returns (bool) Are they equal? |
524 | */ | 524 | */ |
525 | bool operator==( const Link *pOth ) const | 525 | bool operator==( const Link *pOth ) const |
526 | { | 526 | { |
527 | return ( pLink == pOth ); | 527 | return ( pLink == pOth ); |
528 | } | 528 | } |
529 | 529 | ||
530 | /** | 530 | /** |
531 | * Not equals comparison operator. | 531 | * Not equals comparison operator. |
532 | *@param oth (const iterator &) The iterator to compare to. | 532 | *@param oth (const iterator &) The iterator to compare to. |
533 | *@returns (bool) Are they not equal? | 533 | *@returns (bool) Are they not equal? |
534 | */ | 534 | */ |
535 | bool operator!=( const iterator &oth ) const | 535 | bool operator!=( const iterator &oth ) const |
536 | { | 536 | { |
537 | return ( pLink != oth.pLink ); | 537 | return ( pLink != oth.pLink ); |
538 | } | 538 | } |
539 | 539 | ||
540 | /** | 540 | /** |
541 | * Not equals comparison operator. | 541 | * Not equals comparison operator. |
542 | *@param pOth (const Link *) The link to compare to. | 542 | *@param pOth (const Link *) The link to compare to. |
543 | *@returns (bool) Are they not equal? | 543 | *@returns (bool) Are they not equal? |
544 | */ | 544 | */ |
545 | bool operator!=( const Link *pOth ) const | 545 | bool operator!=( const Link *pOth ) const |
546 | { | 546 | { |
547 | return ( pLink != pOth ); | 547 | return ( pLink != pOth ); |
548 | } | 548 | } |
549 | 549 | ||
550 | /** | 550 | /** |
551 | * Dereference operator. | 551 | * Dereference operator. |
552 | *@returns (value_type &) The value. | 552 | *@returns (value_type &) The value. |
553 | */ | 553 | */ |
554 | value &operator*() | 554 | value &operator*() |
555 | { | 555 | { |
556 | return *(pLink->pValue); | 556 | return *(pLink->pValue); |
557 | } | 557 | } |
558 | 558 | ||
559 | /** | 559 | /** |
560 | * Pointer access operator. | 560 | * Pointer access operator. |
561 | *@returns (value_type *) A pointer to the value. | 561 | *@returns (value_type *) A pointer to the value. |
562 | */ | 562 | */ |
563 | value *operator->() | 563 | value *operator->() |
564 | { | 564 | { |
565 | return pLink->pValue; | 565 | return pLink->pValue; |
566 | } | 566 | } |
567 | 567 | ||
568 | iterator &operator++() | 568 | iterator &operator++() |
569 | { | 569 | { |
570 | if( pLink == NULL ) | 570 | if( pLink == NULL ) |
571 | throw Bu::ExceptionBase( | 571 | throw Bu::ExceptionBase( |
572 | "Attempt to iterate past end of list."); | 572 | "Attempt to iterate past end of list."); |
573 | pLink = pLink->pNext; | 573 | pLink = pLink->pNext; |
574 | return *this; | 574 | return *this; |
575 | } | 575 | } |
576 | 576 | ||
577 | iterator &operator--() | 577 | iterator &operator--() |
578 | { | 578 | { |
579 | if( pLink == NULL ) | 579 | if( pLink == NULL ) |
580 | throw Bu::ExceptionBase( | 580 | throw Bu::ExceptionBase( |
581 | "Attempt to iterate past begining of list."); | 581 | "Attempt to iterate past begining of list."); |
582 | pLink = pLink->pPrev; | 582 | pLink = pLink->pPrev; |
583 | return *this; | 583 | return *this; |
584 | } | 584 | } |
585 | 585 | ||
586 | iterator &operator++( int ) | 586 | iterator &operator++( int ) |
587 | { | 587 | { |
588 | if( pLink == NULL ) | 588 | if( pLink == NULL ) |
589 | throw Bu::ExceptionBase( | 589 | throw Bu::ExceptionBase( |
590 | "Attempt to iterate past end of list."); | 590 | "Attempt to iterate past end of list."); |
591 | pLink = pLink->pNext; | 591 | pLink = pLink->pNext; |
592 | return *this; | 592 | return *this; |
593 | } | 593 | } |
594 | 594 | ||
595 | iterator &operator--( int ) | 595 | iterator &operator--( int ) |
596 | { | 596 | { |
597 | if( pLink == NULL ) | 597 | if( pLink == NULL ) |
598 | throw Bu::ExceptionBase( | 598 | throw Bu::ExceptionBase( |
599 | "Attempt to iterate past begining of list."); | 599 | "Attempt to iterate past begining of list."); |
600 | pLink = pLink->pPrev; | 600 | pLink = pLink->pPrev; |
601 | return *this; | 601 | return *this; |
602 | } | 602 | } |
603 | 603 | ||
604 | iterator operator+( int iDelta ) | 604 | iterator operator+( int iDelta ) |
605 | { | 605 | { |
606 | iterator ret( *this ); | 606 | iterator ret( *this ); |
607 | for( int j = 0; j < iDelta; j++ ) | 607 | for( int j = 0; j < iDelta; j++ ) |
608 | { | 608 | { |
609 | if( ret.pLink == NULL ) | 609 | if( ret.pLink == NULL ) |
610 | throw Bu::ExceptionBase( | 610 | throw Bu::ExceptionBase( |
611 | "Attempt to iterate past begining of list."); | 611 | "Attempt to iterate past begining of list."); |
612 | ret.pLink = ret.pLink->pNext; | 612 | ret.pLink = ret.pLink->pNext; |
613 | } | 613 | } |
614 | return ret; | 614 | return ret; |
615 | } | 615 | } |
616 | 616 | ||
617 | iterator operator-( int iDelta ) | 617 | iterator operator-( int iDelta ) |
618 | { | 618 | { |
619 | iterator ret( *this ); | 619 | iterator ret( *this ); |
620 | for( int j = 0; j < iDelta; j++ ) | 620 | for( int j = 0; j < iDelta; j++ ) |
621 | { | 621 | { |
622 | if( ret.pLink == NULL ) | 622 | if( ret.pLink == NULL ) |
623 | throw Bu::ExceptionBase( | 623 | throw Bu::ExceptionBase( |
624 | "Attempt to iterate past begining of list."); | 624 | "Attempt to iterate past begining of list."); |
625 | ret.pLink = ret.pLink->pPrev; | 625 | ret.pLink = ret.pLink->pPrev; |
626 | } | 626 | } |
627 | return ret; | 627 | return ret; |
628 | } | 628 | } |
629 | 629 | ||
630 | operator bool() | 630 | operator bool() |
631 | { | 631 | { |
632 | return pLink != NULL; | 632 | return pLink != NULL; |
633 | } | 633 | } |
634 | 634 | ||
635 | bool isValid() | 635 | bool isValid() |
636 | { | 636 | { |
637 | return pLink != NULL; | 637 | return pLink != NULL; |
638 | } | 638 | } |
639 | 639 | ||
640 | /** | 640 | /** |
641 | * Assignment operator. | 641 | * Assignment operator. |
642 | *@param oth (const iterator &) The other iterator to set this | 642 | *@param oth (const iterator &) The other iterator to set this |
643 | * one to. | 643 | * one to. |
644 | */ | 644 | */ |
645 | iterator &operator=( const iterator &oth ) | 645 | iterator &operator=( const iterator &oth ) |
646 | { | 646 | { |
647 | pLink = oth.pLink; | 647 | pLink = oth.pLink; |
648 | return *this; | 648 | return *this; |
649 | } | 649 | } |
650 | } iterator; | 650 | } iterator; |
651 | 651 | ||
652 | /** | 652 | /** |
653 | *@see iterator | 653 | *@see iterator |
654 | */ | 654 | */ |
655 | typedef struct const_iterator | 655 | typedef struct const_iterator |
656 | { | 656 | { |
657 | friend class List<value, valuealloc, linkalloc>; | 657 | friend class List<value, valuealloc, linkalloc>; |
658 | private: | 658 | private: |
659 | Link *pLink; | 659 | Link *pLink; |
660 | 660 | ||
661 | const_iterator( Link *pLink ) : | 661 | const_iterator( Link *pLink ) : |
662 | pLink( pLink ) | 662 | pLink( pLink ) |
663 | { | 663 | { |
664 | } | 664 | } |
665 | 665 | ||
666 | public: | 666 | public: |
667 | const_iterator() : | 667 | const_iterator() : |
668 | pLink( NULL ) | 668 | pLink( NULL ) |
669 | { | 669 | { |
670 | } | 670 | } |
671 | 671 | ||
672 | const_iterator( const iterator &i ) : | 672 | const_iterator( const iterator &i ) : |
673 | pLink( i.pLink ) | 673 | pLink( i.pLink ) |
674 | { | 674 | { |
675 | } | 675 | } |
676 | 676 | ||
677 | bool operator==( const const_iterator &oth ) const | 677 | bool operator==( const const_iterator &oth ) const |
678 | { | 678 | { |
679 | return ( pLink == oth.pLink ); | 679 | return ( pLink == oth.pLink ); |
680 | } | 680 | } |
681 | 681 | ||
682 | bool operator==( const Link *pOth ) const | 682 | bool operator==( const Link *pOth ) const |
683 | { | 683 | { |
684 | return ( pLink == pOth ); | 684 | return ( pLink == pOth ); |
685 | } | 685 | } |
686 | 686 | ||
687 | bool operator!=( const const_iterator &oth ) const | 687 | bool operator!=( const const_iterator &oth ) const |
688 | { | 688 | { |
689 | return ( pLink != oth.pLink ); | 689 | return ( pLink != oth.pLink ); |
690 | } | 690 | } |
691 | 691 | ||
692 | bool operator!=( const Link *pOth ) const | 692 | bool operator!=( const Link *pOth ) const |
693 | { | 693 | { |
694 | return ( pLink != pOth ); | 694 | return ( pLink != pOth ); |
695 | } | 695 | } |
696 | 696 | ||
697 | const value &operator*() | 697 | const value &operator*() |
698 | { | 698 | { |
699 | return *(pLink->pValue); | 699 | return *(pLink->pValue); |
700 | } | 700 | } |
701 | 701 | ||
702 | const value *operator->() | 702 | const value *operator->() |
703 | { | 703 | { |
704 | return pLink->pValue; | 704 | return pLink->pValue; |
705 | } | 705 | } |
706 | 706 | ||
707 | const_iterator &operator++() | 707 | const_iterator &operator++() |
708 | { | 708 | { |
709 | if( pLink == NULL ) | 709 | if( pLink == NULL ) |
710 | throw Bu::ExceptionBase( | 710 | throw Bu::ExceptionBase( |
711 | "Attempt to iterate past end of list."); | 711 | "Attempt to iterate past end of list."); |
712 | pLink = pLink->pNext; | 712 | pLink = pLink->pNext; |
713 | return *this; | 713 | return *this; |
714 | } | 714 | } |
715 | 715 | ||
716 | const_iterator &operator--() | 716 | const_iterator &operator--() |
717 | { | 717 | { |
718 | if( pLink == NULL ) | 718 | if( pLink == NULL ) |
719 | throw Bu::ExceptionBase( | 719 | throw Bu::ExceptionBase( |
720 | "Attempt to iterate past begining of list."); | 720 | "Attempt to iterate past begining of list."); |
721 | pLink = pLink->pPrev; | 721 | pLink = pLink->pPrev; |
722 | return *this; | 722 | return *this; |
723 | } | 723 | } |
724 | 724 | ||
725 | const_iterator &operator++( int ) | 725 | const_iterator &operator++( int ) |
726 | { | 726 | { |
727 | if( pLink == NULL ) | 727 | if( pLink == NULL ) |
728 | throw Bu::ExceptionBase( | 728 | throw Bu::ExceptionBase( |
729 | "Attempt to iterate past end of list."); | 729 | "Attempt to iterate past end of list."); |
730 | pLink = pLink->pNext; | 730 | pLink = pLink->pNext; |
731 | return *this; | 731 | return *this; |
732 | } | 732 | } |
733 | 733 | ||
734 | const_iterator &operator--( int ) | 734 | const_iterator &operator--( int ) |
735 | { | 735 | { |
736 | if( pLink == NULL ) | 736 | if( pLink == NULL ) |
737 | throw Bu::ExceptionBase( | 737 | throw Bu::ExceptionBase( |
738 | "Attempt to iterate past begining of list."); | 738 | "Attempt to iterate past begining of list."); |
739 | pLink = pLink->pPrev; | 739 | pLink = pLink->pPrev; |
740 | return *this; | 740 | return *this; |
741 | } | 741 | } |
742 | 742 | ||
743 | const_iterator operator+( int iDelta ) | 743 | const_iterator operator+( int iDelta ) |
744 | { | 744 | { |
745 | const_iterator ret( *this ); | 745 | const_iterator ret( *this ); |
746 | for( int j = 0; j < iDelta; j++ ) | 746 | for( int j = 0; j < iDelta; j++ ) |
747 | { | 747 | { |
748 | if( ret.pLink == NULL ) | 748 | if( ret.pLink == NULL ) |
749 | throw Bu::ExceptionBase( | 749 | throw Bu::ExceptionBase( |
750 | "Attempt to iterate past begining of list."); | 750 | "Attempt to iterate past begining of list."); |
751 | ret.pLink = ret.pLink->pNext; | 751 | ret.pLink = ret.pLink->pNext; |
752 | } | 752 | } |
753 | return ret; | 753 | return ret; |
754 | } | 754 | } |
755 | 755 | ||
756 | const_iterator operator-( int iDelta ) | 756 | const_iterator operator-( int iDelta ) |
757 | { | 757 | { |
758 | const_iterator ret( *this ); | 758 | const_iterator ret( *this ); |
759 | for( int j = 0; j < iDelta; j++ ) | 759 | for( int j = 0; j < iDelta; j++ ) |
760 | { | 760 | { |
761 | if( ret.pLink == NULL ) | 761 | if( ret.pLink == NULL ) |
762 | throw Bu::ExceptionBase( | 762 | throw Bu::ExceptionBase( |
763 | "Attempt to iterate past begining of list."); | 763 | "Attempt to iterate past begining of list."); |
764 | ret.pLink = ret.pLink->pPrev; | 764 | ret.pLink = ret.pLink->pPrev; |
765 | } | 765 | } |
766 | return ret; | 766 | return ret; |
767 | } | 767 | } |
768 | 768 | ||
769 | const_iterator &operator=( const iterator &oth ) | 769 | const_iterator &operator=( const iterator &oth ) |
770 | { | 770 | { |
771 | pLink = oth.pLink; | 771 | pLink = oth.pLink; |
772 | return *this; | 772 | return *this; |
773 | } | 773 | } |
774 | 774 | ||
775 | const_iterator &operator=( const const_iterator &oth ) | 775 | const_iterator &operator=( const const_iterator &oth ) |
776 | { | 776 | { |
777 | pLink = oth.pLink; | 777 | pLink = oth.pLink; |
778 | return *this; | 778 | return *this; |
779 | } | 779 | } |
780 | 780 | ||
781 | operator bool() | 781 | operator bool() |
782 | { | 782 | { |
783 | return pLink != NULL; | 783 | return pLink != NULL; |
784 | } | 784 | } |
785 | 785 | ||
786 | bool isValid() | 786 | bool isValid() |
787 | { | 787 | { |
788 | return pLink != NULL; | 788 | return pLink != NULL; |
789 | } | 789 | } |
790 | } const_iterator; | 790 | } const_iterator; |
791 | 791 | ||
792 | /** | 792 | /** |
793 | * Get an iterator pointing to the first item in the list. | 793 | * Get an iterator pointing to the first item in the list. |
794 | *@returns (iterator) | 794 | *@returns (iterator) |
795 | */ | 795 | */ |
796 | iterator begin() | 796 | iterator begin() |
797 | { | 797 | { |
798 | _hardCopy(); | 798 | _hardCopy(); |
799 | return iterator( core->pFirst ); | 799 | return iterator( core->pFirst ); |
800 | } | 800 | } |
801 | 801 | ||
802 | /** | 802 | /** |
803 | * Get a const iterator pointing to the first item in the list. | 803 | * Get a const iterator pointing to the first item in the list. |
804 | *@returns (const const_iterator) | 804 | *@returns (const const_iterator) |
805 | */ | 805 | */ |
806 | const_iterator begin() const | 806 | const_iterator begin() const |
807 | { | 807 | { |
808 | return const_iterator( core->pFirst ); | 808 | return const_iterator( core->pFirst ); |
809 | } | 809 | } |
810 | 810 | ||
811 | /** | 811 | /** |
812 | * Get an iterator pointing to a place just past the last item in | 812 | * Get an iterator pointing to a place just past the last item in |
813 | * the list. | 813 | * the list. |
814 | *@returns (const Link *) | 814 | *@returns (const Link *) |
815 | */ | 815 | */ |
816 | const iterator end() | 816 | const iterator end() |
817 | { | 817 | { |
818 | return iterator( NULL ); | 818 | return iterator( NULL ); |
819 | } | 819 | } |
820 | 820 | ||
821 | /** | 821 | /** |
822 | * Get an iterator pointing to a place just past the last item in | 822 | * Get an iterator pointing to a place just past the last item in |
823 | * the list. | 823 | * the list. |
824 | *@returns (const Link *) | 824 | *@returns (const Link *) |
825 | */ | 825 | */ |
826 | const const_iterator end() const | 826 | const const_iterator end() const |
827 | { | 827 | { |
828 | return const_iterator( NULL ); | 828 | return const_iterator( NULL ); |
829 | } | 829 | } |
830 | 830 | ||
831 | /** | 831 | /** |
832 | * Erase an item from the list. | 832 | * Erase an item from the list. |
833 | *@param i (iterator) The item to erase. | 833 | *@param i (iterator) The item to erase. |
834 | */ | 834 | */ |
835 | MyType &erase( iterator i ) | 835 | MyType &erase( iterator i ) |
836 | { | 836 | { |
837 | _hardCopy(); | 837 | _hardCopy(); |
838 | core->erase( i.pLink ); | 838 | core->erase( i.pLink ); |
839 | 839 | ||
840 | return *this; | 840 | return *this; |
841 | } | 841 | } |
842 | 842 | ||
843 | /** | 843 | /** |
844 | * Erase an item from the list. | 844 | * Erase an item from the list. |
845 | *@param i (iterator) The item to erase. | 845 | *@param i (iterator) The item to erase. |
846 | */ | 846 | */ |
847 | MyType &erase( const_iterator i ) | 847 | MyType &erase( const_iterator i ) |
848 | { | 848 | { |
849 | _hardCopy(); | 849 | _hardCopy(); |
850 | core->erase( i.pLink ); | 850 | core->erase( i.pLink ); |
851 | 851 | ||
852 | return *this; | 852 | return *this; |
853 | } | 853 | } |
854 | 854 | ||
855 | /** | 855 | /** |
856 | * Erase an item from the list if you already know the item. | 856 | * Erase an item from the list if you already know the item. |
857 | *@param v The item to find and erase. | 857 | *@param v The item to find and erase. |
858 | */ | 858 | */ |
859 | MyType &erase( const value &v ) | 859 | MyType &erase( const value &v ) |
860 | { | 860 | { |
861 | for( const_iterator i = begin(); i != end(); i++ ) | 861 | for( const_iterator i = begin(); i != end(); i++ ) |
862 | { | 862 | { |
863 | if( (*i) == v ) | 863 | if( (*i) == v ) |
864 | { | 864 | { |
865 | erase( i ); | 865 | erase( i ); |
866 | return *this; | 866 | return *this; |
867 | } | 867 | } |
868 | } | 868 | } |
869 | 869 | ||
870 | return *this; | 870 | return *this; |
871 | } | 871 | } |
872 | 872 | ||
873 | /** | 873 | /** |
874 | * Erases the first item in the list, identical to pop, but better for | 874 | * Erases the first item in the list, identical to pop, but better for |
875 | * lists that aren't built as stacks, since you know where it will be | 875 | * lists that aren't built as stacks, since you know where it will be |
876 | * erasing from. | 876 | * erasing from. |
877 | */ | 877 | */ |
878 | MyType &eraseFirst() | 878 | MyType &eraseFirst() |
879 | { | 879 | { |
880 | _hardCopy(); | 880 | _hardCopy(); |
881 | erase( begin() ); | 881 | erase( begin() ); |
882 | 882 | ||
883 | return *this; | 883 | return *this; |
884 | } | 884 | } |
885 | 885 | ||
886 | /** | 886 | /** |
887 | * Erases the last item in the list. | 887 | * Erases the last item in the list. |
888 | */ | 888 | */ |
889 | MyType &eraseLast() | 889 | MyType &eraseLast() |
890 | { | 890 | { |
891 | _hardCopy(); | 891 | _hardCopy(); |
892 | core->erase( core->pLast ); | 892 | core->erase( core->pLast ); |
893 | 893 | ||
894 | return *this; | 894 | return *this; |
895 | } | 895 | } |
896 | 896 | ||
897 | iterator find( const value &v ) | 897 | iterator find( const value &v ) |
898 | { | 898 | { |
899 | for( iterator i = begin(); i; i++ ) | 899 | for( iterator i = begin(); i; i++ ) |
900 | { | 900 | { |
901 | if( (*i) == v ) | 901 | if( (*i) == v ) |
902 | return i; | 902 | return i; |
903 | } | 903 | } |
904 | 904 | ||
905 | return end(); | 905 | return end(); |
906 | } | 906 | } |
907 | 907 | ||
908 | const_iterator find( const value &v ) const | 908 | const_iterator find( const value &v ) const |
909 | { | 909 | { |
910 | for( const_iterator i = begin(); i; i++ ) | 910 | for( const_iterator i = begin(); i; i++ ) |
911 | { | 911 | { |
912 | if( (*i) == v ) | 912 | if( (*i) == v ) |
913 | return i; | 913 | return i; |
914 | } | 914 | } |
915 | 915 | ||
916 | return end(); | 916 | return end(); |
917 | } | 917 | } |
918 | 918 | ||
919 | /** | 919 | /** |
920 | * Get the current size of the list. | 920 | * Get the current size of the list. |
921 | *@returns (int) The current size of the list. | 921 | *@returns (int) The current size of the list. |
922 | */ | 922 | */ |
923 | long getSize() const | 923 | long getSize() const |
924 | { | 924 | { |
925 | return core->nSize; | 925 | return core->nSize; |
926 | } | 926 | } |
927 | 927 | ||
928 | /** | 928 | /** |
929 | * Get the first item in the list. | 929 | * Get the first item in the list. |
930 | *@returns (value_type &) The first item in the list. | 930 | *@returns (value_type &) The first item in the list. |
931 | */ | 931 | */ |
932 | value &first() | 932 | value &first() |
933 | { | 933 | { |
934 | if( core->pFirst->pValue == NULL ) | 934 | if( core->pFirst->pValue == NULL ) |
935 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); | 935 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); |
936 | _hardCopy(); | 936 | _hardCopy(); |
937 | return *core->pFirst->pValue; | 937 | return *core->pFirst->pValue; |
938 | } | 938 | } |
939 | 939 | ||
940 | /** | 940 | /** |
941 | * Get the first item in the list. | 941 | * Get the first item in the list. |
942 | *@returns (const value_type &) The first item in the list. | 942 | *@returns (const value_type &) The first item in the list. |
943 | */ | 943 | */ |
944 | const value &first() const | 944 | const value &first() const |
945 | { | 945 | { |
946 | if( core->pFirst->pValue == NULL ) | 946 | if( core->pFirst->pValue == NULL ) |
947 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); | 947 | throw Bu::ExceptionBase("Attempt to read first element from empty list."); |
948 | return *core->pFirst->pValue; | 948 | return *core->pFirst->pValue; |
949 | } | 949 | } |
950 | 950 | ||
951 | /** | 951 | /** |
952 | * Get the last item in the list. | 952 | * Get the last item in the list. |
953 | *@returns (value_type &) The last item in the list. | 953 | *@returns (value_type &) The last item in the list. |
954 | */ | 954 | */ |
955 | value &last() | 955 | value &last() |
956 | { | 956 | { |
957 | _hardCopy(); | 957 | _hardCopy(); |
958 | return *core->pLast->pValue; | 958 | return *core->pLast->pValue; |
959 | } | 959 | } |
960 | 960 | ||
961 | /** | 961 | /** |
962 | * Get the last item in the list. | 962 | * Get the last item in the list. |
963 | *@returns (const value_type &) The last item in the list. | 963 | *@returns (const value_type &) The last item in the list. |
964 | */ | 964 | */ |
965 | const value &last() const | 965 | const value &last() const |
966 | { | 966 | { |
967 | return *core->pLast->pValue; | 967 | return *core->pLast->pValue; |
968 | } | 968 | } |
969 | 969 | ||
970 | bool isEmpty() const | 970 | bool isEmpty() const |
971 | { | 971 | { |
972 | return (core->nSize == 0); | 972 | return (core->nSize == 0); |
973 | } | 973 | } |
974 | 974 | ||
975 | protected: | 975 | protected: |
976 | virtual Core *_copyCore( Core *src ) | 976 | virtual Core *_copyCore( Core *src ) |
977 | { | 977 | { |
978 | Core *pRet = _allocateCore(); | 978 | Core *pRet = _allocateCore(); |
979 | for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) | 979 | for( Link *pCur = src->pFirst; pCur; pCur = pCur->pNext ) |
980 | { | 980 | { |
981 | pRet->append( *pCur->pValue ); | 981 | pRet->append( *pCur->pValue ); |
982 | } | 982 | } |
983 | return pRet; | 983 | return pRet; |
984 | } | 984 | } |
985 | 985 | ||
986 | private: | 986 | private: |
987 | }; | 987 | }; |
988 | 988 | ||
989 | class Formatter; | 989 | class Formatter; |
990 | Formatter &operator<<( Formatter &rOut, char *sStr ); | 990 | Formatter &operator<<( Formatter &rOut, char *sStr ); |
991 | Formatter &operator<<( Formatter &rOut, signed char c ); | 991 | Formatter &operator<<( Formatter &rOut, signed char c ); |
992 | template<typename a, typename b, typename c> | 992 | template<typename a, typename b, typename c> |
993 | Formatter &operator<<( Formatter &f, const Bu::List<a,b,c> &l ) | 993 | Formatter &operator<<( Formatter &f, const Bu::List<a,b,c> &l ) |
994 | { | 994 | { |
995 | f << '['; | 995 | f << '['; |
996 | for( typename Bu::List<a,b,c>::const_iterator i = l.begin(); i; i++ ) | 996 | for( typename Bu::List<a,b,c>::const_iterator i = l.begin(); i; i++ ) |
997 | { | 997 | { |
998 | if( i != l.begin() ) | 998 | if( i != l.begin() ) |
999 | f << ", "; | 999 | f << ", "; |
1000 | f << *i; | 1000 | f << *i; |
1001 | } | 1001 | } |
1002 | f << ']'; | 1002 | f << ']'; |
1003 | 1003 | ||
1004 | return f; | 1004 | return f; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | template<typename value, typename a, typename b> | 1007 | template<typename value, typename a, typename b> |
1008 | ArchiveBase &operator<<( ArchiveBase &ar, const List<value,a,b> &h ) | 1008 | ArchiveBase &operator<<( ArchiveBase &ar, const List<value,a,b> &h ) |
1009 | { | 1009 | { |
1010 | ar << h.getSize(); | 1010 | ar << h.getSize(); |
1011 | for( typename List<value>::const_iterator i = h.begin(); i != h.end(); i++ ) | 1011 | for( typename List<value>::const_iterator i = h.begin(); i != h.end(); i++ ) |
1012 | { | 1012 | { |
1013 | ar << (*i); | 1013 | ar << (*i); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | return ar; | 1016 | return ar; |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | template<typename value, typename a, typename b> | 1019 | template<typename value, typename a, typename b> |
1020 | ArchiveBase &operator>>( ArchiveBase &ar, List<value,a,b> &h ) | 1020 | ArchiveBase &operator>>( ArchiveBase &ar, List<value,a,b> &h ) |
1021 | { | 1021 | { |
1022 | h.clear(); | 1022 | h.clear(); |
1023 | long nSize; | 1023 | long nSize; |
1024 | ar >> nSize; | 1024 | ar >> nSize; |
1025 | 1025 | ||
1026 | for( long j = 0; j < nSize; j++ ) | 1026 | for( long j = 0; j < nSize; j++ ) |
1027 | { | 1027 | { |
1028 | value v; | 1028 | value v; |
1029 | ar >> v; | 1029 | ar >> v; |
1030 | h.append( v ); | 1030 | h.append( v ); |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | return ar; | 1033 | return ar; |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | } | 1036 | } |
1037 | 1037 | ||
diff --git a/src/stable/logger.cpp b/src/stable/logger.cpp index fa0987e..7d49193 100644 --- a/src/stable/logger.cpp +++ b/src/stable/logger.cpp | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | Bu::Logger::Logger() | 15 | Bu::Logger::Logger() |
16 | { | 16 | { |
17 | setFormat("%t"); | 17 | setFormat("%t"); |
18 | } | 18 | } |
19 | 19 | ||
20 | Bu::Logger::~Logger() | 20 | Bu::Logger::~Logger() |
@@ -24,186 +24,186 @@ Bu::Logger::~Logger() | |||
24 | void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) | 24 | void Bu::Logger::log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...) |
25 | { | 25 | { |
26 | #ifndef WIN32 | 26 | #ifndef WIN32 |
27 | if( (nLevel&nLevelMask) == 0 ) | 27 | if( (nLevel&nLevelMask) == 0 ) |
28 | return; | 28 | return; |
29 | 29 | ||
30 | va_list ap; | 30 | va_list ap; |
31 | va_start( ap, sFormat ); | 31 | va_start( ap, sFormat ); |
32 | char *text; | 32 | char *text; |
33 | if( vasprintf( &text, sFormat, ap ) < 0 ) | 33 | if( vasprintf( &text, sFormat, ap ) < 0 ) |
34 | { | 34 | { |
35 | printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); | 35 | printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WTF?\n"); |
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | va_end(ap); | 38 | va_end(ap); |
39 | 39 | ||
40 | time_t t = time(NULL); | 40 | time_t t = time(NULL); |
41 | 41 | ||
42 | char *line = NULL; | 42 | char *line = NULL; |
43 | struct tm *pTime; | 43 | struct tm *pTime; |
44 | pTime = localtime( &t ); | 44 | pTime = localtime( &t ); |
45 | if ( asprintf( | 45 | if ( asprintf( |
46 | &line, | 46 | &line, |
47 | sLogFormat.getStr(), | 47 | sLogFormat.getStr(), |
48 | pTime->tm_year+1900, | 48 | pTime->tm_year+1900, |
49 | pTime->tm_mon+1, | 49 | pTime->tm_mon+1, |
50 | pTime->tm_mday, | 50 | pTime->tm_mday, |
51 | pTime->tm_hour, | 51 | pTime->tm_hour, |
52 | pTime->tm_min, | 52 | pTime->tm_min, |
53 | pTime->tm_sec, | 53 | pTime->tm_sec, |
54 | nLevel, | 54 | nLevel, |
55 | sFile, | 55 | sFile, |
56 | nLine, | 56 | nLine, |
57 | text, | 57 | text, |
58 | sFunction | 58 | sFunction |
59 | ) < 0 ) | 59 | ) < 0 ) |
60 | { | 60 | { |
61 | //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); | 61 | //printf("LOGGER: ERROR ALLOCATING STRING: %s\n", strerror( errno ) ); |
62 | return; | 62 | return; |
63 | } | 63 | } |
64 | write( fileno(stdout), line, strlen(line) ); | 64 | write( fileno(stdout), line, strlen(line) ); |
65 | free( text ); | 65 | free( text ); |
66 | free( line ); | 66 | free( line ); |
67 | #else | 67 | #else |
68 | #warning Bu::Logger::log IS A STUB for WIN32!!!! | 68 | #warning Bu::Logger::log IS A STUB for WIN32!!!! |
69 | #endif | 69 | #endif |
70 | } | 70 | } |
71 | 71 | ||
72 | void Bu::Logger::setFormat( const Bu::String &str ) | 72 | void Bu::Logger::setFormat( const Bu::String &str ) |
73 | { | 73 | { |
74 | sLogFormat = ""; | 74 | sLogFormat = ""; |
75 | 75 | ||
76 | static char fmts[][4]={ | 76 | static char fmts[][4]={ |
77 | {'y', 'd', '0', '1'}, | 77 | {'y', 'd', '0', '1'}, |
78 | {'m', 'd', '0', '2'}, | 78 | {'m', 'd', '0', '2'}, |
79 | {'d', 'd', '0', '3'}, | 79 | {'d', 'd', '0', '3'}, |
80 | {'h', 'd', '0', '4'}, | 80 | {'h', 'd', '0', '4'}, |
81 | {'M', 'd', '0', '5'}, | 81 | {'M', 'd', '0', '5'}, |
82 | {'s', 'd', '0', '6'}, | 82 | {'s', 'd', '0', '6'}, |
83 | {'L', 'd', '0', '7'}, | 83 | {'L', 'd', '0', '7'}, |
84 | {'f', 's', '0', '8'}, | 84 | {'f', 's', '0', '8'}, |
85 | {'l', 'd', '0', '9'}, | 85 | {'l', 'd', '0', '9'}, |
86 | {'t', 's', '1', '0'}, | 86 | {'t', 's', '1', '0'}, |
87 | {'F', 's', '1', '1'}, | 87 | {'F', 's', '1', '1'}, |
88 | {'\0', '\0', '\0', '\0'}, | 88 | {'\0', '\0', '\0', '\0'}, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | for( const char *s = str.getStr(); *s; s++ ) | 91 | for( const char *s = str.getStr(); *s; s++ ) |
92 | { | 92 | { |
93 | if( *s == '%' ) | 93 | if( *s == '%' ) |
94 | { | 94 | { |
95 | sLogFormat += '%'; | 95 | sLogFormat += '%'; |
96 | Bu::String sBuf; | 96 | Bu::String sBuf; |
97 | for(;;) | 97 | for(;;) |
98 | { | 98 | { |
99 | s++; | 99 | s++; |
100 | int l; | 100 | int l; |
101 | for( l = 0;; l++ ) | 101 | for( l = 0;; l++ ) |
102 | { | 102 | { |
103 | if( fmts[l][0] == '\0' ) | 103 | if( fmts[l][0] == '\0' ) |
104 | { | 104 | { |
105 | sBuf += *s; | 105 | sBuf += *s; |
106 | break; | 106 | break; |
107 | } | 107 | } |
108 | else if( *s == fmts[l][0] ) | 108 | else if( *s == fmts[l][0] ) |
109 | { | 109 | { |
110 | sLogFormat += fmts[l][2]; | 110 | sLogFormat += fmts[l][2]; |
111 | sLogFormat += fmts[l][3]; | 111 | sLogFormat += fmts[l][3]; |
112 | sLogFormat += '$'; | 112 | sLogFormat += '$'; |
113 | sLogFormat += sBuf; | 113 | sLogFormat += sBuf; |
114 | sLogFormat += fmts[l][1]; | 114 | sLogFormat += fmts[l][1]; |
115 | break; | 115 | break; |
116 | } | 116 | } |
117 | } | 117 | } |
118 | if( fmts[l][0] != '\0' ) | 118 | if( fmts[l][0] != '\0' ) |
119 | break; | 119 | break; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | else | 122 | else |
123 | { | 123 | { |
124 | sLogFormat += *s; | 124 | sLogFormat += *s; |
125 | } | 125 | } |
126 | } | 126 | } |
127 | sLogFormat += '\n'; | 127 | sLogFormat += '\n'; |
128 | 128 | ||
129 | //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); | 129 | //write( fileno(stdout), sLogFormat.getStr(), sLogFormat.getSize() ); |
130 | } | 130 | } |
131 | 131 | ||
132 | void Bu::Logger::setMask( uint32_t n ) | 132 | void Bu::Logger::setMask( uint32_t n ) |
133 | { | 133 | { |
134 | nLevelMask = n; | 134 | nLevelMask = n; |
135 | } | 135 | } |
136 | 136 | ||
137 | uint32_t Bu::Logger::getMask() | 137 | uint32_t Bu::Logger::getMask() |
138 | { | 138 | { |
139 | return nLevelMask; | 139 | return nLevelMask; |
140 | } | 140 | } |
141 | 141 | ||
142 | void Bu::Logger::setLevel( uint32_t n ) | 142 | void Bu::Logger::setLevel( uint32_t n ) |
143 | { | 143 | { |
144 | int j; | 144 | int j; |
145 | for( j = 31; j > 0; j-- ) | 145 | for( j = 31; j > 0; j-- ) |
146 | { | 146 | { |
147 | if( (n&(1<<j)) ) | 147 | if( (n&(1<<j)) ) |
148 | { | 148 | { |
149 | for(; j >= 0; j-- ) | 149 | for(; j >= 0; j-- ) |
150 | { | 150 | { |
151 | n |= (1<<j); | 151 | n |= (1<<j); |
152 | } | 152 | } |
153 | nLevelMask = n; | 153 | nLevelMask = n; |
154 | return; | 154 | return; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | void Bu::Logger::hexDump( uint32_t nLevel, const char *sFile, | 159 | void Bu::Logger::hexDump( uint32_t nLevel, const char *sFile, |
160 | const char *sFunction, int nLine, const void *pDataV, long nDataLen, | 160 | const char *sFunction, int nLine, const void *pDataV, long nDataLen, |
161 | const char *lpName ) | 161 | const char *lpName ) |
162 | { | 162 | { |
163 | if( (nLevel&nLevelMask) == 0 ) | 163 | if( (nLevel&nLevelMask) == 0 ) |
164 | return; | 164 | return; |
165 | 165 | ||
166 | log( nLevel, sFile, sFunction, nLine, "Displaying %ld bytes of %s.", nDataLen, lpName ); | 166 | log( nLevel, sFile, sFunction, nLine, "Displaying %ld bytes of %s.", nDataLen, lpName ); |
167 | const unsigned char *pData = (const unsigned char *)pDataV; | 167 | const unsigned char *pData = (const unsigned char *)pDataV; |
168 | int j = 0; | 168 | int j = 0; |
169 | Bu::String sBorder; | 169 | Bu::String sBorder; |
170 | for( int l = 0; l < 8*3+2*8+2+5; l++ ) sBorder += ((l!=11&&l!=37)?("-"):("+")); | 170 | for( int l = 0; l < 8*3+2*8+2+5; l++ ) sBorder += ((l!=11&&l!=37)?("-"):("+")); |
171 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); | 171 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); |
172 | Bu::String sLine; | 172 | Bu::String sLine; |
173 | for(;;) | 173 | for(;;) |
174 | { | 174 | { |
175 | { | 175 | { |
176 | char buf[16]; | 176 | char buf[16]; |
177 | sprintf( buf, "%010d | ", j ); | 177 | sprintf( buf, "%010d | ", j ); |
178 | sLine += buf; | 178 | sLine += buf; |
179 | } | 179 | } |
180 | int kmax = 8; | 180 | int kmax = 8; |
181 | if( nDataLen-j < 8 ) kmax = nDataLen-j; | 181 | if( nDataLen-j < 8 ) kmax = nDataLen-j; |
182 | for(int k = 0; k < 8; k++ ) | 182 | for(int k = 0; k < 8; k++ ) |
183 | { | 183 | { |
184 | if( k < kmax ) | 184 | if( k < kmax ) |
185 | { | 185 | { |
186 | char buf[4]; | 186 | char buf[4]; |
187 | sprintf( buf, "%02X ", (int)((unsigned char)pData[j+k]) ); | 187 | sprintf( buf, "%02X ", (int)((unsigned char)pData[j+k]) ); |
188 | sLine += buf; | 188 | sLine += buf; |
189 | } | 189 | } |
190 | else | 190 | else |
191 | { | 191 | { |
192 | sLine += "-- "; | 192 | sLine += "-- "; |
193 | } | 193 | } |
194 | } | 194 | } |
195 | sLine += "| "; | 195 | sLine += "| "; |
196 | for(int k = 0; k < kmax; k++ ) | 196 | for(int k = 0; k < kmax; k++ ) |
197 | { | 197 | { |
198 | char buf[3]; | 198 | char buf[3]; |
199 | sprintf( buf, "%c", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); | 199 | sprintf( buf, "%c", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); |
200 | sLine += buf; | 200 | sLine += buf; |
201 | } | 201 | } |
202 | log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); | 202 | log( nLevel, sFile, sFunction, nLine, sLine.getStr() ); |
203 | sLine = ""; | 203 | sLine = ""; |
204 | j += kmax; | 204 | j += kmax; |
205 | if( j >= nDataLen ) break; | 205 | if( j >= nDataLen ) break; |
206 | } | 206 | } |
207 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); | 207 | log( nLevel, sFile, sFunction, nLine, sBorder.getStr() ); |
208 | } | 208 | } |
209 | 209 | ||
diff --git a/src/stable/logger.h b/src/stable/logger.h index 198ffa2..bcc5a83 100644 --- a/src/stable/logger.h +++ b/src/stable/logger.h | |||
@@ -13,82 +13,82 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * Simple logging facility. All output goes straight to stdout, unlike the | 17 | * Simple logging facility. All output goes straight to stdout, unlike the |
18 | * old multi-log system. Generally we expect any program complex enough to | 18 | * old multi-log system. Generally we expect any program complex enough to |
19 | * want to use this will have other facilities for processing the logging | 19 | * want to use this will have other facilities for processing the logging |
20 | * output, but if we need it we can add other output methods. | 20 | * output, but if we need it we can add other output methods. |
21 | * | 21 | * |
22 | * Currently implemented as a singleton to avoid clutter with globals, you | 22 | * Currently implemented as a singleton to avoid clutter with globals, you |
23 | * generally never want to use the logging system directly, it's annoying. | 23 | * generally never want to use the logging system directly, it's annoying. |
24 | * Instead use the handy macros lineLog, setLogMask, setLogFormat, and | 24 | * Instead use the handy macros lineLog, setLogMask, setLogFormat, and |
25 | * setLogLevel. They do all the real work for you. | 25 | * setLogLevel. They do all the real work for you. |
26 | * | 26 | * |
27 | * In the log format, you can specify extra information that will be written | 27 | * In the log format, you can specify extra information that will be written |
28 | * to the log with every message, and extras in printf style. Use %X flags | 28 | * to the log with every message, and extras in printf style. Use %X flags |
29 | * where X is one of the following: | 29 | * where X is one of the following: |
30 | * - L - Logging level of the log message (not the current mask) | 30 | * - L - Logging level of the log message (not the current mask) |
31 | * - y - Full year | 31 | * - y - Full year |
32 | * - m - Month | 32 | * - m - Month |
33 | * - d - Day of month | 33 | * - d - Day of month |
34 | * - h - Hour (24-hour format) | 34 | * - h - Hour (24-hour format) |
35 | * - M - Minutes | 35 | * - M - Minutes |
36 | * - s - Seconds | 36 | * - s - Seconds |
37 | * - f - Source file | 37 | * - f - Source file |
38 | * - l - Line number | 38 | * - l - Line number |
39 | * - F - function name | 39 | * - F - function name |
40 | * - t - Text of message (usually important) | 40 | * - t - Text of message (usually important) |
41 | * | 41 | * |
42 | * You can include anything extra that you would like, a newline will always | 42 | * You can include anything extra that you would like, a newline will always |
43 | * be added automatically, so no need to worry about that. You can also | 43 | * be added automatically, so no need to worry about that. You can also |
44 | * include any extra printf style formatting that you would like, for | 44 | * include any extra printf style formatting that you would like, for |
45 | * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. | 45 | * example: "%h:%02M:%02s" for the time 4:02:09 instead of 4:2:9. |
46 | * | 46 | * |
47 | * It's generally handy to create an enum of values you use as levels during | 47 | * It's generally handy to create an enum of values you use as levels during |
48 | * program execution (such as error, warning, info, debug, etc). These | 48 | * program execution (such as error, warning, info, debug, etc). These |
49 | * levels should be treated as bitflags, and the most desirable messages, | 49 | * levels should be treated as bitflags, and the most desirable messages, |
50 | * i.e. serious errors and the like should be low order (0x01), and the much | 50 | * i.e. serious errors and the like should be low order (0x01), and the much |
51 | * less desirable messages, like debugging info, should be higher order | 51 | * less desirable messages, like debugging info, should be higher order |
52 | * (0xF0). During operation you can then set either an explicit mask, | 52 | * (0xF0). During operation you can then set either an explicit mask, |
53 | * selecting just the levels that you would like to see printed, or set the | 53 | * selecting just the levels that you would like to see printed, or set the |
54 | * mask using the setLevel helper function, which simulates verbosity | 54 | * mask using the setLevel helper function, which simulates verbosity |
55 | * levels, enabling every flag lower order than the highest order set bit | 55 | * levels, enabling every flag lower order than the highest order set bit |
56 | * passed. I.E. if you had the following enumerated levels: | 56 | * passed. I.E. if you had the following enumerated levels: |
57 | * | 57 | * |
58 | *@code | 58 | *@code |
59 | enum { | 59 | enum { |
60 | logError = 0x01, | 60 | logError = 0x01, |
61 | logWarning = 0x02, | 61 | logWarning = 0x02, |
62 | logInfo = 0x04, | 62 | logInfo = 0x04, |
63 | logDebug = 0x08 | 63 | logDebug = 0x08 |
64 | }; | 64 | }; |
65 | @endcode | 65 | @endcode |
66 | * And you set the mask with setMask( logInfo ) the only messages you would | 66 | * And you set the mask with setMask( logInfo ) the only messages you would |
67 | * see are the ones catagorized logInfo. However, if you used | 67 | * see are the ones catagorized logInfo. However, if you used |
68 | * setLevel( logInfo ) then you would see logInfo, logWarning, and logError | 68 | * setLevel( logInfo ) then you would see logInfo, logWarning, and logError |
69 | * type messages, since they are lower order. | 69 | * type messages, since they are lower order. |
70 | */ | 70 | */ |
71 | class Logger : public Bu::Singleton<Bu::Logger> | 71 | class Logger : public Bu::Singleton<Bu::Logger> |
72 | { | 72 | { |
73 | friend class Bu::Singleton<Bu::Logger>; | 73 | friend class Bu::Singleton<Bu::Logger>; |
74 | private: | 74 | private: |
75 | Logger(); | 75 | Logger(); |
76 | virtual ~Logger(); | 76 | virtual ~Logger(); |
77 | 77 | ||
78 | public: | 78 | public: |
79 | void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); | 79 | void log( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const char *sFormat, ...); |
80 | 80 | ||
81 | void setFormat( const Bu::String &str ); | 81 | void setFormat( const Bu::String &str ); |
82 | void setMask( uint32_t n ); | 82 | void setMask( uint32_t n ); |
83 | void setLevel( uint32_t n ); | 83 | void setLevel( uint32_t n ); |
84 | uint32_t getMask(); | 84 | uint32_t getMask(); |
85 | 85 | ||
86 | void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); | 86 | void hexDump( uint32_t nLevel, const char *sFile, const char *sFunction, int nLine, const void *pData, long nDataLen, const char *lpName ); |
87 | 87 | ||
88 | private: | 88 | private: |
89 | Bu::String sLogFormat; | 89 | Bu::String sLogFormat; |
90 | uint32_t nLevelMask; | 90 | uint32_t nLevelMask; |
91 | }; | 91 | }; |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
@@ -97,29 +97,29 @@ namespace Bu | |||
97 | * file, line number, and function. | 97 | * file, line number, and function. |
98 | */ | 98 | */ |
99 | #define lineLog( nLevel, sFrmt, ...) \ | 99 | #define lineLog( nLevel, sFrmt, ...) \ |
100 | Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) | 100 | Bu::Logger::getInstance().log( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, sFrmt, ##__VA_ARGS__ ) |
101 | 101 | ||
102 | #define logHexDump( nLevel, pData, iSize, sName ) \ | 102 | #define logHexDump( nLevel, pData, iSize, sName ) \ |
103 | Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) | 103 | Bu::Logger::getInstance().hexDump( nLevel, __FILE__, __PRETTY_FUNCTION__, __LINE__, pData, iSize, sName ) |
104 | 104 | ||
105 | /** | 105 | /** |
106 | * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for | 106 | * Set the Bu::Logger logging mask directly. See Bu::Logger::setMask for |
107 | * details. | 107 | * details. |
108 | */ | 108 | */ |
109 | #define setLogMask( nLevel ) \ | 109 | #define setLogMask( nLevel ) \ |
110 | Bu::Logger::getInstance().setMask( nLevel ) | 110 | Bu::Logger::getInstance().setMask( nLevel ) |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * Set the Bu::Logger format. See Bu::Logger::setFormat for details. | 113 | * Set the Bu::Logger format. See Bu::Logger::setFormat for details. |
114 | */ | 114 | */ |
115 | #define setLogFormat( sFrmt ) \ | 115 | #define setLogFormat( sFrmt ) \ |
116 | Bu::Logger::getInstance().setFormat( sFrmt ) | 116 | Bu::Logger::getInstance().setFormat( sFrmt ) |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel | 119 | * Set the Bu::Logger logging mask simulating levels. See Bu::Logger::setLevel |
120 | * for details. | 120 | * for details. |
121 | */ | 121 | */ |
122 | #define setLogLevel( nLevel ) \ | 122 | #define setLogLevel( nLevel ) \ |
123 | Bu::Logger::getInstance().setLevel( nLevel ) | 123 | Bu::Logger::getInstance().setLevel( nLevel ) |
124 | 124 | ||
125 | #endif | 125 | #endif |
diff --git a/src/stable/lzma.cpp b/src/stable/lzma.cpp index 9df8f57..9ec2ce0 100644 --- a/src/stable/lzma.cpp +++ b/src/stable/lzma.cpp | |||
@@ -15,234 +15,234 @@ | |||
15 | using namespace Bu; | 15 | using namespace Bu; |
16 | 16 | ||
17 | Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : | 17 | Bu::Lzma::Lzma( Bu::Stream &rNext, int nCompression, Format eFmt ) : |
18 | Bu::Filter( rNext ), | 18 | Bu::Filter( rNext ), |
19 | prState( NULL ), | 19 | prState( NULL ), |
20 | nCompression( nCompression ), | 20 | nCompression( nCompression ), |
21 | sTotalOut( 0 ), | 21 | sTotalOut( 0 ), |
22 | eFmt( eFmt ), | 22 | eFmt( eFmt ), |
23 | bEos( false ) | 23 | bEos( false ) |
24 | { | 24 | { |
25 | TRACE( nCompression ); | 25 | TRACE( nCompression ); |
26 | start(); | 26 | start(); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Lzma::~Lzma() | 29 | Bu::Lzma::~Lzma() |
30 | { | 30 | { |
31 | TRACE(); | 31 | TRACE(); |
32 | stop(); | 32 | stop(); |
33 | } | 33 | } |
34 | 34 | ||
35 | void Bu::Lzma::start() | 35 | void Bu::Lzma::start() |
36 | { | 36 | { |
37 | TRACE(); | 37 | TRACE(); |
38 | nBufSize = 64*1024; | 38 | nBufSize = 64*1024; |
39 | pBuf = new char[nBufSize]; | 39 | pBuf = new char[nBufSize]; |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::size Bu::Lzma::stop() | 42 | Bu::size Bu::Lzma::stop() |
43 | { | 43 | { |
44 | TRACE(); | 44 | TRACE(); |
45 | if( pState ) | 45 | if( pState ) |
46 | { | 46 | { |
47 | if( bReading ) | 47 | if( bReading ) |
48 | { | 48 | { |
49 | lzma_end( pState ); | 49 | lzma_end( pState ); |
50 | delete[] pBuf; | 50 | delete[] pBuf; |
51 | pBuf = NULL; | 51 | pBuf = NULL; |
52 | delete pState; | 52 | delete pState; |
53 | prState = NULL; | 53 | prState = NULL; |
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | else | 56 | else |
57 | { | 57 | { |
58 | for(;;) | 58 | for(;;) |
59 | { | 59 | { |
60 | pState->next_in = NULL; | 60 | pState->next_in = NULL; |
61 | pState->avail_in = 0; | 61 | pState->avail_in = 0; |
62 | pState->avail_out = nBufSize; | 62 | pState->avail_out = nBufSize; |
63 | pState->next_out = (uint8_t *)pBuf; | 63 | pState->next_out = (uint8_t *)pBuf; |
64 | int res = lzma_code( pState, LZMA_FINISH ); | 64 | int res = lzma_code( pState, LZMA_FINISH ); |
65 | if( pState->avail_out < nBufSize ) | 65 | if( pState->avail_out < nBufSize ) |
66 | { | 66 | { |
67 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 67 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
68 | } | 68 | } |
69 | if( res == LZMA_STREAM_END ) | 69 | if( res == LZMA_STREAM_END ) |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | lzma_end( pState ); | 72 | lzma_end( pState ); |
73 | delete[] pBuf; | 73 | delete[] pBuf; |
74 | pBuf = NULL; | 74 | pBuf = NULL; |
75 | delete pState; | 75 | delete pState; |
76 | prState = NULL; | 76 | prState = NULL; |
77 | return sTotalOut; | 77 | return sTotalOut; |
78 | } | 78 | } |
79 | } | 79 | } |
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::Lzma::lzmaError( int code ) | 83 | void Bu::Lzma::lzmaError( int code ) |
84 | { | 84 | { |
85 | TRACE( code ); | 85 | TRACE( code ); |
86 | switch( code ) | 86 | switch( code ) |
87 | { | 87 | { |
88 | case LZMA_OK: | 88 | case LZMA_OK: |
89 | case LZMA_STREAM_END: | 89 | case LZMA_STREAM_END: |
90 | case LZMA_NO_CHECK: | 90 | case LZMA_NO_CHECK: |
91 | case LZMA_UNSUPPORTED_CHECK: | 91 | case LZMA_UNSUPPORTED_CHECK: |
92 | break; | 92 | break; |
93 | 93 | ||
94 | case LZMA_MEM_ERROR: | 94 | case LZMA_MEM_ERROR: |
95 | throw ExceptionBase("Lzma: Memory allocation error."); | 95 | throw ExceptionBase("Lzma: Memory allocation error."); |
96 | 96 | ||
97 | case LZMA_MEMLIMIT_ERROR: | 97 | case LZMA_MEMLIMIT_ERROR: |
98 | throw ExceptionBase("Lzma: Memory usage limit was reached."); | 98 | throw ExceptionBase("Lzma: Memory usage limit was reached."); |
99 | 99 | ||
100 | case LZMA_FORMAT_ERROR: | 100 | case LZMA_FORMAT_ERROR: |
101 | throw ExceptionBase("Lzma: File format not recognized."); | 101 | throw ExceptionBase("Lzma: File format not recognized."); |
102 | 102 | ||
103 | case LZMA_OPTIONS_ERROR: | 103 | case LZMA_OPTIONS_ERROR: |
104 | throw ExceptionBase("Lzma: Invalid or unsupported options."); | 104 | throw ExceptionBase("Lzma: Invalid or unsupported options."); |
105 | 105 | ||
106 | case LZMA_DATA_ERROR: | 106 | case LZMA_DATA_ERROR: |
107 | throw ExceptionBase("Lzma: Data is corrupt."); | 107 | throw ExceptionBase("Lzma: Data is corrupt."); |
108 | 108 | ||
109 | case LZMA_BUF_ERROR: | 109 | case LZMA_BUF_ERROR: |
110 | throw ExceptionBase("Lzma: No progress is possible."); | 110 | throw ExceptionBase("Lzma: No progress is possible."); |
111 | 111 | ||
112 | case LZMA_PROG_ERROR: | 112 | case LZMA_PROG_ERROR: |
113 | throw ExceptionBase("Lzma: Programming error."); | 113 | throw ExceptionBase("Lzma: Programming error."); |
114 | 114 | ||
115 | default: | 115 | default: |
116 | throw ExceptionBase("Lzma: Unknown error encountered." ); | 116 | throw ExceptionBase("Lzma: Unknown error encountered." ); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) | 120 | Bu::size Bu::Lzma::read( void *pData, Bu::size nBytes ) |
121 | { | 121 | { |
122 | TRACE( pData, nBytes ); | 122 | TRACE( pData, nBytes ); |
123 | if( !pState ) | 123 | if( !pState ) |
124 | { | 124 | { |
125 | prState = new ::lzma_stream; | 125 | prState = new ::lzma_stream; |
126 | lzma_stream zEmpty = LZMA_STREAM_INIT; | 126 | lzma_stream zEmpty = LZMA_STREAM_INIT; |
127 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); | 127 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); |
128 | 128 | ||
129 | bReading = true; | 129 | bReading = true; |
130 | lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); | 130 | lzmaError( lzma_auto_decoder( pState, UINT64_MAX, 0 ) ); |
131 | pState->next_in = (uint8_t *)pBuf; | 131 | pState->next_in = (uint8_t *)pBuf; |
132 | pState->avail_in = 0; | 132 | pState->avail_in = 0; |
133 | } | 133 | } |
134 | if( bReading == false ) | 134 | if( bReading == false ) |
135 | throw ExceptionBase("This lzma filter is in writing mode, you can't read."); | 135 | throw ExceptionBase("This lzma filter is in writing mode, you can't read."); |
136 | 136 | ||
137 | int nRead = 0; | 137 | int nRead = 0; |
138 | int nReadTotal = pState->total_out; | 138 | int nReadTotal = pState->total_out; |
139 | pState->next_out = (uint8_t *)pData; | 139 | pState->next_out = (uint8_t *)pData; |
140 | pState->avail_out = nBytes; | 140 | pState->avail_out = nBytes; |
141 | for(;;) | 141 | for(;;) |
142 | { | 142 | { |
143 | int ret = lzma_code( pState, LZMA_RUN ); | 143 | int ret = lzma_code( pState, LZMA_RUN ); |
144 | // printf("inflate returned %d; avail in=%d, out=%d\n", ret, | 144 | // printf("inflate returned %d; avail in=%d, out=%d\n", ret, |
145 | // pState->avail_in, pState->avail_out ); | 145 | // pState->avail_in, pState->avail_out ); |
146 | 146 | ||
147 | nReadTotal += nRead-pState->avail_out; | 147 | nReadTotal += nRead-pState->avail_out; |
148 | 148 | ||
149 | if( ret == LZMA_STREAM_END ) | 149 | if( ret == LZMA_STREAM_END ) |
150 | { | 150 | { |
151 | bEos = true; | 151 | bEos = true; |
152 | if( pState->avail_in > 0 ) | 152 | if( pState->avail_in > 0 ) |
153 | { | 153 | { |
154 | if( rNext.isSeekable() ) | 154 | if( rNext.isSeekable() ) |
155 | { | 155 | { |
156 | rNext.seek( -pState->avail_in ); | 156 | rNext.seek( -pState->avail_in ); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | return nBytes-pState->avail_out; | 159 | return nBytes-pState->avail_out; |
160 | } | 160 | } |
161 | // if( ret != LZMA_BUF_ERROR ) | 161 | // if( ret != LZMA_BUF_ERROR ) |
162 | lzmaError( ret ); | 162 | lzmaError( ret ); |
163 | 163 | ||
164 | if( pState->avail_out ) | 164 | if( pState->avail_out ) |
165 | { | 165 | { |
166 | if( pState->avail_in == 0 ) | 166 | if( pState->avail_in == 0 ) |
167 | { | 167 | { |
168 | nRead = rNext.read( pBuf, nBufSize ); | 168 | nRead = rNext.read( pBuf, nBufSize ); |
169 | if( nRead == 0 && rNext.isEos() ) | 169 | if( nRead == 0 && rNext.isEos() ) |
170 | { | 170 | { |
171 | throw Bu::ExceptionBase("Premature end of underlying " | 171 | throw Bu::ExceptionBase("Premature end of underlying " |
172 | "stream found reading deflate stream."); | 172 | "stream found reading deflate stream."); |
173 | } | 173 | } |
174 | pState->next_in = (uint8_t *)pBuf; | 174 | pState->next_in = (uint8_t *)pBuf; |
175 | pState->avail_in = nRead; | 175 | pState->avail_in = nRead; |
176 | } | 176 | } |
177 | } | 177 | } |
178 | else | 178 | else |
179 | { | 179 | { |
180 | return nBytes-pState->avail_out; | 180 | return nBytes-pState->avail_out; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | return 0; | 183 | return 0; |
184 | } | 184 | } |
185 | 185 | ||
186 | Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) | 186 | Bu::size Bu::Lzma::write( const void *pData, Bu::size nBytes ) |
187 | { | 187 | { |
188 | TRACE( pData, nBytes ); | 188 | TRACE( pData, nBytes ); |
189 | if( !pState ) | 189 | if( !pState ) |
190 | { | 190 | { |
191 | prState = new ::lzma_stream; | 191 | prState = new ::lzma_stream; |
192 | lzma_stream zEmpty = LZMA_STREAM_INIT; | 192 | lzma_stream zEmpty = LZMA_STREAM_INIT; |
193 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); | 193 | Bu::memcpy( prState, &zEmpty, sizeof(lzma_stream) ); |
194 | 194 | ||
195 | bReading = false; | 195 | bReading = false; |
196 | if( eFmt == Xz ) | 196 | if( eFmt == Xz ) |
197 | lzmaError( | 197 | lzmaError( |
198 | lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) | 198 | lzma_easy_encoder( pState, nCompression, LZMA_CHECK_CRC64 ) |
199 | ); | 199 | ); |
200 | else if( eFmt == LzmaAlone ) | 200 | else if( eFmt == LzmaAlone ) |
201 | { | 201 | { |
202 | lzma_options_lzma opt; | 202 | lzma_options_lzma opt; |
203 | lzma_lzma_preset( &opt, nCompression ); | 203 | lzma_lzma_preset( &opt, nCompression ); |
204 | lzmaError( lzma_alone_encoder( pState, &opt ) ); | 204 | lzmaError( lzma_alone_encoder( pState, &opt ) ); |
205 | } | 205 | } |
206 | else | 206 | else |
207 | throw Bu::ExceptionBase("Invalid format for lzma."); | 207 | throw Bu::ExceptionBase("Invalid format for lzma."); |
208 | } | 208 | } |
209 | if( bReading == true ) | 209 | if( bReading == true ) |
210 | throw ExceptionBase("This lzma filter is in reading mode, you can't write."); | 210 | throw ExceptionBase("This lzma filter is in reading mode, you can't write."); |
211 | 211 | ||
212 | pState->next_in = (uint8_t *)pData; | 212 | pState->next_in = (uint8_t *)pData; |
213 | pState->avail_in = nBytes; | 213 | pState->avail_in = nBytes; |
214 | for(;;) | 214 | for(;;) |
215 | { | 215 | { |
216 | pState->avail_out = nBufSize; | 216 | pState->avail_out = nBufSize; |
217 | pState->next_out = (uint8_t *)pBuf; | 217 | pState->next_out = (uint8_t *)pBuf; |
218 | 218 | ||
219 | lzmaError( lzma_code( pState, LZMA_RUN ) ); | 219 | lzmaError( lzma_code( pState, LZMA_RUN ) ); |
220 | 220 | ||
221 | if( pState->avail_out < nBufSize ) | 221 | if( pState->avail_out < nBufSize ) |
222 | { | 222 | { |
223 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); | 223 | sTotalOut += rNext.write( pBuf, nBufSize-pState->avail_out ); |
224 | } | 224 | } |
225 | if( pState->avail_in == 0 ) | 225 | if( pState->avail_in == 0 ) |
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | 228 | ||
229 | return nBytes; | 229 | return nBytes; |
230 | } | 230 | } |
231 | 231 | ||
232 | bool Bu::Lzma::isOpen() | 232 | bool Bu::Lzma::isOpen() |
233 | { | 233 | { |
234 | TRACE(); | 234 | TRACE(); |
235 | return (pState != NULL); | 235 | return (pState != NULL); |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::Lzma::isEos() | 238 | bool Bu::Lzma::isEos() |
239 | { | 239 | { |
240 | TRACE(); | 240 | TRACE(); |
241 | return bEos; | 241 | return bEos; |
242 | } | 242 | } |
243 | 243 | ||
244 | Bu::size Bu::Lzma::getCompressedSize() | 244 | Bu::size Bu::Lzma::getCompressedSize() |
245 | { | 245 | { |
246 | return sTotalOut; | 246 | return sTotalOut; |
247 | } | 247 | } |
248 | 248 | ||
diff --git a/src/stable/lzma.h b/src/stable/lzma.h index 7118a6b..40963cc 100644 --- a/src/stable/lzma.h +++ b/src/stable/lzma.h | |||
@@ -14,46 +14,46 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as | 18 | * Provides XZ compression and decompression, both LZMA1 (LzmaAlone) as |
19 | * well as the newer LZMA2 (xz) format. This uses .xz by default. | 19 | * well as the newer LZMA2 (xz) format. This uses .xz by default. |
20 | * | 20 | * |
21 | *@ingroup Streams | 21 | *@ingroup Streams |
22 | *@ingroup Compression | 22 | *@ingroup Compression |
23 | */ | 23 | */ |
24 | class Lzma : public Bu::Filter | 24 | class Lzma : public Bu::Filter |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | enum Format | 27 | enum Format |
28 | { | 28 | { |
29 | Xz = 0x01, | 29 | Xz = 0x01, |
30 | LzmaAlone = 0x02, | 30 | LzmaAlone = 0x02, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); | 33 | Lzma( Bu::Stream &rNext, int nCompression=6, Format eFmt=Xz ); |
34 | virtual ~Lzma(); | 34 | virtual ~Lzma(); |
35 | 35 | ||
36 | virtual void start(); | 36 | virtual void start(); |
37 | virtual Bu::size stop(); | 37 | virtual Bu::size stop(); |
38 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 38 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
39 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 39 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
40 | 40 | ||
41 | virtual bool isOpen(); | 41 | virtual bool isOpen(); |
42 | virtual bool isEos(); | 42 | virtual bool isEos(); |
43 | 43 | ||
44 | Bu::size getCompressedSize(); | 44 | Bu::size getCompressedSize(); |
45 | 45 | ||
46 | private: | 46 | private: |
47 | void lzmaError( int code ); | 47 | void lzmaError( int code ); |
48 | void *prState; | 48 | void *prState; |
49 | bool bReading; | 49 | bool bReading; |
50 | int nCompression; | 50 | int nCompression; |
51 | char *pBuf; | 51 | char *pBuf; |
52 | uint32_t nBufSize; | 52 | uint32_t nBufSize; |
53 | Bu::size sTotalOut; | 53 | Bu::size sTotalOut; |
54 | Format eFmt; | 54 | Format eFmt; |
55 | bool bEos; | 55 | bool bEos; |
56 | }; | 56 | }; |
57 | } | 57 | } |
58 | 58 | ||
59 | #endif | 59 | #endif |
diff --git a/src/stable/md5.cpp b/src/stable/md5.cpp index c1d993f..e62cbf4 100644 --- a/src/stable/md5.cpp +++ b/src/stable/md5.cpp | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | Bu::Md5::Md5() | 20 | Bu::Md5::Md5() |
21 | { | 21 | { |
22 | reset(); | 22 | reset(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::Md5::~Md5() | 25 | Bu::Md5::~Md5() |
@@ -28,15 +28,15 @@ Bu::Md5::~Md5() | |||
28 | 28 | ||
29 | void Bu::Md5::reset() | 29 | void Bu::Md5::reset() |
30 | { | 30 | { |
31 | // These are the magic seed numbers... | 31 | // These are the magic seed numbers... |
32 | 32 | ||
33 | sum[0] = 0x67452301U; | 33 | sum[0] = 0x67452301U; |
34 | sum[1] = 0xEFCDAB89U; | 34 | sum[1] = 0xEFCDAB89U; |
35 | sum[2] = 0x98BADCFEU; | 35 | sum[2] = 0x98BADCFEU; |
36 | sum[3] = 0x10325476U; | 36 | sum[3] = 0x10325476U; |
37 | 37 | ||
38 | uBits[0] = 0; | 38 | uBits[0] = 0; |
39 | uBits[1] = 0; | 39 | uBits[1] = 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) | 42 | void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -45,102 +45,102 @@ void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) | |||
45 | 45 | ||
46 | void Bu::Md5::addData( const void *sVData, int iSize ) | 46 | void Bu::Md5::addData( const void *sVData, int iSize ) |
47 | { | 47 | { |
48 | const char *sData = (const char *)sVData; | 48 | const char *sData = (const char *)sVData; |
49 | uint32_t t; | 49 | uint32_t t; |
50 | 50 | ||
51 | t = uBits[0]; | 51 | t = uBits[0]; |
52 | if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) | 52 | if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t ) |
53 | uBits[1]++; | 53 | uBits[1]++; |
54 | uBits[1] += iSize >> 29; | 54 | uBits[1] += iSize >> 29; |
55 | 55 | ||
56 | t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ | 56 | t = (t >> 3) & 0x3f; /* How many bytes we have buffered */ |
57 | 57 | ||
58 | /* Handle any leading odd-sized chunks */ | 58 | /* Handle any leading odd-sized chunks */ |
59 | if( t ) | 59 | if( t ) |
60 | { | 60 | { |
61 | unsigned char *p = (unsigned char *) inbuf + t; | 61 | unsigned char *p = (unsigned char *) inbuf + t; |
62 | 62 | ||
63 | t = 64 - t; | 63 | t = 64 - t; |
64 | if( (uint32_t)iSize < t ) { | 64 | if( (uint32_t)iSize < t ) { |
65 | memcpy( p, sData, iSize ); | 65 | memcpy( p, sData, iSize ); |
66 | return; | 66 | return; |
67 | } | 67 | } |
68 | memcpy( p, sData, t ); | 68 | memcpy( p, sData, t ); |
69 | toLittleEndian( inbuf, 16 ); | 69 | toLittleEndian( inbuf, 16 ); |
70 | compBlock( sum, (uint32_t *)inbuf ); | 70 | compBlock( sum, (uint32_t *)inbuf ); |
71 | sData += t; | 71 | sData += t; |
72 | iSize -= t; | 72 | iSize -= t; |
73 | } | 73 | } |
74 | 74 | ||
75 | /* Process data in 64-byte chunks */ | 75 | /* Process data in 64-byte chunks */ |
76 | while( iSize >= 64 ) | 76 | while( iSize >= 64 ) |
77 | { | 77 | { |
78 | memcpy( inbuf, sData, 64 ); | 78 | memcpy( inbuf, sData, 64 ); |
79 | toLittleEndian( inbuf, 16 ); | 79 | toLittleEndian( inbuf, 16 ); |
80 | compBlock( sum, (uint32_t *)inbuf ); | 80 | compBlock( sum, (uint32_t *)inbuf ); |
81 | sData += 64; | 81 | sData += 64; |
82 | iSize -= 64; | 82 | iSize -= 64; |
83 | } | 83 | } |
84 | 84 | ||
85 | /* Handle any remaining bytes of data. */ | 85 | /* Handle any remaining bytes of data. */ |
86 | memcpy( inbuf, sData, iSize ); | 86 | memcpy( inbuf, sData, iSize ); |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::String Bu::Md5::getResult() | 89 | Bu::String Bu::Md5::getResult() |
90 | { | 90 | { |
91 | uint32_t lsum[4]; | 91 | uint32_t lsum[4]; |
92 | compCap( lsum ); | 92 | compCap( lsum ); |
93 | return Bu::String( (const char *)lsum, 4*4 ); | 93 | return Bu::String( (const char *)lsum, 4*4 ); |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::Md5::writeResult( Bu::Stream &sOut ) | 96 | void Bu::Md5::writeResult( Bu::Stream &sOut ) |
97 | { | 97 | { |
98 | uint32_t lsum[4]; | 98 | uint32_t lsum[4]; |
99 | compCap( lsum ); | 99 | compCap( lsum ); |
100 | sOut.write( lsum, 4*4 ); | 100 | sOut.write( lsum, 4*4 ); |
101 | } | 101 | } |
102 | 102 | ||
103 | void Bu::Md5::compCap( uint32_t *sumout ) | 103 | void Bu::Md5::compCap( uint32_t *sumout ) |
104 | { | 104 | { |
105 | uint8_t tmpbuf[64]; | 105 | uint8_t tmpbuf[64]; |
106 | memcpy( sumout, sum, 4*4 ); | 106 | memcpy( sumout, sum, 4*4 ); |
107 | memcpy( tmpbuf, inbuf, 64 ); | 107 | memcpy( tmpbuf, inbuf, 64 ); |
108 | 108 | ||
109 | uint32_t count; | 109 | uint32_t count; |
110 | uint8_t *p; | 110 | uint8_t *p; |
111 | 111 | ||
112 | /* Compute number of bytes mod 64 */ | 112 | /* Compute number of bytes mod 64 */ |
113 | count = (uBits[0] >> 3) & 0x3F; | 113 | count = (uBits[0] >> 3) & 0x3F; |
114 | 114 | ||
115 | /* Set the first char of padding to 0x80. This is safe since there is | 115 | /* Set the first char of padding to 0x80. This is safe since there is |
116 | always at least one byte free */ | 116 | always at least one byte free */ |
117 | p = tmpbuf + count; | 117 | p = tmpbuf + count; |
118 | *p++ = 0x80; | 118 | *p++ = 0x80; |
119 | 119 | ||
120 | /* Bytes of padding needed to make 64 bytes */ | 120 | /* Bytes of padding needed to make 64 bytes */ |
121 | count = 64 - 1 - count; | 121 | count = 64 - 1 - count; |
122 | 122 | ||
123 | /* Pad out to 56 mod 64 */ | 123 | /* Pad out to 56 mod 64 */ |
124 | if (count < 8) { | 124 | if (count < 8) { |
125 | /* Two lots of padding: Pad the first block to 64 bytes */ | 125 | /* Two lots of padding: Pad the first block to 64 bytes */ |
126 | memset( p, 0, count ); | 126 | memset( p, 0, count ); |
127 | toLittleEndian( tmpbuf, 16 ); | 127 | toLittleEndian( tmpbuf, 16 ); |
128 | compBlock( sumout, (uint32_t *)tmpbuf ); | 128 | compBlock( sumout, (uint32_t *)tmpbuf ); |
129 | 129 | ||
130 | /* Now fill the next block with 56 bytes */ | 130 | /* Now fill the next block with 56 bytes */ |
131 | memset( tmpbuf, 0, 56); | 131 | memset( tmpbuf, 0, 56); |
132 | } else { | 132 | } else { |
133 | /* Pad block to 56 bytes */ | 133 | /* Pad block to 56 bytes */ |
134 | memset( p, 0, count - 8); | 134 | memset( p, 0, count - 8); |
135 | } | 135 | } |
136 | toLittleEndian( tmpbuf, 14 ); | 136 | toLittleEndian( tmpbuf, 14 ); |
137 | 137 | ||
138 | /* Append length in bits and transform */ | 138 | /* Append length in bits and transform */ |
139 | ((uint32_t *) tmpbuf)[14] = uBits[0]; | 139 | ((uint32_t *) tmpbuf)[14] = uBits[0]; |
140 | ((uint32_t *) tmpbuf)[15] = uBits[1]; | 140 | ((uint32_t *) tmpbuf)[15] = uBits[1]; |
141 | 141 | ||
142 | compBlock( sumout, (uint32_t *)tmpbuf ); | 142 | compBlock( sumout, (uint32_t *)tmpbuf ); |
143 | toLittleEndian((unsigned char *)sumout, 4); | 143 | toLittleEndian((unsigned char *)sumout, 4); |
144 | } | 144 | } |
145 | 145 | ||
146 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | 146 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
@@ -150,15 +150,15 @@ void Bu::Md5::compCap( uint32_t *sumout ) | |||
150 | 150 | ||
151 | /* This is the central step in the MD5 algorithm. */ | 151 | /* This is the central step in the MD5 algorithm. */ |
152 | #define MD5STEP(f, w, x, y, z, data, s) \ | 152 | #define MD5STEP(f, w, x, y, z, data, s) \ |
153 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | 153 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) |
154 | 154 | ||
155 | void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) | 155 | void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) |
156 | { | 156 | { |
157 | register uint32_t a, b, c, d; | 157 | register uint32_t a, b, c, d; |
158 | a = lsum[0]; | 158 | a = lsum[0]; |
159 | b = lsum[1]; | 159 | b = lsum[1]; |
160 | c = lsum[2]; | 160 | c = lsum[2]; |
161 | d = lsum[3]; | 161 | d = lsum[3]; |
162 | 162 | ||
163 | MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7); | 163 | MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7); |
164 | MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12); | 164 | MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12); |
@@ -228,19 +228,19 @@ void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x ) | |||
228 | MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15); | 228 | MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15); |
229 | MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21); | 229 | MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21); |
230 | 230 | ||
231 | lsum[0] += a; | 231 | lsum[0] += a; |
232 | lsum[1] += b; | 232 | lsum[1] += b; |
233 | lsum[2] += c; | 233 | lsum[2] += c; |
234 | lsum[3] += d; | 234 | lsum[3] += d; |
235 | } | 235 | } |
236 | 236 | ||
237 | void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) | 237 | void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count ) |
238 | { | 238 | { |
239 | uint32_t t; | 239 | uint32_t t; |
240 | do { | 240 | do { |
241 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | | 241 | t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | |
242 | ((unsigned) buf[1] << 8 | buf[0]); | 242 | ((unsigned) buf[1] << 8 | buf[0]); |
243 | *(uint32_t *) buf = t; | 243 | *(uint32_t *) buf = t; |
244 | buf += 4; | 244 | buf += 4; |
245 | } while( --count ); | 245 | } while( --count ); |
246 | } | 246 | } |
diff --git a/src/stable/md5.h b/src/stable/md5.h index cb7d396..8845082 100644 --- a/src/stable/md5.h +++ b/src/stable/md5.h | |||
@@ -12,43 +12,43 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Class for easily calculating MD5 sums of just about any data. | 16 | * Class for easily calculating MD5 sums of just about any data. |
17 | * This code is based on some public domain code written by Colin Plumb in | 17 | * This code is based on some public domain code written by Colin Plumb in |
18 | * 1993. | 18 | * 1993. |
19 | *@author Mike Buland | 19 | *@author Mike Buland |
20 | */ | 20 | */ |
21 | class Md5 : public Bu::CryptoHash | 21 | class Md5 : public Bu::CryptoHash |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | /** Build an MD5 sum builder. */ | 24 | /** Build an MD5 sum builder. */ |
25 | Md5(); | 25 | Md5(); |
26 | 26 | ||
27 | /** Deconstruct */ | 27 | /** Deconstruct */ |
28 | virtual ~Md5(); | 28 | virtual ~Md5(); |
29 | 29 | ||
30 | virtual void reset(); | 30 | virtual void reset(); |
31 | virtual void setSalt( const Bu::String &sSalt ); | 31 | virtual void setSalt( const Bu::String &sSalt ); |
32 | virtual void addData( const void *sData, int iSize ); | 32 | virtual void addData( const void *sData, int iSize ); |
33 | using Bu::CryptoHash::addData; | 33 | using Bu::CryptoHash::addData; |
34 | virtual String getResult(); | 34 | virtual String getResult(); |
35 | virtual void writeResult( Bu::Stream &sOut ); | 35 | virtual void writeResult( Bu::Stream &sOut ); |
36 | 36 | ||
37 | private: | 37 | private: |
38 | /** | 38 | /** |
39 | * Compute one block of input data. | 39 | * Compute one block of input data. |
40 | */ | 40 | */ |
41 | void compBlock( uint32_t *lsum, uint32_t *x ); | 41 | void compBlock( uint32_t *lsum, uint32_t *x ); |
42 | void compCap( uint32_t *sumout ); | 42 | void compCap( uint32_t *sumout ); |
43 | 43 | ||
44 | void _addData( uint8_t *target, int &iCurFill, const void *sData, | 44 | void _addData( uint8_t *target, int &iCurFill, const void *sData, |
45 | int iSize ); | 45 | int iSize ); |
46 | void _toLittleEndian( uint8_t *buf, uint32_t count ); | 46 | void _toLittleEndian( uint8_t *buf, uint32_t count ); |
47 | 47 | ||
48 | uint8_t inbuf[64]; | 48 | uint8_t inbuf[64]; |
49 | uint32_t sum[4]; | 49 | uint32_t sum[4]; |
50 | uint32_t uBits[2]; | 50 | uint32_t uBits[2]; |
51 | }; | 51 | }; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #endif | 54 | #endif |
diff --git a/src/stable/membuf.cpp b/src/stable/membuf.cpp index dea9a0e..4d6e8e6 100644 --- a/src/stable/membuf.cpp +++ b/src/stable/membuf.cpp | |||
@@ -10,13 +10,13 @@ | |||
10 | using namespace Bu; | 10 | using namespace Bu; |
11 | 11 | ||
12 | Bu::MemBuf::MemBuf() : | 12 | Bu::MemBuf::MemBuf() : |
13 | nPos( 0 ) | 13 | nPos( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::MemBuf::MemBuf( const Bu::String &str ) : | 17 | Bu::MemBuf::MemBuf( const Bu::String &str ) : |
18 | sBuf( str ), | 18 | sBuf( str ), |
19 | nPos( 0 ) | 19 | nPos( 0 ) |
20 | { | 20 | { |
21 | } | 21 | } |
22 | 22 | ||
@@ -30,76 +30,76 @@ void Bu::MemBuf::close() | |||
30 | 30 | ||
31 | size Bu::MemBuf::read( void *pBuf, size nBytes ) | 31 | size Bu::MemBuf::read( void *pBuf, size nBytes ) |
32 | { | 32 | { |
33 | if( (size)sBuf.getSize()-(size)nPos < nBytes ) | 33 | if( (size)sBuf.getSize()-(size)nPos < nBytes ) |
34 | nBytes = sBuf.getSize()-nPos; | 34 | nBytes = sBuf.getSize()-nPos; |
35 | 35 | ||
36 | memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); | 36 | memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); |
37 | nPos += nBytes; | 37 | nPos += nBytes; |
38 | 38 | ||
39 | return nBytes; | 39 | return nBytes; |
40 | } | 40 | } |
41 | 41 | ||
42 | size Bu::MemBuf::write( const void *pBuf, size nBytes ) | 42 | size Bu::MemBuf::write( const void *pBuf, size nBytes ) |
43 | { | 43 | { |
44 | if( nPos == sBuf.getSize() ) | 44 | if( nPos == sBuf.getSize() ) |
45 | { | 45 | { |
46 | // Easiest, just append the data. | 46 | // Easiest, just append the data. |
47 | sBuf.append( (const char *)pBuf, nBytes ); | 47 | sBuf.append( (const char *)pBuf, nBytes ); |
48 | nPos += nBytes; | 48 | nPos += nBytes; |
49 | return nBytes; | 49 | return nBytes; |
50 | } | 50 | } |
51 | else | 51 | else |
52 | { | 52 | { |
53 | // Trickier, we must do this in two parts, overwrite, then append | 53 | // Trickier, we must do this in two parts, overwrite, then append |
54 | // Frist, overwrite. | 54 | // Frist, overwrite. |
55 | size iOver = sBuf.getSize() - nPos; | 55 | size iOver = sBuf.getSize() - nPos; |
56 | if( iOver > nBytes ) | 56 | if( iOver > nBytes ) |
57 | iOver = nBytes; | 57 | iOver = nBytes; |
58 | memcpy( sBuf.getStr()+nPos, pBuf, iOver ); | 58 | memcpy( sBuf.getStr()+nPos, pBuf, iOver ); |
59 | // Then append | 59 | // Then append |
60 | if( iOver < nBytes ) | 60 | if( iOver < nBytes ) |
61 | { | 61 | { |
62 | sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); | 62 | sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver ); |
63 | } | 63 | } |
64 | nPos += nBytes; | 64 | nPos += nBytes; |
65 | return nBytes; | 65 | return nBytes; |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | size Bu::MemBuf::tell() | 69 | size Bu::MemBuf::tell() |
70 | { | 70 | { |
71 | return nPos; | 71 | return nPos; |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::MemBuf::seek( size offset ) | 74 | void Bu::MemBuf::seek( size offset ) |
75 | { | 75 | { |
76 | nPos += offset; | 76 | nPos += offset; |
77 | if( nPos < 0 ) nPos = 0; | 77 | if( nPos < 0 ) nPos = 0; |
78 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 78 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
79 | } | 79 | } |
80 | 80 | ||
81 | void Bu::MemBuf::setPos( size pos ) | 81 | void Bu::MemBuf::setPos( size pos ) |
82 | { | 82 | { |
83 | nPos = pos; | 83 | nPos = pos; |
84 | if( nPos < 0 ) nPos = 0; | 84 | if( nPos < 0 ) nPos = 0; |
85 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 85 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
86 | } | 86 | } |
87 | 87 | ||
88 | void Bu::MemBuf::setPosEnd( size pos ) | 88 | void Bu::MemBuf::setPosEnd( size pos ) |
89 | { | 89 | { |
90 | nPos = sBuf.getSize()-pos; | 90 | nPos = sBuf.getSize()-pos; |
91 | if( nPos < 0 ) nPos = 0; | 91 | if( nPos < 0 ) nPos = 0; |
92 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); | 92 | else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::MemBuf::isEos() | 95 | bool Bu::MemBuf::isEos() |
96 | { | 96 | { |
97 | return (nPos == sBuf.getSize()); | 97 | return (nPos == sBuf.getSize()); |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::MemBuf::isOpen() | 100 | bool Bu::MemBuf::isOpen() |
101 | { | 101 | { |
102 | return true; | 102 | return true; |
103 | } | 103 | } |
104 | 104 | ||
105 | void Bu::MemBuf::flush() | 105 | void Bu::MemBuf::flush() |
@@ -108,32 +108,32 @@ void Bu::MemBuf::flush() | |||
108 | 108 | ||
109 | bool Bu::MemBuf::canRead() | 109 | bool Bu::MemBuf::canRead() |
110 | { | 110 | { |
111 | return !isEos(); | 111 | return !isEos(); |
112 | } | 112 | } |
113 | 113 | ||
114 | bool Bu::MemBuf::canWrite() | 114 | bool Bu::MemBuf::canWrite() |
115 | { | 115 | { |
116 | return true; | 116 | return true; |
117 | } | 117 | } |
118 | 118 | ||
119 | bool Bu::MemBuf::isReadable() | 119 | bool Bu::MemBuf::isReadable() |
120 | { | 120 | { |
121 | return true; | 121 | return true; |
122 | } | 122 | } |
123 | 123 | ||
124 | bool Bu::MemBuf::isWritable() | 124 | bool Bu::MemBuf::isWritable() |
125 | { | 125 | { |
126 | return true; | 126 | return true; |
127 | } | 127 | } |
128 | 128 | ||
129 | bool Bu::MemBuf::isSeekable() | 129 | bool Bu::MemBuf::isSeekable() |
130 | { | 130 | { |
131 | return true; | 131 | return true; |
132 | } | 132 | } |
133 | 133 | ||
134 | bool Bu::MemBuf::isBlocking() | 134 | bool Bu::MemBuf::isBlocking() |
135 | { | 135 | { |
136 | return true; | 136 | return true; |
137 | } | 137 | } |
138 | 138 | ||
139 | void Bu::MemBuf::setBlocking( bool ) | 139 | void Bu::MemBuf::setBlocking( bool ) |
@@ -142,36 +142,36 @@ void Bu::MemBuf::setBlocking( bool ) | |||
142 | 142 | ||
143 | void Bu::MemBuf::setSize( size iSize ) | 143 | void Bu::MemBuf::setSize( size iSize ) |
144 | { | 144 | { |
145 | if( iSize < 0 ) | 145 | if( iSize < 0 ) |
146 | iSize = 0; | 146 | iSize = 0; |
147 | sBuf.setSize( iSize ); | 147 | sBuf.setSize( iSize ); |
148 | if( nPos > iSize ) | 148 | if( nPos > iSize ) |
149 | nPos = iSize; | 149 | nPos = iSize; |
150 | } | 150 | } |
151 | 151 | ||
152 | Bu::size Bu::MemBuf::getSize() const | 152 | Bu::size Bu::MemBuf::getSize() const |
153 | { | 153 | { |
154 | return sBuf.getSize(); | 154 | return sBuf.getSize(); |
155 | } | 155 | } |
156 | 156 | ||
157 | Bu::size Bu::MemBuf::getBlockSize() const | 157 | Bu::size Bu::MemBuf::getBlockSize() const |
158 | { | 158 | { |
159 | return sBuf.getSize(); | 159 | return sBuf.getSize(); |
160 | } | 160 | } |
161 | 161 | ||
162 | Bu::String Bu::MemBuf::getLocation() const | 162 | Bu::String Bu::MemBuf::getLocation() const |
163 | { | 163 | { |
164 | return ""; | 164 | return ""; |
165 | } | 165 | } |
166 | 166 | ||
167 | Bu::String &Bu::MemBuf::getString() | 167 | Bu::String &Bu::MemBuf::getString() |
168 | { | 168 | { |
169 | return sBuf; | 169 | return sBuf; |
170 | } | 170 | } |
171 | 171 | ||
172 | void Bu::MemBuf::setString( const Bu::String &sNewData ) | 172 | void Bu::MemBuf::setString( const Bu::String &sNewData ) |
173 | { | 173 | { |
174 | sBuf = sNewData; | 174 | sBuf = sNewData; |
175 | nPos = 0; | 175 | nPos = 0; |
176 | } | 176 | } |
177 | 177 | ||
diff --git a/src/stable/membuf.h b/src/stable/membuf.h index f016974..f36e0bc 100644 --- a/src/stable/membuf.h +++ b/src/stable/membuf.h | |||
@@ -16,53 +16,53 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * A memory buffer stream. This provides a read/write stream in memory that | 20 | * A memory buffer stream. This provides a read/write stream in memory that |
21 | * works exactly like a file stream...only in memory. You can seed the | 21 | * works exactly like a file stream...only in memory. You can seed the |
22 | * memory buffer with a Bu::String of your own, or start with an empty one. | 22 | * memory buffer with a Bu::String of your own, or start with an empty one. |
23 | * Due to Bu::String using Bu::SharedCore starting with a string will not | 23 | * Due to Bu::String using Bu::SharedCore starting with a string will not |
24 | * necesarilly cause the MemBuf to make a copy of your memory, but if you're | 24 | * necesarilly cause the MemBuf to make a copy of your memory, but if you're |
25 | * sure you're not going to need to change the stream then use StaticMemBuf. | 25 | * sure you're not going to need to change the stream then use StaticMemBuf. |
26 | *@ingroup Streams | 26 | *@ingroup Streams |
27 | */ | 27 | */ |
28 | class MemBuf : public Stream | 28 | class MemBuf : public Stream |
29 | { | 29 | { |
30 | public: | 30 | public: |
31 | MemBuf(); | 31 | MemBuf(); |
32 | MemBuf( const Bu::String &str ); | 32 | MemBuf( const Bu::String &str ); |
33 | virtual ~MemBuf(); | 33 | virtual ~MemBuf(); |
34 | 34 | ||
35 | virtual void close(); | 35 | virtual void close(); |
36 | virtual size read( void *pBuf, size iBytes ); | 36 | virtual size read( void *pBuf, size iBytes ); |
37 | 37 | ||
38 | virtual size write( const void *pBuf, size iBytes ); | 38 | virtual size write( const void *pBuf, size iBytes ); |
39 | using Stream::write; | 39 | using Stream::write; |
40 | virtual size tell(); | 40 | virtual size tell(); |
41 | virtual void seek( size offset ); | 41 | virtual void seek( size offset ); |
42 | virtual void setPos( size pos ); | 42 | virtual void setPos( size pos ); |
43 | virtual void setPosEnd( size pos ); | 43 | virtual void setPosEnd( size pos ); |
44 | virtual bool isEos(); | 44 | virtual bool isEos(); |
45 | virtual bool isOpen(); | 45 | virtual bool isOpen(); |
46 | virtual void flush(); | 46 | virtual void flush(); |
47 | virtual bool canRead(); | 47 | virtual bool canRead(); |
48 | virtual bool canWrite(); | 48 | virtual bool canWrite(); |
49 | virtual bool isReadable(); | 49 | virtual bool isReadable(); |
50 | virtual bool isWritable(); | 50 | virtual bool isWritable(); |
51 | virtual bool isSeekable(); | 51 | virtual bool isSeekable(); |
52 | virtual bool isBlocking(); | 52 | virtual bool isBlocking(); |
53 | virtual void setBlocking( bool bBlocking=true ); | 53 | virtual void setBlocking( bool bBlocking=true ); |
54 | virtual void setSize( size iSize ); | 54 | virtual void setSize( size iSize ); |
55 | virtual size getSize() const; | 55 | virtual size getSize() const; |
56 | virtual size getBlockSize() const; | 56 | virtual size getBlockSize() const; |
57 | virtual Bu::String getLocation() const; | 57 | virtual Bu::String getLocation() const; |
58 | 58 | ||
59 | Bu::String &getString(); | 59 | Bu::String &getString(); |
60 | void setString( const Bu::String &sNewData ); | 60 | void setString( const Bu::String &sNewData ); |
61 | 61 | ||
62 | private: | 62 | private: |
63 | Bu::String sBuf; | 63 | Bu::String sBuf; |
64 | size nPos; | 64 | size nPos; |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/minicron.cpp b/src/stable/minicron.cpp index 87296ae..c83cd44 100644 --- a/src/stable/minicron.cpp +++ b/src/stable/minicron.cpp | |||
@@ -11,260 +11,260 @@ | |||
11 | #include <time.h> | 11 | #include <time.h> |
12 | 12 | ||
13 | Bu::MiniCron::MiniCron() : | 13 | Bu::MiniCron::MiniCron() : |
14 | jidNext( 1 ) | 14 | jidNext( 1 ) |
15 | { | 15 | { |
16 | } | 16 | } |
17 | 17 | ||
18 | Bu::MiniCron::~MiniCron() | 18 | Bu::MiniCron::~MiniCron() |
19 | { | 19 | { |
20 | while( !hJobs.isEmpty() ) | 20 | while( !hJobs.isEmpty() ) |
21 | { | 21 | { |
22 | delete hJobs.dequeue(); | 22 | delete hJobs.dequeue(); |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
26 | bool Bu::MiniCron::hasJobs() | 26 | bool Bu::MiniCron::hasJobs() |
27 | { | 27 | { |
28 | return !hJobs.isEmpty(); | 28 | return !hJobs.isEmpty(); |
29 | } | 29 | } |
30 | 30 | ||
31 | time_t Bu::MiniCron::getNextRun() | 31 | time_t Bu::MiniCron::getNextRun() |
32 | { | 32 | { |
33 | if( hasJobs() ) | 33 | if( hasJobs() ) |
34 | return hJobs.peek()->getNextRun(); | 34 | return hJobs.peek()->getNextRun(); |
35 | return -1; | 35 | return -1; |
36 | } | 36 | } |
37 | 37 | ||
38 | time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) | 38 | time_t Bu::MiniCron::getNextRun( Bu::MiniCron::JobId jid ) |
39 | { | 39 | { |
40 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) | 40 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( (*i)->getId() == jid ) | 42 | if( (*i)->getId() == jid ) |
43 | { | 43 | { |
44 | return (*i)->getNextRunTime(); | 44 | return (*i)->getNextRunTime(); |
45 | } | 45 | } |
46 | } | 46 | } |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
49 | 49 | ||
50 | void Bu::MiniCron::poll() | 50 | void Bu::MiniCron::poll() |
51 | { | 51 | { |
52 | time_t tNow = time( NULL ); | 52 | time_t tNow = time( NULL ); |
53 | 53 | ||
54 | while( !hJobs.isEmpty() ) | 54 | while( !hJobs.isEmpty() ) |
55 | { | 55 | { |
56 | if( hJobs.peek()->getNextRun() <= tNow ) | 56 | if( hJobs.peek()->getNextRun() <= tNow ) |
57 | { | 57 | { |
58 | Job *pJob = hJobs.dequeue(); | 58 | Job *pJob = hJobs.dequeue(); |
59 | pJob->run(); | 59 | pJob->run(); |
60 | if( pJob->bContinue ) | 60 | if( pJob->bContinue ) |
61 | { | 61 | { |
62 | hJobs.enqueue( pJob ); | 62 | hJobs.enqueue( pJob ); |
63 | } | 63 | } |
64 | else | 64 | else |
65 | { | 65 | { |
66 | delete pJob; | 66 | delete pJob; |
67 | } | 67 | } |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | break; | 71 | break; |
72 | } | 72 | } |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, | 76 | Bu::MiniCron::JobId Bu::MiniCron::addJob( const Bu::String &sName, |
77 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) | 77 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) |
78 | { | 78 | { |
79 | JobId jid = jidNext++; | 79 | JobId jid = jidNext++; |
80 | Job *pJob = new Job( sName, jid ); | 80 | Job *pJob = new Job( sName, jid ); |
81 | pJob->sigJob = sigJob; | 81 | pJob->sigJob = sigJob; |
82 | pJob->pTimer = t.clone(); | 82 | pJob->pTimer = t.clone(); |
83 | pJob->tNextRun = pJob->pTimer->nextTime(); | 83 | pJob->tNextRun = pJob->pTimer->nextTime(); |
84 | hJobs.enqueue( pJob ); | 84 | hJobs.enqueue( pJob ); |
85 | 85 | ||
86 | return jid; | 86 | return jid; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, | 89 | Bu::MiniCron::JobId Bu::MiniCron::addJobOnce( const Bu::String &sName, |
90 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) | 90 | Bu::MiniCron::CronSignal sigJob, const Bu::MiniCron::Timer &t ) |
91 | { | 91 | { |
92 | JobId jid = jidNext++; | 92 | JobId jid = jidNext++; |
93 | Job *pJob = new Job( sName, jid, false ); | 93 | Job *pJob = new Job( sName, jid, false ); |
94 | pJob->sigJob = sigJob; | 94 | pJob->sigJob = sigJob; |
95 | pJob->pTimer = t.clone(); | 95 | pJob->pTimer = t.clone(); |
96 | pJob->tNextRun = pJob->pTimer->nextTime(); | 96 | pJob->tNextRun = pJob->pTimer->nextTime(); |
97 | hJobs.enqueue( pJob ); | 97 | hJobs.enqueue( pJob ); |
98 | 98 | ||
99 | return jid; | 99 | return jid; |
100 | } | 100 | } |
101 | 101 | ||
102 | void Bu::MiniCron::removeJob( JobId jid ) | 102 | void Bu::MiniCron::removeJob( JobId jid ) |
103 | { | 103 | { |
104 | Bu::List<Job *> lJobs; | 104 | Bu::List<Job *> lJobs; |
105 | while( !hJobs.isEmpty() ) | 105 | while( !hJobs.isEmpty() ) |
106 | { | 106 | { |
107 | Job *pJob = hJobs.dequeue(); | 107 | Job *pJob = hJobs.dequeue(); |
108 | if( pJob->getId() == jid ) | 108 | if( pJob->getId() == jid ) |
109 | { | 109 | { |
110 | delete pJob; | 110 | delete pJob; |
111 | } | 111 | } |
112 | else | 112 | else |
113 | lJobs.append( pJob ); | 113 | lJobs.append( pJob ); |
114 | } | 114 | } |
115 | 115 | ||
116 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 116 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
117 | { | 117 | { |
118 | hJobs.enqueue( *i ); | 118 | hJobs.enqueue( *i ); |
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) | 122 | void Bu::MiniCron::runJob( JobId jid, bool bReschedule ) |
123 | { | 123 | { |
124 | Bu::List<Job *> lJobs; | 124 | Bu::List<Job *> lJobs; |
125 | while( !hJobs.isEmpty() ) | 125 | while( !hJobs.isEmpty() ) |
126 | { | 126 | { |
127 | Job *pJob = hJobs.dequeue(); | 127 | Job *pJob = hJobs.dequeue(); |
128 | if( pJob->getId() == jid ) | 128 | if( pJob->getId() == jid ) |
129 | { | 129 | { |
130 | pJob->run( bReschedule ); | 130 | pJob->run( bReschedule ); |
131 | if( !pJob->bContinue ) | 131 | if( !pJob->bContinue ) |
132 | { | 132 | { |
133 | delete pJob; | 133 | delete pJob; |
134 | break; | 134 | break; |
135 | } | 135 | } |
136 | lJobs.append( pJob ); | 136 | lJobs.append( pJob ); |
137 | break; | 137 | break; |
138 | } | 138 | } |
139 | lJobs.append( pJob ); | 139 | lJobs.append( pJob ); |
140 | } | 140 | } |
141 | 141 | ||
142 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 142 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
143 | { | 143 | { |
144 | hJobs.enqueue( *i ); | 144 | hJobs.enqueue( *i ); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) | 148 | void Bu::MiniCron::runJob( const Bu::String &sName, bool bReschedule ) |
149 | { | 149 | { |
150 | Bu::List<Job *> lJobs; | 150 | Bu::List<Job *> lJobs; |
151 | while( !hJobs.isEmpty() ) | 151 | while( !hJobs.isEmpty() ) |
152 | { | 152 | { |
153 | Job *pJob = hJobs.dequeue(); | 153 | Job *pJob = hJobs.dequeue(); |
154 | if( pJob->getName() == sName ) | 154 | if( pJob->getName() == sName ) |
155 | { | 155 | { |
156 | pJob->run( bReschedule ); | 156 | pJob->run( bReschedule ); |
157 | if( !pJob->bContinue ) | 157 | if( !pJob->bContinue ) |
158 | { | 158 | { |
159 | delete pJob; | 159 | delete pJob; |
160 | break; | 160 | break; |
161 | } | 161 | } |
162 | lJobs.append( pJob ); | 162 | lJobs.append( pJob ); |
163 | break; | 163 | break; |
164 | } | 164 | } |
165 | lJobs.append( pJob ); | 165 | lJobs.append( pJob ); |
166 | } | 166 | } |
167 | 167 | ||
168 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) | 168 | for( Bu::List<Job *>::iterator i = lJobs.begin(); i; i++ ) |
169 | { | 169 | { |
170 | hJobs.enqueue( *i ); | 170 | hJobs.enqueue( *i ); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
174 | Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() | 174 | Bu::MiniCron::JobInfoList Bu::MiniCron::getJobInfo() |
175 | { | 175 | { |
176 | JobInfoList lRet; | 176 | JobInfoList lRet; |
177 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) | 177 | for( JobHeap::iterator i = hJobs.begin(); i; i++ ) |
178 | { | 178 | { |
179 | lRet.append( | 179 | lRet.append( |
180 | JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) | 180 | JobInfo( (*i)->getName(), (*i)->getId(), (*i)->getNextRun() ) |
181 | ); | 181 | ); |
182 | } | 182 | } |
183 | lRet.sort(); | 183 | lRet.sort(); |
184 | return lRet; | 184 | return lRet; |
185 | } | 185 | } |
186 | 186 | ||
187 | Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : | 187 | Bu::MiniCron::Job::Job( const Bu::String &sName, JobId jid, bool bRepeat ) : |
188 | sName( sName ), | 188 | sName( sName ), |
189 | pTimer( NULL ), | 189 | pTimer( NULL ), |
190 | bContinue( bRepeat ), | 190 | bContinue( bRepeat ), |
191 | jid( jid ), | 191 | jid( jid ), |
192 | tAdded( time( NULL ) ), | 192 | tAdded( time( NULL ) ), |
193 | iRunCount( 0 ) | 193 | iRunCount( 0 ) |
194 | { | 194 | { |
195 | } | 195 | } |
196 | 196 | ||
197 | Bu::MiniCron::Job::~Job() | 197 | Bu::MiniCron::Job::~Job() |
198 | { | 198 | { |
199 | delete pTimer; | 199 | delete pTimer; |
200 | pTimer = NULL; | 200 | pTimer = NULL; |
201 | } | 201 | } |
202 | 202 | ||
203 | void Bu::MiniCron::Job::run( bool bReschedule ) | 203 | void Bu::MiniCron::Job::run( bool bReschedule ) |
204 | { | 204 | { |
205 | iRunCount++; | 205 | iRunCount++; |
206 | if( bReschedule ) | 206 | if( bReschedule ) |
207 | tNextRun = pTimer->nextTime(); | 207 | tNextRun = pTimer->nextTime(); |
208 | sigJob( *this ); | 208 | sigJob( *this ); |
209 | } | 209 | } |
210 | 210 | ||
211 | time_t Bu::MiniCron::Job::getNextRun() const | 211 | time_t Bu::MiniCron::Job::getNextRun() const |
212 | { | 212 | { |
213 | return tNextRun; | 213 | return tNextRun; |
214 | } | 214 | } |
215 | 215 | ||
216 | void Bu::MiniCron::Job::calcNextRun() | 216 | void Bu::MiniCron::Job::calcNextRun() |
217 | { | 217 | { |
218 | if( pTimer ) | 218 | if( pTimer ) |
219 | tNextRun = pTimer->nextTime(); | 219 | tNextRun = pTimer->nextTime(); |
220 | } | 220 | } |
221 | 221 | ||
222 | void Bu::MiniCron::Job::setTimer( const Timer &t ) | 222 | void Bu::MiniCron::Job::setTimer( const Timer &t ) |
223 | { | 223 | { |
224 | delete pTimer; | 224 | delete pTimer; |
225 | pTimer = t.clone(); | 225 | pTimer = t.clone(); |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::MiniCron::Job::stop() | 228 | void Bu::MiniCron::Job::stop() |
229 | { | 229 | { |
230 | bContinue = false; | 230 | bContinue = false; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::MiniCron::Job::resume() | 233 | void Bu::MiniCron::Job::resume() |
234 | { | 234 | { |
235 | bContinue = true; | 235 | bContinue = true; |
236 | } | 236 | } |
237 | 237 | ||
238 | Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const | 238 | Bu::MiniCron::JobId Bu::MiniCron::Job::getId() const |
239 | { | 239 | { |
240 | return jid; | 240 | return jid; |
241 | } | 241 | } |
242 | 242 | ||
243 | time_t Bu::MiniCron::Job::getTimeCreated() const | 243 | time_t Bu::MiniCron::Job::getTimeCreated() const |
244 | { | 244 | { |
245 | return tAdded; | 245 | return tAdded; |
246 | } | 246 | } |
247 | 247 | ||
248 | int Bu::MiniCron::Job::getRunCount() const | 248 | int Bu::MiniCron::Job::getRunCount() const |
249 | { | 249 | { |
250 | return iRunCount; | 250 | return iRunCount; |
251 | } | 251 | } |
252 | 252 | ||
253 | time_t Bu::MiniCron::Job::getNextRunTime() const | 253 | time_t Bu::MiniCron::Job::getNextRunTime() const |
254 | { | 254 | { |
255 | return tNextRun; | 255 | return tNextRun; |
256 | } | 256 | } |
257 | 257 | ||
258 | Bu::String Bu::MiniCron::Job::getName() const | 258 | Bu::String Bu::MiniCron::Job::getName() const |
259 | { | 259 | { |
260 | return sName; | 260 | return sName; |
261 | } | 261 | } |
262 | 262 | ||
263 | Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, | 263 | Bu::MiniCron::JobInfo::JobInfo( const Bu::String &sName, JobId jid, |
264 | time_t tNext ) : | 264 | time_t tNext ) : |
265 | sName( sName ), | 265 | sName( sName ), |
266 | jid( jid ), | 266 | jid( jid ), |
267 | tNext( tNext ) | 267 | tNext( tNext ) |
268 | { | 268 | { |
269 | } | 269 | } |
270 | 270 | ||
@@ -274,7 +274,7 @@ Bu::MiniCron::JobInfo::~JobInfo() | |||
274 | 274 | ||
275 | bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const | 275 | bool Bu::MiniCron::JobInfo::operator<( const JobInfo &rhs ) const |
276 | { | 276 | { |
277 | return jid < rhs.jid; | 277 | return jid < rhs.jid; |
278 | } | 278 | } |
279 | 279 | ||
280 | Bu::MiniCron::Timer::Timer() | 280 | Bu::MiniCron::Timer::Timer() |
@@ -286,8 +286,8 @@ Bu::MiniCron::Timer::~Timer() | |||
286 | } | 286 | } |
287 | 287 | ||
288 | Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : | 288 | Bu::MiniCron::TimerInterval::TimerInterval( time_t tFirst, time_t tInterval ) : |
289 | tNext( tFirst ), | 289 | tNext( tFirst ), |
290 | tInterval( tInterval ) | 290 | tInterval( tInterval ) |
291 | { | 291 | { |
292 | } | 292 | } |
293 | 293 | ||
@@ -297,14 +297,14 @@ Bu::MiniCron::TimerInterval::~TimerInterval() | |||
297 | 297 | ||
298 | time_t Bu::MiniCron::TimerInterval::nextTime() | 298 | time_t Bu::MiniCron::TimerInterval::nextTime() |
299 | { | 299 | { |
300 | time_t tRet = tNext; | 300 | time_t tRet = tNext; |
301 | tNext += tInterval; | 301 | tNext += tInterval; |
302 | return tRet; | 302 | return tRet; |
303 | } | 303 | } |
304 | 304 | ||
305 | Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : | 305 | Bu::MiniCron::TimerBasic::TimerBasic( const Bu::String &s ) : |
306 | tLast( -1 ), | 306 | tLast( -1 ), |
307 | sSpec( s ) | 307 | sSpec( s ) |
308 | { | 308 | { |
309 | } | 309 | } |
310 | 310 | ||
@@ -314,164 +314,164 @@ Bu::MiniCron::TimerBasic::~TimerBasic() | |||
314 | 314 | ||
315 | time_t Bu::MiniCron::TimerBasic::nextTime() | 315 | time_t Bu::MiniCron::TimerBasic::nextTime() |
316 | { | 316 | { |
317 | if( tLast == -1 ) | 317 | if( tLast == -1 ) |
318 | tLast = time( NULL ); | 318 | tLast = time( NULL ); |
319 | 319 | ||
320 | Bu::String::const_iterator i = sSpec.begin(); | 320 | Bu::String::const_iterator i = sSpec.begin(); |
321 | switch( lex( i ) ) | 321 | switch( lex( i ) ) |
322 | { | 322 | { |
323 | case tokDaily: | 323 | case tokDaily: |
324 | { | 324 | { |
325 | int iHour = lexInt( i ); | 325 | int iHour = lexInt( i ); |
326 | int iMin = lexInt( i ); | 326 | int iMin = lexInt( i ); |
327 | 327 | ||
328 | struct tm t; | 328 | struct tm t; |
329 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 329 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
330 | if( iHour < t.tm_hour || | 330 | if( iHour < t.tm_hour || |
331 | (iHour == t.tm_hour && iMin <= t.tm_min) ) | 331 | (iHour == t.tm_hour && iMin <= t.tm_min) ) |
332 | { | 332 | { |
333 | t.tm_mday++; | 333 | t.tm_mday++; |
334 | } | 334 | } |
335 | t.tm_hour = iHour; | 335 | t.tm_hour = iHour; |
336 | t.tm_min = iMin; | 336 | t.tm_min = iMin; |
337 | t.tm_sec = 0; | 337 | t.tm_sec = 0; |
338 | tLast = mktime( &t ); | 338 | tLast = mktime( &t ); |
339 | } | 339 | } |
340 | break; | 340 | break; |
341 | 341 | ||
342 | case tokHourly: | 342 | case tokHourly: |
343 | { | 343 | { |
344 | int iMin = lexInt( i ); | 344 | int iMin = lexInt( i ); |
345 | 345 | ||
346 | struct tm t; | 346 | struct tm t; |
347 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 347 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
348 | if( iMin <= t.tm_min ) | 348 | if( iMin <= t.tm_min ) |
349 | t.tm_hour++; | 349 | t.tm_hour++; |
350 | t.tm_min = iMin; | 350 | t.tm_min = iMin; |
351 | t.tm_sec = 0; | 351 | t.tm_sec = 0; |
352 | tLast = mktime( &t ); | 352 | tLast = mktime( &t ); |
353 | } | 353 | } |
354 | break; | 354 | break; |
355 | 355 | ||
356 | case tokWeekly: | 356 | case tokWeekly: |
357 | { | 357 | { |
358 | int iDay = lexInt( i ); | 358 | int iDay = lexInt( i ); |
359 | int iHour = lexInt( i ); | 359 | int iHour = lexInt( i ); |
360 | int iMin = lexInt( i ); | 360 | int iMin = lexInt( i ); |
361 | 361 | ||
362 | struct tm t; | 362 | struct tm t; |
363 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); | 363 | ::memcpy( &t, localtime( &tLast ), sizeof(struct tm) ); |
364 | if( iDay < t.tm_wday || | 364 | if( iDay < t.tm_wday || |
365 | (iDay == t.tm_wday && iHour < t.tm_hour) || | 365 | (iDay == t.tm_wday && iHour < t.tm_hour) || |
366 | (iDay == t.tm_wday && iHour == t.tm_hour | 366 | (iDay == t.tm_wday && iHour == t.tm_hour |
367 | && iMin <= t.tm_min) ) | 367 | && iMin <= t.tm_min) ) |
368 | { | 368 | { |
369 | if( iDay <= t.tm_wday ) | 369 | if( iDay <= t.tm_wday ) |
370 | t.tm_mday += 7 - (t.tm_wday-iDay); | 370 | t.tm_mday += 7 - (t.tm_wday-iDay); |
371 | else | 371 | else |
372 | t.tm_mday += 7 - (iDay-t.tm_wday); | 372 | t.tm_mday += 7 - (iDay-t.tm_wday); |
373 | } | 373 | } |
374 | else | 374 | else |
375 | { | 375 | { |
376 | t.tm_mday += (iDay-t.tm_wday); | 376 | t.tm_mday += (iDay-t.tm_wday); |
377 | } | 377 | } |
378 | t.tm_hour = iHour; | 378 | t.tm_hour = iHour; |
379 | t.tm_min = iMin; | 379 | t.tm_min = iMin; |
380 | t.tm_sec = 0; | 380 | t.tm_sec = 0; |
381 | tLast = mktime( &t ); | 381 | tLast = mktime( &t ); |
382 | } | 382 | } |
383 | break; | 383 | break; |
384 | 384 | ||
385 | case tokMonthly: | 385 | case tokMonthly: |
386 | break; | 386 | break; |
387 | 387 | ||
388 | case tokYearly: | 388 | case tokYearly: |
389 | break; | 389 | break; |
390 | 390 | ||
391 | default: | 391 | default: |
392 | break; | 392 | break; |
393 | } | 393 | } |
394 | 394 | ||
395 | return tLast; | 395 | return tLast; |
396 | } | 396 | } |
397 | 397 | ||
398 | Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( | 398 | Bu::MiniCron::TimerBasic::Token Bu::MiniCron::TimerBasic::lex( |
399 | Bu::String::const_iterator &i ) | 399 | Bu::String::const_iterator &i ) |
400 | { | 400 | { |
401 | if( !i ) | 401 | if( !i ) |
402 | { | 402 | { |
403 | return tokEos; | 403 | return tokEos; |
404 | } | 404 | } |
405 | 405 | ||
406 | Bu::String::const_iterator b = i; | 406 | Bu::String::const_iterator b = i; |
407 | 407 | ||
408 | for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } | 408 | for(; b && (*b == ' ' || *b == '\t'); b++ ) { i = b+1; } |
409 | for(; b && *b != ' ' && *b != '\t'; b++ ) { } | 409 | for(; b && *b != ' ' && *b != '\t'; b++ ) { } |
410 | 410 | ||
411 | Bu::String sTok( i, b ); | 411 | Bu::String sTok( i, b ); |
412 | i = b; | 412 | i = b; |
413 | 413 | ||
414 | if( sTok == "daily" ) | 414 | if( sTok == "daily" ) |
415 | return tokDaily; | 415 | return tokDaily; |
416 | else if( sTok == "hourly" ) | 416 | else if( sTok == "hourly" ) |
417 | return tokHourly; | 417 | return tokHourly; |
418 | else if( sTok == "weekly" ) | 418 | else if( sTok == "weekly" ) |
419 | return tokWeekly; | 419 | return tokWeekly; |
420 | else if( sTok == "monthly" ) | 420 | else if( sTok == "monthly" ) |
421 | return tokMonthly; | 421 | return tokMonthly; |
422 | else if( sTok == "yearly" ) | 422 | else if( sTok == "yearly" ) |
423 | return tokYearly; | 423 | return tokYearly; |
424 | else if( sTok == "sun" ) | 424 | else if( sTok == "sun" ) |
425 | { | 425 | { |
426 | iVal = 0; | 426 | iVal = 0; |
427 | return valInt; | 427 | return valInt; |
428 | } | 428 | } |
429 | else if( sTok == "mon" ) | 429 | else if( sTok == "mon" ) |
430 | { | 430 | { |
431 | iVal = 1; | 431 | iVal = 1; |
432 | return valInt; | 432 | return valInt; |
433 | } | 433 | } |
434 | else if( sTok == "tue" ) | 434 | else if( sTok == "tue" ) |
435 | { | 435 | { |
436 | iVal = 2; | 436 | iVal = 2; |
437 | return valInt; | 437 | return valInt; |
438 | } | 438 | } |
439 | else if( sTok == "wed" ) | 439 | else if( sTok == "wed" ) |
440 | { | 440 | { |
441 | iVal = 3; | 441 | iVal = 3; |
442 | return valInt; | 442 | return valInt; |
443 | } | 443 | } |
444 | else if( sTok == "thu" ) | 444 | else if( sTok == "thu" ) |
445 | { | 445 | { |
446 | iVal = 4; | 446 | iVal = 4; |
447 | return valInt; | 447 | return valInt; |
448 | } | 448 | } |
449 | else if( sTok == "fri" ) | 449 | else if( sTok == "fri" ) |
450 | { | 450 | { |
451 | iVal = 5; | 451 | iVal = 5; |
452 | return valInt; | 452 | return valInt; |
453 | } | 453 | } |
454 | else if( sTok == "sat" ) | 454 | else if( sTok == "sat" ) |
455 | { | 455 | { |
456 | iVal = 6; | 456 | iVal = 6; |
457 | return valInt; | 457 | return valInt; |
458 | } | 458 | } |
459 | else if( sTok[0] >= '0' && sTok[0] <= '9' ) | 459 | else if( sTok[0] >= '0' && sTok[0] <= '9' ) |
460 | { | 460 | { |
461 | iVal = strtol( sTok.getStr(), NULL, 0 ); | 461 | iVal = strtol( sTok.getStr(), NULL, 0 ); |
462 | return valInt; | 462 | return valInt; |
463 | } | 463 | } |
464 | 464 | ||
465 | return tokErr; | 465 | return tokErr; |
466 | } | 466 | } |
467 | 467 | ||
468 | int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) | 468 | int Bu::MiniCron::TimerBasic::lexInt( Bu::String::const_iterator &i ) |
469 | { | 469 | { |
470 | Token t = lex( i ); | 470 | Token t = lex( i ); |
471 | if( t == tokEos ) | 471 | if( t == tokEos ) |
472 | return 0; | 472 | return 0; |
473 | if( t != valInt ) | 473 | if( t != valInt ) |
474 | throw Bu::ExceptionBase("Expected int, got something else."); | 474 | throw Bu::ExceptionBase("Expected int, got something else."); |
475 | return iVal; | 475 | return iVal; |
476 | } | 476 | } |
477 | 477 | ||
diff --git a/src/stable/minicron.h b/src/stable/minicron.h index 53e5156..953b82a 100644 --- a/src/stable/minicron.h +++ b/src/stable/minicron.h | |||
@@ -16,321 +16,321 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * A simple cron like system designed to be embedded in any program. This | 20 | * A simple cron like system designed to be embedded in any program. This |
21 | * class creates a simple cron system that can run any number of jobs at | 21 | * class creates a simple cron system that can run any number of jobs at |
22 | * customizable intervals or schedules. It does not support some of the | 22 | * customizable intervals or schedules. It does not support some of the |
23 | * more complex scheduling that some cron systems can do such as load | 23 | * more complex scheduling that some cron systems can do such as load |
24 | * balancing directly, but this could be done on the job side. | 24 | * balancing directly, but this could be done on the job side. |
25 | * | 25 | * |
26 | * This system is synchronous, it does not use any threads on it's own, but | 26 | * This system is synchronous, it does not use any threads on it's own, but |
27 | * it is threadsafe, so a cron thread could be created if desired. | 27 | * it is threadsafe, so a cron thread could be created if desired. |
28 | * | 28 | * |
29 | * The operation is fairly simple, jobs can be added at any time, and use | 29 | * The operation is fairly simple, jobs can be added at any time, and use |
30 | * any timer they would like, even custom timers. When it is time for a | 30 | * any timer they would like, even custom timers. When it is time for a |
31 | * job to be run it signals the slot provided when the job was added. Every | 31 | * job to be run it signals the slot provided when the job was added. Every |
32 | * job slot recieves a handle to the job object so that it may control it's | 32 | * job slot recieves a handle to the job object so that it may control it's |
33 | * own lifetime and get information about itself. In addition, every job | 33 | * own lifetime and get information about itself. In addition, every job |
34 | * is assigned a unique ID that can be used to control it's operation | 34 | * is assigned a unique ID that can be used to control it's operation |
35 | * at any time. | 35 | * at any time. |
36 | * | 36 | * |
37 | * By default a job will continually reschedule itself after being run | 37 | * By default a job will continually reschedule itself after being run |
38 | * unless it calls stop() on it's job object, it is removed using | 38 | * unless it calls stop() on it's job object, it is removed using |
39 | * removeJob() on the cron object, or it is added with addJobOnce. | 39 | * removeJob() on the cron object, or it is added with addJobOnce. |
40 | * | 40 | * |
41 | *@todo A minor change to the job execution system could allow a Timer to | 41 | *@todo A minor change to the job execution system could allow a Timer to |
42 | * defer or reschedule execution instead of the job executing. This would, | 42 | * defer or reschedule execution instead of the job executing. This would, |
43 | * in effect, allow us to do every type of interesting scheduling that | 43 | * in effect, allow us to do every type of interesting scheduling that |
44 | * systems like fcron offer, including time constrained load-balanced | 44 | * systems like fcron offer, including time constrained load-balanced |
45 | * execution. | 45 | * execution. |
46 | */ | 46 | */ |
47 | class MiniCron | 47 | class MiniCron |
48 | { | 48 | { |
49 | public: | 49 | public: |
50 | class Job; | 50 | class Job; |
51 | class Timer; | 51 | class Timer; |
52 | typedef Bu::Signal1<void, Bu::MiniCron::Job &> CronSignal; | 52 | typedef Bu::Signal1<void, Bu::MiniCron::Job &> CronSignal; |
53 | typedef int JobId; | 53 | typedef int JobId; |
54 | 54 | ||
55 | MiniCron(); | 55 | MiniCron(); |
56 | virtual ~MiniCron(); | 56 | virtual ~MiniCron(); |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Tells you if there are jobs registered in the MiniCron. | 59 | * Tells you if there are jobs registered in the MiniCron. |
60 | *@returns true if there are jobs, false otherwise. | 60 | *@returns true if there are jobs, false otherwise. |
61 | */ | 61 | */ |
62 | virtual bool hasJobs(); | 62 | virtual bool hasJobs(); |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * If there are jobs, tells you the time the next one will execute. | 65 | * If there are jobs, tells you the time the next one will execute. |
66 | *@returns The timestamp that the next job will execute at. | 66 | *@returns The timestamp that the next job will execute at. |
67 | */ | 67 | */ |
68 | virtual time_t getNextRun(); | 68 | virtual time_t getNextRun(); |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Tells you the time the job matching jid will run next. | 71 | * Tells you the time the job matching jid will run next. |
72 | *@returns The timestamp that the job jid will next run. | 72 | *@returns The timestamp that the job jid will next run. |
73 | */ | 73 | */ |
74 | virtual time_t getNextRun( JobId jid ); | 74 | virtual time_t getNextRun( JobId jid ); |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * Call this regularly to execute all jobs that should be executed. | 77 | * Call this regularly to execute all jobs that should be executed. |
78 | * This will loop until all jobs who's run time match the current time | 78 | * This will loop until all jobs who's run time match the current time |
79 | * or are below the current time (we've missed them). | 79 | * or are below the current time (we've missed them). |
80 | * If there is nothing to run, the runtime of this funcion is constant, | 80 | * If there is nothing to run, the runtime of this funcion is constant, |
81 | * it is very fast. Otherwise it executes at log(N) per job run, | 81 | * it is very fast. Otherwise it executes at log(N) per job run, |
82 | * O(N*log(N)). | 82 | * O(N*log(N)). |
83 | */ | 83 | */ |
84 | virtual void poll(); | 84 | virtual void poll(); |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * Add a job for repeated scheduling. Pass in a slot to signal, and a | 87 | * Add a job for repeated scheduling. Pass in a slot to signal, and a |
88 | * Timer object to use to do the scheduling. This function returns a | 88 | * Timer object to use to do the scheduling. This function returns a |
89 | * JobId which can be used at a later time to control the execution of | 89 | * JobId which can be used at a later time to control the execution of |
90 | * the job. | 90 | * the job. |
91 | */ | 91 | */ |
92 | virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, | 92 | virtual JobId addJob( const Bu::String &sName, CronSignal sigJob, |
93 | const Timer &t ); | 93 | const Timer &t ); |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * Add a job for one time scheduling. Pass in a slot to signal, and a | 96 | * Add a job for one time scheduling. Pass in a slot to signal, and a |
97 | * Timer object to use to schodule the one run of this job. This | 97 | * Timer object to use to schodule the one run of this job. This |
98 | * function returns a JobId which can be used at a later time to control | 98 | * function returns a JobId which can be used at a later time to control |
99 | * the execution of the job. | 99 | * the execution of the job. |
100 | */ | 100 | */ |
101 | virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, | 101 | virtual JobId addJobOnce( const Bu::String &sName, CronSignal sigJob, |
102 | const Timer &t ); | 102 | const Timer &t ); |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * Remove a job, preventing all future runs of the job. If there is no | 105 | * Remove a job, preventing all future runs of the job. If there is no |
106 | * job matching the given JobId then nothing will happen. However, this | 106 | * job matching the given JobId then nothing will happen. However, this |
107 | * function is relatively expensive compared to the others in this class | 107 | * function is relatively expensive compared to the others in this class |
108 | * and has a worse case runtime of 2*N*log(N), still not that bad, and | 108 | * and has a worse case runtime of 2*N*log(N), still not that bad, and |
109 | * a O(N*log(N)). | 109 | * a O(N*log(N)). |
110 | */ | 110 | */ |
111 | virtual void removeJob( JobId jid ); | 111 | virtual void removeJob( JobId jid ); |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Executes the job specified right now. If bReschedule is true then | 114 | * Executes the job specified right now. If bReschedule is true then |
115 | * the job is then removed from the queue and rescheduled as though | 115 | * the job is then removed from the queue and rescheduled as though |
116 | * it's time had come naturally to be run. Otherwise, it's run without | 116 | * it's time had come naturally to be run. Otherwise, it's run without |
117 | * interrupting the normal schedule. | 117 | * interrupting the normal schedule. |
118 | */ | 118 | */ |
119 | virtual void runJob( JobId jid, bool bReschedule=false ); | 119 | virtual void runJob( JobId jid, bool bReschedule=false ); |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * Executes the job specified right now. If bReschedule is true then | 122 | * Executes the job specified right now. If bReschedule is true then |
123 | * the job is then removed from the queue and rescheduled as though | 123 | * the job is then removed from the queue and rescheduled as though |
124 | * it's time had come naturally to be run. Otherwise, it's run without | 124 | * it's time had come naturally to be run. Otherwise, it's run without |
125 | * interrupting the normal schedule. | 125 | * interrupting the normal schedule. |
126 | */ | 126 | */ |
127 | virtual void runJob( const Bu::String &sName, bool bReschedule=false ); | 127 | virtual void runJob( const Bu::String &sName, bool bReschedule=false ); |
128 | 128 | ||
129 | class JobInfo | 129 | class JobInfo |
130 | { | 130 | { |
131 | public: | 131 | public: |
132 | JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); | 132 | JobInfo( const Bu::String &sName, JobId jid, time_t tNext ); |
133 | virtual ~JobInfo(); | 133 | virtual ~JobInfo(); |
134 | 134 | ||
135 | bool operator<( const JobInfo &rhs ) const; | 135 | bool operator<( const JobInfo &rhs ) const; |
136 | 136 | ||
137 | Bu::String sName; | 137 | Bu::String sName; |
138 | JobId jid; | 138 | JobId jid; |
139 | time_t tNext; | 139 | time_t tNext; |
140 | }; | 140 | }; |
141 | typedef Bu::List<JobInfo> JobInfoList; | 141 | typedef Bu::List<JobInfo> JobInfoList; |
142 | 142 | ||
143 | JobInfoList getJobInfo(); | 143 | JobInfoList getJobInfo(); |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * The baseclass for timer/schedulers for MiniCron jobs. Classes that | 146 | * The baseclass for timer/schedulers for MiniCron jobs. Classes that |
147 | * inherit from this are used to determine when jobs will run and at | 147 | * inherit from this are used to determine when jobs will run and at |
148 | * what interval. | 148 | * what interval. |
149 | */ | 149 | */ |
150 | class Timer | 150 | class Timer |
151 | { | 151 | { |
152 | public: | 152 | public: |
153 | Timer(); | 153 | Timer(); |
154 | virtual ~Timer(); | 154 | virtual ~Timer(); |
155 | 155 | ||
156 | /** | 156 | /** |
157 | * Called by MiniCron when each job is run to determine the next | 157 | * Called by MiniCron when each job is run to determine the next |
158 | * time that a job should be run. When a job is run, this function | 158 | * time that a job should be run. When a job is run, this function |
159 | * is actually called before the job is executed again so that the | 159 | * is actually called before the job is executed again so that the |
160 | * job can tell when the next time it will be run will be. | 160 | * job can tell when the next time it will be run will be. |
161 | */ | 161 | */ |
162 | virtual time_t nextTime()=0; | 162 | virtual time_t nextTime()=0; |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * This function should return a copy of the child class. | 165 | * This function should return a copy of the child class. |
166 | */ | 166 | */ |
167 | virtual Timer *clone() const = 0; | 167 | virtual Timer *clone() const = 0; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * Execute the job every tInterval seconds, also you can delay the | 171 | * Execute the job every tInterval seconds, also you can delay the |
172 | * first run by a different amount of time from the job's creation. | 172 | * first run by a different amount of time from the job's creation. |
173 | */ | 173 | */ |
174 | class TimerInterval : public Timer | 174 | class TimerInterval : public Timer |
175 | { | 175 | { |
176 | public: | 176 | public: |
177 | TimerInterval( time_t tFirst, time_t tInterval ); | 177 | TimerInterval( time_t tFirst, time_t tInterval ); |
178 | virtual ~TimerInterval(); | 178 | virtual ~TimerInterval(); |
179 | 179 | ||
180 | virtual time_t nextTime(); | 180 | virtual time_t nextTime(); |
181 | virtual Timer *clone() const | 181 | virtual Timer *clone() const |
182 | { return new TimerInterval( *this ); } | 182 | { return new TimerInterval( *this ); } |
183 | private: | 183 | private: |
184 | time_t tNext; | 184 | time_t tNext; |
185 | time_t tInterval; | 185 | time_t tInterval; |
186 | }; | 186 | }; |
187 | 187 | ||
188 | /** | 188 | /** |
189 | * A much more general timer class that can be used for much more | 189 | * A much more general timer class that can be used for much more |
190 | * "cron-like" functionality. The constructor takes a string that | 190 | * "cron-like" functionality. The constructor takes a string that |
191 | * describes the times that the job should be run. At the moment the | 191 | * describes the times that the job should be run. At the moment the |
192 | * following schemes are understood: | 192 | * following schemes are understood: |
193 | * | 193 | * |
194 | * "daily [hour] [minute]" | 194 | * "daily [hour] [minute]" |
195 | * "hourly [minute]" | 195 | * "hourly [minute]" |
196 | * "weekly [day] [hour] [minute]" | 196 | * "weekly [day] [hour] [minute]" |
197 | * | 197 | * |
198 | * In these examples each word in [brackets] represents a number that | 198 | * In these examples each word in [brackets] represents a number that |
199 | * matches the data type in the brackets. [day] is the number of days | 199 | * matches the data type in the brackets. [day] is the number of days |
200 | * since sunday, 0-6. You can also use lowercase three character | 200 | * since sunday, 0-6. You can also use lowercase three character |
201 | * abbreviations for the day names. | 201 | * abbreviations for the day names. |
202 | * | 202 | * |
203 | * Many more forms follow. | 203 | * Many more forms follow. |
204 | */ | 204 | */ |
205 | class TimerBasic : public Timer | 205 | class TimerBasic : public Timer |
206 | { | 206 | { |
207 | public: | 207 | public: |
208 | TimerBasic( const Bu::String &s ); | 208 | TimerBasic( const Bu::String &s ); |
209 | virtual ~TimerBasic(); | 209 | virtual ~TimerBasic(); |
210 | 210 | ||
211 | virtual time_t nextTime(); | 211 | virtual time_t nextTime(); |
212 | virtual Timer *clone() const | 212 | virtual Timer *clone() const |
213 | { return new TimerBasic( *this ); } | 213 | { return new TimerBasic( *this ); } |
214 | 214 | ||
215 | private: | 215 | private: |
216 | enum Token | 216 | enum Token |
217 | { | 217 | { |
218 | tokDaily, | 218 | tokDaily, |
219 | tokHourly, | 219 | tokHourly, |
220 | tokWeekly, | 220 | tokWeekly, |
221 | tokMonthly, | 221 | tokMonthly, |
222 | tokYearly, | 222 | tokYearly, |
223 | valInt, | 223 | valInt, |
224 | tokErr, | 224 | tokErr, |
225 | tokEos | 225 | tokEos |
226 | }; | 226 | }; |
227 | Token lex( Bu::String::const_iterator &i ); | 227 | Token lex( Bu::String::const_iterator &i ); |
228 | int lexInt( Bu::String::const_iterator &i ); | 228 | int lexInt( Bu::String::const_iterator &i ); |
229 | int iVal; //< A temp variable for parsing. | 229 | int iVal; //< A temp variable for parsing. |
230 | time_t tLast; | 230 | time_t tLast; |
231 | Bu::String sSpec; | 231 | Bu::String sSpec; |
232 | }; | 232 | }; |
233 | 233 | ||
234 | /** | 234 | /** |
235 | * Represents a MiniCron Job. This class is used for both internal | 235 | * Represents a MiniCron Job. This class is used for both internal |
236 | * job management as well as job slot interaction and control. Objects | 236 | * job management as well as job slot interaction and control. Objects |
237 | * of this class are passed into the slots that are signaled when a job | 237 | * of this class are passed into the slots that are signaled when a job |
238 | * is executed. | 238 | * is executed. |
239 | */ | 239 | */ |
240 | class Job | 240 | class Job |
241 | { | 241 | { |
242 | friend class Bu::MiniCron; | 242 | friend class Bu::MiniCron; |
243 | private: | 243 | private: |
244 | Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); | 244 | Job( const Bu::String &sName, JobId jid, bool bRepeat=true ); |
245 | virtual ~Job(); | 245 | virtual ~Job(); |
246 | 246 | ||
247 | public: | 247 | public: |
248 | 248 | ||
249 | /** | 249 | /** |
250 | * Execute this job once, increment the runcount and schedule the | 250 | * Execute this job once, increment the runcount and schedule the |
251 | * next occurance of it. | 251 | * next occurance of it. |
252 | */ | 252 | */ |
253 | void run( bool bReschedule=true ); | 253 | void run( bool bReschedule=true ); |
254 | 254 | ||
255 | /** | 255 | /** |
256 | * Get the time this job will next run. | 256 | * Get the time this job will next run. |
257 | */ | 257 | */ |
258 | time_t getNextRun() const; | 258 | time_t getNextRun() const; |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * Compute the time this job will next run. | 261 | * Compute the time this job will next run. |
262 | */ | 262 | */ |
263 | void calcNextRun(); | 263 | void calcNextRun(); |
264 | 264 | ||
265 | /** | 265 | /** |
266 | * Replace the current job timer with a new one, this will trigger | 266 | * Replace the current job timer with a new one, this will trigger |
267 | * a re-schedule. | 267 | * a re-schedule. |
268 | */ | 268 | */ |
269 | void setTimer( const Timer &t ); | 269 | void setTimer( const Timer &t ); |
270 | 270 | ||
271 | /** | 271 | /** |
272 | * Stop execution of this job, never execute this job again. | 272 | * Stop execution of this job, never execute this job again. |
273 | */ | 273 | */ |
274 | void stop(); | 274 | void stop(); |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * Undo a previous stop. This will cause a job that has been | 277 | * Undo a previous stop. This will cause a job that has been |
278 | * stopped or even added with addJobOnce to be set for repeated | 278 | * stopped or even added with addJobOnce to be set for repeated |
279 | * scheduling. | 279 | * scheduling. |
280 | */ | 280 | */ |
281 | void resume(); | 281 | void resume(); |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * Get the unique ID of this job. | 284 | * Get the unique ID of this job. |
285 | */ | 285 | */ |
286 | JobId getId() const; | 286 | JobId getId() const; |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * Get the timestamp this job was created. | 289 | * Get the timestamp this job was created. |
290 | */ | 290 | */ |
291 | time_t getTimeCreated() const; | 291 | time_t getTimeCreated() const; |
292 | 292 | ||
293 | /** | 293 | /** |
294 | * Get the current run count of this job, how many times it has been | 294 | * Get the current run count of this job, how many times it has been |
295 | * executed. This is incremented before the slot is signaled. | 295 | * executed. This is incremented before the slot is signaled. |
296 | */ | 296 | */ |
297 | int getRunCount() const; | 297 | int getRunCount() const; |
298 | 298 | ||
299 | /** | 299 | /** |
300 | * Get the next time that this job will be run. Certain timers may | 300 | * Get the next time that this job will be run. Certain timers may |
301 | * have the ability to delay job executions, so this is the earliest | 301 | * have the ability to delay job executions, so this is the earliest |
302 | * time that the job may run. | 302 | * time that the job may run. |
303 | */ | 303 | */ |
304 | time_t getNextRunTime() const; | 304 | time_t getNextRunTime() const; |
305 | 305 | ||
306 | /** | 306 | /** |
307 | * Gets the name that was set when the job was created. | 307 | * Gets the name that was set when the job was created. |
308 | */ | 308 | */ |
309 | Bu::String getName() const; | 309 | Bu::String getName() const; |
310 | 310 | ||
311 | private: | 311 | private: |
312 | Bu::String sName; | 312 | Bu::String sName; |
313 | CronSignal sigJob; | 313 | CronSignal sigJob; |
314 | time_t tNextRun; | 314 | time_t tNextRun; |
315 | Timer *pTimer; | 315 | Timer *pTimer; |
316 | bool bContinue; | 316 | bool bContinue; |
317 | JobId jid; | 317 | JobId jid; |
318 | time_t tAdded; | 318 | time_t tAdded; |
319 | int iRunCount; | 319 | int iRunCount; |
320 | }; | 320 | }; |
321 | 321 | ||
322 | private: | 322 | private: |
323 | struct JobPtrCmp | 323 | struct JobPtrCmp |
324 | { | 324 | { |
325 | bool operator()( const Job *pLeft, const Job *pRight ) | 325 | bool operator()( const Job *pLeft, const Job *pRight ) |
326 | { | 326 | { |
327 | return pLeft->tNextRun < pRight->tNextRun; | 327 | return pLeft->tNextRun < pRight->tNextRun; |
328 | } | 328 | } |
329 | }; | 329 | }; |
330 | typedef Bu::Heap<Job *, JobPtrCmp> JobHeap; | 330 | typedef Bu::Heap<Job *, JobPtrCmp> JobHeap; |
331 | JobHeap hJobs; | 331 | JobHeap hJobs; |
332 | JobId jidNext; | 332 | JobId jidNext; |
333 | }; | 333 | }; |
334 | }; | 334 | }; |
335 | 335 | ||
336 | #endif | 336 | #endif |
diff --git a/src/stable/multiserver.cpp b/src/stable/multiserver.cpp index 8856117..bb1cacc 100644 --- a/src/stable/multiserver.cpp +++ b/src/stable/multiserver.cpp | |||
@@ -20,36 +20,36 @@ Bu::MultiServer::~MultiServer() | |||
20 | } | 20 | } |
21 | 21 | ||
22 | void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, | 22 | void Bu::MultiServer::addProtocol( Bu::Protocol *(*proc)(), int iPort, |
23 | int nPoolSize ) | 23 | int nPoolSize ) |
24 | { | 24 | { |
25 | hProtos[iPort] = proc; | 25 | hProtos[iPort] = proc; |
26 | addPort( iPort, nPoolSize ); | 26 | addPort( iPort, nPoolSize ); |
27 | } | 27 | } |
28 | 28 | ||
29 | void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, | 29 | void Bu::MultiServer::addProtocol( Protocol *(*proc)(), const String &sAddr, |
30 | int iPort, int nPoolSize ) | 30 | int iPort, int nPoolSize ) |
31 | { | 31 | { |
32 | hProtos[iPort] = proc; | 32 | hProtos[iPort] = proc; |
33 | addPort( sAddr, iPort, nPoolSize ); | 33 | addPort( sAddr, iPort, nPoolSize ); |
34 | } | 34 | } |
35 | 35 | ||
36 | void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) | 36 | void Bu::MultiServer::onNewConnection( Bu::Client *pClient, int nPort ) |
37 | { | 37 | { |
38 | pClient->setProtocol( hProtos.get( nPort )() ); | 38 | pClient->setProtocol( hProtos.get( nPort )() ); |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) | 41 | void Bu::MultiServer::onClosedConnection( Bu::Client *pClient ) |
42 | { | 42 | { |
43 | delete pClient->getProtocol(); | 43 | delete pClient->getProtocol(); |
44 | } | 44 | } |
45 | 45 | ||
46 | void Bu::MultiServer::shutdown() | 46 | void Bu::MultiServer::shutdown() |
47 | { | 47 | { |
48 | Bu::Server::shutdown(); | 48 | Bu::Server::shutdown(); |
49 | } | 49 | } |
50 | 50 | ||
51 | void Bu::MultiServer::tick() | 51 | void Bu::MultiServer::tick() |
52 | { | 52 | { |
53 | Bu::Server::tick(); | 53 | Bu::Server::tick(); |
54 | } | 54 | } |
55 | 55 | ||
diff --git a/src/stable/multiserver.h b/src/stable/multiserver.h index b2f633a..8a49bbd 100644 --- a/src/stable/multiserver.h +++ b/src/stable/multiserver.h | |||
@@ -13,45 +13,45 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class Protocol; | 16 | class Protocol; |
17 | class Client; | 17 | class Client; |
18 | 18 | ||
19 | template<class T> | 19 | template<class T> |
20 | Protocol *genProtocol() | 20 | Protocol *genProtocol() |
21 | { | 21 | { |
22 | return new T; | 22 | return new T; |
23 | } | 23 | } |
24 | 24 | ||
25 | class MultiServer : protected Server | 25 | class MultiServer : protected Server |
26 | { | 26 | { |
27 | public: | 27 | public: |
28 | MultiServer(); | 28 | MultiServer(); |
29 | virtual ~MultiServer(); | 29 | virtual ~MultiServer(); |
30 | 30 | ||
31 | void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); | 31 | void addProtocol( Protocol *(*proc)(), int iPort, int nPoolSize=40 ); |
32 | void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, | 32 | void addProtocol( Protocol *(*proc)(), const String &sAddr, int iPort, |
33 | int nPoolSize=40 ); | 33 | int nPoolSize=40 ); |
34 | 34 | ||
35 | void scan() | 35 | void scan() |
36 | { | 36 | { |
37 | Server::scan(); | 37 | Server::scan(); |
38 | } | 38 | } |
39 | 39 | ||
40 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) | 40 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ) |
41 | { | 41 | { |
42 | Server::setTimeout( nTimeoutSec, nTimeoutUSec ); | 42 | Server::setTimeout( nTimeoutSec, nTimeoutUSec ); |
43 | } | 43 | } |
44 | 44 | ||
45 | virtual void onNewConnection( Client *pClient, int nPort ); | 45 | virtual void onNewConnection( Client *pClient, int nPort ); |
46 | virtual void onClosedConnection( Client *pClient ); | 46 | virtual void onClosedConnection( Client *pClient ); |
47 | 47 | ||
48 | void shutdown(); | 48 | void shutdown(); |
49 | 49 | ||
50 | void tick(); | 50 | void tick(); |
51 | 51 | ||
52 | private: | 52 | private: |
53 | Bu::Hash<int, Protocol *(*)()> hProtos; | 53 | Bu::Hash<int, Protocol *(*)()> hProtos; |
54 | }; | 54 | }; |
55 | } | 55 | } |
56 | 56 | ||
57 | #endif | 57 | #endif |
diff --git a/src/stable/mutex.cpp b/src/stable/mutex.cpp index 947364c..0391d7a 100644 --- a/src/stable/mutex.cpp +++ b/src/stable/mutex.cpp | |||
@@ -9,26 +9,26 @@ | |||
9 | 9 | ||
10 | Bu::Mutex::Mutex() | 10 | Bu::Mutex::Mutex() |
11 | { | 11 | { |
12 | pthread_mutex_init( &mutex, NULL ); | 12 | pthread_mutex_init( &mutex, NULL ); |
13 | } | 13 | } |
14 | 14 | ||
15 | Bu::Mutex::~Mutex() | 15 | Bu::Mutex::~Mutex() |
16 | { | 16 | { |
17 | pthread_mutex_destroy( &mutex ); | 17 | pthread_mutex_destroy( &mutex ); |
18 | } | 18 | } |
19 | 19 | ||
20 | int Bu::Mutex::lock() | 20 | int Bu::Mutex::lock() |
21 | { | 21 | { |
22 | return pthread_mutex_lock( &mutex ); | 22 | return pthread_mutex_lock( &mutex ); |
23 | } | 23 | } |
24 | 24 | ||
25 | int Bu::Mutex::unlock() | 25 | int Bu::Mutex::unlock() |
26 | { | 26 | { |
27 | return pthread_mutex_unlock( &mutex ); | 27 | return pthread_mutex_unlock( &mutex ); |
28 | } | 28 | } |
29 | 29 | ||
30 | int Bu::Mutex::trylock() | 30 | int Bu::Mutex::trylock() |
31 | { | 31 | { |
32 | return pthread_mutex_trylock( &mutex ); | 32 | return pthread_mutex_trylock( &mutex ); |
33 | } | 33 | } |
34 | 34 | ||
diff --git a/src/stable/mutex.h b/src/stable/mutex.h index 1898118..23963e3 100644 --- a/src/stable/mutex.h +++ b/src/stable/mutex.h | |||
@@ -12,57 +12,57 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Simple mutex wrapper. Currently this doesn't do anything extra for you | 16 | * Simple mutex wrapper. Currently this doesn't do anything extra for you |
17 | * except keep all of the functionality together in an OO sorta' way and | 17 | * except keep all of the functionality together in an OO sorta' way and |
18 | * keep you from having to worry about cleaning up your mutexes properly, | 18 | * keep you from having to worry about cleaning up your mutexes properly, |
19 | * or initing them. | 19 | * or initing them. |
20 | *@ingroup Threading | 20 | *@ingroup Threading |
21 | */ | 21 | */ |
22 | class Mutex | 22 | class Mutex |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | /** | 25 | /** |
26 | * Create an unlocked mutex. | 26 | * Create an unlocked mutex. |
27 | */ | 27 | */ |
28 | Mutex(); | 28 | Mutex(); |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Destroy a mutex. This can only be done when a mutex is unlocked. | 31 | * Destroy a mutex. This can only be done when a mutex is unlocked. |
32 | * Failure to unlock before destroying a mutex object could cause it to | 32 | * Failure to unlock before destroying a mutex object could cause it to |
33 | * wait for the mutex to unlock, the odds of which are usually farily | 33 | * wait for the mutex to unlock, the odds of which are usually farily |
34 | * low at deconstruction time. | 34 | * low at deconstruction time. |
35 | */ | 35 | */ |
36 | ~Mutex(); | 36 | ~Mutex(); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Lock the mutex. This causes all future calls to lock on this | 39 | * Lock the mutex. This causes all future calls to lock on this |
40 | * instance of mutex to block until the first thread that called mutex | 40 | * instance of mutex to block until the first thread that called mutex |
41 | * unlocks it. At that point the next thread that called lock will get | 41 | * unlocks it. At that point the next thread that called lock will get |
42 | * a chance to go to work. Because of the nature of a mutex lock it is | 42 | * a chance to go to work. Because of the nature of a mutex lock it is |
43 | * a very bad idea to do any kind of serious or rather time consuming | 43 | * a very bad idea to do any kind of serious or rather time consuming |
44 | * computation within a locked section. This can cause thread-deadlock | 44 | * computation within a locked section. This can cause thread-deadlock |
45 | * and your program may hang. | 45 | * and your program may hang. |
46 | */ | 46 | */ |
47 | int lock(); | 47 | int lock(); |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * Unlock the mutex. This allows the next thread that asked for a lock | 50 | * Unlock the mutex. This allows the next thread that asked for a lock |
51 | * to lock the mutex and continue with execution. | 51 | * to lock the mutex and continue with execution. |
52 | */ | 52 | */ |
53 | int unlock(); | 53 | int unlock(); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Try to lock the mutex. This is the option to go with if you cannot | 56 | * Try to lock the mutex. This is the option to go with if you cannot |
57 | * avoid putting lengthy operations within a locked section. trylock | 57 | * avoid putting lengthy operations within a locked section. trylock |
58 | * will attempt to lock the mutex, if the mutex is already locked this | 58 | * will attempt to lock the mutex, if the mutex is already locked this |
59 | * function returns immediately with an error code. | 59 | * function returns immediately with an error code. |
60 | */ | 60 | */ |
61 | int trylock(); | 61 | int trylock(); |
62 | 62 | ||
63 | protected: | 63 | protected: |
64 | pthread_mutex_t mutex; /**< The internal mutex reference. */ | 64 | pthread_mutex_t mutex; /**< The internal mutex reference. */ |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/mutexlocker.cpp b/src/stable/mutexlocker.cpp index 90b730e..c8465a3 100644 --- a/src/stable/mutexlocker.cpp +++ b/src/stable/mutexlocker.cpp | |||
@@ -2,23 +2,23 @@ | |||
2 | #include "bu/mutex.h" | 2 | #include "bu/mutex.h" |
3 | 3 | ||
4 | Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : | 4 | Bu::MutexLocker::MutexLocker( Bu::Mutex &mu ) : |
5 | mu( mu ) | 5 | mu( mu ) |
6 | { | 6 | { |
7 | mu.lock(); | 7 | mu.lock(); |
8 | } | 8 | } |
9 | 9 | ||
10 | Bu::MutexLocker::~MutexLocker() | 10 | Bu::MutexLocker::~MutexLocker() |
11 | { | 11 | { |
12 | mu.unlock(); | 12 | mu.unlock(); |
13 | } | 13 | } |
14 | 14 | ||
15 | void Bu::MutexLocker::unlock() | 15 | void Bu::MutexLocker::unlock() |
16 | { | 16 | { |
17 | mu.unlock(); | 17 | mu.unlock(); |
18 | } | 18 | } |
19 | 19 | ||
20 | void Bu::MutexLocker::relock() | 20 | void Bu::MutexLocker::relock() |
21 | { | 21 | { |
22 | mu.lock(); | 22 | mu.lock(); |
23 | } | 23 | } |
24 | 24 | ||
diff --git a/src/stable/mutexlocker.h b/src/stable/mutexlocker.h index 7c3c97e..30e71e6 100644 --- a/src/stable/mutexlocker.h +++ b/src/stable/mutexlocker.h | |||
@@ -3,19 +3,19 @@ | |||
3 | 3 | ||
4 | namespace Bu | 4 | namespace Bu |
5 | { | 5 | { |
6 | class Mutex; | 6 | class Mutex; |
7 | class MutexLocker | 7 | class MutexLocker |
8 | { | 8 | { |
9 | public: | 9 | public: |
10 | MutexLocker( Mutex &mu ); | 10 | MutexLocker( Mutex &mu ); |
11 | virtual ~MutexLocker(); | 11 | virtual ~MutexLocker(); |
12 | 12 | ||
13 | void unlock(); | 13 | void unlock(); |
14 | void relock(); | 14 | void relock(); |
15 | 15 | ||
16 | private: | 16 | private: |
17 | Mutex μ | 17 | Mutex μ |
18 | }; | 18 | }; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | #endif | 21 | #endif |
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp index 4be82f0..2a6a725 100644 --- a/src/stable/myriad.cpp +++ b/src/stable/myriad.cpp | |||
@@ -16,720 +16,720 @@ | |||
16 | using Bu::sio; | 16 | using Bu::sio; |
17 | using Bu::Fmt; | 17 | using Bu::Fmt; |
18 | 18 | ||
19 | #define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") | 19 | #define Myriad_MAGIC_CODE ((unsigned char *)"\x0a\xd3\xfa\x84") |
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | subExceptionDef( MyriadException ) | 23 | subExceptionDef( MyriadException ) |
24 | template<typename t> t blkDiv( t total, t block ) { | 24 | template<typename t> t blkDiv( t total, t block ) { |
25 | return (total/block)+((total%block==0)?(0):(1)); | 25 | return (total/block)+((total%block==0)?(0):(1)); |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : | 29 | Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) : |
30 | sStore( sStore ), | 30 | sStore( sStore ), |
31 | iBlockSize( iBlockSize ), | 31 | iBlockSize( iBlockSize ), |
32 | iBlocks( 0 ), | 32 | iBlocks( 0 ), |
33 | iUsed( 0 ), | 33 | iUsed( 0 ), |
34 | bHeaderChanged( false ) | 34 | bHeaderChanged( false ) |
35 | { | 35 | { |
36 | try | 36 | try |
37 | { | 37 | { |
38 | initialize(); | 38 | initialize(); |
39 | } | 39 | } |
40 | catch( Bu::MyriadException &e ) | 40 | catch( Bu::MyriadException &e ) |
41 | { | 41 | { |
42 | if( e.getErrorCode() == MyriadException::emptyStream ) | 42 | if( e.getErrorCode() == MyriadException::emptyStream ) |
43 | { | 43 | { |
44 | initialize( iBlockSize, iPreallocate ); | 44 | initialize( iBlockSize, iPreallocate ); |
45 | } | 45 | } |
46 | else | 46 | else |
47 | { | 47 | { |
48 | throw; | 48 | throw; |
49 | } | 49 | } |
50 | } | 50 | } |
51 | } | 51 | } |
52 | 52 | ||
53 | Bu::Myriad::~Myriad() | 53 | Bu::Myriad::~Myriad() |
54 | { | 54 | { |
55 | mActiveBlocks.lock(); | 55 | mActiveBlocks.lock(); |
56 | if( !hActiveBlocks.isEmpty() ) | 56 | if( !hActiveBlocks.isEmpty() ) |
57 | { | 57 | { |
58 | sio << "Bu::Myriad::~Myriad(): Error: There are " | 58 | sio << "Bu::Myriad::~Myriad(): Error: There are " |
59 | << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; | 59 | << hActiveBlocks.getSize() << " unsynced blocks!" << sio.nl; |
60 | } | 60 | } |
61 | mActiveBlocks.unlock(); | 61 | mActiveBlocks.unlock(); |
62 | sync(); | 62 | sync(); |
63 | 63 | ||
64 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 64 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
65 | { | 65 | { |
66 | delete *i; | 66 | delete *i; |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | void Bu::Myriad::sync() | 70 | void Bu::Myriad::sync() |
71 | { | 71 | { |
72 | updateHeader(); | 72 | updateHeader(); |
73 | 73 | ||
74 | mActiveBlocks.lock(); | 74 | mActiveBlocks.lock(); |
75 | for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) | 75 | for( BlockHash::iterator i = hActiveBlocks.begin(); i; i++ ) |
76 | { | 76 | { |
77 | if( (*i)->bChanged ) | 77 | if( (*i)->bChanged ) |
78 | { | 78 | { |
79 | syncBlock( *i ); | 79 | syncBlock( *i ); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | mActiveBlocks.unlock(); | 82 | mActiveBlocks.unlock(); |
83 | } | 83 | } |
84 | 84 | ||
85 | void Bu::Myriad::initialize() | 85 | void Bu::Myriad::initialize() |
86 | { | 86 | { |
87 | MutexLocker mLock( mHeader ); | 87 | MutexLocker mLock( mHeader ); |
88 | lFreeBlocks.clear(); | 88 | lFreeBlocks.clear(); |
89 | sStore.setPosEnd( 0 ); | 89 | sStore.setPosEnd( 0 ); |
90 | Bu::size iSize = sStore.tell(); | 90 | Bu::size iSize = sStore.tell(); |
91 | sStore.setPos( 0 ); | 91 | sStore.setPos( 0 ); |
92 | 92 | ||
93 | unsigned char buf[4]; | 93 | unsigned char buf[4]; |
94 | if( sStore.read( buf, 4 ) < 4 ) | 94 | if( sStore.read( buf, 4 ) < 4 ) |
95 | throw MyriadException( MyriadException::emptyStream, | 95 | throw MyriadException( MyriadException::emptyStream, |
96 | "Input stream appears to be empty."); | 96 | "Input stream appears to be empty."); |
97 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | 97 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) |
98 | { | 98 | { |
99 | throw MyriadException( MyriadException::invalidFormat, | 99 | throw MyriadException( MyriadException::invalidFormat, |
100 | "Stream does not appear to be a valid Myriad format."); | 100 | "Stream does not appear to be a valid Myriad format."); |
101 | } | 101 | } |
102 | sStore.read( buf, 2 ); | 102 | sStore.read( buf, 2 ); |
103 | if( buf[0] != 1 ) | 103 | if( buf[0] != 1 ) |
104 | throw MyriadException( MyriadException::badVersion, | 104 | throw MyriadException( MyriadException::badVersion, |
105 | "We can only handle version 1 for now."); | 105 | "We can only handle version 1 for now."); |
106 | if( buf[1] != 32 ) | 106 | if( buf[1] != 32 ) |
107 | throw MyriadException( MyriadException::invalidWordSize, | 107 | throw MyriadException( MyriadException::invalidWordSize, |
108 | "We can only handle 32-bit words at the moment."); | 108 | "We can only handle 32-bit words at the moment."); |
109 | sStore.read( &iBlockSize, 4 ); | 109 | sStore.read( &iBlockSize, 4 ); |
110 | int iStreams; | 110 | int iStreams; |
111 | sStore.read( &iStreams, 4 ); | 111 | sStore.read( &iStreams, 4 ); |
112 | 112 | ||
113 | iBlocks = iSize/iBlockSize; | 113 | iBlocks = iSize/iBlockSize; |
114 | //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize | 114 | //sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize |
115 | // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; | 115 | // << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; |
116 | 116 | ||
117 | int iHeaderSize = 14 + 8 + 4; | 117 | int iHeaderSize = 14 + 8 + 4; |
118 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); | 118 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); |
119 | 119 | ||
120 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | 120 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) |
121 | { | 121 | { |
122 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | 122 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); |
123 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | 123 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; |
124 | } | 124 | } |
125 | 125 | ||
126 | //sio << "Myriad: iHeaderSize=" << iHeaderSize | 126 | //sio << "Myriad: iHeaderSize=" << iHeaderSize |
127 | // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | 127 | // << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; |
128 | 128 | ||
129 | Stream *pFakeHdr = new Stream; | 129 | Stream *pFakeHdr = new Stream; |
130 | pFakeHdr->iId = 0; | 130 | pFakeHdr->iId = 0; |
131 | pFakeHdr->iSize = iHeaderSize; | 131 | pFakeHdr->iSize = iHeaderSize; |
132 | for( int j = 0; j < iHeaderBlocks; j++ ) | 132 | for( int j = 0; j < iHeaderBlocks; j++ ) |
133 | { | 133 | { |
134 | pFakeHdr->aBlocks.append( j ); | 134 | pFakeHdr->aBlocks.append( j ); |
135 | } | 135 | } |
136 | 136 | ||
137 | // sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize | 137 | // sio << "Blocks: " << iBlocks << " (size = " << iSize << "/" << iBlockSize |
138 | // << ")" << sio.nl; | 138 | // << ")" << sio.nl; |
139 | Bu::BitString bsBlockUsed( iBlocks, false ); | 139 | Bu::BitString bsBlockUsed( iBlocks, false ); |
140 | bsBlockUsed.clear(); | 140 | bsBlockUsed.clear(); |
141 | 141 | ||
142 | // bool bCanSkip = false; // Can skip around, post initial header stream i/o | 142 | // bool bCanSkip = false; // Can skip around, post initial header stream i/o |
143 | MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); | 143 | MyriadStream *pIn = new MyriadStream( *this, pFakeHdr ); |
144 | pIn->setPos( sStore.tell() ); | 144 | pIn->setPos( sStore.tell() ); |
145 | for( int j = 0; j < iStreams; j++ ) | 145 | for( int j = 0; j < iStreams; j++ ) |
146 | { | 146 | { |
147 | aStreams.append( new Stream() ); | 147 | aStreams.append( new Stream() ); |
148 | Stream &s = *aStreams[j]; | 148 | Stream &s = *aStreams[j]; |
149 | pIn->read( &s.iId, 4 ); | 149 | pIn->read( &s.iId, 4 ); |
150 | pIn->read( &s.iSize, 4 ); | 150 | pIn->read( &s.iSize, 4 ); |
151 | int iSBlocks = blkDiv(s.iSize, iBlockSize); | 151 | int iSBlocks = blkDiv(s.iSize, iBlockSize); |
152 | // sio << "Myriad: - Stream::iId=" << s.iId | 152 | // sio << "Myriad: - Stream::iId=" << s.iId |
153 | // << ", Stream::iSize=" << s.iSize | 153 | // << ", Stream::iSize=" << s.iSize |
154 | // << ", Stream::aBlocks=" << iSBlocks | 154 | // << ", Stream::aBlocks=" << iSBlocks |
155 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; | 155 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; |
156 | for( int k = 0; k < iSBlocks; k++ ) | 156 | for( int k = 0; k < iSBlocks; k++ ) |
157 | { | 157 | { |
158 | int iBId; | 158 | int iBId; |
159 | pIn->read( &iBId, 4 ); | 159 | pIn->read( &iBId, 4 ); |
160 | // sio << "Myriad: - iBId=" << iBId | 160 | // sio << "Myriad: - iBId=" << iBId |
161 | // << ", iStartPos=" << iBId*iBlockSize | 161 | // << ", iStartPos=" << iBId*iBlockSize |
162 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; | 162 | // << ", pIn->tell()=" << pIn->tell() << sio.nl; |
163 | s.aBlocks.append( iBId ); | 163 | s.aBlocks.append( iBId ); |
164 | bsBlockUsed.setBit( iBId ); | 164 | bsBlockUsed.setBit( iBId ); |
165 | iUsed++; | 165 | iUsed++; |
166 | if( (j == 0 && k == iHeaderBlocks-1) ) | 166 | if( (j == 0 && k == iHeaderBlocks-1) ) |
167 | { | 167 | { |
168 | // sio << "Myriad: - End of prepartition, unlocking skipping." | 168 | // sio << "Myriad: - End of prepartition, unlocking skipping." |
169 | // << sio.nl; | 169 | // << sio.nl; |
170 | // bCanSkip = true; | 170 | // bCanSkip = true; |
171 | MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); | 171 | MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] ); |
172 | // sio << "Myriad - Position = " << pIn->tell() << sio.nl; | 172 | // sio << "Myriad - Position = " << pIn->tell() << sio.nl; |
173 | pTmp->setPos( pIn->tell() ); | 173 | pTmp->setPos( pIn->tell() ); |
174 | delete pIn; | 174 | delete pIn; |
175 | delete pFakeHdr; | 175 | delete pFakeHdr; |
176 | pIn = pTmp; | 176 | pIn = pTmp; |
177 | } | 177 | } |
178 | } | 178 | } |
179 | } | 179 | } |
180 | delete pIn; | 180 | delete pIn; |
181 | 181 | ||
182 | for( int j = 0; j < iBlocks; j++ ) | 182 | for( int j = 0; j < iBlocks; j++ ) |
183 | { | 183 | { |
184 | if( bsBlockUsed.getBit( j ) == false ) | 184 | if( bsBlockUsed.getBit( j ) == false ) |
185 | { | 185 | { |
186 | // sio << "Preinitialized block " << j << " is free." << sio.nl; | 186 | // sio << "Preinitialized block " << j << " is free." << sio.nl; |
187 | lFreeBlocks.append( j ); | 187 | lFreeBlocks.append( j ); |
188 | } | 188 | } |
189 | } | 189 | } |
190 | // sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; | 190 | // sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; |
191 | } | 191 | } |
192 | 192 | ||
193 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) | 193 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) |
194 | { | 194 | { |
195 | MutexLocker mLock( mHeader ); | 195 | MutexLocker mLock( mHeader ); |
196 | lFreeBlocks.clear(); | 196 | lFreeBlocks.clear(); |
197 | 197 | ||
198 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 198 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
199 | { | 199 | { |
200 | delete *i; | 200 | delete *i; |
201 | } | 201 | } |
202 | aStreams.clear(); | 202 | aStreams.clear(); |
203 | iUsed = 0; | 203 | iUsed = 0; |
204 | 204 | ||
205 | int iHeaderSize = 14 + 8 + 4; | 205 | int iHeaderSize = 14 + 8 + 4; |
206 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); | 206 | int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); |
207 | char cBuf = 1; | 207 | char cBuf = 1; |
208 | int iBuf = 0; | 208 | int iBuf = 0; |
209 | 209 | ||
210 | Stream *pStr = new Stream; | 210 | Stream *pStr = new Stream; |
211 | pStr->iId = 0; | 211 | pStr->iId = 0; |
212 | 212 | ||
213 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | 213 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) |
214 | { | 214 | { |
215 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | 215 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); |
216 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | 216 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; |
217 | } | 217 | } |
218 | 218 | ||
219 | iPreAllocate += iHeaderBlocks; | 219 | iPreAllocate += iHeaderBlocks; |
220 | 220 | ||
221 | //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" | 221 | //sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" |
222 | // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | 222 | // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; |
223 | 223 | ||
224 | // bsBlockUsed.setSize( iPreAllocate, true ); | 224 | // bsBlockUsed.setSize( iPreAllocate, true ); |
225 | iUsed++; | 225 | iUsed++; |
226 | 226 | ||
227 | char *pBlock = new char[iBlockSize]; | 227 | char *pBlock = new char[iBlockSize]; |
228 | memset( pBlock, 0, iBlockSize ); | 228 | memset( pBlock, 0, iBlockSize ); |
229 | for( int j = 0; j < iPreAllocate; j++ ) | 229 | for( int j = 0; j < iPreAllocate; j++ ) |
230 | { | 230 | { |
231 | sStore.write( pBlock, iBlockSize ); | 231 | sStore.write( pBlock, iBlockSize ); |
232 | } | 232 | } |
233 | delete[] (char *)pBlock; | 233 | delete[] (char *)pBlock; |
234 | 234 | ||
235 | sStore.setPos( 0 ); | 235 | sStore.setPos( 0 ); |
236 | 236 | ||
237 | // Magic number | 237 | // Magic number |
238 | sStore.write( Myriad_MAGIC_CODE, 4 ); | 238 | sStore.write( Myriad_MAGIC_CODE, 4 ); |
239 | 239 | ||
240 | // Version (0) | 240 | // Version (0) |
241 | sStore.write( &cBuf, 1 ); | 241 | sStore.write( &cBuf, 1 ); |
242 | 242 | ||
243 | // Bits per int | 243 | // Bits per int |
244 | cBuf = 32; | 244 | cBuf = 32; |
245 | sStore.write( &cBuf, 1 ); | 245 | sStore.write( &cBuf, 1 ); |
246 | 246 | ||
247 | // The size of each block | 247 | // The size of each block |
248 | sStore.write( &iBlockSize, 4 ); | 248 | sStore.write( &iBlockSize, 4 ); |
249 | 249 | ||
250 | iBuf = 1; | 250 | iBuf = 1; |
251 | // The number of streams | 251 | // The number of streams |
252 | sStore.write( &iBuf, 4 ); | 252 | sStore.write( &iBuf, 4 ); |
253 | 253 | ||
254 | // Stream header | 254 | // Stream header |
255 | iBuf = 0; | 255 | iBuf = 0; |
256 | sStore.write( &iBuf, 4 ); | 256 | sStore.write( &iBuf, 4 ); |
257 | sStore.write( &iHeaderSize, 4 ); | 257 | sStore.write( &iHeaderSize, 4 ); |
258 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) | 258 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) |
259 | { | 259 | { |
260 | sStore.write( &iBuf, 4 ); | 260 | sStore.write( &iBuf, 4 ); |
261 | } | 261 | } |
262 | 262 | ||
263 | this->iBlockSize = iBlockSize; | 263 | this->iBlockSize = iBlockSize; |
264 | this->iBlocks = iPreAllocate; | 264 | this->iBlocks = iPreAllocate; |
265 | 265 | ||
266 | pStr->iSize = sStore.tell(); | 266 | pStr->iSize = sStore.tell(); |
267 | // sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; | 267 | // sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; |
268 | 268 | ||
269 | pStr->iSize = iHeaderSize; | 269 | pStr->iSize = iHeaderSize; |
270 | for( int j = 0; j < iHeaderBlocks; j++ ) | 270 | for( int j = 0; j < iHeaderBlocks; j++ ) |
271 | { | 271 | { |
272 | // sio << "Started block " << j << " is header." << sio.nl; | 272 | // sio << "Started block " << j << " is header." << sio.nl; |
273 | pStr->aBlocks.append( j ); | 273 | pStr->aBlocks.append( j ); |
274 | // bsBlockUsed.setBit( j ); | 274 | // bsBlockUsed.setBit( j ); |
275 | iUsed++; | 275 | iUsed++; |
276 | } | 276 | } |
277 | for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) | 277 | for( int j = iHeaderBlocks; j < this->iBlocks; j++ ) |
278 | { | 278 | { |
279 | // sio << "Started block " << j << " is free." << sio.nl; | 279 | // sio << "Started block " << j << " is free." << sio.nl; |
280 | lFreeBlocks.append( j ); | 280 | lFreeBlocks.append( j ); |
281 | } | 281 | } |
282 | 282 | ||
283 | aStreams.append( pStr ); | 283 | aStreams.append( pStr ); |
284 | 284 | ||
285 | //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; | 285 | //sio << bsBlockUsed.toString() << " - " << pStr->aBlocks << sio.nl; |
286 | 286 | ||
287 | bHeaderChanged = true; | 287 | bHeaderChanged = true; |
288 | //hStreams.insert( 0, BlockArray( 0 ) ); | 288 | //hStreams.insert( 0, BlockArray( 0 ) ); |
289 | } | 289 | } |
290 | 290 | ||
291 | void Bu::Myriad::updateHeader() | 291 | void Bu::Myriad::updateHeader() |
292 | { | 292 | { |
293 | MutexLocker mLock( mHeader ); | 293 | MutexLocker mLock( mHeader ); |
294 | 294 | ||
295 | if( bHeaderChanged == false ) | 295 | if( bHeaderChanged == false ) |
296 | return; | 296 | return; |
297 | if( !sStore.canWrite() ) | 297 | if( !sStore.canWrite() ) |
298 | return; | 298 | return; |
299 | 299 | ||
300 | char cBuf; | 300 | char cBuf; |
301 | int iBuf; | 301 | int iBuf; |
302 | 302 | ||
303 | //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 303 | //for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
304 | //{ | 304 | //{ |
305 | // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; | 305 | // sio << "Myriad: Stream " << Fmt(4) << (*i)->iId << ": " << (*i)->aBlocks << sio.nl; |
306 | //} | 306 | //} |
307 | 307 | ||
308 | // Compute the new size of the header. | 308 | // Compute the new size of the header. |
309 | int iHeaderSize = 14 + 8*aStreams.getSize(); | 309 | int iHeaderSize = 14 + 8*aStreams.getSize(); |
310 | // sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() | 310 | // sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize() |
311 | // << sio.nl; | 311 | // << sio.nl; |
312 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 312 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
313 | { | 313 | { |
314 | iHeaderSize += 4*(*i)->aBlocks.getSize(); | 314 | iHeaderSize += 4*(*i)->aBlocks.getSize(); |
315 | // sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " | 315 | // sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = " |
316 | // << (*i)->aBlocks.getSize() << sio.nl; | 316 | // << (*i)->aBlocks.getSize() << sio.nl; |
317 | } | 317 | } |
318 | int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); | 318 | int iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); |
319 | while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) | 319 | while( iNewBlocks > aStreams[0]->aBlocks.getSize() ) |
320 | { | 320 | { |
321 | int iBlock = findEmptyBlock(); | 321 | int iBlock = findEmptyBlock(); |
322 | // sio << "Myriad: updateHeader: Appending block " << iBlock | 322 | // sio << "Myriad: updateHeader: Appending block " << iBlock |
323 | // << " to header." << sio.nl; | 323 | // << " to header." << sio.nl; |
324 | aStreams[0]->aBlocks.append( iBlock ); | 324 | aStreams[0]->aBlocks.append( iBlock ); |
325 | // bsBlockUsed.setBit( iBlock ); | 325 | // bsBlockUsed.setBit( iBlock ); |
326 | iUsed++; | 326 | iUsed++; |
327 | iHeaderSize += 4; | 327 | iHeaderSize += 4; |
328 | iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); | 328 | iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); |
329 | } | 329 | } |
330 | aStreams[0]->iSize = iHeaderSize; | 330 | aStreams[0]->iSize = iHeaderSize; |
331 | // sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize | 331 | // sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize |
332 | // << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" | 332 | // << ", iNewBlocks=" << iNewBlocks << ", curBlocks=" |
333 | // << aStreams[0]->aBlocks.getSize() << sio.nl; | 333 | // << aStreams[0]->aBlocks.getSize() << sio.nl; |
334 | 334 | ||
335 | MyriadStream sHdr( *this, aStreams[0] ); | 335 | MyriadStream sHdr( *this, aStreams[0] ); |
336 | sHdr.write( Myriad_MAGIC_CODE, 4 ); | 336 | sHdr.write( Myriad_MAGIC_CODE, 4 ); |
337 | 337 | ||
338 | // Version (1) | 338 | // Version (1) |
339 | cBuf = 1; | 339 | cBuf = 1; |
340 | sHdr.write( &cBuf, 1 ); | 340 | sHdr.write( &cBuf, 1 ); |
341 | 341 | ||
342 | // Bits per int | 342 | // Bits per int |
343 | cBuf = 32; | 343 | cBuf = 32; |
344 | sHdr.write( &cBuf, 1 ); | 344 | sHdr.write( &cBuf, 1 ); |
345 | 345 | ||
346 | // The size of each block | 346 | // The size of each block |
347 | sHdr.write( &iBlockSize, 4 ); | 347 | sHdr.write( &iBlockSize, 4 ); |
348 | 348 | ||
349 | iBuf = aStreams.getSize(); | 349 | iBuf = aStreams.getSize(); |
350 | // The number of streams | 350 | // The number of streams |
351 | sHdr.write( &iBuf, 4 ); | 351 | sHdr.write( &iBuf, 4 ); |
352 | 352 | ||
353 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 353 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
354 | { | 354 | { |
355 | sHdr.write( &(*i)->iId, 4 ); | 355 | sHdr.write( &(*i)->iId, 4 ); |
356 | sHdr.write( &(*i)->iSize, 4 ); | 356 | sHdr.write( &(*i)->iSize, 4 ); |
357 | int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); | 357 | int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize ); |
358 | // for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) | 358 | // for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ ) |
359 | for( int j = 0; j < iUsedBlocks; j++ ) | 359 | for( int j = 0; j < iUsedBlocks; j++ ) |
360 | { | 360 | { |
361 | sHdr.write( &(*i)->aBlocks[j], 4 ); | 361 | sHdr.write( &(*i)->aBlocks[j], 4 ); |
362 | } | 362 | } |
363 | } | 363 | } |
364 | 364 | ||
365 | bHeaderChanged = false; | 365 | bHeaderChanged = false; |
366 | } | 366 | } |
367 | 367 | ||
368 | int Bu::Myriad::createStream( int iPreAllocate ) | 368 | int Bu::Myriad::createStream( int iPreAllocate ) |
369 | { | 369 | { |
370 | MutexLocker mLock( mHeader ); | 370 | MutexLocker mLock( mHeader ); |
371 | 371 | ||
372 | Stream *pStr = new Stream(); | 372 | Stream *pStr = new Stream(); |
373 | pStr->iId = aStreams.last()->iId+1; | 373 | pStr->iId = aStreams.last()->iId+1; |
374 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | 374 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" |
375 | // << iPreAllocate << sio.nl; | 375 | // << iPreAllocate << sio.nl; |
376 | pStr->iSize = 0; | 376 | pStr->iSize = 0; |
377 | aStreams.append( pStr ); | 377 | aStreams.append( pStr ); |
378 | 378 | ||
379 | for( int j = 0; j < iPreAllocate; j++ ) | 379 | for( int j = 0; j < iPreAllocate; j++ ) |
380 | { | 380 | { |
381 | int iFreeBlock = findEmptyBlock(); | 381 | int iFreeBlock = findEmptyBlock(); |
382 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; | 382 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; |
383 | pStr->aBlocks.append( iFreeBlock ); | 383 | pStr->aBlocks.append( iFreeBlock ); |
384 | // bsBlockUsed.setBit( iFreeBlock ); | 384 | // bsBlockUsed.setBit( iFreeBlock ); |
385 | iUsed++; | 385 | iUsed++; |
386 | } | 386 | } |
387 | 387 | ||
388 | bHeaderChanged = true; | 388 | bHeaderChanged = true; |
389 | 389 | ||
390 | return pStr->iId; | 390 | return pStr->iId; |
391 | } | 391 | } |
392 | 392 | ||
393 | int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) | 393 | int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) |
394 | { | 394 | { |
395 | MutexLocker mLock( mHeader ); | 395 | MutexLocker mLock( mHeader ); |
396 | 396 | ||
397 | try | 397 | try |
398 | { | 398 | { |
399 | findStream( iId ); | 399 | findStream( iId ); |
400 | throw MyriadException( MyriadException::streamExists, | 400 | throw MyriadException( MyriadException::streamExists, |
401 | "There is already a stream with the given id."); | 401 | "There is already a stream with the given id."); |
402 | } | 402 | } |
403 | catch( MyriadException &e ) | 403 | catch( MyriadException &e ) |
404 | { | 404 | { |
405 | Stream *pStr = new Stream(); | 405 | Stream *pStr = new Stream(); |
406 | pStr->iId = iId; | 406 | pStr->iId = iId; |
407 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | 407 | //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" |
408 | // << iPreAllocate << sio.nl; | 408 | // << iPreAllocate << sio.nl; |
409 | pStr->iSize = 0; | 409 | pStr->iSize = 0; |
410 | if( aStreams.last()->iId < iId ) | 410 | if( aStreams.last()->iId < iId ) |
411 | { | 411 | { |
412 | aStreams.append( pStr ); | 412 | aStreams.append( pStr ); |
413 | } | 413 | } |
414 | else | 414 | else |
415 | { | 415 | { |
416 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 416 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
417 | { | 417 | { |
418 | if( (*i)->iId > iId ) | 418 | if( (*i)->iId > iId ) |
419 | { | 419 | { |
420 | aStreams.insert( i, pStr ); | 420 | aStreams.insert( i, pStr ); |
421 | break; | 421 | break; |
422 | } | 422 | } |
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | for( int j = 0; j < iPreAllocate; j++ ) | 426 | for( int j = 0; j < iPreAllocate; j++ ) |
427 | { | 427 | { |
428 | int iFreeBlock = findEmptyBlock(); | 428 | int iFreeBlock = findEmptyBlock(); |
429 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; | 429 | // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; |
430 | pStr->aBlocks.append( iFreeBlock ); | 430 | pStr->aBlocks.append( iFreeBlock ); |
431 | // bsBlockUsed.setBit( iFreeBlock ); | 431 | // bsBlockUsed.setBit( iFreeBlock ); |
432 | iUsed++; | 432 | iUsed++; |
433 | } | 433 | } |
434 | 434 | ||
435 | bHeaderChanged = true; | 435 | bHeaderChanged = true; |
436 | 436 | ||
437 | return pStr->iId; | 437 | return pStr->iId; |
438 | } | 438 | } |
439 | } | 439 | } |
440 | 440 | ||
441 | int Bu::Myriad::findEmptyBlock() | 441 | int Bu::Myriad::findEmptyBlock() |
442 | { | 442 | { |
443 | bHeaderChanged = true; | 443 | bHeaderChanged = true; |
444 | 444 | ||
445 | if( lFreeBlocks.isEmpty() ) | 445 | if( lFreeBlocks.isEmpty() ) |
446 | { | 446 | { |
447 | sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); | 447 | sStore.setSize( (iBlocks+1)*(Bu::size)iBlockSize ); |
448 | return iBlocks++; | 448 | return iBlocks++; |
449 | } | 449 | } |
450 | else | 450 | else |
451 | { | 451 | { |
452 | return lFreeBlocks.dequeue(); | 452 | return lFreeBlocks.dequeue(); |
453 | } | 453 | } |
454 | } | 454 | } |
455 | 455 | ||
456 | void Bu::Myriad::deleteStream( int iId ) | 456 | void Bu::Myriad::deleteStream( int iId ) |
457 | { | 457 | { |
458 | MutexLocker mLock( mHeader ); | 458 | MutexLocker mLock( mHeader ); |
459 | 459 | ||
460 | if( iId < 0 ) | 460 | if( iId < 0 ) |
461 | throw MyriadException( MyriadException::invalidStreamId, | 461 | throw MyriadException( MyriadException::invalidStreamId, |
462 | "Invalid stream id."); | 462 | "Invalid stream id."); |
463 | if( iId == 0 ) | 463 | if( iId == 0 ) |
464 | throw MyriadException( MyriadException::protectedStream, | 464 | throw MyriadException( MyriadException::protectedStream, |
465 | "You cannot delete stream zero, it is protected."); | 465 | "You cannot delete stream zero, it is protected."); |
466 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 466 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
467 | { | 467 | { |
468 | if( (*i)->iId == iId ) | 468 | if( (*i)->iId == iId ) |
469 | { | 469 | { |
470 | Stream *pStream = *i; | 470 | Stream *pStream = *i; |
471 | for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) | 471 | for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) |
472 | { | 472 | { |
473 | lFreeBlocks.append( *j ); | 473 | lFreeBlocks.append( *j ); |
474 | // bsBlockUsed.setBit( *j, false ); | 474 | // bsBlockUsed.setBit( *j, false ); |
475 | iUsed--; | 475 | iUsed--; |
476 | } | 476 | } |
477 | aStreams.erase( i ); | 477 | aStreams.erase( i ); |
478 | bHeaderChanged = true; | 478 | bHeaderChanged = true; |
479 | delete pStream; | 479 | delete pStream; |
480 | return; | 480 | return; |
481 | } | 481 | } |
482 | } | 482 | } |
483 | } | 483 | } |
484 | 484 | ||
485 | Bu::Array<int> Bu::Myriad::getStreamIds() | 485 | Bu::Array<int> Bu::Myriad::getStreamIds() |
486 | { | 486 | { |
487 | MutexLocker mLock( mHeader ); | 487 | MutexLocker mLock( mHeader ); |
488 | 488 | ||
489 | Bu::Array<int> aRet( aStreams.getSize() ); | 489 | Bu::Array<int> aRet( aStreams.getSize() ); |
490 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 490 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
491 | { | 491 | { |
492 | aRet.append( (*i)->iId ); | 492 | aRet.append( (*i)->iId ); |
493 | } | 493 | } |
494 | 494 | ||
495 | return aRet; | 495 | return aRet; |
496 | } | 496 | } |
497 | 497 | ||
498 | int Bu::Myriad::getStreamSize( int iId ) | 498 | int Bu::Myriad::getStreamSize( int iId ) |
499 | { | 499 | { |
500 | MutexLocker mLock( mHeader ); | 500 | MutexLocker mLock( mHeader ); |
501 | 501 | ||
502 | return findStream( iId )->iSize; | 502 | return findStream( iId )->iSize; |
503 | } | 503 | } |
504 | 504 | ||
505 | bool Bu::Myriad::hasStream( int iId ) | 505 | bool Bu::Myriad::hasStream( int iId ) |
506 | { | 506 | { |
507 | MutexLocker mLock( mHeader ); | 507 | MutexLocker mLock( mHeader ); |
508 | 508 | ||
509 | try | 509 | try |
510 | { | 510 | { |
511 | findStream( iId ); | 511 | findStream( iId ); |
512 | return true; | 512 | return true; |
513 | }catch(...) | 513 | }catch(...) |
514 | { | 514 | { |
515 | return false; | 515 | return false; |
516 | } | 516 | } |
517 | } | 517 | } |
518 | 518 | ||
519 | Bu::MyriadStream Bu::Myriad::openStream( int iId ) | 519 | Bu::MyriadStream Bu::Myriad::openStream( int iId ) |
520 | { | 520 | { |
521 | MutexLocker mLock( mHeader ); | 521 | MutexLocker mLock( mHeader ); |
522 | 522 | ||
523 | //sio << "Myriad: Request to open stream: " << iId << sio.nl; | 523 | //sio << "Myriad: Request to open stream: " << iId << sio.nl; |
524 | return MyriadStream( *this, findStream( iId ) ); | 524 | return MyriadStream( *this, findStream( iId ) ); |
525 | } | 525 | } |
526 | 526 | ||
527 | int Bu::Myriad::getNumStreams() | 527 | int Bu::Myriad::getNumStreams() |
528 | { | 528 | { |
529 | MutexLocker mLock( mHeader ); | 529 | MutexLocker mLock( mHeader ); |
530 | 530 | ||
531 | return aStreams.getSize(); | 531 | return aStreams.getSize(); |
532 | } | 532 | } |
533 | 533 | ||
534 | int Bu::Myriad::getBlockSize() | 534 | int Bu::Myriad::getBlockSize() |
535 | { | 535 | { |
536 | return iBlockSize; | 536 | return iBlockSize; |
537 | } | 537 | } |
538 | 538 | ||
539 | int Bu::Myriad::getNumBlocks() | 539 | int Bu::Myriad::getNumBlocks() |
540 | { | 540 | { |
541 | return iBlocks; | 541 | return iBlocks; |
542 | } | 542 | } |
543 | 543 | ||
544 | int Bu::Myriad::getNumUsedBlocks() | 544 | int Bu::Myriad::getNumUsedBlocks() |
545 | { | 545 | { |
546 | return iUsed; | 546 | return iUsed; |
547 | } | 547 | } |
548 | 548 | ||
549 | Bu::size Bu::Myriad::getTotalUsedBytes() | 549 | Bu::size Bu::Myriad::getTotalUsedBytes() |
550 | { | 550 | { |
551 | MutexLocker mLock( mHeader ); | 551 | MutexLocker mLock( mHeader ); |
552 | 552 | ||
553 | Bu::size iTotalSize = 0; | 553 | Bu::size iTotalSize = 0; |
554 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 554 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
555 | { | 555 | { |
556 | iTotalSize += (*i)->iSize; | 556 | iTotalSize += (*i)->iSize; |
557 | } | 557 | } |
558 | return iTotalSize; | 558 | return iTotalSize; |
559 | } | 559 | } |
560 | 560 | ||
561 | Bu::size Bu::Myriad::getTotalUnusedBytes() | 561 | Bu::size Bu::Myriad::getTotalUnusedBytes() |
562 | { | 562 | { |
563 | MutexLocker mLock( mHeader ); | 563 | MutexLocker mLock( mHeader ); |
564 | 564 | ||
565 | Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; | 565 | Bu::size iTotalSize = (iBlocks-iUsed)*iBlockSize; |
566 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 566 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
567 | { | 567 | { |
568 | iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); | 568 | iTotalSize += iBlockSize - ((Bu::size)(*i)->iSize%iBlockSize); |
569 | } | 569 | } |
570 | return iTotalSize; | 570 | return iTotalSize; |
571 | } | 571 | } |
572 | 572 | ||
573 | Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) | 573 | Bu::size Bu::Myriad::getTotalUnusedBytes( int iFakeBlockSize ) |
574 | { | 574 | { |
575 | MutexLocker mLock( mHeader ); | 575 | MutexLocker mLock( mHeader ); |
576 | 576 | ||
577 | Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; | 577 | Bu::size iTotalSize = (iBlocks-iUsed)*iFakeBlockSize; |
578 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 578 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
579 | { | 579 | { |
580 | iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); | 580 | iTotalSize += iFakeBlockSize - ((*i)->iSize%iFakeBlockSize); |
581 | } | 581 | } |
582 | return iTotalSize; | 582 | return iTotalSize; |
583 | } | 583 | } |
584 | 584 | ||
585 | Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) | 585 | Bu::Myriad::Stream *Bu::Myriad::findStream( int iId ) |
586 | { | 586 | { |
587 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | 587 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) |
588 | { | 588 | { |
589 | if( (*i)->iId == iId ) | 589 | if( (*i)->iId == iId ) |
590 | return *i; | 590 | return *i; |
591 | } | 591 | } |
592 | 592 | ||
593 | throw MyriadException( MyriadException::noSuchStream, | 593 | throw MyriadException( MyriadException::noSuchStream, |
594 | "The requested stream doesn't exist and cannot be opened." ); | 594 | "The requested stream doesn't exist and cannot be opened." ); |
595 | 595 | ||
596 | return NULL; | 596 | return NULL; |
597 | } | 597 | } |
598 | 598 | ||
599 | Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) | 599 | Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock ) |
600 | { | 600 | { |
601 | // sio << "Myriad: Reading block " << iBlock << ", bytes " | 601 | // sio << "Myriad: Reading block " << iBlock << ", bytes " |
602 | // << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; | 602 | // << iBlockSize*iBlock << "-" << iBlockSize*(iBlock+1) << sio.nl; |
603 | Block *pBlock = new Block; | 603 | Block *pBlock = new Block; |
604 | pBlock->pData = new char[iBlockSize]; | 604 | pBlock->pData = new char[iBlockSize]; |
605 | sStore.setPos( iBlockSize * (Bu::size)iBlock ); | 605 | sStore.setPos( iBlockSize * (Bu::size)iBlock ); |
606 | sStore.read( pBlock->pData, iBlockSize ); | 606 | sStore.read( pBlock->pData, iBlockSize ); |
607 | pBlock->bChanged = false; | 607 | pBlock->bChanged = false; |
608 | pBlock->iBlockIndex = iBlock; | 608 | pBlock->iBlockIndex = iBlock; |
609 | 609 | ||
610 | mActiveBlocks.lock(); | 610 | mActiveBlocks.lock(); |
611 | hActiveBlocks.insert( iBlock, pBlock ); | 611 | hActiveBlocks.insert( iBlock, pBlock ); |
612 | mActiveBlocks.unlock(); | 612 | mActiveBlocks.unlock(); |
613 | 613 | ||
614 | return pBlock; | 614 | return pBlock; |
615 | } | 615 | } |
616 | 616 | ||
617 | void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) | 617 | void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) |
618 | { | 618 | { |
619 | if( pBlock == NULL ) | 619 | if( pBlock == NULL ) |
620 | return; | 620 | return; |
621 | // sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; | 621 | // sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; |
622 | syncBlock( pBlock ); | 622 | syncBlock( pBlock ); |
623 | mActiveBlocks.lock(); | 623 | mActiveBlocks.lock(); |
624 | hActiveBlocks.erase( pBlock->iBlockIndex ); | 624 | hActiveBlocks.erase( pBlock->iBlockIndex ); |
625 | mActiveBlocks.unlock(); | 625 | mActiveBlocks.unlock(); |
626 | 626 | ||
627 | delete[] pBlock->pData; | 627 | delete[] pBlock->pData; |
628 | delete pBlock; | 628 | delete pBlock; |
629 | } | 629 | } |
630 | 630 | ||
631 | void Bu::Myriad::syncBlock( Block *pBlock ) | 631 | void Bu::Myriad::syncBlock( Block *pBlock ) |
632 | { | 632 | { |
633 | if( pBlock->bChanged ) | 633 | if( pBlock->bChanged ) |
634 | { | 634 | { |
635 | // sio << "Myriad: - Block changed, writing back to stream." << sio.nl; | 635 | // sio << "Myriad: - Block changed, writing back to stream." << sio.nl; |
636 | sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); | 636 | sStore.setPos( iBlockSize * (Bu::size)pBlock->iBlockIndex ); |
637 | sStore.write( pBlock->pData, iBlockSize ); | 637 | sStore.write( pBlock->pData, iBlockSize ); |
638 | pBlock->bChanged = false; | 638 | pBlock->bChanged = false; |
639 | } | 639 | } |
640 | } | 640 | } |
641 | 641 | ||
642 | int Bu::Myriad::streamAddBlock( Stream *pStream ) | 642 | int Bu::Myriad::streamAddBlock( Stream *pStream ) |
643 | { | 643 | { |
644 | MutexLocker mLock( mHeader ); | 644 | MutexLocker mLock( mHeader ); |
645 | 645 | ||
646 | int iBlock = findEmptyBlock(); | 646 | int iBlock = findEmptyBlock(); |
647 | pStream->aBlocks.append( iBlock ); | 647 | pStream->aBlocks.append( iBlock ); |
648 | // bsBlockUsed.setBit( iBlock ); | 648 | // bsBlockUsed.setBit( iBlock ); |
649 | // bHeaderChanged = true; | 649 | // bHeaderChanged = true; |
650 | iUsed++; | 650 | iUsed++; |
651 | return iBlock; | 651 | return iBlock; |
652 | } | 652 | } |
653 | 653 | ||
654 | void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) | 654 | void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) |
655 | { | 655 | { |
656 | MutexLocker mLock( mHeader ); | 656 | MutexLocker mLock( mHeader ); |
657 | 657 | ||
658 | if( pStream->iSize == iSize ) | 658 | if( pStream->iSize == iSize ) |
659 | { | 659 | { |
660 | return; | 660 | return; |
661 | } | 661 | } |
662 | else if( pStream->iSize > iSize ) | 662 | else if( pStream->iSize > iSize ) |
663 | { | 663 | { |
664 | // Shrink | 664 | // Shrink |
665 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; | 665 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; |
666 | iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) | 666 | iNewSize-iBlockSize > iSize; iNewSize -= iBlockSize ) |
667 | { | 667 | { |
668 | // if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) | 668 | // if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) |
669 | iUsed--; | 669 | iUsed--; |
670 | // else | 670 | // else |
671 | // sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; | 671 | // sio << "Unused block used in stream? " << pStream->aBlocks.last() << sio.nl; |
672 | lFreeBlocks.enqueue( pStream->aBlocks.last() ); | 672 | lFreeBlocks.enqueue( pStream->aBlocks.last() ); |
673 | // bsBlockUsed.setBit( pStream->aBlocks.last(), false ); | 673 | // bsBlockUsed.setBit( pStream->aBlocks.last(), false ); |
674 | pStream->aBlocks.eraseLast(); | 674 | pStream->aBlocks.eraseLast(); |
675 | } | 675 | } |
676 | pStream->iSize = iSize; | 676 | pStream->iSize = iSize; |
677 | bHeaderChanged = true; | 677 | bHeaderChanged = true; |
678 | } | 678 | } |
679 | else | 679 | else |
680 | { | 680 | { |
681 | // Grow | 681 | // Grow |
682 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; | 682 | for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; |
683 | iNewSize < iSize; iNewSize += iBlockSize ) | 683 | iNewSize < iSize; iNewSize += iBlockSize ) |
684 | { | 684 | { |
685 | //streamAddBlock( pStream ); | 685 | //streamAddBlock( pStream ); |
686 | int iBlock = findEmptyBlock(); | 686 | int iBlock = findEmptyBlock(); |
687 | pStream->aBlocks.append( iBlock ); | 687 | pStream->aBlocks.append( iBlock ); |
688 | // bsBlockUsed.setBit( iBlock ); | 688 | // bsBlockUsed.setBit( iBlock ); |
689 | // bHeaderChanged = true; | 689 | // bHeaderChanged = true; |
690 | iUsed++; | 690 | iUsed++; |
691 | } | 691 | } |
692 | pStream->iSize = iSize; | 692 | pStream->iSize = iSize; |
693 | bHeaderChanged = true; | 693 | bHeaderChanged = true; |
694 | } | 694 | } |
695 | } | 695 | } |
696 | 696 | ||
697 | void Bu::Myriad::headerChanged() | 697 | void Bu::Myriad::headerChanged() |
698 | { | 698 | { |
699 | bHeaderChanged = true; | 699 | bHeaderChanged = true; |
700 | } | 700 | } |
701 | 701 | ||
702 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) | 702 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore ) |
703 | { | 703 | { |
704 | uint8_t uTmp; | 704 | uint8_t uTmp; |
705 | 705 | ||
706 | return isMyriad( sStore, uTmp ); | 706 | return isMyriad( sStore, uTmp ); |
707 | } | 707 | } |
708 | 708 | ||
709 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) | 709 | bool Bu::Myriad::isMyriad( Bu::Stream &sStore, uint8_t &uTmp ) |
710 | { | 710 | { |
711 | sStore.setPos( 0 ); | 711 | sStore.setPos( 0 ); |
712 | 712 | ||
713 | unsigned char buf[4]; | 713 | unsigned char buf[4]; |
714 | if( sStore.read( buf, 4 ) < 4 ) | 714 | if( sStore.read( buf, 4 ) < 4 ) |
715 | throw MyriadException( MyriadException::emptyStream, | 715 | throw MyriadException( MyriadException::emptyStream, |
716 | "Input stream appears to be empty."); | 716 | "Input stream appears to be empty."); |
717 | sStore.read( &uTmp, 1 ); | 717 | sStore.read( &uTmp, 1 ); |
718 | sStore.setPos( 0 ); | 718 | sStore.setPos( 0 ); |
719 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | 719 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) |
720 | { | 720 | { |
721 | return false; | 721 | return false; |
722 | } | 722 | } |
723 | return true; | 723 | return true; |
724 | } | 724 | } |
725 | 725 | ||
726 | const Bu::BitString Bu::Myriad::getBlocksUsed() const | 726 | const Bu::BitString Bu::Myriad::getBlocksUsed() const |
727 | { | 727 | { |
728 | Bu::BitString bs( iBlocks, false ); | 728 | Bu::BitString bs( iBlocks, false ); |
729 | for( int j = 0; j < iBlocks; j++ ) | 729 | for( int j = 0; j < iBlocks; j++ ) |
730 | bs.setBit( j ); | 730 | bs.setBit( j ); |
731 | for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) | 731 | for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ ) |
732 | bs.setBit( *i, false ); | 732 | bs.setBit( *i, false ); |
733 | return bs; | 733 | return bs; |
734 | } | 734 | } |
735 | 735 | ||
diff --git a/src/stable/myriad.h b/src/stable/myriad.h index 6b1db41..4bfd88e 100644 --- a/src/stable/myriad.h +++ b/src/stable/myriad.h | |||
@@ -18,219 +18,219 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | class Stream; | 21 | class Stream; |
22 | class MyriadStream; | 22 | class MyriadStream; |
23 | 23 | ||
24 | subExceptionDeclBegin( MyriadException ) | 24 | subExceptionDeclBegin( MyriadException ) |
25 | enum | 25 | enum |
26 | { | 26 | { |
27 | emptyStream, | 27 | emptyStream, |
28 | invalidFormat, | 28 | invalidFormat, |
29 | badVersion, | 29 | badVersion, |
30 | invalidWordSize, | 30 | invalidWordSize, |
31 | noSuchStream, | 31 | noSuchStream, |
32 | streamExists, | 32 | streamExists, |
33 | invalidStreamId, | 33 | invalidStreamId, |
34 | protectedStream | 34 | protectedStream |
35 | }; | 35 | }; |
36 | subExceptionDeclEnd(); | 36 | subExceptionDeclEnd(); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Myriad block-allocated stream multiplexing system. This is a system for | 39 | * Myriad block-allocated stream multiplexing system. This is a system for |
40 | * creating streams that contain other streams in a flexible and lightweight | 40 | * creating streams that contain other streams in a flexible and lightweight |
41 | * manner. Basically, you can create a file (or any other stream) that can | 41 | * manner. Basically, you can create a file (or any other stream) that can |
42 | * store any number of flexible, growing streams. The streams within the | 42 | * store any number of flexible, growing streams. The streams within the |
43 | * Myriad stream are automatically numbered, not named. This works more | 43 | * Myriad stream are automatically numbered, not named. This works more |
44 | * or less like a filesystem, but without the extra layer for managing | 44 | * or less like a filesystem, but without the extra layer for managing |
45 | * file and directory links. This would actually be very easy to add | 45 | * file and directory links. This would actually be very easy to add |
46 | * on top of Myriad, but is not required. | 46 | * on top of Myriad, but is not required. |
47 | * | 47 | * |
48 | * Header format is as follows: | 48 | * Header format is as follows: |
49 | * | 49 | * |
50 | * MMMMvBssssSSSS* | 50 | * MMMMvBssssSSSS* |
51 | * M = Magic number (0AD3FA84) | 51 | * M = Magic number (0AD3FA84) |
52 | * v = version number | 52 | * v = version number |
53 | * B = Bits per int | 53 | * B = Bits per int |
54 | * s = Blocksize in bytes | 54 | * s = Blocksize in bytes |
55 | * S = Number of Streams | 55 | * S = Number of Streams |
56 | * | 56 | * |
57 | * The * represents the Stream headers, one per stream, as follows: | 57 | * The * represents the Stream headers, one per stream, as follows: |
58 | * IIIIssss$ | 58 | * IIIIssss$ |
59 | * I = Id number of the stream | 59 | * I = Id number of the stream |
60 | * s = size of stream in bytes | 60 | * s = size of stream in bytes |
61 | * | 61 | * |
62 | * The $ represents the Block headers, one per used block, as follows: | 62 | * The $ represents the Block headers, one per used block, as follows: |
63 | * IIII | 63 | * IIII |
64 | * I = Index of the block | 64 | * I = Index of the block |
65 | * | 65 | * |
66 | * The stream/block data is interleaved in the header, so all blocks stored | 66 | * The stream/block data is interleaved in the header, so all blocks stored |
67 | * with one stream are together. The block headers are in order, and the | 67 | * with one stream are together. The block headers are in order, and the |
68 | * data in them is required to be "solid" you cannot fill partial blocks | 68 | * data in them is required to be "solid" you cannot fill partial blocks |
69 | * mid-way through a stream. | 69 | * mid-way through a stream. |
70 | * | 70 | * |
71 | * The initial block starts with the nids header, and is both the zero block | 71 | * The initial block starts with the nids header, and is both the zero block |
72 | * and the zero stream. For now, the minimum block size is the size needed | 72 | * and the zero stream. For now, the minimum block size is the size needed |
73 | * to store the base header, the zero stream header, and the first two | 73 | * to store the base header, the zero stream header, and the first two |
74 | * blocks of the zero stream, so 30 bytes. Since it's reccomended to use | 74 | * blocks of the zero stream, so 30 bytes. Since it's reccomended to use |
75 | * a size that will fit evenly into filesystem blocks, then a size of 32 is | 75 | * a size that will fit evenly into filesystem blocks, then a size of 32 is |
76 | * probably the smallest reccomended size because all powers of two equal | 76 | * probably the smallest reccomended size because all powers of two equal |
77 | * to or greater than 32 are evenly divisible by 32. | 77 | * to or greater than 32 are evenly divisible by 32. |
78 | * | 78 | * |
79 | * I have had a thought that if the block size were smaller than 42 bytes | 79 | * I have had a thought that if the block size were smaller than 42 bytes |
80 | * the header would consume the first N blocks where N * block size is | 80 | * the header would consume the first N blocks where N * block size is |
81 | * enough space to house the initial header, the first stream header, and | 81 | * enough space to house the initial header, the first stream header, and |
82 | * the first N block headers. This, of course, causes you to hit an | 82 | * the first N block headers. This, of course, causes you to hit an |
83 | * infinite header if the block size is small enough. | 83 | * infinite header if the block size is small enough. |
84 | */ | 84 | */ |
85 | class Myriad | 85 | class Myriad |
86 | { | 86 | { |
87 | friend class MyriadStream; | 87 | friend class MyriadStream; |
88 | public: | 88 | public: |
89 | /** | 89 | /** |
90 | * Create a Myriad object that uses the given stream to store data. | 90 | * Create a Myriad object that uses the given stream to store data. |
91 | * This stream must be random access. The block size and preallocate | 91 | * This stream must be random access. The block size and preallocate |
92 | * values passed in are values that will be used if the given stream | 92 | * values passed in are values that will be used if the given stream |
93 | * is empty. In that case the stream will be "formatted" for myriad | 93 | * is empty. In that case the stream will be "formatted" for myriad |
94 | * with the specified block size. If there is already a viable Myriad | 94 | * with the specified block size. If there is already a viable Myriad |
95 | * format present in the stream, then the blocksize and preallocate | 95 | * format present in the stream, then the blocksize and preallocate |
96 | * values will be ignored and the values from the stream will be used | 96 | * values will be ignored and the values from the stream will be used |
97 | * instead. If the stream doesn't appear to be Myriad formatted an | 97 | * instead. If the stream doesn't appear to be Myriad formatted an |
98 | * exception will be thrown. | 98 | * exception will be thrown. |
99 | */ | 99 | */ |
100 | Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); | 100 | Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); |
101 | virtual ~Myriad(); | 101 | virtual ~Myriad(); |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Destroy whatever data may be in the base stream and create a new | 104 | * Destroy whatever data may be in the base stream and create a new |
105 | * Myriad system there with the given blocksize. Use this with care, | 105 | * Myriad system there with the given blocksize. Use this with care, |
106 | * it will destroy anything that was already in the stream, and | 106 | * it will destroy anything that was already in the stream, and |
107 | * generally, should not ever have to be used. | 107 | * generally, should not ever have to be used. |
108 | */ | 108 | */ |
109 | void initialize( int iBlockSize, int iPreAllocate=1 ); | 109 | void initialize( int iBlockSize, int iPreAllocate=1 ); |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * Create a new stream within the Myriad system. The ID of the new | 112 | * Create a new stream within the Myriad system. The ID of the new |
113 | * stream is returned. | 113 | * stream is returned. |
114 | */ | 114 | */ |
115 | int createStream( int iPreAllocate=1 ); | 115 | int createStream( int iPreAllocate=1 ); |
116 | 116 | ||
117 | /** | 117 | /** |
118 | * Create a new stream within the Myriad system with a given id. The | 118 | * Create a new stream within the Myriad system with a given id. The |
119 | * id that you provide will be the new id of the stream unless it's | 119 | * id that you provide will be the new id of the stream unless it's |
120 | * already used, in which case an error is thrown. This is primarilly | 120 | * already used, in which case an error is thrown. This is primarilly |
121 | * useful when copying an old Myriad file into a new one. | 121 | * useful when copying an old Myriad file into a new one. |
122 | */ | 122 | */ |
123 | int createStreamWithId( int iId, int iPreAllocate=1 ); | 123 | int createStreamWithId( int iId, int iPreAllocate=1 ); |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * Delete a stream that's already within the Myriad. | 126 | * Delete a stream that's already within the Myriad. |
127 | */ | 127 | */ |
128 | void deleteStream( int iId ); | 128 | void deleteStream( int iId ); |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * Return a new Stream object assosiated with the given stream ID. | 131 | * Return a new Stream object assosiated with the given stream ID. |
132 | */ | 132 | */ |
133 | MyriadStream openStream( int iId ); | 133 | MyriadStream openStream( int iId ); |
134 | 134 | ||
135 | Bu::Array<int> getStreamIds(); | 135 | Bu::Array<int> getStreamIds(); |
136 | int getStreamSize( int iId ); | 136 | int getStreamSize( int iId ); |
137 | bool hasStream( int iId ); | 137 | bool hasStream( int iId ); |
138 | 138 | ||
139 | int getNumStreams(); | 139 | int getNumStreams(); |
140 | int getBlockSize(); | 140 | int getBlockSize(); |
141 | int getNumBlocks(); | 141 | int getNumBlocks(); |
142 | int getNumUsedBlocks(); | 142 | int getNumUsedBlocks(); |
143 | Bu::size getTotalUsedBytes(); | 143 | Bu::size getTotalUsedBytes(); |
144 | Bu::size getTotalUnusedBytes(); | 144 | Bu::size getTotalUnusedBytes(); |
145 | Bu::size getTotalUnusedBytes( int iFakeBlockSize ); | 145 | Bu::size getTotalUnusedBytes( int iFakeBlockSize ); |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * Syncronize the header data, etc. with the storage stream. It's not | 148 | * Syncronize the header data, etc. with the storage stream. It's not |
149 | * a bad idea to call this periodically. | 149 | * a bad idea to call this periodically. |
150 | */ | 150 | */ |
151 | void sync(); | 151 | void sync(); |
152 | 152 | ||
153 | /** | 153 | /** |
154 | * Read the first few bytes from the given stream and return true/false | 154 | * Read the first few bytes from the given stream and return true/false |
155 | * depending on weather or not it's a Myriad stream. This will throw | 155 | * depending on weather or not it's a Myriad stream. This will throw |
156 | * an exception if the stream is empty, or is not random access. | 156 | * an exception if the stream is empty, or is not random access. |
157 | */ | 157 | */ |
158 | static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); | 158 | static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Read the first few bytes from the given stream and return true/false | 161 | * Read the first few bytes from the given stream and return true/false |
162 | * depending on weather or not it's a Myriad stream. This will throw | 162 | * depending on weather or not it's a Myriad stream. This will throw |
163 | * an exception if the stream is empty, or is not random access. | 163 | * an exception if the stream is empty, or is not random access. |
164 | */ | 164 | */ |
165 | static bool isMyriad( Bu::Stream &sStore ); | 165 | static bool isMyriad( Bu::Stream &sStore ); |
166 | 166 | ||
167 | const Bu::BitString getBlocksUsed() const; | 167 | const Bu::BitString getBlocksUsed() const; |
168 | 168 | ||
169 | private: | 169 | private: |
170 | /** | 170 | /** |
171 | * Initialize this object based on the data already in the assosiated | 171 | * Initialize this object based on the data already in the assosiated |
172 | * stream. This will be called automatically for you if you forget, | 172 | * stream. This will be called automatically for you if you forget, |
173 | * but if you want to pre-initialize for some reason, just call this | 173 | * but if you want to pre-initialize for some reason, just call this |
174 | * once before you actually start doing anything with your Myriad. | 174 | * once before you actually start doing anything with your Myriad. |
175 | */ | 175 | */ |
176 | void initialize(); | 176 | void initialize(); |
177 | 177 | ||
178 | enum | 178 | enum |
179 | { | 179 | { |
180 | blockUnused = 0xFFFFFFFFUL | 180 | blockUnused = 0xFFFFFFFFUL |
181 | }; | 181 | }; |
182 | 182 | ||
183 | typedef Bu::Array<int> BlockArray; | 183 | typedef Bu::Array<int> BlockArray; |
184 | class Stream | 184 | class Stream |
185 | { | 185 | { |
186 | public: | 186 | public: |
187 | int iId; | 187 | int iId; |
188 | int iSize; | 188 | int iSize; |
189 | BlockArray aBlocks; | 189 | BlockArray aBlocks; |
190 | }; | 190 | }; |
191 | typedef Bu::Array<Stream *> StreamArray; | 191 | typedef Bu::Array<Stream *> StreamArray; |
192 | 192 | ||
193 | class Block | 193 | class Block |
194 | { | 194 | { |
195 | public: | 195 | public: |
196 | char *pData; | 196 | char *pData; |
197 | bool bChanged; | 197 | bool bChanged; |
198 | int iBlockIndex; | 198 | int iBlockIndex; |
199 | }; | 199 | }; |
200 | 200 | ||
201 | void updateHeader(); | 201 | void updateHeader(); |
202 | int findEmptyBlock(); | 202 | int findEmptyBlock(); |
203 | 203 | ||
204 | /** | 204 | /** |
205 | *@todo Change this to use a binary search, it's nicer. | 205 | *@todo Change this to use a binary search, it's nicer. |
206 | */ | 206 | */ |
207 | Stream *findStream( int iId ); | 207 | Stream *findStream( int iId ); |
208 | 208 | ||
209 | Block *getBlock( int iBlock ); | 209 | Block *getBlock( int iBlock ); |
210 | void releaseBlock( Block *pBlock ); | 210 | void releaseBlock( Block *pBlock ); |
211 | void syncBlock( Block *pBlock ); | 211 | void syncBlock( Block *pBlock ); |
212 | 212 | ||
213 | int streamAddBlock( Stream *pStream ); | 213 | int streamAddBlock( Stream *pStream ); |
214 | void setStreamSize( Stream *pStream, long iSize ); | 214 | void setStreamSize( Stream *pStream, long iSize ); |
215 | 215 | ||
216 | void headerChanged(); | 216 | void headerChanged(); |
217 | 217 | ||
218 | private: | 218 | private: |
219 | Bu::Stream &sStore; | 219 | Bu::Stream &sStore; |
220 | int iBlockSize; | 220 | int iBlockSize; |
221 | int iBlocks; | 221 | int iBlocks; |
222 | int iUsed; | 222 | int iUsed; |
223 | typedef Bu::List<int> IndexList; | 223 | typedef Bu::List<int> IndexList; |
224 | IndexList lFreeBlocks; | 224 | IndexList lFreeBlocks; |
225 | // Bu::BitString bsBlockUsed; | 225 | // Bu::BitString bsBlockUsed; |
226 | StreamArray aStreams; | 226 | StreamArray aStreams; |
227 | typedef Bu::Hash<int, Block *> BlockHash; | 227 | typedef Bu::Hash<int, Block *> BlockHash; |
228 | BlockHash hActiveBlocks; | 228 | BlockHash hActiveBlocks; |
229 | bool bHeaderChanged; | 229 | bool bHeaderChanged; |
230 | 230 | ||
231 | Bu::Mutex mHeader; | 231 | Bu::Mutex mHeader; |
232 | Bu::Mutex mActiveBlocks; | 232 | Bu::Mutex mActiveBlocks; |
233 | }; | 233 | }; |
234 | }; | 234 | }; |
235 | 235 | ||
236 | #endif | 236 | #endif |
diff --git a/src/stable/myriadstream.cpp b/src/stable/myriadstream.cpp index 58d3936..c33445a 100644 --- a/src/stable/myriadstream.cpp +++ b/src/stable/myriadstream.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include <string.h> | 10 | #include <string.h> |
11 | 11 | ||
12 | // #define MYRIAD_STREAM_DEBUG 1 | 12 | // #define MYRIAD_STREAM_DEBUG 1 |
13 | 13 | ||
14 | #ifdef MYRIAD_STREAM_DEBUG | 14 | #ifdef MYRIAD_STREAM_DEBUG |
15 | #include "bu/sio.h" | 15 | #include "bu/sio.h" |
@@ -19,27 +19,27 @@ using Bu::Fmt; | |||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, | 21 | Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, |
22 | Bu::Myriad::Stream *pStream ) : | 22 | Bu::Myriad::Stream *pStream ) : |
23 | rMyriad( rMyriad ), | 23 | rMyriad( rMyriad ), |
24 | pStream( pStream ), | 24 | pStream( pStream ), |
25 | pCurBlock( NULL ), | 25 | pCurBlock( NULL ), |
26 | iPos( 0 ) | 26 | iPos( 0 ) |
27 | { | 27 | { |
28 | #ifdef MYRIAD_STREAM_DEBUG | 28 | #ifdef MYRIAD_STREAM_DEBUG |
29 | sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" | 29 | sio << "MyriadStream: " << __LINE__ << ": Created, iId=" << pStream->iId << ", iSize=" |
30 | << pStream->iSize << sio.nl; | 30 | << pStream->iSize << sio.nl; |
31 | #endif | 31 | #endif |
32 | //pCurBlock = rMyriad.newBlock(); | 32 | //pCurBlock = rMyriad.newBlock(); |
33 | //rMyriad.getBlock( uStream, pCurBlock ); | 33 | //rMyriad.getBlock( uStream, pCurBlock ); |
34 | //uSize = pCurBlock->uBytesUsed; | 34 | //uSize = pCurBlock->uBytesUsed; |
35 | } | 35 | } |
36 | 36 | ||
37 | Bu::MyriadStream::~MyriadStream() | 37 | Bu::MyriadStream::~MyriadStream() |
38 | { | 38 | { |
39 | if( pCurBlock ) | 39 | if( pCurBlock ) |
40 | rMyriad.releaseBlock( pCurBlock ); | 40 | rMyriad.releaseBlock( pCurBlock ); |
41 | //rMyriad.updateStreamSize( uStream, uSize ); | 41 | //rMyriad.updateStreamSize( uStream, uSize ); |
42 | //rMyriad.deleteBlock( pCurBlock ); | 42 | //rMyriad.deleteBlock( pCurBlock ); |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::MyriadStream::close() | 45 | void Bu::MyriadStream::close() |
@@ -49,200 +49,200 @@ void Bu::MyriadStream::close() | |||
49 | Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) | 49 | Bu::size Bu::MyriadStream::read( void *pBuf, Bu::size nBytes ) |
50 | { | 50 | { |
51 | #ifdef MYRIAD_STREAM_DEBUG | 51 | #ifdef MYRIAD_STREAM_DEBUG |
52 | sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." | 52 | sio << "MyriadStream: read: " << __LINE__ << ": Started, asked to read " << nBytes << "b." |
53 | << sio.nl; | 53 | << sio.nl; |
54 | #endif | 54 | #endif |
55 | if( nBytes > (Bu::size)pStream->iSize-iPos ) | 55 | if( nBytes > (Bu::size)pStream->iSize-iPos ) |
56 | nBytes = pStream->iSize-iPos; | 56 | nBytes = pStream->iSize-iPos; |
57 | if( nBytes <= 0 ) | 57 | if( nBytes <= 0 ) |
58 | return 0; | 58 | return 0; |
59 | int iLeft = nBytes; | 59 | int iLeft = nBytes; |
60 | #ifdef MYRIAD_STREAM_DEBUG | 60 | #ifdef MYRIAD_STREAM_DEBUG |
61 | sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." | 61 | sio << "MyriadStream: read: " << __LINE__ << ": Started, going to read " << nBytes << "b." |
62 | << sio.nl; | 62 | << sio.nl; |
63 | #endif | 63 | #endif |
64 | if( pCurBlock == NULL ) | 64 | if( pCurBlock == NULL ) |
65 | { | 65 | { |
66 | #ifdef MYRIAD_STREAM_DEBUG | 66 | #ifdef MYRIAD_STREAM_DEBUG |
67 | sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." | 67 | sio << "MyriadStream: read: " << __LINE__ << ": No block loaded, loading initial block." |
68 | << sio.nl; | 68 | << sio.nl; |
69 | #endif | 69 | #endif |
70 | pCurBlock = rMyriad.getBlock( | 70 | pCurBlock = rMyriad.getBlock( |
71 | pStream->aBlocks[iPos/rMyriad.iBlockSize] | 71 | pStream->aBlocks[iPos/rMyriad.iBlockSize] |
72 | ); | 72 | ); |
73 | } | 73 | } |
74 | while( iLeft > 0 ) | 74 | while( iLeft > 0 ) |
75 | { | 75 | { |
76 | int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; | 76 | int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; |
77 | if( pCurBlock->iBlockIndex != iCurBlock ) | 77 | if( pCurBlock->iBlockIndex != iCurBlock ) |
78 | { | 78 | { |
79 | #ifdef MYRIAD_STREAM_DEBUG | 79 | #ifdef MYRIAD_STREAM_DEBUG |
80 | sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." | 80 | sio << "MyriadStream: read: " << __LINE__ << ": Loading new block " << iCurBlock << "." |
81 | << sio.nl; | 81 | << sio.nl; |
82 | #endif | 82 | #endif |
83 | rMyriad.releaseBlock( pCurBlock ); | 83 | rMyriad.releaseBlock( pCurBlock ); |
84 | pCurBlock = rMyriad.getBlock( iCurBlock ); | 84 | pCurBlock = rMyriad.getBlock( iCurBlock ); |
85 | } | 85 | } |
86 | 86 | ||
87 | int iAmnt = Bu::buMin( | 87 | int iAmnt = Bu::buMin( |
88 | Bu::buMin( | 88 | Bu::buMin( |
89 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 89 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
90 | iLeft | 90 | iLeft |
91 | ), | 91 | ), |
92 | pStream->iSize-iPos | 92 | pStream->iSize-iPos |
93 | ); | 93 | ); |
94 | #ifdef MYRIAD_STREAM_DEBUG | 94 | #ifdef MYRIAD_STREAM_DEBUG |
95 | sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " | 95 | sio << "MyriadStream: read: " << __LINE__ << ": Copying out bytes: " |
96 | << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" | 96 | << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" |
97 | << iAmnt | 97 | << iAmnt |
98 | << ", " << iLeft << "b left." << sio.nl; | 98 | << ", " << iLeft << "b left." << sio.nl; |
99 | #endif | 99 | #endif |
100 | memcpy( | 100 | memcpy( |
101 | pBuf, | 101 | pBuf, |
102 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 102 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
103 | iAmnt | 103 | iAmnt |
104 | ); | 104 | ); |
105 | iPos += iAmnt; | 105 | iPos += iAmnt; |
106 | pBuf = &((char *)pBuf)[iAmnt]; | 106 | pBuf = &((char *)pBuf)[iAmnt]; |
107 | iLeft -= iAmnt; | 107 | iLeft -= iAmnt; |
108 | } | 108 | } |
109 | return nBytes; | 109 | return nBytes; |
110 | } | 110 | } |
111 | 111 | ||
112 | Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) | 112 | Bu::size Bu::MyriadStream::write( const void *pBuf, Bu::size nBytes ) |
113 | { | 113 | { |
114 | if( nBytes <= 0 ) | 114 | if( nBytes <= 0 ) |
115 | return 0; | 115 | return 0; |
116 | 116 | ||
117 | #ifdef MYRIAD_STREAM_DEBUG | 117 | #ifdef MYRIAD_STREAM_DEBUG |
118 | sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." | 118 | sio << "MyriadStream: write: " << __LINE__ << ": Started, asked to write " << nBytes << "b." |
119 | << sio.nl; | 119 | << sio.nl; |
120 | #endif | 120 | #endif |
121 | if( nBytes <= 0 ) | 121 | if( nBytes <= 0 ) |
122 | return 0; | 122 | return 0; |
123 | int iLeft = nBytes; | 123 | int iLeft = nBytes; |
124 | /* | 124 | /* |
125 | if( pCurBlock == NULL ) | 125 | if( pCurBlock == NULL ) |
126 | { | 126 | { |
127 | #ifdef MYRIAD_STREAM_DEBUG | 127 | #ifdef MYRIAD_STREAM_DEBUG |
128 | sio << "MyriadStream: write: No block loaded, loading initial block." | 128 | sio << "MyriadStream: write: No block loaded, loading initial block." |
129 | << sio.nl; | 129 | << sio.nl; |
130 | #endif | 130 | #endif |
131 | pCurBlock = rMyriad.getBlock( | 131 | pCurBlock = rMyriad.getBlock( |
132 | pStream->aBlocks[iPos/rMyriad.iBlockSize] | 132 | pStream->aBlocks[iPos/rMyriad.iBlockSize] |
133 | ); | 133 | ); |
134 | }*/ | 134 | }*/ |
135 | 135 | ||
136 | while( iLeft > 0 ) | 136 | while( iLeft > 0 ) |
137 | { | 137 | { |
138 | int iCurBlock; | 138 | int iCurBlock; |
139 | if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) | 139 | if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) |
140 | { | 140 | { |
141 | iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; | 141 | iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; |
142 | } | 142 | } |
143 | else | 143 | else |
144 | { | 144 | { |
145 | iCurBlock = rMyriad.streamAddBlock( pStream ); | 145 | iCurBlock = rMyriad.streamAddBlock( pStream ); |
146 | #ifdef MYRIAD_STREAM_DEBUG | 146 | #ifdef MYRIAD_STREAM_DEBUG |
147 | sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " | 147 | sio << "MyriadStream: write: " << __LINE__ << ": New block allocated and appended: " |
148 | << iCurBlock << "." << sio.nl; | 148 | << iCurBlock << "." << sio.nl; |
149 | 149 | ||
150 | #endif | 150 | #endif |
151 | } | 151 | } |
152 | if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) | 152 | if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) |
153 | { | 153 | { |
154 | #ifdef MYRIAD_STREAM_DEBUG | 154 | #ifdef MYRIAD_STREAM_DEBUG |
155 | sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." | 155 | sio << "MyriadStream: write: " << __LINE__ << ": Loading new block " << iCurBlock << "." |
156 | << sio.nl; | 156 | << sio.nl; |
157 | #endif | 157 | #endif |
158 | rMyriad.releaseBlock( pCurBlock ); | 158 | rMyriad.releaseBlock( pCurBlock ); |
159 | pCurBlock = rMyriad.getBlock( iCurBlock ); | 159 | pCurBlock = rMyriad.getBlock( iCurBlock ); |
160 | } | 160 | } |
161 | pCurBlock->bChanged = true; | 161 | pCurBlock->bChanged = true; |
162 | 162 | ||
163 | // There are two main writing modes when it comes down to it. | 163 | // There are two main writing modes when it comes down to it. |
164 | // Overwrite mode and append mode. Append is what pretty much always | 164 | // Overwrite mode and append mode. Append is what pretty much always |
165 | // happens when creating a new stream. | 165 | // happens when creating a new stream. |
166 | if( iPos < pStream->iSize ) | 166 | if( iPos < pStream->iSize ) |
167 | { | 167 | { |
168 | int iAmnt = Bu::buMin( | 168 | int iAmnt = Bu::buMin( |
169 | Bu::buMin( | 169 | Bu::buMin( |
170 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 170 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
171 | iLeft | 171 | iLeft |
172 | ), | 172 | ), |
173 | pStream->iSize-iPos | 173 | pStream->iSize-iPos |
174 | ); | 174 | ); |
175 | #ifdef MYRIAD_STREAM_DEBUG | 175 | #ifdef MYRIAD_STREAM_DEBUG |
176 | sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " | 176 | sio << "MyriadStream: write (ovr): " << __LINE__ << ": Copying in bytes: " |
177 | << (iPos%rMyriad.iBlockSize) << "+" | 177 | << (iPos%rMyriad.iBlockSize) << "+" |
178 | << iAmnt | 178 | << iAmnt |
179 | << ", " << iLeft << "b left." << sio.nl; | 179 | << ", " << iLeft << "b left." << sio.nl; |
180 | #endif | 180 | #endif |
181 | memcpy( | 181 | memcpy( |
182 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 182 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
183 | pBuf, | 183 | pBuf, |
184 | iAmnt | 184 | iAmnt |
185 | ); | 185 | ); |
186 | iPos += iAmnt; | 186 | iPos += iAmnt; |
187 | pBuf = &((char *)pBuf)[iAmnt]; | 187 | pBuf = &((char *)pBuf)[iAmnt]; |
188 | iLeft -= iAmnt; | 188 | iLeft -= iAmnt; |
189 | } | 189 | } |
190 | else | 190 | else |
191 | { | 191 | { |
192 | int iAmnt = Bu::buMin( | 192 | int iAmnt = Bu::buMin( |
193 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, | 193 | rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, |
194 | iLeft | 194 | iLeft |
195 | ); | 195 | ); |
196 | #ifdef MYRIAD_STREAM_DEBUG | 196 | #ifdef MYRIAD_STREAM_DEBUG |
197 | sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " | 197 | sio << "MyriadStream: write (app): " << __LINE__ << ": Copying in bytes: " |
198 | << (iPos%rMyriad.iBlockSize) << "+" | 198 | << (iPos%rMyriad.iBlockSize) << "+" |
199 | << iAmnt | 199 | << iAmnt |
200 | << ", " << iLeft << "b left." << sio.nl; | 200 | << ", " << iLeft << "b left." << sio.nl; |
201 | #endif | 201 | #endif |
202 | memcpy( | 202 | memcpy( |
203 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), | 203 | pCurBlock->pData+(iPos%rMyriad.iBlockSize), |
204 | pBuf, | 204 | pBuf, |
205 | iAmnt | 205 | iAmnt |
206 | ); | 206 | ); |
207 | iPos += iAmnt; | 207 | iPos += iAmnt; |
208 | pStream->iSize += iAmnt; | 208 | pStream->iSize += iAmnt; |
209 | rMyriad.headerChanged(); | 209 | rMyriad.headerChanged(); |
210 | pBuf = &((char *)pBuf)[iAmnt]; | 210 | pBuf = &((char *)pBuf)[iAmnt]; |
211 | iLeft -= iAmnt; | 211 | iLeft -= iAmnt; |
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | return nBytes; | 215 | return nBytes; |
216 | } | 216 | } |
217 | 217 | ||
218 | Bu::size Bu::MyriadStream::tell() | 218 | Bu::size Bu::MyriadStream::tell() |
219 | { | 219 | { |
220 | return iPos; | 220 | return iPos; |
221 | } | 221 | } |
222 | 222 | ||
223 | void Bu::MyriadStream::seek( Bu::size offset ) | 223 | void Bu::MyriadStream::seek( Bu::size offset ) |
224 | { | 224 | { |
225 | iPos += offset; | 225 | iPos += offset; |
226 | } | 226 | } |
227 | 227 | ||
228 | void Bu::MyriadStream::setPos( Bu::size pos ) | 228 | void Bu::MyriadStream::setPos( Bu::size pos ) |
229 | { | 229 | { |
230 | iPos = pos; | 230 | iPos = pos; |
231 | } | 231 | } |
232 | 232 | ||
233 | void Bu::MyriadStream::setPosEnd( Bu::size pos ) | 233 | void Bu::MyriadStream::setPosEnd( Bu::size pos ) |
234 | { | 234 | { |
235 | iPos = pStream->iSize-pos; | 235 | iPos = pStream->iSize-pos; |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::MyriadStream::isEos() | 238 | bool Bu::MyriadStream::isEos() |
239 | { | 239 | { |
240 | return iPos >= pStream->iSize; | 240 | return iPos >= pStream->iSize; |
241 | } | 241 | } |
242 | 242 | ||
243 | bool Bu::MyriadStream::isOpen() | 243 | bool Bu::MyriadStream::isOpen() |
244 | { | 244 | { |
245 | return true; | 245 | return true; |
246 | } | 246 | } |
247 | 247 | ||
248 | void Bu::MyriadStream::flush() | 248 | void Bu::MyriadStream::flush() |
@@ -251,32 +251,32 @@ void Bu::MyriadStream::flush() | |||
251 | 251 | ||
252 | bool Bu::MyriadStream::canRead() | 252 | bool Bu::MyriadStream::canRead() |
253 | { | 253 | { |
254 | return true; | 254 | return true; |
255 | } | 255 | } |
256 | 256 | ||
257 | bool Bu::MyriadStream::canWrite() | 257 | bool Bu::MyriadStream::canWrite() |
258 | { | 258 | { |
259 | return true; | 259 | return true; |
260 | } | 260 | } |
261 | 261 | ||
262 | bool Bu::MyriadStream::isReadable() | 262 | bool Bu::MyriadStream::isReadable() |
263 | { | 263 | { |
264 | return true; | 264 | return true; |
265 | } | 265 | } |
266 | 266 | ||
267 | bool Bu::MyriadStream::isWritable() | 267 | bool Bu::MyriadStream::isWritable() |
268 | { | 268 | { |
269 | return true; | 269 | return true; |
270 | } | 270 | } |
271 | 271 | ||
272 | bool Bu::MyriadStream::isSeekable() | 272 | bool Bu::MyriadStream::isSeekable() |
273 | { | 273 | { |
274 | return true; | 274 | return true; |
275 | } | 275 | } |
276 | 276 | ||
277 | bool Bu::MyriadStream::isBlocking() | 277 | bool Bu::MyriadStream::isBlocking() |
278 | { | 278 | { |
279 | return true; | 279 | return true; |
280 | } | 280 | } |
281 | 281 | ||
282 | void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) | 282 | void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) |
@@ -285,25 +285,25 @@ void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ ) | |||
285 | 285 | ||
286 | void Bu::MyriadStream::setSize( Bu::size iSize ) | 286 | void Bu::MyriadStream::setSize( Bu::size iSize ) |
287 | { | 287 | { |
288 | if( iSize < 0 ) | 288 | if( iSize < 0 ) |
289 | iSize = 0; | 289 | iSize = 0; |
290 | rMyriad.setStreamSize( pStream, iSize ); | 290 | rMyriad.setStreamSize( pStream, iSize ); |
291 | if( iPos > iSize ) | 291 | if( iPos > iSize ) |
292 | iPos = iSize; | 292 | iPos = iSize; |
293 | } | 293 | } |
294 | 294 | ||
295 | Bu::size Bu::MyriadStream::getSize() const | 295 | Bu::size Bu::MyriadStream::getSize() const |
296 | { | 296 | { |
297 | return pStream->iSize; | 297 | return pStream->iSize; |
298 | } | 298 | } |
299 | 299 | ||
300 | Bu::size Bu::MyriadStream::getBlockSize() const | 300 | Bu::size Bu::MyriadStream::getBlockSize() const |
301 | { | 301 | { |
302 | return rMyriad.getBlockSize(); | 302 | return rMyriad.getBlockSize(); |
303 | } | 303 | } |
304 | 304 | ||
305 | Bu::String Bu::MyriadStream::getLocation() const | 305 | Bu::String Bu::MyriadStream::getLocation() const |
306 | { | 306 | { |
307 | return Bu::String("%1").arg( pStream->iId ); | 307 | return Bu::String("%1").arg( pStream->iId ); |
308 | } | 308 | } |
309 | 309 | ||
diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h index 7cc2fc0..fe7453f 100644 --- a/src/stable/myriadstream.h +++ b/src/stable/myriadstream.h | |||
@@ -13,49 +13,49 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class MyriadStream : public Bu::Stream | 16 | class MyriadStream : public Bu::Stream |
17 | { | 17 | { |
18 | friend class Myriad; | 18 | friend class Myriad; |
19 | private: | 19 | private: |
20 | /** | 20 | /** |
21 | * These can only be created by the Myriad class. | 21 | * These can only be created by the Myriad class. |
22 | */ | 22 | */ |
23 | MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); | 23 | MyriadStream( Myriad &rMyriad, Myriad::Stream *pStream ); |
24 | 24 | ||
25 | public: | 25 | public: |
26 | virtual ~MyriadStream(); | 26 | virtual ~MyriadStream(); |
27 | 27 | ||
28 | virtual void close(); | 28 | virtual void close(); |
29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 29 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 30 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
31 | using Stream::write; | 31 | using Stream::write; |
32 | virtual Bu::size tell(); | 32 | virtual Bu::size tell(); |
33 | virtual void seek( Bu::size offset ); | 33 | virtual void seek( Bu::size offset ); |
34 | virtual void setPos( Bu::size pos ); | 34 | virtual void setPos( Bu::size pos ); |
35 | virtual void setPosEnd( Bu::size pos ); | 35 | virtual void setPosEnd( Bu::size pos ); |
36 | virtual bool isEos(); | 36 | virtual bool isEos(); |
37 | virtual bool isOpen(); | 37 | virtual bool isOpen(); |
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | virtual bool canRead(); | 39 | virtual bool canRead(); |
40 | virtual bool canWrite(); | 40 | virtual bool canWrite(); |
41 | virtual bool isReadable(); | 41 | virtual bool isReadable(); |
42 | virtual bool isWritable(); | 42 | virtual bool isWritable(); |
43 | virtual bool isSeekable(); | 43 | virtual bool isSeekable(); |
44 | virtual bool isBlocking(); | 44 | virtual bool isBlocking(); |
45 | virtual void setBlocking( bool bBlocking=true ); | 45 | virtual void setBlocking( bool bBlocking=true ); |
46 | virtual void setSize( Bu::size iSize ); | 46 | virtual void setSize( Bu::size iSize ); |
47 | 47 | ||
48 | virtual size getSize() const; | 48 | virtual size getSize() const; |
49 | virtual size getBlockSize() const; | 49 | virtual size getBlockSize() const; |
50 | virtual Bu::String getLocation() const; | 50 | virtual Bu::String getLocation() const; |
51 | 51 | ||
52 | private: | 52 | private: |
53 | Myriad &rMyriad; | 53 | Myriad &rMyriad; |
54 | Myriad::Stream *pStream; | 54 | Myriad::Stream *pStream; |
55 | Myriad::Block *pCurBlock; | 55 | Myriad::Block *pCurBlock; |
56 | int iBlockSize; | 56 | int iBlockSize; |
57 | int iPos; | 57 | int iPos; |
58 | }; | 58 | }; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | #endif | 61 | #endif |
diff --git a/src/stable/nullstream.cpp b/src/stable/nullstream.cpp index 0dcede2..5f568b9 100644 --- a/src/stable/nullstream.cpp +++ b/src/stable/nullstream.cpp | |||
@@ -8,8 +8,8 @@ | |||
8 | #include "bu/nullstream.h" | 8 | #include "bu/nullstream.h" |
9 | 9 | ||
10 | Bu::NullStream::NullStream() : | 10 | Bu::NullStream::NullStream() : |
11 | sRead( 0 ), | 11 | sRead( 0 ), |
12 | sWrote( 0 ) | 12 | sWrote( 0 ) |
13 | { | 13 | { |
14 | } | 14 | } |
15 | 15 | ||
@@ -19,31 +19,31 @@ Bu::NullStream::~NullStream() | |||
19 | 19 | ||
20 | void Bu::NullStream::close() | 20 | void Bu::NullStream::close() |
21 | { | 21 | { |
22 | sRead = sWrote = 0; | 22 | sRead = sWrote = 0; |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) | 25 | Bu::size Bu::NullStream::read( void *pBuf, Bu::size nBytes ) |
26 | { | 26 | { |
27 | memset( pBuf, 0, nBytes ); | 27 | memset( pBuf, 0, nBytes ); |
28 | sRead += nBytes; | 28 | sRead += nBytes; |
29 | return nBytes; | 29 | return nBytes; |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::String Bu::NullStream::readLine() | 32 | Bu::String Bu::NullStream::readLine() |
33 | { | 33 | { |
34 | sRead++; | 34 | sRead++; |
35 | return Bu::String("\0", 1 ); | 35 | return Bu::String("\0", 1 ); |
36 | } | 36 | } |
37 | 37 | ||
38 | Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) | 38 | Bu::size Bu::NullStream::write( const void *, Bu::size nBytes ) |
39 | { | 39 | { |
40 | sWrote += nBytes; | 40 | sWrote += nBytes; |
41 | return nBytes; | 41 | return nBytes; |
42 | } | 42 | } |
43 | 43 | ||
44 | Bu::size Bu::NullStream::tell() | 44 | Bu::size Bu::NullStream::tell() |
45 | { | 45 | { |
46 | return sRead + sWrote; | 46 | return sRead + sWrote; |
47 | } | 47 | } |
48 | 48 | ||
49 | void Bu::NullStream::seek( Bu::size ) | 49 | void Bu::NullStream::seek( Bu::size ) |
@@ -60,12 +60,12 @@ void Bu::NullStream::setPosEnd( Bu::size ) | |||
60 | 60 | ||
61 | bool Bu::NullStream::isEos() | 61 | bool Bu::NullStream::isEos() |
62 | { | 62 | { |
63 | return false; | 63 | return false; |
64 | } | 64 | } |
65 | 65 | ||
66 | bool Bu::NullStream::isOpen() | 66 | bool Bu::NullStream::isOpen() |
67 | { | 67 | { |
68 | return true; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | void Bu::NullStream::flush() | 71 | void Bu::NullStream::flush() |
@@ -74,32 +74,32 @@ void Bu::NullStream::flush() | |||
74 | 74 | ||
75 | bool Bu::NullStream::canRead() | 75 | bool Bu::NullStream::canRead() |
76 | { | 76 | { |
77 | return true; | 77 | return true; |
78 | } | 78 | } |
79 | 79 | ||
80 | bool Bu::NullStream::canWrite() | 80 | bool Bu::NullStream::canWrite() |
81 | { | 81 | { |
82 | return true; | 82 | return true; |
83 | } | 83 | } |
84 | 84 | ||
85 | bool Bu::NullStream::isReadable() | 85 | bool Bu::NullStream::isReadable() |
86 | { | 86 | { |
87 | return true; | 87 | return true; |
88 | } | 88 | } |
89 | 89 | ||
90 | bool Bu::NullStream::isWritable() | 90 | bool Bu::NullStream::isWritable() |
91 | { | 91 | { |
92 | return true; | 92 | return true; |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::NullStream::isSeekable() | 95 | bool Bu::NullStream::isSeekable() |
96 | { | 96 | { |
97 | return false; | 97 | return false; |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::NullStream::isBlocking() | 100 | bool Bu::NullStream::isBlocking() |
101 | { | 101 | { |
102 | return true; | 102 | return true; |
103 | } | 103 | } |
104 | 104 | ||
105 | void Bu::NullStream::setBlocking( bool ) | 105 | void Bu::NullStream::setBlocking( bool ) |
@@ -112,16 +112,16 @@ void Bu::NullStream::setSize( Bu::size ) | |||
112 | 112 | ||
113 | Bu::size Bu::NullStream::getSize() const | 113 | Bu::size Bu::NullStream::getSize() const |
114 | { | 114 | { |
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | Bu::size Bu::NullStream::getBlockSize() const | 118 | Bu::size Bu::NullStream::getBlockSize() const |
119 | { | 119 | { |
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | Bu::String Bu::NullStream::getLocation() const | 123 | Bu::String Bu::NullStream::getLocation() const |
124 | { | 124 | { |
125 | return ""; | 125 | return ""; |
126 | } | 126 | } |
127 | 127 | ||
diff --git a/src/stable/nullstream.h b/src/stable/nullstream.h index 034b0c5..a8b24e3 100644 --- a/src/stable/nullstream.h +++ b/src/stable/nullstream.h | |||
@@ -12,56 +12,56 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Works a lot like /dev/null on *nix style systems. This class allows | 16 | * Works a lot like /dev/null on *nix style systems. This class allows |
17 | * infinite reading and writing. All operatorns "succeed" even if they | 17 | * infinite reading and writing. All operatorns "succeed" even if they |
18 | * don't seem to do anything. This is great for testing writing code or | 18 | * don't seem to do anything. This is great for testing writing code or |
19 | * doing dry runs. When reading, it will produce NULL bytes, so any | 19 | * doing dry runs. When reading, it will produce NULL bytes, so any |
20 | * application that would like the ability to produce null streams as a | 20 | * application that would like the ability to produce null streams as a |
21 | * snap-in replacement for any other Bu::Stream, this is the right option. | 21 | * snap-in replacement for any other Bu::Stream, this is the right option. |
22 | * | 22 | * |
23 | * As an added feature, the NullStream will track how many bytes it was | 23 | * As an added feature, the NullStream will track how many bytes it was |
24 | * asked to read and write, allowing you to use it to determine how many | 24 | * asked to read and write, allowing you to use it to determine how many |
25 | * bytes a write opretion would use without actually writing anything. | 25 | * bytes a write opretion would use without actually writing anything. |
26 | */ | 26 | */ |
27 | class NullStream : public Bu::Stream | 27 | class NullStream : public Bu::Stream |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | NullStream(); | 30 | NullStream(); |
31 | virtual ~NullStream(); | 31 | virtual ~NullStream(); |
32 | 32 | ||
33 | virtual void close(); | 33 | virtual void close(); |
34 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 34 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
35 | virtual Bu::String readLine(); | 35 | virtual Bu::String readLine(); |
36 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 36 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
37 | using Bu::Stream::write; | 37 | using Bu::Stream::write; |
38 | virtual Bu::size tell(); | 38 | virtual Bu::size tell(); |
39 | virtual void seek( Bu::size offset ); | 39 | virtual void seek( Bu::size offset ); |
40 | virtual void setPos( Bu::size pos ); | 40 | virtual void setPos( Bu::size pos ); |
41 | virtual void setPosEnd( Bu::size pos ); | 41 | virtual void setPosEnd( Bu::size pos ); |
42 | virtual bool isEos(); | 42 | virtual bool isEos(); |
43 | virtual bool isOpen(); | 43 | virtual bool isOpen(); |
44 | virtual void flush(); | 44 | virtual void flush(); |
45 | virtual bool canRead(); | 45 | virtual bool canRead(); |
46 | virtual bool canWrite(); | 46 | virtual bool canWrite(); |
47 | virtual bool isReadable(); | 47 | virtual bool isReadable(); |
48 | virtual bool isWritable(); | 48 | virtual bool isWritable(); |
49 | virtual bool isSeekable(); | 49 | virtual bool isSeekable(); |
50 | virtual bool isBlocking(); | 50 | virtual bool isBlocking(); |
51 | virtual void setBlocking( bool bBlocking=true ); | 51 | virtual void setBlocking( bool bBlocking=true ); |
52 | virtual void setSize( Bu::size iSize ); | 52 | virtual void setSize( Bu::size iSize ); |
53 | 53 | ||
54 | virtual size getSize() const; | 54 | virtual size getSize() const; |
55 | virtual size getBlockSize() const; | 55 | virtual size getBlockSize() const; |
56 | virtual Bu::String getLocation() const; | 56 | virtual Bu::String getLocation() const; |
57 | 57 | ||
58 | Bu::size getBytesRead() { return sRead; } | 58 | Bu::size getBytesRead() { return sRead; } |
59 | Bu::size getByetsWritten() { return sWrote; } | 59 | Bu::size getByetsWritten() { return sWrote; } |
60 | 60 | ||
61 | private: | 61 | private: |
62 | Bu::size sRead; | 62 | Bu::size sRead; |
63 | Bu::size sWrote; | 63 | Bu::size sWrote; |
64 | }; | 64 | }; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #endif | 67 | #endif |
diff --git a/src/stable/optparser.cpp b/src/stable/optparser.cpp index 10a8fb6..aca36a2 100644 --- a/src/stable/optparser.cpp +++ b/src/stable/optparser.cpp | |||
@@ -21,168 +21,168 @@ Bu::OptParser::~OptParser() | |||
21 | 21 | ||
22 | void Bu::OptParser::parse( int argc, char **argv ) | 22 | void Bu::OptParser::parse( int argc, char **argv ) |
23 | { | 23 | { |
24 | for( int j = 1; j < argc; j++ ) | 24 | for( int j = 1; j < argc; j++ ) |
25 | { | 25 | { |
26 | if( argv[j][0] == '-' ) | 26 | if( argv[j][0] == '-' ) |
27 | { | 27 | { |
28 | // Now we're on to something, which kind is it? | 28 | // Now we're on to something, which kind is it? |
29 | if( argv[j][1] == '-' ) | 29 | if( argv[j][1] == '-' ) |
30 | { | 30 | { |
31 | int iEPos; | 31 | int iEPos; |
32 | for( iEPos = 2; argv[j][iEPos] != '\0' && | 32 | for( iEPos = 2; argv[j][iEPos] != '\0' && |
33 | argv[j][iEPos] != '='; iEPos++ ) { } | 33 | argv[j][iEPos] != '='; iEPos++ ) { } |
34 | 34 | ||
35 | Bu::String sOpt; | 35 | Bu::String sOpt; |
36 | int iCount = argc-j; | 36 | int iCount = argc-j; |
37 | Bu::String sExtraParam; | 37 | Bu::String sExtraParam; |
38 | if( argv[j][iEPos] == '=' ) | 38 | if( argv[j][iEPos] == '=' ) |
39 | { | 39 | { |
40 | sOpt.set( argv[j]+2, iEPos-2 ); | 40 | sOpt.set( argv[j]+2, iEPos-2 ); |
41 | iCount++; | 41 | iCount++; |
42 | sExtraParam.set( argv[j]+iEPos+1 ); | 42 | sExtraParam.set( argv[j]+iEPos+1 ); |
43 | } | 43 | } |
44 | else | 44 | else |
45 | { | 45 | { |
46 | sOpt.set( argv[j]+2 ); | 46 | sOpt.set( argv[j]+2 ); |
47 | } | 47 | } |
48 | if( !hlOption.has( sOpt ) ) | 48 | if( !hlOption.has( sOpt ) ) |
49 | { | 49 | { |
50 | optionError( "--" + sOpt ); | 50 | optionError( "--" + sOpt ); |
51 | } | 51 | } |
52 | else | 52 | else |
53 | { | 53 | { |
54 | // Long param, cool, that's easy, first search for = | 54 | // Long param, cool, that's easy, first search for = |
55 | Option *pOpt = hlOption.get( sOpt ); | 55 | Option *pOpt = hlOption.get( sOpt ); |
56 | if( pOpt->sUsed ) | 56 | if( pOpt->sUsed ) |
57 | { | 57 | { |
58 | Bu::StrArray aParams( iCount ); | 58 | Bu::StrArray aParams( iCount ); |
59 | aParams.append( sOpt ); | 59 | aParams.append( sOpt ); |
60 | if( sExtraParam.isSet() ) | 60 | if( sExtraParam.isSet() ) |
61 | { | 61 | { |
62 | aParams.append( argv[j]+iEPos+1 ); | 62 | aParams.append( argv[j]+iEPos+1 ); |
63 | } | 63 | } |
64 | for( int k = j+1; k < argc; k++ ) | 64 | for( int k = j+1; k < argc; k++ ) |
65 | { | 65 | { |
66 | aParams.append( argv[k] ); | 66 | aParams.append( argv[k] ); |
67 | } | 67 | } |
68 | j += pOpt->sUsed( aParams ); | 68 | j += pOpt->sUsed( aParams ); |
69 | } | 69 | } |
70 | else if( pOpt->pProxy ) | 70 | else if( pOpt->pProxy ) |
71 | { | 71 | { |
72 | if( pOpt->sOverride.isSet() ) | 72 | if( pOpt->sOverride.isSet() ) |
73 | { | 73 | { |
74 | pOpt->pProxy->setValue( pOpt->sOverride ); | 74 | pOpt->pProxy->setValue( pOpt->sOverride ); |
75 | } | 75 | } |
76 | else if( sExtraParam.isSet() ) | 76 | else if( sExtraParam.isSet() ) |
77 | { | 77 | { |
78 | pOpt->pProxy->setValueFromStr( sExtraParam ); | 78 | pOpt->pProxy->setValueFromStr( sExtraParam ); |
79 | } | 79 | } |
80 | else if( argv[j+1] != '\0' ) | 80 | else if( argv[j+1] != '\0' ) |
81 | { | 81 | { |
82 | pOpt->pProxy->setValueFromStr( argv[j+1] ); | 82 | pOpt->pProxy->setValueFromStr( argv[j+1] ); |
83 | j++; | 83 | j++; |
84 | } | 84 | } |
85 | } | 85 | } |
86 | } | 86 | } |
87 | } | 87 | } |
88 | else | 88 | else |
89 | { | 89 | { |
90 | int iCPos; | 90 | int iCPos; |
91 | for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) | 91 | for( iCPos = 1; argv[j][iCPos] != '\0'; iCPos++ ) |
92 | { | 92 | { |
93 | if( !hsOption.has( argv[j][iCPos] ) ) | 93 | if( !hsOption.has( argv[j][iCPos] ) ) |
94 | { | 94 | { |
95 | Bu::String sOpt("-"); | 95 | Bu::String sOpt("-"); |
96 | sOpt += argv[j][iCPos]; | 96 | sOpt += argv[j][iCPos]; |
97 | optionError( sOpt ); | 97 | optionError( sOpt ); |
98 | } | 98 | } |
99 | else | 99 | else |
100 | { | 100 | { |
101 | Option *pOpt = hsOption.get( argv[j][iCPos] ); | 101 | Option *pOpt = hsOption.get( argv[j][iCPos] ); |
102 | char buf[2] = {argv[j][iCPos], '\0'}; | 102 | char buf[2] = {argv[j][iCPos], '\0'}; |
103 | if( pOpt->sUsed ) | 103 | if( pOpt->sUsed ) |
104 | { | 104 | { |
105 | Bu::StrArray aParams( argc-j+1 ); | 105 | Bu::StrArray aParams( argc-j+1 ); |
106 | aParams.append( buf ); | 106 | aParams.append( buf ); |
107 | int iMod = 0; | 107 | int iMod = 0; |
108 | if( argv[j][iCPos+1] != '\0' ) | 108 | if( argv[j][iCPos+1] != '\0' ) |
109 | { | 109 | { |
110 | aParams.append( argv[j]+iCPos+1 ); | 110 | aParams.append( argv[j]+iCPos+1 ); |
111 | iMod = -1; | 111 | iMod = -1; |
112 | } | 112 | } |
113 | for( int k = j+1; k < argc; k++ ) | 113 | for( int k = j+1; k < argc; k++ ) |
114 | { | 114 | { |
115 | aParams.append( argv[k] ); | 115 | aParams.append( argv[k] ); |
116 | } | 116 | } |
117 | int iUsed = pOpt->sUsed( aParams ); | 117 | int iUsed = pOpt->sUsed( aParams ); |
118 | if( iUsed > 0 ) | 118 | if( iUsed > 0 ) |
119 | { | 119 | { |
120 | j += iUsed + iMod; | 120 | j += iUsed + iMod; |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | } | 123 | } |
124 | else if( pOpt->pProxy ) | 124 | else if( pOpt->pProxy ) |
125 | { | 125 | { |
126 | if( pOpt->sOverride.isSet() ) | 126 | if( pOpt->sOverride.isSet() ) |
127 | { | 127 | { |
128 | pOpt->pProxy->setValue( pOpt->sOverride ); | 128 | pOpt->pProxy->setValue( pOpt->sOverride ); |
129 | } | 129 | } |
130 | else if( argv[j][iCPos+1] != '\0' ) | 130 | else if( argv[j][iCPos+1] != '\0' ) |
131 | { | 131 | { |
132 | pOpt->pProxy->setValueFromStr( | 132 | pOpt->pProxy->setValueFromStr( |
133 | argv[j]+iCPos+1 | 133 | argv[j]+iCPos+1 |
134 | ); | 134 | ); |
135 | break; | 135 | break; |
136 | } | 136 | } |
137 | else if( argv[j+1] ) | 137 | else if( argv[j+1] ) |
138 | { | 138 | { |
139 | pOpt->pProxy->setValueFromStr( | 139 | pOpt->pProxy->setValueFromStr( |
140 | argv[j+1] | 140 | argv[j+1] |
141 | ); | 141 | ); |
142 | j++; | 142 | j++; |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | } | 146 | } |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | else | 150 | else |
151 | { | 151 | { |
152 | if( !sNonOption ) | 152 | if( !sNonOption ) |
153 | { | 153 | { |
154 | optionError( argv[j] ); | 154 | optionError( argv[j] ); |
155 | } | 155 | } |
156 | else | 156 | else |
157 | { | 157 | { |
158 | int iCount = argc-j; | 158 | int iCount = argc-j; |
159 | Bu::StrArray aParams( iCount ); | 159 | Bu::StrArray aParams( iCount ); |
160 | for( int k = j; k < argc; k++ ) | 160 | for( int k = j; k < argc; k++ ) |
161 | { | 161 | { |
162 | aParams.append( argv[k] ); | 162 | aParams.append( argv[k] ); |
163 | } | 163 | } |
164 | j += sNonOption( aParams ); | 164 | j += sNonOption( aParams ); |
165 | } | 165 | } |
166 | } | 166 | } |
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | void Bu::OptParser::parse( const Bu::String &sLine ) | 170 | void Bu::OptParser::parse( const Bu::String &sLine ) |
171 | { | 171 | { |
172 | Bu::String sCmd = sLine.clone(); | 172 | Bu::String sCmd = sLine.clone(); |
173 | int iParams = 0; | 173 | int iParams = 0; |
174 | bool bInGap = true; | 174 | bool bInGap = true; |
175 | bool bInQuote = false; | 175 | bool bInQuote = false; |
176 | for( Bu::String::iterator i = sCmd.begin(); i; i++ ) | 176 | for( Bu::String::iterator i = sCmd.begin(); i; i++ ) |
177 | { | 177 | { |
178 | if( bInQuote == false && (*i == ' ' || *i == '\t') ) | 178 | if( bInQuote == false && (*i == ' ' || *i == '\t') ) |
179 | { | 179 | { |
180 | if( bInGap == false ) | 180 | if( bInGap == false ) |
181 | { | 181 | { |
182 | bInGap = true; | 182 | bInGap = true; |
183 | } | 183 | } |
184 | } | 184 | } |
185 | else if( *i == '"' ) | 185 | else if( *i == '"' ) |
186 | { | 186 | { |
187 | bInQuote = !bInQuote; | 187 | bInQuote = !bInQuote; |
188 | } | 188 | } |
@@ -211,242 +211,242 @@ void Bu::OptParser::parse( const Bu::String &sLine ) | |||
211 | } | 211 | } |
212 | } | 212 | } |
213 | else if( *i == '"' ) | 213 | else if( *i == '"' ) |
214 | { | 214 | { |
215 | bInQuote = !bInQuote; | 215 | bInQuote = !bInQuote; |
216 | } | 216 | } |
217 | else | 217 | else |
218 | { | 218 | { |
219 | if( bInGap ) | 219 | if( bInGap ) |
220 | { | 220 | { |
221 | asParam[iParams++] = i; | 221 | asParam[iParams++] = i; |
222 | bInGap = false; | 222 | bInGap = false; |
223 | } | 223 | } |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | parse( iParams, asParam ); | 227 | parse( iParams, asParam ); |
228 | 228 | ||
229 | delete[] asParam; | 229 | delete[] asParam; |
230 | } | 230 | } |
231 | 231 | ||
232 | void Bu::OptParser::addOption( const Option &opt ) | 232 | void Bu::OptParser::addOption( const Option &opt ) |
233 | { | 233 | { |
234 | lOption.append( opt ); | 234 | lOption.append( opt ); |
235 | if( opt.cOpt != '\0' ) | 235 | if( opt.cOpt != '\0' ) |
236 | hsOption.insert( opt.cOpt, &lOption.last() ); | 236 | hsOption.insert( opt.cOpt, &lOption.last() ); |
237 | if( opt.sOpt.isSet() ) | 237 | if( opt.sOpt.isSet() ) |
238 | hlOption.insert( opt.sOpt, &lOption.last() ); | 238 | hlOption.insert( opt.sOpt, &lOption.last() ); |
239 | } | 239 | } |
240 | 240 | ||
241 | void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) | 241 | void Bu::OptParser::setOverride( char cOpt, const Bu::Variant &sOverride ) |
242 | { | 242 | { |
243 | hsOption.get( cOpt )->sOverride = sOverride; | 243 | hsOption.get( cOpt )->sOverride = sOverride; |
244 | } | 244 | } |
245 | 245 | ||
246 | void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) | 246 | void Bu::OptParser::setOverride( const Bu::String &sOpt, const Bu::Variant &sOverride ) |
247 | { | 247 | { |
248 | hlOption.get( sOpt )->sOverride = sOverride; | 248 | hlOption.get( sOpt )->sOverride = sOverride; |
249 | } | 249 | } |
250 | 250 | ||
251 | void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) | 251 | void Bu::OptParser::setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ) |
252 | { | 252 | { |
253 | hlOption.get( sOpt )->sHelpDefault = sTxt; | 253 | hlOption.get( sOpt )->sHelpDefault = sTxt; |
254 | } | 254 | } |
255 | 255 | ||
256 | void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) | 256 | void Bu::OptParser::addHelpOption( char c, const Bu::String &s, const Bu::String &sHelp ) |
257 | { | 257 | { |
258 | Option o; | 258 | Option o; |
259 | o.sUsed = slot( this, &OptParser::optHelp ); | 259 | o.sUsed = slot( this, &OptParser::optHelp ); |
260 | o.cOpt = c; | 260 | o.cOpt = c; |
261 | o.sOpt = s; | 261 | o.sOpt = s; |
262 | o.sHelp = sHelp; | 262 | o.sHelp = sHelp; |
263 | addOption( o ); | 263 | addOption( o ); |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) | 266 | void Bu::OptParser::addHelpBanner( const Bu::String &sText, bool bFormatted ) |
267 | { | 267 | { |
268 | Banner b; | 268 | Banner b; |
269 | b.sText = sText; | 269 | b.sText = sText; |
270 | b.bFormatted = bFormatted; | 270 | b.bFormatted = bFormatted; |
271 | if( lOption.getSize() > 0 ) | 271 | if( lOption.getSize() > 0 ) |
272 | { | 272 | { |
273 | for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } | 273 | for( b.iAfter = lOption.begin(); b.iAfter+1; b.iAfter++ ) { } |
274 | } | 274 | } |
275 | lBanner.append( b ); | 275 | lBanner.append( b ); |
276 | } | 276 | } |
277 | 277 | ||
278 | int Bu::OptParser::optHelp( StrArray /*aParams*/ ) | 278 | int Bu::OptParser::optHelp( StrArray /*aParams*/ ) |
279 | { | 279 | { |
280 | bool bHasShort = false; | 280 | bool bHasShort = false; |
281 | int iMaxWidth = 0; | 281 | int iMaxWidth = 0; |
282 | int iScrWidth = 80; | 282 | int iScrWidth = 80; |
283 | char *env = getenv("COLUMNS"); | 283 | char *env = getenv("COLUMNS"); |
284 | if( env ) | 284 | if( env ) |
285 | iScrWidth = strtol( env, NULL, 10 ); | 285 | iScrWidth = strtol( env, NULL, 10 ); |
286 | for( OptionList::iterator i = lOption.begin(); i; i++ ) | 286 | for( OptionList::iterator i = lOption.begin(); i; i++ ) |
287 | { | 287 | { |
288 | if( (*i).cOpt != '\0' ) | 288 | if( (*i).cOpt != '\0' ) |
289 | bHasShort = true; | 289 | bHasShort = true; |
290 | int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); | 290 | int lOptSize = (*i).sOpt.getSize() + (*i).sHelpDefault.getSize(); |
291 | if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) | 291 | if( (*i).sOpt.isSet() && iMaxWidth < lOptSize ) |
292 | iMaxWidth = lOptSize; | 292 | iMaxWidth = lOptSize; |
293 | } | 293 | } |
294 | int iIndent = 4; | 294 | int iIndent = 4; |
295 | if( bHasShort ) | 295 | if( bHasShort ) |
296 | iIndent += 4; | 296 | iIndent += 4; |
297 | if( iMaxWidth > 0 ) | 297 | if( iMaxWidth > 0 ) |
298 | iIndent += 4 + iMaxWidth; | 298 | iIndent += 4 + iMaxWidth; |
299 | 299 | ||
300 | BannerList::iterator iBanner; | 300 | BannerList::iterator iBanner; |
301 | for( iBanner = lBanner.begin(); iBanner; iBanner++ ) | 301 | for( iBanner = lBanner.begin(); iBanner; iBanner++ ) |
302 | { | 302 | { |
303 | if( (*iBanner).iAfter ) | 303 | if( (*iBanner).iAfter ) |
304 | break; | 304 | break; |
305 | 305 | ||
306 | if( (*iBanner).bFormatted ) | 306 | if( (*iBanner).bFormatted ) |
307 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); | 307 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); |
308 | else | 308 | else |
309 | sio << (*iBanner).sText; | 309 | sio << (*iBanner).sText; |
310 | sio << sio.nl; | 310 | sio << sio.nl; |
311 | } | 311 | } |
312 | for( OptionList::iterator i = lOption.begin(); i; i++ ) | 312 | for( OptionList::iterator i = lOption.begin(); i; i++ ) |
313 | { | 313 | { |
314 | sio << " "; | 314 | sio << " "; |
315 | if( bHasShort ) | 315 | if( bHasShort ) |
316 | { | 316 | { |
317 | if( (*i).cOpt == '\0' ) | 317 | if( (*i).cOpt == '\0' ) |
318 | sio << " "; | 318 | sio << " "; |
319 | else | 319 | else |
320 | sio << "-" << (*i).cOpt; | 320 | sio << "-" << (*i).cOpt; |
321 | sio << " "; | 321 | sio << " "; |
322 | } | 322 | } |
323 | if( iMaxWidth > 0 ) | 323 | if( iMaxWidth > 0 ) |
324 | { | 324 | { |
325 | if( (*i).sOpt.isSet() ) | 325 | if( (*i).sOpt.isSet() ) |
326 | { | 326 | { |
327 | sio << "--" << Fmt(iMaxWidth, Fmt::Left) | 327 | sio << "--" << Fmt(iMaxWidth, Fmt::Left) |
328 | << (*i).sOpt + (*i).sHelpDefault; | 328 | << (*i).sOpt + (*i).sHelpDefault; |
329 | } | 329 | } |
330 | else | 330 | else |
331 | { | 331 | { |
332 | sio << " " << Fmt(iMaxWidth) << ""; | 332 | sio << " " << Fmt(iMaxWidth) << ""; |
333 | } | 333 | } |
334 | sio << " "; | 334 | sio << " "; |
335 | } | 335 | } |
336 | sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); | 336 | sio << format( (*i).sHelp, iScrWidth-iIndent-1, iIndent ); |
337 | sio << sio.nl; | 337 | sio << sio.nl; |
338 | 338 | ||
339 | for( ; iBanner; iBanner++ ) | 339 | for( ; iBanner; iBanner++ ) |
340 | { | 340 | { |
341 | if( (*iBanner).iAfter != i ) | 341 | if( (*iBanner).iAfter != i ) |
342 | break; | 342 | break; |
343 | 343 | ||
344 | if( (*iBanner).bFormatted ) | 344 | if( (*iBanner).bFormatted ) |
345 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); | 345 | sio << format( (*iBanner).sText, iScrWidth-1, 0 ); |
346 | else | 346 | else |
347 | sio << (*iBanner).sText; | 347 | sio << (*iBanner).sText; |
348 | sio << sio.nl; | 348 | sio << sio.nl; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | exit( 0 ); | 351 | exit( 0 ); |
352 | return 0; | 352 | return 0; |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::OptParser::optionError( const Bu::String &sOption ) | 355 | void Bu::OptParser::optionError( const Bu::String &sOption ) |
356 | { | 356 | { |
357 | sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; | 357 | sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl; |
358 | exit( 1 ); | 358 | exit( 1 ); |
359 | } | 359 | } |
360 | 360 | ||
361 | void Bu::OptParser::setNonOption( OptionSignal sSignal ) | 361 | void Bu::OptParser::setNonOption( OptionSignal sSignal ) |
362 | { | 362 | { |
363 | sNonOption = sSignal; | 363 | sNonOption = sSignal; |
364 | } | 364 | } |
365 | 365 | ||
366 | Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, | 366 | Bu::String Bu::OptParser::format( const Bu::String &sIn, int iWidth, |
367 | int iIndent ) | 367 | int iIndent ) |
368 | { | 368 | { |
369 | Bu::String sOut; | 369 | Bu::String sOut; |
370 | Bu::String sIndent; | 370 | Bu::String sIndent; |
371 | for( int j = 0; j < iIndent; j++ ) | 371 | for( int j = 0; j < iIndent; j++ ) |
372 | sIndent.append(" ", 1); | 372 | sIndent.append(" ", 1); |
373 | bool bFirst = true; | 373 | bool bFirst = true; |
374 | int iSpaceCount = 0; | 374 | int iSpaceCount = 0; |
375 | bool bSpace = false; | 375 | bool bSpace = false; |
376 | int iPrevLineLen; | 376 | int iPrevLineLen; |
377 | int iLineLen = 0; | 377 | int iLineLen = 0; |
378 | Bu::String::const_iterator iLastSpace, iStart; | 378 | Bu::String::const_iterator iLastSpace, iStart; |
379 | for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) | 379 | for( Bu::String::const_iterator i = iLastSpace = iStart = sIn.begin(); i; i++ ) |
380 | { | 380 | { |
381 | if( *i == ' ' ) | 381 | if( *i == ' ' ) |
382 | { | 382 | { |
383 | if( bSpace == false ) | 383 | if( bSpace == false ) |
384 | { | 384 | { |
385 | iLastSpace = i; | 385 | iLastSpace = i; |
386 | iSpaceCount++; | 386 | iSpaceCount++; |
387 | bSpace = true; | 387 | bSpace = true; |
388 | iPrevLineLen = iLineLen; | 388 | iPrevLineLen = iLineLen; |
389 | } | 389 | } |
390 | } | 390 | } |
391 | else | 391 | else |
392 | { | 392 | { |
393 | bSpace = false; | 393 | bSpace = false; |
394 | } | 394 | } |
395 | iLineLen++; | 395 | iLineLen++; |
396 | 396 | ||
397 | if( iLineLen >= iWidth ) | 397 | if( iLineLen >= iWidth ) |
398 | { | 398 | { |
399 | iSpaceCount--; | 399 | iSpaceCount--; |
400 | if( bFirst == true ) | 400 | if( bFirst == true ) |
401 | bFirst = false; | 401 | bFirst = false; |
402 | else | 402 | else |
403 | sOut += sIndent; | 403 | sOut += sIndent; |
404 | int iExtraSpaces = iWidth-iPrevLineLen; | 404 | int iExtraSpaces = iWidth-iPrevLineLen; |
405 | bSpace = false; | 405 | bSpace = false; |
406 | float fFill = 0.0; | 406 | float fFill = 0.0; |
407 | int iSubSpaceCount = 0; | 407 | int iSubSpaceCount = 0; |
408 | float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); | 408 | float fAdd = ((float)iExtraSpaces/(float)iSpaceCount); |
409 | for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) | 409 | for( Bu::String::const_iterator k = iStart; k != iLastSpace; k++ ) |
410 | { | 410 | { |
411 | sOut += *k; | 411 | sOut += *k; |
412 | if( *k == ' ' ) | 412 | if( *k == ' ' ) |
413 | { | 413 | { |
414 | if( bSpace == false && iExtraSpaces > 0 ) | 414 | if( bSpace == false && iExtraSpaces > 0 ) |
415 | { | 415 | { |
416 | bSpace = true; | 416 | bSpace = true; |
417 | fFill += fAdd; | 417 | fFill += fAdd; |
418 | iSubSpaceCount++; | 418 | iSubSpaceCount++; |
419 | for( int sp = 0; sp < (int)(fFill); sp++ ) | 419 | for( int sp = 0; sp < (int)(fFill); sp++ ) |
420 | { | 420 | { |
421 | sOut += ' '; | 421 | sOut += ' '; |
422 | iExtraSpaces--; | 422 | iExtraSpaces--; |
423 | } | 423 | } |
424 | fFill -= (int)fFill; | 424 | fFill -= (int)fFill; |
425 | if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) | 425 | if( iSubSpaceCount == iSpaceCount && iExtraSpaces > 0 ) |
426 | { | 426 | { |
427 | for(; iExtraSpaces > 0; iExtraSpaces-- ) | 427 | for(; iExtraSpaces > 0; iExtraSpaces-- ) |
428 | { | 428 | { |
429 | sOut += ' '; | 429 | sOut += ' '; |
430 | } | 430 | } |
431 | } | 431 | } |
432 | } | 432 | } |
433 | } | 433 | } |
434 | else | 434 | else |
435 | bSpace = false; | 435 | bSpace = false; |
436 | } | 436 | } |
437 | //sOut.append( iStart, iLastSpace ); | 437 | //sOut.append( iStart, iLastSpace ); |
438 | sOut.append("\n"); | 438 | sOut.append("\n"); |
439 | for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } | 439 | for(; iLastSpace && *iLastSpace == ' '; iLastSpace++ ) { } |
440 | iStart = i = iLastSpace; | 440 | iStart = i = iLastSpace; |
441 | bSpace = false; | 441 | bSpace = false; |
442 | iLineLen = 1; | 442 | iLineLen = 1; |
443 | iSpaceCount = 0; | 443 | iSpaceCount = 0; |
444 | } | 444 | } |
445 | } | 445 | } |
446 | if( !bFirst ) | 446 | if( !bFirst ) |
447 | sOut += sIndent; | 447 | sOut += sIndent; |
448 | sOut.append( iStart ); | 448 | sOut.append( iStart ); |
449 | return sOut; | 449 | return sOut; |
450 | } | 450 | } |
451 | 451 | ||
452 | 452 | ||
@@ -467,26 +467,26 @@ Bu::OptParser::_ValueProxy::~_ValueProxy() | |||
467 | // | 467 | // |
468 | 468 | ||
469 | Bu::OptParser::Option::Option() : | 469 | Bu::OptParser::Option::Option() : |
470 | cOpt( '\0' ), | 470 | cOpt( '\0' ), |
471 | pProxy( NULL ) | 471 | pProxy( NULL ) |
472 | { | 472 | { |
473 | } | 473 | } |
474 | 474 | ||
475 | Bu::OptParser::Option::Option( const Option &rSrc ) : | 475 | Bu::OptParser::Option::Option( const Option &rSrc ) : |
476 | cOpt( rSrc.cOpt ), | 476 | cOpt( rSrc.cOpt ), |
477 | sOpt( rSrc.sOpt ), | 477 | sOpt( rSrc.sOpt ), |
478 | sHelp( rSrc.sHelp ), | 478 | sHelp( rSrc.sHelp ), |
479 | sUsed( rSrc.sUsed ), | 479 | sUsed( rSrc.sUsed ), |
480 | pProxy( NULL ), | 480 | pProxy( NULL ), |
481 | sOverride( rSrc.sOverride ) | 481 | sOverride( rSrc.sOverride ) |
482 | { | 482 | { |
483 | if( rSrc.pProxy ) | 483 | if( rSrc.pProxy ) |
484 | pProxy = rSrc.pProxy->clone(); | 484 | pProxy = rSrc.pProxy->clone(); |
485 | } | 485 | } |
486 | 486 | ||
487 | Bu::OptParser::Option::~Option() | 487 | Bu::OptParser::Option::~Option() |
488 | { | 488 | { |
489 | delete pProxy; | 489 | delete pProxy; |
490 | pProxy = NULL; | 490 | pProxy = NULL; |
491 | } | 491 | } |
492 | 492 | ||
diff --git a/src/stable/optparser.h b/src/stable/optparser.h index 2da93c9..412f262 100644 --- a/src/stable/optparser.h +++ b/src/stable/optparser.h | |||
@@ -19,205 +19,205 @@ | |||
19 | 19 | ||
20 | namespace Bu | 20 | namespace Bu |
21 | { | 21 | { |
22 | typedef Bu::Array<Bu::String> StrArray; | 22 | typedef Bu::Array<Bu::String> StrArray; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * POSIX/Gnu style command line parser. Handles long and short options in | 25 | * POSIX/Gnu style command line parser. Handles long and short options in |
26 | * a variety of fun and useful ways, along with singal based callbacks and | 26 | * a variety of fun and useful ways, along with singal based callbacks and |
27 | * automatic variable setting. It's pretty easy to use, and very flexible. | 27 | * automatic variable setting. It's pretty easy to use, and very flexible. |
28 | * | 28 | * |
29 | * OptParser supports it's own builtin help mechanism which automatically | 29 | * OptParser supports it's own builtin help mechanism which automatically |
30 | * enumerates the available options and their help in a well formatted and | 30 | * enumerates the available options and their help in a well formatted and |
31 | * easy to read way, automatically formatting your help text per option and | 31 | * easy to read way, automatically formatting your help text per option and |
32 | * allows for addition "help banners" which can be placed wherever you | 32 | * allows for addition "help banners" which can be placed wherever you |
33 | * would like. | 33 | * would like. |
34 | */ | 34 | */ |
35 | class OptParser | 35 | class OptParser |
36 | { | 36 | { |
37 | private: | 37 | private: |
38 | class _ValueProxy | 38 | class _ValueProxy |
39 | { | 39 | { |
40 | public: | 40 | public: |
41 | _ValueProxy(); | 41 | _ValueProxy(); |
42 | virtual ~_ValueProxy(); | 42 | virtual ~_ValueProxy(); |
43 | 43 | ||
44 | virtual void setValueFromStr( const Bu::String & )=0; | 44 | virtual void setValueFromStr( const Bu::String & )=0; |
45 | virtual void setValue( const Bu::Variant &vVar )=0; | 45 | virtual void setValue( const Bu::Variant &vVar )=0; |
46 | virtual _ValueProxy *clone()=0; | 46 | virtual _ValueProxy *clone()=0; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | template<typename ptype> | 49 | template<typename ptype> |
50 | class ValueProxy : public _ValueProxy | 50 | class ValueProxy : public _ValueProxy |
51 | { | 51 | { |
52 | public: | 52 | public: |
53 | ValueProxy( ptype &v ) : | 53 | ValueProxy( ptype &v ) : |
54 | v( v ) | 54 | v( v ) |
55 | { | 55 | { |
56 | } | 56 | } |
57 | 57 | ||
58 | virtual ~ValueProxy() | 58 | virtual ~ValueProxy() |
59 | { | 59 | { |
60 | } | 60 | } |
61 | 61 | ||
62 | virtual void setValueFromStr( const Bu::String &sVal ) | 62 | virtual void setValueFromStr( const Bu::String &sVal ) |
63 | { | 63 | { |
64 | Bu::MemBuf mb( sVal ); | 64 | Bu::MemBuf mb( sVal ); |
65 | Bu::Formatter f( mb ); | 65 | Bu::Formatter f( mb ); |
66 | f << Bu::Fmt().tokenize( false ); | 66 | f << Bu::Fmt().tokenize( false ); |
67 | f >> v; | 67 | f >> v; |
68 | } | 68 | } |
69 | 69 | ||
70 | virtual void setValue( const Bu::Variant &vVar ) | 70 | virtual void setValue( const Bu::Variant &vVar ) |
71 | { | 71 | { |
72 | if( vVar.getType() == typeid(ptype) ) | 72 | if( vVar.getType() == typeid(ptype) ) |
73 | { | 73 | { |
74 | v = vVar.get<ptype>(); | 74 | v = vVar.get<ptype>(); |
75 | } | 75 | } |
76 | else if( vVar.getType() == typeid(Bu::String) ) | 76 | else if( vVar.getType() == typeid(Bu::String) ) |
77 | { | 77 | { |
78 | setValueFromStr( vVar.get<Bu::String>() ); | 78 | setValueFromStr( vVar.get<Bu::String>() ); |
79 | } | 79 | } |
80 | else | 80 | else |
81 | { | 81 | { |
82 | Bu::MemBuf mb; | 82 | Bu::MemBuf mb; |
83 | Bu::Formatter f( mb ); | 83 | Bu::Formatter f( mb ); |
84 | // f << vVar; | 84 | // f << vVar; |
85 | setValueFromStr( mb.getString() ); | 85 | setValueFromStr( mb.getString() ); |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | virtual _ValueProxy *clone() | 89 | virtual _ValueProxy *clone() |
90 | { | 90 | { |
91 | return new ValueProxy<ptype>( v ); | 91 | return new ValueProxy<ptype>( v ); |
92 | } | 92 | } |
93 | 93 | ||
94 | private: | 94 | private: |
95 | ptype &v; | 95 | ptype &v; |
96 | }; | 96 | }; |
97 | 97 | ||
98 | public: | 98 | public: |
99 | typedef Signal1<int, StrArray> OptionSignal; | 99 | typedef Signal1<int, StrArray> OptionSignal; |
100 | class Option | 100 | class Option |
101 | { | 101 | { |
102 | public: | 102 | public: |
103 | Option(); | 103 | Option(); |
104 | Option( const Option &rSrc ); | 104 | Option( const Option &rSrc ); |
105 | virtual ~Option(); | 105 | virtual ~Option(); |
106 | 106 | ||
107 | char cOpt; | 107 | char cOpt; |
108 | Bu::String sOpt; | 108 | Bu::String sOpt; |
109 | Bu::String sHelp; | 109 | Bu::String sHelp; |
110 | OptionSignal sUsed; | 110 | OptionSignal sUsed; |
111 | _ValueProxy *pProxy; | 111 | _ValueProxy *pProxy; |
112 | Bu::Variant sOverride; | 112 | Bu::Variant sOverride; |
113 | Bu::String sHelpDefault; | 113 | Bu::String sHelpDefault; |
114 | }; | 114 | }; |
115 | 115 | ||
116 | private: | 116 | private: |
117 | typedef Bu::List<Option> OptionList; | 117 | typedef Bu::List<Option> OptionList; |
118 | typedef Bu::Hash<char, Option *> ShortOptionHash; | 118 | typedef Bu::Hash<char, Option *> ShortOptionHash; |
119 | typedef Bu::Hash<Bu::String, Option *> LongOptionHash; | 119 | typedef Bu::Hash<Bu::String, Option *> LongOptionHash; |
120 | 120 | ||
121 | class Banner | 121 | class Banner |
122 | { | 122 | { |
123 | public: | 123 | public: |
124 | Bu::String sText; | 124 | Bu::String sText; |
125 | bool bFormatted; | 125 | bool bFormatted; |
126 | OptionList::const_iterator iAfter; | 126 | OptionList::const_iterator iAfter; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | typedef Bu::List<Banner> BannerList; | 129 | typedef Bu::List<Banner> BannerList; |
130 | 130 | ||
131 | public: | 131 | public: |
132 | OptParser(); | 132 | OptParser(); |
133 | virtual ~OptParser(); | 133 | virtual ~OptParser(); |
134 | 134 | ||
135 | void parse( int argc, char **argv ); | 135 | void parse( int argc, char **argv ); |
136 | void parse( const Bu::String &sLine ); | 136 | void parse( const Bu::String &sLine ); |
137 | 137 | ||
138 | void addOption( const Option &opt ); | 138 | void addOption( const Option &opt ); |
139 | 139 | ||
140 | template<typename vtype> | 140 | template<typename vtype> |
141 | void addOption( vtype &var, char cOpt, const Bu::String &sOpt, | 141 | void addOption( vtype &var, char cOpt, const Bu::String &sOpt, |
142 | const Bu::String &sHelp ) | 142 | const Bu::String &sHelp ) |
143 | { | 143 | { |
144 | Option o; | 144 | Option o; |
145 | o.cOpt = cOpt; | 145 | o.cOpt = cOpt; |
146 | o.sOpt = sOpt; | 146 | o.sOpt = sOpt; |
147 | o.pProxy = new ValueProxy<vtype>( var ); | 147 | o.pProxy = new ValueProxy<vtype>( var ); |
148 | o.sHelp = sHelp; | 148 | o.sHelp = sHelp; |
149 | addOption( o ); | 149 | addOption( o ); |
150 | } | 150 | } |
151 | 151 | ||
152 | template<typename vtype> | 152 | template<typename vtype> |
153 | void addOption( vtype &var, const Bu::String &sOpt, | 153 | void addOption( vtype &var, const Bu::String &sOpt, |
154 | const Bu::String &sHelp ) | 154 | const Bu::String &sHelp ) |
155 | { | 155 | { |
156 | addOption( var, '\0', sOpt, sHelp ); | 156 | addOption( var, '\0', sOpt, sHelp ); |
157 | } | 157 | } |
158 | 158 | ||
159 | template<typename vtype> | 159 | template<typename vtype> |
160 | void addOption( vtype &var, char cOpt, const Bu::String &sHelp ) | 160 | void addOption( vtype &var, char cOpt, const Bu::String &sHelp ) |
161 | { | 161 | { |
162 | addOption( var, cOpt, "", sHelp ); | 162 | addOption( var, cOpt, "", sHelp ); |
163 | } | 163 | } |
164 | 164 | ||
165 | void addOption( OptionSignal sUsed, char cOpt, const Bu::String &sOpt, | 165 | void addOption( OptionSignal sUsed, char cOpt, const Bu::String &sOpt, |
166 | const Bu::String &sHelp ) | 166 | const Bu::String &sHelp ) |
167 | { | 167 | { |
168 | Option o; | 168 | Option o; |
169 | o.cOpt = cOpt; | 169 | o.cOpt = cOpt; |
170 | o.sOpt = sOpt; | 170 | o.sOpt = sOpt; |
171 | o.sUsed = sUsed; | 171 | o.sUsed = sUsed; |
172 | o.sHelp = sHelp; | 172 | o.sHelp = sHelp; |
173 | addOption( o ); | 173 | addOption( o ); |
174 | } | 174 | } |
175 | 175 | ||
176 | void addOption( OptionSignal sUsed, const Bu::String &sOpt, | 176 | void addOption( OptionSignal sUsed, const Bu::String &sOpt, |
177 | const Bu::String &sHelp ) | 177 | const Bu::String &sHelp ) |
178 | { | 178 | { |
179 | addOption( sUsed, '\0', sOpt, sHelp ); | 179 | addOption( sUsed, '\0', sOpt, sHelp ); |
180 | } | 180 | } |
181 | 181 | ||
182 | void addOption( OptionSignal sUsed, char cOpt, | 182 | void addOption( OptionSignal sUsed, char cOpt, |
183 | const Bu::String &sHelp ) | 183 | const Bu::String &sHelp ) |
184 | { | 184 | { |
185 | addOption( sUsed, cOpt, "", sHelp ); | 185 | addOption( sUsed, cOpt, "", sHelp ); |
186 | } | 186 | } |
187 | 187 | ||
188 | void setOverride( char cOpt, const Bu::Variant &sOverride ); | 188 | void setOverride( char cOpt, const Bu::Variant &sOverride ); |
189 | void setOverride( const Bu::String &sOpt, | 189 | void setOverride( const Bu::String &sOpt, |
190 | const Bu::Variant &sOverride ); | 190 | const Bu::Variant &sOverride ); |
191 | 191 | ||
192 | void setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ); | 192 | void setHelpDefault( const Bu::String &sOpt, const Bu::String &sTxt ); |
193 | 193 | ||
194 | void addHelpOption( char c='h', const Bu::String &s="help", | 194 | void addHelpOption( char c='h', const Bu::String &s="help", |
195 | const Bu::String &sHelp="This help." ); | 195 | const Bu::String &sHelp="This help." ); |
196 | void addHelpBanner( const Bu::String &sText, bool bFormatted=true ); | 196 | void addHelpBanner( const Bu::String &sText, bool bFormatted=true ); |
197 | 197 | ||
198 | int optHelp( StrArray aParams ); | 198 | int optHelp( StrArray aParams ); |
199 | 199 | ||
200 | /** | 200 | /** |
201 | * This function is called when an unrecognized option is found, the | 201 | * This function is called when an unrecognized option is found, the |
202 | * default behaviour is to print an error to stdout and exit( 1 ), if | 202 | * default behaviour is to print an error to stdout and exit( 1 ), if |
203 | * you want to do something different, just override this function. | 203 | * you want to do something different, just override this function. |
204 | * This is also called by default when something is found that hasn't | 204 | * This is also called by default when something is found that hasn't |
205 | * been handled by an option, and isn't an option (starts with - or --). | 205 | * been handled by an option, and isn't an option (starts with - or --). |
206 | * To change this behaviour call | 206 | * To change this behaviour call |
207 | */ | 207 | */ |
208 | virtual void optionError( const Bu::String &sOption ); | 208 | virtual void optionError( const Bu::String &sOption ); |
209 | 209 | ||
210 | void setNonOption( OptionSignal sSignal ); | 210 | void setNonOption( OptionSignal sSignal ); |
211 | 211 | ||
212 | private: | 212 | private: |
213 | Bu::String format( const Bu::String &sIn, int iWidth, int iIndent ); | 213 | Bu::String format( const Bu::String &sIn, int iWidth, int iIndent ); |
214 | 214 | ||
215 | OptionList lOption; | 215 | OptionList lOption; |
216 | ShortOptionHash hsOption; | 216 | ShortOptionHash hsOption; |
217 | LongOptionHash hlOption; | 217 | LongOptionHash hlOption; |
218 | BannerList lBanner; | 218 | BannerList lBanner; |
219 | OptionSignal sNonOption; | 219 | OptionSignal sNonOption; |
220 | }; | 220 | }; |
221 | }; | 221 | }; |
222 | 222 | ||
223 | #endif | 223 | #endif |
diff --git a/src/stable/pearsonhash.cpp b/src/stable/pearsonhash.cpp index d4e82df..6f58470 100644 --- a/src/stable/pearsonhash.cpp +++ b/src/stable/pearsonhash.cpp | |||
@@ -9,28 +9,28 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | uint8_t Bu::PearsonHash::aSBox[] = { | 11 | uint8_t Bu::PearsonHash::aSBox[] = { |
12 | 251, 175, 119, 215, 81, 14, 79, 191, 103, 49, 181, 143, 186, 157, 0, | 12 | 251, 175, 119, 215, 81, 14, 79, 191, 103, 49, 181, 143, 186, 157, 0, |
13 | 232, 31, 32, 55, 60, 152, 58, 17, 237, 174, 70, 160, 144, 220, 90, 57, | 13 | 232, 31, 32, 55, 60, 152, 58, 17, 237, 174, 70, 160, 144, 220, 90, 57, |
14 | 223, 59, 3, 18, 140, 111, 166, 203, 196, 134, 243, 124, 95, 222, 179, | 14 | 223, 59, 3, 18, 140, 111, 166, 203, 196, 134, 243, 124, 95, 222, 179, |
15 | 197, 65, 180, 48, 36, 15, 107, 46, 233, 130, 165, 30, 123, 161, 209, 23, | 15 | 197, 65, 180, 48, 36, 15, 107, 46, 233, 130, 165, 30, 123, 161, 209, 23, |
16 | 97, 16, 40, 91, 219, 61, 100, 10, 210, 109, 250, 127, 22, 138, 29, 108, | 16 | 97, 16, 40, 91, 219, 61, 100, 10, 210, 109, 250, 127, 22, 138, 29, 108, |
17 | 244, 67, 207, 9, 178, 204, 74, 98, 126, 249, 167, 116, 34, 77, 193, | 17 | 244, 67, 207, 9, 178, 204, 74, 98, 126, 249, 167, 116, 34, 77, 193, |
18 | 200, 121, 5, 20, 113, 71, 35, 128, 13, 182, 94, 25, 226, 227, 199, 75, | 18 | 200, 121, 5, 20, 113, 71, 35, 128, 13, 182, 94, 25, 226, 227, 199, 75, |
19 | 27, 41, 245, 230, 224, 43, 225, 177, 26, 155, 150, 212, 142, 218, 115, | 19 | 27, 41, 245, 230, 224, 43, 225, 177, 26, 155, 150, 212, 142, 218, 115, |
20 | 241, 73, 88, 105, 39, 114, 62, 255, 192, 201, 145, 214, 168, 158, 221, | 20 | 241, 73, 88, 105, 39, 114, 62, 255, 192, 201, 145, 214, 168, 158, 221, |
21 | 148, 154, 122, 12, 84, 82, 163, 44, 139, 228, 236, 205, 242, 217, 11, | 21 | 148, 154, 122, 12, 84, 82, 163, 44, 139, 228, 236, 205, 242, 217, 11, |
22 | 187, 146, 159, 64, 86, 239, 195, 42, 106, 198, 118, 112, 184, 172, 87, | 22 | 187, 146, 159, 64, 86, 239, 195, 42, 106, 198, 118, 112, 184, 172, 87, |
23 | 2, 173, 117, 176, 229, 247, 253, 137, 185, 99, 164, 102, 147, 45, 66, | 23 | 2, 173, 117, 176, 229, 247, 253, 137, 185, 99, 164, 102, 147, 45, 66, |
24 | 231, 52, 141, 211, 194, 206, 246, 238, 56, 110, 78, 248, 63, 240, 189, | 24 | 231, 52, 141, 211, 194, 206, 246, 238, 56, 110, 78, 248, 63, 240, 189, |
25 | 93, 92, 51, 53, 183, 19, 171, 72, 50, 33, 104, 101, 69, 8, 252, 83, 120, | 25 | 93, 92, 51, 53, 183, 19, 171, 72, 50, 33, 104, 101, 69, 8, 252, 83, 120, |
26 | 76, 135, 85, 54, 202, 125, 188, 213, 96, 235, 136, 208, 162, 129, 190, | 26 | 76, 135, 85, 54, 202, 125, 188, 213, 96, 235, 136, 208, 162, 129, 190, |
27 | 132, 156, 38, 47, 1, 7, 254, 24, 4, 216, 131, 89, 21, 28, 133, 37, 153, | 27 | 132, 156, 38, 47, 1, 7, 254, 24, 4, 216, 131, 89, 21, 28, 133, 37, 153, |
28 | 149, 80, 170, 68, 6, 169, 234, 151 | 28 | 149, 80, 170, 68, 6, 169, 234, 151 |
29 | }; | 29 | }; |
30 | 30 | ||
31 | Bu::PearsonHash::PearsonHash() | 31 | Bu::PearsonHash::PearsonHash() |
32 | { | 32 | { |
33 | reset(); | 33 | reset(); |
34 | } | 34 | } |
35 | 35 | ||
36 | Bu::PearsonHash::~PearsonHash() | 36 | Bu::PearsonHash::~PearsonHash() |
@@ -39,7 +39,7 @@ Bu::PearsonHash::~PearsonHash() | |||
39 | 39 | ||
40 | void Bu::PearsonHash::reset() | 40 | void Bu::PearsonHash::reset() |
41 | { | 41 | { |
42 | iValue = 0; | 42 | iValue = 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) | 45 | void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -48,19 +48,19 @@ void Bu::PearsonHash::setSalt( const Bu::String & /*sSalt*/ ) | |||
48 | 48 | ||
49 | void Bu::PearsonHash::addData( const void *sData, int iSize ) | 49 | void Bu::PearsonHash::addData( const void *sData, int iSize ) |
50 | { | 50 | { |
51 | for( int j = 0; j < iSize; j++ ) | 51 | for( int j = 0; j < iSize; j++ ) |
52 | { | 52 | { |
53 | iValue = aSBox[ iValue^((unsigned char *)sData)[j] ]; | 53 | iValue = aSBox[ iValue^((unsigned char *)sData)[j] ]; |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::String Bu::PearsonHash::getResult() | 57 | Bu::String Bu::PearsonHash::getResult() |
58 | { | 58 | { |
59 | return Bu::String((char)iValue); | 59 | return Bu::String((char)iValue); |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::PearsonHash::writeResult( Stream &sOut ) | 62 | void Bu::PearsonHash::writeResult( Stream &sOut ) |
63 | { | 63 | { |
64 | sOut.write( &iValue, 1 ); | 64 | sOut.write( &iValue, 1 ); |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/src/stable/pearsonhash.h b/src/stable/pearsonhash.h index ca377c1..ece1d40 100644 --- a/src/stable/pearsonhash.h +++ b/src/stable/pearsonhash.h | |||
@@ -12,35 +12,35 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A pearson hash is a non-cryptographically secure hashing function that | 16 | * A pearson hash is a non-cryptographically secure hashing function that |
17 | * is very light on resources, very fast, and produces a single byte | 17 | * is very light on resources, very fast, and produces a single byte |
18 | * as it's output. It is strongly dependant on every byte in the input, | 18 | * as it's output. It is strongly dependant on every byte in the input, |
19 | * which means that it's a good choice for adding to short messages to | 19 | * which means that it's a good choice for adding to short messages to |
20 | * ensure that the contents of the messages are unchanged. | 20 | * ensure that the contents of the messages are unchanged. |
21 | * | 21 | * |
22 | * Pearson hash is named for it's inventor Peter K. Pearson who described | 22 | * Pearson hash is named for it's inventor Peter K. Pearson who described |
23 | * it in his article "Fast hashing of variable-length text strings" | 23 | * it in his article "Fast hashing of variable-length text strings" |
24 | * published in 1990 by ACM. I haven't read it, because you have to pay to | 24 | * published in 1990 by ACM. I haven't read it, because you have to pay to |
25 | * get a copy :-P | 25 | * get a copy :-P |
26 | */ | 26 | */ |
27 | class PearsonHash : public Bu::CryptoHash | 27 | class PearsonHash : public Bu::CryptoHash |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | PearsonHash(); | 30 | PearsonHash(); |
31 | virtual ~PearsonHash(); | 31 | virtual ~PearsonHash(); |
32 | 32 | ||
33 | virtual void reset(); | 33 | virtual void reset(); |
34 | virtual void setSalt( const Bu::String &sSalt ); | 34 | virtual void setSalt( const Bu::String &sSalt ); |
35 | virtual void addData( const void *sData, int iSize ); | 35 | virtual void addData( const void *sData, int iSize ); |
36 | using Bu::CryptoHash::addData; | 36 | using Bu::CryptoHash::addData; |
37 | virtual String getResult(); | 37 | virtual String getResult(); |
38 | virtual void writeResult( Stream &sOut ); | 38 | virtual void writeResult( Stream &sOut ); |
39 | 39 | ||
40 | private: | 40 | private: |
41 | static uint8_t aSBox[256]; | 41 | static uint8_t aSBox[256]; |
42 | uint8_t iValue; | 42 | uint8_t iValue; |
43 | }; | 43 | }; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | #endif | 46 | #endif |
diff --git a/src/stable/plugger.h b/src/stable/plugger.h index d9eaf34..424613f 100644 --- a/src/stable/plugger.h +++ b/src/stable/plugger.h | |||
@@ -24,59 +24,59 @@ | |||
24 | 24 | ||
25 | namespace Bu | 25 | namespace Bu |
26 | { | 26 | { |
27 | subExceptionDecl( PluginException ); | 27 | subExceptionDecl( PluginException ); |
28 | 28 | ||
29 | typedef struct PluginInfo | 29 | typedef struct PluginInfo |
30 | { | 30 | { |
31 | const char *sID; | 31 | const char *sID; |
32 | const char *sAuthor; | 32 | const char *sAuthor; |
33 | unsigned short nVersion; | 33 | unsigned short nVersion; |
34 | unsigned short nRevision; | 34 | unsigned short nRevision; |
35 | void *(*createPlugin)(); | 35 | void *(*createPlugin)(); |
36 | void (*destroyPlugin)( void * ); | 36 | void (*destroyPlugin)( void * ); |
37 | } PluginInfo; | 37 | } PluginInfo; |
38 | 38 | ||
39 | typedef struct PluginReg | 39 | typedef struct PluginReg |
40 | { | 40 | { |
41 | bool bBuiltin; | 41 | bool bBuiltin; |
42 | #ifdef WIN32 | 42 | #ifdef WIN32 |
43 | HMODULE dlHandle; | 43 | HMODULE dlHandle; |
44 | #else | 44 | #else |
45 | void *dlHandle; | 45 | void *dlHandle; |
46 | #endif | 46 | #endif |
47 | PluginInfo *pInfo; | 47 | PluginInfo *pInfo; |
48 | } PluginReg; | 48 | } PluginReg; |
49 | 49 | ||
50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ | 50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ |
51 | extern "C" { \ | 51 | extern "C" { \ |
52 | baseclass *create ##classname() \ | 52 | baseclass *create ##classname() \ |
53 | { \ | 53 | { \ |
54 | return new classname(); \ | 54 | return new classname(); \ |
55 | } \ | 55 | } \ |
56 | void destroy ##classname( baseclass *pCls ) \ | 56 | void destroy ##classname( baseclass *pCls ) \ |
57 | { \ | 57 | { \ |
58 | delete pCls; \ | 58 | delete pCls; \ |
59 | } \ | 59 | } \ |
60 | Bu::PluginInfo classname = { \ | 60 | Bu::PluginInfo classname = { \ |
61 | #classname, name, ver, rev, \ | 61 | #classname, name, ver, rev, \ |
62 | create ##classname, destroy ##classname }; \ | 62 | create ##classname, destroy ##classname }; \ |
63 | } | 63 | } |
64 | 64 | ||
65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ | 65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ |
66 | extern "C" { \ | 66 | extern "C" { \ |
67 | baseclass *create ##classname() \ | 67 | baseclass *create ##classname() \ |
68 | { \ | 68 | { \ |
69 | return new classname(); \ | 69 | return new classname(); \ |
70 | } \ | 70 | } \ |
71 | void destroy ##classname( baseclass *pCls ) \ | 71 | void destroy ##classname( baseclass *pCls ) \ |
72 | { \ | 72 | { \ |
73 | delete pCls; \ | 73 | delete pCls; \ |
74 | } \ | 74 | } \ |
75 | Bu::PluginInfo pluginname = { \ | 75 | Bu::PluginInfo pluginname = { \ |
76 | #pluginname, name, ver, rev, \ | 76 | #pluginname, name, ver, rev, \ |
77 | (void *(*)())(create ##classname), \ | 77 | (void *(*)())(create ##classname), \ |
78 | (void (*)( void * ))(destroy ##classname) }; \ | 78 | (void (*)( void * ))(destroy ##classname) }; \ |
79 | } | 79 | } |
80 | 80 | ||
81 | // | 81 | // |
82 | // This is probably the main interface to use, I'll describe it some here... | 82 | // This is probably the main interface to use, I'll describe it some here... |
@@ -93,197 +93,197 @@ namespace Bu | |||
93 | // rev - an integer revision number for the plugin | 93 | // rev - an integer revision number for the plugin |
94 | // | 94 | // |
95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ | 95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ |
96 | extern "C" { \ | 96 | extern "C" { \ |
97 | baseclass *create ##classname() \ | 97 | baseclass *create ##classname() \ |
98 | { \ | 98 | { \ |
99 | return new classname(); \ | 99 | return new classname(); \ |
100 | } \ | 100 | } \ |
101 | void destroy ##classname( baseclass *pCls ) \ | 101 | void destroy ##classname( baseclass *pCls ) \ |
102 | { \ | 102 | { \ |
103 | delete pCls; \ | 103 | delete pCls; \ |
104 | } \ | 104 | } \ |
105 | Bu::PluginInfo structname = { \ | 105 | Bu::PluginInfo structname = { \ |
106 | #pluginname, name, ver, rev, \ | 106 | #pluginname, name, ver, rev, \ |
107 | (void *(*)())(create ##classname), \ | 107 | (void *(*)())(create ##classname), \ |
108 | (void (*)( void * ))(destroy ##classname) }; \ | 108 | (void (*)( void * ))(destroy ##classname) }; \ |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * A complete dynamic plugin manager system. This will allow you to design | 112 | * A complete dynamic plugin manager system. This will allow you to design |
113 | * and use plugins that are compiled into your program and dynamically | 113 | * and use plugins that are compiled into your program and dynamically |
114 | * linked to your program interchangably. It works on windows and on *nix | 114 | * linked to your program interchangably. It works on windows and on *nix |
115 | * and bsd type systems (anything that supports dlopen). Basically you | 115 | * and bsd type systems (anything that supports dlopen). Basically you |
116 | * create a base class that will be the basic interface of your plugins. | 116 | * create a base class that will be the basic interface of your plugins. |
117 | * Then you create some classes that inherit from it, and use the | 117 | * Then you create some classes that inherit from it, and use the |
118 | * PluginInterface3 macro to create the required data structures for it. | 118 | * PluginInterface3 macro to create the required data structures for it. |
119 | * | 119 | * |
120 | * Once you have plugins you can create a Plugger, by passing in the base | 120 | * Once you have plugins you can create a Plugger, by passing in the base |
121 | * class as it's template parameter. Once it's created, you can register | 121 | * class as it's template parameter. Once it's created, you can register |
122 | * plugins. To register a plugin that is builtin, you just need to pass | 122 | * plugins. To register a plugin that is builtin, you just need to pass |
123 | * a pointer to it's interface structure to the registerBuiltinPlugin | 123 | * a pointer to it's interface structure to the registerBuiltinPlugin |
124 | * function. To register a plugin that is in a shared object or dll file | 124 | * function. To register a plugin that is in a shared object or dll file |
125 | * you just pass the filename (with path, probably), and the name of the | 125 | * you just pass the filename (with path, probably), and the name of the |
126 | * structure to load and you're all set. | 126 | * structure to load and you're all set. |
127 | * | 127 | * |
128 | * To instantiate an object from a plugin simply call instantiate with the | 128 | * To instantiate an object from a plugin simply call instantiate with the |
129 | * name of the plugin as specified in the interface macro. To destroy an | 129 | * name of the plugin as specified in the interface macro. To destroy an |
130 | * object crated with the plugger do not delete it, instead pass it into | 130 | * object crated with the plugger do not delete it, instead pass it into |
131 | * Plugger's destroy function. | 131 | * Plugger's destroy function. |
132 | * | 132 | * |
133 | * Any objects not destroyed when the plugger is deleted will be destroyed | 133 | * Any objects not destroyed when the plugger is deleted will be destroyed |
134 | * automatically. | 134 | * automatically. |
135 | * | 135 | * |
136 | * It is important to note that some systems (linux at least) partition off | 136 | * It is important to note that some systems (linux at least) partition off |
137 | * the memory allocated by objects linked in at run time into a seperate | 137 | * the memory allocated by objects linked in at run time into a seperate |
138 | * segment that, while it can be accessed by the main program, cannot be | 138 | * segment that, while it can be accessed by the main program, cannot be |
139 | * safely or reliably freed by the main program. With that in mind it is | 139 | * safely or reliably freed by the main program. With that in mind it is |
140 | * a good idea to free all memory allocated by a plugin object in the plugin | 140 | * a good idea to free all memory allocated by a plugin object in the plugin |
141 | * object and not allow the calling program to delete it. | 141 | * object and not allow the calling program to delete it. |
142 | */ | 142 | */ |
143 | template<class T> | 143 | template<class T> |
144 | class Plugger | 144 | class Plugger |
145 | { | 145 | { |
146 | public: | 146 | public: |
147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; | 147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; |
148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; | 148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; |
149 | 149 | ||
150 | public: | 150 | public: |
151 | Plugger() | 151 | Plugger() |
152 | { | 152 | { |
153 | } | 153 | } |
154 | 154 | ||
155 | virtual ~Plugger() | 155 | virtual ~Plugger() |
156 | { | 156 | { |
157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) | 157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) |
158 | { | 158 | { |
159 | T *pPlug = (T *)i.getKey(); | 159 | T *pPlug = (T *)i.getKey(); |
160 | PluginReg *pReg = (PluginReg *)*i; | 160 | PluginReg *pReg = (PluginReg *)*i; |
161 | pReg->pInfo->destroyPlugin( pPlug ); | 161 | pReg->pInfo->destroyPlugin( pPlug ); |
162 | } | 162 | } |
163 | 163 | ||
164 | for( PluginHash::iterator i = hPlugin.begin(); | 164 | for( PluginHash::iterator i = hPlugin.begin(); |
165 | i != hPlugin.end(); i++ ) | 165 | i != hPlugin.end(); i++ ) |
166 | { | 166 | { |
167 | if( (*i)->bBuiltin == false ) | 167 | if( (*i)->bBuiltin == false ) |
168 | { | 168 | { |
169 | #ifdef WIN32 | 169 | #ifdef WIN32 |
170 | FreeLibrary( (*i)->dlHandle ); | 170 | FreeLibrary( (*i)->dlHandle ); |
171 | #else | 171 | #else |
172 | dlclose( (*i)->dlHandle ); | 172 | dlclose( (*i)->dlHandle ); |
173 | #endif | 173 | #endif |
174 | } | 174 | } |
175 | delete (*i); | 175 | delete (*i); |
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | void registerBuiltinPlugin( PluginInfo *pInfo ) | 179 | void registerBuiltinPlugin( PluginInfo *pInfo ) |
180 | { | 180 | { |
181 | PluginReg *pReg = new PluginReg; | 181 | PluginReg *pReg = new PluginReg; |
182 | pReg->bBuiltin = true; | 182 | pReg->bBuiltin = true; |
183 | pReg->pInfo = pInfo; | 183 | pReg->pInfo = pInfo; |
184 | hPlugin.insert( pInfo->sID, pReg ); | 184 | hPlugin.insert( pInfo->sID, pReg ); |
185 | } | 185 | } |
186 | 186 | ||
187 | void registerExternalPlugin( const Bu::String &sFName, | 187 | void registerExternalPlugin( const Bu::String &sFName, |
188 | const Bu::String &sPluginName ) | 188 | const Bu::String &sPluginName ) |
189 | { | 189 | { |
190 | PluginReg *pReg; | 190 | PluginReg *pReg; |
191 | if( hPlugin.has( sPluginName ) ) | 191 | if( hPlugin.has( sPluginName ) ) |
192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " | 192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " |
193 | "loaded.", sPluginName.getStr() ); | 193 | "loaded.", sPluginName.getStr() ); |
194 | 194 | ||
195 | pReg = new PluginReg; | 195 | pReg = new PluginReg; |
196 | 196 | ||
197 | pReg->bBuiltin = false; | 197 | pReg->bBuiltin = false; |
198 | #ifdef WIN32 | 198 | #ifdef WIN32 |
199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); | 199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); |
200 | if( pReg->dlHandle == NULL ) | 200 | if( pReg->dlHandle == NULL ) |
201 | { | 201 | { |
202 | throw PluginException( 1, "Error opening %s: %s", | 202 | throw PluginException( 1, "Error opening %s: %s", |
203 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 203 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
204 | } | 204 | } |
205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, | 205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, |
206 | sPluginName.getStr() ); | 206 | sPluginName.getStr() ); |
207 | if( pReg->pInfo == NULL ) | 207 | if( pReg->pInfo == NULL ) |
208 | { | 208 | { |
209 | throw PluginException( 2, "Error mapping %s: %s", | 209 | throw PluginException( 2, "Error mapping %s: %s", |
210 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 210 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
211 | } | 211 | } |
212 | #else | 212 | #else |
213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); | 213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); |
214 | if( pReg->dlHandle == NULL ) | 214 | if( pReg->dlHandle == NULL ) |
215 | { | 215 | { |
216 | throw PluginException( 1, "Error opening %s: %s", | 216 | throw PluginException( 1, "Error opening %s: %s", |
217 | sFName.getStr(), dlerror() ); | 217 | sFName.getStr(), dlerror() ); |
218 | } | 218 | } |
219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, | 219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, |
220 | sPluginName.getStr() ); | 220 | sPluginName.getStr() ); |
221 | if( pReg->pInfo == NULL ) | 221 | if( pReg->pInfo == NULL ) |
222 | { | 222 | { |
223 | throw PluginException( 2, "Error mapping %s: %s", | 223 | throw PluginException( 2, "Error mapping %s: %s", |
224 | sFName.getStr(), dlerror() ); | 224 | sFName.getStr(), dlerror() ); |
225 | } | 225 | } |
226 | #endif | 226 | #endif |
227 | hPlugin.insert( pReg->pInfo->sID, pReg ); | 227 | hPlugin.insert( pReg->pInfo->sID, pReg ); |
228 | } | 228 | } |
229 | 229 | ||
230 | T *instantiate( const Bu::String &lpName ) | 230 | T *instantiate( const Bu::String &lpName ) |
231 | { | 231 | { |
232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; | 232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; |
233 | if( pReg == NULL ) | 233 | if( pReg == NULL ) |
234 | return NULL; | 234 | return NULL; |
235 | 235 | ||
236 | T *p = (T *)pReg->pInfo->createPlugin(); | 236 | T *p = (T *)pReg->pInfo->createPlugin(); |
237 | hObj.insert( (ptrdiff_t)p, pReg ); | 237 | hObj.insert( (ptrdiff_t)p, pReg ); |
238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); | 238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); |
239 | 239 | ||
240 | return p; | 240 | return p; |
241 | } | 241 | } |
242 | 242 | ||
243 | bool hasPlugin( const Bu::String &lpName ) | 243 | bool hasPlugin( const Bu::String &lpName ) |
244 | { | 244 | { |
245 | return hPlugin.has( lpName ); | 245 | return hPlugin.has( lpName ); |
246 | } | 246 | } |
247 | 247 | ||
248 | void destroy( T *pPlug ) | 248 | void destroy( T *pPlug ) |
249 | { | 249 | { |
250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); | 250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); |
251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); | 251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); |
252 | if( pReg == NULL ) | 252 | if( pReg == NULL ) |
253 | return; | 253 | return; |
254 | 254 | ||
255 | pReg->pInfo->destroyPlugin( pPlug ); | 255 | pReg->pInfo->destroyPlugin( pPlug ); |
256 | 256 | ||
257 | hObj.erase( (ptrdiff_t)pPlug ); | 257 | hObj.erase( (ptrdiff_t)pPlug ); |
258 | } | 258 | } |
259 | 259 | ||
260 | void unloadAll() | 260 | void unloadAll() |
261 | { | 261 | { |
262 | for( PluginHash::iterator i = hPlugin.begin(); | 262 | for( PluginHash::iterator i = hPlugin.begin(); |
263 | i != hPlugin.end(); i++ ) | 263 | i != hPlugin.end(); i++ ) |
264 | { | 264 | { |
265 | if( (*i)->bBuiltin == false ) | 265 | if( (*i)->bBuiltin == false ) |
266 | { | 266 | { |
267 | #ifdef WIN32 | 267 | #ifdef WIN32 |
268 | FreeLibrary( (*i)->dlHandle ); | 268 | FreeLibrary( (*i)->dlHandle ); |
269 | #else | 269 | #else |
270 | dlclose( (*i)->dlHandle ); | 270 | dlclose( (*i)->dlHandle ); |
271 | #endif | 271 | #endif |
272 | } | 272 | } |
273 | delete (*i); | 273 | delete (*i); |
274 | } | 274 | } |
275 | hPlugin.clear(); | 275 | hPlugin.clear(); |
276 | } | 276 | } |
277 | 277 | ||
278 | Bu::List<Bu::String> getPluginList() | 278 | Bu::List<Bu::String> getPluginList() |
279 | { | 279 | { |
280 | return hPlugin.getKeys(); | 280 | return hPlugin.getKeys(); |
281 | } | 281 | } |
282 | 282 | ||
283 | private: | 283 | private: |
284 | PluginHash hPlugin; | 284 | PluginHash hPlugin; |
285 | InstHash hObj; | 285 | InstHash hObj; |
286 | }; | 286 | }; |
287 | } | 287 | } |
288 | 288 | ||
289 | #endif | 289 | #endif |
diff --git a/src/stable/process.cpp b/src/stable/process.cpp index a1adb23..a88ee7c 100644 --- a/src/stable/process.cpp +++ b/src/stable/process.cpp | |||
@@ -27,422 +27,422 @@ | |||
27 | 27 | ||
28 | Bu::Process::ProcData::ProcData() : | 28 | Bu::Process::ProcData::ProcData() : |
29 | #ifdef WIN32 | 29 | #ifdef WIN32 |
30 | hStdIn( NULL ), | 30 | hStdIn( NULL ), |
31 | hStdOut( NULL ), | 31 | hStdOut( NULL ), |
32 | hStdErr( NULL ) | 32 | hStdErr( NULL ) |
33 | #else | 33 | #else |
34 | iStdIn( -1 ), | 34 | iStdIn( -1 ), |
35 | iStdOut( -1 ), | 35 | iStdOut( -1 ), |
36 | iStdErr( -1 ) | 36 | iStdErr( -1 ) |
37 | #endif | 37 | #endif |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | 41 | ||
42 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : | 42 | Bu::Process::Process( Flags eFlags, const char *sName, char *const argv[] ) : |
43 | iProcStatus( 0 ), | 43 | iProcStatus( 0 ), |
44 | bBlocking( true ), | 44 | bBlocking( true ), |
45 | bStdOutEos( true ), | 45 | bStdOutEos( true ), |
46 | bStdErrEos( true ) | 46 | bStdErrEos( true ) |
47 | { | 47 | { |
48 | gexec( eFlags, sName, argv ); | 48 | gexec( eFlags, sName, argv ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : | 51 | Bu::Process::Process( Flags eFlags, const char *sName, const char *argv, ...) : |
52 | iProcStatus( 0 ), | 52 | iProcStatus( 0 ), |
53 | bBlocking( true ), | 53 | bBlocking( true ), |
54 | bStdOutEos( true ), | 54 | bStdOutEos( true ), |
55 | bStdErrEos( true ) | 55 | bStdErrEos( true ) |
56 | { | 56 | { |
57 | int iCnt = 0; | 57 | int iCnt = 0; |
58 | va_list ap; | 58 | va_list ap; |
59 | va_start( ap, argv ); | 59 | va_start( ap, argv ); |
60 | for(; va_arg( ap, const char *); iCnt++ ) { } | 60 | for(; va_arg( ap, const char *); iCnt++ ) { } |
61 | va_end( ap ); | 61 | va_end( ap ); |
62 | 62 | ||
63 | char const **list = new char const *[iCnt+2]; | 63 | char const **list = new char const *[iCnt+2]; |
64 | va_start( ap, argv ); | 64 | va_start( ap, argv ); |
65 | list[0] = argv; | 65 | list[0] = argv; |
66 | for( int j = 1; j <= iCnt; j++ ) | 66 | for( int j = 1; j <= iCnt; j++ ) |
67 | { | 67 | { |
68 | list[j] = va_arg( ap, const char *); | 68 | list[j] = va_arg( ap, const char *); |
69 | } | 69 | } |
70 | list[iCnt+1] = NULL; | 70 | list[iCnt+1] = NULL; |
71 | va_end( ap ); | 71 | va_end( ap ); |
72 | 72 | ||
73 | gexec( eFlags, sName, (char *const *)list ); | 73 | gexec( eFlags, sName, (char *const *)list ); |
74 | delete[] list; | 74 | delete[] list; |
75 | } | 75 | } |
76 | 76 | ||
77 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : | 77 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, char *const argv[] ) : |
78 | iProcStatus( 0 ), | 78 | iProcStatus( 0 ), |
79 | bBlocking( true ), | 79 | bBlocking( true ), |
80 | bStdOutEos( true ), | 80 | bStdOutEos( true ), |
81 | bStdErrEos( true ), | 81 | bStdErrEos( true ), |
82 | opt( opt ) | 82 | opt( opt ) |
83 | { | 83 | { |
84 | gexec( eFlags, sName, argv ); | 84 | gexec( eFlags, sName, argv ); |
85 | } | 85 | } |
86 | 86 | ||
87 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : | 87 | Bu::Process::Process( Flags eFlags, const Bu::Process::Options &opt, const char *sName, const char *argv, ...) : |
88 | iProcStatus( 0 ), | 88 | iProcStatus( 0 ), |
89 | bBlocking( true ), | 89 | bBlocking( true ), |
90 | bStdOutEos( true ), | 90 | bStdOutEos( true ), |
91 | bStdErrEos( true ), | 91 | bStdErrEos( true ), |
92 | opt( opt ) | 92 | opt( opt ) |
93 | { | 93 | { |
94 | int iCnt = 0; | 94 | int iCnt = 0; |
95 | va_list ap; | 95 | va_list ap; |
96 | va_start( ap, argv ); | 96 | va_start( ap, argv ); |
97 | for(; va_arg( ap, const char *); iCnt++ ) { } | 97 | for(; va_arg( ap, const char *); iCnt++ ) { } |
98 | va_end( ap ); | 98 | va_end( ap ); |
99 | 99 | ||
100 | char const **list = new char const *[iCnt+2]; | 100 | char const **list = new char const *[iCnt+2]; |
101 | va_start( ap, argv ); | 101 | va_start( ap, argv ); |
102 | list[0] = argv; | 102 | list[0] = argv; |
103 | for( int j = 1; j <= iCnt; j++ ) | 103 | for( int j = 1; j <= iCnt; j++ ) |
104 | { | 104 | { |
105 | list[j] = va_arg( ap, const char *); | 105 | list[j] = va_arg( ap, const char *); |
106 | } | 106 | } |
107 | list[iCnt+1] = NULL; | 107 | list[iCnt+1] = NULL; |
108 | va_end( ap ); | 108 | va_end( ap ); |
109 | 109 | ||
110 | gexec( eFlags, sName, (char *const *)list ); | 110 | gexec( eFlags, sName, (char *const *)list ); |
111 | delete[] list; | 111 | delete[] list; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::Process::~Process() | 114 | Bu::Process::~Process() |
115 | { | 115 | { |
116 | close(); | 116 | close(); |
117 | } | 117 | } |
118 | 118 | ||
119 | void Bu::Process::wait() | 119 | void Bu::Process::wait() |
120 | { | 120 | { |
121 | close(); | 121 | close(); |
122 | } | 122 | } |
123 | 123 | ||
124 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) | 124 | void Bu::Process::gexec( Flags eFlags, const char *sName, char *const argv[] ) |
125 | { | 125 | { |
126 | #ifdef WIN32 | 126 | #ifdef WIN32 |
127 | bStdErrEos = true; | 127 | bStdErrEos = true; |
128 | SECURITY_ATTRIBUTES saAttr; | 128 | SECURITY_ATTRIBUTES saAttr; |
129 | HANDLE hChildStd_IN_Rd; | 129 | HANDLE hChildStd_IN_Rd; |
130 | HANDLE hChildStd_IN_Wr; | 130 | HANDLE hChildStd_IN_Wr; |
131 | HANDLE hChildStd_OUT_Rd; | 131 | HANDLE hChildStd_OUT_Rd; |
132 | HANDLE hChildStd_OUT_Wr; | 132 | HANDLE hChildStd_OUT_Wr; |
133 | PROCESS_INFORMATION piProcInfo; | 133 | PROCESS_INFORMATION piProcInfo; |
134 | 134 | ||
135 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | 135 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); |
136 | saAttr.bInheritHandle = TRUE; | 136 | saAttr.bInheritHandle = TRUE; |
137 | saAttr.lpSecurityDescriptor = NULL; | 137 | saAttr.lpSecurityDescriptor = NULL; |
138 | 138 | ||
139 | // Create a pipe for the child process's STDOUT. | 139 | // Create a pipe for the child process's STDOUT. |
140 | if ( ! CreatePipe( | 140 | if ( ! CreatePipe( |
141 | &hChildStd_OUT_Rd, | 141 | &hChildStd_OUT_Rd, |
142 | &hChildStd_OUT_Wr, | 142 | &hChildStd_OUT_Wr, |
143 | &saAttr, 0) ) | 143 | &saAttr, 0) ) |
144 | throw "StdoutRd CreatePipe"; | 144 | throw "StdoutRd CreatePipe"; |
145 | 145 | ||
146 | // Ensure the read handle to the pipe for STDOUT is not inherited. | 146 | // Ensure the read handle to the pipe for STDOUT is not inherited. |
147 | if ( ! SetHandleInformation( | 147 | if ( ! SetHandleInformation( |
148 | hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) | 148 | hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ) |
149 | throw "Stdout SetHandleInformation"; | 149 | throw "Stdout SetHandleInformation"; |
150 | 150 | ||
151 | // Create a pipe for the child process's STDIN. | 151 | // Create a pipe for the child process's STDIN. |
152 | if (! CreatePipe( | 152 | if (! CreatePipe( |
153 | &hChildStd_IN_Rd, | 153 | &hChildStd_IN_Rd, |
154 | &hChildStd_IN_Wr, | 154 | &hChildStd_IN_Wr, |
155 | &saAttr, 0)) | 155 | &saAttr, 0)) |
156 | throw "Stdin CreatePipe"; | 156 | throw "Stdin CreatePipe"; |
157 | 157 | ||
158 | // Ensure the write handle to the pipe for STDIN is not inherited. | 158 | // Ensure the write handle to the pipe for STDIN is not inherited. |
159 | if ( ! SetHandleInformation( | 159 | if ( ! SetHandleInformation( |
160 | hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) | 160 | hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) |
161 | throw "Stdin SetHandleInformation"; | 161 | throw "Stdin SetHandleInformation"; |
162 | 162 | ||
163 | //TCHAR szCmdline[] = TEXT( sName ); | 163 | //TCHAR szCmdline[] = TEXT( sName ); |
164 | //PROCESS_INFORMATION pd.piProcInfo; | 164 | //PROCESS_INFORMATION pd.piProcInfo; |
165 | STARTUPINFO siStartInfo; | 165 | STARTUPINFO siStartInfo; |
166 | BOOL bSuccess = FALSE; | 166 | BOOL bSuccess = FALSE; |
167 | 167 | ||
168 | // Set up members of the PROCESS_INFORMATION structure. | 168 | // Set up members of the PROCESS_INFORMATION structure. |
169 | ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); | 169 | ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); |
170 | 170 | ||
171 | // Set up members of the STARTUPINFO structure. | 171 | // Set up members of the STARTUPINFO structure. |
172 | // This structure specifies the STDIN and STDOUT handles for redirection. | 172 | // This structure specifies the STDIN and STDOUT handles for redirection. |
173 | ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); | 173 | ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); |
174 | siStartInfo.cb = sizeof(STARTUPINFO); | 174 | siStartInfo.cb = sizeof(STARTUPINFO); |
175 | siStartInfo.hStdError = hChildStd_OUT_Wr; | 175 | siStartInfo.hStdError = hChildStd_OUT_Wr; |
176 | siStartInfo.hStdOutput = hChildStd_OUT_Wr; | 176 | siStartInfo.hStdOutput = hChildStd_OUT_Wr; |
177 | siStartInfo.hStdInput = hChildStd_IN_Rd; | 177 | siStartInfo.hStdInput = hChildStd_IN_Rd; |
178 | siStartInfo.dwFlags |= STARTF_USESTDHANDLES; | 178 | siStartInfo.dwFlags |= STARTF_USESTDHANDLES; |
179 | 179 | ||
180 | Bu::String sCmd; | 180 | Bu::String sCmd; |
181 | for( char *const *arg = argv; *arg; arg++ ) | 181 | for( char *const *arg = argv; *arg; arg++ ) |
182 | { | 182 | { |
183 | if( arg != argv ) | 183 | if( arg != argv ) |
184 | sCmd += " "; | 184 | sCmd += " "; |
185 | sCmd += *arg; | 185 | sCmd += *arg; |
186 | } | 186 | } |
187 | 187 | ||
188 | // Create the child process. | 188 | // Create the child process. |
189 | bSuccess = CreateProcessA( | 189 | bSuccess = CreateProcessA( |
190 | sName, //sName, //module name | 190 | sName, //sName, //module name |
191 | sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line | 191 | sCmd.getStr(), //(TCHAR *) sName, //szCmdline, // command line |
192 | NULL, // process security attributes | 192 | NULL, // process security attributes |
193 | NULL, // primary thread security attributes | 193 | NULL, // primary thread security attributes |
194 | TRUE, // handles are inherited | 194 | TRUE, // handles are inherited |
195 | CREATE_NO_WINDOW, // creation flags | 195 | CREATE_NO_WINDOW, // creation flags |
196 | NULL, // use parent's environment | 196 | NULL, // use parent's environment |
197 | NULL, // use parent's current directory | 197 | NULL, // use parent's current directory |
198 | &siStartInfo, // STARTUPINFO pointer | 198 | &siStartInfo, // STARTUPINFO pointer |
199 | &piProcInfo ); // receives PROCESS_INFORMATION | 199 | &piProcInfo ); // receives PROCESS_INFORMATION |
200 | 200 | ||
201 | // If an error occurs, exit the application. | 201 | // If an error occurs, exit the application. |
202 | if ( ! bSuccess ) | 202 | if ( ! bSuccess ) |
203 | { | 203 | { |
204 | throw Bu::ExceptionBase("Error spawning child process."); | 204 | throw Bu::ExceptionBase("Error spawning child process."); |
205 | return; | 205 | return; |
206 | } | 206 | } |
207 | else | 207 | else |
208 | { | 208 | { |
209 | // Close handles to the child process and its primary thread. | 209 | // Close handles to the child process and its primary thread. |
210 | // Some applications might keep these handles to monitor the status | 210 | // Some applications might keep these handles to monitor the status |
211 | // of the child process, for example. | 211 | // of the child process, for example. |
212 | 212 | ||
213 | //CloseHandle(pData->pd.piProcInfo.hProcess); | 213 | //CloseHandle(pData->pd.piProcInfo.hProcess); |
214 | CloseHandle(piProcInfo.hThread); | 214 | CloseHandle(piProcInfo.hThread); |
215 | pd.hProcess = piProcInfo.hProcess; | 215 | pd.hProcess = piProcInfo.hProcess; |
216 | 216 | ||
217 | // Close the ends we can't use | 217 | // Close the ends we can't use |
218 | CloseHandle( hChildStd_OUT_Wr ); | 218 | CloseHandle( hChildStd_OUT_Wr ); |
219 | CloseHandle( hChildStd_IN_Rd ); | 219 | CloseHandle( hChildStd_IN_Rd ); |
220 | pd.hStdIn = hChildStd_IN_Wr; | 220 | pd.hStdIn = hChildStd_IN_Wr; |
221 | pd.hStdOut = hChildStd_OUT_Rd; | 221 | pd.hStdOut = hChildStd_OUT_Rd; |
222 | } | 222 | } |
223 | #else | 223 | #else |
224 | int iaStdIn[2]; | 224 | int iaStdIn[2]; |
225 | int iaStdOut[2]; | 225 | int iaStdOut[2]; |
226 | int iaStdErr[2]; | 226 | int iaStdErr[2]; |
227 | pipe( iaStdIn ); | 227 | pipe( iaStdIn ); |
228 | if( eFlags & StdOut ) | 228 | if( eFlags & StdOut ) |
229 | { | 229 | { |
230 | pipe( iaStdOut ); | 230 | pipe( iaStdOut ); |
231 | pd.iStdOut = iaStdOut[0]; | 231 | pd.iStdOut = iaStdOut[0]; |
232 | bStdOutEos = false; | 232 | bStdOutEos = false; |
233 | } | 233 | } |
234 | if( eFlags & StdErr ) | 234 | if( eFlags & StdErr ) |
235 | { | 235 | { |
236 | pipe( iaStdErr ); | 236 | pipe( iaStdErr ); |
237 | pd.iStdErr = iaStdErr[0]; | 237 | pd.iStdErr = iaStdErr[0]; |
238 | bStdErrEos = false; | 238 | bStdErrEos = false; |
239 | } | 239 | } |
240 | 240 | ||
241 | pd.iStdIn = iaStdIn[1]; | 241 | pd.iStdIn = iaStdIn[1]; |
242 | 242 | ||
243 | // fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 243 | // fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
244 | 244 | ||
245 | pd.iPid = fork(); | 245 | pd.iPid = fork(); |
246 | if( pd.iPid == 0 ) | 246 | if( pd.iPid == 0 ) |
247 | { | 247 | { |
248 | ::close( iaStdIn[1] ); | 248 | ::close( iaStdIn[1] ); |
249 | dup2( iaStdIn[0], 0 ); | 249 | dup2( iaStdIn[0], 0 ); |
250 | if( eFlags & StdOut ) | 250 | if( eFlags & StdOut ) |
251 | { | 251 | { |
252 | ::close( iaStdOut[0] ); | 252 | ::close( iaStdOut[0] ); |
253 | dup2( iaStdOut[1], 1 ); | 253 | dup2( iaStdOut[1], 1 ); |
254 | } | 254 | } |
255 | if( eFlags & StdErr ) | 255 | if( eFlags & StdErr ) |
256 | { | 256 | { |
257 | ::close( iaStdErr[0] ); | 257 | ::close( iaStdErr[0] ); |
258 | dup2( iaStdErr[1], 2 ); | 258 | dup2( iaStdErr[1], 2 ); |
259 | } | 259 | } |
260 | if( (opt.eFlags&Options::SetGid) ) | 260 | if( (opt.eFlags&Options::SetGid) ) |
261 | { | 261 | { |
262 | setgid( opt.iGid ); | 262 | setgid( opt.iGid ); |
263 | } | 263 | } |
264 | if( (opt.eFlags&Options::SetUid) ) | 264 | if( (opt.eFlags&Options::SetUid) ) |
265 | { | 265 | { |
266 | setuid( opt.iUid ); | 266 | setuid( opt.iUid ); |
267 | } | 267 | } |
268 | execvp( sName, argv ); | 268 | execvp( sName, argv ); |
269 | throw Bu::ExceptionBase("Hey, execvp failed!"); | 269 | throw Bu::ExceptionBase("Hey, execvp failed!"); |
270 | } | 270 | } |
271 | ::close( iaStdIn[0] ); | 271 | ::close( iaStdIn[0] ); |
272 | if( eFlags & StdOut ) | 272 | if( eFlags & StdOut ) |
273 | ::close( iaStdOut[1] ); | 273 | ::close( iaStdOut[1] ); |
274 | if( eFlags & StdErr ) | 274 | if( eFlags & StdErr ) |
275 | ::close( iaStdErr[1] ); | 275 | ::close( iaStdErr[1] ); |
276 | #endif | 276 | #endif |
277 | } | 277 | } |
278 | 278 | ||
279 | void Bu::Process::close() | 279 | void Bu::Process::close() |
280 | { | 280 | { |
281 | #ifdef WIN32 | 281 | #ifdef WIN32 |
282 | if( pd.hStdIn ) | 282 | if( pd.hStdIn ) |
283 | { | 283 | { |
284 | CloseHandle( pd.hStdIn ); | 284 | CloseHandle( pd.hStdIn ); |
285 | CloseHandle( pd.hStdOut ); | 285 | CloseHandle( pd.hStdOut ); |
286 | 286 | ||
287 | pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; | 287 | pd.hStdIn = pd.hStdOut = pd.hStdErr = NULL; |
288 | 288 | ||
289 | if( !TerminateProcess(pd.hProcess, 1) ) | 289 | if( !TerminateProcess(pd.hProcess, 1) ) |
290 | { | 290 | { |
291 | throw Bu::ExceptionBase("Error closing process."); | 291 | throw Bu::ExceptionBase("Error closing process."); |
292 | } | 292 | } |
293 | 293 | ||
294 | GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus ); | 294 | GetExitCodeProcess( pd.hProcess, (PDWORD)&iProcStatus ); |
295 | 295 | ||
296 | CloseHandle( pd.hProcess ); | 296 | CloseHandle( pd.hProcess ); |
297 | pd.hProcess = NULL; | 297 | pd.hProcess = NULL; |
298 | } | 298 | } |
299 | #else | 299 | #else |
300 | if( pd.iPid ) | 300 | if( pd.iPid ) |
301 | { | 301 | { |
302 | if( pd.iStdIn > -1 ) | 302 | if( pd.iStdIn > -1 ) |
303 | ::close( pd.iStdIn ); | 303 | ::close( pd.iStdIn ); |
304 | if( pd.iStdOut > -1 ) | 304 | if( pd.iStdOut > -1 ) |
305 | ::close( pd.iStdOut ); | 305 | ::close( pd.iStdOut ); |
306 | if( pd.iStdErr > -1 ) | 306 | if( pd.iStdErr > -1 ) |
307 | ::close( pd.iStdErr ); | 307 | ::close( pd.iStdErr ); |
308 | waitpid( pd.iPid, &iProcStatus, 0 ); | 308 | waitpid( pd.iPid, &iProcStatus, 0 ); |
309 | pd.iPid = 0; | 309 | pd.iPid = 0; |
310 | } | 310 | } |
311 | #endif | 311 | #endif |
312 | } | 312 | } |
313 | 313 | ||
314 | void Bu::Process::closeStdIn() | 314 | void Bu::Process::closeStdIn() |
315 | { | 315 | { |
316 | #ifdef WIN32 | 316 | #ifdef WIN32 |
317 | CloseHandle( pd.hStdIn ); | 317 | CloseHandle( pd.hStdIn ); |
318 | pd.hStdIn = NULL; | 318 | pd.hStdIn = NULL; |
319 | #else | 319 | #else |
320 | ::close( pd.iStdIn ); | 320 | ::close( pd.iStdIn ); |
321 | pd.iStdIn = -1; | 321 | pd.iStdIn = -1; |
322 | #endif | 322 | #endif |
323 | } | 323 | } |
324 | 324 | ||
325 | void Bu::Process::closeStdOut() | 325 | void Bu::Process::closeStdOut() |
326 | { | 326 | { |
327 | #ifdef WIN32 | 327 | #ifdef WIN32 |
328 | CloseHandle( pd.hStdOut ); | 328 | CloseHandle( pd.hStdOut ); |
329 | pd.hStdOut = NULL; | 329 | pd.hStdOut = NULL; |
330 | #else | 330 | #else |
331 | ::close( pd.iStdOut ); | 331 | ::close( pd.iStdOut ); |
332 | pd.iStdOut = -1; | 332 | pd.iStdOut = -1; |
333 | #endif | 333 | #endif |
334 | } | 334 | } |
335 | 335 | ||
336 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) | 336 | Bu::size Bu::Process::read( void *pBuf, Bu::size nBytes ) |
337 | { | 337 | { |
338 | #ifdef WIN32 | 338 | #ifdef WIN32 |
339 | DWORD dwRead; | 339 | DWORD dwRead; |
340 | DWORD lExitCode; | 340 | DWORD lExitCode; |
341 | BOOL bSuccess = FALSE; | 341 | BOOL bSuccess = FALSE; |
342 | DWORD dwLen = (DWORD) nBytes; | 342 | DWORD dwLen = (DWORD) nBytes; |
343 | bSuccess = ReadFile( | 343 | bSuccess = ReadFile( |
344 | pd.hStdOut, (char *) pBuf, | 344 | pd.hStdOut, (char *) pBuf, |
345 | dwLen, &dwRead, NULL); | 345 | dwLen, &dwRead, NULL); |
346 | // if( dwRead < dwLen ) | 346 | // if( dwRead < dwLen ) |
347 | { | 347 | { |
348 | bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode ); | 348 | bSuccess = GetExitCodeProcess( pd.hProcess, &lExitCode ); |
349 | if( lExitCode != STILL_ACTIVE ) | 349 | if( lExitCode != STILL_ACTIVE ) |
350 | { | 350 | { |
351 | bStdOutEos = true; | 351 | bStdOutEos = true; |
352 | } | 352 | } |
353 | } | 353 | } |
354 | return (int32_t) dwRead; | 354 | return (int32_t) dwRead; |
355 | #else | 355 | #else |
356 | if( bStdOutEos ) | 356 | if( bStdOutEos ) |
357 | return 0; | 357 | return 0; |
358 | fd_set rfds; | 358 | fd_set rfds; |
359 | FD_ZERO( &rfds ); | 359 | FD_ZERO( &rfds ); |
360 | FD_SET( pd.iStdOut, &rfds ); | 360 | FD_SET( pd.iStdOut, &rfds ); |
361 | struct timeval tv = {0, 0}; | 361 | struct timeval tv = {0, 0}; |
362 | if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) | 362 | if( ::bu_select( pd.iStdOut+1, &rfds, NULL, NULL, &tv ) < 0 ) |
363 | throw Bu::ExceptionBase( strerror( errno ) ); | 363 | throw Bu::ExceptionBase( strerror( errno ) ); |
364 | if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) | 364 | if( FD_ISSET( pd.iStdOut, &rfds ) || bBlocking ) |
365 | { | 365 | { |
366 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); | 366 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdOut, pBuf, nBytes ) ); |
367 | if( nRead == 0 ) | 367 | if( nRead == 0 ) |
368 | { | 368 | { |
369 | bStdOutEos = true; | 369 | bStdOutEos = true; |
370 | checkClose(); | 370 | checkClose(); |
371 | return 0; | 371 | return 0; |
372 | } | 372 | } |
373 | if( nRead < 0 ) | 373 | if( nRead < 0 ) |
374 | { | 374 | { |
375 | if( errno == EAGAIN ) | 375 | if( errno == EAGAIN ) |
376 | return 0; | 376 | return 0; |
377 | throw Bu::ExceptionBase( strerror( errno ) ); | 377 | throw Bu::ExceptionBase( strerror( errno ) ); |
378 | } | 378 | } |
379 | return nRead; | 379 | return nRead; |
380 | } | 380 | } |
381 | return 0; | 381 | return 0; |
382 | #endif | 382 | #endif |
383 | } | 383 | } |
384 | 384 | ||
385 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) | 385 | Bu::size Bu::Process::readErr( void *pBuf, Bu::size nBytes ) |
386 | { | 386 | { |
387 | #ifdef WIN32 | 387 | #ifdef WIN32 |
388 | if( !pd.hStdErr ) | 388 | if( !pd.hStdErr ) |
389 | return 0; | 389 | return 0; |
390 | DWORD dwRead; | 390 | DWORD dwRead; |
391 | BOOL bSuccess = FALSE; | 391 | BOOL bSuccess = FALSE; |
392 | DWORD dwLen = (DWORD) nBytes; | 392 | DWORD dwLen = (DWORD) nBytes; |
393 | bSuccess = ReadFile( | 393 | bSuccess = ReadFile( |
394 | pd.hStdErr, (char *) pBuf, | 394 | pd.hStdErr, (char *) pBuf, |
395 | dwLen, &dwRead, NULL); | 395 | dwLen, &dwRead, NULL); |
396 | return (int32_t) dwRead; | 396 | return (int32_t) dwRead; |
397 | #else | 397 | #else |
398 | if( bStdErrEos ) | 398 | if( bStdErrEos ) |
399 | return 0; | 399 | return 0; |
400 | fd_set rfds; | 400 | fd_set rfds; |
401 | FD_ZERO( &rfds ); | 401 | FD_ZERO( &rfds ); |
402 | FD_SET( pd.iStdErr, &rfds ); | 402 | FD_SET( pd.iStdErr, &rfds ); |
403 | struct timeval tv = {0, 0}; | 403 | struct timeval tv = {0, 0}; |
404 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) | 404 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, &tv ) < 0 ) |
405 | throw Bu::ExceptionBase( strerror( errno ) ); | 405 | throw Bu::ExceptionBase( strerror( errno ) ); |
406 | if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) | 406 | if( FD_ISSET( pd.iStdErr, &rfds ) || bBlocking ) |
407 | { | 407 | { |
408 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); | 408 | Bu::size nRead = TEMP_FAILURE_RETRY( ::read( pd.iStdErr, pBuf, nBytes ) ); |
409 | if( nRead == 0 ) | 409 | if( nRead == 0 ) |
410 | { | 410 | { |
411 | bStdErrEos = true; | 411 | bStdErrEos = true; |
412 | checkClose(); | 412 | checkClose(); |
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | if( nRead < 0 ) | 415 | if( nRead < 0 ) |
416 | { | 416 | { |
417 | if( errno == EAGAIN ) | 417 | if( errno == EAGAIN ) |
418 | return 0; | 418 | return 0; |
419 | throw Bu::ExceptionBase( strerror( errno ) ); | 419 | throw Bu::ExceptionBase( strerror( errno ) ); |
420 | } | 420 | } |
421 | return nRead; | 421 | return nRead; |
422 | } | 422 | } |
423 | return 0; | 423 | return 0; |
424 | #endif | 424 | #endif |
425 | } | 425 | } |
426 | 426 | ||
427 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) | 427 | Bu::size Bu::Process::write( const void *pBuf, Bu::size nBytes ) |
428 | { | 428 | { |
429 | #ifdef WIN32 | 429 | #ifdef WIN32 |
430 | DWORD dwWritten; | 430 | DWORD dwWritten; |
431 | BOOL bSuccess = FALSE; | 431 | BOOL bSuccess = FALSE; |
432 | DWORD dwLen = (DWORD) nBytes; | 432 | DWORD dwLen = (DWORD) nBytes; |
433 | bSuccess = WriteFile( | 433 | bSuccess = WriteFile( |
434 | pd.hStdIn, (const char *) pBuf, | 434 | pd.hStdIn, (const char *) pBuf, |
435 | dwLen, &dwWritten, NULL ); | 435 | dwLen, &dwWritten, NULL ); |
436 | FlushFileBuffers( pd.hStdIn ); | 436 | FlushFileBuffers( pd.hStdIn ); |
437 | return (int32_t) dwWritten; | 437 | return (int32_t) dwWritten; |
438 | #else | 438 | #else |
439 | return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); | 439 | return TEMP_FAILURE_RETRY( ::write( pd.iStdIn, pBuf, nBytes ) ); |
440 | #endif | 440 | #endif |
441 | } | 441 | } |
442 | 442 | ||
443 | Bu::size Bu::Process::tell() | 443 | Bu::size Bu::Process::tell() |
444 | { | 444 | { |
445 | return 0; | 445 | return 0; |
446 | } | 446 | } |
447 | 447 | ||
448 | void Bu::Process::seek( Bu::size ) | 448 | void Bu::Process::seek( Bu::size ) |
@@ -460,15 +460,15 @@ void Bu::Process::setPosEnd( Bu::size ) | |||
460 | bool Bu::Process::isEos() | 460 | bool Bu::Process::isEos() |
461 | { | 461 | { |
462 | #ifdef WIN32 | 462 | #ifdef WIN32 |
463 | return (pd.hProcess == NULL); | 463 | return (pd.hProcess == NULL); |
464 | #else | 464 | #else |
465 | return (pd.iPid == 0); | 465 | return (pd.iPid == 0); |
466 | #endif | 466 | #endif |
467 | } | 467 | } |
468 | 468 | ||
469 | bool Bu::Process::isOpen() | 469 | bool Bu::Process::isOpen() |
470 | { | 470 | { |
471 | return !isEos(); | 471 | return !isEos(); |
472 | } | 472 | } |
473 | 473 | ||
474 | void Bu::Process::flush() | 474 | void Bu::Process::flush() |
@@ -477,53 +477,53 @@ void Bu::Process::flush() | |||
477 | 477 | ||
478 | bool Bu::Process::canRead() | 478 | bool Bu::Process::canRead() |
479 | { | 479 | { |
480 | return true; | 480 | return true; |
481 | } | 481 | } |
482 | 482 | ||
483 | bool Bu::Process::canWrite() | 483 | bool Bu::Process::canWrite() |
484 | { | 484 | { |
485 | return true; | 485 | return true; |
486 | } | 486 | } |
487 | 487 | ||
488 | bool Bu::Process::isReadable() | 488 | bool Bu::Process::isReadable() |
489 | { | 489 | { |
490 | return true; | 490 | return true; |
491 | } | 491 | } |
492 | 492 | ||
493 | bool Bu::Process::isWritable() | 493 | bool Bu::Process::isWritable() |
494 | { | 494 | { |
495 | return true; | 495 | return true; |
496 | } | 496 | } |
497 | 497 | ||
498 | bool Bu::Process::isSeekable() | 498 | bool Bu::Process::isSeekable() |
499 | { | 499 | { |
500 | return false; | 500 | return false; |
501 | } | 501 | } |
502 | 502 | ||
503 | bool Bu::Process::isBlocking() | 503 | bool Bu::Process::isBlocking() |
504 | { | 504 | { |
505 | return true; | 505 | return true; |
506 | } | 506 | } |
507 | 507 | ||
508 | void Bu::Process::setBlocking( bool bBlocking ) | 508 | void Bu::Process::setBlocking( bool bBlocking ) |
509 | { | 509 | { |
510 | #ifdef WIN32 | 510 | #ifdef WIN32 |
511 | #else | 511 | #else |
512 | if( bBlocking ) | 512 | if( bBlocking ) |
513 | { | 513 | { |
514 | if( !bStdOutEos ) | 514 | if( !bStdOutEos ) |
515 | fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); | 515 | fcntl( pd.iStdOut, F_SETFL, fcntl(pd.iStdOut,F_GETFL,0 )&(~O_NONBLOCK) ); |
516 | if( !bStdErrEos ) | 516 | if( !bStdErrEos ) |
517 | fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); | 517 | fcntl( pd.iStdErr, F_SETFL, fcntl(pd.iStdErr,F_GETFL,0 )&(~O_NONBLOCK) ); |
518 | } | 518 | } |
519 | else | 519 | else |
520 | { | 520 | { |
521 | if( !bStdOutEos ) | 521 | if( !bStdOutEos ) |
522 | fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); | 522 | fcntl( pd.iStdOut, F_SETFL, fcntl( pd.iStdOut, F_GETFL, 0 )|O_NONBLOCK ); |
523 | if( !bStdErrEos ) | 523 | if( !bStdErrEos ) |
524 | fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); | 524 | fcntl( pd.iStdErr, F_SETFL, fcntl( pd.iStdErr, F_GETFL, 0 )|O_NONBLOCK ); |
525 | } | 525 | } |
526 | this->bBlocking = bBlocking; | 526 | this->bBlocking = bBlocking; |
527 | #endif | 527 | #endif |
528 | } | 528 | } |
529 | 529 | ||
@@ -533,128 +533,128 @@ void Bu::Process::setSize( Bu::size ) | |||
533 | 533 | ||
534 | Bu::size Bu::Process::getBlockSize() const | 534 | Bu::size Bu::Process::getBlockSize() const |
535 | { | 535 | { |
536 | return 0; | 536 | return 0; |
537 | } | 537 | } |
538 | 538 | ||
539 | Bu::size Bu::Process::getSize() const | 539 | Bu::size Bu::Process::getSize() const |
540 | { | 540 | { |
541 | return 0; | 541 | return 0; |
542 | } | 542 | } |
543 | 543 | ||
544 | Bu::String Bu::Process::getLocation() const | 544 | Bu::String Bu::Process::getLocation() const |
545 | { | 545 | { |
546 | return ""; | 546 | return ""; |
547 | } | 547 | } |
548 | 548 | ||
549 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) | 549 | void Bu::Process::select( bool &bStdOut, bool &bStdErr ) |
550 | { | 550 | { |
551 | #ifdef WIN32 | 551 | #ifdef WIN32 |
552 | #else | 552 | #else |
553 | fd_set rfds; | 553 | fd_set rfds; |
554 | FD_ZERO( &rfds ); | 554 | FD_ZERO( &rfds ); |
555 | if( !bStdOutEos ) | 555 | if( !bStdOutEos ) |
556 | FD_SET( pd.iStdOut, &rfds ); | 556 | FD_SET( pd.iStdOut, &rfds ); |
557 | if( !bStdErrEos ) | 557 | if( !bStdErrEos ) |
558 | FD_SET( pd.iStdErr, &rfds ); | 558 | FD_SET( pd.iStdErr, &rfds ); |
559 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) | 559 | if( ::bu_select( pd.iStdErr+1, &rfds, NULL, NULL, NULL ) < 0 ) |
560 | throw Bu::ExceptionBase( strerror( errno ) ); | 560 | throw Bu::ExceptionBase( strerror( errno ) ); |
561 | 561 | ||
562 | if( FD_ISSET( pd.iStdOut, &rfds ) ) | 562 | if( FD_ISSET( pd.iStdOut, &rfds ) ) |
563 | bStdOut = true; | 563 | bStdOut = true; |
564 | else | 564 | else |
565 | bStdOut = false; | 565 | bStdOut = false; |
566 | 566 | ||
567 | if( FD_ISSET( pd.iStdErr, &rfds ) ) | 567 | if( FD_ISSET( pd.iStdErr, &rfds ) ) |
568 | bStdErr = true; | 568 | bStdErr = true; |
569 | else | 569 | else |
570 | bStdErr = false; | 570 | bStdErr = false; |
571 | #endif | 571 | #endif |
572 | } | 572 | } |
573 | 573 | ||
574 | bool Bu::Process::isRunning() | 574 | bool Bu::Process::isRunning() |
575 | { | 575 | { |
576 | #ifdef WIN32 | 576 | #ifdef WIN32 |
577 | DWORD lExitCode; | 577 | DWORD lExitCode; |
578 | GetExitCodeProcess( pd.hProcess, &lExitCode ); | 578 | GetExitCodeProcess( pd.hProcess, &lExitCode ); |
579 | if( lExitCode != STILL_ACTIVE ) | 579 | if( lExitCode != STILL_ACTIVE ) |
580 | checkClose(); | 580 | checkClose(); |
581 | #else | 581 | #else |
582 | if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) | 582 | if( waitpid( pd.iPid, NULL, WNOHANG ) == pd.iPid ) |
583 | checkClose(); | 583 | checkClose(); |
584 | #endif | 584 | #endif |
585 | return isOpen(); | 585 | return isOpen(); |
586 | } | 586 | } |
587 | 587 | ||
588 | void Bu::Process::ignoreStdErr() | 588 | void Bu::Process::ignoreStdErr() |
589 | { | 589 | { |
590 | #ifdef WIN32 | 590 | #ifdef WIN32 |
591 | #else | 591 | #else |
592 | if( pd.iStdErr == -1 ) | 592 | if( pd.iStdErr == -1 ) |
593 | return; | 593 | return; |
594 | ::close( pd.iStdErr ); | 594 | ::close( pd.iStdErr ); |
595 | pd.iStdErr = -1; | 595 | pd.iStdErr = -1; |
596 | bStdErrEos = true; | 596 | bStdErrEos = true; |
597 | #endif | 597 | #endif |
598 | } | 598 | } |
599 | 599 | ||
600 | pid_t Bu::Process::getPid() | 600 | pid_t Bu::Process::getPid() |
601 | { | 601 | { |
602 | #ifdef WIN32 | 602 | #ifdef WIN32 |
603 | return 0; | 603 | return 0; |
604 | #else | 604 | #else |
605 | return pd.iPid; | 605 | return pd.iPid; |
606 | #endif | 606 | #endif |
607 | } | 607 | } |
608 | 608 | ||
609 | bool Bu::Process::childExited() | 609 | bool Bu::Process::childExited() |
610 | { | 610 | { |
611 | #ifdef WIN32 | 611 | #ifdef WIN32 |
612 | return pd.hProcess != NULL; | 612 | return pd.hProcess != NULL; |
613 | #else | 613 | #else |
614 | return WIFEXITED( iProcStatus ); | 614 | return WIFEXITED( iProcStatus ); |
615 | #endif | 615 | #endif |
616 | } | 616 | } |
617 | 617 | ||
618 | int Bu::Process::childExitStatus() | 618 | int Bu::Process::childExitStatus() |
619 | { | 619 | { |
620 | #ifdef WIN32 | 620 | #ifdef WIN32 |
621 | return iProcStatus; | 621 | return iProcStatus; |
622 | #else | 622 | #else |
623 | return WEXITSTATUS( iProcStatus ); | 623 | return WEXITSTATUS( iProcStatus ); |
624 | #endif | 624 | #endif |
625 | } | 625 | } |
626 | 626 | ||
627 | bool Bu::Process::childSignaled() | 627 | bool Bu::Process::childSignaled() |
628 | { | 628 | { |
629 | #ifdef WIN32 | 629 | #ifdef WIN32 |
630 | return false; | 630 | return false; |
631 | #else | 631 | #else |
632 | return WIFSIGNALED( iProcStatus ); | 632 | return WIFSIGNALED( iProcStatus ); |
633 | #endif | 633 | #endif |
634 | } | 634 | } |
635 | 635 | ||
636 | int Bu::Process::childSignal() | 636 | int Bu::Process::childSignal() |
637 | { | 637 | { |
638 | #ifdef WIN32 | 638 | #ifdef WIN32 |
639 | return 0; | 639 | return 0; |
640 | #else | 640 | #else |
641 | return WTERMSIG( iProcStatus ); | 641 | return WTERMSIG( iProcStatus ); |
642 | #endif | 642 | #endif |
643 | } | 643 | } |
644 | 644 | ||
645 | bool Bu::Process::childCoreDumped() | 645 | bool Bu::Process::childCoreDumped() |
646 | { | 646 | { |
647 | #ifdef WIN32 | 647 | #ifdef WIN32 |
648 | return false; | 648 | return false; |
649 | #else | 649 | #else |
650 | return WCOREDUMP( iProcStatus ); | 650 | return WCOREDUMP( iProcStatus ); |
651 | #endif | 651 | #endif |
652 | } | 652 | } |
653 | 653 | ||
654 | void Bu::Process::checkClose() | 654 | void Bu::Process::checkClose() |
655 | { | 655 | { |
656 | if( bStdOutEos && bStdErrEos ) | 656 | if( bStdOutEos && bStdErrEos ) |
657 | { | 657 | { |
658 | close(); | 658 | close(); |
659 | } | 659 | } |
660 | } | 660 | } |
diff --git a/src/stable/process.h b/src/stable/process.h index 904606a..72b686a 100644 --- a/src/stable/process.h +++ b/src/stable/process.h | |||
@@ -16,151 +16,151 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Runs a program and attaches streams to it's stdin, stdout, and stderr. | 20 | * Runs a program and attaches streams to it's stdin, stdout, and stderr. |
21 | * Reading from a Bu::Process will read from the program's standard output, | 21 | * Reading from a Bu::Process will read from the program's standard output, |
22 | * writing to a Bu::Process will write to the program's standard input. | 22 | * writing to a Bu::Process will write to the program's standard input. |
23 | */ | 23 | */ |
24 | class Process : public Bu::Stream | 24 | class Process : public Bu::Stream |
25 | { | 25 | { |
26 | public: | 26 | public: |
27 | enum Flags | 27 | enum Flags |
28 | { | 28 | { |
29 | None = 0x00, | 29 | None = 0x00, |
30 | StdOut = 0x01, | 30 | StdOut = 0x01, |
31 | StdErr = 0x02, | 31 | StdErr = 0x02, |
32 | Both = 0x03 | 32 | Both = 0x03 |
33 | }; | 33 | }; |
34 | 34 | ||
35 | public: | 35 | public: |
36 | class Options | 36 | class Options |
37 | { | 37 | { |
38 | public: | 38 | public: |
39 | enum OptFlags | 39 | enum OptFlags |
40 | { | 40 | { |
41 | None = 0x00, | 41 | None = 0x00, |
42 | SetUid = 0x01, | 42 | SetUid = 0x01, |
43 | SetGid = 0x02, | 43 | SetGid = 0x02, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | Options() : eFlags( None ) {} | 46 | Options() : eFlags( None ) {} |
47 | 47 | ||
48 | int eFlags; | 48 | int eFlags; |
49 | int iUid; | 49 | int iUid; |
50 | int iGid; | 50 | int iGid; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | Process( Flags eFlags, const char *sName, char *const argv[] ); | 53 | Process( Flags eFlags, const char *sName, char *const argv[] ); |
54 | Process( Flags eFlags, const char *sName, const char *argv, ...); | 54 | Process( Flags eFlags, const char *sName, const char *argv, ...); |
55 | Process( Flags eFlags, const Options &opt, const char *sName, char *const argv[] ); | 55 | Process( Flags eFlags, const Options &opt, const char *sName, char *const argv[] ); |
56 | Process( Flags eFlags, const Options &opt, const char *sName, const char *argv, ...); | 56 | Process( Flags eFlags, const Options &opt, const char *sName, const char *argv, ...); |
57 | virtual ~Process(); | 57 | virtual ~Process(); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * Waits until the process exits. This blocks the caller until the | 60 | * Waits until the process exits. This blocks the caller until the |
61 | * child process terminates. | 61 | * child process terminates. |
62 | */ | 62 | */ |
63 | void wait(); | 63 | void wait(); |
64 | 64 | ||
65 | virtual void close(); | 65 | virtual void close(); |
66 | virtual void closeStdIn(); | 66 | virtual void closeStdIn(); |
67 | virtual void closeStdOut(); | 67 | virtual void closeStdOut(); |
68 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 68 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
69 | virtual Bu::size readErr( void *pBuf, Bu::size nBytes ); | 69 | virtual Bu::size readErr( void *pBuf, Bu::size nBytes ); |
70 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 70 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
71 | using Stream::write; | 71 | using Stream::write; |
72 | 72 | ||
73 | virtual Bu::size tell(); | 73 | virtual Bu::size tell(); |
74 | virtual void seek( Bu::size offset ); | 74 | virtual void seek( Bu::size offset ); |
75 | virtual void setPos( Bu::size pos ); | 75 | virtual void setPos( Bu::size pos ); |
76 | virtual void setPosEnd( Bu::size pos ); | 76 | virtual void setPosEnd( Bu::size pos ); |
77 | virtual bool isEos(); | 77 | virtual bool isEos(); |
78 | virtual bool isOpen(); | 78 | virtual bool isOpen(); |
79 | 79 | ||
80 | virtual void flush(); | 80 | virtual void flush(); |
81 | 81 | ||
82 | virtual bool canRead(); | 82 | virtual bool canRead(); |
83 | virtual bool canWrite(); | 83 | virtual bool canWrite(); |
84 | 84 | ||
85 | virtual bool isReadable(); | 85 | virtual bool isReadable(); |
86 | virtual bool isWritable(); | 86 | virtual bool isWritable(); |
87 | virtual bool isSeekable(); | 87 | virtual bool isSeekable(); |
88 | 88 | ||
89 | virtual bool isBlocking(); | 89 | virtual bool isBlocking(); |
90 | virtual void setBlocking( bool bBlocking=true ); | 90 | virtual void setBlocking( bool bBlocking=true ); |
91 | 91 | ||
92 | virtual void setSize( Bu::size iSize ); | 92 | virtual void setSize( Bu::size iSize ); |
93 | 93 | ||
94 | virtual size getBlockSize() const; | 94 | virtual size getBlockSize() const; |
95 | virtual size getSize() const; | 95 | virtual size getSize() const; |
96 | virtual Bu::String getLocation() const; | 96 | virtual Bu::String getLocation() const; |
97 | 97 | ||
98 | void select( bool &bStdOut, bool &bStdErr ); | 98 | void select( bool &bStdOut, bool &bStdErr ); |
99 | 99 | ||
100 | bool isRunning(); | 100 | bool isRunning(); |
101 | void ignoreStdErr(); | 101 | void ignoreStdErr(); |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Returns the pid of the child process, or zero if there is no | 104 | * Returns the pid of the child process, or zero if there is no |
105 | * currently running child. Note that a read operation must be | 105 | * currently running child. Note that a read operation must be |
106 | * performed in order to discover that the child has ended. | 106 | * performed in order to discover that the child has ended. |
107 | */ | 107 | */ |
108 | pid_t getPid(); | 108 | pid_t getPid(); |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * Returns true if the child exited normally (by calling exit or | 111 | * Returns true if the child exited normally (by calling exit or |
112 | * returning from main). | 112 | * returning from main). |
113 | */ | 113 | */ |
114 | bool childExited(); | 114 | bool childExited(); |
115 | 115 | ||
116 | /** | 116 | /** |
117 | * Returns the 8 bit integer value returned from the child program if | 117 | * Returns the 8 bit integer value returned from the child program if |
118 | * childExited returned true. | 118 | * childExited returned true. |
119 | */ | 119 | */ |
120 | int childExitStatus(); | 120 | int childExitStatus(); |
121 | 121 | ||
122 | /** | 122 | /** |
123 | * Returns true if the child exited because of a signal. | 123 | * Returns true if the child exited because of a signal. |
124 | */ | 124 | */ |
125 | bool childSignaled(); | 125 | bool childSignaled(); |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * Returns the signal ID if the childSignaled return true. | 128 | * Returns the signal ID if the childSignaled return true. |
129 | */ | 129 | */ |
130 | int childSignal(); | 130 | int childSignal(); |
131 | 131 | ||
132 | /** | 132 | /** |
133 | * Returns true if the child left a core dump behind when it exited. | 133 | * Returns true if the child left a core dump behind when it exited. |
134 | */ | 134 | */ |
135 | bool childCoreDumped(); | 135 | bool childCoreDumped(); |
136 | 136 | ||
137 | private: | 137 | private: |
138 | class ProcData | 138 | class ProcData |
139 | { | 139 | { |
140 | public: | 140 | public: |
141 | ProcData(); | 141 | ProcData(); |
142 | #ifdef WIN32 | 142 | #ifdef WIN32 |
143 | void *hStdIn; | 143 | void *hStdIn; |
144 | void *hStdOut; | 144 | void *hStdOut; |
145 | void *hStdErr; | 145 | void *hStdErr; |
146 | void *hProcess; | 146 | void *hProcess; |
147 | #else | 147 | #else |
148 | int iStdIn; | 148 | int iStdIn; |
149 | int iStdOut; | 149 | int iStdOut; |
150 | int iStdErr; | 150 | int iStdErr; |
151 | pid_t iPid; | 151 | pid_t iPid; |
152 | #endif | 152 | #endif |
153 | }; | 153 | }; |
154 | ProcData pd; | 154 | ProcData pd; |
155 | int iProcStatus; | 155 | int iProcStatus; |
156 | bool bBlocking; | 156 | bool bBlocking; |
157 | bool bStdOutEos; | 157 | bool bStdOutEos; |
158 | bool bStdErrEos; | 158 | bool bStdErrEos; |
159 | 159 | ||
160 | void gexec( Flags eFlags, const char *sName, char *const argv[] ); | 160 | void gexec( Flags eFlags, const char *sName, char *const argv[] ); |
161 | void checkClose(); | 161 | void checkClose(); |
162 | Options opt; | 162 | Options opt; |
163 | }; | 163 | }; |
164 | } | 164 | } |
165 | 165 | ||
166 | #endif | 166 | #endif |
diff --git a/src/stable/protocol.h b/src/stable/protocol.h index 1a02143..4e121d9 100644 --- a/src/stable/protocol.h +++ b/src/stable/protocol.h | |||
@@ -14,25 +14,25 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Client; | 17 | class Client; |
18 | 18 | ||
19 | /** | 19 | /** |
20 | *@ingroup Serving | 20 | *@ingroup Serving |
21 | */ | 21 | */ |
22 | class Protocol | 22 | class Protocol |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Protocol(); | 25 | Protocol(); |
26 | virtual ~Protocol(); | 26 | virtual ~Protocol(); |
27 | 27 | ||
28 | virtual void onNewConnection( Bu::Client *pClient ); | 28 | virtual void onNewConnection( Bu::Client *pClient ); |
29 | virtual void onNewData( Bu::Client *pClient ); | 29 | virtual void onNewData( Bu::Client *pClient ); |
30 | virtual void onMessage( Bu::Client *pClient, const Bu::String &sMsg ); | 30 | virtual void onMessage( Bu::Client *pClient, const Bu::String &sMsg ); |
31 | virtual void onTick( Bu::Client *pClient ); | 31 | virtual void onTick( Bu::Client *pClient ); |
32 | 32 | ||
33 | private: | 33 | private: |
34 | 34 | ||
35 | }; | 35 | }; |
36 | } | 36 | } |
37 | 37 | ||
38 | #endif | 38 | #endif |
diff --git a/src/stable/protocolhttp.cpp b/src/stable/protocolhttp.cpp index ea1a86e..352f7c7 100644 --- a/src/stable/protocolhttp.cpp +++ b/src/stable/protocolhttp.cpp | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <dirent.h> | 8 | #include <dirent.h> |
9 | 9 | ||
10 | #ifndef WIN32 | 10 | #ifndef WIN32 |
11 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #include <errno.h> | 14 | #include <errno.h> |
@@ -32,9 +32,9 @@ Bu::ProtocolHttp::~ProtocolHttp() | |||
32 | 32 | ||
33 | void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) | 33 | void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) |
34 | { | 34 | { |
35 | this->pClient = pClient; | 35 | this->pClient = pClient; |
36 | 36 | ||
37 | iState = 0; | 37 | iState = 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | #define SDB( i ) (void)0 | 40 | #define SDB( i ) (void)0 |
@@ -42,196 +42,196 @@ void Bu::ProtocolHttp::onNewConnection( Bu::Client *pClient ) | |||
42 | 42 | ||
43 | void Bu::ProtocolHttp::onNewData( Bu::Client *pClient ) | 43 | void Bu::ProtocolHttp::onNewData( Bu::Client *pClient ) |
44 | { | 44 | { |
45 | /* logHexDump( | 45 | /* logHexDump( |
46 | 1, | 46 | 1, |
47 | pClient->getInput().getStr(), | 47 | pClient->getInput().getStr(), |
48 | pClient->getInput().getSize(), | 48 | pClient->getInput().getSize(), |
49 | "input" | 49 | "input" |
50 | );*/ | 50 | );*/ |
51 | 51 | ||
52 | for(;;) | 52 | for(;;) |
53 | { | 53 | { |
54 | Bu::String sToken; | 54 | Bu::String sToken; |
55 | TokenType tt = getToken( sToken ); | 55 | TokenType tt = getToken( sToken ); |
56 | 56 | ||
57 | if( tt == ttOutOfData ) | 57 | if( tt == ttOutOfData ) |
58 | return; | 58 | return; |
59 | 59 | ||
60 | switch( iState ) | 60 | switch( iState ) |
61 | { | 61 | { |
62 | case 0: // Start token, should be "method" (get, put, etc) | 62 | case 0: // Start token, should be "method" (get, put, etc) |
63 | SDB( 0 ); | 63 | SDB( 0 ); |
64 | sMethod = sToken; | 64 | sMethod = sToken; |
65 | iState = 1; | 65 | iState = 1; |
66 | break; | 66 | break; |
67 | 67 | ||
68 | case 1: // The path requested | 68 | case 1: // The path requested |
69 | SDB( 1 ); | 69 | SDB( 1 ); |
70 | sPath = sToken; | 70 | sPath = sToken; |
71 | iState = 2; | 71 | iState = 2; |
72 | break; | 72 | break; |
73 | 73 | ||
74 | case 2: // The protocol name and version | 74 | case 2: // The protocol name and version |
75 | SDB( 2 ); | 75 | SDB( 2 ); |
76 | if( strncmp( sToken.getStr(), "HTTP/", 5 ) ) | 76 | if( strncmp( sToken.getStr(), "HTTP/", 5 ) ) |
77 | { | 77 | { |
78 | pClient->disconnect(); | 78 | pClient->disconnect(); |
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | else | 81 | else |
82 | { | 82 | { |
83 | char *s, *s2; | 83 | char *s, *s2; |
84 | s = sToken.getStr()+5; | 84 | s = sToken.getStr()+5; |
85 | iMajor = strtol( s, &s2, 10 ); | 85 | iMajor = strtol( s, &s2, 10 ); |
86 | iMinor = strtol( s2+1, NULL, 10 ); | 86 | iMinor = strtol( s2+1, NULL, 10 ); |
87 | iState = 3; | 87 | iState = 3; |
88 | } | 88 | } |
89 | break; | 89 | break; |
90 | 90 | ||
91 | case 3: // End of initial header, now comes mime-style blocks. | 91 | case 3: // End of initial header, now comes mime-style blocks. |
92 | SDB( 3 ); | 92 | SDB( 3 ); |
93 | if( tt == ttNewline ) | 93 | if( tt == ttNewline ) |
94 | { | 94 | { |
95 | iState = 10; | 95 | iState = 10; |
96 | } | 96 | } |
97 | else if( tt == ttDoubleNewline ) | 97 | else if( tt == ttDoubleNewline ) |
98 | { | 98 | { |
99 | earlyResponse(); | 99 | earlyResponse(); |
100 | } | 100 | } |
101 | else | 101 | else |
102 | { | 102 | { |
103 | pClient->disconnect(); | 103 | pClient->disconnect(); |
104 | return; | 104 | return; |
105 | } | 105 | } |
106 | break; | 106 | break; |
107 | 107 | ||
108 | case 10: // HTTP-Message (skipped for now...) | 108 | case 10: // HTTP-Message (skipped for now...) |
109 | SDB( 10 ); | 109 | SDB( 10 ); |
110 | if( tt == ttString ) | 110 | if( tt == ttString ) |
111 | { | 111 | { |
112 | iState = 11; | 112 | iState = 11; |
113 | } | 113 | } |
114 | else | 114 | else |
115 | { | 115 | { |
116 | pClient->disconnect(); | 116 | pClient->disconnect(); |
117 | } | 117 | } |
118 | break; | 118 | break; |
119 | 119 | ||
120 | case 11: // Should be a colon... | 120 | case 11: // Should be a colon... |
121 | SDB( 11 ); | 121 | SDB( 11 ); |
122 | if( tt == ttSeperator && sToken == ":" ) | 122 | if( tt == ttSeperator && sToken == ":" ) |
123 | { | 123 | { |
124 | iState = 12; | 124 | iState = 12; |
125 | } | 125 | } |
126 | else | 126 | else |
127 | { | 127 | { |
128 | pClient->disconnect(); | 128 | pClient->disconnect(); |
129 | } | 129 | } |
130 | break; | 130 | break; |
131 | 131 | ||
132 | case 12: | 132 | case 12: |
133 | SDB( 12 ); | 133 | SDB( 12 ); |
134 | if( tt == ttNewline ) | 134 | if( tt == ttNewline ) |
135 | { | 135 | { |
136 | iState = 10; | 136 | iState = 10; |
137 | } | 137 | } |
138 | if( tt == ttDoubleNewline ) | 138 | if( tt == ttDoubleNewline ) |
139 | { | 139 | { |
140 | earlyResponse(); | 140 | earlyResponse(); |
141 | } | 141 | } |
142 | break; | 142 | break; |
143 | 143 | ||
144 | case 20: | 144 | case 20: |
145 | SDB( 20 ); | 145 | SDB( 20 ); |
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | Bu::ProtocolHttp::TokenType Bu::ProtocolHttp::getToken( Bu::String &line ) | 151 | Bu::ProtocolHttp::TokenType Bu::ProtocolHttp::getToken( Bu::String &line ) |
152 | { | 152 | { |
153 | char s; | 153 | char s; |
154 | int jmax = pClient->getInputSize(); | 154 | int jmax = pClient->getInputSize(); |
155 | bool bNonWS = false; | 155 | bool bNonWS = false; |
156 | 156 | ||
157 | for( int j = 0; j < jmax; j++ ) | 157 | for( int j = 0; j < jmax; j++ ) |
158 | { | 158 | { |
159 | pClient->peek( &s, 1, j ); | 159 | pClient->peek( &s, 1, j ); |
160 | if( iState > 2 && isSeperator( s ) ) | 160 | if( iState > 2 && isSeperator( s ) ) |
161 | { | 161 | { |
162 | if( j == 0 ) | 162 | if( j == 0 ) |
163 | { | 163 | { |
164 | line += s; | 164 | line += s; |
165 | pClient->seek( 1 ); | 165 | pClient->seek( 1 ); |
166 | return ttSeperator; | 166 | return ttSeperator; |
167 | } | 167 | } |
168 | else | 168 | else |
169 | { | 169 | { |
170 | pClient->seek( j ); | 170 | pClient->seek( j ); |
171 | return ttString; | 171 | return ttString; |
172 | } | 172 | } |
173 | } | 173 | } |
174 | else if( isWS( s ) ) | 174 | else if( isWS( s ) ) |
175 | { | 175 | { |
176 | if( bNonWS ) | 176 | if( bNonWS ) |
177 | { | 177 | { |
178 | pClient->seek( j ); | 178 | pClient->seek( j ); |
179 | return ttString; | 179 | return ttString; |
180 | } | 180 | } |
181 | } | 181 | } |
182 | else if( s == CR ) | 182 | else if( s == CR ) |
183 | { | 183 | { |
184 | if( pClient->getInputSize() < 4 ) | 184 | if( pClient->getInputSize() < 4 ) |
185 | return ttOutOfData; | 185 | return ttOutOfData; |
186 | 186 | ||
187 | char ss[3]; | 187 | char ss[3]; |
188 | pClient->peek( ss, 3, j+1 ); | 188 | pClient->peek( ss, 3, j+1 ); |
189 | if( ss[0] == LF && ss[1] != ' ' && ss[1] != '\t' ) | 189 | if( ss[0] == LF && ss[1] != ' ' && ss[1] != '\t' ) |
190 | { | 190 | { |
191 | if( bNonWS ) | 191 | if( bNonWS ) |
192 | { | 192 | { |
193 | pClient->seek( j ); | 193 | pClient->seek( j ); |
194 | return ttString; | 194 | return ttString; |
195 | } | 195 | } |
196 | else if( ss[1] == CR && ss[2] == LF ) | 196 | else if( ss[1] == CR && ss[2] == LF ) |
197 | { | 197 | { |
198 | pClient->seek( 4 ); | 198 | pClient->seek( 4 ); |
199 | return ttDoubleNewline; | 199 | return ttDoubleNewline; |
200 | } | 200 | } |
201 | else | 201 | else |
202 | { | 202 | { |
203 | pClient->seek( 2 ); | 203 | pClient->seek( 2 ); |
204 | return ttNewline; | 204 | return ttNewline; |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | j += 2; | 208 | j += 2; |
209 | if( bNonWS ) | 209 | if( bNonWS ) |
210 | { | 210 | { |
211 | pClient->seek( j ); | 211 | pClient->seek( j ); |
212 | return ttString; | 212 | return ttString; |
213 | } | 213 | } |
214 | } | 214 | } |
215 | else | 215 | else |
216 | { | 216 | { |
217 | line += s; | 217 | line += s; |
218 | bNonWS = true; | 218 | bNonWS = true; |
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | return ttOutOfData; | 222 | return ttOutOfData; |
223 | } | 223 | } |
224 | 224 | ||
225 | bool Bu::ProtocolHttp::isWS( char buf ) | 225 | bool Bu::ProtocolHttp::isWS( char buf ) |
226 | { | 226 | { |
227 | return (buf == ' ' || buf == '\t'); | 227 | return (buf == ' ' || buf == '\t'); |
228 | } | 228 | } |
229 | 229 | ||
230 | bool Bu::ProtocolHttp::isSeperator( char buf ) | 230 | bool Bu::ProtocolHttp::isSeperator( char buf ) |
231 | { | 231 | { |
232 | return (buf == '(' || buf == ')' || buf == '<' || buf == '>' || | 232 | return (buf == '(' || buf == ')' || buf == '<' || buf == '>' || |
233 | buf == '@' || buf == ',' || buf == ';' || buf == ':' || | 233 | buf == '@' || buf == ',' || buf == ';' || buf == ':' || |
234 | buf == '\\' || buf == '\"' || buf == '/' || buf == '[' || | 234 | buf == '\\' || buf == '\"' || buf == '/' || buf == '[' || |
235 | buf == ']' || buf == '?' || buf == '=' || buf == '{' || | 235 | buf == ']' || buf == '?' || buf == '=' || buf == '{' || |
236 | buf == '}' ); | 236 | buf == '}' ); |
237 | } | 237 | } |
diff --git a/src/stable/protocolhttp.h b/src/stable/protocolhttp.h index 87dc49b..51ca58c 100644 --- a/src/stable/protocolhttp.h +++ b/src/stable/protocolhttp.h | |||
@@ -18,89 +18,89 @@ | |||
18 | 18 | ||
19 | namespace Bu | 19 | namespace Bu |
20 | { | 20 | { |
21 | /** | 21 | /** |
22 | * An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text | 22 | * An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text |
23 | * Transfer Protocol, and that the Protocol part is redundant, but in this | 23 | * Transfer Protocol, and that the Protocol part is redundant, but in this |
24 | * case the word Protocol is refering to the Libbu++ construct Bu::Protocol, | 24 | * case the word Protocol is refering to the Libbu++ construct Bu::Protocol, |
25 | * and not a means of encoding conversations. Anyway, this class represents | 25 | * and not a means of encoding conversations. Anyway, this class represents |
26 | * a general HTTP server processor. Every time a request comes in it calls | 26 | * a general HTTP server processor. Every time a request comes in it calls |
27 | * the onRequest function in a subclass with the method and URI that were | 27 | * the onRequest function in a subclass with the method and URI that were |
28 | * requested. The sub-class can then do whatever it needs to to send back | 28 | * requested. The sub-class can then do whatever it needs to to send back |
29 | * a response. | 29 | * a response. |
30 | *@ingroup Serving | 30 | *@ingroup Serving |
31 | */ | 31 | */ |
32 | class ProtocolHttp : public Protocol | 32 | class ProtocolHttp : public Protocol |
33 | { | 33 | { |
34 | public: /* Types */ | 34 | public: /* Types */ |
35 | typedef Bu::List<Bu::String> TokenList; | 35 | typedef Bu::List<Bu::String> TokenList; |
36 | 36 | ||
37 | public: /* Interface */ | 37 | public: /* Interface */ |
38 | ProtocolHttp(); | 38 | ProtocolHttp(); |
39 | virtual ~ProtocolHttp(); | 39 | virtual ~ProtocolHttp(); |
40 | 40 | ||
41 | virtual void onNewConnection( Bu::Client *pClient ); | 41 | virtual void onNewConnection( Bu::Client *pClient ); |
42 | virtual void onNewData( Bu::Client *pClient ); | 42 | virtual void onNewData( Bu::Client *pClient ); |
43 | 43 | ||
44 | virtual void onRequest( | 44 | virtual void onRequest( |
45 | const Bu::String &sMethod, const Bu::String &sPath )=0; | 45 | const Bu::String &sMethod, const Bu::String &sPath )=0; |
46 | 46 | ||
47 | class Response | 47 | class Response |
48 | { | 48 | { |
49 | friend class Bu::ProtocolHttp; | 49 | friend class Bu::ProtocolHttp; |
50 | public: | 50 | public: |
51 | Response( int iCode ); | 51 | Response( int iCode ); |
52 | Response( int iCode, const Bu::String &sReason ); | 52 | Response( int iCode, const Bu::String &sReason ); |
53 | virtual ~Response(); | 53 | virtual ~Response(); |
54 | 54 | ||
55 | void setHeader( const Bu::String &sKey, const Bu::String &sVal ); | 55 | void setHeader( const Bu::String &sKey, const Bu::String &sVal ); |
56 | void setContent( const Bu::String &sCont ); | 56 | void setContent( const Bu::String &sCont ); |
57 | 57 | ||
58 | private: | 58 | private: |
59 | int iCode; | 59 | int iCode; |
60 | Bu::String sReason; | 60 | Bu::String sReason; |
61 | typedef Bu::Hash<Bu::String,Bu::String> StringHash; | 61 | typedef Bu::Hash<Bu::String,Bu::String> StringHash; |
62 | StringHash hHeaders; | 62 | StringHash hHeaders; |
63 | Bu::String sContent; | 63 | Bu::String sContent; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | void sendResponse( const Response &rRes ); | 66 | void sendResponse( const Response &rRes ); |
67 | 67 | ||
68 | private: | 68 | private: |
69 | enum TokenType | 69 | enum TokenType |
70 | { | 70 | { |
71 | ttOutOfData, | 71 | ttOutOfData, |
72 | ttString, | 72 | ttString, |
73 | ttNewline, | 73 | ttNewline, |
74 | ttDoubleNewline, | 74 | ttDoubleNewline, |
75 | ttSeperator | 75 | ttSeperator |
76 | }; | 76 | }; |
77 | /** | 77 | /** |
78 | * Read an HTTP line, this is up to the first CRLF that isn't followed | 78 | * Read an HTTP line, this is up to the first CRLF that isn't followed |
79 | * by a continuation character, converting it to one line as it reads. | 79 | * by a continuation character, converting it to one line as it reads. |
80 | *@param line All data read will be appended to line, even if no | 80 | *@param line All data read will be appended to line, even if no |
81 | * end-of-line is read. | 81 | * end-of-line is read. |
82 | *@returns True if an end-of-line is read and the line should be | 82 | *@returns True if an end-of-line is read and the line should be |
83 | * processed, false if the end-of-line has not been reached, and more | 83 | * processed, false if the end-of-line has not been reached, and more |
84 | * data needs to be read before this operation can continue. | 84 | * data needs to be read before this operation can continue. |
85 | */ | 85 | */ |
86 | TokenType getToken( Bu::String &line ); | 86 | TokenType getToken( Bu::String &line ); |
87 | bool isWS( char buf ); | 87 | bool isWS( char buf ); |
88 | bool isSeperator( char buf ); | 88 | bool isSeperator( char buf ); |
89 | 89 | ||
90 | void earlyResponse(); | 90 | void earlyResponse(); |
91 | void lateResponse(); | 91 | void lateResponse(); |
92 | 92 | ||
93 | private: /* state */ | 93 | private: /* state */ |
94 | Bu::Client *pClient; | 94 | Bu::Client *pClient; |
95 | TokenList lTokens; | 95 | TokenList lTokens; |
96 | 96 | ||
97 | int iState; | 97 | int iState; |
98 | 98 | ||
99 | Bu::String sMethod; | 99 | Bu::String sMethod; |
100 | Bu::String sPath; | 100 | Bu::String sPath; |
101 | int iMajor; | 101 | int iMajor; |
102 | int iMinor; | 102 | int iMinor; |
103 | }; | 103 | }; |
104 | } | 104 | } |
105 | 105 | ||
106 | #endif | 106 | #endif |
diff --git a/src/stable/protocoltelnet.cpp b/src/stable/protocoltelnet.cpp index aed23be..d5465d1 100644 --- a/src/stable/protocoltelnet.cpp +++ b/src/stable/protocoltelnet.cpp | |||
@@ -11,53 +11,53 @@ | |||
11 | /* We apparently at least want defs for the lower 13, not sure we care about | 11 | /* We apparently at least want defs for the lower 13, not sure we care about |
12 | * the rest of the chars, maybe escape. | 12 | * the rest of the chars, maybe escape. |
13 | */ | 13 | */ |
14 | #define CH_NUL '\x00' /* NUL */ | 14 | #define CH_NUL '\x00' /* NUL */ |
15 | #define CH_SOH '\x01' /* Start Of Heading */ | 15 | #define CH_SOH '\x01' /* Start Of Heading */ |
16 | #define CH_STX '\x02' /* Start of Text */ | 16 | #define CH_STX '\x02' /* Start of Text */ |
17 | #define CH_ETX '\x03' /* End of Text */ | 17 | #define CH_ETX '\x03' /* End of Text */ |
18 | #define CH_EOT '\x04' /* End of transmission */ | 18 | #define CH_EOT '\x04' /* End of transmission */ |
19 | #define CH_ENQ '\x05' /* Enquiery */ | 19 | #define CH_ENQ '\x05' /* Enquiery */ |
20 | #define CH_ACK '\x06' /* Acknowledge */ | 20 | #define CH_ACK '\x06' /* Acknowledge */ |
21 | #define CH_BEL '\x07' /* Bell */ | 21 | #define CH_BEL '\x07' /* Bell */ |
22 | #define CH_BS '\x08' /* Backspace */ | 22 | #define CH_BS '\x08' /* Backspace */ |
23 | #define CH_TAB '\x09' /* Horizontal Tab */ | 23 | #define CH_TAB '\x09' /* Horizontal Tab */ |
24 | #define CH_LF '\x0A' /* NL Line feed, new line */ | 24 | #define CH_LF '\x0A' /* NL Line feed, new line */ |
25 | #define CH_VT '\x0B' /* Vertical Tab */ | 25 | #define CH_VT '\x0B' /* Vertical Tab */ |
26 | #define CH_FF '\x0C' /* Form feed, new page */ | 26 | #define CH_FF '\x0C' /* Form feed, new page */ |
27 | #define CH_CR '\x0D' /* Carriage return */ | 27 | #define CH_CR '\x0D' /* Carriage return */ |
28 | #define CH_ESC '\x1B' /* Escape */ | 28 | #define CH_ESC '\x1B' /* Escape */ |
29 | #define CH_DEL '\x7F' /* Delete */ | 29 | #define CH_DEL '\x7F' /* Delete */ |
30 | 30 | ||
31 | #define CODE_SE '\xf0' /* End of subnegotiation params. */ | 31 | #define CODE_SE '\xf0' /* End of subnegotiation params. */ |
32 | #define CODE_NOP '\xf1' /* No operation (keep-alive). */ | 32 | #define CODE_NOP '\xf1' /* No operation (keep-alive). */ |
33 | #define CODE_DM '\xf2' /* Datastream side of a Synch. */ | 33 | #define CODE_DM '\xf2' /* Datastream side of a Synch. */ |
34 | #define CODE_BRK '\xf3' /* Break character. */ | 34 | #define CODE_BRK '\xf3' /* Break character. */ |
35 | #define CODE_IP '\xf4' /* Interrupt Process character. */ | 35 | #define CODE_IP '\xf4' /* Interrupt Process character. */ |
36 | #define CODE_AO '\xf5' /* Abort Output character. */ | 36 | #define CODE_AO '\xf5' /* Abort Output character. */ |
37 | #define CODE_AYT '\xf6' /* Are You There? character. */ | 37 | #define CODE_AYT '\xf6' /* Are You There? character. */ |
38 | #define CODE_EC '\xf7' /* Erase Character character. */ | 38 | #define CODE_EC '\xf7' /* Erase Character character. */ |
39 | #define CODE_EL '\xf8' /* Erase Line character. */ | 39 | #define CODE_EL '\xf8' /* Erase Line character. */ |
40 | #define CODE_GA '\xf9' /* Go Ahead signal. */ | 40 | #define CODE_GA '\xf9' /* Go Ahead signal. */ |
41 | #define CODE_SB '\xfa' /* Begin subnegotiation options. */ | 41 | #define CODE_SB '\xfa' /* Begin subnegotiation options. */ |
42 | #define CODE_WILL '\xfb' /* Desire to do something. */ | 42 | #define CODE_WILL '\xfb' /* Desire to do something. */ |
43 | #define CODE_WONT '\xfc' /* Refuse to perform. */ | 43 | #define CODE_WONT '\xfc' /* Refuse to perform. */ |
44 | #define CODE_DO '\xfd' /* Request option. */ | 44 | #define CODE_DO '\xfd' /* Request option. */ |
45 | #define CODE_DONT '\xfe' /* Demand a stop. */ | 45 | #define CODE_DONT '\xfe' /* Demand a stop. */ |
46 | 46 | ||
47 | #define CODE_IAC '\xff' /* Interpret-As-Command. */ | 47 | #define CODE_IAC '\xff' /* Interpret-As-Command. */ |
48 | 48 | ||
49 | #define OPT_BINARY '\x00' /* Binary mode (file transfers?). */ | 49 | #define OPT_BINARY '\x00' /* Binary mode (file transfers?). */ |
50 | #define OPT_ECHO '\x01' /* (local) Echo mode. */ | 50 | #define OPT_ECHO '\x01' /* (local) Echo mode. */ |
51 | #define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */ | 51 | #define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */ |
52 | #define OPT_STATUS '\x05' /* Allow status messages. */ | 52 | #define OPT_STATUS '\x05' /* Allow status messages. */ |
53 | #define OPT_TIMING '\x06' /* Place a timing mark in the code. */ | 53 | #define OPT_TIMING '\x06' /* Place a timing mark in the code. */ |
54 | #define OPT_EXASCII '\x11' /* Extended ASCII. */ | 54 | #define OPT_EXASCII '\x11' /* Extended ASCII. */ |
55 | #define OPT_LOGOUT '\x12' /* Logout. */ | 55 | #define OPT_LOGOUT '\x12' /* Logout. */ |
56 | #define OPT_TTYPE '\x18' /* Terminal Type. */ | 56 | #define OPT_TTYPE '\x18' /* Terminal Type. */ |
57 | #define OPT_NAWS '\x1f' /* Negotiate about window size. */ | 57 | #define OPT_NAWS '\x1f' /* Negotiate about window size. */ |
58 | #define OPT_TSPEED '\x20' /* Terminal Speed. */ | 58 | #define OPT_TSPEED '\x20' /* Terminal Speed. */ |
59 | #define OPT_NEWENV '\x27' /* New Environment Option. */ | 59 | #define OPT_NEWENV '\x27' /* New Environment Option. */ |
60 | #define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */ | 60 | #define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */ |
61 | 61 | ||
62 | #ifndef __TELNET_DEBUG | 62 | #ifndef __TELNET_DEBUG |
63 | # define printCode( a ) (void)0 | 63 | # define printCode( a ) (void)0 |
@@ -65,12 +65,12 @@ | |||
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | Bu::ProtocolTelnet::ProtocolTelnet() : | 67 | Bu::ProtocolTelnet::ProtocolTelnet() : |
68 | oBinary( *this, OPT_BINARY ), | 68 | oBinary( *this, OPT_BINARY ), |
69 | oEcho( *this, OPT_ECHO ), | 69 | oEcho( *this, OPT_ECHO ), |
70 | oNAWS( *this, OPT_NAWS ), | 70 | oNAWS( *this, OPT_NAWS ), |
71 | oSuppressGA(*this, OPT_SUPGA ), | 71 | oSuppressGA(*this, OPT_SUPGA ), |
72 | bCanonical( true ), | 72 | bCanonical( true ), |
73 | bSubOpt( false ) | 73 | bSubOpt( false ) |
74 | { | 74 | { |
75 | } | 75 | } |
76 | 76 | ||
@@ -80,439 +80,439 @@ Bu::ProtocolTelnet::~ProtocolTelnet() | |||
80 | 80 | ||
81 | void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) | 81 | void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) |
82 | { | 82 | { |
83 | this->pClient = pClient; | 83 | this->pClient = pClient; |
84 | } | 84 | } |
85 | 85 | ||
86 | void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) | 86 | void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) |
87 | { | 87 | { |
88 | char bc; | 88 | char bc; |
89 | int iLeft; | 89 | int iLeft; |
90 | while( (iLeft = pClient->getInputSize()) ) | 90 | while( (iLeft = pClient->getInputSize()) ) |
91 | { | 91 | { |
92 | if( bSubOpt ) | 92 | if( bSubOpt ) |
93 | { | 93 | { |
94 | pClient->peek( &bc, 1 ); | 94 | pClient->peek( &bc, 1 ); |
95 | if( bc == CODE_IAC ) | 95 | if( bc == CODE_IAC ) |
96 | { | 96 | { |
97 | if( iLeft <= 1 ) return; | 97 | if( iLeft <= 1 ) return; |
98 | char bc2; | 98 | char bc2; |
99 | printCode( CODE_IAC ); | 99 | printCode( CODE_IAC ); |
100 | pClient->peek( &bc2, 1, 1 ); | 100 | pClient->peek( &bc2, 1, 1 ); |
101 | printCode( bc2 ); | 101 | printCode( bc2 ); |
102 | if( bc2 == CODE_SE ) | 102 | if( bc2 == CODE_SE ) |
103 | { | 103 | { |
104 | bSubOpt = false; | 104 | bSubOpt = false; |
105 | onSubOpt(); | 105 | onSubOpt(); |
106 | } | 106 | } |
107 | else if( bc2 == CODE_IAC ) | 107 | else if( bc2 == CODE_IAC ) |
108 | { | 108 | { |
109 | sSubBuf += CODE_IAC; | 109 | sSubBuf += CODE_IAC; |
110 | } | 110 | } |
111 | else | 111 | else |
112 | { | 112 | { |
113 | // Error of some sort. | 113 | // Error of some sort. |
114 | } | 114 | } |
115 | pClient->seek( 1 ); | 115 | pClient->seek( 1 ); |
116 | } | 116 | } |
117 | else | 117 | else |
118 | { | 118 | { |
119 | sSubBuf += bc; | 119 | sSubBuf += bc; |
120 | } | 120 | } |
121 | pClient->seek( 1 ); | 121 | pClient->seek( 1 ); |
122 | } | 122 | } |
123 | else | 123 | else |
124 | { | 124 | { |
125 | pClient->peek( &bc, 1 ); | 125 | pClient->peek( &bc, 1 ); |
126 | if( bc == CODE_IAC ) | 126 | if( bc == CODE_IAC ) |
127 | { | 127 | { |
128 | if( iLeft <= 1 ) return; | 128 | if( iLeft <= 1 ) return; |
129 | char bc2; | 129 | char bc2; |
130 | pClient->peek( &bc2, 1, 1 ); | 130 | pClient->peek( &bc2, 1, 1 ); |
131 | printCode( bc ); | 131 | printCode( bc ); |
132 | printCode( bc2 ); | 132 | printCode( bc2 ); |
133 | 133 | ||
134 | switch( bc2 ) | 134 | switch( bc2 ) |
135 | { | 135 | { |
136 | case CODE_WILL: | 136 | case CODE_WILL: |
137 | if( iLeft <= 2 ) return; | 137 | if( iLeft <= 2 ) return; |
138 | { | 138 | { |
139 | char bc3; | 139 | char bc3; |
140 | pClient->peek( &bc3, 1, 2 ); | 140 | pClient->peek( &bc3, 1, 2 ); |
141 | pClient->seek( 1 ); | 141 | pClient->seek( 1 ); |
142 | printOpt( bc3 ); | 142 | printOpt( bc3 ); |
143 | onWill( bc3 ); | 143 | onWill( bc3 ); |
144 | } | 144 | } |
145 | break; | 145 | break; |
146 | 146 | ||
147 | case CODE_WONT: | 147 | case CODE_WONT: |
148 | if( iLeft <= 2 ) return; | 148 | if( iLeft <= 2 ) return; |
149 | { | 149 | { |
150 | char bc3; | 150 | char bc3; |
151 | pClient->peek( &bc3, 1, 2 ); | 151 | pClient->peek( &bc3, 1, 2 ); |
152 | pClient->seek( 1 ); | 152 | pClient->seek( 1 ); |
153 | printOpt( bc3 ); | 153 | printOpt( bc3 ); |
154 | onWont( bc3 ); | 154 | onWont( bc3 ); |
155 | } | 155 | } |
156 | break; | 156 | break; |
157 | 157 | ||
158 | case CODE_DO: | 158 | case CODE_DO: |
159 | if( iLeft <= 2 ) return; | 159 | if( iLeft <= 2 ) return; |
160 | { | 160 | { |
161 | char bc3; | 161 | char bc3; |
162 | pClient->peek( &bc3, 1, 2 ); | 162 | pClient->peek( &bc3, 1, 2 ); |
163 | pClient->seek( 1 ); | 163 | pClient->seek( 1 ); |
164 | printOpt( bc3 ); | 164 | printOpt( bc3 ); |
165 | onDo( bc3 ); | 165 | onDo( bc3 ); |
166 | } | 166 | } |
167 | break; | 167 | break; |
168 | 168 | ||
169 | case CODE_DONT: | 169 | case CODE_DONT: |
170 | if( iLeft <= 2 ) return; | 170 | if( iLeft <= 2 ) return; |
171 | { | 171 | { |
172 | char bc3; | 172 | char bc3; |
173 | pClient->peek( &bc3, 1, 2 ); | 173 | pClient->peek( &bc3, 1, 2 ); |
174 | pClient->seek( 1 ); | 174 | pClient->seek( 1 ); |
175 | printOpt( bc3 ); | 175 | printOpt( bc3 ); |
176 | onDont( bc3 ); | 176 | onDont( bc3 ); |
177 | } | 177 | } |
178 | break; | 178 | break; |
179 | 179 | ||
180 | case CODE_SB: | 180 | case CODE_SB: |
181 | if( iLeft <= 2 ) return; | 181 | if( iLeft <= 2 ) return; |
182 | { | 182 | { |
183 | pClient->peek( &cSubOpt, 1, 2 ); | 183 | pClient->peek( &cSubOpt, 1, 2 ); |
184 | pClient->seek( 1 ); | 184 | pClient->seek( 1 ); |
185 | printOpt( cSubOpt ); | 185 | printOpt( cSubOpt ); |
186 | bSubOpt = true; | 186 | bSubOpt = true; |
187 | } | 187 | } |
188 | break; | 188 | break; |
189 | 189 | ||
190 | case CODE_IAC: | 190 | case CODE_IAC: |
191 | sDataBuf += CODE_IAC; | 191 | sDataBuf += CODE_IAC; |
192 | printCode( CODE_IAC ); | 192 | printCode( CODE_IAC ); |
193 | break; | 193 | break; |
194 | } | 194 | } |
195 | pClient->seek( 1 ); | 195 | pClient->seek( 1 ); |
196 | #ifdef __TELNET_DEBUG | 196 | #ifdef __TELNET_DEBUG |
197 | printf("\n"); | 197 | printf("\n"); |
198 | #endif | 198 | #endif |
199 | } | 199 | } |
200 | else if( bc == CODE_SB ) | 200 | else if( bc == CODE_SB ) |
201 | { | 201 | { |
202 | } | 202 | } |
203 | else | 203 | else |
204 | { | 204 | { |
205 | // This is where control code handling goes | 205 | // This is where control code handling goes |
206 | // Also, possibly, character code conversion, although I'm not | 206 | // Also, possibly, character code conversion, although I'm not |
207 | // sure that really matters anymore, go ASCII/UTF-8 | 207 | // sure that really matters anymore, go ASCII/UTF-8 |
208 | if( bCanonical ) | 208 | if( bCanonical ) |
209 | { | 209 | { |
210 | if( bc < 0x20 || bc >= CH_DEL ) | 210 | if( bc < 0x20 || bc >= CH_DEL ) |
211 | { | 211 | { |
212 | if( bc == CH_CR ) | 212 | if( bc == CH_CR ) |
213 | { | 213 | { |
214 | if( iLeft <= 1 ) return; | 214 | if( iLeft <= 1 ) return; |
215 | char bc2; | 215 | char bc2; |
216 | pClient->peek( &bc2, 1, 1 ); | 216 | pClient->peek( &bc2, 1, 1 ); |
217 | if( bc2 == CH_NUL || bc2 == CH_LF ) | 217 | if( bc2 == CH_NUL || bc2 == CH_LF ) |
218 | { | 218 | { |
219 | onCtlChar( bc ); | 219 | onCtlChar( bc ); |
220 | gotLine( sDataBuf ); | 220 | gotLine( sDataBuf ); |
221 | sDataBuf.clear(); | 221 | sDataBuf.clear(); |
222 | } | 222 | } |
223 | pClient->seek( 1 ); | 223 | pClient->seek( 1 ); |
224 | } | 224 | } |
225 | else | 225 | else |
226 | { | 226 | { |
227 | onCtlChar( bc ); | 227 | onCtlChar( bc ); |
228 | } | 228 | } |
229 | } | 229 | } |
230 | else | 230 | else |
231 | { | 231 | { |
232 | sDataBuf += bc; | 232 | sDataBuf += bc; |
233 | if( oEcho.isLocalSet() ) | 233 | if( oEcho.isLocalSet() ) |
234 | { | 234 | { |
235 | pClient->write( &bc, 1 ); | 235 | pClient->write( &bc, 1 ); |
236 | #ifdef __TELNET_DEBUG | 236 | #ifdef __TELNET_DEBUG |
237 | printf("%c", bc ); | 237 | printf("%c", bc ); |
238 | fflush( stdout ); | 238 | fflush( stdout ); |
239 | #endif | 239 | #endif |
240 | } | 240 | } |
241 | } | 241 | } |
242 | } | 242 | } |
243 | else | 243 | else |
244 | { | 244 | { |
245 | sDataBuf += bc; | 245 | sDataBuf += bc; |
246 | if( oEcho.isLocalSet() ) | 246 | if( oEcho.isLocalSet() ) |
247 | { | 247 | { |
248 | pClient->write( &bc, 1 ); | 248 | pClient->write( &bc, 1 ); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | } | 251 | } |
252 | pClient->seek( 1 ); | 252 | pClient->seek( 1 ); |
253 | } | 253 | } |
254 | } | 254 | } |
255 | 255 | ||
256 | // It's true, this code will not be executed if we only have half of an | 256 | // It's true, this code will not be executed if we only have half of an |
257 | // IAC code or multibyte escape sequence or something, but then again, it | 257 | // IAC code or multibyte escape sequence or something, but then again, it |
258 | // shouldn't be called then, and really, shouldn't be, it'll be called soon | 258 | // shouldn't be called then, and really, shouldn't be, it'll be called soon |
259 | // enough, when we get the rest of that code. | 259 | // enough, when we get the rest of that code. |
260 | if( !bCanonical ) | 260 | if( !bCanonical ) |
261 | { | 261 | { |
262 | gotData( sDataBuf ); | 262 | gotData( sDataBuf ); |
263 | } | 263 | } |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::ProtocolTelnet::setCanonical( bool bCon ) | 266 | void Bu::ProtocolTelnet::setCanonical( bool bCon ) |
267 | { | 267 | { |
268 | bCanonical = bCon; | 268 | bCanonical = bCon; |
269 | } | 269 | } |
270 | 270 | ||
271 | bool Bu::ProtocolTelnet::isCanonical() | 271 | bool Bu::ProtocolTelnet::isCanonical() |
272 | { | 272 | { |
273 | return bCanonical; | 273 | return bCanonical; |
274 | } | 274 | } |
275 | 275 | ||
276 | void Bu::ProtocolTelnet::write( const Bu::String &sData ) | 276 | void Bu::ProtocolTelnet::write( const Bu::String &sData ) |
277 | { | 277 | { |
278 | write( sData.getStr(), sData.getSize() ); | 278 | write( sData.getStr(), sData.getSize() ); |
279 | } | 279 | } |
280 | 280 | ||
281 | void Bu::ProtocolTelnet::write( const char *pData, int iSize ) | 281 | void Bu::ProtocolTelnet::write( const char *pData, int iSize ) |
282 | { | 282 | { |
283 | int iLast = 0, j; | 283 | int iLast = 0, j; |
284 | for( j = iLast; j < iSize; j++ ) | 284 | for( j = iLast; j < iSize; j++ ) |
285 | { | 285 | { |
286 | if( pData[j] == '\n' ) | 286 | if( pData[j] == '\n' ) |
287 | { | 287 | { |
288 | if( j+1 >= iSize || | 288 | if( j+1 >= iSize || |
289 | (pData[j+1] != '\r' && pData[j+1] != '\0') ) | 289 | (pData[j+1] != '\r' && pData[j+1] != '\0') ) |
290 | { | 290 | { |
291 | pClient->write( pData+iLast, j-iLast ); | 291 | pClient->write( pData+iLast, j-iLast ); |
292 | pClient->write( "\n\r", 2 ); | 292 | pClient->write( "\n\r", 2 ); |
293 | iLast = j+1; | 293 | iLast = j+1; |
294 | } | 294 | } |
295 | else | 295 | else |
296 | { | 296 | { |
297 | j++; | 297 | j++; |
298 | } | 298 | } |
299 | } | 299 | } |
300 | } | 300 | } |
301 | if( j > iLast ) | 301 | if( j > iLast ) |
302 | { | 302 | { |
303 | pClient->write( pData+iLast, iSize-iLast ); | 303 | pClient->write( pData+iLast, iSize-iLast ); |
304 | } | 304 | } |
305 | //pClient->write( pData, iSize ); | 305 | //pClient->write( pData, iSize ); |
306 | } | 306 | } |
307 | 307 | ||
308 | void Bu::ProtocolTelnet::write( char cData ) | 308 | void Bu::ProtocolTelnet::write( char cData ) |
309 | { | 309 | { |
310 | write( &cData, 1 ); | 310 | write( &cData, 1 ); |
311 | } | 311 | } |
312 | 312 | ||
313 | void Bu::ProtocolTelnet::onWill( char cCode ) | 313 | void Bu::ProtocolTelnet::onWill( char cCode ) |
314 | { | 314 | { |
315 | try | 315 | try |
316 | { | 316 | { |
317 | Option *pOpt = hOpts[cCode]; | 317 | Option *pOpt = hOpts[cCode]; |
318 | if( pOpt->isRemoteEnabled() ) | 318 | if( pOpt->isRemoteEnabled() ) |
319 | { | 319 | { |
320 | pOpt->fOpts |= Option::fRemoteIs; | 320 | pOpt->fOpts |= Option::fRemoteIs; |
321 | char buf[3] = { CODE_IAC, CODE_DO, cCode }; | 321 | char buf[3] = { CODE_IAC, CODE_DO, cCode }; |
322 | pClient->write( buf, 3 ); | 322 | pClient->write( buf, 3 ); |
323 | } | 323 | } |
324 | else | 324 | else |
325 | { | 325 | { |
326 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 326 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
327 | pClient->write( buf, 3 ); | 327 | pClient->write( buf, 3 ); |
328 | } | 328 | } |
329 | 329 | ||
330 | } | 330 | } |
331 | catch( Bu::HashException &e ) | 331 | catch( Bu::HashException &e ) |
332 | { | 332 | { |
333 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 333 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
334 | pClient->write( buf, 3 ); | 334 | pClient->write( buf, 3 ); |
335 | } | 335 | } |
336 | } | 336 | } |
337 | 337 | ||
338 | void Bu::ProtocolTelnet::onWont( char cCode ) | 338 | void Bu::ProtocolTelnet::onWont( char cCode ) |
339 | { | 339 | { |
340 | try | 340 | try |
341 | { | 341 | { |
342 | Option *pOpt = hOpts[cCode]; | 342 | Option *pOpt = hOpts[cCode]; |
343 | 343 | ||
344 | pOpt->fOpts &= ~Option::fRemoteIs; | 344 | pOpt->fOpts &= ~Option::fRemoteIs; |
345 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 345 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
346 | pClient->write( buf, 3 ); | 346 | pClient->write( buf, 3 ); |
347 | } | 347 | } |
348 | catch( Bu::HashException &e ) | 348 | catch( Bu::HashException &e ) |
349 | { | 349 | { |
350 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 350 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
351 | pClient->write( buf, 3 ); | 351 | pClient->write( buf, 3 ); |
352 | } | 352 | } |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::ProtocolTelnet::onDo( char cCode ) | 355 | void Bu::ProtocolTelnet::onDo( char cCode ) |
356 | { | 356 | { |
357 | try | 357 | try |
358 | { | 358 | { |
359 | Option *pOpt = hOpts[cCode]; | 359 | Option *pOpt = hOpts[cCode]; |
360 | if( pOpt->isLocalEnabled() ) | 360 | if( pOpt->isLocalEnabled() ) |
361 | { | 361 | { |
362 | pOpt->fOpts |= Option::fLocalIs; | 362 | pOpt->fOpts |= Option::fLocalIs; |
363 | char buf[3] = { CODE_IAC, CODE_WILL, cCode }; | 363 | char buf[3] = { CODE_IAC, CODE_WILL, cCode }; |
364 | pClient->write( buf, 3 ); | 364 | pClient->write( buf, 3 ); |
365 | } | 365 | } |
366 | else | 366 | else |
367 | { | 367 | { |
368 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; | 368 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; |
369 | pClient->write( buf, 3 ); | 369 | pClient->write( buf, 3 ); |
370 | } | 370 | } |
371 | 371 | ||
372 | } | 372 | } |
373 | catch( Bu::HashException &e ) | 373 | catch( Bu::HashException &e ) |
374 | { | 374 | { |
375 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; | 375 | char buf[3] = { CODE_IAC, CODE_WONT, cCode }; |
376 | pClient->write( buf, 3 ); | 376 | pClient->write( buf, 3 ); |
377 | } | 377 | } |
378 | } | 378 | } |
379 | 379 | ||
380 | void Bu::ProtocolTelnet::onDont( char cCode ) | 380 | void Bu::ProtocolTelnet::onDont( char cCode ) |
381 | { | 381 | { |
382 | try | 382 | try |
383 | { | 383 | { |
384 | Option *pOpt = hOpts[cCode]; | 384 | Option *pOpt = hOpts[cCode]; |
385 | 385 | ||
386 | pOpt->fOpts &= ~Option::fLocalIs; | 386 | pOpt->fOpts &= ~Option::fLocalIs; |
387 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 387 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
388 | pClient->write( buf, 3 ); | 388 | pClient->write( buf, 3 ); |
389 | } | 389 | } |
390 | catch( Bu::HashException &e ) | 390 | catch( Bu::HashException &e ) |
391 | { | 391 | { |
392 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; | 392 | char buf[3] = { CODE_IAC, CODE_DONT, cCode }; |
393 | pClient->write( buf, 3 ); | 393 | pClient->write( buf, 3 ); |
394 | } | 394 | } |
395 | } | 395 | } |
396 | 396 | ||
397 | void Bu::ProtocolTelnet::onSubOpt() | 397 | void Bu::ProtocolTelnet::onSubOpt() |
398 | { | 398 | { |
399 | switch( cSubOpt ) | 399 | switch( cSubOpt ) |
400 | { | 400 | { |
401 | case OPT_NAWS: | 401 | case OPT_NAWS: |
402 | { | 402 | { |
403 | uint16_t iWidth, iHeight; | 403 | uint16_t iWidth, iHeight; |
404 | ((char *)&iWidth)[1] = sSubBuf[0]; | 404 | ((char *)&iWidth)[1] = sSubBuf[0]; |
405 | ((char *)&iWidth)[0] = sSubBuf[1]; | 405 | ((char *)&iWidth)[0] = sSubBuf[1]; |
406 | ((char *)&iHeight)[1] = sSubBuf[2]; | 406 | ((char *)&iHeight)[1] = sSubBuf[2]; |
407 | ((char *)&iHeight)[0] = sSubBuf[3]; | 407 | ((char *)&iHeight)[0] = sSubBuf[3]; |
408 | onSubNAWS( iWidth, iHeight ); | 408 | onSubNAWS( iWidth, iHeight ); |
409 | } | 409 | } |
410 | break; | 410 | break; |
411 | 411 | ||
412 | default: | 412 | default: |
413 | onSubUnknown( cSubOpt, sSubBuf ); | 413 | onSubUnknown( cSubOpt, sSubBuf ); |
414 | break; | 414 | break; |
415 | } | 415 | } |
416 | 416 | ||
417 | sSubBuf.clear(); | 417 | sSubBuf.clear(); |
418 | } | 418 | } |
419 | 419 | ||
420 | void Bu::ProtocolTelnet::onCtlChar( char cChr ) | 420 | void Bu::ProtocolTelnet::onCtlChar( char cChr ) |
421 | { | 421 | { |
422 | #ifdef __TELNET_DEBUG | 422 | #ifdef __TELNET_DEBUG |
423 | switch( cChr ) | 423 | switch( cChr ) |
424 | { | 424 | { |
425 | case CH_NUL: printf("NUL "); break; | 425 | case CH_NUL: printf("NUL "); break; |
426 | case CH_SOH: printf("SOH "); break; | 426 | case CH_SOH: printf("SOH "); break; |
427 | case CH_STX: printf("STX "); break; | 427 | case CH_STX: printf("STX "); break; |
428 | case CH_ETX: printf("ETX "); break; | 428 | case CH_ETX: printf("ETX "); break; |
429 | case CH_EOT: printf("EOT "); break; | 429 | case CH_EOT: printf("EOT "); break; |
430 | case CH_ENQ: printf("ENQ "); break; | 430 | case CH_ENQ: printf("ENQ "); break; |
431 | case CH_ACK: printf("ACK "); break; | 431 | case CH_ACK: printf("ACK "); break; |
432 | case CH_BEL: printf("BEL "); break; | 432 | case CH_BEL: printf("BEL "); break; |
433 | case CH_BS: printf("BS "); break; | 433 | case CH_BS: printf("BS "); break; |
434 | case CH_TAB: printf("TAB "); break; | 434 | case CH_TAB: printf("TAB "); break; |
435 | case CH_LF: printf("LF "); break; | 435 | case CH_LF: printf("LF "); break; |
436 | case CH_VT: printf("VT "); break; | 436 | case CH_VT: printf("VT "); break; |
437 | case CH_FF: printf("FF "); break; | 437 | case CH_FF: printf("FF "); break; |
438 | case CH_CR: printf("CR "); break; | 438 | case CH_CR: printf("CR "); break; |
439 | case CH_ESC: printf("ESC "); break; | 439 | case CH_ESC: printf("ESC "); break; |
440 | case CH_DEL: printf("DEL "); break; | 440 | case CH_DEL: printf("DEL "); break; |
441 | default: printf("!![%02x] ", cChr ); break; | 441 | default: printf("!![%02x] ", cChr ); break; |
442 | } | 442 | } |
443 | fflush( stdout ); | 443 | fflush( stdout ); |
444 | #endif | 444 | #endif |
445 | 445 | ||
446 | switch( cChr ) | 446 | switch( cChr ) |
447 | { | 447 | { |
448 | case CH_DEL: | 448 | case CH_DEL: |
449 | { | 449 | { |
450 | if( sDataBuf.getSize() > 0 ) | 450 | if( sDataBuf.getSize() > 0 ) |
451 | { | 451 | { |
452 | sDataBuf.resize( sDataBuf.getSize()-1 ); | 452 | sDataBuf.resize( sDataBuf.getSize()-1 ); |
453 | char buf[3] = { CH_BS, ' ', CH_BS }; | 453 | char buf[3] = { CH_BS, ' ', CH_BS }; |
454 | pClient->write( buf, 3 ); | 454 | pClient->write( buf, 3 ); |
455 | } | 455 | } |
456 | } | 456 | } |
457 | break; | 457 | break; |
458 | 458 | ||
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | #ifdef __TELNET_DEBUG | 462 | #ifdef __TELNET_DEBUG |
463 | void Bu::ProtocolTelnet::printCode( char cCode ) | 463 | void Bu::ProtocolTelnet::printCode( char cCode ) |
464 | { | 464 | { |
465 | switch( cCode ) | 465 | switch( cCode ) |
466 | { | 466 | { |
467 | case CODE_SE: printf("SE "); break; | 467 | case CODE_SE: printf("SE "); break; |
468 | case CODE_NOP: printf("NOP "); break; | 468 | case CODE_NOP: printf("NOP "); break; |
469 | case CODE_DM: printf("DM "); break; | 469 | case CODE_DM: printf("DM "); break; |
470 | case CODE_BRK: printf("BRK "); break; | 470 | case CODE_BRK: printf("BRK "); break; |
471 | case CODE_IP: printf("IP "); break; | 471 | case CODE_IP: printf("IP "); break; |
472 | case CODE_AO: printf("AO "); break; | 472 | case CODE_AO: printf("AO "); break; |
473 | case CODE_AYT: printf("AYT "); break; | 473 | case CODE_AYT: printf("AYT "); break; |
474 | case CODE_EC: printf("EC "); break; | 474 | case CODE_EC: printf("EC "); break; |
475 | case CODE_EL: printf("EL "); break; | 475 | case CODE_EL: printf("EL "); break; |
476 | case CODE_GA: printf("GA "); break; | 476 | case CODE_GA: printf("GA "); break; |
477 | case CODE_SB: printf("SB "); break; | 477 | case CODE_SB: printf("SB "); break; |
478 | case CODE_WILL: printf("WILL "); break; | 478 | case CODE_WILL: printf("WILL "); break; |
479 | case CODE_WONT: printf("WONT "); break; | 479 | case CODE_WONT: printf("WONT "); break; |
480 | case CODE_DO: printf("DO "); break; | 480 | case CODE_DO: printf("DO "); break; |
481 | case CODE_DONT: printf("DONT "); break; | 481 | case CODE_DONT: printf("DONT "); break; |
482 | case CODE_IAC: printf("IAC "); break; | 482 | case CODE_IAC: printf("IAC "); break; |
483 | default: printf("??%02x ", cCode ); break; | 483 | default: printf("??%02x ", cCode ); break; |
484 | } | 484 | } |
485 | fflush( stdout ); | 485 | fflush( stdout ); |
486 | } | 486 | } |
487 | 487 | ||
488 | void Bu::ProtocolTelnet::printOpt( char cOpt ) | 488 | void Bu::ProtocolTelnet::printOpt( char cOpt ) |
489 | { | 489 | { |
490 | switch( cOpt ) | 490 | switch( cOpt ) |
491 | { | 491 | { |
492 | case OPT_BINARY: printf("BINARY "); break; | 492 | case OPT_BINARY: printf("BINARY "); break; |
493 | case OPT_ECHO: printf("ECHO "); break; | 493 | case OPT_ECHO: printf("ECHO "); break; |
494 | case OPT_SUPGA: printf("SUPGA "); break; | 494 | case OPT_SUPGA: printf("SUPGA "); break; |
495 | case OPT_STATUS: printf("STATUS "); break; | 495 | case OPT_STATUS: printf("STATUS "); break; |
496 | case OPT_TIMING: printf("TIMING "); break; | 496 | case OPT_TIMING: printf("TIMING "); break; |
497 | case OPT_EXASCII: printf("EXASCII "); break; | 497 | case OPT_EXASCII: printf("EXASCII "); break; |
498 | case OPT_LOGOUT: printf("LOGOUT "); break; | 498 | case OPT_LOGOUT: printf("LOGOUT "); break; |
499 | case OPT_TTYPE: printf("TTYPE "); break; | 499 | case OPT_TTYPE: printf("TTYPE "); break; |
500 | case OPT_NAWS: printf("NAWS "); break; | 500 | case OPT_NAWS: printf("NAWS "); break; |
501 | case OPT_TSPEED: printf("TSPEED "); break; | 501 | case OPT_TSPEED: printf("TSPEED "); break; |
502 | case OPT_NEWENV: printf("NEWENV "); break; | 502 | case OPT_NEWENV: printf("NEWENV "); break; |
503 | case OPT_EXOPL: printf("EXOPL "); break; | 503 | case OPT_EXOPL: printf("EXOPL "); break; |
504 | default: printf("??%02x ", cOpt); break; | 504 | default: printf("??%02x ", cOpt); break; |
505 | } | 505 | } |
506 | fflush( stdout ); | 506 | fflush( stdout ); |
507 | } | 507 | } |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : | 510 | Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : |
511 | rPT( rPT ), | 511 | rPT( rPT ), |
512 | fOpts( 0 ), | 512 | fOpts( 0 ), |
513 | cCode( cCode ) | 513 | cCode( cCode ) |
514 | { | 514 | { |
515 | rPT.hOpts.insert( cCode, this ); | 515 | rPT.hOpts.insert( cCode, this ); |
516 | } | 516 | } |
517 | 517 | ||
518 | Bu::ProtocolTelnet::Option::~Option() | 518 | Bu::ProtocolTelnet::Option::~Option() |
@@ -521,100 +521,100 @@ Bu::ProtocolTelnet::Option::~Option() | |||
521 | 521 | ||
522 | void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) | 522 | void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) |
523 | { | 523 | { |
524 | if( bSet == (bool)(!(fOpts&fLocalCant)) ) return; | 524 | if( bSet == (bool)(!(fOpts&fLocalCant)) ) return; |
525 | 525 | ||
526 | if( bSet ) | 526 | if( bSet ) |
527 | fOpts &= ~fLocalCant; | 527 | fOpts &= ~fLocalCant; |
528 | else | 528 | else |
529 | fOpts |= fLocalCant; | 529 | fOpts |= fLocalCant; |
530 | } | 530 | } |
531 | 531 | ||
532 | void Bu::ProtocolTelnet::Option::localSet( bool bSet ) | 532 | void Bu::ProtocolTelnet::Option::localSet( bool bSet ) |
533 | { | 533 | { |
534 | if( bSet == (bool)(fOpts&fLocalIs) ) return; | 534 | if( bSet == (bool)(fOpts&fLocalIs) ) return; |
535 | 535 | ||
536 | char buf[3] = { CODE_IAC, 0, cCode }; | 536 | char buf[3] = { CODE_IAC, 0, cCode }; |
537 | 537 | ||
538 | if( bSet ) | 538 | if( bSet ) |
539 | { | 539 | { |
540 | buf[1] = CODE_WILL; | 540 | buf[1] = CODE_WILL; |
541 | rPT.pClient->write( buf, 3 ); | 541 | rPT.pClient->write( buf, 3 ); |
542 | #ifdef __TELNET_DEBUG | 542 | #ifdef __TELNET_DEBUG |
543 | printf("<= "); | 543 | printf("<= "); |
544 | rPT.printCode( buf[0] ); | 544 | rPT.printCode( buf[0] ); |
545 | rPT.printCode( buf[1] ); | 545 | rPT.printCode( buf[1] ); |
546 | rPT.printOpt( buf[2] ); | 546 | rPT.printOpt( buf[2] ); |
547 | printf("\n"); | 547 | printf("\n"); |
548 | #endif | 548 | #endif |
549 | } | 549 | } |
550 | else | 550 | else |
551 | { | 551 | { |
552 | buf[1] = CODE_WONT; | 552 | buf[1] = CODE_WONT; |
553 | rPT.pClient->write( buf, 3 ); | 553 | rPT.pClient->write( buf, 3 ); |
554 | #ifdef __TELNET_DEBUG | 554 | #ifdef __TELNET_DEBUG |
555 | printf("<= "); | 555 | printf("<= "); |
556 | rPT.printCode( buf[0] ); | 556 | rPT.printCode( buf[0] ); |
557 | rPT.printCode( buf[1] ); | 557 | rPT.printCode( buf[1] ); |
558 | rPT.printOpt( buf[2] ); | 558 | rPT.printOpt( buf[2] ); |
559 | printf("\n"); | 559 | printf("\n"); |
560 | #endif | 560 | #endif |
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | bool Bu::ProtocolTelnet::Option::isLocalEnabled() | 564 | bool Bu::ProtocolTelnet::Option::isLocalEnabled() |
565 | { | 565 | { |
566 | return (bool)(!(fOpts&fLocalCant)); | 566 | return (bool)(!(fOpts&fLocalCant)); |
567 | } | 567 | } |
568 | 568 | ||
569 | bool Bu::ProtocolTelnet::Option::isLocalSet() | 569 | bool Bu::ProtocolTelnet::Option::isLocalSet() |
570 | { | 570 | { |
571 | return (bool)(fOpts&fLocalIs); | 571 | return (bool)(fOpts&fLocalIs); |
572 | } | 572 | } |
573 | 573 | ||
574 | void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) | 574 | void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) |
575 | { | 575 | { |
576 | return; | 576 | return; |
577 | } | 577 | } |
578 | 578 | ||
579 | void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) | 579 | void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) |
580 | { | 580 | { |
581 | //if( bSet == (bool)(fOpts&fRemoteIs) ) return; | 581 | //if( bSet == (bool)(fOpts&fRemoteIs) ) return; |
582 | 582 | ||
583 | char buf[3] = { CODE_IAC, 0, cCode }; | 583 | char buf[3] = { CODE_IAC, 0, cCode }; |
584 | 584 | ||
585 | if( bSet ) | 585 | if( bSet ) |
586 | { | 586 | { |
587 | buf[1] = CODE_DO; | 587 | buf[1] = CODE_DO; |
588 | rPT.pClient->write( buf, 3 ); | 588 | rPT.pClient->write( buf, 3 ); |
589 | #ifdef __TELNET_DEBUG | 589 | #ifdef __TELNET_DEBUG |
590 | printf("<= "); | 590 | printf("<= "); |
591 | rPT.printCode( buf[0] ); | 591 | rPT.printCode( buf[0] ); |
592 | rPT.printCode( buf[1] ); | 592 | rPT.printCode( buf[1] ); |
593 | rPT.printOpt( buf[2] ); | 593 | rPT.printOpt( buf[2] ); |
594 | printf("\n"); | 594 | printf("\n"); |
595 | #endif | 595 | #endif |
596 | } | 596 | } |
597 | else | 597 | else |
598 | { | 598 | { |
599 | buf[1] = CODE_DONT; | 599 | buf[1] = CODE_DONT; |
600 | rPT.pClient->write( buf, 3 ); | 600 | rPT.pClient->write( buf, 3 ); |
601 | #ifdef __TELNET_DEBUG | 601 | #ifdef __TELNET_DEBUG |
602 | printf("<= "); | 602 | printf("<= "); |
603 | rPT.printCode( buf[0] ); | 603 | rPT.printCode( buf[0] ); |
604 | rPT.printCode( buf[1] ); | 604 | rPT.printCode( buf[1] ); |
605 | rPT.printOpt( buf[2] ); | 605 | rPT.printOpt( buf[2] ); |
606 | printf("\n"); | 606 | printf("\n"); |
607 | #endif | 607 | #endif |
608 | } | 608 | } |
609 | } | 609 | } |
610 | 610 | ||
611 | bool Bu::ProtocolTelnet::Option::isRemoteEnabled() | 611 | bool Bu::ProtocolTelnet::Option::isRemoteEnabled() |
612 | { | 612 | { |
613 | return (bool)(!(fOpts&fRemoteCant)); | 613 | return (bool)(!(fOpts&fRemoteCant)); |
614 | } | 614 | } |
615 | 615 | ||
616 | bool Bu::ProtocolTelnet::Option::isRemoteSet() | 616 | bool Bu::ProtocolTelnet::Option::isRemoteSet() |
617 | { | 617 | { |
618 | return (bool)(fOpts&fRemoteIs); | 618 | return (bool)(fOpts&fRemoteIs); |
619 | } | 619 | } |
620 | 620 | ||
diff --git a/src/stable/protocoltelnet.h b/src/stable/protocoltelnet.h index 9a13496..b212303 100644 --- a/src/stable/protocoltelnet.h +++ b/src/stable/protocoltelnet.h | |||
@@ -16,205 +16,205 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | /** | 19 | /** |
20 | * Telnet Protocol handler. This attempts to provide useful and general | 20 | * Telnet Protocol handler. This attempts to provide useful and general |
21 | * support for most of the most commonly used Telnet extensions in a simple | 21 | * support for most of the most commonly used Telnet extensions in a simple |
22 | * and easy to use way. The Option variables control the settings that can | 22 | * and easy to use way. The Option variables control the settings that can |
23 | * be used on the line, and control which virtual "callbacks" will be called | 23 | * be used on the line, and control which virtual "callbacks" will be called |
24 | * when different events happen. | 24 | * when different events happen. |
25 | * | 25 | * |
26 | * To setup initial values and to disable any options you wish override the | 26 | * To setup initial values and to disable any options you wish override the |
27 | * onNewConnection function in your own class, like this: | 27 | * onNewConnection function in your own class, like this: |
28 | *@code | 28 | *@code |
29 | class MyTelnet : public Bu::ProtocolTelnet | 29 | class MyTelnet : public Bu::ProtocolTelnet |
30 | { | 30 | { |
31 | public: | 31 | public: |
32 | ... | 32 | ... |
33 | 33 | ||
34 | virtual void onNewConnection( class Bu::Client *pClient ) | 34 | virtual void onNewConnection( class Bu::Client *pClient ) |
35 | { | 35 | { |
36 | // Call the parent class' onNewConnection to get everything all | 36 | // Call the parent class' onNewConnection to get everything all |
37 | // set up. | 37 | // set up. |
38 | Bu::ProtocolTelnet::onNewConnection( pClient ); | 38 | Bu::ProtocolTelnet::onNewConnection( pClient ); |
39 | 39 | ||
40 | // These functions disable the option to send files via telnet, | 40 | // These functions disable the option to send files via telnet, |
41 | // disabling the remote option means that we won't accept this | 41 | // disabling the remote option means that we won't accept this |
42 | // option (binary data being sent to us) from the client. | 42 | // option (binary data being sent to us) from the client. |
43 | // | 43 | // |
44 | // Disabling the local option means that the client cannot ask us | 44 | // Disabling the local option means that the client cannot ask us |
45 | // to send them binary data. | 45 | // to send them binary data. |
46 | oBinary.enableRemote( false ); | 46 | oBinary.enableRemote( false ); |
47 | oBinary.enableLocal( false ); | 47 | oBinary.enableLocal( false ); |
48 | 48 | ||
49 | // This requests that the client send us window size updates | 49 | // This requests that the client send us window size updates |
50 | // whenever the size of their window changes, and an initial set to | 50 | // whenever the size of their window changes, and an initial set to |
51 | // boot. | 51 | // boot. |
52 | // | 52 | // |
53 | // To see if this option is set later, try oNAWS.isRemoteSet(), but | 53 | // To see if this option is set later, try oNAWS.isRemoteSet(), but |
54 | // wait a little while, asking immediatly will always return false, | 54 | // wait a little while, asking immediatly will always return false, |
55 | // since the remote side has yet to receive our request. | 55 | // since the remote side has yet to receive our request. |
56 | oNAWS.remoteSet(); | 56 | oNAWS.remoteSet(); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | @endcode | 59 | @endcode |
60 | * | 60 | * |
61 | *@ingroup Serving | 61 | *@ingroup Serving |
62 | */ | 62 | */ |
63 | class ProtocolTelnet : public Protocol | 63 | class ProtocolTelnet : public Protocol |
64 | { | 64 | { |
65 | public: | 65 | public: |
66 | ProtocolTelnet(); | 66 | ProtocolTelnet(); |
67 | virtual ~ProtocolTelnet(); | 67 | virtual ~ProtocolTelnet(); |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * If you override this function in a child class, make sure to call | 70 | * If you override this function in a child class, make sure to call |
71 | * this version of it as the very first thing that you do, before you | 71 | * this version of it as the very first thing that you do, before you |
72 | * set any options. See the example in the class docs. | 72 | * set any options. See the example in the class docs. |
73 | */ | 73 | */ |
74 | virtual void onNewConnection( class Bu::Client *pClient ); | 74 | virtual void onNewConnection( class Bu::Client *pClient ); |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * You should never override this function unless you really, really | 77 | * You should never override this function unless you really, really |
78 | * know what you're doing. If you want to get data after each line | 78 | * know what you're doing. If you want to get data after each line |
79 | * entered (in canonical mode) or after any data arrives (non canonical | 79 | * entered (in canonical mode) or after any data arrives (non canonical |
80 | * mode) then override the gotLine and gotData functions, respectively. | 80 | * mode) then override the gotLine and gotData functions, respectively. |
81 | */ | 81 | */ |
82 | virtual void onNewData( class Bu::Client *pClient ); | 82 | virtual void onNewData( class Bu::Client *pClient ); |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Override this function to be notified of lines being submitted by | 85 | * Override this function to be notified of lines being submitted by |
86 | * the client. This function is only called in canonical mode, after | 86 | * the client. This function is only called in canonical mode, after |
87 | * all edits are performed on the data. In this mode weather you use | 87 | * all edits are performed on the data. In this mode weather you use |
88 | * the line or not, the data will be cleared from the buffer when this | 88 | * the line or not, the data will be cleared from the buffer when this |
89 | * function returns, any changes made to the buffer will be destroyed. | 89 | * function returns, any changes made to the buffer will be destroyed. |
90 | */ | 90 | */ |
91 | virtual void gotLine( Bu::String & /*sLine*/ ){}; | 91 | virtual void gotLine( Bu::String & /*sLine*/ ){}; |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * Override this function to be notified of any new data that comes in | 94 | * Override this function to be notified of any new data that comes in |
95 | * from the client. This function is only called in non-canonical mode, | 95 | * from the client. This function is only called in non-canonical mode, |
96 | * and includes all raw data minus telnet control codes and ansi | 96 | * and includes all raw data minus telnet control codes and ansi |
97 | * escape sequences. In this mode control of the buffer is up to the | 97 | * escape sequences. In this mode control of the buffer is up to the |
98 | * child class in this function, the buffer will never be cleared unless | 98 | * child class in this function, the buffer will never be cleared unless |
99 | * it happens in this function's override. | 99 | * it happens in this function's override. |
100 | */ | 100 | */ |
101 | virtual void gotData( Bu::String & /*sData*/ ){}; | 101 | virtual void gotData( Bu::String & /*sData*/ ){}; |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Using this function to enable or disable canonical mode only affects | 104 | * Using this function to enable or disable canonical mode only affects |
105 | * the way the data is processed and which virtual functions are called | 105 | * the way the data is processed and which virtual functions are called |
106 | * during processing. It does not affect options set locally or | 106 | * during processing. It does not affect options set locally or |
107 | * remotely. Setting this to false will enable char-at-a-time mode, | 107 | * remotely. Setting this to false will enable char-at-a-time mode, |
108 | * effectively disabling internal line-editing code. Characters | 108 | * effectively disabling internal line-editing code. Characters |
109 | * such as backspace that are detected will not be handled and will be | 109 | * such as backspace that are detected will not be handled and will be |
110 | * sent to the user override. The subclass will also be notified every | 110 | * sent to the user override. The subclass will also be notified every |
111 | * time new data is available, not just whole lines. | 111 | * time new data is available, not just whole lines. |
112 | * | 112 | * |
113 | * When set to true (the default), line editing control codes will be | 113 | * When set to true (the default), line editing control codes will be |
114 | * interpreted and used, and the subclass will only be notified when | 114 | * interpreted and used, and the subclass will only be notified when |
115 | * complete lines are available in the buffer. | 115 | * complete lines are available in the buffer. |
116 | */ | 116 | */ |
117 | void setCanonical( bool bCon=true ); | 117 | void setCanonical( bool bCon=true ); |
118 | bool isCanonical(); | 118 | bool isCanonical(); |
119 | 119 | ||
120 | void write( const Bu::String &sData ); | 120 | void write( const Bu::String &sData ); |
121 | void write( const char *pData, int iSize ); | 121 | void write( const char *pData, int iSize ); |
122 | void write( char cData ); | 122 | void write( char cData ); |
123 | 123 | ||
124 | const Bu::String &getBuffer() { return sDataBuf; } | 124 | const Bu::String &getBuffer() { return sDataBuf; } |
125 | 125 | ||
126 | public: | 126 | public: |
127 | /** | 127 | /** |
128 | * If you wish to know the current dimensions of the client window, | 128 | * If you wish to know the current dimensions of the client window, |
129 | * override this function, it will be called whenever the size changes. | 129 | * override this function, it will be called whenever the size changes. |
130 | */ | 130 | */ |
131 | virtual void onSubNAWS( uint16_t /*iWidth*/, uint16_t /*iHeight*/ ){}; | 131 | virtual void onSubNAWS( uint16_t /*iWidth*/, uint16_t /*iHeight*/ ){}; |
132 | 132 | ||
133 | /** | 133 | /** |
134 | * This function is called whenever an unknown sub negotiation option is | 134 | * This function is called whenever an unknown sub negotiation option is |
135 | * sent over the line. This doesn't mean that it's malformatted, it | 135 | * sent over the line. This doesn't mean that it's malformatted, it |
136 | * just means that this class doesn't support that option yet, but you | 136 | * just means that this class doesn't support that option yet, but you |
137 | * can handle it yourself if you'd like. Feel free to change the | 137 | * can handle it yourself if you'd like. Feel free to change the |
138 | * sSubBuf, it will be cleared as soon as this function returns anyway. | 138 | * sSubBuf, it will be cleared as soon as this function returns anyway. |
139 | */ | 139 | */ |
140 | virtual void onSubUnknown( char /*cSubOpt*/, | 140 | virtual void onSubUnknown( char /*cSubOpt*/, |
141 | Bu::String & /*sSubBuf*/ ){}; | 141 | Bu::String & /*sSubBuf*/ ){}; |
142 | 142 | ||
143 | private: | 143 | private: |
144 | /** | 144 | /** |
145 | * Represents a basic telnet option, either on or off, no parameters. | 145 | * Represents a basic telnet option, either on or off, no parameters. |
146 | * Each Option can negotiate effectively on it's own, and has two | 146 | * Each Option can negotiate effectively on it's own, and has two |
147 | * parameters in each of two classes. Both local and remote can be | 147 | * parameters in each of two classes. Both local and remote can be |
148 | * enabled/disabled and set/unset. Enabled represents the ability to | 148 | * enabled/disabled and set/unset. Enabled represents the ability to |
149 | * set the option, disabling an option should also unset it. Set or | 149 | * set the option, disabling an option should also unset it. Set or |
150 | * unset represent wether the option is being used, if it is allowed. | 150 | * unset represent wether the option is being used, if it is allowed. |
151 | */ | 151 | */ |
152 | class Option | 152 | class Option |
153 | { | 153 | { |
154 | friend class Bu::ProtocolTelnet; | 154 | friend class Bu::ProtocolTelnet; |
155 | private: | 155 | private: |
156 | Option( ProtocolTelnet &rPT, char cCode ); | 156 | Option( ProtocolTelnet &rPT, char cCode ); |
157 | virtual ~Option(); | 157 | virtual ~Option(); |
158 | 158 | ||
159 | public: | 159 | public: |
160 | void localEnable( bool bSet=true ); | 160 | void localEnable( bool bSet=true ); |
161 | void localSet( bool bSet=true ); | 161 | void localSet( bool bSet=true ); |
162 | 162 | ||
163 | bool isLocalEnabled(); | 163 | bool isLocalEnabled(); |
164 | bool isLocalSet(); | 164 | bool isLocalSet(); |
165 | 165 | ||
166 | void remoteEnable( bool bSet=true ); | 166 | void remoteEnable( bool bSet=true ); |
167 | void remoteSet( bool bSet=true ); | 167 | void remoteSet( bool bSet=true ); |
168 | 168 | ||
169 | bool isRemoteEnabled(); | 169 | bool isRemoteEnabled(); |
170 | bool isRemoteSet(); | 170 | bool isRemoteSet(); |
171 | 171 | ||
172 | private: | 172 | private: |
173 | enum | 173 | enum |
174 | { | 174 | { |
175 | fLocalCant = 0x01, /**< Local can't/won't allow option. */ | 175 | fLocalCant = 0x01, /**< Local can't/won't allow option. */ |
176 | fLocalIs = 0x02, /**< Local is using option. */ | 176 | fLocalIs = 0x02, /**< Local is using option. */ |
177 | fRemoteCant = 0x04, /**< Remote can't/won't allow option. */ | 177 | fRemoteCant = 0x04, /**< Remote can't/won't allow option. */ |
178 | fRemoteIs = 0x08 /**< Remote is using option. */ | 178 | fRemoteIs = 0x08 /**< Remote is using option. */ |
179 | }; | 179 | }; |
180 | 180 | ||
181 | ProtocolTelnet &rPT; | 181 | ProtocolTelnet &rPT; |
182 | char fOpts; | 182 | char fOpts; |
183 | char cCode; | 183 | char cCode; |
184 | }; | 184 | }; |
185 | friend class Bu::ProtocolTelnet::Option; | 185 | friend class Bu::ProtocolTelnet::Option; |
186 | 186 | ||
187 | Hash<char, Option *> hOpts; | 187 | Hash<char, Option *> hOpts; |
188 | 188 | ||
189 | public: | 189 | public: |
190 | Option oBinary; | 190 | Option oBinary; |
191 | Option oEcho; | 191 | Option oEcho; |
192 | Option oNAWS; | 192 | Option oNAWS; |
193 | Option oSuppressGA; | 193 | Option oSuppressGA; |
194 | 194 | ||
195 | private: | 195 | private: |
196 | void onWill( char cCode ); | 196 | void onWill( char cCode ); |
197 | void onWont( char cCode ); | 197 | void onWont( char cCode ); |
198 | void onDo( char cCode ); | 198 | void onDo( char cCode ); |
199 | void onDont( char cCode ); | 199 | void onDont( char cCode ); |
200 | void onSubOpt(); | 200 | void onSubOpt(); |
201 | void onCtlChar( char cChr ); | 201 | void onCtlChar( char cChr ); |
202 | 202 | ||
203 | #ifdef __TELNET_DEBUG | 203 | #ifdef __TELNET_DEBUG |
204 | void printCode( char cCode ); | 204 | void printCode( char cCode ); |
205 | void printOpt( char cOpt ); | 205 | void printOpt( char cOpt ); |
206 | #endif | 206 | #endif |
207 | 207 | ||
208 | private: | 208 | private: |
209 | Client *pClient; | 209 | Client *pClient; |
210 | 210 | ||
211 | Bu::String sDataBuf; /**< Buffer for regular line data. */ | 211 | Bu::String sDataBuf; /**< Buffer for regular line data. */ |
212 | Bu::String sSubBuf; /**< Buffer for subnegotiation data. */ | 212 | Bu::String sSubBuf; /**< Buffer for subnegotiation data. */ |
213 | char cSubOpt; /**< Which suboption are we processing. */ | 213 | char cSubOpt; /**< Which suboption are we processing. */ |
214 | 214 | ||
215 | bool bCanonical; /**< Are we canonicalizing incoming data? */ | 215 | bool bCanonical; /**< Are we canonicalizing incoming data? */ |
216 | bool bSubOpt; /**< Are we processing a suboption right now? */ | 216 | bool bSubOpt; /**< Are we processing a suboption right now? */ |
217 | }; | 217 | }; |
218 | } | 218 | } |
219 | 219 | ||
220 | #endif | 220 | #endif |
diff --git a/src/stable/queue.h b/src/stable/queue.h index a5f41e9..213d508 100644 --- a/src/stable/queue.h +++ b/src/stable/queue.h | |||
@@ -10,31 +10,31 @@ | |||
10 | 10 | ||
11 | namespace Bu | 11 | namespace Bu |
12 | { | 12 | { |
13 | /** | 13 | /** |
14 | * Queue abstract baseclass | 14 | * Queue abstract baseclass |
15 | */ | 15 | */ |
16 | template<typename value> | 16 | template<typename value> |
17 | class Queue | 17 | class Queue |
18 | { | 18 | { |
19 | public: | 19 | public: |
20 | Queue() | 20 | Queue() |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
24 | virtual ~Queue() | 24 | virtual ~Queue() |
25 | { | 25 | { |
26 | } | 26 | } |
27 | 27 | ||
28 | virtual void enqueue( const value &i )=0; | 28 | virtual void enqueue( const value &i )=0; |
29 | virtual value dequeue()=0; | 29 | virtual value dequeue()=0; |
30 | virtual value &peek()=0; | 30 | virtual value &peek()=0; |
31 | virtual const value &peek() const=0; | 31 | virtual const value &peek() const=0; |
32 | virtual bool isEmpty() const=0; | 32 | virtual bool isEmpty() const=0; |
33 | virtual int getSize() const=0; | 33 | virtual int getSize() const=0; |
34 | 34 | ||
35 | private: | 35 | private: |
36 | 36 | ||
37 | }; | 37 | }; |
38 | } | 38 | } |
39 | 39 | ||
40 | #endif | 40 | #endif |
diff --git a/src/stable/queuebuf.cpp b/src/stable/queuebuf.cpp index 8a3397f..2d49684 100644 --- a/src/stable/queuebuf.cpp +++ b/src/stable/queuebuf.cpp | |||
@@ -11,181 +11,181 @@ | |||
11 | using Bu::sio; | 11 | using Bu::sio; |
12 | 12 | ||
13 | Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : | 13 | Bu::QueueBuf::QueueBuf( int iBlockSize /*=256*/ ) : |
14 | iBlockSize( iBlockSize ), | 14 | iBlockSize( iBlockSize ), |
15 | iReadOffset( 0 ), | 15 | iReadOffset( 0 ), |
16 | iWriteOffset( 0 ), | 16 | iWriteOffset( 0 ), |
17 | iTotalSize( 0 ) | 17 | iTotalSize( 0 ) |
18 | { | 18 | { |
19 | } | 19 | } |
20 | 20 | ||
21 | Bu::QueueBuf::~QueueBuf() | 21 | Bu::QueueBuf::~QueueBuf() |
22 | { | 22 | { |
23 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) | 23 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) |
24 | delete[] *i; | 24 | delete[] *i; |
25 | } | 25 | } |
26 | 26 | ||
27 | void Bu::QueueBuf::close() | 27 | void Bu::QueueBuf::close() |
28 | { | 28 | { |
29 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) | 29 | for( BlockList::iterator i = lBlocks.begin(); i; i++ ) |
30 | delete[] *i; | 30 | delete[] *i; |
31 | lBlocks.clear(); | 31 | lBlocks.clear(); |
32 | iReadOffset = iWriteOffset = iTotalSize = 0; | 32 | iReadOffset = iWriteOffset = iTotalSize = 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) | 35 | Bu::size Bu::QueueBuf::read( void *pRawBuf, Bu::size nBytes ) |
36 | { | 36 | { |
37 | if( nBytes <= 0 ) | 37 | if( nBytes <= 0 ) |
38 | return 0; | 38 | return 0; |
39 | 39 | ||
40 | if( lBlocks.isEmpty() ) | 40 | if( lBlocks.isEmpty() ) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | Bu::size iLeft = nBytes; | 43 | Bu::size iLeft = nBytes; |
44 | char *pBuf = (char *)pRawBuf; | 44 | char *pBuf = (char *)pRawBuf; |
45 | 45 | ||
46 | while( iLeft > 0 && iTotalSize > 0 ) | 46 | while( iLeft > 0 && iTotalSize > 0 ) |
47 | { | 47 | { |
48 | if( iReadOffset == iBlockSize ) | 48 | if( iReadOffset == iBlockSize ) |
49 | { | 49 | { |
50 | removeBlock(); | 50 | removeBlock(); |
51 | if( lBlocks.isEmpty() ) | 51 | if( lBlocks.isEmpty() ) |
52 | { | 52 | { |
53 | return nBytes-iLeft; | 53 | return nBytes-iLeft; |
54 | } | 54 | } |
55 | iReadOffset = 0; | 55 | iReadOffset = 0; |
56 | } | 56 | } |
57 | char *pBlock = lBlocks.first(); | 57 | char *pBlock = lBlocks.first(); |
58 | Bu::size iCopy = iBlockSize-iReadOffset; | 58 | Bu::size iCopy = iBlockSize-iReadOffset; |
59 | if( iLeft < iCopy ) | 59 | if( iLeft < iCopy ) |
60 | iCopy = iLeft; | 60 | iCopy = iLeft; |
61 | if( iTotalSize < iCopy ) | 61 | if( iTotalSize < iCopy ) |
62 | iCopy = iTotalSize; | 62 | iCopy = iTotalSize; |
63 | memcpy( pBuf, pBlock+iReadOffset, iCopy ); | 63 | memcpy( pBuf, pBlock+iReadOffset, iCopy ); |
64 | iReadOffset += iCopy; | 64 | iReadOffset += iCopy; |
65 | iLeft -= iCopy; | 65 | iLeft -= iCopy; |
66 | pBuf += iCopy; | 66 | pBuf += iCopy; |
67 | iTotalSize -= iCopy; | 67 | iTotalSize -= iCopy; |
68 | // sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; | 68 | // sio << "Read " << iCopy << " bytes, new size: " << iTotalSize << sio.nl; |
69 | } | 69 | } |
70 | 70 | ||
71 | return nBytes - iLeft; | 71 | return nBytes - iLeft; |
72 | } | 72 | } |
73 | 73 | ||
74 | Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) | 74 | Bu::size Bu::QueueBuf::peek( void *pBuf, Bu::size nBytes ) |
75 | { | 75 | { |
76 | return peek( pBuf, nBytes, 0 ); | 76 | return peek( pBuf, nBytes, 0 ); |
77 | } | 77 | } |
78 | 78 | ||
79 | Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) | 79 | Bu::size Bu::QueueBuf::peek( void *pRawBuf, Bu::size nBytes, Bu::size nSkip ) |
80 | { | 80 | { |
81 | if( nBytes <= 0 ) | 81 | if( nBytes <= 0 ) |
82 | return 0; | 82 | return 0; |
83 | 83 | ||
84 | if( lBlocks.isEmpty() ) | 84 | if( lBlocks.isEmpty() ) |
85 | return 0; | 85 | return 0; |
86 | 86 | ||
87 | Bu::size iLeft = nBytes; | 87 | Bu::size iLeft = nBytes; |
88 | char *pBuf = (char *)pRawBuf; | 88 | char *pBuf = (char *)pRawBuf; |
89 | 89 | ||
90 | int iTmpReadOffset = iReadOffset + nSkip; | 90 | int iTmpReadOffset = iReadOffset + nSkip; |
91 | Bu::size iTmpRemSize = iTotalSize; | 91 | Bu::size iTmpRemSize = iTotalSize; |
92 | BlockList::iterator iBlock = lBlocks.begin(); | 92 | BlockList::iterator iBlock = lBlocks.begin(); |
93 | while( iTmpReadOffset > iBlockSize ) | 93 | while( iTmpReadOffset > iBlockSize ) |
94 | { | 94 | { |
95 | iTmpReadOffset -= iBlockSize; | 95 | iTmpReadOffset -= iBlockSize; |
96 | iBlock++; | 96 | iBlock++; |
97 | } | 97 | } |
98 | while( iLeft > 0 && iTmpRemSize > 0 ) | 98 | while( iLeft > 0 && iTmpRemSize > 0 ) |
99 | { | 99 | { |
100 | if( iTmpReadOffset == iBlockSize ) | 100 | if( iTmpReadOffset == iBlockSize ) |
101 | { | 101 | { |
102 | iBlock++; | 102 | iBlock++; |
103 | if( iBlock == lBlocks.end() ) | 103 | if( iBlock == lBlocks.end() ) |
104 | { | 104 | { |
105 | return nBytes-iLeft; | 105 | return nBytes-iLeft; |
106 | } | 106 | } |
107 | iTmpReadOffset = 0; | 107 | iTmpReadOffset = 0; |
108 | } | 108 | } |
109 | char *pBlock = *iBlock; | 109 | char *pBlock = *iBlock; |
110 | Bu::size iCopy = iBlockSize-iTmpReadOffset; | 110 | Bu::size iCopy = iBlockSize-iTmpReadOffset; |
111 | if( iLeft < iCopy ) | 111 | if( iLeft < iCopy ) |
112 | iCopy = iLeft; | 112 | iCopy = iLeft; |
113 | if( iTmpRemSize < iCopy ) | 113 | if( iTmpRemSize < iCopy ) |
114 | iCopy = iTmpRemSize; | 114 | iCopy = iTmpRemSize; |
115 | memcpy( pBuf, pBlock+iTmpReadOffset, iCopy ); | 115 | memcpy( pBuf, pBlock+iTmpReadOffset, iCopy ); |
116 | iTmpReadOffset += iCopy; | 116 | iTmpReadOffset += iCopy; |
117 | iLeft -= iCopy; | 117 | iLeft -= iCopy; |
118 | pBuf += iCopy; | 118 | pBuf += iCopy; |
119 | iTmpRemSize -= iCopy; | 119 | iTmpRemSize -= iCopy; |
120 | // sio << "Read (peek) " << iCopy << " bytes, new temp size: " | 120 | // sio << "Read (peek) " << iCopy << " bytes, new temp size: " |
121 | // << iTmpRemSize << sio.nl; | 121 | // << iTmpRemSize << sio.nl; |
122 | } | 122 | } |
123 | 123 | ||
124 | return nBytes - iLeft; | 124 | return nBytes - iLeft; |
125 | } | 125 | } |
126 | 126 | ||
127 | Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) | 127 | Bu::size Bu::QueueBuf::write( const void *pRawBuf, Bu::size nBytes ) |
128 | { | 128 | { |
129 | if( nBytes <= 0 ) | 129 | if( nBytes <= 0 ) |
130 | return 0; | 130 | return 0; |
131 | 131 | ||
132 | if( lBlocks.isEmpty() ) | 132 | if( lBlocks.isEmpty() ) |
133 | { | 133 | { |
134 | addBlock(); | 134 | addBlock(); |
135 | iWriteOffset = 0; | 135 | iWriteOffset = 0; |
136 | } | 136 | } |
137 | Bu::size iLeft = nBytes; | 137 | Bu::size iLeft = nBytes; |
138 | const char *pBuf = (const char *)pRawBuf; | 138 | const char *pBuf = (const char *)pRawBuf; |
139 | 139 | ||
140 | while( iLeft > 0 ) | 140 | while( iLeft > 0 ) |
141 | { | 141 | { |
142 | if( iWriteOffset == iBlockSize ) | 142 | if( iWriteOffset == iBlockSize ) |
143 | { | 143 | { |
144 | addBlock(); | 144 | addBlock(); |
145 | iWriteOffset = 0; | 145 | iWriteOffset = 0; |
146 | } | 146 | } |
147 | char *pBlock = lBlocks.last(); | 147 | char *pBlock = lBlocks.last(); |
148 | Bu::size iCopy = iBlockSize-iWriteOffset; | 148 | Bu::size iCopy = iBlockSize-iWriteOffset; |
149 | if( iLeft < iCopy ) | 149 | if( iLeft < iCopy ) |
150 | iCopy = iLeft; | 150 | iCopy = iLeft; |
151 | memcpy( pBlock+iWriteOffset, pBuf, iCopy ); | 151 | memcpy( pBlock+iWriteOffset, pBuf, iCopy ); |
152 | iWriteOffset += iCopy; | 152 | iWriteOffset += iCopy; |
153 | iLeft -= iCopy; | 153 | iLeft -= iCopy; |
154 | pBuf += iCopy; | 154 | pBuf += iCopy; |
155 | iTotalSize += iCopy; | 155 | iTotalSize += iCopy; |
156 | // sio << "Wrote " << iCopy << " bytes, new size: " << iTotalSize | 156 | // sio << "Wrote " << iCopy << " bytes, new size: " << iTotalSize |
157 | // << sio.nl; | 157 | // << sio.nl; |
158 | } | 158 | } |
159 | 159 | ||
160 | return nBytes; | 160 | return nBytes; |
161 | } | 161 | } |
162 | 162 | ||
163 | Bu::size Bu::QueueBuf::tell() | 163 | Bu::size Bu::QueueBuf::tell() |
164 | { | 164 | { |
165 | return -1; | 165 | return -1; |
166 | } | 166 | } |
167 | 167 | ||
168 | void Bu::QueueBuf::seek( Bu::size iAmnt ) | 168 | void Bu::QueueBuf::seek( Bu::size iAmnt ) |
169 | { | 169 | { |
170 | if( iAmnt <= 0 ) | 170 | if( iAmnt <= 0 ) |
171 | return; | 171 | return; |
172 | 172 | ||
173 | if( (Bu::size)iAmnt >= iTotalSize ) | 173 | if( (Bu::size)iAmnt >= iTotalSize ) |
174 | { | 174 | { |
175 | // sio << "seek: clear all data (" << iAmnt << ">=" << iTotalSize | 175 | // sio << "seek: clear all data (" << iAmnt << ">=" << iTotalSize |
176 | // << ")." << sio.nl; | 176 | // << ")." << sio.nl; |
177 | close(); | 177 | close(); |
178 | return; | 178 | return; |
179 | } | 179 | } |
180 | 180 | ||
181 | iReadOffset += iAmnt; | 181 | iReadOffset += iAmnt; |
182 | iTotalSize -= iAmnt; | 182 | iTotalSize -= iAmnt; |
183 | while( iReadOffset >= iBlockSize ) | 183 | while( iReadOffset >= iBlockSize ) |
184 | { | 184 | { |
185 | removeBlock(); | 185 | removeBlock(); |
186 | iReadOffset -= iBlockSize; | 186 | iReadOffset -= iBlockSize; |
187 | // sio << "seek: removal step (" << iReadOffset << ")" << sio.nl; | 187 | // sio << "seek: removal step (" << iReadOffset << ")" << sio.nl; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | void Bu::QueueBuf::setPos( Bu::size ) | 191 | void Bu::QueueBuf::setPos( Bu::size ) |
@@ -198,12 +198,12 @@ void Bu::QueueBuf::setPosEnd( Bu::size ) | |||
198 | 198 | ||
199 | bool Bu::QueueBuf::isEos() | 199 | bool Bu::QueueBuf::isEos() |
200 | { | 200 | { |
201 | return iTotalSize == 0; | 201 | return iTotalSize == 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | bool Bu::QueueBuf::isOpen() | 204 | bool Bu::QueueBuf::isOpen() |
205 | { | 205 | { |
206 | return true; | 206 | return true; |
207 | } | 207 | } |
208 | 208 | ||
209 | void Bu::QueueBuf::flush() | 209 | void Bu::QueueBuf::flush() |
@@ -212,32 +212,32 @@ void Bu::QueueBuf::flush() | |||
212 | 212 | ||
213 | bool Bu::QueueBuf::canRead() | 213 | bool Bu::QueueBuf::canRead() |
214 | { | 214 | { |
215 | return iTotalSize > 0; | 215 | return iTotalSize > 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | bool Bu::QueueBuf::canWrite() | 218 | bool Bu::QueueBuf::canWrite() |
219 | { | 219 | { |
220 | return true; | 220 | return true; |
221 | } | 221 | } |
222 | 222 | ||
223 | bool Bu::QueueBuf::isReadable() | 223 | bool Bu::QueueBuf::isReadable() |
224 | { | 224 | { |
225 | return true; | 225 | return true; |
226 | } | 226 | } |
227 | 227 | ||
228 | bool Bu::QueueBuf::isWritable() | 228 | bool Bu::QueueBuf::isWritable() |
229 | { | 229 | { |
230 | return true; | 230 | return true; |
231 | } | 231 | } |
232 | 232 | ||
233 | bool Bu::QueueBuf::isSeekable() | 233 | bool Bu::QueueBuf::isSeekable() |
234 | { | 234 | { |
235 | return false; | 235 | return false; |
236 | } | 236 | } |
237 | 237 | ||
238 | bool Bu::QueueBuf::isBlocking() | 238 | bool Bu::QueueBuf::isBlocking() |
239 | { | 239 | { |
240 | return false; | 240 | return false; |
241 | } | 241 | } |
242 | 242 | ||
243 | void Bu::QueueBuf::setBlocking( bool ) | 243 | void Bu::QueueBuf::setBlocking( bool ) |
@@ -250,29 +250,29 @@ void Bu::QueueBuf::setSize( Bu::size ) | |||
250 | 250 | ||
251 | Bu::size Bu::QueueBuf::getSize() const | 251 | Bu::size Bu::QueueBuf::getSize() const |
252 | { | 252 | { |
253 | return iTotalSize; | 253 | return iTotalSize; |
254 | } | 254 | } |
255 | 255 | ||
256 | Bu::size Bu::QueueBuf::getBlockSize() const | 256 | Bu::size Bu::QueueBuf::getBlockSize() const |
257 | { | 257 | { |
258 | return iBlockSize; | 258 | return iBlockSize; |
259 | } | 259 | } |
260 | 260 | ||
261 | Bu::String Bu::QueueBuf::getLocation() const | 261 | Bu::String Bu::QueueBuf::getLocation() const |
262 | { | 262 | { |
263 | return ""; | 263 | return ""; |
264 | } | 264 | } |
265 | 265 | ||
266 | void Bu::QueueBuf::addBlock() | 266 | void Bu::QueueBuf::addBlock() |
267 | { | 267 | { |
268 | lBlocks.append( new char[iBlockSize] ); | 268 | lBlocks.append( new char[iBlockSize] ); |
269 | // sio << "Added new block." << sio.nl; | 269 | // sio << "Added new block." << sio.nl; |
270 | } | 270 | } |
271 | 271 | ||
272 | void Bu::QueueBuf::removeBlock() | 272 | void Bu::QueueBuf::removeBlock() |
273 | { | 273 | { |
274 | delete[] lBlocks.first(); | 274 | delete[] lBlocks.first(); |
275 | lBlocks.erase( lBlocks.begin() ); | 275 | lBlocks.erase( lBlocks.begin() ); |
276 | // sio << "Removed block." << sio.nl; | 276 | // sio << "Removed block." << sio.nl; |
277 | } | 277 | } |
278 | 278 | ||
diff --git a/src/stable/queuebuf.h b/src/stable/queuebuf.h index 6e2a075..60aa115 100644 --- a/src/stable/queuebuf.h +++ b/src/stable/queuebuf.h | |||
@@ -12,55 +12,55 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A queuing buffer stream class. All data written to this class is | 16 | * A queuing buffer stream class. All data written to this class is |
17 | * appended to it, there is no stored position. All data read is read | 17 | * appended to it, there is no stored position. All data read is read |
18 | * from the begining and then thrown away. It operates by using a linked | 18 | * from the begining and then thrown away. It operates by using a linked |
19 | * list of small buffers, and deallocating or reusing them when it can. | 19 | * list of small buffers, and deallocating or reusing them when it can. |
20 | */ | 20 | */ |
21 | class QueueBuf : public Bu::Stream | 21 | class QueueBuf : public Bu::Stream |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | QueueBuf( int iBlockSize=256 ); | 24 | QueueBuf( int iBlockSize=256 ); |
25 | virtual ~QueueBuf(); | 25 | virtual ~QueueBuf(); |
26 | 26 | ||
27 | virtual void close(); | 27 | virtual void close(); |
28 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 28 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
29 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); | 29 | virtual Bu::size peek( void *pBuf, Bu::size nBytes ); |
30 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); | 30 | virtual Bu::size peek( void *pBuf, Bu::size nBytes, Bu::size nSkip ); |
31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 31 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
32 | virtual Bu::size tell(); | 32 | virtual Bu::size tell(); |
33 | virtual void seek( Bu::size offset ); | 33 | virtual void seek( Bu::size offset ); |
34 | virtual void setPos( Bu::size pos ); | 34 | virtual void setPos( Bu::size pos ); |
35 | virtual void setPosEnd( Bu::size pos ); | 35 | virtual void setPosEnd( Bu::size pos ); |
36 | virtual bool isEos(); | 36 | virtual bool isEos(); |
37 | virtual bool isOpen(); | 37 | virtual bool isOpen(); |
38 | virtual void flush(); | 38 | virtual void flush(); |
39 | virtual bool canRead(); | 39 | virtual bool canRead(); |
40 | virtual bool canWrite(); | 40 | virtual bool canWrite(); |
41 | virtual bool isReadable(); | 41 | virtual bool isReadable(); |
42 | virtual bool isWritable(); | 42 | virtual bool isWritable(); |
43 | virtual bool isSeekable(); | 43 | virtual bool isSeekable(); |
44 | virtual bool isBlocking(); | 44 | virtual bool isBlocking(); |
45 | virtual void setBlocking( bool bBlocking=true ); | 45 | virtual void setBlocking( bool bBlocking=true ); |
46 | virtual void setSize( Bu::size iSize ); | 46 | virtual void setSize( Bu::size iSize ); |
47 | 47 | ||
48 | virtual size getSize() const; | 48 | virtual size getSize() const; |
49 | virtual size getBlockSize() const; | 49 | virtual size getBlockSize() const; |
50 | virtual Bu::String getLocation() const; | 50 | virtual Bu::String getLocation() const; |
51 | 51 | ||
52 | private: | 52 | private: |
53 | void addBlock(); | 53 | void addBlock(); |
54 | void removeBlock(); | 54 | void removeBlock(); |
55 | 55 | ||
56 | private: | 56 | private: |
57 | int iBlockSize; | 57 | int iBlockSize; |
58 | int iReadOffset; | 58 | int iReadOffset; |
59 | int iWriteOffset; | 59 | int iWriteOffset; |
60 | Bu::size iTotalSize; | 60 | Bu::size iTotalSize; |
61 | typedef Bu::List<char *> BlockList; | 61 | typedef Bu::List<char *> BlockList; |
62 | BlockList lBlocks; | 62 | BlockList lBlocks; |
63 | }; | 63 | }; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | #endif | 66 | #endif |
diff --git a/src/stable/random.cpp b/src/stable/random.cpp index 63416bf..6dca782 100644 --- a/src/stable/random.cpp +++ b/src/stable/random.cpp | |||
@@ -9,39 +9,39 @@ | |||
9 | #include "bu/randombasic.h" | 9 | #include "bu/randombasic.h" |
10 | 10 | ||
11 | Bu::Random::Random() : | 11 | Bu::Random::Random() : |
12 | pGen( NULL ) | 12 | pGen( NULL ) |
13 | { | 13 | { |
14 | pGen = new RandomBasic(); | 14 | pGen = new RandomBasic(); |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::Random::~Random() | 17 | Bu::Random::~Random() |
18 | { | 18 | { |
19 | delete pGen; | 19 | delete pGen; |
20 | pGen = NULL; | 20 | pGen = NULL; |
21 | } | 21 | } |
22 | 22 | ||
23 | void Bu::Random::seed( int32_t iSeed ) | 23 | void Bu::Random::seed( int32_t iSeed ) |
24 | { | 24 | { |
25 | getInstance().pGen->seed( iSeed ); | 25 | getInstance().pGen->seed( iSeed ); |
26 | } | 26 | } |
27 | 27 | ||
28 | int32_t Bu::Random::rand() | 28 | int32_t Bu::Random::rand() |
29 | { | 29 | { |
30 | return getInstance().pGen->rand(); | 30 | return getInstance().pGen->rand(); |
31 | } | 31 | } |
32 | 32 | ||
33 | int32_t Bu::Random::rand( int32_t iMax ) | 33 | int32_t Bu::Random::rand( int32_t iMax ) |
34 | { | 34 | { |
35 | return getInstance().pGen->rand( iMax ); | 35 | return getInstance().pGen->rand( iMax ); |
36 | } | 36 | } |
37 | 37 | ||
38 | int32_t Bu::Random::rand( int32_t iMin, int32_t iMax ) | 38 | int32_t Bu::Random::rand( int32_t iMin, int32_t iMax ) |
39 | { | 39 | { |
40 | return getInstance().pGen->rand( iMin, iMax ); | 40 | return getInstance().pGen->rand( iMin, iMax ); |
41 | } | 41 | } |
42 | 42 | ||
43 | double Bu::Random::randNorm() | 43 | double Bu::Random::randNorm() |
44 | { | 44 | { |
45 | return getInstance().pGen->randNorm(); | 45 | return getInstance().pGen->randNorm(); |
46 | } | 46 | } |
47 | 47 | ||
diff --git a/src/stable/random.h b/src/stable/random.h index 43b8917..7989188 100644 --- a/src/stable/random.h +++ b/src/stable/random.h | |||
@@ -12,50 +12,50 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class RandomBase; | 15 | class RandomBase; |
16 | class Random : public Bu::Singleton<Bu::Random> | 16 | class Random : public Bu::Singleton<Bu::Random> |
17 | { | 17 | { |
18 | friend class Bu::Singleton<Bu::Random>; | 18 | friend class Bu::Singleton<Bu::Random>; |
19 | private: | 19 | private: |
20 | Random(); | 20 | Random(); |
21 | virtual ~Random(); | 21 | virtual ~Random(); |
22 | 22 | ||
23 | public: | 23 | public: |
24 | template<typename cl> | 24 | template<typename cl> |
25 | static void setGenerator() | 25 | static void setGenerator() |
26 | { | 26 | { |
27 | delete getInstance().pGen; | 27 | delete getInstance().pGen; |
28 | getInstance().pGen = new cl(); | 28 | getInstance().pGen = new cl(); |
29 | } | 29 | } |
30 | 30 | ||
31 | template<typename cl, typename t1> | 31 | template<typename cl, typename t1> |
32 | static void setGenerator( t1 p1 ) | 32 | static void setGenerator( t1 p1 ) |
33 | { | 33 | { |
34 | delete getInstance().pGen; | 34 | delete getInstance().pGen; |
35 | getInstance().pGen = new cl( p1 ); | 35 | getInstance().pGen = new cl( p1 ); |
36 | } | 36 | } |
37 | 37 | ||
38 | template<typename cl, typename t1, typename t2> | 38 | template<typename cl, typename t1, typename t2> |
39 | static void setGenerator( t1 p1, t2 p2 ) | 39 | static void setGenerator( t1 p1, t2 p2 ) |
40 | { | 40 | { |
41 | delete getInstance().pGen; | 41 | delete getInstance().pGen; |
42 | getInstance().pGen = new cl( p1, p2 ); | 42 | getInstance().pGen = new cl( p1, p2 ); |
43 | } | 43 | } |
44 | 44 | ||
45 | RandomBase &getGenerator() { return *pGen; } | 45 | RandomBase &getGenerator() { return *pGen; } |
46 | 46 | ||
47 | static void seed( int32_t iSeed ); | 47 | static void seed( int32_t iSeed ); |
48 | static int32_t rand(); | 48 | static int32_t rand(); |
49 | static int32_t rand( int32_t iMax ); | 49 | static int32_t rand( int32_t iMax ); |
50 | static int32_t rand( int32_t iMin, int32_t iMax ); | 50 | static int32_t rand( int32_t iMin, int32_t iMax ); |
51 | static double randNorm(); | 51 | static double randNorm(); |
52 | 52 | ||
53 | private: | 53 | private: |
54 | void checkInit(); | 54 | void checkInit(); |
55 | 55 | ||
56 | private: | 56 | private: |
57 | Bu::RandomBase *pGen; | 57 | Bu::RandomBase *pGen; |
58 | }; | 58 | }; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | #endif | 61 | #endif |
diff --git a/src/stable/randombase.h b/src/stable/randombase.h index d33bb99..946284f 100644 --- a/src/stable/randombase.h +++ b/src/stable/randombase.h | |||
@@ -11,25 +11,25 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomBase | 14 | class RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomBase(); | 17 | RandomBase(); |
18 | virtual ~RandomBase(); | 18 | virtual ~RandomBase(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed )=0; | 20 | virtual void seed( int32_t iSeed )=0; |
21 | virtual int32_t rand()=0; | 21 | virtual int32_t rand()=0; |
22 | virtual inline int32_t rand( int32_t iMax ) { | 22 | virtual inline int32_t rand( int32_t iMax ) { |
23 | return rand( 0, iMax ); | 23 | return rand( 0, iMax ); |
24 | } | 24 | } |
25 | virtual inline int32_t rand( int32_t iMin, int32_t iMax ) { | 25 | virtual inline int32_t rand( int32_t iMin, int32_t iMax ) { |
26 | return iMin+(randNorm()*(iMax-iMin)); | 26 | return iMin+(randNorm()*(iMax-iMin)); |
27 | } | 27 | } |
28 | virtual inline double randNorm() { | 28 | virtual inline double randNorm() { |
29 | return (((uint32_t)rand())&0xfffffffeul)*0x1.00000001p-32; | 29 | return (((uint32_t)rand())&0xfffffffeul)*0x1.00000001p-32; |
30 | // return (((uint32_t)rand())&0xfffffffeul)/(double)(0xfffffffful); | 30 | // return (((uint32_t)rand())&0xfffffffeul)/(double)(0xfffffffful); |
31 | } | 31 | } |
32 | }; | 32 | }; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #endif | 35 | #endif |
diff --git a/src/stable/randombasic.cpp b/src/stable/randombasic.cpp index 89e2780..e253b70 100644 --- a/src/stable/randombasic.cpp +++ b/src/stable/randombasic.cpp | |||
@@ -8,9 +8,9 @@ | |||
8 | #include "bu/randombasic.h" | 8 | #include "bu/randombasic.h" |
9 | 9 | ||
10 | Bu::RandomBasic::RandomBasic() : | 10 | Bu::RandomBasic::RandomBasic() : |
11 | a( 6364136223846793005ll ), | 11 | a( 6364136223846793005ll ), |
12 | c( 1442695040888963407ll ), | 12 | c( 1442695040888963407ll ), |
13 | x( 0 ) | 13 | x( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,12 +20,12 @@ Bu::RandomBasic::~RandomBasic() | |||
20 | 20 | ||
21 | void Bu::RandomBasic::seed( int32_t iSeed ) | 21 | void Bu::RandomBasic::seed( int32_t iSeed ) |
22 | { | 22 | { |
23 | c = iSeed; | 23 | c = iSeed; |
24 | } | 24 | } |
25 | 25 | ||
26 | int32_t Bu::RandomBasic::rand() | 26 | int32_t Bu::RandomBasic::rand() |
27 | { | 27 | { |
28 | x = (a*x + c); | 28 | x = (a*x + c); |
29 | return (int32_t)x; | 29 | return (int32_t)x; |
30 | } | 30 | } |
31 | 31 | ||
diff --git a/src/stable/randombasic.h b/src/stable/randombasic.h index a53e16f..4d1c2f8 100644 --- a/src/stable/randombasic.h +++ b/src/stable/randombasic.h | |||
@@ -11,19 +11,19 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomBasic : public RandomBase | 14 | class RandomBasic : public RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomBasic(); | 17 | RandomBasic(); |
18 | virtual ~RandomBasic(); | 18 | virtual ~RandomBasic(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed ); | 20 | virtual void seed( int32_t iSeed ); |
21 | 21 | ||
22 | virtual int32_t rand(); | 22 | virtual int32_t rand(); |
23 | 23 | ||
24 | private: | 24 | private: |
25 | int64_t a, c, x; | 25 | int64_t a, c, x; |
26 | }; | 26 | }; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/randomcmwc.cpp b/src/stable/randomcmwc.cpp index 9f68982..1d4a913 100644 --- a/src/stable/randomcmwc.cpp +++ b/src/stable/randomcmwc.cpp | |||
@@ -12,52 +12,52 @@ | |||
12 | #define PHI 0x9e3779b9 | 12 | #define PHI 0x9e3779b9 |
13 | 13 | ||
14 | Bu::RandomCmwc::RandomCmwc() : | 14 | Bu::RandomCmwc::RandomCmwc() : |
15 | q( 0 ), | 15 | q( 0 ), |
16 | c( 362436 ) | 16 | c( 362436 ) |
17 | { | 17 | { |
18 | q = new uint32_t[4096]; | 18 | q = new uint32_t[4096]; |
19 | } | 19 | } |
20 | 20 | ||
21 | Bu::RandomCmwc::~RandomCmwc() | 21 | Bu::RandomCmwc::~RandomCmwc() |
22 | { | 22 | { |
23 | delete[] q; | 23 | delete[] q; |
24 | } | 24 | } |
25 | 25 | ||
26 | void Bu::RandomCmwc::seed( int32_t iSeed ) | 26 | void Bu::RandomCmwc::seed( int32_t iSeed ) |
27 | { | 27 | { |
28 | i = 4095; | 28 | i = 4095; |
29 | c = 362436; | 29 | c = 362436; |
30 | 30 | ||
31 | Bu::RandomBasic rb; | 31 | Bu::RandomBasic rb; |
32 | rb.seed( iSeed ); | 32 | rb.seed( iSeed ); |
33 | 33 | ||
34 | for( int j = 0; j < 4096; j++ ) | 34 | for( int j = 0; j < 4096; j++ ) |
35 | q[j] = rb.rand(); | 35 | q[j] = rb.rand(); |
36 | 36 | ||
37 | c = rb.rand(); | 37 | c = rb.rand(); |
38 | 38 | ||
39 | return; | 39 | return; |
40 | q[0] = (uint32_t)rb.rand(); | 40 | q[0] = (uint32_t)rb.rand(); |
41 | q[1] = (uint32_t)rb.rand() + PHI; | 41 | q[1] = (uint32_t)rb.rand() + PHI; |
42 | q[2] = (uint32_t)rb.rand() + PHI + PHI; | 42 | q[2] = (uint32_t)rb.rand() + PHI + PHI; |
43 | 43 | ||
44 | for (int j = 3; j < 4096; j++) | 44 | for (int j = 3; j < 4096; j++) |
45 | q[j] = q[j - 3] ^ q[j - 2] ^ PHI ^ j; | 45 | q[j] = q[j - 3] ^ q[j - 2] ^ PHI ^ j; |
46 | } | 46 | } |
47 | 47 | ||
48 | int32_t Bu::RandomCmwc::rand() | 48 | int32_t Bu::RandomCmwc::rand() |
49 | { | 49 | { |
50 | uint64_t t, a = 18782LL; | 50 | uint64_t t, a = 18782LL; |
51 | uint32_t x, r = 0xfffffffe; | 51 | uint32_t x, r = 0xfffffffe; |
52 | i = (i + 1) & 4095; | 52 | i = (i + 1) & 4095; |
53 | t = a * q[i] + c; | 53 | t = a * q[i] + c; |
54 | c = (t >> 32); | 54 | c = (t >> 32); |
55 | x = t + c; | 55 | x = t + c; |
56 | if( x < c ) | 56 | if( x < c ) |
57 | { | 57 | { |
58 | x++; | 58 | x++; |
59 | c++; | 59 | c++; |
60 | } | 60 | } |
61 | return (q[i] = r - x); | 61 | return (q[i] = r - x); |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/src/stable/randomcmwc.h b/src/stable/randomcmwc.h index fff891b..547b5bb 100644 --- a/src/stable/randomcmwc.h +++ b/src/stable/randomcmwc.h | |||
@@ -11,19 +11,19 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class RandomCmwc : public RandomBase | 14 | class RandomCmwc : public RandomBase |
15 | { | 15 | { |
16 | public: | 16 | public: |
17 | RandomCmwc(); | 17 | RandomCmwc(); |
18 | virtual ~RandomCmwc(); | 18 | virtual ~RandomCmwc(); |
19 | 19 | ||
20 | virtual void seed( int32_t iSeed ); | 20 | virtual void seed( int32_t iSeed ); |
21 | 21 | ||
22 | virtual int32_t rand(); | 22 | virtual int32_t rand(); |
23 | 23 | ||
24 | private: | 24 | private: |
25 | uint32_t *q, c, i; | 25 | uint32_t *q, c, i; |
26 | }; | 26 | }; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/randomsystem.cpp b/src/stable/randomsystem.cpp index 0501587..68c69d5 100644 --- a/src/stable/randomsystem.cpp +++ b/src/stable/randomsystem.cpp | |||
@@ -2,39 +2,39 @@ | |||
2 | #include "bu/file.h" | 2 | #include "bu/file.h" |
3 | 3 | ||
4 | Bu::RandomSystem::RandomSystem( Type eType ) : | 4 | Bu::RandomSystem::RandomSystem( Type eType ) : |
5 | eType( eType ), | 5 | eType( eType ), |
6 | pSrc( 0 ) | 6 | pSrc( 0 ) |
7 | { | 7 | { |
8 | switch( eType ) | 8 | switch( eType ) |
9 | { | 9 | { |
10 | case Bu::RandomSystem::Fast: | 10 | case Bu::RandomSystem::Fast: |
11 | pSrc = new Bu::File("/dev/urandom", Bu::File::Read ); | 11 | pSrc = new Bu::File("/dev/urandom", Bu::File::Read ); |
12 | break; | 12 | break; |
13 | 13 | ||
14 | case Bu::RandomSystem::Good: | 14 | case Bu::RandomSystem::Good: |
15 | pSrc = new Bu::File("/dev/random", Bu::File::Read ); | 15 | pSrc = new Bu::File("/dev/random", Bu::File::Read ); |
16 | break; | 16 | break; |
17 | } | 17 | } |
18 | } | 18 | } |
19 | 19 | ||
20 | Bu::RandomSystem::~RandomSystem() | 20 | Bu::RandomSystem::~RandomSystem() |
21 | { | 21 | { |
22 | delete pSrc; | 22 | delete pSrc; |
23 | } | 23 | } |
24 | 24 | ||
25 | void Bu::RandomSystem::seed( int32_t /*iSeed*/ ) | 25 | void Bu::RandomSystem::seed( int32_t /*iSeed*/ ) |
26 | { | 26 | { |
27 | // Seed really has no effect here... | 27 | // Seed really has no effect here... |
28 | // on linux, if we were root, we could write data to random/urandom to | 28 | // on linux, if we were root, we could write data to random/urandom to |
29 | // perturb the data, but it's not necesarry | 29 | // perturb the data, but it's not necesarry |
30 | } | 30 | } |
31 | 31 | ||
32 | int32_t Bu::RandomSystem::rand() | 32 | int32_t Bu::RandomSystem::rand() |
33 | { | 33 | { |
34 | if( !pSrc ) | 34 | if( !pSrc ) |
35 | throw Bu::ExceptionBase("Not initialized"); | 35 | throw Bu::ExceptionBase("Not initialized"); |
36 | int32_t i; | 36 | int32_t i; |
37 | pSrc->read( &i, sizeof(int32_t) ); | 37 | pSrc->read( &i, sizeof(int32_t) ); |
38 | return i; | 38 | return i; |
39 | } | 39 | } |
40 | 40 | ||
diff --git a/src/stable/randomsystem.h b/src/stable/randomsystem.h index 7106d58..63b40f3 100644 --- a/src/stable/randomsystem.h +++ b/src/stable/randomsystem.h | |||
@@ -11,27 +11,27 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | class File; | 14 | class File; |
15 | class RandomSystem : public RandomBase | 15 | class RandomSystem : public RandomBase |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | enum Type | 18 | enum Type |
19 | { | 19 | { |
20 | Fast, | 20 | Fast, |
21 | Good | 21 | Good |
22 | }; | 22 | }; |
23 | 23 | ||
24 | RandomSystem( Type eType=Fast ); | 24 | RandomSystem( Type eType=Fast ); |
25 | virtual ~RandomSystem(); | 25 | virtual ~RandomSystem(); |
26 | 26 | ||
27 | virtual void seed( int32_t iSeed ); | 27 | virtual void seed( int32_t iSeed ); |
28 | 28 | ||
29 | virtual int32_t rand(); | 29 | virtual int32_t rand(); |
30 | 30 | ||
31 | private: | 31 | private: |
32 | Type eType; | 32 | Type eType; |
33 | File *pSrc; | 33 | File *pSrc; |
34 | }; | 34 | }; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | #endif | 37 | #endif |
diff --git a/src/stable/ringbuffer.h b/src/stable/ringbuffer.h index 79c5a15..39d053e 100644 --- a/src/stable/ringbuffer.h +++ b/src/stable/ringbuffer.h | |||
@@ -15,237 +15,237 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | template<typename value, typename valuealloc> class RingBuffer; | 18 | template<typename value, typename valuealloc> class RingBuffer; |
19 | 19 | ||
20 | /** @cond DEVEL */ | 20 | /** @cond DEVEL */ |
21 | template<typename value, typename valuealloc> | 21 | template<typename value, typename valuealloc> |
22 | class RingBufferCore | 22 | class RingBufferCore |
23 | { | 23 | { |
24 | friend class RingBuffer<value, valuealloc>; | 24 | friend class RingBuffer<value, valuealloc>; |
25 | friend class SharedCore<RingBuffer<value, valuealloc>, | 25 | friend class SharedCore<RingBuffer<value, valuealloc>, |
26 | RingBufferCore<value, valuealloc> >; | 26 | RingBufferCore<value, valuealloc> >; |
27 | private: | 27 | private: |
28 | RingBufferCore() : | 28 | RingBufferCore() : |
29 | iCapacity( 0 ), | 29 | iCapacity( 0 ), |
30 | iStart( -1 ), | 30 | iStart( -1 ), |
31 | iEnd( -2 ), | 31 | iEnd( -2 ), |
32 | aData( NULL ) | 32 | aData( NULL ) |
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
36 | virtual ~RingBufferCore() | 36 | virtual ~RingBufferCore() |
37 | { | 37 | { |
38 | clear(); | 38 | clear(); |
39 | } | 39 | } |
40 | 40 | ||
41 | void init( int iNewCapacity ) | 41 | void init( int iNewCapacity ) |
42 | { | 42 | { |
43 | if( iCapacity > 0 ) | 43 | if( iCapacity > 0 ) |
44 | return; | 44 | return; |
45 | 45 | ||
46 | iCapacity = iNewCapacity; | 46 | iCapacity = iNewCapacity; |
47 | iStart = -1; | 47 | iStart = -1; |
48 | iEnd = -2; | 48 | iEnd = -2; |
49 | aData = va.allocate( iCapacity ); | 49 | aData = va.allocate( iCapacity ); |
50 | } | 50 | } |
51 | 51 | ||
52 | void clear() | 52 | void clear() |
53 | { | 53 | { |
54 | for( int j = iStart; j < iEnd; j=(j+1%iCapacity) ) | 54 | for( int j = iStart; j < iEnd; j=(j+1%iCapacity) ) |
55 | { | 55 | { |
56 | va.destroy( &aData[j] ); | 56 | va.destroy( &aData[j] ); |
57 | } | 57 | } |
58 | va.deallocate( aData, iCapacity ); | 58 | va.deallocate( aData, iCapacity ); |
59 | aData = NULL; | 59 | aData = NULL; |
60 | iCapacity = 0; | 60 | iCapacity = 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | void enqueue( const value &v ) | 63 | void enqueue( const value &v ) |
64 | { | 64 | { |
65 | if( iStart == -1 ) | 65 | if( iStart == -1 ) |
66 | { | 66 | { |
67 | iStart = 0; | 67 | iStart = 0; |
68 | iEnd = 1; | 68 | iEnd = 1; |
69 | va.construct( &aData[0], v ); | 69 | va.construct( &aData[0], v ); |
70 | return; | 70 | return; |
71 | } | 71 | } |
72 | else if( iStart == iEnd ) | 72 | else if( iStart == iEnd ) |
73 | { | 73 | { |
74 | // The ringbuffer is full | 74 | // The ringbuffer is full |
75 | dequeue(); | 75 | dequeue(); |
76 | } | 76 | } |
77 | va.construct( &aData[iEnd], v ); | 77 | va.construct( &aData[iEnd], v ); |
78 | iEnd = (iEnd+1)%iCapacity; | 78 | iEnd = (iEnd+1)%iCapacity; |
79 | } | 79 | } |
80 | 80 | ||
81 | value dequeue() | 81 | value dequeue() |
82 | { | 82 | { |
83 | if( iStart == -1 ) | 83 | if( iStart == -1 ) |
84 | { | 84 | { |
85 | throw ExceptionBase("No data"); | 85 | throw ExceptionBase("No data"); |
86 | } | 86 | } |
87 | else | 87 | else |
88 | { | 88 | { |
89 | value &v = aData[iStart]; | 89 | value &v = aData[iStart]; |
90 | va.destroy( &aData[iStart] ); | 90 | va.destroy( &aData[iStart] ); |
91 | iStart = (iStart+1)%iCapacity; | 91 | iStart = (iStart+1)%iCapacity; |
92 | if( iStart == iEnd ) | 92 | if( iStart == iEnd ) |
93 | { | 93 | { |
94 | iStart = -1; | 94 | iStart = -1; |
95 | iEnd = -2; | 95 | iEnd = -2; |
96 | } | 96 | } |
97 | return v; | 97 | return v; |
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | value &get( int iIndex ) | 101 | value &get( int iIndex ) |
102 | { | 102 | { |
103 | return aData[(iIndex+iStart)%iCapacity]; | 103 | return aData[(iIndex+iStart)%iCapacity]; |
104 | } | 104 | } |
105 | 105 | ||
106 | value &first() | 106 | value &first() |
107 | { | 107 | { |
108 | return aData[iStart]; | 108 | return aData[iStart]; |
109 | } | 109 | } |
110 | 110 | ||
111 | value &last() | 111 | value &last() |
112 | { | 112 | { |
113 | return aData[(iEnd-1+iCapacity)%iCapacity]; | 113 | return aData[(iEnd-1+iCapacity)%iCapacity]; |
114 | } | 114 | } |
115 | 115 | ||
116 | int getSize() | 116 | int getSize() |
117 | { | 117 | { |
118 | if( iStart < 0 ) | 118 | if( iStart < 0 ) |
119 | return 0; | 119 | return 0; |
120 | if( iEnd == iStart ) | 120 | if( iEnd == iStart ) |
121 | return iCapacity; | 121 | return iCapacity; |
122 | if( iEnd < iStart ) | 122 | if( iEnd < iStart ) |
123 | return iEnd-iStart; | 123 | return iEnd-iStart; |
124 | return iCapacity-(iEnd-iStart); | 124 | return iCapacity-(iEnd-iStart); |
125 | } | 125 | } |
126 | 126 | ||
127 | int iCapacity; | 127 | int iCapacity; |
128 | int iStart, iEnd; | 128 | int iStart, iEnd; |
129 | value *aData; | 129 | value *aData; |
130 | valuealloc va; | 130 | valuealloc va; |
131 | }; | 131 | }; |
132 | /** @endcond */ | 132 | /** @endcond */ |
133 | 133 | ||
134 | /** | 134 | /** |
135 | *@ingroup Containers | 135 | *@ingroup Containers |
136 | */ | 136 | */ |
137 | template<typename value, typename valuealloc=std::allocator<value> > | 137 | template<typename value, typename valuealloc=std::allocator<value> > |
138 | class RingBuffer : public Queue<value>, public SharedCore< | 138 | class RingBuffer : public Queue<value>, public SharedCore< |
139 | RingBuffer<value, valuealloc>, | 139 | RingBuffer<value, valuealloc>, |
140 | RingBufferCore<value, valuealloc> | 140 | RingBufferCore<value, valuealloc> |
141 | > | 141 | > |
142 | { | 142 | { |
143 | private: | 143 | private: |
144 | typedef RingBuffer<value, valuealloc> MyType; | 144 | typedef RingBuffer<value, valuealloc> MyType; |
145 | typedef RingBufferCore<value, valuealloc> Core; | 145 | typedef RingBufferCore<value, valuealloc> Core; |
146 | 146 | ||
147 | protected: | 147 | protected: |
148 | using SharedCore<MyType, Core>::core; | 148 | using SharedCore<MyType, Core>::core; |
149 | using SharedCore<MyType, Core>::_hardCopy; | 149 | using SharedCore<MyType, Core>::_hardCopy; |
150 | using SharedCore<MyType, Core>::_allocateCore; | 150 | using SharedCore<MyType, Core>::_allocateCore; |
151 | 151 | ||
152 | public: | 152 | public: |
153 | RingBuffer( int iCapacity ) | 153 | RingBuffer( int iCapacity ) |
154 | { | 154 | { |
155 | core->init( iCapacity ); | 155 | core->init( iCapacity ); |
156 | } | 156 | } |
157 | 157 | ||
158 | RingBuffer( const RingBuffer &rSrc ) : | 158 | RingBuffer( const RingBuffer &rSrc ) : |
159 | SharedCore<MyType, Core>( rSrc ) | 159 | SharedCore<MyType, Core>( rSrc ) |
160 | { | 160 | { |
161 | } | 161 | } |
162 | 162 | ||
163 | virtual ~RingBuffer() | 163 | virtual ~RingBuffer() |
164 | { | 164 | { |
165 | } | 165 | } |
166 | 166 | ||
167 | int getCapacity() const | 167 | int getCapacity() const |
168 | { | 168 | { |
169 | return core->iCapacity; | 169 | return core->iCapacity; |
170 | } | 170 | } |
171 | 171 | ||
172 | bool isFilled() const | 172 | bool isFilled() const |
173 | { | 173 | { |
174 | return (core->iStart == core->iEnd); | 174 | return (core->iStart == core->iEnd); |
175 | } | 175 | } |
176 | 176 | ||
177 | bool isEmpty() const | 177 | bool isEmpty() const |
178 | { | 178 | { |
179 | return (core->iStart == -1); | 179 | return (core->iStart == -1); |
180 | } | 180 | } |
181 | 181 | ||
182 | virtual void enqueue( const value &v ) | 182 | virtual void enqueue( const value &v ) |
183 | { | 183 | { |
184 | _hardCopy(); | 184 | _hardCopy(); |
185 | 185 | ||
186 | core->enqueue( v ); | 186 | core->enqueue( v ); |
187 | } | 187 | } |
188 | 188 | ||
189 | virtual value dequeue() | 189 | virtual value dequeue() |
190 | { | 190 | { |
191 | _hardCopy(); | 191 | _hardCopy(); |
192 | 192 | ||
193 | return core->dequeue(); | 193 | return core->dequeue(); |
194 | } | 194 | } |
195 | 195 | ||
196 | virtual int getSize() const | 196 | virtual int getSize() const |
197 | { | 197 | { |
198 | return core->getSize(); | 198 | return core->getSize(); |
199 | } | 199 | } |
200 | 200 | ||
201 | virtual value &peek() | 201 | virtual value &peek() |
202 | { | 202 | { |
203 | _hardCopy(); | 203 | _hardCopy(); |
204 | 204 | ||
205 | return core->get( 0 ); | 205 | return core->get( 0 ); |
206 | } | 206 | } |
207 | 207 | ||
208 | virtual const value &peek() const | 208 | virtual const value &peek() const |
209 | { | 209 | { |
210 | return core->get( 0 ); | 210 | return core->get( 0 ); |
211 | } | 211 | } |
212 | 212 | ||
213 | virtual value &first() | 213 | virtual value &first() |
214 | { | 214 | { |
215 | _hardCopy(); | 215 | _hardCopy(); |
216 | 216 | ||
217 | return core->first(); | 217 | return core->first(); |
218 | } | 218 | } |
219 | 219 | ||
220 | virtual value &last() | 220 | virtual value &last() |
221 | { | 221 | { |
222 | _hardCopy(); | 222 | _hardCopy(); |
223 | 223 | ||
224 | return core->last(); | 224 | return core->last(); |
225 | } | 225 | } |
226 | 226 | ||
227 | value &operator[]( int iIndex ) | 227 | value &operator[]( int iIndex ) |
228 | { | 228 | { |
229 | _hardCopy(); | 229 | _hardCopy(); |
230 | 230 | ||
231 | return core->get( iIndex ); | 231 | return core->get( iIndex ); |
232 | } | 232 | } |
233 | 233 | ||
234 | protected: | 234 | protected: |
235 | virtual Core *_copyCore( Core *src ) | 235 | virtual Core *_copyCore( Core *src ) |
236 | { | 236 | { |
237 | Core *pRet = _allocateCore(); | 237 | Core *pRet = _allocateCore(); |
238 | 238 | ||
239 | pRet->init( src->iCapacity ); | 239 | pRet->init( src->iCapacity ); |
240 | int iSize = src->getSize(); | 240 | int iSize = src->getSize(); |
241 | for( int j = 0; j < iSize; j++ ) | 241 | for( int j = 0; j < iSize; j++ ) |
242 | { | 242 | { |
243 | pRet->enqueue( src->get( j ) ); | 243 | pRet->enqueue( src->get( j ) ); |
244 | } | 244 | } |
245 | 245 | ||
246 | return pRet; | 246 | return pRet; |
247 | } | 247 | } |
248 | }; | 248 | }; |
249 | } | 249 | } |
250 | 250 | ||
251 | #endif | 251 | #endif |
diff --git a/src/stable/server.cpp b/src/stable/server.cpp index 39ff7bb..e6c256e 100644 --- a/src/stable/server.cpp +++ b/src/stable/server.cpp | |||
@@ -14,138 +14,138 @@ | |||
14 | #include "bu/config.h" | 14 | #include "bu/config.h" |
15 | 15 | ||
16 | Bu::Server::Server() : | 16 | Bu::Server::Server() : |
17 | nTimeoutSec( 0 ), | 17 | nTimeoutSec( 0 ), |
18 | nTimeoutUSec( 0 ), | 18 | nTimeoutUSec( 0 ), |
19 | bAutoTick( false ) | 19 | bAutoTick( false ) |
20 | { | 20 | { |
21 | FD_ZERO( &fdActive ); | 21 | FD_ZERO( &fdActive ); |
22 | } | 22 | } |
23 | 23 | ||
24 | Bu::Server::~Server() | 24 | Bu::Server::~Server() |
25 | { | 25 | { |
26 | shutdown(); | 26 | shutdown(); |
27 | } | 27 | } |
28 | 28 | ||
29 | void Bu::Server::addPort( int nPort, int nPoolSize ) | 29 | void Bu::Server::addPort( int nPort, int nPoolSize ) |
30 | { | 30 | { |
31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); | 31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); |
32 | socket_t nSocket = s->getSocket(); | 32 | socket_t nSocket = s->getSocket(); |
33 | FD_SET( nSocket, &fdActive ); | 33 | FD_SET( nSocket, &fdActive ); |
34 | hServers.insert( nSocket, s ); | 34 | hServers.insert( nSocket, s ); |
35 | } | 35 | } |
36 | 36 | ||
37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) | 37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) |
38 | { | 38 | { |
39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); | 39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); |
40 | socket_t nSocket = s->getSocket(); | 40 | socket_t nSocket = s->getSocket(); |
41 | FD_SET( nSocket, &fdActive ); | 41 | FD_SET( nSocket, &fdActive ); |
42 | hServers.insert( nSocket, s ); | 42 | hServers.insert( nSocket, s ); |
43 | } | 43 | } |
44 | 44 | ||
45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) | 45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) |
46 | { | 46 | { |
47 | this->nTimeoutSec = nTimeoutSec; | 47 | this->nTimeoutSec = nTimeoutSec; |
48 | this->nTimeoutUSec = nTimeoutUSec; | 48 | this->nTimeoutUSec = nTimeoutUSec; |
49 | } | 49 | } |
50 | 50 | ||
51 | void Bu::Server::scan() | 51 | void Bu::Server::scan() |
52 | { | 52 | { |
53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; | 53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; |
54 | 54 | ||
55 | fd_set fdRead = fdActive; | 55 | fd_set fdRead = fdActive; |
56 | fd_set fdWrite /* = fdActive*/; | 56 | fd_set fdWrite /* = fdActive*/; |
57 | fd_set fdException = fdActive; | 57 | fd_set fdException = fdActive; |
58 | 58 | ||
59 | FD_ZERO( &fdWrite ); | 59 | FD_ZERO( &fdWrite ); |
60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
61 | { | 61 | { |
62 | if( (*i)->hasOutput() ) | 62 | if( (*i)->hasOutput() ) |
63 | FD_SET( i.getKey(), &fdWrite ); | 63 | FD_SET( i.getKey(), &fdWrite ); |
64 | } | 64 | } |
65 | 65 | ||
66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, | 66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, |
67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) | 67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) |
68 | { | 68 | { |
69 | throw ExceptionBase("Error attempting to scan open connections."); | 69 | throw ExceptionBase("Error attempting to scan open connections."); |
70 | } | 70 | } |
71 | 71 | ||
72 | for( int j = 0; j < FD_SETSIZE; j++ ) | 72 | for( int j = 0; j < FD_SETSIZE; j++ ) |
73 | { | 73 | { |
74 | if( FD_ISSET( j, &fdRead ) ) | 74 | if( FD_ISSET( j, &fdRead ) ) |
75 | { | 75 | { |
76 | if( hServers.has( j ) ) | 76 | if( hServers.has( j ) ) |
77 | { | 77 | { |
78 | TcpServerSocket *pSrv = hServers.get( j ); | 78 | TcpServerSocket *pSrv = hServers.get( j ); |
79 | addClient( pSrv->accept(), pSrv->getPort() ); | 79 | addClient( pSrv->accept(), pSrv->getPort() ); |
80 | } | 80 | } |
81 | else | 81 | else |
82 | { | 82 | { |
83 | Client *pClient = hClients.get( j ); | 83 | Client *pClient = hClients.get( j ); |
84 | pClient->processInput(); | 84 | pClient->processInput(); |
85 | if( !pClient->isOpen() ) | 85 | if( !pClient->isOpen() ) |
86 | { | 86 | { |
87 | closeClient( j ); | 87 | closeClient( j ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | } | 90 | } |
91 | if( FD_ISSET( j, &fdWrite ) ) | 91 | if( FD_ISSET( j, &fdWrite ) ) |
92 | { | 92 | { |
93 | try | 93 | try |
94 | { | 94 | { |
95 | Client *pClient = hClients.get( j ); | 95 | Client *pClient = hClients.get( j ); |
96 | try | 96 | try |
97 | { | 97 | { |
98 | pClient->processOutput(); | 98 | pClient->processOutput(); |
99 | } | 99 | } |
100 | catch( Bu::TcpSocketException &e ) | 100 | catch( Bu::TcpSocketException &e ) |
101 | { | 101 | { |
102 | closeClient( j ); | 102 | closeClient( j ); |
103 | } | 103 | } |
104 | } | 104 | } |
105 | catch( Bu::HashException &e ) | 105 | catch( Bu::HashException &e ) |
106 | { | 106 | { |
107 | // Do nothing, I guess, the client is already dead... | 107 | // Do nothing, I guess, the client is already dead... |
108 | // TODO: Someday, we may want to handle this more graceully. | 108 | // TODO: Someday, we may want to handle this more graceully. |
109 | } | 109 | } |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | Bu::List<int> lDelete; | 113 | Bu::List<int> lDelete; |
114 | // Now we just try to write all the pending data on all the sockets. | 114 | // Now we just try to write all the pending data on all the sockets. |
115 | // this could be done better eventually, if we care about the socket | 115 | // this could be done better eventually, if we care about the socket |
116 | // wanting to accept writes (using a select). | 116 | // wanting to accept writes (using a select). |
117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
118 | { | 118 | { |
119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) | 119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) |
120 | { | 120 | { |
121 | lDelete.append( i.getKey() ); | 121 | lDelete.append( i.getKey() ); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) | 125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) |
126 | { | 126 | { |
127 | closeClient( *i ); | 127 | closeClient( *i ); |
128 | } | 128 | } |
129 | 129 | ||
130 | if( bAutoTick ) | 130 | if( bAutoTick ) |
131 | tick(); | 131 | tick(); |
132 | } | 132 | } |
133 | 133 | ||
134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) | 134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) |
135 | { | 135 | { |
136 | FD_SET( nSocket, &fdActive ); | 136 | FD_SET( nSocket, &fdActive ); |
137 | 137 | ||
138 | Client *c = new Client( | 138 | Client *c = new Client( |
139 | new Bu::TcpSocket( nSocket ), | 139 | new Bu::TcpSocket( nSocket ), |
140 | new SrvClientLinkFactory() | 140 | new SrvClientLinkFactory() |
141 | ); | 141 | ); |
142 | hClients.insert( nSocket, c ); | 142 | hClients.insert( nSocket, c ); |
143 | 143 | ||
144 | onNewConnection( c, nPort ); | 144 | onNewConnection( c, nPort ); |
145 | } | 145 | } |
146 | 146 | ||
147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : | 147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : |
148 | pClient( pClient ) | 148 | pClient( pClient ) |
149 | { | 149 | { |
150 | } | 150 | } |
151 | 151 | ||
@@ -155,7 +155,7 @@ Bu::Server::SrvClientLink::~SrvClientLink() | |||
155 | 155 | ||
156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) | 156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) |
157 | { | 157 | { |
158 | pClient->onMessage( sMsg ); | 158 | pClient->onMessage( sMsg ); |
159 | } | 159 | } |
160 | 160 | ||
161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() | 161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() |
@@ -167,48 +167,48 @@ Bu::Server::SrvClientLinkFactory::~SrvClientLinkFactory() | |||
167 | } | 167 | } |
168 | 168 | ||
169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( | 169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( |
170 | Bu::Client *pClient ) | 170 | Bu::Client *pClient ) |
171 | { | 171 | { |
172 | return new SrvClientLink( pClient ); | 172 | return new SrvClientLink( pClient ); |
173 | } | 173 | } |
174 | 174 | ||
175 | void Bu::Server::setAutoTick( bool bEnable ) | 175 | void Bu::Server::setAutoTick( bool bEnable ) |
176 | { | 176 | { |
177 | bAutoTick = bEnable; | 177 | bAutoTick = bEnable; |
178 | } | 178 | } |
179 | 179 | ||
180 | void Bu::Server::tick() | 180 | void Bu::Server::tick() |
181 | { | 181 | { |
182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
183 | { | 183 | { |
184 | (*i)->tick(); | 184 | (*i)->tick(); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | void Bu::Server::shutdown() | 188 | void Bu::Server::shutdown() |
189 | { | 189 | { |
190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) | 190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) |
191 | { | 191 | { |
192 | delete *i; | 192 | delete *i; |
193 | } | 193 | } |
194 | 194 | ||
195 | hServers.clear(); | 195 | hServers.clear(); |
196 | 196 | ||
197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) |
198 | { | 198 | { |
199 | closeClient( i.getKey() ); | 199 | closeClient( i.getKey() ); |
200 | } | 200 | } |
201 | 201 | ||
202 | hClients.clear(); | 202 | hClients.clear(); |
203 | } | 203 | } |
204 | 204 | ||
205 | void Bu::Server::closeClient( socket_t iSocket ) | 205 | void Bu::Server::closeClient( socket_t iSocket ) |
206 | { | 206 | { |
207 | Bu::Client *pClient = hClients.get( iSocket ); | 207 | Bu::Client *pClient = hClients.get( iSocket ); |
208 | onClosedConnection( pClient ); | 208 | onClosedConnection( pClient ); |
209 | pClient->close(); | 209 | pClient->close(); |
210 | hClients.erase( iSocket ); | 210 | hClients.erase( iSocket ); |
211 | FD_CLR( iSocket, &fdActive ); | 211 | FD_CLR( iSocket, &fdActive ); |
212 | delete pClient; | 212 | delete pClient; |
213 | } | 213 | } |
214 | 214 | ||
diff --git a/src/stable/server.h b/src/stable/server.h index 5a414d9..05ec018 100644 --- a/src/stable/server.h +++ b/src/stable/server.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <stdint.h> | 11 | #include <stdint.h> |
12 | 12 | ||
13 | #ifndef WIN32 | 13 | #ifndef WIN32 |
14 | #include <sys/select.h> | 14 | #include <sys/select.h> |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #include "bu/string.h" | 17 | #include "bu/string.h" |
@@ -25,90 +25,90 @@ | |||
25 | 25 | ||
26 | namespace Bu | 26 | namespace Bu |
27 | { | 27 | { |
28 | class TcpServerSocket; | 28 | class TcpServerSocket; |
29 | class TcpSocket; | 29 | class TcpSocket; |
30 | class Client; | 30 | class Client; |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * Core of a network server. This class is distinct from a ServerSocket in | 33 | * Core of a network server. This class is distinct from a ServerSocket in |
34 | * that a ServerSocket is one listening socket, nothing more. Socket will | 34 | * that a ServerSocket is one listening socket, nothing more. Socket will |
35 | * manage a pool of both ServerSockets and connected Sockets along with | 35 | * manage a pool of both ServerSockets and connected Sockets along with |
36 | * their protocols and buffers. | 36 | * their protocols and buffers. |
37 | * | 37 | * |
38 | * To start serving on a new port, use the addPort functions. Each call to | 38 | * To start serving on a new port, use the addPort functions. Each call to |
39 | * addPort creates a new ServerSocket, starts it listening, and adds it to | 39 | * addPort creates a new ServerSocket, starts it listening, and adds it to |
40 | * the server pool. | 40 | * the server pool. |
41 | * | 41 | * |
42 | * All of the real work is done by scan, which will wait for up | 42 | * All of the real work is done by scan, which will wait for up |
43 | * to the timeout set by setTimeout before returning if there is no data | 43 | * to the timeout set by setTimeout before returning if there is no data |
44 | * pending. scan should probably be called in some sort of tight | 44 | * pending. scan should probably be called in some sort of tight |
45 | * loop, possibly in it's own thread, or in the main control loop. | 45 | * loop, possibly in it's own thread, or in the main control loop. |
46 | * | 46 | * |
47 | * In order to use a Server you must subclass it and implement the pure | 47 | * In order to use a Server you must subclass it and implement the pure |
48 | * virtual functions. These allow you to receive notification of events | 48 | * virtual functions. These allow you to receive notification of events |
49 | * happening within the server itself, and actually makes it useful. | 49 | * happening within the server itself, and actually makes it useful. |
50 | *@ingroup Serving | 50 | *@ingroup Serving |
51 | */ | 51 | */ |
52 | class Server | 52 | class Server |
53 | { | 53 | { |
54 | public: | 54 | public: |
55 | Server(); | 55 | Server(); |
56 | virtual ~Server(); | 56 | virtual ~Server(); |
57 | 57 | ||
58 | #ifdef WIN32 | 58 | #ifdef WIN32 |
59 | typedef unsigned int socket_t; | 59 | typedef unsigned int socket_t; |
60 | #else | 60 | #else |
61 | typedef int socket_t; | 61 | typedef int socket_t; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | void addPort( int nPort, int nPoolSize=40 ); | 64 | void addPort( int nPort, int nPoolSize=40 ); |
65 | void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); | 65 | void addPort( const String &sAddr, int nPort, int nPoolSize=40 ); |
66 | 66 | ||
67 | virtual void scan(); | 67 | virtual void scan(); |
68 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); | 68 | void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); |
69 | 69 | ||
70 | void addClient( socket_t nSocket, int nPort ); | 70 | void addClient( socket_t nSocket, int nPort ); |
71 | 71 | ||
72 | void setAutoTick( bool bEnable=true ); | 72 | void setAutoTick( bool bEnable=true ); |
73 | void tick(); | 73 | void tick(); |
74 | 74 | ||
75 | virtual void onNewConnection( Client *pClient, int nPort )=0; | 75 | virtual void onNewConnection( Client *pClient, int nPort )=0; |
76 | virtual void onClosedConnection( Client *pClient )=0; | 76 | virtual void onClosedConnection( Client *pClient )=0; |
77 | 77 | ||
78 | void shutdown(); | 78 | void shutdown(); |
79 | 79 | ||
80 | private: | 80 | private: |
81 | void closeClient( socket_t iSocket ); | 81 | void closeClient( socket_t iSocket ); |
82 | class SrvClientLink : public Bu::ClientLink | 82 | class SrvClientLink : public Bu::ClientLink |
83 | { | 83 | { |
84 | public: | 84 | public: |
85 | SrvClientLink( Bu::Client *pClient ); | 85 | SrvClientLink( Bu::Client *pClient ); |
86 | virtual ~SrvClientLink(); | 86 | virtual ~SrvClientLink(); |
87 | 87 | ||
88 | virtual void sendMessage( const Bu::String &sMsg ); | 88 | virtual void sendMessage( const Bu::String &sMsg ); |
89 | 89 | ||
90 | private: | 90 | private: |
91 | Bu::Client *pClient; | 91 | Bu::Client *pClient; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | class SrvClientLinkFactory : public Bu::ClientLinkFactory | 94 | class SrvClientLinkFactory : public Bu::ClientLinkFactory |
95 | { | 95 | { |
96 | public: | 96 | public: |
97 | SrvClientLinkFactory(); | 97 | SrvClientLinkFactory(); |
98 | virtual ~SrvClientLinkFactory(); | 98 | virtual ~SrvClientLinkFactory(); |
99 | 99 | ||
100 | virtual Bu::ClientLink *createLink( Bu::Client *pClient ); | 100 | virtual Bu::ClientLink *createLink( Bu::Client *pClient ); |
101 | }; | 101 | }; |
102 | 102 | ||
103 | int nTimeoutSec; | 103 | int nTimeoutSec; |
104 | int nTimeoutUSec; | 104 | int nTimeoutUSec; |
105 | fd_set fdActive; | 105 | fd_set fdActive; |
106 | typedef Hash<socket_t,TcpServerSocket *> SrvHash; | 106 | typedef Hash<socket_t,TcpServerSocket *> SrvHash; |
107 | SrvHash hServers; | 107 | SrvHash hServers; |
108 | typedef Hash<socket_t,Client *> ClientHash; | 108 | typedef Hash<socket_t,Client *> ClientHash; |
109 | ClientHash hClients; | 109 | ClientHash hClients; |
110 | bool bAutoTick; | 110 | bool bAutoTick; |
111 | }; | 111 | }; |
112 | } | 112 | } |
113 | 113 | ||
114 | #endif | 114 | #endif |
diff --git a/src/stable/sha1.cpp b/src/stable/sha1.cpp index e6a85cc..30e5dc8 100644 --- a/src/stable/sha1.cpp +++ b/src/stable/sha1.cpp | |||
@@ -12,15 +12,15 @@ | |||
12 | #include "bu/sha1.h" | 12 | #include "bu/sha1.h" |
13 | 13 | ||
14 | Bu::Sha1::Sha1() : | 14 | Bu::Sha1::Sha1() : |
15 | uH0( 0x67452301 ), | 15 | uH0( 0x67452301 ), |
16 | uH1( 0xefcdab89 ), | 16 | uH1( 0xefcdab89 ), |
17 | uH2( 0x98badcfe ), | 17 | uH2( 0x98badcfe ), |
18 | uH3( 0x10325476 ), | 18 | uH3( 0x10325476 ), |
19 | uH4( 0xc3d2e1f0 ), | 19 | uH4( 0xc3d2e1f0 ), |
20 | iUnprocessedBytes( 0 ), | 20 | iUnprocessedBytes( 0 ), |
21 | uTotalBytes( 0 ) | 21 | uTotalBytes( 0 ) |
22 | { | 22 | { |
23 | reset(); | 23 | reset(); |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::Sha1::~Sha1() | 26 | Bu::Sha1::~Sha1() |
@@ -29,13 +29,13 @@ Bu::Sha1::~Sha1() | |||
29 | 29 | ||
30 | void Bu::Sha1::reset() | 30 | void Bu::Sha1::reset() |
31 | { | 31 | { |
32 | uH0 = 0x67452301; | 32 | uH0 = 0x67452301; |
33 | uH1 = 0xefcdab89; | 33 | uH1 = 0xefcdab89; |
34 | uH2 = 0x98badcfe; | 34 | uH2 = 0x98badcfe; |
35 | uH3 = 0x10325476; | 35 | uH3 = 0x10325476; |
36 | uH4 = 0xc3d2e1f0; | 36 | uH4 = 0xc3d2e1f0; |
37 | iUnprocessedBytes = 0; | 37 | iUnprocessedBytes = 0; |
38 | uTotalBytes = 0; | 38 | uTotalBytes = 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) | 41 | void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) |
@@ -44,151 +44,151 @@ void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ ) | |||
44 | 44 | ||
45 | void Bu::Sha1::addData( const void *sDataRaw, int iSize ) | 45 | void Bu::Sha1::addData( const void *sDataRaw, int iSize ) |
46 | { | 46 | { |
47 | const unsigned char *sData = (const unsigned char *)sDataRaw; | 47 | const unsigned char *sData = (const unsigned char *)sDataRaw; |
48 | // add these bytes to the running total | 48 | // add these bytes to the running total |
49 | uTotalBytes += iSize; | 49 | uTotalBytes += iSize; |
50 | 50 | ||
51 | // repeat until all data is processed | 51 | // repeat until all data is processed |
52 | while( iSize > 0 ) | 52 | while( iSize > 0 ) |
53 | { | 53 | { |
54 | // number of bytes required to complete block | 54 | // number of bytes required to complete block |
55 | int iNeeded = 64 - iUnprocessedBytes; | 55 | int iNeeded = 64 - iUnprocessedBytes; |
56 | 56 | ||
57 | // number of bytes to copy (use smaller of two) | 57 | // number of bytes to copy (use smaller of two) |
58 | int iToCopy = (iSize < iNeeded) ? iSize : iNeeded; | 58 | int iToCopy = (iSize < iNeeded) ? iSize : iNeeded; |
59 | 59 | ||
60 | // Copy the bytes | 60 | // Copy the bytes |
61 | memcpy( uBytes + iUnprocessedBytes, sData, iToCopy ); | 61 | memcpy( uBytes + iUnprocessedBytes, sData, iToCopy ); |
62 | 62 | ||
63 | // Bytes have been copied | 63 | // Bytes have been copied |
64 | iSize -= iToCopy; | 64 | iSize -= iToCopy; |
65 | sData += iToCopy; | 65 | sData += iToCopy; |
66 | iUnprocessedBytes += iToCopy; | 66 | iUnprocessedBytes += iToCopy; |
67 | 67 | ||
68 | // there is a full block | 68 | // there is a full block |
69 | if( iUnprocessedBytes == 64 ) | 69 | if( iUnprocessedBytes == 64 ) |
70 | { | 70 | { |
71 | process(); | 71 | process(); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | Bu::String Bu::Sha1::getResult() | 76 | Bu::String Bu::Sha1::getResult() |
77 | { | 77 | { |
78 | // save the message size | 78 | // save the message size |
79 | uint32_t totalBitsL = uTotalBytes << 3; | 79 | uint32_t totalBitsL = uTotalBytes << 3; |
80 | uint32_t totalBitsH = uTotalBytes >> 29; | 80 | uint32_t totalBitsH = uTotalBytes >> 29; |
81 | 81 | ||
82 | // add 0x80 to the message | 82 | // add 0x80 to the message |
83 | addData( "\x80", 1 ); | 83 | addData( "\x80", 1 ); |
84 | 84 | ||
85 | unsigned char footer[64] = { | 85 | unsigned char footer[64] = { |
86 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 86 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
87 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 87 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
88 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 88 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
90 | 90 | ||
91 | // block has no room for 8-byte filesize, so finish it | 91 | // block has no room for 8-byte filesize, so finish it |
92 | if( iUnprocessedBytes > 56 ) | 92 | if( iUnprocessedBytes > 56 ) |
93 | addData( (char*)footer, 64 - iUnprocessedBytes); | 93 | addData( (char*)footer, 64 - iUnprocessedBytes); |
94 | 94 | ||
95 | // how many zeros do we need | 95 | // how many zeros do we need |
96 | int iNeededZeros = 56 - iUnprocessedBytes; | 96 | int iNeededZeros = 56 - iUnprocessedBytes; |
97 | 97 | ||
98 | // store file size (in bits) in big-endian format | 98 | // store file size (in bits) in big-endian format |
99 | toBigEndian( totalBitsH, footer + iNeededZeros ); | 99 | toBigEndian( totalBitsH, footer + iNeededZeros ); |
100 | toBigEndian( totalBitsL, footer + iNeededZeros + 4 ); | 100 | toBigEndian( totalBitsL, footer + iNeededZeros + 4 ); |
101 | 101 | ||
102 | // finish the final block | 102 | // finish the final block |
103 | addData( (char*)footer, iNeededZeros + 8 ); | 103 | addData( (char*)footer, iNeededZeros + 8 ); |
104 | 104 | ||
105 | Bu::String sRet( 20 ); | 105 | Bu::String sRet( 20 ); |
106 | 106 | ||
107 | unsigned char *digest = (unsigned char *)sRet.getStr(); | 107 | unsigned char *digest = (unsigned char *)sRet.getStr(); |
108 | 108 | ||
109 | // copy the digest bytes | 109 | // copy the digest bytes |
110 | toBigEndian( uH0, digest ); | 110 | toBigEndian( uH0, digest ); |
111 | toBigEndian( uH1, digest + 4 ); | 111 | toBigEndian( uH1, digest + 4 ); |
112 | toBigEndian( uH2, digest + 8 ); | 112 | toBigEndian( uH2, digest + 8 ); |
113 | toBigEndian( uH3, digest + 12 ); | 113 | toBigEndian( uH3, digest + 12 ); |
114 | toBigEndian( uH4, digest + 16 ); | 114 | toBigEndian( uH4, digest + 16 ); |
115 | 115 | ||
116 | // return the digest | 116 | // return the digest |
117 | return sRet; | 117 | return sRet; |
118 | } | 118 | } |
119 | 119 | ||
120 | void Bu::Sha1::writeResult( Bu::Stream &sOut ) | 120 | void Bu::Sha1::writeResult( Bu::Stream &sOut ) |
121 | { | 121 | { |
122 | sOut.write( getResult() ); | 122 | sOut.write( getResult() ); |
123 | } | 123 | } |
124 | 124 | ||
125 | void Bu::Sha1::process() | 125 | void Bu::Sha1::process() |
126 | { | 126 | { |
127 | int t; | 127 | int t; |
128 | uint32_t a, b, c, d, e, K, f, W[80]; | 128 | uint32_t a, b, c, d, e, K, f, W[80]; |
129 | 129 | ||
130 | // starting values | 130 | // starting values |
131 | a = uH0; | 131 | a = uH0; |
132 | b = uH1; | 132 | b = uH1; |
133 | c = uH2; | 133 | c = uH2; |
134 | d = uH3; | 134 | d = uH3; |
135 | e = uH4; | 135 | e = uH4; |
136 | 136 | ||
137 | // copy and expand the message block | 137 | // copy and expand the message block |
138 | for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24) | 138 | for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24) |
139 | +(uBytes[t*4 + 1] << 16) | 139 | +(uBytes[t*4 + 1] << 16) |
140 | +(uBytes[t*4 + 2] << 8) | 140 | +(uBytes[t*4 + 2] << 8) |
141 | + uBytes[t*4 + 3]; | 141 | + uBytes[t*4 + 3]; |
142 | for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); | 142 | for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); |
143 | 143 | ||
144 | /* main loop */ | 144 | /* main loop */ |
145 | uint32_t temp; | 145 | uint32_t temp; |
146 | for( t = 0; t < 80; t++ ) | 146 | for( t = 0; t < 80; t++ ) |
147 | { | 147 | { |
148 | if( t < 20 ) { | 148 | if( t < 20 ) { |
149 | K = 0x5a827999; | 149 | K = 0x5a827999; |
150 | f = (b & c) | ((~b) & d); | 150 | f = (b & c) | ((~b) & d); |
151 | } else if( t < 40 ) { | 151 | } else if( t < 40 ) { |
152 | K = 0x6ed9eba1; | 152 | K = 0x6ed9eba1; |
153 | f = b ^ c ^ d; | 153 | f = b ^ c ^ d; |
154 | } else if( t < 60 ) { | 154 | } else if( t < 60 ) { |
155 | K = 0x8f1bbcdc; | 155 | K = 0x8f1bbcdc; |
156 | f = (b & c) | (b & d) | (c & d); | 156 | f = (b & c) | (b & d) | (c & d); |
157 | } else { | 157 | } else { |
158 | K = 0xca62c1d6; | 158 | K = 0xca62c1d6; |
159 | f = b ^ c ^ d; | 159 | f = b ^ c ^ d; |
160 | } | 160 | } |
161 | temp = lrot(a,5) + f + e + W[t] + K; | 161 | temp = lrot(a,5) + f + e + W[t] + K; |
162 | e = d; | 162 | e = d; |
163 | d = c; | 163 | d = c; |
164 | c = lrot(b,30); | 164 | c = lrot(b,30); |
165 | b = a; | 165 | b = a; |
166 | a = temp; | 166 | a = temp; |
167 | //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); | 167 | //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* add variables */ | 170 | /* add variables */ |
171 | uH0 += a; | 171 | uH0 += a; |
172 | uH1 += b; | 172 | uH1 += b; |
173 | uH2 += c; | 173 | uH2 += c; |
174 | uH3 += d; | 174 | uH3 += d; |
175 | uH4 += e; | 175 | uH4 += e; |
176 | 176 | ||
177 | //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); | 177 | //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); |
178 | /* all bytes have been processed */ | 178 | /* all bytes have been processed */ |
179 | iUnprocessedBytes = 0; | 179 | iUnprocessedBytes = 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) | 182 | uint32_t Bu::Sha1::lrot( uint32_t x, int bits ) |
183 | { | 183 | { |
184 | return (x<<bits) | (x>>(32 - bits)); | 184 | return (x<<bits) | (x>>(32 - bits)); |
185 | } | 185 | } |
186 | 186 | ||
187 | void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) | 187 | void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte ) |
188 | { | 188 | { |
189 | byte[0] = (unsigned char)(num>>24); | 189 | byte[0] = (unsigned char)(num>>24); |
190 | byte[1] = (unsigned char)(num>>16); | 190 | byte[1] = (unsigned char)(num>>16); |
191 | byte[2] = (unsigned char)(num>>8); | 191 | byte[2] = (unsigned char)(num>>8); |
192 | byte[3] = (unsigned char)num; | 192 | byte[3] = (unsigned char)num; |
193 | } | 193 | } |
194 | 194 | ||
diff --git a/src/stable/sha1.h b/src/stable/sha1.h index e861f94..f882473 100644 --- a/src/stable/sha1.h +++ b/src/stable/sha1.h | |||
@@ -13,41 +13,41 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * Calculates SHA-1 sums. This is based strongly on code from Michael D. | 17 | * Calculates SHA-1 sums. This is based strongly on code from Michael D. |
18 | * Leonhard who released his code under the terms of the MIT license, | 18 | * Leonhard who released his code under the terms of the MIT license, |
19 | * thank you! Check out his website http://tamale.net he has a lot of | 19 | * thank you! Check out his website http://tamale.net he has a lot of |
20 | * cool stuff there. | 20 | * cool stuff there. |
21 | */ | 21 | */ |
22 | class Sha1 : public CryptoHash | 22 | class Sha1 : public CryptoHash |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | Sha1(); | 25 | Sha1(); |
26 | virtual ~Sha1(); | 26 | virtual ~Sha1(); |
27 | 27 | ||
28 | virtual void reset(); | 28 | virtual void reset(); |
29 | virtual void setSalt( const Bu::String &sSalt ); | 29 | virtual void setSalt( const Bu::String &sSalt ); |
30 | virtual void addData( const void *sData, int iSize ); | 30 | virtual void addData( const void *sData, int iSize ); |
31 | using CryptoHash::addData; | 31 | using CryptoHash::addData; |
32 | virtual String getResult(); | 32 | virtual String getResult(); |
33 | virtual void writeResult( Stream &sOut ); | 33 | virtual void writeResult( Stream &sOut ); |
34 | 34 | ||
35 | void update( const char* data, int num ); | 35 | void update( const char* data, int num ); |
36 | unsigned char* getDigest(); | 36 | unsigned char* getDigest(); |
37 | 37 | ||
38 | // utility methods | 38 | // utility methods |
39 | 39 | ||
40 | private: | 40 | private: |
41 | static uint32_t lrot( uint32_t x, int bits ); | 41 | static uint32_t lrot( uint32_t x, int bits ); |
42 | static void toBigEndian( uint32_t in, unsigned char* out ); | 42 | static void toBigEndian( uint32_t in, unsigned char* out ); |
43 | void process(); | 43 | void process(); |
44 | 44 | ||
45 | private: | 45 | private: |
46 | uint32_t uH0, uH1, uH2, uH3, uH4; | 46 | uint32_t uH0, uH1, uH2, uH3, uH4; |
47 | unsigned char uBytes[64]; | 47 | unsigned char uBytes[64]; |
48 | int iUnprocessedBytes; | 48 | int iUnprocessedBytes; |
49 | uint32_t uTotalBytes; | 49 | uint32_t uTotalBytes; |
50 | }; | 50 | }; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | #endif | 53 | #endif |
diff --git a/src/stable/sharedcore.h b/src/stable/sharedcore.h index f000077..f8b9d4e 100644 --- a/src/stable/sharedcore.h +++ b/src/stable/sharedcore.h | |||
@@ -15,176 +15,176 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * A mechanism for creating classes that perform lazy copies. The concept | 19 | * A mechanism for creating classes that perform lazy copies. The concept |
20 | * behind this is that instead of copying a large object when it is assigned | 20 | * behind this is that instead of copying a large object when it is assigned |
21 | * or passed into a copy constructor we simply copy a pointer internally. | 21 | * or passed into a copy constructor we simply copy a pointer internally. |
22 | * The assumption is that many times when an object is passed by value we | 22 | * The assumption is that many times when an object is passed by value we |
23 | * don't really want to keep the object around, we want the recipient to | 23 | * don't really want to keep the object around, we want the recipient to |
24 | * take ownership without allocating a new object. This allows that to | 24 | * take ownership without allocating a new object. This allows that to |
25 | * happen. | 25 | * happen. |
26 | * | 26 | * |
27 | * When used properly this makes object copying essentially free (O(1), | 27 | * When used properly this makes object copying essentially free (O(1), |
28 | * that is) and performs the actual copy when a user tries to modify the | 28 | * that is) and performs the actual copy when a user tries to modify the |
29 | * object. | 29 | * object. |
30 | * | 30 | * |
31 | * For example, lets look at something like the getKeys function in | 31 | * For example, lets look at something like the getKeys function in |
32 | * Bu::Hash. When this function is called it creates a Bu::List of | 32 | * Bu::Hash. When this function is called it creates a Bu::List of |
33 | * appropriate type, fills it with keys, and returns it. This is a good | 33 | * appropriate type, fills it with keys, and returns it. This is a good |
34 | * way for this function to behave, there may be additional issues if the | 34 | * way for this function to behave, there may be additional issues if the |
35 | * List object were allocated with new and not on the stack. However, | 35 | * List object were allocated with new and not on the stack. However, |
36 | * returning the List at the end of the function could potentially take | 36 | * returning the List at the end of the function could potentially take |
37 | * a very long time depending on the size of the list and the type of the | 37 | * a very long time depending on the size of the list and the type of the |
38 | * key. In this case the getKeys function doesn't want ownership of the | 38 | * key. In this case the getKeys function doesn't want ownership of the |
39 | * List object, and when it returns it, it's local copy will be destroyed. | 39 | * List object, and when it returns it, it's local copy will be destroyed. |
40 | * | 40 | * |
41 | * However, List inherits from SharedCore, which means that when it is | 41 | * However, List inherits from SharedCore, which means that when it is |
42 | * returned all we do is copy a pointer to the "core" of the list, which | 42 | * returned all we do is copy a pointer to the "core" of the list, which |
43 | * is a very fast operatorion. For a brief moment, before anyone can do | 43 | * is a very fast operatorion. For a brief moment, before anyone can do |
44 | * anything else, there are two objects referencing the core of that single | 44 | * anything else, there are two objects referencing the core of that single |
45 | * list. However, the getKeys() function will destroy it's local copy | 45 | * list. However, the getKeys() function will destroy it's local copy |
46 | * before the calling function can use it's new copy. That means that by | 46 | * before the calling function can use it's new copy. That means that by |
47 | * the time the calling function can use it's new List of keys it is the | 47 | * the time the calling function can use it's new List of keys it is the |
48 | * only one with a reference to the core, and no copy will need to happen. | 48 | * only one with a reference to the core, and no copy will need to happen. |
49 | * | 49 | * |
50 | * Using SharedCore on your own classes is fairly straight forward. There | 50 | * Using SharedCore on your own classes is fairly straight forward. There |
51 | * are only a couple of steps. First, break the class into two classes. | 51 | * are only a couple of steps. First, break the class into two classes. |
52 | * Move every variable from the original class (generally everything that's | 52 | * Move every variable from the original class (generally everything that's |
53 | * private) into the new class. Then make the original class inherit from | 53 | * private) into the new class. Then make the original class inherit from |
54 | * SharedCore. The SharedCore template takes 2 parameters, first is the | 54 | * SharedCore. The SharedCore template takes 2 parameters, first is the |
55 | * class it's inheriting from, second is the new core class. Now, in your | 55 | * class it's inheriting from, second is the new core class. Now, in your |
56 | * original class you will have one class variable, a pointer named core. | 56 | * original class you will have one class variable, a pointer named core. |
57 | * All of your original variables will be accessable through core. The next | 57 | * All of your original variables will be accessable through core. The next |
58 | * step is to access everything you used to through core, and to find | 58 | * step is to access everything you used to through core, and to find |
59 | * every function that may change data in the core. At the top of every | 59 | * every function that may change data in the core. At the top of every |
60 | * function that may change data you want to call _hardCopy(). | 60 | * function that may change data you want to call _hardCopy(). |
61 | * | 61 | * |
62 | * That's more or less it. A more detailed guide will be written soon. | 62 | * That's more or less it. A more detailed guide will be written soon. |
63 | * @todo Write a guide for this. | 63 | * @todo Write a guide for this. |
64 | */ | 64 | */ |
65 | template<typename Shell, typename Core> | 65 | template<typename Shell, typename Core> |
66 | class SharedCore | 66 | class SharedCore |
67 | { | 67 | { |
68 | typedef class SharedCore<Shell, Core> _SharedType; | 68 | typedef class SharedCore<Shell, Core> _SharedType; |
69 | public: | 69 | public: |
70 | SharedCore() : | 70 | SharedCore() : |
71 | core( NULL ), | 71 | core( NULL ), |
72 | iRefCount( NULL ) | 72 | iRefCount( NULL ) |
73 | { | 73 | { |
74 | core = _allocateCore(); | 74 | core = _allocateCore(); |
75 | iRefCount = new int(1); | 75 | iRefCount = new int(1); |
76 | } | 76 | } |
77 | 77 | ||
78 | SharedCore( const _SharedType &rSrc ) : | 78 | SharedCore( const _SharedType &rSrc ) : |
79 | core( NULL ), | 79 | core( NULL ), |
80 | iRefCount( NULL ) | 80 | iRefCount( NULL ) |
81 | { | 81 | { |
82 | _softCopy( rSrc ); | 82 | _softCopy( rSrc ); |
83 | } | 83 | } |
84 | 84 | ||
85 | virtual ~SharedCore() | 85 | virtual ~SharedCore() |
86 | { | 86 | { |
87 | _deref(); | 87 | _deref(); |
88 | } | 88 | } |
89 | 89 | ||
90 | SharedCore &operator=( const SharedCore &rhs ) | 90 | SharedCore &operator=( const SharedCore &rhs ) |
91 | { | 91 | { |
92 | if( core == rhs.core ) | 92 | if( core == rhs.core ) |
93 | return *this; | 93 | return *this; |
94 | 94 | ||
95 | _softCopy( rhs ); | 95 | _softCopy( rhs ); |
96 | return *this; | 96 | return *this; |
97 | } | 97 | } |
98 | 98 | ||
99 | int getRefCount() const | 99 | int getRefCount() const |
100 | { | 100 | { |
101 | return *iRefCount; | 101 | return *iRefCount; |
102 | } | 102 | } |
103 | 103 | ||
104 | Shell clone() const | 104 | Shell clone() const |
105 | { | 105 | { |
106 | Shell s( dynamic_cast<const Shell &>(*this) ); | 106 | Shell s( dynamic_cast<const Shell &>(*this) ); |
107 | s._hardCopy(); | 107 | s._hardCopy(); |
108 | return s; | 108 | return s; |
109 | } | 109 | } |
110 | 110 | ||
111 | bool isCoreShared( const Shell &rOther ) const | 111 | bool isCoreShared( const Shell &rOther ) const |
112 | { | 112 | { |
113 | return rOther.core == core; | 113 | return rOther.core == core; |
114 | } | 114 | } |
115 | 115 | ||
116 | protected: | 116 | protected: |
117 | Core *core; | 117 | Core *core; |
118 | void _hardCopy() | 118 | void _hardCopy() |
119 | { | 119 | { |
120 | if( !core || !iRefCount ) | 120 | if( !core || !iRefCount ) |
121 | return; | 121 | return; |
122 | if( (*iRefCount) == 1 ) | 122 | if( (*iRefCount) == 1 ) |
123 | return; | 123 | return; |
124 | Core *copy = _copyCore( core ); | 124 | Core *copy = _copyCore( core ); |
125 | _deref(); | 125 | _deref(); |
126 | core = copy; | 126 | core = copy; |
127 | iRefCount = new int( 1 ); | 127 | iRefCount = new int( 1 ); |
128 | } | 128 | } |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * Reset core acts like a hard copy, except instead of providing a | 131 | * Reset core acts like a hard copy, except instead of providing a |
132 | * standalone copy of the shared core, it provides a brand new core. | 132 | * standalone copy of the shared core, it provides a brand new core. |
133 | * | 133 | * |
134 | * Very useful in functions used to reset the state of an object. | 134 | * Very useful in functions used to reset the state of an object. |
135 | */ | 135 | */ |
136 | void _resetCore() | 136 | void _resetCore() |
137 | { | 137 | { |
138 | if( core ) | 138 | if( core ) |
139 | _deref(); | 139 | _deref(); |
140 | core = _allocateCore(); | 140 | core = _allocateCore(); |
141 | iRefCount = new int( 1 ); | 141 | iRefCount = new int( 1 ); |
142 | } | 142 | } |
143 | 143 | ||
144 | virtual Core *_allocateCore() | 144 | virtual Core *_allocateCore() |
145 | { | 145 | { |
146 | return new Core(); | 146 | return new Core(); |
147 | } | 147 | } |
148 | 148 | ||
149 | virtual Core *_copyCore( Core *pSrc ) | 149 | virtual Core *_copyCore( Core *pSrc ) |
150 | { | 150 | { |
151 | return new Core( *pSrc ); | 151 | return new Core( *pSrc ); |
152 | } | 152 | } |
153 | 153 | ||
154 | virtual void _deallocateCore( Core *pSrc ) | 154 | virtual void _deallocateCore( Core *pSrc ) |
155 | { | 155 | { |
156 | delete pSrc; | 156 | delete pSrc; |
157 | } | 157 | } |
158 | 158 | ||
159 | private: | 159 | private: |
160 | void _deref() | 160 | void _deref() |
161 | { | 161 | { |
162 | if( (--(*iRefCount)) == 0 ) | 162 | if( (--(*iRefCount)) == 0 ) |
163 | { | 163 | { |
164 | _deallocateCore( core ); | 164 | _deallocateCore( core ); |
165 | delete iRefCount; | 165 | delete iRefCount; |
166 | } | 166 | } |
167 | core = NULL; | 167 | core = NULL; |
168 | iRefCount = NULL; | 168 | iRefCount = NULL; |
169 | } | 169 | } |
170 | 170 | ||
171 | void _incRefCount() | 171 | void _incRefCount() |
172 | { | 172 | { |
173 | if( iRefCount && core ) | 173 | if( iRefCount && core ) |
174 | ++(*iRefCount); | 174 | ++(*iRefCount); |
175 | } | 175 | } |
176 | 176 | ||
177 | void _softCopy( const _SharedType &rSrc ) | 177 | void _softCopy( const _SharedType &rSrc ) |
178 | { | 178 | { |
179 | if( core ) | 179 | if( core ) |
180 | _deref(); | 180 | _deref(); |
181 | core = rSrc.core; | 181 | core = rSrc.core; |
182 | iRefCount = rSrc.iRefCount; | 182 | iRefCount = rSrc.iRefCount; |
183 | _incRefCount(); | 183 | _incRefCount(); |
184 | } | 184 | } |
185 | 185 | ||
186 | int *iRefCount; | 186 | int *iRefCount; |
187 | }; | 187 | }; |
188 | }; | 188 | }; |
189 | 189 | ||
190 | #undef fin | 190 | #undef fin |
diff --git a/src/stable/singleton.h b/src/stable/singleton.h index 6fe2777..27d907d 100644 --- a/src/stable/singleton.h +++ b/src/stable/singleton.h | |||
@@ -12,57 +12,57 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Provides singleton functionality in a modular sort of way. Make this the | 16 | * Provides singleton functionality in a modular sort of way. Make this the |
17 | * base class of any other class and you immediately gain singleton | 17 | * base class of any other class and you immediately gain singleton |
18 | * functionality. Be sure to make your constructor and various functions use | 18 | * functionality. Be sure to make your constructor and various functions use |
19 | * intellegent scoping. Cleanup and instantiation are performed automatically | 19 | * intellegent scoping. Cleanup and instantiation are performed automatically |
20 | * for you at first use and program exit. There are two things that you must | 20 | * for you at first use and program exit. There are two things that you must |
21 | * do when using this template, first is to inherit from it with the name of | 21 | * do when using this template, first is to inherit from it with the name of |
22 | * your class filling in for T and then make this class a friend of your class. | 22 | * your class filling in for T and then make this class a friend of your class. |
23 | *@code | 23 | *@code |
24 | * // Making the Single Singleton: | 24 | * // Making the Single Singleton: |
25 | * class Single : public Singleton<Single> | 25 | * class Single : public Singleton<Single> |
26 | * { | 26 | * { |
27 | * friend class Singleton<Single>; | 27 | * friend class Singleton<Single>; |
28 | * protected: | 28 | * protected: |
29 | * Single(); | 29 | * Single(); |
30 | * ... | 30 | * ... |
31 | * }; | 31 | * }; |
32 | @endcode | 32 | @endcode |
33 | * You can still add public functions and variables to your new Singleton child | 33 | * You can still add public functions and variables to your new Singleton child |
34 | * class, but your constructor should be protected (hence the need for the | 34 | * class, but your constructor should be protected (hence the need for the |
35 | * friend decleration). | 35 | * friend decleration). |
36 | */ | 36 | */ |
37 | template <class T> | 37 | template <class T> |
38 | class Singleton | 38 | class Singleton |
39 | { | 39 | { |
40 | protected: | 40 | protected: |
41 | /** | 41 | /** |
42 | * Private constructor. This constructor is empty but has a body so that | 42 | * Private constructor. This constructor is empty but has a body so that |
43 | * you can make your own override of it. Be sure that you're override is | 43 | * you can make your own override of it. Be sure that you're override is |
44 | * also protected. | 44 | * also protected. |
45 | */ | 45 | */ |
46 | Singleton() {}; | 46 | Singleton() {}; |
47 | 47 | ||
48 | private: | 48 | private: |
49 | /** | 49 | /** |
50 | * Copy constructor, defined so that you could write your own as well. | 50 | * Copy constructor, defined so that you could write your own as well. |
51 | */ | 51 | */ |
52 | Singleton( const Singleton& ); | 52 | Singleton( const Singleton& ); |
53 | 53 | ||
54 | public: | 54 | public: |
55 | /** | 55 | /** |
56 | * Get a handle to the contained instance of the contained class. It is | 56 | * Get a handle to the contained instance of the contained class. It is |
57 | * a reference. | 57 | * a reference. |
58 | *@returns A reference to the contained object. | 58 | *@returns A reference to the contained object. |
59 | */ | 59 | */ |
60 | static T &getInstance() | 60 | static T &getInstance() |
61 | { | 61 | { |
62 | static T i; | 62 | static T i; |
63 | return i; | 63 | return i; |
64 | } | 64 | } |
65 | }; | 65 | }; |
66 | } | 66 | } |
67 | 67 | ||
68 | #endif | 68 | #endif |
diff --git a/src/stable/sio.cpp b/src/stable/sio.cpp index 6a650ed..1ea30c2 100644 --- a/src/stable/sio.cpp +++ b/src/stable/sio.cpp | |||
@@ -16,51 +16,51 @@ Bu::Formatter Bu::serr( Bu::serrRaw ); | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | class PrintEndAction : public Bu::String::FormatProxyEndAction | 19 | class PrintEndAction : public Bu::String::FormatProxyEndAction |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | PrintEndAction( Bu::Stream &s, bool bEndLn ) : | 22 | PrintEndAction( Bu::Stream &s, bool bEndLn ) : |
23 | s( s ), | 23 | s( s ), |
24 | bEndLn( bEndLn ) | 24 | bEndLn( bEndLn ) |
25 | { | 25 | { |
26 | } | 26 | } |
27 | 27 | ||
28 | virtual ~PrintEndAction() | 28 | virtual ~PrintEndAction() |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | virtual void operator()( const Bu::String &sFinal ) | 32 | virtual void operator()( const Bu::String &sFinal ) |
33 | { | 33 | { |
34 | s.write( sFinal.getStr(), sFinal.getSize() ); | 34 | s.write( sFinal.getStr(), sFinal.getSize() ); |
35 | if( bEndLn ) | 35 | if( bEndLn ) |
36 | { | 36 | { |
37 | s.write("\n", 1); | 37 | s.write("\n", 1); |
38 | s.flush(); | 38 | s.flush(); |
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | Bu::Stream &s; | 42 | Bu::Stream &s; |
43 | bool bEndLn; | 43 | bool bEndLn; |
44 | }; | 44 | }; |
45 | } | 45 | } |
46 | 46 | ||
47 | Bu::String::FormatProxy Bu::print( Bu::Stream &s, const Bu::String &str ) | 47 | Bu::String::FormatProxy Bu::print( Bu::Stream &s, const Bu::String &str ) |
48 | { | 48 | { |
49 | return str.format( new Bu::PrintEndAction( s, false ) ); | 49 | return str.format( new Bu::PrintEndAction( s, false ) ); |
50 | } | 50 | } |
51 | 51 | ||
52 | Bu::String::FormatProxy Bu::print( const Bu::String &str ) | 52 | Bu::String::FormatProxy Bu::print( const Bu::String &str ) |
53 | { | 53 | { |
54 | return print( sioRaw, str ); | 54 | return print( sioRaw, str ); |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::String::FormatProxy Bu::println( Bu::Stream &s, const Bu::String &str ) | 57 | Bu::String::FormatProxy Bu::println( Bu::Stream &s, const Bu::String &str ) |
58 | { | 58 | { |
59 | return str.format( new Bu::PrintEndAction( s, true ) ); | 59 | return str.format( new Bu::PrintEndAction( s, true ) ); |
60 | } | 60 | } |
61 | 61 | ||
62 | Bu::String::FormatProxy Bu::println( const Bu::String &str ) | 62 | Bu::String::FormatProxy Bu::println( const Bu::String &str ) |
63 | { | 63 | { |
64 | return println( sioRaw, str ); | 64 | return println( sioRaw, str ); |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/src/stable/sio.h b/src/stable/sio.h index 2d4a104..ddaea1b 100644 --- a/src/stable/sio.h +++ b/src/stable/sio.h | |||
@@ -12,18 +12,18 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | class StreamStack; | 15 | class StreamStack; |
16 | 16 | ||
17 | extern Bu::StreamStack sioRaw; | 17 | extern Bu::StreamStack sioRaw; |
18 | extern Bu::Formatter sio; | 18 | extern Bu::Formatter sio; |
19 | extern Bu::StreamStack serrRaw; | 19 | extern Bu::StreamStack serrRaw; |
20 | extern Bu::Formatter serr; | 20 | extern Bu::Formatter serr; |
21 | 21 | ||
22 | Bu::String::FormatProxy print( Bu::Stream &s, const Bu::String &str ); | 22 | Bu::String::FormatProxy print( Bu::Stream &s, const Bu::String &str ); |
23 | Bu::String::FormatProxy print( const Bu::String &str ); | 23 | Bu::String::FormatProxy print( const Bu::String &str ); |
24 | 24 | ||
25 | Bu::String::FormatProxy println( Bu::Stream &s, const Bu::String &str ); | 25 | Bu::String::FormatProxy println( Bu::Stream &s, const Bu::String &str ); |
26 | Bu::String::FormatProxy println( const Bu::String &str ); | 26 | Bu::String::FormatProxy println( const Bu::String &str ); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/src/stable/sptr.h b/src/stable/sptr.h index 58ea223..6a9c340 100644 --- a/src/stable/sptr.h +++ b/src/stable/sptr.h | |||
@@ -13,217 +13,217 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | template<typename T> class SPtr; | 16 | template<typename T> class SPtr; |
17 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ); | 17 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ); |
18 | 18 | ||
19 | /** | 19 | /** |
20 | *@ingroup Containers | 20 | *@ingroup Containers |
21 | */ | 21 | */ |
22 | template<typename T> | 22 | template<typename T> |
23 | class SPtr | 23 | class SPtr |
24 | { | 24 | { |
25 | template<typename Tb, typename Ta> | 25 | template<typename Tb, typename Ta> |
26 | friend SPtr<Tb> SPtrCast( SPtr<Ta> pt ); | 26 | friend SPtr<Tb> SPtrCast( SPtr<Ta> pt ); |
27 | public: | 27 | public: |
28 | SPtr() : | 28 | SPtr() : |
29 | pRefCnt( NULL ), | 29 | pRefCnt( NULL ), |
30 | pData( NULL ) | 30 | pData( NULL ) |
31 | { | 31 | { |
32 | } | 32 | } |
33 | 33 | ||
34 | ~SPtr() | 34 | ~SPtr() |
35 | { | 35 | { |
36 | decCount(); | 36 | decCount(); |
37 | } | 37 | } |
38 | 38 | ||
39 | SPtr( const SPtr<T> &src ) : | 39 | SPtr( const SPtr<T> &src ) : |
40 | pRefCnt( src.pRefCnt ), | 40 | pRefCnt( src.pRefCnt ), |
41 | pData( src.pData ) | 41 | pData( src.pData ) |
42 | { | 42 | { |
43 | if( pRefCnt ) | 43 | if( pRefCnt ) |
44 | (*pRefCnt) += 1; | 44 | (*pRefCnt) += 1; |
45 | } | 45 | } |
46 | 46 | ||
47 | SPtr( T *pSrc ) : | 47 | SPtr( T *pSrc ) : |
48 | pRefCnt( NULL ), | 48 | pRefCnt( NULL ), |
49 | pData( pSrc ) | 49 | pData( pSrc ) |
50 | { | 50 | { |
51 | if( pData ) | 51 | if( pData ) |
52 | { | 52 | { |
53 | pRefCnt = new int32_t; | 53 | pRefCnt = new int32_t; |
54 | (*pRefCnt) = 1; | 54 | (*pRefCnt) = 1; |
55 | } | 55 | } |
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Get the number of references to this pointer. | 59 | * Get the number of references to this pointer. |
60 | *@returns (int32_t) The number of references to this pointer. | 60 | *@returns (int32_t) The number of references to this pointer. |
61 | */ | 61 | */ |
62 | int32_t getRefCount() const | 62 | int32_t getRefCount() const |
63 | { | 63 | { |
64 | return *pRefCnt; | 64 | return *pRefCnt; |
65 | } | 65 | } |
66 | 66 | ||
67 | void clear() | 67 | void clear() |
68 | { | 68 | { |
69 | decCount(); | 69 | decCount(); |
70 | pRefCnt = NULL; | 70 | pRefCnt = NULL; |
71 | pData = NULL; | 71 | pData = NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * Pointer access operator. | 75 | * Pointer access operator. |
76 | *@returns (const T *) | 76 | *@returns (const T *) |
77 | */ | 77 | */ |
78 | const T *operator->() const | 78 | const T *operator->() const |
79 | { | 79 | { |
80 | return pData; | 80 | return pData; |
81 | } | 81 | } |
82 | 82 | ||
83 | /** | 83 | /** |
84 | * Dereference operator. | 84 | * Dereference operator. |
85 | *@returns (const T &) The value at the end of the pointer. | 85 | *@returns (const T &) The value at the end of the pointer. |
86 | */ | 86 | */ |
87 | const T &operator*() const | 87 | const T &operator*() const |
88 | { | 88 | { |
89 | return *pData; | 89 | return *pData; |
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * Pointer access operator. | 93 | * Pointer access operator. |
94 | *@returns (T *) | 94 | *@returns (T *) |
95 | */ | 95 | */ |
96 | T *operator->() | 96 | T *operator->() |
97 | { | 97 | { |
98 | return pData; | 98 | return pData; |
99 | } | 99 | } |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * Dereference operator. | 102 | * Dereference operator. |
103 | *@returns (T &) The value at the end of the pointer. | 103 | *@returns (T &) The value at the end of the pointer. |
104 | */ | 104 | */ |
105 | T &operator*() | 105 | T &operator*() |
106 | { | 106 | { |
107 | return *pData; | 107 | return *pData; |
108 | } | 108 | } |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * Assignment operator. | 111 | * Assignment operator. |
112 | *@param src (const SPtr<T> &) | 112 | *@param src (const SPtr<T> &) |
113 | */ | 113 | */ |
114 | SPtr<T> operator=( const SPtr<T> &src ) | 114 | SPtr<T> operator=( const SPtr<T> &src ) |
115 | { | 115 | { |
116 | decCount(); | 116 | decCount(); |
117 | pRefCnt = src.pRefCnt; | 117 | pRefCnt = src.pRefCnt; |
118 | pData = src.pData; | 118 | pData = src.pData; |
119 | if( pRefCnt ) | 119 | if( pRefCnt ) |
120 | (*pRefCnt) += 1; | 120 | (*pRefCnt) += 1; |
121 | 121 | ||
122 | return *this; | 122 | return *this; |
123 | } | 123 | } |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * Assignment operator. | 126 | * Assignment operator. |
127 | *@param src (const SPtr<T> &) | 127 | *@param src (const SPtr<T> &) |
128 | */ | 128 | */ |
129 | const SPtr<T> operator=( const SPtr<T> &src ) const | 129 | const SPtr<T> operator=( const SPtr<T> &src ) const |
130 | { | 130 | { |
131 | decCount(); | 131 | decCount(); |
132 | pRefCnt = src.pRefCnt; | 132 | pRefCnt = src.pRefCnt; |
133 | pData = src.pData; | 133 | pData = src.pData; |
134 | if( pRefCnt ) | 134 | if( pRefCnt ) |
135 | (*pRefCnt) += 1; | 135 | (*pRefCnt) += 1; |
136 | 136 | ||
137 | return *this; | 137 | return *this; |
138 | } | 138 | } |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * Equals comparison operator. | 141 | * Equals comparison operator. |
142 | *@param src (const SPtr<T> &) The SPtr to compare to. | 142 | *@param src (const SPtr<T> &) The SPtr to compare to. |
143 | *@returns (bool) Are the equal? | 143 | *@returns (bool) Are the equal? |
144 | */ | 144 | */ |
145 | bool operator==( const SPtr<T> &src ) const | 145 | bool operator==( const SPtr<T> &src ) const |
146 | { | 146 | { |
147 | return pData == src.pData; | 147 | return pData == src.pData; |
148 | } | 148 | } |
149 | 149 | ||
150 | /** | 150 | /** |
151 | * Equals comparison operator. | 151 | * Equals comparison operator. |
152 | *@param src (const T *) The pointer to compare to. | 152 | *@param src (const T *) The pointer to compare to. |
153 | *@returns (bool) Are the equal? | 153 | *@returns (bool) Are the equal? |
154 | */ | 154 | */ |
155 | bool operator==( const T *src ) const | 155 | bool operator==( const T *src ) const |
156 | { | 156 | { |
157 | return pData == src; | 157 | return pData == src; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Not equals comparison operator. | 161 | * Not equals comparison operator. |
162 | *@param src (const SPtr<T> &) The SPtr to compare to. | 162 | *@param src (const SPtr<T> &) The SPtr to compare to. |
163 | *@returns (bool) Are the equal? | 163 | *@returns (bool) Are the equal? |
164 | */ | 164 | */ |
165 | bool operator!=( const SPtr<T> &src ) const | 165 | bool operator!=( const SPtr<T> &src ) const |
166 | { | 166 | { |
167 | return !(pData == src.pData); | 167 | return !(pData == src.pData); |
168 | } | 168 | } |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * Not equals comparison operator. | 171 | * Not equals comparison operator. |
172 | *@param src (const T *) The pointer to compare to. | 172 | *@param src (const T *) The pointer to compare to. |
173 | *@returns (bool) Are the equal? | 173 | *@returns (bool) Are the equal? |
174 | */ | 174 | */ |
175 | bool operator!=( const T *src ) const | 175 | bool operator!=( const T *src ) const |
176 | { | 176 | { |
177 | return !(pData == src); | 177 | return !(pData == src); |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * Boolean cast operator. Do we have a pointer? | 181 | * Boolean cast operator. Do we have a pointer? |
182 | */ | 182 | */ |
183 | operator bool() const | 183 | operator bool() const |
184 | { | 184 | { |
185 | return pRefCnt != NULL; | 185 | return pRefCnt != NULL; |
186 | } | 186 | } |
187 | 187 | ||
188 | /** | 188 | /** |
189 | * Do we have a pointer? | 189 | * Do we have a pointer? |
190 | *@returns (bool) Do we have a pointer? | 190 | *@returns (bool) Do we have a pointer? |
191 | */ | 191 | */ |
192 | bool isSet() const | 192 | bool isSet() const |
193 | { | 193 | { |
194 | return pRefCnt != NULL; | 194 | return pRefCnt != NULL; |
195 | } | 195 | } |
196 | 196 | ||
197 | private: | 197 | private: |
198 | void decCount() const | 198 | void decCount() const |
199 | { | 199 | { |
200 | if( pRefCnt ) | 200 | if( pRefCnt ) |
201 | { | 201 | { |
202 | (*pRefCnt) -= 1; | 202 | (*pRefCnt) -= 1; |
203 | //printf("Decrementing ref-count to %d\n", *pRefCnt ); | 203 | //printf("Decrementing ref-count to %d\n", *pRefCnt ); |
204 | if( (*pRefCnt) == 0 ) | 204 | if( (*pRefCnt) == 0 ) |
205 | { | 205 | { |
206 | delete pRefCnt; | 206 | delete pRefCnt; |
207 | delete pData; | 207 | delete pData; |
208 | pRefCnt = NULL; | 208 | pRefCnt = NULL; |
209 | pData = NULL; | 209 | pData = NULL; |
210 | } | 210 | } |
211 | } | 211 | } |
212 | } | 212 | } |
213 | 213 | ||
214 | mutable int32_t *pRefCnt; | 214 | mutable int32_t *pRefCnt; |
215 | mutable T *pData; | 215 | mutable T *pData; |
216 | }; | 216 | }; |
217 | 217 | ||
218 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ) | 218 | template< typename Tb, typename Ta > SPtr<Tb> SPtrCast( SPtr<Ta> src ) |
219 | { | 219 | { |
220 | SPtr<Tb> ret; | 220 | SPtr<Tb> ret; |
221 | ret.pRefCnt = src.pRefCnt; | 221 | ret.pRefCnt = src.pRefCnt; |
222 | ret.pData = dynamic_cast<Tb *>(src.pData); | 222 | ret.pData = dynamic_cast<Tb *>(src.pData); |
223 | if( ret.pRefCnt ) | 223 | if( ret.pRefCnt ) |
224 | (*(ret.pRefCnt)) += 1; | 224 | (*(ret.pRefCnt)) += 1; |
225 | return ret; | 225 | return ret; |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | #endif | 229 | #endif |
diff --git a/src/stable/stack.h b/src/stable/stack.h index f60907d..6b5f65a 100644 --- a/src/stable/stack.h +++ b/src/stable/stack.h | |||
@@ -13,73 +13,73 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | template<typename value, typename valuealloc=std::allocator<value> > | 16 | template<typename value, typename valuealloc=std::allocator<value> > |
17 | class Stack | 17 | class Stack |
18 | { | 18 | { |
19 | private: | 19 | private: |
20 | typedef struct Chunk | 20 | typedef struct Chunk |
21 | { | 21 | { |
22 | value *pValue; | 22 | value *pValue; |
23 | Chunk *pPrev; | 23 | Chunk *pPrev; |
24 | } Chunk; | 24 | } Chunk; |
25 | public: | 25 | public: |
26 | Stack() : | 26 | Stack() : |
27 | pTop( NULL ) | 27 | pTop( NULL ) |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
31 | virtual ~Stack() | 31 | virtual ~Stack() |
32 | { | 32 | { |
33 | } | 33 | } |
34 | 34 | ||
35 | void push( const value &v ) | 35 | void push( const value &v ) |
36 | { | 36 | { |
37 | Chunk *pChnk = new Chunk; | 37 | Chunk *pChnk = new Chunk; |
38 | pChnk->pValue = va.allocate( 1 ); | 38 | pChnk->pValue = va.allocate( 1 ); |
39 | va.construct( pChnk->pValue, v ); | 39 | va.construct( pChnk->pValue, v ); |
40 | pChnk->pPrev = pTop; | 40 | pChnk->pPrev = pTop; |
41 | pTop = pChnk; | 41 | pTop = pChnk; |
42 | } | 42 | } |
43 | 43 | ||
44 | value &peek() | 44 | value &peek() |
45 | { | 45 | { |
46 | return *pTop->pValue; | 46 | return *pTop->pValue; |
47 | } | 47 | } |
48 | 48 | ||
49 | value &top() | 49 | value &top() |
50 | { | 50 | { |
51 | return *pTop->pValue; | 51 | return *pTop->pValue; |
52 | } | 52 | } |
53 | 53 | ||
54 | value pop() | 54 | value pop() |
55 | { | 55 | { |
56 | value ret( *pTop->pValue ); | 56 | value ret( *pTop->pValue ); |
57 | 57 | ||
58 | Chunk *pChnk = pTop; | 58 | Chunk *pChnk = pTop; |
59 | pTop = pTop->pPrev; | 59 | pTop = pTop->pPrev; |
60 | 60 | ||
61 | va.destroy( pChnk->pValue ); | 61 | va.destroy( pChnk->pValue ); |
62 | va.deallocate( pChnk->pValue, 1 ); | 62 | va.deallocate( pChnk->pValue, 1 ); |
63 | delete pChnk; | 63 | delete pChnk; |
64 | 64 | ||
65 | return ret; | 65 | return ret; |
66 | } | 66 | } |
67 | 67 | ||
68 | void clear() | 68 | void clear() |
69 | { | 69 | { |
70 | while( !isEmpty() ) | 70 | while( !isEmpty() ) |
71 | pop(); | 71 | pop(); |
72 | } | 72 | } |
73 | 73 | ||
74 | bool isEmpty() | 74 | bool isEmpty() |
75 | { | 75 | { |
76 | return pTop == NULL; | 76 | return pTop == NULL; |
77 | } | 77 | } |
78 | 78 | ||
79 | private: | 79 | private: |
80 | Chunk *pTop; | 80 | Chunk *pTop; |
81 | valuealloc va; | 81 | valuealloc va; |
82 | }; | 82 | }; |
83 | } | 83 | } |
84 | 84 | ||
85 | #endif | 85 | #endif |
diff --git a/src/stable/staticmembuf.cpp b/src/stable/staticmembuf.cpp index d470916..43f098b 100644 --- a/src/stable/staticmembuf.cpp +++ b/src/stable/staticmembuf.cpp | |||
@@ -10,9 +10,9 @@ | |||
10 | using namespace Bu; | 10 | using namespace Bu; |
11 | 11 | ||
12 | Bu::StaticMemBuf::StaticMemBuf( const void *pData, size iSize ) : | 12 | Bu::StaticMemBuf::StaticMemBuf( const void *pData, size iSize ) : |
13 | pData( pData ), | 13 | pData( pData ), |
14 | iSize( iSize ), | 14 | iSize( iSize ), |
15 | nPos( 0 ) | 15 | nPos( 0 ) |
16 | { | 16 | { |
17 | } | 17 | } |
18 | 18 | ||
@@ -26,54 +26,54 @@ void Bu::StaticMemBuf::close() | |||
26 | 26 | ||
27 | size Bu::StaticMemBuf::read( void *pBuf, size nBytes ) | 27 | size Bu::StaticMemBuf::read( void *pBuf, size nBytes ) |
28 | { | 28 | { |
29 | if( iSize-nPos < nBytes ) | 29 | if( iSize-nPos < nBytes ) |
30 | nBytes = iSize-nPos; | 30 | nBytes = iSize-nPos; |
31 | 31 | ||
32 | memcpy( pBuf, ((char *)pData)+nPos, nBytes ); | 32 | memcpy( pBuf, ((char *)pData)+nPos, nBytes ); |
33 | nPos += nBytes; | 33 | nPos += nBytes; |
34 | 34 | ||
35 | return nBytes; | 35 | return nBytes; |
36 | } | 36 | } |
37 | 37 | ||
38 | size Bu::StaticMemBuf::write( const void *, size ) | 38 | size Bu::StaticMemBuf::write( const void *, size ) |
39 | { | 39 | { |
40 | return -1; | 40 | return -1; |
41 | } | 41 | } |
42 | 42 | ||
43 | size Bu::StaticMemBuf::tell() | 43 | size Bu::StaticMemBuf::tell() |
44 | { | 44 | { |
45 | return nPos; | 45 | return nPos; |
46 | } | 46 | } |
47 | 47 | ||
48 | void Bu::StaticMemBuf::seek( size offset ) | 48 | void Bu::StaticMemBuf::seek( size offset ) |
49 | { | 49 | { |
50 | nPos += offset; | 50 | nPos += offset; |
51 | if( nPos < 0 ) nPos = 0; | 51 | if( nPos < 0 ) nPos = 0; |
52 | else if( nPos > iSize ) nPos = iSize; | 52 | else if( nPos > iSize ) nPos = iSize; |
53 | } | 53 | } |
54 | 54 | ||
55 | void Bu::StaticMemBuf::setPos( size pos ) | 55 | void Bu::StaticMemBuf::setPos( size pos ) |
56 | { | 56 | { |
57 | nPos = pos; | 57 | nPos = pos; |
58 | if( nPos < 0 ) nPos = 0; | 58 | if( nPos < 0 ) nPos = 0; |
59 | else if( nPos > iSize ) nPos = iSize; | 59 | else if( nPos > iSize ) nPos = iSize; |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::StaticMemBuf::setPosEnd( size pos ) | 62 | void Bu::StaticMemBuf::setPosEnd( size pos ) |
63 | { | 63 | { |
64 | nPos = iSize-pos; | 64 | nPos = iSize-pos; |
65 | if( nPos < 0 ) nPos = 0; | 65 | if( nPos < 0 ) nPos = 0; |
66 | else if( nPos > iSize ) nPos = iSize; | 66 | else if( nPos > iSize ) nPos = iSize; |
67 | } | 67 | } |
68 | 68 | ||
69 | bool Bu::StaticMemBuf::isEos() | 69 | bool Bu::StaticMemBuf::isEos() |
70 | { | 70 | { |
71 | return (nPos == iSize); | 71 | return (nPos == iSize); |
72 | } | 72 | } |
73 | 73 | ||
74 | bool Bu::StaticMemBuf::isOpen() | 74 | bool Bu::StaticMemBuf::isOpen() |
75 | { | 75 | { |
76 | return true; | 76 | return true; |
77 | } | 77 | } |
78 | 78 | ||
79 | void Bu::StaticMemBuf::flush() | 79 | void Bu::StaticMemBuf::flush() |
@@ -82,32 +82,32 @@ void Bu::StaticMemBuf::flush() | |||
82 | 82 | ||
83 | bool Bu::StaticMemBuf::canRead() | 83 | bool Bu::StaticMemBuf::canRead() |
84 | { | 84 | { |
85 | return !isEos(); | 85 | return !isEos(); |
86 | } | 86 | } |
87 | 87 | ||
88 | bool Bu::StaticMemBuf::canWrite() | 88 | bool Bu::StaticMemBuf::canWrite() |
89 | { | 89 | { |
90 | return false; | 90 | return false; |
91 | } | 91 | } |
92 | 92 | ||
93 | bool Bu::StaticMemBuf::isReadable() | 93 | bool Bu::StaticMemBuf::isReadable() |
94 | { | 94 | { |
95 | return true; | 95 | return true; |
96 | } | 96 | } |
97 | 97 | ||
98 | bool Bu::StaticMemBuf::isWritable() | 98 | bool Bu::StaticMemBuf::isWritable() |
99 | { | 99 | { |
100 | return false; | 100 | return false; |
101 | } | 101 | } |
102 | 102 | ||
103 | bool Bu::StaticMemBuf::isSeekable() | 103 | bool Bu::StaticMemBuf::isSeekable() |
104 | { | 104 | { |
105 | return true; | 105 | return true; |
106 | } | 106 | } |
107 | 107 | ||
108 | bool Bu::StaticMemBuf::isBlocking() | 108 | bool Bu::StaticMemBuf::isBlocking() |
109 | { | 109 | { |
110 | return true; | 110 | return true; |
111 | } | 111 | } |
112 | 112 | ||
113 | void Bu::StaticMemBuf::setBlocking( bool ) | 113 | void Bu::StaticMemBuf::setBlocking( bool ) |
@@ -120,16 +120,16 @@ void Bu::StaticMemBuf::setSize( size ) | |||
120 | 120 | ||
121 | Bu::size Bu::StaticMemBuf::getSize() const | 121 | Bu::size Bu::StaticMemBuf::getSize() const |
122 | { | 122 | { |
123 | return iSize; | 123 | return iSize; |
124 | } | 124 | } |
125 | 125 | ||
126 | Bu::size Bu::StaticMemBuf::getBlockSize() const | 126 | Bu::size Bu::StaticMemBuf::getBlockSize() const |
127 | { | 127 | { |
128 | return iSize; | 128 | return iSize; |
129 | } | 129 | } |
130 | 130 | ||
131 | Bu::String Bu::StaticMemBuf::getLocation() const | 131 | Bu::String Bu::StaticMemBuf::getLocation() const |
132 | { | 132 | { |
133 | return ""; | 133 | return ""; |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/src/stable/staticmembuf.h b/src/stable/staticmembuf.h index 332e27d..2be05a0 100644 --- a/src/stable/staticmembuf.h +++ b/src/stable/staticmembuf.h | |||
@@ -15,51 +15,51 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * An immutable, read-only memory buffer. Construct this buffer around a | 19 | * An immutable, read-only memory buffer. Construct this buffer around a |
20 | * block of raw memory, provide the length of the block, and you can read | 20 | * block of raw memory, provide the length of the block, and you can read |
21 | * from that block via this class as though it were a normal stream. | 21 | * from that block via this class as though it were a normal stream. |
22 | * | 22 | * |
23 | * Use this class instead of MemBuf when you have a string already, and | 23 | * Use this class instead of MemBuf when you have a string already, and |
24 | * don't need to change it. MemBuf will make a copy of your string for | 24 | * don't need to change it. MemBuf will make a copy of your string for |
25 | * it's own use (often) and this will not (ever). | 25 | * it's own use (often) and this will not (ever). |
26 | *@ingroup Streams | 26 | *@ingroup Streams |
27 | */ | 27 | */ |
28 | class StaticMemBuf : public Stream | 28 | class StaticMemBuf : public Stream |
29 | { | 29 | { |
30 | public: | 30 | public: |
31 | StaticMemBuf( const void *pData, size iSize ); | 31 | StaticMemBuf( const void *pData, size iSize ); |
32 | virtual ~StaticMemBuf(); | 32 | virtual ~StaticMemBuf(); |
33 | 33 | ||
34 | virtual void close(); | 34 | virtual void close(); |
35 | virtual size read( void *pBuf, size iBytes ); | 35 | virtual size read( void *pBuf, size iBytes ); |
36 | 36 | ||
37 | virtual size write( const void *pBuf, size iBytes ); | 37 | virtual size write( const void *pBuf, size iBytes ); |
38 | using Stream::write; | 38 | using Stream::write; |
39 | virtual size tell(); | 39 | virtual size tell(); |
40 | virtual void seek( size offset ); | 40 | virtual void seek( size offset ); |
41 | virtual void setPos( size pos ); | 41 | virtual void setPos( size pos ); |
42 | virtual void setPosEnd( size pos ); | 42 | virtual void setPosEnd( size pos ); |
43 | virtual bool isEos(); | 43 | virtual bool isEos(); |
44 | virtual bool isOpen(); | 44 | virtual bool isOpen(); |
45 | virtual void flush(); | 45 | virtual void flush(); |
46 | virtual bool canRead(); | 46 | virtual bool canRead(); |
47 | virtual bool canWrite(); | 47 | virtual bool canWrite(); |
48 | virtual bool isReadable(); | 48 | virtual bool isReadable(); |
49 | virtual bool isWritable(); | 49 | virtual bool isWritable(); |
50 | virtual bool isSeekable(); | 50 | virtual bool isSeekable(); |
51 | virtual bool isBlocking(); | 51 | virtual bool isBlocking(); |
52 | virtual void setBlocking( bool bBlocking=true ); | 52 | virtual void setBlocking( bool bBlocking=true ); |
53 | virtual void setSize( size iSize ); | 53 | virtual void setSize( size iSize ); |
54 | virtual size getSize() const; | 54 | virtual size getSize() const; |
55 | virtual size getBlockSize() const; | 55 | virtual size getBlockSize() const; |
56 | virtual Bu::String getLocation() const; | 56 | virtual Bu::String getLocation() const; |
57 | 57 | ||
58 | private: | 58 | private: |
59 | const void *pData; | 59 | const void *pData; |
60 | size iSize; | 60 | size iSize; |
61 | size nPos; | 61 | size nPos; |
62 | }; | 62 | }; |
63 | } | 63 | } |
64 | 64 | ||
65 | #endif | 65 | #endif |
diff --git a/src/stable/stdstream.cpp b/src/stable/stdstream.cpp index 25ad8d4..9cd216d 100644 --- a/src/stable/stdstream.cpp +++ b/src/stable/stdstream.cpp | |||
@@ -9,7 +9,7 @@ | |||
9 | #include "bu/stdstream.h" | 9 | #include "bu/stdstream.h" |
10 | 10 | ||
11 | Bu::StdStream::StdStream( OutMode eOut ) : | 11 | Bu::StdStream::StdStream( OutMode eOut ) : |
12 | eOut( eOut ) | 12 | eOut( eOut ) |
13 | { | 13 | { |
14 | } | 14 | } |
15 | 15 | ||
@@ -23,17 +23,17 @@ void Bu::StdStream::close() | |||
23 | 23 | ||
24 | Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes ) | 24 | Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes ) |
25 | { | 25 | { |
26 | return fread( pBuf, 1, nBytes, stdin ); | 26 | return fread( pBuf, 1, nBytes, stdin ); |
27 | } | 27 | } |
28 | 28 | ||
29 | Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes ) | 29 | Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes ) |
30 | { | 30 | { |
31 | return fwrite( pBuf, 1, nBytes, eOut==StdOut?stdout:stderr ); | 31 | return fwrite( pBuf, 1, nBytes, eOut==StdOut?stdout:stderr ); |
32 | } | 32 | } |
33 | 33 | ||
34 | Bu::size Bu::StdStream::tell() | 34 | Bu::size Bu::StdStream::tell() |
35 | { | 35 | { |
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | void Bu::StdStream::seek( Bu::size ) | 39 | void Bu::StdStream::seek( Bu::size ) |
@@ -50,47 +50,47 @@ void Bu::StdStream::setPosEnd( Bu::size ) | |||
50 | 50 | ||
51 | bool Bu::StdStream::isEos() | 51 | bool Bu::StdStream::isEos() |
52 | { | 52 | { |
53 | return false; | 53 | return false; |
54 | } | 54 | } |
55 | 55 | ||
56 | bool Bu::StdStream::isOpen() | 56 | bool Bu::StdStream::isOpen() |
57 | { | 57 | { |
58 | return true; | 58 | return true; |
59 | } | 59 | } |
60 | 60 | ||
61 | void Bu::StdStream::flush() | 61 | void Bu::StdStream::flush() |
62 | { | 62 | { |
63 | fflush( eOut==StdOut?stdout:stderr ); | 63 | fflush( eOut==StdOut?stdout:stderr ); |
64 | } | 64 | } |
65 | 65 | ||
66 | bool Bu::StdStream::canRead() | 66 | bool Bu::StdStream::canRead() |
67 | { | 67 | { |
68 | return true; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | bool Bu::StdStream::canWrite() | 71 | bool Bu::StdStream::canWrite() |
72 | { | 72 | { |
73 | return true; | 73 | return true; |
74 | } | 74 | } |
75 | 75 | ||
76 | bool Bu::StdStream::isReadable() | 76 | bool Bu::StdStream::isReadable() |
77 | { | 77 | { |
78 | return true; | 78 | return true; |
79 | } | 79 | } |
80 | 80 | ||
81 | bool Bu::StdStream::isWritable() | 81 | bool Bu::StdStream::isWritable() |
82 | { | 82 | { |
83 | return true; | 83 | return true; |
84 | } | 84 | } |
85 | 85 | ||
86 | bool Bu::StdStream::isSeekable() | 86 | bool Bu::StdStream::isSeekable() |
87 | { | 87 | { |
88 | return false; | 88 | return false; |
89 | } | 89 | } |
90 | 90 | ||
91 | bool Bu::StdStream::isBlocking() | 91 | bool Bu::StdStream::isBlocking() |
92 | { | 92 | { |
93 | return true; | 93 | return true; |
94 | } | 94 | } |
95 | 95 | ||
96 | void Bu::StdStream::setBlocking( bool ) | 96 | void Bu::StdStream::setBlocking( bool ) |
@@ -103,16 +103,16 @@ void Bu::StdStream::setSize( Bu::size ) | |||
103 | 103 | ||
104 | Bu::size Bu::StdStream::getSize() const | 104 | Bu::size Bu::StdStream::getSize() const |
105 | { | 105 | { |
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | Bu::size Bu::StdStream::getBlockSize() const | 109 | Bu::size Bu::StdStream::getBlockSize() const |
110 | { | 110 | { |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | Bu::String Bu::StdStream::getLocation() const | 114 | Bu::String Bu::StdStream::getLocation() const |
115 | { | 115 | { |
116 | return ""; | 116 | return ""; |
117 | } | 117 | } |
118 | 118 | ||
diff --git a/src/stable/stdstream.h b/src/stable/stdstream.h index d71d95d..80c0fab 100644 --- a/src/stable/stdstream.h +++ b/src/stable/stdstream.h | |||
@@ -13,46 +13,46 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | *@ingroup Streams | 17 | *@ingroup Streams |
18 | */ | 18 | */ |
19 | class StdStream : public Stream | 19 | class StdStream : public Stream |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | enum OutMode | 22 | enum OutMode |
23 | { | 23 | { |
24 | StdOut, | 24 | StdOut, |
25 | StdError | 25 | StdError |
26 | }; | 26 | }; |
27 | StdStream( OutMode eOut=StdOut ); | 27 | StdStream( OutMode eOut=StdOut ); |
28 | virtual ~StdStream(); | 28 | virtual ~StdStream(); |
29 | 29 | ||
30 | virtual void close(); | 30 | virtual void close(); |
31 | virtual size read( void *pBuf, size nBytes ); | 31 | virtual size read( void *pBuf, size nBytes ); |
32 | virtual size write( const void *pBuf, size nBytes ); | 32 | virtual size write( const void *pBuf, size nBytes ); |
33 | using Stream::write; | 33 | using Stream::write; |
34 | virtual size tell(); | 34 | virtual size tell(); |
35 | virtual void seek( size offset ); | 35 | virtual void seek( size offset ); |
36 | virtual void setPos( size pos ); | 36 | virtual void setPos( size pos ); |
37 | virtual void setPosEnd( size pos ); | 37 | virtual void setPosEnd( size pos ); |
38 | virtual bool isEos(); | 38 | virtual bool isEos(); |
39 | virtual bool isOpen(); | 39 | virtual bool isOpen(); |
40 | virtual void flush(); | 40 | virtual void flush(); |
41 | virtual bool canRead(); | 41 | virtual bool canRead(); |
42 | virtual bool canWrite(); | 42 | virtual bool canWrite(); |
43 | virtual bool isReadable(); | 43 | virtual bool isReadable(); |
44 | virtual bool isWritable(); | 44 | virtual bool isWritable(); |
45 | virtual bool isSeekable(); | 45 | virtual bool isSeekable(); |
46 | virtual bool isBlocking(); | 46 | virtual bool isBlocking(); |
47 | virtual void setBlocking( bool bBlocking=true ); | 47 | virtual void setBlocking( bool bBlocking=true ); |
48 | virtual void setSize( size iSize ); | 48 | virtual void setSize( size iSize ); |
49 | virtual size getSize() const; | 49 | virtual size getSize() const; |
50 | virtual size getBlockSize() const; | 50 | virtual size getBlockSize() const; |
51 | virtual Bu::String getLocation() const; | 51 | virtual Bu::String getLocation() const; |
52 | 52 | ||
53 | private: | 53 | private: |
54 | OutMode eOut; | 54 | OutMode eOut; |
55 | }; | 55 | }; |
56 | } | 56 | } |
57 | 57 | ||
58 | #endif | 58 | #endif |
diff --git a/src/stable/stream.cpp b/src/stable/stream.cpp index 23a7f0f..551d657 100644 --- a/src/stable/stream.cpp +++ b/src/stable/stream.cpp | |||
@@ -17,37 +17,37 @@ Bu::Stream::~Stream() | |||
17 | 17 | ||
18 | Bu::String Bu::Stream::readLine() | 18 | Bu::String Bu::Stream::readLine() |
19 | { | 19 | { |
20 | Bu::String sRet; | 20 | Bu::String sRet; |
21 | 21 | ||
22 | for(;;) | 22 | for(;;) |
23 | { | 23 | { |
24 | char s; | 24 | char s; |
25 | if( read( &s, 1 ) == 0 ) | 25 | if( read( &s, 1 ) == 0 ) |
26 | return sRet; | 26 | return sRet; |
27 | if( s == '\n' || s == '\r' ) | 27 | if( s == '\n' || s == '\r' ) |
28 | return sRet; | 28 | return sRet; |
29 | sRet.append( s ); | 29 | sRet.append( s ); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | Bu::String Bu::Stream::readAll() | 33 | Bu::String Bu::Stream::readAll() |
34 | { | 34 | { |
35 | Bu::String sRet; | 35 | Bu::String sRet; |
36 | char buf[4096]; | 36 | char buf[4096]; |
37 | 37 | ||
38 | while( !isEos() ) | 38 | while( !isEos() ) |
39 | { | 39 | { |
40 | int iRead = read( buf, 4096 ); | 40 | int iRead = read( buf, 4096 ); |
41 | if( iRead == 0 ) | 41 | if( iRead == 0 ) |
42 | return sRet; | 42 | return sRet; |
43 | sRet.append( buf, iRead ); | 43 | sRet.append( buf, iRead ); |
44 | } | 44 | } |
45 | 45 | ||
46 | return sRet; | 46 | return sRet; |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::size Bu::Stream::write( const Bu::String &sBuf ) | 49 | Bu::size Bu::Stream::write( const Bu::String &sBuf ) |
50 | { | 50 | { |
51 | return write( sBuf.getStr(), sBuf.getSize() ); | 51 | return write( sBuf.getStr(), sBuf.getSize() ); |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/src/stable/stream.h b/src/stable/stream.h index 21e090e..a76e5fd 100644 --- a/src/stable/stream.h +++ b/src/stable/stream.h | |||
@@ -17,189 +17,189 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /** | 20 | /** |
21 | * The basis for a completely general data transport mechanism. Anything | 21 | * The basis for a completely general data transport mechanism. Anything |
22 | * that inherits from this should provide at least the basic read and/or | 22 | * that inherits from this should provide at least the basic read and/or |
23 | * write functions, and very probably the close function. Any functions | 23 | * write functions, and very probably the close function. Any functions |
24 | * that aren't supported should throw an exception if called. | 24 | * that aren't supported should throw an exception if called. |
25 | * | 25 | * |
26 | * The constructor of a child class should pretty much universally be used | 26 | * The constructor of a child class should pretty much universally be used |
27 | * to open the stream. I can't think of anything that should require an | 27 | * to open the stream. I can't think of anything that should require an |
28 | * exception. | 28 | * exception. |
29 | *@ingroup Streams | 29 | *@ingroup Streams |
30 | */ | 30 | */ |
31 | class Stream | 31 | class Stream |
32 | { | 32 | { |
33 | public: | 33 | public: |
34 | Stream(); | 34 | Stream(); |
35 | virtual ~Stream(); | 35 | virtual ~Stream(); |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * Close the stream. | 38 | * Close the stream. |
39 | */ | 39 | */ |
40 | virtual void close() = 0; | 40 | virtual void close() = 0; |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * Read data from the stream into a buffer. | 43 | * Read data from the stream into a buffer. |
44 | *@param pBuf (void *) Buffer which will be filled. | 44 | *@param pBuf (void *) Buffer which will be filled. |
45 | *@param nBytes (size_t) Max data to read. | 45 | *@param nBytes (size_t) Max data to read. |
46 | *@returns (size_t) Amount of data read. | 46 | *@returns (size_t) Amount of data read. |
47 | */ | 47 | */ |
48 | virtual size read( void *pBuf, size iBytes ) = 0; | 48 | virtual size read( void *pBuf, size iBytes ) = 0; |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Attempts to read a complete line from the stream. This will stop | 51 | * Attempts to read a complete line from the stream. This will stop |
52 | * reading when it has reached the end of the stream, or runs out of | 52 | * reading when it has reached the end of the stream, or runs out of |
53 | * data in a non-blocking stream. | 53 | * data in a non-blocking stream. |
54 | *@returns The line read, not including newline character. | 54 | *@returns The line read, not including newline character. |
55 | */ | 55 | */ |
56 | virtual Bu::String readLine(); | 56 | virtual Bu::String readLine(); |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Reads all data from the current position onward until isEos returns | 59 | * Reads all data from the current position onward until isEos returns |
60 | * true and returns it as a Bu::String. This will also return if no | 60 | * true and returns it as a Bu::String. This will also return if no |
61 | * data is available and the stream is in non-blocking mode. This | 61 | * data is available and the stream is in non-blocking mode. This |
62 | * function is intended for very particular circumstances and is often | 62 | * function is intended for very particular circumstances and is often |
63 | * not the most efficient way to access the data that you would like. | 63 | * not the most efficient way to access the data that you would like. |
64 | *@returns The entire stream contents. | 64 | *@returns The entire stream contents. |
65 | */ | 65 | */ |
66 | virtual Bu::String readAll(); | 66 | virtual Bu::String readAll(); |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * Write data to the stream. | 69 | * Write data to the stream. |
70 | *@param pBuf (const void *) The data to be written. | 70 | *@param pBuf (const void *) The data to be written. |
71 | *@param nBytes (size_t) Amount of data to write from pBuf. | 71 | *@param nBytes (size_t) Amount of data to write from pBuf. |
72 | *@returns (size_t) Amount of data actually written. | 72 | *@returns (size_t) Amount of data actually written. |
73 | */ | 73 | */ |
74 | virtual size write( const void *pBuf, size iBytes ) = 0; | 74 | virtual size write( const void *pBuf, size iBytes ) = 0; |
75 | 75 | ||
76 | virtual size write( const Bu::String &sBuf ); | 76 | virtual size write( const Bu::String &sBuf ); |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * Get the current position in the stream. | 79 | * Get the current position in the stream. |
80 | *@returns (long) The current position in the stream. | 80 | *@returns (long) The current position in the stream. |
81 | */ | 81 | */ |
82 | virtual size tell() = 0; | 82 | virtual size tell() = 0; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * Seek to a position in the stream relative to the current position. | 85 | * Seek to a position in the stream relative to the current position. |
86 | *@param offset (long) Offset from current position to seek to. | 86 | *@param offset (long) Offset from current position to seek to. |
87 | */ | 87 | */ |
88 | virtual void seek( size offset ) = 0; | 88 | virtual void seek( size offset ) = 0; |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * Set position in the stream relative to the start of the stream. | 91 | * Set position in the stream relative to the start of the stream. |
92 | *@param pos (long) The position. | 92 | *@param pos (long) The position. |
93 | */ | 93 | */ |
94 | virtual void setPos( size pos ) = 0; | 94 | virtual void setPos( size pos ) = 0; |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * Set position in the stream relative to the end of the stream. | 97 | * Set position in the stream relative to the end of the stream. |
98 | *@param pos (long) The position. | 98 | *@param pos (long) The position. |
99 | */ | 99 | */ |
100 | virtual void setPosEnd( size pos ) = 0; | 100 | virtual void setPosEnd( size pos ) = 0; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Are we at the end of the stream? | 103 | * Are we at the end of the stream? |
104 | *@returns (bool) Are we at the end of the stream? | 104 | *@returns (bool) Are we at the end of the stream? |
105 | */ | 105 | */ |
106 | virtual bool isEos() = 0; | 106 | virtual bool isEos() = 0; |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * Is the stream open? | 109 | * Is the stream open? |
110 | *@returns (bool) Is the stream open? | 110 | *@returns (bool) Is the stream open? |
111 | */ | 111 | */ |
112 | virtual bool isOpen() = 0; | 112 | virtual bool isOpen() = 0; |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * Flush any data still held in buffers. | 115 | * Flush any data still held in buffers. |
116 | */ | 116 | */ |
117 | virtual void flush() = 0; | 117 | virtual void flush() = 0; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * In non-blocking streams this indicates if a read operation will | 120 | * In non-blocking streams this indicates if a read operation will |
121 | * return data at the moment or not. In blocking streams this should | 121 | * return data at the moment or not. In blocking streams this should |
122 | * return the same value as isEos(). | 122 | * return the same value as isEos(). |
123 | */ | 123 | */ |
124 | virtual bool canRead() = 0; | 124 | virtual bool canRead() = 0; |
125 | 125 | ||
126 | /** | 126 | /** |
127 | * In non-blocking streams this indicates if a write operation will | 127 | * In non-blocking streams this indicates if a write operation will |
128 | * actually write one or more bytes. In some cases writing is not | 128 | * actually write one or more bytes. In some cases writing is not |
129 | * allowed (e.g. internal buffers are full) temporarilly. In blocking | 129 | * allowed (e.g. internal buffers are full) temporarilly. In blocking |
130 | * streams this should return the same value as isWritable. | 130 | * streams this should return the same value as isWritable. |
131 | */ | 131 | */ |
132 | virtual bool canWrite() = 0; | 132 | virtual bool canWrite() = 0; |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * Indicates if the stream is capable of read operations. This does not | 135 | * Indicates if the stream is capable of read operations. This does not |
136 | * indicate if such operations will return useful data, see canRead for | 136 | * indicate if such operations will return useful data, see canRead for |
137 | * that. | 137 | * that. |
138 | */ | 138 | */ |
139 | virtual bool isReadable() = 0; | 139 | virtual bool isReadable() = 0; |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * Indicates if the stream is capable of write operations. This does | 142 | * Indicates if the stream is capable of write operations. This does |
143 | * not indicate if such operations will succeed or fail, see canWrite | 143 | * not indicate if such operations will succeed or fail, see canWrite |
144 | * for that. | 144 | * for that. |
145 | */ | 145 | */ |
146 | virtual bool isWritable() = 0; | 146 | virtual bool isWritable() = 0; |
147 | 147 | ||
148 | /** | 148 | /** |
149 | * Indicates if the stream is capable of seek operations. This is | 149 | * Indicates if the stream is capable of seek operations. This is |
150 | * generally false for non-blocking streams. Some buffered streams may | 150 | * generally false for non-blocking streams. Some buffered streams may |
151 | * support limited in-buffer seeking. | 151 | * support limited in-buffer seeking. |
152 | */ | 152 | */ |
153 | virtual bool isSeekable() = 0; | 153 | virtual bool isSeekable() = 0; |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * Are we currently set to block mode? | 156 | * Are we currently set to block mode? |
157 | *@returns (bool) | 157 | *@returns (bool) |
158 | */ | 158 | */ |
159 | virtual bool isBlocking() = 0; | 159 | virtual bool isBlocking() = 0; |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * Set stream to blocking or non-blocking mode. | 162 | * Set stream to blocking or non-blocking mode. |
163 | *@param bBlocking (bool) Whether we should block or not. | 163 | *@param bBlocking (bool) Whether we should block or not. |
164 | */ | 164 | */ |
165 | virtual void setBlocking( bool bBlocking=true ) = 0; | 165 | virtual void setBlocking( bool bBlocking=true ) = 0; |
166 | 166 | ||
167 | /** | 167 | /** |
168 | * Set the size of the stream, this does not apply to many types of | 168 | * Set the size of the stream, this does not apply to many types of |
169 | * streams. For those that it does apply to, data will be added or | 169 | * streams. For those that it does apply to, data will be added or |
170 | * removed from the end of the stream, but the content of the added | 170 | * removed from the end of the stream, but the content of the added |
171 | * data is undefined. | 171 | * data is undefined. |
172 | */ | 172 | */ |
173 | virtual void setSize( size iSize ) = 0; | 173 | virtual void setSize( size iSize ) = 0; |
174 | 174 | ||
175 | /** | 175 | /** |
176 | * Returns the size of the stream if the stream can have a size. For | 176 | * Returns the size of the stream if the stream can have a size. For |
177 | * streams that do not (sockets, pipes, etc.) this should throw an | 177 | * streams that do not (sockets, pipes, etc.) this should throw an |
178 | * unsupported exception. | 178 | * unsupported exception. |
179 | */ | 179 | */ |
180 | virtual size getSize() const = 0; | 180 | virtual size getSize() const = 0; |
181 | 181 | ||
182 | /** | 182 | /** |
183 | * Returns the block-size of the stream, if it has one. This should | 183 | * Returns the block-size of the stream, if it has one. This should |
184 | * throw an unsupported exception. In some cases the block size | 184 | * throw an unsupported exception. In some cases the block size |
185 | * returned will not represent quite the same thing, for example, | 185 | * returned will not represent quite the same thing, for example, |
186 | * sockets will return their MTU, while files will return the | 186 | * sockets will return their MTU, while files will return the |
187 | * filesystem's block size, and memory buffers will throw an exception. | 187 | * filesystem's block size, and memory buffers will throw an exception. |
188 | */ | 188 | */ |
189 | virtual size getBlockSize() const = 0; | 189 | virtual size getBlockSize() const = 0; |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * If possible, this returns a string that can be used to describe how | 192 | * If possible, this returns a string that can be used to describe how |
193 | * to access the open stream. Not all streams support this, such as | 193 | * to access the open stream. Not all streams support this, such as |
194 | * MemBuf, but for files it may give you a path to a file, for a socket | 194 | * MemBuf, but for files it may give you a path to a file, for a socket |
195 | * it may give you an ip address, etc. If it isn't supported, an empty | 195 | * it may give you an ip address, etc. If it isn't supported, an empty |
196 | * string may be returned. | 196 | * string may be returned. |
197 | */ | 197 | */ |
198 | virtual Bu::String getLocation() const = 0; | 198 | virtual Bu::String getLocation() const = 0; |
199 | 199 | ||
200 | private: | 200 | private: |
201 | 201 | ||
202 | }; | 202 | }; |
203 | } | 203 | } |
204 | 204 | ||
205 | #endif | 205 | #endif |
diff --git a/src/stable/streamstack.cpp b/src/stable/streamstack.cpp index 47ae5c0..deafbcf 100644 --- a/src/stable/streamstack.cpp +++ b/src/stable/streamstack.cpp | |||
@@ -13,222 +13,222 @@ Bu::StreamStack::StreamStack() | |||
13 | 13 | ||
14 | Bu::StreamStack::StreamStack( Bu::Stream *pStream ) | 14 | Bu::StreamStack::StreamStack( Bu::Stream *pStream ) |
15 | { | 15 | { |
16 | lFilts.prepend( pStream ); | 16 | lFilts.prepend( pStream ); |
17 | } | 17 | } |
18 | 18 | ||
19 | Bu::StreamStack::~StreamStack() | 19 | Bu::StreamStack::~StreamStack() |
20 | { | 20 | { |
21 | clear(); | 21 | clear(); |
22 | } | 22 | } |
23 | 23 | ||
24 | bool Bu::StreamStack::isEmpty() | 24 | bool Bu::StreamStack::isEmpty() |
25 | { | 25 | { |
26 | return lFilts.isEmpty(); | 26 | return lFilts.isEmpty(); |
27 | } | 27 | } |
28 | 28 | ||
29 | bool Bu::StreamStack::hasStream() | 29 | bool Bu::StreamStack::hasStream() |
30 | { | 30 | { |
31 | return !lFilts.isEmpty(); | 31 | return !lFilts.isEmpty(); |
32 | } | 32 | } |
33 | 33 | ||
34 | void Bu::StreamStack::setStream( Bu::Stream *pStream ) | 34 | void Bu::StreamStack::setStream( Bu::Stream *pStream ) |
35 | { | 35 | { |
36 | if( !lFilts.isEmpty() ) | 36 | if( !lFilts.isEmpty() ) |
37 | throw Bu::ExceptionBase("There is already a stream set."); | 37 | throw Bu::ExceptionBase("There is already a stream set."); |
38 | 38 | ||
39 | lFilts.prepend( pStream ); | 39 | lFilts.prepend( pStream ); |
40 | } | 40 | } |
41 | 41 | ||
42 | void Bu::StreamStack::clear() | 42 | void Bu::StreamStack::clear() |
43 | { | 43 | { |
44 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 44 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
45 | { | 45 | { |
46 | delete *i; | 46 | delete *i; |
47 | } | 47 | } |
48 | 48 | ||
49 | lFilts.clear(); | 49 | lFilts.clear(); |
50 | } | 50 | } |
51 | 51 | ||
52 | void Bu::StreamStack::popFilter() | 52 | void Bu::StreamStack::popFilter() |
53 | { | 53 | { |
54 | if( lFilts.isEmpty() ) | 54 | if( lFilts.isEmpty() ) |
55 | return; | 55 | return; |
56 | 56 | ||
57 | delete lFilts.first(); | 57 | delete lFilts.first(); |
58 | lFilts.erase( lFilts.begin() ); | 58 | lFilts.erase( lFilts.begin() ); |
59 | } | 59 | } |
60 | 60 | ||
61 | Bu::Stream *Bu::StreamStack::getTop() | 61 | Bu::Stream *Bu::StreamStack::getTop() |
62 | { | 62 | { |
63 | checkStack(); | 63 | checkStack(); |
64 | 64 | ||
65 | return lFilts.first(); | 65 | return lFilts.first(); |
66 | } | 66 | } |
67 | 67 | ||
68 | Bu::Stream *Bu::StreamStack::getStream() | 68 | Bu::Stream *Bu::StreamStack::getStream() |
69 | { | 69 | { |
70 | checkStack(); | 70 | checkStack(); |
71 | 71 | ||
72 | return lFilts.last(); | 72 | return lFilts.last(); |
73 | } | 73 | } |
74 | 74 | ||
75 | void Bu::StreamStack::close() | 75 | void Bu::StreamStack::close() |
76 | { | 76 | { |
77 | checkStack(); | 77 | checkStack(); |
78 | 78 | ||
79 | lFilts.first()->close(); | 79 | lFilts.first()->close(); |
80 | } | 80 | } |
81 | 81 | ||
82 | Bu::size Bu::StreamStack::read( void *pBuf, Bu::size nBytes ) | 82 | Bu::size Bu::StreamStack::read( void *pBuf, Bu::size nBytes ) |
83 | { | 83 | { |
84 | checkStack(); | 84 | checkStack(); |
85 | 85 | ||
86 | return lFilts.first()->read( pBuf, nBytes ); | 86 | return lFilts.first()->read( pBuf, nBytes ); |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::size Bu::StreamStack::write( const void *pBuf, Bu::size nBytes ) | 89 | Bu::size Bu::StreamStack::write( const void *pBuf, Bu::size nBytes ) |
90 | { | 90 | { |
91 | checkStack(); | 91 | checkStack(); |
92 | 92 | ||
93 | return lFilts.first()->write( pBuf, nBytes ); | 93 | return lFilts.first()->write( pBuf, nBytes ); |
94 | } | 94 | } |
95 | 95 | ||
96 | Bu::size Bu::StreamStack::write( const Bu::String &sBuf ) | 96 | Bu::size Bu::StreamStack::write( const Bu::String &sBuf ) |
97 | { | 97 | { |
98 | checkStack(); | 98 | checkStack(); |
99 | 99 | ||
100 | return lFilts.first()->write( sBuf ); | 100 | return lFilts.first()->write( sBuf ); |
101 | } | 101 | } |
102 | 102 | ||
103 | Bu::size Bu::StreamStack::tell() | 103 | Bu::size Bu::StreamStack::tell() |
104 | { | 104 | { |
105 | checkStack(); | 105 | checkStack(); |
106 | 106 | ||
107 | return lFilts.first()->tell(); | 107 | return lFilts.first()->tell(); |
108 | } | 108 | } |
109 | 109 | ||
110 | void Bu::StreamStack::seek( Bu::size offset ) | 110 | void Bu::StreamStack::seek( Bu::size offset ) |
111 | { | 111 | { |
112 | checkStack(); | 112 | checkStack(); |
113 | 113 | ||
114 | lFilts.first()->seek( offset ); | 114 | lFilts.first()->seek( offset ); |
115 | } | 115 | } |
116 | 116 | ||
117 | void Bu::StreamStack::setPos( Bu::size pos ) | 117 | void Bu::StreamStack::setPos( Bu::size pos ) |
118 | { | 118 | { |
119 | checkStack(); | 119 | checkStack(); |
120 | 120 | ||
121 | lFilts.first()->setPos( pos ); | 121 | lFilts.first()->setPos( pos ); |
122 | } | 122 | } |
123 | 123 | ||
124 | void Bu::StreamStack::setPosEnd( Bu::size pos ) | 124 | void Bu::StreamStack::setPosEnd( Bu::size pos ) |
125 | { | 125 | { |
126 | checkStack(); | 126 | checkStack(); |
127 | 127 | ||
128 | lFilts.first()->setPosEnd( pos ); | 128 | lFilts.first()->setPosEnd( pos ); |
129 | } | 129 | } |
130 | 130 | ||
131 | bool Bu::StreamStack::isEos() | 131 | bool Bu::StreamStack::isEos() |
132 | { | 132 | { |
133 | checkStack(); | 133 | checkStack(); |
134 | 134 | ||
135 | return lFilts.first()->isEos(); | 135 | return lFilts.first()->isEos(); |
136 | } | 136 | } |
137 | 137 | ||
138 | bool Bu::StreamStack::isOpen() | 138 | bool Bu::StreamStack::isOpen() |
139 | { | 139 | { |
140 | checkStack(); | 140 | checkStack(); |
141 | 141 | ||
142 | return lFilts.first()->isOpen(); | 142 | return lFilts.first()->isOpen(); |
143 | } | 143 | } |
144 | 144 | ||
145 | void Bu::StreamStack::flush() | 145 | void Bu::StreamStack::flush() |
146 | { | 146 | { |
147 | checkStack(); | 147 | checkStack(); |
148 | 148 | ||
149 | lFilts.first()->flush(); | 149 | lFilts.first()->flush(); |
150 | } | 150 | } |
151 | 151 | ||
152 | bool Bu::StreamStack::canRead() | 152 | bool Bu::StreamStack::canRead() |
153 | { | 153 | { |
154 | checkStack(); | 154 | checkStack(); |
155 | 155 | ||
156 | return lFilts.first()->canRead(); | 156 | return lFilts.first()->canRead(); |
157 | } | 157 | } |
158 | 158 | ||
159 | bool Bu::StreamStack::canWrite() | 159 | bool Bu::StreamStack::canWrite() |
160 | { | 160 | { |
161 | checkStack(); | 161 | checkStack(); |
162 | 162 | ||
163 | return lFilts.first()->canWrite(); | 163 | return lFilts.first()->canWrite(); |
164 | } | 164 | } |
165 | 165 | ||
166 | bool Bu::StreamStack::isReadable() | 166 | bool Bu::StreamStack::isReadable() |
167 | { | 167 | { |
168 | checkStack(); | 168 | checkStack(); |
169 | 169 | ||
170 | return lFilts.first()->isReadable(); | 170 | return lFilts.first()->isReadable(); |
171 | } | 171 | } |
172 | 172 | ||
173 | bool Bu::StreamStack::isWritable() | 173 | bool Bu::StreamStack::isWritable() |
174 | { | 174 | { |
175 | checkStack(); | 175 | checkStack(); |
176 | 176 | ||
177 | return lFilts.first()->isWritable(); | 177 | return lFilts.first()->isWritable(); |
178 | } | 178 | } |
179 | 179 | ||
180 | bool Bu::StreamStack::isSeekable() | 180 | bool Bu::StreamStack::isSeekable() |
181 | { | 181 | { |
182 | checkStack(); | 182 | checkStack(); |
183 | 183 | ||
184 | return lFilts.first()->isSeekable(); | 184 | return lFilts.first()->isSeekable(); |
185 | } | 185 | } |
186 | 186 | ||
187 | bool Bu::StreamStack::isBlocking() | 187 | bool Bu::StreamStack::isBlocking() |
188 | { | 188 | { |
189 | checkStack(); | 189 | checkStack(); |
190 | 190 | ||
191 | return lFilts.first()->isBlocking(); | 191 | return lFilts.first()->isBlocking(); |
192 | } | 192 | } |
193 | 193 | ||
194 | void Bu::StreamStack::setBlocking( bool bBlocking ) | 194 | void Bu::StreamStack::setBlocking( bool bBlocking ) |
195 | { | 195 | { |
196 | checkStack(); | 196 | checkStack(); |
197 | 197 | ||
198 | lFilts.first()->setBlocking( bBlocking ); | 198 | lFilts.first()->setBlocking( bBlocking ); |
199 | } | 199 | } |
200 | 200 | ||
201 | void Bu::StreamStack::setSize( Bu::size iSize ) | 201 | void Bu::StreamStack::setSize( Bu::size iSize ) |
202 | { | 202 | { |
203 | checkStack(); | 203 | checkStack(); |
204 | 204 | ||
205 | lFilts.first()->setSize( iSize ); | 205 | lFilts.first()->setSize( iSize ); |
206 | } | 206 | } |
207 | 207 | ||
208 | Bu::size Bu::StreamStack::getSize() const | 208 | Bu::size Bu::StreamStack::getSize() const |
209 | { | 209 | { |
210 | checkStack(); | 210 | checkStack(); |
211 | 211 | ||
212 | return lFilts.first()->getSize(); | 212 | return lFilts.first()->getSize(); |
213 | } | 213 | } |
214 | 214 | ||
215 | Bu::size Bu::StreamStack::getBlockSize() const | 215 | Bu::size Bu::StreamStack::getBlockSize() const |
216 | { | 216 | { |
217 | checkStack(); | 217 | checkStack(); |
218 | 218 | ||
219 | return lFilts.first()->getBlockSize(); | 219 | return lFilts.first()->getBlockSize(); |
220 | } | 220 | } |
221 | 221 | ||
222 | Bu::String Bu::StreamStack::getLocation() const | 222 | Bu::String Bu::StreamStack::getLocation() const |
223 | { | 223 | { |
224 | checkStack(); | 224 | checkStack(); |
225 | 225 | ||
226 | return lFilts.first()->getLocation(); | 226 | return lFilts.first()->getLocation(); |
227 | } | 227 | } |
228 | 228 | ||
229 | inline void Bu::StreamStack::checkStack() const | 229 | inline void Bu::StreamStack::checkStack() const |
230 | { | 230 | { |
231 | if( lFilts.isEmpty() ) | 231 | if( lFilts.isEmpty() ) |
232 | throw Bu::ExceptionBase("StreamStack is empty."); | 232 | throw Bu::ExceptionBase("StreamStack is empty."); |
233 | } | 233 | } |
234 | 234 | ||
diff --git a/src/stable/streamstack.h b/src/stable/streamstack.h index 36c2e11..06a3214 100644 --- a/src/stable/streamstack.h +++ b/src/stable/streamstack.h | |||
@@ -14,131 +14,131 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class StreamStack : public Bu::Stream | 17 | class StreamStack : public Bu::Stream |
18 | { | 18 | { |
19 | private: | 19 | private: |
20 | typedef Bu::List<Bu::Stream *> FilterList; | 20 | typedef Bu::List<Bu::Stream *> FilterList; |
21 | 21 | ||
22 | public: | 22 | public: |
23 | StreamStack(); | 23 | StreamStack(); |
24 | StreamStack( Bu::Stream *pStream ); | 24 | StreamStack( Bu::Stream *pStream ); |
25 | virtual ~StreamStack(); | 25 | virtual ~StreamStack(); |
26 | 26 | ||
27 | bool isEmpty(); | 27 | bool isEmpty(); |
28 | bool hasStream(); | 28 | bool hasStream(); |
29 | void setStream( Bu::Stream *pStream ); | 29 | void setStream( Bu::Stream *pStream ); |
30 | 30 | ||
31 | void clear(); | 31 | void clear(); |
32 | void popFilter(); | 32 | void popFilter(); |
33 | Bu::Stream *getTop(); | 33 | Bu::Stream *getTop(); |
34 | 34 | ||
35 | Bu::Stream *getStream(); | 35 | Bu::Stream *getStream(); |
36 | 36 | ||
37 | template<typename filter> | 37 | template<typename filter> |
38 | Bu::Stream *findFilter() | 38 | Bu::Stream *findFilter() |
39 | { | 39 | { |
40 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) | 40 | for( FilterList::iterator i = lFilts.begin(); i; i++ ) |
41 | { | 41 | { |
42 | if( typeid(**i) == typeid( filter ) ) | 42 | if( typeid(**i) == typeid( filter ) ) |
43 | { | 43 | { |
44 | return *i; | 44 | return *i; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | throw Bu::ExceptionBase("Filter not found."); | 48 | throw Bu::ExceptionBase("Filter not found."); |
49 | } | 49 | } |
50 | 50 | ||
51 | template<typename filter> | 51 | template<typename filter> |
52 | void pushFilter() | 52 | void pushFilter() |
53 | { | 53 | { |
54 | checkStack(); | 54 | checkStack(); |
55 | 55 | ||
56 | filter *pFlt = new filter( *lFilts.first() ); | 56 | filter *pFlt = new filter( *lFilts.first() ); |
57 | lFilts.prepend( pFlt ); | 57 | lFilts.prepend( pFlt ); |
58 | } | 58 | } |
59 | 59 | ||
60 | template<typename filter, typename p1t> | 60 | template<typename filter, typename p1t> |
61 | void pushFilter( p1t p1 ) | 61 | void pushFilter( p1t p1 ) |
62 | { | 62 | { |
63 | checkStack(); | 63 | checkStack(); |
64 | 64 | ||
65 | filter *pFlt = new filter( *lFilts.first(), p1 ); | 65 | filter *pFlt = new filter( *lFilts.first(), p1 ); |
66 | lFilts.prepend( pFlt ); | 66 | lFilts.prepend( pFlt ); |
67 | } | 67 | } |
68 | 68 | ||
69 | template<typename filter, typename p1t, typename p2t> | 69 | template<typename filter, typename p1t, typename p2t> |
70 | void pushFilter( p1t p1, p2t p2 ) | 70 | void pushFilter( p1t p1, p2t p2 ) |
71 | { | 71 | { |
72 | checkStack(); | 72 | checkStack(); |
73 | 73 | ||
74 | filter *pFlt = new filter( *lFilts.first(), p1, p2 ); | 74 | filter *pFlt = new filter( *lFilts.first(), p1, p2 ); |
75 | lFilts.prepend( pFlt ); | 75 | lFilts.prepend( pFlt ); |
76 | } | 76 | } |
77 | 77 | ||
78 | template<typename filter, typename p1t, typename p2t, typename p3t> | 78 | template<typename filter, typename p1t, typename p2t, typename p3t> |
79 | void pushFilter( p1t p1, p2t p2, p3t p3 ) | 79 | void pushFilter( p1t p1, p2t p2, p3t p3 ) |
80 | { | 80 | { |
81 | checkStack(); | 81 | checkStack(); |
82 | 82 | ||
83 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 ); | 83 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3 ); |
84 | lFilts.prepend( pFlt ); | 84 | lFilts.prepend( pFlt ); |
85 | } | 85 | } |
86 | 86 | ||
87 | template<typename filter, typename p1t, typename p2t, typename p3t, | 87 | template<typename filter, typename p1t, typename p2t, typename p3t, |
88 | typename p4t> | 88 | typename p4t> |
89 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 ) | 89 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4 ) |
90 | { | 90 | { |
91 | checkStack(); | 91 | checkStack(); |
92 | 92 | ||
93 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 ); | 93 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4 ); |
94 | lFilts.prepend( pFlt ); | 94 | lFilts.prepend( pFlt ); |
95 | } | 95 | } |
96 | 96 | ||
97 | template<typename filter, typename p1t, typename p2t, typename p3t, | 97 | template<typename filter, typename p1t, typename p2t, typename p3t, |
98 | typename p4t, typename p5t> | 98 | typename p4t, typename p5t> |
99 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 99 | void pushFilter( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
100 | { | 100 | { |
101 | checkStack(); | 101 | checkStack(); |
102 | 102 | ||
103 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 ); | 103 | filter *pFlt = new filter( *lFilts.first(), p1, p2, p3, p4, p5 ); |
104 | lFilts.prepend( pFlt ); | 104 | lFilts.prepend( pFlt ); |
105 | } | 105 | } |
106 | 106 | ||
107 | // | 107 | // |
108 | // Everything below here merely passes on the call to the top of the | 108 | // Everything below here merely passes on the call to the top of the |
109 | // stream stack. | 109 | // stream stack. |
110 | // | 110 | // |
111 | 111 | ||
112 | virtual void close(); | 112 | virtual void close(); |
113 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 113 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
114 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 114 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
115 | 115 | ||
116 | virtual Bu::size write( const Bu::String &sBuf ); | 116 | virtual Bu::size write( const Bu::String &sBuf ); |
117 | virtual Bu::size tell(); | 117 | virtual Bu::size tell(); |
118 | virtual void seek( Bu::size offset ); | 118 | virtual void seek( Bu::size offset ); |
119 | virtual void setPos( Bu::size pos ); | 119 | virtual void setPos( Bu::size pos ); |
120 | virtual void setPosEnd( Bu::size pos ); | 120 | virtual void setPosEnd( Bu::size pos ); |
121 | virtual bool isEos(); | 121 | virtual bool isEos(); |
122 | virtual bool isOpen(); | 122 | virtual bool isOpen(); |
123 | virtual void flush(); | 123 | virtual void flush(); |
124 | virtual bool canRead(); | 124 | virtual bool canRead(); |
125 | virtual bool canWrite(); | 125 | virtual bool canWrite(); |
126 | virtual bool isReadable(); | 126 | virtual bool isReadable(); |
127 | virtual bool isWritable(); | 127 | virtual bool isWritable(); |
128 | virtual bool isSeekable(); | 128 | virtual bool isSeekable(); |
129 | virtual bool isBlocking(); | 129 | virtual bool isBlocking(); |
130 | virtual void setBlocking( bool bBlocking=true ); | 130 | virtual void setBlocking( bool bBlocking=true ); |
131 | virtual void setSize( Bu::size iSize ); | 131 | virtual void setSize( Bu::size iSize ); |
132 | virtual size getSize() const; | 132 | virtual size getSize() const; |
133 | virtual size getBlockSize() const; | 133 | virtual size getBlockSize() const; |
134 | virtual Bu::String getLocation() const; | 134 | virtual Bu::String getLocation() const; |
135 | 135 | ||
136 | private: | 136 | private: |
137 | void checkStack() const; | 137 | void checkStack() const; |
138 | 138 | ||
139 | private: | 139 | private: |
140 | FilterList lFilts; | 140 | FilterList lFilts; |
141 | }; | 141 | }; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | #endif | 144 | #endif |
diff --git a/src/stable/strfilter.h b/src/stable/strfilter.h index 8da0a3f..c910574 100644 --- a/src/stable/strfilter.h +++ b/src/stable/strfilter.h | |||
@@ -6,119 +6,119 @@ | |||
6 | 6 | ||
7 | namespace Bu | 7 | namespace Bu |
8 | { | 8 | { |
9 | // | 9 | // |
10 | // Encoders | 10 | // Encoders |
11 | // | 11 | // |
12 | template<typename tFilter> | 12 | template<typename tFilter> |
13 | Bu::String encodeStr( const Bu::String &sIn ) | 13 | Bu::String encodeStr( const Bu::String &sIn ) |
14 | { | 14 | { |
15 | Bu::MemBuf mb; | 15 | Bu::MemBuf mb; |
16 | { | 16 | { |
17 | tFilter fEnc( mb ); | 17 | tFilter fEnc( mb ); |
18 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 18 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
19 | } | 19 | } |
20 | return mb.getString(); | 20 | return mb.getString(); |
21 | } | 21 | } |
22 | 22 | ||
23 | template<typename tFilter, typename p1t> | 23 | template<typename tFilter, typename p1t> |
24 | Bu::String encodeStr( const Bu::String &sIn, p1t p1 ) | 24 | Bu::String encodeStr( const Bu::String &sIn, p1t p1 ) |
25 | { | 25 | { |
26 | Bu::MemBuf mb; | 26 | Bu::MemBuf mb; |
27 | { | 27 | { |
28 | tFilter fEnc( mb, p1 ); | 28 | tFilter fEnc( mb, p1 ); |
29 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 29 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
30 | } | 30 | } |
31 | return mb.getString(); | 31 | return mb.getString(); |
32 | } | 32 | } |
33 | 33 | ||
34 | template<typename tFilter, typename p1t, typename p2t> | 34 | template<typename tFilter, typename p1t, typename p2t> |
35 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) | 35 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) |
36 | { | 36 | { |
37 | Bu::MemBuf mb; | 37 | Bu::MemBuf mb; |
38 | { | 38 | { |
39 | tFilter fEnc( mb, p1, p2 ); | 39 | tFilter fEnc( mb, p1, p2 ); |
40 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 40 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
41 | } | 41 | } |
42 | return mb.getString(); | 42 | return mb.getString(); |
43 | } | 43 | } |
44 | 44 | ||
45 | template<typename tFilter, typename p1t, typename p2t, typename p3t> | 45 | template<typename tFilter, typename p1t, typename p2t, typename p3t> |
46 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) | 46 | Bu::String encodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) |
47 | { | 47 | { |
48 | Bu::MemBuf mb; | 48 | Bu::MemBuf mb; |
49 | { | 49 | { |
50 | tFilter fEnc( mb, p1, p2 ); | 50 | tFilter fEnc( mb, p1, p2 ); |
51 | fEnc.write( sIn.getStr(), sIn.getSize() ); | 51 | fEnc.write( sIn.getStr(), sIn.getSize() ); |
52 | } | 52 | } |
53 | return mb.getString(); | 53 | return mb.getString(); |
54 | } | 54 | } |
55 | 55 | ||
56 | // | 56 | // |
57 | // Decoders | 57 | // Decoders |
58 | // | 58 | // |
59 | template<typename tFilter> | 59 | template<typename tFilter> |
60 | Bu::String decodeStr( const Bu::String &sIn ) | 60 | Bu::String decodeStr( const Bu::String &sIn ) |
61 | { | 61 | { |
62 | Bu::MemBuf mb( sIn ); | 62 | Bu::MemBuf mb( sIn ); |
63 | tFilter fDec( mb ); | 63 | tFilter fDec( mb ); |
64 | char buf[1024]; | 64 | char buf[1024]; |
65 | String sRet; | 65 | String sRet; |
66 | for(;;) | 66 | for(;;) |
67 | { | 67 | { |
68 | int iRead = fDec.read( buf, 1024 ); | 68 | int iRead = fDec.read( buf, 1024 ); |
69 | if( iRead == 0 ) | 69 | if( iRead == 0 ) |
70 | return sRet; | 70 | return sRet; |
71 | sRet.append( buf, iRead ); | 71 | sRet.append( buf, iRead ); |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | template<typename tFilter, typename p1t> | 75 | template<typename tFilter, typename p1t> |
76 | Bu::String decodeStr( const Bu::String &sIn, p1t p1 ) | 76 | Bu::String decodeStr( const Bu::String &sIn, p1t p1 ) |
77 | { | 77 | { |
78 | Bu::MemBuf mb( sIn ); | 78 | Bu::MemBuf mb( sIn ); |
79 | tFilter fDec( mb, p1 ); | 79 | tFilter fDec( mb, p1 ); |
80 | char buf[1024]; | 80 | char buf[1024]; |
81 | String sRet; | 81 | String sRet; |
82 | for(;;) | 82 | for(;;) |
83 | { | 83 | { |
84 | int iRead = fDec.read( buf, 1024 ); | 84 | int iRead = fDec.read( buf, 1024 ); |
85 | if( iRead == 0 ) | 85 | if( iRead == 0 ) |
86 | return sRet; | 86 | return sRet; |
87 | sRet.append( buf, iRead ); | 87 | sRet.append( buf, iRead ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
91 | template<typename tFilter, typename p1t, typename p2t> | 91 | template<typename tFilter, typename p1t, typename p2t> |
92 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) | 92 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2 ) |
93 | { | 93 | { |
94 | Bu::MemBuf mb( sIn ); | 94 | Bu::MemBuf mb( sIn ); |
95 | tFilter fDec( mb, p1, p2 ); | 95 | tFilter fDec( mb, p1, p2 ); |
96 | char buf[1024]; | 96 | char buf[1024]; |
97 | String sRet; | 97 | String sRet; |
98 | for(;;) | 98 | for(;;) |
99 | { | 99 | { |
100 | int iRead = fDec.read( buf, 1024 ); | 100 | int iRead = fDec.read( buf, 1024 ); |
101 | if( iRead == 0 ) | 101 | if( iRead == 0 ) |
102 | return sRet; | 102 | return sRet; |
103 | sRet.append( buf, iRead ); | 103 | sRet.append( buf, iRead ); |
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | template<typename tFilter, typename p1t, typename p2t, typename p3t> | 107 | template<typename tFilter, typename p1t, typename p2t, typename p3t> |
108 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) | 108 | Bu::String decodeStr( const Bu::String &sIn, p1t p1, p2t p2, p3t p3 ) |
109 | { | 109 | { |
110 | Bu::MemBuf mb( sIn ); | 110 | Bu::MemBuf mb( sIn ); |
111 | tFilter fDec( mb, p1, p2, p3 ); | 111 | tFilter fDec( mb, p1, p2, p3 ); |
112 | char buf[1024]; | 112 | char buf[1024]; |
113 | String sRet; | 113 | String sRet; |
114 | for(;;) | 114 | for(;;) |
115 | { | 115 | { |
116 | int iRead = fDec.read( buf, 1024 ); | 116 | int iRead = fDec.read( buf, 1024 ); |
117 | if( iRead == 0 ) | 117 | if( iRead == 0 ) |
118 | return sRet; | 118 | return sRet; |
119 | sRet.append( buf, iRead ); | 119 | sRet.append( buf, iRead ); |
120 | } | 120 | } |
121 | } | 121 | } |
122 | }; | 122 | }; |
123 | 123 | ||
124 | #endif | 124 | #endif |
diff --git a/src/stable/string.cpp b/src/stable/string.cpp index dd484fd..d073ec6 100644 --- a/src/stable/string.cpp +++ b/src/stable/string.cpp | |||
@@ -14,117 +14,117 @@ | |||
14 | #include "bu/formatter.h" | 14 | #include "bu/formatter.h" |
15 | #include <stdlib.h> | 15 | #include <stdlib.h> |
16 | 16 | ||
17 | #define nMinSize (256) | 17 | #define nMinSize (256) |
18 | 18 | ||
19 | Bu::StringCore::StringCore() : | 19 | Bu::StringCore::StringCore() : |
20 | nLength( 0 ), | 20 | nLength( 0 ), |
21 | pFirst( NULL ), | 21 | pFirst( NULL ), |
22 | pLast( NULL ) | 22 | pLast( NULL ) |
23 | { | 23 | { |
24 | } | 24 | } |
25 | 25 | ||
26 | Bu::StringCore::StringCore( const StringCore &rSrc ) : | 26 | Bu::StringCore::StringCore( const StringCore &rSrc ) : |
27 | nLength( rSrc.nLength ), | 27 | nLength( rSrc.nLength ), |
28 | pFirst( NULL ), | 28 | pFirst( NULL ), |
29 | pLast( NULL ) | 29 | pLast( NULL ) |
30 | { | 30 | { |
31 | if( rSrc.pFirst == NULL || rSrc.nLength == 0 ) | 31 | if( rSrc.pFirst == NULL || rSrc.nLength == 0 ) |
32 | { | 32 | { |
33 | pFirst = pLast = NULL; | 33 | pFirst = pLast = NULL; |
34 | } | 34 | } |
35 | else | 35 | else |
36 | { | 36 | { |
37 | pFirst = pLast = newChunk( nLength ); | 37 | pFirst = pLast = newChunk( nLength ); |
38 | Chunk *pLink = rSrc.pFirst; | 38 | Chunk *pLink = rSrc.pFirst; |
39 | int iPos = 0; | 39 | int iPos = 0; |
40 | while( pLink != NULL ) | 40 | while( pLink != NULL ) |
41 | { | 41 | { |
42 | memcpy( pFirst->pData+iPos, pLink->pData, pLink->nLength ); | 42 | memcpy( pFirst->pData+iPos, pLink->pData, pLink->nLength ); |
43 | iPos += pLink->nLength; | 43 | iPos += pLink->nLength; |
44 | pLink = pLink->pNext; | 44 | pLink = pLink->pNext; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | Bu::StringCore::~StringCore() | 49 | Bu::StringCore::~StringCore() |
50 | { | 50 | { |
51 | clear(); | 51 | clear(); |
52 | } | 52 | } |
53 | 53 | ||
54 | void Bu::StringCore::clear() const | 54 | void Bu::StringCore::clear() const |
55 | { | 55 | { |
56 | if( pFirst == NULL ) | 56 | if( pFirst == NULL ) |
57 | return; | 57 | return; |
58 | 58 | ||
59 | Chunk *i = pFirst; | 59 | Chunk *i = pFirst; |
60 | for(;;) | 60 | for(;;) |
61 | { | 61 | { |
62 | Chunk *n = i->pNext; | 62 | Chunk *n = i->pNext; |
63 | delete[] i->pData; | 63 | delete[] i->pData; |
64 | delete i; | 64 | delete i; |
65 | if( n == NULL ) | 65 | if( n == NULL ) |
66 | break; | 66 | break; |
67 | i = n; | 67 | i = n; |
68 | } | 68 | } |
69 | pFirst = pLast = NULL; | 69 | pFirst = pLast = NULL; |
70 | nLength = 0; | 70 | nLength = 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | Bu::StringCore::Chunk *Bu::StringCore::newChunk() const | 73 | Bu::StringCore::Chunk *Bu::StringCore::newChunk() const |
74 | { | 74 | { |
75 | Chunk *pNew = new Chunk; | 75 | Chunk *pNew = new Chunk; |
76 | pNew->pNext = NULL; | 76 | pNew->pNext = NULL; |
77 | return pNew; | 77 | return pNew; |
78 | } | 78 | } |
79 | 79 | ||
80 | Bu::StringCore::Chunk *Bu::StringCore::newChunk( long nLen ) const | 80 | Bu::StringCore::Chunk *Bu::StringCore::newChunk( long nLen ) const |
81 | { | 81 | { |
82 | Chunk *pNew = new Chunk; | 82 | Chunk *pNew = new Chunk; |
83 | pNew->pNext = NULL; | 83 | pNew->pNext = NULL; |
84 | pNew->nLength = nLen; | 84 | pNew->nLength = nLen; |
85 | pNew->pData = new char[(nLen<nMinSize)?(nMinSize):(nLen)+1]; | 85 | pNew->pData = new char[(nLen<nMinSize)?(nMinSize):(nLen)+1]; |
86 | pNew->pData[nLen] = (char)0; | 86 | pNew->pData[nLen] = (char)0; |
87 | return pNew; | 87 | return pNew; |
88 | } | 88 | } |
89 | 89 | ||
90 | Bu::StringCore::Chunk *Bu::StringCore::copyChunk( | 90 | Bu::StringCore::Chunk *Bu::StringCore::copyChunk( |
91 | Bu::StringCore::Chunk *pSrc ) const | 91 | Bu::StringCore::Chunk *pSrc ) const |
92 | { | 92 | { |
93 | Chunk *pNew = new Chunk; | 93 | Chunk *pNew = new Chunk; |
94 | pNew->pNext = pSrc->pNext; | 94 | pNew->pNext = pSrc->pNext; |
95 | pNew->nLength = pSrc->nLength; | 95 | pNew->nLength = pSrc->nLength; |
96 | pNew->pData = new char[ | 96 | pNew->pData = new char[ |
97 | (pNew->nLength<nMinSize)?(nMinSize):(pNew->nLength)+1 | 97 | (pNew->nLength<nMinSize)?(nMinSize):(pNew->nLength)+1 |
98 | ]; | 98 | ]; |
99 | memcpy( pNew->pData, pSrc->pData, pSrc->nLength ); | 99 | memcpy( pNew->pData, pSrc->pData, pSrc->nLength ); |
100 | pNew->pData[pNew->nLength] = (char)0; | 100 | pNew->pData[pNew->nLength] = (char)0; |
101 | return pNew; | 101 | return pNew; |
102 | } | 102 | } |
103 | 103 | ||
104 | void Bu::StringCore::appendChunk( Bu::StringCore::Chunk *pNewChunk ) | 104 | void Bu::StringCore::appendChunk( Bu::StringCore::Chunk *pNewChunk ) |
105 | { | 105 | { |
106 | if( pFirst == NULL ) | 106 | if( pFirst == NULL ) |
107 | pLast = pFirst = pNewChunk; | 107 | pLast = pFirst = pNewChunk; |
108 | else | 108 | else |
109 | { | 109 | { |
110 | pLast->pNext = pNewChunk; | 110 | pLast->pNext = pNewChunk; |
111 | pLast = pNewChunk; | 111 | pLast = pNewChunk; |
112 | } | 112 | } |
113 | 113 | ||
114 | nLength += pNewChunk->nLength; | 114 | nLength += pNewChunk->nLength; |
115 | } | 115 | } |
116 | 116 | ||
117 | void Bu::StringCore::prependChunk( Bu::StringCore::Chunk *pNewChunk ) | 117 | void Bu::StringCore::prependChunk( Bu::StringCore::Chunk *pNewChunk ) |
118 | { | 118 | { |
119 | if( pFirst == NULL ) | 119 | if( pFirst == NULL ) |
120 | pLast = pFirst = pNewChunk; | 120 | pLast = pFirst = pNewChunk; |
121 | else | 121 | else |
122 | { | 122 | { |
123 | pNewChunk->pNext = pFirst; | 123 | pNewChunk->pNext = pFirst; |
124 | pFirst = pNewChunk; | 124 | pFirst = pNewChunk; |
125 | } | 125 | } |
126 | 126 | ||
127 | nLength += pNewChunk->nLength; | 127 | nLength += pNewChunk->nLength; |
128 | } | 128 | } |
129 | 129 | ||
130 | Bu::String::String() | 130 | Bu::String::String() |
@@ -133,44 +133,44 @@ Bu::String::String() | |||
133 | 133 | ||
134 | Bu::String::String( const char *pData ) | 134 | Bu::String::String( const char *pData ) |
135 | { | 135 | { |
136 | append( pData ); | 136 | append( pData ); |
137 | } | 137 | } |
138 | 138 | ||
139 | Bu::String::String( const char *pData, long nLength ) | 139 | Bu::String::String( const char *pData, long nLength ) |
140 | { | 140 | { |
141 | append( pData, nLength ); | 141 | append( pData, nLength ); |
142 | } | 142 | } |
143 | 143 | ||
144 | Bu::String::String( const Bu::String &rSrc ) : | 144 | Bu::String::String( const Bu::String &rSrc ) : |
145 | Bu::SharedCore<Bu::String, Bu::StringCore>( rSrc ) | 145 | Bu::SharedCore<Bu::String, Bu::StringCore>( rSrc ) |
146 | { | 146 | { |
147 | } | 147 | } |
148 | 148 | ||
149 | Bu::String::String( const Bu::String &rSrc, long nLength ) | 149 | Bu::String::String( const Bu::String &rSrc, long nLength ) |
150 | { | 150 | { |
151 | append( rSrc, nLength ); | 151 | append( rSrc, nLength ); |
152 | } | 152 | } |
153 | 153 | ||
154 | Bu::String::String( const Bu::String &rSrc, long nStart, long nLength ) | 154 | Bu::String::String( const Bu::String &rSrc, long nStart, long nLength ) |
155 | { | 155 | { |
156 | append( rSrc, nStart, nLength ); | 156 | append( rSrc, nStart, nLength ); |
157 | } | 157 | } |
158 | 158 | ||
159 | Bu::String::String( long nSize ) | 159 | Bu::String::String( long nSize ) |
160 | { | 160 | { |
161 | core->pFirst = core->pLast = core->newChunk( nSize ); | 161 | core->pFirst = core->pLast = core->newChunk( nSize ); |
162 | core->nLength = nSize; | 162 | core->nLength = nSize; |
163 | } | 163 | } |
164 | 164 | ||
165 | Bu::String::String( const Bu::String::const_iterator &s ) | 165 | Bu::String::String( const Bu::String::const_iterator &s ) |
166 | { | 166 | { |
167 | append( s ); | 167 | append( s ); |
168 | } | 168 | } |
169 | 169 | ||
170 | Bu::String::String( const Bu::String::const_iterator &s, | 170 | Bu::String::String( const Bu::String::const_iterator &s, |
171 | const Bu::String::const_iterator &e ) | 171 | const Bu::String::const_iterator &e ) |
172 | { | 172 | { |
173 | append( s, e ); | 173 | append( s, e ); |
174 | } | 174 | } |
175 | 175 | ||
176 | Bu::String::~String() | 176 | Bu::String::~String() |
@@ -179,1049 +179,1049 @@ Bu::String::~String() | |||
179 | 179 | ||
180 | void Bu::String::append( const char *pData ) | 180 | void Bu::String::append( const char *pData ) |
181 | { | 181 | { |
182 | if( !pData ) return; | 182 | if( !pData ) return; |
183 | long nLen; | 183 | long nLen; |
184 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } | 184 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } |
185 | 185 | ||
186 | append( pData, 0, nLen ); | 186 | append( pData, 0, nLen ); |
187 | } | 187 | } |
188 | 188 | ||
189 | void Bu::String::append( const char *pData, long nLen ) | 189 | void Bu::String::append( const char *pData, long nLen ) |
190 | { | 190 | { |
191 | append( pData, 0, nLen ); | 191 | append( pData, 0, nLen ); |
192 | } | 192 | } |
193 | 193 | ||
194 | void Bu::String::append( const char *pData, long nStart, long nLen ) | 194 | void Bu::String::append( const char *pData, long nStart, long nLen ) |
195 | { | 195 | { |
196 | if( !pData ) return; | 196 | if( !pData ) return; |
197 | if( nLen <= 0 ) | 197 | if( nLen <= 0 ) |
198 | return; | 198 | return; |
199 | 199 | ||
200 | pData += nStart; | 200 | pData += nStart; |
201 | 201 | ||
202 | _hardCopy(); | 202 | _hardCopy(); |
203 | 203 | ||
204 | if( core->pLast && core->pLast->nLength < nMinSize ) | 204 | if( core->pLast && core->pLast->nLength < nMinSize ) |
205 | { | 205 | { |
206 | int nAmnt = nMinSize - core->pLast->nLength; | 206 | int nAmnt = nMinSize - core->pLast->nLength; |
207 | if( nAmnt > nLen ) | 207 | if( nAmnt > nLen ) |
208 | nAmnt = nLen; | 208 | nAmnt = nLen; |
209 | memcpy( | 209 | memcpy( |
210 | core->pLast->pData+core->pLast->nLength, | 210 | core->pLast->pData+core->pLast->nLength, |
211 | pData, | 211 | pData, |
212 | nAmnt | 212 | nAmnt |
213 | ); | 213 | ); |
214 | pData += nAmnt; | 214 | pData += nAmnt; |
215 | core->pLast->nLength += nAmnt; | 215 | core->pLast->nLength += nAmnt; |
216 | nLen -= nAmnt; | 216 | nLen -= nAmnt; |
217 | core->nLength += nAmnt; | 217 | core->nLength += nAmnt; |
218 | } | 218 | } |
219 | 219 | ||
220 | if( nLen > 0 ) | 220 | if( nLen > 0 ) |
221 | { | 221 | { |
222 | Chunk *pNew = core->newChunk( nLen ); | 222 | Chunk *pNew = core->newChunk( nLen ); |
223 | memcpy( pNew->pData, pData, nLen ); | 223 | memcpy( pNew->pData, pData, nLen ); |
224 | core->appendChunk( pNew ); | 224 | core->appendChunk( pNew ); |
225 | // core->nLength += nLen; | 225 | // core->nLength += nLen; |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | void Bu::String::append( const char &cData ) | 229 | void Bu::String::append( const char &cData ) |
230 | { | 230 | { |
231 | if( core->pLast && core->pLast->nLength < nMinSize ) | 231 | if( core->pLast && core->pLast->nLength < nMinSize ) |
232 | { | 232 | { |
233 | _hardCopy(); | 233 | _hardCopy(); |
234 | core->pLast->pData[core->pLast->nLength] = cData; | 234 | core->pLast->pData[core->pLast->nLength] = cData; |
235 | ++core->pLast->nLength; ++core->nLength; | 235 | ++core->pLast->nLength; ++core->nLength; |
236 | // pLast->pData[pLast->nLength] = (char)0; | 236 | // pLast->pData[pLast->nLength] = (char)0; |
237 | } | 237 | } |
238 | else | 238 | else |
239 | { | 239 | { |
240 | append( &cData, 1 ); | 240 | append( &cData, 1 ); |
241 | } | 241 | } |
242 | } | 242 | } |
243 | 243 | ||
244 | void Bu::String::append( const String & sData ) | 244 | void Bu::String::append( const String & sData ) |
245 | { | 245 | { |
246 | append( sData.getStr(), 0, sData.getSize() ); | 246 | append( sData.getStr(), 0, sData.getSize() ); |
247 | } | 247 | } |
248 | 248 | ||
249 | void Bu::String::append( const String & sData, long nLen ) | 249 | void Bu::String::append( const String & sData, long nLen ) |
250 | { | 250 | { |
251 | append( sData.getStr(), 0, nLen ); | 251 | append( sData.getStr(), 0, nLen ); |
252 | } | 252 | } |
253 | 253 | ||
254 | void Bu::String::append( const String & sData, long nStart, long nLen ) | 254 | void Bu::String::append( const String & sData, long nStart, long nLen ) |
255 | { | 255 | { |
256 | if( nLen < 0 ) | 256 | if( nLen < 0 ) |
257 | nLen = sData.getSize() - nStart; | 257 | nLen = sData.getSize() - nStart; |
258 | append( sData.getStr(), nStart, nLen ); | 258 | append( sData.getStr(), nStart, nLen ); |
259 | } | 259 | } |
260 | 260 | ||
261 | void Bu::String::append( const const_iterator &s ) | 261 | void Bu::String::append( const const_iterator &s ) |
262 | { | 262 | { |
263 | if( !s.isValid() ) | 263 | if( !s.isValid() ) |
264 | return; | 264 | return; |
265 | Chunk *pSrc = s.pChunk; | 265 | Chunk *pSrc = s.pChunk; |
266 | 266 | ||
267 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); | 267 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); |
268 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | 268 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); |
269 | 269 | ||
270 | _hardCopy(); | 270 | _hardCopy(); |
271 | core->appendChunk( pNew ); | 271 | core->appendChunk( pNew ); |
272 | 272 | ||
273 | while( (pSrc = pSrc->pNext) ) | 273 | while( (pSrc = pSrc->pNext) ) |
274 | { | 274 | { |
275 | core->appendChunk( core->copyChunk( pSrc ) ); | 275 | core->appendChunk( core->copyChunk( pSrc ) ); |
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
279 | void Bu::String::append( const iterator &s ) | 279 | void Bu::String::append( const iterator &s ) |
280 | { | 280 | { |
281 | append( const_iterator( s ) ); | 281 | append( const_iterator( s ) ); |
282 | } | 282 | } |
283 | 283 | ||
284 | void Bu::String::append( const const_iterator &s, const const_iterator &e ) | 284 | void Bu::String::append( const const_iterator &s, const const_iterator &e ) |
285 | { | 285 | { |
286 | if( !s.isValid() ) | 286 | if( !s.isValid() ) |
287 | return; | 287 | return; |
288 | if( !e.isValid() ) | 288 | if( !e.isValid() ) |
289 | { | 289 | { |
290 | append( s ); | 290 | append( s ); |
291 | return; | 291 | return; |
292 | } | 292 | } |
293 | _hardCopy(); | 293 | _hardCopy(); |
294 | if( s.pChunk == e.pChunk ) | 294 | if( s.pChunk == e.pChunk ) |
295 | { | 295 | { |
296 | // Simple case, they're the same chunk | 296 | // Simple case, they're the same chunk |
297 | Chunk *pNew = core->newChunk( e.iPos-s.iPos ); | 297 | Chunk *pNew = core->newChunk( e.iPos-s.iPos ); |
298 | memcpy( pNew->pData, s.pChunk->pData+s.iPos, e.iPos-s.iPos ); | 298 | memcpy( pNew->pData, s.pChunk->pData+s.iPos, e.iPos-s.iPos ); |
299 | core->appendChunk( pNew ); | 299 | core->appendChunk( pNew ); |
300 | } | 300 | } |
301 | else | 301 | else |
302 | { | 302 | { |
303 | // A little trickier, scan the blocks... | 303 | // A little trickier, scan the blocks... |
304 | Chunk *pSrc = s.pChunk; | 304 | Chunk *pSrc = s.pChunk; |
305 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); | 305 | Chunk *pNew = core->newChunk( pSrc->nLength-s.iPos ); |
306 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); | 306 | memcpy( pNew->pData, pSrc->pData+s.iPos, pSrc->nLength-s.iPos ); |
307 | core->appendChunk( pNew ); | 307 | core->appendChunk( pNew ); |
308 | 308 | ||
309 | while( (pSrc = pSrc->pNext) != e.pChunk ) | 309 | while( (pSrc = pSrc->pNext) != e.pChunk ) |
310 | { | 310 | { |
311 | core->appendChunk( core->copyChunk( pSrc ) ); | 311 | core->appendChunk( core->copyChunk( pSrc ) ); |
312 | } | 312 | } |
313 | 313 | ||
314 | pNew = core->newChunk( e.iPos ); | 314 | pNew = core->newChunk( e.iPos ); |
315 | memcpy( pNew->pData, pSrc->pData, e.iPos ); | 315 | memcpy( pNew->pData, pSrc->pData, e.iPos ); |
316 | core->appendChunk( pNew ); | 316 | core->appendChunk( pNew ); |
317 | } | 317 | } |
318 | } | 318 | } |
319 | 319 | ||
320 | void Bu::String::prepend( const String & sData ) | 320 | void Bu::String::prepend( const String & sData ) |
321 | { | 321 | { |
322 | prepend( sData.getStr(), sData.getSize() ); | 322 | prepend( sData.getStr(), sData.getSize() ); |
323 | } | 323 | } |
324 | 324 | ||
325 | void Bu::String::prepend( const char *pData ) | 325 | void Bu::String::prepend( const char *pData ) |
326 | { | 326 | { |
327 | if( pData == NULL ) | 327 | if( pData == NULL ) |
328 | return; | 328 | return; |
329 | 329 | ||
330 | _hardCopy(); | 330 | _hardCopy(); |
331 | long nLen; | 331 | long nLen; |
332 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } | 332 | for( nLen = 0; pData[nLen] != (char)0; nLen++ ) { } |
333 | 333 | ||
334 | Chunk *pNew = core->newChunk( nLen ); | 334 | Chunk *pNew = core->newChunk( nLen ); |
335 | memcpy( pNew->pData, pData, nLen ); | 335 | memcpy( pNew->pData, pData, nLen ); |
336 | 336 | ||
337 | core->prependChunk( pNew ); | 337 | core->prependChunk( pNew ); |
338 | } | 338 | } |
339 | 339 | ||
340 | void Bu::String::prepend( const char *pData, long nLen ) | 340 | void Bu::String::prepend( const char *pData, long nLen ) |
341 | { | 341 | { |
342 | Chunk *pNew = core->newChunk( nLen ); | 342 | Chunk *pNew = core->newChunk( nLen ); |
343 | 343 | ||
344 | memcpy( pNew->pData, pData, nLen ); | 344 | memcpy( pNew->pData, pData, nLen ); |
345 | 345 | ||
346 | _hardCopy(); | 346 | _hardCopy(); |
347 | core->prependChunk( pNew ); | 347 | core->prependChunk( pNew ); |
348 | } | 348 | } |
349 | 349 | ||
350 | void Bu::String::prepend( const char c ) | 350 | void Bu::String::prepend( const char c ) |
351 | { | 351 | { |
352 | prepend( &c, 1 ); | 352 | prepend( &c, 1 ); |
353 | } | 353 | } |
354 | 354 | ||
355 | void Bu::String::insert( long nPos, const char *pData, long nLen ) | 355 | void Bu::String::insert( long nPos, const char *pData, long nLen ) |
356 | { | 356 | { |
357 | if( nLen <= 0 ) | 357 | if( nLen <= 0 ) |
358 | return; | 358 | return; |
359 | if( nPos <= 0 ) | 359 | if( nPos <= 0 ) |
360 | { | 360 | { |
361 | prepend( pData, nLen ); | 361 | prepend( pData, nLen ); |
362 | } | 362 | } |
363 | else if( nPos >= core->nLength ) | 363 | else if( nPos >= core->nLength ) |
364 | { | 364 | { |
365 | append( pData, nLen ); | 365 | append( pData, nLen ); |
366 | } | 366 | } |
367 | else | 367 | else |
368 | { | 368 | { |
369 | // If we're going to flatten anyway, might as well for everyone | 369 | // If we're going to flatten anyway, might as well for everyone |
370 | flatten(); | 370 | flatten(); |
371 | _hardCopy(); | 371 | _hardCopy(); |
372 | Chunk *p1 = core->newChunk( nPos ); | 372 | Chunk *p1 = core->newChunk( nPos ); |
373 | Chunk *p2 = core->newChunk( nLen ); | 373 | Chunk *p2 = core->newChunk( nLen ); |
374 | Chunk *p3 = core->newChunk( core->nLength-nPos ); | 374 | Chunk *p3 = core->newChunk( core->nLength-nPos ); |
375 | memcpy( p1->pData, core->pFirst->pData, nPos ); | 375 | memcpy( p1->pData, core->pFirst->pData, nPos ); |
376 | memcpy( p2->pData, pData, nLen ); | 376 | memcpy( p2->pData, pData, nLen ); |
377 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); | 377 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); |
378 | core->clear(); | 378 | core->clear(); |
379 | core->appendChunk( p1 ); | 379 | core->appendChunk( p1 ); |
380 | core->appendChunk( p2 ); | 380 | core->appendChunk( p2 ); |
381 | core->appendChunk( p3 ); | 381 | core->appendChunk( p3 ); |
382 | } | 382 | } |
383 | } | 383 | } |
384 | 384 | ||
385 | void Bu::String::insert( long nPos, const String &str ) | 385 | void Bu::String::insert( long nPos, const String &str ) |
386 | { | 386 | { |
387 | if( nPos <= 0 ) | 387 | if( nPos <= 0 ) |
388 | { | 388 | { |
389 | prepend( str ); | 389 | prepend( str ); |
390 | } | 390 | } |
391 | else if( nPos >= core->nLength ) | 391 | else if( nPos >= core->nLength ) |
392 | { | 392 | { |
393 | append( str ); | 393 | append( str ); |
394 | } | 394 | } |
395 | else | 395 | else |
396 | { | 396 | { |
397 | flatten(); | 397 | flatten(); |
398 | _hardCopy(); | 398 | _hardCopy(); |
399 | Chunk *p1 = core->newChunk( nPos ); | 399 | Chunk *p1 = core->newChunk( nPos ); |
400 | Chunk *p3 = core->newChunk( core->nLength-nPos ); | 400 | Chunk *p3 = core->newChunk( core->nLength-nPos ); |
401 | memcpy( p1->pData, core->pFirst->pData, nPos ); | 401 | memcpy( p1->pData, core->pFirst->pData, nPos ); |
402 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); | 402 | memcpy( p3->pData, core->pFirst->pData+nPos, core->nLength-nPos ); |
403 | core->clear(); | 403 | core->clear(); |
404 | core->appendChunk( p1 ); | 404 | core->appendChunk( p1 ); |
405 | for( Chunk *pChnk = str.core->pFirst; pChnk; | 405 | for( Chunk *pChnk = str.core->pFirst; pChnk; |
406 | pChnk = pChnk->pNext ) | 406 | pChnk = pChnk->pNext ) |
407 | { | 407 | { |
408 | core->appendChunk( core->copyChunk( pChnk ) ); | 408 | core->appendChunk( core->copyChunk( pChnk ) ); |
409 | } | 409 | } |
410 | 410 | ||
411 | core->appendChunk( p3 ); | 411 | core->appendChunk( p3 ); |
412 | } | 412 | } |
413 | } | 413 | } |
414 | 414 | ||
415 | void Bu::String::insert( long nPos, const char *pData ) | 415 | void Bu::String::insert( long nPos, const char *pData ) |
416 | { | 416 | { |
417 | insert( nPos, pData, strlen( pData ) ); | 417 | insert( nPos, pData, strlen( pData ) ); |
418 | } | 418 | } |
419 | 419 | ||
420 | void Bu::String::remove( long nPos, long nLen ) | 420 | void Bu::String::remove( long nPos, long nLen ) |
421 | { | 421 | { |
422 | if( nLen <= 0 || nPos < 0 || nPos >= core->nLength ) | 422 | if( nLen <= 0 || nPos < 0 || nPos >= core->nLength ) |
423 | return; | 423 | return; |
424 | if( nLen > core->nLength-nPos ) | 424 | if( nLen > core->nLength-nPos ) |
425 | nLen = core->nLength-nPos; | 425 | nLen = core->nLength-nPos; |
426 | flatten(); | 426 | flatten(); |
427 | _hardCopy(); | 427 | _hardCopy(); |
428 | memmove( core->pFirst->pData+nPos, core->pFirst->pData+nPos+nLen, core->nLength-nPos-nLen+1 ); | 428 | memmove( core->pFirst->pData+nPos, core->pFirst->pData+nPos+nLen, core->nLength-nPos-nLen+1 ); |
429 | core->nLength -= nLen; | 429 | core->nLength -= nLen; |
430 | core->pFirst->nLength -= nLen; | 430 | core->pFirst->nLength -= nLen; |
431 | } | 431 | } |
432 | 432 | ||
433 | void Bu::String::clear() | 433 | void Bu::String::clear() |
434 | { | 434 | { |
435 | _hardCopy(); | 435 | _hardCopy(); |
436 | core->clear(); | 436 | core->clear(); |
437 | } | 437 | } |
438 | 438 | ||
439 | Bu::String Bu::String::replace( const Bu::String &fnd, | 439 | Bu::String Bu::String::replace( const Bu::String &fnd, |
440 | const Bu::String &rep ) const | 440 | const Bu::String &rep ) const |
441 | { | 441 | { |
442 | String out; | 442 | String out; |
443 | const_iterator o = begin(); | 443 | const_iterator o = begin(); |
444 | while( true ) | 444 | while( true ) |
445 | { | 445 | { |
446 | const_iterator i = o.find( fnd, fnd.getSize() ); | 446 | const_iterator i = o.find( fnd, fnd.getSize() ); |
447 | if( !i ) | 447 | if( !i ) |
448 | { | 448 | { |
449 | out.append( o ); | 449 | out.append( o ); |
450 | return out; | 450 | return out; |
451 | } | 451 | } |
452 | else | 452 | else |
453 | { | 453 | { |
454 | out.append( o, i ); | 454 | out.append( o, i ); |
455 | out.append( rep ); | 455 | out.append( rep ); |
456 | o = i; | 456 | o = i; |
457 | o += fnd.getSize(); | 457 | o += fnd.getSize(); |
458 | } | 458 | } |
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | void Bu::String::resize( long nNewSize ) | 462 | void Bu::String::resize( long nNewSize ) |
463 | { | 463 | { |
464 | if( core->nLength == nNewSize ) | 464 | if( core->nLength == nNewSize ) |
465 | return; | 465 | return; |
466 | if( nNewSize < 0 ) | 466 | if( nNewSize < 0 ) |
467 | nNewSize = 0; | 467 | nNewSize = 0; |
468 | 468 | ||
469 | flatten(); | 469 | flatten(); |
470 | _hardCopy(); | 470 | _hardCopy(); |
471 | 471 | ||
472 | // TODO: This is bad | 472 | // TODO: This is bad |
473 | 473 | ||
474 | Chunk *pNew = core->newChunk( nNewSize ); | 474 | Chunk *pNew = core->newChunk( nNewSize ); |
475 | long nNewLen = (nNewSize<core->nLength)?(nNewSize):(core->nLength); | 475 | long nNewLen = (nNewSize<core->nLength)?(nNewSize):(core->nLength); |
476 | if( core->nLength > 0 ) | 476 | if( core->nLength > 0 ) |
477 | { | 477 | { |
478 | memcpy( pNew->pData, core->pFirst->pData, nNewLen ); | 478 | memcpy( pNew->pData, core->pFirst->pData, nNewLen ); |
479 | delete[] core->pFirst->pData; | 479 | delete[] core->pFirst->pData; |
480 | delete core->pFirst; | 480 | delete core->pFirst; |
481 | } | 481 | } |
482 | pNew->pData[nNewLen] = (char)0; | 482 | pNew->pData[nNewLen] = (char)0; |
483 | core->pFirst = core->pLast = pNew; | 483 | core->pFirst = core->pLast = pNew; |
484 | core->nLength = nNewSize; | 484 | core->nLength = nNewSize; |
485 | } | 485 | } |
486 | 486 | ||
487 | long Bu::String::getSize() const | 487 | long Bu::String::getSize() const |
488 | { | 488 | { |
489 | return core->nLength; | 489 | return core->nLength; |
490 | } | 490 | } |
491 | 491 | ||
492 | char *Bu::String::getStr() | 492 | char *Bu::String::getStr() |
493 | { | 493 | { |
494 | if( core->pFirst == NULL || core->nLength == 0 ) | 494 | if( core->pFirst == NULL || core->nLength == 0 ) |
495 | return (char *)""; | 495 | return (char *)""; |
496 | 496 | ||
497 | flatten(); | 497 | flatten(); |
498 | _hardCopy(); | 498 | _hardCopy(); |
499 | core->pFirst->pData[core->nLength] = (char)0; | 499 | core->pFirst->pData[core->nLength] = (char)0; |
500 | return core->pFirst->pData; | 500 | return core->pFirst->pData; |
501 | } | 501 | } |
502 | 502 | ||
503 | const char *Bu::String::getStr() const | 503 | const char *Bu::String::getStr() const |
504 | { | 504 | { |
505 | if( core->pFirst == NULL || core->nLength == 0 ) | 505 | if( core->pFirst == NULL || core->nLength == 0 ) |
506 | return (char *)""; | 506 | return (char *)""; |
507 | 507 | ||
508 | flatten(); | 508 | flatten(); |
509 | core->pFirst->pData[core->nLength] = (char)0; | 509 | core->pFirst->pData[core->nLength] = (char)0; |
510 | return core->pFirst->pData; | 510 | return core->pFirst->pData; |
511 | } | 511 | } |
512 | 512 | ||
513 | const char *Bu::String::getConstStr() const | 513 | const char *Bu::String::getConstStr() const |
514 | { | 514 | { |
515 | return getStr(); | 515 | return getStr(); |
516 | } | 516 | } |
517 | 517 | ||
518 | Bu::String Bu::String::getSubStrIdx( long iStart, long iSize ) const | 518 | Bu::String Bu::String::getSubStrIdx( long iStart, long iSize ) const |
519 | { | 519 | { |
520 | if( iStart < 0 ) | 520 | if( iStart < 0 ) |
521 | iStart = 0; | 521 | iStart = 0; |
522 | if( iStart >= core->nLength ) | 522 | if( iStart >= core->nLength ) |
523 | return (const char[]){(char)0}; | 523 | return (const char[]){(char)0}; |
524 | if( iSize < 0 ) | 524 | if( iSize < 0 ) |
525 | iSize = core->nLength; | 525 | iSize = core->nLength; |
526 | if( iStart+iSize > core->nLength ) | 526 | if( iStart+iSize > core->nLength ) |
527 | iSize = core->nLength-iStart; | 527 | iSize = core->nLength-iStart; |
528 | if( iSize == 0 ) | 528 | if( iSize == 0 ) |
529 | return (const char[]){(char)0}; | 529 | return (const char[]){(char)0}; |
530 | 530 | ||
531 | flatten(); | 531 | flatten(); |
532 | String ret( core->pFirst->pData+iStart, iSize ); | 532 | String ret( core->pFirst->pData+iStart, iSize ); |
533 | return ret; | 533 | return ret; |
534 | } | 534 | } |
535 | 535 | ||
536 | Bu::String Bu::String::getSubStr( const_iterator iBegin, | 536 | Bu::String Bu::String::getSubStr( const_iterator iBegin, |
537 | const_iterator iEnd ) const | 537 | const_iterator iEnd ) const |
538 | { | 538 | { |
539 | if( !iBegin.isValid() ) | 539 | if( !iBegin.isValid() ) |
540 | return String(); | 540 | return String(); |
541 | if( iBegin.pChunk == iEnd.pChunk ) | 541 | if( iBegin.pChunk == iEnd.pChunk ) |
542 | { | 542 | { |
543 | return String( iBegin.pChunk->pData+iBegin.iPos, | 543 | return String( iBegin.pChunk->pData+iBegin.iPos, |
544 | iEnd.iPos-iBegin.iPos ); | 544 | iEnd.iPos-iBegin.iPos ); |
545 | } | 545 | } |
546 | else if( !iEnd.isValid() ) | 546 | else if( !iEnd.isValid() ) |
547 | { | 547 | { |
548 | String ret; | 548 | String ret; |
549 | ret.append( | 549 | ret.append( |
550 | iBegin.pChunk->pData+iBegin.iPos, | 550 | iBegin.pChunk->pData+iBegin.iPos, |
551 | iBegin.pChunk->nLength-iBegin.iPos | 551 | iBegin.pChunk->nLength-iBegin.iPos |
552 | ); | 552 | ); |
553 | for( Chunk *pCur = iBegin.pChunk->pNext; | 553 | for( Chunk *pCur = iBegin.pChunk->pNext; |
554 | pCur; pCur = pCur->pNext ) | 554 | pCur; pCur = pCur->pNext ) |
555 | { | 555 | { |
556 | ret.append( pCur->pData, pCur->nLength ); | 556 | ret.append( pCur->pData, pCur->nLength ); |
557 | } | 557 | } |
558 | return ret; | 558 | return ret; |
559 | } | 559 | } |
560 | else | 560 | else |
561 | { | 561 | { |
562 | String ret; | 562 | String ret; |
563 | ret.append( | 563 | ret.append( |
564 | iBegin.pChunk->pData+iBegin.iPos, | 564 | iBegin.pChunk->pData+iBegin.iPos, |
565 | iBegin.pChunk->nLength-iBegin.iPos | 565 | iBegin.pChunk->nLength-iBegin.iPos |
566 | ); | 566 | ); |
567 | for( Chunk *pCur = iBegin.pChunk->pNext; | 567 | for( Chunk *pCur = iBegin.pChunk->pNext; |
568 | pCur != iEnd.pChunk; pCur = pCur->pNext ) | 568 | pCur != iEnd.pChunk; pCur = pCur->pNext ) |
569 | { | 569 | { |
570 | ret.append( pCur->pData, pCur->nLength ); | 570 | ret.append( pCur->pData, pCur->nLength ); |
571 | } | 571 | } |
572 | ret.append( | 572 | ret.append( |
573 | iEnd.pChunk->pData, | 573 | iEnd.pChunk->pData, |
574 | iEnd.iPos | 574 | iEnd.iPos |
575 | ); | 575 | ); |
576 | return ret; | 576 | return ret; |
577 | } | 577 | } |
578 | } | 578 | } |
579 | 579 | ||
580 | Bu::StringList Bu::String::split( const char c ) const | 580 | Bu::StringList Bu::String::split( const char c ) const |
581 | { | 581 | { |
582 | Bu::StringList ret; | 582 | Bu::StringList ret; |
583 | const_iterator l, r; | 583 | const_iterator l, r; |
584 | l = begin(); | 584 | l = begin(); |
585 | for(r=l; l;) | 585 | for(r=l; l;) |
586 | { | 586 | { |
587 | for( r = l; r && r != c; r++ ) { } | 587 | for( r = l; r && r != c; r++ ) { } |
588 | ret.append( String( l, r ) ); | 588 | ret.append( String( l, r ) ); |
589 | l = r; | 589 | l = r; |
590 | l++; | 590 | l++; |
591 | } | 591 | } |
592 | return ret; | 592 | return ret; |
593 | } | 593 | } |
594 | 594 | ||
595 | Bu::String &Bu::String::operator+=( const char *pData ) | 595 | Bu::String &Bu::String::operator+=( const char *pData ) |
596 | { | 596 | { |
597 | append( pData ); | 597 | append( pData ); |
598 | 598 | ||
599 | return (*this); | 599 | return (*this); |
600 | } | 600 | } |
601 | 601 | ||
602 | Bu::String &Bu::String::operator+=( const Bu::String &rSrc ) | 602 | Bu::String &Bu::String::operator+=( const Bu::String &rSrc ) |
603 | { | 603 | { |
604 | append( rSrc ); | 604 | append( rSrc ); |
605 | 605 | ||
606 | return (*this); | 606 | return (*this); |
607 | } | 607 | } |
608 | 608 | ||
609 | Bu::String &Bu::String::operator+=( const Bu::String::const_iterator &i ) | 609 | Bu::String &Bu::String::operator+=( const Bu::String::const_iterator &i ) |
610 | { | 610 | { |
611 | append( i, i+1 ); | 611 | append( i, i+1 ); |
612 | 612 | ||
613 | return (*this); | 613 | return (*this); |
614 | } | 614 | } |
615 | 615 | ||
616 | Bu::String &Bu::String::operator+=( const char cData ) | 616 | Bu::String &Bu::String::operator+=( const char cData ) |
617 | { | 617 | { |
618 | if( core->pLast && core->pLast->nLength < nMinSize ) | 618 | if( core->pLast && core->pLast->nLength < nMinSize ) |
619 | { | 619 | { |
620 | _hardCopy(); | 620 | _hardCopy(); |
621 | core->pLast->pData[core->pLast->nLength] = cData; | 621 | core->pLast->pData[core->pLast->nLength] = cData; |
622 | ++core->pLast->nLength; ++core->nLength; | 622 | ++core->pLast->nLength; ++core->nLength; |
623 | // pLast->pData[pLast->nLength] = (char)0; | 623 | // pLast->pData[pLast->nLength] = (char)0; |
624 | } | 624 | } |
625 | else | 625 | else |
626 | { | 626 | { |
627 | append( &cData, 1 ); | 627 | append( &cData, 1 ); |
628 | } | 628 | } |
629 | //append( pData ); | 629 | //append( pData ); |
630 | 630 | ||
631 | return (*this); | 631 | return (*this); |
632 | } | 632 | } |
633 | 633 | ||
634 | Bu::String &Bu::String::operator=( const char *pData ) | 634 | Bu::String &Bu::String::operator=( const char *pData ) |
635 | { | 635 | { |
636 | set( pData ); | 636 | set( pData ); |
637 | 637 | ||
638 | return (*this); | 638 | return (*this); |
639 | } | 639 | } |
640 | 640 | ||
641 | Bu::String Bu::String::operator+( const Bu::String &rRight ) const | 641 | Bu::String Bu::String::operator+( const Bu::String &rRight ) const |
642 | { | 642 | { |
643 | String ret( *this ); | 643 | String ret( *this ); |
644 | ret.append( rRight ); | 644 | ret.append( rRight ); |
645 | return ret; | 645 | return ret; |
646 | } | 646 | } |
647 | 647 | ||
648 | Bu::String Bu::String::operator+( const char *pRight ) const | 648 | Bu::String Bu::String::operator+( const char *pRight ) const |
649 | { | 649 | { |
650 | String ret( *this ); | 650 | String ret( *this ); |
651 | ret.append( pRight ); | 651 | ret.append( pRight ); |
652 | return ret; | 652 | return ret; |
653 | } | 653 | } |
654 | 654 | ||
655 | Bu::String Bu::String::operator+( char *pRight ) const | 655 | Bu::String Bu::String::operator+( char *pRight ) const |
656 | { | 656 | { |
657 | String ret( *this ); | 657 | String ret( *this ); |
658 | ret.append( pRight ); | 658 | ret.append( pRight ); |
659 | return ret; | 659 | return ret; |
660 | } | 660 | } |
661 | 661 | ||
662 | void Bu::String::set( const char *pData ) | 662 | void Bu::String::set( const char *pData ) |
663 | { | 663 | { |
664 | clear(); | 664 | clear(); |
665 | append( pData ); | 665 | append( pData ); |
666 | } | 666 | } |
667 | 667 | ||
668 | void Bu::String::set( const char *pData, long nSize ) | 668 | void Bu::String::set( const char *pData, long nSize ) |
669 | { | 669 | { |
670 | clear(); | 670 | clear(); |
671 | append( pData, nSize ); | 671 | append( pData, nSize ); |
672 | } | 672 | } |
673 | 673 | ||
674 | void Bu::String::set( const char *pData, long nStart, long nSize ) | 674 | void Bu::String::set( const char *pData, long nStart, long nSize ) |
675 | { | 675 | { |
676 | clear(); | 676 | clear(); |
677 | append( pData, nStart, nSize ); | 677 | append( pData, nStart, nSize ); |
678 | } | 678 | } |
679 | 679 | ||
680 | void Bu::String::set( const String &rData ) | 680 | void Bu::String::set( const String &rData ) |
681 | { | 681 | { |
682 | clear(); | 682 | clear(); |
683 | append( rData ); | 683 | append( rData ); |
684 | } | 684 | } |
685 | 685 | ||
686 | void Bu::String::set( const String &rData, long nSize ) | 686 | void Bu::String::set( const String &rData, long nSize ) |
687 | { | 687 | { |
688 | clear(); | 688 | clear(); |
689 | append( rData, nSize ); | 689 | append( rData, nSize ); |
690 | } | 690 | } |
691 | 691 | ||
692 | void Bu::String::set( const String &rData, long nStart, long nSize ) | 692 | void Bu::String::set( const String &rData, long nStart, long nSize ) |
693 | { | 693 | { |
694 | clear(); | 694 | clear(); |
695 | append( rData, nStart, nSize ); | 695 | append( rData, nStart, nSize ); |
696 | } | 696 | } |
697 | 697 | ||
698 | void Bu::String::set( const_iterator s ) | 698 | void Bu::String::set( const_iterator s ) |
699 | { | 699 | { |
700 | clear(); | 700 | clear(); |
701 | append( s ); | 701 | append( s ); |
702 | } | 702 | } |
703 | 703 | ||
704 | void Bu::String::set( const_iterator s, const_iterator e ) | 704 | void Bu::String::set( const_iterator s, const_iterator e ) |
705 | { | 705 | { |
706 | clear(); | 706 | clear(); |
707 | append( s, e ); | 707 | append( s, e ); |
708 | } | 708 | } |
709 | 709 | ||
710 | void Bu::String::setSize( long iSize ) | 710 | void Bu::String::setSize( long iSize ) |
711 | { | 711 | { |
712 | _hardCopy(); | 712 | _hardCopy(); |
713 | core->clear(); | 713 | core->clear(); |
714 | core->appendChunk( core->newChunk( iSize ) ); | 714 | core->appendChunk( core->newChunk( iSize ) ); |
715 | } | 715 | } |
716 | 716 | ||
717 | bool Bu::String::operator==( const char *pData ) const | 717 | bool Bu::String::operator==( const char *pData ) const |
718 | { | 718 | { |
719 | if( core->pFirst == NULL || core->nLength == 0 ) { | 719 | if( core->pFirst == NULL || core->nLength == 0 ) { |
720 | if( pData == NULL ) | 720 | if( pData == NULL ) |
721 | return true; | 721 | return true; |
722 | if( pData[0] == (char)0 ) | 722 | if( pData[0] == (char)0 ) |
723 | return true; | 723 | return true; |
724 | return false; | 724 | return false; |
725 | } | 725 | } |
726 | 726 | ||
727 | flatten(); | 727 | flatten(); |
728 | core->pFirst->pData[core->nLength] = (char)0; | 728 | core->pFirst->pData[core->nLength] = (char)0; |
729 | const char *a = pData; | 729 | const char *a = pData; |
730 | char *b = core->pFirst->pData; | 730 | char *b = core->pFirst->pData; |
731 | for( long j = 0; *a!=(char)0 || *b!=(char)0; j++, a++, b++ ) | 731 | for( long j = 0; *a!=(char)0 || *b!=(char)0; j++, a++, b++ ) |
732 | { | 732 | { |
733 | if( *a != *b ) | 733 | if( *a != *b ) |
734 | return false; | 734 | return false; |
735 | if( *a == (char)0 && j < core->nLength ) | 735 | if( *a == (char)0 && j < core->nLength ) |
736 | return false; | 736 | return false; |
737 | } | 737 | } |
738 | 738 | ||
739 | return true; | 739 | return true; |
740 | } | 740 | } |
741 | 741 | ||
742 | bool Bu::String::operator==( const String &pData ) const | 742 | bool Bu::String::operator==( const String &pData ) const |
743 | { | 743 | { |
744 | if( core == pData.core ) | 744 | if( core == pData.core ) |
745 | return true; | 745 | return true; |
746 | if( core->pFirst == pData.core->pFirst ) | 746 | if( core->pFirst == pData.core->pFirst ) |
747 | return true; | 747 | return true; |
748 | if( (core->nLength == 0 && pData.core->nLength == 0) ) | 748 | if( (core->nLength == 0 && pData.core->nLength == 0) ) |
749 | return true; | 749 | return true; |
750 | if( core->nLength != pData.core->nLength ) | 750 | if( core->nLength != pData.core->nLength ) |
751 | return false; | 751 | return false; |
752 | if( pData.core->pFirst == NULL || core->pFirst == NULL ) | 752 | if( pData.core->pFirst == NULL || core->pFirst == NULL ) |
753 | return false; | 753 | return false; |
754 | 754 | ||
755 | flatten(); | 755 | flatten(); |
756 | pData.flatten(); | 756 | pData.flatten(); |
757 | const char *a = pData.core->pFirst->pData; | 757 | const char *a = pData.core->pFirst->pData; |
758 | char *b = core->pFirst->pData; | 758 | char *b = core->pFirst->pData; |
759 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 759 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
760 | { | 760 | { |
761 | if( *a != *b ) | 761 | if( *a != *b ) |
762 | return false; | 762 | return false; |
763 | } | 763 | } |
764 | 764 | ||
765 | return true; | 765 | return true; |
766 | } | 766 | } |
767 | 767 | ||
768 | bool Bu::String::operator!=(const char *pData ) const | 768 | bool Bu::String::operator!=(const char *pData ) const |
769 | { | 769 | { |
770 | return !(*this == pData); | 770 | return !(*this == pData); |
771 | } | 771 | } |
772 | 772 | ||
773 | bool Bu::String::operator!=(const String &pData ) const | 773 | bool Bu::String::operator!=(const String &pData ) const |
774 | { | 774 | { |
775 | return !(*this == pData); | 775 | return !(*this == pData); |
776 | } | 776 | } |
777 | 777 | ||
778 | bool Bu::String::operator<(const String &pData ) const | 778 | bool Bu::String::operator<(const String &pData ) const |
779 | { | 779 | { |
780 | flatten(); | 780 | flatten(); |
781 | pData.flatten(); | 781 | pData.flatten(); |
782 | 782 | ||
783 | const char *a = core->pFirst->pData; | 783 | const char *a = core->pFirst->pData; |
784 | char *b = pData.core->pFirst->pData; | 784 | char *b = pData.core->pFirst->pData; |
785 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 785 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
786 | { | 786 | { |
787 | if( *a != *b ) | 787 | if( *a != *b ) |
788 | return *a < *b; | 788 | return *a < *b; |
789 | } | 789 | } |
790 | 790 | ||
791 | return false; | 791 | return false; |
792 | } | 792 | } |
793 | 793 | ||
794 | bool Bu::String::operator<=(const String &pData ) const | 794 | bool Bu::String::operator<=(const String &pData ) const |
795 | { | 795 | { |
796 | flatten(); | 796 | flatten(); |
797 | pData.flatten(); | 797 | pData.flatten(); |
798 | 798 | ||
799 | const char *a = core->pFirst->pData; | 799 | const char *a = core->pFirst->pData; |
800 | char *b = pData.core->pFirst->pData; | 800 | char *b = pData.core->pFirst->pData; |
801 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 801 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
802 | { | 802 | { |
803 | if( *a != *b ) | 803 | if( *a != *b ) |
804 | return *a < *b; | 804 | return *a < *b; |
805 | } | 805 | } |
806 | 806 | ||
807 | return true; | 807 | return true; |
808 | } | 808 | } |
809 | 809 | ||
810 | bool Bu::String::operator>(const String &pData ) const | 810 | bool Bu::String::operator>(const String &pData ) const |
811 | { | 811 | { |
812 | flatten(); | 812 | flatten(); |
813 | pData.flatten(); | 813 | pData.flatten(); |
814 | 814 | ||
815 | const char *a = core->pFirst->pData; | 815 | const char *a = core->pFirst->pData; |
816 | char *b = pData.core->pFirst->pData; | 816 | char *b = pData.core->pFirst->pData; |
817 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 817 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
818 | { | 818 | { |
819 | if( *a != *b ) | 819 | if( *a != *b ) |
820 | return *a > *b; | 820 | return *a > *b; |
821 | } | 821 | } |
822 | 822 | ||
823 | return false; | 823 | return false; |
824 | } | 824 | } |
825 | 825 | ||
826 | bool Bu::String::operator>=(const String &pData ) const | 826 | bool Bu::String::operator>=(const String &pData ) const |
827 | { | 827 | { |
828 | flatten(); | 828 | flatten(); |
829 | pData.flatten(); | 829 | pData.flatten(); |
830 | 830 | ||
831 | const char *a = core->pFirst->pData; | 831 | const char *a = core->pFirst->pData; |
832 | char *b = pData.core->pFirst->pData; | 832 | char *b = pData.core->pFirst->pData; |
833 | for( long j = 0; j < core->nLength; j++, a++, b++ ) | 833 | for( long j = 0; j < core->nLength; j++, a++, b++ ) |
834 | { | 834 | { |
835 | if( *a != *b ) | 835 | if( *a != *b ) |
836 | return *a > *b; | 836 | return *a > *b; |
837 | } | 837 | } |
838 | 838 | ||
839 | return true; | 839 | return true; |
840 | } | 840 | } |
841 | 841 | ||
842 | char &Bu::String::operator[]( long nIndex ) | 842 | char &Bu::String::operator[]( long nIndex ) |
843 | { | 843 | { |
844 | if( nIndex < 0 || nIndex >= core->nLength ) | 844 | if( nIndex < 0 || nIndex >= core->nLength ) |
845 | throw Bu::ExceptionBase("Index out of range."); | 845 | throw Bu::ExceptionBase("Index out of range."); |
846 | flatten(); | 846 | flatten(); |
847 | _hardCopy(); | 847 | _hardCopy(); |
848 | 848 | ||
849 | return core->pFirst->pData[nIndex]; | 849 | return core->pFirst->pData[nIndex]; |
850 | } | 850 | } |
851 | 851 | ||
852 | const char &Bu::String::operator[]( long nIndex ) const | 852 | const char &Bu::String::operator[]( long nIndex ) const |
853 | { | 853 | { |
854 | if( nIndex < 0 || nIndex >= core->nLength ) | 854 | if( nIndex < 0 || nIndex >= core->nLength ) |
855 | throw Bu::ExceptionBase("Index out of range."); | 855 | throw Bu::ExceptionBase("Index out of range."); |
856 | flatten(); | 856 | flatten(); |
857 | 857 | ||
858 | return core->pFirst->pData[nIndex]; | 858 | return core->pFirst->pData[nIndex]; |
859 | } | 859 | } |
860 | 860 | ||
861 | bool Bu::String::isSet() const | 861 | bool Bu::String::isSet() const |
862 | { | 862 | { |
863 | return (core->pFirst != NULL); | 863 | return (core->pFirst != NULL); |
864 | } | 864 | } |
865 | 865 | ||
866 | bool Bu::String::compareSub( const char *pData, long nIndex, long nLen ) const | 866 | bool Bu::String::compareSub( const char *pData, long nIndex, long nLen ) const |
867 | { | 867 | { |
868 | if( core->pFirst == NULL || core->nLength == 0 ) { | 868 | if( core->pFirst == NULL || core->nLength == 0 ) { |
869 | if( pData == NULL ) | 869 | if( pData == NULL ) |
870 | return true; | 870 | return true; |
871 | if( nLen == 0 ) | 871 | if( nLen == 0 ) |
872 | return true; | 872 | return true; |
873 | if( pData[0] == (char)0 ) | 873 | if( pData[0] == (char)0 ) |
874 | return true; | 874 | return true; |
875 | return false; | 875 | return false; |
876 | } | 876 | } |
877 | if( nIndex+nLen > core->nLength ) | 877 | if( nIndex+nLen > core->nLength ) |
878 | return false; | 878 | return false; |
879 | 879 | ||
880 | flatten(); | 880 | flatten(); |
881 | core->pFirst->pData[core->nLength] = (char)0; | 881 | core->pFirst->pData[core->nLength] = (char)0; |
882 | const char *a = pData; | 882 | const char *a = pData; |
883 | char *b = core->pFirst->pData+nIndex; | 883 | char *b = core->pFirst->pData+nIndex; |
884 | for( long j = 0; j < nLen; j++, a++, b++ ) | 884 | for( long j = 0; j < nLen; j++, a++, b++ ) |
885 | { | 885 | { |
886 | if( *a != *b ) | 886 | if( *a != *b ) |
887 | return false; | 887 | return false; |
888 | if( *a == (char)0 && j < core->nLength ) | 888 | if( *a == (char)0 && j < core->nLength ) |
889 | return false; | 889 | return false; |
890 | } | 890 | } |
891 | 891 | ||
892 | return true; | 892 | return true; |
893 | } | 893 | } |
894 | 894 | ||
895 | bool Bu::String::compareSub( const String &rData, long nIndex, long nLen ) const | 895 | bool Bu::String::compareSub( const String &rData, long nIndex, long nLen ) const |
896 | { | 896 | { |
897 | if( core->pFirst == NULL || core->nLength == 0 || rData.core->pFirst == NULL || rData.core->nLength == 0 ) | 897 | if( core->pFirst == NULL || core->nLength == 0 || rData.core->pFirst == NULL || rData.core->nLength == 0 ) |
898 | return false; | 898 | return false; |
899 | if( nLen < 0 ) | 899 | if( nLen < 0 ) |
900 | nLen = rData.core->nLength; | 900 | nLen = rData.core->nLength; |
901 | if( nIndex+nLen > core->nLength ) | 901 | if( nIndex+nLen > core->nLength ) |
902 | return false; | 902 | return false; |
903 | 903 | ||
904 | flatten(); | 904 | flatten(); |
905 | rData.flatten(); | 905 | rData.flatten(); |
906 | const char *a = rData.core->pFirst->pData; | 906 | const char *a = rData.core->pFirst->pData; |
907 | char *b = core->pFirst->pData + nIndex; | 907 | char *b = core->pFirst->pData + nIndex; |
908 | for( long j = 0; j < nLen; j++, a++, b++ ) | 908 | for( long j = 0; j < nLen; j++, a++, b++ ) |
909 | { | 909 | { |
910 | if( *a != *b ) | 910 | if( *a != *b ) |
911 | return false; | 911 | return false; |
912 | } | 912 | } |
913 | 913 | ||
914 | return true; | 914 | return true; |
915 | } | 915 | } |
916 | 916 | ||
917 | bool Bu::String::isWS( long nIndex ) const | 917 | bool Bu::String::isWS( long nIndex ) const |
918 | { | 918 | { |
919 | flatten(); | 919 | flatten(); |
920 | 920 | ||
921 | return core->pFirst->pData[nIndex]==' ' || core->pFirst->pData[nIndex]=='\t' | 921 | return core->pFirst->pData[nIndex]==' ' || core->pFirst->pData[nIndex]=='\t' |
922 | || core->pFirst->pData[nIndex]=='\r' || core->pFirst->pData[nIndex]=='\n'; | 922 | || core->pFirst->pData[nIndex]=='\r' || core->pFirst->pData[nIndex]=='\n'; |
923 | } | 923 | } |
924 | 924 | ||
925 | bool Bu::String::isAlpha( long nIndex ) const | 925 | bool Bu::String::isAlpha( long nIndex ) const |
926 | { | 926 | { |
927 | flatten(); | 927 | flatten(); |
928 | 928 | ||
929 | return (core->pFirst->pData[nIndex] >= 'a' && core->pFirst->pData[nIndex] <= 'z') | 929 | return (core->pFirst->pData[nIndex] >= 'a' && core->pFirst->pData[nIndex] <= 'z') |
930 | || (core->pFirst->pData[nIndex] >= 'A' && core->pFirst->pData[nIndex] <= 'Z'); | 930 | || (core->pFirst->pData[nIndex] >= 'A' && core->pFirst->pData[nIndex] <= 'Z'); |
931 | } | 931 | } |
932 | 932 | ||
933 | Bu::String Bu::String::toLower() const | 933 | Bu::String Bu::String::toLower() const |
934 | { | 934 | { |
935 | Bu::String sRet = *this; | 935 | Bu::String sRet = *this; |
936 | 936 | ||
937 | sRet.flatten(); | 937 | sRet.flatten(); |
938 | sRet._hardCopy(); | 938 | sRet._hardCopy(); |
939 | 939 | ||
940 | for( long j = 0; j < sRet.core->nLength; j++ ) | 940 | for( long j = 0; j < sRet.core->nLength; j++ ) |
941 | { | 941 | { |
942 | if( sRet.core->pFirst->pData[j] >= 'A' && | 942 | if( sRet.core->pFirst->pData[j] >= 'A' && |
943 | sRet.core->pFirst->pData[j] <= 'Z' ) | 943 | sRet.core->pFirst->pData[j] <= 'Z' ) |
944 | sRet.core->pFirst->pData[j] -= 'A'-'a'; | 944 | sRet.core->pFirst->pData[j] -= 'A'-'a'; |
945 | } | 945 | } |
946 | 946 | ||
947 | return sRet; | 947 | return sRet; |
948 | } | 948 | } |
949 | 949 | ||
950 | Bu::String Bu::String::toUpper() const | 950 | Bu::String Bu::String::toUpper() const |
951 | { | 951 | { |
952 | Bu::String sRet = *this; | 952 | Bu::String sRet = *this; |
953 | 953 | ||
954 | sRet.flatten(); | 954 | sRet.flatten(); |
955 | sRet._hardCopy(); | 955 | sRet._hardCopy(); |
956 | 956 | ||
957 | for( long j = 0; j < sRet.core->nLength; j++ ) | 957 | for( long j = 0; j < sRet.core->nLength; j++ ) |
958 | { | 958 | { |
959 | if( sRet.core->pFirst->pData[j] >= 'a' && | 959 | if( sRet.core->pFirst->pData[j] >= 'a' && |
960 | sRet.core->pFirst->pData[j] <= 'z' ) | 960 | sRet.core->pFirst->pData[j] <= 'z' ) |
961 | sRet.core->pFirst->pData[j] += 'A'-'a'; | 961 | sRet.core->pFirst->pData[j] += 'A'-'a'; |
962 | } | 962 | } |
963 | 963 | ||
964 | return sRet; | 964 | return sRet; |
965 | } | 965 | } |
966 | 966 | ||
967 | Bu::String::const_iterator Bu::String::find( const char cChar, | 967 | Bu::String::const_iterator Bu::String::find( const char cChar, |
968 | Bu::String::const_iterator iStart ) const | 968 | Bu::String::const_iterator iStart ) const |
969 | { | 969 | { |
970 | if( !iStart ) iStart = begin(); | 970 | if( !iStart ) iStart = begin(); |
971 | for( ; iStart; iStart++ ) | 971 | for( ; iStart; iStart++ ) |
972 | { | 972 | { |
973 | if( cChar == *iStart ) | 973 | if( cChar == *iStart ) |
974 | return iStart; | 974 | return iStart; |
975 | } | 975 | } |
976 | return end(); | 976 | return end(); |
977 | } | 977 | } |
978 | 978 | ||
979 | Bu::String::const_iterator Bu::String::find( const char *sText, int nLen, | 979 | Bu::String::const_iterator Bu::String::find( const char *sText, int nLen, |
980 | Bu::String::const_iterator iStart ) const | 980 | Bu::String::const_iterator iStart ) const |
981 | { | 981 | { |
982 | if( !iStart ) iStart = begin(); | 982 | if( !iStart ) iStart = begin(); |
983 | for( ; iStart; iStart++ ) | 983 | for( ; iStart; iStart++ ) |
984 | { | 984 | { |
985 | if( iStart.compare( sText, nLen ) ) | 985 | if( iStart.compare( sText, nLen ) ) |
986 | return iStart; | 986 | return iStart; |
987 | } | 987 | } |
988 | return end(); | 988 | return end(); |
989 | } | 989 | } |
990 | 990 | ||
991 | Bu::String::const_iterator Bu::String::find( const String &rStr, | 991 | Bu::String::const_iterator Bu::String::find( const String &rStr, |
992 | Bu::String::const_iterator iStart ) const | 992 | Bu::String::const_iterator iStart ) const |
993 | { | 993 | { |
994 | if( !iStart ) iStart = begin(); | 994 | if( !iStart ) iStart = begin(); |
995 | for( ; iStart; iStart++ ) | 995 | for( ; iStart; iStart++ ) |
996 | { | 996 | { |
997 | if( iStart.compare( rStr ) ) | 997 | if( iStart.compare( rStr ) ) |
998 | return iStart; | 998 | return iStart; |
999 | } | 999 | } |
1000 | return end(); | 1000 | return end(); |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | Bu::String::const_iterator Bu::String::find( const String &rStr, int nLen, | 1003 | Bu::String::const_iterator Bu::String::find( const String &rStr, int nLen, |
1004 | Bu::String::const_iterator iStart ) const | 1004 | Bu::String::const_iterator iStart ) const |
1005 | { | 1005 | { |
1006 | if( !iStart ) iStart = begin(); | 1006 | if( !iStart ) iStart = begin(); |
1007 | for( ; iStart; iStart++ ) | 1007 | for( ; iStart; iStart++ ) |
1008 | { | 1008 | { |
1009 | if( iStart.compare( rStr, nLen ) ) | 1009 | if( iStart.compare( rStr, nLen ) ) |
1010 | return iStart; | 1010 | return iStart; |
1011 | } | 1011 | } |
1012 | return end(); | 1012 | return end(); |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | Bu::String::iterator Bu::String::find( const char cChar, | 1015 | Bu::String::iterator Bu::String::find( const char cChar, |
1016 | Bu::String::const_iterator iStart ) | 1016 | Bu::String::const_iterator iStart ) |
1017 | { | 1017 | { |
1018 | if( !iStart ) iStart = begin(); | 1018 | if( !iStart ) iStart = begin(); |
1019 | for( ; iStart; iStart++ ) | 1019 | for( ; iStart; iStart++ ) |
1020 | { | 1020 | { |
1021 | if( cChar == *iStart ) | 1021 | if( cChar == *iStart ) |
1022 | return iterator( iStart.pChunk, iStart.iPos ); | 1022 | return iterator( iStart.pChunk, iStart.iPos ); |
1023 | } | 1023 | } |
1024 | return end(); | 1024 | return end(); |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | Bu::String::iterator Bu::String::find( const char *sText, int nLen, | 1027 | Bu::String::iterator Bu::String::find( const char *sText, int nLen, |
1028 | Bu::String::const_iterator iStart ) | 1028 | Bu::String::const_iterator iStart ) |
1029 | { | 1029 | { |
1030 | if( !iStart ) iStart = begin(); | 1030 | if( !iStart ) iStart = begin(); |
1031 | for( ; iStart; iStart++ ) | 1031 | for( ; iStart; iStart++ ) |
1032 | { | 1032 | { |
1033 | if( iStart.compare( sText, nLen ) ) | 1033 | if( iStart.compare( sText, nLen ) ) |
1034 | return iterator( iStart.pChunk, iStart.iPos ); | 1034 | return iterator( iStart.pChunk, iStart.iPos ); |
1035 | } | 1035 | } |
1036 | return end(); | 1036 | return end(); |
1037 | } | 1037 | } |
1038 | 1038 | ||
1039 | Bu::String::iterator Bu::String::find( const String &rStr, | 1039 | Bu::String::iterator Bu::String::find( const String &rStr, |
1040 | Bu::String::const_iterator iStart ) | 1040 | Bu::String::const_iterator iStart ) |
1041 | { | 1041 | { |
1042 | if( !iStart ) iStart = begin(); | 1042 | if( !iStart ) iStart = begin(); |
1043 | for( ; iStart; iStart++ ) | 1043 | for( ; iStart; iStart++ ) |
1044 | { | 1044 | { |
1045 | if( iStart.compare( rStr ) ) | 1045 | if( iStart.compare( rStr ) ) |
1046 | return iterator( iStart.pChunk, iStart.iPos ); | 1046 | return iterator( iStart.pChunk, iStart.iPos ); |
1047 | } | 1047 | } |
1048 | return end(); | 1048 | return end(); |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | Bu::String::iterator Bu::String::find( const String &rStr, int nLen, | 1051 | Bu::String::iterator Bu::String::find( const String &rStr, int nLen, |
1052 | Bu::String::const_iterator iStart ) | 1052 | Bu::String::const_iterator iStart ) |
1053 | { | 1053 | { |
1054 | if( !iStart ) iStart = begin(); | 1054 | if( !iStart ) iStart = begin(); |
1055 | for( ; iStart; iStart++ ) | 1055 | for( ; iStart; iStart++ ) |
1056 | { | 1056 | { |
1057 | if( iStart.compare( rStr, nLen ) ) | 1057 | if( iStart.compare( rStr, nLen ) ) |
1058 | return iterator( iStart.pChunk, iStart.iPos ); | 1058 | return iterator( iStart.pChunk, iStart.iPos ); |
1059 | } | 1059 | } |
1060 | return end(); | 1060 | return end(); |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | long Bu::String::findIdx( const char cChar, long iStart ) const | 1063 | long Bu::String::findIdx( const char cChar, long iStart ) const |
1064 | { | 1064 | { |
1065 | flatten(); | 1065 | flatten(); |
1066 | for( long j = iStart; j < core->pFirst->nLength; j++ ) | 1066 | for( long j = iStart; j < core->pFirst->nLength; j++ ) |
1067 | { | 1067 | { |
1068 | if( core->pFirst->pData[j] == cChar ) | 1068 | if( core->pFirst->pData[j] == cChar ) |
1069 | return j; | 1069 | return j; |
1070 | } | 1070 | } |
1071 | return -1; | 1071 | return -1; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | long Bu::String::findIdx( const char *sText, long iStart ) const | 1074 | long Bu::String::findIdx( const char *sText, long iStart ) const |
1075 | { | 1075 | { |
1076 | long nTLen = strlen( sText ); | 1076 | long nTLen = strlen( sText ); |
1077 | flatten(); | 1077 | flatten(); |
1078 | for( long j = iStart; j < core->pFirst->nLength-nTLen; j++ ) | 1078 | for( long j = iStart; j < core->pFirst->nLength-nTLen; j++ ) |
1079 | { | 1079 | { |
1080 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) | 1080 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) |
1081 | return j; | 1081 | return j; |
1082 | } | 1082 | } |
1083 | return -1; | 1083 | return -1; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | long Bu::String::rfindIdx( const char *sText ) const | 1086 | long Bu::String::rfindIdx( const char *sText ) const |
1087 | { | 1087 | { |
1088 | long nTLen = strlen( sText ); | 1088 | long nTLen = strlen( sText ); |
1089 | flatten(); | 1089 | flatten(); |
1090 | for( long j = core->pFirst->nLength-nTLen-1; j >= 0; j-- ) | 1090 | for( long j = core->pFirst->nLength-nTLen-1; j >= 0; j-- ) |
1091 | { | 1091 | { |
1092 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) | 1092 | if( !strncmp( sText, core->pFirst->pData+j, nTLen ) ) |
1093 | return j; | 1093 | return j; |
1094 | } | 1094 | } |
1095 | return -1; | 1095 | return -1; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | void Bu::String::trimFront( long nAmnt ) | 1098 | void Bu::String::trimFront( long nAmnt ) |
1099 | { | 1099 | { |
1100 | long nNewLen = core->nLength - nAmnt; | 1100 | long nNewLen = core->nLength - nAmnt; |
1101 | flatten(); | 1101 | flatten(); |
1102 | Chunk *pNew = core->newChunk( nNewLen ); | 1102 | Chunk *pNew = core->newChunk( nNewLen ); |
1103 | memcpy( pNew->pData, core->pFirst->pData+nAmnt, nNewLen ); | 1103 | memcpy( pNew->pData, core->pFirst->pData+nAmnt, nNewLen ); |
1104 | _hardCopy(); | 1104 | _hardCopy(); |
1105 | core->clear(); | 1105 | core->clear(); |
1106 | core->appendChunk( pNew ); | 1106 | core->appendChunk( pNew ); |
1107 | } | 1107 | } |
1108 | /* | 1108 | /* |
1109 | void Bu::String::trimBack( char c ) | 1109 | void Bu::String::trimBack( char c ) |
1110 | { | 1110 | { |
1111 | if( core->pFirst == NULL || core->nLength == 0 ) | 1111 | if( core->pFirst == NULL || core->nLength == 0 ) |
1112 | return; | 1112 | return; |
1113 | flatten(); | 1113 | flatten(); |
1114 | for( ; core->pFirst->nLength > 0 && | 1114 | for( ; core->pFirst->nLength > 0 && |
1115 | core->pFirst->pData[core->pFirst->nLength-1] == c; | 1115 | core->pFirst->pData[core->pFirst->nLength-1] == c; |
1116 | core->pFirst->nLength--, core->nLength-- ) { } | 1116 | core->pFirst->nLength--, core->nLength-- ) { } |
1117 | } | 1117 | } |
1118 | */ | 1118 | */ |
1119 | void Bu::String::trimBack( long iAmnt ) | 1119 | void Bu::String::trimBack( long iAmnt ) |
1120 | { | 1120 | { |
1121 | if( iAmnt < 0 ) | 1121 | if( iAmnt < 0 ) |
1122 | return; | 1122 | return; |
1123 | if( core->nLength - iAmnt < 0 ) | 1123 | if( core->nLength - iAmnt < 0 ) |
1124 | { | 1124 | { |
1125 | clear(); | 1125 | clear(); |
1126 | return; | 1126 | return; |
1127 | } | 1127 | } |
1128 | if( core->pFirst == NULL || core->nLength == 0 ) | 1128 | if( core->pFirst == NULL || core->nLength == 0 ) |
1129 | return; | 1129 | return; |
1130 | 1130 | ||
1131 | flatten(); | 1131 | flatten(); |
1132 | core->pFirst->nLength -= iAmnt; | 1132 | core->pFirst->nLength -= iAmnt; |
1133 | core->nLength -= iAmnt; | 1133 | core->nLength -= iAmnt; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | Bu::String Bu::String::trimWhitespace() const | 1136 | Bu::String Bu::String::trimWhitespace() const |
1137 | { | 1137 | { |
1138 | if( core->nLength == 0 ) | 1138 | if( core->nLength == 0 ) |
1139 | return ""; | 1139 | return ""; |
1140 | const_iterator i = begin(); | 1140 | const_iterator i = begin(); |
1141 | for( ; i && (*i == ' ' || *i == '\t' || *i == '\n' || *i == '\r'); i++ ) { } | 1141 | for( ; i && (*i == ' ' || *i == '\t' || *i == '\n' || *i == '\r'); i++ ) { } |
1142 | if( !i ) | 1142 | if( !i ) |
1143 | return ""; | 1143 | return ""; |
1144 | 1144 | ||
1145 | const_iterator e = i; | 1145 | const_iterator e = i; |
1146 | for( ; e; e++ ) | 1146 | for( ; e; e++ ) |
1147 | { | 1147 | { |
1148 | if( *e == ' ' || *e == '\t' || *e == '\n' || *e == '\r' ) | 1148 | if( *e == ' ' || *e == '\t' || *e == '\n' || *e == '\r' ) |
1149 | { | 1149 | { |
1150 | const_iterator t = e; | 1150 | const_iterator t = e; |
1151 | for( ; t && (*t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'); t++ ) { } | 1151 | for( ; t && (*t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'); t++ ) { } |
1152 | if( t ) | 1152 | if( t ) |
1153 | { | 1153 | { |
1154 | e = t; | 1154 | e = t; |
1155 | } | 1155 | } |
1156 | else | 1156 | else |
1157 | { | 1157 | { |
1158 | break; | 1158 | break; |
1159 | } | 1159 | } |
1160 | } | 1160 | } |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | return Bu::String( i, e ); | 1163 | return Bu::String( i, e ); |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | Bu::String::iterator Bu::String::begin() | 1166 | Bu::String::iterator Bu::String::begin() |
1167 | { | 1167 | { |
1168 | if( core->nLength == 0 ) | 1168 | if( core->nLength == 0 ) |
1169 | return iterator( NULL, 0 ); | 1169 | return iterator( NULL, 0 ); |
1170 | return iterator( core->pFirst, 0 ); | 1170 | return iterator( core->pFirst, 0 ); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | Bu::String::const_iterator Bu::String::begin() const | 1173 | Bu::String::const_iterator Bu::String::begin() const |
1174 | { | 1174 | { |
1175 | if( core->nLength == 0 ) | 1175 | if( core->nLength == 0 ) |
1176 | return const_iterator( NULL, 0 ); | 1176 | return const_iterator( NULL, 0 ); |
1177 | return iterator( core->pFirst, 0 ); | 1177 | return iterator( core->pFirst, 0 ); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | Bu::String::iterator Bu::String::end() | 1180 | Bu::String::iterator Bu::String::end() |
1181 | { | 1181 | { |
1182 | return iterator( NULL, 0 ); | 1182 | return iterator( NULL, 0 ); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | Bu::String::const_iterator Bu::String::end() const | 1185 | Bu::String::const_iterator Bu::String::end() const |
1186 | { | 1186 | { |
1187 | return const_iterator( NULL, 0 ); | 1187 | return const_iterator( NULL, 0 ); |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | bool Bu::String::isEmpty() const | 1190 | bool Bu::String::isEmpty() const |
1191 | { | 1191 | { |
1192 | if( core->nLength == 0 ) | 1192 | if( core->nLength == 0 ) |
1193 | return true; | 1193 | return true; |
1194 | return false; | 1194 | return false; |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | void Bu::String::flatten() const | 1197 | void Bu::String::flatten() const |
1198 | { | 1198 | { |
1199 | if( isFlat() ) | 1199 | if( isFlat() ) |
1200 | return; | 1200 | return; |
1201 | 1201 | ||
1202 | if( core->pFirst == NULL || core->nLength == 0 ) | 1202 | if( core->pFirst == NULL || core->nLength == 0 ) |
1203 | return; | 1203 | return; |
1204 | 1204 | ||
1205 | Chunk *pNew = core->newChunk( core->nLength ); | 1205 | Chunk *pNew = core->newChunk( core->nLength ); |
1206 | char *pos = pNew->pData; | 1206 | char *pos = pNew->pData; |
1207 | Chunk *i = core->pFirst; | 1207 | Chunk *i = core->pFirst; |
1208 | for(;;) | 1208 | for(;;) |
1209 | { | 1209 | { |
1210 | memcpy( pos, i->pData, i->nLength ); | 1210 | memcpy( pos, i->pData, i->nLength ); |
1211 | pos += i->nLength; | 1211 | pos += i->nLength; |
1212 | i = i->pNext; | 1212 | i = i->pNext; |
1213 | if( i == NULL ) | 1213 | if( i == NULL ) |
1214 | break; | 1214 | break; |
1215 | } | 1215 | } |
1216 | core->clear(); | 1216 | core->clear(); |
1217 | 1217 | ||
1218 | core->pLast = core->pFirst = pNew; | 1218 | core->pLast = core->pFirst = pNew; |
1219 | core->nLength = pNew->nLength; | 1219 | core->nLength = pNew->nLength; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | bool Bu::String::isFlat() const | 1222 | bool Bu::String::isFlat() const |
1223 | { | 1223 | { |
1224 | return (core->pFirst == core->pLast); | 1224 | return (core->pFirst == core->pLast); |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | // | 1227 | // |
@@ -1229,98 +1229,98 @@ bool Bu::String::isFlat() const | |||
1229 | // | 1229 | // |
1230 | 1230 | ||
1231 | Bu::String::FormatProxy::FormatProxy( const String &rFmt, | 1231 | Bu::String::FormatProxy::FormatProxy( const String &rFmt, |
1232 | String::FormatProxyEndAction *pAct ) : | 1232 | String::FormatProxyEndAction *pAct ) : |
1233 | rFmt( rFmt ), | 1233 | rFmt( rFmt ), |
1234 | pAct( pAct ), | 1234 | pAct( pAct ), |
1235 | bOpen( true ) | 1235 | bOpen( true ) |
1236 | { | 1236 | { |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | Bu::String::FormatProxy::~FormatProxy() | 1239 | Bu::String::FormatProxy::~FormatProxy() |
1240 | { | 1240 | { |
1241 | if( pAct && bOpen ) | 1241 | if( pAct && bOpen ) |
1242 | end(); | 1242 | end(); |
1243 | 1243 | ||
1244 | delete pAct; | 1244 | delete pAct; |
1245 | } | 1245 | } |
1246 | 1246 | ||
1247 | Bu::String Bu::String::FormatProxy::end() const | 1247 | Bu::String Bu::String::FormatProxy::end() const |
1248 | { | 1248 | { |
1249 | int iCount = lArgs.getSize(); | 1249 | int iCount = lArgs.getSize(); |
1250 | ArgList::const_iterator *aArg = | 1250 | ArgList::const_iterator *aArg = |
1251 | new ArgList::const_iterator[iCount]; | 1251 | new ArgList::const_iterator[iCount]; |
1252 | { | 1252 | { |
1253 | int j = 0; | 1253 | int j = 0; |
1254 | for( ArgList::const_iterator i = lArgs.begin(); | 1254 | for( ArgList::const_iterator i = lArgs.begin(); |
1255 | i; i++, j++ ) | 1255 | i; i++, j++ ) |
1256 | { | 1256 | { |
1257 | aArg[j] = i; | 1257 | aArg[j] = i; |
1258 | } | 1258 | } |
1259 | } | 1259 | } |
1260 | Bu::MemBuf mbOut; | 1260 | Bu::MemBuf mbOut; |
1261 | Bu::Formatter f( mbOut ); | 1261 | Bu::Formatter f( mbOut ); |
1262 | for( String::const_iterator s = rFmt.begin(); s; ) | 1262 | for( String::const_iterator s = rFmt.begin(); s; ) |
1263 | { | 1263 | { |
1264 | if( *s == '%' ) | 1264 | if( *s == '%' ) |
1265 | { | 1265 | { |
1266 | s++; | 1266 | s++; |
1267 | if( *s == '%' ) | 1267 | if( *s == '%' ) |
1268 | f << *s; | 1268 | f << *s; |
1269 | else | 1269 | else |
1270 | { | 1270 | { |
1271 | String sNum; | 1271 | String sNum; |
1272 | if( *s == '{' ) | 1272 | if( *s == '{' ) |
1273 | { | 1273 | { |
1274 | s++; | 1274 | s++; |
1275 | while( s && *s >= '0' && *s <= '9' ) | 1275 | while( s && *s >= '0' && *s <= '9' ) |
1276 | { | 1276 | { |
1277 | sNum += *s; | 1277 | sNum += *s; |
1278 | s++; | 1278 | s++; |
1279 | } | 1279 | } |
1280 | if( !s || *s != '}' ) | 1280 | if( !s || *s != '}' ) |
1281 | { | 1281 | { |
1282 | delete[] aArg; | 1282 | delete[] aArg; |
1283 | throw Bu::ExceptionBase( | 1283 | throw Bu::ExceptionBase( |
1284 | "Argument started with a '{' but terminated " | 1284 | "Argument started with a '{' but terminated " |
1285 | "with a '%c' instead of '}'.", *s ); | 1285 | "with a '%c' instead of '}'.", *s ); |
1286 | } | 1286 | } |
1287 | s++; | 1287 | s++; |
1288 | } | 1288 | } |
1289 | else | 1289 | else |
1290 | { | 1290 | { |
1291 | while( s && *s >= '0' && *s <= '9' ) | 1291 | while( s && *s >= '0' && *s <= '9' ) |
1292 | { | 1292 | { |
1293 | sNum += *s; | 1293 | sNum += *s; |
1294 | s++; | 1294 | s++; |
1295 | } | 1295 | } |
1296 | } | 1296 | } |
1297 | int iIndex = strtol( sNum.getStr(), 0, 10 )-1; | 1297 | int iIndex = strtol( sNum.getStr(), 0, 10 )-1; |
1298 | if( iIndex < 0 || iIndex >= iCount ) | 1298 | if( iIndex < 0 || iIndex >= iCount ) |
1299 | { | 1299 | { |
1300 | delete[] aArg; | 1300 | delete[] aArg; |
1301 | throw Bu::ExceptionBase( | 1301 | throw Bu::ExceptionBase( |
1302 | "Argument index %d is outside of " | 1302 | "Argument index %d is outside of " |
1303 | "valid range (1-%d).", iIndex+1, iCount | 1303 | "valid range (1-%d).", iIndex+1, iCount |
1304 | ); | 1304 | ); |
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | f << (*aArg[iIndex]).format << (*aArg[iIndex]).value; | 1307 | f << (*aArg[iIndex]).format << (*aArg[iIndex]).value; |
1308 | continue; | 1308 | continue; |
1309 | } | 1309 | } |
1310 | } | 1310 | } |
1311 | else | 1311 | else |
1312 | { | 1312 | { |
1313 | f << *s; | 1313 | f << *s; |
1314 | } | 1314 | } |
1315 | s++; | 1315 | s++; |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | bOpen = false; | 1318 | bOpen = false; |
1319 | delete[] aArg; | 1319 | delete[] aArg; |
1320 | 1320 | ||
1321 | if( pAct ) | 1321 | if( pAct ) |
1322 | (*pAct)( mbOut.getString() ); | 1322 | (*pAct)( mbOut.getString() ); |
1323 | return mbOut.getString(); | 1323 | return mbOut.getString(); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | 1326 | ||
@@ -1371,131 +1371,131 @@ Bu::String Bu::String::FormatProxy::end() const | |||
1371 | 1371 | ||
1372 | template<> uint32_t Bu::__calcHashCode<Bu::String>( const Bu::String &k ) | 1372 | template<> uint32_t Bu::__calcHashCode<Bu::String>( const Bu::String &k ) |
1373 | { | 1373 | { |
1374 | long j, sz = k.getSize(); | 1374 | long j, sz = k.getSize(); |
1375 | const char *s = k.getStr(); | 1375 | const char *s = k.getStr(); |
1376 | 1376 | ||
1377 | long nPos = 0; | 1377 | long nPos = 0; |
1378 | for( j = 0; j < sz; j++, s++ ) | 1378 | for( j = 0; j < sz; j++, s++ ) |
1379 | { | 1379 | { |
1380 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 1380 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | return nPos; | 1383 | return nPos; |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | template<> bool Bu::__cmpHashKeys<Bu::String>( | 1386 | template<> bool Bu::__cmpHashKeys<Bu::String>( |
1387 | const Bu::String &a, const Bu::String &b ) | 1387 | const Bu::String &a, const Bu::String &b ) |
1388 | { | 1388 | { |
1389 | return a == b; | 1389 | return a == b; |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | template<> void Bu::__tracer_format<Bu::String>( const Bu::String &v ) | 1392 | template<> void Bu::__tracer_format<Bu::String>( const Bu::String &v ) |
1393 | { | 1393 | { |
1394 | printf("(%ld)\"%s\"", v.getSize(), v.getStr() ); | 1394 | printf("(%ld)\"%s\"", v.getSize(), v.getStr() ); |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | bool &Bu::operator<<( bool &dst, const Bu::String &sIn ) | 1397 | bool &Bu::operator<<( bool &dst, const Bu::String &sIn ) |
1398 | { | 1398 | { |
1399 | if( sIn == "true" || sIn == "yes" || sIn == "t" ) | 1399 | if( sIn == "true" || sIn == "yes" || sIn == "t" ) |
1400 | dst = true; | 1400 | dst = true; |
1401 | else | 1401 | else |
1402 | dst = false; | 1402 | dst = false; |
1403 | 1403 | ||
1404 | return dst; | 1404 | return dst; |
1405 | } | 1405 | } |
1406 | 1406 | ||
1407 | uint8_t &Bu::operator<<( uint8_t &dst, const Bu::String &sIn ) | 1407 | uint8_t &Bu::operator<<( uint8_t &dst, const Bu::String &sIn ) |
1408 | { | 1408 | { |
1409 | sscanf( sIn.getStr(), "%hhu", &dst ); | 1409 | sscanf( sIn.getStr(), "%hhu", &dst ); |
1410 | return dst; | 1410 | return dst; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | int8_t &Bu::operator<<( int8_t &dst, const Bu::String &sIn ) | 1413 | int8_t &Bu::operator<<( int8_t &dst, const Bu::String &sIn ) |
1414 | { | 1414 | { |
1415 | sscanf( sIn.getStr(), "%hhd", &dst ); | 1415 | sscanf( sIn.getStr(), "%hhd", &dst ); |
1416 | return dst; | 1416 | return dst; |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | char &Bu::operator<<( char &dst, const Bu::String &sIn ) | 1419 | char &Bu::operator<<( char &dst, const Bu::String &sIn ) |
1420 | { | 1420 | { |
1421 | sscanf( sIn.getStr(), "%hhd", &dst ); | 1421 | sscanf( sIn.getStr(), "%hhd", &dst ); |
1422 | return dst; | 1422 | return dst; |
1423 | } | 1423 | } |
1424 | 1424 | ||
1425 | uint16_t &Bu::operator<<( uint16_t &dst, const Bu::String &sIn ) | 1425 | uint16_t &Bu::operator<<( uint16_t &dst, const Bu::String &sIn ) |
1426 | { | 1426 | { |
1427 | sscanf( sIn.getStr(), "%hu", &dst ); | 1427 | sscanf( sIn.getStr(), "%hu", &dst ); |
1428 | return dst; | 1428 | return dst; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | int16_t &Bu::operator<<( int16_t &dst, const Bu::String &sIn ) | 1431 | int16_t &Bu::operator<<( int16_t &dst, const Bu::String &sIn ) |
1432 | { | 1432 | { |
1433 | sscanf( sIn.getStr(), "%hd", &dst ); | 1433 | sscanf( sIn.getStr(), "%hd", &dst ); |
1434 | return dst; | 1434 | return dst; |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | uint32_t &Bu::operator<<( uint32_t &dst, const Bu::String &sIn ) | 1437 | uint32_t &Bu::operator<<( uint32_t &dst, const Bu::String &sIn ) |
1438 | { | 1438 | { |
1439 | sscanf( sIn.getStr(), "%u", &dst ); | 1439 | sscanf( sIn.getStr(), "%u", &dst ); |
1440 | return dst; | 1440 | return dst; |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | int32_t &Bu::operator<<( int32_t &dst, const Bu::String &sIn ) | 1443 | int32_t &Bu::operator<<( int32_t &dst, const Bu::String &sIn ) |
1444 | { | 1444 | { |
1445 | sscanf( sIn.getStr(), "%d", &dst ); | 1445 | sscanf( sIn.getStr(), "%d", &dst ); |
1446 | return dst; | 1446 | return dst; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | uint64_t &Bu::operator<<( uint64_t &dst, const Bu::String &sIn ) | 1449 | uint64_t &Bu::operator<<( uint64_t &dst, const Bu::String &sIn ) |
1450 | { | 1450 | { |
1451 | sscanf( sIn.getStr(), "%llu", &dst ); | 1451 | sscanf( sIn.getStr(), "%llu", &dst ); |
1452 | return dst; | 1452 | return dst; |
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | int64_t &Bu::operator<<( int64_t &dst, const Bu::String &sIn ) | 1455 | int64_t &Bu::operator<<( int64_t &dst, const Bu::String &sIn ) |
1456 | { | 1456 | { |
1457 | sscanf( sIn.getStr(), "%lld", &dst ); | 1457 | sscanf( sIn.getStr(), "%lld", &dst ); |
1458 | return dst; | 1458 | return dst; |
1459 | } | 1459 | } |
1460 | 1460 | ||
1461 | float &Bu::operator<<( float &dst, const Bu::String &sIn ) | 1461 | float &Bu::operator<<( float &dst, const Bu::String &sIn ) |
1462 | { | 1462 | { |
1463 | sscanf( sIn.getStr(), "%f", &dst ); | 1463 | sscanf( sIn.getStr(), "%f", &dst ); |
1464 | return dst; | 1464 | return dst; |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | double &Bu::operator<<( double &dst, const Bu::String &sIn ) | 1467 | double &Bu::operator<<( double &dst, const Bu::String &sIn ) |
1468 | { | 1468 | { |
1469 | sscanf( sIn.getStr(), "%lf", &dst ); | 1469 | sscanf( sIn.getStr(), "%lf", &dst ); |
1470 | return dst; | 1470 | return dst; |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | long double &Bu::operator<<( long double &dst, const Bu::String &sIn ) | 1473 | long double &Bu::operator<<( long double &dst, const Bu::String &sIn ) |
1474 | { | 1474 | { |
1475 | sscanf( sIn.getStr(), "%Lf", &dst ); | 1475 | sscanf( sIn.getStr(), "%Lf", &dst ); |
1476 | return dst; | 1476 | return dst; |
1477 | } | 1477 | } |
1478 | 1478 | ||
1479 | Bu::String &Bu::operator<<( Bu::String &dst, const Bu::String &sIn ) | 1479 | Bu::String &Bu::operator<<( Bu::String &dst, const Bu::String &sIn ) |
1480 | { | 1480 | { |
1481 | dst = sIn; | 1481 | dst = sIn; |
1482 | return dst; | 1482 | return dst; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::String &s ) | 1485 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::String &s ) |
1486 | { | 1486 | { |
1487 | long n = s.getSize(); | 1487 | long n = s.getSize(); |
1488 | ar << n; | 1488 | ar << n; |
1489 | ar.write( s.getConstStr(), n ); | 1489 | ar.write( s.getConstStr(), n ); |
1490 | return ar; | 1490 | return ar; |
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::String &s ) | 1493 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::String &s ) |
1494 | { | 1494 | { |
1495 | long n; | 1495 | long n; |
1496 | ar >> n; | 1496 | ar >> n; |
1497 | s.setSize( n ); | 1497 | s.setSize( n ); |
1498 | ar.read( s.getStr(), n ); | 1498 | ar.read( s.getStr(), n ); |
1499 | return ar; | 1499 | return ar; |
1500 | } | 1500 | } |
1501 | 1501 | ||
diff --git a/src/stable/string.h b/src/stable/string.h index 197821d..3be5bb9 100644 --- a/src/stable/string.h +++ b/src/stable/string.h | |||
@@ -22,1055 +22,1055 @@ | |||
22 | 22 | ||
23 | namespace Bu | 23 | namespace Bu |
24 | { | 24 | { |
25 | class String; | 25 | class String; |
26 | class MemBuf; | 26 | class MemBuf; |
27 | 27 | ||
28 | /** @cond DEVEL */ | 28 | /** @cond DEVEL */ |
29 | class StringCore | 29 | class StringCore |
30 | { | 30 | { |
31 | friend class String; | 31 | friend class String; |
32 | friend class SharedCore<String, StringCore>; | 32 | friend class SharedCore<String, StringCore>; |
33 | private: | 33 | private: |
34 | struct Chunk | 34 | struct Chunk |
35 | { | 35 | { |
36 | long nLength; | 36 | long nLength; |
37 | char *pData; | 37 | char *pData; |
38 | Chunk *pNext; | 38 | Chunk *pNext; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | StringCore(); | 41 | StringCore(); |
42 | StringCore( const StringCore &rSrc ); | 42 | StringCore( const StringCore &rSrc ); |
43 | virtual ~StringCore(); | 43 | virtual ~StringCore(); |
44 | 44 | ||
45 | mutable long nLength; | 45 | mutable long nLength; |
46 | mutable Chunk *pFirst; | 46 | mutable Chunk *pFirst; |
47 | mutable Chunk *pLast; | 47 | mutable Chunk *pLast; |
48 | 48 | ||
49 | void clear() const; | 49 | void clear() const; |
50 | Chunk *newChunk() const; | 50 | Chunk *newChunk() const; |
51 | Chunk *newChunk( long nLen ) const; | 51 | Chunk *newChunk( long nLen ) const; |
52 | Chunk *copyChunk( Chunk *pSrc ) const; | 52 | Chunk *copyChunk( Chunk *pSrc ) const; |
53 | void appendChunk( Chunk *pNewChunk ); | 53 | void appendChunk( Chunk *pNewChunk ); |
54 | void prependChunk( Chunk *pNewChunk ); | 54 | void prependChunk( Chunk *pNewChunk ); |
55 | }; | 55 | }; |
56 | /** @endcond */ | 56 | /** @endcond */ |
57 | 57 | ||
58 | /** | 58 | /** |
59 | */ | 59 | */ |
60 | class String : public SharedCore<String, StringCore> | 60 | class String : public SharedCore<String, StringCore> |
61 | { | 61 | { |
62 | protected: | 62 | protected: |
63 | using SharedCore<String, StringCore >::core; | 63 | using SharedCore<String, StringCore >::core; |
64 | using SharedCore<String, StringCore >::_hardCopy; | 64 | using SharedCore<String, StringCore >::_hardCopy; |
65 | 65 | ||
66 | private: | 66 | private: |
67 | typedef StringCore::Chunk Chunk; | 67 | typedef StringCore::Chunk Chunk; |
68 | 68 | ||
69 | public: // Iterators | 69 | public: // Iterators |
70 | struct iterator; | 70 | struct iterator; |
71 | typedef struct const_iterator | 71 | typedef struct const_iterator |
72 | { | 72 | { |
73 | friend class String; | 73 | friend class String; |
74 | friend struct iterator; | 74 | friend struct iterator; |
75 | private: | 75 | private: |
76 | const_iterator( Chunk *pChunk, int iPos ) : | 76 | const_iterator( Chunk *pChunk, int iPos ) : |
77 | pChunk( pChunk ), | 77 | pChunk( pChunk ), |
78 | iPos( iPos ) | 78 | iPos( iPos ) |
79 | { | 79 | { |
80 | } | 80 | } |
81 | 81 | ||
82 | Chunk *pChunk; | 82 | Chunk *pChunk; |
83 | int iPos; | 83 | int iPos; |
84 | 84 | ||
85 | public: | 85 | public: |
86 | const_iterator( const const_iterator &i ) : | 86 | const_iterator( const const_iterator &i ) : |
87 | pChunk( i.pChunk ), | 87 | pChunk( i.pChunk ), |
88 | iPos( i.iPos ) | 88 | iPos( i.iPos ) |
89 | { | 89 | { |
90 | } | 90 | } |
91 | 91 | ||
92 | const_iterator( const struct iterator &i ) : | 92 | const_iterator( const struct iterator &i ) : |
93 | pChunk( i.pChunk ), | 93 | pChunk( i.pChunk ), |
94 | iPos( i.iPos ) | 94 | iPos( i.iPos ) |
95 | { | 95 | { |
96 | } | 96 | } |
97 | 97 | ||
98 | const_iterator() : | 98 | const_iterator() : |
99 | pChunk( NULL ), | 99 | pChunk( NULL ), |
100 | iPos( 0 ) | 100 | iPos( 0 ) |
101 | { | 101 | { |
102 | } | 102 | } |
103 | 103 | ||
104 | bool operator==( const const_iterator &i ) const | 104 | bool operator==( const const_iterator &i ) const |
105 | { | 105 | { |
106 | return pChunk == i.pChunk && iPos == i.iPos; | 106 | return pChunk == i.pChunk && iPos == i.iPos; |
107 | } | 107 | } |
108 | 108 | ||
109 | bool operator!=( const const_iterator &i ) const | 109 | bool operator!=( const const_iterator &i ) const |
110 | { | 110 | { |
111 | return !(*this == i); | 111 | return !(*this == i); |
112 | } | 112 | } |
113 | 113 | ||
114 | const_iterator &operator=( const const_iterator &i ) | 114 | const_iterator &operator=( const const_iterator &i ) |
115 | { | 115 | { |
116 | pChunk = i.pChunk; | 116 | pChunk = i.pChunk; |
117 | iPos = i.iPos; | 117 | iPos = i.iPos; |
118 | return *this; | 118 | return *this; |
119 | } | 119 | } |
120 | 120 | ||
121 | const_iterator &operator=( const iterator &i ) | 121 | const_iterator &operator=( const iterator &i ) |
122 | { | 122 | { |
123 | pChunk = i.pChunk; | 123 | pChunk = i.pChunk; |
124 | iPos = i.iPos; | 124 | iPos = i.iPos; |
125 | return *this; | 125 | return *this; |
126 | } | 126 | } |
127 | 127 | ||
128 | const_iterator &operator++() | 128 | const_iterator &operator++() |
129 | { | 129 | { |
130 | if( !pChunk ) return *this; | 130 | if( !pChunk ) return *this; |
131 | iPos++; | 131 | iPos++; |
132 | if( iPos >= pChunk->nLength ) | 132 | if( iPos >= pChunk->nLength ) |
133 | { | 133 | { |
134 | iPos = 0; | 134 | iPos = 0; |
135 | pChunk = pChunk->pNext; | 135 | pChunk = pChunk->pNext; |
136 | } | 136 | } |
137 | return *this; | 137 | return *this; |
138 | } | 138 | } |
139 | 139 | ||
140 | const_iterator &operator++( int ) | 140 | const_iterator &operator++( int ) |
141 | { | 141 | { |
142 | if( !pChunk ) return *this; | 142 | if( !pChunk ) return *this; |
143 | iPos++; | 143 | iPos++; |
144 | if( iPos >= pChunk->nLength ) | 144 | if( iPos >= pChunk->nLength ) |
145 | { | 145 | { |
146 | iPos = 0; | 146 | iPos = 0; |
147 | pChunk = pChunk->pNext; | 147 | pChunk = pChunk->pNext; |
148 | } | 148 | } |
149 | return *this; | 149 | return *this; |
150 | } | 150 | } |
151 | 151 | ||
152 | const_iterator &operator+=( int iAmnt ) | 152 | const_iterator &operator+=( int iAmnt ) |
153 | { | 153 | { |
154 | if( !pChunk ) return *this; | 154 | if( !pChunk ) return *this; |
155 | iPos += iAmnt; | 155 | iPos += iAmnt; |
156 | while( iPos >= pChunk->nLength ) | 156 | while( iPos >= pChunk->nLength ) |
157 | { | 157 | { |
158 | iPos -= pChunk->nLength; | 158 | iPos -= pChunk->nLength; |
159 | pChunk = pChunk->pNext; | 159 | pChunk = pChunk->pNext; |
160 | if( pChunk == NULL ) | 160 | if( pChunk == NULL ) |
161 | break; | 161 | break; |
162 | } | 162 | } |
163 | return *this; | 163 | return *this; |
164 | } | 164 | } |
165 | 165 | ||
166 | const_iterator operator+( int iAmnt ) const | 166 | const_iterator operator+( int iAmnt ) const |
167 | { | 167 | { |
168 | if( !pChunk ) return *this; | 168 | if( !pChunk ) return *this; |
169 | const_iterator ret( *this ); | 169 | const_iterator ret( *this ); |
170 | ret += iAmnt; | 170 | ret += iAmnt; |
171 | return ret; | 171 | return ret; |
172 | } | 172 | } |
173 | 173 | ||
174 | const char &operator *() const | 174 | const char &operator *() const |
175 | { | 175 | { |
176 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid const_iterator."); | 176 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid const_iterator."); |
177 | return pChunk->pData[iPos]; | 177 | return pChunk->pData[iPos]; |
178 | } | 178 | } |
179 | 179 | ||
180 | bool operator==( const char &c ) const | 180 | bool operator==( const char &c ) const |
181 | { | 181 | { |
182 | if( !pChunk ) return false; | 182 | if( !pChunk ) return false; |
183 | return pChunk->pData[iPos] == c; | 183 | return pChunk->pData[iPos] == c; |
184 | } | 184 | } |
185 | 185 | ||
186 | bool operator!=( const char &c ) const | 186 | bool operator!=( const char &c ) const |
187 | { | 187 | { |
188 | if( !pChunk ) return false; | 188 | if( !pChunk ) return false; |
189 | return pChunk->pData[iPos] != c; | 189 | return pChunk->pData[iPos] != c; |
190 | } | 190 | } |
191 | 191 | ||
192 | operator bool() const | 192 | operator bool() const |
193 | { | 193 | { |
194 | return pChunk != NULL; | 194 | return pChunk != NULL; |
195 | } | 195 | } |
196 | 196 | ||
197 | bool isValid() const | 197 | bool isValid() const |
198 | { | 198 | { |
199 | return pChunk != NULL; | 199 | return pChunk != NULL; |
200 | } | 200 | } |
201 | 201 | ||
202 | bool compare( const const_iterator &c ) const | 202 | bool compare( const const_iterator &c ) const |
203 | { | 203 | { |
204 | const_iterator a = *this; | 204 | const_iterator a = *this; |
205 | const_iterator b = c; | 205 | const_iterator b = c; |
206 | if( a == b ) | 206 | if( a == b ) |
207 | return true; | 207 | return true; |
208 | for(; a && b; a++, b++ ) | 208 | for(; a && b; a++, b++ ) |
209 | { | 209 | { |
210 | if( *a != *b ) | 210 | if( *a != *b ) |
211 | return false; | 211 | return false; |
212 | } | 212 | } |
213 | if( (bool)a != (bool)b ) | 213 | if( (bool)a != (bool)b ) |
214 | return false; | 214 | return false; |
215 | return true; | 215 | return true; |
216 | } | 216 | } |
217 | 217 | ||
218 | bool compare( const const_iterator &c, int nLen ) const | 218 | bool compare( const const_iterator &c, int nLen ) const |
219 | { | 219 | { |
220 | const_iterator a = *this; | 220 | const_iterator a = *this; |
221 | const_iterator b = c; | 221 | const_iterator b = c; |
222 | if( a == b ) | 222 | if( a == b ) |
223 | return true; | 223 | return true; |
224 | for(int j = 0; j < nLen; a++, b++, j++ ) | 224 | for(int j = 0; j < nLen; a++, b++, j++ ) |
225 | { | 225 | { |
226 | if( !a || !b || *a != *b ) | 226 | if( !a || !b || *a != *b ) |
227 | return false; | 227 | return false; |
228 | } | 228 | } |
229 | return true; | 229 | return true; |
230 | } | 230 | } |
231 | 231 | ||
232 | bool compare( const char *c ) const | 232 | bool compare( const char *c ) const |
233 | { | 233 | { |
234 | if( !pChunk ) return false; | 234 | if( !pChunk ) return false; |
235 | const_iterator a = *this; | 235 | const_iterator a = *this; |
236 | for(; a && *c; a++, c++ ) | 236 | for(; a && *c; a++, c++ ) |
237 | { | 237 | { |
238 | if( *a != *c ) | 238 | if( *a != *c ) |
239 | return false; | 239 | return false; |
240 | } | 240 | } |
241 | if( a.isValid() != (*c!=(char)0) ) | 241 | if( a.isValid() != (*c!=(char)0) ) |
242 | return false; | 242 | return false; |
243 | return true; | 243 | return true; |
244 | } | 244 | } |
245 | 245 | ||
246 | bool compare( const char *c, int nLen ) const | 246 | bool compare( const char *c, int nLen ) const |
247 | { | 247 | { |
248 | if( !pChunk ) return false; | 248 | if( !pChunk ) return false; |
249 | const_iterator a = *this; | 249 | const_iterator a = *this; |
250 | int j = 0; | 250 | int j = 0; |
251 | for(; a && j < nLen; a++, c++, j++ ) | 251 | for(; a && j < nLen; a++, c++, j++ ) |
252 | { | 252 | { |
253 | if( *a != *c ) | 253 | if( *a != *c ) |
254 | return false; | 254 | return false; |
255 | } | 255 | } |
256 | if( j < nLen ) | 256 | if( j < nLen ) |
257 | return false; | 257 | return false; |
258 | return true; | 258 | return true; |
259 | } | 259 | } |
260 | 260 | ||
261 | bool compare( const String &s ) const | 261 | bool compare( const String &s ) const |
262 | { | 262 | { |
263 | if( !pChunk ) return false; | 263 | if( !pChunk ) return false; |
264 | return compare( s.begin() ); | 264 | return compare( s.begin() ); |
265 | } | 265 | } |
266 | 266 | ||
267 | bool compare( const String &s, int nLen ) const | 267 | bool compare( const String &s, int nLen ) const |
268 | { | 268 | { |
269 | if( !pChunk ) return false; | 269 | if( !pChunk ) return false; |
270 | return compare( s.begin(), nLen ); | 270 | return compare( s.begin(), nLen ); |
271 | } | 271 | } |
272 | 272 | ||
273 | const_iterator find( const char c ) const | 273 | const_iterator find( const char c ) const |
274 | { | 274 | { |
275 | for( const_iterator i = *this; i; i++ ) | 275 | for( const_iterator i = *this; i; i++ ) |
276 | { | 276 | { |
277 | if( *i == c ) | 277 | if( *i == c ) |
278 | return i; | 278 | return i; |
279 | } | 279 | } |
280 | return const_iterator( NULL, 0 ); | 280 | return const_iterator( NULL, 0 ); |
281 | } | 281 | } |
282 | 282 | ||
283 | const_iterator find( const char *pStr, int nLen ) const | 283 | const_iterator find( const char *pStr, int nLen ) const |
284 | { | 284 | { |
285 | for( const_iterator i = *this; i; i++ ) | 285 | for( const_iterator i = *this; i; i++ ) |
286 | { | 286 | { |
287 | if( i.compare( pStr, nLen ) ) | 287 | if( i.compare( pStr, nLen ) ) |
288 | return i; | 288 | return i; |
289 | } | 289 | } |
290 | return const_iterator( NULL, 0 ); | 290 | return const_iterator( NULL, 0 ); |
291 | } | 291 | } |
292 | 292 | ||
293 | const_iterator find( const String &s ) const | 293 | const_iterator find( const String &s ) const |
294 | { | 294 | { |
295 | for( const_iterator i = *this; i; i++ ) | 295 | for( const_iterator i = *this; i; i++ ) |
296 | { | 296 | { |
297 | if( i.compare( s ) ) | 297 | if( i.compare( s ) ) |
298 | return i; | 298 | return i; |
299 | } | 299 | } |
300 | return const_iterator( NULL, 0 ); | 300 | return const_iterator( NULL, 0 ); |
301 | } | 301 | } |
302 | 302 | ||
303 | const_iterator find( const String &s, int nLen ) const | 303 | const_iterator find( const String &s, int nLen ) const |
304 | { | 304 | { |
305 | for( const_iterator i = *this; i; i++ ) | 305 | for( const_iterator i = *this; i; i++ ) |
306 | { | 306 | { |
307 | if( i.compare( s, nLen ) ) | 307 | if( i.compare( s, nLen ) ) |
308 | return i; | 308 | return i; |
309 | } | 309 | } |
310 | return const_iterator( NULL, 0 ); | 310 | return const_iterator( NULL, 0 ); |
311 | } | 311 | } |
312 | } const_iterator; | 312 | } const_iterator; |
313 | 313 | ||
314 | typedef struct iterator | 314 | typedef struct iterator |
315 | { | 315 | { |
316 | friend class String; | 316 | friend class String; |
317 | friend struct const_iterator; | 317 | friend struct const_iterator; |
318 | private: | 318 | private: |
319 | iterator( Chunk *pChunk, int iPos ) : | 319 | iterator( Chunk *pChunk, int iPos ) : |
320 | pChunk( pChunk ), | 320 | pChunk( pChunk ), |
321 | iPos( iPos ) | 321 | iPos( iPos ) |
322 | { | 322 | { |
323 | } | 323 | } |
324 | 324 | ||
325 | Chunk *pChunk; | 325 | Chunk *pChunk; |
326 | int iPos; | 326 | int iPos; |
327 | 327 | ||
328 | public: | 328 | public: |
329 | iterator( const iterator &i ) : | 329 | iterator( const iterator &i ) : |
330 | pChunk( i.pChunk ), | 330 | pChunk( i.pChunk ), |
331 | iPos( i.iPos ) | 331 | iPos( i.iPos ) |
332 | { | 332 | { |
333 | } | 333 | } |
334 | 334 | ||
335 | iterator() : | 335 | iterator() : |
336 | pChunk( NULL ), | 336 | pChunk( NULL ), |
337 | iPos( 0 ) | 337 | iPos( 0 ) |
338 | { | 338 | { |
339 | } | 339 | } |
340 | 340 | ||
341 | operator const_iterator() const | 341 | operator const_iterator() const |
342 | { | 342 | { |
343 | return const_iterator( pChunk, iPos ); | 343 | return const_iterator( pChunk, iPos ); |
344 | } | 344 | } |
345 | 345 | ||
346 | bool operator==( const iterator &i ) const | 346 | bool operator==( const iterator &i ) const |
347 | { | 347 | { |
348 | return pChunk == i.pChunk && iPos == i.iPos; | 348 | return pChunk == i.pChunk && iPos == i.iPos; |
349 | } | 349 | } |
350 | 350 | ||
351 | bool operator!=( const iterator &i ) const | 351 | bool operator!=( const iterator &i ) const |
352 | { | 352 | { |
353 | return !(*this == i); | 353 | return !(*this == i); |
354 | } | 354 | } |
355 | 355 | ||
356 | iterator &operator=( const iterator &i ) | 356 | iterator &operator=( const iterator &i ) |
357 | { | 357 | { |
358 | pChunk = i.pChunk; | 358 | pChunk = i.pChunk; |
359 | iPos = i.iPos; | 359 | iPos = i.iPos; |
360 | return *this; | 360 | return *this; |
361 | } | 361 | } |
362 | 362 | ||
363 | iterator &operator++() | 363 | iterator &operator++() |
364 | { | 364 | { |
365 | if( !pChunk ) return *this; | 365 | if( !pChunk ) return *this; |
366 | iPos++; | 366 | iPos++; |
367 | if( iPos >= pChunk->nLength ) | 367 | if( iPos >= pChunk->nLength ) |
368 | { | 368 | { |
369 | iPos = 0; | 369 | iPos = 0; |
370 | pChunk = pChunk->pNext; | 370 | pChunk = pChunk->pNext; |
371 | } | 371 | } |
372 | return *this; | 372 | return *this; |
373 | } | 373 | } |
374 | 374 | ||
375 | iterator &operator++( int ) | 375 | iterator &operator++( int ) |
376 | { | 376 | { |
377 | if( !pChunk ) return *this; | 377 | if( !pChunk ) return *this; |
378 | iPos++; | 378 | iPos++; |
379 | if( iPos >= pChunk->nLength ) | 379 | if( iPos >= pChunk->nLength ) |
380 | { | 380 | { |
381 | iPos = 0; | 381 | iPos = 0; |
382 | pChunk = pChunk->pNext; | 382 | pChunk = pChunk->pNext; |
383 | } | 383 | } |
384 | return *this; | 384 | return *this; |
385 | } | 385 | } |
386 | 386 | ||
387 | iterator &operator+=( int iAmnt ) | 387 | iterator &operator+=( int iAmnt ) |
388 | { | 388 | { |
389 | if( !pChunk ) return *this; | 389 | if( !pChunk ) return *this; |
390 | iPos += iAmnt; | 390 | iPos += iAmnt; |
391 | while( iPos >= pChunk->nLength ) | 391 | while( iPos >= pChunk->nLength ) |
392 | { | 392 | { |
393 | iPos -= pChunk->nLength; | 393 | iPos -= pChunk->nLength; |
394 | pChunk = pChunk->pNext; | 394 | pChunk = pChunk->pNext; |
395 | if( pChunk == NULL ) | 395 | if( pChunk == NULL ) |
396 | break; | 396 | break; |
397 | } | 397 | } |
398 | return *this; | 398 | return *this; |
399 | } | 399 | } |
400 | 400 | ||
401 | iterator operator+( int iAmnt ) const | 401 | iterator operator+( int iAmnt ) const |
402 | { | 402 | { |
403 | if( !pChunk ) return *this; | 403 | if( !pChunk ) return *this; |
404 | iterator ret( *this ); | 404 | iterator ret( *this ); |
405 | ret += iAmnt; | 405 | ret += iAmnt; |
406 | return ret; | 406 | return ret; |
407 | } | 407 | } |
408 | 408 | ||
409 | char &operator*() | 409 | char &operator*() |
410 | { | 410 | { |
411 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 411 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
412 | return pChunk->pData[iPos]; | 412 | return pChunk->pData[iPos]; |
413 | } | 413 | } |
414 | 414 | ||
415 | const char &operator*() const | 415 | const char &operator*() const |
416 | { | 416 | { |
417 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 417 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
418 | return pChunk->pData[iPos]; | 418 | return pChunk->pData[iPos]; |
419 | } | 419 | } |
420 | 420 | ||
421 | bool operator==( const char &c ) const | 421 | bool operator==( const char &c ) const |
422 | { | 422 | { |
423 | if( !pChunk ) return false; | 423 | if( !pChunk ) return false; |
424 | return pChunk->pData[iPos] == c; | 424 | return pChunk->pData[iPos] == c; |
425 | } | 425 | } |
426 | 426 | ||
427 | bool operator!=( const char &c ) const | 427 | bool operator!=( const char &c ) const |
428 | { | 428 | { |
429 | if( !pChunk ) return false; | 429 | if( !pChunk ) return false; |
430 | return pChunk->pData[iPos] != c; | 430 | return pChunk->pData[iPos] != c; |
431 | } | 431 | } |
432 | 432 | ||
433 | iterator &operator=( const char &c ) | 433 | iterator &operator=( const char &c ) |
434 | { | 434 | { |
435 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); | 435 | if( !pChunk ) throw Bu::ExceptionBase("Not a valid iterator."); |
436 | pChunk->pData[iPos] = c; | 436 | pChunk->pData[iPos] = c; |
437 | return *this; | 437 | return *this; |
438 | } | 438 | } |
439 | 439 | ||
440 | operator bool() const | 440 | operator bool() const |
441 | { | 441 | { |
442 | return pChunk != NULL; | 442 | return pChunk != NULL; |
443 | } | 443 | } |
444 | 444 | ||
445 | bool isValid() const | 445 | bool isValid() const |
446 | { | 446 | { |
447 | return pChunk != NULL; | 447 | return pChunk != NULL; |
448 | } | 448 | } |
449 | 449 | ||
450 | bool compare( const const_iterator &c ) const | 450 | bool compare( const const_iterator &c ) const |
451 | { | 451 | { |
452 | const_iterator a( *this ); | 452 | const_iterator a( *this ); |
453 | const_iterator b = c; | 453 | const_iterator b = c; |
454 | if( a == b ) | 454 | if( a == b ) |
455 | return true; | 455 | return true; |
456 | for(; a && b; a++, b++ ) | 456 | for(; a && b; a++, b++ ) |
457 | { | 457 | { |
458 | if( *a != *b ) | 458 | if( *a != *b ) |
459 | return false; | 459 | return false; |
460 | } | 460 | } |
461 | if( (bool)a != (bool)b ) | 461 | if( (bool)a != (bool)b ) |
462 | return false; | 462 | return false; |
463 | return true; | 463 | return true; |
464 | } | 464 | } |
465 | 465 | ||
466 | bool compare( const const_iterator &c, int nLen ) const | 466 | bool compare( const const_iterator &c, int nLen ) const |
467 | { | 467 | { |
468 | const_iterator a( *this ); | 468 | const_iterator a( *this ); |
469 | const_iterator b = c; | 469 | const_iterator b = c; |
470 | if( a == b ) | 470 | if( a == b ) |
471 | return true; | 471 | return true; |
472 | for(int j = 0; j < nLen; a++, b++, j++ ) | 472 | for(int j = 0; j < nLen; a++, b++, j++ ) |
473 | { | 473 | { |
474 | if( !a || !b || *a != *b ) | 474 | if( !a || !b || *a != *b ) |
475 | return false; | 475 | return false; |
476 | } | 476 | } |
477 | return true; | 477 | return true; |
478 | } | 478 | } |
479 | 479 | ||
480 | bool compare( const char *c ) const | 480 | bool compare( const char *c ) const |
481 | { | 481 | { |
482 | if( !pChunk ) return false; | 482 | if( !pChunk ) return false; |
483 | iterator a = *this; | 483 | iterator a = *this; |
484 | for(; a && *c; a++, c++ ) | 484 | for(; a && *c; a++, c++ ) |
485 | { | 485 | { |
486 | if( *a != *c ) | 486 | if( *a != *c ) |
487 | return false; | 487 | return false; |
488 | } | 488 | } |
489 | if( a.isValid() != (*c!=(char)0) ) | 489 | if( a.isValid() != (*c!=(char)0) ) |
490 | return false; | 490 | return false; |
491 | return true; | 491 | return true; |
492 | } | 492 | } |
493 | 493 | ||
494 | bool compare( const char *c, int nLen ) const | 494 | bool compare( const char *c, int nLen ) const |
495 | { | 495 | { |
496 | if( !pChunk ) return false; | 496 | if( !pChunk ) return false; |
497 | iterator a = *this; | 497 | iterator a = *this; |
498 | int j = 0; | 498 | int j = 0; |
499 | for(; a && j < nLen; a++, c++, j++ ) | 499 | for(; a && j < nLen; a++, c++, j++ ) |
500 | { | 500 | { |
501 | if( *a != *c ) | 501 | if( *a != *c ) |
502 | return false; | 502 | return false; |
503 | } | 503 | } |
504 | if( j < nLen ) | 504 | if( j < nLen ) |
505 | return false; | 505 | return false; |
506 | return true; | 506 | return true; |
507 | } | 507 | } |
508 | 508 | ||
509 | bool compare( const String &s ) const | 509 | bool compare( const String &s ) const |
510 | { | 510 | { |
511 | if( !pChunk ) return false; | 511 | if( !pChunk ) return false; |
512 | return compare( s.begin() ); | 512 | return compare( s.begin() ); |
513 | } | 513 | } |
514 | 514 | ||
515 | bool compare( const String &s, int nLen ) const | 515 | bool compare( const String &s, int nLen ) const |
516 | { | 516 | { |
517 | if( !pChunk ) return false; | 517 | if( !pChunk ) return false; |
518 | return compare( s.begin(), nLen ); | 518 | return compare( s.begin(), nLen ); |
519 | } | 519 | } |
520 | 520 | ||
521 | iterator find( const char c ) const | 521 | iterator find( const char c ) const |
522 | { | 522 | { |
523 | for( iterator i = *this; i; i++ ) | 523 | for( iterator i = *this; i; i++ ) |
524 | { | 524 | { |
525 | if( *i == c ) | 525 | if( *i == c ) |
526 | return i; | 526 | return i; |
527 | } | 527 | } |
528 | return iterator( NULL, 0 ); | 528 | return iterator( NULL, 0 ); |
529 | } | 529 | } |
530 | 530 | ||
531 | iterator find( const char *pStr, int nLen ) const | 531 | iterator find( const char *pStr, int nLen ) const |
532 | { | 532 | { |
533 | for( iterator i = *this; i; i++ ) | 533 | for( iterator i = *this; i; i++ ) |
534 | { | 534 | { |
535 | if( i.compare( pStr, nLen ) ) | 535 | if( i.compare( pStr, nLen ) ) |
536 | return i; | 536 | return i; |
537 | } | 537 | } |
538 | return iterator( NULL, 0 ); | 538 | return iterator( NULL, 0 ); |
539 | } | 539 | } |
540 | 540 | ||
541 | iterator find( const String &s ) const | 541 | iterator find( const String &s ) const |
542 | { | 542 | { |
543 | for( iterator i = *this; i; i++ ) | 543 | for( iterator i = *this; i; i++ ) |
544 | { | 544 | { |
545 | if( i.compare( s ) ) | 545 | if( i.compare( s ) ) |
546 | return i; | 546 | return i; |
547 | } | 547 | } |
548 | return iterator( NULL, 0 ); | 548 | return iterator( NULL, 0 ); |
549 | } | 549 | } |
550 | 550 | ||
551 | iterator find( const String &s, int nLen ) const | 551 | iterator find( const String &s, int nLen ) const |
552 | { | 552 | { |
553 | for( iterator i = *this; i; i++ ) | 553 | for( iterator i = *this; i; i++ ) |
554 | { | 554 | { |
555 | if( i.compare( s, nLen ) ) | 555 | if( i.compare( s, nLen ) ) |
556 | return i; | 556 | return i; |
557 | } | 557 | } |
558 | return iterator( NULL, 0 ); | 558 | return iterator( NULL, 0 ); |
559 | } | 559 | } |
560 | } iterator; | 560 | } iterator; |
561 | 561 | ||
562 | public: | 562 | public: |
563 | String(); | 563 | String(); |
564 | String( const char *pData ); | 564 | String( const char *pData ); |
565 | String( const char *pData, long nLength ); | 565 | String( const char *pData, long nLength ); |
566 | String( const String &rSrc ); | 566 | String( const String &rSrc ); |
567 | String( const String &rSrc, long nLength ); | 567 | String( const String &rSrc, long nLength ); |
568 | String( const String &rSrc, long nStart, long nLength ); | 568 | String( const String &rSrc, long nStart, long nLength ); |
569 | String( long nSize ); | 569 | String( long nSize ); |
570 | String( const const_iterator &s ); | 570 | String( const const_iterator &s ); |
571 | String( const const_iterator &s, const const_iterator &e ); | 571 | String( const const_iterator &s, const const_iterator &e ); |
572 | virtual ~String(); | 572 | virtual ~String(); |
573 | 573 | ||
574 | /** | 574 | /** |
575 | * Append data to your string. | 575 | * Append data to your string. |
576 | *@param pData (const char *) The data to append. | 576 | *@param pData (const char *) The data to append. |
577 | */ | 577 | */ |
578 | void append( const char *pData ); | 578 | void append( const char *pData ); |
579 | 579 | ||
580 | /** | 580 | /** |
581 | * Append data to your string. | 581 | * Append data to your string. |
582 | *@param pData (const char *) The data to append. | 582 | *@param pData (const char *) The data to append. |
583 | *@param nLen (long) The length of the data to append. | 583 | *@param nLen (long) The length of the data to append. |
584 | */ | 584 | */ |
585 | void append( const char *pData, long nLen ); | 585 | void append( const char *pData, long nLen ); |
586 | 586 | ||
587 | /** | 587 | /** |
588 | * Append data to your string. | 588 | * Append data to your string. |
589 | *@param pData (const char *) The data to append. | 589 | *@param pData (const char *) The data to append. |
590 | *@param nStart (long) The start position to copy from. | 590 | *@param nStart (long) The start position to copy from. |
591 | *@param nLen (long) The length of the data to append. | 591 | *@param nLen (long) The length of the data to append. |
592 | */ | 592 | */ |
593 | void append( const char *pData, long nStart, long nLen ); | 593 | void append( const char *pData, long nStart, long nLen ); |
594 | 594 | ||
595 | /** | 595 | /** |
596 | * Append a single char to your string. | 596 | * Append a single char to your string. |
597 | *@param cData (const char &) The character to append. | 597 | *@param cData (const char &) The character to append. |
598 | */ | 598 | */ |
599 | void append( const char &cData ); | 599 | void append( const char &cData ); |
600 | 600 | ||
601 | /** | 601 | /** |
602 | * Append another String to this one. | 602 | * Append another String to this one. |
603 | *@param sData (String &) The String to append. | 603 | *@param sData (String &) The String to append. |
604 | *@todo This function can be made much faster by not using getStr() | 604 | *@todo This function can be made much faster by not using getStr() |
605 | */ | 605 | */ |
606 | void append( const String & sData ); | 606 | void append( const String & sData ); |
607 | 607 | ||
608 | /** | 608 | /** |
609 | * Append another String to this one. | 609 | * Append another String to this one. |
610 | *@param sData (String &) The String to append. | 610 | *@param sData (String &) The String to append. |
611 | *@param nLen How much data to append. | 611 | *@param nLen How much data to append. |
612 | *@todo This function can be made much faster by not using getStr() | 612 | *@todo This function can be made much faster by not using getStr() |
613 | */ | 613 | */ |
614 | void append( const String & sData, long nLen ); | 614 | void append( const String & sData, long nLen ); |
615 | 615 | ||
616 | /** | 616 | /** |
617 | * Append another String to this one. | 617 | * Append another String to this one. |
618 | *@param sData (String &) The String to append. | 618 | *@param sData (String &) The String to append. |
619 | *@param nStart Start position in sData to start copying from. | 619 | *@param nStart Start position in sData to start copying from. |
620 | *@param nLen How much data to append. | 620 | *@param nLen How much data to append. |
621 | *@todo This function can be made much faster by not using getStr() | 621 | *@todo This function can be made much faster by not using getStr() |
622 | */ | 622 | */ |
623 | void append( const String & sData, long nStart, long nLen ); | 623 | void append( const String & sData, long nStart, long nLen ); |
624 | 624 | ||
625 | /** | 625 | /** |
626 | * Append data to this String using the passed in iterator as a base. | 626 | * Append data to this String using the passed in iterator as a base. |
627 | * The iterator is const, it is not changed. | 627 | * The iterator is const, it is not changed. |
628 | *@param s Iterator from any compatible String to copy data from. | 628 | *@param s Iterator from any compatible String to copy data from. |
629 | */ | 629 | */ |
630 | void append( const const_iterator &s ); | 630 | void append( const const_iterator &s ); |
631 | 631 | ||
632 | /** | 632 | /** |
633 | * Append data to this String using the passed in iterator as a base. | 633 | * Append data to this String using the passed in iterator as a base. |
634 | * The iterator is const, it is not changed. | 634 | * The iterator is const, it is not changed. |
635 | *@param s Iterator from any compatible String to copy data from. | 635 | *@param s Iterator from any compatible String to copy data from. |
636 | */ | 636 | */ |
637 | void append( const iterator &s ); | 637 | void append( const iterator &s ); |
638 | 638 | ||
639 | /** | 639 | /** |
640 | * Append data to this String using the passed in iterator as a base, | 640 | * Append data to this String using the passed in iterator as a base, |
641 | * and copy data until the ending iterator is reached. The character | 641 | * and copy data until the ending iterator is reached. The character |
642 | * at the ending iterator is not copied. | 642 | * at the ending iterator is not copied. |
643 | * The iterators are const, they are not changed. | 643 | * The iterators are const, they are not changed. |
644 | *@param s Iterator from any compatible String to copy data from. | 644 | *@param s Iterator from any compatible String to copy data from. |
645 | *@param e Iterator to stop copying at. | 645 | *@param e Iterator to stop copying at. |
646 | */ | 646 | */ |
647 | void append( const const_iterator &s, const const_iterator &e ); | 647 | void append( const const_iterator &s, const const_iterator &e ); |
648 | 648 | ||
649 | /** | 649 | /** |
650 | * Prepend another String to this one. | 650 | * Prepend another String to this one. |
651 | *@param sData (String &) The String to prepend. | 651 | *@param sData (String &) The String to prepend. |
652 | *@todo This function can be made much faster by not using getStr() | 652 | *@todo This function can be made much faster by not using getStr() |
653 | */ | 653 | */ |
654 | void prepend( const String & sData ); | 654 | void prepend( const String & sData ); |
655 | 655 | ||
656 | /** | 656 | /** |
657 | * Prepend data to your string. | 657 | * Prepend data to your string. |
658 | *@param pData (const char *) The data to prepend. | 658 | *@param pData (const char *) The data to prepend. |
659 | */ | 659 | */ |
660 | void prepend( const char *pData ); | 660 | void prepend( const char *pData ); |
661 | 661 | ||
662 | /** | 662 | /** |
663 | * Prepend data to your string. | 663 | * Prepend data to your string. |
664 | *@param pData (const char *) The data to prepend. | 664 | *@param pData (const char *) The data to prepend. |
665 | *@param nLen (long) The length of the data to prepend. | 665 | *@param nLen (long) The length of the data to prepend. |
666 | */ | 666 | */ |
667 | void prepend( const char *pData, long nLen ); | 667 | void prepend( const char *pData, long nLen ); |
668 | 668 | ||
669 | void prepend( const char c ); | 669 | void prepend( const char c ); |
670 | 670 | ||
671 | /** | 671 | /** |
672 | * Insert pData before byte nPos, that is, the first byte of pData will | 672 | * Insert pData before byte nPos, that is, the first byte of pData will |
673 | * start at nPos. This could probably be made faster by avoiding | 673 | * start at nPos. This could probably be made faster by avoiding |
674 | * flattening. | 674 | * flattening. |
675 | */ | 675 | */ |
676 | void insert( long nPos, const char *pData, long nLen ); | 676 | void insert( long nPos, const char *pData, long nLen ); |
677 | 677 | ||
678 | void insert( long nPos, const String &str ); | 678 | void insert( long nPos, const String &str ); |
679 | 679 | ||
680 | /** | 680 | /** |
681 | *@todo This function shouldn't use strlen, we should add our own to | 681 | *@todo This function shouldn't use strlen, we should add our own to |
682 | * this class, one that can be overridden in a specific implementation. | 682 | * this class, one that can be overridden in a specific implementation. |
683 | */ | 683 | */ |
684 | void insert( long nPos, const char *pData ); | 684 | void insert( long nPos, const char *pData ); |
685 | 685 | ||
686 | void remove( long nPos, long nLen ); | 686 | void remove( long nPos, long nLen ); |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * Clear all data from the string. | 689 | * Clear all data from the string. |
690 | */ | 690 | */ |
691 | void clear(); | 691 | void clear(); |
692 | 692 | ||
693 | String replace( const String &fnd, const String &rep ) const; | 693 | String replace( const String &fnd, const String &rep ) const; |
694 | 694 | ||
695 | /** | 695 | /** |
696 | * Force the string to resize | 696 | * Force the string to resize |
697 | *@param nNewSize (long) The new size of the string. | 697 | *@param nNewSize (long) The new size of the string. |
698 | */ | 698 | */ |
699 | void resize( long nNewSize ); | 699 | void resize( long nNewSize ); |
700 | 700 | ||
701 | /** | 701 | /** |
702 | * Get the current size of the string. | 702 | * Get the current size of the string. |
703 | *@returns (long) The current size of the string. | 703 | *@returns (long) The current size of the string. |
704 | */ | 704 | */ |
705 | long getSize() const; | 705 | long getSize() const; |
706 | 706 | ||
707 | /** | 707 | /** |
708 | * Get a pointer to the string array. | 708 | * Get a pointer to the string array. |
709 | *@returns (char *) The string data. | 709 | *@returns (char *) The string data. |
710 | */ | 710 | */ |
711 | char *getStr(); | 711 | char *getStr(); |
712 | 712 | ||
713 | /** | 713 | /** |
714 | * Get a const pointer to the string array. | 714 | * Get a const pointer to the string array. |
715 | *@returns (const char *) The string data. | 715 | *@returns (const char *) The string data. |
716 | */ | 716 | */ |
717 | const char *getStr() const; | 717 | const char *getStr() const; |
718 | 718 | ||
719 | /** | 719 | /** |
720 | * A convinience function, this one won't cause as much work as the | 720 | * A convinience function, this one won't cause as much work as the |
721 | * non-const getStr, so if you're not changing the data, consider it. | 721 | * non-const getStr, so if you're not changing the data, consider it. |
722 | */ | 722 | */ |
723 | const char *getConstStr() const; | 723 | const char *getConstStr() const; |
724 | 724 | ||
725 | String getSubStrIdx( long iStart, long iSize=-1 ) const; | 725 | String getSubStrIdx( long iStart, long iSize=-1 ) const; |
726 | 726 | ||
727 | String getSubStr( const_iterator iBegin, | 727 | String getSubStr( const_iterator iBegin, |
728 | const_iterator iEnd=String::const_iterator() ) const; | 728 | const_iterator iEnd=String::const_iterator() ) const; |
729 | 729 | ||
730 | Bu::List<String> split( const char c ) const; | 730 | Bu::List<String> split( const char c ) const; |
731 | 731 | ||
732 | /** | 732 | /** |
733 | * Plus equals operator for String. | 733 | * Plus equals operator for String. |
734 | *@param pData (const char *) The data to append to your String. | 734 | *@param pData (const char *) The data to append to your String. |
735 | */ | 735 | */ |
736 | String &operator+=( const char *pData ); | 736 | String &operator+=( const char *pData ); |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * Plus equals operator for String. | 739 | * Plus equals operator for String. |
740 | *@param rSrc (const String &) The String to append to your String. | 740 | *@param rSrc (const String &) The String to append to your String. |
741 | */ | 741 | */ |
742 | String &operator+=( const String &rSrc ); | 742 | String &operator+=( const String &rSrc ); |
743 | 743 | ||
744 | String &operator+=( const String::const_iterator &i ); | 744 | String &operator+=( const String::const_iterator &i ); |
745 | 745 | ||
746 | /** | 746 | /** |
747 | * Plus equals operator for String. | 747 | * Plus equals operator for String. |
748 | *@param cData (const char) The character to append to your String. | 748 | *@param cData (const char) The character to append to your String. |
749 | */ | 749 | */ |
750 | String &operator+=( const char cData ); | 750 | String &operator+=( const char cData ); |
751 | 751 | ||
752 | /** | 752 | /** |
753 | * Assignment operator. | 753 | * Assignment operator. |
754 | *@param pData (const char *) The character array to append to your | 754 | *@param pData (const char *) The character array to append to your |
755 | * String. | 755 | * String. |
756 | */ | 756 | */ |
757 | String &operator=( const char *pData ); | 757 | String &operator=( const char *pData ); |
758 | 758 | ||
759 | String operator+( const String &rRight ) const; | 759 | String operator+( const String &rRight ) const; |
760 | 760 | ||
761 | String operator+( const char *pRight ) const; | 761 | String operator+( const char *pRight ) const; |
762 | 762 | ||
763 | String operator+( char *pRight ) const; | 763 | String operator+( char *pRight ) const; |
764 | 764 | ||
765 | /** | 765 | /** |
766 | * Reset your String to this character array. | 766 | * Reset your String to this character array. |
767 | *@param pData (const char *) The character array to set your String to. | 767 | *@param pData (const char *) The character array to set your String to. |
768 | */ | 768 | */ |
769 | void set( const char *pData ); | 769 | void set( const char *pData ); |
770 | 770 | ||
771 | /** | 771 | /** |
772 | * Reset your String to this character array. | 772 | * Reset your String to this character array. |
773 | *@param pData (const char *) The character array to set your String to. | 773 | *@param pData (const char *) The character array to set your String to. |
774 | *@param nSize (long) The length of the inputted character array. | 774 | *@param nSize (long) The length of the inputted character array. |
775 | */ | 775 | */ |
776 | void set( const char *pData, long nSize ); | 776 | void set( const char *pData, long nSize ); |
777 | 777 | ||
778 | void set( const char *pData, long nStart, long nSize ); | 778 | void set( const char *pData, long nStart, long nSize ); |
779 | 779 | ||
780 | void set( const String &rData ); | 780 | void set( const String &rData ); |
781 | 781 | ||
782 | void set( const String &rData, long nSize ); | 782 | void set( const String &rData, long nSize ); |
783 | 783 | ||
784 | void set( const String &rData, long nStart, long nSize ); | 784 | void set( const String &rData, long nStart, long nSize ); |
785 | 785 | ||
786 | void set( const_iterator s ); | 786 | void set( const_iterator s ); |
787 | 787 | ||
788 | void set( const_iterator s, const_iterator e ); | 788 | void set( const_iterator s, const_iterator e ); |
789 | 789 | ||
790 | /** | 790 | /** |
791 | * Resize the string, possibly to make room for a copy. At the moment | 791 | * Resize the string, possibly to make room for a copy. At the moment |
792 | * this operation *is* destructive. What was in the string will in no | 792 | * this operation *is* destructive. What was in the string will in no |
793 | * way be preserved. This is, however, very fast. If you want to | 793 | * way be preserved. This is, however, very fast. If you want to |
794 | * keep your data check out resize. | 794 | * keep your data check out resize. |
795 | *@param iSize the new size in bytes. The string is guranteed to have | 795 | *@param iSize the new size in bytes. The string is guranteed to have |
796 | * at least this much contiguous space available when done. | 796 | * at least this much contiguous space available when done. |
797 | */ | 797 | */ |
798 | void setSize( long iSize ); | 798 | void setSize( long iSize ); |
799 | 799 | ||
800 | /** | 800 | /** |
801 | * Equals comparison operator. | 801 | * Equals comparison operator. |
802 | *@param pData (const char *) The character array to compare your String | 802 | *@param pData (const char *) The character array to compare your String |
803 | * to. | 803 | * to. |
804 | */ | 804 | */ |
805 | bool operator==( const char *pData ) const; | 805 | bool operator==( const char *pData ) const; |
806 | 806 | ||
807 | /** | 807 | /** |
808 | * Equals comparison operator. | 808 | * Equals comparison operator. |
809 | *@param pData (const String &) The String to compare your String to. | 809 | *@param pData (const String &) The String to compare your String to. |
810 | */ | 810 | */ |
811 | bool operator==( const String &pData ) const; | 811 | bool operator==( const String &pData ) const; |
812 | 812 | ||
813 | /** | 813 | /** |
814 | * Not equals comparison operator. | 814 | * Not equals comparison operator. |
815 | *@param pData (const char *) The character array to compare your String | 815 | *@param pData (const char *) The character array to compare your String |
816 | * to. | 816 | * to. |
817 | */ | 817 | */ |
818 | bool operator!=(const char *pData ) const; | 818 | bool operator!=(const char *pData ) const; |
819 | 819 | ||
820 | /** | 820 | /** |
821 | * Not equals comparison operator. | 821 | * Not equals comparison operator. |
822 | *@param pData (const String &) The String to compare your String to. | 822 | *@param pData (const String &) The String to compare your String to. |
823 | */ | 823 | */ |
824 | bool operator!=(const String &pData ) const; | 824 | bool operator!=(const String &pData ) const; |
825 | 825 | ||
826 | bool operator<(const String &pData ) const; | 826 | bool operator<(const String &pData ) const; |
827 | 827 | ||
828 | bool operator<=(const String &pData ) const; | 828 | bool operator<=(const String &pData ) const; |
829 | 829 | ||
830 | bool operator>(const String &pData ) const; | 830 | bool operator>(const String &pData ) const; |
831 | 831 | ||
832 | bool operator>=(const String &pData ) const; | 832 | bool operator>=(const String &pData ) const; |
833 | 833 | ||
834 | /** | 834 | /** |
835 | * Indexing operator | 835 | * Indexing operator |
836 | *@param nIndex (long) The index of the character you want. | 836 | *@param nIndex (long) The index of the character you want. |
837 | *@returns (char &) The character at position (nIndex). | 837 | *@returns (char &) The character at position (nIndex). |
838 | */ | 838 | */ |
839 | char &operator[]( long nIndex ); | 839 | char &operator[]( long nIndex ); |
840 | 840 | ||
841 | /** | 841 | /** |
842 | * Const indexing operator | 842 | * Const indexing operator |
843 | *@param nIndex (long) The index of the character you want. | 843 | *@param nIndex (long) The index of the character you want. |
844 | *@returns (const char &) The character at position (nIndex). | 844 | *@returns (const char &) The character at position (nIndex). |
845 | */ | 845 | */ |
846 | const char &operator[]( long nIndex ) const; | 846 | const char &operator[]( long nIndex ) const; |
847 | 847 | ||
848 | bool isSet() const; | 848 | bool isSet() const; |
849 | 849 | ||
850 | bool compareSub( const char *pData, long nIndex, long nLen ) const; | 850 | bool compareSub( const char *pData, long nIndex, long nLen ) const; |
851 | 851 | ||
852 | bool compareSub( const String &rData, long nIndex, long nLen ) const; | 852 | bool compareSub( const String &rData, long nIndex, long nLen ) const; |
853 | 853 | ||
854 | /** | 854 | /** |
855 | * Is the character at index (nIndex) white space? | 855 | * Is the character at index (nIndex) white space? |
856 | *@param nIndex (long) The index of the character you want to check. | 856 | *@param nIndex (long) The index of the character you want to check. |
857 | *@returns (bool) Is it white space? | 857 | *@returns (bool) Is it white space? |
858 | */ | 858 | */ |
859 | bool isWS( long nIndex ) const; | 859 | bool isWS( long nIndex ) const; |
860 | 860 | ||
861 | /** | 861 | /** |
862 | * Is the character at index (nIndex) a letter? | 862 | * Is the character at index (nIndex) a letter? |
863 | *@param nIndex (long) The index of the character you want to check. | 863 | *@param nIndex (long) The index of the character you want to check. |
864 | *@returns (bool) Is it a letter? | 864 | *@returns (bool) Is it a letter? |
865 | */ | 865 | */ |
866 | bool isAlpha( long nIndex ) const; | 866 | bool isAlpha( long nIndex ) const; |
867 | 867 | ||
868 | /** | 868 | /** |
869 | * Convert your alpha characters to lower case. | 869 | * Convert your alpha characters to lower case. |
870 | */ | 870 | */ |
871 | String toLower() const; | 871 | String toLower() const; |
872 | 872 | ||
873 | /** | 873 | /** |
874 | * Convert your alpha characters to upper case. | 874 | * Convert your alpha characters to upper case. |
875 | */ | 875 | */ |
876 | String toUpper() const; | 876 | String toUpper() const; |
877 | 877 | ||
878 | const_iterator find( const char cChar, | 878 | const_iterator find( const char cChar, |
879 | const_iterator iStart=const_iterator() ) const; | 879 | const_iterator iStart=const_iterator() ) const; |
880 | 880 | ||
881 | const_iterator find( const char *sText, int nLen, | 881 | const_iterator find( const char *sText, int nLen, |
882 | const_iterator iStart=const_iterator() ) const; | 882 | const_iterator iStart=const_iterator() ) const; |
883 | 883 | ||
884 | const_iterator find( const String &rStr, | 884 | const_iterator find( const String &rStr, |
885 | const_iterator iStart=const_iterator() ) const; | 885 | const_iterator iStart=const_iterator() ) const; |
886 | 886 | ||
887 | const_iterator find( const String &rStr, int nLen, | 887 | const_iterator find( const String &rStr, int nLen, |
888 | const_iterator iStart=const_iterator() ) const; | 888 | const_iterator iStart=const_iterator() ) const; |
889 | 889 | ||
890 | iterator find( const char cChar, | 890 | iterator find( const char cChar, |
891 | const_iterator iStart=const_iterator() ); | 891 | const_iterator iStart=const_iterator() ); |
892 | 892 | ||
893 | iterator find( const char *sText, int nLen, | 893 | iterator find( const char *sText, int nLen, |
894 | const_iterator iStart=const_iterator() ); | 894 | const_iterator iStart=const_iterator() ); |
895 | 895 | ||
896 | iterator find( const String &rStr, | 896 | iterator find( const String &rStr, |
897 | const_iterator iStart=const_iterator() ); | 897 | const_iterator iStart=const_iterator() ); |
898 | 898 | ||
899 | iterator find( const String &rStr, int nLen, | 899 | iterator find( const String &rStr, int nLen, |
900 | const_iterator iStart=const_iterator() ); | 900 | const_iterator iStart=const_iterator() ); |
901 | 901 | ||
902 | /** | 902 | /** |
903 | * Find the index of the first occurrance of cChar | 903 | * Find the index of the first occurrance of cChar |
904 | *@param cChar The character to search for. | 904 | *@param cChar The character to search for. |
905 | *@param iStart The position in the string to start searching from. | 905 | *@param iStart The position in the string to start searching from. |
906 | *@returns (long) The index of the first occurrance. -1 for not found. | 906 | *@returns (long) The index of the first occurrance. -1 for not found. |
907 | */ | 907 | */ |
908 | long findIdx( const char cChar, long iStart=0 ) const; | 908 | long findIdx( const char cChar, long iStart=0 ) const; |
909 | 909 | ||
910 | /** | 910 | /** |
911 | * Find the index of the first occurrance of sText | 911 | * Find the index of the first occurrance of sText |
912 | *@param sText The null-terminated string to search for. | 912 | *@param sText The null-terminated string to search for. |
913 | *@param iStart The position in the string to start searching from. | 913 | *@param iStart The position in the string to start searching from. |
914 | *@returns The index of the first occurrance. -1 for not found. | 914 | *@returns The index of the first occurrance. -1 for not found. |
915 | */ | 915 | */ |
916 | long findIdx( const char *sText, long iStart=0 ) const; | 916 | long findIdx( const char *sText, long iStart=0 ) const; |
917 | 917 | ||
918 | /** | 918 | /** |
919 | * Do a reverse search for (sText) | 919 | * Do a reverse search for (sText) |
920 | *@param sText (const char *) The string to search for. | 920 | *@param sText (const char *) The string to search for. |
921 | *@returns (long) The index of the last occurrance. -1 for not found. | 921 | *@returns (long) The index of the last occurrance. -1 for not found. |
922 | */ | 922 | */ |
923 | long rfindIdx( const char *sText ) const; | 923 | long rfindIdx( const char *sText ) const; |
924 | 924 | ||
925 | /** | 925 | /** |
926 | * Remove nAmnt bytes from the front of the string. This function | 926 | * Remove nAmnt bytes from the front of the string. This function |
927 | * operates in O(n) time and should be used sparingly. | 927 | * operates in O(n) time and should be used sparingly. |
928 | */ | 928 | */ |
929 | void trimFront( long nAmnt ); | 929 | void trimFront( long nAmnt ); |
930 | 930 | ||
931 | void trimBack( long iAmnt ); | 931 | void trimBack( long iAmnt ); |
932 | 932 | ||
933 | Bu::String trimWhitespace() const; | 933 | Bu::String trimWhitespace() const; |
934 | 934 | ||
935 | iterator begin(); | 935 | iterator begin(); |
936 | 936 | ||
937 | const_iterator begin() const; | 937 | const_iterator begin() const; |
938 | 938 | ||
939 | iterator end(); | 939 | iterator end(); |
940 | 940 | ||
941 | const_iterator end() const; | 941 | const_iterator end() const; |
942 | 942 | ||
943 | bool isEmpty() const; | 943 | bool isEmpty() const; |
944 | 944 | ||
945 | private: | 945 | private: |
946 | void flatten() const; | 946 | void flatten() const; |
947 | bool isFlat() const; | 947 | bool isFlat() const; |
948 | 948 | ||
949 | public: | 949 | public: |
950 | class FormatProxyEndAction | 950 | class FormatProxyEndAction |
951 | { | 951 | { |
952 | public: | 952 | public: |
953 | virtual ~FormatProxyEndAction() { }; | 953 | virtual ~FormatProxyEndAction() { }; |
954 | virtual void operator()( const Bu::String &sFinal )=0; | 954 | virtual void operator()( const Bu::String &sFinal )=0; |
955 | }; | 955 | }; |
956 | 956 | ||
957 | class FormatProxy | 957 | class FormatProxy |
958 | { | 958 | { |
959 | friend class Bu::String; | 959 | friend class Bu::String; |
960 | private: | 960 | private: |
961 | FormatProxy( const String &rFmt, FormatProxyEndAction *pAct=NULL ); | 961 | FormatProxy( const String &rFmt, FormatProxyEndAction *pAct=NULL ); |
962 | 962 | ||
963 | public: | 963 | public: |
964 | virtual ~FormatProxy(); | 964 | virtual ~FormatProxy(); |
965 | template<typename T> | 965 | template<typename T> |
966 | FormatProxy &arg( const T &x ) | 966 | FormatProxy &arg( const T &x ) |
967 | { | 967 | { |
968 | lArgs.append( Arg( x ) ); | 968 | lArgs.append( Arg( x ) ); |
969 | 969 | ||
970 | return *this; | 970 | return *this; |
971 | } | 971 | } |
972 | 972 | ||
973 | template<typename T> | 973 | template<typename T> |
974 | FormatProxy &arg( const T &x, const Bu::Fmt &f ) | 974 | FormatProxy &arg( const T &x, const Bu::Fmt &f ) |
975 | { | 975 | { |
976 | lArgs.append( Arg( x, f ) ); | 976 | lArgs.append( Arg( x, f ) ); |
977 | 977 | ||
978 | return *this; | 978 | return *this; |
979 | } | 979 | } |
980 | 980 | ||
981 | String end() const; | 981 | String end() const; |
982 | operator String() const { return end(); } | 982 | operator String() const { return end(); } |
983 | 983 | ||
984 | private: | 984 | private: |
985 | const String &rFmt; | 985 | const String &rFmt; |
986 | class Arg | 986 | class Arg |
987 | { | 987 | { |
988 | public: | 988 | public: |
989 | template<typename T> | 989 | template<typename T> |
990 | Arg( const T &v ) : | 990 | Arg( const T &v ) : |
991 | value( v ) | 991 | value( v ) |
992 | { | 992 | { |
993 | } | 993 | } |
994 | 994 | ||
995 | template<typename T> | 995 | template<typename T> |
996 | Arg( const T &v, const Bu::Fmt &f ) : | 996 | Arg( const T &v, const Bu::Fmt &f ) : |
997 | value( v ), | 997 | value( v ), |
998 | format( f ) | 998 | format( f ) |
999 | { | 999 | { |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | Bu::Variant value; | 1002 | Bu::Variant value; |
1003 | Bu::Fmt format; | 1003 | Bu::Fmt format; |
1004 | }; | 1004 | }; |
1005 | typedef Bu::List<Arg> ArgList; | 1005 | typedef Bu::List<Arg> ArgList; |
1006 | ArgList lArgs; | 1006 | ArgList lArgs; |
1007 | FormatProxyEndAction *pAct; | 1007 | FormatProxyEndAction *pAct; |
1008 | mutable bool bOpen; | 1008 | mutable bool bOpen; |
1009 | }; | 1009 | }; |
1010 | 1010 | ||
1011 | public: | 1011 | public: |
1012 | template<typename ArgType> | 1012 | template<typename ArgType> |
1013 | FormatProxy arg( const ArgType &x ) const | 1013 | FormatProxy arg( const ArgType &x ) const |
1014 | { | 1014 | { |
1015 | return FormatProxy( *this ).arg( x ); | 1015 | return FormatProxy( *this ).arg( x ); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | template<typename ArgType> | 1018 | template<typename ArgType> |
1019 | FormatProxy arg( const ArgType &x, const Bu::Fmt &f ) const | 1019 | FormatProxy arg( const ArgType &x, const Bu::Fmt &f ) const |
1020 | { | 1020 | { |
1021 | return FormatProxy( *this ).arg( x, f ); | 1021 | return FormatProxy( *this ).arg( x, f ); |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | FormatProxy format() const | 1024 | FormatProxy format() const |
1025 | { | 1025 | { |
1026 | return FormatProxy( *this ); | 1026 | return FormatProxy( *this ); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | FormatProxy format( FormatProxyEndAction *pEndAction ) const | 1029 | FormatProxy format( FormatProxyEndAction *pEndAction ) const |
1030 | { | 1030 | { |
1031 | return FormatProxy( *this, pEndAction ); | 1031 | return FormatProxy( *this, pEndAction ); |
1032 | } | 1032 | } |
1033 | }; | 1033 | }; |
1034 | 1034 | ||
1035 | template<class T> String operator+( const T *pLeft, const String &rRight ) | 1035 | template<class T> String operator+( const T *pLeft, const String &rRight ) |
1036 | { | 1036 | { |
1037 | Bu::String ret( pLeft ); | 1037 | Bu::String ret( pLeft ); |
1038 | ret.append( rRight ); | 1038 | ret.append( rRight ); |
1039 | return ret; | 1039 | return ret; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | ArchiveBase &operator<<( ArchiveBase &ar, const String &s ); | 1042 | ArchiveBase &operator<<( ArchiveBase &ar, const String &s ); |
1043 | ArchiveBase &operator>>( ArchiveBase &ar, String &s ); | 1043 | ArchiveBase &operator>>( ArchiveBase &ar, String &s ); |
1044 | 1044 | ||
1045 | template<typename T> | 1045 | template<typename T> |
1046 | uint32_t __calcHashCode( const T &k ); | 1046 | uint32_t __calcHashCode( const T &k ); |
1047 | 1047 | ||
1048 | template<typename T> | 1048 | template<typename T> |
1049 | bool __cmpHashKeys( const T &a, const T &b ); | 1049 | bool __cmpHashKeys( const T &a, const T &b ); |
1050 | 1050 | ||
1051 | template<> uint32_t __calcHashCode<String>( const String &k ); | 1051 | template<> uint32_t __calcHashCode<String>( const String &k ); |
1052 | template<> bool __cmpHashKeys<String>( | 1052 | template<> bool __cmpHashKeys<String>( |
1053 | const String &a, const String &b ); | 1053 | const String &a, const String &b ); |
1054 | 1054 | ||
1055 | template<typename t> void __tracer_format( const t &v ); | 1055 | template<typename t> void __tracer_format( const t &v ); |
1056 | template<> void __tracer_format<String>( const String &v ); | 1056 | template<> void __tracer_format<String>( const String &v ); |
1057 | 1057 | ||
1058 | bool &operator<<( bool &dst, const String &sIn ); | 1058 | bool &operator<<( bool &dst, const String &sIn ); |
1059 | uint8_t &operator<<( uint8_t &dst, const String &sIn ); | 1059 | uint8_t &operator<<( uint8_t &dst, const String &sIn ); |
1060 | int8_t &operator<<( int8_t &dst, const String &sIn ); | 1060 | int8_t &operator<<( int8_t &dst, const String &sIn ); |
1061 | char &operator<<( char &dst, const String &sIn ); | 1061 | char &operator<<( char &dst, const String &sIn ); |
1062 | uint16_t &operator<<( uint16_t &dst, const String &sIn ); | 1062 | uint16_t &operator<<( uint16_t &dst, const String &sIn ); |
1063 | int16_t &operator<<( int16_t &dst, const String &sIn ); | 1063 | int16_t &operator<<( int16_t &dst, const String &sIn ); |
1064 | uint32_t &operator<<( uint32_t &dst, const String &sIn ); | 1064 | uint32_t &operator<<( uint32_t &dst, const String &sIn ); |
1065 | int32_t &operator<<( int32_t &dst, const String &sIn ); | 1065 | int32_t &operator<<( int32_t &dst, const String &sIn ); |
1066 | uint64_t &operator<<( uint64_t &dst, const String &sIn ); | 1066 | uint64_t &operator<<( uint64_t &dst, const String &sIn ); |
1067 | int64_t &operator<<( int64_t &dst, const String &sIn ); | 1067 | int64_t &operator<<( int64_t &dst, const String &sIn ); |
1068 | float &operator<<( float &dst, const String &sIn ); | 1068 | float &operator<<( float &dst, const String &sIn ); |
1069 | double &operator<<( double &dst, const String &sIn ); | 1069 | double &operator<<( double &dst, const String &sIn ); |
1070 | long double &operator<<( long double &dst, const String &sIn ); | 1070 | long double &operator<<( long double &dst, const String &sIn ); |
1071 | Bu::String &operator<<( Bu::String &dst, const String &sIn ); | 1071 | Bu::String &operator<<( Bu::String &dst, const String &sIn ); |
1072 | 1072 | ||
1073 | typedef Bu::List<String> StringList; | 1073 | typedef Bu::List<String> StringList; |
1074 | }; | 1074 | }; |
1075 | 1075 | ||
1076 | #endif | 1076 | #endif |
diff --git a/src/stable/substream.cpp b/src/stable/substream.cpp index 7e3729b..c55dc04 100644 --- a/src/stable/substream.cpp +++ b/src/stable/substream.cpp | |||
@@ -8,12 +8,12 @@ | |||
8 | #include "bu/substream.h" | 8 | #include "bu/substream.h" |
9 | 9 | ||
10 | Bu::SubStream::SubStream( Bu::Stream &rNext, Bu::size iSize ) : | 10 | Bu::SubStream::SubStream( Bu::Stream &rNext, Bu::size iSize ) : |
11 | Bu::Filter( rNext ), | 11 | Bu::Filter( rNext ), |
12 | iStart( 0 ), | 12 | iStart( 0 ), |
13 | iPos( 0 ), | 13 | iPos( 0 ), |
14 | iSize( iSize ) | 14 | iSize( iSize ) |
15 | { | 15 | { |
16 | iStart = rNext.tell(); | 16 | iStart = rNext.tell(); |
17 | } | 17 | } |
18 | 18 | ||
19 | Bu::SubStream::~SubStream() | 19 | Bu::SubStream::~SubStream() |
@@ -22,88 +22,88 @@ Bu::SubStream::~SubStream() | |||
22 | 22 | ||
23 | Bu::size Bu::SubStream::read( void *pBuf, Bu::size nBytes ) | 23 | Bu::size Bu::SubStream::read( void *pBuf, Bu::size nBytes ) |
24 | { | 24 | { |
25 | if( (Bu::size)nBytes > iSize-iPos ) | 25 | if( (Bu::size)nBytes > iSize-iPos ) |
26 | nBytes = iSize-iPos; | 26 | nBytes = iSize-iPos; |
27 | nBytes = rNext.read( pBuf, nBytes ); | 27 | nBytes = rNext.read( pBuf, nBytes ); |
28 | iPos += nBytes; | 28 | iPos += nBytes; |
29 | return nBytes; | 29 | return nBytes; |
30 | } | 30 | } |
31 | 31 | ||
32 | Bu::size Bu::SubStream::write( const void *pBuf, Bu::size nBytes ) | 32 | Bu::size Bu::SubStream::write( const void *pBuf, Bu::size nBytes ) |
33 | { | 33 | { |
34 | if( (Bu::size)nBytes > iSize-iPos ) | 34 | if( (Bu::size)nBytes > iSize-iPos ) |
35 | nBytes = iSize-iPos; | 35 | nBytes = iSize-iPos; |
36 | nBytes = rNext.write( pBuf, nBytes ); | 36 | nBytes = rNext.write( pBuf, nBytes ); |
37 | iPos += nBytes; | 37 | iPos += nBytes; |
38 | return nBytes; | 38 | return nBytes; |
39 | } | 39 | } |
40 | 40 | ||
41 | void Bu::SubStream::start() | 41 | void Bu::SubStream::start() |
42 | { | 42 | { |
43 | // doesn't mean anything... | 43 | // doesn't mean anything... |
44 | } | 44 | } |
45 | 45 | ||
46 | Bu::size Bu::SubStream::stop() | 46 | Bu::size Bu::SubStream::stop() |
47 | { | 47 | { |
48 | // doesn't mean anything... | 48 | // doesn't mean anything... |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | void Bu::SubStream::close() | 52 | void Bu::SubStream::close() |
53 | { | 53 | { |
54 | // don't do anything? maybe... | 54 | // don't do anything? maybe... |
55 | } | 55 | } |
56 | 56 | ||
57 | Bu::size Bu::SubStream::tell() | 57 | Bu::size Bu::SubStream::tell() |
58 | { | 58 | { |
59 | return iPos; | 59 | return iPos; |
60 | } | 60 | } |
61 | 61 | ||
62 | void Bu::SubStream::seek( Bu::size offset ) | 62 | void Bu::SubStream::seek( Bu::size offset ) |
63 | { | 63 | { |
64 | if( iPos+offset < 0 ) | 64 | if( iPos+offset < 0 ) |
65 | offset = -iPos; | 65 | offset = -iPos; |
66 | else if( iPos+offset > iSize ) | 66 | else if( iPos+offset > iSize ) |
67 | offset = iSize-iPos; | 67 | offset = iSize-iPos; |
68 | rNext.seek( offset ); | 68 | rNext.seek( offset ); |
69 | iPos += offset; | 69 | iPos += offset; |
70 | } | 70 | } |
71 | 71 | ||
72 | void Bu::SubStream::setPos( Bu::size pos ) | 72 | void Bu::SubStream::setPos( Bu::size pos ) |
73 | { | 73 | { |
74 | if( pos < 0 ) | 74 | if( pos < 0 ) |
75 | pos = 0; | 75 | pos = 0; |
76 | else if( pos > iSize ) | 76 | else if( pos > iSize ) |
77 | pos = iSize; | 77 | pos = iSize; |
78 | iPos = pos; | 78 | iPos = pos; |
79 | pos += iStart; | 79 | pos += iStart; |
80 | rNext.setPos( pos ); | 80 | rNext.setPos( pos ); |
81 | } | 81 | } |
82 | 82 | ||
83 | void Bu::SubStream::setPosEnd( Bu::size pos ) | 83 | void Bu::SubStream::setPosEnd( Bu::size pos ) |
84 | { | 84 | { |
85 | if( iSize-pos < 0 ) | 85 | if( iSize-pos < 0 ) |
86 | pos = 0; | 86 | pos = 0; |
87 | else if( iSize-pos > iSize ) | 87 | else if( iSize-pos > iSize ) |
88 | pos = iSize; | 88 | pos = iSize; |
89 | else | 89 | else |
90 | pos = iSize-pos; | 90 | pos = iSize-pos; |
91 | iPos = pos; | 91 | iPos = pos; |
92 | rNext.setPos( iStart+pos ); | 92 | rNext.setPos( iStart+pos ); |
93 | } | 93 | } |
94 | 94 | ||
95 | bool Bu::SubStream::isEos() | 95 | bool Bu::SubStream::isEos() |
96 | { | 96 | { |
97 | return rNext.isEos() || iPos == iSize; | 97 | return rNext.isEos() || iPos == iSize; |
98 | } | 98 | } |
99 | 99 | ||
100 | bool Bu::SubStream::canRead() | 100 | bool Bu::SubStream::canRead() |
101 | { | 101 | { |
102 | return rNext.canRead() && (iPos < iSize); | 102 | return rNext.canRead() && (iPos < iSize); |
103 | } | 103 | } |
104 | 104 | ||
105 | bool Bu::SubStream::canWrite() | 105 | bool Bu::SubStream::canWrite() |
106 | { | 106 | { |
107 | return rNext.canWrite() && (iPos < iSize); | 107 | return rNext.canWrite() && (iPos < iSize); |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/src/stable/substream.h b/src/stable/substream.h index 5905043..f79ed0b 100644 --- a/src/stable/substream.h +++ b/src/stable/substream.h | |||
@@ -12,52 +12,52 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * Creates a sub-stream of a given stream. This allows you to read and | 16 | * Creates a sub-stream of a given stream. This allows you to read and |
17 | * write safely to a section of another stream, keeping all data within | 17 | * write safely to a section of another stream, keeping all data within |
18 | * the given bounds. The substream acts exactly like a top level stream | 18 | * the given bounds. The substream acts exactly like a top level stream |
19 | * when you reach the bounds of either the containing stream or the | 19 | * when you reach the bounds of either the containing stream or the |
20 | * artificial bounds of the substream, except that unlike many stream types, | 20 | * artificial bounds of the substream, except that unlike many stream types, |
21 | * when writing you cannot move beyond the bounds of the substream. Reads, | 21 | * when writing you cannot move beyond the bounds of the substream. Reads, |
22 | * on the other hand, work exactly the same way, returning less data than | 22 | * on the other hand, work exactly the same way, returning less data than |
23 | * requested when the end of the stream is reached. | 23 | * requested when the end of the stream is reached. |
24 | * | 24 | * |
25 | * The substream always begins at the current position in the base stream, | 25 | * The substream always begins at the current position in the base stream, |
26 | * if you would like to skip some data first, simply seek. | 26 | * if you would like to skip some data first, simply seek. |
27 | * | 27 | * |
28 | * The substream class is safe to use with all blocking and non-blocking | 28 | * The substream class is safe to use with all blocking and non-blocking |
29 | * base streams, including sockets, however it can have unpredictable | 29 | * base streams, including sockets, however it can have unpredictable |
30 | * results when used on a buffering stream that may read more data than | 30 | * results when used on a buffering stream that may read more data than |
31 | * requested in order to complete a request such as the buffer or bzip2 | 31 | * requested in order to complete a request such as the buffer or bzip2 |
32 | * filters. | 32 | * filters. |
33 | */ | 33 | */ |
34 | class SubStream : public Bu::Filter | 34 | class SubStream : public Bu::Filter |
35 | { | 35 | { |
36 | public: | 36 | public: |
37 | SubStream( Bu::Stream &rNext, Bu::size iSize ); | 37 | SubStream( Bu::Stream &rNext, Bu::size iSize ); |
38 | virtual ~SubStream(); | 38 | virtual ~SubStream(); |
39 | 39 | ||
40 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); | 40 | virtual Bu::size read( void *pBuf, Bu::size nBytes ); |
41 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); | 41 | virtual Bu::size write( const void *pBuf, Bu::size nBytes ); |
42 | using Bu::Stream::write; | 42 | using Bu::Stream::write; |
43 | 43 | ||
44 | virtual void start(); | 44 | virtual void start(); |
45 | virtual Bu::size stop(); | 45 | virtual Bu::size stop(); |
46 | virtual void close(); | 46 | virtual void close(); |
47 | virtual Bu::size tell(); | 47 | virtual Bu::size tell(); |
48 | virtual void seek( Bu::size offset ); | 48 | virtual void seek( Bu::size offset ); |
49 | virtual void setPos( Bu::size pos ); | 49 | virtual void setPos( Bu::size pos ); |
50 | virtual void setPosEnd( Bu::size pos ); | 50 | virtual void setPosEnd( Bu::size pos ); |
51 | virtual bool isEos(); | 51 | virtual bool isEos(); |
52 | 52 | ||
53 | virtual bool canRead(); | 53 | virtual bool canRead(); |
54 | virtual bool canWrite(); | 54 | virtual bool canWrite(); |
55 | 55 | ||
56 | protected: | 56 | protected: |
57 | Bu::size iStart; | 57 | Bu::size iStart; |
58 | Bu::size iPos; | 58 | Bu::size iPos; |
59 | Bu::size iSize; | 59 | Bu::size iSize; |
60 | }; | 60 | }; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #endif | 63 | #endif |
diff --git a/src/stable/synchroatom.h b/src/stable/synchroatom.h index 2822b20..1d996b6 100644 --- a/src/stable/synchroatom.h +++ b/src/stable/synchroatom.h | |||
@@ -14,50 +14,50 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | /** | 17 | /** |
18 | * A thread-safe wrapper class. | 18 | * A thread-safe wrapper class. |
19 | *@ingroup Threading | 19 | *@ingroup Threading |
20 | */ | 20 | */ |
21 | template <class T> | 21 | template <class T> |
22 | class SynchroAtom | 22 | class SynchroAtom |
23 | { | 23 | { |
24 | public: | 24 | public: |
25 | /** | 25 | /** |
26 | * Construct an empty queue. | 26 | * Construct an empty queue. |
27 | */ | 27 | */ |
28 | SynchroAtom() | 28 | SynchroAtom() |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | SynchroAtom( const T &src ) : | 32 | SynchroAtom( const T &src ) : |
33 | data( src ) | 33 | data( src ) |
34 | { | 34 | { |
35 | } | 35 | } |
36 | 36 | ||
37 | ~SynchroAtom() | 37 | ~SynchroAtom() |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | T get() | 41 | T get() |
42 | { | 42 | { |
43 | mOperate.lock(); | 43 | mOperate.lock(); |
44 | T ret = data; | 44 | T ret = data; |
45 | mOperate.unlock(); | 45 | mOperate.unlock(); |
46 | return ret; | 46 | return ret; |
47 | } | 47 | } |
48 | 48 | ||
49 | void set( const T &val ) | 49 | void set( const T &val ) |
50 | { | 50 | { |
51 | mOperate.lock(); | 51 | mOperate.lock(); |
52 | data = val; | 52 | data = val; |
53 | mOperate.unlock(); | 53 | mOperate.unlock(); |
54 | } | 54 | } |
55 | 55 | ||
56 | private: | 56 | private: |
57 | T data; | 57 | T data; |
58 | 58 | ||
59 | Mutex mOperate; /**< The master mutex, used on all operations. */ | 59 | Mutex mOperate; /**< The master mutex, used on all operations. */ |
60 | }; | 60 | }; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #endif | 63 | #endif |
diff --git a/src/stable/synchrocounter.h b/src/stable/synchrocounter.h index ef86445..17de890 100644 --- a/src/stable/synchrocounter.h +++ b/src/stable/synchrocounter.h | |||
@@ -12,38 +12,38 @@ | |||
12 | 12 | ||
13 | namespace Bu | 13 | namespace Bu |
14 | { | 14 | { |
15 | /** | 15 | /** |
16 | * A simple thread-safe counter class. This is handy for assigning unique | 16 | * A simple thread-safe counter class. This is handy for assigning unique |
17 | * IDs to objects that are being created in different threads. | 17 | * IDs to objects that are being created in different threads. |
18 | *@ingroup Threading Containers | 18 | *@ingroup Threading Containers |
19 | */ | 19 | */ |
20 | template <class T> | 20 | template <class T> |
21 | class SynchroCounter | 21 | class SynchroCounter |
22 | { | 22 | { |
23 | public: | 23 | public: |
24 | SynchroCounter() : | 24 | SynchroCounter() : |
25 | tCounter( 0 ) | 25 | tCounter( 0 ) |
26 | { | 26 | { |
27 | } | 27 | } |
28 | 28 | ||
29 | virtual ~SynchroCounter() | 29 | virtual ~SynchroCounter() |
30 | { | 30 | { |
31 | } | 31 | } |
32 | 32 | ||
33 | T next() | 33 | T next() |
34 | { | 34 | { |
35 | mOperate.lock(); | 35 | mOperate.lock(); |
36 | T tRet = tCounter; | 36 | T tRet = tCounter; |
37 | tCounter++; | 37 | tCounter++; |
38 | mOperate.unlock(); | 38 | mOperate.unlock(); |
39 | 39 | ||
40 | return tRet; | 40 | return tRet; |
41 | } | 41 | } |
42 | 42 | ||
43 | private: | 43 | private: |
44 | T tCounter; /**< The counter itself. */ | 44 | T tCounter; /**< The counter itself. */ |
45 | Mutex mOperate; /**< The master mutex, used on all operations. */ | 45 | Mutex mOperate; /**< The master mutex, used on all operations. */ |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/synchroheap.h b/src/stable/synchroheap.h index 9448625..f5216bf 100644 --- a/src/stable/synchroheap.h +++ b/src/stable/synchroheap.h | |||
@@ -14,137 +14,137 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | template<typename item, typename cmpfunc=__basicLTCmp<item>, | 17 | template<typename item, typename cmpfunc=__basicLTCmp<item>, |
18 | typename itemalloc=std::allocator<item> > | 18 | typename itemalloc=std::allocator<item> > |
19 | class SynchroHeap | 19 | class SynchroHeap |
20 | { | 20 | { |
21 | public: | 21 | public: |
22 | SynchroHeap() | 22 | SynchroHeap() |
23 | { | 23 | { |
24 | } | 24 | } |
25 | 25 | ||
26 | virtual ~SynchroHeap() | 26 | virtual ~SynchroHeap() |
27 | { | 27 | { |
28 | } | 28 | } |
29 | 29 | ||
30 | void enqueue( item i ) | 30 | void enqueue( item i ) |
31 | { | 31 | { |
32 | imData.lock(); | 32 | imData.lock(); |
33 | hData.enqueue( i ); | 33 | hData.enqueue( i ); |
34 | icBlock.signal(); | 34 | icBlock.signal(); |
35 | imData.unlock(); | 35 | imData.unlock(); |
36 | } | 36 | } |
37 | 37 | ||
38 | item dequeue( bool bBlock=false ) | 38 | item dequeue( bool bBlock=false ) |
39 | { | 39 | { |
40 | imData.lock(); | 40 | imData.lock(); |
41 | if( hData.isEmpty() ) | 41 | if( hData.isEmpty() ) |
42 | { | 42 | { |
43 | imData.unlock(); | 43 | imData.unlock(); |
44 | 44 | ||
45 | if( bBlock ) | 45 | if( bBlock ) |
46 | { | 46 | { |
47 | icBlock.lock(); | 47 | icBlock.lock(); |
48 | 48 | ||
49 | while( hData.isEmpty() ) | 49 | while( hData.isEmpty() ) |
50 | icBlock.wait(); | 50 | icBlock.wait(); |
51 | 51 | ||
52 | imData.lock(); | 52 | imData.lock(); |
53 | try | 53 | try |
54 | { | 54 | { |
55 | item iRet = hData.dequeue(); | 55 | item iRet = hData.dequeue(); |
56 | imData.unlock(); | 56 | imData.unlock(); |
57 | icBlock.unlock(); | 57 | icBlock.unlock(); |
58 | return iRet; | 58 | return iRet; |
59 | } | 59 | } |
60 | catch(...) | 60 | catch(...) |
61 | { | 61 | { |
62 | imData.unlock(); | 62 | imData.unlock(); |
63 | icBlock.unlock(); | 63 | icBlock.unlock(); |
64 | throw; | 64 | throw; |
65 | } | 65 | } |
66 | } | 66 | } |
67 | throw HeapException("Heap empty."); | 67 | throw HeapException("Heap empty."); |
68 | } | 68 | } |
69 | else | 69 | else |
70 | { | 70 | { |
71 | try | 71 | try |
72 | { | 72 | { |
73 | item iRet = hData.dequeue(); | 73 | item iRet = hData.dequeue(); |
74 | imData.unlock(); | 74 | imData.unlock(); |
75 | return iRet; | 75 | return iRet; |
76 | } | 76 | } |
77 | catch(...) | 77 | catch(...) |
78 | { | 78 | { |
79 | imData.unlock(); | 79 | imData.unlock(); |
80 | throw; | 80 | throw; |
81 | } | 81 | } |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | item dequeue( int iSec, int iUSec ) | 85 | item dequeue( int iSec, int iUSec ) |
86 | { | 86 | { |
87 | imData.lock(); | 87 | imData.lock(); |
88 | if( hData.isEmpty() ) | 88 | if( hData.isEmpty() ) |
89 | { | 89 | { |
90 | imData.unlock(); | 90 | imData.unlock(); |
91 | 91 | ||
92 | icBlock.lock(); | 92 | icBlock.lock(); |
93 | 93 | ||
94 | icBlock.wait( iSec, iUSec ); | 94 | icBlock.wait( iSec, iUSec ); |
95 | 95 | ||
96 | imData.lock(); | 96 | imData.lock(); |
97 | try | 97 | try |
98 | { | 98 | { |
99 | item iRet = hData.dequeue(); | 99 | item iRet = hData.dequeue(); |
100 | imData.unlock(); | 100 | imData.unlock(); |
101 | icBlock.unlock(); | 101 | icBlock.unlock(); |
102 | return iRet; | 102 | return iRet; |
103 | } | 103 | } |
104 | catch(...) | 104 | catch(...) |
105 | { | 105 | { |
106 | imData.unlock(); | 106 | imData.unlock(); |
107 | icBlock.unlock(); | 107 | icBlock.unlock(); |
108 | throw; | 108 | throw; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | else | 111 | else |
112 | { | 112 | { |
113 | try | 113 | try |
114 | { | 114 | { |
115 | item iRet = hData.dequeue(); | 115 | item iRet = hData.dequeue(); |
116 | imData.unlock(); | 116 | imData.unlock(); |
117 | return iRet; | 117 | return iRet; |
118 | } | 118 | } |
119 | catch(...) | 119 | catch(...) |
120 | { | 120 | { |
121 | imData.unlock(); | 121 | imData.unlock(); |
122 | throw; | 122 | throw; |
123 | } | 123 | } |
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | bool isEmpty() | 127 | bool isEmpty() |
128 | { | 128 | { |
129 | imData.lock(); | 129 | imData.lock(); |
130 | bool bRet = hData.isEmpty(); | 130 | bool bRet = hData.isEmpty(); |
131 | imData.unlock(); | 131 | imData.unlock(); |
132 | return bRet; | 132 | return bRet; |
133 | } | 133 | } |
134 | 134 | ||
135 | int getSize() | 135 | int getSize() |
136 | { | 136 | { |
137 | imData.lock(); | 137 | imData.lock(); |
138 | int iRet = hData.getSize(); | 138 | int iRet = hData.getSize(); |
139 | imData.unlock(); | 139 | imData.unlock(); |
140 | return iRet; | 140 | return iRet; |
141 | } | 141 | } |
142 | 142 | ||
143 | private: | 143 | private: |
144 | Heap< item, cmpfunc, itemalloc > hData; | 144 | Heap< item, cmpfunc, itemalloc > hData; |
145 | Mutex imData; | 145 | Mutex imData; |
146 | Condition icBlock; | 146 | Condition icBlock; |
147 | }; | 147 | }; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | #endif | 150 | #endif |
diff --git a/src/stable/synchroqueue.h b/src/stable/synchroqueue.h index 1c16e15..8dbedba 100644 --- a/src/stable/synchroqueue.h +++ b/src/stable/synchroqueue.h | |||
@@ -15,233 +15,233 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | /** | 18 | /** |
19 | * A thread-safe queue class. This class is a very simple queue with some | 19 | * A thread-safe queue class. This class is a very simple queue with some |
20 | * cool extra functionality for use with the Synchro system. The main extra | 20 | * cool extra functionality for use with the Synchro system. The main extra |
21 | * that it provides is the option to either dequeue without blocking, with | 21 | * that it provides is the option to either dequeue without blocking, with |
22 | * infinite blocking, or with timed blocking, which will return a value if | 22 | * infinite blocking, or with timed blocking, which will return a value if |
23 | * something is enqueued within the specified time limit, or NULL if the | 23 | * something is enqueued within the specified time limit, or NULL if the |
24 | * time limit is exceded. | 24 | * time limit is exceded. |
25 | *@ingroup Threading Containers | 25 | *@ingroup Threading Containers |
26 | */ | 26 | */ |
27 | template <class T> | 27 | template <class T> |
28 | class SynchroQueue | 28 | class SynchroQueue |
29 | { | 29 | { |
30 | private: | 30 | private: |
31 | /** | 31 | /** |
32 | * Helper struct. Keeps track of linked-list items for the queue data. | 32 | * Helper struct. Keeps track of linked-list items for the queue data. |
33 | */ | 33 | */ |
34 | typedef struct Item | 34 | typedef struct Item |
35 | { | 35 | { |
36 | T pData; | 36 | T pData; |
37 | Item *pNext; | 37 | Item *pNext; |
38 | } Item; | 38 | } Item; |
39 | 39 | ||
40 | public: | 40 | public: |
41 | /** | 41 | /** |
42 | * Construct an empty queue. | 42 | * Construct an empty queue. |
43 | */ | 43 | */ |
44 | SynchroQueue() : | 44 | SynchroQueue() : |
45 | pStart( NULL ), | 45 | pStart( NULL ), |
46 | pEnd( NULL ), | 46 | pEnd( NULL ), |
47 | nSize( 0 ) | 47 | nSize( 0 ) |
48 | { | 48 | { |
49 | } | 49 | } |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * Destroy the queue. This function will simply free all contained | 52 | * Destroy the queue. This function will simply free all contained |
53 | * structures. If you stored pointers in the queue, this will lose the | 53 | * structures. If you stored pointers in the queue, this will lose the |
54 | * pointers without cleaning up the memory they pointed to. Make sure | 54 | * pointers without cleaning up the memory they pointed to. Make sure |
55 | * you're queue is empty before allowing it to be destroyed! | 55 | * you're queue is empty before allowing it to be destroyed! |
56 | */ | 56 | */ |
57 | ~SynchroQueue() | 57 | ~SynchroQueue() |
58 | { | 58 | { |
59 | cBlock.lock(); | 59 | cBlock.lock(); |
60 | Item *pCur = pStart; | 60 | Item *pCur = pStart; |
61 | while( pCur ) | 61 | while( pCur ) |
62 | { | 62 | { |
63 | Item *pTmp = pCur->pNext; | 63 | Item *pTmp = pCur->pNext; |
64 | delete pCur; | 64 | delete pCur; |
65 | pCur = pTmp; | 65 | pCur = pTmp; |
66 | } | 66 | } |
67 | cBlock.unlock(); | 67 | cBlock.unlock(); |
68 | } | 68 | } |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Enqueue a pieces of data. The new data will go at the end of the | 71 | * Enqueue a pieces of data. The new data will go at the end of the |
72 | * queue, and unless another piece of data is enqueued, will be the | 72 | * queue, and unless another piece of data is enqueued, will be the |
73 | * last piece of data to be dequeued. | 73 | * last piece of data to be dequeued. |
74 | *@param pData The data to enqueue. If this is not a primitive data | 74 | *@param pData The data to enqueue. If this is not a primitive data |
75 | * type it's probably best to use a pointer type. | 75 | * type it's probably best to use a pointer type. |
76 | */ | 76 | */ |
77 | void enqueue( T pData ) | 77 | void enqueue( T pData ) |
78 | { | 78 | { |
79 | cBlock.lock(); | 79 | cBlock.lock(); |
80 | 80 | ||
81 | if( pStart == NULL ) | 81 | if( pStart == NULL ) |
82 | { | 82 | { |
83 | pStart = pEnd = new Item; | 83 | pStart = pEnd = new Item; |
84 | pStart->pData = pData; | 84 | pStart->pData = pData; |
85 | pStart->pNext = NULL; | 85 | pStart->pNext = NULL; |
86 | nSize++; | 86 | nSize++; |
87 | } | 87 | } |
88 | else | 88 | else |
89 | { | 89 | { |
90 | pEnd->pNext = new Item; | 90 | pEnd->pNext = new Item; |
91 | pEnd = pEnd->pNext; | 91 | pEnd = pEnd->pNext; |
92 | pEnd->pData = pData; | 92 | pEnd->pData = pData; |
93 | pEnd->pNext = NULL; | 93 | pEnd->pNext = NULL; |
94 | nSize++; | 94 | nSize++; |
95 | } | 95 | } |
96 | 96 | ||
97 | cBlock.signal(); | 97 | cBlock.signal(); |
98 | 98 | ||
99 | cBlock.unlock(); | 99 | cBlock.unlock(); |
100 | } | 100 | } |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Dequeue the first item from the queue. This function can operate in | 103 | * Dequeue the first item from the queue. This function can operate in |
104 | * two different modes, blocking and non-blocking. In non-blocking | 104 | * two different modes, blocking and non-blocking. In non-blocking |
105 | * mode it will return immediately weather there was data in the queue | 105 | * mode it will return immediately weather there was data in the queue |
106 | * or not. If there was data it will remove it from the queue and | 106 | * or not. If there was data it will remove it from the queue and |
107 | * return it to the caller. | 107 | * return it to the caller. |
108 | * | 108 | * |
109 | * In blocking mode it will block forever wating for data to be | 109 | * In blocking mode it will block forever wating for data to be |
110 | * enqueued. When data finally is enqueued this function will return | 110 | * enqueued. When data finally is enqueued this function will return |
111 | * immediately with the new data. The only way this function should | 111 | * immediately with the new data. The only way this function should |
112 | * ever return a null in blocking mode is if the calling thread was | 112 | * ever return a null in blocking mode is if the calling thread was |
113 | * cancelled. It's probably a good idea to check for NULL return | 113 | * cancelled. It's probably a good idea to check for NULL return |
114 | * values even if you use blocking, just to be on the safe side. | 114 | * values even if you use blocking, just to be on the safe side. |
115 | *@param bBlock Set to true to enable blocking, leave as false to work | 115 | *@param bBlock Set to true to enable blocking, leave as false to work |
116 | * in non-blocking mode. | 116 | * in non-blocking mode. |
117 | *@returns The next piece of data in the queue, or NULL if no data was | 117 | *@returns The next piece of data in the queue, or NULL if no data was |
118 | * in the queue. | 118 | * in the queue. |
119 | */ | 119 | */ |
120 | T dequeue( bool bBlock=false ) | 120 | T dequeue( bool bBlock=false ) |
121 | { | 121 | { |
122 | cBlock.lock(); | 122 | cBlock.lock(); |
123 | if( pStart == NULL ) | 123 | if( pStart == NULL ) |
124 | { | 124 | { |
125 | if( bBlock ) | 125 | if( bBlock ) |
126 | { | 126 | { |
127 | cBlock.wait(); | 127 | cBlock.wait(); |
128 | 128 | ||
129 | if( pStart == NULL ) | 129 | if( pStart == NULL ) |
130 | { | 130 | { |
131 | cBlock.unlock(); | 131 | cBlock.unlock(); |
132 | return NULL; | 132 | return NULL; |
133 | } | 133 | } |
134 | T pTmp = pStart->pData; | 134 | T pTmp = pStart->pData; |
135 | Item *pDel = pStart; | 135 | Item *pDel = pStart; |
136 | pStart = pStart->pNext; | 136 | pStart = pStart->pNext; |
137 | delete pDel; | 137 | delete pDel; |
138 | nSize--; | 138 | nSize--; |
139 | 139 | ||
140 | cBlock.unlock(); | 140 | cBlock.unlock(); |
141 | return pTmp; | 141 | return pTmp; |
142 | 142 | ||
143 | } | 143 | } |
144 | 144 | ||
145 | cBlock.unlock(); | 145 | cBlock.unlock(); |
146 | return NULL; | 146 | return NULL; |
147 | } | 147 | } |
148 | else | 148 | else |
149 | { | 149 | { |
150 | T pTmp = pStart->pData; | 150 | T pTmp = pStart->pData; |
151 | Item *pDel = pStart; | 151 | Item *pDel = pStart; |
152 | pStart = pStart->pNext; | 152 | pStart = pStart->pNext; |
153 | delete pDel; | 153 | delete pDel; |
154 | nSize--; | 154 | nSize--; |
155 | 155 | ||
156 | cBlock.unlock(); | 156 | cBlock.unlock(); |
157 | return pTmp; | 157 | return pTmp; |
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * Operates just like the other dequeue function in blocking mode with | 162 | * Operates just like the other dequeue function in blocking mode with |
163 | * one twist. This function will block for at most nSec seconds and | 163 | * one twist. This function will block for at most nSec seconds and |
164 | * nUSec micro-seconds. If the timer is up and no data is available, | 164 | * nUSec micro-seconds. If the timer is up and no data is available, |
165 | * this will just return NULL. If data is enqueued before the timeout | 165 | * this will just return NULL. If data is enqueued before the timeout |
166 | * expires, it will dequeue and exit immediately. | 166 | * expires, it will dequeue and exit immediately. |
167 | *@param nSec The number of seconds to wait, max. | 167 | *@param nSec The number of seconds to wait, max. |
168 | *@param nUSec The number of micro-seconds to wait, max. | 168 | *@param nUSec The number of micro-seconds to wait, max. |
169 | *@returns The next piece of data in the queue, or NULL if the timeout | 169 | *@returns The next piece of data in the queue, or NULL if the timeout |
170 | * was exceeded. | 170 | * was exceeded. |
171 | */ | 171 | */ |
172 | T dequeue( int nSec, int nUSec ) | 172 | T dequeue( int nSec, int nUSec ) |
173 | { | 173 | { |
174 | cBlock.lock(); | 174 | cBlock.lock(); |
175 | if( pStart == NULL ) | 175 | if( pStart == NULL ) |
176 | { | 176 | { |
177 | cBlock.wait( nSec, nUSec ); | 177 | cBlock.wait( nSec, nUSec ); |
178 | 178 | ||
179 | if( pStart == NULL ) | 179 | if( pStart == NULL ) |
180 | { | 180 | { |
181 | cBlock.unlock(); | 181 | cBlock.unlock(); |
182 | return NULL; | 182 | return NULL; |
183 | } | 183 | } |
184 | 184 | ||
185 | T pTmp = pStart->pData; | 185 | T pTmp = pStart->pData; |
186 | Item *pDel = pStart; | 186 | Item *pDel = pStart; |
187 | pStart = pStart->pNext; | 187 | pStart = pStart->pNext; |
188 | delete pDel; | 188 | delete pDel; |
189 | nSize--; | 189 | nSize--; |
190 | 190 | ||
191 | cBlock.unlock(); | 191 | cBlock.unlock(); |
192 | return pTmp; | 192 | return pTmp; |
193 | } | 193 | } |
194 | else | 194 | else |
195 | { | 195 | { |
196 | T pTmp = pStart->pData; | 196 | T pTmp = pStart->pData; |
197 | Item *pDel = pStart; | 197 | Item *pDel = pStart; |
198 | pStart = pStart->pNext; | 198 | pStart = pStart->pNext; |
199 | delete pDel; | 199 | delete pDel; |
200 | nSize--; | 200 | nSize--; |
201 | 201 | ||
202 | cBlock.unlock(); | 202 | cBlock.unlock(); |
203 | return pTmp; | 203 | return pTmp; |
204 | } | 204 | } |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * Checks to see if the queue has data in it or not. Note that there | 208 | * Checks to see if the queue has data in it or not. Note that there |
209 | * is no function to determine the length of the queue. This data | 209 | * is no function to determine the length of the queue. This data |
210 | * isn't kept track of. If you really need to know, fix this. | 210 | * isn't kept track of. If you really need to know, fix this. |
211 | *@returns True if the queue is empty, false if it has data in it. | 211 | *@returns True if the queue is empty, false if it has data in it. |
212 | */ | 212 | */ |
213 | bool isEmpty() | 213 | bool isEmpty() |
214 | { | 214 | { |
215 | cBlock.lock(); | 215 | cBlock.lock(); |
216 | bool bEmpty = (pStart == NULL ); | 216 | bool bEmpty = (pStart == NULL ); |
217 | cBlock.unlock(); | 217 | cBlock.unlock(); |
218 | 218 | ||
219 | return bEmpty; | 219 | return bEmpty; |
220 | } | 220 | } |
221 | 221 | ||
222 | long getSize() | 222 | long getSize() |
223 | { | 223 | { |
224 | cBlock.lock(); | 224 | cBlock.lock(); |
225 | long nRet = nSize; | 225 | long nRet = nSize; |
226 | cBlock.unlock(); | 226 | cBlock.unlock(); |
227 | 227 | ||
228 | return nRet; | 228 | return nRet; |
229 | } | 229 | } |
230 | 230 | ||
231 | void unblockAll() | 231 | void unblockAll() |
232 | { | 232 | { |
233 | cBlock.lock(); | 233 | cBlock.lock(); |
234 | cBlock.broadcast(); | 234 | cBlock.broadcast(); |
235 | cBlock.unlock(); | 235 | cBlock.unlock(); |
236 | } | 236 | } |
237 | 237 | ||
238 | private: | 238 | private: |
239 | Item *pStart; /**< The start of the queue, the next element to dequeue. */ | 239 | Item *pStart; /**< The start of the queue, the next element to dequeue. */ |
240 | Item *pEnd; /**< The end of the queue, the last element to dequeue. */ | 240 | Item *pEnd; /**< The end of the queue, the last element to dequeue. */ |
241 | long nSize; /**< The number of items in the queue. */ | 241 | long nSize; /**< The number of items in the queue. */ |
242 | 242 | ||
243 | Condition cBlock; /**< The condition for blocking dequeues. */ | 243 | Condition cBlock; /**< The condition for blocking dequeues. */ |
244 | }; | 244 | }; |
245 | } | 245 | } |
246 | 246 | ||
247 | #endif | 247 | #endif |
diff --git a/src/stable/tafcomment.cpp b/src/stable/tafcomment.cpp index ceda8e3..5168685 100644 --- a/src/stable/tafcomment.cpp +++ b/src/stable/tafcomment.cpp | |||
@@ -8,16 +8,16 @@ | |||
8 | #include "bu/tafcomment.h" | 8 | #include "bu/tafcomment.h" |
9 | 9 | ||
10 | Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : | 10 | Bu::TafComment::TafComment( const Bu::TafComment &rSrc ) : |
11 | TafNode( typeComment ), | 11 | TafNode( typeComment ), |
12 | sText( rSrc.sText ), | 12 | sText( rSrc.sText ), |
13 | bEOL( rSrc.bEOL ) | 13 | bEOL( rSrc.bEOL ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::TafComment::TafComment( const Bu::String &sText, bool bEOL ) : | 17 | Bu::TafComment::TafComment( const Bu::String &sText, bool bEOL ) : |
18 | TafNode( typeComment ), | 18 | TafNode( typeComment ), |
19 | sText( sText ), | 19 | sText( sText ), |
20 | bEOL( bEOL ) | 20 | bEOL( bEOL ) |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
@@ -27,11 +27,11 @@ Bu::TafComment::~TafComment() | |||
27 | 27 | ||
28 | const Bu::String &Bu::TafComment::getText() const | 28 | const Bu::String &Bu::TafComment::getText() const |
29 | { | 29 | { |
30 | return sText; | 30 | return sText; |
31 | } | 31 | } |
32 | 32 | ||
33 | bool Bu::TafComment::isEOLStyle() const | 33 | bool Bu::TafComment::isEOLStyle() const |
34 | { | 34 | { |
35 | return bEOL; | 35 | return bEOL; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/src/stable/tafcomment.h b/src/stable/tafcomment.h index 80c6399..2f403e7 100644 --- a/src/stable/tafcomment.h +++ b/src/stable/tafcomment.h | |||
@@ -13,24 +13,24 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * | 17 | * |
18 | *@ingroup Taf | 18 | *@ingroup Taf |
19 | */ | 19 | */ |
20 | class TafComment : public TafNode | 20 | class TafComment : public TafNode |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | TafComment( const Bu::TafComment &rSrc ); | 23 | TafComment( const Bu::TafComment &rSrc ); |
24 | TafComment( const Bu::String &sText, bool bEOL=false ); | 24 | TafComment( const Bu::String &sText, bool bEOL=false ); |
25 | virtual ~TafComment(); | 25 | virtual ~TafComment(); |
26 | 26 | ||
27 | const Bu::String &getText() const; | 27 | const Bu::String &getText() const; |
28 | bool isEOLStyle() const; | 28 | bool isEOLStyle() const; |
29 | 29 | ||
30 | private: | 30 | private: |
31 | Bu::String sText; | 31 | Bu::String sText; |
32 | bool bEOL; | 32 | bool bEOL; |
33 | }; | 33 | }; |
34 | } | 34 | } |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/src/stable/tafgroup.cpp b/src/stable/tafgroup.cpp index 27af09e..7e15b26 100644 --- a/src/stable/tafgroup.cpp +++ b/src/stable/tafgroup.cpp | |||
@@ -10,215 +10,215 @@ | |||
10 | #include "bu/tafcomment.h" | 10 | #include "bu/tafcomment.h" |
11 | 11 | ||
12 | Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : | 12 | Bu::TafGroup::TafGroup( const TafGroup &rSrc ) : |
13 | TafNode( typeGroup ), | 13 | TafNode( typeGroup ), |
14 | sName( rSrc.sName ) | 14 | sName( rSrc.sName ) |
15 | { | 15 | { |
16 | for( NodeList::const_iterator i = rSrc.lChildren.begin(); i; i++ ) | 16 | for( NodeList::const_iterator i = rSrc.lChildren.begin(); i; i++ ) |
17 | { | 17 | { |
18 | switch( (*i)->getType() ) | 18 | switch( (*i)->getType() ) |
19 | { | 19 | { |
20 | case typeGroup: | 20 | case typeGroup: |
21 | addChild( new TafGroup( *dynamic_cast<const TafGroup *>(*i) ) ); | 21 | addChild( new TafGroup( *dynamic_cast<const TafGroup *>(*i) ) ); |
22 | break; | 22 | break; |
23 | 23 | ||
24 | case typeProperty: | 24 | case typeProperty: |
25 | addChild( new TafProperty( *dynamic_cast<const TafProperty *>(*i) ) ); | 25 | addChild( new TafProperty( *dynamic_cast<const TafProperty *>(*i) ) ); |
26 | break; | 26 | break; |
27 | 27 | ||
28 | case typeComment: | 28 | case typeComment: |
29 | addChild( new TafComment( *dynamic_cast<const TafComment *>(*i) ) ); | 29 | addChild( new TafComment( *dynamic_cast<const TafComment *>(*i) ) ); |
30 | break; | 30 | break; |
31 | } | 31 | } |
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | Bu::TafGroup::TafGroup( const Bu::String &sName ) : | 35 | Bu::TafGroup::TafGroup( const Bu::String &sName ) : |
36 | TafNode( typeGroup ), | 36 | TafNode( typeGroup ), |
37 | sName( sName ) | 37 | sName( sName ) |
38 | { | 38 | { |
39 | } | 39 | } |
40 | 40 | ||
41 | Bu::TafGroup::~TafGroup() | 41 | Bu::TafGroup::~TafGroup() |
42 | { | 42 | { |
43 | for( NodeList::iterator i = lChildren.begin(); i != lChildren.end(); i++ ) | 43 | for( NodeList::iterator i = lChildren.begin(); i != lChildren.end(); i++ ) |
44 | { | 44 | { |
45 | delete (*i); | 45 | delete (*i); |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | const Bu::String &Bu::TafGroup::getName() const | 49 | const Bu::String &Bu::TafGroup::getName() const |
50 | { | 50 | { |
51 | return sName; | 51 | return sName; |
52 | } | 52 | } |
53 | 53 | ||
54 | void Bu::TafGroup::setName( const Bu::String &sName ) | 54 | void Bu::TafGroup::setName( const Bu::String &sName ) |
55 | { | 55 | { |
56 | this->sName = sName; | 56 | this->sName = sName; |
57 | } | 57 | } |
58 | 58 | ||
59 | Bu::TafNode *Bu::TafGroup::addChild( Bu::TafNode *pNode ) | 59 | Bu::TafNode *Bu::TafGroup::addChild( Bu::TafNode *pNode ) |
60 | { | 60 | { |
61 | switch( pNode->getType() ) | 61 | switch( pNode->getType() ) |
62 | { | 62 | { |
63 | case typeGroup: | 63 | case typeGroup: |
64 | addChild( (Bu::TafGroup *)pNode ); | 64 | addChild( (Bu::TafGroup *)pNode ); |
65 | break; | 65 | break; |
66 | 66 | ||
67 | case typeProperty: | 67 | case typeProperty: |
68 | addChild( (Bu::TafProperty *)pNode ); | 68 | addChild( (Bu::TafProperty *)pNode ); |
69 | break; | 69 | break; |
70 | 70 | ||
71 | case typeComment: | 71 | case typeComment: |
72 | addChild( (Bu::TafComment *)pNode ); | 72 | addChild( (Bu::TafComment *)pNode ); |
73 | break; | 73 | break; |
74 | } | 74 | } |
75 | 75 | ||
76 | return pNode; | 76 | return pNode; |
77 | } | 77 | } |
78 | 78 | ||
79 | Bu::TafGroup *Bu::TafGroup::addChild( TafGroup *pNode ) | 79 | Bu::TafGroup *Bu::TafGroup::addChild( TafGroup *pNode ) |
80 | { | 80 | { |
81 | TafGroup *pGroup = (TafGroup *)pNode; | 81 | TafGroup *pGroup = (TafGroup *)pNode; |
82 | if( !hChildren.has( pGroup->getName() ) ) | 82 | if( !hChildren.has( pGroup->getName() ) ) |
83 | hChildren.insert( pGroup->getName(), GroupList() ); | 83 | hChildren.insert( pGroup->getName(), GroupList() ); |
84 | hChildren.get( pGroup->getName() ).append( pGroup ); | 84 | hChildren.get( pGroup->getName() ).append( pGroup ); |
85 | lChildren.append( pNode ); | 85 | lChildren.append( pNode ); |
86 | return pNode; | 86 | return pNode; |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::TafProperty *Bu::TafGroup::addChild( TafProperty *pNode ) | 89 | Bu::TafProperty *Bu::TafGroup::addChild( TafProperty *pNode ) |
90 | { | 90 | { |
91 | TafProperty *pProperty = (TafProperty *)pNode; | 91 | TafProperty *pProperty = (TafProperty *)pNode; |
92 | if( !hProp.has( pProperty->getName() ) ) | 92 | if( !hProp.has( pProperty->getName() ) ) |
93 | hProp.insert( pProperty->getName(), PropList() ); | 93 | hProp.insert( pProperty->getName(), PropList() ); |
94 | hProp.get( pProperty->getName() ).append( pProperty->getValue() ); | 94 | hProp.get( pProperty->getName() ).append( pProperty->getValue() ); |
95 | lChildren.append( pNode ); | 95 | lChildren.append( pNode ); |
96 | return pNode; | 96 | return pNode; |
97 | } | 97 | } |
98 | 98 | ||
99 | Bu::TafComment *Bu::TafGroup::addChild( TafComment *pNode ) | 99 | Bu::TafComment *Bu::TafGroup::addChild( TafComment *pNode ) |
100 | { | 100 | { |
101 | lChildren.append( pNode ); | 101 | lChildren.append( pNode ); |
102 | return pNode; | 102 | return pNode; |
103 | } | 103 | } |
104 | 104 | ||
105 | Bu::TafGroup *Bu::TafGroup::addGroup( const Bu::String &sName ) | 105 | Bu::TafGroup *Bu::TafGroup::addGroup( const Bu::String &sName ) |
106 | { | 106 | { |
107 | return addChild( new TafGroup( sName ) ); | 107 | return addChild( new TafGroup( sName ) ); |
108 | } | 108 | } |
109 | 109 | ||
110 | Bu::TafProperty *Bu::TafGroup::addProperty( | 110 | Bu::TafProperty *Bu::TafGroup::addProperty( |
111 | const Bu::String &sName, const Bu::String &sValue ) | 111 | const Bu::String &sName, const Bu::String &sValue ) |
112 | { | 112 | { |
113 | return addChild( new TafProperty( sName, sValue ) ); | 113 | return addChild( new TafProperty( sName, sValue ) ); |
114 | } | 114 | } |
115 | 115 | ||
116 | bool Bu::TafGroup::hasChild( const Bu::String &sName ) const | 116 | bool Bu::TafGroup::hasChild( const Bu::String &sName ) const |
117 | { | 117 | { |
118 | return hChildren.has( sName ); | 118 | return hChildren.has( sName ); |
119 | } | 119 | } |
120 | 120 | ||
121 | const Bu::TafGroup::GroupList &Bu::TafGroup::getChildren( const Bu::String &sName ) const | 121 | const Bu::TafGroup::GroupList &Bu::TafGroup::getChildren( const Bu::String &sName ) const |
122 | { | 122 | { |
123 | try { | 123 | try { |
124 | return hChildren.get( sName ); | 124 | return hChildren.get( sName ); |
125 | } catch( Bu::HashException &e ) | 125 | } catch( Bu::HashException &e ) |
126 | { | 126 | { |
127 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", | 127 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", |
128 | this->sName.getStr(), sName.getStr() ); | 128 | this->sName.getStr(), sName.getStr() ); |
129 | } | 129 | } |
130 | } | 130 | } |
131 | 131 | ||
132 | const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const | 132 | const Bu::TafGroup::NodeList &Bu::TafGroup::getChildren() const |
133 | { | 133 | { |
134 | return lChildren; | 134 | return lChildren; |
135 | } | 135 | } |
136 | 136 | ||
137 | const Bu::TafGroup *Bu::TafGroup::getChild( const Bu::String &sName ) const | 137 | const Bu::TafGroup *Bu::TafGroup::getChild( const Bu::String &sName ) const |
138 | { | 138 | { |
139 | try { | 139 | try { |
140 | return hChildren.get( sName ).first(); | 140 | return hChildren.get( sName ).first(); |
141 | } catch( Bu::HashException &e ) | 141 | } catch( Bu::HashException &e ) |
142 | { | 142 | { |
143 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", | 143 | throw Bu::TafException("No children of group \"%s\" match \"%s\".", |
144 | this->sName.getStr(), sName.getStr() ); | 144 | this->sName.getStr(), sName.getStr() ); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const | 148 | bool Bu::TafGroup::hasProperty( const Bu::String &sName ) const |
149 | { | 149 | { |
150 | return hProp.has( sName ); | 150 | return hProp.has( sName ); |
151 | } | 151 | } |
152 | 152 | ||
153 | const Bu::TafGroup::PropList &Bu::TafGroup::getProperties( const Bu::String &sName ) const | 153 | const Bu::TafGroup::PropList &Bu::TafGroup::getProperties( const Bu::String &sName ) const |
154 | { | 154 | { |
155 | try { | 155 | try { |
156 | return hProp.get( sName ); | 156 | return hProp.get( sName ); |
157 | } catch( Bu::HashException &e ) | 157 | } catch( Bu::HashException &e ) |
158 | { | 158 | { |
159 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", | 159 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", |
160 | this->sName.getStr(), sName.getStr() ); | 160 | this->sName.getStr(), sName.getStr() ); |
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName ) const | 164 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName ) const |
165 | { | 165 | { |
166 | try { | 166 | try { |
167 | return hProp.get( sName ).first(); | 167 | return hProp.get( sName ).first(); |
168 | } catch( Bu::HashException &e ) | 168 | } catch( Bu::HashException &e ) |
169 | { | 169 | { |
170 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", | 170 | throw Bu::TafException("No properties of group \"%s\" match \"%s\".", |
171 | this->sName.getStr(), sName.getStr() ); | 171 | this->sName.getStr(), sName.getStr() ); |
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName, | 175 | const Bu::String &Bu::TafGroup::getProperty( const Bu::String &sName, |
176 | const Bu::String &sDef ) const | 176 | const Bu::String &sDef ) const |
177 | { | 177 | { |
178 | try | 178 | try |
179 | { | 179 | { |
180 | return hProp.get( sName ).first(); | 180 | return hProp.get( sName ).first(); |
181 | } | 181 | } |
182 | catch( Bu::HashException &e ) | 182 | catch( Bu::HashException &e ) |
183 | { | 183 | { |
184 | return sDef; | 184 | return sDef; |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( | 188 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( |
189 | const Bu::String &sPath ) const | 189 | const Bu::String &sPath ) const |
190 | { | 190 | { |
191 | return getChildByPath( sPath.split('/') ); | 191 | return getChildByPath( sPath.split('/') ); |
192 | } | 192 | } |
193 | 193 | ||
194 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const | 194 | const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const |
195 | { | 195 | { |
196 | const Bu::TafGroup *cur = this; | 196 | const Bu::TafGroup *cur = this; |
197 | 197 | ||
198 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) | 198 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) |
199 | { | 199 | { |
200 | cur = cur->getChild( *i ); | 200 | cur = cur->getChild( *i ); |
201 | } | 201 | } |
202 | 202 | ||
203 | return cur; | 203 | return cur; |
204 | } | 204 | } |
205 | 205 | ||
206 | const Bu::String &Bu::TafGroup::getByPath( const Bu::String &sPath ) const | 206 | const Bu::String &Bu::TafGroup::getByPath( const Bu::String &sPath ) const |
207 | { | 207 | { |
208 | return getByPath( sPath.split('/') ); | 208 | return getByPath( sPath.split('/') ); |
209 | } | 209 | } |
210 | 210 | ||
211 | const Bu::String &Bu::TafGroup::getByPath( Bu::StrList lPath ) const | 211 | const Bu::String &Bu::TafGroup::getByPath( Bu::StrList lPath ) const |
212 | { | 212 | { |
213 | const Bu::TafGroup *cur = this; | 213 | const Bu::TafGroup *cur = this; |
214 | 214 | ||
215 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) | 215 | for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ ) |
216 | { | 216 | { |
217 | if( !(i+1) ) | 217 | if( !(i+1) ) |
218 | break; | 218 | break; |
219 | cur = cur->getChild( *i ); | 219 | cur = cur->getChild( *i ); |
220 | } | 220 | } |
221 | 221 | ||
222 | return cur->getProperty( lPath.last() ); | 222 | return cur->getProperty( lPath.last() ); |
223 | } | 223 | } |
224 | 224 | ||
diff --git a/src/stable/tafgroup.h b/src/stable/tafgroup.h index 3f52ab3..a22059e 100644 --- a/src/stable/tafgroup.h +++ b/src/stable/tafgroup.h | |||
@@ -16,56 +16,56 @@ | |||
16 | 16 | ||
17 | namespace Bu | 17 | namespace Bu |
18 | { | 18 | { |
19 | typedef Bu::List<Bu::String> StrList; | 19 | typedef Bu::List<Bu::String> StrList; |
20 | class TafProperty; | 20 | class TafProperty; |
21 | class TafComment; | 21 | class TafComment; |
22 | /** | 22 | /** |
23 | * | 23 | * |
24 | *@ingroup Taf | 24 | *@ingroup Taf |
25 | */ | 25 | */ |
26 | class TafGroup : public TafNode | 26 | class TafGroup : public TafNode |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | typedef Bu::List<Bu::String> PropList; | 29 | typedef Bu::List<Bu::String> PropList; |
30 | typedef Bu::Hash<Bu::String, PropList> PropHash; | 30 | typedef Bu::Hash<Bu::String, PropList> PropHash; |
31 | typedef Bu::List<class Bu::TafGroup *> GroupList; | 31 | typedef Bu::List<class Bu::TafGroup *> GroupList; |
32 | typedef Bu::Hash<Bu::String, GroupList> GroupHash; | 32 | typedef Bu::Hash<Bu::String, GroupList> GroupHash; |
33 | typedef Bu::List<class Bu::TafNode *> NodeList; | 33 | typedef Bu::List<class Bu::TafNode *> NodeList; |
34 | 34 | ||
35 | TafGroup( const TafGroup &rSrc ); | 35 | TafGroup( const TafGroup &rSrc ); |
36 | TafGroup( const Bu::String &sName ); | 36 | TafGroup( const Bu::String &sName ); |
37 | virtual ~TafGroup(); | 37 | virtual ~TafGroup(); |
38 | 38 | ||
39 | const Bu::String &getName() const; | 39 | const Bu::String &getName() const; |
40 | void setName( const Bu::String &sName ); | 40 | void setName( const Bu::String &sName ); |
41 | 41 | ||
42 | bool hasProperty( const Bu::String &sName ) const; | 42 | bool hasProperty( const Bu::String &sName ) const; |
43 | const Bu::String &getProperty( const Bu::String &sName ) const; | 43 | const Bu::String &getProperty( const Bu::String &sName ) const; |
44 | const Bu::String &getProperty( const Bu::String &sName, | 44 | const Bu::String &getProperty( const Bu::String &sName, |
45 | const Bu::String &sDef ) const; | 45 | const Bu::String &sDef ) const; |
46 | const PropList &getProperties( const Bu::String &sName ) const; | 46 | const PropList &getProperties( const Bu::String &sName ) const; |
47 | bool hasChild( const Bu::String &sName ) const; | 47 | bool hasChild( const Bu::String &sName ) const; |
48 | const TafGroup *getChild( const Bu::String &sName ) const; | 48 | const TafGroup *getChild( const Bu::String &sName ) const; |
49 | const GroupList &getChildren( const Bu::String &sName ) const; | 49 | const GroupList &getChildren( const Bu::String &sName ) const; |
50 | TafNode *addChild( TafNode *pNode ); | 50 | TafNode *addChild( TafNode *pNode ); |
51 | TafGroup *addChild( TafGroup *pNode ); | 51 | TafGroup *addChild( TafGroup *pNode ); |
52 | TafProperty *addChild( TafProperty *pNode ); | 52 | TafProperty *addChild( TafProperty *pNode ); |
53 | TafComment *addChild( TafComment *pNode ); | 53 | TafComment *addChild( TafComment *pNode ); |
54 | TafGroup *addGroup( const Bu::String &sName ); | 54 | TafGroup *addGroup( const Bu::String &sName ); |
55 | TafProperty *addProperty( | 55 | TafProperty *addProperty( |
56 | const Bu::String &sName, const Bu::String &sValue ); | 56 | const Bu::String &sName, const Bu::String &sValue ); |
57 | const NodeList &getChildren() const; | 57 | const NodeList &getChildren() const; |
58 | const TafGroup *getChildByPath( const Bu::String &sPath ) const; | 58 | const TafGroup *getChildByPath( const Bu::String &sPath ) const; |
59 | const TafGroup *getChildByPath( StrList lPath ) const; | 59 | const TafGroup *getChildByPath( StrList lPath ) const; |
60 | const Bu::String &getByPath( const Bu::String &sPath ) const; | 60 | const Bu::String &getByPath( const Bu::String &sPath ) const; |
61 | const Bu::String &getByPath( StrList lPath ) const; | 61 | const Bu::String &getByPath( StrList lPath ) const; |
62 | 62 | ||
63 | private: | 63 | private: |
64 | Bu::String sName; | 64 | Bu::String sName; |
65 | PropHash hProp; | 65 | PropHash hProp; |
66 | GroupHash hChildren; | 66 | GroupHash hChildren; |
67 | NodeList lChildren; | 67 | NodeList lChildren; |
68 | }; | 68 | }; |
69 | } | 69 | } |
70 | 70 | ||
71 | #endif | 71 | #endif |
diff --git a/src/stable/tafnode.cpp b/src/stable/tafnode.cpp index 630bcce..10ba89a 100644 --- a/src/stable/tafnode.cpp +++ b/src/stable/tafnode.cpp | |||
@@ -10,7 +10,7 @@ | |||
10 | namespace Bu { subExceptionDef( TafException ) } | 10 | namespace Bu { subExceptionDef( TafException ) } |
11 | 11 | ||
12 | Bu::TafNode::TafNode( NodeType eType ) : | 12 | Bu::TafNode::TafNode( NodeType eType ) : |
13 | eType( eType ) | 13 | eType( eType ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,6 +20,6 @@ Bu::TafNode::~TafNode() | |||
20 | 20 | ||
21 | Bu::TafNode::NodeType Bu::TafNode::getType() const | 21 | Bu::TafNode::NodeType Bu::TafNode::getType() const |
22 | { | 22 | { |
23 | return eType; | 23 | return eType; |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/src/stable/tafnode.h b/src/stable/tafnode.h index 9c0e0b9..923ee24 100644 --- a/src/stable/tafnode.h +++ b/src/stable/tafnode.h | |||
@@ -15,30 +15,30 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( TafException ); | 18 | subExceptionDecl( TafException ); |
19 | /** | 19 | /** |
20 | * | 20 | * |
21 | *@ingroup Taf | 21 | *@ingroup Taf |
22 | */ | 22 | */ |
23 | class TafNode | 23 | class TafNode |
24 | { | 24 | { |
25 | public: | 25 | public: |
26 | enum NodeType | 26 | enum NodeType |
27 | { | 27 | { |
28 | typeGroup, | 28 | typeGroup, |
29 | typeProperty, | 29 | typeProperty, |
30 | typeComment | 30 | typeComment |
31 | }; | 31 | }; |
32 | 32 | ||
33 | public: | 33 | public: |
34 | TafNode( NodeType eType ); | 34 | TafNode( NodeType eType ); |
35 | virtual ~TafNode(); | 35 | virtual ~TafNode(); |
36 | 36 | ||
37 | NodeType getType() const; | 37 | NodeType getType() const; |
38 | 38 | ||
39 | private: | 39 | private: |
40 | NodeType eType; | 40 | NodeType eType; |
41 | }; | 41 | }; |
42 | } | 42 | } |
43 | 43 | ||
44 | #endif | 44 | #endif |
diff --git a/src/stable/tafproperty.cpp b/src/stable/tafproperty.cpp index 017b294..2b3e338 100644 --- a/src/stable/tafproperty.cpp +++ b/src/stable/tafproperty.cpp | |||
@@ -8,16 +8,16 @@ | |||
8 | #include "bu/tafproperty.h" | 8 | #include "bu/tafproperty.h" |
9 | 9 | ||
10 | Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : | 10 | Bu::TafProperty::TafProperty( const Bu::TafProperty &rSrc ) : |
11 | TafNode( typeProperty ), | 11 | TafNode( typeProperty ), |
12 | sName( rSrc.sName ), | 12 | sName( rSrc.sName ), |
13 | sValue( rSrc.sValue ) | 13 | sValue( rSrc.sValue ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | Bu::TafProperty::TafProperty( const Bu::String &sName, const Bu::String &sValue ) : | 17 | Bu::TafProperty::TafProperty( const Bu::String &sName, const Bu::String &sValue ) : |
18 | TafNode( typeProperty ), | 18 | TafNode( typeProperty ), |
19 | sName( sName ), | 19 | sName( sName ), |
20 | sValue( sValue ) | 20 | sValue( sValue ) |
21 | { | 21 | { |
22 | } | 22 | } |
23 | 23 | ||
@@ -27,11 +27,11 @@ Bu::TafProperty::~TafProperty() | |||
27 | 27 | ||
28 | const Bu::String &Bu::TafProperty::getName() const | 28 | const Bu::String &Bu::TafProperty::getName() const |
29 | { | 29 | { |
30 | return sName; | 30 | return sName; |
31 | } | 31 | } |
32 | 32 | ||
33 | const Bu::String &Bu::TafProperty::getValue() const | 33 | const Bu::String &Bu::TafProperty::getValue() const |
34 | { | 34 | { |
35 | return sValue; | 35 | return sValue; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/src/stable/tafproperty.h b/src/stable/tafproperty.h index b7c6983..b9834e1 100644 --- a/src/stable/tafproperty.h +++ b/src/stable/tafproperty.h | |||
@@ -13,24 +13,24 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | /** | 16 | /** |
17 | * | 17 | * |
18 | *@ingroup Taf | 18 | *@ingroup Taf |
19 | */ | 19 | */ |
20 | class TafProperty : public TafNode | 20 | class TafProperty : public TafNode |
21 | { | 21 | { |
22 | public: | 22 | public: |
23 | TafProperty( const Bu::TafProperty &rSrc ); | 23 | TafProperty( const Bu::TafProperty &rSrc ); |
24 | TafProperty( const Bu::String &sName, const Bu::String &sValue ); | 24 | TafProperty( const Bu::String &sName, const Bu::String &sValue ); |
25 | virtual ~TafProperty(); | 25 | virtual ~TafProperty(); |
26 | 26 | ||
27 | const Bu::String &getName() const; | 27 | const Bu::String &getName() const; |
28 | const Bu::String &getValue() const; | 28 | const Bu::String &getValue() const; |
29 | 29 | ||
30 | private: | 30 | private: |
31 | Bu::String sName; | 31 | Bu::String sName; |
32 | Bu::String sValue; | 32 | Bu::String sValue; |
33 | }; | 33 | }; |
34 | } | 34 | } |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/src/stable/tafreader.cpp b/src/stable/tafreader.cpp index fb17aea..f21505e 100644 --- a/src/stable/tafreader.cpp +++ b/src/stable/tafreader.cpp | |||
@@ -14,12 +14,12 @@ | |||
14 | using namespace Bu; | 14 | using namespace Bu; |
15 | 15 | ||
16 | Bu::TafReader::TafReader( Bu::Stream &sIn ) : | 16 | Bu::TafReader::TafReader( Bu::Stream &sIn ) : |
17 | c( 0 ), | 17 | c( 0 ), |
18 | la( 0 ), | 18 | la( 0 ), |
19 | sIn( sIn ), | 19 | sIn( sIn ), |
20 | iLine( 1 ), iCol( -1 ) | 20 | iLine( 1 ), iCol( -1 ) |
21 | { | 21 | { |
22 | next(); next(); | 22 | next(); next(); |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::TafReader::~TafReader() | 25 | Bu::TafReader::~TafReader() |
@@ -29,122 +29,122 @@ Bu::TafReader::~TafReader() | |||
29 | 29 | ||
30 | Bu::TafGroup *Bu::TafReader::readGroup() | 30 | Bu::TafGroup *Bu::TafReader::readGroup() |
31 | { | 31 | { |
32 | ws(); | 32 | ws(); |
33 | if( c != '{' ) | 33 | if( c != '{' ) |
34 | throw TafException("%d:%d: Expected '{' got '%c'.", iLine, iCol, c ); | 34 | throw TafException("%d:%d: Expected '{' got '%c'.", iLine, iCol, c ); |
35 | next(); | 35 | next(); |
36 | ws(); | 36 | ws(); |
37 | String sName = readStr(); | 37 | String sName = readStr(); |
38 | TafGroup *pGroup = new TafGroup( sName ); | 38 | TafGroup *pGroup = new TafGroup( sName ); |
39 | try | 39 | try |
40 | { | 40 | { |
41 | ws(); | 41 | ws(); |
42 | if( c != ':' ) | 42 | if( c != ':' ) |
43 | throw TafException("%d:%d: Expected ':' got '%c'.", | 43 | throw TafException("%d:%d: Expected ':' got '%c'.", |
44 | iLine, iCol, c ); | 44 | iLine, iCol, c ); |
45 | next(); | 45 | next(); |
46 | //printf("Node[%s]:\n", sName.getStr() ); | 46 | //printf("Node[%s]:\n", sName.getStr() ); |
47 | 47 | ||
48 | groupContent( pGroup ); | 48 | groupContent( pGroup ); |
49 | 49 | ||
50 | if( c != '}' ) | 50 | if( c != '}' ) |
51 | throw TafException("%d:%d: Expected '}' got '%c'.", | 51 | throw TafException("%d:%d: Expected '}' got '%c'.", |
52 | iLine, iCol, c ); | 52 | iLine, iCol, c ); |
53 | 53 | ||
54 | //next(); | 54 | //next(); |
55 | 55 | ||
56 | return pGroup; | 56 | return pGroup; |
57 | } | 57 | } |
58 | catch(...) | 58 | catch(...) |
59 | { | 59 | { |
60 | delete pGroup; | 60 | delete pGroup; |
61 | throw; | 61 | throw; |
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | void Bu::TafReader::groupContent( Bu::TafGroup *pGroup ) | 65 | void Bu::TafReader::groupContent( Bu::TafGroup *pGroup ) |
66 | { | 66 | { |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | ws(); | 69 | ws(); |
70 | if( c == '{' ) | 70 | if( c == '{' ) |
71 | { | 71 | { |
72 | pGroup->addChild( readGroup() ); | 72 | pGroup->addChild( readGroup() ); |
73 | next(); | 73 | next(); |
74 | } | 74 | } |
75 | else if( c == '}' ) | 75 | else if( c == '}' ) |
76 | return; | 76 | return; |
77 | else if( c == '/' && la == '*' ) | 77 | else if( c == '/' && la == '*' ) |
78 | pGroup->addChild( readComment() ); | 78 | pGroup->addChild( readComment() ); |
79 | else if( c == '/' && la == '/' ) | 79 | else if( c == '/' && la == '/' ) |
80 | pGroup->addChild( readComment( true ) ); | 80 | pGroup->addChild( readComment( true ) ); |
81 | else if( c == ':' ) | 81 | else if( c == ':' ) |
82 | throw TafException("%d:%d: Encountered stray ':' in taf stream.", | 82 | throw TafException("%d:%d: Encountered stray ':' in taf stream.", |
83 | iLine, iCol ); | 83 | iLine, iCol ); |
84 | else | 84 | else |
85 | pGroup->addChild( readProperty() ); | 85 | pGroup->addChild( readProperty() ); |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | Bu::TafProperty *Bu::TafReader::readProperty() | 89 | Bu::TafProperty *Bu::TafReader::readProperty() |
90 | { | 90 | { |
91 | String sName = readStr(); | 91 | String sName = readStr(); |
92 | ws(); | 92 | ws(); |
93 | if( c != '=' ) | 93 | if( c != '=' ) |
94 | { | 94 | { |
95 | //printf(" %s (true)\n", sName.getStr() ); | 95 | //printf(" %s (true)\n", sName.getStr() ); |
96 | return new Bu::TafProperty( "", sName ); | 96 | return new Bu::TafProperty( "", sName ); |
97 | } | 97 | } |
98 | next(); | 98 | next(); |
99 | String sValue = readStr(); | 99 | String sValue = readStr(); |
100 | return new Bu::TafProperty( sName, sValue ); | 100 | return new Bu::TafProperty( sName, sValue ); |
101 | //printf(" %s = %s\n", sName.getStr(), sValue.getStr() ); | 101 | //printf(" %s = %s\n", sName.getStr(), sValue.getStr() ); |
102 | } | 102 | } |
103 | 103 | ||
104 | Bu::TafComment *Bu::TafReader::readComment( bool bEOL ) | 104 | Bu::TafComment *Bu::TafReader::readComment( bool bEOL ) |
105 | { | 105 | { |
106 | String sCmnt; | 106 | String sCmnt; |
107 | next(); | 107 | next(); |
108 | if( bEOL ) | 108 | if( bEOL ) |
109 | { | 109 | { |
110 | for(;;) | 110 | for(;;) |
111 | { | 111 | { |
112 | next(); | 112 | next(); |
113 | if( c == '\n' && la == '\r' ) | 113 | if( c == '\n' && la == '\r' ) |
114 | { | 114 | { |
115 | next(); next(); | 115 | next(); next(); |
116 | break; | 116 | break; |
117 | } | 117 | } |
118 | else if( c == '\n' || c == '\r' ) | 118 | else if( c == '\n' || c == '\r' ) |
119 | { | 119 | { |
120 | next(); | 120 | next(); |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | sCmnt += c; | 123 | sCmnt += c; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | else | 126 | else |
127 | { | 127 | { |
128 | for(;;) | 128 | for(;;) |
129 | { | 129 | { |
130 | next(); | 130 | next(); |
131 | if( c == '*' && la == '/' ) | 131 | if( c == '*' && la == '/' ) |
132 | { | 132 | { |
133 | next(); next(); | 133 | next(); next(); |
134 | break; | 134 | break; |
135 | } | 135 | } |
136 | sCmnt += c; | 136 | sCmnt += c; |
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | return new TafComment( sCmnt, bEOL ); | 140 | return new TafComment( sCmnt, bEOL ); |
141 | } | 141 | } |
142 | 142 | ||
143 | Bu::String Bu::TafReader::readStr() | 143 | Bu::String Bu::TafReader::readStr() |
144 | { | 144 | { |
145 | ws(); | 145 | ws(); |
146 | String s; | 146 | String s; |
147 | if( c == '"' ) | 147 | if( c == '"' ) |
148 | { | 148 | { |
149 | next(); | 149 | next(); |
150 | for(;;) | 150 | for(;;) |
@@ -162,7 +162,7 @@ Bu::String Bu::TafReader::readStr() | |||
162 | c = (unsigned char)strtol( code, NULL, 16 ); | 162 | c = (unsigned char)strtol( code, NULL, 16 ); |
163 | } | 163 | } |
164 | else if( c == '"' ) | 164 | else if( c == '"' ) |
165 | c = '"'; | 165 | c = '"'; |
166 | else if( c == '\\' ) | 166 | else if( c == '\\' ) |
167 | c = '\\'; | 167 | c = '\\'; |
168 | else if( c == 'n' ) | 168 | else if( c == 'n' ) |
@@ -174,79 +174,79 @@ Bu::String Bu::TafReader::readStr() | |||
174 | iLine, iCol, c ); | 174 | iLine, iCol, c ); |
175 | } | 175 | } |
176 | else if( c == '"' ) | 176 | else if( c == '"' ) |
177 | break; | 177 | break; |
178 | s += c; | 178 | s += c; |
179 | next(); | 179 | next(); |
180 | } | 180 | } |
181 | next(); | 181 | next(); |
182 | } | 182 | } |
183 | else | 183 | else |
184 | { | 184 | { |
185 | for(;;) | 185 | for(;;) |
186 | { | 186 | { |
187 | if( isws() || c == '}' || c == '{' || c == ':' || c == '=' ) | 187 | if( isws() || c == '}' || c == '{' || c == ':' || c == '=' ) |
188 | break; | 188 | break; |
189 | s += c; | 189 | s += c; |
190 | next(); | 190 | next(); |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
194 | return s; | 194 | return s; |
195 | } | 195 | } |
196 | 196 | ||
197 | void Bu::TafReader::ws() | 197 | void Bu::TafReader::ws() |
198 | { | 198 | { |
199 | for(;;) | 199 | for(;;) |
200 | { | 200 | { |
201 | if( !isws() ) | 201 | if( !isws() ) |
202 | return; | 202 | return; |
203 | 203 | ||
204 | next(); | 204 | next(); |
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | bool Bu::TafReader::isws() | 208 | bool Bu::TafReader::isws() |
209 | { | 209 | { |
210 | return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); | 210 | return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); |
211 | } | 211 | } |
212 | 212 | ||
213 | void Bu::TafReader::next() | 213 | void Bu::TafReader::next() |
214 | { | 214 | { |
215 | if( c == '\n' ) | 215 | if( c == '\n' ) |
216 | { | 216 | { |
217 | iLine++; | 217 | iLine++; |
218 | iCol = 1; | 218 | iCol = 1; |
219 | } | 219 | } |
220 | else | 220 | else |
221 | iCol++; | 221 | iCol++; |
222 | if( c == '}' ) | 222 | if( c == '}' ) |
223 | { | 223 | { |
224 | rawread( &c ); | 224 | rawread( &c ); |
225 | if( c != '}' ) | 225 | if( c != '}' ) |
226 | rawread( &la ); | 226 | rawread( &la ); |
227 | } | 227 | } |
228 | else | 228 | else |
229 | { | 229 | { |
230 | c = la; | 230 | c = la; |
231 | if( c != '}' ) | 231 | if( c != '}' ) |
232 | rawread( &la ); | 232 | rawread( &la ); |
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | void Bu::TafReader::rawread( char *c ) | 236 | void Bu::TafReader::rawread( char *c ) |
237 | { | 237 | { |
238 | if( sIn.read( c, 1 ) < 1 ) | 238 | if( sIn.read( c, 1 ) < 1 ) |
239 | { | 239 | { |
240 | if( sIn.isEos() ) | 240 | if( sIn.isEos() ) |
241 | { | 241 | { |
242 | throw TafException("%d:%d: Premature end of stream.", | 242 | throw TafException("%d:%d: Premature end of stream.", |
243 | iLine, iCol, c ); | 243 | iLine, iCol, c ); |
244 | } | 244 | } |
245 | else | 245 | else |
246 | { | 246 | { |
247 | throw TafException("%d:%d: No data read, but not end of stream?", | 247 | throw TafException("%d:%d: No data read, but not end of stream?", |
248 | iLine, iCol, c ); | 248 | iLine, iCol, c ); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | } | 251 | } |
252 | 252 | ||
diff --git a/src/stable/tafreader.h b/src/stable/tafreader.h index 0cf00a9..b3ced1b 100644 --- a/src/stable/tafreader.h +++ b/src/stable/tafreader.h | |||
@@ -13,37 +13,37 @@ | |||
13 | 13 | ||
14 | namespace Bu | 14 | namespace Bu |
15 | { | 15 | { |
16 | class TafNode; | 16 | class TafNode; |
17 | class TafGroup; | 17 | class TafGroup; |
18 | class TafProperty; | 18 | class TafProperty; |
19 | class TafComment; | 19 | class TafComment; |
20 | class Stream; | 20 | class Stream; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * | 23 | * |
24 | *@ingroup Taf | 24 | *@ingroup Taf |
25 | */ | 25 | */ |
26 | class TafReader | 26 | class TafReader |
27 | { | 27 | { |
28 | public: | 28 | public: |
29 | TafReader( Bu::Stream &sIn ); | 29 | TafReader( Bu::Stream &sIn ); |
30 | virtual ~TafReader(); | 30 | virtual ~TafReader(); |
31 | 31 | ||
32 | Bu::TafGroup *readGroup(); | 32 | Bu::TafGroup *readGroup(); |
33 | 33 | ||
34 | private: | 34 | private: |
35 | void groupContent( Bu::TafGroup *pNode ); | 35 | void groupContent( Bu::TafGroup *pNode ); |
36 | Bu::TafProperty *readProperty(); | 36 | Bu::TafProperty *readProperty(); |
37 | Bu::TafComment *readComment( bool bEOL=false ); | 37 | Bu::TafComment *readComment( bool bEOL=false ); |
38 | void ws(); | 38 | void ws(); |
39 | bool isws(); | 39 | bool isws(); |
40 | void next(); | 40 | void next(); |
41 | Bu::String readStr(); | 41 | Bu::String readStr(); |
42 | void rawread( char *c ); | 42 | void rawread( char *c ); |
43 | char c, la; | 43 | char c, la; |
44 | Bu::Stream &sIn; | 44 | Bu::Stream &sIn; |
45 | int iLine, iCol; | 45 | int iLine, iCol; |
46 | }; | 46 | }; |
47 | } | 47 | } |
48 | 48 | ||
49 | #endif | 49 | #endif |
diff --git a/src/stable/tafwriter.cpp b/src/stable/tafwriter.cpp index 00d9f68..f17a237 100644 --- a/src/stable/tafwriter.cpp +++ b/src/stable/tafwriter.cpp | |||
@@ -9,8 +9,8 @@ | |||
9 | #include "bu/stream.h" | 9 | #include "bu/stream.h" |
10 | 10 | ||
11 | Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : | 11 | Bu::TafWriter::TafWriter( Bu::Stream &sOut ) : |
12 | sOut( sOut ), | 12 | sOut( sOut ), |
13 | iDepth( 0 ) | 13 | iDepth( 0 ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,81 +20,81 @@ Bu::TafWriter::~TafWriter() | |||
20 | 20 | ||
21 | void Bu::TafWriter::ident() | 21 | void Bu::TafWriter::ident() |
22 | { | 22 | { |
23 | for( int j = 0; j < iDepth; j++ ) | 23 | for( int j = 0; j < iDepth; j++ ) |
24 | sOut.write(" ", 4 ); | 24 | sOut.write(" ", 4 ); |
25 | } | 25 | } |
26 | 26 | ||
27 | void Bu::TafWriter::writeGroup( const Bu::TafGroup *pRoot ) | 27 | void Bu::TafWriter::writeGroup( const Bu::TafGroup *pRoot ) |
28 | { | 28 | { |
29 | ident(); | 29 | ident(); |
30 | sOut.write("{", 1 ); | 30 | sOut.write("{", 1 ); |
31 | if( pRoot->getName().isSet() ) | 31 | if( pRoot->getName().isSet() ) |
32 | writeString( pRoot->getName() ); | 32 | writeString( pRoot->getName() ); |
33 | sOut.write(":\n", 2 ); | 33 | sOut.write(":\n", 2 ); |
34 | iDepth++; | 34 | iDepth++; |
35 | const Bu::TafGroup::NodeList &nl = pRoot->getChildren(); | 35 | const Bu::TafGroup::NodeList &nl = pRoot->getChildren(); |
36 | for( Bu::TafGroup::NodeList::const_iterator i = nl.begin(); i != nl.end(); i++ ) | 36 | for( Bu::TafGroup::NodeList::const_iterator i = nl.begin(); i != nl.end(); i++ ) |
37 | { | 37 | { |
38 | switch( (*i)->getType() ) | 38 | switch( (*i)->getType() ) |
39 | { | 39 | { |
40 | case Bu::TafNode::typeGroup: | 40 | case Bu::TafNode::typeGroup: |
41 | writeGroup( (Bu::TafGroup *)(*i) ); | 41 | writeGroup( (Bu::TafGroup *)(*i) ); |
42 | break; | 42 | break; |
43 | 43 | ||
44 | case Bu::TafNode::typeProperty: | 44 | case Bu::TafNode::typeProperty: |
45 | writeProperty( (Bu::TafProperty *)(*i) ); | 45 | writeProperty( (Bu::TafProperty *)(*i) ); |
46 | break; | 46 | break; |
47 | 47 | ||
48 | case Bu::TafNode::typeComment: | 48 | case Bu::TafNode::typeComment: |
49 | writeComment( (Bu::TafComment *)(*i) ); | 49 | writeComment( (Bu::TafComment *)(*i) ); |
50 | break; | 50 | break; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | iDepth--; | 53 | iDepth--; |
54 | ident(); | 54 | ident(); |
55 | sOut.write("}\n", 2 ); | 55 | sOut.write("}\n", 2 ); |
56 | } | 56 | } |
57 | 57 | ||
58 | void Bu::TafWriter::writeProperty( const Bu::TafProperty *pProp ) | 58 | void Bu::TafWriter::writeProperty( const Bu::TafProperty *pProp ) |
59 | { | 59 | { |
60 | ident(); | 60 | ident(); |
61 | if( !pProp->getName().isEmpty() ) | 61 | if( !pProp->getName().isEmpty() ) |
62 | { | 62 | { |
63 | writeString( pProp->getName() ); | 63 | writeString( pProp->getName() ); |
64 | sOut.write("=", 1 ); | 64 | sOut.write("=", 1 ); |
65 | writeString( pProp->getValue() ); | 65 | writeString( pProp->getValue() ); |
66 | } | 66 | } |
67 | else | 67 | else |
68 | { | 68 | { |
69 | writeString( pProp->getValue() ); | 69 | writeString( pProp->getValue() ); |
70 | } | 70 | } |
71 | sOut.write("\n", 1 ); | 71 | sOut.write("\n", 1 ); |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::TafWriter::writeComment( const Bu::TafComment *pComment ) | 74 | void Bu::TafWriter::writeComment( const Bu::TafComment *pComment ) |
75 | { | 75 | { |
76 | ident(); | 76 | ident(); |
77 | if( pComment->isEOLStyle() ) | 77 | if( pComment->isEOLStyle() ) |
78 | { | 78 | { |
79 | sOut.write("//", 2 ); | 79 | sOut.write("//", 2 ); |
80 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); | 80 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); |
81 | sOut.write("\n", 1 ); | 81 | sOut.write("\n", 1 ); |
82 | } | 82 | } |
83 | else | 83 | else |
84 | { | 84 | { |
85 | sOut.write("/*", 2 ); | 85 | sOut.write("/*", 2 ); |
86 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); | 86 | sOut.write( pComment->getText().getStr(), pComment->getText().getSize() ); |
87 | sOut.write("*/ ", 3 ); | 87 | sOut.write("*/ ", 3 ); |
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
91 | void Bu::TafWriter::writeString( const Bu::String &str ) | 91 | void Bu::TafWriter::writeString( const Bu::String &str ) |
92 | { | 92 | { |
93 | sOut.write("\"", 1 ); | 93 | sOut.write("\"", 1 ); |
94 | for( Bu::String::const_iterator s = str.begin(); s != str.end(); s++ ) | 94 | for( Bu::String::const_iterator s = str.begin(); s != str.end(); s++ ) |
95 | { | 95 | { |
96 | if( *s == '\"' ) | 96 | if( *s == '\"' ) |
97 | sOut.write("\\\"", 2 ); | 97 | sOut.write("\\\"", 2 ); |
98 | else if( *s == '\\' ) | 98 | else if( *s == '\\' ) |
99 | sOut.write("\\\\", 2 ); | 99 | sOut.write("\\\\", 2 ); |
100 | else if( *s < 32 || *s > 126 ) | 100 | else if( *s < 32 || *s > 126 ) |
diff --git a/src/stable/tafwriter.h b/src/stable/tafwriter.h index 7e43d64..48787ab 100644 --- a/src/stable/tafwriter.h +++ b/src/stable/tafwriter.h | |||
@@ -14,32 +14,32 @@ | |||
14 | 14 | ||
15 | namespace Bu | 15 | namespace Bu |
16 | { | 16 | { |
17 | class Stream; | 17 | class Stream; |
18 | class TafNode; | 18 | class TafNode; |
19 | class TafGroup; | 19 | class TafGroup; |
20 | class TafProperty; | 20 | class TafProperty; |
21 | class TafComment; | 21 | class TafComment; |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * | 24 | * |
25 | *@ingroup Taf | 25 | *@ingroup Taf |
26 | */ | 26 | */ |
27 | class TafWriter | 27 | class TafWriter |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | TafWriter( Bu::Stream &sOut ); | 30 | TafWriter( Bu::Stream &sOut ); |
31 | virtual ~TafWriter(); | 31 | virtual ~TafWriter(); |
32 | 32 | ||
33 | void writeGroup( const Bu::TafGroup *pRoot ); | 33 | void writeGroup( const Bu::TafGroup *pRoot ); |
34 | 34 | ||
35 | private: | 35 | private: |
36 | void writeProperty( const Bu::TafProperty *pProp ); | 36 | void writeProperty( const Bu::TafProperty *pProp ); |
37 | void writeComment( const Bu::TafComment *pComment ); | 37 | void writeComment( const Bu::TafComment *pComment ); |
38 | void writeString( const Bu::String &str ); | 38 | void writeString( const Bu::String &str ); |
39 | void ident(); | 39 | void ident(); |
40 | Bu::Stream &sOut; | 40 | Bu::Stream &sOut; |
41 | int iDepth; | 41 | int iDepth; |
42 | }; | 42 | }; |
43 | } | 43 | } |
44 | 44 | ||
45 | #endif | 45 | #endif |
diff --git a/src/stable/tcpserversocket.cpp b/src/stable/tcpserversocket.cpp index 91da199..aed7699 100644 --- a/src/stable/tcpserversocket.cpp +++ b/src/stable/tcpserversocket.cpp | |||
@@ -28,230 +28,230 @@ | |||
28 | namespace Bu { subExceptionDef( TcpServerSocketException ) } | 28 | namespace Bu { subExceptionDef( TcpServerSocketException ) } |
29 | 29 | ||
30 | Bu::TcpServerSocket::TcpServerSocket( int nPort, int nPoolSize ) : | 30 | Bu::TcpServerSocket::TcpServerSocket( int nPort, int nPoolSize ) : |
31 | nPort( nPort ) | 31 | nPort( nPort ) |
32 | { | 32 | { |
33 | #ifdef WIN32 | 33 | #ifdef WIN32 |
34 | Bu::Winsock2::getInstance(); | 34 | Bu::Winsock2::getInstance(); |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | /* Create the socket and set it up to accept connections. */ | 37 | /* Create the socket and set it up to accept connections. */ |
38 | struct sockaddr_in name; | 38 | struct sockaddr_in name; |
39 | 39 | ||
40 | /* Give the socket a name. */ | 40 | /* Give the socket a name. */ |
41 | name.sin_family = AF_INET; | 41 | name.sin_family = AF_INET; |
42 | name.sin_port = bu_htons( nPort ); | 42 | name.sin_port = bu_htons( nPort ); |
43 | 43 | ||
44 | // I think this specifies who we will accept connections from, | 44 | // I think this specifies who we will accept connections from, |
45 | // a good thing to make configurable later on | 45 | // a good thing to make configurable later on |
46 | name.sin_addr.s_addr = bu_htonl( INADDR_ANY ); | 46 | name.sin_addr.s_addr = bu_htonl( INADDR_ANY ); |
47 | 47 | ||
48 | startServer( name, nPoolSize ); | 48 | startServer( name, nPoolSize ); |
49 | } | 49 | } |
50 | 50 | ||
51 | Bu::TcpServerSocket::TcpServerSocket(const String &sAddr,int nPort, int nPoolSize) : | 51 | Bu::TcpServerSocket::TcpServerSocket(const String &sAddr,int nPort, int nPoolSize) : |
52 | nPort( nPort ) | 52 | nPort( nPort ) |
53 | { | 53 | { |
54 | #ifdef WIN32 | 54 | #ifdef WIN32 |
55 | Bu::Winsock2::getInstance(); | 55 | Bu::Winsock2::getInstance(); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | /* Create the socket and set it up to accept connections. */ | 58 | /* Create the socket and set it up to accept connections. */ |
59 | struct sockaddr_in name; | 59 | struct sockaddr_in name; |
60 | 60 | ||
61 | /* Give the socket a name. */ | 61 | /* Give the socket a name. */ |
62 | name.sin_family = AF_INET; | 62 | name.sin_family = AF_INET; |
63 | 63 | ||
64 | name.sin_port = bu_htons( nPort ); | 64 | name.sin_port = bu_htons( nPort ); |
65 | 65 | ||
66 | #ifdef WIN32 | 66 | #ifdef WIN32 |
67 | name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() ); | 67 | name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() ); |
68 | #else | 68 | #else |
69 | inet_aton( sAddr.getStr(), &name.sin_addr ); | 69 | inet_aton( sAddr.getStr(), &name.sin_addr ); |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | startServer( name, nPoolSize ); | 72 | startServer( name, nPoolSize ); |
73 | } | 73 | } |
74 | 74 | ||
75 | Bu::TcpServerSocket::TcpServerSocket( socket_t nServer, bool bInit, int nPoolSize ) : | 75 | Bu::TcpServerSocket::TcpServerSocket( socket_t nServer, bool bInit, int nPoolSize ) : |
76 | nServer( nServer ), | 76 | nServer( nServer ), |
77 | nPort( 0 ) | 77 | nPort( 0 ) |
78 | { | 78 | { |
79 | #ifdef WIN32 | 79 | #ifdef WIN32 |
80 | Bu::Winsock2::getInstance(); | 80 | Bu::Winsock2::getInstance(); |
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | if( bInit ) | 83 | if( bInit ) |
84 | { | 84 | { |
85 | struct sockaddr name; | 85 | struct sockaddr name; |
86 | socklen_t namelen = sizeof(name); | 86 | socklen_t namelen = sizeof(name); |
87 | getpeername( nServer, &name, &namelen ); | 87 | getpeername( nServer, &name, &namelen ); |
88 | 88 | ||
89 | initServer( *((sockaddr_in *)&name), nPoolSize ); | 89 | initServer( *((sockaddr_in *)&name), nPoolSize ); |
90 | } | 90 | } |
91 | else | 91 | else |
92 | { | 92 | { |
93 | FD_ZERO( &fdActive ); | 93 | FD_ZERO( &fdActive ); |
94 | FD_SET( nServer, &fdActive ); | 94 | FD_SET( nServer, &fdActive ); |
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | Bu::TcpServerSocket::TcpServerSocket( const TcpServerSocket &rSrc ) | 98 | Bu::TcpServerSocket::TcpServerSocket( const TcpServerSocket &rSrc ) |
99 | { | 99 | { |
100 | #ifdef WIN32 | 100 | #ifdef WIN32 |
101 | Bu::Winsock2::getInstance(); | 101 | Bu::Winsock2::getInstance(); |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | nServer = dup( rSrc.nServer ); | 104 | nServer = dup( rSrc.nServer ); |
105 | nPort = rSrc.nPort; | 105 | nPort = rSrc.nPort; |
106 | FD_ZERO( &fdActive ); | 106 | FD_ZERO( &fdActive ); |
107 | FD_SET( nServer, &fdActive ); | 107 | FD_SET( nServer, &fdActive ); |
108 | } | 108 | } |
109 | 109 | ||
110 | Bu::TcpServerSocket::~TcpServerSocket() | 110 | Bu::TcpServerSocket::~TcpServerSocket() |
111 | { | 111 | { |
112 | #ifdef WIN32 | 112 | #ifdef WIN32 |
113 | if( nServer != INVALID_SOCKET ) | 113 | if( nServer != INVALID_SOCKET ) |
114 | #else | 114 | #else |
115 | if( nServer > -1 ) | 115 | if( nServer > -1 ) |
116 | #endif | 116 | #endif |
117 | ::close( nServer ); | 117 | ::close( nServer ); |
118 | } | 118 | } |
119 | 119 | ||
120 | void Bu::TcpServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) | 120 | void Bu::TcpServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) |
121 | { | 121 | { |
122 | /* Create the socket. */ | 122 | /* Create the socket. */ |
123 | nServer = bu_socket( PF_INET, SOCK_STREAM, 0 ); | 123 | nServer = bu_socket( PF_INET, SOCK_STREAM, 0 ); |
124 | 124 | ||
125 | #ifdef WIN32 | 125 | #ifdef WIN32 |
126 | if( nServer == INVALID_SOCKET ) | 126 | if( nServer == INVALID_SOCKET ) |
127 | #else | 127 | #else |
128 | if( nServer < 0 ) | 128 | if( nServer < 0 ) |
129 | #endif | 129 | #endif |
130 | { | 130 | { |
131 | throw Bu::TcpServerSocketException("Couldn't create a listen socket."); | 131 | throw Bu::TcpServerSocketException("Couldn't create a listen socket."); |
132 | } | 132 | } |
133 | 133 | ||
134 | int opt = 1; | 134 | int opt = 1; |
135 | bu_setsockopt( | 135 | bu_setsockopt( |
136 | nServer, | 136 | nServer, |
137 | SOL_SOCKET, | 137 | SOL_SOCKET, |
138 | SO_REUSEADDR, | 138 | SO_REUSEADDR, |
139 | (char *)&opt, | 139 | (char *)&opt, |
140 | sizeof( opt ) | 140 | sizeof( opt ) |
141 | ); | 141 | ); |
142 | 142 | ||
143 | initServer( name, nPoolSize ); | 143 | initServer( name, nPoolSize ); |
144 | } | 144 | } |
145 | 145 | ||
146 | void Bu::TcpServerSocket::initServer( struct sockaddr_in &name, int nPoolSize ) | 146 | void Bu::TcpServerSocket::initServer( struct sockaddr_in &name, int nPoolSize ) |
147 | { | 147 | { |
148 | if( bu_bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) | 148 | if( bu_bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) |
149 | { | 149 | { |
150 | throw Bu::TcpServerSocketException("Couldn't bind to the listen socket."); | 150 | throw Bu::TcpServerSocketException("Couldn't bind to the listen socket."); |
151 | } | 151 | } |
152 | 152 | ||
153 | if( bu_listen( nServer, nPoolSize ) < 0 ) | 153 | if( bu_listen( nServer, nPoolSize ) < 0 ) |
154 | { | 154 | { |
155 | throw Bu::TcpServerSocketException( | 155 | throw Bu::TcpServerSocketException( |
156 | "Couldn't begin listening to the server socket." | 156 | "Couldn't begin listening to the server socket." |
157 | ); | 157 | ); |
158 | } | 158 | } |
159 | 159 | ||
160 | FD_ZERO( &fdActive ); | 160 | FD_ZERO( &fdActive ); |
161 | /* Initialize the set of active sockets. */ | 161 | /* Initialize the set of active sockets. */ |
162 | FD_SET( nServer, &fdActive ); | 162 | FD_SET( nServer, &fdActive ); |
163 | } | 163 | } |
164 | 164 | ||
165 | int Bu::TcpServerSocket::getSocket() | 165 | int Bu::TcpServerSocket::getSocket() |
166 | { | 166 | { |
167 | return nServer; | 167 | return nServer; |
168 | } | 168 | } |
169 | 169 | ||
170 | int Bu::TcpServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) | 170 | int Bu::TcpServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) |
171 | { | 171 | { |
172 | fd_set fdRead = fdActive; | 172 | fd_set fdRead = fdActive; |
173 | 173 | ||
174 | struct timeval xT; | 174 | struct timeval xT; |
175 | 175 | ||
176 | xT.tv_sec = nTimeoutSec; | 176 | xT.tv_sec = nTimeoutSec; |
177 | xT.tv_usec = nTimeoutUSec; | 177 | xT.tv_usec = nTimeoutUSec; |
178 | 178 | ||
179 | if( TEMP_FAILURE_RETRY( | 179 | if( TEMP_FAILURE_RETRY( |
180 | bu_select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) | 180 | bu_select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) |
181 | { | 181 | { |
182 | throw Bu::TcpServerSocketException( | 182 | throw Bu::TcpServerSocketException( |
183 | "Error scanning for new connections: %s", strerror( errno ) | 183 | "Error scanning for new connections: %s", strerror( errno ) |
184 | ); | 184 | ); |
185 | } | 185 | } |
186 | 186 | ||
187 | if( FD_ISSET( nServer, &fdRead ) ) | 187 | if( FD_ISSET( nServer, &fdRead ) ) |
188 | { | 188 | { |
189 | struct sockaddr_in clientname; | 189 | struct sockaddr_in clientname; |
190 | socklen_t size; | 190 | socklen_t size; |
191 | int nClient; | 191 | int nClient; |
192 | 192 | ||
193 | size = sizeof( clientname ); | 193 | size = sizeof( clientname ); |
194 | #ifdef WIN32 | 194 | #ifdef WIN32 |
195 | nClient = bu_accept( nServer, (struct sockaddr *)&clientname, &size); | 195 | nClient = bu_accept( nServer, (struct sockaddr *)&clientname, &size); |
196 | #else /* not-WIN32 */ | 196 | #else /* not-WIN32 */ |
197 | #ifdef __CYGWIN__ | 197 | #ifdef __CYGWIN__ |
198 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, | 198 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, |
199 | (int *)&size | 199 | (int *)&size |
200 | ); | 200 | ); |
201 | #else /* not-cygwin */ | 201 | #else /* not-cygwin */ |
202 | #ifdef __APPLE__ | 202 | #ifdef __APPLE__ |
203 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, (socklen_t*)&size ); | 203 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, (socklen_t*)&size ); |
204 | #else /* linux */ | 204 | #else /* linux */ |
205 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); | 205 | nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); |
206 | #endif /* __APPLE__ */ | 206 | #endif /* __APPLE__ */ |
207 | #endif /* __CYGWIN__ */ | 207 | #endif /* __CYGWIN__ */ |
208 | #endif /* WIN32 */ | 208 | #endif /* WIN32 */ |
209 | if( nClient < 0 ) | 209 | if( nClient < 0 ) |
210 | { | 210 | { |
211 | throw Bu::TcpServerSocketException( | 211 | throw Bu::TcpServerSocketException( |
212 | "Error accepting a new connection: %s", strerror( errno ) | 212 | "Error accepting a new connection: %s", strerror( errno ) |
213 | ); | 213 | ); |
214 | } | 214 | } |
215 | 215 | ||
216 | #ifndef WIN32 | 216 | #ifndef WIN32 |
217 | char tmpa[20]; | 217 | char tmpa[20]; |
218 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); | 218 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); |
219 | //"New connection from host %s, port %hd.", | 219 | //"New connection from host %s, port %hd.", |
220 | // tmpa, ntohs (clientname.sin_port) ); | 220 | // tmpa, ntohs (clientname.sin_port) ); |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | { | 223 | { |
224 | #ifndef WIN32 | 224 | #ifndef WIN32 |
225 | int flags; | 225 | int flags; |
226 | flags = fcntl( nClient, F_GETFL, 0 ); | 226 | flags = fcntl( nClient, F_GETFL, 0 ); |
227 | flags |= O_NONBLOCK; | 227 | flags |= O_NONBLOCK; |
228 | if( fcntl( nClient, F_SETFL, flags ) < 0) | 228 | if( fcntl( nClient, F_SETFL, flags ) < 0) |
229 | { | 229 | { |
230 | throw Bu::TcpServerSocketException( | 230 | throw Bu::TcpServerSocketException( |
231 | "Error setting option on client socket: %s", | 231 | "Error setting option on client socket: %s", |
232 | strerror( errno ) | 232 | strerror( errno ) |
233 | ); | 233 | ); |
234 | } | 234 | } |
235 | #else | 235 | #else |
236 | //------------------------- | 236 | //------------------------- |
237 | // Set the socket I/O mode: In this case FIONBIO | 237 | // Set the socket I/O mode: In this case FIONBIO |
238 | // enables or disables the blocking mode for the | 238 | // enables or disables the blocking mode for the |
239 | // socket based on the numerical value of iMode. | 239 | // socket based on the numerical value of iMode. |
240 | // If iMode = 0, blocking is enabled; | 240 | // If iMode = 0, blocking is enabled; |
241 | // If iMode != 0, non-blocking mode is enabled. | 241 | // If iMode != 0, non-blocking mode is enabled. |
242 | u_long iMode = 1; | 242 | u_long iMode = 1; |
243 | bu_ioctlsocket(nClient, FIONBIO, &iMode); | 243 | bu_ioctlsocket(nClient, FIONBIO, &iMode); |
244 | #endif | 244 | #endif |
245 | } | 245 | } |
246 | 246 | ||
247 | return nClient; | 247 | return nClient; |
248 | } | 248 | } |
249 | 249 | ||
250 | return -1; | 250 | return -1; |
251 | } | 251 | } |
252 | 252 | ||
253 | int Bu::TcpServerSocket::getPort() | 253 | int Bu::TcpServerSocket::getPort() |
254 | { | 254 | { |
255 | return nPort; | 255 | return nPort; |
256 | } | 256 | } |
257 | 257 | ||
diff --git a/src/stable/tcpserversocket.h b/src/stable/tcpserversocket.h index 9776668..fd1d547 100644 --- a/src/stable/tcpserversocket.h +++ b/src/stable/tcpserversocket.h | |||
@@ -20,46 +20,46 @@ | |||
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | subExceptionDecl( TcpServerSocketException ); | 23 | subExceptionDecl( TcpServerSocketException ); |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * A single tcp/ip server socket. When created the server socket will bind | 26 | * A single tcp/ip server socket. When created the server socket will bind |
27 | * to the specified interface and port, and immediately begin listening for | 27 | * to the specified interface and port, and immediately begin listening for |
28 | * connections. When connections come in they are pooled by the networking | 28 | * connections. When connections come in they are pooled by the networking |
29 | * drivers in the kernel until they are accepted, this means that failure | 29 | * drivers in the kernel until they are accepted, this means that failure |
30 | * to keep space in the connection pool will result in connection refusals. | 30 | * to keep space in the connection pool will result in connection refusals. |
31 | * | 31 | * |
32 | * Although the accept function returns an integral file descriptor, it is | 32 | * Although the accept function returns an integral file descriptor, it is |
33 | * designed to be used with the Socket class. | 33 | * designed to be used with the Socket class. |
34 | * | 34 | * |
35 | *@ingroup Serving | 35 | *@ingroup Serving |
36 | */ | 36 | */ |
37 | class TcpServerSocket | 37 | class TcpServerSocket |
38 | { | 38 | { |
39 | public: | 39 | public: |
40 | #ifdef WIN32 | 40 | #ifdef WIN32 |
41 | typedef unsigned int socket_t; | 41 | typedef unsigned int socket_t; |
42 | #else | 42 | #else |
43 | typedef int socket_t; | 43 | typedef int socket_t; |
44 | #endif | 44 | #endif |
45 | TcpServerSocket( int nPort, int nPoolSize=40 ); | 45 | TcpServerSocket( int nPort, int nPoolSize=40 ); |
46 | TcpServerSocket( const String &sAddr, int nPort, int nPoolSize=40 ); | 46 | TcpServerSocket( const String &sAddr, int nPort, int nPoolSize=40 ); |
47 | TcpServerSocket( socket_t nSocket, bool bInit, int nPoolSize=40 ); | 47 | TcpServerSocket( socket_t nSocket, bool bInit, int nPoolSize=40 ); |
48 | TcpServerSocket( const TcpServerSocket &rSrc ); | 48 | TcpServerSocket( const TcpServerSocket &rSrc ); |
49 | virtual ~TcpServerSocket(); | 49 | virtual ~TcpServerSocket(); |
50 | 50 | ||
51 | int accept( int nTimeoutSec=0, int nTimeoutUSec=0 ); | 51 | int accept( int nTimeoutSec=0, int nTimeoutUSec=0 ); |
52 | int getSocket(); | 52 | int getSocket(); |
53 | int getPort(); | 53 | int getPort(); |
54 | 54 | ||
55 | private: | 55 | private: |
56 | void startServer( struct sockaddr_in &name, int nPoolSize ); | 56 | void startServer( struct sockaddr_in &name, int nPoolSize ); |
57 | void initServer( struct sockaddr_in &name, int nPoolSize ); | 57 | void initServer( struct sockaddr_in &name, int nPoolSize ); |
58 | 58 | ||
59 | fd_set fdActive; | 59 | fd_set fdActive; |
60 | socket_t nServer; | 60 | socket_t nServer; |
61 | int nPort; | 61 | int nPort; |
62 | }; | 62 | }; |
63 | } | 63 | } |
64 | 64 | ||
65 | #endif | 65 | #endif |
diff --git a/src/stable/tcpsocket.cpp b/src/stable/tcpsocket.cpp index fa79a36..b77f439 100644 --- a/src/stable/tcpsocket.cpp +++ b/src/stable/tcpsocket.cpp | |||
@@ -32,392 +32,392 @@ | |||
32 | namespace Bu { subExceptionDef( TcpSocketException ) } | 32 | namespace Bu { subExceptionDef( TcpSocketException ) } |
33 | 33 | ||
34 | Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : | 34 | Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : |
35 | nTcpSocket( nTcpSocket ), | 35 | nTcpSocket( nTcpSocket ), |
36 | bActive( true ), | 36 | bActive( true ), |
37 | bBlocking( true ) | 37 | bBlocking( true ) |
38 | { | 38 | { |
39 | #ifdef WIN32 | 39 | #ifdef WIN32 |
40 | Bu::Winsock2::getInstance(); | 40 | Bu::Winsock2::getInstance(); |
41 | #endif | 41 | #endif |
42 | setAddress(); | 42 | setAddress(); |
43 | } | 43 | } |
44 | 44 | ||
45 | Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, | 45 | Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, |
46 | bool bBlocking ) : | 46 | bool bBlocking ) : |
47 | nTcpSocket( 0 ), | 47 | nTcpSocket( 0 ), |
48 | bActive( false ), | 48 | bActive( false ), |
49 | bBlocking( true ) | 49 | bBlocking( true ) |
50 | { | 50 | { |
51 | #ifdef WIN32 | 51 | #ifdef WIN32 |
52 | Bu::Winsock2::getInstance(); | 52 | Bu::Winsock2::getInstance(); |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* Create the socket. */ | 55 | /* Create the socket. */ |
56 | nTcpSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); | 56 | nTcpSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); |
57 | 57 | ||
58 | #ifdef WIN32 | 58 | #ifdef WIN32 |
59 | if( nTcpSocket == INVALID_SOCKET ) | 59 | if( nTcpSocket == INVALID_SOCKET ) |
60 | #else | 60 | #else |
61 | if( nTcpSocket < 0 ) | 61 | if( nTcpSocket < 0 ) |
62 | #endif | 62 | #endif |
63 | { | 63 | { |
64 | throw ExceptionBase("Couldn't create socket.\n"); | 64 | throw ExceptionBase("Couldn't create socket.\n"); |
65 | } | 65 | } |
66 | 66 | ||
67 | setBlocking( false ); | 67 | setBlocking( false ); |
68 | 68 | ||
69 | /* Connect to the server. */ | 69 | /* Connect to the server. */ |
70 | //printf("Resolving hostname (%s)...\n", sAddr ); | 70 | //printf("Resolving hostname (%s)...\n", sAddr ); |
71 | { | 71 | { |
72 | struct addrinfo *pAddr = NULL; | 72 | struct addrinfo *pAddr = NULL; |
73 | struct addrinfo aiHints; | 73 | struct addrinfo aiHints; |
74 | memset( &aiHints, 0, sizeof(addrinfo) ); | 74 | memset( &aiHints, 0, sizeof(addrinfo) ); |
75 | aiHints.ai_flags = AI_CANONNAME; | 75 | aiHints.ai_flags = AI_CANONNAME; |
76 | aiHints.ai_family = AF_INET; | 76 | aiHints.ai_family = AF_INET; |
77 | aiHints.ai_socktype = SOCK_STREAM; | 77 | aiHints.ai_socktype = SOCK_STREAM; |
78 | char ibuf[10]; | 78 | char ibuf[10]; |
79 | sprintf( ibuf, "%d", nPort ); | 79 | sprintf( ibuf, "%d", nPort ); |
80 | 80 | ||
81 | int ret; | 81 | int ret; |
82 | if( (ret = bu_getaddrinfo( | 82 | if( (ret = bu_getaddrinfo( |
83 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) | 83 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) |
84 | { | 84 | { |
85 | close(); | 85 | close(); |
86 | throw Bu::TcpSocketException("Couldn't resolve hostname %s (%s).\n", | 86 | throw Bu::TcpSocketException("Couldn't resolve hostname %s (%s).\n", |
87 | sAddr.getStr(), bu_gai_strerror(ret)); | 87 | sAddr.getStr(), bu_gai_strerror(ret)); |
88 | } | 88 | } |
89 | 89 | ||
90 | bu_connect( | 90 | bu_connect( |
91 | nTcpSocket, | 91 | nTcpSocket, |
92 | pAddr->ai_addr, | 92 | pAddr->ai_addr, |
93 | pAddr->ai_addrlen | 93 | pAddr->ai_addrlen |
94 | ); | 94 | ); |
95 | 95 | ||
96 | sAddress = pAddr->ai_canonname; | 96 | sAddress = pAddr->ai_canonname; |
97 | 97 | ||
98 | bu_freeaddrinfo( pAddr ); | 98 | bu_freeaddrinfo( pAddr ); |
99 | } | 99 | } |
100 | 100 | ||
101 | bActive = true; | 101 | bActive = true; |
102 | 102 | ||
103 | if( nTimeout > 0 ) | 103 | if( nTimeout > 0 ) |
104 | { | 104 | { |
105 | fd_set rfds, wfds, efds; | 105 | fd_set rfds, wfds, efds; |
106 | int retval; | 106 | int retval; |
107 | 107 | ||
108 | FD_ZERO(&rfds); | 108 | FD_ZERO(&rfds); |
109 | FD_SET(nTcpSocket, &rfds); | 109 | FD_SET(nTcpSocket, &rfds); |
110 | FD_ZERO(&wfds); | 110 | FD_ZERO(&wfds); |
111 | FD_SET(nTcpSocket, &wfds); | 111 | FD_SET(nTcpSocket, &wfds); |
112 | FD_ZERO(&efds); | 112 | FD_ZERO(&efds); |
113 | FD_SET(nTcpSocket, &efds); | 113 | FD_SET(nTcpSocket, &efds); |
114 | 114 | ||
115 | struct timeval tv; | 115 | struct timeval tv; |
116 | tv.tv_sec = nTimeout; | 116 | tv.tv_sec = nTimeout; |
117 | tv.tv_usec = 0; | 117 | tv.tv_usec = 0; |
118 | 118 | ||
119 | retval = bu_select( nTcpSocket+1, &rfds, &wfds, &efds, &tv ); | 119 | retval = bu_select( nTcpSocket+1, &rfds, &wfds, &efds, &tv ); |
120 | 120 | ||
121 | if( retval == 0 ) | 121 | if( retval == 0 ) |
122 | { | 122 | { |
123 | close(); | 123 | close(); |
124 | throw ExceptionBase("Connection timeout.\n"); | 124 | throw ExceptionBase("Connection timeout.\n"); |
125 | } | 125 | } |
126 | read( NULL, 0 ); // See if we can get any errors out of the way early. | 126 | read( NULL, 0 ); // See if we can get any errors out of the way early. |
127 | } | 127 | } |
128 | 128 | ||
129 | if( bBlocking ) | 129 | if( bBlocking ) |
130 | setBlocking( bBlocking ); | 130 | setBlocking( bBlocking ); |
131 | } | 131 | } |
132 | 132 | ||
133 | Bu::TcpSocket::~TcpSocket() | 133 | Bu::TcpSocket::~TcpSocket() |
134 | { | 134 | { |
135 | close(); | 135 | close(); |
136 | } | 136 | } |
137 | 137 | ||
138 | void Bu::TcpSocket::close() | 138 | void Bu::TcpSocket::close() |
139 | { | 139 | { |
140 | if( bActive ) | 140 | if( bActive ) |
141 | { | 141 | { |
142 | #ifndef WIN32 | 142 | #ifndef WIN32 |
143 | fsync( nTcpSocket ); | 143 | fsync( nTcpSocket ); |
144 | #endif | 144 | #endif |
145 | #ifdef WIN32 | 145 | #ifdef WIN32 |
146 | #ifndef SHUT_RDWR | 146 | #ifndef SHUT_RDWR |
147 | #define SHUT_RDWR (SD_BOTH) | 147 | #define SHUT_RDWR (SD_BOTH) |
148 | #endif | 148 | #endif |
149 | #endif | 149 | #endif |
150 | bu_shutdown( nTcpSocket, SHUT_RDWR ); | 150 | bu_shutdown( nTcpSocket, SHUT_RDWR ); |
151 | ::close( nTcpSocket ); | 151 | ::close( nTcpSocket ); |
152 | } | 152 | } |
153 | bActive = false; | 153 | bActive = false; |
154 | } | 154 | } |
155 | 155 | ||
156 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) | 156 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) |
157 | { | 157 | { |
158 | fd_set rfds; | 158 | fd_set rfds; |
159 | FD_ZERO(&rfds); | 159 | FD_ZERO(&rfds); |
160 | FD_SET(nTcpSocket, &rfds); | 160 | FD_SET(nTcpSocket, &rfds); |
161 | struct timeval tv = {0, 0}; | 161 | struct timeval tv = {0, 0}; |
162 | if( bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) | 162 | if( bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) |
163 | { | 163 | { |
164 | int iErr = errno; | 164 | int iErr = errno; |
165 | close(); | 165 | close(); |
166 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | 166 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); |
167 | } | 167 | } |
168 | if( FD_ISSET( nTcpSocket, &rfds ) || bBlocking ) | 168 | if( FD_ISSET( nTcpSocket, &rfds ) || bBlocking ) |
169 | { | 169 | { |
170 | int nRead = TEMP_FAILURE_RETRY( | 170 | int nRead = TEMP_FAILURE_RETRY( |
171 | bu_recv( nTcpSocket, (char *) pBuf, nBytes, 0 ) ); | 171 | bu_recv( nTcpSocket, (char *) pBuf, nBytes, 0 ) ); |
172 | if( nRead == 0 && nBytes > 0 ) | 172 | if( nRead == 0 && nBytes > 0 ) |
173 | { | 173 | { |
174 | close(); | 174 | close(); |
175 | throw TcpSocketException( TcpSocketException::cClosed, "TcpSocket closed."); | 175 | throw TcpSocketException( TcpSocketException::cClosed, "TcpSocket closed."); |
176 | } | 176 | } |
177 | if( nRead < 0 ) | 177 | if( nRead < 0 ) |
178 | { | 178 | { |
179 | #ifdef WIN32 | 179 | #ifdef WIN32 |
180 | int iWSAError = bu_WSAGetLastError(); | 180 | int iWSAError = bu_WSAGetLastError(); |
181 | if( iWSAError == WSAEWOULDBLOCK ) | 181 | if( iWSAError == WSAEWOULDBLOCK ) |
182 | return 0; | 182 | return 0; |
183 | #else | 183 | #else |
184 | if( errno == ENETRESET || errno == ECONNRESET ) | 184 | if( errno == ENETRESET || errno == ECONNRESET ) |
185 | { | 185 | { |
186 | close(); | 186 | close(); |
187 | throw TcpSocketException( TcpSocketException::cClosed, | 187 | throw TcpSocketException( TcpSocketException::cClosed, |
188 | strerror(errno) ); | 188 | strerror(errno) ); |
189 | } | 189 | } |
190 | if( errno == EAGAIN ) | 190 | if( errno == EAGAIN ) |
191 | return 0; | 191 | return 0; |
192 | int iErr = errno; | 192 | int iErr = errno; |
193 | close(); | 193 | close(); |
194 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | 194 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); |
195 | #endif | 195 | #endif |
196 | } | 196 | } |
197 | return nRead; | 197 | return nRead; |
198 | } | 198 | } |
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | 201 | ||
202 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, | 202 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, |
203 | uint32_t nSec, uint32_t nUSec ) | 203 | uint32_t nSec, uint32_t nUSec ) |
204 | { | 204 | { |
205 | struct timeval tv; | 205 | struct timeval tv; |
206 | Bu::size nRead = 0; | 206 | Bu::size nRead = 0; |
207 | 207 | ||
208 | fd_set rfds; | 208 | fd_set rfds; |
209 | FD_ZERO(&rfds); | 209 | FD_ZERO(&rfds); |
210 | FD_SET(nTcpSocket, &rfds); | 210 | FD_SET(nTcpSocket, &rfds); |
211 | 211 | ||
212 | #ifdef WIN32 | 212 | #ifdef WIN32 |
213 | DWORD dwStart = GetTickCount(); | 213 | DWORD dwStart = GetTickCount(); |
214 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | 214 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); |
215 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | 215 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; |
216 | #else | 216 | #else |
217 | struct timeval nt, ct; | 217 | struct timeval nt, ct; |
218 | gettimeofday( &nt, NULL ); | 218 | gettimeofday( &nt, NULL ); |
219 | nt.tv_sec += nSec; | 219 | nt.tv_sec += nSec; |
220 | nt.tv_usec += nUSec; | 220 | nt.tv_usec += nUSec; |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | for(;;) | 223 | for(;;) |
224 | { | 224 | { |
225 | tv.tv_sec = nSec; | 225 | tv.tv_sec = nSec; |
226 | tv.tv_usec = nUSec; | 226 | tv.tv_usec = nUSec; |
227 | bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | 227 | bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); |
228 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); | 228 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); |
229 | if( nRead >= nBytes ) | 229 | if( nRead >= nBytes ) |
230 | break; | 230 | break; |
231 | #ifdef WIN32 | 231 | #ifdef WIN32 |
232 | DWORD dwNow = GetTickCount(); | 232 | DWORD dwNow = GetTickCount(); |
233 | if( dwNow > dwEnd ) | 233 | if( dwNow > dwEnd ) |
234 | break; | 234 | break; |
235 | #else | 235 | #else |
236 | gettimeofday( &ct, NULL ); | 236 | gettimeofday( &ct, NULL ); |
237 | if( (ct.tv_sec > nt.tv_sec) || | 237 | if( (ct.tv_sec > nt.tv_sec) || |
238 | (ct.tv_sec == nt.tv_sec && | 238 | (ct.tv_sec == nt.tv_sec && |
239 | ct.tv_usec >= nt.tv_usec) ) | 239 | ct.tv_usec >= nt.tv_usec) ) |
240 | break; | 240 | break; |
241 | #endif | 241 | #endif |
242 | } | 242 | } |
243 | return nRead; | 243 | return nRead; |
244 | } | 244 | } |
245 | 245 | ||
246 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) | 246 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) |
247 | { | 247 | { |
248 | //#ifdef WIN32 | 248 | //#ifdef WIN32 |
249 | int nWrote = TEMP_FAILURE_RETRY( | 249 | int nWrote = TEMP_FAILURE_RETRY( |
250 | bu_send( nTcpSocket, (const char *) pBuf, nBytes, 0 ) ); | 250 | bu_send( nTcpSocket, (const char *) pBuf, nBytes, 0 ) ); |
251 | //#else | 251 | //#else |
252 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nTcpSocket, pBuf, nBytes ) ); | 252 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nTcpSocket, pBuf, nBytes ) ); |
253 | //#endif | 253 | //#endif |
254 | if( nWrote < 0 ) | 254 | if( nWrote < 0 ) |
255 | { | 255 | { |
256 | #ifdef WIN32 | 256 | #ifdef WIN32 |
257 | int iWSAError = bu_WSAGetLastError(); | 257 | int iWSAError = bu_WSAGetLastError(); |
258 | if( iWSAError == WSAEWOULDBLOCK ) | 258 | if( iWSAError == WSAEWOULDBLOCK ) |
259 | return 0; | 259 | return 0; |
260 | #else | 260 | #else |
261 | if( errno == EAGAIN ) return 0; | 261 | if( errno == EAGAIN ) return 0; |
262 | #endif | 262 | #endif |
263 | throw TcpSocketException( TcpSocketException::cWrite, strerror(errno) ); | 263 | throw TcpSocketException( TcpSocketException::cWrite, strerror(errno) ); |
264 | } | 264 | } |
265 | return nWrote; | 265 | return nWrote; |
266 | } | 266 | } |
267 | 267 | ||
268 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) | 268 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) |
269 | { | 269 | { |
270 | struct timeval tv; | 270 | struct timeval tv; |
271 | Bu::size nWrote = 0; | 271 | Bu::size nWrote = 0; |
272 | 272 | ||
273 | fd_set wfds; | 273 | fd_set wfds; |
274 | FD_ZERO(&wfds); | 274 | FD_ZERO(&wfds); |
275 | FD_SET(nTcpSocket, &wfds); | 275 | FD_SET(nTcpSocket, &wfds); |
276 | 276 | ||
277 | #ifdef WIN32 | 277 | #ifdef WIN32 |
278 | DWORD dwStart = GetTickCount(); | 278 | DWORD dwStart = GetTickCount(); |
279 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | 279 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); |
280 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | 280 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; |
281 | #else | 281 | #else |
282 | struct timeval nt, ct; | 282 | struct timeval nt, ct; |
283 | gettimeofday( &nt, NULL ); | 283 | gettimeofday( &nt, NULL ); |
284 | nt.tv_sec += nSec; | 284 | nt.tv_sec += nSec; |
285 | nt.tv_usec += nUSec; | 285 | nt.tv_usec += nUSec; |
286 | #endif | 286 | #endif |
287 | 287 | ||
288 | for(;;) | 288 | for(;;) |
289 | { | 289 | { |
290 | tv.tv_sec = nSec; | 290 | tv.tv_sec = nSec; |
291 | tv.tv_usec = nUSec; | 291 | tv.tv_usec = nUSec; |
292 | bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | 292 | bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); |
293 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); | 293 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); |
294 | if( nWrote >= nBytes ) | 294 | if( nWrote >= nBytes ) |
295 | break; | 295 | break; |
296 | #ifdef WIN32 | 296 | #ifdef WIN32 |
297 | DWORD dwNow = GetTickCount(); | 297 | DWORD dwNow = GetTickCount(); |
298 | if( dwNow > dwEnd ) | 298 | if( dwNow > dwEnd ) |
299 | break; | 299 | break; |
300 | #else | 300 | #else |
301 | gettimeofday( &ct, NULL ); | 301 | gettimeofday( &ct, NULL ); |
302 | if( (ct.tv_sec > nt.tv_sec) || | 302 | if( (ct.tv_sec > nt.tv_sec) || |
303 | (ct.tv_sec == nt.tv_sec && | 303 | (ct.tv_sec == nt.tv_sec && |
304 | ct.tv_usec >= nt.tv_usec) ) | 304 | ct.tv_usec >= nt.tv_usec) ) |
305 | break; | 305 | break; |
306 | #endif | 306 | #endif |
307 | } | 307 | } |
308 | return nWrote; | 308 | return nWrote; |
309 | } | 309 | } |
310 | 310 | ||
311 | Bu::size Bu::TcpSocket::tell() | 311 | Bu::size Bu::TcpSocket::tell() |
312 | { | 312 | { |
313 | throw UnsupportedException(); | 313 | throw UnsupportedException(); |
314 | } | 314 | } |
315 | 315 | ||
316 | void Bu::TcpSocket::seek( Bu::size ) | 316 | void Bu::TcpSocket::seek( Bu::size ) |
317 | { | 317 | { |
318 | throw UnsupportedException(); | 318 | throw UnsupportedException(); |
319 | } | 319 | } |
320 | 320 | ||
321 | void Bu::TcpSocket::setPos( Bu::size ) | 321 | void Bu::TcpSocket::setPos( Bu::size ) |
322 | { | 322 | { |
323 | throw UnsupportedException(); | 323 | throw UnsupportedException(); |
324 | } | 324 | } |
325 | 325 | ||
326 | void Bu::TcpSocket::setPosEnd( Bu::size ) | 326 | void Bu::TcpSocket::setPosEnd( Bu::size ) |
327 | { | 327 | { |
328 | throw UnsupportedException(); | 328 | throw UnsupportedException(); |
329 | } | 329 | } |
330 | 330 | ||
331 | bool Bu::TcpSocket::isEos() | 331 | bool Bu::TcpSocket::isEos() |
332 | { | 332 | { |
333 | return !bActive; | 333 | return !bActive; |
334 | } | 334 | } |
335 | 335 | ||
336 | bool Bu::TcpSocket::canRead() | 336 | bool Bu::TcpSocket::canRead() |
337 | { | 337 | { |
338 | fd_set rfds; | 338 | fd_set rfds; |
339 | FD_ZERO(&rfds); | 339 | FD_ZERO(&rfds); |
340 | FD_SET(nTcpSocket, &rfds); | 340 | FD_SET(nTcpSocket, &rfds); |
341 | struct timeval tv = { 0, 0 }; | 341 | struct timeval tv = { 0, 0 }; |
342 | int retval = bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | 342 | int retval = bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); |
343 | if( retval == -1 ) | 343 | if( retval == -1 ) |
344 | throw TcpSocketException( | 344 | throw TcpSocketException( |
345 | TcpSocketException::cBadRead, | 345 | TcpSocketException::cBadRead, |
346 | "Bad Read error" | 346 | "Bad Read error" |
347 | ); | 347 | ); |
348 | 348 | ||
349 | if( !FD_ISSET( nTcpSocket, &rfds ) ) | 349 | if( !FD_ISSET( nTcpSocket, &rfds ) ) |
350 | return false; | 350 | return false; |
351 | return true; | 351 | return true; |
352 | } | 352 | } |
353 | 353 | ||
354 | bool Bu::TcpSocket::canWrite() | 354 | bool Bu::TcpSocket::canWrite() |
355 | { | 355 | { |
356 | fd_set wfds; | 356 | fd_set wfds; |
357 | FD_ZERO(&wfds); | 357 | FD_ZERO(&wfds); |
358 | FD_SET(nTcpSocket, &wfds); | 358 | FD_SET(nTcpSocket, &wfds); |
359 | struct timeval tv = { 0, 0 }; | 359 | struct timeval tv = { 0, 0 }; |
360 | int retval = bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | 360 | int retval = bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); |
361 | if( retval == -1 ) | 361 | if( retval == -1 ) |
362 | throw TcpSocketException( | 362 | throw TcpSocketException( |
363 | TcpSocketException::cBadRead, | 363 | TcpSocketException::cBadRead, |
364 | "Bad Read error" | 364 | "Bad Read error" |
365 | ); | 365 | ); |
366 | if( !FD_ISSET( nTcpSocket, &wfds ) ) | 366 | if( !FD_ISSET( nTcpSocket, &wfds ) ) |
367 | return false; | 367 | return false; |
368 | return true; | 368 | return true; |
369 | } | 369 | } |
370 | 370 | ||
371 | bool Bu::TcpSocket::isReadable() | 371 | bool Bu::TcpSocket::isReadable() |
372 | { | 372 | { |
373 | return true; | 373 | return true; |
374 | } | 374 | } |
375 | 375 | ||
376 | bool Bu::TcpSocket::isWritable() | 376 | bool Bu::TcpSocket::isWritable() |
377 | { | 377 | { |
378 | return true; | 378 | return true; |
379 | } | 379 | } |
380 | 380 | ||
381 | bool Bu::TcpSocket::isSeekable() | 381 | bool Bu::TcpSocket::isSeekable() |
382 | { | 382 | { |
383 | return false; | 383 | return false; |
384 | } | 384 | } |
385 | 385 | ||
386 | bool Bu::TcpSocket::isBlocking() | 386 | bool Bu::TcpSocket::isBlocking() |
387 | { | 387 | { |
388 | #ifndef WIN32 | 388 | #ifndef WIN32 |
389 | return ((fcntl( nTcpSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK); | 389 | return ((fcntl( nTcpSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK); |
390 | #else | 390 | #else |
391 | return false; | 391 | return false; |
392 | #endif | 392 | #endif |
393 | } | 393 | } |
394 | 394 | ||
395 | void Bu::TcpSocket::setBlocking( bool bBlocking ) | 395 | void Bu::TcpSocket::setBlocking( bool bBlocking ) |
396 | { | 396 | { |
397 | this->bBlocking = bBlocking; | 397 | this->bBlocking = bBlocking; |
398 | #ifndef WIN32 | 398 | #ifndef WIN32 |
399 | if( bBlocking ) | 399 | if( bBlocking ) |
400 | { | 400 | { |
401 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); | 401 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); |
402 | } | 402 | } |
403 | else | 403 | else |
404 | { | 404 | { |
405 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); | 405 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); |
406 | } | 406 | } |
407 | #else | 407 | #else |
408 | u_long iMode; | 408 | u_long iMode; |
409 | if( bBlocking ) | 409 | if( bBlocking ) |
410 | iMode = 0; | 410 | iMode = 0; |
411 | else | 411 | else |
412 | iMode = 1; | 412 | iMode = 1; |
413 | //------------------------- | 413 | //------------------------- |
414 | // Set the socket I/O mode: In this case FIONBIO | 414 | // Set the socket I/O mode: In this case FIONBIO |
415 | // enables or disables the blocking mode for the | 415 | // enables or disables the blocking mode for the |
416 | // socket based on the numerical value of iMode. | 416 | // socket based on the numerical value of iMode. |
417 | // If iMode = 0, blocking is enabled; | 417 | // If iMode = 0, blocking is enabled; |
418 | // If iMode != 0, non-blocking mode is enabled. | 418 | // If iMode != 0, non-blocking mode is enabled. |
419 | bu_ioctlsocket(nTcpSocket, FIONBIO, &iMode); | 419 | bu_ioctlsocket(nTcpSocket, FIONBIO, &iMode); |
420 | #endif | 420 | #endif |
421 | } | 421 | } |
422 | 422 | ||
423 | void Bu::TcpSocket::setSize( Bu::size ) | 423 | void Bu::TcpSocket::setSize( Bu::size ) |
@@ -430,53 +430,53 @@ void Bu::TcpSocket::flush() | |||
430 | 430 | ||
431 | bool Bu::TcpSocket::isOpen() | 431 | bool Bu::TcpSocket::isOpen() |
432 | { | 432 | { |
433 | return bActive; | 433 | return bActive; |
434 | } | 434 | } |
435 | 435 | ||
436 | void Bu::TcpSocket::setAddress() | 436 | void Bu::TcpSocket::setAddress() |
437 | { | 437 | { |
438 | struct sockaddr_in addr; | 438 | struct sockaddr_in addr; |
439 | socklen_t len = sizeof(addr); | 439 | socklen_t len = sizeof(addr); |
440 | addr.sin_family = AF_INET; | 440 | addr.sin_family = AF_INET; |
441 | bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); | 441 | bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); |
442 | sAddress = bu_inet_ntoa( addr.sin_addr ); | 442 | sAddress = bu_inet_ntoa( addr.sin_addr ); |
443 | } | 443 | } |
444 | 444 | ||
445 | Bu::String Bu::TcpSocket::getAddress() const | 445 | Bu::String Bu::TcpSocket::getAddress() const |
446 | { | 446 | { |
447 | return sAddress; | 447 | return sAddress; |
448 | } | 448 | } |
449 | 449 | ||
450 | Bu::TcpSocket::operator Bu::TcpSocket::handle() const | 450 | Bu::TcpSocket::operator Bu::TcpSocket::handle() const |
451 | { | 451 | { |
452 | return nTcpSocket; | 452 | return nTcpSocket; |
453 | } | 453 | } |
454 | 454 | ||
455 | Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const | 455 | Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const |
456 | { | 456 | { |
457 | return nTcpSocket; | 457 | return nTcpSocket; |
458 | } | 458 | } |
459 | 459 | ||
460 | Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() | 460 | Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() |
461 | { | 461 | { |
462 | handle nRet = nTcpSocket; | 462 | handle nRet = nTcpSocket; |
463 | bActive = false; | 463 | bActive = false; |
464 | nTcpSocket = 0; | 464 | nTcpSocket = 0; |
465 | return nRet; | 465 | return nRet; |
466 | } | 466 | } |
467 | 467 | ||
468 | Bu::size Bu::TcpSocket::getSize() const | 468 | Bu::size Bu::TcpSocket::getSize() const |
469 | { | 469 | { |
470 | throw UnsupportedException(); | 470 | throw UnsupportedException(); |
471 | } | 471 | } |
472 | 472 | ||
473 | Bu::size Bu::TcpSocket::getBlockSize() const | 473 | Bu::size Bu::TcpSocket::getBlockSize() const |
474 | { | 474 | { |
475 | return 1500; //TODO: Fix this, it's stupid. | 475 | return 1500; //TODO: Fix this, it's stupid. |
476 | } | 476 | } |
477 | 477 | ||
478 | Bu::String Bu::TcpSocket::getLocation() const | 478 | Bu::String Bu::TcpSocket::getLocation() const |
479 | { | 479 | { |
480 | return getAddress(); | 480 | return getAddress(); |
481 | } | 481 | } |
482 | 482 | ||
diff --git a/src/stable/tcpsocket.h b/src/stable/tcpsocket.h index 92b3c1f..16eca12 100644 --- a/src/stable/tcpsocket.h +++ b/src/stable/tcpsocket.h | |||
@@ -17,110 +17,110 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | subExceptionDeclBegin( TcpSocketException ); | 20 | subExceptionDeclBegin( TcpSocketException ); |
21 | enum { | 21 | enum { |
22 | cRead, | 22 | cRead, |
23 | cWrite, | 23 | cWrite, |
24 | cBadRead, | 24 | cBadRead, |
25 | cClosed, | 25 | cClosed, |
26 | cTimeout | 26 | cTimeout |
27 | }; | 27 | }; |
28 | subExceptionDeclEnd(); | 28 | subExceptionDeclEnd(); |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Network socket stream class. This class provides a mechanism for | 31 | * Network socket stream class. This class provides a mechanism for |
32 | * communicating over a network using TCP/IP. It will provide other low | 32 | * communicating over a network using TCP/IP. It will provide other low |
33 | * level protocol and addressing support later on, but for now it's just | 33 | * level protocol and addressing support later on, but for now it's just |
34 | * standard STREAM TCP/IP sockets. | 34 | * standard STREAM TCP/IP sockets. |
35 | * | 35 | * |
36 | * Unlike system sockets, these sockets are opened by default in | 36 | * Unlike system sockets, these sockets are opened by default in |
37 | * non-blocking mode, you can specify your own timeout for opening a socket, | 37 | * non-blocking mode, you can specify your own timeout for opening a socket, |
38 | * and a number of non-fatal error messages have been automatically handled | 38 | * and a number of non-fatal error messages have been automatically handled |
39 | * and treated as standard no-data-available-yet situations on read. | 39 | * and treated as standard no-data-available-yet situations on read. |
40 | * | 40 | * |
41 | * Please note that there is a condition that will occur eventually (at | 41 | * Please note that there is a condition that will occur eventually (at |
42 | * least on *nix systems) that will trigger a SIGPIPE condition. This | 42 | * least on *nix systems) that will trigger a SIGPIPE condition. This |
43 | * will terminate your program immediately unless handled properly. Most | 43 | * will terminate your program immediately unless handled properly. Most |
44 | * people doing any connections with TcpSocket will want to put this in | 44 | * people doing any connections with TcpSocket will want to put this in |
45 | * their program somewhere before they use it: | 45 | * their program somewhere before they use it: |
46 | *@code | 46 | *@code |
47 | #include <signal.h> | 47 | #include <signal.h> |
48 | ... | 48 | ... |
49 | ... | 49 | ... |
50 | ... | 50 | ... |
51 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::TcpSocket | 51 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::TcpSocket |
52 | @endcode | 52 | @endcode |
53 | * When this is done, Bu::TcpSocket will simply throw a broken pipe | 53 | * When this is done, Bu::TcpSocket will simply throw a broken pipe |
54 | * exception just like every other error condition, allowing your program | 54 | * exception just like every other error condition, allowing your program |
55 | * to handle it sanely. | 55 | * to handle it sanely. |
56 | * | 56 | * |
57 | *@ingroup Serving | 57 | *@ingroup Serving |
58 | *@ingroup Streams | 58 | *@ingroup Streams |
59 | */ | 59 | */ |
60 | class TcpSocket : public Stream | 60 | class TcpSocket : public Stream |
61 | { | 61 | { |
62 | public: | 62 | public: |
63 | #ifdef WIN32 | 63 | #ifdef WIN32 |
64 | typedef unsigned int handle; | 64 | typedef unsigned int handle; |
65 | #else | 65 | #else |
66 | typedef int handle; | 66 | typedef int handle; |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | TcpSocket( handle nTcpSocket ); | 69 | TcpSocket( handle nTcpSocket ); |
70 | TcpSocket( const String &sAddr, int nPort, int nTimeout=30, | 70 | TcpSocket( const String &sAddr, int nPort, int nTimeout=30, |
71 | bool bBlocking=true ); | 71 | bool bBlocking=true ); |
72 | virtual ~TcpSocket(); | 72 | virtual ~TcpSocket(); |
73 | 73 | ||
74 | virtual void close(); | 74 | virtual void close(); |
75 | virtual size read( void *pBuf, size nBytes ); | 75 | virtual size read( void *pBuf, size nBytes ); |
76 | virtual size read( void *pBuf, size nBytes, | 76 | virtual size read( void *pBuf, size nBytes, |
77 | uint32_t nSec, uint32_t nUSec=0 ); | 77 | uint32_t nSec, uint32_t nUSec=0 ); |
78 | virtual size write( const void *pBuf, size nBytes ); | 78 | virtual size write( const void *pBuf, size nBytes ); |
79 | virtual size write( const void *pBuf, size nBytes, | 79 | virtual size write( const void *pBuf, size nBytes, |
80 | uint32_t nSec, uint32_t nUSec=0 ); | 80 | uint32_t nSec, uint32_t nUSec=0 ); |
81 | using Stream::write; | 81 | using Stream::write; |
82 | 82 | ||
83 | virtual size tell(); | 83 | virtual size tell(); |
84 | virtual void seek( size offset ); | 84 | virtual void seek( size offset ); |
85 | virtual void setPos( size pos ); | 85 | virtual void setPos( size pos ); |
86 | virtual void setPosEnd( size pos ); | 86 | virtual void setPosEnd( size pos ); |
87 | virtual bool isEos(); | 87 | virtual bool isEos(); |
88 | virtual bool isOpen(); | 88 | virtual bool isOpen(); |
89 | 89 | ||
90 | virtual void flush(); | 90 | virtual void flush(); |
91 | 91 | ||
92 | virtual bool canRead(); | 92 | virtual bool canRead(); |
93 | virtual bool canWrite(); | 93 | virtual bool canWrite(); |
94 | 94 | ||
95 | virtual bool isReadable(); | 95 | virtual bool isReadable(); |
96 | virtual bool isWritable(); | 96 | virtual bool isWritable(); |
97 | virtual bool isSeekable(); | 97 | virtual bool isSeekable(); |
98 | 98 | ||
99 | virtual bool isBlocking(); | 99 | virtual bool isBlocking(); |
100 | virtual void setBlocking( bool bBlocking=true ); | 100 | virtual void setBlocking( bool bBlocking=true ); |
101 | 101 | ||
102 | virtual void setSize( size iSize ); | 102 | virtual void setSize( size iSize ); |
103 | 103 | ||
104 | Bu::String getAddress() const; | 104 | Bu::String getAddress() const; |
105 | operator handle() const; | 105 | operator handle() const; |
106 | 106 | ||
107 | handle getHandle() const; | 107 | handle getHandle() const; |
108 | handle takeHandle(); | 108 | handle takeHandle(); |
109 | 109 | ||
110 | virtual size getSize() const; | 110 | virtual size getSize() const; |
111 | virtual size getBlockSize() const; | 111 | virtual size getBlockSize() const; |
112 | virtual Bu::String getLocation() const; | 112 | virtual Bu::String getLocation() const; |
113 | 113 | ||
114 | private: | 114 | private: |
115 | void setAddress(); | 115 | void setAddress(); |
116 | 116 | ||
117 | handle nTcpSocket; | 117 | handle nTcpSocket; |
118 | 118 | ||
119 | bool bActive; | 119 | bool bActive; |
120 | bool bBlocking; | 120 | bool bBlocking; |
121 | String sReadBuf; | 121 | String sReadBuf; |
122 | String sAddress; | 122 | String sAddress; |
123 | }; | 123 | }; |
124 | } | 124 | } |
125 | 125 | ||
126 | #endif | 126 | #endif |
diff --git a/src/stable/thread.cpp b/src/stable/thread.cpp index 30443e6..ddb7ff5 100644 --- a/src/stable/thread.cpp +++ b/src/stable/thread.cpp | |||
@@ -10,7 +10,7 @@ | |||
10 | namespace Bu { subExceptionDef( ThreadException ); } | 10 | namespace Bu { subExceptionDef( ThreadException ); } |
11 | 11 | ||
12 | Bu::ThreadId::ThreadId( pthread_t tId ) : | 12 | Bu::ThreadId::ThreadId( pthread_t tId ) : |
13 | tId( tId ) | 13 | tId( tId ) |
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
@@ -20,12 +20,12 @@ Bu::ThreadId::ThreadId() | |||
20 | 20 | ||
21 | bool Bu::ThreadId::operator==( const Bu::ThreadId &rhs ) | 21 | bool Bu::ThreadId::operator==( const Bu::ThreadId &rhs ) |
22 | { | 22 | { |
23 | return pthread_equal( tId, rhs.tId ); | 23 | return pthread_equal( tId, rhs.tId ); |
24 | } | 24 | } |
25 | 25 | ||
26 | bool Bu::ThreadId::operator!=( const ThreadId &rhs ) | 26 | bool Bu::ThreadId::operator!=( const ThreadId &rhs ) |
27 | { | 27 | { |
28 | return !pthread_equal( tId, rhs.tId ); | 28 | return !pthread_equal( tId, rhs.tId ); |
29 | } | 29 | } |
30 | 30 | ||
31 | Bu::Thread::Thread() | 31 | Bu::Thread::Thread() |
@@ -38,45 +38,45 @@ Bu::Thread::~Thread() | |||
38 | 38 | ||
39 | Bu::ThreadId Bu::Thread::currentThread() | 39 | Bu::ThreadId Bu::Thread::currentThread() |
40 | { | 40 | { |
41 | return ThreadId( pthread_self() ); | 41 | return ThreadId( pthread_self() ); |
42 | } | 42 | } |
43 | 43 | ||
44 | bool Bu::Thread::start() | 44 | bool Bu::Thread::start() |
45 | { | 45 | { |
46 | if( pthread_create( &ptHandle, NULL, threadRunner, this ) ) | 46 | if( pthread_create( &ptHandle, NULL, threadRunner, this ) ) |
47 | { | 47 | { |
48 | throw Bu::ThreadException("Could not start thread."); | 48 | throw Bu::ThreadException("Could not start thread."); |
49 | } | 49 | } |
50 | 50 | ||
51 | return true; | 51 | return true; |
52 | } | 52 | } |
53 | 53 | ||
54 | bool Bu::Thread::stop() | 54 | bool Bu::Thread::stop() |
55 | { | 55 | { |
56 | pthread_cancel( ptHandle ); | 56 | pthread_cancel( ptHandle ); |
57 | 57 | ||
58 | return true; | 58 | return true; |
59 | } | 59 | } |
60 | 60 | ||
61 | void *Bu::Thread::threadRunner( void *pThread ) | 61 | void *Bu::Thread::threadRunner( void *pThread ) |
62 | { | 62 | { |
63 | ((Thread *)pThread)->run(); | 63 | ((Thread *)pThread)->run(); |
64 | pthread_exit( NULL ); | 64 | pthread_exit( NULL ); |
65 | return NULL; | 65 | return NULL; |
66 | } | 66 | } |
67 | 67 | ||
68 | bool Bu::Thread::join() | 68 | bool Bu::Thread::join() |
69 | { | 69 | { |
70 | pthread_join( ptHandle, NULL ); | 70 | pthread_join( ptHandle, NULL ); |
71 | return true; | 71 | return true; |
72 | } | 72 | } |
73 | 73 | ||
74 | void Bu::Thread::yield() | 74 | void Bu::Thread::yield() |
75 | { | 75 | { |
76 | #ifndef WIN32 | 76 | #ifndef WIN32 |
77 | pthread_yield(); | 77 | pthread_yield(); |
78 | #else | 78 | #else |
79 | sched_yield(); | 79 | sched_yield(); |
80 | #endif | 80 | #endif |
81 | } | 81 | } |
82 | 82 | ||
diff --git a/src/stable/thread.h b/src/stable/thread.h index ae07665..ca3ab9f 100644 --- a/src/stable/thread.h +++ b/src/stable/thread.h | |||
@@ -15,120 +15,120 @@ | |||
15 | 15 | ||
16 | namespace Bu | 16 | namespace Bu |
17 | { | 17 | { |
18 | subExceptionDecl( ThreadException ); | 18 | subExceptionDecl( ThreadException ); |
19 | class ThreadId | 19 | class ThreadId |
20 | { | 20 | { |
21 | friend class Thread; | 21 | friend class Thread; |
22 | private: | 22 | private: |
23 | ThreadId( pthread_t tId ); | 23 | ThreadId( pthread_t tId ); |
24 | 24 | ||
25 | public: | 25 | public: |
26 | ThreadId(); | 26 | ThreadId(); |
27 | 27 | ||
28 | bool operator==( const ThreadId &rhs ); | 28 | bool operator==( const ThreadId &rhs ); |
29 | bool operator!=( const ThreadId &rhs ); | 29 | bool operator!=( const ThreadId &rhs ); |
30 | 30 | ||
31 | private: | 31 | private: |
32 | pthread_t tId; | 32 | pthread_t tId; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Simple thread class. This wraps the basic pthread (posix threads) | 36 | * Simple thread class. This wraps the basic pthread (posix threads) |
37 | * system in an object oriented sort of way. It allows you to create a | 37 | * system in an object oriented sort of way. It allows you to create a |
38 | * class with standard member variables and callable functions that can be | 38 | * class with standard member variables and callable functions that can be |
39 | * run in it's own thread, one per class instance. | 39 | * run in it's own thread, one per class instance. |
40 | *@ingroup Threading | 40 | *@ingroup Threading |
41 | */ | 41 | */ |
42 | class Thread | 42 | class Thread |
43 | { | 43 | { |
44 | public: | 44 | public: |
45 | /** | 45 | /** |
46 | * Construct an Thread thread. | 46 | * Construct an Thread thread. |
47 | */ | 47 | */ |
48 | Thread(); | 48 | Thread(); |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Destroy an Thread thread. | 51 | * Destroy an Thread thread. |
52 | */ | 52 | */ |
53 | virtual ~Thread(); | 53 | virtual ~Thread(); |
54 | 54 | ||
55 | static ThreadId currentThread(); | 55 | static ThreadId currentThread(); |
56 | ThreadId getId() { return ThreadId( ptHandle ); } | 56 | ThreadId getId() { return ThreadId( ptHandle ); } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * Begin thread execution. This will call the overridden run function, | 59 | * Begin thread execution. This will call the overridden run function, |
60 | * which will simply execute in it's own thread until the function | 60 | * which will simply execute in it's own thread until the function |
61 | * exits, the thread is killed, or the thread is cancelled (optionally). | 61 | * exits, the thread is killed, or the thread is cancelled (optionally). |
62 | * The thread started in this manner has access to all of it's class | 62 | * The thread started in this manner has access to all of it's class |
63 | * variables, but be sure to protect possible multiple-access with | 63 | * variables, but be sure to protect possible multiple-access with |
64 | * ThreadMutex objects. | 64 | * ThreadMutex objects. |
65 | * @returns True if starting the thread was successful. False if | 65 | * @returns True if starting the thread was successful. False if |
66 | * something went wrong and the thread has not started. | 66 | * something went wrong and the thread has not started. |
67 | */ | 67 | */ |
68 | bool start(); | 68 | bool start(); |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Forcibly kill a thread. This is not generally considered a good | 71 | * Forcibly kill a thread. This is not generally considered a good |
72 | * thing to do, but in those rare cases you need it, it's invaluable. | 72 | * thing to do, but in those rare cases you need it, it's invaluable. |
73 | * The problem with stopping (or killing) a thread is that it stops it | 73 | * The problem with stopping (or killing) a thread is that it stops it |
74 | * the moment you call stop, no matter what it's doing. The object | 74 | * the moment you call stop, no matter what it's doing. The object |
75 | * oriented approach to this will help clean up any class variables | 75 | * oriented approach to this will help clean up any class variables |
76 | * that were used, but anything not managed as a member variable will | 76 | * that were used, but anything not managed as a member variable will |
77 | * probably create a memory leak type of situation. Instead of stop, | 77 | * probably create a memory leak type of situation. Instead of stop, |
78 | * consider using cancel, which can be handled by the running thread in | 78 | * consider using cancel, which can be handled by the running thread in |
79 | * a graceful manner. | 79 | * a graceful manner. |
80 | *@returns True if the thread was stopped, false otherwise. When this | 80 | *@returns True if the thread was stopped, false otherwise. When this |
81 | * function returns the thread may not have stopped, to ensure that the | 81 | * function returns the thread may not have stopped, to ensure that the |
82 | * thread has really stopped, call join. | 82 | * thread has really stopped, call join. |
83 | */ | 83 | */ |
84 | bool stop(); | 84 | bool stop(); |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * Join the thread in action. This function performs what is commonly | 87 | * Join the thread in action. This function performs what is commonly |
88 | * called a thread join. That is that it effectively makes the calling | 88 | * called a thread join. That is that it effectively makes the calling |
89 | * thread an the Thread thread contained in the called object one in the | 89 | * thread an the Thread thread contained in the called object one in the |
90 | * same, and pauses the calling thread until the called thread exits. | 90 | * same, and pauses the calling thread until the called thread exits. |
91 | * That is, when called from, say, your main(), mythread.join() will | 91 | * That is, when called from, say, your main(), mythread.join() will |
92 | * not return until the thread mythread has exited. This is very handy | 92 | * not return until the thread mythread has exited. This is very handy |
93 | * at the end of programs to ensure all of your data was cleaned up. | 93 | * at the end of programs to ensure all of your data was cleaned up. |
94 | *@returns True if the thread was joined, false if the thread couldn't | 94 | *@returns True if the thread was joined, false if the thread couldn't |
95 | * be joined, usually because it isn't running to begin with. | 95 | * be joined, usually because it isn't running to begin with. |
96 | */ | 96 | */ |
97 | bool join(); | 97 | bool join(); |
98 | 98 | ||
99 | private: | 99 | private: |
100 | pthread_t ptHandle; /**< Internal handle to the posix thread. */ | 100 | pthread_t ptHandle; /**< Internal handle to the posix thread. */ |
101 | 101 | ||
102 | protected: | 102 | protected: |
103 | /** | 103 | /** |
104 | * The workhorse of the Thread class. This is the function that will | 104 | * The workhorse of the Thread class. This is the function that will |
105 | * run in the thread, when this function exits the thread dies and is | 105 | * run in the thread, when this function exits the thread dies and is |
106 | * cleaned up by the system. Make sure to read up on Bu::Mutex, | 106 | * cleaned up by the system. Make sure to read up on Bu::Mutex, |
107 | * Bu::Condition, and the Bu::Synchro* classes to see how to control | 107 | * Bu::Condition, and the Bu::Synchro* classes to see how to control |
108 | * and protect everything you do in a safe way within this function. | 108 | * and protect everything you do in a safe way within this function. |
109 | *@returns I'm not sure right now, but this is the posix standard form. | 109 | *@returns I'm not sure right now, but this is the posix standard form. |
110 | */ | 110 | */ |
111 | virtual void run()=0; | 111 | virtual void run()=0; |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * Gives up some cpu-time in the currently running thread. If a thread | 114 | * Gives up some cpu-time in the currently running thread. If a thread |
115 | * is working hard, but you want to give other threads on the system | 115 | * is working hard, but you want to give other threads on the system |
116 | * some time to do some work, call yield. | 116 | * some time to do some work, call yield. |
117 | */ | 117 | */ |
118 | void yield(); | 118 | void yield(); |
119 | 119 | ||
120 | private: | 120 | private: |
121 | /** | 121 | /** |
122 | * This is the hidden-heart of the thread system. While run is what the | 122 | * This is the hidden-heart of the thread system. While run is what the |
123 | * user gets to override, and everything said about it is true, this is | 123 | * user gets to override, and everything said about it is true, this is |
124 | * the function that actually makes up the thread, it simply calls the | 124 | * the function that actually makes up the thread, it simply calls the |
125 | * run member function in an OO-friendly way. This is what allows us to | 125 | * run member function in an OO-friendly way. This is what allows us to |
126 | * use member variables from within the thread itself. | 126 | * use member variables from within the thread itself. |
127 | *@param pThread Should always be this. | 127 | *@param pThread Should always be this. |
128 | *@returns This is specified by posix, I'm not sure yet. | 128 | *@returns This is specified by posix, I'm not sure yet. |
129 | */ | 129 | */ |
130 | static void *threadRunner( void *pThread ); | 130 | static void *threadRunner( void *pThread ); |
131 | }; | 131 | }; |
132 | } | 132 | } |
133 | 133 | ||
134 | #endif | 134 | #endif |
diff --git a/src/stable/trace.cpp b/src/stable/trace.cpp index c072fd9..2b3b863 100644 --- a/src/stable/trace.cpp +++ b/src/stable/trace.cpp | |||
@@ -9,59 +9,59 @@ | |||
9 | 9 | ||
10 | void Bu::__tracer( const char *pf ) | 10 | void Bu::__tracer( const char *pf ) |
11 | { | 11 | { |
12 | printf("trace: %s\n", pf ); | 12 | printf("trace: %s\n", pf ); |
13 | } | 13 | } |
14 | 14 | ||
15 | template<> void Bu::__tracer_format<float>( const float &v ) | 15 | template<> void Bu::__tracer_format<float>( const float &v ) |
16 | { | 16 | { |
17 | printf("%f", v ); | 17 | printf("%f", v ); |
18 | } | 18 | } |
19 | 19 | ||
20 | template<> void Bu::__tracer_format<double>( const double &v ) | 20 | template<> void Bu::__tracer_format<double>( const double &v ) |
21 | { | 21 | { |
22 | printf("%f", v ); | 22 | printf("%f", v ); |
23 | } | 23 | } |
24 | 24 | ||
25 | template<> void Bu::__tracer_format<void *>( void * const &v ) | 25 | template<> void Bu::__tracer_format<void *>( void * const &v ) |
26 | { | 26 | { |
27 | printf("0x%08X", (ptrdiff_t)v ); | 27 | printf("0x%08X", (ptrdiff_t)v ); |
28 | } | 28 | } |
29 | 29 | ||
30 | template<> void Bu::__tracer_format<char *>( char * const &v ) | 30 | template<> void Bu::__tracer_format<char *>( char * const &v ) |
31 | { | 31 | { |
32 | printf("\"%s\"", v ); | 32 | printf("\"%s\"", v ); |
33 | } | 33 | } |
34 | 34 | ||
35 | template<> void Bu::__tracer_format<char **>( char ** const &v ) | 35 | template<> void Bu::__tracer_format<char **>( char ** const &v ) |
36 | { | 36 | { |
37 | printf("["); | 37 | printf("["); |
38 | for( int j = 0; v[j]; j++ ) | 38 | for( int j = 0; v[j]; j++ ) |
39 | { | 39 | { |
40 | if( j > 0 ) | 40 | if( j > 0 ) |
41 | printf(", "); | 41 | printf(", "); |
42 | printf("\"%s\"", v[j] ); | 42 | printf("\"%s\"", v[j] ); |
43 | } | 43 | } |
44 | printf("]"); | 44 | printf("]"); |
45 | } | 45 | } |
46 | 46 | ||
47 | template<> void Bu::__tracer_format<void const *>( void const * const &v ) | 47 | template<> void Bu::__tracer_format<void const *>( void const * const &v ) |
48 | { | 48 | { |
49 | printf("0x%08X", (ptrdiff_t)v ); | 49 | printf("0x%08X", (ptrdiff_t)v ); |
50 | } | 50 | } |
51 | 51 | ||
52 | template<> void Bu::__tracer_format<char const *>( char const * const &v ) | 52 | template<> void Bu::__tracer_format<char const *>( char const * const &v ) |
53 | { | 53 | { |
54 | printf("\"%s\"", v ); | 54 | printf("\"%s\"", v ); |
55 | } | 55 | } |
56 | 56 | ||
57 | template<> void Bu::__tracer_format<char const **>( char const ** const &v ) | 57 | template<> void Bu::__tracer_format<char const **>( char const ** const &v ) |
58 | { | 58 | { |
59 | printf("["); | 59 | printf("["); |
60 | for( int j = 0; v[j]; j++ ) | 60 | for( int j = 0; v[j]; j++ ) |
61 | { | 61 | { |
62 | if( j > 0 ) | 62 | if( j > 0 ) |
63 | printf(", "); | 63 | printf(", "); |
64 | printf("\"%s\"", v[j] ); | 64 | printf("\"%s\"", v[j] ); |
65 | } | 65 | } |
66 | printf("]"); | 66 | printf("]"); |
67 | } | 67 | } |
diff --git a/src/stable/trace.h b/src/stable/trace.h index da67f03..d47df9c 100644 --- a/src/stable/trace.h +++ b/src/stable/trace.h | |||
@@ -17,165 +17,165 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /* template<typename t> void __tracer_format( t &v ) | 20 | /* template<typename t> void __tracer_format( t &v ) |
21 | { | 21 | { |
22 | __tracer_format( *const_cast<const t *>(&v) ); | 22 | __tracer_format( *const_cast<const t *>(&v) ); |
23 | } | 23 | } |
24 | */ | 24 | */ |
25 | template<typename t> void __tracer_format( const t &v ) | 25 | template<typename t> void __tracer_format( const t &v ) |
26 | { | 26 | { |
27 | Bu::sio << v; | 27 | Bu::sio << v; |
28 | } | 28 | } |
29 | 29 | ||
30 | void __tracer( const char *pf ); | 30 | void __tracer( const char *pf ); |
31 | 31 | ||
32 | #define looper( vv ) \ | 32 | #define looper( vv ) \ |
33 | for( ; *n; n++ ) \ | 33 | for( ; *n; n++ ) \ |
34 | { \ | 34 | { \ |
35 | if( bInBracket == true ) \ | 35 | if( bInBracket == true ) \ |
36 | { \ | 36 | { \ |
37 | if( *n == '>' ) \ | 37 | if( *n == '>' ) \ |
38 | bInBracket = false; \ | 38 | bInBracket = false; \ |
39 | } \ | 39 | } \ |
40 | else if( *n == ',' || *n == ')' ) \ | 40 | else if( *n == ',' || *n == ')' ) \ |
41 | { \ | 41 | { \ |
42 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, 1, stdout ); \ | 42 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, 1, stdout ); \ |
43 | fwrite("=", 1, 1, stdout); \ | 43 | fwrite("=", 1, 1, stdout); \ |
44 | __tracer_format( vv ); \ | 44 | __tracer_format( vv ); \ |
45 | s = n; \ | 45 | s = n; \ |
46 | n++; \ | 46 | n++; \ |
47 | break; \ | 47 | break; \ |
48 | } \ | 48 | } \ |
49 | else if( *n == '<' ) \ | 49 | else if( *n == '<' ) \ |
50 | { \ | 50 | { \ |
51 | bInBracket = true; \ | 51 | bInBracket = true; \ |
52 | } \ | 52 | } \ |
53 | } (void)0 | 53 | } (void)0 |
54 | 54 | ||
55 | template<typename t1> void __tracer( const char *pf, t1 &v1 ) | 55 | template<typename t1> void __tracer( const char *pf, t1 &v1 ) |
56 | { | 56 | { |
57 | printf("trace: "); | 57 | printf("trace: "); |
58 | const char *s = pf; | 58 | const char *s = pf; |
59 | const char *n = pf; | 59 | const char *n = pf; |
60 | bool bInBracket = false; | 60 | bool bInBracket = false; |
61 | looper( v1 ); | 61 | looper( v1 ); |
62 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 62 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
63 | fwrite( "\n", 1, 1, stdout ); | 63 | fwrite( "\n", 1, 1, stdout ); |
64 | fflush( stdout ); | 64 | fflush( stdout ); |
65 | } | 65 | } |
66 | 66 | ||
67 | template<typename t1, typename t2> void __tracer( const char *pf, | 67 | template<typename t1, typename t2> void __tracer( const char *pf, |
68 | t1 &v1, t2 &v2 ) | 68 | t1 &v1, t2 &v2 ) |
69 | { | 69 | { |
70 | printf("trace: "); | 70 | printf("trace: "); |
71 | const char *s = pf; | 71 | const char *s = pf; |
72 | const char *n = pf; | 72 | const char *n = pf; |
73 | bool bInBracket = false; | 73 | bool bInBracket = false; |
74 | looper( v1 ); | 74 | looper( v1 ); |
75 | looper( v2 ); | 75 | looper( v2 ); |
76 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 76 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
77 | fwrite( "\n", 1, 1, stdout ); | 77 | fwrite( "\n", 1, 1, stdout ); |
78 | fflush( stdout ); | 78 | fflush( stdout ); |
79 | } | 79 | } |
80 | 80 | ||
81 | template<typename t1, typename t2, typename t3> | 81 | template<typename t1, typename t2, typename t3> |
82 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3 ) | 82 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3 ) |
83 | { | 83 | { |
84 | printf("trace: "); | 84 | printf("trace: "); |
85 | const char *s = pf; | 85 | const char *s = pf; |
86 | const char *n = pf; | 86 | const char *n = pf; |
87 | bool bInBracket = false; | 87 | bool bInBracket = false; |
88 | looper( v1 ); | 88 | looper( v1 ); |
89 | looper( v2 ); | 89 | looper( v2 ); |
90 | looper( v3 ); | 90 | looper( v3 ); |
91 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 91 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
92 | fwrite( "\n", 1, 1, stdout ); | 92 | fwrite( "\n", 1, 1, stdout ); |
93 | fflush( stdout ); | 93 | fflush( stdout ); |
94 | } | 94 | } |
95 | 95 | ||
96 | template<typename t1, typename t2, typename t3, typename t4> | 96 | template<typename t1, typename t2, typename t3, typename t4> |
97 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4 ) | 97 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4 ) |
98 | { | 98 | { |
99 | printf("trace: "); | 99 | printf("trace: "); |
100 | const char *s = pf; | 100 | const char *s = pf; |
101 | const char *n = pf; | 101 | const char *n = pf; |
102 | bool bInBracket = false; | 102 | bool bInBracket = false; |
103 | looper( v1 ); | 103 | looper( v1 ); |
104 | looper( v2 ); | 104 | looper( v2 ); |
105 | looper( v3 ); | 105 | looper( v3 ); |
106 | looper( v4 ); | 106 | looper( v4 ); |
107 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 107 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
108 | fwrite( "\n", 1, 1, stdout ); | 108 | fwrite( "\n", 1, 1, stdout ); |
109 | fflush( stdout ); | 109 | fflush( stdout ); |
110 | } | 110 | } |
111 | 111 | ||
112 | template<typename t1, typename t2, typename t3, typename t4, typename t5> | 112 | template<typename t1, typename t2, typename t3, typename t4, typename t5> |
113 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5 ) | 113 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5 ) |
114 | { | 114 | { |
115 | printf("trace: "); | 115 | printf("trace: "); |
116 | const char *s = pf; | 116 | const char *s = pf; |
117 | const char *n = pf; | 117 | const char *n = pf; |
118 | bool bInBracket = false; | 118 | bool bInBracket = false; |
119 | looper( v1 ); | 119 | looper( v1 ); |
120 | looper( v2 ); | 120 | looper( v2 ); |
121 | looper( v3 ); | 121 | looper( v3 ); |
122 | looper( v4 ); | 122 | looper( v4 ); |
123 | looper( v5 ); | 123 | looper( v5 ); |
124 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 124 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
125 | fwrite( "\n", 1, 1, stdout ); | 125 | fwrite( "\n", 1, 1, stdout ); |
126 | fflush( stdout ); | 126 | fflush( stdout ); |
127 | } | 127 | } |
128 | 128 | ||
129 | template<typename t1, typename t2, typename t3, typename t4, typename t5, | 129 | template<typename t1, typename t2, typename t3, typename t4, typename t5, |
130 | typename t6> | 130 | typename t6> |
131 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, | 131 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, |
132 | t6 &v6) | 132 | t6 &v6) |
133 | { | 133 | { |
134 | printf("trace: "); | 134 | printf("trace: "); |
135 | const char *s = pf; | 135 | const char *s = pf; |
136 | const char *n = pf; | 136 | const char *n = pf; |
137 | bool bInBracket = false; | 137 | bool bInBracket = false; |
138 | looper( v1 ); | 138 | looper( v1 ); |
139 | looper( v2 ); | 139 | looper( v2 ); |
140 | looper( v3 ); | 140 | looper( v3 ); |
141 | looper( v4 ); | 141 | looper( v4 ); |
142 | looper( v5 ); | 142 | looper( v5 ); |
143 | looper( v6 ); | 143 | looper( v6 ); |
144 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 144 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
145 | fwrite( "\n", 1, 1, stdout ); | 145 | fwrite( "\n", 1, 1, stdout ); |
146 | fflush( stdout ); | 146 | fflush( stdout ); |
147 | } | 147 | } |
148 | 148 | ||
149 | template<typename t1, typename t2, typename t3, typename t4, typename t5, | 149 | template<typename t1, typename t2, typename t3, typename t4, typename t5, |
150 | typename t6, typename t7> | 150 | typename t6, typename t7> |
151 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, | 151 | void __tracer( const char *pf, t1 &v1, t2 &v2, t3 &v3, t4 &v4, t5 &v5, |
152 | t6 &v6, t7 &v7 ) | 152 | t6 &v6, t7 &v7 ) |
153 | { | 153 | { |
154 | printf("trace: "); | 154 | printf("trace: "); |
155 | const char *s = pf; | 155 | const char *s = pf; |
156 | const char *n = pf; | 156 | const char *n = pf; |
157 | bool bInBracket = false; | 157 | bool bInBracket = false; |
158 | looper( v1 ); | 158 | looper( v1 ); |
159 | looper( v2 ); | 159 | looper( v2 ); |
160 | looper( v3 ); | 160 | looper( v3 ); |
161 | looper( v4 ); | 161 | looper( v4 ); |
162 | looper( v5 ); | 162 | looper( v5 ); |
163 | looper( v6 ); | 163 | looper( v6 ); |
164 | looper( v7 ); | 164 | looper( v7 ); |
165 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); | 165 | fwrite( s, (ptrdiff_t)n-(ptrdiff_t)s, strlen(s), stdout ); |
166 | fwrite( "\n", 1, 1, stdout ); | 166 | fwrite( "\n", 1, 1, stdout ); |
167 | fflush( stdout ); | 167 | fflush( stdout ); |
168 | } | 168 | } |
169 | #undef looper | 169 | #undef looper |
170 | 170 | ||
171 | template<> void __tracer_format<float>( const float &v ); | 171 | template<> void __tracer_format<float>( const float &v ); |
172 | template<> void __tracer_format<double>( const double &v ); | 172 | template<> void __tracer_format<double>( const double &v ); |
173 | template<> void __tracer_format<void *>( void * const &v ); | 173 | template<> void __tracer_format<void *>( void * const &v ); |
174 | template<> void __tracer_format<char *>( char * const &v ); | 174 | template<> void __tracer_format<char *>( char * const &v ); |
175 | template<> void __tracer_format<char **>( char ** const &v ); | 175 | template<> void __tracer_format<char **>( char ** const &v ); |
176 | template<> void __tracer_format<void const *>( void const * const &v ); | 176 | template<> void __tracer_format<void const *>( void const * const &v ); |
177 | template<> void __tracer_format<char const *>( char const * const &v ); | 177 | template<> void __tracer_format<char const *>( char const * const &v ); |
178 | template<> void __tracer_format<char const **>( char const ** const &v ); | 178 | template<> void __tracer_format<char const **>( char const ** const &v ); |
179 | } | 179 | } |
180 | 180 | ||
181 | #ifdef BU_TRACE | 181 | #ifdef BU_TRACE |
diff --git a/src/stable/unitsuite.cpp b/src/stable/unitsuite.cpp index b6057d0..e0606e6 100644 --- a/src/stable/unitsuite.cpp +++ b/src/stable/unitsuite.cpp | |||
@@ -17,14 +17,14 @@ using namespace Bu; | |||
17 | #include <unistd.h> | 17 | #include <unistd.h> |
18 | 18 | ||
19 | Bu::UnitSuite::UnitSuite() : | 19 | Bu::UnitSuite::UnitSuite() : |
20 | iOptions( 0 ), | 20 | iOptions( 0 ), |
21 | iNameWidth( 0 ) | 21 | iNameWidth( 0 ) |
22 | { | 22 | { |
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::UnitSuite::UnitSuite( int iOptions ) : | 25 | Bu::UnitSuite::UnitSuite( int iOptions ) : |
26 | iOptions( iOptions ), | 26 | iOptions( iOptions ), |
27 | iNameWidth( 0 ) | 27 | iNameWidth( 0 ) |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
@@ -34,240 +34,240 @@ Bu::UnitSuite::~UnitSuite() | |||
34 | 34 | ||
35 | int Bu::UnitSuite::run( int argc, char *argv[] ) | 35 | int Bu::UnitSuite::run( int argc, char *argv[] ) |
36 | { | 36 | { |
37 | bool bCleanup = true; | 37 | bool bCleanup = true; |
38 | OptParser p; | 38 | OptParser p; |
39 | p.addOption( Bu::slot( this, &Bu::UnitSuite::onListCases ), 'l', "list", | 39 | p.addOption( Bu::slot( this, &Bu::UnitSuite::onListCases ), 'l', "list", |
40 | "List available test cases." ); | 40 | "List available test cases." ); |
41 | p.addOption( bCleanup, "no-cleanup", "Don't erase temp files."); | 41 | p.addOption( bCleanup, "no-cleanup", "Don't erase temp files."); |
42 | p.setOverride( "no-cleanup", false ); | 42 | p.setOverride( "no-cleanup", false ); |
43 | p.setNonOption( Bu::slot( this, &Bu::UnitSuite::onAddTest ) ); | 43 | p.setNonOption( Bu::slot( this, &Bu::UnitSuite::onAddTest ) ); |
44 | p.addHelpOption(); | 44 | p.addHelpOption(); |
45 | p.parse( argc, argv ); | 45 | p.parse( argc, argv ); |
46 | 46 | ||
47 | if( !hSelTests.isEmpty() ) | 47 | if( !hSelTests.isEmpty() ) |
48 | { | 48 | { |
49 | TestList lSub; | 49 | TestList lSub; |
50 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) | 50 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) |
51 | { | 51 | { |
52 | if( hSelTests.has( (*i).sName ) ) | 52 | if( hSelTests.has( (*i).sName ) ) |
53 | lSub.append( *i ); | 53 | lSub.append( *i ); |
54 | } | 54 | } |
55 | 55 | ||
56 | lTests = lSub; | 56 | lTests = lSub; |
57 | } | 57 | } |
58 | 58 | ||
59 | int iEPass = 0; | 59 | int iEPass = 0; |
60 | int iEFail = 0; | 60 | int iEFail = 0; |
61 | int iUPass = 0; | 61 | int iUPass = 0; |
62 | int iUFail = 0; | 62 | int iUFail = 0; |
63 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) | 63 | for( TestList::iterator i = lTests.begin(); i != lTests.end(); i++ ) |
64 | { | 64 | { |
65 | sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName | 65 | sio << Fmt( iNameWidth+3, Fmt::Left ).fill('.') << i->sName |
66 | << sio.flush; | 66 | << sio.flush; |
67 | try | 67 | try |
68 | { | 68 | { |
69 | iStepCount = -1; | 69 | iStepCount = -1; |
70 | iProgress = 0; | 70 | iProgress = 0; |
71 | (this->*(i->fTest))(); | 71 | (this->*(i->fTest))(); |
72 | switch( i->eExpect ) | 72 | switch( i->eExpect ) |
73 | { | 73 | { |
74 | case expectPass: | 74 | case expectPass: |
75 | sio << "pass." << sio.nl; | 75 | sio << "pass." << sio.nl; |
76 | iEPass++; | 76 | iEPass++; |
77 | break; | 77 | break; |
78 | 78 | ||
79 | case expectFail: | 79 | case expectFail: |
80 | sio << "unexpected pass." << sio.nl; | 80 | sio << "unexpected pass." << sio.nl; |
81 | iUPass++; | 81 | iUPass++; |
82 | break; | 82 | break; |
83 | } | 83 | } |
84 | } | 84 | } |
85 | catch( Failed &e ) | 85 | catch( Failed &e ) |
86 | { | 86 | { |
87 | switch( i->eExpect ) | 87 | switch( i->eExpect ) |
88 | { | 88 | { |
89 | case expectPass: | 89 | case expectPass: |
90 | sio << "unexpected "; | 90 | sio << "unexpected "; |
91 | iUFail++; | 91 | iUFail++; |
92 | break; | 92 | break; |
93 | 93 | ||
94 | case expectFail: | 94 | case expectFail: |
95 | sio << "expected "; | 95 | sio << "expected "; |
96 | iEFail++; | 96 | iEFail++; |
97 | break; | 97 | break; |
98 | } | 98 | } |
99 | if( e.bFile ) | 99 | if( e.bFile ) |
100 | { | 100 | { |
101 | sio << "fail in unitTest(" << e.str << "). (" << e.sFile | 101 | sio << "fail in unitTest(" << e.str << "). (" << e.sFile |
102 | << ":" << e.nLine << ")." << sio.nl; | 102 | << ":" << e.nLine << ")." << sio.nl; |
103 | } | 103 | } |
104 | else | 104 | else |
105 | { | 105 | { |
106 | sio << "fail in unitTest(" << e.str << ")." << sio.nl; | 106 | sio << "fail in unitTest(" << e.str << ")." << sio.nl; |
107 | } | 107 | } |
108 | 108 | ||
109 | if( (iOptions & optStopOnError) ) | 109 | if( (iOptions & optStopOnError) ) |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | catch( std::exception &e ) | 112 | catch( std::exception &e ) |
113 | { | 113 | { |
114 | switch( i->eExpect ) | 114 | switch( i->eExpect ) |
115 | { | 115 | { |
116 | case expectPass: | 116 | case expectPass: |
117 | sio << "unexpected "; | 117 | sio << "unexpected "; |
118 | iUFail++; | 118 | iUFail++; |
119 | break; | 119 | break; |
120 | 120 | ||
121 | case expectFail: | 121 | case expectFail: |
122 | sio << "expected "; | 122 | sio << "expected "; |
123 | iEFail++; | 123 | iEFail++; |
124 | break; | 124 | break; |
125 | } | 125 | } |
126 | sio << "fail with unknown exception. what: " << e.what() << sio.nl; | 126 | sio << "fail with unknown exception. what: " << e.what() << sio.nl; |
127 | 127 | ||
128 | if( (iOptions & optStopOnError) ) | 128 | if( (iOptions & optStopOnError) ) |
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
131 | catch( ... ) | 131 | catch( ... ) |
132 | { | 132 | { |
133 | switch( i->eExpect ) | 133 | switch( i->eExpect ) |
134 | { | 134 | { |
135 | case expectPass: | 135 | case expectPass: |
136 | sio << "unexpected "; | 136 | sio << "unexpected "; |
137 | iUFail++; | 137 | iUFail++; |
138 | break; | 138 | break; |
139 | 139 | ||
140 | case expectFail: | 140 | case expectFail: |
141 | sio << "expected "; | 141 | sio << "expected "; |
142 | iEFail++; | 142 | iEFail++; |
143 | break; | 143 | break; |
144 | } | 144 | } |
145 | sio << "fail with external exception." << sio.nl; | 145 | sio << "fail with external exception." << sio.nl; |
146 | 146 | ||
147 | if( (iOptions & optStopOnError) ) | 147 | if( (iOptions & optStopOnError) ) |
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | } | 150 | } |
151 | 151 | ||
152 | sio << sio.nl | 152 | sio << sio.nl |
153 | << "Report:" << sio.nl | 153 | << "Report:" << sio.nl |
154 | << "\tTotal tests run: " << lTests.getSize() << sio.nl | 154 | << "\tTotal tests run: " << lTests.getSize() << sio.nl |
155 | << "\tExpected passes: " << iEPass << sio.nl | 155 | << "\tExpected passes: " << iEPass << sio.nl |
156 | << "\tExpected failures: " << iEFail << sio.nl | 156 | << "\tExpected failures: " << iEFail << sio.nl |
157 | << "\tUnexpected passes: " << iUPass << sio.nl | 157 | << "\tUnexpected passes: " << iUPass << sio.nl |
158 | << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; | 158 | << "\tUnexpected failures: " << iUFail << sio.nl << sio.nl; |
159 | if( iUPass == 0 && iUFail == 0 ) | 159 | if( iUPass == 0 && iUFail == 0 ) |
160 | sio << "\tNothing unexpected." << sio.nl << sio.nl; | 160 | sio << "\tNothing unexpected." << sio.nl << sio.nl; |
161 | 161 | ||
162 | if( bCleanup ) | 162 | if( bCleanup ) |
163 | { | 163 | { |
164 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) | 164 | for( StrList::iterator i = lFileCleanup.begin(); i; i++ ) |
165 | { | 165 | { |
166 | unlink( (*i).getStr() ); | 166 | unlink( (*i).getStr() ); |
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | Bu::File Bu::UnitSuite::tempFile( Bu::String &sFileName ) | 173 | Bu::File Bu::UnitSuite::tempFile( Bu::String &sFileName ) |
174 | { | 174 | { |
175 | Bu::File f = Bu::File::tempFile( sFileName ); | 175 | Bu::File f = Bu::File::tempFile( sFileName ); |
176 | lFileCleanup.append( sFileName ); | 176 | lFileCleanup.append( sFileName ); |
177 | return f; | 177 | return f; |
178 | } | 178 | } |
179 | 179 | ||
180 | void Bu::UnitSuite::add( Test fTest, const Bu::String &sName, Expect e ) | 180 | void Bu::UnitSuite::add( Test fTest, const Bu::String &sName, Expect e ) |
181 | { | 181 | { |
182 | TestInfo ti; | 182 | TestInfo ti; |
183 | ti.sName = sName; | 183 | ti.sName = sName; |
184 | ti.eExpect = e; | 184 | ti.eExpect = e; |
185 | long index = ti.sName.rfindIdx("::"); | 185 | long index = ti.sName.rfindIdx("::"); |
186 | if( index != -1 ) | 186 | if( index != -1 ) |
187 | { | 187 | { |
188 | String tmp = sSuiteName; | 188 | String tmp = sSuiteName; |
189 | tmp += ti.sName.getStr()+index; | 189 | tmp += ti.sName.getStr()+index; |
190 | ti.sName = tmp; | 190 | ti.sName = tmp; |
191 | } | 191 | } |
192 | ti.fTest = fTest; | 192 | ti.fTest = fTest; |
193 | lTests.append( ti ); | 193 | lTests.append( ti ); |
194 | if( iNameWidth < ti.sName.getSize() ) | 194 | if( iNameWidth < ti.sName.getSize() ) |
195 | iNameWidth = ti.sName.getSize(); | 195 | iNameWidth = ti.sName.getSize(); |
196 | } | 196 | } |
197 | 197 | ||
198 | void Bu::UnitSuite::setName( const String &sName ) | 198 | void Bu::UnitSuite::setName( const String &sName ) |
199 | { | 199 | { |
200 | sSuiteName = sName; | 200 | sSuiteName = sName; |
201 | } | 201 | } |
202 | 202 | ||
203 | void Bu::UnitSuite::dispProgress() | 203 | void Bu::UnitSuite::dispProgress() |
204 | { | 204 | { |
205 | if( tLastUpdate == time( NULL ) ) | 205 | if( tLastUpdate == time( NULL ) ) |
206 | return; | 206 | return; |
207 | sio << Fmt(3) << (iProgress*100/iStepCount) << "%" << "\b\b\b\b" | 207 | sio << Fmt(3) << (iProgress*100/iStepCount) << "%" << "\b\b\b\b" |
208 | << sio.flush; | 208 | << sio.flush; |
209 | tLastUpdate = time( NULL ); | 209 | tLastUpdate = time( NULL ); |
210 | } | 210 | } |
211 | 211 | ||
212 | void Bu::UnitSuite::setStepCount( int iSteps ) | 212 | void Bu::UnitSuite::setStepCount( int iSteps ) |
213 | { | 213 | { |
214 | iStepCount = iSteps; | 214 | iStepCount = iSteps; |
215 | if( iStepCount < 0 ) | 215 | if( iStepCount < 0 ) |
216 | return; | 216 | return; |
217 | tLastUpdate = 0; | 217 | tLastUpdate = 0; |
218 | dispProgress(); | 218 | dispProgress(); |
219 | } | 219 | } |
220 | 220 | ||
221 | void Bu::UnitSuite::incProgress( int iAmnt ) | 221 | void Bu::UnitSuite::incProgress( int iAmnt ) |
222 | { | 222 | { |
223 | iProgress += iAmnt; | 223 | iProgress += iAmnt; |
224 | if( iProgress < 0 ) | 224 | if( iProgress < 0 ) |
225 | iProgress = 0; | 225 | iProgress = 0; |
226 | if( iProgress > iStepCount ) | 226 | if( iProgress > iStepCount ) |
227 | iProgress = iStepCount; | 227 | iProgress = iStepCount; |
228 | dispProgress(); | 228 | dispProgress(); |
229 | } | 229 | } |
230 | 230 | ||
231 | void Bu::UnitSuite::setProgress( int iAmnt ) | 231 | void Bu::UnitSuite::setProgress( int iAmnt ) |
232 | { | 232 | { |
233 | iProgress = iAmnt; | 233 | iProgress = iAmnt; |
234 | if( iProgress < 0 ) | 234 | if( iProgress < 0 ) |
235 | iProgress = 0; | 235 | iProgress = 0; |
236 | if( iProgress > iStepCount ) | 236 | if( iProgress > iStepCount ) |
237 | iProgress = iStepCount; | 237 | iProgress = iStepCount; |
238 | dispProgress(); | 238 | dispProgress(); |
239 | } | 239 | } |
240 | 240 | ||
241 | int Bu::UnitSuite::onListCases( StrArray ) | 241 | int Bu::UnitSuite::onListCases( StrArray ) |
242 | { | 242 | { |
243 | sio << "Test cases:" << sio.nl; | 243 | sio << "Test cases:" << sio.nl; |
244 | for( TestList::iterator i = lTests.begin(); i; i++ ) | 244 | for( TestList::iterator i = lTests.begin(); i; i++ ) |
245 | { | 245 | { |
246 | sio << "\t- " << Fmt( iNameWidth, 10, Fmt::Left ) << (*i).sName << " " | 246 | sio << "\t- " << Fmt( iNameWidth, 10, Fmt::Left ) << (*i).sName << " " |
247 | << (*i).eExpect << sio.nl; | 247 | << (*i).eExpect << sio.nl; |
248 | } | 248 | } |
249 | sio << sio.nl; | 249 | sio << sio.nl; |
250 | exit( 0 ); | 250 | exit( 0 ); |
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
254 | int Bu::UnitSuite::onAddTest( StrArray aParam ) | 254 | int Bu::UnitSuite::onAddTest( StrArray aParam ) |
255 | { | 255 | { |
256 | hSelTests.insert( aParam[0], true ); | 256 | hSelTests.insert( aParam[0], true ); |
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
260 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ) | 260 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ) |
261 | { | 261 | { |
262 | switch( e ) | 262 | switch( e ) |
263 | { | 263 | { |
264 | case Bu::UnitSuite::expectPass: | 264 | case Bu::UnitSuite::expectPass: |
265 | return f << "expect pass"; | 265 | return f << "expect pass"; |
266 | 266 | ||
267 | case Bu::UnitSuite::expectFail: | 267 | case Bu::UnitSuite::expectFail: |
268 | return f << "expect fail"; | 268 | return f << "expect fail"; |
269 | } | 269 | } |
270 | 270 | ||
271 | return f << "**error**"; | 271 | return f << "**error**"; |
272 | } | 272 | } |
273 | 273 | ||
diff --git a/src/stable/unitsuite.h b/src/stable/unitsuite.h index 3442753..46a0773 100644 --- a/src/stable/unitsuite.h +++ b/src/stable/unitsuite.h | |||
@@ -17,126 +17,126 @@ | |||
17 | 17 | ||
18 | namespace Bu | 18 | namespace Bu |
19 | { | 19 | { |
20 | /** | 20 | /** |
21 | * Provides a unit testing framework. This is pretty easy to use, probably | 21 | * Provides a unit testing framework. This is pretty easy to use, probably |
22 | * the best way to get started is to use ch to generate a template, or use | 22 | * the best way to get started is to use ch to generate a template, or use |
23 | * the code below with appropriate tweaks: | 23 | * the code below with appropriate tweaks: |
24 | *@code | 24 | *@code |
25 | * #include "unitsuite.h" | 25 | * #include "unitsuite.h" |
26 | * | 26 | * |
27 | * class Unit : public Bu::UnitSuite | 27 | * class Unit : public Bu::UnitSuite |
28 | * { | 28 | * { |
29 | * public: | 29 | * public: |
30 | * Unit() | 30 | * Unit() |
31 | * { | 31 | * { |
32 | * setName("Example"); | 32 | * setName("Example"); |
33 | * addTest( Unit::test ); | 33 | * addTest( Unit::test ); |
34 | * } | 34 | * } |
35 | * | 35 | * |
36 | * virtual ~Unit() { } | 36 | * virtual ~Unit() { } |
37 | * | 37 | * |
38 | * // | 38 | * // |
39 | * // Tests go here | 39 | * // Tests go here |
40 | * // | 40 | * // |
41 | * void test() | 41 | * void test() |
42 | * { | 42 | * { |
43 | * unitTest( 1 == 1 ); | 43 | * unitTest( 1 == 1 ); |
44 | * } | 44 | * } |
45 | * }; | 45 | * }; |
46 | * | 46 | * |
47 | * int main( int argc, char *argv[] ) | 47 | * int main( int argc, char *argv[] ) |
48 | * { | 48 | * { |
49 | * return Unit().run( argc, argv ); | 49 | * return Unit().run( argc, argv ); |
50 | * } | 50 | * } |
51 | * | 51 | * |
52 | @endcode | 52 | @endcode |
53 | * The main function can contain other things, but using this one exactly | 53 | * The main function can contain other things, but using this one exactly |
54 | * makes all of the test suites work exactly the same. Using the optional | 54 | * makes all of the test suites work exactly the same. Using the optional |
55 | * setName at the top of the constructor replaces the class name with the | 55 | * setName at the top of the constructor replaces the class name with the |
56 | * chosen name when printing out stats and info. | 56 | * chosen name when printing out stats and info. |
57 | */ | 57 | */ |
58 | class UnitSuite | 58 | class UnitSuite |
59 | { | 59 | { |
60 | public: | 60 | public: |
61 | UnitSuite(); | 61 | UnitSuite(); |
62 | UnitSuite( int iOptions ); | 62 | UnitSuite( int iOptions ); |
63 | virtual ~UnitSuite(); | 63 | virtual ~UnitSuite(); |
64 | 64 | ||
65 | int run( int argc=0, char *argv[]=NULL ); | 65 | int run( int argc=0, char *argv[]=NULL ); |
66 | 66 | ||
67 | Bu::File tempFile( Bu::String &sFileName ); | 67 | Bu::File tempFile( Bu::String &sFileName ); |
68 | 68 | ||
69 | typedef void (UnitSuite::*Test)(); | 69 | typedef void (UnitSuite::*Test)(); |
70 | 70 | ||
71 | class Failed | 71 | class Failed |
72 | { | 72 | { |
73 | public: | 73 | public: |
74 | Failed() : str(""), bFile( false ) { } | 74 | Failed() : str(""), bFile( false ) { } |
75 | Failed( const String &s ) : str( s ), bFile( false ) { } | 75 | Failed( const String &s ) : str( s ), bFile( false ) { } |
76 | Failed( const String &s, const String &sFile, int nLine ) : | 76 | Failed( const String &s, const String &sFile, int nLine ) : |
77 | str( s ), sFile( sFile ), nLine( nLine ), bFile( true ) { } | 77 | str( s ), sFile( sFile ), nLine( nLine ), bFile( true ) { } |
78 | 78 | ||
79 | String str; | 79 | String str; |
80 | String sFile; | 80 | String sFile; |
81 | int nLine; | 81 | int nLine; |
82 | bool bFile; | 82 | bool bFile; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | enum | 85 | enum |
86 | { | 86 | { |
87 | optStopOnError = 0x000001 | 87 | optStopOnError = 0x000001 |
88 | }; | 88 | }; |
89 | 89 | ||
90 | enum Expect | 90 | enum Expect |
91 | { | 91 | { |
92 | expectPass, | 92 | expectPass, |
93 | expectFail | 93 | expectFail |
94 | }; | 94 | }; |
95 | 95 | ||
96 | protected: | 96 | protected: |
97 | void add( Test fTest, const Bu::String &sName, Expect e=expectPass ); | 97 | void add( Test fTest, const Bu::String &sName, Expect e=expectPass ); |
98 | void setName( const String &sName ); | 98 | void setName( const String &sName ); |
99 | 99 | ||
100 | void dispProgress(); | 100 | void dispProgress(); |
101 | void setStepCount( int iSteps ); | 101 | void setStepCount( int iSteps ); |
102 | void incProgress( int iAmnt = 1 ); | 102 | void incProgress( int iAmnt = 1 ); |
103 | void setProgress( int iAmnt ); | 103 | void setProgress( int iAmnt ); |
104 | 104 | ||
105 | private: | 105 | private: |
106 | int onListCases( Bu::Array<Bu::String> aParam ); | 106 | int onListCases( Bu::Array<Bu::String> aParam ); |
107 | int onAddTest( Bu::Array<Bu::String> aParam ); | 107 | int onAddTest( Bu::Array<Bu::String> aParam ); |
108 | 108 | ||
109 | private: | 109 | private: |
110 | typedef struct TestInfo | 110 | typedef struct TestInfo |
111 | { | 111 | { |
112 | String sName; | 112 | String sName; |
113 | Test fTest; | 113 | Test fTest; |
114 | Expect eExpect; | 114 | Expect eExpect; |
115 | } TestInfo; | 115 | } TestInfo; |
116 | 116 | ||
117 | typedef Bu::List<TestInfo> TestList; | 117 | typedef Bu::List<TestInfo> TestList; |
118 | TestList lTests; | 118 | TestList lTests; |
119 | String sSuiteName; | 119 | String sSuiteName; |
120 | 120 | ||
121 | int iOptions; | 121 | int iOptions; |
122 | 122 | ||
123 | typedef Bu::List<Bu::String> StrList; | 123 | typedef Bu::List<Bu::String> StrList; |
124 | StrList lFileCleanup; | 124 | StrList lFileCleanup; |
125 | int iNameWidth; | 125 | int iNameWidth; |
126 | int iStepCount; | 126 | int iStepCount; |
127 | int iProgress; | 127 | int iProgress; |
128 | time_t tLastUpdate; | 128 | time_t tLastUpdate; |
129 | 129 | ||
130 | Bu::Hash<Bu::String, bool> hSelTests; | 130 | Bu::Hash<Bu::String, bool> hSelTests; |
131 | }; | 131 | }; |
132 | 132 | ||
133 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); | 133 | Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e ); |
134 | } | 134 | } |
135 | 135 | ||
136 | #define addTest( fn ) add( static_cast<Bu::UnitSuite::Test>(&fn), #fn ) | 136 | #define addTest( fn ) add( static_cast<Bu::UnitSuite::Test>(&fn), #fn ) |
137 | #define unitTest( tst ) if( !(tst) ) \ | 137 | #define unitTest( tst ) if( !(tst) ) \ |
138 | { \ | 138 | { \ |
139 | throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ | 139 | throw Bu::UnitSuite::Failed( #tst, __FILE__, __LINE__ ); \ |
140 | } else (void)0 | 140 | } else (void)0 |
141 | #define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) | 141 | #define unitFailed( msg ) throw Bu::UnitSuite::Failed(msg, __FILE__, __LINE__) |
142 | 142 | ||
diff --git a/src/stable/util.cpp b/src/stable/util.cpp index b42e040..ff9901b 100644 --- a/src/stable/util.cpp +++ b/src/stable/util.cpp | |||
@@ -9,57 +9,57 @@ | |||
9 | 9 | ||
10 | int Bu::getDaysInMonth( int iMonth, int iYear ) | 10 | int Bu::getDaysInMonth( int iMonth, int iYear ) |
11 | { | 11 | { |
12 | if( iMonth > 11 ) | 12 | if( iMonth > 11 ) |
13 | { | 13 | { |
14 | iYear += iMonth/12; | 14 | iYear += iMonth/12; |
15 | iMonth = iMonth%12; | 15 | iMonth = iMonth%12; |
16 | } | 16 | } |
17 | switch( iMonth ) | 17 | switch( iMonth ) |
18 | { | 18 | { |
19 | case 0: | 19 | case 0: |
20 | case 2: | 20 | case 2: |
21 | case 4: | 21 | case 4: |
22 | case 6: | 22 | case 6: |
23 | case 7: | 23 | case 7: |
24 | case 9: | 24 | case 9: |
25 | case 11: | 25 | case 11: |
26 | return 31; | 26 | return 31; |
27 | break; | 27 | break; |
28 | 28 | ||
29 | case 3: | 29 | case 3: |
30 | case 5: | 30 | case 5: |
31 | case 8: | 31 | case 8: |
32 | case 10: | 32 | case 10: |
33 | return 30; | 33 | return 30; |
34 | break; | 34 | break; |
35 | 35 | ||
36 | case 1: | 36 | case 1: |
37 | if( iYear%400 == 0 ) | 37 | if( iYear%400 == 0 ) |
38 | return 29; | 38 | return 29; |
39 | if( iYear%100 == 0 ) | 39 | if( iYear%100 == 0 ) |
40 | return 28; | 40 | return 28; |
41 | if( iYear%4 == 0 ) | 41 | if( iYear%4 == 0 ) |
42 | return 29; | 42 | return 29; |
43 | return 28; | 43 | return 28; |
44 | break; | 44 | break; |
45 | 45 | ||
46 | default: | 46 | default: |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
49 | } | 49 | } |
50 | void Bu::memcpy( void *pDest, const void *pSrc, size_t iBytes ) | 50 | void Bu::memcpy( void *pDest, const void *pSrc, size_t iBytes ) |
51 | { | 51 | { |
52 | #ifdef VALTEST | 52 | #ifdef VALTEST |
53 | const char *src = (const char *)pSrc; | 53 | const char *src = (const char *)pSrc; |
54 | char *dest = (char *)pDest; | 54 | char *dest = (char *)pDest; |
55 | for( int j = 0; j < count; j++ ) | 55 | for( int j = 0; j < count; j++ ) |
56 | { | 56 | { |
57 | *dest = *src; | 57 | *dest = *src; |
58 | dest++; | 58 | dest++; |
59 | src++; | 59 | src++; |
60 | } | 60 | } |
61 | #else | 61 | #else |
62 | ::memcpy( pDest, pSrc, iBytes ); | 62 | ::memcpy( pDest, pSrc, iBytes ); |
63 | #endif | 63 | #endif |
64 | } | 64 | } |
65 | 65 | ||
diff --git a/src/stable/util.h b/src/stable/util.h index 4514281..ab9cd08 100644 --- a/src/stable/util.h +++ b/src/stable/util.h | |||
@@ -25,158 +25,158 @@ | |||
25 | 25 | ||
26 | namespace Bu | 26 | namespace Bu |
27 | { | 27 | { |
28 | /** | 28 | /** |
29 | * Swap the value of two variables, uses references, so it's pretty safe. | 29 | * Swap the value of two variables, uses references, so it's pretty safe. |
30 | * Objects passed in must support a basic assignemnt operator (=); | 30 | * Objects passed in must support a basic assignemnt operator (=); |
31 | *@param a Variable to recieve the value of parameter b | 31 | *@param a Variable to recieve the value of parameter b |
32 | *@param b Variable to recieve the value of parameter a | 32 | *@param b Variable to recieve the value of parameter a |
33 | */ | 33 | */ |
34 | template<typename item> | 34 | template<typename item> |
35 | void swap( item &a, item &b ) | 35 | void swap( item &a, item &b ) |
36 | { | 36 | { |
37 | item tmp = a; | 37 | item tmp = a; |
38 | a = b; | 38 | a = b; |
39 | b = tmp; | 39 | b = tmp; |
40 | } | 40 | } |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * Finds the lesser of the two objects, objects passed in must be | 43 | * Finds the lesser of the two objects, objects passed in must be |
44 | * less-than-comparable. | 44 | * less-than-comparable. |
45 | *@param a A value to test. | 45 | *@param a A value to test. |
46 | *@param b Another value to test. | 46 | *@param b Another value to test. |
47 | *@returns A reference to the lesser of a or b. | 47 | *@returns A reference to the lesser of a or b. |
48 | */ | 48 | */ |
49 | template<typename item> | 49 | template<typename item> |
50 | const item &buMin( const item &a, const item &b ) | 50 | const item &buMin( const item &a, const item &b ) |
51 | { | 51 | { |
52 | return a<b?a:b; | 52 | return a<b?a:b; |
53 | } | 53 | } |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Finds the lesser of the two objects, objects passed in must be | 56 | * Finds the lesser of the two objects, objects passed in must be |
57 | * less-than-comparable. | 57 | * less-than-comparable. |
58 | *@param a A value to test. | 58 | *@param a A value to test. |
59 | *@param b Another value to test. | 59 | *@param b Another value to test. |
60 | *@returns A reference to the lesser of a or b. | 60 | *@returns A reference to the lesser of a or b. |
61 | */ | 61 | */ |
62 | template<typename item> | 62 | template<typename item> |
63 | item &buMin( item &a, item &b ) | 63 | item &buMin( item &a, item &b ) |
64 | { | 64 | { |
65 | return a<b?a:b; | 65 | return a<b?a:b; |
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * Finds the greater of the two objects, objects passed in must be | 69 | * Finds the greater of the two objects, objects passed in must be |
70 | * less-than-comparable. | 70 | * less-than-comparable. |
71 | *@param a A value to test. | 71 | *@param a A value to test. |
72 | *@param b Another value to test. | 72 | *@param b Another value to test. |
73 | *@returns A reference to the greater of a or b. | 73 | *@returns A reference to the greater of a or b. |
74 | */ | 74 | */ |
75 | template<typename item> | 75 | template<typename item> |
76 | const item &buMax( const item &a, const item &b ) | 76 | const item &buMax( const item &a, const item &b ) |
77 | { | 77 | { |
78 | return b<a?a:b; | 78 | return b<a?a:b; |
79 | } | 79 | } |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * Finds the greater of the two objects, objects passed in must be | 82 | * Finds the greater of the two objects, objects passed in must be |
83 | * less-than-comparable. | 83 | * less-than-comparable. |
84 | *@param a A value to test. | 84 | *@param a A value to test. |
85 | *@param b Another value to test. | 85 | *@param b Another value to test. |
86 | *@returns A reference to the greater of a or b. | 86 | *@returns A reference to the greater of a or b. |
87 | */ | 87 | */ |
88 | template<typename item> | 88 | template<typename item> |
89 | item &buMax( item &a, item &b ) | 89 | item &buMax( item &a, item &b ) |
90 | { | 90 | { |
91 | return b<a?a:b; | 91 | return b<a?a:b; |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * Given three objects this finds the one between the other two. | 95 | * Given three objects this finds the one between the other two. |
96 | *@param a A value to test. | 96 | *@param a A value to test. |
97 | *@param b Another value to test. | 97 | *@param b Another value to test. |
98 | *@param c Yet another value to test. | 98 | *@param c Yet another value to test. |
99 | *@returns A reference to the mid-value of a, b, and c. | 99 | *@returns A reference to the mid-value of a, b, and c. |
100 | */ | 100 | */ |
101 | template<typename item> | 101 | template<typename item> |
102 | const item &buMid( const item &a, const item &b, const item &c ) | 102 | const item &buMid( const item &a, const item &b, const item &c ) |
103 | { | 103 | { |
104 | return buMin( buMax( a, b ), c ); | 104 | return buMin( buMax( a, b ), c ); |
105 | } | 105 | } |
106 | 106 | ||
107 | /** | 107 | /** |
108 | * Given three objects this finds the one between the other two. | 108 | * Given three objects this finds the one between the other two. |
109 | *@param a A value to test. | 109 | *@param a A value to test. |
110 | *@param b Another value to test. | 110 | *@param b Another value to test. |
111 | *@param c Yet another value to test. | 111 | *@param c Yet another value to test. |
112 | *@returns A reference to the mid-value of a, b, and c. | 112 | *@returns A reference to the mid-value of a, b, and c. |
113 | */ | 113 | */ |
114 | template<typename item> | 114 | template<typename item> |
115 | item &buMid( item &a, item &b, item &c ) | 115 | item &buMid( item &a, item &b, item &c ) |
116 | { | 116 | { |
117 | return buMin( buMax( a, b ), c ); | 117 | return buMin( buMax( a, b ), c ); |
118 | } | 118 | } |
119 | 119 | ||
120 | // | 120 | // |
121 | // Basic comparison functors | 121 | // Basic comparison functors |
122 | // | 122 | // |
123 | /** | 123 | /** |
124 | * Simple less-than comparison functor. Objects being used should be | 124 | * Simple less-than comparison functor. Objects being used should be |
125 | * less-than-comparable. | 125 | * less-than-comparable. |
126 | */ | 126 | */ |
127 | template<typename item> | 127 | template<typename item> |
128 | struct __basicLTCmp | 128 | struct __basicLTCmp |
129 | { | 129 | { |
130 | bool operator()( const item &a, const item &b ) | 130 | bool operator()( const item &a, const item &b ) |
131 | { | 131 | { |
132 | return a < b; | 132 | return a < b; |
133 | } | 133 | } |
134 | }; | 134 | }; |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * Simple greater-than comparison functor. Objects being used should be | 137 | * Simple greater-than comparison functor. Objects being used should be |
138 | * greater-than-comparable. | 138 | * greater-than-comparable. |
139 | */ | 139 | */ |
140 | template<typename item> | 140 | template<typename item> |
141 | struct __basicGTCmp | 141 | struct __basicGTCmp |
142 | { | 142 | { |
143 | bool operator()( const item &a, const item &b ) | 143 | bool operator()( const item &a, const item &b ) |
144 | { | 144 | { |
145 | return a > b; | 145 | return a > b; |
146 | } | 146 | } |
147 | }; | 147 | }; |
148 | 148 | ||
149 | /** | 149 | /** |
150 | * As __basicLTCmp but dereferences the passed in pointers before comparing. | 150 | * As __basicLTCmp but dereferences the passed in pointers before comparing. |
151 | */ | 151 | */ |
152 | template<typename item> | 152 | template<typename item> |
153 | struct __basicPtrLTCmp | 153 | struct __basicPtrLTCmp |
154 | { | 154 | { |
155 | bool operator()( const item &a, const item &b ) | 155 | bool operator()( const item &a, const item &b ) |
156 | { | 156 | { |
157 | return *a < *b; | 157 | return *a < *b; |
158 | } | 158 | } |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * As __basicGTCmp but dereferences the passed in pointers before comparing. | 162 | * As __basicGTCmp but dereferences the passed in pointers before comparing. |
163 | */ | 163 | */ |
164 | template<typename item> | 164 | template<typename item> |
165 | struct __basicPtrGTCmp | 165 | struct __basicPtrGTCmp |
166 | { | 166 | { |
167 | bool operator()( const item &a, const item &b ) | 167 | bool operator()( const item &a, const item &b ) |
168 | { | 168 | { |
169 | return *a > *b; | 169 | return *a > *b; |
170 | } | 170 | } |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /** | 173 | /** |
174 | * Get the number of days in the month in the gregorian calendar, taking | 174 | * Get the number of days in the month in the gregorian calendar, taking |
175 | * leap years into account. | 175 | * leap years into account. |
176 | */ | 176 | */ |
177 | int getDaysInMonth( int iMonth, int iYear ); | 177 | int getDaysInMonth( int iMonth, int iYear ); |
178 | 178 | ||
179 | void memcpy( void *pDest, const void *pSrc, size_t iBytes ); | 179 | void memcpy( void *pDest, const void *pSrc, size_t iBytes ); |
180 | }; | 180 | }; |
181 | 181 | ||
182 | #endif | 182 | #endif |
diff --git a/src/stable/variant.cpp b/src/stable/variant.cpp index 674ae04..d724fa7 100644 --- a/src/stable/variant.cpp +++ b/src/stable/variant.cpp | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | namespace Bu | 12 | namespace Bu |
13 | { | 13 | { |
14 | Formatter &operator<<( Formatter &f, const String &s ); | 14 | Formatter &operator<<( Formatter &f, const String &s ); |
15 | }; | 15 | }; |
16 | 16 | ||
17 | Bu::VariantTypeRoot::VariantTypeRoot() | 17 | Bu::VariantTypeRoot::VariantTypeRoot() |
@@ -23,84 +23,84 @@ Bu::VariantTypeRoot::~VariantTypeRoot() | |||
23 | } | 23 | } |
24 | 24 | ||
25 | Bu::Variant::Variant() : | 25 | Bu::Variant::Variant() : |
26 | pCore( NULL ) | 26 | pCore( NULL ) |
27 | { | 27 | { |
28 | } | 28 | } |
29 | 29 | ||
30 | Bu::Variant::Variant( const Variant &v ) : | 30 | Bu::Variant::Variant( const Variant &v ) : |
31 | pCore( NULL ) | 31 | pCore( NULL ) |
32 | { | 32 | { |
33 | if( v.pCore ) | 33 | if( v.pCore ) |
34 | { | 34 | { |
35 | pCore = v.pCore->clone(); | 35 | pCore = v.pCore->clone(); |
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | Bu::Variant::Variant( const char *t ) : | 39 | Bu::Variant::Variant( const char *t ) : |
40 | pCore( NULL ) | 40 | pCore( NULL ) |
41 | { | 41 | { |
42 | set( Bu::String( t ) ); | 42 | set( Bu::String( t ) ); |
43 | } | 43 | } |
44 | 44 | ||
45 | Bu::Variant::~Variant() | 45 | Bu::Variant::~Variant() |
46 | { | 46 | { |
47 | if( pCore ) | 47 | if( pCore ) |
48 | { | 48 | { |
49 | delete pCore; | 49 | delete pCore; |
50 | pCore = NULL; | 50 | pCore = NULL; |
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | Bu::String Bu::Variant::toString() const | 54 | Bu::String Bu::Variant::toString() const |
55 | { | 55 | { |
56 | if( getType() == typeid( Bu::String ) ) | 56 | if( getType() == typeid( Bu::String ) ) |
57 | { | 57 | { |
58 | return get<Bu::String>(); | 58 | return get<Bu::String>(); |
59 | } | 59 | } |
60 | else | 60 | else |
61 | { | 61 | { |
62 | Bu::MemBuf mb; | 62 | Bu::MemBuf mb; |
63 | Bu::Formatter f( mb ); | 63 | Bu::Formatter f( mb ); |
64 | f << *this; | 64 | f << *this; |
65 | return mb.getString(); | 65 | return mb.getString(); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | bool Bu::Variant::isSet() const | 69 | bool Bu::Variant::isSet() const |
70 | { | 70 | { |
71 | return pCore != NULL; | 71 | return pCore != NULL; |
72 | } | 72 | } |
73 | 73 | ||
74 | const std::type_info &Bu::Variant::getType() const | 74 | const std::type_info &Bu::Variant::getType() const |
75 | { | 75 | { |
76 | if( !pCore ) | 76 | if( !pCore ) |
77 | { | 77 | { |
78 | throw Bu::ExceptionBase("No data!"); | 78 | throw Bu::ExceptionBase("No data!"); |
79 | } | 79 | } |
80 | return pCore->getType(); | 80 | return pCore->getType(); |
81 | } | 81 | } |
82 | 82 | ||
83 | Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs ) | 83 | Bu::Variant &Bu::Variant::operator=( const Bu::Variant &rhs ) |
84 | { | 84 | { |
85 | if( pCore ) | 85 | if( pCore ) |
86 | { | 86 | { |
87 | delete pCore; | 87 | delete pCore; |
88 | pCore = NULL; | 88 | pCore = NULL; |
89 | } | 89 | } |
90 | if( rhs.pCore ) | 90 | if( rhs.pCore ) |
91 | { | 91 | { |
92 | pCore = rhs.pCore->clone(); | 92 | pCore = rhs.pCore->clone(); |
93 | } | 93 | } |
94 | 94 | ||
95 | return *this; | 95 | return *this; |
96 | } | 96 | } |
97 | 97 | ||
98 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v ) | 98 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Variant &v ) |
99 | { | 99 | { |
100 | if( !v.pCore ) | 100 | if( !v.pCore ) |
101 | return f << "(null)"; | 101 | return f << "(null)"; |
102 | 102 | ||
103 | v.pCore->format( f ); | 103 | v.pCore->format( f ); |
104 | return f; | 104 | return f; |
105 | } | 105 | } |
106 | 106 | ||
diff --git a/src/stable/variant.h b/src/stable/variant.h index 6837954..227e246 100644 --- a/src/stable/variant.h +++ b/src/stable/variant.h | |||
@@ -20,217 +20,217 @@ | |||
20 | 20 | ||
21 | namespace Bu | 21 | namespace Bu |
22 | { | 22 | { |
23 | class String; | 23 | class String; |
24 | class Formatter; | 24 | class Formatter; |
25 | class Variant; | 25 | class Variant; |
26 | /** @cond DEVEL */ | 26 | /** @cond DEVEL */ |
27 | template<class t> class VariantType; | 27 | template<class t> class VariantType; |
28 | 28 | ||
29 | class VariantTypeRoot | 29 | class VariantTypeRoot |
30 | { | 30 | { |
31 | public: | 31 | public: |
32 | VariantTypeRoot(); | 32 | VariantTypeRoot(); |
33 | virtual ~VariantTypeRoot(); | 33 | virtual ~VariantTypeRoot(); |
34 | 34 | ||
35 | virtual const std::type_info &getType() const=0; | 35 | virtual const std::type_info &getType() const=0; |
36 | virtual VariantTypeRoot *clone() const=0; | 36 | virtual VariantTypeRoot *clone() const=0; |
37 | virtual void format( Bu::Formatter &f ) const=0; | 37 | virtual void format( Bu::Formatter &f ) const=0; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | template<class t> | 40 | template<class t> |
41 | class VariantType : public VariantTypeRoot | 41 | class VariantType : public VariantTypeRoot |
42 | { | 42 | { |
43 | friend class Variant; | 43 | friend class Variant; |
44 | private: | 44 | private: |
45 | VariantType() | 45 | VariantType() |
46 | { | 46 | { |
47 | } | 47 | } |
48 | 48 | ||
49 | VariantType( const t &d ) : | 49 | VariantType( const t &d ) : |
50 | data( d ) | 50 | data( d ) |
51 | { | 51 | { |
52 | } | 52 | } |
53 | 53 | ||
54 | VariantType( const VariantType<t> &vt ) : | 54 | VariantType( const VariantType<t> &vt ) : |
55 | data( vt.data ) | 55 | data( vt.data ) |
56 | { | 56 | { |
57 | } | 57 | } |
58 | 58 | ||
59 | virtual ~VariantType() | 59 | virtual ~VariantType() |
60 | { | 60 | { |
61 | } | 61 | } |
62 | 62 | ||
63 | public: | 63 | public: |
64 | t &getData() | 64 | t &getData() |
65 | { | 65 | { |
66 | return data; | 66 | return data; |
67 | } | 67 | } |
68 | 68 | ||
69 | const t &getData() const | 69 | const t &getData() const |
70 | { | 70 | { |
71 | return data; | 71 | return data; |
72 | } | 72 | } |
73 | 73 | ||
74 | virtual void format( Formatter &f ) const | 74 | virtual void format( Formatter &f ) const |
75 | { | 75 | { |
76 | f << data; | 76 | f << data; |
77 | } | 77 | } |
78 | 78 | ||
79 | virtual const std::type_info &getType() const | 79 | virtual const std::type_info &getType() const |
80 | { | 80 | { |
81 | return typeid( data ); | 81 | return typeid( data ); |
82 | } | 82 | } |
83 | 83 | ||
84 | VariantType<t> operator=( const t &rhs ) | 84 | VariantType<t> operator=( const t &rhs ) |
85 | { | 85 | { |
86 | data = rhs; | 86 | data = rhs; |
87 | 87 | ||
88 | return *this; | 88 | return *this; |
89 | } | 89 | } |
90 | 90 | ||
91 | virtual VariantTypeRoot *clone() const | 91 | virtual VariantTypeRoot *clone() const |
92 | { | 92 | { |
93 | return new VariantType<t>( *this ); | 93 | return new VariantType<t>( *this ); |
94 | } | 94 | } |
95 | 95 | ||
96 | private: | 96 | private: |
97 | t data; | 97 | t data; |
98 | }; | 98 | }; |
99 | /** @endcond */ | 99 | /** @endcond */ |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * Store any data type and access it safely. Variant gives you a way to | 102 | * Store any data type and access it safely. Variant gives you a way to |
103 | * pass arbitrary data types around without having to worry about what | 103 | * pass arbitrary data types around without having to worry about what |
104 | * type a variable is. It allows code to be easily extended and to manage | 104 | * type a variable is. It allows code to be easily extended and to manage |
105 | * data without having to know what type it is ahead of time. | 105 | * data without having to know what type it is ahead of time. |
106 | * | 106 | * |
107 | * Because of the generic method that this class was implemented it may seem | 107 | * Because of the generic method that this class was implemented it may seem |
108 | * to have some drawbacks compared to other Variant classes you may have | 108 | * to have some drawbacks compared to other Variant classes you may have |
109 | * seen, however it is fairly easy to get it to do just about anything you | 109 | * seen, however it is fairly easy to get it to do just about anything you |
110 | * may need. It is also very low overhead. On most compilers the class | 110 | * may need. It is also very low overhead. On most compilers the class |
111 | * itself has only 3 words of overhead + the size of the variable you store | 111 | * itself has only 3 words of overhead + the size of the variable you store |
112 | * in it. And, since many parts of it are templatized they can often be | 112 | * in it. And, since many parts of it are templatized they can often be |
113 | * optimized quite a bit. | 113 | * optimized quite a bit. |
114 | */ | 114 | */ |
115 | class Variant | 115 | class Variant |
116 | { | 116 | { |
117 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); | 117 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); |
118 | public: | 118 | public: |
119 | Variant(); | 119 | Variant(); |
120 | Variant( const Variant &v ); | 120 | Variant( const Variant &v ); |
121 | Variant( const char *t ); | 121 | Variant( const char *t ); |
122 | template<class t> | 122 | template<class t> |
123 | Variant( const t &v ) : | 123 | Variant( const t &v ) : |
124 | pCore( new VariantType<t>() ) | 124 | pCore( new VariantType<t>() ) |
125 | { | 125 | { |
126 | (*dynamic_cast<VariantType<t> *>(pCore)) = v; | 126 | (*dynamic_cast<VariantType<t> *>(pCore)) = v; |
127 | } | 127 | } |
128 | virtual ~Variant(); | 128 | virtual ~Variant(); |
129 | 129 | ||
130 | Bu::String toString() const; | 130 | Bu::String toString() const; |
131 | bool isSet() const; | 131 | bool isSet() const; |
132 | const std::type_info &getType() const; | 132 | const std::type_info &getType() const; |
133 | 133 | ||
134 | Variant &operator=( const Variant &rhs ); | 134 | Variant &operator=( const Variant &rhs ); |
135 | 135 | ||
136 | template<class t> | 136 | template<class t> |
137 | Variant &operator=( const t &rhs ) | 137 | Variant &operator=( const t &rhs ) |
138 | { | 138 | { |
139 | if( pCore ) // && pCore->getType() != typeid(t) ) | 139 | if( pCore ) // && pCore->getType() != typeid(t) ) |
140 | { | 140 | { |
141 | delete pCore; | 141 | delete pCore; |
142 | pCore = NULL; | 142 | pCore = NULL; |
143 | } | 143 | } |
144 | pCore = new VariantType<t>(); | 144 | pCore = new VariantType<t>(); |
145 | (*dynamic_cast<VariantType<t> *>(pCore)) = rhs; | 145 | (*dynamic_cast<VariantType<t> *>(pCore)) = rhs; |
146 | return *this; | 146 | return *this; |
147 | } | 147 | } |
148 | 148 | ||
149 | template<class t> | 149 | template<class t> |
150 | t &get() | 150 | t &get() |
151 | { | 151 | { |
152 | if( !pCore ) | 152 | if( !pCore ) |
153 | { | 153 | { |
154 | throw Bu::ExceptionBase("No data!"); | 154 | throw Bu::ExceptionBase("No data!"); |
155 | } | 155 | } |
156 | if( pCore->getType() != typeid(t) ) | 156 | if( pCore->getType() != typeid(t) ) |
157 | { | 157 | { |
158 | throw Bu::ExceptionBase("Invalid type conversion."); | 158 | throw Bu::ExceptionBase("Invalid type conversion."); |
159 | } | 159 | } |
160 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 160 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
161 | } | 161 | } |
162 | 162 | ||
163 | template<class t> | 163 | template<class t> |
164 | t &get() const | 164 | t &get() const |
165 | { | 165 | { |
166 | if( !pCore ) | 166 | if( !pCore ) |
167 | { | 167 | { |
168 | throw Bu::ExceptionBase("No data!"); | 168 | throw Bu::ExceptionBase("No data!"); |
169 | } | 169 | } |
170 | if( pCore->getType() != typeid(t) ) | 170 | if( pCore->getType() != typeid(t) ) |
171 | { | 171 | { |
172 | throw Bu::ExceptionBase("Invalid type conversion."); | 172 | throw Bu::ExceptionBase("Invalid type conversion."); |
173 | } | 173 | } |
174 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 174 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
175 | } | 175 | } |
176 | 176 | ||
177 | template<class t> | 177 | template<class t> |
178 | void set( const t &val ) | 178 | void set( const t &val ) |
179 | { | 179 | { |
180 | if( pCore && pCore->getType() != typeid(t) ) | 180 | if( pCore && pCore->getType() != typeid(t) ) |
181 | { | 181 | { |
182 | delete pCore; | 182 | delete pCore; |
183 | pCore = NULL; | 183 | pCore = NULL; |
184 | } | 184 | } |
185 | pCore = new VariantType<t>(); | 185 | pCore = new VariantType<t>(); |
186 | (*dynamic_cast<VariantType<t> *>(pCore)) = val; | 186 | (*dynamic_cast<VariantType<t> *>(pCore)) = val; |
187 | } | 187 | } |
188 | 188 | ||
189 | template<class t> | 189 | template<class t> |
190 | bool isType() const | 190 | bool isType() const |
191 | { | 191 | { |
192 | return pCore->getType() == typeid(t); | 192 | return pCore->getType() == typeid(t); |
193 | } | 193 | } |
194 | 194 | ||
195 | template<class t> | 195 | template<class t> |
196 | operator t() | 196 | operator t() |
197 | { | 197 | { |
198 | if( !pCore ) | 198 | if( !pCore ) |
199 | { | 199 | { |
200 | throw Bu::ExceptionBase("No data!"); | 200 | throw Bu::ExceptionBase("No data!"); |
201 | } | 201 | } |
202 | if( pCore->getType() != typeid(t) ) | 202 | if( pCore->getType() != typeid(t) ) |
203 | { | 203 | { |
204 | throw Bu::ExceptionBase("Invalid type conversion."); | 204 | throw Bu::ExceptionBase("Invalid type conversion."); |
205 | } | 205 | } |
206 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 206 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
207 | } | 207 | } |
208 | 208 | ||
209 | template<class t> | 209 | template<class t> |
210 | operator t() const | 210 | operator t() const |
211 | { | 211 | { |
212 | if( !pCore ) | 212 | if( !pCore ) |
213 | { | 213 | { |
214 | throw Bu::ExceptionBase("No data!"); | 214 | throw Bu::ExceptionBase("No data!"); |
215 | } | 215 | } |
216 | if( pCore->getType() != typeid(t) ) | 216 | if( pCore->getType() != typeid(t) ) |
217 | { | 217 | { |
218 | throw Bu::ExceptionBase("Invalid type conversion."); | 218 | throw Bu::ExceptionBase("Invalid type conversion."); |
219 | } | 219 | } |
220 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); | 220 | return dynamic_cast<VariantType<t> *>(pCore)->getData(); |
221 | } | 221 | } |
222 | 222 | ||
223 | private: | 223 | private: |
224 | VariantTypeRoot *pCore; | 224 | VariantTypeRoot *pCore; |
225 | }; | 225 | }; |
226 | /* | 226 | /* |
227 | template<class t> | 227 | template<class t> |
228 | Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt ) | 228 | Bu::Formatter &operator<<( Bu::Formatter &f, const VariantType<t> &vt ) |
229 | { | 229 | { |
230 | return f << vt.getData; | 230 | return f << vt.getData; |
231 | }*/ | 231 | }*/ |
232 | 232 | ||
233 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); | 233 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variant &v ); |
234 | }; | 234 | }; |
235 | 235 | ||
236 | #endif | 236 | #endif |