mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 00:30:53 +00:00
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:
parent
587f433be2
commit
54f8625a2a
1 changed files with 146 additions and 143 deletions
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue