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

Side by Side Diff: components/safe_browsing_db/v4_rice.cc

Issue 2183433002: PVer4: RICE decode bytes to list of uint32 or 4-byte hash prefixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/size_t/unsigned int: to fix some compile errors on Windows Created 4 years, 4 months 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "base/strings/stringprintf.h"
7 #include "components/safe_browsing_db/v4_rice.h"
8
9 using google::protobuf::RepeatedField;
10
11 namespace safe_browsing {
12
13 namespace {
14
15 const unsigned int kMaxBitIndex = 8 * sizeof(uint32_t);
16
17 void GetBytesFromUInt32(uint32_t word, char* bytes) {
18 const size_t mask = 0xFF;
19 bytes[0] = (char)(word & mask);
20 bytes[1] = (char)((word >> 8) & mask);
21 bytes[2] = (char)((word >> 16) & mask);
22 bytes[3] = (char)((word >> 24) & mask);
23 }
24
25 } // namespace
26
27 // static
28 V4DecodeResult V4RiceDecoder::DecodeIntegers(const uint32_t first_value,
29 const int32_t rice_parameter,
30 const int32_t num_entries,
31 const std::string& encoded_data,
32 RepeatedField<uint32_t>* out) {
33 DCHECK(out);
34
35 if (num_entries < 0) {
36 return NUM_ENTRIES_NEGATIVE_FAILURE;
palmer 2016/07/27 23:39:40 Could this be a DCHECK (in addition to a productio
vakh (use Gerrit instead) 2016/07/28 07:26:31 Done.
37 }
38
39 out->Reserve(num_entries + 1);
40 uint32_t last_value = first_value;
41 out->Add(last_value);
42 if (num_entries > 0) {
palmer 2016/07/27 23:39:40 Nit: You could save a level of indentation by putt
vakh (use Gerrit instead) 2016/07/28 07:26:31 Done.
43 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
44 while (decoder.HasAnotherValue()) {
45 uint32_t offset;
46 V4DecodeResult result = decoder.GetNextValue(&offset);
47 if (result != DECODE_SUCCESS) {
48 return result;
49 }
50 last_value += offset;
palmer 2016/07/27 23:39:40 Could this arithmetic overflow? (Does it matter if
vakh (use Gerrit instead) 2016/07/28 07:26:31 Unexpected. Added a DCHECK.
51 out->Add(last_value);
52 }
53 }
54 return DECODE_SUCCESS;
55 }
56
57 // static
58 V4DecodeResult V4RiceDecoder::DecodeBytes(const uint32_t first_value,
59 const int32_t rice_parameter,
60 const int32_t num_entries,
61 const std::string& encoded_data,
62 std::string* out) {
63 DCHECK(out);
64
65 if (num_entries < 0) {
66 return NUM_ENTRIES_NEGATIVE_FAILURE;
67 }
68
69 out->reserve((num_entries + 1) * 4);
70 char bytes[4];
71 uint32_t last_value = first_value;
72 GetBytesFromUInt32(last_value, bytes);
73 out->append(bytes, 4);
74 if (num_entries > 0) {
75 V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
76 while (decoder.HasAnotherValue()) {
77 uint32_t offset;
78 V4DecodeResult result = decoder.GetNextValue(&offset);
79 if (result != DECODE_SUCCESS) {
80 return result;
81 }
82 last_value += offset;
83
84 GetBytesFromUInt32(last_value, bytes);
85 out->append(bytes, 4);
86 }
87 }
88 return DECODE_SUCCESS;
89 }
90
91 V4RiceDecoder::V4RiceDecoder(const int rice_parameter,
92 const int num_entries,
93 const std::string& encoded_data)
94 : rice_parameter_(rice_parameter),
95 num_entries_(num_entries),
96 data_(encoded_data),
97 current_word_(0) {
98 DCHECK_LE(0, num_entries_);
99 DCHECK_LE(2u, rice_parameter_);
100 DCHECK_GE(28u, rice_parameter_);
101
102 data_byte_index_ = 0;
103 current_word_bit_index_ = kMaxBitIndex;
104 }
105
106 V4RiceDecoder::~V4RiceDecoder() {}
107
108 bool V4RiceDecoder::HasAnotherValue() const {
109 return num_entries_ > 0;
110 }
111
112 V4DecodeResult V4RiceDecoder::GetNextValue(uint32_t* value) {
113 if (!HasAnotherValue()) {
114 return DECODE_NO_MORE_ENTRIES_FAILURE;
115 }
116
117 V4DecodeResult result;
118 uint32_t q = 0;
119 uint32_t bit;
120 do {
121 result = GetNextBits(1, &bit);
122 if (result != DECODE_SUCCESS) {
123 return result;
124 }
125 q += bit;
126 } while (bit);
127 uint32_t r = 0;
128 result = GetNextBits(rice_parameter_, &r);
129 if (result != DECODE_SUCCESS) {
130 return result;
131 }
132
133 *value = (q << rice_parameter_) + r;
134 num_entries_--;
135 return DECODE_SUCCESS;
136 }
137
138 V4DecodeResult V4RiceDecoder::GetNextWord(uint32_t* word) {
139 if (data_byte_index_ >= data_.size()) {
140 return DECODE_RAN_OUT_OF_BITS_FAILURE;
141 }
142
143 const size_t mask = 0xFF;
144 *word = (data_[data_byte_index_] & mask);
145 data_byte_index_++;
146 current_word_bit_index_ = 0;
147
148 if (data_byte_index_ < data_.size()) {
149 *word |= ((data_[data_byte_index_] & mask) << 8);
150 data_byte_index_++;
151
152 if (data_byte_index_ < data_.size()) {
153 *word |= ((data_[data_byte_index_] & mask) << 16);
154 data_byte_index_++;
155
156 if (data_byte_index_ < data_.size()) {
157 *word |= ((data_[data_byte_index_] & mask) << 24);
158 data_byte_index_++;
159 }
160 }
161 }
162
163 *word = *word & 0xFFFFFFFF;
palmer 2016/07/27 23:39:40 Is this line necessary? (Maybe it is, I'm not sure
vakh (use Gerrit instead) 2016/07/28 07:26:31 Done. You're right. I had implemented this method
164 return DECODE_SUCCESS;
165 }
166
167 V4DecodeResult V4RiceDecoder::GetNextBits(unsigned int num_requested_bits,
168 uint32_t* x) {
169 if (num_requested_bits > kMaxBitIndex) {
170 NOTREACHED();
171 return DECODE_REQUESTED_TOO_MANY_BITS_FAILURE;
172 }
173
174 if (current_word_bit_index_ == kMaxBitIndex) {
175 V4DecodeResult result = GetNextWord(&current_word_);
176 if (result != DECODE_SUCCESS) {
177 return result;
178 }
179 }
180
181 unsigned int num_bits_left_in_current_word =
182 kMaxBitIndex - current_word_bit_index_;
183 if (num_bits_left_in_current_word >= num_requested_bits) {
184 // All the bits that we need are in current_word_
palmer 2016/07/27 23:39:40 Nit: // All the bits that we need are in |cur
vakh (use Gerrit instead) 2016/07/28 07:26:31 Done.
185 GetBitsFromCurrentWord(num_requested_bits, x);
186 } else {
187 // |current_word_| contains fewer bits than we need so we store the current
188 // value of |current_word_| in |lower|, then read in a new |current_word_|,
189 // and then pick the remaining bits from the new value of |current_word_|.
190 uint32_t lower = current_word_;
191 // Bits we need after we read all of |current_word_|
192 unsigned int num_bits_from_next_word =
193 num_requested_bits - num_bits_left_in_current_word;
194 uint32_t upper;
195 V4DecodeResult result = GetNextWord(&current_word_);
196 if (result != DECODE_SUCCESS) {
197 return result;
198 }
199 GetBitsFromCurrentWord(num_bits_from_next_word, &upper);
200 *x = (upper << (num_requested_bits - num_bits_from_next_word)) | lower;
201 }
202 return DECODE_SUCCESS;
203 }
204
205 void V4RiceDecoder::GetBitsFromCurrentWord(unsigned int num_requested_bits,
206 uint32_t* x) {
207 uint32_t mask = 0xFFFFFFFF >> (kMaxBitIndex - num_requested_bits);
208 *x = current_word_ & mask;
209 current_word_ = current_word_ >> num_requested_bits;
210 current_word_bit_index_ += num_requested_bits;
211 };
212
213 std::string V4RiceDecoder::DebugString() const {
214 return base::StringPrintf(
215 "current_word_: %x; data_byte_index_; %x, "
216 "current_word_bit_index_: %x; rice_parameter_: %x",
217 current_word_, data_byte_index_, current_word_bit_index_,
218 rice_parameter_);
219 }
220
221 std::ostream& operator<<(std::ostream& os, const V4RiceDecoder& rice_decoder) {
222 os << rice_decoder.DebugString();
223 return os;
224 }
225
226 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698