| #include <algorithm> | |
| #include "yaml-cpp/node/convert.h" | |
| namespace { | |
| // we're not gonna mess with the mess that is all the isupper/etc. functions | |
| bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } | |
| bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; } | |
| char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; } | |
| std::string tolower(const std::string& str) { | |
| std::string s(str); | |
| std::transform(s.begin(), s.end(), s.begin(), ToLower); | |
| return s; | |
| } | |
| template <typename T> | |
| bool IsEntirely(const std::string& str, T func) { | |
| return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); }); | |
| } | |
| // IsFlexibleCase | |
| // . Returns true if 'str' is: | |
| // . UPPERCASE | |
| // . lowercase | |
| // . Capitalized | |
| bool IsFlexibleCase(const std::string& str) { | |
| if (str.empty()) | |
| return true; | |
| if (IsEntirely(str, IsLower)) | |
| return true; | |
| bool firstcaps = IsUpper(str[0]); | |
| std::string rest = str.substr(1); | |
| return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper)); | |
| } | |
| } // namespace | |
| namespace YAML { | |
| bool convert<bool>::decode(const Node& node, bool& rhs) { | |
| if (!node.IsScalar()) | |
| return false; | |
| // we can't use iostream bool extraction operators as they don't | |
| // recognize all possible values in the table below (taken from | |
| // http://yaml.org/type/bool.html) | |
| static const struct { | |
| std::string truename, falsename; | |
| } names[] = { | |
| {"y", "n"}, | |
| {"yes", "no"}, | |
| {"true", "false"}, | |
| {"on", "off"}, | |
| }; | |
| if (!IsFlexibleCase(node.Scalar())) | |
| return false; | |
| for (const auto& name : names) { | |
| if (name.truename == tolower(node.Scalar())) { | |
| rhs = true; | |
| return true; | |
| } | |
| if (name.falsename == tolower(node.Scalar())) { | |
| rhs = false; | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| } // namespace YAML |