1 #ifndef _C4_YML_COMMON_HPP_
2 #define _C4_YML_COMMON_HPP_
11 #if defined(C4_MSVC) || defined(C4_MINGW)
21 #ifndef RYML_ERRMSG_SIZE
23 #define RYML_ERRMSG_SIZE (1024)
26 #ifndef RYML_LOGBUF_SIZE
32 #define RYML_LOGBUF_SIZE (256)
35 #ifndef RYML_LOGBUF_SIZE_MAX
42 #define RYML_LOGBUF_SIZE_MAX (1024)
45 #ifndef RYML_LOCATIONS_SMALL_THRESHOLD
48 #define RYML_LOCATIONS_SMALL_THRESHOLD (30)
153 # define RYML_USE_ASSERT
157 # define RYML_NO_DEFAULT_CALLBACKS
162 # define RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
166 # define RYML_NOEXCEPT
175 #ifndef RYML_USE_ASSERT
176 # define RYML_USE_ASSERT C4_USE_ASSERT
180 # define RYML_ASSERT(cond) RYML_CHECK(cond)
181 # define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)
182 # define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))
183 # define _RYML_CB_ASSERT_(cb, cond, loc) _RYML_CB_CHECK((cb), (cond), (loc))
184 # define RYML_NOEXCEPT
186 # define RYML_ASSERT(cond)
187 # define RYML_ASSERT_MSG(cond, msg)
188 # define _RYML_CB_ASSERT(cb, cond)
189 # define _RYML_CB_ASSERT_(cb, cond, loc)
190 # define RYML_NOEXCEPT noexcept
193 #define RYML_DEPRECATED(msg) C4_DEPRECATED(msg)
195 #define RYML_CHECK(cond) \
197 if(C4_UNLIKELY(!(cond))) \
199 RYML_DEBUG_BREAK(); \
200 c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
201 C4_UNREACHABLE_AFTER_ERR(); \
205 #define RYML_CHECK_MSG(cond, msg) \
208 if(C4_UNLIKELY(!(cond))) \
210 RYML_DEBUG_BREAK(); \
211 c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
212 C4_UNREACHABLE_AFTER_ERR(); \
216 #if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)
217 # define RYML_DEBUG_BREAK() \
219 if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \
225 # define RYML_DEBUG_BREAK()
238 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wold-style-cast")
245 #define RYML_ID_TYPE size_t
253 static_assert(std::is_integral<id_type>::value,
"id_type must be an integer type");
256 C4_SUPPRESS_WARNING_GCC_WITH_PUSH(
"-Wuseless-cast")
261 C4_SUPPRESS_WARNING_GCC_CLANG_POP
286 LineCol(
size_t l,
size_t c) : offset(0), line(l), col(c) {}
288 LineCol(
size_t o,
size_t l,
size_t c) : offset(o), line(l), col(c) {}
290 static_assert(std::is_trivial<LineCol>::value,
"LineCol not trivial");
291 static_assert(std::is_standard_layout<LineCol>::value,
"Location not trivial");
306 operator bool ()
const {
return !name.empty() || line != 0 || offset != 0 || col != 0; }
307 operator LineCol const& ()
const {
return reinterpret_cast<LineCol const&
>(*this); }
310 Location(
size_t l,
size_t c) : offset( ), line(l), col(c), name( ) {}
311 Location(
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name( ) {}
312 Location( csubstr n,
size_t l,
size_t c) : offset( ), line(l), col(c), name(n) {}
313 Location( csubstr n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(n) {}
315 Location(
const char *n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(
to_csubstr(n)) {}
317 static_assert(std::is_standard_layout<Location>::value,
"Location not trivial");
359 using pfn_error = void (*) (
const char* msg,
size_t msg_len,
Location location,
void *user_data);
364 using pfn_allocate =
void* (*)(
size_t len,
void* hint,
void *user_data);
369 using pfn_free = void (*)(
void* mem,
size_t size,
void *user_data);
429 [[noreturn]]
RYML_EXPORT void error(Callbacks
const& cb,
const char *msg,
size_t msg_len, Location loc);
430 [[noreturn]]
RYML_EXPORT void error(
const char *msg,
size_t msg_len, Location loc);
432 [[noreturn]]
inline void error(
const char *msg,
size_t msg_len)
434 error(msg, msg_len, Location{});
437 [[noreturn]]
inline void error(
const char (&msg)[N], Location loc)
439 error(msg, N-1, loc);
442 [[noreturn]]
inline void error(
const char (&msg)[N])
444 error(msg, N-1, Location{});
447 #define _RYML_CB_ERR(cb, msg_literal) \
448 _RYML_CB_ERR_(cb, msg_literal, c4::yml::Location(__FILE__, 0, __LINE__, 0))
449 #define _RYML_CB_CHECK(cb, cond) \
450 _RYML_CB_CHECK_(cb, cond, c4::yml::Location(__FILE__, 0, __LINE__, 0))
451 #define _RYML_CB_ERR_(cb, msg_literal, loc) \
454 const char msg[] = msg_literal; \
455 RYML_DEBUG_BREAK(); \
456 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
457 C4_UNREACHABLE_AFTER_ERR(); \
459 #define _RYML_CB_CHECK_(cb, cond, loc) \
462 if(C4_UNLIKELY(!(cond))) \
464 const char msg[] = "check failed: " #cond; \
465 RYML_DEBUG_BREAK(); \
466 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
467 C4_UNREACHABLE_AFTER_ERR(); \
470 #define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)
471 #define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), T, (num), nullptr)
472 #define _RYML_CB_FREE(cb, buf, T, num) \
474 (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
500 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
501 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return str.len; }
502 C4_ALWAYS_INLINE csubstr get() { RYML_ASSERT(valid());
return str; }
507 struct FilterResultExtending
509 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
510 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return reqlen; }
511 C4_ALWAYS_INLINE csubstr get() { RYML_ASSERT(valid());
return str; }
524 template<
int8_t
signedval, u
int8_t
unsignedval>
525 struct _charconstant_t
526 :
public std::conditional<std::is_signed<char>::value,
527 std::integral_constant<int8_t, signedval>,
528 std::integral_constant<uint8_t, unsignedval>>::type
530 #define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
539 _SubstrWriter(substr buf_,
size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }
540 void append(csubstr s)
542 C4_ASSERT(!s.overlaps(buf));
543 C4_ASSERT(s.str || !s.len);
544 if(s.len && pos + s.len <= buf.len)
547 memcpy(buf.str + pos, s.str, s.len);
558 void append_n(
char c,
size_t numtimes)
561 if(numtimes && pos + numtimes < buf.len)
562 memset(buf.str + pos, c, numtimes);
565 size_t slack()
const {
return pos <= buf.len ? buf.len - pos : 0; }
566 size_t excess()
const {
return pos > buf.len ? pos - buf.len : 0; }
568 csubstr curr()
const {
return pos <= buf.len ? buf.first(pos) : buf; }
570 substr rem() {
return pos < buf.len ? buf.sub(pos) : buf.last(0); }
572 size_t advance(
size_t more) { pos += more;
return pos; }
579 template<
class DumpFn,
class ...Args>
580 C4_NO_INLINE
void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)
589 results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);
600 substr largerbuf = {
static_cast<char*
>(_alloca(bufsize)), bufsize};
602 substr largerbuf = {
static_cast<char*
>(alloca(bufsize)), bufsize};
604 results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);
607 template<
class ...Args>
608 C4_NORETURN C4_NO_INLINE
void _report_err(Callbacks
const& C4_RESTRICT callbacks, csubstr fmt, Args
const& C4_RESTRICT ...args)
611 detail::_SubstrWriter writer(errmsg);
612 auto dumpfn = [&writer](csubstr s){ writer.append(s); };
613 _dump(dumpfn, fmt, args...);
616 callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);
617 C4_UNREACHABLE_AFTER_ERR();
622 inline csubstr _c4prc(
const char &C4_RESTRICT c)
626 case '\n':
return csubstr(
"\\n");
627 case '\t':
return csubstr(
"\\t");
628 case '\0':
return csubstr(
"\\0");
629 case '\r':
return csubstr(
"\\r");
630 case '\f':
return csubstr(
"\\f");
631 case '\b':
return csubstr(
"\\b");
632 case '\v':
return csubstr(
"\\v");
633 case '\a':
return csubstr(
"\\a");
634 default:
return csubstr(&c, 1);
640 C4_SUPPRESS_WARNING_GCC_POP
#define RYML_ID_TYPE
The type of a node id in the YAML tree.
#define RYML_ERRMSG_SIZE
size for the error message buffer
#define RYML_LOGBUF_SIZE
size for the buffer used to format individual values to string while preparing an error message....
#define RYML_LOGBUF_SIZE_MAX
size for the fallback larger log buffer. When RYML_LOGBUF_SIZE is not large enough to convert a value...
void reset_callbacks()
set the global callbacks back to their defaults ()
void(*)(const char *msg, size_t msg_len, Location location, void *user_data) pfn_error
the type of the function used to report errors
void set_callbacks(Callbacks const &c)
set the global callbacks for the library; after a call to this function, these callbacks will be used...
void *(*)(size_t len, void *hint, void *user_data) pfn_allocate
the type of the function used to allocate memory; ryml will only allocate memory through this callbac...
Callbacks const & get_callbacks()
get the global callbacks
void(*)(void *mem, size_t size, void *user_data) pfn_free
the type of the function used to free memory; ryml will only free memory through this callback.
csubstr to_csubstr(substr s) noexcept
neutral version for use in generic code
bool operator!=(const char(&s)[N], basic_substring< C > const that) noexcept
bool operator==(const char(&s)[N], basic_substring< C > const that) noexcept
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
@ npos
a null string position
void error(Callbacks const &cb, const char *msg, size_t msg_len, Location loc)
a c-style callbacks class.
holds a position into a source buffer
LineCol(size_t o, size_t l, size_t c)
construct from offset, line and column
size_t offset
number of bytes from the beginning of the source buffer
LineCol(size_t l, size_t c)
construct from line and column
Location(csubstr n, size_t b, size_t l, size_t c)
Location(const char *n, size_t l, size_t c)
size_t offset
number of bytes from the beginning of the source buffer
Location(size_t l, size_t c)
Location(csubstr n, size_t l, size_t c)
Location(const char *n, size_t b, size_t l, size_t c)
Location(size_t b, size_t l, size_t c)