mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
More simply stream management.
This commit is contained in:
parent
2eec5eb675
commit
b90e7fdacf
3 changed files with 319 additions and 164 deletions
160
state.c
160
state.c
|
|
@ -53,7 +53,7 @@ void state_done(struct snapraid_state* state)
|
|||
|
||||
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable)
|
||||
{
|
||||
FILE* f;
|
||||
STREAM* f;
|
||||
unsigned line;
|
||||
unsigned content_count;
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
fflush(stderr);
|
||||
}
|
||||
|
||||
f = fopen(path, "rt");
|
||||
f = sopen(path);
|
||||
if (!f) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "No configuration file found at '%s'\n", path);
|
||||
|
|
@ -91,20 +91,20 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
int c;
|
||||
|
||||
/* skip initial spaces */
|
||||
strgetspace(f);
|
||||
sgetspace(f);
|
||||
|
||||
/* read the command */
|
||||
ret = strgettoken(f, tag, sizeof(tag));
|
||||
ret = sgettok(f, tag, sizeof(tag));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* skip spaces after the command */
|
||||
strgetspace(f);
|
||||
sgetspace(f);
|
||||
|
||||
if (strcmp(tag, "block_size") == 0) {
|
||||
ret = strgetu32(f, &state->block_size);
|
||||
ret = sgetu32(f, &state->block_size);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'block_size' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -129,7 +129,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -142,7 +142,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'q-parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -153,7 +153,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
} else if (strcmp(tag, "content") == 0) {
|
||||
struct snapraid_content* content;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'content' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -166,15 +166,15 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
} else if (strcmp(tag, "disk") == 0) {
|
||||
char dir[PATH_MAX];
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'disk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strgetspace(f);
|
||||
sgetspace(f);
|
||||
|
||||
ret = strgettoken(f, dir, sizeof(dir));
|
||||
ret = sgettok(f, dir, sizeof(dir));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'disk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -184,7 +184,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
} else if (strcmp(tag, "exclude") == 0) {
|
||||
struct snapraid_filter* filter;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'exclude' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -199,7 +199,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
} else if (strcmp(tag, "include") == 0) {
|
||||
struct snapraid_filter* filter;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'include' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -214,37 +214,37 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
} else if (tag[0] == 0) {
|
||||
/* allow empty lines */
|
||||
} else if (tag[0] == '#') {
|
||||
ret = strgetline(f, buffer, sizeof(buffer));
|
||||
ret = sgetline(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid comment in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unknown tag '%s' in '%s' at line %u\n", tag, path, line);
|
||||
fprintf(stderr, "Invalid command '%s' in '%s' at line %u\n", tag, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* skip final spaces */
|
||||
strgetspace(f);
|
||||
sgetspace(f);
|
||||
|
||||
/* next line */
|
||||
c = strgetcnl(f);
|
||||
c = sgeteol(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Extra char '%c' after command specification in '%s' at line %u\n", (char)c, path, line);
|
||||
fprintf(stderr, "Extra data in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
++line;
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
sclose(f);
|
||||
|
||||
if (state->parity[0] == 0) {
|
||||
fprintf(stderr, "No 'parity' specification in '%s'\n", path);
|
||||
|
|
@ -279,7 +279,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
|
||||
void state_read(struct snapraid_state* state)
|
||||
{
|
||||
FILE* f;
|
||||
STREAM* f;
|
||||
char path[PATH_MAX];
|
||||
struct snapraid_disk* disk;
|
||||
struct snapraid_file* file;
|
||||
|
|
@ -305,7 +305,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
printf("Loading state from %s...\n", path);
|
||||
|
||||
f = fopen(path, "rt");
|
||||
f = sopen(path);
|
||||
if (f != 0) {
|
||||
/* if openend stop the search */
|
||||
break;
|
||||
|
|
@ -342,56 +342,24 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
while (1) {
|
||||
char buffer[PATH_MAX];
|
||||
char tag[PATH_MAX];
|
||||
int ret;
|
||||
int cmd;
|
||||
int c;
|
||||
|
||||
/* decode the command */
|
||||
cmd = 0;
|
||||
c = strgetc(f);
|
||||
if (c == 'b') {
|
||||
if (strgetc(f) == 'l' && strgetc(f) == 'k') {
|
||||
c = strgetc(f);
|
||||
if (c == ' ') {
|
||||
cmd = 'b';
|
||||
} else if (c == 's' && strgetc(f) == 'i' && strgetc(f) == 'z' && strgetc(f) == 'e' && strgetc(f) == ' ') {
|
||||
cmd = 's';
|
||||
}
|
||||
}
|
||||
} else if (c == 'i') {
|
||||
if (strgetc(f) == 'n' && strgetc(f) == 'v' && strgetc(f) == ' ') {
|
||||
cmd = 'i';
|
||||
}
|
||||
} else if (c == 'f') {
|
||||
if (strgetc(f) == 'i' && strgetc(f) == 'l' && strgetc(f) == 'e' && strgetc(f) == ' ') {
|
||||
cmd = 'f';
|
||||
}
|
||||
} else if (c == 'c') {
|
||||
if (strgetc(f) == 'h' && strgetc(f) == 'e' && strgetc(f) == 'c' && strgetc(f) == 'k'
|
||||
&& strgetc(f) == 's' && strgetc(f) == 'u' && strgetc(f) == 'm' && strgetc(f) == ' ') {
|
||||
cmd = 'c';
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
} else if (c == '\r') {
|
||||
c = strgetc(f);
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Unexpected carrige return in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (c == '#') {
|
||||
int ret = strgetline(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid comment in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (c == EOF) {
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown char '%c' in '%s' at line %u\n", (char)c, path, line);
|
||||
/* read the command */
|
||||
ret = sgettok(f, tag, sizeof(tag));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (cmd == 'b' || cmd == 'i') {
|
||||
/* skip only one space if present */
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
sungetc(c, f);
|
||||
}
|
||||
|
||||
if (strcmp(tag, "blk") == 0 || strcmp(tag, "inv") == 0) {
|
||||
/* "blk"/"inv" command */
|
||||
block_off_t v_pos;
|
||||
struct snapraid_block* block;
|
||||
|
|
@ -401,7 +369,7 @@ void state_read(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu32(f, &v_pos);
|
||||
ret = sgetu32(f, &v_pos);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -422,10 +390,10 @@ void state_read(struct snapraid_state* state)
|
|||
block->parity_pos = v_pos;
|
||||
|
||||
/* check if we are at the end of the line */
|
||||
c = strgetcnl(f);
|
||||
c = sgeteol(f);
|
||||
if (c == '\n') {
|
||||
/* no hash present */
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
} else {
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
|
|
@ -433,7 +401,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* set the hash only if present */
|
||||
ret = strgethex(f, block->hash, HASH_SIZE);
|
||||
ret = sgethex(f, block->hash, HASH_SIZE);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -443,7 +411,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* set the parity only if present */
|
||||
if (cmd == 'b')
|
||||
if (strcmp(tag, "blk") == 0)
|
||||
block_flag_set(block, BLOCK_HAS_PARITY);
|
||||
|
||||
/* parity implies hash */
|
||||
|
|
@ -465,7 +433,7 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* stat */
|
||||
++count_block;
|
||||
} else if (cmd == 'f') {
|
||||
} else if (strcmp(tag, "file") == 0) {
|
||||
/* file */
|
||||
char buffer[PATH_MAX];
|
||||
char sub[PATH_MAX];
|
||||
|
|
@ -479,55 +447,55 @@ void state_read(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_size);
|
||||
ret = sgetu64(f, &v_size);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_mtime);
|
||||
ret = sgetu64(f, &v_mtime);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_inode);
|
||||
ret = sgetu64(f, &v_inode);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetline(f, sub, sizeof(sub));
|
||||
ret = sgetline(f, sub, sizeof(sub));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -567,8 +535,8 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* stat */
|
||||
++count_file;
|
||||
} else if (cmd == 'c') {
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
} else if (strcmp(tag, "checksum") == 0) {
|
||||
ret = sgettok(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'checksum' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -582,10 +550,10 @@ void state_read(struct snapraid_state* state)
|
|||
fprintf(stderr, "Invalid 'checksum' specification '%s' in '%s' at line %u\n", buffer, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (cmd == 's') {
|
||||
} else if (strcmp(tag, "blksize") == 0) {
|
||||
block_off_t blksize;
|
||||
|
||||
ret = strgetu32(f, &blksize);
|
||||
ret = sgetu32(f, &blksize);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blksize' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -596,21 +564,33 @@ void state_read(struct snapraid_state* state)
|
|||
fprintf(stderr, "Please restore the 'block_size' value in the configuration file to '%u'\n", blksize / 1024);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (tag[0] == 0) {
|
||||
/* allow empty lines */
|
||||
sgetspace(f);
|
||||
} else if (tag[0] == '#') {
|
||||
ret = sgetline(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid comment in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid command '%s' in '%s' at line %u\n", tag, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* next line */
|
||||
c = strgetcnl(f);
|
||||
c = sgeteol(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Extra char '%c' after command specification in '%s' at line %u\n", (char)c, path, line);
|
||||
fprintf(stderr, "Extra data in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
++line;
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error reading the content file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -620,7 +600,7 @@ void state_read(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
sclose(f);
|
||||
|
||||
if (state->verbose) {
|
||||
printf("\tfile %u\n", count_file);
|
||||
|
|
|
|||
208
util.c
208
util.c
|
|
@ -84,28 +84,77 @@ char* strdechex(void* void_data, unsigned data_len, char* str)
|
|||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* get */
|
||||
/* stream */
|
||||
|
||||
int strgettoken(FILE* f, char* s, unsigned size)
|
||||
STREAM* sopen(const char* file)
|
||||
{
|
||||
char* i = s;
|
||||
char* send = s + size;
|
||||
STREAM* s = malloc_nofail(sizeof(STREAM));
|
||||
|
||||
s->f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL);
|
||||
if (s->f == -1) {
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->buffer = malloc_nofail(STREAM_SIZE);
|
||||
s->pos = s->buffer;
|
||||
s->end = s->buffer;
|
||||
s->state = STREAM_OK;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void sclose(STREAM* s)
|
||||
{
|
||||
close(s->f);
|
||||
free(s->buffer);
|
||||
free(s);
|
||||
}
|
||||
|
||||
int sflow(STREAM* s)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
if (s->state != STREAM_OK)
|
||||
return EOF;
|
||||
|
||||
ret = read(s->f, s->buffer, STREAM_SIZE);
|
||||
|
||||
if (ret < 0) {
|
||||
s->state = STREAM_ERROR;
|
||||
return EOF;
|
||||
}
|
||||
if (ret == 0) {
|
||||
s->state = STREAM_EOF;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
s->pos = s->buffer;
|
||||
s->end = s->buffer + ret;
|
||||
|
||||
return *s->pos++;
|
||||
}
|
||||
|
||||
int sgettok(STREAM* f, char* str, int size)
|
||||
{
|
||||
char* i = str;
|
||||
char* send = str + size;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c == ' ' || c == '\t') {
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != s && i[-1] == '\r')
|
||||
if (i != str && i[-1] == '\r')
|
||||
--i;
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -120,29 +169,52 @@ int strgettoken(FILE* f, char* s, unsigned size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int strgetline(FILE* f, char* s, unsigned size)
|
||||
int sgetline(STREAM* f, char* str, int size)
|
||||
{
|
||||
char* i = s;
|
||||
char* send = s + size;
|
||||
char* i = str;
|
||||
char* send = str + size;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = strgetc(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != s && i[-1] == '\r')
|
||||
--i;
|
||||
ungetc(c, f);
|
||||
break;
|
||||
/* if there is enough data in memory */
|
||||
if (sptrlookup(f, size)) {
|
||||
unsigned char* pos = sptrget(f);
|
||||
|
||||
while (1) {
|
||||
c = *pos++;
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != str && i[-1] == '\r')
|
||||
--i;
|
||||
--pos;
|
||||
break;
|
||||
}
|
||||
|
||||
*i++ = c;
|
||||
|
||||
if (i == send)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*i++ = c;
|
||||
sptrset(f, pos);
|
||||
} else {
|
||||
while (1) {
|
||||
c = sgetc(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != str && i[-1] == '\r')
|
||||
--i;
|
||||
sungetc(c, f);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == send)
|
||||
return -1;
|
||||
*i++ = c;
|
||||
|
||||
if (i == send)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*i = 0;
|
||||
|
|
@ -150,26 +222,26 @@ int strgetline(FILE* f, char* s, unsigned size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int strgetu32(FILE* f, uint32_t* value)
|
||||
int sgetu32(STREAM* f, uint32_t* value)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c>='0' && c<='9') {
|
||||
uint32_t v;
|
||||
|
||||
v = c - '0';
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
while (c>='0' && c<='9') {
|
||||
v *= 10;
|
||||
v += c - '0';
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
}
|
||||
|
||||
*value = v;
|
||||
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
return 0;
|
||||
} else {
|
||||
/* nothing read */
|
||||
|
|
@ -177,26 +249,26 @@ int strgetu32(FILE* f, uint32_t* value)
|
|||
}
|
||||
}
|
||||
|
||||
int strgetu64(FILE* f, uint64_t* value)
|
||||
int sgetu64(STREAM* f, uint64_t* value)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c>='0' && c<='9') {
|
||||
uint64_t v;
|
||||
|
||||
v = c - '0';
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
while (c>='0' && c<='9') {
|
||||
v *= 10;
|
||||
v += c - '0';
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
}
|
||||
|
||||
*value = v;
|
||||
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
return 0;
|
||||
} else {
|
||||
/* nothing read */
|
||||
|
|
@ -204,33 +276,63 @@ int strgetu64(FILE* f, uint64_t* value)
|
|||
}
|
||||
}
|
||||
|
||||
int strgethex(FILE* f, void* void_data, unsigned data_len)
|
||||
int sgethex(STREAM* f, void* void_data, int size)
|
||||
{
|
||||
unsigned char* data = void_data;
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<data_len;++i) {
|
||||
unsigned b0;
|
||||
unsigned b1;
|
||||
unsigned b;
|
||||
int c;
|
||||
/* if there is enough data in memory */
|
||||
if (sptrlookup(f, size * 2)) {
|
||||
/* optimized version with all the data in memory */
|
||||
unsigned char* pos = sptrget(f);
|
||||
unsigned x = 0;
|
||||
|
||||
c = strgetc(f);
|
||||
if (c == EOF)
|
||||
while (size--) {
|
||||
unsigned b0;
|
||||
unsigned b1;
|
||||
unsigned b;
|
||||
|
||||
b0 = strdecset[pos[0]];
|
||||
b1 = strdecset[pos[1]];
|
||||
pos += 2;
|
||||
|
||||
b = (b0 << 4) | b1;
|
||||
|
||||
x |= b;
|
||||
|
||||
*data++ = b;
|
||||
}
|
||||
|
||||
/* at the end check if a digit was wrong */
|
||||
if (x > 0xFF) {
|
||||
return -1;
|
||||
b0 = strdecset[c];
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
b1 = strdecset[c];
|
||||
sptrset(f, pos);
|
||||
} else {
|
||||
/* standard version using sgetc() */
|
||||
while (size--) {
|
||||
unsigned b0;
|
||||
unsigned b1;
|
||||
unsigned b;
|
||||
int c;
|
||||
|
||||
b = (b0 << 4) | b1;
|
||||
c = sgetc(f);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
b0 = strdecset[c];
|
||||
|
||||
if (b > 0xFF)
|
||||
return -1;
|
||||
c = sgetc(f);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
b1 = strdecset[c];
|
||||
|
||||
*data++ = b;
|
||||
b = (b0 << 4) | b1;
|
||||
|
||||
if (b > 0xFF)
|
||||
return -1;
|
||||
|
||||
*data++ = b;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
115
util.h
115
util.h
|
|
@ -31,32 +31,105 @@ void strenchex(char* str, const void* void_data, unsigned data_len);
|
|||
*/
|
||||
char* strdechex(void* void_data, unsigned data_len, char* str);
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* get */
|
||||
/* stream */
|
||||
|
||||
#define STREAM_SIZE (64*1024)
|
||||
|
||||
#define STREAM_OK 0
|
||||
#define STREAM_ERROR -1
|
||||
#define STREAM_EOF 1
|
||||
|
||||
struct stream {
|
||||
unsigned char* buffer;
|
||||
unsigned char* pos;
|
||||
unsigned char* end;
|
||||
int state;
|
||||
int f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a char from a stream.
|
||||
* Opaque STREAM type. Like ::FILE.
|
||||
*/
|
||||
static inline int strgetc(FILE* f)
|
||||
typedef struct stream STREAM;
|
||||
|
||||
/**
|
||||
* Open a stream for reading. Like fopen().
|
||||
*/
|
||||
STREAM* sopen(const char* file);
|
||||
|
||||
/**
|
||||
* Close a stream. Like fclose().
|
||||
*/
|
||||
void sclose(STREAM* s);
|
||||
|
||||
/**
|
||||
* Fill the stream buffer and read a char.
|
||||
*/
|
||||
int sflow(STREAM* s);
|
||||
|
||||
/**
|
||||
* Checks if the buffer has enough data loaded.
|
||||
*/
|
||||
static inline int sptrlookup(STREAM* s, int size)
|
||||
{
|
||||
#if HAVE_GETC_UNLOCKED
|
||||
return getc_unlocked(f);
|
||||
#else
|
||||
return getc(f);
|
||||
#endif
|
||||
return s->pos + size <= s->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current stream ptr.
|
||||
*/
|
||||
unsigned char* sptrget(STREAM* s)
|
||||
{
|
||||
return s->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current stream ptr.
|
||||
*/
|
||||
void sptrset(STREAM* s, unsigned char* ptr)
|
||||
{
|
||||
s->pos = ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a char. Like fgetc().
|
||||
*/
|
||||
static inline int sgetc(STREAM* s)
|
||||
{
|
||||
if (s->pos == s->end)
|
||||
return sflow(s);
|
||||
return *s->pos++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unread a char.
|
||||
* Like ungetc() but you have to unget the same char read.
|
||||
*/
|
||||
static inline void sungetc(int c, STREAM* s)
|
||||
{
|
||||
if (c != EOF)
|
||||
--s->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the error status. Like ferror().
|
||||
*/
|
||||
static inline int serror(STREAM* s)
|
||||
{
|
||||
return s->state == STREAM_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a char from a stream, ignoring one '\r'.
|
||||
*/
|
||||
static inline int strgetcnl(FILE* f)
|
||||
static inline int sgeteol(STREAM* f)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
if (c == '\r')
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -65,18 +138,18 @@ static inline int strgetcnl(FILE* f)
|
|||
* Read all the spaces and tabs.
|
||||
* Returns the number of spaces and tabs read.
|
||||
*/
|
||||
static inline int strgetspace(FILE* f)
|
||||
static inline int sgetspace(STREAM* f)
|
||||
{
|
||||
int count = 0;
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
while (c == ' ' || c == '\t') {
|
||||
++count;
|
||||
c = strgetc(f);
|
||||
c = sgetc(f);
|
||||
}
|
||||
|
||||
ungetc(c, f);
|
||||
sungetc(c, f);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
@ -85,34 +158,34 @@ static inline int strgetspace(FILE* f)
|
|||
* Stops at the first ' ', '\t', '\n' or EOF.
|
||||
* Returns error if the buffer is too small.
|
||||
*/
|
||||
int strgettoken(FILE* f, char* str, unsigned size);
|
||||
int sgettok(STREAM* f, char* str, int size);
|
||||
|
||||
/**
|
||||
* Read until the end of line.
|
||||
* Stops at the first '\n' or EOF.
|
||||
* Returns error if the buffer is too small.
|
||||
*/
|
||||
int strgetline(FILE* f, char* str, unsigned size);
|
||||
int sgetline(STREAM* f, char* str, int size);
|
||||
|
||||
/**
|
||||
* Read a 32 bit number.
|
||||
* Stops at the first not digit char or EOF.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgetu32(FILE* f, uint32_t* value);
|
||||
int sgetu32(STREAM* f, uint32_t* value);
|
||||
|
||||
/**
|
||||
* Read a 64 bit number.
|
||||
* Stops at the first not digit char.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgetu64(FILE* f, uint64_t* value);
|
||||
int sgetu64(STREAM* f, uint64_t* value);
|
||||
|
||||
/**
|
||||
* Read an hexadecimal string of fixed length.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgethex(FILE* f, void* void_data, unsigned data_len);
|
||||
int sgethex(STREAM* f, void* data, int size);
|
||||
|
||||
/****************************************************************************/
|
||||
/* path */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue