1 //---------------------------------------------------------------------------
2 #ifndef GSTR_H
3 #define GSTR_H
4 //---------------------------------------------------------------------------
5 #include "GBase.h"
6 #include <string.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 // This class uses reference counting and copy-on-write semantics
11 
12 // All indexes are zero-based.  For all functions that accept an index, a
13 // negative index specifies an index from the right of the string.  Also,
14 // for all functions that accept a length, a length of -1 specifies the rest
15 // of the string.
16 enum enTokenizeMode {
17  tkFullString,
18  tkCharSet
19  };
20 
21 class GStr {
22         friend GStr operator+(const char* s1, const GStr& s2);
23         friend bool operator==(const char* s1, const GStr& s2);
24         friend bool operator<(const char* s1, const GStr& s2);
25         friend bool operator<=(const char* s1, const GStr& s2);
26         friend bool operator>(const char* s1, const GStr& s2);
27         friend bool operator>=(const char* s1, const GStr& s2);
28         friend bool operator!=(const char* s1, const GStr& s2);
29         friend void Gswap(GStr& s1, GStr& s2);
30     public:
31         GStr();
32         GStr(const GStr& s);
33         GStr(const char* s);
34         GStr(const int i);
35         GStr(const double f);
36         GStr(char c, int n = 1);
37         ~GStr();
38         operator const char* () const { return my_data->chars;} //inline here
39         char& operator[](int index);
40         char operator[](int index) const;
41         GStr& operator=(const GStr& s);
42         GStr& operator=(const char* s);
43         GStr& operator=(const int i);
44         GStr& operator=(const double f);
45         GStr operator+(const GStr& s) const;
46         GStr operator+(const char* s) const;
47         GStr operator+(const char c) const;
48         GStr operator+(const int i) const;
49         GStr operator+(const double f) const;
50         bool operator==(const GStr& s) const;
51         bool operator==(const char* s) const;
52         bool operator<(const GStr& s) const;
53         bool operator<(const char* s) const;
54         bool operator<=(const GStr& s) const;
55         bool operator<=(const char* s) const;
56         bool operator>(const GStr& s) const;
57         bool operator>(const char* s) const;
58         bool operator>=(const GStr& s) const;
59         bool operator>=(const char* s) const;
60         bool operator!=(const GStr& s) const;
61         bool operator!=(const char* s) const;
62         GStr& operator+=(const GStr& s) { return append(s.chars()); }
63         GStr& operator+=(const char* s) { return append(s); }
64         GStr& operator+=(char c) { return append(c); }
65         GStr& operator+=(int i) { return append(i); }
66         GStr& operator+=(uint i) { return append(i); }
67         GStr& operator+=(long l) { return append(l); }
68         GStr& operator+=(unsigned long l) { return append(l); }
69         GStr& operator+=(double f);
70       //interface:
71       public:
72         int length() const;
73         bool is_empty() const;
74         bool is_space() const;
75         GStr substr(int index = 0, int len = -1) const;
76         GStr to(char c); //return the first part up to first occurence of c
77                            //or whole string if c not found
78         GStr from(char c); //same as to, but starting from the right side
79         GStr copy() const;
80         GStr& format(const char *fmt,...);
81         GStr& reverse();
82         GStr& appendfmt(const char *fmt,...);
83         GStr& cut(int index = 0, int len = -1); //delete a specified length
remove(int from,int to)84         GStr& remove(int from, int to) {
85             return cut(from, to-from+1);
86             }
87 
88         //paste a string at the specified position
89         GStr& paste(const GStr& s, int index = 0, int len=-1);
90         GStr& paste(const char* s, int index = 0, int len = -1);
91         GStr& replace(const char* from, const char* to=NULL);
92         GStr& insert(const GStr& s, int index = 0);
93         GStr& insert(const char* s, int index = 0);
94         GStr& append(const char* s);
95         GStr& append(const GStr& s);
96         GStr& append(char c);
97         GStr& append(int i);
98         GStr& append(long l);
99         GStr& append(double f);
100         GStr& append(uint i);
101         GStr& append(unsigned long l);
102 
103         GStr& upper();
104         GStr& lower();
105         GStr& clear();//make empty
106         //character translation or removal:
107         GStr& tr(const char* from, const char* to=NULL);
108         //number of occurences of a char in the string:
109         int count(char c);
110         void startTokenize(const char* delimiter=" \t\n", enTokenizeMode tokenizemode=tkCharSet);
111         bool nextToken(GStr& token);
112         int asInt(int base=10);
113         double asReal();
asDouble()114         double asDouble() { return asReal(); }
115         bool asReal(double& r);
asDouble(double & r)116         bool asDouble(double& r) { return asReal(r); }
117         bool asInt(int& r, int base=10);
118         int index(const GStr& s, int start_index = 0) const;
119         int index(const char* s, int start_index = 0) const;
120         int index(char c, int start_index = 0) const;
121         int rindex(char c, int end_index = -1) const;
122         int rindex(const char* str, int end_index = -1) const;
123         bool contains(const GStr& s) const;
124         bool contains(const char* s) const;
125         bool contains(char c) const;
126         bool startsWith(const char* s) const;
127         bool startsWith(const GStr& s) const;
128         bool endsWith(const char* s) const;
129         bool endsWith(const GStr& s) const;
130         GStr split(const char* delim);
131         GStr split(char c);
132            /* splits "this" in two parts, at the first (leftmost)
133                  encounter of delim:
134                  1st would stay in "this"
135                  (which this way is truncated)
136                  2nd will go to the returned string
137            */
138         GStr splitr(const char* delim);
139         GStr splitr(char c);
140            /* splits "this" in two parts, at the last (rightmost)
141                  encounter of delim:
142                  1st would stay in "this"
143                  2nd will be returned
144            */
145 
146         int peelInt() const; //extract an integer, (left to right), from a
147                 //mixed alphanumeric string, e.g. 'T24HC1234b'=> 2
148         int peelIntR() const; //same as above, but starts from the right side
149         //e.g. 'T2HC1234b'=> 1234
150         GStr& trim(char c);
151         GStr& trim(const char* c=" \t\n\r"); //trim both ends of characters in given set
152         GStr& trimR(const char* c=" \t\n\r"); //trim only right end
153         GStr& trimR(char c=' ');
154         GStr& chomp(char c='\n') { return trimR(c); }
155         GStr& chomp(const char* cstr); //like trimR, but given string is taken as a whole
156         GStr& trimL(const char* c=" \t\n\r"); //trim only left end
157         GStr& trimL(char c=' ');
158         GStr& padR(int len, char c=' '); //align it in len spaces to the right
159         GStr& padL(int len, char c=' '); //align it in len spaces to the left
160         GStr& padC(int len, char c=' '); //center it
161         size_t read(FILE* stream, const char* delimiter="\n", size_t bufsize=4096);
162           //read next token from stream, using the given string as
163           //a marker where the block should stop
164         const char* chars() const;
165         const char* text() const;
166     protected:
167         char* fTokenDelimiter;
168         int fLastTokenStart;
169         enTokenizeMode fTokenizeMode;
170         void* readbuf; //file read buffer for the read() function
171         size_t readbufsize; //last setting for the readbuf
172         static void invalid_args_error(const char* fname);
173         static void invalid_index_error(const char* fname);
174         struct Data {//structure holding actual
175                      //string data and reference count information
DataData176                Data() { ref_count=0; length=0; chars[0] = '\0'; }
177                unsigned int ref_count;
178                int length;
179                char chars[1];
180               };
181         static Data* new_data(int length); //alloc a specified length string's Data
182         static Data* new_data(const char* str); //alloc a copy of a specified string
183         void replace_data(int length);
184         void replace_data(Data* data);
185         void make_unique();
186         char* chrs(); // this is dangerous, length should not be affected
187         static Data null_data; //a null (empty) string Data is available here
188         Data* my_data; //pointer to a Data object holding actual string data
189 };
190 
191 /***************************************************************************/
192 
length()193 inline int GStr::length() const {
194  return my_data->length;
195  }
196 
197 
chars()198 inline const char *GStr::chars() const {
199  return my_data->chars;
200  }
201 
chrs()202 inline char *GStr::chrs() { //protected version, allows modification of the chars
203  return my_data->chars;
204  }
205 
text()206 inline const char *GStr::text() const {
207  return my_data->chars;
208  }
209 
210 inline bool operator>=(const char *s1, const GStr& s2) {
211  return (strcmp(s1, s2.chars()) >= 0);
212  }
213 
214 inline bool operator!=(const char *s1, const GStr& s2) {
215  return (strcmp(s1, s2.chars()) != 0);
216  }
217 
Gswap(GStr & s1,GStr & s2)218 inline void Gswap(GStr& s1, GStr& s2) {
219  GStr::Data *tmp = s1.my_data; s1.my_data = s2.my_data;
220  s2.my_data = tmp;
221  }
222 
223 #endif
224