-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathiconv_wrapped.c
78 lines (66 loc) · 1.85 KB
/
iconv_wrapped.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
#include <stdbool.h>
#include <iconv.h>
#include "_iconv_wrapped.c"
/* iconv_wrapped.c - wrapper around system iconv(3) calls
*
* Use this if you want to add cp932 support to your existing iconv(3)
* implementation.
*
* To be able to use this, your linker needs to support the --wrap option.
* Example usage (gcc):
* gcc someprogramobj1.o someprogramobj2.o iconv_wrapped.o \
* -Wl,--wrap=iconv -Wl,--wrap=iconv_open -Wl,--wrap=iconv_close \
* -o someprogram
*/
size_t __real_iconv(iconv_t cd, char **restrict inbuf, size_t *restrict inleft, char **restrict outbuf, size_t *restrict outleft);
iconv_t __real_iconv_open(const char *to, const char *from);
int __real_iconv_close(iconv_t cd);
struct sjconv_state {
union {
struct sjc_sjconv_state *sjc;
iconv_t real;
} cd;
bool is_sjconv;
};
size_t
__wrap_iconv(struct sjconv_state *s, char **restrict inbuf, size_t *restrict inleft, char **restrict outbuf, size_t *restrict outleft)
{
if(s->is_sjconv)
return sjc_iconv(s->cd.sjc, inbuf, inleft, outbuf, outleft);
else
return __real_iconv(s->cd.real, inbuf, inleft, outbuf, outleft);
}
iconv_t
__wrap_iconv_open(const char *to, const char *from)
{
struct sjconv_state *s = malloc(sizeof *s);
iconv_t cd = __real_iconv_open(to, from);
if(cd != (iconv_t)-1) {
s->is_sjconv = false;
s->cd.real = cd;
return s;
}
/* TODO: try converting to utf-8 and then to the target encoding for wider support? */
struct sjc_sjconv_state *scd = sjc_iconv_open(to, from);
if(scd != (struct sjc_sjconv_state *)-1) {
s->is_sjconv = true;
s->cd.sjc = scd;
return s;
}
free(s);
return (iconv_t)-1;
}
int
__wrap_iconv_close(struct sjconv_state *s)
{
int ret;
if(s->is_sjconv) {
if((ret = sjc_iconv_close(s->cd.sjc)) != 0)
return ret;
} else {
if((ret = __real_iconv_close(s->cd.real)) != 0)
return ret;
}
free(s);
return 0;
}