1
/*===========================================================================
2
* Filename : scmport-file.c
3
* About : A ScmBytePort implementation for file stream of the standard C
6
* Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp>
7
* Copyright (c) 2007 SigScheme Project <uim AT freedesktop.org>
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
15
* 1. Redistributions of source code must retain the above copyright
16
* notice, this list of conditions and the following disclaimer.
17
* 2. Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
20
* 3. Neither the name of authors nor the names of its contributors
21
* may be used to endorse or promote products derived from this software
22
* without specific prior written permission.
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
25
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
28
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
===========================================================================*/
38
* - This file is intended to be portable. Don't depend on SigScheme.
39
* - To isolate and hide implementation-dependent things, don't merge this file
50
#include "scmport-config.h"
52
#include "scmport-file.h"
54
/*=======================================
55
File Local Macro Definitions
56
=======================================*/
59
/*=======================================
60
File Local Type Definitions
61
=======================================*/
62
typedef struct ScmFilePort_ ScmFilePort;
64
struct ScmFilePort_ { /* inherits ScmBytePort */
65
const ScmBytePortVTbl *vptr;
68
char *aux_info; /* human readable auxilialy information about the file */
69
scm_bool ownership; /* whether close the file at fileport_close() */
72
/*=======================================
73
File Local Function Declarations
74
=======================================*/
75
static ScmBytePort *fileport_new_internal(FILE *file, const char *aux_info,
77
static ScmBytePort *fileport_open_internal(const char *path, const char *mode);
78
static scm_ichar_t fixup_read_char(FILE *f, int c);
80
static ScmBytePort *fileport_dyn_cast(ScmBytePort *bport,
81
const ScmBytePortVTbl *dest_vptr);
82
static void fileport_close(ScmFilePort *bport);
83
static char *fileport_inspect(ScmFilePort *port);
84
static scm_ichar_t fileport_get_byte(ScmFilePort *bport);
85
static scm_ichar_t fileport_peek_byte(ScmFilePort *bport);
86
static scm_bool fileport_byte_readyp(ScmFilePort *bport);
87
static void fileport_puts(ScmFilePort *bport, const char *str);
88
static void fileport_write(ScmFilePort *bport, size_t nbytes, const char *buf);
89
static void fileport_flush(ScmFilePort *bport);
91
/*=======================================
93
=======================================*/
94
static const ScmBytePortVTbl ScmFilePort_vtbl = {
95
(ScmBytePortMethod_dyn_cast) &fileport_dyn_cast,
96
(ScmBytePortMethod_close) &fileport_close,
97
(ScmBytePortMethod_inspect) &fileport_inspect,
98
(ScmBytePortMethod_get_byte) &fileport_get_byte,
99
(ScmBytePortMethod_peek_byte) &fileport_peek_byte,
100
(ScmBytePortMethod_byte_readyp)&fileport_byte_readyp,
101
(ScmBytePortMethod_puts) &fileport_puts,
102
(ScmBytePortMethod_write) &fileport_write,
103
(ScmBytePortMethod_flush) &fileport_flush
105
SCM_EXPORT const ScmBytePortVTbl *const ScmFilePort_vptr = &ScmFilePort_vtbl;
107
/*=======================================
109
=======================================*/
112
* Client code must call this first even if current implementation does not
113
* contain actual code.
116
scm_fileport_init(void)
121
fileport_new_internal(FILE *file, const char *aux_info, scm_bool ownership)
125
SCM_PORT_ASSERT(file);
126
SCM_PORT_ASSERT(aux_info);
128
port = SCM_PORT_MALLOC(sizeof(ScmFilePort));
130
port->vptr = ScmFilePort_vptr;
132
port->aux_info = SCM_PORT_STRDUP(aux_info);
133
port->ownership = ownership;
135
return (ScmBytePort *)port;
138
SCM_EXPORT ScmBytePort *
139
ScmFilePort_new(FILE *file, const char *aux_info)
141
return fileport_new_internal(file, aux_info, scm_true);
144
SCM_EXPORT ScmBytePort *
145
ScmFilePort_new_shared(FILE *file, const char *aux_info)
147
return fileport_new_internal(file, aux_info, scm_false);
151
fileport_open_internal(const char *path, const char *mode)
155
file = fopen(path, mode);
156
/* FIXME: Raise error by SCM_BYTEPORT_ERROR(). Returning NULL as error
157
* indicator is a temporary solution to display filename to user. */
159
return (file) ? ScmFilePort_new(file, path) : NULL;
162
SCM_BYTEPORT_ERROR(NULL, SCM_ERRMSG_OPEN_PORT);
163
return ScmFilePort_new(file, path);
167
SCM_EXPORT ScmBytePort *
168
ScmFilePort_open_input_file(const char *path)
170
return fileport_open_internal(path, "rb");
173
SCM_EXPORT ScmBytePort *
174
ScmFilePort_open_output_file(const char *path)
176
return fileport_open_internal(path, "wb");
180
fileport_dyn_cast(ScmBytePort *bport, const ScmBytePortVTbl *dst_vptr)
182
return (dst_vptr == ScmFilePort_vptr) ? bport : NULL;
186
fileport_close(ScmFilePort *port)
190
ret = (port->ownership) ? fclose(port->file) : OK;
191
free(port->aux_info);
194
SCM_BYTEPORT_ERROR(NULL, SCM_ERRMSG_CLOSE_PORT);
198
fileport_inspect(ScmFilePort *port)
203
if (port->aux_info) {
204
size = sizeof("file ") + strlen(port->aux_info);
205
combined = SCM_PORT_MALLOC(size);
206
sprintf(combined, "file %s", port->aux_info);
209
return SCM_PORT_STRDUP("file");
214
fixup_read_char(FILE *f, int c)
219
SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_READ_FROM_PORT);
221
return SCM_ICHAR_EOF;
224
return (scm_ichar_t)c;
228
fileport_get_byte(ScmFilePort *port)
232
c = fgetc(port->file);
233
return fixup_read_char(port->file, c);
237
fileport_peek_byte(ScmFilePort *port)
242
ic = fileport_get_byte(port);
243
if (ic != SCM_ICHAR_EOF) {
244
c = ungetc(ic, port->file);
245
ic = fixup_read_char(port->file, c);
252
fileport_byte_readyp(ScmFilePort *port)
254
/* FIXME: does not support a FILE based on a pipe, or opened by
257
if (fileno(port->file) >= 0)
258
SCM_BYTEPORT_ERROR(port, "known bug: ready? operation is not supported on this port");
264
fileport_puts(ScmFilePort *port, const char *str)
268
ret = fputs(str, port->file);
270
SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);
274
fileport_write(ScmFilePort *port, size_t nbytes, const char *buf)
278
written_objs = fwrite(buf, sizeof(char), nbytes, port->file);
279
if (written_objs != nbytes)
280
SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);
284
fileport_flush(ScmFilePort *port)
288
ret = fflush(port->file);
290
SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);