rapidyaml  0.9.0
parse and emit YAML, and do it fast
common.cpp
Go to the documentation of this file.
1 #include "c4/yml/common.hpp"
2 
3 #ifndef RYML_NO_DEFAULT_CALLBACKS
4 # include <stdlib.h>
5 # include <stdio.h>
6 # ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
7 # include <stdexcept>
8 # endif
9 #endif // RYML_NO_DEFAULT_CALLBACKS
10 
11 
12 namespace c4 {
13 namespace yml {
14 
15 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
16 C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702/*unreachable code*/) // on the call to the unreachable macro
17 
18 namespace {
19 Callbacks s_default_callbacks;
20 } // anon namespace
21 
22 #ifndef RYML_NO_DEFAULT_CALLBACKS
23 void report_error_impl(const char* msg, size_t length, Location loc, FILE *f)
24 {
25  if(!f)
26  f = stderr;
27  if(loc)
28  {
29  if(!loc.name.empty())
30  {
31  // this is more portable than using fprintf("%.*s:") which
32  // is not available in some embedded platforms
33  fwrite(loc.name.str, 1, loc.name.len, f); // NOLINT
34  fputc(':', f); // NOLINT
35  }
36  fprintf(f, "%zu:", loc.line); // NOLINT
37  if(loc.col)
38  fprintf(f, "%zu:", loc.col); // NOLINT
39  if(loc.offset)
40  fprintf(f, " (%zuB):", loc.offset); // NOLINT
41  fputc(' ', f); // NOLINT
42  }
43  RYML_ASSERT(!csubstr(msg, length).ends_with('\0'));
44  fwrite(msg, 1, length, f); // NOLINT
45  fputc('\n', f); // NOLINT
46  fflush(f); // NOLINT
47 }
48 
49 [[noreturn]] void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
50 {
51  RYML_ASSERT(!csubstr(msg, length).ends_with('\0'));
52  report_error_impl(msg, length, loc, nullptr);
53 #ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
54  throw std::runtime_error(std::string(msg, length));
55 #else
56  ::abort();
57 #endif
58 }
59 
60 void* allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/)
61 {
62  void *mem = ::malloc(length);
63  if(mem == nullptr)
64  {
65  const char msg[] = "could not allocate memory";
66  error_impl(msg, sizeof(msg)-1, {}, nullptr);
67  }
68  return mem;
69 }
70 
71 void free_impl(void *mem, size_t /*length*/, void * /*user_data*/)
72 {
73  ::free(mem);
74 }
75 #endif // RYML_NO_DEFAULT_CALLBACKS
76 
77 
78 
80  :
81  m_user_data(nullptr),
82  #ifndef RYML_NO_DEFAULT_CALLBACKS
83  m_allocate(allocate_impl),
84  m_free(free_impl),
85  m_error(error_impl)
86  #else
87  m_allocate(nullptr),
88  m_free(nullptr),
89  m_error(nullptr)
90  #endif
91 {
92 }
93 
94 Callbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_error error_)
95  :
96  m_user_data(user_data),
98  m_allocate(alloc_ ? alloc_ : allocate_impl),
99  m_free(free_ ? free_ : free_impl),
100  m_error((error_ ? error_ : error_impl))
101  #else
102  m_allocate(alloc_),
103  m_free(free_),
104  m_error(error_)
105  #endif
106 {
107  RYML_CHECK(m_allocate);
108  RYML_CHECK(m_free);
109  RYML_CHECK(m_error);
110 }
111 
112 
113 void set_callbacks(Callbacks const& c)
114 {
115  s_default_callbacks = c;
116 }
117 
119 {
120  return s_default_callbacks;
121 }
122 
124 {
126 }
127 
128 // the [[noreturn]] attribute needs to be here as well (UB otherwise)
129 // https://en.cppreference.com/w/cpp/language/attributes/noreturn
130 [[noreturn]] void error(Callbacks const& cb, const char *msg, size_t msg_len, Location loc)
131 {
132  cb.m_error(msg, msg_len, loc, cb.m_user_data);
133  abort(); // call abort in case the error callback didn't interrupt execution
134  C4_UNREACHABLE();
135 }
136 
137 // the [[noreturn]] attribute needs to be here as well (UB otherwise)
138 // see https://en.cppreference.com/w/cpp/language/attributes/noreturn
139 [[noreturn]] void error(const char *msg, size_t msg_len, Location loc)
140 {
141  error(s_default_callbacks, msg, msg_len, loc);
142  C4_UNREACHABLE();
143 }
144 
145 C4_SUPPRESS_WARNING_MSVC_POP
146 C4_SUPPRESS_WARNING_GCC_CLANG_POP
147 
148 } // namespace yml
149 } // namespace c4
Common utilities and infrastructure used by ryml.
#define RYML_NO_DEFAULT_CALLBACKS
(Undefined by default) Define this macro to disable ryml's default implementation of the callback fun...
Definition: common.hpp:158
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:360
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:365
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:370
void free_impl(void *mem, size_t, void *)
Definition: common.cpp:71
void error(Callbacks const &cb, const char *msg, size_t msg_len, Location loc)
Definition: common.cpp:130
void error_impl(const char *msg, size_t length, Location loc, void *)
Definition: common.cpp:49
void * allocate_impl(size_t length, void *, void *)
Definition: common.cpp:60
void report_error_impl(const char *msg, size_t length, Location loc, FILE *f)
Definition: common.cpp:23
Definition: common.cpp:12
a c-style callbacks class.
Definition: common.hpp:376
void * m_user_data
Definition: common.hpp:377
pfn_allocate m_allocate
Definition: common.hpp:378
Callbacks() noexcept
Construct an object with the default callbacks.
Definition: common.cpp:79
pfn_free m_free
Definition: common.hpp:379
pfn_error m_error
Definition: common.hpp:380
a source file position
Definition: common.hpp:297
size_t col
column
Definition: common.hpp:303
size_t line
line
Definition: common.hpp:301
size_t offset
number of bytes from the beginning of the source buffer
Definition: common.hpp:299
csubstr name
file name
Definition: common.hpp:305