redo (un)escape_string around output iterators

master
Daniel Kolesa 2021-03-20 06:18:31 +01:00
parent 320fdbaefd
commit 10b2a81cec
7 changed files with 57 additions and 78 deletions

View File

@ -8,6 +8,7 @@
#include <optional>
#include <functional>
#include <type_traits>
#include <algorithm>
#include <utility>
#include "cubescript_conf.hh"
@ -664,37 +665,25 @@ OSTD_EXPORT cs_strref value_list_concat(
namespace util {
template<typename R>
inline R &&escape_string(R &&writer, std::string_view str) {
inline R escape_string(R writer, std::string_view str) {
using namespace ostd::string_literals;
writer.put('"');
*writer++ = '"';
for (auto c: str) {
switch (c) {
case '\n':
ostd::range_put_all(writer, "^n"_sr);
break;
case '\t':
ostd::range_put_all(writer, "^t"_sr);
break;
case '\f':
ostd::range_put_all(writer, "^f"_sr);
break;
case '"':
ostd::range_put_all(writer, "^\""_sr);
break;
case '^':
ostd::range_put_all(writer, "^^"_sr);
break;
default:
writer.put(c);
break;
case '\n': *writer++ = '^'; *writer++ = 'n'; break;
case '\t': *writer++ = '^'; *writer++ = 't'; break;
case '\f': *writer++ = '^'; *writer++ = 'f'; break;
case '"': *writer++ = '^'; *writer++ = '"'; break;
case '^': *writer++ = '^'; *writer++ = '^'; break;
default: *writer++ = c; break;
}
}
writer.put('"');
return std::forward<R>(writer);
*writer++ = '"';
return writer;
}
template<typename R>
inline R &&unescape_string(R &&writer, std::string_view str) {
inline R unescape_string(R writer, std::string_view str) {
for (auto it = str.begin(); it != str.end(); ++it) {
if (*it == '^') {
++it;
@ -702,24 +691,12 @@ namespace util {
break;
}
switch (*it) {
case 'n':
writer.put('\n');
break;
case 't':
writer.put('\r');
break;
case 'f':
writer.put('\f');
break;
case '"':
writer.put('"');
break;
case '^':
writer.put('^');
break;
default:
writer.put(*it);
break;
case 'n': *writer++ = '\n'; break;
case 't': *writer++ = '\r'; break;
case 'f': *writer++ = '\f'; break;
case '"': *writer++ = '"'; break;
case '^': *writer++ = '^'; break;
default: *writer++ = *it; break;
}
} else if (*it == '\\') {
++it;
@ -735,12 +712,12 @@ namespace util {
}
continue;
}
writer.put('\\');
*writer++ = '\\';
} else {
writer.put(str.front());
*writer++ = *it;
}
}
return std::forward<R>(writer);
return writer;
}
OSTD_EXPORT char const *parse_string(

View File

@ -1,10 +1,8 @@
#ifndef LIBCUBESCRIPT_CUBESCRIPT_CONF_HH
#define LIBCUBESCRIPT_CUBESCRIPT_CONF_HH
#include <limits.h>
#include <functional>
#include <span>
#include <ostd/range.hh>
/* do not modify */
namespace cscript {

View File

@ -5,6 +5,7 @@
#include <ctype.h>
#include <limits>
#include <iterator>
namespace cscript {
@ -20,10 +21,9 @@ std::string_view cs_gen_state::get_str() {
}
cs_charbuf cs_gen_state::get_str_dup() {
auto str = get_str();
auto app = ostd::appender<cs_charbuf>(cs);
util::unescape_string(app, str);
return std::move(app.get());
cs_charbuf buf{cs};
util::unescape_string(std::back_inserter(buf), get_str());
return buf;
}
std::string_view cs_gen_state::read_macro_name() {
@ -199,12 +199,14 @@ static inline void compileunescapestr(cs_gen_state &gs) {
);
size_t bufs = (gs.code.capacity() - gs.code.size()) * sizeof(uint32_t);
char *buf = new char[bufs + 1];
auto writer = ostd::char_range(buf, buf + bufs);
size_t len = util::unescape_string(ostd::counting_sink(writer), str).get_written();
memset(&buf[len], 0, sizeof(uint32_t) - len % sizeof(uint32_t));
gs.code.back() |= len << 8;
char *wbuf = util::unescape_string(&buf[0], str);
memset(
&buf[wbuf - buf], 0,
sizeof(uint32_t) - (wbuf - buf) % sizeof(uint32_t)
);
gs.code.back() |= (wbuf - buf) << 8;
uint32_t *ubuf = reinterpret_cast<uint32_t *>(buf);
gs.code.append(ubuf, ubuf + (len / sizeof(uint32_t) + 1));
gs.code.append(ubuf, ubuf + ((wbuf - buf) / sizeof(uint32_t) + 1));
delete[] buf;
}

View File

@ -2,8 +2,9 @@
#include "cs_util.hh"
#include "cs_vm.hh"
#include <ctype.h>
#include <math.h>
#include <cctype>
#include <cmath>
#include <iterator>
namespace cscript {
@ -529,9 +530,9 @@ OSTD_EXPORT std::size_t list_count(cs_list_parse_state &ps, cs_state &cs) {
OSTD_EXPORT cs_strref list_get_item(cs_list_parse_state &ps, cs_state &cs) {
if (!ps.quoted_item.empty() && (ps.quoted_item.front() == '"')) {
auto app = ostd::appender<cs_charbuf>(cs);
util::unescape_string(app, ps.item);
return cs_strref{cs, app.get().str()};
cs_charbuf buf{cs};
util::unescape_string(std::back_inserter(buf), ps.item);
return cs_strref{cs, buf.str()};
}
return cs_strref{cs, ps.item};
}

View File

@ -2,7 +2,6 @@
#include "cs_vm.hh"
#include "cs_util.hh"
#include <ostd/io.hh>
#include <limits>
namespace cscript {

View File

@ -1,4 +1,5 @@
#include <functional>
#include <iterator>
#include <cubescript/cubescript.hh>
#include "cs_util.hh"
@ -423,7 +424,7 @@ end:
});
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) {
auto buf = ostd::appender<cs_charbuf>(cs);
cs_charbuf buf{cs};
std::string_view s = args[0].get_str();
std::string_view conj = args[1].get_str();
cs_list_parse_state p{s};
@ -431,22 +432,22 @@ end:
size_t n = 0;
for (p.set_input(s); list_parse(p, cs); ++n) {
if (!p.quoted_item.empty() && (p.quoted_item.front() == '"')) {
util::unescape_string(buf, p.item);
util::unescape_string(std::back_inserter(buf), p.item);
} else {
buf.get().append(p.item);
buf.append(p.item);
}
if ((n + 1) < len) {
if ((len > 2) || conj.empty()) {
buf.put(',');
buf.push_back(',');
}
if ((n + 2 == len) && !conj.empty()) {
buf.put(' ');
buf.get().append(conj);
buf.push_back(' ');
buf.append(conj);
}
buf.put(' ');
buf.push_back(' ');
}
}
res.set_str(buf.get().str());
res.set_str(buf.str());
});
gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) {
@ -567,7 +568,7 @@ static void cs_list_sort(
size_t nuniq = items.size();
if (body) {
ListSortFun f = { cs, xval, yval, body };
ostd::sort_cmp(ostd::iter(items.buf), f);
std::sort(items.buf.begin(), items.buf.end(), f);
if (!cs_code_is_empty(unique)) {
f.body = unique;
totaluniq = items[0].quote.size();

View File

@ -1,4 +1,5 @@
#include <functional>
#include <iterator>
#include <cubescript/cubescript.hh>
@ -59,7 +60,7 @@ void cs_init_lib_string(cs_state &cs) {
auto inps = std::string_view{args[0].get_str()};
auto *ics = cs_get_sstate(ccs);
auto *buf = ics->strman->alloc_buf(inps.size());
for (auto i: ostd::range(inps.size())) {
for (std::size_t i = 0; i < inps.size(); ++i) {
buf[i] = tolower(inps[i]);
}
auto const *cbuf = ics->strman->steal(buf);
@ -72,7 +73,7 @@ void cs_init_lib_string(cs_state &cs) {
auto inps = std::string_view{args[0].get_str()};
auto *ics = cs_get_sstate(ccs);
auto *buf = ics->strman->alloc_buf(inps.size());
for (auto i: ostd::range(inps.size())) {
for (std::size_t i = 0; i < inps.size(); ++i) {
buf[i] = toupper(inps[i]);
}
auto const *cbuf = ics->strman->steal(buf);
@ -82,15 +83,15 @@ void cs_init_lib_string(cs_state &cs) {
});
cs.new_command("escape", "s", [](auto &ccs, auto args, auto &res) {
auto s = ostd::appender<cs_charbuf>(ccs);
util::escape_string(s, args[0].get_str());
res.set_str(s.get().str());
cs_charbuf s{ccs};
util::escape_string(std::back_inserter(s), args[0].get_str());
res.set_str(s.str());
});
cs.new_command("unescape", "s", [](auto &ccs, auto args, auto &res) {
auto s = ostd::appender<cs_charbuf>(ccs);
util::unescape_string(s, args[0].get_str());
res.set_str(s.get().str());
cs_charbuf s{ccs};
util::unescape_string(std::back_inserter(s), args[0].get_str());
res.set_str(s.str());
});
cs.new_command("concat", "V", [](auto &ccs, auto args, auto &res) {