rapidyaml 0.15.2
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
vector.hpp
Go to the documentation of this file.
1#ifndef C4_YML_STD_VECTOR_HPP_
2#define C4_YML_STD_VECTOR_HPP_
3
4#include "c4/yml/node.hpp"
5#include <c4/std/vector.hpp>
6#include <vector>
7
8namespace c4 {
9namespace yml {
10
11C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
12
13// vector<T> is a sequence-like type, and it requires child nodes
14// in the data tree hierarchy (a SEQ node in ryml parlance).
15// So it should be serialized via write()/read().
16
17/** serialize a vector to a node: implementation for @ref Tree */
18template<class T, class Alloc>
19void write(Tree *tree, id_type id, std::vector<T, Alloc> const& vec)
20{
21 tree->set_seq(id);
22 for(T const& val : vec)
23 tree->set_serialized(tree->append_child(id), val);
24}
25
26/** serialize a vector to a node: implementation for @ref NodeRef */
27template<class T, class Alloc>
28void write(NodeRef *n, std::vector<T, Alloc> const& vec)
29{
30 // don't defer to the tree impl here (if that were the case, we
31 // wouldn't even need to implement this function, as ryml ends up
32 // calling the tree impl by default). It may be the case that the
33 // serialization of T uses a serialization of a nested type that
34 // is not available in the tree implementation, so we need to
35 // provide this as a hook for that. If that's not required, then
36 // the tree implementation will get called anyway.
37 n->set_seq();
38 for(T const& val : vec)
39 {
40 NodeRef ch = n->append_child();
41 // call write() directly. ch.set_serialized() would also work,
42 // but does an additional check (to create the node if it is a
43 // seed). That check is not needed here because we used
44 // .append_child() to create the node.
45 write(&ch, val);
46 }
47}
48
49
50/** deserialize from a @ref Tree node, overwriting existing vector entries. */
51template<class T, class Alloc>
52ReadResult read(Tree const *tree, id_type id, std::vector<T, Alloc> *vec)
53{
54 if C4_UNLIKELY(!tree->is_seq(id))
55 return ReadResult(id);
56 vec->clear();
57 #if C4_CPP < 17 // prior to C++17, emplace_back() does not return a reference
58 size_t pos = 0;
59 #endif
60 for(id_type child = tree->first_child(id); child != NONE; child = tree->next_sibling(child))
61 {
62 #if C4_CPP >= 17
63 T &val = vec->emplace_back();
64 #else
65 vec->emplace_back();
66 T &val = (*vec)[pos++];
67 #endif
68 // do not call read(tree, child, &val) here. we do not know
69 // that the YAML is valid, so we need to do the checks in
70 // child.deserialize()
71 if(!tree->deserialize(child, &val))
72 return ReadResult(id);
73 }
74 return ReadResult{};
75}
76
77/** deserialize from a @ref ConstNodeRef node, overwriting existing vector entries. */
78template<class T, class Alloc>
79ReadResult read(ConstNodeRef const& node, std::vector<T, Alloc> *vec)
80{
81 // don't defer to the tree impl here (if that were the case, we
82 // wouldn't even need to implement this function, as ryml ends up
83 // calling the tree impl by default). It may be the case that the
84 // serialization of T uses a serialization of a nested type that
85 // is not available in the tree implementation, so we need to
86 // provide this as a hook for that. If that's not required, then
87 // the tree implementation will get called anyway.
88 if C4_UNLIKELY(!node.is_seq())
89 return ReadResult(node.id());
90 vec->clear();
91 #if C4_CPP < 17 // prior to C++17, emplace_back() does not return a reference
92 size_t pos = 0;
93 #endif
94 for(ConstNodeRef const& child : node.children())
95 {
96 #if C4_CPP >= 17
97 T &val = vec->emplace_back();
98 #else
99 vec->emplace_back();
100 T &val = (*vec)[pos++];
101 #endif
102 // do not call read(child, &val) here. we do not know that the
103 // YAML is valid, so we need to do the checks in
104 // child.deserialize()
105 if(!child.deserialize(&val))
106 return ReadResult(child.id());
107 }
108 return ReadResult();
109}
110
111
112
113//-----------------------------------------------------
114// specialization for std::vector<bool>. needed because the return
115// type of its operator[] is not bool, but std::vector<bool>::reference
116
117/** deserialize from a @ref Tree node, overwriting existing vector entries. */
118template<class Alloc>
119ReadResult read(Tree const* tree, id_type id, std::vector<bool, Alloc> *vec)
120{
121 if C4_UNLIKELY(!tree->is_seq(id))
122 return ReadResult(id);
123 vec->clear();
124 bool tmp = {};
125 for(id_type child = tree->first_child(id); child != NONE; child = tree->next_sibling(child))
126 {
127 if(!from_chars(tree->val(child), &tmp))
128 return ReadResult(child);
129 vec->push_back(tmp); // leave this. gcc4.8 does not have std::vector<bool>::emplace_back()
130 }
131 return ReadResult();
132}
133
134/** deserialize from a @ref ConstNodeRef node, overwriting existing vector entries. */
135template<class Alloc>
136ReadResult read(ConstNodeRef const& n, std::vector<bool, Alloc> *vec)
137{
138 // call the tree implementation, saving the node readability
139 // checks. we can do that here because bool (the value type) is a
140 // final type, so it can't be overrided.
141 return read(n.tree(), n.id(), vec);
142}
143
144C4_SUPPRESS_WARNING_GCC_POP
145
146} // namespace yml
147} // namespace c4
148
149#endif // C4_YML_STD_VECTOR_HPP_
Holds a pointer to an existing tree, and a node id.
Definition node.hpp:737
id_type id() const noexcept
Definition node.hpp:822
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
Definition node.hpp:987
Tree const * tree() const noexcept
Definition node.hpp:821
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition node.hpp:1063
NodeRef append_child()
Definition node.hpp:1715
id_type first_child(id_type node) const
Definition tree.hpp:577
csubstr const & val(id_type node) const
Definition tree.hpp:460
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
Definition tree.hpp:954
id_type next_sibling(id_type node) const
Definition tree.hpp:572
bool is_seq(id_type node) const
Definition tree.hpp:481
provides conversion and comparison facilities from/between std::vector<char> to c4::substr and c4::cs...
bool from_chars(csubstr buf, uint8_t *v) noexcept
ReadResult read(ConstNodeRef const &n, T *v)
Definition node.hpp:2074
void write(NodeRef *n, T const &v)
Definition node.hpp:2114
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...
Definition common.hpp:124
@ NONE
an index to none
Definition common.hpp:131
Node classes.
A lightweight truthy type, used to enable reporting the offending node when a deserializing error hap...
Definition common.hpp:162
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
Definition node.hpp:208