FreeBASIC  0.91.0
array_redimpresv.c
Go to the documentation of this file.
1 /* redim preserve function */
2 
3 #include "fb.h"
4 
6  (
7  FBARRAY *array,
8  size_t element_len,
9  int doclear,
10  FB_DEFCTOR ctor,
11  FB_DTORMULT dtor_mult,
12  FB_DEFCTOR dtor,
13  size_t dimensions,
14  va_list ap
15  )
16 {
17  size_t i, elements, size;
18  ssize_t diff;
19  FBARRAYDIM *dim;
20  ssize_t lbTB[FB_MAXDIMENSIONS];
21  ssize_t ubTB[FB_MAXDIMENSIONS];
22  const char *this_;
23 
24  /* load bounds */
25  for( i = 0; i < dimensions; i++ )
26  {
27  lbTB[i] = va_arg( ap, ssize_t );
28  ubTB[i] = va_arg( ap, ssize_t );
29 
30  if( lbTB[i] > ubTB[i] )
32  }
33 
34  /* shrinking the array? free unused elements */
35  if( dtor_mult != NULL )
36  {
37  ssize_t new_lb = (ubTB[0] - lbTB[0]) + 1;
38  if( new_lb < array->dimTB[0].elements )
39  {
40  /* !!!FIXME!!! check exceptions (only if rewritten in C++) */
41  dtor_mult( array, dtor, new_lb );
42  }
43  }
44 
45  /* calc size */
46  elements = fb_hArrayCalcElements( dimensions, &lbTB[0], &ubTB[0] );
47  diff = fb_hArrayCalcDiff( dimensions, &lbTB[0], &ubTB[0] ) * element_len;
48  size = elements * element_len;
49 
50  /* realloc */
51  array->ptr = realloc( array->ptr, size );
52  if( array->ptr == NULL )
54 
55  /* clear remainder */
56  if( size > array->size )
57  {
58  this_ = ((const char*)array->ptr) + array->size;
59 
60  if( doclear )
61  memset( (void *)this_, 0, size - array->size );
62 
63  if( ctor != NULL )
64  {
65  size_t objects = (size - array->size) / element_len;
66  while( objects > 0 )
67  {
68  /* !!!FIXME!!! check exceptions (only if rewritten in C++) */
69  ctor( this_ );
70 
71  this_ += element_len;
72  --objects;
73  }
74  }
75  }
76 
77  /* set descriptor */
78  dim = &array->dimTB[0];
79  for( i = 0; i < dimensions; i++, dim++ )
80  {
81  dim->elements = (ubTB[i] - lbTB[i]) + 1;
82  dim->lbound = lbTB[i];
83  dim->ubound = ubTB[i];
84  }
85 
86  FB_ARRAY_SETDESC( array, element_len, dimensions, size, diff );
87 
88  return fb_ErrorSetNum( FB_RTERROR_OK );
89 }
90 
91 static int hRedim
92  (
93  FBARRAY *array,
94  size_t element_len,
95  int doclear,
96  int isvarlen,
97  size_t dimensions,
98  va_list ap
99  )
100 {
101  FB_DTORMULT dtor_mult;
102 
103  /* new? */
104  if( array->ptr == NULL )
105  return fb_hArrayAlloc( array, element_len, doclear, NULL, dimensions, ap );
106 
107  /* realloc.. */
108  if( isvarlen )
109  dtor_mult = &fb_hArrayDtorStr;
110  else
111  dtor_mult = NULL;
112 
113  return fb_hArrayRealloc( array, element_len, doclear, NULL, dtor_mult, NULL, dimensions, ap );
114 }
115 
117  (
118  FBARRAY *array,
119  size_t element_len,
120  int doclear,
121  int isvarlen,
122  size_t dimensions,
123  ...
124  )
125 {
126  va_list ap;
127  int res;
128 
129  va_start( ap, dimensions );
130  res = hRedim( array, element_len, doclear, isvarlen, dimensions, ap );
131  va_end( ap );
132 
133  return res;
134 }
135 
137  (
138  FBARRAY *array,
139  size_t element_len,
140  int isvarlen,
141  size_t dimensions,
142  ...
143  )
144 {
145  va_list ap;
146  int res;
147 
148  va_start( ap, dimensions );
149  res = hRedim( array, element_len, TRUE, isvarlen, dimensions, ap );
150  va_end( ap );
151 
152  return res;
153 }