summaryrefslogtreecommitdiff
path: root/appl/lib/string.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2007-09-06 15:37:43 +0000
committerCharles.Forsyth <devnull@localhost>2007-09-06 15:37:43 +0000
commita584e84874abd077df5ee1f3687f84d9d4fc3bfa (patch)
tree506bd77b52dfb953acf3ac1bf55f77826675085a /appl/lib/string.b
parent06965d10d9199bef760049aa302caf8c1c77e96f (diff)
20070906-1636
Diffstat (limited to 'appl/lib/string.b')
-rw-r--r--appl/lib/string.b243
1 files changed, 156 insertions, 87 deletions
diff --git a/appl/lib/string.b b/appl/lib/string.b
index 16bc1940..fb123f7e 100644
--- a/appl/lib/string.b
+++ b/appl/lib/string.b
@@ -1,4 +1,5 @@
implement String;
+
include "string.m";
splitl(s: string, cl: string): (string, string)
@@ -112,61 +113,56 @@ splitstrr(s: string, t: string): (string, string)
prefix(pre: string, s: string): int
{
- ns := len s;
- n := len pre;
- if(ns < n)
+ if(len s < len pre)
return 0;
- for(k := 0; k < n; k++) {
+ for(k := 0; k < len pre; k++)
if(pre[k] != s[k])
return 0;
- }
return 1;
}
tolower(s: string): string
{
- r := s;
- for(i := 0; i < len r; i++) {
- c := r[i];
- if(c >= int 'A' && c <= int 'Z')
- r[i] = r[i] + (int 'a' - int 'A');
+ for(i := 0; i < len s; i++) {
+ c := s[i];
+ if(c >= 'A' && c <= 'Z')
+ s[i] += 'a' - 'A';
}
- return r;
+ return s;
}
toupper(s: string): string
{
- r := s;
- for(i := 0; i < len r; i++) {
- c := r[i];
- if(c >= int 'a' && c <= int 'z')
- r[i] = r[i] - (int 'a' - int 'A');
+ for(i := 0; i < len s; i++) {
+ c := s[i];
+ if(c >= 'a' && c <= 'z')
+ s[i] += 'A' - 'a';
}
- return r;
+ return s;
}
-tobig(s: string, base: int): (big, string)
+startnum(s: string, base: int): (int, int, int)
{
- if (s == nil || base < 0 || base > 36 || base == 1)
- return (big 0, s);
+ if(s == nil || base != 0 && (base < 2 || base > 36))
+ return (0, 0, 0);
# skip possible leading white space
- c: int;
+ c := ' ';
for (i := 0; i < len s; i++) {
c = s[i];
if(c != ' ' && c != '\t' && c != '\n')
break;
}
- # skip possible sign character
+ # optional sign
neg := 0;
- if (c == '-' || c == '+') {
+ if(c == '-' || c == '+') {
if(c == '-')
neg = 1;
i++;
}
- if (base == 0) {
+ if(base == 0) {
# parse possible leading base designator
start := i;
base = -1;
@@ -183,26 +179,30 @@ tobig(s: string, base: int): (big, string)
i = start;
base = 10;
} else if (base == 0 || base > 36)
- return (big 0, s);
+ return (0, 0, i);
}
+ if(i >= len s)
+ return (0, 0, 0);
+
+ return (base, neg, i);
+}
+
+tobig(s: string, base: int): (big, string)
+{
+ neg, i: int;
+
+ (base, neg, i) = startnum(s, base);
+ if(base == 0)
+ return (big 0, s);
# parse number itself.
- # perhaps this should check for overflow, and max out, as limbo op does?
+ # probably this should check for overflow, and max out, as limbo op does?
start := i;
- dig := '9';
- if (base < 10)
- dig = '0' + base - 1;
n := big 0;
for (; i < len s; i++) {
- c = s[i];
- if ('0' <= c && c <= dig)
- n = (n * big base) + big(c - '0');
- else if ('a' <= c && c < 'a' + base - 10)
- n = (n * big base) + big(c - 'a' + 10);
- else if ('A' <= c && c < 'A' + base - 10)
- n = (n * big base) + big(c - 'A' + 10);
- else
+ if((d := digit(s[i], base)) < 0)
break;
+ n = n*big base + big d;
}
if (i == start)
return (big 0, s);
@@ -213,62 +213,20 @@ tobig(s: string, base: int): (big, string)
toint(s: string, base: int): (int, string)
{
- if (s == nil || base < 0 || base > 36 || base == 1)
- return (0, s);
-
- # skip possible leading white space
- c: int;
- for (i := 0; i < len s; i++) {
- c = s[i];
- if(c != ' ' && c != '\t' && c != '\n')
- break;
- }
+ neg, i: int;
- # skip possible sign character
- neg := 0;
- if (c == '-' || c == '+') {
- if(c == '-')
- neg = 1;
- i++;
- }
-
- if (base == 0) {
- # parse possible leading base designator
- start := i;
- base = -1;
- for (; i < start+3 && i < len s; i++) {
- c = s[i];
- if (c == 'r' && i > start) {
- base = int s[start:i];
- i++;
- break;
- } else if (c < '0' || c > '9')
- break;
- }
- if (base == -1) {
- i = start;
- base = 10;
- } else if (base == 0 || base > 36)
- return (0, s);
- }
+ (base, neg, i) = startnum(s, base);
+ if(base == 0)
+ return (0, s);
# parse number itself.
- # perhaps this should check for overflow, and max out, as limbo op does?
+ # probably this should check for overflow, and max out, as limbo op does?
start := i;
- dig := '9';
- if (base < 10)
- dig = '0' + base - 1;
n := 0;
- for (; i < len s; i++) {
- c = s[i];
- if ('0' <= c && c <= dig)
- n = (n * base) + (c - '0');
- else if ('a' <= c && c < 'a' + base - 10)
- n = (n * base) + (c - 'a' + 10);
- else if ('A' <= c && c < 'A' + base - 10)
- n = (n * base) + (c - 'A' + 10);
- else
+ for (; i < len s; i++){
+ if((d := digit(s[i], base)) < 0)
break;
+ n = n*base + d;
}
if (i == start)
return (0, s);
@@ -277,6 +235,117 @@ toint(s: string, base: int): (int, string)
return (n, s[i:]);
}
+digit(c: int, base: int): int
+{
+ if ('0' <= c && c <= '0' + base - 1)
+ return c-'0';
+ else if ('a' <= c && c < 'a' + base - 10)
+ return (c - 'a' + 10);
+ else if ('A' <= c && c < 'A' + base - 10)
+ return (c - 'A' + 10);
+ else
+ return -1;
+}
+
+rpow(x: real, n: int): real
+{
+ inv := 0;
+ if(n < 0){
+ n = -n;
+ inv = 1;
+ }
+ r := 1.0;
+ for(;;){
+ if(n&1)
+ r *= x;
+ if((n >>= 1) == 0)
+ break;
+ x *= x;
+ }
+ if(inv)
+ r = 1.0/r;
+ return r;
+}
+
+match(p: string, s: string, i: int): int
+{
+ if(i+len p > len s)
+ return 0;
+ for(j := 0; j < len p; j++){
+ c := s[i++];
+ if(c >= 'A' && c <= 'Z')
+ c += 'a'-'A';
+ if(p[j] != c)
+ return 0;
+ }
+ return 1;
+}
+
+toreal(s: string, base: int): (real, string)
+{
+ neg, i: int;
+
+ (base, neg, i) = startnum(s, base);
+ if(base == 0)
+ return (0.0, s);
+
+ c := s[i];
+ if((c == 'i' || c == 'I') && match("infinity", s, i))
+ return (real s, s[i+8:]);
+ if((c == 'n' || c == 'N') && match("nan", s, i))
+ return (real s, s[i+3:]);
+
+ if(digit(c, base) < 0)
+ return (0.0, s);
+
+ num := 0.0;
+ for(; i < len s && (d := digit(s[i], base)) >= 0; i++)
+ num = num*real base + real d;
+ dig := 0; # digits in fraction
+ if(i < len s && s[i] == '.'){
+ i++;
+ for(; i < len s && (d = digit(s[i], base)) >= 0; i++){
+ num = num*real base + real d;
+ dig++;
+ }
+ }
+ exp := 0;
+ eneg := 0;
+ if(i < len s && ((c = s[i]) == 'e' || c == 'E')){
+ start := i; # might still be badly formed
+ i++;
+ if(i < len s && ((c = s[i]) == '-' || c == '+')){
+ i++;
+ if(c == '-'){
+ dig = -dig;
+ eneg = 1;
+ }
+ }
+ if(i < len s && s[i] >= '0' && s[i] <= '9'){ # exponents are always decimal
+ for(; i < len s && (d = digit(s[i], 10)) >= 0; i++)
+ exp = exp*base + d;
+ }else
+ i = start;
+ }
+ if(base == 10)
+ return (real s[0: i], s[i:]); # conversion can be more accurate
+ exp -= dig;
+ if(exp < 0){
+ exp = -exp;
+ eneg = !eneg;
+ }
+ if(exp < 0 || exp > 19999)
+ exp = 19999; # huge but otherwise arbitrary limit
+ dem := rpow(real base, exp);
+ if(eneg)
+ num /= dem;
+ else
+ num *= dem;
+ if(neg)
+ return (-num,s[i:]);
+ return (num, s[i:]);
+}
+
append(s: string, l: list of string): list of string
{
t: list of string;