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   for (std::size_t i = 0; i < str.size(); i++)
20     if (!func(str[i]))
21       return false;
22 
23   return true;
24 }
25 
26 // IsFlexibleCase
27 // . Returns true if 'str' is:
28 //   . UPPERCASE
29 //   . lowercase
30 //   . Capitalized
IsFlexibleCase(const std::string & str)31 bool IsFlexibleCase(const std::string& str) {
32   if (str.empty())
33     return true;
34 
35   if (IsEntirely(str, IsLower))
36     return true;
37 
38   bool firstcaps = IsUpper(str[0]);
39   std::string rest = str.substr(1);
40   return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
41 }
42 }
43 
44 namespace YAML {
decode(const Node & node,bool & rhs)45 bool convert<bool>::decode(const Node& node, bool& rhs) {
46   if (!node.IsScalar())
47     return false;
48 
49   // we can't use iostream bool extraction operators as they don't
50   // recognize all possible values in the table below (taken from
51   // http://yaml.org/type/bool.html)
52   static const struct {
53     std::string truename, falsename;
54   } names[] = {
55       {"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
56   };
57 
58   if (!IsFlexibleCase(node.Scalar()))
59     return false;
60 
61   for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
62     if (names[i].truename == tolower(node.Scalar())) {
63       rhs = true;
64       return true;
65     }
66 
67     if (names[i].falsename == tolower(node.Scalar())) {
68       rhs = false;
69       return true;
70     }
71   }
72 
73   return false;
74 }
75 }
76