1 /*!
2   \file lib/vector/diglib/struct_alloc.c
3 
4   \brief Vector library - allocate and zero array space (lower level functions)
5 
6   Lower level functions for reading/writing/manipulating vectors.
7 
8   These routines all eventually call calloc() to allocate and zero the
9   new space. BUT It is not necessarily safe to assume that the memory
10   will be zero. The next memory location asked for could have been
11   previously used and not zeroed. (e.g. compress()).
12 
13   This program is free software under the GNU General Public License
14   (>=v2). Read the file COPYING that comes with GRASS for details.
15 
16   \author CERL (probably Dave Gerdes)
17   \author Radim Blazek
18 */
19 
20 #include <stdlib.h>
21 #include <grass/vector.h>
22 #include <grass/glocale.h>
23 
24 /*!
25   \brief Allocate new node structure
26 
27   \return pointer to allocated P_node struct
28   \return NULL on error
29 */
dig_alloc_node()30 struct P_node *dig_alloc_node()
31 {
32     struct P_node *Node;
33 
34     Node = (struct P_node *) G_malloc(sizeof(struct P_node));
35     if (Node == NULL)
36         return NULL;
37 
38     G_zero(Node, sizeof(struct P_node));
39 
40     return Node;
41 }
42 
43 /*!
44   \brief Free node structure
45 
46   \param Node pointer to P_node struct to be freed
47 */
dig_free_node(struct P_node * Node)48 void dig_free_node(struct P_node *Node)
49 {
50     if (Node->alloc_lines > 0) {
51         G_free(Node->lines);
52         G_free(Node->angles);
53     }
54 
55     G_free(Node);
56 }
57 
58 /*!
59   \brief Allocate space in P_node struct
60 
61   Lines and angles arrays to add 'add' more lines
62 
63   \param node pointer to P_node struct
64   \param add number lines to be added
65 
66   \return 0 on success
67   \return -1 on error
68 */
dig_node_alloc_line(struct P_node * node,int add)69 int dig_node_alloc_line(struct P_node * node, int add)
70 {
71     int num;
72     char *p;
73 
74     G_debug(5, "dig_node_alloc_line(): add = %d", add);
75 
76     if (node->n_lines + add <= node->alloc_lines)
77 	return 0;
78 
79     num = node->alloc_lines + add;
80 
81     p = G_realloc(node->lines, num * sizeof(plus_t));
82     if (p == NULL)
83         return -1;
84     node->lines = (plus_t *) p;
85 
86     p = G_realloc(node->angles, num * sizeof(float));
87     if (p == NULL)
88         return -1;
89     node->angles = (float *)p;
90 
91     node->alloc_lines = num;
92 
93     return 0;
94 }
95 
96 /*!
97   \brief Reallocate array of pointers to nodes
98 
99   \param Plus pointer to Plus_head structure
100   \param add number of nodes to be added
101 
102   \return 0 on success
103   \return -1 on error
104 */
dig_alloc_nodes(struct Plus_head * Plus,int add)105 int dig_alloc_nodes(struct Plus_head *Plus, int add)
106 {
107     int size;
108     char *p;
109 
110     size = Plus->alloc_nodes + 1 + add;
111     p = G_realloc(Plus->Node, size * sizeof(struct P_node *));
112     if (p == NULL)
113         return -1;
114 
115     Plus->Node = (struct P_node **) p;
116     Plus->alloc_nodes = size - 1;
117 
118     return 0;
119 }
120 
121 /*!
122   \brief Allocate new line structure
123 
124   \return pointer to allocated P_node struct
125   \return NULL on error
126 */
dig_alloc_line()127 struct P_line *dig_alloc_line()
128 {
129     struct P_line *Line;
130 
131     Line = (struct P_line *) G_malloc(sizeof(struct P_line));
132     if (Line == NULL)
133         return NULL;
134 
135     G_zero(Line, sizeof(struct P_line));
136 
137     return Line;
138 }
139 
140 /*!
141   \brief Allocate new topo struct
142 
143   \param type to of struct to allocate
144 */
dig_alloc_topo(char type)145 void *dig_alloc_topo(char type)
146 {
147     void *Topo = NULL;
148 
149     switch (type) {
150         case GV_LINE:
151         Topo = G_malloc(sizeof(struct P_topo_l));
152         break;
153     case GV_BOUNDARY:
154         Topo = G_malloc(sizeof(struct P_topo_b));
155         break;
156     case GV_CENTROID:
157         Topo = G_malloc(sizeof(struct P_topo_c));
158         break;
159     case GV_FACE:
160         Topo = G_malloc(sizeof(struct P_topo_f));
161         break;
162     case GV_KERNEL:
163         Topo = G_malloc(sizeof(struct P_topo_k));
164         break;
165     default:
166         return NULL;
167     }
168 
169     return Topo;
170 }
171 
172 /*!
173   \brief Free line structure
174 
175   \param pointer to P_line struct to be freed
176 */
dig_free_line(struct P_line * Line)177 void dig_free_line(struct P_line *Line)
178 {
179     if (Line->topo)
180         G_free(Line->topo);
181     G_free(Line);
182 }
183 
184 /*!
185   \brief Reallocate array of pointers to lines.
186 
187   \param Plus pointer to Plus_head structure
188   \param add space for 'add' number of lines is added.
189 
190   \return 0 on success
191   \return -1 on error
192 */
dig_alloc_lines(struct Plus_head * Plus,int add)193 int dig_alloc_lines(struct Plus_head *Plus, int add)
194 {
195     int size;
196     char *p;
197 
198     size = Plus->alloc_lines + 1 + add;
199     p = G_realloc(Plus->Line, size * sizeof(struct P_line *));
200     if (p == NULL)
201         return -1;
202 
203     Plus->Line = (struct P_line **) p;
204     Plus->alloc_lines = size - 1;
205 
206     return 0;
207 }
208 
209 /*!
210   \brief Reallocate array of pointers to areas.
211 
212   \param Plus pointer to Plus_head structure
213   \param add space for 'add' number of areas is added
214 
215   \return 0 on success
216   \return -1 on error
217 */
dig_alloc_areas(struct Plus_head * Plus,int add)218 int dig_alloc_areas(struct Plus_head *Plus, int add)
219 {
220     int size;
221     char *p;
222 
223     size = Plus->alloc_areas + 1 + add;
224     p = G_realloc(Plus->Area, size * sizeof(struct P_area *));
225     if (p == NULL)
226         return -1;
227 
228     Plus->Area = (struct P_area **) p;
229     Plus->alloc_areas = size - 1;
230 
231     return 0;
232 }
233 
234 /*!
235   \brief Reallocate array of pointers to isles
236 
237   \param Plus pointer to Plus_head structure
238   \param add space for 'add' number of isles is added.
239 
240   \return 0 on success
241   \return -1 on error
242 */
dig_alloc_isles(struct Plus_head * Plus,int add)243 int dig_alloc_isles(struct Plus_head *Plus, int add)
244 {
245     int size;
246     char *p;
247 
248     G_debug(5, "dig_alloc_isle():");
249     size = Plus->alloc_isles + 1 + add;
250     p = G_realloc(Plus->Isle, size * sizeof(struct P_isle *));
251     if (p == NULL)
252         return -1;
253 
254     Plus->Isle = (struct P_isle **) p;
255     Plus->alloc_isles = size - 1;
256 
257     return 0;
258 }
259 
260 /*!
261   \brief Allocate new area structure
262 
263   \return pointer to allocated P_area struct
264   \return NULL on error
265 */
dig_alloc_area()266 struct P_area *dig_alloc_area()
267 {
268     struct P_area *Area;
269 
270     Area = (struct P_area *) G_malloc(sizeof(struct P_area));
271     if (Area == NULL)
272         return NULL;
273 
274     G_zero(Area, sizeof(struct P_area));
275 
276     return Area;
277 }
278 
279 /*!
280   \brief Free area structure
281 
282   \param Area pointer to P_area struct to be freed
283 */
dig_free_area(struct P_area * Area)284 void dig_free_area(struct P_area *Area)
285 {
286     if (Area->alloc_lines > 0)
287         free(Area->lines);
288 
289     if (Area->alloc_isles > 0)
290         free(Area->isles);
291 
292     G_free(Area);
293 }
294 
295 /*!
296   \brief Allocate new isle structure
297 
298   \return pointer to allocated P_isle struct
299   \return NULL on error
300 */
dig_alloc_isle()301 struct P_isle *dig_alloc_isle()
302 {
303     struct P_isle *Isle;
304 
305     Isle = (struct P_isle *) G_malloc(sizeof(struct P_isle));
306     if (Isle == NULL)
307         return NULL;
308 
309     G_zero(Isle, sizeof(struct P_isle));
310 
311     return Isle;
312 }
313 
314 /*!
315   \brief Free isle structure
316 
317   \param Isle pointer to P_isle struct to be freed
318 */
dig_free_isle(struct P_isle * Isle)319 void dig_free_isle(struct P_isle *Isle)
320 {
321     if (Isle->alloc_lines > 0)
322         G_free(Isle->lines);
323 
324     G_free(Isle);
325 }
326 
327 /*!
328   \brief allocate room for 'num' X and Y  arrays in struct line_pnts
329 
330   \param points pointer to line_pnts struct
331   \param num number of points
332 
333   \return 0 on success
334   \return returns -1 on out of memory
335 */
dig_alloc_points(struct line_pnts * points,int num)336 int dig_alloc_points(struct line_pnts *points, int num)
337 {
338     int alloced;
339     char *p;
340 
341     alloced = points->alloc_points;
342     /* alloc_space will just return if no space is needed */
343     if (!(p =
344           dig__alloc_space(num, &alloced, 50, (char *)points->x,
345                            sizeof(double)))) {
346         return (dig_out_of_memory());
347     }
348     points->x = (double *)p;
349 
350     alloced = points->alloc_points;
351     /* alloc_space will just return if no space is needed */
352     if (!(p =
353           dig__alloc_space(num, &alloced, 50, (char *)points->y,
354                            sizeof(double)))) {
355         return (dig_out_of_memory());
356     }
357     points->y = (double *)p;
358 
359     alloced = points->alloc_points;
360     /* alloc_space will just return if no space is needed */
361     if (!(p =
362           dig__alloc_space(num, &alloced, 50, (char *)points->z,
363                            sizeof(double)))) {
364         return (dig_out_of_memory());
365     }
366     points->z = (double *)p;
367 
368     points->alloc_points = alloced;
369 
370     return 0;
371 }
372 
373 /*!
374   \brief Allocate room for 'num' fields and category arrays
375   in struct line_cats
376 
377   \param cats pointer to line_cats struct
378   \param num number of cats
379 
380   \return 0 on success
381   \return returns -1 on out of memory
382 */
dig_alloc_cats(struct line_cats * cats,int num)383 int dig_alloc_cats(struct line_cats *cats, int num)
384 {
385     int alloced;
386     char *p;
387 
388     /* alloc_space will just return if no space is needed */
389     alloced = cats->alloc_cats;
390     if (!(p =
391           dig__alloc_space(num, &alloced, 1, (int *)cats->field,
392                            sizeof(int)))) {
393         return dig_out_of_memory();
394     }
395     cats->field = (int *)p;
396 
397     alloced = cats->alloc_cats;
398     if (!(p =
399           dig__alloc_space(num, &alloced, 1, (int *)cats->cat,
400                            sizeof(int)))) {
401         return dig_out_of_memory();
402     }
403     cats->cat = (int *)p;
404 
405     cats->alloc_cats = alloced;
406 
407     return 0;
408 }
409 
410 /*!
411   \brief allocate space in  P_area for add new lines
412 
413   \param area pointer to P_area struct
414   \param add number of lines to be added
415 
416   \return 0 on success
417   \return -1 on error
418  */
dig_area_alloc_line(struct P_area * area,int add)419 int dig_area_alloc_line(struct P_area * area, int add)
420 {
421     int num;
422     char *p;
423 
424     num = area->alloc_lines + add;
425 
426     p = G_realloc(area->lines, num * sizeof(plus_t));
427     if (p == NULL)
428         return -1;
429     area->lines = (plus_t *) p;
430 
431     area->alloc_lines = num;
432 
433     return (0);
434 }
435 
436 /*!
437   \brief Allocate space in  P_area for add new isles
438 
439   \param area pointer to P_area struct
440   \param add number of isle to be added
441 
442   \return 0 on success
443   \return -1 on error
444 */
dig_area_alloc_isle(struct P_area * area,int add)445 int dig_area_alloc_isle(struct P_area * area, int add)
446 {
447     int num;
448     char *p;
449 
450     G_debug(5, "dig_area_alloc_isle(): add = %d", add);
451     num = area->alloc_isles + add;
452 
453     p = G_realloc(area->isles, num * sizeof(plus_t));
454     if (p == NULL)
455         return -1;
456     area->isles = (plus_t *) p;
457 
458     area->alloc_isles = num;
459     return (0);
460 }
461 
462 /*!
463   \brief Allocate space in  P_isle for add new lines
464 
465   \param isle pointer to P_area struct
466   \param add number of isle to be added
467 
468   \return 0 on success
469   \return -1 on error
470 */
dig_isle_alloc_line(struct P_isle * isle,int add)471 int dig_isle_alloc_line(struct P_isle * isle, int add)
472 {
473     int num;
474     char *p;
475 
476     G_debug(5, "dig_isle_alloc_line():");
477     num = isle->alloc_lines + add;
478 
479     p = G_realloc(isle->lines, num * sizeof(plus_t));
480     if (p == NULL)
481         return -1;
482     isle->lines = (plus_t *) p;
483 
484     isle->alloc_lines = num;
485 
486     return (0);
487 }
488 
489 /*!
490   \brief For now just print message and return error code
491 */
dig_out_of_memory()492 int dig_out_of_memory()
493 {
494     G_warning(_("Out of memory"));
495     return -1;
496 }
497