diff --git a/string.hpp b/string.hpp index 301b027d..fc531b12 100644 --- a/string.hpp +++ b/string.hpp @@ -21,23 +21,26 @@ namespace cruft { std::string to_utf8 (const std::wstring&); - /// Convert the provided string to all upper case - inline std::string - to_upper (std::string &&val) + /// Apply a functor to each character of a string and return the result. + template + std::string + transform (std::string &&val, FunctionT &&func) { std::transform ( std::begin (val), std::end (val), std::begin (val), - ::toupper + std::forward (func) ); + return std::move (val); } - /// Convert the provided string to all upper case - inline std::string - to_upper (std::string const &val) + /// Apply a functor to each character of a string and return the result. + template + std::string + transform (std::string const &val, FunctionT &&func) { std::string res; res.reserve (val.size ()); @@ -46,11 +49,43 @@ namespace cruft { std::begin (val), std::end (val), std::back_inserter (res), - ::toupper + std::forward (func) ); return res; } + + + /// Convert the provided string to all upper case + inline std::string + to_upper (std::string &&val) + { + return transform (std::move (val), ::toupper); + } + + + /// Convert the provided string to all upper case + inline std::string + to_upper (std::string const &val) + { + return transform (val, ::toupper); + } + + + /// Convert the provided string to all upper case + inline std::string + to_lower (std::string &&val) + { + return transform (std::move (val), ::tolower); + } + + + /// Convert the provided string to all upper case + inline std::string + to_lower (std::string const &val) + { + return transform (val, ::tolower); + } } diff --git a/test/string.cpp b/test/string.cpp index ee510175..30c3443e 100644 --- a/test/string.cpp +++ b/test/string.cpp @@ -6,6 +6,32 @@ #include +/////////////////////////////////////////////////////////////////////////////// +void +test_transforms (cruft::TAP::logger &tap) +{ + static struct { + std::string initial; + std::string upper; + std::string lower; + + char const *message; + } const TESTS[] = { + { "a", "A", "a", "single lower character" }, + { "A", "A", "a", "single upper character" }, + { "asdf", "ASDF", "asdf", "four lower characters" }, + { "ASDF", "ASDF", "asdf", "four upper characters" }, + + { "Don't.", "DON'T.", "don't.", "upper and lower and symbols" }, + }; + + for (auto const [src, upper, lower, msg]: TESTS) { + tap.expect_eq (cruft::to_upper (src), upper, "to_upper, %!", msg); + tap.expect_eq (cruft::to_lower (src), lower, "to_lower, %!", msg); + } +} + + /////////////////////////////////////////////////////////////////////////////// void test_position (cruft::TAP::logger &tap) @@ -203,6 +229,7 @@ main (int, char**) { cruft::TAP::logger tap; + test_transforms (tap); test_tokeniser (tap); test_position (tap); test_contains (tap);