1 /*===========================================================================
2  *  Filename : scmport.h
3  *  About    : Abstract base of port implementation
4  *
5  *  Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp>
6  *  Copyright (c) 2007-2008 SigScheme Project <uim-en AT googlegroups.com>
7  *
8  *  All rights reserved.
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *  1. Redistributions of source code must retain the above copyright
15  *     notice, this list of conditions and the following disclaimer.
16  *  2. Redistributions in binary form must reproduce the above copyright
17  *     notice, this list of conditions and the following disclaimer in the
18  *     documentation and/or other materials provided with the distribution.
19  *  3. Neither the name of authors nor the names of its contributors
20  *     may be used to endorse or promote products derived from this software
21  *     without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
24  *  IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
27  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33  *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 ===========================================================================*/
35 
36 /*
37  * This file is intended to be portable. Don't depend on SigScheme and don't
38  * merge into another file.
39  */
40 
41 #ifndef __SCM_SCMPORT_H
42 #define __SCM_SCMPORT_H
43 
44 #include <stddef.h>
45 #if (HAVE_ASSERT_H && !SCM_SOFT_ASSERT)
46 #include <assert.h>
47 #endif
48 
49 #include "scmint.h"
50 #include "global.h"
51 #if SCM_USE_MULTIBYTE_CHAR
52 #include "encoding.h"
53 #else
54 #include "encoding-dummy.h"
55 #endif
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60 
61 /*=======================================
62   Macro Definitions
63 =======================================*/
64 #ifndef SCM_DEBUG_PORT
65 #define SCM_DEBUG_PORT 0
66 #endif
67 
68 #define SCM_ERRMSG_OPEN_PORT      "failed to open port"
69 #define SCM_ERRMSG_CLOSE_PORT     "failed to close port"
70 #define SCM_ERRMSG_READ_FROM_PORT "failed to read from port"
71 #define SCM_ERRMSG_WRITE_TO_PORT  "failed to write to port"
72 
73 #if SCM_SCMPORT_USE_WITH_SIGSCHEME
74 #define SCM_PORT_ASSERT(exp) (SCM_ASSERT(exp))
75 #elif HAVE_ASSERT_H
76 #define SCM_PORT_ASSERT(exp) (assert(exp))
77 #else
78 #define SCM_PORT_ASSERT(exp) SCM_EMPTY_EXPR
79 #endif
80 
81 #define SCM_PORT_ERROR_INVALID_TYPE(klass, port, type)                       \
82     SCM_##klass##PORT_ERROR((port), #type ": invalid object is passed to")
83 #define SCM_PORT_ERROR_INVALID_OPERATION(klass, port, type)                  \
84     SCM_##klass##PORT_ERROR((port), #type ": invalid operation")
85 #define SCM_PORT_ERROR_NOMEM(klass, port, type)                              \
86     SCM_##klass##PORT_ERROR((port), #type ": Out of memory")
87 
88 /*
89  * To allow safe method invocation (includes from subclasses), all non-standard
90  * method must call SCM_PORT_*DYNAMIC_CAST() explicitly.
91  */
92 #define SCM_CHARPORT_DYNAMIC_CAST(type, obj)                                 \
93     (SCM_PORT_DYNAMIC_CAST(CHAR, type, (obj)))
94 #define SCM_BYTEPORT_DYNAMIC_CAST(type, obj)                                 \
95     (SCM_PORT_DYNAMIC_CAST(BYTE, type, (obj)))
96 #define SCM_PORT_DYNAMIC_CAST(klass, type, obj)                              \
97     ((SCM_PORT_TRY_DYNAMIC_CAST(type, (obj))) ?                              \
98      ((type *)(obj)) : (SCM_PORT_ERROR_INVALID_TYPE(klass, (obj), type), NULL))
99 #define SCM_PORT_TRY_DYNAMIC_CAST(type, obj)                                 \
100     ((type *)(*(obj)->vptr->dyn_cast)((obj), type##_vptr))
101 
102 #define SCM_CHARPORT_CLOSE(cport)        ((*(cport)->vptr->close)(cport))
103 #define SCM_CHARPORT_CODEC(cport)        ((*(cport)->vptr->codec)(cport))
104 #if SCM_USE_MULTIBYTE_CHAR
105 #define SCM_CHARPORT_ENCODING(cport)                                         \
106     (SCM_CHARCODEC_ENCODING(SCM_CHARPORT_CODEC(cport)))
107 #define SCM_CHARPORT_CCS(cport)                                              \
108     (SCM_CHARCODEC_CCS(SCM_CHARPORT_CODEC(cport)))
109 #else /* SCM_USE_MULTIBYTE_CHAR */
110 #define SCM_CHARPORT_ENCODING(cport) ("ISO-8859-1")
111 #define SCM_CHARPORT_CCS(cport)      (SCM_CCS_ISO8859_1)
112 #endif /* SCM_USE_MULTIBYTE_CHAR */
113 #define SCM_CHARPORT_INSPECT(cport)      ((*(cport)->vptr->inspect)(cport))
114 #define SCM_CHARPORT_GET_CHAR(cport)     ((*(cport)->vptr->get_char)(cport))
115 #define SCM_CHARPORT_PEEK_CHAR(cport)    ((*(cport)->vptr->peek_char)(cport))
116 #define SCM_CHARPORT_CHAR_READYP(cport)  ((*(cport)->vptr->char_readyp)(cport))
117 #define SCM_CHARPORT_PUTS(cport, str)                                        \
118     ((*(cport)->vptr->puts)((cport), (str)))
119 #define SCM_CHARPORT_PUT_CHAR(cport, ch)                                     \
120     ((*(cport)->vptr->put_char)((cport), (ch)))
121 #define SCM_CHARPORT_FLUSH(cport)        ((*(cport)->vptr->flush)(cport))
122 
123 #define SCM_BYTEPORT_CLOSE(bport)        ((*(bport)->vptr->close)(bport))
124 #define SCM_BYTEPORT_INSPECT(bport)      ((*(bport)->vptr->inspect)(bport))
125 #define SCM_BYTEPORT_GET_BYTE(bport)     ((*(bport)->vptr->get_byte)(bport))
126 #define SCM_BYTEPORT_PEEK_BYTE(bport)    ((*(bport)->vptr->peek_byte)(bport))
127 #define SCM_BYTEPORT_BYTE_READYP(bport)  ((*(bport)->vptr->byte_readyp)(bport))
128 #define SCM_BYTEPORT_PUTS(bport, str)                                        \
129     ((*(bport)->vptr->puts)((bport), (str)))
130 #define SCM_BYTEPORT_WRITE(bport, nbytes, buf)                               \
131     ((*(bport)->vptr->write)((bport), (nbytes), (buf)))
132 #define SCM_BYTEPORT_FLUSH(bport)        ((*(bport)->vptr->flush)(bport))
133 
134 /*=======================================
135   Type Definitions
136 =======================================*/
137 typedef struct ScmCharPortVTbl_ ScmCharPortVTbl;
138 typedef struct ScmCharPort_     ScmCharPort;
139 typedef struct ScmBaseCharPort_ ScmBaseCharPort;
140 typedef struct ScmBytePortVTbl_ ScmBytePortVTbl;
141 typedef struct ScmBytePort_     ScmBytePort;
142 
143 /*
144  * char port
145  */
146 typedef ScmCharPort *(*ScmCharPortMethod_dyn_cast)(ScmCharPort *cport, const ScmCharPortVTbl *dst_vptr);
147 typedef void (*ScmCharPortMethod_close)(ScmCharPort *cport);
148 typedef ScmCharCodec *(*ScmCharPortMethod_codec)(ScmCharPort *cport);
149 /* returns brief information */
150 typedef char *(*ScmCharPortMethod_inspect)(ScmCharPort *cport);
151 
152 /* input */
153 typedef scm_ichar_t (*ScmCharPortMethod_get_char)(ScmCharPort *cport);
154 typedef scm_ichar_t (*ScmCharPortMethod_peek_char)(ScmCharPort *cport);
155 typedef scm_bool    (*ScmCharPortMethod_char_readyp)(ScmCharPort *cport);
156 
157 /* output */
158 typedef void (*ScmCharPortMethod_puts)(ScmCharPort *cport, const char *str);
159 typedef void (*ScmCharPortMethod_put_char)(ScmCharPort *cport, scm_ichar_t ch);
160 typedef void (*ScmCharPortMethod_flush)(ScmCharPort *cport);
161 
162 struct ScmCharPortVTbl_ {
163     ScmCharPortMethod_dyn_cast    dyn_cast;
164     ScmCharPortMethod_close       close;
165     ScmCharPortMethod_codec       codec;
166     ScmCharPortMethod_inspect     inspect;
167     ScmCharPortMethod_get_char    get_char;
168     ScmCharPortMethod_peek_char   peek_char;
169     ScmCharPortMethod_char_readyp char_readyp;
170     ScmCharPortMethod_puts        puts;
171     ScmCharPortMethod_put_char    put_char;
172     ScmCharPortMethod_flush       flush;
173 };
174 
175 struct ScmCharPort_ {
176     const ScmCharPortVTbl *vptr;
177 };
178 
179 struct ScmBaseCharPort_ {  /* inherits ScmCharPort */
180     const ScmCharPortVTbl *vptr;
181 
182     ScmBytePort *bport;  /* protected */
183     size_t linenum;      /* protected */
184 };
185 
186 /*
187  * byte port
188  */
189 typedef ScmBytePort *(*ScmBytePortMethod_dyn_cast)(ScmBytePort *bport, const ScmBytePortVTbl *dst_vptr);
190 typedef void (*ScmBytePortMethod_close)(ScmBytePort *bport);
191 /* returns brief information */
192 typedef char *(*ScmBytePortMethod_inspect)(ScmBytePort *bport);
193 
194 /* input */
195 typedef scm_ichar_t (*ScmBytePortMethod_get_byte)(ScmBytePort *bport);
196 typedef scm_ichar_t (*ScmBytePortMethod_peek_byte)(ScmBytePort *bport);
197 typedef scm_bool    (*ScmBytePortMethod_byte_readyp)(ScmBytePort *bport);
198 
199 /* output */
200 typedef void (*ScmBytePortMethod_puts)(ScmBytePort *bport, const char *str);
201 typedef void (*ScmBytePortMethod_write)(ScmBytePort *bport,
202                                         size_t nbytes, const char *buf);
203 typedef void (*ScmBytePortMethod_flush)(ScmBytePort *bport);
204 
205 struct ScmBytePortVTbl_ {
206     ScmBytePortMethod_dyn_cast    dyn_cast;
207     ScmBytePortMethod_close       close;
208     ScmBytePortMethod_inspect     inspect;
209     ScmBytePortMethod_get_byte    get_byte;
210     ScmBytePortMethod_peek_byte   peek_byte;
211     ScmBytePortMethod_byte_readyp byte_readyp;
212     ScmBytePortMethod_puts        puts;
213     ScmBytePortMethod_write       write;
214     ScmBytePortMethod_flush       flush;
215 };
216 
217 struct ScmBytePort_ {
218     const ScmBytePortVTbl *vptr;
219 };
220 
221 /*=======================================
222   Variable Declarations
223 =======================================*/
224 SCM_EXTERN(const ScmCharPortVTbl *const ScmBaseCharPort_vptr);
225 
226 /*=======================================
227   Function Declarations
228 =======================================*/
229 SCM_EXPORT void ScmBaseCharPort_construct(ScmBaseCharPort *port,
230                                           const ScmCharPortVTbl *vptr,
231                                           ScmBytePort *bport);
232 SCM_EXPORT char *ScmBaseCharPort_inspect(ScmBaseCharPort *port,
233                                          const char *header);
234 SCM_EXPORT size_t ScmBaseCharPort_line_number(ScmBaseCharPort *port);
235 
236 
237 #ifdef __cplusplus
238 }
239 #endif
240 
241 #endif /* __SCM_SCMPORT_H */
242