GDB (API)
|
00001 /* Vector API for GDB. 00002 Copyright (C) 2004-2013 Free Software Foundation, Inc. 00003 Contributed by Nathan Sidwell <nathan@codesourcery.com> 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #ifdef GDBSERVER 00021 #include "server.h" 00022 #else 00023 #include "defs.h" 00024 #endif 00025 00026 #include "vec.h" 00027 00028 struct vec_prefix 00029 { 00030 unsigned num; 00031 unsigned alloc; 00032 void *vec[1]; 00033 }; 00034 00035 /* Calculate the new ALLOC value, making sure that abs(RESERVE) slots 00036 are free. If RESERVE < 0 grow exactly, otherwise grow 00037 exponentially. */ 00038 00039 static inline unsigned 00040 calculate_allocation (const struct vec_prefix *pfx, int reserve) 00041 { 00042 unsigned alloc = 0; 00043 unsigned num = 0; 00044 00045 if (pfx) 00046 { 00047 alloc = pfx->alloc; 00048 num = pfx->num; 00049 } 00050 else if (!reserve) 00051 /* If there's no prefix, and we've not requested anything, then we 00052 will create a NULL vector. */ 00053 return 0; 00054 00055 /* We must have run out of room. */ 00056 gdb_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve)); 00057 00058 if (reserve < 0) 00059 /* Exact size. */ 00060 alloc = num + -reserve; 00061 else 00062 { 00063 /* Exponential growth. */ 00064 if (!alloc) 00065 alloc = 4; 00066 else if (alloc < 16) 00067 /* Double when small. */ 00068 alloc = alloc * 2; 00069 else 00070 /* Grow slower when large. */ 00071 alloc = (alloc * 3 / 2); 00072 00073 /* If this is still too small, set it to the right size. */ 00074 if (alloc < num + reserve) 00075 alloc = num + reserve; 00076 } 00077 return alloc; 00078 } 00079 00080 /* Ensure there are at least abs(RESERVE) free slots in VEC. If 00081 RESERVE < 0 grow exactly, else grow exponentially. As a special 00082 case, if VEC is NULL, and RESERVE is 0, no vector will be created. */ 00083 00084 void * 00085 vec_p_reserve (void *vec, int reserve) 00086 { 00087 return vec_o_reserve (vec, reserve, 00088 offsetof (struct vec_prefix, vec), sizeof (void *)); 00089 } 00090 00091 /* As vec_p_reserve, but for object vectors. The vector's trailing 00092 array is at VEC_OFFSET offset and consists of ELT_SIZE sized 00093 elements. */ 00094 00095 void * 00096 vec_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size) 00097 { 00098 struct vec_prefix *pfx = vec; 00099 unsigned alloc = calculate_allocation (pfx, reserve); 00100 00101 if (!alloc) 00102 return NULL; 00103 00104 vec = xrealloc (vec, vec_offset + alloc * elt_size); 00105 ((struct vec_prefix *)vec)->alloc = alloc; 00106 if (!pfx) 00107 ((struct vec_prefix *)vec)->num = 0; 00108 00109 return vec; 00110 } 00111 00112 #if 0 00113 /* Example uses. */ 00114 DEF_VEC_I (int); 00115 typedef struct X 00116 { 00117 int i; 00118 } obj_t; 00119 typedef obj_t *ptr_t; 00120 00121 DEF_VEC_P (ptr_t); 00122 DEF_VEC_O (obj_t); 00123 #endif