Logo ROOT  
Reference Guide
RAttrMap.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
3 * All rights reserved. *
4 * *
5 * For the licensing terms see $ROOTSYS/LICENSE. *
6 * For the list of contributors see $ROOTSYS/README/CREDITS. *
7 *************************************************************************/
8
9#include "ROOT/RAttrMap.hxx"
10
11#include "ROOT/RAttrBase.hxx"
12#include "ROOT/RLogger.hxx"
13
14#include <string>
15#include <algorithm>
16#include <limits>
17
18using namespace ROOT::Experimental;
19
20using namespace std::string_literals;
21
22template<> bool RAttrMap::Value_t::Get<bool>() const { return GetBool(); }
23template<> int RAttrMap::Value_t::Get<int>() const { return GetInt(); }
24template<> double RAttrMap::Value_t::Get<double>() const { return GetDouble(); }
25template<> std::string RAttrMap::Value_t::Get<std::string>() const { return GetString(); }
26template<> RPadLength RAttrMap::Value_t::Get<RPadLength>() const { return GetString(); }
27
28template<> bool RAttrMap::Value_t::GetValue<bool,void>(const Value_t *rec) { return rec ? rec->GetBool() : false; }
29template<> int RAttrMap::Value_t::GetValue<int,void>(const Value_t *rec) { return rec ? rec->GetInt() : 0; }
30template<> double RAttrMap::Value_t::GetValue<double,void>(const Value_t *rec) { return rec ? rec->GetDouble() : 0.; }
31template<> std::string RAttrMap::Value_t::GetValue<std::string,void>(const Value_t *rec) { return rec ? rec->GetString() : ""s; }
32template<> RPadLength RAttrMap::Value_t::GetValue<RPadLength,void>(const Value_t *rec) { return rec ? rec->GetString() : ""s; }
33
34template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,void>(const Value_t *rec) { return rec; }
35template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,bool>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kBool) ? rec : nullptr; }
36template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,int>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kInt) ? rec : nullptr; }
37template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,double>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kDouble) ? rec : nullptr; }
38template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,std::string>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kString) ? rec : nullptr; }
39template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,RPadLength>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kString) ? rec : nullptr; }
40
41
42/////////////////////////////////////////////////////////////////////////////////////////////////
43/// Add defaults values form sub attribute
44
46{
47 auto prefix = vis.GetPrefix();
48
49 for (const auto &entry : vis.GetDefaults())
50 m[prefix+entry.first] = entry.second->Copy();
51
52 return *this;
53}
54
55/////////////////////////////////////////////////////////////////////////////////////////////////
56/// Add attribute, converting to best possible type
57/// Tested boolean, int, double. If none works - store as a string
58
59void RAttrMap::AddBestMatch(const std::string &name, const std::string &value)
60{
61 if ((value == "none"s) || (value == "null"s) || value.empty()) {
63 return;
64 }
65
66 if (value == "true"s) {
67 AddBool(name, true);
68 return;
69 }
70
71 if (value == "false"s) {
72 AddBool(name, false);
73 return;
74 }
75
76 auto beg = value.begin();
77 int base = 10;
78 bool int_conversion_fails = false;
79
80 if (*beg == '-') {
81 ++beg;
82 } else if ((value.length() > 2) && (*beg == '0') && (value[1] == 'x')) {
83 beg += 2;
84 base = 16;
85 }
86
87 // check if only digits are present
88 if (std::find_if(beg, value.end(), [](unsigned char c) { return !std::isdigit(c); }) == value.end()) {
89
90 try {
91
92 auto ivalue = std::stoll(base == 16 ? value.substr(2) : value, nullptr, base);
93
94 if ((ivalue >= std::numeric_limits<int>::min()) && (ivalue <= std::numeric_limits<int>::max()))
95 AddInt(name, ivalue);
96 else
97 AddDouble(name, ivalue);
98
99 return;
100 } catch (...) {
101 // int conversion fails
102 int_conversion_fails = true;
103 }
104 }
105
106 // check if characters for double is present
107 if (!int_conversion_fails && std::find_if(beg, value.end(), [](unsigned char c) {
108 return !std::isdigit(c) && (c != '.') && (c != '-') && (c != '+') && (c != 'e');
109 }) == value.end()) {
110 try {
111 double dvalue = std::stod(value);
112 AddDouble(name, dvalue);
113 return;
114 } catch (...) {
115 // do nothing
116 }
117 }
118
119 AddString(name, value);
120}
121
122/////////////////////////////////////////////////////////////////////////////////////////////////
123/// Change attribute using string value and kind
124/// Used to change attributes from JS side
125/// Returns true if value was really changed
126
127bool RAttrMap::Change(const std::string &name, Value_t *value)
128{
129 auto entry = m.find(name);
130 if ((entry == m.end()) || (entry->second->Kind() == kNoValue)) {
131 if (!value) return false;
132 m[name] = value->Copy();
133 return true;
134 }
135
136 // specify nullptr means clear attribute
137 if (!value) {
138 m.erase(entry);
139 return true;
140 }
141
142 // error situation - conversion cannot be performed
143 if(!value->CanConvertTo(entry->second->Kind())) {
144 R__ERROR_HERE("gpadv7") << "Wrong data type provided for attribute " << name;
145 return false;
146 }
147
148 // no need to change something
149 if (entry->second->IsEqual(*value))
150 return false;
151
152 switch (entry->second->Kind()) {
153 case kNoValue: break; // just to avoid compiler warnings
154 case kBool: AddBool(name, value->GetBool()); break;
155 case kInt: AddInt(name, value->GetInt()); break;
156 case kDouble: AddDouble(name, value->GetDouble()); break;
157 case kString: AddString(name, value->GetString()); break;
158 }
159
160 return true;
161}
#define R__ERROR_HERE(GROUP)
Definition: RLogger.hxx:183
#define c(i)
Definition: RSha256.hxx:101
char name[80]
Definition: TGX11.cxx:109
Base class for all attributes, used with RDrawable.
Definition: RAttrBase.hxx:27
const std::string & GetPrefix() const
Definition: RAttrBase.hxx:156
virtual const RAttrMap & GetDefaults() const
Return default values for attributes, empty for base class.
Definition: RAttrBase.cxx:19
virtual std::string GetString() const
Definition: RAttrMap.hxx:51
virtual bool CanConvertTo(EValuesKind kind) const
Definition: RAttrMap.hxx:47
virtual std::unique_ptr< Value_t > Copy() const =0
virtual double GetDouble() const
Definition: RAttrMap.hxx:50
RAttrMap & AddString(const std::string &name, const std::string &value)
Definition: RAttrMap.hxx:146
RAttrMap & AddDouble(const std::string &name, double value)
Definition: RAttrMap.hxx:145
RAttrMap & AddNoValue(const std::string &name)
Definition: RAttrMap.hxx:142
std::unordered_map< std::string, std::unique_ptr< Value_t > > m
JSON_object.
Definition: RAttrMap.hxx:133
RAttrMap & AddInt(const std::string &name, int value)
Definition: RAttrMap.hxx:144
bool Change(const std::string &name, Value_t *value=nullptr)
Change attribute using string value and kind Used to change attributes from JS side Returns true if v...
Definition: RAttrMap.cxx:127
RAttrMap & AddBool(const std::string &name, bool value)
Definition: RAttrMap.hxx:143
RAttrMap & AddDefaults(const RAttrBase &vis)
Add defaults values form sub attribute.
Definition: RAttrMap.cxx:45
void AddBestMatch(const std::string &name, const std::string &value)
Add attribute, converting to best possible type Tested boolean, int, double.
Definition: RAttrMap.cxx:59
static constexpr double s