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"
13#include "ROOT/RLogger.hxx"
14
15#include <string>
16#include <algorithm>
17#include <limits>
18
19using namespace ROOT::Experimental;
20
21using namespace std::string_literals;
22
23template<> bool RAttrMap::Value_t::Get<bool>() const { return GetBool(); }
24template<> int RAttrMap::Value_t::Get<int>() const { return GetInt(); }
25template<> double RAttrMap::Value_t::Get<double>() const { return GetDouble(); }
26template<> std::string RAttrMap::Value_t::Get<std::string>() const { return GetString(); }
27template<> RPadLength RAttrMap::Value_t::Get<RPadLength>() const { return GetString(); }
28template<> RColor RAttrMap::Value_t::Get<RColor>() const { return GetString(); }
29
30template<> bool RAttrMap::Value_t::GetValue<bool,void>(const Value_t *rec) { return rec ? rec->GetBool() : false; }
31template<> int RAttrMap::Value_t::GetValue<int,void>(const Value_t *rec) { return rec ? rec->GetInt() : 0; }
32template<> double RAttrMap::Value_t::GetValue<double,void>(const Value_t *rec) { return rec ? rec->GetDouble() : 0.; }
33template<> std::string RAttrMap::Value_t::GetValue<std::string,void>(const Value_t *rec) { return rec ? rec->GetString() : ""s; }
34template<> RPadLength RAttrMap::Value_t::GetValue<RPadLength,void>(const Value_t *rec) { return rec ? rec->GetString() : ""s; }
35template<> RColor RAttrMap::Value_t::GetValue<RColor,void>(const Value_t *rec) { return rec ? rec->GetString() : ""s; }
36
37template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,void>(const Value_t *rec) { return rec; }
38template<> 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; }
39template<> 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; }
40template<> 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; }
41template<> 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; }
42template<> 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; }
43template<> const RAttrMap::Value_t *RAttrMap::Value_t::GetValue<const RAttrMap::Value_t *,RColor>(const Value_t *rec) { return rec && rec->CanConvertTo(RAttrMap::kString) ? rec : nullptr; }
44
45
46/////////////////////////////////////////////////////////////////////////////////////////////////
47/// Add defaults values form sub attribute
48
50{
51 RAttrMap defaults = vis.CollectDefaults();
52
53 std::string prefix;
54 if (dynamic_cast<const RAttrAggregation *>(&vis) && vis.GetPrefix()) {
55 prefix = vis.GetPrefix();
56 if (!prefix.empty()) prefix.append("_");
57 }
58
59 for (auto &entry : defaults.m)
60 m[prefix + entry.first] = std::move(entry.second);
61
62 return *this;
63}
64
65/////////////////////////////////////////////////////////////////////////////////////////////////
66/// Add attribute, converting to best possible type
67/// Tested boolean, int, double. If none works - store as a string
68
69void RAttrMap::AddBestMatch(const std::string &name, const std::string &value)
70{
71 if ((value == "none"s) || (value == "null"s) || value.empty()) {
73 return;
74 }
75
76 if (value == "true"s) {
77 AddBool(name, true);
78 return;
79 }
80
81 if (value == "false"s) {
82 AddBool(name, false);
83 return;
84 }
85
86 auto beg = value.begin();
87 int base = 10;
88 bool int_conversion_fails = false;
89
90 if (*beg == '-') {
91 ++beg;
92 } else if ((value.length() > 2) && (*beg == '0') && (value[1] == 'x')) {
93 beg += 2;
94 base = 16;
95 }
96
97 // check if only digits are present
98 if (std::find_if(beg, value.end(), [](unsigned char c) { return !std::isdigit(c); }) == value.end()) {
99
100 try {
101
102 auto ivalue = std::stoll(base == 16 ? value.substr(2) : value, nullptr, base);
103
104 if ((ivalue >= std::numeric_limits<int>::min()) && (ivalue <= std::numeric_limits<int>::max()))
105 AddInt(name, ivalue);
106 else
107 AddDouble(name, ivalue);
108
109 return;
110 } catch (...) {
111 // int conversion fails
112 int_conversion_fails = true;
113 }
114 }
115
116 // check if characters for double is present
117 if (!int_conversion_fails && std::find_if(beg, value.end(), [](unsigned char c) {
118 return !std::isdigit(c) && (c != '.') && (c != '-') && (c != '+') && (c != 'e');
119 }) == value.end()) {
120 try {
121 double dvalue = std::stod(value);
122 AddDouble(name, dvalue);
123 return;
124 } catch (...) {
125 // do nothing
126 }
127 }
128
129 AddString(name, value);
130}
131
132/////////////////////////////////////////////////////////////////////////////////////////////////
133/// Change attribute using string value and kind
134/// Used to change attributes from JS side
135/// Returns true if value was really changed
136
137bool RAttrMap::Change(const std::string &name, Value_t *value)
138{
139 auto entry = m.find(name);
140 if ((entry == m.end()) || (entry->second->Kind() == kNoValue)) {
141 if (!value) return false;
142 m[name] = value->Copy();
143 return true;
144 }
145
146 // specify nullptr means clear attribute
147 if (!value) {
148 m.erase(entry);
149 return true;
150 }
151
152 // error situation - conversion cannot be performed
153 if(!value->CanConvertTo(entry->second->Kind())) {
154 R__LOG_ERROR(GPadLog()) << "Wrong data type provided for attribute " << name;
155 return false;
156 }
157
158 // no need to change something
159 if (entry->second->IsEqual(*value))
160 return false;
161
162 switch (entry->second->Kind()) {
163 case kNoValue: break; // just to avoid compiler warnings
164 case kBool: AddBool(name, value->GetBool()); break;
165 case kInt: AddInt(name, value->GetInt()); break;
166 case kDouble: AddDouble(name, value->GetDouble()); break;
167 case kString: AddString(name, value->GetString()); break;
168 }
169
170 return true;
171}
#define R__LOG_ERROR(...)
Definition: RLogger.hxx:362
#define c(i)
Definition: RSha256.hxx:101
char name[80]
Definition: TGX11.cxx:110
Base class for attributes aggregations like lines or fill attributes.
Base class for all attributes, used with RDrawable.
Definition: RAttrBase.hxx:31
const char * GetPrefix() const
Definition: RAttrBase.hxx:151
virtual RAttrMap CollectDefaults() const =0
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:137
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:49
void AddBestMatch(const std::string &name, const std::string &value)
Add attribute, converting to best possible type Tested boolean, int, double.
Definition: RAttrMap.cxx:69
The color class.
Definition: RColor.hxx:33
RLogChannel & GPadLog()
Log channel for GPad diagnostics.
Definition: RAttrBase.cxx:17
static constexpr double s