bug fixed as input stream was char and not unsigned char

This commit is contained in:
Phuntsok Drak-pa 2018-06-11 21:02:59 +02:00
parent ec85a4b978
commit 67a88aaf91
4 changed files with 32 additions and 13 deletions

View File

@ -30,6 +30,9 @@ using ustring = std::basic_string<unsigned char>;
[[nodiscard]] vuchar [[nodiscard]] vuchar
pack_n(const vuint16::const_iterator t_input_begin, pack_n(const vuint16::const_iterator t_input_begin,
const vuint16::const_iterator t_input_end, const int t_n) { const vuint16::const_iterator t_input_end, const int t_n) {
#ifdef Debug
std::printf("%d bits!\n", t_n);
#endif
if (t_n == 16) { if (t_n == 16) {
return pack_16(t_input_begin, t_input_end); return pack_16(t_input_begin, t_input_end);
} }

View File

@ -65,8 +65,11 @@ 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) {
// le code existe dans le dictionnaire sil est < 256 // le code existe dans le dictionnaire sil est < 256
if (t_code < 256) { if (t_code < 256) {
#ifdef Debug
std::printf("Code : %d\tNOT EMPTY\n", t_code);
#endif
ustring e{static_cast<unsigned char>(t_code)}; ustring e{static_cast<unsigned char>(t_code)};
// 256 car on n'a pas encore tenté d'insérer de nouveau caractère
if (t_old < 256) { if (t_old < 256) {
t_dict[static_cast<uint16_t>(t_dict.size() + 256)] = t_dict[static_cast<uint16_t>(t_dict.size() + 256)] =
static_cast<unsigned char>(t_old) + e; static_cast<unsigned char>(t_old) + e;
@ -82,6 +85,9 @@ ustring dico_uncompress(std::map<uint16_t, ustring> &t_dict,
// le code existe dans le dictionnaire // le code existe dans le dictionnaire
if (!e.empty()) { if (!e.empty()) {
#ifdef Debug
std::printf("Code : %d\tNOT EMPTY\n", t_code);
#endif
str += e[0]; str += e[0];
const uint16_t index = static_cast<uint16_t>(t_dict.size() + 256); const uint16_t index = static_cast<uint16_t>(t_dict.size() + 256);
t_dict[index] = str; t_dict[index] = str;
@ -89,6 +95,9 @@ ustring dico_uncompress(std::map<uint16_t, ustring> &t_dict,
} }
// le code n'existe pas encore dans le dictionnaire // le code n'existe pas encore dans le dictionnaire
#ifdef Debug
std::printf("Code : %d\tEMPTY\n", t_code);
#endif
str += str[0]; str += str[0];
e = str; e = str;
t_dict[t_code] = e; t_dict[t_code] = e;

View File

@ -15,7 +15,7 @@ using std::uint8_t;
using std::vector; using std::vector;
using vuint16 = vector<uint16_t>; using vuint16 = vector<uint16_t>;
using vvuint16 = vector<vuint16>; using vvuint16 = vector<vuint16>;
using std::string; 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;
@ -33,7 +33,7 @@ const size_t DICT_MAX = static_cast<size_t>(ipow(2, 17) - 256); /* 16 bits */
* \param t_text Chaîne de caractères uint8_t représentant le fichier d'entrée * \param t_text Chaîne de caractères uint8_t représentant le fichier d'entrée
* \return Vecteur de chunks (vecteurs de uint16_t) * \return Vecteur de chunks (vecteurs de uint16_t)
*/ */
vvuint16 lzw_compress(string &&t_text) { vvuint16 lzw_compress(ustring &&t_text) {
std::puts("Compressing..."); std::puts("Compressing...");
uint16_t w = 0xFFFF; uint16_t w = 0xFFFF;
vuint16 chunk{}; vuint16 chunk{};
@ -49,7 +49,7 @@ vvuint16 lzw_compress(string &&t_text) {
if (const auto &[yes, pos] = dico(dict, w, static_cast<uint8_t>(c)); yes) { if (const auto &[yes, pos] = dico(dict, w, static_cast<uint8_t>(c)); yes) {
w = pos; w = pos;
} else { } else {
chunk.push_back(static_cast<uint16_t>(w)); chunk.push_back(w);
w = static_cast<uint16_t>(c); w = static_cast<uint16_t>(c);
} }
} }
@ -70,20 +70,26 @@ vvuint16 lzw_compress(string &&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) {
std::ifstream input_file{t_in_file}; FILE *const input_file = fopen(t_in_file.c_str(), "rb");
assert(input_file.is_open()); assert(input_file);
FILE *const out = (t_out_file != nullptr) ? fopen(t_out_file, "wb") FILE *const out = (t_out_file != nullptr) ? fopen(t_out_file, "wb")
: fopen("output.lzw", "wb"); : fopen("output.lzw", "wb");
if (out == nullptr) { 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";
input_file.close(); // input_file.close();
std::fclose(input_file);
exit(1); exit(1);
} }
const auto compressed_text{
lzw_compress(std::string{std::istreambuf_iterator<char>(input_file), std::fseek(input_file, 0L, SEEK_END);
std::istreambuf_iterator<char>()})}; 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); fclose(out);
input_file.close(); fclose(input_file);
} }

View File

@ -12,7 +12,8 @@
#include <thread> #include <thread>
/// \brief Compression d'une chaine de caractères /// \brief Compression d'une chaine de caractères
std::vector<std::vector<std::uint16_t>> lzw_compress(std::string &&); std::vector<std::vector<std::uint16_t>>
lzw_compress(std::basic_string<unsigned char> &&);
/// \brief Wrapper de \ref lzw_compress /// \brief Wrapper de \ref lzw_compress
void compress(const std::string &, const char *); void compress(const std::string &, const char *);