A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Mon Jul 07 15:19:16 2014 +0000
Parent:
7:60f5dc3467ff
Child:
9:4947b8c244e9
Commit message:
Internal changes only to try to make it more robust, and require less memory.

Changed in this revision

IniManager.cpp Show annotated file Show diff for this revision Revisions of this file
IniManager.h Show annotated file Show diff for this revision Revisions of this file
--- 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);
 }
 
--- a/IniManager.h	Thu May 22 16:09:43 2014 +0000
+++ b/IniManager.h	Mon Jul 07 15:19:16 2014 +0000
@@ -45,6 +45,18 @@
     */
     ~INI(void);
 
+    /** Determine if a file exists
+    *
+    * This API can be used to determine if a file exists. The file may
+    * be specified as a parameter, but if no parameter is supplied it will
+    * then check to see if the INI file exists. This is either the file
+    * passed to the constructor, or the file passed to the SetFile API.
+    *
+    * @param[in] file is the optional filename to check for existance.
+    * @returns true if the file exists.
+    */
+    bool Exists(const char * file = NULL);
+
     /** set the file to use
     *
     * If not set at the time of construction, or if a change is needed, this
@@ -87,14 +99,17 @@
 private:
     char * iniFile;
 
-    /** Crash recover if we can.
+    /** Cleanup temporary files.
     *
-    * This will attempt to crash recover. If while writing a new file, it could not
-    * complete the process, it may be able to complete the process on the next access.
+    * This will attempt to clean up any temporary files. This can happen
+    * while writing a new file, if something went wrong and the program 
+    * crashed or otherwise could not complete the process.
+    * This will look for the temp files, try to finish processing them
+    * and remove the extraneous.
     *
     * @return true, always until I find a reason not to.
     */
-    bool CrashRecover();
+    bool CleanUp();
     
     /** Rename a file
     *