mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-03 13:21:00 +00:00
Include <math.h>
(FLOAT_FACTOR): New macro. (WRITE_SIGNED_TYPE): Take new first argument, the pointer for the data. (READ_SIGNED_TYPE): Likewise. (WRITE_UNSIGNED_TYPE): Likewise. (READ_UNSIGNED_TYPE): Likewise. ([BinaryCStream -encodeValueOfCType:at:withName:]): [_C_FLT]: Use new scheme, based on frexp() to turn a float into a series of ints. [_C_DBL]: Likewise. ([BinaryCStream -decodeValueOfCType:at:withName:]): [_C_FLT]: Likewise to match. [_C_DBL]: Likewise. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1286 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
341c38f07f
commit
d410dc37bb
1 changed files with 89 additions and 51 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include <objects/TextCStream.h>
|
#include <objects/TextCStream.h>
|
||||||
#include <objects/MallocAddress.h>
|
#include <objects/MallocAddress.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define DEFAULT_FORMAT_VERSION 0
|
#define DEFAULT_FORMAT_VERSION 0
|
||||||
|
|
||||||
|
@ -35,8 +36,15 @@
|
||||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||||
__a*((__v+__a-1)/__a); })
|
__a*((__v+__a-1)/__a); })
|
||||||
|
|
||||||
|
/* The number of bytes used to encode the length of a _C_CHARPTR
|
||||||
|
string that is encoded. */
|
||||||
#define NUM_BYTES_STRING_LENGTH 4
|
#define NUM_BYTES_STRING_LENGTH 4
|
||||||
|
|
||||||
|
/* The value by which we multiply a float or double in order to bring
|
||||||
|
mantissa digits to the left-hand-side of the decimal point, so that
|
||||||
|
we can extra them by assigning the float or double to an int. */
|
||||||
|
#define FLOAT_FACTOR ((double)(1 << ((sizeof(int)*BITSPERBYTE)-2)))
|
||||||
|
|
||||||
@implementation BinaryCStream
|
@implementation BinaryCStream
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
|
@ -90,23 +98,23 @@ static BOOL debug_binary_coder;
|
||||||
|
|
||||||
[stream writeByte: *type];
|
[stream writeByte: *type];
|
||||||
|
|
||||||
#define WRITE_SIGNED_TYPE(_TYPE, CONV_FUNC) \
|
#define WRITE_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||||
{ \
|
{ \
|
||||||
char buffer[1+sizeof(_TYPE)]; \
|
char buffer[1+sizeof(_TYPE)]; \
|
||||||
buffer[0] = sizeof (_TYPE); \
|
buffer[0] = sizeof (_TYPE); \
|
||||||
if (*(_TYPE*)d < 0) \
|
if (*(_TYPE*)_PTR < 0) \
|
||||||
{ \
|
{ \
|
||||||
buffer[0] |= 0x80; \
|
buffer[0] |= 0x80; \
|
||||||
*(_TYPE*)(buffer+1) = CONV_FUNC (- *(_TYPE*)d); \
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
*(_TYPE*)(buffer+1) = CONV_FUNC (*(_TYPE*)d); \
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||||
} \
|
} \
|
||||||
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
|
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_SIGNED_TYPE(_TYPE, CONV_FUNC) \
|
#define READ_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||||
{ \
|
{ \
|
||||||
char sign, size; \
|
char sign, size; \
|
||||||
[stream readByte: &size]; \
|
[stream readByte: &size]; \
|
||||||
|
@ -118,24 +126,24 @@ static BOOL debug_binary_coder;
|
||||||
read_size = [stream readBytes: buffer length: size]; \
|
read_size = [stream readBytes: buffer length: size]; \
|
||||||
assert (read_size == size); \
|
assert (read_size == size); \
|
||||||
assert (size == sizeof(_TYPE)); \
|
assert (size == sizeof(_TYPE)); \
|
||||||
*(unsigned _TYPE*)d = \
|
*(unsigned _TYPE*)_PTR = \
|
||||||
CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||||
if (sign) \
|
if (sign) \
|
||||||
*(_TYPE*)d = - *(_TYPE*)d; \
|
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reading and writing unsigned scalar types. */
|
/* Reading and writing unsigned scalar types. */
|
||||||
|
|
||||||
#define WRITE_UNSIGNED_TYPE(_TYPE, CONV_FUNC) \
|
#define WRITE_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||||
{ \
|
{ \
|
||||||
char buffer[1+sizeof(_TYPE)]; \
|
char buffer[1+sizeof(_TYPE)]; \
|
||||||
buffer[0] = sizeof (_TYPE); \
|
buffer[0] = sizeof (_TYPE); \
|
||||||
*(_TYPE*)(buffer+1) = CONV_FUNC (*(_TYPE*)d); \
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||||
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
|
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_UNSIGNED_TYPE(_TYPE, CONV_FUNC) \
|
#define READ_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||||
{ \
|
{ \
|
||||||
char size; \
|
char size; \
|
||||||
[stream readByte: &size]; \
|
[stream readByte: &size]; \
|
||||||
|
@ -145,8 +153,8 @@ static BOOL debug_binary_coder;
|
||||||
read_size = [stream readBytes: buffer length: size]; \
|
read_size = [stream readBytes: buffer length: size]; \
|
||||||
assert (read_size == size); \
|
assert (read_size == size); \
|
||||||
assert (size == sizeof(_TYPE)); \
|
assert (size == sizeof(_TYPE)); \
|
||||||
*(_TYPE*)d = \
|
*(_TYPE*)_PTR = \
|
||||||
CONV_FUNC (*(_TYPE*)buffer); \
|
_CONV_FUNC (*(_TYPE*)buffer); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,47 +180,67 @@ static BOOL debug_binary_coder;
|
||||||
/* Reading and writing signed scalar types. */
|
/* Reading and writing signed scalar types. */
|
||||||
|
|
||||||
case _C_SHT:
|
case _C_SHT:
|
||||||
WRITE_SIGNED_TYPE (short, htons);
|
WRITE_SIGNED_TYPE (d, short, htons);
|
||||||
break;
|
break;
|
||||||
case _C_USHT:
|
case _C_USHT:
|
||||||
WRITE_UNSIGNED_TYPE (unsigned short, htons);
|
WRITE_UNSIGNED_TYPE (d, unsigned short, htons);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_INT:
|
case _C_INT:
|
||||||
WRITE_SIGNED_TYPE (int, htonl);
|
WRITE_SIGNED_TYPE (d, int, htonl);
|
||||||
break;
|
break;
|
||||||
case _C_UINT:
|
case _C_UINT:
|
||||||
WRITE_UNSIGNED_TYPE (unsigned int, htonl);
|
WRITE_UNSIGNED_TYPE (d, unsigned int, htonl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG:
|
case _C_LNG:
|
||||||
WRITE_SIGNED_TYPE (long, htonl);
|
WRITE_SIGNED_TYPE (d, long, htonl);
|
||||||
break;
|
break;
|
||||||
case _C_ULNG:
|
case _C_ULNG:
|
||||||
WRITE_UNSIGNED_TYPE (unsigned long, htonl);
|
WRITE_UNSIGNED_TYPE (d, unsigned long, htonl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Two quickie kludges to make archiving of floats and doubles work */
|
/* xxx The handling of floats and doubles could be improved.
|
||||||
|
e.g. I should account for varying sizeof(int) vs sizeof(double). */
|
||||||
|
|
||||||
case _C_FLT:
|
case _C_FLT:
|
||||||
{
|
{
|
||||||
char buf[64];
|
volatile double value;
|
||||||
char *s = buf;
|
int exp, mantissa;
|
||||||
sprintf(buf, "%f", *(float*)d);
|
value = *(float*)d;
|
||||||
[self encodeValueOfCType: @encode(char*)
|
/* Get the exponent */
|
||||||
at: &s
|
value = frexp (value, &exp);
|
||||||
withName: @"BinaryCStream float"];
|
/* Get the mantissa. */
|
||||||
|
value *= FLOAT_FACTOR;
|
||||||
|
mantissa = value;
|
||||||
|
assert (value - mantissa == 0);
|
||||||
|
/* Encode the value as its two integer components. */
|
||||||
|
WRITE_SIGNED_TYPE (&exp, int, htonl);
|
||||||
|
WRITE_SIGNED_TYPE (&mantissa, int, htonl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _C_DBL:
|
case _C_DBL:
|
||||||
{
|
{
|
||||||
char buf[64];
|
volatile double value;
|
||||||
char *s = buf;
|
int exp, mantissa1, mantissa2;
|
||||||
sprintf(buf, "%f", *(double*)d);
|
value = *(double*)d;
|
||||||
[self encodeValueOfCType: @encode(char*)
|
/* Get the exponent */
|
||||||
at: &s
|
value = frexp (value, &exp);
|
||||||
withName: @"BinaryCStream double"];
|
/* Get the first part of the mantissa. */
|
||||||
|
value *= FLOAT_FACTOR;
|
||||||
|
mantissa1 = value;
|
||||||
|
value -= mantissa1;
|
||||||
|
value *= FLOAT_FACTOR;
|
||||||
|
mantissa2 = value;
|
||||||
|
assert (value - mantissa2 == 0);
|
||||||
|
/* Encode the value as its three integer components. */
|
||||||
|
WRITE_SIGNED_TYPE (&exp, int, htonl);
|
||||||
|
WRITE_SIGNED_TYPE (&mantissa1, int, htonl);
|
||||||
|
WRITE_SIGNED_TYPE (&mantissa2, int, htonl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
{
|
{
|
||||||
int len = atoi (type+1); /* xxx why +1 ? */
|
int len = atoi (type+1); /* xxx why +1 ? */
|
||||||
|
@ -307,47 +335,57 @@ static BOOL debug_binary_coder;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_SHT:
|
case _C_SHT:
|
||||||
READ_SIGNED_TYPE (short, ntohs);
|
READ_SIGNED_TYPE (d, short, ntohs);
|
||||||
break;
|
break;
|
||||||
case _C_USHT:
|
case _C_USHT:
|
||||||
READ_UNSIGNED_TYPE (unsigned short, ntohs);
|
READ_UNSIGNED_TYPE (d, unsigned short, ntohs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_INT:
|
case _C_INT:
|
||||||
READ_SIGNED_TYPE (int, ntohl);
|
READ_SIGNED_TYPE (d, int, ntohl);
|
||||||
break;
|
break;
|
||||||
case _C_UINT:
|
case _C_UINT:
|
||||||
READ_UNSIGNED_TYPE (unsigned int, ntohl);
|
READ_UNSIGNED_TYPE (d, unsigned int, ntohl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG:
|
case _C_LNG:
|
||||||
READ_SIGNED_TYPE (long, ntohl);
|
READ_SIGNED_TYPE (d, long, ntohl);
|
||||||
break;
|
break;
|
||||||
case _C_ULNG:
|
case _C_ULNG:
|
||||||
READ_UNSIGNED_TYPE (unsigned long, ntohl);
|
READ_UNSIGNED_TYPE (d, unsigned long, ntohl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Two quickie kludges to make archiving of floats and doubles work */
|
|
||||||
case _C_FLT:
|
case _C_FLT:
|
||||||
{
|
{
|
||||||
char *buf;
|
int exp, mantissa;
|
||||||
[self decodeValueOfCType:@encode(char*) at:&buf withName:NULL];
|
double value;
|
||||||
if (sscanf(buf, "%f", (float*)d) != 1)
|
/* Decode the exponent and mantissa. */
|
||||||
[NSException raise: NSGenericException
|
READ_SIGNED_TYPE (&exp, int, ntohl);
|
||||||
format: @"expected float, got %s", buf];
|
READ_SIGNED_TYPE (&mantissa, int, ntohl);
|
||||||
(*objc_free)(buf);
|
/* Assemble them into a double */
|
||||||
|
value = mantissa / FLOAT_FACTOR;
|
||||||
|
value = ldexp (value, exp);
|
||||||
|
/* Put the double into the requested memory location as a float */
|
||||||
|
*(float*)d = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _C_DBL:
|
case _C_DBL:
|
||||||
{
|
{
|
||||||
char *buf;
|
int exp, mantissa1, mantissa2;
|
||||||
[self decodeValueOfCType:@encode(char*) at:&buf withName:NULL];
|
double value;
|
||||||
if (sscanf(buf, "%lf", (double*)d) != 1)
|
/* Decode the exponent and the two pieces of the mantissa. */
|
||||||
[NSException raise: NSGenericException
|
READ_SIGNED_TYPE (&exp, int, ntohl);
|
||||||
format: @"expected double, got %s", buf];
|
READ_SIGNED_TYPE (&mantissa1, int, ntohl);
|
||||||
(*objc_free)(buf);
|
READ_SIGNED_TYPE (&mantissa2, int, ntohl);
|
||||||
|
/* Assemble them into a double */
|
||||||
|
value = ((mantissa2 / FLOAT_FACTOR) + mantissa2) / FLOAT_FACTOR;
|
||||||
|
value = ldexp (value, exp);
|
||||||
|
/* Put the double into the requested memory location. */
|
||||||
|
*(double*)d = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
{
|
{
|
||||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||||
|
|
Loading…
Reference in a new issue