LibreOffice Module stoc (master) 1
dump.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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
10#include <sal/config.h>
11
12#include <bitset>
13
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>
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>
42
43namespace com::sun::star::uno
44{
45class XInterface;
46}
47
48namespace
49{
50template <typename T> OUString hex(T value, sal_Int32 width)
51{
52 OUStringBuffer buf(OUString::number(value, 16));
53 while (buf.getLength() < width)
54 {
55 buf.insert(0, '0');
56 }
57 return buf.makeStringAndClear();
58}
59
60css::uno::TypeDescription getTypeDescription(css::uno::Type const& type)
61{
62 typelib_TypeDescription* d = nullptr;
63 type.getDescription(&d);
64 return css::uno::TypeDescription(d);
65}
66
67OUString
68getIdentifier(css::uno::Reference<css::reflection::XConstantTypeDescription> const& constant)
69{
70 auto const n = constant->getName();
71 auto const i = n.lastIndexOf('.');
72 if (i == -1 || i == n.getLength() - 1)
73 {
74 throw css::uno::DeploymentException("bad constant name " + n);
75 }
76 return n.copy(i + 1);
77}
78
79OUString
80dumpBitset(css::uno::Sequence<css::uno::Reference<css::reflection::XConstantTypeDescription>> const&
81 constants,
82 sal_uInt64 value)
83{
84 OUStringBuffer buf;
85 auto a = value;
86 for (auto const& i : constants)
87 {
88 sal_uInt64 c;
89 if ((i->getConstantValue() >>= c) && std::bitset<64>{ c }.count() == 1 && (a & c) != 0)
90 {
91 if (!buf.isEmpty())
92 {
93 buf.append('+');
94 }
95 buf.append(getIdentifier(i));
96 a &= ~c;
97 }
98 }
99 return a == 0 && !buf.isEmpty() ? buf.makeStringAndClear() : OUString::number(value);
100}
101
102class Dump : public cppu::BaseMutex, public cppu::WeakComponentImplHelper<css::reflection::XDump>
103{
104public:
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)
110 {
111 }
112
113 void SAL_CALL disposing() override
114 {
115 osl::MutexGuard g(m_aMutex);
116 manager_.clear();
117 }
118
119 OUString SAL_CALL dumpValue(css::uno::Any const& value) override
120 {
121 switch (value.getValueTypeClass())
122 {
123 case css::uno::TypeClass_VOID:
124 return "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:
148 {
149 auto const s = value.get<OUString>();
150 OUStringBuffer buf;
151 for (sal_Int32 i = 0; i != s.getLength();)
152 {
153 auto const c = s.iterateCodePoints(&i);
154 if (c >= u8' ' && c <= u8'~')
155 {
156 if (c == u8'\"' || c == u8'\\')
157 {
158 buf.append('\\');
159 }
160 buf.append(char(c));
161 }
162 else if (c <= 0xFFFF)
163 {
164 buf.append("\\u" + hex(c, 4));
165 }
166 else
167 {
168 buf.append("\\U" + hex(c, 8));
169 }
170 }
171 return "\"" + buf + "\"";
172 }
173 case css::uno::TypeClass_TYPE:
174 return value.get<css::uno::Type>().getTypeName();
175 case css::uno::TypeClass_SEQUENCE:
176 {
177 css::uno::Type const t(reinterpret_cast<typelib_IndirectTypeDescription const*>(
178 getTypeDescription(value.getValueType()).get())
179 ->pType);
180 auto const n = getTypeDescription(t).get()->nSize;
181 auto const s = *static_cast<uno_Sequence* const*>(value.getValue());
182 OUStringBuffer buf;
183 for (sal_Int32 i = 0; i != s->nElements; ++i)
184 {
185 if (i != 0)
186 {
187 buf.append(", ");
188 }
189 css::uno::Any const e(s->elements + i * n, t);
190 buf.append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(e)
191 : dumpValue(e));
192 }
193 return "[" + buf + "]";
194 }
195 case css::uno::TypeClass_ENUM:
196 {
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)
201 {
202 if (ed->pEnumValues[i] == e)
203 {
204 return OUString(ed->ppEnumNames[i]);
205 }
206 }
207 return OUString::number(e);
208 }
209 case css::uno::TypeClass_STRUCT:
210 case css::uno::TypeClass_EXCEPTION:
211 {
212 auto const d = getTypeDescription(value.getValueType());
213 OUStringBuffer buf;
214 dumpCompoundType(reinterpret_cast<typelib_CompoundTypeDescription const*>(d.get()),
215 value.getValue(), &buf);
216 return "[" + buf + "]";
217 }
218 case css::uno::TypeClass_INTERFACE:
219 {
220 auto const p = *static_cast<void* const*>(value.getValue());
221 return p == nullptr ? OUString("null")
222 : OUString("0x"
223 + hex(reinterpret_cast<sal_uIntPtr>(p),
224 SAL_TYPES_SIZEOFPOINTER * 2));
225 }
226 default:
228 }
229 }
230
231 OUString SAL_CALL dumpAny(css::uno::Any const& value) override
232 {
233 return "[" + value.getValueType().getTypeName() + ": " + dumpValue(value) + "]";
234 }
235
236 OUString SAL_CALL dumpConstant(OUString const& constantsGroup,
237 css::uno::Any const& value) override
238 {
239 css::uno::Reference<css::container::XHierarchicalNameAccess> manager;
240 {
241 osl::MutexGuard g(m_aMutex);
242 if (rBHelper.bDisposed)
243 {
244 throw css::lang::DisposedException("css.reflection.Dumper");
245 }
247 }
248 css::uno::Reference<css::reflection::XConstantsTypeDescription> g;
249 try
250 {
251 manager_->getByHierarchicalName(constantsGroup) >>= g;
252 }
253 catch (css::container::NoSuchElementException)
254 {
255 }
256 if (!g.is())
257 {
258 throw css::lang::IllegalArgumentException("not a constants group: " + constantsGroup,
259 {}, 0);
260 }
261 auto const s = g->getConstants();
262 switch (value.getValueTypeClass())
263 {
264 case css::uno::TypeClass_BOOLEAN:
265 for (auto const& i : s)
266 {
267 if (i->getConstantValue() == value)
268 {
269 return getIdentifier(i);
270 }
271 }
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:
277 {
278 auto const v = value.get<sal_Int64>();
279 for (auto const& i : s)
280 {
281 sal_Int64 c;
282 if ((i->getConstantValue() >>= c) && c == v)
283 {
284 return getIdentifier(i);
285 }
286 }
287 return v >= 0 ? dumpBitset(s, v) : OUString::number(v);
288 }
289 case css::uno::TypeClass_UNSIGNED_SHORT:
290 case css::uno::TypeClass_UNSIGNED_LONG:
291 case css::uno::TypeClass_UNSIGNED_HYPER:
292 {
293 auto const v = value.get<sal_uInt64>();
294 for (auto const& i : s)
295 {
296 sal_uInt64 c;
297 if ((i->getConstantValue() >>= c) && c == v)
298 {
299 return getIdentifier(i);
300 }
301 }
302 return dumpBitset(s, v);
303 }
304 case css::uno::TypeClass_FLOAT:
305 case css::uno::TypeClass_DOUBLE:
306 {
307 auto const v = value.get<double>();
308 for (auto const& i : s)
309 {
310 double c;
311 if ((i->getConstantValue() >>= c) && c == v)
312 {
313 return getIdentifier(i);
314 }
315 }
316 return OUString::number(v);
317 }
318 default:
319 throw css::lang::IllegalArgumentException(
320 "not a numeric type: " + value.getValueTypeName(), {}, 1);
321 }
322 }
323
324private:
325 css::uno::Reference<css::container::XHierarchicalNameAccess> manager_;
326
327 void dumpCompoundType(typelib_CompoundTypeDescription const* description, void const* data,
328 OUStringBuffer* buffer)
329 {
330 if (auto base = description->pBaseTypeDescription)
331 {
332 dumpCompoundType(base, data, buffer);
333 }
334 for (sal_Int32 i = 0; i != description->nMembers; ++i)
335 {
336 if (!buffer->isEmpty())
337 {
338 buffer->append(", ");
339 }
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],
343 t);
344 buffer->append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(m) : dumpValue(m));
345 }
346 }
347};
348}
349
350extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
351com_sun_star_comp_stoc_Dump_get_implementation(css::uno::XComponentContext* context,
352 css::uno::Sequence<css::uno::Any> const& arguments)
353{
354 SAL_WARN_IF(arguments.hasElements(), "stoc", "unexpected singleton arguments");
355 return cppu::acquire(new Dump(context));
356}
357
358/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
XPropertyListType t
double d
Any value
rtl::Reference< ParseManager > manager
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_stoc_Dump_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &arguments)
Definition: dump.cxx:351
float v
std::mutex m_aMutex
void * p
sal_Int64 n
uno_Any a
rtl::Reference< Manager > manager_
#define SAL_WARN_IF(condition, area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
rtl::OUString getTypeName(rtl::OUString const &rEnvDcp)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
int i
m
sal_uInt16 sal_Unicode
signed char sal_Int8
ResultType type
#define O3TL_UNREACHABLE