source: trunk/src/byteplex.c @ 100

Last change on this file since 100 was 100, checked in by lindanl, 11 years ago

Parsers for internal and external entities.

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