use non-zero data
[tridge/junkcode.git] / iconv_speed.c
1 #include <stdio.h>
2 #include <iconv.h>
3 #include <errno.h>
4 #include <sys/time.h>
5
6 struct timeval tp1,tp2;
7
8 static void start_timer()
9 {
10         gettimeofday(&tp1,NULL);
11 }
12
13 static double end_timer()
14 {
15         gettimeofday(&tp2,NULL);
16         return((tp2.tv_sec - tp1.tv_sec) + 
17                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
18 }
19
20 static size_t utf8_pull(char **inbuf, size_t *inbytesleft,
21                          char **outbuf, size_t *outbytesleft)
22 {
23         while (*inbytesleft >= 1 && *outbytesleft >= 2) {
24                 unsigned char *c = (unsigned char *)*inbuf;
25                 unsigned char *uc = (unsigned char *)*outbuf;
26                 int len = 1;
27
28                 if ((c[0] & 0x80) == 0) {
29                         uc[0] = c[0];
30                         uc[1] = 0;
31                 } else if ((c[0] & 0xf0) == 0xe0) {
32                         if (*inbytesleft < 3) {
33                                 goto badseq;
34                         }
35                         uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF);
36                         uc[0] = (c[1]<<6) | (c[2]&0x3f);
37                         len = 3;
38                 } else if ((c[0] & 0xe0) == 0xc0) {
39                         if (*inbytesleft < 2) {
40                                 goto badseq;
41                         }
42                         uc[1] = (c[0]>>2) & 0x7;
43                         uc[0] = (c[0]<<6) | (c[1]&0x3f);
44                         len = 2;
45                 }
46
47                 (*inbuf)  += len;
48                 (*inbytesleft)  -= len;
49                 (*outbytesleft) -= 2;
50                 (*outbuf) += 2;
51         }
52
53         if (*inbytesleft > 0) {
54                 errno = E2BIG;
55                 return -1;
56         }
57         
58         return 0;
59
60 badseq:
61         errno = EINVAL;
62         return -1;
63 }
64
65 static size_t utf8_push(char **inbuf, size_t *inbytesleft,
66                          char **outbuf, size_t *outbytesleft)
67 {
68         while (*inbytesleft >= 2 && *outbytesleft >= 1) {
69                 unsigned char *c = (unsigned char *)*outbuf;
70                 unsigned char *uc = (unsigned char *)*inbuf;
71                 int len=1;
72
73                 if ((uc[1] & 0xf8) == 0xd8) {
74                         if (*outbytesleft < 3) {
75                                 goto toobig;
76                         }
77                         c[0] = 0xed;
78                         c[1] = 0x9f;
79                         c[2] = 0xbf;
80                         len = 3;
81                 } else if (uc[1] & 0xf8) {
82                         if (*outbytesleft < 3) {
83                                 goto toobig;
84                         }
85                         c[0] = 0xe0 | (uc[1]>>4);
86                         c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6);
87                         c[2] = 0x80 | (uc[0]&0x3f);
88                         len = 3;
89                 } else if (uc[1] | (uc[0] & 0x80)) {
90                         if (*outbytesleft < 2) {
91                                 goto toobig;
92                         }
93                         c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6);
94                         c[1] = 0x80 | (uc[0]&0x3f);
95                         len = 2;
96                 } else {
97                         c[0] = uc[0];
98                 }
99
100
101                 (*outbuf)[0] = (*inbuf)[0];
102                 (*inbytesleft)  -= 2;
103                 (*outbytesleft) -= len;
104                 (*inbuf)  += 2;
105                 (*outbuf) += len;
106         }
107
108         if (*inbytesleft == 1) {
109                 errno = EINVAL;
110                 return -1;
111         }
112
113         if (*inbytesleft > 1) {
114                 errno = E2BIG;
115                 return -1;
116         }
117         
118         return 0;
119
120 toobig:
121         errno = E2BIG;
122         return -1;
123 }
124
125
126
127
128 int main(int argc, char *argv[])
129 {
130         iconv_t cd;
131         char *test_string, *buf1, *buf2;
132         int buflen, string_len;
133         int i;
134         int len1, len2;
135
136         cd = iconv_open("UCS2", argv[1]);
137         test_string = argv[2];
138
139         string_len = strlen(test_string);
140         buflen = strlen(test_string)*5;
141         buf1 = malloc(buflen);
142         buf2 = malloc(buflen);
143
144         start_timer();
145
146         for (i=0; end_timer() < 1; i++) {
147                 char *p = test_string;
148                 char *q = buf1;
149                 size_t inbytes = string_len;
150                 size_t outbytes = buflen;
151
152                 iconv(cd, &p, &inbytes, &q, &outbytes);
153                 len1 = buflen - outbytes;
154
155         }
156
157         printf("iconv: %g ops/sec\n", i/end_timer());
158
159         start_timer();
160
161         for (i=0; end_timer() < 1; i++) {
162                 char *p = test_string;
163                 char *q = buf2;
164                 size_t inbytes = string_len;
165                 size_t outbytes = buflen;
166
167                 utf8_pull(&p, &inbytes, &q, &outbytes);
168                 len2 = buflen - outbytes;               
169         }
170
171         printf("internal: %g ops/sec\n", i/end_timer());
172         printf("string_len=%d len1=%d len2=%d\n", string_len, len1, len2);
173
174         if (len1 != len2 || memcmp(buf1, buf2, len1) != 0) {
175                 printf("results DIFFER! (%10.10s) (%10.10s)\n",
176                        buf1, buf2);
177         }
178
179         return 0;
180 }