1 //////////////////////////////////////////////////////////////////////////////
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are free to incorporate any part of ADLib and Prop into
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
18 // This software is still under development and we welcome any suggestions
19 // and help from the users.
23 //////////////////////////////////////////////////////////////////////////////
29 #include <AD/strings/string.h>
32 ////////////////////////////////////////////////////////////////////////////
34 ////////////////////////////////////////////////////////////////////////////
36 ////////////////////////////////////////////////////////////////////
38 ////////////////////////////////////////////////////////////////////
39 int SubString::contains (RegExp
& regexp
) const
40 { return regexp
.Match(get_string(),len
); }
42 int SubString::contains (char c
) const
43 { /* const char * r = (const char *)memchr(get_string(),c,len);
44 return r ? r - get_string() : -1;
49 int SubString::contains (const char *, int) const
54 int SubString::contains (const String
&) const
59 int SubString::contains (const SubString
&) const
64 ////////////////////////////////////////////////////////////////////////////
66 ////////////////////////////////////////////////////////////////////////////
68 void String::out_of_bounds(int i
) const // error handler
69 { std::cerr
<< "[Attempting to index location " << i
<< " of string: "
74 ////////////////////////////////////////////////////////////////////////////
76 ////////////////////////////////////////////////////////////////////////////
77 String::String(int initial_capacity
)
78 { if (initial_capacity
> 0) {
79 string
= new char [cap
= initial_capacity
];
80 len
= initial_capacity
; string
[len
] = '\0';
81 } else { string
= 0; len
= 0; cap
= 0; }
84 String::String(char c
, int times
)
86 string
= new char [cap
= (len
= times
) + 1];
87 memset(string
,c
,len
); string
[len
] = '\0';
88 } else { string
= 0; len
= 0; cap
= 0; }
91 String::String(const char * s
)
93 string
= new char [cap
= (len
= strlen(s
)) + 1];
94 memcpy(string
,s
,len
); string
[len
] = '\0';
95 } else { string
= 0; len
= cap
= 0; }
98 String::String(const char * s
, int l
)
100 string
= new char [cap
= (len
= l
) + 1];
101 memcpy(string
,s
,len
); string
[len
] = '\0';
102 } else { string
= 0; len
= cap
= 0; }
105 String::String(const String
& s
)
106 { string
= new char [cap
= (len
= s
.len
) + 1];
107 memcpy(string
,s
.string
,len
);
110 ///////////////////////////////////////////////////////////////////////
112 ///////////////////////////////////////////////////////////////////////
113 void String::grow(long new_len
)
114 { cap
= new_len
* 3 / 2 + 1;
115 char * new_string
= new char [cap
];
116 memcpy(new_string
,string
,len
);
117 delete [] string
; string
= new_string
;
120 ///////////////////////////////////////////////////////////////////////
122 ///////////////////////////////////////////////////////////////////////
123 String
& String::operator = (const String
& s
)
125 if (s
.len
>= cap
) grow(s
.len
);
126 memcpy(string
,s
.string
,len
= s
.len
);
132 String
& String::operator = (const char * s
)
133 { if (s
== 0) len
= 0;
136 if (l
>= cap
) grow(l
);
143 String
& String::operator = (const SubString
& s
)
144 { if (s
.length() >= cap
) grow(s
.length());
145 memcpy(string
, s
.get_string(), len
= s
.length());
150 ////////////////////////////////////////////////////////////////////
152 ////////////////////////////////////////////////////////////////////
153 String
& String::splice(int location
, int kill_len
, const char * s
, int size
)
154 { if (size
< 0) size
= s
? strlen(s
) : 0;
155 if (kill_len
< 0) kill_len
= 0;
156 if (location
+ kill_len
>= len
) kill_len
= len
- location
;
157 int new_len
= len
- kill_len
+ size
;
158 if (new_len
>= cap
) grow(new_len
);
159 if (kill_len
> size
) { // shrink string
160 register char * p
, * q
;
161 register int n
= len
- location
+ kill_len
;
162 for (p
= string
+ location
, q
= p
+ kill_len
- size
; n
> 0; n
--)
164 } else if (kill_len
< size
) { // expand string
165 register char * p
, * q
;
166 register int n
= len
- location
+ kill_len
;
167 for (p
= string
+ location
+ n
- 1, q
= p
+ size
- kill_len
+ n
- 1;
171 len
= new_len
; string
[len
] = '\0';
172 memcpy(string
+ location
, s
, size
); // now copy substring
176 ///////////////////////////////////////////////////////////////////////
178 ///////////////////////////////////////////////////////////////////////
179 String
operator + (const String
& a
, const String
& b
)
180 { String
r((int)(a
.len
+ b
.len
));
181 memcpy(r
.string
, a
.string
, a
.len
);
182 memcpy(r
.string
+ a
.len
, b
.string
, b
.len
);
185 String
operator + (const String
& a
, const char * b
)
186 { String
r((int)(a
.len
+ strlen(b
)));
187 memcpy(r
.string
, a
.string
, a
.len
);
188 strcpy(r
.string
+ a
.len
, b
);
192 String
operator + (const String
& a
, char c
)
193 { String
r((int)(a
.len
+ 1));
194 memcpy(r
.string
, a
.string
, a
.len
);
199 String
operator + (const char * a
, const String
& b
)
200 { int a_len
= strlen(a
);
201 String
r((int)(a_len
+ b
.len
));
202 memcpy(r
.string
, a
, a_len
);
203 memcpy(r
.string
+ a_len
, b
.string
, b
.len
);
207 String
operator + (char c
, const String
& s
)
208 { String
r((int)(s
.len
+ 1));
210 memcpy(r
.string
+ 1, s
.string
, s
.len
);
214 ///////////////////////////////////////////////////////////////////////
216 ///////////////////////////////////////////////////////////////////////
217 String
operator * (const String
& s
, int n
)
218 { String
r(s
.length() * n
);
220 for (p
= r
.string
; n
> 0; p
+= s
.length())
221 memcpy(p
, s
.string
, s
.length());
226 String
operator * (const SubString
& s
, int n
)
227 { return String(s
) * n
; }
229 ///////////////////////////////////////////////////////////////////////
231 ///////////////////////////////////////////////////////////////////////
232 String
& String::operator += (const String
& s
)
233 { int new_len
= s
.len
+ len
;
234 if (new_len
>= cap
) grow(new_len
);
235 memcpy(string
+ len
, s
.string
, s
.len
);
236 len
= new_len
; string
[len
] = '\0';
240 String
& String::operator += (const char * s
)
242 int s_len
= strlen(s
);
243 int new_len
= s_len
+ len
;
244 if (new_len
>= cap
) grow(new_len
);
245 memcpy(string
+ len
, s
, s_len
);
246 len
= new_len
; string
[len
] = '\0';
251 String
& String::operator += (char c
)
252 { if (len
+ 1 >= cap
) grow(len
+ 1);
258 ///////////////////////////////////////////////////////////////////////
260 ///////////////////////////////////////////////////////////////////////
261 int String::compare (const String
& s
) const
262 { register const char * p
, * q
;
263 register int n
= len
< s
.len
? len
: s
.len
;
264 for (p
= string
, q
= s
.string
; n
> 0; n
--, p
++, q
++)
265 if (*p
- *q
) return *p
- *q
;
269 int String::compare (const SubString
& s
) const
270 { int l
= len
< s
.len
? len
: s
.len
;
271 int r
= memcmp(string
,s
.S
.string
+ s
.start
, l
);
276 int String::compare (const char * s
, int l
) const
277 { register const char * p
, * q
;
278 if (l
< 0) l
= strlen(s
);
279 register int n
= len
< l
? len
: l
;
280 for (p
= string
, q
= s
; n
> 0; n
--, p
++, q
++)
281 if (*p
- *q
) return *p
- *q
;
285 int String::case_insensitive_compare (const String
& s
) const
286 { return case_insensitive_compare(s
.string
, s
.len
); }
288 int String::case_insensitive_compare (const SubString
& s
) const
289 { return case_insensitive_compare(s
.get_string(), s
.len
); }
291 int String::case_insensitive_compare (const char * s
, int l
) const
292 { register const char * p
, * q
;
293 register int i
= len
< l
? len
: l
;
294 for (p
= string
, q
= s
; i
> 0; i
--, p
++, q
++)
295 if (tolower(*p
) - tolower(*q
))
296 return tolower(*p
) - tolower(*q
);
297 return tolower(*p
) - tolower(*q
);
300 int String::collate (const String
&) const
303 int String::collate (const SubString
&) const
306 int String::collate (const char *, int) const
309 ///////////////////////////////////////////////////////////////////////
310 // In place operations
311 ///////////////////////////////////////////////////////////////////////
312 String
& String::to_upper()
313 { register char * p
, * q
;
314 for (p
= string
, q
= string
+ len
; p
< q
; p
++)
319 String
& String::to_lower()
320 { register char * p
, * q
;
321 for (p
= string
, q
= string
+ len
; p
< q
; p
++)
326 String
& String::trunc(int length
)
327 { if (length
>= 0 && length
< len
) {
328 len
= length
; string
[len
] = '\0';
333 ///////////////////////////////////////////////////////////////////////
335 ///////////////////////////////////////////////////////////////////////
336 int String::contains (RegExp
& regexp
) const
337 { return regexp
.Match(string
,len
); }
339 int String::contains (char c
) const
340 { const char * r
= strchr(string
,c
);
341 return r
? r
- string
: -1;
344 int String::contains (const char * s
, int) const
345 { const char * r
= strstr(string
,s
);
346 return r
? r
- string
: -1;
349 int String::contains (const String
& s
) const
350 { const char * r
= strstr(string
,s
.string
);
351 return r
? r
- string
: -1;
354 int String::contains (const SubString
&) const
357 ///////////////////////////////////////////////////////////////////////
359 ///////////////////////////////////////////////////////////////////////
360 std::istream
& operator >> (std::istream
& in
, String
&)