#pragma once #include #include #include namespace details { // This implementation avoids the complexity of using std::isdigit, which pulls // in all of , and likely has other consequences. inline bool simpleIsDigit(const char c) { return c >= '0' && c <= '9'; } enum class ModeType { STRING, NUMBER }; } // namespace details inline int alphanumComp(const std::string_view left, const std::string_view right) { std::string_view::const_iterator l = left.begin(); std::string_view::const_iterator r = right.begin(); details::ModeType mode = details::ModeType::STRING; while (l != left.end() && r != right.end()) { if (mode == details::ModeType::STRING) { // check if this are digit characters const bool lDigit = details::simpleIsDigit(*l); const bool rDigit = details::simpleIsDigit(*r); // if both characters are digits, we continue in NUMBER mode if (lDigit && rDigit) { mode = details::ModeType::NUMBER; continue; } // if only the left character is a digit, we have a result if (lDigit) { return -1; } // if only the right character is a digit, we have a result if (rDigit) { return +1; } // compute the difference of both characters const int diff = *l - *r; // if they differ we have a result if (diff != 0) { return diff; } // otherwise process the next characters l++; r++; } else // mode==NUMBER { // get the left number int lInt = 0; auto fc = std::from_chars(&(*l), &(*left.end()), lInt); l += std::distance(l, fc.ptr); // get the right number int rInt = 0; fc = std::from_chars(&(*r), &(*right.end()), rInt); r += std::distance(r, fc.ptr); // if the difference is not equal to zero, we have a comparison // result const int diff = lInt - rInt; if (diff != 0) { return diff; } // otherwise we process the next substring in STRING mode mode = details::ModeType::STRING; } } if (r == right.end() && l == left.end()) { return 0; } if (r == right.end()) { return 1; } return -1; } // A generic template type compatible with std::less that can be used on generic // containers (set, map, ect) template struct AlphanumLess { bool operator()(const Type& left, const Type& right) const { return alphanumComp(left, right) < 0; } };