|
1 /** |
|
2 * XML Security Library (http://www.aleksey.com/xmlsec). |
|
3 * |
|
4 * List of pointers. |
|
5 * |
|
6 * This is free software; see Copyright file in the source |
|
7 * distribution for preciese wording. |
|
8 * |
|
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
10 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
11 */ |
|
12 #include "xmlsec_globals.h" |
|
13 |
|
14 #include <stdlib.h> |
|
15 #include <string.h> |
|
16 |
|
17 #include <libxml2_tree.h> |
|
18 #include <libxml2_globals.h> |
|
19 |
|
20 #include "xmlsec_xmlsec.h" |
|
21 #include "xmlsec_list.h" |
|
22 #include "xmlsec_errors.h" |
|
23 |
|
24 |
|
25 static int xmlSecPtrListEnsureSize (xmlSecPtrListPtr list, |
|
26 xmlSecSize size); |
|
27 |
|
28 static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble; |
|
29 static xmlSecSize gInitialSize = 64; |
|
30 |
|
31 /** |
|
32 * xmlSecPtrListSetDefaultAllocMode: |
|
33 * @defAllocMode: the new default memory allocation mode. |
|
34 * @defInitialSize: the new default minimal initial size. |
|
35 * |
|
36 * Sets new default allocation mode and minimal initial list size. |
|
37 */ |
|
38 EXPORT_C |
|
39 void |
|
40 xmlSecPtrListSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) { |
|
41 xmlSecAssert(defInitialSize > 0); |
|
42 |
|
43 gAllocMode = defAllocMode; |
|
44 gInitialSize = defInitialSize; |
|
45 } |
|
46 |
|
47 /** |
|
48 * xmlSecPtrListCreate: |
|
49 * @id: the list klass. |
|
50 * |
|
51 * Creates new list object. Caller is responsible for freeing returned list |
|
52 * by calling #xmlSecPtrListDestroy function. |
|
53 * |
|
54 * Returns pointer to newly allocated list or NULL if an error occurs. |
|
55 */ |
|
56 EXPORT_C |
|
57 xmlSecPtrListPtr |
|
58 xmlSecPtrListCreate(xmlSecPtrListId id) { |
|
59 xmlSecPtrListPtr list; |
|
60 int ret; |
|
61 |
|
62 xmlSecAssert2(id != xmlSecPtrListIdUnknown, NULL); |
|
63 |
|
64 /* Allocate a new xmlSecPtrList and fill the fields. */ |
|
65 list = (xmlSecPtrListPtr)xmlMalloc(sizeof(xmlSecPtrList)); |
|
66 if(list == NULL) { |
|
67 xmlSecError(XMLSEC_ERRORS_HERE, |
|
68 xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)), |
|
69 NULL, |
|
70 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
71 "sizeof(xmlSecPtrList)=%d", |
|
72 sizeof(xmlSecPtrList)); |
|
73 return(NULL); |
|
74 } |
|
75 |
|
76 ret = xmlSecPtrListInitialize(list, id); |
|
77 if(ret < 0) { |
|
78 xmlSecError(XMLSEC_ERRORS_HERE, |
|
79 xmlSecErrorsSafeString(xmlSecPtrListKlassGetName(id)), |
|
80 "xmlSecPtrListInitialize", |
|
81 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
82 XMLSEC_ERRORS_NO_MESSAGE); |
|
83 xmlFree(list); |
|
84 return(NULL); |
|
85 } |
|
86 |
|
87 return(list); |
|
88 } |
|
89 |
|
90 /** |
|
91 * xmlSecPtrListDestroy: |
|
92 * @list: the pointer to list. |
|
93 * |
|
94 * Destroys @list created with #xmlSecPtrListCreate function. |
|
95 */ |
|
96 EXPORT_C |
|
97 void |
|
98 xmlSecPtrListDestroy(xmlSecPtrListPtr list) { |
|
99 xmlSecAssert(xmlSecPtrListIsValid(list)); |
|
100 xmlSecPtrListFinalize(list); |
|
101 xmlFree(list); |
|
102 } |
|
103 |
|
104 /** |
|
105 * xmlSecPtrListInitialize: |
|
106 * @list: the pointer to list. |
|
107 * @id: the list klass. |
|
108 * |
|
109 * Initializes the list of given klass. Caller is responsible |
|
110 * for cleaning up by calling #xmlSecPtrListFinalize function. |
|
111 * |
|
112 * Returns 0 on success or a negative value if an error occurs. |
|
113 */ |
|
114 EXPORT_C |
|
115 int |
|
116 xmlSecPtrListInitialize(xmlSecPtrListPtr list, xmlSecPtrListId id) { |
|
117 xmlSecAssert2(id != xmlSecPtrListIdUnknown, -1); |
|
118 xmlSecAssert2(list != NULL, -1); |
|
119 |
|
120 memset(list, 0, sizeof(xmlSecPtrList)); |
|
121 list->id = id; |
|
122 list->allocMode = gAllocMode; |
|
123 |
|
124 return(0); |
|
125 } |
|
126 |
|
127 /** |
|
128 * xmlSecPtrListFinalize: |
|
129 * @list: the pointer to list. |
|
130 * |
|
131 * Cleans up the list initialized with #xmlSecPtrListInitialize |
|
132 * function. |
|
133 */ |
|
134 EXPORT_C |
|
135 void |
|
136 xmlSecPtrListFinalize(xmlSecPtrListPtr list) { |
|
137 xmlSecAssert(xmlSecPtrListIsValid(list)); |
|
138 |
|
139 xmlSecPtrListEmpty(list); |
|
140 memset(list, 0, sizeof(xmlSecPtrList)); |
|
141 } |
|
142 |
|
143 /** |
|
144 * xmlSecPtrListEmpty: |
|
145 * @list: the pointer to list. |
|
146 * |
|
147 * Remove all items from @list (if any). |
|
148 */ |
|
149 EXPORT_C |
|
150 void |
|
151 xmlSecPtrListEmpty(xmlSecPtrListPtr list) { |
|
152 xmlSecAssert(xmlSecPtrListIsValid(list)); |
|
153 |
|
154 if(list->id->destroyItem != NULL) { |
|
155 xmlSecSize pos; |
|
156 |
|
157 for(pos = 0; pos < list->use; ++pos) { |
|
158 xmlSecAssert(list->data != NULL); |
|
159 if(list->data[pos] != NULL) { |
|
160 list->id->destroyItem(list->data[pos]); |
|
161 } |
|
162 } |
|
163 } |
|
164 if(list->max > 0) { |
|
165 xmlSecAssert(list->data != NULL); |
|
166 |
|
167 memset(list->data, 0, sizeof(xmlSecPtr) * list->use); |
|
168 xmlFree(list->data); |
|
169 } |
|
170 list->max = list->use = 0; |
|
171 list->data = NULL; |
|
172 } |
|
173 |
|
174 /** |
|
175 * xmlSecPtrListCopy: |
|
176 * @dst: the pointer to destination list. |
|
177 * @src: the pointer to source list. |
|
178 * |
|
179 * Copies @src list items to @dst list using #duplicateItem method |
|
180 * of the list klass. If #duplicateItem method is NULL then |
|
181 * we jsut copy pointers to items. |
|
182 * |
|
183 * Returns 0 on success or a negative value if an error occurs. |
|
184 */ |
|
185 EXPORT_C |
|
186 int |
|
187 xmlSecPtrListCopy(xmlSecPtrListPtr dst, xmlSecPtrListPtr src) { |
|
188 xmlSecSize i; |
|
189 int ret; |
|
190 |
|
191 xmlSecAssert2(xmlSecPtrListIsValid(dst), -1); |
|
192 xmlSecAssert2(xmlSecPtrListIsValid(src), -1); |
|
193 xmlSecAssert2(dst->id == src->id, -1); |
|
194 |
|
195 /* allocate memory */ |
|
196 ret = xmlSecPtrListEnsureSize(dst, dst->use + src->use); |
|
197 if(ret < 0) { |
|
198 xmlSecError(XMLSEC_ERRORS_HERE, |
|
199 xmlSecErrorsSafeString(xmlSecPtrListGetName(src)), |
|
200 "xmlSecPtrListEnsureSize", |
|
201 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
202 "size=%d", src->use); |
|
203 return(-1); |
|
204 } |
|
205 |
|
206 /* copy one item after another */ |
|
207 for(i = 0; i < src->use; ++i, ++dst->use) { |
|
208 xmlSecAssert2(src->data != NULL, -1); |
|
209 xmlSecAssert2(dst->data != NULL, -1); |
|
210 |
|
211 if((dst->id->duplicateItem != NULL) && (src->data[i] != NULL)) { |
|
212 dst->data[dst->use] = dst->id->duplicateItem(src->data[i]); |
|
213 if(dst->data[dst->use] == NULL) { |
|
214 xmlSecError(XMLSEC_ERRORS_HERE, |
|
215 xmlSecErrorsSafeString(xmlSecPtrListGetName(src)), |
|
216 "duplicateItem", |
|
217 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
218 XMLSEC_ERRORS_NO_MESSAGE); |
|
219 return(-1); |
|
220 } |
|
221 } else { |
|
222 dst->data[dst->use] = src->data[i]; |
|
223 } |
|
224 } |
|
225 |
|
226 return(0); |
|
227 } |
|
228 |
|
229 /** |
|
230 * xmlSecPtrListDuplicate: |
|
231 * @list: the pointer to list. |
|
232 * |
|
233 * Creates a new copy of @list and all its items. |
|
234 * |
|
235 * Returns pointer to newly allocated list or NULL if an error occurs. |
|
236 */ |
|
237 EXPORT_C |
|
238 xmlSecPtrListPtr |
|
239 xmlSecPtrListDuplicate(xmlSecPtrListPtr list) { |
|
240 xmlSecPtrListPtr newList; |
|
241 int ret; |
|
242 |
|
243 xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); |
|
244 |
|
245 newList = xmlSecPtrListCreate(list->id); |
|
246 if(newList == NULL) { |
|
247 xmlSecError(XMLSEC_ERRORS_HERE, |
|
248 xmlSecErrorsSafeString(xmlSecPtrListGetName(list)), |
|
249 "xmlSecPtrListCreate", |
|
250 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
251 XMLSEC_ERRORS_NO_MESSAGE); |
|
252 return(NULL); |
|
253 } |
|
254 |
|
255 ret = xmlSecPtrListCopy(newList, list); |
|
256 if(ret < 0) { |
|
257 xmlSecError(XMLSEC_ERRORS_HERE, |
|
258 xmlSecErrorsSafeString(xmlSecPtrListGetName(list)), |
|
259 "xmlSecPtrListCopy", |
|
260 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
261 XMLSEC_ERRORS_NO_MESSAGE); |
|
262 xmlSecPtrListDestroy(newList); |
|
263 return(NULL); |
|
264 } |
|
265 return(newList); |
|
266 } |
|
267 |
|
268 /** |
|
269 * xmlSecPtrListGetSize: |
|
270 * @list: the pointer to list. |
|
271 * |
|
272 * Gets list size. |
|
273 * |
|
274 * Returns the number of itmes in @list. |
|
275 */ |
|
276 EXPORT_C |
|
277 xmlSecSize |
|
278 xmlSecPtrListGetSize(xmlSecPtrListPtr list) { |
|
279 xmlSecAssert2(xmlSecPtrListIsValid(list), 0); |
|
280 |
|
281 return(list->use); |
|
282 } |
|
283 |
|
284 /** |
|
285 * xmlSecPtrListGetItem: |
|
286 * @list: the pointer to list. |
|
287 * @pos: the item position. |
|
288 * |
|
289 * Gets item from the list. |
|
290 * |
|
291 * Returns the list item at position @pos or NULL if @pos is greater |
|
292 * than the number of items in the list or an error occurs. |
|
293 */ |
|
294 EXPORT_C |
|
295 xmlSecPtr |
|
296 xmlSecPtrListGetItem(xmlSecPtrListPtr list, xmlSecSize pos) { |
|
297 xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); |
|
298 xmlSecAssert2(list->data != NULL, NULL); |
|
299 xmlSecAssert2(pos < list->use, NULL); |
|
300 |
|
301 return(list->data[pos]); |
|
302 } |
|
303 |
|
304 /** |
|
305 * xmlSecPtrListAdd: |
|
306 * @list: the pointer to list. |
|
307 * @item: the item. |
|
308 * |
|
309 * Adds @item to the end of the @list. |
|
310 * |
|
311 * Returns 0 on success or a negative value if an error occurs. |
|
312 */ |
|
313 EXPORT_C |
|
314 int |
|
315 xmlSecPtrListAdd(xmlSecPtrListPtr list, xmlSecPtr item) { |
|
316 int ret; |
|
317 |
|
318 xmlSecAssert2(xmlSecPtrListIsValid(list), -1); |
|
319 |
|
320 ret = xmlSecPtrListEnsureSize(list, list->use + 1); |
|
321 if(ret < 0) { |
|
322 xmlSecError(XMLSEC_ERRORS_HERE, |
|
323 xmlSecErrorsSafeString(xmlSecPtrListGetName(list)), |
|
324 "xmlSecPtrListAdd", |
|
325 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
326 "size=%d", list->use + 1); |
|
327 return(-1); |
|
328 } |
|
329 |
|
330 list->data[list->use++] = item; |
|
331 return(0); |
|
332 } |
|
333 |
|
334 /** |
|
335 * xmlSecPtrListSet: |
|
336 * @list: the pointer to list. |
|
337 * @item: the item. |
|
338 * @pos: the pos. |
|
339 * |
|
340 * Sets the value of list item at position @pos. The old value |
|
341 * is destroyed. |
|
342 * |
|
343 * Returns 0 on success or a negative value if an error occurs. |
|
344 */ |
|
345 EXPORT_C |
|
346 int |
|
347 xmlSecPtrListSet(xmlSecPtrListPtr list, xmlSecPtr item, xmlSecSize pos) { |
|
348 xmlSecAssert2(xmlSecPtrListIsValid(list), -1); |
|
349 xmlSecAssert2(list->data != NULL, -1); |
|
350 xmlSecAssert2(pos < list->use, -1); |
|
351 |
|
352 if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) { |
|
353 list->id->destroyItem(list->data[pos]); |
|
354 } |
|
355 list->data[pos] = item; |
|
356 return(0); |
|
357 } |
|
358 |
|
359 /** |
|
360 * xmlSecPtrListRemove: |
|
361 * @list: the pointer to list. |
|
362 * @pos: the position. |
|
363 * |
|
364 * Destroys list item at the position @pos and sets it value to NULL. |
|
365 * |
|
366 * Returns 0 on success or a negative value if an error occurs. |
|
367 */ |
|
368 EXPORT_C |
|
369 int |
|
370 xmlSecPtrListRemove(xmlSecPtrListPtr list, xmlSecSize pos) { |
|
371 xmlSecAssert2(xmlSecPtrListIsValid(list), -1); |
|
372 xmlSecAssert2(list->data != NULL, -1); |
|
373 xmlSecAssert2(pos < list->use, -1); |
|
374 |
|
375 if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) { |
|
376 list->id->destroyItem(list->data[pos]); |
|
377 } |
|
378 list->data[pos] = NULL; |
|
379 if(pos == list->use - 1) { |
|
380 --list->use; |
|
381 } |
|
382 return(0); |
|
383 } |
|
384 |
|
385 /** |
|
386 * xmlSecPtrListDebugDump: |
|
387 * @list: the pointer to list. |
|
388 * @output: the pointer to output FILE. |
|
389 * |
|
390 * Prints debug information about @list to the @output. |
|
391 */ |
|
392 EXPORT_C |
|
393 void |
|
394 xmlSecPtrListDebugDump(xmlSecPtrListPtr list, FILE* output) { |
|
395 xmlSecAssert(xmlSecPtrListIsValid(list)); |
|
396 xmlSecAssert(output != NULL); |
|
397 |
|
398 fprintf(output, "=== list size: %d\n", list->use); |
|
399 if(list->id->debugDumpItem != NULL) { |
|
400 xmlSecSize pos; |
|
401 |
|
402 for(pos = 0; pos < list->use; ++pos) { |
|
403 xmlSecAssert(list->data != NULL); |
|
404 if(list->data[pos] != NULL) { |
|
405 list->id->debugDumpItem(list->data[pos], output); |
|
406 } |
|
407 } |
|
408 } |
|
409 } |
|
410 |
|
411 /** |
|
412 * xmlSecPtrListDebugXmlDump: |
|
413 * @list: the pointer to list. |
|
414 * @output: the pointer to output FILE. |
|
415 * |
|
416 * Prints debug information about @list to the @output in XML format. |
|
417 */ |
|
418 EXPORT_C |
|
419 void |
|
420 xmlSecPtrListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) { |
|
421 xmlSecAssert(xmlSecPtrListIsValid(list)); |
|
422 xmlSecAssert(output != NULL); |
|
423 |
|
424 fprintf(output, "<List size=\"%d\">\n", list->use); |
|
425 if(list->id->debugXmlDumpItem != NULL) { |
|
426 xmlSecSize pos; |
|
427 |
|
428 for(pos = 0; pos < list->use; ++pos) { |
|
429 xmlSecAssert(list->data != NULL); |
|
430 if(list->data[pos] != NULL) { |
|
431 list->id->debugXmlDumpItem(list->data[pos], output); |
|
432 } |
|
433 } |
|
434 } |
|
435 fprintf(output, "</List>\n"); |
|
436 } |
|
437 |
|
438 static int |
|
439 xmlSecPtrListEnsureSize(xmlSecPtrListPtr list, xmlSecSize size) { |
|
440 xmlSecPtr* newData; |
|
441 xmlSecSize newSize = 0; |
|
442 |
|
443 xmlSecAssert2(xmlSecPtrListIsValid(list), -1); |
|
444 |
|
445 if(size < list->max) { |
|
446 return(0); |
|
447 } |
|
448 |
|
449 switch(list->allocMode) { |
|
450 case xmlSecAllocModeExact: |
|
451 newSize = size + 8; |
|
452 break; |
|
453 case xmlSecAllocModeDouble: |
|
454 newSize = 2 * size + 32; |
|
455 break; |
|
456 } |
|
457 |
|
458 if(newSize < gInitialSize) { |
|
459 newSize = gInitialSize; |
|
460 } |
|
461 |
|
462 if(list->data != NULL) { |
|
463 newData = (xmlSecPtr*)xmlRealloc(list->data, sizeof(xmlSecPtr) * newSize); |
|
464 } else { |
|
465 newData = (xmlSecPtr*)xmlMalloc(sizeof(xmlSecPtr) * newSize); |
|
466 } |
|
467 if(newData == NULL) { |
|
468 xmlSecError(XMLSEC_ERRORS_HERE, |
|
469 xmlSecErrorsSafeString(xmlSecPtrListGetName(list)), |
|
470 NULL, |
|
471 XMLSEC_ERRORS_R_MALLOC_FAILED, |
|
472 "sizeof(xmlSecPtr)*%d=%d", |
|
473 newSize, sizeof(xmlSecPtr) * newSize); |
|
474 return(-1); |
|
475 } |
|
476 |
|
477 list->data = newData; |
|
478 list->max = newSize; |
|
479 |
|
480 return(0); |
|
481 } |
|
482 |
|
483 /*********************************************************************** |
|
484 * |
|
485 * strings list |
|
486 * |
|
487 **********************************************************************/ |
|
488 static xmlSecPtr xmlSecStringListDuplicateItem (xmlSecPtr ptr); |
|
489 static void xmlSecStringListDestroyItem (xmlSecPtr ptr); |
|
490 |
|
491 static xmlSecPtrListKlass xmlSecStringListKlass = { |
|
492 BAD_CAST "strings-list", |
|
493 xmlSecStringListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ |
|
494 xmlSecStringListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */ |
|
495 NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ |
|
496 NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ |
|
497 }; |
|
498 |
|
499 /** |
|
500 * xmlSecStringListGetKlass: |
|
501 * |
|
502 * The strins list class. |
|
503 * |
|
504 * Returns strings list klass. |
|
505 */ |
|
506 EXPORT_C |
|
507 xmlSecPtrListId |
|
508 xmlSecStringListGetKlass(void) { |
|
509 return(&xmlSecStringListKlass); |
|
510 } |
|
511 |
|
512 static xmlSecPtr |
|
513 xmlSecStringListDuplicateItem(xmlSecPtr ptr) { |
|
514 xmlSecAssert2(ptr != NULL, NULL); |
|
515 |
|
516 return(xmlStrdup((xmlChar*)ptr)); |
|
517 } |
|
518 |
|
519 static void |
|
520 xmlSecStringListDestroyItem(xmlSecPtr ptr) { |
|
521 xmlSecAssert(ptr != NULL); |
|
522 |
|
523 xmlFree(ptr); |
|
524 } |
|
525 |
|
526 |