blob: b8636cc76be5ccd6f79ab02550a67112c516d092 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#if !defined(XALANDOMSTRING_HEADER_GUARD_1357924680)
#define XALANDOMSTRING_HEADER_GUARD_1357924680
#include <XalanDOM/XalanDOMDefinitions.hpp>
#include <vector>
#include <XalanDOM/XalanDOMException.hpp>
#if defined(XALAN_USE_NATIVE_WCHAR_T)
typedef wchar_t XalanDOMChar;
#else
// UTF-16 character...
typedef unsigned short XalanDOMChar;
#endif
#include <cassert>
class XALAN_DOM_EXPORT XalanDOMString
{
public:
#if defined(XALAN_NO_NAMESPACES)
typedef vector<XalanDOMChar> XalanDOMCharVectorType;
typedef vector<char> CharVectorType;
typedef vector<wchar_t> WideCharVectorType;
#else
typedef std::vector<XalanDOMChar> XalanDOMCharVectorType;
typedef std::vector<char> CharVectorType;
typedef std::vector<wchar_t> WideCharVectorType;
#endif
typedef XalanDOMChar value_type;
typedef XalanDOMChar& reference;
typedef const XalanDOMChar& const_reference;
typedef XalanDOMCharVectorType::size_type 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;
#if defined(XALAN_INLINE_INITIALIZATION)
static const size_type npos = ~0u;
#else
enum { npos = -1 };
#endif
explicit
XalanDOMString();
explicit
XalanDOMString(
const char* theString,
size_type theCount = size_type(npos));
XalanDOMString(
const XalanDOMString& theSource,
size_type theStartPosition = 0,
size_type theCount = size_type(npos));
explicit
XalanDOMString(
const XalanDOMChar* theString,
size_type theCount = size_type(npos));
XalanDOMString(
size_type theCount,
XalanDOMChar theChar);
~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.end();
}
const_iterator
end() const
{
invariants();
return m_data.end();
}
reverse_iterator
rbegin()
{
invariants();
return m_data.rbegin();
}
const_reverse_iterator
rbegin() const
{
invariants();
return m_data.rbegin();
}
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();
return m_data.capacity() - 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();
}
void
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];
}
#if 0
// $$$ ToDo: at() is not supported in the current version of GCC's vector<>
// implementation. Eventually, it should be.
const_reference
at(size_type theIndex) const
{
invariants();
return m_data.at(theIndex);
}
reference
at(size_type theIndex)
{
invariants();
return m_data.at(theIndex);
}
#endif
const XalanDOMChar*
c_str() const
{
invariants();
// $$$ ToDo: Do we really want to do this?
// for convenience, we will return a pointer to
// a default empty string so that c_str() never
// returns a null pointer...
return m_data.size() == 0 ? &s_empty : &m_data[0];
}
const XalanDOMChar*
data() const
{
invariants();
return c_str();
}
void
swap(XalanDOMString& theOther)
{
invariants();
m_data.swap(theOther.m_data);
#if defined(XALAN_NO_NAMESPACES)
::swap(m_size, theOther.m_size);
#else
std::swap(m_size, theOther.m_size);
#endif
}
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(
const_iterator theFirstPosition,
const_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,
const_iterator theFirstPosition,
const_iterator theLastPosition);
XalanDOMString
substr(
size_type thePosition = 0,
size_type theCount = size_type(npos)) const
{
assert(theCount == size_type(npos) && thePosition < length() ||
thePosition + theCount <= length());
invariants();
return XalanDOMString(*this, thePosition, theCount);
}
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);
}
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;
int
compare(const char* theString) const
{
invariants();
return compare(XalanDOMString(theString));
}
int
compare(
size_type thePosition1,
size_type theCount1,
const char* theString,
size_type theCount2 = size_type(npos)) const
{
invariants();
return compare(thePosition1, theCount1, XalanDOMString(theString, theCount2));
}
CharVectorType
transcode() const;
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);
class TranscodingError : public XalanDOMException
{
public:
TranscodingError() :
XalanDOMException(TRANSCODING_ERR)
{
}
virtual
~TranscodingError()
{
}
};
protected:
/*
* Function to assert invariant conditions for the class.
*
* @return the iterator
*/
void
invariants() const
{
#if !defined(NDEBUG)
assert((m_data.size() == 0 && m_size == 0) || m_size == m_data.size() - 1);
assert(m_data.size() == 0 || m_data.back() == 0);
#endif
}
/*
* Get an iterator to the position of the terminating null.
*
* @return the iterator
*/
iterator
getBackInsertIterator()
{
invariants();
return m_data.size() == 0 ? m_data.end() : m_data.end() - 1;
}
const_iterator
getBackInsertIterator() const
{
invariants();
return m_data.size() == 0 ? 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;
}
private:
XalanDOMCharVectorType m_data;
size_type m_size;
static const XalanDOMChar s_empty;
};
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);
}
inline XalanDOMString
operator+(
const XalanDOMString& theLHS,
const XalanDOMString& theRHS)
{
XalanDOMString theTemp(theLHS);
return theTemp += theRHS;
}
inline XalanDOMString
operator+(
const XalanDOMString& theLHS,
const XalanDOMChar* theRHS)
{
XalanDOMString theTemp(theLHS);
return theTemp += theRHS;
}
inline XalanDOMString
operator+(
const XalanDOMChar* theLHS,
const XalanDOMString& theRHS)
{
XalanDOMString theTemp(theLHS);
return theTemp += theRHS;
}
inline const XalanDOMString
operator+(
const char* theLHS,
const XalanDOMString& theRHS)
{
return XalanDOMString(theLHS) + theRHS;
}
inline const XalanDOMString
operator+(
const XalanDOMString& theLHS,
const char* theRHS)
{
return theLHS + XalanDOMString(theRHS);
}
// Standard vector of XalanDOMChars and chars
#if defined(XALAN_NO_NAMESPACES)
typedef vector<XalanDOMChar> XalanDOMCharVectorType;
typedef vector<char> CharVectorType;
#else
typedef std::vector<XalanDOMChar> XalanDOMCharVectorType;
typedef std::vector<char> CharVectorType;
#endif
/**
* 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. 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 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.
*/
inline const CharVectorType
TranscodeToLocalCodePage(const XalanDOMChar* theSourceString)
{
CharVectorType theResult;
TranscodeToLocalCodePage(theSourceString, theResult, true);
return theResult;
}
/**
* Convert XalanDOMString to C++ standard library
* vector, transcoding to the default local code
* page.
*
* @param theSourceString The source string
* @param targetVector The target string
* @return true if successful, false if not.
*/
inline bool
TranscodeToLocalCodePage(
const XalanDOMString& theSourceString,
CharVectorType& targetVector,
bool terminate = false)
{
return TranscodeToLocalCodePage(theSourceString.c_str(), targetVector, terminate);
}
/**
* Convert XalanDOMString to C++ standard library
* vector, transcoding to the default local code
* page.
*
* @param thetheSourceString source string
* @return The transcoded string.
*/
inline const CharVectorType
TranscodeToLocalCodePage(const XalanDOMString& theSourceString)
{
CharVectorType theResult;
TranscodeToLocalCodePage(theSourceString, theResult, true);
return theResult;
}
/**
* 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.
*/
inline const XalanDOMString
TranscodeFromLocalCodePage(
const char* theSourceString,
XalanDOMString::size_type theSourceStringLength = XalanDOMString::npos)
{
return XalanDOMString(theSourceString, theSourceStringLength);
}
/**
* 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 vector of characters to a XalanDOMString,
* transcoding from the default local code
*
* @param theSourceString source string
* @return The transcoded string.
*/
inline const XalanDOMString
TranscodeFromLocalCodePage(const CharVectorType& theSourceString)
{
typedef XalanDOMString::size_type size_type;
const CharVectorType::size_type theSize = theSourceString.size();
if (theSourceString[theSize - 1] == CharVectorType::value_type(0))
{
return TranscodeFromLocalCodePage(&*theSourceString.begin(), size_type(theSize) - 1);
}
else
{
return TranscodeFromLocalCodePage(&*theSourceString.begin(), size_type(theSize));
}
}
#endif // !defined(XALANDOMSTRING_HEADER_GUARD_1357924680)