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
CircularBufferCreate(size_t capacity,const LCHAR * mtag,CircularBuffer ** buffer)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
CircularBufferRead(CircularBuffer * buffer,void * data,size_t bufSize)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
CircularBufferSkip(CircularBuffer * buffer,size_t bufSize)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
CircularBufferWrite(CircularBuffer * buffer,const void * data,size_t bufSize)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
CircularBufferUnwrite(CircularBuffer * buffer,size_t amount)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