Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of LibParserUtils.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
  6.  */
  7.  
  8. #include <inttypes.h>
  9. #include <string.h>
  10.  
  11. #include <parserutils/utils/vector.h>
  12.  
  13. /**
  14.  * Vector object
  15.  */
  16. struct parserutils_vector
  17. {
  18.         size_t item_size;               /**< Size of an item in the vector */
  19.         size_t chunk_size;              /**< Size of a vector chunk */
  20.         size_t items_allocated;         /**< Number of slots allocated */
  21.         int32_t current_item;           /**< Index of current item */
  22.         void *items;                    /**< Items in vector */
  23.  
  24.         parserutils_alloc alloc;        /**< Memory (de)allocation function */
  25.         void *pw;                       /**< Client-specific data */
  26. };
  27.  
  28. /**
  29.  * Create a vector
  30.  *
  31.  * \param item_size   Length, in bytes, of an item in the vector
  32.  * \param chunk_size  Number of vector slots in a chunk
  33.  * \param alloc       Memory (de)allocation function
  34.  * \param pw          Pointer to client-specific private data
  35.  * \param vector      Pointer to location to receive vector instance
  36.  * \return PARSERUTILS_OK on success,
  37.  *         PARSERUTILS_BADPARM on bad parameters,
  38.  *         PARSERUTILS_NOMEM on memory exhaustion
  39.  */
  40. parserutils_error parserutils_vector_create(size_t item_size,
  41.                 size_t chunk_size, parserutils_alloc alloc, void *pw,
  42.                 parserutils_vector **vector)
  43. {
  44.         parserutils_vector *v;
  45.  
  46.         if (item_size == 0 || chunk_size == 0 || alloc == NULL ||
  47.                         vector == NULL)
  48.                 return PARSERUTILS_BADPARM;
  49.  
  50.         v = alloc(NULL, sizeof(parserutils_vector), pw);
  51.         if (v == NULL)
  52.                 return PARSERUTILS_NOMEM;
  53.  
  54.         v->items = alloc(NULL, item_size * chunk_size, pw);
  55.         if (v->items == NULL) {
  56.                 alloc(v, 0, pw);
  57.                 return PARSERUTILS_NOMEM;
  58.         }
  59.  
  60.         v->item_size = item_size;
  61.         v->chunk_size = chunk_size;
  62.         v->items_allocated = chunk_size;
  63.         v->current_item = -1;
  64.  
  65.         v->alloc = alloc;
  66.         v->pw = pw;
  67.  
  68.         *vector = v;
  69.  
  70.         return PARSERUTILS_OK;
  71. }
  72.  
  73. /**
  74.  * Destroy a vector instance
  75.  *
  76.  * \param vector  The vector to destroy
  77.  * \return PARSERUTILS_OK on success, appropriate error otherwise.
  78.  */
  79. parserutils_error parserutils_vector_destroy(parserutils_vector *vector)
  80. {
  81.         if (vector == NULL)
  82.                 return PARSERUTILS_BADPARM;
  83.  
  84.         vector->alloc(vector->items, 0, vector->pw);
  85.         vector->alloc(vector, 0, vector->pw);
  86.  
  87.         return PARSERUTILS_OK;
  88. }
  89.  
  90. /**
  91.  * Append an item to the vector
  92.  *
  93.  * \param vector  The vector to append to
  94.  * \param item    The item to append
  95.  * \return PARSERUTILS_OK on success, appropriate error otherwise
  96.  */
  97. parserutils_error parserutils_vector_append(parserutils_vector *vector,
  98.                 void *item)
  99. {
  100.         int32_t slot;
  101.  
  102.         if (vector == NULL || item == NULL)
  103.                 return PARSERUTILS_BADPARM;
  104.  
  105.         /* Ensure we'll get a valid slot */
  106.         if (vector->current_item < -1 || vector->current_item == INT32_MAX)
  107.                 return PARSERUTILS_INVALID;
  108.  
  109.         slot = vector->current_item + 1;
  110.  
  111.         if ((size_t) slot >= vector->items_allocated) {
  112.                 void *temp = vector->alloc(vector->items,
  113.                                 (vector->items_allocated + vector->chunk_size) *
  114.                                 vector->item_size, vector->pw);
  115.                 if (temp == NULL)
  116.                         return PARSERUTILS_NOMEM;
  117.  
  118.                 vector->items = temp;
  119.                 vector->items_allocated += vector->chunk_size;
  120.         }
  121.  
  122.         memcpy((uint8_t *) vector->items + (slot * vector->item_size),
  123.                         item, vector->item_size);
  124.         vector->current_item = slot;
  125.  
  126.         return PARSERUTILS_OK;
  127. }
  128.  
  129. /**
  130.  * Clear a vector
  131.  *
  132.  * \param vector  The vector to clear
  133.  * \return PARSERUTILS_OK on success, appropriate error otherwise.
  134.  */
  135. parserutils_error parserutils_vector_clear(parserutils_vector *vector)
  136. {
  137.         if (vector == NULL)
  138.                 return PARSERUTILS_BADPARM;
  139.  
  140.         if (vector->current_item < 0)
  141.                 return PARSERUTILS_INVALID;
  142.  
  143.         vector->current_item = -1;
  144.  
  145.         return PARSERUTILS_OK;
  146. }
  147.  
  148. /**
  149.  * Remove the last item from a vector
  150.  *
  151.  * \param vector  The vector to remove from
  152.  * \return PARSERUTILS_OK on success, appropriate error otherwise
  153.  */
  154. parserutils_error parserutils_vector_remove_last(parserutils_vector *vector)
  155. {
  156.         if (vector == NULL)
  157.                 return PARSERUTILS_BADPARM;
  158.  
  159.         if (vector->current_item < 0)
  160.                 return PARSERUTILS_INVALID;
  161.  
  162.         vector->current_item--;
  163.  
  164.         return PARSERUTILS_OK;
  165. }
  166.  
  167. /**
  168.  * Acquire the length (in items) of the vector.
  169.  *
  170.  * \param vector  The vector to interrogate.
  171.  * \param length  Pointer to location to receive length information.
  172.  * \return PARSERUTILS_OK on success, appropriate error otherwise
  173.  */
  174. parserutils_error parserutils_vector_get_length(parserutils_vector *vector,
  175.                                                 size_t *length)
  176. {
  177.         if (vector == NULL)
  178.                 return PARSERUTILS_BADPARM;
  179.        
  180.         if (length == NULL)
  181.                 return PARSERUTILS_BADPARM;
  182.        
  183.         *length = vector->current_item + 1;
  184.        
  185.         return PARSERUTILS_OK;
  186. }
  187.  
  188. /**
  189.  * Iterate over a vector
  190.  *
  191.  * \param vector  The vector to iterate over
  192.  * \param ctx     Pointer to an integer for the iterator to use as context.
  193.  * \return Pointer to current item, or NULL if no more
  194.  *
  195.  * \note The value pointed to by \a ctx must be zero to begin the iteration.
  196.  */
  197. const void *parserutils_vector_iterate(const parserutils_vector *vector,
  198.                 int32_t *ctx)
  199. {
  200.         void *item;
  201.  
  202.         if (vector == NULL || ctx == NULL || vector->current_item < 0)
  203.                 return NULL;
  204.  
  205.         if ((*ctx) > vector->current_item)
  206.                 return NULL;
  207.  
  208.         item = (uint8_t *) vector->items + ((*ctx) * vector->item_size);
  209.  
  210.         (*ctx)++;
  211.  
  212.         return item;
  213. }
  214.  
  215. /**
  216.  * Peek at an item in a vector
  217.  *
  218.  * \param vector  The vector to iterate over
  219.  * \param ctx     Integer for the iterator to use as context.
  220.  * \return Pointer to item, or NULL if no more
  221.  */
  222. const void *parserutils_vector_peek(const parserutils_vector *vector,
  223.                 int32_t ctx)
  224. {
  225.         if (vector == NULL || vector->current_item < 0)
  226.                 return NULL;
  227.  
  228.         if (ctx > vector->current_item)
  229.                 return NULL;
  230.  
  231.         return (uint8_t *) vector->items + (ctx * vector->item_size);
  232. }
  233.  
  234.  
  235. #ifndef NDEBUG
  236. #include <stdio.h>
  237.  
  238. extern void parserutils_vector_dump(parserutils_vector *vector,
  239.                 const char *prefix, void (*printer)(void *item));
  240.  
  241. void parserutils_vector_dump(parserutils_vector *vector, const char *prefix,
  242.                 void (*printer)(void *item))
  243. {
  244.         int32_t i;
  245.  
  246.         if (vector == NULL || printer == NULL)
  247.                 return;
  248.  
  249.         for (i = 0; i <= vector->current_item; i++) {
  250.                 printf("%s %d: ", prefix != NULL ? prefix : "", i);
  251.                 printer((uint8_t *) vector->items + (i * vector->item_size));
  252.                 printf("\n");
  253.         }
  254. }
  255.  
  256. #endif
  257.  
  258.