xml/cxmllibrary/src/utils/src/cxml_vector.c
branchRCL_3
changeset 21 604ca70b6235
parent 20 889504eac4fb
equal deleted inserted replaced
20:889504eac4fb 21:604ca70b6235
     1 /*
       
     2 * Copyright (c) 2003 - 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <xml/cxml/nw_tinytree.h>
       
    20 #include "cxml_internal.h"
       
    21 
       
    22 /* ------------------------------------------------------------------------- */
       
    23 
       
    24 /* ------------------------------------------------------------------------- */
       
    25 static
       
    26 CXML_Uint8*
       
    27 CXML_Vector_AllocateSegment (CXML_Vector_t* thisObj, NW_TinyTree_TreeNode_t* sentinel)
       
    28 {
       
    29   CXML_Uint8* buffer = NULL;
       
    30 	if(sentinel)
       
    31 	{
       
    32 		buffer = (NW_Uint8*) NW_Mem_Malloc ((thisObj->segmentSize + 1) * thisObj->elementSize);
       
    33 		if(buffer)
       
    34 		{
       
    35 		NW_Mem_memcpy(buffer, sentinel, sizeof(NW_TinyTree_TreeNode_t));
       
    36 		buffer += thisObj->elementSize;
       
    37    	        }
       
    38 	}
       
    39 	else
       
    40 	{
       
    41 		buffer = (NW_Uint8*) NW_Mem_Malloc (thisObj->segmentSize * thisObj->elementSize);
       
    42 	}
       
    43 	return buffer;
       
    44 }
       
    45 
       
    46 /* ------------------------------------------------------------------------- */
       
    47 static
       
    48 NW_Status_t
       
    49 CXML_Vector_ResizeCapacity (CXML_Vector_t* thisObj,
       
    50 							CXML_Vector_Metric_t capacityNeeded,
       
    51 							NW_TinyTree_TreeNode_t* sentinel)
       
    52 {
       
    53   CXML_Vector_Metric_t newNumSegments;
       
    54   CXML_Vector_Metric_t newSegmentListSize;
       
    55   NW_Uint8** newSegmentList;
       
    56  // CXML_Vector_Metric_t index;
       
    57   
       
    58   /* calculate the new segmentList size */
       
    59   newNumSegments =
       
    60     (CXML_Vector_Metric_t) ((capacityNeeded - 1) / thisObj->segmentSize + 1);
       
    61   newSegmentListSize = (CXML_Vector_Metric_t)
       
    62     (((newNumSegments - 1) / CXML_SEGMENT_LIST_INCREMENT + 1) * CXML_SEGMENT_LIST_INCREMENT);
       
    63 
       
    64   /* if we are shrinking the array, we must first deallocate all the segments
       
    65      that will be obsolete */
       
    66   while (thisObj->numSegments > newNumSegments) {
       
    67     NW_Mem_Free (thisObj->segmentList[--thisObj->numSegments]);
       
    68   }
       
    69   thisObj->capacity =
       
    70     (CXML_Vector_Metric_t) (thisObj->numSegments * thisObj->segmentSize);
       
    71   
       
    72   /* allocate the new segmentList and copy the old segmentList entries into the
       
    73      new */
       
    74   newSegmentList =
       
    75     (NW_Uint8**) NW_Mem_Malloc (newSegmentListSize * sizeof (*newSegmentList));
       
    76   if (newSegmentList == NULL) {
       
    77     return NW_STAT_OUT_OF_MEMORY; 
       
    78   }
       
    79   (void) NW_Mem_memcpy (newSegmentList, thisObj->segmentList,
       
    80                         thisObj->numSegments * sizeof (*newSegmentList));
       
    81  
       
    82   /* free the old segmentList and install the new */
       
    83  NW_Mem_Free (thisObj->segmentList);
       
    84 
       
    85   thisObj->segmentList = newSegmentList;
       
    86   thisObj->segmentListSize = newSegmentListSize;
       
    87 
       
    88   /* if we are growing the array we need to allocate the new segments */
       
    89   while (thisObj->numSegments < newNumSegments) {
       
    90     thisObj->segmentList[thisObj->numSegments] =
       
    91       CXML_Vector_AllocateSegment(thisObj, sentinel);
       
    92     if (thisObj->segmentList[thisObj->numSegments++] == NULL) {
       
    93       thisObj->numSegments -= 1;
       
    94       return NW_STAT_OUT_OF_MEMORY; 
       
    95     }
       
    96   }
       
    97   thisObj->capacity =
       
    98     (CXML_Vector_Metric_t) (thisObj->numSegments * thisObj->segmentSize);
       
    99   
       
   100   /* successful completion */
       
   101   return NW_STAT_SUCCESS;
       
   102 }
       
   103 
       
   104 /* ------------------------------------------------------------------------- */
       
   105 static
       
   106 NW_Status_t
       
   107 CXML_Vector_MoveElements (CXML_Vector_t* thisObj,
       
   108 													CXML_Vector_Metric_t srcIndex,
       
   109 													CXML_Vector_Metric_t dstIndex,
       
   110 													NW_TinyTree_TreeNode_t* sentinel)
       
   111 {
       
   112   NW_Int32 sizeDelta;
       
   113   CXML_Vector_Metric_t numElements;
       
   114   NW_Int32 index;
       
   115 
       
   116   /* */
       
   117   if (dstIndex > srcIndex) {
       
   118     sizeDelta = dstIndex - srcIndex;
       
   119   } else {
       
   120     sizeDelta = - (NW_Int32) (srcIndex - dstIndex);
       
   121   }
       
   122 
       
   123   if (thisObj->size + sizeDelta > thisObj->capacity) {
       
   124     NW_Status_t status;
       
   125 
       
   126     status = CXML_Vector_ResizeCapacity (thisObj,
       
   127 			(CXML_Vector_Metric_t) (thisObj->size + sizeDelta), sentinel);
       
   128     if (status != NW_STAT_SUCCESS) {
       
   129       return status;
       
   130     }
       
   131   }
       
   132 
       
   133   /* now do the actual move */
       
   134   /* TODO: this is a very inefficient way of moving the data, we will probably
       
   135      need to implement a block move capability */
       
   136   numElements = (CXML_Vector_Metric_t) (thisObj->size - srcIndex);
       
   137   if (srcIndex > dstIndex) {
       
   138     for (index = 0; index < NW_INT32_CAST(numElements); index++) {
       
   139       (void) NW_Mem_memcpy (CXML_Vector_AddressAt (thisObj, 
       
   140 				(CXML_Vector_Metric_t) (dstIndex + index)), CXML_Vector_AddressAt (thisObj,
       
   141 				(CXML_Vector_Metric_t) (srcIndex + index)), thisObj->elementSize);
       
   142     }
       
   143   } else {
       
   144     for (index = numElements - 1; index >= 0; index--) {
       
   145       (void) NW_Mem_memcpy (CXML_Vector_AddressAt (thisObj, 
       
   146 				(CXML_Vector_Metric_t) (dstIndex + index)), CXML_Vector_AddressAt (thisObj, 
       
   147 				(CXML_Vector_Metric_t) (srcIndex + index)), thisObj->elementSize);
       
   148     }
       
   149   }
       
   150 
       
   151   /* successful completion */
       
   152   return NW_STAT_SUCCESS;
       
   153 }
       
   154 
       
   155 CXML_Vector_t*
       
   156 CXML_Vector_Construct(CXML_Vector_Metric_t elementSize,
       
   157 											CXML_Vector_Metric_t segmentSize)
       
   158 {
       
   159 	CXML_Vector_t* vector = (CXML_Vector_t*) NW_Mem_Malloc(sizeof(CXML_Vector_t));
       
   160 
       
   161 if(vector)
       
   162  {
       
   163 	vector->elementSize = elementSize;
       
   164 	vector->capacity = 0;
       
   165 	vector->size = 0;
       
   166 
       
   167 	vector->segmentSize = segmentSize;
       
   168 	vector->segmentListSize = CXML_SEGMENT_LIST_INCREMENT;
       
   169 	
       
   170 	//Allocate memory for one segment here. For more memory the
       
   171 	//function CXML_Vector_ResizeCapacity() will do the job.
       
   172 
       
   173 	vector->segmentList = (NW_Uint8**)
       
   174               NW_Mem_Malloc (vector->segmentListSize * sizeof (*vector->segmentList));
       
   175 
       
   176   if (vector->segmentList == NULL) {
       
   177 		NW_Mem_Free(vector);
       
   178                 return NULL;
       
   179   }
       
   180 vector->numSegments = 0;
       
   181 	}
       
   182 	return vector;
       
   183 }
       
   184 
       
   185 void
       
   186 CXML_Vector_Destruct(CXML_Vector_t* vector)
       
   187 {
       
   188 	CXML_Vector_Metric_t index;
       
   189 	for (index = 0; index < vector->numSegments; index++) {
       
   190 		NW_Mem_Free (vector->segmentList[index]);
       
   191 	}
       
   192 	NW_Mem_Free (vector->segmentList);
       
   193 	NW_Mem_Free(vector);
       
   194 }
       
   195 
       
   196 void
       
   197 CXML_Vector_AdjustSegment(CXML_Vector_t* vector)
       
   198 {
       
   199 	CXML_Vector_Metric_t index;
       
   200 
       
   201   /* 
       
   202    * Walk through segment list adjusting pointers to the 
       
   203    * sentinel element at the beginning of each segment
       
   204    */
       
   205   
       
   206   for (index = 0; index < vector->numSegments; index++) {
       
   207     vector->segmentList[index] -= vector->elementSize; 
       
   208   }
       
   209 }
       
   210 
       
   211 NW_Uint8*
       
   212 CXML_Vector_AddressAt (const CXML_Vector_t* thisObj,
       
   213 											 CXML_Vector_Metric_t index)
       
   214 {
       
   215   CXML_Vector_Metric_t segmentIndex;
       
   216 
       
   217   /* determine the segment index and return the offset into that segment */
       
   218   segmentIndex =
       
   219     (CXML_Vector_Metric_t) (index / thisObj->segmentSize);
       
   220   return
       
   221     (NW_Uint8*) thisObj->segmentList[segmentIndex]
       
   222     + (index % thisObj->segmentSize) * thisObj->elementSize;
       
   223 }
       
   224 
       
   225 /* ------------------------------------------------------------------------- */
       
   226 void**
       
   227 CXML_Vector_InsertAt (CXML_Vector_t* thisObj,
       
   228 											void* element,
       
   229 											CXML_Vector_Metric_t where,
       
   230 											void* sentinel)
       
   231 {
       
   232   NW_Status_t status;
       
   233 
       
   234   /* convert the where if CXML_Vector_AtEnd is specified */
       
   235   if (where == CXML_Vector_AtEnd) {
       
   236     where = thisObj->size;
       
   237   }
       
   238 
       
   239   /* make sure that the where element is not out of bounds */
       
   240   NW_ASSERT (where <= thisObj->size);
       
   241 
       
   242   /* move all the elements up by one, if this fails we simply return
       
   243      the error code passed to us */
       
   244   status =
       
   245     CXML_Vector_MoveElements (thisObj, where,
       
   246                               (CXML_Vector_Metric_t) (where + 1),
       
   247                               (NW_TinyTree_TreeNode_t*) sentinel);
       
   248   if (status != NW_STAT_SUCCESS) {
       
   249     return NULL;
       
   250   }
       
   251 
       
   252   /* copy the element into vector */
       
   253   if (element != NULL) {
       
   254     (void) NW_Mem_memcpy (CXML_Vector_AddressAt (thisObj, where),
       
   255 			element, thisObj->elementSize);
       
   256   } else {
       
   257     /*
       
   258      * if element is NULL, then we need to zero out the memory block.  This is necessary
       
   259 	 * because later code which fills in the values for this newly allocated vector
       
   260 	 * element may leave some bytes in the memory block un-assigned due to padding.
       
   261 	 */
       
   262     NW_Mem_memset ( CXML_Vector_AddressAt (thisObj, where), 
       
   263 			0, thisObj->elementSize);
       
   264   }
       
   265 
       
   266   /* increment the size count */
       
   267   thisObj->size += 1;
       
   268 
       
   269   /* successful completion */
       
   270   return (void**)
       
   271     CXML_Vector_AddressAt (thisObj, where);
       
   272 }
       
   273 
       
   274 /* ------------------------------------------------------------------------- */
       
   275 NW_Status_t
       
   276 CXML_Vector_RemoveAt (CXML_Vector_t* thisObj,
       
   277 											CXML_Vector_Metric_t index)
       
   278 {
       
   279   NW_Status_t status;
       
   280 
       
   281   /* convert the index if CXML_Vector_AtEnd is specified */
       
   282   if (index == CXML_Vector_AtEnd) {
       
   283     index = (CXML_Vector_Metric_t) (thisObj->size -  1);
       
   284   }
       
   285 
       
   286   /* make sure that the index element is not out of bounds */
       
   287   if (index >= thisObj->size) {
       
   288     return NW_STAT_FAILURE;
       
   289   }
       
   290 
       
   291   /* don't bother to move anything if the resultant size is zero */
       
   292   if (thisObj->size > 1) {
       
   293     /* move all the elements down by one, if this fails we simply return
       
   294        the error code passed to us */
       
   295     status =
       
   296       CXML_Vector_MoveElements (thisObj, (CXML_Vector_Metric_t) (index + 1),
       
   297 																index, NULL);
       
   298     if (status != NW_STAT_SUCCESS) {
       
   299       return status;
       
   300     }
       
   301   }
       
   302 
       
   303   /* increment the size count */
       
   304   thisObj->size -= 1;
       
   305 
       
   306   /* successful completion */
       
   307   return NW_STAT_SUCCESS;
       
   308 }
       
   309 
       
   310 /* ------------------------------------------------------------------------- */
       
   311 void**
       
   312 CXML_Vector_ElementAt (const CXML_Vector_t* vector,
       
   313 											 CXML_Vector_Metric_t index)
       
   314 {
       
   315   if (index >= vector->size) {
       
   316     return NULL;
       
   317   }
       
   318   return (void**) CXML_Vector_AddressAt (vector, index);
       
   319 }
       
   320 
       
   321 /* ------------------------------------------------------------------------- */
       
   322 CXML_Vector_Metric_t
       
   323 CXML_Vector_GetElementIndex (const CXML_Vector_t* vector,
       
   324 														 void* target)
       
   325 {
       
   326   CXML_Vector_Metric_t index;
       
   327 
       
   328   for (index = 0; index < vector->size; index++) {
       
   329     void* element;
       
   330 
       
   331     /* get and compare the element */
       
   332     element = CXML_Vector_ElementAt (vector, index);
       
   333     if (NW_Mem_memcmp (target, element, vector->elementSize) == 0) {
       
   334       return index;
       
   335     }
       
   336   }
       
   337 
       
   338   /* no match found, return CXML_Vector_AtEnd */
       
   339   return CXML_Vector_AtEnd;
       
   340 }
       
   341