source: trunk/src/byteplex.c @ 151

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

Performance test definitions.

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