/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if !defined(XALANDOMSTRING_HEADER_GUARD_1357924680) #define XALANDOMSTRING_HEADER_GUARD_1357924680 #include #include #include #include #include #include namespace XALAN_CPP_NAMESPACE { class XALAN_DOM_EXPORT XalanDOMString { public: typedef XalanVector XalanDOMCharVectorType; typedef XalanVector CharVectorType; typedef XalanVector WideCharVectorType; typedef XalanDOMChar value_type; typedef XalanDOMChar& reference; typedef const XalanDOMChar& const_reference; typedef XalanSize_t size_type; typedef XalanDOMCharVectorType::iterator iterator; typedef XalanDOMCharVectorType::const_iterator const_iterator; typedef XalanDOMCharVectorType::reverse_iterator reverse_iterator; typedef XalanDOMCharVectorType::const_reverse_iterator const_reverse_iterator; static const size_type npos; XalanDOMString(MemoryManager& theManager XALAN_DEFAULT_CONSTRUCTOR_MEMMGR); explicit XalanDOMString( const char* theString, MemoryManager& theManager XALAN_DEFAULT_MEMMGR, size_type theCount = size_type(npos)); XalanDOMString( const XalanDOMString& theSource, MemoryManager& theManager XALAN_DEFAULT_CONSTRUCTOR_MEMMGR, size_type theStartPosition = 0, size_type theCount = size_type(npos)); explicit XalanDOMString( const XalanDOMChar* theString, MemoryManager& theManager XALAN_DEFAULT_MEMMGR, size_type theCount = size_type(npos)); XalanDOMString( size_type theCount, XalanDOMChar theChar, MemoryManager& theManager XALAN_DEFAULT_MEMMGR); XalanDOMString* clone(MemoryManager& theManager); ~XalanDOMString() { } XalanDOMString& operator=(const XalanDOMString& theRHS) { return assign(theRHS); } XalanDOMString& operator=(const XalanDOMChar* theRHS) { return assign(theRHS); } XalanDOMString& operator=(const char* theRHS) { return assign(theRHS); } XalanDOMString& operator=(XalanDOMChar theRHS) { return assign(1, theRHS); } iterator begin() { invariants(); return m_data.begin(); } const_iterator begin() const { invariants(); return m_data.begin(); } iterator end() { invariants(); return m_data.empty() == true ? m_data.end() : m_data.end() - 1; } const_iterator end() const { invariants(); return m_data.empty() == true ? m_data.end() : m_data.end() - 1; } reverse_iterator rbegin() { invariants(); reverse_iterator i = m_data.rbegin(); if (m_data.empty() == false) { ++i; } return i; } const_reverse_iterator rbegin() const { invariants(); const_reverse_iterator i = m_data.rbegin(); if (m_data.empty() == false) { ++i; } return i; } reverse_iterator rend() { invariants(); return m_data.rend(); } const_reverse_iterator rend() const { invariants(); return m_data.rend(); } size_type size() const { invariants(); return m_size; } size_type length() const { invariants(); return size(); } size_type max_size() const { invariants(); return ~size_type(0); } void resize( size_type theCount, XalanDOMChar theChar); void resize(size_type theCount) { invariants(); resize(theCount, XalanDOMChar(0)); } size_type capacity() const { invariants(); const XalanDOMCharVectorType::size_type theCapacity = m_data.capacity(); return theCapacity == 0 ? 0 : size_type(theCapacity - 1); } void reserve(size_type theCount = 0) { invariants(); m_data.reserve(theCount + 1); } void clear() { invariants(); m_data.erase(m_data.begin(), m_data.end()); m_size = 0; invariants(); } iterator erase(iterator thePosition) { invariants(); m_data.erase(thePosition); --m_size; invariants(); return thePosition; } iterator erase( iterator theFirst, iterator theLast) { invariants(); m_data.erase(theFirst, theLast); m_size = m_data.size() - 1; invariants(); return theFirst; } XalanDOMString& erase( size_type theStartPosition = 0, size_type theCount = size_type(npos)); bool empty() const { invariants(); return m_size == 0 ? true : false; } const_reference operator[](size_type theIndex) const { invariants(); return m_data[theIndex]; } reference operator[](size_type theIndex) { invariants(); return m_data[theIndex]; } const_reference at(size_type theIndex) const { invariants(); return m_data.at(theIndex); } reference at(size_type theIndex) { invariants(); return m_data.at(theIndex); } const XalanDOMChar* c_str() const { invariants(); return m_data.empty() == true ? &s_empty : &m_data[0]; } const XalanDOMChar* data() const { invariants(); return c_str(); } void swap(XalanDOMString& theOther) { invariants(); m_data.swap(theOther.m_data); std::swap(m_size, theOther.m_size); } XalanDOMString& operator+=(const XalanDOMString& theSource) { return append(theSource); } XalanDOMString& operator+=(const XalanDOMChar* theString) { return append(theString); } XalanDOMString& operator+=(XalanDOMChar theChar) { append(1, theChar); return *this; } XalanDOMString& assign(const XalanDOMChar* theSource) { invariants(); erase(); invariants(); return append(theSource); } XalanDOMString& assign( const XalanDOMChar* theSource, size_type theCount) { invariants(); erase(); invariants(); return append(theSource, theCount); } XalanDOMString& assign(const char* theSource) { invariants(); erase(); invariants(); return append(theSource); } XalanDOMString& assign( const char* theSource, size_type theCount) { invariants(); erase(); invariants(); return append(theSource, theCount); } XalanDOMString& assign( const XalanDOMString& theSource, size_type thePosition, size_type theCount); XalanDOMString& assign(const XalanDOMString& theSource) { invariants(); if (&theSource != this) { m_data = theSource.m_data; m_size = theSource.m_size; } invariants(); return *this; } XalanDOMString& assign( size_type theCount, XalanDOMChar theChar) { invariants(); erase(); invariants(); return append(theCount, theChar); } XalanDOMString& assign( iterator theFirstPosition, iterator theLastPosition); XalanDOMString& append(const XalanDOMString& theSource) { return append(theSource.c_str(), theSource.length()); } XalanDOMString& append( const XalanDOMString& theSource, size_type thePosition, size_type theCount) { assert(thePosition < theSource.length() && (theCount == size_type(npos) || thePosition + theCount <= theSource.length())); return append(theSource.c_str() + thePosition, theCount); } XalanDOMString& append( const XalanDOMChar* theString, size_type theCount); XalanDOMString& append(const XalanDOMChar* theString) { return append(theString, length(theString)); } XalanDOMString& append( const char* theString, size_type theCount); XalanDOMString& append(const char* theString) { return append(theString, length(theString)); } XalanDOMString& append( size_type theCount, XalanDOMChar theChar); void push_back(XalanDOMChar theChar) { invariants(); append(1, theChar); invariants(); } XalanDOMString& insert( size_type thePosition, const XalanDOMString& theString) { return insert(thePosition, theString.c_str(), theString.length()); } XalanDOMString& insert( size_type thePosition1, const XalanDOMString& theString, size_type thePosition2, size_type theCount) { return insert(thePosition1, theString.c_str() + thePosition2, theCount); } XalanDOMString& insert( size_type thePosition, const XalanDOMChar* theString, size_type theCount); XalanDOMString& insert( size_type thePosition, const XalanDOMChar* theString) { return insert(thePosition, theString, length(theString)); } XalanDOMString& insert( size_type thePosition, size_type theCount, XalanDOMChar theChar); iterator insert( iterator thePosition, XalanDOMChar theChar); void insert( iterator thePosition, size_type theCount, XalanDOMChar theChar); void insert( iterator theInsertPosition, iterator theFirstPosition, iterator theLastPosition); XalanDOMString& substr( XalanDOMString& theSubstring, size_type thePosition = 0, size_type theCount = size_type(npos)) const { assert((theCount == size_type(npos) && thePosition < length() ) || (thePosition + theCount <= length())); invariants(); return theSubstring.assign( *this, thePosition, theCount == npos ? length() : theCount); } int compare(const XalanDOMString& theString) const { invariants(); return compare(theString.c_str()); } int compare( size_type thePosition1, size_type theCount1, const XalanDOMString& theString) const { invariants(); return compare(thePosition1, theCount1, theString.c_str(), theString.length()); } int compare( size_type thePosition1, size_type theCount1, const XalanDOMString& theString, size_type thePosition2, size_type theCount2) const { invariants(); return compare(thePosition1, theCount1, theString.c_str() + thePosition2, theCount2); } int compare(const XalanDOMChar* theString) const; int compare( size_type thePosition1, size_type theCount1, const XalanDOMChar* theString, size_type theCount2 = size_type(npos)) const; void reset(MemoryManager& theManager, const char* theString); void reset(MemoryManager& theManager, const XalanDOMChar* theString); class TranscodingError : public XalanDOMException { public: TranscodingError() : XalanDOMException(TRANSCODING_ERR) { } virtual ~TranscodingError() { } }; /** * Transcode the string to the local code page. If the string * cannot be properly transcoded, and the transcoder can detect * the error a TranscodingError exception is thrown. * * @param theResult A CharVectorType instance for the transcoded string. The string is null-terminated. */ void transcode(CharVectorType& theResult) const; MemoryManager& getMemoryManager() { return m_data.getMemoryManager(); } size_t hash() const { return hash(c_str(), length()); } static size_t hash( const XalanDOMChar* theString, size_type theLength) { assert(theString != 0); return hash_non_terminated_array()(theString, theLength); } static bool equals( const XalanDOMChar* theLHS, size_type theLHSLength, const XalanDOMChar* theRHS, size_type theRHSLength); static bool equals( const XalanDOMChar* theLHS, const XalanDOMChar* theRHS) { return equals(theLHS, length(theLHS), theRHS, length(theRHS)); } static bool equals( const XalanDOMString& theLHS, const XalanDOMString& theRHS); static bool equals( const XalanDOMString& theLHS, const XalanDOMChar* theRHS) { return equals(theLHS.c_str(), theRHS); } static bool equals( const XalanDOMChar* theLHS, const XalanDOMString& theRHS) { return equals(theLHS, theRHS.c_str()); } /* * Helper function to determine the length of a null- * terminated string. * * @theString The string * @return the length */ static size_type length(const XalanDOMChar* theString); /* * Helper function to determine the length of a null- * terminated string. * * @theString The string * @return the length */ static size_type length(const char* theString); protected: /* * Function to assert invariant conditions for the class. * * @return the iterator */ void invariants() const { #if !defined(NDEBUG) assert((m_data.empty() == true && m_size == 0) || m_size == m_data.size() - 1); assert(m_data.empty() == true || m_data.back() == 0); #endif } /* * Get an iterator to the position of the terminating null. * * @return the iterator */ iterator getBackInsertIterator() { invariants(); return m_data.empty() == true ? m_data.end() : m_data.end() - 1; } const_iterator getBackInsertIterator() const { invariants(); return m_data.empty() == true ? m_data.end() : m_data.end() - 1; } iterator getIteratorForPosition(size_type thePosition) { invariants(); return m_data.begin() + thePosition; } const_iterator getIteratorForPosition(size_type thePosition) const { invariants(); return m_data.begin() + thePosition; } #if defined (XALAN_DEVELOPMENT) // not defined XalanDOMString(); XalanDOMString(const XalanDOMString&); #endif private: XalanDOMCharVectorType m_data; size_type m_size; static const XalanDOMChar s_empty; }; /** * Hash functor for DOMStrings * * @param theKey XalanDOMString to be hashed * @return hash value for XalanDOMString */ struct DOMStringHashFunction { size_t operator() (const XalanDOMString& theKey) const { return theKey.hash(); } }; /** * Hash functor for DOMStrings * * @param theKey XalanDOMString to be hashed * @return hash value for XalanDOMString */ struct DOMStringPointerHashFunction { size_t operator() (const XalanDOMString* theKey) const { assert (theKey != 0); return theKey->hash(); } }; template<> struct XalanMapKeyTraits { typedef DOMStringPointerHashFunction Hasher; typedef pointer_equal Comparator; }; template<> struct XalanMapKeyTraits { typedef DOMStringPointerHashFunction Hasher; typedef pointer_equal Comparator; }; /** * Equals functor for DOMStrings * * @param theLHS first string to compare * @param theRHS second string to compare * @return true if the contents of both strings are identical */ struct DOMStringEqualsFunction { bool operator() (const XalanDOMString& theLHS, const XalanDOMString& theRHS) const { return XalanDOMString::equals(theLHS, theRHS); } }; /** * Not equals functor for DOMStrings * * @param theLHS first string to compare * @param theRHS second string to compare * @return true if the contents of both strings are identical */ struct DOMStringNotEqualsFunction { bool operator() (const XalanDOMString& theLHS, const XalanDOMString& theRHS) const { return !XalanDOMString::equals(theLHS, theRHS); } }; /** * Less than functor for DOMStrings * * @param theLHS first string to compare * @param theRHS second string to compare * @return true if the theLHS is less than theRHSl */ struct DOMStringLessThanFunction { bool operator() (const XalanDOMString& theLHS, const XalanDOMString& theRHS) const { return theLHS.compare(theRHS) < 0 ? true : false; } }; /** * Equal to functor for DOMStrings * * @param theLHS first string to compare * @param theRHS second string to compare * @return true if the theLHS is equal to theRHS */ struct DOMStringPointerEqualToFunction { bool operator() (const XalanDOMString* theLHS, const XalanDOMString* theRHS) const { assert(theLHS != 0 && theRHS != 0); return XalanDOMString::equals(*theLHS, *theRHS); } }; /** * Less than functor for DOMStrings * * @param theLHS first string to compare * @param theRHS second string to compare * @return true if the theLHS is less than theRHSl */ struct DOMStringPointerLessThanFunction { bool operator() (const XalanDOMString* theLHS, const XalanDOMString* theRHS) const { assert(theLHS != 0 && theRHS != 0); return theLHS->compare(*theRHS) < 0 ? true : false; } }; template<> struct XalanMapKeyTraits { typedef DOMStringHashFunction Hasher; typedef std::equal_to Comparator; }; inline bool operator==( const XalanDOMString& theLHS, const XalanDOMString& theRHS) { return XalanDOMString::equals(theLHS, theRHS); } inline bool operator==( const XalanDOMString& theLHS, const XalanDOMChar* theRHS) { return XalanDOMString::equals(theLHS, theRHS); } inline bool operator==( const XalanDOMChar* theLHS, const XalanDOMString& theRHS) { // Note reversing of operands... return XalanDOMString::equals(theLHS, theRHS); } inline bool operator!=( const XalanDOMString& theLHS, const XalanDOMString& theRHS) { return !(theLHS == theRHS); } inline bool operator!=( const XalanDOMChar* theLHS, const XalanDOMString& theRHS) { return !(theLHS == theRHS); } inline bool operator!=( const XalanDOMString& theLHS, const XalanDOMChar* theRHS) { return !(theRHS == theLHS); } #if 0 inline XalanDOMString& add( const XalanDOMString& theLHS, const XalanDOMString& theRHS, XalanDOMString& result) { result.assign(theLHS); return result += theRHS; } inline XalanDOMString& add( const XalanDOMString& theLHS, const XalanDOMChar* theRHS, XalanDOMString& result) { result.assign(theLHS); return result += theRHS; } inline XalanDOMString& add( const XalanDOMChar* theLHS, const XalanDOMString& theRHS, XalanDOMString& result) { result.assign(theLHS); return result += theRHS; } inline const XalanDOMString& add( const char* theLHS, const XalanDOMString& theRHS, XalanDOMString& result) { result.assign(theLHS); result.append(theRHS); return result; } inline const XalanDOMString& add( const XalanDOMString& theLHS, const char* theRHS, XalanDOMString& result) { result.assign(theLHS); result.append(theRHS); return result; } #endif // Standard vector of XalanDOMChars and chars typedef XalanVector XalanDOMCharVectorType; typedef XalanVector CharVectorType; /** * Convert a XalanDOMChar string to C++ standard library * vector, transcoding to the default local code * page. * * @param sourceString The source string * @param sourceStringLength The source string length. * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @return true if successful, false if not. */ XALAN_DOM_EXPORT_FUNCTION(bool) TranscodeToLocalCodePage( const XalanDOMChar* theSourceString, XalanDOMString::size_type theSourceStringLength, CharVectorType& targetVector, bool terminate = false); /** * Convert a XalanDOMChar string to C++ standard library * vector, transcoding to the default local code * page. If the source string contines code points, that can't be * represented in the local code page, the substitution character will be used * * @param sourceString The source string * @param sourceStringLength The source string length. * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @param theSubstitutionChar The substitution character for code points that are not presentable * in the local page */ XALAN_DOM_EXPORT_FUNCTION(void) TranscodeToLocalCodePage( const XalanDOMChar* theSourceString, XalanDOMString::size_type theSourceStringLength, CharVectorType& targetVector, bool terminate, char theSubstitutionChar); /** * Convert a string to a XalanDOMString, transcoding from * the default local code page. * * @param theSourceString The source string * @param theSourceStringLength The source string length. * @return The new string. */ #if !defined(XALAN_DEVELOPMENT) inline const XalanDOMString TranscodeFromLocalCodePage( const char* theSourceString, XalanDOMString::size_type theSourceStringLength = XalanDOMString::npos) { return XalanDOMString(theSourceString,XalanMemMgrs::getDefaultXercesMemMgr(), theSourceStringLength); } #endif /** * Convert a XalanDOMChar string to C++ standard library * vector, transcoding to the default local code * page. The string _must_ be null-terminated. * * @param theSourceString The source string * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @return true if successful, false if not. */ XALAN_DOM_EXPORT_FUNCTION(bool) TranscodeToLocalCodePage( const XalanDOMChar* theSourceString, CharVectorType& targetVector, bool terminate = false); /** * Convert a XalanDOMChar string to C++ standard library * vector, transcoding to the default local code * page. The string _must_ be null-terminated. * * @param theSourceString The source string * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated */ XALAN_DOM_EXPORT_FUNCTION(void) TranscodeToLocalCodePage( const XalanDOMChar* theSourceString, CharVectorType& targetVector, bool terminate, char theSubstitutionChar); /** * Convert XalanDOMString to C++ standard library * vector, transcoding to the default local code * page. Null-terminate the sttring... * * @param theSourceString source string * @return The transcoded string. */ #if !defined(XALAN_DEVELOPMENT) inline const CharVectorType TranscodeToLocalCodePage(const XalanDOMChar* theSourceString) { CharVectorType theResult; TranscodeToLocalCodePage(theSourceString, theResult, true, '?'); return theResult; } #endif /** * Convert XalanDOMString to C++ standard library * vector, transcoding to the default local code * page. * * @param theSourceString The source string * @param theTargetVector The target string * @return true if successful, false if not. */ inline bool TranscodeToLocalCodePage( const XalanDOMString& theSourceString, CharVectorType& theTargetVector, bool terminate = false) { return TranscodeToLocalCodePage( theSourceString.c_str(), theTargetVector, terminate); } /** * Convert XalanDOMString to C++ standard library * vector, transcoding to the default local code * page. * * @param theSourceString The source string * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @param theSubstitutionChar The substitution character for code points that are not presentable * in the local page */ XALAN_DOM_EXPORT_FUNCTION(void) TranscodeToLocalCodePage( const XalanDOMString& theSourceString, CharVectorType& theTargetVector, bool terminate, char theSubstitutionChar); /** * Convert XalanDOMString to C++ standard library * vector, transcoding to the default local code * page. * * @param thetheSourceString source string * @return The transcoded string. */ #if !defined(XALAN_DEVELOPMENT) inline const CharVectorType TranscodeToLocalCodePage(const XalanDOMString& theSourceString) { CharVectorType theResult; TranscodeToLocalCodePage(theSourceString.c_str(), theResult, true, '?'); return theResult; } #endif /** * Convert a string to a XalanDOMString, transcoding from * the default local code page. * * @param theSourceString The source string * @param theResult The result. * @param theSourceStringLength The source string length. * @return The new string. */ inline const XalanDOMString& TranscodeFromLocalCodePage( const char* theSourceString, XalanDOMString& theResult, XalanDOMString::size_type theSourceStringLength = XalanDOMString::npos) { theResult.assign(theSourceString, theSourceStringLength); return theResult; } /** * Convert a string to a C++ standard library * vector, transcoding from the default local code * page. * * @param theSourceString The source string * @param theSourceStringLength The source string length. * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @return true if successful, false if not. */ XALAN_DOM_EXPORT_FUNCTION(bool) TranscodeFromLocalCodePage( const char* theSourceString, XalanDOMString::size_type theSourceStringLength, XalanDOMCharVectorType& theTargetVector, bool terminate = false); /** * Convert a string to a C++ standard library * vector, transcoding from the default local code * page. The string _must_ be null-terminated. * * @param sourceString The source string * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @return true if successful, false if not. */ XALAN_DOM_EXPORT_FUNCTION(bool) TranscodeFromLocalCodePage( const char* theSourceString, XalanDOMCharVectorType& theTargetVector, bool terminate = false); /** * Convert a string to a C++ standard library * vector, transcoding from the default local code * page. * * @param theSourceString The source string * @param theSourceStringLength The source string length. * @param theSourceStringIsNullTerminated true if the source string is null-terminated, otherwise false. * @param targetVector The target string * @param terminate If true, the transcoded string will be null-terminated * @return true if successful, false if not. */ XALAN_DOM_EXPORT_FUNCTION(bool) TranscodeFromLocalCodePage( const char* theSourceString, XalanDOMString::size_type theSourceStringLength, bool theSourceStringIsNullTerminated, XalanDOMCharVectorType& theTargetVector, bool terminate = false); /** * Convert a vector of characters to a XalanDOMString, * transcoding from the default local code * * @param theSourceString The source vector. * @param theResult The result. * @return The transcoded string. */ XALAN_DOM_EXPORT_FUNCTION(const XalanDOMString&) TranscodeFromLocalCodePage( const CharVectorType& theSourceString, XalanDOMString& theResult); XALAN_USES_MEMORY_MANAGER(XalanDOMString) } #endif // !defined(XALANDOMSTRING_HEADER_GUARD_1357924680)