14using namespace std::string_literals;
23 auto res =
block.map.Find(field);
37 for (
const auto &
block : fBlocks) {
38 if (
block.selector == selector) {
39 auto res =
block.map.Find(field);
71 const std::string &css_code;
73 RParser(
const std::string &_code) : css_code(_code)
75 len = css_code.length();
78 bool more_data()
const {
return pos < len; }
80 char current()
const {
return css_code[pos]; }
82 void shift() { ++pos; }
84 bool check_symbol(
bool isfirst =
false)
86 auto symbol = current();
87 if (((symbol >=
'a') && (symbol <=
'z')) ||
88 ((symbol >=
'A') && (symbol <=
'Z')) || (symbol ==
'_'))
return true;
89 return (!isfirst && (symbol>=
'0') && (symbol<=
'9'));
92 std::string error_position()
const
94 std::string res =
"\nLine "s + std::to_string(nline) +
": "s;
97 while ((p<len) && (p < linebeg+100) && (css_code[p] !=
'\n')) ++p;
99 return res + css_code.substr(linebeg, p-linebeg);
104 bool skip_until_newline =
false, skip_until_endblock =
false;
107 if (current() ==
'\n') {
108 skip_until_newline =
false;
114 if (skip_until_endblock && (current() ==
'*') && (pos+1 < len) && (css_code[pos+1] ==
'/')) {
116 skip_until_endblock =
false;
120 if (skip_until_newline || skip_until_endblock || (current() ==
' ') || (current() ==
'\t')) {
125 if ((current() ==
'/') && (pos+1 < len)) {
126 if (css_code[pos+1] ==
'/') {
128 skip_until_newline =
true;
130 }
else if (css_code[pos+1] ==
'*') {
132 skip_until_endblock =
true;
143 std::string scan_identifier(
bool selector =
false)
145 if (pos >= len)
return ""s;
150 if (selector && ((current() ==
'.') || (current() ==
'#'))) shift();
152 bool is_first =
true;
154 while ((pos < len) && check_symbol(is_first)) { shift(); is_first =
false; }
156 return css_code.substr(pos0, pos-pos0);
159 std::string scan_value()
161 if (pos >= len)
return ""s;
165 while ((pos < len) && (current() !=
';') && current() !=
'\n') shift();
172 return css_code.substr(pos0, pos - pos0 - 1);
177 RParser parser(css_code);
181 while (parser.more_data()) {
183 if (!parser.skip_empty())
186 auto sel = parser.scan_identifier(
true);
188 R__ERROR_HERE(
"rstyle") <<
"Fail to find selector" << parser.error_position();
192 if (!parser.skip_empty())
195 if (parser.current() !=
'{') {
196 R__ERROR_HERE(
"rstyle") <<
"Fail to find starting {" << parser.error_position();
202 if (!parser.skip_empty())
207 while (parser.current() !=
'}') {
208 auto name = parser.scan_identifier();
210 R__ERROR_HERE(
"rstyle") <<
"not able to extract identifier" << parser.error_position();
214 if (!parser.skip_empty())
217 if (parser.current() !=
':') {
218 R__ERROR_HERE(
"rstyle") <<
"not able to find separator :" << parser.error_position();
224 if (!parser.skip_empty())
227 if (parser.current() ==
';') {
229 map.AddNoValue(
name);
231 auto value = parser.scan_value();
233 R__ERROR_HERE(
"rstyle") <<
"not able to find value" << parser.error_position();
237 map.AddBestMatch(
name, value);
240 if (!parser.skip_empty())
250 fBlocks.splice(fBlocks.end(), newstyle.
fBlocks);
#define R__ERROR_HERE(GROUP)
Base class for drawable entities: objects that can be painted on a RPad.
bool MatchSelector(const std::string &selector) const
Preliminary method which checks if drawable matches with given selector Following selector are allowe...
A set of defaults for graphics attributes, e.g.
std::list< Block_t > fBlocks
const RAttrMap::Value_t * Eval(const std::string &field, const RDrawable &drawable) const
Evaluate attribute value for provided RDrawable.
void Clear()
Parse string with CSS code inside.
bool ParseString(const std::string &css_code)
Parse string with CSS code inside All data will be append to existing style records.
RAttrMap & AddBlock(const std::string &selector)
static constexpr double s