A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Committer:
WiredHome
Date:
Sun Dec 11 14:05:17 2016 +0000
Revision:
15:3fc2b87a234d
Parent:
13:d5957065d066
Child:
18:282ed56d983b
Add methods for iterating over sections and keys

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:ae5bf432c249 1 // Simple INI file manager.
WiredHome 0:ae5bf432c249 2 //
WiredHome 0:ae5bf432c249 3 #ifdef WIN32
WiredHome 0:ae5bf432c249 4 #include "string.h"
WiredHome 0:ae5bf432c249 5 #include "stdlib.h"
WiredHome 0:ae5bf432c249 6 #include "stdio.h"
WiredHome 0:ae5bf432c249 7 #else
WiredHome 0:ae5bf432c249 8 #include "mbed.h"
WiredHome 0:ae5bf432c249 9 #endif
WiredHome 0:ae5bf432c249 10
WiredHome 0:ae5bf432c249 11 #include "IniManager.h"
WiredHome 0:ae5bf432c249 12
WiredHome 13:d5957065d066 13 //#include "Utility.h" // private memory manager
WiredHome 11:738604f18088 14 #ifndef UTILITY_H
WiredHome 11:738604f18088 15 #define swMalloc malloc // use the standard
WiredHome 11:738604f18088 16 #define swFree free
WiredHome 11:738604f18088 17 #endif
WiredHome 11:738604f18088 18
WiredHome 8:f128b10dfab1 19 //#define DEBUG "INI " //Debug is disabled by default
WiredHome 1:1e2ee9bbee40 20
WiredHome 8:f128b10dfab1 21 #include <cstdio>
WiredHome 1:1e2ee9bbee40 22 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 8:f128b10dfab1 23 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 8:f128b10dfab1 24 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 8:f128b10dfab1 25 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 8:f128b10dfab1 26 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 1:1e2ee9bbee40 27 #else
WiredHome 1:1e2ee9bbee40 28 #define DBG(x, ...)
WiredHome 1:1e2ee9bbee40 29 #define WARN(x, ...)
WiredHome 1:1e2ee9bbee40 30 #define ERR(x, ...)
WiredHome 1:1e2ee9bbee40 31 #define INFO(x, ...)
WiredHome 1:1e2ee9bbee40 32 #endif
WiredHome 1:1e2ee9bbee40 33
WiredHome 0:ae5bf432c249 34 INI::INI(const char * file)
WiredHome 0:ae5bf432c249 35 : iniFile(0)
WiredHome 0:ae5bf432c249 36 {
WiredHome 7:60f5dc3467ff 37 SetFile(file);
WiredHome 0:ae5bf432c249 38 }
WiredHome 0:ae5bf432c249 39
WiredHome 0:ae5bf432c249 40
WiredHome 0:ae5bf432c249 41 INI::~INI(void)
WiredHome 0:ae5bf432c249 42 {
WiredHome 0:ae5bf432c249 43 if (iniFile)
WiredHome 11:738604f18088 44 swFree(iniFile);
WiredHome 0:ae5bf432c249 45 }
WiredHome 0:ae5bf432c249 46
WiredHome 0:ae5bf432c249 47
WiredHome 15:3fc2b87a234d 48 bool INI::GetNextSection(const char * after, char * buffer, size_t bufferSize) {
WiredHome 15:3fc2b87a234d 49 bool returnNext = false;
WiredHome 15:3fc2b87a234d 50 bool found = false;
WiredHome 15:3fc2b87a234d 51
WiredHome 15:3fc2b87a234d 52 if (!iniFile)
WiredHome 15:3fc2b87a234d 53 return found;
WiredHome 15:3fc2b87a234d 54 CleanUp();
WiredHome 15:3fc2b87a234d 55 INFO("GetNextSection after [%s]", after);
WiredHome 15:3fc2b87a234d 56 FILE * fp = fopen(iniFile,"rt");
WiredHome 15:3fc2b87a234d 57 if (fp) {
WiredHome 15:3fc2b87a234d 58 char buf[INTERNAL_BUF_SIZE];
WiredHome 15:3fc2b87a234d 59
WiredHome 15:3fc2b87a234d 60 if (after == NULL || *after == '\0')
WiredHome 15:3fc2b87a234d 61 returnNext = true;
WiredHome 15:3fc2b87a234d 62 while(fgets(buf, sizeof(buf), fp)) {
WiredHome 15:3fc2b87a234d 63 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 15:3fc2b87a234d 64 while (x >= 0 && buf[x] < ' ')
WiredHome 15:3fc2b87a234d 65 buf[x--] = '\0';
WiredHome 15:3fc2b87a234d 66 INFO(" reading \"%s\"", buf);
WiredHome 15:3fc2b87a234d 67 if (buf[0] == '[') {
WiredHome 15:3fc2b87a234d 68 char * pStart = buf + 1;
WiredHome 15:3fc2b87a234d 69 char * pRBrkt = strchr(buf, ']');
WiredHome 15:3fc2b87a234d 70 if (pRBrkt) {
WiredHome 15:3fc2b87a234d 71 *pRBrkt = '\0';
WiredHome 15:3fc2b87a234d 72 if (returnNext) {
WiredHome 15:3fc2b87a234d 73 if (strlen(pStart) < bufferSize) {
WiredHome 15:3fc2b87a234d 74 strcpy(buffer, pStart);
WiredHome 15:3fc2b87a234d 75 found = true;
WiredHome 15:3fc2b87a234d 76 break;
WiredHome 15:3fc2b87a234d 77 }
WiredHome 15:3fc2b87a234d 78 } else if (strcmp(after, pStart) == 0) {
WiredHome 15:3fc2b87a234d 79 returnNext = true;
WiredHome 15:3fc2b87a234d 80 }
WiredHome 15:3fc2b87a234d 81 }
WiredHome 15:3fc2b87a234d 82 }
WiredHome 15:3fc2b87a234d 83 }
WiredHome 15:3fc2b87a234d 84 fclose(fp);
WiredHome 15:3fc2b87a234d 85 }
WiredHome 15:3fc2b87a234d 86 return found;
WiredHome 15:3fc2b87a234d 87 }
WiredHome 15:3fc2b87a234d 88
WiredHome 15:3fc2b87a234d 89
WiredHome 15:3fc2b87a234d 90 bool INI::GetNextKey(const char * Section, const char * after, char * buffer, size_t bufferSize) {
WiredHome 15:3fc2b87a234d 91 bool returnNext = false;
WiredHome 15:3fc2b87a234d 92 bool inSection = false;
WiredHome 15:3fc2b87a234d 93 bool found = false;
WiredHome 15:3fc2b87a234d 94
WiredHome 15:3fc2b87a234d 95 if (!iniFile)
WiredHome 15:3fc2b87a234d 96 return found;
WiredHome 15:3fc2b87a234d 97 CleanUp();
WiredHome 15:3fc2b87a234d 98 INFO("GetNextLey after [%s]", after);
WiredHome 15:3fc2b87a234d 99 FILE * fp = fopen(iniFile,"rt");
WiredHome 15:3fc2b87a234d 100 if (fp) {
WiredHome 15:3fc2b87a234d 101 char buf[INTERNAL_BUF_SIZE];
WiredHome 15:3fc2b87a234d 102
WiredHome 15:3fc2b87a234d 103 if (after == NULL || *after == '\0')
WiredHome 15:3fc2b87a234d 104 returnNext = true;
WiredHome 15:3fc2b87a234d 105 while(fgets(buf, sizeof(buf), fp)) {
WiredHome 15:3fc2b87a234d 106 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 15:3fc2b87a234d 107 while (x >= 0 && buf[x] < ' ')
WiredHome 15:3fc2b87a234d 108 buf[x--] = '\0';
WiredHome 15:3fc2b87a234d 109 INFO(" reading \"%s\"", buf);
WiredHome 15:3fc2b87a234d 110 if (!(buf[0] == '[' || (buf[0] >= 'A' && buf[0] <= 'Z') || (buf[0] >= 'a' && buf[0] <= 'z')))
WiredHome 15:3fc2b87a234d 111 continue;
WiredHome 15:3fc2b87a234d 112 if (buf[0] == '[') {
WiredHome 15:3fc2b87a234d 113 char * pStart = buf + 1;
WiredHome 15:3fc2b87a234d 114 char * pRBrkt = strchr(buf, ']');
WiredHome 15:3fc2b87a234d 115 if (pRBrkt) {
WiredHome 15:3fc2b87a234d 116 *pRBrkt = '\0';
WiredHome 15:3fc2b87a234d 117 if (inSection == true) { // section after wanted, so done.
WiredHome 15:3fc2b87a234d 118 break;
WiredHome 15:3fc2b87a234d 119 } else if (strcmp(pStart, Section) == 0) {
WiredHome 15:3fc2b87a234d 120 inSection = true;
WiredHome 15:3fc2b87a234d 121 continue;
WiredHome 15:3fc2b87a234d 122 }
WiredHome 15:3fc2b87a234d 123 }
WiredHome 15:3fc2b87a234d 124 } else if (inSection) {
WiredHome 15:3fc2b87a234d 125 char * pStart = buf;
WiredHome 15:3fc2b87a234d 126 char * pEqual = strchr(pStart, '=');
WiredHome 15:3fc2b87a234d 127 if (pEqual) {
WiredHome 15:3fc2b87a234d 128 *pEqual = '\0';
WiredHome 15:3fc2b87a234d 129 if (returnNext) {
WiredHome 15:3fc2b87a234d 130 if (strlen(pStart) < bufferSize) {
WiredHome 15:3fc2b87a234d 131 strcpy(buffer, pStart);
WiredHome 15:3fc2b87a234d 132 found = true;
WiredHome 15:3fc2b87a234d 133 break;
WiredHome 15:3fc2b87a234d 134 }
WiredHome 15:3fc2b87a234d 135 } else if (strcmp(after, pStart) == 0) {
WiredHome 15:3fc2b87a234d 136 returnNext = true;
WiredHome 15:3fc2b87a234d 137 }
WiredHome 15:3fc2b87a234d 138 }
WiredHome 15:3fc2b87a234d 139 }
WiredHome 15:3fc2b87a234d 140 }
WiredHome 15:3fc2b87a234d 141 fclose(fp);
WiredHome 15:3fc2b87a234d 142 }
WiredHome 15:3fc2b87a234d 143 return found;
WiredHome 15:3fc2b87a234d 144 }
WiredHome 15:3fc2b87a234d 145
WiredHome 15:3fc2b87a234d 146
WiredHome 8:f128b10dfab1 147 bool INI::Exists(const char * file)
WiredHome 8:f128b10dfab1 148 {
WiredHome 8:f128b10dfab1 149 if (file == NULL)
WiredHome 8:f128b10dfab1 150 file = iniFile;
WiredHome 8:f128b10dfab1 151 INFO("Exists(%s)", file);
WiredHome 8:f128b10dfab1 152 FILE * fp = fopen(file, "r");
WiredHome 8:f128b10dfab1 153 if (fp) {
WiredHome 8:f128b10dfab1 154 fclose(fp);
WiredHome 8:f128b10dfab1 155 INFO(" [%s] exists", file);
WiredHome 8:f128b10dfab1 156 return true;
WiredHome 8:f128b10dfab1 157 } else {
WiredHome 8:f128b10dfab1 158 INFO(" [%s] does not exist", file);
WiredHome 8:f128b10dfab1 159 return false;
WiredHome 8:f128b10dfab1 160 }
WiredHome 8:f128b10dfab1 161 }
WiredHome 8:f128b10dfab1 162
WiredHome 8:f128b10dfab1 163
WiredHome 5:bfeb0882bd82 164 bool INI::SetFile(const char * file)
WiredHome 5:bfeb0882bd82 165 {
WiredHome 8:f128b10dfab1 166 INFO("SetFile(%s)", file);
WiredHome 5:bfeb0882bd82 167 if (file) {
WiredHome 5:bfeb0882bd82 168 if (iniFile)
WiredHome 11:738604f18088 169 swFree(iniFile);
WiredHome 11:738604f18088 170 iniFile = (char *)swMalloc(strlen(file)+1);
WiredHome 5:bfeb0882bd82 171 if (iniFile) {
WiredHome 5:bfeb0882bd82 172 strcpy(iniFile, file);
WiredHome 8:f128b10dfab1 173 INFO(" SetFile(%s) success", iniFile);
WiredHome 5:bfeb0882bd82 174 return true;
WiredHome 5:bfeb0882bd82 175 }
WiredHome 8:f128b10dfab1 176 else {
WiredHome 8:f128b10dfab1 177 iniFile = NULL;
WiredHome 8:f128b10dfab1 178 ERR(" SetFile(%s) failed to allocate memory", file);
WiredHome 8:f128b10dfab1 179 }
WiredHome 5:bfeb0882bd82 180 }
WiredHome 5:bfeb0882bd82 181 return false;
WiredHome 5:bfeb0882bd82 182 }
WiredHome 5:bfeb0882bd82 183
WiredHome 0:ae5bf432c249 184 bool INI::ReadString(const char * section, const char * key, char * buffer, size_t bufferSize, const char * defaultString)
WiredHome 0:ae5bf432c249 185 {
WiredHome 0:ae5bf432c249 186 bool found = false;
WiredHome 0:ae5bf432c249 187 if (!iniFile)
WiredHome 0:ae5bf432c249 188 return found;
WiredHome 8:f128b10dfab1 189 CleanUp();
WiredHome 8:f128b10dfab1 190 INFO("ReadString from %s", iniFile);
WiredHome 0:ae5bf432c249 191 FILE * fp = fopen(iniFile,"rt");
WiredHome 0:ae5bf432c249 192 if (fp) {
WiredHome 0:ae5bf432c249 193 char buf[INTERNAL_BUF_SIZE];
WiredHome 0:ae5bf432c249 194 bool inSection = (section == NULL) ? true : false;
WiredHome 0:ae5bf432c249 195
WiredHome 0:ae5bf432c249 196 while(fgets(buf, sizeof(buf), fp)) {
WiredHome 0:ae5bf432c249 197 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 0:ae5bf432c249 198 while (x >= 0 && buf[x] < ' ')
WiredHome 0:ae5bf432c249 199 buf[x--] = '\0';
WiredHome 8:f128b10dfab1 200 INFO(" reading \"%s\"", buf);
WiredHome 15:3fc2b87a234d 201 if (!(buf[0] == '[' || (buf[0] >= 'A' && buf[0] <= 'Z') || (buf[0] >= 'a' && buf[0] <= 'z')))
WiredHome 15:3fc2b87a234d 202 continue;
WiredHome 15:3fc2b87a234d 203
WiredHome 0:ae5bf432c249 204 if (inSection && buf[0] != '[') {
WiredHome 0:ae5bf432c249 205 char * eq = strchr(buf, '=');
WiredHome 0:ae5bf432c249 206 if (eq) {
WiredHome 0:ae5bf432c249 207 *eq++ = '\0';
WiredHome 0:ae5bf432c249 208 if ( (strcmp(buf,key) == 0) && (strlen(eq) <= bufferSize) ) {
WiredHome 0:ae5bf432c249 209 strcpy(buffer, eq);
WiredHome 0:ae5bf432c249 210 memset(buf, 0, INTERNAL_BUF_SIZE); // secure the memory space
WiredHome 0:ae5bf432c249 211 found = true;
WiredHome 0:ae5bf432c249 212 break;
WiredHome 0:ae5bf432c249 213 }
WiredHome 0:ae5bf432c249 214 }
WiredHome 0:ae5bf432c249 215 } else {
WiredHome 0:ae5bf432c249 216 if (buf[0] == '[') {
WiredHome 0:ae5bf432c249 217 char * br = strchr(buf, ']');
WiredHome 0:ae5bf432c249 218 inSection = false;
WiredHome 0:ae5bf432c249 219 if (br) {
WiredHome 0:ae5bf432c249 220 *br = '\0';
WiredHome 0:ae5bf432c249 221 if (strcmp(buf+1, section) == 0)
WiredHome 0:ae5bf432c249 222 inSection = true;
WiredHome 0:ae5bf432c249 223 }
WiredHome 0:ae5bf432c249 224 }
WiredHome 0:ae5bf432c249 225 }
WiredHome 0:ae5bf432c249 226 }
WiredHome 0:ae5bf432c249 227 fclose(fp);
WiredHome 0:ae5bf432c249 228 }
WiredHome 0:ae5bf432c249 229 if (!found && defaultString != NULL && *defaultString) {
WiredHome 0:ae5bf432c249 230 strncpy(buffer, defaultString, bufferSize);
WiredHome 0:ae5bf432c249 231 buffer[bufferSize-1] = '\0';
WiredHome 8:f128b10dfab1 232 INFO(" sub %s.", buffer);
WiredHome 0:ae5bf432c249 233 found = true;
WiredHome 0:ae5bf432c249 234 }
WiredHome 0:ae5bf432c249 235 return found;
WiredHome 0:ae5bf432c249 236 }
WiredHome 0:ae5bf432c249 237
WiredHome 12:6cf929bde139 238 long int INI::ReadLongInt(const char * section, const char * key, long int defaultValue)
WiredHome 12:6cf929bde139 239 {
WiredHome 12:6cf929bde139 240 char localBuf[16];
WiredHome 12:6cf929bde139 241
WiredHome 12:6cf929bde139 242 if (ReadString(section, key, localBuf, sizeof(localBuf))) {
WiredHome 12:6cf929bde139 243 return atol(localBuf);
WiredHome 12:6cf929bde139 244 } else {
WiredHome 12:6cf929bde139 245 return defaultValue;
WiredHome 12:6cf929bde139 246 }
WiredHome 12:6cf929bde139 247 }
WiredHome 12:6cf929bde139 248
WiredHome 8:f128b10dfab1 249 bool INI::CleanUp()
WiredHome 0:ae5bf432c249 250 {
WiredHome 11:738604f18088 251 char * newFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 11:738604f18088 252 char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 253
WiredHome 0:ae5bf432c249 254 if (newFile && bakFile) {
WiredHome 8:f128b10dfab1 255 INFO("CleanUp");
WiredHome 0:ae5bf432c249 256 strcpy(bakFile, iniFile);
WiredHome 0:ae5bf432c249 257 strcpy(newFile, iniFile);
WiredHome 0:ae5bf432c249 258 strcpy(bakFile + strlen(bakFile) - 4, ".bak");
WiredHome 0:ae5bf432c249 259 strcpy(newFile + strlen(newFile) - 4, ".new");
WiredHome 0:ae5bf432c249 260
WiredHome 8:f128b10dfab1 261 if (Exists(newFile)) {
WiredHome 2:c63a794c1fee 262 int i;
WiredHome 9:4947b8c244e9 263 i = i; // suppress warning about i not used when !DEBUG
WiredHome 0:ae5bf432c249 264 // helps recover if the system crashed before it could swap in the new file
WiredHome 8:f128b10dfab1 265 INFO(" *** found %s, repairing ...", newFile);
WiredHome 0:ae5bf432c249 266 i = remove(bakFile); // remove an old .bak
WiredHome 8:f128b10dfab1 267 INFO(" remove(%s) returned %d", bakFile, i);
WiredHome 0:ae5bf432c249 268 i = Rename(iniFile, bakFile); // move the existing .ini to .bak
WiredHome 8:f128b10dfab1 269 INFO(" rename(%s,%s) returned %d", iniFile, bakFile, i);
WiredHome 0:ae5bf432c249 270 i = Rename(newFile, iniFile); // move the new .new to .ini
WiredHome 8:f128b10dfab1 271 INFO(" rename(%s,%s) returned %d", newFile, iniFile, i);
WiredHome 8:f128b10dfab1 272 } else {
WiredHome 8:f128b10dfab1 273 // nothing to do, move on silently.
WiredHome 0:ae5bf432c249 274 }
WiredHome 0:ae5bf432c249 275 }
WiredHome 11:738604f18088 276 swFree(newFile);
WiredHome 11:738604f18088 277 swFree(bakFile);
WiredHome 0:ae5bf432c249 278 return true;
WiredHome 0:ae5bf432c249 279 }
WiredHome 0:ae5bf432c249 280
WiredHome 0:ae5bf432c249 281 // Create the new version as .new
WiredHome 0:ae5bf432c249 282 // once complete, if something actually changed, then rename the .ini to .bak and rename the .new to .ini
WiredHome 0:ae5bf432c249 283 // once complete, if nothing actually changed, then delete the .new
WiredHome 0:ae5bf432c249 284 //
WiredHome 10:57b93035ad82 285 bool INI::WriteString(const char * section, const char * key, const char * value)
WiredHome 0:ae5bf432c249 286 {
WiredHome 0:ae5bf432c249 287 bool found = false;
WiredHome 0:ae5bf432c249 288 bool fileChanged = false;
WiredHome 0:ae5bf432c249 289
WiredHome 8:f128b10dfab1 290 INFO("WriteString(%s,%s,%s)", section, key, value);
WiredHome 0:ae5bf432c249 291 if (!iniFile || (value != NULL && strlen(value) > INTERNAL_BUF_SIZE))
WiredHome 0:ae5bf432c249 292 return found;
WiredHome 0:ae5bf432c249 293
WiredHome 11:738604f18088 294 char * newFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 11:738604f18088 295 char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 296 if (!newFile)
WiredHome 0:ae5bf432c249 297 return found; // no memory
WiredHome 0:ae5bf432c249 298 if (!bakFile) {
WiredHome 11:738604f18088 299 swFree(newFile);
WiredHome 0:ae5bf432c249 300 return found;
WiredHome 0:ae5bf432c249 301 }
WiredHome 0:ae5bf432c249 302 strcpy(bakFile, iniFile);
WiredHome 0:ae5bf432c249 303 strcpy(newFile, iniFile);
WiredHome 0:ae5bf432c249 304 strcpy(bakFile + strlen(bakFile) - 4, ".bak");
WiredHome 0:ae5bf432c249 305 strcpy(newFile + strlen(newFile) - 4, ".new");
WiredHome 0:ae5bf432c249 306
WiredHome 8:f128b10dfab1 307 CleanUp();
WiredHome 0:ae5bf432c249 308
WiredHome 8:f128b10dfab1 309 INFO(" Opening [%s] and [%s]", iniFile, newFile);
WiredHome 0:ae5bf432c249 310 FILE * fi = fopen(iniFile, "rt");
WiredHome 0:ae5bf432c249 311 FILE * fo = fopen(newFile, "wt");
WiredHome 0:ae5bf432c249 312 if (fo) {
WiredHome 0:ae5bf432c249 313 char buf[INTERNAL_BUF_SIZE];
WiredHome 0:ae5bf432c249 314 bool inSection = (section == NULL) ? true : false;
WiredHome 0:ae5bf432c249 315
WiredHome 0:ae5bf432c249 316 if (fi) {
WiredHome 8:f128b10dfab1 317 INFO(" %s opened for reading", iniFile);
WiredHome 0:ae5bf432c249 318 while(fgets(buf, sizeof(buf), fi)) {
WiredHome 0:ae5bf432c249 319 // if not inSection, copy across
WiredHome 0:ae5bf432c249 320 // if inSection and not key, copy across
WiredHome 0:ae5bf432c249 321 // if InSection and key, write new value (or skip if value is null)
WiredHome 0:ae5bf432c249 322 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 0:ae5bf432c249 323 while (x >= 0 && buf[x] < ' ')
WiredHome 0:ae5bf432c249 324 buf[x--] = '\0';
WiredHome 8:f128b10dfab1 325
WiredHome 0:ae5bf432c249 326 if (inSection && buf[0] != '[') {
WiredHome 0:ae5bf432c249 327 char * eq = strchr(buf, '=');
WiredHome 0:ae5bf432c249 328 if (eq) {
WiredHome 0:ae5bf432c249 329 *eq++ = '\0';
WiredHome 0:ae5bf432c249 330 if (strcmp(buf,key) == 0) {
WiredHome 0:ae5bf432c249 331 if (value != NULL && strcmp(eq, value) != 0) {
WiredHome 0:ae5bf432c249 332 // replace the old record
WiredHome 0:ae5bf432c249 333 if (value != NULL) {
WiredHome 0:ae5bf432c249 334 fprintf(fo, "%s=%s\n", key, value);
WiredHome 0:ae5bf432c249 335 printf("write: %s=%s\r\n", key, value);
WiredHome 8:f128b10dfab1 336 INFO(" write: %s=%s", key, value);
WiredHome 0:ae5bf432c249 337 }
WiredHome 0:ae5bf432c249 338 }
WiredHome 0:ae5bf432c249 339 fileChanged = true;
WiredHome 0:ae5bf432c249 340 inSection = false;
WiredHome 0:ae5bf432c249 341 found = true;
WiredHome 0:ae5bf432c249 342 } else {
WiredHome 0:ae5bf432c249 343 // write old record
WiredHome 0:ae5bf432c249 344 fprintf(fo, "%s=%s\n", buf, eq);
WiredHome 8:f128b10dfab1 345 INFO(" write: %s=%s", buf, eq);
WiredHome 0:ae5bf432c249 346 }
WiredHome 0:ae5bf432c249 347 } else {
WiredHome 0:ae5bf432c249 348 // what to do with unknown record(s)?
WiredHome 0:ae5bf432c249 349 // fprintf(fo, "%s\n", buf); // eliminate them
WiredHome 0:ae5bf432c249 350 }
WiredHome 0:ae5bf432c249 351 } else {
WiredHome 0:ae5bf432c249 352 if (buf[0] == '[') {
WiredHome 0:ae5bf432c249 353 char * br = strchr(buf, ']');
WiredHome 0:ae5bf432c249 354 if (inSection) { // found next section while in good section
WiredHome 0:ae5bf432c249 355 // Append new record to desired section
WiredHome 0:ae5bf432c249 356 if (value != NULL) {
WiredHome 0:ae5bf432c249 357 fprintf(fo, "%s=%s\r\n", key, value);
WiredHome 8:f128b10dfab1 358 INFO(" write: %s=%s", key, value);
WiredHome 0:ae5bf432c249 359 fileChanged = true;
WiredHome 0:ae5bf432c249 360 }
WiredHome 0:ae5bf432c249 361 found = true;
WiredHome 0:ae5bf432c249 362 }
WiredHome 0:ae5bf432c249 363 inSection = false;
WiredHome 0:ae5bf432c249 364 // write old record
WiredHome 0:ae5bf432c249 365 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 366 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 367 if (br) {
WiredHome 0:ae5bf432c249 368 *br = '\0';
WiredHome 0:ae5bf432c249 369 if (strcmp(buf+1, section) == 0)
WiredHome 0:ae5bf432c249 370 inSection = true;
WiredHome 0:ae5bf432c249 371 }
WiredHome 0:ae5bf432c249 372 } else {
WiredHome 0:ae5bf432c249 373 // copy unaltered records across
WiredHome 0:ae5bf432c249 374 if (buf[0]) {
WiredHome 0:ae5bf432c249 375 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 376 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 377 }
WiredHome 0:ae5bf432c249 378 }
WiredHome 0:ae5bf432c249 379 }
WiredHome 0:ae5bf432c249 380 }
WiredHome 8:f128b10dfab1 381 INFO("close %s", iniFile);
WiredHome 0:ae5bf432c249 382 fclose(fi);
WiredHome 8:f128b10dfab1 383 } else {
WiredHome 8:f128b10dfab1 384 INFO(" %s did not previously exist.", iniFile);
WiredHome 0:ae5bf432c249 385 }
WiredHome 0:ae5bf432c249 386 if (!found) {
WiredHome 0:ae5bf432c249 387 // No old file, just create it now
WiredHome 0:ae5bf432c249 388 if (value != NULL) {
WiredHome 0:ae5bf432c249 389 if (!inSection) {
WiredHome 0:ae5bf432c249 390 fprintf(fo, "[%s]\r\n", section);
WiredHome 8:f128b10dfab1 391 INFO(" write: [%s]", section);
WiredHome 0:ae5bf432c249 392 }
WiredHome 0:ae5bf432c249 393 fprintf(fo, "%s=%s\r\n", key, value);
WiredHome 8:f128b10dfab1 394 INFO(" write: %s=%s", key, value);
WiredHome 0:ae5bf432c249 395 fileChanged = true;
WiredHome 0:ae5bf432c249 396 }
WiredHome 0:ae5bf432c249 397 found = true;
WiredHome 0:ae5bf432c249 398 }
WiredHome 8:f128b10dfab1 399 INFO(" close %s", newFile);
WiredHome 0:ae5bf432c249 400 fclose(fo);
WiredHome 8:f128b10dfab1 401 } else {
WiredHome 8:f128b10dfab1 402 ERR("*** Failed to open %s", newFile);
WiredHome 0:ae5bf432c249 403 }
WiredHome 0:ae5bf432c249 404 if (fileChanged) {
WiredHome 8:f128b10dfab1 405 INFO(" File changed: remove bak, rename ini to bak, rename new to ini");
WiredHome 0:ae5bf432c249 406 remove(bakFile); // remove an old .bak
WiredHome 8:f128b10dfab1 407 INFO(" a");
WiredHome 0:ae5bf432c249 408 Rename(iniFile, bakFile); // move the existing .ini to .bak
WiredHome 8:f128b10dfab1 409 INFO(" b");
WiredHome 0:ae5bf432c249 410 Rename(newFile, iniFile); // move the new .new to .ini
WiredHome 8:f128b10dfab1 411 INFO(" c");
WiredHome 4:70042853d43b 412 #ifdef RTOS_H
WiredHome 4:70042853d43b 413 Thread::wait(1000);
WiredHome 4:70042853d43b 414 #else
WiredHome 0:ae5bf432c249 415 wait(1);
WiredHome 4:70042853d43b 416 #endif
WiredHome 8:f128b10dfab1 417 INFO(" d");
WiredHome 0:ae5bf432c249 418 }
WiredHome 11:738604f18088 419 swFree(newFile);
WiredHome 11:738604f18088 420 swFree(bakFile);
WiredHome 0:ae5bf432c249 421 return found;
WiredHome 0:ae5bf432c249 422 }
WiredHome 0:ae5bf432c249 423
WiredHome 0:ae5bf432c249 424
WiredHome 0:ae5bf432c249 425 //***********************************************************
WiredHome 0:ae5bf432c249 426 // Private version that also works with local file system
WiredHome 8:f128b10dfab1 427 // by copying one file to the other.
WiredHome 0:ae5bf432c249 428 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 429 //***********************************************************
WiredHome 0:ae5bf432c249 430 int INI::Rename(const char *oldfname, const char *newfname)
WiredHome 0:ae5bf432c249 431 {
WiredHome 0:ae5bf432c249 432 int retval = 0;
WiredHome 0:ae5bf432c249 433
WiredHome 8:f128b10dfab1 434 INFO("Rename(%s,%s)", oldfname, newfname);
WiredHome 8:f128b10dfab1 435 if (Copy(oldfname, newfname) == 0) {
WiredHome 8:f128b10dfab1 436 remove(oldfname);
WiredHome 8:f128b10dfab1 437 retval = 0;
WiredHome 0:ae5bf432c249 438 } else {
WiredHome 8:f128b10dfab1 439 retval = -1;
WiredHome 0:ae5bf432c249 440 }
WiredHome 0:ae5bf432c249 441 return (retval);
WiredHome 0:ae5bf432c249 442 }
WiredHome 0:ae5bf432c249 443
WiredHome 0:ae5bf432c249 444 //***********************************************************
WiredHome 0:ae5bf432c249 445 // Private version that also works with local file system
WiredHome 0:ae5bf432c249 446 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 447 //***********************************************************
WiredHome 0:ae5bf432c249 448 int INI::Copy(const char *src, const char *dst)
WiredHome 0:ae5bf432c249 449 {
WiredHome 0:ae5bf432c249 450 int retval = 0;
WiredHome 0:ae5bf432c249 451 int ch;
WiredHome 0:ae5bf432c249 452
WiredHome 8:f128b10dfab1 453 INFO("Copy(%s,%s)", src, dst);
WiredHome 0:ae5bf432c249 454 FILE *fpsrc = fopen(src, "r"); // src file
WiredHome 0:ae5bf432c249 455 FILE *fpdst = fopen(dst, "w"); // dest file
WiredHome 0:ae5bf432c249 456
WiredHome 8:f128b10dfab1 457 if (fpsrc) {
WiredHome 8:f128b10dfab1 458 INFO(" c1a");
WiredHome 8:f128b10dfab1 459 if (fpdst) {
WiredHome 8:f128b10dfab1 460 INFO(" c1b");
WiredHome 8:f128b10dfab1 461 while (1) { // Copy src to dest
WiredHome 8:f128b10dfab1 462 ch = fgetc(fpsrc); // until src EOF read.
WiredHome 8:f128b10dfab1 463 if (ch == EOF) break;
WiredHome 8:f128b10dfab1 464 fputc(ch, fpdst);
WiredHome 8:f128b10dfab1 465 }
WiredHome 8:f128b10dfab1 466 INFO(" c2");
WiredHome 8:f128b10dfab1 467 fclose(fpsrc);
WiredHome 8:f128b10dfab1 468 fclose(fpdst);
WiredHome 8:f128b10dfab1 469 }
WiredHome 0:ae5bf432c249 470 }
WiredHome 8:f128b10dfab1 471 INFO(" c3");
WiredHome 0:ae5bf432c249 472
WiredHome 8:f128b10dfab1 473 if (Exists(dst)) {
WiredHome 8:f128b10dfab1 474 retval = 0;
WiredHome 0:ae5bf432c249 475 } else {
WiredHome 8:f128b10dfab1 476 retval = -1;
WiredHome 0:ae5bf432c249 477 }
WiredHome 8:f128b10dfab1 478 INFO(" c4");
WiredHome 0:ae5bf432c249 479 return (retval);
WiredHome 0:ae5bf432c249 480 }
WiredHome 0:ae5bf432c249 481
WiredHome 0:ae5bf432c249 482
WiredHome 0:ae5bf432c249 483 #if 0
WiredHome 0:ae5bf432c249 484 // Test code for basic regression testing
WiredHome 0:ae5bf432c249 485 //
WiredHome 0:ae5bf432c249 486 #include <stdio.h>
WiredHome 0:ae5bf432c249 487 #include <assert.h>
WiredHome 0:ae5bf432c249 488 #include <string.h>
WiredHome 0:ae5bf432c249 489
WiredHome 0:ae5bf432c249 490 #include "INI.h"
WiredHome 0:ae5bf432c249 491
WiredHome 0:ae5bf432c249 492 #define TESTFILE "test.ini"
WiredHome 0:ae5bf432c249 493
WiredHome 0:ae5bf432c249 494 int main(int argc, char * argv[])
WiredHome 0:ae5bf432c249 495 {
WiredHome 0:ae5bf432c249 496 FILE * fp;
WiredHome 0:ae5bf432c249 497 char buffer[100];
WiredHome 0:ae5bf432c249 498 INI ini(TESTFILE);
WiredHome 0:ae5bf432c249 499
WiredHome 0:ae5bf432c249 500 // Start testing
WiredHome 0:ae5bf432c249 501 _unlink(TESTFILE);
WiredHome 0:ae5bf432c249 502 assert(ini.ReadString("Section 1", "Name 1", buffer, sizeof(buffer)) == false);
WiredHome 0:ae5bf432c249 503
WiredHome 0:ae5bf432c249 504 fp = fopen(TESTFILE, "wt");
WiredHome 0:ae5bf432c249 505 assert(fp);
WiredHome 0:ae5bf432c249 506 fprintf(fp, "[Section 1]\n");
WiredHome 0:ae5bf432c249 507 fprintf(fp, "Name 1=Value 1\n");
WiredHome 0:ae5bf432c249 508 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 509 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 510 fprintf(fp, "[Section 2]\n");
WiredHome 0:ae5bf432c249 511 fprintf(fp, "Name 1=Value 2\n");
WiredHome 0:ae5bf432c249 512 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 513 fprintf(fp, "Name 3=Value 3\n");
WiredHome 0:ae5bf432c249 514 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 515 fclose(fp);
WiredHome 0:ae5bf432c249 516
WiredHome 0:ae5bf432c249 517 assert(ini.ReadString("Section 2", "Name 2", buffer, sizeof(buffer)) == true);
WiredHome 0:ae5bf432c249 518 assert(strcmp("Value 2", buffer) == 0);
WiredHome 0:ae5bf432c249 519
WiredHome 0:ae5bf432c249 520 assert(ini.ReadString("Section 3", "Name", buffer, sizeof(buffer)) == false);
WiredHome 0:ae5bf432c249 521 assert(ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)) == false);
WiredHome 0:ae5bf432c249 522
WiredHome 0:ae5bf432c249 523 assert(ini.WriteString("Section 1", "Name 4", "Value 4") == true);
WiredHome 0:ae5bf432c249 524 assert(ini.ReadString("Section 1", "Name 2", buffer, sizeof(buffer)) == true);
WiredHome 0:ae5bf432c249 525 assert(ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)) == false);
WiredHome 0:ae5bf432c249 526 assert(ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)) == true);
WiredHome 0:ae5bf432c249 527 assert(strcmp("Value 4", buffer) == 0);
WiredHome 0:ae5bf432c249 528
WiredHome 0:ae5bf432c249 529 assert(ini.WriteString("Section 1", "Name 4", NULL) == true);
WiredHome 0:ae5bf432c249 530 assert(ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)) == false);
WiredHome 0:ae5bf432c249 531
WiredHome 0:ae5bf432c249 532 return 0;
WiredHome 0:ae5bf432c249 533 }
WiredHome 0:ae5bf432c249 534 #endif
WiredHome 12:6cf929bde139 535
WiredHome 12:6cf929bde139 536