3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
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__
21 #define LONG_LONG_PFORMAT "%lld"
25 enum { FESTRING_PAGE
= 0x7F };
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
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];
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);
50 if (slen
> N
) slen
= N
;
51 Reserved
= N
|FESTRING_PAGE
;
52 char *Ptr
= sizeof(rcint
)+new char[Reserved
+sizeof(rcint
)+1];
56 if (slen
) memcpy(Data
, CStr
, slen
);
60 festring (cfestring
&);
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;
92 sizetype
GetSize () const { return Size
; }
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
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
);
150 static char **IntegerMap
;
151 static const char *EmptyString
;
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
; }
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];
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];
195 if (N
> 0) memset(Ptr
, C
, N
);
199 inline festring::~festring () {
200 if (OwnsData
&& Data
) {
202 if (!REFS(Ptr
)--) delete [] REFSA(Ptr
);
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);
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);
329 return (ThisSize
< StrSize
? -1 : ThisSize
!= StrSize
);
333 inline cchar
*festring::CStr () const {
338 //if (REFS(Ptr) && Ptr[Size]) { ensureUniqueOwned(); Ptr = Data; }
347 inline void festring::Empty () {
350 if (Ptr
&& REFS(Ptr
)) {
351 if (!REFS(Ptr
)--) delete [] REFSA(Ptr
);
361 inline festring
&festring::operator << (char Char
) {
363 sizetype OldSize
= Size
;
364 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && OldSize
< Reserved
) {
365 OldPtr
[OldSize
] = Char
;
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)");
381 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && NewSize
<= Reserved
) {
382 if (N
> 0) memmove(OldPtr
+OldSize
, CStr
, N
);
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
;
397 char *OtherPtr
= Str
.Data
;
398 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && NewSize
<= Reserved
) {
399 if (N
> 0) memmove(OldPtr
+OldSize
, OtherPtr
, N
);
402 SlowAppend(OtherPtr
, N
);
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);