/* * 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.rcfile.text; import com.facebook.presto.rcfile.RcFileCorruptionException; import com.facebook.presto.spi.block.Block; import com.facebook.presto.spi.block.BlockBuilder; import com.facebook.presto.spi.type.Type; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; public class ListEncoding extends BlockEncoding { private final TextColumnEncoding elementEncoding; public ListEncoding(Type type, Slice nullSequence, byte[] separators, Byte escapeByte, TextColumnEncoding elementEncoding) { super(type, nullSequence, separators, escapeByte); this.elementEncoding = elementEncoding; } @Override public void encodeValueInto(int depth, Block block, int position, SliceOutput output) throws RcFileCorruptionException { byte separator = getSeparator(depth); Block list = block.getObject(position, Block.class); for (int elementIndex = 0; elementIndex < list.getPositionCount(); elementIndex++) { if (elementIndex > 0) { output.writeByte(separator); } if (list.isNull(elementIndex)) { output.writeBytes(nullSequence); } else { elementEncoding.encodeValueInto(depth + 1, list, elementIndex, output); } } } @Override public void decodeValueInto(int depth, BlockBuilder builder, Slice slice, int offset, int length) throws RcFileCorruptionException { byte separator = getSeparator(depth); int end = offset + length; BlockBuilder arrayBlockBuilder = builder.beginBlockEntry(); if (length > 0) { int elementOffset = offset; while (offset < end) { byte currentByte = slice.getByte(offset); if (currentByte == separator) { decodeElementValueInto(depth, arrayBlockBuilder, slice, elementOffset, offset - elementOffset); elementOffset = offset + 1; } else if (isEscapeByte(currentByte) && offset + 1 < length) { // ignore the char after escape_char offset++; } offset++; } decodeElementValueInto(depth, arrayBlockBuilder, slice, elementOffset, offset - elementOffset); } builder.closeEntry(); } private void decodeElementValueInto(int depth, BlockBuilder blockBuilder, Slice slice, int offset, int length) throws RcFileCorruptionException { if (nullSequence.equals(0, nullSequence.length(), slice, offset, length)) { blockBuilder.appendNull(); } else { elementEncoding.decodeValueInto(depth + 1, blockBuilder, slice, offset, length); } } }