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