Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Unified Diff: net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc

Issue 2551153003: Add static domain security state generator tool. (Closed)
Patch Set: Fix iOS? Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc
diff --git a/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc b/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f2e68b7c3ef957774d6d6753c52caff0240fe036
--- /dev/null
+++ b/net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/domain_security_preload_generator/huffman/huffman_frequency_tracker.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace net {
+
+namespace transport_security_state {
+
+namespace {
+
+class HuffmanNode {
+ public:
+ HuffmanNode(uint8_t value,
+ uint32_t count,
+ std::unique_ptr<HuffmanNode> left,
+ std::unique_ptr<HuffmanNode> right)
+ : value_(value),
+ count_(count),
+ left_(std::move(left)),
+ right_(std::move(right)) {}
+ ~HuffmanNode() {}
+
+ bool IsLeaf() const {
+ return left_.get() == nullptr && right_.get() == nullptr;
+ }
+
+ uint8_t value() const { return value_; }
+ uint32_t count() const { return count_; }
+ const std::unique_ptr<HuffmanNode>& left() const { return left_; }
+ const std::unique_ptr<HuffmanNode>& right() const { return right_; }
+
+ private:
+ uint8_t value_;
+ uint32_t count_;
+ std::unique_ptr<HuffmanNode> left_;
+ std::unique_ptr<HuffmanNode> right_;
+};
+
+bool CompareNodes(const std::unique_ptr<HuffmanNode>& lhs,
+ const std::unique_ptr<HuffmanNode>& rhs) {
+ return lhs->count() < rhs->count();
+}
+
+} // namespace
+
+HuffmanFrequencyTracker::HuffmanFrequencyTracker() {}
+
+HuffmanFrequencyTracker::~HuffmanFrequencyTracker() {}
+
+void HuffmanFrequencyTracker::RecordUsage(uint8_t character) {
+ counts_[character] += 1;
+}
+
+HuffmanRepresentationTable HuffmanFrequencyTracker::ToTable() {
+ HuffmanRepresentationTable table;
+ std::unique_ptr<HuffmanNode> node(BuildTree());
+
+ TreeToTable(node.get(), 0, 0, &table);
+ return table;
+}
+
+void HuffmanFrequencyTracker::TreeToTable(HuffmanNode* node,
+ uint32_t bits,
+ uint32_t number_of_bits,
+ HuffmanRepresentationTable* table) {
+ if (node->IsLeaf()) {
+ HuffmanRepresentation item;
+ item.bits = bits;
+ item.number_of_bits = number_of_bits;
+
+ table->insert(HuffmanRepresentationPair(node->value(), item));
+ } else {
+ uint32_t new_bits = bits << 1;
+ TreeToTable(node->left().get(), new_bits, number_of_bits + 1, table);
+ TreeToTable(node->right().get(), new_bits | 1, number_of_bits + 1, table);
+ }
+}
+
+std::vector<uint8_t> HuffmanFrequencyTracker::ToVector() {
+ std::vector<uint8_t> bytes;
+ std::unique_ptr<HuffmanNode> node(BuildTree());
+ WriteToVector(node.get(), &bytes);
+ return bytes;
+}
+
+uint32_t HuffmanFrequencyTracker::WriteToVector(HuffmanNode* node,
+ std::vector<uint8_t>* vector) {
+ uint8_t left_value;
+ uint8_t right_value;
+ uint32_t child_position;
+
+ if (node->left()->IsLeaf()) {
+ left_value = 128 | node->left()->value();
+ } else {
+ child_position = WriteToVector(node->left().get(), vector);
+ CHECK(child_position < 512) << "huffman tree too large";
+ left_value = child_position / 2;
+ }
+
+ if (node->right()->IsLeaf()) {
+ right_value = 128 | node->right()->value();
+ } else {
+ child_position = WriteToVector(node->right().get(), vector);
+ CHECK(child_position < 512) << "huffman tree to large";
+ right_value = child_position / 2;
+ }
+
+ uint32_t position = static_cast<uint32_t>(vector->size());
+ vector->push_back(left_value);
+ vector->push_back(right_value);
+ return position;
+}
+
+std::unique_ptr<HuffmanNode> HuffmanFrequencyTracker::BuildTree() {
+ std::vector<std::unique_ptr<HuffmanNode>> nodes;
+ nodes.reserve(counts_.size());
+
+ for (const auto& item : counts_) {
+ if (item.second > 0) {
+ std::unique_ptr<HuffmanNode> node(
+ new HuffmanNode(item.first, item.second, nullptr, nullptr));
+ nodes.push_back(std::move(node));
+ }
+ }
+
+ if (nodes.size() < 2) {
+ return std::move(nodes[0]);
+ }
+
+ std::stable_sort(nodes.begin(), nodes.end(), CompareNodes);
+
+ while (nodes.size() > 1) {
+ std::unique_ptr<HuffmanNode> a = std::move(nodes[0]);
+ std::unique_ptr<HuffmanNode> b = std::move(nodes[1]);
+
+ uint32_t count_a = a->count();
+ uint32_t count_b = b->count();
+
+ std::unique_ptr<HuffmanNode> parent(
+ new HuffmanNode(0, count_a + count_b, std::move(a), std::move(b)));
+
+ nodes.erase(nodes.begin());
+ nodes[0] = std::move(parent);
+
+ std::stable_sort(nodes.begin(), nodes.end(), CompareNodes);
+ }
+
+ return std::move(nodes[0]);
+}
+
+} // namespace transport_security_state
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698