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(
"Impossible de convertir la valeur '{0}' en entier pour le paramètre '{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(
"La valeur '{0}' est hors plage pour le paramètre '{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(
"Impossible de convertir la valeur '{0}' en réel pour le paramètre '{1}'", s, name);
311void* parsePointer(
const std::string& s,
const char* name)
318 ARCCORE_FATAL(
"Impossible de convertir la valeur '{0}' en pointeur pour le paramètre '{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);
519 ARCCORE_FATAL(
"Impossible de lire le fichier JSON '{0}'", filename);
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 <<
"AVERTISSEMENT: paramètre inconnu " << 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 <<
"AVERTISSEMENT: paramètre inconnu " << 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(
"Le paramètre dans put() doit avoir le format \"clé=valeur\" (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: paramètre inconnu " << 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 envoyant une exception FatalErrorException.
Classe pour stocker les paramètres sous forme d'arbre hiérarchique clé/valeur.
Arbre de propriétés hiérarchique minimal avec valeurs de feuilles en chaîne de caractères.
PropertyTreeImpl * findChild(const std::string &name)
Premier enfant direct avec le nom name ou nullptr s'il n'est pas trouvé.
size_t count(const std::string &name) const
Nombre d'enfants directs avec le nom name.
void put(const std::string &path, const std::string &value)
const std::string * getValue(const std::string &path) const
Valeur de feuille au chemin séparé par '.' path ou nullptr s'il n'est pas trouvé.
PropertyTreeImpl * findNode(const std::string &path)
void addChild(const std::string &path, const PropertyTreeImpl &subtree)
PropertyTreeImpl * _createNode(const std::string &path)
Nœud au chemin séparé par '.' path, créant les nœuds intermédiaires.
bool eraseChild(const std::string &name)
Supprime le premier enfant direct avec le nom name.
static std::optional< T > tryParse(StringView s)
Convertit s au type T.
void parse(Span< const Byte > bytes)
Lit le fichier au format UTF-8.
JSONValue root() const
Elément racine.
Représente une valeur JSON.
bool isUint64() const
Vrai si la valeur est un entier dans la plage 'UInt64'.
UInt64 valueAsUInt64() const
Valeur sous forme de UInt64. Retourn 0 si 'null()' est vrai.
Real valueAsReal() const
Valeur sous forme de Real. Retourn 0.0 si 'null()' est vrai.
bool valueAsBool() const
Valeur sous forme de booléen. Retourn false si 'null()' est vrai.
Int64 valueAsInt64() const
Valeur sous forme de Int64. Retourn 0 si 'null()' est vrai.
bool isInt64() const
Vrai si la valeur est un entier dans la plage 'Int64'.
StringView valueAsStringView() const
Valeur sous forme de StringView. La chaîne est vide si 'null()' est vrai.
bool isBool() const
Vrai si la valeur est un booléen.
bool isString() const
Vrai si la valeur est une chaîne de caractères.
bool isNumber() const
Vrai si la valeur est un nombre.
Vue sur une chaîne de caractères UTF-8.
std::string_view toStdStringView() const ARCCORE_NOEXCEPT
Retourne une vue de la STL de la vue actuelle.
Chaîne de caractères unicode.
double toDouble(Real r)
Convertit un Real en double.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::uint64_t UInt64
Type entier non signé sur 64 bits.
std::int64_t Int64
Type entier signé sur 64 bits.
unsigned char Byte
Type d'un octet.
std::int32_t Int32
Type entier signé sur 32 bits.