|
|
@@ -1,15 +1,47 @@
|
|
|
#ifndef BUFFER_H
|
|
|
#define BUFFER_H
|
|
|
|
|
|
+
|
|
|
+
|
|
|
struct buffer {
|
|
|
DA_DEF_STRUCT_ITEM(char, data);
|
|
|
size_t cur;
|
|
|
};
|
|
|
|
|
|
+enum buffer_err {
|
|
|
+ BUFFER_ERR_OK = 0,
|
|
|
+ BUFFER_ERR_EMPTY,
|
|
|
+ BUFFER_ERR_NOT_FOUND,
|
|
|
+ BUFFER_ERR_INVALID_CUR_POS,
|
|
|
+ BUFFER_ERR_FAIL_READ_FILE,
|
|
|
+ BUFFER_ERR_START_GT_END,
|
|
|
+ BUFFER_ERR_INVALID_END_SIZE,
|
|
|
+};
|
|
|
+
|
|
|
+struct ret_buffer_err {
|
|
|
+ struct buffer f1;
|
|
|
+ enum buffer_err f2;
|
|
|
+};
|
|
|
+
|
|
|
+struct ret_size_t_err {
|
|
|
+ size_t f1;
|
|
|
+ enum buffer_err f2;
|
|
|
+};
|
|
|
+
|
|
|
+struct ret_buffer_size_t_err {
|
|
|
+ struct buffer f1;
|
|
|
+ size_t f2;
|
|
|
+ enum buffer_err f3;
|
|
|
+};
|
|
|
+
|
|
|
struct buffer buffer_create(void);
|
|
|
void buffer_destroy(struct buffer buf);
|
|
|
|
|
|
-struct buffer buffer_mv_cur_letf(struct buffer buf);
|
|
|
+struct ret_buffer_err buffer_load_from_file(struct buffer buf,
|
|
|
+ const char *filepath);
|
|
|
+enum buffer_err buffer_save_to_file(struct buffer buf, const char *filepath);
|
|
|
+
|
|
|
+struct buffer buffer_mv_cur_left(struct buffer buf);
|
|
|
struct buffer buffer_mv_cur_right(struct buffer buf);
|
|
|
struct buffer buffer_mv_cur_up(struct buffer buf);
|
|
|
struct buffer buffer_mv_cur_down(struct buffer buf);
|
|
|
@@ -17,14 +49,22 @@ struct buffer buffer_mv_cur_down(struct buffer buf);
|
|
|
struct buffer buffer_insert_char(struct buffer buf, size_t index, char c);
|
|
|
struct buffer buffer_remove_char_mv_cur(struct buffer buf, size_t index);
|
|
|
struct buffer buffer_remove_char(struct buffer buf, size_t index);
|
|
|
-struct buffer buffer_remove_between(struct buffer buf,
|
|
|
- size_t start, size_t end);
|
|
|
+struct ret_buffer_size_t_err buffer_remove_between(struct buffer buf,
|
|
|
+ size_t start, size_t end);
|
|
|
|
|
|
-size_t buffer_index_bw_word(struct buffer buf);
|
|
|
+struct ret_size_t_err buffer_index_bw_word(struct buffer buf);
|
|
|
+struct ret_size_t_err buffer_index_fw_word(struct buffer buf);
|
|
|
+
|
|
|
+struct ret_size_t_err buffer_index_bw_char(struct buffer buf, char c);
|
|
|
+struct ret_size_t_err buffer_index_fw_char(struct buffer buf, char c);
|
|
|
|
|
|
#if defined(BUFFER_IMP) || defined(IMP)
|
|
|
|
|
|
+#include <ctype.h>
|
|
|
+
|
|
|
+#include "file.h"
|
|
|
#include "da.h"
|
|
|
+#include "unwrap.h"
|
|
|
|
|
|
struct buffer
|
|
|
buffer_create(void)
|
|
|
@@ -41,9 +81,47 @@ buffer_destroy(struct buffer buf)
|
|
|
free(buf.data.items);
|
|
|
}
|
|
|
|
|
|
+struct ret_buffer_err
|
|
|
+buffer_load_from_file(struct buffer buf, const char *filepath)
|
|
|
+{
|
|
|
+
|
|
|
+ void *ptr;
|
|
|
+ size_t file_size;
|
|
|
+ enum file_err err;
|
|
|
+ RET_UNWRAP3(ptr, file_size, err,
|
|
|
+ struct ret_void_p_err, file_read_all(filepath));
|
|
|
+
|
|
|
+ if ( err != FILE_ERR_OK ) {
|
|
|
+ return (struct ret_buffer_err) {
|
|
|
+ .f1 = buf,
|
|
|
+ .f2 = BUFFER_ERR_FAIL_READ_FILE
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ buffer_destroy(buf);
|
|
|
+
|
|
|
+ buf.data.items = ptr;
|
|
|
+ buf.data.size = file_size - 1;
|
|
|
+ buf.data.cap = file_size;
|
|
|
+
|
|
|
+ return (struct ret_buffer_err) {
|
|
|
+ .f1 = buf,
|
|
|
+ .f2 = BUFFER_ERR_OK
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+enum buffer_err
|
|
|
+buffer_save_to_file(struct buffer buf, const char *filepath)
|
|
|
+{
|
|
|
+ (void) buf;
|
|
|
+ (void) filepath;
|
|
|
+
|
|
|
+ return BUFFER_ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
struct buffer
|
|
|
-buffer_mv_cur_letf(struct buffer buf)
|
|
|
+buffer_mv_cur_left(struct buffer buf)
|
|
|
{
|
|
|
if ( buf.cur == 0 ) {
|
|
|
return buf;
|
|
|
@@ -134,19 +212,26 @@ buffer_remove_char(struct buffer buf, size_t index)
|
|
|
return buf;
|
|
|
}
|
|
|
|
|
|
-struct buffer
|
|
|
+struct ret_buffer_size_t_err
|
|
|
buffer_remove_between(struct buffer buf, size_t start, size_t end)
|
|
|
{
|
|
|
+ enum buffer_err err = BUFFER_ERR_OK;
|
|
|
if ( buf.data.size == 0 ) {
|
|
|
- return buf;
|
|
|
+ err = BUFFER_ERR_EMPTY;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
if ( start == end ) {
|
|
|
- return buffer_remove_char(buf, start);
|
|
|
+ return (struct ret_buffer_size_t_err) {
|
|
|
+ .f1 = buffer_remove_char(buf, start),
|
|
|
+ .f2 = 1,
|
|
|
+ .f3 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
if ( start > end ) {
|
|
|
- return buf;
|
|
|
+ err = BUFFER_ERR_START_GT_END;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
DA_DEF_STRUCT_ITEM(char, da);
|
|
|
@@ -155,35 +240,99 @@ buffer_remove_between(struct buffer buf, size_t start, size_t end)
|
|
|
/* There is no need to check start > buf.data.size, because */
|
|
|
/* we know that start < end */
|
|
|
if ( end > da.size ) {
|
|
|
- return buf;
|
|
|
+ err = BUFFER_ERR_INVALID_END_SIZE;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
size_t nrm = end - start;
|
|
|
- printf("%ld\n", nrm);
|
|
|
memmove(da.items+start, da.items+end, da.size - nrm);
|
|
|
da.size -= nrm;
|
|
|
- buf.cur -= nrm;
|
|
|
|
|
|
- return buf;
|
|
|
+ return (struct ret_buffer_size_t_err) {
|
|
|
+ .f1 = buf,
|
|
|
+ .f2 = nrm,
|
|
|
+ .f3 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
+
|
|
|
+err: ;
|
|
|
+ return (struct ret_buffer_size_t_err) {
|
|
|
+ .f1 = buf,
|
|
|
+ .f2 = 0,
|
|
|
+ .f3 = err
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
-#include <ctype.h>
|
|
|
|
|
|
-size_t
|
|
|
+struct ret_size_t_err
|
|
|
buffer_index_bw_word(struct buffer buf)
|
|
|
{
|
|
|
+ enum buffer_err err = BUFFER_ERR_OK;
|
|
|
if ( buf.data.size == 0 ) {
|
|
|
- return 0;
|
|
|
+ err = BUFFER_ERR_EMPTY;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( buf.cur > buf.data.size ) {
|
|
|
+ err = BUFFER_ERR_INVALID_CUR_POS;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
bool found_letter = false;
|
|
|
- size_t i = buf.cur;
|
|
|
+ size_t i = buf.cur - 1;
|
|
|
for ( ; i > 0; --i) {
|
|
|
char c = buf.data.items[i];
|
|
|
if ( isalpha(c) ) {
|
|
|
found_letter = true;
|
|
|
} else if ( found_letter ) {
|
|
|
- return i+1;
|
|
|
+ ++i;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ( i == 0 ) {
|
|
|
+ char c = buf.data.items[i];
|
|
|
+ if ( isalpha(c) ) {
|
|
|
+ found_letter = true;
|
|
|
+ } else if ( found_letter ) {
|
|
|
+ ++i;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+exit: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = i,
|
|
|
+ .f2 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
+
|
|
|
+err: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = 0,
|
|
|
+ .f2 = err,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+struct ret_size_t_err
|
|
|
+buffer_index_fw_word(struct buffer buf)
|
|
|
+{
|
|
|
+ enum buffer_err err = BUFFER_ERR_OK;
|
|
|
+ if ( buf.data.size == 0 ) {
|
|
|
+ err = BUFFER_ERR_EMPTY;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( buf.cur > buf.data.size ) {
|
|
|
+ err = BUFFER_ERR_INVALID_CUR_POS;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool found_letter = false;
|
|
|
+ size_t i = buf.cur;
|
|
|
+ for ( ; i < buf.data.size; ++i) {
|
|
|
+ char c = buf.data.items[i];
|
|
|
+ if ( isalpha(c) ) {
|
|
|
+ found_letter = true;
|
|
|
+ } else if ( found_letter ) {
|
|
|
+ goto exit;
|
|
|
}
|
|
|
}
|
|
|
if ( i == 0 ) {
|
|
|
@@ -191,11 +340,94 @@ buffer_index_bw_word(struct buffer buf)
|
|
|
if ( isalpha(c) ) {
|
|
|
found_letter = true;
|
|
|
} else if ( found_letter ) {
|
|
|
- return i+1;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+exit: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = i,
|
|
|
+ .f2 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
+
|
|
|
+err: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = 0,
|
|
|
+ .f2 = err,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+struct ret_size_t_err
|
|
|
+buffer_index_bw_char(struct buffer buf, char c)
|
|
|
+{
|
|
|
+ enum buffer_err err;
|
|
|
+ if ( buf.data.size == 0 ) {
|
|
|
+ err = BUFFER_ERR_EMPTY;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( buf.cur > buf.data.size ) {
|
|
|
+ err = BUFFER_ERR_INVALID_CUR_POS;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ const char *str = buf.data.items;
|
|
|
+
|
|
|
+ bool cond = false;
|
|
|
+ /* TODO: Find a way to not use ssize_t buf size_t */
|
|
|
+ ssize_t closest = -1;
|
|
|
+ for ( ssize_t i = 0; i < (ssize_t) buf.cur; ++i ) {
|
|
|
+ cond = str[i] == c;
|
|
|
+ closest = ( cond ) * i + ( ! cond ) * closest;
|
|
|
+ }
|
|
|
+ if ( closest == -1 ) {
|
|
|
+ err = BUFFER_ERR_NOT_FOUND;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = (size_t) closest,
|
|
|
+ .f2 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
+
|
|
|
+err: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = 0,
|
|
|
+ .f2 = err,
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+struct ret_size_t_err
|
|
|
+buffer_index_fw_char(struct buffer buf, char c)
|
|
|
+{
|
|
|
+ enum buffer_err err;
|
|
|
+ if ( buf.data.size == 0 ) {
|
|
|
+ err = BUFFER_ERR_EMPTY;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( buf.cur > buf.data.size ) {
|
|
|
+ err = BUFFER_ERR_INVALID_CUR_POS;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ const char *str = buf.data.items;
|
|
|
+
|
|
|
+ for ( size_t i = buf.cur; i < buf.data.size; ++i ) {
|
|
|
+ if ( str[i] == c ) {
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = i,
|
|
|
+ .f2 = BUFFER_ERR_OK,
|
|
|
+ };
|
|
|
}
|
|
|
}
|
|
|
+ err = BUFFER_ERR_NOT_FOUND;
|
|
|
|
|
|
- return i;
|
|
|
+err: ;
|
|
|
+ return (struct ret_size_t_err) {
|
|
|
+ .f1 = 0,
|
|
|
+ .f2 = err,
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
#endif /* defined(BUFFER_IMP) || defined(IMP) */
|