Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/rapidyaml/include/c4/yml/writer.hpp
4264 views
1
#ifndef _C4_YML_WRITER_HPP_
2
#define _C4_YML_WRITER_HPP_
3
4
#ifndef _C4_YML_COMMON_HPP_
5
#include "./common.hpp"
6
#endif
7
8
#include <c4/substr.hpp>
9
#include <stdio.h> // fwrite(), fputc()
10
#include <string.h> // memcpy()
11
12
13
namespace c4 {
14
namespace yml {
15
16
17
/** Repeat-Character: a character to be written a number of times. */
18
struct RepC
19
{
20
char c;
21
size_t num_times;
22
};
23
inline RepC indent_to(size_t num_levels)
24
{
25
return {' ', size_t(2) * num_levels};
26
}
27
28
29
//-----------------------------------------------------------------------------
30
//-----------------------------------------------------------------------------
31
//-----------------------------------------------------------------------------
32
/** A writer that outputs to a file. Defaults to stdout. */
33
struct WriterFile
34
{
35
FILE * m_file;
36
size_t m_pos;
37
38
WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}
39
40
inline substr _get(bool /*error_on_excess*/)
41
{
42
substr sp;
43
sp.str = nullptr;
44
sp.len = m_pos;
45
return sp;
46
}
47
48
template<size_t N>
49
inline void _do_write(const char (&a)[N])
50
{
51
fwrite(a, sizeof(char), N - 1, m_file);
52
m_pos += N - 1;
53
}
54
55
inline void _do_write(csubstr sp)
56
{
57
#if defined(__clang__)
58
# pragma clang diagnostic push
59
# pragma GCC diagnostic ignored "-Wsign-conversion"
60
#elif defined(__GNUC__)
61
# pragma GCC diagnostic push
62
# pragma GCC diagnostic ignored "-Wsign-conversion"
63
#endif
64
if(sp.empty()) return;
65
fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);
66
m_pos += sp.len;
67
#if defined(__clang__)
68
# pragma clang diagnostic pop
69
#elif defined(__GNUC__)
70
# pragma GCC diagnostic pop
71
#endif
72
}
73
74
inline void _do_write(const char c)
75
{
76
fputc(c, m_file);
77
++m_pos;
78
}
79
80
inline void _do_write(RepC const rc)
81
{
82
for(size_t i = 0; i < rc.num_times; ++i)
83
{
84
fputc(rc.c, m_file);
85
}
86
m_pos += rc.num_times;
87
}
88
};
89
90
91
//-----------------------------------------------------------------------------
92
//-----------------------------------------------------------------------------
93
//-----------------------------------------------------------------------------
94
/** A writer that outputs to an STL-like ostream. */
95
template<class OStream>
96
struct WriterOStream
97
{
98
OStream& m_stream;
99
size_t m_pos;
100
101
WriterOStream(OStream &s) : m_stream(s), m_pos(0) {}
102
103
inline substr _get(bool /*error_on_excess*/)
104
{
105
substr sp;
106
sp.str = nullptr;
107
sp.len = m_pos;
108
return sp;
109
}
110
111
template<size_t N>
112
inline void _do_write(const char (&a)[N])
113
{
114
m_stream.write(a, N - 1);
115
m_pos += N - 1;
116
}
117
118
inline void _do_write(csubstr sp)
119
{
120
#if defined(__clang__)
121
# pragma clang diagnostic push
122
# pragma GCC diagnostic ignored "-Wsign-conversion"
123
#elif defined(__GNUC__)
124
# pragma GCC diagnostic push
125
# pragma GCC diagnostic ignored "-Wsign-conversion"
126
#endif
127
if(sp.empty()) return;
128
m_stream.write(sp.str, sp.len);
129
m_pos += sp.len;
130
#if defined(__clang__)
131
# pragma clang diagnostic pop
132
#elif defined(__GNUC__)
133
# pragma GCC diagnostic pop
134
#endif
135
}
136
137
inline void _do_write(const char c)
138
{
139
m_stream.put(c);
140
++m_pos;
141
}
142
143
inline void _do_write(RepC const rc)
144
{
145
for(size_t i = 0; i < rc.num_times; ++i)
146
{
147
m_stream.put(rc.c);
148
}
149
m_pos += rc.num_times;
150
}
151
};
152
153
154
//-----------------------------------------------------------------------------
155
//-----------------------------------------------------------------------------
156
//-----------------------------------------------------------------------------
157
/** a writer to a substr */
158
struct WriterBuf
159
{
160
substr m_buf;
161
size_t m_pos;
162
163
WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}
164
165
inline substr _get(bool error_on_excess)
166
{
167
if(m_pos <= m_buf.len)
168
{
169
return m_buf.first(m_pos);
170
}
171
if(error_on_excess)
172
{
173
c4::yml::error("not enough space in the given buffer");
174
}
175
substr sp;
176
sp.str = nullptr;
177
sp.len = m_pos;
178
return sp;
179
}
180
181
template<size_t N>
182
inline void _do_write(const char (&a)[N])
183
{
184
RYML_ASSERT( ! m_buf.overlaps(a));
185
if(m_pos + N-1 <= m_buf.len)
186
{
187
memcpy(&(m_buf[m_pos]), a, N-1);
188
}
189
m_pos += N-1;
190
}
191
192
inline void _do_write(csubstr sp)
193
{
194
if(sp.empty()) return;
195
RYML_ASSERT( ! sp.overlaps(m_buf));
196
if(m_pos + sp.len <= m_buf.len)
197
{
198
memcpy(&(m_buf[m_pos]), sp.str, sp.len);
199
}
200
m_pos += sp.len;
201
}
202
203
inline void _do_write(const char c)
204
{
205
if(m_pos + 1 <= m_buf.len)
206
{
207
m_buf[m_pos] = c;
208
}
209
++m_pos;
210
}
211
212
inline void _do_write(RepC const rc)
213
{
214
if(m_pos + rc.num_times <= m_buf.len)
215
{
216
for(size_t i = 0; i < rc.num_times; ++i)
217
{
218
m_buf[m_pos + i] = rc.c;
219
}
220
}
221
m_pos += rc.num_times;
222
}
223
};
224
225
226
} // namespace yml
227
} // namespace c4
228
229
#endif /* _C4_YML_WRITER_HPP_ */
230
231