ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | 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 }