[libcalamares] Add nested (dotted) key lookup for GS
This commit is contained in:
parent
3f4d2c8040
commit
8a095504c4
@ -190,4 +190,55 @@ GlobalStorage::loadYaml( const QString& filename )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///@brief Implementation for recursively looking up dotted selector parts.
|
||||||
|
static QVariant
|
||||||
|
lookup( const QStringList& nestedKey, int index, const QVariant& v, bool& ok )
|
||||||
|
{
|
||||||
|
if ( !v.canConvert< QVariantMap >() )
|
||||||
|
{
|
||||||
|
// Mismatch: we're still looking for keys, but v is not a submap
|
||||||
|
ok = false;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if ( index >= nestedKey.length() )
|
||||||
|
{
|
||||||
|
cError() << "Recursion error looking at index" << index << "of" << nestedKey;
|
||||||
|
ok = false;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVariantMap map = v.toMap();
|
||||||
|
const QString& key = nestedKey.at( index );
|
||||||
|
if ( index == nestedKey.length() - 1 )
|
||||||
|
{
|
||||||
|
ok = map.contains( key );
|
||||||
|
return ok ? map.value( key ) : QVariant();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return lookup( nestedKey, index + 1, map.value( key ), ok );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
lookup( const GlobalStorage* storage, const QString& nestedKey, bool& ok )
|
||||||
|
{
|
||||||
|
ok = false;
|
||||||
|
if ( !storage )
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nestedKey.contains( '.' ) )
|
||||||
|
{
|
||||||
|
QStringList steps = nestedKey.split( '.' );
|
||||||
|
return lookup( steps, 1, storage->value( steps.first() ), ok );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = storage->contains( nestedKey );
|
||||||
|
return ok ? storage->value( nestedKey ) : QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Calamares
|
} // namespace Calamares
|
||||||
|
@ -167,6 +167,26 @@ private:
|
|||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Gets a value from the store
|
||||||
|
*
|
||||||
|
* When @p nestedKey contains no '.' characters, equivalent
|
||||||
|
* to `gs->value(nestedKey)`. Otherwise recursively looks up
|
||||||
|
* the '.'-separated parts of @p nestedKey in successive sub-maps
|
||||||
|
* of the store, returning the value in the innermost one.
|
||||||
|
*
|
||||||
|
* Example: `lookup(gs, "branding.name")` finds the value of the
|
||||||
|
* 'name' key in the 'branding' submap of the store.
|
||||||
|
*
|
||||||
|
* Sets @p ok to @c true if a value was found. Returns the value
|
||||||
|
* as a variant. If no value is found (e.g. the key is missing
|
||||||
|
* or some prefix submap is missing) sets @p ok to @c false
|
||||||
|
* and returns an invalid QVariant.
|
||||||
|
*
|
||||||
|
* @see GlobalStorage::value
|
||||||
|
*/
|
||||||
|
DLLEXPORT QVariant lookup( const GlobalStorage* gs, const QString& nestedKey, bool& ok );
|
||||||
|
|
||||||
} // namespace Calamares
|
} // namespace Calamares
|
||||||
|
|
||||||
#endif // CALAMARES_GLOBALSTORAGE_H
|
#endif // CALAMARES_GLOBALSTORAGE_H
|
||||||
|
@ -32,6 +32,7 @@ private Q_SLOTS:
|
|||||||
void testGSLoadSave();
|
void testGSLoadSave();
|
||||||
void testGSLoadSave2();
|
void testGSLoadSave2();
|
||||||
void testGSLoadSaveYAMLStringList();
|
void testGSLoadSaveYAMLStringList();
|
||||||
|
void testGSNestedLookup();
|
||||||
|
|
||||||
void testInstanceKey();
|
void testInstanceKey();
|
||||||
void testInstanceDescription();
|
void testInstanceDescription();
|
||||||
@ -177,6 +178,38 @@ TestLibCalamares::testGSLoadSaveYAMLStringList()
|
|||||||
QCOMPARE( gs2.value( "dwarfs" ).toString(), QStringLiteral( "<QStringList>" ) ); // .. they're gone
|
QCOMPARE( gs2.value( "dwarfs" ).toString(), QStringLiteral( "<QStringList>" ) ); // .. they're gone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestLibCalamares::testGSNestedLookup()
|
||||||
|
{
|
||||||
|
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||||
|
|
||||||
|
const QString filename( BUILD_AS_TEST "/testdata/yaml-list.conf" );
|
||||||
|
QVERIFY2( QFile::exists( filename ), qPrintable( filename ) );
|
||||||
|
|
||||||
|
Calamares::GlobalStorage gs2;
|
||||||
|
QVERIFY( gs2.loadYaml( filename ) );
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto v0 = Calamares::lookup( &gs2, "horse.colors.neck", ok );
|
||||||
|
QVERIFY( ok );
|
||||||
|
QVERIFY( v0.canConvert< QString >() );
|
||||||
|
QCOMPARE( v0.toString(), QStringLiteral( "roan" ) );
|
||||||
|
const auto v1 = Calamares::lookup( &gs2, "horse.colors.nose", ok );
|
||||||
|
QVERIFY( !ok );
|
||||||
|
QVERIFY( !v1.isValid() );
|
||||||
|
const auto v2 = Calamares::lookup( &gs2, "cow.colors.nose", ok );
|
||||||
|
QVERIFY( !ok );
|
||||||
|
QVERIFY( !v2.isValid() );
|
||||||
|
const auto v3 = Calamares::lookup( &gs2, "dwarfs", ok );
|
||||||
|
QVERIFY( ok );
|
||||||
|
QVERIFY( v3.canConvert< QVariantList >() ); // because it's a list-valued thing
|
||||||
|
const auto v4 = Calamares::lookup( &gs2, "dwarfs.sleepy", ok );
|
||||||
|
QVERIFY( !ok ); // Sleepy is a value in the list of dwarfs, not a key
|
||||||
|
const auto v5 = Calamares::lookup( &gs2, "derp", ok );
|
||||||
|
QVERIFY( ok );
|
||||||
|
QCOMPARE( v5.toInt(), 17 );
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TestLibCalamares::testInstanceKey()
|
TestLibCalamares::testInstanceKey()
|
||||||
{
|
{
|
||||||
|
6
src/libcalamares/testdata/yaml-list.conf
vendored
6
src/libcalamares/testdata/yaml-list.conf
vendored
@ -9,3 +9,9 @@
|
|||||||
- "sleepy"
|
- "sleepy"
|
||||||
- "sneezy"
|
- "sneezy"
|
||||||
- "doc"
|
- "doc"
|
||||||
|
horse:
|
||||||
|
hoofs: 4
|
||||||
|
colors:
|
||||||
|
mane: black
|
||||||
|
neck: roan
|
||||||
|
tail: white
|
||||||
|
Loading…
Reference in New Issue
Block a user