source: XMLIO_V2/external/src/POCO/Foundation/UTF8Encoding.cpp @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1//
2// UTF8Encoding.cpp
3//
4// $Id: //poco/1.3/Foundation/src/UTF8Encoding.cpp#7 $
5//
6// Library: Foundation
7// Package: Text
8// Module:  UTF8Encoding
9//
10// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// Permission is hereby granted, free of charge, to any person or organization
14// obtaining a copy of the software and accompanying documentation covered by
15// this license (the "Software") to use, reproduce, display, distribute,
16// execute, and transmit the Software, and to prepare derivative works of the
17// Software, and to permit third-parties to whom the Software is furnished to
18// do so, all subject to the following:
19//
20// The copyright notices in the Software and this entire statement, including
21// the above license grant, this restriction and the following disclaimer,
22// must be included in all copies of the Software, in whole or in part, and
23// all derivative works of the Software, unless such copies or derivative
24// works are solely in the form of machine-executable object code generated by
25// a source language processor.
26//
27// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
30// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
31// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
32// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33// DEALINGS IN THE SOFTWARE.
34//
35
36
37#include <Poco/UTF8Encoding.h>
38#include <Poco/String.h>
39
40
41namespace Poco {
42
43
44const char* UTF8Encoding::_names[] =
45{
46        "UTF-8",
47        "UTF8",
48        NULL
49};
50
51
52const TextEncoding::CharacterMap UTF8Encoding::_charMap = 
53{
54        /* 00 */        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
55        /* 10 */        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
56        /* 20 */        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
57        /* 30 */        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
58        /* 40 */        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
59        /* 50 */        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
60        /* 60 */        0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
61        /* 70 */        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 
62        /* 80 */          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, 
63        /* 90 */          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, 
64        /* a0 */          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, 
65        /* b0 */          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, 
66        /* c0 */          -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2, 
67        /* d0 */          -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2, 
68        /* e0 */          -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3,   -3, 
69        /* f0 */          -4,   -4,   -4,   -4,   -4,   -4,   -4,   -4,   -5,   -5,   -5,   -5,   -6,   -6,   -1,   -1, 
70};
71
72
73UTF8Encoding::UTF8Encoding()
74{
75}
76
77
78UTF8Encoding::~UTF8Encoding()
79{
80}
81
82
83const char* UTF8Encoding::canonicalName() const
84{
85        return _names[0];
86}
87
88
89bool UTF8Encoding::isA(const std::string& encodingName) const
90{
91        for (const char** name = _names; *name; ++name)
92        {
93                if (Poco::icompare(encodingName, *name) == 0)
94                        return true;
95        }
96        return false;
97}
98
99
100const TextEncoding::CharacterMap& UTF8Encoding::characterMap() const
101{
102        return _charMap;
103}
104
105
106int UTF8Encoding::convert(const unsigned char* bytes) const
107{
108        int n = _charMap[*bytes];
109        int uc;
110       
111        switch (n)
112        {
113        case -6:
114        case -5:
115        case -1:
116                return -1;
117        case -4:
118        case -3:
119        case -2:
120                if (!isLegal(bytes, -n)) return -1;
121                uc = *bytes & ((0x07 << (n + 4)) | 0x03);
122                break;
123        default:
124                return n;
125        }
126
127        while (n++ < -1) 
128        {       
129                uc <<= 6;
130                uc |= (*++bytes & 0x3F);
131        }
132        return uc;
133}
134
135
136int UTF8Encoding::convert(int ch, unsigned char* bytes, int length) const
137{
138#ifdef _DEBUG
139        unsigned char* lb = bytes;
140#endif
141
142        if (ch <= 0x7F)
143        {
144                if (bytes && length >= 1)
145                        *bytes = (unsigned char) ch;
146                return 1;
147        }
148        else if (ch <= 0x7FF)
149        {
150                if (bytes && length >= 2)
151                {
152                        *bytes++ = (unsigned char) (((ch >> 6) & 0x1F) | 0xC0);
153                        *bytes   = (unsigned char) ((ch & 0x3F) | 0x80);
154                }
155                poco_assert_dbg (isLegal(lb, 2));
156                return 2;
157        }
158        else if (ch <= 0xFFFF)
159        {
160                if (bytes && length >= 3)
161                {
162                        *bytes++ = (unsigned char) (((ch >> 12) & 0x0F) | 0xE0);
163                        *bytes++ = (unsigned char) (((ch >> 6) & 0x3F) | 0x80);
164                        *bytes   = (unsigned char) ((ch & 0x3F) | 0x80);
165                }
166                poco_assert_dbg (isLegal(lb, 3));
167                return 3;
168        }
169        else if (ch <= 0x10FFFF)
170        {
171                if (bytes && length >= 4)
172                {
173                        *bytes++ = (unsigned char) (((ch >> 18) & 0x07) | 0xF0);
174                        *bytes++ = (unsigned char) (((ch >> 12) & 0x3F) | 0x80);
175                        *bytes++ = (unsigned char) (((ch >> 6) & 0x3F) | 0x80);
176                        *bytes   = (unsigned char) ((ch & 0x3F) | 0x80);
177                }
178                poco_assert_dbg (isLegal(lb, 4));
179                return 4;
180        }
181        else return 0;
182}
183
184
185int UTF8Encoding::queryConvert(const unsigned char* bytes, int length) const
186{
187        int n = _charMap[*bytes];
188        int uc;
189        if (-n > length)
190        {
191                return n;
192        }
193        else
194        {
195                switch (n)
196                {
197                case -6:
198                case -5:
199                case -1:
200                        return -1;
201                case -4:
202                case -3:
203                case -2:
204                        if (!isLegal(bytes, -n)) return -1;
205                        uc = *bytes & ((0x07 << (n + 4)) | 0x03);
206                        break;
207                default:
208                        return n;
209                }
210                while (n++ < -1) 
211                {       
212                        uc <<= 6;
213                        uc |= (*++bytes & 0x3F);
214                }
215                return uc;
216        }
217}
218
219
220int UTF8Encoding::sequenceLength(const unsigned char* bytes, int length) const
221{
222        if (1 <= length)
223        {
224                int cc = _charMap[*bytes];
225                if (cc >= 0)
226                        return 1;
227                else
228                        return -cc;
229        }
230        else return -1;
231}
232
233
234bool UTF8Encoding::isLegal(const unsigned char *bytes, int length)
235{
236        // Note: The following is loosely based on the isLegalUTF8 function
237        // from ftp://ftp.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
238        // Excuse the ugliness...
239       
240        if (0 == bytes || 0 == length) return false;
241
242    unsigned char a;
243    const unsigned char* srcptr = bytes + length;
244    switch (length)
245        {
246        default:
247                return false;
248                // Everything else falls through when true.
249        case 4:
250                if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
251        case 3:
252                if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
253        case 2:
254                if ((a = (*--srcptr)) > 0xBF) return false;
255                switch (*bytes) 
256                {
257                case 0xE0:
258                        if (a < 0xA0) return false; 
259                        break;
260                case 0xED:
261                        if (a > 0x9F) return false; 
262                        break;
263                case 0xF0:
264                        if (a < 0x90) return false; 
265                        break;
266                case 0xF4:
267                        if (a > 0x8F) return false; 
268                        break;
269                default:
270                        if (a < 0x80) return false;
271                }
272        case 1:
273                if (*bytes >= 0x80 && *bytes < 0xC2) return false;
274    }
275        return *bytes <= 0xF4;
276}
277
278
279} // namespace Poco
Note: See TracBrowser for help on using the repository browser.