source: icXML/icXML-devel/src/icxmlc/XMLUTF8CharacterSetAdapter.cpp @ 2720

Last change on this file since 2720 was 2720, checked in by cameron, 6 years ago

Initial check-in of icXML 0.8 source files

File size: 29.7 KB
Line 
1/*
2 *  Copyright © 2012 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icXML is a trademark of International Characters.
5 */
6
7/*
8 * @author Nigel Medforth, nigelm -at- interational-characters.com
9 * @version $Id: XMLUTF8CharacterSetAdapter.cpp 217 2012-12-03 15:00:50Z robc $
10 *
11 */
12
13// ---------------------------------------------------------------------------
14//  Includes
15// ---------------------------------------------------------------------------
16
17#include <xercesc/util/TranscodingException.hpp>
18#include <icxmlc/XMLUTF8CharacterSetAdapter.hpp>
19#include <xercesc/util/XMLUniDefs.hpp>
20#include <xercesc/internal/XMLReader.hpp>
21#include <xercesc/internal/XMLScanner.hpp>
22#include <xercesc/util/XMLString.hpp>
23
24#include <simd-lib/bitblock.hpp>
25#include <simd-lib/s2p.hpp>
26#include <simd-lib/p2s.hpp>
27#include <simd-lib/carryQ.hpp>
28
29#include <icxmlc/XMLMultiliteral.h>
30#include <icxmlc/PopCounter.hpp>
31#include <icxmlc/BitTracker.hpp>
32#include <icxmlc/XMLScanIterator.hpp>
33#include <icxmlc/XMLStreamIterator.hpp>
34#include <icxmlc/XMLLineColTracker.hpp>
35#include <icxmlc/XMLReferenceTable.hpp>
36#include <icxmlc/XMLConfig.hpp>
37
38XERCES_CPP_NAMESPACE_BEGIN
39
40
41// --------------------------------------------------------------------------------------
42// XMLUTF8CharacterSetAdapter
43// --------------------------------------------------------------------------------------
44
45#define do_right8_shifts(vec, rshift1, rshift2, rshift4) \
46do { \
47        BitBlock s2; \
48        vec = simd<8>::sub(vec, simd<16>::srli<1>(simd_and(rshift1, vec))); \
49        s2 = simd_and(rshift2, vec);\
50        vec = simd_or(simd<16>::srli<2>(s2), simd_xor(vec, s2));\
51        s2 = simd_and(rshift4, vec);\
52        vec = simd_or(simd<16>::srli<4>(s2), simd_xor(vec, s2));\
53} while(0)
54
55#define del_info_8(delmask, rshift1, rshift2, rshift4) \
56do { \
57        BitBlock del8_trans2; \
58        BitBlock del8_trans4; \
59        BitBlock shift_bits; \
60        rshift1 = simd_xor(simd<8>::slli<1>(delmask), simd<8>::slli<2>(delmask)); \
61        rshift1 = simd_xor(rshift1, simd<8>::slli<2>(rshift1)); \
62        rshift1 = simd_xor(rshift1, simd<8>::slli<4>(rshift1)); \
63        /* Transition to even delcount: odd delcount to left, this one deleted. */ \
64        del8_trans2 = simd_and(rshift1, delmask); \
65        /* Odd number of transition positions to left. */ \
66        rshift2 = simd_xor(simd<8>::slli<1>(del8_trans2), simd<8>::slli<2>(del8_trans2)); \
67        rshift2 = simd_xor(rshift2, simd<8>::slli<2>(rshift2)); \
68        rshift2 = simd_xor(rshift2, simd<8>::slli<4>(rshift2)); \
69        /* Transition positions: odd |del2count| to left, this one a transition to even. */ \
70        del8_trans4 = simd_and(rshift2, del8_trans2); \
71        rshift4 = simd_xor(simd<8>::slli<1>(del8_trans4), simd<8>::slli<2>(del8_trans4)); \
72        rshift4 = simd_xor(rshift4, simd<8>::slli<2>(rshift4)); \
73        rshift4 = simd_xor(rshift4, simd<8>::slli<4>(rshift4)); \
74        /* Only move bits that are not deleted. */ \
75        rshift1 = simd_andc(rshift1, delmask); \
76        rshift2 = simd_andc(rshift2, delmask); \
77        rshift4 = simd_andc(rshift4, delmask); \
78        /* Update |del8_rshift2| to apply after |del8_rshift1|. */ \
79        rshift2 = simd<8>::sub(rshift2, simd<16>::srli<1>(simd_and(rshift1, rshift2))); \
80        /* Update |del8_rshift4| to apply after |del8_rshift2| and |del8_rshift1|. */ \
81        rshift4 = simd<8>::sub(rshift4, simd<16>::srli<1>(simd_and(rshift1, rshift4))); \
82        shift_bits = simd_and(rshift2, rshift4); \
83        rshift4 = simd_or(simd<16>::srli<2>(shift_bits), simd_xor(rshift4, shift_bits)); \
84} while(0)
85
86IDISA_ALWAYS_INLINE
87static void del_count(const BitBlock delmask, BitBlock & delcount)
88{
89        BitBlock delcounts_8 = simd<8>::popcount(delmask);
90        delcount = simd<8>::sub(simd<8>::constant<8>(), delcounts_8);
91}
92
93IDISA_ALWAYS_INLINE
94XMLCh * XMLUTF8CharacterSetAdapter::buildOutputStream
95(
96        const Marker    &                               marker
97        , const Callouts  &                             callouts
98        , const U8        &                             u8
99        ,       U16hi     &                             u16hi
100        ,       U16lo     &                             u16lo
101        , const XMLByte   *                             source
102        , const size_t                                  offset
103        ,               ContentStream &                 contentStream
104        ,       XMLCh *                                 contentStreamPtr
105        ,               StringPtrArray &                stringEndArray
106        , const XMLCh     ** &                  stringEndPtr
107        ,       unsigned int &                  refMarkupCount
108        ,       unsigned int &                  refSymbolCount
109        ,               XMLComplexRefArray &    complexRefArray
110        ,               XMLSize_t &                             complexRefCount
111)
112{
113        BitBlock shift1, shift2, shift4;
114        del_info_8(callouts.delmask, shift1, shift2, shift4);
115        ubitblock del;
116        del_count(callouts.delmask, del._128);
117
118        BytePack U16h[8];
119        BytePack U16l[8];
120
121        XMLCh * contentStreamPtr0 = contentStreamPtr;
122
123        if (likely(bitblock::all(u8.unibyte)))
124        {
125                do_right8_shifts(u16lo.bit_1, shift1, shift2, shift4);
126                do_right8_shifts(u16lo.bit_2, shift1, shift2, shift4);
127                do_right8_shifts(u16lo.bit_3, shift1, shift2, shift4);
128                do_right8_shifts(u16lo.bit_4, shift1, shift2, shift4);
129                do_right8_shifts(u16lo.bit_5, shift1, shift2, shift4);
130                do_right8_shifts(u16lo.bit_6, shift1, shift2, shift4);
131                do_right8_shifts(u16lo.bit_7, shift1, shift2, shift4);
132
133                p2s(u16lo.bit_0,u16lo.bit_1,u16lo.bit_2,u16lo.bit_3,u16lo.bit_4,u16lo.bit_5,u16lo.bit_6,u16lo.bit_7,
134                        U16l[0], U16l[1],U16l[2] ,U16l[3] ,U16l[4] ,U16l[5] ,U16l[6] ,U16l[7]);
135
136                /* --------------------------------------------------------------------- */
137                /* WRITE THE CONTENT STREAM
138                /* --------------------------------------------------------------------- */
139
140                const BitBlock zero = simd<1>::constant<0>();
141                for (unsigned int i = 0; i < 8; i++)
142                {
143                        ubitblock bl;
144                        ubitblock bh;
145
146
147            #ifdef USE_UTF16_BIG_ENDIAN
148            bl._128 = esimd<8>::mergel(U16l[i], zero);
149            bh._128 = esimd<8>::mergeh(U16l[i], zero);
150            #else
151            bl._128 = esimd<8>::mergel(zero, U16l[i]);
152            bh._128 = esimd<8>::mergeh(zero, U16l[i]);
153            #endif
154
155
156                        bitblock::store_unaligned(bl._128, reinterpret_cast<BytePack *>(contentStreamPtr));
157                        contentStreamPtr += del._8[i << 1];
158
159                        bitblock::store_unaligned(bh._128, reinterpret_cast<BytePack *>(contentStreamPtr));
160                        contentStreamPtr += del._8[(i << 1) | 1];
161                }
162        }
163        else
164        {
165                do_right8_shifts(u16lo.bit_0, shift1, shift2, shift4);
166                do_right8_shifts(u16lo.bit_1, shift1, shift2, shift4);
167                do_right8_shifts(u16lo.bit_2, shift1, shift2, shift4);
168                do_right8_shifts(u16lo.bit_3, shift1, shift2, shift4);
169                do_right8_shifts(u16lo.bit_4, shift1, shift2, shift4);
170                do_right8_shifts(u16lo.bit_5, shift1, shift2, shift4);
171                do_right8_shifts(u16lo.bit_6, shift1, shift2, shift4);
172                do_right8_shifts(u16lo.bit_7, shift1, shift2, shift4);
173                if (unlikely(bitblock::any(simd_or(u8.scope33, u8.surrogate))))
174                {
175                        do_right8_shifts(u16hi.bit_0, shift1, shift2, shift4);
176                        do_right8_shifts(u16hi.bit_1, shift1, shift2, shift4);
177                        do_right8_shifts(u16hi.bit_2, shift1, shift2, shift4);
178                        do_right8_shifts(u16hi.bit_3, shift1, shift2, shift4);
179                        do_right8_shifts(u16hi.bit_4, shift1, shift2, shift4);
180                }
181                do_right8_shifts(u16hi.bit_5, shift1, shift2, shift4);
182                do_right8_shifts(u16hi.bit_6, shift1, shift2, shift4);
183                do_right8_shifts(u16hi.bit_7, shift1, shift2, shift4);
184
185                p2s(u16lo.bit_0,u16lo.bit_1,u16lo.bit_2,u16lo.bit_3,u16lo.bit_4,u16lo.bit_5,u16lo.bit_6,u16lo.bit_7,
186            U16l[0], U16l[1],U16l[2] ,U16l[3] ,U16l[4] ,U16l[5] ,U16l[6] ,U16l[7]);
187
188                p2s(u16hi.bit_0,u16hi.bit_1,u16hi.bit_2,u16hi.bit_3,u16hi.bit_4,u16hi.bit_5,u16hi.bit_6,u16hi.bit_7,
189                        U16h[0], U16h[1],U16h[2] ,U16h[3] ,U16h[4] ,U16h[5] ,U16h[6] ,U16h[7]);
190
191        /* --------------------------------------------------------------------- */
192                /* WRITE THE CONTENT STREAM
193                /* --------------------------------------------------------------------- */
194
195        for (unsigned int i = 0; i < 8; i++)
196                {
197                        ubitblock bl;
198                        ubitblock bh;
199
200            #ifdef USE_UTF16_BIG_ENDIAN
201            bl._128 = esimd<8>::mergel(U16l[i], U16h[i]);
202            bh._128 = esimd<8>::mergeh(U16l[i], U16h[i]);
203            #else
204            bl._128 = esimd<8>::mergel(U16h[i], U16l[i]);
205            bh._128 = esimd<8>::mergeh(U16h[i], U16l[i]);
206            #endif
207
208            bitblock::store_unaligned(bl._128, reinterpret_cast<BytePack *>(contentStreamPtr));
209                        contentStreamPtr += del._8[i << 1];
210
211                        bitblock::store_unaligned(bh._128, reinterpret_cast<BytePack *>(contentStreamPtr));
212                        contentStreamPtr += del._8[(i << 1) | 1];
213                }
214        }
215
216        const bool hasStrings = bitblock::any(callouts.StringEnds);
217        ubitblock refMarks;
218        refMarks._128 = simd_or(marker.Ref_opener, marker.Ref_closer);
219        const bool hasRefs = bitblock::any(refMarks._128);
220        if (likely(hasStrings | hasRefs))
221        {
222                /* --------------------------------------------------------------------- */
223                /* CALCULATE PARTIAL SUM OF DELETED CHARACTERS
224                /* --------------------------------------------------------------------- */
225
226                del._128 = simd<8>::sub(simd<8>::constant<8>(), del._128);
227                del._128 = simd<8>::add(del._128, mvmd<8>::slli<1>(del._128));
228                del._128 = simd<8>::add(del._128, mvmd<8>::slli<2>(del._128));
229                del._128 = simd<8>::add(del._128, mvmd<8>::slli<4>(del._128));
230                del._128 = simd<8>::add(del._128, mvmd<8>::slli<8>(del._128));
231                del._128 = mvmd<8>::slli<1>(del._128);
232
233                /* (i.e., if del._8 was initially { 0, 1, 2, 3, 4, ... } it will now be
234                   {8, 15, 21, 26, 30, ... }) */
235
236                // do we have space for at least (BLOCK_SIZE / 2) more strings? (the maximum possible)
237
238                /* --------------------------------------------------------------------- */
239                /* STRING END SPACE CALCULATION
240                /* --------------------------------------------------------------------- */
241                if (unlikely(&stringEndPtr[BLOCK_SIZE] >= stringEndArray.limit()))
242                {
243                        size_t stringEndOffset = stringEndPtr - &stringEndArray[0];
244                        stringEndArray.expand(stringEndOffset);
245                        stringEndPtr = &stringEndArray[stringEndOffset];
246                }
247
248                /* --------------------------------------------------------------------- */
249                /* STRING LENGTH CALCULATIONS
250                /* --------------------------------------------------------------------- */
251                if (likely(hasStrings))
252                {
253                        ubitblock stringEnds;
254                        stringEnds._128 = callouts.StringEnds;
255                        do_right8_shifts(stringEnds._128, shift1, shift2, shift4);
256                        XMLStreamIterator stringEndItr(stringEnds);
257                        size_t pos;
258
259                        while (stringEndItr.next(pos))
260                        {
261                                pos -= del._8[pos >> 3];
262                                *stringEndPtr++ = (contentStreamPtr0 + pos);
263                        }
264                }
265
266                /* --------------------------------------------------------------------- */
267                /* HANDLE REF REPLACEMENTS
268                /* --------------------------------------------------------------------- */
269
270                if (unlikely(hasRefs))
271                {
272                        ubitblock refStart;
273                        refStart._128 = marker.Ref_opener;
274                        do_right8_shifts(refStart._128, shift1, shift2, shift4);
275
276                        ubitblock attValSpan;
277                        attValSpan._128 = callouts.AttValSpan;
278
279                        fReferenceTable.findAndExpandRefs<1>
280                        (
281                                refMarks
282                                , source
283                                , offset
284                                , refStart
285                                , contentStreamPtr0 - &contentStream[0]
286                                , del
287                                , attValSpan
288                                , const_cast<XMLScanner*>(fScanner)
289                                , fSymbolTable
290                                , contentStream
291                                , contentStreamPtr
292                                , stringEndArray
293                                , stringEndPtr
294                                , refMarkupCount
295                                , refSymbolCount
296                                , complexRefArray
297                                , complexRefCount
298                        );
299
300                }
301        }
302
303        return contentStreamPtr;
304}
305
306#undef do_right8_shifts
307
308
309
310// ---------------------------------------------------------------------------
311//  XMLUTF8CharacterSetAdapter: Implementation of the transcoder API
312// ---------------------------------------------------------------------------
313
314XMLCh * XMLUTF8CharacterSetAdapter::parse
315(
316        const XMLByte * const           source
317        , const XMLSize_t                       offset
318        , const XMLSize_t                       avail
319        , const bool                            noMore
320        ,       ContentStream &         contentStream
321        ,           XMLSize_t                   contentOffset
322        ,       unsigned int &          markupCount
323        ,               SymbolArray &           symbolArray
324        ,               unsigned int &          symbolCount
325        ,               StringPtrArray &        stringEndArray
326        ,       unsigned int &          stringEndCount
327        ,       XMLLineColTracker &     lineColTracker
328        ,       BitBlock *                      newLineOrSkipMaskStream
329        ,       BitBlock *                      delMaskStream
330        ,       unsigned int &          incompleteMarkupBytes
331        ,       unsigned int &          unusedSymbols
332        ,       unsigned int &          unusedContent
333        ,               unsigned int &          bytesEaten
334)
335{
336        BitBlock symbolEnds[BUFFER_BLOCKS];
337        BitBlock symbolStream[BUFFER_BLOCKS];
338          struct U8 u8;
339
340
341
342          struct Parameters parameters;
343
344  struct Basis_bits basis_bits;
345
346  struct U16hi u16hi;
347
348  struct U16lo u16lo;
349
350  struct Lex lex;
351
352  struct Marker marker;
353
354  struct Callouts callouts;
355
356  struct Errors errors;
357
358
359
360        PopCounter<3> markupCounter;
361        // initialize the line/col tracker to the previous internal tracker
362        XMLLineColTracker currentLineColTracker(fInternalLineColTracker);
363        XMLLineColTracker outputLineColTracker(lineColTracker);
364        BitTracker lastItem;
365        unsigned int refMarkupCount = 0;
366        unsigned int refSymbolCount = 0;
367        XMLComplexRefArray complexRefArray;
368        XMLSize_t complexRefCount = 0;
369        XMLCh * contentStreamPtr = &contentStream[contentOffset];
370        const XMLCh ** stringEndPtr = &stringEndArray[stringEndCount];
371
372        size_t index = (offset >> LOG_2_BLOCK_SIZE);
373        size_t count = ((avail - offset) >> LOG_2_BLOCK_SIZE);
374
375        for (; count--; index++)
376        {
377                const XMLByte * src = &source[index << LOG_2_BLOCK_SIZE];
378
379        #ifdef PRINT_DEBUG_MESSAGE
380        XMLByte srcData[BLOCK_SIZE + 1] = {0};
381        memcpy(srcData, src, BLOCK_SIZE);
382        for (XMLSize_t i = 0; i < BLOCK_SIZE; i++)
383        {
384            if (srcData[i] < 0x20) srcData[i] = 0x20;
385        }
386        DEBUG_MESSAGE(srcData);
387        #endif
388
389                // transpose the byte data
390                transpose(reinterpret_cast<const BytePack *>(src), basis_bits);
391
392
393
394               
395  init_Parameters.do_block(parameters);
396  classify_bytes.do_block(parameters, basis_bits, lex, u8, errors);
397  parse_CtCDPI.do_block(lex, marker, callouts, errors);
398  parse_tags.do_block(lex, marker, callouts, errors);
399  parse_refs.do_block(lex, marker, callouts, errors);
400  check_CD_end_error.do_block(marker, callouts, errors);
401  utf8_to_utf16.do_block(basis_bits, u8, u16hi, u16lo, callouts, errors);
402  normalize_WS.do_block(parameters, lex, u16hi, u16lo, callouts, marker);
403  prepare_content_buffer.do_block(u16hi, u16lo, lex, callouts, marker);
404
405                bitblock::store_aligned(callouts.Symbol_ends, &symbolEnds[index]);
406                // merge the symbol start and end streams together
407                bitblock::store_aligned(simd_or(callouts.Symbol_starts, callouts.Symbol_ends), &symbolStream[index]);
408
409                currentLineColTracker.next(lex.LF, callouts.skipmask);
410                markupCounter.tally(callouts.MarkupDelimiters);
411
412                // line/col tracking streams (for error reporting)
413                bitblock::store_aligned(simd_or(lex.LF, callouts.skipmask), &newLineOrSkipMaskStream[index]);
414                bitblock::store_aligned(callouts.delmask, &delMaskStream[index]);
415
416
417
418                // scan for errors
419                checkErrors(errors, u8, src, currentLineColTracker);
420
421                // append the new tagged content to the content buffer
422                contentStreamPtr =
423                        buildOutputStream
424                        (
425                                 marker
426                                 , callouts
427                                 , u8
428                                 , u16hi
429                                 , u16lo
430                                 , source
431                                 , index << LOG_2_BLOCK_SIZE
432                                 , contentStream
433                                 , contentStreamPtr
434                                 , stringEndArray
435                                 , stringEndPtr
436                                 , refMarkupCount
437                                 , refSymbolCount
438                                 , complexRefArray
439                                 , complexRefCount
440                        );
441
442                if (lastItem.append(simd_or(callouts.MarkupDelimiters, marker.LAngle)))
443                {
444                        outputLineColTracker = currentLineColTracker;
445                }
446                currentLineColTracker.advance();
447        }
448
449        if (unlikely(noMore))
450        {
451                // will happen only once per document
452                const unsigned int advance = avail & (BLOCK_SIZE - 1);
453                bytesEaten = 0;
454                if (likely((advance) || (parse_refs.carryQ.CarryTest(0, 3) || parse_tags.carryQ.CarryTest(0, 15) || parse_CtCDPI.carryQ.CarryTest(0, 19) || prepare_content_buffer.carryQ.CarryTest(0, 2)) || (classify_bytes.carryQ.CarryTest(0, 5) || utf8_to_utf16.carryQ.CarryTest(0, 20) || normalize_WS.carryQ.CarryTest(0, 3))))
455                {
456                        const XMLByte * src = &source[index << LOG_2_BLOCK_SIZE];
457
458                        // determine the eof mask
459                        const BitBlock EOF_mask = maskre(advance);
460                        // transpose the byte data and mask off any characters that are beyond the EOF mask
461                        transpose(reinterpret_cast<const BytePack *>(src), basis_bits, EOF_mask);
462
463                       
464  init_Parameters.do_final_block(parameters, EOF_mask);
465  classify_bytes.do_final_block(parameters, basis_bits, lex, u8, errors, EOF_mask);
466  parse_CtCDPI.do_block(lex, marker, callouts, errors);
467  parse_tags.do_final_block(lex, marker, callouts, errors, EOF_mask);
468  parse_refs.do_final_block(lex, marker, callouts, errors, EOF_mask);
469  check_CD_end_error.do_final_block(marker, callouts, errors, EOF_mask);
470  utf8_to_utf16.do_final_block(basis_bits, u8, u16hi, u16lo, callouts, errors, EOF_mask);
471  normalize_WS.do_final_block(parameters, lex, u16hi, u16lo, callouts, marker, EOF_mask);
472  prepare_content_buffer.do_final_block(u16hi, u16lo, lex, callouts, marker, EOF_mask);
473
474                        bitblock::store_aligned(callouts.Symbol_ends, &symbolEnds[index]);
475                        // merge the symbol start and end streams together
476                        bitblock::store_aligned(simd_or(callouts.Symbol_starts, callouts.Symbol_ends), &symbolStream[index]);
477
478                        callouts.delmask = simd_or(callouts.delmask, simd_not(EOF_mask));
479                        currentLineColTracker.next(lex.LF, callouts.skipmask);
480                        markupCounter.tally(callouts.MarkupDelimiters);
481
482                        // line/col tracking streams (for error reporting)
483                        bitblock::store_aligned(simd_or(lex.LF, callouts.skipmask), &newLineOrSkipMaskStream[index]);
484                        bitblock::store_aligned(callouts.delmask, &delMaskStream[index]);
485
486                        // scan for errors
487                        checkErrors(errors, u8, src, currentLineColTracker);
488
489                        // append the new tagged content to the content buffer
490                        contentStreamPtr = buildOutputStream
491                        (
492                                 marker
493                                 , callouts
494                                 , u8
495                                 , u16hi
496                                 , u16lo
497                                 , source
498                                 , index << LOG_2_BLOCK_SIZE
499                                 , contentStream
500                                 , contentStreamPtr
501                                 , stringEndArray
502                                 , stringEndPtr
503                                 , refMarkupCount
504                                 , refSymbolCount
505                                 , complexRefArray
506                                 , complexRefCount
507                        );
508
509                        if (lastItem.append(simd_or(callouts.MarkupDelimiters, marker.LAngle)))
510                        {
511                                outputLineColTracker = currentLineColTracker;
512                        }
513                        currentLineColTracker.advance();
514                        index++;
515                }
516        }
517
518        // process the symbols and generate the gid array
519        if (likely(complexRefCount == 0))
520        {
521                // process the symbols and generate the gid array
522                symbolCount = fSymbolTable->resolve<1>
523                (
524                        symbolStream
525                        , source
526                        , (offset >> LOG_2_BLOCK_SIZE)
527                        , index
528                        , symbolCount
529                        , symbolArray
530                );
531        }
532        else
533        {
534                // if we're adding in complex refs, then we cannot be sure whether or not the symbol stream
535                // will have room for them all. tally up the document's symbols and add them to the refSymbolCount
536                symbolCount = fSymbolTable->resolve<1>
537                (
538                        symbolStream
539                        , source
540                        , (offset >> LOG_2_BLOCK_SIZE)
541                        , index
542                        , symbolCount
543                        , symbolArray
544                        , complexRefArray
545                        , complexRefCount
546                        , refSymbolCount
547                        , fReferenceTable
548                );
549        }
550        // if partial symbol or ref exists, then calculate the unused raw data
551        bytesEaten = avail;
552        if (fSymbolTable->fResumeSymbol)
553        {
554                bytesEaten = fSymbolTable->fStartPosition;
555                fSymbolTable->fStartPosition &= (BLOCK_SIZE - 1);
556        }
557        #ifdef TEST_ENTITY_EXPANSION
558        else if (fReferenceTable.fResumeRef)
559        {
560                fReferenceTable.fRefStartPosition = 0;
561                bytesEaten = fReferenceTable.fStartPosition;
562                fReferenceTable.fStartPosition &= (BLOCK_SIZE - 1);
563        }
564        #endif
565
566        // collapse the skip mask information into a fixed line/col # to pass to the parser
567        const unsigned int unusedMarkupBytes = lastItem.distance();
568
569        XMLFileLoc line, col;
570        const unsigned int pos = BLOCK_SIZE - (unusedMarkupBytes & (BLOCK_SIZE - 1));
571        outputLineColTracker.get(pos, line, col);
572        lineColTracker.set(line, col);
573        // store the current line/col for the next iteration
574        fInternalLineColTracker = currentLineColTracker;
575
576        #ifdef CALCULATE_COPY_BACK_POSITION
577        // determine how many symbols / bytes of content will not be used
578        if (unlikely(unusedMarkupBytes == avail))
579        {
580                unusedSymbols += symbolCount;
581                unusedContent += (contentStreamPtr - &contentStream[0]);
582                incompleteMarkupBytes += unusedMarkupBytes;
583        }
584        else
585        {
586                unusedSymbols = calculateUnusedSymbols(symbolEnds, avail, unusedMarkupBytes);
587                unusedContent = calculateUnusedContent(delMaskStream, avail, unusedMarkupBytes);
588                incompleteMarkupBytes = unusedMarkupBytes;
589        }
590        #else
591        incompleteMarkupBytes = unusedMarkupBytes;
592        #endif
593        // calculate how many strings (content, attvals, comments, pis) are in this buffer.
594        *contentStreamPtr = 0xFFFF;
595        *stringEndPtr = contentStreamPtr;
596        stringEndCount = stringEndPtr - &stringEndArray[0];
597
598        // calculate exactly how many pieces of markup are contained in the content buffer
599        markupCount = markupCounter.count() + refMarkupCount;
600
601    // return the final content end pointer
602        return contentStreamPtr;
603}
604
605#ifdef CALCULATE_COPY_BACK_POSITION
606IDISA_ALWAYS_INLINE
607uint64_t XMLUTF8CharacterSetAdapter::calculateUnusedSymbols
608(
609        const BitBlock * const  symbolStream
610        , const unsigned int    avail
611        , const unsigned int    unused
612)
613{
614        PopCounter<1> symbolCounter;
615        unsigned int index = ((avail - unused) >> LOG_2_BLOCK_SIZE);
616        unsigned int count = (avail >> LOG_2_BLOCK_SIZE);
617        BitBlock symbols = simd_andc(bitblock::load_aligned(&symbolStream[index]), mask_reverse_zeroes(unused & (BLOCK_SIZE - 1)));
618        symbolCounter.tally(symbols);
619        while (unlikely(index < count))
620        {
621                symbols = bitblock::load_aligned(&symbolStream[++index]);
622                symbolCounter.tally(symbols);
623        }
624        return symbolCounter.count();
625}
626
627IDISA_ALWAYS_INLINE
628uint64_t XMLUTF8CharacterSetAdapter::calculateUnusedContent
629(
630        const BitBlock * const          delMaskStream
631        , const unsigned int            avail
632        , const unsigned int            unused
633)
634{
635        unsigned int index = (avail + (BLOCK_SIZE - 1)) >> LOG_2_BLOCK_SIZE;
636        size_t markupCount = (unused >> LOG_2_BLOCK_SIZE);
637        size_t unusedContent = unused;
638
639        while (unlikely(markupCount != 0))
640        {
641                markupCount--;
642                BitBlock delMask = bitblock::load_aligned(&delMaskStream[--index]);
643                ubitblock pop;
644                pop._128 = simd128<64>::popcount(delMask);
645                unusedContent -= (pop._64[0] + pop._64[1]);
646        }
647
648        markupCount = unused & (BLOCK_SIZE - 1);
649
650        if (likely(markupCount != 0))
651        {
652                unsigned int pos = (128 / 8) - 1;
653                ubitblock pop;
654                ubitblock del;
655                del._128 = bitblock::load_aligned(&delMaskStream[--index]);
656                pop._128 = simd128<8>::popcount(del._128);
657
658                index = (markupCount >> CONST_LOG_2(8));
659
660                for (; index; --pos, --index)
661                {
662                        unusedContent -= pop._8[pos];
663                }
664
665                // at most 7 markup bytes are remaining
666                markupCount &= (8 - 1);
667
668                if (likely(markupCount != 0))
669                {
670                        const scanword_t one = 1;
671                        scanword_t itr = del._8[pos];
672                        itr &= ~((one << (8 - markupCount)) - one);
673                        while (itr)
674                        {
675                                itr &= (itr - 1);
676                                unusedContent--;
677                        }
678                }
679        }
680
681        return unusedContent;
682}
683
684#endif
685
686IDISA_ALWAYS_INLINE
687void XMLUTF8CharacterSetAdapter::checkErrors(const XMLUTF8CharacterSetAdapter::Errors & errors, const U8 & u8, const XMLByte * source, XMLLineColTracker & lineCol)
688{
689        BitBlock temp0 = simd_or(errors.Unicode, errors.Lexical);
690        BitBlock temp1 = simd_or(errors.ExpectedCommentOrCDATA, errors.PINameExpected);
691        BitBlock temp2 = simd_or(errors.UnterminatedPI, errors.IllegalSequenceInComment);
692        BitBlock temp3 = simd_or(errors.UnterminatedCDATASection, errors.UnterminatedComment);
693        BitBlock temp4 = simd_or(errors.ExpectedElementName, errors.ExpectedAttrName);
694        BitBlock temp5 = simd_or(errors.ExpectedEqSign, errors.ExpectedAttrValue);
695        BitBlock temp6 = simd_or(errors.UnterminatedStartTag, errors.ExpectedWhitespace);
696        BitBlock temp7 = simd_or(errors.UnterminatedEndTag, errors.UnterminatedEntityRef);
697
698        temp0 = simd_or(temp0, temp1);
699        temp2 = simd_or(temp2, temp3);
700        temp4 = simd_or(temp4, temp5);
701        temp6 = simd_or(temp6, temp7);
702
703        temp0 = simd_or(temp0, temp2);
704        temp4 = simd_or(temp4, temp6);
705
706        temp0 = simd_or(temp0, temp4);
707
708        const BitBlock fatalErrors = simd_or(temp0, errors.BadSequenceInCharData);
709
710        // does at least one error exist? all of these are fatal errors in Xerces so we only need to check one
711        if (unlikely(bitblock::any(fatalErrors)))
712        {
713                reportError(fatalErrors, errors, u8, source, lineCol);
714        }
715}
716
717void XMLUTF8CharacterSetAdapter::reportError(const BitBlock fatalErrors, const XMLUTF8CharacterSetAdapter::Errors & errors, const U8 & u8, const XMLByte * source, XMLLineColTracker & lineCol)
718{
719    const size_t fatalErrorPosition = count_forward_zeroes(fatalErrors);
720    const BitBlock fatalErrorMask = mask_forward_zeroes(fatalErrorPosition);
721
722    DEBUG_MESSAGE(" ==================== FATAL ERROR ========================")
723
724    DEBUG_MESSAGE("errors.Unicode=" << errors.Unicode)
725    DEBUG_MESSAGE("errors.Lexical=" << errors.Lexical)
726    DEBUG_MESSAGE("errors.ExpectedCommentOrCDATA=" << errors.ExpectedCommentOrCDATA)
727    DEBUG_MESSAGE("errors.PINameExpected=" << errors.PINameExpected)
728    DEBUG_MESSAGE("errors.UnterminatedPI=" << errors.UnterminatedPI)
729    DEBUG_MESSAGE("errors.IllegalSequenceInComment=" << errors.IllegalSequenceInComment)
730    DEBUG_MESSAGE("errors.UnterminatedCDATASection=" << errors.UnterminatedCDATASection)
731    DEBUG_MESSAGE("errors.UnterminatedComment=" << errors.UnterminatedComment)
732    DEBUG_MESSAGE("errors.ExpectedElementName=" << errors.ExpectedElementName)
733    DEBUG_MESSAGE("errors.ExpectedAttrName=" << errors.ExpectedAttrName)
734    DEBUG_MESSAGE("errors.ExpectedEqSign=" << errors.ExpectedEqSign)
735    DEBUG_MESSAGE("errors.ExpectedAttrValue=" << errors.ExpectedAttrValue)
736    DEBUG_MESSAGE("errors.UnterminatedStartTag=" << errors.UnterminatedStartTag)
737    DEBUG_MESSAGE("errors.ExpectedWhitespace=" << errors.ExpectedWhitespace)
738    DEBUG_MESSAGE("errors.UnterminatedEndTag=" << errors.UnterminatedEndTag)
739    DEBUG_MESSAGE("errors.UnterminatedEntityRef=" << errors.UnterminatedEntityRef)
740
741        if (bitblock::any(simd_and(errors.Unicode, fatalErrorMask)))
742        {
743                // ------------------------------------------------------------
744                // ILLEGAL UTF8 CHARACTER
745                // ------------------------------------------------------------
746                size_t offset = 0;
747                size_t trailingBytes = 0;
748
749                ubitblock u8Error;
750                u8Error._128 = fatalErrorMask;
751
752                #define IF_ERROR_IN(scopeVar, trailingBytesVal, offsetVal) \
753                        if (bitblock::any(simd_and(u8Error._128, scopeVar))) \
754                        { \
755                                offset = offsetVal - 1; \
756                                trailingBytes = trailingBytesVal; \
757                        }
758
759                IF_ERROR_IN(u8.prefix2, 2, 1)
760                else IF_ERROR_IN(u8.scope22, 2, 2)
761                else IF_ERROR_IN(u8.prefix3, 3, 1)
762                else IF_ERROR_IN(u8.scope32, 3, 2)
763                else IF_ERROR_IN(u8.scope33, 3, 3)
764                else IF_ERROR_IN(u8.prefix4, 4, 1)
765                else IF_ERROR_IN(u8.scope42, 4, 2)
766                else IF_ERROR_IN(u8.scope43, 4, 3)
767                else IF_ERROR_IN(u8.scope44, 4, 4)
768                #undef IF_ERROR_IN
769
770                const XMLByte * srcPtr = &source[fatalErrorPosition - offset];
771
772                switch (trailingBytes)
773                {
774
775                        case 2 :
776                                // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx]
777                                // Unicode: [zzzz yyyy] [yyxx xxxx]
778                                //
779                                if ((srcPtr[0] == 0xE0) && (srcPtr[1] < 0xA0))
780                                {
781                                        char byte0[2] = {0xE0, 0};
782                                        char byte1[2] = {srcPtr[1], 0};
783
784                                        ThrowXMLwithMemMgr2(UTFDataFormatException, XMLExcepts::UTF8_Invalid_3BytesSeq, byte0, byte1, getMemoryManager());
785                                }
786
787                                else if ((srcPtr[0] == 0xED) && (srcPtr[1] >= 0xA0))
788                                {
789                                        char byte0[2] = {0xED, 0};
790                                        char byte1[2] = {srcPtr[1], 0};
791
792                                        ThrowXMLwithMemMgr2(UTFDataFormatException, XMLExcepts::UTF8_Irregular_3BytesSeq, byte0, byte1, getMemoryManager());
793                                }
794
795                                break;
796                        case 3 :
797                                // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
798                                // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
799                                //          [1101 11yy] [yyxx xxxx] (low surrogate)
800                                //          * uuuuu = wwww + 1
801                                //
802                                if (((srcPtr[0] == 0xF0) && (srcPtr[1] < 0x90)) || ((srcPtr[0] == 0xF4) && (srcPtr[1] > 0x8F)))
803                                {
804                                        char byte0[2] = {srcPtr[0], 0};
805                                        char byte1[2] = {srcPtr[1], 0};
806
807                                        ThrowXMLwithMemMgr2(UTFDataFormatException, XMLExcepts::UTF8_Invalid_4BytesSeq, byte0, byte1, getMemoryManager());
808                                }
809
810                                break;
811                }
812
813                char pos[2] = {(char)(offset) + '1', 0};
814                char len[2] = {(char)(trailingBytes) + '0', 0};
815                char byte[2] = {srcPtr[offset], 0};
816
817                ThrowXMLwithMemMgr3(UTFDataFormatException, XMLExcepts::UTF8_FormatError, pos, byte, len, getMemoryManager());
818
819        }
820        else if (bitblock::any(simd_and(errors.Lexical, fatalErrorMask)))
821        {
822                // ------------------------------------------------------------
823                // ILLEGAL XML CHARACTER
824                // ------------------------------------------------------------
825                // note: this is a guess for now as to what the real error code should be
826
827                ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
828        }
829        else
830        {
831                XMLErrs::Codes errCode = XMLErrs::NoError;
832                // calculate the line/col of this error
833                XMLFileLoc line, col;
834                lineCol.get(fatalErrorPosition, line, col);
835
836
837                if (bitblock::any(simd_and(errors.ExpectedCommentOrCDATA, fatalErrorMask)))
838                {
839                        errCode = XMLErrs::ExpectedCommentOrCDATA;
840                }
841                else if (bitblock::any(simd_and(errors.PINameExpected, fatalErrorMask)))
842                {
843                        errCode = XMLErrs::PINameExpected;
844                }
845                else if (bitblock::any(simd_and(errors.UnterminatedPI, fatalErrorMask)))
846                {
847                        errCode = XMLErrs::UnterminatedPI;
848                }
849                else if (bitblock::any(simd_and(errors.IllegalSequenceInComment, fatalErrorMask)))
850                {
851                        errCode = XMLErrs::IllegalSequenceInComment;
852                }
853                else if (bitblock::any(simd_and(errors.UnterminatedCDATASection, fatalErrorMask)))
854                {
855                        errCode = XMLErrs::UnterminatedCDATASection;
856                }
857                else if (bitblock::any(simd_and(errors.UnterminatedComment, fatalErrorMask)))
858                {
859                        errCode = XMLErrs::UnterminatedComment;
860                }
861                else if (bitblock::any(simd_and(errors.ExpectedElementName, fatalErrorMask)))
862                {
863                        errCode = XMLErrs::ExpectedElementName;
864                }
865                else if (bitblock::any(simd_and(errors.ExpectedAttrName, fatalErrorMask)))
866                {
867                        errCode = XMLErrs::ExpectedAttrName;
868                }
869                else if (bitblock::any(simd_and(errors.ExpectedEqSign, fatalErrorMask)))
870                {
871                        errCode = XMLErrs::ExpectedEqSign;
872                }
873                else if (bitblock::any(simd_and(errors.ExpectedAttrValue, fatalErrorMask)))
874                {
875                        errCode = XMLErrs::ExpectedAttrValue;
876                }
877                else if (bitblock::any(simd_and(errors.UnterminatedStartTag, fatalErrorMask)))
878                {
879                        errCode = XMLErrs::UnterminatedStartTag;
880                }
881                else if (bitblock::any(simd_and(errors.ExpectedWhitespace, fatalErrorMask)))
882                {
883                        errCode = XMLErrs::ExpectedWhitespace;
884                }
885                else if (bitblock::any(simd_and(errors.UnterminatedEndTag, fatalErrorMask)))
886                {
887                        errCode = XMLErrs::UnterminatedEndTag;
888                }
889                else if (bitblock::any(simd_and(errors.UnterminatedEntityRef, fatalErrorMask)))
890                {
891                        errCode = XMLErrs::UnterminatedEntityRef;
892                }
893                else if (bitblock::any(simd_and(errors.BadSequenceInCharData, fatalErrorMask)))
894                {
895                        errCode = XMLErrs::BadSequenceInCharData;
896                }
897
898                fScanner->emitError(errCode, line, col);
899        }
900}
901
902
903
904
905XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.