Slightly changed serialization format.

printf's %a was too fragile to serialize floats and doubles, as it was
behaving differently on different OSes and OS versions. Instead, a hex
representation of the float/double in big endian is used now. While this
is less readable, it is guaranteed to be accurate and always the same.
This commit is contained in:
Jonathan Schleifer 2012-07-31 13:59:41 +02:00
parent 2d942ed62c
commit 4f843153b7
6 changed files with 51 additions and 15 deletions

View file

@ -323,6 +323,10 @@ static int month_to_day_of_year[12] = {
@try {
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
union {
double d;
uint64_t u;
} d;
if (![[element name] isEqual: [self className]] ||
![[element namespace] isEqual: OF_SERIALIZATION_NS])
@ -330,7 +334,8 @@ static int month_to_day_of_year[12] = {
exceptionWithClass: [self class]
selector: _cmd];
seconds = [element doubleValue];
d.u = (uint64_t)[element hexadecimalValue];
seconds = of_bswap_double_if_le(d.d);
[pool release];
} @catch (id e) {
@ -410,10 +415,17 @@ static int month_to_day_of_year[12] = {
{
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFXMLElement *element;
union {
double d;
uint64_t u;
} d;
element = [OFXMLElement elementWithName: [self className]
namespace: OF_SERIALIZATION_NS];
[element setStringValue: [OFString stringWithFormat: @"%la", seconds]];
d.d = of_bswap_double_if_le(seconds);
[element setStringValue:
[OFString stringWithFormat: @"%016" PRIx64, d.u]];
[element retain];
[pool release];

View file

@ -752,11 +752,25 @@
type = OF_NUMBER_INTMAX;
value.intmax = [element decimalValue];
} else if ([typeString isEqual: @"float"]) {
union {
float f;
uint32_t u;
} f;
f.u = (uint32_t)[element hexadecimalValue];
type = OF_NUMBER_FLOAT;
value.float_ = [element floatValue];
value.float_ = of_bswap_float_if_le(f.f);
} else if ([typeString isEqual: @"double"]) {
union {
double d;
uint64_t u;
} d;
d.u = (uint64_t)[element hexadecimalValue];
type = OF_NUMBER_DOUBLE;
value.double_ = [element doubleValue];
value.double_ = of_bswap_double_if_le(d.d);
} else
@throw [OFInvalidArgumentException
exceptionWithClass: [self class]
@ -1239,17 +1253,31 @@
stringValue: @"signed"];
break;
case OF_NUMBER_FLOAT:;
union {
float f;
uint32_t u;
} f;
f.f = of_bswap_float_if_le(value.float_);
[element addAttributeWithName: @"type"
stringValue: @"float"];
[element setStringValue:
[OFString stringWithFormat: @"%a", value.float_]];
[OFString stringWithFormat: @"%08" PRIx32, f.u]];
break;
case OF_NUMBER_DOUBLE:;
union {
double d;
uint64_t u;
} d;
d.d = of_bswap_double_if_le(value.double_);
[element addAttributeWithName: @"type"
stringValue: @"double"];
[element setStringValue:
[OFString stringWithFormat: @"%la", value.double_]];
[OFString stringWithFormat: @"%016" PRIx64, d.u]];
break;
default:

View file

@ -46,7 +46,7 @@ int _OFObject_Serialization_reference;
root = [OFXMLElement elementWithName: @"serialization"
namespace: OF_SERIALIZATION_NS];
[root addAttributeWithName: @"version"
stringValue: @"0"];
stringValue: @"1"];
[root addChild: element];
ret = [@"<?xml version='1.0' encoding='UTF-8'?>\n"

View file

@ -57,7 +57,7 @@ int _OFString_Serialization_reference;
exceptionWithClass: [self class]
selector: _cmd];
if ([version decimalValue] > 0)
if ([version decimalValue] != 1)
@throw [OFUnsupportedVersionException
exceptionWithClass: [self class]
version: version];

View file

@ -20,10 +20,6 @@
#include <stdlib.h>
#include <stdarg.h>
#ifdef __MINGW32__
# define vsnprintf _vsnprintf
#endif
int
vasprintf(char **cString, const char *format, va_list arguments)
{

View file

@ -1,14 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://webkeks.org/objfw/serialization' version='0'>
<serialization xmlns='https://webkeks.org/objfw/serialization' version='1'>
<OFMutableDictionary>
<key>
<OFArray>
<OFString>Qu&quot;xbar
test</OFString>
<OFNumber type='signed'>1234</OFNumber>
<OFNumber type='double'>0x1.34a456d5cfaadp+10</OFNumber>
<OFNumber type='double'>adfa5c6d454a9340</OFNumber>
<OFMutableString>asd</OFMutableString>
<OFDate>0x1.34a456d5cfaadp+10</OFDate>
<OFDate>adfa5c6d454a9340</OFDate>
</OFArray>
</key>
<object>