source: trunk/src/byteplex.c @ 103

Last change on this file since 103 was 103, checked in by cameron, 11 years ago

X8_Buffer<C> to unify 8-bit byteplex classes for ASCII and EBCDIC families.

File size: 9.0 KB
Line 
1/*  byteplex.c - Parallel byte stream module.
2    Copyright (c) 2008, Robert D. Cameron.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6
7*/
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <errno.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include "byteplex.h"
15#include "multiliteral.h"
16#include "bytelex.h"
17
18
19
20/*  Space for sentinels in bytescans of the pseudo-ASCII stream. */
21const int SENTINEL_PACKS = 1;
22
23
24
25template <CodeUnit_Base C>
26X8_Buffer<C>::X8_Buffer() : Byteplex() {
27        /* For 8-bit code units, the input buffer is a also used directly
28           as the pseudo-ASCII buffer; make sure that there is room for
29           sentinels. */
30        src_buffer = simd_new(BYTEPLEX_SIZE/PACKSIZE+SENTINEL_PACKS);
31        x8data = src_buffer;
32        // Set the sentinel for ScanToQuote,ScanWS in reading XML/text decls.
33        ((unsigned char *) x8data)[BYTEPLEX_SIZE] = Ord<C, '"'>::value;
34}
35
36
37template <CodeUnit_Base C>
38X8_Buffer<C>::~X8_Buffer() {
39  simd_delete((SIMD_type *) src_buffer);
40}
41
42U16_Buffer::U16_Buffer()
43        : Byteplex() {
44
45        src_buffer = simd_new((BYTEPLEX_SIZE/PACKSIZE)*2);
46        x16hi = simd_new(BYTEPLEX_SIZE/PACKSIZE);
47        x16lo = simd_new(BYTEPLEX_SIZE/PACKSIZE);
48        x8data = simd_new(BYTEPLEX_SIZE/PACKSIZE+SENTINEL_PACKS);
49        // Set the sentinel for ScanToQuote,ScanWS in reading XML/text decls.
50        ((unsigned char *) x8data)[BYTEPLEX_SIZE] = '"';
51}
52
53U16_Buffer::~U16_Buffer() {
54  simd_delete((SIMD_type *) x16hi);
55  simd_delete((SIMD_type *) x16lo);
56  simd_delete((SIMD_type *) x8data);
57  simd_delete((SIMD_type *) src_buffer);
58}
59
60U16LE_Buffer::U16LE_Buffer()
61        : U16_Buffer() {
62}
63
64U16BE_Buffer::U16BE_Buffer()
65        : U16_Buffer() {
66}
67
68U32_Buffer::U32_Buffer()
69        : Byteplex() {
70
71        src_buffer = simd_new((BYTEPLEX_SIZE/PACKSIZE)*4);
72        x32hh = simd_new(BYTEPLEX_SIZE/PACKSIZE);
73        x32hl = simd_new(BYTEPLEX_SIZE/PACKSIZE);
74        x32lh = simd_new(BYTEPLEX_SIZE/PACKSIZE);
75        x32ll = simd_new(BYTEPLEX_SIZE/PACKSIZE);
76        x8data = simd_new(BYTEPLEX_SIZE/PACKSIZE+SENTINEL_PACKS);
77        x8data = simd_new(BYTEPLEX_SIZE/PACKSIZE+SENTINEL_PACKS);
78        // Set the sentinel for ScanToQuote,ScanWS in reading XML/text decls.
79        ((unsigned char *) x8data)[BYTEPLEX_SIZE] = '"';
80}
81
82U32_Buffer::~U32_Buffer() {
83  simd_delete((SIMD_type *) x32hh);
84  simd_delete((SIMD_type *) x32hl);
85  simd_delete((SIMD_type *) x32lh);
86  simd_delete((SIMD_type *) x32ll);
87  simd_delete((SIMD_type *) x8data);
88  simd_delete((SIMD_type *) src_buffer);
89}
90
91U32LE_Buffer::U32LE_Buffer()
92        : U32_Buffer() {
93}
94
95U32BE_Buffer::U32BE_Buffer()
96        : U32_Buffer() {
97}
98
99U32_2143_Buffer::U32_2143_Buffer()
100        : U32_Buffer() {
101}
102
103U32_3412_Buffer::U32_3412_Buffer()
104        : U32_Buffer() {
105}
106
107
108/* Byteplex methods.
109
110   No byteplexing is required for 8-bit code units; byteplex methods are no-ops.
111
112*/
113
114template <CodeUnit_Base C>
115void X8_Buffer<C>::DoByteplex() {
116        x8data = src_buffer;
117}
118
119
120inline void DoDuplex(BytePack * src_data, int packs_in_buffer,
121                                         BytePack * p0, BytePack * p1) {
122
123        for (int pk = 0; pk < packs_in_buffer; pk++) {
124                BytePack s0 = src_data[2*pk];
125                BytePack s1 = src_data[2*pk+1];
126#if (BYTE_ORDER == LITTLE_ENDIAN)
127                p0[pk] = simd_pack_16_ll(s1, s0);
128                p1[pk] = simd_pack_16_hh(s1, s0);
129#endif
130#if (BYTE_ORDER == BIG_ENDIAN)
131                p0[pk] = simd_pack_16_hh(s0, s1);
132                p1[pk] = simd_pack_16_ll(s0, s1);
133#endif
134        }
135}
136                                         
137void U16LE_Buffer::DoByteplex() {
138        DoDuplex(src_buffer, packs_in_buffer, x16lo, x16hi);
139}
140
141void U16BE_Buffer::DoByteplex() {
142        DoDuplex(src_buffer, packs_in_buffer, x16hi, x16lo);
143}
144
145inline void DoQuadplex(BytePack * src_data, int packs_in_buffer,
146                                BytePack * p0, BytePack * p1, BytePack * p2, BytePack * p3) {
147
148        for (int pk = 0; pk < packs_in_buffer; pk++) {
149                BytePack s0 = src_data[4*pk];
150                BytePack s1 = src_data[4*pk+1];
151                BytePack s2 = src_data[4*pk+2];
152                BytePack s3 = src_data[4*pk+3];
153#if (BYTE_ORDER == LITTLE_ENDIAN)
154                BytePack p02_0 = simd_pack_16_ll(s1, s0);
155                BytePack p13_0 = simd_pack_16_hh(s1, s0);
156                BytePack p02_1 = simd_pack_16_ll(s3, s2);
157                BytePack p13_1 = simd_pack_16_hh(s3, s2);
158                p0[pk] = simd_pack_16_ll(p02_1, p02_0);
159                p1[pk] = simd_pack_16_ll(p13_1, p13_0);
160                p2[pk] = simd_pack_16_hh(p02_1, p02_0);
161                p3[pk] = simd_pack_16_hh(p13_1, p13_0);
162#endif
163#if (BYTE_ORDER == BIG_ENDIAN)
164                BytePack p02_0 = simd_pack_16_hh(s0, s1);
165                BytePack p13_0 = simd_pack_16_ll(s0, s1);
166                BytePack p02_1 = simd_pack_16_hh(s2, s3);
167                BytePack p13_1 = simd_pack_16_ll(s2, s3);
168                p0[pk] = simd_pack_16_hh(p02_0, p02_1);
169                p1[pk] = simd_pack_16_hh(p13_0, p13_1);
170                p2[pk] = simd_pack_16_ll(p02_0, p02_1);
171                p3[pk] = simd_pack_16_ll(p13_0, p13_1);
172#endif
173        }
174}
175
176void U32LE_Buffer::DoByteplex() {
177        DoQuadplex(src_buffer, packs_in_buffer, x32ll, x32lh, x32hl, x32hh);
178}
179
180void U32BE_Buffer::DoByteplex() {
181        DoQuadplex(src_buffer, packs_in_buffer, x32hh, x32hl, x32lh, x32ll);
182}
183
184void U32_2143_Buffer::DoByteplex() {
185        DoQuadplex(src_buffer, packs_in_buffer, x32hl, x32hh, x32ll, x32lh);
186}
187
188void U32_3412_Buffer::DoByteplex() {
189        DoQuadplex(src_buffer, packs_in_buffer, x32lh, x32ll, x32hh, x32hl);
190}
191
192
193/* Pseudo-ASCII stream methods */
194
195template <CodeUnit_Base C>
196void X8_Buffer<C>::PreparePseudoASCII_Stream() {
197        x8data = src_buffer;
198}
199
200void U16_Buffer::PreparePseudoASCII_Stream() {
201        for (int pk = 0; pk < packs_in_buffer; pk++) {
202                x8data[pk] = simd_or(x16lo[pk], 
203                                     simd_andc(simd_const_8(0x80), 
204                                               simd_eq_8(x16hi[pk], simd_const_8(0))));
205        }
206}
207
208void U32_Buffer::PreparePseudoASCII_Stream() {
209        for (int pk = 0; pk < packs_in_buffer; pk++) {
210                BytePack hi = simd_or(simd_or(x32hh[pk], x32hl[pk]), x32lh[pk]);
211                x8data[pk] = simd_or(x32ll[pk], 
212                                     simd_andc(simd_const_8(0x80), 
213                                               simd_eq_8(hi, simd_const_8(0))));
214        }
215}
216
217
218int Byteplex::CopyAndFill(unsigned char * bytes_to_copy, int lgth, int bytes_to_read) {
219        memcpy(src_buffer, bytes_to_copy, lgth);
220        int bytes_read = fread(&((unsigned char *)src_buffer)[lgth], 1, bytes_to_read, infile);
221        return bytes_read;
222}
223
224void Byteplex::Set_limits(int units) {
225        units_in_buffer = units;
226        packs_in_buffer = (units_in_buffer + PACKSIZE -1)/PACKSIZE;
227        //buffer_limit_pos = min(units_in_buffer, BUFFER_SIZE);
228}
229
230template <CodeUnit_Base C>
231void X8_Buffer<C>::InitializeBuffer(unsigned char * src, int lgth){     
232        int byte_advance = BYTEPLEX_SIZE - lgth;       
233        int bytes_read = CopyAndFill(src, lgth, byte_advance);
234        Set_limits(bytes_read + lgth);
235}
236
237void U16_Buffer::InitializeBuffer(unsigned char * src, int lgth){       
238        int byte_advance = BYTEPLEX_SIZE * 2 - lgth;   
239        int bytes_read = CopyAndFill(src, lgth, byte_advance);
240        if (bytes_read % 2 != 0) {
241                printf("Error: Incomplete code unit at end of file.\n");
242                exit(-1);
243        }
244        Set_limits((bytes_read + lgth)/2);
245}
246
247void U32_Buffer::InitializeBuffer(unsigned char * src, int lgth){       
248        int byte_advance = BYTEPLEX_SIZE * 4 - lgth;   
249        int bytes_read = CopyAndFill(src, lgth, byte_advance);
250        if (bytes_read % 4 != 0) {
251                printf("Error: Incomplete code unit at end of file.\n");
252                exit(-1);
253        }
254        Set_limits((bytes_read + lgth)/4);
255}
256
257
258
259template <CodeUnit_Base C>
260void X8_Buffer<C>::AdvanceInputBuffer(int advance_amt){ 
261        int bytes_to_keep = units_in_buffer - advance_amt;     
262        int bytes_read = CopyAndFill(&((unsigned char *)src_buffer)[advance_amt],
263                                        bytes_to_keep, advance_amt);
264        Set_limits(bytes_read + bytes_to_keep);
265}
266
267void U16_Buffer::AdvanceInputBuffer(int advance_amt){   
268        int bytes_to_keep = (units_in_buffer - advance_amt)*2; 
269        int bytes_read = CopyAndFill(&((unsigned char *)src_buffer)[advance_amt*2],
270                                        bytes_to_keep, advance_amt*2);
271        if (bytes_read % 2 != 0) {
272                printf("Error: Incomplete code unit at end of file.\n");
273                exit(-1);
274        }
275        Set_limits((bytes_read + bytes_to_keep)/2);
276}
277
278void U32_Buffer::AdvanceInputBuffer(int advance_amt){   
279        int bytes_to_keep = (units_in_buffer - advance_amt)*4; 
280        int bytes_read = CopyAndFill(&((unsigned char *)src_buffer)[advance_amt*4],
281                                        bytes_to_keep, advance_amt*4);
282        if (bytes_read % 4 != 0) {
283                printf("Error: Incomplete code unit at end of file.\n");
284                exit(-1);
285        }
286        Set_limits((bytes_read + bytes_to_keep)/4);
287}
288
289Byteplex * Byteplex::ByteplexFactory(Entity_Info * e) {
290        Byteplex * b;
291        if (likely(e->code_unit_size == SingleByte)) {
292                if (likely(e->code_unit_base == ASCII)) 
293                        b = new X8_Buffer<ASCII>();
294                else b = new X8_Buffer<EBCDIC>();
295        }
296        else if (likely(e->code_unit_size == DoubleByte)) {
297                if (likely(e->byte_order == BigEndian))
298                        b = new U16BE_Buffer();
299                else b = new U16LE_Buffer();
300        }
301        else switch (e->byte_order) {
302                case BigEndian: b = new U32BE_Buffer(); break;
303                case LittleEndian: b = new U32LE_Buffer(); break;
304                case Unusual_2143: b = new U32_2143_Buffer(); break;
305                case Unusual_3412: b = new U32_3412_Buffer(); break;
306        }       
307        return b;
308}
309
310Byteplex * Byteplex::ByteplexFactory(Entity_Info * e, FILE * inputfile) {
311        Byteplex * b = ByteplexFactory(e);
312        b->infile = inputfile;
313        return b;
314}
315       
316Byteplex * Byteplex::ByteplexFactory(Entity_Info * e, unsigned char * buffer_bytes, int buffer_size) {
317        Byteplex * b = ByteplexFactory(e);
318        memcpy(b->src_buffer, buffer_bytes, buffer_size);
319    printf("buffer_bytes = %s\n", buffer_bytes);
320        b->units_in_buffer = buffer_size / e->code_unit_size;
321        b->packs_in_buffer = (b->units_in_buffer + PACKSIZE -1)/PACKSIZE;
322        return b;
323}
Note: See TracBrowser for help on using the repository browser.