2017
[folly.git] / folly / detail / GroupVarintDetail.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <stddef.h>
20
21 namespace folly {
22
23 template <typename T>
24 class GroupVarint;
25
26 namespace detail {
27
28 template <typename T>
29 struct GroupVarintTraits;
30
31 template <>
32 struct GroupVarintTraits<uint32_t> {
33   enum : uint32_t {
34     kGroupSize = 4,
35     kHeaderSize = 1,
36   };
37 };
38
39 template <>
40 struct GroupVarintTraits<uint64_t> {
41   enum : uint32_t {
42     kGroupSize = 5,
43     kHeaderSize = 2,
44   };
45 };
46
47 template <typename T>
48 class GroupVarintBase {
49  protected:
50   typedef GroupVarintTraits<T> Traits;
51   enum : uint32_t { kHeaderSize = Traits::kHeaderSize };
52
53  public:
54   typedef T type;
55
56   /**
57    * Number of integers encoded / decoded in one pass.
58    */
59   enum : uint32_t { kGroupSize = Traits::kGroupSize };
60
61   /**
62    * Maximum encoded size.
63    */
64   enum : uint32_t { kMaxSize = kHeaderSize + sizeof(type) * kGroupSize };
65
66   /**
67    * Maximum size for n values.
68    */
69   static size_t maxSize(size_t n) {
70     // Full groups
71     size_t total = (n / kGroupSize) * kFullGroupSize;
72     // Incomplete last group, if any
73     n %= kGroupSize;
74     if (n) {
75       total += kHeaderSize + n * sizeof(type);
76     }
77     return total;
78   }
79
80   /**
81    * Size of n values starting at p.
82    */
83   static size_t totalSize(const T* p, size_t n) {
84     size_t size = 0;
85     for (; n >= kGroupSize; n -= kGroupSize, p += kGroupSize) {
86       size += Derived::size(p);
87     }
88     if (n) {
89       size += Derived::partialSize(p, n);
90     }
91     return size;
92   }
93
94  private:
95   typedef GroupVarint<T> Derived;
96   enum { kFullGroupSize = kHeaderSize + kGroupSize * sizeof(type) };
97 };
98
99 }  // namespace detail
100 }  // namespace folly