A simple .ini file interface.

Dependents:   Smart-WiFly-WebServer SignalGenerator WattEye X10Svr

Committer:
WiredHome
Date:
Thu Jun 11 02:09:41 2020 +0000
Revision:
28:4e7fc08a0fea
Parent:
27:611ffb74fd38
Parent:
26:e8d7b09a77a3
Code cleanup

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