2018-05-22 19:43:54 -04:00
|
|
|
import vec
|
2015-06-28 20:25:27 -04:00
|
|
|
import util
|
2015-06-09 20:02:02 -04:00
|
|
|
import mem
|
2015-08-26 03:45:34 -04:00
|
|
|
import serialize
|
2016-04-30 15:38:28 -04:00
|
|
|
import io
|
2015-03-11 01:58:10 -04:00
|
|
|
|
2016-07-03 22:50:42 -07:00
|
|
|
ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: float): str
|
2016-07-03 22:50:42 -07:00
|
|
|
return to_string((in) cast double)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: double): str {
|
2016-07-03 22:50:42 -07:00
|
|
|
var how_much = snprintf(mem::null<char>(), (0) cast ulong, "%f", in)
|
|
|
|
|
var int_str = mem::new<char>(how_much+2)
|
|
|
|
|
snprintf(int_str, (how_much+1) cast ulong, "%f", in)
|
2018-05-22 19:43:54 -04:00
|
|
|
var to_ret = str(int_str)
|
2016-07-03 22:50:42 -07:00
|
|
|
mem::delete(int_str)
|
|
|
|
|
return to_ret
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
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
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: short): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: ushort): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: int): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: uint): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: long): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string(in: ulong): str
|
2016-04-30 15:38:28 -04:00
|
|
|
return to_string_num(in)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string<T>(in: *T): str
|
|
|
|
|
return str("ptr:<") + to_string_num((in) cast ulong) + ">"
|
2016-04-30 15:38:28 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun string_to_num<T>(it: str): T {
|
2016-05-13 03:10:36 -04:00
|
|
|
var is_negative = false
|
|
|
|
|
if (it[0] == '-') {
|
|
|
|
|
is_negative = true
|
|
|
|
|
it = it.slice(1,-1)
|
|
|
|
|
}
|
2016-07-09 00:45:40 -07:00
|
|
|
var result:T = 0
|
|
|
|
|
var power:T = 1
|
2016-05-13 03:10:36 -04:00
|
|
|
while (it.length()) {
|
|
|
|
|
result += power * (it.last() - '0')
|
|
|
|
|
it = it.slice(0,-2)
|
|
|
|
|
power *= 10
|
|
|
|
|
}
|
|
|
|
|
if (is_negative)
|
|
|
|
|
return -result
|
|
|
|
|
return result
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun string_to_double(it: str): double {
|
2016-05-15 11:09:12 -07:00
|
|
|
var parts = it.split('.')
|
|
|
|
|
var divisor = 1
|
|
|
|
|
for (var i = 0; i < parts[1].length(); i++;) divisor *= 10
|
2016-07-09 00:45:40 -07:00
|
|
|
return string_to_num<long>(parts[0]) + (string_to_num<long>(parts[1])) cast double / divisor
|
2016-05-15 11:09:12 -07:00
|
|
|
}
|
2016-05-13 03:10:36 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun to_string_num<T>(in: T): str {
|
2016-04-30 15:38:28 -04:00
|
|
|
if (in == 0)
|
2018-05-22 19:43:54 -04:00
|
|
|
return str("0")
|
|
|
|
|
var ret = str()
|
2016-04-30 15:38:28 -04:00
|
|
|
var pos = 0
|
|
|
|
|
var is_neg = false
|
|
|
|
|
if (in > 0) {
|
|
|
|
|
pos = in
|
|
|
|
|
} else {
|
|
|
|
|
pos = -in
|
|
|
|
|
is_neg = true
|
|
|
|
|
}
|
|
|
|
|
while (pos) {
|
2018-05-22 19:43:54 -04:00
|
|
|
ret = str((pos%10 + '0') cast char) + ret
|
2016-04-30 15:38:28 -04:00
|
|
|
pos = pos / 10
|
|
|
|
|
}
|
|
|
|
|
if (is_neg)
|
2018-05-22 19:43:54 -04:00
|
|
|
return str("-") + ret
|
2015-08-12 23:15:41 -04:00
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+(first: *char, second: ref str): str {
|
|
|
|
|
return str(first) + second
|
2016-03-20 05:14:26 -04:00
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+(first: int, second: ref str): str {
|
2018-03-06 23:30:00 -05:00
|
|
|
return to_string(first) + second
|
|
|
|
|
}
|
2018-06-18 19:04:24 -04:00
|
|
|
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
|
|
|
|
|
}
|
2016-03-20 05:14:26 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun str(in:*char):str {
|
|
|
|
|
var out.construct(in):str
|
2015-06-08 21:47:02 -04:00
|
|
|
return out
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun str(in:char):str {
|
|
|
|
|
var out.construct():str
|
2015-08-11 01:07:16 -04:00
|
|
|
out += in
|
|
|
|
|
return out
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun str():str {
|
|
|
|
|
return str("")
|
2015-08-26 03:45:34 -04:00
|
|
|
}
|
2015-06-08 21:47:02 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
obj str (Object, Serializable, Hashable) {
|
|
|
|
|
var data: vec::vec<char>;
|
|
|
|
|
fun construct(): *str {
|
2015-03-11 01:58:10 -04:00
|
|
|
data.construct();
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun construct(ammt: int): *str {
|
2018-03-19 21:03:06 -04:00
|
|
|
data.construct(ammt);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun construct(str: *char): *str {
|
2016-06-11 00:45:18 -07:00
|
|
|
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)
|
2015-06-01 01:43:23 -04:00
|
|
|
// no null terminator
|
2015-03-11 01:58:10 -04:00
|
|
|
return this;
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun construct(vec: ref vec::vec<char>): *str {
|
2015-06-01 01:43:23 -04:00
|
|
|
data.copy_construct(&vec);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun construct(str: ref str): *str {
|
2015-06-28 20:25:27 -04:00
|
|
|
return construct(str.data);
|
|
|
|
|
}
|
2015-06-01 01:43:23 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun copy_construct(old: *str): void {
|
2015-06-01 01:43:23 -04:00
|
|
|
data.copy_construct(&old->data)
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-04 17:02:51 -04:00
|
|
|
fun copy_construct(old: **char): void {
|
2015-06-07 19:54:08 -04:00
|
|
|
construct(*old)
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-28 15:28:34 -04:00
|
|
|
fun hash(): ulong {
|
|
|
|
|
var hash: ulong = 7
|
|
|
|
|
for (var i = 0; i < data.size; i++;)
|
|
|
|
|
hash = hash*31 + data[i]
|
|
|
|
|
return hash
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-04 17:02:51 -04:00
|
|
|
fun operator=(str: *char): void {
|
2015-06-27 18:06:02 -04:00
|
|
|
destruct();
|
|
|
|
|
construct(str)
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator=(str: ref str): void {
|
2016-05-05 04:51:10 -04:00
|
|
|
data = str.data
|
2015-06-27 18:06:02 -04:00
|
|
|
}
|
|
|
|
|
|
2015-06-01 01:43:23 -04:00
|
|
|
fun destruct():void {
|
|
|
|
|
data.destruct()
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun serialize(): vec::vec<char> {
|
2015-08-26 03:45:34 -04:00
|
|
|
return serialize::serialize(data)
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun unserialize(it: ref vec::vec<char>, pos: int): int {
|
2015-08-29 21:45:55 -04:00
|
|
|
return data.unserialize(it, pos)
|
2015-08-26 03:45:34 -04:00
|
|
|
}
|
|
|
|
|
|
2015-07-15 00:53:53 -04:00
|
|
|
fun operator[](index: int): ref char { return data[index]; }
|
2018-05-22 19:43:54 -04:00
|
|
|
fun slice(first: int, second: int): str {
|
|
|
|
|
var new.construct(data.slice(first,second)): str
|
2015-06-14 18:13:52 -04:00
|
|
|
return new
|
|
|
|
|
}
|
2015-06-27 11:46:31 -04:00
|
|
|
fun set(index: int, toSet: char) {
|
|
|
|
|
data.set(index, toSet)
|
|
|
|
|
}
|
2015-06-08 21:47:02 -04:00
|
|
|
fun length():int { return data.size; }
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator!=(other: ref str): bool return !(*this ==other)
|
2015-12-06 15:15:33 -05:00
|
|
|
fun operator!=(other: *char): bool return !(*this==other)
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator==(other: ref str): bool {
|
2015-08-04 14:57:56 -04:00
|
|
|
// 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
|
2015-06-28 20:25:27 -04:00
|
|
|
}
|
2015-07-05 02:34:45 -04:00
|
|
|
fun operator==(other: *char): bool {
|
2018-05-22 19:43:54 -04:00
|
|
|
var str.construct(other) : str
|
2015-07-05 02:34:45 -04:00
|
|
|
return *this == str
|
|
|
|
|
}
|
2015-06-28 20:25:27 -04:00
|
|
|
|
2018-06-18 19:04:24 -04:00
|
|
|
fun operator*(n: int): str {
|
|
|
|
|
var to_ret.construct(): str
|
|
|
|
|
while (n-- > 0)
|
|
|
|
|
to_ret += *this
|
|
|
|
|
return to_ret
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+(c: char): str {
|
2018-03-22 00:51:57 -04:00
|
|
|
var to_ret = *this
|
|
|
|
|
to_ret += c
|
|
|
|
|
return to_ret
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
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);*/
|
2016-01-10 18:26:31 -05:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+(str: *char): str {
|
|
|
|
|
var newStr.construct(str):str
|
|
|
|
|
var ret.construct(data + newStr.data):str
|
2015-06-01 01:43:23 -04:00
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+(str: ref str): str {
|
|
|
|
|
var ret.construct(data + str.data):str
|
2015-06-28 20:25:27 -04:00
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-10 18:26:31 -05:00
|
|
|
fun operator+=(integer: int) *this += to_string(integer);
|
2016-07-06 00:16:39 -07:00
|
|
|
fun operator+=(integer: ulong) *this += to_string(integer);
|
2016-06-16 09:53:15 -07:00
|
|
|
/*fun operator+=(b: bool) *this += to_string(b);*/
|
2016-01-10 18:26:31 -05:00
|
|
|
|
2015-07-04 03:21:36 -04:00
|
|
|
fun operator+=(character: char): void {
|
|
|
|
|
data += character
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-04 17:02:51 -04:00
|
|
|
fun operator+=(str: *char): void {
|
2018-05-22 19:43:54 -04:00
|
|
|
var newStr.construct(str):str
|
2015-06-01 01:43:23 -04:00
|
|
|
data += newStr.data
|
|
|
|
|
}
|
2015-03-11 01:58:10 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun operator+=(str: ref str): void {
|
|
|
|
|
//var newStr.construct(str):str
|
2015-08-04 14:57:56 -04:00
|
|
|
//data += newStr.data
|
|
|
|
|
data += str.data
|
2015-06-28 20:25:27 -04:00
|
|
|
}
|
|
|
|
|
|
2015-07-04 17:02:51 -04:00
|
|
|
fun toCharArray(): *char {
|
|
|
|
|
var out: *char = mem::new<char>(data.size+1);
|
2015-05-09 06:24:56 -04:00
|
|
|
for (var i: int = 0; i < data.size; i++;)
|
2015-03-11 01:58:10 -04:00
|
|
|
out[i] = data.get(i);
|
2015-06-01 01:43:23 -04:00
|
|
|
// null terminator
|
|
|
|
|
out[data.size] = 0
|
2015-03-11 01:58:10 -04:00
|
|
|
return out;
|
|
|
|
|
}
|
2016-02-06 23:09:46 -05:00
|
|
|
fun getBackingMemory(): *char return data.getBackingMemory();
|
2015-07-04 03:21:36 -04:00
|
|
|
|
2018-05-22 19:43:54 -04:00
|
|
|
fun split(delim: *char): vec::vec<str> return split(str(delim))
|
|
|
|
|
fun split(delim: str): vec::vec<str> {
|
|
|
|
|
var out.construct(): vec::vec<str>
|
|
|
|
|
var current = str("")
|
2015-07-04 03:21:36 -04:00
|
|
|
for (var i = 0; i < data.size; i++;) {
|
2016-02-05 13:56:29 -05:00
|
|
|
if (i < data.size-delim.length() && slice(i, i+delim.length()) == delim) {
|
|
|
|
|
out.add(current)
|
2018-05-22 19:43:54 -04:00
|
|
|
current = str("")
|
2016-02-05 13:56:29 -05:00
|
|
|
i += delim.length()-1
|
|
|
|
|
} else {
|
|
|
|
|
current += data[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
out.add(current)
|
|
|
|
|
return out
|
|
|
|
|
}
|
2016-07-09 23:52:32 -07:00
|
|
|
fun first(): char return data.first()
|
2016-05-13 03:10:36 -04:00
|
|
|
fun last(): char return data.last()
|
2018-05-22 19:43:54 -04:00
|
|
|
fun lines(): vec::vec<str> return split('\n')
|
|
|
|
|
fun split(delim: char): vec::vec<str> {
|
|
|
|
|
var out.construct(): vec::vec<str>
|
|
|
|
|
var current = str("")
|
2016-02-05 13:56:29 -05:00
|
|
|
for (var i = 0; i < data.size; i++;) {
|
|
|
|
|
if (data[i] == delim) {
|
2015-07-04 03:21:36 -04:00
|
|
|
out.add(current)
|
2018-05-22 19:43:54 -04:00
|
|
|
current = str("")
|
2015-07-04 03:21:36 -04:00
|
|
|
} else {
|
|
|
|
|
current += data[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
out.add(current)
|
|
|
|
|
return out
|
|
|
|
|
}
|
2018-05-22 19:43:54 -04:00
|
|
|
fun join(to_join: ref vec::vec<str>): str {
|
2016-03-28 17:12:53 -04:00
|
|
|
var to_ret = to_join.first()
|
|
|
|
|
for (var i = 1; i < to_join.size; i++;)
|
|
|
|
|
to_ret += *this + to_join[i]
|
|
|
|
|
return to_ret
|
|
|
|
|
}
|
2016-02-15 23:12:56 -05:00
|
|
|
fun for_each(func: fun(char):void) {
|
|
|
|
|
data.for_each(func)
|
|
|
|
|
}
|
2015-03-11 01:58:10 -04:00
|
|
|
};
|
|
|
|
|
|