Tutorial WinAPI C++ 3.9 (Creación del ObjetoZLIB)
Categorías : Windows, Programación, C y C++.

En este tutorial vamos a encapsular las funciones de la ZLIB (libreria de compresion y descompresion escrita por Jean-loup-Gailly y Mark Adler) en un objeto que usaremos tanto en la aplicacion Instalador como en la aplicacion Ensamblador.
De esta forma nos crearemos un objeto que con una linea de codigo sera capaz de comprimir / descomprimir un archivo, y asi no tendremos que preocuparnos mas por este tema una vez creemos las aplicaciones finales de este tutorial.
Lo primero será diseñar un contenedor al que se le puedan agregar partes binarias, que será el destinado a contener los archivos comprimidos / descomprimidos en memoria. Para ello crearemos el objeto ContenedorBinario, veamos su declaración :
// Clase destinada a contener datos comprimidos// Se ha hecho de forma que se puede agregar un archivo por partes de tamaño variable.class ContenedorBinario {public : //////// Miembros publicos// -ConstructorContenedorBinario(void) {_Longitud = 0;_Datos = NULL;};// -Destructor~ContenedorBinario(void) {if (_Datos != NULL) delete [] _Datos;};// -Función para agregar una partevoid AgregarParte(const char *NuevaParte, const size_t LongitudParte) {char *NuevosDatos = new char [_Longitud + LongitudParte];if (_Datos != NULL) {CopyMemory(NuevosDatos, _Datos, _Longitud);delete [] _Datos;}CopyMemory(&NuevosDatos[_Longitud], NuevaParte, LongitudParte);_Datos = NuevosDatos;_Longitud += LongitudParte;};// -Operador que retorna una referencia a los datos// de esta clase en la posición especificadachar *operator[] (const UINT nPos) {return &_Datos[nPos];};// -Operador que retorna la posicion de inicio de// los datos que contiene esta clasechar *operator() (void) const {return _Datos;};// -Función que retorna el tamaño total de los datos de esta claseUINT Longitud(void) const {return _Longitud;};// -Función que borra los datos de esta clasevoid Borrar(void) {_Longitud = 0;if (_Datos != NULL) delete [] _Datos;_Datos = NULL;};protected : ///// Miembros protegidos// -Miembro que contiene los datos agregadoschar *_Datos;// -Miembro que contiene el tamaño de la variable _DatosUINT _Longitud;};
Este objeto nos permite ir agregando partes binarias variables de forma que queden concatenadas. Esto se hace así porque la ZLIB tanto para comprimir como para descomprimir lo hace por trozos. Además en nuestro caso necesitamos añadir todos los archivos comprimidos a un solo archivo, por lo que la mejor opción es mantener el archivo comprimido en memoria.
Ahora veamos la declaración del ObjetoZLIB :
// Clase que contiene las funciones necesarias para ensamblar el instalador, y para instalarseclass ObjetoZLIB {public : //////////////////// Miembros publicos// -ConstructorObjetoZLIB(void);// -Destructor~ObjetoZLIB(void);// -Función que comprime un archivo dentro de una clase ContenedorBinarioconst BOOL Comprimir(const TCHAR *nPathOrigen, ContenedorBinario &Datos);// -Función que descomprime un ContenedorBinario y lo guarda en nPathDestino como un archivoconst BOOL Descomprimir(ContenedorBinario &Datos, const TCHAR *nPathDestino);};
Este objeto tiene dos métodos públicos : Comprimir y Descomprimir.
Veamos la función Comprimir :
const BOOL ObjetoZLIB::Comprimir(const TCHAR *nPathOrigen, ContenedorBinario &Datos) {ObjetoArchivo Origen;Datos.Borrar();// Si el archivo origen no se puede abrir retornamos FALSEif (Origen.AbrirArchivoLectura(nPathOrigen) == false) return FALSE;int ret, flush;unsigned have;z_stream strm;char in[CHUNK];char out[CHUNK];// Inicializaciónstrm.zalloc = Z_NULL;strm.zfree = Z_NULL;strm.opaque = Z_NULL;ret = deflateInit(&strm, 5);if (ret != Z_OK) return FALSE;// Comprimimos hasta el final del archivodo {strm.avail_in = Origen.Leer(&in, CHUNK * sizeof(char));flush = Origen.FinalDelArchivo() ? Z_FINISH : Z_NO_FLUSH;strm.next_in = reinterpret_cast<Bytef *>(&in[0]);// Ejecutamos deflate hasta que comprimamos todo el archivodo {strm.avail_out = CHUNK;strm.next_out = reinterpret_cast<Bytef *>(&out[0]);ret = deflate(&strm, flush);have = CHUNK - strm.avail_out;Datos.AgregarParte(out, have);} while (strm.avail_out == 0);} while (flush != Z_FINISH);// Liberamos la memoria usada por la zlibdeflateEnd(&strm);return TRUE;}
Esta función abre el archivo a comprimir, lee el archivo a partes, comprime cada parte, y introduce las partes dentro del ContenedorBinario.
Y por último la función Descomprimir :
const BOOL ObjetoZLIB::Descomprimir(ContenedorBinario &Datos, const TCHAR *nPathDestino) {ObjetoArchivo Destino;// Si el archivo destino no se puede abrir retornamos FALSEif (Destino.AbrirArchivoEscritura(nPathDestino, true) == FALSE) return FALSE;int ret;unsigned have;z_stream strm;char in[CHUNK] = "";char out[CHUNK] = "";unsigned int Posicion = 0;// Inicializaciónstrm.zalloc = Z_NULL;strm.zfree = Z_NULL;strm.opaque = Z_NULL;strm.avail_in = 0;strm.next_in = Z_NULL;ret = inflateInit(&strm);if (ret != Z_OK) return FALSE;// Descomprimimos hasta que se terminen los datosdo {if (Posicion + CHUNK < Datos.Longitud()) {memcpy(in, Datos[Posicion], CHUNK);strm.avail_in = CHUNK;}else {memcpy(in, Datos[Posicion], Datos.Longitud() - Posicion);strm.avail_in = Datos.Longitud() - Posicion;}Posicion += CHUNK;if (strm.avail_in == 0)break;strm.next_in = reinterpret_cast<Bytef *>(&in[0]);// Ejecutamos inflate para extraer los datosdo {strm.avail_out = CHUNK;strm.next_out = reinterpret_cast<Bytef *>(&out[0]);ret = inflate(&strm, Z_NO_FLUSH);switch (ret) {case Z_NEED_DICT:ret = Z_DATA_ERROR;case Z_DATA_ERROR:case Z_MEM_ERROR:(void)inflateEnd(&strm);return ret;}have = CHUNK - strm.avail_out;Destino.Guardar(out, have);} while (strm.avail_out == 0);// Terminamos cuando inflate retorne Z_STREAM_END} while (ret != Z_STREAM_END);// Liberamos la memoria usada por la ZLIBinflateEnd(&strm);return (ret == Z_STREAM_END) ? TRUE : FALSE;}
Esta función abre el archivo a descomprimir, lee el ContenedorBinario por partes, descomprime cada parte, y va guardando las partes descomprimidas en el path destino.
Con esto ya tenemos todos los requisitos para crear el instalador.
Siguiente tutorial : 3.10 Terminando el Instalador