The code from https://github.com/vpcola/Nucleo

Committer:
sinrab
Date:
Wed Oct 08 11:00:24 2014 +0000
Revision:
0:5464d5e415e5
The code from https://github.com/vpcola/Nucleo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sinrab 0:5464d5e415e5 1 /* inih -- simple .INI file parser
sinrab 0:5464d5e415e5 2
sinrab 0:5464d5e415e5 3 inih is released under the New BSD license (see LICENSE.txt). Go to the project
sinrab 0:5464d5e415e5 4 home page for more info:
sinrab 0:5464d5e415e5 5
sinrab 0:5464d5e415e5 6 http://code.google.com/p/inih/
sinrab 0:5464d5e415e5 7
sinrab 0:5464d5e415e5 8 */
sinrab 0:5464d5e415e5 9
sinrab 0:5464d5e415e5 10 #include <stdio.h>
sinrab 0:5464d5e415e5 11 #include <ctype.h>
sinrab 0:5464d5e415e5 12 #include <string.h>
sinrab 0:5464d5e415e5 13
sinrab 0:5464d5e415e5 14 #include "ini.h"
sinrab 0:5464d5e415e5 15
sinrab 0:5464d5e415e5 16 #if !INI_USE_STACK
sinrab 0:5464d5e415e5 17 #include <stdlib.h>
sinrab 0:5464d5e415e5 18 #endif
sinrab 0:5464d5e415e5 19
sinrab 0:5464d5e415e5 20 #define MAX_SECTION 50
sinrab 0:5464d5e415e5 21 #define MAX_NAME 50
sinrab 0:5464d5e415e5 22
sinrab 0:5464d5e415e5 23 /* Strip whitespace chars off end of given string, in place. Return s. */
sinrab 0:5464d5e415e5 24 static char* rstrip(char* s)
sinrab 0:5464d5e415e5 25 {
sinrab 0:5464d5e415e5 26 char* p = s + strlen(s);
sinrab 0:5464d5e415e5 27 while (p > s && isspace((unsigned char)(*--p)))
sinrab 0:5464d5e415e5 28 *p = '\0';
sinrab 0:5464d5e415e5 29 return s;
sinrab 0:5464d5e415e5 30 }
sinrab 0:5464d5e415e5 31
sinrab 0:5464d5e415e5 32 /* Return pointer to first non-whitespace char in given string. */
sinrab 0:5464d5e415e5 33 static char* lskip(const char* s)
sinrab 0:5464d5e415e5 34 {
sinrab 0:5464d5e415e5 35 while (*s && isspace((unsigned char)(*s)))
sinrab 0:5464d5e415e5 36 s++;
sinrab 0:5464d5e415e5 37 return (char*)s;
sinrab 0:5464d5e415e5 38 }
sinrab 0:5464d5e415e5 39
sinrab 0:5464d5e415e5 40 /* Return pointer to first char c or ';' comment in given string, or pointer to
sinrab 0:5464d5e415e5 41 null at end of string if neither found. ';' must be prefixed by a whitespace
sinrab 0:5464d5e415e5 42 character to register as a comment. */
sinrab 0:5464d5e415e5 43 static char* find_char_or_comment(const char* s, char c)
sinrab 0:5464d5e415e5 44 {
sinrab 0:5464d5e415e5 45 int was_whitespace = 0;
sinrab 0:5464d5e415e5 46 while (*s && *s != c && !(was_whitespace && *s == ';')) {
sinrab 0:5464d5e415e5 47 was_whitespace = isspace((unsigned char)(*s));
sinrab 0:5464d5e415e5 48 s++;
sinrab 0:5464d5e415e5 49 }
sinrab 0:5464d5e415e5 50 return (char*)s;
sinrab 0:5464d5e415e5 51 }
sinrab 0:5464d5e415e5 52
sinrab 0:5464d5e415e5 53 /* Version of strncpy that ensures dest (size bytes) is null-terminated. */
sinrab 0:5464d5e415e5 54 static char* strncpy0(char* dest, const char* src, size_t size)
sinrab 0:5464d5e415e5 55 {
sinrab 0:5464d5e415e5 56 strncpy(dest, src, size);
sinrab 0:5464d5e415e5 57 dest[size - 1] = '\0';
sinrab 0:5464d5e415e5 58 return dest;
sinrab 0:5464d5e415e5 59 }
sinrab 0:5464d5e415e5 60
sinrab 0:5464d5e415e5 61 /* See documentation in header file. */
sinrab 0:5464d5e415e5 62 int ini_parse_file(FILE* file,
sinrab 0:5464d5e415e5 63 int (*handler)(void*, const char*, const char*,
sinrab 0:5464d5e415e5 64 const char*),
sinrab 0:5464d5e415e5 65 void* user)
sinrab 0:5464d5e415e5 66 {
sinrab 0:5464d5e415e5 67 /* Uses a fair bit of stack (use heap instead if you need to) */
sinrab 0:5464d5e415e5 68 #if INI_USE_STACK
sinrab 0:5464d5e415e5 69 char line[INI_MAX_LINE];
sinrab 0:5464d5e415e5 70 #else
sinrab 0:5464d5e415e5 71 char* line;
sinrab 0:5464d5e415e5 72 #endif
sinrab 0:5464d5e415e5 73 char section[MAX_SECTION] = "";
sinrab 0:5464d5e415e5 74 char prev_name[MAX_NAME] = "";
sinrab 0:5464d5e415e5 75
sinrab 0:5464d5e415e5 76 char* start;
sinrab 0:5464d5e415e5 77 char* end;
sinrab 0:5464d5e415e5 78 char* name;
sinrab 0:5464d5e415e5 79 char* value;
sinrab 0:5464d5e415e5 80 int lineno = 0;
sinrab 0:5464d5e415e5 81 int error = 0;
sinrab 0:5464d5e415e5 82
sinrab 0:5464d5e415e5 83 #if !INI_USE_STACK
sinrab 0:5464d5e415e5 84 line = (char*)malloc(INI_MAX_LINE);
sinrab 0:5464d5e415e5 85 if (!line) {
sinrab 0:5464d5e415e5 86 return -2;
sinrab 0:5464d5e415e5 87 }
sinrab 0:5464d5e415e5 88 #endif
sinrab 0:5464d5e415e5 89
sinrab 0:5464d5e415e5 90 /* Scan through file line by line */
sinrab 0:5464d5e415e5 91 while (fgets(line, INI_MAX_LINE, file) != NULL) {
sinrab 0:5464d5e415e5 92 lineno++;
sinrab 0:5464d5e415e5 93
sinrab 0:5464d5e415e5 94 start = line;
sinrab 0:5464d5e415e5 95 #if INI_ALLOW_BOM
sinrab 0:5464d5e415e5 96 if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
sinrab 0:5464d5e415e5 97 (unsigned char)start[1] == 0xBB &&
sinrab 0:5464d5e415e5 98 (unsigned char)start[2] == 0xBF) {
sinrab 0:5464d5e415e5 99 start += 3;
sinrab 0:5464d5e415e5 100 }
sinrab 0:5464d5e415e5 101 #endif
sinrab 0:5464d5e415e5 102 start = lskip(rstrip(start));
sinrab 0:5464d5e415e5 103
sinrab 0:5464d5e415e5 104 if (*start == ';' || *start == '#') {
sinrab 0:5464d5e415e5 105 /* Per Python ConfigParser, allow '#' comments at start of line */
sinrab 0:5464d5e415e5 106 }
sinrab 0:5464d5e415e5 107 #if INI_ALLOW_MULTILINE
sinrab 0:5464d5e415e5 108 else if (*prev_name && *start && start > line) {
sinrab 0:5464d5e415e5 109 /* Non-black line with leading whitespace, treat as continuation
sinrab 0:5464d5e415e5 110 of previous name's value (as per Python ConfigParser). */
sinrab 0:5464d5e415e5 111 if (!handler(user, section, prev_name, start) && !error)
sinrab 0:5464d5e415e5 112 error = lineno;
sinrab 0:5464d5e415e5 113 }
sinrab 0:5464d5e415e5 114 #endif
sinrab 0:5464d5e415e5 115 else if (*start == '[') {
sinrab 0:5464d5e415e5 116 /* A "[section]" line */
sinrab 0:5464d5e415e5 117 end = find_char_or_comment(start + 1, ']');
sinrab 0:5464d5e415e5 118 if (*end == ']') {
sinrab 0:5464d5e415e5 119 *end = '\0';
sinrab 0:5464d5e415e5 120 strncpy0(section, start + 1, sizeof(section));
sinrab 0:5464d5e415e5 121 *prev_name = '\0';
sinrab 0:5464d5e415e5 122 }
sinrab 0:5464d5e415e5 123 else if (!error) {
sinrab 0:5464d5e415e5 124 /* No ']' found on section line */
sinrab 0:5464d5e415e5 125 error = lineno;
sinrab 0:5464d5e415e5 126 }
sinrab 0:5464d5e415e5 127 }
sinrab 0:5464d5e415e5 128 else if (*start && *start != ';') {
sinrab 0:5464d5e415e5 129 /* Not a comment, must be a name[=:]value pair */
sinrab 0:5464d5e415e5 130 end = find_char_or_comment(start, '=');
sinrab 0:5464d5e415e5 131 if (*end != '=') {
sinrab 0:5464d5e415e5 132 end = find_char_or_comment(start, ':');
sinrab 0:5464d5e415e5 133 }
sinrab 0:5464d5e415e5 134 if (*end == '=' || *end == ':') {
sinrab 0:5464d5e415e5 135 *end = '\0';
sinrab 0:5464d5e415e5 136 name = rstrip(start);
sinrab 0:5464d5e415e5 137 value = lskip(end + 1);
sinrab 0:5464d5e415e5 138 end = find_char_or_comment(value, '\0');
sinrab 0:5464d5e415e5 139 if (*end == ';')
sinrab 0:5464d5e415e5 140 *end = '\0';
sinrab 0:5464d5e415e5 141 rstrip(value);
sinrab 0:5464d5e415e5 142
sinrab 0:5464d5e415e5 143 /* Valid name[=:]value pair found, call handler */
sinrab 0:5464d5e415e5 144 strncpy0(prev_name, name, sizeof(prev_name));
sinrab 0:5464d5e415e5 145 if (!handler(user, section, name, value) && !error)
sinrab 0:5464d5e415e5 146 error = lineno;
sinrab 0:5464d5e415e5 147 }
sinrab 0:5464d5e415e5 148 else if (!error) {
sinrab 0:5464d5e415e5 149 /* No '=' or ':' found on name[=:]value line */
sinrab 0:5464d5e415e5 150 error = lineno;
sinrab 0:5464d5e415e5 151 }
sinrab 0:5464d5e415e5 152 }
sinrab 0:5464d5e415e5 153
sinrab 0:5464d5e415e5 154 #if INI_STOP_ON_FIRST_ERROR
sinrab 0:5464d5e415e5 155 if (error)
sinrab 0:5464d5e415e5 156 break;
sinrab 0:5464d5e415e5 157 #endif
sinrab 0:5464d5e415e5 158 }
sinrab 0:5464d5e415e5 159
sinrab 0:5464d5e415e5 160 #if !INI_USE_STACK
sinrab 0:5464d5e415e5 161 free(line);
sinrab 0:5464d5e415e5 162 #endif
sinrab 0:5464d5e415e5 163
sinrab 0:5464d5e415e5 164 return error;
sinrab 0:5464d5e415e5 165 }
sinrab 0:5464d5e415e5 166
sinrab 0:5464d5e415e5 167 /* See documentation in header file. */
sinrab 0:5464d5e415e5 168 int ini_parse(const char* filename,
sinrab 0:5464d5e415e5 169 int (*handler)(void*, const char*, const char*, const char*),
sinrab 0:5464d5e415e5 170 void* user)
sinrab 0:5464d5e415e5 171 {
sinrab 0:5464d5e415e5 172 FILE* file;
sinrab 0:5464d5e415e5 173 int error;
sinrab 0:5464d5e415e5 174
sinrab 0:5464d5e415e5 175 file = fopen(filename, "r");
sinrab 0:5464d5e415e5 176 if (!file)
sinrab 0:5464d5e415e5 177 return -1;
sinrab 0:5464d5e415e5 178 error = ini_parse_file(file, handler, user);
sinrab 0:5464d5e415e5 179 fclose(file);
sinrab 0:5464d5e415e5 180 return error;
sinrab 0:5464d5e415e5 181 }
sinrab 0:5464d5e415e5 182