<commit_before>// Copyright (c) 2017 <NAME>
#include "Jewel3D/Precompiled.h"
#include "ConfigTable.h"
#include "Jewel3D/Application/FileSystem.h"
#include "Jewel3D/Utilities/String.h"

namespace
{
	template<typename Func>
	void ProcessArrayElements(std::string_view array, Func&& functor)
	{
		if (array.empty())
			return;

		const char* currentPos = array.data();
		const char* currentElementStart = currentPos;
		const char* end = currentPos + array.size();
		while (currentPos != end)
		{
			if (*currentPos == ',')
			{
				functor(std::string_view(currentElementStart, currentPos - currentElementStart));
				currentElementStart = currentPos + 1;
			}

			++currentPos;
		}

		functor(std::string_view(currentElementStart, end - currentElementStart));
	}
}

namespace Jwl
{
	bool ConfigTable::Load(std::string_view file)
	{
		FileReader input;
		if (!input.OpenAsBuffer(file))
		{
			return false;
		}

		while (!input.IsEOF())
		{
			std::string line = input.GetLine();

			if (line.empty() || line[0] == ':')
				continue;

			// Check that the position is valid and not the last character.
			size_t pos = line.find('=');
			if (pos == std::string::npos || pos == line.size() - 1)
				continue;

			std::string leftSide = line.substr(0, pos);
			std::string rightSide = line.substr(pos + 1);

			settings[leftSide] = rightSide;
		}

		return true;
	}

	bool ConfigTable::Save(std::string_view file) const
	{
		std::ofstream output(file.data());
		if (!output)
		{
			return false;
		}

		for (auto& [name, value] : settings)
		{
			output << name << '=' << value << '\n';
		}

		return true;<commit_msg>ConfigTable now allows empty values to be loaded<commit_after>// Copyright (c) 2017 <NAME>
#include "Jewel3D/Precompiled.h"
#include "ConfigTable.h"
#include "Jewel3D/Application/FileSystem.h"
#include "Jewel3D/Utilities/String.h"

namespace
{
	template<typename Func>
	void ProcessArrayElements(std::string_view array, Func&& functor)
	{
		if (array.empty())
			return;

		const char* currentPos = array.data();
		const char* currentElementStart = currentPos;
		const char* end = currentPos + array.size();
		while (currentPos != end)
		{
			if (*currentPos == ',')
			{
				functor(std::string_view(currentElementStart, currentPos - currentElementStart));
				currentElementStart = currentPos + 1;
			}

			++currentPos;
		}

		functor(std::string_view(currentElementStart, end - currentElementStart));
	}
}

namespace Jwl
{
	bool ConfigTable::Load(std::string_view file)
	{
		FileReader input;
		if (!input.OpenAsBuffer(file))
		{
			return false;
		}

		while (!input.IsEOF())
		{
			std::string line = input.GetLine();

			if (line.empty() || line[0] == ':')
				continue;

			size_t pos = line.find('=');
			if (pos == std::string::npos)
				continue;

			std::string leftSide = line.substr(0, pos);
			std::string rightSide;
			if (pos != line.size() - 1)
			{
				rightSide = line.substr(pos + 1);
			}

			settings[std::move(leftSide)] = std::move(rightSide);
		}

		return true;
	}

	bool ConfigTable::Save(std::string_view file) const
	{
		std::ofstream output(file.data());
		if (!output)
		{
			return false;
		}

		for (auto& [name, value] : settings)
		{
			output << name << '=' << value << '\n';
		}

		return true;
{'fraction_non_alphanumeric': 0.155980271270037, 'fraction_numerical': 0.007398273736128237, 'mean_word_length': 3.7165697674418605, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3817611', 'n_tokens_mistral': 1298, 'n_tokens_neox': 1105, 'n_words': 249}