YSTest: ValueNode.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

ValueNode.cpp
浏览该文件的文档.
1 /*
2 © 2012-2019 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YSLib/Core/YModules.h"
29 #include YFM_YSLib_Core_ValueNode // for ystdex::invoke_value_or,
30 // ystdex::call_value_or, ystdex::addrof, ystdex::compose, std::mem_fn,
31 // ystdex::bind1, ystdex::ref_eq;
32 #include <ystdex/cstdint.hpp> // for ystdex::floor_lb;
33
34 namespace YSLib
35 {
36
37 ValueNode&
38 ValueNode::operator%=(const ValueNode& node)
39 {
40 return Deref(insert_or_assign(node.name, node).first);
41 }
42 ValueNode&
43 ValueNode::operator%=(ValueNode&& node)
44 {
45 return Deref(insert_or_assign(node.name, std::move(node)).first);
46 }
47
48 ValueNode::Container
49 ValueNode::CreateRecursively(const Container& con, IValueHolder::Creation c)
50 {
51 return CreateRecursively(con, ystdex::bind1(&ValueObject::Create, c));
52 }
53
54 void
55 ValueNode::MoveContent(ValueNode&& node)
56 {
57 YAssert(!ystdex::ref_eq<>()(*this, node), "Invalid self move found.");
58
59 // NOTE: This is required for the case when the moved-to object (referenced
60 // by '*this') is an ancestor of the moved-from node (referenced by the
61 // parameter). In such cases, an object moved from the moved-to object
62 // container is needed to preserve the content of the moved-from node
63 // living sufficient long, since the move %operator= of %Container does not
64 // guarantee the old content of the container (as it can clear the old
65 // content in the container before moving elements). This also avoids
66 // cyclic references even when the move %operator= of %Container does
67 // preserved the old content of the container longer (e.g. by copy and
68 // swap), which would leak resources instead of d.
69 const auto t(std::move(GetContainerRef()));
70
71 SetContent(std::move(node));
72 }
73
74 void
75 ValueNode::SwapContent(ValueNode& node) ynothrowv
76 {
77 SwapContainer(node),
78 swap(Value, node.Value);
79 }
80
81 void
82 ValueNode::ThrowIndexOutOfRange(size_t idx)
83 {
84 throw std::out_of_range(ystdex::sfmt("Index '%zu' is out of range.", idx));
85 }
86
87 void
88 ValueNode::ThrowWrongNameFound(string_view name)
89 {
90 throw std::out_of_range(ystdex::sfmt("Wrong name '%s' found.",
91 Nonnull(name.data())));
92 }
93
94 void
95 swap(ValueNode& x, ValueNode& y) ynothrowv
96 {
97 std::swap(x.name, y.name),
98 x.SwapContent(y);
99 }
100
101 ValueNode&
102 AccessNode(ValueNode::Container* p_con, const string& name)
103 {
104 if(const auto p = AccessNodePtr(p_con, name))
105 return *p;
106 ValueNode::ThrowWrongNameFound(name);
107 }
108 const ValueNode&
109 AccessNode(const ValueNode::Container* p_con, const string& name)
110 {
111 if(const auto p = AccessNodePtr(p_con, name))
112 return *p;
113 ValueNode::ThrowWrongNameFound(name);
114 }
115 ValueNode&
116 AccessNode(ValueNode& node, size_t n)
117 {
118 const auto p(AccessNodePtr(node, n));
119
120 if(p)
121 return *p;
122 ValueNode::ThrowIndexOutOfRange(n);
123 }
124 const ValueNode&
125 AccessNode(const ValueNode& node, size_t n)
126 {
127 const auto p(AccessNodePtr(node, n));
128
129 if(p)
130 return *p;
131 ValueNode::ThrowIndexOutOfRange(n);
132 }
133
134 observer_ptr<ValueNode>
135 AccessNodePtr(ValueNode::Container& con, const string& name) ynothrow
136 {
137 return make_observer(ystdex::call_value_or<ValueNode*>(ystdex::addrof<>(),
138 con.find(name), {}, ystdex::end(con)));
139 }
140 observer_ptr<const ValueNode>
141 AccessNodePtr(const ValueNode::Container& con, const string& name) ynothrow
142 {
143 return make_observer(ystdex::call_value_or<const ValueNode*>(
144 ystdex::addrof<>(), con.find(name), {}, ystdex::end(con)));
145 }
146 observer_ptr<ValueNode>
147 AccessNodePtr(ValueNode& node, size_t n)
148 {
149 auto& con(node.GetContainerRef());
150
151 // XXX: Conversion to 'ptrdiff_t' might be implementation-defined.
152 return n < con.size()
153 ? make_observer(&*std::next(con.begin(), ptrdiff_t(n))) : nullptr;
154 }
155 observer_ptr<const ValueNode>
156 AccessNodePtr(const ValueNode& node, size_t n)
157 {
158 auto& con(node.GetContainer());
159
160 // XXX: Conversion to 'ptrdiff_t' might be implementation-defined.
161 return n < con.size()
162 ? make_observer(&*std::next(con.cbegin(), ptrdiff_t(n))) : nullptr;
163 }
164
165 ValueObject
166 GetValueOf(observer_ptr<const ValueNode> p_node)
167 {
168 return ystdex::invoke_value_or(&ValueNode::Value, p_node);
169 }
170
171 observer_ptr<const ValueObject>
172 GetValuePtrOf(observer_ptr<const ValueNode> p_node)
173 {
174 return ystdex::call_value_or(ystdex::compose(make_observer<const ValueObject
175 >, ystdex::addrof<>(), std::mem_fn(&ValueNode::Value)), p_node);
176 }
177
178
179 void
180 RemoveEmptyChildren(ValueNode::Container& con) ynothrow
181 {
182 ystdex::erase_all_if(con, std::mem_fn(&ValueNode::operator!));
183 }
184
185 void
186 RemoveHead(ValueNode::Container& con) ynothrowv
187 {
188 YAssert(!con.empty(), "Empty node container found.");
189 con.erase(con.cbegin());
190 }
191
192
193 bool
194 IsPrefixedIndex(string_view name, char prefix)
195 {
196 YAssertNonnull(name.data());
197 if(name.length() > 1 && name.front() == prefix)
198 try
199 {
200 const auto ss(name.substr(1));
201
202 return MakeIndex(DecodeIndex(ss)) == ss;
203 }
204 CatchIgnore(std::invalid_argument&)
205 return {};
206 }
207
208 string
209 MakeIndex(size_t n)
210 {
211 string str;
212 // XXX: Conversion might be implementation-defined with steady result
213 // expectedly.
214 const auto lb(n > 1 ? ystdex::floor_lb(n) + 1 : n);
215
216 str.resize((lb + 7) / 8 + 1);
217
218 size_t i(str.size() - 1);
219 while(n != 0)
220 {
221 if(i > 0)
222 {
223 str[i] = char(n & 0xFF);
224 n >>= 8;
225 --i;
226 }
227 else
228 YAssert(false, "Unexpected argument found.");
229 }
230 str[0] = char(lb);
231 return str;
232 }
233
234 size_t
235 DecodeIndex(string_view sv)
236 {
237 YAssert(sv.data(), "Invalid argument found.");
238
239 if(!sv.empty())
240 {
241 // XXX: Conversion might be implementation-defined with steady result
242 // expectedly.
243 const auto lb(size_t(sv.front()));
244 const size_t sz(sv.size());
245
246 if(sz < std::numeric_limits<size_t>::digits / 8 + 1
247 && sz == (lb + 7) / 8 + 1)
248 {
249 size_t n(0);
250 for(size_t i(1); i < sz; ++i)
251 {
252 n <<= 8;
253 n |= size_t(sv[i]);
254 }
255 return n;
256 }
257 }
258 throw std::invalid_argument("Invalid string name found.");
259 }
260
261 } // namespace YSLib;
262
ystdex::mapped_set< ValueNode, ystdex::less<>, MappedSetTraits, allocator_type >
x
const EncapsulationBase & x
Definition: NPLA1Forms.cpp:1536
YSLib::swap
void swap(ValueNode &x, ValueNode &y) ynothrowv
Definition: ValueNode.cpp:95
platform::Nonnull
YB_PURE _type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:518
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
CHRLib::c
c
Definition: CharacterProcessing.h:84
YSLib::RemoveEmptyChildren
YF_API void RemoveEmptyChildren(ValueNode::Container &) ynothrow
移除空子节点。
Definition: ValueNode.cpp:180
ystdex::bind1
auto bind1(_func &&f, _tParams &&... args) -> decltype(std::bind(std::forward< decltype(f)>(f), std::placeholders::_1, std::forward< decltype(args)>(args)...))
复合调用 std::bind 和 std::placeholders::_1 。
Definition: functional.hpp:53
YSLib::IsPrefixedIndex
YB_ATTR_nodiscard YF_API YB_PURE bool IsPrefixedIndex(string_view, char='$')
判断字符串是否是前缀索引：一个指定字符和非负整数的组合。
Definition: ValueNode.cpp:194
ystdex::cpp2017::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:437
YSLib::ValueNode::ThrowIndexOutOfRange
static YB_NORETURN void ThrowIndexOutOfRange(size_t)
抛出索引越界异常。
Definition: ValueNode.cpp:82
ystdex::addrof
一元 & 操作。
Definition: functor.hpp:441
YSLib::ValueNode::name
string name
Definition: ValueNode.h:214
YSLib::GetValuePtrOf
YB_ATTR_nodiscard YF_API YB_PURE observer_ptr< const ValueObject > GetValuePtrOf(observer_ptr< const ValueNode >)
取指定名称指称的值的指针。
Definition: ValueNode.cpp:172
YModules.h
YSLib 核心模块配置文件。
next
tidy_ptr< slink > next
Definition: memory_resource.cpp:223
ystdex::invoke_value_or
auto invoke_value_or(_func f, _type &&p) -> decay_t< decltype(ystdex::invoke(f, *std::forward< decltype(p)>(p)))>
使用 invoke 调用非空值或取默认值。
Definition: invoke.hpp:588
YSLib::ValueNode::ThrowWrongNameFound
static YB_NORETURN void ThrowWrongNameFound(string_view)
抛出名称错误异常。
Definition: ValueNode.cpp:88
ystdex::floor_lb
size_t floor_lb(std::uintmax_t n)
计算 2 为底数的无符号整数的向下取整的对数值。
Definition: cstdint.hpp:443
YSLib::MakeIndex
YB_ATTR_nodiscard YF_API YB_PURE string MakeIndex(size_t)
转换节点大小为新的节点索引值。
Definition: ValueNode.cpp:209
ystdex::erase_all_if
void erase_all_if(_tCon &con, _tIter first, _tIter last, _fPred pred)
删除指定容器中指定区间中的或全部满足谓词的元素。
Definition: container.hpp:525
YSLib::ValueNode::operator%=
PDefHOp(ValueNode &,=, const ValueNode &node) ImplRet(ystdex ValueNode & operator%=(ValueNode &&)
复制赋值：使用参数的分配器构造的副本和交换操作。
Definition: ValueNode.h:406
YSLib::YAssert
YAssert(!(v< Deref(a)), "Value less than lower bound found.")
YSLib::RemoveHead
YF_API void RemoveHead(ValueNode::Container &) ynothrowv
移除第一个子节点。
Definition: ValueNode.cpp:186
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:405
YSLib::ValueObject
值类型对象类。
Definition: YObject.h:1068
YSLib::DecodeIndex
YB_ATTR_nodiscard YF_API size_t DecodeIndex(string_view)
解码节点名称的前缀索引。
Definition: ValueNode.cpp:235
ystdex::cpp2017::end
auto end(_tRange &c) -> decltype(c.end())
Definition: range.hpp:345
YSLib::ValueNode
值类型节点。
Definition: ValueNode.h:73
ystdex::sfmt
_tString sfmt(const typename string_traits< _tString >::value_type *fmt,...)
以 C 标准输出格式的输出 basic_string 实例的对象。
Definition: string.hpp:2028
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:165
YSLib::i
return i
Definition: YCoreUtilities.h:177
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
ystdex::ref_eq
引用等价关系仿函数。
Definition: functor.hpp:450
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:46
YSLib::str
const char * str
Definition: YException.cpp:60
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:169
YSLib::ValueNode::Container
ystdex::mapped_set< ValueNode, ystdex::less<>, MappedSetTraits, allocator_type > Container
Definition: ValueNode.h:201
YSLib::ValueNode::MoveContent
void MoveContent(ValueNode &&)
转移参数内容。
Definition: ValueNode.cpp:55
NPL::A1::name
const char * name
Definition: NPLA1.h:1876
YSLib::ValueNode::CreateRecursively
static Container CreateRecursively(_tCon &&con, _fCallable f)
Definition: ValueNode.h:657
platform::Deref
YB_PURE yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:547
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:1219
YSLib::ValueNode::insert_or_assign
iterator insert_or_assign(const_iterator hint, _tKey &&k, _tParam &&arg)
Definition: ValueNode.h:887
YSLib::AccessNodePtr
YB_ATTR_nodiscard YB_PURE observer_ptr< ValueNode > AccessNodePtr(ValueNode::Container *, const _tKey &) ynothrow
Definition: ValueNode.h:1149
platform::p
return p p
Definition: YCLib/FileSystem.h:209
YSLib::size_t
YF_API const char size_t
Definition: YException.h:149
ystdex::compose
auto compose(_func f, _func2 g, _func3 h, _funcs... args) -> decltype(ystdex::compose(ystdex::compose(f, g), h, args...))
Definition: functional.hpp:124
ystdex::path_category::node
@ node
YSLib::GetValueOf
YB_ATTR_nodiscard YF_API YB_PURE ValueObject GetValueOf(observer_ptr< const ValueNode >)
取指定名称指称的值。
Definition: ValueNode.cpp:166
YSLib::ValueNode::Value
ValueObject Value
Definition: ValueNode.h:223
YSLib::AccessNode
YB_ATTR_nodiscard YF_API YB_PURE ValueNode & AccessNode(ValueNode::Container *, const string &)
访问节点。
Definition: ValueNode.cpp:102
ystdex::call_value_or
auto call_value_or(_func f, _type &&p) -> decay_t< decltype(f(*std::forward< decltype(p)>(p)))>
调用非空值或取默认值。
Definition: deref_op.hpp:152
cstdint.hpp
ISO C 标准整数类型和相关扩展操作。