/* * Copyright 2021 Google LLC * * 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. */ #pragma once #include #include "bits_util.h" class Varint { public: // Maximum lengths of varint encoding of uint64 static constexpr int kMax64 = 10; // REQUIRES "ptr" points to a buffer of length sufficient to hold "v". // EFFECTS Encodes "v" into "ptr" and returns a pointer to the // byte just past the last encoded byte. static char* Encode32(char* ptr, uint32_t v); static char* Encode64(char* ptr, uint64_t v); // EFFECTS Returns the encoding length of the specified value. static int Length64(uint64_t v); private: // A fully inlined version of Encode32: useful in the most time critical // routines, but its code size is large static char* Encode32Inline(char* ptr, uint32_t v); }; inline int Varint::Length64(uint64_t v) { // This computes value == 0 ? 1 : floor(log2(v)) / 7 + 1 using an explicit // multiplication to implement the division of a number in the 1..63 range. // Explicit OR 0x1 to handle v == 0. uint32_t log2value = BitsUtil::Log2FloorNonZero64(v | 0x1); return static_cast((log2value * 9 + 73) / 64); } inline char* Varint::Encode32Inline(char* sptr, uint32_t v) { // Operate on characters as unsigneds uint8_t* ptr = reinterpret_cast(sptr); static const uint32_t B = 128; if (v < (1 << 7)) { *(ptr++) = static_cast(v); } else if (v < (1 << 14)) { *(ptr++) = static_cast(v | B); *(ptr++) = static_cast(v >> 7); } else if (v < (1 << 21)) { *(ptr++) = static_cast(v | B); *(ptr++) = static_cast((v >> 7) | B); *(ptr++) = static_cast(v >> 14); } else if (v < (1 << 28)) { *(ptr++) = static_cast(v | B); *(ptr++) = static_cast((v >> 7) | B); *(ptr++) = static_cast((v >> 14) | B); *(ptr++) = static_cast(v >> 21); } else { *(ptr++) = static_cast(v | B); *(ptr++) = static_cast((v >> 7) | B); *(ptr++) = static_cast((v >> 14) | B); *(ptr++) = static_cast((v >> 21) | B); *(ptr++) = static_cast(v >> 28); } return reinterpret_cast(ptr); }