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")
36 template<
class Writer>
class Emitter;
37 template<
class OStream>
64 typedef enum : uint32_t {
65 EMIT_NONROOT_KEY = 1u << 0u,
66 EMIT_NONROOT_DASH = 1u << 1u,
67 EMIT_NONROOT_MARKUP = EMIT_NONROOT_KEY|EMIT_NONROOT_DASH,
68 INDENT_FLOW_ML = 1u << 2u,
69 JSON_ERR_ON_TAG = 1u << 3u,
70 JSON_ERR_ON_ANCHOR = 1u << 4u,
71 _JSON_ERR_MASK = JSON_ERR_ON_TAG|JSON_ERR_ON_ANCHOR,
72 DEFAULT_FLAGS = EMIT_NONROOT_KEY|INDENT_FLOW_ML,
82 C4_ALWAYS_INLINE
bool emit_nonroot_key() const noexcept {
return (m_option_flags & EMIT_NONROOT_KEY) != 0; }
83 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; }
85 C4_ALWAYS_INLINE
bool emit_nonroot_dash() const noexcept {
return (m_option_flags & EMIT_NONROOT_DASH) != 0; }
86 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; }
88 C4_ALWAYS_INLINE
bool indent_flow_ml() const noexcept {
return (m_option_flags & INDENT_FLOW_ML) != 0; }
89 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; }
91 C4_ALWAYS_INLINE EmitOptionFlags_e
json_error_flags() const noexcept {
return (EmitOptionFlags_e)(m_option_flags & _JSON_ERR_MASK); }
106 static constexpr
const id_type max_depth_default = 64;
113 return m_max_depth == that.m_max_depth &&
114 m_option_flags == that.m_option_flags;
120 id_type m_max_depth{max_depth_default};
121 EmitOptionFlags_e m_option_flags{DEFAULT_FLAGS};
132 template<
class Writer>
142 template<
class ...WriterArgs>
144 : Writer(std::forward<WriterArgs>(args)...)
156 template<
class ...WriterArgs>
158 : Writer(std::forward<WriterArgs>(args)...)
192 return this->emit_as(type, t, t.
root_id(), error_on_excess);
199 return this->emit_as(type, *n.
tree(), n.
id(), error_on_excess);
220 void _visit_stream(
id_type id);
222 void _visit_doc_val(
id_type id);
223 void _visit_blck_container(
id_type id);
224 void _visit_flow_container(
id_type id);
226 void _visit_flow_sl(
id_type id);
227 void _visit_flow_sl_seq(
id_type id);
228 void _visit_flow_sl_map(
id_type id);
230 void _visit_flow_ml(
id_type id);
231 void _visit_flow_ml_seq(
id_type id);
232 void _visit_flow_ml_map(
id_type id);
235 void _visit_blck_seq(
id_type id);
236 void _visit_blck_map(
id_type id);
238 void _top_open_entry(
id_type id);
239 void _top_close_entry(
id_type id);
240 void _blck_seq_open_entry(
id_type id);
241 void _blck_map_open_entry(
id_type id);
242 void _blck_close_entry(
id_type id);
244 void _blck_write_scalar(csubstr str,
type_bits type);
246 void _flow_seq_open_entry(
id_type id);
247 void _flow_map_open_entry(
id_type id);
250 void _flow_write_scalar(csubstr str,
type_bits type);
255 void _write_scalar_literal(csubstr s,
id_type level);
256 void _write_scalar_folded(csubstr s,
id_type level);
257 void _write_scalar_squo(csubstr s,
id_type level);
258 void _write_scalar_dquo(csubstr s,
id_type level);
259 void _write_scalar_plain(csubstr s,
id_type level);
261 size_t _write_escaped_newlines(csubstr s,
size_t i);
262 size_t _write_indented_block(csubstr s,
size_t i,
id_type level);
268 bool _json_maybe_write_naninf(csubstr s);
271 void _json_write_scalar_dquo(csubstr s);
272 void _json_write_number(csubstr s);
276 void _write_tag(csubstr tag)
278 if(!tag.begins_with(
'!'))
282 void _write_ref(csubstr ref)
286 if(!ref.begins_with(
'*'))
294 C4_ALWAYS_INLINE
void _indent(
id_type level)
296 size_t num = (size_t)(2u * level);
297 this->Writer::_do_write(
' ', num);
302 C4_ALWAYS_INLINE
void _write(
const char (&a)[N])
304 this->Writer::_do_write(std::forward<
const char (&)[N]>(a));
307 C4_ALWAYS_INLINE
void _write(csubstr s)
309 this->Writer::_do_write(s);
312 C4_ALWAYS_INLINE
void _write(
char c)
314 this->Writer::_do_write(c);
317 C4_ALWAYS_INLINE
void _write(
char c,
size_t num)
319 this->Writer::_do_write(c, num);
324 C4_ALWAYS_INLINE
void _newl()
326 this->Writer::_do_write(
'\n');
333 typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e;
336 C4_ALWAYS_INLINE
void _pend_none() noexcept
341 C4_ALWAYS_INLINE
void _pend_newl() noexcept
346 C4_ALWAYS_INLINE
void _pend_space() noexcept
351 C4_ALWAYS_INLINE
void _write_pws_and_pend(Pws_e next=_PWS_NONE) noexcept
353 if(m_pws == _PWS_SPACE)
357 else if(m_pws == _PWS_NEWL)
367 Tree
const* C4_RESTRICT m_tree;
377 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
378 #pragma GCC diagnostic push
379 #pragma GCC diagnostic ignored "-Wparentheses"
394 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
395 #pragma GCC diagnostic pop
520 template<
class OStream>
530 template<
class OStream>
583 template<
class OStream>
594 template<
class OStream>
674 inline substr
emit_yaml(
Tree const& t, substr buf,
bool error_on_excess=
true)
693 inline substr
emit_json(
Tree const& t, substr buf,
bool error_on_excess=
true)
764 template<
class CharOwningContainer>
767 size_t startpos = append ? cont->size() : 0u;
768 cont->resize(cont->capacity());
769 substr buf =
to_substr(*cont).sub(startpos);
770 substr ret =
emit_yaml(t,
id, opts, buf,
false);
771 if(ret.str ==
nullptr && ret.len > 0)
773 cont->resize(startpos + ret.len);
779 cont->resize(startpos + ret.len);
784 template<
class CharOwningContainer>
794 template<
class CharOwningContainer>
797 const size_t startpos = append ? cont->size() : 0u;
798 cont->resize(cont->capacity());
799 substr buf =
to_substr(*cont).sub(startpos);
801 substr ret =
emit_json(t,
id, opts, buf,
false);
802 if(ret.str ==
nullptr && ret.len > 0)
804 cont->resize(startpos + ret.len);
810 cont->resize(startpos + ret.len);
815 template<
class CharOwningContainer>
823 template<
class CharOwningContainer>
826 CharOwningContainer c;
831 template<
class CharOwningContainer>
834 CharOwningContainer c;
845 template<
class CharOwningContainer>
853 template<
class CharOwningContainer>
863 template<
class CharOwningContainer>
871 template<
class CharOwningContainer>
881 template<
class CharOwningContainer>
884 CharOwningContainer c;
891 template<
class CharOwningContainer>
894 CharOwningContainer c;
908 template<
class CharOwningContainer>
916 template<
class CharOwningContainer>
926 template<
class CharOwningContainer>
934 template<
class CharOwningContainer>
944 template<
class CharOwningContainer>
949 CharOwningContainer c;
954 template<
class CharOwningContainer>
959 CharOwningContainer c;
972 #define RYML_DEPRECATE_EMIT \
973 RYML_DEPRECATED("use emit_yaml() instead. " \
974 "See https://github.com/biojppm/rapidyaml/issues/120")
975 #define RYML_DEPRECATE_EMITRS \
976 RYML_DEPRECATED("use emitrs_yaml() instead. " \
977 "See https://github.com/biojppm/rapidyaml/issues/120")
983 #define RYML_TMP_EMIT_
987 RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t,
id_type id, FILE *f)
991 RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t, FILE *f=
nullptr)
995 RYML_DEPRECATE_EMIT
inline size_t emit(ConstNodeRef
const& r, FILE *f=
nullptr)
1000 RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t,
id_type id, substr buf,
bool error_on_excess=
true)
1002 return emit_yaml(t,
id, buf, error_on_excess);
1004 RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t, substr buf,
bool error_on_excess=
true)
1006 return emit_yaml(t, buf, error_on_excess);
1008 RYML_DEPRECATE_EMIT
inline substr emit(ConstNodeRef
const& r, substr buf,
bool error_on_excess=
true)
1010 return emit_yaml(r, buf, error_on_excess);
1013 #ifdef RYML_TMP_EMIT_
1015 #undef RYML_TMP_EMIT_
1018 template<
class CharOwningContainer>
1019 RYML_DEPRECATE_EMITRS substr emitrs(Tree
const& t,
id_type id, CharOwningContainer * cont)
1023 template<
class CharOwningContainer>
1024 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t,
id_type id)
1026 return emitrs_yaml<CharOwningContainer>(t,
id);
1028 template<
class CharOwningContainer>
1029 RYML_DEPRECATE_EMITRS substr emitrs(Tree
const& t, CharOwningContainer * cont)
1033 template<
class CharOwningContainer>
1034 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t)
1036 return emitrs_yaml<CharOwningContainer>(t);
1038 template<
class CharOwningContainer>
1039 RYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef
const& n, CharOwningContainer * cont)
1043 template<
class CharOwningContainer>
1044 RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef
const& n)
1046 return emitrs_yaml<CharOwningContainer>(n);
1056 C4_SUPPRESS_WARNING_GCC_CLANG_POP
1058 #undef RYML_DEPRECATE_EMIT
1059 #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<< .