Home
       tmem.c - iomenu - interactive terminal-based selection menu
  HTML git clone git://bitreich.org/iomenu git://hg6vgqziawt5s4dj.onion/iomenu
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       tmem.c (2901B)
       ---
            1 #include "mem.h"
            2 
            3 #include <assert.h>
            4 #include <errno.h>
            5 #include <stdint.h>
            6 #include <stdlib.h>
            7 #include <string.h>
            8 #include <unistd.h>
            9 
           10 static struct mem_block *
           11 mem_block(void **memp)
           12 {
           13         struct mem_block *block = (void *)((char *)memp - sizeof *block);
           14 
           15         assert(memcmp(block->magic, MEM_BLOCK_MAGIC, 8) == 0);
           16         return block;
           17 }
           18 
           19 void *
           20 mem_alloc(struct mem_pool *pool, size_t len)
           21 {
           22         struct mem_block *block;
           23 
           24         block = calloc(1, sizeof *block + len);
           25         if (block == NULL)
           26                 return NULL;
           27         memcpy(block->magic, MEM_BLOCK_MAGIC, 8);
           28 
           29         block->len = len;
           30         block->pool = pool;
           31         block->prev = NULL;
           32         block->next = pool->head;
           33         if (pool->head != NULL)
           34                 pool->head->prev = block;
           35         pool->head = block;
           36 
           37         return block->buf;
           38 }
           39 
           40 int
           41 mem_resize(void **memp, size_t len)
           42 {
           43         struct mem_block *block = mem_block(*memp);
           44         int is_first = (block == block->pool->head);
           45         int is_same;
           46         void *v;
           47 
           48         v = realloc(block, sizeof *block + len);
           49         if (v == NULL)
           50                 return -1;
           51         is_same = (block == v);
           52         block = v;
           53 
           54         block->len = len;
           55 
           56         if (is_same)
           57                 return 0;
           58 
           59         if (block->prev != NULL)
           60                 block->prev->next = v;
           61         if (block->next != NULL)
           62                 block->next->prev = v;
           63         if (is_first)
           64                 block->pool->head = v;
           65         *memp = block->buf;
           66 
           67         assert(memcmp(block->magic, MEM_BLOCK_MAGIC, 8) == 0);
           68         return 0;
           69 }
           70 
           71 int
           72 mem_grow(void **memp, size_t len)
           73 {
           74         assert(SIZE_MAX - len >= mem_block(*memp)->len);
           75 
           76         return mem_resize(memp, mem_length(*memp) + len);
           77 }
           78 
           79 int
           80 mem_shrink(void **memp, size_t len)
           81 {
           82         assert(mem_block(*memp)->len >= len);
           83 
           84         return mem_resize(memp, mem_length(*memp) - len);
           85 }
           86 
           87 size_t
           88 mem_length(void *mem)
           89 {
           90         return mem_block(mem)->len;
           91 }
           92 
           93 int
           94 mem_append(void **memp, void const *buf, size_t len)
           95 {
           96         size_t old_len = mem_length(*memp);
           97         struct mem_block *block;
           98 
           99         if (mem_grow(memp, len) < 0)
          100                 return -1;
          101         block = mem_block(*memp);
          102         memcpy((char *)block->buf + old_len, buf, len);
          103 
          104         assert(memcmp(block->magic, MEM_BLOCK_MAGIC, 8) == 0);
          105         return 0;
          106 }
          107 
          108 int
          109 mem_read(void **memp, struct mem_pool *pool)
          110 {
          111         struct mem_block *block;
          112         ssize_t sz = 0;
          113         void *mem;
          114 
          115         mem = mem_alloc(pool, 0);
          116         if (mem == NULL)
          117                 return -1;
          118 
          119         for (ssize_t r = 1; r > 0; sz += r) {
          120                 if (mem_resize(&mem, sz + 2048) < 0)
          121                         return -1;
          122 
          123                 r = read(0, (char *)mem + sz, 2048);
          124                 if (r < 0)
          125                         return -1;
          126         }
          127         block = mem_block(mem);
          128         block->len = sz;
          129 
          130         *memp = mem;
          131         assert(memcmp(block->magic, MEM_BLOCK_MAGIC, 8) == 0);
          132         return 0;
          133 }
          134 
          135 void
          136 mem_delete(void *mem)
          137 {
          138         struct mem_block *block = mem_block(mem);;
          139 
          140         if (block == block->pool->head)
          141                 block->pool->head = block->next;
          142         if (block->next != NULL)
          143                 block->next->prev = block->prev;
          144         if (block->prev != NULL)
          145                 block->prev->next = block->next;
          146         memset(block, 0, sizeof *block);
          147         free(block);
          148 }
          149 
          150 void
          151 mem_free(struct mem_pool *pool)
          152 {
          153         struct mem_block *block, *next;
          154 
          155         for (block = pool->head; block != NULL; block = next) {
          156                 next = block->next;
          157                 memset(block, 0, sizeof *block);
          158                 free(block);
          159         }
          160 }