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:
mccallum 1996-03-29 15:51:13 +00:00
parent 341c38f07f
commit d410dc37bb

View file

@ -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 ? */