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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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