lzw-assignment/src/common.cc

97 lines
3.2 KiB
C++
Raw Normal View History

2018-04-05 16:47:07 +00:00
/**
* \file common.cc
* \brief Implementation for functions in common
*/
#include "common.hh"
2018-06-05 09:38:27 +00:00
using std::uint16_t;
2018-06-11 14:34:35 +00:00
using std::uint8_t;
2018-06-05 09:38:27 +00:00
using dic_comp_t = std::map<std::pair<uint16_t, uint8_t>, uint16_t>;
using ustring = std::basic_string<unsigned char>;
2018-06-11 14:34:35 +00:00
using p_ustring = std::shared_ptr<ustring>;
2018-04-05 16:47:07 +00:00
2018-06-09 21:11:27 +00: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 16:47:07 +00:00
/**
* Cette fonction a pour double usage la recherche dune chaine de caractères
2018-06-11 14:34:35 +00:00
* dans le dictionnaire, ou bien lajout dune nouvelle chaîne si celle-ci
* nest 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 sagit 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.
2018-04-05 16:47:07 +00:00
*
2018-04-29 12:13:14 +00: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 09:38:27 +00:00
* \return const std::pair<bool, uint16_t>
2018-04-05 16:47:07 +00: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 14:27:54 +00:00
if (t_nr_chaine == 0xFFFF) {
2018-04-05 16:47:07 +00:00
return std::make_pair(true, t_c);
2018-05-23 14:27:54 +00:00
}
2018-04-05 16:47:07 +00:00
auto &e = t_dictionary[std::make_pair(t_nr_chaine, t_c)];
2018-05-23 14:27:54 +00:00
return (e != 0) ? std::make_pair(true, e)
2018-06-11 14:34:35 +00:00
: std::make_pair(false, (e = static_cast<uint16_t>(
t_dictionary.size() + 255)));
2018-04-05 16:47:07 +00:00
}
2018-06-11 14:34:35 +00:00
/**
* 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,
2018-06-11 14:34:35 +00:00
const uint16_t t_code, const uint16_t t_old) {
// le code existe dans le dictionnaire sil est < 256
if (t_code < 256) {
ustring e{static_cast<unsigned char>(t_code)};
// 256 car on n'a pas encore tenté d'insérer de nouveau caractère
2018-06-11 14:34:35 +00:00
if (t_old < 256) {
t_dict[static_cast<uint16_t>(t_dict.size() + 256)] =
static_cast<unsigned char>(t_old) + e;
2018-06-10 22:58:01 +00:00
} else {
2018-06-11 14:34:35 +00:00
t_dict[static_cast<uint16_t>(t_dict.size() + 256)] = t_dict[t_old] + e;
}
return e;
}
2018-06-11 14:34:35 +00:00
auto &e = t_dict[t_code];
auto str = (t_old < 256) ? ustring{static_cast<unsigned char>(t_old)}
: t_dict[t_old];
// le code existe dans le dictionnaire
if (!e.empty()) {
str += e[0];
2018-06-15 17:54:00 +00:00
const auto index = static_cast<uint16_t>(t_dict.size() + 256);
2018-06-11 14:34:35 +00:00
t_dict[index] = str;
return e;
}
// le code n'existe pas encore dans le dictionnaire
str += str[0];
e = str;
2018-06-10 22:58:01 +00:00
t_dict[t_code] = e;
return e;
}