libs-base/Source/StdioStream.m
Andrew McCallum 445444b81f ([StdioStream -readBytes:length:]): Don't assert that we get as many
bytes as we asked for.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1620 72102866-910b-0410-8b05-ffd578937521
1996-05-31 17:34:17 +00:00

278 lines
5.5 KiB
Objective-C

/* Implementation of GNU Objective C stdio stream
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Date: July 1994
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.
*/
#include <gnustep/base/preface.h>
#include <gnustep/base/StdioStream.h>
#include <gnustep/base/Coder.h>
#include <Foundation/NSException.h>
#include <stdarg.h>
/* xxx I should test return values of all functions on the FILE*. */
enum {
STREAM_READONLY = 0,
STREAM_READWRITE,
STREAM_WRITEONLY
};
extern int
o_vscanf (void *stream,
int (*inchar_func)(void*),
void (*unchar_func)(void*,int),
const char *format, va_list argptr);
@implementation StdioStream
+ standardIn
{
static id stdinStream = nil;
if (!stdinStream)
stdinStream = [[self alloc] initWithFilePointer:stdin fmode:"r"];
return stdinStream;
}
+ standardOut
{
static id stdoutStream = nil;
if (!stdoutStream)
stdoutStream = [[self alloc] initWithFilePointer:stdout fmode:"w"];
return stdoutStream;
}
+ standardError
{
static id stderrStream = nil;
if (!stderrStream)
stderrStream = [[self alloc] initWithFilePointer:stderr fmode:"w"];
return stderrStream;
}
+ streamWithFilename: (id <String>)name fmode: (const char *)m
{
return [[[self alloc]
initWithFilename: name fmode: m]
autorelease];
}
- initWithFilePointer: (FILE*)afp fmode: (const char *)mo
{
#if 0
/* xxx Is this portable? I don't think so.
How do I find out if a FILE* is open for reading/writing?
I want to get rid of the "mode" instance variable. */
if (afp->_flag & _IOREAD)
mode = STREAM_READONLY;
else if (afp->_flag & _IOWRT)
mode = STREAM_WRITEONLY;
else
mode = STREAM_READWRITE;
#else
if (!strcmp(mo, "rw"))
mode = STREAM_READWRITE;
else if (*mo == 'r')
mode = STREAM_READONLY;
else if (*mo == 'w')
mode = STREAM_WRITEONLY;
#endif
[super init];
fp = afp;
return self;
}
- initWithFilename: (id <String>)name fmode: (const char *)m
{
FILE *afp = fopen([name cStringNoCopy], (char*)m);
/* xxx Add error checking. */
return [self initWithFilePointer:afp fmode:m];
}
- initWithFileDescriptor: (int)fd fmode: (const char *)m
{
FILE *afp = fdopen(fd, (char*)m);
/* xxx Add error checking. */
return [self initWithFilePointer:afp fmode:m];
}
- initWithPipeTo: (id <String>) systemCommand
{
return [self initWithFilePointer:
popen([systemCommand cStringNoCopy], "w")
fmode:"w"];
}
- initWithPipeFrom: (id <String>) systemCommand
{
return [self initWithFilePointer:
popen([systemCommand cStringNoCopy], "r")
fmode:"r"];
}
- init
{
return [self initWithFilePointer:stdout fmode:"w"];
}
- (int) writeBytes: (const void*)b length: (int)len
{
/* xxx Check error conditions. */
int ret = fwrite (b, 1, len, fp);
if (ret != len)
printf ("Write bytes differ.\n");
assert (ret == len);
return ret;
}
- (int) readBytes: (void*)b length: (int)len
{
/* xxx Check error conditions. */
int ret = fread (b, 1, len, fp);
#if 0 /* No. Sometimes we don't get as much as we asked for, and that ok. */
if (ret != len)
{
printf ("Read bytes differ.\n");
if (feof (fp))
[NSException raise: NSGenericException
format: @"Tried to read from eof"];
}
assert (ret == len);
#endif
return ret;
}
- (int) writeFormat: (id <String>)format, ...
{
int ret;
va_list ap;
va_start(ap, format);
ret = vfprintf(fp, [format cStringNoCopy], ap);
va_end(ap);
return ret;
}
static int
stdio_inchar_func(void *s)
{
return getc((FILE*)s);
}
static void
stdio_unchar_func(void *s, int c)
{
ungetc(c, (FILE*)s);
}
- (int) readFormat: (id <String>)format, ...
{
int ret;
va_list ap;
/* Wow. Why does putting in these nested functions crash the
va_arg stuff in vscanf? */
#if 0
int inchar_func()
{
return getc(fp);
}
void unchar_func(int c)
{
ungetc(c, fp);
}
#endif
va_start(ap, format);
ret = o_vscanf(fp, stdio_inchar_func, stdio_unchar_func,
[format cStringNoCopy], ap);
va_end(ap);
return ret;
}
- (void) flushStream
{
fflush(fp);
}
- (void) close
{
fclose(fp);
}
- (BOOL) isClosed
{
/* xxx How should this be implemented? */
[self notImplemented:_cmd];
return NO;
}
/* xxx Add "- (BOOL) isOpen" method? */
- (void) rewindStream
{
rewind(fp);
}
- (void) setStreamPosition: (unsigned)i
{
fseek(fp, i, 0);
}
- (unsigned) streamPosition
{
return ftell(fp);
}
- (BOOL) isAtEof
{
if (feof(fp))
return YES;
else
return NO;
}
- (BOOL) isWritable
{
if (mode)
return YES;
else
return NO;
}
- (void) dealloc
{
fclose(fp);
[super dealloc];
}
- (void) encodeWithCoder: (Coder*)anEncoder
{
[self notImplemented:_cmd];
}
- initWithCoder: (Coder*)aDecoder
{
[self notImplemented:_cmd];
return self;
}
@end