Skip to content
Snippets Groups Projects
QName.cpp 12.4 KiB
Newer Older
PeiYong Zhang's avatar
PeiYong Zhang committed
/*
 * 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.
PeiYong Zhang's avatar
PeiYong Zhang committed
 */

/*
PeiYong Zhang's avatar
PeiYong Zhang committed
 */

#include <xercesc/util/Janitor.hpp>
PeiYong Zhang's avatar
PeiYong Zhang committed
#include <xercesc/util/QName.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
PeiYong Zhang's avatar
PeiYong Zhang committed

Tinny Ng's avatar
Tinny Ng committed
XERCES_CPP_NAMESPACE_BEGIN

PeiYong Zhang's avatar
PeiYong Zhang committed
// ---------------------------------------------------------------------------
//  QName: Constructors and Destructor
// ---------------------------------------------------------------------------
PeiYong Zhang's avatar
PeiYong Zhang committed
QName::QName(MemoryManager* const manager)
:fPrefixBufSz(0)
,fLocalPartBufSz(0)
,fRawNameBufSz(0)
,fURIId(0)
,fPrefix(0)
,fLocalPart(0)
Alberto Massari's avatar
Alberto Massari committed
,fRawName(0)
PeiYong Zhang's avatar
PeiYong Zhang committed
,fMemoryManager(manager)
typedef JanitorMemFunCall<QName>    CleanupType;

QName::QName( const XMLCh* const   prefix
            , const XMLCh* const   localPart
            , const unsigned int   uriId
PeiYong Zhang's avatar
PeiYong Zhang committed
            , MemoryManager* const manager)
:fPrefixBufSz(0)
,fLocalPartBufSz(0)
,fRawNameBufSz(0)
,fURIId(0)
,fPrefix(0)
,fLocalPart(0)
Alberto Massari's avatar
Alberto Massari committed
,fRawName(0)
PeiYong Zhang's avatar
PeiYong Zhang committed
,fMemoryManager(manager)
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    CleanupType cleanup(this, &QName::cleanUp);

PeiYong Zhang's avatar
PeiYong Zhang committed
    try
    {
        //
        //  Just call the local setters to set up everything. Too much
        //  work is required to replicate that functionality here.
        //
        setName(prefix, localPart, uriId);
    }
        cleanup.release();


    cleanup.release();
PeiYong Zhang's avatar
PeiYong Zhang committed
}

QName::QName( const XMLCh* const rawName
            , const unsigned int uriId
PeiYong Zhang's avatar
PeiYong Zhang committed
            , MemoryManager* const manager)
:fPrefixBufSz(0)
,fLocalPartBufSz(0)
,fRawNameBufSz(0)
,fURIId(0)
,fPrefix(0)
,fLocalPart(0)
Alberto Massari's avatar
Alberto Massari committed
,fRawName(0)
PeiYong Zhang's avatar
PeiYong Zhang committed
,fMemoryManager(manager)
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    CleanupType cleanup(this, &QName::cleanUp);

PeiYong Zhang's avatar
PeiYong Zhang committed
    try
    {
        //
        //  Just call the local setters to set up everything. Too much
        //  work is required to replicate that functionality here.
        //
        setName(rawName, uriId);
    }
        cleanup.release();


    cleanup.release();
PeiYong Zhang's avatar
PeiYong Zhang committed
}

QName::~QName()
{
	cleanUp();
}

// ---------------------------------------------------------------------------
//  QName: Copy Constructors
// ---------------------------------------------------------------------------
PeiYong Zhang's avatar
PeiYong Zhang committed
QName::QName(const QName& qname)
Alberto Massari's avatar
Alberto Massari committed
:XSerializable(qname)
,XMemory(qname)
,fPrefixBufSz(0)
PeiYong Zhang's avatar
PeiYong Zhang committed
,fLocalPartBufSz(0)
,fRawNameBufSz(0)
,fURIId(0)
,fPrefix(0)
,fLocalPart(0)
Alberto Massari's avatar
Alberto Massari committed
,fRawName(0)
PeiYong Zhang's avatar
PeiYong Zhang committed
,fMemoryManager(qname.fMemoryManager)
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    unsigned int newLen;

    newLen = XMLString::stringLen(qname.getLocalPart());
PeiYong Zhang's avatar
PeiYong Zhang committed
    fLocalPartBufSz = newLen + 8;
    fLocalPart = (XMLCh*) fMemoryManager->allocate
    (
        (fLocalPartBufSz + 1) * sizeof(XMLCh)
    ); //new XMLCh[fLocalPartBufSz + 1];
    XMLString::moveChars(fLocalPart, qname.getLocalPart(), newLen + 1);
PeiYong Zhang's avatar
PeiYong Zhang committed

    newLen = XMLString::stringLen(qname.getPrefix());
PeiYong Zhang's avatar
PeiYong Zhang committed
    fPrefixBufSz = newLen + 8;
    fPrefix = (XMLCh*) fMemoryManager->allocate
    (
        (fPrefixBufSz + 1) * sizeof(XMLCh)
    ); //new XMLCh[fPrefixBufSz + 1];
    XMLString::moveChars(fPrefix, qname.getPrefix(), newLen + 1);
PeiYong Zhang's avatar
PeiYong Zhang committed

PeiYong Zhang's avatar
PeiYong Zhang committed
}

// ---------------------------------------------------------------------------
//  QName: Getter methods
// ---------------------------------------------------------------------------
const XMLCh* QName::getRawName() const
{
    //
    //  If there is no buffer, or if there is but we've not faulted in the
    //  value yet, then we have to do that now.
    //
    if (!fRawName || !*fRawName)
    {
        //
        //  If we have a prefix, then do the prefix:name version. Else, its
        //  just the name.
        //
        if (*fPrefix)
        {
            //
            //  Calculate the worst case size buffer we will need. We use the
            //  current high water marks of the prefix and name buffers, so it
            //  might be a little wasteful of memory but we don't have to do
            //  string len operations on the two strings.
            //
            const unsigned int neededLen = fPrefixBufSz + fLocalPartBufSz + 1;

            //
            //  If no buffer, or the current one is too small, then allocate one
            //  and get rid of any old one.
            //
            if (!fRawName || (neededLen > fRawNameBufSz))
            {
                fMemoryManager->deallocate(fRawName); //delete [] fRawName;
PeiYong Zhang's avatar
PeiYong Zhang committed

PeiYong Zhang's avatar
PeiYong Zhang committed
                // We have to cast off the const'ness to do this
                ((QName*)this)->fRawNameBufSz = neededLen;
                ((QName*)this)->fRawName = (XMLCh*) fMemoryManager->allocate
                (
                    (neededLen + 1) * sizeof(XMLCh)
                ); //new XMLCh[neededLen + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed

                // Make sure its initially empty
                *fRawName = 0;
            }

            const unsigned int prefixLen = XMLString::stringLen(fPrefix);

            XMLString::moveChars(fRawName, fPrefix, prefixLen);
            fRawName[prefixLen] = chColon;
            XMLString::copyString(&fRawName[prefixLen+1], fLocalPart);
        }
         else
        {
            return fLocalPart;
        }
    }
    return fRawName;
}

XMLCh* QName::getRawName()
{
    //
    //  If there is no buffer, or if there is but we've not faulted in the
    //  value yet, then we have to do that now.
    //
    if (!fRawName || !*fRawName)
    {
        //
        //  If we have a prefix, then do the prefix:name version. Else, its
        //  just the name.
        //
        if (*fPrefix)
        {
            //
            //  Calculate the worst case size buffer we will need. We use the
            //  current high water marks of the prefix and name buffers, so it
            //  might be a little wasteful of memory but we don't have to do
            //  string len operations on the two strings.
            //
            const unsigned int neededLen = fPrefixBufSz + fLocalPartBufSz + 1;

            //
            //  If no buffer, or the current one is too small, then allocate one
            //  and get rid of any old one.
            //
            if (!fRawName || (neededLen > fRawNameBufSz))
            {
                fMemoryManager->deallocate(fRawName); //delete [] fRawName;
PeiYong Zhang's avatar
PeiYong Zhang committed
                // We have to cast off the const'ness to do this
                ((QName*)this)->fRawNameBufSz = neededLen;
                ((QName*)this)->fRawName = (XMLCh*) fMemoryManager->allocate
                (
                    (neededLen + 1) * sizeof(XMLCh)
                ); //new XMLCh[neededLen + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed

                // Make sure its initially empty
                *fRawName = 0;
            }


            const unsigned int prefixLen = XMLString::stringLen(fPrefix);

            XMLString::moveChars(fRawName, fPrefix, prefixLen);
            fRawName[prefixLen] = chColon;
            XMLString::copyString(&fRawName[prefixLen+1], fLocalPart);
        }
         else
        {
            return fLocalPart;
        }
    }
    return fRawName;
}

// ---------------------------------------------------------------------------
//  QName: Setter methods
// ---------------------------------------------------------------------------
void QName::setName(const XMLCh* const    prefix
                  , const XMLCh* const    localPart
                  , const unsigned int    uriId)
{
    setPrefix(prefix);
    setLocalPart(localPart);

    // And clean up any QName and leave it undone until/if asked for again
    if (fRawName)
        *fRawName = 0;

    // And finally store the URI id parameter
    fURIId = uriId;
}

void QName::setName(const XMLCh* const    rawName
                  , const unsigned int    uriId)
{
    //set the rawName
Khaled Noaman's avatar
Khaled Noaman committed
    unsigned int newLen = XMLString::stringLen(rawName);
PeiYong Zhang's avatar
PeiYong Zhang committed
    //find out the prefix and localPart from the rawName
    const int colonInd = XMLString::indexOf(rawName, chColon);
PeiYong Zhang's avatar
PeiYong Zhang committed
    if (colonInd >= 0)
    {
Khaled Noaman's avatar
Khaled Noaman committed
        if (!fRawNameBufSz || (newLen > fRawNameBufSz))
        {
            fMemoryManager->deallocate(fRawName); //delete [] fRawName;
Khaled Noaman's avatar
Khaled Noaman committed
            fRawNameBufSz = newLen + 8;
            fRawName = (XMLCh*) fMemoryManager->allocate
            (
                (fRawNameBufSz + 1) * sizeof(XMLCh)
            ); //new XMLCh[fRawNameBufSz + 1];
        }
        XMLString::moveChars(fRawName, rawName, newLen + 1);
PeiYong Zhang's avatar
PeiYong Zhang committed
        setNPrefix(rawName, colonInd);
    }
Khaled Noaman's avatar
Khaled Noaman committed
    else
PeiYong Zhang's avatar
PeiYong Zhang committed
    {
        // No colon, so we just have a name with no prefix
        setPrefix(XMLUni::fgZeroLenString);
Khaled Noaman's avatar
Khaled Noaman committed

        // And clean up any QName and leave it undone until/if asked for again
        if (fRawName)
            *fRawName = 0;
PeiYong Zhang's avatar
PeiYong Zhang committed
    }

    setNLocalPart(&rawName[colonInd+1], newLen-colonInd-1);

    // And finally store the URI id parameter
    fURIId = uriId;
}

void QName::setPrefix(const XMLCh* prefix)
{
Alberto Massari's avatar
Alberto Massari committed
    setNPrefix(prefix, XMLString::stringLen(prefix));
PeiYong Zhang's avatar
PeiYong Zhang committed
}

void QName::setNPrefix(const XMLCh* prefix, const unsigned int newLen)
{
    if (!fPrefixBufSz || (newLen > fPrefixBufSz))
    {
        fMemoryManager->deallocate(fPrefix); //delete [] fPrefix;
PeiYong Zhang's avatar
PeiYong Zhang committed
        fPrefixBufSz = newLen + 8;
        fPrefix = (XMLCh*) fMemoryManager->allocate
        (
            (fPrefixBufSz + 1) * sizeof(XMLCh)
        ); //new XMLCh[fPrefixBufSz + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed
    }
    XMLString::moveChars(fPrefix, prefix, newLen);
    fPrefix[newLen] = chNull;
}

void QName::setLocalPart(const XMLCh* localPart)
{
Alberto Massari's avatar
Alberto Massari committed
    setNLocalPart(localPart, XMLString::stringLen(localPart));
PeiYong Zhang's avatar
PeiYong Zhang committed
}

void QName::setNLocalPart(const XMLCh* localPart, const unsigned int newLen)
{
    if (!fLocalPartBufSz || (newLen > fLocalPartBufSz))
    {
        fMemoryManager->deallocate(fLocalPart); //delete [] fLocalPart;
PeiYong Zhang's avatar
PeiYong Zhang committed
        fLocalPartBufSz = newLen + 8;
        fLocalPart = (XMLCh*) fMemoryManager->allocate
        (
            (fLocalPartBufSz + 1) * sizeof(XMLCh)
        ); //new XMLCh[fLocalPartBufSz + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed
    }
    XMLString::moveChars(fLocalPart, localPart, newLen);
    fLocalPart[newLen] = chNull;
}

void QName::setValues(const QName& qname)
{
    setPrefix(qname.getPrefix());
    setLocalPart(qname.getLocalPart());
    setURI(qname.getURI());
}

// -----------------------------------------------------------------------
//  comparison
// -----------------------------------------------------------------------
bool QName::operator==(const QName& qname) const
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    if (fURIId == 0) // null URI
        return (XMLString::equals(getRawName(),qname.getRawName()));

    return ((fURIId == qname.getURI()) &&
           (XMLString::equals(fLocalPart, qname.getLocalPart())));
PeiYong Zhang's avatar
PeiYong Zhang committed
}

// ---------------------------------------------------------------------------
//  QName: Private, helper methods
// ---------------------------------------------------------------------------
void QName::cleanUp()
{
    fMemoryManager->deallocate(fLocalPart); //delete [] fLocalPart;
    fMemoryManager->deallocate(fPrefix); //delete [] fPrefix;
    fMemoryManager->deallocate(fRawName); //delete [] fRawName;
    fLocalPart = fPrefix = fRawName = 0;
PeiYong Zhang's avatar
PeiYong Zhang committed
}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_TOCREATE(QName)

void QName::serialize(XSerializeEngine& serEng)
{

    if (serEng.isStoring())
    {
        serEng.writeString(fPrefix, fPrefixBufSz, XSerializeEngine::toWriteBufferLen);
        serEng.writeString(fLocalPart, fLocalPartBufSz, XSerializeEngine::toWriteBufferLen);

        //do not serialize rawName

        serEng<<fURIId;
    }
    else
    {
        int dataLen = 0;
        serEng.readString(fPrefix, (int&)fPrefixBufSz, dataLen, XSerializeEngine::toReadBufferLen);
        serEng.readString(fLocalPart, (int&)fLocalPartBufSz, dataLen, XSerializeEngine::toReadBufferLen);

        //force raw name rebuilt
        fRawNameBufSz = 0;        
        fRawName = 0;

        serEng>>fURIId;
    }

}

Tinny Ng's avatar
Tinny Ng committed
XERCES_CPP_NAMESPACE_END