From 9111536f1bbaed489ed3ed36315e05d4b3940f5b Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Tue, 21 Mar 2023 23:16:35 +0100 Subject: [PATCH] Introduce css.reflection.Dump singleton ...and revert e1c6f36d8bcc0799281e3a7e244175f682d97cb2 "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 Tested-by: Jenkins --- codemaker/source/cppumaker/cpputype.cxx | 159 -------- cppu/qa/cppumaker/test_cppumaker.cxx | 32 -- stoc/CppunitTest_stoc_dump.mk | 33 ++ stoc/Library_reflection.mk | 1 + stoc/Module_stoc.mk | 1 + stoc/source/corereflection/dump.cxx | 358 ++++++++++++++++++ .../corereflection/reflection.component | 5 + stoc/test/dump.cxx | 152 ++++++++ stoc/test/dump.idl | 85 +++++ udkapi/UnoApi_udkapi.mk | 2 + udkapi/com/sun/star/reflection/Dump.idl | 22 ++ udkapi/com/sun/star/reflection/XDump.idl | 58 +++ 12 files changed, 717 insertions(+), 191 deletions(-) create mode 100644 stoc/CppunitTest_stoc_dump.mk create mode 100644 stoc/source/corereflection/dump.cxx create mode 100644 stoc/test/dump.cxx create mode 100644 stoc/test/dump.idl create mode 100644 udkapi/com/sun/star/reflection/Dump.idl create mode 100644 udkapi/com/sun/star/reflection/XDump.idl diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx index c4ccbbb7ad0c..bb8e3ed7d33c 100644 --- a/codemaker/source/cppumaker/cpputype.cxx +++ b/codemaker/source/cppumaker/cpputype.cxx @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -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 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(member.value.booleanValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_BYTE: - if (!handledValues.insert(static_cast(member.value.byteValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_SHORT: - if (!handledValues.insert(static_cast(member.value.shortValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT: - if (!handledValues.insert(static_cast(member.value.unsignedShortValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_LONG: - if (!handledValues.insert(static_cast(member.value.longValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_UNSIGNED_LONG: - if (!handledValues.insert(static_cast(member.value.unsignedLongValue)).second) - skip = true; - break; - case unoidl::ConstantValue::TYPE_HYPER: - if (!handledValues.insert(static_cast(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(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(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(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(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(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(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(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) diff --git a/cppu/qa/cppumaker/test_cppumaker.cxx b/cppu/qa/cppumaker/test_cppumaker.cxx index cec02d3c710e..a6d3e4942f06 100644 --- a/cppu/qa/cppumaker/test_cppumaker.cxx +++ b/cppu/qa/cppumaker/test_cppumaker.cxx @@ -352,9 +352,6 @@ #include #include #include -#include -#include -#include #include #include @@ -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(-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(-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_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); } diff --git a/stoc/CppunitTest_stoc_dump.mk b/stoc/CppunitTest_stoc_dump.mk new file mode 100644 index 000000000000..98f5fe7f8dc3 --- /dev/null +++ b/stoc/CppunitTest_stoc_dump.mk @@ -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: diff --git a/stoc/Library_reflection.mk b/stoc/Library_reflection.mk index eac448030f14..083b2378363b 100644 --- a/stoc/Library_reflection.mk +++ b/stoc/Library_reflection.mk @@ -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: diff --git a/stoc/Module_stoc.mk b/stoc/Module_stoc.mk index d05c53d55fd3..e94e5be476b4 100644 --- a/stoc/Module_stoc.mk +++ b/stoc/Module_stoc.mk @@ -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 \ )) diff --git a/stoc/source/corereflection/dump.cxx b/stoc/source/corereflection/dump.cxx new file mode 100644 index 000000000000..0905393db9bc --- /dev/null +++ b/stoc/source/corereflection/dump.cxx @@ -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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace com::sun::star::uno +{ +class XInterface; +} + +namespace +{ +template 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 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> 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 +{ +public: + explicit Dump(css::uno::Reference 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()); + case css::uno::TypeClass_BYTE: + return OUString::number(value.get()); + case css::uno::TypeClass_SHORT: + return OUString::number(value.get()); + case css::uno::TypeClass_UNSIGNED_SHORT: + return OUString::number(value.get()); + case css::uno::TypeClass_LONG: + return OUString::number(value.get()); + case css::uno::TypeClass_UNSIGNED_LONG: + return OUString::number(value.get()); + case css::uno::TypeClass_HYPER: + return OUString::number(value.get()); + case css::uno::TypeClass_UNSIGNED_HYPER: + return OUString::number(value.get()); + case css::uno::TypeClass_FLOAT: + return OUString::number(value.get()); + case css::uno::TypeClass_DOUBLE: + return OUString::number(value.get()); + case css::uno::TypeClass_CHAR: + return "U+" + hex(value.get(), 16); + case css::uno::TypeClass_STRING: + { + auto const s = value.get(); + 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().getTypeName(); + case css::uno::TypeClass_SEQUENCE: + { + css::uno::Type const t(reinterpret_cast( + getTypeDescription(value.getValueType()).get()) + ->pType); + auto const n = getTypeDescription(t).get()->nSize; + auto const s = *static_cast(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::get() ? dumpAny(e) + : dumpValue(e)); + } + return "[" + buf + "]"; + } + case css::uno::TypeClass_ENUM: + { + auto const d = getTypeDescription(value.getValueType()); + auto const ed = reinterpret_cast(d.get()); + auto const e = *static_cast(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(d.get()), + value.getValue(), &buf); + return "[" + buf + "]"; + } + case css::uno::TypeClass_INTERFACE: + { + auto const p = *static_cast(value.getValue()); + return p == nullptr ? OUString("null") + : OUString("0x" + + hex(reinterpret_cast(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 manager; + { + osl::MutexGuard g(m_aMutex); + if (rBHelper.bDisposed) + { + throw css::lang::DisposedException("css.reflection.Dumper"); + } + manager = manager_; + } + css::uno::Reference 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()); + 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(); + 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(); + 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(); + 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 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(data) + description->pMemberOffsets[i], + t); + buffer->append(t == cppu::UnoType::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 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: */ diff --git a/stoc/source/corereflection/reflection.component b/stoc/source/corereflection/reflection.component index 70ccb68e0402..0210c80904f0 100644 --- a/stoc/source/corereflection/reflection.component +++ b/stoc/source/corereflection/reflection.component @@ -25,4 +25,9 @@ + + + diff --git a/stoc/test/dump.cxx b/stoc/test/dump.cxx new file mode 100644 index 000000000000..798e05acc2ca --- /dev/null +++ b/stoc/test/dump.cxx @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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{}))); + CPPUNIT_ASSERT_EQUAL(OUString("[1]"), + dump_->dumpValue(css::uno::Any(css::uno::Sequence{ 1 }))); + CPPUNIT_ASSERT_EQUAL(OUString("[1, 2, 3]"), dump_->dumpValue(css::uno::Any( + css::uno::Sequence{ 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(sal_Int32(1)), css::uno::Any(OUString("2")), + css::uno::Any(css::uno::Sequence{ 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 dump_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(Dump); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/stoc/test/dump.idl b/stoc/test/dump.idl new file mode 100644 index 000000000000..65bac74a32bf --- /dev/null +++ b/stoc/test/dump.idl @@ -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: */ diff --git a/udkapi/UnoApi_udkapi.mk b/udkapi/UnoApi_udkapi.mk index 03a3accd2c6c..f18b9f758ddc 100644 --- a/udkapi/UnoApi_udkapi.mk +++ b/udkapi/UnoApi_udkapi.mk @@ -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 \ diff --git a/udkapi/com/sun/star/reflection/Dump.idl b/udkapi/com/sun/star/reflection/Dump.idl new file mode 100644 index 000000000000..849a788a773e --- /dev/null +++ b/udkapi/com/sun/star/reflection/Dump.idl @@ -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: */ diff --git a/udkapi/com/sun/star/reflection/XDump.idl b/udkapi/com/sun/star/reflection/XDump.idl new file mode 100644 index 000000000000..fac2a48eafc5 --- /dev/null +++ b/udkapi/com/sun/star/reflection/XDump.idl @@ -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: */