
com.ggasoftware.parso.CharDecompressor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of parso Show documentation
Show all versions of parso Show documentation
A lightweight library to parse sas7bdat files. Supports 'CHAR' compression.
package com.ggasoftware.parso;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of the CHAR compression algorithm which corresponds to the literal "SASYZCRL".
* Refer the documentation for further details.
* It follows the general contract provided by the interface Decompressor
.
*
* @author dzhelezov
*
*/
public final class CharDecompressor implements Decompressor {
private static final Logger logger = LoggerFactory.getLogger(CharDecompressor.class);
public static final CharDecompressor instance = new CharDecompressor();
private CharDecompressor() {
//prevent multiple instances
}
/**
* The function to decompress data. Compressed data are an array of bytes with control bytes and data bytes.
* The project documentation contains descriptions of the decompression algorithm.
*
* @param offset the offset of bytes array in {@link SasFileParser#cachedPage} that contains compressed data.
* @param length the length of bytes array that contains compressed data.
* @return an array of bytes with decompressed data.
*/
public byte[] decompressRow(int offset, int length, int resultLength, byte[] page) {
byte[] resultByteArray = new byte[resultLength];
int currentResultArrayIndex = 0;
for (int currentByteIndex = 0; currentByteIndex < length; currentByteIndex++) {
byte controlByte = (byte) (page[offset+currentByteIndex] & 0xF0);
byte endOfFirstByte = (byte) (page[offset+currentByteIndex] & 0x0F);
int countOfBytesToCopy;
switch (controlByte) {
case (byte) 0x00:
if (currentByteIndex != length - 1) {
countOfBytesToCopy = (page[offset+currentByteIndex + 1] & 0xFF) + 64 +
endOfFirstByte * 256;
System.arraycopy(page, offset + currentByteIndex + 2, resultByteArray,
currentResultArrayIndex, countOfBytesToCopy);
currentByteIndex += countOfBytesToCopy + 1;
currentResultArrayIndex += countOfBytesToCopy;
}
break;
case (byte) 0x40:
int copyCounter = endOfFirstByte * 16 + (page[offset+currentByteIndex + 1] & 0xFF);
for (int i = 0; i < copyCounter + 18; i++) {
resultByteArray[currentResultArrayIndex++] = page[offset+currentByteIndex + 2];
}
currentByteIndex += 2;
break;
case (byte) 0x60:
for (int i = 0; i < endOfFirstByte * 256 + (page[offset+currentByteIndex + 1] & 0xFF) + 17;
i++) {
resultByteArray[currentResultArrayIndex++] = 0x20;
}
currentByteIndex++;
break;
case (byte) 0x70:
for (int i = 0; i < (page[offset+currentByteIndex + 1] & 0xFF) + 17; i++) {
resultByteArray[currentResultArrayIndex++] = 0x00;
}
currentByteIndex++;
break;
case (byte) 0x80:
countOfBytesToCopy = Math.min(endOfFirstByte + 1, length - (currentByteIndex + 1));
System.arraycopy(page, offset + currentByteIndex + 1, resultByteArray,
currentResultArrayIndex, countOfBytesToCopy);
currentByteIndex += countOfBytesToCopy;
currentResultArrayIndex += countOfBytesToCopy;
break;
case (byte) 0x90:
countOfBytesToCopy = Math.min(endOfFirstByte + 17, length - (currentByteIndex + 1));
System.arraycopy(page, offset + currentByteIndex + 1, resultByteArray,
currentResultArrayIndex, countOfBytesToCopy);
currentByteIndex += countOfBytesToCopy;
currentResultArrayIndex += countOfBytesToCopy;
break;
case (byte) 0xA0:
countOfBytesToCopy = Math.min(endOfFirstByte + 33, length - (currentByteIndex + 1));
System.arraycopy(page, offset + currentByteIndex + 1, resultByteArray,
currentResultArrayIndex, countOfBytesToCopy);
currentByteIndex += countOfBytesToCopy;
currentResultArrayIndex += countOfBytesToCopy;
break;
case (byte) 0xB0:
countOfBytesToCopy = Math.min(endOfFirstByte + 49, length - (currentByteIndex + 1));
System.arraycopy(page, offset + currentByteIndex + 1, resultByteArray,
currentResultArrayIndex, countOfBytesToCopy);
currentByteIndex += countOfBytesToCopy;
currentResultArrayIndex += countOfBytesToCopy;
break;
case (byte) 0xC0:
for (int i = 0; i < endOfFirstByte + 3; i++) {
resultByteArray[currentResultArrayIndex++] = page[offset+currentByteIndex + 1];
}
currentByteIndex++;
break;
case (byte) 0xD0:
for (int i = 0; i < endOfFirstByte + 2; i++) {
resultByteArray[currentResultArrayIndex++] = 0x40;
}
break;
case (byte) 0xE0:
for (int i = 0; i < endOfFirstByte + 2; i++) {
resultByteArray[currentResultArrayIndex++] = 0x20;
}
break;
case (byte) 0xF0:
for (int i = 0; i < endOfFirstByte + 2; i++) {
resultByteArray[currentResultArrayIndex++] = 0x00;
}
break;
default:
logger.error("Error control byte: {}", controlByte);
break;
}
}
return resultByteArray;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy