1/*
2 * << Haru Free PDF Library >> -- hpdf_mmgr.c
3 *
4 * URL: http://libharu.org
5 *
6 * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7 * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8 *
9 * Permission to use, copy, modify, distribute and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appear in all copies and
12 * that both that copyright notice and this permission notice appear
13 * in supporting documentation.
14 * It is provided "as is" without express or implied warranty.
15 *
16 */
17
18#include "hpdf_conf.h"
19#include "hpdf_consts.h"
20#include "hpdf_mmgr.h"
21#include "hpdf_utils.h"
22
23#ifndef HPDF_STDCALL
24#ifdef HPDF_DLL_MAKE
25#define HPDF_STDCALL __stdcall
26#else
27#ifdef HPDF_DLL
28#define HPDF_STDCALL __stdcall
29#else
30#define HPDF_STDCALL
31#endif
32#endif
33#endif
34
35static void * HPDF_STDCALL
36InternalGetMem (HPDF_UINT size);
37
38static void HPDF_STDCALL
39InternalFreeMem (void* aptr);
40
41
42HPDF_MMgr
43HPDF_MMgr_New (HPDF_Error error,
44 HPDF_UINT buf_size,
45 HPDF_Alloc_Func alloc_fn,
46 HPDF_Free_Func free_fn)
47{
48 HPDF_MMgr mmgr;
49
50 HPDF_PTRACE((" HPDF_MMgr_New\n"));
51
52 if (alloc_fn)
53 mmgr = (HPDF_MMgr)alloc_fn (sizeof(HPDF_MMgr_Rec));
54 else
55 mmgr = (HPDF_MMgr)InternalGetMem (sizeof(HPDF_MMgr_Rec));
56
57 HPDF_PTRACE(("+%p mmgr-new\n", mmgr));
58
59 if (mmgr != NULL) {
60 /* initialize mmgr object */
61 mmgr->error = error;
62
63
64#ifdef HPDF_MEM_DEBUG
65 mmgr->alloc_cnt = 0;
66 mmgr->free_cnt = 0;
67#endif
68 /*
69 * if alloc_fn and free_fn are specified, these function is
70 * used. if not, default function (maybe these will be "malloc" and
71 * "free") is used.
72 */
73 if (alloc_fn && free_fn) {
74 mmgr->alloc_fn = alloc_fn;
75 mmgr->free_fn = free_fn;
76 } else {
77 mmgr->alloc_fn = InternalGetMem;
78 mmgr->free_fn = InternalFreeMem;
79 }
80
81 /*
82 * if buf_size parameter is specified, this object is configured
83 * to be using memory-pool.
84 *
85 */
86 if (!buf_size)
87 mmgr->mpool = NULL;
88 else {
89 HPDF_MPool_Node node;
90
91 node = (HPDF_MPool_Node)mmgr->alloc_fn (sizeof(HPDF_MPool_Node_Rec) +
92 buf_size);
93
94 HPDF_PTRACE(("+%p mmgr-node-new\n", node));
95
96 if (node == NULL) {
97 HPDF_SetError (error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
98
99 mmgr->free_fn(mmgr);
100 mmgr = NULL;
101 } else {
102 mmgr->mpool = node;
103 node->buf = (HPDF_BYTE *)node + sizeof(HPDF_MPool_Node_Rec);
104 node->size = buf_size;
105 node->used_size = 0;
106 node->next_node = NULL;
107 }
108
109#ifdef HPDF_MEM_DEBUG
110 if (mmgr) {
111 mmgr->alloc_cnt += 1;
112 }
113#endif
114 }
115
116 if (mmgr) {
117 mmgr->buf_size = buf_size;
118 }
119 } else
120 HPDF_SetError(error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
121
122 return mmgr;
123}
124
125void
126HPDF_MMgr_Free (HPDF_MMgr mmgr)
127{
128 HPDF_MPool_Node node;
129
130 HPDF_PTRACE((" HPDF_MMgr_Free\n"));
131
132 if (mmgr == NULL)
133 return;
134
135 node = mmgr->mpool;
136
137 /* delete all nodes recursively */
138 while (node != NULL) {
139 HPDF_MPool_Node tmp = node;
140 node = tmp->next_node;
141
142 HPDF_PTRACE(("-%p mmgr-node-free\n", tmp));
143 mmgr->free_fn (tmp);
144
145#ifdef HPDF_MEM_DEBUG
146 mmgr->free_cnt++;
147#endif
148
149 }
150
151#ifdef HPDF_MEM_DEBUG
152 HPDF_PRINTF ("# HPDF_MMgr alloc-cnt=%u, free-cnt=%u\n",
153 mmgr->alloc_cnt, mmgr->free_cnt);
154
155 if (mmgr->alloc_cnt != mmgr->free_cnt)
156 HPDF_PRINTF ("# ERROR #\n");
157#endif
158
159 HPDF_PTRACE(("-%p mmgr-free\n", mmgr));
160 mmgr->free_fn (mmgr);
161}
162
163void*
164HPDF_GetMem (HPDF_MMgr mmgr,
165 HPDF_UINT size)
166{
167 void * ptr;
168
169 if (mmgr->mpool) {
170 HPDF_MPool_Node node = mmgr->mpool;
171
172#ifdef HPDF_ALINMENT_SIZ
173 size = (size + (HPDF_ALINMENT_SIZ - 1)) / HPDF_ALINMENT_SIZ;
174 size *= HPDF_ALINMENT_SIZ;
175#endif
176
177 if (node->size - node->used_size >= size) {
178 ptr = (HPDF_BYTE*)node->buf + node->used_size;
179 node->used_size += size;
180 return ptr;
181 } else {
182 HPDF_UINT tmp_buf_siz = (mmgr->buf_size < size) ? size :
183 mmgr->buf_size;
184
185 node = (HPDF_MPool_Node)mmgr->alloc_fn (sizeof(HPDF_MPool_Node_Rec)
186 + tmp_buf_siz);
187 HPDF_PTRACE(("+%p mmgr-new-node\n", node));
188
189 if (!node) {
190 HPDF_SetError (mmgr->error, HPDF_FAILD_TO_ALLOC_MEM,
191 HPDF_NOERROR);
192 return NULL;
193 }
194
195 node->size = tmp_buf_siz;
196 }
197
198 node->next_node = mmgr->mpool;
199 mmgr->mpool = node;
200 node->used_size = size;
201 node->buf = (HPDF_BYTE*)node + sizeof(HPDF_MPool_Node_Rec);
202 ptr = node->buf;
203 } else {
204 ptr = mmgr->alloc_fn (size);
205 HPDF_PTRACE(("+%p mmgr-alloc_fn size=%u\n", ptr, size));
206
207 if (ptr == NULL)
208 HPDF_SetError (mmgr->error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
209 }
210
211#ifdef HPDF_MEM_DEBUG
212 if (ptr)
213 mmgr->alloc_cnt++;
214#endif
215
216 return ptr;
217}
218
219void
220HPDF_FreeMem (HPDF_MMgr mmgr,
221 void *aptr)
222{
223 if (!aptr)
224 return;
225
226 if (!mmgr->mpool) {
227 HPDF_PTRACE(("-%p mmgr-free-mem\n", aptr));
228 mmgr->free_fn(aptr);
229
230#ifdef HPDF_MEM_DEBUG
231 mmgr->free_cnt++;
232#endif
233 }
234
235 return;
236}
237
238static void * HPDF_STDCALL
239InternalGetMem (HPDF_UINT size)
240{
241 return HPDF_MALLOC (size);
242}
243
244static void HPDF_STDCALL
245InternalFreeMem (void* aptr)
246{
247 HPDF_FREE (aptr);
248}
249
250
251