mirror of
https://github.com/simon987/sist2.git
synced 2025-04-19 10:16:42 +00:00
310 lines
7.9 KiB
C
310 lines
7.9 KiB
C
#include "util.h"
|
|
|
|
dyn_buffer_t dyn_buffer_create() {
|
|
dyn_buffer_t buf;
|
|
|
|
buf.size = INITIAL_BUF_SIZE;
|
|
buf.cur = 0;
|
|
buf.buf = malloc(INITIAL_BUF_SIZE);
|
|
|
|
return buf;
|
|
}
|
|
|
|
void grow_buffer(dyn_buffer_t *buf, size_t size) {
|
|
if (buf->cur + size > buf->size) {
|
|
do {
|
|
buf->size *= 2;
|
|
} while (buf->cur + size > buf->size);
|
|
|
|
buf->buf = realloc(buf->buf, buf->size);
|
|
}
|
|
}
|
|
|
|
void grow_buffer_small(dyn_buffer_t *buf) {
|
|
if (buf->cur + sizeof(long) > buf->size) {
|
|
buf->size *= 2;
|
|
buf->buf = realloc(buf->buf, buf->size);
|
|
}
|
|
}
|
|
|
|
void dyn_buffer_write(dyn_buffer_t *buf, void *data, size_t size) {
|
|
grow_buffer(buf, size);
|
|
|
|
memcpy(buf->buf + buf->cur, data, size);
|
|
buf->cur += size;
|
|
}
|
|
|
|
void dyn_buffer_write_char(dyn_buffer_t *buf, char c) {
|
|
grow_buffer_small(buf);
|
|
|
|
*(buf->buf + buf->cur) = c;
|
|
buf->cur += sizeof(c);
|
|
}
|
|
|
|
void dyn_buffer_write_str(dyn_buffer_t *buf, char *str) {
|
|
dyn_buffer_write(buf, str, strlen(str));
|
|
dyn_buffer_write_char(buf, '\0');
|
|
}
|
|
|
|
void dyn_buffer_write_int(dyn_buffer_t *buf, int d) {
|
|
grow_buffer_small(buf);
|
|
|
|
*(int *) (buf->buf + buf->cur) = d;
|
|
buf->cur += sizeof(int);
|
|
}
|
|
|
|
void dyn_buffer_write_short(dyn_buffer_t *buf, short s) {
|
|
grow_buffer_small(buf);
|
|
|
|
*(short *) (buf->buf + buf->cur) = s;
|
|
buf->cur += sizeof(short);
|
|
}
|
|
|
|
void dyn_buffer_write_long(dyn_buffer_t *buf, unsigned long l) {
|
|
grow_buffer_small(buf);
|
|
|
|
*(unsigned long *) (buf->buf + buf->cur) = l;
|
|
buf->cur += sizeof(unsigned long);
|
|
}
|
|
|
|
void dyn_buffer_destroy(dyn_buffer_t *buf) {
|
|
free(buf->buf);
|
|
}
|
|
|
|
void text_buffer_destroy(text_buffer_t *buf) {
|
|
dyn_buffer_destroy(&buf->dyn_buffer);
|
|
}
|
|
|
|
text_buffer_t text_buffer_create(int max_size) {
|
|
text_buffer_t text_buf;
|
|
|
|
text_buf.dyn_buffer = dyn_buffer_create();
|
|
text_buf.max_size = max_size;
|
|
text_buf.last_char_was_whitespace = FALSE;
|
|
|
|
return text_buf;
|
|
}
|
|
|
|
void text_buffer_terminate_string(text_buffer_t *buf) {
|
|
dyn_buffer_write_char(&buf->dyn_buffer, '\0');
|
|
}
|
|
|
|
__always_inline
|
|
int utf8_validchr(const char* s) {
|
|
if (0x00 == (0x80 & *s)) {
|
|
return TRUE;
|
|
} else if (0xf0 == (0xf8 & *s)) {
|
|
if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2])) ||
|
|
(0x80 != (0xc0 & s[3]))) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (0x80 == (0xc0 & s[4])) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((0 == (0x07 & s[0])) && (0 == (0x30 & s[1]))) {
|
|
return FALSE;
|
|
}
|
|
} else if (0xe0 == (0xf0 & *s)) {
|
|
if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2]))) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (0x80 == (0xc0 & s[3])) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((0 == (0x0f & s[0])) && (0 == (0x20 & s[1]))) {
|
|
return FALSE;
|
|
}
|
|
} else if (0xc0 == (0xe0 & *s)) {
|
|
if (0x80 != (0xc0 & s[1])) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (0x80 == (0xc0 & s[2])) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (0 == (0x1e & s[0])) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int text_buffer_append_string(text_buffer_t *buf, char *str, size_t len) {
|
|
|
|
utf8_int32_t c;
|
|
for (void *v = utf8codepoint(str, &c); c != '\0' && ((char*)v - str + 4) < len; v = utf8codepoint(v, &c)) {
|
|
if (utf8_validchr(v)) {
|
|
text_buffer_append_char(buf, c);
|
|
}
|
|
}
|
|
text_buffer_terminate_string(buf);
|
|
}
|
|
|
|
int text_buffer_append_string0(text_buffer_t *buf, char *str) {
|
|
utf8_int32_t c;
|
|
for (void *v = utf8codepoint(str, &c); c != '\0'; v = utf8codepoint(v, &c)) {
|
|
if (utf8_validchr(v)) {
|
|
text_buffer_append_char(buf, c);
|
|
}
|
|
}
|
|
text_buffer_terminate_string(buf);
|
|
}
|
|
|
|
int text_buffer_append_char(text_buffer_t *buf, int c) {
|
|
|
|
if (SHOULD_IGNORE_CHAR(c)) {
|
|
if (!buf->last_char_was_whitespace) {
|
|
dyn_buffer_write_char(&buf->dyn_buffer, ' ');
|
|
buf->last_char_was_whitespace = TRUE;
|
|
|
|
if (buf->max_size > 0 && buf->dyn_buffer.cur >= buf->max_size) {
|
|
return TEXT_BUF_FULL;
|
|
}
|
|
}
|
|
} else {
|
|
buf->last_char_was_whitespace = FALSE;
|
|
grow_buffer_small(&buf->dyn_buffer);
|
|
|
|
if (0 == ((utf8_int32_t) 0xffffff80 & c)) {
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = (char) c;
|
|
} else if (0 == ((utf8_int32_t) 0xfffff800 & c)) {
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0xc0 | (char) (c >> 6);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) (c & 0x3f);
|
|
} else if (0 == ((utf8_int32_t) 0xffff0000 & c)) {
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0xe0 | (char) (c >> 12);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) ((c >> 6) & 0x3f);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) (c & 0x3f);
|
|
} else {
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0xf0 | (char) (c >> 18);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) ((c >> 12) & 0x3f);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) ((c >> 6) & 0x3f);
|
|
*(buf->dyn_buffer.buf + buf->dyn_buffer.cur++) = 0x80 | (char) (c & 0x3f);
|
|
}
|
|
|
|
if (buf->max_size > 0 && buf->dyn_buffer.cur >= buf->max_size) {
|
|
return TEXT_BUF_FULL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void incremental_put(GHashTable *table, unsigned long inode_no, int mtime) {
|
|
g_hash_table_insert(table, (gpointer) inode_no, GINT_TO_POINTER(mtime));
|
|
}
|
|
|
|
int incremental_get(GHashTable *table, unsigned long inode_no) {
|
|
if (table != NULL) {
|
|
return GPOINTER_TO_INT(g_hash_table_lookup(table, (gpointer) inode_no));
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int incremental_mark_file_for_copy(GHashTable *table, unsigned long inode_no) {
|
|
g_hash_table_insert(table, GINT_TO_POINTER(inode_no), GINT_TO_POINTER(1));
|
|
}
|
|
|
|
|
|
#define PBSTR "========================================"
|
|
#define PBWIDTH 40
|
|
|
|
dyn_buffer_t url_escape(char *str) {
|
|
|
|
dyn_buffer_t text = dyn_buffer_create();
|
|
|
|
char *ptr = str;
|
|
while (*ptr) {
|
|
if (*ptr == '#') {
|
|
dyn_buffer_write(&text, "%23", 3);
|
|
ptr++;
|
|
}
|
|
|
|
dyn_buffer_write_char(&text, *ptr++);
|
|
}
|
|
dyn_buffer_write_char(&text, '\0');
|
|
|
|
return text;
|
|
}
|
|
|
|
char *abspath(const char *path) {
|
|
wordexp_t w;
|
|
wordexp(path, &w, 0);
|
|
|
|
char *abs = realpath(w.we_wordv[0], NULL);
|
|
if (abs == NULL) {
|
|
return NULL;
|
|
}
|
|
abs = realloc(abs, strlen(abs) + 2);
|
|
strcat(abs, "/");
|
|
|
|
wordfree(&w);
|
|
return abs;
|
|
}
|
|
|
|
char *expandpath(const char *path) {
|
|
wordexp_t w;
|
|
wordexp(path, &w, 0);
|
|
|
|
char *expanded = malloc(strlen(w.we_wordv[0]) + 2);
|
|
strcpy(expanded, w.we_wordv[0]);
|
|
strcat(expanded, "/");
|
|
|
|
wordfree(&w);
|
|
return expanded;
|
|
}
|
|
|
|
void progress_bar_print(double percentage, size_t tn_size, size_t index_size) {
|
|
|
|
static int last_val = -1;
|
|
int val = (int) (percentage * 100);
|
|
if (last_val == val || val > 100 || index_size < 1024) {
|
|
return;
|
|
}
|
|
last_val = val;
|
|
|
|
int lpad = (int) ((percentage + 0.01) * PBWIDTH);
|
|
int rpad = PBWIDTH - lpad;
|
|
|
|
char tn_unit;
|
|
if (tn_size > 1000 * 1000 * 1000) {
|
|
tn_size = tn_size / 1000 / 1000 / 1000;
|
|
tn_unit = 'G';
|
|
} else {
|
|
tn_size = tn_size / 1000 / 1000;
|
|
tn_unit = 'M';
|
|
}
|
|
|
|
char index_unit;
|
|
if (index_size > 1000 * 1000 * 1000) {
|
|
index_size = index_size / 1000 / 1000 / 1000;
|
|
index_unit = 'G';
|
|
} else {
|
|
index_size = index_size / 1000 / 1000;
|
|
index_unit = 'M';
|
|
}
|
|
|
|
printf(
|
|
"\r%3d%%[%.*s>%*s] TN:%3d%c IDX:%3d%c",
|
|
val, lpad, PBSTR, rpad, "",
|
|
(int) tn_size, tn_unit,
|
|
(int) index_size, index_unit
|
|
);
|
|
fflush(stdout);
|
|
}
|
|
|
|
GHashTable *incremental_get_table() {
|
|
GHashTable *file_table = g_hash_table_new(g_direct_hash, g_direct_equal);
|
|
return file_table;
|
|
}
|
|
|
|
|