Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/rapidyaml/include/c4/yml/common.hpp
4264 views
1
#ifndef _C4_YML_COMMON_HPP_
2
#define _C4_YML_COMMON_HPP_
3
4
#include <cstddef>
5
#include <c4/substr.hpp>
6
#include <c4/yml/export.hpp>
7
8
9
#ifndef RYML_USE_ASSERT
10
# define RYML_USE_ASSERT C4_USE_ASSERT
11
#endif
12
13
14
#if RYML_USE_ASSERT
15
# define RYML_ASSERT(cond) RYML_CHECK(cond)
16
# define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)
17
#else
18
# define RYML_ASSERT(cond)
19
# define RYML_ASSERT_MSG(cond, msg)
20
#endif
21
22
23
#if defined(NDEBUG) || defined(C4_NO_DEBUG_BREAK)
24
# define RYML_DEBUG_BREAK()
25
#else
26
# define RYML_DEBUG_BREAK() \
27
{ \
28
if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \
29
{ \
30
C4_DEBUG_BREAK(); \
31
} \
32
}
33
#endif
34
35
36
#define RYML_CHECK(cond) \
37
do { \
38
if(!(cond)) \
39
{ \
40
RYML_DEBUG_BREAK() \
41
c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
42
} \
43
} while(0)
44
45
#define RYML_CHECK_MSG(cond, msg) \
46
do \
47
{ \
48
if(!(cond)) \
49
{ \
50
RYML_DEBUG_BREAK() \
51
c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
52
} \
53
} while(0)
54
55
56
#if C4_CPP >= 14
57
# define RYML_DEPRECATED(msg) [[deprecated(msg)]]
58
#else
59
# if defined(_MSC_VER)
60
# define RYML_DEPRECATED(msg) __declspec(deprecated(msg))
61
# else // defined(__GNUC__) || defined(__clang__)
62
# define RYML_DEPRECATED(msg) __attribute__((deprecated(msg)))
63
# endif
64
#endif
65
66
67
//-----------------------------------------------------------------------------
68
//-----------------------------------------------------------------------------
69
//-----------------------------------------------------------------------------
70
71
namespace c4 {
72
namespace yml {
73
74
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
75
76
enum : size_t {
77
/** a null position */
78
npos = size_t(-1),
79
/** an index to none */
80
NONE = size_t(-1)
81
};
82
83
84
//-----------------------------------------------------------------------------
85
//-----------------------------------------------------------------------------
86
//-----------------------------------------------------------------------------
87
88
//! holds a position into a source buffer
89
struct RYML_EXPORT LineCol
90
{
91
//! number of bytes from the beginning of the source buffer
92
size_t offset;
93
//! line
94
size_t line;
95
//! column
96
size_t col;
97
98
LineCol() : offset(), line(), col() {}
99
//! construct from line and column
100
LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {}
101
//! construct from offset, line and column
102
LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {}
103
};
104
105
106
//! a source file position
107
struct RYML_EXPORT Location : public LineCol
108
{
109
csubstr name;
110
111
operator bool () const { return !name.empty() || line != 0 || offset != 0; }
112
113
Location() : LineCol(), name() {}
114
Location( size_t l, size_t c) : LineCol{ l, c}, name( ) {}
115
Location( csubstr n, size_t l, size_t c) : LineCol{ l, c}, name(n) {}
116
Location( csubstr n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(n) {}
117
Location(const char *n, size_t l, size_t c) : LineCol{ l, c}, name(to_csubstr(n)) {}
118
Location(const char *n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(to_csubstr(n)) {}
119
};
120
121
122
//-----------------------------------------------------------------------------
123
124
/** the type of the function used to report errors. This function must
125
* interrupt execution, either by raising an exception or calling
126
* std::abort().
127
*
128
* @warning the error callback must never return: it must either abort
129
* or throw an exception. Otherwise, the parser will enter into an
130
* infinite loop, or the program may crash. */
131
using pfn_error = void (*)(const char* msg, size_t msg_len, Location location, void *user_data);
132
/** the type of the function used to allocate memory */
133
using pfn_allocate = void* (*)(size_t len, void* hint, void *user_data);
134
/** the type of the function used to free memory */
135
using pfn_free = void (*)(void* mem, size_t size, void *user_data);
136
137
/** trigger an error: call the current error callback. */
138
RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc);
139
/** @overload error */
140
inline void error(const char *msg, size_t msg_len)
141
{
142
error(msg, msg_len, Location{});
143
}
144
/** @overload error */
145
template<size_t N>
146
inline void error(const char (&msg)[N], Location loc)
147
{
148
error(msg, N-1, loc);
149
}
150
/** @overload error */
151
template<size_t N>
152
inline void error(const char (&msg)[N])
153
{
154
error(msg, N-1, Location{});
155
}
156
157
//-----------------------------------------------------------------------------
158
159
/** a c-style callbacks class
160
*
161
* @warning the error callback must never return: it must either abort
162
* or throw an exception. Otherwise, the parser will enter into an
163
* infinite loop, or the program may crash. */
164
struct RYML_EXPORT Callbacks
165
{
166
void * m_user_data;
167
pfn_allocate m_allocate;
168
pfn_free m_free;
169
pfn_error m_error;
170
171
Callbacks();
172
Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error_);
173
174
bool operator!= (Callbacks const& that) const { return !operator==(that); }
175
bool operator== (Callbacks const& that) const
176
{
177
return (m_user_data == that.m_user_data &&
178
m_allocate == that.m_allocate &&
179
m_free == that.m_free &&
180
m_error == that.m_error);
181
}
182
};
183
184
/** set the global callbacks.
185
*
186
* @warning the error callback must never return: it must either abort
187
* or throw an exception. Otherwise, the parser will enter into an
188
* infinite loop, or the program may crash. */
189
RYML_EXPORT void set_callbacks(Callbacks const& c);
190
/// get the global callbacks
191
RYML_EXPORT Callbacks const& get_callbacks();
192
/// set the global callbacks back to their defaults
193
RYML_EXPORT void reset_callbacks();
194
195
/// @cond dev
196
#define _RYML_CB_ERR(cb, msg_literal) \
197
do \
198
{ \
199
const char msg[] = msg_literal; \
200
RYML_DEBUG_BREAK() \
201
(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \
202
} while(0)
203
#define _RYML_CB_CHECK(cb, cond) \
204
do \
205
{ \
206
if(!(cond)) \
207
{ \
208
const char msg[] = "check failed: " #cond; \
209
RYML_DEBUG_BREAK() \
210
(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \
211
} \
212
} while(0)
213
#ifdef RYML_USE_ASSERT
214
#define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))
215
#else
216
#define _RYML_CB_ASSERT(cb, cond) do {} while(0)
217
#endif
218
#define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)
219
#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), (T), (num), nullptr)
220
#define _RYML_CB_FREE(cb, buf, T, num) \
221
do { \
222
(cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
223
(buf) = nullptr; \
224
} while(0)
225
226
227
228
namespace detail {
229
template<int8_t signedval, uint8_t unsignedval>
230
struct _charconstant_t
231
: public std::conditional<std::is_signed<char>::value,
232
std::integral_constant<int8_t, signedval>,
233
std::integral_constant<uint8_t, unsignedval>>::type
234
{};
235
#define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
236
} // namespace detail
237
238
239
namespace detail {
240
struct _SubstrWriter
241
{
242
substr buf;
243
size_t pos;
244
_SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) {}
245
void append(csubstr s)
246
{
247
C4_ASSERT(!s.overlaps(buf));
248
if(pos + s.len <= buf.len)
249
memcpy(buf.str + pos, s.str, s.len);
250
pos += s.len;
251
}
252
void append(char c)
253
{
254
if(pos < buf.len)
255
buf.str[pos] = c;
256
++pos;
257
}
258
void append_n(char c, size_t numtimes)
259
{
260
if(pos + numtimes < buf.len)
261
memset(buf.str + pos, c, numtimes);
262
pos += numtimes;
263
}
264
size_t slack() const { return pos <= buf.len ? buf.len - pos : 0; }
265
size_t excess() const { return pos > buf.len ? pos - buf.len : 0; }
266
//! get the part written so far
267
csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; }
268
//! get the part that is still free to write to (the remainder)
269
substr rem() { return pos < buf.len ? buf.sub(pos) : buf.last(0); }
270
271
size_t advance(size_t more) { pos += more; return pos; }
272
};
273
} // namespace detail
274
275
/// @endcond
276
277
C4_SUPPRESS_WARNING_GCC_CLANG_POP
278
279
} // namespace yml
280
} // namespace c4
281
282
#endif /* _C4_YML_COMMON_HPP_ */
283
284