summaryrefslogtreecommitdiff
path: root/codemaker
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2023-03-16 15:32:10 +0200
committerTor Lillqvist <tml@collabora.com>2023-03-17 11:46:36 +0000
commite1c6f36d8bcc0799281e3a7e244175f682d97cb2 (patch)
tree3218e006a6abe07260b3248621012b0ae5fa5864 /codemaker
parentf92721bf182952be88b0349a17e46b684d630c29 (diff)
Add a to_string() function to the code generated for UNO IDL constant groups
If the inpt matches one of the constants exactly, the result is the name of that constant. If the input matches some combination of constant values that are single bits, the result is the sequence of the names of those constants joined with plus signs. For instance, if the IDL has: constants Constants { const byte BIT0 = 1; const byte BIT1 = 2; const byte BIT2 = 4; const byte BIT3 = 8; } The result of Constants::to_string(5) is "BIT0+BIT2", and the result of Constants::to_string(17) is "17". I am sure there are corner cases that aren't handled as would be intuitive, especially with types that include unsigned values. Correspondingly, the semantics of the generated to_string() functions is not formally defined. Also add a unit test for the new functionality. Change-Id: I14aa826d0989ac6dfe97dd5c09119b1601c65643 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148995 Tested-by: Jenkins Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'codemaker')
-rw-r--r--codemaker/source/cppumaker/cpputype.cxx159
1 files changed, 159 insertions, 0 deletions
diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx
index bb8e3ed7d33c..c4ccbbb7ad0c 100644
--- a/codemaker/source/cppumaker/cpputype.cxx
+++ b/codemaker/source/cppumaker/cpputype.cxx
@@ -21,6 +21,7 @@
#include <sal/log.hxx>
#include <algorithm>
+#include <bitset>
#include <cassert>
#include <cstdlib>
#include <map>
@@ -1660,6 +1661,7 @@ 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)) {
@@ -1685,6 +1687,10 @@ 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) {
@@ -1693,30 +1699,60 @@ 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 << " = ";
@@ -1770,6 +1806,129 @@ 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)