1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#ifndef VARINT_ENCODE_H 16#define VARINT_ENCODE_H 17#include <cinttypes> 18#include <cstddef> 19#include <type_traits> 20#include <cstdint> 21 22namespace OHOS { 23namespace Developtools { 24namespace Profiler { 25namespace ProtoEncoder { 26constexpr uint32_t VARINT32_SIZE = 4; 27constexpr uint32_t VARINT32_ENCODE_SIZE = 5; 28constexpr uint32_t VARINT64_SIZE = 8; 29constexpr uint32_t VARINT64_ENCODE_SIZE = 10; 30constexpr uint32_t VARINT_ENCODE_MAX_SIZE = VARINT64_ENCODE_SIZE; 31 32constexpr uint32_t VARINT_MAX_1BYTE = (1u << (7 * 1)) - 1; 33constexpr uint32_t VARINT_MAX_2BYTE = (1u << (7 * 2)) - 1; 34constexpr uint32_t VARINT_MAX_3BYTE = (1u << (7 * 3)) - 1; 35constexpr uint32_t VARINT_MAX_4BYTE = (1u << (7 * 4)) - 1; 36 37constexpr uint8_t VARINT_PAYLOAD_BITS = 7; 38constexpr uint8_t VARINT_MASK_PAYLOAD = 0x7F; 39constexpr uint8_t VARINT_MASK_MSB = 0x80; 40 41inline uint32_t GetPackedVarintLenSize(uint32_t itemCount, uint32_t itemSize, uint32_t& len) 42{ 43 len = itemCount; 44 if (itemSize == VARINT32_SIZE) { 45 len = itemCount * VARINT32_ENCODE_SIZE; 46 } else if (itemSize == VARINT64_SIZE) { 47 len = itemCount * VARINT64_ENCODE_SIZE; 48 } // else bool is 1 byte 49 50 const uint32_t one = 1; 51 const uint32_t two = 2; 52 const uint32_t three = 3; 53 const uint32_t four = 4; 54 if (len <= VARINT_MAX_1BYTE) { 55 return one; 56 } else if (len <= VARINT_MAX_2BYTE) { 57 return two; 58 } else if (len <= VARINT_MAX_3BYTE) { 59 return three; 60 } else if (len <= VARINT_MAX_4BYTE) { 61 return four; 62 } 63 64 return 0; // illegal, too large 65} 66 67template<typename T> 68inline typename std::make_unsigned<T>::type EncodeZigZag(T v) 69{ 70 if (v >= 0) { 71 return ((typename std::make_unsigned<T>::type)(v) << 1); 72 } 73 74 return ((typename std::make_unsigned<T>::type)(~v) << 1) + 1; 75} 76 77template<typename T> 78inline uint32_t EncodeVarint(uint8_t* buf, T v) 79{ 80 // https://developers.google.com/protocol-buffers/docs/encoding 81 // Unsigned Integers and Signed Integers(intN) 82 uint64_t value = static_cast<uint64_t>(v); 83 uint32_t size = 0; 84 while (value > static_cast<uint64_t>(VARINT_MAX_1BYTE)) { 85 buf[size] = (VARINT_MASK_PAYLOAD & value) | VARINT_MASK_MSB; 86 size++; 87 value >>= VARINT_PAYLOAD_BITS; 88 } 89 buf[size] = (VARINT_MASK_PAYLOAD & value); 90 size++; 91 92 return size; 93} 94 95template<typename T> 96inline uint32_t EncodeZigZagVarint(uint8_t* buf, T v) 97{ 98 return EncodeVarint(buf, EncodeZigZag(v)); 99} 100 101template<typename T> 102inline void EncodeVarintPadding(uint8_t* buf, T v, uint32_t paddingSize) 103{ 104 uint32_t size = 0; 105 paddingSize--; 106 while (size < paddingSize) { 107 buf[size] = (VARINT_MASK_PAYLOAD & v) | VARINT_MASK_MSB; 108 size++; 109 v >>= VARINT_PAYLOAD_BITS; 110 } 111 buf[size] = (VARINT_MASK_PAYLOAD & v); 112} 113} // namespace ProtoEncoder 114} // namespace Profiler 115} // namespace Developtools 116} // namespace OHOS 117#endif // VARINT_ENCODE_H 118