blob: 483d0c92de3c7368a8f38caa8cbca77d67315e25 [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_IntPacker_ENCODER_H
#define ENCODING_IntPacker_ENCODER_H
#define NUM_OF_INTS 8
#include "encoder.h"
namespace storage {
class IntPacker {
private:
int width_;
public:
IntPacker(int width_) { this->width_ = width_; }
~IntPacker() { destroy(); }
void destroy() { /* do nothing for IntPacker */
}
void reset() { /* do thing for IntPacker */
}
void pack_8values(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 32 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 |= (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 |= (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 |= ((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(unsigned char buf[], int offset, int64_t values[]) {
int byte_idx = offset;
uint64_t buffer = 0;
// total bits which have reader from 'buf' to 'buffer'. i.e.,
// number of available bits to be decoded.
int total_bits = 0;
int value_idx = 0;
while (value_idx < NUM_OF_INTS) {
// If current available bits are not enough to decode one Integer,
// then add next byte from buf to 'buffer' until total_bits >= width
while (total_bits < width_) {
buffer = (buffer << 8) | (buf[byte_idx] & 0xFF);
byte_idx++;
total_bits += 8;
}
// If current available bits are enough to decode one Integer,
// then decode one Integer one by one until left bits in 'buffer' is
// not enough to decode one Integer.
while (total_bits >= width_ && value_idx < 8) {
values[value_idx] = (int)(buffer >> (total_bits - width_));
value_idx++;
total_bits -= width_;
buffer = buffer & ((1 << total_bits) - 1);
}
}
}
/**
* 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(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