A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Committer:
WiredHome
Date:
Wed Apr 11 00:28:03 2018 +0000
Revision:
24:ba5fa9548f59
Parent:
23:18b5f3d7ef14
Child:
25:1362b843de86
Add a method to write long integers to the ini file.

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 24:ba5fa9548f59 316 INI::INI_Return INI::WriteLongInt(const char * section, const char * key, long int value)
WiredHome 24:ba5fa9548f59 317 {
WiredHome 24:ba5fa9548f59 318 char buf[20];
WiredHome 24:ba5fa9548f59 319 snprintf(buf, 20, "%ld", value);
WiredHome 24:ba5fa9548f59 320 return WriteString(section, key, buf);
WiredHome 24:ba5fa9548f59 321 }
WiredHome 24:ba5fa9548f59 322
WiredHome 24:ba5fa9548f59 323
WiredHome 0:ae5bf432c249 324 // Create the new version as .new
WiredHome 0:ae5bf432c249 325 // once complete, if something actually changed, then rename the .ini to .bak and rename the .new to .ini
WiredHome 0:ae5bf432c249 326 // once complete, if nothing actually changed, then delete the .new
WiredHome 0:ae5bf432c249 327 //
WiredHome 18:282ed56d983b 328 INI::INI_Return INI::WriteString(const char * section, const char * key, const char * value, int len)
WiredHome 0:ae5bf432c249 329 {
WiredHome 0:ae5bf432c249 330 bool found = false;
WiredHome 0:ae5bf432c249 331 bool fileChanged = false;
WiredHome 18:282ed56d983b 332 INI_Return retVal;
WiredHome 18:282ed56d983b 333
WiredHome 16:82e0f8747b95 334 if (len == -1)
WiredHome 16:82e0f8747b95 335 len = strlen(value);
WiredHome 8:f128b10dfab1 336 INFO("WriteString(%s,%s,%s)", section, key, value);
WiredHome 18:282ed56d983b 337 if (!iniFile)
WiredHome 18:282ed56d983b 338 return RetXLate[INI_NO_FILE_SPEC][version];
WiredHome 18:282ed56d983b 339
WiredHome 18:282ed56d983b 340 if (strlen(value) > INTERNAL_BUF_SIZE)
WiredHome 18:282ed56d983b 341 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 0:ae5bf432c249 342
WiredHome 11:738604f18088 343 char * newFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 344 if (!newFile)
WiredHome 18:282ed56d983b 345 return RetXLate[INI_INTERNAL_ERROR][version]; // no memory
WiredHome 16:82e0f8747b95 346 char * bakFile = (char *)swMalloc(strlen(iniFile)+1);
WiredHome 0:ae5bf432c249 347 if (!bakFile) {
WiredHome 11:738604f18088 348 swFree(newFile);
WiredHome 18:282ed56d983b 349 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 0:ae5bf432c249 350 }
WiredHome 16:82e0f8747b95 351 char * valBuf = (char *)swMalloc(len+1);
WiredHome 16:82e0f8747b95 352 if (!valBuf) {
WiredHome 16:82e0f8747b95 353 swFree(bakFile);
WiredHome 16:82e0f8747b95 354 swFree(newFile);
WiredHome 18:282ed56d983b 355 return RetXLate[INI_INTERNAL_ERROR][version];
WiredHome 16:82e0f8747b95 356 }
WiredHome 16:82e0f8747b95 357
WiredHome 0:ae5bf432c249 358 strcpy(bakFile, iniFile);
WiredHome 0:ae5bf432c249 359 strcpy(newFile, iniFile);
WiredHome 0:ae5bf432c249 360 strcpy(bakFile + strlen(bakFile) - 4, ".bak");
WiredHome 0:ae5bf432c249 361 strcpy(newFile + strlen(newFile) - 4, ".new");
WiredHome 16:82e0f8747b95 362 strncpy(valBuf, value, len);
WiredHome 16:82e0f8747b95 363 valBuf[len] = '\0';
WiredHome 8:f128b10dfab1 364 CleanUp();
WiredHome 0:ae5bf432c249 365
WiredHome 8:f128b10dfab1 366 INFO(" Opening [%s] and [%s]", iniFile, newFile);
WiredHome 0:ae5bf432c249 367 FILE * fi = fopen(iniFile, "rt");
WiredHome 0:ae5bf432c249 368 FILE * fo = fopen(newFile, "wt");
WiredHome 0:ae5bf432c249 369 if (fo) {
WiredHome 0:ae5bf432c249 370 char buf[INTERNAL_BUF_SIZE];
WiredHome 0:ae5bf432c249 371 bool inSection = (section == NULL) ? true : false;
WiredHome 0:ae5bf432c249 372
WiredHome 0:ae5bf432c249 373 if (fi) {
WiredHome 8:f128b10dfab1 374 INFO(" %s opened for reading", iniFile);
WiredHome 0:ae5bf432c249 375 while(fgets(buf, sizeof(buf), fi)) {
WiredHome 0:ae5bf432c249 376 // if not inSection, copy across
WiredHome 0:ae5bf432c249 377 // if inSection and not key, copy across
WiredHome 0:ae5bf432c249 378 // if InSection and key, write new value (or skip if value is null)
WiredHome 0:ae5bf432c249 379 int x = strlen(buf) - 1; // remove trailing \r\n combinations
WiredHome 0:ae5bf432c249 380 while (x >= 0 && buf[x] < ' ')
WiredHome 0:ae5bf432c249 381 buf[x--] = '\0';
WiredHome 8:f128b10dfab1 382
WiredHome 0:ae5bf432c249 383 if (inSection && buf[0] != '[') {
WiredHome 0:ae5bf432c249 384 char * eq = strchr(buf, '=');
WiredHome 0:ae5bf432c249 385 if (eq) {
WiredHome 0:ae5bf432c249 386 *eq++ = '\0';
WiredHome 0:ae5bf432c249 387 if (strcmp(buf,key) == 0) {
WiredHome 18:282ed56d983b 388 // delete, or replace the old record
WiredHome 16:82e0f8747b95 389 if (valBuf != NULL && strcmp(eq, valBuf) != 0) {
WiredHome 0:ae5bf432c249 390 // replace the old record
WiredHome 16:82e0f8747b95 391 if (valBuf != NULL) {
WiredHome 17:01c0ee144433 392 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 393 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 394 }
WiredHome 0:ae5bf432c249 395 }
WiredHome 18:282ed56d983b 396 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 397 fileChanged = true;
WiredHome 0:ae5bf432c249 398 inSection = false;
WiredHome 0:ae5bf432c249 399 found = true;
WiredHome 0:ae5bf432c249 400 } else {
WiredHome 0:ae5bf432c249 401 // write old record
WiredHome 17:01c0ee144433 402 fprintf(fo, "%s=%s\r\n", buf, eq);
WiredHome 8:f128b10dfab1 403 INFO(" write: %s=%s", buf, eq);
WiredHome 0:ae5bf432c249 404 }
WiredHome 0:ae5bf432c249 405 } else {
WiredHome 0:ae5bf432c249 406 // what to do with unknown record(s)?
WiredHome 0:ae5bf432c249 407 // fprintf(fo, "%s\n", buf); // eliminate them
WiredHome 0:ae5bf432c249 408 }
WiredHome 0:ae5bf432c249 409 } else {
WiredHome 0:ae5bf432c249 410 if (buf[0] == '[') {
WiredHome 0:ae5bf432c249 411 char * br = strchr(buf, ']');
WiredHome 0:ae5bf432c249 412 if (inSection) { // found next section while in good section
WiredHome 0:ae5bf432c249 413 // Append new record to desired section
WiredHome 16:82e0f8747b95 414 if (valBuf != NULL) {
WiredHome 16:82e0f8747b95 415 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 416 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 417 fileChanged = true;
WiredHome 0:ae5bf432c249 418 }
WiredHome 0:ae5bf432c249 419 found = true;
WiredHome 18:282ed56d983b 420 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 421 }
WiredHome 0:ae5bf432c249 422 inSection = false;
WiredHome 0:ae5bf432c249 423 // write old record
WiredHome 0:ae5bf432c249 424 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 425 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 426 if (br) {
WiredHome 0:ae5bf432c249 427 *br = '\0';
WiredHome 0:ae5bf432c249 428 if (strcmp(buf+1, section) == 0)
WiredHome 0:ae5bf432c249 429 inSection = true;
WiredHome 0:ae5bf432c249 430 }
WiredHome 0:ae5bf432c249 431 } else {
WiredHome 0:ae5bf432c249 432 // copy unaltered records across
WiredHome 0:ae5bf432c249 433 if (buf[0]) {
WiredHome 0:ae5bf432c249 434 fprintf(fo, "%s\r\n", buf);
WiredHome 8:f128b10dfab1 435 INFO(" write: %s", buf);
WiredHome 0:ae5bf432c249 436 }
WiredHome 0:ae5bf432c249 437 }
WiredHome 0:ae5bf432c249 438 }
WiredHome 0:ae5bf432c249 439 }
WiredHome 8:f128b10dfab1 440 INFO("close %s", iniFile);
WiredHome 0:ae5bf432c249 441 fclose(fi);
WiredHome 8:f128b10dfab1 442 } else {
WiredHome 8:f128b10dfab1 443 INFO(" %s did not previously exist.", iniFile);
WiredHome 0:ae5bf432c249 444 }
WiredHome 0:ae5bf432c249 445 if (!found) {
WiredHome 0:ae5bf432c249 446 // No old file, just create it now
WiredHome 16:82e0f8747b95 447 if (valBuf != NULL) {
WiredHome 0:ae5bf432c249 448 if (!inSection) {
WiredHome 17:01c0ee144433 449 fprintf(fo, "\r\n[%s]\r\n", section);
WiredHome 8:f128b10dfab1 450 INFO(" write: [%s]", section);
WiredHome 0:ae5bf432c249 451 }
WiredHome 16:82e0f8747b95 452 fprintf(fo, "%s=%s\r\n", key, valBuf);
WiredHome 16:82e0f8747b95 453 INFO(" write: %s=%s", key, valBuf);
WiredHome 0:ae5bf432c249 454 fileChanged = true;
WiredHome 0:ae5bf432c249 455 }
WiredHome 0:ae5bf432c249 456 found = true;
WiredHome 18:282ed56d983b 457 retVal = RetXLate[INI_SUCCESS][version];
WiredHome 0:ae5bf432c249 458 }
WiredHome 8:f128b10dfab1 459 INFO(" close %s", newFile);
WiredHome 0:ae5bf432c249 460 fclose(fo);
WiredHome 8:f128b10dfab1 461 } else {
WiredHome 8:f128b10dfab1 462 ERR("*** Failed to open %s", newFile);
WiredHome 18:282ed56d983b 463 retVal = RetXLate[INI_FILE_NOT_FOUND][version];
WiredHome 0:ae5bf432c249 464 }
WiredHome 0:ae5bf432c249 465 if (fileChanged) {
WiredHome 8:f128b10dfab1 466 INFO(" File changed: remove bak, rename ini to bak, rename new to ini");
WiredHome 0:ae5bf432c249 467 remove(bakFile); // remove an old .bak
WiredHome 8:f128b10dfab1 468 INFO(" a");
WiredHome 0:ae5bf432c249 469 Rename(iniFile, bakFile); // move the existing .ini to .bak
WiredHome 8:f128b10dfab1 470 INFO(" b");
WiredHome 0:ae5bf432c249 471 Rename(newFile, iniFile); // move the new .new to .ini
WiredHome 8:f128b10dfab1 472 INFO(" c");
WiredHome 4:70042853d43b 473 #ifdef RTOS_H
WiredHome 4:70042853d43b 474 Thread::wait(1000);
WiredHome 4:70042853d43b 475 #else
WiredHome 0:ae5bf432c249 476 wait(1);
WiredHome 4:70042853d43b 477 #endif
WiredHome 8:f128b10dfab1 478 INFO(" d");
WiredHome 0:ae5bf432c249 479 }
WiredHome 16:82e0f8747b95 480 swFree(valBuf);
WiredHome 11:738604f18088 481 swFree(newFile);
WiredHome 11:738604f18088 482 swFree(bakFile);
WiredHome 18:282ed56d983b 483 return retVal;
WiredHome 0:ae5bf432c249 484 }
WiredHome 0:ae5bf432c249 485
WiredHome 0:ae5bf432c249 486
WiredHome 0:ae5bf432c249 487 //***********************************************************
WiredHome 0:ae5bf432c249 488 // Private version that also works with local file system
WiredHome 8:f128b10dfab1 489 // by copying one file to the other.
WiredHome 0:ae5bf432c249 490 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 491 //***********************************************************
WiredHome 0:ae5bf432c249 492 int INI::Rename(const char *oldfname, const char *newfname)
WiredHome 0:ae5bf432c249 493 {
WiredHome 0:ae5bf432c249 494 int retval = 0;
WiredHome 0:ae5bf432c249 495
WiredHome 8:f128b10dfab1 496 INFO("Rename(%s,%s)", oldfname, newfname);
WiredHome 8:f128b10dfab1 497 if (Copy(oldfname, newfname) == 0) {
WiredHome 8:f128b10dfab1 498 remove(oldfname);
WiredHome 8:f128b10dfab1 499 retval = 0;
WiredHome 0:ae5bf432c249 500 } else {
WiredHome 8:f128b10dfab1 501 retval = -1;
WiredHome 0:ae5bf432c249 502 }
WiredHome 0:ae5bf432c249 503 return (retval);
WiredHome 0:ae5bf432c249 504 }
WiredHome 0:ae5bf432c249 505
WiredHome 0:ae5bf432c249 506 //***********************************************************
WiredHome 0:ae5bf432c249 507 // Private version that also works with local file system
WiredHome 0:ae5bf432c249 508 // Returns -1 = error; 0 = success
WiredHome 0:ae5bf432c249 509 //***********************************************************
WiredHome 0:ae5bf432c249 510 int INI::Copy(const char *src, const char *dst)
WiredHome 0:ae5bf432c249 511 {
WiredHome 0:ae5bf432c249 512 int retval = 0;
WiredHome 0:ae5bf432c249 513 int ch;
WiredHome 0:ae5bf432c249 514
WiredHome 8:f128b10dfab1 515 INFO("Copy(%s,%s)", src, dst);
WiredHome 0:ae5bf432c249 516 FILE *fpsrc = fopen(src, "r"); // src file
WiredHome 0:ae5bf432c249 517 FILE *fpdst = fopen(dst, "w"); // dest file
WiredHome 0:ae5bf432c249 518
WiredHome 8:f128b10dfab1 519 if (fpsrc) {
WiredHome 8:f128b10dfab1 520 INFO(" c1a");
WiredHome 8:f128b10dfab1 521 if (fpdst) {
WiredHome 8:f128b10dfab1 522 INFO(" c1b");
WiredHome 8:f128b10dfab1 523 while (1) { // Copy src to dest
WiredHome 8:f128b10dfab1 524 ch = fgetc(fpsrc); // until src EOF read.
WiredHome 8:f128b10dfab1 525 if (ch == EOF) break;
WiredHome 8:f128b10dfab1 526 fputc(ch, fpdst);
WiredHome 8:f128b10dfab1 527 }
WiredHome 8:f128b10dfab1 528 INFO(" c2");
WiredHome 8:f128b10dfab1 529 fclose(fpsrc);
WiredHome 8:f128b10dfab1 530 fclose(fpdst);
WiredHome 8:f128b10dfab1 531 }
WiredHome 0:ae5bf432c249 532 }
WiredHome 8:f128b10dfab1 533 INFO(" c3");
WiredHome 0:ae5bf432c249 534
WiredHome 8:f128b10dfab1 535 if (Exists(dst)) {
WiredHome 8:f128b10dfab1 536 retval = 0;
WiredHome 0:ae5bf432c249 537 } else {
WiredHome 8:f128b10dfab1 538 retval = -1;
WiredHome 0:ae5bf432c249 539 }
WiredHome 8:f128b10dfab1 540 INFO(" c4");
WiredHome 0:ae5bf432c249 541 return (retval);
WiredHome 0:ae5bf432c249 542 }
WiredHome 0:ae5bf432c249 543
WiredHome 0:ae5bf432c249 544
WiredHome 18:282ed56d983b 545 const char * INI::GetReturnMessage(INI_Return retVal) {
WiredHome 18:282ed56d983b 546 if (version == 0) {
WiredHome 18:282ed56d983b 547 switch (retVal) {
WiredHome 18:282ed56d983b 548 default:
WiredHome 18:282ed56d983b 549 case INI_V1_FAIL: return "INI Fail";
WiredHome 18:282ed56d983b 550 case INI_V1_SUCCESS: return "INI Success";
WiredHome 18:282ed56d983b 551 }
WiredHome 18:282ed56d983b 552 } else {
WiredHome 18:282ed56d983b 553 switch (retVal) {
WiredHome 18:282ed56d983b 554 case INI_SUCCESS: return "INI Success - operation succeeded";
WiredHome 18:282ed56d983b 555 case INI_NO_FILE_SPEC: return "INI Fail - no file was specified";
WiredHome 18:282ed56d983b 556 case INI_FILE_NOT_FOUND: return "INI Fail - ini file not found, or failed to open";
WiredHome 18:282ed56d983b 557 case INI_SECTION_NOT_FOUND: return "INI Fail - section not found";
WiredHome 18:282ed56d983b 558 case INI_KEY_NOT_FOUND: return "INI Fail - key not found";
WiredHome 18:282ed56d983b 559 case INI_BUF_TOO_SMALL: return "INI Fail - buffer to small for value";
WiredHome 18:282ed56d983b 560 case INI_INTERNAL_ERROR: return "INI Fail - internal error - can't malloc";
WiredHome 18:282ed56d983b 561 default: return "INI Fail - Code Unknown";
WiredHome 18:282ed56d983b 562 }
WiredHome 18:282ed56d983b 563 }
WiredHome 18:282ed56d983b 564 }
WiredHome 18:282ed56d983b 565
WiredHome 0:ae5bf432c249 566 #if 0
WiredHome 0:ae5bf432c249 567 // Test code for basic regression testing
WiredHome 0:ae5bf432c249 568 //
WiredHome 0:ae5bf432c249 569 #include <stdio.h>
WiredHome 0:ae5bf432c249 570 #include <assert.h>
WiredHome 0:ae5bf432c249 571 #include <string.h>
WiredHome 0:ae5bf432c249 572
WiredHome 0:ae5bf432c249 573 #include "INI.h"
WiredHome 0:ae5bf432c249 574
WiredHome 0:ae5bf432c249 575 #define TESTFILE "test.ini"
WiredHome 0:ae5bf432c249 576
WiredHome 20:392d1ec637eb 577
WiredHome 20:392d1ec637eb 578 //INI_V1_FAIL = 0, ///< Version 1 return value - Fail
WiredHome 20:392d1ec637eb 579 //INI_V1_SUCCESS = 1, ///< Version 1 return value - Success
WiredHome 20:392d1ec637eb 580 //INI_SUCCESS = 0, ///< Success - operation succeeded
WiredHome 20:392d1ec637eb 581 //INI_NO_FILE_SPEC, ///< Fail - no file was specified
WiredHome 20:392d1ec637eb 582 //INI_FILE_NOT_FOUND, ///< Fail - ini file not found, or failed to open
WiredHome 20:392d1ec637eb 583 //INI_SECTION_NOT_FOUND, ///< Fail - section not found
WiredHome 20:392d1ec637eb 584 //INI_KEY_NOT_FOUND, ///< Fail - key not found
WiredHome 20:392d1ec637eb 585 //INI_BUF_TOO_SMALL, ///< Fail - buffer to small for value
WiredHome 20:392d1ec637eb 586 //INI_INTERNAL_ERROR ///< Fail - internal error - can't alloc buffers
WiredHome 20:392d1ec637eb 587
WiredHome 0:ae5bf432c249 588 int main(int argc, char * argv[])
WiredHome 0:ae5bf432c249 589 {
WiredHome 0:ae5bf432c249 590 FILE * fp;
WiredHome 0:ae5bf432c249 591 char buffer[100];
WiredHome 20:392d1ec637eb 592 INI ini(TESTFILE, 2);
WiredHome 0:ae5bf432c249 593
WiredHome 0:ae5bf432c249 594 // Start testing
WiredHome 0:ae5bf432c249 595 _unlink(TESTFILE);
WiredHome 20:392d1ec637eb 596 assert(INI::INI_FILE_NOT_FOUND == ini.ReadString("Section 1", "Name 1", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 597
WiredHome 0:ae5bf432c249 598 fp = fopen(TESTFILE, "wt");
WiredHome 0:ae5bf432c249 599 assert(fp);
WiredHome 0:ae5bf432c249 600 fprintf(fp, "[Section 1]\n");
WiredHome 0:ae5bf432c249 601 fprintf(fp, "Name 1=Value 1\n");
WiredHome 0:ae5bf432c249 602 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 603 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 604 fprintf(fp, "[Section 2]\n");
WiredHome 0:ae5bf432c249 605 fprintf(fp, "Name 1=Value 2\n");
WiredHome 0:ae5bf432c249 606 fprintf(fp, "Name 2=Value 2\n");
WiredHome 0:ae5bf432c249 607 fprintf(fp, "Name 3=Value 3\n");
WiredHome 0:ae5bf432c249 608 fprintf(fp, "\n");
WiredHome 0:ae5bf432c249 609 fclose(fp);
WiredHome 0:ae5bf432c249 610
WiredHome 20:392d1ec637eb 611 assert(INI::INI_SUCCESS == ini.ReadString("Section 2", "Name 2", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 612 assert(strcmp("Value 2", buffer) == 0);
WiredHome 0:ae5bf432c249 613
WiredHome 20:392d1ec637eb 614 assert(INI::INI_SECTION_NOT_FOUND == ini.ReadString("Section 3", "Name", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 615 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 616
WiredHome 20:392d1ec637eb 617 assert(INI::INI_SUCCESS == ini.WriteString("Section 1", "Name 4", "Value 4"));
WiredHome 20:392d1ec637eb 618 assert(INI::INI_SUCCESS == ini.ReadString("Section 1", "Name 2", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 619 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 3", buffer, sizeof(buffer)));
WiredHome 20:392d1ec637eb 620 assert(INI::INI_SUCCESS == ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 621 assert(strcmp("Value 4", buffer) == 0);
WiredHome 0:ae5bf432c249 622
WiredHome 20:392d1ec637eb 623 assert(INI::INI_SUCCESS == ini.WriteString("Section 1", "Name 4", NULL));
WiredHome 20:392d1ec637eb 624 assert(INI::INI_KEY_NOT_FOUND == ini.ReadString("Section 1", "Name 4", buffer, sizeof(buffer)));
WiredHome 0:ae5bf432c249 625
WiredHome 0:ae5bf432c249 626 return 0;
WiredHome 0:ae5bf432c249 627 }
WiredHome 0:ae5bf432c249 628 #endif
WiredHome 12:6cf929bde139 629
WiredHome 12:6cf929bde139 630
WiredHome 16:82e0f8747b95 631