1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sal/config.h>
14 #include <com/sun/star/container/NoSuchElementException.hpp>
15 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
16 #include <com/sun/star/lang/DisposedException.hpp>
17 #include <com/sun/star/lang/IllegalArgumentException.hpp>
18 #include <com/sun/star/reflection/XConstantTypeDescription.hpp>
19 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
20 #include <com/sun/star/reflection/XDump.hpp>
21 #include <com/sun/star/uno/Any.hxx>
22 #include <com/sun/star/uno/DeploymentException.hpp>
23 #include <com/sun/star/uno/Reference.hxx>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/uno/Type.hxx>
26 #include <com/sun/star/uno/TypeClass.hpp>
27 #include <com/sun/star/uno/XComponentContext.hpp>
28 #include <config_typesizes.h>
29 #include <cppu/unotype.hxx>
30 #include <cppuhelper/basemutex.hxx>
31 #include <cppuhelper/compbase.hxx>
32 #include <cppuhelper/interfacecontainer.hxx>
33 #include <o3tl/unreachable.hxx>
34 #include <osl/mutex.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <rtl/ustring.hxx>
37 #include <sal/log.hxx>
38 #include <sal/types.h>
39 #include <typelib/typedescription.h>
40 #include <typelib/typedescription.hxx>
41 #include <uno/sequence2.h>
43 namespace com::sun::star::uno
50 template <typename T
> OUString
hex(T value
, sal_Int32 width
)
52 OUStringBuffer
buf(OUString::number(value
, 16));
53 while (buf
.getLength() < width
)
57 return buf
.makeStringAndClear();
60 css::uno::TypeDescription
getTypeDescription(css::uno::Type
const& type
)
62 typelib_TypeDescription
* d
= nullptr;
63 type
.getDescription(&d
);
64 return css::uno::TypeDescription(d
);
68 getIdentifier(css::uno::Reference
<css::reflection::XConstantTypeDescription
> const& constant
)
70 auto const n
= constant
->getName();
71 auto const i
= n
.lastIndexOf('.');
72 if (i
== -1 || i
== n
.getLength() - 1)
74 throw css::uno::DeploymentException("bad constant name " + n
);
80 dumpBitset(css::uno::Sequence
<css::uno::Reference
<css::reflection::XConstantTypeDescription
>> const&
86 for (auto const& i
: constants
)
89 if ((i
->getConstantValue() >>= c
) && std::bitset
<64>{ c
}.count() == 1 && (a
& c
) != 0)
95 buf
.append(getIdentifier(i
));
99 return a
== 0 && !buf
.isEmpty() ? buf
.makeStringAndClear() : OUString::number(value
);
102 class Dump
: public cppu::BaseMutex
, public cppu::WeakComponentImplHelper
<css::reflection::XDump
>
105 explicit Dump(css::uno::Reference
<css::uno::XComponentContext
> const& context
)
106 : WeakComponentImplHelper(m_aMutex
)
107 , manager_(context
->getValueByName(
108 "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
109 css::uno::UNO_QUERY_THROW
)
113 void SAL_CALL
disposing() override
115 osl::MutexGuard
g(m_aMutex
);
119 OUString SAL_CALL
dumpValue(css::uno::Any
const& value
) override
121 switch (value
.getValueTypeClass())
123 case css::uno::TypeClass_VOID
:
125 case css::uno::TypeClass_BOOLEAN
:
126 return OUString::boolean(value
.get
<bool>());
127 case css::uno::TypeClass_BYTE
:
128 return OUString::number(value
.get
<sal_Int8
>());
129 case css::uno::TypeClass_SHORT
:
130 return OUString::number(value
.get
<sal_Int16
>());
131 case css::uno::TypeClass_UNSIGNED_SHORT
:
132 return OUString::number(value
.get
<sal_uInt16
>());
133 case css::uno::TypeClass_LONG
:
134 return OUString::number(value
.get
<sal_Int32
>());
135 case css::uno::TypeClass_UNSIGNED_LONG
:
136 return OUString::number(value
.get
<sal_uInt32
>());
137 case css::uno::TypeClass_HYPER
:
138 return OUString::number(value
.get
<sal_Int64
>());
139 case css::uno::TypeClass_UNSIGNED_HYPER
:
140 return OUString::number(value
.get
<sal_uInt64
>());
141 case css::uno::TypeClass_FLOAT
:
142 return OUString::number(value
.get
<float>());
143 case css::uno::TypeClass_DOUBLE
:
144 return OUString::number(value
.get
<double>());
145 case css::uno::TypeClass_CHAR
:
146 return "U+" + hex(value
.get
<sal_Unicode
>(), 16);
147 case css::uno::TypeClass_STRING
:
149 auto const s
= value
.get
<OUString
>();
151 for (sal_Int32 i
= 0; i
!= s
.getLength();)
153 auto const c
= s
.iterateCodePoints(&i
);
154 if (c
>= u8
' ' && c
<= u8
'~')
156 if (c
== u8
'\"' || c
== u8
'\\')
162 else if (c
<= 0xFFFF)
164 buf
.append("\\u" + hex(c
, 4));
168 buf
.append("\\U" + hex(c
, 8));
171 return "\"" + buf
+ "\"";
173 case css::uno::TypeClass_TYPE
:
174 return value
.get
<css::uno::Type
>().getTypeName();
175 case css::uno::TypeClass_SEQUENCE
:
177 css::uno::Type
const t(reinterpret_cast<typelib_IndirectTypeDescription
const*>(
178 getTypeDescription(value
.getValueType()).get())
180 auto const n
= getTypeDescription(t
).get()->nSize
;
181 auto const s
= *static_cast<uno_Sequence
* const*>(value
.getValue());
183 for (sal_Int32 i
= 0; i
!= s
->nElements
; ++i
)
189 css::uno::Any
const e(s
->elements
+ i
* n
, t
);
190 buf
.append(t
== cppu::UnoType
<css::uno::Any
>::get() ? dumpAny(e
)
193 return "[" + buf
+ "]";
195 case css::uno::TypeClass_ENUM
:
197 auto const d
= getTypeDescription(value
.getValueType());
198 auto const ed
= reinterpret_cast<typelib_EnumTypeDescription
const*>(d
.get());
199 auto const e
= *static_cast<sal_Int32
const*>(value
.getValue());
200 for (sal_Int32 i
= 0; i
!= ed
->nEnumValues
; ++i
)
202 if (ed
->pEnumValues
[i
] == e
)
204 return OUString(ed
->ppEnumNames
[i
]);
207 return OUString::number(e
);
209 case css::uno::TypeClass_STRUCT
:
210 case css::uno::TypeClass_EXCEPTION
:
212 auto const d
= getTypeDescription(value
.getValueType());
214 dumpCompoundType(reinterpret_cast<typelib_CompoundTypeDescription
const*>(d
.get()),
215 value
.getValue(), &buf
);
216 return "[" + buf
+ "]";
218 case css::uno::TypeClass_INTERFACE
:
220 auto const p
= *static_cast<void* const*>(value
.getValue());
221 return p
== nullptr ? OUString("null")
223 + hex(reinterpret_cast<sal_uIntPtr
>(p
),
224 SAL_TYPES_SIZEOFPOINTER
* 2));
231 OUString SAL_CALL
dumpAny(css::uno::Any
const& value
) override
233 return "[" + value
.getValueType().getTypeName() + ": " + dumpValue(value
) + "]";
236 OUString SAL_CALL
dumpConstant(OUString
const& constantsGroup
,
237 css::uno::Any
const& value
) override
239 css::uno::Reference
<css::container::XHierarchicalNameAccess
> manager
;
241 osl::MutexGuard
g(m_aMutex
);
242 if (rBHelper
.bDisposed
)
244 throw css::lang::DisposedException("css.reflection.Dumper");
248 css::uno::Reference
<css::reflection::XConstantsTypeDescription
> g
;
251 manager_
->getByHierarchicalName(constantsGroup
) >>= g
;
253 catch (css::container::NoSuchElementException
)
258 throw css::lang::IllegalArgumentException("not a constants group: " + constantsGroup
,
261 auto const s
= g
->getConstants();
262 switch (value
.getValueTypeClass())
264 case css::uno::TypeClass_BOOLEAN
:
265 for (auto const& i
: s
)
267 if (i
->getConstantValue() == value
)
269 return getIdentifier(i
);
272 return OUString::boolean(value
.get
<bool>());
273 case css::uno::TypeClass_BYTE
:
274 case css::uno::TypeClass_SHORT
:
275 case css::uno::TypeClass_LONG
:
276 case css::uno::TypeClass_HYPER
:
278 auto const v
= value
.get
<sal_Int64
>();
279 for (auto const& i
: s
)
282 if ((i
->getConstantValue() >>= c
) && c
== v
)
284 return getIdentifier(i
);
287 return v
>= 0 ? dumpBitset(s
, v
) : OUString::number(v
);
289 case css::uno::TypeClass_UNSIGNED_SHORT
:
290 case css::uno::TypeClass_UNSIGNED_LONG
:
291 case css::uno::TypeClass_UNSIGNED_HYPER
:
293 auto const v
= value
.get
<sal_uInt64
>();
294 for (auto const& i
: s
)
297 if ((i
->getConstantValue() >>= c
) && c
== v
)
299 return getIdentifier(i
);
302 return dumpBitset(s
, v
);
304 case css::uno::TypeClass_FLOAT
:
305 case css::uno::TypeClass_DOUBLE
:
307 auto const v
= value
.get
<double>();
308 for (auto const& i
: s
)
311 if ((i
->getConstantValue() >>= c
) && c
== v
)
313 return getIdentifier(i
);
316 return OUString::number(v
);
319 throw css::lang::IllegalArgumentException(
320 "not a numeric type: " + value
.getValueTypeName(), {}, 1);
325 css::uno::Reference
<css::container::XHierarchicalNameAccess
> manager_
;
327 void dumpCompoundType(typelib_CompoundTypeDescription
const* description
, void const* data
,
328 OUStringBuffer
* buffer
)
330 if (auto base
= description
->pBaseTypeDescription
)
332 dumpCompoundType(base
, data
, buffer
);
334 for (sal_Int32 i
= 0; i
!= description
->nMembers
; ++i
)
336 if (!buffer
->isEmpty())
338 buffer
->append(", ");
340 buffer
->append(OUString::unacquired(description
->ppMemberNames
+ i
) + ": ");
341 css::uno::Type
t(description
->ppTypeRefs
[i
]);
342 css::uno::Any
const m(static_cast<char const*>(data
) + description
->pMemberOffsets
[i
],
344 buffer
->append(t
== cppu::UnoType
<css::uno::Any
>::get() ? dumpAny(m
) : dumpValue(m
));
350 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
351 com_sun_star_comp_stoc_Dump_get_implementation(css::uno::XComponentContext
* context
,
352 css::uno::Sequence
<css::uno::Any
> const& arguments
)
354 SAL_WARN_IF(arguments
.hasElements(), "stoc", "unexpected singleton arguments");
355 return cppu::acquire(new Dump(context
));
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */