00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <basix/string.hpp>
00014 #include <basix/vector.hpp>
00015 #include <string.h>
00016 namespace mmx {
00017
00018
00019
00020
00021
00022 string::string (char c) {
00023 rep= new string_rep(1);
00024 rep->a[0]=c;
00025 }
00026
00027 string::string (const char *a) {
00028 register nat i, n=strlen(a);
00029 rep= new string_rep(n);
00030 for (i=0; i<n; i++)
00031 rep->a[i]=a[i];
00032 }
00033
00034 string::string (const char* a, nat n) {
00035 register nat i;
00036 rep= new string_rep(n);
00037 for (i=0; i<n; i++)
00038 rep->a[i]=a[i];
00039 }
00040
00041 void
00042 string_rep::resize (nat n2) {
00043 nat l2;
00044 if (n2 > l) l2= max (n2, l << 1);
00045 else if (n2 < (l >> 1)) l2= n2;
00046 else { n= n2; return; }
00047 nat m= min (n, n2);
00048 char* b= (char*) mmx_malloc (l2);
00049 for (nat i=0; i<m; i++) b[i]= a[i];
00050 mmx_free ((void*) a, l);
00051 a= b;
00052 n= n2;
00053 l= l2;
00054 }
00055
00056
00057
00058
00059
00060 nat
00061 hash (const string& s) {
00062 register const char* a= S(s);
00063 register nat i, h=0, n= N(s);
00064 for (i=0; i<n; i++)
00065 h= (h<<1) ^ (h<<9) ^ (h>>23) ^ ((nat) a[i]);
00066 return h;
00067 }
00068
00069
00070
00071
00072
00073 char*
00074 as_charp (const string& s) {
00075 nat i, n= N(s);
00076 char* r= (char*) mmx_malloc (n+1);
00077 for (i=0; i<n; i++) r[i]= s[i];
00078 r[i]= '\0';
00079 return r;
00080 }
00081
00082 void
00083 free_charp (char* s) {
00084 mmx_free (s, strlen (s) + 1);
00085 }
00086
00087 string
00088 as_string (void* ptr) {
00089 char buffer[100];
00090 sprintf (buffer, "0x%lx", (unsigned long) ptr);
00091 return string (buffer);
00092 }
00093
00094 string
00095 as_string (int i) {
00096 char buffer[100];
00097 sprintf (buffer, "%d", i);
00098 return string (buffer);
00099 }
00100
00101 string
00102 as_string (unsigned int i) {
00103 char buffer[100];
00104 sprintf (buffer, "%u", i);
00105 return string (buffer);
00106 }
00107
00108 string
00109 as_string (long int i) {
00110 char buffer[100];
00111 sprintf (buffer, "%ld", i);
00112 return string (buffer);
00113 }
00114
00115 string
00116 as_string (long unsigned int i) {
00117 char buffer[100];
00118 sprintf (buffer, "%lu", i);
00119 return string (buffer);
00120 }
00121
00122 string
00123 as_string (long long int i) {
00124 char buffer[100];
00125 sprintf (buffer, "%lld", i);
00126 return string (buffer);
00127 }
00128
00129 string
00130 as_string (long long unsigned int i) {
00131 char buffer[100];
00132 sprintf (buffer, "%llu", i);
00133 return string (buffer);
00134 }
00135
00136 int
00137 as_int (const string& s) {
00138 int i=0, n=N(s), val=0;
00139 if (n==0) return 0;
00140 if (s[0]=='-') i++;
00141 while (i<n) {
00142 if (s[i]<'0') break;
00143 if (s[i]>'9') break;
00144 val *= 10;
00145 val += (int) (s[i]-'0');
00146 i++;
00147 }
00148 if (s[0]=='-') val=-val;
00149 return val;
00150 }
00151
00152 string
00153 as_string (float x) {
00154 if (x == 0.0) return "0";
00155 char buffer[32];
00156 sprintf (buffer, "%1.3e", x);
00157 return string (buffer);
00158 }
00159
00160 string (*as_string_hook) (double x)= NULL;
00161
00162 string
00163 as_string (double x) {
00164 if (as_string_hook != NULL)
00165 return as_string_hook (x);
00166 if (x == 0.0) return "0";
00167 char buffer[32];
00168 sprintf (buffer, "%1.12g", x);
00169 return string (buffer);
00170 }
00171
00172 string
00173 as_string (long double x) {
00174 char buffer[64];
00175 sprintf (buffer, "%Lf", x);
00176 return string (buffer);
00177 }
00178
00179 double
00180 as_double (const string& s) {
00181 double x;
00182 char buffer[100];
00183 strncpy (buffer, s->a, 99);
00184 buffer[max(N(s),(nat) 99)]= '\0';
00185 sscanf (buffer, "%lf", &x);
00186 return x;
00187 }
00188
00189
00190
00191
00192
00193 bool
00194 is_integer_string (const string& s) {
00195 nat i= 0, n= N(s);
00196 if (i < n && s[i] == '-') i++;
00197 if (i == n) return false;
00198 while (i < n && s[i] >= '0' && s[i] <= '9') i++;
00199 return i == n;
00200 }
00201
00202 bool
00203 is_floating_string (const string& s) {
00204 nat i= 0, n= N(s);
00205 if (i < n && s[i] == '-') i++;
00206 if (i >= n || s[i] < '0' || s[i] > '9') return false;
00207 while (i < n && s[i] >= '0' && s[i] <= '9') i++;
00208 if (i >= n || s[i] != '.') return false;
00209 i++;
00210 while (i < n && s[i] >= '0' && s[i] <= '9') i++;
00211 if (i < n && (s[i] == 'e' || s[i] == 'E')) {
00212 i++;
00213 if (i < n && s[i] == '-') i++;
00214 while (i < n && s[i] >= '0' && s[i] <= '9') i++;
00215 }
00216 return i == n;
00217 }
00218
00219 template<typename C> inline void
00220 floating_to_string (const C& val, string& s, const char* fm) {
00221 char buffer[40];
00222 sprintf (buffer, fm, val);
00223 s << string (buffer);
00224 }
00225
00226 template<typename C> inline void
00227 string_to_floating (const string& s, C& val, const char* fm) {
00228 nat n= max (N(s), (nat) 39);
00229 char buffer[40];
00230 strncpy (buffer, inside (s, 0), n);
00231 buffer [n]= '\0';
00232 sscanf (buffer, fm, &val);
00233 }
00234
00235 STMPL void numeric_to_string (const float& x, string& s) {
00236 floating_to_string (x, s, "%1.8e"); }
00237 STMPL void numeric_to_string (const double& x, string& s) {
00238 floating_to_string (x, s, "%1.17le"); }
00239 STMPL void numeric_to_string (const long double& x, string& s) {
00240 floating_to_string (x, s, "%1.21Le"); }
00241 STMPL bool string_to_numeric (const string& s, float& x) {
00242 string_to_floating (s, x, "%f");
00243 return is_floating_string (s); }
00244 STMPL bool string_to_numeric (const string& s, double& x) {
00245 string_to_floating (s, x, "%lf");
00246 return is_floating_string (s); }
00247 STMPL bool string_to_numeric (const string& s, long double& x) {
00248 string_to_floating (s, x, "%Lf");
00249 return is_floating_string (s); }
00250
00251
00252
00253
00254
00255 bool
00256 string::operator == (const char* s) const {
00257 register nat i, n= rep->n;
00258 register char* S= rep->a;
00259 for (i=0; i<n; i++) {
00260 if (s[i]!=S[i]) return false;
00261 if (s[i]=='\0') return false;
00262 }
00263 return (s[i]=='\0');
00264 }
00265
00266 bool
00267 string::operator == (const string& s) const {
00268 register nat i;
00269 if (rep->n != s.rep->n) return false;
00270 for (i=0; i<rep->n; i++)
00271 if (rep->a[i] != s.rep->a[i]) return false;
00272 return true;
00273 }
00274
00275 bool
00276 string::operator != (const char* s) const {
00277 register nat i, n= rep->n;
00278 register char* S= rep->a;
00279 for (i=0; i<n; i++) {
00280 if (s[i]!=S[i]) return true;
00281 if (s[i]=='\0') return true;
00282 }
00283 return (s[i]!='\0');
00284 }
00285
00286 bool
00287 string::operator != (const string& s) const {
00288 register nat i;
00289 if (rep->n != s.rep->n) return true;
00290 for (i=0; i<rep->n; i++)
00291 if (rep->a[i] != s.rep->a[i]) return true;
00292 return false;
00293 }
00294
00295 bool
00296 operator < (const string& s1, const string& s2) {
00297 register nat i;
00298 for (i=0; i<N(s1); i++) {
00299 if (i >= N(s2)) return false;
00300 if (s1[i] < s2[i]) return true;
00301 if (s2[i] < s1[i]) return false;
00302 }
00303 return false;
00304 }
00305
00306 bool
00307 operator <= (const string& s1, const string& s2) {
00308 register nat i;
00309 for (i=0; i<N(s1); i++) {
00310 if (i >= N(s2)) return false;
00311 if (s1[i] < s2[i]) return true;
00312 if (s2[i] < s1[i]) return false;
00313 }
00314 return true;
00315 }
00316
00317 bool
00318 operator > (const string& s1, const string& s2) {
00319 register nat i;
00320 for (i=0; i<N(s1); i++) {
00321 if (i >= N(s2)) return true;
00322 if (s1[i] > s2[i]) return true;
00323 if (s2[i] > s1[i]) return false;
00324 }
00325 return false;
00326 }
00327
00328 bool
00329 operator >= (const string& s1, const string& s2) {
00330 register nat i;
00331 for (i=0; i<N(s1); i++) {
00332 if (i >= N(s2)) return true;
00333 if (s1[i] > s2[i]) return true;
00334 if (s2[i] > s1[i]) return false;
00335 }
00336 return true;
00337 }
00338
00339
00340
00341
00342
00343 bool
00344 starts (const string& s, const string& what) {
00345 return N(s) >= N(what) && s (0, N(what)) == what;
00346 }
00347
00348 bool
00349 ends (const string& s, const string& what) {
00350 return N(s) >= N(what) && s (N(s) - N(what), N(s)) == what;
00351 }
00352
00353 string
00354 string::operator () (nat i1, nat i2) const {
00355 register nat i;
00356 string r (i2-i1);
00357 for (i=i1; i<i2; i++) r.rep->a[i-i1]= rep->a[i];
00358 return r;
00359 }
00360
00361 string
00362 copy (const string& s) {
00363 register nat i, n= N(s);
00364 string r (n);
00365 for (i=0; i<n; i++) r.rep->a[i]= s.rep->a[i];
00366 return r;
00367 }
00368
00369 void
00370 string_rep::extend (nat d) {
00371 if (n+d > l) {
00372 register nat old_l= l;
00373 l= max (l << 1, n+d);
00374 char* b= (char*) mmx_malloc (l);
00375 for (nat i=0; i<n; i++)
00376 b[i]= a[i];
00377 mmx_free ((void*) a, old_l);
00378 a= b;
00379 }
00380 n += d;
00381 }
00382
00383 string&
00384 string::operator << (char x) {
00385 secure ();
00386 rep->extend (1);
00387 rep->a[rep->n-1]= x;
00388 return *this;
00389 }
00390
00391 string&
00392 string::operator << (const string& s) {
00393 register nat i, k1= rep->n, k2=N(s);
00394 secure ();
00395 rep->extend (k2);
00396 for (i=0; i<k2; i++)
00397 rep->a[i+k1]= s.rep->a[i];
00398 return *this;
00399 }
00400
00401 string&
00402 string::operator >> (char& x) {
00403 ASSERT (rep->n != 0, "non empty string expected");
00404 secure ();
00405 x= rep->a[rep->n-1];
00406 rep->resize (rep->n-1);
00407 return *this;
00408 }
00409
00410 string
00411 operator * (const string& s1, const string& s2) {
00412 register nat i, n1=N(s1), n2=N(s2);
00413 string r (n1 + n2);
00414 for (i=0; i<n1; i++) r.rep->a[i ]= s1.rep->a[i];
00415 for (i=0; i<n2; i++) r.rep->a[i+n1]= s2.rep->a[i];
00416 return r;
00417 }
00418
00419
00420
00421
00422
00423 static bool
00424 is_locase (register char c) {
00425 int code= (int) ((unsigned char) c);
00426 return
00427 ((c>='a') && (c<='z')) ||
00428 ((code >= 160) && (code < 189)) ||
00429 (code >= 224);
00430 }
00431
00432 static bool
00433 is_upcase (register char c) {
00434 int code= (int) ((unsigned char) c);
00435 return
00436 ((c>='A') && (c<='Z')) ||
00437 ((code >= 128) && (code < 159)) ||
00438 ((code >= 192) && (code < 224));
00439 }
00440
00441 string
00442 upcase (const string& s) {
00443 nat i, n= N(s);
00444 string r (n);
00445 for (i=0; i<n; i++)
00446 if (!is_locase (s[i])) r[i]= s[i];
00447 else r[i]= (char) (((int) ((unsigned char) s[i]))-32);
00448 return r;
00449 }
00450
00451 string
00452 locase (const string& s) {
00453 nat i, n= N(s);
00454 string r (n);
00455 for (i=0; i<n; i++)
00456 if (!is_upcase (s[i])) r[i]= s[i];
00457 else r[i]= (char) (((int) ((unsigned char) s[i]))+32);
00458 return r;
00459 }
00460
00461 string
00462 upcase_first (const string& s) {
00463 string r= copy (s);
00464 if (N(r) != 0 && is_locase (s[0]))
00465 r[0]= (char) (((int) ((unsigned char) s[0]))-32);
00466 return r;
00467 }
00468
00469 string
00470 locase_first (const string& s) {
00471 string r= copy (s);
00472 if (N(r) != 0 && is_upcase (s[0]))
00473 r[0]= (char) (((int) ((unsigned char) s[0]))+32);
00474 return r;
00475 }
00476
00477 string
00478 escape (const string& s) {
00479 int i, n= N(s);
00480 string r;
00481 for (i=0; i<n; i++)
00482 if ((s[i] == '\\') || (s[i] == '\"')) r << '\\' << s[i];
00483 else if (s[i] == '\b') r << "\\b";
00484 else if (s[i] == '\t') r << "\\t";
00485 else if (s[i] == '\n') r << "\\n";
00486 else if (s[i] == '\r') r << "\\r";
00487 else r << s[i];
00488 return r;
00489 }
00490
00491 string
00492 unescape (const string& s) {
00493 int i, n= N(s);
00494 string r;
00495 for (i=0; i<n; i++)
00496 if ((i+1<n) && (s[i] == '\\')) {
00497 i++;
00498 if (s[i] == 't') r << '\t';
00499 else if (s[i] == 'n') r << '\n';
00500 else if (s[i] == 'r') r << '\r';
00501 else if (s[i] == 'b') {
00502 if (N(r)>0)
00503 r.rep->resize (N(r)-1);
00504 }
00505 else r << s[i];
00506 }
00507 else r << s[i];
00508 return r;
00509 }
00510
00511 bool
00512 is_quoted (const string& s) {
00513 nat i, n= N(s);
00514 if (n < 2) return false;
00515 if (s[0] == '\"' && s[n-1] == '\"') {
00516 for (i=1; i<n-1; i++)
00517 if (s[i] == '\\') i++;
00518 else if (s[i] == '\"') return false;
00519 return i == n-1;
00520 }
00521 if (s[0] == '/' && s[1] == '\"' && s[n-2] == '\"' && s[n-1] == '/') {
00522 for (i=2; i<n-2; i++)
00523 if (s[i] == '\"' && s[i+1] == '/') return false;
00524 return i == n-2;
00525 }
00526 return false;
00527 }
00528
00529 string
00530 quote (const string& s) {
00531 return "\"" * escape (s) * "\"";
00532 }
00533
00534 string
00535 unquote (const string& s) {
00536 if ((N(s) >= 2) && (s[0] == '\"') && (s[N(s)-1] == '\"'))
00537 return unescape (s (1, N(s)-1));
00538 else if (starts (s, "/\"") && ends (s, "\"/"))
00539 return s (2, N(s)-2);
00540 else return unescape (s);
00541 }
00542
00543
00544
00545
00546
00547 static bool
00548 reads (const string& s, nat pos, const string& what) {
00549 nat i, n= N(s), l= N(what);
00550 for (i=0; pos+i<n && i<l; i++)
00551 if (s[pos+i] != what[i]) return false;
00552 return i == l;
00553 }
00554
00555 string
00556 replace (const string& s, const string& what, const string& by) {
00557 nat i, n= N(s);
00558 string r;
00559 for (i=0; i<n; )
00560 if (reads (s, i, what)) { r << by; i += N(what); }
00561 else r << s[i++];
00562 return r;
00563 }
00564
00565 int
00566 search_forwards (const string& s, const string& what, const int& pos) {
00567 for (nat i= pos; i + N(what) <= N(s); i++)
00568 if (reads (s, i, what)) return i;
00569 return -1;
00570 }
00571
00572 int
00573 search_backwards (const string& s, const string& what, const int& pos) {
00574 for (int i= pos - N(what); i >= 0; i--)
00575 if (reads (s, i, what)) return i;
00576 return -1;
00577 }
00578
00579 string
00580 reverse (const string& s) {
00581 nat i, n= N(s);
00582 string r (n);
00583 for (i=0; i<n; i++) r[i]= s[n-1-i];
00584 return r;
00585 }
00586
00587
00588
00589
00590
00591 vector<string>
00592 tokenize (const string& s, const string& sep, bool keep) {
00593 ASSERT (N(sep) != 0, "separator should be non-empty");
00594 vector<string> v;
00595 nat start= 0;
00596 while (start < N(s)) {
00597 nat end= start;
00598 while (end < N(s) &&
00599 (s[end] != sep[0] || s (end, min (N(s), end + N(sep))) != sep))
00600 end++;
00601 if (keep) v << (s (start, end) * sep);
00602 else v << s (start, end);
00603 start= end + N(sep);
00604 }
00605 return v;
00606 }
00607
00608 string
00609 recompose (const vector<string>& v, const string& sep, bool last) {
00610 string s;
00611 for (nat i=0; i<N(v); i++) {
00612 s << v[i];
00613 if (i+1 < N(v) || last) s << sep;
00614 }
00615 return s;
00616 }
00617
00618
00619
00620
00621
00622 string
00623 repeated (const string& s, nat n) {
00624 string r;
00625 for (nat i=0; i<n; i++) r << s;
00626 return r;
00627 }
00628
00629 nat
00630 get_indentation (const string& s) {
00631 if (N(s) == 0) return 0;
00632 vector<string> v= tokenize (s, "\n");
00633 nat r= ((nat) -1);
00634 for (nat y=0; y<N(v); y++)
00635 for (nat x=0; x<N(v[y]); x++)
00636 if (v[y][x] != ' ') {
00637 r= min (r, x);
00638 break;
00639 }
00640 return r;
00641 }
00642
00643 string
00644 add_indentation (const string& s, int delta) {
00645 if (delta == 0) return s;
00646 vector<string> v= tokenize (s, "\n");
00647 for (nat i=0; i<N(v); i++)
00648 if (delta > 0) v[i]= repeated (" ", delta) * v[i];
00649 else {
00650 int l= min (-delta, (int) N(v[i]));
00651 ASSERT (v[i] (0, l) == repeated (" ", l), "insufficient indentation");
00652 v[i]= v[i] (l, N(v[i]));
00653 }
00654 return recompose (v, "\n", N(s) != 0 && s[N(s) - 1] == '\n');
00655 }
00656
00657 }