C++ Client API Reference for Oracle Coherence
14c (14.1.2.0.0)

F79659-03

coherence/lang/String.hpp

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