A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Revision:
18:282ed56d983b
Parent:
15:3fc2b87a234d
Parent:
17:01c0ee144433
Child:
20:392d1ec637eb
--- a/IniManager.cpp	Sun Dec 11 14:05:17 2016 +0000
+++ b/IniManager.cpp	Wed Dec 28 00:21:01 2016 +0000
@@ -31,10 +31,24 @@
 #define INFO(x, ...)
 #endif
 
-INI::INI(const char * file)
+// 2 versions, to translate new return values to old format
+// return RetXLate[new value][version]
+INI::INI_Return RetXLate[INI::INI_INTERNAL_ERROR+1][2] = {
+//  Ver1,                   Ver2 return values.
+    INI::INI_V1_SUCCESS,    INI::INI_SUCCESS,            /// Success - operation succeeded
+    INI::INI_V1_FAIL,       INI::INI_NO_FILE_SPEC,       /// Fail - no file was specified
+    INI::INI_V1_FAIL,       INI::INI_FILE_NOT_FOUND,     /// Fail - ini file not found, or failed to open
+    INI::INI_V1_FAIL,       INI::INI_SECTION_NOT_FOUND,  /// Fail - section not found
+    INI::INI_V1_FAIL,       INI::INI_KEY_NOT_FOUND,      /// Fail - key not found
+    INI::INI_V1_FAIL,       INI::INI_BUF_TOO_SMALL,      /// Fail - buffer to small for value
+    INI::INI_V1_FAIL,       INI::INI_INTERNAL_ERROR      /// Fail - internal error - can't alloc buffers
+};
+
+INI::INI(const char * file, int Version)
     : iniFile(0)
 {
     SetFile(file);
+    version = (Version == 2) ? 1 : 0;   // Version 1 or 2 is return value index 0 or 1
 }
 
 
@@ -161,9 +175,10 @@
 }
 
 
-bool INI::SetFile(const char * file)
+bool INI::SetFile(const char * file, int Version)
 {
-    INFO("SetFile(%s)", file);
+    INFO("SetFile(%s,%d)", file, Version);
+    version = (Version == 2) ? 1 : 0;   // Version 1 or 2 is return value index 0 or 1
     if (file) {
         if (iniFile)
             swFree(iniFile);
@@ -181,18 +196,22 @@
     return false;
 }
 
-bool INI::ReadString(const char * section, const char * key, char * buffer, size_t bufferSize, const char * defaultString)
+INI::INI_Return INI::ReadString(const char * section, const char * key, char * buffer, size_t bufferSize, const char * defaultString)
 {
+    INI_Return retVal;
     bool found = false;
+    
     if (!iniFile)
-        return found;
+        return RetXLate[INI_NO_FILE_SPEC][version];
     CleanUp();
     INFO("ReadString from %s", iniFile);
     FILE * fp = fopen(iniFile,"rt");
-    if (fp) {
+    if (!fp) {
+        return RetXLate[INI_FILE_NOT_FOUND][version];
+    } else {
         char buf[INTERNAL_BUF_SIZE];
         bool inSection = (section == NULL) ? true : false;
-
+        retVal = RetXLate[INI_SECTION_NOT_FOUND][version];     // assume we won't find the section, until we do.
         while(fgets(buf, sizeof(buf), fp)) {
             int x = strlen(buf) - 1;        // remove trailing \r\n combinations
             while (x >= 0 && buf[x] < ' ')
@@ -205,21 +224,32 @@
                 char * eq = strchr(buf, '=');
                 if (eq) {
                     *eq++ = '\0';
-                    if ( (strcmp(buf,key) == 0) && (strlen(eq) <= bufferSize) ) {
-                        strcpy(buffer, eq);
-                        memset(buf, 0, INTERNAL_BUF_SIZE);  // secure the memory space
-                        found = true;
+                    if (strcmp(buf,key) == 0) {        // Found the key of interest
+                        if (strlen(eq) < bufferSize) {
+                            strcpy(buffer, eq);
+                            memset(buf, 0, INTERNAL_BUF_SIZE);  // secure the memory space
+                            found = true;
+                            retVal = RetXLate[INI_SUCCESS][version];
+                        } else {
+                            retVal = RetXLate[INI_BUF_TOO_SMALL][version];
+                        }
                         break;
                     }
                 }
             } else {
                 if (buf[0] == '[') {
                     char * br = strchr(buf, ']');
-                    inSection = false;
-                    if (br) {
-                        *br = '\0';
-                        if (strcmp(buf+1, section) == 0)
-                            inSection = true;
+                    if (inSection) {        // we were in the section of interest and just hit the next section...
+                        break;
+                    } else {
+                        inSection = false;
+                        if (br) {
+                            *br = '\0';
+                            if (strcmp(buf+1, section) == 0) {
+                                inSection = true;
+                                retVal = RetXLate[INI_KEY_NOT_FOUND][version];     // assume we won't find the key, until we do
+                            }
+                        }
                     }
                 }
             }
@@ -227,14 +257,17 @@
         fclose(fp);
     }
     if (!found && defaultString != NULL && *defaultString) {
-        strncpy(buffer, defaultString, bufferSize);
-        buffer[bufferSize-1] = '\0';
-        INFO("  sub %s.", buffer);
-        found = true;
+        if (strlen(defaultString) < bufferSize) {
+            strcpy(buffer, defaultString);
+            retVal = RetXLate[INI_SUCCESS][version];
+        } else {
+            retVal = RetXLate[INI_BUF_TOO_SMALL][version];
+        }
     }
-    return found;
+    return retVal;
 }
 
+
 long int INI::ReadLongInt(const char * section, const char * key, long int defaultValue)
 {
     char localBuf[16];
@@ -282,28 +315,42 @@
 // once complete, if something actually changed, then rename the .ini to .bak and rename the .new to .ini
 // once complete, if nothing actually changed, then delete the .new
 //
-bool INI::WriteString(const char * section, const char * key, const char * value)
+INI::INI_Return INI::WriteString(const char * section, const char * key, const char * value, int len)
 {
     bool found = false;
     bool fileChanged = false;
-
+    INI_Return retVal;
+    
+    if (len == -1)
+        len = strlen(value);
     INFO("WriteString(%s,%s,%s)", section, key, value);
-    if (!iniFile || (value != NULL && strlen(value) > INTERNAL_BUF_SIZE))
-        return found;
+    if (!iniFile)
+        return RetXLate[INI_NO_FILE_SPEC][version];
+        
+    if (strlen(value) > INTERNAL_BUF_SIZE)
+        return RetXLate[INI_INTERNAL_ERROR][version];
 
     char * newFile = (char *)swMalloc(strlen(iniFile)+1);
+    if (!newFile)
+        return RetXLate[INI_INTERNAL_ERROR][version];       // no memory
     char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
-    if (!newFile)
-        return found;       // no memory
     if (!bakFile) {
         swFree(newFile);
-        return found;
+        return RetXLate[INI_INTERNAL_ERROR][version];
     }
+    char * valBuf = (char *)swMalloc(len+1);
+    if (!valBuf) {
+        swFree(bakFile);
+        swFree(newFile);
+        return RetXLate[INI_INTERNAL_ERROR][version];
+    }
+
     strcpy(bakFile, iniFile);
     strcpy(newFile, iniFile);
     strcpy(bakFile + strlen(bakFile) - 4, ".bak");
     strcpy(newFile + strlen(newFile) - 4, ".new");
-
+    strncpy(valBuf, value, len);
+    valBuf[len] = '\0';
     CleanUp();
 
     INFO("  Opening [%s] and [%s]", iniFile, newFile);
@@ -328,20 +375,22 @@
                     if (eq) {
                         *eq++ = '\0';
                         if (strcmp(buf,key) == 0) {
-                            if (value != NULL && strcmp(eq, value) != 0) {
+                            // delete, or replace the old record
+                            if (valBuf != NULL && strcmp(eq, valBuf) != 0) {
                                 // replace the old record
-                                if (value != NULL) {
-                                    fprintf(fo, "%s=%s\n", key, value);
-                                    printf("write: %s=%s\r\n", key, value);
-                                    INFO("  write: %s=%s", key, value);
+                                if (valBuf != NULL) {
+                                    fprintf(fo, "%s=%s\r\n", key, valBuf);
+                                    printf("write: %s=%s\r\n", key, valBuf);
+                                    INFO("  write: %s=%s", key, valBuf);
                                 }
                             }
+                            retVal = RetXLate[INI_SUCCESS][version];
                             fileChanged = true;
                             inSection = false;
                             found = true;
                         } else {
                             // write old record
-                            fprintf(fo, "%s=%s\n", buf, eq);
+                            fprintf(fo, "%s=%s\r\n", buf, eq);
                             INFO("  write: %s=%s", buf, eq);
                         }
                     } else {
@@ -353,12 +402,13 @@
                         char * br = strchr(buf, ']');
                         if (inSection) { // found next section while in good section
                             // Append new record to desired section
-                            if (value != NULL) {
-                                fprintf(fo, "%s=%s\r\n", key, value);
-                                INFO("  write: %s=%s", key, value);
+                            if (valBuf != NULL) {
+                                fprintf(fo, "%s=%s\r\n", key, valBuf);
+                                INFO("  write: %s=%s", key, valBuf);
                                 fileChanged = true;
                             }
                             found = true;
+                            retVal = RetXLate[INI_SUCCESS][version];
                         }
                         inSection = false;
                         // write old record
@@ -385,21 +435,23 @@
         }
         if (!found) {
             // No old file, just create it now
-            if (value != NULL) {
+            if (valBuf != NULL) {
                 if (!inSection) {
-                    fprintf(fo, "[%s]\r\n", section);
+                    fprintf(fo, "\r\n[%s]\r\n", section);
                     INFO("  write: [%s]", section);
                 }
-                fprintf(fo, "%s=%s\r\n", key, value);
-                INFO("  write: %s=%s", key, value);
+                fprintf(fo, "%s=%s\r\n", key, valBuf);
+                INFO("  write: %s=%s", key, valBuf);
                 fileChanged = true;
             }
             found = true;
+            retVal = RetXLate[INI_SUCCESS][version];
         }
         INFO("  close %s", newFile);
         fclose(fo);
     } else {
         ERR("*** Failed to open %s", newFile);
+        retVal = RetXLate[INI_FILE_NOT_FOUND][version];
     }
     if (fileChanged) {
         INFO("  File changed: remove bak, rename ini to bak, rename new to ini");
@@ -416,9 +468,10 @@
         #endif
         INFO("  d");
     }
+    swFree(valBuf);
     swFree(newFile);
     swFree(bakFile);
-    return found;
+    return retVal;
 }
 
 
@@ -480,6 +533,27 @@
 }
 
 
+const char * INI::GetReturnMessage(INI_Return retVal) {
+    if (version == 0) {
+        switch (retVal) {
+            default:
+            case INI_V1_FAIL:           return "INI Fail";
+            case INI_V1_SUCCESS:        return "INI Success";
+        }
+    } else {
+        switch (retVal) {
+            case INI_SUCCESS:           return "INI Success - operation succeeded";
+            case INI_NO_FILE_SPEC:      return "INI Fail - no file was specified";
+            case INI_FILE_NOT_FOUND:    return "INI Fail - ini file not found, or failed to open";
+            case INI_SECTION_NOT_FOUND: return "INI Fail - section not found";
+            case INI_KEY_NOT_FOUND:     return "INI Fail - key not found";
+            case INI_BUF_TOO_SMALL:     return "INI Fail - buffer to small for value";
+            case INI_INTERNAL_ERROR:    return "INI Fail - internal error - can't malloc";
+            default:                    return "INI Fail - Code Unknown";
+        }
+    }
+}
+
 #if 0
 // Test code for basic regression testing
 //
@@ -534,3 +608,4 @@
 #endif
 
 
+