14#include "arccore/alina/AlinaUtils.h"
16#include "arccore/base/Convert.h"
18#include "arccore/common/JSONReader.h"
19#include "arccore/common/JSONWriter.h"
21#include "arccore/alina/CSRMatrixView.h"
30namespace Arcane::Alina::detail
50 bool has_data =
false;
51 std::list<std::pair<std::string, PropertyTreeImpl>> children;
55 bool empty()
const {
return !has_data && children.empty(); }
62 for (
auto& c : children)
69 for (
const auto& c : children)
76 size_t count(
const std::string& name)
const
79 for (
const auto& c : children)
88 auto it = children.begin();
89 while (it != children.end()) {
90 if (it->first == name) {
108 for (
const auto& part : _splitPath(path)) {
120 for (
const auto& part : _splitPath(path)) {
129 const std::string*
getValue(
const std::string& path)
const
132 if (n && n->has_data)
141 void put(
const std::string& path,
const std::string& value)
152 std::vector<std::string> parts = _splitPath(path);
155 std::string parent_path;
156 for (
size_t i = 0; i + 1 < parts.size(); ++i) {
157 if (!parent_path.empty())
159 parent_path += parts[i];
162 parent->children.emplace_back(std::move(parts.back()), subtree);
167 static std::vector<std::string> _splitPath(
const std::string& path)
169 std::vector<std::string> parts;
171 for (
char c : path) {
173 parts.push_back(current);
180 parts.push_back(current);
188 for (
const auto& part : _splitPath(path)) {
201const PropertyTreeImpl& empty_ptree()
203 static const PropertyTreeImpl p;
233using namespace Arcane::Alina;
237 return detail::PropertyWrapper::toImpl(p);
241 return detail::PropertyWrapper::toImpl(*p);
245 return detail::PropertyWrapper::toImpl(*p);
251std::string realToString(
double v)
254 auto res = std::to_chars(buf, buf +
sizeof(buf), v);
255 return std::string(buf, res.ptr);
258bool tryParseInt64(
const std::string& s, Int64& v)
267bool tryParseDouble(
const std::string& s,
double& v)
278Int64 parseInteger(
const std::string& s,
const char* name)
285 if (!tryParseInt64(s, v))
286 ARCCORE_FATAL(
"Can not convert value '{0}' to integer for parameter '{1}'", s, name);
290Int32 parseInt32(
const std::string& s,
const char* name)
292 Int64 v = parseInteger(s, name);
293 if (v <
static_cast<Int64
>(std::numeric_limits<Int32>::min()) ||
294 v >
static_cast<Int64
>(std::numeric_limits<Int32>::max()))
295 ARCCORE_FATAL(
"Value '{0}' is out of range for parameter '{1}'", s, name);
296 return static_cast<Int32
>(v);
299double parseReal(
const std::string& s,
const char* name)
306 if (!tryParseDouble(s, v))
307 ARCCORE_FATAL(
"Can not convert value '{0}' to real for parameter '{1}'", s, name);
311void* parsePointer(
const std::string& s,
const char* name)
318 ARCCORE_FATAL(
"Can not convert value '{0}' to pointer for parameter '{1}'", s, name);
319 return reinterpret_cast<void*
>(
static_cast<std::uintptr_t
>(*x));
322std::string pointerToString(
const void* p)
324 std::ostringstream ostr;
325 ostr <<
"0x" << std::hex << reinterpret_cast<std::uintptr_t>(p);
332PropertyTreeImpl nodeFromJson(
const JSONValue& v)
336 for (
const auto& kv : v.keyValueChildren()) {
337 std::string name(kv.name().toStdStringView());
338 n.children.emplace_back(std::move(name), nodeFromJson(kv.value()));
341 else if (v.isArray()) {
342 for (
const auto& e : v.valueAsArray())
343 n.children.emplace_back(
"", nodeFromJson(e));
359 if (u <=
static_cast<UInt64>(std::numeric_limits<Int64>::max()))
360 n.data = std::to_string(
static_cast<Int64
>(u));
362 n.data = realToString(
static_cast<double>(u));
387 if (tryParseInt64(s, i)) {
392 if (tryParseDouble(s, d)) {
399void writeJsonNode(
JSONWriter& w,
const PropertyTreeImpl& n)
401 if (n.children.empty()) {
405 bool is_array =
true;
406 for (
const auto& c : n.children)
407 if (!c.first.empty()) {
413 for (
const auto& c : n.children)
414 writeJsonNode(w, c.second);
419 for (
const auto& c : n.children) {
421 if (c.second.children.empty()) {
422 writeKeyValue(w, key, c.second.has_data ? c.second.data : std::string());
427 writeJsonNode(w, c.second);
440namespace Arcane::Alina
447PropertyTree(PropertyTreeImpl* p,
bool is_own)
464PropertyTree(
const PropertyTree& rhs)
471 m_property_tree = rhs.m_property_tree;
479PropertyTree& PropertyTree::
480operator=(
const PropertyTree& rhs)
486 delete &toImpl(
this);
487 m_property_tree = new_property_tree;
499 delete &toImpl(
this);
505PropertyTree PropertyTree::
506get_child_empty(
const std::string& path)
const
510 child = &detail::empty_ptree();
519erase(
const char* name)
521 return toImpl(
this).eraseChild(name);
528count(
const char* name)
const
530 return toImpl(
this).count(name);
537read_json(
const std::string& filename)
539 std::ifstream is(filename, std::ios::binary);
542 std::string content((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
545 Span<const Byte> bytes(
reinterpret_cast<const Byte*
>(content.data()), content.size());
546 doc.
parse(bytes, StringView(filename));
548 toImpl(
this) = nodeFromJson(doc.
root());
554Int32 PropertyTree::get(
const char* param_type,
Int32 default_value)
const
556 const std::string* s = toImpl(
this).getValue(param_type);
558 return default_value;
559 return parseInt32(*s, param_type);
561Int64 PropertyTree::get(
const char* param_type,
Int64 default_value)
const
563 const std::string* s = toImpl(
this).getValue(param_type);
565 return default_value;
566 return parseInteger(*s, param_type);
568double PropertyTree::get(
const char* param_type,
double default_value)
const
570 const std::string* s = toImpl(
this).getValue(param_type);
572 return default_value;
573 return parseReal(*s, param_type);
575double* PropertyTree::get(
const char* param_type,
double* default_value)
const
577 const std::string* s = toImpl(
this).getValue(param_type);
579 return default_value;
580 return static_cast<double*
>(parsePointer(*s, param_type));
582void* PropertyTree::get(
const char* param_type,
void* default_value)
const
584 const std::string* s = toImpl(
this).getValue(param_type);
586 return default_value;
587 return parsePointer(*s, param_type);
589std::string PropertyTree::get(
const char* param_type,
const std::string& default_value)
const
591 const std::string* s = toImpl(
this).getValue(param_type);
593 return default_value;
597void PropertyTree::put(
const std::string& path,
Int32 value)
599 toImpl(
this).put(path, std::to_string(value));
601void PropertyTree::put(
const std::string& path,
Int64 value)
603 toImpl(
this).put(path, std::to_string(value));
605void PropertyTree::put(
const std::string& path,
double value)
607 toImpl(
this).put(path, realToString(value));
609void PropertyTree::put(
const std::string& path,
const std::string& value)
611 toImpl(
this).put(path, value);
613void PropertyTree::put(
const std::string& path,
double* value)
615 toImpl(
this).put(path, pointerToString(value));
617void PropertyTree::put(
const std::string& path,
void* value)
619 toImpl(
this).put(path, pointerToString(value));
626_addChild(
const std::string& path,
const char* name,
627 const PropertyTree& obj)
629 toImpl(
this).addChild(std::string(path) + name, toImpl(obj));
636check_params(
const std::set<std::string>& names)
const
638 const auto& p = toImpl(
this);
639 bool has_error =
false;
640 for (
const auto& n : names) {
642 ARCCORE_ALINA_PARAM_MISSING(n);
645 for (
const auto& v : p.children) {
646 if (!names.count(v.first)) {
647 std::cerr <<
"WARNING: unknown parameter " << v.first <<
"\n";
659check_params(
const std::set<std::string>& names,
660 const std::set<std::string>& opt_names)
const
662 const auto& p = toImpl(
this);
663 bool has_error =
false;
665 for (
const auto& n : names) {
667 ARCCORE_ALINA_PARAM_MISSING(n);
670 for (
const auto& n : opt_names) {
672 ARCCORE_ALINA_PARAM_MISSING(n);
675 for (
const auto& v : p.children) {
676 if (!names.count(v.first) && !opt_names.count(v.first)) {
677 std::cerr <<
"WARNING: unknown parameter " << v.first <<
"\n";
689putKeyValue(
const std::string& param)
691 size_t eq_pos = param.find(
'=');
692 if (eq_pos == std::string::npos)
693 ARCCORE_FATAL(
"param in put() should have \"key=value\" format (param='{0}')", param);
694 toImpl(
this).put(param.substr(0, eq_pos), param.substr(eq_pos + 1));
700detail::empty_params::
701empty_params(
const PropertyTree& ap)
703 const auto& p = toImpl(ap);
704 for (
const auto& v : p.children) {
705 std::cerr <<
"Alina: unknown parameter " << v.first <<
"\n";
712std::ostream& operator<<(std::ostream& o,
const PropertyTree& obj)
714 JSONWriter writer(JSONWriter::FormatFlags::None);
715 writeJsonNode(writer, toImpl(obj));
716 o << writer.getBuffer();
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Class to store parameters as a hierarchical key/value tree.
Minimal hierarchical property tree with string leaf values.
PropertyTreeImpl * findChild(const std::string &name)
First direct child with name name or nullptr if not found.
size_t count(const std::string &name) const
Number of direct children with name name.
void put(const std::string &path, const std::string &value)
const std::string * getValue(const std::string &path) const
Leaf value at the '.'-separated path path or nullptr if not found.
PropertyTreeImpl * findNode(const std::string &path)
void addChild(const std::string &path, const PropertyTreeImpl &subtree)
PropertyTreeImpl * _createNode(const std::string &path)
Node at the '.'-separated path path, creating intermediate nodes.
bool eraseChild(const std::string &name)
Remove the first direct child with name name.
static std::optional< T > tryParse(StringView s)
Converts s to type T.
void parse(Span< const Byte > bytes, Int16 flags=ParseNoFlags)
Reads the file in UTF-8 format.
JSONValue root() const
Root element.
bool isUint64() const
True if the value is an integer in the 'UInt64' range.
UInt64 valueAsUInt64() const
Value in UInt64 format. Returns 0 if 'null()' is true.
Real valueAsReal() const
Value in Real format. Returns 0.0 if 'null()' is true.
bool valueAsBool() const
Value in boolean format. Returns false if 'null()' is true.
Int64 valueAsInt64() const
Value in Int64 format. Returns 0 if 'null()' is true.
bool isInt64() const
True if the value is an integer in the 'Int64' range.
StringView valueAsStringView() const
Value in StringView format. The string is empty if 'null()' is true.
bool isBool() const
True if the value is a boolean.
bool isString() const
True if the value is a string.
bool isNumber() const
True if the value is a number.
View of a UTF-8 character string.
std::string_view toStdStringView() const ARCCORE_NOEXCEPT
Returns an STL view of the current view.
constexpr bool empty() const ARCCORE_NOEXCEPT
True if the string is null or empty.
Unicode character string.
double toDouble(Real r)
Converts a Real to double.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::uint64_t UInt64
Unsigned integer type of 64 bits.
std::int64_t Int64
Signed integer type of 64 bits.
unsigned char Byte
Type of a byte.
std::int32_t Int32
Signed integer type of 32 bits.