import vector import util import mem import serialize import io ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int fun to_string(in: float): string return to_string((in) cast double) fun to_string(in: double): string { var how_much = snprintf(mem::null(), (0) cast ulong, "%f", in) var int_str = mem::new(how_much+2) snprintf(int_str, (how_much+1) cast ulong, "%f", in) var to_ret = string(int_str) mem::delete(int_str) return to_ret } fun to_string(in: bool): string if (in) return string("true") else return string("false") fun to_string(in: char): string return string(in) fun to_string(in: uchar): string return to_string_num(in) fun to_string(in: short): string return to_string_num(in) fun to_string(in: ushort): string return to_string_num(in) fun to_string(in: int): string return to_string_num(in) fun to_string(in: uint): string return to_string_num(in) fun to_string(in: long): string return to_string_num(in) fun to_string(in: ulong): string return to_string_num(in) fun to_string(in: *T): string return string("ptr:<") + to_string_num((in) cast ulong) + ">" fun string_to_num(it: string): T { var is_negative = false if (it[0] == '-') { is_negative = true it = it.slice(1,-1) } var result:T = 0 var power:T = 1 while (it.length()) { result += power * (it.last() - '0') it = it.slice(0,-2) power *= 10 } if (is_negative) return -result return result } fun string_to_double(it: string): double { var parts = it.split('.') var divisor = 1 for (var i = 0; i < parts[1].length(); i++;) divisor *= 10 return string_to_num(parts[0]) + (string_to_num(parts[1])) cast double / divisor } fun to_string_num(in: T): string { if (in == 0) return string("0") var ret = string() var pos = 0 var is_neg = false if (in > 0) { pos = in } else { pos = -in is_neg = true } while (pos) { ret = string((pos%10 + '0') cast char) + ret pos = pos / 10 } if (is_neg) return string("-") + ret return ret } fun operator+(first: *char, second: ref string): string { return string(first) + second } fun string(in:*char):string { var out.construct(in):string return out } fun string(in:char):string { var out.construct():string out += in return out } fun string():string { return string("") } obj string (Object, Serializable) { var data: vector::vector; fun construct(): *string { data.construct(); return this; } fun construct(str: *char): *string { var len = 0 while (str[len] != 0) len++ data.construct(len); data.set_size(len); mem::memmove((data.getBackingMemory()) cast *void, (str) cast *void, (len) cast ulong) // no null terminator return this; } fun construct(vec: ref vector::vector): *string { data.copy_construct(&vec); return this; } fun construct(str: ref string): *string { return construct(str.data); } fun copy_construct(old: *string): void { data.copy_construct(&old->data) } fun copy_construct(old: **char): void { construct(*old) } fun operator=(str: *char): void { destruct(); construct(str) } fun operator=(str: ref string): void { data = str.data } fun destruct():void { data.destruct() } fun serialize(): vector::vector { return serialize::serialize(data) } fun unserialize(it: ref vector::vector, pos: int): int { /*construct()*/ /*util::unpack(data, pos) = serialize::unserialize>(it, pos)*/ return data.unserialize(it, pos) } fun operator[](index: int): ref char { return data[index]; } fun slice(first: int, second: int): string { var new.construct(data.slice(first,second)): string return new } fun set(index: int, toSet: char) { data.set(index, toSet) } fun length():int { return data.size; } fun operator!=(other: ref string): bool return !(*this ==other) fun operator!=(other: *char): bool return !(*this==other) fun operator==(other: ref string): bool { // you were too good for this world //return length() == other.length() && !util::range(length()).any_true(fun(i: int):bool { return data[i] != other[i]; } ) if (data.size != other.data.size) return false for (var i = 0; i < data.size; i++;) if (data.data[i] != other.data.data[i]) return false return true } fun operator==(other: *char): bool { var str.construct(other) : string return *this == str } fun operator+(integer: int): string return *this + to_string(integer); fun operator+(integer: ulong): string return *this + to_string(integer); /*fun operator+(b: bool): string return *this + to_string(b);*/ fun operator+(str: *char): string { var newStr.construct(str):string var ret.construct(data + newStr.data):string return ret } fun operator+(str: ref string): string { var ret.construct(data + str.data):string return ret } fun operator+=(integer: int) *this += to_string(integer); fun operator+=(integer: ulong) *this += to_string(integer); /*fun operator+=(b: bool) *this += to_string(b);*/ fun operator+=(character: char): void { data += character } fun operator+=(str: *char): void { var newStr.construct(str):string data += newStr.data } fun operator+=(str: ref string): void { //var newStr.construct(str):string //data += newStr.data data += str.data } fun toCharArray(): *char { var out: *char = mem::new(data.size+1); for (var i: int = 0; i < data.size; i++;) out[i] = data.get(i); // null terminator out[data.size] = 0 return out; } fun getBackingMemory(): *char return data.getBackingMemory(); fun split(delim: *char): vector::vector return split(string(delim)) fun split(delim: string): vector::vector { var out.construct(): vector::vector var current = string("") for (var i = 0; i < data.size; i++;) { if (i < data.size-delim.length() && slice(i, i+delim.length()) == delim) { out.add(current) current = string("") i += delim.length()-1 } else { current += data[i] } } out.add(current) return out } fun last(): char return data.last() fun lines(): vector::vector return split('\n') fun split(delim: char): vector::vector { var out.construct(): vector::vector var current = string("") for (var i = 0; i < data.size; i++;) { if (data[i] == delim) { out.add(current) current = string("") } else { current += data[i] } } out.add(current) return out } fun join(to_join: ref vector::vector): string { var to_ret = to_join.first() for (var i = 1; i < to_join.size; i++;) to_ret += *this + to_join[i] return to_ret } fun for_each(func: fun(char):void) { data.for_each(func) } };