Path: blob/master/dep/rapidyaml/include/c4/yml/common.hpp
4264 views
#ifndef _C4_YML_COMMON_HPP_1#define _C4_YML_COMMON_HPP_23#include <cstddef>4#include <c4/substr.hpp>5#include <c4/yml/export.hpp>678#ifndef RYML_USE_ASSERT9# define RYML_USE_ASSERT C4_USE_ASSERT10#endif111213#if RYML_USE_ASSERT14# define RYML_ASSERT(cond) RYML_CHECK(cond)15# define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)16#else17# define RYML_ASSERT(cond)18# define RYML_ASSERT_MSG(cond, msg)19#endif202122#if defined(NDEBUG) || defined(C4_NO_DEBUG_BREAK)23# define RYML_DEBUG_BREAK()24#else25# define RYML_DEBUG_BREAK() \26{ \27if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \28{ \29C4_DEBUG_BREAK(); \30} \31}32#endif333435#define RYML_CHECK(cond) \36do { \37if(!(cond)) \38{ \39RYML_DEBUG_BREAK() \40c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \41} \42} while(0)4344#define RYML_CHECK_MSG(cond, msg) \45do \46{ \47if(!(cond)) \48{ \49RYML_DEBUG_BREAK() \50c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \51} \52} while(0)535455#if C4_CPP >= 1456# define RYML_DEPRECATED(msg) [[deprecated(msg)]]57#else58# if defined(_MSC_VER)59# define RYML_DEPRECATED(msg) __declspec(deprecated(msg))60# else // defined(__GNUC__) || defined(__clang__)61# define RYML_DEPRECATED(msg) __attribute__((deprecated(msg)))62# endif63#endif646566//-----------------------------------------------------------------------------67//-----------------------------------------------------------------------------68//-----------------------------------------------------------------------------6970namespace c4 {71namespace yml {7273C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")7475enum : size_t {76/** a null position */77npos = size_t(-1),78/** an index to none */79NONE = size_t(-1)80};818283//-----------------------------------------------------------------------------84//-----------------------------------------------------------------------------85//-----------------------------------------------------------------------------8687//! holds a position into a source buffer88struct RYML_EXPORT LineCol89{90//! number of bytes from the beginning of the source buffer91size_t offset;92//! line93size_t line;94//! column95size_t col;9697LineCol() : offset(), line(), col() {}98//! construct from line and column99LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {}100//! construct from offset, line and column101LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {}102};103104105//! a source file position106struct RYML_EXPORT Location : public LineCol107{108csubstr name;109110operator bool () const { return !name.empty() || line != 0 || offset != 0; }111112Location() : LineCol(), name() {}113Location( size_t l, size_t c) : LineCol{ l, c}, name( ) {}114Location( csubstr n, size_t l, size_t c) : LineCol{ l, c}, name(n) {}115Location( csubstr n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(n) {}116Location(const char *n, size_t l, size_t c) : LineCol{ l, c}, name(to_csubstr(n)) {}117Location(const char *n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(to_csubstr(n)) {}118};119120121//-----------------------------------------------------------------------------122123/** the type of the function used to report errors. This function must124* interrupt execution, either by raising an exception or calling125* std::abort().126*127* @warning the error callback must never return: it must either abort128* or throw an exception. Otherwise, the parser will enter into an129* infinite loop, or the program may crash. */130using pfn_error = void (*)(const char* msg, size_t msg_len, Location location, void *user_data);131/** the type of the function used to allocate memory */132using pfn_allocate = void* (*)(size_t len, void* hint, void *user_data);133/** the type of the function used to free memory */134using pfn_free = void (*)(void* mem, size_t size, void *user_data);135136/** trigger an error: call the current error callback. */137RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc);138/** @overload error */139inline void error(const char *msg, size_t msg_len)140{141error(msg, msg_len, Location{});142}143/** @overload error */144template<size_t N>145inline void error(const char (&msg)[N], Location loc)146{147error(msg, N-1, loc);148}149/** @overload error */150template<size_t N>151inline void error(const char (&msg)[N])152{153error(msg, N-1, Location{});154}155156//-----------------------------------------------------------------------------157158/** a c-style callbacks class159*160* @warning the error callback must never return: it must either abort161* or throw an exception. Otherwise, the parser will enter into an162* infinite loop, or the program may crash. */163struct RYML_EXPORT Callbacks164{165void * m_user_data;166pfn_allocate m_allocate;167pfn_free m_free;168pfn_error m_error;169170Callbacks();171Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error_);172173bool operator!= (Callbacks const& that) const { return !operator==(that); }174bool operator== (Callbacks const& that) const175{176return (m_user_data == that.m_user_data &&177m_allocate == that.m_allocate &&178m_free == that.m_free &&179m_error == that.m_error);180}181};182183/** set the global callbacks.184*185* @warning the error callback must never return: it must either abort186* or throw an exception. Otherwise, the parser will enter into an187* infinite loop, or the program may crash. */188RYML_EXPORT void set_callbacks(Callbacks const& c);189/// get the global callbacks190RYML_EXPORT Callbacks const& get_callbacks();191/// set the global callbacks back to their defaults192RYML_EXPORT void reset_callbacks();193194/// @cond dev195#define _RYML_CB_ERR(cb, msg_literal) \196do \197{ \198const char msg[] = msg_literal; \199RYML_DEBUG_BREAK() \200(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \201} while(0)202#define _RYML_CB_CHECK(cb, cond) \203do \204{ \205if(!(cond)) \206{ \207const char msg[] = "check failed: " #cond; \208RYML_DEBUG_BREAK() \209(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \210} \211} while(0)212#ifdef RYML_USE_ASSERT213#define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))214#else215#define _RYML_CB_ASSERT(cb, cond) do {} while(0)216#endif217#define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)218#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), (T), (num), nullptr)219#define _RYML_CB_FREE(cb, buf, T, num) \220do { \221(cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \222(buf) = nullptr; \223} while(0)224225226227namespace detail {228template<int8_t signedval, uint8_t unsignedval>229struct _charconstant_t230: public std::conditional<std::is_signed<char>::value,231std::integral_constant<int8_t, signedval>,232std::integral_constant<uint8_t, unsignedval>>::type233{};234#define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value235} // namespace detail236237238namespace detail {239struct _SubstrWriter240{241substr buf;242size_t pos;243_SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) {}244void append(csubstr s)245{246C4_ASSERT(!s.overlaps(buf));247if(pos + s.len <= buf.len)248memcpy(buf.str + pos, s.str, s.len);249pos += s.len;250}251void append(char c)252{253if(pos < buf.len)254buf.str[pos] = c;255++pos;256}257void append_n(char c, size_t numtimes)258{259if(pos + numtimes < buf.len)260memset(buf.str + pos, c, numtimes);261pos += numtimes;262}263size_t slack() const { return pos <= buf.len ? buf.len - pos : 0; }264size_t excess() const { return pos > buf.len ? pos - buf.len : 0; }265//! get the part written so far266csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; }267//! get the part that is still free to write to (the remainder)268substr rem() { return pos < buf.len ? buf.sub(pos) : buf.last(0); }269270size_t advance(size_t more) { pos += more; return pos; }271};272} // namespace detail273274/// @endcond275276C4_SUPPRESS_WARNING_GCC_CLANG_POP277278} // namespace yml279} // namespace c4280281#endif /* _C4_YML_COMMON_HPP_ */282283284