diff options
25 files changed, 223 insertions, 341 deletions
diff --git a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.cxx b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.cxx index 4bdadcdcde61..ae1744615073 100644 --- a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.cxx +++ b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.cxx @@ -35,7 +35,7 @@ SvXMLAutoCorrectTokenHandler::~SvXMLAutoCorrectTokenHandler() sal_Int32 SAL_CALL SvXMLAutoCorrectTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& Identifier ) { - return getTokenDirect( reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength() ); + return getTokenDirect( std::string_view(reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength()) ); } Sequence< sal_Int8 > SAL_CALL SvXMLAutoCorrectTokenHandler::getUTF8Identifier( sal_Int32 ) @@ -43,11 +43,9 @@ Sequence< sal_Int8 > SAL_CALL SvXMLAutoCorrectTokenHandler::getUTF8Identifier( s return Sequence< sal_Int8 >(); } -sal_Int32 SvXMLAutoCorrectTokenHandler::getTokenDirect( const char *pTag, sal_Int32 nLength ) const +sal_Int32 SvXMLAutoCorrectTokenHandler::getTokenDirect(std::string_view token) const { - if( !nLength ) - nLength = strlen( pTag ); - const struct xmltoken* pToken = Perfect_Hash::in_word_set( pTag, nLength ); + const struct xmltoken* pToken = Perfect_Hash::in_word_set(token.data(), token.size()); return pToken ? pToken->nToken : XML_TOKEN_INVALID; } diff --git a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx index df913dbe6b01..0c86077fd4b5 100644 --- a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx +++ b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx @@ -39,7 +39,7 @@ public: virtual css::uno::Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 Token ) override; // Much faster direct C++ shortcut to the method that matters - virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const override; + virtual sal_Int32 getTokenDirect(std::string_view token) const override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/core/fasttokenhandler.hxx b/include/oox/core/fasttokenhandler.hxx index 396474b988a1..d47c81dd0130 100644 --- a/include/oox/core/fasttokenhandler.hxx +++ b/include/oox/core/fasttokenhandler.hxx @@ -29,8 +29,6 @@ #include <sal/types.h> #include <sax/fastattribs.hxx> -namespace oox { class TokenMap; } - namespace oox::core { @@ -41,8 +39,7 @@ class OOX_DLLPUBLIC FastTokenHandler final : public cppu::ImplInheritanceHelper< sax_fastparser::FastTokenHandlerBase, css::lang::XServiceInfo > { public: - explicit FastTokenHandler(); - virtual ~FastTokenHandler() override; + explicit FastTokenHandler() = default; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; @@ -54,10 +51,7 @@ public: virtual sal_Int32 SAL_CALL getTokenFromUTF8( const css::uno::Sequence< sal_Int8 >& Identifier ) override; // Much faster direct C++ shortcut to the method that matters - virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const override; - -private: - const TokenMap& mrTokenMap; ///< Reference to global token map singleton. + virtual sal_Int32 getTokenDirect(std::string_view token) const override; }; diff --git a/include/oox/helper/attributelist.hxx b/include/oox/helper/attributelist.hxx index 25f2ebe4f823..7e3c773a5781 100644 --- a/include/oox/helper/attributelist.hxx +++ b/include/oox/helper/attributelist.hxx @@ -29,6 +29,7 @@ #include <com/sun/star/util/DateTime.hpp> #include <oox/dllapi.h> #include <rtl/ustring.hxx> +#include <rtl/ref.hxx> #include <sal/types.h> #include <oox/drawingml/color.hxx> @@ -83,10 +84,10 @@ class OOX_DLLPUBLIC AttributeList public: explicit AttributeList( const css::uno::Reference< css::xml::sax::XFastAttributeList >& rxAttribs ); + ~AttributeList(); /** Returns the wrapped com.sun.star.xml.sax.XFastAttributeList object. */ - const css::uno::Reference< css::xml::sax::XFastAttributeList >& - getFastAttributeList() const { return mxAttribs; } + css::uno::Reference<css::xml::sax::XFastAttributeList> getFastAttributeList() const; /** Returns true, if the specified attribute is present. */ bool hasAttribute( sal_Int32 nAttrToken ) const; @@ -180,10 +181,12 @@ public: std::vector<sal_Int32> getTokenList(sal_Int32 nAttrToken) const; private: - css::uno::Reference< css::xml::sax::XFastAttributeList > - mxAttribs; - mutable sax_fastparser::FastAttributeList *mpAttribList; - sax_fastparser::FastAttributeList *getAttribList() const; + AttributeList(const AttributeList&) = delete; + AttributeList(AttributeList&&) = delete; + void operator=(const AttributeList&) = delete; + void operator=(AttributeList&&) = delete; + + rtl::Reference<sax_fastparser::FastAttributeList> mxAttribs; }; diff --git a/include/oox/token/tokenmap.hxx b/include/oox/token/tokenmap.hxx index 4358822c360f..3c0c50d5a013 100644 --- a/include/oox/token/tokenmap.hxx +++ b/include/oox/token/tokenmap.hxx @@ -35,70 +35,29 @@ namespace oox { -class TokenMap +namespace TokenMap { -public: - explicit TokenMap(); - ~TokenMap(); +/** Returns the token identifier for a UTF8 string passed in pToken */ +sal_Int32 getTokenFromUtf8(std::string_view token); - /** Returns the token identifier for the passed Unicode token name. */ - static sal_Int32 getTokenFromUnicode( std::u16string_view rUnicodeName ); - - /** Returns the UTF8 name of the passed token identifier as byte sequence. */ - css::uno::Sequence< sal_Int8 > const & - getUtf8TokenName( sal_Int32 nToken ) const - { - SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "oox", "Wrong nToken parameter"); - if (0 <= nToken && nToken < XML_TOKEN_COUNT) - return maTokenNames[ nToken ]; - return EMPTY_BYTE_SEQ; - } - - /** Returns the token identifier for the passed UTF8 token name. */ - sal_Int32 getTokenFromUtf8( - const css::uno::Sequence< sal_Int8 >& rUtf8Name ) const - { - return getTokenFromUTF8( reinterpret_cast< const char * >( - rUtf8Name.getConstArray() ), - rUtf8Name.getLength() ); - } - - /** Returns the token identifier for a UTF8 string passed in pToken */ - sal_Int32 getTokenFromUTF8( const char *pToken, sal_Int32 nLength ) const - { - // 50% of OOXML tokens are primarily 1 lower-case character, a-z - if( nLength == 1) - { - char c = pToken[0]; - if (c >= 'a' && c <= 'z') - return mnAlphaTokens[ c - 'a' ]; - } - return getTokenPerfectHash( pToken, nLength ); - } - - /** Returns the name of the passed token identifier as OUString. */ - OUString getUnicodeTokenName(sal_Int32 nToken) const - { - SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "oox", "Wrong nToken parameter"); - OUString const ret((0 <= nToken && nToken < XML_TOKEN_COUNT) - ? rtl::OUString(reinterpret_cast<const char*>(maTokenNames[nToken].getConstArray()), - maTokenNames[nToken].getLength(), RTL_TEXTENCODING_UTF8) - : OUString()); - return ret; - } +/** Returns the token identifier for the passed Unicode token name. */ +inline sal_Int32 getTokenFromUnicode(std::u16string_view rUnicodeName) +{ + return getTokenFromUtf8(OUStringToOString(rUnicodeName, RTL_TEXTENCODING_UTF8)); +} -private: - static sal_Int32 getTokenPerfectHash( const char *pToken, sal_Int32 nLength ); - static const css::uno::Sequence< sal_Int8 > EMPTY_BYTE_SEQ; +/** Returns the UTF8 name of the passed token identifier as byte sequence. */ +css::uno::Sequence<sal_Int8> const& getUtf8TokenName(sal_Int32 nToken); - std::vector< css::uno::Sequence< sal_Int8 > > - maTokenNames; - sal_Int32 mnAlphaTokens[26]; +/** Returns the name of the passed token identifier as OUString. */ +inline OUString getUnicodeTokenName(sal_Int32 nToken) +{ + auto name = getUtf8TokenName(nToken); + return OUString(reinterpret_cast<const char*>(name.getConstArray()), name.getLength(), + RTL_TEXTENCODING_UTF8); +} }; - -TokenMap& StaticTokenMap(); - } // namespace oox #endif diff --git a/include/sax/fastattribs.hxx b/include/sax/fastattribs.hxx index fb6f47eb7f9d..72eb9cf890d3 100644 --- a/include/sax/fastattribs.hxx +++ b/include/sax/fastattribs.hxx @@ -56,7 +56,7 @@ class SAX_DLLPUBLIC FastTokenHandlerBase : { public: virtual ~FastTokenHandlerBase(); - virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const = 0; + virtual sal_Int32 getTokenDirect(std::string_view token) const = 0; /** * Client method to attempt the use of this interface if possible. @@ -122,6 +122,7 @@ public: { return OStringToOUString(getAsViewByIndex(nTokenIndex), RTL_TEXTENCODING_UTF8); } + sal_Int32 getValueTokenByIndex(sal_Int32 nTokenIndex) const; // XFastAttributeList virtual sal_Bool SAL_CALL hasAttribute( ::sal_Int32 Token ) override; diff --git a/oox/qa/token/tokenmap-test.cxx b/oox/qa/token/tokenmap-test.cxx index e30b6aef806b..b8b29911c30f 100644 --- a/oox/qa/token/tokenmap-test.cxx +++ b/oox/qa/token/tokenmap-test.cxx @@ -30,9 +30,6 @@ public: CPPUNIT_TEST(test_roundTrip); CPPUNIT_TEST(test_roundTripUnicode); CPPUNIT_TEST_SUITE_END(); - -private: - TokenMap tokenMap; }; void TokenmapTest::test_roundTrip() @@ -40,10 +37,9 @@ void TokenmapTest::test_roundTrip() for ( sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken ) { // check that the getIdentifier <-> getToken roundtrip works - Sequence< sal_Int8 > rUtf8Name = tokenMap.getUtf8TokenName(nToken); - sal_Int32 ret = tokenMap.getTokenFromUTF8( - reinterpret_cast< const char * >(rUtf8Name.getConstArray()), - rUtf8Name.getLength() ); + Sequence< sal_Int8 > rUtf8Name = TokenMap::getUtf8TokenName(nToken); + sal_Int32 ret = TokenMap::getTokenFromUtf8(std::string_view( + reinterpret_cast<const char*>(rUtf8Name.getConstArray()), rUtf8Name.getLength())); CPPUNIT_ASSERT_EQUAL(ret, nToken); } } @@ -53,7 +49,7 @@ void TokenmapTest::test_roundTripUnicode() for (sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken) { // check that the getIdentifier <-> getToken roundtrip works for OUString - OUString sName = tokenMap.getUnicodeTokenName(nToken); + OUString sName = TokenMap::getUnicodeTokenName(nToken); sal_Int32 ret = oox::TokenMap::getTokenFromUnicode(sName); CPPUNIT_ASSERT_EQUAL(ret, nToken); } diff --git a/oox/source/core/fasttokenhandler.cxx b/oox/source/core/fasttokenhandler.cxx index 08531b16dc96..34c0405ee847 100644 --- a/oox/source/core/fasttokenhandler.cxx +++ b/oox/source/core/fasttokenhandler.cxx @@ -29,15 +29,6 @@ namespace oox::core { using namespace ::com::sun::star::uno; -FastTokenHandler::FastTokenHandler() : - mrTokenMap( StaticTokenMap() ) -{ -} - -FastTokenHandler::~FastTokenHandler() -{ -} - // XServiceInfo OUString SAL_CALL FastTokenHandler::getImplementationName() { @@ -57,17 +48,18 @@ Sequence< OUString > SAL_CALL FastTokenHandler::getSupportedServiceNames() Sequence< sal_Int8 > FastTokenHandler::getUTF8Identifier( sal_Int32 nToken ) { - return mrTokenMap.getUtf8TokenName( nToken ); + return TokenMap::getUtf8TokenName(nToken); } sal_Int32 FastTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& rIdentifier ) { - return mrTokenMap.getTokenFromUtf8( rIdentifier ); + return TokenMap::getTokenFromUtf8(std::string_view( + reinterpret_cast<const char*>(rIdentifier.getConstArray()), rIdentifier.getLength())); } -sal_Int32 FastTokenHandler::getTokenDirect( const char *pToken, sal_Int32 nLength ) const +sal_Int32 FastTokenHandler::getTokenDirect(std::string_view token) const { - return mrTokenMap.getTokenFromUTF8( pToken, nLength ); + return TokenMap::getTokenFromUtf8(token); } } // namespace oox::core @@ -76,7 +68,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* com_sun_star_comp_oox_core_FastTokenHandler_get_implementation( uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) { - return cppu::acquire(new oox::core::FastTokenHandler()); + return cppu::acquire(new oox::core::FastTokenHandler); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx index 5fa217d42044..1f164aa6ab42 100644 --- a/oox/source/crypto/AgileEngine.cxx +++ b/oox/source/crypto/AgileEngine.cxx @@ -65,7 +65,7 @@ public: return Sequence<sal_Int8>(); } - virtual sal_Int32 getTokenDirect( const char * /* pToken */, sal_Int32 /* nLength */ ) const override + virtual sal_Int32 getTokenDirect(std::string_view /* token */) const override { return -1; } diff --git a/oox/source/drawingml/customshapeproperties.cxx b/oox/source/drawingml/customshapeproperties.cxx index 447f5262b13f..1b069f8939d7 100644 --- a/oox/source/drawingml/customshapeproperties.cxx +++ b/oox/source/drawingml/customshapeproperties.cxx @@ -117,7 +117,7 @@ CustomShapeProperties::CustomShapeProperties() OUString CustomShapeProperties::getShapePresetTypeName() const { - return StaticTokenMap().getUnicodeTokenName(mnShapePresetType); + return TokenMap::getUnicodeTokenName(mnShapePresetType); } bool CustomShapeProperties::representsDefaultShape() const diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx index 21948145e1d2..3a10597996ba 100644 --- a/oox/source/drawingml/table/tablecell.cxx +++ b/oox/source/drawingml/table/tablecell.cxx @@ -605,7 +605,7 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons else if ( getVertToken() != XML_horz && getVertToken() != XML_eaVert ) { // put the vert value in the grab bag for roundtrip - const OUString aTokenName(StaticTokenMap().getUnicodeTokenName(getVertToken())); + const OUString aTokenName(TokenMap::getUnicodeTokenName(getVertToken())); Sequence<PropertyValue> aGrabBag; xPropSet->getPropertyValue(u"CellInteropGrabBag"_ustr) >>= aGrabBag; PropertyValue aPropertyValue = comphelper::makePropertyValue(u"mso-tcPr-vert-value"_ustr, aTokenName); diff --git a/oox/source/helper/attributelist.cxx b/oox/source/helper/attributelist.cxx index 488105d4eed1..dc5c54c14d3d 100644 --- a/oox/source/helper/attributelist.cxx +++ b/oox/source/helper/attributelist.cxx @@ -62,6 +62,19 @@ sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd ) return *rpcStr++; } +template<typename C> sal_uInt32 decodeUnsigned_impl(std::basic_string_view<C> rValue) +{ + return getLimitedValue<sal_uInt32, sal_Int64>(o3tl::toInt64(rValue), 0, SAL_MAX_UINT32); +} + +template <typename C> sal_Int32 decodeIntegerHex_impl(std::basic_string_view<C> rValue) +{ + // It looks like all Office Open XML attributes containing hexadecimal + // values are based on xsd:hexBinary and so use an unsigned representation: + return static_cast<sal_Int32>(o3tl::toUInt32(rValue, 16)); + //TODO: Change this function to return sal_uInt32 and get rid of the + // cast, but that will have a ripple effect +} } // namespace #define STRING_TO_TOKEN(color) if (sColorName == u"" #color) return XML_##color @@ -98,12 +111,13 @@ OUString AttributeConversion::decodeXString( const OUString& rValue ) // string shorter than one encoded character - no need to decode if( rValue.getLength() < XSTRING_ENCCHAR_LEN ) return rValue; - if (rValue.indexOf(u"_x") == -1) + sal_Int32 index = rValue.indexOf(u"_x"); + if (index == -1) return rValue; - OUStringBuffer aBuffer; - const sal_Unicode* pcStr = rValue.getStr(); - const sal_Unicode* pcEnd = pcStr + rValue.getLength(); + OUStringBuffer aBuffer(rValue.subView(0, index)); + const sal_Unicode* pcStr = rValue.getStr() + index; + const sal_Unicode* pcEnd = rValue.getStr() + rValue.getLength(); while( pcStr < pcEnd ) aBuffer.append( lclGetXChar( pcStr, pcEnd ) ); return comphelper::string::sanitizeStringSurrogates(aBuffer.makeStringAndClear()); @@ -116,7 +130,7 @@ sal_Int32 AttributeConversion::decodeInteger( std::u16string_view rValue ) sal_uInt32 AttributeConversion::decodeUnsigned( std::u16string_view rValue ) { - return getLimitedValue< sal_uInt32, sal_Int64 >( o3tl::toInt64(rValue), 0, SAL_MAX_UINT32 ); + return decodeUnsigned_impl(rValue); } sal_Int64 AttributeConversion::decodeHyper( std::u16string_view rValue ) @@ -126,27 +140,19 @@ sal_Int64 AttributeConversion::decodeHyper( std::u16string_view rValue ) sal_Int32 AttributeConversion::decodeIntegerHex( std::u16string_view rValue ) { - // It looks like all Office Open XML attributes containing hexadecimal - // values are based on xsd:hexBinary and so use an unsigned representation: - return static_cast< sal_Int32 >(o3tl::toUInt32(rValue, 16)); - //TODO: Change this function to return sal_uInt32 and get rid of the - // cast, but that will have a ripple effect + return decodeIntegerHex_impl(rValue); } AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) : - mxAttribs( rxAttribs ), - mpAttribList( nullptr ) + mxAttribs(&sax_fastparser::castToFastAttributeList(rxAttribs)) { - OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" ); } -sax_fastparser::FastAttributeList *AttributeList::getAttribList() const +AttributeList::~AttributeList() = default; + +css::uno::Reference<css::xml::sax::XFastAttributeList> AttributeList::getFastAttributeList() const { - if( mpAttribList == nullptr ) - { - mpAttribList = &sax_fastparser::castToFastAttributeList( mxAttribs ); - } - return mpAttribList; + return mxAttribs; } bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const @@ -173,46 +179,43 @@ std::optional< sal_Int32 > AttributeList::getToken( sal_Int32 nAttrToken ) const std::optional< OUString > AttributeList::getString( sal_Int32 nAttrToken ) const { // check if the attribute exists (empty string may be different to missing attribute) - if( mxAttribs->hasAttribute( nAttrToken ) ) - return std::optional< OUString >( mxAttribs->getOptionalValue( nAttrToken ) ); + if (sal_Int32 index = mxAttribs->getAttributeIndex(nAttrToken); index >= 0) + return mxAttribs->getValueByIndex(index); return std::optional< OUString >(); } OUString AttributeList::getStringDefaulted( sal_Int32 nAttrToken ) const { - // check if the attribute exists (empty string may be different to missing attribute) - if( mxAttribs->hasAttribute( nAttrToken ) ) - return mxAttribs->getOptionalValue( nAttrToken ); - return OUString(); + return mxAttribs->getOptionalValue(nAttrToken); } std::optional< OUString > AttributeList::getXString( sal_Int32 nAttrToken ) const { // check if the attribute exists (empty string may be different to missing attribute) - if( mxAttribs->hasAttribute( nAttrToken ) ) - return std::optional< OUString >( AttributeConversion::decodeXString( mxAttribs->getOptionalValue( nAttrToken ) ) ); + if (sal_Int32 index = mxAttribs->getAttributeIndex(nAttrToken); index >= 0) + return AttributeConversion::decodeXString(mxAttribs->getValueByIndex(index)); return std::optional< OUString >(); } std::optional< double > AttributeList::getDouble( sal_Int32 nAttrToken ) const { double nValue; - bool bValid = getAttribList()->getAsDouble( nAttrToken, nValue ); + bool bValid = mxAttribs->getAsDouble(nAttrToken, nValue); return bValid ? std::optional< double >( nValue ) : std::optional< double >(); } std::optional< sal_Int32 > AttributeList::getInteger( sal_Int32 nAttrToken ) const { sal_Int32 nValue; - bool bValid = getAttribList()->getAsInteger( nAttrToken, nValue ); + bool bValid = mxAttribs->getAsInteger(nAttrToken, nValue); return bValid ? std::optional< sal_Int32 >( nValue ) : std::optional< sal_Int32 >(); } std::optional< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nAttrToken ) const { - OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); - bool bValid = !aValue.isEmpty(); - return bValid ? std::optional< sal_uInt32 >( AttributeConversion::decodeUnsigned( aValue ) ) : std::optional< sal_uInt32 >(); + std::string_view aValue = getView(nAttrToken); + bool bValid = !aValue.empty(); + return bValid ? std::optional< sal_uInt32 >( decodeUnsigned_impl( aValue ) ) : std::optional< sal_uInt32 >(); } std::optional< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const @@ -224,19 +227,19 @@ std::optional< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const std::optional< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const { - OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); - bool bValid = !aValue.isEmpty(); - return bValid ? std::optional< sal_Int32 >( AttributeConversion::decodeIntegerHex( aValue ) ) : std::optional< sal_Int32 >(); + std::string_view aValue = getView(nAttrToken); + bool bValid = !aValue.empty(); + return bValid ? std::optional< sal_Int32 >( decodeIntegerHex_impl( aValue ) ) : std::optional< sal_Int32 >(); } std::optional< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const { - std::string_view pAttr; + sal_Int32 index = mxAttribs->getAttributeIndex(nAttrToken); + if (index == -1) + return std::optional< bool >(); + std::string_view pAttr = mxAttribs->getAsViewByIndex(index); // catch the common cases as quickly as possible first - bool bHasAttr = getAttribList()->getAsView( nAttrToken, pAttr ); - if( !bHasAttr ) - return std::optional< bool >(); if( pAttr == "false" ) return std::optional< bool >( false ); if( pAttr == "true" ) @@ -245,7 +248,7 @@ std::optional< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const // now for all the crazy stuff // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0" - switch( getToken( nAttrToken, XML_TOKEN_INVALID ) ) + switch (mxAttribs->getValueTokenByIndex(index)) { case XML_t: return std::optional< bool >( true ); // used in VML case XML_true: return std::optional< bool >( true ); @@ -254,8 +257,7 @@ std::optional< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const case XML_false: return std::optional< bool >( false ); case XML_off: return std::optional< bool >( false ); } - std::optional< sal_Int32 > onValue = getInteger( nAttrToken ); - return onValue.has_value() ? std::optional< bool >( onValue.value() != 0 ) : std::optional< bool >(); + return std::optional<bool>(o3tl::toInt32(pAttr) != 0); } std::optional< util::DateTime > AttributeList::getDateTime( sal_Int32 nAttrToken ) const @@ -288,17 +290,8 @@ sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) co OUString AttributeList::getString( sal_Int32 nAttrToken, const OUString& rDefault ) const { - // try to avoid slow exception throw/catch if we can - if (rDefault.isEmpty()) - return mxAttribs->getOptionalValue( nAttrToken ); - - try - { - return mxAttribs->getValue( nAttrToken ); - } - catch( Exception& ) - { - } + if (sal_Int32 index = mxAttribs->getAttributeIndex(nAttrToken); index >= 0) + return mxAttribs->getValueByIndex(index); return rDefault; } @@ -310,7 +303,7 @@ OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefau std::string_view AttributeList::getView( sal_Int32 nAttrToken ) const { std::string_view p; - getAttribList()->getAsView(nAttrToken, p); + mxAttribs->getAsView(nAttrToken, p); return p; } @@ -357,12 +350,9 @@ util::DateTime AttributeList::getDateTime( sal_Int32 nAttrToken, const util::Dat std::vector<sal_Int32> AttributeList::getTokenList(sal_Int32 nAttrToken) const { std::vector<sal_Int32> aValues; - OUString sValue = getString(nAttrToken, u""_ustr); - sal_Int32 nIndex = 0; - do - { - aValues.push_back(AttributeConversion::decodeToken(o3tl::getToken(sValue, 0, ' ', nIndex))); - } while (nIndex >= 0); + if (std::string_view sValue = getView(nAttrToken); !sValue.empty()) + for (size_t index = 0; index != std::string_view::npos;) + aValues.push_back(TokenMap::getTokenFromUtf8(o3tl::getToken(sValue, ' ', index))); return aValues; } diff --git a/oox/source/mathml/importutils.cxx b/oox/source/mathml/importutils.cxx index 7aa8a1a924e5..4f6c243b9970 100644 --- a/oox/source/mathml/importutils.cxx +++ b/oox/source/mathml/importutils.cxx @@ -52,7 +52,7 @@ AttributeListBuilder::AttributeListBuilder( const uno::Reference< xml::sax::XFas OString tokenToString( int token ) { - uno::Sequence< sal_Int8 > const & aTokenNameSeq = StaticTokenMap().getUtf8TokenName( token & TOKEN_MASK ); + uno::Sequence<sal_Int8> const& aTokenNameSeq = TokenMap::getUtf8TokenName(token & TOKEN_MASK); OString tokenname( reinterpret_cast< const char* >( aTokenNameSeq.getConstArray() ), aTokenNameSeq.getLength() ); if( tokenname.isEmpty()) tokenname = "???"_ostr; diff --git a/oox/source/token/tokenmap.cxx b/oox/source/token/tokenmap.cxx index 1e51116192c6..dcd1481cbe15 100644 --- a/oox/source/token/tokenmap.cxx +++ b/oox/source/token/tokenmap.cxx @@ -17,6 +17,10 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + +#include <array> + #include <oox/token/tokenmap.hxx> #include <string.h> @@ -25,8 +29,6 @@ namespace oox { -using ::com::sun::star::uno::Sequence; - namespace { // include auto-generated Perfect_Hash #if defined __clang__ @@ -42,55 +44,61 @@ namespace { #endif } // namespace -const css::uno::Sequence< sal_Int8 > TokenMap::EMPTY_BYTE_SEQ; +static sal_Int32 getTokenPerfectHash(const char* pStr, sal_Int32 nLength) +{ + const struct xmltoken* pToken = Perfect_Hash::in_word_set( pStr, nLength ); + return pToken ? pToken->nToken : XML_TOKEN_INVALID; +} -TokenMap::TokenMap() : - maTokenNames( static_cast< size_t >( XML_TOKEN_COUNT ) ) +css::uno::Sequence<sal_Int8> const& TokenMap::getUtf8TokenName(sal_Int32 nToken) { - static const char* sppcTokenNames[] = + static const auto saTokenNames = []() { + static constexpr std::string_view sppcTokenNames[] = { // include auto-generated C array with token names as C strings #include <tokennames.inc> - "" - }; - - const char* const* ppcTokenName = sppcTokenNames; - for (auto & tokenName : maTokenNames) - { - OString aUtf8Token( *ppcTokenName ); - tokenName = Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUtf8Token.getStr() ), aUtf8Token.getLength() ); - ++ppcTokenName; - } + }; + static_assert(std::size(sppcTokenNames) == XML_TOKEN_COUNT); - for (unsigned char c = 'a'; c <= 'z'; c++) - { - const struct xmltoken* pToken = Perfect_Hash::in_word_set( - reinterpret_cast< const char* >( &c ), 1 ); - mnAlphaTokens[ c - 'a' ] = pToken ? pToken->nToken : XML_TOKEN_INVALID; - } -} + std::vector<css::uno::Sequence<sal_Int8>> aTokenNames; + aTokenNames.reserve(std::size(sppcTokenNames)); + std::transform( + std::begin(sppcTokenNames), std::end(sppcTokenNames), std::back_inserter(aTokenNames), + [](auto aUtf8Token) + { + return css::uno::Sequence<sal_Int8>( + reinterpret_cast<const sal_Int8*>(aUtf8Token.data()), aUtf8Token.size()); + }); + return aTokenNames; + }(); -TokenMap::~TokenMap() -{ + SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "oox", "Wrong nToken parameter"); + if (0 <= nToken && nToken < XML_TOKEN_COUNT) + return saTokenNames[nToken]; + static const css::uno::Sequence<sal_Int8> EMPTY_BYTE_SEQ; + return EMPTY_BYTE_SEQ; } -sal_Int32 TokenMap::getTokenFromUnicode( std::u16string_view rUnicodeName ) -{ - OString aUtf8Name = OUStringToOString( rUnicodeName, RTL_TEXTENCODING_UTF8 ); - const struct xmltoken* pToken = Perfect_Hash::in_word_set( aUtf8Name.getStr(), aUtf8Name.getLength() ); - return pToken ? pToken->nToken : XML_TOKEN_INVALID; -} -sal_Int32 TokenMap::getTokenPerfectHash( const char *pStr, sal_Int32 nLength ) +/** Returns the token identifier for a UTF8 string passed in pToken */ +sal_Int32 TokenMap::getTokenFromUtf8(std::string_view token) { - const struct xmltoken* pToken = Perfect_Hash::in_word_set( pStr, nLength ); - return pToken ? pToken->nToken : XML_TOKEN_INVALID; -} + static const auto snAlphaTokens = []() + { + std::array<sal_Int32, 26> nAlphaTokens{}; + for (char c = 'a'; c <= 'z'; c++) + nAlphaTokens[c - 'a'] = getTokenPerfectHash(&c, 1); + return nAlphaTokens; + }(); -TokenMap& StaticTokenMap() -{ - static TokenMap SINGLETON; - return SINGLETON; + // 50% of OOXML tokens are primarily 1 lower-case character, a-z + if (token.size() == 1) + { + char c = token[0]; + if (c >= 'a' && c <= 'z') + return snAlphaTokens[c - 'a']; + } + return getTokenPerfectHash(token.data(), token.size()); } } // namespace oox diff --git a/sax/qa/cppunit/parser.cxx b/sax/qa/cppunit/parser.cxx index 670c1afa9277..288a91eefda0 100644 --- a/sax/qa/cppunit/parser.cxx +++ b/sax/qa/cppunit/parser.cxx @@ -37,7 +37,7 @@ public: CPPUNIT_ASSERT_MESSAGE( "getUTF8Identifier: unexpected call", false ); return uno::Sequence<sal_Int8>(); } - virtual sal_Int32 getTokenDirect( const char * /* pToken */, sal_Int32 /* nLength */ ) const override + virtual sal_Int32 getTokenDirect(std::string_view /* token */) const override { return -1; } diff --git a/sax/qa/cppunit/xmlimport.cxx b/sax/qa/cppunit/xmlimport.cxx index 963fa97f6893..18f8c9a21112 100644 --- a/sax/qa/cppunit/xmlimport.cxx +++ b/sax/qa/cppunit/xmlimport.cxx @@ -262,7 +262,7 @@ public: virtual Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 nToken ) override; virtual sal_Int32 SAL_CALL getTokenFromUTF8( const css::uno::Sequence< sal_Int8 >& Identifier ) override; //FastTokenHandlerBase - virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const override; + virtual sal_Int32 getTokenDirect(std::string_view sToken) const override; }; const std::string_view DummyTokenHandler::tokens[] = { @@ -304,13 +304,12 @@ Sequence< sal_Int8 > DummyTokenHandler::getUTF8Identifier( sal_Int32 nToken ) sal_Int32 DummyTokenHandler::getTokenFromUTF8( const uno::Sequence< sal_Int8 >& rIdentifier ) { - return getTokenDirect( reinterpret_cast< const char* >( - rIdentifier.getConstArray() ), rIdentifier.getLength() ); + return getTokenDirect(std::string_view( + reinterpret_cast<const char*>(rIdentifier.getConstArray()), rIdentifier.getLength())); } -sal_Int32 DummyTokenHandler::getTokenDirect( const char* pToken, sal_Int32 nLength ) const +sal_Int32 DummyTokenHandler::getTokenDirect(std::string_view sToken) const { - std::string_view sToken( pToken, nLength ); for( size_t i = 0; i < std::size(tokens); i++ ) { if ( tokens[i] == sToken ) diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx index 45e2e9c5ebba..ceda451bafc5 100644 --- a/sax/source/tools/fastattribs.cxx +++ b/sax/source/tools/fastattribs.cxx @@ -172,9 +172,7 @@ 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, - getAsViewByIndex(i) ); + return getValueTokenByIndex(i); throw SAXException("FastAttributeList::getValueToken: unknown token " + OUString::number(Token), nullptr, Any()); } @@ -183,9 +181,7 @@ sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int { for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i) if (maAttributeTokens[i] == Token) - return FastTokenHandlerBase::getTokenFromChars( - mpTokenHandler, - getAsViewByIndex(i) ); + return getValueTokenByIndex(i); return Default; } @@ -246,6 +242,12 @@ OUString FastAttributeList::getOptionalValue( ::sal_Int32 Token ) return OUString(); } + +sal_Int32 FastAttributeList::getValueTokenByIndex(sal_Int32 nTokenIndex) const +{ + return FastTokenHandlerBase::getTokenFromChars(mpTokenHandler, getAsViewByIndex(nTokenIndex)); +} + Sequence< Attribute > FastAttributeList::getUnknownAttributes( ) { auto nSize = maUnknownAttributes.size(); @@ -282,7 +284,7 @@ sal_Int32 FastTokenHandlerBase::getTokenFromChars( const FastTokenHandlerBase *pTokenHandler, std::string_view token ) { - return pTokenHandler->getTokenDirect(token.data(), token.size()); + return pTokenHandler->getTokenDirect(token); } } diff --git a/sw/source/core/inc/SwXMLBlockImport.hxx b/sw/source/core/inc/SwXMLBlockImport.hxx index 821033c1e1e5..8932236e327d 100644 --- a/sw/source/core/inc/SwXMLBlockImport.hxx +++ b/sw/source/core/inc/SwXMLBlockImport.hxx @@ -94,7 +94,7 @@ public: css::uno::Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 Token ) override; //Much fast direct C++ shortcut to the method that matters - virtual sal_Int32 getTokenDirect( const char *pTag, sal_Int32 nLength ) const override; + virtual sal_Int32 getTokenDirect(std::string_view token) const override; }; enum SwXMLBlockListToken : sal_Int32 @@ -120,7 +120,7 @@ public: css::uno::Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 Token ) override; //Much fast direct C++ shortcut to the method that matters - virtual sal_Int32 getTokenDirect( const char *pTag, sal_Int32 nLength ) const override; + virtual sal_Int32 getTokenDirect(std::string_view token) const override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/swg/SwXMLBlockImport.cxx b/sw/source/core/swg/SwXMLBlockImport.cxx index 76031dfb11ce..4f19f72510f3 100644 --- a/sw/source/core/swg/SwXMLBlockImport.cxx +++ b/sw/source/core/swg/SwXMLBlockImport.cxx @@ -127,7 +127,7 @@ SwXMLTextBlockTokenHandler::~SwXMLTextBlockTokenHandler() sal_Int32 SAL_CALL SwXMLTextBlockTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& Identifier ) { - return getTokenDirect( reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength() ); + return getTokenDirect( std::string_view(reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength()) ); } Sequence< sal_Int8 > SAL_CALL SwXMLTextBlockTokenHandler::getUTF8Identifier( sal_Int32 ) @@ -135,11 +135,9 @@ Sequence< sal_Int8 > SAL_CALL SwXMLTextBlockTokenHandler::getUTF8Identifier( sal return Sequence< sal_Int8 >(); } -sal_Int32 SwXMLTextBlockTokenHandler::getTokenDirect( const char *pTag, sal_Int32 nLength ) const +sal_Int32 SwXMLTextBlockTokenHandler::getTokenDirect(std::string_view token) const { - if( !nLength ) - nLength = strlen( pTag ); - const struct xmltoken* pToken = TextBlockTokens::in_word_set( pTag, nLength ); + const struct xmltoken* pToken = TextBlockTokens::in_word_set(token.data(), token.size()); return pToken ? pToken->nToken : XML_TOKEN_INVALID; } @@ -153,7 +151,7 @@ SwXMLBlockListTokenHandler::~SwXMLBlockListTokenHandler() sal_Int32 SAL_CALL SwXMLBlockListTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& Identifier ) { - return getTokenDirect( reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength() ); + return getTokenDirect( std::string_view(reinterpret_cast< const char* >( Identifier.getConstArray() ), Identifier.getLength()) ); } Sequence< sal_Int8 > SAL_CALL SwXMLBlockListTokenHandler::getUTF8Identifier( sal_Int32 ) @@ -161,11 +159,9 @@ Sequence< sal_Int8 > SAL_CALL SwXMLBlockListTokenHandler::getUTF8Identifier( sal return Sequence< sal_Int8 >(); } -sal_Int32 SwXMLBlockListTokenHandler::getTokenDirect( const char *pTag, sal_Int32 nLength ) const +sal_Int32 SwXMLBlockListTokenHandler::getTokenDirect(std::string_view token) const { - if( !nLength ) - nLength = strlen( pTag ); - const struct xmltoken* pToken = BlockListTokens::in_word_set( pTag, nLength ); + const struct xmltoken* pToken = BlockListTokens::in_word_set(token.data(), token.size()); return pToken ? pToken->nToken : XML_TOKEN_INVALID; } diff --git a/sw/source/writerfilter/ooxml/OOXMLStreamImpl.cxx b/sw/source/writerfilter/ooxml/OOXMLStreamImpl.cxx index 6ca6bb85a10b..ed9fbcfbeddd 100644 --- a/sw/source/writerfilter/ooxml/OOXMLStreamImpl.cxx +++ b/sw/source/writerfilter/ooxml/OOXMLStreamImpl.cxx @@ -394,7 +394,7 @@ uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext() uno::Reference <xml::sax::XFastTokenHandler> OOXMLStreamImpl::getFastTokenHandler() { if (! mxFastTokenHandler.is()) - mxFastTokenHandler.set(new oox::core::FastTokenHandler()); + mxFastTokenHandler.set(new oox::core::FastTokenHandler); return mxFastTokenHandler; } diff --git a/unoxml/qa/unit/domtest.cxx b/unoxml/qa/unit/domtest.cxx index d96b149a03fd..5cc4235c8bbd 100644 --- a/unoxml/qa/unit/domtest.cxx +++ b/unoxml/qa/unit/domtest.cxx @@ -183,7 +183,7 @@ struct TokenHandler : public sax_fastparser::FastTokenHandlerBase return uno::Sequence<sal_Int8>(); } - virtual sal_Int32 getTokenDirect( const char * /* pToken */, sal_Int32 /* nLength */ ) const override + virtual sal_Int32 getTokenDirect( std::string_view /* token */ ) const override { return -1; } diff --git a/xmloff/inc/fasttokenhandler.hxx b/xmloff/inc/fasttokenhandler.hxx index ed64c6938065..3654ada39888 100644 --- a/xmloff/inc/fasttokenhandler.hxx +++ b/xmloff/inc/fasttokenhandler.hxx @@ -15,72 +15,29 @@ namespace xmloff::token { -class TokenMap +namespace TokenMap { -public: - explicit TokenMap(); - ~TokenMap(); - - /** Returns the UTF-8 name of the passed token identifier as byte sequence. */ - css::uno::Sequence< sal_Int8 > const & getUtf8TokenName( sal_Int32 nToken ) const - { - SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "xmloff", "Wrong nToken parameter"); - if( 0 <= nToken && nToken < XML_TOKEN_COUNT ) - return maTokenNamesUtf8[ nToken ]; - return EMPTY_BYTE_SEQ; - } - - const OUString& getTokenName( sal_Int32 nToken ) const - { - SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "xmloff", "Wrong nToken parameter"); - if( 0 <= nToken && nToken < XML_TOKEN_COUNT ) - return maTokenNames[ nToken ]; - return EMPTY_STRING; - } - - /** Returns the token identifier for the passed UTF-8 token name. */ - static sal_Int32 getTokenFromUtf8( const css::uno::Sequence< sal_Int8 >& rUtf8Name ) - { - return getTokenFromUTF8( reinterpret_cast< const char* >( - rUtf8Name.getConstArray() ), rUtf8Name.getLength() ); - } - - /** Returns the token identifier for a UTF-8 string */ - static sal_Int32 getTokenFromUTF8( const char *pToken, sal_Int32 nLength ) - { - return getTokenPerfectHash( pToken, nLength ); - } +/** Returns the UTF-8 name of the passed token identifier as byte sequence. */ +css::uno::Sequence<sal_Int8> const& getUtf8TokenName(sal_Int32 nToken); -private: - static sal_Int32 getTokenPerfectHash( const char *pToken, sal_Int32 nLength ); - - std::vector< css::uno::Sequence< sal_Int8 > > maTokenNamesUtf8; - std::vector< OUString > maTokenNames; - - static const css::uno::Sequence< sal_Int8 > EMPTY_BYTE_SEQ; - static const OUString EMPTY_STRING; +/** Returns the token identifier for a UTF-8 string */ +sal_Int32 getTokenFromUtf8(std::string_view token); }; -TokenMap& StaticTokenMap(); - class FastTokenHandler final : public sax_fastparser::FastTokenHandlerBase { public: - explicit FastTokenHandler(); - virtual ~FastTokenHandler() override; + explicit FastTokenHandler() = default; // XFastTokenHandler virtual css::uno::Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 nToken ) override; virtual sal_Int32 SAL_CALL getTokenFromUTF8( const css::uno::Sequence< sal_Int8 >& Identifier ) override; - const OUString & getIdentifier( sal_Int32 nToken ) const; + static const OUString& getIdentifier(sal_Int32 nToken); // Much faster direct C++ shortcut to the method that matters - virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const override; - -private: - TokenMap& mrTokenMap; + virtual sal_Int32 getTokenDirect(std::string_view token) const override; }; } // namespace xmloff::token diff --git a/xmloff/qa/unit/tokenmap-test.cxx b/xmloff/qa/unit/tokenmap-test.cxx index 395237b8adb1..a3ef3f5da9eb 100644 --- a/xmloff/qa/unit/tokenmap-test.cxx +++ b/xmloff/qa/unit/tokenmap-test.cxx @@ -23,9 +23,6 @@ namespace xmloff { class TokenmapTest: public CppUnit::TestFixture { public: - - TokenmapTest(); - void test_roundTrip(); void test_listEquality(); @@ -35,25 +32,18 @@ public: CPPUNIT_TEST(test_listEquality); CPPUNIT_TEST_SUITE_END(); - -private: - std::unique_ptr<token::TokenMap> pTokenMap; }; -TokenmapTest::TokenmapTest() : pTokenMap(new token::TokenMap) -{ -} - void TokenmapTest::test_roundTrip() { for ( sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken ) { // check that the getIdentifier <-> getToken roundtrip works - Sequence< sal_Int8 > rUtf8Name = pTokenMap->getUtf8TokenName(nToken); + Sequence< sal_Int8 > rUtf8Name = token::TokenMap::getUtf8TokenName(nToken); CPPUNIT_ASSERT_MESSAGE("Token name sequence should not be empty", rUtf8Name.getLength()); const char* pChar = reinterpret_cast< const char * >(rUtf8Name.getConstArray()); CPPUNIT_ASSERT_MESSAGE("Token name sequence array pointer failed", pChar); - sal_Int32 ret = token::TokenMap::getTokenFromUTF8( pChar, rUtf8Name.getLength() ); + sal_Int32 ret = token::TokenMap::getTokenFromUtf8( std::string_view(pChar, rUtf8Name.getLength()) ); CPPUNIT_ASSERT_EQUAL_MESSAGE("No roundtrip for token", ret, nToken); } } @@ -65,7 +55,7 @@ void TokenmapTest::test_listEquality() // aTokenList in xmloff/source/core/xmltoken.cxx, and xmloff/source/token/tokens.txt for ( sal_Int32 nToken = 0; nToken < XML_TOKEN_COUNT; ++nToken ) { - Sequence< sal_Int8 > rUtf8Name = pTokenMap->getUtf8TokenName(nToken); + Sequence<sal_Int8> rUtf8Name = token::TokenMap::getUtf8TokenName(nToken); const OUString& rName = OUString( reinterpret_cast< const char* >( rUtf8Name.getConstArray() ), rUtf8Name.getLength(), RTL_TEXTENCODING_UTF8 ); if ( rName.endsWith("_DUMMY") ) @@ -78,7 +68,7 @@ void TokenmapTest::test_listEquality() nToken < xmloff::token::XMLTokenEnum::XML_TOKEN_END; ++nToken ) { const OUString& rTokenName = GetXMLToken( static_cast<xmloff::token::XMLTokenEnum>(nToken) ); - Sequence< sal_Int8 > rUtf8Name = pTokenMap->getUtf8TokenName(nToken); + Sequence<sal_Int8> rUtf8Name = token::TokenMap::getUtf8TokenName(nToken); const OUString& rName = OUString( reinterpret_cast< const char* >( rUtf8Name.getConstArray() ), rUtf8Name.getLength(), RTL_TEXTENCODING_UTF8 ); if ( !rName.endsWith("_DUMMY") ) diff --git a/xmloff/source/core/fasttokenhandler.cxx b/xmloff/source/core/fasttokenhandler.cxx index b82ee67bfe54..e7b2dc7e017e 100644 --- a/xmloff/source/core/fasttokenhandler.cxx +++ b/xmloff/source/core/fasttokenhandler.cxx @@ -32,76 +32,73 @@ namespace token { using namespace css; -TokenMap& StaticTokenMap() +static sal_Int32 getTokenPerfectHash(const char* pStr, sal_Int32 nLength) { - static TokenMap SINGLETON; - return SINGLETON; + const struct xmltoken* pToken = Perfect_Hash::in_word_set(pStr, nLength); + return pToken ? pToken->nToken : xmloff::XML_TOKEN_INVALID; } -const css::uno::Sequence< sal_Int8 > TokenMap::EMPTY_BYTE_SEQ; -const OUString TokenMap::EMPTY_STRING; - -TokenMap::TokenMap() : - maTokenNamesUtf8( static_cast< size_t >( XML_TOKEN_COUNT ) ), - maTokenNames( static_cast< size_t >( XML_TOKEN_COUNT ) ) +static const std::pair<css::uno::Sequence<sal_Int8>, OUString>& getNames(sal_Int32 nToken) { - static const char* sppcTokenNames[] = + static const auto saTokenNames = []() { + static constexpr std::string_view sppcTokenNames[] = { #include <tokennames.inc> - "" - }; - - const char* const* ppcTokenName = sppcTokenNames; - int i = 0; - for( auto& rTokenName : maTokenNamesUtf8 ) - { - std::string_view pStr = *ppcTokenName; - rTokenName = uno::Sequence< sal_Int8 >( - reinterpret_cast< const sal_Int8* >( pStr.data() ), pStr.length() ); - maTokenNames[i++] = OStringToOUString( pStr, RTL_TEXTENCODING_UTF8 ); - ++ppcTokenName; - } -} - -TokenMap::~TokenMap() -{ -} - -sal_Int32 TokenMap::getTokenPerfectHash( const char *pStr, sal_Int32 nLength ) -{ - const struct xmltoken *pToken = Perfect_Hash::in_word_set( pStr, nLength ); - return pToken ? pToken->nToken : xmloff::XML_TOKEN_INVALID; + }; + static_assert(std::size(sppcTokenNames) == XML_TOKEN_COUNT); + + std::vector<std::pair<css::uno::Sequence<sal_Int8>, OUString>> names; + names.reserve(std::size(sppcTokenNames)); + std::transform(std::begin(sppcTokenNames), std::end(sppcTokenNames), + std::back_inserter(names), + [](auto token) + { + return std::make_pair( + css::uno::Sequence<sal_Int8>( + reinterpret_cast<const sal_Int8*>(token.data()), token.size()), + OStringToOUString(token, RTL_TEXTENCODING_UTF8)); + }); + return names; + }(); + + SAL_WARN_IF(nToken < 0 || nToken >= XML_TOKEN_COUNT, "xmloff", "Wrong nToken parameter"); + if (0 <= nToken && nToken < XML_TOKEN_COUNT) + return saTokenNames[nToken]; + static const std::pair<css::uno::Sequence<sal_Int8>, OUString> EMPTY; + return EMPTY; } -FastTokenHandler::FastTokenHandler() : - mrTokenMap( StaticTokenMap() ) +css::uno::Sequence<sal_Int8> const& TokenMap::getUtf8TokenName(sal_Int32 nToken) { + return getNames(nToken).first; } -FastTokenHandler::~FastTokenHandler() +sal_Int32 TokenMap::getTokenFromUtf8(std::string_view token) { + return getTokenPerfectHash(token.data(), token.size()); } // XFastTokenHandler uno::Sequence< sal_Int8 > FastTokenHandler::getUTF8Identifier( sal_Int32 nToken ) { - return mrTokenMap.getUtf8TokenName( nToken ); + return TokenMap::getUtf8TokenName( nToken ); } -const OUString& FastTokenHandler::getIdentifier( sal_Int32 nToken ) const +const OUString& FastTokenHandler::getIdentifier(sal_Int32 nToken) { - return mrTokenMap.getTokenName( nToken ); + return getNames(nToken).second; } sal_Int32 FastTokenHandler::getTokenFromUTF8( const uno::Sequence< sal_Int8 >& rIdentifier ) { - return TokenMap::getTokenFromUtf8( rIdentifier ); + return TokenMap::getTokenFromUtf8(std::string_view( + reinterpret_cast<const char*>(rIdentifier.getConstArray()), rIdentifier.getLength())); } // Much faster direct C++ shortcut -sal_Int32 FastTokenHandler::getTokenDirect( const char* pToken, sal_Int32 nLength ) const +sal_Int32 FastTokenHandler::getTokenDirect(std::string_view token) const { - return TokenMap::getTokenFromUTF8( pToken, nLength ); + return TokenMap::getTokenFromUtf8(token); } } // namespace token diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 016ca91dc014..bcac90108c28 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -88,7 +88,7 @@ using namespace ::com::sun::star::container; using namespace ::com::sun::star::document; using namespace ::xmloff::token; -rtl::Reference< FastTokenHandler > SvXMLImport::xTokenHandler( new FastTokenHandler() ); +rtl::Reference<FastTokenHandler> SvXMLImport::xTokenHandler(new FastTokenHandler); std::unordered_map< sal_Int32, std::pair< OUString, OUString > > SvXMLImport::aNamespaceMap; std::unordered_map< OUString, OUString > SvXMLImport::aNamespaceURIPrefixMap; bool SvXMLImport::bIsNSMapsInitialized = false; @@ -1985,7 +1985,7 @@ bool SvXMLImport::embeddedFontAlreadyProcessed( const OUString& url ) const OUString & SvXMLImport::getNameFromToken( sal_Int32 nToken ) { - return xTokenHandler->getIdentifier( nToken & TOKEN_MASK ); + return FastTokenHandler::getIdentifier( nToken & TOKEN_MASK ); } OUString SvXMLImport::getPrefixAndNameFromToken( sal_Int32 nToken ) @@ -1995,7 +1995,7 @@ OUString SvXMLImport::getPrefixAndNameFromToken( sal_Int32 nToken ) auto aIter( aNamespaceMap.find( nNamespaceToken ) ); if( aIter != aNamespaceMap.end() ) rv = (*aIter).second.second + " " + aIter->second.first + ":"; - return rv + xTokenHandler->getIdentifier( nToken & TOKEN_MASK ); + return rv + FastTokenHandler::getIdentifier(nToken & TOKEN_MASK); } OUString SvXMLImport::getNamespacePrefixFromToken(sal_Int32 nToken, const SvXMLNamespaceMap* pMap) |