blob: 15aa09470bca222cef52bd547833defc66f61f8b [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39/**
40 * @file string.h
41 * @short Common C++ generic string class
42 **/
43
44#ifndef CCXX_STRING_H_
45#define CCXX_STRING_H_
46
47#ifndef CCXX_MISSING_H_
48#include <cc++/missing.h>
49#endif
50
51#ifndef CCXX_STRCHAR_H_
52#include <cc++/strchar.h>
53#endif
54
55#ifdef CCXX_NAMESPACES
56namespace ost {
57#endif
58
59class MemPager;
60
61/**
62 * This is a generic and portable string class. It uses optimized
63 * memory allocation strategies to efficiently handle smaller string
64 * content by grouping strings into 32 byte aligned slots that can
65 * be re-allocated from a free list directly.
66 *
67 * While meant to cover the basic functionality of the ANSI C++
68 * string class in form and function, this class offers some important
69 * enhancements, including the ability to derive class type specific
70 * versions of itself. The latter might be used to derive a unicode
71 * string, a string for data and time data types, or to add case
72 * insensitive comparisons, for example.
73 *
74 * @author David Sugar <dyfet@ostel.com>
75 * @short Generic string class.
76 */
77class __EXPORT String
78{
79protected:
80 static const unsigned minsize;
81 static const unsigned slotsize;
82 static const unsigned pagesize;
83 static const unsigned slotlimit;
84 static const unsigned slotcount;
85
86 friend class StringObject;
87
88private:
89 friend class MemPager;
90
91 static MemPager *pager;
92 static char **idx;
93
94#ifdef CCXX_PACKED
95#pragma pack(1)
96#endif
97
98 union {
99 struct {
100 char *text;
101 size_t size;
102 size_t length;
103 } bigstring;
104 struct {
105 char text[(sizeof(char *) + (sizeof(size_t) * 2) + 1)];
106 char length : 6;
107 bool big : 1;
108 } ministring;
109 } content;
110
111#ifdef CCXX_PACKED
112#pragma pack()
113#endif
114
115protected:
116 /**
117 * Determine if string is allocated in local variable or an
118 * external reference.
119 *
120 * @return true if external heap is used.
121 */
122 inline bool isBig(void) const
123 {return content.ministring.big;};
124
125 /**
126 * Set the content of the string variable to the specified
127 * string value, and use smart re-allocation strategies if
128 * appropriate to shrink the size of the variable.
129 *
130 * @param str string to set.
131 * @param len length of string if passed.
132 */
133 const char *set(const char *str, size_t len = 0);
134
135 /**
136 * Set the content of the string variable to that of another
137 * variable. Uses the string set method.
138 *
139 * @param str string to copy from.
140 */
141 void set(const String &str);
142
143#ifdef HAVE_SNPRINTF
144 /**
145 * Set the content of the string variable to that of a
146 * formatted printf style string.
147 *
148 * @param size of string data to set.
149 * @param format of string to write into object.
150 */
151 const char *set(size_t size, const char *format, ...);
152#endif
153
154 /**
155 * Impliment the copy constructor, used internally. Will always
156 * create a minimum sized string allocation.
157 *
158 * @param str string to copy from.
159 */
160 void copy(const String &str);
161
162 /**
163 * Used to initialize a string object.
164 */
165 void init(void);
166
167 /**
168 * Used to fetch memory, if needed, based on the size, from the
169 * pager, or the system heap.
170 *
171 * @return string pointer to space.
172 * @param size of space needed.
173 */
174 static char *getSpace(size_t size);
175
176 /**
177 * Set the size of allocated space in the string variable
178 * (capacity) to a known value. The value is recomputed and
179 * adjusted based on allocation method.
180 *
181 * @param size in bytes.
182 */
183 size_t setSize(size_t size);
184
185 /**
186 * Set the length value of the string content.
187 *
188 * @param len size in bytes.
189 */
190 void setLength(size_t len);
191
192 /**
193 * A derivable low level comparison operator. This can be used
194 * to create custom comparison data types in derived string
195 * classes.
196 *
197 * @return 0 if match, or value for ordering.
198 * @param text text to compare.
199 * @param len length of text to compare.
200 * @param index offset from start of string, used in searchs.
201 */
202 virtual int compare(const char *text, size_t len = 0, size_t index = 0) const;
203
204 /**
205 * An internal method used to search for a substring starting at
206 * a known offset. Used by find and count methods.
207 *
208 * @return npos if fails, or offset to text found.
209 * @param text text to search for.
210 * @param clen length of search text.
211 * @param offset offset to start from.
212 */
213 size_t search(const char *text, size_t clen = 0, size_t offset = 0) const;
214
215public:
216 static const size_t npos;
217
218 typedef size_t size_type;
219
220 /**
221 * Construct an empty string.
222 */
223 String();
224
225 /**
226 * Copy constructor.
227 *
228 * @param original string to copy from.
229 */
230 String(const String &original);
231
232 /**
233 * Create a string from a cstring.
234 *
235 * @param str text to set with.
236 */
237 String(const char *str);
238
239 /**
240 * Create a String from std::string.
241 *
242 * @param string from std::string to copy from.
243 */
244 String(std::string string);
245
246 /**
247 * Create a new string from a subset of another string.
248 *
249 * @param str reference of source string.
250 * @param offset offset to start of data in prior string.
251 * @param len length of our substring.
252 */
253 String(const String &str, size_t offset, size_t len = npos);
254
255#ifdef HAVE_SNPRINTF
256 /**
257 * Create a string from formatted text input.
258 *
259 * @param size to allocate for our new string.
260 * @param format of data to input.
261 */
262 String(size_t size, const char *format, ...);
263#else
264 /**
265 * Create a string of a known size, and optionally fill with
266 * content.
267 *
268 * @param count size to allocate for our new string.
269 * @param str content to put into it.
270 */
271 String(size_t count, const char *str);
272#endif
273
274 /**
275 * Fill a new string with character data.
276 *
277 * @param count size of new string.
278 * @param fill char to fill string with.
279 */
280 String(size_t count, const char fill = ' ');
281
282 /**
283 * Destroy the string...
284 */
285 virtual ~String();
286
287 /**
288 * Get a string pointer to string content based on an indexed
289 * offset. A NULL is returned if the index is outsize of range.
290 *
291 * @return string content or NULL if invalid index.
292 * @param index
293 */
294 const char *getIndex(size_t index) const;
295
296 /**
297 * Get the text of a string.
298 *
299 * @return string content.
300 */
301 char *getText(void) const;
302
303 /**
304 * Get the value of a string.
305 *
306 * @return string value as number.
307 */
308 long getValue(long defvalue = 0l) const;
309
310 /**
311 * Get the bool flag of a string.
312 *
313 * @return boolean value.
314 */
315 bool getBool(bool defbool = false) const;
316
317 /**
318 * Get the assigned length of string.
319 *
320 * @return string length.
321 */
322 const size_t getLength(void) const;
323
324 /**
325 * Get the allocation size of the string variable.
326 *
327 * @return allocation size.
328 */
329 const size_t getSize(void) const;
330
331 /**
332 * Return true if string is empty.
333 *
334 * @return true if string is empty string.
335 */
336 bool isEmpty(void) const;
337
338 /**
339 * Re-allocate buffer space for string.
340 *
341 * @param size new size to use.
342 */
343 void resize(size_t size);
344
345 /**
346 * Clear the contents of the entire string.
347 */
348 void clear(void);
349
350 /**
351 * Return a character at a known offset.
352 *
353 * @return character at offset.
354 */
355 char at(ssize_t offset) const;
356
357 /**
358 * Count the number of occurences of a specific string within
359 * our string.
360 *
361 * @return count of instances.
362 * @param s string to test.
363 * @param offset offset to start from.
364 */
365 unsigned count(const String &s, size_t offset = 0) const;
366
367 /**
368 * Count the number of occurrences of a specific text pattern
369 * within our string.
370 *
371 * @return count of instances.
372 * @param s text pattern to find
373 * @param offset offset to start from.
374 * @param len length of text pattern if specified.
375 */
376 unsigned count(const char *s, size_t offset = 0, size_t len = 0) const;
377
378 /**
379 * Extract a new string as a token from the current string.
380 *
381 * @return string containing token.
382 * @param delim deliminator characters.
383 * @param offset offset to start from.
384 */
385 String token(const char *delim = " \t\n\r", size_t offset = 0);
386
387 /**
388 * Find the index to the nth instance of a substring in our string.
389 *
390 * @return index of found substring.
391 * @param s string to search for.
392 * @param offset offset to start at.
393 * @param instance instance to look for.
394 */
395 size_t find(const String &s, size_t offset = 0, unsigned instance = 1) const;
396
397 /**
398 * Find last occurence of a substring in our string.
399 *
400 * @return index of last instance found,
401 * @param s string to search for.
402 * @param offset offset to start from.
403 */
404 size_t rfind(const String &s, size_t offset = 0) const;
405
406 /**
407 * Find the index to the nth instance of text in our string.
408 *
409 * @return index of found substring.
410 * @param s string to search for.
411 * @param offset offset to start at.
412 * @param len size of string text.
413 * @param count instance to look for.
414 */
415 size_t find(const char *s, size_t offset = 0, size_t len = 0, unsigned count = 1) const;
416
417 /**
418 * Find last occurence of a text in our string.
419 *
420 * @return index of last instance found,
421 * @param s string to search for.
422 * @param offset offset to start from.
423 * @param len size of string to look for.
424 */
425 size_t rfind(const char *s, size_t offset = 0, size_t len = 0) const;
426
427 /**
428 * Trim trailing characters from a string.
429 *
430 * @param cs list of chars to trim.
431 */
432 inline void trim(const char *cs)
433 {setLength(strtrim(cs, getText(), getLength()));};
434
435 /**
436 * Chop leading characters from a string.
437 *
438 * @param cs list of chars to chop.
439 */
440 inline void chop(const char *cs)
441 {setLength(strchop(cs, getText(), getLength()));};
442
443 /**
444 * Strip lead and trailing characters from a string.
445 *
446 * @param cs list of chars to strip.
447 */
448 void strip(const char *cs);
449
450 /**
451 * Chop n leading characters from a string.
452 *
453 * @param chars count to chop.
454 */
455 inline void chop(size_t chars)
456 {erase(0, chars);};
457
458 /**
459 * Trim n trailing characters from a string.
460 *
461 * @param count number of bytes to trim.
462 */
463 void trim(size_t count);
464
465 /**
466 * Erase a portion of string.
467 *
468 * @param start starting index to erase from.
469 * @param len number of characters to erase.
470 */
471 void erase(size_t start, size_t len = npos);
472
473 /**
474 * Insert text into a string.
475 *
476 * @param start starting offset to insert at.
477 * @param text text to insert.
478 * @param len size of text to insert.
479 */
480 void insert(size_t start, const char *text, size_t len = 0);
481
482 /**
483 * Insert other string into our string.
484 *
485 * @param start string offset to insert at.
486 * @param str string to insert.
487 */
488 void insert(size_t start, const String &str);
489
490 /**
491 * Replace text at a specific position in the string with new
492 * text.
493 *
494 * @param start starting offset to replace at.
495 * @param len length of text to remove.
496 * @param text text to replace with.
497 * @param count size of replacement text.
498 */
499 void replace(size_t start, size_t len, const char *text, size_t count = 0);
500
501 /**
502 * Replace text at a specific position in the string with new
503 * string,
504 *
505 * @param start starting offset to replace at.
506 * @param len length of text to remove.
507 * @param string reference to replace with.
508 */
509 void replace(size_t start, size_t len, const String &string);
510
511 /**
512 * A more convenient version of find for nth occurences, by
513 * putting the instance first.
514 *
515 * @param instance nth instance to look for.
516 * @param text text to look for.
517 * @param offset offset to start at.
518 * @param len length of text.
519 */
520 inline size_t find(unsigned instance, const char *text, size_t offset = 0, size_t len = 0) const
521 {return find(text, offset, len, instance);};
522
523 /**
524 * A more convenient version of find for nth occurences, by
525 * putting the instance first.
526 *
527 * @param instance nth instance to look for.
528 * @param string reference to look for.
529 * @param offset offset to start at.
530 */
531 inline size_t find(unsigned instance, const String &string, size_t offset = 0) const
532 {return find(string, offset, instance);};
533
534 /**
535 * Return a new string that contains a specific substring of the
536 * current string.
537 *
538 * @return new string.
539 * @param start starting offset for extracted substring.
540 * @param len length of substring.
541 */
542 inline String substr(size_t start, size_t len) const
543 {return String(*this, start, len);};
544
545 /**
546 * Return an indexed string based on the index, such as from a
547 * find. If out of range, a NULL string is returned.
548 *
549 * @return pointer to string data from our string,
550 * @param ind index or offset to use.
551 */
552 inline const char *(index)(size_t ind) const
553 {return getIndex(ind);};
554
555 /**
556 * Reduce the size of the string allocation to the minimum
557 * needed based on the current effective length.
558 */
559 inline void compact(void)
560 {resize(getLength() + 1);};
561
562 /**
563 * Old ANSI C++ compatible string pointer extraction.
564 *
565 * @return string data.
566 */
567 inline char *c_str(void) const
568 {return getText();};
569
570 /**
571 * Get our string data through dereference operator.
572 *
573 * @return string data.
574 */
575 inline operator char *() const
576 {return getText();};
577
578 /**
579 * Logical test for string empty.
580 *
581 * @return true if is empty.
582 */
583 inline bool operator!(void) const
584 {return isEmpty();};
585
586 /**
587 * Alternate get text method.
588 *
589 * @return string data.
590 */
591 inline char *text(void) const
592 {return getText();};
593
594 /**
595 * Alternate get text method.
596 *
597 * @return string data.
598 */
599 inline char *data(void) const
600 {return getText();};
601
602 /**
603 * Get length as if null terminated string.
604 *
605 * @return cstring length.
606 */
607 inline size_t length(void) const
608 {return strlen(getText());};
609
610 /**
611 * Get actual length of string data.
612 *
613 * @return actual size of string.
614 */
615 inline size_t size(void) const
616 {return getLength();};
617
618 /**
619 * Get space allocated to hold current string.
620 *
621 * @return space of memory buffer from heap or local.
622 */
623 inline size_t capacity(void) const
624 {return getSize();};
625
626 /**
627 * Return true if string is empty.
628 */
629 bool empty(void) const
630 {return isEmpty();};
631
632 /**
633 * Append text to the end of the current string.
634 *
635 * @param str text to append.
636 * @param count size of text to append.
637 */
638 void append(const char *str, size_t count = 0);
639
640#ifdef HAVE_SNPRINTF
641 /**
642 * Append formatted text to the end of the current string.
643 *
644 * @param size size of text to append.
645 * @param format of data to append.
646 */
647 void append(size_t size, const char *format, ...);
648#endif
649
650 /**
651 * Append text into the current string.
652 *
653 * @param str text to append.
654 * @param offset offset to overlay.
655 * @param count size of text to append.
656 */
657 void append(const char *str, size_t offset, size_t count);
658
659 /**
660 * Add a character to the end of a string.
661 *
662 * @param c char to add.
663 */
664 void add(char c);
665
666 /**
667 * Append string to the end of the current string.
668 *
669 * @param str string to append.
670 */
671 void append(const String &str);
672
673 /**
674 * Extract a character by array indexing.
675 *
676 * @return character code.
677 */
678 inline const char operator[](unsigned ind) const
679 {return at(ind);};
680
681 /**
682 * Assign our string for c string.
683 */
684 inline const char *operator =(const char *str)
685 {return set(str);};
686
687 /**
688 * Add two strings and return a temporary object.
689 */
690 friend __EXPORT String operator+(const String &s1, const String &s2);
691
692 friend __EXPORT String operator+(const String &s1, const char *s2);
693
694 friend __EXPORT String operator+(const char *s1, const String &s2);
695
696 friend __EXPORT String operator+(const String &s1, const char c2);
697
698 friend __EXPORT String operator+(const char c1, const String &s2);
699
700 /**
701 * Append operator.
702 */
703 inline String &operator+=(const String &str)
704 {append(str); return *this;};
705
706 /**
707 * Append operator.
708 */
709 inline String &operator+=(char c)
710 {add(c); return *this;};
711
712 /**
713 * Append operator.
714 */
715 inline String &operator+=(const char *str)
716 {append(str); return *this;};
717
718 /**
719 * Append operator.
720 */
721 inline String &operator+=(const std::string &str)
722 {append(str.c_str()); return *this;};
723
724 /**
725 * Fetch input from a std::istream into the current string
726 * variable until either the string variable is filled (based on
727 * current length) or the deliminator is read.
728 *
729 * @param is stream to read.
730 * @param str string to save into.
731 * @param delim deliminator to use.
732 * @param size optional size limitor.
733 */
734 friend __EXPORT std::istream &getline(std::istream &is, String &str, char delim = '\n', size_t size = 0);
735
736 /**
737 * Stream the content of our string variable directly to a C++
738 * streaming source.
739 */
740 friend __EXPORT std::ostream &operator<<(std::ostream &os, const String &str);
741
742 /**
743 * Stream input into our variable.
744 */
745 inline friend std::istream &operator>>(std::istream &is, String &str)
746 {return getline(is, str);};
747
748#ifdef HAVE_SNPRINTF
749 /**
750 * Print values directly into a string variable.
751 *
752 * @return character count.
753 * @param str object reference to use.
754 * @param size of string required.
755 * @param format of data.
756 */
757 friend __EXPORT int strprintf(String &str, size_t size, const char *format, ...);
758#endif
759
760 bool operator<(const String &str) const;
761 bool operator<(const char *str) const;
762 bool operator>(const String &str) const;
763 bool operator>(const char *str) const;
764 bool operator<=(const String &str) const;
765 bool operator<=(const char *str) const;
766 bool operator>=(const String &str) const;
767 bool operator>=(const char *str) const;
768 bool operator==(const String &str) const;
769 bool operator==(const char *str) const;
770 bool operator!=(const String &str) const;
771 bool operator!=(const char *str) const;
772
773#ifdef HAVE_SNPRINTF
774
775 /**
776 * Append operator
777 */
778 inline String &operator+=(int i)
779 {append(16, "%d", i); return *this;};
780
781 inline String &operator+=(unsigned int i)
782 {append(16, "%u", i); return *this;};
783
784 inline String &operator+=(long l)
785 {append(16, "%l", l); return *this;};
786
787 inline String &operator+=(unsigned long l)
788 {append(16, "%ul", l); return *this;};
789
790 inline String &operator+=(float f)
791 {append(32, "%f", f); return *this;};
792
793 inline String &operator+=(double d)
794 {append(32, "%f", d); return *this;};
795
796 inline String &operator+=(short s)
797 {append(8, "%hd", s); return *this;};
798
799 inline String &operator+=(unsigned short s)
800 {append(8, "%hu", s); return *this;};
801
802
803 /**
804 * Assignment operator.
805 */
806 inline String &operator=(int i)
807 {set(16, "%d", i); return *this;};
808
809 inline String &operator=(unsigned int i)
810 {set(16, "%u", i); return *this;};
811
812 inline String &operator=(long l)
813 {set(16, "%l", l); return *this;};
814
815 inline String &operator=(unsigned long l)
816 {set(16, "%ul", l); return *this;};
817
818 inline String &operator=(float f)
819 {set(32, "%f", f); return *this;};
820
821 inline String &operator=(double d)
822 {set(32, "%f", d); return *this;};
823
824 inline String &operator=(short s)
825 {set(8, "%hd", s); return *this;};
826
827 inline String &operator=(unsigned short s)
828 {set(8, "%hu", s); return *this;};
829#endif
830
831 inline String &operator=(const String &original)
832 {copy(original); return *this;};
833
834 /**
835 * Test if string is contained in our string.
836 */
837 bool operator*=(const String &str) const;
838
839 /**
840 * Test if text is contained in our string.
841 */
842 bool operator*=(const char *str) const;
843};
844
845class __EXPORT SString : public String, protected std::streambuf, public std::ostream
846{
847protected:
848 /**
849 * This is the streambuf function that actually outputs the data
850 * to the string. Since all output should be done with the standard
851 * ostream operators, this function should never be called directly.
852 */
853 int overflow(int c);
854
855public:
856 /**
857 * Create an empty streamable string ready for input.
858 */
859 SString();
860
861 /**
862 * Copy constructor
863 */
864 SString(const SString &from);
865
866 /**
867 * Cancel out the object.
868 */
869 ~SString();
870};
871
872/**
873 * The StringObject class is used to derive subclasses that use the
874 * String managed memory pool for all space allocations by overriding
875 * new and delete operators. Due to size limits, StringObject should
876 * not hold very large objects.
877 *
878 * @author David Sugar <dyfet@ostel.com>
879 * @short Objects managed in reusable String memory pools
880 */
881class __EXPORT StringObject
882{
883public:
884 /**
885 * Create a new object in string managed space.
886 */
887 void *operator new(size_t size) NEW_THROWS;
888
889 /**
890 * Delete object from string managed space.
891 */
892 void operator delete(void *obj);
893};
894
895#ifdef CCXX_NAMESPACES
896}
897#endif
898
899#endif