<file_sep>/*
  This file is a part of DSRC software distributed under GNU GPL 2 licence.
  The homepage of the DSRC project is http://sun.aei.polsl.pl/dsrc
  
  Authors: <NAME> and <NAME>
  
  Version: 2.00
*/

/*
  Modified by <NAME>
  <EMAIL>
*/

#ifndef BUFFER_H
#define BUFFER_H

#include "Globals.h"

#include <algorithm>

#include "utils.h"


namespace mash
{

namespace core
{

#define USE_64BIT_MEMORY 1

class Buffer
{
public:
	Buffer(uint64 size_)
	{
		ASSERT(size_ != 0);

#if (USE_64BIT_MEMORY)
		uint64 size64 = size_ / 8;
		if (size64 * 8 < size_)
			size64 += 1;
		buffer = new uint64[size64];
#else
		buffer = new byte[size_];
#endif
		size = size_;
	}

	~Buffer()
	{
		delete buffer;
	}

	uint64 Size() const
	{
		return size;
	}

	byte* Pointer() const
	{
		return (byte*)buffer;
	}

#if (USE_64BIT_MEMORY)
	uint64* Pointer64() const
	{
		return buffer;
	}
#endif

	void Extend(uint64 size_, bool copy_ = false)
	{		
#if (USE_64BIT_MEMORY)
		uint64 size64 = size / 8;
		if (size64 * 8 < size)
			size64 += 1;

		uint64 newSize64 = size_ / 8;
		if (newSize64 * 8 < size_)
			newSize64 += 1;

		if (size > size_)
			return;

		if (size64 == newSize64)
		{
			size = size_;
			return;
		}

		uint64* p = new uint64[newSize64];

		if (copy_)
			std::copy(buffer, buffer + size64, p);
#else
		if (size > size_)
			return;

		byte* p = new byte[size_];

		if (copy_)
			std::copy(buffer, buffer + size, p);

#endif
		delete[] buffer;

		buffer = p;
		size = size_;
	}

	void Swap(Buffer& b)
	{
		TSwap(b.buffer, buffer);
		TSwap(b.size, size);
	}

private:
	Buffer(const Buffer& ) {}
	Buffer& operator= (const Buffer& )
	{ return *this; }

#if (USE_64BIT_MEMORY)
	uint64* buffer;
#else
	byte* buffer;
#endif
	uint64 size;
};


struct DataChunk
{
	static const uint64 DefaultBufferSize = 1 << 20;		// 1 << 22

	Buffer data;
	uint64 size;
	DataChunk *next = NULL;//[haoz:]added for all seqchunk in one part

	DataChunk(const uint64 bufferSize_ = DefaultBufferSize)
		:	data(bufferSize_)
		,	size(0)
	{}

	void Reset()
	{
		size = 0;
		next = NULL;
	}
};

struct DataPairChunk
{
	DataChunk* left_part;
	DataChunk* right_part;
};

} // namespace core

} // namespace mash


#endif // BUFFER_H
<file_sep>/*
  This file is a part of DSRC software distributed under GNU GPL 2 licence.
  The homepage of the DSRC project is http://sun.aei.polsl.pl/dsrc
  
  Authors: <NAME> and <NAME>
  
  Version: 2.00
*/

#ifndef H_DATA_POOL
#define H_DATA_POOL

#include "Globals.h"

#include <vector>
#include <iostream>
#include <algorithm>

#ifdef USE_BOOST_THREAD
#include <boost/thread.hpp>
namespace th = boost;
#else
#include <thread>
#include <mutex>
#include <condition_variable>

namespace th = std;
#endif

namespace mash
{

namespace core
{

template <class _TDataType>
class TDataPool
{
	typedef _TDataType DataType;
	typedef std::vector<DataType*> part_pool;

	const uint32 maxPartNum;
	const uint32 bufferPartSize;

	part_pool availablePartsPool;
	part_pool allocatedPartsPool;

	th::mutex mutex;
	th::condition_variable partsAvailableCondition;

public:
	volatile uint32 partNum;
	static const uint32 DefaultMaxPartNum = 32;
	static const uint32 DefaultBufferPartSize = 1 << 22;

	TDataPool(uint32 maxPartNum_ = DefaultMaxPartNum, uint32 bufferPartSize_ = DefaultBufferPartSize)
		:	maxPartNum(maxPartNum_)
		,	bufferPartSize(bufferPartSize_)
		,	partNum(0)
	{
		availablePartsPool.resize(maxPartNum);
		allocatedPartsPool.reserve(maxPartNum);
	}

	~TDataPool()
	{
		for (typename part_pool::iterator i = allocatedPartsPool.begin(); i != allocatedPartsPool.end(); ++i)
		{
			ASSERT(*i != NULL);
			delete *i;
		}
	}

	void Acquire(DataType* &part_)
	{
		th::unique_lock<th::mutex> lock(mutex);

		while (partNum >= maxPartNum)
			partsAvailableCondition.wait(lock);

		ASSERT(availablePartsPool.size() > 0);

		DataType*& pp = availablePartsPool.back();
		availablePartsPool.pop_back();
		if (pp == NULL)
		{
			pp = new DataType(bufferPartSize);
			allocatedPartsPool.push_back(pp);
		}
		else
		{
			pp->Reset();
		}

		partNum++;
		part_ = pp;
	}

	void Release(const DataType* part_)
	{
		th::lock_guard<th::mutex> lock(mutex);

		ASSERT(part_ != NULL);
		ASSERT(partNum != 0 && partNum <= maxPartNum);
		ASSERT(std::find(allocatedPartsPool.begin(), allocatedPartsPool.end(), part_) != allocatedPartsPool.end());
		availablePartsPool.push_back((DataType*)part_);
		partNum--;

		partsAvailableCondition.notify_one();
	}
};

} // namespace core

} // namespace mash


#endif // H_DATA_POOL
<file_sep>/*
  This file is a part of DSRC software distributed under GNU GPL 2 licence.
  The homepage of the DSRC project is http://sun.aei.polsl.pl/dsrc
  
  Authors: <NAME> and <NAME>
  
  Version: 2.00
*/
  
#include <cstdio>
#include <vector>
#include <map>
#include <cstdio>

//#include "../Sketch.h"
#include "Reference.h"
#include "FastxIO.h"
#include "Buffer.h"
#include "FastxStream.h" 
//#include "read.h"
//#include "Sequence.h"

using namespace std;

namespace mash
{

namespace fa
{
/*
FastaChunk* FastaReader::readNextChunk(){
	FastaDataChunk* part = NULL;
	recordsPool.Acquire(part);
	FastaChunk *dataPart = new FastaChunk;
	dataPart->chunk = part;
	if(fileReader.ReadNextChunk(dataPart, this->seqInfos))
	{
		return dataPart;
	}
	else
	{
		recordsPool.Release(part);
		return NULL;
	}
}
*/

//int chunkFormat(FastaDataChunk* &chunk, std::vector<Sequence*> &data, bool mHasQuality){
//	//format a whole chunk and return number of reads
//	int seq_count = 0;
//	int line_count = 0;
//	int pos_ = 0;
//
//	while(true){
//		//TODO rewrite to deal with part sequence
//		//string name = getLine(chunk, pos_);
//		//if(name.empty()) break;//dsrc guarantees that read are completed!
//		//std::cout << name << std::endl;
//
//		//string sequence = getSequence(chunk, pos_);
//		//std::cout << sequence << std::endl;
//
//		//data.push_back(new Read(name, sequence));
//		//seq_count++;
//
//	}
//
//	return seq_count;
//}


//FIXME:support enter = \n only
string getSequence(FastaDataChunk * &chunk, uint64 &pos)
{
	int start_pos = pos;
	char * data = (char *)chunk->data.Pointer();
	//cerr << "start pos: " << pos << endl << flush;
	//cerr << "chunk size: " << chunk->size << endl << flush;
	//cerr << "data[pos]: " << (int)data[pos] << endl << flush;
	string res="";

	while(pos < chunk->size - 1 )
	{
		if(data[pos] == '\n'){
			res += string(data+start_pos, pos-start_pos);
			pos++;
			start_pos = pos;
			if(data[pos] == '>')
				return res;		
		}
		else{
			pos++;
		}
	}

	//deal with last char	
	if(pos == chunk->size - 1)
	{
		if(data[pos] == '\n')
			res += string(data+start_pos, pos - start_pos);
		else
			res += string(data+start_pos, pos - start_pos + 1);

		return res;
	}	

		
	return "";
}

//only support uinx-like '\n'
string getLine(FastaDataChunk * &chunk, uint64 &pos)
{
	int start_pos = pos;
	char* data = (char *)chunk->data.Pointer();

	while(pos < chunk->size){
		if(data[pos] == '\n'){
			pos++;
			return string(data+start_pos, pos-start_pos - 1);
		}
		else{
			pos++;
		}
	}

	return "";
}

int chunkFormat(FastaChunk & fachunk, vector<Reference> & refs)
{
	uint64 pos = 0;
	bool done = false;
	//cerr << "into chunkFormat" << endl;
	while(true){
	
		Reference ref = getNextSeq(fachunk, done, pos);
		if(done) break;
		refs.push_back(ref);
	}

	ASSERT(refs.size() == fachunk.nseqs);

	return refs.size();
	
}

//design to filter out kmer apps
int chunkFormat(FastaChunk & fachunk, vector<Reference> & refs, int kmerSize)
{
	uint64 pos = 0;
	bool done = false;
	//cerr << "into chunkFormat" << endl;
	uint64 short_count = 0; //counter for seqs shorter than kmer
	while(true){
	
		Reference ref = getNextSeq(fachunk, done, pos);
		if(done) break;
		if(ref.seq.length() < kmerSize)
			short_count++;
		else
			refs.push_back(ref);
	}

	ASSERT(refs.size() + short_count == fachunk.nseqs);

	return refs.size();
	
}

Reference getNextSeq(FastaChunk & fachunk, bool & done, uint64 & pos)
{
	Reference ref;
	if(pos >= fachunk.chunk->size - 1){
		done = true;
		return ref;
	}

	char *data = (char *)fachunk.chunk->data.Pointer();	

	//while(data[pos] == '\n') pos++;//jump empty lines

	if(data[pos] != '>')
	{
		ref.seq = getSequence(fachunk.chunk, pos);	
		ref.length = ref.seq.size();
		ref.gid = fachunk.start;
		fachunk.start++;
	}else{
		string line = getLine(fachunk.chunk, pos);
		int str_pos = line.find_first_of(' ');
		ref.name = line.substr(1, str_pos-1);	//remove '>' and ' '
		if(str_pos < line.size()) 
			ref.comment = line.substr(str_pos + 1);
		//cerr << "name: " << ref.name << endl << flush;
		ref.seq = getSequence(fachunk.chunk, pos);	
		//cerr << "seq: " << ref.seq << endl << flush;
		ref.length = ref.seq.size();
		ref.gid = fachunk.start;
		fachunk.start++;
	}

	return ref;
}

} // namesapce fa

namespace fq
{

/*
void FastqReader::readChunk()
{
	FastqDataChunk* part = NULL;

	recordsPool.Acquire(part);
	printf("fastqio: ready to into while\n");

	//while (!errorHandler.IsError() && fileReader.ReadNextChunk(part))
	while(fileReader.ReadNextChunk(part))
	{
		ASSERT(part->size > 0);

		//recordsQueue.Push(numParts, part); //[haoz:] Push:把<numparts, part>组成pair然后放到recordsQueue里面然后notifiy_one
		printf("numParts is %d\n", numParts);
		numParts++;

		recordsPool.Release(part);	
		recordsPool.Acquire(part);
	}

	ASSERT(part->size == 0);
	recordsPool.Release(part);		// the last empty part

	//recordsQueue.SetCompleted();
}

FastqDataChunk* FastqReader::readNextChunk(){
	FastqDataChunk* part = NULL;
	recordsPool.Acquire(part);
	if(fileReader.ReadNextChunk(part))
	{
		return part;
	}
	else
	{
		recordsPool.Release(part);
		return NULL;
	}
}
*/
//FastqDataChunk* FastqReader::readNextPairedChunk(){
//	FastqDataChunk* part = NULL;
//	recordsPool.Acquire(part);
//	if(fileReader.ReadNextPairedChunk(part))
//	{
//		//std::cout <<"read one chunk:   " << std::endl;
//		//std::cerr << (char*)part->data.Pointer() << endl;
//		//std::cerr << "chunk end" << endl;
//		return part;
//	}
//	else
//	{
//		//std::cout <<"read one chunk failed :   " << std::endl;
//		recordsPool.Release(part);
//		return NULL;
//	}
//}
void print_read(neoReference& ref){
	std::cout << std::string((char*)ref.base+ref.pname, ref.lname) << std::endl;
	std::cout << std::string((char*)ref.base+ref.pseq, ref.lseq) << std::endl;
	std::cout << std::string((char*)ref.base+ref.pstrand, ref.lstrand) << std::endl;
	std::cout << std::string((char*)ref.base+ref.pqual, ref.lqual) << std::endl;
}
int chunkFormat(FastqChunk* &fqChunk, std::vector<neoReference> &data, bool mHasQuality = true){
	FastqDataChunk * chunk = fqChunk->chunk;
	uint64_t seq_count = 0;
	uint64_t line_count = 0;
	uint64_t pos_ = 0;
	neoReference ref;
	while(true){
		ref.base = chunk->data.Pointer();
		ref.pname = pos_;
		if(neoGetLine(chunk, pos_, ref.lname)){
			ref.pseq = pos_; 
		} 
		else{ break;}
		neoGetLine(chunk, pos_, ref.lseq); 
		ref.pstrand = pos_; 
		neoGetLine(chunk, pos_, ref.lstrand); 
		ref.pqual = pos_;  
		neoGetLine(chunk, pos_, ref.lqual);
		seq_count++;
		//print_read(ref);
		data.emplace_back(ref);
	}

	return seq_count;
}
/*
int chunkFormat(FastqChunk* &fqChunk, std::vector<Reference> &data, bool mHasQuality = true){
	//format a whole chunk and return number of reads
	FastqDataChunk * chunk = fqChunk->chunk;
	int seq_count = 0;
	int line_count = 0;
	int pos_ = 0;
	Reference ref;

	while(true){
		string name = getLine(chunk, pos_);
		if(name.empty()) break;//dsrc guarantees that read are completed!
		//std::cerr << name << std::endl;

		string sequence = getLine(chunk, pos_);
		//std::cerr<< sequence << std::endl;

		string strand = getLine(chunk, pos_);
		//std::cerr << strand << std::endl;
		ref.name = name;
		ref.seq = sequence;
		ref.strand = strand;

		if(!mHasQuality){
			string quality = string(sequence.length(), 'K');
			//std::cerr << quality << std::endl;
			//data.push_back(new Read(name, sequence, strand, quality));
			//data.emplace_back(Sketch::Reference(name, "", sequence, strand, quality));
			ref.quality = quality;
			data.push_back(ref);
			seq_count++;

		}else{
			string quality = getLine(chunk, pos_);
			//std::cerr << quality << std::endl;
			//data.push_back(new Read(name, sequence, strand, quality));
			//data.emplace_back(Sketch::Reference(name, "", sequence, strand, quality));
			ref.quality = quality;
			data.push_back(ref);
			seq_count++;
		}
	}

	return seq_count;
}
*/
//int pairedChunkFormat(FastqDataChunk* &chunk, std::vector<ReadPair*> &data, bool mHasQuality){
//	//format a whole chunk and return number of reads
//	int seq_count = 0;
//	int pos_ = 0;
//	//处理一开始的两条序列
//	Read* first = getOnePairedRead(chunk,pos_,mHasQuality);
//	Read* second = getOnePairedRead(chunk,pos_,mHasQuality);
//
//
//	if(first->mName.substr(0, first->mName.find(' ')) == second->mName.substr(0, second->mName.find(' ')) ){
//		//cerr << first->mName<<" + " << endl;
//
//		data.push_back(new ReadPair(first,second));
//		seq_count++;
//
//	}else{
//		//std::cout<<"Right"<<std::endl;
//		//cerr << first->mName<<" - "<<endl;
//		Read* third = getOnePairedRead(chunk,pos_,mHasQuality);
//		data.push_back(new ReadPair(second,third));
//		seq_count++;
//	}
//	while(true){
//		Read* t1=getOnePairedRead(chunk,pos_,mHasQuality);
//		if(t1 == NULL){
//			break;
//		}
//		Read* t2 =getOnePairedRead(chunk,pos_,mHasQuality);
//		if(t2 == NULL){
//			//cerr << t1->mName << " with + without -" << endl;
//			break;
//		}
//		data.push_back(new ReadPair(t1,t2));
//		seq_count++;
//	}
//
//	//for(int i =0;i<seq_count;i++){
//	//	cerr << data[i]->mLeft->mName<<endl;
//	//	cerr << data[i]->mLeft->mSeq.mStr<<endl;
//	//	cerr << data[i]->mLeft->mStrand<<endl;
//	//	cerr << data[i]->mLeft->mQuality<<endl;
//	//	cerr << data[i]->mRight->mName<<endl;
//	//	cerr << data[i]->mRight->mSeq.mStr<<endl;
//	//	cerr << data[i]->mRight->mStrand<<endl;
//	//	cerr << data[i]->mRight->mQuality<<endl;
//	//	
//	//}
//	//cerr << data[seq_count-1]->mLeft->mName<<endl;
//		
//	return seq_count;
//}
//Read* getOnePairedRead(FastqDataChunk* &chunk,int &pos_, bool mHasQuality){
//	while(true){
//		string name = getLine(chunk, pos_);
//		if(name.empty()) return NULL;
//		//std::cerr << name << std::endl;
//		string sequence = getLine(chunk, pos_);
//
//		string strand = getLine(chunk, pos_);
//		if(!mHasQuality){
//			string quality = string(sequence.length(), 'K');
//			return new Read(name, sequence, strand, quality);
//	
//		}else{
//			string quality = getLine(chunk, pos_);
//			//std::cerr << quality << std::endl;
//			return new Read(name, sequence, strand, quality);
//		}
//	}
//}


string getLine(FastqDataChunk* &chunk, int &pos){
	int start_pos = pos;
	char* data = (char *)chunk->data.Pointer();

	while(pos <= (chunk->size + 1)){
		if(data[pos] == '\n' || data[pos] == '\r' || pos == (chunk->size + 1)){
			//find a line
			pos++;
			return string(data+start_pos, pos-start_pos - 1);
		}
		else{
			pos++;
		}
	}
	return "";
}
int neoGetLine(FastqDataChunk* &chunk, uint64_t &pos, uint64_t &len){
	int start_pos = pos;
	const char* data = (char *)chunk->data.Pointer();
	const uint64_t chunk_size = chunk->size + 1;
	/*
	while (pos <= chunk_size && data[pos] != '\n'){
		pos++;
	}
	len = pos - start_pos - 1;
	return len;
	*/
	//while(pos <= (chunk->size + 1)){
	while(pos <= chunk_size){
		//if(data[pos] == '\n' || data[pos] == '\r' || pos == (chunk->size + 1)){
		if(data[pos] == '\n'){
			//find a line
			pos++;
			//return string(data+start_pos, pos-start_pos - 1);
			//pos = start_pos; 
			len = pos - start_pos - 1;
			return len;
		}
		else{
			pos++;
		}
	}
	return 0;
}
/*
int neoGetLine(FastqDataChunk* &chunk, char* &pos, uint64_t &len){
	char* start_pos  = pos;
	char* data = (char *)chunk->data.Pointer();
	char* chunkend = data + chunk->size + 1; //the end address of this chunk(memory address)
	while(pos <= chunkend){
		if(*pos == '\n' || *pos == '\r' || pos == chunkend){
			//find a line
			pos++;
			len = (pos - start_pos)/sizeof(char); //-------if need the division??-------//
			//return string(data+start_pos, pos-start_pos - 1);
			return len;
		}
		else{
			pos++;
		}
	}
	return 0;
}
*/
} // namesapce fq

} // namespace mash
<file_sep>/*
  This file is a part of DSRC software distributed under GNU GPL 2 licence.
  The homepage of the DSRC project is http://sun.aei.polsl.pl/dsrc
  
  Authors: <NAME> and <NAME>
  
  Version: 2.00

  last modified by <NAME> 2020/5/18
*/
 
#include "FastxStream.h"
//#include "../Sketch.h"
#include <iostream>
#include <string>
#include "Reference.h"

namespace mash
{

namespace fa
{

FastaChunk* FastaFileReader::readNextChunk(){
	FastaDataChunk* part = NULL;
	recordsPool.Acquire(part);
	FastaChunk *dataPart = new FastaChunk;
	dataPart->chunk = part;
	if(ReadNextChunk(dataPart, this->seqInfos))
	{
		return dataPart;
	}
	else
	{
		std::cout << "read over!" << std::endl;
		recordsPool.Release(part);
		return NULL;
	}
}
/*
Description:
	this function make sure one FastaChunk(dataPart) contains at least
	one whole sequence, because 
*/
FastaChunk* FastaFileReader::readNextChunkList(){
	FastaDataChunk* part = NULL;
	recordsPool.Acquire(part);
	FastaChunk *dataPart = new FastaChunk;
	dataPart->chunk = part;
	FastaDataChunk* currnet = NULL;
	bool continue_read = false;
	if(ReadNextFaChunk(dataPart->chunk, this->seqInfos, continue_read))
	{
		FastaDataChunk* current = part;
		while(continue_read){
			FastaDataChunk *append = NULL;
			recordsPool.Acquire(append);
			if(ReadNextFaChunk(append, this->seqInfos, continue_read)){
				current->next = append;
				currnet = append;
			}else{
				recordsPool.Release(append);
				break;
			}
		}
		return dataPart;
	}
	else
	{
		recordsPool.Release(part);
		return NULL;
	}
}

bool FastaFileReader::ReadNextChunk(FastaChunk* dataChunk_, SeqInfos& seqInfos)
{
	//std::cout << "==================Next Chunk =========================" << std::endl;
	FastaDataChunk *chunk_ = dataChunk_->chunk;
	if (Eof())
	{
		chunk_->size = 0;
		return false;
	}

	// flush the data from previous incomplete chunk
	uchar* data = chunk_->data.Pointer();
	const uint64 cbufSize = chunk_->data.Size();
	chunk_->size = 0;
	int64 toRead = cbufSize - bufferSize;// buffersize: size left from last chunk
	
	if (bufferSize > 0)
	{
		std::copy(swapBuffer.Pointer(), swapBuffer.Pointer() + bufferSize, data);
		chunk_->size = bufferSize;
		bufferSize = 0;
	}

	// read the next chunk
	int64 r = this->Read(data + chunk_->size, toRead);
	//std::cout << "r is :" << r << std::endl;
	//std::cout << "toRead: " << toRead << std::endl;
	
	if (r > 0)
	{
		if (r == toRead)	// somewhere before end
		{
		    //uint64 chunkEnd = cbufSize - SwapBufferSize; // Swapbuffersize: 1 << 13
			////std::cout << "chunkend  cbufsize Swapbuffersize: " << chunkEnd <<" "<< cbufSize << " " << SwapBufferSize << std::endl;
			//chunkEnd = GetNextRecordPos(data, chunkEnd, cbufSize);
			//chunk_->size = chunkEnd - 1; //remove \n
			//if (usesCrlf)
			//	chunk_->size -= 1;

			//std::copy(data + chunkEnd, data + cbufSize, swapBuffer.Pointer());
			//bufferSize = cbufSize - chunkEnd;

			//dealing with halo region
			uint64 chunkEnd = FindCutPos(dataChunk_, data, cbufSize, mHalo, seqInfos);
			chunk_->size = chunkEnd;// - 1; //1 char back from last '>'

			//debug only
			//std::string content((char*)data, chunk_->size);
			//std::cout << "chunkEnd data: " << (char)data[chunkEnd-1] << std::endl;
			//std::cout << "chunkEnd: " << (uint64)chunkEnd << std::endl;
			//std::cout << "chunk_->size: " << chunk_->size << std::endl;
			//std::cout << "content_ori: " << data << std::endl;
			//std::cout << "content    : " << content << std::endl;
			//end debug
			
			if (usesCrlf)
				chunk_->size -= 1;
			//copy tail to swapBuffer
			//if(data[chunkEnd] == '\n') chunkEnd++;
			//TODO: dealing with halo region
			//get rid of '\n' in halo region FIXME: Crlf not supported
			int haloCount = 0;
			uint64 tmpPtr = chunkEnd - 1;
			if(mHalo > 0){
				while(true){
					if(data[tmpPtr] != '\n')
					{
						haloCount++;
						//std::cerr << (char)data[tmpPtr] << std::endl;
						if(haloCount == mHalo) break;
					}
					tmpPtr--;
				}
				//std::cerr << "haloCount: " << haloCount << std::endl;
			}else{
				tmpPtr = chunkEnd; //nocopy	
			}
			//std::copy(data + chunkEnd - mHalo, data + cbufSize, swapBuffer.Pointer());
			std::copy(data + tmpPtr, data + cbufSize, swapBuffer.Pointer());
			//bufferSize = cbufSize - chunkEnd + mHalo;
			bufferSize = cbufSize - tmpPtr;

		}
		else				// at the end of file
		{
			chunk_->size += r - 1;	// skip the last EOF symbol
			if (usesCrlf)
				chunk_->size -= 1;

			//only for get seqsinfo
			uint64 chunkEnd = FindCutPos(dataChunk_, data, chunk_->size, mHalo, seqInfos);
			//debug only
			//std::string content((char*)data, chunk_->size);
			//std::cout << "tail content ori: " << data << std::endl;
			//std::cout << "tail content    : " << content << std::endl;
			//end debug

			eof = true;
		}
	}
	else
	{
		eof = true;
	}

	return true;
}

uint64 FastaFileReader::FindCutPos(FastaChunk* dataChunk_, uchar* data_, const uint64 size_, const uint64 halo_, SeqInfos& seqInfos)
{
	int count = 0;
	uint64 pos_ = 0;
	uint64 cut_ = 0; //cut_ point to next '>'
	uint64 lastSeq_ = 0; //-> the start of last sequences content
	uint64 lastName_ = 0; //-> the last '>'
	OneSeqInfo seqInfo;
	/*
	[haoz:] dataChunk_ -> start和dataChunk_ -> end 是表示当前这个chunk的开始部分的序列的index和
			最终部分序列的index
	*/
	if(data_[0] == '>') //start with '>'
	{
		dataChunk_->start = this->totalSeqs;	
		while(pos_ < size_){
			if(data_[pos_] == '>'){
				lastName_ = pos_;
				if(FindEol(data_, pos_, size_)) //find name
				{
					++pos_;
					lastSeq_ = pos_;

					seqInfo.gid = this->totalSeqs;
					seqInfos.push_back(seqInfo);

					this->totalSeqs++;
				}else{
					cut_ = pos_; //find a cut: incomplete name
					//std::cerr << "cut char: " << (char)data_[cut_] << std::endl;
					break;
				}
			}else{
				++pos_;
			}
	
		}

	}else{ //start with {ACGT}
		dataChunk_->start = this->totalSeqs - 1;	
		while(pos_ < size_){
			if(data_[pos_] == '>'){
				lastName_ = pos_;
				if(FindEol(data_, pos_, size_)) //find name
				{
					++pos_;
					lastSeq_ = pos_;
					seqInfo.gid = this->totalSeqs;
					seqInfos.push_back(seqInfo);
					this->totalSeqs++;
				}else{
					cut_ = pos_; //find a cut -> '>'
					//std::cout << "cut char: " << (char)data_[cut_] << std::endl;
					break;
				}
			}else{
				++pos_;
			}
	
		}	
	}

	//no tail cut
	//make sure that cbufSize > name_len + halo
	if(cut_ == 0){
		uint64 lastSeqLen_ = size_ - lastSeq_;	
		if(lastSeqLen_ < halo_){
			cut_ = lastName_;	
			this->totalSeqs--;
		}
	}
	
	dataChunk_->nseqs = this->totalSeqs - dataChunk_->start;
	dataChunk_->end = this->totalSeqs - 1;

	//if(cut_ != 0) std::cout << "cut: " << cut_ << std::endl;

	return cut_ ? cut_ : size_;	
}
bool find_next_seq_start(uchar* data, uint64 size, uint64 &pos_){
	if(pos_ == size - 1) return false;
	do{
		pos_++;
	}while(pos_ < size && data[pos_] != '>');

	return data[pos_] == '>' ? true : false;
}

//bool FastaFileReader::ReadNextFaChunk(FastaChunk* dataChunk_, SeqInfos& seqInfos, bool &continue_read){
bool FastaFileReader::ReadNextFaChunk(FastaDataChunk* chunk_, SeqInfos& seqInfos, bool &continue_read){
	if (Eof())
	{
		chunk_->size = 0;
		return false;
	}

	// flush the data from previous incomplete chunk
	uchar* data = chunk_->data.Pointer();
	const uint64 cbufSize = chunk_->data.Size();
	chunk_->size = 0;
	int64 toRead = cbufSize - bufferSize;// buffersize: size left from last chunk
	
	if (bufferSize > 0)
	{
		std::copy(swapBuffer.Pointer(), swapBuffer.Pointer() + bufferSize, data);
		chunk_->size = bufferSize;
		bufferSize = 0;
	}

	// read the next chunk
	int64 r = this->Read(data + chunk_->size, toRead);
	//std::cout << "r is :" << r << std::endl;
	//std::cout << "toRead: " << toRead << std::endl;
	
	if (r > 0)
	{
		if (r == toRead)	// somewhere before end
		{
			if(data[0] == '>'){
				uint64 chunkEnd = 0, pos_ = 0;
				pos_ = chunk_->size;
				while(find_next_seq_start(data, cbufSize, pos_)){
					chunkEnd = pos_;
				}
				if(chunkEnd == 0){ //means this chunk is a big one, one chunk can not contain all
					continue_read = true;
					chunkEnd = cbufSize;
				}else{
					continue_read = false;
				}
				chunk_->size = chunkEnd - 1;
				if (usesCrlf)
					chunk_->size -= 1;
				std::copy(data + chunkEnd, data + cbufSize, swapBuffer.Pointer());
				bufferSize = cbufSize - chunkEnd;
			}else{ // means this is a continue chunk for last sequence 
				uint64 chunkEnd = 0, pos_ = 0;
				pos_ = chunk_->size;
				if(find_next_seq_start(data, cbufSize, pos_)){
					chunkEnd = pos_;
				}
				if(chunkEnd == 0){ //means this chunk is a big one, one chunk can not contain all
					continue_read = true;
					chunkEnd = cbufSize;
				}else{
					continue_read = false;
				}
				chunk_->size = chunkEnd - 1;
				if (usesCrlf)
					chunk_->size -= 1;
				std::copy(data + chunkEnd, data + cbufSize, swapBuffer.Pointer());
				bufferSize = cbufSize - chunkEnd;
			}
		}else{ // at the end of file
			chunk_ -> size += r - 1; //skip the last eof symbol
			if(usesCrlf)
				chunk_->size -= 1;
			eof = true;
		}
	}
	else
	{
		eof = true;
	}

	return true;
}

} // namespace fa

namespace fq
{

int64 count_line(uchar* contenx, int64 read_bytes){
	int64 count_n = 0;
	for(int i = 0; i < read_bytes; ++i){
		//printf("%c",contenx[i]);
		if(contenx[i] == '\n') count_n++;
	}
	return count_n;
}


void FastqFileReader::readChunk()
{
	FastqDataChunk* part = NULL;

	recordsPool.Acquire(part);
	printf("fastqio: ready to into while\n");

	//while (!errorHandler.IsError() && fileReader.ReadNextChunk(part))
	while(ReadNextChunk(part))
	{
		ASSERT(part->size > 0);

		//recordsQueue.Push(numParts, part); //[haoz:] Push:把<numparts, part>组成pair然后放到recordsQueue里面然后notifiy_one
		printf("numParts is %d\n", numParts);
		numParts++;

		recordsPool.Release(part);	
		recordsPool.Acquire(part);
	}

	ASSERT(part->size == 0);
	recordsPool.Release(part);		// the last empty part

	//recordsQueue.SetCompleted();
}
FastqDataChunk* FastqFileReader::readNextChunk(){
	FastqDataChunk* part = NULL;
	recordsPool.Acquire(part);
	if(ReadNextChunk(part))
	{
		return part;
	}
	else
	{
		recordsPool.Release(part);
		return NULL;
	}
}

FastqDataPairChunk* FastqFileReader::readNextPairChunk(){
	FastqDataPairChunk* pair = new FastqDataPairChunk;

	FastqDataChunk *leftPart = NULL;
	recordsPool.Acquire(leftPart); //song: all in one datapool

	FastqDataChunk *rightPart = NULL;
	recordsPool.Acquire(rightPart);

	int64 left_line_count = 0;
	int64 right_line_count = 0;
	int64 chunkEnd = 0;
	int64 chunkEnd_right = 0;

	//---------read left chunk------------
	if(eof){
		leftPart->size = 0;
		rightPart->size = 0;
		//return false;
		recordsPool.Release(leftPart);
		recordsPool.Release(rightPart);
		return NULL; 
	}

	//flush the data from previous incomplete chunk
	uchar* data = leftPart->data.Pointer();
	const uint64 cbufSize = leftPart->data.Size();
	leftPart -> size = 0;
	int64 toRead;
	toRead = cbufSize - bufferSize;
	if(bufferSize > 0){
		std::copy(swapBuffer.Pointer(), swapBuffer.Pointer()+bufferSize, data);
		leftPart->size = bufferSize;
		bufferSize = 0;
	}
	int64 r;
	r = Read(data + leftPart->size, toRead);
	if(r > 0){
		if(r == toRead){
			chunkEnd = cbufSize - (1<<13);//SwapBufferSize; // SwapBuffersize defined in FastqStream.h as constant value : 1<<13;
			chunkEnd = GetNextRecordPos(data, chunkEnd, cbufSize);
			//leftPart->size = chunkEnd - 1;
			//if(usesCrlf)
			//	leftPart->size -= 1;

			//std::copy(data + chunkEnd, data + cbufSize, swapBuffer_left.Pointer());
			//bufferSize_left = cbufSize - chunkEnd;
		}else{
			//chunkEnd = r;
			leftPart->size += r - 1;
			if(usesCrlf)
				leftPart->size -= 1;
			eof = true;
		}
	}else{
		eof = true;
		//fastqPool_left -> Release(leftPart);
		//fastqPool_right->Release(rightPart);
		return NULL;
	}
//------read left chunk end------//

//-----------------read right chunk---------------------//	
	uchar* data_right = rightPart->data.Pointer();
	const uint64 cbufSize_right = rightPart->data.Size();
	rightPart -> size = 0;
	toRead = cbufSize_right - bufferSize2;
	if(bufferSize2 > 0){
		std::copy(swapBuffer2.Pointer(), swapBuffer2.Pointer()+bufferSize2 , data_right);
		rightPart->size = bufferSize2;
		bufferSize2 = 0;
	}
	r = Read2(data_right + rightPart->size, toRead);
	if(r > 0){
		if(r == toRead){
			chunkEnd_right = cbufSize_right - (1<<13); //SwapBufferSize; // SwapBuffersize defined in FastqStream.h as constant value : 1<<13;
			chunkEnd_right = GetNextRecordPos(data_right, chunkEnd_right, cbufSize_right);
			//leftPart->size = chunkEnd - 1;
			//if(usesCrlf)
			//	leftPart->size -= 1;

			//std::copy(data + chunkEnd, data + cbufSize, swapBuffer_left.Pointer());
			//bufferSize_left = cbufSize - chunkEnd;
		}else{
			//chunkEnd_right += r;
			rightPart->size += r - 1;
			if(usesCrlf)
				rightPart->size -= 1;
			eof = true;
		}
	}else{
		eof = true;
		return NULL;
	}
//--------------read right chunk end---------------------//

	if(!eof){
	    //std::cout << "chunkEnd chunkEnd_right: " << chunkEnd <<" "<< chunkEnd_right << std::endl;
	    left_line_count = count_line(data, chunkEnd);
	    right_line_count = count_line(data_right, chunkEnd_right);
	    //int64 difference = right_line_count - left_line_count;
		int64 difference = left_line_count - right_line_count;
	    //if((r != toRead) && (difference != 0)){
	    //	cerr << "read error! inconsistent end!!";
	    //	exit(0);
	    //}
	    //std::cout<<"left right difference: " << left_line_count <<" "<< right_line_count <<" "<< difference << std::endl;
	    if(difference>0){
	    	//move rightPart difference lines before
			//std::cout << "difference > 0 "<<left_line_count <<" " <<right_line_count << " " << difference <<std::endl;
			std::cout << "start: " << chunkEnd_right << std::endl;
	    	//while(true){
			while(chunkEnd_right < cbufSize){
	    		if(data_right[chunkEnd_right] == '\n'){
	    			difference--;
	    			if(difference == 0){
	    				chunkEnd_right++;
	    				break;
					}
	    		}
	    		chunkEnd_right++;
	    	}
			std::cout << "end: " << chunkEnd_right << std::endl;
	    			
	    }else if(difference < 0){
	    	//move leftPart difference lines before
			//std::cout << "difference < 0 "  <<left_line_count <<" " <<right_line_count << " " << difference << std::endl;
	    	//while(true){
	    	while(chunkEnd < cbufSize){
	    		if(data[chunkEnd] == '\n'){
	    			difference++;
	    			if(difference == 0){
	    				chunkEnd++;
	    				break;
					}
	    		}
	    		chunkEnd++;
	    	}
	    }

	    leftPart->size = chunkEnd - 1;
	    if(usesCrlf)
	    	leftPart->size -= 1;

	    std::copy(data + chunkEnd, data + cbufSize, swapBuffer.Pointer());
	    bufferSize = cbufSize - chunkEnd;

	    rightPart->size = chunkEnd_right - 1;
	    if(usesCrlf)
	    	rightPart->size -= 1;
	    std::copy(data_right + chunkEnd_right, data_right + cbufSize_right, swapBuffer2.Pointer());
	    bufferSize2 = cbufSize_right - chunkEnd_right;
	}	
	pair->left_part = leftPart;
	pair->right_part = rightPart;
	return pair;	
}


//bool IFastqStreamReader::ReadNextChunk(FastqDataChunk* chunk_)
bool FastqFileReader::ReadNextChunk(FastqDataChunk* chunk_)
{
	if (Eof())
	{
		chunk_->size = 0;
		return false;
	}

	// flush the data from previous incomplete chunk
	uchar* data = chunk_->data.Pointer();
	const uint64 cbufSize = chunk_->data.Size();
	chunk_->size = 0;
	int64 toRead = cbufSize - bufferSize;
	//---------------------------------
	if (bufferSize > 0)
	{
		std::copy(swapBuffer.Pointer(), swapBuffer.Pointer() + bufferSize, data);
		chunk_->size = bufferSize;
		bufferSize = 0;
	}

	// read the next chunk
	int64 r = Read(data + chunk_->size, toRead);
	//std::cout << "r is :" << r << std::endl;
	
	if (r > 0)
	{
		if (r == toRead)	// somewhere before end
		{
		    uint64 chunkEnd = cbufSize - SwapBufferSize; // Swapbuffersize: 1 << 13
			//std::cout << "chunkend  cbufsize Swapbuffersize: " << chunkEnd <<" "<< cbufSize << " " << SwapBufferSize << std::endl;
			chunkEnd = GetNextRecordPos(data, chunkEnd, cbufSize);
			chunk_->size = chunkEnd - 1;
			if (usesCrlf)
				chunk_->size -= 1;

			std::copy(data + chunkEnd, data + cbufSize, swapBuffer.Pointer());
			bufferSize = cbufSize - chunkEnd;
		}
		else				// at the end of file
		{
			chunk_->size += r - 1;	// skip the last EOF symbol
			if (usesCrlf)
				chunk_->size -= 1;

			eof = true;
		}
	}
	else
	{
		eof = true;
	}

	return true;
}
//bool FastqFileReader::ReadNextPairedChunk(FastqDataChunk* chunk_)
//{	//std::cout<<"ReadNextPairedChunk: enter" <<std::endl;
//	if (Eof())
//	{
//		chunk_->size = 0;
//		return false;
//	}
//
//	// flush the data from previous incomplete chunk
//	uchar* data = chunk_->data.Pointer();
//	const uint64 cbufSize = chunk_->data.Size();
//	chunk_->size = 0;
//	int64 toRead = cbufSize - bufferSize;
//	//---------------------------------
//	if (bufferSize > 0)
//	{
//		std::copy(swapBuffer.Pointer(), swapBuffer.Pointer() + bufferSize, data);
//		chunk_->size = bufferSize;
//		bufferSize = 0;
//	}
//
//	// read the next chunk
//	int64 r = Read(data + chunk_->size, toRead);
//	//std::cout << "r is :" << r << std::endl;
//	
//	if (r > 0)
//	{
//		if (r == toRead)	// somewhere before end
//		{
//		    //uint64 chunkEnd = cbufSize - SwapBufferSize; // Swapbuffersize: 1 << 13
//			//std::cout << "chunkend  : " << cbufSize-1 <<std::endl;
//			lastOneReadPos = GetPreviousRecordPos(data, cbufSize-1,cbufSize);
//			//std::cout << "one：" << lastOneReadPos<<std::endl;
//			lastTwoReadPos = GetPreviousRecordPos(data, lastOneReadPos-1,cbufSize);
//			//std::cout << "two :" << lastTwoReadPos<<std::endl;
//			chunk_->size = lastOneReadPos - 1;
//			if (usesCrlf) // TODO windows先不管
//				chunk_->size -= 1;
//
//			std::copy(data + lastTwoReadPos, data + cbufSize, swapBuffer.Pointer());
//			bufferSize = cbufSize - lastTwoReadPos;
//		}
//		else				// at the end of file
//		{
//			chunk_->size += r - 1;	// skip the last EOF symbol
//			if (usesCrlf)
//				chunk_->size -= 1;
//
//			eof = true;
//		}
//	}
//	else
//	{
//		eof = true;
//	}
//	//std::cout<<"ReadNextPairedChunk: success@!!!!!!!" <<std::endl;
//	return true;
//}
//
//需要向前找到倒数第2条read的开头，不仅仅是@号这么简单
uint64 FastqFileReader::GetPreviousRecordPos(uchar* data_, uint64 pos_,const uint64 size_)
{	int offset =2;

	SkipToSol(data_,pos_,size_);
	if(usesCrlf){
		offset=3;
	}
	while(data_[pos_+offset] !='@'){ //+2
		//std::cout<<"pos_"<<pos_<<std::endl;
		SkipToSol(data_,pos_,size_);
	}
	//标记一下，看是否是质量分
	uint64 pos0=pos_+offset;
	SkipToSol(data_,pos_,size_);
	if(data_[pos_+offset]== '+'){
		//说明上一个@号是质量分
		SkipToSol(data_,pos_,size_);
		SkipToSol(data_,pos_,size_);
		//此时应该是name
		if(data_[pos_+offset]!='@'){
			std::cout << "core dump is " << data_[pos_+offset] << std::endl;
			return pos_+offset;
		}else{
			return pos_+offset;
		}
	}
	else{
		return pos0;
	}
}




//uint64 IFastqStreamReader::GetNextRecordPos(uchar* data_, uint64 pos_, const uint64 size_)
//chunkEnd = GetNextRecordPos(data, chunkEnd, cbufSize);
uint64 FastqFileReader::GetNextRecordPos(uchar* data_, uint64 pos_, const uint64 size_)
{
	SkipToEol(data_, pos_, size_);
	++pos_;

	// find beginning of the next record
	while (data_[pos_] != '@')
	{
		SkipToEol(data_, pos_, size_);
		++pos_;
	}
	uint64 pos0 = pos_;
		
	SkipToEol(data_, pos_, size_);
	++pos_;

	if (data_[pos_] == '@')			// previous one was a quality field
		return pos_;
//-----[haoz:] is the following code necessary??-------------//	
	SkipToEol(data_, pos_, size_);
	++pos_;
	if(data_[pos_] != '+')
		std::cout << "core dump is pos: " << pos_ << " char: " << data_[pos_] << std::endl;	
	ASSERT(data_[pos_] == '+');	// pos0 was the start of tag
	return pos0;
}

} // namespace fq

} // namespace mash

<file_sep>cmake_minimum_required(VERSION 3.0)

project(RabbitIO-Ktrim)
#openmp
find_package(OpenMP REQUIRED)
if(OPENMP_FOUND)
message("OPENMP FOUND")
set(CMAKE_CXX_COMPILER "/usr/bin/g++")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERB")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
set(EXECUTABLE_OUTPUT_PATH .)
endif()
#link

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "-O3 -g -ffast-math ${CMAKE_CXX_FLAGS}")

add_subdirectory(src/io)
#message(${SOURCE_LIST})
#include_directories(./src)

add_executable (${PROJECT_NAME} src/main.cpp)
#add_executable (RabbitIO ${SOURCE_LIST})

target_link_libraries(${PROJECT_NAME} z)
target_link_libraries(${PROJECT_NAME} io_lib)
<file_sep>/*
  This file is a part of DSRC software distributed under GNU GPL 2 licence.
  The homepage of the DSRC project is http://sun.aei.polsl.pl/dsrc
  
  Authors: <NAME> and <NAME>
  
  Version: 2.00
*/

#ifndef H_FASTXREADER
#define H_FASTXREADER

#include <vector>
#include <string>

#include "Globals.h"
#include "Common.h"
#include "DataQueue.h"
#include "DataPool.h"
#include "FastxStream.h"
#include "FastxChunk.h"
//#include "Sequence.h"
//#include "../Sketch.h"
#include "Reference.h"

namespace mash
{

namespace fa
{

/*
class FastaReader
{
public:
    FastaReader(FastaFileReader& reader_, FastaDataPool& pool_)
	    :   recordsPool(pool_)
		,	fileReader(reader_)
		,	numParts(0)
	{};

	FastaChunk* readNextChunk();
	
	int64 Read(byte* memory_, uint64 size_)
	{
		int64 n = fileReader.Read(memory_, size_);
		return n;
	}

public:	
	SeqInfos seqInfos;

private:

	FastaDataPool&      recordsPool;
	FastaFileReader&	fileReader;
	uint32 numParts;
};
*/
//int chunkFormat(FastaDataChunk* &chunk, std::vector<Sequence*>&, bool);


std::string getSequence(FastaDataChunk* &chunk, uint64 &pos);	//addbyxxm
std::string getLine(FastaDataChunk* &chunk, uint64 &pos);
int chunkFormat(FastaChunk & fachunk, std::vector<Reference> & refs);
int chunkFormat(FastaChunk & fachunk, std::vector<Reference> & refs, int kmerSize);
Reference getNextSeq(FastaChunk & fachunk, bool & done, uint64 & pos);

} // namespace fa

namespace fq
{

//moved to FastxChunk.h
//typedef core::TDataQueue<FastqDataChunk> FastqDataQueue;
//typedef core::TDataPool<FastqDataChunk> FastqDataPool;

/*
class FastqReader //: public IFastqIoOperator
{
public:
    FastqReader(FastqFileReader& reader_, FastqDataPool& pool_)
	    :   recordsPool(pool_)
		,	fileReader(reader_)
		,	numParts(0)
	{};

	void readChunk();
	FastqDataChunk* readNextChunk();
	//single pe file
	FastqDataChunk* readNextPairedChunk();
	
	int64 Read(byte* memory_, uint64 size_)
	{
		int64 n = fileReader.Read(memory_, size_);
		return n;
	}

private:

	FastqDataPool&      recordsPool;
	FastqFileReader&	fileReader;
	uint32 numParts;
};
*/ 

int chunkFormat(FastqChunk* &chunk, std::vector<Reference> &,bool);
int chunkFormat(FastqChunk* &chunk, std::vector<neoReference> &,bool);

//single pe file 
//int pairedChunkFormat(FastqDataChunk* &chunk, std::vector<ReadPair*>&,bool mHasQuality);
//Read* getOnePairedRead(FastqDataChunk* &chunk,int &pos_, bool mHasQuality);
//end single pe file
std::string getLine(FastqDataChunk* &chunk, int &pos);
int neoGetLine(FastqDataChunk* &chunk, uint64_t &pos, uint64_t &len);

} // namespace fq

} // namespace mash

#endif
<file_sep>#ifndef __REFERENCE_H_
#define __REFERENCE_H_

#include <string> 
#include <vector>
#include "Globals.h"
struct Reference{
    std::string name;
    std::string comment;
    std::string seq;
    std::string quality;
    std::string strand;
    uint64_t length;
    uint64_t gid;
};

struct neoReference{
    uint64_t pname; //name offset
    uint64_t pcom; //comment ??
    uint64_t pseq; //sequence
    uint64_t pqual; //quality
    uint64_t pstrand;

    uint64_t lname;
    uint64_t lcom;
    uint64_t lseq;
    uint64_t lqual;
    uint64_t lstrand;
    //uint64_t length;
    uint64_t gid;
    mash::byte* base;
};
typedef std::vector<Reference> SeqInfos;
typedef Reference OneSeqInfo;


#endif