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_trivially_copyable<LineCol>::value,
"LineCol not trivially copyable");
292 static_assert(std::is_trivially_default_constructible<LineCol>::value,
"LineCol not trivially default constructible");
293 static_assert(std::is_standard_layout<LineCol>::value,
"Location not trivial");
308 operator bool ()
const {
return !name.empty() || line != 0 || offset != 0 || col != 0; }
309 operator LineCol const& ()
const {
return reinterpret_cast<LineCol const&
>(*this); }
312 Location(
size_t l,
size_t c) : offset( ), line(l), col(c), name( ) {}
313 Location(
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name( ) {}
314 Location( csubstr n,
size_t l,
size_t c) : offset( ), line(l), col(c), name(n) {}
315 Location( csubstr n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(n) {}
317 Location(
const char *n,
size_t b,
size_t l,
size_t c) : offset(b), line(l), col(c), name(
to_csubstr(n)) {}
319 static_assert(std::is_standard_layout<Location>::value,
"Location not trivial");
361 using pfn_error = void (*) (
const char* msg,
size_t msg_len,
Location location,
void *user_data);
366 using pfn_allocate =
void* (*)(
size_t len,
void* hint,
void *user_data);
371 using pfn_free = void (*)(
void* mem,
size_t size,
void *user_data);
445 [[noreturn]]
RYML_EXPORT void error(Callbacks
const& cb,
const char *msg,
size_t msg_len, Location loc);
446 [[noreturn]]
RYML_EXPORT void error(
const char *msg,
size_t msg_len, Location loc);
448 [[noreturn]]
inline void error(
const char *msg,
size_t msg_len)
450 error(msg, msg_len, Location{});
453 [[noreturn]]
inline void error(
const char (&msg)[N], Location loc)
455 error(msg, N-1, loc);
458 [[noreturn]]
inline void error(
const char (&msg)[N])
460 error(msg, N-1, Location{});
463 #define _RYML_CB_ERR(cb, msg_literal) \
464 _RYML_CB_ERR_(cb, msg_literal, c4::yml::Location(__FILE__, 0, __LINE__, 0))
465 #define _RYML_CB_CHECK(cb, cond) \
466 _RYML_CB_CHECK_(cb, cond, c4::yml::Location(__FILE__, 0, __LINE__, 0))
467 #define _RYML_CB_ERR_(cb, msg_literal, loc) \
470 const char msg[] = msg_literal; \
471 RYML_DEBUG_BREAK(); \
472 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
473 C4_UNREACHABLE_AFTER_ERR(); \
475 #define _RYML_CB_CHECK_(cb, cond, loc) \
478 if(C4_UNLIKELY(!(cond))) \
480 const char msg[] = "check failed: " #cond; \
481 RYML_DEBUG_BREAK(); \
482 c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
483 C4_UNREACHABLE_AFTER_ERR(); \
486 #define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)
487 #define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), T, (num), nullptr)
488 #define _RYML_CB_FREE(cb, buf, T, num) \
490 (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
515 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
516 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return str.len; }
517 C4_ALWAYS_INLINE csubstr get()
const { RYML_ASSERT(valid());
return str; }
522 struct FilterResultExtending
524 C4_ALWAYS_INLINE
bool valid() const noexcept {
return str.str !=
nullptr; }
525 C4_ALWAYS_INLINE
size_t required_len() const noexcept {
return reqlen; }
526 C4_ALWAYS_INLINE csubstr get()
const { RYML_ASSERT(valid());
return str; }
539 template<
int8_t
signedval, u
int8_t
unsignedval>
540 struct _charconstant_t
541 :
public std::conditional<std::is_signed<char>::value,
542 std::integral_constant<int8_t, static_cast<int8_t>(unsignedval)>,
543 std::integral_constant<uint8_t, unsignedval>>::type
545 #define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
554 _SubstrWriter(substr buf_,
size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }
555 void append(csubstr s)
557 C4_ASSERT(!s.overlaps(buf));
558 C4_ASSERT(s.str || !s.len);
559 if(s.len && pos + s.len <= buf.len)
562 memcpy(buf.str + pos, s.str, s.len);
573 void append_n(
char c,
size_t numtimes)
576 if(numtimes && pos + numtimes < buf.len)
577 memset(buf.str + pos, c, numtimes);
580 size_t slack()
const {
return pos <= buf.len ? buf.len - pos : 0; }
581 size_t excess()
const {
return pos > buf.len ? pos - buf.len : 0; }
583 csubstr curr()
const {
return pos <= buf.len ? buf.first(pos) : buf; }
585 substr rem()
const {
return pos < buf.len ? buf.sub(pos) : buf.last(0); }
587 size_t advance(
size_t more) { pos += more;
return pos; }
594 template<
class DumpFn,
class ...Args>
595 C4_NO_INLINE
void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)
604 results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);
615 substr largerbuf = {
static_cast<char*
>(_alloca(bufsize)), bufsize};
617 substr largerbuf = {
static_cast<char*
>(alloca(bufsize)), bufsize};
619 results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);
622 template<
class ...Args>
623 C4_NORETURN C4_NO_INLINE
void _report_err(Callbacks
const& C4_RESTRICT callbacks, csubstr fmt, Args
const& C4_RESTRICT ...args)
626 detail::_SubstrWriter writer(errmsg);
627 auto dumpfn = [&writer](csubstr s){ writer.append(s); };
628 _dump(dumpfn, fmt, args...);
631 callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);
632 C4_UNREACHABLE_AFTER_ERR();
637 inline csubstr _c4prc(
const char &C4_RESTRICT c)
641 case '\n':
return csubstr(
"\\n");
642 case '\t':
return csubstr(
"\\t");
643 case '\0':
return csubstr(
"\\0");
644 case '\r':
return csubstr(
"\\r");
645 case '\f':
return csubstr(
"\\f");
646 case '\b':
return csubstr(
"\\b");
647 case '\v':
return csubstr(
"\\v");
648 case '\a':
return csubstr(
"\\a");
649 default:
return csubstr(&c, 1);
655 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)