rapidyaml  0.11.1
parse and emit YAML, and do it fast
writer.hpp
Go to the documentation of this file.
1 #ifndef _C4_YML_WRITER_HPP_
2 #define _C4_YML_WRITER_HPP_
3 
4 #ifndef _C4_YML_ERROR_HPP_
5 #include "./error.hpp"
6 #endif
7 
8 #include <stdio.h> // fwrite(), fputc()
9 #include <string.h> // memcpy()
10 
11 
12 namespace c4 {
13 namespace yml {
14 
15 /** @addtogroup doc_emit
16  * @{
17  */
18 
19 /** @defgroup doc_writers Writer objects to use with an Emitter
20  * @see Emitter
21  * @{
22  */
23 
24 
25 //-----------------------------------------------------------------------------
26 //-----------------------------------------------------------------------------
27 //-----------------------------------------------------------------------------
28 /** A writer that outputs to a file. Defaults to stdout. */
29 struct WriterFile
30 {
31  FILE * m_file;
32  size_t m_pos;
33 
34  WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}
35 
36  substr _get(bool /*error_on_excess*/) const
37  {
38  substr sp;
39  sp.str = nullptr;
40  sp.len = m_pos;
41  return sp;
42  }
43 
44  template<size_t N>
45  void _do_write(const char (&a)[N])
46  {
47  (void)fwrite(a, sizeof(char), N - 1, m_file);
48  m_pos += N - 1;
49  }
50 
51  void _do_write(csubstr sp)
52  {
53  C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wsign-conversion")
54  if(sp.empty())
55  return;
56  (void)fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);
57  m_pos += sp.len;
58  C4_SUPPRESS_WARNING_GCC_CLANG_POP
59  }
60 
61  void _do_write(const char c)
62  {
63  (void)fputc(c, m_file);
64  ++m_pos;
65  }
66 
67  void _do_write(const char c, size_t num_times)
68  {
69  for(size_t i = 0; i < num_times; ++i)
70  (void)fputc(c, m_file);
71  m_pos += num_times;
72  }
73 };
74 
75 
76 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
78 //-----------------------------------------------------------------------------
79 /** A writer that outputs to an STL-like ostream. */
80 template<class OStream>
82 {
83  OStream* m_stream;
84  size_t m_pos;
85 
86  WriterOStream(OStream &s) : m_stream(&s), m_pos(0) {}
87 
88  substr _get(bool /*error_on_excess*/) const
89  {
90  substr sp;
91  sp.str = nullptr;
92  sp.len = m_pos;
93  return sp;
94  }
95 
96  template<size_t N>
97  void _do_write(const char (&a)[N])
98  {
99  m_stream->write(a, N - 1);
100  m_pos += N - 1;
101  }
102 
103  void _do_write(csubstr sp)
104  {
105  C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wsign-conversion")
106  if(sp.empty())
107  return;
108  m_stream->write(sp.str, sp.len);
109  m_pos += sp.len;
110  C4_SUPPRESS_WARNING_GCC_CLANG_POP
111  }
112 
113  void _do_write(const char c)
114  {
115  m_stream->put(c);
116  ++m_pos;
117  }
118 
119  void _do_write(const char c, size_t num_times)
120  {
121  for(size_t i = 0; i < num_times; ++i)
122  m_stream->put(c);
123  m_pos += num_times;
124  }
125 };
126 
127 
128 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
130 //-----------------------------------------------------------------------------
131 /** a writer to a substr */
132 struct WriterBuf
133 {
134  substr m_buf;
135  size_t m_pos;
136 
137  WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}
138 
139  substr _get(bool error_on_excess) const
140  {
141  if(m_pos <= m_buf.len)
142  return m_buf.first(m_pos);
143  else if(error_on_excess)
144  c4::yml::err_basic(RYML_LOC_HERE(), "not enough space in the given buffer");
145  substr sp;
146  sp.str = nullptr;
147  sp.len = m_pos;
148  return sp;
149  }
150 
151  template<size_t N>
152  void _do_write(const char (&a)[N])
153  {
154  _RYML_ASSERT_BASIC( ! m_buf.overlaps(a));
155  if(m_pos + N-1 <= m_buf.len)
156  memcpy(&(m_buf[m_pos]), a, N-1);
157  m_pos += N-1;
158  }
159 
160  void _do_write(csubstr sp)
161  {
162  if(sp.empty())
163  return;
164  _RYML_ASSERT_BASIC( ! sp.overlaps(m_buf));
165  if(m_pos + sp.len <= m_buf.len)
166  memcpy(&(m_buf[m_pos]), sp.str, sp.len);
167  m_pos += sp.len;
168  }
169 
170  void _do_write(const char c)
171  {
172  if(m_pos + 1 <= m_buf.len)
173  m_buf[m_pos] = c;
174  ++m_pos;
175  }
176 
177  void _do_write(const char c, size_t num_times)
178  {
179  if(m_pos + num_times <= m_buf.len)
180  for(size_t i = 0; i < num_times; ++i)
181  m_buf[m_pos + i] = c;
182  m_pos += num_times;
183  }
184 };
185 
186 /** @ } */
187 
188 /** @ } */
189 
190 
191 } // namespace yml
192 } // namespace c4
193 
194 #endif /* _C4_YML_WRITER_HPP_ */
Error utilities used by ryml.
void err_basic(ErrorDataBasic const &errdata, const char *msg)
trigger a basic error to its respective handler, with a non-formatted error message.
Definition: common.cpp:196
void _do_write(csubstr sp)
Definition: writer.hpp:103
WriterOStream(OStream &s)
Definition: writer.hpp:86
substr _get(bool) const
Definition: writer.hpp:88
void _do_write(const char(&a)[N])
Definition: writer.hpp:45
void _do_write(const char c)
Definition: writer.hpp:61
WriterFile(FILE *f=nullptr)
Definition: writer.hpp:34
OStream * m_stream
Definition: writer.hpp:83
substr _get(bool error_on_excess) const
Definition: writer.hpp:139
void _do_write(csubstr sp)
Definition: writer.hpp:160
void _do_write(const char c, size_t num_times)
Definition: writer.hpp:119
void _do_write(const char c, size_t num_times)
Definition: writer.hpp:177
substr _get(bool) const
Definition: writer.hpp:36
void _do_write(const char(&a)[N])
Definition: writer.hpp:152
WriterBuf(substr sp)
Definition: writer.hpp:137
void _do_write(const char c)
Definition: writer.hpp:113
void _do_write(const char(&a)[N])
Definition: writer.hpp:97
void _do_write(csubstr sp)
Definition: writer.hpp:51
void _do_write(const char c, size_t num_times)
Definition: writer.hpp:67
void _do_write(const char c)
Definition: writer.hpp:170
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition: common.cpp:14
a writer to a substr
Definition: writer.hpp:133
A writer that outputs to a file.
Definition: writer.hpp:30
A writer that outputs to an STL-like ostream.
Definition: writer.hpp:82