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); |
63 |
GStr& operator+=(const char* s); |
64 |
GStr& operator+=(const char c); |
65 |
GStr& operator+=(const int i); |
66 |
GStr& operator+=(const double f); |
67 |
//interface: |
68 |
public: |
69 |
int length() const; |
70 |
bool is_empty() const; |
71 |
bool is_space() const; |
72 |
GStr substr(int index = 0, int len = -1) const; |
73 |
GStr to(char c); //return the first part up to first occurence of c |
74 |
//or whole string if c not found |
75 |
GStr from(char c); //same as to, but starting from the right side |
76 |
GStr copy() const; |
77 |
GStr& format(const char *fmt,...); |
78 |
GStr& reverse(); |
79 |
GStr& appendfmt(const char *fmt,...); |
80 |
GStr& cut(int index = 0, int len = -1); //delete a specified length |
81 |
GStr& remove(int from, int to) { |
82 |
return cut(from, to-from+1); |
83 |
} |
84 |
|
85 |
//paste a string at the specified position |
86 |
GStr& paste(const GStr& s, int index = 0, int len=-1); |
87 |
GStr& paste(const char* s, int index = 0, int len = -1); |
88 |
GStr& replace(const char* from, const char* to=NULL); |
89 |
GStr& insert(const GStr& s, int index = 0); |
90 |
GStr& insert(const char* s, int index = 0); |
91 |
GStr& append(const char* s); |
92 |
GStr& append(const GStr& s); |
93 |
GStr& upper(); |
94 |
GStr& lower(); |
95 |
GStr& clear();//make empty |
96 |
//character translation or removal: |
97 |
GStr& tr(const char* from, const char* to=NULL); |
98 |
//number of occurences of a char in the string: |
99 |
int count(char c); |
100 |
void startTokenize(const char* delimiter, enTokenizeMode tokenizemode=tkCharSet); |
101 |
bool nextToken(GStr& token); |
102 |
int asInt(int base=10); |
103 |
double asReal(); |
104 |
double asDouble() { return asReal(); } |
105 |
bool asReal(double& r); |
106 |
bool asDouble(double& r) { return asReal(r); } |
107 |
bool asInt(int& r, int base=10); |
108 |
int index(const GStr& s, int start_index = 0) const; |
109 |
int index(const char* s, int start_index = 0) const; |
110 |
int index(char c, int start_index = 0) const; |
111 |
int rindex(char c, int end_index = -1) const; |
112 |
int rindex(const char* str, int end_index = -1) const; |
113 |
bool contains(const GStr& s) const; |
114 |
bool contains(const char* s) const; |
115 |
bool contains(char c) const; |
116 |
bool startsWith(const char* s) const; |
117 |
bool startsWith(const GStr& s) const; |
118 |
bool endsWith(const char* s) const; |
119 |
bool endsWith(const GStr& s) const; |
120 |
GStr split(const char* delim); |
121 |
GStr split(char c); |
122 |
/* splits "this" in two parts, at the first (leftmost) |
123 |
encounter of delim: |
124 |
1st would stay in "this" |
125 |
(which this way is truncated) |
126 |
2nd will go to the returned string |
127 |
*/ |
128 |
GStr splitr(const char* delim); |
129 |
GStr splitr(char c); |
130 |
/* splits "this" in two parts, at the last (rightmost) |
131 |
encounter of delim: |
132 |
1st would stay in "this" |
133 |
2nd will be returned |
134 |
*/ |
135 |
|
136 |
int peelInt() const; //extract an integer, (left to right), from a |
137 |
//mixed alphanumeric string, e.g. 'T24HC1234b'=> 2 |
138 |
int peelIntR() const; //same as above, but starts from the right side |
139 |
//e.g. 'T2HC1234b'=> 1234 |
140 |
GStr& trim(char c); |
141 |
GStr& trim(const char* c=" \t\n\r"); //trim both ends of characters in given set |
142 |
GStr& trimR(const char* c=" \t\n\r"); //trim only right end |
143 |
GStr& trimR(char c=' '); |
144 |
GStr& chomp(char c='\n') { return trimR(c); } |
145 |
GStr& chomp(const char* cstr); //like trimR, but given string is taken as a whole |
146 |
GStr& trimL(const char* c=" \t\n\r"); //trim only left end |
147 |
GStr& trimL(char c=' '); |
148 |
GStr& padR(int len, char c=' '); //align it in len spaces to the right |
149 |
GStr& padL(int len, char c=' '); //align it in len spaces to the left |
150 |
GStr& padC(int len, char c=' '); //center it |
151 |
size_t read(FILE* stream, const char* delimiter="\n", size_t bufsize=4096); |
152 |
//read next token from stream, using the given string as |
153 |
//a marker where the block should stop |
154 |
const char* chars() const; |
155 |
const char* text() const; |
156 |
protected: |
157 |
char* fTokenDelimiter; |
158 |
int fLastTokenStart; |
159 |
enTokenizeMode fTokenizeMode; |
160 |
void* readbuf; //file read buffer for the read() function |
161 |
size_t readbufsize; //last setting for the readbuf |
162 |
static void invalid_args_error(const char* fname); |
163 |
static void invalid_index_error(const char* fname); |
164 |
struct Data {//structure holding actual |
165 |
//string data and reference count information |
166 |
Data() { ref_count=0; length=0; chars[0] = '\0'; } |
167 |
unsigned int ref_count; |
168 |
int length; |
169 |
char chars[1]; |
170 |
}; |
171 |
static Data* new_data(int length); //alloc a specified length string's Data |
172 |
static Data* new_data(const char* str); //alloc a copy of a specified string |
173 |
void replace_data(int length); |
174 |
void replace_data(Data* data); |
175 |
void make_unique(); |
176 |
char* chrs(); // this is dangerous, length should not be affected |
177 |
static Data null_data; //a null (empty) string Data is available here |
178 |
Data* my_data; //pointer to a Data object holding actual string data |
179 |
}; |
180 |
|
181 |
/***************************************************************************/ |
182 |
|
183 |
inline int GStr::length() const { |
184 |
return my_data->length; |
185 |
} |
186 |
|
187 |
|
188 |
inline const char *GStr::chars() const { |
189 |
return my_data->chars; |
190 |
} |
191 |
|
192 |
inline char *GStr::chrs() { //protected version, allows modification of the chars |
193 |
return my_data->chars; |
194 |
} |
195 |
|
196 |
inline const char *GStr::text() const { |
197 |
return my_data->chars; |
198 |
} |
199 |
|
200 |
inline bool operator>=(const char *s1, const GStr& s2) { |
201 |
return (strcmp(s1, s2.chars()) >= 0); |
202 |
} |
203 |
|
204 |
inline bool operator!=(const char *s1, const GStr& s2) { |
205 |
return (strcmp(s1, s2.chars()) != 0); |
206 |
} |
207 |
|
208 |
inline void Gswap(GStr& s1, GStr& s2) { |
209 |
GStr::Data *tmp = s1.my_data; s1.my_data = s2.my_data; |
210 |
s2.my_data = tmp; |
211 |
} |
212 |
|
213 |
#endif |