~dexter/parrot-pkg/maverick

« back to all changes in this revision

Viewing changes to src/string/encoding/ucs2.c

  • Committer: Piotr Roszatycki
  • Date: 2011-01-11 14:34:28 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: piotr.roszatycki@gmail.com-20110111143428-s7pa7qz38m61o4tw
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
Copyright (C) 2001-2010, Parrot Foundation.
3
 
$Id: ucs2.c 49088 2010-09-17 17:51:12Z nwellnhof $
4
3
 
5
4
=head1 NAME
6
5
 
8
7
 
9
8
=head1 DESCRIPTION
10
9
 
11
 
UCS-2 encoding with the help of the ICU library.
 
10
UCS-2 encoding
12
11
 
13
12
=head2 Functions
14
13
 
19
18
*/
20
19
 
21
20
#include "parrot/parrot.h"
 
21
#include "../unicode.h"
22
22
#include "shared.h"
23
23
 
24
 
#if !PARROT_HAS_ICU
25
 
PARROT_DOES_NOT_RETURN
26
 
static void no_ICU_lib(PARROT_INTERP) /* HEADERIZER SKIP */
27
 
{
28
 
    Parrot_ex_throw_from_c_args(interp, NULL,
29
 
        EXCEPTION_LIBRARY_ERROR,
30
 
        "no ICU lib loaded");
31
 
}
32
 
#endif
33
 
 
34
24
/* HEADERIZER HFILE: none */
35
25
 
36
26
/* HEADERIZER BEGIN: static */
37
27
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
38
28
 
39
 
static size_t ucs2_hash(PARROT_INTERP,
40
 
    ARGIN(const STRING *s),
 
29
PARROT_INLINE
 
30
static void ucs2_check_codepoint(PARROT_INTERP, UINTVAL c)
 
31
        __attribute__nonnull__(1);
 
32
 
 
33
static size_t ucs2_hash(SHIM_INTERP,
 
34
    ARGIN(const STRING *src),
41
35
    size_t hashval)
42
 
        __attribute__nonnull__(1)
43
36
        __attribute__nonnull__(2);
44
37
 
45
 
static UINTVAL ucs2_iter_get(PARROT_INTERP,
 
38
static UINTVAL ucs2_iter_get(SHIM_INTERP,
46
39
    ARGIN(const STRING *str),
47
40
    ARGIN(const String_iter *i),
48
41
    INTVAL offset)
49
 
        __attribute__nonnull__(1)
50
42
        __attribute__nonnull__(2)
51
43
        __attribute__nonnull__(3);
52
44
 
53
 
static UINTVAL ucs2_iter_get_and_advance(PARROT_INTERP,
 
45
static UINTVAL ucs2_iter_get_and_advance(SHIM_INTERP,
54
46
    ARGIN(const STRING *str),
55
47
    ARGMOD(String_iter *i))
56
 
        __attribute__nonnull__(1)
57
48
        __attribute__nonnull__(2)
58
49
        __attribute__nonnull__(3)
59
50
        FUNC_MODIFIES(*i);
68
59
        FUNC_MODIFIES(*str)
69
60
        FUNC_MODIFIES(*i);
70
61
 
71
 
static void ucs2_iter_set_position(PARROT_INTERP,
72
 
    ARGIN(const STRING *str),
73
 
    ARGMOD(String_iter *i),
74
 
    UINTVAL n)
75
 
        __attribute__nonnull__(1)
76
 
        __attribute__nonnull__(2)
77
 
        __attribute__nonnull__(3)
78
 
        FUNC_MODIFIES(*i);
79
 
 
80
 
static void ucs2_iter_skip(PARROT_INTERP,
81
 
    ARGIN(const STRING *str),
 
62
static void ucs2_iter_skip(SHIM_INTERP,
 
63
    SHIM(const STRING *str),
82
64
    ARGMOD(String_iter *i),
83
65
    INTVAL skip)
84
 
        __attribute__nonnull__(1)
85
 
        __attribute__nonnull__(2)
86
66
        __attribute__nonnull__(3)
87
67
        FUNC_MODIFIES(*i);
88
68
 
89
 
static UINTVAL ucs2_ord(PARROT_INTERP,
90
 
    ARGIN(const STRING *src),
91
 
    UINTVAL offset)
 
69
static UINTVAL ucs2_ord(PARROT_INTERP, ARGIN(const STRING *src), INTVAL idx)
92
70
        __attribute__nonnull__(1)
93
71
        __attribute__nonnull__(2);
94
72
 
99
77
 
100
78
PARROT_WARN_UNUSED_RESULT
101
79
PARROT_CANNOT_RETURN_NULL
102
 
static STRING * ucs2_substr(PARROT_INTERP,
103
 
    ARGIN(const STRING *src),
104
 
    UINTVAL offset,
105
 
    UINTVAL count)
106
 
        __attribute__nonnull__(1)
107
 
        __attribute__nonnull__(2);
108
 
 
109
 
PARROT_WARN_UNUSED_RESULT
110
 
PARROT_CANNOT_RETURN_NULL
111
80
static STRING * ucs2_to_encoding(PARROT_INTERP, ARGIN(const STRING *src))
112
81
        __attribute__nonnull__(1)
113
82
        __attribute__nonnull__(2);
114
83
 
 
84
#define ASSERT_ARGS_ucs2_check_codepoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
 
85
       PARROT_ASSERT_ARG(interp))
115
86
#define ASSERT_ARGS_ucs2_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
116
 
       PARROT_ASSERT_ARG(interp) \
117
 
    , PARROT_ASSERT_ARG(s))
 
87
       PARROT_ASSERT_ARG(src))
118
88
#define ASSERT_ARGS_ucs2_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
119
 
       PARROT_ASSERT_ARG(interp) \
120
 
    , PARROT_ASSERT_ARG(str) \
 
89
       PARROT_ASSERT_ARG(str) \
121
90
    , PARROT_ASSERT_ARG(i))
122
91
#define ASSERT_ARGS_ucs2_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
123
 
       PARROT_ASSERT_ARG(interp) \
124
 
    , PARROT_ASSERT_ARG(str) \
 
92
       PARROT_ASSERT_ARG(str) \
125
93
    , PARROT_ASSERT_ARG(i))
126
94
#define ASSERT_ARGS_ucs2_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
127
95
       PARROT_ASSERT_ARG(interp) \
128
96
    , PARROT_ASSERT_ARG(str) \
129
97
    , PARROT_ASSERT_ARG(i))
130
 
#define ASSERT_ARGS_ucs2_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
131
 
       PARROT_ASSERT_ARG(interp) \
132
 
    , PARROT_ASSERT_ARG(str) \
133
 
    , PARROT_ASSERT_ARG(i))
134
98
#define ASSERT_ARGS_ucs2_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
135
 
       PARROT_ASSERT_ARG(interp) \
136
 
    , PARROT_ASSERT_ARG(str) \
137
 
    , PARROT_ASSERT_ARG(i))
 
99
       PARROT_ASSERT_ARG(i))
138
100
#define ASSERT_ARGS_ucs2_ord __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
139
101
       PARROT_ASSERT_ARG(interp) \
140
102
    , PARROT_ASSERT_ARG(src))
141
103
#define ASSERT_ARGS_ucs2_scan __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
142
104
       PARROT_ASSERT_ARG(interp) \
143
105
    , PARROT_ASSERT_ARG(src))
144
 
#define ASSERT_ARGS_ucs2_substr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
145
 
       PARROT_ASSERT_ARG(interp) \
146
 
    , PARROT_ASSERT_ARG(src))
147
106
#define ASSERT_ARGS_ucs2_to_encoding __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
148
107
       PARROT_ASSERT_ARG(interp) \
149
108
    , PARROT_ASSERT_ARG(src))
150
109
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
151
110
/* HEADERIZER END: static */
152
111
 
153
 
#if PARROT_HAS_ICU
154
 
#  include <unicode/ustring.h>
155
 
#endif
156
 
 
157
112
#define UNIMPL Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED, \
158
113
    "unimpl ucs2")
159
114
 
178
133
    STRING * const result =
179
134
        Parrot_utf16_encoding_ptr->to_encoding(interp, src);
180
135
 
181
 
    /* conversion to utf16 downgrads to ucs-2 if possible - check result */
 
136
    /* conversion to utf16 downgrades to ucs-2 if possible - check result */
182
137
    if (result->encoding == Parrot_utf16_encoding_ptr)
183
138
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING,
184
 
            "can't convert string with surrogates to ucs2");
 
139
            "Lossy conversion to UCS-2\n");
185
140
 
186
141
    return result;
187
142
}
188
143
 
189
144
/*
190
145
 
 
146
=item C<static void ucs2_check_codepoint(PARROT_INTERP, UINTVAL c)>
 
147
 
 
148
Throws an exception if codepoint C<c> is invalid.
 
149
 
 
150
=cut
 
151
 
 
152
*/
 
153
 
 
154
PARROT_INLINE
 
155
static void
 
156
ucs2_check_codepoint(PARROT_INTERP, UINTVAL c)
 
157
{
 
158
    ASSERT_ARGS(ucs2_check_codepoint)
 
159
 
 
160
    if (UNICODE_IS_SURROGATE(c)
 
161
    || (c >= 0xFDD0 && c <= 0xFDEF)
 
162
    ||  c >= 0xFFFE)
 
163
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_CHARACTER,
 
164
                "Invalid character in UCS-2 string\n");
 
165
}
 
166
 
 
167
/*
 
168
 
191
169
=item C<static UINTVAL ucs2_scan(PARROT_INTERP, const STRING *src)>
192
170
 
193
171
Returns the number of codepoints in string C<src>.
201
179
ucs2_scan(PARROT_INTERP, ARGIN(const STRING *src))
202
180
{
203
181
    ASSERT_ARGS(ucs2_scan)
204
 
#if PARROT_HAS_ICU
205
 
    UNUSED(interp);
206
 
    return src->bufused / sizeof (UChar);
207
 
#else
208
 
    UNUSED(src);
209
 
    no_ICU_lib(interp);
210
 
#endif
 
182
    const utf16_t * const ptr = (utf16_t *)src->strstart;
 
183
    const UINTVAL         len = src->bufused >> 1;
 
184
    UINTVAL               i;
 
185
 
 
186
    if (src->bufused & 1)
 
187
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_CHARACTER,
 
188
            "Unaligned end in UCS-2 string\n");
 
189
 
 
190
    for (i = 0; i < len; ++i) {
 
191
        ucs2_check_codepoint(interp, ptr[i]);
 
192
    }
 
193
 
 
194
    return len;
211
195
}
212
196
 
213
197
/*
214
198
 
215
 
=item C<static UINTVAL ucs2_ord(PARROT_INTERP, const STRING *src, UINTVAL
216
 
offset)>
 
199
=item C<static UINTVAL ucs2_ord(PARROT_INTERP, const STRING *src, INTVAL idx)>
217
200
 
218
201
Returns the codepoint in string C<src> at position C<offset>.
219
202
 
222
205
*/
223
206
 
224
207
static UINTVAL
225
 
ucs2_ord(PARROT_INTERP, ARGIN(const STRING *src), UINTVAL offset)
 
208
ucs2_ord(PARROT_INTERP, ARGIN(const STRING *src), INTVAL idx)
226
209
{
227
210
    ASSERT_ARGS(ucs2_ord)
228
 
#if PARROT_HAS_ICU
229
 
    const UChar * const s = (const UChar*) src->strstart;
230
 
    UNUSED(interp);
231
 
    return s[offset];
232
 
#else
233
 
    UNUSED(offset);
234
 
    UNUSED(src);
235
 
    no_ICU_lib(interp);
236
 
#endif
237
 
}
238
 
 
239
 
/*
240
 
 
241
 
=item C<static STRING * ucs2_substr(PARROT_INTERP, const STRING *src, UINTVAL
242
 
offset, UINTVAL count)>
243
 
 
244
 
Returns the codepoints in string C<src> at position C<offset> and length
245
 
C<count>.
246
 
 
247
 
=cut
248
 
 
249
 
*/
250
 
 
251
 
PARROT_WARN_UNUSED_RESULT
252
 
PARROT_CANNOT_RETURN_NULL
253
 
static STRING *
254
 
ucs2_substr(PARROT_INTERP, ARGIN(const STRING *src), UINTVAL offset, UINTVAL count)
255
 
{
256
 
    ASSERT_ARGS(ucs2_substr)
257
 
    STRING * const return_string = Parrot_str_copy(interp, src);
258
 
 
259
 
#if PARROT_HAS_ICU
260
 
    return_string->strstart = (char*)src->strstart + offset * sizeof (UChar);
261
 
    return_string->bufused  = count * sizeof (UChar);
262
 
    return_string->strlen   = count;
263
 
    return_string->hashval  = 0;
264
 
    return return_string;
265
 
#else
266
 
    UNUSED(src);
267
 
    UNUSED(offset);
268
 
    UNUSED(count);
269
 
    no_ICU_lib(interp);
270
 
#endif
271
 
}
 
211
    const utf16_t * const ptr = (utf16_t *)src->strstart;
 
212
    const UINTVAL         len = STRING_length(src);
 
213
 
 
214
    if (idx < 0)
 
215
        idx += len;
 
216
 
 
217
    if ((UINTVAL)idx >= len)
 
218
        encoding_ord_error(interp, src, idx);
 
219
 
 
220
    return ptr[idx];
 
221
}
 
222
 
272
223
 
273
224
/*
274
225
 
282
233
*/
283
234
 
284
235
static UINTVAL
285
 
ucs2_iter_get(PARROT_INTERP,
 
236
ucs2_iter_get(SHIM_INTERP,
286
237
    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset)
287
238
{
288
239
    ASSERT_ARGS(ucs2_iter_get)
289
 
    return ucs2_ord(interp, str, i->charpos + offset);
 
240
    const utf16_t * const ptr = (utf16_t *)str->strstart;
 
241
 
 
242
    return ptr[i->charpos + offset];
290
243
}
291
244
 
292
245
/*
301
254
*/
302
255
 
303
256
static void
304
 
ucs2_iter_skip(PARROT_INTERP,
305
 
    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip)
 
257
ucs2_iter_skip(SHIM_INTERP,
 
258
    SHIM(const STRING *str), ARGMOD(String_iter *i), INTVAL skip)
306
259
{
307
260
    ASSERT_ARGS(ucs2_iter_skip)
308
 
    UNUSED(str);
309
261
 
310
 
#if PARROT_HAS_ICU
311
262
    i->charpos += skip;
312
 
    i->bytepos += skip * sizeof (UChar);
313
 
#else
314
 
    UNUSED(i);
315
 
    UNUSED(skip);
316
 
    no_ICU_lib(interp);
317
 
#endif
 
263
    i->bytepos += skip * 2;
318
264
}
319
265
 
320
266
/*
329
275
*/
330
276
 
331
277
static UINTVAL
332
 
ucs2_iter_get_and_advance(PARROT_INTERP,
 
278
ucs2_iter_get_and_advance(SHIM_INTERP,
333
279
    ARGIN(const STRING *str), ARGMOD(String_iter *i))
334
280
{
335
281
    ASSERT_ARGS(ucs2_iter_get_and_advance)
336
 
 
337
 
#if PARROT_HAS_ICU
338
 
    UChar * const s = (UChar*) str->strstart;
339
 
    size_t pos = i->bytepos / sizeof (UChar);
340
 
 
341
 
    /* TODO either make sure that we don't go past end or use SAFE
342
 
     *      iter versions
343
 
     */
344
 
    const UChar c = s[pos++];
345
 
    i->charpos++;
346
 
    i->bytepos = pos * sizeof (UChar);
 
282
    const utf16_t * const ptr = (utf16_t *)str->strstart;
 
283
    const UINTVAL         c   = ptr[i->charpos];
 
284
 
 
285
    i->charpos += 1;
 
286
    i->bytepos += 2;
 
287
 
347
288
    return c;
348
 
#else
349
 
    UNUSED(str);
350
 
    UNUSED(i);
351
 
    no_ICU_lib(interp);
352
 
    return (UINTVAL)0; /* Stop the static analyzers from panicing */
353
 
#endif
354
289
}
355
290
 
356
291
/*
370
305
    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c)
371
306
{
372
307
    ASSERT_ARGS(ucs2_iter_set_and_advance)
373
 
 
374
 
#if PARROT_HAS_ICU
375
 
    UChar * const s = (UChar*) str->strstart;
376
 
    UINTVAL pos = i->bytepos / sizeof (UChar);
377
 
    s[pos++] = (UChar)c;
378
 
    i->charpos++;
379
 
    i->bytepos = pos * sizeof (UChar);
380
 
#else
381
 
    UNUSED(str);
382
 
    UNUSED(i);
383
 
    UNUSED(c);
384
 
    no_ICU_lib(interp);
385
 
#endif
386
 
}
387
 
 
388
 
/*
389
 
 
390
 
=item C<static void ucs2_iter_set_position(PARROT_INTERP, const STRING *str,
391
 
String_iter *i, UINTVAL n)>
392
 
 
393
 
Moves the string iterator C<i> to the position C<n> in the string.
394
 
 
395
 
=cut
396
 
 
397
 
*/
398
 
 
399
 
static void
400
 
ucs2_iter_set_position(PARROT_INTERP,
401
 
    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n)
402
 
{
403
 
    ASSERT_ARGS(ucs2_iter_set_position)
404
 
    UNUSED(str);
405
 
 
406
 
#if PARROT_HAS_ICU
407
 
    i->charpos = n;
408
 
    i->bytepos = n * sizeof (UChar);
409
 
#else
410
 
    UNUSED(i);
411
 
    UNUSED(n);
412
 
    no_ICU_lib(interp);
413
 
#endif
414
 
}
415
 
 
416
 
/*
417
 
 
418
 
=item C<static size_t ucs2_hash(PARROT_INTERP, const STRING *s, size_t hashval)>
 
308
    utf16_t * const ptr = (utf16_t *)str->strstart;
 
309
 
 
310
    ucs2_check_codepoint(interp, c);
 
311
 
 
312
    ptr[i->charpos] = c;
 
313
 
 
314
    i->charpos += 1;
 
315
    i->bytepos += 2;
 
316
}
 
317
 
 
318
/*
 
319
 
 
320
=item C<static size_t ucs2_hash(PARROT_INTERP, const STRING *src, size_t
 
321
hashval)>
419
322
 
420
323
Returns the hashed value of the string, given a seed in hashval.
421
324
 
424
327
*/
425
328
 
426
329
static size_t
427
 
ucs2_hash(PARROT_INTERP, ARGIN(const STRING *s), size_t hashval)
 
330
ucs2_hash(SHIM_INTERP, ARGIN(const STRING *src), size_t hashval)
428
331
{
429
332
    ASSERT_ARGS(ucs2_hash)
430
 
#if PARROT_HAS_ICU
431
 
    const UChar *pos = (const UChar*) s->strstart;
432
 
    UINTVAL len = s->strlen;
433
 
    UNUSED(interp);
 
333
    DECL_CONST_CAST;
 
334
    STRING * const s   = PARROT_const_cast(STRING *, src);
 
335
    const utf16_t *ptr = (utf16_t *)s->strstart;
 
336
    UINTVAL        len = s->strlen;
434
337
 
435
338
    while (len--) {
436
339
        hashval += hashval << 5;
437
 
        hashval += *(pos++);
 
340
        hashval += *(ptr++);
438
341
    }
439
342
 
 
343
    s->hashval = hashval;
 
344
 
440
345
    return hashval;
441
 
 
442
 
#else
443
 
    UNUSED(s);
444
 
    UNUSED(hashval);
445
 
 
446
 
    no_ICU_lib(interp);
447
 
#endif
448
346
}
449
347
 
450
348
static STR_VTABLE Parrot_ucs2_encoding = {
460
358
    encoding_compare,
461
359
    encoding_index,
462
360
    encoding_rindex,
463
 
    encoding_hash,
464
 
    unicode_validate,
 
361
    ucs2_hash,
465
362
 
466
363
    ucs2_scan,
467
364
    ucs2_ord,
468
 
    ucs2_substr,
 
365
    fixed_substr,
469
366
 
470
367
    encoding_is_cclass,
471
368
    encoding_find_cclass,
485
382
    ucs2_iter_get,
486
383
    ucs2_iter_skip,
487
384
    ucs2_iter_get_and_advance,
488
 
    ucs2_iter_set_and_advance,
489
 
    ucs2_iter_set_position
 
385
    ucs2_iter_set_and_advance
490
386
};
491
387
 
492
388
STR_VTABLE *Parrot_ucs2_encoding_ptr = &Parrot_ucs2_encoding;
513
409
 * Local variables:
514
410
 *   c-file-style: "parrot"
515
411
 * End:
516
 
 * vim: expandtab shiftwidth=4:
 
412
 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
517
413
 */