Advertisement
EeZotop

lzw cpp

Dec 31st, 2021
1,086
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.47 KB | None | 0 0
  1. #include <algorithm>
  2. #include <bitset>
  3. #include <byteswap.h>
  4. #include <cstddef>
  5. #include <cstdio>
  6. #include <cstring>
  7. #include <iostream>
  8. #include <ostream>
  9. #include <vector>
  10.  
  11. #include "x86intrin.h"
  12.  
  13. extern "C" size_t lol(const uint8_t * in, size_t in_size, uint8_t * out, size_t out_size);
  14.  
  15. #ifndef NDEBUG
  16. #define Log(strm) std::cout << strm
  17. #else
  18. #define Log(strm)
  19. #endif
  20.  
  21. struct StrView
  22. {
  23.     uint32_t data = 0;
  24.     uint32_t size = 0;
  25. };
  26.  
  27. class StrViewPrinter
  28. {
  29. public:
  30.     StrViewPrinter(const uint8_t * data, StrView view)
  31.         : data(data + view.data)
  32.         , size(view.size)
  33.     {}
  34.  
  35.     friend std::ostream & operator<<(std::ostream & out, StrViewPrinter printer)
  36.     {
  37.         out << std::hex;
  38.         auto * it = printer.data;
  39.         auto * end = it + printer.size;
  40.         while (it != end) {
  41.             out << uint32_t(*it++) << ' ';
  42.         }
  43.         return out;
  44.     }
  45.  
  46. private:
  47.     const uint8_t * const data = nullptr;
  48.     const size_t size = 0;
  49. };
  50.  
  51. volatile uint64_t rdtscp()
  52. {
  53.     unsigned dummy;
  54.     return __rdtscp(&dummy);
  55. }
  56.  
  57. constexpr uint32_t bits(uint32_t &) { return 32; }
  58. constexpr uint32_t half_bits(uint32_t &) { return 16; }
  59.  
  60. constexpr uint32_t ClearCode = 256;
  61. constexpr uint32_t EOI = 257;
  62. constexpr uint32_t FirstInTable = 258;
  63.  
  64. constexpr uint32_t SwitchTo10 = 510;
  65. constexpr uint32_t SwitchTo11 = 1022;
  66. constexpr uint32_t SwitchTo12 = 2046;
  67.  
  68. constexpr size_t TableSize = 4096;
  69.  
  70.  
  71. uint32_t read_num(const uint8_t *& in, uint32_t & buff, uint8_t & bit_idx, uint8_t num_size)
  72. {
  73.     Log("read_num:\n");
  74.     Log(" buff:" << std::bitset<sizeof(buff)>(buff));
  75.     Log(std::dec);
  76.     Log(" bit_idx: " << int(bit_idx));
  77.     Log(" num_size: " << int(num_size));
  78.  
  79.     uint32_t res = (buff) << bit_idx;
  80.     res = res >> (bits(buff) - num_size);
  81.     Log(std::hex << " res: " << res << std::endl);
  82.  
  83.     bit_idx += num_size;
  84.     if (bit_idx > half_bits(buff)) {
  85.         bit_idx -= half_bits(buff);
  86.         buff = (buff << 8) | *in++;
  87.         buff = (buff << 8) | *in++;
  88.     }
  89.     return res;
  90.  
  91. }
  92.  
  93. void clear_table(StrView * table)
  94. {
  95.     auto * end = table + TableSize;
  96.     table += FirstInTable;
  97.     while (table != end) {
  98.         *table++ = {0, 0};
  99.     }
  100. }
  101.  
  102. void write_string(uint32_t code, StrView * table, const uint8_t * strings, uint8_t *& out)
  103. {
  104.     if (code < FirstInTable) {
  105.         Log("writech: " << code << '\n');
  106.         *out++ = code;
  107.     } else {
  108.         StrView view = table[code];
  109.         const uint8_t * str = strings + view.data;
  110.         const uint8_t * end = str + view.size;
  111.         Log("writestr: " << StrViewPrinter(strings, view) << '\n');
  112.         while (str != end) {
  113.             *out++ = *str++;
  114.         }
  115.     }
  116. }
  117.  
  118. size_t lzw_dec(const uint8_t * in, size_t in_size, uint8_t * out, size_t out_size)
  119. {
  120.     uint32_t buff = *in++;
  121.     buff = (buff << 8) | *in++;
  122.     buff = (buff << 8) | *in++;
  123.     buff = (buff << 8) | *in++;
  124.  
  125.     uint8_t bit_idx = 0;
  126.     uint8_t num_size = 9;
  127.  
  128.     uint32_t num = 0;
  129.     uint32_t old_num = 0;
  130.  
  131.     StrView table[TableSize];
  132.     for (auto it = table, end = it + FirstInTable; it != end; ++it) {
  133.         it->size = 1;
  134.     }
  135.     const uint8_t * strings = out;
  136.     uint32_t free_code;
  137.  
  138.     Log(std::hex);
  139.  
  140.     while ((num = read_num(in, buff, bit_idx, num_size)) != EOI) {
  141.         Log("num: " << num << '\n');
  142.         if (num == ClearCode) {
  143.             Log("cleaning up" << std::endl);
  144.             clear_table(table);
  145.             num_size = 9;
  146.             free_code = FirstInTable;
  147.             num = read_num(in, buff, bit_idx, num_size);
  148.             Log(num << '\n');
  149.             if (num == EOI) {
  150.                 break;
  151.             }
  152.             write_string(num, table, strings, out);
  153.             old_num = num;
  154.         } else {
  155.             StrView new_entry;
  156.             new_entry.data = (out - strings) - table[old_num].size; // old_num is what we've just written
  157.             new_entry.size = table[old_num].size + 1;
  158.             if (num < FirstInTable || table[num].size != 0) { // is in table
  159.                 write_string(num, table, strings, out);
  160.             } else {
  161.                 write_string(old_num, table, strings, out);
  162.                 uint8_t cycled = strings[new_entry.data];
  163.                 *out++ = cycled;
  164.                 Log("writeafter: " << int(cycled) << '\n');
  165.             }
  166.             Log("written: " << (out - strings) << '\n');
  167.             old_num = num;
  168.  
  169.             table[free_code] = new_entry;
  170.                 Log("code: " << free_code << " "
  171.                     "string: " << StrViewPrinter(strings, new_entry) << '\n');
  172.             switch (free_code) {
  173.                 case SwitchTo10:
  174.                 case SwitchTo11:
  175.                 case SwitchTo12:
  176.                     num_size++;
  177.                     Log("new_free_code: " << std::dec << free_code << std::endl);
  178.                     Log("new_num_size: " << int(num_size) << std::hex << std::endl);
  179.                     break;
  180.             }
  181.             free_code++;
  182.         }
  183.     }
  184.     return out - strings;
  185. }
  186.  
  187. uint8_t in[30000];
  188. uint8_t out[40000];
  189.  
  190. int main()
  191. {
  192.     auto input = fopen("in", "rb");
  193.     fread(in, 22118, 1, input);
  194.     fclose(input);
  195.  
  196.     volatile auto start = rdtscp();
  197.     auto decoded = lzw_dec(in, 22118, out, 40000);
  198.     volatile auto end = rdtscp();
  199.  
  200.     std::cout << "decode time: " << (end - start) << '\n';
  201.  
  202.     auto output = fopen("my_out", "wb");
  203.     fwrite(out, decoded, 1, output);
  204.     fclose(output);
  205.  
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement