Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/comphelper/source/misc/anytohash.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
21
#include <comphelper/anytohash.hxx>
22
23
#include <o3tl/hash_combine.hxx>
24
#include <typelib/typedescription.hxx>
25
#include <com/sun/star/uno/Any.hxx>
26
27
#include "typedescriptionref.hxx"
28
29
using namespace ::com::sun::star;
30
using ::com::sun::star::uno::TypeDescription;
31
using ::comphelper::detail::TypeDescriptionRef;
32
33
namespace comphelper {
34
namespace {
35
36
std::optional<size_t> hashValue( size_t hash,
37
                  void const * val, typelib_TypeDescriptionReference * typeRef )
38
75.7M
{
39
75.7M
    o3tl::hash_combine( hash, typeRef->eTypeClass );
40
75.7M
    if (typeRef->eTypeClass == typelib_TypeClass_VOID) {
41
104
        return hash;
42
104
    }
43
75.7M
    assert(val != nullptr);
44
45
75.7M
    switch (typeRef->eTypeClass) {
46
0
    case typelib_TypeClass_INTERFACE: {
47
0
        return std::nullopt; // not implemented
48
0
    }
49
22.8M
    case typelib_TypeClass_STRUCT:
50
22.8M
    case typelib_TypeClass_EXCEPTION: {
51
22.8M
        TypeDescription typeDescr( typeRef );
52
22.8M
        if (!typeDescr.is())
53
0
            typeDescr.makeComplete();
54
22.8M
        if (!typeDescr.is())
55
0
            return std::nullopt;
56
57
22.8M
        typelib_CompoundTypeDescription * compType =
58
22.8M
            reinterpret_cast< typelib_CompoundTypeDescription * >(
59
22.8M
                typeDescr.get() );
60
22.8M
        sal_Int32 nDescr = compType->nMembers;
61
62
22.8M
        if (compType->pBaseTypeDescription) {
63
0
            std::optional<size_t> tmpHash = hashValue(
64
0
                hash, val, reinterpret_cast<
65
0
                typelib_TypeDescription * >(
66
0
                    compType->pBaseTypeDescription)->pWeakRef);
67
0
            if(!tmpHash.has_value())
68
0
                return std::nullopt;
69
0
            hash = *tmpHash;
70
0
        }
71
72
22.8M
        typelib_TypeDescriptionReference ** ppTypeRefs =
73
22.8M
            compType->ppTypeRefs;
74
22.8M
        sal_Int32 * memberOffsets = compType->pMemberOffsets;
75
76
73.0M
        for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
77
50.1M
        {
78
50.1M
            TypeDescriptionRef memberType( ppTypeRefs[ nPos ] );
79
50.1M
            if (!memberType.is())
80
0
                return std::nullopt;
81
82
50.1M
            std::optional<size_t> tmpHash = hashValue( hash,
83
50.1M
                             static_cast< char const * >(
84
50.1M
                                 val ) + memberOffsets[ nPos ],
85
50.1M
                             memberType->pWeakRef );
86
50.1M
            if(!tmpHash.has_value())
87
0
                return std::nullopt;
88
50.1M
            hash = *tmpHash;
89
50.1M
        }
90
22.8M
        break;
91
22.8M
    }
92
22.8M
    case typelib_TypeClass_SEQUENCE: {
93
1.27M
        TypeDescriptionRef typeDescr( typeRef );
94
1.27M
        if (!typeDescr.is())
95
0
            return std::nullopt;
96
97
1.27M
        typelib_TypeDescriptionReference * elementTypeRef =
98
1.27M
            reinterpret_cast<
99
1.27M
            typelib_IndirectTypeDescription * >(typeDescr.get())->pType;
100
1.27M
        TypeDescriptionRef elementTypeDescr( elementTypeRef );
101
1.27M
        if (!elementTypeDescr.is())
102
0
            return std::nullopt;
103
104
1.27M
        sal_Int32 nElementSize = elementTypeDescr->nSize;
105
1.27M
        uno_Sequence * seq =
106
1.27M
            *static_cast< uno_Sequence * const * >(val);
107
1.27M
        sal_Int32 nElements = seq->nElements;
108
109
1.27M
        if (nElements > 0)
110
1.13M
        {
111
1.13M
            char const * pElements = seq->elements;
112
19.6M
            for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
113
18.4M
            {
114
18.4M
                std::optional<size_t> tmpHash = hashValue( hash,
115
18.4M
                    pElements + (nElementSize * nPos),
116
18.4M
                    elementTypeDescr->pWeakRef );
117
18.4M
                if(!tmpHash.has_value())
118
0
                    return std::nullopt;
119
18.4M
                hash = *tmpHash;
120
18.4M
            }
121
1.13M
        }
122
1.27M
        break;
123
1.27M
    }
124
6.72M
    case typelib_TypeClass_ANY: {
125
6.72M
        uno_Any const * pAny = static_cast< uno_Any const * >(val);
126
6.72M
        return hashValue( hash, pAny->pData, pAny->pType );
127
1.27M
    }
128
0
    case typelib_TypeClass_TYPE: {
129
0
        OUString const & str = OUString::unacquired(
130
0
            &(*static_cast<
131
0
                     typelib_TypeDescriptionReference * const * >(val)
132
0
                        )->pTypeName );
133
0
        o3tl::hash_combine( hash, str.hashCode() );
134
0
        break;
135
1.27M
    }
136
3.01M
    case typelib_TypeClass_STRING: {
137
3.01M
        OUString const & str = OUString::unacquired(
138
3.01M
            static_cast< rtl_uString * const * >(val) );
139
3.01M
        o3tl::hash_combine( hash, str.hashCode() );
140
3.01M
        break;
141
1.27M
    }
142
2.19M
    case typelib_TypeClass_ENUM: {
143
2.19M
        TypeDescription typeDescr( typeRef );
144
2.19M
        if (!typeDescr.is())
145
0
            typeDescr.makeComplete();
146
2.19M
        if (!typeDescr.is())
147
0
            return std::nullopt;
148
149
2.19M
        o3tl::hash_combine( hash, *static_cast< int const * >(val));
150
2.19M
        break;
151
2.19M
    }
152
212k
    case typelib_TypeClass_BOOLEAN:
153
212k
        if (*static_cast< sal_Bool const * >(val))
154
92.5k
            o3tl::hash_combine( hash, true );
155
119k
        else
156
119k
            o3tl::hash_combine( hash, false );
157
212k
        break;
158
0
    case typelib_TypeClass_CHAR: {
159
0
        o3tl::hash_combine( hash, *static_cast< sal_Unicode const * >(val));
160
0
        break;
161
2.19M
    }
162
0
    case typelib_TypeClass_FLOAT:
163
0
        o3tl::hash_combine( hash, *static_cast< float const * >(val) );
164
0
        break;
165
131k
    case typelib_TypeClass_DOUBLE:
166
131k
        o3tl::hash_combine( hash, *static_cast< double const * >(val) );
167
131k
        break;
168
0
    case typelib_TypeClass_BYTE:
169
0
        o3tl::hash_combine( hash, *static_cast< sal_Int8 const * >(val) );
170
0
        break;
171
31.9M
    case typelib_TypeClass_SHORT:
172
31.9M
        o3tl::hash_combine( hash, *static_cast< sal_Int16 const * >(val) );
173
31.9M
        break;
174
0
    case typelib_TypeClass_UNSIGNED_SHORT:
175
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt16 const * >(val) );
176
0
        break;
177
7.45M
    case typelib_TypeClass_LONG:
178
7.45M
        o3tl::hash_combine( hash, *static_cast< sal_Int32 const * >(val) );
179
7.45M
        break;
180
0
    case typelib_TypeClass_UNSIGNED_LONG:
181
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt32 const * >(val) );
182
0
        break;
183
0
    case typelib_TypeClass_HYPER:
184
0
        o3tl::hash_combine( hash, *static_cast< sal_Int64 const * >(val) );
185
0
        break;
186
0
    case typelib_TypeClass_UNSIGNED_HYPER:
187
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt64 const * >(val) );
188
0
        break;
189
//     case typelib_TypeClass_UNKNOWN:
190
//     case typelib_TypeClass_SERVICE:
191
//     case typelib_TypeClass_MODULE:
192
0
    default:
193
0
        return std::nullopt;
194
75.7M
    }
195
69.0M
    return hash;
196
75.7M
}
197
198
} // anon namespace
199
200
201
std::optional<size_t> anyToHash( uno::Any const & value )
202
415k
{
203
415k
    size_t hash = 0;
204
415k
    return hashValue( hash, value.getValue(), value.getValueTypeRef());
205
415k
}
206
207
} // namespace comphelper
208
209
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */