FreeBASIC  0.91.0
utf_convto_char.c
Go to the documentation of this file.
1 /* UTF to zstring conversion
2  * (based on ConvertUTF.c free implementation from Unicode, Inc)
3  */
4 
5 #include "fb.h"
6 
7 extern const char __fb_utf8_trailingTb[256];
8 extern const UTF_32 __fb_utf8_offsetsTb[6];
9 
10 char *fb_hUTF8ToChar( const UTF_8 *src, char *dst, ssize_t *chars )
11 {
12  UTF_32 c;
13  ssize_t extbytes, charsleft;
14  char *buffer = dst;
15 
16  if( dst == NULL )
17  {
18  ssize_t dst_size = 0;
19  charsleft = 0;
20  do
21  {
22  extbytes = __fb_utf8_trailingTb[(unsigned int)*src];
23 
24  c = 0;
25  switch( extbytes )
26  {
27  case 5:
28  c += *src++; c <<= 6;
29  case 4:
30  c += *src++; c <<= 6;
31  case 3:
32  c += *src++; c <<= 6;
33  case 2:
34  c += *src++; c <<= 6;
35  case 1:
36  c += *src++; c <<= 6;
37  case 0:
38  c += *src++;
39  }
40 
41  c -= __fb_utf8_offsetsTb[extbytes];
42 
43  if( c > 255 )
44  c = '?';
45 
46  if( charsleft == 0 )
47  {
48  charsleft = 8;
49  dst_size += charsleft;
50  buffer = realloc( buffer, dst_size );
51  dst = buffer + dst_size - charsleft;
52  }
53 
54  *dst++ = c;
55 
56  if( c == 0 )
57  break;
58 
59  --charsleft;
60  } while( 1 );
61 
62  *chars = dst_size - charsleft;
63  }
64  else
65  {
66  charsleft = *chars;
67  while( charsleft > 0 )
68  {
69  extbytes = __fb_utf8_trailingTb[*src];
70 
71  c = 0;
72  switch( extbytes )
73  {
74  case 5:
75  c += *src++; c <<= 6;
76  case 4:
77  c += *src++; c <<= 6;
78  case 3:
79  c += *src++; c <<= 6;
80  case 2:
81  c += *src++; c <<= 6;
82  case 1:
83  c += *src++; c <<= 6;
84  case 0:
85  c += *src++;
86  }
87 
88  c -= __fb_utf8_offsetsTb[extbytes];
89 
90  if( c > 255 )
91  c = '?';
92 
93  *dst++ = c;
94 
95  if( c == 0 )
96  break;
97 
98  --charsleft;
99  }
100 
101  *chars -= charsleft;
102  }
103 
104  return buffer;
105 }
106 
107 char *fb_hUTF16ToChar( const UTF_16 *src, char *dst, ssize_t *chars )
108 {
109  UTF_16 c;
110  ssize_t charsleft;
111  char *buffer = dst;
112 
113  if( dst == NULL )
114  {
115  ssize_t dst_size = 0;
116  charsleft = 0;
117  do
118  {
119  c = *src++;
120  if( c > 255 )
121  {
122  if( c >= UTF16_SUR_HIGH_START && c <= UTF16_SUR_HIGH_END )
123  ++src;
124  c = '?';
125  }
126 
127  if( charsleft == 0 )
128  {
129  charsleft = 8;
130  dst_size += charsleft;
131  buffer = realloc( buffer, dst_size );
132  dst = buffer + dst_size - charsleft;
133  }
134 
135  *dst++ = c;
136 
137  if( c == 0 )
138  break;
139 
140  --charsleft;
141  } while( 1 );
142 
143  *chars = dst_size - charsleft;
144  }
145  else
146  {
147  charsleft = *chars;
148  while( charsleft > 0 )
149  {
150  c = *src++;
151  if( c > 255 )
152  {
153  if( c >= UTF16_SUR_HIGH_START && c <= UTF16_SUR_HIGH_END )
154  ++src;
155  c = '?';
156  }
157 
158  *dst++ = c;
159 
160  if( c == 0 )
161  break;
162 
163  --charsleft;
164  }
165 
166  *chars -= charsleft;
167  }
168 
169  return buffer;
170 }
171 
172 char *fb_hUTF32ToChar( const UTF_32 *src, char *dst, ssize_t *chars )
173 {
174  UTF_32 c;
175  ssize_t charsleft;
176  char *buffer = dst;
177 
178  if( dst == NULL )
179  {
180  ssize_t dst_size = 0;
181  charsleft = 0;
182  do
183  {
184  c = *src++;
185  if( c > 255 )
186  c = '?';
187 
188  if( charsleft == 0 )
189  {
190  charsleft = 8;
191  dst_size += charsleft;
192  buffer = realloc( buffer, dst_size );
193  dst = buffer + dst_size - charsleft;
194  }
195 
196  *dst++ = c;
197 
198  if( c == 0 )
199  break;
200 
201  --charsleft;
202  } while( 1 );
203 
204  *chars = dst_size - charsleft;
205  }
206  else
207  {
208  charsleft = *chars;
209  while( charsleft > 0 )
210  {
211  c = *src++;
212  if( c > 255 )
213  c = '?';
214 
215  *dst++ = c;
216 
217  if( c == 0 )
218  break;
219 
220  --charsleft;
221  }
222 
223  *chars -= charsleft;
224  }
225 
226  return buffer;
227 }
228 
229 char *fb_UTFToChar( FB_FILE_ENCOD encod, const void *src, char *dst, ssize_t *chars )
230 {
231  switch( encod )
232  {
233  case FB_FILE_ENCOD_UTF8:
234  return fb_hUTF8ToChar( src, dst, chars );
235 
236  case FB_FILE_ENCOD_UTF16:
237  return fb_hUTF16ToChar( src, dst, chars );
238 
239  case FB_FILE_ENCOD_UTF32:
240  return fb_hUTF32ToChar( src, dst, chars );
241 
242  default:
243  return NULL;
244  }
245 
246 }