LMMS
Loading...
Searching...
No Matches
heapbuf.h
Go to the documentation of this file.
1/*
2 WDL - heapbuf.h
3 Copyright (C) 2005 and later Cockos Incorporated
4
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.
8
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:
12
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.
20
21*/
22
23/*
24
25 This file provides the interface and implementation for WDL_HeapBuf, a simple
26 malloc() wrapper for resizeable blocks.
27
28 Also in this file is WDL_TypedBuf which is a templated version WDL_HeapBuf
29 that manages type and type-size.
30
31*/
32
33#ifndef _WDL_HEAPBUF_H_
34#define _WDL_HEAPBUF_H_
35
36#ifndef WDL_HEAPBUF_IMPL_ONLY
37
38#ifdef WDL_HEAPBUF_TRACE
39#include <windows.h>
40#define WDL_HEAPBUF_TRACEPARM(x) ,(x)
41#else
42#define WDL_HEAPBUF_TRACEPARM(x)
43#endif
44
45#include "wdltypes.h"
46
48{
49 public:
50 // interface
51#ifdef WDL_HEAPBUF_INTF_ONLY
52 void *Resize(int newsize, bool resizedown=true);
53 void CopyFrom(const WDL_HeapBuf *hb, bool exactCopyOfConfig=false);
54#endif
55 void *Get() const { return m_size?m_buf:NULL; } // returns NULL if size is 0
56 void *GetFast() const { return m_buf; } // returns last buffer if size is 0
57 int GetSize() const { return m_size; }
58 void *GetAligned(int align) const { return (void *)(((UINT_PTR)Get() + (align-1)) & ~(UINT_PTR)(align-1)); }
59
60 void SetGranul(int granul) { m_granul = granul; }
61 int GetGranul() const { return m_granul; }
62
63 void *ResizeOK(int newsize, bool resizedown = true) { void *p=Resize(newsize, resizedown); return GetSize() == newsize ? p : NULL; }
64
66 {
67 m_buf=0;
68 CopyFrom(&cp,true);
69 }
71 {
72 CopyFrom(&cp,false);
73 return *this;
74 }
75
76
77
78 #ifndef WDL_HEAPBUF_TRACE
79 explicit WDL_HeapBuf(int granul=4096) : m_buf(NULL), m_alloc(0), m_size(0), m_granul(granul)
80 {
81 }
83 {
84 free(m_buf);
85 }
86 #else
87 explicit WDL_HeapBuf(int granul=4096, const char *tracetype="WDL_HeapBuf"
88 ) : m_buf(NULL), m_alloc(0), m_size(0), m_granul(granul)
89 {
90 m_tracetype = tracetype;
91 char tmp[512];
92 wsprintf(tmp,"WDL_HeapBuf: created type: %s granul=%d\n",tracetype,granul);
93 OutputDebugString(tmp);
94 }
96 {
97 char tmp[512];
98 wsprintf(tmp,"WDL_HeapBuf: destroying type: %s (alloc=%d, size=%d)\n",m_tracetype,m_alloc,m_size);
99 OutputDebugString(tmp);
100 free(m_buf);
101 }
102 #endif
103
104#endif // !WDL_HEAPBUF_IMPL_ONLY
105
106 // implementation bits
107#ifndef WDL_HEAPBUF_INTF_ONLY
108 #ifdef WDL_HEAPBUF_IMPL_ONLY
109 void *WDL_HeapBuf::Resize(int newsize, bool resizedown)
110 #else
111 void *Resize(int newsize, bool resizedown=true)
112 #endif
113 {
114 if (newsize<0) newsize=0;
115 #ifdef DEBUG_TIGHT_ALLOC // horribly slow, do not use for release builds
116 if (newsize == m_size) return m_buf;
117
118 int a = newsize;
119 if (a > m_size) a=m_size;
120 void *newbuf = newsize ? malloc(newsize) : 0;
121 if (!newbuf && newsize)
122 {
123 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
124 WDL_HEAPBUF_ONMALLOCFAIL(newsize)
125 #endif
126 return m_buf;
127 }
128 if (newbuf&&m_buf) memcpy(newbuf,m_buf,a);
129 m_size=m_alloc=newsize;
130 free(m_buf);
131 return m_buf=newbuf;
132 #endif
133
134 if (newsize!=m_size || (resizedown && newsize < m_alloc/2))
135 {
136 int resizedown_under = 0;
137 if (resizedown && newsize < m_size)
138 {
139 // shrinking buffer: only shrink if allocation decreases to min(alloc/2, alloc-granul*4) or 0
140 resizedown_under = m_alloc - (m_granul<<2);
141 if (resizedown_under > m_alloc/2) resizedown_under = m_alloc/2;
142 if (resizedown_under < 1) resizedown_under=1;
143 }
144
145 if (newsize > m_alloc || newsize < resizedown_under)
146 {
147 int granul=newsize/2;
148 int newalloc;
149 if (granul < m_granul) granul=m_granul;
150
151 if (newsize<1) newalloc=0;
152 else if (m_granul<4096) newalloc=newsize+granul;
153 else
154 {
155 granul &= ~4095;
156 if (granul< 4096) granul=4096;
157 else if (granul>4*1024*1024) granul=4*1024*1024;
158 newalloc = ((newsize + granul + 96)&~4095)-96;
159 }
160
161 if (newalloc != m_alloc)
162 {
163
164 #ifdef WDL_HEAPBUF_TRACE
165 char tmp[512];
166 wsprintf(tmp,"WDL_HeapBuf: type %s realloc(%d) from %d\n",m_tracetype,newalloc,m_alloc);
167 OutputDebugString(tmp);
168 #endif
169 if (newalloc <= 0)
170 {
171 free(m_buf);
172 m_buf=0;
173 m_alloc=0;
174 m_size=0;
175 return 0;
176 }
177 void *nbuf=realloc(m_buf,newalloc);
178 if (!nbuf)
179 {
180 if (!(nbuf=malloc(newalloc)))
181 {
182 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
183 WDL_HEAPBUF_ONMALLOCFAIL(newalloc);
184 #endif
185 return m_size?m_buf:0; // failed, do not resize
186 }
187
188 if (m_buf)
189 {
190 int sz=newsize<m_size?newsize:m_size;
191 if (sz>0) memcpy(nbuf,m_buf,sz);
192 free(m_buf);
193 }
194 }
195
196 m_buf=nbuf;
197 m_alloc=newalloc;
198 } // alloc size change
199 } // need size up or down
200 m_size=newsize;
201 } // size change
202 return m_size?m_buf:0;
203 }
204
205 #ifdef WDL_HEAPBUF_IMPL_ONLY
206 void WDL_HeapBuf::CopyFrom(const WDL_HeapBuf *hb, bool exactCopyOfConfig)
207 #else
208 void CopyFrom(const WDL_HeapBuf *hb, bool exactCopyOfConfig=false)
209 #endif
210 {
211 if (exactCopyOfConfig) // copy all settings
212 {
213 free(m_buf);
214
215 #ifdef WDL_HEAPBUF_TRACE
216 m_tracetype = hb->m_tracetype;
217 #endif
218 m_granul = hb->m_granul;
219
220 m_size=m_alloc=0;
221 m_buf=hb->m_buf && hb->m_alloc>0 ? malloc(m_alloc = hb->m_alloc) : NULL;
222 #ifdef WDL_HEAPBUF_ONMALLOCFAIL
223 if (!m_buf && m_alloc) { WDL_HEAPBUF_ONMALLOCFAIL(m_alloc) } ;
224 #endif
225 if (m_buf) memcpy(m_buf,hb->m_buf,m_size = hb->m_size);
226 else m_alloc=0;
227 }
228 else // copy just the data + size
229 {
230 const int newsz=hb->GetSize();
231 Resize(newsz,true);
232 if (GetSize()!=newsz) Resize(0);
233 else memcpy(Get(),hb->Get(),newsz);
234 }
235 }
236
237#endif // ! WDL_HEAPBUF_INTF_ONLY
238
239#ifndef WDL_HEAPBUF_IMPL_ONLY
240
241 private:
242 void *m_buf;
246
247 #if defined(_WIN64) || defined(__LP64__)
248 public:
249 int ___pad; // keep size 8 byte aligned
250 #endif
251
252 #ifdef WDL_HEAPBUF_TRACE
253 const char *m_tracetype;
254 #endif
255
256};
257
258template<class PTRTYPE> class WDL_TypedBuf
259{
260 public:
261 PTRTYPE *Get() const { return (PTRTYPE *) m_hb.Get(); }
262 PTRTYPE *GetFast() const { return (PTRTYPE *) m_hb.GetFast(); }
263 int GetSize() const { return m_hb.GetSize()/(unsigned int)sizeof(PTRTYPE); }
264
265 PTRTYPE *Resize(int newsize, bool resizedown = true) { return (PTRTYPE *)m_hb.Resize(newsize*sizeof(PTRTYPE),resizedown); }
266 PTRTYPE *ResizeOK(int newsize, bool resizedown = true) { return (PTRTYPE *)m_hb.ResizeOK(newsize*sizeof(PTRTYPE), resizedown); }
267
268 PTRTYPE *GetAligned(int align) const { return (PTRTYPE *) m_hb.GetAligned(align); }
269
270 PTRTYPE *Add(PTRTYPE val)
271 {
272 const int sz=GetSize();
273 PTRTYPE* p=ResizeOK(sz+1,false);
274 if (p)
275 {
276 p[sz]=val;
277 return p+sz;
278 }
279 return NULL;
280 }
281 PTRTYPE *Add(const PTRTYPE *buf, int bufsz)
282 {
283 if (bufsz>0)
284 {
285 const int sz=GetSize();
286 PTRTYPE* p=ResizeOK(sz+bufsz,false);
287 if (p)
288 {
289 p+=sz;
290 if (buf) memcpy(p,buf,bufsz*sizeof(PTRTYPE));
291 else memset((char*)p,0,bufsz*sizeof(PTRTYPE));
292 return p;
293 }
294 }
295 return NULL;
296 }
297 PTRTYPE *Set(const PTRTYPE *buf, int bufsz)
298 {
299 if (bufsz>=0)
300 {
301 PTRTYPE* p=ResizeOK(bufsz,false);
302 if (p)
303 {
304 if (buf) memcpy(p,buf,bufsz*sizeof(PTRTYPE));
305 else memset((char*)p,0,bufsz*sizeof(PTRTYPE));
306 return p;
307 }
308 }
309 return NULL;
310 }
311 PTRTYPE* Insert(PTRTYPE val, int idx)
312 {
313 const int sz=GetSize();
314 if (idx >= 0 && idx <= sz)
315 {
316 PTRTYPE* p=ResizeOK(sz+1,false);
317 if (p)
318 {
319 memmove(p+idx+1, p+idx, (sz-idx)*sizeof(PTRTYPE));
320 p[idx]=val;
321 return p+idx;
322 }
323 }
324 return NULL;
325 }
326
327 void Delete(int idx)
328 {
329 PTRTYPE* p=Get();
330 const int sz=GetSize();
331 if (idx >= 0 && idx < sz)
332 {
333 memmove(p+idx, p+idx+1, (sz-idx-1)*sizeof(PTRTYPE));
334 Resize(sz-1,false);
335 }
336 }
337
338 void SetGranul(int gran) { m_hb.SetGranul(gran); }
339
340 int Find(PTRTYPE val) const
341 {
342 const PTRTYPE* p=Get();
343 const int sz=GetSize();
344 int i;
345 for (i=0; i < sz; ++i) if (p[i] == val) return i;
346 return -1;
347 }
348
349#ifndef WDL_HEAPBUF_TRACE
350 explicit WDL_TypedBuf(int granul=4096) : m_hb(granul) { }
351#else
352 explicit WDL_TypedBuf(int granul=4096, const char *tracetype="WDL_TypedBuf") : m_hb(granul WDL_HEAPBUF_TRACEPARM(tracetype)) { }
353#endif
355 {
356 }
357
359 const WDL_HeapBuf *GetHeapBuf() const { return &m_hb; }
360
361 int DeleteBatch(bool (*proc)(PTRTYPE *p, void *ctx), void *ctx=NULL) // proc returns true to delete item. returns number deleted
362 {
363 const int sz = GetSize();
364 int cnt=0;
365 PTRTYPE *rd = Get(), *wr = rd;
366 for (int x = 0; x < sz; x ++)
367 {
368 if (!proc(rd,ctx))
369 {
370 if (rd != wr) *wr=*rd;
371 wr++;
372 cnt++;
373 }
374 rd++;
375 }
376 if (cnt < sz) Resize(cnt,false);
377 return sz - cnt;
378 }
379
380 private:
382};
383
384#endif // ! WDL_HEAPBUF_IMPL_ONLY
385
386#endif // _WDL_HEAPBUF_H_
#define NULL
Definition CarlaBridgeFormat.cpp:30
uint8_t a
Definition Spc_Cpu.h:141
Definition heapbuf.h:48
void * Resize(int newsize, bool resizedown=true)
Definition heapbuf.h:111
~WDL_HeapBuf()
Definition heapbuf.h:82
void * m_buf
Definition heapbuf.h:242
void * GetFast() const
Definition heapbuf.h:56
int m_size
Definition heapbuf.h:244
int GetGranul() const
Definition heapbuf.h:61
void * ResizeOK(int newsize, bool resizedown=true)
Definition heapbuf.h:63
void * Get() const
Definition heapbuf.h:55
int GetSize() const
Definition heapbuf.h:57
WDL_HeapBuf & operator=(const WDL_HeapBuf &cp)
Definition heapbuf.h:70
void * GetAligned(int align) const
Definition heapbuf.h:58
void SetGranul(int granul)
Definition heapbuf.h:60
void CopyFrom(const WDL_HeapBuf *hb, bool exactCopyOfConfig=false)
Definition heapbuf.h:208
WDL_HeapBuf(int granul=4096)
Definition heapbuf.h:79
int m_alloc
Definition heapbuf.h:243
int m_granul
Definition heapbuf.h:245
WDL_HeapBuf(const WDL_HeapBuf &cp)
Definition heapbuf.h:65
PTRTYPE * Resize(int newsize, bool resizedown=true)
Definition heapbuf.h:265
~WDL_TypedBuf()
Definition heapbuf.h:354
WDL_TypedBuf(int granul=4096)
Definition heapbuf.h:350
int Find(PTRTYPE val) const
Definition heapbuf.h:340
PTRTYPE * GetFast() const
Definition heapbuf.h:262
WDL_HeapBuf m_hb
Definition heapbuf.h:381
PTRTYPE * Insert(PTRTYPE val, int idx)
Definition heapbuf.h:311
WDL_HeapBuf * GetHeapBuf()
Definition heapbuf.h:358
PTRTYPE * ResizeOK(int newsize, bool resizedown=true)
Definition heapbuf.h:266
PTRTYPE * GetAligned(int align) const
Definition heapbuf.h:268
PTRTYPE * Add(const PTRTYPE *buf, int bufsz)
Definition heapbuf.h:281
void Delete(int idx)
Definition heapbuf.h:327
const WDL_HeapBuf * GetHeapBuf() const
Definition heapbuf.h:359
void SetGranul(int gran)
Definition heapbuf.h:338
PTRTYPE * Set(const PTRTYPE *buf, int bufsz)
Definition heapbuf.h:297
int GetSize() const
Definition heapbuf.h:263
PTRTYPE * Add(PTRTYPE val)
Definition heapbuf.h:270
PTRTYPE * Get() const
Definition heapbuf.h:261
int DeleteBatch(bool(*proc)(PTRTYPE *p, void *ctx), void *ctx=NULL)
Definition heapbuf.h:361
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
#define WDL_HEAPBUF_TRACEPARM(x)
Definition heapbuf.h:42
int val
Definition jpeglib.h:956
uintptr_t UINT_PTR
Definition swell-types.h:43
#define wsprintf
Definition swell-types.h:81
uch * p
Definition crypt.c:594
memcpy(hh, h, RAND_HEAD_LEN)
char * cp
Definition unix.c:513
typedef int(UZ_EXP MsgFn)()
char * malloc()