#ifndef LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH #define LIBCUBESCRIPT_CUBESCRIPT_ERROR_HH #include #include #include #include #include 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, std::size_t(p_errend - p_errbeg)}; } 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 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 */