#include "../strff.h" #include #include #include #include #include #include #include #include /* keys can be defined either with key= or with [key]. The first is the equalform, the second the bracketform. There can be no keyforms after the bracketform. */ static int skip_to_next_line(buffer *b) { int r; char c; for (;;) { r = buffer_getc(b, &c); if (r == 0 || c == '\n') break; if (r < 0) return 0; } return 1; } /* * advances the cursor until it is positioned at the value of a * field. It will look for both the equalform and bracketform of * the field, and returns STRFF_TYPE_BRACKET or STRFF_TYPE_EQUAL * accordingly. If no such field is found, it returns STRFF_TYPE_NONE. * On error, -1 is returned. */ static int seek_field(buffer *b, char *equalform, char *bracketform) { size_t linemax, linelen; char *line; int r; /* bracketform is longer */ linemax = str_len(bracketform) + 1; line = alloca(linemax); linelen = 0; for (;;) { r = buffer_getc(b, line + linelen); if (r < 0) return -1; if (r == 0) break; linelen++; if (byte_starts(line, linelen, bracketform)) { return STRFF_TYPE_BRACKET; } if (line[0] == '[') { /* equalform cannot come after a bracketform */ equalform = NULL; } if (equalform && byte_starts(line, linelen, equalform)){ return STRFF_TYPE_EQUAL; } if (line[linelen-1] == '\n') { /* reset line */ linelen = 0; continue; } if (linelen == linemax) { if (!skip_to_next_line(b)) return -1; linelen = 0; } } /* not found */ return STRFF_TYPE_NONE; } static int to_equalform(char *key, char *result) { size_t l; l = str_copy(result, key); result[l++] = '='; result[l++] = 0; return 1; } static int to_bracketform(char *key, char *result) { size_t l; l = 0; result[l++] = '['; l += str_copy(result + l, key); result[l++] = ']'; result[l++] = '\n'; result[l++] = 0; return 1; } int strff_seek(struct strff *strff, char *key) { char *equalform, *bracketform; int fieldtype; if (str_chr(key, '[') != str_len(key)) { errno = EINVAL; /* key cannot contain '[' */ return 0; } equalform = alloca(str_len(key) + 2); to_equalform(key, equalform); bracketform = alloca(str_len(key) + 4); to_bracketform(key, bracketform); buffer_init(&strff->b, read, strff->fd, strff->buf, sizeof strff->buf); lseek(strff->fd, 0, SEEK_SET); fieldtype = seek_field(&strff->b, equalform, bracketform); if (fieldtype < 0) return 0; strff->fieldtype = fieldtype; if (fieldtype == STRFF_TYPE_NONE) { errno = ENOKEY; return 0; } return 1; }