~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to mess/src/lib/util/unicode.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************************
2
 
 
3
 
    unicode.c
4
 
 
5
 
    Unicode related functions
6
 
 
7
 
****************************************************************************
8
 
 
9
 
    Copyright Aaron Giles
10
 
    All rights reserved.
11
 
 
12
 
    Redistribution and use in source and binary forms, with or without
13
 
    modification, are permitted provided that the following conditions are
14
 
    met:
15
 
 
16
 
        * Redistributions of source code must retain the above copyright
17
 
          notice, this list of conditions and the following disclaimer.
18
 
        * Redistributions in binary form must reproduce the above copyright
19
 
          notice, this list of conditions and the following disclaimer in
20
 
          the documentation and/or other materials provided with the
21
 
          distribution.
22
 
        * Neither the name 'MAME' nor the names of its contributors may be
23
 
          used to endorse or promote products derived from this software
24
 
          without specific prior written permission.
25
 
 
26
 
    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
27
 
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
 
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
 
    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
30
 
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
 
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
 
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
 
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34
 
    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35
 
    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
 
    POSSIBILITY OF SUCH DAMAGE.
37
 
 
38
 
***************************************************************************/
39
 
 
40
 
#include "unicode.h"
41
 
 
42
 
 
43
 
/*-------------------------------------------------
44
 
    uchar_isvalid - return true if a given
45
 
    character is a legitimate unicode character
46
 
-------------------------------------------------*/
47
 
 
48
 
int uchar_isvalid(unicode_char uchar)
49
 
{
50
 
        return (uchar < 0x110000) && !((uchar >= 0xd800) && (uchar <= 0xdfff));
51
 
}
52
 
 
53
 
 
54
 
/*-------------------------------------------------
55
 
    uchar_from_utf8 - convert a UTF-8 sequence
56
 
    into a unicode character
57
 
-------------------------------------------------*/
58
 
 
59
 
int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count)
60
 
{
61
 
        unicode_char c, minchar;
62
 
        int auxlen, i;
63
 
        char auxchar;
64
 
 
65
 
        /* validate parameters */
66
 
        if (utf8char == NULL || count == 0)
67
 
                return 0;
68
 
 
69
 
        /* start with the first byte */
70
 
        c = (unsigned char) *utf8char;
71
 
        count--;
72
 
        utf8char++;
73
 
 
74
 
        /* based on that, determine how many additional bytes we need */
75
 
        if (c < 0x80)
76
 
        {
77
 
                /* unicode char 0x00000000 - 0x0000007F */
78
 
                c &= 0x7f;
79
 
                auxlen = 0;
80
 
                minchar = 0x00000000;
81
 
        }
82
 
        else if (c >= 0xc0 && c < 0xe0)
83
 
        {
84
 
                /* unicode char 0x00000080 - 0x000007FF */
85
 
                c &= 0x1f;
86
 
                auxlen = 1;
87
 
                minchar = 0x00000080;
88
 
        }
89
 
        else if (c >= 0xe0 && c < 0xf0)
90
 
        {
91
 
                /* unicode char 0x00000800 - 0x0000FFFF */
92
 
                c &= 0x0f;
93
 
                auxlen = 2;
94
 
                minchar = 0x00000800;
95
 
        }
96
 
        else if (c >= 0xf0 && c < 0xf8)
97
 
        {
98
 
                /* unicode char 0x00010000 - 0x001FFFFF */
99
 
                c &= 0x07;
100
 
                auxlen = 3;
101
 
                minchar = 0x00010000;
102
 
        }
103
 
        else if (c >= 0xf8 && c < 0xfc)
104
 
        {
105
 
                /* unicode char 0x00200000 - 0x03FFFFFF */
106
 
                c &= 0x03;
107
 
                auxlen = 4;
108
 
                minchar = 0x00200000;
109
 
        }
110
 
        else if (c >= 0xfc && c < 0xfe)
111
 
        {
112
 
                /* unicode char 0x04000000 - 0x7FFFFFFF */
113
 
                c &= 0x01;
114
 
                auxlen = 5;
115
 
                minchar = 0x04000000;
116
 
        }
117
 
        else
118
 
        {
119
 
                /* invalid */
120
 
                return -1;
121
 
        }
122
 
 
123
 
        /* exceeds the count? */
124
 
        if (auxlen > count)
125
 
                return -1;
126
 
 
127
 
        /* we now know how long the char is, now compute it */
128
 
        for (i = 0; i < auxlen; i++)
129
 
        {
130
 
                auxchar = utf8char[i];
131
 
 
132
 
                /* all auxillary chars must be between 0x80-0xbf */
133
 
                if ((auxchar & 0xc0) != 0x80)
134
 
                        return -1;
135
 
 
136
 
                c = c << 6;
137
 
                c |= auxchar & 0x3f;
138
 
        }
139
 
 
140
 
        /* make sure that this char is above the minimum */
141
 
        if (c < minchar)
142
 
                return -1;
143
 
 
144
 
        *uchar = c;
145
 
        return auxlen + 1;
146
 
}
147
 
 
148
 
 
149
 
/*-------------------------------------------------
150
 
    uchar_from_utf16 - convert a UTF-16 sequence
151
 
    into a unicode character
152
 
-------------------------------------------------*/
153
 
 
154
 
int uchar_from_utf16(unicode_char *uchar, const utf16_char *utf16char, size_t count)
155
 
{
156
 
        int rc = -1;
157
 
 
158
 
        /* validate parameters */
159
 
        if (utf16char == NULL || count == 0)
160
 
                return 0;
161
 
 
162
 
        /* handle the two-byte case */
163
 
        if (utf16char[0] >= 0xd800 && utf16char[0] <= 0xdbff)
164
 
        {
165
 
                if (count > 1 && utf16char[1] >= 0xdc00 && utf16char[1] <= 0xdfff)
166
 
                {
167
 
                        *uchar = 0x10000 + ((utf16char[0] & 0x3ff) * 0x400) + (utf16char[1] & 0x3ff);
168
 
                        rc = 2;
169
 
                }
170
 
        }
171
 
 
172
 
        /* handle the one-byte case */
173
 
        else if (utf16char[0] < 0xdc00 || utf16char[0] > 0xdfff)
174
 
        {
175
 
                *uchar = utf16char[0];
176
 
                rc = 1;
177
 
        }
178
 
 
179
 
        return rc;
180
 
}
181
 
 
182
 
 
183
 
/*-------------------------------------------------
184
 
    uchar_from_utf16f - convert a UTF-16 sequence
185
 
    into a unicode character from a flipped
186
 
    byte order
187
 
-------------------------------------------------*/
188
 
 
189
 
int uchar_from_utf16f(unicode_char *uchar, const utf16_char *utf16char, size_t count)
190
 
{
191
 
        utf16_char buf[2] = {0};
192
 
        if (count > 0)
193
 
                buf[0] = FLIPENDIAN_INT16(utf16char[0]);
194
 
        if (count > 1)
195
 
                buf[1] = FLIPENDIAN_INT16(utf16char[1]);
196
 
        return uchar_from_utf16(uchar, buf, count);
197
 
}
198
 
 
199
 
 
200
 
/*-------------------------------------------------
201
 
    utf8_from_uchar - convert a unicode character
202
 
    into a UTF-8 sequence
203
 
-------------------------------------------------*/
204
 
 
205
 
int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar)
206
 
{
207
 
        int rc = 0;
208
 
 
209
 
        /* error on invalid characters */
210
 
        if (!uchar_isvalid(uchar))
211
 
                return -1;
212
 
 
213
 
        /* based on the value, output the appropriate number of bytes */
214
 
        if (uchar < 0x80)
215
 
        {
216
 
                /* unicode char 0x00000000 - 0x0000007F */
217
 
                if (count < 1)
218
 
                        return -1;
219
 
                utf8string[rc++] = (char) uchar;
220
 
        }
221
 
        else if (uchar < 0x800)
222
 
        {
223
 
                /* unicode char 0x00000080 - 0x000007FF */
224
 
                if (count < 2)
225
 
                        return -1;
226
 
                utf8string[rc++] = ((char) (uchar >> 6)) | 0xC0;
227
 
                utf8string[rc++] = ((char) ((uchar >> 0) & 0x3F)) | 0x80;
228
 
        }
229
 
        else if (uchar < 0x10000)
230
 
        {
231
 
                /* unicode char 0x00000800 - 0x0000FFFF */
232
 
                if (count < 3)
233
 
                        return -1;
234
 
                utf8string[rc++] = ((char) (uchar >> 12)) | 0xE0;
235
 
                utf8string[rc++] = ((char) ((uchar >> 6) & 0x3F)) | 0x80;
236
 
                utf8string[rc++] = ((char) ((uchar >> 0) & 0x3F)) | 0x80;
237
 
        }
238
 
        else if (uchar < 0x00200000)
239
 
        {
240
 
                /* unicode char 0x00010000 - 0x001FFFFF */
241
 
                if (count < 4)
242
 
                        return -1;
243
 
                utf8string[rc++] = ((char) (uchar >> 18)) | 0xF0;
244
 
                utf8string[rc++] = ((char) ((uchar >> 12) & 0x3F)) | 0x80;
245
 
                utf8string[rc++] = ((char) ((uchar >> 6) & 0x3F)) | 0x80;
246
 
                utf8string[rc++] = ((char) ((uchar >> 0) & 0x3F)) | 0x80;
247
 
        }
248
 
        else if (uchar < 0x04000000)
249
 
        {
250
 
                /* unicode char 0x00200000 - 0x03FFFFFF */
251
 
                if (count < 5)
252
 
                        return -1;
253
 
                utf8string[rc++] = ((char) (uchar >> 24)) | 0xF8;
254
 
                utf8string[rc++] = ((char) ((uchar >> 18) & 0x3F)) | 0x80;
255
 
                utf8string[rc++] = ((char) ((uchar >> 12) & 0x3F)) | 0x80;
256
 
                utf8string[rc++] = ((char) ((uchar >> 6) & 0x3F)) | 0x80;
257
 
                utf8string[rc++] = ((char) ((uchar >> 0) & 0x3F)) | 0x80;
258
 
        }
259
 
        else if (uchar < 0x80000000)
260
 
        {
261
 
                /* unicode char 0x04000000 - 0x7FFFFFFF */
262
 
                if (count < 6)
263
 
                        return -1;
264
 
                utf8string[rc++] = ((char) (uchar >> 30)) | 0xFC;
265
 
                utf8string[rc++] = ((char) ((uchar >> 24) & 0x3F)) | 0x80;
266
 
                utf8string[rc++] = ((char) ((uchar >> 18) & 0x3F)) | 0x80;
267
 
                utf8string[rc++] = ((char) ((uchar >> 12) & 0x3F)) | 0x80;
268
 
                utf8string[rc++] = ((char) ((uchar >> 6) & 0x3F)) | 0x80;
269
 
                utf8string[rc++] = ((char) ((uchar >> 0) & 0x3F)) | 0x80;
270
 
        }
271
 
        else
272
 
                rc = -1;
273
 
 
274
 
        return rc;
275
 
}
276
 
 
277
 
 
278
 
/*-------------------------------------------------
279
 
    utf16_from_uchar - convert a unicode character
280
 
    into a UTF-16 sequence
281
 
-------------------------------------------------*/
282
 
 
283
 
int utf16_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar)
284
 
{
285
 
        int rc;
286
 
 
287
 
        /* error on invalid characters */
288
 
        if (!uchar_isvalid(uchar))
289
 
                return -1;
290
 
 
291
 
        /* single word case */
292
 
        if (uchar < 0x10000)
293
 
        {
294
 
                if (count < 1)
295
 
                        return -1;
296
 
                utf16string[0] = (utf16_char) uchar;
297
 
                rc = 1;
298
 
        }
299
 
 
300
 
        /* double word case */
301
 
        else if (uchar < 0x100000)
302
 
        {
303
 
                if (count < 2)
304
 
                        return -1;
305
 
                utf16string[0] = ((uchar >> 10) & 0x03ff) | 0xd800;
306
 
                utf16string[1] = ((uchar >>  0) & 0x03ff) | 0xdc00;
307
 
                rc = 2;
308
 
        }
309
 
        else
310
 
                return -1;
311
 
        return rc;
312
 
}
313
 
 
314
 
 
315
 
/*-------------------------------------------------
316
 
    utf16_from_uchar - convert a unicode character
317
 
    into a UTF-16 sequence with flipped endianness
318
 
-------------------------------------------------*/
319
 
 
320
 
int utf16f_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar)
321
 
{
322
 
        int rc;
323
 
        utf16_char buf[2] = { 0, 0 };
324
 
 
325
 
        rc = utf16_from_uchar(buf, count, uchar);
326
 
 
327
 
        if (rc >= 1)
328
 
                utf16string[0] = FLIPENDIAN_INT16(buf[0]);
329
 
        if (rc >= 2)
330
 
                utf16string[1] = FLIPENDIAN_INT16(buf[1]);
331
 
        return rc;
332
 
}
333
 
 
334
 
 
335
 
/*-------------------------------------------------
336
 
    utf8_previous_char - return a pointer to the
337
 
    previous character in a string
338
 
-------------------------------------------------*/
339
 
 
340
 
const char *utf8_previous_char(const char *utf8string)
341
 
{
342
 
        while ((*--utf8string & 0xc0) == 0x80)
343
 
                ;
344
 
        return utf8string;
345
 
}
346
 
 
347
 
 
348
 
/*-------------------------------------------------
349
 
    utf8_is_valid_string - return true if the
350
 
    given string is a properly formed sequence of
351
 
    UTF-8 characters
352
 
-------------------------------------------------*/
353
 
 
354
 
int utf8_is_valid_string(const char *utf8string)
355
 
{
356
 
        int remaining_length = strlen(utf8string);
357
 
 
358
 
        while (*utf8string != 0)
359
 
        {
360
 
                unicode_char uchar = 0;
361
 
                int charlen;
362
 
 
363
 
                /* extract the current character and verify it */
364
 
                charlen = uchar_from_utf8(&uchar, utf8string, remaining_length);
365
 
                if (charlen <= 0 || uchar == 0 || !uchar_isvalid(uchar))
366
 
                        return FALSE;
367
 
 
368
 
                /* advance */
369
 
                utf8string += charlen;
370
 
                remaining_length -= charlen;
371
 
        }
372
 
 
373
 
        return TRUE;
374
 
}