rapidyaml  0.10.0
parse and emit YAML, and do it fast
common.hpp
Go to the documentation of this file.
1 #ifndef _C4_YML_COMMON_HPP_
2 #define _C4_YML_COMMON_HPP_
3 
4 /** @file common.hpp Common utilities and infrastructure used by ryml. */
5 
6 #include <cstddef>
7 #include <c4/substr.hpp>
8 #include <c4/charconv.hpp>
9 #include <c4/dump.hpp>
10 #include <c4/yml/export.hpp>
11 
12 #if defined(C4_MSVC) || defined(C4_MINGW)
13 #include <malloc.h>
14 #else
15 #include <alloca.h>
16 #endif
17 
18 
19 
20 //-----------------------------------------------------------------------------
21 
22 #ifndef RYML_ERRMSG_SIZE
23 /// size for the error message buffer
24 #define RYML_ERRMSG_SIZE (1024)
25 #endif
26 
27 #ifndef RYML_LOGBUF_SIZE
28 /// size for the buffer used to format individual values to string
29 /// while preparing an error message. This is only used for formatting
30 /// individual values in the message; final messages will be larger
31 /// than this value (see @ref RYML_ERRMSG_SIZE). This is also used for
32 /// the detailed debug log messages when RYML_DBG is defined.
33 #define RYML_LOGBUF_SIZE (256)
34 #endif
35 
36 #ifndef RYML_LOGBUF_SIZE_MAX
37 /// size for the fallback larger log buffer. When @ref
38 /// RYML_LOGBUF_SIZE is not large enough to convert a value to string,
39 /// then temporary stack memory is allocated up to
40 /// RYML_LOGBUF_SIZE_MAX. This limit is in place to prevent a stack
41 /// overflow. If the printed value requires more than
42 /// RYML_LOGBUF_SIZE_MAX, the value is silently skipped.
43 #define RYML_LOGBUF_SIZE_MAX (1024)
44 #endif
45 
46 #ifndef RYML_LOCATIONS_SMALL_THRESHOLD
47 /// threshold at which a location search will revert from linear to
48 /// binary search.
49 #define RYML_LOCATIONS_SMALL_THRESHOLD (30)
50 #endif
51 
52 
53 //-----------------------------------------------------------------------------
54 // Specify groups to have a predefined topic order in doxygen:
55 
56 /** @defgroup doc_quickstart Quickstart
57  *
58  * Example code for every feature.
59  */
60 
61 /** @defgroup doc_parse Parse utilities
62  * @see sample::sample_parse_in_place
63  * @see sample::sample_parse_in_arena
64  * @see sample::sample_parse_file
65  * @see sample::sample_parse_reuse_tree
66  * @see sample::sample_parse_reuse_parser
67  * @see sample::sample_parse_reuse_tree_and_parser
68  * @see sample::sample_location_tracking
69  */
70 
71 /** @defgroup doc_emit Emit utilities
72  *
73  * Utilities to emit YAML and JSON, either to a memory buffer or to a
74  * file or ostream-like class.
75  *
76  * @see sample::sample_emit_to_container
77  * @see sample::sample_emit_to_stream
78  * @see sample::sample_emit_to_file
79  * @see sample::sample_emit_nested_node
80  * @see sample::sample_emit_style
81  */
82 
83 /** @defgroup doc_node_type Node types
84  */
85 
86 /** @defgroup doc_tree Tree utilities
87  * @see sample::sample_quick_overview
88  * @see sample::sample_iterate_trees
89  * @see sample::sample_create_trees
90  * @see sample::sample_tree_arena
91  *
92  * @see sample::sample_static_trees
93  * @see sample::sample_location_tracking
94  *
95  * @see sample::sample_docs
96  * @see sample::sample_anchors_and_aliases
97  * @see sample::sample_tags
98  */
99 
100 /** @defgroup doc_node_classes Node classes
101  *
102  * High-level node classes.
103  *
104  * @see sample::sample_quick_overview
105  * @see sample::sample_iterate_trees
106  * @see sample::sample_create_trees
107  * @see sample::sample_tree_arena
108  */
109 
110 /** @defgroup doc_callbacks Callbacks for errors and allocation
111  *
112  * Functions called by ryml to allocate/free memory and to report
113  * errors.
114  *
115  * @see sample::sample_error_handler
116  * @see sample::sample_global_allocator
117  * @see sample::sample_per_tree_allocator
118  */
119 
120 /** @defgroup doc_serialization Serialization/deserialization
121  *
122  * Contains information on how to serialize and deserialize
123  * fundamental types, user scalar types, user container types and
124  * interop with std scalar/container types.
125  *
126  */
127 
128 /** @defgroup doc_ref_utils Anchor/Reference utilities
129  *
130  * @see sample::sample_anchors_and_aliases
131  * */
132 
133 /** @defgroup doc_tag_utils Tag utilities
134  * @see sample::sample_tags
135  */
136 
137 /** @defgroup doc_preprocessors Preprocessors
138  *
139  * Functions for preprocessing YAML prior to parsing.
140  */
141 
142 
143 //-----------------------------------------------------------------------------
144 
145 // document macros for doxygen
146 #ifdef __DOXYGEN__ // defined in Doxyfile::PREDEFINED
147 
148 /** define this macro with a boolean value to enable/disable
149  * assertions to check preconditions and assumptions throughout the
150  * codebase; this causes a slowdown of the code, and larger code
151  * size. By default, this macro is defined unless NDEBUG is defined
152  * (see C4_USE_ASSERT); as a result, by default this macro is truthy
153  * only in debug builds. */
154 # define RYML_USE_ASSERT
155 
156 /** (Undefined by default) Define this macro to disable ryml's default
157  * implementation of the callback functions; see @ref c4::yml::Callbacks */
158 # define RYML_NO_DEFAULT_CALLBACKS
159 
160 /** (Undefined by default) When this macro is defined (and
161  * @ref RYML_NO_DEFAULT_CALLBACKS is not defined), the default error
162  * handler will throw C++ exceptions of type `std::runtime_error`. */
163 # define RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
164 
165 /** Conditionally expands to `noexcept` when @ref RYML_USE_ASSERT is 0 and
166  * is empty otherwise. The user is unable to override this macro. */
167 # define RYML_NOEXCEPT
168 
169 #endif
170 
171 
172 //-----------------------------------------------------------------------------
173 
174 
175 /** @cond dev*/
176 #ifndef RYML_USE_ASSERT
177 # define RYML_USE_ASSERT C4_USE_ASSERT
178 #endif
179 
180 #if RYML_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
186 #else
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
192 #endif
193 
194 #define RYML_DEPRECATED(msg) C4_DEPRECATED(msg)
195 
196 #define RYML_CHECK(cond) \
197  do { \
198  if(C4_UNLIKELY(!(cond))) \
199  { \
200  RYML_DEBUG_BREAK(); \
201  c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
202  C4_UNREACHABLE_AFTER_ERR(); \
203  } \
204  } while(0)
205 
206 #define RYML_CHECK_MSG(cond, msg) \
207  do \
208  { \
209  if(C4_UNLIKELY(!(cond))) \
210  { \
211  RYML_DEBUG_BREAK(); \
212  c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
213  C4_UNREACHABLE_AFTER_ERR(); \
214  } \
215  } while(0)
216 
217 #if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)
218 # define RYML_DEBUG_BREAK() \
219  do { \
220  if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \
221  { \
222  C4_DEBUG_BREAK(); \
223  } \
224  } while(0)
225 #else
226 # define RYML_DEBUG_BREAK()
227 #endif
228 
229 /** @endcond */
230 
231 
232 //-----------------------------------------------------------------------------
233 //-----------------------------------------------------------------------------
234 //-----------------------------------------------------------------------------
235 
236 namespace c4 {
237 namespace yml {
238 
239 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
240 
241 
242 #ifndef RYML_ID_TYPE
243 /** The type of a node id in the YAML tree. In the future, the default
244  * will likely change to int32_t, which was observed to be faster.
245  * @see id_type */
246 #define RYML_ID_TYPE size_t
247 #endif
248 
249 
250 /** The type of a node id in the YAML tree; to override the default
251  * type, define the macro @ref RYML_ID_TYPE to a suitable integer
252  * type. */
254 static_assert(std::is_integral<id_type>::value, "id_type must be an integer type");
255 
256 
257 C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
258 enum : id_type {
259  /** an index to none */
260  NONE = id_type(-1),
261 };
262 C4_SUPPRESS_WARNING_GCC_CLANG_POP
263 
264 
265 enum : size_t {
266  /** a null string position */
267  npos = size_t(-1)
268 };
269 
270 
271 //-----------------------------------------------------------------------------
272 //-----------------------------------------------------------------------------
273 //-----------------------------------------------------------------------------
274 
275 //! holds a position into a source buffer
277 {
278  //! number of bytes from the beginning of the source buffer
279  size_t offset;
280  //! line
281  size_t line;
282  //! column
283  size_t col;
284 
285  LineCol() = default;
286  //! construct from line and column
287  LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {}
288  //! construct from offset, line and column
289  LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {}
290 };
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");
294 
295 
296 //! a source file position
298 {
299  //! number of bytes from the beginning of the source buffer
300  size_t offset;
301  //! line
302  size_t line;
303  //! column
304  size_t col;
305  //! file name
306  csubstr name;
307 
308  operator bool () const { return !name.empty() || line != 0 || offset != 0 || col != 0; }
309  operator LineCol const& () const { return reinterpret_cast<LineCol const&>(*this); } // NOLINT
310 
311  Location() = default;
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) {}
316  Location(const char *n, size_t l, size_t c) : offset( ), line(l), col(c), name(to_csubstr(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)) {}
318 };
319 static_assert(std::is_standard_layout<Location>::value, "Location not trivial");
320 
321 
322 //-----------------------------------------------------------------------------
323 
324 /** @addtogroup doc_callbacks
325  *
326  * @{ */
327 
328 struct Callbacks;
329 
330 
331 /** set the global callbacks for the library; after a call to this
332  * function, these callbacks will be used by newly created objects
333  * (unless they are copying older objects with different
334  * callbacks). If @ref RYML_NO_DEFAULT_CALLBACKS is defined, it is
335  * mandatory to call this function prior to using any other library
336  * facility.
337  *
338  * @warning This function is NOT thread-safe.
339  *
340  * @warning the error callback must never return: see @ref pfn_error
341  * for more details */
342 RYML_EXPORT void set_callbacks(Callbacks const& c);
343 
344 /** get the global callbacks
345  * @warning This function is not thread-safe. */
346 RYML_EXPORT Callbacks const& get_callbacks();
347 
348 /** set the global callbacks back to their defaults ()
349  * @warning This function is not thread-safe. */
351 
352 
353 /** the type of the function used to report errors
354  *
355  * @warning When given by the user, this function MUST interrupt
356  * execution, typically by either throwing an exception, or using
357  * `std::longjmp()` ([see
358  * documentation](https://en.cppreference.com/w/cpp/utility/program/setjmp))
359  * or by calling `std::abort()`. If the function returned, the parser
360  * would enter into an infinite loop, or the program may crash. */
361 using pfn_error = void (*) (const char* msg, size_t msg_len, Location location, void *user_data);
362 
363 
364 /** the type of the function used to allocate memory; ryml will only
365  * allocate memory through this callback. */
366 using pfn_allocate = void* (*)(size_t len, void* hint, void *user_data);
367 
368 
369 /** the type of the function used to free memory; ryml will only free
370  * memory through this callback. */
371 using pfn_free = void (*)(void* mem, size_t size, void *user_data);
372 
373 
374 /** a c-style callbacks class. Can be used globally by the library
375  * and/or locally by @ref Tree and @ref Parser objects. */
377 {
378  void * m_user_data;
382 
383  /** Construct an object with the default callbacks. If
384  * @ref RYML_NO_DEFAULT_CALLBACKS is defined, the object will have null
385  * members.*/
386  Callbacks() noexcept;
387 
388  /** Construct an object with the given callbacks.
389  *
390  * @param user_data Data to be forwarded in every call to a callback.
391  *
392  * @param alloc A pointer to an allocate function. Unless
393  * @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
394  * parameter is null, will fall back to ryml's default
395  * alloc implementation.
396  *
397  * @param free A pointer to a free function. Unless
398  * @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
399  * parameter is null, will fall back to ryml's default free
400  * implementation.
401  *
402  * @param error A pointer to an error function, which must never
403  * return (see @ref pfn_error). Unless
404  * @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
405  * parameter is null, will fall back to ryml's default
406  * error implementation.
407  */
408  Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error);
409 
410  bool operator!= (Callbacks const& that) const { return !operator==(that); }
411  bool operator== (Callbacks const& that) const
412  {
413  return (m_user_data == that.m_user_data &&
414  m_allocate == that.m_allocate &&
415  m_free == that.m_free &&
416  m_error == that.m_error);
417  }
418 };
419 
420 
421 /** @} */
422 
423 
424 //-----------------------------------------------------------------------------
425 //-----------------------------------------------------------------------------
426 //-----------------------------------------------------------------------------
427 
428 typedef enum {
435 } Encoding_e;
436 
437 
438 //-----------------------------------------------------------------------------
439 //-----------------------------------------------------------------------------
440 //-----------------------------------------------------------------------------
441 
442 /// @cond dev
443 
444 // BEWARE! MSVC requires that [[noreturn]] appears before RYML_EXPORT
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);
447 
448 [[noreturn]] inline void error(const char *msg, size_t msg_len)
449 {
450  error(msg, msg_len, Location{});
451 }
452 template<size_t N>
453 [[noreturn]] inline void error(const char (&msg)[N], Location loc)
454 {
455  error(msg, N-1, loc);
456 }
457 template<size_t N>
458 [[noreturn]] inline void error(const char (&msg)[N])
459 {
460  error(msg, N-1, Location{});
461 }
462 
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) \
468 do \
469 { \
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(); \
474 } while(0)
475 #define _RYML_CB_CHECK_(cb, cond, loc) \
476  do \
477  { \
478  if(C4_UNLIKELY(!(cond))) \
479  { \
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(); \
484  } \
485  } while(0)
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) \
489  do { \
490  (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
491  (buf) = nullptr; \
492  } while(0)
493 
494 
495 //-----------------------------------------------------------------------------
496 //-----------------------------------------------------------------------------
497 //-----------------------------------------------------------------------------
498 
499 typedef enum {
500  BLOCK_LITERAL, //!< keep newlines (|)
501  BLOCK_FOLD //!< replace newline with single space (>)
502 } BlockStyle_e;
503 
504 typedef enum {
505  CHOMP_CLIP, //!< single newline at end (default)
506  CHOMP_STRIP, //!< no newline at end (-)
507  CHOMP_KEEP //!< all newlines from end (+)
508 } BlockChomp_e;
509 
510 
511 /** Abstracts the fact that a scalar filter result may not fit in the
512  * intended memory. */
513 struct FilterResult
514 {
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; }
518  csubstr str;
519 };
520 /** Abstracts the fact that a scalar filter result may not fit in the
521  * intended memory. */
522 struct FilterResultExtending
523 {
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; }
527  csubstr str;
528  size_t reqlen;
529 };
530 
531 
532 //-----------------------------------------------------------------------------
533 //-----------------------------------------------------------------------------
534 //-----------------------------------------------------------------------------
535 
536 
537 namespace detail {
538 // is there a better way to do this?
539 template<int8_t signedval, uint8_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
544 {};
545 #define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
546 } // namespace detail
547 
548 
549 namespace detail {
550 struct _SubstrWriter
551 {
552  substr buf;
553  size_t pos;
554  _SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }
555  void append(csubstr s)
556  {
557  C4_ASSERT(!s.overlaps(buf));
558  C4_ASSERT(s.str || !s.len);
559  if(s.len && pos + s.len <= buf.len)
560  {
561  C4_ASSERT(s.str);
562  memcpy(buf.str + pos, s.str, s.len);
563  }
564  pos += s.len;
565  }
566  void append(char c)
567  {
568  C4_ASSERT(buf.str);
569  if(pos < buf.len)
570  buf.str[pos] = c;
571  ++pos;
572  }
573  void append_n(char c, size_t numtimes)
574  {
575  C4_ASSERT(buf.str);
576  if(numtimes && pos + numtimes < buf.len)
577  memset(buf.str + pos, c, numtimes);
578  pos += numtimes;
579  }
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; }
582  //! get the part written so far
583  csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; }
584  //! get the part that is still free to write to (the remainder)
585  substr rem() const { return pos < buf.len ? buf.sub(pos) : buf.last(0); }
586 
587  size_t advance(size_t more) { pos += more; return pos; }
588 };
589 } // namespace detail
590 
591 
592 namespace detail {
593 // dumpfn is a function abstracting prints to terminal (or to string).
594 template<class DumpFn, class ...Args>
595 C4_NO_INLINE void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)
596 {
597  DumpResults results;
598  // try writing everything:
599  {
600  // buffer for converting individual arguments. it is defined
601  // in a child scope to free it in case the buffer is too small
602  // for any of the arguments.
603  char writebuf[RYML_LOGBUF_SIZE];
604  results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);
605  }
606  // if any of the arguments failed to fit the buffer, allocate a
607  // larger buffer (up to a limit) and resume writing.
608  //
609  // results.bufsize is set to the size of the largest element
610  // serialized. Eg int(1) will require 1 byte.
611  if(C4_UNLIKELY(results.bufsize > RYML_LOGBUF_SIZE))
612  {
613  const size_t bufsize = results.bufsize <= RYML_LOGBUF_SIZE_MAX ? results.bufsize : RYML_LOGBUF_SIZE_MAX;
614  #ifdef C4_MSVC
615  substr largerbuf = {static_cast<char*>(_alloca(bufsize)), bufsize};
616  #else
617  substr largerbuf = {static_cast<char*>(alloca(bufsize)), bufsize};
618  #endif
619  results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);
620  }
621 }
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)
624 {
625  char errmsg[RYML_ERRMSG_SIZE] = {0};
626  detail::_SubstrWriter writer(errmsg);
627  auto dumpfn = [&writer](csubstr s){ writer.append(s); };
628  _dump(dumpfn, fmt, args...);
629  writer.append('\n');
630  const size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE;
631  callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);
632  C4_UNREACHABLE_AFTER_ERR();
633 }
634 } // namespace detail
635 
636 
637 inline csubstr _c4prc(const char &C4_RESTRICT c) // pass by reference!
638 {
639  switch(c)
640  {
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);
650  }
651 }
652 
653 /// @endcond
654 
655 C4_SUPPRESS_WARNING_GCC_POP
656 
657 } // namespace yml
658 } // namespace c4
659 
660 #endif /* _C4_YML_COMMON_HPP_ */
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.
Definition: common.hpp:246
#define RYML_ERRMSG_SIZE
size for the error message buffer
Definition: common.hpp:24
#define RYML_LOGBUF_SIZE
size for the buffer used to format individual values to string while preparing an error message....
Definition: common.hpp:33
#define RYML_LOGBUF_SIZE_MAX
size for the fallback larger log buffer. When RYML_LOGBUF_SIZE is not large enough to convert a value...
Definition: common.hpp:43
#define RYML_EXPORT
Definition: export.hpp:15
void reset_callbacks()
set the global callbacks back to their defaults ()
Definition: common.cpp:123
void(*)(const char *msg, size_t msg_len, Location location, void *user_data) pfn_error
the type of the function used to report errors
Definition: common.hpp:361
void set_callbacks(Callbacks const &c)
set the global callbacks for the library; after a call to this function, these callbacks will be used...
Definition: common.cpp:113
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...
Definition: common.hpp:366
Callbacks const & get_callbacks()
get the global callbacks
Definition: common.cpp:118
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.
Definition: common.hpp:371
csubstr to_csubstr(substr s) noexcept
neutral version for use in generic code
Definition: substr.hpp:2186
bool operator==(const char(&s)[N], basic_substring< C > const that) noexcept
Definition: substr.hpp:2223
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...
Definition: common.hpp:253
@ npos
a null string position
Definition: common.hpp:267
void error(Callbacks const &cb, const char *msg, size_t msg_len, Location loc)
Definition: common.cpp:130
Encoding_e
Definition: common.hpp:428
@ UTF16BE
Definition: common.hpp:432
@ UTF8
Definition: common.hpp:430
@ UTF16LE
Definition: common.hpp:431
@ NOBOM
Definition: common.hpp:429
@ UTF32BE
Definition: common.hpp:434
@ UTF32LE
Definition: common.hpp:433
@ NONE
an index to none
Definition: common.hpp:260
Definition: common.cpp:12
a c-style callbacks class.
Definition: common.hpp:377
void * m_user_data
Definition: common.hpp:378
pfn_allocate m_allocate
Definition: common.hpp:379
pfn_free m_free
Definition: common.hpp:380
pfn_error m_error
Definition: common.hpp:381
holds a position into a source buffer
Definition: common.hpp:277
size_t line
line
Definition: common.hpp:281
LineCol(size_t o, size_t l, size_t c)
construct from offset, line and column
Definition: common.hpp:289
size_t offset
number of bytes from the beginning of the source buffer
Definition: common.hpp:279
LineCol(size_t l, size_t c)
construct from line and column
Definition: common.hpp:287
LineCol()=default
size_t col
column
Definition: common.hpp:283
a source file position
Definition: common.hpp:298
Location(csubstr n, size_t b, size_t l, size_t c)
Definition: common.hpp:315
size_t col
column
Definition: common.hpp:304
Location()=default
size_t line
line
Definition: common.hpp:302
Location(const char *n, size_t l, size_t c)
Definition: common.hpp:316
size_t offset
number of bytes from the beginning of the source buffer
Definition: common.hpp:300
Location(size_t l, size_t c)
Definition: common.hpp:312
Location(csubstr n, size_t l, size_t c)
Definition: common.hpp:314
csubstr name
file name
Definition: common.hpp:306
Location(const char *n, size_t b, size_t l, size_t c)
Definition: common.hpp:317
Location(size_t b, size_t l, size_t c)
Definition: common.hpp:313
read+write string views