moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / felib / festring.cpp
blob0d7e09610a22c0bcbb145afe93a7b78a4fb0322f
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 #include <cctype>
13 #include <cstdlib>
14 #include <cstdio>
16 #include "festring.h"
17 #include "allocate.h"
18 #include "feerror.h"
21 char **festring::IntegerMap = 0;
22 const char *festring::EmptyString = "";
23 festring::csizetype festring::NPos = festring::sizetype(-1);
26 void festring::CreateOwnData (cchar *CStr, sizetype N) {
27 Size = N;
28 Reserved = N|FESTRING_PAGE;
29 char *Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
30 REFS(Ptr) = 0;
31 Data = Ptr;
32 if (N > 0 && CStr) memmove(Ptr, CStr, N);
33 OwnsData = true;
37 void festring::ensureUniqueOwned (bool allocEmpty) {
38 if (!OwnsData) {
39 if (Size == 0 && !allocEmpty) Empty(); else CreateOwnData(Data, Size);
40 return;
42 if (Size == 0 && !allocEmpty) { Empty(); return; }
43 char *Ptr = Data;
44 if (REFS(Ptr)) {
45 --REFS(Ptr);
46 CreateOwnData(Ptr, Size);
51 festring &festring::Append (cchar *CStr, sizetype N) {
52 sizetype OldSize = Size;
53 sizetype NewSize = OldSize+N;
54 char *OldPtr = Data;
55 if (OwnsData && OldPtr && !REFS(OldPtr) && NewSize <= Reserved) {
56 if (N > 0) memmove(OldPtr+OldSize, CStr, N);
57 Size = NewSize;
58 } else {
59 SlowAppend(CStr, N);
61 return *this;
65 festring &festring::operator = (cchar *CStr) {
66 sizetype NewSize = (CStr ? strlen(CStr) : 0);
67 if (NewSize > 0x7ffff000) ABORT("String too big (or invalid)");
68 if (NewSize == 0) { Empty(); return *this; }
69 Size = NewSize;
70 char *Ptr = Data;
71 if (Ptr && OwnsData) {
72 if (!REFS(Ptr) && NewSize <= Reserved) {
73 if (NewSize > 0) memmove(Ptr, CStr, NewSize);
74 return *this;
76 if (!REFS(Ptr)--) delete [] REFSA(Ptr);
78 Data = const_cast<char *>(CStr);
79 OwnsData = false;
80 return *this;
84 festring &festring::operator = (cfestring &Str) {
85 sizetype NewSize = Str.Size;
86 if (NewSize == 0) { Empty(); return *this; }
87 Size = NewSize;
88 char *Ptr = Data;
89 char *StrPtr = Str.Data;
90 if (Ptr && OwnsData) {
91 if (!REFS(Ptr) && NewSize <= Reserved) {
92 if (StrPtr && NewSize > 0) memmove(Ptr, StrPtr, NewSize);
93 return *this;
95 if (!REFS(Ptr)--) delete [] REFSA(Ptr);
97 if ((Data = StrPtr) && (OwnsData = Str.OwnsData)) {
98 ++REFS(StrPtr);
99 Reserved = Str.Reserved;
101 return *this;
105 /* Size must be > 0 */
106 festring &festring::Capitalize () {
107 if (Size > 0 && *Data >= 'a' && *Data <= 'z') {
108 ensureUniqueOwned();
109 *Data -= 0x20;
111 return *this;
115 void festring::SlowAppend (char Char) {
116 char *OldPtr = Data;
117 if (OldPtr) {
118 sizetype OldSize = Size++;
119 int *DeletePtr = 0;
120 if (OwnsData && !REFS(OldPtr)--) DeletePtr = REFSA(OldPtr);
121 Reserved = (OldSize+1)|FESTRING_PAGE;
122 char *NewPtr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
123 REFS(NewPtr) = 0;
124 Data = NewPtr;
125 if (OldSize > 0) memmove(NewPtr, OldPtr, OldSize);
126 NewPtr[OldSize] = Char;
127 if (DeletePtr) delete [] DeletePtr;
128 } else {
129 Size = 1;
130 Reserved = FESTRING_PAGE;
131 char *Ptr = sizeof(rcint)+new char[FESTRING_PAGE+sizeof(rcint)+1];
132 REFS(Ptr) = 0;
133 Ptr[0] = Char;
134 Data = Ptr;
136 OwnsData = true;
140 void festring::SlowAppend (cchar *CStr, sizetype N) {
141 if (N == 0) return;
142 char *OldPtr = Data;
143 if (OldPtr) {
144 sizetype OldSize = Size;
145 sizetype NewSize = OldSize+N;
146 Size = NewSize;
147 int *DeletePtr = 0;
148 if (OwnsData && !REFS(OldPtr)--) DeletePtr = REFSA(OldPtr);
149 Reserved = NewSize|FESTRING_PAGE;
150 char *NewPtr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
151 REFS(NewPtr) = 0;
152 Data = NewPtr;
153 if (OldSize > 0) memmove(NewPtr, OldPtr, OldSize);
154 if (N > 0) memmove(NewPtr+OldSize, CStr, N);
155 OwnsData = true;
156 if (DeletePtr) delete [] DeletePtr;
157 } else {
158 CreateOwnData(CStr, N);
163 void festring::Assign (sizetype N, char C) {
164 if (N == 0) { Empty(); return; }
165 Size = N;
166 char *Ptr = Data;
167 if (OwnsData && Ptr) {
168 if (REFS(Ptr)) {
169 --REFS(Ptr);
170 } else {
171 if (N <= Reserved) {
172 memset(Ptr, C, N);
173 return;
175 delete [] REFSA(Ptr);
178 Reserved = N|FESTRING_PAGE;
179 Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
180 REFS(Ptr) = 0;
181 Data = Ptr;
182 if (N > 0) memset(Ptr, C, N);
183 OwnsData = true;
187 void festring::Resize (sizetype N, char C) {
188 if (N == 0) { Empty(); return; }
189 sizetype OldSize = Size;
190 char *OldPtr = Data;
191 char *NewPtr;
192 Size = N;
193 if (OldSize < N) {
194 int *DeletePtr = 0;
195 if (OwnsData && OldPtr) {
196 if (!REFS(OldPtr)) {
197 if (N <= Reserved) {
198 memset(OldPtr+OldSize, C, N-OldSize);
199 return;
201 DeletePtr = REFSA(OldPtr);
202 } else {
203 --REFS(OldPtr);
206 Reserved = N|FESTRING_PAGE;
207 NewPtr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
208 REFS(NewPtr) = 0;
209 Data = NewPtr;
210 if (OldSize > 0) memmove(NewPtr, OldPtr, OldSize);
211 if (N > OldSize) memset(NewPtr+OldSize, C, N-OldSize);
212 OwnsData = true;
213 if (DeletePtr) delete [] DeletePtr;
214 } else {
215 if (OwnsData && OldPtr) {
216 if (!REFS(OldPtr)) return;
217 --REFS(OldPtr);
219 Reserved = N|FESTRING_PAGE;
220 NewPtr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
221 REFS(NewPtr) = 0;
222 Data = NewPtr;
223 if (N > 0) memmove(NewPtr, OldPtr, N);
224 OwnsData = true;
229 festring::sizetype festring::Find (char Char, sizetype Pos) const {
230 char *Ptr = Data;
231 if (Ptr) {
232 char *Result = static_cast<char *>(memchr(Ptr+Pos, Char, Size-Pos));
233 if (Result) return Result-Ptr;
235 return NPos;
239 festring::sizetype festring::Find (cchar *CStr, sizetype Pos, sizetype N) const {
240 if (N && Pos < Size) {
241 char *Ptr = Data;
242 if (Ptr) {
243 char Char = CStr[0];
244 while (Size-Pos >= N) {
245 if (Size-Pos < N) return NPos;
246 char *Result = static_cast<char *>(memchr(Ptr+Pos, Char, Size-Pos));
247 if (!Result) return NPos;
248 if (!memcmp(Result, CStr, N)) return Result-Ptr;
249 Pos = Result-Ptr+1;
253 return NPos;
257 festring::sizetype festring::FindLast (char Char, sizetype Pos) const {
258 char *Ptr = Data;
259 if (Ptr) {
260 if (Pos >= Size) Pos = Size-1;
261 sizetype c;
262 for (c = Pos; c != NPos && Ptr[c] != Char; --c);
263 return c;
265 return NPos;
269 festring::sizetype festring::FindLast (const char *CStr, sizetype Pos, sizetype N) const {
270 if (N) {
271 char *Ptr = Data;
272 if (Ptr && Size >= N) {
273 char Char = CStr[0];
274 if (Pos > Size-N) Pos = Size-N;
275 for (sizetype c = Pos; c != NPos; --c) if (Ptr[c] == Char && !memcmp(Ptr+c, CStr, N)) return c;
276 return NPos;
279 return NPos;
283 void festring::Erase (sizetype Pos, sizetype Length) {
284 if (Pos >= Size) return;
285 if (Length >= Size && Pos == 0) { Empty(); return; }
286 char *OldPtr = Data;
287 if (OldPtr && Length) {
288 sizetype OldSize = Size;
289 if (Pos < OldSize) {
290 truth MoveReq = (Length < OldSize-Pos);
291 if (OwnsData) {
292 if (!REFS(OldPtr)) {
293 if (MoveReq) {
294 sizetype End = Pos+Length;
295 memmove(OldPtr+Pos, OldPtr+End, OldSize-End);
297 Size -= Length;
298 return;
299 } else {
300 --REFS(OldPtr);
303 sizetype NewSize = (MoveReq ? OldSize-Length : Pos);
304 Size = NewSize;
305 Reserved = NewSize|FESTRING_PAGE;
306 char *Ptr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
307 REFS(Ptr) = 0;
308 Data = Ptr;
309 OwnsData = true;
310 if (Pos > 0) memmove(Ptr, OldPtr, Pos);
311 if (MoveReq) {
312 sizetype End = Pos+Length;
313 if (OldSize > End) memmove(Ptr+Pos, OldPtr+End, OldSize-End);
320 void festring::Insert (sizetype Pos, cchar *CStr, sizetype N) {
321 if (N) {
322 sizetype OldSize = Size;
323 if (Pos < OldSize) {
324 // this implies Data != 0
325 char *OldPtr = Data;
326 int *DeletePtr = 0;
327 sizetype NewSize = OldSize+N;
328 Size = NewSize;
329 if (OwnsData) {
330 if (!REFS(OldPtr)) {
331 if (NewSize <= Reserved) {
332 char *Ptr = OldPtr+Pos;
333 memmove(Ptr+N, Ptr, OldSize-Pos);
334 if (N > 0) memmove(Ptr, CStr, N);
335 return;
336 } else {
337 DeletePtr = REFSA(OldPtr);
339 } else {
340 --REFS(OldPtr);
343 Reserved = NewSize|FESTRING_PAGE;
344 char* NewPtr = sizeof(rcint)+new char[Reserved+sizeof(rcint)+1];
345 REFS(NewPtr) = 0;
346 Data = NewPtr;
347 if (Pos > 0) memmove(NewPtr, OldPtr, Pos);
348 if (N > 0) memmove(NewPtr+Pos, CStr, N);
349 if (OldSize > Pos) memmove(NewPtr+Pos+N, OldPtr+Pos, OldSize-Pos);
350 OwnsData = true;
351 if (DeletePtr) delete [] DeletePtr;
352 } else if (Pos == OldSize) {
353 Append(CStr, N);
354 } else {
355 ABORT("Illegal festring insertion detected!");
361 /* Creates map of char representations of numbers 0-999 used by
362 * festring::Append(sLong). Due to automatization, you don't need
363 * to explicitly call it. */
364 void festring::InstallIntegerMap () {
365 Alloc2D(IntegerMap, 1000, 3);
366 char Ones = '0', Tens = '0', Hundreds = '0';
367 for (int c = 0; c < 1000; ++c) {
368 IntegerMap[c][0] = Hundreds;
369 IntegerMap[c][1] = Tens;
370 IntegerMap[c][2] = Ones;
371 if (++Ones > '9') {
372 Ones = '0';
373 if (++Tens > '9') {
374 Tens = '0';
375 ++Hundreds;
379 atexit(DeInstallIntegerMap);
383 /* Deletes the integer map used by festring::Append(sLong).
384 * Due to automatization, you don't need to explicitly call it. */
385 void festring::DeInstallIntegerMap () {
386 delete [] IntegerMap;
387 IntegerMap = 0;
391 /* Displays numbers in the range [-2147483647, 2147483647].
392 * Much faster than sprintf and (nonstandard) itoa. */
393 festring &festring::Append (sLong Integer) {
394 if (!IntegerMap) InstallIntegerMap();
395 char IntegerBuffer[12];
396 char *BufferPtr = IntegerBuffer;
397 truth Negative = false;
398 if (Integer < 0) {
399 if (Integer < -2147483647) return Append("-Inf", 4);
400 *BufferPtr++ = '0';
401 Integer = -Integer;
402 Negative = true;
403 } else if (Integer > 2147483647) return Append("Inf", 3);
404 truth ForceZeros = false;
405 if (Integer >= 2000000000) {
406 *BufferPtr++ = '2';
407 Integer -= 2000000000;
408 ForceZeros = true;
409 } else if (Integer >= 1000000000) {
410 *BufferPtr++ = '1';
411 Integer -= 1000000000;
412 ForceZeros = true;
414 if (ForceZeros || Integer >= 1000000) {
415 int Temp = Integer/1000000;
416 *BufferPtr++ = IntegerMap[Temp][0];
417 *BufferPtr++ = IntegerMap[Temp][1];
418 *BufferPtr++ = IntegerMap[Temp][2];
419 Integer -= Temp*1000000;
420 ForceZeros = true;
422 if (ForceZeros || Integer >= 1000) {
423 int Temp = Integer/1000;
424 *BufferPtr++ = IntegerMap[Temp][0];
425 *BufferPtr++ = IntegerMap[Temp][1];
426 *BufferPtr++ = IntegerMap[Temp][2];
427 Integer -= Temp*1000;
429 *BufferPtr++ = IntegerMap[Integer][0];
430 *BufferPtr++ = IntegerMap[Integer][1];
431 *BufferPtr++ = IntegerMap[Integer][2];
432 *BufferPtr = 0;
433 char *EndPtr = BufferPtr;
434 for (BufferPtr = IntegerBuffer; *BufferPtr == '0'; ++BufferPtr);
435 if (Negative) *--BufferPtr = '-';
436 else if (!*BufferPtr) --BufferPtr; // check if the original Integer was zero
437 return Append(BufferPtr, EndPtr-BufferPtr);
441 festring &festring::Append (int64_t Integer) {
442 char buf[256];
443 auto len = snprintf(buf, sizeof(buf)-1, LONG_LONG_PFORMAT, Integer);
444 return Append(buf, len);
448 /* The Result string receives up to Length characters from source,
449 * but words are left uncut if possible. */
450 void festring::SplitString (festring &Source, festring &Result, sizetype Length) {
452 if (Source.GetSize() <= Length) {
453 Result << Source;
454 Source.Empty();
455 return;
457 sizetype Pos = Source.FindLast(' ', Length);
458 if (Pos != NPos) {
459 Result.Append(Source, Pos);
460 Source.Erase(0, Pos+1);
461 } else {
462 Result.Append(Source, Length);
463 Source.Erase(0, Length);
466 SplitStringColored(Source, Result, Length);
470 /* The Result string receives up to Length characters from source,
471 * but words are left uncut if possible. */
472 void festring::SplitStringColored (festring &Source, festring &Result, sizetype Length) {
473 if (Source.GetSize() <= Length || Length < 1) {
474 Result << Source;
475 Source.Empty();
476 return;
479 char clrchar = 0;
480 sizetype len = 0; // collected
482 // add words
483 while (Source.Size > 0) {
484 cchar *s = Source.Data;
485 sizetype left = Source.Size;
486 sizetype wordlen = 0;
488 // skip leading spaces
489 while (left > 0) {
490 if (*s == '\1') { ++s; --left; if (left) { clrchar = *s++; --left; } continue; }
491 if (*s == '\2') { clrchar = 0; ++s; --left; continue; }
492 if (*s != ' ') break;
493 ++s;
494 --left;
495 ++wordlen;
498 // find word end
499 while (left > 0 && *s != ' ') {
500 if (*s == '\1') { ++s; --left; if (left) { clrchar = *s++; --left; } continue; }
501 if (*s == '\2') { clrchar = 0; ++s; --left; continue; }
502 ++wordlen;
503 ++s;
504 --left;
507 sizetype cplen = (sizetype)(s-Source.Data);
509 if (len == 0 && wordlen > Length) {
510 // oops, first word is too long, do it specially
511 cchar *s = Source.Data;
512 sizetype left = Source.Size;
513 // append chars up to `Length`
514 wordlen = 0;
515 while (left > 0) {
516 if (*s == '\1') { ++s; --left; if (left) { clrchar = *s++; --left; } continue; }
517 if (*s == '\2') { clrchar = 0; ++s; --left; if (wordlen == Length) break; continue; }
518 if (wordlen == Length) break;
519 ++wordlen;
520 ++s;
521 --left;
523 cplen = (sizetype)(s-Source.Data);
524 Result.Append(Source.Data, cplen);
525 Source.Erase(0, cplen);
526 // insert color code
527 if (clrchar != 0) { char ccbuf[2]; ccbuf[0] = '\1'; ccbuf[1] = clrchar; Source.Insert(0, ccbuf, 2); }
528 return;
531 // fits?
532 if (len == 0 || len+wordlen <= Length) {
533 // yes, append it
534 Result.Append(Source.Data, cplen);
535 len += wordlen;
536 // erase appended part
537 Source.Erase(0, cplen);
538 continue;
541 // can't append; remove leading space (if any)
542 if (Source.Size > 0 && *Source.Data == ' ') Source.Erase(0, 1);
543 // insert color code
544 if (clrchar != 0) { char ccbuf[2]; ccbuf[0] = '\1'; ccbuf[1] = clrchar; Source.Insert(0, ccbuf, 2); }
545 return;
548 // clear `Source`
549 if (Source.Size > 0) Source.Erase(0, Source.Size);
553 /* Divides Source into lines of size up to Length without cutting words
554 * and stores them one by one to StringVector. You can also specify a
555 * Marginal, in which case a number of spaces is inserted in the
556 * beginning of each line except the first. It returns the number of
557 * created lines. */
558 int festring::SplitString (cfestring &Source, std::vector<festring> &StringVector, sizetype Length, sizetype Marginal) {
560 if (!Length) ABORT("Illegal Length 0 passed to festring::SplitString()!");
561 if (Marginal >= Length) ABORT("Illegal festring::SplitString() call: Marginal must be less than Length!");
562 festring CopyOfSource(Source);
563 if (StringVector.empty()) StringVector.push_back(festring()); else StringVector[0].Empty();
564 SplitString(CopyOfSource, StringVector[0], Length);
565 sizetype Size = 1;
566 while (!CopyOfSource.IsEmpty()) {
567 if (StringVector.size() <= Size) StringVector.push_back(festring());
568 festring &String = StringVector[Size++];
569 String.Assign(Marginal, ' ');
570 SplitString(CopyOfSource, String, Length-Marginal);
572 return Size;
574 return SplitStringColored(Source, StringVector, Length, Marginal);
578 int festring::SplitStringColored (cfestring &Source, std::vector<festring> &StringVector, sizetype Length, sizetype Marginal) {
579 if (!Length) ABORT("Illegal Length 0 passed to festring::SplitStringColored()!");
580 if (Marginal >= Length) ABORT("Illegal festring::SplitStringColored() call: Marginal must be less than Length!");
581 festring CopyOfSource(Source);
582 if (StringVector.empty()) StringVector.push_back(festring()); else StringVector[0].Empty();
583 SplitStringColored(CopyOfSource, StringVector[0], Length);
584 sizetype Size = 1;
585 while (!CopyOfSource.IsEmpty()) {
586 if (StringVector.size() <= Size) StringVector.push_back(festring());
587 festring &String = StringVector[Size++];
588 String.Assign(Marginal, ' ');
589 SplitStringColored(CopyOfSource, String, Length-Marginal);
591 return Size;
595 truth festring::hasCtlCodes () const {
596 cchar *str = Data;
597 for (sizetype c = Size; c > 0; --c, ++str) {
598 if (*str == '\1' || *str == '\2') return true;
600 return false;
604 // without color codes
605 festring::sizetype festring::rawLength () const {
606 sizetype len = 0;
607 cchar *str = Data;
608 for (sizetype c = Size; c > 0; --c, ++str) {
609 switch (*str) {
610 case '\1': if (c > 1) { ++str; --c; } break;
611 case '\2': break;
612 default: ++len;
615 return len;
619 static inline char Capitalize (char Char) { return (char)(Char >= 'a' && Char <= 'z' ? Char-32 : Char); }
622 truth festring::startsWith (cchar *str, int slen) const {
623 if (!str) return (slen <= 0);
624 int realslen = (int)strlen(str);
625 if (slen < 0) slen = (int)realslen; else if (slen > realslen) return false;
626 if ((sizetype)slen > Size) return false;
627 if (slen == 0) return true;
628 return (memcmp(Data, str, slen) == 0);
632 truth festring::endsWith (cchar *str, int slen) const {
633 if (!str) return (slen <= 0);
634 int realslen = (int)strlen(str);
635 if (slen < 0) slen = (int)realslen; else if (slen > realslen) return false;
636 if (slen == 0) return true;
637 if ((sizetype)slen > Size) return false;
638 return (memcmp(Data+Size-slen, str, slen) == 0);
642 truth festring::startsWithCI (cchar *str, int slen) const {
643 if (!str) return (slen <= 0);
644 int realslen = (int)strlen(str);
645 if (slen < 0) slen = (int)realslen; else if (slen > realslen) return false;
646 if (slen == 0) return true;
647 if ((sizetype)slen > Size) return false;
648 cchar *ep = Data;
649 for (; slen > 0; ++str, ++ep, --slen) {
650 if (::Capitalize(*str) != ::Capitalize(*ep)) return false;
652 return true;
656 truth festring::endsWithCI (cchar *str, int slen) const {
657 if (!str) return (slen <= 0);
658 int realslen = (int)strlen(str);
659 if (slen < 0) slen = (int)realslen; else if (slen > realslen) return false;
660 if (slen == 0) return true;
661 if ((sizetype)slen > Size) return false;
662 cchar *ep = Data+Size-slen;
663 for (; slen > 0; ++str, ++ep, --slen) {
664 if (::Capitalize(*str) != ::Capitalize(*ep)) return false;
666 return true;
670 truth festring::startsWith (cfestring &str) const { return startsWith(str.Data, (int)str.Size); }
671 truth festring::endsWith (cfestring &str) const { return endsWith(str.Data, (int)str.Size); }
672 truth festring::startsWithCI (cfestring &str) const { return startsWithCI(str.Data, (int)str.Size); }
673 truth festring::endsWithCI (cfestring &str) const { return endsWithCI(str.Data, (int)str.Size); }
676 /* Returns the position of the first occurance of What in Where
677 * starting at Begin or after it, ignoring the case of letters.
678 * If the search fails, festring::NPos is returned instead. */
679 festring::sizetype festring::IgnoreCaseFind (cfestring &Where, cfestring &What, sizetype Begin) {
680 if (What.IsEmpty()) return Begin;
681 for (; Where.GetSize() >= What.GetSize() + Begin; ++Begin) {
682 if (::Capitalize(Where[Begin]) == ::Capitalize(What[0])) {
683 truth Equal = true;
684 for (sizetype c = 1; c < What.GetSize(); ++c)
685 if (::Capitalize(Where[Begin + c]) != ::Capitalize(What[c])) {
686 Equal = false;
687 break;
689 if (Equal) return Begin;
692 return NPos;
696 /* Replaces all occurances of What in Where after Begin with With */
697 void festring::SearchAndReplace (festring &Where, cfestring &What, cfestring &With, sizetype Begin) {
698 for (sizetype Pos = Where.Find(What, Begin); Pos != NPos; Pos = Where.Find(What, Pos)) {
699 Where.Erase(Pos, What.GetSize());
700 Where.Insert(Pos, With);
705 /* Returns whether First is behind Second in alphabetical order, ignoring case */
706 bool festring::IgnoreCaseCompare (cfestring &First, cfestring & Second) {
707 for (sizetype Pos = 0; Pos < First.GetSize() && Pos < Second.GetSize(); ++Pos) {
708 char Char1 = ::Capitalize(First[Pos]);
709 char Char2 = ::Capitalize(Second[Pos]);
710 if (Char1 != Char2) return Char1 < Char2;
712 return First.GetSize() < Second.GetSize();
716 void festring::SwapData (festring &Str) {
717 char *const TData = Data;
718 csizetype TSize = Size;
719 csizetype TReserved = Reserved;
720 ctruth TOwnsData = OwnsData;
721 Data = Str.Data;
722 Size = Str.Size;
723 Reserved = Str.Reserved;
724 OwnsData = Str.OwnsData;
725 Str.Data = TData;
726 Str.Size = TSize;
727 Str.Reserved = TReserved;
728 Str.OwnsData = TOwnsData;
732 sLong festring::GetCheckSum () const {
733 sLong Counter = 0;
734 for (uShort c = 0; c < GetSize(); ++c) Counter = sLong(Data[c]);
735 return Counter;