14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  CircularBuffer.c  *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the 'License');          *
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  you may not use this file except in compliance with the License.         *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  You may obtain a copy of the License at                                  *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0                           *
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software      *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  distributed under the License is distributed on an 'AS IS' BASIS,        *
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  See the License for the specific language governing permissions and      *
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  limitations under the License.                                           *
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef _WIN32
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if _MSC_VER >= 1100    // Visual C++ 5.x
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#pragma warning( disable : 4786 4503 )
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "CircularBuffer.h"
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "pmemory.h"
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef __vxworks
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <memory.h>
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectESR_ReturnCode CircularBufferCreate(size_t capacity, const LCHAR* mtag, CircularBuffer** buffer)
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CircularBuffer* Interface;
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer == NULL || capacity <= 0)
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_INVALID_ARGUMENT;
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Interface = (CircularBuffer *) MALLOC(sizeof(CircularBuffer) + capacity, mtag);
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (Interface == NULL)
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return ESR_OUT_OF_MEMORY;
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Interface->capacity = capacity;
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  CircularBufferReset(Interface);
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *buffer = Interface;
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return ESR_SUCCESS;
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint CircularBufferRead(CircularBuffer* buffer, void* data, size_t bufSize)
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t nbRead = 0;
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *bufferData = NULL;
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer == NULL || (data == NULL && bufSize > 0))
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return -1;
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer->size < bufSize)
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bufSize = buffer->size;
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (bufSize == 0)
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 0;
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bufferData = ((unsigned char *) buffer) + sizeof(CircularBuffer);
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer->readIdx >= buffer->writeIdx)
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    nbRead = buffer->capacity - buffer-> readIdx;
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (nbRead > bufSize) nbRead = bufSize;
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(data, bufferData + buffer->readIdx, nbRead);
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->size -= nbRead;
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->readIdx += nbRead;
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (buffer->readIdx == buffer->capacity)
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      buffer->readIdx = 0;
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (nbRead < bufSize)
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int toRead = bufSize - nbRead;
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(((unsigned char *) data) + nbRead, bufferData + buffer->readIdx, toRead);
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->size -= toRead;
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->readIdx += toRead;
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return bufSize;
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint CircularBufferSkip(CircularBuffer* buffer, size_t bufSize)
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if ( buffer == NULL )
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return -1;
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer->size < bufSize)
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    bufSize = buffer->size;
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (bufSize == 0)
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 0;
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  buffer->readIdx += bufSize;
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer->readIdx >= buffer->capacity)
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->readIdx -= buffer->capacity;
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  buffer->size -= bufSize;
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return bufSize;
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint CircularBufferWrite(CircularBuffer* buffer, const void *data, size_t bufSize)
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t nbWritten = 0;
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  unsigned char *bufferData;
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t available = buffer->capacity - buffer->size;
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (data == NULL && bufSize > 0)
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return -1;
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (available < bufSize)	/* We need to force an error to be logged here */
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return -1;
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*    bufSize = available;	Throwing data on the floor with no notice is asking for trouble */
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (bufSize == 0)
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return 0;
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bufferData = ((unsigned char*) buffer) + sizeof(CircularBuffer);
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (buffer->writeIdx >= buffer->readIdx)
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    nbWritten = buffer->capacity - buffer->writeIdx;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (nbWritten > bufSize) nbWritten = bufSize;
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(bufferData + buffer->writeIdx, data, nbWritten);
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->size += nbWritten;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->writeIdx += nbWritten;
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (buffer->writeIdx == buffer->capacity)
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      buffer->writeIdx = 0;
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (nbWritten < bufSize)
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    size_t toWrite = bufSize - nbWritten;
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    memcpy(bufferData + buffer->writeIdx, ((unsigned char*) data) + nbWritten, toWrite);
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->size += toWrite;
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    buffer->writeIdx += toWrite;
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return bufSize;
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint CircularBufferUnwrite(CircularBuffer* buffer, size_t amount)
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  size_t available = buffer->capacity - buffer->size;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (available < amount)
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    amount = available;
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  buffer->size -= amount;
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return amount;
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
158