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 | |
22 | HPDF_Array |
23 | HPDF_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 | |
46 | HPDF_Array |
47 | HPDF_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 | |
73 | void |
74 | HPDF_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 | |
91 | HPDF_STATUS |
92 | HPDF_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 | |
123 | HPDF_STATUS |
124 | HPDF_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 | |
138 | HPDF_STATUS |
139 | HPDF_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 | |
153 | HPDF_STATUS |
154 | HPDF_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 | |
167 | HPDF_STATUS |
168 | HPDF_Array_Add (HPDF_Array array, |
169 | void *obj) |
170 | { |
171 | HPDF_Obj_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 | |
217 | HPDF_UINT |
218 | HPDF_Array_Items (HPDF_Array array) |
219 | { |
220 | return array->list->count; |
221 | } |
222 | |
223 | |
224 | HPDF_STATUS |
225 | HPDF_Array_Insert (HPDF_Array array, |
226 | void *target, |
227 | void *obj) |
228 | { |
229 | HPDF_Obj_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 | |
301 | void* |
302 | HPDF_Array_GetItem (HPDF_Array array, |
303 | HPDF_UINT index, |
304 | HPDF_UINT16 obj_class) |
305 | { |
306 | void *obj; |
307 | HPDF_Obj_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 | |
334 | void |
335 | HPDF_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 | |