CUBRID Engine  latest
adjustable_array.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * adjustable_array.c - adjustable array functions
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stddef.h>
33 #include <assert.h>
34 
35 #include "porting.h"
36 #include "adjustable_array.h"
37 
38 /*
39  * adj_ar_concat_strings() - concatenate the specified strings
40  * return: concatenated string
41  * string1(in): the first string to be concatednated
42  * string2(in): the second string to be concatednated
43  *
44  * Note: The returned pointer must not be freed, and its contents must not be
45  * accessed after the next call to this function.
46  */
47 const char *
48 adj_ar_concat_strings (const char *string1, const char *string2, ...)
49 {
50  va_list next_arg;
51  const char *next_string;
52  static ADJ_ARRAY *string_buffer = NULL;
53 
54  if (string_buffer == NULL)
55  {
56  string_buffer = adj_ar_new (1, 0, 2.0);
57  }
58 
59  (void) adj_ar_reset (string_buffer, 1, 64, 2.0);
60 
61  if (!string1)
62  {
63  string1 = "?";
64  }
65  (void) adj_ar_append (string_buffer, string1, (int) strlen (string1));
66  if (!string2)
67  {
68  string2 = "?";
69  }
70  (void) adj_ar_append (string_buffer, string2, (int) strlen (string2));
71 
72  va_start (next_arg, string2);
73  while ((next_string = va_arg (next_arg, const char *)))
74  {
75  (void) adj_ar_append (string_buffer, next_string, (int) strlen (next_string));
76  }
77 
78  (void) adj_ar_append (string_buffer, "\0", 1);
79 
80  va_end (next_arg);
81 
82  return (const char *) adj_ar_get_buffer (string_buffer);
83 }
84 
85 /*
86  * adj_ar_new() - allocate a new ADJ_ARRAY structure.
87  * return: ADJ_ARRAY pointer if suucess,
88  * NULL otherwise.
89  * element_size(in): size of array element
90  * min(in) : minimum elements in array
91  * growth_rate(in) : growth rate of array
92  *
93  */
94 ADJ_ARRAY *
95 adj_ar_new (int element_size, int min, float growth_rate)
96 {
98 
99  adj_array = (ADJ_ARRAY *) malloc (sizeof (ADJ_ARRAY));
100  if (adj_array)
101  {
102  adj_array->buffer = NULL;
103  adj_array->max_length = 0;
104  adj_array->element_size = element_size;
105  if (adj_ar_reset (adj_array, element_size, min, growth_rate) != ADJ_NOERROR)
106  {
107  free (adj_array);
108  adj_array = NULL;
109  }
110  }
111  return adj_array;
112 }
113 
114 /*
115  * ard_ar_free() - deallocate the memory block previously
116  * allocated by adj_ar_new().
117  * return: nothing
118  * adj_array_p(in/out): the ADJ_ARRAY pointer
119  *
120  */
121 void
122 adj_ar_free (ADJ_ARRAY * adj_array_p)
123 {
124  if (adj_array_p)
125  {
126  if (adj_array_p->buffer)
127  {
128  free (adj_array_p->buffer);
129  }
130  free (adj_array_p);
131  }
132 }
133 
134 /*
135  * adj_ar_reset() - reset ADJ_ARRAY with the given values.
136  * return: ADJ_ERR_CODE
137  * adj_array_p(in/out) : the ADJ_ARRAY pointer
138  * element_size(in) : size of array element
139  * min(in) : minimum elements in array
140  * growth_rate(in) : growth rate of array
141  */
142 int
143 adj_ar_reset (ADJ_ARRAY * adj_array_p, int element_size, int min, float growth_rate)
144 {
145  assert (adj_array_p != NULL);
146 
147  if (element_size < 1)
148  {
149  return ADJ_ERR_BAD_ELEMENT;
150  }
151  if (min < 0)
152  {
153  return ADJ_ERR_BAD_MIN;
154  }
155  if (growth_rate < 1.0)
156  {
157  return ADJ_ERR_BAD_RATE;
158  }
159 
160  adj_array_p->max_length *= adj_array_p->element_size / element_size;
161  adj_array_p->cur_length = 0;
162  adj_array_p->element_size = element_size;
163  adj_array_p->min_length = min;
164  adj_array_p->rate = growth_rate;
165 
166  return ADJ_NOERROR;
167 }
168 
169 /*
170  * adj_ar_initialize() - initialize ADJ_ARRAY buffer with the given data.
171  * return: ADJ_ERR_CODE
172  * adj_array_p(in/out) : the ADJ_ARRAY pointer
173  * initial(in) : the initial buffer contents
174  * initial_length(in) : number of elements contained in 'initial' buffer
175  */
176 int
177 adj_ar_initialize (ADJ_ARRAY * adj_array_p, const void *initial, int initial_length)
178 {
179  assert (adj_array_p != NULL);
180 
181  if (adj_array_p->cur_length > 0)
182  {
183  return ADJ_ERR_BAD_INIT;
184  }
185  if (initial_length < 0)
186  {
187  return ADJ_ERR_BAD_LENGTH;
188  }
189 
190  if (initial_length == 0)
191  {
192  initial_length = adj_array_p->min_length;
193  }
194 
195  /* Reset array size to initial_length. */
196  adj_ar_remove (adj_array_p, 0, ADJ_AR_EOA);
197  adj_ar_append (adj_array_p, NULL, initial_length);
198 
199  /* Copy initial value into array elements. */
200  if (initial != NULL)
201  {
202  if (adj_array_p->element_size == 1)
203  {
204  memset ((char *) adj_array_p->buffer, *((unsigned char *) initial), initial_length);
205  }
206  else
207  {
208  void *p;
209  for (p = adj_array_p->buffer; initial_length-- > 0; p = (void *) ((char *) p + adj_array_p->element_size))
210  {
211  memmove (p, initial, adj_array_p->element_size);
212  /* TODO ?? initial = (char*) initial + adj_array_p->element_size */
213  }
214  }
215  }
216 
217  return ADJ_NOERROR;
218 }
219 
220 /*
221  * adj_ar_replace() - replace the ADJ_ARRAY buffer with the given data
222  * to the specified range
223  * return: ADJ_ERR_CODE
224  * adj_array_p(in/out): the ADJ_ARRAY pointer
225  * src (in): source buffer
226  * src_length (in) : number of elements in src buffer
227  * start (in): start position in the array buffer to be replaced, inclusive
228  * end (in): end position in the array buffer to be replaced, exclusive
229  */
230 int
231 adj_ar_replace (ADJ_ARRAY * adj_array_p, const void *src, int src_length, int start, int end)
232 {
233  int new_length;
234 
235  assert (adj_array_p != NULL);
236 
237  /* Expand ADJ_AR_EOA. */
238  if (end == ADJ_AR_EOA)
239  {
240  end = adj_array_p->cur_length;
241  }
242  if (start == ADJ_AR_EOA)
243  {
244  start = adj_array_p->cur_length;
245  }
246 
247  /* Check for errors. */
248  if (start < 0)
249  {
250  return ADJ_ERR_BAD_START;
251  }
252  else if (start > adj_array_p->cur_length)
253  {
254  return ADJ_ERR_BAD_START;
255  }
256  else if (end < start)
257  {
258  return ADJ_ERR_BAD_END;
259  }
260  else if (end > adj_array_p->cur_length)
261  {
262  return ADJ_ERR_BAD_END;
263  }
264  else if (src_length < 0)
265  {
266  return ADJ_ERR_BAD_NFROM;
267  }
268 
269  new_length = adj_array_p->cur_length + src_length - (end - start);
270  if (new_length > adj_array_p->max_length)
271  {
272  /* allocate larger buffer. */
273  void *new_buffer;
274  int new_max = MAX (adj_array_p->min_length,
275  MAX ((int) (adj_array_p->max_length * adj_array_p->rate),
276  new_length));
277 
278  if (adj_array_p->buffer)
279  {
280  new_buffer = realloc (adj_array_p->buffer, new_max * adj_array_p->element_size);
281  }
282  else
283  {
284  new_buffer = malloc (new_max * adj_array_p->element_size);
285  }
286 
287  if (!new_buffer)
288  {
289  return ADJ_ERR_BAD_ALLOC;
290  }
291  adj_array_p->buffer = new_buffer;
292  adj_array_p->max_length = new_max;
293  }
294 
295  /* Shift elements following replaced subarray. */
296  memmove ((void *) ((char *) adj_array_p->buffer + (start + src_length) * adj_array_p->element_size),
297  (void *) ((char *) adj_array_p->buffer + end * adj_array_p->element_size),
298  (adj_array_p->cur_length - end) * adj_array_p->element_size);
299 
300  if (src)
301  {
302  memmove ((void *) ((char *) adj_array_p->buffer + start * adj_array_p->element_size), src,
303  src_length * adj_array_p->element_size);
304  }
305  adj_array_p->cur_length = new_length;
306 
307  return ADJ_NOERROR;
308 }
309 
310 /*
311  * adj_ar_remove() - remove data of the given buffer range
312  * return: ADJ_ERR_CODE
313  * adj_array_p(in/out): the ADJ_ARRAY pointer
314  * start (in) : start position in the array buffer to be removed, inclusive
315  * end (in) : end position in the array buffer to be removed, exclusive
316  */
317 int
318 adj_ar_remove (ADJ_ARRAY * adj_array_p, int start, int end)
319 {
320  assert (adj_array_p != NULL);
321 
322  return adj_ar_replace (adj_array_p, NULL, 0, start, end);
323 }
324 
325 /*
326  * adj_ar_insert() - insert data at the specified buffer position
327  * return: ADJ_ERR_CODE
328  * adj_array_p(in/out): the ADJ_ARRAY pointer
329  * src (in) : source buffer to be inserted
330  * src_length (in) : number of elements in 'src' buffer
331  * start (in) : start position in the 'adj_array_p'
332  */
333 int
334 adj_ar_insert (ADJ_ARRAY * adj_array_p, const void *src, int src_length, int start)
335 {
336  assert (adj_array_p != NULL);
337 
338  return adj_ar_replace (adj_array_p, src, src_length, start, start);
339 }
340 
341 /*
342  * adj_ar_append() - append data at end of ADJ_ARRAY buffer
343  * return: ADJ_ERR_CODE
344  * adj_array_p(in/out): the ADJ_ARRAY pointer
345  * src (in) : source buffer to be appended
346  * src_length (in) : number of elements in 'src' buffer
347  */
348 int
349 adj_ar_append (ADJ_ARRAY * adj_array_p, const void *src, int src_length)
350 {
351  assert (adj_array_p != NULL);
352 
353  return adj_ar_replace (adj_array_p, src, src_length, ADJ_AR_EOA, ADJ_AR_EOA);
354 }
355 
356 /*
357  * adj_ar_get_buffer() - return the buffer pointer of ADJ_ARRAY
358  * return: buffer pointer of ADJ_ARRAY
359  * adj_array_p(in): the ADJ_ARRAY pointer
360  */
361 void *
362 adj_ar_get_buffer (const ADJ_ARRAY * adj_array_p)
363 {
364  assert (adj_array_p != NULL);
365 
366  return adj_array_p->buffer;
367 }
368 
369 /*
370  * adj_ar_length() - return the current length of ADJ_ARRAY buffer
371  * return: current length of ADJ_ARRAY buffer
372  * adj_array_p(in): the ADJ_ARRAY pointer
373  */
374 int
375 adj_ar_length (const ADJ_ARRAY * adj_array_p)
376 {
377  assert (adj_array_p != NULL);
378 
379  return adj_array_p->cur_length;
380 }
381 
382 #if defined (ENABLE_UNUSED_FUNCTION)
383 /*
384  * adj_ar_get_nth_buffer() - return the nth buffer pointer of ADJ_ARRAY
385  * return: NULL if the specified n is out of buffer range,
386  * nth buffer pointer otherwise
387  * adj_array_p(in): the ADJ_ARRAY pointer
388  * n (in) : buffer position
389  */
390 void *
391 adj_ar_get_nth_buffer (const ADJ_ARRAY * adj_array_p, int n)
392 {
393  assert (adj_array_p != NULL);
394 
395  if (n >= 0 && n < adj_array_p->cur_length)
396  {
397  return ((char *) adj_array_p->buffer + n * adj_array_p->element_size);
398  }
399 
400  return NULL;
401 }
402 #endif /* ENABLE_UNUSED_FUNCTION */
const char * adj_ar_concat_strings(const char *string1, const char *string2,...)
#define ADJ_AR_EOA
void * adj_ar_get_buffer(const ADJ_ARRAY *adj_array_p)
int adj_ar_length(const ADJ_ARRAY *adj_array_p)
#define assert(x)
#define min(a, b)
#define NULL
Definition: freelistheap.h:34
int adj_ar_replace(ADJ_ARRAY *adj_array_p, const void *src, int src_length, int start, int end)
int adj_ar_append(ADJ_ARRAY *adj_array_p, const void *src, int src_length)
int adj_ar_remove(ADJ_ARRAY *adj_array_p, int start, int end)
int adj_ar_reset(ADJ_ARRAY *adj_array_p, int element_size, int min, float growth_rate)
#define strlen(s1)
Definition: intl_support.c:43
int adj_ar_insert(ADJ_ARRAY *adj_array_p, const void *src, int src_length, int start)
ADJ_ARRAY * adj_ar_new(int element_size, int min, float growth_rate)
const char ** p
Definition: dynamic_load.c:945
int adj_ar_initialize(ADJ_ARRAY *adj_array_p, const void *initial, int initial_length)
void adj_ar_free(ADJ_ARRAY *adj_array_p)