Introduction
Introduction Statistics Contact Development Disclaimer Help
memory.c - ledit - Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/ledit.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/…
Log
Files
Refs
README
LICENSE
---
memory.c (6618B)
---
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "assert.h"
7 #include "memory.h"
8 #include "cleanup.h"
9
10 static void
11 fatal_err(const char *msg) {
12 fprintf(stderr, "%s", msg);
13 /* FIXME: maybe don't cleanup here - it will probably fail anywa…
14 ledit_cleanup();
15 exit(1);
16 }
17
18 void
19 err_overflow_impl(const char *file, int line, const char *func) {
20 (void)fprintf(stderr, "Integer overflow: file \"%s\", line %d, f…
21 ledit_emergencydump(file, line, func, "Integer overflow");
22 abort();
23 }
24
25 /* FIXME: should these perform emergencydump instead of just
26 fatal_err? It probably isn't of much use when there isn't
27 even any memory left. */
28 char *
29 ledit_strdup(const char *s) {
30 char *str = strdup(s);
31 ledit_assert(str && "Out of memory.");
32 if (!str)
33 fatal_err("Out of memory.\n");
34 return str;
35 }
36
37 char *
38 ledit_strndup(const char *s, size_t n) {
39 char *str = strndup(s, n);
40 if (!str)
41 fatal_err("Out of memory.\n");
42 return str;
43 }
44
45 void *
46 ledit_malloc(size_t size) {
47 void *ptr = malloc(size);
48 if (!ptr)
49 fatal_err("Out of memory.\n");
50 return ptr;
51 }
52
53 void *
54 ledit_calloc(size_t nmemb, size_t size) {
55 void *ptr = calloc(nmemb, size);
56 if (!ptr)
57 fatal_err("Out of memory.\n");
58 return ptr;
59 }
60
61 void *
62 ledit_realloc(void *ptr, size_t size) {
63 void *new_ptr = realloc(ptr, size);
64 if (!new_ptr)
65 fatal_err("Out of memory.\n");
66 return new_ptr;
67 }
68
69 /* Concatenate the two given strings and return the result.
70 This allocates new memory for the result string, unlike
71 the actual strcat. Aborts program on error */
72 char *
73 ledit_strcat(const char *str1, const char *str2) {
74 size_t len1, len2;
75 char *ret;
76
77 len1 = strlen(str1);
78 len2 = strlen(str2);
79 ret = ledit_malloc(len1 + len2 + 1);
80 strcpy(ret, str1);
81 strcpy(ret + len1, str2);
82
83 return ret;
84 }
85
86 char *
87 print_fmt(char *fmt, ...) {
88 va_list args;
89 va_start(args, fmt);
90 int len = vsnprintf(NULL, 0, fmt, args);
91 /* FIXME: what should be done on error? */
92 if (len < 0)
93 fatal_err("Error in vsnprintf called from print_fmt");
94 /* FIXME: overflow */
95 char *str = ledit_malloc(len + 1);
96 va_end(args);
97 va_start(args, fmt);
98 vsnprintf(str, len + 1, fmt, args);
99 va_end(args);
100 return str;
101 }
102
103 /*
104 * This (reallocarray) is from OpenBSD (adapted to exit on error):
105 * Copyright (c) 2008 Otto Moerbeek <[email protected]>
106 */
107
108 /*
109 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
110 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
111 */
112 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
113
114 void *
115 ledit_reallocarray(void *optr, size_t nmemb, size_t size)
116 {
117 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
118 nmemb > 0 && SIZE_MAX / nmemb < size) {
119 err_overflow();
120 }
121 return ledit_realloc(optr, size * nmemb);
122 }
123
124 void
125 move_gap(
126 void *array, size_t elem_size, size_t index,
127 size_t gap, size_t cap, size_t len,
128 size_t *new_gap_ret) {
129 ledit_assert(array != NULL);
130 ledit_assert(index <= len);
131 ledit_assert(len <= cap);
132 char *carray = (char *)array; /* cast to char * for pointer arit…
133 /* since the array has size cap * elem_size, it is assumed that …
134 if (index > gap) {
135 /* move piece between end of original gap and
136 index to beginning of original gap */
137 memmove(
138 carray + gap * elem_size,
139 carray + (gap + cap - len) * elem_size,
140 (index - gap) * elem_size
141 );
142 } else if (index < gap) {
143 /* move piece between index and original gap to
144 end of original gap */
145 memmove(
146 carray + (index + cap - len) * elem_size,
147 carray + index * elem_size,
148 (gap - index) * elem_size
149 );
150 }
151 if (new_gap_ret)
152 *new_gap_ret = index;
153 }
154
155 /* FIXME: replace with macro version that takes type parameter in order
156 to avoid errors with elem_size */
157 /* This is almost certainly premature optimization and maybe
158 not optimization at all. */
159 void *
160 resize_and_move_gap(
161 void *array, size_t elem_size,
162 size_t old_gap, size_t old_cap, size_t len,
163 size_t min_size, size_t index,
164 size_t *new_gap_ret, size_t *new_cap_ret) {
165 ledit_assert(array != NULL || (len == 0 && old_cap == 0));
166 ledit_assert(index <= len);
167 ledit_assert(len <= old_cap);
168 ledit_assert(old_gap <= len);
169 size_t gap_size = old_cap - len;
170 size_t new_cap = ideal_array_size(old_cap, min_size);;
171 if (new_cap >= old_cap) {
172 if (new_cap > old_cap)
173 array = ledit_reallocarray(array, new_cap, elem_…
174 char *carray = (char*)array; /* cast to char to do point…
175 /* we already know new_cap * elem_size does not wrap aro…
176 is of that size, so all the other multiplications her…
177 (at least that's what I think, but I may be wrong) */
178 if (index > old_gap) {
179 /* move piece between end of original gap and in…
180 beginning of original gap */
181 memmove(
182 carray + old_gap * elem_size,
183 carray + (old_gap + gap_size) * elem_size,
184 (index - old_gap) * elem_size
185 );
186 /* move piece after index to end of buffer */
187 memmove(
188 carray + (new_cap - (len - index)) * elem_si…
189 carray + (index + gap_size) * elem_size,
190 (len - index) * elem_size
191 );
192 } else if (index < old_gap) {
193 /* move piece after original gap to end of buffe…
194 memmove(
195 carray + (new_cap - (len - old_gap)) * elem_…
196 carray + (old_gap + gap_size) * elem_size,
197 (len - old_gap) * elem_size
198 );
199 /* move piece between index and original gap to …
200 memmove(
201 carray + (new_cap - len + index) * elem_size,
202 carray + index * elem_size,
203 (old_gap - index) * elem_size
204 );
205 } else {
206 /* move piece after original gap to end of buffe…
207 memmove(
208 carray + (new_cap - (len - old_gap)) * elem_…
209 carray + (old_gap + gap_size) * elem_size,
210 (len - old_gap) * elem_size
211 );
212 }
213 } else {
214 /* otherwise, parts may be cut off */
215 ledit_assert(min_size >= len);
216 /* FIXME: optimize this */
217 if (array)
218 move_gap(array, elem_size, len, old_gap, old_cap…
219 array = ledit_reallocarray(array, new_cap, elem_size);
220 move_gap(array, elem_size, index, len, new_cap, len, NUL…
221 }
222 if (new_gap_ret)
223 *new_gap_ret = index;
224 if (new_cap_ret)
225 *new_cap_ret = new_cap;
226 return array;
227 }
228
229 /* FIXME: maybe don't double when already very large? */
230 /* FIXME: better start size when old == 0? */
231 size_t
232 ideal_array_size(size_t old, size_t needed) {
233 size_t ret = old;
234 if (old < needed)
235 ret = old * 2 > needed ? old * 2 : needed;
236 else if (needed * 4 < old)
237 ret = old / 2;
238 if (ret == 0)
239 ret = 1; /* not sure if this is necessary */
240 return ret;
241 }
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.