1 /*
2  ****************************************************************************
3  *
4  * MODULE:       Vector library
5  *
6  * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
7  *               Update to GRASS 5.7 Radim Blazek.
8  *
9  * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
10  *
11  * COPYRIGHT:    (C) 2001 by the GRASS Development Team
12  *
13  *               This program is free software under the GNU General Public
14  *              License (>=v2). Read the file COPYING that comes with GRASS
15  *              for details.
16  *
17  *****************************************************************************/
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <grass/vector.h>
21 
22 /*  functions - alloc_space(), falloc(), frealloc() _falloc() _frealloc() */
23 
24 
25 /*   alloc_space ()    allocates space if needed.
26  *    All allocated space is created by calloc (2).
27  *
28  *   args: number of elements wanted, pointer to number of currently allocated
29  *   elements, size of chunks to allocate,  pointer to current array, sizeof
30  *   an element.
31  */
32 
dig_alloc_space(int n_wanted,int * n_elements,int chunk_size,void * ptr,int element_size)33 void *dig_alloc_space(int n_wanted,
34 		      int *n_elements,
35 		      int chunk_size, void *ptr, int element_size)
36 {
37     char *p;
38 
39     p = dig__alloc_space(n_wanted, n_elements, chunk_size, ptr, element_size);
40 
41     if (p == NULL) {
42 	fprintf(stderr, "\nERROR: out of memory.  memory asked for: %d\n",
43 		n_wanted);
44 	exit(EXIT_FAILURE);
45     }
46 
47     return (p);
48 }
49 
dig__alloc_space(int n_wanted,int * n_elements,int chunk_size,void * ptr,int element_size)50 void *dig__alloc_space(int n_wanted, int *n_elements, int chunk_size, void *ptr,	/* changed char -> void instead of casting.  WBH 8/16/1998  */
51 		       int element_size)
52 {
53     int to_alloc;
54 
55     to_alloc = *n_elements;
56 
57     /*  do we need to allocate more space  */
58     if (n_wanted < to_alloc)
59 	return (ptr);
60 
61     /*  calculate the number needed by chunk size */
62     /*  ORIGINAL
63        while (n_wanted >= to_alloc)
64        to_alloc += chunk_size;
65      */
66     /*
67      **  This was changed as a test on Aug 21, 1990
68      **  Build.vect was taking outrageous amounts of
69      **  memory to run, so instead of blaming my
70      **  code, I decided that it could be the realloc/malloc
71      **  stuff not making efficient use of the space.
72      **  So the fix is to instead of asking for many small
73      **  increments, ask for twice as much space as we are currently
74      **  using, each time we need more space.
75      */
76     while (n_wanted >= to_alloc)
77 	to_alloc += *n_elements ? *n_elements : chunk_size;
78 
79     /*  first time called allocate initial storage  */
80     if (*n_elements == 0)
81 	ptr = G_calloc(to_alloc, element_size);
82     else
83 	ptr = dig__frealloc((char *)ptr, to_alloc, element_size, *n_elements);
84 
85     *n_elements = to_alloc;
86 
87     return (ptr);
88 }
89 
90 
dig_falloc(int nelem,int elsize)91 void *dig_falloc(int nelem, int elsize)
92 {
93     void *ret;
94 
95     if ((ret = dig__falloc(nelem, elsize)) == NULL) {
96 	fprintf(stderr, "Out of Memory.\n");
97 	G_sleep(2);
98 	exit(EXIT_FAILURE);
99     }
100     return (ret);
101 }
102 
dig_frealloc(void * oldptr,int nelem,int elsize,int oldnelem)103 void *dig_frealloc(void *oldptr, int nelem, int elsize, int oldnelem)
104 {
105     char *ret;
106 
107     if ((ret = dig__frealloc(oldptr, nelem, elsize, oldnelem)) == NULL) {
108 	fprintf(stderr, "\nOut of Memory on realloc.\n");
109 	G_sleep(2);
110 	exit(EXIT_FAILURE);
111     }
112     return (ret);
113 }
114 
115 /*  these functions don't exit on "no more memory",  calling function should
116    check the return value  */
117 
dig__falloc(int nelem,int elsize)118 void *dig__falloc(int nelem, int elsize)
119 {
120     char *ptr;
121 
122     if (elsize == 0) {
123 	elsize = 4;
124     }
125     if (nelem == 0) {
126 	nelem = 1;
127     }
128 
129     ptr = G_calloc(nelem, elsize);
130     return (ptr);
131 }
132 
dig__frealloc(void * oldptr,int nelem,int elsize,int oldnelem)133 void *dig__frealloc(void *oldptr, int nelem, int elsize, int oldnelem)
134 {
135     char *ptr;
136 
137     if (elsize == 0) {
138 	elsize = 4;
139     }
140     if (nelem == 0) {
141 	nelem = 1;
142     }
143 
144     ptr = G_calloc(nelem, elsize);
145 
146     /*  out of memory  */
147     if (!ptr)
148 	return (ptr);
149 
150     {
151 	register char *a;
152 	register char *b;
153 	register size_t n;
154 
155 	n = oldnelem * elsize;
156 	a = ptr;
157 	b = oldptr;
158 	while (n--)
159 	    *a++ = *b++;
160     }
161 
162     G_free(oldptr);
163     return (ptr);
164 }
165