/*---------------------------------------------------------------------------* * CircularBuffer.c * * * * Copyright 2007, 2008 Nuance Communciations, Inc. * * * * Licensed under the Apache License, Version 2.0 (the 'License'); * * you may not use this file except in compliance with the License. * * * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an 'AS IS' BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * *---------------------------------------------------------------------------*/ #ifdef _WIN32 #if _MSC_VER >= 1100 // Visual C++ 5.x #pragma warning( disable : 4786 4503 ) #endif #endif #include "CircularBuffer.h" #include "pmemory.h" #ifndef __vxworks #include <memory.h> #endif ESR_ReturnCode CircularBufferCreate(size_t capacity, const LCHAR* mtag, CircularBuffer** buffer) { CircularBuffer* Interface; if (buffer == NULL || capacity <= 0) return ESR_INVALID_ARGUMENT; Interface = (CircularBuffer *) MALLOC(sizeof(CircularBuffer) + capacity, mtag); if (Interface == NULL) return ESR_OUT_OF_MEMORY; Interface->capacity = capacity; CircularBufferReset(Interface); *buffer = Interface; return ESR_SUCCESS; } int CircularBufferRead(CircularBuffer* buffer, void* data, size_t bufSize) { size_t nbRead = 0; unsigned char *bufferData = NULL; if (buffer == NULL || (data == NULL && bufSize > 0)) return -1; if (buffer->size < bufSize) bufSize = buffer->size; if (bufSize == 0) return 0; bufferData = ((unsigned char *) buffer) + sizeof(CircularBuffer); if (buffer->readIdx >= buffer->writeIdx) { nbRead = buffer->capacity - buffer-> readIdx; if (nbRead > bufSize) nbRead = bufSize; memcpy(data, bufferData + buffer->readIdx, nbRead); buffer->size -= nbRead; buffer->readIdx += nbRead; if (buffer->readIdx == buffer->capacity) buffer->readIdx = 0; } if (nbRead < bufSize) { int toRead = bufSize - nbRead; memcpy(((unsigned char *) data) + nbRead, bufferData + buffer->readIdx, toRead); buffer->size -= toRead; buffer->readIdx += toRead; } return bufSize; } int CircularBufferSkip(CircularBuffer* buffer, size_t bufSize) { if ( buffer == NULL ) return -1; if (buffer->size < bufSize) bufSize = buffer->size; if (bufSize == 0) return 0; buffer->readIdx += bufSize; if (buffer->readIdx >= buffer->capacity) buffer->readIdx -= buffer->capacity; buffer->size -= bufSize; return bufSize; } int CircularBufferWrite(CircularBuffer* buffer, const void *data, size_t bufSize) { size_t nbWritten = 0; unsigned char *bufferData; size_t available = buffer->capacity - buffer->size; if (data == NULL && bufSize > 0) return -1; if (available < bufSize) /* We need to force an error to be logged here */ return -1; /* bufSize = available; Throwing data on the floor with no notice is asking for trouble */ if (bufSize == 0) return 0; bufferData = ((unsigned char*) buffer) + sizeof(CircularBuffer); if (buffer->writeIdx >= buffer->readIdx) { nbWritten = buffer->capacity - buffer->writeIdx; if (nbWritten > bufSize) nbWritten = bufSize; memcpy(bufferData + buffer->writeIdx, data, nbWritten); buffer->size += nbWritten; buffer->writeIdx += nbWritten; if (buffer->writeIdx == buffer->capacity) buffer->writeIdx = 0; } if (nbWritten < bufSize) { size_t toWrite = bufSize - nbWritten; memcpy(bufferData + buffer->writeIdx, ((unsigned char*) data) + nbWritten, toWrite); buffer->size += toWrite; buffer->writeIdx += toWrite; } return bufSize; } int CircularBufferUnwrite(CircularBuffer* buffer, size_t amount) { size_t available = buffer->capacity - buffer->size; if (available < amount) amount = available; buffer->size -= amount; return amount; }