memory.c - ltk - GUI toolkit for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
memory.c (4768B)
---
1 /*
2 * Copyright (c) 2021-2024 lumidify <nobody@lumidify.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <stdint.h>
22 #include "util.h"
23 #include "memory.h"
24
25 char *
26 ltk_strdup_impl(const char *s) {
27 char *str = strdup(s);
28 if (!str)
29 ltk_fatal("Out of memory.\n");
30 return str;
31 }
32
33 char *
34 ltk_strndup_impl(const char *s, size_t n) {
35 char *str = strndup(s, n);
36 if (!str)
37 ltk_fatal("Out of memory.\n");
38 return str;
39 }
40
41 void *
42 ltk_malloc_impl(size_t size) {
43 void *ptr = malloc(size);
44 if (!ptr)
45 ltk_fatal("Out of memory.\n");
46 return ptr;
47 }
48
49 void *
50 ltk_calloc_impl(size_t nmemb, size_t size) {
51 void *ptr = calloc(nmemb, size);
52 if (!ptr)
53 ltk_fatal("Out of memory.\n");
54 return ptr;
55 }
56
57 void *
58 ltk_realloc_impl(void *ptr, size_t size) {
59 void *new_ptr = realloc(ptr, size);
60 if (!new_ptr)
61 ltk_fatal("Out of memory.\n");
62 return new_ptr;
63 }
64
65 #if MEMDEBUG == 1
66
67 char *
68 ltk_strdup_debug(const char *s, const char *caller, const char *file, int line) {
69 char *str = strdup(s);
70 fprintf(stderr, "DEBUG: strdup %p to %p in %s (%s:%d)\n",
71 (void *)s, (void *)str, caller, file, line);
72 if (!str)
73 ltk_fatal("Out of memory.\n");
74 return str;
75 }
76
77 char *
78 ltk_strndup_debug(const char *s, size_t n, const char *caller, const char *file, int line) {
79 char *str = strndup(s, n);
80 fprintf(stderr, "DEBUG: strndup %p to %p in %s (%s:%d)\n",
81 (void *)s, (void *)str, caller, file, line);
82 if (!str)
83 ltk_fatal("Out of memory.\n");
84 return str;
85 }
86
87 void *
88 ltk_malloc_debug(size_t size, const char *caller, const char *file, int line) {
89 void *ptr = malloc(size);
90 fprintf(stderr, "DEBUG: malloc %p, %zu bytes in %s (%s:%d)\n",
91 ptr, size, caller, file, line);
92 if (!ptr)
93 ltk_fatal("Out of memory.\n");
94 return ptr;
95 }
96
97 void *
98 ltk_calloc_debug(size_t nmemb, size_t size, const char *caller, const char *file, int line) {
99 void *ptr = calloc(nmemb, size);
100 fprintf(stderr, "DEBUG: calloc %p, %zu bytes in %s (%s:%d)\n",
101 ptr, size, caller, file, line);
102 if (!ptr)
103 ltk_fatal("Out of memory.\n");
104 return ptr;
105 }
106
107 void *
108 ltk_realloc_debug(void *ptr, size_t size, const char *caller, const char *file, int line) {
109 void *new_ptr = realloc(ptr, size);
110 fprintf(stderr, "DEBUG: realloc %p to %p, %zu bytes in %s (%s:%d)\n",
111 ptr, new_ptr, size, caller, file, line);
112 if (!new_ptr)
113 ltk_fatal("Out of memory.\n");
114 return new_ptr;
115 }
116
117 void
118 ltk_free_debug(void *ptr, const char *caller, const char *file, int line) {
119 fprintf(stderr, "DEBUG: free %p in %s (%s:%d)\n", ptr, caller, file, line);
120 free(ptr);
121 }
122
123 #endif
124
125 /*
126 * This (reallocarray) is from OpenBSD (adapted to exit on error):
127 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
128 */
129
130 /*
131 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
132 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
133 */
134 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
135
136 void *
137 ltk_reallocarray(void *optr, size_t nmemb, size_t size)
138 {
139 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
140 nmemb > 0 && SIZE_MAX / nmemb < size) {
141 ltk_fatal("Integer overflow in allocation.\n");
142 }
143 return ltk_realloc(optr, size * nmemb);
144 }
145
146 /* FIXME: maybe don't double when already very large? */
147 /* FIXME: better start size when old == 0? */
148 size_t
149 ideal_array_size(size_t old, size_t needed) {
150 size_t ret = old;
151 /* FIXME: the shrinking here only makes sense if not
152 many elements are removed at once - what would be
153 more sensible here? */
154 /* FIXME: overflow */
155 if (old < needed)
156 ret = old * 2 > needed ? old * 2 : needed;
157 else if (needed * 4 < old)
158 ret = old / 2;
159 if (ret == 0)
160 ret = 1; /* not sure if this is necessary */
161 return ret;
162 }
163
164 char *
165 ltk_print_fmt(char *fmt, ...) {
166 va_list args;
167 va_start(args, fmt);
168 int len = vsnprintf(NULL, 0, fmt, args);
169 /* FIXME: what should be done on error? */
170 if (len < 0)
171 ltk_fatal("Error in vsnprintf called from print_fmt");
172 /* FIXME: overflow */
173 char *str = ltk_malloc(len + 1);
174 va_end(args);
175 va_start(args, fmt);
176 vsnprintf(str, len + 1, fmt, args);
177 va_end(args);
178 return str;
179 }