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 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);
541 ARCCORE_FATAL(
"Impossible de lire le fichier JSON '{0}'", filename);
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 <<
"AVERTISSEMENT: paramètre inconnu " << 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 <<
"AVERTISSEMENT: paramètre inconnu " << 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(
"Le paramètre dans put() doit avoir le format \"clé=valeur\" (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: paramètre inconnu " << 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 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, Int16 flags=ParseNoFlags)
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.
constexpr bool empty() const ARCCORE_NOEXCEPT
Vrai si la chaîne est nulle ou vide.
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.