Les fonctions de base
Voici les fonctions de base de la bibliothèque zlib :
ZEXTERN const char * ZEXPORT zlibVersion(void); |
L'application peut comparer zlibVersion et ZLIB_VERSION pour vérifier la cohérence. Si le premier caractère diffère, le code de la bibliothèque réellement utilisé n'est pas compatible avec le fichier d'entête zlib.h utilisé par l'application. Cette vérification est effectuée automatiquement par deflateInit et inflateInit.
ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); |
Initialise l'état du flux interne pour la compression. Les champs zalloc, zfree et opaque doivent être initialisés au préalable par l'appelant. Si zalloc et zfree sont définis sur Z_NULL, deflateInit les met à jour pour utiliser les fonctions d'allocation par défaut. total_in, total_out, adler et msg sont initialisés.
Le niveau de compression doit être Z_DEFAULT_COMPRESSION, ou compris entre 0 et 9 : 1 donne la meilleure vitesse, 9 donne la meilleure compression, 0 ne donne aucune compression (les données d'entrée sont simplement copiées bloc par bloc). Z_DEFAULT_COMPRESSION demande un compromis par défaut entre vitesse et compression (actuellement équivalent au niveau 6).
deflateInit renvoie Z_OK en cas de succès, Z_MEM_ERROR s'il n'y avait pas assez de mémoire, Z_STREAM_ERROR si level n'est pas un niveau de compression valide, Z_VERSION_ERROR si la version de la bibliothèque zlib (zlib_version) est incompatible avec la version supposée par l'appelant (ZLIB_VERSION). msg est défini sur null s'il n'y a pas de message d'erreur. deflateInit n'effectue aucune compression : cela sera fait par deflate().
ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); |
deflate compresse autant de données que possible et s'arrête lorsque le tampon d'entrée devient vide ou que le tampon de sortie devient plein. Il peut introduire une certaine latence de sortie (lecture d'entrée sans produire de sortie) sauf en cas de vidage forcé.
La sémantique détaillée est la suivante. deflate effectue une ou les deux actions suivantes :
- Compresser plus d'entrées à partir de next_in et mettre à jour next_in et avail_in en conséquence. Si toutes les entrées ne peuvent pas être traitées (parce qu'il n'y a pas assez de place dans le tampon de sortie), next_in et avail_in sont mis à jour et le traitement reprendra à ce stade pour le prochain appel de deflate().
- Générer plus de sortie à partir de next_out et mettre à jour next_out et avail_out en conséquence. Cette action est forcée si le paramètre flush est différent de zéro. Le fait de forcer flush dégrade fréquemment le taux de compression, ce paramètre ne doit donc être défini que lorsque cela est nécessaire. Une sortie peut être fournie même si flush est nul.
Avant l'appel de deflate(), l'application doit s'assurer qu'au moins une des actions est possible, en fournissant plus d'entrées et/ou en consommant plus de sorties, et en mettant à jour avail_in ou avail_out en conséquence; avail_out ne doit jamais être nul avant l'appel. L'application peut consommer la sortie compressée quand elle le souhaite, par exemple lorsque le tampon de sortie est plein (avail_out == 0), ou après chaque appel de deflate(). Si deflate renvoie Z_OK et avec avail_out nul, il doit être rappelé après avoir fait de la place dans le tampon car il peut y avoir plus de sorties en attente. Voir deflatePending(), pouvant être utilisé si vous le souhaitez pour déterminer s'il y a plus de sorties ou non dans ce cas.
Normalement, le paramètre flush est défini sur Z_NO_FLUSH, ce qui permet à deflate de décider de la quantité de données à accumuler avant de produire une sortie, afin de maximiser la compression.
Si le paramètre flush est défini sur Z_SYNC_FLUSH, toutes les sorties en attente sont vidées dans le tampon de sortie et la sortie est alignée sur une limite d'octet, de sorte que le décompresseur puisse obtenir toutes les données d'entrée disponibles jusqu'à présent. (En particulier, avail_in est nul après l'appel si suffisamment d'espace de sortie a été fourni avant l'appel.) Le vidage peut dégrader la compression pour certains algorithmes de compression et ne doit donc être utilisé que lorsque cela est nécessaire. Cela complète le bloc de dégonflage actuel et le suit avec un bloc stocké vide de trois bits plus des bits de remplissage jusqu'à l'octet suivant, suivi de quatre octets (00 00 ff ff).
Si flush est défini sur Z_PARTIAL_FLUSH, toutes les sorties en attente sont vidées dans le tampon de sortie, mais la sortie n'est pas alignée sur une limite d'octet. Toutes les données d'entrée jusqu'à présent seront disponibles pour le décompresseur, comme pour Z_SYNC_FLUSH. Cela complète le bloc de dégonflage actuel et le suit avec un bloc de codes fixes vide de 10 bits de long. Cela garantit qu'un nombre suffisant d'octets est émis pour que le décompresseur termine le bloc avant le bloc de codes fixes vide.
Si flush est défini sur Z_BLOCK, un bloc de décompression est terminé et émis, comme pour Z_SYNC_FLUSH, mais la sortie n'est pas alignée sur une limite d'octet, et jusqu'à sept bits du bloc actuel sont conservés pour être écrits comme l'octet suivant après la fin du bloc de décompression suivant. Dans ce cas, le décompresseur peut ne pas disposer de suffisamment de bits à ce stade pour terminer la décompression des données fournies jusqu'à présent au compresseur. Il peut être nécessaire d'attendre que le bloc suivant soit émis. Ceci est destiné aux applications avancées qui doivent contrôler l'émission de blocs de décompression.
Si flush est défini sur Z_FULL_FLUSH, toutes les sorties sont vidées comme avec Z_SYNC_FLUSH, et l'état de compression est réinitialisé afin que la décompression puisse redémarrer à partir de ce point si les données compressées précédentes ont été endommagées ou si un accès aléatoire est souhaité. L'utilisation trop fréquente de Z_FULL_FLUSH peut sérieusement dégrader la compression.
Si deflate renvoie avec avail_out == 0, cette fonction doit être appelée à nouveau avec la même valeur du paramètre flush et plus d'espace de sortie (avail_out mis à jour), jusqu'à ce que le vidage soit terminé (deflate renvoie avec avail_out différent de zéro). Dans le cas d'un Z_FULL_FLUSH ou Z_SYNC_FLUSH, assurez-vous que avail_out est supérieur à six lorsque le marqueur de vidage commence, afin d'éviter des marqueurs de vidage répétés lors de l'appel à nouveau de deflate() lorsque avail_out == 0.
Si le paramètre flush est défini sur Z_FINISH, l'entrée en attente est traitée, la sortie en attente est vidée et deflate renvoie avec Z_STREAM_END s'il y avait suffisamment d'espace de sortie. Si deflate renvoie Z_OK ou Z_BUF_ERROR, cette fonction doit être appelée à nouveau avec Z_FINISH et plus d'espace de sortie (avail_out mis à jour) mais plus de données d'entrée, jusqu'à ce qu'elle renvoie Z_STREAM_END ou une erreur. Une fois que deflate a renvoyé Z_STREAM_END, les seules opérations possibles sur le flux sont deflateReset ou deflateEnd.
Z_FINISH peut être utilisé dans le premier appel deflate après deflateInit si toute la compression doit être effectuée en une seule étape. Pour terminer en un seul appel, avail_out doit être au moins la valeur renvoyée par deflateBound (voir ci-dessous). deflate est alors assuré de renvoyer Z_STREAM_END. Si l'espace de sortie fourni est insuffisant, deflate ne renverra pas Z_STREAM_END et il devra être appelé à nouveau comme décrit ci-dessus.
deflate() définit strm->adler sur la somme de contrôle Adler-32 de toutes les entrées lues jusqu'à présent (c'est-à-dire total_in octets). Si un flux gzip est généré, strm->adler sera alors la somme de contrôle CRC-32 des entrées lues jusqu'à présent. (Voir deflateInit2 ci-dessous.)
deflate() peut mettre à jour strm->data_type s'il peut deviner le type de données d'entrée (Z_BINARY ou Z_TEXT). En cas de doute, les données sont considérées comme binaires. Ce champ est uniquement à titre informatif et n'affecte en aucune manière l'algorithme de compression.
deflate() renvoie Z_OK si des progrès ont été réalisés (plus d'entrées traitées ou plus de sorties produites), Z_STREAM_END si toutes les entrées ont été consommées et toutes les sorties produites (uniquement lorsque flush est défini sur Z_FINISH), Z_STREAM_ERROR si l'état du flux était incohérent (par exemple si next_in ou next_out était Z_NULL ou si l'état a été écrasé par inadvertance par l'application), ou Z_BUF_ERROR si aucune progression n'est possible (par exemple avail_in ou avail_out était nul). Notez que Z_BUF_ERROR n'est pas fatal et que deflate() peut être appelé à nouveau avec plus d'espace d'entrée et plus d'espace de sortie pour continuer la compression.
ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); |
Toutes les structures de données allouées dynamiquement pour ce flux sont libérées. Cette fonction rejette toute entrée non traitée et ne vide aucune sortie en attente.
deflateEnd renvoie Z_OK en cas de succès, Z_STREAM_ERROR si l'état du flux était incohérent, Z_DATA_ERROR si le flux a été libéré prématurément (une entrée ou une sortie a été rejetée). En cas d'erreur, msg peut être défini mais pointe alors vers une chaîne statique (ne devant pas être désallouée).
ZEXTERN int ZEXPORT inflateInit(z_streamp strm); |
Initialise l'état du flux interne pour la décompression. Les champs next_in, avail_in, zalloc, zfree et opaque doivent être initialisés au préalable par l'appelant. Dans la version actuelle d'inflate, l'entrée fournie n'est ni lue ni consommée. L'allocation d'une fenêtre glissante sera différée au premier appel d'inflate (si la décompression ne se termine pas au premier appel). Si zalloc et zfree sont définis sur Z_NULL, inflateInit les met à jour pour utiliser les fonctions d'allocation par défaut. total_in, total_out, adler et msg sont initialisés.
inflateInit renvoie Z_OK en cas de succès, Z_MEM_ERROR s'il n'y avait pas assez de mémoire, Z_VERSION_ERROR si la version de la bibliothèque zlib est incompatible avec la version supposée par l'appelant, ou Z_STREAM_ERROR si les paramètres ne sont pas valides, comme un pointeur nul vers la structure. msg est défini sur null s'il n'y a pas de message d'erreur. inflateInit n'effectue aucune décompression. La décompression proprement dite sera effectuée par inflate(). Ainsi, next_in, avail_in, next_out et avail_out ne sont pas utilisés et ne sont pas modifiés. L'implémentation actuelle de inflateInit() ne traite aucune information d'entête, étant différée jusqu'à ce que inflate() soit appelé.
ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); |
inflate décompresse autant de données que possible et s'arrête lorsque le tampon d'entrée devient vide ou que le tampon de sortie devient plein. Il peut introduire une certaine latence de sortie (lecture d'entrée sans produire de sortie) sauf en cas de vidage forcé.
La sémantique détaillée est la suivante. inflate effectue une ou les deux actions suivantes :
- Décompressez davantage d'entrées à partir de next_in et mettez à jour next_in et avail_in en conséquence. Si toutes les entrées ne peuvent pas être traitées (parce qu'il n'y a pas assez de place dans le tampon de sortie), alors next_in et avail_in sont mis à jour en conséquence et le traitement reprendra à ce stade pour le prochain appel de inflate().
- Générez davantage de sortie à partir de next_out et mettez à jour next_out et avail_out en conséquence. inflate() fournit autant de sortie que possible, jusqu'à ce qu'il n'y ait plus de données d'entrée ou plus d'espace dans le tampon de sortie (voir ci-dessous à propos du paramètre flush).
Avant l'appel de inflate(), l'application doit s'assurer qu'au moins une des actions est possible, en fournissant plus d'entrées et/ou en consommant plus de sorties, et en mettant à jour les valeurs next_* et avail_* en conséquence. Si l'appelant de inflate() ne fournit pas à la fois l'espace d'entrée et l'espace de sortie disponibles, il est possible qu'aucune progression ne soit réalisée. L'application peut consommer la sortie non compressée quand elle le souhaite, par exemple lorsque le tampon de sortie est plein (avail_out == 0), ou après chaque appel de inflate(). Si inflate renvoie Z_OK et avec avail_out zéro, il doit être appelé à nouveau après avoir fait de la place dans le tampon de sortie car il peut y avoir plus de sorties en attente.
Le paramètre flush de inflate() peut être Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK ou Z_TREES. Z_SYNC_FLUSH demande à inflate() de vider autant de sorties que possible dans le tampon de sortie. Z_BLOCK demande à inflate() de s'arrêter si et quand il atteint la limite du bloc deflate suivant. Lors du décodage du format zlib ou gzip, cela entraînera le retour de inflate() immédiatement après l'entête et avant le premier bloc. Lors d'un inflate brut, inflate() continuera et traitera le premier bloc, et reviendra lorsqu'il arrivera à la fin de ce bloc, ou lorsqu'il n'aura plus de données.
L'option Z_BLOCK permet d'ajouter ou de combiner des flux deflate. Pour faciliter cela, au retour, inflate() définit toujours strm->data_type sur le nombre de bits inutilisés dans le dernier octet extrait de strm->next_in, plus 64 si inflate() est en train de décoder le dernier bloc du flux deflate, plus 128 si inflate() est retourné immédiatement après le décodage d'un code de fin de bloc ou le décodage de l'entête complet jusqu'à juste avant le premier octet du flux deflate. La fin du bloc ne sera pas indiquée tant que toutes les données non compressées de ce bloc n'auront pas été écrites dans strm->next_out. Le nombre de bits inutilisés peut en général être supérieur à sept, sauf lorsque le bit 7 de data_type est défini, auquel cas le nombre de bits inutilisés sera inférieur à huit. data_type est défini comme indiqué ici à chaque fois que inflate() renvoie pour toutes les options de vidage, et peut donc être utilisé pour déterminer la quantité d'entrée actuellement consommée en bits.
L'option Z_TREES se comporte comme le fait Z_BLOCK, mais elle renvoie également lorsque la fin de chaque entête de bloc deflate est atteinte, avant que les données réelles de ce bloc ne soient décodées. Cela permet à l'appelant de déterminer la longueur de l'en-tête de bloc deflate pour une utilisation ultérieure dans un accès aléatoire dans un bloc deflate. 256 est ajouté à la valeur de strm->data_type lorsque inflate() renvoie immédiatement après avoir atteint la fin de l'entête de bloc deflate.
inflate() doit normalement être appelé jusqu'à ce qu'il renvoie Z_STREAM_END ou une erreur. Cependant, si toute la décompression doit être effectuée en une seule étape (un seul appel à inflate), le paramètre flush doit être défini sur Z_FINISH. Dans ce cas, toutes les entrées en attente sont traitées et toutes les sorties en attente sont vidées; avail_out doit être suffisamment grand pour contenir toutes les données non compressées pour que l'opération soit terminée. (La taille des données non compressées peut avoir été enregistrée par le compresseur à cette fin.) L'utilisation de Z_FINISH n'est pas nécessaire pour effectuer un gonflage en une seule étape. Cependant, il peut être utilisé pour informer inflate qu'une approche plus rapide peut être utilisée pour l'appel unique à inflate(). Z_FINISH informe également inflate de ne pas maintenir une fenêtre glissante si le flux se termine, ce qui réduit l'empreinte mémoire d'inflate. Si le flux ne se termine pas, soit parce que la totalité du flux n'est pas fournie, soit parce qu'il n'y a pas assez d'espace de sortie, une fenêtre glissante sera allouée et inflate() pourra être appelé à nouveau pour continuer l'opération comme si Z_NO_FLUSH avait été utilisé.
Dans cette implémentation, inflate() vide toujours autant de sortie que possible dans le tampon de sortie et utilise toujours l'approche la plus rapide lors du premier appel. Ainsi, les effets du paramètre flush dans cette implémentation sont sur la valeur de retour de inflate() comme indiqué ci-dessous, lorsque inflate() retourne tôt lorsque Z_BLOCK ou Z_TREES est utilisé, et lorsque inflate() évite l'allocation de mémoire pour une fenêtre glissante lorsque Z_FINISH est utilisé.
Si un dictionnaire prédéfini est nécessaire après cet appel (voir inflateSetDictionary ci-dessous), inflate définit strm->adler sur la somme de contrôle Adler-32 du dictionnaire choisi par le compresseur et renvoie Z_NEED_DICT; sinon, il définit strm-&ht;adler sur la somme de contrôle Adler-32 de toutes les sorties produites jusqu'à présent (c'est-à-dire total_out octets) et renvoie Z_OK, Z_STREAM_END ou un code d'erreur comme décrit ci-dessous. À la fin du flux, inflate() vérifie que sa somme de contrôle Adler-32 calculée est égale à celle enregistrée par le compresseur et renvoie Z_STREAM_END uniquement si la somme de contrôle est correcte.
inflate() décompresse et vérifie les données deflate encapsulées dans zlib ou dans gzip. Le type d'entête est détecté automatiquement, s'il est demandé lors de l'initialisation avec inflateInit2(). Les informations contenues dans l'entête gzip ne sont pas conservées à moins que inflateGetHeader() ne soit utilisé. Lors du traitement des données deflate encapsulées dans gzip, strm->adler32 est défini sur le CRC-32 de la sortie produite jusqu'à présent. Le CRC-32 est vérifié par rapport à la fin gzip, tout comme la longueur non compressée, modulo 2^32.
inflate() renvoie Z_OK si des progrès ont été réalisés (plus d'entrées traitées ou plus de sorties produites), Z_STREAM_END si la fin des données compressées a été atteinte et que toutes les sorties non compressées ont été produites, Z_NEED_DICT si un dictionnaire prédéfini est nécessaire à ce stade, Z_DATA_ERROR si les données d'entrée ont été corrompues (flux d'entrée non conforme au format zlib ou valeur de contrôle incorrecte, auquel cas strm->msg pointe vers une chaîne de caractères avec une erreur plus spécifique), Z_STREAM_ERROR si la structure du flux était incohérente (par exemple next_in ou next_out était Z_NULL, ou l'état a été écrasé par inadvertance par l'application), Z_MEM_ERROR s'il n'y avait pas assez de mémoire, Z_BUF_ERROR si aucune progression n'était possible ou s'il n'y avait pas assez de place dans le tampon de sortie lorsque Z_FINISH est utilisé. Notez que Z_BUF_ERROR n'est pas fatal et que inflate() peut être appelé à nouveau avec plus d'espace d'entrée et de sortie pour continuer la décompression. Si Z_DATA_ERROR est renvoyé, l'application peut alors appeler inflateSync() pour rechercher un bon bloc de compression si une récupération partielle des données doit être tentée.
ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); |
Toutes les structures de données allouées dynamiquement pour ce flux sont libérées. Cette fonction supprime toute entrée non traitée et ne vide aucune sortie en attente.
inflateEnd renvoie Z_OK en cas de succès, ou Z_STREAM_ERROR si l'état du flux était incohérent.