[IPLUG/EXAMPLES] IPlugResampler: qualification of min no longer needed
[wdl/wdl-ol.git] / WDL / heapbuf.h
blob1c3e4d0bee5aee47a61ede7d648fa606ff314fcc
1 /*
2 WDL - heapbuf.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 the interface and implementation for WDL_HeapBuf, a simple
26 malloc() wrapper for resizeable blocks.
28 Also in this file is WDL_TypedBuf which is a templated version WDL_HeapBuf
29 that manages type and type-size.
33 #ifndef _WDL_HEAPBUF_H_
34 #define _WDL_HEAPBUF_H_
36 #ifndef WDL_HEAPBUF_IMPL_ONLY
39 //#define WDL_HEAPBUF_TRACE
41 #ifdef WDL_HEAPBUF_TRACE
42 #include <windows.h>
43 #define WDL_HEAPBUF_TRACEPARM(x) ,(x)
44 #else
45 #define WDL_HEAPBUF_TRACEPARM(x)
46 #endif
48 #include "wdltypes.h"
50 class WDL_HeapBuf
52 public:
53 explicit WDL_HeapBuf(int granul=4096
54 #ifdef WDL_HEAPBUF_TRACE
55 , const char *tracetype="WDL_HeapBuf"
56 #endif
57 ) : m_alloc(0), m_size(0), m_mas(0)
59 SetGranul(granul);
60 m_buf=0;
62 #ifdef WDL_HEAPBUF_TRACE
63 m_tracetype = tracetype;
64 char tmp[512];
65 wsprintf(tmp,"WDL_HeapBuf: created type: %s granul=%d\n",tracetype,granul);
66 OutputDebugString(tmp);
67 #endif
69 ~WDL_HeapBuf()
71 #ifdef WDL_HEAPBUF_TRACE
72 char tmp[512];
73 wsprintf(tmp,"WDL_HeapBuf: destroying type: %s (alloc=%d, size=%d)\n",m_tracetype,m_alloc,m_size);
74 OutputDebugString(tmp);
75 #endif
76 free(m_buf);
80 WDL_HeapBuf(const WDL_HeapBuf &cp)
82 m_buf=0;
83 CopyFrom(&cp,true);
85 WDL_HeapBuf &operator=(const WDL_HeapBuf &cp)
87 CopyFrom(&cp,true);
88 return *this;
91 void CopyFrom(const WDL_HeapBuf *hb, bool exactCopyOfConfig=false)
93 if (exactCopyOfConfig) // copy all settings
95 free(m_buf);
97 #ifdef WDL_HEAPBUF_TRACE
98 m_tracetype = hb->m_tracetype;
99 #endif
100 m_granul = hb->m_granul;
101 m_mas = hb->m_mas;
103 m_size=m_alloc=0;
104 m_buf=hb->m_buf && hb->m_alloc>0 ? malloc(m_alloc = hb->m_alloc) : NULL;
105 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
106 if (!m_buf && m_alloc) { WDL_HEAPBUF_ONMALLOCFAIL(m_alloc) } ;
107 #endif
108 if (m_buf) memcpy(m_buf,hb->m_buf,m_size = hb->m_size);
109 else m_alloc=0;
111 else // copy just the data + size
113 int newsz=hb->GetSize();
114 Resize(newsz);
115 if (GetSize()!=newsz) Resize(0);
116 else memcpy(Get(),hb->Get(),newsz);
121 void *Get() const { return m_size?m_buf:NULL; }
122 int GetSize() const { return m_size; }
124 void SetGranul(int granul)
126 m_granul = granul;
129 void SetMinAllocSize(int mas)
131 m_mas=mas;
133 #define WDL_HEAPBUF_PREFIX
134 #else
135 #define WDL_HEAPBUF_PREFIX WDL_HeapBuf::
136 #endif
138 void * WDL_HEAPBUF_PREFIX Resize(int newsize, bool resizedown
139 #ifdef WDL_HEAPBUF_INTF_ONLY
140 =true);
141 #else
142 #ifdef WDL_HEAPBUF_IMPL_ONLY
144 #else
145 =true)
146 #endif
148 #ifdef DEBUG_TIGHT_ALLOC // horribly slow, do not use for release builds
149 if (newsize == m_size) return m_buf;
151 int a = newsize;
152 if (a > m_size) a=m_size;
153 void *newbuf = newsize ? malloc(newsize) : 0;
154 if (!newbuf && newsize)
156 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
157 WDL_HEAPBUF_ONMALLOCFAIL(newsize)
158 #endif
159 return m_buf;
161 if (newbuf&&m_buf) memcpy(newbuf,m_buf,a);
162 m_size=m_alloc=newsize;
163 free(m_buf);
164 return m_buf=newbuf;
165 #endif
167 //#define WDL_HEAPBUF_DYNAMIC
168 #ifdef WDL_HEAPBUF_DYNAMIC
169 // ignoring m_granul and m_mas
171 if (newsize!=m_size)
173 if ((newsize > m_size && newsize <= m_alloc) || (newsize < m_size && !resizedown))
175 m_size = newsize;
176 return m_buf;
179 // next highest power of 2
180 int n = newsize;
181 if (n)
183 if (n < 64)
185 n = 64;
187 else
189 --n;
190 n = (n>>1)|n;
191 n = (n>>2)|n;
192 n = (n>>4)|n;
193 n = (n>>8)|n;
194 n = (n>>16)|n;
195 ++n;
199 if (n == m_alloc)
201 m_size = newsize;
202 return m_buf;
205 void* newbuf = realloc(m_buf, n); // realloc==free when size==0
206 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
207 if (!newbuf && n) { WDL_HEAPBUF_ONMALLOCFAIL(n) } ;
208 #endif
209 if (newbuf || !newsize)
211 m_alloc = n;
212 m_buf = newbuf;
213 m_size = newsize;
217 return (m_size ? m_buf : 0);
219 #else // WDL_HEAPBUF_DYNAMIC
220 if (newsize!=m_size)
222 // if we are not using m_smallbuf or we need to not use it
223 // and if if growing or resizing down
224 if (
225 (newsize > m_alloc ||
226 (resizedown && newsize < m_size &&
227 newsize < m_alloc/2 &&
228 newsize < m_alloc - (m_granul<<2))))
230 int granul=newsize/2;
231 int newalloc;
232 if (granul < m_granul) granul=m_granul;
234 if (m_granul<4096) newalloc=newsize+granul;
235 else
237 granul &= ~4095;
238 if (granul< 4096) granul=4096;
239 else if (granul>4*1024*1024) granul=4*1024*1024;
240 newalloc = ((newsize + granul + 96)&~4095)-96;
243 if (newalloc < m_mas) newalloc=m_mas;
245 if (newalloc != m_alloc)
247 #ifdef WDL_HEAPBUF_TRACE
248 char tmp[512];
249 wsprintf(tmp,"WDL_HeapBuf: type %s realloc(%d) from %d\n",m_tracetype,newalloc,m_alloc);
250 OutputDebugString(tmp);
251 #endif
252 void *nbuf= realloc(m_buf,newalloc);
253 if (!nbuf && newalloc)
255 if (!(nbuf=malloc(newalloc)))
257 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
258 WDL_HEAPBUF_ONMALLOCFAIL(newalloc);
259 #endif
260 return m_size?m_buf:0; // failed, do not resize
263 if (m_buf)
265 int sz=newsize<m_size?newsize:m_size;
266 if (sz>0) memcpy(nbuf,m_buf,sz);
267 free(m_buf);
271 m_buf=nbuf;
272 m_alloc=newalloc;
273 } // alloc size change
274 } // need size up or down
275 m_size=newsize;
276 } // size change
277 return m_size?m_buf:0;
279 #endif // WDL_HEAPBUF_DYNAMIC
281 #endif // !WDL_HEAPBUF_IMPL_ONLY, I think
283 #ifndef WDL_HEAPBUF_IMPL_ONLY
284 private:
285 void *m_buf;
286 #if !defined(_WIN64) && !defined(__LP64__)
287 int ___pad; // keep this 8 byte aligned on osx32
288 #endif
289 int m_granul;
290 int m_alloc;
291 int m_size;
292 int m_mas;
294 #ifdef WDL_HEAPBUF_TRACE
295 const char *m_tracetype;
296 #endif
299 template<class PTRTYPE> class WDL_TypedBuf
301 public:
302 explicit WDL_TypedBuf(int granul=4096
303 #ifdef WDL_HEAPBUF_TRACE
304 , const char *tracetype="WDL_TypedBuf"
305 #endif
306 ) : m_hb(granul WDL_HEAPBUF_TRACEPARM(tracetype))
309 ~WDL_TypedBuf()
312 PTRTYPE *Get() { return (PTRTYPE *) m_hb.Get(); }
313 int GetSize() { return m_hb.GetSize()/sizeof(PTRTYPE); }
315 PTRTYPE *Resize(int newsize, bool resizedown=true) { return (PTRTYPE *)m_hb.Resize(newsize*sizeof(PTRTYPE),resizedown); }
317 PTRTYPE *Add(PTRTYPE val)
319 int sz=GetSize();
320 PTRTYPE *p=Resize(sz+1);
321 if (p && GetSize() == sz+1)
323 p[sz]=val;
324 return p+sz;
326 return 0;
329 void SetGranul(int gran)
331 m_hb.SetGranul(gran);
334 int Find(PTRTYPE val)
336 PTRTYPE* p=Get();
337 int i;
338 for (i=0; i < GetSize(); ++i)
340 if (p[i] == val) return i;
342 return -1;
345 private:
346 WDL_HeapBuf m_hb;
349 #endif
350 #endif