Commit 8303479c authored by Volker Krause's avatar Volker Krause
Browse files

Use unique string keys for class and layer selectors

This is more efficient as those can be compared by a single pointer
comparison, need less runtime memory and fewer allocations. With this
layer selectors are now also preserved (but not actually evaluated yet).
parent cac6bba6
Pipeline #65280 canceled with stage
......@@ -142,7 +142,7 @@ way.importantShops|z20-
color: "blue";
}
way[highway]
way[highway]::road
{
width: 8;
color: #ffffffff;
......@@ -150,7 +150,7 @@ way[highway]
casing-color: #ffa0a0a0;
}
way[railway=tram]
way[railway=tram]::tram
{
width: 2;
color: #ff303030;
......
......@@ -122,8 +122,9 @@ bool MapCSSDeclaration::isValid() const
case PropertyDeclaration:
return property() != Unknown;
case TagDeclaration:
case ClassDeclaration:
return !m_identValue.isEmpty();
case ClassDeclaration:
return !m_class.isNull();
}
Q_UNREACHABLE();
......@@ -289,6 +290,16 @@ void MapCSSDeclaration::setUnit(const char *val, int len)
m_unit = NoUnit;
}
ClassSelectorKey MapCSSDeclaration::classSelectorKey() const
{
return m_class;
}
void MapCSSDeclaration::setClassSelectorKey(ClassSelectorKey key)
{
m_class = key;
}
void MapCSSDeclaration::compile(const OSM::DataSet &dataSet)
{
Q_UNUSED(dataSet);
......@@ -347,7 +358,7 @@ void MapCSSDeclaration::write(QIODevice *out) const
break;
case ClassDeclaration:
out->write("set .");
out->write(m_identValue);
out->write(m_class.name());
break;
}
......
......@@ -8,6 +8,7 @@
#define KOSMINDOORMAP_MAPCSSDECLARATION_P_H
#include "kosmindoormap_export.h"
#include "mapcsstypes.h"
#include <QByteArray>
#include <QColor>
......@@ -157,6 +158,8 @@ public:
};
Unit unit() const;
ClassSelectorKey classSelectorKey() const;
void compile(const OSM::DataSet &dataSet);
void write(QIODevice *out) const;
......@@ -172,6 +175,7 @@ private:
void setColorRgba(uint32_t argb);
void setDashesValue(const QVector<double> &dashes);
void setUnit(const char *val, int len);
void setClassSelectorKey(ClassSelectorKey key);
Property m_property = Unknown;
int m_flags = NoFlag;
......@@ -181,6 +185,7 @@ private:
double m_doubleValue = NAN;
QVector<double> m_dashValue;
QString m_stringValue;
ClassSelectorKey m_class;
Unit m_unit = NoUnit;
Type m_type;
};
......
......@@ -11,6 +11,7 @@
#include "mapcssrule_p.h"
#include "mapcssscanner.h"
#include "mapcssstyle.h"
#include "mapcssstyle_p.h"
#include <QDebug>
#include <QFile>
......@@ -135,7 +136,7 @@ bool MapCSSParser::addImport(char* fileName)
void MapCSSParser::addRule(MapCSSRule *rule)
{
m_currentStyle->m_rules.push_back(std::unique_ptr<MapCSSRule>(rule));
MapCSSStylePrivate::get(m_currentStyle)->m_rules.push_back(std::unique_ptr<MapCSSRule>(rule));
}
void MapCSSParser::setError(const QString &msg, int line, int column)
......@@ -145,3 +146,13 @@ void MapCSSParser::setError(const QString &msg, int line, int column)
m_line = line;
m_column = column;
}
ClassSelectorKey MapCSSParser::makeClassSelector(const char *str, std::size_t len)
{
return MapCSSStylePrivate::get(m_currentStyle)->m_classSelectorRegistry.makeKey(str, len, OSM::StringMemory::Transient);
}
LayerSelectorKey MapCSSParser::makeLayerSelector(const char *str, std::size_t len)
{
return MapCSSStylePrivate::get(m_currentStyle)->m_layerSelectorRegistry.makeKey(str, len, OSM::StringMemory::Transient);
}
......@@ -9,6 +9,8 @@
#include "kosmindoormap_export.h"
#include "mapcsstypes.h"
#include <QString>
namespace KOSMIndoorMap { class MapCSSParser; }
......@@ -43,6 +45,9 @@ private:
void addRule(MapCSSRule *rule);
void setError(const QString &msg, int line, int column);
ClassSelectorKey makeClassSelector(const char *str, std::size_t len);
LayerSelectorKey makeLayerSelector(const char *str, std::size_t len);
MapCSSStyle *m_currentStyle = nullptr;
QString m_currentFileName;
bool m_error = false;
......
......@@ -192,17 +192,27 @@ Selector:
BasicSelector:
T_IDENT[I] ClassSelector[C] ZoomRange[Z] Tests[T] LayerSelector[L] {
$$ = new MapCSSBasicSelector;
$$->setClass($C.str, $C.len);
if ($C.str) {
$$->setClass(parser->makeClassSelector($C.str, $C.len));
}
$$->setObjectType($I.str, $I.len);
$$->setZoomRange($Z.low, $Z.high);
$$->setConditions($T);
if ($L.str) {
$$->setLayer(parser->makeLayerSelector($L.str, $L.len));
}
}
| T_STAR ClassSelector[C] ZoomRange[Z] Tests[T] LayerSelector[L] {
$$ = new MapCSSBasicSelector;
$$->objectType = MapCSSBasicSelector::Any;
$$->setClass($C.str, $C.len);
if ($C.str) {
$$->setClass(parser->makeClassSelector($C.str, $C.len));
}
$$->setZoomRange($Z.low, $Z.high);
$$->setConditions($T);
if ($L.str) {
$$->setLayer(parser->makeLayerSelector($L.str, $L.len));
}
}
;
......@@ -270,7 +280,7 @@ Declaration:
}
| T_KEYWORD_SET T_DOT T_IDENT[C] T_SEMICOLON {
$$ = new MapCSSDeclaration(MapCSSDeclaration::ClassDeclaration);
$$->setIdentifierValue($C.str, $C.len);
$$->setClassSelectorKey(parser->makeClassSelector($C.str, $C.len));
}
;
......
......@@ -65,7 +65,7 @@ void MapCSSResult::addDeclaration(const MapCSSDeclaration *decl)
m_flags |= decl->propertyFlags();
}
void MapCSSResult::addClass(const QByteArray &cls)
void MapCSSResult::addClass(ClassSelectorKey cls)
{
const auto it = std::lower_bound(m_classes.begin(), m_classes.end(), cls);
if (it == m_classes.end() || (*it) != cls) {
......@@ -73,7 +73,7 @@ void MapCSSResult::addClass(const QByteArray &cls)
}
}
bool MapCSSResult::hasClass(const QByteArray& cls) const
bool MapCSSResult::hasClass(ClassSelectorKey cls) const
{
return std::binary_search(m_classes.begin(), m_classes.end(), cls);
}
......@@ -8,6 +8,7 @@
#define KOSMINDOORMAP_MAPCSSRESULT_P_H
#include "mapcssdeclaration_p.h"
#include "mapcsstypes.h"
#include <vector>
......@@ -36,12 +37,12 @@ public:
/** @internal */
void addDeclaration(const MapCSSDeclaration *decl);
void addClass(const QByteArray &cls);
bool hasClass(const QByteArray &cls) const;
void addClass(ClassSelectorKey cls);
bool hasClass(ClassSelectorKey cls) const;
private:
std::vector<const MapCSSDeclaration*> m_declarations;
std::vector<QByteArray> m_classes;
std::vector<ClassSelectorKey> m_classes;
int m_flags = 0;
};
......
......@@ -37,7 +37,7 @@ void MapCSSRule::evaluate(const MapCSSState &state, MapCSSResult &result) const
result.addDeclaration(decl.get());
break;
case MapCSSDeclaration::ClassDeclaration:
result.addClass(decl->keyValue());
result.addClass(decl->classSelectorKey());
break;
case MapCSSDeclaration::TagDeclaration:
// TODO
......
......@@ -72,7 +72,7 @@ bool MapCSSBasicSelector::matches(const MapCSSState &state, const MapCSSResult &
case Any: break;
}
if (!m_class.isEmpty() && !result.hasClass(m_class)) {
if (!m_class.isNull() && !result.hasClass(m_class)) {
return false;
}
......@@ -117,9 +117,9 @@ void MapCSSBasicSelector::write(QIODevice *out) const
}
}
if (!m_class.isEmpty()) {
if (!m_class.isNull()) {
out->write(".");
out->write(m_class);
out->write(m_class.name());
}
if (m_zoomLow > 0 || m_zoomHigh > 0) {
......@@ -140,6 +140,11 @@ void MapCSSBasicSelector::write(QIODevice *out) const
for (const auto &cond : conditions) {
cond->write(out);
}
if (!m_layer.isNull()) {
out->write("::");
out->write(m_layer.name());
}
}
void MapCSSBasicSelector::setObjectType(const char *str, std::size_t len)
......@@ -167,11 +172,14 @@ void MapCSSBasicSelector::setConditions(MapCSSConditionHolder *conds)
delete conds;
}
void MapCSSBasicSelector::setClass(const char *str, std::size_t len)
void MapCSSBasicSelector::setClass(ClassSelectorKey key)
{
if (str) {
m_class = QByteArray(str, len);
}
m_class = key;
}
void MapCSSBasicSelector::setLayer(LayerSelectorKey key)
{
m_layer = key;
}
......
......@@ -7,6 +7,8 @@
#ifndef KOSMINDOORMAP_MAPCSSSELECTOR_P_H
#define KOSMINDOORMAP_MAPCSSSELECTOR_P_H
#include "mapcsstypes.h"
#include <osm/datatypes.h>
#include <memory>
......@@ -67,12 +69,14 @@ public:
void setObjectType(const char *str, std::size_t len);
void setZoomRange(int low, int high);
void setConditions(MapCSSConditionHolder *conds);
void setClass(const char *str, std::size_t len);
void setClass(ClassSelectorKey key);
void setLayer(LayerSelectorKey key);
std::vector<std::unique_ptr<MapCSSCondition>> conditions;
OSM::TagKey m_areaKey;
OSM::TagKey m_typeKey;
QByteArray m_class;
ClassSelectorKey m_class;
LayerSelectorKey m_layer;
int m_zoomLow = 0;
int m_zoomHigh = 0;
};
......
......@@ -5,6 +5,7 @@
*/
#include "mapcssstyle.h"
#include "mapcssstyle_p.h"
#include "mapcssparser.h"
#include "mapcssresult_p.h"
#include "mapcssrule_p.h"
......@@ -15,14 +16,17 @@
using namespace KOSMIndoorMap;
MapCSSStyle::MapCSSStyle() = default;
MapCSSStyle::MapCSSStyle()
: d(new MapCSSStylePrivate)
{}
MapCSSStyle::MapCSSStyle(MapCSSStyle&&) = default;
MapCSSStyle::~MapCSSStyle() = default;
MapCSSStyle& MapCSSStyle::operator=(MapCSSStyle&&) = default;
void MapCSSStyle::compile(const OSM::DataSet &dataSet)
{
for (const auto &rule : m_rules) {
for (const auto &rule : d->m_rules) {
rule->compile(dataSet);
}
}
......@@ -30,7 +34,7 @@ void MapCSSStyle::compile(const OSM::DataSet &dataSet)
void MapCSSStyle::evaluate(const MapCSSState &state, MapCSSResult &result) const
{
result.clear();
for (const auto &rule : m_rules) {
for (const auto &rule : d->m_rules) {
rule->evaluate(state, result);
}
}
......@@ -38,14 +42,14 @@ void MapCSSStyle::evaluate(const MapCSSState &state, MapCSSResult &result) const
void MapCSSStyle::evaluateCanvas(const MapCSSState &state, MapCSSResult &result) const
{
result.clear();
for (const auto &rule : m_rules) {
for (const auto &rule : d->m_rules) {
rule->evaluateCanvas(state, result);
}
}
void MapCSSStyle::write(QIODevice *out) const
{
for (const auto &rule : m_rules) {
for (const auto &rule : d->m_rules) {
rule->write(out);
}
}
......@@ -10,7 +10,6 @@
#include "kosmindoormap_export.h"
#include <memory>
#include <vector>
class QIODevice;
......@@ -20,10 +19,9 @@ class DataSet;
namespace KOSMIndoorMap {
class MapCSSParser;
class MapCSSResult;
class MapCSSRule;
class MapCSSState;
class MapCSSStylePrivate;
/** A parsed MapCSS style sheet.
* @see MapCSSParser::parse for how to obtain a valid instance
......@@ -60,8 +58,8 @@ public:
void write(QIODevice *out) const;
private:
friend class MapCSSParser;
std::vector<std::unique_ptr<MapCSSRule>> m_rules;
friend class MapCSSStylePrivate;
std::unique_ptr<MapCSSStylePrivate> d;
};
}
......
/*
SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KOSMINDOORMAP_MAPCSSSTYLE_P_H
#define KOSMINDOORMAP_MAPCSSSTYLE_P_H
#include "mapcsstypes.h"
#include <memory>
#include <vector>
namespace KOSMIndoorMap {
class MapCSSRule;
class MapCSSStylePrivate {
public:
std::vector<std::unique_ptr<MapCSSRule>> m_rules;
OSM::StringKeyRegistry<ClassSelectorKey> m_classSelectorRegistry;
OSM::StringKeyRegistry<LayerSelectorKey> m_layerSelectorRegistry;
inline static MapCSSStylePrivate* get(MapCSSStyle *style) { return style->d.get(); }
};
}
#endif // KOSMINDOORMAP_MAPCSSSTYLE_P_H
/*
SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KOSMINDOORMAP_MAPCSSTYPES_H
#define KOSMINDOORMAP_MAPCSSTYPES_H
#include <osm/stringpool.h>
namespace KOSMIndoorMap {
class ClassSelectorKey : public OSM::StringKey {};
class LayerSelectorKey : public OSM::StringKey {};
}
#endif // KOSMINDOORMAP_MAPCSSTYPES_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment