/[pearpc]/src/tools/str.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/tools/str.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 14836 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * HT Editor
3     * str.cc
4     *
5     * Copyright (C) 2002 Stefan Weyergraf
6     * Copyright (C) 2002, 2003 Sebastian Biallas (sb@biallas.net)
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2 as
10     * published by the Free Software Foundation.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     */
21    
22     #include <cctype>
23     #include <cstdlib>
24     #include <cstring>
25    
26     #include "except.h"
27     #include "debug.h"
28     #include "snprintf.h"
29     #include "str.h"
30     #include "stream.h"
31     #include "strtools.h"
32    
33     #ifdef HAVE_HT_OBJECTS
34     #include "atom.h"
35     #endif
36    
37     //extern "C" {
38     //#include "regex.h"
39     //}
40    
41     /*
42     * CLASS String
43     */
44    
45     /**
46     * creates empty string
47     */
48     String::String()
49     {
50     mContent = NULL;
51     realloc(0);
52     }
53    
54     /**
55     * create string from char *
56     */
57     String::String(const char *s)
58     {
59     mContent = NULL;
60     assign(s);
61     }
62    
63     /**
64     * copy constructor
65     */
66     String::String(const String *s)
67     {
68     mContent = NULL;
69     assign(s);
70     }
71    
72     /**
73     * copy constructor
74     */
75     String::String(const String &s)
76     {
77     ASSERT(&s != this);
78     mContent = NULL;
79     assign(s);
80     }
81    
82     /**
83     * creates string from array |s| size |aLength|
84     */
85     String::String(const byte *s, int aLength)
86     {
87     mContent = NULL;
88     assign(s, aLength);
89     }
90    
91     /**
92     * creates string with |count| times |c|
93     */
94     String::String(char c, int count)
95     {
96     mContent = NULL;
97     assign(c, count);
98     }
99    
100     String::~String()
101     {
102     if (mContent) free(mContent);
103     }
104    
105     /**
106     * (re-)assigns string to |s|
107     */
108     void String::assign(const String *s)
109     {
110     realloc(s->mLength);
111     memcpy(mContent, s->mContent, mLength);
112     }
113    
114     /**
115     * (re-)assigns string to |s|
116     */
117     void String::assign(const String &s)
118     {
119     realloc(s.mLength);
120     memcpy(mContent, s.mContent, mLength);
121     }
122    
123     /**
124     * (re-)assigns string to char * |s|
125     */
126     void String::assign(const char *s)
127     {
128     int slen = s ? strlen(s) : 0;
129     realloc(slen);
130     memcpy(mContent, s, mLength);
131     }
132    
133     /**
134     * (re-)assigns string to array |s| length |aLength|
135     */
136     void String::assign(const byte *s, int aLength)
137     {
138     realloc(aLength);
139     memcpy(mContent, s, mLength);
140     }
141    
142     /**
143     * (re-)assigns string to |count| times |c|
144     */
145     void String::assign(char c, int count)
146     {
147     realloc(count);
148     memset(mContent, c, count);
149     }
150    
151     /**
152     * (re-)assigns string via ht_snprintf
153     */
154     void String::assignFormat(const char *s, ...)
155     {
156     char buf[1024];
157     va_list vargs;
158     va_start(vargs, s);
159     ht_vsnprintf(buf, sizeof buf, s, vargs);
160     va_end(vargs);
161     assign(buf);
162     }
163    
164     /**
165     * appends |s| to the end
166     */
167     void String::append(const String &s)
168     {
169     if (s.mLength) {
170     int oldLength = mLength;
171     realloc(mLength + s.mLength);
172     memcpy(&mContent[oldLength], s.mContent, s.mLength);
173     }
174     }
175    
176     void String::append(const char *s)
177     {
178     if (s && *s) {
179     int oldLength = mLength;
180     int slen = strlen(s);
181     realloc(mLength + slen);
182     memcpy(&mContent[oldLength], s, slen);
183     }
184     }
185    
186     void String::appendChar(char c)
187     {
188     realloc(mLength+1);
189     mContent[mLength-1] = c;
190     }
191    
192     /**
193     * prepends |s| to the front
194     */
195     void String::prepend(const String &s)
196     {
197     if (s.mLength) {
198     int oldLength = mLength;
199     realloc(mLength + s.mLength);
200     memmove(&mContent[s.mLength], &mContent[0], oldLength);
201     memcpy(&mContent[0], s.mContent, s.mLength);
202     }
203     }
204    
205     /**
206     * Empties string.
207     */
208     void String::clear()
209     {
210     realloc(0);
211     }
212    
213     String *String::clone() const
214     {
215     return new String(mContent, mLength);
216     }
217    
218     /**
219     * compares to characters.
220     * used in compareTo() and findXXX() (and therefore replace())
221     * @returns 0 for equality, negative number if |c1<c2| and positive number if |c1>c2|
222     */
223     int String::compareChar(char c1, char c2) const
224     {
225     if (c1<c2) return -1;
226     if (c1>c2) return 1;
227     return 0;
228     }
229    
230     int String::compare(const char *s) const
231     {
232     if (!mLength) {
233     return (s) ? -1: 0;
234     }
235     if (!s) {
236     return 1;
237     }
238     int l = mLength;
239     for (int i=0; i < l; i++) {
240     if (!*s) return 1;
241     int r = compareChar(mContent[i], s[i]);
242     if (r) return r;
243     }
244     if (s[l]) return -1;
245     return 0;
246     }
247    
248     int String::compare(const String &s) const
249     {
250     if (!mContent) {
251     return (s.mContent) ? -1: 0;
252     }
253     if (!s.mContent) {
254     return 1;
255     }
256     int l = MIN(mLength, s.mLength);
257     for (int i=0; i<l; i++) {
258     int r = compareChar(mContent[i], s.mContent[i]);
259     if (r) return r;
260     }
261     if (mLength < s.mLength) return -1;
262     if (mLength == s.mLength) return 0;
263     return 1;
264     }
265    
266     /*
267     * like compare(s) but considers a maximum of |aMax| characters
268     */
269     int String::compare(const String &s, int aMax) const
270     {
271     if (aMax <= 0) return 0;
272     if (!mContent) {
273     return (s.mContent) ? -1: 0;
274     }
275     if (!s.mContent) {
276     return 1;
277     }
278     int l = MIN(mLength, s.mLength);
279     l = MIN(l, aMax);
280     int i;
281     for (i=0; i<l; i++) {
282     int r = compareChar(mContent[i], s.mContent[i]);
283     if (r) return r;
284     }
285     if (i == aMax) return 0;
286     if (mLength < s.mLength) return -1;
287     if (mLength == s.mLength) return 0;
288     return 1;
289     }
290    
291     int String::compareTo(const Object *o) const
292     {
293     ASSERT(getObjectID() == o->getObjectID());
294     return compare(*((String *)o));
295     }
296    
297     /**
298     * Crops the string to contain a maximum of |aNewLength| characters.
299     */
300     void String::crop(int aNewLength)
301     {
302     if ((aNewLength >= 0) && (aNewLength < mLength)) realloc(aNewLength);
303     }
304    
305     /**
306     * Deletes |aLength| characters at |pos|
307     */
308     void String::del(int pos, int aLength)
309     {
310     if (pos < 0) {
311     aLength += pos;
312     pos = 0;
313     }
314     if (aLength <= 0 || pos >= mLength) return;
315     if (pos+aLength >= mLength) aLength = mLength-pos;
316     if (!aLength) return;
317     if (pos + aLength < mLength) {
318     memmove(&mContent[pos], &mContent[pos+aLength], mLength-aLength-pos);
319     }
320     realloc(mLength-aLength);
321     }
322    
323     /**
324     * Escapes certains characters in a c-style manner (all characters < 0x20).
325     * @param aSpecialChars characters that need a \
326     * @param bit7 hex encode (\x..) characters >127
327     */
328     void String::escape(const char *aSpecialChars, bool bit7)
329     {
330     if (!mLength) return;
331     String copy(this);
332     realloc(mLength*4);
333     realloc(escape_special((char*)mContent, mLength, copy.mContent,
334     copy.mLength, aSpecialChars, bit7));
335     }
336    
337     /**
338     * Search forwards for |c| in string
339     * @param c character to search for
340     * @param start first character position to look for
341     * @returns position of character or number < 0 if not found
342     */
343     int String::findFirstChar(char c, int start) const
344     {
345     if (!mLength) return -1;
346     if (start >= mLength) return -1;
347     if (start < 0) start = 0;
348     for (int i=start; i<mLength; i++) {
349     if (compareChar(mContent[i], c) == 0) return i;
350     }
351     return -1;
352     }
353    
354     /**
355     * Search forwards for |s| in string
356     * @param s string to search for
357     * @param start first character position to look for
358     * @returns position of character or number < 0 if not found
359     */
360     int String::findFirstString(const String &s, int start) const
361     {
362     if (!s.mLength) return 0;
363     if (start < 0) start = 0;
364     if (!mLength || (start+s.mLength > mLength)) return -1;
365     for (int i=start; (i+s.mLength <= mLength); i++) {
366     for (int j=i; (j>=0) && (j+s.mLength <= mLength) && (j-i < s.mLength); j++) {
367     if (compareChar(mContent[j], s.mContent[j-i])) goto notfound;
368     }
369     return i;
370     notfound:;
371     }
372     return -1;
373     }
374    
375     /**
376     * Search backwards for |c| in string
377     * @param c character to search for
378     * @param start first character position to look for
379     * @returns position of character or number < 0 if not found
380     */
381     int String::findLastChar(char c, int start) const
382     {
383     if (!mLength) return -1;
384     if (start >= mLength) return -1;
385     if (start < 0) start = mLength-1;
386     for (int i=start; i>=0; i--) {
387     if (compareChar(mContent[i], c) == 0) return i;
388     }
389     return -1;
390     }
391    
392     /**
393     * Search backwards for |s| in string
394     * @param s string to search for
395     * @param start first character position to look for
396     * @returns position of character or number < 0 if not found
397     */
398     int String::findLastString(const String &s, int start) const
399     {
400     if (!mLength) return -1;
401     return -1;
402     }
403    
404     /**
405     * inserts |s| at postion |pos| in string.
406     */
407     void String::insert(const String &s, int pos)
408     {
409     if (pos > mLength || pos < 0) throw MsgException("index out of bounds");
410     if (!s.mLength) return;
411     realloc(mLength+s.mLength);
412     if (mLength-s.mLength-pos > 0)
413     memmove(&mContent[pos+s.mLength], &mContent[pos], mLength-s.mLength-pos);
414     memmove(&mContent[pos], s.mContent, s.mLength);
415     }
416    
417     bool String::instanceOf(ObjectID id) const
418     {
419     if (id == getObjectID()) return true;
420     return Object::instanceOf(id);
421     }
422    
423     bool String::leftSplit(char chr, String &initial, String &rem) const
424     {
425     int pivot = findFirstChar(chr);
426     if (pivot < 0) {
427     initial = *this;
428     rem.clear();
429     return false;
430     }
431     subString(0, pivot, initial);
432     subString(pivot+1, length(), rem);
433     return true;
434     }
435    
436     ObjectID String::getObjectID() const
437     {
438     return OBJID_STRING;
439     }
440    
441     void String::realloc(int aNewSize)
442     {
443     mLength = aNewSize;
444     mContent = (byte*)::realloc(mContent, mLength+1);
445     mContent[mLength] = 0;
446     /* if (mContent) {
447     if (aNewSize) {
448     mContent = (byte*)::realloc(mContent, aNewSize);
449     } else {
450     free(mContent);
451     mContent = NULL;
452     }
453     } else {
454     if (aNewSize) {
455     mContent = (byte*)malloc(aNewSize);
456     }
457     }
458     mLength = aNewSize;*/
459     }
460    
461     /*bool String::regexMatch(const String &aRegEx, Container *resultStrings, int maxRegExMatches) const
462     {
463     const char *re = aRegEx.toString();
464     bool result = false;
465     regex_t rx;
466    
467     int r = regcomp(&rx, re, REG_EXTENDED | ((compareChar('A','a')==0) ? REG_ICASE : 0));
468     if (r) throw MsgException("EINVAL");
469    
470     regmatch_t pmatch[maxRegExMatches];
471     if (regexec(&rx, (char*)mContent, maxRegExMatches, pmatch, 0) != 0) return false;
472    
473     if (resultStrings) {
474     for (int i=1; i < maxRegExMatches; i++) {
475     if (pmatch[i].rm_so == -1) break;
476     String *s = new String();
477     subString(pmatch[i].rm_so, pmatch[i].rm_eo-pmatch[i].rm_so, *s);
478     resultStrings->insert(s);
479     }
480     }
481    
482     delete re;
483     return result;
484     }*/
485    
486     /**
487     * replaces all occurences of |what| in string with |with|
488     * @param what searchstring
489     * @param with replacement
490     * @param start
491     * @param maxReplacements
492     * @returns number of replacements
493     */
494     int String::replace(const String &what, const String &with, int start, int maxReplacements)
495     {
496     if (!maxReplacements) return 0;
497     int whatlen = what.length();
498     int withlen = with.length();
499     int numRepl = 0;
500     int p = findFirstString(what, start);
501     while (p >= 0) {
502     if (whatlen == withlen) {
503     // replace in situ
504     memmove(&mContent[p], with.mContent, withlen);
505     } else {
506     del(p, whatlen);
507     insert(with, p);
508     }
509     numRepl++;
510     if (maxReplacements > 0) {
511     maxReplacements--;
512     if (!maxReplacements) break;
513     }
514     p = findFirstString(what, p+withlen);
515     }
516     return numRepl;
517     }
518    
519     bool String::rightSplit(char chr, String &initial, String &rem) const
520     {
521     int pivot = findLastChar(chr);
522     if (pivot < 0) {
523     initial = *this;
524     rem.clear();
525     return false;
526     }
527     subString(0, pivot, initial);
528     subString(pivot+1, length(), rem);
529     return true;
530     }
531    
532     /**
533     * assigns result to the substring with
534     * |aLength| characters starting at |aStart|.
535     * @param result will hold the result
536     * @param aStart position of first character in new string
537     * @param aLength number of characters to copy
538     * @returns number of characters copied
539     */
540     int String::subString(int aStart, int aLength, String &result) const
541     {
542     if (aLength <= 0 || aStart >= mLength) {
543     result.clear();
544     return 0;
545     }
546     if (aStart+aLength >= mLength) aLength = mLength-aStart;
547     result.assign(&mContent[aStart], aLength);
548     return aLength;
549     }
550    
551     /**
552     *
553     */
554     void String::transformCase(StringCase c)
555     {
556     if (c==stringCaseCaps) {
557     } else {
558     for (int i=0; i<mLength; i++) {
559     if (c==stringCaseLower) {
560     mContent[i]=tolower(mContent[i]);
561     } else {
562     mContent[i]=toupper(mContent[i]);
563     }
564     }
565     }
566     }
567    
568     /**
569     * replace all characters of |inAlpha| in string with the corrensponding
570     * characters of |outAlpha|. The lengths of |inAlpha| and |outAlpha| must
571     * be identical. |inAlpha| should not contain the same characters multiple
572     * times.
573     */
574     void String::translate(const String &inAlpha, const String &outAlpha)
575     {
576     ASSERT(inAlpha.mLength == outAlpha.mLength);
577     if (inAlpha.isEmpty() || isEmpty()) return;
578     byte tr[256];
579     for (int i=0; i<256; i++) tr[i] = i;
580     for (int i=0; i<inAlpha.mLength; i++) {
581     tr[inAlpha.mContent[i]] = outAlpha.mContent[i];
582     }
583     for (int i=0; i<mLength; i++) {
584     mContent[i] = tr[mContent[i]];
585     }
586     }
587    
588     /**
589     *
590     */
591     int String::toArray(byte *buf, int buflen) const
592     {
593     if (buflen <= 0) return 0;
594     int r = MIN(mLength, buflen-1);
595     memcpy(buf, mContent, r);
596     return r;
597     }
598    
599     /**
600     *
601     */
602     bool String::toInt(int &i, int defaultbase) const
603     {
604     const char *b = (const char*)mContent;
605     uint64 u64;
606     if (!parseIntStr(b, u64, defaultbase)) return false;
607     if (b-(const char*)mContent != mLength) return false;
608     i = (sint64)u64;
609     return true;
610     }
611    
612     /**
613     *
614     */
615     bool String::toInt32(uint32 &u32, int defaultbase) const
616     {
617     const char *b = (const char*)mContent;
618     uint64 u64;
619     if (!parseIntStr(b, u64, defaultbase)) return false;
620     if (b-(const char*)mContent != mLength) return false;
621     u32 = u64;
622     return true;
623     }
624    
625     /**
626     *
627     */
628     bool String::toInt64(uint64 &u64, int defaultbase) const
629     {
630     const char *b = (const char*)mContent;
631     if (!parseIntStr(b, u64, defaultbase)) return false;
632     return (b-(const char*)mContent == mLength);
633     }
634    
635     int String::toString(char *buf, int buflen) const
636     {
637     if (buflen <= 0) return 0;
638     int r = MIN(mLength, buflen-1);
639     for (int i=0; i<r; i++) {
640     if (mContent[i]) {
641     buf[i] = mContent[i];
642     } else {
643     buf[i] = ' ';
644     }
645     }
646     buf[r] = 0;
647     return r;
648     }
649    
650     /**
651     * all '\0' will be converted to ' ' (space)
652     * @returns new[] allocated char *
653     */
654     char *String::toString() const
655     {
656     char *s = new char[mLength+1];
657     for (int i=0; i<mLength; i++) {
658     if (mContent[i]) {
659     s[i] = mContent[i];
660     } else {
661     s[i] = ' ';
662     }
663     }
664     s[mLength] = 0;
665     return s;
666     }
667    
668     /**
669     * reverses action of <code>escape</code>.
670     * Note that output isnt defined if string wasnt escaped before.
671     */
672     void String::unescape()
673     {
674     String copy(this);
675     realloc(unescape_special(mContent, mLength, (char*)copy.mContent));
676     }
677    
678     String &String::operator +=(char c)
679     {
680     realloc(mLength+1);
681     mContent[mLength-1] = c;
682     return *this;
683     }
684    
685     /*
686     * global
687     */
688    
689     String operator +(const String &s1, const String &s2)
690     {
691     String temp = String(s1);
692     temp.append(s2);
693     return temp;
694     }
695    
696     String operator +(const char *s1, const String &s2)
697     {
698     String temp = String(s1);
699     temp.append(s2);
700     return temp;
701     }
702    
703     /*
704     * CLASS IString
705     */
706    
707     IString::IString()
708     {
709     }
710    
711     IString *IString::clone() const
712     {
713     IString *r = new IString();
714     *r = *this;
715     return r;
716     }
717    
718     int IString::compareChar(char c1, char c2) const
719     {
720     c1 = tolower(c1);
721     c2 = tolower(c2);
722     return String::compareChar(c1, c2);
723     }
724    
725     bool IString::instanceOf(ObjectID id) const
726     {
727     if (id == getObjectID()) return true;
728     return String::instanceOf(id);
729     }
730    
731     ObjectID IString::getObjectID() const
732     {
733     return OBJID_ISTRING;
734     }
735    

  ViewVC Help
Powered by ViewVC 1.1.26