2017-02-08 01:07:35 +01:00
|
|
|
#include <functional>
|
2021-03-20 06:18:31 +01:00
|
|
|
#include <iterator>
|
2017-02-08 01:07:35 +01:00
|
|
|
|
2017-06-20 21:21:39 +02:00
|
|
|
#include <cubescript/cubescript.hh>
|
2021-03-23 01:11:21 +01:00
|
|
|
#include "cs_std.hh"
|
2021-03-23 22:17:25 +01:00
|
|
|
#include "cs_parser.hh"
|
2021-03-25 01:37:13 +01:00
|
|
|
#include "cs_thread.hh"
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
namespace cubescript {
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2016-08-17 20:51:21 +02:00
|
|
|
template<typename T>
|
2021-03-23 23:29:32 +01:00
|
|
|
struct arg_val;
|
2016-08-17 20:51:21 +02:00
|
|
|
|
|
|
|
template<>
|
2021-03-23 23:29:32 +01:00
|
|
|
struct arg_val<integer_type> {
|
2021-04-11 03:32:14 +02:00
|
|
|
static integer_type get(any_value &tv, state &) {
|
2021-04-06 00:54:46 +02:00
|
|
|
return tv.get_integer();
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2021-03-23 23:29:32 +01:00
|
|
|
struct arg_val<float_type> {
|
2021-04-11 03:32:14 +02:00
|
|
|
static float_type get(any_value &tv, state &) {
|
2016-08-17 20:51:21 +02:00
|
|
|
return tv.get_float();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2021-03-23 23:29:32 +01:00
|
|
|
struct arg_val<std::string_view> {
|
2021-04-11 03:32:14 +02:00
|
|
|
static std::string_view get(any_value &tv, state &cs) {
|
|
|
|
return tv.get_string(cs);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
static inline void list_find(
|
2021-04-15 20:26:49 +02:00
|
|
|
state &cs, span_type<any_value> args, any_value &res, F cmp
|
2016-09-25 15:26:38 +02:00
|
|
|
) {
|
2021-04-06 00:54:46 +02:00
|
|
|
integer_type n = 0, skip = args[2].get_integer();
|
2021-04-11 03:32:14 +02:00
|
|
|
T val = arg_val<T>::get(args[1], cs);
|
|
|
|
for (list_parser p{cs, args[0].get_string(cs)}; p.parse(); ++n) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if (cmp(p, val)) {
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_integer(n);
|
2016-08-17 20:51:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < skip; ++i) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) {
|
2016-08-17 20:51:21 +02:00
|
|
|
goto notfound;
|
|
|
|
}
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
notfound:
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_integer(-1);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
static inline void list_assoc(
|
2021-04-15 20:26:49 +02:00
|
|
|
state &cs, span_type<any_value> args, any_value &res, F cmp
|
2016-09-25 15:26:38 +02:00
|
|
|
) {
|
2021-04-11 03:32:14 +02:00
|
|
|
T val = arg_val<T>::get(args[1], cs);
|
|
|
|
for (list_parser p{cs, args[0].get_string(cs)}; p.parse();) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if (cmp(p, val)) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (p.parse()) {
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_string(p.get_item());
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) {
|
2016-08-17 20:51:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
static void loop_list_conc(
|
2021-04-24 23:33:19 +02:00
|
|
|
state &cs, any_value &res, ident &id, std::string_view list,
|
2021-04-01 05:05:43 +02:00
|
|
|
bcode_ref &&body, bool space
|
2016-08-11 19:14:18 +02:00
|
|
|
) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, id};
|
|
|
|
any_value idv{};
|
|
|
|
charbuf r{cs};
|
|
|
|
int n = 0;
|
|
|
|
for (list_parser p{cs, list}; p.parse(); ++n) {
|
|
|
|
idv.set_string(p.get_item());
|
|
|
|
st.set(std::move(idv));
|
|
|
|
if (n && space) {
|
|
|
|
r.push_back(' ');
|
2016-09-14 23:24:13 +02:00
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
any_value v{};
|
|
|
|
switch (cs.run_loop(body, v)) {
|
|
|
|
case loop_state::BREAK:
|
|
|
|
goto end;
|
|
|
|
case loop_state::CONTINUE:
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r.append(v.get_string(cs));
|
2021-03-30 20:55:50 +02:00
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
end:
|
|
|
|
res.set_string(r.str(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
int list_includes(
|
|
|
|
state &cs, std::string_view list, std::string_view needle
|
2016-09-25 15:26:38 +02:00
|
|
|
) {
|
2016-08-02 02:21:36 +02:00
|
|
|
int offset = 0;
|
2021-03-23 23:29:32 +01:00
|
|
|
for (list_parser p{cs, list}; p.parse();) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (p.get_raw_item() == needle) {
|
2016-08-02 02:21:36 +02:00
|
|
|
return offset;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
++offset;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-08-17 20:51:21 +02:00
|
|
|
template<bool PushList, bool Swap, typename F>
|
2021-03-23 23:29:32 +01:00
|
|
|
static inline void list_merge(
|
2021-04-15 20:26:49 +02:00
|
|
|
state &cs, span_type<any_value> args, any_value &res, F cmp
|
2016-09-25 15:26:38 +02:00
|
|
|
) {
|
2021-04-11 03:32:14 +02:00
|
|
|
std::string_view list = args[0].get_string(cs);
|
|
|
|
std::string_view elems = args[1].get_string(cs);
|
2021-03-23 23:29:32 +01:00
|
|
|
charbuf buf{cs};
|
2016-08-17 20:51:21 +02:00
|
|
|
if (PushList) {
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.append(list);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
if (Swap) {
|
2017-01-29 15:56:38 +01:00
|
|
|
std::swap(list, elems);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
for (list_parser p{cs, list}; p.parse();) {
|
|
|
|
if (cmp(list_includes(cs, elems, p.get_raw_item()), 0)) {
|
2016-08-17 20:52:18 +02:00
|
|
|
if (!buf.empty()) {
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.push_back(' ');
|
2016-08-17 20:52:18 +02:00
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
buf.append(p.get_quoted_item());
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(buf.str(), cs);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
static void init_lib_list_sort(state &cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) {
|
|
|
|
new_cmd_quiet(gcs, "listlen", "s", [](auto &cs, auto args, auto &res) {
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_integer(
|
|
|
|
integer_type(list_parser{cs, args[0].get_string(cs)}.count())
|
|
|
|
);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "at", "si1V", [](auto &cs, auto args, auto &res) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if (args.empty()) {
|
2016-08-02 02:21:36 +02:00
|
|
|
return;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
if (args.size() <= 1) {
|
|
|
|
res = args[0];
|
|
|
|
return;
|
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
auto str = args[0].get_string(cs);
|
2021-03-23 23:29:32 +01:00
|
|
|
list_parser p{cs, str};
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t i = 1; i < args.size(); ++i) {
|
2021-03-20 02:26:37 +01:00
|
|
|
p.set_input(str);
|
2021-04-06 00:54:46 +02:00
|
|
|
integer_type pos = args[i].get_integer();
|
2016-08-17 20:51:21 +02:00
|
|
|
for (; pos > 0; --pos) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) {
|
2016-08-17 20:51:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
if (pos > 0 || !p.parse()) {
|
|
|
|
p.set_input("");
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_string(p.get_item());
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "sublist", "siiN", [](auto &cs, auto args, auto &res) {
|
2021-04-06 00:54:46 +02:00
|
|
|
integer_type skip = args[1].get_integer(),
|
|
|
|
count = args[2].get_integer(),
|
|
|
|
numargs = args[3].get_integer();
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
integer_type offset = std::max(skip, integer_type(0)),
|
|
|
|
len = (numargs >= 3) ? std::max(count, integer_type(0)) : -1;
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-04-11 03:32:14 +02:00
|
|
|
list_parser p{cs, args[0].get_string(cs)};
|
2021-03-23 23:29:32 +01:00
|
|
|
for (integer_type i = 0; i < offset; ++i) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) break;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
if (len < 0) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if (offset > 0) {
|
2021-03-20 19:34:26 +01:00
|
|
|
p.skip_until_item();
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(p.get_input(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-20 02:26:37 +01:00
|
|
|
char const *list = p.get_input().data();
|
2021-03-20 19:34:26 +01:00
|
|
|
if (len > 0 && p.parse()) {
|
|
|
|
while (--len > 0 && p.parse());
|
|
|
|
} else {
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string("", cs);
|
2021-03-20 19:34:26 +01:00
|
|
|
return;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
auto quote = p.get_quoted_item();
|
|
|
|
auto *qend = "e[quote.size()];
|
2021-04-12 19:53:24 +02:00
|
|
|
res.set_string(make_str_view(list, qend), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listfind", "rse", [](auto &cs, auto args, auto &res) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, args[0]};
|
|
|
|
any_value idv{};
|
|
|
|
auto body = args[2].get_code();
|
|
|
|
int n = -1;
|
|
|
|
for (list_parser p{cs, args[1].get_string(cs)}; p.parse();) {
|
|
|
|
++n;
|
|
|
|
idv.set_string(p.get_raw_item(), cs);
|
|
|
|
st.set(std::move(idv));
|
|
|
|
if (cs.run(body).get_bool()) {
|
|
|
|
res.set_integer(integer_type(n));
|
|
|
|
return;
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_integer(-1);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listassoc", "rse", [](auto &cs, auto args, auto &res) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, args[0]};
|
|
|
|
any_value idv{};
|
|
|
|
auto body = args[2].get_code();
|
|
|
|
int n = -1;
|
|
|
|
for (list_parser p{cs, args[1].get_string(cs)}; p.parse();) {
|
|
|
|
++n;
|
|
|
|
idv.set_string(p.get_raw_item(), cs);
|
|
|
|
st.set(std::move(idv));
|
|
|
|
if (cs.run(body).get_bool()) {
|
|
|
|
if (p.parse()) {
|
|
|
|
res.set_string(p.get_item());
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!p.parse()) {
|
|
|
|
break;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listfind=", "i", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_find<integer_type>(
|
|
|
|
cs, args, res, [](list_parser const &p, integer_type val) {
|
2021-03-23 01:45:35 +01:00
|
|
|
return parse_int(p.get_raw_item()) == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listfind=f", "f", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_find<float_type>(
|
|
|
|
cs, args, res, [](list_parser const &p, float_type val) {
|
2021-03-23 01:45:35 +01:00
|
|
|
return parse_float(p.get_raw_item()) == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listfind=s", "s", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_find<std::string_view>(
|
|
|
|
cs, args, res, [](list_parser const &p, std::string_view val) {
|
2021-03-20 19:34:26 +01:00
|
|
|
return p.get_raw_item() == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listassoc=", "i", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_assoc<integer_type>(
|
|
|
|
cs, args, res, [](list_parser const &p, integer_type val) {
|
2021-03-23 01:45:35 +01:00
|
|
|
return parse_int(p.get_raw_item()) == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listassoc=f", "f", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_assoc<float_type>(
|
|
|
|
cs, args, res, [](list_parser const &p, float_type val) {
|
2021-03-23 01:45:35 +01:00
|
|
|
return parse_float(p.get_raw_item()) == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listassoc=s", "s", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_assoc<std::string_view>(
|
|
|
|
cs, args, res, [](list_parser const &p, std::string_view val) {
|
2021-03-20 19:34:26 +01:00
|
|
|
return p.get_raw_item() == val;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "looplist", "rse", [](auto &cs, auto args, auto &) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, args[0]};
|
|
|
|
any_value idv{};
|
|
|
|
auto body = args[2].get_code();
|
|
|
|
int n = 0;
|
|
|
|
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
|
|
|
|
idv.set_string(p.get_item());
|
|
|
|
st.set(std::move(idv));
|
|
|
|
switch (cs.run_loop(body)) {
|
|
|
|
case loop_state::BREAK:
|
|
|
|
return;
|
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
2016-09-14 23:24:13 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "looplist2", "rrse", [](auto &cs, auto args, auto &) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st1{cs, args[0]};
|
|
|
|
alias_local st2{cs, args[1]};
|
2021-04-11 03:32:14 +02:00
|
|
|
any_value idv{};
|
2016-08-31 19:49:24 +02:00
|
|
|
auto body = args[3].get_code();
|
2016-08-02 02:21:36 +02:00
|
|
|
int n = 0;
|
2021-04-11 03:32:14 +02:00
|
|
|
for (list_parser p{cs, args[2].get_string(cs)}; p.parse(); n += 2) {
|
2021-04-06 00:54:46 +02:00
|
|
|
idv.set_string(p.get_item());
|
2021-03-30 20:55:50 +02:00
|
|
|
st1.set(std::move(idv));
|
2021-03-20 19:34:26 +01:00
|
|
|
if (p.parse()) {
|
2021-04-06 00:54:46 +02:00
|
|
|
idv.set_string(p.get_item());
|
2016-09-15 22:34:52 +02:00
|
|
|
} else {
|
2021-04-11 03:32:14 +02:00
|
|
|
idv.set_string("", cs);
|
2016-09-15 22:34:52 +02:00
|
|
|
}
|
2021-03-30 20:55:50 +02:00
|
|
|
st2.set(std::move(idv));
|
2016-09-14 23:24:13 +02:00
|
|
|
switch (cs.run_loop(body)) {
|
2021-03-23 23:29:32 +01:00
|
|
|
case loop_state::BREAK:
|
2021-03-30 20:55:50 +02:00
|
|
|
return;
|
2016-09-14 23:24:13 +02:00
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "looplist3", "rrrse", [](auto &cs, auto args, auto &) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st1{cs, args[0]};
|
|
|
|
alias_local st2{cs, args[1]};
|
|
|
|
alias_local st3{cs, args[2]};
|
2021-04-11 03:32:14 +02:00
|
|
|
any_value idv{};
|
2016-08-31 19:49:24 +02:00
|
|
|
auto body = args[4].get_code();
|
2016-08-02 02:21:36 +02:00
|
|
|
int n = 0;
|
2021-04-11 03:32:14 +02:00
|
|
|
for (list_parser p{cs, args[3].get_string(cs)}; p.parse(); n += 3) {
|
2021-04-06 00:54:46 +02:00
|
|
|
idv.set_string(p.get_item());
|
2021-03-30 20:55:50 +02:00
|
|
|
st1.set(std::move(idv));
|
2021-03-20 19:34:26 +01:00
|
|
|
if (p.parse()) {
|
2021-04-06 00:54:46 +02:00
|
|
|
idv.set_string(p.get_item());
|
2016-09-15 22:34:52 +02:00
|
|
|
} else {
|
2021-04-11 03:32:14 +02:00
|
|
|
idv.set_string("", cs);
|
2016-09-15 22:34:52 +02:00
|
|
|
}
|
2021-03-30 20:55:50 +02:00
|
|
|
st2.set(std::move(idv));
|
2021-03-20 19:34:26 +01:00
|
|
|
if (p.parse()) {
|
2021-04-06 00:54:46 +02:00
|
|
|
idv.set_string(p.get_item());
|
2016-09-15 22:34:52 +02:00
|
|
|
} else {
|
2021-04-11 03:32:14 +02:00
|
|
|
idv.set_string("", cs);
|
2016-09-15 22:34:52 +02:00
|
|
|
}
|
2021-03-30 20:55:50 +02:00
|
|
|
st3.set(std::move(idv));
|
2016-09-14 23:24:13 +02:00
|
|
|
switch (cs.run_loop(body)) {
|
2021-03-23 23:29:32 +01:00
|
|
|
case loop_state::BREAK:
|
2021-03-30 20:55:50 +02:00
|
|
|
return;
|
2016-09-14 23:24:13 +02:00
|
|
|
default: /* continue and normal */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "looplistconcat", "rse", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
loop_list_conc(
|
2021-04-24 23:33:19 +02:00
|
|
|
cs, res, args[0].get_ident(cs), args[1].get_string(cs),
|
2016-08-02 02:21:36 +02:00
|
|
|
args[2].get_code(), true
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "looplistconcatword", "rse", [](
|
2016-09-15 00:42:19 +02:00
|
|
|
auto &cs, auto args, auto &res
|
2016-08-17 20:51:21 +02:00
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
loop_list_conc(
|
2021-04-24 23:33:19 +02:00
|
|
|
cs, res, args[0].get_ident(cs), args[1].get_string(cs),
|
2016-08-02 02:21:36 +02:00
|
|
|
args[2].get_code(), false
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listfilter", "rse", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, args[0]};
|
|
|
|
any_value idv{};
|
|
|
|
auto body = args[2].get_code();
|
|
|
|
charbuf r{cs};
|
|
|
|
int n = 0;
|
|
|
|
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
|
|
|
|
idv.set_string(p.get_raw_item(), cs);
|
|
|
|
st.set(std::move(idv));
|
|
|
|
if (cs.run(body).get_bool()) {
|
|
|
|
if (r.size()) {
|
|
|
|
r.push_back(' ');
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
r.append(p.get_quoted_item());
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
res.set_string(r.str(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listcount", "rse", [](auto &cs, auto args, auto &res) {
|
2021-04-24 23:33:19 +02:00
|
|
|
alias_local st{cs, args[0]};
|
|
|
|
any_value idv{};
|
|
|
|
auto body = args[2].get_code();
|
|
|
|
int n = 0, r = 0;
|
|
|
|
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
|
|
|
|
idv.set_string(p.get_raw_item(), cs);
|
|
|
|
st.set(std::move(idv));
|
|
|
|
if (cs.run(body).get_bool()) {
|
|
|
|
r++;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-04-24 23:33:19 +02:00
|
|
|
res.set_integer(r);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "prettylist", "ss", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
charbuf buf{cs};
|
2021-04-11 03:32:14 +02:00
|
|
|
std::string_view s = args[0].get_string(cs);
|
|
|
|
std::string_view conj = args[1].get_string(cs);
|
2021-03-23 23:29:32 +01:00
|
|
|
list_parser p{cs, s};
|
2021-03-20 19:34:26 +01:00
|
|
|
size_t len = p.count();
|
2017-01-25 02:09:50 +01:00
|
|
|
size_t n = 0;
|
2021-03-20 19:34:26 +01:00
|
|
|
for (p.set_input(s); p.parse(); ++n) {
|
|
|
|
auto qi = p.get_quoted_item();
|
|
|
|
if (!qi.empty() && (qi.front() == '"')) {
|
2021-03-23 23:29:32 +01:00
|
|
|
unescape_string(std::back_inserter(buf), p.get_raw_item());
|
2016-08-02 02:21:36 +02:00
|
|
|
} else {
|
2021-03-20 19:34:26 +01:00
|
|
|
buf.append(p.get_raw_item());
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
if ((n + 1) < len) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if ((len > 2) || conj.empty()) {
|
2021-03-20 06:18:31 +01:00
|
|
|
buf.push_back(',');
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
if ((n + 2 == len) && !conj.empty()) {
|
2021-03-20 06:18:31 +01:00
|
|
|
buf.push_back(' ');
|
|
|
|
buf.append(conj);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-03-20 06:18:31 +01:00
|
|
|
buf.push_back(' ');
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(buf.str(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "indexof", "ss", [](auto &cs, auto args, auto &res) {
|
2021-04-06 00:54:46 +02:00
|
|
|
res.set_integer(
|
2021-04-11 03:32:14 +02:00
|
|
|
list_includes(cs, args[0].get_string(cs), args[1].get_string(cs))
|
2016-08-02 02:21:36 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listdel", "ss", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_merge<false, false>(cs, args, res, std::less<int>());
|
2016-08-17 20:51:21 +02:00
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listintersect", "ss", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_merge<false, false>(cs, args, res, std::greater_equal<int>());
|
2016-08-17 20:51:21 +02:00
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listunion", "ss", [](auto &cs, auto args, auto &res) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_merge<true, true>(cs, args, res, std::less<int>());
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "listsplice", "ssii", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-04-06 00:54:46 +02:00
|
|
|
integer_type offset = std::max(args[2].get_integer(), integer_type(0));
|
|
|
|
integer_type len = std::max(args[3].get_integer(), integer_type(0));
|
2021-04-11 03:32:14 +02:00
|
|
|
std::string_view s = args[0].get_string(cs);
|
|
|
|
std::string_view vals = args[1].get_string(cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
char const *list = s.data();
|
2021-03-23 23:29:32 +01:00
|
|
|
list_parser p{cs, s};
|
|
|
|
for (integer_type i = 0; i < offset; ++i) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) {
|
2016-08-02 02:21:36 +02:00
|
|
|
break;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
std::string_view quote = p.get_quoted_item();
|
2016-11-07 23:33:53 +01:00
|
|
|
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
2021-03-23 23:29:32 +01:00
|
|
|
charbuf buf{cs};
|
2016-08-17 20:51:21 +02:00
|
|
|
if (qend > list) {
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.append(list, qend);
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
if (!vals.empty()) {
|
2016-08-17 20:51:21 +02:00
|
|
|
if (!buf.empty()) {
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.push_back(' ');
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.append(vals);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-03-23 23:29:32 +01:00
|
|
|
for (integer_type i = 0; i < len; ++i) {
|
2021-03-20 19:34:26 +01:00
|
|
|
if (!p.parse()) {
|
2016-08-02 02:21:36 +02:00
|
|
|
break;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-20 19:34:26 +01:00
|
|
|
p.skip_until_item();
|
2021-03-20 02:26:37 +01:00
|
|
|
if (!p.get_input().empty()) {
|
|
|
|
switch (p.get_input().front()) {
|
2016-08-17 20:51:21 +02:00
|
|
|
case ')':
|
|
|
|
case ']':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!buf.empty()) {
|
2021-03-19 02:55:59 +01:00
|
|
|
buf.push_back(' ');
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-20 02:26:37 +01:00
|
|
|
buf.append(p.get_input());
|
2016-08-17 20:51:21 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(buf.str(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
});
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
init_lib_list_sort(gcs);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ListSortItem {
|
2021-03-20 02:26:37 +01:00
|
|
|
std::string_view str;
|
|
|
|
std::string_view quote;
|
2016-08-02 02:21:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ListSortFun {
|
2021-03-23 23:29:32 +01:00
|
|
|
state &cs;
|
2021-04-02 04:43:57 +02:00
|
|
|
alias_local &xst, &yst;
|
2021-04-01 05:05:43 +02:00
|
|
|
bcode_ref const *body;
|
2016-08-02 02:21:36 +02:00
|
|
|
|
|
|
|
bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
|
2021-04-11 03:32:14 +02:00
|
|
|
any_value v{};
|
|
|
|
v.set_string(xval.str, cs);
|
2021-03-30 20:55:50 +02:00
|
|
|
xst.set(std::move(v));
|
2021-04-11 03:32:14 +02:00
|
|
|
v.set_string(yval.str, cs);
|
2021-03-30 20:55:50 +02:00
|
|
|
yst.set(std::move(v));
|
2021-04-01 05:05:43 +02:00
|
|
|
return cs.run(*body).get_bool();
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
static void list_sort(
|
|
|
|
state &cs, any_value &res, std::string_view list,
|
2021-04-24 23:33:19 +02:00
|
|
|
ident &x, ident &y, bcode_ref &&body, bcode_ref &&unique
|
2016-08-02 02:21:36 +02:00
|
|
|
) {
|
2021-03-30 20:55:50 +02:00
|
|
|
if (x == y) {
|
2016-08-02 02:21:36 +02:00
|
|
|
return;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-04-02 04:43:57 +02:00
|
|
|
alias_local xst{cs, x}, yst{cs, y};
|
2016-08-18 00:06:39 +02:00
|
|
|
|
2021-04-05 04:10:39 +02:00
|
|
|
valbuf<ListSortItem> items{state_p{cs}.ts().istate};
|
2017-01-25 02:09:50 +01:00
|
|
|
size_t total = 0;
|
2016-08-02 02:21:36 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
for (list_parser p{cs, list}; p.parse();) {
|
2021-03-20 19:34:26 +01:00
|
|
|
ListSortItem item = { p.get_raw_item(), p.get_quoted_item() };
|
2017-01-25 01:18:29 +01:00
|
|
|
items.push_back(item);
|
2016-08-02 02:21:36 +02:00
|
|
|
total += item.quote.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (items.empty()) {
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(list, cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-25 02:09:50 +01:00
|
|
|
size_t totaluniq = total;
|
|
|
|
size_t nuniq = items.size();
|
2016-08-02 02:21:36 +02:00
|
|
|
if (body) {
|
2021-04-01 05:05:43 +02:00
|
|
|
ListSortFun f = { cs, xst, yst, &body };
|
2021-03-20 06:18:31 +01:00
|
|
|
std::sort(items.buf.begin(), items.buf.end(), f);
|
2021-04-01 05:05:43 +02:00
|
|
|
if (!unique.empty()) {
|
|
|
|
f.body = &unique;
|
2016-08-02 02:21:36 +02:00
|
|
|
totaluniq = items[0].quote.size();
|
|
|
|
nuniq = 1;
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t i = 1; i < items.size(); i++) {
|
2016-08-02 02:21:36 +02:00
|
|
|
ListSortItem &item = items[i];
|
2016-08-17 20:51:21 +02:00
|
|
|
if (f(items[i - 1], item)) {
|
2021-03-20 02:26:37 +01:00
|
|
|
item.quote = std::string_view{};
|
2016-08-17 20:51:21 +02:00
|
|
|
} else {
|
2016-08-02 02:21:36 +02:00
|
|
|
totaluniq += item.quote.size();
|
|
|
|
++nuniq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-04-01 05:05:43 +02:00
|
|
|
ListSortFun f = { cs, xst, yst, &unique };
|
2016-08-02 02:21:36 +02:00
|
|
|
totaluniq = items[0].quote.size();
|
|
|
|
nuniq = 1;
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t i = 1; i < items.size(); i++) {
|
2016-08-02 02:21:36 +02:00
|
|
|
ListSortItem &item = items[i];
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t j = 0; j < i; ++j) {
|
2016-08-02 02:21:36 +02:00
|
|
|
ListSortItem &prev = items[j];
|
|
|
|
if (!prev.quote.empty() && f(item, prev)) {
|
2021-03-20 02:26:37 +01:00
|
|
|
item.quote = std::string_view{};
|
2016-08-02 02:21:36 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!item.quote.empty()) {
|
|
|
|
totaluniq += item.quote.size();
|
|
|
|
++nuniq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
charbuf sorted{cs};
|
2017-02-18 17:49:01 +01:00
|
|
|
sorted.reserve(totaluniq + std::max(nuniq - 1, size_t(0)));
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t i = 0; i < items.size(); ++i) {
|
2016-08-02 02:21:36 +02:00
|
|
|
ListSortItem &item = items[i];
|
2016-08-17 20:51:21 +02:00
|
|
|
if (item.quote.empty()) {
|
2016-08-02 02:21:36 +02:00
|
|
|
continue;
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
|
|
|
if (i) {
|
2021-03-19 02:55:59 +01:00
|
|
|
sorted.push_back(' ');
|
2016-08-17 20:51:21 +02:00
|
|
|
}
|
2021-03-19 02:55:59 +01:00
|
|
|
sorted.append(item.quote);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
res.set_string(sorted.str(), cs);
|
2016-08-02 02:21:36 +02:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
static void init_lib_list_sort(state &gcs) {
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "sortlist", "srree", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_sort(
|
2021-04-24 23:33:19 +02:00
|
|
|
cs, res, args[0].get_string(cs), args[1].get_ident(cs),
|
|
|
|
args[2].get_ident(cs), args[3].get_code(), args[4].get_code()
|
2016-08-02 02:21:36 +02:00
|
|
|
);
|
|
|
|
});
|
2021-04-11 19:36:20 +02:00
|
|
|
new_cmd_quiet(gcs, "uniquelist", "srre", [](
|
|
|
|
auto &cs, auto args, auto &res
|
|
|
|
) {
|
2021-03-23 23:29:32 +01:00
|
|
|
list_sort(
|
2021-04-24 23:33:19 +02:00
|
|
|
cs, res, args[0].get_string(cs), args[1].get_ident(cs),
|
|
|
|
args[2].get_ident(cs), bcode_ref{}, args[3].get_code()
|
2016-08-02 02:21:36 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
} /* namespace cubescript */
|