Introduce css.reflection.Dump singleton

...and revert e1c6f36d8b "Add a to_string()
function to the code generated for UNO IDL constant groups".  (But keep the
constants groups the latter had added to cppu/qa/cppumaker/types.idl, and use
them in the newly added CppunitTest_stoc_dump, for better or worse.)

Change-Id: I56e9eaeb1e45b83a72a25eceef13e719dc6f3a1e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149281
Reviewed-by: Tor Lillqvist <tml@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Stephan Bergmann 2023-03-21 23:16:35 +01:00
parent 464a3549ae
commit 9111536f1b
12 changed files with 717 additions and 191 deletions

View file

@ -21,7 +21,6 @@
#include <sal/log.hxx>
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cstdlib>
#include <map>
@ -1661,7 +1660,6 @@ void ConstantGroup::dumpHdlFile(
OUString headerDefine(dumpHeaderDefine(out, u"HDL"));
out << "\n";
addDefaultHIncludes(includes);
includes.addRtlUstringHxx();
includes.dump(out, nullptr, true);
out << "\n";
if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, true)) {
@ -1687,10 +1685,6 @@ void ConstantGroup::dumpHppFile(
void ConstantGroup::dumpDeclaration(FileStream & out)
{
unoidl::ConstantValue::Type largestType = unoidl::ConstantValue::TYPE_BOOLEAN;
OUString largestTypeName = "sal_Bool";
bool haveFloatingPoint = false;
for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
out << "static const ";
switch (member.value.type) {
@ -1699,60 +1693,30 @@ void ConstantGroup::dumpDeclaration(FileStream & out)
break;
case unoidl::ConstantValue::TYPE_BYTE:
out << "::sal_Int8";
if (largestType < unoidl::ConstantValue::TYPE_BYTE) {
largestType = unoidl::ConstantValue::TYPE_BYTE;
largestTypeName = "sal_Int8";
}
break;
case unoidl::ConstantValue::TYPE_SHORT:
out << "::sal_Int16";
if (largestType < unoidl::ConstantValue::TYPE_SHORT) {
largestType = unoidl::ConstantValue::TYPE_SHORT;
largestTypeName = "sal_Int16";
}
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
out << "::sal_uInt16";
if (largestType < unoidl::ConstantValue::TYPE_UNSIGNED_SHORT) {
largestType = unoidl::ConstantValue::TYPE_UNSIGNED_SHORT;
largestTypeName = "sal_uInt16";
}
break;
case unoidl::ConstantValue::TYPE_LONG:
out << "::sal_Int32";
if (largestType < unoidl::ConstantValue::TYPE_LONG) {
largestType = unoidl::ConstantValue::TYPE_LONG;
largestTypeName = "sal_Int32";
}
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
out << "::sal_uInt32";
if (largestType < unoidl::ConstantValue::TYPE_UNSIGNED_LONG) {
largestType = unoidl::ConstantValue::TYPE_UNSIGNED_LONG;
largestTypeName = "sal_uInt32";
}
break;
case unoidl::ConstantValue::TYPE_HYPER:
out << "::sal_Int64";
if (largestType < unoidl::ConstantValue::TYPE_HYPER) {
largestType = unoidl::ConstantValue::TYPE_HYPER;
largestTypeName = "sal_Int64";
}
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
out << "::sal_uInt64";
if (largestType < unoidl::ConstantValue::TYPE_UNSIGNED_HYPER) {
largestType = unoidl::ConstantValue::TYPE_UNSIGNED_HYPER;
largestTypeName = "sal_uInt64";
}
break;
case unoidl::ConstantValue::TYPE_FLOAT:
out << "float";
haveFloatingPoint = true;
break;
case unoidl::ConstantValue::TYPE_DOUBLE:
out << "double";
haveFloatingPoint = true;
break;
}
out << " " << member.name << " = ";
@ -1806,129 +1770,6 @@ void ConstantGroup::dumpDeclaration(FileStream & out)
}
out << ";\n";
}
// If there are only integral constants, generate a function to
// produce a symbolic string of a value of the type.
if (!haveFloatingPoint) {
out << "\n"
"#ifdef LIBO_INTERNAL_ONLY\n";
out << "inline ::rtl::OUString to_string(::" << largestTypeName << " input_value) {\n";
out << " switch (input_value) {\n";
std::set<sal_uInt64> handledValues;
// Go through each constant and generate a case for exactly
// that, unless there was another constant with the same
// value.
for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
bool skip = false;
switch (member.value.type) {
case unoidl::ConstantValue::TYPE_BOOLEAN:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.booleanValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_BYTE:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.byteValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_SHORT:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.shortValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.unsignedShortValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_LONG:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.longValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.unsignedLongValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_HYPER:
if (!handledValues.insert(static_cast<sal_uInt64>(member.value.hyperValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
if (!handledValues.insert(member.value.unsignedHyperValue).second)
skip = true;
break;
default:
assert(false); // Can not happen
}
if (!skip)
out << " case (" << largestTypeName << ")" << member.name << ": return \"" << member.name << "\";\n";
}
out << " default:\n";
// Next generate code to check for each individual bit, for
// the constants that are single bit values.
handledValues.clear();
out << " ::rtl::OUString result_string;\n"
" " << largestTypeName << " accum_value = input_value;\n";
for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
bool skip = false;
switch (member.value.type) {
case unoidl::ConstantValue::TYPE_BOOLEAN:
if (!member.value.booleanValue || !handledValues.insert(static_cast<sal_uInt64>(member.value.booleanValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_BYTE:
if (std::bitset<8>(member.value.byteValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.byteValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_SHORT:
if (std::bitset<16>(member.value.shortValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.shortValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
if (std::bitset<16>(member.value.unsignedShortValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.unsignedShortValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_LONG:
if (std::bitset<32>(member.value.longValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.longValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
if (std::bitset<32>(member.value.unsignedLongValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.unsignedLongValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_HYPER:
if (std::bitset<64>(member.value.hyperValue).count() != 1 || !handledValues.insert(static_cast<sal_uInt64>(member.value.hyperValue)).second)
skip = true;
break;
case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
if (std::bitset<64>(member.value.unsignedHyperValue).count() != 1 || !handledValues.insert(member.value.unsignedHyperValue).second)
skip = true;
break;
default:
assert(false);
}
if (!skip)
out << " if ((accum_value&" << member.name << ") == (" << largestTypeName << ")" << member.name << ") {\n"
" if (!result_string.isEmpty())\n"
" result_string += \"+\";\n"
" result_string += \"" << member.name << "\";\n"
" accum_value &= ~" << member.name << ";\n"
" }\n";
}
out << " if (accum_value == 0 && !result_string.isEmpty())\n"
" return result_string;\n"
" }\n";
out << " return ::rtl::OUString::number(input_value);\n"
"}\n"
"#endif\n";
// The caller takes care of finally calling dumpNamespaceClose().
}
}
void dumpTypeParameterName(FileStream & out, std::u16string_view name)

View file

@ -352,9 +352,6 @@
#include <test/codemaker/cppumaker/TestException1.hpp>
#include <test/codemaker/cppumaker/TestException2.hpp>
#include <test/codemaker/cppumaker/Constants.hpp>
#include <test/codemaker/cppumaker/ByteBits.hpp>
#include <test/codemaker/cppumaker/ShortBits.hpp>
#include <test/codemaker/cppumaker/UnsignedHyperBits.hpp>
#include <memory>
#include <com/sun/star/uno/Any.hxx>
@ -393,14 +390,11 @@ public:
void testConstants();
void testSymbolicConstants();
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testBigStruct);
CPPUNIT_TEST(testPolyStruct);
CPPUNIT_TEST(testExceptions);
CPPUNIT_TEST(testConstants);
CPPUNIT_TEST(testSymbolicConstants);
CPPUNIT_TEST_SUITE_END();
};
@ -556,32 +550,6 @@ void Test::testConstants() {
test::codemaker::cppumaker::Constants::unsignedHyperMax);
}
void Test::testSymbolicConstants() {
CPPUNIT_ASSERT_EQUAL(OUString("byteMin"), test::codemaker::cppumaker::Constants::to_string(static_cast<sal_uInt64>(-128)));
CPPUNIT_ASSERT_EQUAL(OUString("byteMax"), test::codemaker::cppumaker::Constants::to_string(127));
CPPUNIT_ASSERT_EQUAL(OUString("longMin"), test::codemaker::cppumaker::Constants::to_string(static_cast<sal_uInt64>(-2147483648)));
CPPUNIT_ASSERT_EQUAL(OUString("longMax"), test::codemaker::cppumaker::Constants::to_string(2147483647));
CPPUNIT_ASSERT_EQUAL(OUString("hyperMin"), test::codemaker::cppumaker::Constants::to_string(static_cast<sal_uInt64>(SAL_MIN_INT64)));
CPPUNIT_ASSERT_EQUAL(OUString("hyperMax"), test::codemaker::cppumaker::Constants::to_string(SAL_MAX_INT64));
CPPUNIT_ASSERT_EQUAL(OUString("17"), test::codemaker::cppumaker::Constants::to_string(17));
CPPUNIT_ASSERT_EQUAL(OUString("2147483646"), test::codemaker::cppumaker::Constants::to_string(2147483646));
CPPUNIT_ASSERT_EQUAL(OUString("0"), test::codemaker::cppumaker::ByteBits::to_string(0));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT2"), test::codemaker::cppumaker::ByteBits::to_string(5));
CPPUNIT_ASSERT_EQUAL(OUString("BIT4"), test::codemaker::cppumaker::ByteBits::to_string(16));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT4"), test::codemaker::cppumaker::ByteBits::to_string(17));
CPPUNIT_ASSERT_EQUAL(OUString("BIT7"), test::codemaker::cppumaker::ByteBits::to_string(-128));
CPPUNIT_ASSERT_EQUAL(OUString("ALL"), test::codemaker::cppumaker::ByteBits::to_string(-1));
CPPUNIT_ASSERT_EQUAL(OUString("BIT7"), test::codemaker::cppumaker::ShortBits::to_string(128));
CPPUNIT_ASSERT_EQUAL(OUString("ALL"), test::codemaker::cppumaker::ShortBits::to_string(-1));
CPPUNIT_ASSERT_EQUAL(OUString("BIT63"), test::codemaker::cppumaker::UnsignedHyperBits::to_string(9223372036854775808u));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT62"), test::codemaker::cppumaker::UnsignedHyperBits::to_string(4611686018427387905));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT63"), test::codemaker::cppumaker::UnsignedHyperBits::to_string(9223372036854775809u));
CPPUNIT_ASSERT_EQUAL(OUString("ALL"), test::codemaker::cppumaker::UnsignedHyperBits::to_string(SAL_MAX_UINT64));
}
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
}

View file

@ -0,0 +1,33 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_CppunitTest_CppunitTest,stoc_dump))
$(eval $(call gb_CppunitTest_add_exception_objects,stoc_dump, \
stoc/test/dump \
))
$(eval $(call gb_CppunitTest_use_internal_api,stoc_dump, \
cppu_qa_cppumaker_types \
))
$(eval $(call gb_CppunitTest_use_libraries,stoc_dump, \
cppu \
cppuhelper \
sal \
))
$(eval $(call gb_CppunitTest_use_udk_api,stoc_dump))
$(eval $(call gb_CppunitTest_use_ure,stoc_dump))
$(call gb_CppunitTest_get_target,stoc_dump): \
UNO_TYPES += $(call gb_UnoApiTarget_get_target,cppu_qa_cppumaker_types)
# vim: set noet sw=4 ts=4:

View file

@ -28,6 +28,7 @@ $(eval $(call gb_Library_add_exception_objects,reflection,\
stoc/source/corereflection/crefl \
stoc/source/corereflection/crenum \
stoc/source/corereflection/criface \
stoc/source/corereflection/dump \
))
# vim:set noet sw=4 ts=4:

View file

@ -30,6 +30,7 @@ $(eval $(call gb_Module_add_targets,stoc,\
endif
$(eval $(call gb_Module_add_check_targets,stoc, \
CppunitTest_stoc_dump \
CppunitTest_stoc_uriproc \
))

View file

@ -0,0 +1,358 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <bitset>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/reflection/XConstantTypeDescription.hpp>
#include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
#include <com/sun/star/reflection/XDump.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/DeploymentException.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/uno/TypeClass.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <config_typesizes.h>
#include <cppu/unotype.hxx>
#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/compbase.hxx>
#include <cppuhelper/interfacecontainer.hxx>
#include <o3tl/unreachable.hxx>
#include <osl/mutex.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <sal/types.h>
#include <typelib/typedescription.h>
#include <typelib/typedescription.hxx>
#include <uno/sequence2.h>
namespace com::sun::star::uno
{
class XInterface;
}
namespace
{
template <typename T> OUString hex(T value, sal_Int32 width)
{
OUStringBuffer buf(OUString::number(value, 16));
while (buf.getLength() < width)
{
buf.insert(0, '0');
}
return buf.makeStringAndClear();
}
css::uno::TypeDescription getTypeDescription(css::uno::Type const& type)
{
typelib_TypeDescription* d = nullptr;
type.getDescription(&d);
return css::uno::TypeDescription(d);
}
OUString
getIdentifier(css::uno::Reference<css::reflection::XConstantTypeDescription> const& constant)
{
auto const n = constant->getName();
auto const i = n.lastIndexOf('.');
if (i == -1 || i == n.getLength() - 1)
{
throw css::uno::DeploymentException("bad constant name " + n);
}
return n.copy(i + 1);
}
OUString
dumpBitset(css::uno::Sequence<css::uno::Reference<css::reflection::XConstantTypeDescription>> const&
constants,
sal_uInt64 value)
{
OUStringBuffer buf;
auto a = value;
for (auto const& i : constants)
{
sal_uInt64 c;
if ((i->getConstantValue() >>= c) && std::bitset<64>{ c }.count() == 1 && (a & c) != 0)
{
if (!buf.isEmpty())
{
buf.append('+');
}
buf.append(getIdentifier(i));
a &= ~c;
}
}
return a == 0 && !buf.isEmpty() ? buf.makeStringAndClear() : OUString::number(value);
}
class Dump : public cppu::BaseMutex, public cppu::WeakComponentImplHelper<css::reflection::XDump>
{
public:
explicit Dump(css::uno::Reference<css::uno::XComponentContext> const& context)
: WeakComponentImplHelper(m_aMutex)
, manager_(context->getValueByName(
"/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
css::uno::UNO_QUERY_THROW)
{
}
void SAL_CALL disposing() override
{
osl::MutexGuard g(m_aMutex);
manager_.clear();
}
OUString SAL_CALL dumpValue(css::uno::Any const& value) override
{
switch (value.getValueTypeClass())
{
case css::uno::TypeClass_VOID:
return "void";
case css::uno::TypeClass_BOOLEAN:
return OUString::boolean(value.get<bool>());
case css::uno::TypeClass_BYTE:
return OUString::number(value.get<sal_Int8>());
case css::uno::TypeClass_SHORT:
return OUString::number(value.get<sal_Int16>());
case css::uno::TypeClass_UNSIGNED_SHORT:
return OUString::number(value.get<sal_uInt16>());
case css::uno::TypeClass_LONG:
return OUString::number(value.get<sal_Int32>());
case css::uno::TypeClass_UNSIGNED_LONG:
return OUString::number(value.get<sal_uInt32>());
case css::uno::TypeClass_HYPER:
return OUString::number(value.get<sal_Int64>());
case css::uno::TypeClass_UNSIGNED_HYPER:
return OUString::number(value.get<sal_uInt64>());
case css::uno::TypeClass_FLOAT:
return OUString::number(value.get<float>());
case css::uno::TypeClass_DOUBLE:
return OUString::number(value.get<double>());
case css::uno::TypeClass_CHAR:
return "U+" + hex(value.get<sal_Unicode>(), 16);
case css::uno::TypeClass_STRING:
{
auto const s = value.get<OUString>();
OUStringBuffer buf;
for (sal_Int32 i = 0; i != s.getLength();)
{
auto const c = s.iterateCodePoints(&i);
if (c >= u8' ' && c <= u8'~')
{
if (c == u8'\"' || c == u8'\\')
{
buf.append('\\');
}
buf.append(char(c));
}
else if (c <= 0xFFFF)
{
buf.append("\\u" + hex(c, 4));
}
else
{
buf.append("\\U" + hex(c, 8));
}
}
return "\"" + buf + "\"";
}
case css::uno::TypeClass_TYPE:
return value.get<css::uno::Type>().getTypeName();
case css::uno::TypeClass_SEQUENCE:
{
css::uno::Type const t(reinterpret_cast<typelib_IndirectTypeDescription const*>(
getTypeDescription(value.getValueType()).get())
->pType);
auto const n = getTypeDescription(t).get()->nSize;
auto const s = *static_cast<uno_Sequence* const*>(value.getValue());
OUStringBuffer buf;
for (sal_Int32 i = 0; i != s->nElements; ++i)
{
if (i != 0)
{
buf.append(", ");
}
css::uno::Any const e(s->elements + i * n, t);
buf.append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(e)
: dumpValue(e));
}
return "[" + buf + "]";
}
case css::uno::TypeClass_ENUM:
{
auto const d = getTypeDescription(value.getValueType());
auto const ed = reinterpret_cast<typelib_EnumTypeDescription const*>(d.get());
auto const e = *static_cast<sal_Int32 const*>(value.getValue());
for (sal_Int32 i = 0; i != ed->nEnumValues; ++i)
{
if (ed->pEnumValues[i] == e)
{
return OUString(ed->ppEnumNames[i]);
}
}
return OUString::number(e);
}
case css::uno::TypeClass_STRUCT:
case css::uno::TypeClass_EXCEPTION:
{
auto const d = getTypeDescription(value.getValueType());
OUStringBuffer buf;
dumpCompoundType(reinterpret_cast<typelib_CompoundTypeDescription const*>(d.get()),
value.getValue(), &buf);
return "[" + buf + "]";
}
case css::uno::TypeClass_INTERFACE:
{
auto const p = *static_cast<void* const*>(value.getValue());
return p == nullptr ? OUString("null")
: OUString("0x"
+ hex(reinterpret_cast<sal_uIntPtr>(p),
SAL_TYPES_SIZEOFPOINTER * 2));
}
default:
O3TL_UNREACHABLE;
}
}
OUString SAL_CALL dumpAny(css::uno::Any const& value) override
{
return "[" + value.getValueType().getTypeName() + ": " + dumpValue(value) + "]";
}
OUString SAL_CALL dumpConstant(OUString const& constantsGroup,
css::uno::Any const& value) override
{
css::uno::Reference<css::container::XHierarchicalNameAccess> manager;
{
osl::MutexGuard g(m_aMutex);
if (rBHelper.bDisposed)
{
throw css::lang::DisposedException("css.reflection.Dumper");
}
manager = manager_;
}
css::uno::Reference<css::reflection::XConstantsTypeDescription> g;
try
{
manager_->getByHierarchicalName(constantsGroup) >>= g;
}
catch (css::container::NoSuchElementException)
{
}
if (!g.is())
{
throw css::lang::IllegalArgumentException("not a constants group: " + constantsGroup,
{}, 0);
}
auto const s = g->getConstants();
switch (value.getValueTypeClass())
{
case css::uno::TypeClass_BOOLEAN:
for (auto const& i : s)
{
if (i->getConstantValue() == value)
{
return getIdentifier(i);
}
}
return OUString::boolean(value.get<bool>());
case css::uno::TypeClass_BYTE:
case css::uno::TypeClass_SHORT:
case css::uno::TypeClass_LONG:
case css::uno::TypeClass_HYPER:
{
auto const v = value.get<sal_Int64>();
for (auto const& i : s)
{
sal_Int64 c;
if ((i->getConstantValue() >>= c) && c == v)
{
return getIdentifier(i);
}
}
return v >= 0 ? dumpBitset(s, v) : OUString::number(v);
}
case css::uno::TypeClass_UNSIGNED_SHORT:
case css::uno::TypeClass_UNSIGNED_LONG:
case css::uno::TypeClass_UNSIGNED_HYPER:
{
auto const v = value.get<sal_uInt64>();
for (auto const& i : s)
{
sal_uInt64 c;
if ((i->getConstantValue() >>= c) && c == v)
{
return getIdentifier(i);
}
}
return dumpBitset(s, v);
}
case css::uno::TypeClass_FLOAT:
case css::uno::TypeClass_DOUBLE:
{
auto const v = value.get<double>();
for (auto const& i : s)
{
double c;
if ((i->getConstantValue() >>= c) && c == v)
{
return getIdentifier(i);
}
}
return OUString::number(v);
}
default:
throw css::lang::IllegalArgumentException(
"not a numeric type: " + value.getValueTypeName(), {}, 1);
}
}
private:
css::uno::Reference<css::container::XHierarchicalNameAccess> manager_;
void dumpCompoundType(typelib_CompoundTypeDescription const* description, void const* data,
OUStringBuffer* buffer)
{
if (auto base = description->pBaseTypeDescription)
{
dumpCompoundType(base, data, buffer);
}
for (sal_Int32 i = 0; i != description->nMembers; ++i)
{
if (!buffer->isEmpty())
{
buffer->append(", ");
}
buffer->append(OUString::unacquired(description->ppMemberNames + i) + ": ");
css::uno::Type t(description->ppTypeRefs[i]);
css::uno::Any const m(static_cast<char const*>(data) + description->pMemberOffsets[i],
t);
buffer->append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(m) : dumpValue(m));
}
}
};
}
extern "C" 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)
{
SAL_WARN_IF(arguments.hasElements(), "stoc", "unexpected singleton arguments");
return cppu::acquire(new Dump(context));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -25,4 +25,9 @@
<service name="com.sun.star.reflection.CoreReflection"/>
<singleton name="com.sun.star.reflection.theCoreReflection"/>
</implementation>
<implementation name="com.sun.star.comp.stoc.Dump"
constructor="com_sun_star_comp_stoc_Dump_get_implementation"
single-instance="true">
<singleton name="com.sun.star.reflection.Dump"/>
</implementation>
</component>

152
stoc/test/dump.cxx Normal file
View file

@ -0,0 +1,152 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
#include <com/sun/star/reflection/Dump.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/TypeClass.hpp>
#include <cppuhelper/bootstrap.hxx>
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <test/codemaker/cppumaker/ByteBits.hpp>
#include <test/codemaker/cppumaker/Constants.hpp>
#include <test/codemaker/cppumaker/ShortBits.hpp>
#include <test/codemaker/cppumaker/UnsignedHyperBits.hpp>
namespace
{
class Dump : public CppUnit::TestFixture
{
public:
void setUp() override
{
dump_ = css::reflection::Dump::get(cppu::defaultBootstrap_InitialComponentContext());
}
void testSequence()
{
CPPUNIT_ASSERT_EQUAL(OUString("[]"),
dump_->dumpValue(css::uno::Any(css::uno::Sequence<sal_Int32>{})));
CPPUNIT_ASSERT_EQUAL(OUString("[1]"),
dump_->dumpValue(css::uno::Any(css::uno::Sequence<sal_Int32>{ 1 })));
CPPUNIT_ASSERT_EQUAL(OUString("[1, 2, 3]"), dump_->dumpValue(css::uno::Any(
css::uno::Sequence<sal_Int32>{ 1, 2, 3 })));
CPPUNIT_ASSERT_EQUAL(OUString("[[long: 1], [string: \"2\"], [[]long: [1, 2]]]"),
(dump_->dumpValue(css::uno::Any(css::uno::Sequence<css::uno::Any>{
css::uno::Any(sal_Int32(1)), css::uno::Any(OUString("2")),
css::uno::Any(css::uno::Sequence<sal_Int32>{ 1, 2 }) }))));
}
void testEnum()
{
CPPUNIT_ASSERT_EQUAL(OUString("ENUM"),
dump_->dumpValue(css::uno::Any(css::uno::TypeClass_ENUM)));
CPPUNIT_ASSERT_EQUAL(OUString("-1"),
dump_->dumpValue(css::uno::Any(css::uno::TypeClass(-1))));
CPPUNIT_ASSERT_EQUAL(OUString("12345"),
dump_->dumpValue(css::uno::Any(css::uno::TypeClass(12345))));
}
void testStruct()
{
CPPUNIT_ASSERT_EQUAL(
OUString("[Source: null, PropertyName: \"test\", Further: false, PropertyHandle: 3, "
"OldValue: [void: void], NewValue: [long: 5]]"),
dump_->dumpValue(css::uno::Any(css::beans::PropertyChangeEvent(
{}, "test", false, 3, {}, css::uno::Any(sal_Int32(5))))));
}
void testConstantsGroup()
{
CPPUNIT_ASSERT_EQUAL(OUString("byteMin"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int8(-128))));
CPPUNIT_ASSERT_EQUAL(OUString("byteMax"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int8(127))));
CPPUNIT_ASSERT_EQUAL(OUString("longMin"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int32(-2147483648))));
CPPUNIT_ASSERT_EQUAL(OUString("longMax"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int32(2147483647))));
CPPUNIT_ASSERT_EQUAL(OUString("hyperMin"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(SAL_MIN_INT64)));
CPPUNIT_ASSERT_EQUAL(OUString("hyperMax"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(SAL_MAX_INT64)));
CPPUNIT_ASSERT_EQUAL(OUString("17"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int32(17))));
CPPUNIT_ASSERT_EQUAL(OUString("2147483646"),
dump_->dumpConstant("test.codemaker.cppumaker.Constants",
css::uno::Any(sal_Int32(2147483646))));
CPPUNIT_ASSERT_EQUAL(OUString("0"), dump_->dumpConstant("test.codemaker.cppumaker.ByteBits",
css::uno::Any(sal_Int8(0))));
CPPUNIT_ASSERT_EQUAL(
OUString("BIT0+BIT2"),
dump_->dumpConstant("test.codemaker.cppumaker.ByteBits", css::uno::Any(sal_Int8(5))));
CPPUNIT_ASSERT_EQUAL(
OUString("BIT4"),
dump_->dumpConstant("test.codemaker.cppumaker.ByteBits", css::uno::Any(sal_Int8(16))));
CPPUNIT_ASSERT_EQUAL(
OUString("BIT0+BIT4"),
dump_->dumpConstant("test.codemaker.cppumaker.ByteBits", css::uno::Any(sal_Int8(17))));
CPPUNIT_ASSERT_EQUAL(OUString("BIT7"),
dump_->dumpConstant("test.codemaker.cppumaker.ByteBits",
css::uno::Any(sal_Int8(-128))));
CPPUNIT_ASSERT_EQUAL(
OUString("ALL"),
dump_->dumpConstant("test.codemaker.cppumaker.ByteBits", css::uno::Any(sal_Int8(-1))));
CPPUNIT_ASSERT_EQUAL(OUString("BIT7"),
dump_->dumpConstant("test.codemaker.cppumaker.ShortBits",
css::uno::Any(sal_Int16(128))));
CPPUNIT_ASSERT_EQUAL(OUString("ALL"),
dump_->dumpConstant("test.codemaker.cppumaker.ShortBits",
css::uno::Any(sal_Int16(-1))));
CPPUNIT_ASSERT_EQUAL(OUString("BIT63"),
dump_->dumpConstant("test.codemaker.cppumaker.UnsignedHyperBits",
css::uno::Any(sal_uInt64(9223372036854775808u))));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT62"),
dump_->dumpConstant("test.codemaker.cppumaker.UnsignedHyperBits",
css::uno::Any(sal_uInt64(4611686018427387905))));
CPPUNIT_ASSERT_EQUAL(OUString("BIT0+BIT63"),
dump_->dumpConstant("test.codemaker.cppumaker.UnsignedHyperBits",
css::uno::Any(sal_uInt64(9223372036854775809u))));
CPPUNIT_ASSERT_EQUAL(OUString("ALL"),
dump_->dumpConstant("test.codemaker.cppumaker.UnsignedHyperBits",
css::uno::Any(SAL_MAX_UINT64)));
}
CPPUNIT_TEST_SUITE(Dump);
CPPUNIT_TEST(testSequence);
CPPUNIT_TEST(testEnum);
CPPUNIT_TEST(testStruct);
CPPUNIT_TEST(testConstantsGroup);
CPPUNIT_TEST_SUITE_END();
private:
css::uno::Reference<css::reflection::XDump> dump_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(Dump);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

85
stoc/test/dump.idl Normal file
View file

@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
module org { module libreoffice { module test {
constants Constants {
const byte byteMin = -128;
const byte byteMax = 127;
const short shortMin = -32768;
const short shortMax = 32767;
const unsigned short unsignedShortMin = 0;
const unsigned short unsignedShortMax = 65535;
const long longMin = -2147483648;
const long longMax = 2147483647;
const unsigned long unsignedLongMin = 0;
const unsigned long unsignedLongMax = 4294967295;
const hyper hyperMin = -9223372036854775808;
const hyper hyperMax = 9223372036854775807;
const unsigned hyper unsignedHyperMin = 0;
const unsigned hyper unsignedHyperMax = 18446744073709551615;
};
constants ByteBits {
const byte BIT0 = 1;
const byte BIT1 = 2;
const byte BIT2 = 4;
const byte BIT3 = 8;
const byte BIT4 = 16;
const byte BIT5 = 32;
const byte BIT6 = 64;
const byte BIT7 = -128;
const byte ALL = -1;
};
constants ShortBits {
const short BIT0 = 1;
const short BIT1 = 2;
const short BIT2 = 4;
const short BIT3 = 8;
const short BIT4 = 16;
const short BIT5 = 32;
const short BIT6 = 64;
const short BIT7 = 128;
const short BIT8 = 256;
const short BIT9 = 512;
const short BIT10 = 1024;
const short BIT11 = 2048;
const short BIT12 = 4096;
const short BIT13 = 8192;
const short BIT14 = 16384;
const short BIT15 = -32768;
const short ALL = -1;
};
constants UnsignedHyperBits {
const unsigned hyper BIT0 = 1;
const unsigned hyper BIT1 = 2;
const unsigned hyper BIT2 = 4;
const unsigned hyper BIT3 = 8;
const unsigned hyper BIT4 = 16;
const unsigned hyper BIT5 = 32;
const unsigned hyper BIT6 = 64;
const unsigned hyper BIT7 = 128;
const unsigned hyper BIT8 = 256;
const unsigned hyper BIT9 = 512;
const unsigned hyper BIT10 = 1024;
const unsigned hyper BIT11 = 2048;
const unsigned hyper BIT12 = 4096;
const unsigned hyper BIT13 = 8192;
const unsigned hyper BIT14 = 16384;
const unsigned hyper BIT15 = 32768;
const unsigned hyper BIT62 = 4611686018427387904;
const unsigned hyper BIT63 = 9223372036854775808;
const unsigned hyper ALL = 18446744073709551615;
};
}; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -104,6 +104,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,udkapi,com/sun/star/java,\
))
$(eval $(call gb_UnoApi_add_idlfiles_nohdl,udkapi,com/sun/star/reflection,\
theCoreReflection \
Dump \
ProxyFactory \
))
$(eval $(call gb_UnoApi_add_idlfiles_nohdl,udkapi,com/sun/star/registry,\
@ -378,6 +379,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,udkapi,com/sun/star/reflection,\
XCompoundTypeDescription \
XConstantTypeDescription \
XConstantsTypeDescription \
XDump \
XEnumTypeDescription \
XIdlArray \
XIdlClass \

View file

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
module com { module sun { module star { module reflection {
/** Dump any UNOIDL value as a string.
Mainly useful for logging and debugging purposes.
@since LibreOffice 7.6
*/
singleton Dump: XDump;
}; }; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
module com { module sun { module star { module reflection {
/** Dump any UNOIDL value as a string.
Mainly useful for logging and debugging purposes.
@since LibreOffice 7.6
*/
interface XDump {
/** Dump a UNOIDL value as a string.
This just dumps the value itself, without any further decoration.
@param value any UNOIDL value
@returns a string representation of the given value
*/
string dumpValue([in] any value);
/** Dump the value of a UNOIDL ANY as a string.
This dumps the type and value of the given ANY.
@param value any UNOIDL ANY
@returns a string representation of the given ANY
*/
string dumpAny([in] any value);
/** Dump a numeric UNOIDL value, interpreted relative to a UNOIDL constants group, as a string.
@param constantsGroup the name (in dotted notation, as supported by
/singletons/theTypeDescriptionManager) of a UNOIDL constants group
@param value a UNOIDL value of type BOOLEAN, BYTE, SHORT, UNSIGNED SHORT, LONG, UNSIGNED
LONG, HYPER, UNSIGNED HYPER, FLOAT, or DOUBLE
@returns a string representation of the given numeric value
@throws com::sun::star::lang::IllegalArgumentException if the constantsGroup argument does
not represent a UNOIDL constants group or the value argument is of wrong type
*/
string dumpConstant([in] string constantsGroup, [in] any value)
raises (com::sun::star::lang::IllegalArgumentException);
};
}; }; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */