From f150ed241ff796a25bd1a797155104198b415f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Wed, 22 Feb 2012 15:35:41 +0100 Subject: [PATCH] OUString ctor for string literals without RTL_CONSTASCII stuff http://lists.freedesktop.org/archives/libreoffice/2012-February/025662.html --- basic/source/uno/namecont.cxx | 14 +-- dbaccess/source/ui/browser/unodatbr.cxx | 2 +- desktop/source/deployment/inc/dp_misc.h | 18 ---- .../configuration/dp_configuration.cxx | 4 +- sal/CppunitTest_sal_rtl_strings.mk | 1 + sal/inc/rtl/ustring.hxx | 62 +++++++++++++ sal/inc/sal/log-areas.dox | 4 + .../strings/test_oustring_stringliterals.cxx | 91 +++++++++++++++++++ sal/rtl/source/ustring.cxx | 3 +- svl/source/misc/inethist.cxx | 4 +- 10 files changed, 172 insertions(+), 31 deletions(-) create mode 100644 sal/qa/rtl/strings/test_oustring_stringliterals.cxx diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx index db0bf668c6e7..db72a4fc640a 100644 --- a/basic/source/uno/namecont.cxx +++ b/basic/source/uno/namecont.cxx @@ -1001,13 +1001,13 @@ sal_Bool SfxLibraryContainer::init_Impl( INetURLObject aUserBasicInetObj( String(maLibraryPath).GetToken(1) ); OUString aStandardStr( RTL_CONSTASCII_USTRINGPARAM("Standard") ); - static char strPrevFolderName_1[] = "__basic_80"; - static char strPrevFolderName_2[] = "__basic_80_2"; + static char const strPrevFolderName_1[] = "__basic_80"; + static char const strPrevFolderName_2[] = "__basic_80_2"; INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj ); aPrevUserBasicInetObj_1.removeSegment(); INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1; - aPrevUserBasicInetObj_1.Append( strPrevFolderName_1 ); - aPrevUserBasicInetObj_2.Append( strPrevFolderName_2 ); + aPrevUserBasicInetObj_1.Append( rtl::OString( strPrevFolderName_1 )); + aPrevUserBasicInetObj_2.Append( rtl::OString( strPrevFolderName_2 )); // #i93163 bool bCleanUp = false; @@ -1072,7 +1072,7 @@ sal_Bool SfxLibraryContainer::init_Impl( String aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::NO_DECODE ); INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj ); aUserBasicTmpInetObj.removeSegment(); - aUserBasicTmpInetObj.Append( "__basic_tmp" ); + aUserBasicTmpInetObj.Append( rtl::OString( "__basic_tmp" )); String aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::NO_DECODE ); mxSFI->move( aFolderUserBasic, aFolderTmp ); @@ -1195,10 +1195,10 @@ sal_Bool SfxLibraryContainer::init_Impl( { SAL_WARN("basic", "Upgrade of Basic installation failed somehow"); - static char strErrorSavFolderName[] = "__basic_80_err"; + static const char strErrorSavFolderName[] = "__basic_80_err"; INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj ); aPrevUserBasicInetObj_Err.removeSegment(); - aPrevUserBasicInetObj_Err.Append( strErrorSavFolderName ); + aPrevUserBasicInetObj_Err.Append( rtl::OString( strErrorSavFolderName )); String aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::NO_DECODE ); bool bSaved = false; diff --git a/dbaccess/source/ui/browser/unodatbr.cxx b/dbaccess/source/ui/browser/unodatbr.cxx index 6e311415d00b..705cb24c2172 100644 --- a/dbaccess/source/ui/browser/unodatbr.cxx +++ b/dbaccess/source/ui/browser/unodatbr.cxx @@ -1916,7 +1916,7 @@ void SbaTableQueryBrowser::Execute(sal_uInt16 nId, const Sequence< PropertyValue break; case ID_TREE_CLOSE_CONN: - openHelpAgent( HID_DSBROWSER_DISCONNECTING ); + openHelpAgent( rtl::OString( HID_DSBROWSER_DISCONNECTING )); closeConnection( m_pTreeView->getListBox().GetRootLevelParent( m_pTreeView->getListBox().GetCurEntry() ) ); break; diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h index 9e912531e9f8..29fd14007d71 100644 --- a/desktop/source/deployment/inc/dp_misc.h +++ b/desktop/source/deployment/inc/dp_misc.h @@ -128,15 +128,6 @@ oslProcess raiseProcess( ::rtl::OUString const & appURL, DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void writeConsole(::rtl::OUString const & sText); -/** writes the argument string to the console. - On Linux/Unix/etc. the string is passed into fprintf without any conversion. - On Windows the string is converted to UTF16 assuming the argument is UTF8 - encoded. The UTF16 string is written to stdout with WriteFile. unopkg.com - reads the data and prints them out using WriteConsoleW. -*/ -DESKTOP_DEPLOYMENTMISC_DLLPUBLIC -void writeConsole(::rtl::OString const & sText); - /** writes the argument to the console using the error stream. Otherwise the same as writeConsole. */ @@ -144,13 +135,6 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void writeConsoleError(::rtl::OUString const & sText); -/** writes the argument to the console using the error stream. - Otherwise the same as writeConsole. -*/ -DESKTOP_DEPLOYMENTMISC_DLLPUBLIC -void writeConsoleError(::rtl::OString const & sText); - - /** reads from the console. On Linux/Unix/etc. it uses fgets to read char values and converts them to OUString using osl_getThreadTextEncoding as target encoding. The returned string has a maximum @@ -165,8 +149,6 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC */ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void TRACE(::rtl::OUString const & sText); -DESKTOP_DEPLOYMENTMISC_DLLPUBLIC -void TRACE(::rtl::OString const & sText); /** registers or revokes shared or bundled extensions which have been recently added or removed. diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.cxx b/desktop/source/deployment/registry/configuration/dp_configuration.cxx index 12e5f50984ea..dd1b00b989fa 100644 --- a/desktop/source/deployment/registry/configuration/dp_configuration.cxx +++ b/desktop/source/deployment/registry/configuration/dp_configuration.cxx @@ -244,8 +244,8 @@ BackendImpl::BackendImpl( } catch (const Exception &e) { - rtl::OStringBuffer aStr( "Exception loading legacy package database: '" ); - aStr.append( rtl::OUStringToOString( e.Message, osl_getThreadTextEncoding() ) ); + rtl::OUStringBuffer aStr( "Exception loading legacy package database: '" ); + aStr.append( e.Message ); aStr.append( "' - ignoring file, please remove it.\n" ); dp_misc::writeConsole( aStr.getStr() ); } diff --git a/sal/CppunitTest_sal_rtl_strings.mk b/sal/CppunitTest_sal_rtl_strings.mk index f43e7fd3a73d..8bc537010701 100644 --- a/sal/CppunitTest_sal_rtl_strings.mk +++ b/sal/CppunitTest_sal_rtl_strings.mk @@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sal_rtl_strings,\ sal/qa/rtl/strings/test_oustring_convert \ sal/qa/rtl/strings/test_oustring_endswith \ sal/qa/rtl/strings/test_oustring_noadditional \ + sal/qa/rtl/strings/test_oustring_stringliterals \ )) $(eval $(call gb_CppunitTest_add_linked_libs,sal_rtl_strings,\ diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx index faff676dcedb..f55fb7d6fdaf 100644 --- a/sal/inc/rtl/ustring.hxx +++ b/sal/inc/rtl/ustring.hxx @@ -167,6 +167,65 @@ public: rtl_uString_newFromStr_WithLength( &pData, value, length ); } + /** + New string from an 8-Bit string literal that is expected to be in UTF-8 + (or its subset, ASCII). All string literals in the codebase are + assumed to be only UTF-8/ASCII, so this constructor allows an efficient + and convenient way to create OUString instances from literals. + + @param value the 8-bit string literal + + @exception std::bad_alloc is thrown if an out-of-memory condition occurs + */ + template< int N > + OUString( const char (&literal)[ N ] ) + { + pData = 0; + rtl_string2UString( &pData, literal, N - 1, RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS ); + if (pData == 0) { +#if defined EXCEPTIONS_OFF + SAL_WARN("sal", "std::bad_alloc but EXCEPTIONS_OFF"); +#else + throw std::bad_alloc(); +#endif + } + } + + /** + * This overload exists only to avoid creating instances directly from (non-const) char[], + * which would otherwise be picked up by the optimized const char[] constructor. + * Since the non-const array cannot be guaranteed to contain characters in the expected + * UTF-8/ASCII encoding, this needs to be prevented. + * + * It is an error to try to call this overload. + * + * @internal + */ + template< int N > + OUString( char (&value)[ N ] ) +#ifndef RTL_STRING_UNITTEST + ; // intentionally not implemented +#else + { + (void) value; // unused + pData = 0; // for the unittest create an empty string + rtl_uString_new( &pData ); + } +#endif + +#ifdef RTL_STRING_UNITTEST + /** + * Only used by unittests to detect incorrect conversions. + * @internal + */ + template< typename T > + OUString( T ) + { + pData = 0; + rtl_uString_new( &pData ); + } +#endif + /** New string from a 8-Bit character buffer array. @@ -1722,6 +1781,9 @@ public: all ASCII characters are in the allowed range between 0 and 127. The ASCII string must be NULL-terminated. + Note that for string literals it is simpler and more efficient + to directly use the OUString constructor. + @param value the 8-Bit ASCII character string @return a string with the string representation of the argument. */ diff --git a/sal/inc/sal/log-areas.dox b/sal/inc/sal/log-areas.dox index d89bbdc886ba..7c2d8cea568c 100644 --- a/sal/inc/sal/log-areas.dox +++ b/sal/inc/sal/log-areas.dox @@ -25,6 +25,10 @@ certain functionality. @li oox.xmlstream - XmlStream class +@section SAL/RTL + +@li rtl.string - rtl::OString, rtl::OUString and related functionality + @section VCL @li vcl.gdi - the GDI part of VCL: devices, bitmaps, etc. diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx new file mode 100644 index 000000000000..142f53d9a8cf --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// activate the extra needed ctor +#define RTL_STRING_UNITTEST + +#include "sal/config.h" +#include "sal/precppunit.hxx" + +#include +#include +#include "rtl/string.h" +#include "rtl/ustring.hxx" + +namespace test { namespace oustring { + +class StringLiterals: public CppUnit::TestFixture +{ +private: + void checkCtors(); + + void testcall( const char str[] ); + // invalid conversions will trigger templated OUString ctor that creates an empty string + // (see RTL_STRING_UNITTEST) + bool validConversion( const rtl::OUString& str ) { return !str.isEmpty(); } + +CPPUNIT_TEST_SUITE(StringLiterals); +CPPUNIT_TEST(checkCtors); +CPPUNIT_TEST_SUITE_END(); +}; + +void test::oustring::StringLiterals::checkCtors() +{ + CPPUNIT_ASSERT( validConversion( rtl::OUString( "test" ))); + const char good1[] = "test"; + CPPUNIT_ASSERT( validConversion( rtl::OUString( good1 ))); + + CPPUNIT_ASSERT( !validConversion( rtl::OUString( (const char*) "test" ))); + const char* bad1 = good1; + CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad1 ))); + char bad2[] = "test"; + CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad2 ))); + char* bad3 = bad2; + CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad3 ))); + const char* bad4[] = { "test1" }; + CPPUNIT_ASSERT( !validConversion( rtl::OUString( bad4[ 0 ] ))); + testcall( good1 ); + +// This one is technically broken, since the first element is 6 characters test\0\0, +// but there does not appear a way to detect this by compile time (runtime will complain). +// RTL_CONSTASCII_USTRINGPARAM() has the same flaw. + const char bad5[][ 6 ] = { "test", "test2" }; +// CPPUNIT_ASSERT( validConversion( rtl::OUString( bad5[ 0 ] ))); + CPPUNIT_ASSERT( validConversion( rtl::OUString( bad5[ 1 ] ))); +} + +void test::oustring::StringLiterals::testcall( const char str[] ) +{ + CPPUNIT_ASSERT( !validConversion( rtl::OUString( str ))); +} + +}} // namespace + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/rtl/source/ustring.cxx b/sal/rtl/source/ustring.cxx index 0156ceae9a08..d7f8a96971ec 100644 --- a/sal/rtl/source/ustring.cxx +++ b/sal/rtl/source/ustring.cxx @@ -45,6 +45,7 @@ #include #include +#include #include "hash.hxx" #include "strimp.hxx" @@ -600,7 +601,7 @@ static void rtl_string2UString_status( rtl_uString** ppThis, do { /* Check ASCII range */ - OSL_ENSURE( ((unsigned char)*pStr) <= 127, + SAL_WARN_IF( ((unsigned char)*pStr) > 127, "rtl.string", "rtl_string2UString_status() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" ); *pBuffer = *pStr; diff --git a/svl/source/misc/inethist.cxx b/svl/source/misc/inethist.cxx index 16745c09272f..e9a2bb0ee8eb 100644 --- a/svl/source/misc/inethist.cxx +++ b/svl/source/misc/inethist.cxx @@ -443,14 +443,14 @@ void INetURLHistory::NormalizeUrl_Impl (INetURLObject &rUrl) if (!rUrl.HasPort()) rUrl.SetPort (INETHIST_DEF_HTTP_PORT); if (!rUrl.HasURLPath()) - rUrl.SetURLPath ("/"); + rUrl.SetURLPath (rtl::OString("/")); break; case INET_PROT_HTTPS: if (!rUrl.HasPort()) rUrl.SetPort (INETHIST_DEF_HTTPS_PORT); if (!rUrl.HasURLPath()) - rUrl.SetURLPath ("/"); + rUrl.SetURLPath (rtl::OString("/")); break; default: