v1.0
Fork of RGB_Matrix by
ini.c@1:0a1a89c55c7c, 2017-06-20 (annotated)
- Committer:
- perlatecnica
- Date:
- Tue Jun 20 17:53:58 2017 +0000
- Revision:
- 1:0a1a89c55c7c
v1.0;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
perlatecnica | 1:0a1a89c55c7c | 1 | /* inih -- simple .INI file parser |
perlatecnica | 1:0a1a89c55c7c | 2 | |
perlatecnica | 1:0a1a89c55c7c | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project |
perlatecnica | 1:0a1a89c55c7c | 4 | home page for more info: |
perlatecnica | 1:0a1a89c55c7c | 5 | |
perlatecnica | 1:0a1a89c55c7c | 6 | http://code.google.com/p/inih/ |
perlatecnica | 1:0a1a89c55c7c | 7 | |
perlatecnica | 1:0a1a89c55c7c | 8 | */ |
perlatecnica | 1:0a1a89c55c7c | 9 | |
perlatecnica | 1:0a1a89c55c7c | 10 | #include <stdio.h> |
perlatecnica | 1:0a1a89c55c7c | 11 | #include <ctype.h> |
perlatecnica | 1:0a1a89c55c7c | 12 | #include <string.h> |
perlatecnica | 1:0a1a89c55c7c | 13 | |
perlatecnica | 1:0a1a89c55c7c | 14 | #include "ini.h" |
perlatecnica | 1:0a1a89c55c7c | 15 | |
perlatecnica | 1:0a1a89c55c7c | 16 | #define MAX_LINE 200 |
perlatecnica | 1:0a1a89c55c7c | 17 | #define MAX_SECTION 50 |
perlatecnica | 1:0a1a89c55c7c | 18 | #define MAX_NAME 50 |
perlatecnica | 1:0a1a89c55c7c | 19 | |
perlatecnica | 1:0a1a89c55c7c | 20 | /* Strip whitespace chars off end of given string, in place. Return s. */ |
perlatecnica | 1:0a1a89c55c7c | 21 | static char* rstrip(char* s) |
perlatecnica | 1:0a1a89c55c7c | 22 | { |
perlatecnica | 1:0a1a89c55c7c | 23 | char* p = s + strlen(s); |
perlatecnica | 1:0a1a89c55c7c | 24 | while (p > s && isspace(*--p)) |
perlatecnica | 1:0a1a89c55c7c | 25 | *p = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 26 | return s; |
perlatecnica | 1:0a1a89c55c7c | 27 | } |
perlatecnica | 1:0a1a89c55c7c | 28 | |
perlatecnica | 1:0a1a89c55c7c | 29 | /* Return pointer to first non-whitespace char in given string. */ |
perlatecnica | 1:0a1a89c55c7c | 30 | static char* lskip(const char* s) |
perlatecnica | 1:0a1a89c55c7c | 31 | { |
perlatecnica | 1:0a1a89c55c7c | 32 | while (*s && isspace(*s)) |
perlatecnica | 1:0a1a89c55c7c | 33 | s++; |
perlatecnica | 1:0a1a89c55c7c | 34 | return (char*)s; |
perlatecnica | 1:0a1a89c55c7c | 35 | } |
perlatecnica | 1:0a1a89c55c7c | 36 | |
perlatecnica | 1:0a1a89c55c7c | 37 | /* Return pointer to first char c or ';' in given string, or pointer to |
perlatecnica | 1:0a1a89c55c7c | 38 | null at end of string if neither found. */ |
perlatecnica | 1:0a1a89c55c7c | 39 | static char* find_char_or_comment(const char* s, char c) |
perlatecnica | 1:0a1a89c55c7c | 40 | { |
perlatecnica | 1:0a1a89c55c7c | 41 | while (*s && *s != c && *s != ';') |
perlatecnica | 1:0a1a89c55c7c | 42 | s++; |
perlatecnica | 1:0a1a89c55c7c | 43 | return (char*)s; |
perlatecnica | 1:0a1a89c55c7c | 44 | } |
perlatecnica | 1:0a1a89c55c7c | 45 | |
perlatecnica | 1:0a1a89c55c7c | 46 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ |
perlatecnica | 1:0a1a89c55c7c | 47 | static char* strncpy0(char* dest, const char* src, size_t size) |
perlatecnica | 1:0a1a89c55c7c | 48 | { |
perlatecnica | 1:0a1a89c55c7c | 49 | strncpy(dest, src, size); |
perlatecnica | 1:0a1a89c55c7c | 50 | dest[size - 1] = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 51 | return dest; |
perlatecnica | 1:0a1a89c55c7c | 52 | } |
perlatecnica | 1:0a1a89c55c7c | 53 | |
perlatecnica | 1:0a1a89c55c7c | 54 | /* See documentation in header file. */ |
perlatecnica | 1:0a1a89c55c7c | 55 | int ini_parse(const char* filename, |
perlatecnica | 1:0a1a89c55c7c | 56 | int (*handler)(void*, const char*, const char*, const char*), |
perlatecnica | 1:0a1a89c55c7c | 57 | void* user) |
perlatecnica | 1:0a1a89c55c7c | 58 | { |
perlatecnica | 1:0a1a89c55c7c | 59 | /* Uses a fair bit of stack (use heap instead if you need to) */ |
perlatecnica | 1:0a1a89c55c7c | 60 | char line[MAX_LINE]; |
perlatecnica | 1:0a1a89c55c7c | 61 | char section[MAX_SECTION] = ""; |
perlatecnica | 1:0a1a89c55c7c | 62 | char prev_name[MAX_NAME] = ""; |
perlatecnica | 1:0a1a89c55c7c | 63 | |
perlatecnica | 1:0a1a89c55c7c | 64 | FILE* file; |
perlatecnica | 1:0a1a89c55c7c | 65 | char* start; |
perlatecnica | 1:0a1a89c55c7c | 66 | char* end; |
perlatecnica | 1:0a1a89c55c7c | 67 | char* name; |
perlatecnica | 1:0a1a89c55c7c | 68 | char* value; |
perlatecnica | 1:0a1a89c55c7c | 69 | int lineno = 0; |
perlatecnica | 1:0a1a89c55c7c | 70 | int error = 0; |
perlatecnica | 1:0a1a89c55c7c | 71 | |
perlatecnica | 1:0a1a89c55c7c | 72 | file = fopen(filename, "r"); |
perlatecnica | 1:0a1a89c55c7c | 73 | if (!file) |
perlatecnica | 1:0a1a89c55c7c | 74 | return -1; |
perlatecnica | 1:0a1a89c55c7c | 75 | |
perlatecnica | 1:0a1a89c55c7c | 76 | /* Scan through file line by line */ |
perlatecnica | 1:0a1a89c55c7c | 77 | while (fgets(line, sizeof(line), file) != NULL) { |
perlatecnica | 1:0a1a89c55c7c | 78 | lineno++; |
perlatecnica | 1:0a1a89c55c7c | 79 | start = lskip(rstrip(line)); |
perlatecnica | 1:0a1a89c55c7c | 80 | |
perlatecnica | 1:0a1a89c55c7c | 81 | #if INI_ALLOW_MULTILINE |
perlatecnica | 1:0a1a89c55c7c | 82 | if (*prev_name && *start && start > line) { |
perlatecnica | 1:0a1a89c55c7c | 83 | /* Non-black line with leading whitespace, treat as continuation |
perlatecnica | 1:0a1a89c55c7c | 84 | of previous name's value (as per Python ConfigParser). */ |
perlatecnica | 1:0a1a89c55c7c | 85 | if (!handler(user, section, prev_name, start) && !error) |
perlatecnica | 1:0a1a89c55c7c | 86 | error = lineno; |
perlatecnica | 1:0a1a89c55c7c | 87 | } |
perlatecnica | 1:0a1a89c55c7c | 88 | else |
perlatecnica | 1:0a1a89c55c7c | 89 | #endif |
perlatecnica | 1:0a1a89c55c7c | 90 | if (*start == '[') { |
perlatecnica | 1:0a1a89c55c7c | 91 | /* A "[section]" line */ |
perlatecnica | 1:0a1a89c55c7c | 92 | end = find_char_or_comment(start + 1, ']'); |
perlatecnica | 1:0a1a89c55c7c | 93 | if (*end == ']') { |
perlatecnica | 1:0a1a89c55c7c | 94 | *end = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 95 | strncpy0(section, start + 1, sizeof(section)); |
perlatecnica | 1:0a1a89c55c7c | 96 | *prev_name = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 97 | } |
perlatecnica | 1:0a1a89c55c7c | 98 | else if (!error) { |
perlatecnica | 1:0a1a89c55c7c | 99 | /* No ']' found on section line */ |
perlatecnica | 1:0a1a89c55c7c | 100 | error = lineno; |
perlatecnica | 1:0a1a89c55c7c | 101 | } |
perlatecnica | 1:0a1a89c55c7c | 102 | } |
perlatecnica | 1:0a1a89c55c7c | 103 | else if (*start && *start != ';') { |
perlatecnica | 1:0a1a89c55c7c | 104 | /* Not a comment, must be a name=value pair */ |
perlatecnica | 1:0a1a89c55c7c | 105 | end = find_char_or_comment(start, '='); |
perlatecnica | 1:0a1a89c55c7c | 106 | if (*end == '=') { |
perlatecnica | 1:0a1a89c55c7c | 107 | *end = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 108 | name = rstrip(start); |
perlatecnica | 1:0a1a89c55c7c | 109 | value = lskip(end + 1); |
perlatecnica | 1:0a1a89c55c7c | 110 | end = find_char_or_comment(value, ';'); |
perlatecnica | 1:0a1a89c55c7c | 111 | if (*end == ';') |
perlatecnica | 1:0a1a89c55c7c | 112 | *end = '\0'; |
perlatecnica | 1:0a1a89c55c7c | 113 | rstrip(value); |
perlatecnica | 1:0a1a89c55c7c | 114 | |
perlatecnica | 1:0a1a89c55c7c | 115 | /* Valid name=value pair found, call handler */ |
perlatecnica | 1:0a1a89c55c7c | 116 | strncpy0(prev_name, name, sizeof(prev_name)); |
perlatecnica | 1:0a1a89c55c7c | 117 | if (!handler(user, section, name, value) && !error) |
perlatecnica | 1:0a1a89c55c7c | 118 | error = lineno; |
perlatecnica | 1:0a1a89c55c7c | 119 | } |
perlatecnica | 1:0a1a89c55c7c | 120 | else if (!error) { |
perlatecnica | 1:0a1a89c55c7c | 121 | /* No '=' found on name=value line */ |
perlatecnica | 1:0a1a89c55c7c | 122 | error = lineno; |
perlatecnica | 1:0a1a89c55c7c | 123 | } |
perlatecnica | 1:0a1a89c55c7c | 124 | } |
perlatecnica | 1:0a1a89c55c7c | 125 | } |
perlatecnica | 1:0a1a89c55c7c | 126 | |
perlatecnica | 1:0a1a89c55c7c | 127 | fclose(file); |
perlatecnica | 1:0a1a89c55c7c | 128 | |
perlatecnica | 1:0a1a89c55c7c | 129 | return error; |
perlatecnica | 1:0a1a89c55c7c | 130 | } |