blob: a47e9ce794d5fd3c0e971bbf663443cc338d10da [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
// Some portions Copyright (c) 2011 The LevelDB Authors.
//
// Endian-neutral encoding:
// * Fixed-length numbers are encoded with least-significant byte first
// * In addition we support variable length "varint" encoding
// * Strings are encoded prefixed by their length in varint format
#ifndef KUDU_UTIL_CODING_INL_H
#define KUDU_UTIL_CODING_INL_H
#include <cstdint>
#include <cstring>
#include "kudu/gutil/port.h" // IWYU pragma: keep
// IWYU pragma: no_include <endian.h>
namespace kudu {
inline uint8_t *InlineEncodeVarint32(uint8_t *dst, uint32_t v) {
// Operate on characters as unsigneds
uint8_t *ptr = dst;
static const int B = 128;
if (v < (1<<7)) {
*(ptr++) = v;
} else if (v < (1<<14)) {
*(ptr++) = v | B;
*(ptr++) = v>>7;
} else if (v < (1<<21)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = v>>14;
} else if (v < (1<<28)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = v>>21;
} else {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = (v>>21) | B;
*(ptr++) = v>>28;
}
return ptr;
}
inline void InlineEncodeFixed32(uint8_t *buf, uint32_t value) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(buf, &value, sizeof(value));
#else
buf[0] = value & 0xff;
buf[1] = (value >> 8) & 0xff;
buf[2] = (value >> 16) & 0xff;
buf[3] = (value >> 24) & 0xff;
#endif
}
inline void InlineEncodeFixed64(uint8_t *buf, uint64_t value) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(buf, &value, sizeof(value));
#else
buf[0] = value & 0xff;
buf[1] = (value >> 8) & 0xff;
buf[2] = (value >> 16) & 0xff;
buf[3] = (value >> 24) & 0xff;
buf[4] = (value >> 32) & 0xff;
buf[5] = (value >> 40) & 0xff;
buf[6] = (value >> 48) & 0xff;
buf[7] = (value >> 56) & 0xff;
#endif
}
// Standard Put... routines append to a string
template <class StrType>
inline void InlinePutFixed32(StrType *dst, uint32_t value) {
uint8_t buf[sizeof(value)];
InlineEncodeFixed32(buf, value);
dst->append(buf, sizeof(buf));
}
template <class StrType>
inline void InlinePutFixed64(StrType *dst, uint64_t value) {
uint8_t buf[sizeof(value)];
InlineEncodeFixed64(buf, value);
dst->append(buf, sizeof(buf));
}
template <class StrType>
inline void InlinePutVarint32(StrType* dst, uint32_t v) {
// We resize the array and then size it back down as appropriate
// rather than using append(), since the generated code ends up
// being substantially shorter.
int old_size = dst->size();
dst->resize(old_size + 5);
uint8_t* p = &(*dst)[old_size];
uint8_t *ptr = InlineEncodeVarint32(p, v);
dst->resize(old_size + ptr - p);
}
} // namespace kudu
#endif