1 module zua.vm.std..string;
2 import zua.vm.engine;
3 import zua.vm.reflection;
4 import std.algorithm.mutation;
5 import std.typecons;
6 import std.variant;
7 import std.conv;
8 
9 private ubyte[] lstring_byte(string s, Nullable!long ni, Nullable!long nj) {
10 	long i = ni.isNull ? 1 : ni.get;
11 	long j = nj.isNull ? i : nj.get;
12 
13 	if (i < 0) i += s.length; else i--;
14 	if (j < 0) j += s.length; else j--;
15 
16 	if (i > j) return [];
17 
18 	if (i < 0) i = 0;
19 	if (j > s.length) j = s.length - 1;
20 
21 	return cast(ubyte[]) s[i .. j + 1];
22 }
23 
24 private string lstring_char(long[] args...) {
25 	string str;
26 
27 	foreach (i; 0 .. args.length) {
28 		long v = args[i];
29 		if (v < 0 || v > 255) {
30 			throw new Exception("bad argument #" ~ (i + 1).to!string ~ " to 'char' (invalid value)");
31 		}
32 		str ~= cast(char) v;
33 	}
34 
35 	return str;
36 }
37 
38 private size_t lstring_len(string s) {
39 	return s.length;
40 }
41 
42 private string lstring_lower(string s) {
43 	string res;
44 	res.reserve(s.length);
45 	foreach (c; s) {
46 		if (c >= 'A' && c <= 'Z') res ~= c + ('a' - 'A');
47 		else res ~= c;
48 	}
49 	return res;
50 }
51 
52 private string lstring_rep(string s, long n) {
53 	if (n < 1) return "";
54 	string res;
55 	res.reserve(s.length * n);
56 	foreach (i; 0 .. n) {
57 		res ~= s;
58 	}
59 	return res;
60 }
61 
62 private string lstring_reverse(string s) {
63 	string res;
64 	res.reserve(s.length);
65 	foreach_reverse (c; s) {
66 		res ~= c;
67 	}
68 	return res;
69 }
70 
71 private string lstring_sub(string s, Nullable!long ni, Nullable!long nj) {
72 	long i = ni.isNull ? 1 : ni.get;
73 	long j = nj.isNull ? i : nj.get;
74 
75 	if (i < 0) i += s.length; else i--;
76 	if (j < 0) j += s.length; else j--;
77 
78 	if (i > j) return [];
79 
80 	if (i < 0) i = 0;
81 	if (j > s.length) j = s.length - 1;
82 
83 	return s[i .. j + 1];
84 }
85 
86 private string lstring_upper(string s) {
87 	string res;
88 	res.reserve(s.length);
89 	foreach (c; s) {
90 		if (c >= 'a' && c <= 'z') res ~= c - ('a' - 'A');
91 		else res ~= c;
92 	}
93 	return res;
94 }
95 
96 /** Get string library */
97 Value stringlib() {
98 	TableValue res = new TableValue;
99 	res.set(Value("byte"), exposeFunction!(lstring_byte, "byte"));
100 	res.set(Value("char"), exposeFunction!(lstring_char, "char"));
101 	res.set(Value("len"), exposeFunction!(lstring_len, "len"));
102 	res.set(Value("lower"), exposeFunction!(lstring_lower, "lower"));
103 	res.set(Value("rep"), exposeFunction!(lstring_rep, "rep"));
104 	res.set(Value("reverse"), exposeFunction!(lstring_reverse, "reverse"));
105 	res.set(Value("sub"), exposeFunction!(lstring_sub, "sub"));
106 	res.set(Value("upper"), exposeFunction!(lstring_upper, "upper"));
107 	return Value(res);
108 }