/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include using namespace ::com::sun::star::uno; using namespace ::com::sun::star::xml; using namespace ::com::sun::star::xml::sax; namespace sax_fastparser { // wastage to keep MSVC happy vs. an in-line {} FastTokenHandlerBase::~FastTokenHandlerBase() { } UnknownAttribute::UnknownAttribute( OUString aNamespaceURL, OString aName, OString value ) : maNamespaceURL(std::move( aNamespaceURL )), maName(std::move( aName )), maValue(std::move( value )) { } UnknownAttribute::UnknownAttribute( OString aName, OString value ) : maName(std::move( aName )), maValue(std::move( value )) { } void UnknownAttribute::FillAttribute( Attribute* pAttrib ) const { if( pAttrib ) { pAttrib->Name = OStringToOUString( maName, RTL_TEXTENCODING_UTF8 ); pAttrib->NamespaceURL = maNamespaceURL; pAttrib->Value = OStringToOUString( maValue, RTL_TEXTENCODING_UTF8 ); } } FastAttributeList::FastAttributeList( sax_fastparser::FastTokenHandlerBase *pTokenHandler) : mpTokenHandler( pTokenHandler ) { // random initial size of buffer to store attribute values mnChunkLength = 58; mpChunk = static_cast(malloc( mnChunkLength )); maAttributeValues.push_back( 0 ); } FastAttributeList::FastAttributeList( const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) { const auto& rOther = castToFastAttributeList(xAttrList); mpTokenHandler = rOther.mpTokenHandler; mpChunk = static_cast(malloc( rOther.mnChunkLength )); mnChunkLength = rOther.mnChunkLength; memcpy(mpChunk, rOther.mpChunk, rOther.mnChunkLength); maAttributeValues = rOther.maAttributeValues; maAttributeTokens = rOther.maAttributeTokens; maUnknownAttributes = rOther.maUnknownAttributes; } css::uno::Reference< ::css::util::XCloneable > FastAttributeList::createClone() { return new FastAttributeList(this); } FastAttributeList::~FastAttributeList() { free( mpChunk ); } void FastAttributeList::clear() { maAttributeTokens.clear(); maAttributeValues.resize(1); assert(maAttributeValues[0] == 0); maUnknownAttributes.clear(); } void FastAttributeList::add( sal_Int32 nToken, const char* pValue, size_t nValueLength ) { assert(nToken != -1); assert(nToken != 0); assert(nValueLength < SAL_MAX_INT32); // protect against absurd values maAttributeTokens.push_back( nToken ); sal_Int32 nWritePosition = maAttributeValues.back(); maAttributeValues.push_back( maAttributeValues.back() + nValueLength + 1 ); if (maAttributeValues.back() > mnChunkLength) { const sal_Int32 newLen = std::max(mnChunkLength * 2, maAttributeValues.back()); auto p = static_cast(realloc(mpChunk, newLen)); if (!p) throw std::bad_alloc(); mnChunkLength = newLen; mpChunk = p; } memcpy(mpChunk + nWritePosition, pValue, nValueLength); mpChunk[nWritePosition + nValueLength] = '\0'; } void FastAttributeList::add( sal_Int32 nToken, const char* pValue ) { add( nToken, pValue, strlen( pValue )); } void FastAttributeList::add( sal_Int32 nToken, const OString& rValue ) { add( nToken, rValue.getStr(), rValue.getLength() ); } void FastAttributeList::add(sal_Int32 nToken, std::u16string_view sValue) { add(nToken, OUStringToOString(sValue, RTL_TEXTENCODING_UTF8)); } void FastAttributeList::addNS( sal_Int32 nNamespaceToken, sal_Int32 nToken, const OString& rValue ) { sal_Int32 nCombinedToken = (nNamespaceToken << 16) | nToken; add( nCombinedToken, rValue ); } void FastAttributeList::addNS(sal_Int32 nNamespaceToken, sal_Int32 nToken, std::u16string_view sValue) { sal_Int32 nCombinedToken = (nNamespaceToken << 16) | nToken; add(nCombinedToken, sValue); } void FastAttributeList::addUnknown( const OUString& rNamespaceURL, const OString& rName, const OString& value ) { maUnknownAttributes.emplace_back( rNamespaceURL, rName, value ); } void FastAttributeList::addUnknown( const OString& rName, const OString& value ) { maUnknownAttributes.emplace_back( rName, value ); } void FastAttributeList::add( const css::uno::Reference& xAttrList ) { const auto& rOther = castToFastAttributeList(xAttrList); add(rOther); } void FastAttributeList::add( const FastAttributeList& rOther ) { for (size_t i=0; i < rOther.maAttributeTokens.size(); ++i) add(rOther.maAttributeTokens[i], rOther.getFastAttributeValue(i), rOther.AttributeValueLength(i)); for (const auto & i : rOther.maUnknownAttributes) addUnknown(i.maNamespaceURL, i.maName, i.maValue); } // XFastAttributeList sal_Bool FastAttributeList::hasAttribute( ::sal_Int32 Token ) { for (sal_Int32 i : maAttributeTokens) if (i == Token) return true; return false; } sal_Int32 FastAttributeList::getValueToken( ::sal_Int32 Token ) { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == Token) return FastTokenHandlerBase::getTokenFromChars( mpTokenHandler, getFastAttributeValue(i), AttributeValueLength( i ) ); throw SAXException("FastAttributeList::getValueToken: unknown token " + OUString::number(Token), nullptr, Any()); } sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int32 Default ) { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == Token) return FastTokenHandlerBase::getTokenFromChars( mpTokenHandler, getFastAttributeValue(i), AttributeValueLength( i ) ); return Default; } // performance sensitive shortcuts to avoid allocation ... bool FastAttributeList::getAsInteger( sal_Int32 nToken, sal_Int32 &rInt) const { rInt = 0; for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == nToken) { sal_Int64 nVal = rtl_str_toInt64_WithLength( getFastAttributeValue(i), 10, AttributeValueLength(i) ); if (nVal < SAL_MIN_INT32 || nVal > SAL_MAX_INT32) { nVal = 0; } rInt = nVal; return true; } return false; } sal_Int32 FastAttributeList::getAsIntegerByIndex( sal_Int32 nTokenIndex ) const { sal_Int64 n = rtl_str_toInt64_WithLength( getFastAttributeValue(nTokenIndex), 10, AttributeValueLength(nTokenIndex) ); if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32) { n = 0; } return n; } bool FastAttributeList::getAsDouble( sal_Int32 nToken, double &rDouble) const { rDouble = 0.0; for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == nToken) { auto const p = getFastAttributeValue(i); rDouble = rtl_math_stringToDouble( p, p + AttributeValueLength(i), '.', 0, nullptr, nullptr ); return true; } return false; } bool FastAttributeList::getAsView( sal_Int32 nToken, std::string_view& rPos ) const { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) { if (maAttributeTokens[i] != nToken) continue; sal_Int32 nOffset = maAttributeValues[i]; size_t nValueLen = maAttributeValues[i + 1] - maAttributeValues[i] - 1; rPos = { mpChunk + nOffset, nValueLen }; return true; } return false; } std::string_view FastAttributeList::getAsViewByIndex( sal_Int32 nTokenIndex ) const { sal_Int32 nOffset = maAttributeValues[nTokenIndex]; size_t nValueLen = maAttributeValues[nTokenIndex + 1] - maAttributeValues[nTokenIndex] - 1; return { mpChunk + nOffset, nValueLen }; } OUString FastAttributeList::getValue( ::sal_Int32 Token ) { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == Token) return OUString( getFastAttributeValue(i), AttributeValueLength(i), RTL_TEXTENCODING_UTF8 ); throw SAXException("FastAttributeList::getValue: unknown token " + OUString::number(Token), nullptr, Any()); } OUString FastAttributeList::getValueByIndex( ::sal_Int32 nTokenIndex ) const { return OUString( getFastAttributeValue(nTokenIndex), AttributeValueLength(nTokenIndex), RTL_TEXTENCODING_UTF8 ); } OUString FastAttributeList::getOptionalValue( ::sal_Int32 Token ) { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == Token) return OUString( getFastAttributeValue(i), AttributeValueLength(i), RTL_TEXTENCODING_UTF8 ); return OUString(); } Sequence< Attribute > FastAttributeList::getUnknownAttributes( ) { auto nSize = maUnknownAttributes.size(); if (nSize == 0) return {}; Sequence< Attribute > aSeq( nSize ); Attribute* pAttr = aSeq.getArray(); for( const auto& rAttr : maUnknownAttributes ) rAttr.FillAttribute( pAttr++ ); return aSeq; } Sequence< FastAttribute > FastAttributeList::getFastAttributes( ) { Sequence< FastAttribute > aSeq( maAttributeTokens.size() ); FastAttribute* pAttr = aSeq.getArray(); for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) { pAttr->Token = maAttributeTokens[i]; pAttr->Value = OUString( getFastAttributeValue(i), AttributeValueLength(i), RTL_TEXTENCODING_UTF8 ); pAttr++; } return aSeq; } FastAttributeList::FastAttributeIter FastAttributeList::find( sal_Int32 nToken ) const { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if( maAttributeTokens[i] == nToken ) return FastAttributeIter(*this, i); return end(); } sal_Int32 FastTokenHandlerBase::getTokenFromChars( const FastTokenHandlerBase *pTokenHandler, const char *pToken, size_t nLen /* = 0 */ ) { sal_Int32 nRet; if( !nLen ) nLen = strlen( pToken ); nRet = pTokenHandler->getTokenDirect( pToken, static_cast(nLen) ); return nRet; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */