00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#ifndef __CB2__UTILS_H__
00019
#define __CB2__UTILS_H__
00020
00021
00022
#include <math.h>
00023
#include <string>
00024
#include <ostream>
00025
00026
00035 #define CB2_ASSERT(cond, warning) \
00036
if (!(cond)) \
00037
throw ExceptionAssert(warning ": " #cond " in " __FILE__, __LINE__);
00038
00039
00040 #define CB2_CONVERSION(cond, warning) \
00041
if (!(cond)) \
00042
throw ExceptionConversion(warning ": " #cond " in " __FILE__, __LINE__);
00043
00044
00045 #define CB2_RANGECHECK(cond, value) \
00046
if (!(cond)) \
00047
throw ExceptionRange< typeof(value)>(#cond ": Value " #value "=", value, " is out of range in " __FILE__, __LINE__);
00048
00049
00050 #define CB2_MEMORYCHECK(cond) \
00051
if (!(cond)) \
00052
throw ExceptionMemory(#cond ": Memory dereference fault in " __FILE__, __LINE__);
00053
00054
00055 #define CB2_NOTFOUND(cond) \
00056
if (!(cond)) \
00057
throw ExceptionNotFound(#cond ": Item not found in " __FILE__, __LINE__);
00058
00059
00066 namespace CB2 {
00067
00068
00074 class Class {
00075
public:
00076 int tag;
00077 };
00078
00079
00080
template<
class Tsize>
class ExceptionRange;
00081
class ExceptionConversion;
00082
class ExceptionMemory;
00083
class ExceptionAssert;
00084
class ExceptionNotFound;
00109 template<
class Tcontainer,
class Tref,
class Tmemb>
class Iterator :
public Class {
00110
public:
00111
00112 typedef Iterator< Tcontainer, Tref, Tmemb> this_type;
00124 Iterator(
const Tcontainer & cont,
const Tref & reference)
00125 :
container(cont) {
00126
ref = reference;
00127 }
00128
00129
00138 const this_type &
operator++() {
00139
ref =
container.RefNext(
ref);
00140
return *
this;
00141 }
00142
00143
00154 bool operator==(
const this_type & it)
const {
00155
return (
ref == it.
ref);
00156 }
00157
00158 bool operator!=(
const this_type & it)
const {
00159
return (!
operator==(it));
00160 }
00161
00162
00171 const Tmemb &
operator*()
const {
00172
return container.Deref(
ref);
00173 }
00174
00175 const Tmemb *
operator->()
const {
00176
return &
container.Deref(
ref);
00177 }
00178
00179
private:
00180
00181 const Tcontainer &
container;
00182 Tref
ref;
00184 };
00185
00186
00209 template<
class Tcontainer,
class Tref,
class Tmemb>
class RevIterator :
public Class {
00210
public:
00211
00212 typedef RevIterator< Tcontainer, Tref, Tmemb> this_type;
00223 RevIterator(
const Tcontainer & cont,
const Tref & reference)
00224 :
container(cont) {
00225
ref = reference;
00226 }
00227
00228
00237 const this_type &
operator--() {
00238
ref =
container.RefPrev(
ref);
00239
return *
this;
00240 }
00241
00242
00253 bool operator==(
const this_type & it)
const {
00254
return (
ref == it.
ref);
00255 }
00256
00257 bool operator!=(
const this_type & it)
const {
00258
return (!
operator==(it));
00259 }
00260
00261
00270 const Tmemb &
operator*()
const {
00271
return container.RevDeref(
ref);
00272 }
00273
00274 const Tmemb *
operator->()
const {
00275
return &
container.RevDeref(
ref);
00276 }
00277
00278
private:
00279
00280 const Tcontainer &
container;
00281 Tref
ref;
00283 };
00284
00285
00305 template<
class Tmemb>
class Array :
public Class {
00306
public:
00307
00308 typedef Array< Tmemb> this_type;
00309 typedef size_t size_type;
00310 typedef Tmemb *
ref_type;
00311 typedef Iterator< this_type, ref_type, Tmemb> iterator;
00312 typedef RevIterator< this_type, ref_type, Tmemb> rev_iterator;
00323 Array(
const size_type fragment = 4096) {
00324
00325 data = NULL;
00326 allocated = 0;
00327 frag = fragment;
00328 allocate(0);
00329 }
00330
00331
00340 Array(
const this_type & prev) {
00341
00342 data = NULL;
00343 allocated = 0;
00344 frag = prev.
frag;
00345 privatize(prev);
00346 }
00347
00348
00354 ~Array() {
00355
if (data)
00356
delete[] data;
00357 }
00358
00359
00368 const this_type & operator=(
const this_type & prev) {
00369
if (&prev !=
this) {
00370 frag = prev.
frag;
00371 privatize(prev);
00372 }
00373
return *
this;
00374 }
00375
00376
00384 operator const Tmemb * ()
const {
00385
return (
const Tmemb * ) data;
00386 }
00387
00388
00399 const this_type &
operator<<(
const Tmemb & prev) {
00400 allocate(len + 1);
00401 memcpy(data + len - 1, &prev,
sizeof(Tmemb));
00402
00403
return *
this;
00404 }
00405
00406
00422 const this_type & operator>>(
const Tmemb & prev) {
00423 allocate(len + 1);
00424
00425
00426
00427 memmove(data + 1, data, len - 1);
00428 memcpy(data, &prev,
sizeof(Tmemb));
00429
00430
return *
this;
00431 }
00432
00433
00445 const this_type & operator+=(
const size_type nmemb) {
00446 allocate(len + nmemb);
00447
return *
this;
00448 }
00449
00450
00463 const this_type & operator-=(
const size_type nmemb) {
00464
if (nmemb > len)
00465 allocate(0);
00466
else
00467 allocate(len - nmemb);
00468
00469
return *
this;
00470 }
00471
00472
00484 Tmemb & operator[](
const size_type pos)
const {
00485
CB2_RANGECHECK(pos < len, pos);
00486
return data[pos];
00487 }
00488
00489
00501 void Fill(
const Tmemb * buffer,
const size_type nmemb) {
00502 allocate(nmemb);
00503 memmove(data, buffer,
sizeof(Tmemb) * nmemb);
00504 }
00505
00506
00515 void Discart(
const bool shrink =
false) {
00516
if (shrink) {
00517
00518
if (data)
00519
delete[] data;
00520 data = NULL;
00521 allocated = 0;
00522 }
00523 allocate(0);
00524 }
00525
00526
00532 size_type
Len()
const {
00533
return len;
00534 }
00535
00536
00542 bool Empty()
const {
00543
return (len == 0);
00544 }
00545
00546
00557 ref_type
RefBegin()
const {
00558
if (
Len() > 0)
00559
return data;
00560
00561
return NULL;
00562 }
00563
00564
00575 ref_type
RefEnd()
const {
00576 size_type len =
Len();
00577
00578
if (len > 0)
00579
return (data + len);
00580
00581
return NULL;
00582 }
00583
00584
00594 ref_type
RevRefBegin()
const {
00595
return RefEnd();
00596 }
00597
00598
00608 ref_type
RevRefEnd()
const {
00609
return RefBegin();
00610 }
00611
00612
00627 ref_type RefNext(
const ref_type & prev)
const {
00628
if ((prev >=
RefEnd()) || (prev <
RefBegin()))
00629
return RefEnd();
00630
00631
return (prev + 1);
00632 }
00633
00634
00649 ref_type RefPrev(
const ref_type & prev)
const {
00650
if ((prev <= RevRefEnd()) || (prev >
RevRefBegin()))
00651
return RevRefEnd();
00652
00653
return (prev - 1);
00654 }
00655
00656
00668 const Tmemb & Deref(
const ref_type & ref)
const {
00669
00670
CB2_MEMORYCHECK((ref < RefEnd()) && (ref >=
RefBegin()));
00671
return (*ref);
00672 }
00673
00674
00678 const Tmemb & RevDeref(
const ref_type & ref)
const {
00679
00680
CB2_MEMORYCHECK((ref >
RevRefEnd()) && (ref <=
RevRefBegin()));
00681
return (*(ref - 1));
00682 }
00683
00684
00690 iterator Begin()
const {
00691
return iterator(*
this,
RefBegin());
00692 }
00693
00694
00700 iterator End()
const {
00701
return iterator(*
this,
RefEnd());
00702 }
00703
00704
00710 rev_iterator RevBegin()
const {
00711
return rev_iterator(*
this,
RevRefBegin());
00712 }
00713
00714
00720 rev_iterator RevEnd()
const {
00721
return rev_iterator(*
this,
RevRefEnd());
00722 }
00723
00724
00739 void Cut(
const size_type pos,
const size_type cnt) {
00740
00741
CB2_RANGECHECK(pos < len, pos);
00742
CB2_RANGECHECK(pos + cnt <= len, pos);
00743
00744
if (cnt > 0) {
00745 size_type mv = len - pos - cnt;
00746
00747
if (mv > 0)
00748 memmove(data + pos, data + pos + cnt,
sizeof(Tmemb) * mv);
00749
00750
00751 allocate(len - cnt);
00752 }
00753 }
00754
00755
00777 void Insert(
const size_type pos,
const size_type cnt,
const this_type & ins) {
00778
CB2_ASSERT(&ins !=
this,
"Cannot insert self-referred items");
00779
00780
00781
CB2_RANGECHECK(pos < len, pos);
00782
CB2_RANGECHECK(cnt < ins.
Len(), cnt);
00783
00784 size_t mv = len - pos;
00785
00786 allocate(len + cnt);
00787
if (mv > 0)
00788 memmove(data + pos + cnt, data + pos,
sizeof(Tmemb) * mv);
00789
00790
00791 memcpy(data + pos, ins.
data,
sizeof(Tmemb) * cnt);
00792 }
00793
00794
private:
00795
00796 Tmemb * data;
00797 size_type allocated;
00798 size_type len;
00799 size_type frag;
00818 void allocate(
const size_type nlen) {
00819
00820 len = nlen;
00821 size_type nalloc = ((len / frag) + 1) * frag;
00822
00823
if (nalloc > allocated) {
00824 Tmemb * newdata =
new Tmemb[nalloc];
00825
if (data != NULL) {
00826 memcpy(newdata, data,
sizeof(Tmemb) * allocated);
00827
delete[] data;
00828 }
00829 data = newdata;
00830 allocated = nalloc;
00831 }
00832 }
00833
00834
00843 void privatize(
const this_type & prev) {
00844
if (&prev !=
this) {
00845 allocate(prev.
len);
00846 memcpy(data, prev.
data,
sizeof(Tmemb) * prev.
len);
00847 }
00848 }
00849
00850 };
00851
00852
00853
template<
class T
char>
class PString;
00867 template<
class T
char>
PString< Tchar> operator+(
const PString< Tchar> & left,
const PString< Tchar> & right) {
00868
PString< Tchar> output(left);
00869 output += right;
00870
return output;
00871 }
00872
00873
00881 template<
class T
char> std::basic_ostream< Tchar, std::char_traits< Tchar> > & operator<<(std::basic_ostream< Tchar, std::char_traits< Tchar> > & stream,
const PString< Tchar> & str) {
00882 stream.write(str.data, str.Len());
00883
return stream;
00884 }
00885
00886
00900 template<
class T
char>
class PString :
public Class {
00901
public:
00902
00903 typedef PString< Tchar> this_type;
00904 typedef Array< Tchar> storage_type;
00905 typedef typename storage_type::size_type
size_type;
00906 typedef typename storage_type::ref_type
ref_type;
00907 typedef Iterator< this_type, ref_type, Tchar> iterator;
00908 typedef RevIterator< this_type, ref_type, Tchar> rev_iterator;
00916 PString()
00917 :
data(
def_frag) {
00918
00919
data << 0;
00920 }
00921
00922
00933 PString(
const this_type & prev)
00934 :
data(prev.
data) {
00935 }
00936
00937 PString(
const Tchar * dt,
const size_type ln)
00938 :
data(
def_frag) {
00939
data.
Fill(dt, ln);
00940
00941
data << 0;
00942 }
00943
00944 PString(
const Tchar * prev)
00945 :
data(
def_frag) {
00946
cpy(prev);
00947 }
00948
00949 PString(
const std::basic_string< Tchar> & prev)
00950 :
data(
def_frag) {
00951
cpy(prev);
00952 }
00953
00954 PString(
const Tchar prev)
00955 :
data(
def_frag) {
00956
cpy(prev);
00957 }
00958
00959 PString(
const signed int prev,
const size_type base = 10)
00960 :
data(
def_frag) {
00961
cpy_numeric_int(prev, base);
00962 }
00963
00964 PString(
const unsigned int prev,
const size_type base = 10)
00965 :
data(
def_frag) {
00966
cpy_numeric_int(prev, base);
00967 }
00968
00969 PString(
const signed long int prev,
const size_type base = 10)
00970 :
data(
def_frag) {
00971
cpy_numeric_int(prev, base);
00972 }
00973
00974 PString(
const unsigned long int prev,
const size_type base = 10)
00975 :
data(
def_frag) {
00976
cpy_numeric_int(prev, base);
00977 }
00978
00979 PString(
const signed long long int prev,
const size_type base = 10)
00980 :
data(
def_frag) {
00981
cpy_numeric_int(prev, base);
00982 }
00983
00984 PString(
const unsigned long long int prev,
const size_type base = 10)
00985 :
data(
def_frag) {
00986
cpy_numeric_int(prev, base);
00987 }
00988
00989 PString(
const float prev)
00990 :
data(
def_frag) {
00991
cpy_numeric_float(prev);
00992 }
00993
00994 PString(
const double prev)
00995 :
data(
def_frag) {
00996
cpy_numeric_float(prev);
00997 }
00998
00999
01010 const this_type &
operator=(
const this_type & prev) {
01011
if (&prev !=
this)
01012
data = prev.
data;
01013
return *
this;
01014 }
01015
01016 const this_type &
operator=(
const Tchar * prev) {
01017
cpy(prev);
01018
return *
this;
01019 }
01020
01021 const this_type &
operator=(
const std::basic_string< Tchar> prev) {
01022
cpy(prev);
01023
return *
this;
01024 }
01025
01026 const this_type &
operator=(
const Tchar prev) {
01027
cpy(prev);
01028
return *
this;
01029 }
01030
01031 const this_type &
operator=(
const signed int prev) {
01032
cpy_numeric_int(prev, 10);
01033
return *
this;
01034 }
01035
01036 const this_type &
operator=(
const unsigned int prev) {
01037
cpy_numeric_int(prev, 10);
01038
return *
this;
01039 }
01040
01041 const this_type &
operator=(
const signed long int prev) {
01042
cpy_numeric_int(prev, 10);
01043
return *
this;
01044 }
01045
01046 const this_type &
operator=(
const unsigned long int prev) {
01047
cpy_numeric_int(prev, 10);
01048
return *
this;
01049 }
01050
01051 const this_type &
operator=(
const signed long long int prev) {
01052
cpy_numeric_int(prev, 10);
01053
return *
this;
01054 }
01055
01056 const this_type &
operator=(
const unsigned long long int prev) {
01057
cpy_numeric_int(prev, 10);
01058
return *
this;
01059 }
01060
01061 const this_type &
operator=(
const float prev) {
01062
cpy_numeric_float(prev);
01063
return *
this;
01064 }
01065
01066 const this_type &
operator=(
const double prev) {
01067
cpy_numeric_float(prev);
01068
return *
this;
01069 }
01070
01071
01078 const this_type &
operator<<(
const Tchar & right) {
01079
data[
data.
Len() - 1] = right;
01080
01081
01082
data << 0;
01083
01084
return *
this;
01085 }
01086
01087
01099 const this_type &
operator+=(
const this_type & right) {
01100
01101
data -= 1;
01102
01103
01104
for (
size_type i = 0; i < right.
Len(); i++)
01105
data << right.
data[i];
01106
01107
01108
data << 0;
01109
01110
return *
this;
01111 }
01112
01113 const this_type &
operator+(
const this_type & right) {
01114
return operator+=(right);
01115 }
01116
01117
friend PString< Tchar> operator+<>(
const PString< Tchar> & left,
const PString< Tchar> & right);
01120
friend std::basic_ostream< Tchar, std::char_traits< Tchar> > & operator<<<>(std::basic_ostream< Tchar, std::char_traits< Tchar> > & stream,
const PString< Tchar> & str);
01139 operator const Tchar * ()
const {
01140
return (
const Tchar * )
data;
01141 }
01142
01143 operator std::basic_string< Tchar> ()
const {
01144 std::basic_string< Tchar> str;
01145
01146
for (
size_type i = 0; i <
Len(); i++)
01147 str +=
data[i];
01148
01149
return str;
01150 }
01151
01152 operator Tchar ()
const {
01153
CB2_CONVERSION(Len() > 0,
"Can't convert empty string to character");
01154
return (Tchar) data[(size_type) 0];
01155 }
01156
01157 operator signed int ()
const {
01158
return (
signed int) numeric_int(
true, (
signed int) 0);
01159 }
01160
01161 operator unsigned int ()
const {
01162
return (
unsigned int) numeric_int(
false, (
unsigned int) 0);
01163 }
01164
01165 operator signed long int ()
const {
01166
return (
signed long int) numeric_int(
true, (
signed long int) 0);
01167 }
01168
01169 operator unsigned long int ()
const {
01170
return (
unsigned long int) numeric_int(
false, (
unsigned long int) 0);
01171 }
01172
01173 operator signed long long int ()
const {
01174
return (
signed long long int) numeric_int(
true, (
signed long long int) 0);
01175 }
01176
01177 operator unsigned long long int ()
const {
01178
return (
unsigned long long int) numeric_int(
false, (
unsigned long long int) 0);
01179 }
01180
01181 operator float ()
const {
01182
return (
float) numeric_float((
float) 0);
01183 }
01184
01185 operator double ()
const {
01186
return (
double) numeric_float((
double) 0);
01187 }
01188
01189
01195 size_type Len()
const {
01196 size_type len = data.Len();
01197
CB2_ASSERT(len > 0,
"Incosistent NULL-termination");
01198
return (len - 1);
01199 }
01200
01201
01208 size_type
Size()
const {
01209
return (Len() *
sizeof(Tchar));
01210 }
01211
01212
01225 Tchar & operator[](
const size_type pos)
const {
01226
CB2_RANGECHECK(pos < Len(), pos);
01227
return data[pos];
01228 }
01229
01230
01241 bool operator==(
const this_type & str)
const {
01242
if (Len() != str.
Len())
01243
return false;
01244
01245
for (size_type i = 0; i < Len(); i++) {
01246
if (data[i] != str.
data[i])
01247
return false;
01248 }
01249
01250
return true;
01251 }
01252
01253
01254 bool operator!=(
const this_type & str)
const {
01255
return (!operator==(str));
01256 }
01257
01258 bool operator==(
const Tchar * str)
const {
01259
if (Len() != strlen(str))
01260
return false;
01261
01262
for (size_type i = 0; i < Len(); i++) {
01263
if (data[i] != str[i])
01264
return false;
01265 }
01266
01267
return true;
01268 }
01269
01270 bool operator!=(
const Tchar * str)
const {
01271
return (!operator==(str));
01272 }
01273
01274
01293 this_type Substr(
const size_type base,
const size_type length = (size_type) -1)
const {
01294
if ((Empty()) || (base >= Len()))
01295
return this_type();
01296
01297 size_type len;
01298
01299
if ((length == (size_type) -1) || (base + length > Len()))
01300 len = Len() - base;
01301
else
01302 len = length;
01303
01304
return this_type(data + base, len);
01305 }
01306
01307
01313 bool Empty()
const {
01314
return (Len() == 0);
01315 }
01316
01317
01326 void Discart(
const bool shrink =
false) {
01327 data.Discart(shrink);
01328
01329 data << 0;
01330 }
01331
01332
01349 bool Pos(
const this_type & needle, size_type & pos,
const size_type from = 0)
const {
01350
if ((Empty()) || (needle.
Empty()))
01351
return false;
01352
01353 size_type ni = 0;
01354
01355
for (size_type i = from; i < Len(); i++) {
01356
while ((i + ni < Len()) && (data[i + ni] == needle.
data[ni])) {
01357 ni++;
01358
01359
if (ni == needle.
Len()) {
01360 pos = i;
01361
return true;
01362 }
01363 }
01364 ni = 0;
01365 }
01366
01367
return false;
01368 }
01369
01381 size_type Subst(
const this_type & needle,
const this_type & replacement) {
01382 size_type cnt = 0;
01383 size_type i = 0;
01384 size_type pos;
01385 size_type nlen = needle.
Len();
01386 size_type rlen = replacement.
Len();
01387
01388
while (Pos(needle, pos, i)) {
01389 data.Cut(pos, nlen);
01390 data.Insert(pos, rlen, replacement.
data);
01391
01392 i = pos + rlen;
01393 cnt++;
01394 }
01395
01396
return cnt;
01397 }
01398
01399
01412 this_type HTML(
const this_type & nl =
"")
const {
01413
this_type str;
01414
bool nl_subst = (nl !=
"");
01415
01416
for (size_type i = 0; i < Len(); i++) {
01417
switch (data[i]) {
01418
case '&':
01419 str +=
"&";
01420
break;
01421
case '<':
01422 str +=
"<";
01423
break;
01424
case '>':
01425 str +=
">";
01426
break;
01427
case '"':
01428 str +=
""";
01429
break;
01430
case '\n':
01431
if (nl_subst) {
01432 str += nl;
01433
break;
01434 }
01435
default:
01436 str << data[i];
01437 }
01438 }
01439
01440
return str;
01441 }
01442
01443
01452 this_type HTMLdecode()
const {
01453
this_type str;
01454
01455
for (size_type i = 0; i < Len(); i++) {
01456
if (data[i] ==
'&') {
01457
if (Substr(i + 1, 4) ==
"amp;") {
01458 str <<
'&';
01459 i += 4;
01460 }
else if (Substr(i + 1, 3) ==
"lt;") {
01461 str <<
'<';
01462 i += 3;
01463 }
else if (Substr(i + 1, 3) ==
"gt;") {
01464 str << '>';
01465 i += 3;
01466 }
else if (Substr(i + 1, 5) ==
"quot;") {
01467 str <<
'"';
01468 i += 5;
01469 }
else
01470
CB2_CONVERSION(
false,
"Unsupported HTML entity");
01471 }
else
01472 str << data[i];
01473 }
01474
01475
return str;
01476 }
01477
01478
01488 this_type SQL()
const {
01489
this_type str;
01490
01491
for (size_type i = 0; i < Len(); i++) {
01492
switch (data[i]) {
01493
case '\'':
01494 str +=
"\\\'";
01495
break;
01496
case '"':
01497 str +=
"\\\"";
01498
break;
01499
case '\\':
01500 str +=
"\\\\";
01501
break;
01502
case 0:
01503 str +=
"\\0";
01504
break;
01505
default:
01506 str << data[i];
01507 }
01508 }
01509
01510
return str;
01511 }
01512
01513
01524 this_type SQLdecode()
const {
01525
this_type str;
01526
01527
for (size_type i = 0; i < Len(); i++) {
01528
if (data[i] ==
'\\') {
01529
CB2_CONVERSION(i + 1 < Len(),
"Illegal character escape");
01530
if (data[i + 1] ==
'0')
01531 str << (Tchar) 0;
01532
else
01533 str << data[i + 1];
01534 i++;
01535 }
else
01536 str << data[i];
01537 }
01538
01539
return str;
01540 }
01541
01542
01554 this_type URL()
const {
01555
this_type str;
01556
01557
for (size_type i = 0; i < Len(); i++) {
01558
switch (data[i]) {
01559
case 'a'...
'z':
01560
case 'A'...
'Z':
01561
case '0'...
'9':
01562
case '-':
01563
case '_':
01564 str << data[i];
01565
break;
01566
case ' ':
01567 str <<
'+';
01568
break;
01569
default:
01570 str <<
'%';
01571
01572
int ord = (((
int) data[i]) >> 4) & 15;
01573
if (ord < 10)
01574 str << (Tchar) ((
int)
'0' + ord);
01575
else
01576 str << (Tchar) ((
int)
'A' + ord);
01577
01578 ord = ((
int) data[i]) & 15;
01579
if (ord < 10)
01580 str << (Tchar) ((
int)
'0' + ord);
01581
else
01582 str << (Tchar) ((
int)
'A' + ord);
01583 }
01584 }
01585
01586
return str;
01587 }
01588
01599 this_type URLdecode()
const {
01600
this_type str;
01601
01602
for (size_type i = 0; i < Len(); i++) {
01603
switch (data[i]) {
01604
case '+':
01605 str <<
' ';
01606
break;
01607
case '%':
01608
CB2_CONVERSION(i + 2 < Len(),
"Illegal character escape");
01609
01610 Tchar c;
01611
01612
switch (data[i + 1]) {
01613
case '0'...
'9':
01614 c = (data[i + 1] -
'0') << 4;
01615
break;
01616
case 'a'...
'f':
01617 c = (data[i + 1] -
'a' + 10) << 4;
01618
break;
01619
case 'A'...
'F':
01620 c = (data[i + 1] -
'A' + 10) << 4;
01621
break;
01622
default:
01623
CB2_CONVERSION(
false,
"Illegal hexadecimal character");
01624 }
01625
01626
switch (data[i + 2]) {
01627
case '0'...
'9':
01628 c += (data[i + 2] -
'0');
01629
break;
01630
case 'a'...
'f':
01631 c += (data[i + 2] -
'a' + 10);
01632
break;
01633
case 'A'...
'F':
01634 c += (data[i + 2] -
'A' + 10);
01635
break;
01636
default:
01637
CB2_CONVERSION(
false,
"Illegal hexadecimal character");
01638 }
01639 str << c;
01640 i += 2;
01641
break;
01642
default:
01643 str << data[i];
01644 }
01645 }
01646
01647
return str;
01648 }
01649
01650
01660 ref_type RefBegin()
const {
01661
return data.
RefBegin();
01662 }
01663
01664
01674 ref_type RefEnd()
const {
01675
return data.RefPrev(data.RevRefBegin());
01676 }
01677
01678
01687 ref_type RevRefBegin()
const {
01688
return data.RefPrev(data.RevRefBegin());
01689 }
01690
01691
01700 ref_type RevRefEnd()
const {
01701
return data.RevRefEnd();
01702 }
01703
01704
01718 ref_type RefNext(
const ref_type & prev)
const {
01719
if ((prev >= RefEnd()) || (prev < RefBegin()))
01720
return RefEnd();
01721
01722
return data.RefNext(prev);
01723 }
01724
01725
01739 ref_type RefPrev(
const ref_type & prev)
const {
01740
if ((prev <= RevRefEnd()) || (prev > RevRefBegin()))
01741
return RevRefEnd();
01742
01743
return data.RefPrev(prev);
01744 }
01745
01746
01758 const Tchar & Deref(
const ref_type & ref)
const {
01759
01760
CB2_MEMORYCHECK((ref < RefEnd()) && (ref >= RefBegin()));
01761
return (*ref);
01762 }
01763
01764
01776 const Tchar & RevDeref(
const ref_type & ref)
const {
01777
01778
CB2_MEMORYCHECK((ref > RevRefEnd()) && (ref <= RevRefBegin()));
01779
return (*(ref - 1));
01780 }
01781
01782
01788 iterator Begin()
const {
01789
return iterator(*
this, RefBegin());
01790 }
01791
01792
01798 iterator End()
const {
01799
return iterator(*
this, RefEnd());
01800 }
01801
01802
01808 rev_iterator RevBegin()
const {
01809
return rev_iterator(*
this, RevRefBegin());
01810 }
01811
01812
01818 rev_iterator RevEnd()
const {
01819
return rev_iterator(*
this, RevRefEnd());
01820 }
01821
01822
private:
01823
01824 storage_type data ;
01825 static const size_type def_frag = 1024;
01836 void cpy(
const Tchar * prev) {
01837 data.Fill(prev, strlen(prev));
01838 data << 0;
01839 }
01840
01841 void cpy(
const std::basic_string< Tchar> & prev) {
01842 data.Discart();
01843
01844
for (
typename std::basic_string< Tchar>::size_type i = 0; i < prev.length(); i++)
01845 data << prev[i];
01846
01847 data << 0;
01848 }
01849
01850 void cpy(
const Tchar prev) {
01851 data.Fill(&prev, 1);
01852 data << 0;
01853 }
01854
01855
01868 template <
class Tnum>
void cpy_numeric_int(
const Tnum prev,
const size_type base) {
01869
CB2_ASSERT((base > 1) || (base < 37),
"Invalid numeric base");
01870
01871
bool sign;
01872 Tnum value = prev;
01873
01874 data.Discart();
01875
01876
if (value < 0) {
01877 sign =
true;
01878 value = -value;
01879 }
else
01880 sign =
false;
01881
01882
while (value > 0) {
01883 Tnum ord = value % base;
01884 value = value / base;
01885
if (ord < 10)
01886 data >> ((Tnum)
'0' + ord);
01887
else
01888 data >> ((Tnum)
'A' + ord);
01889 }
01890
01891
if (sign)
01892 data >>
'-';
01893
01894 data << 0;
01895 }
01896
01897
01906 template <
class Tnum>
void cpy_numeric_float(
const Tnum prev) {
01907
bool sign;
01908 Tnum value = prev;
01909
01910 data.Discart();
01911
01912
if (value < 0) {
01913 sign =
true;
01914 value = -value;
01915 }
else
01916 sign =
false;
01917
01918 Tnum value_floor = floor(prev);
01919 Tnum value_diff = value_floor - value;
01920
01921
while (value_floor > 0) {
01922 Tnum oval = value_floor;
01923 value_floor = floor(value_floor / 10);
01924
int ord = (
int) (oval - value_floor * 10);
01925 data >> ((
int)
'0' + ord);
01926 }
01927
01928
if (sign)
01929 data >>
'-';
01930
01931
bool first =
true;
01932
while (value_diff > 0) {
01933 value_diff = value_diff * 10;
01934
int ord = (
int) value_diff;
01935 value_floor = floor(value_diff);
01936 value_diff = value_diff - value_floor;
01937
if (first) {
01938 data <<
'.';
01939 first =
false;
01940 }
01941 data << ((
int)
'0' + ord);
01942 }
01943
01944 data << 0;
01945 }
01946
01947
01959 template<
class Tnum> Tnum numeric_int(
const bool signed_type,
const Tnum zero)
const {
01960 Tnum value = zero;
01961 Tnum base = 10;
01962 Tnum literal;
01963
01964
int state;
01965
01966
01967
01968
01969
01970
bool sign =
false;
01971
01972
if (signed_type)
01973 state = 0;
01974
else
01975 state = 1;
01976
01977
for (size_type i = 0; i < Len(); i++) {
01978
switch (data[i]) {
01979
case '+':
01980
switch (state) {
01981
case 0:
01982 state = 1;
01983
break;
01984
default:
01985
CB2_CONVERSION(
false,
"Misplaced sign characters");
01986 }
01987
break;
01988
case '-':
01989
if (!signed_type)
01990
CB2_CONVERSION(
false,
"Unary minus while converting to unsigned type");
01991
switch (state) {
01992
case 0:
01993 state = 1;
01994 sign =
true;
01995
break;
01996
default:
01997
CB2_CONVERSION(
false,
"Misplaced sign characters");
01998 }
01999
break;
02000
case '0':
02001
if (state == 1) {
02002
if ((i + 1 < Len()) && (data[i + 1] ==
'x')) {
02003 base = 16;
02004 state = 2;
02005 i++;
02006
break;
02007 }
else {
02008 base = 8;
02009 state = 2;
02010
break;
02011 }
02012 }
02013
case '1'...
'9':
02014
switch (state) {
02015
case 0:
02016
case 1:
02017
case 2:
02018 state = 2;
02019 literal = (Tnum) data[i] - (Tnum)
'0';
02020
CB2_CONVERSION(literal < base,
"Invalid numeric literal");
02021 value *= base;
02022 value += literal;
02023
break;
02024
default:
02025
CB2_CONVERSION(
false,
"Misplaced character");
02026 }
02027
break;
02028
case 'a'...
'z':
02029
switch (state) {
02030
case 0:
02031
case 1:
02032
case 2:
02033 state = 2;
02034 literal = (Tnum) data[i] - (Tnum)
'a' + 10;
02035
CB2_CONVERSION(literal < base,
"Invalid numeric literal");
02036 value *= base;
02037 value += literal;
02038
break;
02039
default:
02040
CB2_CONVERSION(
false,
"Misplaced character");
02041 }
02042
break;
02043
case 'A'...
'Z':
02044
switch (state) {
02045
case 0:
02046
case 1:
02047
case 2:
02048 state = 2;
02049 literal = (Tnum) data[i] - (Tnum)
'A' + 10;
02050
CB2_CONVERSION(literal < base,
"Invalid numeric literal");
02051 value *= base;
02052 value += literal;
02053
break;
02054
default:
02055
CB2_CONVERSION(
false,
"Misplaced character");
02056 }
02057
break;
02058
case ' ':
02059
case '\t':
02060
case 0:
02061
switch (state) {
02062
case 0:
02063
break;
02064
case 2:
02065 state = 3;
02066
break;
02067
default:
02068
CB2_CONVERSION(
false,
"Misplaced whitespace");
02069 }
02070
break;
02071
default:
02072
CB2_CONVERSION(
false,
"Invalid character");
02073 }
02074 }
02075
02076
if (sign)
02077 value = -value;
02078
02079
CB2_CONVERSION(state >= 2,
"Invalid number");
02080
02081
return value;
02082
02083 }
02084
02085
02099 template<
class Tnum> Tnum numeric_float(
const Tnum zero)
const {
02100 Tnum value = zero;
02101 Tnum fraction = 10;
02102
02103
int state = 0;
02104
02105
02106
02107
02108
02109
bool sign =
false;
02110
02111
for (size_type i = 0; i < Len(); i++) {
02112
switch (data[i]) {
02113
case '+':
02114
switch (state) {
02115
case 0:
02116 state = 1;
02117
break;
02118
default:
02119
CB2_CONVERSION(
false,
"Misplaced sign characters");
02120 }
02121
break;
02122
case '-':
02123
switch (state) {
02124
case 0:
02125 state = 1;
02126 sign =
true;
02127
break;
02128
default:
02129
CB2_CONVERSION(
false,
"Misplaced sign characters");
02130 }
02131
break;
02132
case '0'...
'9':
02133
switch (state) {
02134
case 0:
02135
case 1:
02136 state = 1;
02137 value *= 10;
02138 value += (Tnum) data[i] - (Tnum)
'0';
02139
break;
02140
case 2:
02141 value += ((Tnum) data[i] - (Tnum)
'0') / fraction;
02142 fraction *= 10;
02143
break;
02144
default:
02145
CB2_CONVERSION(
false,
"Misplaced character");
02146 }
02147
break;
02148
case '.':
02149
switch (state) {
02150
case 0:
02151
case 1:
02152 state = 2;
02153
break;
02154
default:
02155
CB2_CONVERSION(
false,
"Misplaced period");
02156 }
02157
break;
02158
case ' ':
02159
case '\t':
02160
case 0:
02161
switch (state) {
02162
case 0:
02163
break;
02164
case 1:
02165
case 2:
02166 state = 3;
02167
break;
02168
default:
02169
CB2_CONVERSION(
false,
"Misplaced whitespace");
02170 }
02171
break;
02172
default:
02173
CB2_CONVERSION(
false,
"Invalid character");
02174 }
02175 }
02176
02177
if (sign)
02178 value = -value;
02179
02180
CB2_CONVERSION(state >= 1,
"Invalid number");
02181
02182
return value;
02183
02184 }
02185
02186
02187 };
02188
02189
02204 template<
class Tmemb>
class List :
public Class {
02205
public:
02206
02207 typedef List< Tmemb> this_type;
02208 typedef size_t size_type;
02220 typedef struct _item_type {
02221 Tmemb * data;
02222 bool local;
02223 struct _item_type * prev;
02224 struct _item_type * next;
02225 }
item_type;
02226
02227 typedef item_type *
ref_type;
02228 typedef Iterator< this_type, ref_type, Tmemb> iterator;
02229 typedef RevIterator< this_type, ref_type, Tmemb> rev_iterator;
02237 List() {
02238 list = NULL;
02239 tail = NULL;
02240 len = 0;
02241 }
02242
02243
02251 List(
const this_type & prev) {
02252
for (item_type * ac = prev.
list; ac != NULL; ac = ac->
next) {
02253
if (ac->local)
02254 PushBack(*(ac->data));
02255
else
02256
operator<<(ac->data);
02257 }
02258 }
02259
02260
02266 ~
List() {
02267 Discart();
02268 }
02269
02270
02278 const this_type & operator=(
const this_type & prev) {
02279
if (&prev !=
this) {
02280 Discart();
02281
for (item_type * ac = prev.
list; ac != NULL; ac = ac->
next) {
02282
if (ac->local)
02283 PushBack(*(ac->data));
02284
else
02285
operator<<(ac->data);
02286 }
02287 }
02288
return *
this;
02289 }
02290
02291
02307 const this_type &
operator<<(Tmemb * prev) {
02308
if (list == NULL) {
02309 list =
new item_type;
02310 list->data = prev;
02311 list->local =
false;
02312 list->prev = NULL;
02313 list->next = NULL;
02314 tail = list;
02315 }
else {
02316 tail->next =
new item_type;
02317 tail->next->data = prev;
02318 tail->next->local =
false;
02319 tail->next->prev = tail;
02320 tail->next->next = NULL;
02321 tail = tail->next;
02322 }
02323 len++;
02324
02325
return *
this;
02326 }
02327
02328
02344 const this_type & operator>>(Tmemb * prev) {
02345
if (list == NULL) {
02346 list =
new item_type;
02347 list->data = prev;
02348 list->local =
false;
02349 list->prev = NULL;
02350 list->next = NULL;
02351 tail = list;
02352 }
else {
02353 item_type * ac =
new item_type;
02354 ac->data = prev;
02355 ac->local =
false;
02356 ac->prev = NULL;
02357 ac->next = list;
02358 list->prev = ac;
02359 list = ac;
02360 }
02361 len++;
02362
02363
return *
this;
02364 }
02365
02366
02377 void PushBack(
const Tmemb & prev) {
02378 Tmemb * local =
new Tmemb(prev);
02379
02380
if (list == NULL) {
02381 list =
new item_type;
02382 list->data = local;
02383 list->local =
true;
02384 list->prev = NULL;
02385 list->next = NULL;
02386 tail = list;
02387 }
else {
02388 tail->next =
new item_type;
02389 tail->next->data = local;
02390 tail->next->local =
true;
02391 tail->next->prev = tail;
02392 tail->next->next = NULL;
02393 tail = tail->next;
02394 }
02395 len++;
02396 }
02397
02398
02409 void PushFront(
const Tmemb & prev) {
02410 Tmemb * local =
new Tmemb(prev);
02411
02412
if (list == NULL) {
02413 list =
new item_type;
02414 list->data = local;
02415 list->local =
true;
02416 list->prev = NULL;
02417 list->next = NULL;
02418 tail = list;
02419 }
else {
02420 item_type * ac =
new item_type;
02421 ac->data = local;
02422 ac->local =
true;
02423 ac->prev = NULL;
02424 ac->next = list;
02425 list->prev = ac;
02426 list = ac;
02427 }
02428 len++;
02429 }
02430
02431
02443 Tmemb & operator[](
const size_type pos)
const {
02444
CB2_RANGECHECK(pos < len, pos);
02445
02446 item_type * ac = list;
02447 size_type i = pos;
02448
02449
while (ac != NULL) {
02450
if (i == 0)
02451
return *(ac->data);
02452 i--;
02453 ac = ac->next;
02454 }
02455
02456
CB2_ASSERT(
false,
"Inconsistent list data");
02457
return *(list->data);
02458 }
02459
02460
02466 void Discart() {
02467 item_type * ac = list;
02468
02469
while (ac != NULL) {
02470
if (ac->local)
02471
delete ac->data;
02472
02473 item_type * next = ac->next;
02474
delete ac;
02475 ac = next;
02476 }
02477
02478 list = NULL;
02479 tail = NULL;
02480 }
02481
02482
02488 size_type Len()
const {
02489
return len;
02490 }
02491
02492
02498 bool Empty()
const {
02499
return (len == 0);
02500 }
02501
02502
02508 Tmemb * Head()
const {
02509
if (list != NULL)
02510
return list->data;
02511
02512
return NULL;
02513 }
02514
02515
02521 Tmemb * Tail()
const {
02522
if (tail != NULL)
02523
return tail->data;
02524
02525
return NULL;
02526 }
02527
02528
02539 ref_type RefBegin()
const {
02540
return list;
02541 }
02542
02543
02551 ref_type RefEnd()
const {
02552
return NULL;
02553 }
02554
02555
02566 ref_type RevRefBegin()
const {
02567
return tail;
02568 }
02569
02570
02578 ref_type RevRefEnd()
const {
02579
return NULL;
02580 }
02581
02582
02594 ref_type RefNext(
const ref_type & prev)
const {
02595
return prev->next;
02596 }
02597
02598
02610 ref_type RefPrev(
const ref_type & prev)
const {
02611
return prev->prev;
02612 }
02613
02614
02626 const Tmemb & Deref(
const ref_type & ref)
const {
02627
CB2_MEMORYCHECK(ref != NULL);
02628
return *(ref->data);
02629 }
02630
02631
02643 const Tmemb & RevDeref(
const ref_type & ref)
const {
02644
CB2_MEMORYCHECK(ref != NULL);
02645
return *(ref->data);
02646 }
02647
02648
02654 iterator Begin()
const {
02655
return iterator(*
this, RefBegin());
02656 }
02657
02658
02664 iterator End()
const {
02665
return iterator(*
this, RefEnd());
02666 }
02667
02668
02674 rev_iterator RevBegin()
const {
02675
return rev_iterator(*
this, RevRefBegin());
02676 }
02677
02678
02684 rev_iterator RevEnd()
const {
02685
return rev_iterator(*
this, RevRefEnd());
02686 }
02687
02688
private:
02689
02690 item_type * list;
02691 item_type * tail;
02692 size_type len;
02694 };
02695
02696
02705 template<
class Tkey,
class Tvalue>
class PMap :
public Class {
02706
public:
02707
02708 typedef PMap< Tkey, Tvalue> this_type;
02719 PMap(
const Tkey & key,
const Tvalue & value) {
02720 _key = key;
02721 _value = value;
02722 _null =
false;
02723 }
02724
02725
02733 PMap(
const Tkey & key) {
02734 _key = key;
02735 _null =
true;
02736 }
02737
02738
02747 PMap(
const this_type & prev) {
02748 _key = prev.
_key;
02749
if (prev.
_null)
02750 _null =
true;
02751
else {
02752 _value = prev.
_value;
02753 _null =
false;
02754 }
02755 }
02756
02757
02767 const this_type & operator=(
const this_type & prev) {
02768
if (&prev !=
this) {
02769 _key = prev.
_key;
02770
if (prev.
_null)
02771 _null =
true;
02772
else {
02773 _value = prev.
_value;
02774 _null =
false;
02775 }
02776 }
02777
return *
this;
02778 }
02779
02780
02786 const Tkey & GetKey()
const {
02787
return _key;
02788 }
02789
02790
02799 const Tvalue & GetValue()
const {
02800
CB2_ASSERT(_null ==
false,
"Value of NULL field is undefined");
02801
return _value;
02802 }
02803
02804
02810 bool IsNULL()
const {
02811
return _null;
02812 }
02813
02814
private:
02815
02816 Tkey _key;
02817 Tvalue _value;
02818 bool _null;
02820 };
02821
02822
02830 template<
class Tkey,
class Tvalue>
class PMapList :
public Class {
02831
public:
02832
02833 typedef PMapList< Tkey, Tvalue> this_type;
02834 typedef PMap< Tkey, Tvalue> item_type;
02835 typedef List< item_type> storage_type;
02836 typedef typename storage_type::size_type
size_type;
02837 typedef typename storage_type::ref_type
ref_type;
02838 typedef Iterator< this_type, ref_type, item_type> iterator;
02839 typedef RevIterator< this_type, ref_type, item_type> rev_iterator;
02847 PMapList() {
02848
02849 }
02850
02851
02857 ~
PMapList() {
02858
02859 }
02860
02861
02872 const this_type &
operator<<(
const item_type & map) {
02873 data.PushBack(map);
02874
return *
this;
02875 }
02876
02877
02886 void Add(
const Tkey & key,
const Tvalue & value) {
02887
item_type map(key, value);
02888 data.PushBack(map);
02889 }
02890
02891
02899 void Add(
const Tkey & key) {
02900
item_type map(key);
02901 data.PushBack(map);
02902 }
02903
02904
02918 const Tvalue & operator[](
const Tkey & key)
const {
02919
for (
typename storage_type::iterator it = data.Begin(); it != data.End(); ++it) {
02920
if (it->GetKey() == key)
02921
return it->GetValue();
02922 }
02923
CB2_NOTFOUND(
false);
02924 }
02925
02926
02938 bool IsNULL(
const Tkey & key)
const {
02939
for (
typename storage_type::iterator it = data.Begin(); it != data.End(); ++it) {
02940
if (it->GetKey() == key)
02941
return it->IsNULL();
02942 }
02943
CB2_NOTFOUND(
false);
02944 }
02945
02946
02952 size_type Len()
const {
02953
return data.Len();
02954 }
02955
02956
02962 bool Empty()
const {
02963
return data.Empty();
02964 }
02965
02966
02977 ref_type RefBegin()
const {
02978
return data.RefBegin();
02979 }
02980
02981
02989 ref_type RefEnd()
const {
02990
return data.RefEnd();
02991 }
02992
02993
03004 ref_type RevRefBegin()
const {
03005
return data.RevRefBegin();
03006 }
03007
03008
03016 ref_type RevRefEnd()
const {
03017
return data.RevRefEnd();
03018 }
03019
03020
03032 ref_type RefNext(
const ref_type & prev)
const {
03033
return data.RefNext(prev);
03034 }
03035
03036
03048 ref_type RefPrev(
const ref_type & prev)
const {
03049
return data.RefPrev(prev);
03050 }
03051
03052
03064 const item_type & Deref(
const ref_type & ref)
const {
03065
return data.Deref(ref);
03066 }
03067
03068
03080 const item_type & RevDeref(
const ref_type & ref)
const {
03081
return data.RevDeref(ref);
03082 }
03083
03084
03090 iterator Begin()
const {
03091
return iterator(*
this, RefBegin());
03092 }
03093
03094
03100 iterator End()
const {
03101
return iterator(*
this, RefEnd());
03102 }
03103
03104
03110 rev_iterator RevBegin()
const {
03111
return rev_iterator(*
this, RevRefBegin());
03112 }
03113
03114
03120 rev_iterator RevEnd()
const {
03121
return rev_iterator(*
this, RevRefEnd());
03122 }
03123
03124
private:
03125
03126 storage_type data;
03127 };
03128
03129
03136 template<
class Tmemb>
class Tree :
public Class {
03137
public:
03138
03139 typedef Tree< Tmemb> this_type;
03140 typedef List< this_type> subtrees_type;
03141 typedef typename subtrees_type::size_type
size_type;
03142 typedef typename subtrees_type::ref_type
ref_type;
03143 typedef Iterator< this_type, ref_type, this_type> iterator;
03144 typedef RevIterator< this_type, ref_type, this_type> rev_iterator;
03152 Tree() {
03153 data = NULL;
03154 }
03155
03156
03162 ~
Tree() {
03163
if (local)
03164
delete data;
03165
03166 }
03167
03168
03178 bool IsNULL()
const {
03179
return (data == NULL);
03180 }
03181
03182
03188 size_type CountSubtrees()
const {
03189
return subtrees.Len();
03190 }
03191
03192
03203 const this_type &
operator<<(
const Tmemb * prev) {
03204
CB2_ASSERT(data == NULL,
"Tree node can hold just one value");
03205 data = prev;
03206 local =
false;
03207 }
03208
03209
03219 void Push(
const Tmemb & prev) {
03220
CB2_ASSERT(data == NULL,
"Tree node can hold just one value");
03221 data =
new Tmemb(prev);
03222 local =
true;
03223 }
03224
03225
03233 this_type * AddChild() {
03234
Tree< Tmemb> child;
03235 subtrees.PushBack(child);
03236
return subtrees.Tail();
03237 }
03238
03239
03245 ref_type RefBegin()
const {
03246
return subtrees.RefBegin();
03247 }
03248
03249
03255 ref_type RefEnd()
const {
03256
return subtrees.RefEnd();
03257 }
03258
03259
03265 ref_type RevRefBegin()
const {
03266
return subtrees.RevRefBegin();
03267 }
03268
03269
03275 ref_type RevRefEnd()
const {
03276
return subtrees.RevRefEnd();
03277 }
03278
03279
03287 ref_type RefNext(
const ref_type & prev)
const {
03288
return subtrees.RefNext(prev);
03289 }
03290
03291
03299 ref_type RefPrev(
const ref_type & prev)
const {
03300
return subtrees.RefPrev(prev);
03301 }
03302
03303
03311 const this_type & Deref(
const ref_type & ref)
const {
03312
return subtree.Deref(ref);
03313 }
03314
03315
03323 const this_type & RevDeref(
const ref_type & ref)
const {
03324
return subtree.RevDeref(ref);
03325 }
03326
03327
03333 iterator Begin()
const {
03334
return iterator(*
this, RefBegin());
03335 }
03336
03337
03343 iterator End()
const {
03344
return iterator(*
this, RefEnd());
03345 }
03346
03347
03353 rev_iterator RevBegin()
const {
03354
return rev_iterator(*
this, RevRefBegin());
03355 }
03356
03357
03363 rev_iterator RevEnd()
const {
03364
return rev_iterator(*
this, RevRefEnd());
03365 }
03366
03367
private:
03368 Tmemb * data;
03369 bool local;
03370 subtrees_type subtrees;
03372 };
03373
03374
03383 template<
class T
char>
class PStringTokenizer :
public Class {
03384
public:
03385
03386 typedef PStringTokenizer< Tchar> this_type;
03387 typedef PString< Tchar> item_type;
03388 typedef List< item_type> storage_type;
03389 typedef typename storage_type::size_type
size_type;
03390 typedef typename storage_type::ref_type
ref_type;
03391 typedef Iterator< this_type, ref_type, item_type> iterator;
03392 typedef RevIterator< this_type, ref_type, item_type> rev_iterator;
03405 PStringTokenizer(
const item_type & str,
const item_type & delim) {
03406 tokens =
new storage_type;
03407
03408 size_type pos = 0;
03409 size_type len;
03410 size_type dlen = delim.
Len();
03411
03412
while ((pos < str.
Len()) && (str.
Pos(delim, len, pos))) {
03413 tokens->PushBack(str.
Substr(pos, len - pos));
03414 pos = len + dlen;
03415 }
03416
03417 tokens->PushBack(str.
Substr(pos));
03418 }
03419
03420
03426 ~
PStringTokenizer() {
03427
delete tokens;
03428 }
03429
03430
03436 size_type Len()
const {
03437
return tokens->Len();
03438 }
03439
03440
03448 const item_type & operator[](
const size_type pos)
const {
03449
return (*tokens)[pos];
03450 }
03451
03452
03461 ref_type RefBegin()
const {
03462
return tokens->RefBegin();
03463 }
03464
03465
03475 ref_type RefEnd()
const {
03476
return tokens->RefEnd();
03477 }
03478
03479
03488 ref_type RevRefBegin()
const {
03489
return tokens->RevRefBegin();
03490 }
03491
03492
03501 ref_type RevRefEnd()
const {
03502
return tokens->RevRefBegin();
03503 }
03504
03505
03517 ref_type RefNext(
const ref_type & prev)
const {
03518
return tokens->RefNext(prev);
03519 }
03520
03521
03533 ref_type RefPrev(
const ref_type & prev)
const {
03534
return tokens->RefPrev(prev);
03535 }
03536
03537
03549 const item_type & Deref(
const ref_type & ref)
const {
03550
return tokens->Deref(ref);
03551 }
03552
03553
03565 const item_type & RevDeref(
const ref_type & ref)
const {
03566
return tokens->RevDeref(ref);
03567 }
03568
03569
03575 iterator Begin()
const {
03576
return iterator(*
this, RefBegin());
03577 }
03578
03579
03585 iterator End()
const {
03586
return iterator(*
this, RefEnd());
03587 }
03588
03589
03595 rev_iterator RevBegin()
const {
03596
return rev_iterator(*
this, RevRefBegin());
03597 }
03598
03599
03605 rev_iterator RevEnd()
const {
03606
return rev_iterator(*
this, RevRefEnd());
03607 }
03608
03609
private:
03610
03611 storage_type * tokens;
03613 };
03614
03615
03616 typedef PString< char> String;
03617 typedef PStringTokenizer< char> StringTokenizer;
03618 typedef PMap< String, String> Map;
03619 typedef PMapList< String, String> MapList;
03628 class Exception :
public Class {
03629
public:
03630
Exception();
03631
Exception(
const String what);
03632
Exception(
const String what,
const int line);
03634
String What()
const;
03635
private:
03636 String except;
03637 };
03638
03639
03647 template<
class Tsize>
class ExceptionRange :
public Exception {
03648
public:
03649
03650
03656 ExceptionRange()
03657 :
Exception() {
03658
03659 }
03660
03661
03669 ExceptionRange(
const String what)
03670 :
Exception(what) {
03671
03672 }
03673
03674
03683 ExceptionRange(
const String what,
const int line)
03684 :
Exception(what, line) {
03685 }
03686
03687
03697 ExceptionRange(
const String what,
const Tsize value,
const String what2,
const int line)
03698 :
Exception(what +
String(value) + what2, line) {
03699 }
03700 };
03701
03702
03712 class ExceptionConversion :
public Exception {
03713
public:
03714
ExceptionConversion();
03715
ExceptionConversion(
const String what);
03716
ExceptionConversion(
const String what,
const int line);
03717 };
03718
03719
03727 class ExceptionMemory :
public Exception {
03728
public:
03729
ExceptionMemory();
03730
ExceptionMemory(
const String what);
03731
ExceptionMemory(
const String what,
const int line);
03732 };
03733
03734
03741 class ExceptionAssert :
public Exception {
03742
public:
03743
ExceptionAssert();
03744
ExceptionAssert(
const String what);
03745
ExceptionAssert(
const String what,
const int line);
03746 };
03747
03748
03756 class ExceptionNotFound :
public Exception {
03757
public:
03758
ExceptionNotFound();
03759
ExceptionNotFound(
const String what);
03760
ExceptionNotFound(
const String what,
const int line);
03761 };
03762
03763 };
03764
03765
03766
#endif