source: proto/u8u16/template.c @ 653

Last change on this file since 653 was 648, checked in by cameron, 9 years ago

Fix error adjustments for 4-byte sequences

File size: 11.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <stdint.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#define minimum(x,y) ((x) <(y) ?(x) :(y) )
9#include <iostream>
10using namespace std;
11
12#include "../lib/lib_simd.h"
13#include "../lib/block_carry.h"
14#include "../lib/perflib/perfsec.h"
15#include "../lib/s2p.h"
16#include "../lib/p2s.h"
17
18typedef SIMD_type BytePack;
19typedef SIMD_type BitBlock;
20
21
22// Profiling
23#if (defined(BUFFER_PROFILING) || defined(CODE_CLOCKER))
24  #include "../lib/perflib/perfsec.h"
25#endif
26
27#ifdef BUFFER_PROFILING
28BOM_Table * transcode_timer;
29#endif
30
31#ifdef CODE_CLOCKER
32        #define NUM_EVENTS 1
33        int Events[NUM_EVENTS] = {PAPI_TOT_CYC};
34        //int Events[NUM_EVENTS] = {PAPI_L2_DCM};
35        //int Events[NUM_EVENTS] = {PAPI_TOT_CYC, PAPI_BR_MSP};
36        int cal_size = 20;
37        CC * transcode_timer = new CC(Events,NUM_EVENTS,cal_size);
38#endif
39
40/*===========================================================================*/
41/* UErrorCode */
42/* Extracted from ICU */
43/*===========================================================================*/
44
45typedef enum UErrorCode {
46
47    U_ZERO_ERROR              =  0,     /**< No error, no warning. */
48    U_TRUNCATED_CHAR_FOUND    = 11,     /**< Character conversion: Incomplete input sequence. */
49    U_ILLEGAL_CHAR_FOUND      = 12,     /**< Character conversion: Illegal input sequence/combination of input units. */
50} UErrorCode;
51
52typedef  uint16_t UChar;
53
54
55#define do_right8_shifts(vec, rshift1, rshift2, rshift4) \
56{ BitBlock s2; \
57  vec = simd_sub_8(vec, simd_srli_16(simd_and(rshift1, vec), 1)); \
58  s2 = simd_and(rshift2, vec);\
59  vec = simd_or(simd_srli_16(s2, 2), simd_xor(vec, s2));\
60  s2 = simd_and(rshift4, vec);\
61  vec = simd_or(simd_srli_16(s2, 4), simd_xor(vec, s2));\
62}
63
64static inline void del_info_8(BitBlock &del8_rshift1, BitBlock &del8_rshift2, BitBlock &del8_rshift4, BitBlock delmask){
65        BitBlock del8_trans2;
66        BitBlock del8_trans4;
67        BitBlock shift_bits;
68       
69        del8_rshift1 = simd_xor(simd_slli_8(delmask, 1), simd_slli_8(delmask, 2));
70        del8_rshift1 = simd_xor(del8_rshift1, simd_slli_8(del8_rshift1, 2));
71        del8_rshift1 = simd_xor(del8_rshift1, simd_slli_8(del8_rshift1, 4));
72        /* Transition to even delcount: odd delcount to left, this one deleted. */
73        del8_trans2 = simd_and(del8_rshift1, delmask);
74        /* Odd number of transition positions to left. */
75        del8_rshift2 = simd_xor(simd_slli_8(del8_trans2, 1), simd_slli_8(del8_trans2, 2));
76        del8_rshift2 = simd_xor(del8_rshift2, simd_slli_8(del8_rshift2, 2));
77        del8_rshift2 = simd_xor(del8_rshift2, simd_slli_8(del8_rshift2, 4));
78        /* Transition positions: odd |del2count| to left, this one a transition to even. */
79        del8_trans4 = simd_and(del8_rshift2, del8_trans2);
80        del8_rshift4 = simd_xor(simd_slli_8(del8_trans4, 1), simd_slli_8(del8_trans4, 2));
81        del8_rshift4 = simd_xor(del8_rshift4, simd_slli_8(del8_rshift4, 2));
82        del8_rshift4 = simd_xor(del8_rshift4, simd_slli_8(del8_rshift4, 4));
83        /* Only move bits that are not deleted. */
84        del8_rshift1 = simd_andc(del8_rshift1, delmask);
85        del8_rshift2 = simd_andc(del8_rshift2, delmask);
86        del8_rshift4 = simd_andc(del8_rshift4, delmask);
87        /* Update |del8_rshift2| to apply after |del8_rshift1|. */
88        del8_rshift2 = simd_sub_8(del8_rshift2, simd_srli_16(simd_and(del8_rshift1, del8_rshift2),1));
89        /* Update |del8_rshift4| to apply after |del8_rshift2| and |del8_rshift1|. */
90        del8_rshift4 = simd_sub_8(del8_rshift4, simd_srli_16(simd_and(del8_rshift1, del8_rshift4),1));
91        shift_bits = simd_and(del8_rshift2, del8_rshift4);
92        del8_rshift4 = simd_or(simd_srli_16(shift_bits, 4), simd_xor(del8_rshift4, shift_bits));
93}
94
95
96static inline void del_count(BitBlock delmask, unsigned char *u16_units_per_reg){
97
98        BitBlock delcounts_2;
99        BitBlock delcounts_4;
100        BitBlock delcounts_8;
101
102        delcounts_2 = simd_add_2_lh(delmask, delmask);
103        delcounts_4 = simd_add_4_lh(delcounts_2, delcounts_2);
104        delcounts_8 = simd_add_8_lh(delcounts_4, delcounts_4);
105        sisd_store_unaligned(simd_sub_8(simd_const_8(8), delcounts_8),
106                          (BytePack *) u16_units_per_reg);
107}
108
109
110#define BLOCK_SIZE 128       
111#define BUFFER_SIZE 12800   
112
113void u8u16(UChar ** targetbuf, const UChar * targetlimit, char ** srcbuf, const char * srclimit, UErrorCode * err){
114
115  @decl
116
117  SIMD_type u16l [8];
118  SIMD_type u16h [8];
119
120
121  BytePack U16s[16];
122  BytePack U16h[8];
123  BytePack U16l[8];
124
125  BitBlock EOF_mask;
126
127  BitBlock U8[8];
128
129  int pos = 0;
130
131  bool error_found = false;
132  int err_pos;
133
134  @stream_stmts
135
136       
137    while ((*srcbuf) < srclimit){
138     
139      int u8advance = minimum(srclimit-(*srcbuf),BLOCK_SIZE);
140      if(u8advance < BLOCK_SIZE){
141        EOF_mask = sisd_srl(simd_const_1(1),sisd_from_int(BLOCK_SIZE-u8advance));
142      }
143      else
144        EOF_mask = simd_const_1(1);
145     
146      BytePack * U8pack = (BytePack *) (*srcbuf);
147      U8[0] = sisd_load_unaligned(&U8pack[0]);
148      U8[1] = sisd_load_unaligned(&U8pack[1]);
149      U8[2] = sisd_load_unaligned(&U8pack[2]);
150      U8[3] = sisd_load_unaligned(&U8pack[3]);
151      U8[4] = sisd_load_unaligned(&U8pack[4]);
152      U8[5] = sisd_load_unaligned(&U8pack[5]);
153      U8[6] = sisd_load_unaligned(&U8pack[6]);
154      U8[7] = sisd_load_unaligned(&U8pack[7]); 
155     
156      s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
157      array_bit__0_,array_bit__1_,array_bit__2_,array_bit__3_,array_bit__4_,array_bit__5_,array_bit__6_,array_bit__7_);
158
159      array_bit__0_ &= EOF_mask;
160      array_bit__1_ &= EOF_mask;
161      array_bit__2_ &= EOF_mask;
162      array_bit__3_ &= EOF_mask;
163      array_bit__4_ &= EOF_mask;
164      array_bit__5_ &= EOF_mask;
165      array_bit__6_ &= EOF_mask;
166      array_bit__7_ &= EOF_mask;
167   
168      @block_stmts
169     
170      delmask |= ~EOF_mask;
171      error_found = bitblock_has_bit(error_mask);
172      if (error_found) {
173        int errpos = count_forward_zeroes(error_mask);
174        if (errpos >= u8advance) {
175          *err = U_TRUNCATED_CHAR_FOUND;
176        }
177        else *err = U_ILLEGAL_CHAR_FOUND;
178        BitBlock cutoff_mask = sisd_sfl(simd_const_8(-1), sisd_from_int(errpos));
179        BitBlock errbit = simd_andc(error_mask, sisd_sfli(cutoff_mask, 1));
180        u8advance = errpos;
181        if (bitblock_has_bit(simd_and(strct_u8__scope44_, errbit))) {
182          u8advance -= 3;
183          /* May have already first of a surrogate pair to targetbuf. */
184          if (u8advance == -3) *targetbuf -= 2;
185        }
186        else if (bitblock_has_bit(simd_and(strct_u8__scope43_, errbit))) {
187          u8advance -= 2;
188        }
189        else if (bitblock_has_bit(simd_and(strct_u8__scope33_, errbit))) {
190          u8advance -= 2;
191        }
192        else if (bitblock_has_bit(simd_and(simd_or(strct_u8__scope22_, simd_or(strct_u8__scope32_, strct_u8__scope42_)), errbit))) {
193          u8advance -= 1;
194        }
195        if (u8advance <= 0) {
196          (*srcbuf) += u8advance;
197          return;
198        }
199        delmask |= sisd_sfl(simd_const_8(-1), sisd_from_int(u8advance));
200//      fprintf(stderr, "errpos = %i, u8advance = %i\n", errpos, u8advance);
201      }
202     
203       
204      BitBlock shift1, shift2, shift4;
205      del_info_8(shift1, shift2, shift4, delmask);
206      do_right8_shifts(array_u16lo__0_, shift1, shift2, shift4)
207      do_right8_shifts(array_u16lo__1_, shift1, shift2, shift4)
208      do_right8_shifts(array_u16lo__2_, shift1, shift2, shift4)
209      do_right8_shifts(array_u16lo__3_, shift1, shift2, shift4)
210      do_right8_shifts(array_u16lo__4_, shift1, shift2, shift4)
211      do_right8_shifts(array_u16lo__5_, shift1, shift2, shift4)
212      do_right8_shifts(array_u16lo__6_, shift1, shift2, shift4)
213      do_right8_shifts(array_u16lo__7_, shift1, shift2, shift4)
214      do_right8_shifts(array_u16hi__0_, shift1, shift2, shift4)
215      do_right8_shifts(array_u16hi__1_, shift1, shift2, shift4)
216      do_right8_shifts(array_u16hi__2_, shift1, shift2, shift4)
217      do_right8_shifts(array_u16hi__3_, shift1, shift2, shift4)
218      do_right8_shifts(array_u16hi__4_, shift1, shift2, shift4)
219      do_right8_shifts(array_u16hi__5_, shift1, shift2, shift4)
220      do_right8_shifts(array_u16hi__6_, shift1, shift2, shift4)
221      do_right8_shifts(array_u16hi__7_, shift1, shift2, shift4)
222
223      unsigned char u16_units_per_reg[16];
224     
225      p2s(array_u16lo__0_,array_u16lo__1_,array_u16lo__2_,array_u16lo__3_,array_u16lo__4_,array_u16lo__5_,array_u16lo__6_,array_u16lo__7_,
226                        U16l[0], U16l[1],U16l[2] ,U16l[3] ,U16l[4] ,U16l[5] ,U16l[6] ,U16l[7]);
227      p2s(array_u16hi__0_,array_u16hi__1_,array_u16hi__2_,array_u16hi__3_,array_u16hi__4_,array_u16hi__5_,array_u16hi__6_,array_u16hi__7_,
228                        U16h[0], U16h[1],U16h[2] ,U16h[3] ,U16h[4] ,U16h[5] ,U16h[6] ,U16h[7]);
229      for (int i=0; i<8; i++) {
230        U16s[2*i] = simd_mergel_8(U16l[i], U16h[i]);
231        U16s[2*i+1] = simd_mergeh_8(U16l[i], U16h[i]);
232      }
233       
234      for(int k=0; k<16; k++) u16_units_per_reg[k] = 0;
235      del_count(delmask,u16_units_per_reg);
236
237      for(int j=0; j<16; j++){
238        sisd_store_unaligned(U16s[j],(SIMD_type *) (*targetbuf));
239        *targetbuf += u16_units_per_reg[j];
240      }
241
242      (*srcbuf) += u8advance;
243         
244      if (error_found) return;
245    }
246
247}
248
249
250void do_process(FILE *infile, FILE *outfile) {
251
252  int buf_pos = 0;
253  int bytes_available = 0;
254  int excess_bytes, i;
255  char srcbuf[BUFFER_SIZE+BLOCK_SIZE];
256  char * srclimit;
257  UChar targetbuf[BUFFER_SIZE+BLOCK_SIZE];
258  UChar * targetlimit;
259  UChar * targetbuf_start;
260  UChar * targetbuf_ptr=targetbuf;
261  char * srcbuf_ptr=srcbuf;
262  UErrorCode status;
263 
264  bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
265  srclimit = srcbuf + bytes_available;
266  targetbuf_start = targetbuf;
267
268  while(bytes_available>0){
269
270    PERF_SEC_START(transcode_timer);
271       
272    srcbuf_ptr=srcbuf;
273    targetbuf_ptr=targetbuf;
274
275    u8u16(&targetbuf_ptr, targetlimit, &srcbuf_ptr, srclimit, &status); 
276    excess_bytes = (int) (srclimit - srcbuf_ptr);
277    buf_pos += bytes_available - excess_bytes;
278
279    PERF_SEC_END(transcode_timer, bytes_available - excess_bytes);
280   
281   
282    fwrite(targetbuf_start , sizeof(UChar) ,  targetbuf_ptr - targetbuf_start, outfile );
283   
284    if (status == U_ILLEGAL_CHAR_FOUND) {
285            fclose(infile);
286            fclose(outfile);
287            fprintf(stderr, "Illegal UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
288            exit(-1);
289    }
290    else if (status == U_TRUNCATED_CHAR_FOUND) {
291        for (i = 0; i < excess_bytes; i++) {
292          srcbuf[i] = srcbuf_ptr[i];
293        }
294        bytes_available = fread((void *) &(srcbuf[excess_bytes]), sizeof(char), BUFFER_SIZE-excess_bytes, infile);
295        if (bytes_available == 0) {
296            fclose(infile);
297            fclose(outfile);
298            fprintf(stderr, "EOF with incomplete UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
299            exit(-1);
300        }
301        bytes_available += excess_bytes;
302        srclimit = srcbuf + bytes_available;
303    }
304    else {
305      bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
306      srclimit = srcbuf + bytes_available;
307    }
308  }
309}
310
311
312
313int
314main(int argc, char * argv[]) {
315        char * infilename, * outfilename;       
316        FILE *infile, *outfile;
317
318        if (argc < 2) {
319                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
320                exit(-1);
321        }
322
323        infilename = argv[1];
324        infile = fopen(infilename, "rb");
325        if (!infile) {
326                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
327                exit(-1);
328        }
329       
330        if (argc < 3) outfile = stdout;
331        else {
332                outfilename = argv[2];
333                outfile = fopen(outfilename, "wb");
334                if (!outfile) {
335                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
336                        exit(-1);
337                }
338        }
339
340
341        PERF_SEC_INIT(transcode_timer);
342
343        do_process(infile, outfile);
344       
345        PERF_SEC_DUMP(transcode_timer);
346
347        PERF_SEC_DESTROY(transcode_timer);     
348       
349        fclose(infile);
350        fclose(outfile);
351        return(0);
352}
Note: See TracBrowser for help on using the repository browser.