conversion.cpp 2.34 KB
Newer Older
1
2
#include "conversion.h"
#include <algorithm>
3
#include <cstdlib>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

////////////////////////////////////////////////////////////////
// Specializations for converting a string to specific types

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)
	{
		for(unsigned i=0;i<str.size();i++)
			if(!func(str[i]))
				return false;

		return true;
	}

	// 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 YAML
{
	template <>
	bool Converter<bool>::Convert(const std::string& input, bool& b)
	{
		// 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(input))
			return false;

		for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
			if(names[i].truename == tolower(input)) {
				b = true;
				return true;
			}

			if(names[i].falsename == tolower(input)) {
				b = false;
				return true;
			}
		}

		return false;
	}
85
	
86
87
88
89
90
91
	template <>
	bool Converter<_Null>::Convert(const std::string& input, _Null& /*output*/)
	{
		return input.empty() || input == "~" || input == "null" || input == "Null" || input == "NULL";
	}

92
93
94
95
96
97
98
99
100
101
102
103
104
	template <>
	bool Converter<std::wstring>::Convert(const std::string& input, std::wstring& output)
	{
		output.clear();
		output.resize(std::mbstowcs(NULL, input.data(), input.size()));
		std::mbstowcs(
			(wchar_t *) output.data(),
			input.data(),
			input.size()
		);
		
		return true;
	}
105
106
}