blob: 23267206f62471f891fd286827d876e71b9550a0 [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.
*/
#ifndef ENCODING_INT64PACKER_ENCODER_H
#define ENCODING_INT64PACKER_ENCODER_H
#define NUM_OF_INTS 8
#include "encoder.h"
namespace storage {
class Int64Packer {
private:
int width_;
public:
Int64Packer(int width_) { this->width_ = width_; }
~Int64Packer() { destroy(); }
void destroy() { /* do nothing for IntPacker */
}
void reset() { /* do thing for IntPacker */
}
void pack_8values(const int64_t values[], int offset, unsigned char buf[]) {
int buf_idx = 0;
int value_idx = offset;
// remaining bits for the current unfinished Integer
int left_bit = 0;
while (value_idx < NUM_OF_INTS + offset) {
// buffer is used for saving 64 bits as a part of result
int64_t buffer = 0;
// remaining size of bits in the 'buffer'
int left_size = 64;
// encode the left bits of current Integer to 'buffer'
if (left_bit > 0) {
buffer |= (static_cast<uint64_t>(values[value_idx])
<< (64 - left_bit));
left_size -= left_bit;
left_bit = 0;
value_idx++;
}
while (left_size >= width_ && value_idx < NUM_OF_INTS + offset) {
// encode one Integer to the 'buffer'
buffer |= (static_cast<uint64_t>(values[value_idx])
<< (left_size - width_));
left_size -= width_;
value_idx++;
}
// If the remaining space of the buffer can not save the bits for
// one Integer,
if (left_size > 0 && value_idx < NUM_OF_INTS + offset) {
// put the first 'left_size' bits of the Integer into remaining
// space of the buffer
buffer |= ((static_cast<uint64_t>(values[value_idx])) >>
(width_ - left_size));
left_bit = width_ - left_size;
}
// put the buffer into the final result
for (int j = 0; j < 8; j++) {
buf[buf_idx] =
(unsigned char)(((uint64_t)buffer >> ((8 - j - 1) * 8)) &
0xFF);
buf_idx++;
// width_ is the bit num of each value, but here is means the
// max byte num
if (buf_idx >= width_ * 8 / 8) {
return;
}
}
}
}
/**
* decode Integers from byte array.
*
* @param buf - array where bytes are in.
* @param offset - offset of first byte to be decoded in buf
* @param values - decoded result , the length of 'values' should be @{link
* IntPacker#NUM_OF_INTS}
*/
void unpack_8values(const unsigned char buf[], int offset,
int64_t values[]) {
int byte_idx = offset;
int value_idx = 0;
int left_bits = 8;
int total_bits = 0;
while (value_idx < 8) {
values[value_idx] = 0;
total_bits = 0;
while (total_bits < width_) {
if (width_ - total_bits >= left_bits) {
values[value_idx] <<= left_bits;
values[value_idx] |= static_cast<int64_t>(
buf[byte_idx] & ((1 << left_bits) - 1));
total_bits += left_bits;
byte_idx++;
left_bits = 8;
} else {
int t = width_ - total_bits;
values[value_idx] <<= t;
values[value_idx] |= static_cast<int64_t>(
(buf[byte_idx] & ((1 << left_bits) - 1)) >>
(left_bits - t));
left_bits -= t;
total_bits += t;
}
}
value_idx++;
}
}
/**
* decode all values from 'buf' with specified offset and length decoded
* result will be saved in the array named 'values'.
*
* @param buf array where all bytes are in.
* @param length length of bytes to be decoded in buf.
* @param values decoded result.
*/
void unpack_all_values(const unsigned char buf[], int length,
int64_t values[]) {
int idx = 0;
int k = 0;
while (idx < length) {
int64_t tv[8];
// decode 8 values one time, current result will be saved in the
// array named 'tv'
unpack_8values(buf, idx, tv);
// System.arraycopy(tv, 0, values, k, 8);
std::memmove(values + k, tv, 8 * sizeof(int64_t));
idx += width_;
k += 8;
}
}
void set_width(int width_) { this->width_ = width_; }
};
} // end namespace storage
#endif // ENCODING_IntPacker_ENCODER_H