#include "../../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include "ATStringOrDerivedImpl.hpp" #include #include #include #include #include #include #include #include "../../exceptions/XPath2TypeCastException.hpp" #include "../../exceptions/InvalidLexicalSpaceException.hpp" #include #include // defines X() and XMLCh* #include #include #include #include #include #include #include #include ATStringOrDerivedImpl:: ATStringOrDerivedImpl(const XMLCh* typeURI, const XMLCh* typeName, const XMLCh* value, XPath2MemoryManager* memMgr, const DynamicContext* context): ATStringOrDerived(memMgr), _typeName(typeName), _typeURI(typeURI) { _value = getMemoryManager()->getPooledString(value); } /* Get the name of the primitive type (basic type) of this type * (ie "decimal" for xs:decimal) */ const XMLCh* ATStringOrDerivedImpl::getPrimitiveTypeName() const { return this->getPrimitiveName(); } const XMLCh* ATStringOrDerivedImpl::getPrimitiveName() { return XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING; } /* Get the name of this type (ie "integer" for xs:integer) */ const XMLCh* ATStringOrDerivedImpl::getTypeName() const { return _typeName; } /* Get the namespace URI for this type */ const XMLCh* ATStringOrDerivedImpl::getTypeURI() const { return _typeURI; } AnyAtomicType::AtomicObjectType ATStringOrDerivedImpl::getTypeIndex() { return AnyAtomicType::STRING; } const AnyAtomicType* ATStringOrDerivedImpl::castAsInternal(const XMLCh* targetURI, const XMLCh* targetType, const DynamicContext* context) const { const DatatypeFactory* target = context->getDatatypeFactory(targetURI, targetType); AnyAtomicType::AtomicObjectType targetIndex = target->getPrimitiveTypeIndex(); switch (targetIndex) { case DOUBLE: { const XMLCh* upCase = XPath2Utils::toUpper(_value, context->getMemoryManager()); return DatatypeFactory::STR2AT::createDoubleOrDerived(context->getMemoryManager(), targetURI, targetType, upCase, context); } case FLOAT: { const XMLCh* upCase = XPath2Utils::toUpper(_value, context->getMemoryManager()); return DatatypeFactory::STR2AT::createFloatOrDerived(context->getMemoryManager(), targetURI, targetType, upCase, context); } default: return AnyAtomicType::castAsInternal(targetURI, targetType, context); } } /* returns the XMLCh* (canonical) representation of this type */ const XMLCh* ATStringOrDerivedImpl::asString(const DynamicContext* context) const { return _value; } /* returns this string as a set of codepoints */ const Sequence ATStringOrDerivedImpl::asCodepoints(const DynamicContext* context) const { unsigned int length = this->getLength(); Sequence result(length,context->getMemoryManager()); for(unsigned int i=0; igetMemoryManager(), (long int)_value[i], context)); } return result; } /* returns the substring starting at startingLoc of given length */ const ATStringOrDerived* ATStringOrDerivedImpl::substring(const Numeric* startingLoc, const Numeric* length, const DynamicContext* context) const { const ATDecimalOrDerived* one = DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), 1, context); const ATDecimalOrDerived* strLength = DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), (long)this->getLength(), context); // More specifically, returns the characters in $sourceString whose position $p obeys: // fn:round($startingLoc) <= $p < fn:round($startingLoc) + fn:round($length) const Numeric* startIndex = startingLoc->round(context); length=length->round(context); const Numeric* endIndex = startIndex->add(length, context); if(startIndex->greaterThan(strLength, context) || startIndex->greaterThan(endIndex, context)) { return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context); } XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer buffer(1023, context->getMemoryManager()); const Numeric* index = one;//DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), 0, context); // i is kept at one less than index, since XMLCh* start at index 0 int i = 0; // for(index = one; index <= strLength; index++) for(; !index->greaterThan(strLength, context); index = index->add(one, context), i++) { // if (index >= startIndex and index < endIndex), add the char at i if(!index->lessThan(startIndex, context) && index->lessThan(endIndex, context)) buffer.append(_value[i]); } return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), buffer.getRawBuffer(), context); } /* returns the substring that occurs after the first occurence of pattern */ const ATStringOrDerived* ATStringOrDerivedImpl::substringAfter(const ATStringOrDerived* pattern, Collation* collation, const DynamicContext* context) const { unsigned int containerLength = this->getLength(); unsigned int patternLength = pattern->getLength(); if(patternLength == 0) { return this; } if(patternLength > containerLength) { return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context); } const XMLCh* patternStr = pattern->asString(context); // search pattern must be shorter than (or same length as) string being searched for(unsigned int i = 0; i <= (containerLength - patternLength); i++) { // extract a substring of the same length of the pattern and compare them const XMLCh *substr=XPath2Utils::subString(_value, i, patternLength, context->getMemoryManager()); bool result = (collation->compare(substr,patternStr)==0); if(result) { int index = i + patternLength; const XMLCh* value = XPath2Utils::subString(_value, index, containerLength - index, context->getMemoryManager()); return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), value, context); } } return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context); } /* returns the substring that occurs before the first occurence of pattern */ const ATStringOrDerived* ATStringOrDerivedImpl::substringBefore(const ATStringOrDerived* pattern, Collation* collation, const DynamicContext* context) const { unsigned int containerLength = this->getLength(); unsigned int patternLength = pattern->getLength(); if(patternLength == 0) { return this; } if(patternLength > containerLength) { return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context); } const XMLCh* patternStr = pattern->asString(context); // search pattern must be shorter than (or same length as) string being searched for(unsigned int i = 0; i <= (containerLength - patternLength); i++) { // extract a substring of the same length of the pattern and compare them const XMLCh *substr=XPath2Utils::subString(_value, i, patternLength, context->getMemoryManager()); bool result = (collation->compare(substr,patternStr)==0); if(result) { const XMLCh* value = XPath2Utils::subString(_value, 0, i, context->getMemoryManager()); return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), value, context); } } return DatatypeFactory::STR2AT::createString(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context); } unsigned int ATStringOrDerivedImpl::getLength() const { return XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(_value); } /* returns true if the two objects' are equal (string comparison) * false otherwise */ bool ATStringOrDerivedImpl::equals(const AnyAtomicType* target, const DynamicContext* context) const { if(this->getPrimitiveTypeIndex() != target->getPrimitiveTypeIndex()) { DSLthrow(IllegalArgumentException,X("ATStringOrDerivedImpl::equals"), X("Equality operator for given types not supported")); } return XPath2Utils::equals(((ATStringOrDerivedImpl*)target)->_value, _value); } AnyAtomicType::AtomicObjectType ATStringOrDerivedImpl::getPrimitiveTypeIndex() const { return this->getTypeIndex(); } /** Releases the memory used by this Item */ void ATStringOrDerivedImpl::release() const { //TODO needs to check for ownership before releasing! getMemoryManager()->deallocate((void*)this); }