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