[Libreoffice-commits] core.git: cppuhelper/source registry/tools

Stephan Bergmann sbergman at redhat.com
Mon Feb 11 02:45:38 PST 2013


 cppuhelper/source/typedescriptionprovider.cxx |  149 ++++++++++++++++++++------
 registry/tools/reg2bin.cxx                    |   46 ++++++--
 2 files changed, 159 insertions(+), 36 deletions(-)

New commits:
commit a6b1ed45fb5cf4ef192f0bb32adb8da963a51283
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Feb 11 11:45:10 2013 +0100

    Fix floating point handling
    
    Change-Id: Ib29dfc71f8c2d0797ead2c32f77bedf7156a3393

diff --git a/cppuhelper/source/typedescriptionprovider.cxx b/cppuhelper/source/typedescriptionprovider.cxx
index 2d19518..7e12c29 100644
--- a/cppuhelper/source/typedescriptionprovider.cxx
+++ b/cppuhelper/source/typedescriptionprovider.cxx
@@ -49,6 +49,7 @@
 #include "com/sun/star/uno/XInterface.hpp"
 #include "cppuhelper/compbase2.hxx"
 #include "cppuhelper/implbase1.hxx"
+#include "osl/endian.h"
 #include "osl/file.h"
 #include "osl/file.hxx"
 #include "osl/mutex.hxx"
@@ -221,11 +222,11 @@
 // *** 7: UNSIGNED HYPER
 // **** followed by UInt64 value
 // *** 8: FLOAT
-// **** followed by UInt32 value, representing values in IEEE-754 single
-//       precision format
+// **** followed by 4-byte value, representing values in ISO 60599 binary32
+//       format, LSB first
 // *** 9: DOUBLE
-// **** followed by UInt64 value, representing values in IEEE-754 double
-//       precision format
+// **** followed by 8-byte value, representing values in ISO 60599 binary64
+//       format, LSB first
 //
 // Memory layout:
 //
@@ -236,33 +237,51 @@
 
 namespace {
 
-// sizeof (UInt16) == 2
-struct UInt16 {
+// sizeof (Memory16) == 2
+struct Memory16 {
     unsigned char byte[2];
 
-    sal_uInt16 get() const {
+    sal_uInt16 getUnsigned16() const {
         return static_cast< sal_uInt16 >(byte[0])
             | (static_cast< sal_uInt16 >(byte[1]) << 8);
     }
 };
 
-// sizeof (UInt32) == 4
-struct UInt32 {
+// sizeof (Memory32) == 4
+struct Memory32 {
     unsigned char byte[4];
 
-    sal_uInt32 get() const {
+    sal_uInt32 getUnsigned32() const {
         return static_cast< sal_uInt32 >(byte[0])
             | (static_cast< sal_uInt32 >(byte[1]) << 8)
             | (static_cast< sal_uInt32 >(byte[2]) << 16)
             | (static_cast< sal_uInt32 >(byte[3]) << 24);
     }
+
+    float getIso60599Binary32() const {
+        // Create a copy in either case, for alingment:
+        unsigned char buf[4];
+#if defined OSL_LITENDIAN
+        buf[0] = byte[0];
+        buf[1] = byte[1];
+        buf[2] = byte[2];
+        buf[3] = byte[3];
+#else
+        buf[0] = byte[3];
+        buf[1] = byte[2];
+        buf[2] = byte[1];
+        buf[3] = byte[0];
+#endif
+        return *reinterpret_cast< float * >(buf);
+            // assuming float is ISO 60599 binary32
+    }
 };
 
-// sizeof (UInt64) == 8
-struct UInt64 {
+// sizeof (Memory64) == 8
+struct Memory64 {
     unsigned char byte[8];
 
-    sal_uInt64 get() const {
+    sal_uInt64 getUnsigned64() const {
         return static_cast< sal_uInt64 >(byte[0])
             | (static_cast< sal_uInt64 >(byte[1]) << 8)
             | (static_cast< sal_uInt64 >(byte[2]) << 16)
@@ -272,6 +291,32 @@ struct UInt64 {
             | (static_cast< sal_uInt64 >(byte[6]) << 48)
             | (static_cast< sal_uInt64 >(byte[7]) << 56);
         }
+
+    double getIso60599Binary64() const {
+        // Create a copy in either case, for alingment:
+        unsigned char buf[8];
+#if defined OSL_LITENDIAN
+        buf[0] = byte[0];
+        buf[1] = byte[1];
+        buf[2] = byte[2];
+        buf[3] = byte[3];
+        buf[4] = byte[4];
+        buf[5] = byte[5];
+        buf[6] = byte[6];
+        buf[7] = byte[7];
+#else
+        buf[0] = byte[7];
+        buf[1] = byte[6];
+        buf[2] = byte[5];
+        buf[3] = byte[4];
+        buf[4] = byte[3];
+        buf[5] = byte[2];
+        buf[6] = byte[1];
+        buf[7] = byte[0];
+#endif
+        return *reinterpret_cast< double * >(buf);
+            // assuming double is ISO 60599 binary64
+    }
 };
 
 struct MappedFile:
@@ -287,6 +332,10 @@ struct MappedFile:
 
     sal_uInt64 read64(sal_uInt32 offset) const;
 
+    float readIso60599Binary32(sal_uInt32 offset) const;
+
+    double readIso60599Binary64(sal_uInt32 offset) const;
+
     rtl::OUString readNameNul(sal_uInt32 offset) const;
 
     rtl::OUString readNameLen(sal_uInt32 offset, sal_uInt32 * newOffset = 0)
@@ -306,6 +355,10 @@ private:
     sal_uInt32 get32(sal_uInt32 offset) const;
 
     sal_uInt64 get64(sal_uInt32 offset) const;
+
+    float getIso60599Binary32(sal_uInt32 offset) const;
+
+    double getIso60599Binary64(sal_uInt32 offset) const;
 };
 
 MappedFile::MappedFile(rtl::OUString const & fileUrl) {
@@ -378,6 +431,26 @@ sal_uInt64 MappedFile::read64(sal_uInt32 offset) const {
     return get64(offset);
 }
 
+float MappedFile::readIso60599Binary32(sal_uInt32 offset) const {
+    assert(size >= 8);
+    if (offset > size - 4) {
+        throw css::uno::DeploymentException(
+            "broken UNOIDL file: offset for 32-bit value too large",
+            css::uno::Reference< css::uno::XInterface >());
+    }
+    return getIso60599Binary32(offset);
+}
+
+double MappedFile::readIso60599Binary64(sal_uInt32 offset) const {
+    assert(size >= 8);
+    if (offset > size - 8) {
+        throw css::uno::DeploymentException(
+            "broken UNOIDL file: offset for 64-bit value too large",
+            css::uno::Reference< css::uno::XInterface >());
+    }
+    return getIso60599Binary64(offset);
+}
+
 rtl::OUString MappedFile::readNameNul(sal_uInt32 offset) const {
     if (offset > size) {
         throw css::uno::DeploymentException(
@@ -473,22 +546,36 @@ sal_uInt8 MappedFile::get8(sal_uInt32 offset) const {
 sal_uInt16 MappedFile::get16(sal_uInt32 offset) const {
     assert(size >= 8);
     assert(offset <= size - 2);
-    return reinterpret_cast< UInt16 const * >(
-        static_cast< char const * >(address) + offset)->get();
+    return reinterpret_cast< Memory16 const * >(
+        static_cast< char const * >(address) + offset)->getUnsigned16();
 }
 
 sal_uInt32 MappedFile::get32(sal_uInt32 offset) const {
     assert(size >= 8);
     assert(offset <= size - 4);
-    return reinterpret_cast< UInt32 const * >(
-        static_cast< char const * >(address) + offset)->get();
+    return reinterpret_cast< Memory32 const * >(
+        static_cast< char const * >(address) + offset)->getUnsigned32();
 }
 
 sal_uInt64 MappedFile::get64(sal_uInt32 offset) const {
     assert(size >= 8);
     assert(offset <= size - 8);
-    return reinterpret_cast< UInt64 const * >(
-        static_cast< char const * >(address) + offset)->get();
+    return reinterpret_cast< Memory64 const * >(
+        static_cast< char const * >(address) + offset)->getUnsigned64();
+}
+
+float MappedFile::getIso60599Binary32(sal_uInt32 offset) const {
+    assert(size >= 8);
+    assert(offset <= size - 4);
+    return reinterpret_cast< Memory32 const * >(
+        static_cast< char const * >(address) + offset)->getIso60599Binary32();
+}
+
+double MappedFile::getIso60599Binary64(sal_uInt32 offset) const {
+    assert(size >= 8);
+    assert(offset <= size - 8);
+    return reinterpret_cast< Memory64 const * >(
+        static_cast< char const * >(address) + offset)->getIso60599Binary64();
 }
 
 css::uno::Reference< css::reflection::XTypeDescription > resolve(
@@ -2035,8 +2122,8 @@ private:
 
 // sizeof (MapEntry) == 8
 struct MapEntry {
-    UInt32 name;
-    UInt32 data;
+    Memory32 name;
+    Memory32 data;
 };
 
 class Enumeration:
@@ -2139,7 +2226,7 @@ void Enumeration::proceed() {
     assert(!positions_.empty());
     assert(positions_.top().position < positions_.top().end);
     if (deep_) {
-        sal_uInt32 off = positions_.top().position->data.get();
+        sal_uInt32 off = positions_.top().position->data.getUnsigned32();
         int v = file_->read8(off);
         bool recurse;
         bool cgroup = bool();
@@ -2155,7 +2242,8 @@ void Enumeration::proceed() {
         if (recurse) {
             rtl::OUString prefix(
                 positions_.top().prefix
-                + file_->readNameNul(positions_.top().position->name.get())
+                + file_->readNameNul(
+                    positions_.top().position->name.getUnsigned32())
                 + ".");
             sal_uInt32 mapSize = file_->read32(off + 1);
             if (8 * mapSize > file_->size - off - 5) { //TODO: overflow
@@ -2187,7 +2275,7 @@ void Enumeration::findMatch() {
             assert(matches(css::uno::TypeClass_CONSTANT));
             match = true;
         } else {
-            sal_uInt32 off = positions_.top().position->data.get();
+            sal_uInt32 off = positions_.top().position->data.getUnsigned32();
             int v = file_->read8(off);
             css::uno::TypeClass tc;
             switch (v & 0x1F) {
@@ -2232,7 +2320,8 @@ void Enumeration::findMatch() {
         }
         if (match) {
             current_ = positions_.top().prefix
-                + file_->readNameNul(positions_.top().position->name.get());
+                + file_->readNameNul(
+                    positions_.top().position->name.getUnsigned32());
             return;
         }
     }
@@ -2383,9 +2472,11 @@ css::uno::Any Provider::getByHierarchicalName(rtl::OUString const & aName)
             any <<= file_->read64(off + 1);
             break;
         case 8: // FLOAT
-            //TODO
+            any <<= file_->readIso60599Binary32(off + 1);
+            break;
         case 9: // DOUBLE
-            //TODO
+            any <<= file_->readIso60599Binary64(off + 1);
+            break;
         default:
             throw css::uno::DeploymentException(
                 ("broken UNOIDL file: bad constant type byte "
@@ -3036,7 +3127,7 @@ sal_uInt32 Provider::findInMap(
     default: // COMPARE_EQUAL
         break;
     }
-    sal_uInt32 off = mapBegin[n].data.get();
+    sal_uInt32 off = mapBegin[n].data.getUnsigned32();
     if (off == 0) {
         throw css::uno::DeploymentException(
             "broken UNOIDL file: map entry data offset is null",
@@ -3050,7 +3141,7 @@ Provider::Compare Provider::compare(
     MapEntry const * entry) const
 {
     assert(entry != 0);
-    sal_uInt32 off = entry->name.get();
+    sal_uInt32 off = entry->name.getUnsigned32();
     if (off > file_->size - 1) { // at least a trailing NUL
         throw css::uno::DeploymentException(
             "broken UNOIDL file: string offset too large",
diff --git a/registry/tools/reg2bin.cxx b/registry/tools/reg2bin.cxx
index 5983b56..2a1ca05 100644
--- a/registry/tools/reg2bin.cxx
+++ b/registry/tools/reg2bin.cxx
@@ -9,6 +9,7 @@
 
 #include "sal/config.h"
 
+#include <algorithm>
 #include <cassert>
 #include <cstdlib>
 #include <cstring>
@@ -17,6 +18,7 @@
 #include <utility>
 #include <vector>
 
+#include "osl/endian.h"
 #include "osl/file.h"
 #include "osl/file.hxx"
 #include "osl/process.h"
@@ -31,6 +33,7 @@
 #include "rtl/textenc.h"
 #include "rtl/textcvt.h"
 #include "rtl/ustring.hxx"
+#include "sal/macros.h"
 #include "sal/main.h"
 
 namespace {
@@ -910,8 +913,9 @@ void write8(osl::File & file, sal_uInt64 value) {
         std::cerr << "Cannot write value >= 2^8; input is too large\n";
         std::exit(EXIT_FAILURE);
     }
-    unsigned char buf = value & 0xFF;
-    write(file, &buf, 1);
+    unsigned char buf[1];
+    buf[0] = value & 0xFF;
+    write(file, buf, SAL_N_ELEMENTS(buf));
 }
 
 void write16(osl::File & file, sal_uInt64 value) {
@@ -922,7 +926,7 @@ void write16(osl::File & file, sal_uInt64 value) {
     unsigned char buf[2];
     buf[0] = value & 0xFF;
     buf[1] = (value >> 8) & 0xFF;
-    write(file, buf, 2);
+    write(file, buf, SAL_N_ELEMENTS(buf));
 }
 
 void write32(osl::File & file, sal_uInt64 value) {
@@ -935,7 +939,7 @@ void write32(osl::File & file, sal_uInt64 value) {
     buf[1] = (value >> 8) & 0xFF;
     buf[2] = (value >> 16) & 0xFF;
     buf[3] = (value >> 24) & 0xFF;
-    write(file, buf, 4);
+    write(file, buf, SAL_N_ELEMENTS(buf));
 }
 
 void write64(osl::File & file, sal_uInt64 value) {
@@ -948,7 +952,31 @@ void write64(osl::File & file, sal_uInt64 value) {
     buf[3] = (value >> 40) & 0xFF;
     buf[3] = (value >> 48) & 0xFF;
     buf[3] = (value >> 56) & 0xFF;
-    write(file, buf, 8);
+    write(file, buf, SAL_N_ELEMENTS(buf));
+}
+
+void writeIso60599Binary32(osl::File & file, float value) {
+    unsigned char buf[4];
+    *reinterpret_cast< float * >(buf) = value;
+        // assuming float is ISO 60599 binary32
+#if defined OSL_BIGENDIAN
+    std::swap(buf[0], buf[3]);
+    std::swap(buf[1], buf[2]);
+#endif
+    write(file, buf, SAL_N_ELEMENTS(buf));
+}
+
+void writeIso60599Binary64(osl::File & file, double value) {
+    unsigned char buf[8];
+    *reinterpret_cast< double * >(buf) = value;
+        // assuming double is ISO 60599 binary64
+#if defined OSL_BIGENDIAN
+    std::swap(buf[0], buf[7]);
+    std::swap(buf[1], buf[6]);
+    std::swap(buf[2], buf[5]);
+    std::swap(buf[3], buf[4]);
+#endif
+    write(file, buf, SAL_N_ELEMENTS(buf));
 }
 
 rtl::OString toAscii(rtl::OUString const & name) {
@@ -1196,7 +1224,6 @@ sal_uInt64 writeMap(
                         static_cast< sal_uInt32 >(j->second.constantValue.l));
                     break;
                 case CONSTANT_TYPE_UNSIGNED_LONG:
-                case CONSTANT_TYPE_FLOAT: //access through union for strict-aliasing
                     write32(file, j->second.constantValue.ul);
                     break;
                 case CONSTANT_TYPE_HYPER:
@@ -1205,9 +1232,14 @@ sal_uInt64 writeMap(
                         static_cast< sal_uInt64 >(j->second.constantValue.h));
                     break;
                 case CONSTANT_TYPE_UNSIGNED_HYPER:
-                case CONSTANT_TYPE_DOUBLE: //access through union for strict-aliasing
                     write64(file, j->second.constantValue.uh);
                     break;
+                case CONSTANT_TYPE_FLOAT:
+                    writeIso60599Binary32(file, j->second.constantValue.f);
+                    break;
+                case CONSTANT_TYPE_DOUBLE:
+                    writeIso60599Binary64(file, j->second.constantValue.d);
+                    break;
                 default:
                     std::abort(); // this cannot happen
                 }


More information about the Libreoffice-commits mailing list