// file : butl/utility -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BUTL_UTILITY #define BUTL_UTILITY #include #include // size_t #include // forward() #include // strcmp(), strlen() namespace butl { // Convert ASCII character/string case. If there is no upper/lower case // counterpart, leave the character unchanged. The POSIX locale (also known // as C locale) must be the current application locale. Otherwise the // behavior is undefined. // // Note that the POSIX locale specifies behaviour on data consisting // entirely of characters from the portable character set (subset of ASCII // including 103 non-negative characters and English alphabet letters in // particular) and the control character set (more about them at // http://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap06.html). // // Also note that according to the POSIX locale definition the case // conversion can be applied only to [A-Z] and [a-z] character ranges being // translated to each other (more about that at // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html#tag_07_02) // char ucase (char); std::string ucase (const char*, std::size_t = std::string::npos); std::string ucase (const std::string&); std::string& ucase (std::string&); void ucase (char*, std::size_t); char lcase (char); std::string lcase (const char*, std::size_t = std::string::npos); std::string lcase (const std::string&); std::string& lcase (std::string&); void lcase (char*, std::size_t); // Compare ASCII characters/strings ignoring case. Behave as if characters // had been converted to the lower case and then byte-compared. Return a // negative, zero or positive value if the left hand side is less, equal or // greater than the right hand side, respectivelly. The POSIX locale (also // known as C locale) must be the current application locale. Otherwise the // behavior is undefined. // // The optional size argument specifies the maximum number of characters // to compare. // int casecmp (char, char); int casecmp (const std::string&, const std::string&, std::size_t = std::string::npos); int casecmp (const std::string&, const char*, std::size_t = std::string::npos); int casecmp (const char*, const char*, std::size_t = std::string::npos); // Case-insensitive key comparators (i.e., to be used in sets, maps, etc). // struct case_compare_string { bool operator() (const std::string& x, const std::string& y) const { return casecmp (x, y) < 0; } }; struct case_compare_c_string { bool operator() (const char* x, const char* y) const { return casecmp (x, y) < 0; } }; bool alpha (char); bool digit (char); bool alnum (char); // Key comparators (i.e., to be used in sets, maps, etc). // struct compare_c_string { bool operator() (const char* x, const char* y) const { return std::strcmp (x, y) < 0; } }; struct compare_pointer_target { template bool operator() (const P& x, const P& y) const {return *x < *y;} }; // Combine one or more hash values. // inline std::size_t combine_hash (std::size_t s, std::size_t h) { // Magic formula from boost::hash_combine(). // return s ^ (h + 0x9e3779b9 + (s << 6) + (s >> 2)); } template inline std::size_t combine_hash (std::size_t s, std::size_t h, S... hs) { return combine_hash (combine_hash (s, h), hs...); } // Support for reverse iteration using range-based for-loop: // // for (... : reverse_iterate (x)) ... // template class reverse_range { T x_; public: reverse_range (T&& x): x_ (std::forward (x)) {} auto begin () const -> decltype (this->x_.rbegin ()) {return x_.rbegin ();} auto end () const -> decltype (this->x_.rend ()) {return x_.rend ();} }; template inline reverse_range reverse_iterate (T&& x) {return reverse_range (std::forward (x));} } #include #endif // BUTL_UTILITY