fixed some bugs in new 'g'o system
[k8-i-v-a-n.git] / src / felib / festring.h
blob787a82240996cbf83f7c19edc74de75e878f0723
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #ifndef __FELIB_FESTRING_H__
13 #define __FELIB_FESTRING_H__
15 #include <cctype>
16 #include <vector>
17 #include <time.h>
19 #include "felibdef.h"
21 #ifndef WIN32
22 # define LONG_LONG_PFORMAT "%lld"
23 #else
24 # define LONG_LONG_PFORMAT "%I64d"
25 #endif
27 #define FESTRING_PAGE 0x7F
29 class festring {
30 public:
31 typedef feuLong sizetype;
32 typedef const feuLong csizetype;
33 /* It can be proven that the code works even if OwnsData is left
34 uninitialized. However, Valgrind reports this as a possible error
35 which is annoying */
36 festring () : Data(0), Size(0), OwnsData(false), Reserved(0) {}
37 explicit festring (sizetype);
38 festring (sizetype, char);
39 #if 1
40 festring (cchar *CStr) : Data(0/*const_cast<char *>(CStr)*/), Size(strlen(CStr)), OwnsData(true), Reserved(0) {
41 const char *s = const_cast<char *>(CStr);
42 int N = s ? strlen(s) : 0;
43 Reserved = N|FESTRING_PAGE;
44 char *Ptr = 4+new char[Reserved+5];
45 REFS(Ptr) = 0;
46 Data = Ptr;
47 if (N > 0) {
48 if (s) memmove(Data, s, N); else memset(Data, 0, N);
51 festring (cchar *CStr, sizetype N) : Data(0/*const_cast<char *>(CStr)*/), Size(N), OwnsData(true), Reserved(0) {
52 const char *s = const_cast<char *>(CStr);
53 Reserved = N|FESTRING_PAGE;
54 char *Ptr = 4+new char[Reserved+5];
55 REFS(Ptr) = 0;
56 Data = Ptr;
57 if (N > 0) {
58 if (s) memmove(Data, s, N); else memset(Data, 0, N);
61 #else
62 festring (cchar *CStr) : Data(const_cast<char *>(CStr)), Size(strlen(CStr)), OwnsData(false), Reserved(0) {}
63 festring (cchar *CStr, sizetype N) : Data(const_cast<char *>(CStr)), Size(N), OwnsData(false), Reserved(0) {}
64 #endif
65 festring (cfestring &);
66 ~festring ();
67 festring &Capitalize ();
68 festring CapitalizeCopy () const { return festring(*this).Capitalize(); }
69 festring &operator = (cchar *);
70 festring &operator = (cfestring &);
71 festring &operator << (char);
72 festring &operator << (cchar *);
73 festring &operator << (cfestring &);
74 festring &operator << (short Int) { return Append(Int); }
75 festring &operator << (uShort Int) { return Append(Int); }
76 festring &operator << (int Int) { return Append(Int); }
77 festring &operator << (uInt Int) { return Append((int)Int); } //k8:64
78 //festring &operator << (sLong Int) { return Append(Int); } //k8:64
79 //festring &operator << (feuLong Int) { return Append(Int); } //k8:64
80 festring &operator << (time_t Int) { return Append((int64_t)Int); } //k8:64
81 bool operator < (cfestring &) const;
82 bool operator <= (cfestring &) const;
83 bool operator > (cfestring &) const;
84 bool operator >= (cfestring &) const;
85 truth operator == (cfestring &) const;
86 truth operator != (cfestring &) const;
87 truth operator == (cchar*) const;
88 truth operator != (cchar*) const;
89 int Compare (cfestring &) const;
90 int CompareIgnoreCase (cfestring &) const;
91 cchar *CStr () const;
92 sizetype GetSize () const { return Size; }
93 void Empty ();
94 void Assign (sizetype, char);
95 void Resize (sizetype, char=' ');
96 sizetype Find (char, sizetype=0) const;
97 sizetype Find (cchar *CStr, sizetype Pos=0) const { return Find(CStr, Pos, strlen(CStr)); }
98 sizetype Find (cchar *, sizetype, sizetype) const;
99 sizetype Find (cfestring &S, sizetype Pos=0) const { return Find(S.Data, Pos, S.Size); }
100 sizetype FindLast (char, sizetype=NPos) const;
101 sizetype FindLast (const char *CStr, sizetype Pos=NPos) const { return FindLast(CStr, Pos, strlen(CStr)); }
102 sizetype FindLast (const char *, sizetype, sizetype) const;
103 sizetype FindLast (const festring& S, sizetype Pos=NPos) const { return FindLast(S.Data, Pos, S.Size); }
104 void Erase (sizetype Pos, sizetype Length);
105 void Insert (sizetype Pos, cchar *CStr) { Insert(Pos, CStr, strlen(CStr)); }
106 void Insert (sizetype, cchar *, sizetype);
107 void Insert (sizetype Pos, cfestring& S) { Insert(Pos, S.Data, S.Size); }
108 festring &Append (cfestring &Str, sizetype N) { return Append(Str.Data, N); }
109 static csizetype NPos;
110 static void SplitString (festring &, festring &, sizetype);
111 static int SplitString (cfestring &, std::vector<festring> &, sizetype, sizetype=0);
112 static sizetype IgnoreCaseFind (cfestring &, cfestring &, sizetype=0);
113 static void SearchAndReplace (festring &, cfestring &, cfestring &, sizetype=0);
114 static bool IgnoreCaseCompare (cfestring &, cfestring &);
115 truth IsEmpty() const { return !Size; }
116 /* HORRIBLE ERROR!!!! */
117 char &operator [] (sizetype Index) const { return Data[Index]; }
118 void PreProcessForFebot ();
119 void PostProcessForFebot ();
120 void SwapData (festring &);
121 void ExtractWord (festring &);
122 sLong GetCheckSum () const;
123 void EnsureOwnsData ();
124 private:
125 static void InstallIntegerMap ();
126 static void DeInstallIntegerMap ();
127 void CreateOwnData (cchar *, sizetype);
128 festring &Append (int64_t);
129 festring &Append (sLong);
130 festring &Append (cchar *, sizetype);
131 void SlowAppend (char);
132 void SlowAppend (cchar *, sizetype);
134 static char **IntegerMap;
135 static const char *EmptyString;
136 char *Data;
137 sizetype Size;
138 sizetype OwnsData : 1;
139 sizetype Reserved : 31;
143 class festringpile {
144 public:
145 festringpile (cfestring &String) : String(String) {}
146 template <class type> festringpile &operator + (type What) { String << What; return *this; }
147 festringpile &operator + (cfestring &What) { String << What; return *this; }
148 festringpile &operator + (const festringpile& What) { String << What.String; return *this; }
149 operator festring () const { return String; }
150 private:
151 festring String;
155 template <class type> inline festringpile operator + (cfestring& S, type What) { return festringpile(S)+What; }
156 inline festringpile operator + (cfestring &S, cfestring &What) { return festringpile(S)+What; }
157 inline festringpile operator + (cfestring &S, const festringpile &What) { return festringpile(S)+What; }
160 inline festring::festring (cfestring &Str) :
161 Data(Str.Data), Size(Str.Size), OwnsData(Str.OwnsData), Reserved(Str.Reserved)
163 if (Data && OwnsData) ++REFS(Data);
166 inline festring::festring (sizetype N) : Size(N), OwnsData(true), Reserved(N|FESTRING_PAGE) {
167 char *Ptr = 4+new char[Reserved+5];
168 REFS(Ptr) = 0;
169 Data = Ptr;
173 inline festring::festring (sizetype N, char C) : Size(N), OwnsData(true), Reserved(N|FESTRING_PAGE) {
174 char* Ptr = 4+new char[Reserved+5];
175 REFS(Ptr) = 0;
176 Data = Ptr;
177 memset(Ptr, C, N);
181 inline festring::~festring () {
182 if (OwnsData && Data) {
183 char *Ptr = Data;
184 if (!REFS(Ptr)--) delete [] REFSA(Ptr);
189 inline bool festring::operator < (cfestring &Str) const {
190 sizetype ThisSize = Size;
191 sizetype StrSize = Str.Size;
192 if (ThisSize && StrSize) {
193 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
194 return Comp < 0 || (!Comp && StrSize > ThisSize);
196 return !ThisSize && StrSize;
200 inline bool festring::operator <= (cfestring &Str) const {
201 sizetype ThisSize = Size;
202 sizetype StrSize = Str.Size;
203 if (ThisSize && StrSize) {
204 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
205 return Comp <= 0 || (StrSize > ThisSize);
207 return !ThisSize && StrSize;
211 inline bool festring::operator > (cfestring &Str) const {
212 sizetype ThisSize = Size;
213 sizetype StrSize = Str.Size;
214 if (ThisSize && StrSize) {
215 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
216 return Comp > 0 || (!Comp && ThisSize > StrSize);
218 return !ThisSize && StrSize;
222 inline bool festring::operator >= (cfestring &Str) const {
223 sizetype ThisSize = Size;
224 sizetype StrSize = Str.Size;
225 if (ThisSize && StrSize) {
226 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
227 return Comp >= 0 || (ThisSize > StrSize);
229 return !ThisSize && StrSize;
233 inline truth festring::operator == (cfestring &Str) const {
234 sizetype StrSize = Str.Size;
235 return Size == StrSize && (!StrSize || !memcmp(Data, Str.Data, StrSize));
239 inline truth festring::operator != (cfestring &Str) const {
240 sizetype StrSize = Str.Size;
241 return Size != StrSize || (StrSize && memcmp(Data, Str.Data, StrSize));
245 inline truth festring::operator == (cchar *CStr) const {
246 sizetype StrSize = strlen(CStr);
247 return Size == StrSize && (!StrSize || !memcmp(Data, CStr, StrSize));
251 inline truth festring::operator != (cchar *CStr) const {
252 sizetype StrSize = strlen(CStr);
253 return Size != StrSize || (StrSize && memcmp(Data, CStr, StrSize));
257 /* Returns -1 if this is before Str in alphabetical order, zero
258 if strings are identical, else 1 */
259 inline int festring::Compare (cfestring &Str) const {
260 sizetype ThisSize = Size;
261 sizetype StrSize = Str.Size;
262 if (ThisSize && StrSize) {
263 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
264 if (Comp) return Comp;
266 return ThisSize < StrSize ? -1 : ThisSize != StrSize;
270 inline int festring::CompareIgnoreCase (cfestring &Str) const {
271 sizetype ThisSize = Size;
272 sizetype StrSize = Str.Size;
273 if (ThisSize && StrSize) {
274 for (sizetype Pos = 0; Pos < GetSize(); ++Pos) {
275 char Char1 = toupper(Data[Pos]);
276 char Char2 = toupper(Str[Pos]);
277 if (Char1 != Char2) return Char1-Char2;
279 return 0;
281 return ThisSize < StrSize ? -1 : ThisSize != StrSize;
285 inline cchar *festring::CStr() const {
286 char *Ptr = Data;
287 if (Ptr) {
288 if (OwnsData) Ptr[Size] = 0;
289 return Ptr;
291 return EmptyString;
295 inline void festring::Empty () {
296 Size = 0;
297 if (OwnsData) {
298 char *Ptr = Data;
299 if (Ptr && REFS(Ptr)) {
300 --REFS(Ptr);
301 Data = 0;
303 } else {
304 Data = 0;
309 inline festring &festring::operator << (char Char) {
310 char *OldPtr = Data;
311 sizetype OldSize = Size;
312 if (OwnsData && OldPtr && !REFS(OldPtr) && OldSize < Reserved) {
313 OldPtr[OldSize] = Char;
314 ++Size;
315 } else {
316 SlowAppend(Char);
318 return *this;
322 inline festring &festring::operator << (cchar *CStr) {
323 sizetype N = strlen(CStr);
324 sizetype OldSize = Size;
325 sizetype NewSize = OldSize+N;
326 char *OldPtr = Data;
327 if (OwnsData && OldPtr && !REFS(OldPtr) && NewSize <= Reserved) {
328 if (N > 0) memmove(OldPtr+OldSize, CStr, N);
329 Size = NewSize;
330 } else {
331 SlowAppend(CStr, N);
333 return *this;
337 inline festring &festring::operator << (cfestring &Str) {
338 sizetype N = Str.Size;
339 sizetype OldSize = Size;
340 sizetype NewSize = OldSize+N;
341 char *OldPtr = Data;
342 char *OtherPtr = Str.Data;
343 if (OwnsData && OldPtr && !REFS(OldPtr) && NewSize <= Reserved) {
344 if (N > 0) memmove(OldPtr+OldSize, OtherPtr, N);
345 Size = NewSize;
346 } else {
347 SlowAppend(OtherPtr, N);
349 return *this;
353 struct charcomparer {
354 bool operator () (cchar *const &S1, cchar *const &S2) const { return strcmp(S1, S2) < 0; }
358 struct ignorecaseorderer {
359 bool operator () (cfestring &S1, cfestring &S2) const { return festring::IgnoreCaseCompare(S1, S2); }
363 #define CONST_S(str) festring(str, sizeof(str)-1)
367 * This macro doesn't evaluate with if what
368 * is not found so it's often faster
370 #define SEARCH_N_REPLACE(where, what, with) \
371 if (where.Find(what) != festring::NPos) festring::SearchAndReplace(where, what, with);
374 #endif