1
2 /******************************************************************************
3 * MODULE : string.cpp
4 * DESCRIPTION: Fixed size strings with reference counting.
5 * Zero characters can be part of string.
6 * COPYRIGHT : (C) 1999 Joris van der Hoeven
7 *******************************************************************************
8 * This software falls under the GNU general public license version 3 or later.
9 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
10 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ******************************************************************************/
12
13 #include "string.hpp"
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17
18 /******************************************************************************
19 * Low level routines and constructors
20 ******************************************************************************/
21
22 static inline int
round_length(int n)23 round_length (int n) {
24 n=(n+3)&(0xfffffffc);
25 if (n<24) return n;
26 register int i=32;
27 while (n>i) i<<=1;
28 return i;
29 }
30
string_rep(int n2)31 string_rep::string_rep (int n2):
32 n(n2), a ((n==0)?((char*) NULL):tm_new_array<char> (round_length(n))) {}
33
34 void
resize(register int m)35 string_rep::resize (register int m) {
36 register int nn= round_length (n);
37 register int mm= round_length (m);
38 if (mm != nn) {
39 if (mm != 0) {
40 register int i, k= (m<n? m: n);
41 char* b= tm_new_array<char> (mm);
42 for (i=0; i<k; i++) b[i]= a[i];
43 if (nn != 0) tm_delete_array (a);
44 a= b;
45 }
46 else if (nn != 0) tm_delete_array (a);
47 }
48 n= m;
49 }
50
string(char c)51 string::string (char c) {
52 rep= tm_new<string_rep> (1);
53 rep->a[0]=c;
54 }
55
string(char c,int n)56 string::string (char c, int n) {
57 rep= tm_new<string_rep> (n);
58 for (int i=0; i<n; i++)
59 rep->a[i]=c;
60 }
61
string(const char * a)62 string::string (const char* a) {
63 int i, n=strlen(a);
64 rep= tm_new<string_rep> (n);
65 for (i=0; i<n; i++)
66 rep->a[i]=a[i];
67 }
68
string(const char * a,int n)69 string::string (const char* a, int n) {
70 register int i;
71 rep= tm_new<string_rep> (n);
72 for (i=0; i<n; i++)
73 rep->a[i]=a[i];
74 }
75
76 /******************************************************************************
77 * Common routines for strings
78 ******************************************************************************/
79
80 bool
operator ==(const char * s)81 string::operator == (const char* s) {
82 register int i, n= rep->n;
83 register char* S= rep->a;
84 for (i=0; i<n; i++) {
85 if (s[i]!=S[i]) return false;
86 if (s[i]=='\0') return false;
87 }
88 return (s[i]=='\0');
89 }
90
91 bool
operator !=(const char * s)92 string::operator != (const char* s) {
93 register int i, n= rep->n;
94 register char* S= rep->a;
95 for (i=0; i<n; i++) {
96 if (s[i]!=S[i]) return true;
97 if (s[i]=='\0') return true;
98 }
99 return (s[i]!='\0');
100 }
101
102 bool
operator ==(string a)103 string::operator == (string a) {
104 register int i;
105 if (rep->n!=a->n) return false;
106 for (i=0; i<rep->n; i++)
107 if (rep->a[i]!=a->a[i]) return false;
108 return true;
109 }
110
111 bool
operator !=(string a)112 string::operator != (string a) {
113 register int i;
114 if (rep->n!=a->n) return true;
115 for (i=0; i<rep->n; i++)
116 if (rep->a[i]!=a->a[i]) return true;
117 return false;
118 }
119
120 string
operator ()(int begin,int end)121 string::operator () (int begin, int end) {
122 register int i;
123 string r (end-begin);
124 for (i=begin; i<end; i++) r[i-begin]=rep->a[i];
125 return r;
126 }
127
128 string
copy(string s)129 copy (string s) {
130 register int i, n=N(s);
131 string r (n);
132 for (i=0; i<n; i++) r[i]=s[i];
133 return r;
134 }
135
136 string&
operator <<(string & a,char x)137 operator << (string& a, char x) {
138 a->resize (N(a)+ 1);
139 a [N(a)-1]=x;
140 return a;
141 }
142
143 string&
operator <<(string & a,string b)144 operator << (string& a, string b) {
145 register int i, k1= N(a), k2=N(b);
146 a->resize (k1+k2);
147 for (i=0; i<k2; i++) a[i+k1]= b[i];
148 return a;
149 }
150
151 string
operator *(string a,string b)152 operator * (string a, string b) {
153 register int i, n1=N(a), n2=N(b);
154 string c(n1+n2);
155 for (i=0; i<n1; i++) c[i]=a[i];
156 for (i=0; i<n2; i++) c[i+n1]=b[i];
157 return c;
158 }
159
160 string
operator *(const char * a,string b)161 operator * (const char* a, string b) {
162 return string (a) * b;
163 }
164
165 string
operator *(string a,const char * b)166 operator * (string a, const char* b) {
167 return a * string (b);
168 }
169
170 bool
operator <(string s1,string s2)171 operator < (string s1, string s2) {
172 register int i;
173 for (i=0; i<N(s1); i++) {
174 if (i>=N(s2)) return false;
175 if (s1[i]<s2[i]) return true;
176 if (s2[i]<s1[i]) return false;
177 }
178 return i<N(s2);
179 }
180
181 bool
operator <=(string s1,string s2)182 operator <= (string s1, string s2) {
183 register int i;
184 for (i=0; i<N(s1); i++) {
185 if (i>=N(s2)) return false;
186 if (s1[i]<s2[i]) return true;
187 if (s2[i]<s1[i]) return false;
188 }
189 return true;
190 }
191
192 tm_ostream&
operator <<(tm_ostream & out,string a)193 operator << (tm_ostream& out, string a) {
194 int i, n=N(a);
195 if (n==0) return out;
196 for (i=0; i<n; i++) out << a[i];
197 return out;
198 }
199
200 int
hash(string s)201 hash (string s) {
202 register int i, h=0, n=N(s);
203 for (i=0; i<n; i++) {
204 h=(h<<9)+(h>>23);
205 h=h+((int) s[i]);
206 }
207 return h;
208 }
209
210 /******************************************************************************
211 * Conversion routines
212 ******************************************************************************/
213
214 bool
as_bool(string s)215 as_bool (string s) {
216 return (s == "true" || s == "#t");
217 }
218
219 int
as_int(string s)220 as_int (string s) {
221 int i=0, n=N(s), val=0;
222 if (n==0) return 0;
223 if (s[0]=='-') i++;
224 while (i<n) {
225 if (s[i]<'0') break;
226 if (s[i]>'9') break;
227 val *= 10;
228 val += (int) (s[i]-'0');
229 i++;
230 }
231 if (s[0]=='-') val=-val;
232 return val;
233 }
234
235
236 long int
as_long_int(string s)237 as_long_int (string s) {
238 int i=0, n=N(s);
239 long int val=0;
240 if (n==0) return 0;
241 if (s[0]=='-') i++;
242 while (i<n) {
243 if (s[i]<'0') break;
244 if (s[i]>'9') break;
245 val *= 10;
246 val += (int) (s[i]-'0');
247 i++;
248 }
249 if (s[0]=='-') val=-val;
250 return val;
251 }
252
253 double
as_double(string s)254 as_double (string s) {
255 double x= 0.0;
256 {
257 int i, n= N(s);
258 STACK_NEW_ARRAY (buf, char, n+1);
259 for (i=0; i<n; i++) buf[i]=s[i];
260 buf[n]='\0';
261 sscanf (buf, "%lf", &x);
262 STACK_DELETE_ARRAY (buf);
263 } // in order to avoid segmentation fault due to compiler bug
264 return x;
265 }
266
267 char*
as_charp(string s)268 as_charp (string s) {
269 int i, n= N(s);
270 char *s2= tm_new_array<char> (n+1);
271 for (i=0; i<n; i++) s2[i]=s[i];
272 s2[n]= '\0';
273 return s2;
274 }
275
276 string
as_string_bool(bool f)277 as_string_bool (bool f) {
278 if (f) return string ("true");
279 else return string ("false");
280 }
281
282 string
as_string(int i)283 as_string (int i) {
284 char buf[64];
285 sprintf (buf, "%i", i);
286 // sprintf (buf, "%i\0", i);
287 return string (buf);
288 }
289
290 string
as_string(unsigned int i)291 as_string (unsigned int i) {
292 char buf[64];
293 sprintf (buf, "%u", i);
294 // sprintf (buf, "%u\0", i);
295 return string (buf);
296 }
297
298 string
as_string(long int i)299 as_string (long int i) {
300 char buf[64];
301 sprintf (buf, "%li", i);
302 // sprintf (buf, "%li\0", i);
303 return string (buf);
304 }
305
306 string
as_string(long long int i)307 as_string (long long int i) {
308 char buf[64];
309 #if defined (__MINGW__) || defined (__MINGW32__)
310 sprintf (buf, "%I64d", i);
311 #else
312 sprintf (buf, "%lli", i);
313 #endif
314 // sprintf (buf, "%lli\0", i);
315 return string (buf);
316 }
317
318 string
as_string(unsigned long int i)319 as_string (unsigned long int i) {
320 char buf[64];
321 sprintf (buf, "%lu", i);
322 // sprintf (buf, "%lu\0", i);
323 return string (buf);
324 }
325
326 string
as_string(double x)327 as_string (double x) {
328 char buf[64];
329 sprintf (buf, "%g", x);
330 // sprintf (buf, "%g\0", x);
331 return string(buf);
332 }
333
334 string
as_string(const char * s)335 as_string (const char* s) {
336 return string (s);
337 }
338
339 bool
is_bool(string s)340 is_bool (string s) {
341 return (s == "true") || (s == "false");
342 }
343
344 bool
is_int(string s)345 is_int (string s) {
346 int i=0, n=N(s);
347 if (n==0) return false;
348 if (s[i]=='+') i++;
349 if (s[i]=='-') i++;
350 if (i==n) return false;
351 for (; i<n; i++)
352 if ((s[i]<'0') || (s[i]>'9')) return false;
353 return true;
354 }
355
356 bool
is_double(string s)357 is_double (string s) {
358 int i=0, n=N(s);
359 if (n==0) return false;
360 if (s[i]=='+') i++;
361 if (s[i]=='-') i++;
362 if (i==n) return false;
363 for (; i< n; i++)
364 if ((s[i]<'0') || (s[i]>'9')) break;
365 if (i==n) return true;
366 if (s[i]=='.') {
367 i++;
368 if (i==n) return false;
369 for (; i< n; i++)
370 if ((s[i]<'0') || (s[i]>'9')) break;
371 }
372 if (i==n) return true;
373 if (s[i++]!='e') return false;
374 if (s[i]=='+') i++;
375 if (s[i]=='-') i++;
376 if (i==n) return false;
377 for (; i< n; i++)
378 if ((s[i]<'0') || (s[i]>'9')) return false;
379 return true;
380 }
381
382 bool
is_charp(string s)383 is_charp (string s) { (void) s;
384 return true;
385 }
386
387 bool
is_quoted(string s)388 is_quoted (string s) {
389 return (N(s)>=2) && (s[0]=='\042') && (s[N(s)-1]=='\042');
390 }
391
392 bool
is_id(string s)393 is_id (string s) {
394 int i=0, n=N(s);
395 if (n==0) return false;
396 for (i=0; i< n; i++) {
397 if ((i>0) && (s[i]>='0') && (s[i]<='9')) continue;
398 if ((s[i]>='a') && (s[i]<='z')) continue;
399 if ((s[i]>='A') && (s[i]<='Z')) continue;
400 if (s[i]=='_') continue;
401 return false;
402 }
403 return true;
404 }
405
406 /******************************************************************************
407 * Error messages
408 ******************************************************************************/
409
410 static void (*the_wait_handler) (string, string, int) = NULL;
411
412 void
set_wait_handler(void (* routine)(string,string,int))413 set_wait_handler (void (*routine) (string, string, int)) {
414 the_wait_handler= routine; }
415
416 void
system_wait(string message,string argument,int level)417 system_wait (string message, string argument, int level) {
418 if (the_wait_handler == NULL) {
419 if (DEBUG_AUTO) {
420 if (message == "") cout << "TeXmacs] Done" << LF;
421 else {
422 if (argument == "") cout << "TeXmacs] " << message << LF;
423 else cout << "TeXmacs] " << message << " " << argument << LF;
424 cout << "TeXmacs] Please wait..." << LF;
425 }
426 }
427 }
428 else the_wait_handler (message, argument, level);
429 }
430