Foros - Stratos

Programadores => Código de la Semana => Mensaje iniciado por: ethernet en 16 de Febrero de 2003, 05:04:59 PM

Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 16 de Febrero de 2003, 05:04:59 PM


#include <windows.h>



#include "inifile.h"











void main()



{



      IniFile* pIni = new IniFile("settings.ini");



     



      if(pIni)



      {



             // Get [graphics]



             //            mode=...



           



             char szGraphicMode[32];



           



             pIni->GetKey((char*)szGraphicMode,"graphics","mode");



             MessageBox(NULL,szGraphicMode,"Selected mode",MB_OK);



           



             // Set [graphics]



             //            bpp=16



           



             pIni->SetKey("16","graphics","bpp");



           



             // Check [sound]



             //            3d=true



           



             if(pIni->IsKeyTrue("sound","3d"))



                    MessageBox(NULL,"3d sound enabled","Status",MB_OK);



           



           



             delete pIni;



      }



     



}





Aquí hemos supuesto que tenemos un fichero de texto en el mismo directorio del programa llamado "settings.ini" donde tenemos guardada la configuración de nuestro juego.



Primero consultamos una clave, luego modificamos una, y finalmente comprobamos que una de las claves tiene como valor "true". Hacer todo esto sin la ayuda de una clase genera mucho código.



Si probais a dar valor a una clave que no existe, comprobaréis que automáticamente se crea la sección necesaria(si no existía ya) y la clave con el nombre adecuado.



Ahora os toca a vosotros enviar los bugs que encontréis(que los tiene) y proponer posibles mejoras.



Julio Gorgé, ZS Games

Éste código fue enviado por Julio Gorgé aka ZaelsiuS el 6 de febrero del 2003

Si quieres enviar tu propio código hazlo a  eth_cotd@lycos.es
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 16 de Febrero de 2003, 05:07:07 PM
Hay q agradecer q ZaelsiuS ha subido el codigo por su cuenta y ha enviado  comentario bastante completo y util,  tal cual lo veis aqui.

gracias ;**
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: CordayUK en 20 de Febrero de 2003, 07:38:24 PM
                                mola esta muy bien!                                
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 20 de Febrero de 2003, 07:44:10 PM
Nadie dice nada ? habra q meter un poco de caña XDD

m_szFilename = new char[strlen(szFilename) +3];
strcpy(m_szFilename,".");
strcat(m_szFilename,szFilename);

q pasaria ahi si resulta q le pasamos un string sin tener un al final ? puede llegar a pasar si miras el codigo

por q no compruebas si m_szFileName es != NULL para usar las funciones

q pasaria aqui :

return WritePrivateProfileString(szSection,szKey,szBuffer,m_szFilename);

si resulta q no se ha iniciado bien la clase pero seguimos usandola ?

yo pondria un assert(m_szFileName); para chequear eso en debug o usar un if(m_zsFileNmae) { resto de la funcion}


otra cosa, es necesario poner un "."  antes del fichero? asi no podras usar inis de fuera de la carpeta del exe a no ser q cambies de directorio :(


La verdad q son estupideces pero nadie hablaba xDDD por lo demas me parece un buen codigo, util y limpio.

saludos
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: CordayUK en 20 de Febrero de 2003, 07:49:31 PM
                                de paso voy y pregunto yo algo....

el tipico fichero .ini guardas cadenas y booleanos, genial que tengamos un GetKey () y un IsTrue () etc... pero tambien podemos tener valores float por ejemplo, molaria ampliar la clase con un GetFlaot () en lugar de tener que convertir el texto a mano despues.
Yo en mis ficheros ini tambien guardo DWORD por ejemplo

[FOG]
FogColor=0xccffaa22
FogMaxZ=50.0

molaria tambien tener un GetDW () entonces.
lo que yo hago es parsear cada numero de la cadena 0xccff... y crear un dword a mano y devolverlo.  es un poco tedioso la verdad. Si alguien conoce algun metodo para hacerlo de forma elegante que lo postee aqui!! :)                                
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 20 de Febrero de 2003, 07:55:07 PM
corday cabron, no jodas el COTW de la semana proxima XDD
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: CordayUK en 20 de Febrero de 2003, 07:56:32 PM
                                era una mierda de COTW de todas formas XDDDDDDDDDDD                                
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 21 de Febrero de 2003, 08:54:08 PM
Gracias por comentar un poco el COTW!!

Pues me apunto los bugs y sugerencias, y respecto a lo de incluir . en la clase... sólo se que no me iba bien si no lo ponía delante(no estoy seguro ahora mismo si es por alguna movida del debug working directory del VC++), así que si alguien lo prueba pues mejor.

No lo intenté probar yo pq como se supone que los .ini van dentro de la carpeta del exe(aunque alguien querría poner exe en /bin y .ini's en /config por ejemplo).

Ethernet: cuando en el constructor pongo "szFilename", indico al programador que se trata de una cadena acabada con mediante
el sufijo sz(intento seguir la notación húngara de MS :D ).

También añadiré la posibilidad de leer DWORD's y alguna cosilla más.
Cuando revise la clase ya lo postearé por aquí. Y mejor aun, si alguien se anima a hacerlo, que me envie la clase y la reemplazo en mi web.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 22 de Febrero de 2003, 03:21:10 PM
comentaba lo del . por q algunos programas guardan sus configuraciones en c:windows o similar pero es un detalle sin importancia.

Con el cotw de corday q esta por llegar se puede mejorar tu clase para lo q comentaba corday...mañana lo veremos :DD

saludos
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 23 de Agosto de 2003, 10:04:33 PM
 Rebuscando entre el código de Emule y xMule, he encontrado la clase dedicada a manejo de ficheros .ini y (aparte de ser la misma en los dos programas) es similar a la que puse en este cotw, aunque está algo más completa.

En el caso de xMule, creo que en las plataformas no windows deben utilizar algun otro mecanismo, pq la clase se basa en las funciones de la API win32 - como writeprivateprofilestring(), etc...-  creo(aun no lo he comprobado) que dichos casos echan mano de la librería wxWindows(puede que hayan clonado estas funciones).
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 23 de Agosto de 2003, 11:23:57 PM
 mira los fuentes del unreal, hay una solucion completamente portable. Yo por otra parte hice la mia propia un dia q la necesitaba para alguna chorrada:


namespace conf
{
   typedef  std::string st;
   typedef  st::size_type sz_t;
   typedef  std::map<st,st> Vars;
   typedef  std::map<st,Vars> ini_t;
   typedef  const st c_st;
   typedef  char const * const ccc;
   
   enum { BUFF = 256 , CTAG = ';'};  

   class IniFile: public ini_t
   {  
           typedef  std::vector<st> ArgList;        
           bool isws (char c,ccc wstr){return strchr(wstr,c)!=0;}
           st trim(c_st &s,sz_t &idx,ccc ws= " "){
               sz_t i = s.find_first_not_of(ws,idx);
               sz_t j = idx = s.find_first_of(ws,i);
               return st(s.substr(i,j-i));
             
           }
           void stk (ArgList &l,c_st &s,ccc ws = " \r\t\n"){
               sz_t i = 0;l.clear();
               while (i<s.size())l.push_back(trim(s,i,ws));  
           }
       public:
           IniFile(ccc f= 0){ if(f)readvars(f); }
           bool readvars(c_st& file)
           {
               char b[BUFF];
               st secc;
               ArgList a;
               ifstream f(file.c_str(),ios::in|ios::nocreate);
               f.getline(b,BUFF);        
               while(f.good())
               {              
                   stk(a,b," \t\r\n=");
                   if(a.size() && a[0][0]!=CTAG)
                        if(a[0][0]=='[') secc=a[0].substr(1,a[0].size()-2);              
                        else   (*this)[secc][a[0]]=a[1];      
                   f.getline(b,BUFF);        
               }
               return f.bad();
           }
   };
};
int main(int argc, char* argv[])
{
   conf::IniFile a("1.ini");
   
   cout << a["holas"]["hola"].c_str() << endl;
   cout << a["juego"]["var"].c_str() << endl;
   
return 0;
}
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 24 de Agosto de 2003, 12:51:15 AM
 Yo tb estaba haciendo una implementación portable ahora... XD    ¡marikita el resto!  :lol:  
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: DraKKaR en 24 de Agosto de 2003, 12:17:07 PM
 Ei, si haceis una implementacion completamente portable avisad (que no dependa de nada)! Yo tambien uso ficheros ini para nuestro juego, y me estaba preguntando si tendria ke reescribir las funciones de tratamiento de ficheros ini a pelo para que furulara en linux.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 24 de Agosto de 2003, 01:58:53 PM
 La implementación que estoy haciendo es totalmente portable, pq la necesitamos para linux/windows. Aparte de algunas optimizaciones y tal, hay soporte para leer directamente booleanos, dwords, y alguna cosilla más.  Supongo que para mediados de septiembre la tendré lista, pq ahora no puedo avanzar demasiado con los estudios y movidas varias.

PD. la sobrecarga del operador [] de la implementación de Unreal mola!
PDD. la implementación de Quake III es ininteligible XD, sólo hay comentarios al respecto de posibles bugs o mejoras... y como lo hacen todo sin clases, con C a pelo, no hay quien entienda nada mirándola por encima
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ethernet en 24 de Agosto de 2003, 05:41:35 PM
 uh? donde esta la sobrecarga del operador [] en el codigo del unreal? no sera la del Map ?  
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 24 de Agosto de 2003, 08:16:52 PM
Cita de: "ethernet"uh? donde esta la sobrecarga del operador [] en el codigo del unreal? no sera la del Map ?
Si, fallo mio, es que utilizar el pc sin ratón me estresa XD.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 13 de Octubre de 2003, 08:20:57 PM
 Vuelvo a dar por saco con el IniFile...  :P

Aquí teneis una versión beta de IniFile 1.0.

Como novedades, pues la principal es la portabilidad, o sea Windows/Linux/etc.. . Tambien he añadido algunas mejoras para leer DWORD's y bueno, mejor os enseño la interfaz pública:


class IniFile
{

public:

// Constructors
IniFile();
IniFile(const char* szFilename);
~IniFile();

// File handling

int Open(const char* szFilename);
void Close();

// Data handling functions
 
int GetKey(char* szBuffer, const DWORD dwSize, const char* szSection, const char* szKey);
int GetKey(DWORD* dwValue, const char* szSection, const char* szKey);
int GetKey(int* iValue, const char* szSection, const char* szKey);
int GetKey(bool* bValue,const char* szSection,const char* szKey);

int SetKey(const char* szBuffer, const char* szSection, const char* szKey);
int SetKey(const DWORD dwValue, const char* szSection, const char* szKey);
int SetKey(const int iValue, const char* szSection, const char* szKey);
int SetKey(const bool bValue,const char* szSection,const char* szKey);
 
bool IsKeyTrue(const char* szSection, const char* szKey);
bool IsKeyFalse(const char* szSection, const char* szKey);
 
bool IsKeyLike(const char* szStringLike, const char* szSection, const char* szKey);

...

}


Funciona muy bien, pero supongo que debe haberseme escapado algo... si fueseis tan amables de probarla o mirarla un poco os lo agradeceria.  :P

Miraos el ejemplo Initest.cpp pq algunas cosas han cambiado a la hora de usar la clase y detectar errores.

Os digo de antemano que faltan más comentarios y renombrar alguna variable para no ofuscar el código en algunos sitios.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 13 de Octubre de 2003, 08:24:21 PM
 Sobre las funciones GetKey*...

Comprobar el valor de retorno de las funciones miembro es un poco rollo.. lo sé. ¿ Qué tal os pareceria la inclusión de un cuarto parámetro que incluya el valor por defecto a devolver en caso de error?

Algo como GetKey(&myint,"seccion","clave",VALOR_X_DEFECTO);
:huh:  
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: DraKKaR en 13 de Octubre de 2003, 09:50:14 PM
 secundo la proposición de Zaelsius (mm creo que nunca habia escrito tu nick), es como se hace en la API de Windows y es muy útil a mi parecer.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 25 de Octubre de 2003, 12:31:02 AM
 Dicho y hecho  B)

Download "Rilís Candideit 1" en http://www.alu.ua.es/j/jgf8/code/IniFileRC1.zip

- Añadido el parámetro de valor de retorno por defecto.
- Corregidos pequeños bugs
- Quedan pequeñas cosas por arreglar pero es 100% estable y funcional
- Multiplataforma.. aunque requiere STL-port o SGI STL para compilar(eso no lo dije antes)
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 10 de Enero de 2004, 04:18:29 PM
 IniFile Release Candidate 4 disponible en:
http://www.alu.ua.es/j/jgf8/code/IniFile-RC4.zip

Cambios más importantes:

- Ya no requiere STL de SGI/STLPort para compilar.
- Testada con GCC.
- Licencia LGPL(es la adecuada no?)
- Algunos bugs solucionados.

Incluye un .cpp de ejemplo.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zeigon en 10 de Enero de 2004, 10:27:42 PM
 ahora no necesito las STL, después de habermelas instalado  <_<    bueno así me obligo a aprender a manejarlas :)


aprovecho para hacerte una pregunta pq me da un error y no sé si será de tu IniFile. Yo tengo un archivo .ini:

[bart]
muestra = Images/bart.gif

[fondo]
casa = Images/casa.jpg


y quiero cargar las 2 imágenes. es en sdl, así q 1º cargo el ini y bien, cargo a bart y bien, pero el error me da cuando cargo el fondo. Vamos el error le he puesto q me lo saque por el archivo stderr si da error al cargar la imagen con SDL.

el código de la función que cargas las imágenes es este (está hecho deprisa sólo pa parobar si funcionaba):


void InitImages()
{
 
char cBuffy[256]; //Buffer para el contenido de las claves del archivo

if(ConfigFile.Open("prueba.ini")!=INI_OK)
{
 fprintf(stderr, "Error al cargar el archivo de configuración");
 exit(0);
}


//Carga fondo

if(ConfigFile.GetKey((char*)cBuffy,sizeof(cBuffy),"fondo","casa")!=INI_OK)
{
 fprintf(stderr, "Error en la búsqueda en el archivo de configuración de fondo");
 exit(0);
}

if(!(back = IMG_Load(cBuffy)))
{
 fprintf(stderr,"Error al cargar la imagen: %s\n", IMG_GetError());
 exit(0);
}

//Fin carga fondo


//Carga personaje

if(ConfigFile.GetKey((char*)cBuffy,sizeof(cBuffy),"bart","muestra")!=INI_OK)
{
 fprintf(stderr, "Error en la búsqueda en el archivo de configuración de personaje");
 exit(0);
}
 
if(!(image = IMG_Load(cBuffy)))
{
 fprintf(stderr,"Error al cargar la imagen: %s\n", IMG_GetError());
 exit(0);
}

//Fin carga personaje

}



entonces ejecuta y se sale, diciendo que no se ha podido cargar el fondo. sí lo q hago es 1º cargar el personaje, me lo carga pero el error me da otra vez en el fondo. Vamos cambiar las cargas de imágenes de orden, bart arriba y fondo abajo. Y ya no sé que hacer (aunq lo mismo cuando rehaga todo el código ya sale...) porque no es de la imagen, q si pongo IMG_Load("Images/casa.jpg") tal cual, en vez de cBuffy q es lo q devuelve el GetKey, sí q carga el fondo.

ya no sé q puede ser   :blink:  :(
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 10 de Enero de 2004, 11:52:20 PM
 Acabo de probar tu código(obviando los IMG_loads) y funciona bien.
Para salir de dudas podrias imprimir el valor de cBuffy entre el GetKey y el IMG_Load, asi sabrás si es el inifile lo que falla(tendrás que quitar los exit())

Usas Linux? GCC?
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zeigon en 11 de Enero de 2004, 03:43:05 AM
 pues nada, no me va.

he cambiado la búsqueda para que saque cBuffy a stdout, pero no escribe nada.


if(ConfigFile.GetKey((char*)cBuffy,sizeof(cBuffy),"fondo","casa")!=INI_OK)
{
 fprintf(stdout,"cBuffy = %s", cBuffy);
 fprintf(stderr, "Error en la búsqueda en el archivo de configuración de fondo\n");
 exit(0);
}

pongo el fprintf ahí pq es en ese exit donde se pira, asi q tengo q ponerlo dentro. si lo quito se me va en el exit del IMG_Load, así q...

lo q me saca el stdout es:

cBuffy = nada más.

por cierto, tengo W2000 Professional y VC++ 6. q raro es pq si encima dices q a ti te funciona...  :blink:
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 15 de Enero de 2004, 11:40:55 PM
 Acabo de probar el código con GCC(cygwin) y me falla, aunque en VS.NET sí funciona bien, tanto en release como en debug, y Windows 2000 :huh: .

Lo depuraré como pueda con gdb a ver que coj@#~@ pasa. Si no consigo ver nada con gdb, el lunes en la uni probaré suerte con VC6.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 16 de Enero de 2004, 12:09:03 AM
 Pues ahora no me falla, no sé si la primera vez ha sido un espejismo o q...

Prueba en tu compilador este código concreto, con el prueba.ini que pusiste arriba:


#include <cstdio>
#include "inifile.h"

int main()
{

IniFile ConfigFile;

char cBuffy[256]; //Buffer para el contenido de las claves del archivo

if(ConfigFile.Open("prueba.ini")!=INI_OK)
{
fprintf(stderr, "Error al cargar el archivo de configuración\n");
exit(0);
}

//Carga fondo

if(ConfigFile.GetKey((char*)cBuffy,sizeof(cBuffy),"fondo","casa")!=INI_OK)
{
fprintf(stdout,"cBuffy = %s", cBuffy);
fprintf(stderr, "Error en la búsqueda en el archivo de configuración de fondo\n");
exit(0);
}

//Fin carga fondo

printf("%s\n",cBuffy);

//Carga personaje

if(ConfigFile.GetKey((char*)cBuffy,sizeof(cBuffy),"bart","muestra")!=INI_OK)
{
fprintf(stdout,"cBuffy = %s", cBuffy);
fprintf(stderr, "Error en la búsqueda en el archivo de configuración de personaje");
exit(0);
}

printf("%s\n",cBuffy);

//system("pause");
//Fin carga personaje

}



Si alguien se aburre mucho en su casa que pruebe si le funciona  :blink:

Edit: Zeigon, ¿el initest.cpp que viene en el último paquete te funciona?
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ALRAZ en 27 de Septiembre de 2004, 04:15:25 AM
 Pregunta estúpida:

Qué tal si lo que quiero es tener una sección, donde el usuario le ponga nombre a las variables?
Algo como:



;Los números representa el gráfico que se utilizará en cada frame de la animación

[Animaciones]
Parado = 1, 2, 3, 3, 3, 3, 2, 2, 1
Andando = 5, 6, 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5



sería bueno tener una función como


GetKey (Destino, NombreSeccion, VariableN)

y recorrer todas las variables de una sección en un ciclo:



char Tmp [256], Valor;
unsigned int Contador;

   while ( (Valor = GetKey (Tmp, "Animaciones", Contador ++)) == INI_OK)
   {
             // Aquí Tmp sería el nombre de la variable encontrada en la posición Contador
          //y Valor contendría .... pos eso XD el valor de la variable
    }
 


Inclusive, se podría usar el valor de Tmp  para hacer otra llamada a GetKey, pasando
Tmp como nombre de la variable que buscamos.

La función regresaría algo distinto a INI_OK cuando la variable N no se encuentre en dicha sección
Es decir: La sección tiene menos de N variables.

espero la idea sea factible  :)
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 27 de Septiembre de 2004, 01:51:05 PM
 Hola Alraz. Tu idea es buena, me la apunto para implementarla pronto. Te recomiendo que descargues la última versión de IniFile desde http://www.lemonteam.com (está incluida en un paquete llamado LemonGT).
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ALRAZ en 10 de Septiembre de 2005, 10:30:18 AM
 Wenas


ZaelSius:
estuve manoseando un poco el código de tu clase para manejar archivos .Ini

y le agregué un poco de funcionalidad. Si te interesa te puedo enviar los archivos modificados para que le eches un ojo.

Funcionalidad agregada:
-Método para obtener el nombre de una sección, dada su posición en el archivo .Ini (es decir "Dame el nombre de la tercera sección")
-Método para saber cuanta secciones tiene el archivo Ini
-Método para saber si una sección existe (HasSection (NombreDeLaSeccion)
-No distingue entre mayúsculas y minúsculas! case-sensitiveless rulez!

también corregí algunos errores leves, como el hecho de que el método CacheSections no ignoraba los comentarios.
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: Zaelsius en 10 de Septiembre de 2005, 02:40:33 PM
 Hace poco reescribí la clase, simplificando mucho el código internamente, y dejándola en un sólo .H

inifile.h

Ahora debería ser mucho más fácil de leer y modificar :ph34r: . A ver si actualizado la página de una vez, y saco el inifile de la libreria LemonGT(que la tengo super abandonada :P). Esta versión funciona correctamente en Win/Linux/Mac. La antigua hacía alguna cosa rara al reescribir los ficheros en un SO. Tambien le he puesto licencia ZLib, más permisiva que la LGPL.

Pues nada, si te animas a aplicarle los cambios... mira el código, es realmente sencilla ahora.

Para enviarme cosas, usa julio ((en)) lemonteam ((punto)) com
Título: Clase para manejo de ini - Julio Gorgé
Publicado por: ALRAZ en 12 de Septiembre de 2005, 10:27:54 AM
 ok...

estoy tratando de hacer una especialización de la clase string para que convierta todo a mayúsculas y así hacerlo case-sensitiveless

el problema es que aparentemente no se pueden derivar clases de clases standar


class CaselessStr : public std::string
{

};

CaselessStr Texto = "Algo";   //Error! no se ha heredado absolutamente nada!


el resultado del anterior código es una clase totalmente vacía

luego intenté con algo como

class CaselessStr
{
private:
  string strOriginal;

public:
  //...
  CaselessStr &operator = (const string &Str);
  //...
}


pero me di por vencido luego de múltiples errores en el IniMap relacionados con los corchetes
Seguro me han de faltar varios operadores....

pero qué sé yo...


sugerencias?


(todo esto en visual studio .net 2003)