insert code for reading double numbers from ini-file

Fork of IniFileLib by rinosh 2

IniFile.cpp

Committer:
kokisan2000
Date:
2015-01-07
Revision:
3:1f40bfa093d0
Parent:
2:4ae80a05f6ea

File content as of revision 3:1f40bfa093d0:

///////////////////////////////////////////////////////////////////////////////
// IniFile: .ini file parser    by rinos 2010
///////////////////////////////////////////////////////////////////////////////
// 07.01.2015: by DS - insert code for double format
///////////////////////////////////////////////////////////////////////////////

#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;

		case DTYPE_DOUBLE:
			strtrim(line, p, INI_LINE_BUF);
			*(double*)ret = strtod(line, &p);
			
			printf("IniFile::get %s DOUBLE %f\n", key, *(double*)ret);
			return S_SUCCESS; // always 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 char* key, double& ret){
	return get(key, (char*)&ret, DTYPE_DOUBLE);
}
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;
}