com.facebook.presto.orc.stream.DecimalStream Maven / Gradle / Ivy
/*
* 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.
*/
package com.facebook.presto.orc.stream;
import com.facebook.presto.orc.OrcCorruptionException;
import com.facebook.presto.orc.checkpoint.DecimalStreamCheckpoint;
import java.io.IOException;
import java.math.BigInteger;
import static java.lang.Long.MAX_VALUE;
public class DecimalStream
implements ValueStream
{
private final OrcInputStream input;
public DecimalStream(OrcInputStream input)
{
this.input = input;
}
@Override
public Class extends DecimalStreamCheckpoint> getCheckpointType()
{
return DecimalStreamCheckpoint.class;
}
@Override
public void seekToCheckpoint(DecimalStreamCheckpoint checkpoint)
throws IOException
{
input.seekToCheckpoint(checkpoint.getInputStreamCheckpoint());
}
// This comes from the Apache Hive ORC code (see org.apache.hadoop.hive.ql.io.orc.SerializationUtils.java)
public BigInteger nextBigInteger()
throws IOException
{
BigInteger result = BigInteger.ZERO;
long work = 0;
int offset = 0;
long b;
do {
b = input.read();
if (b == -1) {
throw new OrcCorruptionException("Reading BigInteger past EOF from " + input);
}
work |= (0x7f & b) << (offset % 63);
if (offset >= 126 && (offset != 126 || work > 3)) {
throw new OrcCorruptionException("Decimal exceeds 128 bits");
}
offset += 7;
// if we've read 63 bits, roll them into the result
if (offset == 63) {
result = BigInteger.valueOf(work);
work = 0;
}
else if (offset % 63 == 0) {
result = result.or(BigInteger.valueOf(work).shiftLeft(offset - 63));
work = 0;
}
}
while (b >= 0x80);
if (work != 0) {
result = result.or(BigInteger.valueOf(work).shiftLeft((offset / 63) * 63));
}
// convert back to a signed number
boolean isNegative = result.testBit(0);
if (isNegative) {
result = result.add(BigInteger.ONE);
result = result.negate();
}
result = result.shiftRight(1);
return result;
}
public void nextBigIntegerVector(int items, BigInteger[] vector)
throws IOException
{
for (int i = 0; i < items; i++) {
vector[i] = nextBigInteger();
}
}
public void nextBigIntegerVector(int items, BigInteger[] vector, boolean[] isNull)
throws IOException
{
for (int i = 0; i < items; i++) {
if (!isNull[i]) {
vector[i] = nextBigInteger();
}
}
}
public long nextLong()
throws IOException
{
long result = 0;
int offset = 0;
long b;
do {
b = input.read();
if (b == -1) {
throw new OrcCorruptionException("Reading BigInteger past EOF from " + input);
}
long work = 0x7f & b;
if (offset >= 63 && (offset != 63 || work > 1)) {
throw new OrcCorruptionException("Decimal does not fit long (invalid table schema?)");
}
result |= work << offset;
offset += 7;
}
while (b >= 0x80);
boolean isNegative = (result & 0x01) != 0;
if (isNegative) {
result += 1;
result = -result;
result = result >> 1;
result |= 0x01L << 63;
}
else {
result = result >> 1;
result &= MAX_VALUE;
}
return result;
}
public void nextLongVector(int items, long[] vector)
throws IOException
{
for (int i = 0; i < items; i++) {
vector[i] = nextLong();
}
}
public void nextLongVector(int items, long[] vector, boolean[] isNull)
throws IOException
{
for (int i = 0; i < items; i++) {
if (!isNull[i]) {
vector[i] = nextLong();
}
}
}
@Override
public void skip(long items)
throws IOException
{
while (items-- > 0) {
int b;
do {
b = input.read();
if (b == -1) {
throw new OrcCorruptionException("Reading BigInteger past EOF from " + input);
}
}
while (b >= 0x80);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy