Better field parsing
scanf style. kind of
This commit is contained in:
parent
09c8a57a78
commit
7a6df64690
6
Makefile
6
Makefile
@ -1,9 +1,10 @@
|
|||||||
InstallPrefix := /usr/local/bin
|
InstallPrefix := /usr/local/bin
|
||||||
|
|
||||||
|
gitref="$(shell git rev-parse --short HEAD)@$(shell git branch --show-current)"
|
||||||
PROGNAME := caniadd
|
PROGNAME := caniadd
|
||||||
VERSION := 1
|
VERSION := 1
|
||||||
CFLAGS := -Wall -std=gnu11 #-march=native #-Werror
|
CFLAGS := -Wall -std=gnu11 #-march=native #-Werror
|
||||||
CPPFLAGS := -DCBC=0 -DCTR=0 -DECB=1 -Isubm/tiny-AES-c/ -Isubm/md5-c/ -Isubm/MD4/ -DPROG_VERSION='"$(VERSION)"'
|
CPPFLAGS := -DCBC=0 -DCTR=0 -DECB=1 -Isubm/tiny-AES-c/ -Isubm/md5-c/ -Isubm/MD4/ -DPROG_VERSION='"$(VERSION)"' -DGIT_REF='$(gitref)'
|
||||||
LDFLAGS := -lpthread -lsqlite3
|
LDFLAGS := -lpthread -lsqlite3
|
||||||
|
|
||||||
SOURCES := $(wildcard src/*.c) subm/tiny-AES-c/aes.c subm/md5-c/md5.c subm/MD4/md4.c #$(TOML_SRC) $(BENCODE_SRC)
|
SOURCES := $(wildcard src/*.c) subm/tiny-AES-c/aes.c subm/md5-c/md5.c subm/MD4/md4.c #$(TOML_SRC) $(BENCODE_SRC)
|
||||||
@ -17,9 +18,6 @@ all: $(PROGNAME)
|
|||||||
dev: CFLAGS += -Og -ggdb -fsanitize=address -fsanitize=leak -fstack-protector-all -no-pie
|
dev: CFLAGS += -Og -ggdb -fsanitize=address -fsanitize=leak -fstack-protector-all -no-pie
|
||||||
dev: $(PROGNAME)
|
dev: $(PROGNAME)
|
||||||
|
|
||||||
t:
|
|
||||||
echo $(SOURCES)
|
|
||||||
|
|
||||||
install: $(PROGNAME)
|
install: $(PROGNAME)
|
||||||
install -s -- $< $(InstallPrefix)/$(PROGNAME)
|
install -s -- $< $(InstallPrefix)/$(PROGNAME)
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ make
|
|||||||
- Decode escaping from server
|
- Decode escaping from server
|
||||||
- Use a config file
|
- Use a config file
|
||||||
- Add newline escape to server
|
- Add newline escape to server
|
||||||
- Better field parsing, remove the horrors at code 310
|
|
||||||
- Add myliststats cmd as --stats arg
|
- Add myliststats cmd as --stats arg
|
||||||
- Add support for compression
|
- Add support for compression
|
||||||
- Implement session saving between different invocations, and session destroying
|
- Implement session saving between different invocations, and session destroying
|
||||||
|
98
src/api.c
98
src/api.c
@ -557,6 +557,55 @@ static bool api_get_field(const char *buffer, int32_t field_num,
|
|||||||
return api_get_fl(buffer, field_num, " |\n", out_field_start, out_field_len);
|
return api_get_fl(buffer, field_num, " |\n", out_field_start, out_field_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a line, where fields are separated by '|'
|
||||||
|
* Varargs should be:
|
||||||
|
* A scanf like format specifier - out ptr, ...
|
||||||
|
* Ended with a NULL format specifier
|
||||||
|
*
|
||||||
|
* %s is overridden, so if the string is 0 length, it will return NULL
|
||||||
|
*
|
||||||
|
* Returns the number of fields parsed
|
||||||
|
*/
|
||||||
|
int api_field_parse(const char *line, ...)
|
||||||
|
{
|
||||||
|
int f_count = 1;
|
||||||
|
va_list ap;
|
||||||
|
const char *fmt;
|
||||||
|
|
||||||
|
va_start(ap, line);
|
||||||
|
fmt = va_arg(ap, const char*);
|
||||||
|
while (fmt) {
|
||||||
|
char *fs;
|
||||||
|
size_t fl;
|
||||||
|
void *ptr;
|
||||||
|
char scan_fmt[32];
|
||||||
|
|
||||||
|
assert(fmt[0] == '%');
|
||||||
|
api_get_fl(line, f_count, "|\n", &fs, &fl);
|
||||||
|
assert(!(fl == 0 && fmt[1] != 's'));
|
||||||
|
ptr = va_arg(ap, void*);
|
||||||
|
if (fl == 0) {
|
||||||
|
*(void**)ptr = NULL;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (fmt[1] == 's') {
|
||||||
|
*(char**)ptr = strndup(fs, fl);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
snprintf(scan_fmt, sizeof(scan_fmt), "%%%d%s", fl, &fmt[1]);
|
||||||
|
if (sscanf(fs, scan_fmt, ptr) != 1)
|
||||||
|
goto end;
|
||||||
|
next:
|
||||||
|
f_count++;
|
||||||
|
fmt = va_arg(ap, const char*);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
va_end(ap);
|
||||||
|
return f_count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static char *api_get_field_mod(char *buffer, int32_t field_num)
|
static char *api_get_field_mod(char *buffer, int32_t field_num)
|
||||||
{
|
{
|
||||||
@ -858,6 +907,7 @@ enum error api_cmd_mylistadd(int64_t size, const uint8_t *hash,
|
|||||||
/* {int4 lid}|{int4 fid}|{int4 eid}|{int4 aid}|{int4 gid}|
|
/* {int4 lid}|{int4 fid}|{int4 eid}|{int4 aid}|{int4 gid}|
|
||||||
* {int4 date}|{int2 state}|{int4 viewdate}|{str storage}|
|
* {int4 date}|{int2 state}|{int4 viewdate}|{str storage}|
|
||||||
* {str source}|{str other}|{int2 filestate} */
|
* {str source}|{str other}|{int2 filestate} */
|
||||||
|
int fc; /* the Freedom Club */
|
||||||
char *ls;
|
char *ls;
|
||||||
size_t ll;
|
size_t ll;
|
||||||
struct api_mylistadd_result *mr = &res->mylistadd;
|
struct api_mylistadd_result *mr = &res->mylistadd;
|
||||||
@ -866,39 +916,23 @@ enum error api_cmd_mylistadd(int64_t size, const uint8_t *hash,
|
|||||||
assert(ll < API_BUFSIZE - 1);
|
assert(ll < API_BUFSIZE - 1);
|
||||||
(void)glr;
|
(void)glr;
|
||||||
|
|
||||||
ls[ll] = '\0';
|
fc = api_field_parse(ls,
|
||||||
void *fptrs[] = {
|
"%Lu", &mr->lid, "%Lu", &mr->fid, "%Lu", &mr->eid,
|
||||||
&mr->lid, &mr->fid, &mr->eid, &mr->aid, &mr->gid, &mr->date,
|
"%Lu", &mr->aid, "%Lu", &mr->gid, "%Lu", &mr->date,
|
||||||
&mr->state, &mr->viewdate, &mr->storage, &mr->source,
|
"%hu", &mr->state, "%Lu", &mr->viewdate, "%s", &mr->storage,
|
||||||
&mr->other, &mr->filestate,
|
"%s", &mr->source, "%s", &mr->other, "%hu", &mr->filestate,
|
||||||
};
|
NULL);
|
||||||
for (int idx = 1; idx <= 12; idx++) {
|
|
||||||
char *fs, *endptr;
|
|
||||||
size_t fl;
|
|
||||||
bool pr;
|
|
||||||
uint64_t val;
|
|
||||||
size_t cpy_size = sizeof(mr->lid);
|
|
||||||
|
|
||||||
if (idx == 7)
|
uio_debug("Fc is: %d", fc);
|
||||||
cpy_size = sizeof(mr->state);
|
if (fc != 12) {
|
||||||
if (idx == 12)
|
if (fc >= 9)
|
||||||
cpy_size = sizeof(mr->filestate);
|
free(mr->storage);
|
||||||
|
if (fc >= 10)
|
||||||
pr = api_get_field(ls, idx, &fs, &fl);
|
free(mr->source);
|
||||||
assert(pr);
|
if (fc >= 11)
|
||||||
(void)pr;
|
free(mr->other);
|
||||||
|
uio_error("Scanf only parsed %d", fc);
|
||||||
if (idx == 9 || idx == 10 || idx == 11) { /* string fields */
|
err = ERR_API_RESP_INVALID;
|
||||||
if (fl == 0)
|
|
||||||
*(char**)fptrs[idx-1] = NULL;
|
|
||||||
else
|
|
||||||
*(char**)fptrs[idx-1] = strndup(fs, fl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = strtoull(fs, &endptr, 10);
|
|
||||||
assert(!(val == 0 && fs == endptr));
|
|
||||||
memcpy(fptrs[idx-1], &val, cpy_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user