Merge pull request #110 from tesselode/fixes
[wdl/wdl-ol.git] / WDL / queue.h
blob35b97f769abde08a4e830a810e9237e2530bd964
1 /*
2 WDL - queue.h
3 Copyright (C) 2005 and later, 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 FIFO queue of bytes. It uses a simple buffer,
26 so should not generally be used for large quantities of data (it can advance the queue
27 pointer, but Compact() needs to be called regularly to keep memory usage down, and when
28 it is called, there's a memcpy() penalty for the remaining data. oh well, is what it is).
30 You may also wish to look at fastqueue.h or circbuf.h if these limitations aren't acceptable.
34 #ifndef _WDL_QUEUE_H_
35 #define _WDL_QUEUE_H_
37 #include "heapbuf.h"
40 class WDL_Queue
42 public:
43 WDL_Queue() : m_hb(4096 WDL_HEAPBUF_TRACEPARM("WDL_Queue")), m_pos(0) { }
44 WDL_Queue(int hbgran) : m_hb(hbgran WDL_HEAPBUF_TRACEPARM("WDL_Queue")), m_pos(0) { }
45 ~WDL_Queue() { }
47 template <class T> void* AddT(T* buf)
49 return Add(buf, sizeof(T));
52 void *Add(const void *buf, int len)
54 int olen=m_hb.GetSize();
55 if (m_pos >= olen) m_pos=olen=0; // if queue is empty then autoreset it
57 char *newbuf=(char *)m_hb.ResizeOK(olen+len,false);
58 if (newbuf)
60 newbuf += olen;
61 if (buf) memcpy(newbuf,buf,len);
63 return newbuf;
66 template <class T> T* GetT(T* val=0)
68 T* p = (T*) Get(sizeof(T));
69 if (val && p) *val = *p;
70 return p;
73 void* Get(int size)
75 void* p = Get();
76 if (p) Advance(size);
77 return p;
80 void *Get() const
82 if (m_pos >= 0 && m_pos < m_hb.GetSize()) return (char *)m_hb.Get()+m_pos;
83 return NULL;
86 void* Rewind()
88 m_pos = 0;
89 return m_hb.Get();
92 int GetSize() const
94 return m_hb.GetSize()-m_pos;
96 int Available() const { return GetSize(); }
98 void Clear()
100 m_pos=0;
101 m_hb.Resize(0,false);
104 void Advance(int bytecnt)
106 m_pos+=bytecnt;
107 if (m_pos<0)m_pos=0;
108 else if (m_pos > m_hb.GetSize()) m_pos=m_hb.GetSize();
111 void Compact(bool allocdown=false, bool force=false)
113 int olen=m_hb.GetSize();
114 if (m_pos > (force ? 0 : olen/2))
116 olen -= m_pos;
117 if (olen > 0)
119 char *a=(char*)m_hb.Get();
120 memmove(a,a+m_pos,olen);
122 else
124 olen = 0;
126 m_hb.Resize(olen,allocdown);
127 m_pos=0;
131 void SetGranul(int granul) { m_hb.SetGranul(granul); }
136 // endian-management stuff
138 static void WDL_Queue__bswap_buffer(void *buf, int len)
140 #ifdef __ppc__
141 char *p=(char *)buf;
142 char *ep=p+len;
143 while ((len-=2) >= 0)
145 char tmp=*p; *p++=*--ep; *ep=tmp;
147 #endif
150 // older API of static functions (that endedu p warning a bit anyway)
151 #define WDL_Queue__AddToLE(q, v) (q)->AddToLE(v)
152 #define WDL_Queue__AddDataToLE(q,d,ds,us) (q)->AddDataToLE(d,ds,us)
153 #define WDL_Queue__GetTFromLE(q,v) (q)->GetTFromLE(v)
154 #define WDL_Queue__GetDataFromLE(q,ds,us) (q)->GetDataFromLE(ds,us)
156 template<class T> void AddToLE(T *val)
158 WDL_Queue__bswap_buffer(AddT(val),sizeof(T));
160 void AddDataToLE(void *data, int datasize, int unitsize)
162 #ifdef __ppc__
163 char *dout = (char *)Add(data,datasize);
164 while (datasize >= unitsize)
166 WDL_Queue__bswap_buffer(dout,unitsize);
167 dout+=unitsize;
168 datasize-=unitsize;
170 #else
171 Add(data,datasize);
172 #endif
176 // NOTE: these thrash the contents of the queue if on LE systems. So for example if you are going to rewind it later or use it elsewhere,
177 // then get ready to get unhappy.
178 template<class T> T *GetTFromLE(T* val=0)
180 T *p = GetT(val);
181 if (p) {
182 WDL_Queue__bswap_buffer(p,sizeof(T));
183 if (val) *val = *p;
185 return p;
188 void *GetDataFromLE(int datasize, int unitsize)
190 void *data=Get(datasize);
191 #ifdef __ppc__
192 char *dout=(char *)data;
193 if (dout) while (datasize >= unitsize)
195 WDL_Queue__bswap_buffer(dout,unitsize);
196 dout+=unitsize;
197 datasize-=unitsize;
199 #endif
200 return data;
204 private:
205 WDL_HeapBuf m_hb;
206 int m_pos;
207 public:
208 int __pad; // keep 8 byte aligned
211 template <class T> class WDL_TypedQueue
213 public:
214 WDL_TypedQueue() : m_hb(4096 WDL_HEAPBUF_TRACEPARM("WDL_TypedQueue")), m_pos(0) { }
215 ~WDL_TypedQueue() { }
217 T *Add(const T *buf, int len)
219 int olen=m_hb.GetSize();
220 if (m_pos >= olen) olen=m_pos=0;
221 len *= (int)sizeof(T);
223 char *newbuf=(char*)m_hb.ResizeOK(olen+len,false);
224 if (newbuf)
226 newbuf += olen;
227 if (buf) memcpy(newbuf,buf,len);
229 return (T*) newbuf;
232 T *Get() const
234 if (m_pos >= 0 && m_pos < m_hb.GetSize()) return (T*)((char *)m_hb.Get()+m_pos);
235 return NULL;
238 int GetSize() const
240 return m_pos < m_hb.GetSize() ? (m_hb.GetSize()-m_pos)/sizeof(T) : 0;
242 int Available() const { return GetSize(); }
244 void Clear()
246 m_pos=0;
247 m_hb.Resize(0,false);
250 void Advance(int cnt)
252 m_pos+=cnt*(int)sizeof(T);
253 if (m_pos<0)m_pos=0;
254 else if (m_pos > m_hb.GetSize()) m_pos=m_hb.GetSize();
257 void Compact(bool allocdown=false, bool force=false)
259 int olen=m_hb.GetSize();
260 if (m_pos > (force ? 0 : olen/2))
262 olen -= m_pos;
263 if (olen > 0)
265 char *a=(char*)m_hb.Get();
266 memmove(a,a+m_pos,olen);
268 else
270 olen = 0;
272 m_hb.Resize(olen,allocdown);
273 m_pos=0;
277 void SetGranul(int granul) { m_hb.SetGranul(granul); }
279 private:
280 WDL_HeapBuf m_hb;
281 int m_pos;
282 public:
283 int __pad; // keep 8 byte aligned
286 #endif