Simple library of INI file parser.

Dependents:   TrainInfoSample WatchSensorMail

Committer:
rinosh2
Date:
Tue Nov 16 16:34:45 2010 +0000
Revision:
0:995403221573
Child:
1:3601c7feb547

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rinosh2 0:995403221573 1 ///////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 2 // IniFile: .ini file parser by rinos 2010
rinosh2 0:995403221573 3 ///////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 4
rinosh2 0:995403221573 5 #include "IniFile.h"
rinosh2 0:995403221573 6 #include <string.h>
rinosh2 0:995403221573 7 #include <stdlib.h>
rinosh2 0:995403221573 8
rinosh2 0:995403221573 9 ////////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 10 // defines
rinosh2 0:995403221573 11 const char INI_DELIM[] = " \t\r\n";
rinosh2 0:995403221573 12 const int INI_LINE_BUF= 256;
rinosh2 0:995403221573 13
rinosh2 0:995403221573 14 ////////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 15 // IniFile
rinosh2 0:995403221573 16 IniFile::IniFile(const char* file): m_fp(0) {
rinosh2 0:995403221573 17 if(file) open(file);
rinosh2 0:995403221573 18 }
rinosh2 0:995403221573 19 IniFile::~IniFile(){
rinosh2 0:995403221573 20 close();
rinosh2 0:995403221573 21 }
rinosh2 0:995403221573 22
rinosh2 0:995403221573 23 ////////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 24 // internal funcs
rinosh2 0:995403221573 25 IniFile::Status IniFile::strtrim(char* dst, const char* src, int dst_size){
rinosh2 0:995403221573 26 if(!dst_size) return S_BUFFER_TOO_SHORT; // myStrcpy needs more than 1 byte for '\0'.
rinosh2 0:995403221573 27
rinosh2 0:995403221573 28 // Find valid string area
rinosh2 0:995403221573 29 const char* p1 = strchr (src, '"');
rinosh2 0:995403221573 30 const char* p2 = p1? strrchr(++p1, '"') : 0;
rinosh2 0:995403221573 31 if(!p2){
rinosh2 0:995403221573 32 // trim space or tab
rinosh2 0:995403221573 33 for(p1 = src ; *p1 && strchr(INI_DELIM, *p1) ; p1++);
rinosh2 0:995403221573 34 if(!*p1){ // all char is space or tab
rinosh2 0:995403221573 35 *dst = 0;
rinosh2 0:995403221573 36 return S_SUCCESS;
rinosh2 0:995403221573 37 }
rinosh2 0:995403221573 38 for(p2 = p1 + strlen(p1) ; strchr(INI_DELIM, p2[-1]) ; --p2);
rinosh2 0:995403221573 39 }
rinosh2 0:995403221573 40
rinosh2 0:995403221573 41 // Check copy size
rinosh2 0:995403221573 42 Status ret;
rinosh2 0:995403221573 43 if(dst_size > p2 - p1){
rinosh2 0:995403221573 44 dst_size = p2 - p1;
rinosh2 0:995403221573 45 ret = S_SUCCESS;
rinosh2 0:995403221573 46 } else {
rinosh2 0:995403221573 47 dst_size--;
rinosh2 0:995403221573 48 ret = S_BUFFER_TOO_SHORT;
rinosh2 0:995403221573 49 }
rinosh2 0:995403221573 50
rinosh2 0:995403221573 51 // copy buffer
rinosh2 0:995403221573 52 if(dst != p1) memmove(dst, p1, dst_size);
rinosh2 0:995403221573 53 dst[dst_size] = 0;
rinosh2 0:995403221573 54 return ret;
rinosh2 0:995403221573 55 }
rinosh2 0:995403221573 56
rinosh2 0:995403221573 57 ////////////////////////////////////////////////////////////////////////////////
rinosh2 0:995403221573 58 // Access methods
rinosh2 0:995403221573 59 IniFile::Status IniFile::open(const char* file){
rinosh2 0:995403221573 60 close();
rinosh2 0:995403221573 61 m_fp = fopen(file, "r");
rinosh2 0:995403221573 62 if(m_fp) return S_SUCCESS;
rinosh2 0:995403221573 63
rinosh2 0:995403221573 64 //printf("IniFile: Can't open %s\n", file);
rinosh2 0:995403221573 65 return S_OPEN_ERROR;
rinosh2 0:995403221573 66 }
rinosh2 0:995403221573 67
rinosh2 0:995403221573 68 IniFile::Status IniFile::close(){
rinosh2 0:995403221573 69 if(!m_fp) return S_NOT_OPENED;
rinosh2 0:995403221573 70
rinosh2 0:995403221573 71 fclose(m_fp);
rinosh2 0:995403221573 72 m_fp = 0;
rinosh2 0:995403221573 73 return S_SUCCESS;
rinosh2 0:995403221573 74 }
rinosh2 0:995403221573 75
rinosh2 0:995403221573 76 IniFile::Status IniFile::get(const char* key, char* ret, int ret_size){
rinosh2 0:995403221573 77 if(!m_fp) return S_OPEN_ERROR;
rinosh2 0:995403221573 78
rinosh2 0:995403221573 79 rewind(m_fp);
rinosh2 0:995403221573 80 char line[INI_LINE_BUF];
rinosh2 0:995403221573 81 while(fgets(line, sizeof(line), m_fp)){
rinosh2 0:995403221573 82 if(*line == '#') continue; // comment line
rinosh2 0:995403221573 83
rinosh2 0:995403221573 84 char* p = strchr(line, '=');
rinosh2 0:995403221573 85 if(!p || line == p) continue; // invalid line
rinosh2 0:995403221573 86
rinosh2 0:995403221573 87 *p++ = 0;
rinosh2 0:995403221573 88 strtrim(line, line, p - line);
rinosh2 0:995403221573 89 if(strcmp(line, key)) continue; // different key
rinosh2 0:995403221573 90
rinosh2 0:995403221573 91 // check data type
rinosh2 0:995403221573 92 switch(ret_size){
rinosh2 0:995403221573 93 case DTYPE_INT:
rinosh2 0:995403221573 94 strtrim(line, p, INI_LINE_BUF);
rinosh2 0:995403221573 95 *(int*)ret = strtoul(line, &p, 0);
rinosh2 0:995403221573 96 //return p[0]? S_FORMAT_ERROR : S_SUCCESS; // check end
rinosh2 0:995403221573 97 return S_SUCCESS; // always success
rinosh2 0:995403221573 98
rinosh2 0:995403221573 99 case DTYPE_BOOL:
rinosh2 0:995403221573 100 strtrim(line, p, INI_LINE_BUF);
rinosh2 0:995403221573 101 switch(line[0]){
rinosh2 0:995403221573 102 case 'T':
rinosh2 0:995403221573 103 case 't': *(bool*)ret = true; break;
rinosh2 0:995403221573 104 case 'F':
rinosh2 0:995403221573 105 case 'f': *(bool*)ret = false; break;
rinosh2 0:995403221573 106 default: *(bool*)ret = strtoul(line, &p, 0)? true : false;
rinosh2 0:995403221573 107 }
rinosh2 0:995403221573 108 return S_SUCCESS;
rinosh2 0:995403221573 109
rinosh2 0:995403221573 110 default: // string
rinosh2 0:995403221573 111 return strtrim(ret, p, ret_size);
rinosh2 0:995403221573 112 }
rinosh2 0:995403221573 113 }
rinosh2 0:995403221573 114 return S_NO_KEY; // No key
rinosh2 0:995403221573 115 }
rinosh2 0:995403221573 116 IniFile::Status IniFile::get(const char* key, int& ret){
rinosh2 0:995403221573 117 return get(key, (char*)&ret, DTYPE_INT);
rinosh2 0:995403221573 118 }
rinosh2 0:995403221573 119 IniFile::Status IniFile::get(const char* key, bool& ret){
rinosh2 0:995403221573 120 return get(key, (char*)&ret, DTYPE_BOOL);
rinosh2 0:995403221573 121 }
rinosh2 0:995403221573 122
rinosh2 0:995403221573 123
rinosh2 0:995403221573 124 IniFile::Status IniFile::get(IniFile::IniList* inilist){
rinosh2 0:995403221573 125 Status ret = S_SUCCESS;
rinosh2 0:995403221573 126 for(; inilist->key ; ++inilist){
rinosh2 0:995403221573 127 Status sts = get(inilist->key, (char*)inilist->buf, inilist->typelen);
rinosh2 0:995403221573 128 switch(sts){
rinosh2 0:995403221573 129 case S_SUCCESS:
rinosh2 0:995403221573 130 break;
rinosh2 0:995403221573 131 case S_NO_KEY:
rinosh2 0:995403221573 132 ret = sts; // continue
rinosh2 0:995403221573 133 break;
rinosh2 0:995403221573 134 default:
rinosh2 0:995403221573 135 return sts; // fatal error
rinosh2 0:995403221573 136 }
rinosh2 0:995403221573 137 }
rinosh2 0:995403221573 138 return ret;
rinosh2 0:995403221573 139 }