rippled
Loading...
Searching...
No Matches
beast_PropertyStream.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/beast/utility/PropertyStream.h>
21#include <xrpl/beast/utility/instrumentation.h>
22
23#include <algorithm>
24#include <iostream>
25#include <mutex>
26#include <string>
27#include <utility>
28
29namespace beast {
30
31//------------------------------------------------------------------------------
32//
33// Item
34//
35//------------------------------------------------------------------------------
36
37PropertyStream::Item::Item(Source* source) : m_source(source)
38{
39}
40
43{
44 return *m_source;
45}
46
49{
50 return &source();
51}
52
55{
56 return source();
57}
58
59//------------------------------------------------------------------------------
60//
61// Proxy
62//
63//------------------------------------------------------------------------------
64
66 : m_map(&map), m_key(key)
67{
68}
69
71 : m_map(other.m_map), m_key(other.m_key)
72{
73}
74
76{
77 std::string const s(m_ostream.str());
78 if (!s.empty())
79 m_map->add(m_key, s);
80}
81
84{
85 return m_ostream << manip;
86}
87
88//------------------------------------------------------------------------------
89//
90// Map
91//
92//------------------------------------------------------------------------------
93
94PropertyStream::Map::Map(PropertyStream& stream) : m_stream(stream)
95{
96}
97
98PropertyStream::Map::Map(Set& parent) : m_stream(parent.stream())
99{
101}
102
104 : m_stream(map.stream())
105{
106 m_stream.map_begin(key);
107}
108
110 : m_stream(stream)
111{
112 m_stream.map_begin(key);
113}
114
116{
117 m_stream.map_end();
118}
119
122{
123 return m_stream;
124}
125
126PropertyStream const&
128{
129 return m_stream;
130}
131
134{
135 return Proxy(*this, key);
136}
137
138//------------------------------------------------------------------------------
139//
140// Set
141//
142//------------------------------------------------------------------------------
143
145 : m_stream(map.stream())
146{
148}
149
151 : m_stream(stream)
152{
154}
155
157{
158 m_stream.array_end();
159}
160
163{
164 return m_stream;
165}
166
167PropertyStream const&
169{
170 return m_stream;
171}
172
173//------------------------------------------------------------------------------
174//
175// Source
176//
177//------------------------------------------------------------------------------
178
180 : m_name(name), item_(this), parent_(nullptr)
181{
182}
183
185{
186 std::lock_guard _(lock_);
187 if (parent_ != nullptr)
188 parent_->remove(*this);
189 removeAll();
190}
191
192std::string const&
194{
195 return m_name;
196}
197
198void
200{
201 std::lock(lock_, source.lock_);
204
205 XRPL_ASSERT(
206 source.parent_ == nullptr,
207 "beast::PropertyStream::Source::add : null source parent");
208 children_.push_back(source.item_);
209 source.parent_ = this;
210}
211
212void
214{
215 std::lock(lock_, child.lock_);
217 std::lock_guard lk2(child.lock_, std::adopt_lock);
218
219 XRPL_ASSERT(
220 child.parent_ == this,
221 "beast::PropertyStream::Source::remove : child parent match");
222 children_.erase(children_.iterator_to(child.item_));
223 child.parent_ = nullptr;
224}
225
226void
228{
229 std::lock_guard _(lock_);
230 for (auto iter = children_.begin(); iter != children_.end();)
231 {
232 std::lock_guard _cl((*iter)->lock_);
233 remove(*(*iter));
234 }
235}
236
237//------------------------------------------------------------------------------
238
239void
241{
242 Map map(m_name, stream);
243 onWrite(map);
244}
245
246void
248{
249 Map map(m_name, stream);
250 onWrite(map);
251
252 std::lock_guard _(lock_);
253
254 for (auto& child : children_)
255 child.source().write(stream);
256}
257
258void
260{
261 std::pair<Source*, bool> result(find(path));
262
263 if (result.first == nullptr)
264 return;
265
266 if (result.second)
267 result.first->write(stream);
268 else
269 result.first->write_one(stream);
270}
271
274{
275 bool const deep(peel_trailing_slashstar(&path));
276 bool const rooted(peel_leading_slash(&path));
277 Source* source(this);
278 if (!path.empty())
279 {
280 if (!rooted)
281 {
282 std::string const name(peel_name(&path));
283 source = find_one_deep(name);
284 if (source == nullptr)
285 return std::make_pair(nullptr, deep);
286 }
287 source = source->find_path(path);
288 }
289 return std::make_pair(source, deep);
290}
291
292bool
294{
295 if (!path->empty() && path->front() == '/')
296 {
297 *path = std::string(path->begin() + 1, path->end());
298 return true;
299 }
300 return false;
301}
302
303bool
305{
306 bool found(false);
307 if (path->empty())
308 return false;
309 if (path->back() == '*')
310 {
311 found = true;
312 path->pop_back();
313 }
314 if (!path->empty() && path->back() == '/')
315 path->pop_back();
316 return found;
317}
318
321{
322 if (path->empty())
323 return "";
324
325 std::string::const_iterator first = (*path).begin();
326 std::string::const_iterator last = (*path).end();
327 std::string::const_iterator pos = std::find(first, last, '/');
328 std::string s(first, pos);
329
330 if (pos != last)
331 *path = std::string(pos + 1, last);
332 else
333 *path = std::string();
334
335 return s;
336}
337
338// Recursive search through the whole tree until name is found
341{
342 Source* found = find_one(name);
343 if (found != nullptr)
344 return found;
345
346 std::lock_guard _(lock_);
347 for (auto& s : children_)
348 {
349 found = s.source().find_one_deep(name);
350 if (found != nullptr)
351 return found;
352 }
353 return nullptr;
354}
355
358{
359 if (path.empty())
360 return this;
361 Source* source(this);
362 do
363 {
364 std::string const name(peel_name(&path));
365 if (name.empty())
366 break;
367 source = source->find_one(name);
368 } while (source != nullptr);
369 return source;
370}
371
372// This function only looks at immediate children
373// If no immediate children match, then return nullptr
376{
377 std::lock_guard _(lock_);
378 for (auto& s : children_)
379 {
380 if (s.source().m_name == name)
381 return &s.source();
382 }
383 return nullptr;
384}
385
386void
390
391//------------------------------------------------------------------------------
392//
393// PropertyStream
394//
395//------------------------------------------------------------------------------
396
397void
398PropertyStream::add(std::string const& key, bool value)
399{
400 if (value)
401 add(key, "true");
402 else
403 add(key, "false");
404}
405
406void
407PropertyStream::add(std::string const& key, char value)
408{
409 lexical_add(key, value);
410}
411
412void
413PropertyStream::add(std::string const& key, signed char value)
414{
415 lexical_add(key, value);
416}
417
418void
419PropertyStream::add(std::string const& key, unsigned char value)
420{
421 lexical_add(key, value);
422}
423
424void
425PropertyStream::add(std::string const& key, short value)
426{
427 lexical_add(key, value);
428}
429
430void
431PropertyStream::add(std::string const& key, unsigned short value)
432{
433 lexical_add(key, value);
434}
435
436void
437PropertyStream::add(std::string const& key, int value)
438{
439 lexical_add(key, value);
440}
441
442void
443PropertyStream::add(std::string const& key, unsigned int value)
444{
445 lexical_add(key, value);
446}
447
448void
449PropertyStream::add(std::string const& key, long value)
450{
451 lexical_add(key, value);
452}
453
454void
455PropertyStream::add(std::string const& key, unsigned long value)
456{
457 lexical_add(key, value);
458}
459
460void
461PropertyStream::add(std::string const& key, long long value)
462{
463 lexical_add(key, value);
464}
465
466void
467PropertyStream::add(std::string const& key, unsigned long long value)
468{
469 lexical_add(key, value);
470}
471
472void
473PropertyStream::add(std::string const& key, float value)
474{
475 lexical_add(key, value);
476}
477
478void
479PropertyStream::add(std::string const& key, double value)
480{
481 lexical_add(key, value);
482}
483
484void
485PropertyStream::add(std::string const& key, long double value)
486{
487 lexical_add(key, value);
488}
489
490void
492{
493 if (value)
494 add("true");
495 else
496 add("false");
497}
498
499void
501{
502 lexical_add(value);
503}
504
505void
506PropertyStream::add(signed char value)
507{
508 lexical_add(value);
509}
510
511void
512PropertyStream::add(unsigned char value)
513{
514 lexical_add(value);
515}
516
517void
519{
520 lexical_add(value);
521}
522
523void
524PropertyStream::add(unsigned short value)
525{
526 lexical_add(value);
527}
528
529void
531{
532 lexical_add(value);
533}
534
535void
536PropertyStream::add(unsigned int value)
537{
538 lexical_add(value);
539}
540
541void
543{
544 lexical_add(value);
545}
546
547void
548PropertyStream::add(unsigned long value)
549{
550 lexical_add(value);
551}
552
553void
554PropertyStream::add(long long value)
555{
556 lexical_add(value);
557}
558
559void
560PropertyStream::add(unsigned long long value)
561{
562 lexical_add(value);
563}
564
565void
567{
568 lexical_add(value);
569}
570
571void
573{
574 lexical_add(value);
575}
576
577void
578PropertyStream::add(long double value)
579{
580 lexical_add(value);
581}
582
583} // namespace beast
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 find(T... args)
T is_same_v
T lock(T... args)
T make_pair(T... args)