source: calamares/trunk/fuentes/src/libcalamares/utils/YamlUtils.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 17 months ago

sync with github

File size: 5.6 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
4 *   Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
5 *
6 *   Calamares is free software: you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation, either version 3 of the License, or
9 *   (at your option) any later version.
10 *
11 *   Calamares is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include "YamlUtils.h"
20
21#include "utils/Logger.h"
22
23#include <yaml-cpp/yaml.h>
24
25#include <QByteArray>
26#include <QFile>
27#include <QFileInfo>
28#include <QRegExp>
29
30void
31operator>>( const YAML::Node& node, QStringList& v )
32{
33    for ( size_t i = 0; i < node.size(); ++i )
34    {
35        v.append( QString::fromStdString( node[ i ].as< std::string >() ) );
36    }
37}
38
39namespace CalamaresUtils
40{
41
42const QRegExp _yamlScalarTrueValues = QRegExp( "true|True|TRUE|on|On|ON" );
43const QRegExp _yamlScalarFalseValues = QRegExp( "false|False|FALSE|off|Off|OFF" );
44
45QVariant
46yamlToVariant( const YAML::Node& node )
47{
48    switch ( node.Type() )
49    {
50    case YAML::NodeType::Scalar:
51        return yamlScalarToVariant( node );
52
53    case YAML::NodeType::Sequence:
54        return yamlSequenceToVariant( node );
55
56    case YAML::NodeType::Map:
57        return yamlMapToVariant( node );
58
59    case YAML::NodeType::Null:
60    case YAML::NodeType::Undefined:
61        return QVariant();
62    }
63
64    // NOTREACHED
65    return QVariant();
66}
67
68
69QVariant
70yamlScalarToVariant( const YAML::Node& scalarNode )
71{
72    std::string stdScalar = scalarNode.as< std::string >();
73    QString scalarString = QString::fromStdString( stdScalar );
74    if ( _yamlScalarTrueValues.exactMatch( scalarString ) )
75        return QVariant( true );
76    if ( _yamlScalarFalseValues.exactMatch( scalarString ) )
77        return QVariant( false );
78    if ( QRegExp( "[-+]?\\d+" ).exactMatch( scalarString ) )
79        return QVariant( scalarString.toInt() );
80    if ( QRegExp( "[-+]?\\d*\\.?\\d+" ).exactMatch( scalarString ) )
81        return QVariant( scalarString.toDouble() );
82    return QVariant( scalarString );
83}
84
85
86QVariant
87yamlSequenceToVariant( const YAML::Node& sequenceNode )
88{
89    QVariantList vl;
90    for ( YAML::const_iterator it = sequenceNode.begin();
91          it != sequenceNode.end(); ++it )
92    {
93        vl << yamlToVariant( *it );
94    }
95    return vl;
96}
97
98
99QVariant
100yamlMapToVariant( const YAML::Node& mapNode )
101{
102    QVariantMap vm;
103    for ( YAML::const_iterator it = mapNode.begin();
104          it != mapNode.end(); ++it )
105    {
106        vm.insert( QString::fromStdString( it->first.as< std::string >() ),
107                   yamlToVariant( it->second ) );
108    }
109    return vm;
110}
111
112
113void
114explainYamlException( const YAML::Exception& e, const QByteArray& yamlData, const char *label )
115{
116    cWarning() << "YAML error " << e.what() << "in" << label << '.';
117    explainYamlException( e, yamlData );
118}
119
120void
121explainYamlException( const YAML::Exception& e, const QByteArray& yamlData, const QString& label )
122{
123    cWarning() << "YAML error " << e.what() << "in" << label << '.';
124    explainYamlException( e, yamlData );
125}
126
127void
128explainYamlException( const YAML::Exception& e, const QByteArray& yamlData )
129{
130    if ( ( e.mark.line >= 0 ) && ( e.mark.column >= 0 ) )
131    {
132        // Try to show the line where it happened.
133        int linestart = 0;
134        for ( int linecount = 0; linecount < e.mark.line; ++linecount )
135        {
136            linestart = yamlData.indexOf( '\n', linestart );
137            // No more \ns found, weird
138            if ( linestart < 0 )
139                break;
140            linestart += 1;  // Skip that \n
141        }
142        int lineend = linestart;
143        if ( linestart >= 0 )
144        {
145            lineend = yamlData.indexOf( '\n', linestart );
146            if ( lineend < 0 )
147                lineend = yamlData.length();
148        }
149
150        int rangestart = linestart;
151        int rangeend = lineend;
152        // Adjust range (linestart..lineend) so it's not too long
153        if ( ( linestart >= 0 ) && ( e.mark.column > 30 ) )
154            rangestart += ( e.mark.column - 30 );
155        if ( ( linestart >= 0 ) && ( rangeend - rangestart > 40 ) )
156            rangeend = rangestart + 40;
157
158        if ( linestart >= 0 )
159            cWarning() << "offending YAML data:" << yamlData.mid( rangestart, rangeend-rangestart ).constData();
160
161    }
162}
163
164QVariantMap
165loadYaml(const QFileInfo& fi, bool* ok)
166{
167    return loadYaml( fi.absoluteFilePath(), ok );
168}
169
170QVariantMap
171loadYaml(const QString& filename, bool* ok)
172{
173    if ( ok )
174        *ok = false;
175
176    QFile descriptorFile( filename );
177    QVariant moduleDescriptor;
178    if ( descriptorFile.exists() && descriptorFile.open( QFile::ReadOnly | QFile::Text ) )
179    {
180        QByteArray ba = descriptorFile.readAll();
181        try
182        {
183            YAML::Node doc = YAML::Load( ba.constData() );
184            moduleDescriptor = CalamaresUtils::yamlToVariant( doc );
185        }
186        catch ( YAML::Exception& e )
187        {
188            explainYamlException( e, ba, filename );
189            return QVariantMap();
190        }
191    }
192
193
194    if ( moduleDescriptor.isValid() &&
195         !moduleDescriptor.isNull() &&
196         moduleDescriptor.type() == QVariant::Map )
197    {
198        if ( ok )
199            *ok = true;
200        return moduleDescriptor.toMap();
201    }
202
203    return QVariantMap();
204}
205
206}  // namespace
Note: See TracBrowser for help on using the repository browser.