Mercurial > minori
diff dep/animone/src/player.cc @ 301:b1f625b0227c
*: convert all files CRLF -> LF
some files were in DOS format, others were in unix. now everything
(that at least is under our control) should all be the same format
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Mon, 13 May 2024 15:04:51 -0400 |
parents | 862d0d8619f6 |
children | a7d4e5107531 |
line wrap: on
line diff
--- a/dep/animone/src/player.cc Mon May 13 14:56:37 2024 -0400 +++ b/dep/animone/src/player.cc Mon May 13 15:04:51 2024 -0400 @@ -1,181 +1,181 @@ -#include "animone/player.h" -#include "animone/util.h" - -#include <map> -#include <sstream> -#include <string> -#include <vector> - -namespace animone { - -namespace internal::parser { - -enum class State { - ExpectPlayerName, - ExpectSection, - ExpectWindow, - ExpectExecutable, - ExpectStrategy, - ExpectType, - ExpectWindowTitle, -}; - -size_t GetIndentation(const std::string& line) { - return line.find_first_not_of('\t'); -} - -bool HandleIndentation(const size_t current, const std::vector<Player>& players, State& state) { - // Each state has a definitive expected indentation - const auto expected = [&state]() -> size_t { - switch (state) { - default: - case State::ExpectPlayerName: return 0; - case State::ExpectSection: return 1; - case State::ExpectWindow: - case State::ExpectExecutable: - case State::ExpectStrategy: - case State::ExpectType: return 2; - case State::ExpectWindowTitle: return 3; - } - }(); - - if (current > expected) - return false; // Disallow excessive indentation - - if (current < expected) { - auto fix_state = [&]() { state = !current ? State::ExpectPlayerName : State::ExpectSection; }; - switch (state) { - case State::ExpectWindow: - if (players.back().windows.empty()) - return false; - fix_state(); - break; - case State::ExpectExecutable: - if (players.back().executables.empty()) - return false; - fix_state(); - break; - case State::ExpectStrategy: - if (players.back().strategies.empty()) - return false; - fix_state(); - break; - case State::ExpectType: fix_state(); break; - case State::ExpectWindowTitle: return false; - } - } - - return true; -} - -bool HandleState(std::string& line, std::vector<Player>& players, State& state) { - switch (state) { - case State::ExpectPlayerName: - players.push_back(Player()); - players.back().name = line; - state = State::ExpectSection; - break; - - case State::ExpectSection: { - static const std::map<std::string, State> sections = { - {"windows", State::ExpectWindow }, - {"executables", State::ExpectExecutable}, - {"strategies", State::ExpectStrategy }, - {"type", State::ExpectType }, - }; - util::TrimRight(line, ":"); - const auto it = sections.find(line); - if (it == sections.end()) - return false; - state = it->second; - break; - } - - case State::ExpectWindow: players.back().windows.push_back(line); break; - - case State::ExpectExecutable: players.back().executables.push_back(line); break; - - case State::ExpectStrategy: { - static const std::map<std::string, Strategy> strategies = { - {"window_title", Strategy::WindowTitle }, - {"open_files", Strategy::OpenFiles }, - {"ui_automation", Strategy::UiAutomation}, - }; - util::TrimRight(line, ":"); - const auto it = strategies.find(line); - if (it == strategies.end()) - return false; - const auto strategy = it->second; - players.back().strategies.push_back(strategy); - switch (strategy) { - case Strategy::WindowTitle: state = State::ExpectWindowTitle; break; - } - break; - } - - case State::ExpectType: { - static const std::map<std::string, PlayerType> types = { - {"default", PlayerType::Default }, - {"web_browser", PlayerType::WebBrowser}, - }; - const auto it = types.find(line); - if (it == types.end()) - return false; - players.back().type = it->second; - break; - } - - case State::ExpectWindowTitle: - players.back().window_title_format = line; - state = State::ExpectStrategy; - break; - } - - return true; -} - -} // namespace internal::parser - -//////////////////////////////////////////////////////////////////////////////// - -bool ParsePlayersData(const std::string& data, std::vector<Player>& players) { - if (data.empty()) - return false; - - std::istringstream stream(data); - std::string line; - size_t indentation = 0; - auto state = internal::parser::State::ExpectPlayerName; - - while (std::getline(stream, line, '\n')) { - if (line.empty()) - continue; // Ignore empty lines - - indentation = internal::parser::GetIndentation(line); - - internal::util::TrimLeft(line, "\t"); - internal::util::TrimRight(line, "\n\r"); - - if (line.empty() || line.front() == '#') - continue; // Ignore empty lines and comments - - if (!internal::parser::HandleIndentation(indentation, players, state)) - return false; - - if (!internal::parser::HandleState(line, players, state)) - return false; - } - - return !players.empty(); -} - -bool ParsePlayersFile(const std::string& path, std::vector<Player>& players) { - std::string data; - - if (!internal::util::ReadFile(path, data)) - return false; - - return ParsePlayersData(data, players); -} - -} // namespace animone +#include "animone/player.h" +#include "animone/util.h" + +#include <map> +#include <sstream> +#include <string> +#include <vector> + +namespace animone { + +namespace internal::parser { + +enum class State { + ExpectPlayerName, + ExpectSection, + ExpectWindow, + ExpectExecutable, + ExpectStrategy, + ExpectType, + ExpectWindowTitle, +}; + +size_t GetIndentation(const std::string& line) { + return line.find_first_not_of('\t'); +} + +bool HandleIndentation(const size_t current, const std::vector<Player>& players, State& state) { + // Each state has a definitive expected indentation + const auto expected = [&state]() -> size_t { + switch (state) { + default: + case State::ExpectPlayerName: return 0; + case State::ExpectSection: return 1; + case State::ExpectWindow: + case State::ExpectExecutable: + case State::ExpectStrategy: + case State::ExpectType: return 2; + case State::ExpectWindowTitle: return 3; + } + }(); + + if (current > expected) + return false; // Disallow excessive indentation + + if (current < expected) { + auto fix_state = [&]() { state = !current ? State::ExpectPlayerName : State::ExpectSection; }; + switch (state) { + case State::ExpectWindow: + if (players.back().windows.empty()) + return false; + fix_state(); + break; + case State::ExpectExecutable: + if (players.back().executables.empty()) + return false; + fix_state(); + break; + case State::ExpectStrategy: + if (players.back().strategies.empty()) + return false; + fix_state(); + break; + case State::ExpectType: fix_state(); break; + case State::ExpectWindowTitle: return false; + } + } + + return true; +} + +bool HandleState(std::string& line, std::vector<Player>& players, State& state) { + switch (state) { + case State::ExpectPlayerName: + players.push_back(Player()); + players.back().name = line; + state = State::ExpectSection; + break; + + case State::ExpectSection: { + static const std::map<std::string, State> sections = { + {"windows", State::ExpectWindow }, + {"executables", State::ExpectExecutable}, + {"strategies", State::ExpectStrategy }, + {"type", State::ExpectType }, + }; + util::TrimRight(line, ":"); + const auto it = sections.find(line); + if (it == sections.end()) + return false; + state = it->second; + break; + } + + case State::ExpectWindow: players.back().windows.push_back(line); break; + + case State::ExpectExecutable: players.back().executables.push_back(line); break; + + case State::ExpectStrategy: { + static const std::map<std::string, Strategy> strategies = { + {"window_title", Strategy::WindowTitle }, + {"open_files", Strategy::OpenFiles }, + {"ui_automation", Strategy::UiAutomation}, + }; + util::TrimRight(line, ":"); + const auto it = strategies.find(line); + if (it == strategies.end()) + return false; + const auto strategy = it->second; + players.back().strategies.push_back(strategy); + switch (strategy) { + case Strategy::WindowTitle: state = State::ExpectWindowTitle; break; + } + break; + } + + case State::ExpectType: { + static const std::map<std::string, PlayerType> types = { + {"default", PlayerType::Default }, + {"web_browser", PlayerType::WebBrowser}, + }; + const auto it = types.find(line); + if (it == types.end()) + return false; + players.back().type = it->second; + break; + } + + case State::ExpectWindowTitle: + players.back().window_title_format = line; + state = State::ExpectStrategy; + break; + } + + return true; +} + +} // namespace internal::parser + +//////////////////////////////////////////////////////////////////////////////// + +bool ParsePlayersData(const std::string& data, std::vector<Player>& players) { + if (data.empty()) + return false; + + std::istringstream stream(data); + std::string line; + size_t indentation = 0; + auto state = internal::parser::State::ExpectPlayerName; + + while (std::getline(stream, line, '\n')) { + if (line.empty()) + continue; // Ignore empty lines + + indentation = internal::parser::GetIndentation(line); + + internal::util::TrimLeft(line, "\t"); + internal::util::TrimRight(line, "\n\r"); + + if (line.empty() || line.front() == '#') + continue; // Ignore empty lines and comments + + if (!internal::parser::HandleIndentation(indentation, players, state)) + return false; + + if (!internal::parser::HandleState(line, players, state)) + return false; + } + + return !players.empty(); +} + +bool ParsePlayersFile(const std::string& path, std::vector<Player>& players) { + std::string data; + + if (!internal::util::ReadFile(path, data)) + return false; + + return ParsePlayersData(data, players); +} + +} // namespace animone