exponse concat/format code to API and properly utilize it

master
Daniel Kolesa 2016-08-10 00:10:09 +01:00
parent 8c5fd534bb
commit b7ae0c500a
3 changed files with 73 additions and 53 deletions

View File

@ -1138,32 +1138,6 @@ ostd::ConstCharRange cs_parse_str(ostd::ConstCharRange str) {
return str;
}
char *conc(ostd::Vector<char> &buf, TvalRange v, bool space) {
for (ostd::Size i = 0; i < v.size(); ++i) {
ostd::String s;
switch (v[i].get_type()) {
case VAL_INT:
s = ostd::move(intstr(v[i].i));
break;
case VAL_FLOAT:
s = ostd::move(floatstr(v[i].f));
break;
case VAL_STR:
case VAL_CSTR:
s = ostd::ConstCharRange(v[i].s, v[i].len);
break;
case VAL_MACRO:
s = ostd::ConstCharRange(v[i].s, reinterpret_cast<ostd::Uint32 const *>(v[i].code)[-1] >> 8);
break;
}
buf.push_n(s.data(), s.size());
if (i == v.size() - 1) break;
if (space) buf.push(' ');
}
buf.push('\0');
return buf.data();
}
static inline void skipcomments(char const *&p) {
for (;;) {
p += strspn(p, " \t\r");
@ -2614,9 +2588,10 @@ static inline void callcommand(CsState &cs, Ident *id, TaggedValue *args, int nu
break;
case 'C': {
i = ostd::max(i + 1, numargs);
ostd::Vector<char> buf;
auto buf = ostd::appender<ostd::String>();
cscript::util::tvals_concat(buf, ostd::iter(args, i), " ");
TaggedValue tv;
tv.set_mstr(conc(buf, ostd::iter(args, i), true));
tv.set_mstr(buf.get().iter());
id->cb_cftv(TvalRange(&tv, 1));
goto cleanup;
}
@ -3158,10 +3133,10 @@ static ostd::Uint32 const *runcode(CsState &cs, ostd::Uint32 const *code, Tagged
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
result.force_null();
{
ostd::Vector<char> buf;
buf.reserve(256);
auto buf = ostd::appender<ostd::String>();
cscript::util::tvals_concat(buf, ostd::iter(&args[offset], callargs), " ");
TaggedValue tv;
tv.set_mstr(conc(buf, ostd::iter(&args[offset], callargs), true));
tv.set_mstr(buf.get().iter());
id->cb_cftv(TvalRange(&tv, 1));
}
force_arg(result, op & CODE_RET_MASK);
@ -3178,12 +3153,11 @@ static ostd::Uint32 const *runcode(CsState &cs, ostd::Uint32 const *code, Tagged
case CODE_CONCW|RET_FLOAT:
case CODE_CONCW|RET_INT: {
int numconc = op >> 8;
ostd::Vector<char> buf;
char *s = conc(buf, ostd::iter(&args[numargs - numconc], numconc), (op & CODE_OP_MASK) == CODE_CONC);
ostd::Size len = buf.size() - 1;
buf.disown();
auto buf = ostd::appender<ostd::String>();
cscript::util::tvals_concat(buf, ostd::iter(&args[numargs - numconc], numconc), ((op & CODE_OP_MASK) == CODE_CONC) ? " " : "");
free_args(args, numargs, numargs - numconc);
args[numargs].set_mstr(ostd::CharRange(s, len));
args[numargs].set_mstr(buf.get().iter());
buf.get().disown();
force_arg(args[numargs], op & CODE_RET_MASK);
numargs++;
continue;
@ -3194,12 +3168,11 @@ static ostd::Uint32 const *runcode(CsState &cs, ostd::Uint32 const *code, Tagged
case CODE_CONCM|RET_FLOAT:
case CODE_CONCM|RET_INT: {
int numconc = op >> 8;
ostd::Vector<char> buf;
char *s = conc(buf, ostd::iter(&args[numargs - numconc], numconc), false);
ostd::Size len = buf.size() - 1;
buf.disown();
auto buf = ostd::appender<ostd::String>();
cscript::util::tvals_concat(buf, ostd::iter(&args[numargs - numconc], numconc));
free_args(args, numargs, numargs - numconc);
result.set_mstr(ostd::CharRange(s, len));
result.set_mstr(buf.get().iter());
buf.get().disown();
force_arg(result, op & CODE_RET_MASK);
continue;
}

View File

@ -550,6 +550,57 @@ namespace util {
ostd::Vector<ostd::String> list_explode(
ostd::ConstCharRange s, ostd::Size limit = -1
);
template<typename R>
inline ostd::Ptrdiff format_int(R &&writer, int val) {
return ostd::format(ostd::forward<R>(writer), "%d", val);
}
template<typename R>
inline ostd::Ptrdiff format_float(R &&writer, int val) {
return ostd::format(
ostd::forward<R>(writer), (val == int(val)) ? "%.1f" : "%.7g", val
);
}
template<typename R>
inline ostd::Size tvals_concat(
R &&writer, TvalRange vals,
ostd::ConstCharRange sep = ostd::ConstCharRange()
) {
ostd::Size ret = 0;
for (ostd::Size i = 0; i < vals.size(); ++i) {
auto s = ostd::appender<ostd::String>();
switch (vals[i].get_type()) {
case VAL_INT: {
auto r = format_int(ostd::forward<R>(writer), vals[i].i);
if (r > 0) {
ret += ostd::Size(r);
}
break;
}
case VAL_FLOAT: {
auto r = format_float(ostd::forward<R>(writer), vals[i].i);
if (r > 0) {
ret += ostd::Size(r);
}
break;
}
case VAL_STR:
case VAL_CSTR:
case VAL_MACRO:
ret += writer.put_n(vals[i].s, vals[i].len);
break;
default:
break;
}
if (i == (vals.size() - 1)) {
break;
}
ret += writer.put_n(sep.data(), sep.size());
}
return ret;
}
} /* namespace util */
} /* namespace cscript */

View File

@ -2,8 +2,6 @@
namespace cscript {
char *conc(ostd::Vector<char> &buf, TvalRange v, bool space);
void cs_init_lib_string(CsState &cs) {
cs.add_command("strstr", "ss", [&cs](TvalRange args) {
ostd::ConstCharRange a = args[0].get_strr(), b = args[1].get_strr();
@ -74,19 +72,17 @@ void cs_init_lib_string(CsState &cs) {
});
cs.add_command("concat", "V", [&cs](TvalRange args) {
ostd::Vector<char> buf;
char *s = conc(buf, args, true);
ostd::Size len = buf.size() - 1;
buf.disown();
cs.result->set_mstr(ostd::CharRange(s, len));
auto s = ostd::appender<ostd::String>();
cscript::util::tvals_concat(s, args, " ");
cs.result->set_mstr(s.get().iter());
s.get().disown();
});
cs.add_command("concatword", "V", [&cs](TvalRange args) {
ostd::Vector<char> buf;
char *s = conc(buf, args, false);
ostd::Size len = buf.size() - 1;
buf.disown();
cs.result->set_mstr(ostd::CharRange(s, len));
auto s = ostd::appender<ostd::String>();
cscript::util::tvals_concat(s, args);
cs.result->set_mstr(s.get().iter());
s.get().disown();
});
cs.add_command("format", "V", [&cs](TvalRange args) {