tmemory.c - ltk - Socket-based GUI for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tmemory.c (4742B)
---
1 /*
2 * Copyright (c) 2021, 2022 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_strdup_debug(const char *s, const char *caller, const char *file, int line) {
35 char *str = strdup(s);
36 fprintf(stderr, "DEBUG: strdup %p to %p in %s (%s:%d)\n",
37 (void *)s, (void *)str, caller, file, line);
38 if (!str)
39 ltk_fatal("Out of memory.\n");
40 return str;
41 }
42
43 char *
44 ltk_strndup_impl(const char *s, size_t n) {
45 char *str = strndup(s, n);
46 if (!str)
47 ltk_fatal("Out of memory.\n");
48 return str;
49 }
50
51 char *
52 ltk_strndup_debug(const char *s, size_t n, const char *caller, const char *file, int line) {
53 char *str = strndup(s, n);
54 fprintf(stderr, "DEBUG: strndup %p to %p in %s (%s:%d)\n",
55 (void *)s, (void *)str, caller, file, line);
56 if (!str)
57 ltk_fatal("Out of memory.\n");
58 return str;
59 }
60
61 void *
62 ltk_malloc_impl(size_t size) {
63 void *ptr = malloc(size);
64 if (!ptr)
65 ltk_fatal("Out of memory.\n");
66 return ptr;
67 }
68
69 void *
70 ltk_malloc_debug(size_t size, const char *caller, const char *file, int line) {
71 void *ptr = malloc(size);
72 fprintf(stderr, "DEBUG: malloc %p, %zu bytes in %s (%s:%d)\n",
73 ptr, size, caller, file, line);
74 if (!ptr)
75 ltk_fatal("Out of memory.\n");
76 return ptr;
77 }
78
79 void *
80 ltk_calloc_impl(size_t nmemb, size_t size) {
81 void *ptr = calloc(nmemb, size);
82 if (!ptr)
83 ltk_fatal("Out of memory.\n");
84 return ptr;
85 }
86
87 void *
88 ltk_calloc_debug(size_t nmemb, size_t size, const char *caller, const char *file, int line) {
89 void *ptr = calloc(nmemb, size);
90 fprintf(stderr, "DEBUG: calloc %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_realloc_impl(void *ptr, size_t size) {
99 void *new_ptr = realloc(ptr, size);
100 if (!new_ptr)
101 ltk_fatal("Out of memory.\n");
102 return new_ptr;
103 }
104
105 void *
106 ltk_realloc_debug(void *ptr, size_t size, const char *caller, const char *file, int line) {
107 void *new_ptr = realloc(ptr, size);
108 fprintf(stderr, "DEBUG: realloc %p to %p, %zu bytes in %s (%s:%d)\n",
109 ptr, new_ptr, size, caller, file, line);
110 if (!new_ptr)
111 ltk_fatal("Out of memory.\n");
112 return new_ptr;
113 }
114
115 void
116 ltk_free_debug(void *ptr, const char *caller, const char *file, int line) {
117 fprintf(stderr, "DEBUG: free %p in %s (%s:%d)\n", ptr, caller, file, line);
118 free(ptr);
119 }
120
121 /*
122 * This (reallocarray) is from OpenBSD (adapted to exit on error):
123 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
124 */
125
126 /*
127 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
128 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
129 */
130 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
131
132 void *
133 ltk_reallocarray(void *optr, size_t nmemb, size_t size)
134 {
135 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
136 nmemb > 0 && SIZE_MAX / nmemb < size) {
137 ltk_fatal("Integer overflow in allocation.\n");
138 }
139 return ltk_realloc(optr, size * nmemb);
140 }
141
142 /* FIXME: maybe don't double when already very large? */
143 /* FIXME: better start size when old == 0? */
144 size_t
145 ideal_array_size(size_t old, size_t needed) {
146 size_t ret = old;
147 /* FIXME: the shrinking here only makes sense if not
148 many elements are removed at once - what would be
149 more sensible here? */
150 /* FIXME: overflow */
151 if (old < needed)
152 ret = old * 2 > needed ? old * 2 : needed;
153 else if (needed * 4 < old)
154 ret = old / 2;
155 if (ret == 0)
156 ret = 1; /* not sure if this is necessary */
157 return ret;
158 }
159
160 char *
161 ltk_print_fmt(char *fmt, ...) {
162 va_list args;
163 va_start(args, fmt);
164 int len = vsnprintf(NULL, 0, fmt, args);
165 /* FIXME: what should be done on error? */
166 if (len < 0)
167 ltk_fatal("Error in vsnprintf called from print_fmt");
168 /* FIXME: overflow */
169 char *str = ltk_malloc(len + 1);
170 va_end(args);
171 va_start(args, fmt);
172 vsnprintf(str, len + 1, fmt, args);
173 va_end(args);
174 return str;
175 }