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