A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Revision:
8:f128b10dfab1
Parent:
7:60f5dc3467ff
Child:
9:4947b8c244e9
--- a/IniManager.cpp	Thu May 22 16:09:43 2014 +0000
+++ b/IniManager.cpp	Mon Jul 07 15:19:16 2014 +0000
@@ -10,13 +10,14 @@
 
 #include "IniManager.h"
 
-//#define DEBUG       //Debug is disabled by default
+//#define DEBUG "INI "      //Debug is disabled by default
 
+#include <cstdio>
 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
-#define DBG(x, ...)  std::printf("[DBG INI%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
-#define WARN(x, ...) std::printf("[WRN INI%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
-#define ERR(x, ...)  std::printf("[ERR INI%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
-#define INFO(x, ...) std::printf("[INF INI%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
+#define DBG(x, ...)  std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
 #else
 #define DBG(x, ...)
 #define WARN(x, ...)
@@ -28,15 +29,6 @@
     : iniFile(0)
 {
     SetFile(file);
-#if 0
-    if (file) {
-        iniFile = (char *)malloc(strlen(file)+1);
-        if (iniFile)
-            strcpy(iniFile, file);
-        else
-            iniFile = NULL;
-    }
-#endif
 }
 
 
@@ -47,18 +39,39 @@
 }
 
 
+bool INI::Exists(const char * file)
+{
+    if (file == NULL)
+        file = iniFile;
+    INFO("Exists(%s)", file);
+    FILE * fp = fopen(file, "r");
+    if (fp) {
+        fclose(fp);
+        INFO("  [%s] exists", file);
+        return true;
+    } else {
+        INFO("  [%s] does not exist", file);
+        return false;
+    }
+}
+
+
 bool INI::SetFile(const char * file)
 {
+    INFO("SetFile(%s)", file);
     if (file) {
         if (iniFile)
             free(iniFile);
         iniFile = (char *)malloc(strlen(file)+1);
         if (iniFile) {
             strcpy(iniFile, file);
+            INFO("  SetFile(%s) success", iniFile);
             return true;
         }
-        else
-            iniFile = NULL;        
+        else {
+            iniFile = NULL;
+            ERR("  SetFile(%s) failed to allocate memory", file);
+        }
     }
     return false;
 }
@@ -68,8 +81,8 @@
     bool found = false;
     if (!iniFile)
         return found;
-    CrashRecover();
-    INFO("ReadString from %s\r\n", iniFile);
+    CleanUp();
+    INFO("ReadString from %s", iniFile);
     FILE * fp = fopen(iniFile,"rt");
     if (fp) {
         char buf[INTERNAL_BUF_SIZE];
@@ -79,7 +92,7 @@
             int x = strlen(buf) - 1;        // remove trailing \r\n combinations
             while (x >= 0 && buf[x] < ' ')
                 buf[x--] = '\0';
-            INFO("read in [%s]\r\n", buf);
+            INFO("  reading \"%s\"", buf);
             if (inSection && buf[0] != '[') {
                 char * eq = strchr(buf, '=');
                 if (eq) {
@@ -108,37 +121,37 @@
     if (!found && defaultString != NULL && *defaultString) {
         strncpy(buffer, defaultString, bufferSize);
         buffer[bufferSize-1] = '\0';
-        INFO("sub %s.\r\n", buffer);
+        INFO("  sub %s.", buffer);
         found = true;
     }
     return found;
 }
 
-bool INI::CrashRecover()
+bool INI::CleanUp()
 {
     char * newFile = (char *)malloc(strlen(iniFile)+1);
     char * bakFile = (char *)malloc(strlen(iniFile)+1);
 
     if (newFile && bakFile) {
-        WARN("*** CrashRecover\r\n");
+        INFO("CleanUp");
         strcpy(bakFile, iniFile);
         strcpy(newFile, iniFile);
         strcpy(bakFile + strlen(bakFile) - 4, ".bak");
         strcpy(newFile + strlen(newFile) - 4, ".new");
 
-        FILE * repair = fopen(newFile, "rt");
-        if (repair) {
+        if (Exists(newFile)) {
             int i;
-            i = i;    // suppress warning about i not used when !DEBUG
+            (void)i;    // suppress warning about i not used when !DEBUG
             // helps recover if the system crashed before it could swap in the new file
-            INFO("*** repairing\r\n");
-            fclose(repair);
+            INFO("  *** found %s, repairing ...", newFile);
             i = remove(bakFile);            // remove an old .bak
-            INFO("remove(%s) returned %d\r\n", bakFile, i);
+            INFO("  remove(%s) returned %d", bakFile, i);
             i = Rename(iniFile, bakFile);   // move the existing .ini to .bak
-            INFO("rename(%s,%s) returned %d\r\n", iniFile, bakFile, i);
+            INFO("  rename(%s,%s) returned %d", iniFile, bakFile, i);
             i = Rename(newFile, iniFile);   // move the new .new to .ini
-            INFO("rename(%s,%s) returned %d\r\n", newFile, iniFile, i);
+            INFO("  rename(%s,%s) returned %d", newFile, iniFile, i);
+        } else {
+            // nothing to do, move on silently.
         }
     }
     free(newFile);
@@ -155,6 +168,7 @@
     bool found = false;
     bool fileChanged = false;
 
+    INFO("WriteString(%s,%s,%s)", section, key, value);
     if (!iniFile || (value != NULL && strlen(value) > INTERNAL_BUF_SIZE))
         return found;
 
@@ -171,9 +185,9 @@
     strcpy(bakFile + strlen(bakFile) - 4, ".bak");
     strcpy(newFile + strlen(newFile) - 4, ".new");
 
-    CrashRecover();
+    CleanUp();
 
-    INFO("Opening [%s] and [%s]\r\n", iniFile, newFile);
+    INFO("  Opening [%s] and [%s]", iniFile, newFile);
     FILE * fi = fopen(iniFile, "rt");
     FILE * fo = fopen(newFile, "wt");
     if (fo) {
@@ -181,6 +195,7 @@
         bool inSection = (section == NULL) ? true : false;
 
         if (fi) {
+            INFO("  %s opened for reading", iniFile);
             while(fgets(buf, sizeof(buf), fi)) {
                 // if not inSection, copy across
                 // if inSection and not key, copy across
@@ -188,6 +203,7 @@
                 int x = strlen(buf) - 1;        // remove trailing \r\n combinations
                 while (x >= 0 && buf[x] < ' ')
                     buf[x--] = '\0';
+                
                 if (inSection && buf[0] != '[') {
                     char * eq = strchr(buf, '=');
                     if (eq) {
@@ -198,6 +214,7 @@
                                 if (value != NULL) {
                                     fprintf(fo, "%s=%s\n", key, value);
                                     printf("write: %s=%s\r\n", key, value);
+                                    INFO("  write: %s=%s", key, value);
                                 }
                             }
                             fileChanged = true;
@@ -206,7 +223,7 @@
                         } else {
                             // write old record
                             fprintf(fo, "%s=%s\n", buf, eq);
-                            INFO("write: %s=%s\r\n", buf, eq);
+                            INFO("  write: %s=%s", buf, eq);
                         }
                     } else {
                         // what to do with unknown record(s)?
@@ -219,7 +236,7 @@
                             // Append new record to desired section
                             if (value != NULL) {
                                 fprintf(fo, "%s=%s\r\n", key, value);
-                                INFO("write: %s=%s\r\n", key, value);
+                                INFO("  write: %s=%s", key, value);
                                 fileChanged = true;
                             }
                             found = true;
@@ -227,7 +244,7 @@
                         inSection = false;
                         // write old record
                         fprintf(fo, "%s\r\n", buf);
-                        INFO("write: %s\r\n", buf);
+                        INFO("  write: %s", buf);
                         if (br) {
                             *br = '\0';
                             if (strcmp(buf+1, section) == 0)
@@ -237,40 +254,48 @@
                         // copy unaltered records across
                         if (buf[0]) {
                             fprintf(fo, "%s\r\n", buf);
-                            INFO("write: %s\r\n", buf);
+                            INFO("  write: %s", buf);
                         }
                     }
                 }
             }
-            INFO("close %s\r\n", iniFile);
+            INFO("close %s", iniFile);
             fclose(fi);
+        } else {
+            INFO("  %s did not previously exist.", iniFile);
         }
         if (!found) {
             // No old file, just create it now
             if (value != NULL) {
                 if (!inSection) {
                     fprintf(fo, "[%s]\r\n", section);
-                    INFO("write: [%s]\r\n", section);
+                    INFO("  write: [%s]", section);
                 }
                 fprintf(fo, "%s=%s\r\n", key, value);
-                INFO("write: %s=%s\r\n", key, value);
+                INFO("  write: %s=%s", key, value);
                 fileChanged = true;
             }
             found = true;
         }
-        INFO("close %s\r\n", newFile);
+        INFO("  close %s", newFile);
         fclose(fo);
+    } else {
+        ERR("*** Failed to open %s", newFile);
     }
     if (fileChanged) {
-        INFO("remove bak, rename ini to bak, rename new to ini\r\n");
+        INFO("  File changed: remove bak, rename ini to bak, rename new to ini");
         remove(bakFile);            // remove an old .bak
+        INFO("  a");
         Rename(iniFile, bakFile);   // move the existing .ini to .bak
+        INFO("  b");
         Rename(newFile, iniFile);   // move the new .new to .ini
+        INFO("  c");
         #ifdef RTOS_H
         Thread::wait(1000);
         #else
         wait(1);
         #endif
+        INFO("  d");
     }
     free(newFile);
     free(bakFile);
@@ -280,32 +305,19 @@
 
 //***********************************************************
 // Private version that also works with local file system
+// by copying one file to the other.
 //    Returns -1 = error; 0 = success
 //***********************************************************
 int INI::Rename(const char *oldfname, const char *newfname)
 {
     int retval = 0;
-    int ch;
 
-    FILE *fpold = fopen(oldfname, "r");   // src file
-    FILE *fpnew = fopen(newfname, "w");   // dest file
-
-    while (1) {                   // Copy src to dest
-        ch = fgetc(fpold);        // until src EOF read.
-        if (ch == EOF) break;
-        fputc(ch, fpnew);
-    }
-
-    fclose(fpnew);
-    fclose(fpold);
-
-    fpnew = fopen(newfname, "r"); // Reopen dest to insure
-    if(fpnew == NULL) {           // that it was created.
-        retval = (-1);            // Return Error.
+    INFO("Rename(%s,%s)", oldfname, newfname);
+    if (Copy(oldfname, newfname) == 0) {
+        remove(oldfname);
+        retval = 0;
     } else {
-        fclose(fpnew);
-        remove(oldfname);         // Remove original file.
-        retval = (0);             // Return Success.
+        retval = -1;
     }
     return (retval);
 }
@@ -319,24 +331,32 @@
     int retval = 0;
     int ch;
 
+    INFO("Copy(%s,%s)", src, dst);
     FILE *fpsrc = fopen(src, "r");   // src file
     FILE *fpdst = fopen(dst, "w");   // dest file
 
-    while (1) {                  // Copy src to dest
-        ch = fgetc(fpsrc);       // until src EOF read.
-        if (ch == EOF) break;
-        fputc(ch, fpdst);
+    if (fpsrc) {
+        INFO("  c1a");
+        if (fpdst) {
+            INFO("  c1b");
+            while (1) {                  // Copy src to dest
+                ch = fgetc(fpsrc);       // until src EOF read.
+                if (ch == EOF) break;
+                fputc(ch, fpdst);
+            }
+            INFO("  c2");
+        fclose(fpsrc);
+        fclose(fpdst);
+        }
     }
-    fclose(fpsrc);
-    fclose(fpdst);
+    INFO("  c3");
 
-    fpdst = fopen(dst, "r");     // Reopen dest to insure
-    if(fpdst == NULL) {          // that it was created.
-        retval = (-1);           // Return error.
+    if (Exists(dst)) {
+        retval = 0;
     } else {
-        fclose(fpdst);
-        retval = (0);            // Return success.
+        retval = -1;
     }
+    INFO("  c4");
     return (retval);
 }