-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathutf8.c
159 lines (140 loc) · 4.33 KB
/
utf8.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* Copyright (C) 2008 Huang Guan
* Copyright (C) 2011 iBoxpay.com inc.
*
* $Id$
*
* Description: This file mainly includes the functions about utf8
*
* History:
* 2008-7-10 13:31:57 Created.
* 2011-12-28 Format the code style, and add comments by Lytsing
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef __WIN32__
#include <windows.h>
#else
#include <iconv.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <memory.h>
#include "utf8.h"
#ifdef __WIN32__
void utf8_to_gb(const char* src, char* dst, int len)
{
int ret = 0;
WCHAR* strA;
int i= MultiByteToWideChar(CP_UTF8, 0, src, -1, NULL, 0);
if (i <= 0) {
printf("ERROR.");
return;
}
strA = (WCHAR*)malloc(i * 2);
MultiByteToWideChar(CP_UTF8, 0, src, -1, strA, i);
i = WideCharToMultiByte(CP_ACP, 0, strA, -1, NULL, 0, NULL, NULL);
if (len >= i) {
ret = WideCharToMultiByte(CP_ACP, 0, strA, -1, dst, i, NULL, NULL);
dst[i] = 0;
}
if (ret <= 0) {
free(strA);
return;
}
free( strA );
}
void gb_to_utf8(const char* src, char* dst, int len)
{
int ret = 0;
WCHAR* strA;
int i= MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
if (i <= 0) {
printf("ERROR.");
return;
}
strA = (WCHAR*)malloc(i * 2);
MultiByteToWideChar(CP_ACP, 0, src, -1, strA, i);
i = WideCharToMultiByte(CP_UTF8, 0, strA, -1, NULL, 0, NULL, NULL);
if (len >= i) {
ret = WideCharToMultiByte(CP_UTF8, 0, strA, -1, dst, i, NULL, NULL);
dst[i] = 0;
}
if (ret <= 0) {
free(strA);
return;
}
free(strA);
}
#else //Linux
// starkwong: In iconv implementations, inlen and outlen should be type of size_t not uint, which is different in length on Mac
void utf8_to_gb(const char* src, char* dst, int len)
{
int ret = 0;
size_t inlen = strlen(src) + 1;
size_t outlen = len;
// duanqn: The iconv function in Linux requires non-const char *
// So we need to copy the source string
char* inbuf = (char *)malloc(len);
char* inbuf_hold = inbuf; // iconv may change the address of inbuf
// so we use another pointer to keep the address
memcpy(inbuf, src, len);
char* outbuf = dst;
iconv_t cd;
cd = iconv_open("GBK", "UTF-8");
if (cd != (iconv_t)-1) {
ret = iconv(cd, &inbuf, &inlen, &outbuf, &outlen);
if (ret != 0) {
printf("iconv failed err: %s\n", strerror(errno));
}
iconv_close(cd);
}
free(inbuf_hold); // Don't pass in inbuf as it may have been modified
}
void gb_to_utf8(const char* src, char* dst, int len)
{
int ret = 0;
size_t inlen = strlen(src) + 1;
size_t outlen = len;
// duanqn: The iconv function in Linux requires non-const char *
// So we need to copy the source string
char* inbuf = (char *)malloc(len);
char* inbuf_hold = inbuf; // iconv may change the address of inbuf
// so we use another pointer to keep the address
memcpy(inbuf, src, len);
char* outbuf2 = NULL;
char* outbuf = dst;
iconv_t cd;
// starkwong: if src==dst, the string will become invalid during conversion since UTF-8 is 3 chars in Chinese but GBK is mostly 2 chars
if (src == dst) {
outbuf2 = (char*)malloc(len);
memset(outbuf2, 0, len);
outbuf = outbuf2;
}
cd = iconv_open("UTF-8", "GBK");
if (cd != (iconv_t)-1) {
ret = iconv(cd, &inbuf, &inlen, &outbuf, &outlen);
if (ret != 0)
printf("iconv failed err: %s\n", strerror(errno));
if (outbuf2 != NULL) {
strcpy(dst, outbuf2);
free(outbuf2);
}
iconv_close(cd);
}
free(inbuf_hold); // Don't pass in inbuf as it may have been modified
}
#endif