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, 93 const CompareType ct=CASE_SENSITIVE); 94 bool startsWith(const tstring &str, const tstring &substr, 95 const CompareType ct=CASE_SENSITIVE); 96 bool endsWith(const tstring &str, const tstring &substr, 97 const CompareType ct=CASE_SENSITIVE); 98 99 enum SplitType {ST_ALL, ST_EXCEPT_EMPTY_STRING}; 100 void split(tstring_array &strVector, const tstring &str, 101 const tstring &delimiter, const SplitType st = ST_ALL); 102 inline tstring_array split(const tstring &str, const tstring &delimiter, 103 const SplitType st = ST_ALL) { 104 tstring_array result; 105 split(result, str, delimiter, st); 106 return result; 107 } 108 tstring trim(const tstring& str, const tstring& whitespace = _T(" \t")); 109 110 /** 111 * Writes sequence of values from [b, e) range into string buffer inserting 112 * 'delimiter' after each value except of the last one. 113 * Returns contents of string buffer. 114 */ 115 template <class It> 116 tstring join(It b, It e, const tstring& delimiter=tstring()) { 117 tostringstream buf; 118 if (b != e) { 119 for (;;) { 120 buf << *b; 121 if (++b == e) { 122 break; 123 } 124 buf << delimiter; 125 } 126 } 127 return buf.str(); 128 } 129 130 tstring toLower(const tstring& str); 131 132 tstring replace(const tstring &str, const tstring &search, 133 const tstring &replace); 134 } 135 136 137 namespace tstrings { 138 inline std::string toUtf8(const std::string& utf8str) { 139 return utf8str; 140 } 141 142 #ifdef TSTRINGS_WITH_WCHAR 143 // conversion to Utf8 144 std::string toUtf8(const std::wstring& utf16str); 145 146 // conversion to Utf16 147 std::wstring toUtf16(const std::string& utf8str); 148 149 inline std::wstring fromUtf8(const std::string& utf8str) { 150 return toUtf16(utf8str); 151 } 152 153 #else 154 inline std::string fromUtf8(const std::string& utf8str) { 155 return utf8str; 156 } 157 #endif 158 } // namespace tstrings 159 160 161 namespace tstrings { 162 namespace format_detail { 163 164 template <class T> 165 struct str_arg_value { 166 const tstring value; 167 168 str_arg_value(const std::string& v): value(fromUtf8(v)) { 169 } 170 171 #ifdef TSTRINGS_WITH_WCHAR 172 str_arg_value(const std::wstring& v): value(v) { 173 } 174 #endif 175 176 tstring::const_pointer operator () () const { 177 return value.c_str(); 178 } 179 }; 180 181 template <> 182 struct str_arg_value<tstring> { 183 const tstring::const_pointer value; 184 185 str_arg_value(const tstring& v): value(v.c_str()) { 186 } 187 188 str_arg_value(tstring::const_pointer v): value(v) { 189 } 190 191 tstring::const_pointer operator () () const { 192 return value; 193 } 194 }; 195 196 inline str_arg_value<std::string> arg(const std::string& v) { 197 return v; 198 } 199 200 inline str_arg_value<std::string> arg(std::string::const_pointer v) { 201 return (v ? v : "(null)"); 202 } 203 204 #ifdef TSTRINGS_WITH_WCHAR 205 inline str_arg_value<std::wstring> arg(const std::wstring& v) { 206 return v; 207 } 208 209 inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) { 210 return (v ? v : L"(null)"); 211 } 212 #else 213 void arg(const std::wstring&); // Compilation error by design. 214 void arg(std::wstring::const_pointer); // Compilation error by design. 215 #endif 216 217 template <class T> 218 struct arg_value { 219 arg_value(const T v): v(v) { 220 } 221 T operator () () const { 222 return v; 223 } 224 private: 225 const T v; 226 }; 227 228 inline arg_value<int> arg(int v) { 229 return v; 230 } 231 inline arg_value<unsigned> arg(unsigned v) { 232 return v; 233 } 234 inline arg_value<long> arg(long v) { 235 return v; 236 } 237 inline arg_value<unsigned long> arg(unsigned long v) { 238 return v; 239 } 240 inline arg_value<long long> arg(long long v) { 241 return v; 242 } 243 inline arg_value<unsigned long long> arg(unsigned long long v) { 244 return v; 245 } 246 inline arg_value<float> arg(float v) { 247 return v; 248 } 249 inline arg_value<double> arg(double v) { 250 return v; 251 } 252 inline arg_value<bool> arg(bool v) { 253 return v; 254 } 255 inline arg_value<const void*> arg(const void* v) { 256 return v; 257 } 258 259 } // namespace format_detail 260 } // namespace tstrings 261 262 263 namespace tstrings { 264 template <class T, class T2, class T3, class T4, class T5, class T6, class T7> 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, const T7& v7) { 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 format_detail::arg(v7)()); 273 } 274 275 template <class T, class T2, class T3, class T4, class T5, class T6> 276 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) { 277 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 278 format_detail::arg(v2)(), 279 format_detail::arg(v3)(), 280 format_detail::arg(v4)(), 281 format_detail::arg(v5)(), 282 format_detail::arg(v6)()); 283 } 284 285 template <class T, class T2, class T3, class T4, class T5> 286 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5) { 287 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 288 format_detail::arg(v2)(), 289 format_detail::arg(v3)(), 290 format_detail::arg(v4)(), 291 format_detail::arg(v5)()); 292 } 293 294 template <class T, class T2, class T3, class T4> 295 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4) { 296 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 297 format_detail::arg(v2)(), 298 format_detail::arg(v3)(), 299 format_detail::arg(v4)()); 300 } 301 302 template <class T, class T2, class T3> 303 inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3) { 304 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 305 format_detail::arg(v2)(), 306 format_detail::arg(v3)()); 307 } 308 309 template <class T, class T2> 310 inline tstring format(const tstring& fmt, const T& v, const T2& v2) { 311 return unsafe_format(fmt.c_str(), format_detail::arg(v)(), 312 format_detail::arg(v2)()); 313 314 } 315 316 template <class T> 317 inline tstring format(const tstring& fmt, const T& v) { 318 return unsafe_format(fmt.c_str(), format_detail::arg(v)()); 319 } 320 } // namespace tstrings 321 322 323 namespace tstrings { 324 /** 325 * Buffer that accepts both std::wstring and std::string instances doing 326 * encoding conversions behind the scenes. All std::string-s assumed to be 327 * UTF8-encoded, all std::wstring-s assumed to be UTF16-encoded. 328 */ 329 class any { 330 public: 331 any() { 332 } 333 334 any(std::string::const_pointer msg) { 335 data << fromUtf8(msg); 336 } 337 338 any(const std::string& msg) { 339 data << fromUtf8(msg); 340 } 341 342 #ifdef TSTRINGS_WITH_WCHAR 343 any(std::wstring::const_pointer msg) { 344 data << msg; 345 } 346 347 any(const std::wstring& msg) { 348 data << msg; 349 } 350 351 any& operator << (const std::wstring& v) { 352 data << v; 353 return *this; 354 } 355 356 // need this specialization instead std::wstring::pointer, 357 // otherwise LPWSTR is handled as abstract pointer (void*) 358 any& operator << (LPWSTR v) { 359 data << (v ? v : L"NULL"); 360 return *this; 361 } 362 363 // need this specialization instead std::wstring::const_pointer, 364 // otherwise LPCWSTR is handled as abstract pointer (const void*) 365 any& operator << (LPCWSTR v) { 366 data << (v ? v : L"NULL"); 367 return *this; 368 } 369 370 std::wstring wstr() const { 371 return data.str(); 372 } 373 #endif 374 375 template <class T> 376 any& operator << (T v) { 377 data << v; 378 return *this; 379 } 380 381 any& operator << (tostream& (*pf)(tostream&)) { 382 data << pf; 383 return *this; 384 } 385 386 any& operator << (tios& (*pf)(tios&)) { 387 data << pf; 388 return *this; 389 } 390 391 any& operator << (std::ios_base& (*pf)(std::ios_base&)) { 392 data << pf; 393 return *this; 394 } 395 396 std::string str() const { 397 return toUtf8(data.str()); 398 } 399 400 tstring tstr() const { 401 return data.str(); 402 } 403 404 private: 405 tostringstream data; 406 }; 407 408 inline tstring to_tstring(const any& val) { 409 return val.tstr(); 410 } 411 } // namespace tstrings 412 413 414 inline std::ostream& operator << (std::ostream& os, const tstrings::any& buf) { 415 os << buf.str(); 416 return os; 417 } 418 419 #ifdef TSTRINGS_WITH_WCHAR 420 inline std::wostream& operator << (std::wostream& os, const tstrings::any& buf) { 421 os << buf.wstr(); 422 return os; 423 } 424 #endif 425 426 #endif //TSTRINGS_H