/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)

This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
**********/
// "liveMedia"
// Copyright (c) 1996-2020 Live Networks, Inc.  All rights reserved.
// Abstract class for parsing a byte stream
// Implementation

#include "StreamParser.hh"

#include <string.h>
#include <stdlib.h>

#define BANK_SIZE 150000

void StreamParser::flushInput() {
  fCurParserIndex = fSavedParserIndex = 0;
  fSavedRemainingUnparsedBits = fRemainingUnparsedBits = 0;
  fTotNumValidBytes = 0;
}

StreamParser::StreamParser(FramedSource* inputSource,
			   FramedSource::onCloseFunc* onInputCloseFunc,
			   void* onInputCloseClientData,
			   clientContinueFunc* clientContinueFunc,
			   void* clientContinueClientData)
  : fInputSource(inputSource), fClientOnInputCloseFunc(onInputCloseFunc),
    fClientOnInputCloseClientData(onInputCloseClientData),
    fClientContinueFunc(clientContinueFunc),
    fClientContinueClientData(clientContinueClientData),
    fSavedParserIndex(0), fSavedRemainingUnparsedBits(0),
    fCurParserIndex(0), fRemainingUnparsedBits(0),
    fTotNumValidBytes(0), fHaveSeenEOF(False) {
  fBank[0] = new unsigned char[BANK_SIZE];
  fBank[1] = new unsigned char[BANK_SIZE];
  fCurBankNum = 0;
  fCurBank = fBank[fCurBankNum];

  fLastSeenPresentationTime.tv_sec = 0; fLastSeenPresentationTime.tv_usec = 0;
}

StreamParser::~StreamParser() {
  delete[] fBank[0]; delete[] fBank[1];
}

void StreamParser::saveParserState() {
  fSavedParserIndex = fCurParserIndex;
  fSavedRemainingUnparsedBits = fRemainingUnparsedBits;
}

void StreamParser::restoreSavedParserState() {
  fCurParserIndex = fSavedParserIndex;
  fRemainingUnparsedBits = fSavedRemainingUnparsedBits;
}

void StreamParser::skipBits(unsigned numBits) {
  if (numBits <= fRemainingUnparsedBits) {
    fRemainingUnparsedBits -= numBits;
  } else {
    numBits -= fRemainingUnparsedBits;

    unsigned numBytesToExamine = (numBits+7)/8; // round up
    ensureValidBytes(numBytesToExamine);
    fCurParserIndex += numBytesToExamine;

    fRemainingUnparsedBits = 8*numBytesToExamine - numBits;
  }
}

unsigned StreamParser::getBits(unsigned numBits) {
  if (numBits <= fRemainingUnparsedBits) {
    unsigned char lastByte = *lastParsed();
    lastByte >>= (fRemainingUnparsedBits - numBits);
    fRemainingUnparsedBits -= numBits;

    return (unsigned)lastByte &~ ((~0u)<<numBits);
  } else {
    unsigned char lastByte;
    if (fRemainingUnparsedBits > 0) {
      lastByte = *lastParsed();
    } else {
      lastByte = 0;
    }

    unsigned remainingBits = numBits - fRemainingUnparsedBits; // > 0

    // For simplicity, read the next 4 bytes, even though we might not
    // need all of them here:
    unsigned result = test4Bytes();

    result >>= (32 - remainingBits);
    result |= (lastByte << remainingBits);
    if (numBits < 32) result &=~ ((~0u)<<numBits);

    unsigned const numRemainingBytes = (remainingBits+7)/8;
    fCurParserIndex += numRemainingBytes;
    fRemainingUnparsedBits = 8*numRemainingBytes - remainingBits;

    return result;
  }
}

unsigned StreamParser::bankSize() const {
  return BANK_SIZE;
}

#define NO_MORE_BUFFERED_INPUT 1

void StreamParser::ensureValidBytes1(unsigned numBytesNeeded) {
  // We need to read some more bytes from the input source.
  // First, clarify how much data to ask for:
  unsigned maxInputFrameSize = fInputSource->maxFrameSize();
  if (maxInputFrameSize > numBytesNeeded) numBytesNeeded = maxInputFrameSize;

  // First, check whether these new bytes would overflow the current
  // bank.  If so, start using a new bank now.
  if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
    // Swap banks, but save any still-needed bytes from the old bank:
    unsigned numBytesToSave = fTotNumValidBytes - fSavedParserIndex;
    unsigned char const* from = &curBank()[fSavedParserIndex];

    fCurBankNum = (fCurBankNum + 1)%2;
    fCurBank = fBank[fCurBankNum];
    memmove(curBank(), from, numBytesToSave);
    fCurParserIndex = fCurParserIndex - fSavedParserIndex;
    fSavedParserIndex = 0;
    fTotNumValidBytes = numBytesToSave;
  }

  // ASSERT: fCurParserIndex + numBytesNeeded > fTotNumValidBytes
  //      && fCurParserIndex + numBytesNeeded <= BANK_SIZE
  if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
    // If this happens, it means that we have too much saved parser state.
    // To fix this, increase BANK_SIZE as appropriate.
    fInputSource->envir() << "StreamParser internal error ("
			  << fCurParserIndex << " + "
			  << numBytesNeeded << " > "
			  << BANK_SIZE << ")\n";
    fInputSource->envir().internalError();
  }

  // Try to read as many new bytes as will fit in the current bank:
  unsigned maxNumBytesToRead = BANK_SIZE - fTotNumValidBytes;
  fInputSource->getNextFrame(&curBank()[fTotNumValidBytes],
			     maxNumBytesToRead,
			     afterGettingBytes, this,
			     onInputClosure, this);

  throw NO_MORE_BUFFERED_INPUT;
}

void StreamParser::afterGettingBytes(void* clientData,
				     unsigned numBytesRead,
				     unsigned /*numTruncatedBytes*/,
				     struct timeval presentationTime,
				     unsigned /*durationInMicroseconds*/){
  StreamParser* parser = (StreamParser*)clientData;
  if (parser != NULL) parser->afterGettingBytes1(numBytesRead, presentationTime);
}

void StreamParser::afterGettingBytes1(unsigned numBytesRead, struct timeval presentationTime) {
  // Sanity check: Make sure we didn't get too many bytes for our bank:
  if (fTotNumValidBytes + numBytesRead > BANK_SIZE) {
    fInputSource->envir()
      << "StreamParser::afterGettingBytes() warning: read "
      << numBytesRead << " bytes; expected no more than "
      << BANK_SIZE - fTotNumValidBytes << "\n";
  }

  fLastSeenPresentationTime = presentationTime;

  unsigned char* ptr = &curBank()[fTotNumValidBytes];
  fTotNumValidBytes += numBytesRead;

  // Continue our original calling source where it left off:
  restoreSavedParserState();
      // Sigh... this is a crock; things would have been a lot simpler
      // here if we were using threads, with synchronous I/O...
  fClientContinueFunc(fClientContinueClientData, ptr, numBytesRead, presentationTime);
}

void StreamParser::onInputClosure(void* clientData) {
  StreamParser* parser = (StreamParser*)clientData;
  if (parser != NULL) parser->onInputClosure1();
}

void StreamParser::onInputClosure1() {
  if (!fHaveSeenEOF) {
    // We're hitting EOF for the first time.  Set our 'EOF' flag, and continue parsing, as if we'd just read 0 bytes of data.
    // This allows the parser to re-parse any remaining unparsed data (perhaps while testing for EOF at the end):
    fHaveSeenEOF = True;
    afterGettingBytes1(0, fLastSeenPresentationTime);
  } else {
    // We're hitting EOF for the second time.  Now, we handle the source input closure:
    fHaveSeenEOF = False;
    if (fClientOnInputCloseFunc != NULL) (*fClientOnInputCloseFunc)(fClientOnInputCloseClientData);
  }
}
