Simple library of INI file parser.
Dependents: TrainInfoSample WatchSensorMail
IniFile.cpp@1:3601c7feb547, 2010-11-17 (annotated)
- Committer:
- rinosh2
- Date:
- Wed Nov 17 16:24:11 2010 +0000
- Revision:
- 1:3601c7feb547
- Parent:
- 0:995403221573
- Child:
- 2:4ae80a05f6ea
Move strtrim to static method
Who changed what in which revision?
User | Revision | Line number | New 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 | 1:3601c7feb547 | 123 | IniFile::Status IniFile::get(const IniFile::IniList* inilist){ |
rinosh2 | 0:995403221573 | 124 | Status ret = S_SUCCESS; |
rinosh2 | 0:995403221573 | 125 | for(; inilist->key ; ++inilist){ |
rinosh2 | 0:995403221573 | 126 | Status sts = get(inilist->key, (char*)inilist->buf, inilist->typelen); |
rinosh2 | 0:995403221573 | 127 | switch(sts){ |
rinosh2 | 0:995403221573 | 128 | case S_SUCCESS: |
rinosh2 | 0:995403221573 | 129 | break; |
rinosh2 | 0:995403221573 | 130 | case S_NO_KEY: |
rinosh2 | 0:995403221573 | 131 | ret = sts; // continue |
rinosh2 | 0:995403221573 | 132 | break; |
rinosh2 | 0:995403221573 | 133 | default: |
rinosh2 | 0:995403221573 | 134 | return sts; // fatal error |
rinosh2 | 0:995403221573 | 135 | } |
rinosh2 | 0:995403221573 | 136 | } |
rinosh2 | 0:995403221573 | 137 | return ret; |
rinosh2 | 0:995403221573 | 138 | } |