libcubescript/include/cubescript/cubescript.hh

692 lines
16 KiB
C++
Raw Normal View History

2016-08-14 18:35:38 +02:00
#ifndef LIBCUBESCRIPT_CUBESCRIPT_HH
#define LIBCUBESCRIPT_CUBESCRIPT_HH
2015-09-10 19:53:43 +02:00
#include <cstring>
#include <cstddef>
2017-04-23 15:34:45 +02:00
#include <vector>
2017-01-30 19:38:11 +01:00
#include <optional>
2017-02-08 01:07:35 +01:00
#include <functional>
2017-02-09 20:59:14 +01:00
#include <type_traits>
#include <algorithm>
#include <stdexcept>
#include <memory>
2017-02-16 20:51:03 +01:00
#include <utility>
#include <span>
2021-03-24 02:42:33 +01:00
#include <new>
2017-01-30 19:38:11 +01:00
2016-08-14 18:35:38 +02:00
#include "cubescript_conf.hh"
2021-03-30 23:37:55 +02:00
#include "cubescript/callable.hh"
#if defined(__CYGWIN__) || (defined(_WIN32) && !defined(_XBOX_VER))
# ifdef LIBCUBESCRIPT_DLL
# ifdef LIBCUBESCRIPT_BUILD
# define LIBCUBESCRIPT_EXPORT __declspec(dllexport)
# else
# define LIBCUBESCRIPT_EXPORT __declspec(dllimport)
# endif
# else
# define LIBCUBESCRIPT_EXPORT
# endif
# define LIBCUBESCRIPT_LOCAL
#else
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define LIBCUBESCRIPT_EXPORT __attribute__((visibility("default")))
# define LIBCUBESCRIPT_LOCAL __attribute__((visibility("hidden")))
# else
# define LIBCUBESCRIPT_EXPORT
# define LIBCUBESCRIPT_LOCAL
# endif
#endif
2021-03-23 23:32:25 +01:00
namespace cubescript {
2015-08-08 17:13:46 +02:00
2021-03-23 23:29:32 +01:00
struct internal_error: std::runtime_error {
using std::runtime_error::runtime_error;
};
2021-04-03 05:46:05 +02:00
using alloc_func = void *(*)(void *, void *, size_t, size_t);
2021-04-03 05:46:05 +02:00
using hook_func = callable<void, struct state &>;
2021-04-03 03:37:58 +02:00
using command_func = callable<
2021-04-03 05:46:05 +02:00
void, struct state &, std::span<struct any_value>, struct any_value &
>;
2021-03-23 23:29:32 +01:00
struct internal_state;
2016-08-06 20:12:38 +02:00
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT bcode_ref {
bcode_ref():
2016-08-07 22:39:27 +02:00
p_code(nullptr)
{}
bcode_ref(struct bcode *v);
2021-03-23 23:29:32 +01:00
bcode_ref(bcode_ref const &v);
bcode_ref(bcode_ref &&v):
2016-08-07 22:39:27 +02:00
p_code(v.p_code)
{
v.p_code = nullptr;
}
2015-12-20 00:28:12 +01:00
2021-03-23 23:29:32 +01:00
~bcode_ref();
2021-03-23 23:29:32 +01:00
bcode_ref &operator=(bcode_ref const &v);
bcode_ref &operator=(bcode_ref &&v);
2015-12-20 00:28:12 +01:00
bool empty() const;
operator bool() const;
operator struct bcode *() const;
2015-12-20 00:28:12 +01:00
private:
struct bcode *p_code;
2015-12-20 00:28:12 +01:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT string_ref {
friend struct any_value;
friend struct string_pool;
2021-03-23 23:29:32 +01:00
string_ref() = delete;
string_ref(internal_state *cs, std::string_view str);
string_ref(state &cs, std::string_view str);
2021-03-23 23:29:32 +01:00
string_ref(string_ref const &ref);
2021-03-23 23:29:32 +01:00
~string_ref();
2021-03-23 23:29:32 +01:00
string_ref &operator=(string_ref const &ref);
operator std::string_view() const;
2021-03-17 21:57:47 +01:00
std::size_t size() const {
return std::string_view{*this}.size();
2021-03-17 21:57:47 +01:00
}
std::size_t length() const {
return std::string_view{*this}.length();
2021-03-17 21:57:47 +01:00
}
2021-03-17 23:32:38 +01:00
char const *data() const {
return std::string_view{*this}.data();
2021-03-17 23:32:38 +01:00
}
2021-03-23 23:29:32 +01:00
bool operator==(string_ref const &s) const;
private:
/* for internal use only */
2021-03-23 23:29:32 +01:00
string_ref(char const *p, internal_state *cs);
2021-03-23 23:29:32 +01:00
internal_state *p_state;
char const *p_str;
};
2021-03-23 23:29:32 +01:00
enum class value_type {
2021-03-18 20:55:14 +01:00
NONE = 0, INT, FLOAT, STRING, CODE, IDENT
};
2021-04-03 05:46:05 +02:00
struct ident;
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT any_value {
any_value() = delete;
~any_value();
2021-03-23 23:29:32 +01:00
any_value(state &);
any_value(internal_state &);
2021-03-23 23:29:32 +01:00
any_value(any_value const &);
any_value(any_value &&v);
2021-03-23 23:29:32 +01:00
any_value &operator=(any_value const &);
any_value &operator=(any_value &&);
2021-03-23 23:29:32 +01:00
value_type get_type() const;
2016-08-25 22:24:23 +02:00
2021-03-23 23:29:32 +01:00
void set_int(integer_type val);
void set_float(float_type val);
void set_str(std::string_view val);
2021-03-23 23:29:32 +01:00
void set_str(string_ref const &val);
2021-03-18 20:55:14 +01:00
void set_none();
void set_code(bcode_ref const &val);
2021-03-23 23:29:32 +01:00
void set_ident(ident *val);
2016-08-25 22:24:23 +02:00
2021-03-23 23:29:32 +01:00
string_ref get_str() const;
integer_type get_int() const;
float_type get_float() const;
bcode_ref get_code() const;
2021-03-23 23:29:32 +01:00
ident *get_ident() const;
void get_val(any_value &r) const;
bool get_bool() const;
2021-03-18 20:55:14 +01:00
void force_none();
2021-03-23 23:29:32 +01:00
float_type force_float();
integer_type force_int();
std::string_view force_str();
bcode_ref force_code(state &cs);
ident *force_ident(state &cs);
2015-08-13 22:48:03 +02:00
private:
template<typename T>
struct stor_t {
2021-03-23 23:29:32 +01:00
internal_state *state;
T val;
};
2021-03-23 23:29:32 +01:00
internal_state *get_state() const {
2021-03-24 02:42:33 +01:00
return std::launder(
reinterpret_cast<stor_t<void *> const *>(&p_stor)
)->state;
}
std::aligned_union_t<1,
2021-03-23 23:29:32 +01:00
stor_t<integer_type>,
stor_t<float_type>,
stor_t<void *>,
2021-03-23 23:29:32 +01:00
string_ref
> p_stor;
2021-03-23 23:29:32 +01:00
value_type p_type;
};
2021-03-23 23:29:32 +01:00
struct error;
struct codegen_state;
2021-03-23 23:29:32 +01:00
enum class ident_type {
2021-03-18 20:55:14 +01:00
IVAR = 0, FVAR, SVAR, COMMAND, ALIAS, SPECIAL
2016-08-10 19:33:43 +02:00
};
2021-03-23 23:29:32 +01:00
struct global_var;
struct integer_var;
struct float_var;
struct string_var;
struct alias;
struct command;
2016-08-18 00:54:57 +02:00
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT ident {
2021-03-21 02:41:04 +01:00
int get_raw_type() const;
2021-03-23 23:29:32 +01:00
ident_type get_type() const;
std::string_view get_name() const;
2016-08-18 03:53:51 +02:00
int get_index() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_alias() const;
2021-03-23 23:29:32 +01:00
alias *get_alias();
alias const *get_alias() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_command() const;
2021-03-23 23:29:32 +01:00
command *get_command();
command const *get_command() const;
2016-08-18 03:53:51 +02:00
bool is_special() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_var() const;
2021-03-23 23:29:32 +01:00
global_var *get_var();
global_var const *get_var() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_ivar() const;
2021-03-23 23:29:32 +01:00
integer_var *get_ivar();
integer_var const *get_ivar() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_fvar() const;
2021-03-23 23:29:32 +01:00
float_var *get_fvar();
float_var const *get_fvar() const;
2016-08-10 19:33:43 +02:00
2016-08-18 00:54:57 +02:00
bool is_svar() const;
2021-03-23 23:29:32 +01:00
string_var *get_svar();
string_var const *get_svar() const;
2016-08-17 23:04:43 +02:00
bool is_overridden(state &cs) const;
bool is_persistent(state &cs) const;
2016-08-17 23:04:43 +02:00
protected:
2021-03-23 23:29:32 +01:00
ident() = default;
2016-08-18 03:53:51 +02:00
2021-04-03 06:16:43 +02:00
friend struct internal_state;
2021-03-21 02:41:04 +01:00
2021-04-03 05:46:05 +02:00
struct ident_impl *p_impl{};
2016-08-17 23:04:43 +02:00
};
enum class var_type {
DEFAULT = 0,
PERSISTENT,
OVERRIDABLE
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT global_var: ident {
bool is_read_only() const;
bool is_overridable() const;
var_type get_variable_type() const;
2021-04-04 02:44:35 +02:00
void save(state &cs);
2016-08-18 04:14:55 +02:00
protected:
2021-03-23 23:29:32 +01:00
global_var() = default;
2016-08-17 23:04:43 +02:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT integer_var: global_var {
integer_type get_value() const;
void set_value(
state &cs, integer_type val, bool do_write = true, bool trigger = true
);
2021-04-04 02:58:04 +02:00
void set_raw_value(integer_type val);
2021-03-21 02:41:04 +01:00
protected:
2021-03-23 23:29:32 +01:00
integer_var() = default;
2016-08-17 23:04:43 +02:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT float_var: global_var {
float_type get_value() const;
void set_value(
state &cs, float_type val, bool do_write = true, bool trigger = true
);
2021-04-04 02:58:04 +02:00
void set_raw_value(float_type val);
2021-03-21 02:41:04 +01:00
protected:
2021-03-23 23:29:32 +01:00
float_var() = default;
2016-08-17 23:04:43 +02:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT string_var: global_var {
string_ref get_value() const;
void set_value(
state &cs, string_ref val, bool do_write = true, bool trigger = true
);
2021-04-04 02:58:04 +02:00
void set_raw_value(string_ref val);
2021-03-21 02:41:04 +01:00
protected:
2021-03-23 23:29:32 +01:00
string_var() = default;
2016-08-17 23:04:43 +02:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT alias: ident {
bool is_arg() const;
2021-03-21 02:41:04 +01:00
protected:
2021-03-23 23:29:32 +01:00
alias() = default;
2016-08-17 23:04:43 +02:00
};
struct LIBCUBESCRIPT_EXPORT command: ident {
std::string_view get_args() const;
2016-09-02 22:49:05 +02:00
int get_num_args() const;
2021-03-21 02:41:04 +01:00
protected:
2021-03-23 23:29:32 +01:00
command() = default;
};
2016-08-18 20:47:29 +02:00
enum {
2021-03-23 23:29:32 +01:00
LIB_MATH = 1 << 0,
LIB_STRING = 1 << 1,
LIB_LIST = 1 << 2,
LIB_ALL = 0b111
2016-08-18 20:47:29 +02:00
};
2021-03-23 23:29:32 +01:00
enum class loop_state {
2021-03-18 20:55:14 +01:00
NORMAL = 0, BREAK, CONTINUE
2016-09-14 23:24:13 +02:00
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT state {
state();
state(alloc_func func, void *data);
virtual ~state();
2021-03-23 23:29:32 +01:00
state(state const &) = delete;
state(state &&s) {
2018-04-26 19:23:11 +02:00
swap(s);
}
2021-03-23 23:29:32 +01:00
state &operator=(state const &) = delete;
state &operator=(state &&s) {
2018-04-26 19:23:11 +02:00
swap(s);
s.destroy();
return *this;
}
void destroy();
2021-03-23 23:29:32 +01:00
void swap(state &s) {
std::swap(p_tstate, s.p_tstate);
2018-04-26 19:23:11 +02:00
}
2021-03-23 23:29:32 +01:00
state new_thread();
2018-04-26 19:23:11 +02:00
template<typename F>
2021-03-23 23:29:32 +01:00
hook_func set_call_hook(F &&f) {
return set_call_hook(
2021-03-23 23:29:32 +01:00
hook_func{std::forward<F>(f), callable_alloc, this}
);
}
2021-03-23 23:29:32 +01:00
hook_func const &get_call_hook() const;
hook_func &get_call_hook();
2021-03-23 23:29:32 +01:00
void init_libs(int libs = LIB_ALL);
void clear_override(ident &id);
void clear_overrides();
2021-03-23 23:29:32 +01:00
integer_var *new_ivar(
std::string_view n, integer_type v, bool read_only = false,
var_type vtp = var_type::DEFAULT
2021-04-03 03:37:58 +02:00
);
2021-03-23 23:29:32 +01:00
float_var *new_fvar(
std::string_view n, float_type v, bool read_only = false,
var_type vtp = var_type::DEFAULT
2021-04-03 03:37:58 +02:00
);
2021-03-23 23:29:32 +01:00
string_var *new_svar(
std::string_view n, std::string_view v, bool read_only = false,
var_type vtp = var_type::DEFAULT
2021-04-03 03:37:58 +02:00
);
ident *new_ident(std::string_view n);
void reset_var(std::string_view name);
void touch_var(std::string_view name);
2021-04-03 03:37:58 +02:00
template<typename F>
2021-03-23 23:29:32 +01:00
command *new_command(
std::string_view name, std::string_view args, F &&f
) {
return new_command(
name, args,
2021-03-23 23:29:32 +01:00
command_func{std::forward<F>(f), callable_alloc, this}
);
}
2016-09-02 19:03:01 +02:00
2021-03-23 23:29:32 +01:00
ident *get_ident(std::string_view name);
alias *get_alias(std::string_view name);
bool have_ident(std::string_view name);
2021-03-23 23:29:32 +01:00
std::span<ident *> get_idents();
std::span<ident const *> get_idents() const;
void run(bcode_ref const &code, any_value &ret);
2021-03-23 23:29:32 +01:00
void run(std::string_view code, any_value &ret);
void run(std::string_view code, any_value &ret, std::string_view source);
void run(ident *id, std::span<any_value> args, any_value &ret);
2015-08-07 22:04:31 +02:00
any_value run(bcode_ref const &code);
2021-03-23 23:29:32 +01:00
any_value run(std::string_view code);
any_value run(std::string_view code, std::string_view source);
any_value run(ident *id, std::span<any_value> args);
2016-08-18 20:34:24 +02:00
loop_state run_loop(bcode_ref const &code, any_value &ret);
loop_state run_loop(bcode_ref const &code);
2016-09-14 23:24:13 +02:00
bool get_override_mode() const;
bool set_override_mode(bool v);
bool get_persist_mode() const;
bool set_persist_mode(bool v);
std::size_t get_max_run_depth() const;
std::size_t set_max_run_depth(std::size_t v);
2021-03-23 23:29:32 +01:00
void set_alias(std::string_view name, any_value v);
2015-08-07 03:11:53 +02:00
2021-03-23 23:29:32 +01:00
std::optional<string_ref> get_alias_val(std::string_view name);
2015-08-07 22:38:57 +02:00
2016-08-21 02:34:03 +02:00
private:
friend struct state_p;
2021-03-23 23:29:32 +01:00
hook_func set_call_hook(hook_func func);
2021-03-23 23:29:32 +01:00
command *new_command(
std::string_view name, std::string_view args, command_func func
);
static void *callable_alloc(
void *data, void *p, std::size_t os, std::size_t ns
) {
2021-03-23 23:29:32 +01:00
return static_cast<state *>(data)->alloc(p, os, ns);
}
2021-03-23 23:29:32 +01:00
LIBCUBESCRIPT_LOCAL state(internal_state *s);
2018-04-26 19:23:11 +02:00
void *alloc(void *ptr, size_t olds, size_t news);
2021-03-26 03:05:14 +01:00
struct thread_state *p_tstate = nullptr;
};
struct LIBCUBESCRIPT_EXPORT stack_state {
2021-03-26 02:59:42 +01:00
struct node {
node const *next;
ident const *id;
int index;
};
2021-03-23 23:29:32 +01:00
stack_state() = delete;
stack_state(state &cs, node *nd = nullptr, bool gap = false);
2021-03-23 23:29:32 +01:00
stack_state(stack_state const &) = delete;
stack_state(stack_state &&st);
~stack_state();
2016-09-14 00:14:21 +02:00
2021-03-23 23:29:32 +01:00
stack_state &operator=(stack_state const &) = delete;
stack_state &operator=(stack_state &&);
2016-09-14 00:14:21 +02:00
2021-03-26 02:59:42 +01:00
node const *get() const;
2016-09-14 00:14:21 +02:00
bool gap() const;
private:
state &p_state;
2021-03-26 02:59:42 +01:00
node *p_node;
2016-09-14 00:14:21 +02:00
bool p_gap;
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT error {
friend struct state;
2016-09-14 00:14:21 +02:00
2021-03-23 23:29:32 +01:00
error() = delete;
error(error const &) = delete;
error(error &&v):
p_errbeg{v.p_errbeg}, p_errend{v.p_errend},
p_stack{std::move(v.p_stack)}
2016-09-14 00:14:21 +02:00
{}
std::string_view what() const {
return std::string_view{p_errbeg, p_errend};
2016-09-14 00:14:21 +02:00
}
2021-03-23 23:29:32 +01:00
stack_state &get_stack() {
2016-09-14 00:14:21 +02:00
return p_stack;
}
2021-03-23 23:29:32 +01:00
stack_state const &get_stack() const {
2016-09-14 00:14:21 +02:00
return p_stack;
}
error(state &cs, std::string_view msg):
p_errbeg{}, p_errend{}, p_stack{cs}
2016-09-14 00:14:21 +02:00
{
char *sp;
char *buf = request_buf(cs, msg.size(), sp);
std::memcpy(buf, msg.data(), msg.size());
buf[msg.size()] = '\0';
p_errbeg = sp;
p_errend = buf + msg.size();
p_stack = save_stack(cs);
2016-09-14 00:14:21 +02:00
}
template<typename ...A>
error(state &cs, std::string_view msg, A const &...args):
p_errbeg{}, p_errend{}, p_stack{cs}
2016-09-14 00:14:21 +02:00
{
std::size_t sz = msg.size() + 64;
char *buf, *sp;
for (;;) {
buf = request_buf(cs, sz, sp);
int written = std::snprintf(buf, sz, msg.data(), args...);
if (written <= 0) {
2021-03-23 23:29:32 +01:00
throw internal_error{"format error"};
} else if (std::size_t(written) <= sz) {
break;
}
sz = std::size_t(written);
2016-09-14 00:14:21 +02:00
}
p_errbeg = sp;
p_errend = buf + sz;
p_stack = save_stack(cs);
2016-09-14 00:14:21 +02:00
}
private:
stack_state save_stack(state &cs);
char *request_buf(state &cs, std::size_t bufs, char *&sp);
2016-09-14 00:14:21 +02:00
char const *p_errbeg, *p_errend;
2021-03-23 23:29:32 +01:00
stack_state p_stack;
2016-09-14 00:14:21 +02:00
};
2021-04-02 04:43:57 +02:00
struct LIBCUBESCRIPT_EXPORT alias_local {
alias_local(state &cs, ident *a);
~alias_local();
2021-04-02 04:43:57 +02:00
alias_local(alias_local const &) = delete;
alias_local(alias_local &&) = delete;
2021-04-02 04:43:57 +02:00
alias_local &operator=(alias_local const &) = delete;
alias_local &operator=(alias_local &&v) = delete;
alias *get_alias() noexcept { return p_alias; }
alias const *get_alias() const noexcept { return p_alias; }
bool set(any_value val);
explicit operator bool() const noexcept;
private:
alias *p_alias;
void *p_sp;
};
2021-03-23 23:29:32 +01:00
struct LIBCUBESCRIPT_EXPORT list_parser {
list_parser(state &cs, std::string_view s = std::string_view{}):
2021-03-20 19:34:26 +01:00
p_state{&cs}, p_input_beg{s.data()}, p_input_end{s.data() + s.size()}
{}
2021-03-18 23:53:16 +01:00
void set_input(std::string_view s) {
2021-03-20 19:34:26 +01:00
p_input_beg = s.data();
p_input_end = s.data() + s.size();
}
std::string_view get_input() const {
2021-03-20 19:34:26 +01:00
return std::string_view{p_input_beg, p_input_end};
}
2021-03-20 19:34:26 +01:00
bool parse();
std::size_t count();
2021-03-23 23:29:32 +01:00
string_ref get_item() const;
2021-03-20 19:34:26 +01:00
2021-03-31 01:48:56 +02:00
std::string_view get_raw_item() const {
return std::string_view{p_ibeg, p_iend};
}
std::string_view get_quoted_item() const {
return std::string_view{p_qbeg, p_qend};
}
2021-03-20 19:34:26 +01:00
void skip_until_item();
2021-03-18 23:53:16 +01:00
2021-03-20 19:34:26 +01:00
private:
2021-03-23 23:29:32 +01:00
state *p_state;
2021-03-20 19:34:26 +01:00
char const *p_input_beg, *p_input_end;
2021-03-31 01:48:56 +02:00
char const *p_ibeg{}, *p_iend{};
char const *p_qbeg{}, *p_qend{};
2021-03-20 19:34:26 +01:00
};
2021-03-18 23:53:16 +01:00
2021-03-23 02:02:43 +01:00
2021-03-23 23:29:32 +01:00
LIBCUBESCRIPT_EXPORT char const *parse_string(
state &cs, std::string_view str, size_t &nlines
2021-03-23 02:02:43 +01:00
);
2021-03-23 23:29:32 +01:00
inline char const *parse_string(
state &cs, std::string_view str
2021-03-23 02:02:43 +01:00
) {
size_t nlines;
2021-03-23 23:29:32 +01:00
return parse_string(cs, str, nlines);
2021-03-23 02:02:43 +01:00
}
2021-03-23 23:29:32 +01:00
LIBCUBESCRIPT_EXPORT char const *parse_word(
state &cs, std::string_view str
2021-03-23 02:02:43 +01:00
);
2021-03-23 23:29:32 +01:00
LIBCUBESCRIPT_EXPORT string_ref concat_values(
state &cs, std::span<any_value> vals,
2021-03-20 05:41:25 +01:00
std::string_view sep = std::string_view{}
);
2021-03-23 02:02:43 +01:00
template<typename R>
2021-03-23 23:29:32 +01:00
inline R escape_string(R writer, std::string_view str) {
2021-03-23 02:02:43 +01:00
*writer++ = '"';
for (auto c: str) {
switch (c) {
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;
2015-08-08 17:06:18 +02:00
}
}
2021-03-23 02:02:43 +01:00
*writer++ = '"';
return writer;
}
2015-08-08 18:07:01 +02:00
2021-03-23 02:02:43 +01:00
template<typename R>
2021-03-23 23:29:32 +01:00
inline R unescape_string(R writer, std::string_view str) {
2021-03-23 02:02:43 +01:00
for (auto it = str.begin(); it != str.end(); ++it) {
if (*it == '^') {
++it;
if (it == str.end()) {
break;
}
switch (*it) {
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;
if (it == str.end()) {
break;
}
char c = *it;
if ((c == '\r') || (c == '\n')) {
if ((c == '\r') && ((it + 1) != str.end())) {
if (it[1] == '\n') {
++it;
}
}
2021-03-23 02:02:43 +01:00
continue;
2015-08-11 03:18:53 +02:00
}
2021-03-23 02:02:43 +01:00
*writer++ = '\\';
} else {
*writer++ = *it;
2015-08-11 03:18:53 +02:00
}
}
2021-03-23 02:02:43 +01:00
return writer;
}
template<typename R>
2021-03-23 23:29:32 +01:00
inline R print_stack(R writer, stack_state const &st) {
2021-03-23 02:02:43 +01:00
char buf[32] = {0};
auto nd = st.get();
while (nd) {
auto name = nd->id->get_name();
*writer++ = ' ';
*writer++ = ' ';
if ((nd->index == 1) && st.gap()) {
*writer++ = '.';
*writer++ = '.';
}
snprintf(buf, sizeof(buf), "%d", nd->index);
char const *p = buf;
std::copy(p, p + strlen(p), writer);
*writer++ = ')';
std::copy(name.begin(), name.end(), writer);
nd = nd->next;
if (nd) {
*writer++ = '\n';
2016-09-09 19:19:50 +02:00
}
}
2021-03-23 02:02:43 +01:00
return writer;
}
2015-08-08 17:13:46 +02:00
2021-03-23 23:32:25 +01:00
} /* namespace cubescript */
2015-09-10 19:53:43 +02:00
2016-08-14 18:35:38 +02:00
#endif /* LIBCUBESCRIPT_CUBESCRIPT_HH */