summaryrefslogtreecommitdiff
path: root/examples/cxx/tree/streaming/grammar-input-stream.cxx
blob: ffdb5b42b47f90e4f124cc54e6dd909d60f2a391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// file      : examples/cxx/tree/streaming/grammar-input-stream.cxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : not copyrighted - public domain

#include <cassert>
#include "grammar-input-stream.hxx"

grammar_input_stream::
grammar_input_stream (const XMLByte* data, std::size_t size)
      : data_ (data),
        size_ (size),
        pos_ (0),
        vpos_ (0),
        cseq_ (0),
        add_zero_ (false)
{
}

XMLFilePos grammar_input_stream::
curPos () const
{
  return static_cast<XMLFilePos> (vpos_);
}

XMLSize_t grammar_input_stream::
readBytes (XMLByte* const buf, const XMLSize_t size)
{
  std::size_t i (0);

  // Add a zero from the alternating sequence if it didn't
  // fit on the previous read.
  //
  if (add_zero_)
  {
    buf[i++] = 0;
    add_zero_ = false;
  }

  // If have an unfinished sequential sequence, output it now.
  //
  if (cseq_ != 0 && !alt_)
  {
    for (; cseq_ != 0 && i < size; --cseq_)
      buf[i++] = 0;
  }

  for (; i < size && pos_ < size_;)
  {
    XMLByte b = buf[i++] = data_[pos_++];

    // See if we are in a compression sequence.
    //
    if (cseq_ != 0)
    {
      if (i < size)
        buf[i++] = 0;
      else
        add_zero_ = true; // Add it on the next read.

      cseq_--;
      continue;
    }

    // If we are not in a compression sequence and this byte is
    // not zero then we are done.
    //
    if (b != 0)
      continue;

    // We have a zero.
    //
    assert (pos_ < size_); // There has to be another byte.
    unsigned char v (static_cast<unsigned char> (data_[pos_++]));
    alt_ = (v & 128) != 0;
    cseq_ = v & 127;

    // If it is a sequential sequence, output as many zeros as
    // we can.
    //
    if (!alt_)
    {
      for (; cseq_ != 0 && i < size; --cseq_)
        buf[i++] = 0;
    }
  }

  vpos_ += i;

  return static_cast<XMLSize_t> (i);
}

const XMLCh* grammar_input_stream::
getContentType () const
{
  return 0;
}