Ejemplo n.º 1
0
/*
 * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
 * bits are not filled yet.  The |rembits| must be in range [1, 8],
 * inclusive.  At the end of the process, the |*dest_ptr| is updated
 * and points where next output should be placed. The number of
 * unfilled bits in the pointed location is returned.
 */
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
                               size_t rembits,
                               const nghttp2_huff_sym *sym)
{
  int rv;
  size_t nbits = sym->nbits;

  for(;;) {
    if(rembits > nbits) {
      if(*avail_ptr) {
        nghttp2_bufs_fast_orb_hold(bufs, sym->code << (rembits - nbits));
      } else {
        rv = nghttp2_bufs_orb_hold(bufs, sym->code << (rembits - nbits));
        if(rv != 0) {
          return rv;
        }

        *avail_ptr = nghttp2_bufs_cur_avail(bufs);
      }

      rembits -= nbits;

      break;
    }

    if(*avail_ptr) {
      nghttp2_bufs_fast_orb(bufs, sym->code >> (nbits - rembits));
      --*avail_ptr;
    } else {
      rv = nghttp2_bufs_orb(bufs, sym->code >> (nbits - rembits));
      if(rv != 0) {
        return rv;
      }

      *avail_ptr = nghttp2_bufs_cur_avail(bufs);
    }

    nbits -= rembits;
    rembits = 8;

    if(nbits == 0) {
      break;
    }

    if(*avail_ptr) {
      nghttp2_bufs_fast_addb_hold(bufs, 0);
    } else {
      rv = nghttp2_bufs_addb_hold(bufs, 0);
      if(rv != 0) {
        return rv;
      }

      *avail_ptr = nghttp2_bufs_cur_avail(bufs);
    }
  }
Ejemplo n.º 2
0
/*
 * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
 * bits are not filled yet.  The |rembits| must be in range [1, 8],
 * inclusive.  At the end of the process, the |*dest_ptr| is updated
 * and points where next output should be placed. The number of
 * unfilled bits in the pointed location is returned.
 */
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
                               size_t rembits, const nghttp2_huff_sym *sym) {
  int rv;
  size_t nbits = sym->nbits;
  uint32_t code = sym->code;

  /* We assume that sym->nbits <= 32 */
  if (rembits > nbits) {
    nghttp2_bufs_fast_orb_hold(bufs, code << (rembits - nbits));
    return (ssize_t)(rembits - nbits);
  }

  if (rembits == nbits) {
    nghttp2_bufs_fast_orb(bufs, code);
    --*avail_ptr;
    return 8;
  }

  nghttp2_bufs_fast_orb(bufs, code >> (nbits - rembits));
  --*avail_ptr;

  nbits -= rembits;
  if (nbits & 0x7) {
    /* align code to MSB byte boundary */
    code <<= 8 - (nbits & 0x7);
  }

  /* we lose at most 3 bytes, but it is not critical in practice */
  if (*avail_ptr < (nbits + 7) / 8) {
    rv = nghttp2_bufs_advance(bufs);
    if (rv != 0) {
      return rv;
    }
    *avail_ptr = nghttp2_bufs_cur_avail(bufs);
    /* we assume that we at least 3 buffer space available */
    assert(*avail_ptr >= 3);
  }

  /* fast path, since most code is less than 8 */
  if (nbits < 8) {
    nghttp2_bufs_fast_addb_hold(bufs, code);
    *avail_ptr = nghttp2_bufs_cur_avail(bufs);
    return (ssize_t)(8 - nbits);
  }

  /* handle longer code path */
  if (nbits > 24) {
    nghttp2_bufs_fast_addb(bufs, code >> 24);
    nbits -= 8;
  }
Ejemplo n.º 3
0
void test_nghttp2_bufs_addb(void)
{
  int rv;
  nghttp2_bufs bufs;
  ssize_t i;

  rv = nghttp2_bufs_init(&bufs, 1000, 3);
  CU_ASSERT(0 == rv);

  rv = nghttp2_bufs_addb(&bufs, 14);
  CU_ASSERT(0 == rv);
  CU_ASSERT(1 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(1 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(14 == *bufs.cur->buf.pos);

  for(i = 0; i < 999; ++i) {
    rv = nghttp2_bufs_addb(&bufs, 254);

    CU_ASSERT(0 == rv);
    CU_ASSERT(i + 2 == nghttp2_buf_len(&bufs.cur->buf));
    CU_ASSERT(i + 2 == nghttp2_bufs_len(&bufs));
    CU_ASSERT(254 == *(bufs.cur->buf.last - 1));
    CU_ASSERT(bufs.cur == bufs.head);
  }

  rv = nghttp2_bufs_addb(&bufs, 253);
  CU_ASSERT(0 == rv);
  CU_ASSERT(1 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(1001 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(253 == *(bufs.cur->buf.last - 1));
  CU_ASSERT(bufs.cur == bufs.head->next);

  rv = nghttp2_bufs_addb_hold(&bufs, 15);
  CU_ASSERT(0 == rv);
  CU_ASSERT(1 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(1001 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(15 == *(bufs.cur->buf.last));

  /* test fast version */

  nghttp2_bufs_fast_addb(&bufs, 240);

  CU_ASSERT(2 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(1002 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(240 == *(bufs.cur->buf.last - 1));

  nghttp2_bufs_fast_addb_hold(&bufs, 113);

  CU_ASSERT(2 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(1002 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(113 == *(bufs.cur->buf.last));

  /* addb_hold when last == end */
  bufs.cur->buf.last = bufs.cur->buf.end;

  rv = nghttp2_bufs_addb_hold(&bufs, 19);
  CU_ASSERT(0 == rv);
  CU_ASSERT(0 == nghttp2_buf_len(&bufs.cur->buf));
  CU_ASSERT(2000 == nghttp2_bufs_len(&bufs));
  CU_ASSERT(19 == *(bufs.cur->buf.last));

  nghttp2_bufs_free(&bufs);
}