⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swibufferedinputstream.cpp

📁 openvxi3.4是一个voicexml对话脚本语言的解释器源码.可用VC6.0编译.
💻 CPP
字号:

/****************License************************************************
 * Vocalocity OpenVXI
 * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *  
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
 * registered trademarks of Vocalocity, Inc. 
 * OpenVXI is a trademark of Scansoft, Inc. and used under license 
 * by Vocalocity.
 ***********************************************************************/

#include "SWIbufferedInputStream.hpp"
#include "SWIoutputStream.hpp"
#include <string.h>

SWIbufferedInputStream::SWIbufferedInputStream(SWIinputStream *stream,
                                     int bufSize, int lookAhead,
                                     bool ownStream):
  SWIfilterInputStream(stream, ownStream),
  _eofSeen(false), _buffer(NULL)
{
  _lookAhead = (lookAhead < 1) ? 1 : lookAhead;
  if (bufSize < 1) bufSize = 1;
  _readSize = bufSize > _lookAhead ? bufSize : _lookAhead;
  _pos = _end = _buffer =
    new unsigned char[bufSize + _lookAhead - 1];
}

SWIbufferedInputStream::~SWIbufferedInputStream()
{
  close();
}

int SWIbufferedInputStream::read()
{
  if (_buffer == NULL) return ILLEGAL_STATE;
  if (_pos < _end) return *_pos++;

  int rc = fillBuffer();
  if (rc < 0) return rc;
  rc = *_pos++;
  return rc;
}

int SWIbufferedInputStream::readBytes(void *data, int dataSize)
{
  if (_buffer == NULL) return ILLEGAL_STATE;
  if (dataSize  < 0 ) return INVALID_ARGUMENT;
  if (data == NULL && dataSize > 0) return INVALID_ARGUMENT;

  unsigned char *p0 = static_cast<unsigned char *>(data);
  unsigned char *p = p0;
  unsigned char *q = p0 + dataSize;
  int rc = SWIstream::SUCCESS;

  for (;;)
  {
    while (_pos < _end && p < q) *p++ = *_pos++;

    // Have we read the required number of bytes?
    if (p == q) break;

    // Ran out of bytes in our buffer.  Only fill the buffer if that would
    // not block and we haven't read a byte yet.
    if (p > p0 && SWIfilterInputStream::waitReady(0) != SUCCESS) break;

    // Bail out if an error occurs while filling the buffer.
    if ((rc = fillBuffer()) < 0) break;
  }

  int nbRead = p - p0;
  return nbRead > 0 ? nbRead : rc;
}

int SWIbufferedInputStream::peek(int offset) const
{
  if (offset < 0 || offset >= _lookAhead)
    return INVALID_ARGUMENT;

  if (_buffer == NULL) return ILLEGAL_STATE;
  if (_end - _pos > offset) return _pos[offset];

  int remaining =
    const_cast<SWIbufferedInputStream *>(this)->fillBuffer(offset);

  if (remaining < 0) return remaining;
  if (remaining > offset) return _pos[offset];
  return END_OF_FILE;
}

int SWIbufferedInputStream::getLookAhead() const
{
  return _lookAhead;
}

int SWIbufferedInputStream::readLine(SWIoutputStream& outstream)
{
  if (_buffer == NULL) return ILLEGAL_STATE;
  int rc = 0;
  int nbWritten = 0;

  for (;;)
  {
    unsigned char *p = _pos;

    while (p < _end && *p != '\r' && *p != '\n') p++;

    int len = p - _pos;

    if (len > 0)
    {
      if ((rc = outstream.writeBytes(_pos, len)) != len)
        break;

      nbWritten += len;
      _pos = p;
    }

    if (_pos < _end)
    {
      if (*_pos == '\r')
      {
        _pos++;
        if ((rc = fillBuffer()) < 0)
          break;
      }
      if (*_pos == '\n')
        _pos++;
      break;
    }
    else if ((rc = fillBuffer()) < 0)
      break;
  }

  if (nbWritten == 0)
    return rc > 0 ? 0 : rc;

  return nbWritten;
}

int SWIbufferedInputStream::readLine(char *buffer, int bufSize)
{
  if (_buffer == NULL) return ILLEGAL_STATE;
  int rc = 0;
  char *p = buffer;
  char *q = buffer + bufSize - 1; // keep one byte for '\0'

  while (p < q)
  {
    while (_pos < _end && p < q)
    {
      switch (*_pos)
      {
       case '\r':
         _pos++;
         rc = fillBuffer();
         if (rc <= 0) goto terminateString;
         if (*_pos != '\n') goto terminateString;
         // no break: intentional
       case '\n':
         _pos++;
         goto terminateString;
       default:
         *p++ = *_pos++;
         break;
      }
    }
    rc = fillBuffer();
    if (rc <= 0) break;
  }

 terminateString:
  *p = '\0';

  if (p == q)
    return BUFFER_OVERFLOW;

  int len = p - buffer;
  if (len == 0)
    return rc > 0 ? 0 : rc;

  return len;
}

bool SWIbufferedInputStream::isBuffered() const
{
  return true;
}

SWIstream::Result SWIbufferedInputStream::waitReady(long timeoutMs)
{
  if (_buffer == NULL) return ILLEGAL_STATE;
  if (_pos < _end) return SUCCESS;
  return SWIfilterInputStream::waitReady(timeoutMs);
}

SWIstream::Result SWIbufferedInputStream::close()
{
  delete [] _buffer;
  _end = _pos = _buffer = NULL;
  return SWIfilterInputStream::close();
}

/**
 * Returns the number of bytes available in the buffer.
 **/
int SWIbufferedInputStream::fillBuffer(int lowBound)
{
  int remaining = _end - _pos;

  // If there are enough remaining characters, return them so that we won't
  // block trying to fill the look-ahead buffer.
  if (remaining > lowBound) return remaining;

  if (remaining == 0 && _eofSeen) return END_OF_FILE;

  // shift data at the beginning of the buffer.
  memmove(_buffer, _pos, remaining);

  _pos = _buffer;
  _end = _pos + remaining;

  // Now read from the stream.
  int rc = SWIfilterInputStream::readBytes(_end, _readSize - remaining);

  switch (rc)
  {
   case END_OF_FILE:
     _eofSeen = true;
     return remaining;
   case 0:
     // This should not really happen, it should either return TIMED_OUT or
     // WOULD_BLOCK.
     return TIMED_OUT;
   default:
     if (rc > 0)
     {
       _end += rc;
       return remaining + rc;
     }
     return rc;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -