package aliview.importer;
import java.io.EOFException;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import sun.nio.cs.ext.ISCII91;
import it.unimi.dsi.io.ByteBufferInpStream;
public class MappedBuffReaderHelper {
private static final Logger logger = Logger.getLogger(MappedBuffReaderHelper.class);
private ByteBufferInpStream mappedBuff;
private byte lastRead;
public MappedBuffReaderHelper(ByteBufferInpStream mappedBuff) {
this.mappedBuff = mappedBuff;
}
public void setPosition(long position) {
mappedBuff.position(position);
}
public long findNext(byte target){
while(true){
if(target == mappedBuff.read()){
return mappedBuff.position() - 1;
}
}
}
public long findNextOrEOF(byte target) {
while(true){
if(target == mappedBuff.read()){
return mappedBuff.position() - 1;
}
}
}
private boolean isEOF(){
return lastRead == -1;
}
private byte read() throws EOFException {
lastRead = (byte)mappedBuff.read();
//logger.info("" + (char) lastRead);
if(lastRead == -1){
throw new EOFException();
}
return lastRead;
}
public long appendBytesUntilNextLF(StringBuilder stringBuff) throws EOFException{
while(true){
int nextByte = read();
if(isLF(nextByte)){
return mappedBuff.position() - 1;
}else{
stringBuff.append((char)nextByte);
}
}
}
private boolean isReturnOrLF(int nextByte) {
if(nextByte == '\n' || nextByte == '\r'){
return true;
}
return false;
}
private boolean isLF(int nextByte) {
if(nextByte == '\n'){
return true;
}
return false;
}
private boolean isSpaceOrTab(int nextByte) {
if(nextByte == ' ' || nextByte == '\t'){
return true;
}
return false;
}
private boolean isWhiteOrLF(int nextByte){
if(nextByte == ' ' || nextByte == '\t' || nextByte == '\r' || nextByte == '\n'){
return true;
}
return false;
}
private boolean isSpace(int nextByte) {
if(nextByte == ' '){
return true;
}
return false;
}
private boolean isCitation(byte nextByte) {
if(nextByte == '\''){
return true;
}
return false;
}
public boolean hasNext() {
return !isEOF();
}
public String readLine() throws EOFException {
StringBuilder buff = new StringBuilder();
appendBytesUntilNextLF(buff);
return buff.toString();
}
public long posOfFirstNonWhiteCharAfterWhiteChar() throws EOFException{
boolean whiteFound = false;
long foundPos = -1;
while(true){
byte next = read();
if(isSpaceOrTab(next)){
whiteFound = true;
}
if(whiteFound && !isSpaceOrTab(next)){
foundPos = mappedBuff.position() - 1;
break;
}
}
return foundPos;
}
public void posOfFirstCharAfterNexusName() {
boolean charFound = false;
boolean whiteFound = false;
/*
while(true){
byte next = read();
if(isCitation(next)){
long endNamePos = findNext((byte)'\'');
return endNamePos +1;
}
if(isSpaceOrTab(nextByte)){
whiteFound = true;
}else{
charFound = true;
}
if(whiteFound && !isSpaceOrTab(next)){
foundPos = mappedBuff.position() - 1;
break;
}
}
return foundPos;
*/
}
public boolean hasLineOnlyOneContinousSpace() throws EOFException {
byte previous = -1;
int spaceCount = 0;
while(true){
byte next = read();
if(isLF(next)){
return spaceCount == 1;
}
if(isSpaceOrTab(next) && !isSpaceOrTab(previous)){
spaceCount ++;
if(spaceCount > 1){
return false;
}
}
previous = next;
}
}
public long posOfNextNewline() throws EOFException {
long foundPos = -1;
while(true){
byte next = read();
if(isLF(next)){
foundPos = mappedBuff.position() - 1;
break;
}
}
return foundPos;
}
public int countSpaceBetween(long seqStartPos, long firstNewlinePos) throws EOFException {
mappedBuff.position(seqStartPos);
int spaceCount = 0;
long len = firstNewlinePos - seqStartPos;
for(int n = 0; n < len; n++){
byte next = read();
if(isSpace(next)){
spaceCount ++;
}
}
return spaceCount;
}
public long posAtNSequenceCharacters(long seqStartPos, int countTarget) throws EOFException {
mappedBuff.position(seqStartPos);
int charCount = 0;
while(charCount < countTarget){
byte next = read();
if(isWhiteOrLF(next) == false){
charCount ++;
}
}
return mappedBuff.position() - 1;
}
public boolean isNextLF() throws EOFException {
byte next = read();
return isReturnOrLF(next);
}
public String readString(long startPos, long endPos) throws IOException{
long length = endPos - startPos;
byte[] nameArray = new byte[(int)length];
mappedBuff.position(startPos);
mappedBuff.read(nameArray);
return new String(nameArray);
}
public long posOfNextNonWhiteChar() throws EOFException {
long foundPos = -1;
while(true){
byte next = read();
if(! isWhiteOrLF(next)){
foundPos = mappedBuff.position() - 1;
break;
}
}
return foundPos;
}
public long skipUntilNextNonWhiteChar() throws EOFException {
return posOfNextNonWhiteChar();
}
public int skipUntilNextNonWhiteCharOnNextLine() throws EOFException {
long foundPos = -1;
int linebreaks = 0;
while(true){
byte next = read();
//logger.info("next" + (char) next);
if(isLF(next)){
linebreaks ++;
}
if(linebreaks > 0){
if(! isWhiteOrLF(next)){
mappedBuff.position(mappedBuff.position() - 1);
return linebreaks;
}
}
}
}
public int skipUntilNextNonWhiteCharInFirstPosAfterNewLine() throws EOFException {
long foundPos = -1;
int linebreaks = 0;
int charCountSinceLF = 0;
while(true){
byte next = read();
charCountSinceLF ++;
if(isLF(next)){
linebreaks ++;
charCountSinceLF = 0;
}
if(charCountSinceLF == 1){
if(linebreaks > 0){
if(! isWhiteOrLF(next)){
mappedBuff.position(mappedBuff.position() - 1);
return linebreaks;
}
}
}
}
}
public String skipUntilLineContains(String string) throws EOFException {
long startPointer = mappedBuff.position();
while(true){
startPointer = mappedBuff.position();
String nextLine = readLine();
if(nextLine.toUpperCase().contains(string.toUpperCase())){
mappedBuff.position(startPointer);
return nextLine;
}
}
}
private boolean isTokenDelimiter(int nextByte){
if(nextByte == ' ' || nextByte == '\t' || nextByte == '\r' || nextByte == '\n' || nextByte == '=' || nextByte == ';'){
return true;
}
return false;
}
private boolean isNexusCommentStart(int nextByte){
return nextByte == '[';
}
private boolean isNexusCommentEnd(int nextByte){
return nextByte == ']';
}
private boolean isNexusNameCitation(int nextByte) {
return nextByte == '\'';
}
public String getCharsUntilNexusCitation() throws EOFException{
StringBuilder buff = new StringBuilder();
while(true){
int nextByte = read();
if(isNexusNameCitation(nextByte)){
return buff.toString();
}
else{
buff.append(nextByte);
}
}
}
public void skipUntilNexusCommentEnd() throws EOFException{
while(true){
int nextByte = read();
if(isNexusCommentEnd(nextByte)){
// logger.info("done skip comment");
return;
}
// logger.info("skip comment");
}
}
public ArrayList<String> readAllNexusTokensUntil(String endToken) throws EOFException{
ArrayList<String> tokens = new ArrayList<String>();
StringBuilder buff = new StringBuilder();
while(true){
int nextByte = read();
if(isNexusCommentStart(nextByte)){
skipUntilNexusCommentEnd();
}
if(isTokenDelimiter(nextByte)){
if(buff.length() > 0){
String token = buff.toString();
tokens.add(token);
if(StringUtils.equalsIgnoreCase(token, endToken)){
return tokens;
}
buff = new StringBuilder();
}
}else{
buff.append((char)nextByte);
}
}
}
public String readNextNexusSeqName() throws EOFException {
StringBuilder buff = new StringBuilder();
while(true){
int nextByte = read();
if(isNexusCommentStart(nextByte)){
skipUntilNexusCommentEnd();
}
else if(isNexusNameCitation(nextByte)){
String name = getCharsUntilNexusCitation();
buff.append(name);
}
else if(isWhiteOrLF(nextByte)){
// don't return until there is a name
if(buff.length() > 0){
return buff.toString();
}
}
else{
buff.append((char)nextByte);
}
}
}
public long posOfNextNonWhiteNexusChar() throws EOFException {
while(true){
int nextByte = read();
if(isNexusCommentStart(nextByte)){
skipUntilNexusCommentEnd();
}
if(isWhiteOrLF(nextByte)){
// skip
}else{
return mappedBuff.position() -1;
}
}
}
public long posOfNextWhitespaceOrLF() throws EOFException {
while(true){
int nextByte = read();
if(isWhiteOrLF(nextByte)){
return mappedBuff.position() - 1;
}
}
}
public long getPosOfNonWhiteNexusCharacter(int skipCount) throws EOFException {
int counter = 0;
while(true){
int nextByte = read();
if(isNexusCommentStart(nextByte)){
skipUntilNexusCommentEnd();
}
else if(isWhiteOrLF(nextByte)){
// skip
}else{
counter++;
// logger.info((char)nextByte);
if(counter == skipCount){
// logger.info("lastseqchar=" + (char)nextByte);
return mappedBuff.position() - 1;
}
}
}
}
public byte[] getBytesBetween(long seqStartPointer, long seqEndPointer) {
long len = seqEndPointer - seqStartPointer + 1; // +1 because inclusive
byte[] bytes = new byte[(int)len];
mappedBuff.read(bytes, 0, bytes.length);
return bytes;
}
public void readUntilNextNonBlankLine() {
// TODO Auto-generated method stub
}
public long position() {
return mappedBuff.position();
}
}