Claes Ekengren / Mbed 2 deprecated Measurement_system

Dependencies:   mbed

IniFileLib/IniFile.cpp

Committer:
CE
Date:
2011-01-06
Revision:
0:0732b16d9a92

File content as of revision 0:0732b16d9a92:

///////////////////////////////////////////////////////////////////////////////
// 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){
        printf("IniFile::get %s S_OPEN_ERROR\n", key);
        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 // stricmp?

        // 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
            printf("IniFile::get %s INT %d\n", key, *(int*)ret);
            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;
            }
            printf("IniFile::get %s BOOL %d\n", key, *(bool*)ret);
            return S_SUCCESS;

        default: // string
            {
                Status sts = strtrim(ret, p, ret_size);
                printf("IniFile::get %s = '%s'\n", key, ret_size? ret : "E");
                return sts;
            }
        }
    }
    printf("IniFile::get S_NO_KEY'%s'\n", key);
    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(const 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;
}