Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ini.c
00001 /* inih -- simple .INI file parser 00002 00003 inih is released under the New BSD license (see LICENSE.txt). Go to the project 00004 home page for more info: 00005 00006 http://code.google.com/p/inih/ 00007 00008 */ 00009 00010 #include <stdio.h> 00011 #include <ctype.h> 00012 #include <string.h> 00013 00014 #include "ini.h" 00015 00016 #if !INI_USE_STACK 00017 #include <stdlib.h> 00018 #endif 00019 00020 #define MAX_SECTION 50 00021 #define MAX_NAME 50 00022 00023 /* Strip whitespace chars off end of given string, in place. Return s. */ 00024 static char* rstrip(char* s) 00025 { 00026 char* p = s + strlen(s); 00027 while (p > s && isspace((unsigned char)(*--p))) 00028 *p = '\0'; 00029 return s; 00030 } 00031 00032 /* Return pointer to first non-whitespace char in given string. */ 00033 static char* lskip(const char* s) 00034 { 00035 while (*s && isspace((unsigned char)(*s))) 00036 s++; 00037 return (char*)s; 00038 } 00039 00040 /* Return pointer to first char c or ';' comment in given string, or pointer to 00041 null at end of string if neither found. ';' must be prefixed by a whitespace 00042 character to register as a comment. */ 00043 static char* find_char_or_comment(const char* s, char c) 00044 { 00045 int was_whitespace = 0; 00046 while (*s && *s != c && !(was_whitespace && *s == ';')) { 00047 was_whitespace = isspace((unsigned char)(*s)); 00048 s++; 00049 } 00050 return (char*)s; 00051 } 00052 00053 /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 00054 static char* strncpy0(char* dest, const char* src, size_t size) 00055 { 00056 strncpy(dest, src, size); 00057 dest[size - 1] = '\0'; 00058 return dest; 00059 } 00060 00061 /* See documentation in header file. */ 00062 int ini_parse_file(FILE* file, 00063 int (*handler)(void*, const char*, const char*, 00064 const char*), 00065 void* user) 00066 { 00067 /* Uses a fair bit of stack (use heap instead if you need to) */ 00068 #if INI_USE_STACK 00069 char line[INI_MAX_LINE]; 00070 #else 00071 char* line; 00072 #endif 00073 char section[MAX_SECTION] = ""; 00074 char prev_name[MAX_NAME] = ""; 00075 00076 char* start; 00077 char* end; 00078 char* name; 00079 char* value; 00080 int lineno = 0; 00081 int error = 0; 00082 00083 #if !INI_USE_STACK 00084 line = (char*)malloc(INI_MAX_LINE); 00085 if (!line) { 00086 return -2; 00087 } 00088 #endif 00089 00090 /* Scan through file line by line */ 00091 while (fgets(line, INI_MAX_LINE, file) != NULL) { 00092 lineno++; 00093 00094 start = line; 00095 #if INI_ALLOW_BOM 00096 if (lineno == 1 && (unsigned char)start[0] == 0xEF && 00097 (unsigned char)start[1] == 0xBB && 00098 (unsigned char)start[2] == 0xBF) { 00099 start += 3; 00100 } 00101 #endif 00102 start = lskip(rstrip(start)); 00103 00104 if (*start == ';' || *start == '#') { 00105 /* Per Python ConfigParser, allow '#' comments at start of line */ 00106 } 00107 #if INI_ALLOW_MULTILINE 00108 else if (*prev_name && *start && start > line) { 00109 /* Non-black line with leading whitespace, treat as continuation 00110 of previous name's value (as per Python ConfigParser). */ 00111 if (!handler(user, section, prev_name, start) && !error) 00112 error = lineno; 00113 } 00114 #endif 00115 else if (*start == '[') { 00116 /* A "[section]" line */ 00117 end = find_char_or_comment(start + 1, ']'); 00118 if (*end == ']') { 00119 *end = '\0'; 00120 strncpy0(section, start + 1, sizeof(section)); 00121 *prev_name = '\0'; 00122 } 00123 else if (!error) { 00124 /* No ']' found on section line */ 00125 error = lineno; 00126 } 00127 } 00128 else if (*start && *start != ';') { 00129 /* Not a comment, must be a name[=:]value pair */ 00130 end = find_char_or_comment(start, '='); 00131 if (*end != '=') { 00132 end = find_char_or_comment(start, ':'); 00133 } 00134 if (*end == '=' || *end == ':') { 00135 *end = '\0'; 00136 name = rstrip(start); 00137 value = lskip(end + 1); 00138 end = find_char_or_comment(value, '\0'); 00139 if (*end == ';') 00140 *end = '\0'; 00141 rstrip(value); 00142 00143 /* Valid name[=:]value pair found, call handler */ 00144 strncpy0(prev_name, name, sizeof(prev_name)); 00145 if (!handler(user, section, name, value) && !error) 00146 error = lineno; 00147 } 00148 else if (!error) { 00149 /* No '=' or ':' found on name[=:]value line */ 00150 error = lineno; 00151 } 00152 } 00153 00154 #if INI_STOP_ON_FIRST_ERROR 00155 if (error) 00156 break; 00157 #endif 00158 } 00159 00160 #if !INI_USE_STACK 00161 free(line); 00162 #endif 00163 00164 return error; 00165 } 00166 00167 /* See documentation in header file. */ 00168 int ini_parse(const char* filename, 00169 int (*handler)(void*, const char*, const char*, const char*), 00170 void* user) 00171 { 00172 FILE* file; 00173 int error; 00174 00175 file = fopen(filename, "r"); 00176 if (!file) 00177 return -1; 00178 error = ini_parse_file(file, handler, user); 00179 fclose(file); 00180 return error; 00181 } 00182
Generated on Tue Jul 12 2022 18:55:01 by
1.7.2