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:
parent
2d942ed62c
commit
4f843153b7
6 changed files with 51 additions and 15 deletions
16
src/OFDate.m
16
src/OFDate.m
|
@ -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];
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue