source: trunk/src/byteplex.c @ 68

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

Parallel Byte Stream Module refactoring

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