Optimize allocations in project saving and editor rendering

Refactor IniFile storage to keep keys and values in unified SmallVector-backed
records, avoiding parallel vector growth and allocations for common small
configurations.

Use std::string_view by value throughout the IniFile input API to prevent
temporary std::string allocations for keys, value names, paths, and comments.
Write serialized components directly to streams instead of constructing a
temporary string for every line.

Return ProjectBuildConfiguration by const reference to avoid copying it during
project saves, and use inline storage for DocumentView visual lines to avoid
heap allocations while rendering the code editor minimap.

Add IniFile tests covering parsing, mutation, ordered serialization, and a
byte-for-byte ecode project-state round trip.
This commit is contained in:
Martín Lucas Golini
2026-08-13 16:03:04 -03:00
parent 74d9fa660c
commit a2c9adca9a
6 changed files with 264 additions and 228 deletions
+51 -59
View File
@@ -16,12 +16,12 @@
#ifndef EE_SYSTEM_INIFILE_HPP #ifndef EE_SYSTEM_INIFILE_HPP
#define EE_SYSTEM_INIFILE_HPP #define EE_SYSTEM_INIFILE_HPP
#include <eepp/core/small_vector.hpp>
#include <eepp/system/iostream.hpp> #include <eepp/system/iostream.hpp>
#include <map> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <unordered_map> #include <unordered_map>
#include <vector>
namespace EE { namespace System { namespace EE { namespace System {
@@ -32,13 +32,13 @@ class EE_API IniFile {
enum errors { noID = -1 }; enum errors { noID = -1 };
/** Initialize and load the ini file from path */ /** Initialize and load the ini file from path */
IniFile( const std::string& iniPath = "", bool autoLoad = true ); IniFile( std::string_view iniPath = {}, bool autoLoad = true );
/** Initialize and load the ini file from memory */ /** Initialize and load the ini file from memory */
IniFile( const Uint8* RAWData, const Uint32& size, bool autoLoad = true ); IniFile( const Uint8* RAWData, const Uint32& size, bool autoLoad = true );
/** Initialize and load the ini file from a pack file */ /** Initialize and load the ini file from a pack file */
IniFile( Pack* Pack, const std::string& iniPackPath, bool autoLoad = true ); IniFile( Pack* Pack, std::string_view iniPackPath, bool autoLoad = true );
/** Initialize and load the ini file from a stream */ /** Initialize and load the ini file from a stream */
IniFile( IOStream& stream, bool autoLoad = true ); IniFile( IOStream& stream, bool autoLoad = true );
@@ -46,19 +46,19 @@ class EE_API IniFile {
virtual ~IniFile() {} virtual ~IniFile() {}
/** Loads an ini file from path */ /** Loads an ini file from path */
bool loadFromFile( const std::string& iniPath ); bool loadFromFile( std::string_view iniPath );
/** Loads an ini file from memory */ /** Loads an ini file from memory */
bool loadFromMemory( const Uint8* RAWData, const Uint32& size ); bool loadFromMemory( const Uint8* RAWData, const Uint32& size );
/** Loads an ini file from a pack file */ /** Loads an ini file from a pack file */
bool loadFromPack( Pack* Pack, const std::string& iniPackPath ); bool loadFromPack( Pack* Pack, std::string_view iniPackPath );
/** Loads an ini file from a stream */ /** Loads an ini file from a stream */
bool loadFromStream( IOStream& stream ); bool loadFromStream( IOStream& stream );
/** Sets mPath of ini file to read and write from. */ /** Sets mPath of ini file to read and write from. */
void path( const std::string& newPath ) { mPath = newPath; } void path( std::string_view newPath ) { mPath.assign( newPath ); }
/** @return The ini file path */ /** @return The ini file path */
const std::string& path() const { return mPath; } const std::string& path() const { return mPath; }
@@ -77,22 +77,16 @@ class EE_API IniFile {
void clear(); void clear();
/** @return index of specified key, or noID if not found. */ /** @return index of specified key, or noID if not found. */
long findKey( const std::string& keyname ) const; long findKey( std::string_view keyname ) const;
long findKey( const std::string_view& keyname ) const;
/** @return index of specified value, in the specified key, or noID if not found. */ /** @return index of specified value, in the specified key, or noID if not found. */
long findValue( unsigned const keyID, const std::string& valuename ) const; long findValue( unsigned const keyID, std::string_view valuename ) const;
long findValue( unsigned const keyID, const std::string_view& valuename ) const;
/** @return number of Keys currently in the ini. */ /** @return number of Keys currently in the ini. */
unsigned getNumKeys() const { return (unsigned int)mNames.size(); } unsigned getNumKeys() const { return (unsigned int)mKeys.size(); }
/** Add a key name. */ /** Add a key name. */
unsigned addKeyName( const std::string& keyname ); unsigned addKeyName( std::string_view keyname );
unsigned addKeyName( const std::string_view& keyname );
/** @return key Names by index. */ /** @return key Names by index. */
std::string getKeyName( unsigned const keyID ) const; std::string getKeyName( unsigned const keyID ) const;
@@ -101,45 +95,45 @@ class EE_API IniFile {
unsigned getNumValues( unsigned const keyID ); unsigned getNumValues( unsigned const keyID );
/** @return number of values stored for specified key from its name. */ /** @return number of values stored for specified key from its name. */
unsigned getNumValues( const std::string& keyname ); unsigned getNumValues( std::string_view keyname );
/** @return value name by index for a given keyname or keyID. */ /** @return value name by index for a given keyname or keyID. */
std::string getValueName( unsigned const keyID, unsigned const valueID ) const; std::string getValueName( unsigned const keyID, unsigned const valueID ) const;
/** @return A value name from keyname and valueId */ /** @return A value name from keyname and valueId */
std::string getValueName( const std::string& keyname, unsigned const valueID ) const; std::string getValueName( std::string_view keyname, unsigned const valueID ) const;
/** Gets value of [keyname] valuename =. /** Gets value of [keyname] valuename =.
** Overloaded to return std::string, int, and double. ** Overloaded to return std::string, int, and double.
** @return defValue if key/value not found otherwise the value obtained. */ ** @return defValue if key/value not found otherwise the value obtained. */
std::string getValue( unsigned const keyID, unsigned const valueID, std::string getValue( unsigned const keyID, unsigned const valueID,
const std::string& defValue = "" ) const; std::string_view defValue = {} ) const;
/** Gets a value from a keyname and valuename */ /** Gets a value from a keyname and valuename */
std::string getValue( const std::string& keyname, const std::string& valuename, std::string getValue( std::string_view keyname, std::string_view valuename,
const std::string& defValue = "" ) const; std::string_view defValue = {} ) const;
/** Gets the value as integer */ /** Gets the value as integer */
int getValueI( const std::string& keyname, const std::string& valuename, int getValueI( std::string_view keyname, std::string_view valuename,
int const defValue = 0 ) const; int const defValue = 0 ) const;
/** Gets the value as an unsigned long */ /** Gets the value as an unsigned long */
unsigned long getValueU( const std::string& keyname, const std::string& valuename, unsigned long getValueU( std::string_view keyname, std::string_view valuename,
unsigned long const defValue = 0 ) const; unsigned long const defValue = 0 ) const;
/** Gets the value as boolean */ /** Gets the value as boolean */
bool getValueB( const std::string& keyname, const std::string& valuename, bool getValueB( std::string_view keyname, std::string_view valuename,
bool const defValue = false ) const; bool const defValue = false ) const;
/** Gets the value as double */ /** Gets the value as double */
double getValueF( const std::string& keyname, const std::string& valuename, double getValueF( std::string_view keyname, std::string_view valuename,
double const defValue = 0.0 ) const; double const defValue = 0.0 ) const;
/** Sets value of [keyname] valuename =. /** Sets value of [keyname] valuename =.
** Specify the optional parameter as false (0) if you do not want it to create ** Specify the optional parameter as false (0) if you do not want it to create
** the key if it doesn't exist. @return true if data entered, false otherwise. ** the key if it doesn't exist. @return true if data entered, false otherwise.
** Overloaded to accept std::string, int, and double. */ ** Overloaded to accept std::string, int, and double. */
bool setValue( unsigned const keyID, unsigned const valueID, const std::string& value ); bool setValue( unsigned const keyID, unsigned const valueID, std::string_view value );
/** Sets the value from a keyname and a valuename /** Sets the value from a keyname and a valuename
* @param keyname The key name * @param keyname The key name
@@ -147,11 +141,8 @@ class EE_API IniFile {
* @param value The value to assign * @param value The value to assign
* @param create If true it will create the keyname if doesn't exists * @param create If true it will create the keyname if doesn't exists
*/ */
bool setValue( const std::string& keyname, const std::string& valuename, bool setValue( std::string_view keyname, std::string_view valuename, std::string_view value,
const std::string& value, bool create = true ); bool create = true );
bool setValue( const std::string_view& keyname, const std::string_view& valuename,
const std::string_view& value, bool create = true );
/** Sets a integer value from a keyname and a valuename /** Sets a integer value from a keyname and a valuename
* @param keyname The key name * @param keyname The key name
@@ -159,7 +150,7 @@ class EE_API IniFile {
* @param value The value to assign * @param value The value to assign
* @param create If true it will create the keyname if doesn't exists * @param create If true it will create the keyname if doesn't exists
*/ */
bool setValueI( const std::string& keyname, const std::string& valuename, int const value, bool setValueI( std::string_view keyname, std::string_view valuename, int const value,
bool create = true ); bool create = true );
/** Sets a unsigned long value from a keyname and a valuename /** Sets a unsigned long value from a keyname and a valuename
@@ -168,8 +159,8 @@ class EE_API IniFile {
* @param value The value to assign * @param value The value to assign
* @param create If true it will create the keyname if doesn't exists * @param create If true it will create the keyname if doesn't exists
*/ */
bool setValueU( const std::string& keyname, const std::string& valuename, bool setValueU( std::string_view keyname, std::string_view valuename, unsigned long const value,
unsigned long const value, bool create = true ); bool create = true );
/** Sets a boolean value from a keyname and a valuename /** Sets a boolean value from a keyname and a valuename
* @param keyname The key name * @param keyname The key name
@@ -177,7 +168,7 @@ class EE_API IniFile {
* @param value The value to assign * @param value The value to assign
* @param create If true it will create the keyname if doesn't exists * @param create If true it will create the keyname if doesn't exists
*/ */
bool setValueB( const std::string& keyname, const std::string& valuename, bool const value, bool setValueB( std::string_view keyname, std::string_view valuename, bool const value,
bool create = true ) { bool create = true ) {
return setValueI( keyname, valuename, int( value ), create ); return setValueI( keyname, valuename, int( value ), create );
} }
@@ -188,19 +179,19 @@ class EE_API IniFile {
* @param value The value to assign * @param value The value to assign
* @param create If true it will create the keyname if doesn't exists * @param create If true it will create the keyname if doesn't exists
*/ */
bool setValueF( const std::string& keyname, const std::string& valuename, double const value, bool setValueF( std::string_view keyname, std::string_view valuename, double const value,
bool create = true ); bool create = true );
/** Sets a formatted value from a keyname and a valuename */ /** Sets a formatted value from a keyname and a valuename */
bool setValueV( const std::string& keyname, const std::string& valuename, char* format, ... ); bool setValueV( std::string_view keyname, std::string_view valuename, char* format, ... );
/** Deletes specified value. /** Deletes specified value.
** @return true if value existed and deleted, false otherwise. */ ** @return true if value existed and deleted, false otherwise. */
bool deleteValue( const std::string& keyname, const std::string& valuename ); bool deleteValue( std::string_view keyname, std::string_view valuename );
/** Deletes specified key and all values contained within. /** Deletes specified key and all values contained within.
** @return true if key existed and deleted, false otherwise. */ ** @return true if key existed and deleted, false otherwise. */
bool deleteKey( const std::string& keyname ); bool deleteKey( std::string_view keyname );
/** Header comment functions. /** Header comment functions.
** Header comments are those comments before the first key. ** Header comments are those comments before the first key.
@@ -208,7 +199,7 @@ class EE_API IniFile {
unsigned numHeaderComments() { return (unsigned int)mComments.size(); } unsigned numHeaderComments() { return (unsigned int)mComments.size(); }
/** Add a header comment. */ /** Add a header comment. */
void addHeaderComment( const std::string& comment ); void addHeaderComment( std::string_view comment );
/** Return a header comment. */ /** Return a header comment. */
std::string getHeaderComment( unsigned const commentID ) const; std::string getHeaderComment( unsigned const commentID ) const;
@@ -221,12 +212,12 @@ class EE_API IniFile {
std::map<std::string, std::string> getKeyMap( const unsigned& keyID ) const; std::map<std::string, std::string> getKeyMap( const unsigned& keyID ) const;
std::map<std::string, std::string> getKeyMap( const std::string& keyname ) const; std::map<std::string, std::string> getKeyMap( std::string_view keyname ) const;
std::unordered_map<std::string, std::string> getKeyUnorderedMap( const unsigned& keyID ) const; std::unordered_map<std::string, std::string> getKeyUnorderedMap( const unsigned& keyID ) const;
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
getKeyUnorderedMap( const std::string& keyname ) const; getKeyUnorderedMap( std::string_view keyname ) const;
/** Key comment functions. /** Key comment functions.
** Key comments are those comments within a key. Any comments ** Key comments are those comments within a key. Any comments
@@ -235,44 +226,45 @@ class EE_API IniFile {
** the IniFile::writeFile() is called. ** the IniFile::writeFile() is called.
** Number of key comments. */ ** Number of key comments. */
unsigned getNumKeyComments( unsigned const keyID ) const; unsigned getNumKeyComments( unsigned const keyID ) const;
unsigned getNumKeyComments( const std::string& keyname ) const; unsigned getNumKeyComments( std::string_view keyname ) const;
/** Add a key comment.*/ /** Add a key comment.*/
bool addKeyComment( unsigned const keyID, const std::string& comment ); bool addKeyComment( unsigned const keyID, std::string_view comment );
bool addKeyComment( unsigned const keyID, const std::string_view& comment ); bool addKeyComment( std::string_view keyname, std::string_view comment );
bool addKeyComment( const std::string& keyname, const std::string& comment );
bool addKeyComment( const std::string_view& keyname, const std::string_view& comment );
/** Return a key comment. */ /** Return a key comment. */
std::string getKeyComment( unsigned const keyID, unsigned const commentID ) const; std::string getKeyComment( unsigned const keyID, unsigned const commentID ) const;
std::string getKeyComment( const std::string& keyname, unsigned const commentID ) const; std::string getKeyComment( std::string_view keyname, unsigned const commentID ) const;
/** Delete a key comment. */ /** Delete a key comment. */
bool deleteKeyComment( unsigned const keyID, unsigned const commentID ); bool deleteKeyComment( unsigned const keyID, unsigned const commentID );
bool deleteKeyComment( const std::string& keyname, unsigned const commentID ); bool deleteKeyComment( std::string_view keyname, unsigned const commentID );
/** Delete all comments for a key. */ /** Delete all comments for a key. */
bool deleteKeyComments( unsigned const keyID ); bool deleteKeyComments( unsigned const keyID );
bool deleteKeyComments( const std::string& keyname ); bool deleteKeyComments( std::string_view keyname );
bool iniParsed() { return mIniRead; } bool iniParsed() { return mIniRead; }
bool keyExists( const std::string& keyname ) const; bool keyExists( std::string_view keyname ) const;
bool keyValueExists( const std::string& keyname, const std::string& valuename ) const; bool keyValueExists( std::string_view keyname, std::string_view valuename ) const;
private: private:
bool mIniRead{ false }; bool mIniRead{ false };
std::string mPath; std::string mPath;
std::string mBuffer; std::string mBuffer;
struct key { struct value {
std::vector<std::string> names; std::string name;
std::vector<std::string> values; std::string data;
std::vector<std::string> comments;
}; };
std::vector<key> mKeys; struct key {
std::vector<std::string> mNames; std::string name;
std::vector<std::string> mComments; SmallVector<value, 2> values;
SmallVector<std::string, 1> comments;
};
SmallVector<key, 4> mKeys;
SmallVector<std::string, 2> mComments;
}; };
}} // namespace EE::System }} // namespace EE::System
+1 -1
View File
@@ -37,7 +37,7 @@ class EE_API DocumentView {
struct VisibleLineInfo { struct VisibleLineInfo {
VisibleIndex visibleIndex{ VisibleIndex::invalid }; VisibleIndex visibleIndex{ VisibleIndex::invalid };
Float paddingStart{ 0 }; Float paddingStart{ 0 };
std::vector<TextPosition> visualLines; SmallVector<TextPosition, 2> visualLines;
}; };
struct VisibleLineRange { struct VisibleLineRange {
+103 -166
View File
@@ -14,7 +14,7 @@
namespace EE { namespace System { namespace EE { namespace System {
IniFile::IniFile( const std::string& iniPath, bool autoLoad ) { IniFile::IniFile( std::string_view iniPath, bool autoLoad ) {
if ( autoLoad ) if ( autoLoad )
loadFromFile( iniPath ); loadFromFile( iniPath );
else else
@@ -26,7 +26,7 @@ IniFile::IniFile( const Uint8* RAWData, const Uint32& size, bool autoLoad ) {
loadFromMemory( RAWData, size ); loadFromMemory( RAWData, size );
} }
IniFile::IniFile( Pack* Pack, const std::string& iniPackPath, bool autoLoad ) { IniFile::IniFile( Pack* Pack, std::string_view iniPackPath, bool autoLoad ) {
if ( autoLoad ) if ( autoLoad )
loadFromPack( Pack, iniPackPath ); loadFromPack( Pack, iniPackPath );
} }
@@ -36,11 +36,12 @@ IniFile::IniFile( IOStream& stream, bool autoLoad ) {
loadFromStream( stream ); loadFromStream( stream );
} }
bool IniFile::loadFromPack( Pack* Pack, const std::string& iniPackPath ) { bool IniFile::loadFromPack( Pack* Pack, std::string_view iniPackPath ) {
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( iniPackPath ) ) { std::string path( iniPackPath );
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( path ) ) {
ScopedBuffer buffer; ScopedBuffer buffer;
Pack->extractFileToMemory( iniPackPath, buffer ); Pack->extractFileToMemory( path, buffer );
return loadFromMemory( buffer.get(), buffer.length() ); return loadFromMemory( buffer.get(), buffer.length() );
} }
@@ -66,14 +67,14 @@ bool IniFile::loadFromMemory( const Uint8* RAWData, const Uint32& size ) {
return loadFromStream( f ); return loadFromStream( f );
} }
bool IniFile::loadFromFile( const std::string& iniPath ) { bool IniFile::loadFromFile( std::string_view iniPath ) {
path( iniPath ); path( iniPath );
if ( FileSystem::fileExists( iniPath ) ) { if ( FileSystem::fileExists( mPath ) ) {
IOStreamFile f( mPath ); IOStreamFile f( mPath );
return loadFromStream( f ); return loadFromStream( f );
} else if ( PackRegistry::instance()->isFallbackToPacksActive() ) { } else if ( PackRegistry::instance()->isFallbackToPacksActive() ) {
std::string tPath( iniPath ); std::string tPath( mPath );
Pack* tPack = PackRegistry::instance()->exists( tPath ); Pack* tPack = PackRegistry::instance()->exists( tPath );
@@ -149,7 +150,7 @@ bool IniFile::readFile() {
break; break;
case ';': case ';':
case '#': case '#':
if ( !mNames.size() ) if ( mKeys.empty() )
addHeaderComment( std::string{ line.substr( pLeft + 1 ) } ); addHeaderComment( std::string{ line.substr( pLeft + 1 ) } );
else else
addKeyComment( keyname, std::string{ line.substr( pLeft + 1 ) } ); addKeyComment( keyname, std::string{ line.substr( pLeft + 1 ) } );
@@ -158,7 +159,7 @@ bool IniFile::readFile() {
} }
} }
if ( mNames.size() ) { if ( !mKeys.empty() ) {
mIniRead = true; mIniRead = true;
return true; return true;
@@ -176,132 +177,113 @@ bool IniFile::writeStream( IOStream& stream ) {
if ( !stream.isOpen() ) if ( !stream.isOpen() )
return false; return false;
unsigned commentID, keyID, valueID; static constexpr char commentPrefix = ';';
std::string str; static constexpr char keyPrefix = '[';
static constexpr char keySuffix[] = "]\n";
static constexpr char valueSeparator = '=';
static constexpr char newline = '\n';
// Write header mComments. // Write header mComments.
for ( commentID = 0; commentID < mComments.size(); ++commentID ) { for ( const auto& comment : mComments ) {
str = ';' + mComments[commentID] + '\n'; stream.write( &commentPrefix, 1 );
stream.write( str.c_str(), str.size() ); stream.write( comment.data(), comment.size() );
stream.write( &newline, 1 );
} }
if ( mComments.size() ) { if ( !mComments.empty() )
str = "\n"; stream.write( &newline, 1 );
stream.write( str.c_str(), str.size() );
}
// Write Keys and values. // Write Keys and values.
for ( keyID = 0; keyID < mKeys.size(); ++keyID ) { for ( const auto& key : mKeys ) {
str = '[' + mNames[keyID] + ']' + '\n'; stream.write( &keyPrefix, 1 );
stream.write( str.c_str(), str.size() ); stream.write( key.name.data(), key.name.size() );
stream.write( keySuffix, sizeof( keySuffix ) - 1 );
// Comments. // Comments.
for ( commentID = 0; commentID < mKeys[keyID].comments.size(); ++commentID ) { for ( const auto& comment : key.comments ) {
str = ';' + mKeys[keyID].comments[commentID] + '\n'; stream.write( &commentPrefix, 1 );
stream.write( str.c_str(), str.size() ); stream.write( comment.data(), comment.size() );
stream.write( &newline, 1 );
} }
// Values. // Values.
for ( valueID = 0; valueID < mKeys[keyID].names.size(); ++valueID ) { for ( const auto& value : key.values ) {
str = mKeys[keyID].names[valueID] + '=' + mKeys[keyID].values[valueID] + '\n'; stream.write( value.name.data(), value.name.size() );
stream.write( str.c_str(), str.size() ); stream.write( &valueSeparator, 1 );
stream.write( value.data.data(), value.data.size() );
stream.write( &newline, 1 );
} }
str = "\n"; stream.write( &newline, 1 );
stream.write( str.c_str(), str.size() );
} }
return true; return true;
} }
long IniFile::findKey( const std::string& keyname ) const { long IniFile::findKey( std::string_view keyname ) const {
for ( unsigned keyID = 0; keyID < mNames.size(); ++keyID ) for ( unsigned keyID = 0; keyID < mKeys.size(); ++keyID )
if ( mNames[keyID] == keyname ) if ( mKeys[keyID].name == keyname )
return long( keyID ); return long( keyID );
return noID; return noID;
} }
long IniFile::findKey( const std::string_view& keyname ) const { long IniFile::findValue( const unsigned int keyID, std::string_view valuename ) const {
for ( unsigned keyID = 0; keyID < mNames.size(); ++keyID )
if ( mNames[keyID] == keyname )
return long( keyID );
return noID;
}
long IniFile::findValue( unsigned const keyID, const std::string& valuename ) const {
if ( !mKeys.size() || keyID >= mKeys.size() ) if ( !mKeys.size() || keyID >= mKeys.size() )
return noID; return noID;
for ( unsigned valueID = 0; valueID < mKeys[keyID].names.size(); ++valueID ) for ( unsigned valueID = 0; valueID < mKeys[keyID].values.size(); ++valueID )
if ( mKeys[keyID].names[valueID] == valuename ) if ( mKeys[keyID].values[valueID].name == valuename )
return long( valueID ); return long( valueID );
return noID; return noID;
} }
long IniFile::findValue( const unsigned int keyID, const std::string_view& valuename ) const { unsigned int IniFile::addKeyName( std::string_view keyname ) {
if ( !mKeys.size() || keyID >= mKeys.size() ) mKeys.push_back( { std::string{ keyname }, {}, {} } );
return noID; return (unsigned int)( mKeys.size() - 1 );
for ( unsigned valueID = 0; valueID < mKeys[keyID].names.size(); ++valueID )
if ( mKeys[keyID].names[valueID] == valuename )
return long( valueID );
return noID;
}
unsigned IniFile::addKeyName( const std::string& keyname ) {
mNames.resize( mNames.size() + 1, keyname );
mKeys.resize( mKeys.size() + 1 );
return (unsigned int)( mNames.size() - 1 );
}
unsigned int IniFile::addKeyName( const std::string_view& keyname ) {
mNames.resize( mNames.size() + 1, std::string{ keyname } );
mKeys.resize( mKeys.size() + 1 );
return (unsigned int)( mNames.size() - 1 );
} }
std::string IniFile::getKeyName( unsigned const keyID ) const { std::string IniFile::getKeyName( unsigned const keyID ) const {
if ( keyID < mNames.size() ) if ( keyID < mKeys.size() )
return mNames[keyID]; return mKeys[keyID].name;
else else
return ""; return "";
} }
unsigned IniFile::getNumValues( unsigned const keyID ) { unsigned IniFile::getNumValues( unsigned const keyID ) {
if ( keyID < mKeys.size() ) if ( keyID < mKeys.size() )
return (unsigned int)mKeys[keyID].names.size(); return (unsigned int)mKeys[keyID].values.size();
return 0; return 0;
} }
unsigned IniFile::getNumValues( const std::string& keyname ) { unsigned IniFile::getNumValues( std::string_view keyname ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return 0; return 0;
return (unsigned int)mKeys[keyID].names.size(); return (unsigned int)mKeys[keyID].values.size();
} }
std::string IniFile::getValueName( unsigned const keyID, unsigned const valueID ) const { std::string IniFile::getValueName( unsigned const keyID, unsigned const valueID ) const {
if ( keyID < mKeys.size() && valueID < mKeys[keyID].names.size() ) if ( keyID < mKeys.size() && valueID < mKeys[keyID].values.size() )
return mKeys[keyID].names[valueID]; return mKeys[keyID].values[valueID].name;
return ""; return "";
} }
std::string IniFile::getValueName( const std::string& keyname, unsigned const valueID ) const { std::string IniFile::getValueName( std::string_view keyname, unsigned const valueID ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return ""; return "";
return getValueName( keyID, valueID ); return getValueName( keyID, valueID );
} }
bool IniFile::setValue( unsigned const keyID, unsigned const valueID, const std::string& value ) { bool IniFile::setValue( unsigned const keyID, unsigned const valueID, std::string_view value ) {
if ( keyID < mKeys.size() && valueID < mKeys[keyID].names.size() ) if ( keyID < mKeys.size() && valueID < mKeys[keyID].values.size() )
mKeys[keyID].values[valueID] = value; mKeys[keyID].values[valueID].data.assign( value );
return false; return false;
} }
bool IniFile::setValue( const std::string& keyname, const std::string& valuename, bool IniFile::setValue( std::string_view keyname, std::string_view valuename,
const std::string& value, bool create ) { std::string_view value, bool create ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) { if ( keyID == noID ) {
if ( create ) if ( create )
@@ -314,37 +296,14 @@ bool IniFile::setValue( const std::string& keyname, const std::string& valuename
if ( valueID == noID ) { if ( valueID == noID ) {
if ( !create ) if ( !create )
return false; return false;
mKeys[keyID].names.resize( mKeys[keyID].names.size() + 1, valuename ); mKeys[keyID].values.push_back( { std::string{ valuename }, std::string{ value } } );
mKeys[keyID].values.resize( mKeys[keyID].values.size() + 1, value );
} else } else
mKeys[keyID].values[valueID] = value; mKeys[keyID].values[valueID].data.assign( value );
return true; return true;
} }
bool IniFile::setValue( const std::string_view& keyname, const std::string_view& valuename, bool IniFile::setValueI( std::string_view keyname, std::string_view valuename, int const value,
const std::string_view& value, bool create ) {
long keyID = findKey( keyname );
if ( keyID == noID ) {
if ( create )
keyID = long( addKeyName( std::string{ keyname } ) );
else
return false;
}
long valueID = findValue( unsigned( keyID ), valuename );
if ( valueID == noID ) {
if ( !create )
return false;
mKeys[keyID].names.resize( mKeys[keyID].names.size() + 1, std::string{ valuename } );
mKeys[keyID].values.resize( mKeys[keyID].values.size() + 1, std::string{ value } );
} else
mKeys[keyID].values[valueID] = value;
return true;
}
bool IniFile::setValueI( const std::string& keyname, const std::string& valuename, int const value,
bool create ) { bool create ) {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
@@ -352,7 +311,7 @@ bool IniFile::setValueI( const std::string& keyname, const std::string& valuenam
return setValue( keyname, valuename, svalue, create ); return setValue( keyname, valuename, svalue, create );
} }
bool IniFile::setValueU( const std::string& keyname, const std::string& valuename, bool IniFile::setValueU( std::string_view keyname, std::string_view valuename,
const unsigned long value, bool create ) { const unsigned long value, bool create ) {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
@@ -360,16 +319,15 @@ bool IniFile::setValueU( const std::string& keyname, const std::string& valuenam
return setValue( keyname, valuename, svalue, create ); return setValue( keyname, valuename, svalue, create );
} }
bool IniFile::setValueF( const std::string& keyname, const std::string& valuename, bool IniFile::setValueF( std::string_view keyname, std::string_view valuename, double const value,
double const value, bool create ) { bool create ) {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
String::formatBuffer( svalue, MAX_VALUEDATA, "%f", value ); String::formatBuffer( svalue, MAX_VALUEDATA, "%f", value );
return setValue( keyname, valuename, svalue, create ); return setValue( keyname, valuename, svalue, create );
} }
bool IniFile::setValueV( const std::string& keyname, const std::string& valuename, char* format, bool IniFile::setValueV( std::string_view keyname, std::string_view valuename, char* format, ... ) {
... ) {
va_list args; va_list args;
char value[MAX_VALUEDATA]; char value[MAX_VALUEDATA];
@@ -384,26 +342,26 @@ bool IniFile::setValueV( const std::string& keyname, const std::string& valuenam
} }
std::string IniFile::getValue( unsigned const keyID, unsigned const valueID, std::string IniFile::getValue( unsigned const keyID, unsigned const valueID,
const std::string& defValue ) const { std::string_view defValue ) const {
if ( keyID < mKeys.size() && valueID < mKeys[keyID].names.size() ) if ( keyID < mKeys.size() && valueID < mKeys[keyID].values.size() )
return mKeys[keyID].values[valueID]; return mKeys[keyID].values[valueID].data;
return defValue; return std::string{ defValue };
} }
std::string IniFile::getValue( const std::string& keyname, const std::string& valuename, std::string IniFile::getValue( std::string_view keyname, std::string_view valuename,
const std::string& defValue ) const { std::string_view defValue ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return defValue; return std::string{ defValue };
long valueID = findValue( unsigned( keyID ), valuename ); long valueID = findValue( unsigned( keyID ), valuename );
if ( valueID == noID ) if ( valueID == noID )
return defValue; return std::string{ defValue };
return mKeys[keyID].values[valueID]; return mKeys[keyID].values[valueID].data;
} }
int IniFile::getValueI( const std::string& keyname, const std::string& valuename, int IniFile::getValueI( std::string_view keyname, std::string_view valuename,
int const defValue ) const { int const defValue ) const {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
@@ -411,7 +369,7 @@ int IniFile::getValueI( const std::string& keyname, const std::string& valuename
return atoi( getValue( keyname, valuename, svalue ).c_str() ); return atoi( getValue( keyname, valuename, svalue ).c_str() );
} }
unsigned long IniFile::getValueU( const std::string& keyname, const std::string& valuename, unsigned long IniFile::getValueU( std::string_view keyname, std::string_view valuename,
const unsigned long defValue ) const { const unsigned long defValue ) const {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
@@ -419,14 +377,14 @@ unsigned long IniFile::getValueU( const std::string& keyname, const std::string&
return atoi( getValue( keyname, valuename, svalue ).c_str() ); return atoi( getValue( keyname, valuename, svalue ).c_str() );
} }
bool IniFile::getValueB( const std::string& keyname, const std::string& valuename, bool IniFile::getValueB( std::string_view keyname, std::string_view valuename,
const bool defValue ) const { const bool defValue ) const {
std::string val = getValue( keyname, valuename, defValue ? "1" : "0" ); std::string val = getValue( keyname, valuename, defValue ? "1" : "0" );
char fist = !val.empty() ? val[0] : '0'; char fist = !val.empty() ? val[0] : '0';
return fist == '1' || fist == 't' || fist == 'y' || fist == 'T' || fist == 'Y'; return fist == '1' || fist == 't' || fist == 'y' || fist == 'T' || fist == 'Y';
} }
double IniFile::getValueF( const std::string& keyname, const std::string& valuename, double IniFile::getValueF( std::string_view keyname, std::string_view valuename,
double const defValue ) const { double const defValue ) const {
char svalue[MAX_VALUEDATA]; char svalue[MAX_VALUEDATA];
@@ -434,7 +392,7 @@ double IniFile::getValueF( const std::string& keyname, const std::string& valuen
return atof( getValue( keyname, valuename, svalue ).c_str() ); return atof( getValue( keyname, valuename, svalue ).c_str() );
} }
bool IniFile::deleteValue( const std::string& keyname, const std::string& valuename ) { bool IniFile::deleteValue( std::string_view keyname, std::string_view valuename ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
@@ -443,37 +401,30 @@ bool IniFile::deleteValue( const std::string& keyname, const std::string& valuen
if ( valueID == noID ) if ( valueID == noID )
return false; return false;
// This looks strange, but is necessary. auto pos = mKeys[keyID].values.begin() + valueID;
std::vector<std::string>::iterator npos = mKeys[keyID].names.begin() + valueID; mKeys[keyID].values.erase( pos );
std::vector<std::string>::iterator vpos = mKeys[keyID].values.begin() + valueID;
mKeys[keyID].names.erase( npos, npos + 1 );
mKeys[keyID].values.erase( vpos, vpos + 1 );
return true; return true;
} }
bool IniFile::deleteKey( const std::string& keyname ) { bool IniFile::deleteKey( std::string_view keyname ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
std::vector<std::string>::iterator npos = mNames.begin() + keyID; mKeys.erase( mKeys.begin() + keyID );
std::vector<key>::iterator kpos = mKeys.begin() + keyID;
mNames.erase( npos, npos + 1 );
mKeys.erase( kpos, kpos + 1 );
return true; return true;
} }
void IniFile::clear() { void IniFile::clear() {
mIniRead = false; mIniRead = false;
mNames.clear();
mKeys.clear(); mKeys.clear();
mComments.clear(); mComments.clear();
} }
void IniFile::addHeaderComment( const std::string& comment ) { void IniFile::addHeaderComment( std::string_view comment ) {
mComments.resize( mComments.size() + 1, comment ); mComments.emplace_back( comment );
} }
std::string IniFile::getHeaderComment( unsigned const commentID ) const { std::string IniFile::getHeaderComment( unsigned const commentID ) const {
@@ -484,7 +435,7 @@ std::string IniFile::getHeaderComment( unsigned const commentID ) const {
bool IniFile::deleteHeaderComment( unsigned commentID ) { bool IniFile::deleteHeaderComment( unsigned commentID ) {
if ( commentID < mComments.size() ) { if ( commentID < mComments.size() ) {
std::vector<std::string>::iterator cpos = mComments.begin() + commentID; auto cpos = mComments.begin() + commentID;
mComments.erase( cpos, cpos + 1 ); mComments.erase( cpos, cpos + 1 );
return true; return true;
} }
@@ -494,15 +445,15 @@ bool IniFile::deleteHeaderComment( unsigned commentID ) {
std::map<std::string, std::string> IniFile::getKeyMap( const unsigned& keyID ) const { std::map<std::string, std::string> IniFile::getKeyMap( const unsigned& keyID ) const {
std::map<std::string, std::string> map; std::map<std::string, std::string> map;
if ( keyID < mKeys.size() ) { if ( keyID < mKeys.size() ) {
for ( size_t i = 0; i < mKeys[keyID].names.size(); i++ ) { for ( const auto& value : mKeys[keyID].values ) {
map[mKeys[keyID].names[i]] = mKeys[keyID].values[i]; map[value.name] = value.data;
} }
return map; return map;
} }
return {}; return {};
} }
std::map<std::string, std::string> IniFile::getKeyMap( const std::string& keyname ) const { std::map<std::string, std::string> IniFile::getKeyMap( std::string_view keyname ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID != noID ) if ( keyID != noID )
return getKeyMap( keyID ); return getKeyMap( keyID );
@@ -513,8 +464,9 @@ std::unordered_map<std::string, std::string>
IniFile::getKeyUnorderedMap( const unsigned& keyID ) const { IniFile::getKeyUnorderedMap( const unsigned& keyID ) const {
std::unordered_map<std::string, std::string> map; std::unordered_map<std::string, std::string> map;
if ( keyID < mKeys.size() ) { if ( keyID < mKeys.size() ) {
for ( size_t i = 0; i < mKeys[keyID].names.size(); i++ ) { map.reserve( mKeys[keyID].values.size() );
map[mKeys[keyID].names[i]] = mKeys[keyID].values[i]; for ( const auto& value : mKeys[keyID].values ) {
map.emplace( value.name, value.data );
} }
return map; return map;
} }
@@ -522,7 +474,7 @@ IniFile::getKeyUnorderedMap( const unsigned& keyID ) const {
} }
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
IniFile::getKeyUnorderedMap( const std::string& keyname ) const { IniFile::getKeyUnorderedMap( std::string_view keyname ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID != noID ) if ( keyID != noID )
return getKeyUnorderedMap( keyID ); return getKeyUnorderedMap( keyID );
@@ -535,37 +487,22 @@ unsigned IniFile::getNumKeyComments( unsigned const keyID ) const {
return 0; return 0;
} }
unsigned IniFile::getNumKeyComments( const std::string& keyname ) const { unsigned IniFile::getNumKeyComments( std::string_view keyname ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return 0; return 0;
return (unsigned int)mKeys[keyID].comments.size(); return (unsigned int)mKeys[keyID].comments.size();
} }
bool IniFile::addKeyComment( unsigned const keyID, const std::string& comment ) { bool IniFile::addKeyComment( unsigned const keyID, std::string_view comment ) {
if ( keyID < mKeys.size() ) { if ( keyID < mKeys.size() ) {
mKeys[keyID].comments.resize( mKeys[keyID].comments.size() + 1, comment ); mKeys[keyID].comments.emplace_back( comment );
return true; return true;
} }
return false; return false;
} }
bool IniFile::addKeyComment( unsigned const keyID, const std::string_view& comment ) { bool IniFile::addKeyComment( std::string_view keyname, std::string_view comment ) {
if ( keyID < mKeys.size() ) {
mKeys[keyID].comments.resize( mKeys[keyID].comments.size() + 1, std::string{ comment } );
return true;
}
return false;
}
bool IniFile::addKeyComment( const std::string& keyname, const std::string& comment ) {
long keyID = findKey( keyname );
if ( keyID == noID )
return false;
return addKeyComment( unsigned( keyID ), comment );
}
bool IniFile::addKeyComment( const std::string_view& keyname, const std::string_view& comment ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
@@ -578,7 +515,7 @@ std::string IniFile::getKeyComment( unsigned const keyID, unsigned const comment
return ""; return "";
} }
std::string IniFile::getKeyComment( const std::string& keyname, unsigned const commentID ) const { std::string IniFile::getKeyComment( std::string_view keyname, unsigned const commentID ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return ""; return "";
@@ -587,14 +524,14 @@ std::string IniFile::getKeyComment( const std::string& keyname, unsigned const c
bool IniFile::deleteKeyComment( unsigned const keyID, unsigned const commentID ) { bool IniFile::deleteKeyComment( unsigned const keyID, unsigned const commentID ) {
if ( keyID < mKeys.size() && commentID < mKeys[keyID].comments.size() ) { if ( keyID < mKeys.size() && commentID < mKeys[keyID].comments.size() ) {
std::vector<std::string>::iterator cpos = mKeys[keyID].comments.begin() + commentID; auto cpos = mKeys[keyID].comments.begin() + commentID;
mKeys[keyID].comments.erase( cpos, cpos + 1 ); mKeys[keyID].comments.erase( cpos, cpos + 1 );
return true; return true;
} }
return false; return false;
} }
bool IniFile::deleteKeyComment( const std::string& keyname, unsigned const commentID ) { bool IniFile::deleteKeyComment( std::string_view keyname, unsigned const commentID ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
@@ -609,18 +546,18 @@ bool IniFile::deleteKeyComments( unsigned const keyID ) {
return false; return false;
} }
bool IniFile::deleteKeyComments( const std::string& keyname ) { bool IniFile::deleteKeyComments( std::string_view keyname ) {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
return deleteKeyComments( unsigned( keyID ) ); return deleteKeyComments( unsigned( keyID ) );
} }
bool IniFile::keyExists( const std::string& keyname ) const { bool IniFile::keyExists( std::string_view keyname ) const {
return findKey( keyname ) != noID; return findKey( keyname ) != noID;
} }
bool IniFile::keyValueExists( const std::string& keyname, const std::string& valuename ) const { bool IniFile::keyValueExists( std::string_view keyname, std::string_view valuename ) const {
long keyID = findKey( keyname ); long keyID = findKey( keyname );
if ( keyID == noID ) if ( keyID == noID )
return false; return false;
+107
View File
@@ -0,0 +1,107 @@
#include "utest.hpp"
#include <eepp/system/inifile.hpp>
#include <eepp/system/iostreamstring.hpp>
using namespace EE::System;
UTEST( IniFile, preservesInsertionOrderAndSerializes ) {
IniFile ini( "", false );
ini.addHeaderComment( "header" );
ini.setValue( std::string_view{ "project" }, std::string_view{ "path" },
std::string_view{ "/tmp/project" } );
ini.setValue( std::string_view{ "project" }, std::string_view{ "session" },
std::string_view{ "open" } );
ini.addKeyComment( std::string_view{ "project" }, std::string_view{ "state" } );
ini.setValueI( "editor", "tab_width", 4 );
IOStreamString stream;
EXPECT_TRUE( ini.writeStream( stream ) );
EXPECT_STDSTREQ( ";header\n\n[project]\n;state\npath=/tmp/project\nsession=open\n\n"
"[editor]\ntab_width=4\n\n",
stream.getStream() );
EXPECT_EQ( 2u, ini.getNumKeys() );
EXPECT_STDSTREQ( "project", ini.getKeyName( 0 ) );
EXPECT_STDSTREQ( "session", ini.getValueName( 0, 1 ) );
EXPECT_STDSTREQ( "open", ini.getValue( 0, 1 ) );
}
UTEST( IniFile, parsesUpdatesAndDeletesValues ) {
const std::string source =
"[project]\npath=/tmp/project\nsession=open\n\n[editor]\ntab_width=4\n";
IniFile ini( reinterpret_cast<const EE::Uint8*>( source.data() ),
static_cast<EE::Uint32>( source.size() ) );
EXPECT_TRUE( ini.iniParsed() );
EXPECT_TRUE( ini.setValue( std::string_view{ "project" }, std::string_view{ "session" },
std::string_view{ "closed" } ) );
EXPECT_TRUE( ini.deleteValue( "project", "path" ) );
EXPECT_EQ( 1u, ini.getNumValues( "project" ) );
EXPECT_STDSTREQ( "closed", ini.getValue( "project", "session" ) );
EXPECT_TRUE( ini.deleteKey( "editor" ) );
EXPECT_EQ( 1u, ini.getNumKeys() );
}
UTEST( IniFile, ecodeProjectStateRoundTripsByteForByte ) {
IniFile project( "/tmp/project.cfg", false );
auto set = [&project]( std::string_view key, std::string_view name, std::string_view data ) {
return project.setValue( key, name, data );
};
EXPECT_TRUE( set( "path", "folder_path", "/home/user/projects/eepp/" ) );
project.setValueB( "project_tree", "show_hidden_files", true );
project.setValueB( "document", "use_global_settings", false );
EXPECT_TRUE( set( "document", "h_ext_language_type", "cpp" ) );
project.setValueB( "document", "trim_trailing_whitespaces", true );
project.setValueB( "document", "force_new_line_at_end_of_file", true );
project.setValueB( "document", "auto_detect_indent_type", false );
EXPECT_TRUE( set( "document", "auto_indent", "keep-indentation" ) );
project.setValueB( "document", "write_bom", false );
project.setValueI( "document", "indent_width", 4 );
project.setValueB( "document", "indent_spaces", false );
EXPECT_TRUE( set( "document", "line_endings", "LF" ) );
project.setValueI( "document", "tab_width", 4 );
project.setValueI( "document", "line_breaking_column", 100 );
EXPECT_TRUE( set( "build", "build_name", "eepp-linux-ninja" ) );
EXPECT_TRUE( set( "build", "build_type", "release" ) );
EXPECT_TRUE( set( "build", "run_name", "ecode" ) );
EXPECT_TRUE( set(
"nodes", "documents",
R"({"type":"splitter","first":{"type":"tabwidget","files":[{"type":"editor","path":"/home/user/projects/eepp/src/tools/ecode/appconfig.cpp"}]},"last":{"type":"tabwidget","files":[]}})" ) );
EXPECT_TRUE( set( "languages_extensions", ".h", "cpp" ) );
EXPECT_TRUE( set( "languages_extensions", ".inl", "cpp" ) );
const std::string expected =
"[path]\nfolder_path=/home/user/projects/eepp/\n\n"
"[project_tree]\nshow_hidden_files=1\n\n"
"[document]\nuse_global_settings=0\nh_ext_language_type=cpp\n"
"trim_trailing_whitespaces=1\nforce_new_line_at_end_of_file=1\n"
"auto_detect_indent_type=0\nauto_indent=keep-indentation\nwrite_bom=0\n"
"indent_width=4\nindent_spaces=0\nline_endings=LF\ntab_width=4\n"
"line_breaking_column=100\n\n"
"[build]\nbuild_name=eepp-linux-ninja\nbuild_type=release\nrun_name=ecode\n\n"
"[nodes]\ndocuments={\"type\":\"splitter\",\"first\":{\"type\":\"tabwidget\","
"\"files\":[{\"type\":\"editor\",\"path\":\"/home/user/projects/eepp/src/tools/"
"ecode/appconfig.cpp\"}]},\"last\":{\"type\":\"tabwidget\",\"files\":[]}}\n\n"
"[languages_extensions]\n.h=cpp\n.inl=cpp\n\n";
IOStreamString firstWrite;
EXPECT_TRUE( project.writeStream( firstWrite ) );
EXPECT_STDSTREQ( expected, firstWrite.getStream() );
IniFile reloaded( reinterpret_cast<const EE::Uint8*>( expected.data() ),
static_cast<EE::Uint32>( expected.size() ) );
EXPECT_TRUE( reloaded.iniParsed() );
EXPECT_STDSTREQ( "/home/user/projects/eepp/", reloaded.getValue( "path", "folder_path" ) );
EXPECT_EQ( 100, reloaded.getValueI( "document", "line_breaking_column" ) );
EXPECT_TRUE( reloaded.getValueB( "project_tree", "show_hidden_files" ) );
EXPECT_FALSE( reloaded.setValue( std::string_view{ "missing" }, std::string_view{ "value" },
std::string_view{ "data" }, false ) );
EXPECT_TRUE( reloaded.setValue( std::string_view{ "build" }, std::string_view{ "run_name" },
std::string_view{ "ecode" }, false ) );
IOStreamString secondWrite;
EXPECT_TRUE( reloaded.writeStream( secondWrite ) );
EXPECT_STDSTREQ( expected, secondWrite.getStream() );
}
+1 -1
View File
@@ -735,7 +735,7 @@ void ProjectBuildManager::cancelRun() {
mProcessRun->kill(); mProcessRun->kill();
} }
ProjectBuildConfiguration ProjectBuildManager::getConfig() const { const ProjectBuildConfiguration& ProjectBuildManager::getConfig() const {
return mConfig; return mConfig;
} }
+1 -1
View File
@@ -326,7 +326,7 @@ class ProjectBuildManager {
void cancelRun(); void cancelRun();
ProjectBuildConfiguration getConfig() const; const ProjectBuildConfiguration& getConfig() const;
void setConfig( const ProjectBuildConfiguration& config ); void setConfig( const ProjectBuildConfiguration& config );