318
|
1 // Copyright Toru Niina 2017.
|
|
2 // Distributed under the MIT License.
|
|
3 #ifndef TOML11_STRING_HPP
|
|
4 #define TOML11_STRING_HPP
|
|
5
|
|
6 #include "version.hpp"
|
|
7
|
|
8 #include <cstdint>
|
|
9
|
|
10 #include <algorithm>
|
|
11 #include <string>
|
|
12
|
|
13 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
|
14 #if __has_include(<string_view>)
|
|
15 #define TOML11_USING_STRING_VIEW 1
|
|
16 #include <string_view>
|
|
17 #endif
|
|
18 #endif
|
|
19
|
|
20 namespace toml
|
|
21 {
|
|
22
|
|
23 enum class string_t : std::uint8_t
|
|
24 {
|
|
25 basic = 0,
|
|
26 literal = 1,
|
|
27 };
|
|
28
|
|
29 struct string
|
|
30 {
|
|
31 string() = default;
|
|
32 ~string() = default;
|
|
33 string(const string& s) = default;
|
|
34 string(string&& s) = default;
|
|
35 string& operator=(const string& s) = default;
|
|
36 string& operator=(string&& s) = default;
|
|
37
|
|
38 string(const std::string& s): kind(string_t::basic), str(s){}
|
|
39 string(const std::string& s, string_t k): kind(k), str(s){}
|
|
40 string(const char* s): kind(string_t::basic), str(s){}
|
|
41 string(const char* s, string_t k): kind(k), str(s){}
|
|
42
|
|
43 string(std::string&& s): kind(string_t::basic), str(std::move(s)){}
|
|
44 string(std::string&& s, string_t k): kind(k), str(std::move(s)){}
|
|
45
|
|
46 string& operator=(const std::string& s)
|
|
47 {kind = string_t::basic; str = s; return *this;}
|
|
48 string& operator=(std::string&& s)
|
|
49 {kind = string_t::basic; str = std::move(s); return *this;}
|
|
50
|
|
51 operator std::string& () & noexcept {return str;}
|
|
52 operator std::string const& () const& noexcept {return str;}
|
|
53 operator std::string&& () && noexcept {return std::move(str);}
|
|
54
|
|
55 string& operator+=(const char* rhs) {str += rhs; return *this;}
|
|
56 string& operator+=(const char rhs) {str += rhs; return *this;}
|
|
57 string& operator+=(const std::string& rhs) {str += rhs; return *this;}
|
|
58 string& operator+=(const string& rhs) {str += rhs.str; return *this;}
|
|
59
|
|
60 #if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
|
|
61 explicit string(std::string_view s): kind(string_t::basic), str(s){}
|
|
62 string(std::string_view s, string_t k): kind(k), str(s){}
|
|
63
|
|
64 string& operator=(std::string_view s)
|
|
65 {kind = string_t::basic; str = s; return *this;}
|
|
66
|
|
67 explicit operator std::string_view() const noexcept
|
|
68 {return std::string_view(str);}
|
|
69
|
|
70 string& operator+=(const std::string_view& rhs) {str += rhs; return *this;}
|
|
71 #endif
|
|
72
|
|
73 string_t kind;
|
|
74 std::string str;
|
|
75 };
|
|
76
|
|
77 inline bool operator==(const string& lhs, const string& rhs)
|
|
78 {
|
|
79 return lhs.kind == rhs.kind && lhs.str == rhs.str;
|
|
80 }
|
|
81 inline bool operator!=(const string& lhs, const string& rhs)
|
|
82 {
|
|
83 return !(lhs == rhs);
|
|
84 }
|
|
85 inline bool operator<(const string& lhs, const string& rhs)
|
|
86 {
|
|
87 return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind);
|
|
88 }
|
|
89 inline bool operator>(const string& lhs, const string& rhs)
|
|
90 {
|
|
91 return rhs < lhs;
|
|
92 }
|
|
93 inline bool operator<=(const string& lhs, const string& rhs)
|
|
94 {
|
|
95 return !(rhs < lhs);
|
|
96 }
|
|
97 inline bool operator>=(const string& lhs, const string& rhs)
|
|
98 {
|
|
99 return !(lhs < rhs);
|
|
100 }
|
|
101
|
|
102 inline bool
|
|
103 operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;}
|
|
104 inline bool
|
|
105 operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;}
|
|
106 inline bool
|
|
107 operator< (const string& lhs, const std::string& rhs) {return lhs.str < rhs;}
|
|
108 inline bool
|
|
109 operator> (const string& lhs, const std::string& rhs) {return lhs.str > rhs;}
|
|
110 inline bool
|
|
111 operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;}
|
|
112 inline bool
|
|
113 operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;}
|
|
114
|
|
115 inline bool
|
|
116 operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;}
|
|
117 inline bool
|
|
118 operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;}
|
|
119 inline bool
|
|
120 operator< (const std::string& lhs, const string& rhs) {return lhs < rhs.str;}
|
|
121 inline bool
|
|
122 operator> (const std::string& lhs, const string& rhs) {return lhs > rhs.str;}
|
|
123 inline bool
|
|
124 operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;}
|
|
125 inline bool
|
|
126 operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;}
|
|
127
|
|
128 inline bool
|
|
129 operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);}
|
|
130 inline bool
|
|
131 operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);}
|
|
132 inline bool
|
|
133 operator< (const string& lhs, const char* rhs) {return lhs.str < std::string(rhs);}
|
|
134 inline bool
|
|
135 operator> (const string& lhs, const char* rhs) {return lhs.str > std::string(rhs);}
|
|
136 inline bool
|
|
137 operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);}
|
|
138 inline bool
|
|
139 operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);}
|
|
140
|
|
141 inline bool
|
|
142 operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;}
|
|
143 inline bool
|
|
144 operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;}
|
|
145 inline bool
|
|
146 operator< (const char* lhs, const string& rhs) {return std::string(lhs) < rhs.str;}
|
|
147 inline bool
|
|
148 operator> (const char* lhs, const string& rhs) {return std::string(lhs) > rhs.str;}
|
|
149 inline bool
|
|
150 operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;}
|
|
151 inline bool
|
|
152 operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;}
|
|
153
|
|
154 template<typename charT, typename traits>
|
|
155 std::basic_ostream<charT, traits>&
|
|
156 operator<<(std::basic_ostream<charT, traits>& os, const string& s)
|
|
157 {
|
|
158 if(s.kind == string_t::basic)
|
|
159 {
|
|
160 if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
|
|
161 {
|
|
162 // it contains newline. make it multiline string.
|
|
163 os << "\"\"\"\n";
|
|
164 for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
|
|
165 {
|
|
166 switch(*i)
|
|
167 {
|
|
168 case '\\': {os << "\\\\"; break;}
|
|
169 case '\"': {os << "\\\""; break;}
|
|
170 case '\b': {os << "\\b"; break;}
|
|
171 case '\t': {os << "\\t"; break;}
|
|
172 case '\f': {os << "\\f"; break;}
|
|
173 case '\n': {os << '\n'; break;}
|
|
174 case '\r':
|
|
175 {
|
|
176 // since it is a multiline string,
|
|
177 // CRLF is not needed to be escaped.
|
|
178 if(std::next(i) != e && *std::next(i) == '\n')
|
|
179 {
|
|
180 os << "\r\n";
|
|
181 ++i;
|
|
182 }
|
|
183 else
|
|
184 {
|
|
185 os << "\\r";
|
|
186 }
|
|
187 break;
|
|
188 }
|
|
189 default: {os << *i; break;}
|
|
190 }
|
|
191 }
|
|
192 os << "\\\n\"\"\"";
|
|
193 return os;
|
|
194 }
|
|
195 // no newline. make it inline.
|
|
196 os << "\"";
|
|
197 for(const auto c : s.str)
|
|
198 {
|
|
199 switch(c)
|
|
200 {
|
|
201 case '\\': {os << "\\\\"; break;}
|
|
202 case '\"': {os << "\\\""; break;}
|
|
203 case '\b': {os << "\\b"; break;}
|
|
204 case '\t': {os << "\\t"; break;}
|
|
205 case '\f': {os << "\\f"; break;}
|
|
206 case '\n': {os << "\\n"; break;}
|
|
207 case '\r': {os << "\\r"; break;}
|
|
208 default : {os << c; break;}
|
|
209 }
|
|
210 }
|
|
211 os << "\"";
|
|
212 return os;
|
|
213 }
|
|
214 // the string `s` is literal-string.
|
|
215 if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
|
|
216 std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
|
|
217 {
|
|
218 // contains newline or single quote. make it multiline.
|
|
219 os << "'''\n" << s.str << "'''";
|
|
220 return os;
|
|
221 }
|
|
222 // normal literal string
|
|
223 os << '\'' << s.str << '\'';
|
|
224 return os;
|
|
225 }
|
|
226
|
|
227 } // toml
|
|
228 #endif// TOML11_STRING_H
|