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 + -
显示快捷键?