2018-04-05 18:47:07 +02:00
|
|
|
|
/**
|
|
|
|
|
* \file common.cc
|
|
|
|
|
* \brief Implementation for functions in common
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "common.hh"
|
|
|
|
|
|
2018-06-10 23:44:10 +02:00
|
|
|
|
#ifdef Debug
|
|
|
|
|
constexpr bool debug_mode = true;
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#else
|
|
|
|
|
constexpr bool debug_mode = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-06-05 11:38:27 +02:00
|
|
|
|
using std::uint8_t;
|
|
|
|
|
using std::uint16_t;
|
|
|
|
|
using dic_comp_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
|
2018-06-10 21:21:06 +02:00
|
|
|
|
// using dic_un_t = std::map<std::uint16_t, std::unique_ptr<std::pair<uint16_t, uint8_t>>>;
|
2018-06-05 11:38:27 +02:00
|
|
|
|
using ustring = std::basic_string<unsigned char>;
|
2018-04-05 18:47:07 +02:00
|
|
|
|
|
2018-06-09 23:11:27 +02:00
|
|
|
|
int ipow(int base, int exp) {
|
|
|
|
|
int result = 1;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (exp & 1) {
|
|
|
|
|
result *= base;
|
|
|
|
|
}
|
|
|
|
|
exp >>= 1;
|
|
|
|
|
if (exp == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
base *= base;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-05 18:47:07 +02:00
|
|
|
|
/**
|
|
|
|
|
* 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
|
2018-06-05 11:38:27 +02:00
|
|
|
|
* 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
|
2018-04-05 18:47:07 +02:00
|
|
|
|
* numérique de la chaîne dans le dictionnaire.
|
|
|
|
|
*
|
2018-04-29 14:13:14 +02:00
|
|
|
|
* \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_c Caractère suivant la chaine de caractères \p t_nr_chaine
|
2018-06-05 11:38:27 +02:00
|
|
|
|
* \return const std::pair<bool, uint16_t>
|
2018-04-05 18:47:07 +02:00
|
|
|
|
*/
|
2018-06-10 21:21:06 +02:00
|
|
|
|
std::pair<bool, uint16_t> dico(dic_comp_t &t_dictionary,
|
|
|
|
|
const uint16_t t_nr_chaine, const uint8_t t_c) {
|
2018-05-23 16:27:54 +02:00
|
|
|
|
if (t_nr_chaine == 0xFFFF) {
|
2018-04-05 18:47:07 +02:00
|
|
|
|
return std::make_pair(true, t_c);
|
2018-05-23 16:27:54 +02:00
|
|
|
|
}
|
2018-04-05 18:47:07 +02:00
|
|
|
|
auto &e = t_dictionary[std::make_pair(t_nr_chaine, t_c)];
|
2018-05-23 16:27:54 +02:00
|
|
|
|
return (e != 0) ? std::make_pair(true, e)
|
2018-04-05 18:47:07 +02:00
|
|
|
|
: std::make_pair(
|
|
|
|
|
false,
|
|
|
|
|
(e = static_cast<
|
|
|
|
|
typename std::remove_reference<decltype(e)>::type>(
|
|
|
|
|
t_dictionary.size()) +
|
|
|
|
|
255));
|
|
|
|
|
}
|
2018-06-10 21:21:06 +02:00
|
|
|
|
|
2018-06-10 23:44:10 +02:00
|
|
|
|
ustring dico_uncompress(std::map<uint16_t, ustring> &t_dict,
|
2018-06-10 21:21:06 +02:00
|
|
|
|
const uint16_t t_code, const uint16_t t_old) {
|
2018-06-10 23:44:10 +02:00
|
|
|
|
if constexpr(debug_mode) {
|
|
|
|
|
std::printf("Code: %d\tOld code: %d\n", t_code, t_old);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto e = (t_code < 256) ? ustring{static_cast<unsigned char>(t_code)}
|
|
|
|
|
: t_dict[t_code];
|
|
|
|
|
|
|
|
|
|
// Si le code n'existe pas
|
|
|
|
|
|
2018-06-10 21:21:06 +02:00
|
|
|
|
if(e.empty()) {
|
2018-06-10 23:44:10 +02:00
|
|
|
|
e = (t_old < 256) ? ustring{static_cast<unsigned char>(t_old)}
|
|
|
|
|
: t_dict[t_old];
|
2018-06-10 21:21:06 +02:00
|
|
|
|
const auto temp = e[0];
|
|
|
|
|
e += temp;
|
2018-06-10 23:44:10 +02:00
|
|
|
|
t_dict[t_code] = std::move(e);
|
|
|
|
|
if constexpr(debug_mode) {
|
|
|
|
|
std::printf("String: %s\n", e.c_str());
|
|
|
|
|
}
|
2018-06-10 21:21:06 +02:00
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-10 23:44:10 +02:00
|
|
|
|
// auto str = t_dict[t_old];
|
|
|
|
|
auto str = (t_old < 256) ? ustring{static_cast<unsigned char>(t_old)}
|
|
|
|
|
: t_dict[t_old];
|
2018-06-10 21:21:06 +02:00
|
|
|
|
str += str[0];
|
2018-06-10 23:44:10 +02:00
|
|
|
|
t_dict[static_cast<uint16_t>(t_dict.size() + 255)] = std::move(str);
|
|
|
|
|
if constexpr(debug_mode) {
|
|
|
|
|
std::printf("String: %s\n", e.c_str());
|
|
|
|
|
}
|
2018-06-10 21:21:06 +02:00
|
|
|
|
return e;
|
|
|
|
|
}
|