import vec import util import mem import serialize import io ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int fun to_string(in: float): str return to_string((in) cast double) fun to_string(in: double): str { 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 = str(int_str) mem::delete(int_str) return to_ret } fun to_string(in: bool): str if (in) return str("true") else return str("false") fun to_string(in: char): str return str(in) fun to_string(in: uchar): str return to_string_num(in) fun to_string(in: short): str return to_string_num(in) fun to_string(in: ushort): str return to_string_num(in) fun to_string(in: int): str return to_string_num(in) fun to_string(in: uint): str return to_string_num(in) fun to_string(in: long): str return to_string_num(in) fun to_string(in: ulong): str return to_string_num(in) fun to_string(in: *T): str return str("ptr:<") + to_string_num((in) cast ulong) + ">" /*fun deref_to_string(in: *T): str*/ /*if (in == mem::null())*/ /*return str("null")*/ /*else*/ /*return to_string(in)*/ /*return in->to_string()*/ fun string_to_num(it: str): 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: str): 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): str { if (in == 0) return str("0") var ret = str() var pos = 0 var is_neg = false if (in > 0) { pos = in } else { pos = -in is_neg = true } while (pos) { ret = str((pos%10 + '0') cast char) + ret pos = pos / 10 } if (is_neg) return str("-") + ret return ret } fun operator+(first: *char, second: ref str): str { return str(first) + second } fun operator+(first: int, second: ref str): str { return to_string(first) + second } fun operator*(first: *char, second: int): str { return str(first) * second } fun operator*(first: int, second: *char): str { return str(second) * first } fun operator*(first: int, second: ref str): str { return second * first } fun str(in:*char):str { var out.construct(in):str return out } fun str(in:char):str { var out.construct():str out += in return out } fun str():str { return str("") } obj str (Object, Serializable, Hashable) { var data: vec::vec; fun construct(): *str { data.construct(); return this; } fun construct(ammt: int): *str { data.construct(ammt); return this; } fun construct(str: *char): *str { 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 vec::vec): *str { data.copy_construct(&vec); return this; } fun construct(str: ref str): *str { return construct(str.data); } fun copy_construct(old: *str): void { data.copy_construct(&old->data) } fun copy_construct(old: **char): void { construct(*old) } fun hash(): ulong { var hash: ulong = 7 for (var i = 0; i < data.size; i++;) hash = hash*31 + data[i] return hash } fun operator=(str: *char): void { destruct(); construct(str) } fun operator=(str: ref str): void { data = str.data } fun destruct():void { data.destruct() } fun serialize(): vec::vec { return serialize::serialize(data) } fun unserialize(it: ref vec::vec, pos: int): int { return data.unserialize(it, pos) } fun operator[](index: int): ref char { return data[index]; } fun slice(first: int, second: int): str { var new.construct(data.slice(first,second)): str return new } fun set(index: int, toSet: char) { data.set(index, toSet) } fun length():int { return data.size; } fun operator!=(other: ref str): bool return !(*this ==other) fun operator!=(other: *char): bool return !(*this==other) fun operator==(other: ref str): 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) : str return *this == str } fun operator<=(other: ref str): bool { var l = 0 var r = 0 while (l < length() || r < other.length()) { if l == length() { return true } else if r == other.length() { return false } else if (*this)[l] < other[r] { return true } else if (*this)[l] > other[r] { return false } l++ r++ } } fun operator<(other: ref str): bool { return *this <= other && *this != other } fun operator*(n: int): str { var to_ret.construct(): str while (n-- > 0) to_ret += *this return to_ret } fun operator+(c: char): str { var to_ret = *this to_ret += c return to_ret } fun operator+(integer: int): str return *this + to_string(integer); fun operator+(integer: long): str return *this + to_string(integer); fun operator+(integer: ulong): str return *this + to_string(integer); /*fun operator+(b: bool): str return *this + to_string(b);*/ fun operator+(str: *char): str { var newStr.construct(str):str var ret.construct(data + newStr.data):str return ret } fun operator+(str: ref str): str { var ret.construct(data + str.data):str 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):str data += newStr.data } fun operator+=(str: ref str): void { //var newStr.construct(str):str //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): vec::vec return split(str(delim)) fun split(delim: str): vec::vec { var out.construct(): vec::vec var current = str("") for (var i = 0; i < data.size; i++;) { if (i < data.size-delim.length() && slice(i, i+delim.length()) == delim) { out.add(current) current = str("") i += delim.length()-1 } else { current += data[i] } } out.add(current) return out } fun first(): char return data.first() fun last(): char return data.last() fun lines(): vec::vec return split('\n') fun split(delim: char): vec::vec { var out.construct(): vec::vec var current = str("") for (var i = 0; i < data.size; i++;) { if (data[i] == delim) { out.add(current) current = str("") } else { current += data[i] } } out.add(current) return out } fun join(to_join: ref vec::vec): str { if (to_join.size != 0) { var to_ret = to_join.first() for (var i = 1; i < to_join.size; i++;) to_ret += *this + to_join[i] return to_ret } else { return str("") } } fun for_each(func: fun(char):void) { data.for_each(func) } fun contains(c: char): bool { return data.contains(c) } };