1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com/*---------------------------------------------------------------------------* 2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * CircularBuffer.c * 3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * * 4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Copyright 2007, 2008 Nuance Communciations, Inc. * 5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * * 6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Licensed under the Apache License, Version 2.0 (the 'License'); * 7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * you may not use this file except in compliance with the License. * 8cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * * 9cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * You may obtain a copy of the License at * 108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * http://www.apache.org/licenses/LICENSE-2.0 * 118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * * 128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * Unless required by applicable law or agreed to in writing, software * 138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * distributed under the License is distributed on an 'AS IS' BASIS, * 148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * See the License for the specific language governing permissions and * 168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * limitations under the License. * 178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * * 188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *---------------------------------------------------------------------------*/ 198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#ifdef _WIN32 238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#if _MSC_VER >= 1100 // Visual C++ 5.x 248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#pragma warning( disable : 4786 4503 ) 258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#endif 268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#endif 278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "CircularBuffer.h" 298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "pmemory.h" 308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#ifndef __vxworks 318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include <memory.h> 328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#endif 338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comESR_ReturnCode CircularBufferCreate(size_t capacity, const LCHAR* mtag, CircularBuffer** buffer) 358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CircularBuffer* Interface; 378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer == NULL || capacity <= 0) 388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return ESR_INVALID_ARGUMENT; 398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com Interface = (CircularBuffer *) MALLOC(sizeof(CircularBuffer) + capacity, mtag); 418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (Interface == NULL) 428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return ESR_OUT_OF_MEMORY; 438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com Interface->capacity = capacity; 448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CircularBufferReset(Interface); 458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *buffer = Interface; 468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return ESR_SUCCESS; 478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comint CircularBufferRead(CircularBuffer* buffer, void* data, size_t bufSize) 518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com size_t nbRead = 0; 538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com unsigned char *bufferData = NULL; 548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer == NULL || (data == NULL && bufSize > 0)) 568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return -1; 578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->size < bufSize) 598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bufSize = buffer->size; 608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (bufSize == 0) 628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return 0; 638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bufferData = ((unsigned char *) buffer) + sizeof(CircularBuffer); 658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->readIdx >= buffer->writeIdx) 678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nbRead = buffer->capacity - buffer-> readIdx; 698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (nbRead > bufSize) nbRead = bufSize; 708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com memcpy(data, bufferData + buffer->readIdx, nbRead); 728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size -= nbRead; 738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->readIdx += nbRead; 748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->readIdx == buffer->capacity) 758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->readIdx = 0; 768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (nbRead < bufSize) 798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com int toRead = bufSize - nbRead; 818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com memcpy(((unsigned char *) data) + nbRead, bufferData + buffer->readIdx, toRead); 828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size -= toRead; 838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->readIdx += toRead; 848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return bufSize; 878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comint CircularBufferSkip(CircularBuffer* buffer, size_t bufSize) 908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ( buffer == NULL ) 928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return -1; 938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->size < bufSize) 958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bufSize = buffer->size; 968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (bufSize == 0) 988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return 0; 998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->readIdx += bufSize; 1018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->readIdx >= buffer->capacity) 1028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->readIdx -= buffer->capacity; 1038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size -= bufSize; 1058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return bufSize; 1078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comint CircularBufferWrite(CircularBuffer* buffer, const void *data, size_t bufSize) 1108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 1118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com size_t nbWritten = 0; 1128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com unsigned char *bufferData; 1138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com size_t available = buffer->capacity - buffer->size; 1148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (data == NULL && bufSize > 0) 1168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return -1; 1178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (available < bufSize) /* We need to force an error to be logged here */ 1198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return -1; 1208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/* bufSize = available; Throwing data on the floor with no notice is asking for trouble */ 1218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (bufSize == 0) 1238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return 0; 1248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bufferData = ((unsigned char*) buffer) + sizeof(CircularBuffer); 1268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->writeIdx >= buffer->readIdx) 1288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nbWritten = buffer->capacity - buffer->writeIdx; 1308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (nbWritten > bufSize) nbWritten = bufSize; 1318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com memcpy(bufferData + buffer->writeIdx, data, nbWritten); 1328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size += nbWritten; 1338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->writeIdx += nbWritten; 1348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (buffer->writeIdx == buffer->capacity) 1358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->writeIdx = 0; 1368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (nbWritten < bufSize) 1398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com size_t toWrite = bufSize - nbWritten; 1418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com memcpy(bufferData + buffer->writeIdx, ((unsigned char*) data) + nbWritten, toWrite); 1428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size += toWrite; 1438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->writeIdx += toWrite; 1448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return bufSize; 1478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comint CircularBufferUnwrite(CircularBuffer* buffer, size_t amount) 1508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 1518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com size_t available = buffer->capacity - buffer->size; 1528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (available < amount) 1548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com amount = available; 1558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com buffer->size -= amount; 1568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return amount; 1578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com