Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* dynstr.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Port                                                                   */
  6. /*                                                                           */
  7. /* Handling of strings with dynamic allocation                               */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15.  
  16. #include "dynstr.h"
  17.  
  18. static void check_dynamic(const as_dynstr_t *p_str)
  19. {
  20.   if (!p_str->dynamic)
  21.   {
  22.     fprintf(stderr, "attemt to resize non-dynamic string\n");
  23.     abort();
  24.   }
  25. }
  26.  
  27. /*!------------------------------------------------------------------------
  28.  * \fn     as_dynstr_ini(as_dynstr_t *p_str, size_t AllocLen)
  29.  * \brief  initialize empty string with given capacity
  30.  * \param  p_str string to initialize
  31.  * \param  AllocLen initial alloc length
  32.  * ------------------------------------------------------------------------ */
  33.  
  34. void as_dynstr_ini(as_dynstr_t *p_str, size_t ini_capacity)
  35. {
  36.   p_str->p_str = ini_capacity ? (char*)malloc(ini_capacity) : NULL;
  37.   p_str->capacity = p_str->p_str ? ini_capacity : 0;
  38.   p_str->dynamic = !!p_str->p_str;
  39.   memset(p_str->p_str, 0, p_str->capacity);
  40. }
  41.  
  42. /*!------------------------------------------------------------------------
  43.  * \fn     as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
  44.  * \brief  initialize empty string from other string
  45.  * \param  p_str string to initialize
  46.  * \param  p_src string to clone
  47.  * ------------------------------------------------------------------------ */
  48.  
  49. void as_dynstr_ini_clone(as_dynstr_t *p_str, const as_dynstr_t *p_src)
  50. {
  51.   p_str->p_str = (char*)malloc(p_src->capacity);
  52.   if (p_str->p_str)
  53.   {
  54.     strcpy(p_str->p_str, p_src->p_str);
  55.     p_str->capacity = p_src->capacity;
  56.     p_str->dynamic = 1;
  57.   }
  58.   else
  59.   {
  60.     p_str->capacity = 0;
  61.     p_str->dynamic = 0;
  62.   }
  63. }
  64.  
  65. /*!------------------------------------------------------------------------
  66.  * \fn     as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
  67.  * \brief  initialize string from C string
  68.  * \param  p_str string to initialize
  69.  * \param  p_src init source
  70.  * ------------------------------------------------------------------------ */
  71.  
  72. void as_dynstr_ini_c_str(as_dynstr_t *p_str, const char *p_src)
  73. {
  74.   size_t capacity = as_dynstr_roundup_len(strlen(p_src));
  75.  
  76.   p_str->p_str = (char*)malloc(capacity);
  77.   if (p_str->p_str)
  78.   {
  79.     strcpy(p_str->p_str, p_src);
  80.     p_str->capacity = capacity;
  81.     p_str->dynamic = 1;
  82.   }
  83.   else
  84.   {
  85.     p_str->capacity = 0;
  86.     p_str->dynamic = 0;
  87.   }
  88. }
  89.  
  90. /*!------------------------------------------------------------------------
  91.  * \fn     as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
  92.  * \brief  shrink/grow string's capacity
  93.  * \param  p_str string to adapt
  94.  * \param  new_capacity new capacity
  95.  * \return 0 if success or error code
  96.  * ------------------------------------------------------------------------ */
  97.  
  98. int as_dynstr_realloc(as_dynstr_t *p_str, size_t new_capacity)
  99. {
  100.   char *p_new;
  101.   size_t old_capacity;
  102.  
  103.   check_dynamic(p_str);
  104.   p_new = (char*)realloc(p_str->p_str, new_capacity);
  105.   old_capacity = p_str->capacity;
  106.   if (p_new)
  107.   {
  108.     p_str->p_str = p_new;
  109.     p_str->capacity = new_capacity;
  110.     if (new_capacity > old_capacity)
  111.       memset(p_str->p_str + old_capacity, 0, new_capacity - old_capacity);
  112.     else if (new_capacity > 0)
  113.       p_str->p_str[new_capacity - 1] = '\0';
  114.     return 0;
  115.   }
  116.   else
  117.     return ENOMEM;
  118. }
  119.  
  120. /*!------------------------------------------------------------------------
  121.  * \fn     as_dynstr_free(as_dynstr_t *p_str)
  122.  * \brief  free/destroy string
  123.  * \param  p_str string to handle
  124.  * ------------------------------------------------------------------------ */
  125.  
  126. void as_dynstr_free(as_dynstr_t *p_str)
  127. {
  128.   if (p_str->dynamic && p_str->p_str)
  129.     free(p_str->p_str);
  130.   p_str->p_str = NULL;
  131.   p_str->capacity = 0;
  132.   p_str->dynamic = 0;
  133. }
  134.  
  135. /*!------------------------------------------------------------------------
  136.  * \fn     as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
  137.  * \brief  set string from other string
  138.  * \param  p_str string to set
  139.  * \param  p_src init source
  140.  * \return actual # of characters copied
  141.  * ------------------------------------------------------------------------ */
  142.  
  143. size_t as_dynstr_copy(as_dynstr_t *p_dest, const as_dynstr_t *p_src)
  144. {
  145.   return as_dynstr_copy_c_str(p_dest, p_src->p_str);
  146. }
  147.  
  148. /*!------------------------------------------------------------------------
  149.  * \fn     as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
  150.  * \brief  set string from C string
  151.  * \param  p_str string to set
  152.  * \param  p_src init source
  153.  * \return actual # of characters copied
  154.  * ------------------------------------------------------------------------ */
  155.  
  156. size_t as_dynstr_copy_c_str(as_dynstr_t *p_dest, const char *p_src)
  157. {
  158.   size_t len = strlen(p_src);
  159.  
  160.   if ((len >= p_dest->capacity) && p_dest->dynamic)
  161.     as_dynstr_realloc(p_dest, as_dynstr_roundup_len(len));
  162.  
  163.   if (len >= p_dest->capacity)
  164.     len = p_dest->capacity - 1;
  165.   memcpy(p_dest->p_str, p_src, len);
  166.   p_dest->p_str[len] = '\0';
  167.   return len;
  168. }
  169.  
  170. /*!------------------------------------------------------------------------
  171.  * \fn     as_dynstr_append(as_dynstr_t *p_dest, const char *p_src, size_t src_len)
  172.  * \brief  extend string
  173.  * \param  p_dest string to extend
  174.  * \param  p_src what to append
  175.  * \param  src_len how much to append
  176.  * \return actual # of bytes transferred
  177.  * ------------------------------------------------------------------------ */
  178.  
  179. size_t as_dynstr_append(as_dynstr_t *p_dest, const char *p_src, size_t src_len)
  180. {
  181.   size_t dest_len = strlen(p_dest->p_str);
  182.  
  183.   if ((dest_len + src_len + 1 > p_dest->capacity) && p_dest->dynamic)
  184.     as_dynstr_realloc(p_dest, as_dynstr_roundup_len(dest_len + src_len));
  185.   if (src_len >= p_dest->capacity - dest_len)
  186.     src_len = p_dest->capacity - dest_len - 1;
  187.   memcpy(p_dest->p_str + dest_len, p_src, src_len);
  188.   p_dest->p_str[dest_len + src_len] = '\0';
  189.   return src_len;
  190. }
  191.  
  192. /*!------------------------------------------------------------------------
  193.  * \fn     as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
  194.  * \brief  extend string
  195.  * \param  p_dest string to extend
  196.  * \param  p_src what to append
  197.  * \return actual # of bytes transferred
  198.  * ------------------------------------------------------------------------ */
  199.  
  200. size_t as_dynstr_append_c_str(as_dynstr_t *p_dest, const char *p_src)
  201. {
  202.   return as_dynstr_append(p_dest, p_src, strlen(p_src));
  203. }
  204.  
  205. /*!------------------------------------------------------------------------
  206.  * \fn     as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
  207.  * \brief  debug helper
  208.  * \param  p_file where to dump
  209.  * \param  p_str string to dump
  210.  * ------------------------------------------------------------------------ */
  211.  
  212. void as_dynstr_dump_hex(FILE *p_file, const as_dynstr_t *p_str)
  213. {
  214.   const char *p_run;
  215.  
  216.   fprintf(p_file, "[%u]", (unsigned)p_str->capacity);
  217.   for (p_run = p_str->p_str; *p_run; p_run++) fprintf(p_file, " %02x", *p_run & 0xff);
  218.   fprintf(p_file, "\n");
  219. }
  220.