xmlsecurityengine/xmlsec/src/xmlsec_list.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     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