added demo of signal/uid handling feature
[tridge/junkcode.git] / charset.c
1 #include <stdio.h>\r
2 #include <errno.h>\r
3 #include <iconv.h>\r
4 \r
5 typedef unsigned short smb_ucs2_t;\r
6 \r
7 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])\r
8 #define DEBUG(x, s) printf s\r
9 \r
10 static size_t utf8_pull(char **inbuf, size_t *inbytesleft,\r
11                          char **outbuf, size_t *outbytesleft)\r
12 {\r
13         while (*inbytesleft >= 1 && *outbytesleft >= 2) {\r
14                 unsigned char *c = (unsigned char *)*inbuf;\r
15                 unsigned char *uc = (unsigned char *)*outbuf;\r
16                 int len = 1;\r
17 \r
18                 if ((c[0] & 0x80) == 0) {\r
19                         uc[0] = c[0];\r
20                         uc[1] = 0;\r
21                 } else if ((c[0] & 0xf0) == 0xe0) {\r
22                         if (*inbytesleft < 3) {\r
23                                 DEBUG(0,("short utf8 char\n"));\r
24                                 goto badseq;\r
25                         }\r
26                         uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF);\r
27                         uc[0] = (c[1]<<6) | (c[2]&0x3f);\r
28                         len = 3;\r
29                 } else if ((c[0] & 0xe0) == 0xc0) {\r
30                         if (*inbytesleft < 2) {\r
31                                 DEBUG(0,("short utf8 char\n"));\r
32                                 goto badseq;\r
33                         }\r
34                         uc[1] = (c[0]>>2) & 0x7;\r
35                         uc[0] = (c[0]<<6) | (c[1]&0x3f);\r
36                         len = 2;\r
37                 }\r
38 \r
39                 (*inbuf)  += len;\r
40                 (*inbytesleft)  -= len;\r
41                 (*outbytesleft) -= 2;\r
42                 (*outbuf) += 2;\r
43         }\r
44 \r
45         if (*inbytesleft > 0) {\r
46                 errno = E2BIG;\r
47                 return -1;\r
48         }\r
49         \r
50         return 0;\r
51 \r
52 badseq:\r
53         errno = EINVAL;\r
54         return -1;\r
55 }\r
56 \r
57 static size_t utf8_push(char **inbuf, size_t *inbytesleft,\r
58                          char **outbuf, size_t *outbytesleft)\r
59 {\r
60         while (*inbytesleft >= 2 && *outbytesleft >= 1) {\r
61                 unsigned char *c = (unsigned char *)*outbuf;\r
62                 unsigned char *uc = (unsigned char *)*inbuf;\r
63                 int len=1;\r
64 \r
65                 if ((uc[1] & 0xf8) == 0xd8) {\r
66                         if (*outbytesleft < 3) {\r
67                                 DEBUG(0,("short utf8 write\n"));\r
68                                 goto toobig;\r
69                         }\r
70                         c[0] = 0xed;\r
71                         c[1] = 0x9f;\r
72                         c[2] = 0xbf;\r
73                         len = 3;\r
74                 } else if (uc[1] & 0xf8) {\r
75                         if (*outbytesleft < 3) {\r
76                                 DEBUG(0,("short utf8 write\n"));\r
77                                 goto toobig;\r
78                         }\r
79                         c[0] = 0xe0 | (uc[1]>>4);\r
80                         c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6);\r
81                         c[2] = 0x80 | (uc[0]&0x3f);\r
82                         len = 3;\r
83                 } else if (uc[1] | (uc[0] & 0x80)) {\r
84                         if (*outbytesleft < 2) {\r
85                                 DEBUG(0,("short utf8 write\n"));\r
86                                 goto toobig;\r
87                         }\r
88                         c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6);\r
89                         c[1] = 0x80 | (uc[0]&0x3f);\r
90                         len = 2;\r
91                 } else {\r
92                         c[0] = uc[0];\r
93                 }\r
94 \r
95 \r
96                 (*inbytesleft)  -= 2;\r
97                 (*outbytesleft) -= len;\r
98                 (*inbuf)  += 2;\r
99                 (*outbuf) += len;\r
100         }\r
101 \r
102         if (*inbytesleft == 1) {\r
103                 errno = EINVAL;\r
104                 return -1;\r
105         }\r
106 \r
107         if (*inbytesleft > 1) {\r
108                 errno = E2BIG;\r
109                 return -1;\r
110         }\r
111         \r
112         return 0;\r
113 \r
114 toobig:\r
115         errno = E2BIG;\r
116         return -1;\r
117 }\r
118 \r
119 \r
120 \r
121 main()\r
122 {\r
123         smb_ucs2_t s[2] = {0xe4, 0};\r
124         iconv_t cd;\r
125         unsigned char buf[10];\r
126         int i;\r
127         char *inp, *outp;\r
128         int inlen, outlen;\r
129 \r
130         printf("Converting 0x%04x\n", s[0]);\r
131 \r
132         cd = iconv_open("UTF8", "UCS2");\r
133 \r
134         inp = s;\r
135         inlen = 2;\r
136         outp = buf;\r
137         outlen = 10;\r
138 \r
139         utf8_push(&inp, &inlen, &outp, &outlen);\r
140 \r
141         for (i=0;i<10-outlen;i++) {\r
142                 printf("%02x ", buf[i]);\r
143         }\r
144         printf("\n");\r
145 \r
146         inp = s;\r
147         inlen = 2;\r
148         outp = buf;\r
149         outlen = 10;\r
150 \r
151         iconv(cd, &inp, &inlen, &outp, &outlen);\r
152 \r
153         for (i=0;i<10-outlen;i++) {\r
154                 printf("%02x ", buf[i]);\r
155         }\r
156         printf("\n");\r
157 }\r