attrimpl.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 692 行 · 第 1/2 页

CPP
692
字号
/* * Copyright 1999-2002,2004 The Apache Software Foundation. *  * Licensed 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. *//* * $Id: AttrImpl.cpp,v 1.9 2004/09/08 13:55:42 peiyongz Exp $ * * <p><b>WARNING</b>: Some of the code here is partially duplicated in * ParentNode, be careful to keep these two classes in sync! */#include "AttrImpl.hpp"#include "DOM_DOMException.hpp"#include "DocumentImpl.hpp"#include "TextImpl.hpp"#include "ElementImpl.hpp"#include "DStringPool.hpp"#include "NodeIDMap.hpp"#include "RangeImpl.hpp"XERCES_CPP_NAMESPACE_BEGIN/* * The handling of the value field being either the first child node (a * ChildNode*) or directly the value (a DOMString) is rather tricky. In the * DOMString case we need to get the field in the right type so that the * compiler is happy and the appropriate operator gets called. This is * essential for the reference counts of the DOMStrings involved to be updated * as due. * This is consistently achieved by taking the address of the value field and * changing it into a DOMString*, and then dereferencing it to get a DOMString. * The typical piece of code is: * DOMString *x = (DomString *)&value; *  ... use of *x which is the DOMString ... * This was amended by neilg after memory management was * introduced.  Now a union exists which is either a  * DOMString * or a ChildNode *.  This will be less efficient * (one more dereference per access) but actually works on all the * compilers we support. */AttrImpl::AttrImpl(DocumentImpl *ownerDoc, const DOMString &aName)    : NodeImpl (ownerDoc){    name = aName.clone();    isSpecified(true);    hasStringValue(true);    value.child = null;};AttrImpl::AttrImpl(const AttrImpl &other, bool deep)    : NodeImpl(other){    name = other.name.clone();	    isSpecified(other.isSpecified());    /* We must initialize the void* value to null in *all* cases. Failing to do     * so would cause, in case of assignment to a DOMString later, its content     * to be derefenced as a DOMString, which would lead the ref count code to     * be called on something that is not actually a DOMString... Really bad     * things would then happen!!!     */    value.child = null;    hasStringValue(other.hasStringValue());    if (other.isIdAttr())    {        isIdAttr(true);        this->getOwnerDocument()->getNodeIDMap()->add(this);    }    // take care of case where there are kids    if (!hasStringValue()) {        cloneChildren(other);    }    else {        if(other.value.str == null)         {            if(value.str != null)            {                *(value.str) = null;                delete value.str;                value.str = null;            }       }       else       {            // get the address of the value field of this as a DOMString*            DOMString *x = (value.str == null                ?(value.str = new (getOwnerDocument()->getMemoryManager()) DOMString())                :value.str            );            // and the address of the value field of other as a DOMString*            DOMString *y = other.value.str;            // We can now safely do the cloning and assignement, both operands            // being a DOMString their ref counts will be updated appropriately            *x = y->clone();        }    }};AttrImpl::~AttrImpl() {    if (hasStringValue()) {        // if value is a DOMString we must make sure its ref count is updated.        // this is achieved by changing the address of the value field into a        // DOMString* and setting the value field to null        if(value.str != null)         {            *(value.str) = null;            delete value.str;            value.str = null;        }    }}// create a real Text node as child if we don't have one yetvoid AttrImpl::makeChildNode() {    if (hasStringValue()) {        if (value.child != null) {            // change the address of the value field into a DOMString*            DOMString *x = (value.str == null                ?(value.str = new (getOwnerDocument()->getMemoryManager()) DOMString())                :value.str            );            // create a Text node passing the DOMString it points to            TextImpl *text =              (TextImpl *) getOwnerDocument()->createTextNode(*x);            // get the DOMString ref count to be updated by setting the value            // field to null            *x = null;            delete x;            // finally reassign the value to the node address            value.child = text;            text->isFirstChild(true);            text->previousSibling = text;            text->ownerNode = this;            text->isOwned(true);        }        hasStringValue(false);    }}NodeImpl * AttrImpl::cloneNode(bool deep){    return new (getOwnerDocument()->getMemoryManager()) AttrImpl(*this, deep);};DOMString AttrImpl::getNodeName() {    return name;};short AttrImpl::getNodeType() {    return DOM_Node::ATTRIBUTE_NODE;};DOMString AttrImpl::getName(){    return name;};DOMString AttrImpl::getNodeValue(){    return getValue();};bool AttrImpl::getSpecified(){    return isSpecified();};DOMString AttrImpl::getValue(){    if (value.child == null) {        return 0; // return "";    }    if (hasStringValue()) {        // change value into a DOMString*        DOMString *x = (value.str == null            ?(value.str = new (getOwnerDocument()->getMemoryManager()) DOMString())            :value.str        );        // return the DOMString it points to        return *x;    }    ChildNode *firstChild = value.child;    ChildNode *node = firstChild->nextSibling;    if (node == null) {        return firstChild->getNodeValue().clone();    }    int             length = 0;    for (node = firstChild; node != null; node = node->nextSibling)        length += node->getNodeValue().length();    DOMString retString;    retString.reserve(length);    for (node = firstChild; node != null; node = node->nextSibling)    {        retString.appendData(node->getNodeValue());    };    return retString;};bool AttrImpl::isAttrImpl(){    return true;};void AttrImpl::setNodeValue(const DOMString &val){    setValue(val);};void AttrImpl::setSpecified(bool arg){    isSpecified(arg);};void AttrImpl::setValue(const DOMString &newvalue){    if (isReadOnly())    {        throw DOM_DOMException        (            DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null        );    }    //  If this attribute was of type ID and in the map, take it out,    //    then put it back in with the new name.  For now, we don't worry    //    about what happens if the new name conflicts    //    if (isIdAttr())        this->getOwnerDocument()->getNodeIDMap()->remove(this);    if (!hasStringValue() && value.str != null) {        NodeImpl *kid;        while ((kid = value.child) != null) { // Remove existing kids            removeChild(kid);            if (kid->nodeRefCount == 0)                NodeImpl::deleteIf(kid);        }    }    // directly store the string as the value by changing the value field    // into a DOMString    DOMString *x = (value.str == null         ?(value.str = new (getOwnerDocument()->getMemoryManager()) DOMString())        :value.str    );    if (newvalue != null) {        *x = newvalue.clone();    }    else {        *x = null;        delete x;        value.str = null;    }    hasStringValue(true);    isSpecified(true);    changed();    if (isIdAttr())        this->getOwnerDocument()->getNodeIDMap()->add(this);};DOMString AttrImpl::toString(){    DOMString retString;    retString.appendData(name);    retString.appendData(DOMString("=\""));    retString.appendData(getValue());    retString.appendData(DOMString("\""));    return retString;}//Introduced in DOM Level 2ElementImpl *AttrImpl::getOwnerElement(){    // if we have an owner, ownerNode is our ownerElement, otherwise it's    // our ownerDocument and we don't have an ownerElement    return (ElementImpl *) (isOwned() ? ownerNode : null);}//internal use by parser onlyvoid AttrImpl::setOwnerElement(ElementImpl *ownerElem){    ownerNode = ownerElem;    isOwned(false);}// ParentNode stuffvoid AttrImpl::cloneChildren(const NodeImpl &other) {  //    for (NodeImpl *mykid = other.getFirstChild();    for (NodeImpl *mykid = ((NodeImpl&)other).getFirstChild();         mykid != null;         mykid = mykid->getNextSibling()) {        this->appendChild(mykid->cloneNode(true));    }}NodeListImpl *AttrImpl::getChildNodes() {    return this;}NodeImpl * AttrImpl::getFirstChild() {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?