KOSMIndoorMap

mapcssparser.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "mapcssparser.h"
8#include "mapcssparser_p.h"
9#include "logging.h"
10
11#include "mapcssparser_impl.h"
12#include "mapcssdeclaration_p.h"
13#include "mapcssrule_p.h"
14#include "mapcssscanner.h"
15#include "mapcssstyle.h"
16#include "mapcssstyle_p.h"
17
18#include <QDebug>
19#include <QFile>
20#include <QFileInfo>
21#include <QScopeGuard>
22
23#include <cstring>
24
25char* unquoteString(const char *str)
26{
27 const auto size = strlen(str) - 2;
28 if (size <= 0) {
29 return nullptr;
30 }
31 auto out = (char*)malloc(size + 1);
32 memset(out, 0, size + 1);
33 auto outIt = out;
34 for (auto it = str + 1; it < str + size + 1; ++it, ++outIt) {
35 if (*it == '\\') {
36 ++it;
37 switch (*it) {
38 case '\\':
39 case '"':
40 *outIt = *it; break;
41 case 'n':
42 *outIt = '\n'; break;
43 case 't':
44 *outIt = '\t'; break;
45 default:
46 *outIt++ = '\\';
47 *outIt = *it;
48 }
49 } else {
50 *outIt = *it;
51 }
52 }
53 return out;
54}
55
56using namespace KOSMIndoorMap;
57
58MapCSSParser::MapCSSParser()
59 : d(new MapCSSParserPrivate)
60{
61}
62
63MapCSSParser::~MapCSSParser() = default;
64
65bool MapCSSParser::hasError() const
66{
67 return d->m_error;
68}
69
70QString MapCSSParser::fileName() const
71{
72 return d->m_currentFileName;
73}
74
75QString MapCSSParser::errorMessage() const
76{
77 if (!d->m_error) {
78 return {};
79 }
80
81 return d->m_errorMsg + QLatin1String(": ") + fileName() + QLatin1Char(':') + QString::number(d->m_line) + QLatin1Char(':') + QString::number(d->m_column);
82}
83
84MapCSSStyle MapCSSParser::parse(const QString &fileName)
85{
86 d->m_error = true;
87
88 MapCSSStyle style;
89 d->parse(&style, fileName, {});
90 if (d->m_error) {
91 return MapCSSStyle();
92 }
93
94 return style;
95}
96
97void MapCSSParserPrivate::parse(MapCSSStyle *style, const QString &fileName, ClassSelectorKey importClass)
98{
99 QFile f(fileName);
100 if (!f.open(QFile::ReadOnly)) {
101 qCWarning(Log) << f.fileName() << f.errorString();
102 m_error = true;
103 m_errorMsg = f.errorString();
104 return;
105 }
106 m_currentFileName = fileName;
107 m_currentStyle = style;
108 m_importClass = importClass;
109
110 yyscan_t scanner;
111 if (yylex_init(&scanner)) {
112 return;
113 }
114 const auto lexerCleanup = qScopeGuard([&scanner]{ yylex_destroy(scanner); });
115
116 const auto b = f.readAll();
117 YY_BUFFER_STATE state;
118 state = yy_scan_string(b.constData(), scanner);
119 if (yyparse(this, scanner)) {
120 m_error = true;
121 return;
122 }
123
124 yy_delete_buffer(state, scanner);
125
126 m_error = false;
127 m_currentStyle = nullptr;
128 m_importClass = {};
129}
130
131bool MapCSSParserPrivate::addImport(char* fileName, ClassSelectorKey importClass)
132{
133 auto cssFile = QString::fromUtf8(fileName);
134 free(fileName);
135
136 if (QFileInfo(cssFile).isRelative()) {
137 cssFile = QFileInfo(m_currentFileName).absolutePath() + QLatin1Char('/') + cssFile;
138 }
139
140 MapCSSParser p;
141 p.d->parse(m_currentStyle, cssFile, importClass);
142 if (p.hasError()) {
143 m_error = p.d->m_error;
144 m_errorMsg = p.errorMessage();
145 }
146 return !p.hasError();
147}
148
149void MapCSSParserPrivate::addRule(MapCSSRule *rule)
150{
151 if (!m_importClass.isNull()) {
152 auto decl = new MapCSSDeclaration(MapCSSDeclaration::ClassDeclaration);
153 decl->setClassSelectorKey(m_importClass);
154 rule->addDeclaration(decl);
155 }
156 MapCSSStylePrivate::get(m_currentStyle)->m_rules.push_back(std::unique_ptr<MapCSSRule>(rule));
157}
158
159void MapCSSParserPrivate::setError(const QString &msg, int line, int column)
160{
161 m_error = true;
162 m_errorMsg = msg;
163 m_line = line;
164 m_column = column;
165}
166
167ClassSelectorKey MapCSSParserPrivate::makeClassSelector(const char *str, std::size_t len) const
168{
169 return MapCSSStylePrivate::get(m_currentStyle)->m_classSelectorRegistry.makeKey(str, len, OSM::StringMemory::Transient);
170}
171
172LayerSelectorKey MapCSSParserPrivate::makeLayerSelector(const char *str, std::size_t len) const
173{
174 if (!str || std::strcmp(str, "default") == 0) {
175 return {};
176 }
177 return MapCSSStylePrivate::get(m_currentStyle)->m_layerSelectorRegistry.makeKey(str, len, OSM::StringMemory::Transient);
178}
A parsed MapCSS style sheet.
Definition mapcssstyle.h:33
OSM-based multi-floor indoor maps for buildings.
QString absolutePath() const const
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.