La clase que presento sirve para cargar valores de configuración usando el lenguaje de script LUA (www.lua.org). La ventaja de usar un lenguaje de script en el archivo de configuración es que permite incluir cierta lógica en el mismo. Por ejemplo, el fichero de configuración siguiente, impide que se cometa un error al declarar el ancho y el alto de la pantalla ( no se me ocurrió un ejemplo mejor :P )
--funcion tonta para ver que se puede incluir
-- mas significado a un fichero de configuracion
function pantalla(an,al)
al = 480 / 640 * an
return an, al
end
ancho, alto = pantalla(800,480)
otro = ancho / alto
nombre = "tholatmundontttAdiostmundo"
Y a continuación como leeríamos los valores de ancho, alto, otro y nombre desde el programa
ConfigFile mi_conf("configura.lua");
double val;
mi_conf.DaValor(val, "ancho");
printf("valor de ancho = %fn",val);
mi_conf.DaValor(val, "alto");
printf("valor de alto = %fn",val);
char *nombre=0;
mi_conf.DaValor(nombre, "nombre");
printf("valor de nombre = %sn",nombre);
mi_conf.DaValor(val, "otro");
printf("valor de otro = %fn",val);
La ventaja de usar este tipo de archivos de configuración es la potencia que tienen y a la vez la simplicidad de uso. Otra ventaja en el caso de LUA es que el archivo de configuración puede compilarse a un archivo binario, sin necesidad de tocar el programa propio.
A continuación pongo el código de la clase. Comentar lo siguiente. El constructor ejecuta el fichero de configuración y si ocurre algún error lo marca en una variable booleana, esto permite impedir que se llame erróneamente a funciones de Lua en el resto de la clase. Las funciones que comienzan con 'lua_' son del interfaz de LUA. Para ejecutar el programa se necesita 'lua.dll'.
extern "C"{
.#include "lua.h"
};
class ConfigFile{
public:
ConfigFile(const char *file);
~ConfigFile();
bool DaValor(double &val, const char *nom);
bool DaValor(const char *(&val),const char *nom);
private:
lua_State *m_lua;
bool mb_error;
};
ConfigFile::ConfigFile(const char *file){
m_lua = lua_open(100);
mb_error = (0 != lua_dofile(m_lua, file));
}
ConfigFile::~ConfigFile(){
if( mb_error ) return;
lua_close(m_lua);
}
bool ConfigFile::DaValor(double &val, const char *nom){
if( mb_error ) return false;
// meter en la pila el valor de nom
lua_getglobal(m_lua, nom);
int indice = lua_gettop(m_lua);
bool retorno = false;
// si nom es un nombre
if( lua_isnumber(m_lua, indice) ){
// obtener el valor de nom
val=lua_tonumber(m_lua, indice);
retorno = true;
}
// restaurar la pila
lua_pop(m_lua, 1);
return retorno;
}
bool ConfigFile::DaValor(const char *(&val),const char *nom){
if( mb_error ) return false;
// meter en la pila el valor de nom
lua_getglobal(m_lua, nom);
int indice = lua_gettop(m_lua);
bool retorno = false;
// si nom es un string
if( lua_isstring(m_lua, indice) ){
// obtener el valor de nom
val = lua_tostring(m_lua, indice);
retorno = true;
}
// restaurar la pila
lua_pop(m_lua, 1);
return retorno;
}
Puedes bajar el codigo de:
http://www26.brinkster.com/zhen4/config.zipUn saludo, Luis Cabellos
Web:
http://www.zhenstudio.netÉste código fue enviado por Luis Cabellos el 1 de marzo del 2003 zhen@iespana.es
Si quieres enviar tu propio código hazlo a eth_cotd@lycos.es
¡Muy interesante!
No he tenido tiempo de mirar mucho el codigo, de todas formas es una alternativa interesante a la propuesta el otro dia sobre ficheros .ini. La logica adicional q puedes añadir puede dar mucho de si. Supongo q podras usar cualquier caracteristica de LUA.
saludos
Bueno antes de que os de tiempo a mirarlo mas detenidamente :-? y me pilleis el error, el método que devuelve una cadena de texto puede dar error de memoria si se libera el objeto ConfigFile. De la siguiente manera se crea una nueva cadena y ya se encargada el usuario de borrarlo cuando crea.
if( lua_isstring(m_lua, indice) ){
// borrar val anterior
if(val) delete[] val;
// obtener el valor de nom
val = strdup(lua_tostring(m_lua, indice));
retorno = true;
}
Tambien comentar que se puede usar toda la potencia de Lua en el archivo de configuracion, aunque puede ser necesario cargar las librerias adicionales con lua_iolibopen(m_lua); lua_mathlibopen(m_lua); /*...*/
en el constructor.
Un saludo, Luis Cabellos
Yo lo haria devolviendo la cadena directamente, para algo esta std::string,
std::string pilla_valor(....)
{
char *s=lua_pillo_str(...);
return std::string(s);
}