tmem.c - iomenu - interactive terminal-based selection menu
(HTM) 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 }