Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2010 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 : #undef NDEBUG
20 : #define TDS_DONT_DEFINE_DEFAULT_FUNCTIONS
21 : #include "common.h"
22 :
23 : #include <ctype.h>
24 : #include <assert.h>
25 :
26 : int utf8_max_len = 0;
27 :
28 : int
29 26466 : get_unichar(const char **psrc)
30 : {
31 26466 : const char *src = *psrc;
32 : int n;
33 :
34 26466 : if (!*src) return -1;
35 :
36 50004 : if (src[0] == '&' && src[1] == '#') {
37 : char *end;
38 24390 : int radix = 10;
39 :
40 24390 : if (toupper(src[2]) == 'X') {
41 13572 : radix = 16;
42 13572 : ++src;
43 : }
44 24390 : n = strtol(src+2, &end, radix);
45 24390 : assert(*end == ';' && n > 0 && n < 0x10000);
46 24390 : src = end + 1;
47 : } else {
48 1224 : n = (unsigned char) *src++;
49 : }
50 25614 : *psrc = src;
51 25614 : return n;
52 : }
53 :
54 : char *
55 852 : to_utf8(const char *src, char *dest)
56 : {
57 852 : unsigned char *p = (unsigned char *) dest;
58 852 : int len = 0, n;
59 :
60 27318 : while ((n=get_unichar(&src)) > 0) {
61 25614 : if (n >= 0x2000) {
62 23598 : *p++ = 0xe0 | (n >> 12);
63 23598 : *p++ = 0x80 | ((n >> 6) & 0x3f);
64 23598 : *p++ = 0x80 | (n & 0x3f);
65 2016 : } else if (n >= 0x80) {
66 792 : *p++ = 0xc0 | (n >> 6);
67 792 : *p++ = 0x80 | (n & 0x3f);
68 : } else {
69 1224 : *p++ = (unsigned char) n;
70 : }
71 25614 : ++len;
72 : }
73 852 : if (len > utf8_max_len)
74 294 : utf8_max_len = len;
75 852 : *p = 0;
76 852 : return dest;
77 : }
78 :
|