109 lines
2.6 KiB
C++
109 lines
2.6 KiB
C++
#ifndef LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH
|
|
#define LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH
|
|
|
|
#include <string_view>
|
|
#include <stdexcept>
|
|
#include <utility>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
namespace cubescript {
|
|
|
|
struct state;
|
|
|
|
struct internal_error: std::runtime_error {
|
|
using std::runtime_error::runtime_error;
|
|
};
|
|
|
|
struct LIBCUBESCRIPT_EXPORT stack_state {
|
|
struct node {
|
|
node const *next;
|
|
struct ident const *id;
|
|
int index;
|
|
};
|
|
|
|
stack_state() = delete;
|
|
stack_state(state &cs, node *nd = nullptr, bool gap = false);
|
|
stack_state(stack_state const &) = delete;
|
|
stack_state(stack_state &&st);
|
|
~stack_state();
|
|
|
|
stack_state &operator=(stack_state const &) = delete;
|
|
stack_state &operator=(stack_state &&);
|
|
|
|
node const *get() const;
|
|
bool gap() const;
|
|
|
|
private:
|
|
state &p_state;
|
|
node *p_node;
|
|
bool p_gap;
|
|
};
|
|
|
|
struct LIBCUBESCRIPT_EXPORT error {
|
|
friend struct state;
|
|
|
|
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)}
|
|
{}
|
|
|
|
std::string_view what() const {
|
|
return std::string_view{p_errbeg, p_errend};
|
|
}
|
|
|
|
stack_state &get_stack() {
|
|
return p_stack;
|
|
}
|
|
|
|
stack_state const &get_stack() const {
|
|
return p_stack;
|
|
}
|
|
|
|
error(state &cs, std::string_view msg):
|
|
p_errbeg{}, p_errend{}, p_stack{cs}
|
|
{
|
|
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);
|
|
}
|
|
|
|
template<typename ...A>
|
|
error(state &cs, std::string_view msg, A const &...args):
|
|
p_errbeg{}, p_errend{}, p_stack{cs}
|
|
{
|
|
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) {
|
|
throw internal_error{"format error"};
|
|
} else if (std::size_t(written) <= sz) {
|
|
break;
|
|
}
|
|
sz = std::size_t(written);
|
|
}
|
|
p_errbeg = sp;
|
|
p_errend = buf + sz;
|
|
p_stack = save_stack(cs);
|
|
}
|
|
|
|
private:
|
|
stack_state save_stack(state &cs);
|
|
char *request_buf(state &cs, std::size_t bufs, char *&sp);
|
|
|
|
char const *p_errbeg, *p_errend;
|
|
stack_state p_stack;
|
|
};
|
|
|
|
} /* namespace cubescript */
|
|
|
|
#endif /* LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH */
|