more "code scripting" fixes; converted script context to struct
[k8-i-v-a-n.git] / src / felib / festring.h
blobbffd8c047bd34459ca3e8f29eb2a13c632ddd0d5
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 #define LONG_LONG_PFORMAT "%lld"
23 class festring {
24 private:
25 enum { FESTRING_PAGE = 0x7F };
26 public:
27 typedef unsigned int sizetype;
28 typedef const unsigned int csizetype;
29 /* It can be proven that the code works even if OwnsData is left
30 uninitialized. However, Valgrind reports this as a possible error
31 which is annoying */
32 festring () : Data(0), Size(0), Reserved(0), OwnsData(false) {}
33 explicit festring (sizetype);
34 festring (sizetype, char);
35 festring (cchar *CStr) : Data(const_cast<char *>(CStr)), Size(CStr ? strlen(CStr) : 0), Reserved(0), OwnsData(false) {}
37 if (Size > 0x7ffff000) ABORT("String too big (or invalid)");
38 Reserved = Size|FESTRING_PAGE;
39 char *Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
40 REFS(Ptr) = 0;
41 Data = Ptr;
42 if (Size > 0) memmove(Data, CStr, N);
45 festring (cchar *CStr, sizetype N) : Data(const_cast<char *>(CStr)), Size(N), Reserved(0), OwnsData(false) {
46 //if (N > 0x7ffff000) ABORT("String too big (or invalid)");
47 if (N == 0) { Data = 0; return; }
48 sizetype slen = (CStr ? (sizetype)strlen(CStr) : 0);
49 if (slen != N) {
50 if (slen > N) slen = N;
51 Reserved = N|FESTRING_PAGE;
52 char *Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
53 REFS(Ptr) = 0;
54 Data = Ptr;
55 memset(Data, 0, N);
56 if (slen) memcpy(Data, CStr, slen);
57 OwnsData = true;
60 festring (cfestring &);
61 ~festring ();
62 festring &Capitalize ();
63 festring CapitalizeCopy () const { return festring(*this).Capitalize(); }
64 festring &operator = (cchar *);
65 festring &operator = (cfestring &);
66 festring &operator << (char);
67 festring &operator << (cchar *);
68 festring &operator << (cfestring &);
69 festring &operator << (short Int) { return Append(Int); }
70 festring &operator << (uShort Int) { return Append(Int); }
71 festring &operator << (int Int) { return Append(Int); }
72 festring &operator << (uInt Int) { return Append((int)Int); } //k8:64
73 festring &operator += (char);
74 festring &operator += (cchar *);
75 festring &operator += (cfestring &);
76 //festring &operator << (sLong Int) { return Append(Int); } //k8:64
77 //festring &operator << (feuLong Int) { return Append(Int); } //k8:64
78 festring &operator << (time_t Int) { return Append((int64_t)Int); } //k8:64
79 bool operator < (cfestring &) const;
80 bool operator <= (cfestring &) const;
81 bool operator > (cfestring &) const;
82 bool operator >= (cfestring &) const;
83 truth operator == (cfestring &) const;
84 truth operator != (cfestring &) const;
85 truth operator == (cchar*) const;
86 truth operator != (cchar*) const;
87 int Compare (cfestring &) const;
88 int CompareIgnoreCase (cfestring &) const;
89 int Compare (cchar *) const;
90 int CompareIgnoreCase (cchar *) 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 Pos, cchar *CStr, sizetype N);
107 void Insert (sizetype Pos, cfestring& S) { Insert(Pos, S.Data, S.Size); }
108 void Insert (sizetype Pos, char ch) { Insert(Pos, &ch, 1); }
109 festring &Append (cfestring &Str, sizetype N) { return Append(Str.Data, N); }
111 truth startsWith (cchar *str, int slen=-1) const;
112 truth endsWith (cchar *str, int slen=-1) const;
113 truth startsWithCI (cchar *str, int slen=-1) const;
114 truth endsWithCI (cchar *str, int slen=-1) const;
116 truth startsWith (cfestring &str) const;
117 truth endsWith (cfestring &str) const;
118 truth startsWithCI (cfestring &str) const;
119 truth endsWithCI (cfestring &str) const;
121 static csizetype NPos;
122 static void SplitString (festring &, festring &, sizetype);
123 static void SplitStringColored (festring &, festring &, sizetype);
124 static int SplitString (cfestring &, std::vector<festring> &, sizetype, sizetype=0);
125 static int SplitStringColored (cfestring &, std::vector<festring> &, sizetype, sizetype=0);
126 static sizetype IgnoreCaseFind (cfestring &, cfestring &, sizetype=0);
127 static void SearchAndReplace (festring &, cfestring &, cfestring &, sizetype=0);
128 static bool IgnoreCaseCompare (cfestring &, cfestring &);
129 truth IsEmpty () const { return (Size == 0); }
130 /* HORRIBLE ERROR!!!! */
131 char &operator [] (sizetype Index) const { return Data[Index]; }
132 void SwapData (festring &);
133 sLong GetCheckSum () const;
134 void ensureUniqueOwned (bool allocEmpty=false);
136 truth hasCtlCodes () const;
137 sizetype rawLength () const; // without color codes
139 private:
140 static void InstallIntegerMap ();
141 static void DeInstallIntegerMap ();
142 void CreateOwnData (cchar *, sizetype);
143 festring &Append (int64_t);
144 festring &Append (sLong);
145 festring &Append (cchar *, sizetype);
146 void SlowAppend (char);
147 void SlowAppend (cchar *, sizetype);
149 private:
150 static char **IntegerMap;
151 static const char *EmptyString;
152 char *Data;
153 sizetype Size;
154 sizetype Reserved;
155 bool OwnsData;
159 class festringpile {
160 public:
161 festringpile (cfestring &String) : String(String) {}
162 template <class type> festringpile &operator + (type What) { String << What; return *this; }
163 festringpile &operator + (cfestring &What) { String << What; return *this; }
164 festringpile &operator + (const festringpile& What) { String << What.String; return *this; }
165 operator festring () const { return String; }
166 private:
167 festring String;
171 template <class type> inline festringpile operator + (cfestring& S, type What) { return festringpile(S)+What; }
172 inline festringpile operator + (cfestring &S, cfestring &What) { return festringpile(S)+What; }
173 inline festringpile operator + (cfestring &S, const festringpile &What) { return festringpile(S)+What; }
176 inline festring::festring (cfestring &Str) :
177 Data(Str.Data), Size(Str.Size), Reserved(Str.Reserved), OwnsData(Str.OwnsData)
179 if (Data && OwnsData) ++REFS(Data);
182 inline festring::festring (sizetype N) : Size(N), Reserved(N|FESTRING_PAGE), OwnsData(true) {
183 //if (N > 0x7ffff000) ABORT("String too big (or invalid)");
184 char *Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
185 REFS(Ptr) = 0;
186 Data = Ptr;
190 inline festring::festring (sizetype N, char C) : Size(N), Reserved(N|FESTRING_PAGE), OwnsData(true) {
191 //if (N > 0x7ffff000) ABORT("String too big (or invalid)");
192 char* Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
193 REFS(Ptr) = 0;
194 Data = Ptr;
195 if (N > 0) memset(Ptr, C, N);
199 inline festring::~festring () {
200 if (OwnsData && Data) {
201 char *Ptr = Data;
202 if (!REFS(Ptr)--) delete [] REFSA(Ptr);
204 Data = 0;
205 Size = 0;
206 Reserved = 0;
207 OwnsData = false;
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 && StrSize > ThisSize);
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 || (StrSize > ThisSize);
229 return !ThisSize && StrSize;
233 inline bool festring::operator > (cfestring &Str) const {
234 sizetype ThisSize = Size;
235 sizetype StrSize = Str.Size;
236 if (ThisSize && StrSize) {
237 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
238 return Comp > 0 || (!Comp && ThisSize > StrSize);
240 return !ThisSize && StrSize;
244 inline bool festring::operator >= (cfestring &Str) const {
245 sizetype ThisSize = Size;
246 sizetype StrSize = Str.Size;
247 if (ThisSize && StrSize) {
248 int Comp = memcmp(Data, Str.Data, StrSize > ThisSize ? ThisSize : StrSize);
249 return Comp >= 0 || (ThisSize > StrSize);
251 return !ThisSize && StrSize;
255 inline truth festring::operator == (cfestring &Str) const {
256 sizetype StrSize = Str.Size;
257 return Size == StrSize && (!StrSize || !memcmp(Data, Str.Data, StrSize));
261 inline truth festring::operator != (cfestring &Str) const {
262 sizetype StrSize = Str.Size;
263 return Size != StrSize || (StrSize && memcmp(Data, Str.Data, StrSize));
267 inline truth festring::operator == (cchar *CStr) const {
268 sizetype StrSize = strlen(CStr);
269 return Size == StrSize && (!StrSize || !memcmp(Data, CStr, StrSize));
273 inline truth festring::operator != (cchar *CStr) const {
274 sizetype StrSize = strlen(CStr);
275 return Size != StrSize || (StrSize && memcmp(Data, CStr, StrSize));
279 /* Returns -1 if this is before Str in alphabetical order, zero
280 if strings are identical, else 1 */
281 inline int festring::Compare (cfestring &Str) const {
282 sizetype ThisSize = Size;
283 sizetype StrSize = Str.Size;
284 if (ThisSize && StrSize) {
285 int Comp = memcmp(Data, Str.Data, (StrSize > ThisSize ? ThisSize : StrSize));
286 if (Comp) return Comp;
288 return (ThisSize < StrSize ? -1 : ThisSize != StrSize);
292 inline int festring::CompareIgnoreCase (cfestring &Str) const {
293 sizetype ThisSize = Size;
294 sizetype StrSize = Str.Size;
295 if (ThisSize && StrSize) {
296 for (sizetype Pos = 0; Pos < GetSize(); ++Pos) {
297 char Char1 = toupper(Data[Pos]);
298 char Char2 = toupper(Str[Pos]);
299 if (Char1 != Char2) return (Char1 < Char2 ? -1 : 1);
301 return 0;
303 return (ThisSize < StrSize ? -1 : ThisSize != StrSize);
307 inline int festring::Compare (cchar *str) const {
308 sizetype ThisSize = Size;
309 sizetype StrSize = (sizetype)(str ? strlen(str) : 0);
310 if (ThisSize && StrSize) {
311 int Comp = memcmp(Data, str, (StrSize > ThisSize ? ThisSize : StrSize));
312 if (Comp) return Comp;
314 return (ThisSize < StrSize ? -1 : ThisSize != StrSize);
318 inline int festring::CompareIgnoreCase (cchar *str) const {
319 sizetype ThisSize = Size;
320 sizetype StrSize = (sizetype)(str ? strlen(str) : 0);
321 if (ThisSize && StrSize) {
322 for (sizetype Pos = 0; Pos < GetSize(); ++Pos) {
323 char Char1 = toupper(Data[Pos]);
324 char Char2 = toupper(str[Pos]);
325 if (Char1 != Char2) return (Char1 < Char2 ? -1 : 1);
327 return 0;
329 return (ThisSize < StrSize ? -1 : ThisSize != StrSize);
333 inline cchar *festring::CStr () const {
334 char *Ptr = Data;
335 if (Ptr) {
336 if (OwnsData) {
337 // need to copy?
338 //if (REFS(Ptr) && Ptr[Size]) { ensureUniqueOwned(); Ptr = Data; }
339 Ptr[Size] = 0;
341 return Ptr;
343 return EmptyString;
347 inline void festring::Empty () {
348 if (OwnsData) {
349 char *Ptr = Data;
350 if (Ptr && REFS(Ptr)) {
351 if (!REFS(Ptr)--) delete [] REFSA(Ptr);
354 Data = 0;
355 Size = 0;
356 Reserved = 0;
357 OwnsData = false;
361 inline festring &festring::operator << (char Char) {
362 char *OldPtr = Data;
363 sizetype OldSize = Size;
364 if (OwnsData && OldPtr && !REFS(OldPtr) && OldSize < Reserved) {
365 OldPtr[OldSize] = Char;
366 ++Size;
367 } else {
368 SlowAppend(Char);
370 return *this;
374 inline festring &festring::operator << (cchar *CStr) {
375 sizetype N = (CStr ? strlen(CStr) : 0);
376 if (N == 0) return *this;
377 sizetype OldSize = Size;
378 sizetype NewSize = OldSize+N;
379 //if (N > 0x7ffff000) ABORT("String too big (or invalid)");
380 char *OldPtr = Data;
381 if (OwnsData && OldPtr && !REFS(OldPtr) && NewSize <= Reserved) {
382 if (N > 0) memmove(OldPtr+OldSize, CStr, N);
383 Size = NewSize;
384 } else {
385 SlowAppend(CStr, N);
387 return *this;
391 inline festring &festring::operator << (cfestring &Str) {
392 sizetype N = Str.Size;
393 if (N == 0) return *this;
394 sizetype OldSize = Size;
395 sizetype NewSize = OldSize+N;
396 char *OldPtr = Data;
397 char *OtherPtr = Str.Data;
398 if (OwnsData && OldPtr && !REFS(OldPtr) && NewSize <= Reserved) {
399 if (N > 0) memmove(OldPtr+OldSize, OtherPtr, N);
400 Size = NewSize;
401 } else {
402 SlowAppend(OtherPtr, N);
404 return *this;
408 inline festring &festring::operator += (char Char) { return *this << Char; }
409 inline festring &festring::operator += (cchar *CStr) { return *this << CStr; }
410 inline festring &festring::operator += (cfestring &Str) { return *this << Str; }
413 struct charcomparer {
414 bool operator () (cchar *const &S1, cchar *const &S2) const { return strcmp(S1, S2) < 0; }
418 struct ignorecaseorderer {
419 bool operator () (cfestring &S1, cfestring &S2) const { return festring::IgnoreCaseCompare(S1, S2); }
423 //#define CONST_S(str) festring(str, sizeof(str)-1)
424 #define CONST_S(str) festring(str)
428 * This macro doesn't evaluate with if what
429 * is not found so it's often faster
431 #define SEARCH_N_REPLACE(where, what, with) \
432 if (where.Find(what) != festring::NPos) festring::SearchAndReplace(where, what, with);
435 #endif