]>
Commit | Line | Data |
---|---|---|
67bc59df SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Handles a buffer that can be allocated and freed | |
4 | * | |
5 | * Copyright 2021 Google LLC | |
6 | * Written by Simon Glass <[email protected]> | |
7 | */ | |
8 | ||
90ad4e28 | 9 | #ifndef USE_HOSTCC |
67bc59df SG |
10 | #include <malloc.h> |
11 | #include <mapmem.h> | |
12 | #include <string.h> | |
90ad4e28 SG |
13 | #endif |
14 | ||
15 | #include <abuf.h> | |
67bc59df SG |
16 | |
17 | void abuf_set(struct abuf *abuf, void *data, size_t size) | |
18 | { | |
19 | abuf_uninit(abuf); | |
20 | abuf->data = data; | |
21 | abuf->size = size; | |
22 | } | |
23 | ||
90ad4e28 | 24 | #ifndef USE_HOSTCC |
67bc59df SG |
25 | void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) |
26 | { | |
27 | abuf_set(abuf, map_sysmem(addr, size), size); | |
28 | } | |
90ad4e28 SG |
29 | #else |
30 | /* copied from lib/string.c for convenience */ | |
31 | static char *memdup(const void *src, size_t len) | |
32 | { | |
33 | char *p; | |
34 | ||
35 | p = malloc(len); | |
36 | if (!p) | |
37 | return NULL; | |
38 | ||
39 | memcpy(p, src, len); | |
40 | ||
41 | return p; | |
42 | } | |
43 | #endif | |
67bc59df SG |
44 | |
45 | bool abuf_realloc(struct abuf *abuf, size_t new_size) | |
46 | { | |
47 | void *ptr; | |
48 | ||
49 | if (!new_size) { | |
50 | /* easy case, just need to uninit, freeing any allocation */ | |
51 | abuf_uninit(abuf); | |
52 | return true; | |
53 | } else if (abuf->alloced) { | |
54 | /* currently allocated, so need to reallocate */ | |
55 | ptr = realloc(abuf->data, new_size); | |
56 | if (!ptr) | |
57 | return false; | |
58 | abuf->data = ptr; | |
59 | abuf->size = new_size; | |
60 | return true; | |
61 | } else if (new_size <= abuf->size) { | |
62 | /* | |
63 | * not currently alloced and new size is no larger. Just update | |
64 | * it. Data is lost off the end if new_size < abuf->size | |
65 | */ | |
66 | abuf->size = new_size; | |
67 | return true; | |
68 | } else { | |
69 | /* not currently allocated and new size is larger. Alloc and | |
70 | * copy in data. The new space is not inited. | |
71 | */ | |
99aca9ef | 72 | ptr = malloc(new_size); |
67bc59df SG |
73 | if (!ptr) |
74 | return false; | |
99aca9ef SG |
75 | if (abuf->size) |
76 | memcpy(ptr, abuf->data, abuf->size); | |
67bc59df SG |
77 | abuf->data = ptr; |
78 | abuf->size = new_size; | |
79 | abuf->alloced = true; | |
80 | return true; | |
81 | } | |
82 | } | |
83 | ||
34ecba1f SG |
84 | bool abuf_realloc_inc(struct abuf *abuf, size_t inc) |
85 | { | |
86 | return abuf_realloc(abuf, abuf->size + inc); | |
87 | } | |
88 | ||
67bc59df SG |
89 | void *abuf_uninit_move(struct abuf *abuf, size_t *sizep) |
90 | { | |
91 | void *ptr; | |
92 | ||
93 | if (sizep) | |
94 | *sizep = abuf->size; | |
95 | if (!abuf->size) | |
96 | return NULL; | |
97 | if (abuf->alloced) { | |
98 | ptr = abuf->data; | |
99 | } else { | |
100 | ptr = memdup(abuf->data, abuf->size); | |
101 | if (!ptr) | |
102 | return NULL; | |
103 | } | |
104 | /* Clear everything out so there is no record of the data */ | |
105 | abuf_init(abuf); | |
106 | ||
107 | return ptr; | |
108 | } | |
109 | ||
110 | void abuf_init_set(struct abuf *abuf, void *data, size_t size) | |
111 | { | |
112 | abuf_init(abuf); | |
113 | abuf_set(abuf, data, size); | |
114 | } | |
115 | ||
116 | void abuf_init_move(struct abuf *abuf, void *data, size_t size) | |
117 | { | |
118 | abuf_init_set(abuf, data, size); | |
119 | abuf->alloced = true; | |
120 | } | |
121 | ||
122 | void abuf_uninit(struct abuf *abuf) | |
123 | { | |
124 | if (abuf->alloced) | |
125 | free(abuf->data); | |
126 | abuf_init(abuf); | |
127 | } | |
128 | ||
129 | void abuf_init(struct abuf *abuf) | |
130 | { | |
131 | abuf->data = NULL; | |
132 | abuf->size = 0; | |
133 | abuf->alloced = false; | |
134 | } |