Simple library of INI file parser.
Dependents: TrainInfoSample WatchSensorMail
Diff: IniFile.cpp
- Revision:
- 0:995403221573
- Child:
- 1:3601c7feb547
diff -r 000000000000 -r 995403221573 IniFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IniFile.cpp Tue Nov 16 16:34:45 2010 +0000 @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////// +// IniFile: .ini file parser by rinos 2010 +/////////////////////////////////////////////////////////////////////////////// + +#include "IniFile.h" +#include <string.h> +#include <stdlib.h> + +//////////////////////////////////////////////////////////////////////////////// +// defines +const char INI_DELIM[] = " \t\r\n"; +const int INI_LINE_BUF= 256; + +//////////////////////////////////////////////////////////////////////////////// +// IniFile +IniFile::IniFile(const char* file): m_fp(0) { + if(file) open(file); +} +IniFile::~IniFile(){ + close(); +} + +//////////////////////////////////////////////////////////////////////////////// +// internal funcs +IniFile::Status IniFile::strtrim(char* dst, const char* src, int dst_size){ + if(!dst_size) return S_BUFFER_TOO_SHORT; // myStrcpy needs more than 1 byte for '\0'. + + // Find valid string area + const char* p1 = strchr (src, '"'); + const char* p2 = p1? strrchr(++p1, '"') : 0; + if(!p2){ + // trim space or tab + for(p1 = src ; *p1 && strchr(INI_DELIM, *p1) ; p1++); + if(!*p1){ // all char is space or tab + *dst = 0; + return S_SUCCESS; + } + for(p2 = p1 + strlen(p1) ; strchr(INI_DELIM, p2[-1]) ; --p2); + } + + // Check copy size + Status ret; + if(dst_size > p2 - p1){ + dst_size = p2 - p1; + ret = S_SUCCESS; + } else { + dst_size--; + ret = S_BUFFER_TOO_SHORT; + } + + // copy buffer + if(dst != p1) memmove(dst, p1, dst_size); + dst[dst_size] = 0; + return ret; +} + +//////////////////////////////////////////////////////////////////////////////// +// Access methods +IniFile::Status IniFile::open(const char* file){ + close(); + m_fp = fopen(file, "r"); + if(m_fp) return S_SUCCESS; + + //printf("IniFile: Can't open %s\n", file); + return S_OPEN_ERROR; +} + +IniFile::Status IniFile::close(){ + if(!m_fp) return S_NOT_OPENED; + + fclose(m_fp); + m_fp = 0; + return S_SUCCESS; +} + +IniFile::Status IniFile::get(const char* key, char* ret, int ret_size){ + if(!m_fp) return S_OPEN_ERROR; + + rewind(m_fp); + char line[INI_LINE_BUF]; + while(fgets(line, sizeof(line), m_fp)){ + if(*line == '#') continue; // comment line + + char* p = strchr(line, '='); + if(!p || line == p) continue; // invalid line + + *p++ = 0; + strtrim(line, line, p - line); + if(strcmp(line, key)) continue; // different key + + // check data type + switch(ret_size){ + case DTYPE_INT: + strtrim(line, p, INI_LINE_BUF); + *(int*)ret = strtoul(line, &p, 0); + //return p[0]? S_FORMAT_ERROR : S_SUCCESS; // check end + return S_SUCCESS; // always success + + case DTYPE_BOOL: + strtrim(line, p, INI_LINE_BUF); + switch(line[0]){ + case 'T': + case 't': *(bool*)ret = true; break; + case 'F': + case 'f': *(bool*)ret = false; break; + default: *(bool*)ret = strtoul(line, &p, 0)? true : false; + } + return S_SUCCESS; + + default: // string + return strtrim(ret, p, ret_size); + } + } + return S_NO_KEY; // No key +} +IniFile::Status IniFile::get(const char* key, int& ret){ + return get(key, (char*)&ret, DTYPE_INT); +} +IniFile::Status IniFile::get(const char* key, bool& ret){ + return get(key, (char*)&ret, DTYPE_BOOL); +} + + +IniFile::Status IniFile::get(IniFile::IniList* inilist){ + Status ret = S_SUCCESS; + for(; inilist->key ; ++inilist){ + Status sts = get(inilist->key, (char*)inilist->buf, inilist->typelen); + switch(sts){ + case S_SUCCESS: + break; + case S_NO_KEY: + ret = sts; // continue + break; + default: + return sts; // fatal error + } + } + return ret; +}