1 /*---------------------------------------------------------------------------* 2 * CircularBuffer.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 21 22 #ifdef _WIN32 23 #if _MSC_VER >= 1100 // Visual C++ 5.x 24 #pragma warning( disable : 4786 4503 ) 25 #endif 26 #endif 27 28 #include "CircularBuffer.h" 29 #include "pmemory.h" 30 #ifndef __vxworks 31 #include <memory.h> 32 #endif 33 34 ESR_ReturnCode CircularBufferCreate(size_t capacity, const LCHAR* mtag, CircularBuffer** buffer) 35 { 36 CircularBuffer* Interface; 37 if (buffer == NULL || capacity <= 0) 38 return ESR_INVALID_ARGUMENT; 39 40 Interface = (CircularBuffer *) MALLOC(sizeof(CircularBuffer) + capacity, mtag); 41 if (Interface == NULL) 42 return ESR_OUT_OF_MEMORY; 43 Interface->capacity = capacity; 44 CircularBufferReset(Interface); 45 *buffer = Interface; 46 return ESR_SUCCESS; 47 } 48 49 50 int CircularBufferRead(CircularBuffer* buffer, void* data, size_t bufSize) 51 { 52 size_t nbRead = 0; 53 unsigned char *bufferData = NULL; 54 55 if (buffer == NULL || (data == NULL && bufSize > 0)) 56 return -1; 57 58 if (buffer->size < bufSize) 59 bufSize = buffer->size; 60 61 if (bufSize == 0) 62 return 0; 63 64 bufferData = ((unsigned char *) buffer) + sizeof(CircularBuffer); 65 66 if (buffer->readIdx >= buffer->writeIdx) 67 { 68 nbRead = buffer->capacity - buffer-> readIdx; 69 if (nbRead > bufSize) nbRead = bufSize; 70 71 memcpy(data, bufferData + buffer->readIdx, nbRead); 72 buffer->size -= nbRead; 73 buffer->readIdx += nbRead; 74 if (buffer->readIdx == buffer->capacity) 75 buffer->readIdx = 0; 76 } 77 78 if (nbRead < bufSize) 79 { 80 int toRead = bufSize - nbRead; 81 memcpy(((unsigned char *) data) + nbRead, bufferData + buffer->readIdx, toRead); 82 buffer->size -= toRead; 83 buffer->readIdx += toRead; 84 } 85 86 return bufSize; 87 } 88 89 int CircularBufferSkip(CircularBuffer* buffer, size_t bufSize) 90 { 91 if ( buffer == NULL ) 92 return -1; 93 94 if (buffer->size < bufSize) 95 bufSize = buffer->size; 96 97 if (bufSize == 0) 98 return 0; 99 100 buffer->readIdx += bufSize; 101 if (buffer->readIdx >= buffer->capacity) 102 buffer->readIdx -= buffer->capacity; 103 104 buffer->size -= bufSize; 105 106 return bufSize; 107 } 108 109 int CircularBufferWrite(CircularBuffer* buffer, const void *data, size_t bufSize) 110 { 111 size_t nbWritten = 0; 112 unsigned char *bufferData; 113 size_t available = buffer->capacity - buffer->size; 114 115 if (data == NULL && bufSize > 0) 116 return -1; 117 118 if (available < bufSize) /* We need to force an error to be logged here */ 119 return -1; 120 /* bufSize = available; Throwing data on the floor with no notice is asking for trouble */ 121 122 if (bufSize == 0) 123 return 0; 124 125 bufferData = ((unsigned char*) buffer) + sizeof(CircularBuffer); 126 127 if (buffer->writeIdx >= buffer->readIdx) 128 { 129 nbWritten = buffer->capacity - buffer->writeIdx; 130 if (nbWritten > bufSize) nbWritten = bufSize; 131 memcpy(bufferData + buffer->writeIdx, data, nbWritten); 132 buffer->size += nbWritten; 133 buffer->writeIdx += nbWritten; 134 if (buffer->writeIdx == buffer->capacity) 135 buffer->writeIdx = 0; 136 } 137 138 if (nbWritten < bufSize) 139 { 140 size_t toWrite = bufSize - nbWritten; 141 memcpy(bufferData + buffer->writeIdx, ((unsigned char*) data) + nbWritten, toWrite); 142 buffer->size += toWrite; 143 buffer->writeIdx += toWrite; 144 } 145 146 return bufSize; 147 } 148 149 int CircularBufferUnwrite(CircularBuffer* buffer, size_t amount) 150 { 151 size_t available = buffer->capacity - buffer->size; 152 153 if (available < amount) 154 amount = available; 155 buffer->size -= amount; 156 return amount; 157 } 158