remove parselist

master
Daniel Kolesa 2015-08-13 01:18:33 +01:00
parent a3c3b65251
commit 2260c1ec0a
1 changed files with 34 additions and 117 deletions

View File

@ -3801,93 +3801,6 @@ void cs_init_lib_base_loops(CsState &cs) {
}); });
} }
static const char *liststart = nullptr, *listend = nullptr, *listquotestart = nullptr, *listquoteend = nullptr;
static inline void skiplist(const char *&p) {
for (;;) {
p += strspn(p, " \t\r\n");
if (p[0] != '/' || p[1] != '/') break;
p += strcspn(p, "\n\0");
}
}
static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *&quotestart = listquotestart, const char *&quoteend = listquoteend) {
skiplist(s);
switch (*s) {
case '"':
quotestart = s++;
start = s;
s = parsestring(s);
end = s;
if (*s == '"') s++;
quoteend = s;
break;
case '(':
case '[':
quotestart = s;
start = s + 1;
for (int braktype = *s++, brak = 1;;) {
s += strcspn(s, "\"/;()[]\0");
int c = *s++;
switch (c) {
case '\0':
s--;
quoteend = end = s;
return true;
case '"':
s = parsestring(s);
if (*s == '"') s++;
break;
case '/':
if (*s == '/') s += strcspn(s, "\n\0");
break;
case '(':
case '[':
if (c == braktype) brak++;
break;
case ')':
if (braktype == '(' && --brak <= 0) goto endblock;
break;
case ']':
if (braktype == '[' && --brak <= 0) goto endblock;
break;
}
}
endblock:
end = s - 1;
quoteend = s;
break;
case '\0':
case ')':
case ']':
return false;
default:
quotestart = start = s;
s = parseword(s);
quoteend = end = s;
break;
}
skiplist(s);
if (*s == ';') s++;
return true;
}
static inline ostd::String listelem(const char *start, const char *end, const char *quotestart) {
ostd::Size len = end - start;
ostd::String s;
s.reserve(len);
if (*quotestart == '"') {
auto writer = s.iter_cap();
util::unescape_string(writer, ostd::ConstCharRange(start, end));
writer.put('\0');
} else {
memcpy(s.data(), start, len);
s[len] = '\0';
}
s.advance(len);
return s;
}
struct ListParser { struct ListParser {
ostd::ConstCharRange input; ostd::ConstCharRange input;
ostd::ConstCharRange quote = ostd::ConstCharRange(); ostd::ConstCharRange quote = ostd::ConstCharRange();
@ -4093,35 +4006,38 @@ void init_lib_list(CsState &cs) {
if (!numargs) if (!numargs)
return; return;
ostd::ConstCharRange str = args[0].get_str(); ostd::ConstCharRange str = args[0].get_str();
const char *start = str.data(), ListParser p(str);
*end = &str[str.size()], p.item = str;
*qstart = "";
for (int i = 1; i < numargs; ++i) { for (int i = 1; i < numargs; ++i) {
const char *list = start; p.input = str;
int pos = args[i].get_int(); int pos = args[i].get_int();
for (; pos > 0; --pos) for (; pos > 0; --pos)
if (!parselist(list)) break; if (!p.parse()) break;
if (pos > 0 || !parselist(list, start, end, qstart)) if (pos > 0 || !p.parse())
start = end = qstart = ""; p.item = p.quote = ostd::ConstCharRange();
} }
cs.result->set_str(listelem(start, end, qstart).disown()); cs.result->set_str(p.element().disown());
}); });
cs.add_command("sublist", "siiN", [](CsState &cs, const char *s, cs.add_command("sublist", "siiN", [](CsState &cs, const char *s,
int *skip, int *count, int *numargs) { int *skip, int *count, int *numargs) {
int offset = ostd::max(*skip, 0), int offset = ostd::max(*skip, 0),
len = (*numargs >= 3) ? ostd::max(*count, 0) : -1; len = (*numargs >= 3) ? ostd::max(*count, 0) : -1;
ListParser p(s);
for (int i = 0; i < offset; ++i) for (int i = 0; i < offset; ++i)
if (!parselist(s)) break; if (!p.parse()) break;
if (len < 0) { if (len < 0) {
if (offset > 0) if (offset > 0)
skiplist(s); p.skip();
cs.result->set_str(cs_dup_ostr(s)); cs.result->set_str(cs_dup_ostr(p.input));
return; return;
} }
const char *list = s, *start, *end, *qstart, *qend = s;
if (len > 0 && parselist(s, start, end, list, qend)) const char *list = p.input.data();
while (--len > 0 && parselist(s, start, end, qstart, qend)); p.quote = ostd::ConstCharRange();
if (len > 0 && p.parse())
while (--len > 0 && p.parse());
const char *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
cs.result->set_str(cs_dup_ostr(ostd::ConstCharRange(list, qend - list))); cs.result->set_str(cs_dup_ostr(ostd::ConstCharRange(list, qend - list)));
}); });
@ -4390,35 +4306,36 @@ found:
int *count) { int *count) {
int offset = ostd::max(*skip, 0); int offset = ostd::max(*skip, 0);
int len = ostd::max(*count, 0); int len = ostd::max(*count, 0);
const char *list = s, *start, *end, *qstart, *qend = s; const char *list = s;
ListParser p(s);
for (int i = 0; i < offset; ++i) for (int i = 0; i < offset; ++i)
if (!parselist(s, start, end, qstart, qend)) if (!p.parse())
break; break;
ostd::Vector<char> p; const char *qend = !p.quote.empty() ? &p.quote[p.quote.size()] : list;
ostd::Vector<char> buf;
if (qend > list) if (qend > list)
p.push_n(list, qend - list); buf.push_n(list, qend - list);
if (*vals) { if (*vals) {
if (!p.empty()) if (!buf.empty())
p.push(' '); buf.push(' ');
p.push_n(vals, strlen(vals)); buf.push_n(vals, strlen(vals));
} }
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
if (!parselist(s)) if (!p.parse())
break; break;
skiplist(s); p.skip();
switch (*s) { if (!p.input.empty()) switch (p.input.front()) {
case '\0':
case ')': case ')':
case ']': case ']':
break; break;
default: default:
if (!p.empty()) if (!buf.empty())
p.push(' '); buf.push(' ');
p.push_n(s, strlen(s)); buf.push_n(p.input.data(), p.input.size());
break; break;
} }
p.push('\0'); buf.push('\0');
cs.result->set_str(p.disown()); cs.result->set_str(buf.disown());
}); });
cs_init_lib_list_sort(cs); cs_init_lib_list_sort(cs);