[libcalamares] Add nested (dotted) key lookup for GS

This commit is contained in:
Adriaan de Groot 2024-11-05 14:50:20 +01:00
parent 3f4d2c8040
commit 8a095504c4
4 changed files with 110 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
{ {

View File

@ -9,3 +9,9 @@
- "sleepy" - "sleepy"
- "sneezy" - "sneezy"
- "doc" - "doc"
horse:
hoofs: 4
colors:
mane: black
neck: roan
tail: white