~ubuntu-branches/ubuntu/hardy/uim/hardy

« back to all changes in this revision

Viewing changes to sigscheme/src/scmport-mbchar.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2007-04-21 03:46:09 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070421034609-gpcurkutp8vaysqj
Tags: 1:1.4.1-3
* Switch to dh_gtkmodules for the gtk 2.10 transition (Closes:
  #419318)
  - debian/control: Add ${misc:Depends} and remove libgtk2.0-bin on
    uim-gtk2.0.
  - debian/uim-gtk2.0.post{inst,rm}: Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
 *  Filename : scmport-mbchar.c
 
3
 *  About    : A ScmCharPort implementation for multibyte character stream
 
4
 *
 
5
 *  Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp>
 
6
 *  Copyright (c) 2007 SigScheme Project <uim AT freedesktop.org>
 
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.
 
38
 * - To isolate and hide implementation-dependent things, don't merge this file
 
39
 *   into another
 
40
 */
 
41
 
 
42
#include <config.h>
 
43
 
 
44
#include <stdlib.h>
 
45
#include <stdio.h>
 
46
#include <string.h>
 
47
 
 
48
#include "scmint.h"
 
49
#include "encoding.h"
 
50
#include "scmport-config.h"
 
51
#include "scmport.h"
 
52
#include "scmport-mbchar.h"
 
53
 
 
54
/*=======================================
 
55
  File Local Macro Definitions
 
56
=======================================*/
 
57
#define HANDLE_MBC_START 0
 
58
 
 
59
#if SCM_USE_STATEFUL_ENCODING
 
60
#define SCM_MBCPORT_CLEAR_STATE(port) (port->state = NULL)
 
61
#else
 
62
#define SCM_MBCPORT_CLEAR_STATE(port) SCM_EMPTY_EXPR
 
63
#endif
 
64
 
 
65
/*=======================================
 
66
  File Local Type Definitions
 
67
=======================================*/
 
68
struct ScmMultiByteCharPort_ {  /* inherits ScmBaseCharPort */
 
69
    const ScmCharPortVTbl *vptr;
 
70
 
 
71
    ScmBytePort *bport;  /* protected */
 
72
    size_t linenum;      /* protected */
 
73
 
 
74
    ScmCharCodec *codec;
 
75
    ScmMultibyteState state;
 
76
    scm_byte_t rbuf[SCM_MB_CHAR_BUF_SIZE];
 
77
};
 
78
 
 
79
/*=======================================
 
80
  File Local Function Declarations
 
81
=======================================*/
 
82
static ScmCharPort *mbcport_dyn_cast(ScmCharPort *cport,
 
83
                                     const ScmCharPortVTbl *dst_vptr);
 
84
static ScmCharCodec *mbcport_codec(ScmMultiByteCharPort *port);
 
85
static char *mbcport_inspect(ScmMultiByteCharPort *port);
 
86
static scm_ichar_t mbcport_get_char(ScmMultiByteCharPort *port);
 
87
static scm_ichar_t mbcport_peek_char(ScmMultiByteCharPort *port);
 
88
static scm_bool mbcport_char_readyp(ScmMultiByteCharPort *port);
 
89
static void mbcport_put_char(ScmMultiByteCharPort *port, scm_ichar_t ch);
 
90
 
 
91
static ScmMultibyteCharInfo mbcport_fill_rbuf(ScmMultiByteCharPort *port,
 
92
                                              scm_bool blockp);
 
93
 
 
94
/*=======================================
 
95
  Variable Definitions
 
96
=======================================*/
 
97
SCM_GLOBAL_VARS_BEGIN(static_scmport_mbchar);
 
98
#define static
 
99
static ScmCharPortVTbl l_ScmMultiByteCharPort_vtbl;
 
100
#undef static
 
101
SCM_GLOBAL_VARS_END(static_scmport_mbchar);
 
102
#define l_ScmMultiByteCharPort_vtbl                                          \
 
103
        SCM_GLOBAL_VAR(static_scmport_mbchar, l_ScmMultiByteCharPort_vtbl)
 
104
SCM_DEFINE_STATIC_VARS(static_scmport_mbchar);
 
105
 
 
106
SCM_EXPORT const ScmCharPortVTbl *ScmMultiByteCharPort_vptr;
 
107
 
 
108
/*=======================================
 
109
  Function Definitions
 
110
=======================================*/
 
111
SCM_EXPORT void
 
112
scm_mbcport_init(void)
 
113
{
 
114
    ScmCharPortVTbl *vptr;
 
115
 
 
116
    SCM_GLOBAL_VARS_INIT(static_scmport_mbchar);
 
117
 
 
118
    l_ScmMultiByteCharPort_vtbl = *ScmBaseCharPort_vptr;
 
119
 
 
120
    vptr = &l_ScmMultiByteCharPort_vtbl;
 
121
    vptr->dyn_cast    = (ScmCharPortMethod_dyn_cast)&mbcport_dyn_cast;
 
122
    vptr->codec       = (ScmCharPortMethod_codec)&mbcport_codec;
 
123
    vptr->inspect     = (ScmCharPortMethod_inspect)&mbcport_inspect;
 
124
    vptr->get_char    = (ScmCharPortMethod_get_char)&mbcport_get_char;
 
125
    vptr->peek_char   = (ScmCharPortMethod_peek_char)&mbcport_peek_char;
 
126
    vptr->char_readyp = (ScmCharPortMethod_char_readyp)&mbcport_char_readyp;
 
127
    vptr->put_char    = (ScmCharPortMethod_put_char)&mbcport_put_char;
 
128
    ScmMultiByteCharPort_vptr = vptr;
 
129
}
 
130
 
 
131
SCM_EXPORT void
 
132
ScmMultiByteCharPort_construct(ScmMultiByteCharPort *port,
 
133
                               const ScmCharPortVTbl *vptr,
 
134
                               ScmBytePort *bport, ScmCharCodec *codec)
 
135
{
 
136
    ScmBaseCharPort_construct((ScmBaseCharPort *)port, vptr, bport);
 
137
 
 
138
    port->codec = codec;
 
139
    port->rbuf[0] = '\0';
 
140
    SCM_MBCPORT_CLEAR_STATE(port);
 
141
}
 
142
 
 
143
SCM_EXPORT ScmCharPort *
 
144
ScmMultiByteCharPort_new(ScmBytePort *bport, ScmCharCodec *codec)
 
145
{
 
146
    ScmMultiByteCharPort *cport;
 
147
 
 
148
    cport = SCM_PORT_MALLOC(sizeof(ScmMultiByteCharPort));
 
149
    ScmMultiByteCharPort_construct(cport, ScmMultiByteCharPort_vptr,
 
150
                                   bport, codec);
 
151
 
 
152
    return (ScmCharPort *)cport;
 
153
}
 
154
 
 
155
SCM_EXPORT void
 
156
ScmMultiByteCharPort_set_codec(ScmCharPort *cport, ScmCharCodec *codec)
 
157
{
 
158
    ScmMultiByteCharPort *mbcport;
 
159
 
 
160
    mbcport = SCM_BYTEPORT_DYNAMIC_CAST(ScmMultiByteCharPort, cport);
 
161
    mbcport->codec = codec;
 
162
    SCM_MBCPORT_CLEAR_STATE(mbcport);
 
163
    /* only one byte can be preserved for new codec. otherwise cleared */
 
164
    if (1 < strlen((char *)mbcport->rbuf))
 
165
        mbcport->rbuf[0] = '\0';
 
166
}
 
167
 
 
168
static ScmCharPort *
 
169
mbcport_dyn_cast(ScmCharPort *cport, const ScmCharPortVTbl *dst_vptr)
 
170
{
 
171
    return (dst_vptr == ScmBaseCharPort_vptr
 
172
            || dst_vptr == ScmMultiByteCharPort_vptr) ? cport : NULL;
 
173
}
 
174
 
 
175
static ScmCharCodec *
 
176
mbcport_codec(ScmMultiByteCharPort *port)
 
177
{
 
178
    return port->codec;
 
179
}
 
180
 
 
181
static char *
 
182
mbcport_inspect(ScmMultiByteCharPort *port)
 
183
{
 
184
    return ScmBaseCharPort_inspect((ScmBaseCharPort *)port, "mb");
 
185
}
 
186
 
 
187
static scm_ichar_t
 
188
mbcport_get_char(ScmMultiByteCharPort *port)
 
189
{
 
190
    scm_ichar_t ch;
 
191
#if SCM_USE_STATEFUL_ENCODING
 
192
    ScmMultibyteCharInfo mbc;
 
193
    ScmMultibyteState next_state;
 
194
 
 
195
    mbc = mbcport_fill_rbuf(port, scm_true);
 
196
    next_state = SCM_MBCINFO_GET_STATE(mbc);
 
197
#endif
 
198
 
 
199
    ch = mbcport_peek_char(port);
 
200
    port->rbuf[0] = '\0';
 
201
#if SCM_USE_STATEFUL_ENCODING
 
202
    SCM_MBCPORT_SET_STATE(port, next_state)
 
203
#endif
 
204
#if SCM_DEBUG
 
205
    if (ch == SCM_NEWLINE_STR[0])
 
206
        port->linenum++;
 
207
#endif
 
208
 
 
209
    return ch;
 
210
}
 
211
 
 
212
static scm_ichar_t
 
213
mbcport_peek_char(ScmMultiByteCharPort *port)
 
214
{
 
215
    ScmMultibyteCharInfo mbc;
 
216
    size_t size;
 
217
    scm_ichar_t ch;
 
218
 
 
219
    mbc = mbcport_fill_rbuf(port, scm_true);
 
220
    size = SCM_MBCINFO_GET_SIZE(mbc);
 
221
    if (size)
 
222
        ch = SCM_CHARCODEC_STR2INT(port->codec, (char *)port->rbuf, size,
 
223
                                   port->state);
 
224
    else
 
225
        ch = SCM_ICHAR_EOF;
 
226
 
 
227
    return ch;
 
228
}
 
229
 
 
230
static scm_bool
 
231
mbcport_char_readyp(ScmMultiByteCharPort *port)
 
232
{
 
233
    ScmMultibyteCharInfo mbc;
 
234
 
 
235
    mbc = mbcport_fill_rbuf(port, scm_false);
 
236
    return !SCM_MBCINFO_INCOMPLETEP(mbc);
 
237
}
 
238
 
 
239
static void
 
240
mbcport_put_char(ScmMultiByteCharPort *port, scm_ichar_t ch)
 
241
{
 
242
    size_t size;
 
243
    char *end;
 
244
    char wbuf[SCM_MB_CHAR_BUF_SIZE];
 
245
 
 
246
    /* FIXME: set updated state to port->state */
 
247
    end = SCM_CHARCODEC_INT2STR(port->codec, wbuf, ch, port->state);
 
248
    if (!end)
 
249
        SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: invalid character");
 
250
    size = end - wbuf;
 
251
    SCM_BYTEPORT_WRITE(port->bport, size, wbuf);
 
252
}
 
253
 
 
254
static ScmMultibyteCharInfo
 
255
mbcport_fill_rbuf(ScmMultiByteCharPort *port, scm_bool blockp)
 
256
{
 
257
    scm_byte_t *end;
 
258
    scm_ichar_t byte;
 
259
    ScmMultibyteString mbs;
 
260
    ScmMultibyteCharInfo mbc;
 
261
 
 
262
    end = (scm_byte_t *)strchr((char *)port->rbuf, '\0');
 
263
    SCM_MBS_SET_STATE(mbs, port->state);
 
264
    do {
 
265
        SCM_MBS_SET_STR(mbs, (char *)port->rbuf);
 
266
        SCM_MBS_SET_SIZE(mbs, end - port->rbuf);
 
267
 
 
268
        mbc = SCM_CHARCODEC_SCAN_CHAR(port->codec, mbs);
 
269
 
 
270
        if (SCM_MBCINFO_ERRORP(mbc))
 
271
            SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: broken character");
 
272
        if (!SCM_MBCINFO_INCOMPLETEP(mbc) && SCM_MBCINFO_GET_SIZE(mbc))
 
273
            break;
 
274
        if (SCM_MBS_GET_SIZE(mbs) == SCM_MB_MAX_LEN)
 
275
            SCM_CHARPORT_ERROR(port, "ScmMultibyteCharPort: broken scanner");
 
276
 
 
277
        byte = SCM_BYTEPORT_GET_BYTE(port->bport);
 
278
        SCM_MBCINFO_SET_STATE(mbc, SCM_MBS_GET_STATE(mbs));
 
279
        if (byte == SCM_ICHAR_EOF) {
 
280
            SCM_MBCINFO_INIT(mbc);
 
281
            port->rbuf[0] = '\0';
 
282
#if HANDLE_MBC_START
 
283
            mbc->start = (char *)port->rbuf;
 
284
#endif
 
285
            break;
 
286
        }
 
287
        *end++ = byte;
 
288
        *end = '\0';
 
289
    } while (blockp || SCM_BYTEPORT_BYTE_READYP(port->bport));
 
290
 
 
291
    return mbc;
 
292
}