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#include <algorithm>
23#include <iostream>
24#include <limits>
25
26namespace beast {
27
28//------------------------------------------------------------------------------
29//
30// Item
31//
32//------------------------------------------------------------------------------
33
34PropertyStream::Item::Item(Source* source) : m_source(source)
35{
36}
37
40{
41 return *m_source;
42}
43
46{
47 return &source();
48}
49
52{
53 return source();
54}
55
56//------------------------------------------------------------------------------
57//
58// Proxy
59//
60//------------------------------------------------------------------------------
61
63 : m_map(&map), m_key(key)
64{
65}
66
68 : m_map(other.m_map), m_key(other.m_key)
69{
70}
71
73{
74 std::string const s(m_ostream.str());
75 if (!s.empty())
76 m_map->add(m_key, s);
77}
78
81{
82 return m_ostream << manip;
83}
84
85//------------------------------------------------------------------------------
86//
87// Map
88//
89//------------------------------------------------------------------------------
90
91PropertyStream::Map::Map(PropertyStream& stream) : m_stream(stream)
92{
93}
94
95PropertyStream::Map::Map(Set& parent) : m_stream(parent.stream())
96{
98}
99
101 : m_stream(map.stream())
102{
103 m_stream.map_begin(key);
104}
105
107 : m_stream(stream)
108{
109 m_stream.map_begin(key);
110}
111
113{
114 m_stream.map_end();
115}
116
119{
120 return m_stream;
121}
122
123PropertyStream const&
125{
126 return m_stream;
127}
128
131{
132 return Proxy(*this, key);
133}
134
135//------------------------------------------------------------------------------
136//
137// Set
138//
139//------------------------------------------------------------------------------
140
142 : m_stream(map.stream())
143{
145}
146
148 : m_stream(stream)
149{
151}
152
154{
155 m_stream.array_end();
156}
157
160{
161 return m_stream;
162}
163
164PropertyStream const&
166{
167 return m_stream;
168}
169
170//------------------------------------------------------------------------------
171//
172// Source
173//
174//------------------------------------------------------------------------------
175
177 : m_name(name), item_(this), parent_(nullptr)
178{
179}
180
182{
183 std::lock_guard _(lock_);
184 if (parent_ != nullptr)
185 parent_->remove(*this);
186 removeAll();
187}
188
189std::string const&
191{
192 return m_name;
193}
194
195void
197{
198 std::lock(lock_, source.lock_);
199 std::lock_guard lk1(lock_, std::adopt_lock);
200 std::lock_guard lk2(source.lock_, std::adopt_lock);
201
202 XRPL_ASSERT(
203 source.parent_ == nullptr,
204 "beast::PropertyStream::Source::add : null source parent");
205 children_.push_back(source.item_);
206 source.parent_ = this;
207}
208
209void
211{
212 std::lock(lock_, child.lock_);
213 std::lock_guard lk1(lock_, std::adopt_lock);
214 std::lock_guard lk2(child.lock_, std::adopt_lock);
215
216 XRPL_ASSERT(
217 child.parent_ == this,
218 "beast::PropertyStream::Source::remove : child parent match");
219 children_.erase(children_.iterator_to(child.item_));
220 child.parent_ = nullptr;
221}
222
223void
225{
226 std::lock_guard _(lock_);
227 for (auto iter = children_.begin(); iter != children_.end();)
228 {
229 std::lock_guard _cl((*iter)->lock_);
230 remove(*(*iter));
231 }
232}
233
234//------------------------------------------------------------------------------
235
236void
238{
239 Map map(m_name, stream);
240 onWrite(map);
241}
242
243void
245{
246 Map map(m_name, stream);
247 onWrite(map);
248
249 std::lock_guard _(lock_);
250
251 for (auto& child : children_)
252 child.source().write(stream);
253}
254
255void
257{
258 std::pair<Source*, bool> result(find(path));
259
260 if (result.first == nullptr)
261 return;
262
263 if (result.second)
264 result.first->write(stream);
265 else
266 result.first->write_one(stream);
267}
268
271{
272 bool const deep(peel_trailing_slashstar(&path));
273 bool const rooted(peel_leading_slash(&path));
274 Source* source(this);
275 if (!path.empty())
276 {
277 if (!rooted)
278 {
279 std::string const name(peel_name(&path));
280 source = find_one_deep(name);
281 if (source == nullptr)
282 return std::make_pair(nullptr, deep);
283 }
284 source = source->find_path(path);
285 }
286 return std::make_pair(source, deep);
287}
288
289bool
291{
292 if (!path->empty() && path->front() == '/')
293 {
294 *path = std::string(path->begin() + 1, path->end());
295 return true;
296 }
297 return false;
298}
299
300bool
302{
303 bool found(false);
304 if (path->empty())
305 return false;
306 if (path->back() == '*')
307 {
308 found = true;
309 path->pop_back();
310 }
311 if (!path->empty() && path->back() == '/')
312 path->pop_back();
313 return found;
314}
315
318{
319 if (path->empty())
320 return "";
321
322 std::string::const_iterator first = (*path).begin();
323 std::string::const_iterator last = (*path).end();
324 std::string::const_iterator pos = std::find(first, last, '/');
325 std::string s(first, pos);
326
327 if (pos != last)
328 *path = std::string(pos + 1, last);
329 else
330 *path = std::string();
331
332 return s;
333}
334
335// Recursive search through the whole tree until name is found
338{
339 Source* found = find_one(name);
340 if (found != nullptr)
341 return found;
342
343 std::lock_guard _(lock_);
344 for (auto& s : children_)
345 {
346 found = s.source().find_one_deep(name);
347 if (found != nullptr)
348 return found;
349 }
350 return nullptr;
351}
352
355{
356 if (path.empty())
357 return this;
358 Source* source(this);
359 do
360 {
361 std::string const name(peel_name(&path));
362 if (name.empty())
363 break;
364 source = source->find_one(name);
365 } while (source != nullptr);
366 return source;
367}
368
369// This function only looks at immediate children
370// If no immediate children match, then return nullptr
373{
374 std::lock_guard _(lock_);
375 for (auto& s : children_)
376 {
377 if (s.source().m_name == name)
378 return &s.source();
379 }
380 return nullptr;
381}
382
383void
385{
386}
387
388//------------------------------------------------------------------------------
389//
390// PropertyStream
391//
392//------------------------------------------------------------------------------
393
394void
395PropertyStream::add(std::string const& key, bool value)
396{
397 if (value)
398 add(key, "true");
399 else
400 add(key, "false");
401}
402
403void
404PropertyStream::add(std::string const& key, char value)
405{
406 lexical_add(key, value);
407}
408
409void
410PropertyStream::add(std::string const& key, signed char value)
411{
412 lexical_add(key, value);
413}
414
415void
416PropertyStream::add(std::string const& key, unsigned char value)
417{
418 lexical_add(key, value);
419}
420
421void
422PropertyStream::add(std::string const& key, short value)
423{
424 lexical_add(key, value);
425}
426
427void
428PropertyStream::add(std::string const& key, unsigned short value)
429{
430 lexical_add(key, value);
431}
432
433void
434PropertyStream::add(std::string const& key, int value)
435{
436 lexical_add(key, value);
437}
438
439void
440PropertyStream::add(std::string const& key, unsigned int value)
441{
442 lexical_add(key, value);
443}
444
445void
446PropertyStream::add(std::string const& key, long value)
447{
448 lexical_add(key, value);
449}
450
451void
452PropertyStream::add(std::string const& key, unsigned long value)
453{
454 lexical_add(key, value);
455}
456
457void
458PropertyStream::add(std::string const& key, long long value)
459{
460 lexical_add(key, value);
461}
462
463void
464PropertyStream::add(std::string const& key, unsigned long long value)
465{
466 lexical_add(key, value);
467}
468
469void
470PropertyStream::add(std::string const& key, float value)
471{
472 lexical_add(key, value);
473}
474
475void
476PropertyStream::add(std::string const& key, double value)
477{
478 lexical_add(key, value);
479}
480
481void
482PropertyStream::add(std::string const& key, long double value)
483{
484 lexical_add(key, value);
485}
486
487void
489{
490 if (value)
491 add("true");
492 else
493 add("false");
494}
495
496void
498{
499 lexical_add(value);
500}
501
502void
503PropertyStream::add(signed char value)
504{
505 lexical_add(value);
506}
507
508void
509PropertyStream::add(unsigned char value)
510{
511 lexical_add(value);
512}
513
514void
516{
517 lexical_add(value);
518}
519
520void
521PropertyStream::add(unsigned short value)
522{
523 lexical_add(value);
524}
525
526void
528{
529 lexical_add(value);
530}
531
532void
533PropertyStream::add(unsigned int value)
534{
535 lexical_add(value);
536}
537
538void
540{
541 lexical_add(value);
542}
543
544void
545PropertyStream::add(unsigned long value)
546{
547 lexical_add(value);
548}
549
550void
551PropertyStream::add(long long value)
552{
553 lexical_add(value);
554}
555
556void
557PropertyStream::add(unsigned long long value)
558{
559 lexical_add(value);
560}
561
562void
564{
565 lexical_add(value);
566}
567
568void
570{
571 lexical_add(value);
572}
573
574void
575PropertyStream::add(long double value)
576{
577 lexical_add(value);
578}
579
580} // namespace beast
T begin(T... args)
Map(PropertyStream &stream)
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::recursive_mutex lock_
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 lock(T... args)
T make_pair(T... args)