#include "../../plugins/EpisodeNameParser.hpp" namespace QuickMedia { static bool has_season_in_name(std::string_view episode_name) { size_t sep_count = 0; size_t index = 0; while(true) { size_t next_index = episode_name.find(" - ", index); if(next_index == std::string_view::npos) break; index = next_index + 3; ++sep_count; } return sep_count >= 2; } static bool is_whitespace(char c) { return c == ' ' || c == '\n' || c == '\t' || c == '\v'; } static std::string_view strip_left(std::string_view str) { size_t i = 0; for(; i < str.size(); ++i) { if(!is_whitespace(str[i])) break; } return str.substr(i); } static std::string_view strip_right(std::string_view str) { long i = (long)str.size() - 1; for(; i >= 0; --i) { if(!is_whitespace(str[i])) break; } return str.substr(0, i + 1); } static std::string_view episode_name_extract_group(std::string_view &episode_name) { episode_name = strip_left(episode_name); if(episode_name[0] == '[') { size_t group_end_index = episode_name.find(']', 1); if(group_end_index == std::string_view::npos) return {}; std::string_view group = episode_name.substr(1, group_end_index - 1); episode_name.remove_prefix(group_end_index + 1); return group; } return {}; } static std::string_view episode_name_extract_anime(std::string_view &episode_name) { episode_name = strip_left(episode_name); size_t episode_or_season_sep_index = episode_name.find(" - "); if(episode_or_season_sep_index == std::string_view::npos) episode_or_season_sep_index = episode_name.size(); std::string_view anime = episode_name.substr(0, episode_or_season_sep_index); anime = strip_right(anime); if(episode_or_season_sep_index + 3 > episode_name.size()) episode_name = {}; else episode_name.remove_prefix(episode_or_season_sep_index + 3); return anime; } static std::string_view episode_name_extract_season(std::string_view &episode_name) { return episode_name_extract_anime(episode_name); } static bool is_num_real_char(char c) { return (c >= '0' && c <= '9') || c == '.'; } static std::string_view episode_name_extract_episode(std::string_view &episode_name) { episode_name = strip_left(episode_name); size_t i = 0; for(; i < episode_name.size(); ++i) { if(!is_num_real_char(episode_name[i])) break; } if(i == 0) return {}; std::string_view episode = episode_name.substr(0, i); episode_name.remove_prefix(i + 1); return episode; } std::optional episode_name_extract_parts(std::string_view episode_name) { EpisodeNameParts name_parts; const bool has_season = has_season_in_name(episode_name); name_parts.group = episode_name_extract_group(episode_name); name_parts.anime = episode_name_extract_anime(episode_name); if(name_parts.anime.empty()) return std::nullopt; if(has_season) name_parts.season = episode_name_extract_season(episode_name); name_parts.episode = episode_name_extract_episode(episode_name); if(name_parts.episode.empty()) return std::nullopt; return name_parts; } }