diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2022-03-27 22:52:48 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2022-04-05 01:57:21 +0200 |
commit | cf4d5ed026c8799a70432a832a8a707c2e316216 (patch) | |
tree | 0b30a1863b4331208eca9454579714ff8e725d23 | |
parent | be7d84a3fbd47bf9a078ac7e6854bc4927e84933 (diff) |
add tools::Guid class to generate, parse GUID values
Change-Id: Ie4d8fad4d8f22c8277c22c21b7a9eb3e7c9e4f1b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132513
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | comphelper/source/xml/xmltools.cxx | 13 | ||||
-rw-r--r-- | include/tools/Guid.hxx | 166 | ||||
-rw-r--r-- | sc/source/filter/xcl97/XclExpChangeTrack.cxx | 20 | ||||
-rw-r--r-- | tools/CppunitTest_tools_test.mk | 1 | ||||
-rw-r--r-- | tools/qa/cppunit/test_guid.cxx | 123 |
5 files changed, 300 insertions, 23 deletions
diff --git a/comphelper/source/xml/xmltools.cxx b/comphelper/source/xml/xmltools.cxx index 366321076bad..1b10964b1a35 100644 --- a/comphelper/source/xml/xmltools.cxx +++ b/comphelper/source/xml/xmltools.cxx @@ -9,7 +9,7 @@ #include <comphelper/xmltools.hxx> #include <rtl/random.h> -#include <rtl/uuid.h> +#include <tools/Guid.hxx> #include <vector> using namespace com::sun::star; @@ -92,15 +92,8 @@ namespace comphelper::xml OString generateGUIDString() { - sal_uInt8 aSeq[16]; - rtl_createUuid(aSeq, nullptr, true); - - char str[39]; - sprintf(str, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - aSeq[0], aSeq[1], aSeq[2], aSeq[3], aSeq[4], aSeq[5], aSeq[6], aSeq[7], aSeq[8], - aSeq[9], aSeq[10], aSeq[11], aSeq[12], aSeq[13], aSeq[14], aSeq[15]); - - return OString(str); + tools::Guid aGuid(tools::Guid::Generate); + return aGuid.getString(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/Guid.hxx b/include/tools/Guid.hxx new file mode 100644 index 000000000000..980048d9415d --- /dev/null +++ b/include/tools/Guid.hxx @@ -0,0 +1,166 @@ +/* -*- 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/. + */ + +#pragma once + +#include <array> +#include <rtl/uuid.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustring.hxx> +#include <algorithm> +#include <stdio.h> +#include <cctype> + +namespace tools +{ +class Guid +{ +private: + typedef std::array<sal_uInt8, 16> GuidArrayType; + + GuidArrayType maGuidArray; + + static sal_uInt8 gethex(char nChar) + { + if (nChar >= '0' && nChar <= '9') + return nChar - '0'; + else if (nChar >= 'a' && nChar <= 'f') + return nChar - 'a' + 10; + else if (nChar >= 'A' && nChar <= 'F') + return nChar - 'A' + 10; + else + return 0; + } + + static sal_uInt8 covertHexChar(char high, char low) + { + return (gethex(high) << 4) + gethex(low); + } + + void parse(OString const& rString) + { + if (rString.getLength() != 38) + return; + + if (rString[0] != '{' || rString[37] != '}' || rString[9] != '-' || rString[14] != '-' + || rString[19] != '-' || rString[24] != '-') + return; + + for (size_t x = 1; x <= 8; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 10; x <= 13; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 15; x <= 18; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 20; x <= 23; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 25; x <= 36; x++) + if (!std::isxdigit(rString[x])) + return; + + maGuidArray[0] = covertHexChar(rString[1], rString[2]); + maGuidArray[1] = covertHexChar(rString[3], rString[4]); + maGuidArray[2] = covertHexChar(rString[5], rString[6]); + maGuidArray[3] = covertHexChar(rString[7], rString[8]); + + maGuidArray[4] = covertHexChar(rString[10], rString[11]); + maGuidArray[5] = covertHexChar(rString[12], rString[13]); + + maGuidArray[6] = covertHexChar(rString[15], rString[16]); + maGuidArray[7] = covertHexChar(rString[17], rString[18]); + + maGuidArray[8] = covertHexChar(rString[20], rString[21]); + maGuidArray[9] = covertHexChar(rString[22], rString[23]); + + maGuidArray[10] = covertHexChar(rString[25], rString[26]); + maGuidArray[11] = covertHexChar(rString[27], rString[28]); + maGuidArray[12] = covertHexChar(rString[29], rString[30]); + maGuidArray[13] = covertHexChar(rString[31], rString[32]); + maGuidArray[14] = covertHexChar(rString[33], rString[34]); + maGuidArray[15] = covertHexChar(rString[35], rString[36]); + } + +public: + /// GenerateTag is used as a flag for generating the GUID + enum GenerateTag + { + Generate = 0 + }; + + /// Constructor which generates the GUID + Guid(enum GenerateTag) { rtl_createUuid(maGuidArray.data(), nullptr, false); } + + /// Default constructor which initializes the values to 0 (empty GUID) + Guid() { maGuidArray.fill(0); } + + /// parse the GUID from the string + Guid(OString const& rString) + { + maGuidArray.fill(0); + parse(rString); + } + + /// set the GUID from an array + Guid(const sal_uInt8 aGuidArray[16]) + { + std::copy(aGuidArray, aGuidArray + 16, maGuidArray.begin()); + } + + Guid(Guid&&) = delete; + + Guid(Guid const& rOther) { *this = rOther; } + + void operator=(Guid const& rOther) { std::copy(rOther.cbegin(), rOther.cend(), begin()); } + + bool isEmpty() { return *std::max_element(maGuidArray.begin(), maGuidArray.end()) == 0; } + + GuidArrayType::iterator begin() { return maGuidArray.begin(); } + GuidArrayType::iterator end() { return maGuidArray.end(); } + GuidArrayType::const_iterator cbegin() const { return maGuidArray.cbegin(); } + GuidArrayType::const_iterator cend() const { return maGuidArray.cend(); } + + OString getString() const + { + char sBuffer[40]; + snprintf(sBuffer, sizeof(sBuffer), + "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + maGuidArray[0], maGuidArray[1], maGuidArray[2], maGuidArray[3], maGuidArray[4], + maGuidArray[5], maGuidArray[6], maGuidArray[7], maGuidArray[8], maGuidArray[9], + maGuidArray[10], maGuidArray[11], maGuidArray[12], maGuidArray[13], + maGuidArray[14], maGuidArray[15]); + + return OString(sBuffer); + } + + OUString getOUString() { return OStringToOUString(getString(), RTL_TEXTENCODING_ASCII_US); } + + bool operator==(Guid const& rCompare) const + { + return rtl_compareUuid(maGuidArray.data(), rCompare.maGuidArray.data()) == 0; + } + + bool operator!=(Guid const& rCompare) const { return !(*this == rCompare); } +}; + +template <typename charT, typename traits> +inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& rStream, + tools::Guid const& rGuid) +{ + OString aString = rGuid.getString(); + rStream << "GUID" << aString.getStr(); + return rStream; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx index 5ebe27d36103..2ef1b5bce3e2 100644 --- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx +++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx @@ -29,6 +29,7 @@ #include <document.hxx> #include <editutil.hxx> #include <root.hxx> +#include <tools/Guid.hxx> #include <oox/export/utils.hxx> #include <oox/token/namespaces.hxx> @@ -38,16 +39,6 @@ using namespace oox; -static OString lcl_GuidToOString( sal_uInt8 aGuid[ 16 ] ) -{ - char sBuf[ 40 ]; - snprintf( sBuf, sizeof( sBuf ), - "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - aGuid[ 0 ], aGuid[ 1 ], aGuid[ 2 ], aGuid[ 3 ], aGuid[ 4 ], aGuid[ 5 ], aGuid[ 6 ], aGuid[ 7 ], - aGuid[ 8 ], aGuid[ 9 ], aGuid[ 10 ], aGuid[ 11 ], aGuid[ 12 ], aGuid[ 13 ], aGuid[ 14 ], aGuid[ 15 ] ); - return OString(sBuf); -} - static OString lcl_DateTimeToOString( const DateTime& rDateTime ) { char sBuf[ 200 ]; @@ -351,8 +342,9 @@ std::size_t XclExpChTrHeader::GetLen() const void XclExpChTrHeader::SaveXml( XclExpXmlStream& rRevisionHeadersStrm ) { sax_fastparser::FSHelperPtr pHeaders = rRevisionHeadersStrm.GetCurrentStream(); + tools::Guid aGuid(aGUID); rRevisionHeadersStrm.WriteAttributes( - XML_guid, lcl_GuidToOString(aGUID), + XML_guid, aGuid.getString(), XML_lastGuid, nullptr, // OOXTODO XML_shared, nullptr, // OOXTODO XML_diskRevisions, nullptr, // OOXTODO @@ -378,10 +370,11 @@ void XclExpXmlChTrHeaders::SaveXml( XclExpXmlStream& rStrm ) pHeaders->write("<")->writeId(XML_headers); + tools::Guid aGuid(maGUID); rStrm.WriteAttributes( XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)), FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)), - XML_guid, lcl_GuidToOString(maGUID), + XML_guid, aGuid.getString(), XML_lastGuid, nullptr, // OOXTODO XML_shared, nullptr, // OOXTODO XML_diskRevisions, nullptr, // OOXTODO @@ -426,8 +419,9 @@ void XclExpXmlChTrHeader::SaveXml( XclExpXmlStream& rStrm ) CREATE_OFFICEDOC_RELATION_TYPE("revisionLog"), &aRelId); + tools::Guid aGuid(maGUID); rStrm.WriteAttributes( - XML_guid, lcl_GuidToOString(maGUID), + XML_guid, aGuid.getString(), XML_dateTime, lcl_DateTimeToOString(maDateTime), XML_userName, maUserName, FSNS(XML_r, XML_id), aRelId); diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk index be47c09ab191..c36af07547c2 100644 --- a/tools/CppunitTest_tools_test.mk +++ b/tools/CppunitTest_tools_test.mk @@ -33,6 +33,7 @@ $(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 \ diff --git a/tools/qa/cppunit/test_guid.cxx b/tools/qa/cppunit/test_guid.cxx new file mode 100644 index 000000000000..39c23080e1e7 --- /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 contructor + 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: */ |