chiark / gitweb /
tree-wide: drop 'This file is part of systemd' blurb
[elogind.git] / src / basic / alloc-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   Copyright 2010 Lennart Poettering
4 ***/
5
6 #include <stdint.h>
7 #include <string.h>
8
9 #include "alloc-util.h"
10 #include "macro.h"
11 #include "util.h"
12
13 void* memdup(const void *p, size_t l) {
14         void *ret;
15
16         assert(l == 0 || p);
17
18         ret = malloc(l);
19         if (!ret)
20                 return NULL;
21
22         memcpy(ret, p, l);
23         return ret;
24 }
25
26 void* memdup_suffix0(const void *p, size_t l) {
27         void *ret;
28
29         assert(l == 0 || p);
30
31         /* The same as memdup() but place a safety NUL byte after the allocated memory */
32
33         ret = malloc(l + 1);
34         if (!ret)
35                 return NULL;
36
37         *((uint8_t*) mempcpy(ret, p, l)) = 0;
38         return ret;
39 }
40
41 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
42         size_t a, newalloc;
43         void *q;
44
45         assert(p);
46         assert(allocated);
47
48         if (*allocated >= need)
49                 return *p;
50
51         newalloc = MAX(need * 2, 64u / size);
52         a = newalloc * size;
53
54         /* check for overflows */
55         if (a < size * need)
56                 return NULL;
57
58         q = realloc(*p, a);
59         if (!q)
60                 return NULL;
61
62         *p = q;
63         *allocated = newalloc;
64         return q;
65 }
66
67 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
68         size_t prev;
69         uint8_t *q;
70
71         assert(p);
72         assert(allocated);
73
74         prev = *allocated;
75
76         q = greedy_realloc(p, allocated, need, size);
77         if (!q)
78                 return NULL;
79
80         if (*allocated > prev)
81                 memzero(q + prev * size, (*allocated - prev) * size);
82
83         return q;
84 }