aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/EpisodeNameParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/EpisodeNameParser.cpp')
-rw-r--r--src/plugins/EpisodeNameParser.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/plugins/EpisodeNameParser.cpp b/src/plugins/EpisodeNameParser.cpp
new file mode 100644
index 0000000..cbaae50
--- /dev/null
+++ b/src/plugins/EpisodeNameParser.cpp
@@ -0,0 +1,112 @@
+#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<EpisodeNameParts> 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;
+ }
+} \ No newline at end of file