A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Committer:
WiredHome
Date:
Mon Jan 16 02:09:09 2017 +0000
Revision:
21:a69c8ec96cb1
Parent:
20:392d1ec637eb
Child:
23:18b5f3d7ef14
Removed an extraneous printf

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 18:282ed56d983b 210 return RetXLate[INI_FILE_NOT_FOUND][version];
WiredHome 18:282ed56d983b 211 } else {
WiredHome 0:ae5bf432c249 212 char buf[INTERNAL_BUF_SIZE];
WiredHome 0:ae5bf432c249 213 bool inSection = (section == NULL) ? true : false;
WiredHome 18:282ed56d983b 214 retVal = RetXLate[INI_SECTION_NOT_FOUND][version]; // assume we won't find the section, until we do.
WiredHome 0:ae5bf432c249 215 while(fgets(buf, sizeof(buf), fp)) {
WiredHome 0:ae5bf432c249 216 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 0:ae5bf432c249 217 while (x >= 0 && buf[x] < ' ')
WiredHome 0:ae5bf432c249 218 buf[x--] = '\0';
WiredHome 8:f128b10dfab1 219 INFO(" reading \"%s\"", buf);
WiredHome 15:3fc2b87a234d 220 if (!(buf[0] == '[' || (buf[0] >= 'A' && buf[0] <= 'Z') || (buf[0] >= 'a' && buf[0] <= 'z')))
WiredHome 15:3fc2b87a234d 221 continue;
WiredHome 15:3fc2b87a234d 222
WiredHome 0:ae5bf432c249 223 if (inSection && buf[0] != '[') {
WiredHome 0:ae5bf432c249 224 char * eq = strchr(buf, '=');
WiredHome 0:ae5bf432c249 225 if (eq) {
WiredHome 0:ae5bf432c249 226 *eq++ = '\0';
WiredHome 18:282ed56d983b 227 if (strcmp(buf,key) == 0) { // Found the key of interest
WiredHome 18:282ed56d983b 228 if (strlen(eq) < bufferSize) {
WiredHome 18:282ed56d983b 229 strcpy(buffer, eq);
WiredHome 18:282ed56d983b 230 memset(buf, 0, INTERNAL_BUF_SIZE); // secure the memory space
WiredHome 18:282ed56d983b 231 found = true;
WiredHome 18:282ed56d983b 232 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 18:282ed56d983b 233 } else {
WiredHome 18:282ed56d983b 234 retVal = RetXLate[INI_BUF_TOO_SMALL][version];
WiredHome 18:282ed56d983b 235 }
WiredHome 0:ae5bf432c249 236 break;
WiredHome 0:ae5bf432c249 237 }
WiredHome 0:ae5bf432c249 238 }
WiredHome 0:ae5bf432c249 239 } else {
WiredHome 0:ae5bf432c249 240 if (buf[0] == '[') {
WiredHome 0:ae5bf432c249 241 char * br = strchr(buf, ']');
WiredHome 18:282ed56d983b 242 if (inSection) { // we were in the section of interest and just hit the next section...
WiredHome 18:282ed56d983b 243 break;
WiredHome 18:282ed56d983b 244 } else {
WiredHome 18:282ed56d983b 245 inSection = false;
WiredHome 18:282ed56d983b 246 if (br) {
WiredHome 18:282ed56d983b 247 *br = '\0';
WiredHome 18:282ed56d983b 248 if (strcmp(buf+1, section) == 0) {
WiredHome 18:282ed56d983b 249 inSection = true;
WiredHome 18:282ed56d983b 250 retVal = RetXLate[INI_KEY_NOT_FOUND][version]; // assume we won't find the key, until we do
WiredHome 18:282ed56d983b 251 }
WiredHome 18:282ed56d983b 252 }
WiredHome 0:ae5bf432c249 253 }
WiredHome 0:ae5bf432c249 254 }
WiredHome 0:ae5bf432c249 255 }
WiredHome 0:ae5bf432c249 256 }
WiredHome 0:ae5bf432c249 257 fclose(fp);
WiredHome 0:ae5bf432c249 258 }
WiredHome 0:ae5bf432c249 259 if (!found && defaultString != NULL && *defaultString) {
WiredHome 18:282ed56d983b 260 if (strlen(defaultString) < bufferSize) {
WiredHome 18:282ed56d983b 261 strcpy(buffer, defaultString);
WiredHome 18:282ed56d983b 262 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 18:282ed56d983b 263 } else {
WiredHome 18:282ed56d983b 264 retVal = RetXLate[INI_BUF_TOO_SMALL][version];
WiredHome 18:282ed56d983b 265 }
WiredHome 0:ae5bf432c249 266 }
WiredHome 18:282ed56d983b 267 return retVal;
WiredHome 0:ae5bf432c249 268 }
WiredHome 0:ae5bf432c249 269
WiredHome 18:282ed56d983b 270
WiredHome 12:6cf929bde139 271 long int INI::ReadLongInt(const char * section, const char * key, long int defaultValue)
WiredHome 12:6cf929bde139 272 {
WiredHome 12:6cf929bde139 273 char localBuf[16];
WiredHome 12:6cf929bde139 274
WiredHome 20:392d1ec637eb 275 if (INI::INI_SUCCESS == ReadString(section, key, localBuf, sizeof(localBuf))) {
WiredHome 12:6cf929bde139 276 return atol(localBuf);
WiredHome 12:6cf929bde139 277 } else {
WiredHome 12:6cf929bde139 278 return defaultValue;
WiredHome 12:6cf929bde139 279 }
WiredHome 12:6cf929bde139 280 }
WiredHome 12:6cf929bde139 281
WiredHome 8:f128b10dfab1 282 bool INI::CleanUp()
WiredHome 0:ae5bf432c249 283 {
WiredHome 11:738604f18088 284 char * newFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 11:738604f18088 285 char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 286
WiredHome 0:ae5bf432c249 287 if (newFile && bakFile) {
WiredHome 8:f128b10dfab1 288 INFO("CleanUp");
WiredHome 0:ae5bf432c249 289 strcpy(bakFile, iniFile);
WiredHome 0:ae5bf432c249 290 strcpy(newFile, iniFile);
WiredHome 0:ae5bf432c249 291 strcpy(bakFile + strlen(bakFile) - 4, ".bak");
WiredHome 0:ae5bf432c249 292 strcpy(newFile + strlen(newFile) - 4, ".new");
WiredHome 0:ae5bf432c249 293
WiredHome 8:f128b10dfab1 294 if (Exists(newFile)) {
WiredHome 2:c63a794c1fee 295 int i;
WiredHome 9:4947b8c244e9 296 i = i; // suppress warning about i not used when !DEBUG
WiredHome 0:ae5bf432c249 297 // helps recover if the system crashed before it could swap in the new file
WiredHome 8:f128b10dfab1 298 INFO(" *** found %s, repairing ...", newFile);
WiredHome 0:ae5bf432c249 299 i = remove(bakFile); // remove an old .bak
WiredHome 8:f128b10dfab1 300 INFO(" remove(%s) returned %d", bakFile, i);
WiredHome 0:ae5bf432c249 301 i = Rename(iniFile, bakFile); // move the existing .ini to .bak
WiredHome 8:f128b10dfab1 302 INFO(" rename(%s,%s) returned %d", iniFile, bakFile, i);
WiredHome 0:ae5bf432c249 303 i = Rename(newFile, iniFile); // move the new .new to .ini
WiredHome 8:f128b10dfab1 304 INFO(" rename(%s,%s) returned %d", newFile, iniFile, i);
WiredHome 8:f128b10dfab1 305 } else {
WiredHome 8:f128b10dfab1 306 // nothing to do, move on silently.
WiredHome 0:ae5bf432c249 307 }
WiredHome 0:ae5bf432c249 308 }
WiredHome 11:738604f18088 309 swFree(newFile);
WiredHome 11:738604f18088 310 swFree(bakFile);
WiredHome 0:ae5bf432c249 311 return true;
WiredHome 0:ae5bf432c249 312 }
WiredHome 0:ae5bf432c249 313
WiredHome 0:ae5bf432c249 314 // Create the new version as .new
WiredHome 0:ae5bf432c249 315 // once complete, if something actually changed, then rename the .ini to .bak and rename the .new to .ini
WiredHome 0:ae5bf432c249 316 // once complete, if nothing actually changed, then delete the .new
WiredHome 0:ae5bf432c249 317 //
WiredHome 18:282ed56d983b 318 INI::INI_Return INI::WriteString(const char * section, const char * key, const char * value, int len)
WiredHome 0:ae5bf432c249 319 {
WiredHome 0:ae5bf432c249 320 bool found = false;
WiredHome 0:ae5bf432c249 321 bool fileChanged = false;
WiredHome 18:282ed56d983b 322 INI_Return retVal;
WiredHome 18:282ed56d983b 323
WiredHome 16:82e0f8747b95 324 if (len == -1)
WiredHome 16:82e0f8747b95 325 len = strlen(value);
WiredHome 8:f128b10dfab1 326 INFO("WriteString(%s,%s,%s)", section, key, value);
WiredHome 18:282ed56d983b 327 if (!iniFile)
WiredHome 18:282ed56d983b 328 return RetXLate[INI_NO_FILE_SPEC][version];
WiredHome 18:282ed56d983b 329
WiredHome 18:282ed56d983b 330 if (strlen(value) > INTERNAL_BUF_SIZE)
WiredHome 18:282ed56d983b 331 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 0:ae5bf432c249 332
WiredHome 11:738604f18088 333 char * newFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 334 if (!newFile)
WiredHome 18:282ed56d983b 335 return RetXLate[INI_INTERNAL_ERROR][version]; // no memory
WiredHome 16:82e0f8747b95 336 char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 337 if (!bakFile) {
WiredHome 11:738604f18088 338 swFree(newFile);
WiredHome 18:282ed56d983b 339 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 0:ae5bf432c249 340 }
WiredHome 16:82e0f8747b95 341 char * valBuf = (char *)swMalloc(len+1);
WiredHome 16:82e0f8747b95 342 if (!valBuf) {
WiredHome 16:82e0f8747b95 343 swFree(bakFile);
WiredHome 16:82e0f8747b95 344 swFree(newFile);
WiredHome 18:282ed56d983b 345 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 16:82e0f8747b95 346 }
WiredHome 16:82e0f8747b95 347
WiredHome 0:ae5bf432c249 348 strcpy(bakFile, iniFile);
WiredHome 0:ae5bf432c249 349 strcpy(newFile, iniFile);
WiredHome 0:ae5bf432c249 350 strcpy(bakFile + strlen(bakFile) - 4, ".bak");
WiredHome 0:ae5bf432c249 351 strcpy(newFile + strlen(newFile) - 4, ".new");
WiredHome 16:82e0f8747b95 352 strncpy(valBuf, value, len);
WiredHome 16:82e0f8747b95 353 valBuf[len] = '\0';
WiredHome 8:f128b10dfab1 354 CleanUp();
WiredHome 0:ae5bf432c249 355
WiredHome 8:f128b10dfab1 356 INFO(" Opening [%s] and [%s]", iniFile, newFile);
WiredHome 0:ae5bf432c249 357 FILE * fi = fopen(iniFile, "rt");
WiredHome 0:ae5bf432c249 358 FILE * fo = fopen(newFile, "wt");
WiredHome 0:ae5bf432c249 359 if (fo) {
WiredHome 0:ae5bf432c249 360 char buf[INTERNAL_BUF_SIZE];
WiredHome 0:ae5bf432c249 361 bool inSection = (section == NULL) ? true : false;
WiredHome 0:ae5bf432c249 362
WiredHome 0:ae5bf432c249 363 if (fi) {
WiredHome 8:f128b10dfab1 364 INFO(" %s opened for reading", iniFile);
WiredHome 0:ae5bf432c249 365 while(fgets(buf, sizeof(buf), fi)) {
WiredHome 0:ae5bf432c249 366 // if not inSection, copy across
WiredHome 0:ae5bf432c249 367 // if inSection and not key, copy across
WiredHome 0:ae5bf432c249 368 // if InSection and key, write new value (or skip if value is null)
WiredHome 0:ae5bf432c249 369 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 0:ae5bf432c249 370 while (x >= 0 && buf[x] < ' ')
WiredHome 0:ae5bf432c249 371 buf[x--] = '\0';
WiredHome 8:f128b10dfab1 372
WiredHome 0:ae5bf432c249 373 if (inSection && buf[0] != '[') {
WiredHome 0:ae5bf432c249 374 char * eq = strchr(buf, '=');
WiredHome 0:ae5bf432c249 375 if (eq) {
WiredHome 0:ae5bf432c249 376 *eq++ = '\0';
WiredHome 0:ae5bf432c249 377 if (strcmp(buf,key) == 0) {
WiredHome 18:282ed56d983b 378 // delete, or replace the old record
WiredHome 16:82e0f8747b95 379 if (valBuf != NULL && strcmp(eq, valBuf) != 0) {
WiredHome 0:ae5bf432c249 380 // replace the old record
WiredHome 16:82e0f8747b95 381 if (valBuf != NULL) {
WiredHome 17:01c0ee144433 382 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 383 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 384 }
WiredHome 0:ae5bf432c249 385 }
WiredHome 18:282ed56d983b 386 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 387 fileChanged = true;
WiredHome 0:ae5bf432c249 388 inSection = false;
WiredHome 0:ae5bf432c249 389 found = true;
WiredHome 0:ae5bf432c249 390 } else {
WiredHome 0:ae5bf432c249 391 // write old record
WiredHome 17:01c0ee144433 392 fprintf(fo, "%s=%s\r\n", buf, eq);
WiredHome 8:f128b10dfab1 393 INFO(" write: %s=%s", buf, eq);
WiredHome 0:ae5bf432c249 394 }
WiredHome 0:ae5bf432c249 395 } else {
WiredHome 0:ae5bf432c249 396 // what to do with unknown record(s)?
WiredHome 0:ae5bf432c249 397 // fprintf(fo, "%s\n", buf); // eliminate them
WiredHome 0:ae5bf432c249 398 }
WiredHome 0:ae5bf432c249 399 } else {
WiredHome 0:ae5bf432c249 400 if (buf[0] == '[') {
WiredHome 0:ae5bf432c249 401 char * br = strchr(buf, ']');
WiredHome 0:ae5bf432c249 402 if (inSection) { // found next section while in good section
WiredHome 0:ae5bf432c249 403 // Append new record to desired section
WiredHome 16:82e0f8747b95 404 if (valBuf != NULL) {
WiredHome 16:82e0f8747b95 405 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 406 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 407 fileChanged = true;
WiredHome 0:ae5bf432c249 408 }
WiredHome 0:ae5bf432c249 409 found = true;
WiredHome 18:282ed56d983b 410 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 411 }
WiredHome 0:ae5bf432c249 412 inSection = false;
WiredHome 0:ae5bf432c249 413 // write old record
WiredHome 0:ae5bf432c249 414 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 415 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 416 if (br) {
WiredHome 0:ae5bf432c249 417 *br = '\0';
WiredHome 0:ae5bf432c249 418 if (strcmp(buf+1, section) == 0)
WiredHome 0:ae5bf432c249 419 inSection = true;
WiredHome 0:ae5bf432c249 420 }
WiredHome 0:ae5bf432c249 421 } else {
WiredHome 0:ae5bf432c249 422 // copy unaltered records across
WiredHome 0:ae5bf432c249 423 if (buf[0]) {
WiredHome 0:ae5bf432c249 424 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 425 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 426 }
WiredHome 0:ae5bf432c249 427 }
WiredHome 0:ae5bf432c249 428 }
WiredHome 0:ae5bf432c249 429 }
WiredHome 8:f128b10dfab1 430 INFO("close %s", iniFile);
WiredHome 0:ae5bf432c249 431 fclose(fi);
WiredHome 8:f128b10dfab1 432 } else {
WiredHome 8:f128b10dfab1 433 INFO(" %s did not previously exist.", iniFile);
WiredHome 0:ae5bf432c249 434 }
WiredHome 0:ae5bf432c249 435 if (!found) {
WiredHome 0:ae5bf432c249 436 // No old file, just create it now
WiredHome 16:82e0f8747b95 437 if (valBuf != NULL) {
WiredHome 0:ae5bf432c249 438 if (!inSection) {
WiredHome 17:01c0ee144433 439 fprintf(fo, "\r\n[%s]\r\n", section);
WiredHome 8:f128b10dfab1 440 INFO(" write: [%s]", section);
WiredHome 0:ae5bf432c249 441 }
WiredHome 16:82e0f8747b95 442 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 443 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 444 fileChanged = true;
WiredHome 0:ae5bf432c249 445 }
WiredHome 0:ae5bf432c249 446 found = true;
WiredHome 18:282ed56d983b 447 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 448 }
WiredHome 8:f128b10dfab1 449 INFO(" close %s", newFile);
WiredHome 0:ae5bf432c249 450 fclose(fo);
WiredHome 8:f128b10dfab1 451 } else {
WiredHome 8:f128b10dfab1 452 ERR("*** Failed to open %s", newFile);
WiredHome 18:282ed56d983b 453 retVal = RetXLate[INI_FILE_NOT_FOUND][version];
WiredHome 0:ae5bf432c249 454 }
WiredHome 0:ae5bf432c249 455 if (fileChanged) {
WiredHome 8:f128b10dfab1 456 INFO(" File changed: remove bak, rename ini to bak, rename new to ini");
WiredHome 0:ae5bf432c249 457 remove(bakFile); // remove an old .bak
WiredHome 8:f128b10dfab1 458 INFO(" a");
WiredHome 0:ae5bf432c249 459 Rename(iniFile, bakFile); // move the existing .ini to .bak
WiredHome 8:f128b10dfab1 460 INFO(" b");
WiredHome 0:ae5bf432c249 461 Rename(newFile, iniFile); // move the new .new to .ini
WiredHome 8:f128b10dfab1 462 INFO(" c");
WiredHome 4:70042853d43b 463 #ifdef RTOS_H
WiredHome 4:70042853d43b 464 Thread::wait(1000);
WiredHome 4:70042853d43b 465 #else
WiredHome 0:ae5bf432c249 466 wait(1);
WiredHome 4:70042853d43b 467 #endif
WiredHome 8:f128b10dfab1 468 INFO(" d");
WiredHome 0:ae5bf432c249 469 }
WiredHome 16:82e0f8747b95 470 swFree(valBuf);
WiredHome 11:738604f18088 471 swFree(newFile);
WiredHome 11:738604f18088 472 swFree(bakFile);
WiredHome 18:282ed56d983b 473 return retVal;
WiredHome 0:ae5bf432c249 474 }
WiredHome 0:ae5bf432c249 475
WiredHome 0:ae5bf432c249 476
WiredHome 0:ae5bf432c249 477 //***********************************************************
WiredHome 0:ae5bf432c249 478 // Private version that also works with local file system
WiredHome 8:f128b10dfab1 479 // by copying one file to the other.
WiredHome 0:ae5bf432c249 480 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 481 //***********************************************************
WiredHome 0:ae5bf432c249 482 int INI::Rename(const char *oldfname, const char *newfname)
WiredHome 0:ae5bf432c249 483 {
WiredHome 0:ae5bf432c249 484 int retval = 0;
WiredHome 0:ae5bf432c249 485
WiredHome 8:f128b10dfab1 486 INFO("Rename(%s,%s)", oldfname, newfname);
WiredHome 8:f128b10dfab1 487 if (Copy(oldfname, newfname) == 0) {
WiredHome 8:f128b10dfab1 488 remove(oldfname);
WiredHome 8:f128b10dfab1 489 retval = 0;
WiredHome 0:ae5bf432c249 490 } else {
WiredHome 8:f128b10dfab1 491 retval = -1;
WiredHome 0:ae5bf432c249 492 }
WiredHome 0:ae5bf432c249 493 return (retval);
WiredHome 0:ae5bf432c249 494 }
WiredHome 0:ae5bf432c249 495
WiredHome 0:ae5bf432c249 496 //***********************************************************
WiredHome 0:ae5bf432c249 497 // Private version that also works with local file system
WiredHome 0:ae5bf432c249 498 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 499 //***********************************************************
WiredHome 0:ae5bf432c249 500 int INI::Copy(const char *src, const char *dst)
WiredHome 0:ae5bf432c249 501 {
WiredHome 0:ae5bf432c249 502 int retval = 0;
WiredHome 0:ae5bf432c249 503 int ch;
WiredHome 0:ae5bf432c249 504
WiredHome 8:f128b10dfab1 505 INFO("Copy(%s,%s)", src, dst);
WiredHome 0:ae5bf432c249 506 FILE *fpsrc = fopen(src, "r"); // src file
WiredHome 0:ae5bf432c249 507 FILE *fpdst = fopen(dst, "w"); // dest file
WiredHome 0:ae5bf432c249 508
WiredHome 8:f128b10dfab1 509 if (fpsrc) {
WiredHome 8:f128b10dfab1 510 INFO(" c1a");
WiredHome 8:f128b10dfab1 511 if (fpdst) {
WiredHome 8:f128b10dfab1 512 INFO(" c1b");
WiredHome 8:f128b10dfab1 513 while (1) { // Copy src to dest
WiredHome 8:f128b10dfab1 514 ch = fgetc(fpsrc); // until src EOF read.
WiredHome 8:f128b10dfab1 515 if (ch == EOF) break;
WiredHome 8:f128b10dfab1 516 fputc(ch, fpdst);
WiredHome 8:f128b10dfab1 517 }
WiredHome 8:f128b10dfab1 518 INFO(" c2");
WiredHome 8:f128b10dfab1 519 fclose(fpsrc);
WiredHome 8:f128b10dfab1 520 fclose(fpdst);
WiredHome 8:f128b10dfab1 521 }
WiredHome 0:ae5bf432c249 522 }
WiredHome 8:f128b10dfab1 523 INFO(" c3");
WiredHome 0:ae5bf432c249 524
WiredHome 8:f128b10dfab1 525 if (Exists(dst)) {
WiredHome 8:f128b10dfab1 526 retval = 0;
WiredHome 0:ae5bf432c249 527 } else {
WiredHome 8:f128b10dfab1 528 retval = -1;
WiredHome 0:ae5bf432c249 529 }
WiredHome 8:f128b10dfab1 530 INFO(" c4");
WiredHome 0:ae5bf432c249 531 return (retval);
WiredHome 0:ae5bf432c249 532 }
WiredHome 0:ae5bf432c249 533
WiredHome 0:ae5bf432c249 534
WiredHome 18:282ed56d983b 535 const char * INI::GetReturnMessage(INI_Return retVal) {
WiredHome 18:282ed56d983b 536 if (version == 0) {
WiredHome 18:282ed56d983b 537 switch (retVal) {
WiredHome 18:282ed56d983b 538 default:
WiredHome 18:282ed56d983b 539 case INI_V1_FAIL: return "INI Fail";
WiredHome 18:282ed56d983b 540 case INI_V1_SUCCESS: return "INI Success";
WiredHome 18:282ed56d983b 541 }
WiredHome 18:282ed56d983b 542 } else {
WiredHome 18:282ed56d983b 543 switch (retVal) {
WiredHome 18:282ed56d983b 544 case INI_SUCCESS: return "INI Success - operation succeeded";
WiredHome 18:282ed56d983b 545 case INI_NO_FILE_SPEC: return "INI Fail - no file was specified";
WiredHome 18:282ed56d983b 546 case INI_FILE_NOT_FOUND: return "INI Fail - ini file not found, or failed to open";
WiredHome 18:282ed56d983b 547 case INI_SECTION_NOT_FOUND: return "INI Fail - section not found";
WiredHome 18:282ed56d983b 548 case INI_KEY_NOT_FOUND: return "INI Fail - key not found";
WiredHome 18:282ed56d983b 549 case INI_BUF_TOO_SMALL: return "INI Fail - buffer to small for value";
WiredHome 18:282ed56d983b 550 case INI_INTERNAL_ERROR: return "INI Fail - internal error - can't malloc";
WiredHome 18:282ed56d983b 551 default: return "INI Fail - Code Unknown";
WiredHome 18:282ed56d983b 552 }
WiredHome 18:282ed56d983b 553 }
WiredHome 18:282ed56d983b 554 }
WiredHome 18:282ed56d983b 555
WiredHome 0:ae5bf432c249 556 #if 0
WiredHome 0:ae5bf432c249 557 // Test code for basic regression testing
WiredHome 0:ae5bf432c249 558 //
WiredHome 0:ae5bf432c249 559 #include <stdio.h>
WiredHome 0:ae5bf432c249 560 #include <assert.h>
WiredHome 0:ae5bf432c249 561 #include <string.h>
WiredHome 0:ae5bf432c249 562
WiredHome 0:ae5bf432c249 563 #include "INI.h"
WiredHome 0:ae5bf432c249 564
WiredHome 0:ae5bf432c249 565 #define TESTFILE "test.ini"
WiredHome 0:ae5bf432c249 566
WiredHome 20:392d1ec637eb 567
WiredHome 20:392d1ec637eb 568 //INI_V1_FAIL = 0, ///< Version 1 return value - Fail
WiredHome 20:392d1ec637eb 569 //INI_V1_SUCCESS = 1, ///< Version 1 return value - Success
WiredHome 20:392d1ec637eb 570 //INI_SUCCESS = 0, ///< Success - operation succeeded
WiredHome 20:392d1ec637eb 571 //INI_NO_FILE_SPEC, ///< Fail - no file was specified
WiredHome 20:392d1ec637eb 572 //INI_FILE_NOT_FOUND, ///< Fail - ini file not found, or failed to open
WiredHome 20:392d1ec637eb 573 //INI_SECTION_NOT_FOUND, ///< Fail - section not found
WiredHome 20:392d1ec637eb 574 //INI_KEY_NOT_FOUND, ///< Fail - key not found
WiredHome 20:392d1ec637eb 575 //INI_BUF_TOO_SMALL, ///< Fail - buffer to small for value
WiredHome 20:392d1ec637eb 576 //INI_INTERNAL_ERROR ///< Fail - internal error - can't alloc buffers
WiredHome 20:392d1ec637eb 577
WiredHome 0:ae5bf432c249 578 int main(int argc, char * argv[])
WiredHome 0:ae5bf432c249 579 {
WiredHome 0:ae5bf432c249 580 FILE * fp;
WiredHome 0:ae5bf432c249 581 char buffer[100];
WiredHome 20:392d1ec637eb 582 INI ini(TESTFILE, 2);
WiredHome 0:ae5bf432c249 583
WiredHome 0:ae5bf432c249 584 // Start testing
WiredHome 0:ae5bf432c249 585 _unlink(TESTFILE);
WiredHome 20:392d1ec637eb 586 assert(INI::INI_FILE_NOT_FOUND == ini.ReadString("Section 1", "Name 1", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 587
WiredHome 0:ae5bf432c249 588 fp = fopen(TESTFILE, "wt");
WiredHome 0:ae5bf432c249 589 assert(fp);
WiredHome 0:ae5bf432c249 590 fprintf(fp, "[Section 1]\n");
WiredHome 0:ae5bf432c249 591 fprintf(fp, "Name 1=Value 1\n");
WiredHome 0:ae5bf432c249 592 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 593 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 594 fprintf(fp, "[Section 2]\n");
WiredHome 0:ae5bf432c249 595 fprintf(fp, "Name 1=Value 2\n");
WiredHome 0:ae5bf432c249 596 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 597 fprintf(fp, "Name 3=Value 3\n");
WiredHome 0:ae5bf432c249 598 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 599 fclose(fp);
WiredHome 0:ae5bf432c249 600
WiredHome 20:392d1ec637eb 601 assert(INI::INI_SUCCESS == ini.ReadString("Section 2", "Name 2", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 602 assert(strcmp("Value 2", buffer) == 0);
WiredHome 0:ae5bf432c249 603
WiredHome 20:392d1ec637eb 604 assert(INI::INI_SECTION_NOT_FOUND == ini.ReadString("Section 3", "Name", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 605 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 606
WiredHome 20:392d1ec637eb 607 assert(INI::INI_SUCCESS == ini.WriteString("Section 1", "Name 4", "Value 4"));
WiredHome 20:392d1ec637eb 608 assert(INI::INI_SUCCESS == ini.ReadString("Section 1", "Name 2", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 609 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 610 assert(INI::INI_SUCCESS == ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 611 assert(strcmp("Value 4", buffer) == 0);
WiredHome 0:ae5bf432c249 612
WiredHome 20:392d1ec637eb 613 assert(INI::INI_SUCCESS == ini.WriteString("Section 1", "Name 4", NULL));
WiredHome 20:392d1ec637eb 614 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 615
WiredHome 0:ae5bf432c249 616 return 0;
WiredHome 0:ae5bf432c249 617 }
WiredHome 0:ae5bf432c249 618 #endif
WiredHome 12:6cf929bde139 619
WiredHome 12:6cf929bde139 620
WiredHome 16:82e0f8747b95 621