StreamingLexer.h 30 KB

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