2016-09-07 20:57:28 +00:00
|
|
|
#include "cubescript/cubescript.hh"
|
2016-08-15 01:19:59 +00:00
|
|
|
#include "cs_util.hh"
|
2016-08-02 00:21:36 +00:00
|
|
|
|
|
|
|
namespace cscript {
|
|
|
|
|
2016-08-17 18:51:21 +00:00
|
|
|
template<typename T>
|
|
|
|
struct CsArgVal;
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct CsArgVal<CsInt> {
|
2016-08-18 18:38:30 +00:00
|
|
|
static CsInt get(CsValue &tv) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return tv.get_int();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct CsArgVal<CsFloat> {
|
2016-08-18 18:38:30 +00:00
|
|
|
static CsFloat get(CsValue &tv) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return tv.get_float();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct CsArgVal<ostd::ConstCharRange> {
|
2016-08-18 18:38:30 +00:00
|
|
|
static ostd::ConstCharRange get(CsValue &tv) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return tv.get_strr();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename F>
|
2016-09-25 13:26:38 +00:00
|
|
|
static inline void cs_list_find(
|
|
|
|
CsState &cs, CsValueRange args, CsValue &res, F cmp
|
|
|
|
) {
|
2016-08-17 18:51:21 +00:00
|
|
|
CsInt n = 0, skip = args[2].get_int();
|
|
|
|
T val = CsArgVal<T>::get(args[1]);
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[0].get_strr()); p.parse(); ++n) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (cmp(p, val)) {
|
|
|
|
res.set_int(n);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < skip; ++i) {
|
|
|
|
if (!p.parse()) {
|
|
|
|
goto notfound;
|
|
|
|
}
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
notfound:
|
|
|
|
res.set_int(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename F>
|
2016-09-25 13:26:38 +00:00
|
|
|
static inline void cs_list_assoc(
|
|
|
|
CsState &cs, CsValueRange args, CsValue &res, F cmp
|
|
|
|
) {
|
2016-08-17 18:51:21 +00:00
|
|
|
T val = CsArgVal<T>::get(args[1]);
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[0].get_strr()); p.parse();) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (cmp(p, val)) {
|
|
|
|
if (p.parse()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(p.element());
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!p.parse()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-11 17:14:18 +00:00
|
|
|
static void cs_loop_list_conc(
|
2016-08-29 17:17:11 +00:00
|
|
|
CsState &cs, CsValue &res, CsIdent *id, ostd::ConstCharRange list,
|
2016-08-30 20:29:09 +00:00
|
|
|
CsBytecode *body, bool space
|
2016-08-11 17:14:18 +00:00
|
|
|
) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{id};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
CsString r;
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, list); p.parse(); ++n) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.element());
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-08-17 18:51:21 +00:00
|
|
|
if (n && space) {
|
2016-09-15 20:34:52 +00:00
|
|
|
r += ' ';
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-18 18:38:30 +00:00
|
|
|
CsValue v;
|
2016-09-14 21:24:13 +00:00
|
|
|
switch (cs.run_loop(body, v)) {
|
|
|
|
case CsLoopState::Break:
|
|
|
|
goto end;
|
|
|
|
case CsLoopState::Continue:
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
r += v.get_str();
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-14 21:24:13 +00:00
|
|
|
end:
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(ostd::move(r));
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
int cs_list_includes(
|
|
|
|
CsState &cs, ostd::ConstCharRange list, ostd::ConstCharRange needle
|
|
|
|
) {
|
2016-08-02 00:21:36 +00:00
|
|
|
int offset = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, list); p.parse();) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (p.item == needle) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return offset;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
++offset;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-08-17 18:51:21 +00:00
|
|
|
template<bool PushList, bool Swap, typename F>
|
2016-09-25 13:26:38 +00:00
|
|
|
static inline void cs_list_merge(
|
|
|
|
CsState &cs, CsValueRange args, CsValue &res, F cmp
|
|
|
|
) {
|
2016-08-17 18:51:21 +00:00
|
|
|
ostd::ConstCharRange list = args[0].get_strr();
|
|
|
|
ostd::ConstCharRange elems = args[1].get_strr();
|
2016-09-15 20:34:52 +00:00
|
|
|
CsString buf;
|
2016-08-17 18:51:21 +00:00
|
|
|
if (PushList) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += list;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
if (Swap) {
|
|
|
|
ostd::swap(list, elems);
|
|
|
|
}
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, list); p.parse();) {
|
|
|
|
if (cmp(cs_list_includes(cs, elems, p.item), 0)) {
|
2016-08-17 18:52:18 +00:00
|
|
|
if (!buf.empty()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += ' ';
|
2016-08-17 18:52:18 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += p.quote;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(ostd::move(buf));
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 00:21:36 +00:00
|
|
|
static void cs_init_lib_list_sort(CsState &cs);
|
|
|
|
|
2016-09-11 21:13:39 +00:00
|
|
|
void cs_init_lib_list(CsState &gcs) {
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listlen", "s", [](auto &cs, auto args, auto &res) {
|
2016-10-24 00:33:04 +00:00
|
|
|
res.set_int(CsInt(util::ListParser(cs, args[0].get_strr()).count()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (args.empty()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-21 00:34:03 +00:00
|
|
|
CsString str = ostd::move(args[0].get_str());
|
2016-09-25 13:26:38 +00:00
|
|
|
util::ListParser p(cs, str);
|
2016-08-02 00:21:36 +00:00
|
|
|
p.item = str;
|
|
|
|
for (ostd::Size i = 1; i < args.size(); ++i) {
|
|
|
|
p.input = str;
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt pos = args[i].get_int();
|
2016-08-17 18:51:21 +00:00
|
|
|
for (; pos > 0; --pos) {
|
|
|
|
if (!p.parse()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pos > 0 || !p.parse()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
p.item = p.quote = ostd::ConstCharRange();
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(p.element());
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("sublist", "siiN", [](auto &cs, auto args, auto &res) {
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt skip = args[1].get_int(),
|
|
|
|
count = args[2].get_int(),
|
2016-10-24 00:38:52 +00:00
|
|
|
numargs = args[3].get_int();
|
2016-08-02 00:21:36 +00:00
|
|
|
|
2016-09-09 15:43:23 +00:00
|
|
|
CsInt offset = ostd::max(skip, CsInt(0)),
|
|
|
|
len = (numargs >= 3) ? ostd::max(count, CsInt(0)) : -1;
|
2016-08-02 00:21:36 +00:00
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
util::ListParser p(cs, args[0].get_strr());
|
2016-08-17 18:51:21 +00:00
|
|
|
for (CsInt i = 0; i < offset; ++i) {
|
2016-08-02 00:21:36 +00:00
|
|
|
if (!p.parse()) break;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
if (len < 0) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (offset > 0) {
|
2016-08-02 00:21:36 +00:00
|
|
|
p.skip();
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_str(p.input);
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char const *list = p.input.data();
|
|
|
|
p.quote = ostd::ConstCharRange();
|
2016-08-17 18:51:21 +00:00
|
|
|
if (len > 0 && p.parse()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
while (--len > 0 && p.parse());
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_str(ostd::ConstCharRange(list, qend - list));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{args[0].get_ident()};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(-1);
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[2].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = -1;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[1].get_strr()); p.parse();) {
|
2016-08-02 00:21:36 +00:00
|
|
|
++n;
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.item);
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-08-02 00:21:36 +00:00
|
|
|
if (cs.run_bool(body)) {
|
2016-08-14 16:35:38 +00:00
|
|
|
res.set_int(CsInt(n));
|
2016-08-31 17:49:24 +00:00
|
|
|
return;
|
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-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("listassoc", "rse", [](auto &cs, auto args, auto &res) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{args[0].get_ident()};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[2].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = -1;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[1].get_strr()); p.parse();) {
|
2016-08-02 00:21:36 +00:00
|
|
|
++n;
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.item);
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-08-02 00:21:36 +00:00
|
|
|
if (cs.run_bool(body)) {
|
|
|
|
if (p.parse()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(p.element());
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-08-17 18:51:21 +00:00
|
|
|
if (!p.parse()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
break;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_find<CsInt>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, CsInt val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return cs_parse_int(p.item) == val;
|
|
|
|
}
|
|
|
|
);
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_find<CsFloat>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, CsFloat val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return cs_parse_float(p.item) == val;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_find<ostd::ConstCharRange>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, ostd::ConstCharRange val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return p.item == val;
|
|
|
|
}
|
|
|
|
);
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_assoc<CsInt>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, CsInt val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return cs_parse_int(p.item) == val;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_assoc<CsFloat>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, CsFloat val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return cs_parse_float(p.item) == val;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) {
|
2016-08-17 18:51:21 +00:00
|
|
|
cs_list_assoc<ostd::ConstCharRange>(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs, args, res, [](const util::ListParser &p, ostd::ConstCharRange val) {
|
2016-08-17 18:51:21 +00:00
|
|
|
return p.item == val;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2016-08-02 00:21:36 +00:00
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("looplist", "rse", [](auto &cs, auto args, auto &) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{args[0].get_ident()};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[2].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[1].get_strr()); p.parse(); ++n) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.element());
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-09-14 21:24:13 +00:00
|
|
|
switch (cs.run_loop(body)) {
|
|
|
|
case CsLoopState::Break:
|
|
|
|
goto end;
|
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-14 21:24:13 +00:00
|
|
|
end:
|
|
|
|
return;
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("looplist2", "rrse", [](auto &cs, auto args, auto &) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv1{args[0].get_ident()}, idv2{args[1].get_ident()};
|
|
|
|
if (!idv1.has_alias() || !idv2.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[3].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[2].get_strr()); p.parse(); n += 2) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv1.set_str(p.element());
|
|
|
|
if (p.parse()) {
|
|
|
|
idv2.set_str(p.element());
|
|
|
|
} else {
|
|
|
|
idv2.set_str("");
|
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
idv1.push();
|
|
|
|
idv2.push();
|
2016-09-14 21:24:13 +00:00
|
|
|
switch (cs.run_loop(body)) {
|
|
|
|
case CsLoopState::Break:
|
|
|
|
goto end;
|
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-14 21:24:13 +00:00
|
|
|
end:
|
|
|
|
return;
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("looplist3", "rrrse", [](auto &cs, auto args, auto &) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv1{args[0].get_ident()};
|
|
|
|
CsStackedValue idv2{args[1].get_ident()};
|
|
|
|
CsStackedValue idv3{args[2].get_ident()};
|
|
|
|
if (!idv1.has_alias() || !idv2.has_alias() || !idv3.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[4].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[3].get_strr()); p.parse(); n += 3) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv1.set_str(p.element());
|
|
|
|
if (p.parse()) {
|
|
|
|
idv2.set_str(p.element());
|
|
|
|
} else {
|
|
|
|
idv2.set_str("");
|
|
|
|
}
|
|
|
|
if (p.parse()) {
|
|
|
|
idv3.set_str(p.element());
|
|
|
|
} else {
|
|
|
|
idv3.set_str("");
|
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
idv1.push();
|
|
|
|
idv2.push();
|
|
|
|
idv3.push();
|
2016-09-14 21:24:13 +00:00
|
|
|
switch (cs.run_loop(body)) {
|
|
|
|
case CsLoopState::Break:
|
|
|
|
goto end;
|
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-14 21:24:13 +00:00
|
|
|
end:
|
|
|
|
return;
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("looplistconcat", "rse", [](auto &cs, auto args, auto &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
cs_loop_list_conc(
|
2016-08-11 17:14:18 +00:00
|
|
|
cs, res, args[0].get_ident(), args[1].get_strr(),
|
2016-08-02 00:21:36 +00:00
|
|
|
args[2].get_code(), true
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2016-09-11 21:13:39 +00:00
|
|
|
gcs.new_command("looplistconcatword", "rse", [](
|
2016-09-14 22:42:19 +00:00
|
|
|
auto &cs, auto args, auto &res
|
2016-08-17 18:51:21 +00:00
|
|
|
) {
|
2016-08-02 00:21:36 +00:00
|
|
|
cs_loop_list_conc(
|
2016-08-11 17:14:18 +00:00
|
|
|
cs, res, args[0].get_ident(), args[1].get_strr(),
|
2016-08-02 00:21:36 +00:00
|
|
|
args[2].get_code(), false
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("listfilter", "rse", [](auto &cs, auto args, auto &res) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{args[0].get_ident()};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[2].get_code();
|
2016-09-15 20:34:52 +00:00
|
|
|
CsString r;
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[1].get_strr()); p.parse(); ++n) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.item);
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-08-02 00:21:36 +00:00
|
|
|
if (cs.run_bool(body)) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (r.size()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
r += ' ';
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
r += p.quote;
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(ostd::move(r));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("listcount", "rse", [](auto &cs, auto args, auto &res) {
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue idv{args[0].get_ident()};
|
|
|
|
if (!idv.has_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-31 17:49:24 +00:00
|
|
|
auto body = args[2].get_code();
|
2016-08-02 00:21:36 +00:00
|
|
|
int n = 0, r = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, args[1].get_strr()); p.parse(); ++n) {
|
2016-09-15 20:34:52 +00:00
|
|
|
idv.set_str(p.item);
|
2016-08-31 17:49:24 +00:00
|
|
|
idv.push();
|
2016-08-17 18:51:21 +00:00
|
|
|
if (cs.run_bool(body)) {
|
2016-08-02 00:21:36 +00:00
|
|
|
r++;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(r);
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) {
|
2016-09-15 20:34:52 +00:00
|
|
|
auto buf = ostd::appender<CsString>();
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
ostd::ConstCharRange conj = args[1].get_strr();
|
2016-10-24 00:33:04 +00:00
|
|
|
ostd::Size len = util::ListParser(cs, s).count();
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::Size n = 0;
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, s); p.parse(); ++n) {
|
2016-08-02 00:21:36 +00:00
|
|
|
if (!p.quote.empty() && (p.quote.front() == '"')) {
|
2016-09-15 20:34:52 +00:00
|
|
|
util::unescape_string(buf, p.item);
|
2016-08-02 00:21:36 +00:00
|
|
|
} else {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf.put_n(p.item.data(), p.item.size());
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
if ((n + 1) < len) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if ((len > 2) || conj.empty()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf.put(',');
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
if ((n + 2 == len) && !conj.empty()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf.put(' ');
|
|
|
|
buf.put_n(conj.data(), conj.size());
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
buf.put(' ');
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(ostd::move(buf.get()));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) {
|
2016-08-11 17:14:18 +00:00
|
|
|
res.set_int(
|
2016-09-25 13:26:38 +00:00
|
|
|
cs_list_includes(cs, args[0].get_strr(), args[1].get_strr())
|
2016-08-02 00:21:36 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listdel", "ss", [](auto &cs, auto args, auto &res) {
|
|
|
|
cs_list_merge<false, false>(cs, args, res, ostd::Less<int>());
|
2016-08-17 18:51:21 +00:00
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listintersect", "ss", [](auto &cs, auto args, auto &res) {
|
|
|
|
cs_list_merge<false, false>(cs, args, res, ostd::GreaterEqual<int>());
|
2016-08-17 18:51:21 +00:00
|
|
|
});
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listunion", "ss", [](auto &cs, auto args, auto &res) {
|
|
|
|
cs_list_merge<true, true>(cs, args, res, ostd::Less<int>());
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
gcs.new_command("listsplice", "ssii", [](auto &cs, auto args, auto &res) {
|
2016-09-09 15:43:23 +00:00
|
|
|
CsInt offset = ostd::max(args[2].get_int(), CsInt(0));
|
|
|
|
CsInt len = ostd::max(args[3].get_int(), CsInt(0));
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange s = args[0].get_strr();
|
|
|
|
ostd::ConstCharRange vals = args[1].get_strr();
|
|
|
|
char const *list = s.data();
|
2016-09-25 13:26:38 +00:00
|
|
|
util::ListParser p(cs, s);
|
2016-08-17 18:51:21 +00:00
|
|
|
for (CsInt i = 0; i < offset; ++i) {
|
|
|
|
if (!p.parse()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
break;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
2016-09-15 20:34:52 +00:00
|
|
|
CsString buf;
|
2016-08-17 18:51:21 +00:00
|
|
|
if (qend > list) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += ostd::ConstCharRange(list, qend - list);
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
if (!vals.empty()) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (!buf.empty()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += ' ';
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += vals;
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-08-17 18:51:21 +00:00
|
|
|
for (CsInt i = 0; i < len; ++i) {
|
|
|
|
if (!p.parse()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
break;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
p.skip();
|
2016-08-17 18:51:21 +00:00
|
|
|
if (!p.input.empty()) {
|
|
|
|
switch (p.input.front()) {
|
|
|
|
case ')':
|
|
|
|
case ']':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!buf.empty()) {
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += ' ';
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
buf += p.input;
|
2016-08-17 18:51:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-15 20:34:52 +00:00
|
|
|
res.set_str(ostd::move(buf));
|
2016-08-02 00:21:36 +00:00
|
|
|
});
|
|
|
|
|
2016-09-11 21:13:39 +00:00
|
|
|
cs_init_lib_list_sort(gcs);
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ListSortItem {
|
2016-09-15 20:45:28 +00:00
|
|
|
ostd::ConstCharRange str;
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::ConstCharRange quote;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ListSortFun {
|
|
|
|
CsState &cs;
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue &xv, &yv;
|
2016-08-28 17:40:18 +00:00
|
|
|
CsBytecode *body;
|
2016-08-02 00:21:36 +00:00
|
|
|
|
|
|
|
bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
|
2016-08-31 17:49:24 +00:00
|
|
|
xv.set_cstr(xval.str);
|
|
|
|
yv.set_cstr(yval.str);
|
|
|
|
xv.push();
|
|
|
|
yv.push();
|
2016-08-02 00:21:36 +00:00
|
|
|
return cs.run_bool(body);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void cs_list_sort(
|
2016-09-11 21:13:39 +00:00
|
|
|
CsState &cs, CsValue &res, ostd::ConstCharRange list,
|
|
|
|
CsIdent *x, CsIdent *y, CsBytecode *body, CsBytecode *unique
|
2016-08-02 00:21:36 +00:00
|
|
|
) {
|
2016-08-17 18:51:21 +00:00
|
|
|
if (x == y || !x->is_alias() || !y->is_alias()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-08-02 00:21:36 +00:00
|
|
|
|
2016-08-29 17:17:11 +00:00
|
|
|
CsAlias *xa = static_cast<CsAlias *>(x), *ya = static_cast<CsAlias *>(y);
|
2016-08-17 22:06:39 +00:00
|
|
|
|
2016-08-21 00:34:03 +00:00
|
|
|
CsVector<ListSortItem> items;
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::Size total = 0;
|
|
|
|
|
2016-09-25 13:26:38 +00:00
|
|
|
for (util::ListParser p(cs, list); p.parse();) {
|
2016-09-15 20:45:28 +00:00
|
|
|
ListSortItem item = { p.item, p.quote };
|
2016-08-02 00:21:36 +00:00
|
|
|
items.push(item);
|
|
|
|
total += item.quote.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (items.empty()) {
|
2016-09-15 20:45:28 +00:00
|
|
|
res.set_str(list);
|
2016-08-02 00:21:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-31 17:49:24 +00:00
|
|
|
CsStackedValue xval{xa}, yval{ya};
|
|
|
|
xval.set_null();
|
|
|
|
yval.set_null();
|
|
|
|
xval.push();
|
|
|
|
yval.push();
|
2016-08-02 00:21:36 +00:00
|
|
|
|
|
|
|
ostd::Size totaluniq = total;
|
|
|
|
ostd::Size nuniq = items.size();
|
|
|
|
if (body) {
|
2016-08-31 17:49:24 +00:00
|
|
|
ListSortFun f = { cs, xval, yval, body };
|
2016-08-02 00:21:36 +00:00
|
|
|
ostd::sort_cmp(items.iter(), f);
|
2016-08-29 17:17:11 +00:00
|
|
|
if (!cs_code_is_empty(unique)) {
|
2016-08-02 00:21:36 +00:00
|
|
|
f.body = unique;
|
|
|
|
totaluniq = items[0].quote.size();
|
|
|
|
nuniq = 1;
|
|
|
|
for (ostd::Size i = 1; i < items.size(); i++) {
|
|
|
|
ListSortItem &item = items[i];
|
2016-08-17 18:51:21 +00:00
|
|
|
if (f(items[i - 1], item)) {
|
2016-08-02 00:21:36 +00:00
|
|
|
item.quote = nullptr;
|
2016-08-17 18:51:21 +00:00
|
|
|
} else {
|
2016-08-02 00:21:36 +00:00
|
|
|
totaluniq += item.quote.size();
|
|
|
|
++nuniq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-08-31 17:49:24 +00:00
|
|
|
ListSortFun f = { cs, xval, yval, unique };
|
2016-08-02 00:21:36 +00:00
|
|
|
totaluniq = items[0].quote.size();
|
|
|
|
nuniq = 1;
|
|
|
|
for (ostd::Size i = 1; i < items.size(); i++) {
|
|
|
|
ListSortItem &item = items[i];
|
|
|
|
for (ostd::Size j = 0; j < i; ++j) {
|
|
|
|
ListSortItem &prev = items[j];
|
|
|
|
if (!prev.quote.empty() && f(item, prev)) {
|
|
|
|
item.quote = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!item.quote.empty()) {
|
|
|
|
totaluniq += item.quote.size();
|
|
|
|
++nuniq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-31 17:49:24 +00:00
|
|
|
xval.pop();
|
|
|
|
yval.pop();
|
2016-08-02 00:21:36 +00:00
|
|
|
|
2016-09-15 20:45:28 +00:00
|
|
|
CsString sorted;
|
|
|
|
sorted.reserve(totaluniq + ostd::max(nuniq - 1, ostd::Size(0)));
|
2016-08-02 00:21:36 +00:00
|
|
|
for (ostd::Size i = 0; i < items.size(); ++i) {
|
|
|
|
ListSortItem &item = items[i];
|
2016-08-17 18:51:21 +00:00
|
|
|
if (item.quote.empty()) {
|
2016-08-02 00:21:36 +00:00
|
|
|
continue;
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
|
|
|
if (i) {
|
2016-09-15 20:45:28 +00:00
|
|
|
sorted += ' ';
|
2016-08-17 18:51:21 +00:00
|
|
|
}
|
2016-09-15 20:45:28 +00:00
|
|
|
sorted += item.quote;
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
2016-09-15 20:45:28 +00:00
|
|
|
res.set_str(ostd::move(sorted));
|
2016-08-02 00:21:36 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 21:13:39 +00:00
|
|
|
static void cs_init_lib_list_sort(CsState &gcs) {
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("sortlist", "srree", [](auto &cs, auto args, auto &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
cs_list_sort(
|
2016-08-11 17:14:18 +00:00
|
|
|
cs, res, args[0].get_strr(), args[1].get_ident(),
|
|
|
|
args[2].get_ident(), args[3].get_code(), args[4].get_code()
|
2016-08-02 00:21:36 +00:00
|
|
|
);
|
|
|
|
});
|
2016-09-14 22:42:19 +00:00
|
|
|
gcs.new_command("uniquelist", "srre", [](auto &cs, auto args, auto &res) {
|
2016-08-02 00:21:36 +00:00
|
|
|
cs_list_sort(
|
2016-08-11 17:14:18 +00:00
|
|
|
cs, res, args[0].get_strr(), args[1].get_ident(),
|
|
|
|
args[2].get_ident(), nullptr, args[3].get_code()
|
2016-08-02 00:21:36 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace cscript */
|