aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/brotli/enc/histogram.c
blob: df29e30e94a1bcd92c5b2b0e21a97d065fcf6364 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Copyright 2013 Google Inc. All Rights Reserved. 
 
   Distributed under MIT license. 
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 
*/ 
 
/* Build per-context histograms of literals, commands and distance codes. */ 
 
#include "./histogram.h" 
 
#include "../common/context.h"
#include "./block_splitter.h" 
#include "./command.h" 
 
#if defined(__cplusplus) || defined(c_plusplus) 
extern "C" { 
#endif 
 
typedef struct BlockSplitIterator { 
  const BlockSplit* split_;  /* Not owned. */ 
  size_t idx_; 
  size_t type_; 
  size_t length_; 
} BlockSplitIterator; 
 
static void InitBlockSplitIterator(BlockSplitIterator* self, 
    const BlockSplit* split) { 
  self->split_ = split; 
  self->idx_ = 0; 
  self->type_ = 0; 
  self->length_ = split->lengths ? split->lengths[0] : 0; 
} 
 
static void BlockSplitIteratorNext(BlockSplitIterator* self) { 
  if (self->length_ == 0) { 
    ++self->idx_; 
    self->type_ = self->split_->types[self->idx_]; 
    self->length_ = self->split_->lengths[self->idx_]; 
  } 
  --self->length_; 
} 
 
void BrotliBuildHistogramsWithContext( 
    const Command* cmds, const size_t num_commands, 
    const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, 
    const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos, 
    size_t mask, uint8_t prev_byte, uint8_t prev_byte2, 
    const ContextType* context_modes, HistogramLiteral* literal_histograms, 
    HistogramCommand* insert_and_copy_histograms, 
    HistogramDistance* copy_dist_histograms) { 
  size_t pos = start_pos; 
  BlockSplitIterator literal_it; 
  BlockSplitIterator insert_and_copy_it; 
  BlockSplitIterator dist_it; 
  size_t i; 
 
  InitBlockSplitIterator(&literal_it, literal_split); 
  InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split); 
  InitBlockSplitIterator(&dist_it, dist_split); 
  for (i = 0; i < num_commands; ++i) { 
    const Command* cmd = &cmds[i]; 
    size_t j; 
    BlockSplitIteratorNext(&insert_and_copy_it); 
    HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], 
        cmd->cmd_prefix_); 
    /* TODO: unwrap iterator blocks. */
    for (j = cmd->insert_len_; j != 0; --j) { 
      size_t context; 
      BlockSplitIteratorNext(&literal_it); 
      context = literal_it.type_;
      if (context_modes) {
        ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]);
        context = (context << BROTLI_LITERAL_CONTEXT_BITS) +
            BROTLI_CONTEXT(prev_byte, prev_byte2, lut);
      }
      HistogramAddLiteral(&literal_histograms[context], 
          ringbuffer[pos & mask]); 
      prev_byte2 = prev_byte; 
      prev_byte = ringbuffer[pos & mask]; 
      ++pos; 
    } 
    pos += CommandCopyLen(cmd); 
    if (CommandCopyLen(cmd)) { 
      prev_byte2 = ringbuffer[(pos - 2) & mask]; 
      prev_byte = ringbuffer[(pos - 1) & mask]; 
      if (cmd->cmd_prefix_ >= 128) { 
        size_t context; 
        BlockSplitIteratorNext(&dist_it); 
        context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) + 
            CommandDistanceContext(cmd); 
        HistogramAddDistance(&copy_dist_histograms[context], 
            cmd->dist_prefix_ & 0x3FF);
      } 
    } 
  } 
} 
 
#if defined(__cplusplus) || defined(c_plusplus) 
}  /* extern "C" */ 
#endif