A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Committer:
WiredHome
Date:
Sat Mar 31 23:36:47 2018 +0000
Revision:
23:18b5f3d7ef14
Parent:
21:a69c8ec96cb1
Child:
24:ba5fa9548f59
ReadString - now defaults as intended if the file is not found, but a default string is provided.

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