diff --git a/src/openrct2/config.c b/src/openrct2/config.c index b329f66bc8..3368fe5cb0 100644 --- a/src/openrct2/config.c +++ b/src/openrct2/config.c @@ -338,7 +338,7 @@ network_configuration gConfigNetwork; notification_configuration gConfigNotifications; font_configuration gConfigFonts; -static bool config_open(const utf8string path); +bool config_open(const utf8string path); static bool config_save(const utf8string path); static void config_read_properties(config_section_definition **currentSection, const_utf8string line); static void config_save_property_value(SDL_RWops *file, uint8 type, value_union *value); @@ -500,7 +500,7 @@ bool config_save_default() return false; } -bool config_open(const utf8string path) +bool config_open_2(const utf8string path) { SDL_RWops *file; utf8string lineBuffer; diff --git a/src/openrct2/config/IniReader.cpp b/src/openrct2/config/IniReader.cpp new file mode 100644 index 0000000000..454abe3098 --- /dev/null +++ b/src/openrct2/config/IniReader.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include "../common.h" +#include "../core/FileStream.hpp" +#include "../core/String.hpp" + +class ConfigEnum +{ + +}; + +class IniReader +{ +private: + std::vector _buffer; + std::vector> _lines; + std::unordered_map _sections; + +public: + IniReader(const std::string &path) + { + auto fs = FileStream(path, FILE_MODE_OPEN); + uint64 length = fs.GetLength(); + _buffer.resize(length); + fs.Read(_buffer.data(), length); + + RemoveBOM(); + + // Ensure there is a null terminator on the end, this is + // mainly for ParseLines's sake + if (_buffer[length - 1] != 0) + { + _buffer.push_back(0); + } + + ParseLines(); + ParseSections(); + } + + bool ReadSection(const std::string &name) + { + auto it = _sections.find(name); + if (it == _sections.end()) + { + return false; + } + + size_t startLine = it->second; + UNUSED(startLine); + return true; + } + + bool GetBoolean(const std::string &name, bool defaultValue) + { + + } + + sint32 GetSint32(const std::string &name, sint32 defaultValue, const ConfigEnum * configEnum = nullptr) + { + + } + + std::string GetString(const std::string &name, const std::string &defaultValue) + { + + } + +private: + void RemoveBOM() + { + utf8 * file = (utf8 *)_buffer.data(); + utf8 * content = String::SkipBOM(file); + if (file != content) + { + size_t skipLength = content - file; + _buffer.erase(_buffer.begin(), _buffer.begin() + skipLength); + } + } + + void ParseLines() + { + size_t lineBegin = 0; + bool onNewLineCh = false; + for (size_t i = 0; i < _buffer.size(); i++) + { + char b = (char)_buffer[i]; + if (b == 0 || b == '\n' || b == '\r') + { + if (!onNewLineCh) + { + onNewLineCh = true; + size_t lineEnd = i; + _lines.emplace_back(lineBegin, lineEnd - lineBegin); + } + } + else if (onNewLineCh) + { + onNewLineCh = false; + lineBegin = i; + } + } + } + + void ParseSections() + { + for (size_t i = 0; i < _lines.size(); i++) + { + std::string line = GetLine(i); + line = String::Trim(line); + if (line.size() > 3 && line[0] == '[') + { + size_t endIndex = line.find_first_of(']'); + std::string sectionName = line.substr(1, endIndex - 1); + _sections[sectionName] = i; + } + } + } + + std::string GetLine(size_t index) + { + utf8 * szBuffer = (utf8 *)_buffer.data(); + auto span = _lines[index]; + auto line = std::string(szBuffer + std::get<0>(span), std::get<1>(span)); + return line; + } +}; + +extern "C" +{ + bool config_open(const utf8 * path) + { + auto iniReader = IniReader(path); + bool b = iniReader.ReadSection("general"); + UNUSED(b); + + return false; + } +} diff --git a/src/openrct2/config/IniReader.h b/src/openrct2/config/IniReader.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/src/openrct2/config/IniReader.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index 68c9ad85ba..bc8a0035a7 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -393,4 +393,44 @@ namespace String { return String::Set(buffer, bufferSize, TrimStart(src)); } + + std::string Trim(const std::string &s) + { + const utf8 * firstNonWhitespace = nullptr; + + codepoint_t codepoint; + const utf8 * ch = s.c_str(); + const utf8 * nextCh; + while ((codepoint = GetNextCodepoint(ch, &nextCh)) != '\0') + { + bool isWhiteSpace = codepoint <= WCHAR_MAX && iswspace((wchar_t)codepoint); + if (isWhiteSpace) + { + if (firstNonWhitespace != nullptr) + { + break; + } + } + else + { + if (firstNonWhitespace == nullptr) + { + firstNonWhitespace = ch; + } + } + ch = nextCh; + } + + if (firstNonWhitespace != nullptr && + firstNonWhitespace != s.c_str()) + { + size_t newStringSize = ch - firstNonWhitespace; + return std::string(firstNonWhitespace, newStringSize); + } + else + { + size_t newStringSize = ch - s.c_str(); + return std::string(s.c_str(), newStringSize); + } + } } diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index 287c1c3cd0..427374b2af 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -75,4 +75,5 @@ namespace String utf8 * Trim(utf8 * str); const utf8 * TrimStart(const utf8 * str); utf8 * TrimStart(utf8 * buffer, size_t bufferSize, const utf8 * src); + std::string Trim(const std::string &s); } diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 601b403f64..c842c27096 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -72,6 +72,7 @@ + @@ -419,6 +420,7 @@ +