rippled
Loading...
Searching...
No Matches
beast_PropertyStream.cpp
1#include <xrpl/beast/utility/PropertyStream.h>
2#include <xrpl/beast/utility/instrumentation.h>
3
4#include <algorithm>
5#include <iostream>
6#include <mutex>
7#include <string>
8#include <utility>
9
10namespace beast {
11
12//------------------------------------------------------------------------------
13//
14// Item
15//
16//------------------------------------------------------------------------------
17
18PropertyStream::Item::Item(Source* source) : ListNode(), m_source(source)
19{
20}
21
24{
25 return *m_source;
26}
27
30{
31 return &source();
32}
33
36{
37 return source();
38}
39
40//------------------------------------------------------------------------------
41//
42// Proxy
43//
44//------------------------------------------------------------------------------
45
46PropertyStream::Proxy::Proxy(Map const& map, std::string const& key) : m_map(&map), m_key(key)
47{
48}
49
50PropertyStream::Proxy::Proxy(Proxy const& other) : m_map(other.m_map), m_key(other.m_key)
51{
52}
53
55{
56 std::string const s(m_ostream.str());
57 if (!s.empty())
58 m_map->add(m_key, s);
59}
60
63{
64 return m_ostream << manip;
65}
66
67//------------------------------------------------------------------------------
68//
69// Map
70//
71//------------------------------------------------------------------------------
72
73PropertyStream::Map::Map(PropertyStream& stream) : m_stream(stream)
74{
75}
76
77PropertyStream::Map::Map(Set& parent) : m_stream(parent.stream())
78{
80}
81
82PropertyStream::Map::Map(std::string const& key, Map& map) : m_stream(map.stream())
83{
85}
86
87PropertyStream::Map::Map(std::string const& key, PropertyStream& stream) : m_stream(stream)
88{
90}
91
93{
94 m_stream.map_end();
95}
96
99{
100 return m_stream;
101}
102
103PropertyStream const&
105{
106 return m_stream;
107}
108
111{
112 return Proxy(*this, key);
113}
114
115//------------------------------------------------------------------------------
116//
117// Set
118//
119//------------------------------------------------------------------------------
120
121PropertyStream::Set::Set(std::string const& key, Map& map) : m_stream(map.stream())
122{
124}
125
126PropertyStream::Set::Set(std::string const& key, PropertyStream& stream) : m_stream(stream)
127{
129}
130
132{
133 m_stream.array_end();
134}
135
138{
139 return m_stream;
140}
141
142PropertyStream const&
144{
145 return m_stream;
146}
147
148//------------------------------------------------------------------------------
149//
150// Source
151//
152//------------------------------------------------------------------------------
153
154PropertyStream::Source::Source(std::string const& name) : m_name(name), item_(this)
155{
156}
157
159{
160 std::lock_guard const _(lock_);
161 if (parent_ != nullptr)
162 parent_->remove(*this);
163 removeAll();
164}
165
166std::string const&
168{
169 return m_name;
170}
171
172void
174{
175 std::lock(lock_, source.lock_);
176 std::lock_guard const lk1(lock_, std::adopt_lock);
177 std::lock_guard const lk2(source.lock_, std::adopt_lock);
178
179 XRPL_ASSERT(
180 source.parent_ == nullptr, "beast::PropertyStream::Source::add : null source parent");
181 children_.push_back(source.item_);
182 source.parent_ = this;
183}
184
185void
187{
188 std::lock(lock_, child.lock_);
189 std::lock_guard const lk1(lock_, std::adopt_lock);
190 std::lock_guard const lk2(child.lock_, std::adopt_lock);
191
192 XRPL_ASSERT(
193 child.parent_ == this, "beast::PropertyStream::Source::remove : child parent match");
194 children_.erase(children_.iterator_to(child.item_));
195 child.parent_ = nullptr;
196}
197
198void
200{
201 std::lock_guard const _(lock_);
202 for (auto iter = children_.begin(); iter != children_.end();)
203 {
204 std::lock_guard const _cl((*iter)->lock_);
205 remove(*(*iter));
206 }
207}
208
209//------------------------------------------------------------------------------
210
211void
213{
214 Map map(m_name, stream);
215 onWrite(map);
216}
217
218void
220{
221 Map map(m_name, stream);
222 onWrite(map);
223
224 std::lock_guard const _(lock_);
225
226 for (auto& child : children_)
227 child.source().write(stream);
228}
229
230void
232{
233 std::pair<Source*, bool> result(find(path));
234
235 if (result.first == nullptr)
236 return;
237
238 if (result.second)
239 {
240 result.first->write(stream);
241 }
242 else
243 {
244 result.first->write_one(stream);
245 }
246}
247
250{
251 bool const deep(peel_trailing_slashstar(&path));
252 bool const rooted(peel_leading_slash(&path));
253 Source* source(this);
254 if (!path.empty())
255 {
256 if (!rooted)
257 {
258 std::string const name(peel_name(&path));
259 source = find_one_deep(name);
260 if (source == nullptr)
261 return std::make_pair(nullptr, deep);
262 }
263 source = source->find_path(path);
264 }
265 return std::make_pair(source, deep);
266}
267
268bool
270{
271 if (!path->empty() && path->front() == '/')
272 {
273 *path = std::string(path->begin() + 1, path->end());
274 return true;
275 }
276 return false;
277}
278
279bool
281{
282 bool found(false);
283 if (path->empty())
284 return false;
285 if (path->back() == '*')
286 {
287 found = true;
288 path->pop_back();
289 }
290 if (!path->empty() && path->back() == '/')
291 path->pop_back();
292 return found;
293}
294
297{
298 if (path->empty())
299 return "";
300
301 std::string::const_iterator const first = (*path).begin();
302 std::string::const_iterator const last = (*path).end();
303 std::string::const_iterator const pos = std::find(first, last, '/');
304 std::string s(first, pos);
305
306 if (pos != last)
307 {
308 *path = std::string(pos + 1, last);
309 }
310 else
311 {
312 *path = std::string();
313 }
314
315 return s;
316}
317
318// Recursive search through the whole tree until name is found
321{
322 Source* found = find_one(name); // NOLINT(misc-const-correctness)
323 if (found != nullptr)
324 return found;
325
326 std::lock_guard const _(lock_);
327 for (auto& s : children_)
328 {
329 found = s.source().find_one_deep(name);
330 if (found != nullptr)
331 return found;
332 }
333 return nullptr;
334}
335
338{
339 if (path.empty())
340 return this;
341 Source* source(this);
342 do
343 {
344 std::string const name(peel_name(&path));
345 if (name.empty())
346 break;
347 source = source->find_one(name);
348 } while (source != nullptr);
349 return source;
350}
351
352// This function only looks at immediate children
353// If no immediate children match, then return nullptr
356{
357 std::lock_guard const _(lock_);
358 for (auto& s : children_)
359 {
360 if (s.source().m_name == name)
361 return &s.source();
362 }
363 return nullptr;
364}
365
366void
370
371//------------------------------------------------------------------------------
372//
373// PropertyStream
374//
375//------------------------------------------------------------------------------
376
377void
378PropertyStream::add(std::string const& key, bool value)
379{
380 if (value)
381 {
382 add(key, "true");
383 }
384 else
385 {
386 add(key, "false");
387 }
388}
389
390void
391PropertyStream::add(std::string const& key, char value)
392{
393 lexical_add(key, value);
394}
395
396void
397PropertyStream::add(std::string const& key, signed char value)
398{
399 lexical_add(key, value);
400}
401
402void
403PropertyStream::add(std::string const& key, unsigned char value)
404{
405 lexical_add(key, value);
406}
407
408void
409PropertyStream::add(std::string const& key, short value)
410{
411 lexical_add(key, value);
412}
413
414void
415PropertyStream::add(std::string const& key, unsigned short value)
416{
417 lexical_add(key, value);
418}
419
420void
421PropertyStream::add(std::string const& key, int value)
422{
423 lexical_add(key, value);
424}
425
426void
427PropertyStream::add(std::string const& key, unsigned int value)
428{
429 lexical_add(key, value);
430}
431
432void
433PropertyStream::add(std::string const& key, long value)
434{
435 lexical_add(key, value);
436}
437
438void
439PropertyStream::add(std::string const& key, unsigned long value)
440{
441 lexical_add(key, value);
442}
443
444void
445PropertyStream::add(std::string const& key, long long value)
446{
447 lexical_add(key, value);
448}
449
450void
451PropertyStream::add(std::string const& key, unsigned long long value)
452{
453 lexical_add(key, value);
454}
455
456void
457PropertyStream::add(std::string const& key, float value)
458{
459 lexical_add(key, value);
460}
461
462void
463PropertyStream::add(std::string const& key, double value)
464{
465 lexical_add(key, value);
466}
467
468void
469PropertyStream::add(std::string const& key, long double value)
470{
471 lexical_add(key, value);
472}
473
474void
476{
477 if (value)
478 {
479 add("true");
480 }
481 else
482 {
483 add("false");
484 }
485}
486
487void
489{
490 lexical_add(value);
491}
492
493void
494PropertyStream::add(signed char value)
495{
496 lexical_add(value);
497}
498
499void
500PropertyStream::add(unsigned char value)
501{
502 lexical_add(value);
503}
504
505void
507{
508 lexical_add(value);
509}
510
511void
512PropertyStream::add(unsigned short value)
513{
514 lexical_add(value);
515}
516
517void
519{
520 lexical_add(value);
521}
522
523void
524PropertyStream::add(unsigned int value)
525{
526 lexical_add(value);
527}
528
529void
531{
532 lexical_add(value);
533}
534
535void
536PropertyStream::add(unsigned long value)
537{
538 lexical_add(value);
539}
540
541void
542PropertyStream::add(long long value)
543{
544 lexical_add(value);
545}
546
547void
548PropertyStream::add(unsigned long long value)
549{
550 lexical_add(value);
551}
552
553void
555{
556 lexical_add(value);
557}
558
559void
561{
562 lexical_add(value);
563}
564
565void
566PropertyStream::add(long double value)
567{
568 lexical_add(value);
569}
570
571} // namespace beast
T back(T... args)
T begin(T... args)
Proxy operator[](std::string const &key)
Proxy(Map const &map, std::string const &key)
std::ostream & operator<<(std::ostream &manip(std::ostream &)) const
Set(std::string const &key, Map &map)
Subclasses can be called to write to a stream and have children.
static bool peel_leading_slash(std::string *path)
PropertyStream::Source * find_one(std::string const &name)
void removeAll()
Remove all child sources from this Source.
std::pair< Source *, bool > find(std::string path)
Parse the dot-delimited Source path and return the result.
void remove(Source &child)
Remove a child source from this Source.
std::string const & name() const
Returns the name of this source.
void add(Source &source)
Add a child source.
PropertyStream::Source * find_path(std::string path)
void write_one(PropertyStream &stream)
Write only this Source to the stream.
Source * find_one_deep(std::string const &name)
void write(PropertyStream &stream)
write this source and all its children recursively to the stream.
static std::string peel_name(std::string *path)
static bool peel_trailing_slashstar(std::string *path)
virtual void onWrite(Map &)
Subclass override.
Abstract stream with RAII containers that produce a property tree.
virtual void add(std::string const &key, std::string const &value)=0
virtual void map_begin()=0
virtual void array_begin()=0
void lexical_add(std::string const &key, Value value)
T empty(T... args)
T end(T... args)
T find(T... args)
T front(T... args)
T is_same_v
T lock(T... args)
T make_pair(T... args)
T pop_back(T... args)