bugfixes
This commit is contained in:
parent
94435ef305
commit
4c212907c2
@ -32,7 +32,8 @@ constexpr uint16_t masks[17] = {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
vuchar pack(const vuint16 &t_input) {
|
vuchar pack(const vuint16 &t_input) {
|
||||||
return pack_n(t_input.begin(), t_input.end(), vuchar{}, 9);
|
vuchar vec{};
|
||||||
|
return pack_n(t_input.begin(), t_input.end(), vec, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,10 +46,13 @@ vuchar pack(const vuint16 &t_input) {
|
|||||||
* char containing the packed values from t_input
|
* char containing the packed values from t_input
|
||||||
*/
|
*/
|
||||||
vuchar pack_n(const vuint16::const_iterator t_input_begin,
|
vuchar pack_n(const vuint16::const_iterator t_input_begin,
|
||||||
const vuint16::const_iterator t_input_end, vuchar t_res,
|
const vuint16::const_iterator t_input_end, vuchar &t_res,
|
||||||
int t_n) {
|
int t_n) {
|
||||||
|
#ifdef Debug
|
||||||
|
std::printf("%d bits!\n", t_n);
|
||||||
|
#endif // Debug
|
||||||
if (t_n == 16) {
|
if (t_n == 16) {
|
||||||
return pack_16(t_input_begin, t_input_end, vector<unsigned char>());
|
return pack_16(t_input_begin, t_input_end, t_res);
|
||||||
}
|
}
|
||||||
const int max_value = max(t_n); // max value held within t_n bits
|
const int max_value = max(t_n); // max value held within t_n bits
|
||||||
|
|
||||||
@ -60,22 +64,24 @@ vuchar pack_n(const vuint16::const_iterator t_input_begin,
|
|||||||
|
|
||||||
// pour chaque élément
|
// pour chaque élément
|
||||||
for (auto it = t_input_begin; it != t_input_end; ++it) {
|
for (auto it = t_input_begin; it != t_input_end; ++it) {
|
||||||
// si on a atteint ou dépassé la valeur maximale, on change de nombre de bits
|
// si on a atteint ou dépassé la valeur maximale, on change de nombre de
|
||||||
|
// bits
|
||||||
if (*it >= max_value) {
|
if (*it >= max_value) {
|
||||||
// écriture du masque pour notifier à la décompression du changement de bits
|
// écriture du masque pour notifier à la décompression du changement de
|
||||||
|
// bits
|
||||||
if ((left_shift += step) >= t_n) {
|
if ((left_shift += step) >= t_n) {
|
||||||
left_shift = (left_shift - t_n) + step;
|
left_shift = (left_shift - t_n) + step;
|
||||||
}
|
}
|
||||||
const auto mask = masks[t_n] >> left_shift;
|
const auto mask = masks[t_n] >> left_shift;
|
||||||
t_res.push_back(
|
t_res.push_back(static_cast<uchar>(current_char | mask));
|
||||||
static_cast<uchar>(current_char | mask));
|
|
||||||
bool zero_rs = (right_shift == 0);
|
bool zero_rs = (right_shift == 0);
|
||||||
|
|
||||||
right_shift -= step;
|
right_shift -= step;
|
||||||
if(right_shift < 0) { // si right_shift est inférieur à zéro
|
if (right_shift < 0) { // si right_shift est inférieur à zéro
|
||||||
// si right_shift était différent de zéro, alors extra octet
|
// si right_shift était différent de zéro, alors extra octet
|
||||||
if (!zero_rs) {
|
if (!zero_rs) {
|
||||||
current_char = static_cast<uchar>(masks[t_n] >> (-right_shift) & 0xffu);
|
current_char =
|
||||||
|
static_cast<uchar>(masks[t_n] >> (-right_shift) & 0xffu);
|
||||||
t_res.push_back(current_char);
|
t_res.push_back(current_char);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +123,7 @@ vuchar pack_n(const vuint16::const_iterator t_input_begin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vuchar pack_16(const vuint16::const_iterator t_input_begin,
|
vuchar pack_16(const vuint16::const_iterator t_input_begin,
|
||||||
const vuint16::const_iterator t_input_end, vuchar t_res) {
|
const vuint16::const_iterator t_input_end, vuchar &t_res) {
|
||||||
std::for_each(t_input_begin, t_input_end, [&](const auto value) {
|
std::for_each(t_input_begin, t_input_end, [&](const auto value) {
|
||||||
t_res.push_back(static_cast<uchar>(value >> 8 & 0xFFu));
|
t_res.push_back(static_cast<uchar>(value >> 8 & 0xFFu));
|
||||||
t_res.push_back(static_cast<uchar>(value & 0xFFu));
|
t_res.push_back(static_cast<uchar>(value & 0xFFu));
|
||||||
@ -130,13 +136,14 @@ vuchar pack_16(const vuint16::const_iterator t_input_begin,
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
vuint16 unpack(ustring &&t_input) {
|
vuint16 unpack(ustring &&t_input) {
|
||||||
return unpack_n(t_input.begin(), t_input.end(), vuint16{}, 9);
|
vuint16 vec{};
|
||||||
|
return unpack_n(t_input.begin(), t_input.end(), vec, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
vuint16 unpack_n(const ustring::const_iterator t_begin,
|
vuint16 unpack_n(const ustring::const_iterator t_begin,
|
||||||
const ustring::const_iterator t_end, vuint16 t_res, int t_n) {
|
const ustring::const_iterator t_end, vuint16 &t_res, int t_n) {
|
||||||
if (t_n == 16) {
|
if (t_n == 16) {
|
||||||
return unpack_16(t_begin, t_end, vector<uint16_t>());
|
return unpack_16(t_begin, t_end, t_res);
|
||||||
}
|
}
|
||||||
int step = t_n % 8;
|
int step = t_n % 8;
|
||||||
int left_shift = 0;
|
int left_shift = 0;
|
||||||
@ -173,7 +180,7 @@ vuint16 unpack_n(const ustring::const_iterator t_begin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vuint16 unpack_16(const ustring::const_iterator t_begin,
|
vuint16 unpack_16(const ustring::const_iterator t_begin,
|
||||||
const ustring::const_iterator t_end, vuint16 t_res) {
|
const ustring::const_iterator t_end, vuint16 &t_res) {
|
||||||
for (auto it = t_begin; it < t_end; ++it) {
|
for (auto it = t_begin; it < t_end; ++it) {
|
||||||
t_res.push_back(static_cast<uint16_t>(*it << 8 | *++it));
|
t_res.push_back(static_cast<uint16_t>(*it << 8 | *++it));
|
||||||
}
|
}
|
||||||
|
@ -14,25 +14,25 @@
|
|||||||
std::vector<unsigned char> pack(const std::vector<std::uint16_t> &);
|
std::vector<unsigned char> pack(const std::vector<std::uint16_t> &);
|
||||||
|
|
||||||
/// \brief Packs std::uint16_t of n bits into unsigned char
|
/// \brief Packs std::uint16_t of n bits into unsigned char
|
||||||
std::vector<unsigned char>
|
std::vector<unsigned char> pack_n(std::vector<std::uint16_t>::const_iterator,
|
||||||
pack_n(std::vector<std::uint16_t>::const_iterator , std::vector<std::uint16_t>::const_iterator ,
|
std::vector<std::uint16_t>::const_iterator,
|
||||||
std::vector<unsigned char> , int );
|
std::vector<unsigned char> &, int);
|
||||||
|
|
||||||
/// \brief Specialization of \ref pack_n for 16bits
|
/// \brief Specialization of \ref pack_n for 16bits
|
||||||
std::vector<unsigned char>
|
std::vector<unsigned char> pack_16(std::vector<std::uint16_t>::const_iterator,
|
||||||
pack_16(std::vector<std::uint16_t>::const_iterator , std::vector<std::uint16_t>::const_iterator ,
|
std::vector<std::uint16_t>::const_iterator,
|
||||||
std::vector<unsigned char> );
|
std::vector<unsigned char> &);
|
||||||
|
|
||||||
std::vector<std::uint16_t> unpack(std::basic_string<unsigned char> &&);
|
std::vector<std::uint16_t> unpack(std::basic_string<unsigned char> &&);
|
||||||
|
|
||||||
std::vector<std::uint16_t>
|
std::vector<std::uint16_t>
|
||||||
unpack_n(std::basic_string<unsigned char>::const_iterator t_begin,
|
unpack_n(std::basic_string<unsigned char>::const_iterator t_begin,
|
||||||
std::basic_string<unsigned char>::const_iterator t_end,
|
std::basic_string<unsigned char>::const_iterator t_end,
|
||||||
std::vector<std::uint16_t> t_res, int t_n);
|
std::vector<std::uint16_t> &, int t_n);
|
||||||
|
|
||||||
std::vector<std::uint16_t>
|
std::vector<std::uint16_t>
|
||||||
unpack_16(std::basic_string<unsigned char>::const_iterator,
|
unpack_16(std::basic_string<unsigned char>::const_iterator,
|
||||||
std::basic_string<unsigned char>::const_iterator,
|
std::basic_string<unsigned char>::const_iterator,
|
||||||
std::vector<std::uint16_t>);
|
std::vector<std::uint16_t> &);
|
||||||
|
|
||||||
#endif /* LZW_SRC_BITPACK_H_ */
|
#endif /* LZW_SRC_BITPACK_H_ */
|
||||||
|
@ -40,9 +40,9 @@ int ipow(int base, int exp) {
|
|||||||
* valeur numérique de la chaîne dans le dictionnaire.
|
* valeur numérique de la chaîne dans le dictionnaire.
|
||||||
*
|
*
|
||||||
* \param t_dictionary Dictionnaire
|
* \param t_dictionary Dictionnaire
|
||||||
* \param t_nr_chaine Numéro de la chaine précédant le caractères \p t_c dans \p t_dictionary
|
* \param t_nr_chaine Numéro de la chaine précédant le caractères \p t_c dans
|
||||||
* \param t_c Caractère suivant la chaine de caractères \p t_nr_chaine
|
* \p t_dictionary \param t_c Caractère suivant la chaine de caractères \p
|
||||||
* \return const std::pair<bool, uint16_t>
|
* t_nr_chaine \return const std::pair<bool, uint16_t>
|
||||||
*/
|
*/
|
||||||
std::pair<bool, uint16_t> dico(dic_comp_t &t_dictionary,
|
std::pair<bool, uint16_t> dico(dic_comp_t &t_dictionary,
|
||||||
const uint16_t t_nr_chaine, const uint8_t t_c) {
|
const uint16_t t_nr_chaine, const uint8_t t_c) {
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "compress.hh"
|
#include "compress.hh"
|
||||||
#include "io.hh"
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
|
#include "io.hh"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
using std::ios;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::uint16_t;
|
using std::uint16_t;
|
||||||
using std::uint8_t;
|
using std::uint8_t;
|
||||||
@ -20,7 +22,20 @@ using ustring = std::basic_string<unsigned char>;
|
|||||||
using dict_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
|
using dict_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
|
||||||
using std::printf;
|
using std::printf;
|
||||||
|
|
||||||
const size_t DICT_MAX = static_cast<size_t>(ipow(2, 17) - 256); /* 16 bits */
|
ustring read_file(const string &filename) {
|
||||||
|
std::ifstream file{filename, ios::binary};
|
||||||
|
assert(file);
|
||||||
|
file.unsetf(ios::skipws);
|
||||||
|
file.seekg(0, ios::end);
|
||||||
|
const auto file_size = file.tellg();
|
||||||
|
file.seekg(0, ios::beg);
|
||||||
|
ustring res{};
|
||||||
|
res.reserve(file_size);
|
||||||
|
res.insert(res.begin(), std::istream_iterator<unsigned char>(file),
|
||||||
|
std::istream_iterator<unsigned char>());
|
||||||
|
file.close();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* La chaîne de caractères \p t_text est lue caractère par caractère, et est
|
* La chaîne de caractères \p t_text est lue caractère par caractère, et est
|
||||||
@ -35,6 +50,7 @@ const size_t DICT_MAX = static_cast<size_t>(ipow(2, 17) - 256); /* 16 bits */
|
|||||||
*/
|
*/
|
||||||
vvuint16 lzw_compress(ustring &&t_text) {
|
vvuint16 lzw_compress(ustring &&t_text) {
|
||||||
std::puts("Compressing...");
|
std::puts("Compressing...");
|
||||||
|
const auto DICT_MAX = static_cast<size_t>(ipow(2, 17) - 256); /* 16 bits */
|
||||||
uint16_t w = 0xFFFF;
|
uint16_t w = 0xFFFF;
|
||||||
vuint16 chunk{};
|
vuint16 chunk{};
|
||||||
vvuint16 res{};
|
vvuint16 res{};
|
||||||
@ -46,7 +62,8 @@ vvuint16 lzw_compress(ustring &&t_text) {
|
|||||||
dict = dict_t{};
|
dict = dict_t{};
|
||||||
w = 0xFFFF;
|
w = 0xFFFF;
|
||||||
}
|
}
|
||||||
if (const auto &[yes, pos] = dico(dict, w, static_cast<uint8_t>(c)); yes) {
|
if (const auto &[exists, pos] = dico(dict, w, static_cast<uint8_t>(c));
|
||||||
|
exists) {
|
||||||
w = pos;
|
w = pos;
|
||||||
} else {
|
} else {
|
||||||
chunk.push_back(w);
|
chunk.push_back(w);
|
||||||
@ -70,25 +87,14 @@ vvuint16 lzw_compress(ustring &&t_text) {
|
|||||||
* \param[in] t_out_file Chemin vers le fichier de sortie
|
* \param[in] t_out_file Chemin vers le fichier de sortie
|
||||||
*/
|
*/
|
||||||
void compress(const std::string &t_in_file, const char *t_out_file) {
|
void compress(const std::string &t_in_file, const char *t_out_file) {
|
||||||
FILE *const input_file = fopen(t_in_file.c_str(), "rb");
|
std::ofstream out{(t_out_file != nullptr) ? t_out_file : "output.lzw",
|
||||||
assert(input_file);
|
std::ios::out | std::ios::binary};
|
||||||
FILE *const out = (t_out_file != nullptr) ? fopen(t_out_file, "wb")
|
if (!out.is_open()) {
|
||||||
: fopen("output.lzw", "wb");
|
|
||||||
if (out == nullptr) {
|
|
||||||
std::cerr << "Error at " << __FILE__ << ":" << __LINE__ - 4
|
std::cerr << "Error at " << __FILE__ << ":" << __LINE__ - 4
|
||||||
<< ": could not open output file. Aborting...\n";
|
<< ": could not open output file. Aborting...\n";
|
||||||
std::fclose(input_file);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
const auto compressed_text(lzw_compress(read_file(t_in_file)));
|
||||||
std::fseek(input_file, 0L, SEEK_END);
|
|
||||||
const auto file_size = static_cast<size_t>(ftell(input_file));
|
|
||||||
std::rewind(input_file);
|
|
||||||
|
|
||||||
auto raw_text = std::make_unique<unsigned char[]>(file_size);
|
|
||||||
std::fread(raw_text.get(), sizeof(unsigned char), file_size, input_file);
|
|
||||||
const auto compressed_text(lzw_compress(ustring{raw_text.get(), &raw_text[file_size]}));
|
|
||||||
write_file(out, compressed_text);
|
write_file(out, compressed_text);
|
||||||
fclose(out);
|
out.close();
|
||||||
fclose(input_file);
|
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
#define LZW_SRC_COMPRESS_H_
|
#define LZW_SRC_COMPRESS_H_
|
||||||
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/// \brief Compression d'une chaine de caractères
|
/// \brief Compression d'une chaine de caractères
|
||||||
std::vector<std::vector<std::uint16_t>>
|
std::vector<std::vector<std::uint16_t>>
|
||||||
|
46
src/io.cc
46
src/io.cc
@ -6,46 +6,36 @@
|
|||||||
#include "io.hh"
|
#include "io.hh"
|
||||||
#include "bitpack.hh"
|
#include "bitpack.hh"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#ifdef Debug
|
|
||||||
constexpr bool debug_mode = true;
|
|
||||||
#include <algorithm>
|
|
||||||
#else
|
|
||||||
constexpr bool debug_mode = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::uint16_t;
|
using std::uint16_t;
|
||||||
|
using std::vector;
|
||||||
using vuint16 = vector<uint16_t>;
|
using vuint16 = vector<uint16_t>;
|
||||||
using vvuint16 = vector<vuint16>;
|
using vvuint16 = vector<vuint16>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Écrit dans le fichier \p t_out les chunks passés en paramètre. Le fichier de
|
* Écrit dans le fichier \p t_out les chunks passés en paramètre. Le fichier de
|
||||||
* sortie est composé des éléments suivants :\n
|
* sortie est composé des éléments suivants :\n
|
||||||
* - Sur deux octets sont écrit un `uint16_t` déterminant le nombre de chunk
|
* - Sur deux octets sont écrit un `uint16_t` (deux octets) déterminant le
|
||||||
* composant le fichier\n
|
* nombre de chunk composant le fichier\n
|
||||||
* - Sont ensuite écrits les chunks sur un nombre variable d’octets suivant la
|
* - Sont ensuite écrits les chunks sur un nombre variable d’octets suivant la
|
||||||
* taille des chunks\n
|
* taille des chunks\n
|
||||||
* \n
|
* \n
|
||||||
* Un chunk est composé de la manière qui suit :\n
|
* Un chunk est composé de la manière qui suit :\n
|
||||||
* - Sur deux octets sont écrit un `uint32_t` déterminant le nombre d’octets
|
* - Sur deux octets sont écrit un `uint32_t` (quatre octets) déterminant le
|
||||||
* composant le chunk\n
|
* nombre d’octets composant le chunk\n
|
||||||
* - Sur le nombre d’octets précisés par le header du chunk se trouvent les
|
* - Sur le nombre d’octets précisés par le header du chunk se trouvent les
|
||||||
* données compressées par l’algorithme lzw puis via bit-packing.\n
|
* données compressées par l’algorithme lzw puis via bit-packing.\n
|
||||||
*
|
*
|
||||||
* \param[out] t_out Fichier de sortie
|
* \param[out] t_out Fichier de sortie
|
||||||
* \param[in] t_text Collection ordonnée des chunks à écrire dans \p t_out
|
* \param[in] t_chunks Collection ordonnée des chunks à écrire dans \p t_out
|
||||||
*/
|
*/
|
||||||
void write_file(FILE *const t_out, const vvuint16 &t_text) {
|
void write_file(std::ofstream &t_out, const vvuint16 &t_chunks) {
|
||||||
const auto size = static_cast<uint16_t>(t_text.size());
|
const auto nr_chunks = static_cast<uint16_t>(t_chunks.size());
|
||||||
if constexpr (debug_mode) {
|
#ifdef Debug
|
||||||
std::printf("Number of chunks: %u\n", size);
|
std::printf("Number of chunks: %u\n", nr_chunks);
|
||||||
}
|
#endif
|
||||||
fwrite(&size, sizeof(size), 1, t_out);
|
t_out.write(reinterpret_cast<const char *>(&nr_chunks), sizeof(nr_chunks));
|
||||||
for (const auto &chunk : t_text) {
|
for (const auto &chunk : t_chunks) {
|
||||||
if constexpr (debug_mode)
|
|
||||||
std::printf("Chunk!\n");
|
|
||||||
write_chunk(t_out, chunk);
|
write_chunk(t_out, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,9 +47,13 @@ void write_file(FILE *const t_out, const vvuint16 &t_text) {
|
|||||||
* \param t_out Output file
|
* \param t_out Output file
|
||||||
* \param t_chunk Chunk to be written to \p t_out
|
* \param t_chunk Chunk to be written to \p t_out
|
||||||
*/
|
*/
|
||||||
void write_chunk(FILE *const t_out, const vuint16 &t_chunk) {
|
void write_chunk(std::ofstream &t_out, const vuint16 &t_chunk) {
|
||||||
|
#ifdef Debug
|
||||||
|
std::printf("Chunk!\n");
|
||||||
|
#endif
|
||||||
const auto output = pack(t_chunk);
|
const auto output = pack(t_chunk);
|
||||||
const auto chunk_size = static_cast<uint32_t>(output.size());
|
const auto chunk_size = static_cast<uint32_t>(output.size());
|
||||||
fwrite(&chunk_size, sizeof(chunk_size), 1, t_out);
|
t_out.write(reinterpret_cast<const char *>(&chunk_size), sizeof(chunk_size));
|
||||||
fwrite(output.data(), sizeof(output[0]), output.size(), t_out);
|
t_out.write(reinterpret_cast<const char *>(output.data()),
|
||||||
|
sizeof(output[0]) * output.size());
|
||||||
}
|
}
|
||||||
|
12
src/io.hh
12
src/io.hh
@ -6,8 +6,9 @@
|
|||||||
#ifndef LZW_SRC_IO_H_
|
#ifndef LZW_SRC_IO_H_
|
||||||
#define LZW_SRC_IO_H_
|
#define LZW_SRC_IO_H_
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -19,17 +20,18 @@
|
|||||||
*
|
*
|
||||||
* Un chunk se compose ainsi :
|
* Un chunk se compose ainsi :
|
||||||
* nb_char_chunk : nombre de caractères du chunk (2B)
|
* nb_char_chunk : nombre de caractères du chunk (2B)
|
||||||
* text* : caractères de taille char_size (ceil((char_size * nb_char_chunk) / 8))
|
* text* : caractères de taille char_size (ceil((char_size * nb_char_chunk) /
|
||||||
|
* 8))
|
||||||
*
|
*
|
||||||
* Si le dernier caractère ne termine pas le dernier octet du chunk, les
|
* Si le dernier caractère ne termine pas le dernier octet du chunk, les
|
||||||
* derniers bits sont mit à zéro
|
* derniers bits sont mit à zéro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/// \brief Écrit dans le fichier le texte compressé
|
/// \brief Écrit dans le fichier le texte compressé
|
||||||
void write_file(FILE *const, const std::vector<std::vector<std::uint16_t>> &);
|
void write_file(std::ofstream &,
|
||||||
|
const std::vector<std::vector<std::uint16_t>> &);
|
||||||
|
|
||||||
/// \brief Écrit un chunk dans le fichier de sortie
|
/// \brief Écrit un chunk dans le fichier de sortie
|
||||||
void write_chunk(FILE *const, const std::vector<std::uint16_t> &);
|
void write_chunk(std::ofstream &, const std::vector<std::uint16_t> &);
|
||||||
|
|
||||||
#endif /* LZW_SRC_IO_H_ */
|
#endif /* LZW_SRC_IO_H_ */
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <cassert>
|
|
||||||
#include <tuple>
|
|
||||||
#include "compress.hh"
|
#include "compress.hh"
|
||||||
#include "uncompress.hh"
|
#include "uncompress.hh"
|
||||||
|
#include <cassert>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
using std::printf;
|
using std::printf;
|
||||||
using std::puts;
|
using std::puts;
|
||||||
@ -70,7 +70,8 @@ std::tuple<string, string, bool> process_args(int t_argc, char *t_argv[]) {
|
|||||||
{"uncompress", no_argument, nullptr, 'u'},
|
{"uncompress", no_argument, nullptr, 'u'},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
int c = getopt_long(t_argc, t_argv, "hi:o:cu", long_options, &option_index);
|
int c = getopt_long(t_argc, t_argv, "hi:o:cu", long_options, &option_index);
|
||||||
if (c == -1) break;
|
if (c == -1)
|
||||||
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
using std::fclose;
|
using std::fclose;
|
||||||
using std::fopen;
|
using std::fopen;
|
||||||
@ -18,14 +20,17 @@ ustring lzw_uncompress(vuint16 &&t_compressed) {
|
|||||||
ustring ret{};
|
ustring ret{};
|
||||||
uint16_t old = 0;
|
uint16_t old = 0;
|
||||||
std::map<uint16_t, ustring> dict{};
|
std::map<uint16_t, ustring> dict{};
|
||||||
uint16_t v = t_compressed[0];
|
// uint16_t v = t_compressed[0];
|
||||||
ret.append({static_cast<unsigned char>(v)});
|
// ret.append({static_cast<unsigned char>(v)});
|
||||||
old = v;
|
// old = v;
|
||||||
|
ret.append({static_cast<unsigned char>(t_compressed[0])});
|
||||||
|
old = t_compressed[0];
|
||||||
for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) {
|
for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) {
|
||||||
v = *it;
|
// v = *it;
|
||||||
const auto uncompressed{dico_uncompress(dict, v, old)};
|
const auto uncompressed{dico_uncompress(dict, *it, old)};
|
||||||
ret.insert(ret.end(), uncompressed.begin(), uncompressed.end());
|
ret.insert(ret.end(), uncompressed.begin(), uncompressed.end());
|
||||||
old = v;
|
// old = v;
|
||||||
|
old = *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -34,31 +39,28 @@ ustring lzw_uncompress(vuint16 &&t_compressed) {
|
|||||||
void uncompress(const string &t_input_name, const char *t_output_name) {
|
void uncompress(const string &t_input_name, const char *t_output_name) {
|
||||||
FILE *const input = std::fopen(t_input_name.c_str(), "rb");
|
FILE *const input = std::fopen(t_input_name.c_str(), "rb");
|
||||||
assert(input);
|
assert(input);
|
||||||
|
|
||||||
FILE *const output =
|
FILE *const output =
|
||||||
(t_output_name != nullptr)
|
(t_output_name != nullptr)
|
||||||
? std::fopen(t_output_name, "wb")
|
? std::fopen(t_output_name, "wb")
|
||||||
: std::fopen((t_input_name + "_uncompressed").c_str(), "wb");
|
: std::fopen((t_input_name + "_uncompressed").c_str(), "wb");
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
uint16_t nb_chunks = 0;
|
uint16_t nb_chunks = 0;
|
||||||
std::fseek(input, 0, SEEK_SET);
|
|
||||||
std::fread(&nb_chunks, sizeof(nb_chunks), 1, input);
|
std::fread(&nb_chunks, sizeof(nb_chunks), 1, input);
|
||||||
|
|
||||||
for (uint16_t i = 0; i < nb_chunks; ++i) {
|
for (uint16_t i = 0; i < nb_chunks; ++i) {
|
||||||
uint32_t size_chunk = 0;
|
uncompress_chunk(input, output);
|
||||||
fread(&size_chunk, sizeof(size_chunk), 1, input);
|
|
||||||
auto *chunk = static_cast<unsigned char *>(
|
|
||||||
std::malloc(sizeof(unsigned char) * size_chunk));
|
|
||||||
fread(chunk, sizeof(unsigned char), size_chunk, input);
|
|
||||||
|
|
||||||
auto unpacked = unpack(ustring{chunk, chunk + size_chunk});
|
|
||||||
const auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
|
|
||||||
// sometimes will add null char
|
|
||||||
std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]),
|
|
||||||
uncompressed_chunk.size(), output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fclose(output);
|
std::fclose(output);
|
||||||
std::fclose(input);
|
std::fclose(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uncompress_chunk(FILE *const input, FILE *const output) {
|
||||||
|
uint32_t size_chunk = 0;
|
||||||
|
fread(&size_chunk, sizeof(size_chunk), 1, input);
|
||||||
|
auto chunk = new unsigned char[size_chunk];
|
||||||
|
fread(chunk, sizeof(unsigned char), size_chunk, input);
|
||||||
|
auto unpacked = unpack(ustring{chunk, chunk + size_chunk});
|
||||||
|
delete[] chunk;
|
||||||
|
const auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
|
||||||
|
std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]),
|
||||||
|
uncompressed_chunk.size(), output);
|
||||||
|
}
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
std::basic_string<unsigned char>
|
std::basic_string<unsigned char> lzw_uncompress(std::vector<std::uint16_t> &&);
|
||||||
lzw_uncompress(std::vector<std::uint16_t> &&);
|
|
||||||
|
|
||||||
void uncompress(const std::string &, const char*);
|
void uncompress(const std::string &, const char *);
|
||||||
|
|
||||||
|
void uncompress_chunk(FILE *, FILE *);
|
||||||
|
|
||||||
#endif /* LZW_SRC_UNCOMPRESS_H_ */
|
#endif /* LZW_SRC_UNCOMPRESS_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user