1 #ifndef _C4_YML_COMMON_HPP_
2 #define _C4_YML_COMMON_HPP_
12 #if defined(C4_MSVC) || defined(C4_MINGW)
22 #ifndef RYML_ERRMSG_SIZE
24 #define RYML_ERRMSG_SIZE (1024)
27 #ifndef RYML_LOGBUF_SIZE
33 #define RYML_LOGBUF_SIZE (256)
36 #ifndef RYML_LOGBUF_SIZE_MAX
43 #define RYML_LOGBUF_SIZE_MAX (1024)
46 #ifndef RYML_LOCATIONS_SMALL_THRESHOLD
49 #define RYML_LOCATIONS_SMALL_THRESHOLD (30)
154 # define RYML_USE_ASSERT
158 # define RYML_NO_DEFAULT_CALLBACKS
163 # define RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
167 # define RYML_NOEXCEPT
176 #ifndef RYML_USE_ASSERT
177 # define RYML_USE_ASSERT C4_USE_ASSERT
181 # define RYML_ASSERT(cond) RYML_CHECK(cond)
182 # define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)
183 # define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))
184 # define _RYML_CB_ASSERT_(cb, cond, loc) _RYML_CB_CHECK((cb), (cond), (loc))
185 # define RYML_NOEXCEPT
187 # define RYML_ASSERT(cond)
188 # define RYML_ASSERT_MSG(cond, msg)
189 # define _RYML_CB_ASSERT(cb, cond)
190 # define _RYML_CB_ASSERT_(cb, cond, loc)
191 # define RYML_NOEXCEPT noexcept
194 #define RYML_DEPRECATED(msg) C4_DEPRECATED(msg)
196 #define RYML_CHECK(cond) \
198 if(C4_UNLIKELY(!(cond))) \
200 RYML_DEBUG_BREAK(); \
201 c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
202 C4_UNREACHABLE_AFTER_ERR(); \
206 #define RYML_CHECK_MSG(cond, msg) \
209 if(C4_UNLIKELY(!(cond))) \
211 RYML_DEBUG_BREAK(); \
212 c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
213 C4_UNREACHABLE_AFTER_ERR(); \
217 #if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)
218 # define RYML_DEBUG_BREAK() \
220 if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \
226 # define RYML_DEBUG_BREAK()
239 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wold-style-cast")
246 #define RYML_ID_TYPE size_t
254 static_assert(std::is_integral<id_type>::value,
"id_type must be an integer type");
257 C4_SUPPRESS_WARNING_GCC_WITH_PUSH(
"-Wuseless-cast")
262 C4_SUPPRESS_WARNING_GCC_CLANG_POP
287 LineCol(
size_t l,
size_t c) : offset(0), line(l), col(c) {}
289 LineCol(
size_t o,
size_t l,
size_t c) : offset(o), line(l), col(c) {}
291 static_assert(std::is_trivial<LineCol>::value,
"LineCol not trivial");
292 static_assert(std::is_standard_layout<LineCol>::value,
"Location not trivial");
307 operator bool ()
const {
return !name.empty() || line != 0 || offset != 0 || col != 0; }
308 operator LineCol const& ()
const {
return reinterpret_cast<LineCol const&
>(*this); }
311 Location(
size_t l,
size_t c) : offset( ), line(l), col(c), name( ) {}
312 Location(
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name( ) {}
313 Location( csubstr n,
size_t l,
size_t c) : offset( ), line(l), col(c), name(n) {}
314 Location( csubstr n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(n) {}
316 Location(
const char *n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(
to_csubstr(n)) {}
318 static_assert(std::is_standard_layout<Location>::value,
"Location not trivial");
360 using pfn_error = void (*) (
const char* msg,
size_t msg_len,
Location location,
void *user_data);
365 using pfn_allocate =
void* (*)(
size_t len,
void* hint,
void *user_data);
370 using pfn_free = void (*)(
void* mem,
size_t size,
void *user_data);
444 [[noreturn]]
RYML_EXPORT void error(Callbacks
const& cb,
const char *msg,
size_t msg_len, Location loc);
445 [[noreturn]]
RYML_EXPORT void error(
const char *msg,
size_t msg_len, Location loc);
447 [[noreturn]]
inline void error(
const char *msg,
size_t msg_len)
449 error(msg, msg_len, Location{});
452 [[noreturn]]
inline void error(
const char (&msg)[N], Location loc)
454 error(msg, N-1, loc);
457 [[noreturn]]
inline void error(
const char (&msg)[N])
459 error(msg, N-1, Location{});
462 #define _RYML_CB_ERR(cb, msg_literal) \
463 _RYML_CB_ERR_(cb, msg_literal, c4::yml::Location(__FILE__, 0, __LINE__, 0))
464 #define _RYML_CB_CHECK(cb, cond) \
465 _RYML_CB_CHECK_(cb, cond, c4::yml::Location(__FILE__, 0, __LINE__, 0))
466 #define _RYML_CB_ERR_(cb, msg_literal, loc) \
469 const char msg[] = msg_literal; \
470 RYML_DEBUG_BREAK(); \
471 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
472 C4_UNREACHABLE_AFTER_ERR(); \
474 #define _RYML_CB_CHECK_(cb, cond, loc) \
477 if(C4_UNLIKELY(!(cond))) \
479 const char msg[] = "check failed: " #cond; \
480 RYML_DEBUG_BREAK(); \
481 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
482 C4_UNREACHABLE_AFTER_ERR(); \
485 #define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)
486 #define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), T, (num), nullptr)
487 #define _RYML_CB_FREE(cb, buf, T, num) \
489 (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
514 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
515 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return str.len; }
516 C4_ALWAYS_INLINE csubstr get()
const { RYML_ASSERT(valid());
return str; }
521 struct FilterResultExtending
523 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
524 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return reqlen; }
525 C4_ALWAYS_INLINE csubstr get()
const { RYML_ASSERT(valid());
return str; }
538 template<
int8_t
signedval, u
int8_t
unsignedval>
539 struct _charconstant_t
540 :
public std::conditional<std::is_signed<char>::value,
541 std::integral_constant<int8_t, static_cast<int8_t>(unsignedval)>,
542 std::integral_constant<uint8_t, unsignedval>>::type
544 #define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
553 _SubstrWriter(substr buf_,
size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }
554 void append(csubstr s)
556 C4_ASSERT(!s.overlaps(buf));
557 C4_ASSERT(s.str || !s.len);
558 if(s.len && pos + s.len <= buf.len)
561 memcpy(buf.str + pos, s.str, s.len);
572 void append_n(
char c,
size_t numtimes)
575 if(numtimes && pos + numtimes < buf.len)
576 memset(buf.str + pos, c, numtimes);
579 size_t slack()
const {
return pos <= buf.len ? buf.len - pos : 0; }
580 size_t excess()
const {
return pos > buf.len ? pos - buf.len : 0; }
582 csubstr curr()
const {
return pos <= buf.len ? buf.first(pos) : buf; }
584 substr rem()
const {
return pos < buf.len ? buf.sub(pos) : buf.last(0); }
586 size_t advance(
size_t more) { pos += more;
return pos; }
593 template<
class DumpFn,
class ...Args>
594 C4_NO_INLINE
void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)
603 results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);
614 substr largerbuf = {
static_cast<char*
>(_alloca(bufsize)), bufsize};
616 substr largerbuf = {
static_cast<char*
>(alloca(bufsize)), bufsize};
618 results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);
621 template<
class ...Args>
622 C4_NORETURN C4_NO_INLINE
void _report_err(Callbacks
const& C4_RESTRICT callbacks, csubstr fmt, Args
const& C4_RESTRICT ...args)
625 detail::_SubstrWriter writer(errmsg);
626 auto dumpfn = [&writer](csubstr s){ writer.append(s); };
627 _dump(dumpfn, fmt, args...);
630 callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);
631 C4_UNREACHABLE_AFTER_ERR();
636 inline csubstr _c4prc(
const char &C4_RESTRICT c)
640 case '\n':
return csubstr(
"\\n");
641 case '\t':
return csubstr(
"\\t");
642 case '\0':
return csubstr(
"\\0");
643 case '\r':
return csubstr(
"\\r");
644 case '\f':
return csubstr(
"\\f");
645 case '\b':
return csubstr(
"\\b");
646 case '\v':
return csubstr(
"\\v");
647 case '\a':
return csubstr(
"\\a");
648 default:
return csubstr(&c, 1);
654 C4_SUPPRESS_WARNING_GCC_POP
Lightweight generic type-safe wrappers for converting individual values to/from strings.
#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
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)