1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "logging/rtc_event_log/encoder/var_int.h"
12 
13 #include "rtc_base/checks.h"
14 
15 // TODO(eladalon): Add unit tests.
16 
17 namespace webrtc {
18 
19 const size_t kMaxVarIntLengthBytes = 10;  // ceil(64 / 7.0) is 10.
20 
EncodeVarInt(uint64_t input)21 std::string EncodeVarInt(uint64_t input) {
22   std::string output;
23   output.reserve(kMaxVarIntLengthBytes);
24 
25   do {
26     uint8_t byte = static_cast<uint8_t>(input & 0x7f);
27     input >>= 7;
28     if (input > 0) {
29       byte |= 0x80;
30     }
31     output += byte;
32   } while (input > 0);
33 
34   RTC_DCHECK_GE(output.size(), 1u);
35   RTC_DCHECK_LE(output.size(), kMaxVarIntLengthBytes);
36 
37   return output;
38 }
39 
40 // There is some code duplication between the flavors of this function.
41 // For performance's sake, it's best to just keep it.
DecodeVarInt(absl::string_view input,uint64_t * output)42 size_t DecodeVarInt(absl::string_view input, uint64_t* output) {
43   RTC_DCHECK(output);
44 
45   uint64_t decoded = 0;
46   for (size_t i = 0; i < input.length() && i < kMaxVarIntLengthBytes; ++i) {
47     decoded += (static_cast<uint64_t>(input[i] & 0x7f)
48                 << static_cast<uint64_t>(7 * i));
49     if (!(input[i] & 0x80)) {
50       *output = decoded;
51       return i + 1;
52     }
53   }
54 
55   return 0;
56 }
57 
58 // There is some code duplication between the flavors of this function.
59 // For performance's sake, it's best to just keep it.
DecodeVarInt(rtc::BitBuffer * input,uint64_t * output)60 size_t DecodeVarInt(rtc::BitBuffer* input, uint64_t* output) {
61   RTC_DCHECK(output);
62 
63   uint64_t decoded = 0;
64   for (size_t i = 0; i < kMaxVarIntLengthBytes; ++i) {
65     uint8_t byte;
66     if (!input->ReadUInt8(&byte)) {
67       return 0;
68     }
69     decoded +=
70         (static_cast<uint64_t>(byte & 0x7f) << static_cast<uint64_t>(7 * i));
71     if (!(byte & 0x80)) {
72       *output = decoded;
73       return i + 1;
74     }
75   }
76 
77   return 0;
78 }
79 
80 }  // namespace webrtc
81