1 /*
2 * unicode.c
3 *
4 * $Id$
5 *
6 * ODBC unicode functions
7 *
8 * The iODBC driver manager.
9 *
10 * Copyright (C) 1996-2021 OpenLink Software <iodbc@openlinksw.com>
11 * All Rights Reserved.
12 *
13 * This software is released under the terms of either of the following
14 * licenses:
15 *
16 * - GNU Library General Public License (see LICENSE.LGPL)
17 * - The BSD License (see LICENSE.BSD).
18 *
19 * Note that the only valid version of the LGPL license as far as this
20 * project is concerned is the original GNU Library General Public License
21 * Version 2, dated June 1991.
22 *
23 * While not mandated by the BSD license, any patches you make to the
24 * iODBC source code may be contributed back into the iODBC project
25 * at your discretion. Contributions will benefit the Open Source and
26 * Data Access community as a whole. Submissions may be made at:
27 *
28 * http://www.iodbc.org
29 *
30 *
31 * GNU Library Generic Public License Version 2
32 * ============================================
33 * This library is free software; you can redistribute it and/or
34 * modify it under the terms of the GNU Library General Public
35 * License as published by the Free Software Foundation; only
36 * Version 2 of the License dated June 1991.
37 *
38 * This library is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 * Library General Public License for more details.
42 *
43 * You should have received a copy of the GNU Library General Public
44 * License along with this library; if not, write to the Free
45 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
46 *
47 *
48 * The BSD License
49 * ===============
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in
58 * the documentation and/or other materials provided with the
59 * distribution.
60 * 3. Neither the name of OpenLink Software Inc. nor the names of its
61 * contributors may be used to endorse or promote products derived
62 * from this software without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
65 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
66 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
67 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
68 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
69 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
70 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
71 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
72 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
73 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
74 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75 */
76
77 #define UNICODE
78
79 #include <iodbc.h>
80
81 #include <sql.h>
82 #include <sqlext.h>
83 #include <sqltypes.h>
84
85 #include <stdlib.h>
86 #include <string.h>
87
88 #ifdef WIN32
89 #if _MSC_VER < 1300
90 #include <ansiapi.h>
91 #endif
92 #include <stringapiset.h>
93 #endif
94
95 #include "unicode.h"
96
97
98 #ifndef UNICHAR_DEFINED
99 #define UNICHAR_DEFINED
100 typedef int unichar; /*!< 31-bit unicode values, negative ones are invalid */
101 #endif
102
103 #define UNICHAR_EOD ((unichar)(-2)) /*!< End of source buffer reached, no data to convert */
104 #define UNICHAR_NO_DATA ((unichar)(-3)) /*!< Source buffer is too short, but nonempty (contains part of a char) */
105 #define UNICHAR_NO_ROOM ((unichar)(-4)) /*!< Target buffer is too short */
106 #define UNICHAR_BAD_ENCODING ((unichar)(-5)) /*!< Invalid character decoded from invalid string */
107 #define UNICHAR_OUT_OF_WCHAR ((unichar)(-6)) /*!< The encoded data are valid but the encoded character is out of 16-bit range and will not fit 2-byte wchar_t. */
108
109 typedef const char *__constcharptr;
110
111 static unichar eh_decode_char__UTF16BE (__constcharptr *src_begin_ptr,
112 const char *src_buf_end, ...);
113 static char *eh_encode_char__UTF16BE (unichar char_to_put, char *tgt_buf,
114 char *tgt_buf_end, ...);
115 static unichar eh_decode_char__UTF16LE (__constcharptr *src_begin_ptr,
116 const char *src_buf_end, ...);
117 static char *eh_encode_char__UTF16LE (unichar char_to_put, char *tgt_buf,
118 char *tgt_buf_end, ...);
119
120 static size_t _calc_len_for_utf8 (IODBC_CHARSET charset, void * str,
121 int size);
122 static size_t _wcxtoutf8 (IODBC_CHARSET charset, void * wstr, char * ustr,
123 int size);
124 static size_t _wcxntoutf8 (IODBC_CHARSET charset, void * wstr, char *ustr,
125 int wlen, int size, int * converted);
126 static size_t _utf8towcx (IODBC_CHARSET charset, char * ustr, void * wstr,
127 int size);
128
129 static size_t _WCSLEN(IODBC_CHARSET charset, void *str);
130
131 static size_t dm_UWtoA(wchar_t *src, int ilen, char *dest, int olen);
132 static size_t dm_AtoUW(char *src, int ilen, wchar_t *dest, size_t olen);
133
134 #ifndef MAX
135 # define MAX(X,Y) (X > Y ? X : Y)
136 # define MIN(X,Y) (X < Y ? X : Y)
137 #endif
138
139
140 #if !defined(HAVE_WCSLEN)
141 size_t
wcslen(const wchar_t * wcs)142 wcslen (const wchar_t * wcs)
143 {
144 size_t len = 0;
145
146 while (*wcs++ != L'\0')
147 len++;
148
149 return len;
150 }
151 #endif
152
153
154 #if !defined(HAVE_WCSCPY)
155 wchar_t *
wcscpy(wchar_t * wcd,const wchar_t * wcs)156 wcscpy (wchar_t * wcd, const wchar_t * wcs)
157 {
158 wchar_t *dst = wcd;
159
160 while ((*dst++ = *wcs++) != L'\0')
161 ;
162
163 return wcd;
164 }
165 #endif
166
167
168 #if !defined (HAVE_WCSNCPY)
169 wchar_t *
wcsncpy(wchar_t * wcd,const wchar_t * wcs,size_t n)170 wcsncpy (wchar_t * wcd, const wchar_t * wcs, size_t n)
171 {
172 wchar_t *dst = wcd;
173 size_t len = 0;
174
175 while ( len < n && (*dst++ = *wcs++) != L'\0')
176 len++;
177
178 for (; len < n; len++)
179 *dst++ = L'\0';
180
181 return wcd;
182 }
183 #endif
184
185 #if !defined(HAVE_WCSCHR)
wcschr(const wchar_t * wcs,const wchar_t wc)186 wchar_t* wcschr(const wchar_t *wcs, const wchar_t wc)
187 {
188 do
189 if(*wcs == wc)
190 return (wchar_t*) wcs;
191 while(*wcs++ != L'\0');
192
193 return NULL;
194 }
195 #endif
196
197 #if !defined(HAVE_WCSCAT)
wcscat(wchar_t * dest,const wchar_t * src)198 wchar_t* wcscat(wchar_t *dest, const wchar_t *src)
199 {
200 wchar_t *s1 = dest;
201 const wchar_t *s2 = src;
202 wchar_t c;
203
204 do
205 c = *s1 ++;
206 while(c != L'\0');
207
208 s1 -= 2;
209
210 do
211 {
212 c = *s2 ++;
213 *++s1 = c;
214 }
215 while(c != L'\0');
216
217 return dest;
218 }
219 #endif
220
221 #if !defined(HAVE_WCSCMP)
wcscmp(const wchar_t * s1,const wchar_t * s2)222 int wcscmp (const wchar_t* s1, const wchar_t* s2)
223 {
224 wchar_t c1, c2;
225
226 if (s1 == s2)
227 return 0;
228
229 do
230 {
231 c1 = *s1++;
232 c2 = *s2++;
233 if(c1 == L'\0')
234 break;
235 }
236 while (c1 == c2);
237
238 return c1 - c2;
239 }
240 #endif
241
242
243 #if !defined(HAVE_TOWLOWER)
244
245 #if (defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64)))
246
247 #include <Carbon/Carbon.h>
248
249 wchar_t
towlower(wchar_t wc)250 towlower (wchar_t wc)
251 {
252 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0);
253 UniChar c = (UniChar) wc;
254 wchar_t wcs;
255
256 CFStringAppendCharacters (strRef, &c, 1);
257 CFStringLowercase (strRef, NULL);
258 wcs = CFStringGetCharacterAtIndex (strRef, 0);
259 CFRelease (strRef);
260
261 return wcs;
262 }
263
264 #else
265
266 /* Use dummy function */
267 wchar_t
towlower(wchar_t wc)268 towlower (wchar_t wc)
269 {
270 return wc;
271 }
272
273 #endif /* __APPLE__ */
274 #endif /* !HAVE_TOWLOWER */
275
276
277 #if !defined(HAVE_WCSNCASECMP)
wcsncasecmp(const wchar_t * s1,const wchar_t * s2,size_t n)278 int wcsncasecmp (const wchar_t* s1, const wchar_t* s2, size_t n)
279 {
280 wchar_t c1, c2;
281
282 if (s1 == s2 || n ==0)
283 return 0;
284
285 do
286 {
287 c1 = towlower(*s1++);
288 c2 = towlower(*s2++);
289 if(c1 == L'\0' || c1 != c2)
290 return c1 - c2;
291 } while (--n > 0);
292
293 return c1 - c2;
294 }
295 #endif
296
297
298 /* UTF-16BE */
299
300 static unichar
eh_decode_char__UTF16BE(__constcharptr * src_begin_ptr,const char * src_buf_end,...)301 eh_decode_char__UTF16BE (__constcharptr *src_begin_ptr, const char *src_buf_end, ...)
302 {
303 /* As is in RFC 2781...
304 U' = yyyyyyyyyyxxxxxxxxxx
305 W1 = 110110yyyyyyyyyy
306 W2 = 110111xxxxxxxxxx
307 */
308 unsigned char *src_begin = (unsigned char *)(src_begin_ptr[0]);
309 unsigned char hi, lo, hiaddon, loaddon;
310 unichar acc /* W1 */, accaddon /* W2 */;
311 if (src_begin >= (unsigned char *)src_buf_end)
312 return UNICHAR_EOD;
313 if (src_begin+1 >= (unsigned char *)src_buf_end)
314 return UNICHAR_NO_DATA;
315 hi = src_begin[0];
316 lo = src_begin[1];
317 acc = (hi << 8) | lo;
318 if (0xFFFE == acc)
319 return UNICHAR_BAD_ENCODING; /* Maybe UTF16LE ? */
320 switch (acc & 0xFC00)
321 {
322 case 0xD800:
323 if (src_begin+3 >= (unsigned char *)src_buf_end)
324 return UNICHAR_NO_DATA;
325 hiaddon = src_begin[2];
326 loaddon = src_begin[3];
327 accaddon = (hiaddon << 8) | loaddon;
328 if (0xDC00 != (accaddon & 0xFC00))
329 return UNICHAR_BAD_ENCODING; /* No low-half after hi-half ? */
330 src_begin_ptr[0] += 4;
331 return 0x10000 + (((acc & 0x3FF) << 10) | (accaddon & 0x3FF));
332 case 0xDC00:
333 return UNICHAR_BAD_ENCODING; /* Low-half first ? */
334 default:
335 src_begin_ptr[0] += 2;
336 return acc;
337 }
338 }
339
340
341 static char *
eh_encode_char__UTF16BE(unichar char_to_put,char * tgt_buf,char * tgt_buf_end,...)342 eh_encode_char__UTF16BE (unichar char_to_put, char *tgt_buf, char *tgt_buf_end, ...)
343 {
344 if (char_to_put < 0)
345 return tgt_buf;
346 if (char_to_put & ~0xFFFF)
347 {
348 if (tgt_buf+4 > tgt_buf_end)
349 return (char *)UNICHAR_NO_ROOM;
350 char_to_put -= 0x10000;
351 tgt_buf[0] = (unsigned char)(0xD8 | ((char_to_put >> 18) & 0x03));
352 tgt_buf[1] = (unsigned char)((char_to_put >> 10) & 0xFF);
353 tgt_buf[2] = (unsigned char)(0xDC | ((char_to_put >> 8) & 0x03));
354 tgt_buf[3] = (unsigned char)(char_to_put & 0xFF);
355 return tgt_buf+4;
356 }
357 if (0xD800 == (char_to_put & 0xF800))
358 return tgt_buf;
359 if (tgt_buf+2 > tgt_buf_end)
360 return (char *)UNICHAR_NO_ROOM;
361 tgt_buf[0] = (unsigned char)(char_to_put >> 8);
362 tgt_buf[1] = (unsigned char)(char_to_put & 0xFF);
363 return tgt_buf+2;
364 }
365
366
367 /* UTF-16LE */
368
369 static unichar
eh_decode_char__UTF16LE(__constcharptr * src_begin_ptr,const char * src_buf_end,...)370 eh_decode_char__UTF16LE (__constcharptr *src_begin_ptr, const char *src_buf_end, ...)
371 {
372 /* As is in RFC 2781...
373 U' = yyyyyyyyyyxxxxxxxxxx
374 W1 = 110110yyyyyyyyyy
375 W2 = 110111xxxxxxxxxx
376 */
377 unsigned char *src_begin = (unsigned char *)(src_begin_ptr[0]);
378 unsigned char hi, lo, hiaddon, loaddon;
379 unichar acc /* W1 */, accaddon /* W2 */;
380 if (src_begin >= (unsigned char *)src_buf_end)
381 return UNICHAR_EOD;
382 if (src_begin+1 >= (unsigned char *)src_buf_end)
383 return UNICHAR_NO_DATA;
384 hi = src_begin[1];
385 lo = src_begin[0];
386 acc = (hi << 8) | lo;
387 if (0xFFFE == acc)
388 return UNICHAR_BAD_ENCODING; /* Maybe UTF16BE ? */
389 switch (acc & 0xFC00)
390 {
391 case 0xD800:
392 if (src_begin+3 >= (unsigned char *)src_buf_end)
393 return UNICHAR_NO_DATA;
394 hiaddon = src_begin[3];
395 loaddon = src_begin[2];
396 accaddon = (hiaddon << 8) | loaddon;
397 if (0xDC00 != (accaddon & 0xFC00))
398 return UNICHAR_BAD_ENCODING; /* No low-half after hi-half ? */
399 src_begin_ptr[0] += 4;
400 return 0x10000 + (((acc & 0x3FF) << 10) | (accaddon & 0x3FF));
401 case 0xDC00:
402 return UNICHAR_BAD_ENCODING; /* Low-half first ? */
403 default:
404 src_begin_ptr[0] += 2;
405 return acc;
406 }
407 }
408
409
410 static char *
eh_encode_char__UTF16LE(unichar char_to_put,char * tgt_buf,char * tgt_buf_end,...)411 eh_encode_char__UTF16LE (unichar char_to_put, char *tgt_buf, char *tgt_buf_end, ...)
412 {
413 if (char_to_put < 0)
414 return tgt_buf;
415 if (char_to_put & ~0xFFFF)
416 {
417 if (tgt_buf+4 > tgt_buf_end)
418 return (char *)UNICHAR_NO_ROOM;
419 char_to_put -= 0x10000;
420 tgt_buf[1] = (unsigned char)(0xD8 | ((char_to_put >> 18) & 0x03));
421 tgt_buf[0] = (unsigned char)((char_to_put >> 10) & 0xFF);
422 tgt_buf[3] = (unsigned char)(0xDC | ((char_to_put >> 8) & 0x03));
423 tgt_buf[2] = (unsigned char)(char_to_put & 0xFF);
424 return tgt_buf+4;
425 }
426 if (0xD800 == (char_to_put & 0xF800))
427 return tgt_buf;
428 if (tgt_buf+2 > tgt_buf_end)
429 return (char *)UNICHAR_NO_ROOM;
430 tgt_buf[1] = (unsigned char)(char_to_put >> 8);
431 tgt_buf[0] = (unsigned char)(char_to_put & 0xFF);
432 return tgt_buf+2;
433 }
434
435
436
437 SQLCHAR *
dm_SQL_W2A(SQLWCHAR * inStr,int size)438 dm_SQL_W2A (SQLWCHAR * inStr, int size)
439 {
440 SQLCHAR *outStr = NULL;
441 size_t len;
442
443 if (inStr == NULL)
444 return NULL;
445
446 if (size == SQL_NTS)
447 len = wcslen (inStr);
448 else if (size < 0)
449 return NULL;
450 else
451 len = (size_t)size;
452
453 # ifdef WIN32
454 if ((outStr = (SQLCHAR *) calloc (len * UTF8_MAX_CHAR_LEN + 1, 1)) != NULL)
455 {
456 if (len > 0)
457 OPL_W2A (inStr, outStr, len);
458 outStr[len] = '\0';
459 }
460 #else
461 if ((outStr = (SQLCHAR *) calloc (len * MB_CUR_MAX + 1, 1)) != NULL)
462 {
463 if (len > 0)
464 dm_UWtoA(inStr, len, outStr, len * MB_CUR_MAX);
465 }
466 #endif
467
468 return outStr;
469 }
470
471
472 SQLWCHAR *
dm_SQL_A2W(SQLCHAR * inStr,int size)473 dm_SQL_A2W (SQLCHAR * inStr, int size)
474 {
475 SQLWCHAR *outStr = NULL;
476 size_t len;
477
478 if (inStr == NULL)
479 return NULL;
480
481 if (size == SQL_NTS)
482 len = strlen ((char *) inStr);
483 else if (size < 0)
484 return NULL;
485 else
486 len = (size_t)size;
487
488 if ((outStr = (SQLWCHAR *) calloc (len + 1, sizeof (SQLWCHAR))) != NULL)
489 {
490 if (len > 0)
491 dm_AtoUW(inStr, len, outStr, len);
492 }
493
494 return outStr;
495 }
496
497
498 int
dm_StrCopyOut2_A2W(SQLCHAR * inStr,SQLWCHAR * outStr,SQLSMALLINT size,WORD * result)499 dm_StrCopyOut2_A2W (
500 SQLCHAR * inStr,
501 SQLWCHAR * outStr,
502 SQLSMALLINT size,
503 WORD * result)
504 {
505 size_t length;
506
507 if (!inStr)
508 return -1;
509
510 length = strlen ((char *) inStr);
511
512 if (result)
513 *result = (SQLSMALLINT) length;
514
515 if (!outStr)
516 return 0;
517
518 if (size >= length + 1)
519 {
520 if (length > 0)
521 length = dm_AtoUW(inStr, length, outStr, length);
522
523 outStr[length] = L'\0';
524 return 0;
525 }
526 if (size > 0)
527 {
528 length = dm_AtoUW(inStr, length, outStr, size);
529 outStr[length] = L'\0';
530 }
531 return -1;
532 }
533
534 int
dm_StrCopyOut2_W2A(SQLWCHAR * inStr,SQLCHAR * outStr,SQLSMALLINT size,WORD * result)535 dm_StrCopyOut2_W2A (
536 SQLWCHAR * inStr,
537 SQLCHAR * outStr,
538 SQLSMALLINT size,
539 WORD * result)
540 {
541 size_t length;
542
543 if (!inStr)
544 return -1;
545
546 length = wcslen (inStr);
547
548 if (result)
549 *result = (SQLSMALLINT) length;
550
551 if (!outStr)
552 return 0;
553
554 if (size >= length + 1)
555 {
556 if (length > 0)
557 length = dm_UWtoA(inStr, length, outStr, length);
558
559 outStr[length] = '\0';
560 return 0;
561 }
562 if (size > 0)
563 {
564 length = dm_UWtoA(inStr, length, outStr, size);
565 outStr[length] = '\0';
566 }
567 return -1;
568 }
569
570
571 SQLWCHAR *
dm_strcpy_A2W(SQLWCHAR * destStr,SQLCHAR * sourStr)572 dm_strcpy_A2W (SQLWCHAR * destStr, SQLCHAR * sourStr)
573 {
574 size_t length;
575
576 if (!sourStr || !destStr)
577 return destStr;
578
579 length = strlen ((char *) sourStr);
580
581 if (length > 0)
582 length = dm_AtoUW(sourStr, length, destStr, length);
583
584 destStr[length] = L'\0';
585 return destStr;
586 }
587
588
589 SQLCHAR *
dm_strcpy_W2A(SQLCHAR * destStr,SQLWCHAR * sourStr)590 dm_strcpy_W2A (SQLCHAR * destStr, SQLWCHAR * sourStr)
591 {
592 size_t length;
593
594 if (!sourStr || !destStr)
595 return destStr;
596
597 length = wcslen (sourStr);
598
599 if (length > 0)
600 length = dm_UWtoA(sourStr, length, destStr, length);
601
602 destStr[length] = '\0';
603 return destStr;
604 }
605
606
607 /* encode */
608 #define LEN_FOR_UTF8(Char, Len) \
609 if (Char < 0x80) \
610 { \
611 Len = 1; \
612 } \
613 else if (Char < 0x800) \
614 { \
615 Len = 2; \
616 } \
617 else if (Char < 0x10000) \
618 { \
619 Len = 3; \
620 } \
621 else if (Char < 0x110000) \
622 { \
623 Len = 4; \
624 } \
625 else \
626 { \
627 Len = 1; \
628 }
629
630 #define CONV_TO_UTF8(Char, Len, First) \
631 if (Char < 0x80) \
632 { \
633 Len = 1; \
634 First = 0; \
635 } \
636 else if (Char < 0x800) \
637 { \
638 Len = 2; \
639 First = 0xC0; \
640 } \
641 else if (Char < 0x10000) \
642 { \
643 Len = 3; \
644 First = 0xE0; \
645 } \
646 else if (Char < 0x110000) \
647 { \
648 Len = 4; \
649 First = 0xf0; \
650 } \
651 else \
652 { \
653 Len = 1; \
654 First = 0; \
655 Char = '?'; \
656 }
657
658
659 /* decode */
660 #define UTF8_COMPUTE(Char, Mask, Len) \
661 if (Char < 128) \
662 { \
663 Len = 1; \
664 Mask = 0x7f; \
665 } \
666 else if ((Char & 0xe0) == 0xc0) \
667 { \
668 Len = 2; \
669 Mask = 0x1f; \
670 } \
671 else if ((Char & 0xf0) == 0xe0) \
672 { \
673 Len = 3; \
674 Mask = 0x0f; \
675 } \
676 else if ((Char & 0xf8) == 0xf0) \
677 { \
678 Len = 4; \
679 Mask = 0x07; \
680 } \
681 else \
682 Len = -1;
683
684
685
686 static size_t
_WCHARSIZE(IODBC_CHARSET charset)687 _WCHARSIZE(IODBC_CHARSET charset)
688 {
689 switch(charset)
690 {
691 case CP_UTF8: return 1;
692 case CP_UTF16: return sizeof(ucs2_t);
693 case CP_UCS4: return sizeof(ucs4_t);
694 }
695 }
696
697
698 static size_t
_WCHARSIZE_ALLOC(IODBC_CHARSET charset)699 _WCHARSIZE_ALLOC(IODBC_CHARSET charset)
700 {
701 switch(charset)
702 {
703 case CP_UTF8: return UTF8_MAX_CHAR_LEN;
704 case CP_UTF16: return sizeof(ucs2_t) * 2;
705 case CP_UCS4: return sizeof(ucs4_t);
706 }
707 }
708
709
710 static size_t
_utf16_calc_len_for_utf8(ucs2_t * str,int size)711 _utf16_calc_len_for_utf8 (ucs2_t *str, int size)
712 {
713 size_t len = 0;
714 ucs4_t wc;
715 char *us = (char *) str;
716 char *us_end;
717 size_t utf8_len = 0;
718
719 if (!str)
720 return len;
721
722 us_end = (char *)(str + size);
723
724 while (size > 0)
725 {
726 #ifdef WORDS_BIGENDIAN
727 wc = (ucs4_t) eh_decode_char__UTF16BE((__constcharptr *) &us, us_end);
728 #else
729 wc = (ucs4_t) eh_decode_char__UTF16LE((__constcharptr *) &us, us_end);
730 #endif
731 if (wc == UNICHAR_EOD || wc == UNICHAR_NO_DATA || wc == UNICHAR_BAD_ENCODING)
732 break;
733
734 LEN_FOR_UTF8(wc, utf8_len);
735 len += utf8_len;
736
737 size--;
738 }
739
740 return len;
741 }
742
743 static size_t
_ucs4_calc_len_for_utf8(ucs4_t * str,int size)744 _ucs4_calc_len_for_utf8 (ucs4_t *str, int size)
745 {
746 size_t len = 0;
747 ucs4_t wc;
748 size_t utf8_len = 0;
749
750 if (!str)
751 return len;
752
753 while (size > 0)
754 {
755 wc = *str;
756
757 LEN_FOR_UTF8(wc, utf8_len);
758 len += utf8_len;
759
760 str++;
761 size--;
762 }
763
764 return len;
765 }
766
767
768 static size_t
_calc_len_for_utf8(IODBC_CHARSET charset,void * str,int size)769 _calc_len_for_utf8 (IODBC_CHARSET charset, void * str, int size)
770 {
771 if (!str)
772 return 0;
773
774 if (size == SQL_NTS)
775 size = _WCSLEN (charset, str);
776
777 if (charset == CP_UTF16)
778 return _utf16_calc_len_for_utf8 ((ucs2_t*)str, size);
779 else
780 return _ucs4_calc_len_for_utf8 ((ucs4_t*)str, size);
781 }
782
783
784
785 static size_t
utf8_len(SQLCHAR * p,int size)786 utf8_len (SQLCHAR * p, int size)
787 {
788 size_t len = 0;
789
790 if (!*p)
791 return 0;
792
793 if (size == SQL_NTS)
794 while (*p)
795 {
796 for (p++; (*p & 0xC0) == 0x80; p++)
797 ;
798 len++;
799 }
800 else
801 while (size > 0)
802 {
803 for (p++, size--; (size > 0) && ((*p & 0xC0) == 0x80); p++, size--)
804 ;
805 len++;
806 }
807 return len;
808 }
809
810
811 /*
812 * size - size of buffer for output utf8 string in bytes
813 * return - length of output utf8 string
814 */
815 static size_t
wcstoutf8(wchar_t * wstr,char * ustr,int size_bytes)816 wcstoutf8 (wchar_t *wstr, char *ustr, int size_bytes)
817 {
818 return _wcxtoutf8 (CP_DEF, (void *)wstr, ustr, size_bytes);
819 }
820
821 static size_t
_utf16ntoutf8(ucs2_t * wstr,char * ustr,int wlen,int size_bytes,int * converted)822 _utf16ntoutf8 (ucs2_t *wstr, char *ustr, int wlen, int size_bytes, int *converted)
823 {
824 int len;
825 ucs4_t wc;
826 int first;
827 int i;
828 int count = 0;
829 char *us0 = (char *) wstr;
830 char *us = (char *) wstr;
831 char *us_end;
832 int _converted = 0;
833
834 if (!wstr)
835 return 0;
836
837 us_end = (char *)(wstr + wlen);
838
839 while(_converted < wlen && count < size_bytes)
840 {
841 #ifdef WORDS_BIGENDIAN
842 wc = (ucs4_t) eh_decode_char__UTF16BE((__constcharptr *) &us, us_end);
843 #else
844 wc = (ucs4_t) eh_decode_char__UTF16LE((__constcharptr *) &us, us_end);
845 #endif
846 if (wc == UNICHAR_EOD || wc == UNICHAR_NO_DATA || wc == UNICHAR_BAD_ENCODING)
847 break;
848
849 CONV_TO_UTF8(wc, len, first);
850
851 if (size_bytes - count < len)
852 {
853 if (converted)
854 *converted = _converted;
855 return count;
856 }
857
858 for (i = len - 1; i > 0; --i)
859 {
860 ustr[i] = (wc & 0x3f) | 0x80;
861 wc >>= 6;
862 }
863 ustr[0] = wc | first;
864
865 ustr += len;
866 count += len;
867 _converted = (us - us0) / sizeof(ucs2_t);
868 }
869
870 if (converted)
871 *converted = _converted;
872
873 return count;
874 }
875
876
877 /*
878 * wlen - length of input *wstr string in symbols(for utf8 in bytes)
879 * size - size of buffer ( *ustr string) in bytes
880 * converted - number of converted symbols from *wstr(for utf8 in bytes)
881 *
882 * Return - length of output utf8 string
883 */
884 static size_t
_wcxntoutf8(IODBC_CHARSET charset,void * wstr,char * ustr,int wlen,int size_bytes,int * converted)885 _wcxntoutf8 (
886 IODBC_CHARSET charset,
887 void * wstr,
888 char * ustr,
889 int wlen,
890 int size_bytes,
891 int * converted)
892 {
893 int len;
894 ucs4_t c;
895 int first;
896 int i;
897 int count = 0;
898 int _converted = 0;
899 ucs4_t *u4str = (ucs4_t *)wstr;
900 wchar_t *sstr = (wchar_t *)wstr;
901
902 if (!wstr)
903 return 0;
904
905 if (charset == CP_UTF8)
906 {
907 unsigned char *u8str = (unsigned char*)wstr;
908 int mask;
909
910 while (_converted < wlen && count < size_bytes)
911 {
912 UTF8_COMPUTE(*u8str, mask, len);
913
914 if (size_bytes - count < len)
915 {
916 if (converted)
917 *converted = _converted;
918 return count;
919 }
920
921 for (i = 0; i < len; i++)
922 *ustr++ = *u8str++;
923
924 count += len;
925 _converted+=len;
926 }
927
928 if (converted)
929 *converted = _converted;
930
931 return count;
932 }
933 else if (charset == CP_UTF16)
934 {
935 return _utf16ntoutf8 ((ucs2_t *) wstr, ustr, wlen, size_bytes, converted);
936 }
937 else
938 {
939 while (_converted < wlen && count < size_bytes)
940 {
941 switch(charset)
942 {
943 case CP_UCS4: c = (ucs4_t)*u4str; break;
944 default: c = (ucs4_t)*sstr; break;
945 }
946
947 CONV_TO_UTF8(c, len, first);
948
949 if (size_bytes - count < len)
950 {
951 if (converted)
952 *converted = _converted;
953 return count;
954 }
955
956 for (i = len - 1; i > 0; --i)
957 {
958 ustr[i] = (c & 0x3f) | 0x80;
959 c >>= 6;
960 }
961 ustr[0] = c | first;
962
963 ustr += len;
964 count += len;
965 _converted++;
966
967 switch(charset)
968 {
969 case CP_UCS4: u4str++; break;
970 default: sstr++; break;
971 }
972 }
973
974 if (converted)
975 *converted = _converted;
976
977 return count;
978 }
979 }
980
981
982 /*
983 * size - size of buffer for output utf8 string in bytes
984 * return - length of output utf8 string in bytes
985 */
986 static size_t
_wcxtoutf8(IODBC_CHARSET charset,void * wstr,char * ustr,int size_bytes)987 _wcxtoutf8 (IODBC_CHARSET charset, void * wstr, char * ustr, int size_bytes)
988 {
989 if (!wstr)
990 return 0;
991
992 return _wcxntoutf8 (charset, wstr, ustr, _WCSLEN(charset, wstr), size_bytes, NULL);
993 }
994
995
996 /*
997 * wlen - length of input *wstr string in symbols
998 * size - size of buffer ( *ustr string) in bytes
999 * converted - number of converted symbols from *wstr
1000 *
1001 * Return - length of output utf8 string
1002 */
1003 static size_t
wcsntoutf8(wchar_t * wstr,char * ustr,int wlen,int size,int * converted)1004 wcsntoutf8 (wchar_t *wstr, char *ustr, int wlen, int size,
1005 int *converted)
1006 {
1007 if (!wstr)
1008 return 0;
1009
1010 return _wcxntoutf8 (CP_DEF, (void*)wstr, ustr, wlen, size, converted);
1011 }
1012
1013
1014
1015 static SQLCHAR *
strdup_WtoU8(SQLWCHAR * str)1016 strdup_WtoU8 (SQLWCHAR * str)
1017 {
1018 SQLCHAR *ret;
1019 int len;
1020
1021 if (!str)
1022 return NULL;
1023
1024 len = _calc_len_for_utf8 (CP_DEF, str, SQL_NTS);
1025 if ((ret = (SQLCHAR *) malloc (len + 1)) == NULL)
1026 return NULL;
1027
1028 len = wcstoutf8 (str, (char *)ret, len);
1029 ret[len] = '\0';
1030
1031 return ret;
1032 }
1033
1034
1035 /*
1036 * size - size of buffer for output string in symbols (SQLWCHAR)
1037 * return - length of output SQLWCHAR string
1038 */
1039 static size_t
utf8towcs(char * ustr,SQLWCHAR * wstr,int size)1040 utf8towcs (char *ustr, SQLWCHAR *wstr, int size)
1041 {
1042 return _utf8towcx (CP_DEF, ustr, (void *)wstr, size);
1043 }
1044
1045
1046 /*
1047 * ulen - length of input *ustr string in bytes
1048 * size - size of buffer ( *wstr string) in symbols
1049 * converted - number of converted bytes from *ustr
1050 *
1051 * Return - length of output wcs string
1052 */
1053 static size_t
_utf8ntoutf16(char * ustr,ucs2_t * wstr,int ulen,int size,int * converted)1054 _utf8ntoutf16 (
1055 char * ustr,
1056 ucs2_t * wstr,
1057 int ulen,
1058 int size,
1059 int * converted)
1060 {
1061 int i;
1062 int mask = 0;
1063 int len;
1064 SQLCHAR c;
1065 ucs4_t wc;
1066 int count = 0;
1067 int _converted = 0;
1068 char *rc;
1069 char *us = (char*) wstr;
1070 char *us_end = (char*) (wstr + size);
1071
1072 if (!ustr)
1073 return 0;
1074
1075 while ((_converted < ulen) && (count < size))
1076 {
1077 c = *ustr;
1078 UTF8_COMPUTE (c, mask, len);
1079 if ((len == -1) || (_converted + len > ulen))
1080 {
1081 if (converted)
1082 *converted = _converted;
1083 return count;
1084 }
1085
1086 wc = c & mask;
1087 for (i = 1; i < len; i++)
1088 {
1089 if ((ustr[i] & 0xC0) != 0x80)
1090 {
1091 if (converted)
1092 *converted = _converted;
1093 return count;
1094 }
1095 wc <<= 6;
1096 wc |= (ustr[i] & 0x3F);
1097 }
1098
1099 #ifdef WORDS_BIGENDIAN
1100 rc = eh_encode_char__UTF16BE ((unichar)wc, us, us_end);
1101 #else
1102 rc = eh_encode_char__UTF16LE ((unichar)wc, us, us_end);
1103 #endif
1104 if ((char *)UNICHAR_NO_ROOM == rc)
1105 break;
1106
1107 count += (rc - us) / sizeof(ucs2_t);
1108 us = rc;
1109 ustr += len;
1110 _converted += len;
1111 }
1112 if (converted)
1113 *converted = _converted;
1114 return count;
1115 }
1116
1117
1118 /*
1119 * ulen - length of input *ustr string in bytes
1120 * size - size of buffer ( *wstr string) in symbols
1121 * converted - number of converted bytes from *ustr
1122 *
1123 * Return - length of output wcs string
1124 */
1125 static size_t
_utf8ntowcx(IODBC_CHARSET charset,char * ustr,void * wstr,int ulen,int size,int * converted)1126 _utf8ntowcx (
1127 IODBC_CHARSET charset,
1128 char * ustr,
1129 void * wstr,
1130 int ulen,
1131 int size,
1132 int * converted)
1133 {
1134 int i;
1135 int mask = 0;
1136 int len;
1137 unsigned char c;
1138 ucs4_t wc;
1139 int count = 0;
1140 int _converted = 0;
1141 ucs4_t *u4str = (ucs4_t *)wstr;
1142 char *u8str = (char*)wstr;
1143
1144 if (!ustr)
1145 return 0;
1146
1147 if (charset == CP_UTF16)
1148 return _utf8ntoutf16 (ustr, wstr, ulen, size, converted);
1149
1150 while ((_converted < ulen) && (count < size))
1151 {
1152 c = (unsigned char)*ustr;
1153 UTF8_COMPUTE (c, mask, len);
1154
1155 if ((len == -1) || (_converted + len > ulen))
1156 {
1157 if (converted)
1158 *converted = _converted;
1159 return count;
1160 }
1161
1162 if (charset == CP_UTF8)
1163 {
1164 for (i = 0; i < len; i++)
1165 *u8str++ = *ustr++;
1166
1167 count += len;
1168 _converted += len;
1169 }
1170 else /* CP_UCS4 */
1171 {
1172 wc = c & mask;
1173 for (i = 1; i < len; i++)
1174 {
1175 if ((ustr[i] & 0xC0) != 0x80)
1176 {
1177 if (converted)
1178 *converted = _converted;
1179 return count;
1180 }
1181 wc <<= 6;
1182 wc |= (ustr[i] & 0x3F);
1183 }
1184
1185 *u4str = (ucs4_t)wc;
1186 u4str++;
1187
1188 ustr += len;
1189 count++;
1190 _converted += len;
1191 }
1192 }
1193
1194 if (converted)
1195 *converted = _converted;
1196 return count;
1197 }
1198
1199 /*
1200 * size - size of buffer for output string in symbols
1201 * return - length of output SQLWCHAR string in bytes
1202 */
1203 static size_t
_utf8towcx(IODBC_CHARSET charset,char * ustr,void * wstr,int size)1204 _utf8towcx (IODBC_CHARSET charset, char * ustr, void * wstr, int size)
1205 {
1206 if (!ustr)
1207 return 0;
1208
1209 return _utf8ntowcx (charset, ustr, wstr, strlen(ustr), size, NULL);
1210 }
1211
1212
1213 /*
1214 * ulen - length of input *ustr string in bytes
1215 * size - size of buffer ( *wstr string) in symbols
1216 * converted - number of converted bytes from *ustr
1217 *
1218 * Return - length of output wcs string
1219 */
1220 static size_t
utf8ntowcs(SQLCHAR * ustr,SQLWCHAR * wstr,int ulen,int size,int * converted)1221 utf8ntowcs (
1222 SQLCHAR * ustr,
1223 SQLWCHAR * wstr,
1224 int ulen,
1225 int size,
1226 int * converted)
1227 {
1228 int i;
1229 int mask = 0;
1230 int len;
1231 SQLCHAR c;
1232 SQLWCHAR wc;
1233 int count = 0;
1234 int _converted = 0;
1235
1236 if (!ustr)
1237 return 0;
1238
1239 while ((_converted < ulen) && (count < size))
1240 {
1241 c = (SQLCHAR) *ustr;
1242 UTF8_COMPUTE (c, mask, len);
1243 if ((len == -1) || (_converted + len > ulen))
1244 {
1245 if (converted)
1246 *converted = _converted;
1247 return count;
1248 }
1249
1250 wc = c & mask;
1251 for (i = 1; i < len; i++)
1252 {
1253 if ((ustr[i] & 0xC0) != 0x80)
1254 {
1255 if (converted)
1256 *converted = _converted;
1257 return count;
1258 }
1259 wc <<= 6;
1260 wc |= (ustr[i] & 0x3F);
1261 }
1262 *wstr = wc;
1263 ustr += len;
1264 wstr++;
1265 count++;
1266 _converted += len;
1267 }
1268 if (converted)
1269 *converted = _converted;
1270 return count;
1271 }
1272
1273
1274 static SQLWCHAR *
strdup_U8toW(SQLCHAR * str)1275 strdup_U8toW (SQLCHAR * str)
1276 {
1277 SQLWCHAR *ret;
1278 int len;
1279
1280 if (!str)
1281 return NULL;
1282
1283 len = utf8_len (str, SQL_NTS);
1284 if ((ret = (SQLWCHAR *) malloc ((len + 1) * sizeof (SQLWCHAR))) == NULL)
1285 return NULL;
1286
1287 len = utf8towcs ((char *)str, ret, len);
1288 ret[len] = L'\0';
1289
1290 return ret;
1291 }
1292
1293
1294 SQLCHAR *
dm_SQL_WtoU8(SQLWCHAR * inStr,int size)1295 dm_SQL_WtoU8 (SQLWCHAR * inStr, int size)
1296 {
1297 SQLCHAR *outStr = NULL;
1298 int len;
1299
1300 if (inStr == NULL)
1301 return NULL;
1302
1303 if (size == SQL_NTS)
1304 {
1305 outStr = strdup_WtoU8 (inStr);
1306 }
1307 else
1308 {
1309 len = _calc_len_for_utf8 (CP_DEF, inStr, size);
1310 if ((outStr = (SQLCHAR *) malloc (len + 1)) != NULL)
1311 {
1312 len = wcsntoutf8 (inStr, (char*)outStr, size, len, NULL);
1313 outStr[len] = '\0';
1314 }
1315 }
1316
1317 return outStr;
1318 }
1319
1320
1321 SQLWCHAR *
dm_SQL_U8toW(SQLCHAR * inStr,int size)1322 dm_SQL_U8toW (SQLCHAR * inStr, int size)
1323 {
1324 SQLWCHAR *outStr = NULL;
1325 int len;
1326
1327 if (inStr == NULL)
1328 return NULL;
1329
1330 if (size == SQL_NTS)
1331 {
1332 outStr = strdup_U8toW (inStr);
1333 }
1334 else
1335 {
1336 len = utf8_len (inStr, size);
1337 if ((outStr = (SQLWCHAR *) calloc (len + 1, sizeof (SQLWCHAR))) != NULL)
1338 utf8ntowcs (inStr, outStr, size, len, NULL);
1339 }
1340
1341 return outStr;
1342 }
1343
1344
1345 int
dm_StrCopyOut2_U8toW(SQLCHAR * inStr,SQLWCHAR * outStr,int size,WORD * result)1346 dm_StrCopyOut2_U8toW (
1347 SQLCHAR * inStr,
1348 SQLWCHAR * outStr,
1349 int size,
1350 WORD * result)
1351 {
1352 int length;
1353
1354 if (!inStr)
1355 return -1;
1356
1357 length = utf8_len (inStr, SQL_NTS);
1358
1359 if (result)
1360 *result = (SQLSMALLINT) length;
1361
1362 if (!outStr)
1363 return 0;
1364
1365 if (size >= length + 1)
1366 {
1367 length = utf8towcs ((char *)inStr, outStr, size);
1368 outStr[length] = L'\0';
1369 return 0;
1370 }
1371 if (size > 0)
1372 {
1373 length = utf8towcs ((char *)inStr, outStr, size - 1);
1374 outStr[length] = L'\0';
1375 }
1376 return -1;
1377 }
1378
1379
1380 static size_t
_WCSLEN(IODBC_CHARSET charset,void * str)1381 _WCSLEN(IODBC_CHARSET charset, void *str)
1382 {
1383 size_t len = 0;
1384 ucs4_t *u4str = (ucs4_t *)str;
1385 ucs2_t *u2str = (ucs2_t *)str;
1386
1387 if (!str)
1388 return 0;
1389
1390 switch(charset)
1391 {
1392 case CP_UTF8:
1393 return utf8_len((SQLCHAR *)str, SQL_NTS);
1394 case CP_UTF16:
1395 while (*u2str++ != 0)
1396 len++;
1397 break;
1398 case CP_UCS4:
1399 while (*u4str++ != 0)
1400 len++;
1401 break;
1402 }
1403 return len;
1404 }
1405
1406
1407
1408 /*
1409 * ilen - length of inStr in SQL Ind format
1410 * olen - size of outStr buffer in symbols
1411 * return length of copied data in symbols
1412 */
1413 static size_t
dm_U2toU4(ucs2_t * inStr,int ilen,ucs4_t * outStr,int olen)1414 dm_U2toU4(ucs2_t *inStr, int ilen, ucs4_t *outStr, int olen)
1415 {
1416 size_t n = 0;
1417 char *us = (char *) inStr;
1418 char *us_end = (char *)(inStr + ilen);
1419 ucs4_t wc;
1420 int count = 0;
1421
1422 while(n < ilen)
1423 {
1424 #ifdef WORDS_BIGENDIAN
1425 wc = (ucs4_t) eh_decode_char__UTF16BE((__constcharptr *) &us, us_end);
1426 #else
1427 wc = (ucs4_t) eh_decode_char__UTF16LE((__constcharptr *) &us, us_end);
1428 #endif
1429 if (wc == UNICHAR_EOD || wc == UNICHAR_NO_DATA || wc == UNICHAR_BAD_ENCODING)
1430 break;
1431
1432 if (count + 1 > olen)
1433 break;
1434
1435 *outStr = wc;
1436 n++;
1437 outStr++;
1438 count ++;
1439 }
1440 return count;
1441 }
1442
1443
1444
1445 static size_t
dm_U4toU2(ucs4_t * inStr,int ilen,ucs2_t * outStr,int olen)1446 dm_U4toU2(ucs4_t *inStr, int ilen, ucs2_t *outStr, int olen)
1447 {
1448 size_t n = 0;
1449 char *rc;
1450 char *us = (char*) outStr;
1451 char *us_end = (char*) (outStr + olen);
1452
1453 while (n < ilen && us < us_end)
1454 {
1455 #ifdef WORDS_BIGENDIAN
1456 rc = eh_encode_char__UTF16BE (*inStr, us, us_end);
1457 #else
1458 rc = eh_encode_char__UTF16LE (*inStr, us, us_end);
1459 #endif
1460 if ((char *)UNICHAR_NO_ROOM == rc)
1461 break;
1462
1463 us = rc;
1464 n++;
1465 inStr++;
1466
1467 if (!*inStr)
1468 break;
1469 }
1470 return (us - (char *)outStr) / sizeof(ucs2_t);
1471 }
1472
1473
1474
1475 static size_t
dm_AtoU2(char * src,int ilen,ucs2_t * dest,int olen)1476 dm_AtoU2(char *src, int ilen, ucs2_t *dest, int olen)
1477 {
1478 size_t n = 0;
1479 wchar_t wc;
1480 char *rc;
1481 char *us = (char*) dest;
1482 char *us_end = (char*)(dest + olen);
1483 mbstate_t st;
1484
1485 memset (&st, 0, sizeof (st));
1486
1487 while (n < ilen && us < us_end)
1488 {
1489 size_t sz = mbrtowc (&wc, src, ilen - n, &st);
1490
1491 if (((long) sz) > 0)
1492 {
1493 n += sz - 1;
1494 src += sz - 1;
1495 }
1496 else if (((long) sz) < 0)
1497 {
1498 wc = 0xFFFD;
1499 }
1500
1501 #ifdef WORDS_BIGENDIAN
1502 rc = eh_encode_char__UTF16BE (wc, us, us_end);
1503 #else
1504 rc = eh_encode_char__UTF16LE (wc, us, us_end);
1505 #endif
1506 if ((char *)UNICHAR_NO_ROOM == rc)
1507 break;
1508
1509 us = rc;
1510 n++;
1511 if (!*src)
1512 break;
1513 src++;
1514 }
1515 return (us - (char *)dest) / sizeof(ucs2_t);
1516 }
1517
1518
1519 static size_t
dm_AtoU4(char * src,int ilen,ucs4_t * dest,size_t olen)1520 dm_AtoU4(char *src, int ilen, ucs4_t *dest, size_t olen)
1521 {
1522 size_t n = 0;
1523 wchar_t wc;
1524 ucs4_t *us = dest;
1525 int count = 0;
1526 mbstate_t st;
1527
1528 memset (&st, 0, sizeof (st));
1529
1530 while (n < ilen && count < olen)
1531 {
1532 size_t sz = mbrtowc (&wc, src, ilen - n, &st);
1533
1534 if (((long) sz) > 0)
1535 {
1536 n += sz - 1;
1537 src += sz - 1;
1538 }
1539 else if (((long) sz) < 0)
1540 {
1541 wc = 0xFFFD;
1542 }
1543
1544 *us = wc;
1545 n++;
1546 us++;
1547 count++;
1548 if (!*src)
1549 break;
1550 src++;
1551 }
1552 return count;
1553 }
1554
1555
1556 static size_t
dm_AtoUW(char * src,int ilen,wchar_t * dest,size_t olen)1557 dm_AtoUW(char *src, int ilen, wchar_t *dest, size_t olen)
1558 {
1559 size_t n = 0;
1560 wchar_t wc;
1561 ucs4_t *us = dest;
1562 int count = 0;
1563 mbstate_t st;
1564
1565 memset (&st, 0, sizeof (st));
1566
1567 while (n < ilen && count < olen)
1568 {
1569 size_t sz = mbrtowc (&wc, src, ilen - n, &st);
1570
1571 if (((long) sz) > 0)
1572 {
1573 n += sz - 1;
1574 src += sz - 1;
1575 }
1576 else if (((long) sz) < 0)
1577 {
1578 wc = 0xFFFD;
1579 }
1580
1581 *us = wc;
1582 n++;
1583 us++;
1584 count++;
1585 if (!*src)
1586 break;
1587 src++;
1588 }
1589 return count;
1590 }
1591
1592
1593 static size_t
dm_U2toA(ucs2_t * src,int ilen,char * dest,int olen)1594 dm_U2toA(ucs2_t *src, int ilen, char *dest, int olen)
1595 {
1596 size_t n = 0;
1597 char *us = (char *) src;
1598 char *us_end = (char*)(src + ilen);
1599 wchar_t wc;
1600 mbstate_t st;
1601
1602 if (!*src)
1603 return 0;
1604
1605 while (n < olen)
1606 {
1607 char temp[MB_CUR_MAX];
1608 size_t sz, sz_written = 0;
1609 #ifdef WORDS_BIGENDIAN
1610 wc = eh_decode_char__UTF16BE((__constcharptr *) &us, us_end);
1611 #else
1612 wc = eh_decode_char__UTF16LE((__constcharptr *) &us, us_end);
1613 #endif
1614 if (wc == UNICHAR_EOD || wc == UNICHAR_NO_DATA || wc == UNICHAR_BAD_ENCODING)
1615 break;
1616
1617 memset (&st, 0, sizeof (st));
1618
1619 sz = wcrtomb (temp, wc, &st);
1620 if (((long) sz) > 0)
1621 {
1622 if (sz > olen - n)
1623 break;
1624
1625 memcpy (dest, temp, sz);
1626 n += sz - 1;
1627 dest += sz - 1;
1628 }
1629 else
1630 *dest = '?';
1631
1632 n++;
1633 dest++;
1634 }
1635 return n;
1636 }
1637
1638
1639 static size_t
dm_U4toA(ucs4_t * src,int ilen,char * dest,int olen)1640 dm_U4toA(ucs4_t *src, int ilen, char *dest, int olen)
1641 {
1642 int n = 0;
1643 wchar_t wc;
1644 int count = 0;
1645 mbstate_t st;
1646
1647 if (!*src)
1648 return 0;
1649
1650 while (n < ilen && count < olen)
1651 {
1652 char temp[MB_CUR_MAX];
1653 size_t sz, sz_written = 0;
1654
1655 memset (&st, 0, sizeof (st));
1656
1657 wc = *src;
1658 sz = wcrtomb (temp, wc, &st);
1659
1660 if (((long) sz) > 0)
1661 {
1662 if (sz > olen - count)
1663 break;
1664
1665 memcpy (dest, temp, sz);
1666 count += sz - 1;
1667 dest += sz - 1;
1668 }
1669 else
1670 *dest = '?';
1671
1672 src++;
1673 count++;
1674 n++;
1675 dest++;
1676 }
1677 return n;
1678 }
1679
1680
1681
1682 static size_t
dm_UWtoA(wchar_t * src,int ilen,char * dest,int olen)1683 dm_UWtoA(wchar_t *src, int ilen, char *dest, int olen)
1684 {
1685 int n = 0;
1686 wchar_t wc;
1687 int count = 0;
1688 mbstate_t st;
1689
1690 if (!*src)
1691 return 0;
1692
1693 while (n < ilen && count < olen)
1694 {
1695 char temp[MB_CUR_MAX];
1696 size_t sz, sz_written = 0;
1697
1698 memset (&st, 0, sizeof (st));
1699
1700 wc = *src;
1701 sz = wcrtomb (temp, wc, &st);
1702
1703 if (((long) sz) > 0)
1704 {
1705 if (sz > olen - count)
1706 break;
1707
1708 memcpy (dest, temp, sz);
1709 count += sz - 1;
1710 dest += sz - 1;
1711 }
1712 else
1713 *dest = '?';
1714
1715 src++;
1716 count++;
1717 n++;
1718 dest++;
1719 }
1720 return n;
1721 }
1722
1723
1724
1725 /*
1726 * len - length of inStr in SQL Ind format
1727 * size - size of outStr buffer in bytes
1728 * return length of copied data in bytes
1729 */
1730 int
dm_conv_W2W(void * inStr,int len,void * outStr,int size,IODBC_CHARSET icharset,IODBC_CHARSET ocharset)1731 dm_conv_W2W(void *inStr, int len, void *outStr, int size,
1732 IODBC_CHARSET icharset, IODBC_CHARSET ocharset)
1733 {
1734 int count = 0;
1735 int o_wchar_size = _WCHARSIZE(ocharset);
1736
1737 size /= o_wchar_size;
1738
1739 if (icharset == CP_UTF8)
1740 {
1741 if (len == SQL_NTS)
1742 len = strlen((char*)inStr);
1743
1744 count = _utf8ntowcx(ocharset, (char*)inStr, outStr, len, size, NULL);
1745 return count * o_wchar_size;
1746 }
1747 else if (ocharset == CP_UTF8)
1748 {
1749 if (len == SQL_NTS)
1750 len = (icharset==CP_UTF8)?strlen((char*)inStr):_WCSLEN(icharset, inStr);
1751
1752 return _wcxntoutf8(icharset, inStr, (char*)outStr, len, size, NULL);
1753 }
1754 else
1755 {
1756 if (len == SQL_NTS)
1757 len = _WCSLEN(icharset, inStr);
1758
1759 if (icharset == CP_UTF16)
1760 {
1761 if (ocharset == CP_UCS4)
1762 {
1763 count = dm_U2toU4((ucs2_t *)inStr, len, (ucs4_t *)outStr, size);
1764 return count * o_wchar_size;
1765 }
1766 else
1767 {
1768 ucs2_t *u2i = (ucs2_t *) inStr;
1769 ucs2_t *u2o = (ucs2_t *) outStr;
1770 while(len > 0 && count < size)
1771 {
1772 *u2o = *u2i;
1773 u2o++;
1774 u2i++;
1775 len--;
1776 count++;
1777 }
1778 return count * o_wchar_size;
1779 }
1780 }
1781 else /* CP_UCS4 */
1782 {
1783 if (ocharset == CP_UTF16)
1784 {
1785 count = dm_U4toU2((ucs4_t *)inStr, len, (ucs2_t *)outStr, size);
1786 return count * o_wchar_size;
1787 }
1788 else
1789 {
1790 ucs4_t *u4i = (ucs4_t *) inStr;
1791 ucs4_t *u4o = (ucs4_t *) outStr;
1792 while(len > 0 && count < size)
1793 {
1794 *u4o = *u4i;
1795 u4o++;
1796 u4i++;
1797 len--;
1798 count++;
1799 }
1800 return count * o_wchar_size;
1801 }
1802 }
1803 }
1804 }
1805
1806
1807 /*
1808 * len - length of inStr in SQL Ind format
1809 * size - size of buffer for output string in bytes
1810 * return length of copied data in bytes
1811 */
1812 int
dm_conv_W2A(void * inStr,int inLen,char * outStr,int size,IODBC_CHARSET charset)1813 dm_conv_W2A(void *inStr, int inLen, char *outStr, int size,
1814 IODBC_CHARSET charset)
1815 {
1816 SQLWCHAR wc;
1817 int count = 0;
1818
1819 if (inLen == SQL_NTS)
1820 {
1821 inLen = (charset == CP_UTF8) ? strlen((char*)inStr)
1822 : _WCSLEN(charset, inStr);
1823 }
1824
1825 if (size > 0)
1826 {
1827 if (charset == CP_UTF8)
1828 {
1829 SQLCHAR *u8 = (SQLCHAR *)inStr;
1830 SQLCHAR c;
1831 int len, mask, i;
1832 char temp[MB_CUR_MAX];
1833 mbstate_t st;
1834 size_t rc;
1835
1836 while((c = *u8) && size > 0 && inLen > 0)
1837 {
1838 UTF8_COMPUTE (c, mask, len);
1839 if (len == -1)
1840 return count;
1841
1842 wc = c & mask;
1843 for(i = 1; i < len; i++)
1844 {
1845 if ((u8[i] & 0xC0) != 0x80)
1846 return count;
1847 wc <<= 6;
1848 wc |= (u8[i] & 0x3F);
1849 }
1850
1851 memset (&st, 0, sizeof (st));
1852 rc = wcrtomb (temp, wc, &st);
1853 if (((ssize_t)rc) > 0)
1854 {
1855 rc = MIN(rc, MB_CUR_MAX);
1856 if (rc > size)
1857 break;
1858
1859 memcpy(outStr, temp, rc);
1860 size -= rc -1;
1861 outStr += rc - 1;
1862 count += rc - 1;
1863 }
1864 else if (rc == 0)
1865 {
1866 *outStr = 0;
1867 }
1868 else
1869 {
1870 *outStr = '?';
1871 }
1872
1873 size --;
1874 outStr ++;
1875 count ++;
1876
1877 u8 += len;
1878 inLen -= len;
1879 }
1880 }
1881 else if (charset == CP_UTF16)
1882 {
1883 count = dm_U2toA((ucs2_t *)inStr, inLen, outStr, size);
1884 }
1885 else if (charset == CP_UCS4)
1886 {
1887 count = dm_U4toA((ucs4_t *)inStr, inLen, outStr, size);
1888 }
1889 }
1890 return count;
1891 }
1892
1893
1894 /*
1895 * len - length of inStr in SQL Ind format
1896 * size - size of buffer for output string in bytes
1897 * return length of copied data in bytes
1898 */
1899 int
dm_conv_A2W(char * inStr,int inLen,void * outStr,int size,IODBC_CHARSET charset)1900 dm_conv_A2W(char *inStr, int inLen, void *outStr, int size,
1901 IODBC_CHARSET charset)
1902 {
1903 SQLWCHAR wc;
1904 int count = 0;
1905 int o_wchar_size = _WCHARSIZE(charset);
1906
1907 if (inLen == SQL_NTS)
1908 inLen = strlen(inStr);
1909
1910 if (size > 0)
1911 {
1912 if (charset == CP_UTF8)
1913 {
1914 SQLCHAR *u8 = (SQLCHAR*)outStr;
1915 int len,first,i;
1916 mbstate_t st;
1917
1918 memset (&st, 0, sizeof (st));
1919
1920 while(*inStr && size>0 && inLen > 0)
1921 {
1922 size_t rc;
1923 rc = mbrtowc (&wc, inStr, (size_t)inLen, &st);
1924 if (((ssize_t)rc) > 0)
1925 {
1926 inLen -= rc - 1;
1927 inStr += rc - 1;
1928 }
1929 else if (((ssize_t)rc) < 0)
1930 {
1931 wc = 0xFFFD;
1932 }
1933
1934 CONV_TO_UTF8(wc, len, first);
1935 for(i = len-1; i > 0; --i)
1936 {
1937 u8[i] = (wc & 0x3F) | 0x80;
1938 wc >>= 6;
1939 }
1940 u8[0] = wc | first;
1941 u8 += len;
1942 size -= len;
1943 count += len;
1944 inStr++;
1945 inLen--;
1946 }
1947 }
1948 else if (charset == CP_UTF16)
1949 {
1950 count = dm_AtoU2(inStr, inLen, (ucs2_t *)outStr, size/o_wchar_size);
1951 count *= o_wchar_size;
1952 }
1953 else if (charset == CP_UCS4)
1954 {
1955 count = dm_AtoU4(inStr, inLen, (ucs4_t *)outStr, size/o_wchar_size);
1956 count *= o_wchar_size;
1957 }
1958 }
1959 return count;
1960 }
1961
1962
1963 static void
_SetWCharAt(IODBC_CHARSET charset,void * str,int pos,int ch)1964 _SetWCharAt(IODBC_CHARSET charset, void *str, int pos, int ch)
1965 {
1966 ucs4_t *u4 = (ucs4_t *)str;
1967 ucs2_t *u2 = (ucs2_t *)str;
1968
1969 if (!str)
1970 return;
1971
1972 switch(charset)
1973 {
1974 case CP_UTF8:
1975 {
1976 int i=0;
1977 SQLCHAR *u8str = (SQLCHAR*)str;
1978 while(i < pos)
1979 {
1980 int mask, len;
1981 UTF8_COMPUTE(*u8str, mask, len);
1982 if (len == -1)
1983 break;
1984 u8str += len;
1985 i++;
1986 }
1987 *u8str = (SQLCHAR)ch;
1988 }
1989 break;
1990 case CP_UTF16: u2[pos] = (ucs4_t)ch; break;
1991 case CP_UCS4: u4[pos] = (ucs4_t)ch; break;
1992 }
1993 }
1994
1995
1996 void
DM_strcpy_U8toW(DM_CONV * conv,void * dest,SQLCHAR * sour)1997 DM_strcpy_U8toW (DM_CONV *conv, void *dest, SQLCHAR *sour)
1998 {
1999 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2000 int len;
2001
2002 if (!sour)
2003 return;
2004
2005 if (charset == CP_UTF16 || charset == CP_UCS4)
2006 {
2007 len = utf8_len(sour, SQL_NTS) * _WCHARSIZE(charset);
2008 _utf8towcx(charset, (char *)sour, dest, len);
2009 }
2010 else
2011 strcpy(dest, (char *)sour);
2012 }
2013
2014
2015 size_t
DRV_WCHARSIZE(DM_CONV * conv)2016 DRV_WCHARSIZE(DM_CONV *conv)
2017 {
2018 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2019 return _WCHARSIZE(charset);
2020 }
2021
2022
2023 size_t
DM_WCHARSIZE(DM_CONV * conv)2024 DM_WCHARSIZE(DM_CONV *conv)
2025 {
2026 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2027 return _WCHARSIZE(charset);
2028 }
2029
2030
2031 size_t
DRV_WCHARSIZE_ALLOC(DM_CONV * conv)2032 DRV_WCHARSIZE_ALLOC(DM_CONV *conv)
2033 {
2034 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2035 return _WCHARSIZE_ALLOC(charset);
2036 }
2037
2038
2039 size_t
DM_WCHARSIZE_ALLOC(DM_CONV * conv)2040 DM_WCHARSIZE_ALLOC(DM_CONV *conv)
2041 {
2042 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2043 return _WCHARSIZE_ALLOC(charset);
2044 }
2045
2046 void *
DM_A2W(DM_CONV * conv,SQLCHAR * inStr,int size)2047 DM_A2W(DM_CONV *conv, SQLCHAR * inStr, int size)
2048 {
2049 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2050 SQLWCHAR *outStr = NULL;
2051 ssize_t len;
2052
2053 if (size == SQL_NTS)
2054 len = strlen((char *) inStr);
2055 else
2056 len = size;
2057
2058 if (len < 0)
2059 return NULL;
2060
2061 outStr = (SQLWCHAR *) calloc(len + 1, DM_WCHARSIZE_ALLOC(conv));
2062 if (!outStr)
2063 return NULL;
2064
2065 dm_conv_A2W((char *)inStr, size, outStr, len*DM_WCHARSIZE_ALLOC(conv), charset);
2066 return outStr;
2067 }
2068
2069
2070 static SQLCHAR *
__W2A(IODBC_CHARSET charset,void * inStr,int size)2071 __W2A(IODBC_CHARSET charset, void * inStr, int size)
2072 {
2073 SQLCHAR *outStr = NULL;
2074 ssize_t len;
2075
2076 if (size == SQL_NTS)
2077 len = _WCSLEN(charset, inStr);
2078 else
2079 len = size;
2080
2081 if (len < 0)
2082 return NULL;
2083
2084 outStr = (SQLCHAR *) calloc (len * MB_CUR_MAX + 1, 1);
2085 if (!outStr)
2086 return NULL;
2087
2088 dm_conv_W2A(inStr, size, (char *)outStr, len, charset);
2089 return outStr;
2090 }
2091
2092 SQLCHAR *
DM_W2A(DM_CONV * conv,void * inStr,int size)2093 DM_W2A(DM_CONV *conv, void * inStr, int size)
2094 {
2095 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2096 return __W2A(charset, inStr, size);
2097 }
2098
2099 SQLCHAR *
DRV_W2A(DM_CONV * conv,void * inStr,int size)2100 DRV_W2A(DM_CONV *conv, void * inStr, int size)
2101 {
2102 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2103 return __W2A(charset, inStr, size);
2104 }
2105
2106 void
DM_SetWCharAt(DM_CONV * conv,void * str,int pos,int ch)2107 DM_SetWCharAt(DM_CONV *conv, void *str, int pos, int ch)
2108 {
2109 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2110 _SetWCharAt(charset, str, pos, ch);
2111 }
2112
2113
2114 void
DRV_SetWCharAt(DM_CONV * conv,void * str,int pos,int ch)2115 DRV_SetWCharAt(DM_CONV *conv, void *str, int pos, int ch)
2116 {
2117 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2118 _SetWCharAt(charset, str, pos, ch);
2119 }
2120
2121
2122 SQLWCHAR
DM_GetWCharAt(DM_CONV * conv,void * str,int pos)2123 DM_GetWCharAt(DM_CONV *conv, void *str, int pos)
2124 {
2125 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2126 ucs4_t *u4 = (ucs4_t *)str;
2127 ucs2_t *u2 = (ucs2_t *)str;
2128
2129 if (!str)
2130 return 0;
2131
2132 switch(charset)
2133 {
2134 case CP_UTF8:
2135 {
2136 int mask, len, i=0;
2137 SQLWCHAR wc = 0;
2138 SQLCHAR *u8str = (SQLCHAR*)str;
2139 while(i < pos)
2140 {
2141 UTF8_COMPUTE(*u8str, mask, len);
2142 if (len == -1)
2143 break;
2144 u8str += len;
2145 i++;
2146 }
2147 UTF8_COMPUTE(*u8str, mask, len);
2148 wc = (*u8str)&mask;
2149 for(i=1; i < len; i++)
2150 {
2151 if ((u8str[i] & 0xC0) != 0x80)
2152 return 0;
2153 wc <<= 6;
2154 wc |= (u8str[i] & 0x3F);
2155 }
2156 return wc;
2157 }
2158 case CP_UTF16: return (SQLWCHAR)u2[pos];
2159 case CP_UCS4: return (SQLWCHAR)u4[pos];
2160 }
2161 }
2162
2163
2164 static void *
_WCSCPY(IODBC_CHARSET charset,void * dest,void * sour)2165 _WCSCPY(IODBC_CHARSET charset, void *dest, void *sour)
2166 {
2167 ucs4_t *u4dst = (ucs4_t *)dest;
2168 ucs2_t *u2dst = (ucs2_t *)dest;
2169 ucs4_t *u4src = (ucs4_t *)sour;
2170 ucs2_t *u2src = (ucs2_t *)sour;
2171
2172 switch(charset)
2173 {
2174 case CP_UTF8:
2175 strcpy((char*)dest, (char*)sour);
2176 break;
2177 case CP_UTF16:
2178 while ((*u2dst++ = *u2src++) != 0)
2179 ;
2180 *u2dst = 0;
2181 break;
2182 case CP_UCS4:
2183 while ((*u4dst++ = *u4src++) != 0)
2184 ;
2185 *u4dst = 0;
2186 break;
2187 }
2188 return dest;
2189 }
2190
2191
2192 static void *
_WCSNCPY(IODBC_CHARSET charset,void * dest,void * sour,size_t count)2193 _WCSNCPY(IODBC_CHARSET charset, void *dest, void *sour, size_t count)
2194 {
2195 size_t len = 0;
2196 ucs4_t *u4dst = (ucs4_t *)dest;
2197 ucs2_t *u2dst = (ucs2_t *)dest;
2198 ucs4_t *u4src = (ucs4_t *)sour;
2199 ucs2_t *u2src = (ucs2_t *)sour;
2200
2201 switch(charset)
2202 {
2203 case CP_UTF8:
2204 strncpy((char*)dest, (char*)sour, count);
2205 break;
2206 case CP_UTF16:
2207 while (len < count && (*u2dst++ = *u2src++) != 0)
2208 len++;
2209 if (len < count)
2210 *u2dst = 0;
2211 break;
2212 case CP_UCS4:
2213 while (len < count && (*u4dst++ = *u4src++) != 0)
2214 len++;
2215 if (len < count)
2216 *u4dst = 0;
2217 break;
2218 }
2219 return dest;
2220 }
2221
2222
2223 void *
DM_WCSCPY(DM_CONV * conv,void * dest,void * sour)2224 DM_WCSCPY(DM_CONV *conv, void *dest, void *sour)
2225 {
2226 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2227 return _WCSCPY(charset, dest, sour);
2228 }
2229
2230
2231 void *
DM_WCSNCPY(DM_CONV * conv,void * dest,void * sour,size_t count)2232 DM_WCSNCPY(DM_CONV *conv, void *dest, void *sour, size_t count)
2233 {
2234 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2235 return _WCSNCPY(charset, dest, sour, count);
2236 }
2237
2238
2239 void *
DRV_WCSNCPY(DM_CONV * conv,void * dest,void * sour,size_t count)2240 DRV_WCSNCPY(DM_CONV *conv, void *dest, void *sour, size_t count)
2241 {
2242 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2243 return _WCSNCPY(charset, dest, sour, count);
2244 }
2245
2246
2247 size_t
DM_WCSLEN(DM_CONV * conv,void * str)2248 DM_WCSLEN(DM_CONV *conv, void *str)
2249 {
2250 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2251 return _WCSLEN(charset, str);
2252 }
2253
2254
2255 size_t
DRV_WCSLEN(DM_CONV * conv,void * str)2256 DRV_WCSLEN(DM_CONV *conv, void *str)
2257 {
2258 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2259 return _WCSLEN(charset, str);
2260 }
2261
2262
2263 static SQLCHAR *
__WtoU8(IODBC_CHARSET charset,void * inStr,int size)2264 __WtoU8(IODBC_CHARSET charset, void *inStr, int size)
2265 {
2266 SQLCHAR *outStr = NULL;
2267 int len;
2268
2269 if (inStr == NULL)
2270 return NULL;
2271
2272 len = _calc_len_for_utf8(charset, inStr, size);
2273 if (!(outStr = (SQLCHAR *) calloc (len + 1, sizeof(char))))
2274 return NULL;
2275
2276 if (size == SQL_NTS)
2277 _wcxtoutf8 (charset, inStr, (char *)outStr, len);
2278 else
2279 _wcxntoutf8 (charset, inStr, (char *)outStr, size, len, NULL);
2280
2281 return outStr;
2282 }
2283
2284
2285 SQLCHAR *
DM_WtoU8(DM_CONV * conv,void * inStr,int size)2286 DM_WtoU8(DM_CONV *conv, void *inStr, int size)
2287 {
2288 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2289 return __WtoU8(charset, inStr, size);
2290 }
2291
2292
2293 SQLCHAR *
DRV_WtoU8(DM_CONV * conv,void * inStr,int size)2294 DRV_WtoU8(DM_CONV *conv, void *inStr, int size)
2295 {
2296 IODBC_CHARSET charset = (conv) ? conv->drv_cp : CP_DEF;
2297 return __WtoU8(charset, inStr, size);
2298 }
2299
2300
2301 void *
DM_U8toW(DM_CONV * conv,SQLCHAR * inStr,int size)2302 DM_U8toW(DM_CONV *conv, SQLCHAR *inStr, int size)
2303 {
2304 IODBC_CHARSET charset = (conv) ? conv->dm_cp : CP_DEF;
2305 void *outStr = NULL;
2306 int len = 0;
2307
2308 if (inStr == NULL)
2309 return NULL;
2310
2311 len = utf8_len (inStr, size);
2312 outStr = (void *) calloc (len + 1, _WCHARSIZE_ALLOC(charset));
2313
2314 if (size == SQL_NTS)
2315 _utf8towcx(charset, (char *)inStr, outStr, len);
2316 else
2317 _utf8ntowcx(charset, (char *)inStr, outStr, size, len, NULL);
2318
2319 return outStr;
2320 }
2321
2322
2323 /* drv => dm
2324 *
2325 * size - size of outStr in bytes
2326 * result - length in symbols
2327 * copied - count of copied in bytes
2328 */
2329 int
dm_StrCopyOut2_A2W_d2m(DM_CONV * conv,SQLCHAR * inStr,void * outStr,int size,SQLSMALLINT * result,int * copied)2330 dm_StrCopyOut2_A2W_d2m (DM_CONV *conv, SQLCHAR *inStr,
2331 void *outStr, int size, SQLSMALLINT *result, int *copied)
2332 {
2333 IODBC_CHARSET o_charset = (conv) ? conv->dm_cp : CP_DEF;
2334 int length, count;
2335 int ret = 0;
2336
2337 if (!inStr)
2338 return -1;
2339
2340 length = strlen ((char *) inStr);
2341
2342 if (result)
2343 *result = (SQLSMALLINT) length;
2344
2345 if (!outStr)
2346 return 0;
2347
2348 size -= DM_WCHARSIZE(conv);
2349
2350 if (size <= 0)
2351 return -1;
2352
2353 count = dm_conv_A2W((char *)inStr, SQL_NTS, outStr, size, o_charset);
2354
2355 if (o_charset == CP_UTF16 || o_charset == CP_UCS4)
2356 _SetWCharAt(o_charset, outStr, count/_WCHARSIZE(o_charset), 0);
2357 else
2358 *(char*)(outStr + count) = 0;
2359
2360 if (_WCSLEN(o_charset, outStr) < length)
2361 ret = -1;
2362
2363 if (copied)
2364 *copied = count;
2365
2366 return ret;
2367 }
2368
2369
2370 /* drv => dm */
2371 int
dm_StrCopyOut2_W2A_d2m(DM_CONV * conv,void * inStr,SQLCHAR * outStr,int size,SQLSMALLINT * result,int * copied)2372 dm_StrCopyOut2_W2A_d2m (DM_CONV *conv, void *inStr,
2373 SQLCHAR *outStr, int size, SQLSMALLINT *result, int *copied)
2374 {
2375 IODBC_CHARSET i_charset = (conv) ? conv->drv_cp : CP_DEF;
2376 int length, count;
2377 int ret = 0;
2378
2379 if (!inStr)
2380 return -1;
2381
2382 length = _WCSLEN(i_charset, inStr);
2383
2384 if (result)
2385 *result = (SQLSMALLINT) length;
2386
2387 if (!outStr)
2388 return 0;
2389
2390 size--;
2391
2392 if (size < 0)
2393 return -1;
2394
2395 count = dm_conv_W2A(inStr, SQL_NTS, (char *)outStr, size, i_charset);
2396 outStr[count] = '\0';
2397
2398 if (count < length)
2399 ret = -1;
2400
2401 if (copied)
2402 *copied = count;
2403
2404 return ret;
2405 }
2406
2407
2408 /* dm => drv */
2409 int
dm_StrCopyOut2_W2A_m2d(DM_CONV * conv,void * inStr,SQLCHAR * outStr,int size,SQLSMALLINT * result,int * copied)2410 dm_StrCopyOut2_W2A_m2d (DM_CONV *conv, void *inStr,
2411 SQLCHAR *outStr, int size, SQLSMALLINT *result, int *copied)
2412 {
2413 IODBC_CHARSET i_charset = (conv) ? conv->dm_cp : CP_DEF;
2414 int length, count;
2415 int ret = 0;
2416
2417 if (!inStr)
2418 return -1;
2419
2420 length = _WCSLEN(i_charset, inStr);
2421
2422 if (result)
2423 *result = (SQLSMALLINT) length;
2424
2425 if (!outStr)
2426 return 0;
2427
2428 size--;
2429
2430 if (size < 0)
2431 return -1;
2432
2433 count = dm_conv_W2A(inStr, SQL_NTS, (char *)outStr, size, i_charset);
2434 outStr[count] = '\0';
2435
2436 if (count < length)
2437 ret = -1;
2438
2439 if (copied)
2440 *copied = count;
2441
2442 return ret;
2443 }
2444
2445
2446 /* drv => dm
2447 *
2448 * size - size of outStr in bytes
2449 * result - length in symbols
2450 * copied - count of copied in bytes
2451 */
2452 int
dm_StrCopyOut2_U8toW_d2m(DM_CONV * conv,SQLCHAR * inStr,void * outStr,int size,SQLSMALLINT * result,int * copied)2453 dm_StrCopyOut2_U8toW_d2m (DM_CONV *conv, SQLCHAR *inStr,
2454 void *outStr, int size, SQLSMALLINT *result, int *copied)
2455 {
2456 IODBC_CHARSET o_charset = (conv) ? conv->dm_cp : CP_DEF;
2457 int length;
2458 int ret = 0;
2459 int count = 0;
2460
2461 if (!inStr)
2462 return -1;
2463
2464 length = utf8_len ((SQLCHAR *) inStr, SQL_NTS);
2465
2466 if (result)
2467 *result = (SQLSMALLINT) length;
2468
2469 if (!outStr)
2470 return 0;
2471
2472 size -= _WCHARSIZE(o_charset);
2473
2474 if (size < 0)
2475 return -1;
2476
2477 count = dm_conv_W2W(inStr, SQL_NTS, outStr, size, CP_UTF8, o_charset);
2478
2479 if (o_charset == CP_UTF16 || o_charset == CP_UCS4)
2480 _SetWCharAt(o_charset, outStr, count/_WCHARSIZE(o_charset), 0);
2481 else
2482 *(char*)(outStr + count) = 0;
2483
2484 if (_WCSLEN(o_charset, outStr) < length)
2485 ret = -1;
2486
2487 if (copied)
2488 *copied = count;
2489
2490 return ret;
2491 }
2492
2493
2494
2495 /* drv => dm
2496 *
2497 * size - size of outStr in bytes
2498 * result - length in symbols
2499 * copied - count of copied in bytes
2500 */
2501 int
dm_StrCopyOut2_W2W_d2m(DM_CONV * conv,void * inStr,void * outStr,int size,SQLSMALLINT * result,int * copied)2502 dm_StrCopyOut2_W2W_d2m (DM_CONV *conv, void *inStr,
2503 void *outStr, int size, SQLSMALLINT *result, int *copied)
2504 {
2505 IODBC_CHARSET o_charset = (conv) ? conv->dm_cp : CP_DEF;
2506 IODBC_CHARSET i_charset = (conv) ? conv->drv_cp : CP_DEF;
2507 int length;
2508 int ret = 0;
2509 int count = 0;
2510
2511 if (!inStr)
2512 return -1;
2513
2514 length = _WCSLEN(i_charset, inStr);
2515
2516 if (result)
2517 *result = (SQLSMALLINT) length;
2518
2519 if (!outStr)
2520 return 0;
2521
2522 size -= _WCHARSIZE(o_charset);
2523
2524 if (size <= 0)
2525 return -1;
2526
2527 count = dm_conv_W2W(inStr, SQL_NTS, outStr, size, i_charset, o_charset);
2528
2529 if (o_charset == CP_UTF16 || o_charset == CP_UCS4)
2530 _SetWCharAt(o_charset, outStr, count/_WCHARSIZE(o_charset), 0);
2531 else
2532 *(char*)(outStr + count) = 0;
2533
2534 if (_WCSLEN(o_charset, outStr) < length)
2535 ret = -1;
2536
2537 if (copied)
2538 *copied = count;
2539
2540 return ret;
2541 }
2542
2543
2544 /* dm => drv
2545 *
2546 * size - size of outStr in bytes
2547 * result - length in symbols
2548 * copied - count of copied in bytes
2549 */
2550 int
dm_StrCopyOut2_W2W_m2d(DM_CONV * conv,void * inStr,void * outStr,int size,SQLSMALLINT * result,int * copied)2551 dm_StrCopyOut2_W2W_m2d (DM_CONV *conv, void *inStr,
2552 void *outStr, int size, SQLSMALLINT *result, int *copied)
2553 {
2554 IODBC_CHARSET o_charset = (conv) ? conv->drv_cp : CP_DEF;
2555 IODBC_CHARSET i_charset = (conv) ? conv->dm_cp : CP_DEF;
2556 int length;
2557 int ret = 0;
2558 int count = 0;
2559
2560 if (!inStr)
2561 return -1;
2562
2563 length = _WCSLEN(i_charset, inStr);
2564
2565 if (result)
2566 *result = (SQLSMALLINT) length;
2567
2568 if (!outStr)
2569 return 0;
2570
2571 size -= _WCHARSIZE(o_charset);
2572
2573 if (size <= 0)
2574 return -1;
2575
2576 count = dm_conv_W2W(inStr, SQL_NTS, outStr, size, i_charset, o_charset);
2577
2578 if (o_charset == CP_UTF16 || o_charset == CP_UCS4)
2579 _SetWCharAt(o_charset, outStr, count/_WCHARSIZE(o_charset), 0);
2580 else
2581 *(char*)(outStr + count) = 0;
2582
2583 if (_WCSLEN(o_charset, outStr) < length)
2584 ret = -1;
2585
2586 if (copied)
2587 *copied = count;
2588
2589 return ret;
2590 }
2591
2592
2593 /* drv => dm */
2594 void *
conv_text_d2m(DM_CONV * conv,void * inStr,int size,CONV_DIRECT direct)2595 conv_text_d2m(DM_CONV *conv, void *inStr, int size, CONV_DIRECT direct)
2596 {
2597 IODBC_CHARSET m_charset = (conv) ? conv->dm_cp : CP_DEF;
2598 IODBC_CHARSET d_charset = (conv) ? conv->drv_cp : CP_DEF;
2599 void *outStr = NULL;
2600 int len;
2601
2602 if (inStr == NULL)
2603 return NULL;
2604
2605 if (size == SQL_NTS)
2606 {
2607 if (direct == CD_W2A || direct == CD_W2W)
2608 len = DRV_WCSLEN(conv, inStr);
2609 else
2610 len = strlen ((char *)inStr);
2611 }
2612 else
2613 len = size;
2614
2615 if (len < 0)
2616 return NULL;
2617
2618 if (direct == CD_W2A)
2619 outStr = calloc (len * MB_CUR_MAX + 1, 1);
2620 else
2621 outStr = calloc(len + 1, DM_WCHARSIZE_ALLOC(conv));
2622
2623 if (outStr)
2624 {
2625 if (direct == CD_A2W)
2626 {
2627 dm_conv_A2W((char *)inStr, size, outStr,
2628 len*DM_WCHARSIZE_ALLOC(conv),m_charset);
2629 }
2630 else if (direct == CD_W2A)
2631 {
2632 dm_conv_W2A(inStr, size, (char *)outStr, len, d_charset);
2633 }
2634 else /* CD_W2W */
2635 {
2636 dm_conv_W2W(inStr, size, outStr, len*DM_WCHARSIZE_ALLOC(conv),
2637 d_charset, m_charset);
2638 }
2639 }
2640
2641 return outStr;
2642 }
2643
2644
2645
2646 /* dm => drv */
2647 void *
conv_text_m2d(DM_CONV * conv,void * inStr,int size,CONV_DIRECT direct)2648 conv_text_m2d(DM_CONV *conv, void *inStr, int size, CONV_DIRECT direct)
2649 {
2650 IODBC_CHARSET m_charset = (conv) ? conv->dm_cp : CP_DEF;
2651 IODBC_CHARSET d_charset = (conv) ? conv->drv_cp : CP_DEF;
2652 void *outStr = NULL;
2653 int len;
2654
2655 if (inStr == NULL)
2656 return NULL;
2657
2658 if (size == SQL_NTS)
2659 {
2660 if (direct == CD_W2A || direct == CD_W2W)
2661 len = DM_WCSLEN(conv, inStr);
2662 else
2663 len = strlen ((char *)inStr);
2664 }
2665 else
2666 len = size;
2667
2668 if (len < 0)
2669 return NULL;
2670
2671 if (direct == CD_W2A)
2672 outStr = calloc (len * MB_CUR_MAX + 1, 1);
2673 else
2674 outStr = calloc(len + 1, DRV_WCHARSIZE_ALLOC(conv));
2675
2676 if (outStr)
2677 {
2678 if (direct == CD_A2W)
2679 {
2680 dm_conv_A2W((char *)inStr, size, outStr,
2681 len*DRV_WCHARSIZE_ALLOC(conv), d_charset);
2682 }
2683 else if (direct == CD_W2A)
2684 {
2685 dm_conv_W2A(inStr, size, (char *)outStr, len, m_charset);
2686 }
2687 else /* CD_W2W */
2688 {
2689 dm_conv_W2W(inStr, size, outStr, len*DRV_WCHARSIZE_ALLOC(conv),
2690 m_charset, d_charset);
2691 }
2692 }
2693
2694 return outStr;
2695 }
2696
2697
2698 void *
conv_text_m2d_W2W(DM_CONV * conv,void * inStr,SQLLEN size,SQLLEN * copied)2699 conv_text_m2d_W2W(DM_CONV *conv, void *inStr, SQLLEN size, SQLLEN *copied)
2700 {
2701 IODBC_CHARSET m_charset = (conv) ? conv->dm_cp : CP_DEF;
2702 IODBC_CHARSET d_charset = (conv) ? conv->drv_cp : CP_DEF;
2703 void *outStr = NULL;
2704 int len;
2705 int rc;
2706
2707 if (inStr == NULL)
2708 return NULL;
2709
2710 len = size / DM_WCHARSIZE(conv);
2711
2712 if (len < 0)
2713 return NULL;
2714
2715 outStr = calloc(len + 1, DRV_WCHARSIZE_ALLOC(conv));
2716
2717 if (outStr)
2718 {
2719 rc = dm_conv_W2W(inStr, len, outStr, len*DRV_WCHARSIZE_ALLOC(conv),
2720 m_charset, d_charset);
2721 if (copied)
2722 *copied = rc;
2723 }
2724
2725 return outStr;
2726 }
2727