cleanup lib_list
parent
1cf98dab50
commit
85bdcae6ee
382
lib_list.cc
382
lib_list.cc
|
@ -5,6 +5,69 @@ namespace cscript {
|
||||||
|
|
||||||
char *cs_dup_ostr(ostd::ConstCharRange s);
|
char *cs_dup_ostr(ostd::ConstCharRange s);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct CsArgVal;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct CsArgVal<CsInt> {
|
||||||
|
static CsInt get(TaggedValue &tv) {
|
||||||
|
return tv.get_int();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct CsArgVal<CsFloat> {
|
||||||
|
static CsFloat get(TaggedValue &tv) {
|
||||||
|
return tv.get_float();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct CsArgVal<ostd::ConstCharRange> {
|
||||||
|
static ostd::ConstCharRange get(TaggedValue &tv) {
|
||||||
|
return tv.get_strr();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename F>
|
||||||
|
static inline void cs_list_find(TvalRange args, TaggedValue &res, F cmp) {
|
||||||
|
CsInt n = 0, skip = args[2].get_int();
|
||||||
|
T val = CsArgVal<T>::get(args[1]);
|
||||||
|
for (util::ListParser p(args[0].get_strr()); p.parse(); ++n) {
|
||||||
|
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>
|
||||||
|
static inline void cs_list_assoc(TvalRange args, TaggedValue &res, F cmp) {
|
||||||
|
T val = CsArgVal<T>::get(args[1]);
|
||||||
|
for (util::ListParser p(args[0].get_strr()); p.parse();) {
|
||||||
|
if (cmp(p, val)) {
|
||||||
|
if (p.parse()) {
|
||||||
|
auto elem = p.element();
|
||||||
|
auto er = elem.iter();
|
||||||
|
elem.disown();
|
||||||
|
res.set_mstr(er);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!p.parse()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void cs_set_iter(Ident &id, char *val, IdentStack &stack) {
|
static inline void cs_set_iter(Ident &id, char *val, IdentStack &stack) {
|
||||||
if (id.stack == &stack) {
|
if (id.stack == &stack) {
|
||||||
if (id.get_valtype() == VAL_STR) {
|
if (id.get_valtype() == VAL_STR) {
|
||||||
|
@ -26,24 +89,27 @@ static void cs_loop_list_conc(
|
||||||
CsState &cs, TaggedValue &res, Ident *id, ostd::ConstCharRange list,
|
CsState &cs, TaggedValue &res, Ident *id, ostd::ConstCharRange list,
|
||||||
Bytecode const *body, bool space
|
Bytecode const *body, bool space
|
||||||
) {
|
) {
|
||||||
if (!id->is_alias())
|
if (!id->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack;
|
IdentStack stack;
|
||||||
ostd::Vector<char> r;
|
ostd::Vector<char> r;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::ListParser p(list); p.parse(); ++n) {
|
for (util::ListParser p(list); p.parse(); ++n) {
|
||||||
char *val = p.element().disown();
|
char *val = p.element().disown();
|
||||||
cs_set_iter(*id, val, stack);
|
cs_set_iter(*id, val, stack);
|
||||||
if (n && space)
|
if (n && space) {
|
||||||
r.push(' ');
|
r.push(' ');
|
||||||
|
}
|
||||||
TaggedValue v;
|
TaggedValue v;
|
||||||
cs.run_ret(body, v);
|
cs.run_ret(body, v);
|
||||||
ostd::String vstr = ostd::move(v.get_str());
|
ostd::String vstr = ostd::move(v.get_str());
|
||||||
r.push_n(vstr.data(), vstr.size());
|
r.push_n(vstr.data(), vstr.size());
|
||||||
v.cleanup();
|
v.cleanup();
|
||||||
}
|
}
|
||||||
if (n)
|
if (n) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
r.push('\0');
|
r.push('\0');
|
||||||
ostd::Size len = r.size();
|
ostd::Size len = r.size();
|
||||||
res.set_mstr(ostd::CharRange(r.disown(), len - 1));
|
res.set_mstr(ostd::CharRange(r.disown(), len - 1));
|
||||||
|
@ -52,33 +118,62 @@ static void cs_loop_list_conc(
|
||||||
int cs_list_includes(ostd::ConstCharRange list, ostd::ConstCharRange needle) {
|
int cs_list_includes(ostd::ConstCharRange list, ostd::ConstCharRange needle) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (util::ListParser p(list); p.parse();) {
|
for (util::ListParser p(list); p.parse();) {
|
||||||
if (p.item == needle)
|
if (p.item == needle) {
|
||||||
return offset;
|
return offset;
|
||||||
|
}
|
||||||
++offset;
|
++offset;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool PushList, bool Swap, typename F>
|
||||||
|
static inline void cs_list_merge(TvalRange args, TaggedValue &res, F cmp) {
|
||||||
|
ostd::ConstCharRange list = args[0].get_strr();
|
||||||
|
ostd::ConstCharRange elems = args[1].get_strr();
|
||||||
|
ostd::Vector<char> buf;
|
||||||
|
if (PushList) {
|
||||||
|
buf.push_n(list.data(), list.size());
|
||||||
|
}
|
||||||
|
if (Swap) {
|
||||||
|
ostd::swap(list, elems);
|
||||||
|
}
|
||||||
|
for (util::ListParser p(list); p.parse();) {
|
||||||
|
if (cmp(cs_list_includes(elems, p.item), 0)) {
|
||||||
|
if (!buf.empty())
|
||||||
|
buf.push(' ');
|
||||||
|
buf.push_n(p.quote.data(), p.quote.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.push('\0');
|
||||||
|
ostd::Size len = buf.size() - 1;
|
||||||
|
res.set_mstr(ostd::CharRange(buf.disown(), len));
|
||||||
|
}
|
||||||
|
|
||||||
static void cs_init_lib_list_sort(CsState &cs);
|
static void cs_init_lib_list_sort(CsState &cs);
|
||||||
|
|
||||||
void cs_init_lib_list(CsState &cs) {
|
void cs_init_lib_list(CsState &cs) {
|
||||||
cs.add_command("listlen", "s", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("listlen", "s", [](TvalRange args, TaggedValue &res) {
|
||||||
res.set_int(CsInt(util::list_length(args[0].get_strr())));
|
res.set_int(CsInt(util::list_length(args[0].get_strr())));
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("at", "si1V", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("at", "si1V", [](TvalRange args, TaggedValue &res) {
|
||||||
if (args.empty())
|
if (args.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ostd::String str = ostd::move(args[0].get_str());
|
ostd::String str = ostd::move(args[0].get_str());
|
||||||
util::ListParser p(str);
|
util::ListParser p(str);
|
||||||
p.item = str;
|
p.item = str;
|
||||||
for (ostd::Size i = 1; i < args.size(); ++i) {
|
for (ostd::Size i = 1; i < args.size(); ++i) {
|
||||||
p.input = str;
|
p.input = str;
|
||||||
CsInt pos = args[i].get_int();
|
CsInt pos = args[i].get_int();
|
||||||
for (; pos > 0; --pos)
|
for (; pos > 0; --pos) {
|
||||||
if (!p.parse()) break;
|
if (!p.parse()) {
|
||||||
if (pos > 0 || !p.parse())
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos > 0 || !p.parse()) {
|
||||||
p.item = p.quote = ostd::ConstCharRange();
|
p.item = p.quote = ostd::ConstCharRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto elem = p.element();
|
auto elem = p.element();
|
||||||
auto er = p.element().iter();
|
auto er = p.element().iter();
|
||||||
|
@ -86,7 +181,7 @@ void cs_init_lib_list(CsState &cs) {
|
||||||
res.set_mstr(er);
|
res.set_mstr(er);
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("sublist", "siiN", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("sublist", "siiN", [](TvalRange args, TaggedValue &res) {
|
||||||
CsInt skip = args[1].get_int(),
|
CsInt skip = args[1].get_int(),
|
||||||
count = args[2].get_int(),
|
count = args[2].get_int(),
|
||||||
numargs = args[2].get_int();
|
numargs = args[2].get_int();
|
||||||
|
@ -95,19 +190,22 @@ void cs_init_lib_list(CsState &cs) {
|
||||||
len = (numargs >= 3) ? ostd::max(count, 0) : -1;
|
len = (numargs >= 3) ? ostd::max(count, 0) : -1;
|
||||||
|
|
||||||
util::ListParser p(args[0].get_strr());
|
util::ListParser p(args[0].get_strr());
|
||||||
for (CsInt i = 0; i < offset; ++i)
|
for (CsInt i = 0; i < offset; ++i) {
|
||||||
if (!p.parse()) break;
|
if (!p.parse()) break;
|
||||||
|
}
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
if (offset > 0)
|
if (offset > 0) {
|
||||||
p.skip();
|
p.skip();
|
||||||
|
}
|
||||||
res.set_str(p.input);
|
res.set_str(p.input);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *list = p.input.data();
|
char const *list = p.input.data();
|
||||||
p.quote = ostd::ConstCharRange();
|
p.quote = ostd::ConstCharRange();
|
||||||
if (len > 0 && p.parse())
|
if (len > 0 && p.parse()) {
|
||||||
while (--len > 0 && p.parse());
|
while (--len > 0 && p.parse());
|
||||||
|
}
|
||||||
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
||||||
res.set_str(ostd::ConstCharRange(list, qend - list));
|
res.set_str(ostd::ConstCharRange(list, qend - list));
|
||||||
});
|
});
|
||||||
|
@ -131,15 +229,17 @@ void cs_init_lib_list(CsState &cs) {
|
||||||
}
|
}
|
||||||
res.set_int(-1);
|
res.set_int(-1);
|
||||||
found:
|
found:
|
||||||
if (n >= 0)
|
if (n >= 0) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("listassoc", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("listassoc", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
||||||
Ident *id = args[0].get_ident();
|
Ident *id = args[0].get_ident();
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
if (!id->is_alias())
|
if (!id->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack;
|
IdentStack stack;
|
||||||
int n = -1;
|
int n = -1;
|
||||||
for (util::ListParser p(args[1].get_strr()); p.parse();) {
|
for (util::ListParser p(args[1].get_strr()); p.parse();) {
|
||||||
|
@ -154,88 +254,89 @@ found:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!p.parse())
|
if (!p.parse()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (n >= 0)
|
if (n >= 0) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#define CS_CMD_LIST_FIND(name, fmt, gmeth, cmp) \
|
cs.add_command("listfind=", "i", [](TvalRange args, TaggedValue &res) {
|
||||||
cs.add_command(name, "s" fmt "i", [&cs](TvalRange args, TaggedValue &res) { \
|
cs_list_find<CsInt>(
|
||||||
CsInt n = 0, skip = args[2].get_int(); \
|
args, res, [](const util::ListParser &p, CsInt val) {
|
||||||
auto val = args[1].gmeth(); \
|
return cs_parse_int(p.item) == val;
|
||||||
for (util::ListParser p(args[0].get_strr()); p.parse(); ++n) { \
|
}
|
||||||
if (cmp) { \
|
);
|
||||||
res.set_int(n); \
|
});
|
||||||
return; \
|
cs.add_command("listfind=f", "f", [](TvalRange args, TaggedValue &res) {
|
||||||
} \
|
cs_list_find<CsFloat>(
|
||||||
for (int i = 0; i < skip; ++i) { \
|
args, res, [](const util::ListParser &p, CsFloat val) {
|
||||||
if (!p.parse()) \
|
return cs_parse_float(p.item) == val;
|
||||||
goto notfound; \
|
}
|
||||||
++n; \
|
);
|
||||||
} \
|
});
|
||||||
} \
|
cs.add_command("listfind=s", "s", [](TvalRange args, TaggedValue &res) {
|
||||||
notfound: \
|
cs_list_find<ostd::ConstCharRange>(
|
||||||
res.set_int(-1); \
|
args, res, [](const util::ListParser &p, ostd::ConstCharRange val) {
|
||||||
|
return p.item == val;
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
CS_CMD_LIST_FIND("listfind=", "i", get_int, cs_parse_int(p.item) == val);
|
cs.add_command("listassoc=", "i", [](TvalRange args, TaggedValue &res) {
|
||||||
CS_CMD_LIST_FIND("listfind=f", "f", get_float, cs_parse_float(p.item) == val);
|
cs_list_assoc<CsInt>(
|
||||||
CS_CMD_LIST_FIND("listfind=s", "s", get_strr, p.item == val);
|
args, res, [](const util::ListParser &p, CsInt val) {
|
||||||
|
return cs_parse_int(p.item) == val;
|
||||||
#undef CS_CMD_LIST_FIND
|
}
|
||||||
|
);
|
||||||
#define CS_CMD_LIST_ASSOC(name, fmt, gmeth, cmp) \
|
});
|
||||||
cs.add_command(name, "s" fmt, [&cs](TvalRange args, TaggedValue &res) { \
|
cs.add_command("listassoc=f", "f", [](TvalRange args, TaggedValue &res) {
|
||||||
auto val = args[1].gmeth(); \
|
cs_list_assoc<CsFloat>(
|
||||||
for (util::ListParser p(args[0].get_strr()); p.parse();) { \
|
args, res, [](const util::ListParser &p, CsFloat val) {
|
||||||
if (cmp) { \
|
return cs_parse_float(p.item) == val;
|
||||||
if (p.parse()) { \
|
}
|
||||||
auto elem = p.element(); \
|
);
|
||||||
auto er = elem.iter(); \
|
});
|
||||||
elem.disown(); \
|
cs.add_command("listassoc=s", "s", [](TvalRange args, TaggedValue &res) {
|
||||||
res.set_mstr(er); \
|
cs_list_assoc<ostd::ConstCharRange>(
|
||||||
} \
|
args, res, [](const util::ListParser &p, ostd::ConstCharRange val) {
|
||||||
return; \
|
return p.item == val;
|
||||||
} \
|
}
|
||||||
if (!p.parse()) \
|
);
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
});
|
});
|
||||||
|
|
||||||
CS_CMD_LIST_ASSOC("listassoc=", "i", get_int, cs_parse_int(p.item) == val);
|
|
||||||
CS_CMD_LIST_ASSOC("listassoc=f", "f", get_float, cs_parse_float(p.item) == val);
|
|
||||||
CS_CMD_LIST_ASSOC("listassoc=s", "s", get_strr, p.item == val);
|
|
||||||
|
|
||||||
#undef CS_CMD_LIST_ASSOC
|
|
||||||
|
|
||||||
cs.add_command("looplist", "rse", [&cs](TvalRange args, TaggedValue &) {
|
cs.add_command("looplist", "rse", [&cs](TvalRange args, TaggedValue &) {
|
||||||
Ident *id = args[0].get_ident();
|
Ident *id = args[0].get_ident();
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
if (!id->is_alias())
|
if (!id->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack;
|
IdentStack stack;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::ListParser p(args[1].get_strr()); p.parse(); ++n) {
|
for (util::ListParser p(args[1].get_strr()); p.parse(); ++n) {
|
||||||
cs_set_iter(*id, p.element().disown(), stack);
|
cs_set_iter(*id, p.element().disown(), stack);
|
||||||
cs.run_int(body);
|
cs.run_int(body);
|
||||||
}
|
}
|
||||||
if (n)
|
if (n) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("looplist2", "rrse", [&cs](TvalRange args, TaggedValue &) {
|
cs.add_command("looplist2", "rrse", [&cs](TvalRange args, TaggedValue &) {
|
||||||
Ident *id = args[0].get_ident(), *id2 = args[1].get_ident();
|
Ident *id = args[0].get_ident(), *id2 = args[1].get_ident();
|
||||||
auto body = args[3].get_code();
|
auto body = args[3].get_code();
|
||||||
if (!id->is_alias() || !id2->is_alias())
|
if (!id->is_alias() || !id2->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack, stack2;
|
IdentStack stack, stack2;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::ListParser p(args[2].get_strr()); p.parse(); n += 2) {
|
for (util::ListParser p(args[2].get_strr()); p.parse(); n += 2) {
|
||||||
cs_set_iter(*id, p.element().disown(), stack);
|
cs_set_iter(*id, p.element().disown(), stack);
|
||||||
cs_set_iter(*id2, p.parse() ? p.element().disown()
|
cs_set_iter(
|
||||||
: cs_dup_ostr(""), stack2);
|
*id2, p.parse() ? p.element().disown() : cs_dup_ostr(""), stack2
|
||||||
|
);
|
||||||
cs.run_int(body);
|
cs.run_int(body);
|
||||||
}
|
}
|
||||||
if (n) {
|
if (n) {
|
||||||
|
@ -249,16 +350,19 @@ found:
|
||||||
Ident *id2 = args[1].get_ident();
|
Ident *id2 = args[1].get_ident();
|
||||||
Ident *id3 = args[2].get_ident();
|
Ident *id3 = args[2].get_ident();
|
||||||
auto body = args[4].get_code();
|
auto body = args[4].get_code();
|
||||||
if (!id->is_alias() || !id2->is_alias() || !id3->is_alias())
|
if (!id->is_alias() || !id2->is_alias() || !id3->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack, stack2, stack3;
|
IdentStack stack, stack2, stack3;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (util::ListParser p(args[3].get_strr()); p.parse(); n += 3) {
|
for (util::ListParser p(args[3].get_strr()); p.parse(); n += 3) {
|
||||||
cs_set_iter(*id, p.element().disown(), stack);
|
cs_set_iter(*id, p.element().disown(), stack);
|
||||||
cs_set_iter(*id2, p.parse() ? p.element().disown()
|
cs_set_iter(
|
||||||
: cs_dup_ostr(""), stack2);
|
*id2, p.parse() ? p.element().disown() : cs_dup_ostr(""), stack2
|
||||||
cs_set_iter(*id3, p.parse() ? p.element().disown()
|
);
|
||||||
: cs_dup_ostr(""), stack3);
|
cs_set_iter(
|
||||||
|
*id3, p.parse() ? p.element().disown() : cs_dup_ostr(""), stack3
|
||||||
|
);
|
||||||
cs.run_int(body);
|
cs.run_int(body);
|
||||||
}
|
}
|
||||||
if (n) {
|
if (n) {
|
||||||
|
@ -268,14 +372,18 @@ found:
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("looplistconcat", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("looplistconcat", "rse", [&cs](
|
||||||
|
TvalRange args, TaggedValue &res
|
||||||
|
) {
|
||||||
cs_loop_list_conc(
|
cs_loop_list_conc(
|
||||||
cs, res, args[0].get_ident(), args[1].get_strr(),
|
cs, res, args[0].get_ident(), args[1].get_strr(),
|
||||||
args[2].get_code(), true
|
args[2].get_code(), true
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("looplistconcatword", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("looplistconcatword", "rse", [&cs](
|
||||||
|
TvalRange args, TaggedValue &res
|
||||||
|
) {
|
||||||
cs_loop_list_conc(
|
cs_loop_list_conc(
|
||||||
cs, res, args[0].get_ident(), args[1].get_strr(),
|
cs, res, args[0].get_ident(), args[1].get_strr(),
|
||||||
args[2].get_code(), false
|
args[2].get_code(), false
|
||||||
|
@ -285,8 +393,9 @@ found:
|
||||||
cs.add_command("listfilter", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("listfilter", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
||||||
Ident *id = args[0].get_ident();
|
Ident *id = args[0].get_ident();
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
if (!id->is_alias())
|
if (!id->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack;
|
IdentStack stack;
|
||||||
ostd::Vector<char> r;
|
ostd::Vector<char> r;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
@ -294,12 +403,15 @@ found:
|
||||||
char *val = cs_dup_ostr(p.item);
|
char *val = cs_dup_ostr(p.item);
|
||||||
cs_set_iter(*id, val, stack);
|
cs_set_iter(*id, val, stack);
|
||||||
if (cs.run_bool(body)) {
|
if (cs.run_bool(body)) {
|
||||||
if (r.size()) r.push(' ');
|
if (r.size()) {
|
||||||
|
r.push(' ');
|
||||||
|
}
|
||||||
r.push_n(p.quote.data(), p.quote.size());
|
r.push_n(p.quote.data(), p.quote.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n)
|
if (n) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
r.push('\0');
|
r.push('\0');
|
||||||
ostd::Size len = r.size() - 1;
|
ostd::Size len = r.size() - 1;
|
||||||
res.set_mstr(ostd::CharRange(r.disown(), len));
|
res.set_mstr(ostd::CharRange(r.disown(), len));
|
||||||
|
@ -308,22 +420,25 @@ found:
|
||||||
cs.add_command("listcount", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("listcount", "rse", [&cs](TvalRange args, TaggedValue &res) {
|
||||||
Ident *id = args[0].get_ident();
|
Ident *id = args[0].get_ident();
|
||||||
auto body = args[2].get_code();
|
auto body = args[2].get_code();
|
||||||
if (!id->is_alias())
|
if (!id->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
IdentStack stack;
|
IdentStack stack;
|
||||||
int n = 0, r = 0;
|
int n = 0, r = 0;
|
||||||
for (util::ListParser p(args[1].get_strr()); p.parse(); ++n) {
|
for (util::ListParser p(args[1].get_strr()); p.parse(); ++n) {
|
||||||
char *val = cs_dup_ostr(p.item);
|
char *val = cs_dup_ostr(p.item);
|
||||||
cs_set_iter(*id, val, stack);
|
cs_set_iter(*id, val, stack);
|
||||||
if (cs.run_bool(body))
|
if (cs.run_bool(body)) {
|
||||||
r++;
|
r++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (n)
|
if (n) {
|
||||||
id->pop_arg();
|
id->pop_arg();
|
||||||
|
}
|
||||||
res.set_int(r);
|
res.set_int(r);
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("prettylist", "ss", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("prettylist", "ss", [](TvalRange args, TaggedValue &res) {
|
||||||
ostd::Vector<char> buf;
|
ostd::Vector<char> buf;
|
||||||
ostd::ConstCharRange s = args[0].get_strr();
|
ostd::ConstCharRange s = args[0].get_strr();
|
||||||
ostd::ConstCharRange conj = args[1].get_strr();
|
ostd::ConstCharRange conj = args[1].get_strr();
|
||||||
|
@ -332,8 +447,9 @@ found:
|
||||||
for (util::ListParser p(s); p.parse(); ++n) {
|
for (util::ListParser p(s); p.parse(); ++n) {
|
||||||
if (!p.quote.empty() && (p.quote.front() == '"')) {
|
if (!p.quote.empty() && (p.quote.front() == '"')) {
|
||||||
buf.reserve(buf.size() + p.item.size());
|
buf.reserve(buf.size() + p.item.size());
|
||||||
auto writer = ostd::CharRange(&buf[buf.size()],
|
auto writer = ostd::CharRange(
|
||||||
buf.capacity() - buf.size());
|
&buf[buf.size()], buf.capacity() - buf.size()
|
||||||
|
);
|
||||||
ostd::Size adv = util::unescape_string(writer, p.item);
|
ostd::Size adv = util::unescape_string(writer, p.item);
|
||||||
writer.put('\0');
|
writer.put('\0');
|
||||||
buf.advance(adv);
|
buf.advance(adv);
|
||||||
|
@ -341,8 +457,9 @@ found:
|
||||||
buf.push_n(p.item.data(), p.item.size());
|
buf.push_n(p.item.data(), p.item.size());
|
||||||
}
|
}
|
||||||
if ((n + 1) < len) {
|
if ((n + 1) < len) {
|
||||||
if ((len > 2) || conj.empty())
|
if ((len > 2) || conj.empty()) {
|
||||||
buf.push(',');
|
buf.push(',');
|
||||||
|
}
|
||||||
if ((n + 2 == len) && !conj.empty()) {
|
if ((n + 2 == len) && !conj.empty()) {
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
buf.push_n(conj.data(), conj.size());
|
buf.push_n(conj.data(), conj.size());
|
||||||
|
@ -355,69 +472,63 @@ found:
|
||||||
res.set_mstr(ostd::CharRange(buf.disown(), slen));
|
res.set_mstr(ostd::CharRange(buf.disown(), slen));
|
||||||
});
|
});
|
||||||
|
|
||||||
cs.add_command("indexof", "ss", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("indexof", "ss", [](TvalRange args, TaggedValue &res) {
|
||||||
res.set_int(
|
res.set_int(
|
||||||
cs_list_includes(args[0].get_strr(), args[1].get_strr())
|
cs_list_includes(args[0].get_strr(), args[1].get_strr())
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
#define CS_CMD_LIST_MERGE(name, init, iter, filter, dir) \
|
cs.add_command("listdel", "ss", [](TvalRange args, TaggedValue &res) {
|
||||||
cs.add_command(name, "ss", [&cs](TvalRange args, TaggedValue &res) { \
|
cs_list_merge<false, false>(args, res, ostd::Less<int>());
|
||||||
ostd::ConstCharRange list = args[0].get_strr(); \
|
});
|
||||||
ostd::ConstCharRange elems = args[1].get_strr(); \
|
cs.add_command("listintersect", "ss", [](TvalRange args, TaggedValue &res) {
|
||||||
ostd::Vector<char> buf; \
|
cs_list_merge<false, false>(args, res, ostd::GreaterEqual<int>());
|
||||||
init; \
|
});
|
||||||
for (util::ListParser p(iter); p.parse();) { \
|
cs.add_command("listunion", "ss", [](TvalRange args, TaggedValue &res) {
|
||||||
if (cs_list_includes(filter, p.item) dir 0) { \
|
cs_list_merge<true, true>(args, res, ostd::Less<int>());
|
||||||
if (!buf.empty()) \
|
|
||||||
buf.push(' '); \
|
|
||||||
buf.push_n(p.quote.data(), p.quote.size()); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
buf.push('\0'); \
|
|
||||||
ostd::Size len = buf.size() - 1; \
|
|
||||||
res.set_mstr(ostd::CharRange(buf.disown(), len)); \
|
|
||||||
});
|
});
|
||||||
|
|
||||||
CS_CMD_LIST_MERGE("listdel", {}, list, elems, <);
|
cs.add_command("listsplice", "ssii", [](TvalRange args, TaggedValue &res) {
|
||||||
CS_CMD_LIST_MERGE("listintersect", {}, list, elems, >=);
|
|
||||||
CS_CMD_LIST_MERGE("listunion", buf.push_n(list.data(), list.size()), elems,
|
|
||||||
list, <);
|
|
||||||
|
|
||||||
#undef CS_CMD_LIST_MERGE
|
|
||||||
|
|
||||||
cs.add_command("listsplice", "ssii", [&cs](TvalRange args, TaggedValue &res) {
|
|
||||||
CsInt offset = ostd::max(args[2].get_int(), 0);
|
CsInt offset = ostd::max(args[2].get_int(), 0);
|
||||||
CsInt len = ostd::max(args[3].get_int(), 0);
|
CsInt len = ostd::max(args[3].get_int(), 0);
|
||||||
ostd::ConstCharRange s = args[0].get_strr();
|
ostd::ConstCharRange s = args[0].get_strr();
|
||||||
ostd::ConstCharRange vals = args[1].get_strr();
|
ostd::ConstCharRange vals = args[1].get_strr();
|
||||||
char const *list = s.data();
|
char const *list = s.data();
|
||||||
util::ListParser p(s);
|
util::ListParser p(s);
|
||||||
for (CsInt i = 0; i < offset; ++i)
|
for (CsInt i = 0; i < offset; ++i) {
|
||||||
if (!p.parse())
|
if (!p.parse()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
char const *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
|
||||||
ostd::Vector<char> buf;
|
ostd::Vector<char> buf;
|
||||||
if (qend > list)
|
if (qend > list) {
|
||||||
buf.push_n(list, qend - list);
|
buf.push_n(list, qend - list);
|
||||||
|
}
|
||||||
if (!vals.empty()) {
|
if (!vals.empty()) {
|
||||||
if (!buf.empty())
|
if (!buf.empty()) {
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
|
}
|
||||||
buf.push_n(vals.data(), vals.size());
|
buf.push_n(vals.data(), vals.size());
|
||||||
}
|
}
|
||||||
for (CsInt i = 0; i < len; ++i)
|
for (CsInt i = 0; i < len; ++i) {
|
||||||
if (!p.parse())
|
if (!p.parse()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
p.skip();
|
p.skip();
|
||||||
if (!p.input.empty()) switch (p.input.front()) {
|
if (!p.input.empty()) {
|
||||||
case ')':
|
switch (p.input.front()) {
|
||||||
case ']':
|
case ')':
|
||||||
break;
|
case ']':
|
||||||
default:
|
break;
|
||||||
if (!buf.empty())
|
default:
|
||||||
buf.push(' ');
|
if (!buf.empty()) {
|
||||||
buf.push_n(p.input.data(), p.input.size());
|
buf.push(' ');
|
||||||
break;
|
}
|
||||||
|
buf.push_n(p.input.data(), p.input.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf.push('\0');
|
buf.push('\0');
|
||||||
ostd::Size slen = buf.size() - 1;
|
ostd::Size slen = buf.size() - 1;
|
||||||
|
@ -458,8 +569,9 @@ static void cs_list_sort(
|
||||||
CsState &cs, TaggedValue &res, ostd::ConstCharRange list, Ident *x, Ident *y,
|
CsState &cs, TaggedValue &res, ostd::ConstCharRange list, Ident *x, Ident *y,
|
||||||
Bytecode *body, Bytecode *unique
|
Bytecode *body, Bytecode *unique
|
||||||
) {
|
) {
|
||||||
if (x == y || !x->is_alias() || !y->is_alias())
|
if (x == y || !x->is_alias() || !y->is_alias()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ostd::Vector<ListSortItem> items;
|
ostd::Vector<ListSortItem> items;
|
||||||
ostd::Size clen = list.size();
|
ostd::Size clen = list.size();
|
||||||
|
@ -497,9 +609,9 @@ static void cs_list_sort(
|
||||||
nuniq = 1;
|
nuniq = 1;
|
||||||
for (ostd::Size i = 1; i < items.size(); i++) {
|
for (ostd::Size i = 1; i < items.size(); i++) {
|
||||||
ListSortItem &item = items[i];
|
ListSortItem &item = items[i];
|
||||||
if (f(items[i - 1], item))
|
if (f(items[i - 1], item)) {
|
||||||
item.quote = nullptr;
|
item.quote = nullptr;
|
||||||
else {
|
} else {
|
||||||
totaluniq += item.quote.size();
|
totaluniq += item.quote.size();
|
||||||
++nuniq;
|
++nuniq;
|
||||||
}
|
}
|
||||||
|
@ -538,10 +650,12 @@ static void cs_list_sort(
|
||||||
ostd::Size offset = 0;
|
ostd::Size offset = 0;
|
||||||
for (ostd::Size i = 0; i < items.size(); ++i) {
|
for (ostd::Size i = 0; i < items.size(); ++i) {
|
||||||
ListSortItem &item = items[i];
|
ListSortItem &item = items[i];
|
||||||
if (item.quote.empty())
|
if (item.quote.empty()) {
|
||||||
continue;
|
continue;
|
||||||
if (i)
|
}
|
||||||
|
if (i) {
|
||||||
sorted[offset++] = ' ';
|
sorted[offset++] = ' ';
|
||||||
|
}
|
||||||
memcpy(&sorted[offset], item.quote.data(), item.quote.size());
|
memcpy(&sorted[offset], item.quote.data(), item.quote.size());
|
||||||
offset += item.quote.size();
|
offset += item.quote.size();
|
||||||
}
|
}
|
||||||
|
@ -551,13 +665,17 @@ static void cs_list_sort(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cs_init_lib_list_sort(CsState &cs) {
|
static void cs_init_lib_list_sort(CsState &cs) {
|
||||||
cs.add_command("sortlist", "srree", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("sortlist", "srree", [&cs](
|
||||||
|
TvalRange args, TaggedValue &res
|
||||||
|
) {
|
||||||
cs_list_sort(
|
cs_list_sort(
|
||||||
cs, res, args[0].get_strr(), args[1].get_ident(),
|
cs, res, args[0].get_strr(), args[1].get_ident(),
|
||||||
args[2].get_ident(), args[3].get_code(), args[4].get_code()
|
args[2].get_ident(), args[3].get_code(), args[4].get_code()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cs.add_command("uniquelist", "srre", [&cs](TvalRange args, TaggedValue &res) {
|
cs.add_command("uniquelist", "srre", [&cs](
|
||||||
|
TvalRange args, TaggedValue &res
|
||||||
|
) {
|
||||||
cs_list_sort(
|
cs_list_sort(
|
||||||
cs, res, args[0].get_strr(), args[1].get_ident(),
|
cs, res, args[0].get_strr(), args[1].get_ident(),
|
||||||
args[2].get_ident(), nullptr, args[3].get_code()
|
args[2].get_ident(), nullptr, args[3].get_code()
|
||||||
|
|
Loading…
Reference in New Issue