libs-base/Source/RawCStream.m
Andrew McCallum 168f431ba9 Change "Gnustep" to "GNUstep"
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1521 72102866-910b-0410-8b05-ffd578937521
1996-05-12 00:56:10 +00:00

289 lines
6.3 KiB
Objective-C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Implementation of GNU Objective-C raw-binary stream for archiving
Copyright (C) 1996 Free Software Foundation, Inc.
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Written: Jan 1996
This file is part of the GNUstep Base Library.
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.
*/
/* Use this CStream subclass when you are encoding/decoding on the
same architecture, and you care about time and space.
WARNING: This encoding is *not* machine-independent. */
#include <gnustep/base/preface.h>
#include <gnustep/base/RawCStream.h>
#include <gnustep/base/NSString.h>
#include <gnustep/base/StdioStream.h>
#include <gnustep/base/TextCStream.h>
#define DEFAULT_FORMAT_VERSION 0
#define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \
__a*((__v+__a-1)/__a); })
@implementation RawCStream
/* For debugging */
static BOOL debug_binary_coder;
+ setDebugging: (BOOL)f
{
debug_binary_coder = f;
return self;
}
+ debugStderrCoder
{
static id c = nil;
if (!c)
c = [[TextCStream alloc]
initForWritingToStream: [StdioStream standardError]];
return c;
}
- (void) encodeName: (id <String>) name
{
if (debug_binary_coder)
[[[self class] debugStderrCoder]
encodeName:name];
}
/* Encoding/decoding C values */
- (void) encodeValueOfCType: (const char*)type
at: (const void*)d
withName: (id <String>) name
{
if (debug_binary_coder)
{
[[[self class] debugStderrCoder]
encodeValueOfCType:type
at:d
withName:name];
}
assert(type);
assert(*type != '@');
assert(*type != '^');
assert(*type != ':');
switch (*type)
{
case _C_CHARPTR:
{
int length = strlen(*(char**)d);
[self encodeValueOfCType:@encode(int)
at:&length withName:@"BinaryCStream char* length"];
[stream writeBytes:*(char**)d length:length];
break;
}
case _C_CHR:
case _C_UCHR:
[stream writeByte:*(unsigned char*)d];
break;
case _C_SHT:
case _C_USHT:
[stream writeBytes:d length:sizeof(short)];
break;
case _C_INT:
case _C_UINT:
[stream writeBytes:d length:sizeof(int)];
break;
case _C_LNG:
case _C_ULNG:
[stream writeBytes:d length:sizeof(long)];
break;
case _C_FLT:
[stream writeBytes:d length:sizeof(float)];
break;
case _C_DBL:
[stream writeBytes:d length:sizeof(double)];
break;
case _C_ARY_B:
{
int len = atoi (type+1); /* xxx why +1 ? */
int offset;
while (isdigit(*++type));
offset = objc_sizeof_type(type);
while (len-- > 0)
{
/* Change this so we don't re-write type info every time. */
[self encodeValueOfCType: type
at: d
withName: NULL];
((char*)d) += offset;
}
break;
}
case _C_STRUCT_B:
{
int acc_size = 0;
int align;
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
while (*type != _C_STRUCT_E)
{
align = objc_alignof_type (type); /* pad to alignment */
acc_size = ROUND (acc_size, align);
[self encodeValueOfCType: type
at: ((char*)d)+acc_size
withName: NULL];
acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */
}
break;
}
default:
[self error:"Unrecognized Type %s", type];
}
}
- (void) decodeValueOfCType: (const char*)type
at: (void*)d
withName: (id <String> *)namePtr
{
assert(type);
assert(*type != '@');
assert(*type != '^');
assert(*type != ':');
switch (*type)
{
case _C_CHARPTR:
{
int length;
[self decodeValueOfCType:@encode(int)
at:&length withName:NULL];
OBJC_MALLOC(*(char**)d, char, length+1);
[stream readBytes:*(char**)d length:length];
(*(char**)d)[length] = '\0';
break;
}
case _C_CHR:
case _C_UCHR:
[stream readByte:d];
break;
case _C_SHT:
case _C_USHT:
[stream readBytes:d length:sizeof(short)];
break;
case _C_INT:
case _C_UINT:
[stream readBytes:d length:sizeof(int)];
break;
case _C_LNG:
case _C_ULNG:
[stream readBytes:d length:sizeof(long)];
break;
case _C_FLT:
[stream readBytes:d length:sizeof(float)];
break;
case _C_DBL:
[stream readBytes:d length:sizeof(double)];
break;
case _C_ARY_B:
{
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
int len = atoi(type+1);
int offset;
while (isdigit(*++type));
offset = objc_sizeof_type(type);
while (len-- > 0)
{
[self decodeValueOfCType:type
at:d
withName:namePtr];
((char*)d) += offset;
}
break;
}
case _C_STRUCT_B:
{
/* xxx Do we need to allocate space just like char* ? No. */
int acc_size = 0;
int align;
const char *save_type = type;
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
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;
break;
}
default:
[self error:"Unrecognized Type %s", type];
}
if (debug_binary_coder)
{
[[[self class] debugStderrCoder]
encodeValueOfCType:type
at:d
withName:@"decoding unnamed"];
}
}
/* Returning default format version. */
+ (int) defaultFormatVersion
{
return DEFAULT_FORMAT_VERSION;
}
- (void) decodeName: (id <String> *)n
{
#if 1
if (n)
*n = nil;
#else
if (n)
*n = [[[NSString alloc] init] autorelease];
#endif
}
@end