Changeset 35


Ignore:
Timestamp:
Feb 10, 2008, 6:08:48 AM (12 years ago)
Author:
cameron
Message:

Charset Architecture: Byteplexing Buffer Factory

Location:
trunk/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/xmlbuffer.c

    r15 r35  
    11/*  xmlbuffer.c - Input buffering for XML entities.
    2     Copyright (c) 2007, Robert D. Cameron.
     2    Copyright (c) 2007, 2008, Robert D. Cameron.
    33    Licensed to the public under the Open Software License 3.0.
    44    Licensed to International Characters, Inc., under the Academic
     
    1313#include <sys/stat.h>
    1414#include "xmlbuffer.h"
    15 
    16 
    17 XML_Buffer::XML_Buffer(char* filename, int pad_bytes) {
    18   int chars_read;
    19   struct stat fileinfo;
    20   stat(filename, &fileinfo);
    21   /* Allocate a buffer big enough to hold the file contents and sentinel,
    22      plus additional space up to the next block boundary. */
    23   alloc_size = fileinfo.st_size + pad_bytes;
    24   ByteBuffer = (unsigned char *) malloc(alloc_size);
    25   if (ByteBuffer == NULL) {
    26       fprintf(stderr, "Error: buffer for %s of size %i cannot be created.\n",
    27               filename, alloc_size);
    28       exit(-1);
    29   }
    30   FILE *infile;
    31   infile = fopen(filename, "rb");
    32   if (!infile) {
    33       fprintf(stderr, "Error: cannot open %s for input.\n", filename);
    34       exit(-1);
    35   }
    36   chars_read = fread(ByteBuffer, 1, fileinfo.st_size, infile);
    37   if (chars_read != fileinfo.st_size) {
    38       fprintf(stderr, "Error: fread returned %i characters, expecting %i.\n",
    39               chars_read, fileinfo.st_size);
    40       exit(-1);
    41   }
    42   buffer_bytes = fileinfo.st_size;
    43   current_pos = 0;
    44 }
    45 
    46 void XML_Buffer::InstallPadding(const unsigned char* pad_string) {
    47   strcpy((char *) &ByteBuffer[buffer_bytes], (char *) pad_string);
    48 }
    49 
    50 int XML_Buffer::PrepareBytes(int position, int bytes_to_prepare) {
    51   int bytes_left = buffer_bytes - position;
    52   current_pos = position;
    53   if (bytes_to_prepare > bytes_left) {
    54     return bytes_left;
    55   }
    56   else {
    57     return bytes_to_prepare;
    58   }
    59 }
    60 
    61 unsigned char * XML_Buffer::BytePtr(int pos) {
    62   return &ByteBuffer[pos];
    63 }
     15#include "multiliteral.h"
     16#include "bytelex.h"
     17#ifdef __i386
     18#include "../lib/sse_simd.h"
     19#endif
     20#ifdef _ARCH_PPC
     21#include "../lib/altivec_simd.h"
     22#endif
     23
     24XML_Buffer_Interface::XML_Buffer_Interface() {}
     25
     26template <CodeUnit_Base C>
     27XML_Buffer<C>::XML_Buffer(BytePack * src, int lgth, int BOM)
     28        : XML_Buffer_Interface() {
     29        ByteBuffer = src;
     30        buffer_bytes = lgth;
     31        BOM_units = BOM;
     32        code_unit_base = C;
     33        current_unit = BOM_units; /* skip the BOM for parsing.*/
     34}
     35
     36Extended_ASCII_8_Buffer::Extended_ASCII_8_Buffer(BytePack * src, int lgth, int BOM)
     37        : XML_Buffer<ASCII>(src, lgth, BOM) {
     38        code_unit_size = SingleByte;
     39        total_blocks = (buffer_bytes + BLOCKSIZE - 1)/BLOCKSIZE;
     40        byte_order = BigEndian;  /* dummy value; byte order irrelevant for single-byte units.*/
     41}
     42
     43EBCDIC_Buffer::EBCDIC_Buffer(BytePack * src, int lgth, int BOM)
     44        : XML_Buffer<EBCDIC>(src, lgth, BOM) {
     45        code_unit_size = SingleByte;
     46        total_blocks = (buffer_bytes + BLOCKSIZE - 1)/BLOCKSIZE;
     47        byte_order = BigEndian;
     48}
     49
     50const int LOOKAHEAD_PACKS = (LOOKAHEAD_POSITIONS - 1)/PACKSIZE + 1;
     51
     52U16_Buffer::U16_Buffer(BytePack * src, int lgth, int BOM)
     53        : XML_Buffer<ASCII>(src, lgth, BOM) {
     54        code_unit_size = DoubleByte;
     55        total_blocks = (buffer_bytes/2 + BLOCKSIZE - 1)/BLOCKSIZE;
     56        if (buffer_bytes % 2 != 0) {
     57                printf("Error: Incomplete code unit at end of file.\n");
     58                exit(-1);
     59        }
     60        int byte_stream_size = total_blocks * BLOCKSIZE + LOOKAHEAD_POSITIONS;
     61        posix_memalign((void **) &x16hi, sizeof(BytePack), byte_stream_size);
     62        posix_memalign((void **) &x16lo, sizeof(BytePack), byte_stream_size);
     63/*
     64        x16hi = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     65        x16lo = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     66*/
     67#ifdef DEBUG
     68        printf("x16hi addr = %x\n", (int) x16hi);
     69        printf("x16lo addr = %x\n", (int) x16lo);
     70#endif
     71}
     72
     73U16LE_Buffer::U16LE_Buffer(BytePack * src, int lgth, int BOM)
     74        : U16_Buffer(src, lgth, BOM) {
     75        byte_order = LittleEndian;
     76}
     77
     78U16BE_Buffer::U16BE_Buffer(BytePack * src, int lgth, int BOM)
     79        : U16_Buffer(src, lgth, BOM) {
     80        byte_order = BigEndian;
     81}
     82
     83U32_Buffer::U32_Buffer(BytePack * src, int lgth, int BOM)
     84        : XML_Buffer<ASCII>(src, lgth, BOM) {
     85        code_unit_size = QuadByte;
     86        total_blocks = (buffer_bytes/4 + BLOCKSIZE - 1)/BLOCKSIZE;
     87        if (buffer_bytes % 4 != 0) {
     88                printf("Error: Incomplete code unit at end of file.\n");
     89                exit(-1);
     90        }
     91        int byte_stream_size = total_blocks * BLOCKSIZE + LOOKAHEAD_POSITIONS;
     92        posix_memalign((void **) &x32hh, sizeof(BytePack), byte_stream_size);
     93        posix_memalign((void **) &x32hl, sizeof(BytePack), byte_stream_size);
     94        posix_memalign((void **) &x32lh, sizeof(BytePack), byte_stream_size);
     95        posix_memalign((void **) &x32ll, sizeof(BytePack), byte_stream_size);
     96/*      x32hh = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     97        x32hl = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     98        x32lh = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     99        x32ll = new BytePack[8*total_blocks+LOOKAHEAD_PACKS];
     100*/
     101#ifdef DEBUG
     102        printf("x32hh addr = %x\n", (int) x32hh);
     103        printf("x32hl addr = %x\n", (int) x32hl);
     104        printf("x32lh addr = %x\n", (int) x32lh);
     105        printf("x32ll addr = %x\n", (int) x32ll);
     106#endif
     107}
     108
     109U32LE_Buffer::U32LE_Buffer(BytePack * src, int lgth, int BOM)
     110        : U32_Buffer(src, lgth, BOM) {
     111        byte_order = LittleEndian;
     112}
     113
     114U32BE_Buffer::U32BE_Buffer(BytePack * src, int lgth, int BOM)
     115        : U32_Buffer(src, lgth, BOM) {
     116        byte_order = BigEndian;
     117}
     118
     119U32_2143_Buffer::U32_2143_Buffer(BytePack * src, int lgth, int BOM)
     120        : U32_Buffer(src, lgth, BOM) {
     121        byte_order = Unusual_2143;
     122}
     123
     124U32_3412_Buffer::U32_3412_Buffer(BytePack * src, int lgth, int BOM)
     125        : U32_Buffer(src, lgth, BOM) {
     126        byte_order = Unusual_3412;
     127}
     128
     129
     130/* Byteplex methods.
     131
     132   No byteplexing is required for 8-bit code units; byteplex methods are no-ops.
     133
     134*/
     135
     136void Extended_ASCII_8_Buffer::DoByteplex() {}
     137
     138void EBCDIC_Buffer::DoByteplex() {}
     139
     140
     141inline void DoDuplex(BytePack * src_data, int total_blocks,
     142                                         BytePack * p0, BytePack * p1) {
     143        int total_packs = 8*total_blocks + LOOKAHEAD_PACKS;
     144        for (int pk = 0; pk < total_packs; pk++) {
     145/*              BytePack s0 = sisd_load_unaligned(&src_data[2*pk]);
     146                BytePack s1 = sisd_load_unaligned(&src_data[2*pk+1]);*/
     147                BytePack s0 = src_data[2*pk];
     148                BytePack s1 = src_data[2*pk+1];
     149#if (BYTE_ORDER == LITTLE_ENDIAN)
     150                p0[pk] = simd_pack_16_ll(s1, s0);
     151                p1[pk] = simd_pack_16_hh(s1, s0);
     152#endif
     153#if (BYTE_ORDER == BIG_ENDIAN)
     154                p0[pk] = simd_pack_16_hh(s0, s1);
     155                p1[pk] = simd_pack_16_ll(s0, s1);
     156#endif
     157        }
     158}
     159                                         
     160void U16LE_Buffer::DoByteplex() {
     161        DoDuplex(ByteBuffer, total_blocks, x16lo, x16hi);
     162}
     163
     164void U16BE_Buffer::DoByteplex() {
     165        DoDuplex(ByteBuffer, total_blocks, x16hi, x16lo);
     166}
     167
     168inline void DoQuadplex(BytePack * src_data, int total_blocks,
     169                                BytePack * p0, BytePack * p1, BytePack * p2, BytePack * p3) {
     170        int total_packs = 8*total_blocks + LOOKAHEAD_PACKS;
     171        for (int pk = 0; pk < total_packs; pk++) {
     172/*              BytePack s0 = sisd_load_unaligned(&src_data[4*pk]);
     173                BytePack s1 = sisd_load_unaligned(&src_data[4*pk+1]);
     174                BytePack s2 = sisd_load_unaligned(&src_data[4*pk+2]);
     175                BytePack s3 = sisd_load_unaligned(&src_data[4*pk+3]);*/
     176                BytePack s0 = src_data[4*pk];
     177                BytePack s1 = src_data[4*pk+1];
     178                BytePack s2 = src_data[4*pk+2];
     179                BytePack s3 = src_data[4*pk+3];
     180#if (BYTE_ORDER == LITTLE_ENDIAN)
     181                BytePack p02_0 = simd_pack_16_ll(s1, s0);
     182                BytePack p13_0 = simd_pack_16_hh(s1, s0);
     183                BytePack p02_1 = simd_pack_16_ll(s3, s2);
     184                BytePack p13_1 = simd_pack_16_hh(s3, s2);
     185                p0[pk] = simd_pack_16_ll(p02_1, p02_0);
     186                p1[pk] = simd_pack_16_ll(p13_1, p13_0);
     187                p2[pk] = simd_pack_16_hh(p02_1, p02_0);
     188                p3[pk] = simd_pack_16_hh(p13_1, p13_0);
     189#endif
     190#if (BYTE_ORDER == BIG_ENDIAN)
     191                BytePack p02_0 = simd_pack_16_hh(s0, s1);
     192                BytePack p13_0 = simd_pack_16_ll(s0, s1);
     193                BytePack p02_1 = simd_pack_16_hh(s2, s3);
     194                BytePack p13_1 = simd_pack_16_ll(s2, s3);
     195                p0[pk] = simd_pack_16_hh(p02_0, p02_1);
     196                p1[pk] = simd_pack_16_hh(p13_0, p13_1);
     197                p2[pk] = simd_pack_16_ll(p02_0, p02_1);
     198                p3[pk] = simd_pack_16_ll(p13_0, p13_1);
     199#endif
     200        }
     201}
     202
     203void U32LE_Buffer::DoByteplex() {
     204        DoQuadplex(ByteBuffer, total_blocks, x32ll, x32lh, x32hl, x32hh);
     205}
     206
     207void U32BE_Buffer::DoByteplex() {
     208        DoQuadplex(ByteBuffer, total_blocks, x32hh, x32hl, x32lh, x32ll);
     209}
     210
     211void U32_2143_Buffer::DoByteplex() {
     212        DoQuadplex(ByteBuffer, total_blocks, x32hl, x32hh, x32ll, x32lh);
     213}
     214
     215void U32_3412_Buffer::DoByteplex() {
     216        DoQuadplex(ByteBuffer, total_blocks, x32lh, x32ll, x32hh, x32hl);
     217}
     218
     219
     220/* Pseudo-ASCII stream methods */
     221
     222void Extended_ASCII_8_Buffer::PreparePseudoASCII_Stream() {
     223        x8data = ByteBuffer;
     224}
     225
     226void EBCDIC_Buffer::PreparePseudoASCII_Stream() {
     227        x8data = ByteBuffer;
     228}
     229
     230void U16_Buffer::PreparePseudoASCII_Stream() {
     231        int total_packs = 8*(buffer_bytes/2 + BLOCKSIZE - 1)/BLOCKSIZE + LOOKAHEAD_PACKS;
     232        posix_memalign((void **) &x8data, sizeof(BytePack), total_packs * PACKSIZE);
     233/*      x8data = new BytePack[total_packs];*/
     234        for (int pk = 0; pk < total_packs; pk++) {
     235                x8data[pk] = simd_or(x16lo[pk],
     236                                     simd_andc(simd_const_8(0x80),
     237                                               simd_eq_8(x16hi[pk], simd_const_8(0))));
     238        }
     239}
     240
     241void U32_Buffer::PreparePseudoASCII_Stream() {
     242        int total_packs = 8*(buffer_bytes/2 + BLOCKSIZE - 1)/BLOCKSIZE + LOOKAHEAD_PACKS;
     243        posix_memalign((void **) &x8data, sizeof(BytePack), total_packs * PACKSIZE);
     244/*      x8data = new BytePack[total_packs];*/
     245        for (int pk = 0; pk < total_packs; pk++) {
     246                BytePack hi = simd_or(simd_or(x32hh[pk], x32hl[pk]), x32lh[pk]);
     247                x8data[pk] = simd_or(x32ll[pk],
     248                                     simd_andc(simd_const_8(0x80),
     249                                               simd_eq_8(hi, simd_const_8(0))));
     250        }
     251}
     252
     253
     254template <CodeUnit_Base C>
     255inline int XML_Buffer<C>::AbsPos() const {
     256        return current_unit;
     257}
     258
     259template <CodeUnit_Base C>
     260inline unsigned char * XML_Buffer<C>::cur() const {
     261        return &((unsigned char *) x8data)[current_unit];
     262}
     263
     264template <CodeUnit_Base C>
     265inline void XML_Buffer<C>::Advance(int n) {
     266        current_unit += n;
     267}
     268
     269
     270/* To avoid any potential for a segmentation fault when loading
     271   and processing the final block of input, the input buffer
     272   is made one full block larger than required to handle the
     273   input file plus sentinel. */
     274
     275const int MAX_CODE_UNIT_SIZE = 4;
     276const int BUFFER_PADDING = MAX_CODE_UNIT_SIZE * BLOCKSIZE;
     277
     278
     279/* Signature-based character set family detection in accord with
     280   Appendix F of the XML 1.0 and 1.1 specifications. */
     281
     282/* These definitions use b2int16 to determine appropriate doublebyte
     283   values based on endianness of the underlying architecture. */
     284static const int x0000 = b2int16<0x00, 0x00>::value;
     285static const int xFEFF = b2int16<0xFE, 0xFF>::value;
     286static const int xFFFE = b2int16<0xFF, 0xFE>::value;
     287static const int x003C = b2int16<0x00, 0x3C>::value;
     288static const int x3C00 = b2int16<0x3C, 0x00>::value;
     289static const int x4C6F = b2int16<0x4C, 0x6F>::value;
     290static const int xA794 = b2int16<0xA7, 0x94>::value;
     291static const int xEFBE = b2int16<0xEF, 0xBE>::value;
     292
     293
     294XML_Buffer_Interface * XML_Buffer_Interface::BufferFactory(char* filename) {
     295        int chars_read;
     296        BytePack * src_data;
     297        struct stat fileinfo;
     298        stat(filename, &fileinfo);
     299        int buffer_size = fileinfo.st_size + BUFFER_PADDING;
     300        posix_memalign((void **) &src_data, sizeof(BytePack), buffer_size);
     301/*      src_data = new BytePack [buffer_size/PACKSIZE+1];*/
     302#ifdef DEBUG
     303        printf("__alignof(*src_data) = %i\n", __alignof(*src_data));
     304        printf("src_data addr = %x\n", (int) src_data);
     305#endif
     306        unsigned char * bytedata = (unsigned char *) src_data;
     307        FILE *infile;
     308        infile = fopen(filename, "rb");
     309        if (!infile) {
     310                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
     311                exit(-1);
     312        }
     313        chars_read = fread(bytedata, 1, fileinfo.st_size, infile);
     314        if (chars_read != fileinfo.st_size) {
     315                fprintf(stderr, "Error: fread returned %i characters, expecting %i.\n",
     316                        chars_read, fileinfo.st_size);
     317                exit(-1);
     318        }
     319        // Install null sentinels.
     320        memset(&bytedata[chars_read], 0, BUFFER_PADDING);
     321        uint16_t * XML_dbl_byte = (uint16_t *) src_data;
     322        switch (XML_dbl_byte[0]) {
     323                case x0000:
     324                        switch (XML_dbl_byte[1]) {
     325                                case xFEFF: return new U32BE_Buffer(src_data, chars_read, 1);
     326                                case xFFFE: return new U32_2143_Buffer(src_data, chars_read, 1);
     327                                case x3C00: return new U32_2143_Buffer(src_data, chars_read, 0);
     328                                default: return new U32BE_Buffer(src_data, chars_read, 0);
     329                        }
     330                case xFEFF:
     331                        if (XML_dbl_byte[1] == x0000)
     332                                return new U32_3412_Buffer(src_data, chars_read, 1);
     333                        else return new U16BE_Buffer(src_data, chars_read, 1);
     334                case xFFFE:
     335                        if (XML_dbl_byte[1] == x0000)
     336                                return new U32LE_Buffer(src_data, chars_read, 1);
     337                        else return new U16LE_Buffer(src_data, chars_read, 1);
     338                case x003C:
     339                        if (XML_dbl_byte[1] == x0000)
     340                                return new U32_3412_Buffer(src_data, chars_read, 0);
     341                        else return new U16BE_Buffer(src_data, chars_read, 0);
     342                case x3C00:
     343                        if (XML_dbl_byte[1] == x0000)
     344                                return new U32LE_Buffer(src_data, chars_read, 0);
     345                        else return new U16LE_Buffer(src_data, chars_read, 0);
     346                case x4C6F:
     347                        if (XML_dbl_byte[1] == xA794)
     348                                return new EBCDIC_Buffer(src_data, chars_read, 0);
     349                        else return new Extended_ASCII_8_Buffer(src_data, chars_read, 0);
     350                case xEFBE:
     351                        if (bytedata[2] == 0xBF)
     352                                return new Extended_ASCII_8_Buffer(src_data, chars_read, 3);
     353                        else return new Extended_ASCII_8_Buffer(src_data, chars_read, 0);
     354                default:
     355                        return new Extended_ASCII_8_Buffer(src_data, chars_read, 0);
     356        }
     357}
     358
     359int XML_Buffer_Interface::AvailableUnits(int pos) {
     360        return (buffer_bytes/(int) code_unit_size) - pos;
     361}
     362
     363
     364
     365template <CodeUnit_Base C>
     366inline void XML_Buffer<C>::Scan_WS() {
     367        while (at_WhiteSpace<XML_1_0, C>(cur())) Advance(1);
     368}
     369
     370inline bool AtEOS(unsigned char * s) {
     371        return s[0] == 0;
     372}
     373
     374template <CodeUnit_Base C>
     375inline void XML_Buffer<C>::ScanToQuote() {
     376        while(!AtChar<ASCII,'<'>(cur()) && !AtChar<ASCII,'&'>(cur())
     377                && !AtQuote<ASCII>(cur()) && !AtEOS(cur()))
     378                Advance(1);
     379}
     380
     381void DeclarationError(int pos) {
     382        printf("Parsing error at position %i in XML or Text declaration.\n", pos);
     383        exit(-1);
     384}
     385
     386//
     387// The following does not yet validate the syntax of EncNames.
     388// EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
     389// Future approach: first use lookup in EncNameTable,
     390//           if not found, do case convert, try again,
     391//             (avoids cost of case convert normally)
     392//           if not found, validate syntax of EncNames,
     393//           report error or EncName unknown.
     394//
     395template <CodeUnit_Base C>
     396void XML_Buffer<C>::ReadXMLInfo() {
     397        version = no_XML_version_value;
     398        has_encoding_decl = false;
     399        standalone = Standalone_no_value;
     400        int decl_start = AbsPos();
     401        // It is possible that there is no XML declaration.
     402        if (!at_XmlDecl_start<C>(cur())) return;
     403        // Otherwise, the XML declaration exists and must have
     404        // at least version information.
     405        Advance(6);
     406        Scan_WS();
     407        if (!at_version<C>(cur())) DeclarationError(AbsPos());
     408        Advance(7);
     409        Scan_WS();
     410        if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
     411        Advance(1);
     412        Scan_WS();
     413        if (at_1_0<C>(cur())) version = XML_1_0;
     414        else if (at_1_1<C>(cur())) version = XML_1_1;
     415        else DeclarationError(AbsPos());
     416        Advance(5);
     417        if (at_PI_End<C>(cur())) {
     418                Advance(2);
     419                content_start_pos = AbsPos();
     420                return;
     421        }
     422        if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
     423        Scan_WS();
     424        if (at_encoding<C>(cur())) {
     425                has_encoding_decl = true;
     426                Advance(8);
     427                Scan_WS();
     428                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
     429                Advance(1);
     430                Scan_WS();
     431                encoding_start_pos = AbsPos()+1;
     432                if (AtQuote<C>(cur())) {
     433                        unsigned char quoteCh = cur()[0];
     434                        Advance(1);
     435                        ScanToQuote();
     436                        if (cur()[0] != quoteCh) DeclarationError(AbsPos());
     437                }
     438                else DeclarationError(AbsPos());
     439                encoding_lgth = AbsPos()-encoding_start_pos;
     440                Advance(1);
     441                if (at_PI_End<C>(cur())) {
     442                        Advance(2);
     443                        content_start_pos = AbsPos();
     444                        return;
     445                }
     446                if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
     447                Scan_WS();
     448        }
     449        if (at_standalone<C>(cur())) {
     450                Advance(10);
     451                Scan_WS();
     452                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
     453                Advance(1);
     454                Scan_WS();
     455                if (at_yes<C>(cur())) {Advance(5); standalone = Standalone_yes;}
     456                else if (at_no<C>(cur())) {Advance(4); standalone = Standalone_no;}
     457                else DeclarationError(AbsPos());
     458                Scan_WS();
     459        }
     460        if (!at_PI_End<C>(cur())) DeclarationError(AbsPos());
     461        Advance(2);
     462        content_start_pos = AbsPos();
     463}
     464
     465// Similar to reading the XML_declaration of the document entity,
     466// ReadTextDeclaration reads the text declaration of an external
     467// parsed entity.  This is not really needed at present, for DTDless
     468// processing.
     469template <CodeUnit_Base C>
     470void XML_Buffer<C>::ReadTextDeclaration() {
     471        version = no_XML_version_value;
     472        has_encoding_decl = false;
     473        standalone = Standalone_no_value;
     474        int decl_start = AbsPos();
     475        // It is possible that there is no XML declaration.
     476        if (!at_XmlDecl_start<C>(cur())) return;
     477        // Otherwise, the text declaration exists and may have
     478        // version information.
     479        Advance(6);
     480        Scan_WS();
     481        if (at_version<C>(cur())) {
     482                Advance(7);
     483                Scan_WS();
     484                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
     485                Advance(1);
     486                Scan_WS();
     487                if (at_1_0<C>(cur())) version = XML_1_0;
     488                else if (at_1_1<C>(cur())) version = XML_1_1;
     489                else DeclarationError(AbsPos());
     490                Advance(5);
     491                // Must have whitespace character before declaration.
     492                if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
     493                Scan_WS();
     494        }
     495        if (!at_encoding<C>(cur())) DeclarationError(AbsPos());
     496        has_encoding_decl = true;
     497        Advance(8);
     498        Scan_WS();
     499        if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
     500        Advance(1);
     501        Scan_WS();
     502        encoding_start_pos = AbsPos()+1;
     503        if (AtQuote<C>(cur())) {
     504                unsigned char quoteCh = cur()[0];
     505                Advance(1);
     506                ScanToQuote();
     507                if (cur()[0] != quoteCh) DeclarationError(AbsPos());
     508        }
     509        else DeclarationError(AbsPos());
     510        encoding_lgth = AbsPos()-encoding_start_pos;
     511        Advance(1);
     512        Scan_WS();
     513        if (!at_PI_End<C>(cur())) DeclarationError(AbsPos());
     514        Advance(2);
     515        content_start_pos = AbsPos();
     516}
     517
     518int XML_Buffer_Interface::ContentStartUnit() {
     519        return content_start_pos;
     520}
     521
  • trunk/src/xmlbuffer.h

    r15 r35  
    11/*  xmlbuffer.h - Input buffering for XML entities.
    2     Copyright (c) 2007, Robert D. Cameron.
     2    Copyright (c) 2007, 2008,  Robert D. Cameron.
    33    Licensed to the public under the Open Software License 3.0.
    44    Licensed to International Characters, Inc., under the Academic
    55    Free License 3.0.
    66
    7 
    8     The goal of the XML_Buffer class is to handle I/O issues for
    9     the XML parsing engine.   The present interface and implementation
    10     is a quick hack.
    117*/
    128#ifndef XML_BUFFER_H
    139#define XML_BUFFER_H
    1410
     11#include "xmlparam.h"
     12
     13#ifdef __i386
     14#include "../lib/sse_simd.h"
     15#endif
     16#ifdef _ARCH_PPC
     17#include "../lib/altivec_simd.h"
     18#endif
    1519
    1620
    17 class XML_Buffer {
     21/* The BytePack and the BitBlock are the two fundamental
     22   types used by the parabix program for data held in
     23   SIMD registers, representing, respectively, the byte-oriented
     24   and bit-oriented views of character data.*/
    1825
     26typedef SIMD_type BytePack;
     27typedef SIMD_type BitBlock;
     28const int PACKSIZE = sizeof(SIMD_type);
     29const int BLOCKSIZE = sizeof(SIMD_type) * 8;
     30
     31/* Define the size of buffer used for lexical analysis/parsing. */
     32const int BUFFER_BLOCKS = 1024;
     33const int BUFFER_SIZE = BUFFER_BLOCKS * BLOCKSIZE;
     34
     35/* When working near the end of a buffer, a bytespace test may involve
     36   a multibyte literal.  The bytespace buffer must always make available
     37   a number of lookahead bytes at least equal to the maximum length of any
     38   such literal. */
     39
     40const int LOOKAHEAD_POSITIONS = 16;
     41
     42
     43class XML_Buffer_Interface {
    1944public:
    20         XML_Buffer(char* filename, int pad_bytes);
    21         void InstallPadding(const unsigned char* pad_string);
    22         int PrepareBytes(int position, int bytes_to_prepare);
    23         unsigned char * BytePtr(int pos);
    24 private:
    25         unsigned char * ByteBuffer;
     45        XML_Buffer_Interface ();
     46        /* Create and initialize an XML Buffer object for parsing a file,
     47           based on autodetection of the character encoding family
     48           from the initial 4-byte signature. */
     49        static XML_Buffer_Interface * BufferFactory(char * filename);
     50        virtual void DoByteplex() = 0;
     51        virtual void PreparePseudoASCII_Stream() = 0;
     52        virtual void ReadXMLInfo() = 0;
     53        virtual void ReadTextDeclaration() = 0;
     54        int AvailableUnits(int pos);
     55        int ContentStartUnit();
     56
     57        /* Information returned from the initialization process.
     58           See xmlparam.h for types.  */
     59        int BOM_units; /* no of initial code units for a Byte Order Mark */
     60        XML_version version;
     61        bool has_encoding_decl;
     62        int encoding_start_pos;
     63        int encoding_lgth;
     64        CodeUnit_Base code_unit_base;
     65        CodeUnit_Size code_unit_size;
     66        CodeUnit_ByteOrder byte_order;
     67        XML_standalone standalone;
     68        int content_start_pos;
     69
     70        /* Pseudo-ASCII stream. */
     71        BytePack * x8data;
     72
     73protected:
     74
    2675        unsigned int buffer_bytes;
    27         unsigned int alloc_size; /* size of allocated ByteBuffer */
    28         int current_pos;
     76        unsigned int total_blocks;
     77        BytePack * ByteBuffer;
     78        int current_unit;
    2979
    3080};
    3181
     82template <CodeUnit_Base C>
     83class XML_Buffer : public XML_Buffer_Interface {
     84public:
     85        XML_Buffer (BytePack * src_data, int lgth, int byte_order_units);
     86        void ReadXMLInfo();
     87        void ReadTextDeclaration();
     88        virtual void DoByteplex() = 0;
     89        virtual void PreparePseudoASCII_Stream() = 0;
     90
     91protected:
     92
     93        void Advance(int n);
     94        int AbsPos() const;
     95        unsigned char * cur() const;
     96
     97private:
     98        /* Bytespace parsing routines for internal use in ReadXMLInfo and
     99           ReadTextDeclaration. */
     100        void Scan_WS();
     101        void ScanToQuote();
     102};
     103
     104
     105/*  Various ASCII based character sets using 8-bit code units are processed
     106    using the Extended_ASCII_8_Buffer class.   This includes 7-bit ASCII
     107    itself (with high-order bit 0), the ISO-8859 character sets and UTF-8.
     108*/
     109class Extended_ASCII_8_Buffer : public XML_Buffer<ASCII> {
     110public:
     111        Extended_ASCII_8_Buffer(BytePack * src, int lgth, int BOM);
     112        void DoByteplex();
     113        void PreparePseudoASCII_Stream();
     114};
     115
     116/*  The family of 8-bit EBCDIC based character sets are processed using
     117    the EBCDIC_Buffer class.
     118*/
     119class EBCDIC_Buffer : public XML_Buffer<EBCDIC> {
     120public:
     121        EBCDIC_Buffer(BytePack * src, int lgth, int BOM);
     122        void DoByteplex();
     123        void PreparePseudoASCII_Stream();
     124};
     125
     126
     127
     128/*  UTF-16 and UCS-4 character set families in BE and LE byte orders.
     129    The U16LE and U16BE subclasses each provide a distinct byteplexer to
     130    produce 2 parallel byte streams for the high and low bytes of each
     131    16-bit code unit.  Once byteplexing is complete, a generic pseudoASCII
     132    conversion routine can be applied at the U16_Buffer level. */
     133
     134class U16_Buffer : public XML_Buffer<ASCII> {
     135public:
     136        U16_Buffer(BytePack * src, int lgth, int BOM);
     137        virtual void DoByteplex() = 0;
     138        void PreparePseudoASCII_Stream();
     139protected:
     140        BytePack * x16hi;
     141        BytePack * x16lo;
     142};
     143
     144class U16LE_Buffer : public U16_Buffer {
     145public:
     146        U16LE_Buffer(BytePack * src, int lgth, int BOM);
     147        void DoByteplex();
     148};
     149
     150class U16BE_Buffer : public U16_Buffer {
     151public:
     152        U16BE_Buffer(BytePack * src, int lgth, int BOM);
     153        void DoByteplex();
     154};
     155
     156
     157/*  UTF-32/UCS-4 character sets in BE, LE, 2143 and 3412 byte orders.
     158    Each subclass of U32_Buffer provide a distinct byteplexer to
     159    produce the 4 parallel byte streams of Unicode data.  Once
     160    byteplexing is complete, a generic pseudoASCII routine can
     161    be applied. */
     162class U32_Buffer : public XML_Buffer<ASCII> {
     163public:
     164        U32_Buffer(BytePack * src, int lgth, int BOM);
     165        virtual void DoByteplex() = 0;
     166        void PreparePseudoASCII_Stream();
     167protected:
     168        BytePack * x32hh;
     169        BytePack * x32hl;
     170        BytePack * x32lh;
     171        BytePack * x32ll;
     172};
     173
     174class U32LE_Buffer : public U32_Buffer {
     175public:
     176        U32LE_Buffer(BytePack * src, int lgth, int BOM);
     177        void DoByteplex();
     178};
     179
     180class U32BE_Buffer : public U32_Buffer {
     181public:
     182        U32BE_Buffer(BytePack * src, int lgth, int BOM);
     183        void DoByteplex();
     184};
     185
     186class U32_2143_Buffer : public U32_Buffer {
     187public:
     188        U32_2143_Buffer(BytePack * src, int lgth, int BOM);
     189        void DoByteplex();
     190};
     191
     192class U32_3412_Buffer : public U32_Buffer {
     193public:
     194        U32_3412_Buffer(BytePack * src, int lgth, int BOM);
     195        void DoByteplex();
     196};
     197
     198
    32199#endif
Note: See TracChangeset for help on using the changeset viewer.