diff options
Diffstat (limited to 'tools')
38 files changed, 995 insertions, 622 deletions
diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk index 096b3ddb1835..c36af07547c2 100644 --- a/tools/CppunitTest_tools_test.mk +++ b/tools/CppunitTest_tools_test.mk @@ -33,10 +33,12 @@ $(eval $(call gb_CppunitTest_add_exception_objects,tools_test, \ tools/qa/cppunit/test_xmlwalker \ tools/qa/cppunit/test_xmlwriter \ tools/qa/cppunit/test_GenericTypeSerializer \ + tools/qa/cppunit/test_guid \ tools/qa/cppunit/test_cpuid \ tools/qa/cppunit/test_cpu_runtime_detection_AVX2 \ tools/qa/cppunit/test_cpu_runtime_detection_SSE2 \ tools/qa/cppunit/test_cpu_runtime_detection_SSSE3 \ + tools/qa/cppunit/test_Wildcard \ )) $(eval $(call gb_CppunitTest_add_exception_objects,tools_test,\ diff --git a/tools/IwyuFilter_tools.yaml b/tools/IwyuFilter_tools.yaml index cfd771ba1ee9..ecc4dd5f86f9 100644 --- a/tools/IwyuFilter_tools.yaml +++ b/tools/IwyuFilter_tools.yaml @@ -7,12 +7,20 @@ excludelist: - cppunit/plugin/TestPlugIn.h - tools/pathutils.hxx - cwchar + tools/qa/cppunit/test_cpu_runtime_detection_AVX2_check.cxx: + # Needed for LO_AVX2_AVAILABLE case + - sal/types.h + - tools/simdsupport.hxx + - stdlib.h + tools/qa/cppunit/test_cpu_runtime_detection_SSSE3_check.cxx: + # Needed for LO_SSSE3_AVAILABLE case + - tools/simdsupport.hxx + - stdlib.h tools/source/debug/debug.cxx: # Needed for linker visibility - tools/diagnose_ex.h - tools/source/generic/poly.cxx: - # OSL_BIGENDIAN is being checked - - osl/endian.h + # Keep for commented out "if defined __GLIBCXX__" path + - cxxabi.h tools/source/misc/extendapplicationenvironment.cxx: # Needed on MACOSX - config_folders.h diff --git a/tools/Library_tl.mk b/tools/Library_tl.mk index ecad06913ed2..bccbf95a2a01 100644 --- a/tools/Library_tl.mk +++ b/tools/Library_tl.mk @@ -81,6 +81,12 @@ $(eval $(call gb_Library_add_exception_objects,tl,\ tools/source/xml/XmlWalker \ )) +ifneq ($(SYSTEM_LIBFIXMATH),TRUE) +$(eval $(call gb_Library_add_exception_objects,tl,\ + tools/source/misc/fix16 \ +)) +endif + ifeq ($(OS),WNT) $(eval $(call gb_Library_add_exception_objects,tl, \ tools/source/stream/strmwnt \ @@ -107,6 +113,12 @@ $(eval $(call gb_Library_add_libs,tl,\ )) endif +ifeq ($(SYSTEM_LIBFIXMATH),TRUE) +$(eval $(call gb_Library_add_libs,tl,\ + -llibfixmath \ +)) +endif + ifeq ($(OS),WNT) $(eval $(call gb_Library_use_system_win32_libs,tl,\ diff --git a/tools/inc/poly.h b/tools/inc/poly.h index 64885ac29762..772e854e31fb 100644 --- a/tools/inc/poly.h +++ b/tools/inc/poly.h @@ -38,7 +38,7 @@ public: ImplPolygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound); ImplPolygon( const Point& rCenter, tools::Long nRadX, tools::Long nRadY ); ImplPolygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd, - PolyStyle eStyle ); + PolyStyle eStyle, bool bClockWiseArcDirection ); ImplPolygon( const Point& rBezPt1, const Point& rCtrlPt1, const Point& rBezPt2, const Point& rCtrlPt2, sal_uInt16 nPoints ); ImplPolygon(const basegfx::B2DPolygon& rPolygon); diff --git a/tools/qa/cppunit/test_100mm2twips.cxx b/tools/qa/cppunit/test_100mm2twips.cxx index fc1d228f2d49..1fb69d98209b 100644 --- a/tools/qa/cppunit/test_100mm2twips.cxx +++ b/tools/qa/cppunit/test_100mm2twips.cxx @@ -22,7 +22,6 @@ #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <tools/helpers.hxx> #include <tools/UnitConversion.hxx> class UnitConversionTest : public CppUnit::TestFixture diff --git a/tools/qa/cppunit/test_Wildcard.cxx b/tools/qa/cppunit/test_Wildcard.cxx new file mode 100644 index 000000000000..1760ca6932db --- /dev/null +++ b/tools/qa/cppunit/test_Wildcard.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <tools/wldcrd.hxx> + +namespace +{ +class Test : public CppUnit::TestFixture +{ +public: + void test_Wildcard(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test_Wildcard); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::test_Wildcard() +{ + WildCard wildcard(u"*.html;*??a;*\\*abc;*\\?xyz", ';'); // tdf#148253 + CPPUNIT_ASSERT(wildcard.Matches(u"foo.html")); + CPPUNIT_ASSERT(wildcard.Matches(u"foo.ht.html")); // test stepping back after partial match + CPPUNIT_ASSERT(wildcard.Matches(u"foo.html.html")); // test stepping back after full match + CPPUNIT_ASSERT(wildcard.Matches(u"??aa")); // test stepping back with question marks + CPPUNIT_ASSERT(wildcard.Matches(u"111*abc")); // test escaped asterisk + CPPUNIT_ASSERT(!wildcard.Matches(u"111-abc")); // test escaped asterisk + CPPUNIT_ASSERT(wildcard.Matches(u"111?xyz")); // test escaped question mark + CPPUNIT_ASSERT(!wildcard.Matches(u"111-xyz")); // test escaped question mark +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx index 5a3a1ee26638..5ba8ed9ee2fb 100644 --- a/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx +++ b/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx @@ -7,13 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <tools/simdsupport.hxx> #include "test_cpu_runtime_detection_x86_checks.hxx" -#include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> #include <tools/cpuid.hxx> diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx index 6da1850a135a..93bac6f2a130 100644 --- a/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx @@ -7,14 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <tools/simdsupport.hxx> - #include "test_cpu_runtime_detection_x86_checks.hxx" -#include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> #include <tools/cpuid.hxx> diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSE2_check.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2_check.cxx index 7f14e1b51789..12e39eabfd64 100644 --- a/tools/qa/cppunit/test_cpu_runtime_detection_SSE2_check.cxx +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2_check.cxx @@ -7,7 +7,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <sal/types.h> #include <tools/simdsupport.hxx> #include <stdlib.h> diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx index 290d073745da..3c0e9d252466 100644 --- a/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx @@ -7,14 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <tools/simdsupport.hxx> - #include "test_cpu_runtime_detection_x86_checks.hxx" -#include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> #include <tools/cpuid.hxx> diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3_check.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3_check.cxx index 9a93dadea79c..705e5c2ab3c9 100644 --- a/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3_check.cxx +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3_check.cxx @@ -7,7 +7,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <sal/types.h> #include <tools/simdsupport.hxx> #include <stdlib.h> diff --git a/tools/qa/cppunit/test_cpuid.cxx b/tools/qa/cppunit/test_cpuid.cxx index cb9c1b9a7fb6..7d9b5c41cce3 100644 --- a/tools/qa/cppunit/test_cpuid.cxx +++ b/tools/qa/cppunit/test_cpuid.cxx @@ -10,7 +10,6 @@ #include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> #include <tools/cpuid.hxx> #include <rtl/ustring.hxx> diff --git a/tools/qa/cppunit/test_guid.cxx b/tools/qa/cppunit/test_guid.cxx new file mode 100644 index 000000000000..177e58591ba7 --- /dev/null +++ b/tools/qa/cppunit/test_guid.cxx @@ -0,0 +1,123 @@ +/* -*- 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/. + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <tools/Guid.hxx> + +namespace tools +{ +class GuidTest : public CppUnit::TestFixture +{ +public: + void testGetString() + { + sal_uInt8 pArray[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + Guid aGuid(pArray); + CPPUNIT_ASSERT_EQUAL(OString("{01020304-0506-0708-090A-0B0C0D0E0F10}"), aGuid.getString()); + } + + void testCreate() + { + // data is generated when Guid is created + Guid aGuid1(Guid::Generate); + + // check it's not initialized to 0 + CPPUNIT_ASSERT(*std::max_element(aGuid1.begin(), aGuid1.end()) > 0u); + + // data is generated when Guid is created + Guid aGuid2(Guid::Generate); + + CPPUNIT_ASSERT_EQUAL(aGuid1, aGuid1); + CPPUNIT_ASSERT_EQUAL(aGuid2, aGuid2); + + CPPUNIT_ASSERT(aGuid1 != aGuid2); + } + + void testParse() + { + sal_uInt8 pArray1[16] = { 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5 }; + Guid aGuid1(pArray1); + + Guid aGuid2("{01010101-0202-0303-0404-050505050505}"); + CPPUNIT_ASSERT_EQUAL(aGuid1, aGuid2); + + sal_uInt8 pArray2[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + Guid aGuid3(pArray2); + + Guid aGuid4("{FFffFFff-FFff-FFff-FFff-FFffFFffFFff}"); + CPPUNIT_ASSERT_EQUAL(aGuid3, aGuid4); + + Guid aGuid5("{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}"); + CPPUNIT_ASSERT_EQUAL(aGuid5, aGuid4); + + Guid aGuid6("01010101-0202-0303-0404-0505050505005"); + CPPUNIT_ASSERT(aGuid6.isEmpty()); + + Guid aGuid7("Random"); + CPPUNIT_ASSERT(aGuid7.isEmpty()); + + Guid aGuid8("{0G010101-0202-0303-0404-050505050505}"); + CPPUNIT_ASSERT(aGuid8.isEmpty()); + + Guid aGuid9("{FFAAFFAA-FFAA-FFAA-FFAA-FF00FF11FF22}"); + CPPUNIT_ASSERT(!aGuid9.isEmpty()); + + Guid aGuid10("{FFAAFFAA?FFAA-FFAA-FFAA-FF00FF11FF22}"); + CPPUNIT_ASSERT(aGuid10.isEmpty()); + } + + void testEmpty() + { + sal_uInt8 pArray1[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + Guid aGuid1(pArray1); + CPPUNIT_ASSERT(aGuid1.isEmpty()); + + sal_uInt8 pArray2[16] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + Guid aGuid2(pArray2); + CPPUNIT_ASSERT(!aGuid2.isEmpty()); + + Guid aGuid3; + CPPUNIT_ASSERT(aGuid3.isEmpty()); + } + + void testCopyAndAssign() + { + sal_uInt8 pArray1[16] = { 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5 }; + Guid aGuid1(pArray1); + + // test copy constructor + Guid aGuid2(aGuid1); + CPPUNIT_ASSERT_EQUAL(aGuid1, aGuid2); + CPPUNIT_ASSERT(std::equal(aGuid1.cbegin(), aGuid1.cend(), aGuid2.cbegin(), aGuid2.cend())); + + // test assign + Guid aGuid3 = aGuid1; + CPPUNIT_ASSERT_EQUAL(aGuid3, aGuid1); + CPPUNIT_ASSERT(std::equal(aGuid3.cbegin(), aGuid3.cend(), aGuid1.cbegin(), aGuid1.cend())); + CPPUNIT_ASSERT_EQUAL(aGuid3, aGuid2); + CPPUNIT_ASSERT(std::equal(aGuid3.cbegin(), aGuid3.cend(), aGuid2.cbegin(), aGuid2.cend())); + } + + CPPUNIT_TEST_SUITE(GuidTest); + CPPUNIT_TEST(testGetString); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testEmpty); + CPPUNIT_TEST(testCopyAndAssign); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(GuidTest); + +} // namespace tools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/qa/cppunit/test_json_writer.cxx b/tools/qa/cppunit/test_json_writer.cxx index fe3019e91b0a..188b22f9c617 100644 --- a/tools/qa/cppunit/test_json_writer.cxx +++ b/tools/qa/cppunit/test_json_writer.cxx @@ -9,13 +9,10 @@ #include <sal/config.h> -#include <cstdlib> - #include <cppunit/extensions/HelperMacros.h> #include <o3tl/deleter.hxx> #include <test/bootstrapfixture.hxx> #include <rtl/ustring.hxx> -#include <tools/stream.hxx> #include <tools/json_writer.hxx> namespace @@ -32,10 +29,12 @@ public: void test1(); void test2(); + void testArray(); CPPUNIT_TEST_SUITE(JsonWriterTest); CPPUNIT_TEST(test1); CPPUNIT_TEST(test2); + CPPUNIT_TEST(testArray); CPPUNIT_TEST_SUITE_END(); }; @@ -84,6 +83,21 @@ void JsonWriterTest::test2() std::string(result.get())); } +void JsonWriterTest::testArray() +{ + tools::JsonWriter aJson; + { + tools::ScopedJsonWriterArray aArray = aJson.startArray("items"); + aJson.putSimpleValue("foo"); + aJson.putSimpleValue("bar"); + } + + std::unique_ptr<char, o3tl::free_delete> aResult(aJson.extractData()); + + CPPUNIT_ASSERT_EQUAL(std::string("{ \"items\": [ \"foo\", \"bar\"]}"), + std::string(aResult.get())); +} + CPPUNIT_TEST_SUITE_REGISTRATION(JsonWriterTest); } diff --git a/tools/qa/cppunit/test_urlobj.cxx b/tools/qa/cppunit/test_urlobj.cxx index a335701c5cab..8402fae5ed55 100644 --- a/tools/qa/cppunit/test_urlobj.cxx +++ b/tools/qa/cppunit/test_urlobj.cxx @@ -48,7 +48,7 @@ namespace tools_urlobj // this is only demonstration code void urlobjTest_001( ) { - INetURLObject aUrl( OUString( "file://10.10.1.1/sampledir/sample.file" ) ); + INetURLObject aUrl( u"file://10.10.1.1/sampledir/sample.file" ); CPPUNIT_ASSERT_EQUAL(INetProtocol::File, aUrl.GetProtocol()); CPPUNIT_ASSERT_EQUAL(OUString("10.10.1.1"), aUrl.GetHost(INetURLObject::DecodeMechanism::NONE)); @@ -62,7 +62,7 @@ namespace tools_urlobj void urlobjTest_004( ) { - INetURLObject aUrl( OUString( "smb://10.10.1.1/sampledir/sample.file" ) ); + INetURLObject aUrl( u"smb://10.10.1.1/sampledir/sample.file" ); CPPUNIT_ASSERT_EQUAL( INetProtocol::Smb, aUrl.GetProtocol( ) ); CPPUNIT_ASSERT_EQUAL(OUString("10.10.1.1"), aUrl.GetHost(INetURLObject::DecodeMechanism::NONE)); @@ -77,7 +77,7 @@ namespace tools_urlobj { // Test with a username part { - INetURLObject aUrl( OUString( "vnd.libreoffice.cmis://username@http:%2F%2Ffoo.bar.com:8080%2Fmy%2Fcmis%2Fatom%23repo-id-encoded/path/to/content" ) ); + INetURLObject aUrl( u"vnd.libreoffice.cmis://username@http:%2F%2Ffoo.bar.com:8080%2Fmy%2Fcmis%2Fatom%23repo-id-encoded/path/to/content" ); CPPUNIT_ASSERT_EQUAL( std::string( "http://foo.bar.com:8080/my/cmis/atom#repo-id-encoded" ), OUSTR_TO_STDSTR( aUrl.GetHost( INetURLObject::DecodeMechanism::WithCharset ) ) ); CPPUNIT_ASSERT_EQUAL( std::string( "username" ), OUSTR_TO_STDSTR( aUrl.GetUser( ) ) ); @@ -88,8 +88,8 @@ namespace tools_urlobj // Test without a username part { - INetURLObject aUrl( OUString( - "vnd.libreoffice.cmis://http:%2F%2Ffoo.bar.com:8080%2Fmy%2Fcmis%2Fatom%23repo-id-encoded/path/to/content" ) ); + INetURLObject aUrl( + u"vnd.libreoffice.cmis://http:%2F%2Ffoo.bar.com:8080%2Fmy%2Fcmis%2Fatom%23repo-id-encoded/path/to/content" ); CPPUNIT_ASSERT_EQUAL( std::string( "http://foo.bar.com:8080/my/cmis/atom#repo-id-encoded" ), OUSTR_TO_STDSTR( aUrl.GetHost( INetURLObject::DecodeMechanism::WithCharset ) ) ); CPPUNIT_ASSERT( !aUrl.HasUserData() ); @@ -101,18 +101,18 @@ namespace tools_urlobj void urlobjTest_emptyPath() { { - INetURLObject url(OUString("http://example.com")); + INetURLObject url(u"http://example.com"); CPPUNIT_ASSERT_EQUAL(INetProtocol::Http, url.GetProtocol()); CPPUNIT_ASSERT_EQUAL(OUString("example.com"), url.GetHost()); CPPUNIT_ASSERT_EQUAL(OUString("/"), url.GetURLPath()); } { // This is an invalid http URL per RFC 2616: - INetURLObject url(OUString("http://example.com?query")); + INetURLObject url(u"http://example.com?query"); CPPUNIT_ASSERT(url.HasError()); } { - INetURLObject url(OUString("http://example.com#fragment")); + INetURLObject url(u"http://example.com#fragment"); CPPUNIT_ASSERT_EQUAL(INetProtocol::Http, url.GetProtocol()); CPPUNIT_ASSERT_EQUAL(OUString("example.com"), url.GetHost()); CPPUNIT_ASSERT_EQUAL(OUString("/"), url.GetURLPath()); @@ -125,19 +125,19 @@ namespace tools_urlobj std::unique_ptr<SvMemoryStream> strm; unsigned char const * buf; - url = INetURLObject("data:"); + url = INetURLObject(u"data:"); //TODO: CPPUNIT_ASSERT(url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(!strm); - url = INetURLObject("data:,"); + url = INetURLObject(u"data:,"); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), strm->GetSize()); strm.reset(); - url = INetURLObject("data:,,%C3%A4%90"); + url = INetURLObject(u"data:,,%C3%A4%90"); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); @@ -149,26 +149,26 @@ namespace tools_urlobj CPPUNIT_ASSERT_EQUAL(0x90, int(buf[3])); strm.reset(); - url = INetURLObject("data:base64,"); + url = INetURLObject(u"data:base64,"); //TODO: CPPUNIT_ASSERT(url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(!strm); - url = INetURLObject("data:;base64,"); + url = INetURLObject(u"data:;base64,"); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), strm->GetSize()); strm.reset(); - url = INetURLObject("data:;bAsE64,"); + url = INetURLObject(u"data:;bAsE64,"); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); CPPUNIT_ASSERT_EQUAL(sal_uInt64(0), strm->GetSize()); strm.reset(); - url = INetURLObject("data:;base64,YWJjCg=="); + url = INetURLObject(u"data:;base64,YWJjCg=="); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); @@ -180,17 +180,17 @@ namespace tools_urlobj CPPUNIT_ASSERT_EQUAL(0x0A, int(buf[3])); strm.reset(); - url = INetURLObject("data:;base64,YWJjCg="); + url = INetURLObject(u"data:;base64,YWJjCg="); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(!strm); - url = INetURLObject("data:;base64,YWJ$Cg=="); + url = INetURLObject(u"data:;base64,YWJ$Cg=="); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(!strm); - url = INetURLObject("data:text/plain;param=%22;base64,%22,YQ=="); + url = INetURLObject(u"data:text/plain;param=%22;base64,%22,YQ=="); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(strm != nullptr); @@ -202,7 +202,7 @@ namespace tools_urlobj CPPUNIT_ASSERT_EQUAL(0x3D, int(buf[3])); strm.reset(); - url = INetURLObject("http://example.com"); + url = INetURLObject(u"http://example.com"); CPPUNIT_ASSERT(!url.HasError()); strm = url.getData(); CPPUNIT_ASSERT(!strm); @@ -212,62 +212,62 @@ namespace tools_urlobj CPPUNIT_ASSERT(INetURLObject().isSchemeEqualTo(INetProtocol::NotValid)); CPPUNIT_ASSERT(!INetURLObject().isSchemeEqualTo(u"")); CPPUNIT_ASSERT( - INetURLObject("http://example.org").isSchemeEqualTo( + INetURLObject(u"http://example.org").isSchemeEqualTo( INetProtocol::Http)); CPPUNIT_ASSERT( - !INetURLObject("http://example.org").isSchemeEqualTo( + !INetURLObject(u"http://example.org").isSchemeEqualTo( INetProtocol::Https)); CPPUNIT_ASSERT( - INetURLObject("http://example.org").isSchemeEqualTo(u"Http")); + INetURLObject(u"http://example.org").isSchemeEqualTo(u"Http")); CPPUNIT_ASSERT( - !INetURLObject("http://example.org").isSchemeEqualTo(u"dav")); + !INetURLObject(u"http://example.org").isSchemeEqualTo(u"dav")); CPPUNIT_ASSERT( - INetURLObject("dav://example.org").isSchemeEqualTo(u"dav")); + INetURLObject(u"dav://example.org").isSchemeEqualTo(u"dav")); } void urlobjTest_isAnyKnownWebDAVScheme() { CPPUNIT_ASSERT( - INetURLObject("http://example.org").isAnyKnownWebDAVScheme()); + INetURLObject(u"http://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - INetURLObject("https://example.org").isAnyKnownWebDAVScheme()); + INetURLObject(u"https://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - INetURLObject("vnd.sun.star.webdav://example.org").isAnyKnownWebDAVScheme()); + INetURLObject(u"vnd.sun.star.webdav://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - INetURLObject("vnd.sun.star.webdavs://example.org").isAnyKnownWebDAVScheme()); + INetURLObject(u"vnd.sun.star.webdavs://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - !INetURLObject("ftp://example.org").isAnyKnownWebDAVScheme()); + !INetURLObject(u"ftp://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - !INetURLObject("file://example.org").isAnyKnownWebDAVScheme()); + !INetURLObject(u"file://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - !INetURLObject("dav://example.org").isAnyKnownWebDAVScheme()); + !INetURLObject(u"dav://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - !INetURLObject("davs://example.org").isAnyKnownWebDAVScheme()); + !INetURLObject(u"davs://example.org").isAnyKnownWebDAVScheme()); CPPUNIT_ASSERT( - !INetURLObject("vnd.sun.star.pkg://example.org").isAnyKnownWebDAVScheme()); + !INetURLObject(u"vnd.sun.star.pkg://example.org").isAnyKnownWebDAVScheme()); } void testSetName() { { - INetURLObject obj("file:///"); + INetURLObject obj(u"file:///"); bool ok = obj.setName(u"foo"); CPPUNIT_ASSERT(!ok); } { - INetURLObject obj("file:///foo"); + INetURLObject obj(u"file:///foo"); bool ok = obj.setName(u"bar"); CPPUNIT_ASSERT(ok); CPPUNIT_ASSERT_EQUAL( OUString("file:///bar"), obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); } { - INetURLObject obj("file:///foo/"); + INetURLObject obj(u"file:///foo/"); bool ok = obj.setName(u"bar"); CPPUNIT_ASSERT(ok); CPPUNIT_ASSERT_EQUAL( OUString("file:///bar/"), obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); } { - INetURLObject obj("file:///foo/bar"); + INetURLObject obj(u"file:///foo/bar"); bool ok = obj.setName(u"baz"); CPPUNIT_ASSERT(ok); CPPUNIT_ASSERT_EQUAL( @@ -275,7 +275,7 @@ namespace tools_urlobj obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); } { - INetURLObject obj("file:///foo/bar/"); + INetURLObject obj(u"file:///foo/bar/"); bool ok = obj.setName(u"baz"); CPPUNIT_ASSERT(ok); CPPUNIT_ASSERT_EQUAL( @@ -285,7 +285,7 @@ namespace tools_urlobj } void testSetExtension() { - INetURLObject obj("file:///foo/bar.baz/"); + INetURLObject obj(u"file:///foo/bar.baz/"); bool ok = obj.setExtension( u"other", INetURLObject::LAST_SEGMENT, false); CPPUNIT_ASSERT(ok); @@ -295,7 +295,7 @@ namespace tools_urlobj } void testChangeScheme() { - INetURLObject obj("unknown://example.com/foo/bar"); + INetURLObject obj(u"unknown://example.com/foo/bar"); CPPUNIT_ASSERT(!obj.HasError()); obj.changeScheme(INetProtocol::Http); CPPUNIT_ASSERT_EQUAL( @@ -311,6 +311,40 @@ namespace tools_urlobj obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); } + void testTd146382() { + INetURLObject obj(u"file://share.allotropia.de@SSL/DavWWWRoot/remote.php"); + CPPUNIT_ASSERT(!obj.HasError()); + CPPUNIT_ASSERT_EQUAL( + OUString("file://share.allotropia.de@SSL/DavWWWRoot/remote.php"), + obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + } + + void testParseSmart() + { + { + // host:port must not be misinterpreted as scheme:path + INetURLObject obj(u"example.com:8080/foo", INetProtocol::Http); + CPPUNIT_ASSERT(!obj.HasError()); + CPPUNIT_ASSERT_EQUAL(OUString("http://example.com:8080/foo"), + obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + CPPUNIT_ASSERT_EQUAL(INetProtocol::Http, obj.GetProtocol()); + CPPUNIT_ASSERT_EQUAL(OUString("example.com"), obj.GetHost()); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(8080), obj.GetPort()); + CPPUNIT_ASSERT_EQUAL(OUString("/foo"), obj.GetURLPath()); + } + { + // port may only contain decimal digits, so this must be treated as unknown scheme + INetURLObject obj(u"example.com:80a0/foo", INetProtocol::Http); + CPPUNIT_ASSERT(!obj.HasError()); + CPPUNIT_ASSERT_EQUAL(OUString("example.com:80a0/foo"), + obj.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + CPPUNIT_ASSERT_EQUAL(INetProtocol::Generic, obj.GetProtocol()); + CPPUNIT_ASSERT(obj.isSchemeEqualTo(u"example.com")); + CPPUNIT_ASSERT_EQUAL(OUString(""), obj.GetHost()); + CPPUNIT_ASSERT_EQUAL(OUString("80a0/foo"), obj.GetURLPath()); + } + } + // Change the following lines only, if you add, remove or rename // member functions of the current class, // because these macros are need by auto register mechanism. @@ -326,6 +360,8 @@ namespace tools_urlobj CPPUNIT_TEST( testSetName ); CPPUNIT_TEST( testSetExtension ); CPPUNIT_TEST( testChangeScheme ); + CPPUNIT_TEST( testTd146382 ); + CPPUNIT_TEST( testParseSmart ); CPPUNIT_TEST_SUITE_END( ); }; // class createPool diff --git a/tools/qa/cppunit/test_xmlwriter.cxx b/tools/qa/cppunit/test_xmlwriter.cxx index 1cd207a4afe5..0fddb3d77de4 100644 --- a/tools/qa/cppunit/test_xmlwriter.cxx +++ b/tools/qa/cppunit/test_xmlwriter.cxx @@ -9,7 +9,6 @@ #include <cppunit/extensions/HelperMacros.h> #include <test/bootstrapfixture.hxx> -#include <rtl/ustring.hxx> #include <tools/stream.hxx> #include <tools/XmlWriter.hxx> diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx index c6c89c934886..ee9e427205ef 100644 --- a/tools/source/datetime/ttime.cxx +++ b/tools/source/datetime/ttime.cxx @@ -477,11 +477,12 @@ sal_uInt64 tools::Time::GetMonotonicTicks() #if defined(_POSIX_TIMERS) struct timespec currentTime; clock_gettime( CLOCK_MONOTONIC, ¤tTime ); - nMicroSeconds = currentTime.tv_sec * 1000 * 1000 + currentTime.tv_nsec / 1000; + nMicroSeconds + = static_cast<sal_uInt64>(currentTime.tv_sec) * 1000 * 1000 + currentTime.tv_nsec / 1000; #else struct timeval currentTime; gettimeofday( ¤tTime, nullptr ); - nMicroSeconds = currentTime.tv_sec * 1000 * 1000 + currentTime.tv_usec; + nMicroSeconds = static_cast<sal_uInt64>(currentTime.tv_sec) * 1000 * 1000 + currentTime.tv_usec; #endif #endif // __MACH__ return nMicroSeconds; diff --git a/tools/source/debug/debug.cxx b/tools/source/debug/debug.cxx index 82406a3624ff..3bb080959e67 100644 --- a/tools/source/debug/debug.cxx +++ b/tools/source/debug/debug.cxx @@ -52,9 +52,6 @@ #include <osl/thread.h> #include <rtl/strbuf.hxx> -#include <cstdlib> -#include <typeinfo> - #include <tools/diagnose_ex.h> #if defined __GLIBCXX__ @@ -105,8 +102,9 @@ static void exceptionToStringImpl(OStringBuffer& sMessage, const css::uno::Any & caught >>= exception; if ( !exception.Message.isEmpty() ) { - sMessage.append(" message: "); + sMessage.append(" message: \""); sMessage.append(toOString(exception.Message)); + sMessage.append("\""); } /* TODO FIXME (see https://gerrit.libreoffice.org/#/c/83245/) if ( exception.Context.is() ) diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx index 8c3d2845eab2..00e3207b2d3b 100644 --- a/tools/source/fsys/urlobj.cxx +++ b/tools/source/fsys/urlobj.cxx @@ -45,6 +45,7 @@ #include <com/sun/star/uno/Sequence.hxx> #include <comphelper/base64.hxx> +#include <comphelper/string.hxx> using namespace css; @@ -646,10 +647,10 @@ std::unique_ptr<SvMemoryStream> INetURLObject::getData() const else if (sURLPath.matchIgnoreAsciiCase(";base64,", nCharactersSkipped)) { nCharactersSkipped += strlen(";base64,"); - OUString sBase64Data = sURLPath.copy( nCharactersSkipped ); + std::u16string_view sBase64Data = sURLPath.subView( nCharactersSkipped ); css::uno::Sequence< sal_Int8 > aDecodedData; if (comphelper::Base64::decodeSomeChars(aDecodedData, sBase64Data) - == sBase64Data.getLength()) + == sBase64Data.size()) { return memoryStream( aDecodedData.getArray(), aDecodedData.getLength()); @@ -719,14 +720,14 @@ OUString parseScheme( } -bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, +bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef, EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bSmart, FSysStyle eStyle) { - sal_Unicode const * pPos = rTheAbsURIRef.getStr(); - sal_Unicode const * pEnd = pPos + rTheAbsURIRef.getLength(); + sal_Unicode const * pPos = rTheAbsURIRef.data(); + sal_Unicode const * pEnd = pPos + rTheAbsURIRef.size(); setInvalid(); @@ -869,8 +870,34 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter); if (!aSynScheme.isEmpty()) { - m_eScheme = INetProtocol::Generic; - pPos = p1; + if (bSmart && m_eSmartScheme != m_eScheme && p1 != pEnd && rtl::isAsciiDigit(*p1)) + { + // rTheAbsURIRef doesn't define a known scheme (handled by the "if (pPrefix)" + // branch above); but a known scheme is defined in m_eSmartScheme. If this + // scheme may have a port in authority component, then avoid misinterpreting + // URLs like www.foo.bar:123/baz as using unknown "www.foo.bar" scheme with + // 123/baz rootless path. For now, do not try to handle possible colons in + // user information, require such ambiguous URLs to have explicit scheme part. + // Also ignore possibility of empty port. + const SchemeInfo& rInfo = getSchemeInfo(m_eSmartScheme); + if (rInfo.m_bAuthority && rInfo.m_bPort) + { + // Make sure that all characters from colon to [/?#] or to EOL are digits. + // Or maybe make it simple, and just assume that "xyz:1..." is more likely + // to be host "xyz" and port "1...", than scheme "xyz" and path "1..."? + sal_Unicode const* p2 = p1 + 1; + while (p2 != pEnd && rtl::isAsciiDigit(*p2)) + ++p2; + if (p2 == pEnd || *p2 == '/' || *p2 == '?' || *p2 == '#') + m_eScheme = m_eSmartScheme; + } + } + + if (m_eScheme == INetProtocol::NotValid) + { + m_eScheme = INetProtocol::Generic; + pPos = p1; + } } } @@ -930,7 +957,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, PART_AUTHORITY, eCharset, false); } m_aHost.set(m_aAbsURIRef, - aSynAuthority.makeStringAndClear(), + aSynAuthority, m_aAbsURIRef.getLength()); // misusing m_aHost to store the authority break; @@ -966,7 +993,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, return false; } m_aHost.set(m_aAbsURIRef, - aSynAuthority.makeStringAndClear(), + aSynAuthority, m_aAbsURIRef.getLength()); // misusing m_aHost to store the authority } @@ -1007,7 +1034,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, else { m_aUser.set(m_aAbsURIRef, - aSynUser.makeStringAndClear(), + aSynUser, m_aAbsURIRef.getLength()); m_aAbsURIRef.append("@"); ++pPos; @@ -1030,7 +1057,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, return false; } m_aHost.set(m_aAbsURIRef, - aSynAuthority.makeStringAndClear(), + aSynAuthority, m_aAbsURIRef.getLength()); // misusing m_aHost to store the authority break; @@ -1314,8 +1341,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, appendUCS4(aSynUser, nUTF32, eEscapeType, ePart, eCharset, false); } - m_aUser.set(m_aAbsURIRef, aSynUser.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aUser.set(m_aAbsURIRef, aSynUser, m_aAbsURIRef.getLength()); if (bHasAuth) { if (bSupportsPassword) @@ -1331,8 +1357,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, appendUCS4(aSynAuth, nUTF32, eEscapeType, ePart, eCharset, false); } - m_aAuth.set(m_aAbsURIRef, aSynAuth.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aAuth.set(m_aAbsURIRef, aSynAuth, m_aAbsURIRef.getLength()); } else { @@ -1352,8 +1377,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, appendUCS4(aSynAuth, nUTF32, eEscapeType, ePart, eCharset, false); } - m_aAuth.set(m_aAbsURIRef, aSynAuth.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aAuth.set(m_aAbsURIRef, aSynAuth, m_aAbsURIRef.getLength()); } } if (pHostPortBegin) @@ -1444,8 +1468,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, appendUCS4(aSynQuery, nUTF32, eEscapeType, PART_URIC, eCharset, true); } - m_aQuery.set(m_aAbsURIRef, aSynQuery.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aQuery.set(m_aAbsURIRef, aSynQuery, m_aAbsURIRef.getLength()); } // Parse #<fragment> @@ -1461,8 +1484,7 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef, appendUCS4(aSynFragment, nUTF32, eEscapeType, PART_URIC, eCharset, true); } - m_aFragment.set(m_aAbsURIRef, aSynFragment.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aFragment.set(m_aAbsURIRef, aSynFragment, m_aAbsURIRef.getLength()); } if (pPos != pEnd) @@ -2059,8 +2081,9 @@ bool INetURLObject::convertIntToExt(std::u16string_view rTheIntURIRef, DecodeMechanism eDecodeMechanism, rtl_TextEncoding eCharset) { - OUString aSynExtURIRef(encodeText(rTheIntURIRef, PART_VISIBLE, - EncodeMechanism::NotCanonical, eCharset, true)); + OUStringBuffer aSynExtURIRef(256); + encodeText(aSynExtURIRef, rTheIntURIRef, PART_VISIBLE, + EncodeMechanism::NotCanonical, eCharset, true); sal_Unicode const * pBegin = aSynExtURIRef.getStr(); sal_Unicode const * pEnd = pBegin + aSynExtURIRef.getLength(); sal_Unicode const * p = pBegin; @@ -2068,8 +2091,7 @@ bool INetURLObject::convertIntToExt(std::u16string_view rTheIntURIRef, bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::Kind::Internal; if (bConvert) { - aSynExtURIRef = - aSynExtURIRef.replaceAt(0, p - pBegin, + comphelper::string::replaceAt(aSynExtURIRef, 0, p - pBegin, OUString::createFromAscii(pPrefix->m_pTranslatedPrefix)); } rTheExtURIRef = decode(aSynExtURIRef, eDecodeMechanism, eCharset); @@ -2082,8 +2104,9 @@ bool INetURLObject::convertExtToInt(std::u16string_view rTheExtURIRef, DecodeMechanism eDecodeMechanism, rtl_TextEncoding eCharset) { - OUString aSynIntURIRef(encodeText(rTheExtURIRef, PART_VISIBLE, - EncodeMechanism::NotCanonical, eCharset, true)); + OUStringBuffer aSynIntURIRef(256); + encodeText(aSynIntURIRef, rTheExtURIRef, PART_VISIBLE, + EncodeMechanism::NotCanonical, eCharset, true); sal_Unicode const * pBegin = aSynIntURIRef.getStr(); sal_Unicode const * pEnd = pBegin + aSynIntURIRef.getLength(); sal_Unicode const * p = pBegin; @@ -2091,9 +2114,8 @@ bool INetURLObject::convertExtToInt(std::u16string_view rTheExtURIRef, bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::Kind::External; if (bConvert) { - aSynIntURIRef = - aSynIntURIRef.replaceAt(0, p - pBegin, - OUString::createFromAscii(pPrefix->m_pTranslatedPrefix)); + comphelper::string::replaceAt(aSynIntURIRef, 0, p - pBegin, + OUString::createFromAscii(pPrefix->m_pTranslatedPrefix)); } rTheIntURIRef = decode(aSynIntURIRef, eDecodeMechanism, eCharset); return bConvert; @@ -2262,8 +2284,9 @@ bool INetURLObject::setUser(std::u16string_view rTheUser, return false; } - OUString aNewUser(encodeText(rTheUser, PART_USER_PASSWORD, - EncodeMechanism::WasEncoded, eCharset, false)); + OUStringBuffer aNewUser; + encodeText(aNewUser, rTheUser, PART_USER_PASSWORD, + EncodeMechanism::WasEncoded, eCharset, false); sal_Int32 nDelta; if (m_aUser.isPresent()) nDelta = m_aUser.set(m_aAbsURIRef, aNewUser); @@ -2317,8 +2340,9 @@ bool INetURLObject::setPassword(std::u16string_view rThePassword, { if (!getSchemeInfo().m_bPassword) return false; - OUString aNewAuth(encodeText(rThePassword, PART_USER_PASSWORD, - EncodeMechanism::WasEncoded, eCharset, false)); + OUStringBuffer aNewAuth; + encodeText(aNewAuth, rThePassword, PART_USER_PASSWORD, + EncodeMechanism::WasEncoded, eCharset, false); sal_Int32 nDelta; if (m_aAuth.isPresent()) nDelta = m_aAuth.set(m_aAbsURIRef, aNewAuth); @@ -2831,63 +2855,47 @@ bool INetURLObject::parseHostOrNetBiosName( EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bNetBiosName, OUStringBuffer* pCanonic) { + if (pBegin >= pEnd) + return true; sal_Int32 nOriginalCanonicLength = pCanonic ? pCanonic->getLength() : 0; - if (pBegin < pEnd) + if (sal_Unicode const* p = pBegin; parseHost(p, pEnd, pCanonic) && p == pEnd) + return true; + if (pCanonic) + pCanonic->setLength(nOriginalCanonicLength); // discard parseHost results + if (!bNetBiosName) + return false; + while (pBegin < pEnd) { - sal_Unicode const * p = pBegin; - if (!parseHost(p, pEnd, pCanonic) || p != pEnd) + EscapeType eEscapeType; + switch (sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, eMechanism, eCharset, eEscapeType)) { - if (bNetBiosName) - { - OUStringBuffer buf; - while (pBegin < pEnd) + default: + if (INetMIME::isVisible(nUTF32)) { - EscapeType eEscapeType; - sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, - eMechanism, eCharset, - eEscapeType); - if (!INetMIME::isVisible(nUTF32)) - { - if (pCanonic) - pCanonic->setLength(nOriginalCanonicLength); - return false; - } - if (!rtl::isAsciiAlphanumeric(nUTF32)) - switch (nUTF32) - { - case '"': - case '*': - case '+': - case ',': - case '/': - case ':': - case ';': - case '<': - case '=': - case '>': - case '?': - case '[': - case '\\': - case ']': - case '`': - case '|': - return false; - } - if (pCanonic != nullptr) { - appendUCS4( - buf, nUTF32, eEscapeType, PART_URIC, - eCharset, true); - } + if (pCanonic) + appendUCS4(*pCanonic, nUTF32, eEscapeType, PART_URIC, eCharset, true); + break; } - if (pCanonic) - pCanonic->append(buf); - } - else - { + [[fallthrough]]; + case '"': + case '*': + case '+': + case ',': + case '/': + case ':': + case ';': + case '<': + case '=': + case '>': + case '?': + case '[': + case '\\': + case ']': + case '`': + case '|': if (pCanonic) pCanonic->setLength(nOriginalCanonicLength); return false; - } } } return true; @@ -2904,8 +2912,7 @@ bool INetURLObject::setHost(std::u16string_view rTheHost, { case INetProtocol::File: { - OUString sTemp(aSynHost.toString()); - if (sTemp.equalsIgnoreAsciiCase("localhost")) + if (OUString::unacquired(aSynHost).equalsIgnoreAsciiCase("localhost")) { aSynHost.setLength(0); } @@ -2926,7 +2933,7 @@ bool INetURLObject::setHost(std::u16string_view rTheHost, aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(), EncodeMechanism::WasEncoded, eCharset, bNetBiosName, &aSynHost)) return false; - sal_Int32 nDelta = m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear()); + sal_Int32 nDelta = m_aHost.set(m_aAbsURIRef, aSynHost); m_aPort += nDelta; m_aPath += nDelta; m_aQuery += nDelta; @@ -3191,18 +3198,18 @@ failed: return false; } -bool INetURLObject::setPath(OUString const & rThePath, +bool INetURLObject::setPath(std::u16string_view rThePath, EncodeMechanism eMechanism, rtl_TextEncoding eCharset) { OUStringBuffer aSynPath(256); - sal_Unicode const * p = rThePath.getStr(); - sal_Unicode const * pEnd = p + rThePath.getLength(); + sal_Unicode const * p = rThePath.data(); + sal_Unicode const * pEnd = p + rThePath.size(); if (!parsePath(m_eScheme, &p, pEnd, eMechanism, eCharset, false, '/', 0x80000000, 0x80000000, 0x80000000, aSynPath) || p != pEnd) return false; - sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear()); + sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath); m_aQuery += nDelta; m_aFragment += nDelta; return true; @@ -3346,14 +3353,14 @@ bool INetURLObject::insertName(std::u16string_view rTheName, OUStringBuffer aNewPath(256); aNewPath.append(pPathBegin, pPrefixEnd - pPathBegin); aNewPath.append('/'); - aNewPath.append(encodeText(rTheName, PART_PCHAR, - eMechanism, eCharset, true)); + encodeText(aNewPath, rTheName, PART_PCHAR, + eMechanism, eCharset, true); if (bInsertSlash) { aNewPath.append('/'); } aNewPath.append(pSuffixBegin, pPathEnd - pSuffixBegin); - return setPath(aNewPath.makeStringAndClear(), EncodeMechanism::NotCanonical, + return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); } @@ -3375,8 +3382,9 @@ bool INetURLObject::setQuery(std::u16string_view rTheQuery, { if (!getSchemeInfo().m_bQuery) return false; - OUString aNewQuery(encodeText(rTheQuery, PART_URIC, - eMechanism, eCharset, true)); + OUStringBuffer aNewQuery; + encodeText(aNewQuery, rTheQuery, PART_URIC, + eMechanism, eCharset, true); sal_Int32 nDelta; if (m_aQuery.isPresent()) nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery); @@ -3408,8 +3416,9 @@ bool INetURLObject::setFragment(std::u16string_view rTheFragment, { if (HasError()) return false; - OUString aNewFragment(encodeText(rTheFragment, PART_URIC, - eMechanism, eCharset, true)); + OUStringBuffer aNewFragment; + encodeText(aNewFragment, rTheFragment, PART_URIC, + eMechanism, eCharset, true); if (m_aFragment.isPresent()) m_aFragment.set(m_aAbsURIRef, aNewFragment); else @@ -3432,22 +3441,21 @@ bool INetURLObject::hasDosVolume(FSysStyle eStyle) const } // static -OUString INetURLObject::encodeText(sal_Unicode const * pBegin, - sal_Unicode const * pEnd, - Part ePart, EncodeMechanism eMechanism, - rtl_TextEncoding eCharset, - bool bKeepVisibleEscapes) +void INetURLObject::encodeText( OUStringBuffer& rOutputBuffer, + sal_Unicode const * pBegin, + sal_Unicode const * pEnd, + Part ePart, EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + bool bKeepVisibleEscapes) { - OUStringBuffer aResult(256); while (pBegin < pEnd) { EscapeType eEscapeType; sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, eMechanism, eCharset, eEscapeType); - appendUCS4(aResult, nUTF32, eEscapeType, ePart, + appendUCS4(rOutputBuffer, nUTF32, eEscapeType, ePart, eCharset, bKeepVisibleEscapes); } - return aResult.makeStringAndClear(); } // static @@ -3711,7 +3719,7 @@ bool INetURLObject::operator ==(INetURLObject const & rObject) const if (m_eScheme != rObject.m_eScheme) return false; if (m_eScheme == INetProtocol::NotValid) - return m_aAbsURIRef.toString() == rObject.m_aAbsURIRef.toString(); + return std::u16string_view(m_aAbsURIRef) == std::u16string_view(rObject.m_aAbsURIRef); if ((m_aScheme.compare( rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef) != 0) @@ -3764,7 +3772,7 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, std::u16string_view rThePassword, std::u16string_view rTheHost, sal_uInt32 nThePort, - OUString const & rThePath) + std::u16string_view rThePath) { setInvalid(); m_eScheme = eTheScheme; @@ -3781,10 +3789,10 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, { if (!rTheUser.empty()) { - m_aUser.set(m_aAbsURIRef, - encodeText(rTheUser, PART_USER_PASSWORD, - EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false), - m_aAbsURIRef.getLength()); + OUStringBuffer aNewUser; + encodeText(aNewUser, rTheUser, PART_USER_PASSWORD, + EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false); + m_aUser.set(m_aAbsURIRef, aNewUser, m_aAbsURIRef.getLength()); bUserInfo = true; } } @@ -3798,10 +3806,10 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, if (getSchemeInfo().m_bPassword) { m_aAbsURIRef.append(':'); - m_aAuth.set(m_aAbsURIRef, - encodeText(rThePassword, PART_USER_PASSWORD, - EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false), - m_aAbsURIRef.getLength()); + OUStringBuffer aNewAuth; + encodeText(aNewAuth, rThePassword, PART_USER_PASSWORD, + EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false); + m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aAbsURIRef.getLength()); bUserInfo = true; } else @@ -3820,8 +3828,7 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, { case INetProtocol::File: { - OUString sTemp(aSynHost.toString()); - if (sTemp.equalsIgnoreAsciiCase( "localhost" )) + if (OUString::unacquired(aSynHost).equalsIgnoreAsciiCase( "localhost" )) { aSynHost.setLength(0); } @@ -3852,8 +3859,7 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, setInvalid(); return false; } - m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aHost.set(m_aAbsURIRef, aSynHost, m_aAbsURIRef.getLength()); if (nThePort != 0) { if (getSchemeInfo().m_bPort) @@ -3877,8 +3883,8 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, } } OUStringBuffer aSynPath(256); - sal_Unicode const * p = rThePath.getStr(); - sal_Unicode const * pEnd = p + rThePath.getLength(); + sal_Unicode const * p = rThePath.data(); + sal_Unicode const * pEnd = p + rThePath.size(); if (!parsePath(m_eScheme, &p, pEnd, EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false, '/', 0x80000000, 0x80000000, 0x80000000, aSynPath) || p != pEnd) @@ -3886,13 +3892,12 @@ bool INetURLObject::ConcatData(INetProtocol eTheScheme, setInvalid(); return false; } - m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear(), - m_aAbsURIRef.getLength()); + m_aPath.set(m_aAbsURIRef, aSynPath, m_aAbsURIRef.getLength()); return true; } // static -OUString INetURLObject::GetAbsURL(OUString const & rTheBaseURIRef, +OUString INetURLObject::GetAbsURL(std::u16string_view rTheBaseURIRef, OUString const & rTheRelURIRef, EncodeMechanism eEncodeMechanism, DecodeMechanism eDecodeMechanism, @@ -3920,7 +3925,7 @@ OUString INetURLObject::getExternalURL() const { OUString aTheExtURIRef; translateToExternal( - m_aAbsURIRef.toString(), aTheExtURIRef); + m_aAbsURIRef, aTheExtURIRef); return aTheExtURIRef; } @@ -3955,11 +3960,10 @@ const OUString & INetURLObject::GetSchemeName(INetProtocol eTheScheme) } // static -INetProtocol INetURLObject::CompareProtocolScheme(OUString const & - rTheAbsURIRef) +INetProtocol INetURLObject::CompareProtocolScheme(std::u16string_view aTheAbsURIRef) { - sal_Unicode const * p = rTheAbsURIRef.getStr(); - PrefixInfo const * pPrefix = getPrefix(p, p + rTheAbsURIRef.getLength()); + sal_Unicode const * p = aTheAbsURIRef.data(); + PrefixInfo const * pPrefix = getPrefix(p, p + aTheAbsURIRef.size()); return pPrefix ? pPrefix->m_eScheme : INetProtocol::NotValid; } @@ -4049,7 +4053,7 @@ bool INetURLObject::removeSegment(sal_Int32 nIndex, bool bIgnoreFinalSlash) aNewPath.append('/'); } - return setPath(aNewPath.makeStringAndClear(), EncodeMechanism::NotCanonical, + return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); } @@ -4094,12 +4098,11 @@ bool INetURLObject::setName(std::u16string_view rTheName, EncodeMechanism eMecha while (p != pSegEnd && *p != ';') ++p; - return setPath( - std::u16string_view(pPathBegin, pSegBegin - pPathBegin) - + encodeText(rTheName, PART_PCHAR, eMechanism, eCharset, true) - + std::u16string_view(p, pPathEnd - p), - EncodeMechanism::NotCanonical, - RTL_TEXTENCODING_UTF8); + OUStringBuffer aNewPath(256); + aNewPath.append(std::u16string_view(pPathBegin, pSegBegin - pPathBegin)); + encodeText(aNewPath, rTheName, PART_PCHAR, eMechanism, eCharset, true); + aNewPath.append(std::u16string_view(p, pPathEnd - p)); + return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); } bool INetURLObject::hasExtension() @@ -4171,12 +4174,11 @@ bool INetURLObject::setBase(std::u16string_view rTheBase, sal_Int32 nIndex, if (!pExtension) pExtension = p; - return setPath( - std::u16string_view(pPathBegin, pSegBegin - pPathBegin) - + encodeText(rTheBase, PART_PCHAR, eMechanism, eCharset, true) - + std::u16string_view(pExtension, pPathEnd - pExtension), - EncodeMechanism::NotCanonical, - RTL_TEXTENCODING_UTF8); + OUStringBuffer aNewPath(256); + aNewPath.append(std::u16string_view(pPathBegin, pSegBegin - pPathBegin)); + encodeText(aNewPath, rTheBase, PART_PCHAR, eMechanism, eCharset, true); + aNewPath.append(std::u16string_view(pExtension, pPathEnd - pExtension)); + return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); } OUString INetURLObject::getExtension(sal_Int32 nIndex, @@ -4231,12 +4233,11 @@ bool INetURLObject::setExtension(std::u16string_view rTheExtension, if (!pExtension) pExtension = p; - return setPath( - OUString::Concat(std::u16string_view(pPathBegin, pExtension - pPathBegin)) + "." - + encodeText(rTheExtension, PART_PCHAR, EncodeMechanism::WasEncoded, eCharset, true) - + std::u16string_view(p, pPathEnd - p), - EncodeMechanism::NotCanonical, - RTL_TEXTENCODING_UTF8); + OUStringBuffer aNewPath(256); + aNewPath.append(OUString::Concat(std::u16string_view(pPathBegin, pExtension - pPathBegin)) + "."); + encodeText(aNewPath, rTheExtension, PART_PCHAR, EncodeMechanism::WasEncoded, eCharset, true); + aNewPath.append(std::u16string_view(p, pPathEnd - p)); + return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); } bool INetURLObject::removeExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash) diff --git a/tools/source/fsys/wldcrd.cxx b/tools/source/fsys/wldcrd.cxx index 6e0259696aca..e8199975c6e5 100644 --- a/tools/source/fsys/wldcrd.cxx +++ b/tools/source/fsys/wldcrd.cxx @@ -25,85 +25,96 @@ * '?' in pWild mean match exactly one character. * */ -bool WildCard::ImpMatch( const sal_Unicode *pWild, const sal_Unicode *pStr ) +bool WildCard::ImpMatch( std::u16string_view aWild, std::u16string_view aStr ) { - int pos=0; - int flag=0; + const sal_Unicode* pPosAfterAsterisk = nullptr; + const sal_Unicode* pWild = aWild.data(); + const sal_Unicode* pWildEnd = aWild.data() + aWild.size(); + const sal_Unicode* pStr = aStr.data(); + const sal_Unicode* pStrEnd = aStr.data() + aStr.size(); - while ( *pWild || flag ) + while (pWild != pWildEnd) { switch (*pWild) { case '?': - if ( *pStr == '\0' ) + if ( pStr == pStrEnd ) return false; - break; - - default: - if ( (*pWild == '\\') && ((*(pWild+1)=='?') || (*(pWild+1) == '*')) ) + break; // Match -> proceed to the next character + case '\\': // Escaping '?' and '*'; don't we need to escape '\\'? + if ((pWild + 1 != pWildEnd) && ((*(pWild + 1) == '?') || (*(pWild + 1) == '*'))) pWild++; - if ( *pWild != *pStr ) - if ( !pos ) - return false; - else - pWild += pos; - else - break; - // WARNING/TODO: may cause execution of next case in some - // circumstances! + [[fallthrough]]; + default: // No wildcard, literal match + if (pStr == pStrEnd) + return false; + if (*pWild == *pStr) + break; // Match -> proceed to the next character + if (!pPosAfterAsterisk) + return false; + pWild = pPosAfterAsterisk; [[fallthrough]]; case '*': - while ( *pWild == '*' ) + while ( pWild != pWildEnd && *pWild == '*' ) pWild++; - if ( *pWild == '\0' ) + if ( pWild == pWildEnd ) return true; - flag = 1; - pos = 0; - if ( *pStr == '\0' ) - return ( *pWild == '\0' ); - while ( *pStr && *pStr != *pWild ) + // Consider strange things like "**?*?*" + while (*pWild == '?') { - if ( *pWild == '?' ) { + if (pStr == pStrEnd) + return false; + pWild++; + pStr++; + while (pWild != pWildEnd && *pWild == '*') pWild++; - while ( *pWild == '*' ) - pWild++; - } + if (pWild == pWildEnd) + return true; + } + // At this point, we are past wildcards, and a literal match must follow + if ( pStr == pStrEnd ) + return false; + pPosAfterAsterisk = pWild; + if ((*pWild == '\\') && (pWild + 1 != pWildEnd) && ((*(pWild + 1) == '?') || (*(pWild + 1) == '*'))) + pWild++; + while (*pStr != *pWild) + { pStr++; - if ( *pStr == '\0' ) - return ( *pWild == '\0' ); + if ( pStr == pStrEnd ) + return false; } - break; + break; // Match -> proceed to the next character } - if ( *pWild != '\0' ) - pWild++; - if ( *pStr != '\0' ) - pStr++; - else - flag = 0; - if ( flag ) - pos--; + // We arrive here when the current characters in pWild and pStr match + assert(pWild != pWildEnd); + pWild++; + assert(pStr != pStrEnd); + pStr++; + if (pWild == pWildEnd && pPosAfterAsterisk && pStr != pStrEnd) + pWild = pPosAfterAsterisk; // Try again on the rest of pStr } - return ( *pStr == '\0' ) && ( *pWild == '\0' ); + assert(pWild == pWildEnd); + return pStr == pStrEnd; } bool WildCard::Matches( std::u16string_view rString ) const { - OUString aTmpWild = aWildString; + std::u16string_view aTmpWild = aWildString; - sal_Int32 nSepPos; + size_t nSepPos; if ( cSepSymbol != '\0' ) { - while ( (nSepPos = aTmpWild.indexOf(cSepSymbol)) != -1 ) + while ( (nSepPos = aTmpWild.find(cSepSymbol)) != std::u16string_view::npos ) { // Check all split wildcards - if ( ImpMatch( aTmpWild.subView( 0, nSepPos ).data(), rString.data() ) ) + if ( ImpMatch( aTmpWild.substr( 0, nSepPos ), rString ) ) return true; - aTmpWild = aTmpWild.copy(nSepPos + 1); // remove separator + aTmpWild = aTmpWild.substr(nSepPos + 1); // remove separator } } - return ImpMatch( aTmpWild.getStr(), rString.data() ); + return ImpMatch( aTmpWild, rString ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/source/generic/bigint.cxx b/tools/source/generic/bigint.cxx index f6627200a61c..51810cab17c2 100644 --- a/tools/source/generic/bigint.cxx +++ b/tools/source/generic/bigint.cxx @@ -475,20 +475,25 @@ BigInt::BigInt( const BigInt& rBigInt ) nVal = rBigInt.nVal; } -BigInt::BigInt( const OUString& rString ) +BigInt::BigInt( std::u16string_view rString ) : nLen(0) { bIsNeg = false; nVal = 0; bool bNeg = false; - const sal_Unicode* p = rString.getStr(); + auto p = rString.begin(); + auto pEnd = rString.end(); + if (p == pEnd) + return; if ( *p == '-' ) { bNeg = true; p++; } - while( *p >= '0' && *p <= '9' ) + if (p == pEnd) + return; + while( p != pEnd && *p >= '0' && *p <= '9' ) { *this *= 10; *this += *p - '0'; diff --git a/tools/source/generic/color.cxx b/tools/source/generic/color.cxx index 5df32719eb2c..1c740f03df03 100644 --- a/tools/source/generic/color.cxx +++ b/tools/source/generic/color.cxx @@ -27,6 +27,7 @@ #include <tools/color.hxx> #include <tools/helpers.hxx> #include <tools/long.hxx> +#include <o3tl/string_view.hxx> #include <basegfx/color/bcolortools.hxx> void Color::IncreaseLuminance(sal_uInt8 cLumInc) @@ -158,30 +159,30 @@ Color Color::HSBtoRGB( sal_uInt16 nHue, sal_uInt16 nSat, sal_uInt16 nBri ) return Color( cR, cG, cB ); } -Color Color::STRtoRGB(const OUString& colorname) +Color Color::STRtoRGB(std::u16string_view colorname) { Color col; - if(colorname.isEmpty()) return col; + if(colorname.empty()) return col; - switch(colorname.getLength()){ + switch(colorname.size()){ case 7: - col.mValue = colorname.copy(1,6).toUInt32(16); + col.mValue = o3tl::toUInt32(colorname.substr(1,6), 16); break; case 6: - col.mValue = colorname.toUInt32(16); + col.mValue = o3tl::toUInt32(colorname, 16); break; case 4: { sal_Unicode data[6] = { colorname[1], colorname[1], colorname[2], colorname[2], colorname[3], colorname[3] }; - col.mValue = OUString(data,6).toUInt32(16); + col.mValue = o3tl::toUInt32(std::u16string_view(data,6), 16); break; } case 3: { sal_Unicode data[6] = { colorname[0], colorname[0], colorname[1], colorname[1], colorname[2], colorname[2] }; - col.mValue = OUString(data,6).toUInt32(16); + col.mValue = o3tl::toUInt32(std::u16string_view(data,6), 16); break; } default: diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx index 93a92fb3a12a..7f2ffba1003d 100644 --- a/tools/source/generic/fract.cxx +++ b/tools/source/generic/fract.cxx @@ -19,7 +19,7 @@ #include <tools/fract.hxx> #include <tools/debug.hxx> -#include <tools/stream.hxx> +#include <o3tl/hash_combine.hxx> #include <o3tl/safeint.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> @@ -182,6 +182,9 @@ namespace sal_Int32 gcd1 = std::gcd(i.numerator(), den); sal_Int32 gcd2 = std::gcd(num, i.denominator()); + if (!gcd1 || !gcd2) + return true; + bool fail = false; fail |= o3tl::checked_multiply(i.numerator() / gcd1, num / gcd2, num); fail |= o3tl::checked_multiply(i.denominator() / gcd2, den / gcd1, den); @@ -471,4 +474,13 @@ static void rational_ReduceInaccurate(boost::rational<sal_Int32>& rRational, uns rRational.assign( bNeg ? -nMul : nMul, nDiv ); } +size_t Fraction::GetHashValue() const +{ + size_t hash = 0; + o3tl::hash_combine( hash, mnNumerator ); + o3tl::hash_combine( hash, mnDenominator ); + o3tl::hash_combine( hash, mbValid ); + return hash; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/source/generic/gen.cxx b/tools/source/generic/gen.cxx index 1fe47071d4ce..27120d6abbd1 100644 --- a/tools/source/generic/gen.cxx +++ b/tools/source/generic/gen.cxx @@ -18,14 +18,13 @@ */ #include <sal/config.h> -#include <sal/log.hxx> +#include <rtl/string.hxx> #include <algorithm> -#include <cassert> -#include <sstream> +#include <tuple> +#include <o3tl/hash_combine.hxx> #include <o3tl/safeint.hxx> #include <tools/gen.hxx> -#include <tools/stream.hxx> OString Pair::toString() const { @@ -35,6 +34,14 @@ OString Pair::toString() const return OString::number(A()) + ", " + OString::number(B()); } +size_t Pair::GetHashValue() const +{ + size_t hash = 0; + o3tl::hash_combine( hash, nA ); + o3tl::hash_combine( hash, nB ); + return hash; +} + void tools::Rectangle::SetSize( const Size& rSize ) { if ( rSize.Width() < 0 ) diff --git a/tools/source/generic/point.cxx b/tools/source/generic/point.cxx index e9c3bd842a15..1aba284ff27f 100644 --- a/tools/source/generic/point.cxx +++ b/tools/source/generic/point.cxx @@ -18,7 +18,6 @@ */ #include <tools/gen.hxx> -#include <basegfx/numeric/ftools.hxx> void Point::RotateAround( Point& rPoint, Degree10 nOrientation ) const diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx index 13d2df0e47ef..166803b38f04 100644 --- a/tools/source/generic/poly.cxx +++ b/tools/source/generic/poly.cxx @@ -38,9 +38,8 @@ #include <memory> #include <vector> -#include <iterator> #include <algorithm> -#include <cstdlib> +#include <cassert> #include <cstring> #include <limits.h> #include <cmath> @@ -225,21 +224,21 @@ ImplPolygon::ImplPolygon( const Point& rCenter, tools::Long nRadX, tools::Long n mnPoints = 0; } -ImplPolygon::ImplPolygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd, - PolyStyle eStyle ) +ImplPolygon::ImplPolygon(const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd, + PolyStyle eStyle, const bool bClockWiseArcDirection) { const auto nWidth = rBound.GetWidth(); const auto nHeight = rBound.GetHeight(); - if( ( nWidth != 0 ) && ( nHeight != 0 ) ) + if ((nWidth != 0) && (nHeight != 0)) { - const Point aCenter( rBound.Center() ); + const Point aCenter(rBound.Center()); // tdf#142268 Get Top Left corner of rectangle (the rectangle is not always correctly created) const auto aBoundLeft = rBound.Left() < aCenter.X() ? rBound.Left() : rBound.Right(); const auto aBoundTop = rBound.Top() < aCenter.Y() ? rBound.Top() : rBound.Bottom(); const auto nRadX = o3tl::saturating_sub(aCenter.X(), aBoundLeft); const auto nRadY = o3tl::saturating_sub(aCenter.Y(), aBoundTop); - sal_uInt16 nPoints; + sal_uInt16 nPoints; tools::Long nRadXY; const bool bOverflow = o3tl::checked_multiply(nRadX, nRadY, nRadXY); @@ -270,17 +269,29 @@ ImplPolygon::ImplPolygon( const tools::Rectangle& rBound, const Point& rStart, c double fStep; sal_uInt16 nStart; sal_uInt16 nEnd; - // #i73608# If startPoint is equal to endPoint, then draw full circle instead of nothing (as Metafiles spec) - if( fDiff <= 0. ) - fDiff += 2 * M_PI; + + if (bClockWiseArcDirection == false) + { + // #i73608# If startPoint is equal to endPoint, then draw full circle instead of nothing (as Metafiles spec) + if (fDiff <= 0.) + fDiff += 2. * M_PI; + } + else + { + fDiff = (2. * M_PI) - fDiff; + if (fDiff > 2. * M_PI) + fDiff -= 2. * M_PI; + } // Proportionally shrink number of points( fDiff / (2PI) ); - nPoints = std::max( static_cast<sal_uInt16>( ( fDiff / (2 * M_PI) ) * nPoints ), sal_uInt16(16) ); - fStep = fDiff / ( nPoints - 1 ); + nPoints = std::max(static_cast<sal_uInt16>((fDiff / (2. * M_PI)) * nPoints), sal_uInt16(16)); + fStep = fDiff / (nPoints - 1); + if (bClockWiseArcDirection == true) + fStep = -fStep; - if( PolyStyle::Pie == eStyle ) + if (PolyStyle::Pie == eStyle) { - const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) ); + const Point aCenter2(FRound(fCenterX), FRound(fCenterY)); nStart = 1; nEnd = nPoints + 1; @@ -903,8 +914,9 @@ Polygon::Polygon( const Point& rCenter, tools::Long nRadX, tools::Long nRadY ) { } -Polygon::Polygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd, - PolyStyle eStyle ) : mpImplPolygon(ImplPolygon(rBound, rStart, rEnd, eStyle)) +Polygon::Polygon(const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd, + PolyStyle eStyle, const bool bClockWiseArcDirection) + : mpImplPolygon(ImplPolygon(rBound, rStart, rEnd, eStyle, bClockWiseArcDirection)) { } @@ -1093,8 +1105,8 @@ void Polygon::Optimize( PolyOptimizeFlags nOptimizeFlags ) /** Recursively subdivide cubic bezier curve via deCasteljau. - @param rPointIter - Output iterator, where the subdivided polylines are written to. + @param rPoints + Output vector, where the subdivided polylines are written to. @param d Squared difference of curve to a straight line @@ -1107,7 +1119,7 @@ void Polygon::Optimize( PolyOptimizeFlags nOptimizeFlags ) curve does not deviate more than one pixel from a straight line. */ -static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< Point > >& rPointIter, +static void ImplAdaptiveSubdivide( std::vector<Point>& rPoints, const double old_d2, int recursionDepth, const double d2, @@ -1143,7 +1155,8 @@ static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< P // stop if distance from line is guaranteed to be bounded by d if( old_d2 > d2 && recursionDepth < maxRecursionDepth && - distance2 >= d2 ) + distance2 >= d2 && + rPoints.size() < SAL_MAX_UINT16 ) { // deCasteljau bezier arc, split at t=0.5 // Foley/vanDam, p. 508 @@ -1159,15 +1172,15 @@ static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< P // subdivide further ++recursionDepth; - ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y); - ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y); + ImplAdaptiveSubdivide(rPoints, distance2, recursionDepth, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y); + ImplAdaptiveSubdivide(rPoints, distance2, recursionDepth, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y); } else { // requested resolution reached. // Add end points to output iterator. // order is preserved, since this is so to say depth first traversal. - *rPointIter++ = Point( FRound(P1x), FRound(P1y) ); + rPoints.push_back(Point(FRound(P1x), FRound(P1y))); } } @@ -1183,7 +1196,6 @@ void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const sal_uInt16 nPts( GetSize() ); ::std::vector< Point > aPoints; aPoints.reserve( nPts ); - ::std::back_insert_iterator< ::std::vector< Point > > aPointIter( aPoints ); for(i=0; i<nPts;) { @@ -1197,7 +1209,7 @@ void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const ( PolyFlags::Control == mpImplPolygon->mxFlagAry[ i + 2 ] ) && ( PolyFlags::Normal == P4 || PolyFlags::Smooth == P4 || PolyFlags::Symmetric == P4 ) ) { - ImplAdaptiveSubdivide( aPointIter, d*d+1.0, 0, d*d, + ImplAdaptiveSubdivide( aPoints, d*d+1.0, 0, d*d, mpImplPolygon->mxPointAry[ i ].X(), mpImplPolygon->mxPointAry[ i ].Y(), mpImplPolygon->mxPointAry[ i+1 ].X(), mpImplPolygon->mxPointAry[ i+1 ].Y(), mpImplPolygon->mxPointAry[ i+2 ].X(), mpImplPolygon->mxPointAry[ i+2 ].Y(), @@ -1207,7 +1219,7 @@ void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const } } - *aPointIter++ = mpImplPolygon->mxPointAry[ i++ ]; + aPoints.push_back(mpImplPolygon->mxPointAry[i++]); if (aPoints.size() >= SAL_MAX_UINT16) { @@ -1567,7 +1579,7 @@ void Polygon::Insert( sal_uInt16 nPos, const tools::Polygon& rPoly ) Point& Polygon::operator[]( sal_uInt16 nPos ) { - DBG_ASSERT( nPos < mpImplPolygon->mnPoints, "Polygon::[]: nPos >= nPoints" ); + assert( nPos < mpImplPolygon->mnPoints ); return mpImplPolygon->mxPointAry[nPos]; } @@ -1663,7 +1675,12 @@ void Polygon::ImplRead( SvStream& rIStream ) if ( bHasPolyFlags ) { mpImplPolygon->mxFlagAry.reset(new PolyFlags[mpImplPolygon->mnPoints]); - rIStream.ReadBytes(mpImplPolygon->mxFlagAry.get(), mpImplPolygon->mnPoints); + auto nRead = rIStream.ReadBytes(mpImplPolygon->mxFlagAry.get(), mpImplPolygon->mnPoints); + if (nRead != mpImplPolygon->mnPoints) + { + SAL_WARN("tools", "Short read"); + memset(mpImplPolygon->mxFlagAry.get() + nRead, 0, mpImplPolygon->mnPoints - nRead); + } } } diff --git a/tools/source/inet/inetmime.cxx b/tools/source/inet/inetmime.cxx index f7265523b6e2..2a57c099c93f 100644 --- a/tools/source/inet/inetmime.cxx +++ b/tools/source/inet/inetmime.cxx @@ -131,30 +131,6 @@ std::unique_ptr<sal_Unicode[]> convertToUnicode(const char * pBegin, return pBuffer; } -/** Put the UTF-16 encoding of a UTF-32 character into a buffer. - - @param pBuffer Points to a buffer, must not be null. - - @param nUTF32 A UTF-32 character, must be in the range 0..0x10FFFF. - - @return A pointer past the UTF-16 characters put into the buffer - (i.e., pBuffer + 1 or pBuffer + 2). - */ -sal_Unicode * putUTF32Character(sal_Unicode * pBuffer, - sal_uInt32 nUTF32) -{ - DBG_ASSERT(rtl::isUnicodeCodePoint(nUTF32), "putUTF32Character(): Bad char"); - if (nUTF32 < 0x10000) - *pBuffer++ = sal_Unicode(nUTF32); - else - { - nUTF32 -= 0x10000; - *pBuffer++ = sal_Unicode(0xD800 | (nUTF32 >> 10)); - *pBuffer++ = sal_Unicode(0xDC00 | (nUTF32 & 0x3FF)); - } - return pBuffer; -} - void writeUTF8(OStringBuffer & rSink, sal_uInt32 nChar) { // See RFC 2279 for a discussion of UTF-8. @@ -1027,11 +1003,11 @@ bool INetMIME::scanUnsigned(const sal_Unicode *& rBegin, // static sal_Unicode const * INetMIME::scanContentType( - OUString const & rStr, OUString * pType, + std::u16string_view rStr, OUString * pType, OUString * pSubType, INetContentTypeParameterList * pParameters) { - sal_Unicode const * pBegin = rStr.getStr(); - sal_Unicode const * pEnd = pBegin + rStr.getLength(); + sal_Unicode const * pBegin = rStr.data(); + sal_Unicode const * pEnd = pBegin + rStr.size(); sal_Unicode const * p = skipLinearWhiteSpaceComment(pBegin, pEnd); sal_Unicode const * pTypeBegin = p; while (p != pEnd && isTokenChar(*p)) @@ -1386,9 +1362,7 @@ OUString INetMIME::decodeHeaderFieldBody(const OString& rBody) if (translateUTF8Char(pUTF8End, pEnd, nCharacter)) { appendISO88591(sDecoded, pCopyBegin, p - 1); - sal_Unicode aUTF16Buf[2]; - sal_Int32 nUTF16Len = putUTF32Character(aUTF16Buf, nCharacter) - aUTF16Buf; - sDecoded.append(aUTF16Buf, nUTF16Len); + sDecoded.appendUtf32(nCharacter); p = pUTF8End; pCopyBegin = p; } diff --git a/tools/source/inet/inetmsg.cxx b/tools/source/inet/inetmsg.cxx index bb8a700d16f1..d58581e74200 100644 --- a/tools/source/inet/inetmsg.cxx +++ b/tools/source/inet/inetmsg.cxx @@ -22,6 +22,8 @@ #include <tools/inetmsg.hxx> #include <comphelper/string.hxx> #include <rtl/character.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> #include <map> @@ -52,32 +54,32 @@ static const char *months[12] = "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -static sal_uInt16 ParseNumber(const OString& rStr, sal_Int32& nIndex) +static sal_uInt16 ParseNumber(std::string_view rStr, size_t& nIndex) { - sal_Int32 n = nIndex; - while ((n < rStr.getLength()) + size_t n = nIndex; + while ((n < rStr.size()) && rtl::isAsciiDigit(static_cast<unsigned char>(rStr[n]))) n++; - OString aNum(rStr.copy(nIndex, (n - nIndex))); + std::string_view aNum(rStr.substr(nIndex, (n - nIndex))); nIndex = n; - return static_cast<sal_uInt16>(aNum.toInt32()); + return static_cast<sal_uInt16>(o3tl::toInt32(aNum)); } -static sal_uInt16 ParseMonth(const OString& rStr, sal_Int32& nIndex) +static sal_uInt16 ParseMonth(std::string_view rStr, size_t& nIndex) { - sal_Int32 n = nIndex; - while ((n < rStr.getLength()) + size_t n = nIndex; + while ((n < rStr.size()) && rtl::isAsciiAlpha(static_cast<unsigned char>(rStr[n]))) n++; - OString aMonth(rStr.copy(nIndex, 3)); + std::string_view aMonth(rStr.substr(nIndex, 3)); nIndex = n; sal_uInt16 i; for (i = 0; i < 12; i++) - if (aMonth.equalsIgnoreAsciiCase(months[i])) break; + if (o3tl::equalsIgnoreAsciiCase(aMonth, months[i])) break; return (i + 1); } @@ -92,20 +94,20 @@ bool INetMIMEMessage::ParseDateField ( if (aDateField.indexOf(':') != -1) { // Some DateTime format. - sal_Int32 nIndex = 0; + size_t nIndex = 0; // Skip over <Wkd> or <Weekday>, leading and trailing space. - while ((nIndex < aDateField.getLength()) && + while ((nIndex < o3tl::make_unsigned(aDateField.getLength())) && (aDateField[nIndex] == ' ')) nIndex++; while ( - (nIndex < aDateField.getLength()) && + (nIndex < o3tl::make_unsigned(aDateField.getLength())) && (rtl::isAsciiAlpha (static_cast<unsigned char>(aDateField[nIndex])) || (aDateField[nIndex] == ',') )) nIndex++; - while ((nIndex < aDateField.getLength()) && + while ((nIndex < o3tl::make_unsigned(aDateField.getLength())) && (aDateField[nIndex] == ' ')) nIndex++; @@ -143,7 +145,7 @@ bool INetMIMEMessage::ParseDateField ( rDateTime.SetSec (ParseNumber (aDateField, nIndex)); nIndex++; rDateTime.SetNanoSec (0); - const char cPossiblePlusMinus = nIndex < aDateField.getLength() ? aDateField[nIndex] : 0; + const char cPossiblePlusMinus = nIndex < o3tl::make_unsigned(aDateField.getLength()) ? aDateField[nIndex] : 0; if (cPossiblePlusMinus == '+' || cPossiblePlusMinus == '-') { // Offset from GMT: "(+|-)HHMM". diff --git a/tools/source/inet/inetstrm.cxx b/tools/source/inet/inetstrm.cxx index 62889bae4733..c68b232d967c 100644 --- a/tools/source/inet/inetstrm.cxx +++ b/tools/source/inet/inetstrm.cxx @@ -22,7 +22,6 @@ #include <cassert> #include <sal/types.h> -#include <rtl/strbuf.hxx> #include <tools/inetmsg.hxx> #include <tools/inetstrm.hxx> diff --git a/tools/source/memtools/multisel.cxx b/tools/source/memtools/multisel.cxx index 1f3f8eb5a23a..c6dd9d8c3146 100644 --- a/tools/source/memtools/multisel.cxx +++ b/tools/source/memtools/multisel.cxx @@ -468,7 +468,7 @@ void MultiSelection::SetTotalRange( const Range& rTotRange ) // StringRangeEnumerator -StringRangeEnumerator::StringRangeEnumerator( const OUString& i_rInput, +StringRangeEnumerator::StringRangeEnumerator( std::u16string_view i_rInput, sal_Int32 i_nMinNumber, sal_Int32 i_nMaxNumber, sal_Int32 i_nLogicalOffset @@ -566,18 +566,19 @@ void StringRangeEnumerator::insertJoinedRanges( } } -bool StringRangeEnumerator::setRange( const OUString& i_rNewRange ) +bool StringRangeEnumerator::setRange( std::u16string_view aNewRange ) { mnCount = 0; maSequence.clear(); - const sal_Unicode* pInput = i_rNewRange.getStr(); + auto pInput = aNewRange.begin(); + auto pInputEnd = aNewRange.end(); OUStringBuffer aNumberBuf( 16 ); std::vector< sal_Int32 > aNumbers; bool bSequence = false; - while( *pInput ) + while( pInput != pInputEnd ) { - while( *pInput >= '0' && *pInput <= '9' ) + while( pInput != pInputEnd && *pInput >= '0' && *pInput <= '9' ) aNumberBuf.append( *pInput++ ); if( !aNumberBuf.isEmpty() ) { @@ -585,7 +586,8 @@ bool StringRangeEnumerator::setRange( const OUString& i_rNewRange ) aNumbers.push_back( nNumber ); bSequence = false; } - + if (pInput == pInputEnd) + break; if( *pInput == '-' ) { bSequence = true; @@ -607,11 +609,10 @@ bool StringRangeEnumerator::setRange( const OUString& i_rNewRange ) aNumbers.clear(); bSequence = false; } - else if( *pInput && *pInput != ' ' ) + else if( *pInput != ' ' ) return false; // parse error - if( *pInput ) - pInput++; + pInput++; } // insert last entries if( bSequence && !aNumbers.empty() ) @@ -710,7 +711,7 @@ StringRangeEnumerator::Iterator StringRangeEnumerator::end( const o3tl::sorted_v return StringRangeEnumerator::Iterator( this, i_pPossibleValues, -1, -1 ); } -bool StringRangeEnumerator::getRangesFromString( const OUString& i_rPageRange, +bool StringRangeEnumerator::getRangesFromString( std::u16string_view i_rPageRange, std::vector< sal_Int32 >& o_rPageVector, sal_Int32 i_nMinNumber, sal_Int32 i_nMaxNumber, diff --git a/tools/source/misc/fix16.cxx b/tools/source/misc/fix16.cxx new file mode 100644 index 000000000000..978f77291dce --- /dev/null +++ b/tools/source/misc/fix16.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * libfixmath is Copyright (c) 2011-2021 Flatmush <Flatmush@gmail.com>, + * Petteri Aimonen <Petteri.Aimonen@gmail.com>, & libfixmath AUTHORS + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <tools/fix16.hxx> + +const fix16_t fix16_minimum = 0x80000000; /*!< the minimum value of fix16_t */ +const fix16_t fix16_overflow = 0x80000000; /*!< the value used to indicate overflows */ + +static inline uint32_t fix_abs(fix16_t in) +{ + if (in == fix16_minimum) + { + // minimum negative number has same representation as + // its absolute value in unsigned + return 0x80000000; + } + else + { + return (in >= 0) ? in : -in; + } +} + +/* 64-bit implementation for fix16_mul. Fastest version for e.g. ARM Cortex M3. + * Performs a 32*32 -> 64bit multiplication. The middle 32 bits are the result, + * bottom 16 bits are used for rounding, and upper 16 bits are used for overflow + * detection. + */ + +fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) +{ + int64_t product = static_cast<int64_t>(inArg0) * inArg1; + + // The upper 17 bits should all be the same (the sign). + uint32_t upper = (product >> 47); + + if (product < 0) + { + if (~upper) + return fix16_overflow; + + // This adjustment is required in order to round -1/2 correctly + product--; + } + else + { + if (upper) + return fix16_overflow; + } + + fix16_t result = product >> 16; + result += (product & 0x8000) >> 15; + + return result; +} + +/* 32-bit implementation of fix16_div. Fastest version for e.g. ARM Cortex M3. + * Performs 32-bit divisions repeatedly to reduce the remainder. For this to + * be efficient, the processor has to have 32-bit hardware division. + */ +#ifdef __GNUC__ +// Count leading zeros, using processor-specific instruction if available. +#define clz(x) (__builtin_clzl(x) - (8 * sizeof(long) - 32)) +#else +static uint8_t clz(uint32_t x) +{ + uint8_t result = 0; + if (x == 0) + return 32; + while (!(x & 0xF0000000)) + { + result += 4; + x <<= 4; + } + while (!(x & 0x80000000)) + { + result += 1; + x <<= 1; + } + return result; +} +#endif + +fix16_t fix16_div(fix16_t a, fix16_t b) +{ + // This uses a hardware 32/32 bit division multiple times, until we have + // computed all the bits in (a<<17)/b. Usually this takes 1-3 iterations. + + if (b == 0) + return fix16_minimum; + + uint32_t remainder = fix_abs(a); + uint32_t divider = fix_abs(b); + uint64_t quotient = 0; + int bit_pos = 17; + + // Kick-start the division a bit. + // This improves speed in the worst-case scenarios where N and D are large + // It gets a lower estimate for the result by N/(D >> 17 + 1). + if (divider & 0xFFF00000) + { + uint32_t shifted_div = (divider >> 17) + 1; + quotient = remainder / shifted_div; + uint64_t tmp = (quotient * static_cast<uint64_t>(divider)) >> 17; + remainder -= static_cast<uint32_t>(tmp); + } + + // If the divider is divisible by 2^n, take advantage of it. + while (!(divider & 0xF) && bit_pos >= 4) + { + divider >>= 4; + bit_pos -= 4; + } + + while (remainder && bit_pos >= 0) + { + // Shift remainder as much as we can without overflowing + int shift = clz(remainder); + if (shift > bit_pos) + shift = bit_pos; + remainder <<= shift; + bit_pos -= shift; + + uint32_t div = remainder / divider; + remainder = remainder % divider; + quotient += static_cast<uint64_t>(div) << bit_pos; + + if (div & ~(0xFFFFFFFF >> bit_pos)) + return fix16_overflow; + + remainder <<= 1; + bit_pos--; + } + + // Quotient is always positive so rounding is easy + quotient++; + + fix16_t result = quotient >> 1; + + // Figure out the sign of the result + if ((a ^ b) & 0x80000000) + { + if (result == fix16_minimum) + return fix16_overflow; + + result = -result; + } + + return result; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/tools/source/misc/json_writer.cxx b/tools/source/misc/json_writer.cxx index d6e34179f930..fbb29bb2472c 100644 --- a/tools/source/misc/json_writer.cxx +++ b/tools/source/misc/json_writer.cxx @@ -9,7 +9,6 @@ #include <tools/json_writer.hxx> #include <stdio.h> -#include <algorithm> #include <cstring> #include <rtl/math.hxx> @@ -30,6 +29,8 @@ JsonWriter::JsonWriter() ++mPos; *mPos = ' '; ++mPos; + + addValidationMark(); } JsonWriter::~JsonWriter() @@ -41,7 +42,7 @@ JsonWriter::~JsonWriter() ScopedJsonWriterNode JsonWriter::startNode(const char* pNodeName) { auto len = strlen(pNodeName); - ensureSpace(len + 6); + ensureSpace(len + 8); addCommaBeforeField(); @@ -53,6 +54,9 @@ ScopedJsonWriterNode JsonWriter::startNode(const char* pNodeName) mPos += 5; mStartNodeCount++; mbFirstFieldInNode = true; + + validate(); + return ScopedJsonWriterNode(*this); } @@ -64,12 +68,14 @@ void JsonWriter::endNode() *mPos = '}'; ++mPos; mbFirstFieldInNode = false; + + validate(); } ScopedJsonWriterArray JsonWriter::startArray(const char* pNodeName) { auto len = strlen(pNodeName); - ensureSpace(len + 6); + ensureSpace(len + 8); addCommaBeforeField(); @@ -81,6 +87,9 @@ ScopedJsonWriterArray JsonWriter::startArray(const char* pNodeName) mPos += 5; mStartNodeCount++; mbFirstFieldInNode = true; + + validate(); + return ScopedJsonWriterArray(*this); } @@ -92,6 +101,8 @@ void JsonWriter::endArray() *mPos = ']'; ++mPos; mbFirstFieldInNode = false; + + validate(); } ScopedJsonWriterStruct JsonWriter::startStruct() @@ -106,6 +117,9 @@ ScopedJsonWriterStruct JsonWriter::startStruct() ++mPos; mStartNodeCount++; mbFirstFieldInNode = true; + + validate(); + return ScopedJsonWriterStruct(*this); } @@ -117,6 +131,8 @@ void JsonWriter::endStruct() *mPos = '}'; ++mPos; mbFirstFieldInNode = false; + + validate(); } static char getEscapementChar(char ch) @@ -211,6 +227,8 @@ void JsonWriter::writeEscapedOUString(const OUString& rPropVal) ++mPos; } } + + validate(); } void JsonWriter::put(const char* pPropName, const OUString& rPropVal) @@ -234,6 +252,8 @@ void JsonWriter::put(const char* pPropName, const OUString& rPropVal) *mPos = '"'; ++mPos; + + validate(); } void JsonWriter::put(const char* pPropName, std::string_view rPropVal) @@ -287,6 +307,8 @@ void JsonWriter::put(const char* pPropName, std::string_view rPropVal) *mPos = '"'; ++mPos; + + validate(); } void JsonWriter::put(const char* pPropName, sal_Int64 nPropVal) @@ -305,6 +327,8 @@ void JsonWriter::put(const char* pPropName, sal_Int64 nPropVal) mPos += 3; mPos += sprintf(mPos, "%" SAL_PRIdINT64, nPropVal); + + validate(); } void JsonWriter::put(const char* pPropName, double fPropVal) @@ -324,6 +348,8 @@ void JsonWriter::put(const char* pPropName, double fPropVal) memcpy(mPos, sPropVal.getStr(), sPropVal.getLength()); mPos += sPropVal.getLength(); + + validate(); } void JsonWriter::put(const char* pPropName, bool nPropVal) @@ -347,6 +373,8 @@ void JsonWriter::put(const char* pPropName, bool nPropVal) pVal = "false"; memcpy(mPos, pVal, strlen(pVal)); mPos += strlen(pVal); + + validate(); } void JsonWriter::putSimpleValue(const OUString& rPropVal) @@ -363,6 +391,8 @@ void JsonWriter::putSimpleValue(const OUString& rPropVal) *mPos = '"'; ++mPos; + + validate(); } void JsonWriter::putRaw(std::string_view rRawBuf) @@ -373,6 +403,8 @@ void JsonWriter::putRaw(std::string_view rRawBuf) memcpy(mPos, rRawBuf.data(), rRawBuf.size()); mPos += rRawBuf.size(); + + validate(); } void JsonWriter::addCommaBeforeField() @@ -398,6 +430,8 @@ void JsonWriter::ensureSpace(int noMoreBytesRequired) mpBuffer = static_cast<char*>(realloc(mpBuffer, newSize)); mPos = mpBuffer + currentUsed; mSpaceAllocated = newSize; + + addValidationMark(); } } diff --git a/tools/source/ref/globname.cxx b/tools/source/ref/globname.cxx index fda6fafab53c..a41b29bba6d3 100644 --- a/tools/source/ref/globname.cxx +++ b/tools/source/ref/globname.cxx @@ -20,262 +20,156 @@ #include <stdio.h> #include <string.h> -#include <rtl/strbuf.hxx> +#include <comphelper/mimeconfighelper.hxx> #include <rtl/character.hxx> #include <tools/stream.hxx> #include <tools/globname.hxx> -// ImpSvGlobalName ------------------------------------------------------------ -ImpSvGlobalName::ImpSvGlobalName( const ImpSvGlobalName & rObj ) - : szData(rObj.szData) -{ -} - -ImpSvGlobalName::ImpSvGlobalName(sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, - sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, - sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15) -{ - szData.Data1 = n1; - szData.Data2 = n2; - szData.Data3 = n3; - szData.Data4[0] = b8; - szData.Data4[1] = b9; - szData.Data4[2] = b10; - szData.Data4[3] = b11; - szData.Data4[4] = b12; - szData.Data4[5] = b13; - szData.Data4[6] = b14; - szData.Data4[7] = b15; -} - -bool ImpSvGlobalName::operator == ( const ImpSvGlobalName & rObj ) const -{ - return !memcmp( &szData, &rObj.szData, sizeof( szData ) ); -} - // SvGlobalName ---------------------------------------------------------------- -SvGlobalName::SvGlobalName() -{ -} - SvGlobalName::SvGlobalName( const SvGUID & rId ) : - pImp( ImpSvGlobalName( rId ) ) + m_aData( rId ) { } SvGlobalName::SvGlobalName( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ) : - pImp( ImpSvGlobalName(n1, n2, n3, b8, b9, b10, b11, b12, b13, b14, b15) ) + m_aData{ n1, n2, n3, { b8, b9, b10, b11, b12, b13, b14, b15 } } { } SvGlobalName::SvGlobalName( const css::uno::Sequence < sal_Int8 >& aSeq ) { // create SvGlobalName from a platform independent representation - SvGUID aResult = {}; if ( aSeq.getLength() == 16 ) { - aResult.Data1 = ( ( ( ( ( static_cast<sal_uInt8>(aSeq[0]) << 8 ) + static_cast<sal_uInt8>(aSeq[1]) ) << 8 ) + static_cast<sal_uInt8>(aSeq[2]) ) << 8 ) + static_cast<sal_uInt8>(aSeq[3]); - aResult.Data2 = ( static_cast<sal_uInt8>(aSeq[4]) << 8 ) + static_cast<sal_uInt8>(aSeq[5]); - aResult.Data3 = ( static_cast<sal_uInt8>(aSeq[6]) << 8 ) + static_cast<sal_uInt8>(aSeq[7]); + m_aData.Data1 = ( ( ( ( ( static_cast<sal_uInt8>(aSeq[0]) << 8 ) + static_cast<sal_uInt8>(aSeq[1]) ) << 8 ) + static_cast<sal_uInt8>(aSeq[2]) ) << 8 ) + static_cast<sal_uInt8>(aSeq[3]); + m_aData.Data2 = ( static_cast<sal_uInt8>(aSeq[4]) << 8 ) + static_cast<sal_uInt8>(aSeq[5]); + m_aData.Data3 = ( static_cast<sal_uInt8>(aSeq[6]) << 8 ) + static_cast<sal_uInt8>(aSeq[7]); for( int nInd = 0; nInd < 8; nInd++ ) - aResult.Data4[nInd] = static_cast<sal_uInt8>(aSeq[nInd+8]); + m_aData.Data4[nInd] = static_cast<sal_uInt8>(aSeq[nInd+8]); } - - pImp = ::o3tl::cow_wrapper< ImpSvGlobalName >(aResult); -} - -SvGlobalName::~SvGlobalName() -{ -} - -SvGlobalName & SvGlobalName::operator = ( const SvGlobalName & rObj ) -{ - pImp = rObj.pImp; - - return *this; -} - -SvGlobalName & SvGlobalName::operator = ( SvGlobalName && rObj ) noexcept -{ - pImp = std::move(rObj.pImp); - return *this; } SvStream& WriteSvGlobalName( SvStream& rOStr, const SvGlobalName & rObj ) { - rOStr.WriteUInt32( rObj.pImp->szData.Data1 ); - rOStr.WriteUInt16( rObj.pImp->szData.Data2 ); - rOStr.WriteUInt16( rObj.pImp->szData.Data3 ); - rOStr.WriteBytes( &rObj.pImp->szData.Data4, 8 ); + rOStr.WriteUInt32( rObj.m_aData.Data1 ); + rOStr.WriteUInt16( rObj.m_aData.Data2 ); + rOStr.WriteUInt16( rObj.m_aData.Data3 ); + rOStr.WriteBytes( &rObj.m_aData.Data4, 8 ); return rOStr; } SvStream& operator >> ( SvStream& rStr, SvGlobalName & rObj ) { - // the non-const dereferencing operator - // ensures pImp is unique - rStr.ReadUInt32( rObj.pImp->szData.Data1 ); - rStr.ReadUInt16( rObj.pImp->szData.Data2 ); - rStr.ReadUInt16( rObj.pImp->szData.Data3 ); - rStr.ReadBytes( &rObj.pImp->szData.Data4, 8 ); + rStr.ReadUInt32( rObj.m_aData.Data1 ); + rStr.ReadUInt16( rObj.m_aData.Data2 ); + rStr.ReadUInt16( rObj.m_aData.Data3 ); + rStr.ReadBytes( &rObj.m_aData.Data4, 8 ); return rStr; } bool SvGlobalName::operator < ( const SvGlobalName & rObj ) const { - if( pImp->szData.Data3 < rObj.pImp->szData.Data3 ) + if( m_aData.Data3 < rObj.m_aData.Data3 ) return true; - else if( pImp->szData.Data3 > rObj.pImp->szData.Data3 ) + else if( m_aData.Data3 > rObj.m_aData.Data3 ) return false; - if( pImp->szData.Data2 < rObj.pImp->szData.Data2 ) + if( m_aData.Data2 < rObj.m_aData.Data2 ) return true; - else if( pImp->szData.Data2 > rObj.pImp->szData.Data2 ) + else if( m_aData.Data2 > rObj.m_aData.Data2 ) return false; - return pImp->szData.Data1 < rObj.pImp->szData.Data1; + return m_aData.Data1 < rObj.m_aData.Data1; } bool SvGlobalName::operator == ( const SvGlobalName & rObj ) const { - return pImp == rObj.pImp; + return memcmp(&m_aData, &rObj.m_aData, sizeof(m_aData)) == 0; } void SvGlobalName::MakeFromMemory( void const * pData ) { - memcpy( &pImp->szData, pData, sizeof( pImp->szData ) ); + memcpy( &m_aData, pData, sizeof( m_aData ) ); } -bool SvGlobalName::MakeId( const OUString & rIdStr ) +bool SvGlobalName::MakeId( std::u16string_view rIdStr ) { - const sal_Unicode *pStr = rIdStr.getStr(); - if( rIdStr.getLength() == 36 - && '-' == pStr[ 8 ] && '-' == pStr[ 13 ] - && '-' == pStr[ 18 ] && '-' == pStr[ 23 ] ) + const sal_Unicode *pStr = rIdStr.data(); + if( rIdStr.size() != 36 + || '-' != pStr[ 8 ] || '-' != pStr[ 13 ] + || '-' != pStr[ 18 ] || '-' != pStr[ 23 ] ) + return false; + + SvGUID aGuid = {}; + auto asciiHexDigitToNumber = [](sal_Unicode c) -> sal_uInt8 { - sal_uInt32 nFirst = 0; - int i = 0; - for( i = 0; i < 8; i++ ) - { - if( rtl::isAsciiHexDigit( *pStr ) ) - if( rtl::isAsciiDigit( *pStr ) ) - nFirst = nFirst * 16 + (*pStr - '0'); - else - nFirst = nFirst * 16 + (rtl::toAsciiUpperCase( *pStr ) - 'A' + 10 ); - else - return false; - pStr++; - } + if (rtl::isAsciiDigit(c)) + return c - '0'; + else + return rtl::toAsciiUpperCase(c) - 'A' + 10; + }; - sal_uInt16 nSec = 0; - pStr++; - for( i = 0; i < 4; i++ ) - { - if( rtl::isAsciiHexDigit( *pStr ) ) - if( rtl::isAsciiDigit( *pStr ) ) - nSec = nSec * 16 + (*pStr - '0'); - else - nSec = nSec * 16 + static_cast<sal_uInt16>(rtl::toAsciiUpperCase( *pStr ) - 'A' + 10 ); - else - return false; - pStr++; - } + for( int i = 0; i < 8; i++ ) + { + if( !rtl::isAsciiHexDigit( *pStr ) ) + return false; + aGuid.Data1 = aGuid.Data1 * 16 + asciiHexDigitToNumber( *pStr++ ); + } - sal_uInt16 nThird = 0; - pStr++; - for( i = 0; i < 4; i++ ) - { - if( rtl::isAsciiHexDigit( *pStr ) ) - if( rtl::isAsciiDigit( *pStr ) ) - nThird = nThird * 16 + (*pStr - '0'); - else - nThird = nThird * 16 + static_cast<sal_uInt16>(rtl::toAsciiUpperCase( *pStr ) - 'A' + 10 ); - else - return false; - pStr++; - } + pStr++; + for( int i = 0; i < 4; i++ ) + { + if( !rtl::isAsciiHexDigit( *pStr ) ) + return false; + aGuid.Data2 = aGuid.Data2 * 16 + asciiHexDigitToNumber( *pStr++ ); + } - sal_Int8 szRemain[ 8 ] = {}; - pStr++; - for( i = 0; i < 16; i++ ) - { - if( rtl::isAsciiHexDigit( *pStr ) ) - if( rtl::isAsciiDigit( *pStr ) ) - szRemain[i/2] = szRemain[i/2] * 16 + (*pStr - '0'); - else - szRemain[i/2] = szRemain[i/2] * 16 + static_cast<sal_Int8>(rtl::toAsciiUpperCase( *pStr ) - 'A' + 10 ); - else - return false; - pStr++; - if( i == 3 ) - pStr++; - } + pStr++; + for( int i = 0; i < 4; i++ ) + { + if( !rtl::isAsciiHexDigit( *pStr ) ) + return false; + aGuid.Data3 = aGuid.Data3 * 16 + asciiHexDigitToNumber( *pStr++ ); + } - memcpy(&pImp->szData.Data1, &nFirst, sizeof(nFirst)); - memcpy(&pImp->szData.Data2, &nSec, sizeof(nSec)); - memcpy(&pImp->szData.Data3, &nThird, sizeof(nThird)); - memcpy(&pImp->szData.Data4, szRemain, 8); - return true; + pStr++; + for( int i = 0; i < 16; i++ ) + { + if( !rtl::isAsciiHexDigit( *pStr ) ) + return false; + aGuid.Data4[i/2] = aGuid.Data4[i/2] * 16 + asciiHexDigitToNumber( *pStr++ ); + if( i == 3 ) + pStr++; } - return false; + + m_aData = aGuid; + return true; } OUString SvGlobalName::GetHexName() const { - OStringBuffer aHexBuffer(36); - - char buf[ 10 ]; - sprintf( buf, "%8.8" SAL_PRIXUINT32, pImp->szData.Data1 ); - aHexBuffer.append(buf); - aHexBuffer.append('-'); - sprintf( buf, "%4.4X", pImp->szData.Data2 ); - aHexBuffer.append(buf); - aHexBuffer.append('-'); - sprintf( buf, "%4.4X", pImp->szData.Data3 ); - aHexBuffer.append(buf); - aHexBuffer.append('-'); - for( int i = 0; i < 2; i++ ) - { - sprintf( buf, "%2.2x", pImp->szData.Data4[ i ] ); - aHexBuffer.append(buf); - } - aHexBuffer.append('-'); - for( int i = 2; i < 8; i++ ) - { - sprintf( buf, "%2.2x", pImp->szData.Data4[ i ] ); - aHexBuffer.append(buf); - } - return OStringToOUString(aHexBuffer.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); + char buf[ 37 ]; + int n = sprintf(buf, + "%8.8" SAL_PRIXUINT32 "-%4.4X-%4.4X-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", + m_aData.Data1, m_aData.Data2, m_aData.Data3, + m_aData.Data4[0], m_aData.Data4[1], m_aData.Data4[2], m_aData.Data4[3], + m_aData.Data4[4], m_aData.Data4[5], m_aData.Data4[6], m_aData.Data4[7]); + assert(n == 36); + return OUString::createFromAscii(std::string_view(buf, n)); } css::uno::Sequence < sal_Int8 > SvGlobalName::GetByteSequence() const { // platform independent representation of a "GlobalName" // maybe transported remotely - css::uno::Sequence< sal_Int8 > aResult{ - /* [ 0] */ static_cast<sal_Int8>(pImp->szData.Data1 >> 24), - /* [ 1] */ static_cast<sal_Int8>((pImp->szData.Data1 << 8 ) >> 24), - /* [ 2] */ static_cast<sal_Int8>((pImp->szData.Data1 << 16 ) >> 24), - /* [ 3] */ static_cast<sal_Int8>((pImp->szData.Data1 << 24 ) >> 24), - /* [ 4] */ static_cast<sal_Int8>(pImp->szData.Data2 >> 8), - /* [ 5] */ static_cast<sal_Int8>((pImp->szData.Data2 << 8 ) >> 8), - /* [ 6] */ static_cast<sal_Int8>(pImp->szData.Data3 >> 8), - /* [ 7] */ static_cast<sal_Int8>((pImp->szData.Data3 << 8 ) >> 8), - /* [ 8] */ static_cast<sal_Int8>(pImp->szData.Data4[ 0 ]), - /* [ 9] */ static_cast<sal_Int8>(pImp->szData.Data4[ 1 ]), - /* [10] */ static_cast<sal_Int8>(pImp->szData.Data4[ 2 ]), - /* [11] */ static_cast<sal_Int8>(pImp->szData.Data4[ 3 ]), - /* [12] */ static_cast<sal_Int8>(pImp->szData.Data4[ 4 ]), - /* [13] */ static_cast<sal_Int8>(pImp->szData.Data4[ 5 ]), - /* [14] */ static_cast<sal_Int8>(pImp->szData.Data4[ 6 ]), - /* [15] */ static_cast<sal_Int8>(pImp->szData.Data4[ 7 ]) - }; - - return aResult; + return comphelper::MimeConfigurationHelper::GetSequenceClassID( + m_aData.Data1, m_aData.Data2, m_aData.Data3, + m_aData.Data4[0], m_aData.Data4[1], m_aData.Data4[2], m_aData.Data4[3], + m_aData.Data4[4], m_aData.Data4[5], m_aData.Data4[6], m_aData.Data4[7]); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/source/stream/GenericTypeSerializer.cxx b/tools/source/stream/GenericTypeSerializer.cxx index 7bba06d97aba..8abe23237d85 100644 --- a/tools/source/stream/GenericTypeSerializer.cxx +++ b/tools/source/stream/GenericTypeSerializer.cxx @@ -36,9 +36,9 @@ void GenericTypeSerializer::readColor(Color& rColor) if (nColorNameID & COL_NAME_USER) { - sal_uInt16 nRed; - sal_uInt16 nGreen; - sal_uInt16 nBlue; + sal_uInt16 nRed(0); + sal_uInt16 nGreen(0); + sal_uInt16 nBlue(0); mrStream.ReadUInt16(nRed); mrStream.ReadUInt16(nGreen); diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx index d42cefdf63cf..9ab7291e3bfc 100644 --- a/tools/source/stream/stream.cxx +++ b/tools/source/stream/stream.cxx @@ -378,7 +378,7 @@ void SvStream::SetBufferSize( sal_uInt16 nBufferSize ) bool bDontSeek = (m_pRWBuf == nullptr); if (m_isDirty && m_isWritable) // due to Windows NT: Access denied - Flush(); + FlushBuffer(); if (m_nBufSize) { @@ -426,13 +426,21 @@ bool SvStream::ReadByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet, bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead ) { + OStringBuffer aBuf(4096); + bool rv = ReadLine(aBuf, nMaxBytesToRead); + rStr = aBuf.makeStringAndClear(); + return rv; +} + +bool SvStream::ReadLine( OStringBuffer& aBuf, sal_Int32 nMaxBytesToRead ) +{ char buf[256+1]; bool bEnd = false; sal_uInt64 nOldFilePos = Tell(); char c = 0; std::size_t nTotalLen = 0; - OStringBuffer aBuf(4096); + aBuf.setLength(0); while( !bEnd && !GetError() ) // Don't test for EOF as we // are reading block-wise! { @@ -443,7 +451,7 @@ bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead ) { // Exit on first block-read error m_isEof = true; - rStr.clear(); + aBuf.setLength(0); return false; } else @@ -494,7 +502,6 @@ bool SvStream::ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead ) if ( bEnd ) m_isEof = false; - rStr = aBuf.makeStringAndClear(); return bEnd; } @@ -718,52 +725,54 @@ void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet ) eReadBomCharSet == RTL_TEXTENCODING_UTF8)) return; // nothing to read - bool bTryUtf8 = false; - sal_uInt16 nFlag(0); - sal_sSize nBack = sizeof(nFlag); - ReadUInt16( nFlag ); + const sal_uInt64 nOldPos = Tell(); + bool bGetBack = true; + unsigned char nFlag(0); + ReadUChar( nFlag ); switch ( nFlag ) { - case 0xfeff : - // native UTF-16 + case 0xfe: // UTF-16BE? if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UNICODE) - nBack = 0; + { + ReadUChar(nFlag); + if (nFlag == 0xff) + { + SetEndian(SvStreamEndian::BIG); + bGetBack = false; + } + } break; - case 0xfffe : - // swapped UTF-16 + case 0xff: // UTF-16LE? if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || eReadBomCharSet == RTL_TEXTENCODING_UNICODE) { - SetEndian( m_nEndian == SvStreamEndian::BIG ? SvStreamEndian::LITTLE : SvStreamEndian::BIG ); - nBack = 0; + ReadUChar(nFlag); + if (nFlag == 0xfe) + { + SetEndian(SvStreamEndian::LITTLE); + bGetBack = false; + } } break; - case 0xefbb : - if (m_nEndian == SvStreamEndian::BIG && - (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || - eReadBomCharSet == RTL_TEXTENCODING_UTF8)) - bTryUtf8 = true; - break; - case 0xbbef : - if (m_nEndian == SvStreamEndian::LITTLE && - (eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || - eReadBomCharSet == RTL_TEXTENCODING_UTF8)) - bTryUtf8 = true; + case 0xef: // UTF-8? + if ( eReadBomCharSet == RTL_TEXTENCODING_DONTKNOW || + eReadBomCharSet == RTL_TEXTENCODING_UTF8) + { + ReadUChar(nFlag); + if (nFlag == 0xbb) + { + ReadUChar(nFlag); + if (nFlag == 0xbf) + bGetBack = false; // it is UTF-8 + } + } break; default: ; // nothing } - if (bTryUtf8) - { - unsigned char nChar(0); - nBack += sizeof(nChar); - ReadUChar( nChar ); - if (nChar == 0xbf) - nBack = 0; // it is UTF-8 - } - if (nBack) - SeekRel( -nBack ); // no BOM, pure data + if (bGetBack) + Seek(nOldPos); // no BOM, pure data } sal_uInt64 SvStream::SeekRel(sal_Int64 const nPos) @@ -1544,7 +1553,7 @@ SvMemoryStream::~SvMemoryStream() if( bOwnsData ) FreeMemory(); else - Flush(); + FlushBuffer(); } } @@ -1752,7 +1761,7 @@ void SvMemoryStream::FreeMemory() void* SvMemoryStream::SwitchBuffer() { - Flush(); + FlushBuffer(); if( !bOwnsData ) return nullptr; Seek( STREAM_SEEK_TO_BEGIN ); @@ -1785,7 +1794,8 @@ void SvMemoryStream::SetSize(sal_uInt64 const nNewSize) ReAllocateMemory( nDiff ); } -//Create an OString of nLen bytes from rStream +// Create an OString of nLen bytes from rStream +// coverity[ +taint_sanitize ] OString read_uInt8s_ToOString(SvStream& rStrm, std::size_t nLen) { rtl_String *pStr = nullptr; @@ -1816,7 +1826,8 @@ OString read_uInt8s_ToOString(SvStream& rStrm, std::size_t nLen) return pStr ? OString(pStr, SAL_NO_ACQUIRE) : OString(); } -//Create an OUString of nLen sal_Unicode code units from rStream +// Create an OUString of nLen sal_Unicode code units from rStream +// coverity[ +taint_sanitize ] OUString read_uInt16s_ToOUString(SvStream& rStrm, std::size_t nLen) { rtl_uString *pStr = nullptr; @@ -1848,7 +1859,7 @@ OUString read_uInt16s_ToOUString(SvStream& rStrm, std::size_t nLen) } } - //take ownership of buffer and return, otherwise return empty string + // take ownership of buffer and return, otherwise return empty string return pStr ? OUString(pStr, SAL_NO_ACQUIRE) : OUString(); } diff --git a/tools/source/stream/strmunx.cxx b/tools/source/stream/strmunx.cxx index 853389266ac3..5964529f34a1 100644 --- a/tools/source/stream/strmunx.cxx +++ b/tools/source/stream/strmunx.cxx @@ -24,7 +24,7 @@ #include <tools/stream.hxx> #include <map> -#include <osl/mutex.hxx> +#include <mutex> #include <osl/thread.h> #include <sal/log.hxx> @@ -37,9 +37,9 @@ using namespace osl; namespace { -osl::Mutex& LockMutex() +std::mutex& LockMutex() { - static osl::Mutex SINGLETON; + static std::mutex SINGLETON; return SINGLETON; } @@ -63,7 +63,7 @@ bool lockFile( const SvFileStream* pStream ) if( aStatus.getFileType() == osl::FileStatus::Directory ) return true; - osl::MutexGuard aGuard( LockMutex() ); + std::unique_lock aGuard( LockMutex() ); for( const auto& [rLockStream, rLockItem] : gLocks ) { if( aItem.isIdenticalTo( rLockItem ) ) @@ -86,7 +86,7 @@ bool lockFile( const SvFileStream* pStream ) void unlockFile( SvFileStream const * pStream ) { - osl::MutexGuard aGuard( LockMutex() ); + std::unique_lock aGuard( LockMutex() ); gLocks.erase(pStream); } @@ -198,7 +198,6 @@ SvFileStream::SvFileStream( const OUString& rFileName, StreamMode nOpenMode ) { bIsOpen = false; m_isWritable = false; - mbDontFlushOnClose = false; pInstanceData.reset(new StreamData); SetBufferSize( 1024 ); @@ -216,7 +215,6 @@ SvFileStream::SvFileStream() { bIsOpen = false; m_isWritable = false; - mbDontFlushOnClose = false; pInstanceData.reset(new StreamData); SetBufferSize( 1024 ); } @@ -374,14 +372,20 @@ void SvFileStream::Open( const OUString& rFilename, StreamMode nOpenMode ) // FIXME: we really need to switch to a pure URL model ... if ( osl::File::getFileURLFromSystemPath( aFilename, aFileURL ) != osl::FileBase::E_None ) aFileURL = aFilename; - bool bStatValid = ( osl::DirectoryItem::get( aFileURL, aItem) == osl::FileBase::E_None && - aItem.getFileStatus( aStatus ) == osl::FileBase::E_None ); - // SvFileStream can't open a directory - if( bStatValid && aStatus.getFileType() == osl::FileStatus::Directory ) + // don't both stat()ing a temporary file, unnecessary + bool bStatValid = true; + if (!(nOpenMode & StreamMode::TEMPORARY)) { - SetError( ::GetSvError( EISDIR ) ); - return; + bStatValid = ( osl::DirectoryItem::get( aFileURL, aItem) == osl::FileBase::E_None && + aItem.getFileStatus( aStatus ) == osl::FileBase::E_None ); + + // SvFileStream can't open a directory + if( bStatValid && aStatus.getFileType() == osl::FileStatus::Directory ) + { + SetError( ::GetSvError( EISDIR ) ); + return; + } } if ( !( nOpenMode & StreamMode::WRITE ) ) @@ -460,8 +464,7 @@ void SvFileStream::Close() if ( IsOpen() ) { SAL_INFO("tools", "Closing " << aFilename); - if ( !mbDontFlushOnClose ) - Flush(); + FlushBuffer(); osl_closeFile( pInstanceData->rHandle ); pInstanceData->rHandle = nullptr; } diff --git a/tools/source/stream/strmwnt.cxx b/tools/source/stream/strmwnt.cxx index c91628b55091..4ea9c7eb1d42 100644 --- a/tools/source/stream/strmwnt.cxx +++ b/tools/source/stream/strmwnt.cxx @@ -107,7 +107,6 @@ SvFileStream::SvFileStream( const OUString& rFileName, StreamMode nMode ) bIsOpen = false; nLockCounter = 0; m_isWritable = false; - mbDontFlushOnClose = false; pInstanceData.reset( new StreamData ); SetBufferSize( 8192 ); @@ -124,7 +123,6 @@ SvFileStream::SvFileStream() bIsOpen = false; nLockCounter = 0; m_isWritable = false; - mbDontFlushOnClose = false; pInstanceData.reset( new StreamData ); SetBufferSize( 8192 ); @@ -379,8 +377,7 @@ void SvFileStream::Close() nLockCounter = 1; UnlockFile(); } - if ( !mbDontFlushOnClose ) - Flush(); + FlushBuffer(); CloseHandle( pInstanceData->hFile ); } bIsOpen = false; diff --git a/tools/source/zcodec/zcodec.cxx b/tools/source/zcodec/zcodec.cxx index 97a03a463021..80daa1507a19 100644 --- a/tools/source/zcodec/zcodec.cxx +++ b/tools/source/zcodec/zcodec.cxx @@ -36,7 +36,7 @@ #define GZ_COMMENT 0x10 /* bit 4 set: file comment present */ #define GZ_RESERVED 0xE0 /* bits 5..7: reserved */ -const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */ +constexpr sal_uInt16 GZ_MAGIC_BYTES_LE = 0x8B1F; /* gzip magic bytes, little endian */ ZCodec::ZCodec( size_t nInBufSize, size_t nOutBufSize ) : meState(STATE_INIT) @@ -58,6 +58,16 @@ ZCodec::~ZCodec() delete pStream; } +bool ZCodec::IsZCompressed( SvStream& rIStm ) +{ + sal_uInt64 nCurPos = rIStm.Tell(); + rIStm.Seek( 0 ); + sal_uInt16 nFirstTwoBytes = 0; + rIStm.ReadUInt16( nFirstTwoBytes ); + rIStm.Seek( nCurPos ); + return nFirstTwoBytes == GZ_MAGIC_BYTES_LE; +} + void ZCodec::BeginCompression( int nCompressLevel, bool gzLib ) { assert(meState == STATE_INIT); @@ -272,12 +282,11 @@ void ZCodec::InitDecompress(SvStream & inStream) if ( mbStatus && mbGzLib ) { sal_uInt8 j, nMethod, nFlags; - for (int i : gz_magic) // gz - magic number - { - inStream.ReadUChar( j ); - if ( j != i ) - mbStatus = false; - } + sal_uInt16 nFirstTwoBytes; + inStream.Seek( 0 ); + inStream.ReadUInt16( nFirstTwoBytes ); + if ( nFirstTwoBytes != GZ_MAGIC_BYTES_LE ) + mbStatus = false; inStream.ReadUChar( nMethod ); inStream.ReadUChar( nFlags ); if ( nMethod != Z_DEFLATED ) |