src/http/ngx_http_huff_encode.c - nginx source code

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. * Copyright (C) Valentin V. Bartenev
  4. * Copyright (C) 2015 Vlad Krasnov
  5. */


  6. #include <ngx_config.h>
  7. #include <ngx_core.h>
  8. #include <ngx_http.h>


  9. typedef struct {
  10.     uint32_t  code;
  11.     uint32_t  len;
  12. } ngx_http_huff_encode_code_t;


  13. static ngx_http_huff_encode_code_t  ngx_http_huff_encode_table[256] =
  14. {
  15.     {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28},
  16.     {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28},
  17.     {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28},
  18.     {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28},
  19.     {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28},
  20.     {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28},
  21.     {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28},
  22.     {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28},
  23.     {0x000000146}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12},
  24.     {0x00001ff9, 13}, {0x000000156}, {0x000000f88}, {0x000007fa, 11},
  25.     {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f98}, {0x000007fb, 11},
  26.     {0x000000fa8}, {0x000000166}, {0x000000176}, {0x000000186},
  27.     {0x000000005}, {0x000000015}, {0x000000025}, {0x000000196},
  28.     {0x0000001a6}, {0x0000001b6}, {0x0000001c6}, {0x0000001d6},
  29.     {0x0000001e6}, {0x0000001f6}, {0x0000005c7}, {0x000000fb8},
  30.     {0x00007ffc, 15}, {0x000000206}, {0x00000ffb, 12}, {0x000003fc, 10},
  31.     {0x00001ffa, 13}, {0x000000216}, {0x0000005d7}, {0x0000005e7},
  32.     {0x0000005f7}, {0x000000607}, {0x000000617}, {0x000000627},
  33.     {0x000000637}, {0x000000647}, {0x000000657}, {0x000000667},
  34.     {0x000000677}, {0x000000687}, {0x000000697}, {0x0000006a7},
  35.     {0x0000006b7}, {0x0000006c7}, {0x0000006d7}, {0x0000006e7},
  36.     {0x0000006f7}, {0x000000707}, {0x000000717}, {0x000000727},
  37.     {0x000000fc8}, {0x000000737}, {0x000000fd8}, {0x00001ffb, 13},
  38.     {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x000000226},
  39.     {0x00007ffd, 15}, {0x000000035}, {0x000000236}, {0x000000045},
  40.     {0x000000246}, {0x000000055}, {0x000000256}, {0x000000266},
  41.     {0x000000276}, {0x000000065}, {0x000000747}, {0x000000757},
  42.     {0x000000286}, {0x000000296}, {0x0000002a6}, {0x000000075},
  43.     {0x0000002b6}, {0x000000767}, {0x0000002c6}, {0x000000085},
  44.     {0x000000095}, {0x0000002d6}, {0x000000777}, {0x000000787},
  45.     {0x000000797}, {0x0000007a7}, {0x0000007b7}, {0x00007ffe, 15},
  46.     {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28},
  47.     {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20},
  48.     {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23},
  49.     {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23},
  50.     {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23},
  51.     {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23},
  52.     {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23},
  53.     {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23},
  54.     {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24},
  55.     {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22},
  56.     {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21},
  57.     {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24},
  58.     {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23},
  59.     {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21},
  60.     {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23},
  61.     {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22},
  62.     {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23},
  63.     {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19},
  64.     {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25},
  65.     {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27},
  66.     {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25},
  67.     {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27},
  68.     {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24},
  69.     {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26},
  70.     {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27},
  71.     {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21},
  72.     {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23},
  73.     {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25},
  74.     {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23},
  75.     {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26},
  76.     {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27},
  77.     {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27},
  78.     {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26}
  79. };


  80. /* same as above, but embeds lowercase transformation */
  81. static ngx_http_huff_encode_code_t  ngx_http_huff_encode_table_lc[256] =
  82. {
  83.     {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28},
  84.     {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28},
  85.     {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28},
  86.     {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28},
  87.     {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28},
  88.     {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28},
  89.     {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28},
  90.     {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28},
  91.     {0x000000146}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12},
  92.     {0x00001ff9, 13}, {0x000000156}, {0x000000f88}, {0x000007fa, 11},
  93.     {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f98}, {0x000007fb, 11},
  94.     {0x000000fa8}, {0x000000166}, {0x000000176}, {0x000000186},
  95.     {0x000000005}, {0x000000015}, {0x000000025}, {0x000000196},
  96.     {0x0000001a6}, {0x0000001b6}, {0x0000001c6}, {0x0000001d6},
  97.     {0x0000001e6}, {0x0000001f6}, {0x0000005c7}, {0x000000fb8},
  98.     {0x00007ffc, 15}, {0x000000206}, {0x00000ffb, 12}, {0x000003fc, 10},
  99.     {0x00001ffa, 13}, {0x000000035}, {0x000000236}, {0x000000045},
  100.     {0x000000246}, {0x000000055}, {0x000000256}, {0x000000266},
  101.     {0x000000276}, {0x000000065}, {0x000000747}, {0x000000757},
  102.     {0x000000286}, {0x000000296}, {0x0000002a6}, {0x000000075},
  103.     {0x0000002b6}, {0x000000767}, {0x0000002c6}, {0x000000085},
  104.     {0x000000095}, {0x0000002d6}, {0x000000777}, {0x000000787},
  105.     {0x000000797}, {0x0000007a7}, {0x0000007b7}, {0x00001ffb, 13},
  106.     {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x000000226},
  107.     {0x00007ffd, 15}, {0x000000035}, {0x000000236}, {0x000000045},
  108.     {0x000000246}, {0x000000055}, {0x000000256}, {0x000000266},
  109.     {0x000000276}, {0x000000065}, {0x000000747}, {0x000000757},
  110.     {0x000000286}, {0x000000296}, {0x0000002a6}, {0x000000075},
  111.     {0x0000002b6}, {0x000000767}, {0x0000002c6}, {0x000000085},
  112.     {0x000000095}, {0x0000002d6}, {0x000000777}, {0x000000787},
  113.     {0x000000797}, {0x0000007a7}, {0x0000007b7}, {0x00007ffe, 15},
  114.     {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28},
  115.     {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20},
  116.     {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23},
  117.     {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23},
  118.     {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23},
  119.     {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23},
  120.     {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23},
  121.     {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23},
  122.     {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24},
  123.     {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22},
  124.     {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21},
  125.     {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24},
  126.     {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23},
  127.     {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21},
  128.     {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23},
  129.     {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22},
  130.     {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23},
  131.     {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19},
  132.     {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25},
  133.     {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27},
  134.     {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25},
  135.     {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27},
  136.     {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24},
  137.     {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26},
  138.     {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27},
  139.     {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21},
  140.     {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23},
  141.     {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25},
  142.     {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23},
  143.     {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26},
  144.     {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27},
  145.     {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27},
  146.     {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26}
  147. };


  148. #if (NGX_PTR_SIZE == 8)

  149. #if (NGX_HAVE_LITTLE_ENDIAN)

  150. #if (NGX_HAVE_GCC_BSWAP64)
  151. #define ngx_http_huff_encode_buf(dst, buf)                                    \
  152.     (*(uint64_t *) (dst) = __builtin_bswap64(buf))
  153. #else
  154. #define ngx_http_huff_encode_buf(dst, buf)                                    \
  155.     ((dst)[0] = (u_char) ((buf) >> 56),                                       \
  156.      (dst)[1] = (u_char) ((buf) >> 48),                                       \
  157.      (dst)[2] = (u_char) ((buf) >> 40),                                       \
  158.      (dst)[3] = (u_char) ((buf) >> 32),                                       \
  159.      (dst)[4] = (u_char) ((buf) >> 24),                                       \
  160.      (dst)[5] = (u_char) ((buf) >> 16),                                       \
  161.      (dst)[6] = (u_char) ((buf) >> 8),                                        \
  162.      (dst)[7] = (u_char)  (buf))
  163. #endif

  164. #else /* !NGX_HAVE_LITTLE_ENDIAN */
  165. #define ngx_http_huff_encode_buf(dst, buf)                                    \
  166.     (*(uint64_t *) (dst) = (buf))
  167. #endif

  168. #else /* NGX_PTR_SIZE == 4 */

  169. #define ngx_http_huff_encode_buf(dst, buf)                                    \
  170.     (*(uint32_t *) (dst) = htonl(buf))

  171. #endif


  172. size_t
  173. ngx_http_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower)
  174. {
  175.     u_char                       *end;
  176.     size_t                        hlen;
  177.     ngx_uint_t                    buf, pending, code;
  178.     ngx_http_huff_encode_code_t  *table, *next;

  179.     table = lower ? ngx_http_huff_encode_table_lc
  180.                   : ngx_http_huff_encode_table;
  181.     hlen = 0;
  182.     buf = 0;
  183.     pending = 0;

  184.     end = src + len;

  185.     while (src != end) {
  186.         next = &table[*src++];

  187.         code = next->code;
  188.         pending += next->len;

  189.         /* accumulate bits */
  190.         if (pending < sizeof(buf) * 8) {
  191.             buf |= code << (sizeof(buf) * 8 - pending);
  192.             continue;
  193.         }

  194.         if (hlen + sizeof(buf) >= len) {
  195.             return 0;
  196.         }

  197.         pending -= sizeof(buf) * 8;

  198.         buf |= code >> pending;

  199.         ngx_http_huff_encode_buf(&dst[hlen], buf);

  200.         hlen += sizeof(buf);

  201.         buf = pending ? code << (sizeof(buf) * 8 - pending) : 0;
  202.     }

  203.     if (pending == 0) {
  204.         return hlen;
  205.     }

  206.     buf |= (ngx_uint_t) -1 >> pending;

  207.     pending = ngx_align(pending, 8);

  208.     if (hlen + pending / 8 >= len) {
  209.         return 0;
  210.     }

  211.     buf >>= sizeof(buf) * 8 - pending;

  212.     do {
  213.         pending -= 8;
  214.         dst[hlen++] = (u_char) (buf >> pending);
  215.     } while (pending);

  216.     return hlen;
  217. }