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__
22 # define LONG_LONG_PFORMAT "%lld"
24 # define LONG_LONG_PFORMAT "%I64d"
27 #define FESTRING_PAGE 0x7F
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
36 festring () : Data(0), Size(0), OwnsData(false), Reserved(0) {}
37 explicit festring (sizetype
);
38 festring (sizetype
, char);
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];
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];
58 if (s
) memmove(Data
, s
, N
); else memset(Data
, 0, N
);
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) {}
65 festring (cfestring
&);
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;
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
, 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 ();
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
;
138 sizetype OwnsData
: 1;
139 sizetype Reserved
: 31;
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
; }
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];
173 inline festring::festring (sizetype N
, char C
) : Size(N
), OwnsData(true), Reserved(N
|FESTRING_PAGE
) {
174 char* Ptr
= 4+new char[Reserved
+5];
181 inline festring::~festring () {
182 if (OwnsData
&& 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
;
281 return ThisSize
< StrSize
? -1 : ThisSize
!= StrSize
;
285 inline cchar
*festring::CStr() const {
288 if (OwnsData
) Ptr
[Size
] = 0;
295 inline void festring::Empty () {
299 if (Ptr
&& REFS(Ptr
)) {
309 inline festring
&festring::operator << (char Char
) {
311 sizetype OldSize
= Size
;
312 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && OldSize
< Reserved
) {
313 OldPtr
[OldSize
] = Char
;
322 inline festring
&festring::operator << (cchar
*CStr
) {
323 sizetype N
= strlen(CStr
);
324 sizetype OldSize
= Size
;
325 sizetype NewSize
= OldSize
+N
;
327 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && NewSize
<= Reserved
) {
328 if (N
> 0) memmove(OldPtr
+OldSize
, CStr
, N
);
337 inline festring
&festring::operator << (cfestring
&Str
) {
338 sizetype N
= Str
.Size
;
339 sizetype OldSize
= Size
;
340 sizetype NewSize
= OldSize
+N
;
342 char *OtherPtr
= Str
.Data
;
343 if (OwnsData
&& OldPtr
&& !REFS(OldPtr
) && NewSize
<= Reserved
) {
344 if (N
> 0) memmove(OldPtr
+OldSize
, OtherPtr
, N
);
347 SlowAppend(OtherPtr
, N
);
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);