| /*---------------------------------------------------------------------------* |
| * 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; |
| } |