00001 /* 00002 * String.hpp 00003 * 00004 * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_STRING_HPP 00017 #define COH_STRING_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 #include "coherence/lang/Array.hpp" 00022 #include "coherence/lang/Comparable.hpp" 00023 #include "coherence/lang/Object.hpp" 00024 00025 #include <memory> 00026 00027 #include <sstream> 00028 #include <string> 00029 00030 COH_OPEN_NAMESPACE2(coherence,lang) 00031 00032 /** 00033 * @internal 00034 * 00035 * Used to protect protected inheritance of Array<octet_t> by String, as 00036 * spec based class definitions don't have a notion of protected 00037 * inheritance. 00038 */ 00039 class COH_EXPORT_SPEC ProtectedOctetArray 00040 : protected Array<octet_t> 00041 { 00042 public: 00043 typedef Array<octet_t>::super super; 00044 typedef Array<octet_t>::alias alias; 00045 00046 protected: 00047 ProtectedOctetArray(size32_t cb, octet_t* ab) 00048 : Array<octet_t>(cb, ab) 00049 {} 00050 00051 ProtectedOctetArray(ProtectedOctetArray::View vThat, 00052 size32_t iFrom, size32_t iTo) 00053 : Array<octet_t>(vThat, iFrom, iTo) 00054 {} 00055 00056 virtual ~ProtectedOctetArray() 00057 {} 00058 }; 00059 00060 00061 /** 00062 * A managed C-style (NUL terminated) string. 00063 * 00064 * In addition to exposing the underlying char array, the String class 00065 * supports transformations to and from Unicode code points within the Basic 00066 * Multilingual Plane (BMP): 00067 * 00068 * <ul> 00069 * <li>UTF-8 BMP char array</li> 00070 * <li>UTF-16 BMP wchar_t array (on platforms where wchar_t is >= 16 bits)</li> 00071 * <li>UTF-8 BMP octet_t array</li> 00072 * <li>UTF-16 BMP wchar16_t array</li> 00073 * </ul> 00074 * 00075 * Note: the ASCII character set is a subset of UTF-8 BMP. 00076 * 00077 * Unlike most managed types in the Coherence class hierarchy, Strings are 00078 * auto-boxable by default. That is a String::Handle or String::View can be 00079 * directly assigned from or to common string representations. For example 00080 * the following code is legal: 00081 * @code 00082 * String::Handle hs = "hello world"; 00083 * @endcode 00084 * as is 00085 * @code 00086 * void someFunction(String::View vs); 00087 * 00088 * someFunction("some value"); 00089 * @endcode 00090 * 00091 * @see StringHandle for details 00092 * 00093 * @author mf/jh/djl 2007.07.05 00094 */ 00095 class COH_EXPORT String 00096 : public cloneable_spec<String, 00097 extends<ProtectedOctetArray>, 00098 implements<Comparable> > 00099 { 00100 friend class factory<String>; 00101 00102 // ----- constants ------------------------------------------------------ 00103 00104 public: 00105 /** 00106 * The largest possible value of type size32_t. 00107 */ 00108 static const size32_t npos = size32_t(-1); 00109 00110 00111 // ----- typedefs ------------------------------------------------------- 00112 00113 public: 00114 /** 00115 * While StringHandle boxes a number of common string types, String is 00116 * still compatible with BoxHandle, and when used with it can box to 00117 * only one type. By default Strings are boxable from a number of 00118 * types, see StringHandle for details. 00119 */ 00120 typedef std::string BoxedType; 00121 00122 00123 // ----- nested class: StringHandle ------------------------------------- 00124 00125 public: 00126 /** 00127 * StringHandle provides standard TypedHandle features as well as 00128 * auto-boxing support for standard string types including: 00129 * 00130 * <ul> 00131 * <li>char[] C-style NUL terminated char array</li> 00132 * <li>std::string STL string</li> 00133 * <li>std::wstring STL wide string</li> 00134 * </ul> 00135 * 00136 * Boxing from wchar_t[] is supported, but requires an explicit 00137 * constructor call in order to avoid ambiguity when assigning a 00138 * String handle/view to NULL. 00139 * 00140 * Unboxing to char[] and wchar[] is not supported as it is unsafe to 00141 * maintain a reference to the underlying character array without 00142 * holding a reference to the String. Unboxing to std::string, and 00143 * std::wstring is both supported and safe. 00144 */ 00145 template<class T> class StringHandle 00146 : public TypedHandle<T> 00147 { 00148 // ----- constructors --------------------------------------- 00149 00150 public: 00151 /** 00152 * Create an empty StringHandle. 00153 */ 00154 StringHandle() 00155 : TypedHandle<T>() 00156 { 00157 } 00158 00159 /** 00160 * Create a new StringHandle from a boxable type. 00161 */ 00162 StringHandle(const char* ach) 00163 : TypedHandle<T>() 00164 { 00165 if (NULL != ach) 00166 { 00167 TypedHandle<T>::operator=(T::create(ach)); 00168 } 00169 } 00170 00171 /** 00172 * Create a new StringHandle from a boxable type. 00173 */ 00174 explicit StringHandle(const wchar_t* ach) 00175 : TypedHandle<T>() 00176 { 00177 if (NULL != ach) 00178 { 00179 TypedHandle<T>::operator=(T::create(ach)); 00180 } 00181 } 00182 00183 /** 00184 * Create a new StringHandle from a boxable type. 00185 */ 00186 template<class C, class R, class A> COH_INLINE 00187 StringHandle(const std::basic_string<C, R, A>& s) 00188 : TypedHandle<T>(T::create(s)) 00189 { 00190 } 00191 00192 /** 00193 * Create a new StringHandle from the TypedHandle with a type 00194 * conversion. 00195 */ 00196 template<class O> StringHandle<T>(const TypedHandle<O>& that) 00197 : TypedHandle<T>(that) 00198 { 00199 } 00200 00201 /** 00202 * The copy constructor. 00203 */ 00204 StringHandle(const StringHandle& that) 00205 : TypedHandle<T>(that) 00206 { 00207 } 00208 00209 /** 00210 * Create a new StringHandle from the raw pointer. 00211 */ 00212 explicit StringHandle(T* o) 00213 : TypedHandle<T>(o) 00214 { 00215 } 00216 00217 // ----- operators ------------------------------------------ 00218 00219 public: 00220 /** 00221 * The assignment operator. 00222 */ 00223 template<class O> 00224 StringHandle& operator=(const TypedHandle<O>& that) 00225 { 00226 TypedHandle<T>::operator=(that); 00227 return *this; 00228 } 00229 00230 /** 00231 * The "boxing" operator. 00232 */ 00233 StringHandle& operator=(const char* ach) 00234 { 00235 if (NULL == ach) 00236 { 00237 TypedHandle<T>::operator=(NULL); 00238 } 00239 else 00240 { 00241 TypedHandle<T>::operator=(T::create(ach)); 00242 } 00243 return *this; 00244 } 00245 00246 /** 00247 * The "boxing" operator. 00248 */ 00249 template<class C, class R, class A> COH_INLINE 00250 StringHandle& operator=(const std::basic_string<C, R, A>& s) 00251 { 00252 TypedHandle<T>::operator=(T::create(s)); 00253 return *this; 00254 } 00255 00256 /** 00257 * The "unboxing" operator. 00258 * 00259 * @return a copy of the referenced Object 00260 */ 00261 template<class C, class R, class A> COH_INLINE 00262 operator std::basic_string<C, R, A>() const 00263 { 00264 const T* pT = TypedHandle<T>::get(); 00265 if (NULL == pT) 00266 { 00267 coh_throw_npe(typeid(T)); 00268 } 00269 return (std::basic_string<C, R, A>) *pT; 00270 } 00271 }; 00272 00273 // ----- handle definitions --------------------------------------------- 00274 00275 public: 00276 /** 00277 * Handle definition. 00278 */ 00279 typedef StringHandle<String> Handle; 00280 00281 /** 00282 * View definition. 00283 */ 00284 typedef StringHandle<const String> View; 00285 00286 00287 // ----- factory methods ------------------------------------------------ 00288 00289 public: 00290 /** 00291 * Create a String from a C-style NUL terminated char array. 00292 * 00293 * @param ach the NUL terminated string of chars to copy 00294 * @param cch the number of chars to copy; if npos, until NUL 00295 * 00296 * @throws IllegalArgumentException if any of the elements in the 00297 * array are not UTF-8 BMP 00298 */ 00299 static String::Handle create(const char* achSrc = "", size32_t cch = npos); 00300 00301 /** 00302 * Create a String from a C-style NUL terminated wide char array. 00303 * 00304 * @param ach the NUL terminated string of wide chars to copy 00305 * @param cch the number of chars to copy; if npos, copy until NUL 00306 * 00307 * @throws IllegalArgumentException if any of the elements in the 00308 * array are not UTF-16 BMP 00309 */ 00310 static String::Handle create(const wchar_t* achSrc, size32_t cch = npos); 00311 00312 /** 00313 * Create a String from an STL string. 00314 * 00315 * @param s the STL string to copy 00316 * 00317 * @throws IllegalArgumentException if any of the elements in the 00318 * array are not UTF-8 BMP 00319 */ 00320 template<class C, class R, class A> static COH_INLINE 00321 String::Handle create(const std::basic_string<C, R, A>& s) 00322 { 00323 size_t cch = s.size(); 00324 if (cch >= npos) // for 64b 00325 { 00326 coh_throw_illegal_argument("maximum String length exceeded"); 00327 } 00328 return String::create(s.data(), size32_t(cch)); 00329 } 00330 00331 /** 00332 * Create a String from a char array. 00333 * 00334 * @param vach the array of chars to copy 00335 * @param of the offset at which to start copying 00336 * @param cch the number of chars to copy; if npos, copy all 00337 * subsequent chars in the array 00338 * 00339 * @throws IndexOutOfBoundsException if of > vach->length or if 00340 * cch < npos and of + cch > vach->length 00341 * @throws IllegalArgumentException if any of the elements in the 00342 * array are not UTF-8 BMP 00343 */ 00344 static String::Handle create(Array<char>::View vachSrc, 00345 size32_t of = 0, size32_t cch = npos); 00346 00347 /** 00348 * Create a String from a wide char array. 00349 * 00350 * @param vach the array of chars to copy 00351 * @param of the offset at which to start copying 00352 * @param cch the number of chars to copy; if npos, copy all 00353 * subsequent chars in the array 00354 * 00355 * @throws IndexOutOfBoundsException if of > vach->length or if 00356 * cch < npos and of + cch > vach->length 00357 * @throws IllegalArgumentException if any of the elements in the 00358 * array are not UTF-16 BMP 00359 * @throws UnsupportedOperationException if sizeof(wchar_t) < 00360 * sizeof(wchar16_t) 00361 */ 00362 static String::Handle create(Array<wchar_t>::View vachSrc, 00363 size32_t of = 0, size32_t cch = npos); 00364 00365 /** 00366 * Create a String from an octet array. 00367 * 00368 * @param vab the array of octets to copy 00369 * @param of the offset at which to start copying 00370 * @param cb the number of octets to copy; if npos, copy all 00371 * subsequent octets in the array 00372 * 00373 * @throws IndexOutOfBoundsException if of > vab->length or if 00374 * cb < npos and of + cb > vab->length 00375 * @throws IllegalArgumentException if any of the elements in the 00376 * array are not UTF-8 BMP 00377 */ 00378 static String::Handle create(Array<octet_t>::View vabSrc, 00379 size32_t of = 0, size32_t cb = npos); 00380 00381 /** 00382 * Create a String from a 16-bit char array. 00383 * 00384 * @param vach the array of chars to copy 00385 * @param of the offset at which to start copying 00386 * @param cch the number of chars to copy; if npos, copy all 00387 * subsequent chars in the array 00388 * 00389 * @throws IndexOutOfBoundsException if of > vach->length or if 00390 * cch < npos and of + cch > vach->length 00391 * @throws IllegalArgumentException if any of the elements in the 00392 * array are not UTF-16 BMP 00393 */ 00394 static String::Handle create(Array<wchar16_t>::View vachSrc, 00395 size32_t of = 0, size32_t cch = npos); 00396 00397 /** 00398 * Create a String from another String. 00399 * 00400 * Needed for clone(). 00401 * 00402 * @param that the String to copy 00403 * 00404 * @since Coherence 3.7.1.8 00405 */ 00406 static String::Handle create(const String& that); 00407 00408 00409 // ----- constructors --------------------------------------------------- 00410 00411 private: 00412 /** 00413 * Constructor. 00414 * 00415 * @param ccp the number of code points in the string 00416 * @param cb the number of octets in the string 00417 * @param ab the String's octets 00418 * @param fCs true if ab represents a c string 00419 */ 00420 String(size32_t ccp, size32_t cb, octet_t* ab, bool fCs); 00421 00422 /** 00423 * Copy constructor. 00424 */ 00425 String(const String& that); 00426 00427 00428 // ----- String interface ----------------------------------------------- 00429 00430 public: 00431 /** 00432 * Return true iff the String contains only ASCII (ISO-8859-1) 00433 * characters. In this case each character is represented by a single 00434 * char, otherwise a character can take between one and three chars. 00435 * 00436 * @return true iff the String contains only ASCII characters 00437 */ 00438 virtual bool isASCII() const; 00439 00440 /** 00441 * Return true if the String is ASCII and does not contain embedded nuls. 00442 * 00443 * @return true if the String is a C string. 00444 */ 00445 virtual bool isCString() const; 00446 00447 /** 00448 * Return the number of unicode code points (characters) in this String. 00449 * 00450 * @return the number of characters in this String 00451 */ 00452 virtual size32_t length() const; 00453 00454 /** 00455 * Returns true if, and only if, length() is 0. 00456 * 00457 * @return true if length() is 0, otherwise false 00458 * 00459 * @since 12.2.1 00460 */ 00461 virtual bool isEmpty() const; 00462 00463 /** 00464 * Return the String as a C-style NUL terminated char array. 00465 * 00466 * If the String is non-ASCII then the String::next() method may be 00467 * used to expand the char array into a sequence of wchar16_t unicode 00468 * characters. 00469 * 00470 * The returned array's lifetime is bound to the lifetime of the 00471 * String which it was returned from. Specifically it is unsafe to use 00472 * the returned char* while not holding a handle to the String. 00473 * 00474 * @return the char array representing the String. 00475 */ 00476 virtual const char* getCString() const; 00477 00478 /** 00479 * Compare this String against the supplied C-style string. 00480 * 00481 * @param ach the NUL terminated C-style string to compare to this 00482 * String 00483 * @param cch the length of the supplied string, or npos to rely on 00484 * NUL terminator 00485 * 00486 * @return true iff the two strings are identical 00487 */ 00488 virtual bool equals(const char* ach, size32_t cch = npos) const; 00489 00490 /** 00491 * Compare this String against the supplied C-style wide char string. 00492 * 00493 * @param ach the NUL terminated C-style string to compare to this 00494 * String 00495 * @param cch the length of the supplied string, or npos to rely on 00496 * NUL terminator 00497 * 00498 * @return true iff the two strings are identical 00499 * 00500 * @throws UnsupportedOperationException if sizeof(wchar_t) < sizeof(wchar16_t) 00501 */ 00502 virtual bool equals(const wchar_t* ach, size32_t cch = npos) const; 00503 00504 /** 00505 * Compare this String against the supplied STL string or wstring. 00506 * 00507 * @param s the STL string to compare to this String 00508 * 00509 * @return true iff the two strings are identical 00510 */ 00511 template<class C, class R, class A> COH_INLINE 00512 bool equalsStd(const std::basic_string<C, R, A>& s) const 00513 { 00514 size_t cch = s.size(); 00515 return cch < npos && equals(s.data(), size32_t(cch)); 00516 } 00517 00518 /** 00519 * Convert the String to any of the types supported by StringHandle, 00520 * namely an STL string or wstring. 00521 * 00522 * @return the std::string/wstring representation 00523 */ 00524 template<class C, class R, class A> COH_INLINE 00525 operator std::basic_string<C, R, A>() const 00526 { 00527 if (sizeof(C) == sizeof(octet_t)) 00528 { 00529 return std::basic_string<C, R, A>((const C*) getCString(), 00530 super::length - 1); 00531 } 00532 00533 if (sizeof(C) < sizeof(wchar16_t)) 00534 { 00535 coh_throw_unsupported_operation("unsupported string type"); 00536 } 00537 00538 typename std::basic_string<C, R, A>::size_type cch = 00539 typename std::basic_string<C, R, A>::size_type(length()); 00540 const char* iter = getCString(); 00541 std::basic_string<C, R, A> ws; 00542 ws.reserve(cch); 00543 for (typename std::basic_string<C, R, A>::size_type 00544 i = 0; i < cch; ++i) 00545 { 00546 ws.push_back((C) String::next(iter)); 00547 } 00548 return ws; 00549 } 00550 00551 /** 00552 * Return the index of a substring within this String. 00553 * 00554 * @param vsSearch the substring to search for in vsSource 00555 * @param iBegin the location in the string to start searching 00556 * 00557 * @return the index of the substring found within this String or npos 00558 */ 00559 virtual size32_t indexOf(String::View vsSearch, 00560 size32_t iBegin = 0) const; 00561 00562 /** 00563 * Return the index of a character within this String. 00564 * 00565 * @param chSearch the character to search for in this String 00566 * @param iBegin the location in this String to start searching 00567 * 00568 * @return the index of the character found within this String or npos 00569 */ 00570 virtual size32_t indexOf(wchar16_t chSearch, 00571 size32_t iBegin = 0) const; 00572 00573 /** 00574 * Return the index of a substring within this String by searching 00575 * backward from the given beginning index. 00576 * 00577 * @param vsSearh the substring to search for within this String 00578 * @param iBegin the location in this String to start searching 00579 * 00580 * @return the index of the substring found within this String or npos 00581 */ 00582 virtual size32_t lastIndexOf(String::View vsSearch, 00583 size32_t iBegin = npos) const; 00584 00585 /** 00586 * Return the index of a substring within this String by searching 00587 * backward from the given beginning index. 00588 * 00589 * @param chSearch the character to search for in this String 00590 * @param iBegin the location in this String to start searching 00591 * 00592 * @return the index of the character found within this String or npos 00593 */ 00594 virtual size32_t lastIndexOf(wchar16_t chSearch, 00595 size32_t iBegin = npos) const; 00596 00597 /** 00598 * Return a new String that is a substring of this string. The substring 00599 * begins at the specified iBegin and extends to the character at 00600 * index iEnd - 1. Thus the length of the substring is iEnd-iBegin. 00601 * 00602 * @param iBegin the starting index from which to create the string 00603 * @param iEnd the index of where the substring should stop 00604 * in this String or npos for end of string 00605 * 00606 * @throws IndexOutOfBoundsException if iEnd is larger than the length 00607 * of this String object, or if iBegin 00608 * is larger than iEnd. 00609 * 00610 * @return the new substring created from this String 00611 */ 00612 virtual String::View substring(size32_t iBegin, 00613 size32_t iEnd = npos) const; 00614 00615 /** 00616 * Return true if this String starts with the supplied String. 00617 * 00618 * @param vsSearch the string to search for 00619 * 00620 * @return true if this String starts with vsSearch 00621 */ 00622 virtual bool startsWith(String::View vsSearch) const; 00623 00624 /** 00625 * Return true if this String ends with the supplied String. 00626 * 00627 * @param vsSearch the string to search for 00628 * 00629 * @return true if this String ends with vsSearch 00630 */ 00631 virtual bool endsWith(String::View vsSearch) const; 00632 00633 /** 00634 * A substring of this String is compared to a substring of a supplied 00635 * String. 00636 * 00637 * @param ofSource the offset in this String where comparison begins 00638 * @param vsOther the String whose substring is compared against 00639 * this String 00640 * @param ofOther the offset in vsOther where comparison begins 00641 * @param cch the count of characters to compare, or npos for 00642 * (vsOther->length - ofOther) 00643 * 00644 * @return the result of the two substrings 00645 */ 00646 virtual bool regionMatches(size32_t ofSourse, 00647 String::View vsOther, size32_t ofOther = 0, 00648 size32_t cch = npos) const; 00649 00650 /** 00651 * Return a String that is the result of removing all leading and 00652 * trailing white space. 00653 * 00654 * @return a trimmed copy of this String 00655 */ 00656 String::View trim() const; 00657 00658 /** 00659 * Return the underlying UTF-8 BMP NUL terminated Array<octet_t>. 00660 * 00661 * For performance reasons the returned Array may not support cloning. 00662 * If clone() is called the result will a String, which depending on 00663 * the compiler's handling of dynamic_cast to a private super class may 00664 * fail to be castable to an Array<octet_t>. 00665 * 00666 * @return the Array<octet_t> 00667 */ 00668 virtual Array<octet_t>::View getOctets() const; 00669 00670 // ----- static methods ------------------------------------------------- 00671 00672 public: 00673 /** 00674 * Returns the string representation of the {@code v} argument. 00675 * 00676 * @param v an Object. 00677 * 00678 * @return if the argument is {@code NULL}, then a string equal to 00679 * {@code "NULL"}; otherwise, the value of 00680 * {@code v->toString()} is returned 00681 * 00682 * @see Object#toString() 00683 * 00684 * @since 12.2.1 00685 */ 00686 static String::View valueOf(Object::View v); 00687 00688 // ----- Array interface ------------------------------------------------ 00689 00690 protected: 00691 using Array<octet_t>::regionMatches; 00692 00693 00694 // ----- Comparable interface ------------------------------------------- 00695 00696 public: 00697 /** 00698 * {@inheritDoc} 00699 */ 00700 virtual int32_t compareTo(Object::View v) const; 00701 00702 00703 // ----- Object interface ----------------------------------------------- 00704 00705 public: 00706 /** 00707 * {@inheritDoc} 00708 */ 00709 virtual size32_t hashCode() const; 00710 00711 /** 00712 * {@inheritDoc} 00713 */ 00714 virtual TypedHandle<const String> toString() const; 00715 00716 /** 00717 * {@inheritDoc} 00718 */ 00719 virtual bool isImmutable() const; 00720 00721 /** 00722 * {@inheritDoc} 00723 */ 00724 virtual bool equals(Object::View v) const; 00725 00726 /** 00727 * {@inheritDoc} 00728 */ 00729 virtual size64_t sizeOf(bool fDeep = false) const; 00730 00731 // ----- static helpers ------------------------------------------------- 00732 00733 public: 00734 /** 00735 * Return the Unicode character as UTF-16 from the char array, and 00736 * increment the pointer such that it references the start of the 00737 * next Unicode character. 00738 * 00739 * @param ach pointer to the start of the next UTF-8 code point. 00740 * 00741 * @return the next Unicode character 00742 * 00743 * @throws IllegalArgumentException if a non UTF-8 BMP sequence is 00744 * encountered 00745 */ 00746 static wchar16_t next(const char*& ach); 00747 00748 00749 // ----- data members --------------------------------------------------- 00750 00751 protected: 00752 /** 00753 * The number of unicode code points (characters) in the String. 00754 */ 00755 size32_t m_ccp; 00756 00757 /** 00758 * True iff the String is a C string. 00759 */ 00760 bool m_fCString; 00761 00762 00763 // ----- constants ------------------------------------------------------ 00764 00765 public: 00766 /** 00767 * String referencing NULL. 00768 * 00769 * This constant is generally only needed for defining a default 00770 * value for a function parameter: 00771 * 00772 * @code 00773 * void function(String::View vs = String::null_string) 00774 * @endcode 00775 * 00776 * Simply passing NULL as a default is not allowable for Strings as due 00777 * to auto-boxing the compiler is unable to determine if NULL indicates 00778 * a String* or a char*. For all other uses of NULL with String the 00779 * literal NULL is preferred. 00780 */ 00781 static const char* const null_string; 00782 }; 00783 00784 00785 // ----- non-member operators and functions --------------------------------- 00786 00787 /** 00788 * Output a human-readable description of the specified Object to the given 00789 * stream. 00790 * 00791 * @param out the stream used to output the description 00792 * @param o the Object to describe 00793 * 00794 * @return the supplied stream 00795 */ 00796 COH_INLINE std::ostream& operator<<(std::ostream& out, const Object& o) 00797 { 00798 // legacy support for deprecated toStream method, test if toStream or toString has been overridden 00799 // this is relatively expensive and will be removed in a future release when toStream is removed 00800 std::stringstream ss; 00801 o.toStream(ss); // no-op on Object 00802 if (ss.tellp() <= 0) // common case - on empty stream STLport returns -1; others return 0 00803 { 00804 // toStream has not been overridden, use toString 00805 String::View vs = o.toString(); // ensure String stays alive while working with the c string 00806 if (vs->isCString()) // NUL terminated ASCII 00807 { 00808 out << vs->getCString(); 00809 } 00810 else if (vs->isASCII()) // ASCII with embedded NULs 00811 { 00812 const char* pch = vs->getCString(); 00813 for (size32_t i = 0, c = vs->length(); i < c; ++i) 00814 { 00815 out << pch[i]; 00816 } 00817 } 00818 else // unicode, "inherit" however std::string outputs embedded unicode to an ostream 00819 { 00820 std::string s = vs; 00821 out << s; 00822 } 00823 } 00824 else // toStream wrote output (was overridden) 00825 { 00826 out << ss.str(); 00827 } 00828 return out; 00829 } 00830 00831 /** 00832 * Output a human-readable description of the specified Object to the given 00833 * stream. 00834 * 00835 * @param out the stream used to output the description 00836 * @param o the Object to describe 00837 * 00838 * @return the supplied stream 00839 */ 00840 COH_INLINE std::wostream& operator<<(std::wostream& out, const Object& o) 00841 { 00842 String::View vs = o.toString(); // ensure String stays alive while working with the c string 00843 const char* pch = vs->getCString(); 00844 if (vs->isCString()) // NUL terminated ASCII 00845 { 00846 out << pch; 00847 } 00848 else if (vs->isASCII()) // ASCII with embedded NULs 00849 { 00850 for (size32_t i = 0, c = vs->length(); i < c; ++i) 00851 { 00852 out << pch[i]; 00853 } 00854 } 00855 else // unicode, decode to wchars 00856 { 00857 for (size32_t i = 0, c = vs->length(); i < c; ++i) 00858 { 00859 out << wchar_t(String::next(pch)); 00860 } 00861 } 00862 return out; 00863 } 00864 00865 // ----- helper macros ------------------------------------------------------ 00866 00867 /** 00868 * This macro will take any set of wstreamable contents and turn them into a 00869 * coherence#lang#String instance. 00870 * 00871 * @param CONTENTS the contents to use in constructing the String. 00872 * 00873 * Usage example: 00874 * @code 00875 * String::Handle hsFoo = COH_TO_WIDE_STRING("This value: " << 5 << " is my value"); 00876 * @endcode 00877 */ 00878 #define COH_TO_WIDE_STRING(CONTENTS) \ 00879 coherence::lang::String::create(((std::wstringstream&) \ 00880 (*(COH_AUTO_PTR<std::wstringstream>(new std::wstringstream())) \ 00881 << CONTENTS)).str()) 00882 00883 /** 00884 * This macro will take any set of streamable contents and turn them into a 00885 * coherence#lang#String instance. 00886 * 00887 * @param CONTENTS the contents to use in constructing the String. 00888 * 00889 * Usage example: 00890 * @code 00891 * String::Handle hsFoo = COH_TO_NARROW_STRING("This value: " << 5 << " is my value"); 00892 * @endcode 00893 */ 00894 #define COH_TO_NARROW_STRING(CONTENTS) \ 00895 coherence::lang::String::create(((std::stringstream&) \ 00896 (*(COH_AUTO_PTR<std::stringstream>(new std::stringstream())) \ 00897 << CONTENTS)).str()) 00898 00899 /** 00900 * Compile time option to select the default operator<< to use. If COH_DEFAULT_NARROW_TO_STRING 00901 * is defined then the COH_TO_STRING macro will only require operator<< to be defined 00902 * for std::ostream, alternatively if COH_DEFAULT_WIDE_TO_STRING is then operator<< must be 00903 * defined for std::wostream. The preferable choice is to implement them both via a single template 00904 * based implementation: 00905 * 00906 * template <typename Char, typename Traits> std::basic_ostream<Char, Traits>& 00907 * operator<<(std::basic_ostream<Char, Traits>& out, const your_class& v) 00908 * 00909 * Note all managed classes deriving from Object (including Managed) are already compatible 00910 * with both stream types, the above operators only need be defined for non-managed 00911 * classes. 00912 */ 00913 #if defined(COH_DEFAULT_NARROW_TO_STRING) 00914 #define COH_TO_STRING(CONTENTS) COH_TO_NARROW_STRING(CONTENTS) 00915 #elif defined(COH_DEFAULT_WIDE_TO_STRING) 00916 #define COH_TO_STRING(CONTENTS) COH_TO_WIDE_STRING(CONTENTS) 00917 #elif defined(COH_BUILD) // default coherence internals build to wide 00918 #define COH_TO_STRING(CONTENTS) COH_TO_WIDE_STRING(CONTENTS) 00919 #else // default users to narrow not all types (includeing std::string) are compatible with std::wostream 00920 #define COH_TO_STRING(CONTENTS) COH_TO_NARROW_STRING(CONTENTS) 00921 #endif 00922 00923 COH_CLOSE_NAMESPACE2 00924 00925 #endif // COH_STRING_HPP