comphelper/source/xml/xmltools.cxx           |   13 --
 include/tools/Guid.hxx                       |  166 +++++++++++++++++++++++++++
 sc/source/filter/xcl97/XclExpChangeTrack.cxx |   20 +--
 tools/CppunitTest_tools_test.mk              |    1 
 tools/qa/cppunit/test_guid.cxx               |  123 ++++++++++++++++++++
 5 files changed, 300 insertions(+), 23 deletions(-)

New commits:
commit cf4d5ed026c8799a70432a832a8a707c2e316216
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sun Mar 27 22:52:48 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Tue Apr 5 01:57:21 2022 +0200

    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 <qui...@gmail.com>

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: */

Reply via email to