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/MallocAddress.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <math.h>
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
|
@ -35,8 +36,15 @@
|
|||
({ typeof(V) __v=(V); typeof(A) __a=(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
|
||||
|
||||
/* 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
|
||||
|
||||
+ (void) initialize
|
||||
|
@ -90,23 +98,23 @@ static BOOL debug_binary_coder;
|
|||
|
||||
[stream writeByte: *type];
|
||||
|
||||
#define WRITE_SIGNED_TYPE(_TYPE, CONV_FUNC) \
|
||||
#define WRITE_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char buffer[1+sizeof(_TYPE)]; \
|
||||
buffer[0] = sizeof (_TYPE); \
|
||||
if (*(_TYPE*)d < 0) \
|
||||
if (*(_TYPE*)_PTR < 0) \
|
||||
{ \
|
||||
buffer[0] |= 0x80; \
|
||||
*(_TYPE*)(buffer+1) = CONV_FUNC (- *(_TYPE*)d); \
|
||||
*(_TYPE*)(buffer+1) = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*(_TYPE*)(buffer+1) = CONV_FUNC (*(_TYPE*)d); \
|
||||
*(_TYPE*)(buffer+1) = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
} \
|
||||
[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; \
|
||||
[stream readByte: &size]; \
|
||||
|
@ -118,24 +126,24 @@ static BOOL debug_binary_coder;
|
|||
read_size = [stream readBytes: buffer length: size]; \
|
||||
assert (read_size == size); \
|
||||
assert (size == sizeof(_TYPE)); \
|
||||
*(unsigned _TYPE*)d = \
|
||||
CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
if (sign) \
|
||||
*(_TYPE*)d = - *(_TYPE*)d; \
|
||||
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 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)]; \
|
||||
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))]; \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE(_TYPE, CONV_FUNC) \
|
||||
#define READ_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char size; \
|
||||
[stream readByte: &size]; \
|
||||
|
@ -145,8 +153,8 @@ static BOOL debug_binary_coder;
|
|||
read_size = [stream readBytes: buffer length: size]; \
|
||||
assert (read_size == size); \
|
||||
assert (size == sizeof(_TYPE)); \
|
||||
*(_TYPE*)d = \
|
||||
CONV_FUNC (*(_TYPE*)buffer); \
|
||||
*(_TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(_TYPE*)buffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -172,47 +180,67 @@ static BOOL debug_binary_coder;
|
|||
/* Reading and writing signed scalar types. */
|
||||
|
||||
case _C_SHT:
|
||||
WRITE_SIGNED_TYPE (short, htons);
|
||||
WRITE_SIGNED_TYPE (d, short, htons);
|
||||
break;
|
||||
case _C_USHT:
|
||||
WRITE_UNSIGNED_TYPE (unsigned short, htons);
|
||||
WRITE_UNSIGNED_TYPE (d, unsigned short, htons);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
WRITE_SIGNED_TYPE (int, htonl);
|
||||
WRITE_SIGNED_TYPE (d, int, htonl);
|
||||
break;
|
||||
case _C_UINT:
|
||||
WRITE_UNSIGNED_TYPE (unsigned int, htonl);
|
||||
WRITE_UNSIGNED_TYPE (d, unsigned int, htonl);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
WRITE_SIGNED_TYPE (long, htonl);
|
||||
WRITE_SIGNED_TYPE (d, long, htonl);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
WRITE_UNSIGNED_TYPE (unsigned long, htonl);
|
||||
WRITE_UNSIGNED_TYPE (d, unsigned long, htonl);
|
||||
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:
|
||||
{
|
||||
char buf[64];
|
||||
char *s = buf;
|
||||
sprintf(buf, "%f", *(float*)d);
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &s
|
||||
withName: @"BinaryCStream float"];
|
||||
volatile double value;
|
||||
int exp, mantissa;
|
||||
value = *(float*)d;
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exp);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
char buf[64];
|
||||
char *s = buf;
|
||||
sprintf(buf, "%f", *(double*)d);
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &s
|
||||
withName: @"BinaryCStream double"];
|
||||
volatile double value;
|
||||
int exp, mantissa1, mantissa2;
|
||||
value = *(double*)d;
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exp);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
|
@ -307,47 +335,57 @@ static BOOL debug_binary_coder;
|
|||
break;
|
||||
|
||||
case _C_SHT:
|
||||
READ_SIGNED_TYPE (short, ntohs);
|
||||
READ_SIGNED_TYPE (d, short, ntohs);
|
||||
break;
|
||||
case _C_USHT:
|
||||
READ_UNSIGNED_TYPE (unsigned short, ntohs);
|
||||
READ_UNSIGNED_TYPE (d, unsigned short, ntohs);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
READ_SIGNED_TYPE (int, ntohl);
|
||||
READ_SIGNED_TYPE (d, int, ntohl);
|
||||
break;
|
||||
case _C_UINT:
|
||||
READ_UNSIGNED_TYPE (unsigned int, ntohl);
|
||||
READ_UNSIGNED_TYPE (d, unsigned int, ntohl);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
READ_SIGNED_TYPE (long, ntohl);
|
||||
READ_SIGNED_TYPE (d, long, ntohl);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
READ_UNSIGNED_TYPE (unsigned long, ntohl);
|
||||
READ_UNSIGNED_TYPE (d, unsigned long, ntohl);
|
||||
break;
|
||||
|
||||
/* Two quickie kludges to make archiving of floats and doubles work */
|
||||
case _C_FLT:
|
||||
{
|
||||
char *buf;
|
||||
[self decodeValueOfCType:@encode(char*) at:&buf withName:NULL];
|
||||
if (sscanf(buf, "%f", (float*)d) != 1)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"expected float, got %s", buf];
|
||||
(*objc_free)(buf);
|
||||
int exp, mantissa;
|
||||
double value;
|
||||
/* Decode the exponent and mantissa. */
|
||||
READ_SIGNED_TYPE (&exp, int, ntohl);
|
||||
READ_SIGNED_TYPE (&mantissa, int, ntohl);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
char *buf;
|
||||
[self decodeValueOfCType:@encode(char*) at:&buf withName:NULL];
|
||||
if (sscanf(buf, "%lf", (double*)d) != 1)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"expected double, got %s", buf];
|
||||
(*objc_free)(buf);
|
||||
int exp, mantissa1, mantissa2;
|
||||
double value;
|
||||
/* Decode the exponent and the two pieces of the mantissa. */
|
||||
READ_SIGNED_TYPE (&exp, int, ntohl);
|
||||
READ_SIGNED_TYPE (&mantissa1, int, ntohl);
|
||||
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;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
|
|
Loading…
Reference in a new issue