чување a3e96a3b779237982b8f9a7a0cdd460c1bd71a28
родитељ c01ec23d384713be9039c7a5cfdbf0298e0de56b
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Fri, 14 Jun 2024 22:21:04 +0200
Switch {u32_,}str* -> {u32_,}memccpy
Diffstat:
| M | TODO | | | 2 | ++ |
| M | sled.c | | | 146 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
| M | util.c | | | 113 | ++++++++++++++++++++++++++++++++++--------------------------------------------- |
| M | util.h | | | 58 | ++++++++++++++++++++++++++++++++++++++-------------------- |
измењених датотека: 4, додавања: 182(+), брисања: 137(-)
diff --git a/TODO b/TODO
@@ -1,6 +1,8 @@
TODO
====
+[ ] Make y/n prompts case-insensitive
+
< > Make allocation errors prompt to save the file before exiting?
- Would this make sense?
diff --git a/sled.c b/sled.c
@@ -212,6 +212,8 @@ dirname(char* dir, char* path, const size_t dir_size)
if (p > dir + 2 && *(p - 2) == '/')
*p = 0;
+ if (p > dir + 1)
+ p--;
while (p != dir && *p != '/')
{
@@ -237,7 +239,10 @@ do_search_replace(struct DrawState* state)
/* minimum size is LINE_DEFAULT to avoid 0-allocation */
size_t bufsize = LINE_DEFAULT; /* size in uint32_t units */
size_t buflen = 0;
+ size_t old_buflen = 0;
size_t search_len = u32_strlen(state->search);
+ size_t input_len = u32_strlen(state->input);
+ size_t after_len = 0;
int start_row = 0;
int end_row = state->rows_count;
uint32_t* before = NULL;
@@ -251,7 +256,7 @@ do_search_replace(struct DrawState* state)
if (state->buffer[row].size > bufsize)
bufsize = state->buffer[row].size;
- buf = malloc(bufsize * sizeof(uint32_t));
+ buf = calloc(bufsize, sizeof(uint32_t));
if (!buf)
goto do_search_replace_error;
@@ -259,40 +264,48 @@ do_search_replace(struct DrawState* state)
{
before = state->buffer[row].text;
found = (uint32_t*)u32_strstr(before, state->search);
- after = before;
- *buf = 0;
+ if (!found)
+ continue;
- buflen = 0;
+ state->dirty = 1;
+ *buf = 0;
+ *found = 0;
+ buflen = u32_strlen(before);
+ ENSURE_SIZE(buf, temp, bufsize, buflen + 1, buflen + 1,
+ do_search_replace_error, uint32_t);
+ U32_MEMCCPY(buf, before, bufsize, temp);
+ after = found + search_len;
+ *(after - 1) = 0;
while (found)
{
- state->dirty = 1;
- *found = 0;
- buflen += u32_strlen(before) + u32_strlen(state->input);
-
+ old_buflen = buflen;
+ buflen += input_len;
ENSURE_SIZE(buf, temp, bufsize, buflen + 1, buflen + 1,
do_search_replace_error, uint32_t);
- u32_strncat(buf, before, bufsize);
- u32_strncat(buf, state->input, bufsize);
- before = found + search_len;
+ U32_MEMCCPY((buf + old_buflen), state->input,
+ input_len + 1, temp);
+ before = after;
found = (uint32_t*)u32_strstr(before, state->search);
- if (found)
- after = found + search_len;
- else
- after = before;
- }
- if (state->buffer[row].text + state->buffer[row].length > after)
- {
- buflen += u32_strlen(after);
+ if (found) /* new found, after before */
+ *found = 0;
+ after_len = u32_strlen(after);
+ old_buflen = buflen;
+ buflen += after_len;
ENSURE_SIZE(buf, temp, bufsize, buflen + 1, buflen + 1,
do_search_replace_error, uint32_t);
- u32_strncat(buf, after, bufsize);
+ U32_MEMCCPY((buf + old_buflen), after, after_len + 1,
+ temp);
+ if (found) /* new found, after before */
+ {
+ after = found + search_len;
+ *(after - 1) = 0;
+ }
}
-
U32_SAFE_COPY(state->buffer[row].text, temp,
state->buffer[row].size, buf, bufsize,
do_search_replace_error);
- state->buffer[row].length = u32_strlen(buf);
+ state->buffer[row].length = buflen;
}
free(buf);
return 0;
@@ -316,6 +329,7 @@ erase_selection(struct DrawState* state)
int sec = 0;
uint32_t* buf = NULL;
size_t bufsize = state->buffer[ser].size;
+ uint32_t* temp = NULL;
buf = calloc(bufsize, sizeof(uint32_t));
if (!buf)
@@ -323,10 +337,11 @@ erase_selection(struct DrawState* state)
get_selection(&ssr, &ssc, &ser, &sec, state);
- u32_strncpy(buf, state->buffer[ser].text + sec, bufsize);
+ U32_MEMCCPY(buf, state->buffer[ser].text + sec, bufsize - sec,
+ temp);
- *(state->buffer[ssr].text + ssc) = 0;
- u32_strncat(state->buffer[ssr].text, buf, bufsize);
+ U32_MEMCCPY((state->buffer[ssr].text + ssc), buf, bufsize - ssc,
+ temp);
state->buffer[ssr].length = u32_strlen(state->buffer[ssr].text);
if (ssr != ser)
@@ -334,9 +349,9 @@ erase_selection(struct DrawState* state)
for (size_t row = 0; ser + row + 1 < state->rows_count;
row++)
{
- u32_strncpy(state->buffer[ssr + row + 1].text,
+ U32_MEMCCPY(state->buffer[ssr + row + 1].text,
state->buffer[ser + row + 1].text,
- bufsize);
+ bufsize, temp);
state->buffer[ssr + row + 1].length
= state->buffer[ser + row + 1].length;
}
@@ -621,7 +636,7 @@ insert_char(struct DrawState* state, uint32_t ch)
uint32_t* ptext = NULL;
ENSURE_SIZE(state->buffer[state->coord.row].text, ptext,
- state->buffer[state->coord.row].size, state->coord.col + 1,
+ state->buffer[state->coord.row].size, state->coord.col + 2,
state->coord.col + LINE_ALLOC_DELTA, insert_char_error,
uint32_t);
@@ -840,8 +855,8 @@ load_file(struct DrawState* state, long* lineno, long* col)
input_len + LINE_ALLOC_DELTA, load_file_alloc_error,
uint32_t);
- line->length
- = u32_u8_strncpy(line->text, input_line, line->size);
+ U32_U8_MEMCCPY(line->text, input_line, line->size, ptext);
+ line->length = u32_strlen(line->text);
state->rows_count++;
}
fclose(input);
@@ -1140,8 +1155,10 @@ save_skip_backup_symlink:
for (size_t row = 0; row < state->rows_count; row++)
{
- ENSURE_SIZE(buf, pbuf, bufsize, state->buffer[row].length + 1,
- state->buffer[row].length + LINE_ALLOC_DELTA,
+ ENSURE_SIZE(buf, pbuf, bufsize,
+ UTF8REPMAX * state->buffer[row].length + 1,
+ UTF8REPMAX * state->buffer[row].length
+ + LINE_ALLOC_DELTA,
save_file_alloc_error, char);
unicode_string_to_u8(buf, state->buffer[row].text, bufsize);
fprintf(output, "%s\n", buf);
@@ -1193,7 +1210,8 @@ search_replace_replace_dialog_callback(struct DrawState* state)
void
search_update_callback(struct DrawState* state)
{
- u32_strncpy(state->search, state->input, MAXINPUT);
+ uint32_t* temp = NULL;
+ U32_MEMCCPY(state->search, state->input, MAXINPUT, temp);
}
int
@@ -1523,9 +1541,10 @@ input_erase_forward(struct DrawState* state)
int
input_erase_to_end(struct DrawState* state)
{
+ uint32_t* temp = NULL;
state->input[state->input_column] = 0;
input_move_end(state);
- u32_strncpy(state->search, state->input, MAXINPUT);
+ U32_MEMCCPY(state->search, state->input, MAXINPUT, temp);
if (state->input_update_callback)
state->input_update_callback(state);
return 0;
@@ -1906,7 +1925,7 @@ paste_from_paste(struct DrawState* state)
}
line = state->buffer + state->coord.row;
- newsize = line->size + state->paste[0].length + 1;
+ newsize = line->length + state->paste[0].length + 1;
newtext = calloc(newsize, sizeof(uint32_t));
if (!newtext)
{
@@ -1915,17 +1934,23 @@ paste_from_paste(struct DrawState* state)
temp);
goto paste_from_paste_cleanup;
}
- u32_strncpy(newtext, line->text, state->coord.col);
- u32_strncat(newtext, state->paste[0].text, newsize);
+ U32_MEMCCPY(newtext, line->text, state->coord.col + 1, ptext);
+ U32_MEMCCPY((newtext + state->coord.col), state->paste[0].text, newsize,
+ ptext);
assign_coord(&newpos, state->coord);
if (state->paste_count == 1)
{
- u32_strncat(newtext, line->text + state->coord.col, newsize);
- line->length = u32_strncpy(line->text, newtext, newsize);
- line->size = newsize;
- newpos.col += state->paste[state->paste_count - 1].length;
+ if (ptext)
+ U32_MEMCCPY_EXT((ptext - 1), newtext,
+ line->text + state->coord.col,
+ line->length - state->coord.col, newsize,
+ ptext);
+ U32_SAFE_COPY(line->text, ptext, line->size, newtext, newsize,
+ paste_from_paste_cleanup);
+ line->length = u32_strlen(line->text);
+ newpos.col += state->paste[0].length;
}
else
{
@@ -1939,7 +1964,8 @@ paste_from_paste(struct DrawState* state)
LINE_DEFAULT, temp);
goto paste_from_paste_cleanup;
}
- u32_strncpy(rest, line->text + state->coord.col, rest_size);
+ U32_MEMCCPY(rest, line->text + state->coord.col, rest_size,
+ ptext);
U32_SAFE_COPY(line->text, ptext, line->size, newtext, newsize,
paste_from_paste_cleanup);
line->length = u32_strlen(line->text);
@@ -1975,7 +2001,10 @@ paste_from_paste(struct DrawState* state)
state->paste[state->paste_count - 1].text,
state->paste[state->paste_count - 1].size + rest_size,
paste_from_paste_cleanup);
- u32_strncat(newtext, rest, newsize);
+ if (ptext)
+ U32_MEMCCPY_EXT((ptext - 1), newtext, rest,
+ newsize - (ptext - newtext - 1), newsize,
+ ptext);
U32_SAFE_COPY(line->text, ptext, line->size, newtext, newsize,
paste_from_paste_cleanup);
line->length = u32_strlen(line->text);
@@ -2267,11 +2296,15 @@ simple_join_lines(struct DrawState* state)
state->buffer[first_line].length
+ state->buffer[first_line + 1].length + 1,
simple_join_lines_error, uint32_t);
- u32_strncat(state->buffer[first_line].text,
+ U32_MEMCCPY((state->buffer[first_line].text
+ + state->buffer[first_line].length),
state->buffer[first_line + 1].text,
- state->buffer[first_line].size);
+ state->buffer[first_line].size
+ - state->buffer[first_line + 1].length,
+ ptext);
state->buffer[first_line].length
= u32_strlen(state->buffer[first_line].text);
+ //+= state->buffer[first_line + 1].length;
for (size_t i = first_line + 1; i < state->rows_count - 1; i++)
{
U32_SAFE_COPY(state->buffer[i].text, ptext,
@@ -2343,17 +2376,16 @@ simple_yank(struct DrawState* state)
if (state->paste_count == 1)
{
U32_SAFE_COPY(state->paste[0].text, ptext, state->paste[0].size,
- state->buffer[ssr].text + ssc, sec - ssc,
+ state->buffer[ssr].text + ssc, sec - ssc + 1,
simple_yank_alloc_error);
- state->paste[0].length = u32_strlen(state->paste[0].text);
+ state->paste[0].length = sec - ssc;
}
else
{
- size_t first_line_len
- = u32_strlen(state->buffer[ssr].text + ssc);
+ size_t first_line_len = state->buffer[ssr].length - ssc;
U32_SAFE_COPY(state->paste[0].text, ptext, state->paste[0].size,
- state->buffer[ssr].text + ssc, first_line_len,
+ state->buffer[ssr].text + ssc, first_line_len + 1,
simple_yank_alloc_error);
state->paste[0].length = first_line_len;
@@ -2370,9 +2402,9 @@ simple_yank(struct DrawState* state)
U32_SAFE_COPY(state->paste[state->paste_count - 1].text, ptext,
state->paste[state->paste_count - 1].size,
- state->buffer[ser].text, sec, simple_yank_alloc_error);
- state->paste[state->paste_count - 1].length
- = u32_strlen(state->paste[state->paste_count - 1].text);
+ state->buffer[ser].text, sec + 1,
+ simple_yank_alloc_error);
+ state->paste[state->paste_count - 1].length = sec;
}
return;
@@ -2641,6 +2673,12 @@ main(int argc, char** argv)
{
MEMCCPY(state.real_filename, dir,
limits[L_PATH_MAX], temp);
+ if (!temp)
+ {
+ print_error(1, "Pathname too long");
+ free(filename);
+ exit(1);
+ }
*(temp - 1) = '/';
MEMCCPY_EXT(temp, state.real_filename, rfn,
limits[L_PATH_MAX] - state.rfn_len - 1,
@@ -2757,6 +2795,7 @@ main(int argc, char** argv)
perror("sled: unveil");
free(filename);
free(dir);
+ free(rfn);
exit(1);
}
#endif
@@ -2792,6 +2831,7 @@ general_error:
free(state.backup_filename);
free(filename);
free(dir);
+ free(rfn);
return result;
init_termbox:
diff --git a/util.c b/util.c
@@ -11,10 +11,6 @@
#include "termbox.h"
#include "util.h"
-enum { UTLERRNONE = 0, UTLERROVFL = 1 };
-
-int utlerrno = UTLERRNONE;
-
size_t
u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
{
@@ -39,12 +35,11 @@ u8_string_to_unicode(uint32_t* us, const char* s, const size_t max)
return added;
}
-/* If the textual representation of characters in us exceeds max, utlerrno is
- * set to UTLERROVFL */
size_t
unicode_string_to_u8(char* s, const uint32_t* us, const size_t max)
{
char ch[8];
+ char* ps = NULL;
const uint32_t* pus = us;
size_t len;
size_t added = 0;
@@ -52,25 +47,65 @@ unicode_string_to_u8(char* s, const uint32_t* us, const size_t max)
if (!pus)
return added;
- *s = 0;
+ ps = s;
while (*pus)
{
len = tb_utf8_unicode_to_char(ch, *pus);
if (added + 1 >= max)
- break;
- ch[len] = 0;
- if (strlcat(s, ch, max) >= max)
- {
- utlerrno = UTLERROVFL;
return added;
- }
+ memccpy(ps, ch, 0, len);
+ ps += len;
added++;
pus++;
}
- utlerrno = UTLERRNONE;
+ *ps = 0;
return added;
}
+uint32_t*
+u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c, size_t len)
+{
+ size_t copied = 0;
+ while ((*dst++ = *src++) != c && copied < len)
+ copied++;
+ if (copied == len)
+ return NULL;
+ return dst;
+}
+
+/* len is the max length of src in bytes */
+uint32_t*
+u32_u8_memccpy(uint32_t* dst, const char* src, char c, size_t len)
+{
+ size_t copied = 0;
+ size_t u8_len;
+ uint32_t uch;
+ const char* psrc = src;
+
+ if (!*psrc)
+ {
+ *dst = 0;
+ return dst;
+ }
+
+ u8_len = tb_utf8_char_to_unicode(&uch, psrc);
+ while ((*dst++ = uch) != c && copied < len)
+ {
+ psrc += u8_len;
+ copied += u8_len;
+ if (copied >= len)
+ return NULL;
+ if (*psrc)
+ u8_len = tb_utf8_char_to_unicode(&uch, psrc);
+ else
+ {
+ *dst = 0;
+ break;
+ }
+ }
+ return dst;
+}
+
size_t
u8_strlen(const char* s)
{
@@ -151,56 +186,6 @@ u32_strchr(const uint32_t* haystack, const uint32_t needle)
return NULL;
}
-size_t
-u32_strncpy(uint32_t* to, const uint32_t* from, const size_t max)
-{
- const uint32_t* pfrom = from;
- size_t copied = 0;
- while (*pfrom && copied < max)
- {
- *to++ = *pfrom++;
- copied++;
- }
- *to = 0;
- return copied;
-}
-
-/*
- * to - u32 string to concatenate to
- * max - total combined string size
- * from - u32 string to concatenate */
-size_t
-u32_strncat(uint32_t* to, const uint32_t* from, const size_t max)
-{
- const uint32_t* pfrom = from;
- size_t copied = 0;
- while (*to && copied < max)
- {
- to++;
- copied++;
- }
- while (*pfrom && copied < max)
- {
- *to++ = *pfrom++;
- copied++;
- }
- *to = 0;
- return copied;
-}
-
-size_t
-u32_u8_strncpy(uint32_t* to, const char* from, const size_t max)
-{
- uint32_t* ufrom = NULL;
- size_t len;
- if (!(ufrom = malloc(max * sizeof(uint32_t))))
- return 0;
- u8_string_to_unicode(ufrom, from, max);
- len = u32_strncpy(to, ufrom, max);
- free(ufrom);
- return len;
-}
-
const int
is_word_boundary(const char ch, const int strictly_whitespace)
{
diff --git a/util.h b/util.h
@@ -10,19 +10,40 @@
#define LEN(x) (sizeof(x) / sizeof(x[0]))
#define MAX(a, b) ((a > b) ? (a) : (b))
#define MIN(a, b) ((a < b) ? (a) : (b))
-#define MEMCCPY(to, from, tolen, temp) \
- do \
- { \
- temp = memccpy(to, from, 0, tolen); \
- if (!temp) \
- to[tolen - 1] = 0; \
+#define MEMCCPY(to, from, tolen, temp) \
+ do \
+ { \
+ temp = memccpy(to, from, 0, tolen); \
+ if (!temp) \
+ to[tolen > 0 ? tolen - 1 : 0] = 0; \
} while (0)
-#define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \
- do \
- { \
- temp = memccpy(to, from, 0, tolen); \
- if (!temp) \
- fallbackto[tolen - 1] = 0; \
+#define MEMCCPY_EXT(to, fallbackto, from, tolen, temp) \
+ do \
+ { \
+ temp = memccpy(to, from, 0, tolen); \
+ if (!temp) \
+ fallbackto[tolen > 0 ? tolen - 1 : 0] = 0; \
+ } while (0)
+#define U32_MEMCCPY(to, from, tolen, temp) \
+ do \
+ { \
+ temp = u32_memccpy(to, from, 0L, tolen); \
+ if (!temp) \
+ to[tolen > 0 ? tolen - 1 : 0] = 0; \
+ } while (0)
+#define U32_U8_MEMCCPY(to, from, tolen, temp) \
+ do \
+ { \
+ temp = u32_u8_memccpy(to, from, 0L, tolen); \
+ if (!temp) \
+ to[tolen > 0 ? tolen - 1 : 0] = 0; \
+ } while (0)
+#define U32_MEMCCPY_EXT(to, fallbackto, from, tolen, fbtolen, temp) \
+ do \
+ { \
+ temp = u32_memccpy(to, from, 0L, tolen); \
+ if (!temp) \
+ fallbackto[fbtolen > 0 ? fbtolen - 1 : 0] = 0; \
} while (0)
#define ENSURE_SIZE(to, temp, tosize, testsize, fromsize, label, type) \
@@ -54,7 +75,7 @@
do \
{ \
ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, char); \
- u8_strncpy(to, from, fromsize); \
+ MEMCCPY(to, from, fromsize, temp); \
} while (0)
/*
* - Make sure the size of the destination string is large enough to copy, and
@@ -68,7 +89,7 @@
{ \
ENSURE_SIZE(to, temp, tosize, fromsize, fromsize, label, \
uint32_t); \
- u32_strncpy(to, from, fromsize); \
+ U32_MEMCCPY(to, from, fromsize, temp); \
} while (0)
enum {
@@ -101,20 +122,17 @@ enum { ACT_WRITING, ACT_READING };
extern int utlerrno;
-size_t strlcpy(char* dst, const char* src, size_t dsize);
-size_t strlcat(char* dst, const char* src, size_t dsize);
-
size_t u8_string_to_unicode(uint32_t* us, const char* s, const size_t max);
size_t unicode_string_to_u8(char* s, const uint32_t* us, const size_t max);
+uint32_t* u32_memccpy(uint32_t* dst, const uint32_t* src, uint32_t c,
+ size_t len);
+uint32_t* u32_u8_memccpy(uint32_t* dst, const char* src, char c, size_t len);
size_t u8_strlen(const char* s);
size_t u32_strlen(const uint32_t* s);
const uint32_t* u32_strstr(const uint32_t* haystack, const uint32_t* needle);
const uint32_t* u32_strrstr(const uint32_t* haystack, const uint32_t* needle,
const uint32_t* haystack_tail);
const uint32_t* u32_strchr(const uint32_t* haystack, const uint32_t needle);
-size_t u32_strncpy(uint32_t* to, const uint32_t* from, const size_t max);
-size_t u32_strncat(uint32_t* to, const uint32_t* from, const size_t max);
-size_t u32_u8_strncpy(uint32_t* to, const char* from, const size_t max);
const int is_word_boundary(const char ch, const int strictly_whitespace);
const int u32_is_word_boundary(const uint32_t ch, const int strictly_whitespace);
const int starts_with(const char* s, const char* with);