bool Parser::IsResolution(const string_t& str) { // Using a regex such as "\\d{3,4}(p|(x\\d{3,4}))$" would be more elegant, // but it's much slower (e.g. 2.4ms -> 24.9ms). // *###x###* if (str.size() >= 3 + 1 + 3) { size_t pos = str.find_first_of(L"xX\u00D7"); // multiplication sign if (pos != str.npos) { for (size_t i = 0; i < str.size(); i++) if (i != pos && !IsNumericChar(str.at(i))) return false; return true; } // *###p } else if (str.size() >= 3 + 1) { if (str.back() == L'p' || str.back() == L'P') { for (size_t i = 0; i < str.size() - 1; i++) if (!IsNumericChar(str.at(i))) return false; return true; } } return false; }
int SortAsEpisodeRange(const std::wstring& str1, const std::wstring& str2) { auto is_volume = [](const std::wstring& str) { return !str.empty() && !IsNumericChar(str.front()); }; auto get_last_number_in_range = [](const std::wstring& str) { auto pos = InStr(str, L"-"); return pos > -1 ? ToInt(str.substr(pos + 1)) : ToInt(str); }; auto get_volume = [&](const std::wstring& str) { auto pos = InStr(str, L" "); return pos > -1 ? get_last_number_in_range(str.substr(pos + 1)) : 0; }; bool is_volume1 = is_volume(str1); bool is_volume2 = is_volume(str2); if (is_volume1 && is_volume2) { return CompareValues<int>(get_volume(str1), get_volume(str2)); } else if (!is_volume1 && !is_volume2) { return CompareValues<int>(get_last_number_in_range(str1), get_last_number_in_range(str2)); } else { return is_volume1 ? base::kLessThan : base::kGreaterThan; } }
bool Parser::MatchEpisodePatterns(string_t word, Token& token) { // All patterns contain at least one non-numeric character if (IsNumericString(word)) return false; TrimString(word, L" -"); const bool numeric_front = IsNumericChar(word.front()); const bool numeric_back = IsNumericChar(word.back()); // e.g. "01v2" if (numeric_front && numeric_back) if (MatchSingleEpisodePattern(word, token)) return true; // e.g. "01-02", "03-05v2" if (numeric_front && numeric_back) if (MatchMultiEpisodePattern(word, token)) return true; // e.g. "2x01", "S01E03", "S01-02xE001-150" if (numeric_back) if (MatchSeasonAndEpisodePattern(word, token)) return true; // e.g. "ED1", "OP4a", "OVA2" if (!numeric_front) if (MatchTypeAndEpisodePattern(word, token)) return true; // e.g. "07.5" if (numeric_front && numeric_back) if (MatchFractionalEpisodePattern(word, token)) return true; // e.g. "4a", "111C" if (numeric_front && !numeric_back) if (MatchPartialEpisodePattern(word, token)) return true; // e.g. "#01", "#02-03v2" if (numeric_back) if (MatchNumberSignPattern(word, token)) return true; // U+8A71 is used as counter for stories, episodes of TV series, etc. if (numeric_front) if (MatchJapaneseCounterPattern(word, token)) return true; return false; }
void FormatDialog::RefreshPreviewText() { // Replace variables std::wstring str; GetDlgItemText(IDC_RICHEDIT_FORMAT, str); anime::Episode* episode = &taiga::DummyEpisode; if (CurrentEpisode.anime_id > 0) episode = &CurrentEpisode; str = ReplaceVariables(str, *episode, false, false, true); switch (mode) { case kFormatModeMirc: { // Strip IRC characters for (size_t i = 0; i < str.length(); i++) { if (str[i] == 0x02 || // Bold str[i] == 0x16 || // Reverse str[i] == 0x1D || // Italic str[i] == 0x1F || // Underline str[i] == 0x0F) { // Disable all str.erase(i, 1); i--; continue; } // Color code if (str[i] == 0x03) { str.erase(i, 1); if (IsNumericChar(str[i])) str.erase(i, 1); if (IsNumericChar(str[i])) str.erase(i, 1); i--; continue; } } break; } case kFormatModeSkype: { // Strip HTML codes StripHtmlTags(str); break; } } // Set final text SetDlgItemText(IDC_EDIT_PREVIEW, str.c_str()); }
int SortAsFileSize(LPCWSTR str1, LPCWSTR str2) { UINT64 size[2] = {1, 1}; for (size_t i = 0; i < 2; i++) { std::wstring value = i == 0 ? str1 : str2; std::wstring unit; TrimRight(value, L".\r"); EraseChars(value, L" "); if (value.length() >= 2) { for (auto it = value.rbegin(); it != value.rend(); ++it) { if (IsNumericChar(*it)) break; unit.insert(unit.begin(), *it); } value.resize(value.length() - unit.length()); Trim(unit); } int index = InStr(value, L"."); if (index > -1) { int length = value.substr(index + 1).length(); if (length <= 2) value.append(2 - length, '0'); EraseChars(value, L"."); } else { value.append(2, '0'); } if (IsEqual(unit, L"KB")) { size[i] *= 1000; } else if (IsEqual(unit, L"KiB")) { size[i] *= 1024; } else if (IsEqual(unit, L"MB")) { size[i] *= 1000 * 1000; } else if (IsEqual(unit, L"MiB")) { size[i] *= 1024 * 1024; } else if (IsEqual(unit, L"GB")) { size[i] *= 1000 * 1000 * 1000; } else if (IsEqual(unit, L"GiB")) { size[i] *= 1024 * 1024 * 1024; } size[i] *= _wtoi(value.c_str()); } return CompareValues<UINT64>(size[0], size[1]); }
bool Parser::SearchForEpisodePatterns(std::vector<size_t>& tokens) { for (const auto& token_index : tokens) { auto token = tokens_.begin() + token_index; bool numeric_front = IsNumericChar(token->content.front()); if (!numeric_front) { // e.g. "EP.01" if (NumberComesAfterEpisodePrefix(*token)) return true; } else { // e.g. "8 of 12" if (NumberComesBeforeTotalNumber(token)) return true; } // Look for other patterns if (MatchEpisodePatterns(token->content, *token)) return true; } return false; }
inline bool IsCIdentifierChar(char x) { return '_'==x || IsAlphabeticChar(x) || IsNumericChar(x); }