Some fixes, dictionary still broken
This commit is contained in:
parent
e54e5fa07d
commit
ec85a4b978
@ -3,13 +3,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef Debug
|
|
||||||
#include <cstdio>
|
|
||||||
constexpr bool debug = true;
|
|
||||||
#else
|
|
||||||
constexpr bool debug = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::uint16_t;
|
using std::uint16_t;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using uchar = unsigned char;
|
using uchar = unsigned char;
|
||||||
@ -128,37 +121,25 @@ uint16_t mask_n(int t_nb_bits) {
|
|||||||
vuint16 ret{};
|
vuint16 ret{};
|
||||||
const uint16_t mask = mask_n(t_n);
|
const uint16_t mask = mask_n(t_n);
|
||||||
const int max_value = ipow(2, t_n);
|
const int max_value = ipow(2, t_n);
|
||||||
for (auto it = t_begin; it < t_end;) {
|
for (auto it = t_begin; it < t_end - 1; /* nope */) {
|
||||||
uint16_t current_char = 0;
|
uint16_t current_char = 0;
|
||||||
// left bits
|
// left bits
|
||||||
left_shift =
|
left_shift =
|
||||||
((left_shift += step) >= t_n) ? (left_shift - t_n) + step : left_shift;
|
((left_shift += step) >= t_n) ? (left_shift - t_n) + step : left_shift;
|
||||||
current_char = static_cast<uint16_t>(*it << left_shift);
|
current_char = static_cast<uint16_t>(*it << left_shift);
|
||||||
if constexpr(debug) {
|
|
||||||
std::printf("left:\t%d\t", left_shift);
|
|
||||||
}
|
|
||||||
// right bits
|
// right bits
|
||||||
bool zero_rs = right_shift;
|
bool zero_rs = right_shift;
|
||||||
right_shift -= step;
|
right_shift -= step;
|
||||||
if (right_shift < 0) {
|
if (right_shift < 0) {
|
||||||
// optional middle bits before right bits
|
// optional middle bits before right bits
|
||||||
if (zero_rs) {
|
if (zero_rs) {
|
||||||
current_char |= *(++it) << std::abs(right_shift);
|
current_char |= *++it << std::abs(right_shift);
|
||||||
if constexpr(debug) {
|
|
||||||
std::printf("middle:\t%d\t", std::abs(right_shift));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
right_shift = 8 - std::abs(right_shift);
|
right_shift = 8 - std::abs(right_shift);
|
||||||
}
|
}
|
||||||
current_char |= *(++it) >> right_shift;
|
current_char |= *(++it) >> right_shift;
|
||||||
if constexpr(debug) {
|
|
||||||
std::printf("right\t%d\t", right_shift);
|
|
||||||
}
|
|
||||||
// char made!
|
// char made!
|
||||||
ret.push_back(current_char &= mask);
|
ret.push_back(current_char &= mask);
|
||||||
if constexpr(debug) {
|
|
||||||
std::printf("value:\t%d\n", current_char);
|
|
||||||
}
|
|
||||||
if(right_shift == 0) {
|
if(right_shift == 0) {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
|
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
|
|
||||||
using std::uint8_t;
|
|
||||||
using std::uint16_t;
|
using std::uint16_t;
|
||||||
|
using std::uint8_t;
|
||||||
using dic_comp_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
|
using dic_comp_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
|
||||||
using ustring = std::basic_string<unsigned char>;
|
using ustring = std::basic_string<unsigned char>;
|
||||||
|
using p_ustring = std::shared_ptr<ustring>;
|
||||||
|
|
||||||
int ipow(int base, int exp) {
|
int ipow(int base, int exp) {
|
||||||
int result = 1;
|
int result = 1;
|
||||||
@ -27,16 +28,16 @@ int ipow(int base, int exp) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Cette fonction a pour double usage la recherche d’une chaine de caractères
|
* Cette fonction a pour double usage la recherche d’une chaine de caractères
|
||||||
* dans le dictionnaire, ou bien l’ajout d’une nouvelle chaîne si celle-ci n’est
|
* dans le dictionnaire, ou bien l’ajout d’une nouvelle chaîne si celle-ci
|
||||||
* pas déjà présente. Une chaine de caractères est représentée par un couple
|
* n’est pas déjà présente. Une chaine de caractères est représentée par un
|
||||||
* numéro de chaine / caractère, le numéro de chaine renvoyant au caractère
|
* couple numéro de chaine / caractère, le numéro de chaine renvoyant au
|
||||||
* précédent (soit son code ASCII, soit son indice dans le dictionnaire) et le
|
* caractère précédent (soit son code ASCII, soit son indice dans le
|
||||||
* caractère se référant au dernier caractère de la chaine courante. Si le
|
* dictionnaire) et le caractère se référant au dernier caractère de la chaine
|
||||||
* numéro de chaine est -1, alors il s’agit du premier caractère de la chaine,
|
* courante. Si le numéro de chaine est -1, alors il s’agit du premier caractère
|
||||||
* et la valeur renvoyée sera la valeur ASCII du caractère. La fonction renvoie
|
* de la chaine, et la valeur renvoyée sera la valeur ASCII du caractère. La
|
||||||
* une paire bool/uint16_t, la valeur booléene indiquant si une nouvelle fut
|
* fonction renvoie une paire bool/uint16_t, la valeur booléene indiquant si une
|
||||||
* ajoutée dans le dictionnaire ou non, et le uint16_t indiquant la valeur
|
* nouvelle fut ajoutée dans le dictionnaire ou non, et le uint16_t indiquant la
|
||||||
* 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 \p t_dictionary
|
||||||
@ -50,33 +51,46 @@ std::pair<bool, uint16_t> dico(dic_comp_t &t_dictionary,
|
|||||||
}
|
}
|
||||||
auto &e = t_dictionary[std::make_pair(t_nr_chaine, t_c)];
|
auto &e = t_dictionary[std::make_pair(t_nr_chaine, t_c)];
|
||||||
return (e != 0) ? std::make_pair(true, e)
|
return (e != 0) ? std::make_pair(true, e)
|
||||||
: std::make_pair(
|
: std::make_pair(false, (e = static_cast<uint16_t>(
|
||||||
false,
|
t_dictionary.size() + 255)));
|
||||||
(e = static_cast<
|
|
||||||
typename std::remove_reference<decltype(e)>::type>(
|
|
||||||
t_dictionary.size()) +
|
|
||||||
255));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed description
|
||||||
|
*
|
||||||
|
* \param t_dict Dictionnaire
|
||||||
|
* \return Retourne une chaîne de caractères non signés
|
||||||
|
*/
|
||||||
ustring dico_uncompress(std::map<uint16_t, ustring> &t_dict,
|
ustring dico_uncompress(std::map<uint16_t, ustring> &t_dict,
|
||||||
const uint16_t t_code, const uint16_t t_old) {
|
const uint16_t t_code, const uint16_t t_old) {
|
||||||
auto e = (t_code < 256) ? ustring{static_cast<unsigned char>(t_code)}
|
// le code existe dans le dictionnaire s’il est < 256
|
||||||
: t_dict[t_code];
|
if (t_code < 256) {
|
||||||
if (!e.empty()) {
|
|
||||||
ustring str;
|
ustring e{static_cast<unsigned char>(t_code)};
|
||||||
if(t_old < 256) {
|
if (t_old < 256) {
|
||||||
str = ustring{static_cast<unsigned char>(t_old)};
|
t_dict[static_cast<uint16_t>(t_dict.size() + 256)] =
|
||||||
|
static_cast<unsigned char>(t_old) + e;
|
||||||
} else {
|
} else {
|
||||||
str = t_dict[t_old];
|
t_dict[static_cast<uint16_t>(t_dict.size() + 256)] = t_dict[t_old] + e;
|
||||||
str += str[0];
|
|
||||||
}
|
}
|
||||||
t_dict[static_cast<uint16_t>(t_dict.size() + 255)] = std::move(str);
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = (t_old < 256) ? ustring{static_cast<unsigned char>(t_old)}
|
auto &e = t_dict[t_code];
|
||||||
|
auto str = (t_old < 256) ? ustring{static_cast<unsigned char>(t_old)}
|
||||||
: t_dict[t_old];
|
: t_dict[t_old];
|
||||||
e += e[0];
|
|
||||||
|
// le code existe dans le dictionnaire
|
||||||
|
if (!e.empty()) {
|
||||||
|
str += e[0];
|
||||||
|
const uint16_t index = static_cast<uint16_t>(t_dict.size() + 256);
|
||||||
|
t_dict[index] = str;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// le code n'existe pas encore dans le dictionnaire
|
||||||
|
str += str[0];
|
||||||
|
e = str;
|
||||||
t_dict[t_code] = e;
|
t_dict[t_code] = e;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -99,11 +99,6 @@ int main(int argc, char *argv[]) {
|
|||||||
const auto [input_path, output_path, compressing] = process_args(argc, argv);
|
const auto [input_path, output_path, compressing] = process_args(argc, argv);
|
||||||
assert(!input_path.empty());
|
assert(!input_path.empty());
|
||||||
if (compressing) {
|
if (compressing) {
|
||||||
// if (output_path.empty()) {
|
|
||||||
// compress(input_path, nullptr);
|
|
||||||
// } else {
|
|
||||||
// compress(input_path, output_path.c_str());
|
|
||||||
// }
|
|
||||||
compress(input_path, (output_path.empty()) ? nullptr : output_path.c_str());
|
compress(input_path, (output_path.empty()) ? nullptr : output_path.c_str());
|
||||||
} else {
|
} else {
|
||||||
uncompress(input_path,
|
uncompress(input_path,
|
||||||
|
@ -5,12 +5,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#ifdef Debug
|
|
||||||
constexpr bool debug_mode = true;
|
|
||||||
#else
|
|
||||||
constexpr bool debug_mode = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using std::fclose;
|
using std::fclose;
|
||||||
using std::fopen;
|
using std::fopen;
|
||||||
using std::fseek;
|
using std::fseek;
|
||||||
@ -23,21 +17,27 @@ using vuint16 = vector<uint16_t>;
|
|||||||
[[nodiscard]] ustring lzw_uncompress(vuint16 &&t_compressed) {
|
[[nodiscard]] ustring lzw_uncompress(vuint16 &&t_compressed) {
|
||||||
ustring ret{};
|
ustring ret{};
|
||||||
uint16_t old = 0;
|
uint16_t old = 0;
|
||||||
uint16_t code = t_compressed[0];
|
|
||||||
|
// [1]
|
||||||
std::map<uint16_t, ustring> dict{};
|
std::map<uint16_t, ustring> dict{};
|
||||||
ret.push_back(static_cast<unsigned char>(code));
|
|
||||||
if constexpr(debug_mode) {
|
// [2]
|
||||||
std::printf("%d\n", code);
|
uint16_t v = t_compressed[0];
|
||||||
}
|
|
||||||
old = code;
|
// [3]
|
||||||
|
ret.append({static_cast<unsigned char>(v)});
|
||||||
|
|
||||||
|
// [4]
|
||||||
|
old = v;
|
||||||
|
|
||||||
for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) {
|
for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) {
|
||||||
if constexpr(debug_mode) {
|
// [5]
|
||||||
std::printf("%d\n", *it);
|
v = *it;
|
||||||
}
|
|
||||||
code = *it;
|
// [6]
|
||||||
const auto uncompressed{dico_uncompress(dict, code, old)};
|
const auto uncompressed{dico_uncompress(dict, v, old)};
|
||||||
ret.insert(ret.end(), uncompressed.begin(), uncompressed.end());
|
ret.insert(ret.end(), uncompressed.begin(), uncompressed.end());
|
||||||
old = code;
|
old = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -57,27 +57,16 @@ void uncompress(const string &t_input_name, const char *t_output_name) {
|
|||||||
std::fseek(input, 0, SEEK_SET);
|
std::fseek(input, 0, SEEK_SET);
|
||||||
std::fread(&nb_chunks, sizeof(nb_chunks), 1, input);
|
std::fread(&nb_chunks, sizeof(nb_chunks), 1, input);
|
||||||
|
|
||||||
if constexpr (debug_mode) {
|
|
||||||
std::printf("Number of chunks: %d\n", nb_chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < nb_chunks; ++i) {
|
for (uint16_t i = 0; i < nb_chunks; ++i) {
|
||||||
uint16_t size_chunk = 0;
|
uint16_t size_chunk = 0;
|
||||||
fread(&size_chunk, sizeof(size_chunk), 1, input);
|
fread(&size_chunk, sizeof(size_chunk), 1, input);
|
||||||
if constexpr (debug_mode) {
|
auto *chunk = static_cast<unsigned char *>(
|
||||||
printf("Chunk! Size of chunk:\t%d\n", size_chunk);
|
|
||||||
}
|
|
||||||
unsigned char *chunk = static_cast<unsigned char *>(
|
|
||||||
std::malloc(sizeof(unsigned char) * size_chunk));
|
std::malloc(sizeof(unsigned char) * size_chunk));
|
||||||
fread(chunk, sizeof(unsigned char), size_chunk, input);
|
fread(chunk, sizeof(unsigned char), size_chunk, input);
|
||||||
|
|
||||||
auto unpacked = unpack(ustring{chunk, chunk + size_chunk});
|
auto unpacked = unpack(ustring{chunk, chunk + size_chunk});
|
||||||
if constexpr(debug_mode) {
|
|
||||||
for(const auto c : unpacked) {
|
|
||||||
std::printf("%d\n", c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
|
const auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
|
||||||
|
// sometimes will add null char
|
||||||
std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]),
|
std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]),
|
||||||
uncompressed_chunk.size(), output);
|
uncompressed_chunk.size(), output);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef LZW_SRC_UNCOMPRESS_H_
|
#ifndef LZW_SRC_UNCOMPRESS_H_
|
||||||
#define LZW_SRC_UNCOMPRESS_H_
|
#define LZW_SRC_UNCOMPRESS_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user