~ubuntu-branches/ubuntu/hardy/sigscheme/hardy-proposed

« back to all changes in this revision

Viewing changes to src/mbcport.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2006-05-23 21:46:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060523214641-6ix4gz34wpiehub8
Tags: 0.5.0-2
* debian/control (Build-Depends): Added ruby.
  Thanks to Frederik Schueler.  Closes: #368571
* debian/rules (clean): invoke 'distclean' instead of 'clean'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
 *  FileName : mbcport.c
 
3
 *  About    : A ScmCharPort implementation for multibyte character stream
 
4
 *
 
5
 *  Copyright (C) 2005-2006 YamaKen <yamaken AT bp.iij4u.or.jp>
 
6
 *
 
7
 *  All rights reserved.
 
8
 *
 
9
 *  Redistribution and use in source and binary forms, with or without
 
10
 *  modification, are permitted provided that the following conditions
 
11
 *  are met:
 
12
 *
 
13
 *  1. Redistributions of source code must retain the above copyright
 
14
 *     notice, this list of conditions and the following disclaimer.
 
15
 *  2. Redistributions in binary form must reproduce the above copyright
 
16
 *     notice, this list of conditions and the following disclaimer in the
 
17
 *     documentation and/or other materials provided with the distribution.
 
18
 *  3. Neither the name of authors nor the names of its contributors
 
19
 *     may be used to endorse or promote products derived from this software
 
20
 *     without specific prior written permission.
 
21
 *
 
22
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 
23
 *  IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
24
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
25
 *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 
26
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
27
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
28
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
29
 *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
30
 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
31
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
32
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
33
===========================================================================*/
 
34
 
 
35
/*
 
36
 * - This file is intended to be portable. Don't depend on SigScheme.
 
37
 * - To isolate and hide implementation-dependent things, don't merge this file
 
38
 *   into another
 
39
 */
 
40
 
 
41
#include "config.h"
 
42
 
 
43
/*=======================================
 
44
  System Include
 
45
=======================================*/
 
46
#include <stdlib.h>
 
47
#include <stdio.h>
 
48
#include <stdarg.h>
 
49
#include <string.h>
 
50
 
 
51
/*=======================================
 
52
  Local Include
 
53
=======================================*/
 
54
/* To override SCM_{CHAR,BYTE}PORT_ERROR() and SCM_PORT_*ALLOC(). Don't depend
 
55
 * on SigScheme-specific things */
 
56
#include "sigscheme.h"
 
57
#include "sigschemeinternal.h"
 
58
 
 
59
#include "encoding.h"
 
60
#include "baseport.h"
 
61
#include "mbcport.h"
 
62
 
 
63
/*=======================================
 
64
  File Local Macro Definitions
 
65
=======================================*/
 
66
#define HANDLE_MBC_START 0
 
67
 
 
68
#if SCM_USE_STATEFUL_ENCODING
 
69
#define SCM_MBCPORT_CLEAR_STATE(port) (port->state = NULL)
 
70
#else
 
71
#define SCM_MBCPORT_CLEAR_STATE(port)
 
72
#endif
 
73
 
 
74
/*=======================================
 
75
  File Local Type Definitions
 
76
=======================================*/
 
77
struct ScmMultiByteCharPort_ {  /* inherits ScmBaseCharPort */
 
78
    const ScmCharPortVTbl *vptr;
 
79
 
 
80
    ScmBytePort *bport;  /* protected */
 
81
    int linenum;         /* protected */
 
82
 
 
83
    ScmCharCodec *codec;
 
84
    ScmMultibyteState state;
 
85
    scm_byte_t rbuf[SCM_MB_MAX_LEN + sizeof("")];
 
86
};
 
87
 
 
88
/*=======================================
 
89
  File Local Function Declarations
 
90
=======================================*/
 
91
static ScmCharPort *mbcport_dyn_cast(ScmCharPort *cport,
 
92
                                     const ScmCharPortVTbl *dst_vptr);
 
93
static ScmCharCodec *mbcport_codec(ScmMultiByteCharPort *port);
 
94
static char *mbcport_inspect(ScmMultiByteCharPort *port);
 
95
static scm_ichar_t mbcport_get_char(ScmMultiByteCharPort *port);
 
96
static scm_ichar_t mbcport_peek_char(ScmMultiByteCharPort *port);
 
97
static scm_bool mbcport_char_readyp(ScmMultiByteCharPort *port);
 
98
static int mbcport_put_char(ScmMultiByteCharPort *port, scm_ichar_t ch);
 
99
 
 
100
static ScmMultibyteCharInfo mbcport_fill_rbuf(ScmMultiByteCharPort *port,
 
101
                                              scm_bool blockp);
 
102
 
 
103
/*=======================================
 
104
  Variable Declarations
 
105
=======================================*/
 
106
static ScmCharPortVTbl ScmMultiByteCharPort_vtbl;
 
107
const ScmCharPortVTbl *ScmMultiByteCharPort_vptr = &ScmMultiByteCharPort_vtbl;
 
108
 
 
109
/*=======================================
 
110
  Function Implementations
 
111
=======================================*/
 
112
void
 
113
scm_mbcport_init(void)
 
114
{
 
115
    ScmCharPortVTbl *vptr;
 
116
 
 
117
    ScmMultiByteCharPort_vtbl = *ScmBaseCharPort_vptr;
 
118
 
 
119
    vptr = &ScmMultiByteCharPort_vtbl;
 
120
    vptr->dyn_cast    = (ScmCharPortMethod_dyn_cast)&mbcport_dyn_cast;
 
121
    vptr->codec       = (ScmCharPortMethod_codec)&mbcport_codec;
 
122
    vptr->inspect     = (ScmCharPortMethod_inspect)&mbcport_inspect;
 
123
    vptr->get_char    = (ScmCharPortMethod_get_char)&mbcport_get_char;
 
124
    vptr->peek_char   = (ScmCharPortMethod_peek_char)&mbcport_peek_char;
 
125
    vptr->char_readyp = (ScmCharPortMethod_char_readyp)&mbcport_char_readyp;
 
126
    vptr->put_char    = (ScmCharPortMethod_put_char)&mbcport_put_char;
 
127
}
 
128
 
 
129
void
 
130
ScmMultiByteCharPort_construct(ScmMultiByteCharPort *port,
 
131
                               const ScmCharPortVTbl *vptr,
 
132
                               ScmBytePort *bport, ScmCharCodec *codec)
 
133
{
 
134
    ScmBaseCharPort_construct((ScmBaseCharPort *)port, vptr, bport);
 
135
 
 
136
    port->codec = codec;
 
137
    port->rbuf[0] = '\0';
 
138
    SCM_MBCPORT_CLEAR_STATE(port);
 
139
}
 
140
 
 
141
ScmCharPort *
 
142
ScmMultiByteCharPort_new(ScmBytePort *bport, ScmCharCodec *codec)
 
143
{
 
144
    ScmMultiByteCharPort *cport;
 
145
 
 
146
    cport = SCM_PORT_MALLOC(sizeof(ScmMultiByteCharPort));
 
147
    ScmMultiByteCharPort_construct(cport, ScmMultiByteCharPort_vptr,
 
148
                                   bport, codec);
 
149
 
 
150
    return (ScmCharPort *)cport;
 
151
}
 
152
 
 
153
void
 
154
ScmMultiByteCharPort_set_codec(ScmCharPort *cport, ScmCharCodec *codec)
 
155
{
 
156
    ScmMultiByteCharPort *mbcport;
 
157
 
 
158
    mbcport = SCM_BYTEPORT_DYNAMIC_CAST(ScmMultiByteCharPort, cport);
 
159
    mbcport->codec = codec;
 
160
    SCM_MBCPORT_CLEAR_STATE(mbcport);
 
161
    /* only one byte can be preserved for new codec. otherwise cleared */
 
162
    if (1 < strlen((char *)mbcport->rbuf))
 
163
        mbcport->rbuf[0] = '\0';
 
164
}
 
165
 
 
166
static ScmCharPort *
 
167
mbcport_dyn_cast(ScmCharPort *cport, const ScmCharPortVTbl *dst_vptr)
 
168
{
 
169
    return (dst_vptr == ScmBaseCharPort_vptr
 
170
            || dst_vptr == ScmMultiByteCharPort_vptr) ? cport : NULL;
 
171
}
 
172
 
 
173
static ScmCharCodec *
 
174
mbcport_codec(ScmMultiByteCharPort *port)
 
175
{
 
176
    return port->codec;
 
177
}
 
178
 
 
179
static char *
 
180
mbcport_inspect(ScmMultiByteCharPort *port)
 
181
{
 
182
    return ScmBaseCharPort_inspect((ScmBaseCharPort *)port, "mb");
 
183
}
 
184
 
 
185
static scm_ichar_t
 
186
mbcport_get_char(ScmMultiByteCharPort *port)
 
187
{
 
188
    scm_ichar_t ch;
 
189
#if SCM_USE_STATEFUL_ENCODING
 
190
    ScmMultibyteCharInfo mbc;
 
191
    ScmMultibyteState next_state;
 
192
 
 
193
    mbc = mbcport_fill_rbuf(port, scm_true);
 
194
    next_state = SCM_MBCINFO_GET_STATE(mbc);
 
195
#endif
 
196
 
 
197
    ch = mbcport_peek_char(port);
 
198
    port->rbuf[0] = '\0';
 
199
#if SCM_USE_STATEFUL_ENCODING
 
200
    SCM_MBCPORT_SET_STATE(port, next_state)
 
201
#endif
 
202
#if SCM_DEBUG
 
203
    if (ch == SCM_NEWLINE_STR[0])
 
204
        port->linenum++;
 
205
#endif
 
206
 
 
207
    return ch;
 
208
}
 
209
 
 
210
static scm_ichar_t
 
211
mbcport_peek_char(ScmMultiByteCharPort *port)
 
212
{
 
213
    ScmMultibyteCharInfo mbc;
 
214
    size_t size;
 
215
    scm_ichar_t ch;
 
216
 
 
217
    mbc = mbcport_fill_rbuf(port, scm_true);
 
218
    size = SCM_MBCINFO_GET_SIZE(mbc);
 
219
    if (size)
 
220
        ch = SCM_CHARCODEC_STR2INT(port->codec, (char *)port->rbuf, size,
 
221
                                   port->state);
 
222
    else
 
223
        ch = EOF;
 
224
 
 
225
    return ch;
 
226
}
 
227
 
 
228
static scm_bool
 
229
mbcport_char_readyp(ScmMultiByteCharPort *port)
 
230
{
 
231
    ScmMultibyteCharInfo mbc;
 
232
 
 
233
    mbc = mbcport_fill_rbuf(port, scm_false);
 
234
    return !SCM_MBCINFO_INCOMPLETEP(mbc);
 
235
}
 
236
 
 
237
static int
 
238
mbcport_put_char(ScmMultiByteCharPort *port, scm_ichar_t ch)
 
239
{
 
240
    char *end;
 
241
    char wbuf[SCM_MB_MAX_LEN + sizeof("")];
 
242
 
 
243
    /* FIXME: set updated state to port->state */
 
244
    end = SCM_CHARCODEC_INT2STR(port->codec, wbuf, ch, port->state);
 
245
    if (!end)
 
246
        SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: invalid character");
 
247
    return SCM_BYTEPORT_WRITE(port->bport, end - wbuf, wbuf);
 
248
}
 
249
 
 
250
static ScmMultibyteCharInfo
 
251
mbcport_fill_rbuf(ScmMultiByteCharPort *port, scm_bool blockp)
 
252
{
 
253
    scm_byte_t *end;
 
254
    scm_ichar_t byte;
 
255
    ScmMultibyteString mbs;
 
256
    ScmMultibyteCharInfo mbc;
 
257
 
 
258
    end = (scm_byte_t *)strchr((char *)port->rbuf, '\0');
 
259
    SCM_MBS_SET_STATE(mbs, port->state);
 
260
    do {
 
261
        SCM_MBS_SET_STR(mbs, (char *)port->rbuf);
 
262
        SCM_MBS_SET_SIZE(mbs, end - port->rbuf);
 
263
 
 
264
        mbc = SCM_CHARCODEC_SCAN_CHAR(port->codec, mbs);
 
265
 
 
266
        if (SCM_MBCINFO_ERRORP(mbc))
 
267
            SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: broken character");
 
268
        if (!SCM_MBCINFO_INCOMPLETEP(mbc) && SCM_MBCINFO_GET_SIZE(mbc))
 
269
            break;
 
270
        if (SCM_MBS_GET_SIZE(mbs) == SCM_MB_MAX_LEN)
 
271
            SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: broken scanner");
 
272
 
 
273
        byte = SCM_BYTEPORT_GET_BYTE(port->bport);
 
274
        SCM_MBCINFO_SET_STATE(mbc, SCM_MBS_GET_STATE(mbs));
 
275
        if (byte == EOF) {
 
276
            SCM_MBCINFO_INIT(mbc);
 
277
            port->rbuf[0] = '\0';
 
278
#if HANDLE_MBC_START
 
279
            mbc->start = (char *)port->rbuf;
 
280
#endif
 
281
            break;
 
282
        }
 
283
        *end++ = byte;
 
284
        *end = '\0';
 
285
    } while (blockp || SCM_BYTEPORT_BYTE_READYP(port->bport));
 
286
 
 
287
    return mbc;
 
288
}