1 #ifndef _C4_YML_EMIT_HPP_
2 #define _C4_YML_EMIT_HPP_
6 #ifndef _C4_YML_WRITER_HPP_
10 #ifndef _C4_YML_TREE_HPP_
14 #ifndef _C4_YML_NODE_HPP_
19 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wold-style-cast")
35 template<
class Writer>
class Emitter;
36 template<
class OStream>
63 typedef enum : uint32_t {
64 EMIT_NONROOT_KEY = 1u << 0u,
65 EMIT_NONROOT_DASH = 1u << 1u,
66 EMIT_NONROOT_MARKUP = EMIT_NONROOT_KEY|EMIT_NONROOT_DASH,
67 INDENT_FLOW_ML = 1u << 2u,
68 JSON_ERR_ON_TAG = 1u << 3u,
69 JSON_ERR_ON_ANCHOR = 1u << 4u,
70 _JSON_ERR_MASK = JSON_ERR_ON_TAG|JSON_ERR_ON_ANCHOR,
71 DEFAULT_FLAGS = EMIT_NONROOT_KEY|INDENT_FLOW_ML,
81 C4_ALWAYS_INLINE
bool emit_nonroot_key() const noexcept {
return (m_option_flags & EMIT_NONROOT_KEY) != 0; }
82 EmitOptions&
emit_nonroot_key(
bool enabled) noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | EMIT_NONROOT_KEY) : (m_option_flags & ~EMIT_NONROOT_KEY));
return *
this; }
84 C4_ALWAYS_INLINE
bool emit_nonroot_dash() const noexcept {
return (m_option_flags & EMIT_NONROOT_DASH) != 0; }
85 EmitOptions&
emit_nonroot_dash(
bool enabled) noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | EMIT_NONROOT_DASH) : (m_option_flags & ~EMIT_NONROOT_DASH));
return *
this; }
87 C4_ALWAYS_INLINE
bool indent_flow_ml() const noexcept {
return (m_option_flags & INDENT_FLOW_ML) != 0; }
88 EmitOptions&
indent_flow_ml(
bool enabled) noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | INDENT_FLOW_ML) : (m_option_flags & ~INDENT_FLOW_ML));
return *
this; }
90 C4_ALWAYS_INLINE EmitOptionFlags_e
json_error_flags() const noexcept {
return (EmitOptionFlags_e)(m_option_flags & _JSON_ERR_MASK); }
105 static constexpr
const id_type max_depth_default = 64;
112 return m_max_depth == that.m_max_depth &&
113 m_option_flags == that.m_option_flags;
119 id_type m_max_depth{max_depth_default};
120 EmitOptionFlags_e m_option_flags{DEFAULT_FLAGS};
131 template<
class Writer>
141 template<
class ...WriterArgs>
143 : Writer(std::forward<WriterArgs>(args)...)
155 template<
class ...WriterArgs>
157 : Writer(std::forward<WriterArgs>(args)...)
191 return this->emit_as(type, t, t.
root_id(), error_on_excess);
198 return this->emit_as(type, *n.
tree(), n.
id(), error_on_excess);
219 void _visit_stream(
id_type id);
221 void _visit_doc_val(
id_type id);
222 void _visit_blck_container(
id_type id);
223 void _visit_flow_container(
id_type id);
225 void _visit_flow_sl(
id_type id);
226 void _visit_flow_sl_seq(
id_type id);
227 void _visit_flow_sl_map(
id_type id);
229 void _visit_flow_ml(
id_type id);
230 void _visit_flow_ml_seq(
id_type id);
231 void _visit_flow_ml_map(
id_type id);
234 void _visit_blck_seq(
id_type id);
235 void _visit_blck_map(
id_type id);
237 void _top_open_entry(
id_type id);
238 void _top_close_entry(
id_type id);
239 void _blck_seq_open_entry(
id_type id);
240 void _blck_map_open_entry(
id_type id);
241 void _blck_close_entry(
id_type id);
243 void _blck_write_scalar(csubstr str,
type_bits type);
245 void _flow_seq_open_entry(
id_type id);
246 void _flow_map_open_entry(
id_type id);
249 void _flow_write_scalar(csubstr str,
type_bits type);
254 void _write_scalar_literal(csubstr s,
id_type level);
255 void _write_scalar_folded(csubstr s,
id_type level);
256 void _write_scalar_squo(csubstr s,
id_type level);
257 void _write_scalar_dquo(csubstr s,
id_type level);
258 void _write_scalar_plain(csubstr s,
id_type level);
260 size_t _write_escaped_newlines(csubstr s,
size_t i);
261 size_t _write_indented_block(csubstr s,
size_t i,
id_type level);
267 bool _json_maybe_write_naninf(csubstr s);
270 void _json_write_scalar_dquo(csubstr s);
271 void _json_write_number(csubstr s);
275 void _write_tag(csubstr tag)
277 if(!tag.begins_with(
'!'))
281 void _write_ref(csubstr ref)
285 if(!ref.begins_with(
'*'))
293 C4_ALWAYS_INLINE
void _indent(
id_type level)
295 size_t num = (size_t)(2u * level);
296 this->Writer::_do_write(
' ', num);
301 C4_ALWAYS_INLINE
void _write(
const char (&a)[N])
303 this->Writer::_do_write(std::forward<
const char (&)[N]>(a));
306 C4_ALWAYS_INLINE
void _write(csubstr s)
308 this->Writer::_do_write(s);
311 C4_ALWAYS_INLINE
void _write(
char c)
313 this->Writer::_do_write(c);
316 C4_ALWAYS_INLINE
void _write(
char c,
size_t num)
318 this->Writer::_do_write(c, num);
323 C4_ALWAYS_INLINE
void _newl()
325 this->Writer::_do_write(
'\n');
332 typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e;
335 C4_ALWAYS_INLINE
void _pend_none() noexcept
340 C4_ALWAYS_INLINE
void _pend_newl() noexcept
345 C4_ALWAYS_INLINE
void _pend_space() noexcept
350 C4_ALWAYS_INLINE
void _write_pws_and_pend(Pws_e next=_PWS_NONE) noexcept
352 if(m_pws == _PWS_SPACE)
356 else if(m_pws == _PWS_NEWL)
366 Tree
const* C4_RESTRICT m_tree;
376 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
377 #pragma GCC diagnostic push
378 #pragma GCC diagnostic ignored "-Wparentheses"
393 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
394 #pragma GCC diagnostic pop
519 template<
class OStream>
529 template<
class OStream>
582 template<
class OStream>
593 template<
class OStream>
673 inline substr
emit_yaml(
Tree const& t, substr buf,
bool error_on_excess=
true)
692 inline substr
emit_json(
Tree const& t, substr buf,
bool error_on_excess=
true)
763 template<
class CharOwningContainer>
766 size_t startpos = append ? cont->size() : 0u;
767 cont->resize(cont->capacity());
768 substr buf =
to_substr(*cont).sub(startpos);
769 substr ret =
emit_yaml(t,
id, opts, buf,
false);
770 if(ret.str ==
nullptr && ret.len > 0)
772 cont->resize(startpos + ret.len);
778 cont->resize(startpos + ret.len);
783 template<
class CharOwningContainer>
793 template<
class CharOwningContainer>
796 const size_t startpos = append ? cont->size() : 0u;
797 cont->resize(cont->capacity());
798 substr buf =
to_substr(*cont).sub(startpos);
800 substr ret =
emit_json(t,
id, opts, buf,
false);
801 if(ret.str ==
nullptr && ret.len > 0)
803 cont->resize(startpos + ret.len);
809 cont->resize(startpos + ret.len);
814 template<
class CharOwningContainer>
822 template<
class CharOwningContainer>
825 CharOwningContainer c;
830 template<
class CharOwningContainer>
833 CharOwningContainer c;
844 template<
class CharOwningContainer>
852 template<
class CharOwningContainer>
862 template<
class CharOwningContainer>
870 template<
class CharOwningContainer>
880 template<
class CharOwningContainer>
883 CharOwningContainer c;
890 template<
class CharOwningContainer>
893 CharOwningContainer c;
907 template<
class CharOwningContainer>
915 template<
class CharOwningContainer>
925 template<
class CharOwningContainer>
933 template<
class CharOwningContainer>
943 template<
class CharOwningContainer>
948 CharOwningContainer c;
953 template<
class CharOwningContainer>
958 CharOwningContainer c;
971 #define RYML_DEPRECATE_EMIT \
972 RYML_DEPRECATED("use emit_yaml() instead. " \
973 "See https://github.com/biojppm/rapidyaml/issues/120")
974 #define RYML_DEPRECATE_EMITRS \
975 RYML_DEPRECATED("use emitrs_yaml() instead. " \
976 "See https://github.com/biojppm/rapidyaml/issues/120")
982 #define RYML_TMP_EMIT_
986 RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t,
id_type id, FILE *f)
990 RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t, FILE *f=
nullptr)
994 RYML_DEPRECATE_EMIT
inline size_t emit(ConstNodeRef
const& r, FILE *f=
nullptr)
999 RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t,
id_type id, substr buf,
bool error_on_excess=
true)
1001 return emit_yaml(t,
id, buf, error_on_excess);
1003 RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t, substr buf,
bool error_on_excess=
true)
1005 return emit_yaml(t, buf, error_on_excess);
1007 RYML_DEPRECATE_EMIT
inline substr emit(ConstNodeRef
const& r, substr buf,
bool error_on_excess=
true)
1009 return emit_yaml(r, buf, error_on_excess);
1012 #ifdef RYML_TMP_EMIT_
1014 #undef RYML_TMP_EMIT_
1017 template<
class CharOwningContainer>
1018 RYML_DEPRECATE_EMITRS substr emitrs(Tree
const& t,
id_type id, CharOwningContainer * cont)
1022 template<
class CharOwningContainer>
1023 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t,
id_type id)
1025 return emitrs_yaml<CharOwningContainer>(t,
id);
1027 template<
class CharOwningContainer>
1028 RYML_DEPRECATE_EMITRS substr emitrs(Tree
const& t, CharOwningContainer * cont)
1032 template<
class CharOwningContainer>
1033 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t)
1035 return emitrs_yaml<CharOwningContainer>(t);
1037 template<
class CharOwningContainer>
1038 RYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef
const& n, CharOwningContainer * cont)
1042 template<
class CharOwningContainer>
1043 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef
const& n)
1045 return emitrs_yaml<CharOwningContainer>(n);
1054 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1056 #undef RYML_DEPRECATE_EMIT
1057 #undef RYML_DEPRECATE_EMITRS
Holds a pointer to an existing tree, and a node id.
Tree const * tree() const noexcept
id_type id() const noexcept
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
A stateful emitter, for use with a writer such as WriterBuf, WriterFile, or WriterOStream.
id_type root_id() const
Get the id of the root node. The tree must not be empty.
Definitions for emit functions.
EmitOptionFlags_e json_error_flags() const noexcept
id_type max_depth() const noexcept
get the max depth for emitted trees (to prevent a stack overflow)
substr emit_as(EmitType_e type, ConstNodeRef const &n, bool error_on_excess=true)
emit starting at the given node
bool emit_nonroot_key() const noexcept
void max_depth(id_type max_depth) noexcept
set the max depth for emitted trees (to prevent a stack overflow)
as_yaml(Tree const &t, EmitOptions const &opts={})
void options(EmitOptions opts) noexcept
set the emit options for this object
substr emit_as(EmitType_e type, Tree const &t, bool error_on_excess=true)
emit starting at the root node
id_type max_depth() const noexcept
as_yaml(Tree const &t, id_type id, EmitOptions const &opts={})
Emitter(WriterArgs &&...args)
Construct the emitter and its internal Writer state, using default emit options.
Emitter(EmitOptions const &opts, WriterArgs &&...args)
Construct the emitter and its internal Writer state.
substr emit_as(EmitType_e type, Tree const &t, id_type id, bool error_on_excess)
emit!
EmitOptions & emit_nonroot_key(bool enabled) noexcept
as_json(Tree const &t, EmitOptions const &opts={})
as_yaml(ConstNodeRef const &n, EmitOptions const &opts={})
substr emit_yaml(ConstNodeRef const &r, substr buf, bool error_on_excess=true)
(2) like (1), but use default emit options
EmitOptions & indent_flow_ml(bool enabled) noexcept
bool indent_flow_ml() const noexcept
EmitOptions & emit_nonroot_dash(bool enabled) noexcept
bool emit_nonroot_dash() const noexcept
as_json(ConstNodeRef const &n, EmitOptions const &opts={})
EmitOptions const & options() const noexcept
get the emit options for this object
substr emit_json(ConstNodeRef const &r, substr buf, bool error_on_excess=true)
(2) like (1), but use default emit options
EmitOptions & max_depth(id_type d) noexcept
as_json(Tree const &t, id_type id, EmitOptions const &opts={})
EmitOptions & json_error_flags(EmitOptionFlags_e d) noexcept
CharOwningContainer emitrs_yaml(ConstNodeRef const &n, EmitOptions const &opts={})
(3) emit+resize: YAML to a newly-created std::string/std::vector-like container.
CharOwningContainer emitrs_json(ConstNodeRef const &n, EmitOptions const &opts={})
(3) emit+resize: JSON to a newly-created std::string/std::vector-like container.
OStream & operator<<(OStream &s, as_yaml const &y)
emit yaml to an STL-like stream
EmitType_e
Specifies the type of content to emit.
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
@ KEY_DQUO
mark key scalar as double quoted "
@ VAL_FOLDED
mark val scalar as multiline, block folded >
@ VAL_STYLE
mask of all the scalar styles for val (not container styles!)
@ VAL_SQUO
mark val scalar as single quoted '
@ KEY_STYLE
mask of all the scalar styles for key (not container styles!)
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ VAL_DQUO
mark val scalar as double quoted "
@ KEY_SQUO
mark key scalar as single quoted '
@ VAL_LITERAL
mark val scalar as multiline, block literal |
@ KEY_LITERAL
mark key scalar as multiline, block literal |
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
@ KEY_FOLDED
mark key scalar as multiline, block folded >
substr to_substr(substr s) noexcept
neutral version for use in generic code
bool operator==(const char(&s)[N], basic_substring< C > const that) noexcept
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
A lightweight object containing options to be used when emitting.
wraps a NodeType_e element with some syntactic sugar and predicates
mark a tree or node to be emitted as yaml when using operator<<, with options.
mark a tree or node to be emitted as yaml when using operator<< .