Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/image/StreamingLexer.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/**
8
 * StreamingLexer is a lexing framework designed to make it simple to write
9
 * image decoders without worrying about the details of how the data is arriving
10
 * from the network.
11
 */
12
13
#ifndef mozilla_image_StreamingLexer_h
14
#define mozilla_image_StreamingLexer_h
15
16
#include <algorithm>
17
#include <cstdint>
18
#include "mozilla/Assertions.h"
19
#include "mozilla/Attributes.h"
20
#include "mozilla/Maybe.h"
21
#include "mozilla/Move.h"
22
#include "mozilla/Variant.h"
23
#include "mozilla/Vector.h"
24
#include "SourceBuffer.h"
25
26
namespace mozilla {
27
namespace image {
28
29
/// Buffering behaviors for StreamingLexer transitions.
30
enum class BufferingStrategy
31
{
32
  BUFFERED,   // Data will be buffered and processed in one chunk.
33
  UNBUFFERED  // Data will be processed as it arrives, in multiple chunks.
34
};
35
36
/// Control flow behaviors for StreamingLexer transitions.
37
enum class ControlFlowStrategy
38
{
39
  CONTINUE,  // If there's enough data, proceed to the next state immediately.
40
  YIELD      // Yield to the caller before proceeding to the next state.
41
};
42
43
/// Possible terminal states for the lexer.
44
enum class TerminalState
45
{
46
  SUCCESS,
47
  FAILURE
48
};
49
50
/// Possible yield reasons for the lexer.
51
enum class Yield
52
{
53
  NEED_MORE_DATA,   // The lexer cannot continue without more data.
54
  OUTPUT_AVAILABLE  // There is output available for the caller to consume.
55
};
56
57
/// The result of a call to StreamingLexer::Lex().
58
typedef Variant<TerminalState, Yield> LexerResult;
59
60
/**
61
 * LexerTransition is a type used to give commands to the lexing framework.
62
 * Code that uses StreamingLexer can create LexerTransition values using the
63
 * static methods on Transition, and then return them to the lexing framework
64
 * for execution.
65
 */
66
template <typename State>
67
class LexerTransition
68
{
69
public:
70
  // This is implicit so that Terminate{Success,Failure}() can return a
71
  // TerminalState and have it implicitly converted to a
72
  // LexerTransition<State>, which avoids the need for a "<State>"
73
  // qualification to the Terminate{Success,Failure}() callsite.
74
  MOZ_IMPLICIT LexerTransition(TerminalState aFinalState)
75
    : mNextState(aFinalState)
76
0
  {}
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::LexerTransition(mozilla::image::TerminalState)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::LexerTransition(mozilla::image::TerminalState)
77
78
  bool NextStateIsTerminal() const
79
0
  {
80
0
    return mNextState.template is<TerminalState>();
81
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::NextStateIsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::NextStateIsTerminal() const
82
83
  TerminalState NextStateAsTerminal() const
84
0
  {
85
0
    return mNextState.template as<TerminalState>();
86
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::NextStateAsTerminal() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::NextStateAsTerminal() const
87
88
  State NextState() const
89
0
  {
90
0
    return mNextState.template as<NonTerminalState>().mState;
91
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::NextState() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::NextState() const
92
93
  State UnbufferedState() const
94
0
  {
95
0
    return *mNextState.template as<NonTerminalState>().mUnbufferedState;
96
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::UnbufferedState() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::UnbufferedState() const
97
98
  size_t Size() const
99
0
  {
100
0
    return mNextState.template as<NonTerminalState>().mSize;
101
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::Size() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::Size() const
102
103
  BufferingStrategy Buffering() const
104
0
  {
105
0
    return mNextState.template as<NonTerminalState>().mBufferingStrategy;
106
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::Buffering() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::Buffering() const
107
108
  ControlFlowStrategy ControlFlow() const
109
0
  {
110
0
    return mNextState.template as<NonTerminalState>().mControlFlowStrategy;
111
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::ControlFlow() const
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::ControlFlow() const
112
113
private:
114
  friend struct Transition;
115
116
  LexerTransition(State aNextState,
117
                  const Maybe<State>& aUnbufferedState,
118
                  size_t aSize,
119
                  BufferingStrategy aBufferingStrategy,
120
                  ControlFlowStrategy aControlFlowStrategy)
121
    : mNextState(NonTerminalState(aNextState, aUnbufferedState, aSize,
122
                                  aBufferingStrategy, aControlFlowStrategy))
123
0
  {}
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::LexerTransition(mozilla::image::nsBMPDecoder::State, mozilla::Maybe<mozilla::image::nsBMPDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::LexerTransition(mozilla::image::nsGIFDecoder2::State, mozilla::Maybe<mozilla::image::nsGIFDecoder2::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::LexerTransition(mozilla::image::ICOState, mozilla::Maybe<mozilla::image::ICOState> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::LexerTransition(mozilla::image::nsIconDecoder::State, mozilla::Maybe<mozilla::image::nsIconDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::LexerTransition(mozilla::image::nsJPEGDecoder::State, mozilla::Maybe<mozilla::image::nsJPEGDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::LexerTransition(mozilla::image::nsPNGDecoder::State, mozilla::Maybe<mozilla::image::nsPNGDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::LexerTransition(TestState, mozilla::Maybe<TestState> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
124
125
  struct NonTerminalState
126
  {
127
    State mState;
128
    Maybe<State> mUnbufferedState;
129
    size_t mSize;
130
    BufferingStrategy mBufferingStrategy;
131
    ControlFlowStrategy mControlFlowStrategy;
132
133
    NonTerminalState(State aState,
134
                     const Maybe<State>& aUnbufferedState,
135
                     size_t aSize,
136
                     BufferingStrategy aBufferingStrategy,
137
                     ControlFlowStrategy aControlFlowStrategy)
138
      : mState(aState)
139
      , mUnbufferedState(aUnbufferedState)
140
      , mSize(aSize)
141
      , mBufferingStrategy(aBufferingStrategy)
142
      , mControlFlowStrategy(aControlFlowStrategy)
143
0
    {
144
0
      MOZ_ASSERT_IF(mBufferingStrategy == BufferingStrategy::UNBUFFERED,
145
0
                    mUnbufferedState);
146
0
      MOZ_ASSERT_IF(mUnbufferedState,
147
0
                    mBufferingStrategy == BufferingStrategy::UNBUFFERED);
148
0
    }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State>::NonTerminalState::NonTerminalState(mozilla::image::nsBMPDecoder::State, mozilla::Maybe<mozilla::image::nsBMPDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State>::NonTerminalState::NonTerminalState(mozilla::image::nsGIFDecoder2::State, mozilla::Maybe<mozilla::image::nsGIFDecoder2::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState>::NonTerminalState::NonTerminalState(mozilla::image::ICOState, mozilla::Maybe<mozilla::image::ICOState> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State>::NonTerminalState::NonTerminalState(mozilla::image::nsIconDecoder::State, mozilla::Maybe<mozilla::image::nsIconDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State>::NonTerminalState::NonTerminalState(mozilla::image::nsJPEGDecoder::State, mozilla::Maybe<mozilla::image::nsJPEGDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State>::NonTerminalState::NonTerminalState(mozilla::image::nsPNGDecoder::State, mozilla::Maybe<mozilla::image::nsPNGDecoder::State> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState>::NonTerminalState::NonTerminalState(TestState, mozilla::Maybe<TestState> const&, unsigned long, mozilla::image::BufferingStrategy, mozilla::image::ControlFlowStrategy)
149
  };
150
151
  Variant<NonTerminalState, TerminalState> mNextState;
152
};
153
154
struct Transition
155
{
156
  /// Transition to @aNextState, buffering @aSize bytes of data.
157
  template <typename State>
158
  static LexerTransition<State>
159
  To(const State& aNextState, size_t aSize)
160
0
  {
161
0
    return LexerTransition<State>(aNextState, Nothing(), aSize,
162
0
                                  BufferingStrategy::BUFFERED,
163
0
                                  ControlFlowStrategy::CONTINUE);
164
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> mozilla::image::Transition::To<mozilla::image::nsBMPDecoder::State>(mozilla::image::nsBMPDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> mozilla::image::Transition::To<mozilla::image::nsGIFDecoder2::State>(mozilla::image::nsGIFDecoder2::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState> mozilla::image::Transition::To<mozilla::image::ICOState>(mozilla::image::ICOState const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State> mozilla::image::Transition::To<mozilla::image::nsIconDecoder::State>(mozilla::image::nsIconDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState> mozilla::image::Transition::To<TestState>(TestState const&, unsigned long)
165
166
  /// Yield to the caller, transitioning to @aNextState when Lex() is next
167
  /// invoked. The same data that was delivered for the current state will be
168
  /// delivered again.
169
  template <typename State>
170
  static LexerTransition<State>
171
  ToAfterYield(const State& aNextState)
172
0
  {
173
0
    return LexerTransition<State>(aNextState, Nothing(), 0,
174
0
                                  BufferingStrategy::BUFFERED,
175
0
                                  ControlFlowStrategy::YIELD);
176
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> mozilla::image::Transition::ToAfterYield<mozilla::image::nsGIFDecoder2::State>(mozilla::image::nsGIFDecoder2::State const&)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState> mozilla::image::Transition::ToAfterYield<TestState>(TestState const&)
177
178
  /**
179
   * Transition to @aNextState via @aUnbufferedState, reading @aSize bytes of
180
   * data unbuffered.
181
   *
182
   * The unbuffered data will be delivered in state @aUnbufferedState, which may
183
   * be invoked repeatedly until all @aSize bytes have been delivered. Then,
184
   * @aNextState will be invoked with no data. No state transitions are allowed
185
   * from @aUnbufferedState except for transitions to a terminal state, so
186
   * @aNextState will always be reached unless lexing terminates early.
187
   */
188
  template <typename State>
189
  static LexerTransition<State>
190
  ToUnbuffered(const State& aNextState,
191
               const State& aUnbufferedState,
192
               size_t aSize)
193
0
  {
194
0
    return LexerTransition<State>(aNextState, Some(aUnbufferedState), aSize,
195
0
                                  BufferingStrategy::UNBUFFERED,
196
0
                                  ControlFlowStrategy::CONTINUE);
197
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> mozilla::image::Transition::ToUnbuffered<mozilla::image::nsBMPDecoder::State>(mozilla::image::nsBMPDecoder::State const&, mozilla::image::nsBMPDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> mozilla::image::Transition::ToUnbuffered<mozilla::image::nsGIFDecoder2::State>(mozilla::image::nsGIFDecoder2::State const&, mozilla::image::nsGIFDecoder2::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState> mozilla::image::Transition::ToUnbuffered<mozilla::image::ICOState>(mozilla::image::ICOState const&, mozilla::image::ICOState const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State> mozilla::image::Transition::ToUnbuffered<mozilla::image::nsJPEGDecoder::State>(mozilla::image::nsJPEGDecoder::State const&, mozilla::image::nsJPEGDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> mozilla::image::Transition::ToUnbuffered<mozilla::image::nsPNGDecoder::State>(mozilla::image::nsPNGDecoder::State const&, mozilla::image::nsPNGDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState> mozilla::image::Transition::ToUnbuffered<TestState>(TestState const&, TestState const&, unsigned long)
198
199
  /**
200
   * Continue receiving unbuffered data. @aUnbufferedState should be the same
201
   * state as the @aUnbufferedState specified in the preceding call to
202
   * ToUnbuffered().
203
   *
204
   * This should be used during an unbuffered read initiated by ToUnbuffered().
205
   */
206
  template <typename State>
207
  static LexerTransition<State>
208
  ContinueUnbuffered(const State& aUnbufferedState)
209
0
  {
210
0
    return LexerTransition<State>(aUnbufferedState, Nothing(), 0,
211
0
                                  BufferingStrategy::BUFFERED,
212
0
                                  ControlFlowStrategy::CONTINUE);
213
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> mozilla::image::Transition::ContinueUnbuffered<mozilla::image::nsBMPDecoder::State>(mozilla::image::nsBMPDecoder::State const&)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> mozilla::image::Transition::ContinueUnbuffered<mozilla::image::nsGIFDecoder2::State>(mozilla::image::nsGIFDecoder2::State const&)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::ICOState> mozilla::image::Transition::ContinueUnbuffered<mozilla::image::ICOState>(mozilla::image::ICOState const&)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State> mozilla::image::Transition::ContinueUnbuffered<mozilla::image::nsJPEGDecoder::State>(mozilla::image::nsJPEGDecoder::State const&)
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> mozilla::image::Transition::ContinueUnbuffered<mozilla::image::nsPNGDecoder::State>(mozilla::image::nsPNGDecoder::State const&)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState> mozilla::image::Transition::ContinueUnbuffered<TestState>(TestState const&)
214
215
  /**
216
   * Continue receiving unbuffered data. @aUnbufferedState should be the same
217
   * state as the @aUnbufferedState specified in the preceding call to
218
   * ToUnbuffered(). @aSize indicates the amount of data that has already been
219
   * consumed; the next state will receive the same data that was delivered to
220
   * the current state, without the first @aSize bytes.
221
   *
222
   * This should be used during an unbuffered read initiated by ToUnbuffered().
223
   */
224
  template <typename State>
225
  static LexerTransition<State>
226
  ContinueUnbufferedAfterYield(const State& aUnbufferedState, size_t aSize)
227
0
  {
228
0
    return LexerTransition<State>(aUnbufferedState, Nothing(), aSize,
229
0
                                  BufferingStrategy::BUFFERED,
230
0
                                  ControlFlowStrategy::YIELD);
231
0
  }
Unexecuted instantiation: mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> mozilla::image::Transition::ContinueUnbufferedAfterYield<mozilla::image::nsPNGDecoder::State>(mozilla::image::nsPNGDecoder::State const&, unsigned long)
Unexecuted instantiation: mozilla::image::LexerTransition<TestState> mozilla::image::Transition::ContinueUnbufferedAfterYield<TestState>(TestState const&, unsigned long)
232
233
  /**
234
   * Terminate lexing, ending up in terminal state SUCCESS. (The implicit
235
   * LexerTransition constructor will convert the result to a LexerTransition
236
   * as needed.)
237
   *
238
   * No more data will be delivered after this function is used.
239
   */
240
  static TerminalState
241
  TerminateSuccess()
242
0
  {
243
0
    return TerminalState::SUCCESS;
244
0
  }
245
246
  /**
247
   * Terminate lexing, ending up in terminal state FAILURE. (The implicit
248
   * LexerTransition constructor will convert the result to a LexerTransition
249
   * as needed.)
250
   *
251
   * No more data will be delivered after this function is used.
252
   */
253
  static TerminalState
254
  TerminateFailure()
255
0
  {
256
0
    return TerminalState::FAILURE;
257
0
  }
258
259
private:
260
  Transition();
261
};
262
263
/**
264
 * StreamingLexer is a lexing framework designed to make it simple to write
265
 * image decoders without worrying about the details of how the data is arriving
266
 * from the network.
267
 *
268
 * To use StreamingLexer:
269
 *
270
 *  - Create a State type. This should be an |enum class| listing all of the
271
 *    states that you can be in while lexing the image format you're trying to
272
 *    read.
273
 *
274
 *  - Add an instance of StreamingLexer<State> to your decoder class. Initialize
275
 *    it with a Transition::To() the state that you want to start lexing in, and
276
 *    a Transition::To() the state you'd like to use to handle truncated data.
277
 *
278
 *  - In your decoder's DoDecode() method, call Lex(), passing in the input
279
 *    data and length that are passed to DoDecode(). You also need to pass
280
 *    a lambda which dispatches to lexing code for each state based on the State
281
 *    value that's passed in. The lambda generally should just continue a
282
 *    |switch| statement that calls different methods for each State value. Each
283
 *    method should return a LexerTransition<State>, which the lambda should
284
 *    return in turn.
285
 *
286
 *  - Write the methods that actually implement lexing for your image format.
287
 *    These methods should return either Transition::To(), to move on to another
288
 *    state, or Transition::Terminate{Success,Failure}(), if lexing has
289
 *    terminated in either success or failure. (There are also additional
290
 *    transitions for unbuffered reads; see below.)
291
 *
292
 * That's the basics. The StreamingLexer will track your position in the input
293
 * and buffer enough data so that your lexing methods can process everything in
294
 * one pass. Lex() returns Yield::NEED_MORE_DATA if more data is needed, in
295
 * which case you should just return from DoDecode(). If lexing reaches a
296
 * terminal state, Lex() returns TerminalState::SUCCESS or
297
 * TerminalState::FAILURE, and you can check which one to determine if lexing
298
 * succeeded or failed and do any necessary cleanup.
299
 *
300
 * Sometimes, the input data is truncated. StreamingLexer will notify you when
301
 * this happens by invoking the truncated data state you passed to the
302
 * constructor. At this point you can attempt to recover and return
303
 * TerminalState::SUCCESS or TerminalState::FAILURE, depending on whether you
304
 * were successful. Note that you can't return anything other than a terminal
305
 * state in this situation, since there's no more data to read. For the same
306
 * reason, your truncated data state shouldn't require any data. (That is, the
307
 * @aSize argument you pass to Transition::To() must be zero.) Violating these
308
 * requirements will trigger assertions and an immediate transition to
309
 * TerminalState::FAILURE.
310
 *
311
 * Some lexers may want to *avoid* buffering in some cases, and just process the
312
 * data as it comes in. This is useful if, for example, you just want to skip
313
 * over a large section of data; there's no point in buffering data you're just
314
 * going to ignore.
315
 *
316
 * You can begin an unbuffered read with Transition::ToUnbuffered(). This works
317
 * a little differently than Transition::To() in that you specify *two* states.
318
 * The @aUnbufferedState argument specifies a state that will be called
319
 * repeatedly with unbuffered data, as soon as it arrives. The implementation
320
 * for that state should return either a transition to a terminal state, or a
321
 * Transition::ContinueUnbuffered() to the same @aUnbufferedState. (From a
322
 * technical perspective, it's not necessary to specify the state again, but
323
 * it's helpful to human readers.) Once the amount of data requested in the
324
 * original call to Transition::ToUnbuffered() has been delivered, Lex() will
325
 * transition to the @aNextState state specified via Transition::ToUnbuffered().
326
 * That state will be invoked with *no* data; it's just called to signal that
327
 * the unbuffered read is over.
328
 *
329
 * It's sometimes useful for a lexer to provide incremental results, rather
330
 * than simply running to completion and presenting all its output at once. For
331
 * example, when decoding animated images, it may be useful to produce each
332
 * frame incrementally. StreamingLexer supports this by allowing a lexer to
333
 * yield.
334
 *
335
 * To yield back to the caller, a state implementation can simply return
336
 * Transition::ToAfterYield(). ToAfterYield()'s @aNextState argument specifies
337
 * the next state that the lexer should transition to, just like when using
338
 * Transition::To(), but there are two differences. One is that Lex() will
339
 * return to the caller before processing any more data when it encounters a
340
 * yield transition. This provides an opportunity for the caller to interact with the
341
 * lexer's intermediate results. The second difference is that @aNextState
342
 * will be called with *the same data as the state that you returned
343
 * Transition::ToAfterYield() from*. This allows a lexer to partially consume
344
 * the data, return intermediate results, and then finish consuming the data
345
 * when @aNextState is called.
346
 *
347
 * It's also possible to yield during an unbuffered read. Just return a
348
 * Transition::ContinueUnbufferedAfterYield(). Just like with
349
 * Transition::ContinueUnbuffered(), the @aUnbufferedState must be the same as
350
 * the one originally passed to Transition::ToUnbuffered(). The second argument,
351
 * @aSize, specifies the amount of data that the lexer has already consumed.
352
 * When @aUnbufferedState is next invoked, it will get the same data that it
353
 * received previously, except that the first @aSize bytes will be excluded.
354
 * This makes it easy to consume unbuffered data incrementally.
355
 *
356
 * XXX(seth): We should be able to get of the |State| stuff totally once bug
357
 * 1198451 lands, since we can then just return a function representing the next
358
 * state directly.
359
 */
360
template <typename State, size_t InlineBufferSize = 16>
361
class StreamingLexer
362
{
363
public:
364
  StreamingLexer(const LexerTransition<State>& aStartState,
365
                 const LexerTransition<State>& aTruncatedState)
366
    : mTransition(TerminalState::FAILURE)
367
    , mTruncatedTransition(aTruncatedState)
368
0
  {
369
0
    if (!aStartState.NextStateIsTerminal() &&
370
0
        aStartState.ControlFlow() == ControlFlowStrategy::YIELD) {
371
0
      // Allowing a StreamingLexer to start in a yield state doesn't make sense
372
0
      // semantically (since yield states are supposed to deliver the same data
373
0
      // as previous states, and there's no previous state here), but more
374
0
      // importantly, it's necessary to advance a SourceBufferIterator at least
375
0
      // once before you can read from it, and adding the necessary checks to
376
0
      // Lex() to avoid that issue has the potential to mask real bugs. So
377
0
      // instead, it's better to forbid starting in a yield state.
378
0
      MOZ_ASSERT_UNREACHABLE("Starting in a yield state");
379
0
      return;
380
0
    }
381
0
382
0
    if (!aTruncatedState.NextStateIsTerminal() &&
383
0
          (aTruncatedState.ControlFlow() == ControlFlowStrategy::YIELD ||
384
0
           aTruncatedState.Buffering() == BufferingStrategy::UNBUFFERED ||
385
0
           aTruncatedState.Size() != 0)) {
386
0
      // The truncated state can't receive any data because, by definition,
387
0
      // there is no more data to receive. That means that yielding or an
388
0
      // unbuffered read would not make sense, and that the state must require
389
0
      // zero bytes.
390
0
      MOZ_ASSERT_UNREACHABLE("Truncated state makes no sense");
391
0
      return;
392
0
    }
393
0
394
0
    SetTransition(aStartState);
395
0
  }
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> const&, mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> const&, mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::ICOState> const&, mozilla::image::LexerTransition<mozilla::image::ICOState> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State> const&, mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State> const&, mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::StreamingLexer(mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> const&, mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<TestState, 16ul>::StreamingLexer(mozilla::image::LexerTransition<TestState> const&, mozilla::image::LexerTransition<TestState> const&)
396
397
  /**
398
   * From the given SourceBufferIterator, aIterator, create a new iterator at
399
   * the same position, with the given read limit, aReadLimit. The read limit
400
   * applies after adjusting for the position. If the given iterator has been
401
   * advanced, but required buffering inside StreamingLexer, the position
402
   * of the cloned iterator will be at the beginning of buffered data; this
403
   * should match the perspective of the caller.
404
   */
405
  Maybe<SourceBufferIterator> Clone(SourceBufferIterator& aIterator,
406
                                    size_t aReadLimit) const
407
0
  {
408
0
    // In order to advance to the current position of the iterator from the
409
0
    // perspective of the caller, we need to take into account if we are
410
0
    // buffering data.
411
0
    size_t pos = aIterator.Position();
412
0
    if (!mBuffer.empty()) {
413
0
      pos += aIterator.Length();
414
0
      MOZ_ASSERT(pos > mBuffer.length());
415
0
      pos -= mBuffer.length();
416
0
    }
417
0
418
0
    size_t readLimit = aReadLimit;
419
0
    if (aReadLimit != SIZE_MAX) {
420
0
      readLimit += pos;
421
0
    }
422
0
423
0
    SourceBufferIterator other = aIterator.Owner()->Iterator(readLimit);
424
0
425
0
    // Since the current iterator has already advanced to this point, we
426
0
    // know that the state can only be READY or COMPLETE. That does not mean
427
0
    // everything is stored in a single chunk, and may require multiple Advance
428
0
    // calls to get where we want to be.
429
0
    SourceBufferIterator::State state;
430
0
    do {
431
0
      state = other.Advance(pos);
432
0
      if (state != SourceBufferIterator::READY) {
433
0
        // The only way we should fail to advance over data we already seen is
434
0
        // if we hit an error while inserting data into the buffer. This will
435
0
        // cause an early exit.
436
0
        MOZ_ASSERT(NS_FAILED(other.CompletionStatus()));
437
0
        return Nothing();
438
0
      }
439
0
      MOZ_ASSERT(pos >= other.Length());
440
0
      pos -= other.Length();
441
0
    } while (pos > 0);
442
0
443
0
    // Force the data pointer to be where we expect it to be.
444
0
    state = other.Advance(0);
445
0
    if (state != SourceBufferIterator::READY) {
446
0
      // The current position could be the end of the buffer, in which case
447
0
      // there is no point cloning with no more data to read.
448
0
      MOZ_ASSERT(state == SourceBufferIterator::COMPLETE);
449
0
      return Nothing();
450
0
    }
451
0
    return Some(std::move(other));
452
0
  }
453
454
  template <typename Func>
455
  LexerResult Lex(SourceBufferIterator& aIterator,
456
                  IResumable* aOnResume,
457
                  Func aFunc)
458
0
  {
459
0
    if (mTransition.NextStateIsTerminal()) {
460
0
      // We've already reached a terminal state. We never deliver any more data
461
0
      // in this case; just return the terminal state again immediately.
462
0
      return LexerResult(mTransition.NextStateAsTerminal());
463
0
    }
464
0
465
0
    Maybe<LexerResult> result;
466
0
467
0
    // If the lexer requested a yield last time, we deliver the same data again
468
0
    // before we read anything else from |aIterator|. Note that although to the
469
0
    // callers of Lex(), Yield::NEED_MORE_DATA is just another type of yield,
470
0
    // internally they're different in that we don't redeliver the same data in
471
0
    // the Yield::NEED_MORE_DATA case, and |mYieldingToState| is not set. This
472
0
    // means that for Yield::NEED_MORE_DATA, we go directly to the loop below.
473
0
    if (mYieldingToState) {
474
0
      result = mTransition.Buffering() == BufferingStrategy::UNBUFFERED
475
0
             ? UnbufferedReadAfterYield(aIterator, aFunc)
476
0
             : BufferedReadAfterYield(aIterator, aFunc);
477
0
    }
478
0
479
0
    while (!result) {
480
0
      MOZ_ASSERT_IF(mTransition.Buffering() == BufferingStrategy::UNBUFFERED,
481
0
                    mUnbufferedState);
482
0
483
0
      // Figure out how much we need to read.
484
0
      const size_t toRead = mTransition.Buffering() == BufferingStrategy::UNBUFFERED
485
0
                          ? mUnbufferedState->mBytesRemaining
486
0
                          : mTransition.Size() - mBuffer.length();
487
0
488
0
      // Attempt to advance the iterator by |toRead| bytes.
489
0
      switch (aIterator.AdvanceOrScheduleResume(toRead, aOnResume)) {
490
0
        case SourceBufferIterator::WAITING:
491
0
          // We can't continue because the rest of the data hasn't arrived from
492
0
          // the network yet. We don't have to do anything special; the
493
0
          // SourceBufferIterator will ensure that |aOnResume| gets called when
494
0
          // more data is available.
495
0
          result = Some(LexerResult(Yield::NEED_MORE_DATA));
496
0
          break;
497
0
498
0
        case SourceBufferIterator::COMPLETE:
499
0
          // The data is truncated; if not, the lexer would've reached a
500
0
          // terminal state by now. We only get to
501
0
          // SourceBufferIterator::COMPLETE after every byte of data has been
502
0
          // delivered to the lexer.
503
0
          result = Truncated(aIterator, aFunc);
504
0
          break;
505
0
506
0
        case SourceBufferIterator::READY:
507
0
          // Process the new data that became available.
508
0
          MOZ_ASSERT(aIterator.Data());
509
0
510
0
          result = mTransition.Buffering() == BufferingStrategy::UNBUFFERED
511
0
                 ? UnbufferedRead(aIterator, aFunc)
512
0
                 : BufferedRead(aIterator, aFunc);
513
0
          break;
514
0
515
0
        default:
516
0
          MOZ_ASSERT_UNREACHABLE("Unknown SourceBufferIterator state");
517
0
          result = SetTransition(Transition::TerminateFailure());
518
0
      }
519
0
    };
520
0
521
0
    return *result;
522
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::Lex<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::Lex<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::Lex<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::Lex<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::Lex<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::Lex<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> mozilla::image::StreamingLexer<TestState, 16ul>::Lex<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
523
524
private:
525
  template <typename Func>
526
  Maybe<LexerResult> UnbufferedRead(SourceBufferIterator& aIterator, Func aFunc)
527
0
  {
528
0
    MOZ_ASSERT(mTransition.Buffering() == BufferingStrategy::UNBUFFERED);
529
0
    MOZ_ASSERT(mUnbufferedState);
530
0
    MOZ_ASSERT(!mYieldingToState);
531
0
    MOZ_ASSERT(mBuffer.empty(),
532
0
               "Buffered read at the same time as unbuffered read?");
533
0
    MOZ_ASSERT(aIterator.Length() <= mUnbufferedState->mBytesRemaining,
534
0
               "Read too much data during unbuffered read?");
535
0
    MOZ_ASSERT(mUnbufferedState->mBytesConsumedInCurrentChunk == 0,
536
0
               "Already consumed data in the current chunk, but not yielding?");
537
0
538
0
    if (mUnbufferedState->mBytesRemaining == 0) {
539
0
      // We're done with the unbuffered read, so transition to the next state.
540
0
      return SetTransition(aFunc(mTransition.NextState(), nullptr, 0));
541
0
    }
542
0
543
0
    return ContinueUnbufferedRead(aIterator.Data(), aIterator.Length(),
544
0
                                  aIterator.Length(), aFunc);
545
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::UnbufferedRead<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::UnbufferedRead<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::UnbufferedRead<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::UnbufferedRead<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::UnbufferedRead<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::UnbufferedRead<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
546
547
  template <typename Func>
548
  Maybe<LexerResult> UnbufferedReadAfterYield(SourceBufferIterator& aIterator, Func aFunc)
549
0
  {
550
0
    MOZ_ASSERT(mTransition.Buffering() == BufferingStrategy::UNBUFFERED);
551
0
    MOZ_ASSERT(mUnbufferedState);
552
0
    MOZ_ASSERT(mYieldingToState);
553
0
    MOZ_ASSERT(mBuffer.empty(),
554
0
               "Buffered read at the same time as unbuffered read?");
555
0
    MOZ_ASSERT(aIterator.Length() <= mUnbufferedState->mBytesRemaining,
556
0
               "Read too much data during unbuffered read?");
557
0
    MOZ_ASSERT(mUnbufferedState->mBytesConsumedInCurrentChunk <= aIterator.Length(),
558
0
               "Consumed more data than the current chunk holds?");
559
0
    MOZ_ASSERT(mTransition.UnbufferedState() == *mYieldingToState);
560
0
561
0
    mYieldingToState = Nothing();
562
0
563
0
    if (mUnbufferedState->mBytesRemaining == 0) {
564
0
      // We're done with the unbuffered read, so transition to the next state.
565
0
      return SetTransition(aFunc(mTransition.NextState(), nullptr, 0));
566
0
    }
567
0
568
0
    // Since we've yielded, we may have already consumed some data in this
569
0
    // chunk. Make the necessary adjustments. (Note that the std::min call is
570
0
    // just belt-and-suspenders to keep this code memory safe even if there's
571
0
    // a bug somewhere.)
572
0
    const size_t toSkip =
573
0
      std::min(mUnbufferedState->mBytesConsumedInCurrentChunk, aIterator.Length());
574
0
    const char* data = aIterator.Data() + toSkip;
575
0
    const size_t length = aIterator.Length() - toSkip;
576
0
577
0
    // If |length| is zero, we've hit the end of the current chunk. This only
578
0
    // happens if we yield right at the end of a chunk. Rather than call |aFunc|
579
0
    // with a |length| of zero bytes (which seems potentially surprising to
580
0
    // decoder authors), we go ahead and read more data.
581
0
    if (length == 0) {
582
0
      return FinishCurrentChunkOfUnbufferedRead(aIterator.Length());
583
0
    }
584
0
585
0
    return ContinueUnbufferedRead(data, length, aIterator.Length(), aFunc);
586
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::UnbufferedReadAfterYield<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::UnbufferedReadAfterYield<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::UnbufferedReadAfterYield<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::UnbufferedReadAfterYield<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::UnbufferedReadAfterYield<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::UnbufferedReadAfterYield<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedReadAfterYield<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
587
588
  template <typename Func>
589
  Maybe<LexerResult> ContinueUnbufferedRead(const char* aData,
590
                                            size_t aLength,
591
                                            size_t aChunkLength,
592
                                            Func aFunc)
593
0
  {
594
0
    // Call aFunc with the unbuffered state to indicate that we're in the
595
0
    // middle of an unbuffered read. We enforce that any state transition
596
0
    // passed back to us is either a terminal state or takes us back to the
597
0
    // unbuffered state.
598
0
    LexerTransition<State> unbufferedTransition =
599
0
      aFunc(mTransition.UnbufferedState(), aData, aLength);
600
0
601
0
    // If we reached a terminal state, we're done.
602
0
    if (unbufferedTransition.NextStateIsTerminal()) {
603
0
      return SetTransition(unbufferedTransition);
604
0
    }
605
0
606
0
    MOZ_ASSERT(mTransition.UnbufferedState() ==
607
0
                 unbufferedTransition.NextState());
608
0
609
0
    // Perform bookkeeping.
610
0
    if (unbufferedTransition.ControlFlow() == ControlFlowStrategy::YIELD) {
611
0
      mUnbufferedState->mBytesConsumedInCurrentChunk += unbufferedTransition.Size();
612
0
      return SetTransition(unbufferedTransition);
613
0
    }
614
0
615
0
    MOZ_ASSERT(unbufferedTransition.Size() == 0);
616
0
    return FinishCurrentChunkOfUnbufferedRead(aChunkLength);
617
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(char const*, unsigned long, unsigned long, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(char const*, unsigned long, unsigned long, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::ContinueUnbufferedRead<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(char const*, unsigned long, unsigned long, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(char const*, unsigned long, unsigned long, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(char const*, unsigned long, unsigned long, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(char const*, unsigned long, unsigned long, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(char const*, unsigned long, unsigned long, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(char const*, unsigned long, unsigned long, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(char const*, unsigned long, unsigned long, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(char const*, unsigned long, unsigned long, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(char const*, unsigned long, unsigned long, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(char const*, unsigned long, unsigned long, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(char const*, unsigned long, unsigned long, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(char const*, unsigned long, unsigned long, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(char const*, unsigned long, unsigned long, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::ContinueUnbufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(char const*, unsigned long, unsigned long, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
618
619
  Maybe<LexerResult> FinishCurrentChunkOfUnbufferedRead(size_t aChunkLength)
620
0
  {
621
0
    // We've finished an unbuffered read of a chunk of length |aChunkLength|, so
622
0
    // update |myBytesRemaining| to reflect that we're |aChunkLength| closer to
623
0
    // the end of the unbuffered read. (The std::min call is just
624
0
    // belt-and-suspenders to keep this code memory safe even if there's a bug
625
0
    // somewhere.)
626
0
    mUnbufferedState->mBytesRemaining -=
627
0
      std::min(mUnbufferedState->mBytesRemaining, aChunkLength);
628
0
629
0
    // Since we're moving on to a new chunk, we can forget about the count of
630
0
    // bytes consumed by yielding in the current chunk.
631
0
    mUnbufferedState->mBytesConsumedInCurrentChunk = 0;
632
0
633
0
    return Nothing();  // Keep processing.
634
0
  }
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<TestState, 16ul>::FinishCurrentChunkOfUnbufferedRead(unsigned long)
635
636
  template <typename Func>
637
  Maybe<LexerResult> BufferedRead(SourceBufferIterator& aIterator, Func aFunc)
638
0
  {
639
0
    MOZ_ASSERT(mTransition.Buffering() == BufferingStrategy::BUFFERED);
640
0
    MOZ_ASSERT(!mYieldingToState);
641
0
    MOZ_ASSERT(!mUnbufferedState,
642
0
               "Buffered read at the same time as unbuffered read?");
643
0
    MOZ_ASSERT(mBuffer.length() < mTransition.Size() ||
644
0
               (mBuffer.length() == 0 && mTransition.Size() == 0),
645
0
               "Buffered more than we needed?");
646
0
647
0
    // If we have all the data, we don't actually need to buffer anything.
648
0
    if (mBuffer.empty() && aIterator.Length() == mTransition.Size()) {
649
0
      return SetTransition(aFunc(mTransition.NextState(),
650
0
                                 aIterator.Data(),
651
0
                                 aIterator.Length()));
652
0
    }
653
0
654
0
    // We do need to buffer, so make sure the buffer has enough capacity. We
655
0
    // deliberately wait until we know for sure we need to buffer to call
656
0
    // reserve() since it could require memory allocation.
657
0
    if (!mBuffer.reserve(mTransition.Size())) {
658
0
      return SetTransition(Transition::TerminateFailure());
659
0
    }
660
0
661
0
    // Append the new data we just got to the buffer.
662
0
    if (!mBuffer.append(aIterator.Data(), aIterator.Length())) {
663
0
      return SetTransition(Transition::TerminateFailure());
664
0
    }
665
0
666
0
    if (mBuffer.length() != mTransition.Size()) {
667
0
      return Nothing();  // Keep processing.
668
0
    }
669
0
670
0
    // We've buffered everything, so transition to the next state.
671
0
    return SetTransition(aFunc(mTransition.NextState(),
672
0
                               mBuffer.begin(),
673
0
                               mBuffer.length()));
674
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::BufferedRead<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::BufferedRead<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::BufferedRead<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::BufferedRead<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::BufferedRead<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::BufferedRead<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedRead<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
675
676
  template <typename Func>
677
  Maybe<LexerResult> BufferedReadAfterYield(SourceBufferIterator& aIterator,
678
                                            Func aFunc)
679
0
  {
680
0
    MOZ_ASSERT(mTransition.Buffering() == BufferingStrategy::BUFFERED);
681
0
    MOZ_ASSERT(mYieldingToState);
682
0
    MOZ_ASSERT(!mUnbufferedState,
683
0
               "Buffered read at the same time as unbuffered read?");
684
0
    MOZ_ASSERT(mBuffer.length() <= mTransition.Size(),
685
0
               "Buffered more than we needed?");
686
0
687
0
    State nextState = std::move(*mYieldingToState);
688
0
689
0
    // After a yield, we need to take the same data that we delivered to the
690
0
    // last state, and deliver it again to the new state. We know that this is
691
0
    // happening right at a state transition, and that the last state was a
692
0
    // buffered read, so there are two cases:
693
0
694
0
    // 1. We got the data from the SourceBufferIterator directly.
695
0
    if (mBuffer.empty() && aIterator.Length() == mTransition.Size()) {
696
0
      return SetTransition(aFunc(nextState,
697
0
                                 aIterator.Data(),
698
0
                                 aIterator.Length()));
699
0
    }
700
0
701
0
    // 2. We got the data from the buffer.
702
0
    if (mBuffer.length() == mTransition.Size()) {
703
0
      return SetTransition(aFunc(nextState,
704
0
                                 mBuffer.begin(),
705
0
                                 mBuffer.length()));
706
0
    }
707
0
708
0
    // Anything else indicates a bug.
709
0
    MOZ_ASSERT_UNREACHABLE("Unexpected state encountered during yield");
710
0
    return SetTransition(Transition::TerminateFailure());
711
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::BufferedReadAfterYield<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::BufferedReadAfterYield<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::BufferedReadAfterYield<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::BufferedReadAfterYield<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::BufferedReadAfterYield<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::BufferedReadAfterYield<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::BufferedReadAfterYield<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
712
713
  template <typename Func>
714
  Maybe<LexerResult> Truncated(SourceBufferIterator& aIterator,
715
                               Func aFunc)
716
0
  {
717
0
    // The data is truncated. Let the lexer clean up and decide which terminal
718
0
    // state we should end up in.
719
0
    LexerTransition<State> transition
720
0
      = mTruncatedTransition.NextStateIsTerminal()
721
0
      ? mTruncatedTransition
722
0
      : aFunc(mTruncatedTransition.NextState(), nullptr, 0);
723
0
724
0
    if (!transition.NextStateIsTerminal()) {
725
0
      MOZ_ASSERT_UNREACHABLE("Truncated state didn't lead to terminal state?");
726
0
      return SetTransition(Transition::TerminateFailure());
727
0
    }
728
0
729
0
    // If the SourceBuffer was completed with a failing state, we end in
730
0
    // TerminalState::FAILURE no matter what. This only happens in exceptional
731
0
    // situations like SourceBuffer itself encountering a failure due to OOM.
732
0
    if (NS_FAILED(aIterator.CompletionStatus())) {
733
0
      return SetTransition(Transition::TerminateFailure());
734
0
    }
735
0
736
0
    return SetTransition(transition);
737
0
  }
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::Truncated<mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0>(mozilla::image::SourceBufferIterator&, mozilla::image::nsBMPDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_0)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::Truncated<mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1>(mozilla::image::SourceBufferIterator&, mozilla::image::nsGIFDecoder2::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_1)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::Truncated<mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4>(mozilla::image::SourceBufferIterator&, mozilla::image::nsICODecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_4)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::Truncated<mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5>(mozilla::image::SourceBufferIterator&, mozilla::image::nsIconDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_5)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::Truncated<mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7>(mozilla::image::SourceBufferIterator&, mozilla::image::nsJPEGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_7)
Unexecuted instantiation: Unified_cpp_image_decoders0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::Truncated<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(mozilla::image::SourceBufferIterator&, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8)
Unexecuted instantiation: mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long)>(mozilla::image::SourceBufferIterator&, mozilla::image::LexerTransition<TestState> (*)(TestState, char const*, unsigned long))
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_SingleChunkWithUnbuffered_Test::TestBody()::$_76)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbuffered_Test::TestBody()::$_77)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ChunkPerStateWithUnbufferedYield_Test::TestBody()::$_78)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_OneByteChunksWithUnbuffered_Test::TestBody()::$_79)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_ZeroLengthStateWithUnbufferedYield_Test::TestBody()::$_80)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_81)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateSuccess_Test::TestBody()::$_82)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_83)
Unexecuted instantiation: Unified_cpp_image_test_gtest0.cpp:mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<TestState, 16ul>::Truncated<ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84>(mozilla::image::SourceBufferIterator&, ImageStreamingLexer_TerminateFailure_Test::TestBody()::$_84)
738
739
  Maybe<LexerResult> SetTransition(const LexerTransition<State>& aTransition)
740
0
  {
741
0
    // There should be no transitions while we're buffering for a buffered read
742
0
    // unless they're to terminal states. (The terminal state transitions would
743
0
    // generally be triggered by error handling code.)
744
0
    MOZ_ASSERT_IF(!mBuffer.empty(),
745
0
                  aTransition.NextStateIsTerminal() ||
746
0
                  mBuffer.length() == mTransition.Size());
747
0
748
0
    // Similarly, the only transitions allowed in the middle of an unbuffered
749
0
    // read are to a terminal state, or a yield to the same state. Otherwise, we
750
0
    // should remain in the same state until the unbuffered read completes.
751
0
    MOZ_ASSERT_IF(mUnbufferedState,
752
0
                  aTransition.NextStateIsTerminal() ||
753
0
                  (aTransition.ControlFlow() == ControlFlowStrategy::YIELD &&
754
0
                   aTransition.NextState() == mTransition.UnbufferedState()) ||
755
0
                  mUnbufferedState->mBytesRemaining == 0);
756
0
757
0
    // If this transition is a yield, save the next state and return. We'll
758
0
    // handle the rest when Lex() gets called again.
759
0
    if (!aTransition.NextStateIsTerminal() &&
760
0
        aTransition.ControlFlow() == ControlFlowStrategy::YIELD) {
761
0
      mYieldingToState = Some(aTransition.NextState());
762
0
      return Some(LexerResult(Yield::OUTPUT_AVAILABLE));
763
0
    }
764
0
765
0
    // Update our transition.
766
0
    mTransition = aTransition;
767
0
768
0
    // Get rid of anything left over from the previous state.
769
0
    mBuffer.clear();
770
0
    mYieldingToState = Nothing();
771
0
    mUnbufferedState = Nothing();
772
0
773
0
    // If we reached a terminal state, let the caller know.
774
0
    if (mTransition.NextStateIsTerminal()) {
775
0
      return Some(LexerResult(mTransition.NextStateAsTerminal()));
776
0
    }
777
0
778
0
    // If we're entering an unbuffered state, record how long we'll stay in it.
779
0
    if (mTransition.Buffering() == BufferingStrategy::UNBUFFERED) {
780
0
      mUnbufferedState.emplace(mTransition.Size());
781
0
    }
782
0
783
0
    return Nothing();  // Keep processing.
784
0
  }
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::nsBMPDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::nsGIFDecoder2::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::ICOState> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::nsIconDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::nsJPEGDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::SetTransition(mozilla::image::LexerTransition<mozilla::image::nsPNGDecoder::State> const&)
Unexecuted instantiation: mozilla::image::StreamingLexer<TestState, 16ul>::SetTransition(mozilla::image::LexerTransition<TestState> const&)
785
786
  // State that tracks our position within an unbuffered read.
787
  struct UnbufferedState
788
  {
789
    explicit UnbufferedState(size_t aBytesRemaining)
790
      : mBytesRemaining(aBytesRemaining)
791
      , mBytesConsumedInCurrentChunk(0)
792
0
    { }
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsBMPDecoder::State, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsGIFDecoder2::State, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::ICOState, 32ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsIconDecoder::State, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsJPEGDecoder::State, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
Unexecuted instantiation: mozilla::image::StreamingLexer<TestState, 16ul>::UnbufferedState::UnbufferedState(unsigned long)
793
794
    size_t mBytesRemaining;
795
    size_t mBytesConsumedInCurrentChunk;
796
  };
797
798
  Vector<char, InlineBufferSize> mBuffer;
799
  LexerTransition<State> mTransition;
800
  const LexerTransition<State> mTruncatedTransition;
801
  Maybe<State> mYieldingToState;
802
  Maybe<UnbufferedState> mUnbufferedState;
803
};
804
805
} // namespace image
806
} // namespace mozilla
807
808
#endif // mozilla_image_StreamingLexer_h