Read each entry from ini file

I built a plugin to make persistent changes to scability settings, following Ramma tutorials on the wiki. Now I’m writing some variables on the GameIni like: Mouse Sensitivity and Volume.

What I’d like is to read them all and return to the bp. I found this: https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Misc/FConfigCacheIni/ForEachEntry/index.html but I don’t know how to use it.

USManager::GetGameSettings(){

	FString Section = "GameSettings";

	GConfig->ForEachEntry(
		SOMETHING_HERE_I_DONT_KNOW_WHAT
		*Section,
		GGameIni
		);

}

And how do I retrieve the values?

Thank you for reading.


Edit¹

Here is the function (from Engine\Source\Runtime\Core\Private\Misc):

bool FConfigCacheIni::ForEachEntry(const FKeyValueSink& Visitor, const TCHAR* Section, const FString& Filename)
{
	FConfigFile* File = Find(Filename, 0);
	if(!File)
	{
		return false;
	}

	FConfigSection* Sec = File->Find(Section);
	if(!Sec)
	{
		return false;
	}

	for(FConfigSectionMap::TIterator It(*Sec); It; ++It)
	{
		Visitor.Execute(*It.Key().GetPlainNameString(), *It.Value());
	}

	return true;
}

Breaking down to this part: **Visitor.Execute(It.Key().GetPlainNameString(), It.Value());


Edit²

Found this: DECLARE_DELEGATE_TwoParams(FKeyValueSink, const TCHAR, const TCHAR);**

And this: https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Delegates/index.html.
Yet, I don’t know what to do.


Edit³

I made a class:

class FGetFromIni
{
public:
	static void OnEntry(const TCHAR *Key, const TCHAR* Value)
	{
	}

	static TArray<FString> KeyAndValues;
};

And I’m calling:

TArray<FString> OMSPlugin::GetFromIni(FString Section)
{	
	GConfig->ForEachEntry(FKeyValueSink::CreateStatic(&FGetFromIni::OnEntry), *Section, GGameIni);
	
	return FGetFromIni::KeyAndValues;

Now I’m getting the error: error LNK2001: unresolved external symbol "public: static class TArray FGetFromIni::KeyAndValues"

Take a look at FKeyValueSink &. The F describes that it’s a function reference, I believe it will look something like this:

value_T lambda(key_T, value_T)

Which is an anonymous function that likely takes in a Key Type and a Value Type as parameters and returns a Value Type, or perhaps does something else. I’m not near my project computer right now or I would, but I urge you to go to Visual Studio and right-click on FKeyValueSink and ‘Go to Definition’ and see what kind of values it takes and returns. Likely what is going to happen is that it will go through and for each individual entry in the .ini file it will “Visit” it, which means that it applies the function to it. This function could sum to an internal cache, or it might return a value back to each line it visits, so you can edit the line. I’m not really sure.

This kind of passing function-by-reference is a trope of functional programming.

Here’s some helpful pages:

I edited the main post.

Tried a lot of things like this:

GConfig->ForEachEntry(
		[](&k, &v) { return v; },
		*Section,
		GGameIni
	);

[](FString &k, FString &v) { return v; }

[](k, v) { return v; }

I’m just shooting everywhere, I don’t even know what I’m doing.

Hi Ringeril, have you solved this yet? 'cause I have the same problem here, and I can’t find anything about it

Well, that for loop in the implementation of ForEachEntry() function actually tell us how to access each entry by using an iterator, you should override that function, or use that implementation in your code directly.

//...
//...
for(FConfigSectionMap::TIterator It(*Sec); It; ++It)
{
     Visitor.Execute(*It.Key().GetPlainNameString(), *It.Value());
}

Answering an older post, but here’s how you would handle it using delegates for anyone that stumbles across this today.

To fill in for the SOMETHING_HERE_I_DONT_KNOW_WHAT in the original poster’s question:
In their USManager.h class definition:

Class USManager
{
public:
    // public things here
private:
    FKeyValueSink _keyValueSink; // This is the actual sink delegate, or pointer to our HandleSink function
    void HandleSink(const TCHAR* key, const TCHAR* value); // Callback function called for each key/value
}

In their USManager.cpp implementation:

// In the constructor of the USManager object, bind the delegate to our callback function
USManager::USManager() {
    _keyValueSink.BindSP(this, &USManager::HandleSink);
}
 
    // Implementation of the callback
    void USManager::HandleSink(const TCHAR* key, const TCHAR* value) {
    // TODO: whatever you want for each key/value pair 
}
    
USManager::GetGameSettings(){
     
     FString Section = "GameSettings";
     
     GConfig->ForEachEntry(
         _keyValueSink,
         *Section,
         GGameIni
         );
     
}