URI: 
       tarray.h - 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
       ---
       tarray.h (7752B)
       ---
            1 /*
            2  * This file is part of the Lumidify ToolKit (LTK)
            3  * Copyright (c) 2020, 2023 lumidify <nobody@lumidify.org>
            4  *
            5  * Permission is hereby granted, free of charge, to any person obtaining a copy
            6  * of this software and associated documentation files (the "Software"), to deal
            7  * in the Software without restriction, including without limitation the rights
            8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
            9  * copies of the Software, and to permit persons to whom the Software is
           10  * furnished to do so, subject to the following conditions:
           11  *
           12  * The above copyright notice and this permission notice shall be included in all
           13  * copies or substantial portions of the Software.
           14  *
           15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
           18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
           19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
           21  * SOFTWARE.
           22  */
           23 
           24 #ifndef _LTK_ARRAY_H_
           25 #define _LTK_ARRAY_H_
           26 
           27 #include <stdio.h>
           28 #include <stdlib.h>
           29 
           30 #include "util.h"
           31 #include "memory.h"
           32 
           33 /* FIXME: make this work on more compilers? */
           34 #if (defined(__GNUC__) || defined(__clang__))
           35 #define LTK_UNUSED_FUNC __attribute__((unused))
           36 #else
           37 #define LTK_UNUSED_FUNC
           38 #endif
           39 
           40 #define LTK_ARRAY_INIT_DECL_BASE(name, type, storage)                                                                        \
           41 typedef struct {                                                                                                        \
           42         type *buf;                                                                                                        \
           43         size_t buf_size;                                                                                                \
           44         size_t len;                                                                                                        \
           45 } ltk_array_##name;                                                                                                        \
           46                                                                                                                         \
           47 LTK_UNUSED_FUNC storage ltk_array_##name *ltk_array_create_##name(size_t initial_len);                                        \
           48 LTK_UNUSED_FUNC storage type ltk_array_pop_##name(ltk_array_##name *ar);                                                \
           49 LTK_UNUSED_FUNC storage void ltk_array_prepare_gap_##name(ltk_array_##name *ar, size_t index, size_t len);                \
           50 LTK_UNUSED_FUNC storage void ltk_array_insert_##name(ltk_array_##name *ar, size_t index, type *elem, size_t len);        \
           51 LTK_UNUSED_FUNC storage void ltk_array_resize_##name(ltk_array_##name *ar, size_t size);                                \
           52 LTK_UNUSED_FUNC storage void ltk_array_destroy_##name(ltk_array_##name *ar);                                                \
           53 LTK_UNUSED_FUNC storage void ltk_array_clear_##name(ltk_array_##name *ar);                                                \
           54 LTK_UNUSED_FUNC storage void ltk_array_append_##name(ltk_array_##name *ar, type elem);                                        \
           55 LTK_UNUSED_FUNC storage void ltk_array_destroy_deep_##name(ltk_array_##name *ar, void (*destroy_func)(type));                \
           56 LTK_UNUSED_FUNC storage type ltk_array_get_safe_##name(ltk_array_##name *ar, size_t index);                                \
           57 LTK_UNUSED_FUNC storage void ltk_array_set_safe_##name(ltk_array_##name *ar, size_t index, type e);
           58 
           59 #define LTK_ARRAY_INIT_IMPL_BASE(name, type, storage)                                                        \
           60 LTK_UNUSED_FUNC storage ltk_array_##name *                                                                \
           61 ltk_array_create_##name(size_t initial_len) {                                                                \
           62         if (initial_len == 0)                                                                                \
           63                 ltk_fatal("Array length is zero\n");                                                        \
           64         ltk_array_##name *ar = ltk_malloc(sizeof(ltk_array_##name));                                        \
           65         ar->buf = ltk_reallocarray(NULL, initial_len, sizeof(type));                                        \
           66         ar->buf_size = initial_len;                                                                        \
           67         ar->len = 0;                                                                                        \
           68         return ar;                                                                                        \
           69 }                                                                                                        \
           70                                                                                                         \
           71 LTK_UNUSED_FUNC storage type                                                                                \
           72 ltk_array_pop_##name(ltk_array_##name *ar) {                                                                \
           73         if (ar->len == 0)                                                                                 \
           74                 ltk_fatal("Array empty; cannot pop.\n");                                                \
           75         ar->len--;                                                                                        \
           76         return ar->buf[ar->len];                                                                        \
           77 }                                                                                                        \
           78                                                                                                         \
           79 /* FIXME: having this function in the public interface is ugly */                                        \
           80 LTK_UNUSED_FUNC storage void                                                                                \
           81 ltk_array_prepare_gap_##name(ltk_array_##name *ar, size_t index, size_t len) {                                \
           82         if (index > ar->len)                                                                                 \
           83                 ltk_fatal("Array index out of bounds\n");                                                \
           84         ltk_array_resize_##name(ar, ar->len + len);                                                        \
           85         ar->len += len;                                                                                        \
           86         if (ar->len - len == index)                                                                        \
           87                 return;                                                                                        \
           88         memmove(ar->buf + index + len, ar->buf + index,                                                        \
           89             (ar->len - len - index) * sizeof(type));                                                        \
           90 }                                                                                                        \
           91                                                                                                         \
           92 LTK_UNUSED_FUNC storage void                                                                                \
           93 ltk_array_insert_##name(ltk_array_##name *ar, size_t index, type *elem, size_t len) {                        \
           94         ltk_array_prepare_gap_##name(ar, index, len);                                                        \
           95         for (size_t i = 0; i < len; i++) {                                                                \
           96                 ar->buf[index + i] = elem[i];                                                                \
           97         }                                                                                                \
           98 }                                                                                                        \
           99                                                                                                         \
          100 LTK_UNUSED_FUNC storage void                                                                                \
          101 ltk_array_append_##name(ltk_array_##name *ar, type elem) {                                                \
          102         if (ar->len == ar->buf_size)                                                                        \
          103                 ltk_array_resize_##name(ar, ar->len + 1);                                                \
          104         ar->buf[ar->len++] = elem;                                                                        \
          105 }                                                                                                        \
          106                                                                                                         \
          107 LTK_UNUSED_FUNC storage void                                                                                \
          108 ltk_array_clear_##name(ltk_array_##name *ar) {                                                                \
          109         ar->len = 0;                                                                                        \
          110         ltk_array_resize_##name(ar, 1);                                                                        \
          111 }                                                                                                        \
          112                                                                                                         \
          113 LTK_UNUSED_FUNC storage void                                                                                \
          114 ltk_array_resize_##name(ltk_array_##name *ar, size_t len) {                                                \
          115         size_t new_size = ideal_array_size(ar->buf_size, len);                                                \
          116         if (new_size != ar->buf_size) {                                                                        \
          117                 ar->buf = ltk_reallocarray(ar->buf, new_size, sizeof(type));                                \
          118                 ar->buf_size = new_size;                                                                \
          119                 ar->len = ar->len < new_size ? ar->len : new_size;                                        \
          120         }                                                                                               \
          121 }                                                                                                        \
          122                                                                                                         \
          123 LTK_UNUSED_FUNC storage void                                                                                \
          124 ltk_array_destroy_##name(ltk_array_##name *ar) {                                                        \
          125         if (!ar)                                                                                        \
          126                 return;                                                                                        \
          127         ltk_free(ar->buf);                                                                                \
          128         ltk_free(ar);                                                                                        \
          129 }                                                                                                        \
          130                                                                                                         \
          131 LTK_UNUSED_FUNC storage void                                                                                \
          132 ltk_array_destroy_deep_##name(ltk_array_##name *ar, void (*destroy_func)(type)) {                        \
          133         if (!ar)                                                                                        \
          134                 return;                                                                                        \
          135         for (size_t i = 0; i < ar->len; i++) {                                                                \
          136                 destroy_func(ar->buf[i]);                                                                \
          137         }                                                                                                \
          138         ltk_array_destroy_##name(ar);                                                                        \
          139 }                                                                                                        \
          140                                                                                                         \
          141 LTK_UNUSED_FUNC storage type                                                                                \
          142 ltk_array_get_safe_##name(ltk_array_##name *ar, size_t index) {                                                \
          143         if (index >= ar->len)                                                                                \
          144                 ltk_fatal("Index out of bounds.\n");                                                        \
          145         return ar->buf[index];                                                                                \
          146 }                                                                                                        \
          147                                                                                                         \
          148 LTK_UNUSED_FUNC storage void                                                                                \
          149 ltk_array_set_safe_##name(ltk_array_##name *ar, size_t index, type e) {                                        \
          150         if (index >= ar->len)                                                                                \
          151                 ltk_fatal("Index out of bounds.\n");                                                        \
          152         ar->buf[index] = e;                                                                                \
          153 }
          154 
          155 #define ltk_array(name) ltk_array_##name
          156 #define ltk_array_create(name, initial_len) ltk_array_create_##name(initial_len)
          157 #define ltk_array_pop(name, ar) ltk_array_pop_##name(ar)
          158 #define ltk_array_insert(name, ar, index, elem, len) ltk_array_insert_##name(ar, index, elem, len)
          159 #define ltk_array_resize(name, ar, size) ltk_array_resize_##name(ar, size)
          160 #define ltk_array_destroy(name, ar) ltk_array_destroy_##name(ar)
          161 #define ltk_array_clear(name, ar) ltk_array_clear_##name(ar)
          162 #define ltk_array_append(name, ar, elem) ltk_array_append_##name(ar, elem)
          163 #define ltk_array_destroy_deep(name, ar, destroy_func) ltk_array_destroy_deep_##name(ar, destroy_func)
          164 #define ltk_array_length(ar) ((ar)->len)
          165 #define ltk_array_get(ar, index) ((ar)->buf[index])
          166 #define ltk_array_get_safe(name, ar, index) ltk_array_get_safe_##name(ar, index)
          167 #define ltk_array_set_safe(name, ar, index, e) ltk_array_set_safe_##name(ar, index, e)
          168 
          169 #define LTK_ARRAY_INIT_DECL(name, type) LTK_ARRAY_INIT_DECL_BASE(name, type,)
          170 #define LTK_ARRAY_INIT_IMPL(name, type) LTK_ARRAY_INIT_IMPL_BASE(name, type,)
          171 #define LTK_ARRAY_INIT_DECL_STATIC(name, type) LTK_ARRAY_INIT_DECL_BASE(name, type, static)
          172 #define LTK_ARRAY_INIT_IMPL_STATIC(name, type) LTK_ARRAY_INIT_IMPL_BASE(name, type, static)
          173 
          174 #endif /* _LTK_ARRAY_H_ */