LCOV - code coverage report
Current view: top level - xpcom/ds - IncrementalTokenizer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 93 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "mozilla/IncrementalTokenizer.h"
       8             : 
       9             : #include "mozilla/AutoRestore.h"
      10             : 
      11             : #include "nsIInputStream.h"
      12             : #include "IncrementalTokenizer.h"
      13             : #include <algorithm>
      14             : 
      15             : namespace mozilla {
      16             : 
      17           0 : IncrementalTokenizer::IncrementalTokenizer(Consumer&& aConsumer,
      18             :                                            const char * aWhitespaces,
      19             :                                            const char * aAdditionalWordChars,
      20           0 :                                            uint32_t aRawMinBuffered)
      21             :   : TokenizerBase(aWhitespaces, aAdditionalWordChars)
      22             : #ifdef DEBUG
      23             :   , mConsuming(false)
      24             : #endif
      25             :   , mNeedMoreInput(false)
      26             :   , mRollback(false)
      27             :   , mInputCursor(0)
      28           0 :   , mConsumer(Move(aConsumer))
      29             : {
      30           0 :   mInputFinished = false;
      31           0 :   mMinRawDelivery = aRawMinBuffered;
      32           0 : }
      33             : 
      34           0 : nsresult IncrementalTokenizer::FeedInput(const nsACString & aInput)
      35             : {
      36           0 :   NS_ENSURE_TRUE(mConsumer, NS_ERROR_NOT_INITIALIZED);
      37           0 :   MOZ_ASSERT(!mInputFinished);
      38             : 
      39           0 :   mInput.Cut(0, mInputCursor);
      40           0 :   mInputCursor = 0;
      41             : 
      42           0 :   mInput.Append(aInput);
      43             : 
      44           0 :   return Process();
      45             : }
      46             : 
      47           0 : nsresult IncrementalTokenizer::FeedInput(nsIInputStream * aInput, uint32_t aCount)
      48             : {
      49           0 :   NS_ENSURE_TRUE(mConsumer, NS_ERROR_NOT_INITIALIZED);
      50           0 :   MOZ_ASSERT(!mInputFinished);
      51           0 :   MOZ_ASSERT(!mConsuming);
      52             : 
      53           0 :   mInput.Cut(0, mInputCursor);
      54           0 :   mInputCursor = 0;
      55             : 
      56           0 :   nsresult rv = NS_OK;
      57           0 :   while (NS_SUCCEEDED(rv) && aCount) {
      58           0 :     nsCString::index_type remainder = mInput.Length();
      59             :     nsCString::index_type load =
      60           0 :       std::min<nsCString::index_type>(aCount, PR_UINT32_MAX - remainder);
      61             : 
      62           0 :     if (!load) {
      63             :       // To keep the API simple, we fail if the input data buffer if filled.
      64             :       // It's highly unlikely there will ever be such amout of data cumulated
      65             :       // unless a logic fault in the consumer code.
      66           0 :       NS_ERROR("IncrementalTokenizer consumer not reading data?");
      67           0 :       return NS_ERROR_OUT_OF_MEMORY;
      68             :     }
      69             : 
      70           0 :     if (!mInput.SetLength(remainder + load, fallible)) {
      71           0 :       return NS_ERROR_OUT_OF_MEMORY;
      72             :     }
      73             : 
      74           0 :     nsCString::char_iterator buffer = mInput.BeginWriting() + remainder;
      75             : 
      76             :     uint32_t read;
      77           0 :     rv = aInput->Read(buffer, load, &read);
      78           0 :     if (NS_SUCCEEDED(rv)) {
      79             :       // remainder + load fits the uint32_t size, so must remainder + read.
      80           0 :       mInput.SetLength(remainder + read);
      81           0 :       aCount -= read;
      82             : 
      83           0 :       rv = Process();
      84             :     }
      85             :   }
      86             : 
      87           0 :   return rv;
      88             : }
      89             : 
      90           0 : nsresult IncrementalTokenizer::FinishInput()
      91             : {
      92           0 :   NS_ENSURE_TRUE(mConsumer, NS_ERROR_NOT_INITIALIZED);
      93           0 :   MOZ_ASSERT(!mInputFinished);
      94           0 :   MOZ_ASSERT(!mConsuming);
      95             : 
      96           0 :   mInput.Cut(0, mInputCursor);
      97           0 :   mInputCursor = 0;
      98             : 
      99           0 :   mInputFinished = true;
     100           0 :   nsresult rv = Process();
     101           0 :   mConsumer = nullptr;
     102           0 :   return rv;
     103             : }
     104             : 
     105           0 : bool IncrementalTokenizer::Next(Token & aToken)
     106             : {
     107             :   // Assert we are called only from the consumer callback
     108           0 :   MOZ_ASSERT(mConsuming);
     109             : 
     110           0 :   if (mPastEof) {
     111           0 :     return false;
     112             :   }
     113             : 
     114           0 :   nsACString::const_char_iterator next = Parse(aToken);
     115           0 :   mPastEof = aToken.Type() == TOKEN_EOF;
     116           0 :   if (next == mCursor && !mPastEof) {
     117             :     // Not enough input to make a deterministic decision.
     118           0 :     return false;
     119             :   }
     120             : 
     121           0 :   AssignFragment(aToken, mCursor, next);
     122           0 :   mCursor = next;
     123           0 :   return true;
     124             : }
     125             : 
     126           0 : void IncrementalTokenizer::NeedMoreInput()
     127             : {
     128             :   // Assert we are called only from the consumer callback
     129           0 :   MOZ_ASSERT(mConsuming);
     130             : 
     131             :   // When the input has been finished, we can't set the flag to prevent
     132             :   // indefinite wait for more input (that will never come)
     133           0 :   mNeedMoreInput = !mInputFinished;
     134           0 : }
     135             : 
     136           0 : void IncrementalTokenizer::Rollback()
     137             : {
     138             :   // Assert we are called only from the consumer callback
     139           0 :   MOZ_ASSERT(mConsuming);
     140             : 
     141           0 :   mRollback = true;
     142           0 : }
     143             : 
     144           0 : nsresult IncrementalTokenizer::Process()
     145             : {
     146             : #ifdef DEBUG
     147             :   // Assert we are not re-entered
     148           0 :   MOZ_ASSERT(!mConsuming);
     149             : 
     150           0 :   AutoRestore<bool> consuming(mConsuming);
     151           0 :   mConsuming = true;
     152             : #endif
     153             : 
     154           0 :   MOZ_ASSERT(!mPastEof);
     155             : 
     156           0 :   nsresult rv = NS_OK;
     157             : 
     158           0 :   mInput.BeginReading(mCursor);
     159           0 :   mCursor += mInputCursor;
     160           0 :   mInput.EndReading(mEnd);
     161             : 
     162           0 :   while (NS_SUCCEEDED(rv) && !mPastEof) {
     163           0 :     Token token;
     164           0 :     nsACString::const_char_iterator next = Parse(token);
     165           0 :     mPastEof = token.Type() == TOKEN_EOF;
     166           0 :     if (next == mCursor && !mPastEof) {
     167             :       // Not enough input to make a deterministic decision.
     168           0 :       break;
     169             :     }
     170             : 
     171           0 :     AssignFragment(token, mCursor, next);
     172             : 
     173           0 :     nsACString::const_char_iterator rollback = mCursor;
     174           0 :     mCursor = next;
     175             : 
     176           0 :     mNeedMoreInput = mRollback = false;
     177             : 
     178           0 :     rv = mConsumer(token, *this);
     179           0 :     if (NS_FAILED(rv)) {
     180           0 :       break;
     181             :     }
     182           0 :     if (mNeedMoreInput || mRollback) {
     183           0 :       mCursor = rollback;
     184           0 :       mPastEof = false;
     185           0 :       if (mNeedMoreInput) {
     186           0 :         break;
     187             :       }
     188             :     }
     189             :   }
     190             : 
     191           0 :   mInputCursor = mCursor - mInput.BeginReading();
     192           0 :   return rv;
     193             : }
     194             : 
     195             : } // mozilla

Generated by: LCOV version 1.13