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 std::cout <<
"KEY='" << key <<
"'\n";
422 if (c.second.children.empty()) {
423 writeKeyValue(w, key, c.second.has_data ? c.second.data : std::string());
428 writeJsonNode(w, c.second);
441namespace Arcane::Alina
449: m_property_tree(new PropertyTreeImpl())
458PropertyTree(
const PropertyTree& rhs)
465 m_property_tree = rhs.m_property_tree;
477 delete &toImpl(
this);
483PropertyTree PropertyTree::
484get_child_empty(
const std::string& path)
const
488 p.m_property_tree =
const_cast<PropertyTreeImpl*
>(child ? child : &detail::empty_ptree());
497erase(
const char* name)
499 return toImpl(
this).eraseChild(name);
506count(
const char* name)
const
508 return toImpl(
this).count(name);
515read_json(
const std::string& filename)
517 std::ifstream is(filename, std::ios::binary);
520 std::string content((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
523 Span<const Byte> bytes(
reinterpret_cast<const Byte*
>(content.data()), content.size());
524 doc.
parse(bytes, StringView(filename));
526 toImpl(
this) = nodeFromJson(doc.
root());
532Int32 PropertyTree::get(
const char* param_type,
Int32 default_value)
const
534 const std::string* s = toImpl(
this).getValue(param_type);
536 return default_value;
537 return parseInt32(*s, param_type);
539Int64 PropertyTree::get(
const char* param_type,
Int64 default_value)
const
541 const std::string* s = toImpl(
this).getValue(param_type);
543 return default_value;
544 return parseInteger(*s, param_type);
546double PropertyTree::get(
const char* param_type,
double default_value)
const
548 const std::string* s = toImpl(
this).getValue(param_type);
550 return default_value;
551 return parseReal(*s, param_type);
553double* PropertyTree::get(
const char* param_type,
double* default_value)
const
555 const std::string* s = toImpl(
this).getValue(param_type);
557 return default_value;
558 return static_cast<double*
>(parsePointer(*s, param_type));
560void* PropertyTree::get(
const char* param_type,
void* default_value)
const
562 const std::string* s = toImpl(
this).getValue(param_type);
564 return default_value;
565 return parsePointer(*s, param_type);
567std::string PropertyTree::get(
const char* param_type,
const std::string& default_value)
const
569 const std::string* s = toImpl(
this).getValue(param_type);
571 return default_value;
575void PropertyTree::put(
const std::string& path,
Int32 value)
577 toImpl(
this).put(path, std::to_string(value));
579void PropertyTree::put(
const std::string& path,
Int64 value)
581 toImpl(
this).put(path, std::to_string(value));
583void PropertyTree::put(
const std::string& path,
double value)
585 toImpl(
this).put(path, realToString(value));
587void PropertyTree::put(
const std::string& path,
const std::string& value)
589 toImpl(
this).put(path, value);
591void PropertyTree::put(
const std::string& path,
double* value)
593 toImpl(
this).put(path, pointerToString(value));
595void PropertyTree::put(
const std::string& path,
void* value)
597 toImpl(
this).put(path, pointerToString(value));
604_addChild(
const std::string& path,
const char* name,
605 const PropertyTree& obj)
607 toImpl(
this).addChild(std::string(path) + name, toImpl(obj));
614check_params(
const std::set<std::string>& names)
const
616 const auto& p = toImpl(
this);
617 bool has_error =
false;
618 for (
const auto& n : names) {
620 ARCCORE_ALINA_PARAM_MISSING(n);
623 for (
const auto& v : p.children) {
624 if (!names.count(v.first)) {
625 std::cerr <<
"WARNING: unknown parameter " << v.first <<
"\n";
637check_params(
const std::set<std::string>& names,
638 const std::set<std::string>& opt_names)
const
640 const auto& p = toImpl(
this);
641 bool has_error =
false;
643 for (
const auto& n : names) {
645 ARCCORE_ALINA_PARAM_MISSING(n);
648 for (
const auto& n : opt_names) {
650 ARCCORE_ALINA_PARAM_MISSING(n);
653 for (
const auto& v : p.children) {
654 if (!names.count(v.first) && !opt_names.count(v.first)) {
655 std::cerr <<
"WARNING: unknown parameter " << v.first <<
"\n";
667putKeyValue(
const std::string& param)
669 size_t eq_pos = param.find(
'=');
670 if (eq_pos == std::string::npos)
671 ARCCORE_FATAL(
"param in put() should have \"key=value\" format (param='{0}')", param);
672 toImpl(
this).put(param.substr(0, eq_pos), param.substr(eq_pos + 1));
678detail::empty_params::
679empty_params(
const PropertyTree& ap)
681 const auto& p = toImpl(ap);
682 for (
const auto& v : p.children) {
683 std::cerr <<
"Alina: unknown parameter " << v.first <<
"\n";
690std::ostream& operator<<(std::ostream& o,
const PropertyTree& obj)
692 JSONWriter writer(JSONWriter::FormatFlags::None);
693 writeJsonNode(writer, toImpl(obj));
694 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.
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.