1996-01-24 14:09:55 +00:00
|
|
|
|
/* Implementation of GNU Objective-C binary stream object for use serializing
|
|
|
|
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
|
|
|
|
|
1996-04-17 20:17:45 +00:00
|
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
1996-01-24 14:09:55 +00:00
|
|
|
|
Written: Jan 1996
|
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
1996-04-17 15:34:35 +00:00
|
|
|
|
#include <gnustep/base/preface.h>
|
1996-04-17 15:23:00 +00:00
|
|
|
|
#include <gnustep/base/BinaryCStream.h>
|
|
|
|
|
#include <gnustep/base/NSString.h>
|
|
|
|
|
#include <gnustep/base/StdioStream.h>
|
|
|
|
|
#include <gnustep/base/TextCStream.h>
|
|
|
|
|
#include <gnustep/base/MallocAddress.h>
|
1996-03-26 20:59:42 +00:00
|
|
|
|
#include <Foundation/NSException.h>
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#include <math.h>
|
1996-05-27 14:26:41 +00:00
|
|
|
|
#ifndef WIN32
|
1996-05-10 13:55:35 +00:00
|
|
|
|
#include <values.h> // This gets BITSPERBYTE on Solaris
|
1996-05-13 15:39:21 +00:00
|
|
|
|
#include <netinet/in.h> // for byte-conversion
|
1996-05-27 14:26:41 +00:00
|
|
|
|
#endif /* !WIN32 */
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
#define DEFAULT_FORMAT_VERSION 0
|
|
|
|
|
|
1996-01-27 00:54:11 +00:00
|
|
|
|
#define ROUND(V, A) \
|
|
|
|
|
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
|
|
|
|
__a*((__v+__a-1)/__a); })
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* The number of bytes used to encode the length of a _C_CHARPTR
|
|
|
|
|
string that is encoded. */
|
1996-03-22 00:31:09 +00:00
|
|
|
|
#define NUM_BYTES_STRING_LENGTH 4
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* 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. */
|
1996-05-08 14:53:02 +00:00
|
|
|
|
#if !defined(BITSPERBYTE) && defined(NeXT)
|
|
|
|
|
#include <mach/vm_param.h>
|
|
|
|
|
#define BITSPERBYTE BYTE_SIZE
|
|
|
|
|
#endif
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#define FLOAT_FACTOR ((double)(1 << ((sizeof(int)*BITSPERBYTE)-2)))
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
@implementation BinaryCStream
|
|
|
|
|
|
1996-03-22 00:31:09 +00:00
|
|
|
|
+ (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);
|
|
|
|
|
}
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
/* For debugging */
|
|
|
|
|
|
1996-04-14 00:59:58 +00:00
|
|
|
|
static int debug_binary_coder = 0;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
+ setDebugging: (BOOL)f
|
|
|
|
|
{
|
|
|
|
|
debug_binary_coder = f;
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ debugStderrCoder
|
|
|
|
|
{
|
|
|
|
|
static id c = nil;
|
|
|
|
|
|
|
|
|
|
if (!c)
|
|
|
|
|
c = [[TextCStream alloc]
|
|
|
|
|
initForWritingToStream: [StdioStream standardError]];
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Encoding/decoding C values */
|
|
|
|
|
|
|
|
|
|
- (void) encodeValueOfCType: (const char*)type
|
|
|
|
|
at: (const void*)d
|
|
|
|
|
withName: (id <String>) name
|
|
|
|
|
{
|
1996-03-22 00:31:09 +00:00
|
|
|
|
/* Make sure we're not being asked to encode an "ObjC" type. */
|
|
|
|
|
assert(type);
|
|
|
|
|
assert(*type != '@');
|
|
|
|
|
assert(*type != '^');
|
|
|
|
|
assert(*type != ':');
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
if (debug_binary_coder)
|
|
|
|
|
{
|
|
|
|
|
[[[self class] debugStderrCoder]
|
1996-03-22 00:31:09 +00:00
|
|
|
|
encodeValueOfCType: type
|
|
|
|
|
at: d
|
|
|
|
|
withName: name];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-03-22 00:31:09 +00:00
|
|
|
|
[stream writeByte: *type];
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#define WRITE_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
{ \
|
|
|
|
|
char buffer[1+sizeof(_TYPE)]; \
|
|
|
|
|
buffer[0] = sizeof (_TYPE); \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
if (*(_TYPE*)_PTR < 0) \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
{ \
|
|
|
|
|
buffer[0] |= 0x80; \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
} \
|
|
|
|
|
else \
|
|
|
|
|
{ \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (*(_TYPE*)_PTR); \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
} \
|
|
|
|
|
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
|
|
|
|
|
}
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#define READ_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
{ \
|
|
|
|
|
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)); \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(unsigned _TYPE*)_PTR = \
|
|
|
|
|
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
if (sign) \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
} \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reading and writing unsigned scalar types. */
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#define WRITE_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
{ \
|
|
|
|
|
char buffer[1+sizeof(_TYPE)]; \
|
|
|
|
|
buffer[0] = sizeof (_TYPE); \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(_TYPE*)(buffer+1) = _CONV_FUNC (*(_TYPE*)_PTR); \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
|
|
|
|
|
}
|
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
#define READ_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
{ \
|
|
|
|
|
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)); \
|
1996-03-29 15:51:13 +00:00
|
|
|
|
*(_TYPE*)_PTR = \
|
|
|
|
|
_CONV_FUNC (*(_TYPE*)buffer); \
|
1996-03-22 00:31:09 +00:00
|
|
|
|
} \
|
|
|
|
|
}
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
switch (*type)
|
|
|
|
|
{
|
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
{
|
1996-03-22 00:31:09 +00:00
|
|
|
|
unsigned length = strlen (*(char**)d);
|
1996-03-22 02:36:22 +00:00
|
|
|
|
unsigned nlength;
|
|
|
|
|
nlength = htonl (length);
|
|
|
|
|
[stream writeBytes: &nlength
|
1996-03-22 00:31:09 +00:00
|
|
|
|
length: NUM_BYTES_STRING_LENGTH];
|
|
|
|
|
[stream writeBytes: *(char**)d
|
|
|
|
|
length: length];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
1996-03-22 00:31:09 +00:00
|
|
|
|
[stream writeByte: *(unsigned char*)d];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1996-03-22 00:31:09 +00:00
|
|
|
|
/* Reading and writing signed scalar types. */
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_SHT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (d, short, htons);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_USHT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_UNSIGNED_TYPE (d, unsigned short, htons);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
case _C_INT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (d, int, htonl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_UINT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_UNSIGNED_TYPE (d, unsigned int, htonl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
case _C_LNG:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (d, long, htonl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_ULNG:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_UNSIGNED_TYPE (d, unsigned long, htonl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* xxx The handling of floats and doubles could be improved.
|
|
|
|
|
e.g. I should account for varying sizeof(int) vs sizeof(double). */
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
1996-03-29 15:51:13 +00:00
|
|
|
|
volatile double value;
|
1996-03-30 00:50:30 +00:00
|
|
|
|
int exponent, mantissa;
|
|
|
|
|
short exponent_encoded;
|
1996-03-29 15:51:13 +00:00
|
|
|
|
value = *(float*)d;
|
|
|
|
|
/* Get the exponent */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
value = frexp (value, &exponent);
|
|
|
|
|
exponent_encoded = exponent;
|
|
|
|
|
NSParameterAssert (exponent_encoded == exponent);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* Get the mantissa. */
|
|
|
|
|
value *= FLOAT_FACTOR;
|
|
|
|
|
mantissa = value;
|
|
|
|
|
assert (value - mantissa == 0);
|
|
|
|
|
/* Encode the value as its two integer components. */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (&exponent_encoded, short, htons);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (&mantissa, int, htonl);
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1996-03-29 15:51:13 +00:00
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
1996-03-29 15:51:13 +00:00
|
|
|
|
volatile double value;
|
1996-03-30 00:50:30 +00:00
|
|
|
|
int exponent, mantissa1, mantissa2;
|
|
|
|
|
short exponent_encoded;
|
1996-03-29 15:51:13 +00:00
|
|
|
|
value = *(double*)d;
|
|
|
|
|
/* Get the exponent */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
value = frexp (value, &exponent);
|
|
|
|
|
exponent_encoded = exponent;
|
|
|
|
|
NSParameterAssert (exponent_encoded == exponent);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* 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. */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (&exponent_encoded, short, htons);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
WRITE_SIGNED_TYPE (&mantissa1, int, htonl);
|
|
|
|
|
WRITE_SIGNED_TYPE (&mantissa2, int, htonl);
|
1996-01-27 00:54:11 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1996-03-29 15:51:13 +00:00
|
|
|
|
|
1996-01-27 00:54:11 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
int len = atoi (type+1); /* xxx why +1 ? */
|
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
|
|
while (isdigit(*++type));
|
|
|
|
|
offset = objc_sizeof_type(type);
|
|
|
|
|
[self encodeName:name];
|
|
|
|
|
[self encodeIndent];
|
|
|
|
|
while (len-- > 0)
|
|
|
|
|
{
|
|
|
|
|
/* Change this so we don't re-write type info every time. */
|
1996-03-22 00:31:09 +00:00
|
|
|
|
/* xxx We should be able to encode arrays "ObjC" types also! */
|
1996-01-27 00:54:11 +00:00
|
|
|
|
[self encodeValueOfCType:type
|
|
|
|
|
at:d
|
|
|
|
|
withName:@"array component"];
|
|
|
|
|
((char*)d) += offset;
|
|
|
|
|
}
|
|
|
|
|
[self encodeUnindent];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
|
|
|
|
int acc_size = 0;
|
|
|
|
|
int align;
|
|
|
|
|
|
|
|
|
|
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
|
|
|
|
[self encodeName:name];
|
|
|
|
|
[self encodeIndent];
|
|
|
|
|
while (*type != _C_STRUCT_E)
|
|
|
|
|
{
|
|
|
|
|
align = objc_alignof_type (type); /* pad to alignment */
|
|
|
|
|
acc_size = ROUND (acc_size, align);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
/* xxx We should be able to encode structs "ObjC" types also! */
|
1996-01-27 00:54:11 +00:00
|
|
|
|
[self encodeValueOfCType:type
|
|
|
|
|
at:((char*)d)+acc_size
|
|
|
|
|
withName:@"structure component"];
|
|
|
|
|
acc_size += objc_sizeof_type (type); /* add component size */
|
|
|
|
|
type = objc_skip_typespec (type); /* skip component */
|
|
|
|
|
}
|
|
|
|
|
[self encodeUnindent];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
1996-03-26 19:23:09 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Unrecognized type %s", type];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) decodeValueOfCType: (const char*)type
|
|
|
|
|
at: (void*)d
|
|
|
|
|
withName: (id <String> *)namePtr
|
|
|
|
|
{
|
|
|
|
|
char encoded_type;
|
|
|
|
|
|
|
|
|
|
assert(type);
|
|
|
|
|
assert(*type != '@');
|
|
|
|
|
assert(*type != '^');
|
|
|
|
|
assert(*type != ':');
|
|
|
|
|
|
1996-03-22 00:31:09 +00:00
|
|
|
|
[stream readByte: &encoded_type];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
if (encoded_type != *type
|
|
|
|
|
&& !((encoded_type=='c' || encoded_type=='C')
|
|
|
|
|
&& (*type=='c' || *type=='C')))
|
1996-03-26 19:23:09 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
1996-03-26 20:59:42 +00:00
|
|
|
|
format: @"Expected type \"%c\", got type \"%c\"",
|
1996-03-26 19:23:09 +00:00
|
|
|
|
*type, encoded_type];
|
1996-03-22 00:31:09 +00:00
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
switch (encoded_type)
|
|
|
|
|
{
|
|
|
|
|
case _C_CHARPTR:
|
|
|
|
|
{
|
1996-03-22 00:31:09 +00:00
|
|
|
|
unsigned length;
|
|
|
|
|
unsigned read_count;
|
|
|
|
|
read_count = [stream readBytes: &length
|
|
|
|
|
length: NUM_BYTES_STRING_LENGTH];
|
|
|
|
|
assert (read_count == NUM_BYTES_STRING_LENGTH);
|
|
|
|
|
length = ntohl (length);
|
|
|
|
|
OBJC_MALLOC (*(char**)d, char, length+1);
|
|
|
|
|
read_count = [stream readBytes: *(char**)d
|
|
|
|
|
length: length];
|
|
|
|
|
assert (read_count == length);
|
1996-01-24 14:09:55 +00:00
|
|
|
|
(*(char**)d)[length] = '\0';
|
1996-03-29 17:53:05 +00:00
|
|
|
|
/* Autorelease the newly malloc'ed pointer? Grep for (*objc_free)
|
|
|
|
|
to see the places the may have to be changed
|
|
|
|
|
[MallocAddress autoreleaseMallocAddress: *(char**)d]; */
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case _C_CHR:
|
|
|
|
|
case _C_UCHR:
|
1996-03-22 00:31:09 +00:00
|
|
|
|
[stream readByte: (unsigned char*)d];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case _C_SHT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_SIGNED_TYPE (d, short, ntohs);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_USHT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_UNSIGNED_TYPE (d, unsigned short, ntohs);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
case _C_INT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_SIGNED_TYPE (d, int, ntohl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_UINT:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_UNSIGNED_TYPE (d, unsigned int, ntohl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
case _C_LNG:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_SIGNED_TYPE (d, long, ntohl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_ULNG:
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_UNSIGNED_TYPE (d, unsigned long, ntohl);
|
1996-03-22 00:31:09 +00:00
|
|
|
|
break;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
|
|
|
|
|
case _C_FLT:
|
|
|
|
|
{
|
1996-03-30 00:50:30 +00:00
|
|
|
|
short exponent;
|
|
|
|
|
int mantissa;
|
1996-03-29 15:51:13 +00:00
|
|
|
|
double value;
|
|
|
|
|
/* Decode the exponent and mantissa. */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
READ_SIGNED_TYPE (&exponent, short, ntohs);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_SIGNED_TYPE (&mantissa, int, ntohl);
|
|
|
|
|
/* Assemble them into a double */
|
|
|
|
|
value = mantissa / FLOAT_FACTOR;
|
1996-03-30 00:50:30 +00:00
|
|
|
|
value = ldexp (value, exponent);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* Put the double into the requested memory location as a float */
|
|
|
|
|
*(float*)d = value;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1996-03-29 15:51:13 +00:00
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
case _C_DBL:
|
|
|
|
|
{
|
1996-03-30 00:50:30 +00:00
|
|
|
|
short exponent;
|
|
|
|
|
int mantissa1, mantissa2;
|
1996-03-29 17:53:05 +00:00
|
|
|
|
volatile double value;
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* Decode the exponent and the two pieces of the mantissa. */
|
1996-03-30 00:50:30 +00:00
|
|
|
|
READ_SIGNED_TYPE (&exponent, short, ntohs);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
READ_SIGNED_TYPE (&mantissa1, int, ntohl);
|
|
|
|
|
READ_SIGNED_TYPE (&mantissa2, int, ntohl);
|
|
|
|
|
/* Assemble them into a double */
|
1996-03-29 17:53:05 +00:00
|
|
|
|
value = ((mantissa2 / FLOAT_FACTOR) + mantissa1) / FLOAT_FACTOR;
|
1996-03-30 00:50:30 +00:00
|
|
|
|
value = ldexp (value, exponent);
|
1996-03-29 15:51:13 +00:00
|
|
|
|
/* Put the double into the requested memory location. */
|
|
|
|
|
*(double*)d = value;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1996-03-29 15:51:13 +00:00
|
|
|
|
|
1996-01-27 00:54:11 +00:00
|
|
|
|
case _C_ARY_B:
|
|
|
|
|
{
|
|
|
|
|
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
|
|
|
|
int len = atoi(type+1);
|
|
|
|
|
int offset;
|
|
|
|
|
[self decodeName:namePtr];
|
|
|
|
|
[self decodeIndent];
|
|
|
|
|
while (isdigit(*++type));
|
|
|
|
|
offset = objc_sizeof_type(type);
|
|
|
|
|
while (len-- > 0)
|
|
|
|
|
{
|
|
|
|
|
[self decodeValueOfCType:type
|
|
|
|
|
at:d
|
|
|
|
|
withName:namePtr];
|
|
|
|
|
((char*)d) += offset;
|
|
|
|
|
}
|
|
|
|
|
[self decodeUnindent];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case _C_STRUCT_B:
|
|
|
|
|
{
|
|
|
|
|
/* xxx Do we need to allocate space just like char* ? No. */
|
|
|
|
|
int acc_size = 0;
|
|
|
|
|
int align;
|
1996-02-22 15:13:13 +00:00
|
|
|
|
const char *save_type = type;
|
1996-01-27 00:54:11 +00:00
|
|
|
|
|
|
|
|
|
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
|
|
|
|
[self decodeName:namePtr];
|
|
|
|
|
[self decodeIndent]; /* xxx insert [self decodeName:] */
|
|
|
|
|
while (*type != _C_STRUCT_E)
|
|
|
|
|
{
|
|
|
|
|
align = objc_alignof_type (type); /* pad to alignment */
|
|
|
|
|
acc_size = ROUND (acc_size, align);
|
|
|
|
|
[self decodeValueOfCType:type
|
|
|
|
|
at:((char*)d)+acc_size
|
|
|
|
|
withName:namePtr];
|
|
|
|
|
acc_size += objc_sizeof_type (type); /* add component size */
|
|
|
|
|
type = objc_skip_typespec (type); /* skip component */
|
|
|
|
|
}
|
|
|
|
|
type = save_type;
|
|
|
|
|
[self decodeUnindent];
|
|
|
|
|
break;
|
|
|
|
|
}
|
1996-01-24 14:09:55 +00:00
|
|
|
|
default:
|
1996-03-26 19:23:09 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"Unrecognized Type %s", type];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debug_binary_coder)
|
|
|
|
|
{
|
|
|
|
|
[[[self class] debugStderrCoder]
|
|
|
|
|
encodeValueOfCType:type
|
|
|
|
|
at:d
|
|
|
|
|
withName:@"decoding unnamed"];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Returning default format version. */
|
|
|
|
|
|
|
|
|
|
+ (int) defaultFormatVersion
|
|
|
|
|
{
|
|
|
|
|
return DEFAULT_FORMAT_VERSION;
|
|
|
|
|
}
|
|
|
|
|
|
1996-03-22 00:31:09 +00:00
|
|
|
|
|
|
|
|
|
/* Encoding and decoding names. */
|
|
|
|
|
|
|
|
|
|
- (void) encodeName: (id <String>) name
|
|
|
|
|
{
|
|
|
|
|
if (debug_binary_coder)
|
|
|
|
|
[[[self class] debugStderrCoder]
|
|
|
|
|
encodeName:name];
|
|
|
|
|
}
|
|
|
|
|
|
1996-01-24 14:09:55 +00:00
|
|
|
|
- (void) decodeName: (id <String> *)n
|
|
|
|
|
{
|
|
|
|
|
#if 1
|
1996-01-26 20:34:42 +00:00
|
|
|
|
if (n)
|
|
|
|
|
*n = nil;
|
1996-01-24 14:09:55 +00:00
|
|
|
|
#else
|
1996-01-26 20:34:42 +00:00
|
|
|
|
if (n)
|
|
|
|
|
*n = [[[NSString alloc] init] autorelease];
|
1996-01-24 14:09:55 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|