Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/comphelper/source/misc/anytohash.cxx
Line
Count
Source (jump to first uncovered line)
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
26
#include <com/sun/star/uno/Sequence.hxx>
27
28
#include "typedescriptionref.hxx"
29
30
using namespace ::com::sun::star;
31
using ::com::sun::star::uno::TypeDescription;
32
using ::comphelper::detail::TypeDescriptionRef;
33
34
namespace comphelper {
35
namespace {
36
37
std::optional<size_t> hashValue( size_t hash,
38
                  void const * val, typelib_TypeDescriptionReference * typeRef )
39
124M
{
40
124M
    o3tl::hash_combine( hash, typeRef->eTypeClass );
41
124M
    if (typeRef->eTypeClass == typelib_TypeClass_VOID) {
42
96
        return hash;
43
96
    }
44
124M
    assert(val != nullptr);
45
46
124M
    switch (typeRef->eTypeClass) {
47
0
    case typelib_TypeClass_INTERFACE: {
48
0
        return std::nullopt; // not implemented
49
0
    }
50
37.0M
    case typelib_TypeClass_STRUCT:
51
37.0M
    case typelib_TypeClass_EXCEPTION: {
52
37.0M
        TypeDescription typeDescr( typeRef );
53
37.0M
        if (!typeDescr.is())
54
0
            typeDescr.makeComplete();
55
37.0M
        if (!typeDescr.is())
56
0
            return std::nullopt;
57
58
37.0M
        typelib_CompoundTypeDescription * compType =
59
37.0M
            reinterpret_cast< typelib_CompoundTypeDescription * >(
60
37.0M
                typeDescr.get() );
61
37.0M
        sal_Int32 nDescr = compType->nMembers;
62
63
37.0M
        if (compType->pBaseTypeDescription) {
64
0
            std::optional<size_t> tmpHash = hashValue(
65
0
                hash, val, reinterpret_cast<
66
0
                typelib_TypeDescription * >(
67
0
                    compType->pBaseTypeDescription)->pWeakRef);
68
0
            if(!tmpHash.has_value())
69
0
                return std::nullopt;
70
0
            hash = *tmpHash;
71
0
        }
72
73
37.0M
        typelib_TypeDescriptionReference ** ppTypeRefs =
74
37.0M
            compType->ppTypeRefs;
75
37.0M
        sal_Int32 * memberOffsets = compType->pMemberOffsets;
76
77
119M
        for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
78
82.1M
        {
79
82.1M
            TypeDescriptionRef memberType( ppTypeRefs[ nPos ] );
80
82.1M
            if (!memberType.is())
81
0
                return std::nullopt;
82
83
82.1M
            std::optional<size_t> tmpHash = hashValue( hash,
84
82.1M
                             static_cast< char const * >(
85
82.1M
                                 val ) + memberOffsets[ nPos ],
86
82.1M
                             memberType->pWeakRef );
87
82.1M
            if(!tmpHash.has_value())
88
0
                return std::nullopt;
89
82.1M
            hash = *tmpHash;
90
82.1M
        }
91
37.0M
        break;
92
37.0M
    }
93
37.0M
    case typelib_TypeClass_SEQUENCE: {
94
2.36M
        TypeDescriptionRef typeDescr( typeRef );
95
2.36M
        if (!typeDescr.is())
96
0
            return std::nullopt;
97
98
2.36M
        typelib_TypeDescriptionReference * elementTypeRef =
99
2.36M
            reinterpret_cast<
100
2.36M
            typelib_IndirectTypeDescription * >(typeDescr.get())->pType;
101
2.36M
        TypeDescriptionRef elementTypeDescr( elementTypeRef );
102
2.36M
        if (!elementTypeDescr.is())
103
0
            return std::nullopt;
104
105
2.36M
        sal_Int32 nElementSize = elementTypeDescr->nSize;
106
2.36M
        uno_Sequence * seq =
107
2.36M
            *static_cast< uno_Sequence * const * >(val);
108
2.36M
        sal_Int32 nElements = seq->nElements;
109
110
2.36M
        if (nElements > 0)
111
2.15M
        {
112
2.15M
            char const * pElements = seq->elements;
113
31.7M
            for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
114
29.5M
            {
115
29.5M
                std::optional<size_t> tmpHash = hashValue( hash,
116
29.5M
                    pElements + (nElementSize * nPos),
117
29.5M
                    elementTypeDescr->pWeakRef );
118
29.5M
                if(!tmpHash.has_value())
119
0
                    return std::nullopt;
120
29.5M
                hash = *tmpHash;
121
29.5M
            }
122
2.15M
        }
123
2.36M
        break;
124
2.36M
    }
125
11.7M
    case typelib_TypeClass_ANY: {
126
11.7M
        uno_Any const * pAny = static_cast< uno_Any const * >(val);
127
11.7M
        return hashValue( hash, pAny->pData, pAny->pType );
128
2.36M
    }
129
0
    case typelib_TypeClass_TYPE: {
130
0
        OUString const & str = OUString::unacquired(
131
0
            &(*static_cast<
132
0
                     typelib_TypeDescriptionReference * const * >(val)
133
0
                        )->pTypeName );
134
0
        o3tl::hash_combine( hash, str.hashCode() );
135
0
        break;
136
2.36M
    }
137
5.48M
    case typelib_TypeClass_STRING: {
138
5.48M
        OUString const & str = OUString::unacquired(
139
5.48M
            static_cast< rtl_uString * const * >(val) );
140
5.48M
        o3tl::hash_combine( hash, str.hashCode() );
141
5.48M
        break;
142
2.36M
    }
143
3.93M
    case typelib_TypeClass_ENUM: {
144
3.93M
        TypeDescription typeDescr( typeRef );
145
3.93M
        if (!typeDescr.is())
146
0
            typeDescr.makeComplete();
147
3.93M
        if (!typeDescr.is())
148
0
            return std::nullopt;
149
150
3.93M
        o3tl::hash_combine( hash, *static_cast< int const * >(val));
151
3.93M
        break;
152
3.93M
    }
153
310k
    case typelib_TypeClass_BOOLEAN:
154
310k
        if (*static_cast< sal_Bool const * >(val))
155
145k
            o3tl::hash_combine( hash, true );
156
165k
        else
157
165k
            o3tl::hash_combine( hash, false );
158
310k
        break;
159
0
    case typelib_TypeClass_CHAR: {
160
0
        o3tl::hash_combine( hash, *static_cast< sal_Unicode const * >(val));
161
0
        break;
162
3.93M
    }
163
0
    case typelib_TypeClass_FLOAT:
164
0
        o3tl::hash_combine( hash, *static_cast< float const * >(val) );
165
0
        break;
166
240k
    case typelib_TypeClass_DOUBLE:
167
240k
        o3tl::hash_combine( hash, *static_cast< double const * >(val) );
168
240k
        break;
169
0
    case typelib_TypeClass_BYTE:
170
0
        o3tl::hash_combine( hash, *static_cast< sal_Int8 const * >(val) );
171
0
        break;
172
50.1M
    case typelib_TypeClass_SHORT:
173
50.1M
        o3tl::hash_combine( hash, *static_cast< sal_Int16 const * >(val) );
174
50.1M
        break;
175
0
    case typelib_TypeClass_UNSIGNED_SHORT:
176
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt16 const * >(val) );
177
0
        break;
178
12.9M
    case typelib_TypeClass_LONG:
179
12.9M
        o3tl::hash_combine( hash, *static_cast< sal_Int32 const * >(val) );
180
12.9M
        break;
181
0
    case typelib_TypeClass_UNSIGNED_LONG:
182
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt32 const * >(val) );
183
0
        break;
184
0
    case typelib_TypeClass_HYPER:
185
0
        o3tl::hash_combine( hash, *static_cast< sal_Int64 const * >(val) );
186
0
        break;
187
0
    case typelib_TypeClass_UNSIGNED_HYPER:
188
0
        o3tl::hash_combine( hash, *static_cast< sal_uInt64 const * >(val) );
189
0
        break;
190
//     case typelib_TypeClass_UNKNOWN:
191
//     case typelib_TypeClass_SERVICE:
192
//     case typelib_TypeClass_MODULE:
193
0
    default:
194
0
        return std::nullopt;
195
124M
    }
196
112M
    return hash;
197
124M
}
198
199
} // anon namespace
200
201
202
std::optional<size_t> anyToHash( uno::Any const & value )
203
811k
{
204
811k
    size_t hash = 0;
205
811k
    return hashValue( hash, value.getValue(), value.getValueTypeRef());
206
811k
}
207
208
} // namespace comphelper
209
210
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */