<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-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 "Xerces" 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) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

#include "DOMNodeVector.hpp"
#include "DOMNamedNodeMapImpl.hpp"
#include "DOMCasts.hpp"
#include "DOMDocumentImpl.hpp"
#include "DOMNodeImpl.hpp"

XERCES_CPP_NAMESPACE_BEGIN

DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod)
{
    fOwnerNode=ownerNod;
    memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*));
}

DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl()
{
}

bool DOMNamedNodeMapImpl::readOnly()
{
    return castToNodeImpl(fOwnerNode)->isReadOnly();
}

DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod)
{
    DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument());
    DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod);

    for(int index=0;index<MAP_SIZE;index++)
        if (fBuckets[index] != 0) {
            XMLSize_t size=fBuckets[index]->size();
            newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size);
            for (XMLSize_t i = 0; i < size; ++i) {
                DOMNode *s = fBuckets[index]->elementAt(i);
                DOMNode *n = s->cloneNode(true);
			    castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified());
                castToNodeImpl(n)->fOwnerNode = ownerNod;
                castToNodeImpl(n)->isOwned(true);
                newmap->fBuckets[index]->addElement(n);
            }
        }

    return newmap;
}

XMLSize_t DOMNamedNodeMapImpl::getLength() const
{
    XMLSize_t count=0;
    for(int index=0;index<MAP_SIZE;index++)
        count+=(fBuckets[index]==0?0:fBuckets[index]->size());
    return count;
}

DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const
{
    XMLSize_t count=0;
    for(XMLSize_t i=0;i<MAP_SIZE;i++) {
        if(fBuckets[i]==0)
            continue;
        XMLSize_t thisBucket=fBuckets[i]->size();
        if(index>=count && index<(count+thisBucket))
            return fBuckets[i]->elementAt(index-count);
    }
    return NULL;
}

DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const
{
    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        return 0;

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName()))
            return n;
    }

    return 0;
}

//
// removeNamedItem() - Remove the named item, and return it.
//                      The caller can release the
//                      returned item if it's not used
//                      we can't do it here because the caller would
//                      never see the returned node.
//
DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name)
{
    if (this->readOnly())
        throw DOMException(
            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName())) {
            fBuckets[hash]->removeElementAt(i);
            castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
            castToNodeImpl(n)->isOwned(false);
            return n;
        }
    }

    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    return 0;
}

//
// setNamedItem()  Put the item into the NamedNodeList by name.
//                  If an item with the same name already was
//                  in the list, replace it.  Return the old
//                  item, if there was one.
//                  Caller is responsible for arranging for
//                  deletion of the old item if its ref count is
//                  zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg)
{
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
    if(argImpl->getOwnerDocument() != doc)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
    if (this->readOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);

    argImpl->fOwnerNode = fOwnerNode;
    argImpl->isOwned(true);

    const XMLCh* name=arg->getNodeName();
    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        fBuckets[hash] = new (doc) DOMNodeVector(doc, 3);

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName())) {
            fBuckets[hash]->setElementAt(arg,i);
            castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
            castToNodeImpl(n)->isOwned(false);
            return n;
        }
    }
    fBuckets[hash]->addElement(arg);
    return 0;
}

void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
{
    // this->fReadOnly=readOnl;
    if(deep) {
        for (int index = 0; index < MAP_SIZE; index++) {
            if(fBuckets[index]==0)
                continue;
            int sz = fBuckets[index]->size();
            for (int i=0; i<sz; ++i)
                castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep);
        }
    }
}

//Introduced in DOM Level 2

DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const
{
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName())))
                    return n;
            }
        }
    }
    return 0;
}

//
// setNamedItemNS()  Put the item into the NamedNodeList by name.
//                  If an item with the same name already was
//                  in the list, replace it.  Return the old
//                  item, if there was one.
//                  Caller is responsible for arranging for
//                  deletion of the old item if its ref count is
//                  zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg)
{
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
    if (argImpl->getOwnerDocument() != doc)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
    if (this->readOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    if (argImpl->isOwned())
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);

    argImpl->fOwnerNode = fOwnerNode;
    argImpl->isOwned(true);

    const XMLCh* namespaceURI=arg->getNamespaceURI();
    const XMLCh* localName=arg->getLocalName();
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
                    fBuckets[index]->setElementAt(arg,i);
                    castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
                    castToNodeImpl(n)->isOwned(false);
                    return n;
                }
            }
        }
    }
    // if not found, add it using the full name as key
    return setNamedItem(arg);
}

// removeNamedItemNS() - Remove the named item, and return it.
//                      The caller can release the
//                      returned item if it's not used
//                      we can't do it here because the caller would
//                      never see the returned node.
DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI,
                                                 const XMLCh *localName)
{
    if (this->readOnly())
        throw DOMException(
        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
                    fBuckets[index]->removeElementAt(i);
                    castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
                    castToNodeImpl(n)->isOwned(false);
                    return n;
                }
            }
        }
    }
    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    return 0;
}

XERCES_CPP_NAMESPACE_END

<commit_msg>item() was could only return items found in the first non-empty bucket (patch by Berin Lautenbach)<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-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 "Xerces" 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) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

#include "DOMNodeVector.hpp"
#include "DOMNamedNodeMapImpl.hpp"
#include "DOMCasts.hpp"
#include "DOMDocumentImpl.hpp"
#include "DOMNodeImpl.hpp"

XERCES_CPP_NAMESPACE_BEGIN

DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod)
{
    fOwnerNode=ownerNod;
    memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*));
}

DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl()
{
}

bool DOMNamedNodeMapImpl::readOnly()
{
    return castToNodeImpl(fOwnerNode)->isReadOnly();
}

DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod)
{
    DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument());
    DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod);

    for(int index=0;index<MAP_SIZE;index++)
        if (fBuckets[index] != 0) {
            XMLSize_t size=fBuckets[index]->size();
            newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size);
            for (XMLSize_t i = 0; i < size; ++i) {
                DOMNode *s = fBuckets[index]->elementAt(i);
                DOMNode *n = s->cloneNode(true);
			    castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified());
                castToNodeImpl(n)->fOwnerNode = ownerNod;
                castToNodeImpl(n)->isOwned(true);
                newmap->fBuckets[index]->addElement(n);
            }
        }

    return newmap;
}

XMLSize_t DOMNamedNodeMapImpl::getLength() const
{
    XMLSize_t count=0;
    for(int index=0;index<MAP_SIZE;index++)
        count+=(fBuckets[index]==0?0:fBuckets[index]->size());
    return count;
}

DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const
{
    XMLSize_t count=0;
    for(XMLSize_t i=0;i<MAP_SIZE;i++) {
        if(fBuckets[i]==0)
            continue;
        XMLSize_t thisBucket=fBuckets[i]->size();
        if(index>=count && index<(count+thisBucket))
            return fBuckets[i]->elementAt(index-count);
        count+=thisBucket;
    }
    return NULL;
}

DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const
{
    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        return 0;

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName()))
            return n;
    }

    return 0;
}

//
// removeNamedItem() - Remove the named item, and return it.
//                      The caller can release the
//                      returned item if it's not used
//                      we can't do it here because the caller would
//                      never see the returned node.
//
DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name)
{
    if (this->readOnly())
        throw DOMException(
            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName())) {
            fBuckets[hash]->removeElementAt(i);
            castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
            castToNodeImpl(n)->isOwned(false);
            return n;
        }
    }

    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    return 0;
}

//
// setNamedItem()  Put the item into the NamedNodeList by name.
//                  If an item with the same name already was
//                  in the list, replace it.  Return the old
//                  item, if there was one.
//                  Caller is responsible for arranging for
//                  deletion of the old item if its ref count is
//                  zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg)
{
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
    if(argImpl->getOwnerDocument() != doc)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
    if (this->readOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);

    argImpl->fOwnerNode = fOwnerNode;
    argImpl->isOwned(true);

    const XMLCh* name=arg->getNodeName();
    unsigned int hash=XMLString::hash(name,MAP_SIZE);
    if(fBuckets[hash]==0)
        fBuckets[hash] = new (doc) DOMNodeVector(doc, 3);

    int i = 0;
    int size = fBuckets[hash]->size();
    for (i = 0; i < size; ++i) {
        DOMNode *n=fBuckets[hash]->elementAt(i);
        if(XMLString::equals(name,n->getNodeName())) {
            fBuckets[hash]->setElementAt(arg,i);
            castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
            castToNodeImpl(n)->isOwned(false);
            return n;
        }
    }
    fBuckets[hash]->addElement(arg);
    return 0;
}

void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
{
    // this->fReadOnly=readOnl;
    if(deep) {
        for (int index = 0; index < MAP_SIZE; index++) {
            if(fBuckets[index]==0)
                continue;
            int sz = fBuckets[index]->size();
            for (int i=0; i<sz; ++i)
                castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep);
        }
    }
}

//Introduced in DOM Level 2

DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const
{
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName())))
                    return n;
            }
        }
    }
    return 0;
}

//
// setNamedItemNS()  Put the item into the NamedNodeList by name.
//                  If an item with the same name already was
//                  in the list, replace it.  Return the old
//                  item, if there was one.
//                  Caller is responsible for arranging for
//                  deletion of the old item if its ref count is
//                  zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg)
{
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
    if (argImpl->getOwnerDocument() != doc)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
    if (this->readOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    if (argImpl->isOwned())
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);

    argImpl->fOwnerNode = fOwnerNode;
    argImpl->isOwned(true);

    const XMLCh* namespaceURI=arg->getNamespaceURI();
    const XMLCh* localName=arg->getLocalName();
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
                    fBuckets[index]->setElementAt(arg,i);
                    castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
                    castToNodeImpl(n)->isOwned(false);
                    return n;
                }
            }
        }
    }
    // if not found, add it using the full name as key
    return setNamedItem(arg);
}

// removeNamedItemNS() - Remove the named item, and return it.
//                      The caller can release the
//                      returned item if it's not used
//                      we can't do it here because the caller would
//                      never see the returned node.
DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI,
                                                 const XMLCh *localName)
{
    if (this->readOnly())
        throw DOMException(
        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);

    // the map is indexed using the full name of nodes; to search given a namespace and a local name
    // we have to do a linear search
    for (int index = 0; index < MAP_SIZE; index++) {
        if(fBuckets[index]==0)
            continue;

        int i = 0;
        int size = fBuckets[index]->size();
        for (i = 0; i < size; ++i) {
            DOMNode *n=fBuckets[index]->elementAt(i);
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
            const XMLCh * nLocalName = n->getLocalName();
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
                continue;
            else {
                if (XMLString::equals(localName, nLocalName)
                    ||
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
                    fBuckets[index]->removeElementAt(i);
                    castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
                    castToNodeImpl(n)->isOwned(false);
                    return n;
                }
            }
        }
    }
    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
    return 0;
}

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>#ifndef STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#define STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char* matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix multiplication on the OpenCL device
     *
     * @param[in] A the left matrix in matrix multiplication
     * @param[in] B the right matrix in matrix multiplication
     * @param[out] C the output matrix
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix B
     * @param[in] K Number of cols for matrix A and number of rows for matrix B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void matrix_multiply(
        const __global double* A, const __global double* B, __global double* C,
        const int M, const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      // thread index inside the thread_block
      const int thread_block_row = get_local_id(0);
      const int thread_block_col = get_local_id(1);
      // global thread index
      const int i = THREAD_BLOCK_SIZE * get_group_id(0) + thread_block_row;
      const int j = THREAD_BLOCK_SIZE * get_group_id(1) + thread_block_col;

      // local memory
      __local double A_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];
      __local double B_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];

      double acc[WORK_PER_THREAD];
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        acc[w] = 0.0;
      }

      const int num_tiles = (K + THREAD_BLOCK_SIZE - 1) / THREAD_BLOCK_SIZE;

      // This kernel is based on the well known
      // general matrix multiplication kernels that
      // use tiling for shared memory
      // In cases where a matrix is lower triangular
      // its not necessary to multiply the elements
      // over the diagonal, therefore those tiles
      // in the matrix multiply can be skipped.
      // With upper triangular matrices we dont need
      // to multiply the elements under the diagonal,
      // so those tiles can be skipped.
      // The following code determines the start and
      // end tile based on triangularity of the input matrices
      // If no matrices are triangular the starting tile
      // is 0 and the end tile is num_tiles-1 which
      // is then a general matrix multiply
      const int end_tile_A
          = lower_upper_A == LOWER ? (i / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int end_tile_B
          = lower_upper_B == UPPER ? (j / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int start_tile_A
          = lower_upper_A == UPPER ? (i / THREAD_BLOCK_SIZE) : 0;
      const int start_tile_B
          = lower_upper_B == LOWER ? (j / THREAD_BLOCK_SIZE) : 0;
      const int start_tile = max(start_tile_A, start_tile_B);
      const int end_tile = min(end_tile_A, end_tile_B);  // NOLINT

      for (int tile_idx = start_tile; tile_idx <= end_tile; tile_idx++) {
        const int tiled_i = THREAD_BLOCK_SIZE * tile_idx + thread_block_row;
        const int tiled_j = THREAD_BLOCK_SIZE * tile_idx + thread_block_col;
        // each thread copies WORK_PER_THREAD values to the local
        // memory
        for (int w = 0; w < WORK_PER_THREAD; w++) {
          // For the tiles on the diagonal we can ignore the values over
          // the diagonal if the matrix is lower triangular or under
          // the diagonal if the matrix is upper triangular
          const A_curr_j = tiled_j + w * THREAD_BLOCK_SIZE_COL;
          const B_curr_j = j + w * THREAD_BLOCK_SIZE_COL;
          // check if the indexes are outside the matrix
          // or under/above the diagonal with upper/lower
          // triangular matrices
          if (A_curr_j >= K || i >= M
              || (lower_upper_A == LOWER && A_curr_j > i)
              || (lower_upper_A == UPPER && A_curr_j < i)) {
            A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = 0.0;
          } else {
            A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = A[A_curr_j * M + i];
          }
          if (B_curr_j >= N || tiled_i >= K
              || (lower_upper_B == LOWER && B_curr_j > tiled_i)
              || (lower_upper_B == UPPER && B_curr_j < tiled_i)) {
            B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = 0.0;
          } else {
            B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = B[B_curr_j * K + tiled_i];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        for (int block_idx = 0; block_idx < THREAD_BLOCK_SIZE; block_idx++) {
          for (int w = 0; w < WORK_PER_THREAD; w++) {
            acc[w] += A_local[block_idx][thread_block_row]
                      * B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                               [block_idx];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      // each thread saves WORK_PER_THREAD values
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        // This prevents threads from accessing elements
        // outside the allocated memory for C. The check
        // is in the loop because some threads
        // can be assigned elements in and out of
        // the allocated memory.
        if ((j + w * THREAD_BLOCK_SIZE_COL) < N && i < M) {
          C[(j + w * THREAD_BLOCK_SIZE_COL) * M + i] = acc[w];
        }
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int,
                         TriangularViewCL, TriangularViewCL>
    matrix_multiply("matrix_multiply", matrix_multiply_kernel_code,
                    {{"THREAD_BLOCK_SIZE", 32}, {"WORK_PER_THREAD", 8}});

// \cond
static const char* matrix_vector_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix-vector multiplication R=A*B on the OpenCL device
     *
     * @param[in] A matrix in matrix-vector multiplication
     * @param[in] B vector in matrix-vector multiplication
     * @param[out] R the output vector
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix A and number of rows for vector B
     */
    __kernel void matrix_vector_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int M, const int N, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      const int gid = get_global_id(0);

      int start = 0;
      int stop = N;
      if (lower_upper_A == UPPER) {
        start = gid;
      } else if (lower_upper_A == LOWER) {
        stop = gid + 1;
      }
      if (lower_upper_B == UPPER) {
        stop = 1;
      }

      double acc = 0;
      for (int i = start, j = M * start; i < stop; i++, j += M) {
        acc += A[j + gid] * B[i];
      }
      R[gid] = acc;
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_vector_multiply()
 * \endlink
 */
const global_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int,
                          TriangularViewCL, TriangularViewCL>
    matrix_vector_multiply("matrix_vector_multiply",
                           matrix_vector_multiply_kernel_code);

// \cond
static const char* row_vector_matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Row vector-matrix multiplication R=A*B on the OpenCL device
     *
     * @param[in] A row vector in row vector-matrix multiplication
     * @param[in] B matrix in row vector-matrix multiplication
     * @param[out] R the output vector
     * @param[in] N Number of cols for vector A and number of rows for matrix B
     * @param[in] K Number of cols for matrix B
     */
    __kernel void row_vector_matrix_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      const int lid = get_local_id(0);
      const int gid = get_global_id(0);
      const int wgid = get_group_id(0);

      int start = 0;
      int stop = N;
      if (lower_upper_B == UPPER) {
        stop = wgid + 1;
      } else if (lower_upper_B == LOWER) {
        start = wgid;
      }
      if (lower_upper_A == LOWER) {
        stop = 1;
      }

      double acc = 0;
      for (int i = lid + start; i < stop; i += LOCAL_SIZE_) {
        acc += A[i] * B[i + wgid * N];
      }

      __local double res_loc[LOCAL_SIZE_];
      res_loc[lid] = acc;
      barrier(CLK_LOCAL_MEM_FENCE);
      for (int step = LOCAL_SIZE_ / REDUCTION_STEP_SIZE; step > 0;
           step /= REDUCTION_STEP_SIZE) {
        if (lid < step) {
          for (int i = 1; i < REDUCTION_STEP_SIZE; i++) {
            res_loc[lid] += res_loc[lid + step * i];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      if (lid == 0) {
        R[wgid] = res_loc[0];
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp
 * row_vector_matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int,
                         TriangularViewCL, TriangularViewCL>
    row_vector_matrix_multiply("row_vector_matrix_multiply",
                               row_vector_matrix_multiply_kernel_code,
                               {{"LOCAL_SIZE_", 64},
                                {"REDUCTION_STEP_SIZE", 4}});

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<commit_msg>fixed doxygen<commit_after>#ifndef STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#define STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char* matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix multiplication on the OpenCL device
     *
     * @param[in] A the left matrix in matrix multiplication
     * @param[in] B the right matrix in matrix multiplication
     * @param[out] C the output matrix
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix B
     * @param[in] K Number of cols for matrix A and number of rows for matrix B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void matrix_multiply(
        const __global double* A, const __global double* B, __global double* C,
        const int M, const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      // thread index inside the thread_block
      const int thread_block_row = get_local_id(0);
      const int thread_block_col = get_local_id(1);
      // global thread index
      const int i = THREAD_BLOCK_SIZE * get_group_id(0) + thread_block_row;
      const int j = THREAD_BLOCK_SIZE * get_group_id(1) + thread_block_col;

      // local memory
      __local double A_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];
      __local double B_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];

      double acc[WORK_PER_THREAD];
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        acc[w] = 0.0;
      }

      const int num_tiles = (K + THREAD_BLOCK_SIZE - 1) / THREAD_BLOCK_SIZE;

      // This kernel is based on the well known
      // general matrix multiplication kernels that
      // use tiling for shared memory
      // In cases where a matrix is lower triangular
      // its not necessary to multiply the elements
      // over the diagonal, therefore those tiles
      // in the matrix multiply can be skipped.
      // With upper triangular matrices we dont need
      // to multiply the elements under the diagonal,
      // so those tiles can be skipped.
      // The following code determines the start and
      // end tile based on triangularity of the input matrices
      // If no matrices are triangular the starting tile
      // is 0 and the end tile is num_tiles-1 which
      // is then a general matrix multiply
      const int end_tile_A
          = lower_upper_A == LOWER ? (i / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int end_tile_B
          = lower_upper_B == UPPER ? (j / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int start_tile_A
          = lower_upper_A == UPPER ? (i / THREAD_BLOCK_SIZE) : 0;
      const int start_tile_B
          = lower_upper_B == LOWER ? (j / THREAD_BLOCK_SIZE) : 0;
      const int start_tile = max(start_tile_A, start_tile_B);
      const int end_tile = min(end_tile_A, end_tile_B);  // NOLINT

      for (int tile_idx = start_tile; tile_idx <= end_tile; tile_idx++) {
        const int tiled_i = THREAD_BLOCK_SIZE * tile_idx + thread_block_row;
        const int tiled_j = THREAD_BLOCK_SIZE * tile_idx + thread_block_col;
        // each thread copies WORK_PER_THREAD values to the local
        // memory
        for (int w = 0; w < WORK_PER_THREAD; w++) {
          // For the tiles on the diagonal we can ignore the values over
          // the diagonal if the matrix is lower triangular or under
          // the diagonal if the matrix is upper triangular
          const A_curr_j = tiled_j + w * THREAD_BLOCK_SIZE_COL;
          const B_curr_j = j + w * THREAD_BLOCK_SIZE_COL;
          // check if the indexes are outside the matrix
          // or under/above the diagonal with upper/lower
          // triangular matrices
          if (A_curr_j >= K || i >= M
              || (lower_upper_A == LOWER && A_curr_j > i)
              || (lower_upper_A == UPPER && A_curr_j < i)) {
            A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = 0.0;
          } else {
            A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = A[A_curr_j * M + i];
          }
          if (B_curr_j >= N || tiled_i >= K
              || (lower_upper_B == LOWER && B_curr_j > tiled_i)
              || (lower_upper_B == UPPER && B_curr_j < tiled_i)) {
            B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = 0.0;
          } else {
            B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                   [thread_block_row]
                = B[B_curr_j * K + tiled_i];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        for (int block_idx = 0; block_idx < THREAD_BLOCK_SIZE; block_idx++) {
          for (int w = 0; w < WORK_PER_THREAD; w++) {
            acc[w] += A_local[block_idx][thread_block_row]
                      * B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                               [block_idx];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      // each thread saves WORK_PER_THREAD values
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        // This prevents threads from accessing elements
        // outside the allocated memory for C. The check
        // is in the loop because some threads
        // can be assigned elements in and out of
        // the allocated memory.
        if ((j + w * THREAD_BLOCK_SIZE_COL) < N && i < M) {
          C[(j + w * THREAD_BLOCK_SIZE_COL) * M + i] = acc[w];
        }
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int,
                         TriangularViewCL, TriangularViewCL>
    matrix_multiply("matrix_multiply", matrix_multiply_kernel_code,
                    {{"THREAD_BLOCK_SIZE", 32}, {"WORK_PER_THREAD", 8}});

// \cond
static const char* matrix_vector_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix-vector multiplication R=A*B on the OpenCL device
     *
     * @param[in] A matrix in matrix-vector multiplication
     * @param[in] B vector in matrix-vector multiplication
     * @param[out] R the output vector
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix A and number of rows for vector B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void matrix_vector_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int M, const int N, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      const int gid = get_global_id(0);

      int start = 0;
      int stop = N;
      if (lower_upper_A == UPPER) {
        start = gid;
      } else if (lower_upper_A == LOWER) {
        stop = gid + 1;
      }
      if (lower_upper_B == UPPER) {
        stop = 1;
      }

      double acc = 0;
      for (int i = start, j = M * start; i < stop; i++, j += M) {
        acc += A[j + gid] * B[i];
      }
      R[gid] = acc;
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_vector_multiply()
 * \endlink
 */
const global_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int,
                          TriangularViewCL, TriangularViewCL>
    matrix_vector_multiply("matrix_vector_multiply",
                           matrix_vector_multiply_kernel_code);

// \cond
static const char* row_vector_matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Row vector-matrix multiplication R=A*B on the OpenCL device
     *
     * @param[in] A row vector in row vector-matrix multiplication
     * @param[in] B matrix in row vector-matrix multiplication
     * @param[out] R the output vector
     * @param[in] N Number of cols for vector A and number of rows for matrix B
     * @param[in] K Number of cols for matrix B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void row_vector_matrix_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      const int lid = get_local_id(0);
      const int gid = get_global_id(0);
      const int wgid = get_group_id(0);

      int start = 0;
      int stop = N;
      if (lower_upper_B == UPPER) {
        stop = wgid + 1;
      } else if (lower_upper_B == LOWER) {
        start = wgid;
      }
      if (lower_upper_A == LOWER) {
        stop = 1;
      }

      double acc = 0;
      for (int i = lid + start; i < stop; i += LOCAL_SIZE_) {
        acc += A[i] * B[i + wgid * N];
      }

      __local double res_loc[LOCAL_SIZE_];
      res_loc[lid] = acc;
      barrier(CLK_LOCAL_MEM_FENCE);
      for (int step = LOCAL_SIZE_ / REDUCTION_STEP_SIZE; step > 0;
           step /= REDUCTION_STEP_SIZE) {
        if (lid < step) {
          for (int i = 1; i < REDUCTION_STEP_SIZE; i++) {
            res_loc[lid] += res_loc[lid + step * i];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      if (lid == 0) {
        R[wgid] = res_loc[0];
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp
 * row_vector_matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int,
                         TriangularViewCL, TriangularViewCL>
    row_vector_matrix_multiply("row_vector_matrix_multiply",
                               row_vector_matrix_multiply_kernel_code,
                               {{"LOCAL_SIZE_", 64},
                                {"REDUCTION_STEP_SIZE", 4}});

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Interface/Modules/Render/ViewScene.h>
#include <Dataflow/Network/ModuleStateInterface.h>
#include <Core/Datatypes/Geometry.h>
#include <QFileDialog>
#include "QtGLContext.h"

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Datatypes;

//------------------------------------------------------------------------------
ViewSceneDialog::ViewSceneDialog(const std::string& name, ModuleStateHandle state,
  QWidget* parent /* = 0 */)
  : ModuleDialogGeneric(state, parent)
{
  setupUi(this);
  setWindowTitle(QString::fromStdString(name));

  // Setup Qt OpenGL widget.
  QGLFormat fmt;
  fmt.setAlpha(true);
  fmt.setRgba(true);
  mGLWidget = new GLWidget(new QtGLContext(fmt));

  if (mGLWidget->isValid())
  {
    // Hook up the GLWidget
    glLayout->addWidget(mGLWidget);
    glLayout->update();

    // Set spire transient value (should no longer be used).
    mSpire = std::weak_ptr<Spire::SCIRun::SRInterface>(mGLWidget->getSpire());
  }
  else
  {
    /// \todo Display dialog.
    delete mGLWidget;
  }
}

//------------------------------------------------------------------------------
ViewSceneDialog::~ViewSceneDialog()
{
}

//------------------------------------------------------------------------------
void ViewSceneDialog::closeEvent(QCloseEvent *evt)
{
}

//------------------------------------------------------------------------------
void ViewSceneDialog::moduleExecuted()
{
  // Grab the geomData transient value.
  boost::any geomDataTransient = state_->getTransientValue("geomData");
  if (!geomDataTransient.empty())
  {
    boost::shared_ptr<std::list<boost::shared_ptr<Core::Datatypes::GeometryObject>>> geomData; // Whoa...
    try
    {
      geomData = boost::any_cast<boost::shared_ptr<std::list<boost::shared_ptr<Core::Datatypes::GeometryObject>>>>(geomDataTransient);
    }
    catch (const boost::bad_any_cast&)
    {
      //error("Unable to cast boost::any transient value to spire pointer.");
      return;
    }
    std::shared_ptr<Spire::SCIRun::SRInterface> spire = mSpire.lock();
    if (spire == nullptr)
      return;

    // Grab objects (to be regenerated with supplied data)
    std::shared_ptr<Spire::StuInterface> stuPipe = spire->getStuPipe();

    // Remove ALL prior objects.
    stuPipe->removeAllObjects();

    for (auto it = geomData->begin(); it != geomData->end(); ++it)
    {
      boost::shared_ptr<Core::Datatypes::GeometryObject> obj = *it;

      // Since we simply remove all objects from the scene everyframe (that
      // needs to change) we don't need to remove the objects one-by-one.
      //// Try/catch is for single-threaded cases. Exceptions are handled on the
      //// spire thread when spire is threaded.
      //try
      //{
      //  // Will remove all traces of old VBO's / IBO's not in use.
      //  // (remember, we remove the VBOs/IBOs we added at the end of this loop,
      //  //  this is to ensure there is only 1 shared_ptr reference to the IBOs
      //  //  and VBOs in Spire).
      //  stuPipe->removeObject(obj->objectName);
      //}
      //catch (std::out_of_range&)
      //{
      //  // Ignore
      //}

      stuPipe->addObject(obj->objectName);

      // Add vertex buffer objects.
      for (auto it = obj->mVBOs.cbegin(); it != obj->mVBOs.cend(); ++it)
      {
        const GeometryObject::SpireVBO& vbo = *it;
        stuPipe->addVBO(vbo.name, vbo.data, vbo.attributeNames);
      }

      // Add index buffer objects.
      for (auto it = obj->mIBOs.cbegin(); it != obj->mIBOs.cend(); ++it)
      {
        const GeometryObject::SpireIBO& ibo = *it;
        Spire::StuInterface::IBO_TYPE type;
        switch (ibo.indexSize)
        {
          case 1: // 8-bit
            type = Spire::StuInterface::IBO_8BIT;
            break;

          case 2: // 16-bit
            type = Spire::StuInterface::IBO_16BIT;
            break;

          case 4: // 32-bit
            type = Spire::StuInterface::IBO_32BIT;
            break;

          default:
            type = Spire::StuInterface::IBO_32BIT;
            throw std::invalid_argument("Unable to determine index buffer depth.");
            break;
        }
        stuPipe->addIBO(ibo.name, ibo.data, type);
      }

      // Add passes
      for (auto it = obj->mPasses.cbegin(); it != obj->mPasses.cend(); ++it)
      {
        const GeometryObject::SpirePass& pass = *it;
        stuPipe->addPassToObject(obj->objectName, pass.passName, pass.programName,
                                 pass.vboName, pass.iboName, pass.type);

        // Add uniforms associated with the pass
        for (auto it = pass.uniforms.begin(); it != pass.uniforms.end(); ++it)
        {
          std::string uniformName = std::get<0>(*it);
          std::shared_ptr<Spire::AbstractUniformStateItem> uniform(std::get<1>(*it));
          stuPipe->addPassUniformConcrete(obj->objectName, pass.passName,
                                          uniformName, uniform);
        }

        // Add gpu state if it has been set.
        if (pass.hasGPUState == true)
          stuPipe->addPassGPUState(obj->objectName, pass.passName, pass.gpuState);
      }

      // Now that we have created all of the appropriate passes, get rid of the
      // VBOs and IBOs.
      for (auto it = obj->mVBOs.cbegin(); it != obj->mVBOs.cend(); ++it)
      {
        const GeometryObject::SpireVBO& vbo = *it;
        stuPipe->removeVBO(vbo.name);
      }

      for (auto it = obj->mIBOs.cbegin(); it != obj->mIBOs.cend(); ++it)
      {
        const GeometryObject::SpireIBO& ibo = *it;
        stuPipe->removeIBO(ibo.name);
      }
    }
  }
}
<commit_msg>Add mouse control choice dropdown to ViewScene. Starts #331<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Interface/Modules/Render/ViewScene.h>
#include <Dataflow/Network/ModuleStateInterface.h>
#include <Core/Datatypes/Geometry.h>
#include <QtGui>
#include "QtGLContext.h"

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Datatypes;

//------------------------------------------------------------------------------
ViewSceneDialog::ViewSceneDialog(const std::string& name, ModuleStateHandle state,
  QWidget* parent /* = 0 */)
  : ModuleDialogGeneric(state, parent)
{
  setupUi(this);
  setWindowTitle(QString::fromStdString(name));

  auto tools = new QToolBar(this);
  auto menu = new QComboBox(this);
  menu->addItem("Legacy Mouse Control");
  menu->addItem("New Mouse Control");
  tools->addWidget(menu);
  glLayout->addWidget(tools);

  // Setup Qt OpenGL widget.
  QGLFormat fmt;
  fmt.setAlpha(true);
  fmt.setRgba(true);
  mGLWidget = new GLWidget(new QtGLContext(fmt));

  if (mGLWidget->isValid())
  {
    // Hook up the GLWidget
    glLayout->addWidget(mGLWidget);
    glLayout->update();

    // Set spire transient value (should no longer be used).
    mSpire = std::weak_ptr<Spire::SCIRun::SRInterface>(mGLWidget->getSpire());
  }
  else
  {
    /// \todo Display dialog.
    delete mGLWidget;
  }
}

//------------------------------------------------------------------------------
ViewSceneDialog::~ViewSceneDialog()
{
}

//------------------------------------------------------------------------------
void ViewSceneDialog::closeEvent(QCloseEvent *evt)
{
}

//------------------------------------------------------------------------------
void ViewSceneDialog::moduleExecuted()
{
  // Grab the geomData transient value.
  boost::any geomDataTransient = state_->getTransientValue("geomData");
  if (!geomDataTransient.empty())
  {
    boost::shared_ptr<std::list<boost::shared_ptr<Core::Datatypes::GeometryObject>>> geomData; // Whoa...
    try
    {
      geomData = boost::any_cast<boost::shared_ptr<std::list<boost::shared_ptr<Core::Datatypes::GeometryObject>>>>(geomDataTransient);
    }
    catch (const boost::bad_any_cast&)
    {
      //error("Unable to cast boost::any transient value to spire pointer.");
      return;
    }
    std::shared_ptr<Spire::SCIRun::SRInterface> spire = mSpire.lock();
    if (spire == nullptr)
      return;

    // Grab objects (to be regenerated with supplied data)
    std::shared_ptr<Spire::StuInterface> stuPipe = spire->getStuPipe();

    // Remove ALL prior objects.
    stuPipe->removeAllObjects();

    for (auto it = geomData->begin(); it != geomData->end(); ++it)
    {
      boost::shared_ptr<Core::Datatypes::GeometryObject> obj = *it;

      // Since we simply remove all objects from the scene everyframe (that
      // needs to change) we don't need to remove the objects one-by-one.
      //// Try/catch is for single-threaded cases. Exceptions are handled on the
      //// spire thread when spire is threaded.
      //try
      //{
      //  // Will remove all traces of old VBO's / IBO's not in use.
      //  // (remember, we remove the VBOs/IBOs we added at the end of this loop,
      //  //  this is to ensure there is only 1 shared_ptr reference to the IBOs
      //  //  and VBOs in Spire).
      //  stuPipe->removeObject(obj->objectName);
      //}
      //catch (std::out_of_range&)
      //{
      //  // Ignore
      //}

      stuPipe->addObject(obj->objectName);

      // Add vertex buffer objects.
      for (auto it = obj->mVBOs.cbegin(); it != obj->mVBOs.cend(); ++it)
      {
        const GeometryObject::SpireVBO& vbo = *it;
        stuPipe->addVBO(vbo.name, vbo.data, vbo.attributeNames);
      }

      // Add index buffer objects.
      for (auto it = obj->mIBOs.cbegin(); it != obj->mIBOs.cend(); ++it)
      {
        const GeometryObject::SpireIBO& ibo = *it;
        Spire::StuInterface::IBO_TYPE type;
        switch (ibo.indexSize)
        {
          case 1: // 8-bit
            type = Spire::StuInterface::IBO_8BIT;
            break;

          case 2: // 16-bit
            type = Spire::StuInterface::IBO_16BIT;
            break;

          case 4: // 32-bit
            type = Spire::StuInterface::IBO_32BIT;
            break;

          default:
            type = Spire::StuInterface::IBO_32BIT;
            throw std::invalid_argument("Unable to determine index buffer depth.");
            break;
        }
        stuPipe->addIBO(ibo.name, ibo.data, type);
      }

      // Add passes
      for (auto it = obj->mPasses.cbegin(); it != obj->mPasses.cend(); ++it)
      {
        const GeometryObject::SpirePass& pass = *it;
        stuPipe->addPassToObject(obj->objectName, pass.passName, pass.programName,
                                 pass.vboName, pass.iboName, pass.type);

        // Add uniforms associated with the pass
        for (auto it = pass.uniforms.begin(); it != pass.uniforms.end(); ++it)
        {
          std::string uniformName = std::get<0>(*it);
          std::shared_ptr<Spire::AbstractUniformStateItem> uniform(std::get<1>(*it));
          stuPipe->addPassUniformConcrete(obj->objectName, pass.passName,
                                          uniformName, uniform);
        }

        // Add gpu state if it has been set.
        if (pass.hasGPUState == true)
          stuPipe->addPassGPUState(obj->objectName, pass.passName, pass.gpuState);
      }

      // Now that we have created all of the appropriate passes, get rid of the
      // VBOs and IBOs.
      for (auto it = obj->mVBOs.cbegin(); it != obj->mVBOs.cend(); ++it)
      {
        const GeometryObject::SpireVBO& vbo = *it;
        stuPipe->removeVBO(vbo.name);
      }

      for (auto it = obj->mIBOs.cbegin(); it != obj->mIBOs.cend(); ++it)
      {
        const GeometryObject::SpireIBO& ibo = *it;
        stuPipe->removeIBO(ibo.name);
      }
    }
  }
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 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(XALANOUTPUTSTREAM_HEADER_GUARD_1357924680)
#define XALANOUTPUTSTREAM_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <PlatformSupport/PlatformSupportDefinitions.hpp>

#include <vector>

#include <XalanDOM/XalanDOMString.hpp>

#include <PlatformSupport/XSLException.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XalanOutputTranscoder;

class XALAN_PLATFORMSUPPORT_EXPORT XalanOutputStream
{
public :

	enum { eDefaultBufferSize = 512, eDefaultTranscoderBlockSize = 1024 };

#if defined(XALAN_NO_STD_NAMESPACE)
	typedef vector<XalanDOMChar>		BufferType;

	typedef vector<char>				TranscodeVectorType;
#else
	typedef std::vector<XalanDOMChar>	BufferType;

	typedef std::vector<char>			TranscodeVectorType;
#endif

	typedef BufferType::size_type	size_type;

	/**
	 * Constructor.
	 *
	 * @param theBufferSize the size of the transcoding buffer
	 * @param theTranscoderBlockSize the size of the block used by the transcoder
	 * @param fThrowTranscodeException If true, an error transcoding will result in an exception being thrown.
	 */
	explicit
	XalanOutputStream(
			BufferType::size_type			theBufferSize = eDefaultBufferSize,
			TranscodeVectorType::size_type	theTranscoderBlockSize = eDefaultTranscoderBlockSize,
			bool							fThrowTranscodeException = true);

	virtual
	~XalanOutputStream();

	static const XalanDOMChar*
	defaultNewlineString()
	{
#if defined(XALAN_NEWLINE_IS_CRLF)
		return s_nlCRString;
#else
		return s_nlString;
#endif
	}

	/**
	 * Write the appropriate newline character(s) to the stream.
	 */
	virtual void
	newline();

	/**
	 * Get the string which is appropriate for inserting a line feed in the stream.
	 */
	virtual const XalanDOMChar*
	getNewlineString() const;

	/**
	 * Flush the stream's buffer.
	 */
	void
	flush()
	{
		flushBuffer();

		doFlush();
	}

	/**
	 * Write a character to the output stream.	The character
	 * will not be transcoded.
	 *
	 * @param theChar		the character to write
	 */
	void
	write(char	theChar)
	{
		write(&theChar, 1);
	}

	/**
	 * Write a wide character to the output stream.  The character
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theChar		the character to write
	 */
	void
	write(XalanDOMChar	theChar)
	{
		assert(m_bufferSize > 0);

		if (m_buffer.size() == m_bufferSize)
		{
			flushBuffer();
		}

		m_buffer.push_back(theChar);
	}

	/**
	 * Write a null-terminated string to the output file.  The character
	 * will not be transcoded.
	 *
	 * @param theBuffer 	  character buffer to write
	 */
	void
	write(const char*	theBuffer)
	{
		assert(theBuffer != 0);

		XALAN_USING_XALAN(length)

		write(theBuffer, length(theBuffer));
	}

	/**
	 * Write a null-terminated wide string to the output file.	The string
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theBuffer 	  character buffer to write
	 */
	void
	write(const XalanDOMChar*	theBuffer)
	{
		XALAN_USING_XALAN(length)

		write(theBuffer, length(theBuffer));
	}

	/**
	 * Write a specified number of characters to the output stream.  The string
	 * will not be transcoded.
	 *
	 * @param theBuffer 	  character buffer to write
	 * @param theBufferLength number of characters to write
	 */
	void
	write(
			const char* 	theBuffer,
			size_type		theBufferLength)
	{
		assert(theBuffer != 0);

		flushBuffer();

		writeData(theBuffer,
				  theBufferLength);
	}

	/**
	 * Write a specified number of characters to the output stream.  The string
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theBuffer 	  character buffer to write
	 * @param theBufferLength number of characters to write
	 */
	void
	write(
			const XalanDOMChar* 	theBuffer,
			size_type				theBufferLength);

	/**
	 * Get the output encoding for the stream.
	 *
	 * @return The encoding name
	 */
	const XalanDOMString&
	getOutputEncoding() const
	{
		return m_encoding;
	}

	/**
	 * Set the output encoding for the stream.
	 *
	 * @param theEncoding The encoding name
	 */
	void
	setOutputEncoding(const XalanDOMString& 	theEncoding);

	/**
	 * Determine if a given value can be represented in
	 * the output encoding.
	 *
	 * @return true if the value can be represented, and false if not.
	 */
	bool
	canTranscodeTo(unsigned int 	theChar) const;

	const XalanOutputTranscoder*
	getTranscoder() const
	{
		return m_transcoder;
	}

	/**
	 * Set the flag that indicates whether a transcoding
	 * error should throw an exception.  The default is
	 * to throw an exception.  If this flag is false, and
	 * and an error occurs transcoding, then data will
	 * likely be lost.
	 *
	 * @return the value of the flag.
	 */
	bool
	getThrowTranscodeException() const
	{
		return m_throwTranscodeException;
	}

	/**
	 * Set the flag that indicates whether a transcoding
	 * error should throw an exception.  The default is
	 * to throw an exception.  If this flag is false, and
	 * and an error occurs transcoding, then data will
	 * likely be lost.
	 *
	 * @param the new value of the flag.
	 */
	void
	setThrowTranscodeException(bool flag)
	{
		m_throwTranscodeException = flag;
	}

	/**
	 * Set the size of the output buffer.
	 *
	 * @param theBufferSize The buffer size.
	 */
	void
	setBufferSize(BufferType::size_type 	theBufferSize);

	class XALAN_PLATFORMSUPPORT_EXPORT XalanOutputStreamException : public XSLException
	{
	public:

		XalanOutputStreamException(
			const XalanDOMString&	theMessage,
			const XalanDOMString&	theType);

		virtual
		~XalanOutputStreamException();
	};

	class XALAN_PLATFORMSUPPORT_EXPORT UnknownEncodingException : public XalanOutputStreamException
	{
	public:

		explicit
		UnknownEncodingException();

		virtual
		~UnknownEncodingException();
	};

	class XALAN_PLATFORMSUPPORT_EXPORT UnsupportedEncodingException : public XalanOutputStreamException
	{
	public:

		UnsupportedEncodingException(const XalanDOMString&	theEncoding);

		virtual
		~UnsupportedEncodingException();

		const XalanDOMString&
		getEncoding() const
		{
			return m_encoding;
		}

	private:

		const XalanDOMString	m_encoding;
	};

	class XALAN_PLATFORMSUPPORT_EXPORT TranscoderInternalFailureException : public XalanOutputStreamException
	{
	public:

		TranscoderInternalFailureException(const XalanDOMString&	theEncoding);

		virtual
		~TranscoderInternalFailureException();

		const XalanDOMString&
		getEncoding() const
		{
			return m_encoding;
		}

	private:

		const XalanDOMString	m_encoding;
	};

	class XALAN_PLATFORMSUPPORT_EXPORT TranscodingException : public XalanOutputStreamException
	{
	public:

		explicit
		TranscodingException();

		virtual
		~TranscodingException();
	};

protected:

	/**
	 * Transcode a wide string.
	 *
	 * @param theBuffer The string to transcode.
	 * @param theBufferLength The length of the string.
	 * @param theDestination The destination vector.
	 */
	void
	transcode(
			const XalanDOMChar* 	theBuffer,
			size_type				theBufferLength,
			TranscodeVectorType&	theDestination);

	/**
	 * Write the data in the buffer
	 *
	 * @param theBuffer The data to write
	 * @param theBufferLength The length of theBuffer.
	 */
	virtual void
	writeData(
			const char* 	theBuffer,
			size_type		theBufferLength) = 0;

	/**
	 * Flush the stream.
	 */
	virtual void
	doFlush() = 0;

	static const XalanDOMChar				s_nlString[];
	static const XalanDOMChar				s_nlCRString[];

	static const XalanDOMString::size_type	s_nlStringLength;
	static const XalanDOMString::size_type	s_nlCRStringLength;

private:

	// These are not implemented...
	XalanOutputStream(const XalanOutputStream&);

	XalanOutputStream&
	operator=(const XalanOutputStream&);

	bool
	operator==(const XalanOutputStream&) const;

	// Utility functions...
	void
	flushBuffer();

	void
	doWrite(
			const XalanDOMChar* 	theBuffer,
			size_t					theBufferLength);

	const TranscodeVectorType::size_type	m_transcoderBlockSize;

	XalanOutputTranscoder*					m_transcoder;

	BufferType::size_type					m_bufferSize;

	BufferType								m_buffer;

	XalanDOMString							m_encoding;

	bool									m_writeAsUTF16;

	bool									m_throwTranscodeException;

	TranscodeVectorType 					m_transcodingBuffer;
};

XALAN_CPP_NAMESPACE_END

#endif	// XALANOUTPUTSTREAM_HEADER_GUARD_1357924680
<commit_msg>Removed superfluous using directives.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 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(XALANOUTPUTSTREAM_HEADER_GUARD_1357924680)
#define XALANOUTPUTSTREAM_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <PlatformSupport/PlatformSupportDefinitions.hpp>

#include <vector>

#include <XalanDOM/XalanDOMString.hpp>

#include <PlatformSupport/XSLException.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XalanOutputTranscoder;

class XALAN_PLATFORMSUPPORT_EXPORT XalanOutputStream
{
public :

	enum { eDefaultBufferSize = 512, eDefaultTranscoderBlockSize = 1024 };

#if defined(XALAN_NO_STD_NAMESPACE)
	typedef vector<XalanDOMChar>		BufferType;

	typedef vector<char>				TranscodeVectorType;
#else
	typedef std::vector<XalanDOMChar>	BufferType;

	typedef std::vector<char>			TranscodeVectorType;
#endif

	typedef BufferType::size_type	size_type;

	/**
	 * Constructor.
	 *
	 * @param theBufferSize the size of the transcoding buffer
	 * @param theTranscoderBlockSize the size of the block used by the transcoder
	 * @param fThrowTranscodeException If true, an error transcoding will result in an exception being thrown.
	 */
	explicit
	XalanOutputStream(
			BufferType::size_type			theBufferSize = eDefaultBufferSize,
			TranscodeVectorType::size_type	theTranscoderBlockSize = eDefaultTranscoderBlockSize,
			bool							fThrowTranscodeException = true);

	virtual
	~XalanOutputStream();

	static const XalanDOMChar*
	defaultNewlineString()
	{
#if defined(XALAN_NEWLINE_IS_CRLF)
		return s_nlCRString;
#else
		return s_nlString;
#endif
	}

	/**
	 * Write the appropriate newline character(s) to the stream.
	 */
	virtual void
	newline();

	/**
	 * Get the string which is appropriate for inserting a line feed in the stream.
	 */
	virtual const XalanDOMChar*
	getNewlineString() const;

	/**
	 * Flush the stream's buffer.
	 */
	void
	flush()
	{
		flushBuffer();

		doFlush();
	}

	/**
	 * Write a character to the output stream.	The character
	 * will not be transcoded.
	 *
	 * @param theChar		the character to write
	 */
	void
	write(char	theChar)
	{
		write(&theChar, 1);
	}

	/**
	 * Write a wide character to the output stream.  The character
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theChar		the character to write
	 */
	void
	write(XalanDOMChar	theChar)
	{
		assert(m_bufferSize > 0);

		if (m_buffer.size() == m_bufferSize)
		{
			flushBuffer();
		}

		m_buffer.push_back(theChar);
	}

	/**
	 * Write a null-terminated string to the output file.  The character
	 * will not be transcoded.
	 *
	 * @param theBuffer 	  character buffer to write
	 */
	void
	write(const char*	theBuffer)
	{
		assert(theBuffer != 0);

		write(theBuffer, length(theBuffer));
	}

	/**
	 * Write a null-terminated wide string to the output file.	The string
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theBuffer 	  character buffer to write
	 */
	void
	write(const XalanDOMChar*	theBuffer)
	{
		write(theBuffer, length(theBuffer));
	}

	/**
	 * Write a specified number of characters to the output stream.  The string
	 * will not be transcoded.
	 *
	 * @param theBuffer 	  character buffer to write
	 * @param theBufferLength number of characters to write
	 */
	void
	write(
			const char* 	theBuffer,
			size_type		theBufferLength)
	{
		assert(theBuffer != 0);

		flushBuffer();

		writeData(theBuffer,
				  theBufferLength);
	}

	/**
	 * Write a specified number of characters to the output stream.  The string
	 * will be transcoded, if an output encoding is specified.
	 *
	 * @param theBuffer 	  character buffer to write
	 * @param theBufferLength number of characters to write
	 */
	void
	write(
			const XalanDOMChar* 	theBuffer,
			size_type				theBufferLength);

	/**
	 * Get the output encoding for the stream.
	 *
	 * @return The encoding name
	 */
	const XalanDOMString&
	getOutputEncoding() const
	{
		return m_encoding;
	}

	/**
	 * Set the output encoding for the stream.
	 *
	 * @param theEncoding The encoding name
	 */
	void
	setOutputEncoding(const XalanDOMString& 	theEncoding);

	/**
	 * Determine if a given value can be represented in
	 * the output encoding.
	 *
	 * @return true if the value can be represented, and false if not.
	 */
	bool
	canTranscodeTo(unsigned int 	theChar) const;

	const XalanOutputTranscoder*
	getTranscoder() const
	{
		return m_transcoder;
	}

	/**
	 * Set the flag that indicates whether a transcoding
	 * error should throw an exception.  The default is
	 * to throw an exception.  If this flag is false, and
	 * and an error occurs transcoding, then data will
	 * likely be lost.
	 *
	 * @return the value of the flag.
	 */
	bool
	getThrowTranscodeException() const
	{
		return m_throwTranscodeException;
	}

	/**
	 * Set the flag that indicates whether a transcoding
	 * error should throw an exception.  The default is
	 * to throw an exception.  If this flag is false, and
	 * and an error occurs transcoding, then data will
	 * likely be lost.
	 *
	 * @param the new value of the flag.
	 */
	void
	setThrowTranscodeException(bool flag)
	{
		m_throwTranscodeException = flag;
	}

	/**
	 * Set the size of the output buffer.
	 *
	 * @param theBufferSize The buffer size.
	 */
	void
	setBufferSize(BufferType::size_type 	theBufferSize);

	class XALAN_PLATFORMSUPPORT_EXPORT XalanOutputStreamException : public XSLException
	{
	public:

		XalanOutputStreamException(
			const XalanDOMString&	theMessage,
			const XalanDOMString&	theType);

		virtual
		~XalanOutputStreamException();
	};

	class XALAN_PLATFORMSUPPORT_EXPORT UnknownEncodingException : public XalanOutputStreamException
	{
	public:

		explicit
		UnknownEncodingException();

		virtual
		~UnknownEncodingException();
	};

	class XALAN_PLATFORMSUPPORT_EXPORT UnsupportedEncodingException : public XalanOutputStreamException
	{
	public:

		UnsupportedEncodingException(const XalanDOMString&	theEncoding);

		virtual
		~UnsupportedEncodingException();

		const XalanDOMString&
		getEncoding() const
		{
			return m_encoding;
		}

	private:

		const XalanDOMString	m_encoding;
	};

	class XALAN_PLATFORMSUPPORT_EXPORT TranscoderInternalFailureException : public XalanOutputStreamException
	{
	public:

		TranscoderInternalFailureException(const XalanDOMString&	theEncoding);

		virtual
		~TranscoderInternalFailureException();

		const XalanDOMString&
		getEncoding() const
		{
			return m_encoding;
		}

	private:

		const XalanDOMString	m_encoding;
	};

	class XALAN_PLATFORMSUPPORT_EXPORT TranscodingException : public XalanOutputStreamException
	{
	public:

		explicit
		TranscodingException();

		virtual
		~TranscodingException();
	};

protected:

	/**
	 * Transcode a wide string.
	 *
	 * @param theBuffer The string to transcode.
	 * @param theBufferLength The length of the string.
	 * @param theDestination The destination vector.
	 */
	void
	transcode(
			const XalanDOMChar* 	theBuffer,
			size_type				theBufferLength,
			TranscodeVectorType&	theDestination);

	/**
	 * Write the data in the buffer
	 *
	 * @param theBuffer The data to write
	 * @param theBufferLength The length of theBuffer.
	 */
	virtual void
	writeData(
			const char* 	theBuffer,
			size_type		theBufferLength) = 0;

	/**
	 * Flush the stream.
	 */
	virtual void
	doFlush() = 0;

	static const XalanDOMChar				s_nlString[];
	static const XalanDOMChar				s_nlCRString[];

	static const XalanDOMString::size_type	s_nlStringLength;
	static const XalanDOMString::size_type	s_nlCRStringLength;

private:

	// These are not implemented...
	XalanOutputStream(const XalanOutputStream&);

	XalanOutputStream&
	operator=(const XalanOutputStream&);

	bool
	operator==(const XalanOutputStream&) const;

	// Utility functions...
	void
	flushBuffer();

	void
	doWrite(
			const XalanDOMChar* 	theBuffer,
			size_t					theBufferLength);

	const TranscodeVectorType::size_type	m_transcoderBlockSize;

	XalanOutputTranscoder*					m_transcoder;

	BufferType::size_type					m_bufferSize;

	BufferType								m_buffer;

	XalanDOMString							m_encoding;

	bool									m_writeAsUTF16;

	bool									m_throwTranscodeException;

	TranscodeVectorType 					m_transcodingBuffer;
};

XALAN_CPP_NAMESPACE_END

#endif	// XALANOUTPUTSTREAM_HEADER_GUARD_1357924680
<|endoftext|>