mapcssparser.cpp 3.74 KB
Newer Older
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"
Volker Krause's avatar
Volker Krause committed
8
#include "logging.h"
9
10

#include "mapcssparser_p.h"
11
#include "mapcssrule_p.h"
12
13
#include "mapcssscanner.h"
#include "mapcssstyle.h"
14
#include "mapcssstyle_p.h"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QScopeGuard>

#include <cstring>

char* unquoteString(const char *str)
{
    const auto size = strlen(str) - 2;
    if (size <= 0)
        return nullptr;
    auto out = (char*)malloc(size + 1);
    memset(out, 0, size + 1);
    auto outIt = out;
    for (auto it = str + 1; it < str + size + 1; ++it, ++outIt) {
        if (*it == '\\') {
            ++it;
            switch (*it) {
                case '\\':
                case '"':
                    *outIt = *it; break;
                case 'n':
                    *outIt = '\n'; break;
                case 't':
                    *outIt = '\t'; break;
                default:
                    *outIt++ = '\\';
                    *outIt = *it;
            }
        } else {
            *outIt = *it;
        }
    }
    return out;
}

using namespace KOSMIndoorMap;

bool MapCSSParser::hasError() const
{
    return m_error;
}

QString MapCSSParser::fileName() const
{
    return m_currentFileName;
}

65
66
67
68
69
70
71
72
73
QString MapCSSParser::errorMessage() const
{
    if (!m_error) {
        return {};
    }

    return m_errorMsg + QLatin1String(": ") + fileName() + QLatin1Char(':') + QString::number(m_line) + QLatin1Char(':') + QString::number(m_column);
}

74
75
76
77
78
79
80
MapCSSStyle MapCSSParser::parse(const QString &fileName)
{
    m_error = true;

    MapCSSStyle style;
    parse(&style, fileName);
    if (m_error) {
81
        return MapCSSStyle();
82
83
84
85
86
87
88
89
90
    }

    return style;
}

void MapCSSParser::parse(MapCSSStyle *style, const QString &fileName)
{
    QFile f(fileName);
    if (!f.open(QFile::ReadOnly)) {
Volker Krause's avatar
Volker Krause committed
91
        qCWarning(Log) << f.fileName() << f.errorString();
92
93
        m_error = true;
        m_errorMsg = f.errorString();
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
        return;
    }
    m_currentFileName = fileName;
    m_currentStyle = style;

    yyscan_t scanner;
    if (yylex_init(&scanner)) {
        return;
    }
    const auto lexerCleanup = qScopeGuard([&scanner]{ yylex_destroy(scanner); });

    const auto b = f.readAll();
    YY_BUFFER_STATE state;
    state = yy_scan_string(b.constData(), scanner);
    if (yyparse(this, scanner)) {
109
        m_error = true;
110
111
112
113
114
115
116
117
118
        return;
    }

    yy_delete_buffer(state, scanner);

    m_error = false;
    m_currentStyle = nullptr;
}

119
bool MapCSSParser::addImport(char* fileName)
120
121
122
123
124
125
126
127
128
129
{
    auto cssFile = QString::fromUtf8(fileName);
    free(fileName);

    if (QFileInfo(cssFile).isRelative()) {
        cssFile = QFileInfo(m_currentFileName).absolutePath() + QLatin1Char('/') + cssFile;
    }

    MapCSSParser p;
    p.parse(m_currentStyle, cssFile);
130
131
132
133
134
    if (p.hasError()) {
        m_error = p.m_error;
        m_errorMsg = p.errorMessage();
    }
    return !p.hasError();
135
136
137
138
}

void MapCSSParser::addRule(MapCSSRule *rule)
{
139
    MapCSSStylePrivate::get(m_currentStyle)->m_rules.push_back(std::unique_ptr<MapCSSRule>(rule));
140
}
141
142
143
144
145
146
147
148

void MapCSSParser::setError(const QString &msg, int line, int column)
{
    m_error = true;
    m_errorMsg = msg;
    m_line = line;
    m_column = column;
}
149
150
151
152
153
154
155
156

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)
{
Volker Krause's avatar
Volker Krause committed
157
158
159
    if (!str || std::strcmp(str, "default") == 0) {
        return {};
    }
160
161
    return MapCSSStylePrivate::get(m_currentStyle)->m_layerSelectorRegistry.makeKey(str, len, OSM::StringMemory::Transient);
}