1/*
2 * << Haru Free PDF Library >> -- hpdf_array.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_utils.h"
20#include "hpdf_objects.h"
21
22HPDF_Array
23HPDF_Array_New (HPDF_MMgr mmgr)
24{
25 HPDF_Array obj;
26
27 HPDF_PTRACE((" HPDF_Array_New\n"));
28
29 obj = HPDF_GetMem (mmgr, sizeof(HPDF_Array_Rec));
30 if (obj) {
31 HPDF_MemSet (obj, 0, sizeof(HPDF_Array_Rec));
32 obj->header.obj_class = HPDF_OCLASS_ARRAY;
33 obj->mmgr = mmgr;
34 obj->error = mmgr->error;
35 obj->list = HPDF_List_New (mmgr, HPDF_DEF_ITEMS_PER_BLOCK);
36 if (!obj->list) {
37 HPDF_FreeMem (mmgr, obj);
38 obj = NULL;
39 }
40 }
41
42 return obj;
43}
44
45
46HPDF_Array
47HPDF_Box_Array_New (HPDF_MMgr mmgr,
48 HPDF_Box box)
49{
50 HPDF_Array obj;
51 HPDF_STATUS ret = HPDF_OK;
52
53 HPDF_PTRACE((" HPDF_Box_Array_New\n"));
54
55 obj = HPDF_Array_New (mmgr);
56 if (!obj)
57 return NULL;
58
59 ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.left));
60 ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.bottom));
61 ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.right));
62 ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.top));
63
64 if (ret != HPDF_OK) {
65 HPDF_Array_Free (obj);
66 return NULL;
67 }
68
69 return obj;
70}
71
72
73void
74HPDF_Array_Free (HPDF_Array array)
75{
76 if (!array)
77 return;
78
79 HPDF_PTRACE((" HPDF_Array_Free\n"));
80
81 HPDF_Array_Clear (array);
82
83 HPDF_List_Free (array->list);
84
85 array->header.obj_class = 0;
86
87 HPDF_FreeMem (array->mmgr, array);
88}
89
90
91HPDF_STATUS
92HPDF_Array_Write (HPDF_Array array,
93 HPDF_Stream stream,
94 HPDF_Encrypt e)
95{
96 HPDF_UINT i;
97 HPDF_STATUS ret;
98
99 HPDF_PTRACE((" HPDF_Array_Write\n"));
100
101 ret = HPDF_Stream_WriteStr (stream, "[ ");
102 if (ret != HPDF_OK)
103 return ret;
104
105 for (i = 0; i < array->list->count; i++) {
106 void * element = HPDF_List_ItemAt (array->list, i);
107
108 ret = HPDF_Obj_Write (element, stream, e);
109 if (ret != HPDF_OK)
110 return ret;
111
112 ret = HPDF_Stream_WriteChar (stream, ' ');
113 if (ret != HPDF_OK)
114 return ret;
115 }
116
117 ret = HPDF_Stream_WriteChar (stream, ']');
118
119 return ret;
120}
121
122
123HPDF_STATUS
124HPDF_Array_AddNumber (HPDF_Array array,
125 HPDF_INT32 value)
126{
127 HPDF_Number n = HPDF_Number_New (array->mmgr, value);
128
129 HPDF_PTRACE((" HPDF_Array_AddNumber\n"));
130
131 if (!n)
132 return HPDF_Error_GetCode (array->error);
133 else
134 return HPDF_Array_Add (array, n);
135}
136
137
138HPDF_STATUS
139HPDF_Array_AddReal (HPDF_Array array,
140 HPDF_REAL value)
141{
142 HPDF_Real r = HPDF_Real_New (array->mmgr, value);
143
144 HPDF_PTRACE((" HPDF_Array_AddReal\n"));
145
146 if (!r)
147 return HPDF_Error_GetCode (array->error);
148 else
149 return HPDF_Array_Add (array, r);
150}
151
152
153HPDF_STATUS
154HPDF_Array_AddName (HPDF_Array array,
155 const char *value)
156{
157 HPDF_Name n = HPDF_Name_New (array->mmgr, value);
158
159 HPDF_PTRACE((" HPDF_Array_AddName\n"));
160
161 if (!n)
162 return HPDF_Error_GetCode (array->error);
163 else
164 return HPDF_Array_Add (array, n);
165}
166
167HPDF_STATUS
168HPDF_Array_Add (HPDF_Array array,
169 void *obj)
170{
171 HPDF_Obj_Header *header;
172 HPDF_STATUS ret;
173
174 HPDF_PTRACE((" HPDF_Array_Add\n"));
175
176 if (!obj) {
177 if (HPDF_Error_GetCode (array->error) == HPDF_OK)
178 return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
179 else
180 return HPDF_INVALID_OBJECT;
181 }
182
183 header = (HPDF_Obj_Header *)obj;
184
185 if (header->obj_id & HPDF_OTYPE_DIRECT)
186 return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
187
188 if (array->list->count >= HPDF_LIMIT_MAX_ARRAY) {
189 HPDF_PTRACE((" HPDF_Array_Add exceed limitatin of array count(%d)\n",
190 HPDF_LIMIT_MAX_ARRAY));
191
192 HPDF_Obj_Free (array->mmgr, obj);
193 return HPDF_SetError (array->error, HPDF_ARRAY_COUNT_ERR, 0);
194 }
195
196 if (header->obj_id & HPDF_OTYPE_INDIRECT) {
197 HPDF_Proxy proxy = HPDF_Proxy_New (array->mmgr, obj);
198
199 if (!proxy) {
200 HPDF_Obj_Free (array->mmgr, obj);
201 return HPDF_Error_GetCode (array->error);
202 }
203
204 proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
205 obj = proxy;
206 } else
207 header->obj_id |= HPDF_OTYPE_DIRECT;
208
209 ret = HPDF_List_Add (array->list, obj);
210 if (ret != HPDF_OK)
211 HPDF_Obj_Free (array->mmgr, obj);
212
213 return ret;
214}
215
216
217HPDF_UINT
218HPDF_Array_Items (HPDF_Array array)
219{
220 return array->list->count;
221}
222
223
224HPDF_STATUS
225HPDF_Array_Insert (HPDF_Array array,
226 void *target,
227 void *obj)
228{
229 HPDF_Obj_Header *header;
230 HPDF_STATUS ret;
231 HPDF_UINT i;
232
233 HPDF_PTRACE((" HPDF_Array_Insert\n"));
234
235 if (!obj) {
236 if (HPDF_Error_GetCode (array->error) == HPDF_OK)
237 return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
238 else
239 return HPDF_INVALID_OBJECT;
240 }
241
242 header = (HPDF_Obj_Header *)obj;
243
244 if (header->obj_id & HPDF_OTYPE_DIRECT) {
245 HPDF_PTRACE((" HPDF_Array_Add this object cannot owned by array "
246 "obj=0x%08X\n", (HPDF_UINT)array));
247
248 return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
249 }
250
251 if (array->list->count >= HPDF_LIMIT_MAX_ARRAY) {
252 HPDF_PTRACE((" HPDF_Array_Add exceed limitatin of array count(%d)\n",
253 HPDF_LIMIT_MAX_ARRAY));
254
255 HPDF_Obj_Free (array->mmgr, obj);
256
257 return HPDF_SetError (array->error, HPDF_ARRAY_COUNT_ERR, 0);
258 }
259
260 if (header->obj_id & HPDF_OTYPE_INDIRECT) {
261 HPDF_Proxy proxy = HPDF_Proxy_New (array->mmgr, obj);
262
263 if (!proxy) {
264 HPDF_Obj_Free (array->mmgr, obj);
265 return HPDF_Error_GetCode (array->error);
266 }
267
268 proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
269 obj = proxy;
270 } else
271 header->obj_id |= HPDF_OTYPE_DIRECT;
272
273 /* get the target-object from object-list
274 * consider that the pointer contained in list may be proxy-object.
275 */
276 for (i = 0; i < array->list->count; i++) {
277 void *ptr = HPDF_List_ItemAt (array->list, i);
278 void *obj_ptr;
279
280 header = (HPDF_Obj_Header *)obj;
281 if (header->obj_class == HPDF_OCLASS_PROXY)
282 obj_ptr = ((HPDF_Proxy)ptr)->obj;
283 else
284 obj_ptr = ptr;
285
286 if (obj_ptr == target) {
287 ret = HPDF_List_Insert (array->list, ptr, obj);
288 if (ret != HPDF_OK)
289 HPDF_Obj_Free (array->mmgr, obj);
290
291 return ret;
292 }
293 }
294
295 HPDF_Obj_Free (array->mmgr, obj);
296
297 return HPDF_ITEM_NOT_FOUND;
298}
299
300
301void*
302HPDF_Array_GetItem (HPDF_Array array,
303 HPDF_UINT index,
304 HPDF_UINT16 obj_class)
305{
306 void *obj;
307 HPDF_Obj_Header *header;
308
309 HPDF_PTRACE((" HPDF_Array_GetItem\n"));
310
311 obj = HPDF_List_ItemAt (array->list, index);
312
313 if (!obj) {
314 HPDF_SetError (array->error, HPDF_ARRAY_ITEM_NOT_FOUND, 0);
315 return NULL;
316 }
317
318 header = (HPDF_Obj_Header *)obj;
319
320 if (header->obj_class == HPDF_OCLASS_PROXY) {
321 obj = ((HPDF_Proxy)obj)->obj;
322 header = (HPDF_Obj_Header *)obj;
323 }
324
325 if ((header->obj_class & HPDF_OCLASS_ANY) != obj_class) {
326 HPDF_SetError (array->error, HPDF_ARRAY_ITEM_UNEXPECTED_TYPE, 0);
327
328 return NULL;
329 }
330
331 return obj;
332}
333
334void
335HPDF_Array_Clear (HPDF_Array array)
336{
337 HPDF_UINT i;
338
339 HPDF_PTRACE((" HPDF_Array_Clear\n"));
340
341 if (!array)
342 return;
343
344 for (i = 0; i < array->list->count; i++) {
345 void * obj = HPDF_List_ItemAt (array->list, i);
346
347 if (obj) {
348 HPDF_Obj_Free (array->mmgr, obj);
349 }
350 }
351
352 HPDF_List_Clear (array->list);
353}
354
355