langpackedit v0.13 -- from 8f9f0878
[wdl.git] / WDL / circbuf.h
blob25f8165d042876948f6d6787fbec018edfb4e6d3
1 /*
2 WDL - circbuf.h
3 Copyright (C) 2005 Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
25 This file provides a simple class for a circular FIFO queue of bytes.
29 #ifndef _WDL_CIRCBUF_H_
30 #define _WDL_CIRCBUF_H_
32 #include "heapbuf.h"
34 class WDL_CircBuf
36 public:
37 WDL_CircBuf()
39 m_inbuf = m_wrptr = 0;
40 m_buf = NULL;
41 m_alloc = 0;
43 ~WDL_CircBuf()
45 free(m_buf);
47 void SetSize(int size)
49 if (size<0) size=0;
50 m_inbuf = m_wrptr = 0;
51 if (size != m_alloc || !m_buf)
53 m_alloc = size;
54 free(m_buf);
55 m_buf = size ? (char*)malloc(size) : NULL;
59 void SetSizePreserveContents(int newsz)
61 if (newsz < NbInBuf()) newsz = NbInBuf(); // do not allow destructive resize down
62 const int oldsz = m_alloc, dsize = newsz - oldsz;
63 if (!dsize) return;
64 if (!m_inbuf||!m_buf) { SetSize(newsz); return; }
66 const int div1 = m_inbuf - m_wrptr; // div1>0 is size of end block, div1<0 is offset of start block
67 char *buf=NULL;
68 if (dsize > 0)
70 buf = (char *)realloc(m_buf, newsz);
71 if (WDL_NORMALLY(buf) && div1 > 0) // block crossing loop, need to shuffle some data
73 if (div1 > m_wrptr) // m_wrptr is size of start block, div1 is size of end block
75 // end block is larger than start, move some of start block to end of end block and shuffle forward start
76 if (dsize >= m_wrptr)
78 if (m_wrptr>0) memmove(buf+oldsz,buf,m_wrptr);
79 m_wrptr += oldsz;
81 else
83 memmove(buf + oldsz, buf, dsize);
84 m_wrptr -= dsize;
85 memmove(buf, buf+dsize, m_wrptr);
88 else // end block is smaller, move it to the new end of buffer
90 memmove(buf + newsz - div1, buf + oldsz - div1, div1);
94 else if (div1 < 0) // shrinking, and not a wrapped buffer
96 if (m_wrptr > newsz)
98 memmove(m_buf,m_buf-div1, m_inbuf);
99 m_wrptr = m_inbuf;
101 buf = (char *)realloc(m_buf, newsz);
104 if (!buf) // failed realloc(), or sizing down with block crossing loop boundary
106 buf = (char *)malloc(newsz);
107 if (WDL_NOT_NORMALLY(!buf)) return;
108 const int peeked = Peek(buf,0,m_inbuf);
109 if (peeked != m_inbuf) { WDL_ASSERT(peeked == m_inbuf); }
110 free(m_buf);
111 m_wrptr = m_inbuf = peeked;
113 if (m_wrptr > newsz) { WDL_ASSERT(m_wrptr <= newsz); }
114 if (m_wrptr >= newsz) m_wrptr=0;
115 m_alloc = newsz;
116 m_buf = buf;
118 void Reset() { m_inbuf = m_wrptr = 0; }
119 int Add(const void *buf, int l)
121 if (!m_buf) return 0;
122 const int bf = m_alloc - m_inbuf;
123 if (l>bf) l = bf;
124 if (l > 0)
126 m_wrptr = __write_bytes(m_wrptr,l,buf);
127 m_inbuf += l;
129 return l;
131 void UnAdd(int amt)
133 if (amt > 0)
135 if (amt > m_inbuf) amt=m_inbuf;
136 m_wrptr -= amt;
137 if (m_wrptr < 0) m_wrptr += m_alloc;
138 m_inbuf -= amt;
142 void Skip(int l) // can be used to rewind read pointer
144 m_inbuf -= l;
145 if (m_inbuf<0) m_inbuf=0;
146 else if (m_inbuf>m_alloc) m_inbuf=m_alloc;
149 int Peek(void *buf, int offs, int len) const
151 if (offs<0||!m_buf) return 0;
152 const int ibo = m_inbuf-offs;
153 if (len > ibo) len = ibo;
154 if (len > 0)
156 int rp = m_wrptr - ibo;
157 if (rp < 0) rp += m_alloc;
158 const int wr1 = m_alloc - rp;
159 char * const rd = m_buf;
160 if (wr1 < len)
162 memcpy(buf,rd+rp,wr1);
163 memcpy((char*)buf+wr1,rd,len-wr1);
165 else
167 memcpy(buf,rd+rp,len);
170 return len;
173 void WriteAtReadPointer(const void *buf, int len, int offs=0)
175 if (WDL_NOT_NORMALLY(offs<0) || WDL_NOT_NORMALLY(offs>=m_inbuf)) return;
176 if (!m_buf || len<1) return;
177 if (offs+len > m_inbuf) len = m_inbuf-offs;
179 int write_offs = m_wrptr - m_inbuf + offs;
180 if (write_offs < 0) write_offs += m_alloc;
181 __write_bytes(write_offs, len, buf);
184 int Get(void *buf, int l)
186 const int amt = Peek(buf,0,l);
187 m_inbuf -= amt;
188 return amt;
190 int NbFree() const { return m_alloc - m_inbuf; } // formerly Available()
191 int NbInBuf() const { return m_inbuf; }
192 int GetTotalSize() const { return m_alloc; }
194 private:
195 int __write_bytes(int wrptr, int l, const void *buf) // no bounds checking, return end offset
197 const int wr1 = m_alloc-wrptr;
198 char * const p = m_buf, * const pw = p + wrptr;
199 if (wr1 < l)
201 if (buf)
203 memcpy(pw, buf, wr1);
204 memcpy(p, (char*)buf + wr1, l-wr1);
206 else
208 memset(pw, 0, wr1);
209 memset(p, 0, l-wr1);
211 return l-wr1;
214 if (buf) memcpy(pw, buf, l);
215 else memset(pw, 0, l);
216 return wr1 == l ? 0 : wrptr+l;
219 char *m_buf;
220 int m_inbuf, m_wrptr,m_alloc;
221 } WDL_FIXALIGN;
224 template <class T>
225 class WDL_TypedCircBuf
227 public:
229 WDL_TypedCircBuf() {}
230 ~WDL_TypedCircBuf() {}
232 void SetSize(int size)
234 mBuf.SetSize(size * sizeof(T));
236 void SetSizePreserveContents(int size)
238 mBuf.SetSizePreserveContents(size*sizeof(T));
241 void Reset()
243 mBuf.Reset();
246 void UnAdd(int l) { mBuf.UnAdd(l*sizeof(T)); }
248 int Add(const T* buf, int l)
250 return mBuf.Add(buf, l * sizeof(T)) / sizeof(T);
253 int Get(T* buf, int l)
255 return mBuf.Get(buf, l * sizeof(T)) / sizeof(T);
258 int Peek(T* buf, int offs, int l)
260 return mBuf.Peek(buf, offs*sizeof(T), l * sizeof(T)) / sizeof(T);
262 void Skip(int l) { mBuf.Skip(l*sizeof(T)); }
264 void WriteAtReadPointer(const void *buf, int len, int offs=0) { mBuf.WriteAtReadPointer(buf,len*sizeof(T),offs*sizeof(T)); }
266 int NbFree() const { return mBuf.NbFree() / sizeof(T); } // formerly Available()
267 int ItemsInQueue() const { return mBuf.NbInBuf() / sizeof(T); }
268 int NbInBuf() const { return mBuf.NbInBuf() / sizeof(T); }
269 int GetTotalSize() const { return mBuf.GetTotalSize() / sizeof(T); }
271 private:
272 WDL_CircBuf mBuf;
273 } WDL_FIXALIGN;
275 #endif