//[of]:imports //[c] import "base/types" import "base/memory" import "base/memory-allocator" //[cf] //[c] //[of]:globals //[c] //[c]The global empty string //[c] public def empty string := "" //[cf] //[of]:instance creation //[of]:new string (string) //[c]Constructs a string from a raw buffer //[c] public func new string (s: string) def len = size (s) + 1 def buf = allocate memory (len): string copy (buf:mem, s:mem, len) return buf end //[cf] //[of]:new string (string, size) //[c]Constructs a string from a raw buffer //[c] public func new string (s: string, len: size) def buf = allocate memory (len+1): string copy (buf:mem, s:mem, len) buf[len] = \0 return buf end //[cf] //[of]:new string (string, limit) //[c]Constructs a string from a raw buffer //[c] public func new string (s: string, limit: string) return new string (s, limit - s) end //[cf] //[of]:new string (size) //[c]Reserves space for a string //[c] public func new string (len: size) return allocate memory (len+1) : string end //[cf] //[c] //[of]:delete (s) //[c]Delete a string //[c]Delete a null pointer does nothing but is valid //[c]Delete the GLOBAL empty string has no effect. //[c] public func delete (s: string) // compare reference, not content if s:mem == empty string:mem return end free memory (s) end //[cf] //[cf] //[c] //[of]:numerical conversion //[of]:number to dword (s, [] string) //[c]Converts a decimal string to an integer //[c] public func number to dword (p: string, endptr: [] string) def base: int def value = 0:dword if p[0]==$0 && (p[1]==$x || p[1]==$X) p += 2 base = 16 else base = 10 end repeat def c = p++[] if c==nul char break end if c>=$a c -= $a - 10:char elsif c>=$A c -= $A - 10:char elsif c<=$9 c -= $0 else c = 0xff:char end if c:byte > base:byte break end value *= base value += c:byte:dword end endptr[] = p-1 return value end //[cf] //[of]:hexa to dword (s) //[c]Converts an hexadecimal string to an integer //[c] public func hexa to dword (s: string) def value = 0:dword def q = s def c = q++[] while not nul (c) value <<= 4 if $0 <= c && c < $9 + 1:char value += (c - $0):dword elsif $a <= c && c < $f + 1:char value += (c - $a + 10:char):dword elsif $A <= c && c < $F + 1:char value += (c - $A + 10:char):dword else break end c = q++[] end return value end //[cf] //[of]:decimal to integer (s) //[c]Converts the string to an integer //[c] public func decimal to integer (s: string) def c = s++[] def neg = false if c == $- neg = true c = s++[] elsif c == $+ c = s++[] end def value = 0 repeat def digit = (c - $0):byte if digit > 10:byte break end value = value * 10 + digit:int c = s++[] end if neg value -! end return value end //[cf] //[cf] //[of]:case conversion //[of]:to lower (s) public func to lower (s: string) def p = s repeat def c = p[] if is nul (c) break elsif is upper (c) p [] = c + ($a - $A) end ++p end end //[cf] //[of]:to upper (s) public func to upper (s: string) def p = s repeat def c = p[] if is nul (c) break elsif is lower (c) p [] = c + ($A - $a) end ++p end end //[cf] //[cf] //[of]:writing //[of]:copy (dest string, source string) //[c] public func copy (dest: string, source: string) def p = source def q = dest repeat def c = p++[] q++[] = c if c == nul char break end end return p end //[cf] //[of]:copy (dest string, source string, size) //[c] public func copy (dest: string, source: string, count: size) def p = source def q = dest while count>0 --count def c = p++[] q++[] = c if c == nul char break end end return p end //[cf] //[of]:append (s, char) //[c]Appends a single char //[c] public func append (s: string, c: char) s[] = c return s+1 end //[cf] //[of]:append (s, string) //[c]Appends a string //[c] public func append (s: string, str: string) def size = size (str) copy (s , str, size) return s + size end //[cf] //[of]:append (s, string, size) //[c]Appends a sub-string //[c] public func append (s: string, str: string, size: size) copy (s:mem, str:mem, size) return s + size end //[cf] //[of]:s << char //[c] public equ @shl (s: string, c: char) = append (s, c) //[cf] //[of]:s << string //[c] public equ @shl (s: string, str: string) = append (s, str) //[cf] //[cf] //[of]:searching //[of]:first occurrence (s, char) //[c]Returns the first occurrence of a char, nil if not found //[c] public func first occurrence (s: string, c: char) def q = s def d = q++[] while not nul (d) if d==c return q - 1 end d = q++[] end // not found return nil end //[cf] //[of]:last occurrence (s, char) //[c]Returns the last occurrence of a char, nil if not found //[c] public func last occurrence (s: string, c: char) def q = s + size(s) - 1 while q:[]byte >= s:[]byte if q[] == c return q end q -= 1 end // not found return nil end //[cf] //[of]:first occurrence (s, string) //[c]Returns the first occurrence of a substring, nil if not found //[c] public func first occurrence (s: string, t: string) def p = s def q = t def c = p++[] def d = q++[] def size = size(q) while not nul (d) if c==d && is equal (p:mem, q:mem, size) return p - 1 end c = p++[] end // not found return nil end //[cf] //[c] //[of]:skip blanks (string) //[c] public func skip blanks (s: string) def p = s while is blank (p []) ++ p end return p end //[cf] //[of]:skip non blanks (string) //[c] public func skip non blanks (s: string) def p = s repeat def c = p [] if is nul (c) || is blank (c) break end ++ p end return p end //[cf] //[cf] //[of]:accessing //[of]:size (s) //[c]Returns the length of the string //[c] public func size (s: string) def p = s while not nul (p[]) ++p end return p - s end //[cf] //[of]:compare (s1, s2) //[c]Compares two strings //[c] public func compare (s1: string, s2: string) def c: char repeat c = s1[] if c<>s2[] break end if is nul (c) break end ++s1 ++s2 end return (c - s2[]) : octet : int end //[cf] //[of]:compare no case (s1, s2) //[c]Compare two strings in case insensitive mode //[c] public func compare no case (s1: string, s2: string) def c1: char def c2: char repeat c1 = upper (s1++[]) c2 = upper (s2++[]) if c1<>c2 || is nul (c1) return (c1 - c2) : octet : int end end return 0 end //[cf] //[of]:compare no case (s1, s2, size) //[c]Compare two strings in case insensitive mode //[c] public func compare no case (s1: string, s2: string, size: size) def limit = (s2 + size) : [] byte // compare pointers, not values def c1: char def c2: char while s2 < limit c1 = upper (s1++[]) c2 = upper (s2++[]) if c1<>c2 || is nul (c1) return (c1 - c2):octet:int end end return 0 end //[cf] //[of]:hash (s) //[c]Returns the hash code of the string //[c] public func hash (s: string) def q = s def sum = 0xA5A5A5A5 while not nul (q[]) //sum = (sum<<1) ^ q++[]:int sum = (sum>>1) + (q++[]:int<<24) end return sum end //[cf] //[cf] //[of]:testing //[c]testing //[c] //[of]:is equal (s1, s2) //[c]Equality test function //[c]to use when function pointer is required //[c] public func is equal (s1: string, s2: string) def c: char def d: char repeat c = s1++[] d = s2++[] if c<>d return false end if is nul (c) break end end return true end //[cf] //[c] //[of]:s1 < s2 //[c] public equ @less than (s1: string, s2: string) = compare(s1,s2) < 0 //[cf] //[of]:s1 > s2 //[c] public equ @greater than (s1: string, s2: string) = compare(s1,s2) > 0 //[cf] //[of]:s1 <= s2 //[c] public equ @less or equal (s1: string, s2: string) = compare(s1,s2) <= 0 //[cf] //[of]:s1 >= s2 //[c] public equ @greater or equal (s1: string, s2: string) = compare(s1,s2) >= 0 //[cf] //[of]:s1 == s2 //[c] public equ @equal (s1: string, s2: string) = compare (s1, s2) == 0 //[cf] //[of]:s1 <> s2 //[c] public equ @not equal (s1: string, s2: string) = compare (s1, s2) <> 0 //[cf] //[c] //[of]:is empty (s) //[c] public equ is empty (s: string) = is nul (s[]) //[cf] //[of]:not empty (s) //[c] public equ not empty (s: string) = not nul (s[]) //[cf] //[of]:starts with (s, char) //[c] public equ starts with (s: string, c: char) = s[0]==c //[cf] //[of]:ends with (s, char) //[c] public func ends with (s: string, c: char) // Test if the last char is the given one def len = size(s) return (len>0) && (s[len-1]==c) end //[cf] //[of]:starts with (s, string) //[c] public func starts with (s: string, str: string) def size = size (str) return is equal (s:mem, str:mem, size) end //[cf] //[of]:ends with (s, string) //[c] public func ends with (s: string, str: string) def size 1 = size (s) def size 2 = size (str) return is equal ((s + size 1 - size 2):mem, str:mem, size 2) end //[cf] //[of]:contains (s, string) //[c] public equ contains (s: string, t: string) = first occurrence (s,t) <> nil //[cf] //[cf]