diff --git a/src/bitpack.cc b/src/bitpack.cc index f548cfd..d9f4421 100644 --- a/src/bitpack.cc +++ b/src/bitpack.cc @@ -3,13 +3,6 @@ #include #include -#ifdef Debug -#include -constexpr bool debug = true; -#else -constexpr bool debug = false; -#endif - using std::uint16_t; using std::vector; using uchar = unsigned char; @@ -128,37 +121,25 @@ uint16_t mask_n(int t_nb_bits) { vuint16 ret{}; const uint16_t mask = mask_n(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; // left bits left_shift = ((left_shift += step) >= t_n) ? (left_shift - t_n) + step : left_shift; current_char = static_cast(*it << left_shift); - if constexpr(debug) { - std::printf("left:\t%d\t", left_shift); - } // right bits bool zero_rs = right_shift; right_shift -= step; if (right_shift < 0) { // optional middle bits before right bits if (zero_rs) { - current_char |= *(++it) << std::abs(right_shift); - if constexpr(debug) { - std::printf("middle:\t%d\t", std::abs(right_shift)); - } + current_char |= *++it << std::abs(right_shift); } right_shift = 8 - std::abs(right_shift); } current_char |= *(++it) >> right_shift; - if constexpr(debug) { - std::printf("right\t%d\t", right_shift); - } // char made! ret.push_back(current_char &= mask); - if constexpr(debug) { - std::printf("value:\t%d\n", current_char); - } if(right_shift == 0) { ++it; } diff --git a/src/common.cc b/src/common.cc index 092f394..056a01d 100644 --- a/src/common.cc +++ b/src/common.cc @@ -5,10 +5,11 @@ #include "common.hh" -using std::uint8_t; using std::uint16_t; +using std::uint8_t; using dic_comp_t = std::map, uint16_t>; using ustring = std::basic_string; +using p_ustring = std::shared_ptr; int ipow(int base, int exp) { 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 - * dans le dictionnaire, ou bien l’ajout d’une nouvelle chaîne si celle-ci n’est - * pas déjà présente. Une chaine de caractères est représentée par un couple - * numéro de chaine / caractère, le numéro de chaine renvoyant au caractère - * précédent (soit son code ASCII, soit son indice dans le dictionnaire) et le - * caractère se référant au dernier caractère de la chaine courante. Si le - * numéro de chaine est -1, alors il s’agit du premier caractère de la chaine, - * et la valeur renvoyée sera la valeur ASCII du caractère. La fonction renvoie - * une paire bool/uint16_t, la valeur booléene indiquant si une nouvelle fut - * ajoutée dans le dictionnaire ou non, et le uint16_t indiquant la valeur - * numérique de la chaîne dans le dictionnaire. + * dans le dictionnaire, ou bien l’ajout d’une nouvelle chaîne si celle-ci + * n’est pas déjà présente. Une chaine de caractères est représentée par un + * couple numéro de chaine / caractère, le numéro de chaine renvoyant au + * caractère précédent (soit son code ASCII, soit son indice dans le + * dictionnaire) et le caractère se référant au dernier caractère de la chaine + * courante. Si le numéro de chaine est -1, alors il s’agit du premier caractère + * de la chaine, et la valeur renvoyée sera la valeur ASCII du caractère. La + * fonction renvoie une paire bool/uint16_t, la valeur booléene indiquant si une + * nouvelle fut ajoutée dans le dictionnaire ou non, et le uint16_t indiquant la + * valeur numérique de la chaîne dans le 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 @@ -50,33 +51,46 @@ std::pair dico(dic_comp_t &t_dictionary, } auto &e = t_dictionary[std::make_pair(t_nr_chaine, t_c)]; return (e != 0) ? std::make_pair(true, e) - : std::make_pair( - false, - (e = static_cast< - typename std::remove_reference::type>( - t_dictionary.size()) + - 255)); + : std::make_pair(false, (e = static_cast( + 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 &t_dict, - const uint16_t t_code, const uint16_t t_old) { - auto e = (t_code < 256) ? ustring{static_cast(t_code)} - : t_dict[t_code]; - if (!e.empty()) { - ustring str; - if(t_old < 256) { - str = ustring{static_cast(t_old)}; + const uint16_t t_code, const uint16_t t_old) { + // le code existe dans le dictionnaire s’il est < 256 + if (t_code < 256) { + + ustring e{static_cast(t_code)}; + if (t_old < 256) { + t_dict[static_cast(t_dict.size() + 256)] = + static_cast(t_old) + e; } else { - str = t_dict[t_old]; - str += str[0]; + t_dict[static_cast(t_dict.size() + 256)] = t_dict[t_old] + e; } - t_dict[static_cast(t_dict.size() + 255)] = std::move(str); return e; } - e = (t_old < 256) ? ustring{static_cast(t_old)} - : t_dict[t_old]; - e += e[0]; + auto &e = t_dict[t_code]; + auto str = (t_old < 256) ? ustring{static_cast(t_old)} + : t_dict[t_old]; + + // le code existe dans le dictionnaire + if (!e.empty()) { + str += e[0]; + const uint16_t index = static_cast(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; return e; } diff --git a/src/common.hh b/src/common.hh index 28199d3..8087188 100644 --- a/src/common.hh +++ b/src/common.hh @@ -19,6 +19,6 @@ dico(std::map, std::uint16_t> &, std::basic_string dico_uncompress(std::map> &, - const std::uint16_t, const std::uint16_t); + const std::uint16_t, const std::uint16_t); #endif /* LZW_SRC_COMMON_H_ */ diff --git a/src/main.cc b/src/main.cc index 0cf5199..9c6d5db 100644 --- a/src/main.cc +++ b/src/main.cc @@ -99,11 +99,6 @@ int main(int argc, char *argv[]) { const auto [input_path, output_path, compressing] = process_args(argc, argv); assert(!input_path.empty()); 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()); } else { uncompress(input_path, diff --git a/src/uncompress.cc b/src/uncompress.cc index cb65d09..7bef079 100644 --- a/src/uncompress.cc +++ b/src/uncompress.cc @@ -5,12 +5,6 @@ #include #include -#ifdef Debug -constexpr bool debug_mode = true; -#else -constexpr bool debug_mode = false; -#endif - using std::fclose; using std::fopen; using std::fseek; @@ -23,21 +17,27 @@ using vuint16 = vector; [[nodiscard]] ustring lzw_uncompress(vuint16 &&t_compressed) { ustring ret{}; uint16_t old = 0; - uint16_t code = t_compressed[0]; + + // [1] std::map dict{}; - ret.push_back(static_cast(code)); - if constexpr(debug_mode) { - std::printf("%d\n", code); - } - old = code; + + // [2] + uint16_t v = t_compressed[0]; + + // [3] + ret.append({static_cast(v)}); + + // [4] + old = v; + for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) { - if constexpr(debug_mode) { - std::printf("%d\n", *it); - } - code = *it; - const auto uncompressed{dico_uncompress(dict, code, old)}; + // [5] + v = *it; + + // [6] + const auto uncompressed{dico_uncompress(dict, v, old)}; ret.insert(ret.end(), uncompressed.begin(), uncompressed.end()); - old = code; + old = v; } 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::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) { uint16_t size_chunk = 0; fread(&size_chunk, sizeof(size_chunk), 1, input); - if constexpr (debug_mode) { - printf("Chunk! Size of chunk:\t%d\n", size_chunk); - } - unsigned char *chunk = static_cast( + auto *chunk = static_cast( std::malloc(sizeof(unsigned char) * size_chunk)); fread(chunk, sizeof(unsigned char), size_chunk, input); 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)); + // sometimes will add null char std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]), uncompressed_chunk.size(), output); } diff --git a/src/uncompress.hh b/src/uncompress.hh index d12eadb..2519e6b 100644 --- a/src/uncompress.hh +++ b/src/uncompress.hh @@ -1,6 +1,7 @@ #ifndef LZW_SRC_UNCOMPRESS_H_ #define LZW_SRC_UNCOMPRESS_H_ +#include #include #include