<commit_before>/*
 *     Copyright (C) 2005 by Thorsten Staerk <kde@staerk.de>
 *                   2007 the ktimetracker developers
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this program; if not, write to the
 *      Free Software Foundation, Inc.
 *      51 Franklin Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "ktimetrackerpart.h"

#include <QMenu>

#include <KAboutData>
#include <KAction>
#include <KComponentData>
#include <KGlobal>
#include <KLocale>
#include <KStandardAction>
#include <KStandardDirs>
#include <KXMLGUIFactory>
#include <KActionCollection>

#include <kdemacros.h>
#include <kparts/genericfactory.h>
#include "mainwindow.h"
#include "ktimetrackerutility.h"
#include "task.h"
#include "preferences.h"
#include "tray.h"
#include "version.h"
#include "ktimetracker.h"
#include "timetrackerwidget.h"

K_PLUGIN_FACTORY(ktimetrackerPartFactory, registerPlugin<ktimetrackerpart>();)
K_EXPORT_PLUGIN( ktimetrackerPartFactory("ktimetracker","ktimetracker") )

ktimetrackerpart::ktimetrackerpart( QWidget *parentWidget, QObject *parent, const QVariantList& )
    : KParts::ReadWritePart(parent)
{
    KGlobal::locale()->insertCatalog("ktimetracker");

    // we need an instance
    setComponentData( ktimetrackerPartFactory::componentData() );
    mMainWidget = new TimetrackerWidget( parentWidget );
    setWidget( mMainWidget );
    setXMLFile( "ktimetrackerui.rc" );
    makeMenus();
}

ktimetrackerpart::~ktimetrackerpart()
{
}

KAboutData *ktimetrackerpart::createAboutData()
{
    const QByteArray& appname=QByteArray("ktimetracker");
    const QByteArray& catalogname=QByteArray("ktimetracker");
    const KLocalizedString localizedname=ki18n("ktimetracker");
    const QByteArray version=QByteArray(KTIMETRACKER_VERSION);
    KAboutData* aboutData=new KAboutData( appname, catalogname, localizedname, version);
    return aboutData;
}

void ktimetrackerpart::makeMenus()
{
    mMainWidget->setupActions( actionCollection() );
    KAction *actionKeyBindings;
    actionKeyBindings = KStandardAction::keyBindings( this, SLOT( keyBindings() ),
        actionCollection() );
    // Tool tips must be set after the createGUI.
    actionKeyBindings->setToolTip( i18n("Configure key bindings") );
    actionKeyBindings->setWhatsThis( i18n("This will let you configure key"
                                        "bindings which are specific to ktimetracker") );
}

void ktimetrackerpart::setStatusBar(const QString & qs)
{
    kDebug(5970) << "Entering function";
    emit setStatusBarText(qs);
}

bool ktimetrackerpart::openFile(QString icsfile)
{
    mMainWidget->openFile(icsfile);
    emit setWindowCaption(icsfile);
    if ( KTimeTrackerSettings::trayIcon() ) mTray = new TrayIcon( this );
    else mTray = new TrayIcon( );

    // connections
    connect( mMainWidget, SIGNAL( totalTimesChanged( long, long ) ),
           this, SLOT( updateTime( long, long ) ) );
    connect( mMainWidget, SIGNAL( statusBarTextChangeRequested( QString ) ),
           this, SLOT( setStatusBar( QString ) ) );
    connect( mMainWidget, SIGNAL( setCaption( const QString& ) ),
           this, SIGNAL( setWindowCaption( const QString& ) ) );
    connect( mTray, SIGNAL( quitSelected() ), SLOT( quit() ) );
    connect( mMainWidget, SIGNAL( timersActive() ), mTray, SLOT( startClock() ) );
    connect( mMainWidget, SIGNAL( timersInactive() ), mTray, SLOT( stopClock() ) );
    connect( mMainWidget, SIGNAL( tasksChanged( const QList<Task*>& ) ),
           mTray, SLOT( updateToolTip( QList<Task*> ) ));
    return true;
}

bool ktimetrackerpart::openFile()
{
    return openFile(KStandardDirs::locateLocal( "data", QString::fromLatin1( "ktimetracker/ktimetracker.ics" ) ));
}

bool ktimetrackerpart::saveFile()
{
    mMainWidget->saveFile();
    return true;
}

#include "ktimetrackerpart.moc"
<commit_msg>load catalog with translations for kdatepickerpopup<commit_after>/*
 *     Copyright (C) 2005 by Thorsten Staerk <kde@staerk.de>
 *                   2007 the ktimetracker developers
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this program; if not, write to the
 *      Free Software Foundation, Inc.
 *      51 Franklin Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "ktimetrackerpart.h"

#include <QMenu>

#include <KAboutData>
#include <KAction>
#include <KComponentData>
#include <KGlobal>
#include <KLocale>
#include <KStandardAction>
#include <KStandardDirs>
#include <KXMLGUIFactory>
#include <KActionCollection>

#include <kdemacros.h>
#include <kparts/genericfactory.h>
#include "mainwindow.h"
#include "ktimetrackerutility.h"
#include "task.h"
#include "preferences.h"
#include "tray.h"
#include "version.h"
#include "ktimetracker.h"
#include "timetrackerwidget.h"

K_PLUGIN_FACTORY(ktimetrackerPartFactory, registerPlugin<ktimetrackerpart>();)
K_EXPORT_PLUGIN( ktimetrackerPartFactory("ktimetracker","ktimetracker") )

ktimetrackerpart::ktimetrackerpart( QWidget *parentWidget, QObject *parent, const QVariantList& )
    : KParts::ReadWritePart(parent)
{
    KGlobal::locale()->insertCatalog("ktimetracker");
    KGlobal::locale()->insertCatalog("libkdepim");
    // we need an instance
    setComponentData( ktimetrackerPartFactory::componentData() );
    mMainWidget = new TimetrackerWidget( parentWidget );
    setWidget( mMainWidget );
    setXMLFile( "ktimetrackerui.rc" );
    makeMenus();
}

ktimetrackerpart::~ktimetrackerpart()
{
}

KAboutData *ktimetrackerpart::createAboutData()
{
    const QByteArray& appname=QByteArray("ktimetracker");
    const QByteArray& catalogname=QByteArray("ktimetracker");
    const KLocalizedString localizedname=ki18n("ktimetracker");
    const QByteArray version=QByteArray(KTIMETRACKER_VERSION);
    KAboutData* aboutData=new KAboutData( appname, catalogname, localizedname, version);
    return aboutData;
}

void ktimetrackerpart::makeMenus()
{
    mMainWidget->setupActions( actionCollection() );
    KAction *actionKeyBindings;
    actionKeyBindings = KStandardAction::keyBindings( this, SLOT( keyBindings() ),
        actionCollection() );
    // Tool tips must be set after the createGUI.
    actionKeyBindings->setToolTip( i18n("Configure key bindings") );
    actionKeyBindings->setWhatsThis( i18n("This will let you configure key"
                                        "bindings which are specific to ktimetracker") );
}

void ktimetrackerpart::setStatusBar(const QString & qs)
{
    kDebug(5970) << "Entering function";
    emit setStatusBarText(qs);
}

bool ktimetrackerpart::openFile(QString icsfile)
{
    mMainWidget->openFile(icsfile);
    emit setWindowCaption(icsfile);
    if ( KTimeTrackerSettings::trayIcon() ) mTray = new TrayIcon( this );
    else mTray = new TrayIcon( );

    // connections
    connect( mMainWidget, SIGNAL( totalTimesChanged( long, long ) ),
           this, SLOT( updateTime( long, long ) ) );
    connect( mMainWidget, SIGNAL( statusBarTextChangeRequested( QString ) ),
           this, SLOT( setStatusBar( QString ) ) );
    connect( mMainWidget, SIGNAL( setCaption( const QString& ) ),
           this, SIGNAL( setWindowCaption( const QString& ) ) );
    connect( mTray, SIGNAL( quitSelected() ), SLOT( quit() ) );
    connect( mMainWidget, SIGNAL( timersActive() ), mTray, SLOT( startClock() ) );
    connect( mMainWidget, SIGNAL( timersInactive() ), mTray, SLOT( stopClock() ) );
    connect( mMainWidget, SIGNAL( tasksChanged( const QList<Task*>& ) ),
           mTray, SLOT( updateToolTip( QList<Task*> ) ));
    return true;
}

bool ktimetrackerpart::openFile()
{
    return openFile(KStandardDirs::locateLocal( "data", QString::fromLatin1( "ktimetracker/ktimetracker.ics" ) ));
}

bool ktimetrackerpart::saveFile()
{
    mMainWidget->saveFile();
    return true;
}

#include "ktimetrackerpart.moc"
<|endoftext|>


<commit_before>#include <img_processing.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <settings_class.h>
#include <stdlib.h>
#include <ancillary_functions.h>

#include <boost/filesystem.hpp>

#define DEFAULT_RESCALE_Y 100
#define DEFAULT_RESCALE_X 100

// change image to same dimensions
float Img_Processing::compareImages(std::string img1, std::string img2){
	int* bucket1 = (int*) calloc(BUCKET_SIZE, sizeof(int));
	int* bucket2 = (int*) calloc(BUCKET_SIZE, sizeof(int));
	int bytes_to_read = 0;
	FILE* img1_loaded;
	FILE* img2_loaded;
	if(!(img1_loaded = fopen(img1.c_str(), "r"))) std::cerr << "Couldn't open image";
	if(!(img2_loaded = fopen(img2.c_str(), "r"))) std::cerr << "Couldn't open image"; // add exception?
	bytes_to_read = boost::filesystem::file_size(img1);
	Img_Processing::getBuckets(img1_loaded, bucket1, bytes_to_read - 1);
	fclose(img1_loaded);
	// practice clearing pointers
	//Print first 2kb of image 1
	/*for(int x = 0; x < BUCKET_SIZE; x++){
		printf("%02d ", bucket1[x]);
		if(x % 20 == 1 && x > 1) std::cout << "\n";
	}*/
	std::cout << "\n";
	bytes_to_read = boost::filesystem::file_size(img2);
	Img_Processing::getBuckets(img2_loaded, bucket2, bytes_to_read);
	//Print first 2kb of Image2
	/*for(int x = 0; x < BUCKET_SIZE; x++){
		printf("%02d ", bucket2[x]);
		if(x % 20 == 1 && x > 1) std::cout << "\n";
	}*/

	// Compare the buckets
	int difference = 0;
	int sum_diff = 0;
	for(int x = 0; x < BUCKET_SIZE; x++){
		difference = bucket1[x] - bucket2[x]; // average and compare to original?
		if(difference < 0) difference *= -1;
		sum_diff += difference;
	}
	printf("\nDifference between images: %%%.4f", ((float) sum_diff / (bytes_to_read * 256)) * 1000);
	fclose(img2_loaded);
	return 1.0;
}

void Img_Processing::getBuckets(FILE* img, int* store, int bytes_to_read){
	unsigned char* buffer = (unsigned char*) calloc(bytes_to_read, sizeof(char));
	fread(buffer, sizeof(char), bytes_to_read, img);
	for(int x = 0; x < bytes_to_read; x++){
		store[buffer[x]]++;
	}
}

float Img_Processing::compareMemoryImg(HBITMAP mem_img1, HBITMAP mem_img2){
	Gdiplus::Bitmap img1(mem_img1, NULL);
	Gdiplus::Bitmap img2(mem_img2, NULL);
	float per_diff = 0;
	int rgb_diff[3] = {0};
	int temp;
	// Gives Resolution of Image
	//img1.GetWidth() img1.GetHeight() << ;
	img1.SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
	img2.SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
	Gdiplus::Color c1;
	Gdiplus::Color c2;
	for(int x = 0; x < DEFAULT_RESCALE_X; x++){
		for(int y = 0; y < DEFAULT_RESCALE_Y; y++){
			img1.GetPixel(x, y, &c1);
			img2.GetPixel(x, y, &c2);
			temp = c1.GetR() - c2.GetR();
			if(temp < 0) temp *= -1;
			rgb_diff[0] += temp;
			temp = c1.GetB() - c2.GetB();
			if(temp < 0) temp *= -1;
			rgb_diff[1] += temp;
			temp = c1.GetG() - c2.GetG();
			if(temp < 0) temp *= -1;
			rgb_diff[2] += temp;
			//printf("Img 1: R: %03d G: %03d B: %03d\tImg 2: R: %03d G: %03d B: %03d\n", c1.GetR(), c1.GetG(), c1.GetB(), c2.GetR(), c2.GetG(), c2.GetB());
		}
	}
	for(int x = 0; x < 3; x++){
		per_diff += rgb_diff[x];
	}
	per_diff = per_diff / (DEFAULT_RESCALE_Y * DEFAULT_RESCALE_X);
	return per_diff;
}

struct result_data Img_Processing::compareMemoryImgSel(HBITMAP canvas, HBITMAP img, int x, int y, struct Scaling_Info* si_s){
	Gdiplus::Bitmap img1(canvas, NULL);
	std::vector<Gdiplus::Bitmap*> img2;
	struct result_data rdt;
	rdt.difference = NULL;
	//************************check canvas is bigger than img*********************************
	//****************************************************************************************
	float scale_factor_x = img1.GetWidth() / si_s->x_scaler;
	float scale_factor_y = img1.GetHeight() / si_s->y_scaler ;
	si_s->scaling_ratio = scale_factor_x;
	std::cout << "Scale factor " << scale_factor_y << scale_factor_x << " " << "\n";
	std::cout << "Snapshot dimensions after scale factor applied: " << img1.GetHeight() << "x" << img1.GetWidth() << "\n";
	std::vector<Gdiplus::Bitmap*> newmap;
	int count = si_s->num_images;
	std::cout << "number of images: " << count << std::endl;
	rdt.difference = (float*) calloc(sizeof(float), count);
	rdt.threshold = (float*) calloc(sizeof(float), count);
	//const CLSID codec = { 0x557cf406, 0x1a04, 0x11d3,{ 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } };
	//newmap->Save(L"test.png", &codec, NULL);
	//exit(1);
	/*std::string file_name = "testf.png";

	const CLSID codec = { 0x557cf406, 0x1a04, 0x11d3,{ 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } };
	int size = file_name.length();
	wchar_t name[size + 1];
	swprintf(name, size + 1, L"%s", file_name.c_str());
	int status = (*newmap).Save(name, &codec, NULL);
	if(status){
		std::cerr << "Error saving image: " << status << "\n";
		return 1;
	}*/
	float per_diff = 0;
	int rgb_diff[3] = {0};
	int temp;
	try{
		for(int z = 0; z < count; z++){
			per_diff = 0;
			for(int x = 0; x < 3; x++) rgb_diff[x] = 0;
			img2.push_back(new Gdiplus::Bitmap(si_s->pic_data_array[z].bmp, NULL));
			x = si_s->pic_data_array[z].x;
			y = si_s->pic_data_array[z].y;
			printf("statistics: x: %d y: %d width: %d height: %d scale_factor: %f", x, y, img2.back()->GetHeight(), img2.back()->GetWidth(), scale_factor_x);
			newmap.push_back(img1.Clone(x * scale_factor_x, y * scale_factor_y, img2.back()->GetWidth() * scale_factor_x, img2.back()->GetHeight() * scale_factor_y, PixelFormat32bppARGB));
			img2.back()->SetResolution(DEFAULT_RESCALE_X * scale_factor_x, DEFAULT_RESCALE_Y * scale_factor_y);
			newmap.back()->SetResolution(DEFAULT_RESCALE_X * scale_factor_x, DEFAULT_RESCALE_Y * scale_factor_y);
			Gdiplus::Color c1;
			Gdiplus::Color c2;
			for(int c = 0; c < DEFAULT_RESCALE_X * scale_factor_x; c++){
				for(int b = 0; b < DEFAULT_RESCALE_Y * scale_factor_y; b++){
					newmap.back()->GetPixel(c, b, &c1);
					img2.back()->GetPixel(c, b, &c2);
					temp = c1.GetR() - c2.GetR();
					if(temp < 0) temp *= -1;
					rgb_diff[0] += temp;
					temp = c1.GetB() - c2.GetB();
					if(temp < 0) temp *= -1;
					rgb_diff[1] += temp;
					temp = c1.GetG() - c2.GetG();
					if(temp < 0) temp *= -1;
					rgb_diff[2] += temp;
					//printf("Img 1: R: %03d G: %03d B: %03d\tImg 2: R: %03d G: %03d B: %03d\n", c1.GetR(), c1.GetG(), c1.GetB(), c2.GetR(), c2.GetG(), c2.GetB());
				}
			}
			for(int z = 0; z < 3; z++){
				per_diff += rgb_diff[z];
			}
			per_diff = per_diff / ((DEFAULT_RESCALE_Y * scale_factor_y) * (DEFAULT_RESCALE_X * scale_factor_x));
			rdt.difference[z] = per_diff;
		}
	}catch(std::exception &e){
			std::cerr << "Error: " << e.what();
			exit(1);
	}
	for(int z = 0; z < img2.size() ; z++)delete img2.at(z);
	for(int z = 0; z < newmap.size(); z++) delete newmap.at(z);
	img2.clear();
	newmap.clear();
	return rdt;
	}<commit_msg>revised comparing method, now using LockBits<commit_after>#include <img_processing.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
//#include <ancillary_functions.h>

//#include <boost/filesystem.hpp>

#define DEFAULT_RESCALE_Y 100
#define DEFAULT_RESCALE_X 100
// change image to same dimensions
namespace Img_Processing{

	float compareImages(std::string img1, std::string img2){
		int sum_diff, temp = 0;
		float per_diff = 0;
		int rgb_diff[3] = {0};
		FILE* img1_loaded;
		FILE* img2_loaded;
		if(!(img1_loaded = fopen(img1.c_str(), "r"))) std::cerr << "Couldn't open image";
		if(!(img2_loaded = fopen(img2.c_str(), "r"))) std::cerr << "Couldn't open image"; // add exception?

		Gdiplus::Bitmap* img1_bmp = new Gdiplus::Bitmap(std::wstring(img1.begin(), img1.end()).c_str(), NULL);
		Gdiplus::Bitmap* img2_bmp = new Gdiplus::Bitmap(std::wstring(img2.begin(), img2.end()).c_str(), NULL);
		img1_bmp->SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
		img2_bmp->SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
		Gdiplus::Color c1;
		Gdiplus::Color c2;

		for(int x = 0; x < DEFAULT_RESCALE_X; x++){
			for(int y = 0; y < DEFAULT_RESCALE_Y; y++){
				img1_bmp->GetPixel(x, y, &c1);
				img2_bmp->GetPixel(x, y, &c2);
				temp = c1.GetR() - c2.GetR();
				if(temp < 0) temp *= -1;
				rgb_diff[0] += temp;
				temp = c1.GetB() - c2.GetB();
				if(temp < 0) temp *= -1;
				rgb_diff[1] += temp;
				temp = c1.GetG() - c2.GetG();
				if(temp < 0) temp *= -1;
				rgb_diff[2] += temp;
				//printf("Img 1: R: %03d G: %03d B: %03d\tImg 2: R: %03d G: %03d B: %03d\n", c1.GetR(), c1.GetG(), c1.GetB(), c2.GetR(), c2.GetG(), c2.GetB());
			}
		}
		for(int x = 0; x < 3; x++){
			per_diff += rgb_diff[x];
		}
		per_diff = per_diff / (DEFAULT_RESCALE_Y * DEFAULT_RESCALE_X);

		// clean up
		DeleteObject(img1_bmp);
		DeleteObject(img2_bmp);
		return per_diff;
	}

	float compareMemoryImg(HBITMAP mem_img1, HBITMAP mem_img2){
		Gdiplus::Bitmap img1(mem_img1, NULL);
		Gdiplus::Bitmap img2(mem_img2, NULL);
		float per_diff = 0;
		int rgb_diff[3] = {0};
		int temp;
		// Gives Resolution of Image
		//img1.GetWidth() img1.GetHeight() << ;
		img1.SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
		img2.SetResolution(DEFAULT_RESCALE_X, DEFAULT_RESCALE_Y);
		Gdiplus::Color c1;
		Gdiplus::Color c2;
		for(int x = 0; x < DEFAULT_RESCALE_X; x++){
			for(int y = 0; y < DEFAULT_RESCALE_Y; y++){
				img1.GetPixel(x, y, &c1);
				img2.GetPixel(x, y, &c2);
				temp = c1.GetR() - c2.GetR();
				if(temp < 0) temp *= -1;
				rgb_diff[0] += temp;
				temp = c1.GetB() - c2.GetB();
				if(temp < 0) temp *= -1;
				rgb_diff[1] += temp;
				temp = c1.GetG() - c2.GetG();
				if(temp < 0) temp *= -1;
				rgb_diff[2] += temp;
				//printf("Img 1: R: %03d G: %03d B: %03d\tImg 2: R: %03d G: %03d B: %03d\n", c1.GetR(), c1.GetG(), c1.GetB(), c2.GetR(), c2.GetG(), c2.GetB());
			}
		}
		for(int x = 0; x < 3; x++){
			per_diff += rgb_diff[x];
		}
		per_diff = per_diff / (DEFAULT_RESCALE_Y * DEFAULT_RESCALE_X);
		return per_diff;
	}

	struct result_data compareMemoryImgSel(HBITMAP canvas, HBITMAP img, int x, int y, struct Scaling_Info* si_s){
		float per_diff = 0;
		int temp = 0;
		int rgb_diff[3] = {0};
		Gdiplus::Bitmap img1(canvas, NULL);
		vector<Gdiplus::Bitmap*> img2;
		struct result_data rdt;
		rdt.difference = NULL;
		//************************check canvas is bigger than img*********************************
		//****************************************************************************************
		float scale_factor_x = img1.GetWidth() / si_s->x_scaler;
		float scale_factor_y = img1.GetHeight() / si_s->y_scaler ;
		si_s->scaling_ratio = scale_factor_x;
		cout << "Scale factor " << scale_factor_y << scale_factor_x << " " << "\n";
		cout << "Snapshot dimensions after scale factor applied: " << img1.GetHeight() << "x" << img1.GetWidth() << "\n";
		vector<Gdiplus::Bitmap*> newmap;
		int count = si_s->num_images;
		cout << "number of images: " << count << std::endl;
		rdt.difference = (float*) calloc(sizeof(float), count);
		rdt.threshold = (float*) calloc(sizeof(float), count);

		try{
			for(int z = 0; z < count; z++){
				per_diff = 0;
				for(int x = 0; x < 3; x++) rgb_diff[x] = 0;
				img2.push_back(new Gdiplus::Bitmap(si_s->pic_data_array[z].bmp, NULL));
				x = si_s->pic_data_array[z].x;
				y = si_s->pic_data_array[z].y;
				printf("statistics: x: %d y: %d width: %d height: %d scale_factor: %f", x, y, img2.back()->GetHeight(), img2.back()->GetWidth(), scale_factor_x);
				newmap.push_back(img1.Clone(x * scale_factor_x, y * scale_factor_y, img2.back()->GetWidth() * scale_factor_x, img2.back()->GetHeight() * scale_factor_y, PixelFormat32bppARGB));
				img2.back()->SetResolution(DEFAULT_RESCALE_X * scale_factor_x, DEFAULT_RESCALE_Y * scale_factor_y);
				newmap.back()->SetResolution(DEFAULT_RESCALE_X * scale_factor_x, DEFAULT_RESCALE_Y * scale_factor_y);
				Gdiplus::Color c1;
				Gdiplus::Color c2;
				for(int c = 0; c < DEFAULT_RESCALE_X * scale_factor_x; c++){
					for(int b = 0; b < DEFAULT_RESCALE_Y * scale_factor_y; b++){
						newmap.back()->GetPixel(c, b, &c1);
						img2.back()->GetPixel(c, b, &c2);
						temp = c1.GetR() - c2.GetR();
						if(temp < 0) temp *= -1;
						rgb_diff[0] += temp;
						temp = c1.GetB() - c2.GetB();
						if(temp < 0) temp *= -1;
						rgb_diff[1] += temp;
						temp = c1.GetG() - c2.GetG();
						if(temp < 0) temp *= -1;
						rgb_diff[2] += temp;
						//printf("Img 1: R: %03d G: %03d B: %03d\tImg 2: R: %03d G: %03d B: %03d\n", c1.GetR(), c1.GetG(), c1.GetB(), c2.GetR(), c2.GetG(), c2.GetB());
					}
				}
				for(int z = 0; z < 3; z++){
					per_diff += rgb_diff[z];
				}
				per_diff = per_diff / ((DEFAULT_RESCALE_Y * scale_factor_y) * (DEFAULT_RESCALE_X * scale_factor_x));
				rdt.difference[z] = per_diff;
			}
		}catch(std::exception &e){
				std::cerr << "Error: " << e.what();
				exit(1);
		}
		for(int z = 0; z < img2.size() ; z++)delete img2.at(z);
		for(int z = 0; z < newmap.size(); z++) delete newmap.at(z);
		img2.clear();
		newmap.clear();
		return rdt;
	}

	void getBuckets(FILE* img, int* store, int bytes_to_read){
		unsigned char* buffer = (unsigned char*) calloc(bytes_to_read, sizeof(char));
		fread(buffer, sizeof(char), bytes_to_read, img);
		for(int x = 0; x < bytes_to_read; x++){
			store[buffer[x]]++;
		}
		free(buffer);
	}

	/**
	 * Compares two bitmaps and returns the overall color difference as a decimal where 100% difference would be 1.00 and a match would 0
	 * @param  img1 First image to compare
	 * @param  img2 Second image to compare
	 * @return      the overall difference as a decimal which is <= 1
	 */
	float compareMemoryImg(Gdiplus::Bitmap* img1, Gdiplus::Bitmap* img2){
		// compare bitmaps
		float difference, per_diff = 0;
		int height, width;
		height = img1->GetHeight();
		width = img1->GetWidth();
		if(height > img2->GetHeight()) height = img2->GetHeight();
		if(width > img2->GetWidth()) width = img2->GetWidth();

		Gdiplus::BitmapData* bitmapData1 = new Gdiplus::BitmapData;
		Gdiplus::BitmapData* bitmapData2 = new Gdiplus::BitmapData;
		Gdiplus::Color c1;
		Gdiplus::Color c2;

		Gdiplus::Rect rect(0,0, width, height);
		img1->LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData1);
		img2->LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData2);

		int current_pixel_place;
		unsigned char* pixels_1 = (unsigned char*) bitmapData1->Scan0;
		unsigned char* pixels_2 = (unsigned char*) bitmapData2->Scan0;

		for(int x = 0; x < height; x++){
			for(int y = 0; y < width; y++){
				current_pixel_place = x * bitmapData1->Stride / 4 + y*4;
				for(int z = 0; z < 2; z ++)
				{
					difference = pixels_1[current_pixel_place + z] - pixels_2[current_pixel_place + z];
					if(difference < 0) difference *= -1;
					per_diff += difference;
				}
			}
		}

		img1->UnlockBits(bitmapData1);
		img2->UnlockBits(bitmapData2);
		delete bitmapData1;
		delete bitmapData2;
		DeleteObject(bitmapData1);
		DeleteObject(bitmapData2);
		return (per_diff / (width * height * 765));
	}

	void cropBitmap(Gdiplus::Bitmap** img, int x, int y, int width, int height){
		Gdiplus::Bitmap* temp = (*img)->Clone(x, y, width, height, PixelFormat32bppARGB);
		delete *img;
		*img = temp;
	}

}<|endoftext|>


<commit_before>// Copyright (C) 2010 Nikhil Marathe <nsm.nikhil@gmail.com>

#include <string>
#include <vector>
#include <iostream>

#include <v8.h>
#include <node.h>

#include <libface/LibFace.h>
#include <libface/Face.h>

using namespace v8;
using namespace node;

namespace face {

Handle<Value> Faces( const Arguments &args ) {
  HandleScope scope;

  std::string filename;
  if (args.Length() > 0 && args[0]->IsString()) {
    Local<String> p = args[0]->ToString();
    String::AsciiValue asc(p);
    filename = *asc;
  }

  libface::LibFace detector;
  std::vector<libface::Face> faces = detector.detectFaces(filename);

  Local<Array> faceArray = Array::New(faces.size());
  for(int i = 0, l = faces.size(); i < l; i++) {
      Local<Object> coords = Object::New();
      coords->Set(String::New("x"), Integer::New(faces[i].getX1()));
      coords->Set(String::New("y"), Integer::New(faces[i].getY1()));
      coords->Set(String::New("width"), Integer::New(faces[i].getWidth()));
      coords->Set(String::New("height"), Integer::New(faces[i].getHeight()));

      faceArray->Set(Integer::New(i), coords);
  }

  return faceArray;
}

void Initialize( Handle<Object> target ) {
  HandleScope scope;

  Local<FunctionTemplate> t = FunctionTemplate::New(Faces);

  target->Set( String::NewSymbol( "faces" ), t->GetFunction() );
}
}

extern "C"
void init( Handle<Object> target ) {
  HandleScope scope;
  face::Initialize( target );
}

<commit_msg>Check if image is valid.<commit_after>// Copyright (C) 2010 Nikhil Marathe <nsm.nikhil@gmail.com>

#include <string>
#include <vector>
#include <iostream>

#include <v8.h>
#include <node.h>

#include <opencv2/opencv.hpp>
#include <libface/LibFace.h>
#include <libface/Face.h>

using namespace v8;
using namespace node;

namespace face {

Handle<Value> Faces( const Arguments &args ) {
  HandleScope scope;

  std::string filename;
  if (args.Length() > 0 && args[0]->IsString()) {
    Local<String> p = args[0]->ToString();
    String::AsciiValue asc(p);
    filename = *asc;
  }

  IplImage *img = cvLoadImage(filename.c_str());
  if( !img ) {
      return String::New( cvErrorStr( cvGetErrStatus() ) );
  }

  libface::LibFace detector;
  std::vector<libface::Face> faces = detector.detectFaces(filename);

  Local<Array> faceArray = Array::New(faces.size());
  for(int i = 0, l = faces.size(); i < l; i++) {
      Local<Object> coords = Object::New();
      coords->Set(String::New("x"), Integer::New(faces[i].getX1()));
      coords->Set(String::New("y"), Integer::New(faces[i].getY1()));
      coords->Set(String::New("width"), Integer::New(faces[i].getWidth()));
      coords->Set(String::New("height"), Integer::New(faces[i].getHeight()));

      faceArray->Set(Integer::New(i), coords);
  }

  return scope.Close(faceArray);
}

void Initialize( Handle<Object> target ) {
  HandleScope scope;

  Local<FunctionTemplate> t = FunctionTemplate::New(Faces);

  target->Set( String::NewSymbol( "faces" ), t->GetFunction() );
}
}

extern "C"
void init( Handle<Object> target ) {
  HandleScope scope;
  face::Initialize( target );
}

<|endoftext|>


<commit_before>#include <QPdfWriter>
#include <QPrintDialog>
#include <QPainter>
#include <QPrintPreviewWidget>
#include <QPrintPreviewDialog>
#include <QTextBrowser>
#include <QFile>
#include <QTextStream>
#include "engine.hpp"

namespace qtreports {

	Engine::Engine( QObject * parent ) :
		QObject( parent ),
		m_isCompiled( false ) {}

	Engine::~Engine() {}

	bool	Engine::compile( const QString & path ) {
		detail::Translator translator;
		bool result = translator.parse( path );
		if( !result ) {
			m_lastError = translator.getLastError();
			return false;
		}

		m_isCompiled = true;
		m_compiledPath = path;
		m_widget = translator.getWidget();
		return true;
	}

	bool	Engine::setParameters( const QMap< QString, QString > & map ) {
		//QString or QVariant?
		return true;
	}

	bool	Engine::setConnection( const QSqlDatabase & connection ) {
		if( connection.isOpen() ) {
			m_lastError = "Connection not open";
			return false;
		}

		return true;
	}

	bool	Engine::createPDF( const QString & path ) {
		QPdfWriter writer( path );
		//Very small, need resize to page size.
		m_widget->render( &writer );
		return true;
	}

	bool	Engine::createHTML( const QString & path ) {
		auto isCopied = QFile::copy( m_compiledPath, path );
		if( !isCopied ) {
			m_lastError = "Can not create html file";
			return false;
		}

		return true;
		/*
		auto browser = dynamic_cast< QTextBrowser * >( m_widget.data() );
		QFile file( path );
		file.open(
			QIODevice::OpenModeFlag::WriteOnly |
			QIODevice::OpenModeFlag::Text |
			QIODevice::OpenModeFlag::Truncate
		);

		if( !file.isOpen() ) {
			m_lastError = "The file can not be opened";
			return false;
		}

		QTextStream stream( &file );
		stream << browser->toHtml();

		return true;
		*/
	}

	bool	Engine::print() {
		QPrinter printer;

		QPrintPreviewDialog preview( &printer );
		connect(
			&preview, &QPrintPreviewDialog::paintRequested,
			this, &Engine::drawPreview
		);
		preview.exec();

		return true;
	}

	void	Engine::drawPreview( QPrinter * printer ) {
		QRectF rect = printer->pageRect();
		QPainter painter( printer );
		double xscale = rect.width() / m_widget->width();
		double yscale = rect.height() / m_widget->height();
		double scale = std::min( xscale, yscale );
		painter.translate(
			0, rect.height() / 2 - scale * m_widget->height() / 2
		);
		painter.scale( scale, scale );
		m_widget->render( &painter );
	}

	const QString		Engine::getLastError() const {
		return m_lastError;
	}

	const QWidgetPtr	Engine::getWidget() const {
		return m_widget;
	}

	const bool			Engine::isCompiled() const {
		return m_isCompiled;
	}
}<commit_msg>Delete engine.cpp<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \file libuvalue/ubinary.cc

#include <iostream>
#include <sstream>
#include <libport/debug.hh>
#include <libport/escape.hh>
#include <urbi/ubinary.hh>
#include <boost/algorithm/string/replace.hpp>

GD_CATEGORY(UValue);

namespace urbi
{

  UBinary::UBinary()
    : type(BINARY_NONE)
    , allocated_(true)
  {
    common.data = 0;
    common.size = 0;
  }

  UBinary::UBinary(const UBinary& b, bool copy)
    : type(BINARY_NONE)
    , allocated_(copy)
  {
    common.data = 0;
    if (copy)
      *this = b;
    else
    {
      // Be safe, do not try to guess which is bigger.
      image = b.image;
      sound = b.sound;
      message = b.message;
      type = b.type;
    }
  }

  UBinary::UBinary(const UImage& i, bool copy)
    : type(BINARY_IMAGE)
    , image(i)
    , allocated_(copy)
  {
    if (copy)
    {
      image.data = static_cast<unsigned char*> (malloc (image.size));
      memcpy(image.data, i.data, image.size);
    }
  }

  UBinary::UBinary(const USound& i, bool copy)
    : type(BINARY_SOUND)
    , sound(i)
    , allocated_(copy)
  {
    if (copy)
    {
      sound.data = static_cast<char*> (malloc (sound.size));
      memcpy(sound.data, i.data, sound.size);
    }
  }

  void
  UBinary::clear()
  {
    if (allocated_)
      free(common.data);
  }

  UBinary::~UBinary()
  {
    clear();
  }

  UBinary& UBinary::operator= (const UBinary& b)
  {
    if (this == &b)
      return *this;

    clear();

    type = b.type;
    message = b.message;
    common.size = b.common.size;
    switch(type)
    {
      case BINARY_IMAGE:
	image = b.image;
	break;
      case BINARY_SOUND:
	sound = b.sound;
	break;
      case BINARY_NONE:
      case BINARY_UNKNOWN:
	break;
    }
    common.data = malloc(common.size);
    memcpy(common.data, b.common.data, b.common.size);
    return *this;
  }

  int
  UBinary::parse(const char* message, int pos,
		 const binaries_type& bins,
		 binaries_type::const_iterator& binpos, bool copy)
  {
    std::istringstream is(message + pos);
    bool ok = parse(is, bins, binpos, copy);
    // tellg() might be -1 if we encountered an error.
    int endpos = is.tellg();
    if (endpos == -1)
      endpos = strlen(message) - pos;
    return (ok ? 1:-1) * (pos + endpos);
  }

  namespace
  {
    /// Return everything up to the next "\n" or "\n\r" or ";", not included.
    /// Leave \a i after that delimiter.
    /// Return empty string on errors.
    static
    std::string
    headers_get(std::istringstream& i)
    {
      std::string res;
      int c = 0;
      while (!i.eof()
             && (c = i.get()) && c != '\n' && c != ';')
        res.append(1, c);
      if (i.eof())
        GD_ERROR("unexpected end of file while parsing UBinary headers");
      else
      {
        // Skip the delimiter.
        if (c == '\n')
        {
          i.ignore();
          if (c == '\r')
            i.ignore();
        }
        else
          i.ignore();
      }

      return res;
    }
  }

  bool
  UBinary::parse(std::istringstream& is,
		 const binaries_type& bins,
		 binaries_type::const_iterator& binpos, bool copy)

  {
    // LIBPORT_ECHO("Parsing: {" << is.str() << "}");
    if (binpos == bins.end())
    {
      GD_ERROR("no binary data available");
      return false;
    }

    // Validate size.
    size_t psize;
    is >> psize;
    if (is.fail())
    {
      GD_FERROR("cannot read bin size: %s (%s)", is.str(), psize);
      return false;
    }
    if (psize != binpos->size)
    {
      GD_FERROR("bin size inconsistency: %s != %s", psize, binpos->size);
      return false;
    }
    common.size = psize;
    if (copy)
    {
      common.data = malloc(common.size);
      memcpy(common.data, binpos->data, common.size);
    }
    else
    {
      common.data = binpos->data;
      this->allocated_ = false;
    }
    ++binpos;

    // Skip spaces.
    while (is.peek() == ' ')
      is.ignore();

    // Get the headers.
    message = headers_get(is);

    // Analyse the header to decode know UBinary types.
    // Header stream.
    std::istringstream hs(message);

    // Parse the optional type.  Don't check hs.fail, since the type
    // is optional, in which case t remains empty.
    std::string t;
    hs >> t;
    UImageFormat image_format = parse_image_format(t);
    if (image_format != IMAGE_UNKNOWN || t.find("image_")==0)
    {
      type = BINARY_IMAGE;
      image.size = common.size;
      // In some cases (jpeg source), image size is not present in headers.
      image.width = image.height = 0;
      hs >> image.width >> image.height;
      image.imageFormat = image_format;
    }
    else if (t == "raw" || t == "wav")
    {
      type = BINARY_SOUND;
      sound.soundFormat = (t == "raw" ? SOUND_RAW
                           : t == "wav" ? SOUND_WAV
                           : SOUND_UNKNOWN);
      sound.size = common.size;
      hs >> sound.channels
         >> sound.rate
         >> sound.sampleSize >> sound.sampleFormat;
    }
    else
    {
      // GD_FWARN("unknown binary type: %s", t);
      type = BINARY_UNKNOWN;
    }

    return true;
  }

  void UBinary::buildMessage()
  {
    message = getMessage();
  }

  std::string UBinary::getMessage() const
  {
    switch (type)
    {
    case BINARY_IMAGE:
      return image.headers_();
    case BINARY_SOUND:
      return sound.headers_();
    case BINARY_UNKNOWN:
      {
        bool warned = false;
        std::string res = message;
        foreach (char& c, res)
          if (c == '\0' || c == '\n' || c == ';')
          {
            if (!warned++)
              GD_FERROR("invalid UBinary header: "
                        "prohibited `\\n', `\\0' and `;' will be "
                        "smashed to space: %s",
                        libport::escape(message));
            c = ' ';
          }
        return res;
      }
    case BINARY_NONE:
      return "";
    }
    unreachable();
  }

  std::ostream&
  UBinary::print(std::ostream& o) const
  {
    // Format for the Kernel, which wants ';' as header terminator.
    o << "BIN "<< common.size << ' ' << getMessage() << ';';
    o.write((char*) common.data, common.size);
    return o;
  }

  std::ostream&
  operator<< (std::ostream& o, const UBinary& t)
  {
    return t.print(o);
  }

} // namespace urbi
<commit_msg>UBinary: fix.<commit_after>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \file libuvalue/ubinary.cc

#include <iostream>
#include <sstream>
#include <libport/debug.hh>
#include <libport/escape.hh>
#include <urbi/ubinary.hh>
#include <boost/algorithm/string/replace.hpp>

GD_CATEGORY(UValue);

namespace urbi
{

  UBinary::UBinary()
    : type(BINARY_NONE)
    , allocated_(true)
  {
    common.data = 0;
    common.size = 0;
  }

  UBinary::UBinary(const UBinary& b, bool copy)
    : type(BINARY_NONE)
    , allocated_(copy)
  {
    common.data = 0;
    if (copy)
      *this = b;
    else
    {
      // Be safe, do not try to guess which is bigger.
      image = b.image;
      sound = b.sound;
      message = b.message;
      type = b.type;
    }
  }

  UBinary::UBinary(const UImage& i, bool copy)
    : type(BINARY_IMAGE)
    , image(i)
    , allocated_(copy)
  {
    if (copy)
    {
      image.data = static_cast<unsigned char*> (malloc (image.size));
      memcpy(image.data, i.data, image.size);
    }
  }

  UBinary::UBinary(const USound& i, bool copy)
    : type(BINARY_SOUND)
    , sound(i)
    , allocated_(copy)
  {
    if (copy)
    {
      sound.data = static_cast<char*> (malloc (sound.size));
      memcpy(sound.data, i.data, sound.size);
    }
  }

  void
  UBinary::clear()
  {
    if (allocated_)
      free(common.data);
  }

  UBinary::~UBinary()
  {
    clear();
  }

  UBinary& UBinary::operator= (const UBinary& b)
  {
    if (this == &b)
      return *this;

    clear();

    type = b.type;
    message = b.message;
    common.size = b.common.size;
    switch(type)
    {
      case BINARY_IMAGE:
	image = b.image;
	break;
      case BINARY_SOUND:
	sound = b.sound;
	break;
      case BINARY_NONE:
      case BINARY_UNKNOWN:
	break;
    }
    common.data = malloc(common.size);
    memcpy(common.data, b.common.data, b.common.size);
    return *this;
  }

  int
  UBinary::parse(const char* message, int pos,
		 const binaries_type& bins,
		 binaries_type::const_iterator& binpos, bool copy)
  {
    std::istringstream is(message + pos);
    bool ok = parse(is, bins, binpos, copy);
    // tellg() might be -1 if we encountered an error.
    int endpos = is.tellg();
    if (endpos == -1)
      endpos = strlen(message) - pos;
    return (ok ? 1:-1) * (pos + endpos);
  }

  namespace
  {
    /// Return everything up to the next "\n" or "\n\r" or ";", not included.
    /// Leave \a i after that delimiter.
    /// Return empty string on errors.
    static
    std::string
    headers_get(std::istringstream& i)
    {
      std::string res;
      int c = 0;
      while (!i.eof()
             && (c = i.get()) && c != '\n' && c != ';')
        res.append(1, c);
      if (i.eof())
        GD_ERROR("unexpected end of file while parsing UBinary headers");
      else
      {
        // Skip the delimiter.
        if (c == '\n')
        {
          i.ignore();
          if (i.peek() == '\r')
            i.ignore();
        }
        else
          i.ignore();
      }

      return res;
    }
  }

  bool
  UBinary::parse(std::istringstream& is,
		 const binaries_type& bins,
		 binaries_type::const_iterator& binpos, bool copy)

  {
    // LIBPORT_ECHO("Parsing: {" << is.str() << "}");
    if (binpos == bins.end())
    {
      GD_ERROR("no binary data available");
      return false;
    }

    // Validate size.
    size_t psize;
    is >> psize;
    if (is.fail())
    {
      GD_FERROR("cannot read bin size: %s (%s)", is.str(), psize);
      return false;
    }
    if (psize != binpos->size)
    {
      GD_FERROR("bin size inconsistency: %s != %s", psize, binpos->size);
      return false;
    }
    common.size = psize;
    if (copy)
    {
      common.data = malloc(common.size);
      memcpy(common.data, binpos->data, common.size);
    }
    else
    {
      common.data = binpos->data;
      this->allocated_ = false;
    }
    ++binpos;

    // Skip spaces.
    while (is.peek() == ' ')
      is.ignore();

    // Get the headers.
    message = headers_get(is);

    // Analyse the header to decode know UBinary types.
    // Header stream.
    std::istringstream hs(message);

    // Parse the optional type.  Don't check hs.fail, since the type
    // is optional, in which case t remains empty.
    std::string t;
    hs >> t;
    UImageFormat image_format = parse_image_format(t);
    if (image_format != IMAGE_UNKNOWN || t.find("image_")==0)
    {
      type = BINARY_IMAGE;
      image.size = common.size;
      // In some cases (jpeg source), image size is not present in headers.
      image.width = image.height = 0;
      hs >> image.width >> image.height;
      image.imageFormat = image_format;
    }
    else if (t == "raw" || t == "wav")
    {
      type = BINARY_SOUND;
      sound.soundFormat = (t == "raw" ? SOUND_RAW
                           : t == "wav" ? SOUND_WAV
                           : SOUND_UNKNOWN);
      sound.size = common.size;
      hs >> sound.channels
         >> sound.rate
         >> sound.sampleSize >> sound.sampleFormat;
    }
    else
    {
      // GD_FWARN("unknown binary type: %s", t);
      type = BINARY_UNKNOWN;
    }

    return true;
  }

  void UBinary::buildMessage()
  {
    message = getMessage();
  }

  std::string UBinary::getMessage() const
  {
    switch (type)
    {
    case BINARY_IMAGE:
      return image.headers_();
    case BINARY_SOUND:
      return sound.headers_();
    case BINARY_UNKNOWN:
      {
        bool warned = false;
        std::string res = message;
        foreach (char& c, res)
          if (c == '\0' || c == '\n' || c == ';')
          {
            if (!warned++)
              GD_FERROR("invalid UBinary header: "
                        "prohibited `\\n', `\\0' and `;' will be "
                        "smashed to space: %s",
                        libport::escape(message));
            c = ' ';
          }
        return res;
      }
    case BINARY_NONE:
      return "";
    }
    unreachable();
  }

  std::ostream&
  UBinary::print(std::ostream& o) const
  {
    // Format for the Kernel, which wants ';' as header terminator.
    o << "BIN "<< common.size << ' ' << getMessage() << ';';
    o.write((char*) common.data, common.size);
    return o;
  }

  std::ostream&
  operator<< (std::ostream& o, const UBinary& t)
  {
    return t.print(o);
  }

} // namespace urbi
<|endoftext|>


<commit_before>/*
Copyright (c) 2015, Wator Vapor
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of wator nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wator.hpp"
using namespace Wator;

#include <bitset>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;

/**
 * Constructor
 **/
V1CortexLayer::V1CortexLayer()
{

    memory_.push_back({});
}
V1CortexLayer::~V1CortexLayer()
{
    INFO_VAR(this);
}

/**
 * update
 * @return None.
 **/
void V1CortexLayer::update(void)
{
    INFO_VAR("finnish V1CortexLayer::update");
}

/**
 * round
 * @return None.
 **/
void V1CortexLayer::round(void)
{
    this->forward();
    this->update();
    INFO_VAR("finnish V1CortexLayer::round");
    LayerBase::round();
    this->dump();
}

/**
 * forward
 * @return None.
 **/
void V1CortexLayer::forward(void)
{
    pinchs_.clear();
    blobs_.clear();
    for(auto btm:bottom_){
        CoulombLayer *coulom  = dynamic_cast<CoulombLayer*>(btm);
        auto coulomBlob = coulom->getBlob(this);
        INFO_VAR(coulomBlob->w_);
        INFO_VAR(coulomBlob->h_);
        INFO_VAR(coulomBlob->ch_);
//        const int size = (coulomBlob->w_/this->w_ )* (coulomBlob->h_ /this->h_)* coulomBlob->ch_;
        for (auto top:top_) {
            auto pinch = new Blob<bool>(coulomBlob->w_,coulomBlob->h_,coulomBlob->ch_);
            for (int ch = 0; ch < coulomBlob->ch_; ch++) {
                for (int y = 0; y < coulomBlob->h_; y++) {
                    for (int x = 0; x < coulomBlob->w_; x++) {
                        int grid = (y/this->h_) * (coulomBlob->w_/this->w_) + (x/this->w_) ;
                        int index = ch * coulomBlob->w_ * coulomBlob->h_;
                        index += grid * this->w_ * this->h_;
                        index += (y%this->h_)*this->w_  + x%this->w_ ;
                        TRACE_VAR(index);
                        TRACE_VAR(x);
                        TRACE_VAR(y);
                        int index2 = ch * coulomBlob->w_ * coulomBlob->h_;
                        index2 += y*coulomBlob->w_ + x;
                        TRACE_VAR(index2);
                        if (index >= coulomBlob->size_|| index2 >= coulomBlob->size_) {
                            /// 无法整除的最后几行，不能的到下一层的完整输出，省略。
                            TRACE_VAR(this->w_);
                            TRACE_VAR(this->h_);
                            TRACE_VAR(grid);
                            TRACE_VAR(x);
                            TRACE_VAR(y);
                            TRACE_VAR(index);
                            TRACE_VAR(index2);
                            TRACE_VAR(coulomBlob->w_);
                            TRACE_VAR(coulomBlob->h_);
                            TRACE_VAR(coulomBlob->size_);
                            continue;
                        }
                        pinch->data_[index] = coulomBlob->data_[index2];
                    }
                }
            }
            pinchs_.push_back(pinch);
        }
    }
    INFO_VAR(pinchs_.size());
    for(int index = 0; index < pinchs_.size();index++) {
        auto &memory = memory_[index];
        auto pinch = pinchs_[index];
        TRACE_VAR(pinch->size_);
        for (int i = 0;i < pinch->size_;i += this->w_*this->h_) {
            uint64_t memIndex = 0;
            for (int j = 0; j < this->w_*this->h_; j++) {
                if (pinch->data_[i + j]) {
                    memIndex++;
                }
                memIndex = memIndex <<1;
            }
            std::bitset<64> memBit(memIndex);
            // sparse +- 1/3
            //if (memBit.count() < this->sparse_*2/3 || memBit.count() > this->sparse_*6/3) {
            if (memBit.count() != this->sparse_) {
                continue;
            }
            TRACE_VAR(memBit);
            TRACE_VAR(memIndex);
            auto it = memory.find(memIndex);
            if (it != memory.end()) {
                it->second++;
            } else {
                memory[memIndex] = 1;
            }
        }
        memory_[index] = memory;
    }
    INFO_VAR(memory_.size());
    for(auto memory :memory_) {
        map<uint64_t,vector<uint64_t>> sortByCount;
        for (auto it:memory) {
            auto memCount = it.second;
            auto itSort = sortByCount.find(memCount);
            if (sortByCount.end() != itSort) {
                itSort->second.push_back(it.first);
            } else {
                sortByCount[memCount] = {it.first};
            }
        }
        for (auto it:sortByCount) {
            auto memCount = it.first;
            INFO_VAR(memCount);
            for (auto mem:it.second) {
                if(9 ==this->w_*this->h_) {
                    std::bitset<9> memBit(mem);
                    INFO_VAR(memBit);
                }
                if(25 ==this->w_*this->h_) {
                    std::bitset<25> memBit(mem);
                    INFO_VAR(memBit);
                }
            }
        }
        INFO_VAR(memory.size());
        INFO_VAR(sortByCount.size());
#if 0
        {
            uint64_t line = 0b010010010;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b000111000;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b100010001;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b001010100;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
#endif
    }
    INFO_VAR(blobs_.size());
    INFO_VAR("finnish V1CortexLayer::forward");
}

/**
 * dump to png
 * @return None.
 **/
void V1CortexLayer::dump(void){
    INFO_VAR(blobs_.size());
    for (auto blob:blobs_) {
        blob->dump();
    }
}
<commit_msg>fix coredump<commit_after>/*
Copyright (c) 2015, Wator Vapor
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of wator nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wator.hpp"
using namespace Wator;

#include <bitset>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;

/**
 * Constructor
 **/
V1CortexLayer::V1CortexLayer()
{

    memory_.push_back({});
}
V1CortexLayer::~V1CortexLayer()
{
    INFO_VAR(this);
}

/**
 * update
 * @return None.
 **/
void V1CortexLayer::update(void)
{
    INFO_VAR("finnish V1CortexLayer::update");
}

/**
 * round
 * @return None.
 **/
void V1CortexLayer::round(void)
{
    this->forward();
    this->update();
    INFO_VAR("finnish V1CortexLayer::round");
    LayerBase::round();
    this->dump();
}

/**
 * forward
 * @return None.
 **/
void V1CortexLayer::forward(void)
{
    pinchs_.clear();
    blobs_.clear();
    for(auto btm:bottom_){
        CoulombLayer *coulom  = dynamic_cast<CoulombLayer*>(btm);
        auto coulomBlob = coulom->getBlob(this);
        INFO_VAR(coulomBlob->w_);
        INFO_VAR(coulomBlob->h_);
        INFO_VAR(coulomBlob->ch_);
//        const int size = (coulomBlob->w_/this->w_ )* (coulomBlob->h_ /this->h_)* coulomBlob->ch_;
        for (auto top:top_) {
            auto pinch = new Blob<bool>(coulomBlob->w_,coulomBlob->h_,coulomBlob->ch_);
            for (int ch = 0; ch < coulomBlob->ch_; ch++) {
                for (int y = 0; y < coulomBlob->h_; y++) {
                    for (int x = 0; x < coulomBlob->w_; x++) {
                        int grid = (y/this->h_) * (coulomBlob->w_/this->w_) + (x/this->w_) ;
                        int index = ch * coulomBlob->w_ * coulomBlob->h_;
                        index += grid * this->w_ * this->h_;
                        index += (y%this->h_)*this->w_  + x%this->w_ ;
                        TRACE_VAR(index);
                        TRACE_VAR(x);
                        TRACE_VAR(y);
                        int index2 = ch * coulomBlob->w_ * coulomBlob->h_;
                        index2 += y*coulomBlob->w_ + x;
                        TRACE_VAR(index2);
                        if (index >= coulomBlob->size_|| index2 >= coulomBlob->size_) {
                            // 无法整除的最后几行，不能的到下一层的完整输出，省略。
                            TRACE_VAR(this->w_);
                            TRACE_VAR(this->h_);
                            TRACE_VAR(grid);
                            TRACE_VAR(x);
                            TRACE_VAR(y);
                            TRACE_VAR(index);
                            TRACE_VAR(index2);
                            TRACE_VAR(coulomBlob->w_);
                            TRACE_VAR(coulomBlob->h_);
                            TRACE_VAR(coulomBlob->size_);
                            continue;
                        }
                        pinch->data_[index] = coulomBlob->data_[index2];
                    }
                }
            }
            pinchs_.push_back(pinch);
        }
    }
    INFO_VAR(pinchs_.size());
    for(int index = 0; index < pinchs_.size();index++) {
        auto &memory = memory_[index];
        auto pinch = pinchs_[index];
        TRACE_VAR(pinch->size_);
        for (int i = 0;i < pinch->size_;i += this->w_*this->h_) {
            uint64_t memIndex = 0;
            for (int j = 0; j < this->w_*this->h_; j++) {
                auto index = i + j;
                // 无法整除的最后几点，不能的到下一层的完整输出，省略。
                if (index >= pinch->size_) {
                    continue;
                }
                if (pinch->data_[index]) {
                    memIndex++;
                }
                memIndex = memIndex <<1;
            }
            std::bitset<64> memBit(memIndex);
            // sparse +- 1/3
            //if (memBit.count() < this->sparse_*2/3 || memBit.count() > this->sparse_*6/3) {
            if (memBit.count() != this->sparse_) {
                continue;
            }
            TRACE_VAR(memBit);
            TRACE_VAR(memIndex);
            auto it = memory.find(memIndex);
            if (it != memory.end()) {
                it->second++;
            } else {
                memory[memIndex] = 1;
            }
        }
        memory_[index] = memory;
    }
    INFO_VAR(memory_.size());
    for(auto memory :memory_) {
        map<uint64_t,vector<uint64_t>> sortByCount;
        for (auto it:memory) {
            auto memCount = it.second;
            auto itSort = sortByCount.find(memCount);
            if (sortByCount.end() != itSort) {
                itSort->second.push_back(it.first);
            } else {
                sortByCount[memCount] = {it.first};
            }
        }
        for (auto it:sortByCount) {
            auto memCount = it.first;
            INFO_VAR(memCount);
            for (auto mem:it.second) {
                if(9 ==this->w_*this->h_) {
                    std::bitset<9> memBit(mem);
                    INFO_VAR(memBit);
                }
                if(25 ==this->w_*this->h_) {
                    std::bitset<25> memBit(mem);
                    INFO_VAR(memBit);
                }
            }
        }
        INFO_VAR(memory.size());
        INFO_VAR(sortByCount.size());
#if 0
        {
            uint64_t line = 0b010010010;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b000111000;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b100010001;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
        {
            uint64_t line = 0b001010100;
            std::bitset<9> LineB(line);
            INFO_VAR(LineB);
            auto it = memory.find(line);
            if (memory.end() != it) {
                INFO_VAR(it->second);
            } else {
                INFO_VAR(0);
            }
        }
#endif
    }
    INFO_VAR(blobs_.size());
    INFO_VAR("finnish V1CortexLayer::forward");
}

/**
 * dump to png
 * @return None.
 **/
void V1CortexLayer::dump(void){
    INFO_VAR(blobs_.size());
    for (auto blob:blobs_) {
        blob->dump();
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/resolver.hpp"
#include <boost/bind.hpp>
#include "libtorrent/debug.hpp"

namespace libtorrent
{
// TODO: 3 the first places to use this resolver is the
// http_connection/http_tracker_connection and udp_tracker_connection.
// make sure to prefer cache on shutdown
	resolver::resolver(io_service& ios)
		: m_ios(ios)
		, m_resolver(ios)
		, m_max_size(700)
		, m_timeout(seconds(1200))
	{}

	void resolver::on_lookup(error_code const& ec, tcp::resolver::iterator i
		, resolver_interface::callback_t h, std::string hostname)
	{
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("resolver::on_lookup");
#endif
		if (ec)
		{
			std::vector<address> empty;
			h(ec, empty);
			return;
		}

		dns_cache_entry& ce = m_cache[hostname];
		ptime now = time_now();
		ce.last_seen = now;
		ce.addresses.clear();
		while (i != tcp::resolver::iterator())
		{
			ce.addresses.push_back(i->endpoint().address());
			++i;
		}

		h(ec, ce.addresses);

		// if m_cache grows too big, weed out the
		// oldest entries
		if (m_cache.size() > m_max_size)
		{
			cache_t::iterator oldest = m_cache.begin();
			for (cache_t::iterator i = m_cache.begin();
				i != m_cache.end(); ++i)
			{
				cache_t::iterator e = i;
				++i;
				if (e->second.last_seen < oldest->second.last_seen)
					oldest = e;
			}

			// remove the oldest entry
			m_cache.erase(oldest);
		}
	}

	void resolver::async_resolve(std::string const& host, int flags
		, resolver_interface::callback_t const& h)
	{
		cache_t::iterator i = m_cache.find(host);
		if (i != m_cache.end())
		{
			// keep cache entries valid for m_timeout seconds
			if ((flags & resolver_interface::prefer_cache)
				|| i->second.last_seen + m_timeout >= time_now())
			{
				error_code ec;
				m_ios.post(boost::bind(h, ec, i->second.addresses));
				return;
			}
		}

		// the port is ignored
		tcp::resolver::query q(host, "80");

#if defined TORRENT_ASIO_DEBUGGING
		add_outstanding_async("resolver::on_lookup");
#endif
		m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2
			, h, host));
	}
}

<commit_msg>fix bug in hostname resolver<commit_after>/*

Copyright (c) 2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/resolver.hpp"
#include <boost/bind.hpp>
#include "libtorrent/debug.hpp"

namespace libtorrent
{
// TODO: 3 the first places to use this resolver is the
// http_connection/http_tracker_connection and udp_tracker_connection.
// make sure to prefer cache on shutdown
	resolver::resolver(io_service& ios)
		: m_ios(ios)
		, m_resolver(ios)
		, m_max_size(700)
		, m_timeout(seconds(1200))
	{}

	void resolver::on_lookup(error_code const& ec, tcp::resolver::iterator i
		, resolver_interface::callback_t h, std::string hostname)
	{
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("resolver::on_lookup");
#endif
		if (ec)
		{
			std::vector<address> empty;
			h(ec, empty);
			return;
		}

		dns_cache_entry& ce = m_cache[hostname];
		ptime now = time_now();
		ce.last_seen = now;
		ce.addresses.clear();
		while (i != tcp::resolver::iterator())
		{
			ce.addresses.push_back(i->endpoint().address());
			++i;
		}

		h(ec, ce.addresses);

		// if m_cache grows too big, weed out the
		// oldest entries
		if (m_cache.size() > m_max_size)
		{
			cache_t::iterator oldest = m_cache.begin();
			for (cache_t::iterator i = m_cache.begin();
				i != m_cache.end(); ++i)
			{
				if (i->second.last_seen < oldest->second.last_seen)
					oldest = i;
			}

			// remove the oldest entry
			m_cache.erase(oldest);
		}
	}

	void resolver::async_resolve(std::string const& host, int flags
		, resolver_interface::callback_t const& h)
	{
		cache_t::iterator i = m_cache.find(host);
		if (i != m_cache.end())
		{
			// keep cache entries valid for m_timeout seconds
			if ((flags & resolver_interface::prefer_cache)
				|| i->second.last_seen + m_timeout >= time_now())
			{
				error_code ec;
				m_ios.post(boost::bind(h, ec, i->second.addresses));
				return;
			}
		}

		// the port is ignored
		tcp::resolver::query q(host, "80");

#if defined TORRENT_ASIO_DEBUGGING
		add_outstanding_async("resolver::on_lookup");
#endif
		m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2
			, h, host));
	}
}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * 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.
 */

/**
 * @file    file_loader.hpp
 * @ingroup io
 * @author  Tony Pan <tpan7@gatech.edu>
 * @brief   contains a generic FileLoader class to perform distributed and concurrent file access.
 *
 */

#ifndef FILE_LOADER_HPP_
#define FILE_LOADER_HPP_

#include "bliss-config.hpp"

#if defined(USE_MPI)
#include "mpi.h"
#endif

#if defined(USE_OPENMP)
#include "omp.h"
#endif

#include <string>
#include <cstring>      // memcpy, strerror
#include <exception>    // ioexception
#include <sstream>      // stringstream
#include <memory>

#include <unistd.h>     // sysconf
#include <sys/stat.h>   // block size.
#include <sys/mman.h>   // mmap
#include <fcntl.h>      // for open

#include <sys/sysinfo.h>  // for meminfo
#include <type_traits>

#include "partition/range.hpp"
#include "partition/partitioner.hpp"
//#include "io/data_block.hpp"
#include "io/io_exception.hpp"
#include "utils/logging.h"
#include "common/sequence.hpp"
#include <mxx/comm.hpp> // for mxx::comm

namespace bliss
{
namespace io
{
  struct BaseFile {

  };

  // TODO: simplify  possibly by separating L1 and L2 partitioning.

  /**
   * @brief  Partitions input data into sequences, e.g. blocks or reads.
   * @details  Iterator template parameter refers to the iterator type that is currently being traversed.
   * 		 this applies to the sequence object, and the following methods:
   * 		 get_next_record, and find_first_record.
   *
   * 		 init method can potentially use a different iterator type. this is useful when
   * 		   state information is extracted from perhaps a containing block (e.g. L1Block),
   * 		   then used with a sub block (e.g. L2Block).
   *
   * @note   there are 2 (non-interchangeable) scenarios when we may need to change the iterator type.
   *    1. L1 at process level, L2 at thread level.  SeqParser state is calculated at L1.
   *    2. L1 at rank 0 of a sub communicator (processes), L2 is broadcast from rank0 of the rest of processes.  SeqParser state is calculated at L1.
   *
   *    to handle the first case: approaches are
   *    1a. to allow a parser to operate on different iterator types when invoking find_first_record, increment.
   *          additional template parameter for these functions.  SequenceType will need to change.
   *          API in SequenceIterator, BaseFileParser, FASTQParser, FASTAParser all need to change
   *    1b. convert the seq parser from L1 to L2, but copy the state of L1.
   *          can be shared between threads.  additional api for convert only
   *
   *    to handle the second case.
   *    2a. convert the seq parser from L1 to L2, communicate (and copy) the state of L1.
   *          additional api for convert and broadcast. minimal api change. requires L1 to be block (or cyclic with synchronization).
   *    2b. create seq parser for L2, and initialize using all processes.
   *          no api change, but works only when L1 and L2 are block partitioned (or cyclic with synchronization).
   *          potentially less communication, and Parser does not need to have a broadcast semantic.
   *
   *    1a is not general, potentially complicated, and a source of potential errors.
   *    1b and 2a share common apis.
   *    2b requires application to specifically call init at L2.  Also, already initialized L1 during data load.
   *
   *    choose 2b and 1b.  Sequence Iterator does not call init_for_iterator, mostly for flexibility and compatibility with case 1.
   *
   * @tparam Iterator   The underlying iterator to be traversed to generate a Sequence
   *
   */
  template <typename Iterator>
   class BaseFileParser {

      // let another BaseFileParser with some other iterator type be a friend so we can convert.
      template <typename Iterator2>
      friend class BaseFileParser;

     public:
//      using SequenceIdType = SeqIdType;
      using SequenceType = typename ::bliss::common::Sequence<Iterator, ::bliss::common::SequenceId>;
      using SequenceIdType = typename SequenceType::IdType;

      /// static constant for end of line. Iterator note this is same for unicode as well
      static constexpr unsigned char eol = '\n';
      /// static constant for carriage return.  note this is same for unicode as well
      static constexpr unsigned char cr = '\r';

     protected:
       /**
        * @typedef RangeType
        * @brief   range object types
        */
      using RangeType = bliss::partition::range<size_t>;

       /**
        * @brief  search for first non-EOL character in a iterator, returns the stopping position as an iterator.  also records offset.
        * @details       iter can point to the previous EOL, or a nonEOL character.
        * @param[in/out] iter    iterator to advance
        * @param[in]     end     position to stop the traversal
        * @param[in/out] offset  the global offset of the sequence record within the file.  used as record id.
        * @return        iterator at the new position, where the Non EOL char is found, or end.
        */
       template <typename IT = Iterator,
           typename = typename ::std::enable_if<(::std::is_same<typename ::std::iterator_traits<IT>::value_type, char>::value ||
                                                ::std::is_same<typename ::std::iterator_traits<IT>::value_type, unsigned char>::value)
                                               >::type >
       inline IT findNonEOL(IT& iter, const IT& end, size_t &offset) const {
         while ((iter != end) && ((*iter == eol) || (*iter == cr))) {
           ++iter;
           ++offset;
         }
         return iter;
       }

       /**
        * @brief  search for first EOL character in a iterator, returns the stopping position as an iterator.  also records offset.
        * @details       iter can point to a nonEOL char, or an EOL char.
        * @param[in/out] iter    iterator to advance
        * @param[in]     end     position to stop the traversal
        * @param[in/out] offset  the global offset of the sequence record within the file.  used as record id.
        * @return        iterator at the new position, where the EOL char is found, or end.
        */
       template <typename IT = Iterator,
           typename = typename ::std::enable_if<(::std::is_same<typename ::std::iterator_traits<IT>::value_type, char>::value ||
                                                ::std::is_same<typename ::std::iterator_traits<IT>::value_type, unsigned char>::value)
                                               >::type >
       inline IT findEOL(IT& iter, const IT& end, size_t &offset) const {
         while ((iter != end) && ((*iter != eol) && (*iter != cr) ) ) {
           ++iter;
           ++offset;
         }
         return iter;
       }

       /**
        * @brief constructs an IOException object with the relevant debug data.
        * @param errType     string indicating the source of the error.  user choice
        * @param start       iterator pointing to beginning of the data in question
        * @param end         iterator pointing to end of the data in question
        * @param startOffset offset for the beginning of the data in question
        * @param endOffset   offset for the end of the data in question
        */
       void handleError(const std::string& errType, const Iterator &start, const Iterator &end, const size_t& startOffset, const size_t& endOffset) throw (bliss::io::IOException) {
         std::stringstream ss;
//#ifdef USE_MPI
//         int rank = 0;
//         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//         ss << "rank: " << rank << " ";
//#endif

         ss << "ERROR: " << errType << " in " << startOffset << " to " << endOffset << std::endl;
         ss << "  offending string is \"";
         std::ostream_iterator<typename std::iterator_traits<Iterator>::value_type> oit(ss);
         std::copy(start, end, oit);
         ss << "\".";
         throw ::std::logic_error(ss.str());
       }

       /**
        * @brief print out an Warning, for example when there is malformed partial data.
        * @param errType     string indicating the source of the error.  user choice
        * @param start       iterator pointing to beginning of the data in question
        * @param end         iterator pointing to end of the data in question
        * @param startOffset offset for the beginning of the data in question
        * @param endOffset   offset for the end of the data in question
        */
       void handleWarning(const std::string& errType, const Iterator &start, const Iterator &end, const size_t& startOffset, const size_t& endOffset) {
         BL_WARNING("WARNING: " << errType << " in " << startOffset << " to " << endOffset);
       }

     public:

       /// default constructor.
       BaseFileParser() {};

       /// default destructor
       virtual ~BaseFileParser() {};

       /// converting constructor.
       template <typename Iterator2>
       BaseFileParser(BaseFileParser<Iterator2> const & other) {}
       /// converting assignment operator that can transform the base iterator type.
       template <typename Iterator2>
       BaseFileParser<Iterator>& operator=(BaseFileParser<Iterator2> const & other) {
         return *this;
       }

       /**
        * @brief given a block/range, find the starting point of the first sequence object (here, just the actual start)
        * @note  virtual function, for convenience.
        *         used by getNextL1BlockRange to find exact range for an L1 Partition.
        *
        *         Also can be used to do other initializations.
        *
        * @param _data
        * @param parentRange
        * @param inMemRange
        * @param searchRange
        * @return
        */
       virtual std::size_t find_first_record(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange)
       {
         //== range checking
         if(!parentRange.contains(inMemRange)) {
           ::std::cout << "parent: " << parentRange << " , in mem: " << inMemRange << ::std::endl;
           throw std::invalid_argument("ERROR: Parent Range does not contain inMemRange");
         }

         // no op, other than to use intersect to make sure that the start is valid and within parent, and in memry ranges.
         return RangeType::intersect(searchRange, inMemRange).start;
       }
#ifdef USE_MPI
       virtual std::size_t find_first_record(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange, const mxx::comm& comm) {
         return find_first_record(_data, parentRange, inMemRange, searchRange);
       }
#endif

       virtual typename RangeType::ValueType find_overlap_end(const Iterator &_data,
    		   const RangeType &parentRange, const RangeType &inMemRange, typename RangeType::ValueType end, size_t overlap ) {
         return std::max(inMemRange.start, std::min(end + overlap, inMemRange.end));
       }

       /// reset any parser internal state so the parser can be reused on a different data range.  overridden in subclass.
       virtual void reset() {}

       virtual bool should_parse(const RangeType & range) {
         return range.size() > 0;
       }
#ifdef USE_MPI
       virtual bool should_parse(const RangeType & range, const mxx::comm & comm) {
         return range.size() > 0;
       }
#endif

       /// initializes parser for a particular data range.  overridden in subclass.  returns start of first record.  _data points to first element in mem.
       virtual std::size_t init_parser(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange) {
         return this->find_first_record(_data, parentRange, inMemRange, searchRange);
       }
#ifdef USE_MPI
       /// initializes the parser.  only useful for FASTA parser for now.  Assumes searchRange do NOT overlap between processes.   _data points to first element in mem.
       virtual std::size_t init_parser(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange, const mxx::comm& comm)
       {
         return this->find_first_record(_data, parentRange, inMemRange, searchRange);
       };
#endif

       /**
        * @brief increment to get next sequence object
        * @note   not virtual because SequenceType is different for each subclass, so the signatures are different.  We rely on compiler to enforce the correct one.
        *         this is in general not an issue as we do not need polymorphic Sequence Parsers - they are specific to file types.
        *         this is probably better for performance anyways.
        *
        *         Used by FileLoader's getRecordSize to compute an average record size.
        *
        * @param iter           start of a sequence object.  this is the beginning of a record, not just DNA sequence
        * @param end            end of a sequence object.  this is the end of a record, not just DNA sequence
        * @param offset         offset in the file for the start of the record.
        * @param seq_offset     index in the local (shared) vector of sequence breaks, if there is one (e.g. FASTA).  used by FASTA to lookup the nearest complete sequence record info.
        * @param output         updated sequence object.
        * @return               next seq id offset.
        */
       SequenceType get_next_record(Iterator & iter, const Iterator & end, size_t & offset)
       {
         Iterator orig_iter = iter;
         size_t orig_offset = offset;

         size_t dist = std::distance(iter, end);

         offset += dist;
         iter = end;

         return SequenceType(SequenceIdType(orig_offset), dist, 0, 0, orig_iter, end);
       }

       /**
        * @brief   get the average record size in the supplied range
        * @return  return the records size and the internal data size
        */
       virtual ::std::pair<size_t, size_t> get_record_size(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &validRange, size_t const count) {
         size_t dist = validRange.size();
         return ::std::pair<size_t, size_t>(dist,dist);
       }
#ifdef USE_MPI
       virtual ::std::pair<size_t, size_t> get_record_size(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &validRange, mxx::comm const & comm, size_t const count) {
         size_t dist = validRange.size();
         return ::std::pair<size_t, size_t>(dist,dist);
       }
#endif

   };
   /// template class' static variable definition (declared and initialized in class)
  template <typename Iterator>
   constexpr unsigned char bliss::io::BaseFileParser<Iterator >::eol;
  template <typename Iterator>
   constexpr unsigned char bliss::io::BaseFileParser<Iterator>::cr;

  } /* namespace functional */
} /* namespace bliss */
#endif /* FILE_LOADER_HPP_ */
<commit_msg>FIX: gcc 6 compiler error, part2.<commit_after>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * 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.
 */

/**
 * @file    file_loader.hpp
 * @ingroup io
 * @author  Tony Pan <tpan7@gatech.edu>
 * @brief   contains a generic FileLoader class to perform distributed and concurrent file access.
 *
 */

#ifndef FILE_LOADER_HPP_
#define FILE_LOADER_HPP_

#include "bliss-config.hpp"

#if defined(USE_MPI)
#include "mpi.h"
#endif

#if defined(USE_OPENMP)
#include "omp.h"
#endif

#include <string>
#include <cstring>      // memcpy, strerror
#include <exception>    // ioexception
#include <sstream>      // stringstream
#include <memory>

#include <unistd.h>     // sysconf
#include <sys/stat.h>   // block size.
#include <sys/mman.h>   // mmap
#include <fcntl.h>      // for open

#include <sys/sysinfo.h>  // for meminfo
#include <type_traits>

#include "partition/range.hpp"
#include "partition/partitioner.hpp"
//#include "io/data_block.hpp"
#include "io/io_exception.hpp"
#include "utils/logging.h"
#include "common/sequence.hpp"
#include <mxx/comm.hpp> // for mxx::comm

namespace bliss
{
namespace io
{
  struct BaseFile {

  };

  // TODO: simplify  possibly by separating L1 and L2 partitioning.

  /**
   * @brief  Partitions input data into sequences, e.g. blocks or reads.
   * @details  Iterator template parameter refers to the iterator type that is currently being traversed.
   * 		 this applies to the sequence object, and the following methods:
   * 		 get_next_record, and find_first_record.
   *
   * 		 init method can potentially use a different iterator type. this is useful when
   * 		   state information is extracted from perhaps a containing block (e.g. L1Block),
   * 		   then used with a sub block (e.g. L2Block).
   *
   * @note   there are 2 (non-interchangeable) scenarios when we may need to change the iterator type.
   *    1. L1 at process level, L2 at thread level.  SeqParser state is calculated at L1.
   *    2. L1 at rank 0 of a sub communicator (processes), L2 is broadcast from rank0 of the rest of processes.  SeqParser state is calculated at L1.
   *
   *    to handle the first case: approaches are
   *    1a. to allow a parser to operate on different iterator types when invoking find_first_record, increment.
   *          additional template parameter for these functions.  SequenceType will need to change.
   *          API in SequenceIterator, BaseFileParser, FASTQParser, FASTAParser all need to change
   *    1b. convert the seq parser from L1 to L2, but copy the state of L1.
   *          can be shared between threads.  additional api for convert only
   *
   *    to handle the second case.
   *    2a. convert the seq parser from L1 to L2, communicate (and copy) the state of L1.
   *          additional api for convert and broadcast. minimal api change. requires L1 to be block (or cyclic with synchronization).
   *    2b. create seq parser for L2, and initialize using all processes.
   *          no api change, but works only when L1 and L2 are block partitioned (or cyclic with synchronization).
   *          potentially less communication, and Parser does not need to have a broadcast semantic.
   *
   *    1a is not general, potentially complicated, and a source of potential errors.
   *    1b and 2a share common apis.
   *    2b requires application to specifically call init at L2.  Also, already initialized L1 during data load.
   *
   *    choose 2b and 1b.  Sequence Iterator does not call init_for_iterator, mostly for flexibility and compatibility with case 1.
   *
   * @tparam Iterator   The underlying iterator to be traversed to generate a Sequence
   *
   */
  template <typename Iterator>
   class BaseFileParser {

      // let another BaseFileParser with some other iterator type be a friend so we can convert.
      template <typename Iterator2>
      friend class BaseFileParser;

     public:
//      using SequenceIdType = SeqIdType;
      using SequenceType = typename ::bliss::common::Sequence<Iterator, ::bliss::common::SequenceId>;
      using SequenceIdType = typename SequenceType::IdType;

      /// static constant for end of line. Iterator note this is same for unicode as well
      static constexpr unsigned char eol = '\n';
      /// static constant for carriage return.  note this is same for unicode as well
      static constexpr unsigned char cr = '\r';

     protected:
       /**
        * @typedef RangeType
        * @brief   range object types
        */
      using RangeType = bliss::partition::range<size_t>;

       /**
        * @brief  search for first non-EOL character in a iterator, returns the stopping position as an iterator.  also records offset.
        * @details       iter can point to the previous EOL, or a nonEOL character.
        * @param[in/out] iter    iterator to advance
        * @param[in]     end     position to stop the traversal
        * @param[in/out] offset  the global offset of the sequence record within the file.  used as record id.
        * @return        iterator at the new position, where the Non EOL char is found, or end.
        */
       template <typename IT = Iterator,
           typename = typename ::std::enable_if<(::std::is_same<typename ::std::iterator_traits<IT>::value_type, char>::value ||
                                                ::std::is_same<typename ::std::iterator_traits<IT>::value_type, unsigned char>::value)
                                               >::type >
       inline IT findNonEOL(IT& iter, const IT& end, size_t &offset) const {
         while ((iter != end) && ((*iter == eol) || (*iter == cr))) {
           ++iter;
           ++offset;
         }
         return iter;
       }

       /**
        * @brief  search for first EOL character in a iterator, returns the stopping position as an iterator.  also records offset.
        * @details       iter can point to a nonEOL char, or an EOL char.
        * @param[in/out] iter    iterator to advance
        * @param[in]     end     position to stop the traversal
        * @param[in/out] offset  the global offset of the sequence record within the file.  used as record id.
        * @return        iterator at the new position, where the EOL char is found, or end.
        */
       template <typename IT = Iterator,
           typename = typename ::std::enable_if<(::std::is_same<typename ::std::iterator_traits<IT>::value_type, char>::value ||
                                                ::std::is_same<typename ::std::iterator_traits<IT>::value_type, unsigned char>::value)
                                               >::type >
       inline IT findEOL(IT& iter, const IT& end, size_t &offset) const {
         while ((iter != end) && ((*iter != eol) && (*iter != cr) ) ) {
           ++iter;
           ++offset;
         }
         return iter;
       }

       /**
        * @brief constructs an IOException object with the relevant debug data.
        * @param errType     string indicating the source of the error.  user choice
        * @param start       iterator pointing to beginning of the data in question
        * @param end         iterator pointing to end of the data in question
        * @param startOffset offset for the beginning of the data in question
        * @param endOffset   offset for the end of the data in question
        */
       void handleError(const std::string& errType, const Iterator &start, const Iterator &end, const size_t& startOffset, const size_t& endOffset) {
         std::stringstream ss;
//#ifdef USE_MPI
//         int rank = 0;
//         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//         ss << "rank: " << rank << " ";
//#endif

         ss << "ERROR: " << errType << " in " << startOffset << " to " << endOffset << std::endl;
         ss << "  offending string is \"";
         std::ostream_iterator<typename std::iterator_traits<Iterator>::value_type> oit(ss);
         std::copy(start, end, oit);
         ss << "\".";
         throw ::std::logic_error(ss.str());
       }

       /**
        * @brief print out an Warning, for example when there is malformed partial data.
        * @param errType     string indicating the source of the error.  user choice
        * @param start       iterator pointing to beginning of the data in question
        * @param end         iterator pointing to end of the data in question
        * @param startOffset offset for the beginning of the data in question
        * @param endOffset   offset for the end of the data in question
        */
       void handleWarning(const std::string& errType, const Iterator &start, const Iterator &end, const size_t& startOffset, const size_t& endOffset) {
         BL_WARNING("WARNING: " << errType << " in " << startOffset << " to " << endOffset);
       }

     public:

       /// default constructor.
       BaseFileParser() {};

       /// default destructor
       virtual ~BaseFileParser() {};

       /// converting constructor.
       template <typename Iterator2>
       BaseFileParser(BaseFileParser<Iterator2> const & other) {}
       /// converting assignment operator that can transform the base iterator type.
       template <typename Iterator2>
       BaseFileParser<Iterator>& operator=(BaseFileParser<Iterator2> const & other) {
         return *this;
       }

       /**
        * @brief given a block/range, find the starting point of the first sequence object (here, just the actual start)
        * @note  virtual function, for convenience.
        *         used by getNextL1BlockRange to find exact range for an L1 Partition.
        *
        *         Also can be used to do other initializations.
        *
        * @param _data
        * @param parentRange
        * @param inMemRange
        * @param searchRange
        * @return
        */
       virtual std::size_t find_first_record(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange)
       {
         //== range checking
         if(!parentRange.contains(inMemRange)) {
           ::std::cout << "parent: " << parentRange << " , in mem: " << inMemRange << ::std::endl;
           throw std::invalid_argument("ERROR: Parent Range does not contain inMemRange");
         }

         // no op, other than to use intersect to make sure that the start is valid and within parent, and in memry ranges.
         return RangeType::intersect(searchRange, inMemRange).start;
       }
#ifdef USE_MPI
       virtual std::size_t find_first_record(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange, const mxx::comm& comm) {
         return find_first_record(_data, parentRange, inMemRange, searchRange);
       }
#endif

       virtual typename RangeType::ValueType find_overlap_end(const Iterator &_data,
    		   const RangeType &parentRange, const RangeType &inMemRange, typename RangeType::ValueType end, size_t overlap ) {
         return std::max(inMemRange.start, std::min(end + overlap, inMemRange.end));
       }

       /// reset any parser internal state so the parser can be reused on a different data range.  overridden in subclass.
       virtual void reset() {}

       virtual bool should_parse(const RangeType & range) {
         return range.size() > 0;
       }
#ifdef USE_MPI
       virtual bool should_parse(const RangeType & range, const mxx::comm & comm) {
         return range.size() > 0;
       }
#endif

       /// initializes parser for a particular data range.  overridden in subclass.  returns start of first record.  _data points to first element in mem.
       virtual std::size_t init_parser(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange) {
         return this->find_first_record(_data, parentRange, inMemRange, searchRange);
       }
#ifdef USE_MPI
       /// initializes the parser.  only useful for FASTA parser for now.  Assumes searchRange do NOT overlap between processes.   _data points to first element in mem.
       virtual std::size_t init_parser(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &searchRange, const mxx::comm& comm)
       {
         return this->find_first_record(_data, parentRange, inMemRange, searchRange);
       };
#endif

       /**
        * @brief increment to get next sequence object
        * @note   not virtual because SequenceType is different for each subclass, so the signatures are different.  We rely on compiler to enforce the correct one.
        *         this is in general not an issue as we do not need polymorphic Sequence Parsers - they are specific to file types.
        *         this is probably better for performance anyways.
        *
        *         Used by FileLoader's getRecordSize to compute an average record size.
        *
        * @param iter           start of a sequence object.  this is the beginning of a record, not just DNA sequence
        * @param end            end of a sequence object.  this is the end of a record, not just DNA sequence
        * @param offset         offset in the file for the start of the record.
        * @param seq_offset     index in the local (shared) vector of sequence breaks, if there is one (e.g. FASTA).  used by FASTA to lookup the nearest complete sequence record info.
        * @param output         updated sequence object.
        * @return               next seq id offset.
        */
       SequenceType get_next_record(Iterator & iter, const Iterator & end, size_t & offset)
       {
         Iterator orig_iter = iter;
         size_t orig_offset = offset;

         size_t dist = std::distance(iter, end);

         offset += dist;
         iter = end;

         return SequenceType(SequenceIdType(orig_offset), dist, 0, 0, orig_iter, end);
       }

       /**
        * @brief   get the average record size in the supplied range
        * @return  return the records size and the internal data size
        */
       virtual ::std::pair<size_t, size_t> get_record_size(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &validRange, size_t const count) {
         size_t dist = validRange.size();
         return ::std::pair<size_t, size_t>(dist,dist);
       }
#ifdef USE_MPI
       virtual ::std::pair<size_t, size_t> get_record_size(const Iterator &_data, const RangeType &parentRange, const RangeType &inMemRange, const RangeType &validRange, mxx::comm const & comm, size_t const count) {
         size_t dist = validRange.size();
         return ::std::pair<size_t, size_t>(dist,dist);
       }
#endif

   };
   /// template class' static variable definition (declared and initialized in class)
  template <typename Iterator>
   constexpr unsigned char bliss::io::BaseFileParser<Iterator >::eol;
  template <typename Iterator>
   constexpr unsigned char bliss::io::BaseFileParser<Iterator>::cr;

  } /* namespace functional */
} /* namespace bliss */
#endif /* FILE_LOADER_HPP_ */
<|endoftext|>


<commit_before><commit_msg>Use more proper types and range-for loops<commit_after><|endoftext|>