1 #include <algorithm>
2 
3 #include "yaml-cpp/node/convert.h"
4 
5 namespace {
6 // we're not gonna mess with the mess that is all the isupper/etc. functions
IsLower(char ch)7 bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
IsUpper(char ch)8 bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
ToLower(char ch)9 char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
10 
tolower(const std::string & str)11 std::string tolower(const std::string& str) {
12   std::string s(str);
13   std::transform(s.begin(), s.end(), s.begin(), ToLower);
14   return s;
15 }
16 
17 template <typename T>
IsEntirely(const std::string & str,T func)18 bool IsEntirely(const std::string& str, T func) {
19   return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
20 }
21 
22 // IsFlexibleCase
23 // . Returns true if 'str' is:
24 //   . UPPERCASE
25 //   . lowercase
26 //   . Capitalized
IsFlexibleCase(const std::string & str)27 bool IsFlexibleCase(const std::string& str) {
28   if (str.empty())
29     return true;
30 
31   if (IsEntirely(str, IsLower))
32     return true;
33 
34   bool firstcaps = IsUpper(str[0]);
35   std::string rest = str.substr(1);
36   return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
37 }
38 }  // namespace
39 
40 namespace YAML {
decode(const Node & node,bool & rhs)41 bool convert<bool>::decode(const Node& node, bool& rhs) {
42   if (!node.IsScalar())
43     return false;
44 
45   // we can't use iostream bool extraction operators as they don't
46   // recognize all possible values in the table below (taken from
47   // http://yaml.org/type/bool.html)
48   static const struct {
49     std::string truename, falsename;
50   } names[] = {
51       {"y", "n"},
52       {"yes", "no"},
53       {"true", "false"},
54       {"on", "off"},
55   };
56 
57   if (!IsFlexibleCase(node.Scalar()))
58     return false;
59 
60   for (const auto& name : names) {
61     if (name.truename == tolower(node.Scalar())) {
62       rhs = true;
63       return true;
64     }
65 
66     if (name.falsename == tolower(node.Scalar())) {
67       rhs = false;
68       return true;
69     }
70   }
71 
72   return false;
73 }
74 }  // namespace YAML
75