// Copyright 2013 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Build per-context histograms of literals, commands and distance codes. #include "./histogram.h" #include #include #include "./block_splitter.h" #include "./command.h" #include "./context.h" #include "./prefix.h" namespace brotli { void BuildHistograms( const std::vector& cmds, const BlockSplit& literal_split, const BlockSplit& insert_and_copy_split, const BlockSplit& dist_split, const uint8_t* ringbuffer, size_t pos, size_t mask, const std::vector& context_modes, std::vector* literal_histograms, std::vector* insert_and_copy_histograms, std::vector* copy_dist_histograms) { BlockSplitIterator literal_it(literal_split); BlockSplitIterator insert_and_copy_it(insert_and_copy_split); BlockSplitIterator dist_it(dist_split); for (int i = 0; i < cmds.size(); ++i) { const Command &cmd = cmds[i]; insert_and_copy_it.Next(); (*insert_and_copy_histograms)[insert_and_copy_it.type_].Add( cmd.command_prefix_); for (int j = 0; j < cmd.insert_length_; ++j) { literal_it.Next(); uint8_t prev_byte = pos > 0 ? ringbuffer[(pos - 1) & mask] : 0; uint8_t prev_byte2 = pos > 1 ? ringbuffer[(pos - 2) & mask] : 0; int context = (literal_it.type_ << kLiteralContextBits) + Context(prev_byte, prev_byte2, context_modes[literal_it.type_]); (*literal_histograms)[context].Add(ringbuffer[pos & mask]); ++pos; } pos += cmd.copy_length_; if (cmd.copy_length_ > 0 && cmd.distance_prefix_ != 0xffff) { dist_it.Next(); int context = (dist_it.type_ << kDistanceContextBits) + ((cmd.copy_length_code_ > 4) ? 3 : cmd.copy_length_code_ - 2); (*copy_dist_histograms)[context].Add(cmd.distance_prefix_); } } } void BuildLiteralHistogramsForBlockType( const std::vector& cmds, const BlockSplit& literal_split, const uint8_t* ringbuffer, size_t pos, size_t mask, int block_type, int context_mode, std::vector* histograms) { BlockSplitIterator literal_it(literal_split); for (int i = 0; i < cmds.size(); ++i) { const Command &cmd = cmds[i]; for (int j = 0; j < cmd.insert_length_; ++j) { literal_it.Next(); if (literal_it.type_ == block_type) { uint8_t prev_byte = pos > 0 ? ringbuffer[(pos - 1) & mask] : 0; uint8_t prev_byte2 = pos > 1 ? ringbuffer[(pos - 2) & mask] : 0; int context = Context(prev_byte, prev_byte2, context_mode); (*histograms)[context].Add(ringbuffer[pos & mask]); } ++pos; } pos += cmd.copy_length_; } } } // namespace brotli