Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

utils.h

Go to the documentation of this file.
00001 /*********************************************************************** 00002 00003 ColorBox2: utils.h 00004 (c) 2004 by Martin Decky 00005 00006 Common datatypes, classes, macros. 00007 00008 Distributed under the terms of Lesser General Public Licence, see 00009 COPYING. 00010 00011 0.3 10th August 2004 complete rewrite, C++ 00012 0.4 10th September 2004 reverse iterators 00013 0.5 15th September 2004 this_types, storage_types, cleanup 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 /* Empty data */ 00325 data = NULL; 00326 allocated = 0; 00327 frag = fragment; 00328 allocate(0); 00329 } 00330 00331 00340 Array(const this_type & prev) { 00341 /* Empty data */ 00342 data = NULL; 00343 allocated = 0; 00344 frag = prev.frag; 00345 privatize(prev); 00346 } 00347 00348 00354 ~Array() { 00355 if (data) /* Dispose data */ 00356 delete[] data; 00357 } 00358 00359 00368 const this_type & operator=(const this_type & prev) { 00369 if (&prev != this) { /* No self-assignment */ 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 /* Shift original items 00426 and put new item at the beginning */ 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 /* Dispose data */ 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())) /* Check pointer range */ 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())) /* Check pointer range */ 00651 return RevRefEnd(); 00652 00653 return (prev - 1); 00654 } 00655 00656 00668 const Tmemb & Deref(const ref_type & ref) const { 00669 /* Check pointer range */ 00670 CB2_MEMORYCHECK((ref < RefEnd()) && (ref >= RefBegin())); 00671 return (*ref); 00672 } 00673 00674 00678 const Tmemb & RevDeref(const ref_type & ref) const { 00679 /* Check pointer range */ 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 /* Range check */ 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) /* Shift items front */ 00748 memmove(data + pos, data + pos + cnt, sizeof(Tmemb) * mv); 00749 00750 /* Discart overlapping items */ 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 /* Range check */ 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) /* Shift items back */ 00788 memmove(data + pos + cnt, data + pos, sizeof(Tmemb) * mv); 00789 00790 /* Insert items */ 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 /* Round items to nearest fragment */ 00820 len = nlen; 00821 size_type nalloc = ((len / frag) + 1) * frag; 00822 00823 if (nalloc > allocated) { /* Enlarge memory pool */ 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 Tchar> class PString; 00867 template< class Tchar> 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 Tchar> 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 Tchar> 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 /* Add NULL-termination */ 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 /* Add NULL-termination */ 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 /* Add NULL-termination */ 01082 data << 0; 01083 01084 return *this; 01085 } 01086 01087 01099 const this_type & operator+=(const this_type & right) { 01100 /* Remove NULL-termination from left operand */ 01101 data -= 1; 01102 01103 /* Concatenate characters */ 01104 for (size_type i = 0; i < right.Len(); i++) 01105 data << right.data[i]; 01106 01107 /* Add NULL-termination */ 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++) { /* Compare string characters */ 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++) { /* Compare string characters */ 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())) /* Truncate length */ 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 /* Add NULL-termination */ 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++) { /* For each character in haystack */ 01356 while ((i + ni < Len()) && (data[i + ni] == needle.data[ni])) { /* Compare characters with needle */ 01357 ni++; 01358 01359 if (ni == needle.Len()) { /* Found match */ 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); /* Cut out needle */ 01390 data.Insert(pos, rlen, replacement.data); /* Insert replacement */ 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 += "&amp;"; 01420 break; 01421 case '<': 01422 str += "&lt;"; 01423 break; 01424 case '>': 01425 str += "&gt;"; 01426 break; 01427 case '"': 01428 str += "&quot;"; 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())) /* Check ranges */ 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())) /* Check ranges */ 01741 return RevRefEnd(); 01742 01743 return data.RefPrev(prev); 01744 } 01745 01746 01758 const Tchar & Deref(const ref_type & ref) const { 01759 /* Check pointer range */ 01760 CB2_MEMORYCHECK((ref < RefEnd()) && (ref >= RefBegin())); 01761 return (*ref); 01762 } 01763 01764 01776 const Tchar & RevDeref(const ref_type & ref) const { 01777 /* Check pointer range */ 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) { /* Work with absolute value, note sign */ 01877 sign = true; 01878 value = -value; 01879 } else 01880 sign = false; 01881 01882 while (value > 0) { /* Get orders */ 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) /* Add unary minus */ 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) { /* Work with absolute value, note sign */ 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) { /* Itegral part */ 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) { /* Fraction part */ 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 /* State numbers: 01966 0 ... awaiting sign character, base prefix or literal 01967 1 ... awaiting base prefix or literal 01968 2 ... awaiting literal 01969 3 ... tailing whitespace */ 01970 bool sign = false; 01971 01972 if (signed_type) 01973 state = 0; 01974 else 01975 state = 1; /* Unsigned type -> don't accept sign character */ 01976 01977 for (size_type i = 0; i < Len(); i++) { 01978 switch (data[i]) { 01979 case '+': /* Unary plus */ 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 '-': /* Unary minus */ 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': /* '0' as literal or as base prefix */ 02001 if (state == 1) { 02002 if ((i + 1 < Len()) && (data[i + 1] == 'x')) { /* Leading '0x' -> hexadecimal */ 02003 base = 16; 02004 state = 2; 02005 i++; 02006 break; 02007 } else { /* Leading '0' -> octal */ 02008 base = 8; 02009 state = 2; 02010 break; 02011 } 02012 } 02013 case '1'...'9': /* Literals */ 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': /* Literals */ 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': /* Literals */ 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: /* Beginning or tailing whitespace */ 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) /* 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 /* State numbers: 02105 0 ... awaiting sign character, integer literal or period 02106 1 ... integer literal or period 02107 2 ... awaiting fraction literal 02108 3 ... tailing whitespace */ 02109 bool sign = false; 02110 02111 for (size_type i = 0; i < Len(); i++) { 02112 switch (data[i]) { 02113 case '+': /* Unary plus */ 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 '-': /* Unary minus */ 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': /* Literal */ 02133 switch (state) { 02134 case 0: 02135 case 1: /* Integral part */ 02136 state = 1; 02137 value *= 10; 02138 value += (Tnum) data[i] - (Tnum) '0'; 02139 break; 02140 case 2: /* Fraction part */ 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 '.': /* Period */ 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: /* Beginning or tailing whitespace */ 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) /* 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) { /* No self-assignment */ 02280 Discart(); 02281 for (item_type * ac = prev.list; ac != NULL; ac = ac->next) { /* Copy list items */ 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); /* Unreachable, just to supress compiler errors */ 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) /* NULL value */ 02750 _null = true; 02751 else { /* Non-NULL value */ 02752 _value = prev._value; 02753 _null = false; 02754 } 02755 } 02756 02757 02767 const this_type & operator=(const this_type & prev) { 02768 if (&prev != this) { /* No self-assignment */ 02769 _key = prev._key; 02770 if (prev._null) /* NULL value */ 02771 _null = true; 02772 else { /* Non-NULL value */ 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 /* Empty */ 02849 } 02850 02851 02857 ~PMapList() { 02858 /* Empty */ 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; /* Delete data if local copy */ 03165 /* Subtrees will be deallocated recursivelly */ 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 Tchar> 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 /* Empty */ 03659 } 03660 03661 03669 ExceptionRange(const String what) 03670 : Exception(what) { 03671 /* Empty */ 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

Generated on Thu Sep 16 23:26:49 2004 for ColorBox2 by doxygen 1.3.7