1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifndef TSTRINGS_H 27 #define TSTRINGS_H 28 29 #ifdef _MSC_VER 30 # define TSTRINGS_WITH_WCHAR 31 #endif 32 33 #ifdef TSTRINGS_WITH_WCHAR 34 #include <windows.h> 35 #include <tchar.h> 36 // Want compiler issue C4995 warnings for encounters of deprecated functions. 37 #include <strsafe.h> 38 #endif 39 40 // STL's string header depends on deprecated functions. 41 // We don't care about warnings from STL header, so disable them locally. 42 #ifdef _MSC_VER 43 # pragma warning(push) 44 # pragma warning(disable:4995) 45 #endif 46 47 #include <string> 48 #include <sstream> 49 #include <iostream> 50 #include <vector> 51 52 #ifdef _MSC_VER 53 # pragma warning(pop) 54 #endif 55 56 57 #ifndef _T 58 # define _T(x) x 59 #endif 60 61 62 #ifdef TSTRINGS_WITH_WCHAR 63 typedef std::wstring tstring; 64 typedef std::wostringstream tostringstream; 65 typedef std::wistringstream tistringstream; 66 typedef std::wstringstream tstringstream; 67 typedef std::wistream tistream; 68 typedef std::wostream tostream; 69 typedef std::wiostream tiostream; 70 typedef std::wios tios; 71 #else 72 typedef std::string tstring; 73 typedef std::ostringstream tostringstream; 74 typedef std::istringstream tistringstream; 75 typedef std::stringstream tstringstream; 76 typedef std::istream tistream; 77 typedef std::ostream tostream; 78 typedef std::iostream tiostream; 79 typedef std::ios tios; 80 81 typedef const char* LPCTSTR; 82 typedef char TCHAR; 83 #endif 84 85 // frequently used "array of tstrings" type 86 typedef std::vector<tstring> tstring_array; 87 88 namespace tstrings { 89 tstring unsafe_format(tstring::const_pointer format, ...); 90 91 enum CompareType {CASE_SENSITIVE, IGNORE_CASE}; 92 bool equals(const tstring& a, const tstring& b, const CompareType ct=CASE_SENSITIVE); 93 bool startsWith(const tstring &str, const tstring &substr, const CompareType ct=CASE_SENSITIVE); 94 bool endsWith(const tstring &str, const tstring &substr, const CompareType ct=CASE_SENSITIVE); 95 96 enum SplitType {ST_ALL, ST_EXCEPT_EMPTY_STRING}; 97 void split(tstring_array &strVector, const tstring &str, 98 const tstring &delimiter, const SplitType st = ST_ALL); 99 inline tstring_array split(const tstring &str, const tstring &delimiter, const SplitType st = ST_ALL) { 100 tstring_array result; 101 split(result, str, delimiter, st); 102 return result; 103 } 104 tstring trim(const tstring& str, const tstring& whitespace = _T(" \t")); 105 106 /** 107 * Writes sequence of values from [b, e) range into string buffer inserting 108 * 'delimiter' after each value except of the last one. 109 * Returns contents of string buffer. 110 */ 111 template <class It> 112 tstring join(It b, It e, const tstring& delimiter=tstring()) { 113 tostringstream buf; 114 if (b != e) { 115 for (;;) { 116 buf << *b; 117 if (++b == e) { 118 break; 119 } 120 buf << delimiter; 121 } 122 } 123 return buf.str(); 124 } 125 126 tstring toLower(const tstring& str); 127 128 tstring replace(const tstring &str, const tstring &search, const tstring &replace); 129 } 130 131 132 namespace tstrings { 133 inline std::string toUtf8(const std::string& utf8str) { return utf8str; } 134 135 #ifdef TSTRINGS_WITH_WCHAR 136 // conversion to Utf8 137 std::string toUtf8(const std::wstring& utf16str); 138 139 // conversion to Utf16 140 std::wstring toUtf16(const std::string& utf8str); 141 142 inline std::wstring fromUtf8(const std::string& utf8str) { return toUtf16(utf8str); } 143 144 #else 145 inline std::string fromUtf8(const std::string& utf8str) { return utf8str; } 146 #endif 147 } // namespace tstrings 148 149 150 namespace tstrings { 151 namespace format_detail { 152 153 template <class T> 154 struct str_arg_value { 155 const tstring value; 156 157 str_arg_value(const std::string& v): value(fromUtf8(v)) { 158 } 159 160 #ifdef TSTRINGS_WITH_WCHAR 161 str_arg_value(const std::wstring& v): value(v) { 162 } 163 #endif 164 165 tstring::const_pointer operator () () const { 166 return value.c_str(); 167 } 168 }; 169 170 template <> 171 struct str_arg_value<tstring> { 172 const tstring::const_pointer value; 173 174 str_arg_value(const tstring& v): value(v.c_str()) { 175 } 176 177 str_arg_value(tstring::const_pointer v): value(v) { 178 } 179 180 tstring::const_pointer operator () () const { 181 return value; 182 } 183 }; 184 185 inline str_arg_value<std::string> arg(const std::string& v) { 186 return v; 187 } 188 189 inline str_arg_value<std::string> arg(std::string::const_pointer v) { 190 return (v ? v : "(null)"); 191 } 192 193 #ifdef TSTRINGS_WITH_WCHAR 194 inline str_arg_value<std::wstring> arg(const std::wstring& v) { 195 return v; 196 } 197 198 inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) { 199 return (v ? v : L"(null)"); 200 } 201 #else 202 void arg(const std::wstring&); // Compilation error by design. 203 void arg(std::wstring::const_pointer); // Compilation error by design. 204 #endif 205 206 template <class T> 207 struct arg_value { 208 arg_value(const T v): v(v) { 209 } 210 T operator () () const { 211 return v; 212 } 213 private: 214 const T v; 215 }; 216 217 inline arg_value<int> arg(int v) { 218 return v; 219 } 220 inline arg_value<unsigned> arg(unsigned v) { 221 return v; 222 } 223 inline arg_value<long> arg(long v) { 224 return v; 225 } 226 inline arg_value<unsigned long> arg(unsigned long v) { 227 return v; 228 } 229 inline arg_value<long long> arg(long long v) { 230 return v; 231 } 232 inline arg_value<unsigned long long> arg(unsigned long long v) { 233 return v; 234 } 235 inline arg_value<float> arg(float v) { 236 return v; 237 } 238 inline arg_value<double> arg(double v) { 239 return v; 240 } 241 inline arg_value<bool> arg(bool v) { 242 return v; 243 } 244 inline arg_value<const void*> arg(const void* v) { 245 return v; 246 } 247 248 } // namespace format_detail 249 } // namespace tstrings 250 251 252 namespace tstrings { 253 template <class T, class T2, class T3, class T4, class T5, class T6, class T7> 254 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7) { 255 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 256 format_detail::arg(v2)(), 257 format_detail::arg(v3)(), 258 format_detail::arg(v4)(), 259 format_detail::arg(v5)(), 260 format_detail::arg(v6)(), 261 format_detail::arg(v7)()); 262 } 263 264 template <class T, class T2, class T3, class T4, class T5, class T6> 265 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) { 266 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 267 format_detail::arg(v2)(), 268 format_detail::arg(v3)(), 269 format_detail::arg(v4)(), 270 format_detail::arg(v5)(), 271 format_detail::arg(v6)()); 272 } 273 274 template <class T, class T2, class T3, class T4, class T5> 275 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5) { 276 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 277 format_detail::arg(v2)(), 278 format_detail::arg(v3)(), 279 format_detail::arg(v4)(), 280 format_detail::arg(v5)()); 281 } 282 283 template <class T, class T2, class T3, class T4> 284 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4) { 285 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 286 format_detail::arg(v2)(), 287 format_detail::arg(v3)(), 288 format_detail::arg(v4)()); 289 } 290 291 template <class T, class T2, class T3> 292 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3) { 293 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 294 format_detail::arg(v2)(), 295 format_detail::arg(v3)()); 296 } 297 298 template <class T, class T2> 299 inline tstring format(const tstring& fmt, const T& v, const T2& v2) { 300 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 301 format_detail::arg(v2)()); 302 303 } 304 305 template <class T> 306 inline tstring format(const tstring& fmt, const T& v) { 307 return unsafe_format(fmt.c_str(), format_detail::arg(v)()); 308 } 309 } // namespace tstrings 310 311 312 namespace tstrings { 313 /** 314 * Buffer that accepts both std::wstring and std::string instances doing 315 * encoding conversions behind the scenes. All std::string-s assumed to be 316 * UTF8-encoded, all std::wstring-s assumed to be UTF16-encoded. 317 */ 318 class any { 319 public: 320 any() { 321 } 322 323 any(std::string::const_pointer msg) { 324 data << fromUtf8(msg); 325 } 326 327 any(const std::string& msg) { 328 data << fromUtf8(msg); 329 } 330 331 #ifdef TSTRINGS_WITH_WCHAR 332 any(std::wstring::const_pointer msg) { 333 data << msg; 334 } 335 336 any(const std::wstring& msg) { 337 data << msg; 338 } 339 340 any& operator << (const std::wstring& v) { 341 data << v; 342 return *this; 343 } 344 345 // need this specialization instead std::wstring::pointer, 346 // otherwise LPWSTR is handled as abstract pointer (void*) 347 any& operator << (LPWSTR v) { 348 data << (v ? v : L"NULL"); 349 return *this; 350 } 351 352 // need this specialization instead std::wstring::const_pointer, 353 // otherwise LPCWSTR is handled as abstract pointer (const void*) 354 any& operator << (LPCWSTR v) { 355 data << (v ? v : L"NULL"); 356 return *this; 357 } 358 359 std::wstring wstr() const { 360 return data.str(); 361 } 362 #endif 363 364 template <class T> 365 any& operator << (T v) { 366 data << v; 367 return *this; 368 } 369 370 any& operator << (tostream& (*pf)(tostream&)) { 371 data << pf; 372 return *this; 373 } 374 375 any& operator << (tios& (*pf)(tios&)) { 376 data << pf; 377 return *this; 378 } 379 380 any& operator << (std::ios_base& (*pf)(std::ios_base&)) { 381 data << pf; 382 return *this; 383 } 384 385 std::string str() const { 386 return toUtf8(data.str()); 387 } 388 389 tstring tstr() const { 390 return data.str(); 391 } 392 393 private: 394 tostringstream data; 395 }; 396 397 inline tstring to_tstring(const any& val) { 398 return val.tstr(); 399 } 400 } // namespace tstrings 401 402 403 inline std::ostream& operator << (std::ostream& os, const tstrings::any& buf) { 404 os << buf.str(); 405 return os; 406 } 407 408 #ifdef TSTRINGS_WITH_WCHAR 409 inline std::wostream& operator << (std::wostream& os, const tstrings::any& buf) { 410 os << buf.wstr(); 411 return os; 412 } 413 #endif 414 415 #endif //TSTRINGS_H