gdb/common/vec.c - gdb

Data types defined

Functions defined

Source code

  1. /* Vector API for GDB.
  2.    Copyright (C) 2004-2015 Free Software Foundation, Inc.
  3.    Contributed by Nathan Sidwell <nathan@codesourcery.com>

  4.    This file is part of GDB.

  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 3 of the License, or
  8.    (at your option) any later version.

  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.

  13.    You should have received a copy of the GNU General Public License
  14.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  15. #include "common-defs.h"
  16. #include "vec.h"

  17. struct vec_prefix
  18. {
  19.   unsigned num;
  20.   unsigned alloc;
  21.   void *vec[1];
  22. };

  23. /* Calculate the new ALLOC value, making sure that abs(RESERVE) slots
  24.    are free.  If RESERVE < 0 grow exactly, otherwise grow
  25.    exponentially.  */

  26. static inline unsigned
  27. calculate_allocation (const struct vec_prefix *pfx, int reserve)
  28. {
  29.   unsigned alloc = 0;
  30.   unsigned num = 0;

  31.   if (pfx)
  32.     {
  33.       alloc = pfx->alloc;
  34.       num = pfx->num;
  35.     }
  36.   else if (!reserve)
  37.     /* If there's no prefix, and we've not requested anything, then we
  38.        will create a NULL vector.  */
  39.     return 0;

  40.   /* We must have run out of room.  */
  41.   gdb_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve));

  42.   if (reserve < 0)
  43.     /* Exact size.  */
  44.     alloc = num + -reserve;
  45.   else
  46.     {
  47.       /* Exponential growth.  */
  48.       if (!alloc)
  49.         alloc = 4;
  50.       else if (alloc < 16)
  51.         /* Double when small.  */
  52.         alloc = alloc * 2;
  53.       else
  54.         /* Grow slower when large.  */
  55.         alloc = (alloc * 3 / 2);

  56.       /* If this is still too small, set it to the right size.  */
  57.       if (alloc < num + reserve)
  58.         alloc = num + reserve;
  59.     }
  60.   return alloc;
  61. }

  62. /* Ensure there are at least abs(RESERVE) free slots in VEC.  If
  63.    RESERVE < 0 grow exactly, else grow exponentially.  As a special
  64.    case, if VEC is NULL, and RESERVE is 0, no vector will be created.  */

  65. void *
  66. vec_p_reserve (void *vec, int reserve)
  67. {
  68.   return vec_o_reserve (vec, reserve,
  69.                         offsetof (struct vec_prefix, vec), sizeof (void *));
  70. }

  71. /* As vec_p_reserve, but for object vectors.  The vector's trailing
  72.    array is at VEC_OFFSET offset and consists of ELT_SIZE sized
  73.    elements.  */

  74. void *
  75. vec_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size)
  76. {
  77.   struct vec_prefix *pfx = vec;
  78.   unsigned alloc = calculate_allocation (pfx, reserve);

  79.   if (!alloc)
  80.     return NULL;

  81.   vec = xrealloc (vec, vec_offset + alloc * elt_size);
  82.   ((struct vec_prefix *)vec)->alloc = alloc;
  83.   if (!pfx)
  84.     ((struct vec_prefix *)vec)->num = 0;

  85.   return vec;
  86. }

  87. #if 0
  88. /* Example uses.  */
  89. DEF_VEC_I (int);
  90. typedef struct X
  91. {
  92.   int i;
  93. } obj_t;
  94. typedef obj_t *ptr_t;

  95. DEF_VEC_P (ptr_t);
  96. DEF_VEC_O (obj_t);
  97. #endif