Files
projectm/src/libprojectM/PresetFileParser.hpp
Kai Blaschke f0bad56ca1 Treat keys in FileParser case-insensitively
Presets and user sprites could use any casing for the keys, so we should also behave properly.
2025-02-27 15:55:14 +01:00

132 lines
5.1 KiB
C++

#pragma once
#include <map>
#include <string>
namespace libprojectM {
/**
* @brief Milkdrop preset file parser
*
* Reads in the file as key/value pairs, where the key is either separated from the value by an equal sign or a space.
* Lines not matching this pattern are simply ignored, e.g. the [preset00] INI section.
*
* Values and code blocks can easily be accessed via the helper functions. It is also possible to access the parsed
* map contents directly if required.
*/
class PresetFileParser
{
public:
using ValueMap = std::map<std::string, std::string>; //!< A map with key/value pairs, each representing one line in the preset file.
static constexpr size_t maxFileSize = 0x100000; //!< Maximum size of a preset file. Used for sanity checks.
/**
* @brief Reads the preset file into an internal map to prepare for parsing.
* @return True if the file was parsed successfully, false if an error occurred or no line could be parsed.
*/
[[nodiscard]] auto Read(const std::string& presetFile) -> bool;
/**
* @brief Reads the data stream into an internal map to prepare for parsing.
* @return True if the stream was parsed successfully, false if an error occurred or no line could be parsed.
*/
[[nodiscard]] auto Read(std::istream& presetStream) -> bool;
/**
* @brief Returns a block of code, ready for parsing or use in shader compilation.
*
* Shaders have a "`" prepended on each line. If a line starts with this character, it's stripped and a newline
* character is added at the end of each line. Equations are returned as a single, long line.
*
* The function appends numbers to the prefix, starting with 1, and stops when a key is missing. This is following
* Milkdrop's behaviour, so any gap in numbers will essentially cut off all code after the gap.
*
* Comments starting with // or \\\\ will be stripped until the end of each line in both equations and shader code.
*
* @param keyPrefix The key prefix for the code block to be returned.
* @return The code that was parsed from the given prefix. Empty if no code was found.
*/
[[nodiscard]] auto GetCode(const std::string& keyPrefix) const -> std::string;
/**
* @brief Returns the given key value as an integer.
*
* Returns the default value if no value can be parsed or the key doesn't exist.
*
* Any additional text after the number, e.g. a comment, is ignored.
*
* @param key The key to retrieve the value from.
* @param defaultValue The default value to return if key is not found.
* @return The converted value or the default value.
*/
[[nodiscard]] auto GetInt(const std::string& key, int defaultValue) -> int;
/**
* @brief Returns the given key value as a floating-point value.
*
* Returns the default value if no value can be parsed or the key doesn't exist.
*
* Any additional text after the number, e.g. a comment, is ignored.
*
* @param key The key to retrieve the value from.
* @param defaultValue The default value to return if key is not found.
* @return The converted value or the default value.
*/
[[nodiscard]] auto GetFloat(const std::string& key, float defaultValue) -> float;
/**
* @brief Returns the given key value as a boolean.
*
* Returns the default value if no value can be parsed or the key doesn't exist.
*
* Any additional text after the number, e.g. a comment, is ignored.
*
* @param key The key to retrieve the value from.
* @param defaultValue The default value to return if key is not found.
* @return True if the value is non-zero, false otherwise.
*/
[[nodiscard]] auto GetBool(const std::string& key, bool defaultValue) -> bool;
/**
* @brief Returns the given key value as a string.
*
* Returns the default value if no value can be parsed or the key doesn't exist.
*
* @param key The key to retrieve the value from.
* @param defaultValue The default value to return if key is not found.
* @return the string content of the key, or the default value.
*/
[[nodiscard]] auto GetString(const std::string& key, const std::string& defaultValue) -> std::string;
/**
* @brief Returns a reference to the internal value map.
* @return A reference to the internal value map.
*/
auto PresetValues() const -> const ValueMap&;
protected:
/**
* @brief Parses a single line and stores the result in the value map.
*
* The function doesn't really care about invalid lines with random text or comments. The first "word"
* is added as key to the map, but will not be used afterwards.
*
* @param line The line to parse.
*/
void ParseLine(const std::string& line);
private:
/**
* @brief Converts the string to lower-case.
* Only letters A-Z are converted to a-z by default.
* @param str The original string.
* @return The lower-case string.
*/
static auto ToLower(std::string str) -> std::string;
ValueMap m_presetValues; //!< Map with preset keys and their value.
};
} // namespace libprojectM