Overhauled to use htonl() and friends. New format is incompatible

with the old.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1237 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
mccallum 1996-03-22 00:31:09 +00:00
parent 587f433be2
commit 54f8625a2a

View file

@ -33,8 +33,17 @@
({ 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); })
#define NUM_BYTES_STRING_LENGTH 4
@implementation BinaryCStream @implementation BinaryCStream
+ (void) initialize
{
if (self == [BinaryCStream class])
/* Make sure that we don't overrun memory when reading _C_CHARPTR. */
assert (sizeof(unsigned) >= NUM_BYTES_STRING_LENGTH);
}
/* For debugging */ /* For debugging */
@ -56,14 +65,6 @@ static BOOL debug_binary_coder;
return c; return c;
} }
- (void) encodeName: (id <String>) name
{
if (debug_binary_coder)
[[[self class] debugStderrCoder]
encodeName:name];
}
/* Encoding/decoding C values */ /* Encoding/decoding C values */
@ -71,99 +72,122 @@ static BOOL debug_binary_coder;
at: (const void*)d at: (const void*)d
withName: (id <String>) name withName: (id <String>) name
{ {
unsigned char size; /* Make sure we're not being asked to encode an "ObjC" type. */
if (debug_binary_coder)
{
[[[self class] debugStderrCoder]
encodeValueOfCType:type
at:d
withName:name];
}
assert(type); assert(type);
assert(*type != '@'); assert(*type != '@');
assert(*type != '^'); assert(*type != '^');
assert(*type != ':'); assert(*type != ':');
/* A fairly stupid, inefficient binary encoding. This could use if (debug_binary_coder)
some improvement. For instance, we could compress the sign {
information and the type information. [[[self class] debugStderrCoder]
It could probably also use some portability fixes. */ encodeValueOfCType: type
[stream writeByte:*type]; at: d
size = objc_sizeof_type(type); withName: name];
[stream writeByte:size]; }
[stream writeByte: *type];
#define WRITE_SIGNED_TYPE(_TYPE, CONV_FUNC) \
{ \
char buffer[1+sizeof(_TYPE)]; \
buffer[0] = sizeof (_TYPE); \
if (*(_TYPE*)d < 0) \
{ \
buffer[0] |= 0x80; \
*(_TYPE*)(buffer+1) = CONV_FUNC (- *(_TYPE*)d); \
} \
else \
{ \
*(_TYPE*)(buffer+1) = CONV_FUNC (*(_TYPE*)d); \
} \
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
}
#define READ_SIGNED_TYPE(_TYPE, CONV_FUNC) \
{ \
char sign, size; \
[stream readByte: &size]; \
sign = size & 0x80; \
size &= ~0x80; \
{ \
char buffer[size]; \
int read_size; \
read_size = [stream readBytes: buffer length: size]; \
assert (read_size == size); \
assert (size == sizeof(_TYPE)); \
*(unsigned _TYPE*)d = \
CONV_FUNC (*(unsigned _TYPE*)buffer); \
if (sign) \
*(_TYPE*)d = - *(_TYPE*)d; \
} \
}
/* Reading and writing unsigned scalar types. */
#define WRITE_UNSIGNED_TYPE(_TYPE, CONV_FUNC) \
{ \
char buffer[1+sizeof(_TYPE)]; \
buffer[0] = sizeof (_TYPE); \
*(_TYPE*)(buffer+1) = CONV_FUNC (*(_TYPE*)d); \
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
}
#define READ_UNSIGNED_TYPE(_TYPE, CONV_FUNC) \
{ \
char size; \
[stream readByte: &size]; \
{ \
char buffer[size]; \
int read_size; \
read_size = [stream readBytes: buffer length: size]; \
assert (read_size == size); \
assert (size == sizeof(_TYPE)); \
*(_TYPE*)d = \
CONV_FUNC (*(_TYPE*)buffer); \
} \
}
switch (*type) switch (*type)
{ {
case _C_CHARPTR: case _C_CHARPTR:
{ {
int length = strlen(*(char**)d); unsigned length = strlen (*(char**)d);
[self encodeValueOfCType:@encode(int) length = htonl (length);
at:&length withName:@"BinaryCStream char* length"]; [stream writeBytes: &length
[stream writeBytes:*(char**)d length:length]; length: NUM_BYTES_STRING_LENGTH];
[stream writeBytes: *(char**)d
length: length];
break; break;
} }
case _C_CHR: case _C_CHR:
#ifndef __CHAR_UNSIGNED__
if (*(char*)d < 0)
[stream writeByte:1];
else
#endif
[stream writeByte:0];
case _C_UCHR: case _C_UCHR:
[stream writeByte:*(unsigned char*)d]; [stream writeByte: *(unsigned char*)d];
break; break;
/* Reading and writing signed scalar types. */
case _C_SHT: case _C_SHT:
if (*(short*)d < 0) WRITE_SIGNED_TYPE (short, htons);
[stream writeByte:1]; break;
else
[stream writeByte:0];
case _C_USHT: case _C_USHT:
{ WRITE_UNSIGNED_TYPE (unsigned short, htons);
unsigned char *buf = alloca(size); break;
short s = *(short*)d;
int count = size;
if (s < 0) s = -s;
for (; count--; s >>= 8)
buf[count] = (char) (s % 0x100);
[stream writeBytes:buf length:size];
break;
}
case _C_INT: case _C_INT:
if (*(int*)d < 0) WRITE_SIGNED_TYPE (int, htonl);
[stream writeByte:1]; break;
else
[stream writeByte:0];
case _C_UINT: case _C_UINT:
{ WRITE_UNSIGNED_TYPE (unsigned int, htonl);
unsigned char *buf = alloca(size); break;
int s = *(int*)d;
int count = size;
if (s < 0) s = -s;
for (; count--; s >>= 8)
buf[count] = (char) (s % 0x100);
[stream writeBytes:buf length:size];
break;
}
case _C_LNG: case _C_LNG:
if (*(long*)d < 0) WRITE_SIGNED_TYPE (long, htonl);
[stream writeByte:1]; break;
else
[stream writeByte:0];
case _C_ULNG: case _C_ULNG:
{ WRITE_UNSIGNED_TYPE (unsigned long, htonl);
unsigned char *buf = alloca(size); break;
long s = *(long*)d;
int count = size;
if (s < 0) s = -s;
for (; count--; s >>= 8)
buf[count] = (char) (s % 0x100);
[stream writeBytes:buf length:size];
break;
}
/* Two quickie kludges to make archiving of floats and doubles work */ /* Two quickie kludges to make archiving of floats and doubles work */
case _C_FLT: case _C_FLT:
@ -171,17 +195,19 @@ static BOOL debug_binary_coder;
char buf[64]; char buf[64];
char *s = buf; char *s = buf;
sprintf(buf, "%f", *(float*)d); sprintf(buf, "%f", *(float*)d);
[self encodeValueOfCType:@encode(char*) [self encodeValueOfCType: @encode(char*)
at:&s withName:@"BinaryCStream float"]; at: &s
withName: @"BinaryCStream float"];
break; break;
} }
case _C_DBL: case _C_DBL:
{ {
char buf[64]; char buf[64];
char *s = buf; char *s = buf;
sprintf(buf, "%f", *(double*)d); sprintf(buf, "%lf", *(double*)d);
[self encodeValueOfCType:@encode(char*) [self encodeValueOfCType: @encode(char*)
at:&s withName:@"BinaryCStream double"]; at: &s
withName: @"BinaryCStream double"];
break; break;
} }
case _C_ARY_B: case _C_ARY_B:
@ -196,6 +222,7 @@ static BOOL debug_binary_coder;
while (len-- > 0) while (len-- > 0)
{ {
/* Change this so we don't re-write type info every time. */ /* Change this so we don't re-write type info every time. */
/* xxx We should be able to encode arrays "ObjC" types also! */
[self encodeValueOfCType:type [self encodeValueOfCType:type
at:d at:d
withName:@"array component"]; withName:@"array component"];
@ -216,6 +243,7 @@ static BOOL debug_binary_coder;
{ {
align = objc_alignof_type (type); /* pad to alignment */ align = objc_alignof_type (type); /* pad to alignment */
acc_size = ROUND (acc_size, align); acc_size = ROUND (acc_size, align);
/* xxx We should be able to encode structs "ObjC" types also! */
[self encodeValueOfCType:type [self encodeValueOfCType:type
at:((char*)d)+acc_size at:((char*)d)+acc_size
withName:@"structure component"]; withName:@"structure component"];
@ -235,97 +263,62 @@ static BOOL debug_binary_coder;
withName: (id <String> *)namePtr withName: (id <String> *)namePtr
{ {
char encoded_type; char encoded_type;
unsigned char encoded_size;
unsigned char encoded_sign = 0;
assert(type); assert(type);
assert(*type != '@'); assert(*type != '@');
assert(*type != '^'); assert(*type != '^');
assert(*type != ':'); assert(*type != ':');
[stream readByte:&encoded_type]; [stream readByte: &encoded_type];
if (encoded_type != *type if (encoded_type != *type
&& !((encoded_type=='c' || encoded_type=='C') && !((encoded_type=='c' || encoded_type=='C')
&& (*type=='c' || *type=='C'))) && (*type=='c' || *type=='C')))
[self error:"Expected type \"%c\", got type \"%c\"", *type, encoded_type]; [self error:"Expected type \"%c\", got type \"%c\"", *type, encoded_type];
[stream readByte:&encoded_size];
switch (encoded_type) switch (encoded_type)
{ {
case _C_CHARPTR: case _C_CHARPTR:
{ {
int length; unsigned length;
[self decodeValueOfCType:@encode(int) unsigned read_count;
at:&length withName:NULL]; read_count = [stream readBytes: &length
OBJC_MALLOC(*(char**)d, char, length+1); length: NUM_BYTES_STRING_LENGTH];
[stream readBytes:*(char**)d length:length]; assert (read_count == NUM_BYTES_STRING_LENGTH);
length = ntohl (length);
/* xxx Maybe I should make this alloca() instead of malloc(). */
OBJC_MALLOC (*(char**)d, char, length+1);
read_count = [stream readBytes: *(char**)d
length: length];
assert (read_count == length);
(*(char**)d)[length] = '\0'; (*(char**)d)[length] = '\0';
break; break;
} }
case _C_CHR: case _C_CHR:
[stream readByte:&encoded_sign];
case _C_UCHR: case _C_UCHR:
[stream readByte:(unsigned char*)d]; [stream readByte: (unsigned char*)d];
if (encoded_sign)
*(char*)d = *(char*)d * -1;
break; break;
case _C_SHT: case _C_SHT:
[stream readByte:&encoded_sign]; READ_SIGNED_TYPE (short, ntohs);
break;
case _C_USHT: case _C_USHT:
{ READ_UNSIGNED_TYPE (unsigned short, ntohs);
unsigned char *buf = alloca(encoded_size); break;
int i;
short s = 0;
[stream readBytes:buf length:encoded_size];
for (i = 0; i < sizeof(short); i++)
{
s <<= 8;
s += buf[i];
}
if (encoded_sign)
s = -s;
*(short*)d = s;
break;
}
case _C_INT: case _C_INT:
[stream readByte:&encoded_sign]; READ_SIGNED_TYPE (int, ntohl);
break;
case _C_UINT: case _C_UINT:
{ READ_UNSIGNED_TYPE (unsigned int, ntohl);
unsigned char *buf = alloca(encoded_size); break;
int i;
int s = 0;
[stream readBytes:buf length:encoded_size];
for (i = 0; i < sizeof(int); i++)
{
s <<= 8;
s += buf[i];
}
if (encoded_sign)
s = -s;
*(int*)d = s;
break;
}
case _C_LNG: case _C_LNG:
[stream readByte:&encoded_sign]; READ_SIGNED_TYPE (long, ntohl);
break;
case _C_ULNG: case _C_ULNG:
{ READ_UNSIGNED_TYPE (unsigned long, ntohl);
unsigned char *buf = alloca(encoded_size); break;
int i;
long s = 0;
[stream readBytes:buf length:encoded_size];
for (i = 0; i < sizeof(long); i++)
{
s <<= 8;
s += buf[i];
}
if (encoded_sign)
s = -s;
*(long*)d = s;
break;
}
/* Two quickie kludges to make archiving of floats and doubles work */ /* Two quickie kludges to make archiving of floats and doubles work */
case _C_FLT: case _C_FLT:
@ -410,6 +403,16 @@ static BOOL debug_binary_coder;
return DEFAULT_FORMAT_VERSION; return DEFAULT_FORMAT_VERSION;
} }
/* Encoding and decoding names. */
- (void) encodeName: (id <String>) name
{
if (debug_binary_coder)
[[[self class] debugStderrCoder]
encodeName:name];
}
- (void) decodeName: (id <String> *)n - (void) decodeName: (id <String> *)n
{ {
#if 1 #if 1