2016-08-17 17:20:19 +00:00
|
|
|
#include <ostd/functional.hh>
|
|
|
|
|
2016-08-02 00:21:36 +00:00
|
|
|
#include "cubescript.hh"
|
|
|
|
|
|
|
|
namespace cscript {
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
template<typename F>
|
|
|
|
static inline void cs_strgcmp(TvalRange args, TaggedValue &res, F cfunc) {
|
|
|
|
bool val;
|
|
|
|
if (args.size() >= 2) {
|
|
|
|
val = cfunc(args[0].get_strr(), args[1].get_strr());
|
|
|
|
for (ostd::Size i = 2; (i < args.size()) && val; ++i) {
|
|
|
|
val = cfunc(args[i - 1].get_strr(), args[i].get_strr());
|
|
|
|
}
|
|
|
|
} else {
|
2016-08-17 17:21:24 +00:00
|
|
|
val = cfunc(
|
|
|
|
!args.empty() ? args[0].get_strr() : ostd::ConstCharRange(),
|
|
|
|
ostd::ConstCharRange()
|
|
|
|
);
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
|
|
|
res.set_int(CsInt(val));
|
|
|
|
};
|
|
|
|
|
2016-08-02 00:21:36 +00:00
|
|
|
void cs_init_lib_string(CsState &cs) {
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strstr", "ss", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange a = args[0].get_strr(), b = args[1].get_strr();
|
|
|
|
ostd::ConstCharRange s = a;
|
2016-08-14 16:35:38 +00:00
|
|
|
for (CsInt i = 0; b.size() <= s.size(); ++i) {
|
2016-08-02 00:21:36 +00:00
|
|
|
if (b == s.slice(0, b.size())) {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(i);
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-08-17 17:20:19 +00:00
|
|
|
++s;
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(-1);
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strlen", "s", [](TvalRange args, TaggedValue &res) {
|
2016-08-14 16:35:38 +00:00
|
|
|
res.set_int(CsInt(args[0].get_strr().size()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strcode", "si", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange str = args[0].get_strr();
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt i = args[1].get_int();
|
|
|
|
if (i >= CsInt(str.size())) {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(0);
|
2016-08-02 00:21:36 +00:00
|
|
|
} else {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(ostd::byte(str[i]));
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("codestr", "i", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
char *s = new char[2];
|
|
|
|
s[0] = char(args[0].get_int());
|
|
|
|
s[1] = '\0';
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(s);
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strlower", "s", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
char *buf = new char[s.size() + 1];
|
2016-08-17 17:20:19 +00:00
|
|
|
for (auto i: ostd::range(s.size())) {
|
2016-08-02 00:21:36 +00:00
|
|
|
buf[i] = tolower(s[i]);
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
buf[s.size()] = '\0';
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(buf, s.size()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strupper", "s", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
char *buf = new char[s.size() + 1];
|
2016-08-17 17:20:19 +00:00
|
|
|
for (auto i: ostd::range(s.size())) {
|
2016-08-02 00:21:36 +00:00
|
|
|
buf[i] = toupper(s[i]);
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
buf[s.size()] = '\0';
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(buf, s.size()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("escape", "s", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
auto x = ostd::appender<ostd::String>();
|
|
|
|
util::escape_string(x, args[0].get_strr());
|
|
|
|
ostd::Size len = x.size();
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(x.get().disown(), len));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("unescape", "s", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
char *buf = new char[s.size() + 1];
|
|
|
|
auto writer = ostd::CharRange(buf, s.size() + 1);
|
|
|
|
util::unescape_string(writer, s);
|
|
|
|
writer.put('\0');
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(buf, s.size()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("concat", "V", [](TvalRange args, TaggedValue &res) {
|
2016-08-09 23:10:09 +00:00
|
|
|
auto s = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(s, args, " ");
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(s.get().iter());
|
2016-08-09 23:10:09 +00:00
|
|
|
s.get().disown();
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("concatword", "V", [](TvalRange args, TaggedValue &res) {
|
2016-08-09 23:10:09 +00:00
|
|
|
auto s = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(s, args);
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(s.get().iter());
|
2016-08-09 23:10:09 +00:00
|
|
|
s.get().disown();
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("format", "V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
if (args.empty()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::Vector<char> s;
|
|
|
|
ostd::String fs = ostd::move(args[0].get_str());
|
|
|
|
ostd::ConstCharRange f = fs.iter();
|
|
|
|
while (!f.empty()) {
|
2016-08-17 17:20:19 +00:00
|
|
|
char c = *f;
|
|
|
|
++f;
|
2016-08-02 00:21:36 +00:00
|
|
|
if ((c == '%') && !f.empty()) {
|
2016-08-17 17:20:19 +00:00
|
|
|
char ic = *f;
|
|
|
|
++f;
|
2016-08-02 00:21:36 +00:00
|
|
|
if (ic >= '1' && ic <= '9') {
|
|
|
|
int i = ic - '0';
|
2016-08-17 17:20:19 +00:00
|
|
|
ostd::String sub = ostd::move(
|
|
|
|
(ostd::Size(i) < args.size())
|
|
|
|
? args[i].get_str()
|
|
|
|
: ostd::String("")
|
|
|
|
);
|
2016-08-02 00:21:36 +00:00
|
|
|
s.push_n(sub.data(), sub.size());
|
2016-08-17 17:20:19 +00:00
|
|
|
} else {
|
|
|
|
s.push(ic);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
s.push(c);
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
s.push('\0');
|
|
|
|
ostd::Size len = s.size() - 1;
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(s.disown(), len));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("tohex", "ii", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
auto r = ostd::appender<ostd::Vector<char>>();
|
2016-08-17 17:20:19 +00:00
|
|
|
ostd::format(
|
|
|
|
r, "0x%.*X", ostd::max(args[1].get_int(), 1), args[0].get_int()
|
|
|
|
);
|
2016-08-02 00:21:36 +00:00
|
|
|
r.put('\0');
|
|
|
|
ostd::Size len = r.size() - 1;
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(r.get().disown(), len));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("substr", "siiN", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt start = args[1].get_int(), count = args[2].get_int();
|
|
|
|
CsInt numargs = args[3].get_int();
|
|
|
|
CsInt len = CsInt(s.size()), offset = ostd::clamp(start, 0, len);
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_str(ostd::ConstCharRange(
|
2016-08-02 00:21:36 +00:00
|
|
|
&s[offset],
|
2016-08-17 17:20:19 +00:00
|
|
|
(numargs >= 3) ? ostd::clamp(count, 0, len - offset) : (len - offset)
|
2016-08-02 00:21:36 +00:00
|
|
|
));
|
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strcmp", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::Equal<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command("=s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::Equal<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command("!=s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::NotEqual<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command("<s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::Less<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command(">s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::Greater<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command("<=s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::LessEqual<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
cs.add_command(">=s", "s1V", [](TvalRange args, TaggedValue &res) {
|
|
|
|
cs_strgcmp(args, res, ostd::GreaterEqual<ostd::ConstCharRange>());
|
|
|
|
});
|
|
|
|
|
|
|
|
cs.add_command("strreplace", "ssss", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
ostd::ConstCharRange oldval = args[1].get_strr(),
|
|
|
|
newval = args[2].get_strr(),
|
|
|
|
newval2 = args[3].get_strr();
|
|
|
|
if (newval2.empty()) {
|
|
|
|
newval2 = newval;
|
|
|
|
}
|
|
|
|
ostd::Vector<char> buf;
|
|
|
|
if (!oldval.size()) {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_str(s);
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (ostd::Size i = 0;; ++i) {
|
|
|
|
ostd::ConstCharRange found;
|
|
|
|
ostd::ConstCharRange trys = s;
|
2016-08-17 17:20:19 +00:00
|
|
|
for (; oldval.size() <= trys.size(); ++trys) {
|
2016-08-02 00:21:36 +00:00
|
|
|
if (trys.slice(0, oldval.size()) == oldval) {
|
|
|
|
found = trys;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found.empty()) {
|
|
|
|
auto bef = ostd::slice_until(s, found);
|
2016-08-17 17:20:19 +00:00
|
|
|
for (; !bef.empty(); ++bef) {
|
|
|
|
buf.push(*bef);
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
auto use = (i & 1) ? newval2 : newval;
|
2016-08-17 17:20:19 +00:00
|
|
|
for (; !use.empty(); ++use) {
|
|
|
|
buf.push(*use);
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
s = found + oldval.size();
|
|
|
|
} else {
|
2016-08-17 17:20:19 +00:00
|
|
|
for (; !s.empty(); ++s) {
|
|
|
|
buf.push(*s);
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
buf.push('\0');
|
|
|
|
ostd::Size len = buf.size() - 1;
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(buf.disown(), len));
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-17 17:20:19 +00:00
|
|
|
cs.add_command("strsplice", "ssii", [](TvalRange args, TaggedValue &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
ostd::ConstCharRange vals = args[1].get_strr();
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt skip = args[2].get_int(),
|
|
|
|
count = args[3].get_int();
|
|
|
|
CsInt slen = CsInt(s.size()),
|
|
|
|
vlen = CsInt(vals.size());
|
|
|
|
CsInt offset = ostd::clamp(skip, 0, slen),
|
|
|
|
len = ostd::clamp(count, 0, slen - offset);
|
2016-08-02 00:21:36 +00:00
|
|
|
char *p = new char[slen - len + vlen + 1];
|
2016-08-17 17:20:19 +00:00
|
|
|
if (offset) {
|
2016-08-02 00:21:36 +00:00
|
|
|
memcpy(p, s.data(), offset);
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
|
|
|
if (vlen) {
|
2016-08-02 00:21:36 +00:00
|
|
|
memcpy(&p[offset], vals.data(), vlen);
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
|
|
|
if (offset + len < slen) {
|
2016-08-02 00:21:36 +00:00
|
|
|
memcpy(&p[offset + vlen], &s[offset + len], slen - (offset + len));
|
2016-08-17 17:20:19 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
p[slen - len + vlen] = '\0';
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_mstr(ostd::CharRange(p, slen - len + vlen));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace cscript */
|