<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <assert.h>

XERCES_CPP_NAMESPACE_BEGIN

void* XMemory::operator new(size_t size)
{
	size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
										sizeof(MemoryManager*));

    void* const block = XMLPlatformUtils::fgMemoryManager->allocate
        (
	        headerSize + size
        );
    *(MemoryManager**)block = XMLPlatformUtils::fgMemoryManager;

    return (char*)block + headerSize;
}

#if defined(XML_VISUALCPP)

void* XMemory::operator new(size_t size, const char* file, int line)
{
		 return operator new(size);
}

void XMemory::operator delete(void* p, const char* file, int line)
{
		 operator delete(p);
}

#endif

void* XMemory::operator new(size_t size, MemoryManager* manager)
{
    assert(manager != 0);

	size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
										sizeof(MemoryManager*));
    void* const block = manager->allocate(headerSize + size);
    *(MemoryManager**)block = manager;

    return (char*)block + headerSize;
}

void XMemory::operator delete(void* p)
{
    if (p != 0)
    {
		size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
											sizeof(MemoryManager*));
        void* const block = (char*)p - headerSize;

        MemoryManager* const manager = *(MemoryManager**)block;
        assert(manager != 0);
        manager->deallocate(block);
    }
}

//The HP compiler is complaining about duplicate overloading of delete
#if !defined(XML_HPUX) && !defined(XML_BORLAND)

void XMemory::operator delete(void* p, MemoryManager* manager)
{
    assert(manager != 0);

    if (p != 0)
    {
        size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(MemoryManager*));
        void* const block = (char*)p - headerSize;
        assert(*(MemoryManager**)block == manager);
        /***
         * NOTE: for compiler which can't properly trace the memory manager used in the
         *       placement new, we use the memory manager embedded in the memory rather
         *       than the one passed in
         */
        MemoryManager* pM = *(MemoryManager**)block;
        pM->deallocate(block);
    }
}

#endif

XERCES_CPP_NAMESPACE_END

<commit_msg>do not assert memorymanager in placement delete.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <assert.h>

XERCES_CPP_NAMESPACE_BEGIN

void* XMemory::operator new(size_t size)
{
	size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
										sizeof(MemoryManager*));

    void* const block = XMLPlatformUtils::fgMemoryManager->allocate
        (
	        headerSize + size
        );
    *(MemoryManager**)block = XMLPlatformUtils::fgMemoryManager;

    return (char*)block + headerSize;
}

#if defined(XML_VISUALCPP)

void* XMemory::operator new(size_t size, const char* file, int line)
{
		 return operator new(size);
}

void XMemory::operator delete(void* p, const char* file, int line)
{
		 operator delete(p);
}

#endif

void* XMemory::operator new(size_t size, MemoryManager* manager)
{
    assert(manager != 0);

	size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
										sizeof(MemoryManager*));
    void* const block = manager->allocate(headerSize + size);
    *(MemoryManager**)block = manager;

    return (char*)block + headerSize;
}

void XMemory::operator delete(void* p)
{
    if (p != 0)
    {
		size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(
											sizeof(MemoryManager*));
        void* const block = (char*)p - headerSize;

        MemoryManager* const manager = *(MemoryManager**)block;
        assert(manager != 0);
        manager->deallocate(block);
    }
}

//The HP compiler is complaining about duplicate overloading of delete
#if !defined(XML_HPUX) && !defined(XML_BORLAND)

void XMemory::operator delete(void* p, MemoryManager* manager)
{
    assert(manager != 0);

    if (p != 0)
    {
        size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(MemoryManager*));
        void* const block = (char*)p - headerSize;

        /***
         * assert(*(MemoryManager**)block == manager);
         *
         * NOTE: for compiler which can't properly trace the memory manager used in the
         *       placement new, we use the memory manager embedded in the memory rather
         *       than the one passed in
         */
        MemoryManager* pM = *(MemoryManager**)block;
        pM->deallocate(block);
    }
}

#endif

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>#include <yafray_config.h>
#include <cstdlib>
#include <cctype>
#include <algorithm>

#ifdef WIN32
	#include <windows.h>
#endif

#include <core_api/scene.h>
#include <core_api/environment.h>
#include <core_api/integrator.h>
#include <core_api/imagefilm.h>
#include <yafraycore/xmlparser.h>
#include <yaf_revision.h>
#include <utilities/console_utils.h>
#include <yafraycore/imageOutput.h>

#include <gui/yafqtapi.h>

using namespace::yafaray;

int main(int argc, char *argv[])
{
	std::string xmlLoaderVersion = "YafaRay XML loader version 0.2";

	cliParser_t parse(argc, argv, 2, 1, "You need to set at least a yafaray's valid XML file.");

	parse.setAppName(xmlLoaderVersion,
	"[OPTIONS]... <input xml file> [output filename]\n<input xml file> : A valid yafaray XML file\n[output filename] : The filename of the rendered image without extension.\n*Note: If output filename is ommited the name \"yafaray\" will be used instead.");

	parse.setOption("pp","plugin-path", false, "Path to load plugins.");
	parse.setOption("vl","verbosity-level", false, "Set verbosity level, options are:\n                                       0 - MUTE (Prints nothing)\n                                       1 - ERROR (Prints only errors)\n                                       2 - WARNING (Prints only errors and warnings)\n                                       3 - INFO (Prints all messages)\n");
	parse.parseCommandLine();

#ifdef RELEASE
	std::string version = std::string(VERSION);
#else
	std::string version = std::string(YAF_SVN_REV);
#endif

	renderEnvironment_t *env = new renderEnvironment_t();

	// Plugin load
	std::string ppath = parse.getOptionString("pp");
	int verbLevel = parse.getOptionInteger("vl");

	if(verbLevel >= 0) yafout.setMasterVerbosity(verbLevel);

	if(ppath.empty()) env->getPluginPath(ppath);

	if (!ppath.empty())
	{
		Y_INFO << "The plugin path is: " << ppath << yendl;
		env->loadPlugins(ppath);
	}
	else
	{
		Y_ERROR << "Getting plugin path from render environment failed!" << yendl;
		return 1;
	}

	std::vector<std::string> formats = env->listImageHandlers();

	std::string formatString = "";
	for(size_t i = 0; i < formats.size(); i++)
	{
		formatString.append("                                       " + formats[i]);
		if(i < formats.size() - 1) formatString.append("\n");
	}

	parse.setOption("v","version", true, "Displays this program's version.");
	parse.setOption("h","help", true, "Displays this help text.");
	parse.setOption("op","output-path", false, "Uses the path in <value> as rendered image output path.");
	parse.setOption("o","output-file", false, "Uses the path in <value> as rendered image output filename.");
	parse.setOption("f","format", false, "Sets the output image format, available formats are:\n\n" + formatString + "\n                                       Default: tga.\n");
	parse.setOption("t","threads", false, "Overrides threads setting on the XML file, for auto selection use -1.");
	parse.setOption("a","with-alpha", true, "Enables saving the image with alpha channel.");
	parse.setOption("dp","draw-params", true, "Enables saving the image with a settings badge.");
	parse.setOption("ndp","no-draw-params", true, "Disables saving the image with a settings badge (warning: this overrides --draw-params setting).");
	parse.setOption("cs","custom-string", false, "Sets the custom string to be used on the settings badge.");
	parse.setOption("z","z-buffer", true, "Enables the rendering of the depth map (Z-Buffer) (this flag overrides XML setting).");
	parse.setOption("nz","no-z-buffer", true, "Disables the rendering of the depth map (Z-Buffer) (this flag overrides XML setting).");

	bool parseOk = parse.parseCommandLine();

	if(parse.getFlag("h"))
	{
		parse.printUsage();
		return 0;
	}

	if(parse.getFlag("v"))
	{
		Y_INFO << xmlLoaderVersion << yendl << "Built with YafaRay version " << version << yendl;
		return 0;
	}

	if(!parseOk)
	{
		parse.printError();
		parse.printUsage();
		return 0;
	}

	bool alpha = parse.getFlag("a");
	std::string format = parse.getOptionString("f");
	std::string outputPath = parse.getOptionString("op");
	std::string outputFilename = parse.getOptionString("o");
	int threads = parse.getOptionInteger("t");
	bool drawparams = parse.getFlag("dp");
	bool nodrawparams = parse.getFlag("ndp");
	std::string customString = parse.getOptionString("cs");
	bool zbuf = parse.getFlag("z");
	bool nozbuf = parse.getFlag("nz");

	if(format.empty()) format = "tga";
	bool formatValid = false;

	for(size_t i = 0; i < formats.size(); i++)
	{
		if(formats[i].find(format) != std::string::npos) formatValid = true;
	}

	if(!formatValid)
	{
		Y_ERROR << "Couldn't find any valid image format, image handlers missing?" << yendl;
		return 1;
	}

	const std::vector<std::string> files = parse.getCleanArgs();

	if(files.size() == 0)
	{
		return 0;
	}

    std::string outName;
    if(outputFilename.empty())
        outName = "yafray." + format;
    else
        outName = outputFilename;

	if(files.size() > 1) outName = files[1] + "." + format;

	std::string xmlFile = files[0];

	//env->Debug = debug; //disabled until proper debugging messages are set throughout the core

	// Set the full output path with filename
	if (outputPath.empty())
	{
		outputPath = outName;
	}
	else if (outputPath.at(outputPath.length() - 1) == '/')
	{
		outputPath += outName;
	}
	else if (outputPath.at(outputPath.length() - 1) != '/')
	{
		outputPath += "/" + outName;
	}

	scene_t *scene = new scene_t();
	env->setScene(scene);
	paraMap_t render;

	bool success = parse_xml_file(xmlFile.c_str(), scene, env, render);
	if(!success) exit(1);

	int width=320, height=240;
	int bx = 0, by = 0;
	render.getParam("width", width); // width of rendered image
	render.getParam("height", height); // height of rendered image
	render.getParam("xstart", bx); // border render x start
	render.getParam("ystart", by); // border render y start

	if(threads >= -1) render["threads"] = threads;

	if(drawparams)
	{
		render["drawParams"] = true;
		if(!customString.empty()) render["customString"] = customString;
	}

	if(nodrawparams) render["drawParams"] = false;

	if(zbuf) render["z_channel"] = true;
	if(nozbuf) render["z_channel"] = false;

	bool use_zbuf = false;
	render.getParam("z_channel", use_zbuf);

	// create output
	colorOutput_t *out = NULL;

	paraMap_t ihParams;
	ihParams["type"] = format;
	ihParams["width"] = width;
	ihParams["height"] = height;
	ihParams["alpha_channel"] = alpha;
	ihParams["z_channel"] = use_zbuf;

	imageHandler_t *ih = env->createImageHandler("outFile", ihParams);

	if(ih)
	{
		out = new imageOutput_t(ih, outputPath, bx, by);
		if(!out) return 1;
	}
	else return 1;

	if(! env->setupScene(*scene, render, *out) ) return 1;

	scene->render();
	env->clearAll();

	imageFilm_t *film = scene->getImageFilm();

	delete film;
	delete out;

	return 0;
}
<commit_msg>Review code from 'rubdos' patch:     - set only the file name, the extension is set with parsing 'f' option<commit_after>#include <yafray_config.h>
#include <cstdlib>
#include <cctype>
#include <algorithm>

#ifdef WIN32
	#include <windows.h>
#endif

#include <core_api/scene.h>
#include <core_api/environment.h>
#include <core_api/integrator.h>
#include <core_api/imagefilm.h>
#include <yafraycore/xmlparser.h>
#include <yaf_revision.h>
#include <utilities/console_utils.h>
#include <yafraycore/imageOutput.h>

#include <gui/yafqtapi.h>

using namespace::yafaray;

int main(int argc, char *argv[])
{
	std::string xmlLoaderVersion = "YafaRay XML loader version 0.2";

	cliParser_t parse(argc, argv, 2, 1, "You need to set at least a yafaray's valid XML file.");

	parse.setAppName(xmlLoaderVersion,
		"[OPTIONS]... <input xml file> [output filename]\n<input xml file> : A valid yafaray XML file\n[output filename] : The filename of the rendered image without extension.\n*Note: If output filename is ommited the name \"yafaray\" will be used instead.");

	parse.setOption("pp", "plugin-path", false, "Path to load plugins.");
	parse.setOption("vl", "verbosity-level", false, "Set verbosity level, options are:\n                                       0 - MUTE (Prints nothing)\n                                       1 - ERROR (Prints only errors)\n                                       2 - WARNING (Prints only errors and warnings)\n                                       3 - INFO (Prints all messages)\n");
	parse.parseCommandLine();

#ifdef RELEASE
	std::string version = std::string(VERSION);
#else
	std::string version = std::string(YAF_SVN_REV);
#endif

	renderEnvironment_t *env = new renderEnvironment_t();

	// Plugin load
	std::string ppath = parse.getOptionString("pp");
	int verbLevel = parse.getOptionInteger("vl");

	if (verbLevel >= 0) yafout.setMasterVerbosity(verbLevel);

	if (ppath.empty()) env->getPluginPath(ppath);

	if (!ppath.empty())
	{
		Y_INFO << "The plugin path is: " << ppath << yendl;
		env->loadPlugins(ppath);
	}
	else
	{
		Y_ERROR << "Getting plugin path from render environment failed!" << yendl;
		return 1;
	}

	std::vector<std::string> formats = env->listImageHandlers();

	std::string formatString = "";
	for (size_t i = 0; i < formats.size(); i++)
	{
		formatString.append("                                       " + formats[i]);
		if (i < formats.size() - 1) formatString.append("\n");
	}

	parse.setOption("v", "version", true, "Displays this program's version.");
	parse.setOption("h", "help", true, "Displays this help text.");
	parse.setOption("op", "output-path", false, "Uses the path in <value> as rendered image output path.");
	parse.setOption("o", "output-file", false, "Uses the path in <value> as rendered image output filename.");
	parse.setOption("f", "format", false, "Sets the output image format, available formats are:\n\n" + formatString + "\n                                       Default: tga.\n");
	parse.setOption("t", "threads", false, "Overrides threads setting on the XML file, for auto selection use -1.");
	parse.setOption("a", "with-alpha", true, "Enables saving the image with alpha channel.");
	parse.setOption("dp", "draw-params", true, "Enables saving the image with a settings badge.");
	parse.setOption("ndp", "no-draw-params", true, "Disables saving the image with a settings badge (warning: this overrides --draw-params setting).");
	parse.setOption("cs", "custom-string", false, "Sets the custom string to be used on the settings badge.");
	parse.setOption("z", "z-buffer", true, "Enables the rendering of the depth map (Z-Buffer) (this flag overrides XML setting).");
	parse.setOption("nz", "no-z-buffer", true, "Disables the rendering of the depth map (Z-Buffer) (this flag overrides XML setting).");

	bool parseOk = parse.parseCommandLine();

	if (parse.getFlag("h"))
	{
		parse.printUsage();
		return 0;
	}

	if (parse.getFlag("v"))
	{
		Y_INFO << xmlLoaderVersion << yendl << "Built with YafaRay version " << version << yendl;
		return 0;
	}

	if (!parseOk)
	{
		parse.printError();
		parse.printUsage();
		return 0;
	}

	bool alpha = parse.getFlag("a");
	std::string format = parse.getOptionString("f");
	std::string outputPath = parse.getOptionString("op");
	std::string outputFilename = parse.getOptionString("o");
	int threads = parse.getOptionInteger("t");
	bool drawparams = parse.getFlag("dp");
	bool nodrawparams = parse.getFlag("ndp");
	std::string customString = parse.getOptionString("cs");
	bool zbuf = parse.getFlag("z");
	bool nozbuf = parse.getFlag("nz");

	if (format.empty()) format = "tga";
	bool formatValid = false;

	for (size_t i = 0; i < formats.size(); i++)
	{
		if (formats[i].find(format) != std::string::npos) formatValid = true;
	}

	if (!formatValid)
	{
		Y_ERROR << "Couldn't find any valid image format, image handlers missing?" << yendl;
		return 1;
	}

	const std::vector<std::string> files = parse.getCleanArgs();

	if (files.size() == 0)
	{
		return 0;
	}

	std::string outName;
	if (outputFilename.empty())
	{
		outName = "yafray." + format;
	}
	else
	{
		outName = outputFilename + "." + format;
	}

	if(files.size() > 1) outName = files[1] + "." + format;

	std::string xmlFile = files[0];

	//env->Debug = debug; //disabled until proper debugging messages are set throughout the core

	// Set the full output path with filename
	if (outputPath.empty())
	{
		outputPath = outName;
	}
	else if (outputPath.at(outputPath.length() - 1) == '/')
	{
		outputPath += outName;
	}
	else if (outputPath.at(outputPath.length() - 1) != '/')
	{
		outputPath += "/" + outName;
	}

	scene_t *scene = new scene_t();
	env->setScene(scene);
	paraMap_t render;

	bool success = parse_xml_file(xmlFile.c_str(), scene, env, render);
	if(!success) exit(1);

	int width=320, height=240;
	int bx = 0, by = 0;
	render.getParam("width", width); // width of rendered image
	render.getParam("height", height); // height of rendered image
	render.getParam("xstart", bx); // border render x start
	render.getParam("ystart", by); // border render y start

	if(threads >= -1) render["threads"] = threads;

	if(drawparams)
	{
		render["drawParams"] = true;
		if(!customString.empty()) render["customString"] = customString;
	}

	if(nodrawparams) render["drawParams"] = false;

	if(zbuf) render["z_channel"] = true;
	if(nozbuf) render["z_channel"] = false;

	bool use_zbuf = false;
	render.getParam("z_channel", use_zbuf);

	// create output
	colorOutput_t *out = NULL;

	paraMap_t ihParams;
	ihParams["type"] = format;
	ihParams["width"] = width;
	ihParams["height"] = height;
	ihParams["alpha_channel"] = alpha;
	ihParams["z_channel"] = use_zbuf;

	imageHandler_t *ih = env->createImageHandler("outFile", ihParams);

	if(ih)
	{
		out = new imageOutput_t(ih, outputPath, bx, by);
		if(!out) return 1;
	}
	else return 1;

	if(! env->setupScene(*scene, render, *out) ) return 1;

	scene->render();
	env->clearAll();

	imageFilm_t *film = scene->getImageFilm();

	delete film;
	delete out;

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <getopt.h>
#include "fieldpropertiesdb.h"
#include "streamanalyzer.h"
#include "analyzerconfiguration.h"
using namespace std;
using namespace Strigi;

void
printDot(ostream& out, const char* locale) {
    const map<string, FieldProperties>& p
        = FieldPropertiesDb::db().allProperties();
    map<string, FieldProperties>::const_iterator i;
    out << "digraph {" << endl;
    for (i = p.begin(); i != p.end(); ++i) {
        const vector<string>& parents = i->second.parentUris();
        vector<string>::const_iterator j;
        for (j = parents.begin(); j != parents.end(); ++j) {
            out << '"' << *j << "\"->\"" << i->second.uri() << '"' << endl;
        }
    }
    out << "}" << endl;
}
void
printRdfsProperties(ostream& out, const FieldProperties& p) {
    out << " <rdf:Property rdf:about='" << p.uri() << "'>\n"
        << "  <rdfs:label>" << p.name() << "</rdfs:label>\n"
        << "  <rdfs:comment>" << p.description() << "</rdfs:comment>\n";
    const vector<string>& parents = p.parentUris();
    vector<string>::const_iterator j;
    for (j = parents.begin(); j != parents.end(); ++j) {
        out << "  <rdfs:subPropertyOf rdf:resource='" << *j << "'/>\n";
    }
    out << "  <rdfs:range rdf:resource='" << p.typeUri() << "'/>\n";
    const map<string, FieldProperties::Localized>& l = p.localized();
    map<string, FieldProperties::Localized>::const_iterator k;
    for (k = l.begin(); k != l.end(); ++k) {
        out << "  <rdfs:label xml:lang='" << k->first << "'>" << k->second.name
            << "</rdfs:label>\n";
        out << "  <rdfs:comment xml:lang='" << k->first << "'>"
            << k->second.description << "</rdfs:comment>\n";
    }
    out << "  <rdfs:domain rdf:resource='&strigi;file'/>\n"
        << " </rdf:Property>\n";
}

void
printRdfs(ostream& out) {
    out << "<?xml version='1.0' encoding='UTF-8'?>\n"
        "<!DOCTYPE rdf:RDF [\n"
        "    <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
        "    <!ENTITY strigi 'http://strigi URL goes here#'>\n"
        "    <!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>\n"
        "]>\n"
        "<rdf:RDF "
            "xmlns:rdf='&rdf;' xmlns:strigi='&strigi;' xmlns:rdfs='&rdfs;'>\n";

    const map<string, FieldProperties>& p
        = FieldPropertiesDb::db().allProperties();
    map<string, FieldProperties>::const_iterator i;
    for (i = p.begin(); i != p.end(); ++i) {
        printRdfsProperties(out, i->second);
    }
    out << "</rdf:RDF>" << endl;
}
void
printHelp(const char* program) {
    cerr << "Usage: " << program << " [--type=<type>] [--locale=<locale>]"
        << endl;
}

int
main(int argc, char** argv) {
    struct option long_options[] = {
        {"help",   no_argument,       0, 0},
        {"type",   required_argument, 0, 0},
        {"locale", required_argument, 0, 0}
    };
    const char* type = 0;
    const char* locale = 0;
    bool help = false;
    while (1) {
        int optindex;
        int c = getopt_long_only(argc, argv, "", long_options, &optindex);
        if (c == -1) break;
        if (c == 0) {
            if (optindex == 1) type   = optarg;
            if (optindex == 2) locale = optarg;
        }
        switch (c) {
        case '?':
            printHelp(argv[0]);
            exit(1);
        default:
            break;
        }
        printf("%i %i %s\n", c, optindex, optarg);
    }

    // load the plugins
    AnalyzerConfiguration ac;
    StreamAnalyzer s(ac);

    if (help) {
        printHelp(argv[0]);
    } else if (type && strcmp(type, "dot") == 0) {
        printDot(cout, locale);
    } else {
        printRdfs(cout);
    }
    return 0;
}
<commit_msg>fuller graphviz output for the field hierarchy<commit_after>#include <iostream>
#include <unistd.h>
#include <getopt.h>
#include "fieldpropertiesdb.h"
#include "streamanalyzer.h"
#include "analyzerconfiguration.h"
using namespace std;
using namespace Strigi;

void
printDot(ostream& out, const char* locale) {
    const map<string, FieldProperties>& p
        = FieldPropertiesDb::db().allProperties();
    map<string, FieldProperties>::const_iterator i;
    out << "digraph{graph[rankdir=LR];" << endl;
    for (i = p.begin(); i != p.end(); ++i) {
        const vector<string>& parents = i->second.parentUris();
        vector<string>::const_iterator j;
        out << '"' << i->second.uri() << "\" [shape=record];" << endl;
        for (j = parents.begin(); j != parents.end(); ++j) {
            out << '"' << *j << "\"->\"" << i->second.uri() << '"' << endl;
        }
    }
    out << "}" << endl;
}
void
printRdfsProperties(ostream& out, const FieldProperties& p) {
    out << " <rdf:Property rdf:about='" << p.uri() << "'>\n"
        << "  <rdfs:label>" << p.name() << "</rdfs:label>\n"
        << "  <rdfs:comment>" << p.description() << "</rdfs:comment>\n";
    const vector<string>& parents = p.parentUris();
    vector<string>::const_iterator j;
    for (j = parents.begin(); j != parents.end(); ++j) {
        out << "  <rdfs:subPropertyOf rdf:resource='" << *j << "'/>\n";
    }
    out << "  <rdfs:range rdf:resource='" << p.typeUri() << "'/>\n";
    const map<string, FieldProperties::Localized>& l = p.localized();
    map<string, FieldProperties::Localized>::const_iterator k;
    for (k = l.begin(); k != l.end(); ++k) {
        out << "  <rdfs:label xml:lang='" << k->first << "'>" << k->second.name
            << "</rdfs:label>\n";
        out << "  <rdfs:comment xml:lang='" << k->first << "'>"
            << k->second.description << "</rdfs:comment>\n";
    }
    out << "  <rdfs:domain rdf:resource='&strigi;file'/>\n"
        << " </rdf:Property>\n";
}

void
printRdfs(ostream& out) {
    out << "<?xml version='1.0' encoding='UTF-8'?>\n"
        "<!DOCTYPE rdf:RDF [\n"
        "    <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
        "    <!ENTITY strigi 'http://strigi URL goes here#'>\n"
        "    <!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>\n"
        "]>\n"
        "<rdf:RDF "
            "xmlns:rdf='&rdf;' xmlns:strigi='&strigi;' xmlns:rdfs='&rdfs;'>\n";

    const map<string, FieldProperties>& p
        = FieldPropertiesDb::db().allProperties();
    map<string, FieldProperties>::const_iterator i;
    for (i = p.begin(); i != p.end(); ++i) {
        printRdfsProperties(out, i->second);
    }
    out << "</rdf:RDF>" << endl;
}
void
printHelp(const char* program) {
    cerr << "Usage: " << program << " [--type=<type>] [--locale=<locale>]"
        << endl;
}
int
main(int argc, char** argv) {
    struct option long_options[] = {
        {"help",   no_argument,       0, 0},
        {"type",   required_argument, 0, 0},
        {"locale", required_argument, 0, 0}
    };
    const char* type = 0;
    const char* locale = 0;
    bool help = false;
    while (1) {
        int optindex;
        int c = getopt_long_only(argc, argv, "", long_options, &optindex);
        if (c == -1) break;
        if (c == 0) {
            if (optindex == 0) help = true;
            if (optindex == 1) type   = optarg;
            if (optindex == 2) locale = optarg;
        }
        switch (c) {
        case '?':
            printHelp(argv[0]);
            exit(1);
        default:
            break;
        }
    }

    // load the plugins
    AnalyzerConfiguration ac;
    StreamAnalyzer s(ac);

    if (help) {
        printHelp(argv[0]);
    } else if (type && strcmp(type, "dot") == 0) {
        printDot(cout, locale);
    } else {
        printRdfs(cout);
    }
    return 0;
}
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetRecoImageToolsTests
#include <boost/test/unit_test.hpp>
#include <vector>
#include <utility>
#include <fstream>
#include <iostream>

#include "./JPetRecoImageTools.h"
#include "../../JPetCommonTools/JPetCommonTools.h"

BOOST_AUTO_TEST_SUITE(FirstSuite)

BOOST_AUTO_TEST_CASE(rescale_0)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {3, 0}, {0, 0}};
  double resFact = 5;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 5, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {2, 1}, {1, 1}};
  double resFact = 2;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 2, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale_2)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {5, 2}, {1, 2}};
  double resFact = 2;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 2, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0.5, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0.5, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale_3)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {5, 3}, {1, 2}};
  double resFact = 8;
  double minCutoff = 2; /// -> 5, 3 , 2, 2
  /// after background subtraction 3, 1, 0,0
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 8, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 1. * 8. / 3., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0 * 8. / 3., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}
BOOST_AUTO_TEST_CASE(matrixGetterFactoryTest)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  BOOST_REQUIRE_CLOSE(getter(0, 0), 1, epsilon);
  BOOST_REQUIRE_CLOSE(getter(0, 1), 2, epsilon);
  BOOST_REQUIRE_CLOSE(getter(1, 0), 3, epsilon);
  BOOST_REQUIRE_CLOSE(getter(1, 1), 4, epsilon);
  BOOST_REQUIRE_CLOSE(getter(3, 3), 0, epsilon); /// out of range should return 0
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  BOOST_REQUIRE_CLOSE(getterT(0, 0), 1, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(0, 1), 3, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(1, 0), 2, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(1, 1), 4, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(3, 3), 0, epsilon); /// out of range should return 0
}

BOOST_AUTO_TEST_CASE(nearestNeighbour)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  /// first argument is i second j  (i,j)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0, getter), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0, getter), 3, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.6, getter), 2, epsilon); // (0,1)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.4, getter), 1, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.4, getter), 3, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.8, getter), 4, epsilon); // (0,0)
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  /// first argument is j second i  (j,i)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0, getterT), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0, getterT), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.6, getterT), 3, epsilon); // (1,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.4, getterT), 1, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.4, getterT), 2, epsilon); // (0,1)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.8, getterT), 4, epsilon); // (1,1)
}

BOOST_AUTO_TEST_CASE(linear)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  /// first argument is i second j  (i,j)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0, getter), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 1, getter), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.9, getter), 1.9, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0, getter), 3, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.4, getter), 1.4, epsilon); // 1 * 0.6 + 2 * 0.4
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0.4, getter), 3.4, epsilon); //  3* 0.6 + 4 * 0.4
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  /// first argument is j second i  (j,i)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0, getterT), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0, getterT), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.6, getterT), 2.2, epsilon); //1*0.4 +  3  *0.6
}

//BOOST_AUTO_TEST_CASE(calculateProjection)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{4}};
////static double calculateProjection(const Matrix2D& emissionMatrix,
////double phi,
////int scanNumber,
////int nScans,
////InterpolationFunc& interpolationFunction
////);
///// first argument is i second j  (i,j)
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,0,0,1, func), 4, epsilon);
//}

//BOOST_AUTO_TEST_CASE(calculateProjection2)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
////static double calculateProjection(const Matrix2D& emissionMatrix,
////double phi,
////int scanNumber,
////int nScans,
////InterpolationFunc& interpolationFunction
////);
///// first argument is i second j  (i,j)
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::linear;
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,0,0,1, func), 4, epsilon);
//}

//BOOST_AUTO_TEST_CASE(ONE_POINT_MATRIX_NOT_IN_CENTER)
//{
//std::vector<std::vector<int>> m(4, std::vector<int>(4));
//for (unsigned int i = 0; i < 4; i++) {
//for (unsigned int j = 0; j < 4; j++) {
//m[i][j] = 0;
//}
//}
//m[2][2] = 100;
//int views = 2;
//int scans = 4;
//std::vector<std::vector<double>> result = JPetRecoImageTools::sinogram(m, views, scans);
//for (int i = 0; i < views; i++) {
//for (int j = 0; j < scans; j++) {
//if ((i == 0 && j == 2) || (i == 1 && j == 1))
//BOOST_REQUIRE_EQUAL(result[i][j], 100);
//else
//BOOST_REQUIRE_EQUAL(result[i][j], 0);
//}
//}
//}

//BOOST_AUTO_TEST_CASE(ONE_POINT_MATRIX_NOT_IN_CENTER_2)
//{
//std::vector<std::vector<int>> m(4, std::vector<int>(4));
//for (unsigned int i = 0; i < 4; i++) {
//for (unsigned int j = 0; j < 4; j++) {
//m[i][j] = 0;
//}
//}
//m[2][2] = 100;
//int views = 2;
//int scans = 4;
//std::vector<std::vector<double>> result2 = JPetRecoImageTools::sinogram(m, views, scans, 0, 180,  JPetRecoImageTools::nearestNeighbour);
//for (int i = 0; i < views; i++) {
//for (int j = 0; j < scans; j++) {
//if ((i == 0 && j == 2) || (i == 1 && j == 1))
//BOOST_REQUIRE_EQUAL(result2[i][j], 100);
//else
//BOOST_REQUIRE_EQUAL(result2[i][j], 0);
//}
//}
//}

/// This test takes a Shepp-Logan phantom and creates a sinogram.
BOOST_AUTO_TEST_CASE(sinogram)
{
  const auto inFile = "unitTestData/JPetSinogramTest/phantom.pgm";
  const auto outFile = "sinogram.ppm";
  /// read phantom
  std::ifstream in(inFile);
  BOOST_REQUIRE(in);
  std::string line;
  getline(in, line);
  unsigned int width;
  unsigned int height;
  in >> width;
  in >> height;
  int val;
  in >> val; // skip max val
  std::vector<std::vector<int>> m(width, std::vector<int>(height));
  for (unsigned int i = 0; i < width; i++) {
    for (unsigned int j = 0; j < height; j++) {
      in >> val;
      m[i][j] = val;
    }
  }
  int views = 180;
  int scans = 256;
  std::vector<std::vector<double>> result = JPetRecoImageTools::sinogram(m, views, scans, 0, 180, JPetRecoImageTools::linear, JPetRecoImageTools::rescale);
  /// save sinogram
  std::ofstream res(outFile);
  res << "P2" << std::endl;
  res << scans << " " << views << std::endl;
  res << "255" << std::endl;
  for (int i = 0; i < views; i++) {
    for (int j = 0; j < scans; j++) {
      res << static_cast<int>(result[i][j]) << " ";
    }
    res << std::endl;
  }
  res.close();
  BOOST_REQUIRE(JPetCommonTools::ifFileExisting(outFile));
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Add more tests.<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetRecoImageToolsTests
#include <boost/test/unit_test.hpp>
#include <vector>
#include <utility>
#include <fstream>
#include <iostream>

#include "./JPetRecoImageTools.h"
#include "../../JPetCommonTools/JPetCommonTools.h"

BOOST_AUTO_TEST_SUITE(FirstSuite)

BOOST_AUTO_TEST_CASE(rescale_0)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {3, 0}, {0, 0}};
  double resFact = 5;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 5, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {2, 1}, {1, 1}};
  double resFact = 2;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 2, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale_2)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {5, 2}, {1, 2}};
  double resFact = 2;
  double minCutoff = 0;
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 2, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 0.5, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0.5, epsilon );
}

BOOST_AUTO_TEST_CASE(rescale_3)
{
  JPetRecoImageTools::Matrix2DProj matrix = { {5, 3}, {1, 2}};
  double resFact = 8;
  double minCutoff = 2; /// -> 5, 3 , 2, 2
  /// after background subtraction 3, 1, 0,0
  double epsilon = 0.00001;
  JPetRecoImageTools::rescale(matrix, minCutoff, resFact);
  BOOST_REQUIRE_CLOSE(matrix[0][0], 8, epsilon );
  BOOST_REQUIRE_CLOSE(matrix[0][1], 1. * 8. / 3., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][0], 0 * 8. / 3., epsilon );
  BOOST_REQUIRE_CLOSE(matrix[1][1], 0, epsilon );
}
BOOST_AUTO_TEST_CASE(matrixGetterFactoryTest)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  BOOST_REQUIRE_CLOSE(getter(0, 0), 1, epsilon);
  BOOST_REQUIRE_CLOSE(getter(0, 1), 2, epsilon);
  BOOST_REQUIRE_CLOSE(getter(1, 0), 3, epsilon);
  BOOST_REQUIRE_CLOSE(getter(1, 1), 4, epsilon);
  BOOST_REQUIRE_CLOSE(getter(3, 3), 0, epsilon); /// out of range should return 0
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  BOOST_REQUIRE_CLOSE(getterT(0, 0), 1, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(0, 1), 3, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(1, 0), 2, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(1, 1), 4, epsilon);
  BOOST_REQUIRE_CLOSE(getterT(3, 3), 0, epsilon); /// out of range should return 0
}

BOOST_AUTO_TEST_CASE(nearestNeighbour)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  /// first argument is i second j  (i,j)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0, getter), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0, getter), 3, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.6, getter), 2, epsilon); // (0,1)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.4, getter), 1, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.4, getter), 3, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.8, getter), 4, epsilon); // (0,0)
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  /// first argument is j second i  (j,i)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0, getterT), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0, getterT), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.6, getterT), 3, epsilon); // (1,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(0, 0.4, getterT), 1, epsilon); // (0,0)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.4, getterT), 2, epsilon); // (0,1)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::nearestNeighbour(1, 0.8, getterT), 4, epsilon); // (1,1)
}

BOOST_AUTO_TEST_CASE(linear)
{
  double epsilon = 0.00001;
  JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
  auto getter =  JPetRecoImageTools::matrixGetterFactory(matrix, false);
  /// first argument is i second j  (i,j)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0, getter), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 1, getter), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.9, getter), 1.9, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0, getter), 3, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.4, getter), 1.4, epsilon); // 1 * 0.6 + 2 * 0.4
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0.4, getter), 3.4, epsilon); //  3* 0.6 + 4 * 0.4
  auto getterT =  JPetRecoImageTools::matrixGetterFactory(matrix, true); /// transposed
  /// first argument is j second i  (j,i)
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0, getterT), 1, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(1, 0, getterT), 2, epsilon);
  BOOST_REQUIRE_CLOSE(JPetRecoImageTools::linear(0, 0.6, getterT), 2.2, epsilon); //1*0.4 +  3  *0.6
}

//BOOST_AUTO_TEST_CASE(calculateProjection)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{4}};
////static double calculateProjection(const Matrix2D& emissionMatrix,
////double phi,
////int scanNumber,
////int nScans,
////InterpolationFunc& interpolationFunction
////);
///// first argument is i second j  (i,j)
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,0,0,1, func), 4, epsilon);
//}

//BOOST_AUTO_TEST_CASE(calculateProjection2)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{1, 2}, {3, 4}};
///// 1 2
///// 3 4
///// angle = 0
///// nScans = 2
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//const int kNScans = 2;
//auto angle = 0.0;
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,0,kNScans, func), 4, epsilon);
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,1,kNScans, func), 4, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,1,kNScans, func), 6, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,45,0,1, func), 4, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,90,0,kNScans, func), 3, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,125,0,1, func), 4, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,180,0,1, func), 4, epsilon);
//}

//BOOST_AUTO_TEST_CASE(calculateProjection3)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{1, 2, 3}, {4, 5, 6}, {7,8,9}};
///// 1 2 3
///// 4 5 6
///// 7 8 9
///// angle = 0
///// nScans = 3
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//const int kNScans = 3;
//auto angle = 0.0;
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,0,kNScans, func), 12, epsilon);
//BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,1,kNScans, func), 15, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,angle,1,kNScans, func), 6, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,45,0,1, func), 4, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,90,0,kNScans, func), 3, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,125,0,1, func), 4, epsilon);
////BOOST_REQUIRE_CLOSE(JPetRecoImageTools::calculateProjection(matrix,180,0,1, func), 4, epsilon);
//}

//BOOST_AUTO_TEST_CASE(sinogram1)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{1, 2, 3}, {4, 5, 6}, {7,8,9}};
///// 1 2 3
///// 4 5 6
///// 7 8 9
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//JPetRecoImageTools::RescaleFunc func2= JPetRecoImageTools::nonRescale;
//const int kNScans = 3;
//const int kNViews = 2;
//auto results = JPetRecoImageTools::sinogram(matrix,kNViews,kNScans, 0 , 90,  func, func2);
//for (auto i: results)
//for (auto j: i)
//std::cout <<j <<std::endl;
//}

//BOOST_AUTO_TEST_CASE(sinogram2)
//{
//double epsilon = 0.00001;
//JPetRecoImageTools::Matrix2D matrix = {{0, 0, 0}, {0, 10, 0}, {0,0,0}};
//JPetRecoImageTools::InterpolationFunc func = JPetRecoImageTools::nearestNeighbour;
//JPetRecoImageTools::RescaleFunc func2= JPetRecoImageTools::nonRescale;
//const int kNScans = 3;
//const int kNViews = 4;
//auto results = JPetRecoImageTools::sinogram(matrix,kNViews,kNScans, 0 , 180,  func, func2);
//for (auto i: results)
//for (auto j: i)
//std::cout <<j <<std::endl;
//}

// This test takes a Shepp-Logan phantom and creates a sinogram.
BOOST_AUTO_TEST_CASE(sinogram)
{
  const auto inFile = "unitTestData/JPetRecoImageToolsTest/phantom.pgm";
  const auto outFile = "sinogram.ppm";
  /// read phantom
  std::ifstream in(inFile);
  BOOST_REQUIRE(in);
  std::string line;
  getline(in, line);
  unsigned int width;
  unsigned int height;
  in >> width;
  in >> height;
  int val;
  in >> val; // skip max val
  std::vector<std::vector<int>> m(width, std::vector<int>(height));
  for (unsigned int i = 0; i < width; i++) {
    for (unsigned int j = 0; j < height; j++) {
      in >> val;
      m[i][j] = val;
    }
  }
  int views = 180;
  int scans = 256;
  std::vector<std::vector<double>> result = JPetRecoImageTools::sinogram(m, views, scans, 0, 180, JPetRecoImageTools::linear, JPetRecoImageTools::rescale);
  /// save sinogram
  std::ofstream res(outFile);
  res << "P2" << std::endl;
  res << scans << " " << views << std::endl;
  res << "255" << std::endl;
  for (int i = 0; i < views; i++) {
    for (int j = 0; j < scans; j++) {
      res << static_cast<int>(result[i][j]) << " ";
    }
    res << std::endl;
  }
  res.close();
  BOOST_REQUIRE(JPetCommonTools::ifFileExisting(outFile));
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before><commit_msg>fix incorrect string conversion in 9e310cc32923ceb4b18d97ce68d54a339b935f01<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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
 * @brief IronBee --- CLIPP Parse Modifier Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include "parse_modifier.hpp"

#include <boost/spirit/include/qi.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/function.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>

using namespace std;

namespace IronBee {
namespace CLIPP {

namespace {

typedef boost::iterator_range<const char*> span_t;
typedef boost::tuple<span_t, span_t> two_span_t;
typedef boost::tuple<span_t, span_t, span_t> three_span_t;

Input::Buffer to_buffer(const span_t& span)
{
    if (span.empty()) {
        return Input::Buffer();
    }
    return Input::Buffer(span.begin(), span.size());
}

span_t from_buffer(const Input::Buffer& buffer)
{
    return span_t(buffer.data, buffer.data + buffer.length);
}

// Read until \n or \r\n.
// Updates @a span to start just after line.
span_t fetch_line(span_t& span)
{
    using namespace boost::spirit::qi;

    span_t line;

    const char* new_begin = span.begin();
    bool success = parse(
        new_begin, span.end(),
        raw[*(ascii::char_ - ascii::char_("\n"))]
            >> omit["\n"],
        line
    );
    if (success) {
        span = span_t(new_begin, span.end());
        const char* end = line.end();
        assert(end > line.begin());
        if (*(end-1) == '\r') {
            --end;
        }
        return span_t(line.begin(), end);
    }
    else {
        // No end of line, return entire buffer as line.
        span = span_t(span.end(), span.end());
        return span_t(new_begin, span.end());
    }
    // unreachable
}

three_span_t parse_first_line(const span_t& span)
{
    using namespace boost::spirit::qi;

    three_span_t result;
    // Parse should only fail on an empty span in which case an empty
    // result is fine.
    parse(
        span.begin(), span.end(),
        omit[*space] >>
        raw[+(ascii::char_-' ')] >> omit[*space] >>
        raw[*(ascii::char_-' ')] >> omit[*space] >>
        raw[*ascii::char_] >> omit[*space],
        result
    );

    return result;
}

two_span_t parse_header(const span_t& span)
{
    using namespace boost::spirit::qi;

    two_span_t result;
    // Parse should never fail.
    bool success = parse(
        span.begin(), span.end(),
        raw[*(ascii::char_ - ':')] >>
            -(omit[lit(':') >> *space] >> raw[+ascii::char_]),
        result
    );
    if (! success) {
        throw logic_error(
            "Insanity error: Parse header fialed."
            "Please report as bug."
        );
    }

    return result;
}

template <typename StartEventType>
three_span_t convert_first_line(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       start_event,
    double               pre_delay
)
{
    span_t current_line = fetch_line(input);
    three_span_t info = parse_first_line(current_line);
    events.push_back(
        boost::make_shared<StartEventType>(
            start_event,
            to_buffer(current_line),
            to_buffer(info.get<0>()),
            to_buffer(info.get<1>()),
            to_buffer(info.get<2>())
        )
    );
    events.back()->pre_delay = pre_delay;

    return info;
}

void convert_headers(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       header_event,
    Input::event_e       header_finished_event
)
{
    Input::header_list_t headers;
    const char* begin = input.begin();
    ParseModifier::parse_header_block(headers, begin, input.end());
    input = span_t(begin, input.end());
    if (! headers.empty()) {
        boost::shared_ptr<Input::HeaderEvent> specific =
            boost::make_shared<Input::HeaderEvent>(header_event);
        specific->headers.swap(headers);
        events.push_back(specific);
    }
    events.push_back(
        boost::make_shared<Input::NullEvent>(header_finished_event)
    );
}

void convert_remainder(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       body_event,
    Input::event_e       finished_event,
    double               pre_delay,
    double               post_delay
)
{
    events.push_back(
        boost::make_shared<Input::DataEvent>(body_event, to_buffer(input))
    );
    events.back()->pre_delay = pre_delay;
    pre_delay = 0;

    events.push_back(
        boost::make_shared<Input::NullEvent>(finished_event)
    );
    events.back()->pre_delay  = pre_delay;
    events.back()->post_delay = post_delay;
}

struct data_t
{
    boost::any old_source;
    Input::transaction_list_t transactions;
};

}

bool ParseModifier::operator()(Input::input_p& input)
{
    if (! input) {
        return true;
    }

    boost::shared_ptr<data_t> data = boost::make_shared<data_t>();
    data->old_source   = input->source;
    data->transactions = input->connection.transactions;
    input->source      = data;

    Input::transaction_list_t new_transactions;
    enum last_seen_e {
        NOTHING,
        IN,
        OUT
    };
    last_seen_e last_seen = NOTHING;
    bool is_http09 = false;
    BOOST_FOREACH(Input::Transaction& tx, input->connection.transactions) {
        new_transactions.push_back(Input::Transaction());
        Input::Transaction& new_tx = new_transactions.back();
        BOOST_FOREACH(const Input::event_p& event, tx.events) {
            switch (event->which) {
                case Input::CONNECTION_DATA_IN: {
                    if (last_seen == IN) {
                        throw runtime_error(
                            "@parse does not support repeated connection "
                            "data in events."
                        );
                    }
                    last_seen = IN;
                    Input::DataEvent& specific =
                        dynamic_cast<Input::DataEvent&>(
                            *event
                        );
                    span_t input = from_buffer(specific.data);
                    three_span_t info =
                        convert_first_line<Input::RequestEvent>(
                            new_tx.events,
                            input,
                            Input::REQUEST_STARTED,
                            specific.pre_delay
                        );
                    is_http09 = info.get<2>().empty();

                    if (! is_http09) {
                        convert_headers(
                            new_tx.events,
                            input,
                            Input::REQUEST_HEADER,
                            Input::REQUEST_HEADER_FINISHED
                        );
                    }
                    else {
                        new_tx.events.push_back(
                            boost::make_shared<Input::HeaderEvent>(Input::REQUEST_HEADER)
                        );
                        new_tx.events.push_back(
                            boost::make_shared<Input::NullEvent>(Input::REQUEST_HEADER_FINISHED)
                        );
                    }

                    convert_remainder(
                        new_tx.events,
                        input,
                        Input::REQUEST_BODY,
                        Input::REQUEST_FINISHED,
                        0,
                        specific.post_delay
                    );
                    break;
                }
                case Input::CONNECTION_DATA_OUT: {
                    if (last_seen == OUT) {
                        throw runtime_error(
                            "@parse does not support repeated connection "
                            "data out events."
                        );
                    }
                    last_seen = OUT;
                    Input::DataEvent& specific =
                        dynamic_cast<Input::DataEvent&>(
                            *event
                        );

                    span_t input = from_buffer(specific.data);

                    if (! is_http09) {
                        convert_first_line<Input::ResponseEvent>(
                            new_tx.events,
                            input,
                            Input::RESPONSE_STARTED,
                            specific.pre_delay
                        );
                        convert_headers(
                            new_tx.events,
                            input,
                            Input::RESPONSE_HEADER,
                            Input::RESPONSE_HEADER_FINISHED
                        );
                    }
                    else {
                        new_tx.events.push_back(
                            boost::make_shared<Input::ResponseEvent>(
                                Input::RESPONSE_STARTED,
                                Input::Buffer(),
                                Input::Buffer(),
                                Input::Buffer(),
                                Input::Buffer()
                            )
                        );
                        new_tx.events.back()->pre_delay = specific.pre_delay;
                        new_tx.events.push_back(
                            boost::make_shared<Input::HeaderEvent>(Input::RESPONSE_HEADER)
                        );
                        new_tx.events.push_back(
                            boost::make_shared<Input::NullEvent>(Input::RESPONSE_HEADER_FINISHED)
                        );
                    }

                    convert_remainder(
                        new_tx.events,
                        input,
                        Input::RESPONSE_BODY,
                        Input::RESPONSE_FINISHED,
                        0,
                        specific.post_delay
                    );
                    break;
                }
                default:
                    new_tx.events.push_back(event);
            }
        }
    }
    input->connection.transactions.swap(new_transactions);

    return true;
}

void ParseModifier::parse_header_block(
    Input::header_list_t& headers,
    const char*& begin, const char* end
)
{
    span_t input(begin, end);
    while (! input.empty()) {
        span_t current_line = fetch_line(input);
        if (current_line.empty()) {
            // End of headers
            break;
        }
        two_span_t info = parse_header(current_line);
        headers.push_back(make_pair(
            to_buffer(info.get<0>()),
            to_buffer(info.get<1>())
        ));
    }
    begin = input.begin();
}

void ParseModifier::parse_request_line(
    Input::RequestEvent& event,
    const char* begin, const char* end
)
{
    span_t input(begin, end);
    three_span_t info = parse_first_line(input);
    event.raw      = to_buffer(input);
    event.method   = to_buffer(info.get<0>());
    event.uri      = to_buffer(info.get<1>());
    event.protocol = to_buffer(info.get<2>());
}

void ParseModifier::parse_response_line(
    Input::ResponseEvent& event,
    const char* begin, const char* end
)
{
    span_t input(begin, end);
    three_span_t info = parse_first_line(input);
    event.raw      = to_buffer(input);
    event.protocol = to_buffer(info.get<0>());
    event.status   = to_buffer(info.get<1>());
    event.message  = to_buffer(info.get<2>());
}

} // CLIPP
} // IronBee
<commit_msg>clipp/parse_modifier: Fix incorrect assert in previous commit.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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
 * @brief IronBee --- CLIPP Parse Modifier Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include "parse_modifier.hpp"

#include <boost/spirit/include/qi.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/function.hpp>
#include <boost/make_shared.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>

using namespace std;

namespace IronBee {
namespace CLIPP {

namespace {

typedef boost::iterator_range<const char*> span_t;
typedef boost::tuple<span_t, span_t> two_span_t;
typedef boost::tuple<span_t, span_t, span_t> three_span_t;

Input::Buffer to_buffer(const span_t& span)
{
    if (span.empty()) {
        return Input::Buffer();
    }
    return Input::Buffer(span.begin(), span.size());
}

span_t from_buffer(const Input::Buffer& buffer)
{
    return span_t(buffer.data, buffer.data + buffer.length);
}

// Read until \n or \r\n.
// Updates @a span to start just after line.
span_t fetch_line(span_t& span)
{
    using namespace boost::spirit::qi;

    span_t line;

    const char* new_begin = span.begin();
    bool success = parse(
        new_begin, span.end(),
        raw[*(ascii::char_ - ascii::char_("\n"))]
            >> omit["\n"],
        line
    );
    if (success) {
        span = span_t(new_begin, span.end());
        const char* end = line.end();
        if (end > line.begin() && *(end-1) == '\r') {
            --end;
        }
        return span_t(line.begin(), end);
    }
    else {
        // No end of line, return entire buffer as line.
        span = span_t(span.end(), span.end());
        return span_t(new_begin, span.end());
    }
    // unreachable
}

three_span_t parse_first_line(const span_t& span)
{
    using namespace boost::spirit::qi;

    three_span_t result;
    // Parse should only fail on an empty span in which case an empty
    // result is fine.
    parse(
        span.begin(), span.end(),
        omit[*space] >>
        raw[+(ascii::char_-' ')] >> omit[*space] >>
        raw[*(ascii::char_-' ')] >> omit[*space] >>
        raw[*ascii::char_] >> omit[*space],
        result
    );

    return result;
}

two_span_t parse_header(const span_t& span)
{
    using namespace boost::spirit::qi;

    two_span_t result;
    // Parse should never fail.
    bool success = parse(
        span.begin(), span.end(),
        raw[*(ascii::char_ - ':')] >>
            -(omit[lit(':') >> *space] >> raw[+ascii::char_]),
        result
    );
    if (! success) {
        throw logic_error(
            "Insanity error: Parse header fialed."
            "Please report as bug."
        );
    }

    return result;
}

template <typename StartEventType>
three_span_t convert_first_line(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       start_event,
    double               pre_delay
)
{
    span_t current_line = fetch_line(input);
    three_span_t info = parse_first_line(current_line);
    events.push_back(
        boost::make_shared<StartEventType>(
            start_event,
            to_buffer(current_line),
            to_buffer(info.get<0>()),
            to_buffer(info.get<1>()),
            to_buffer(info.get<2>())
        )
    );
    events.back()->pre_delay = pre_delay;

    return info;
}

void convert_headers(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       header_event,
    Input::event_e       header_finished_event
)
{
    Input::header_list_t headers;
    const char* begin = input.begin();
    ParseModifier::parse_header_block(headers, begin, input.end());
    input = span_t(begin, input.end());
    if (! headers.empty()) {
        boost::shared_ptr<Input::HeaderEvent> specific =
            boost::make_shared<Input::HeaderEvent>(header_event);
        specific->headers.swap(headers);
        events.push_back(specific);
    }
    events.push_back(
        boost::make_shared<Input::NullEvent>(header_finished_event)
    );
}

void convert_remainder(
    Input::event_list_t& events,
    span_t&              input,
    Input::event_e       body_event,
    Input::event_e       finished_event,
    double               pre_delay,
    double               post_delay
)
{
    events.push_back(
        boost::make_shared<Input::DataEvent>(body_event, to_buffer(input))
    );
    events.back()->pre_delay = pre_delay;
    pre_delay = 0;

    events.push_back(
        boost::make_shared<Input::NullEvent>(finished_event)
    );
    events.back()->pre_delay  = pre_delay;
    events.back()->post_delay = post_delay;
}

struct data_t
{
    boost::any old_source;
    Input::transaction_list_t transactions;
};

}

bool ParseModifier::operator()(Input::input_p& input)
{
    if (! input) {
        return true;
    }

    boost::shared_ptr<data_t> data = boost::make_shared<data_t>();
    data->old_source   = input->source;
    data->transactions = input->connection.transactions;
    input->source      = data;

    Input::transaction_list_t new_transactions;
    enum last_seen_e {
        NOTHING,
        IN,
        OUT
    };
    last_seen_e last_seen = NOTHING;
    bool is_http09 = false;
    BOOST_FOREACH(Input::Transaction& tx, input->connection.transactions) {
        new_transactions.push_back(Input::Transaction());
        Input::Transaction& new_tx = new_transactions.back();
        BOOST_FOREACH(const Input::event_p& event, tx.events) {
            switch (event->which) {
                case Input::CONNECTION_DATA_IN: {
                    if (last_seen == IN) {
                        throw runtime_error(
                            "@parse does not support repeated connection "
                            "data in events."
                        );
                    }
                    last_seen = IN;
                    Input::DataEvent& specific =
                        dynamic_cast<Input::DataEvent&>(
                            *event
                        );
                    span_t input = from_buffer(specific.data);
                    three_span_t info =
                        convert_first_line<Input::RequestEvent>(
                            new_tx.events,
                            input,
                            Input::REQUEST_STARTED,
                            specific.pre_delay
                        );
                    is_http09 = info.get<2>().empty();

                    if (! is_http09) {
                        convert_headers(
                            new_tx.events,
                            input,
                            Input::REQUEST_HEADER,
                            Input::REQUEST_HEADER_FINISHED
                        );
                    }
                    else {
                        new_tx.events.push_back(
                            boost::make_shared<Input::HeaderEvent>(Input::REQUEST_HEADER)
                        );
                        new_tx.events.push_back(
                            boost::make_shared<Input::NullEvent>(Input::REQUEST_HEADER_FINISHED)
                        );
                    }

                    convert_remainder(
                        new_tx.events,
                        input,
                        Input::REQUEST_BODY,
                        Input::REQUEST_FINISHED,
                        0,
                        specific.post_delay
                    );
                    break;
                }
                case Input::CONNECTION_DATA_OUT: {
                    if (last_seen == OUT) {
                        throw runtime_error(
                            "@parse does not support repeated connection "
                            "data out events."
                        );
                    }
                    last_seen = OUT;
                    Input::DataEvent& specific =
                        dynamic_cast<Input::DataEvent&>(
                            *event
                        );

                    span_t input = from_buffer(specific.data);

                    if (! is_http09) {
                        convert_first_line<Input::ResponseEvent>(
                            new_tx.events,
                            input,
                            Input::RESPONSE_STARTED,
                            specific.pre_delay
                        );
                        convert_headers(
                            new_tx.events,
                            input,
                            Input::RESPONSE_HEADER,
                            Input::RESPONSE_HEADER_FINISHED
                        );
                    }
                    else {
                        new_tx.events.push_back(
                            boost::make_shared<Input::ResponseEvent>(
                                Input::RESPONSE_STARTED,
                                Input::Buffer(),
                                Input::Buffer(),
                                Input::Buffer(),
                                Input::Buffer()
                            )
                        );
                        new_tx.events.back()->pre_delay = specific.pre_delay;
                        new_tx.events.push_back(
                            boost::make_shared<Input::HeaderEvent>(Input::RESPONSE_HEADER)
                        );
                        new_tx.events.push_back(
                            boost::make_shared<Input::NullEvent>(Input::RESPONSE_HEADER_FINISHED)
                        );
                    }

                    convert_remainder(
                        new_tx.events,
                        input,
                        Input::RESPONSE_BODY,
                        Input::RESPONSE_FINISHED,
                        0,
                        specific.post_delay
                    );
                    break;
                }
                default:
                    new_tx.events.push_back(event);
            }
        }
    }
    input->connection.transactions.swap(new_transactions);

    return true;
}

void ParseModifier::parse_header_block(
    Input::header_list_t& headers,
    const char*& begin, const char* end
)
{
    span_t input(begin, end);
    while (! input.empty()) {
        span_t current_line = fetch_line(input);
        if (current_line.empty()) {
            // End of headers
            break;
        }
        two_span_t info = parse_header(current_line);
        headers.push_back(make_pair(
            to_buffer(info.get<0>()),
            to_buffer(info.get<1>())
        ));
    }
    begin = input.begin();
}

void ParseModifier::parse_request_line(
    Input::RequestEvent& event,
    const char* begin, const char* end
)
{
    span_t input(begin, end);
    three_span_t info = parse_first_line(input);
    event.raw      = to_buffer(input);
    event.method   = to_buffer(info.get<0>());
    event.uri      = to_buffer(info.get<1>());
    event.protocol = to_buffer(info.get<2>());
}

void ParseModifier::parse_response_line(
    Input::ResponseEvent& event,
    const char* begin, const char* end
)
{
    span_t input(begin, end);
    three_span_t info = parse_first_line(input);
    event.raw      = to_buffer(input);
    event.protocol = to_buffer(info.get<0>());
    event.status   = to_buffer(info.get<1>());
    event.message  = to_buffer(info.get<2>());
}

} // CLIPP
} // IronBee
<|endoftext|>


<commit_before>#include "clstm.h"
#include <assert.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <iostream>
#include <memory>
#include <regex>
#include <set>
#include <sstream>
#include <vector>
#include "clstmhl.h"
#include "extras.h"
#include "pstring.h"
#include "utils.h"

using namespace Eigen;
using namespace ocropus;
using std::vector;
using std::map;
using std::make_pair;
using std::shared_ptr;
using std::unique_ptr;
using std::cout;
using std::ifstream;
using std::set;
using std::to_string;
using std_string = std::string;
using std_wstring = std::wstring;
using std::regex;
using std::regex_replace;
#define string std_string
#define wstring std_wstring

#ifndef NODISPLAY
void show(PyServer &py, Sequence &s, int subplot = 0, int batch = 0) {
  Tensor<float, 2> temp;
  temp.resize(s.size(), s.rows());
  for (int i = 0; i < s.size(); i++)
    for (int j = 0; j < s.rows(); j++) temp(i, j) = s[i].v(j, batch);
  if (subplot > 0) py.evalf("subplot(%d)", subplot);
  py.imshowT(temp, "cmap=cm.hot");
}
#endif

wstring separate_chars(const wstring &s, const wstring &charsep) {
  if (charsep == L"") return s;
  wstring result;
  for (int i = 0; i < s.size(); i++) {
    if (i > 0) result.push_back(charsep[0]);
    result.push_back(s[i]);
  }
  return result;
}

struct Dataset {
  vector<string> fnames;
  wstring charsep = utf8_to_utf32(getsenv("charsep", ""));
  int size() { return fnames.size(); }
  Dataset() {}
  Dataset(string file_list) { readFileList(file_list); }
  void readFileList(string file_list) { read_lines(fnames, file_list); }
  void getCodec(Codec &codec) {
    vector<string> gtnames;
    for (auto s : fnames) gtnames.push_back(basename(s) + ".gt.txt");
    codec.build(gtnames, charsep);
  }
  void readSample(Tensor2 &raw, wstring &gt, int index) {
    string fname = fnames[index];
    string base = basename(fname);
    gt = separate_chars(read_text32(base + ".gt.txt"), charsep);
    read_png(raw, fname.c_str());
    raw() = -raw() + Float(1);
  }
};

pair<double, double> test_set_error(CLSTMOCR &clstm, Dataset &testset) {
  double count = 0.0;
  double errors = 0.0;
  for (int test = 0; test < testset.size(); test++) {
    Tensor2 raw;
    wstring gt;
    testset.readSample(raw, gt, test);
    wstring pred = clstm.predict(raw());
    count += gt.size();
    errors += levenshtein(pred, gt);
  }
  return make_pair(count, errors);
}

int print_usage(char **argv) {
    cerr << "Usage: [VAR=VAL...] " << argv[0] << " TRAININGLIST [TESTLIST]\n";
    cerr << "\n";
    cerr << "  Arguments:\n";
    cerr << "    TRAININGLIST     File with filenames to train with\n";
    cerr << "    TESTLIST         File with filenames to evaluate training\n";
    cerr << "  \n";
    cerr << "  Variables:\n";
    cerr << "     load            Filename of model file to load. Default: ''\n";
    cerr << "     save_name       Basename of model file to save. Default: '_ocr'\n";
    cerr << "     nhidden         Number of hidden Default: 100\n";
    cerr << "     lrate           Learning rate. Default: 1e-4\n";
    cerr << "     momentum        Momentum. Default: 0.9\n";
    cerr << "     target_height   Line height to normalize. Default: 48\n";
    cerr << "     ntrain          Number of iterations. Default: 10000000\n";
    cerr << "     start           Initial iteration. Default: -1\n";
    cerr << "     charsep         Separator between characters in ground truth. Default: ''\n";
    cerr << "     report_time     Set to 1 to report time. Default: 0\n";
    cerr << "     test_every      Evaluate model every n-th iteration. Default: 10000\n";
    cerr << "     report_every    Log current state every n-th iteration. Default: 100\n";
    cerr << "     save_every      Save model with iteration as suffix every n-th\n";
    cerr << "                     iteration. Default: 10000\n";
    cerr << "     display_every   Update display every n-th iteration. Requires compilation\n";
    cerr << "                     with 'scons display=1'. Default: 0\n";
    cerr << "     params          Whether to report variable values on read. Default: 1\n";
}

int main1(int argc, char **argv) {
  if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
      return print_usage(argv);
  int ntrain = getienv("ntrain", 10000000);
  string save_name = getsenv("save_name", "_ocr");
  int report_time = getienv("report_time", 0);

  Dataset trainingset(argv[1]);
  assert(trainingset.size() > 0);
  Dataset testset;
  if (argc > 2) testset.readFileList(argv[2]);
  print("got", trainingset.size(), "files,", testset.size(), "tests");

  string load_name = getsenv("load", "");

  CLSTMOCR clstm;

  if (load_name != "") {
    clstm.load(load_name);
  } else {
    Codec codec;
    trainingset.getCodec(codec);
    print("got", codec.size(), "classes");

    clstm.target_height = int(getrenv("target_height", 48));
    clstm.createBidi(codec.codec, getienv("nhidden", 100));
    clstm.setLearningRate(getdenv("lrate", 1e-4), getdenv("momentum", 0.9));
  }
  network_info(clstm.net, "");

  double test_error = 9999.0;
  double best_error = 1e38;

#ifndef NODISPLAY
  PyServer py;
  if (display_every > 0) py.open();
#endif
  double start_time = now();
  int start = clstm.net->attr.get("trial", getienv("start", -1)) + 1;
  if (start > 0) print("start", start);

  Trigger test_trigger(getienv("test_every", 10000), -1, start);
  test_trigger.skip0();
  Trigger save_trigger(getienv("save_every", 10000), ntrain, start);
  save_trigger.enable(save_name != "").skip0();
  Trigger report_trigger(getienv("report_every", 100), ntrain, start);
  Trigger display_trigger(getienv("display_every", 0), ntrain, start);

  for (int trial = start; trial < ntrain; trial++) {
    int sample = lrand48() % trainingset.size();
    Tensor2 raw;
    wstring gt;
    trainingset.readSample(raw, gt, sample);
    wstring pred = clstm.train(raw(), gt);

    if (report_trigger(trial)) {
      print(trial);
      print("TRU", gt);
      print("ALN", clstm.aligned_utf8());
      print("OUT", utf32_to_utf8(pred));
      if (trial > 0 && report_time)
        print("steptime", (now() - start_time) / report_trigger.since());
      start_time = now();
    }

#ifndef NODISPLAY
    if (display_trigger(trial)) {
      py.evalf("clf");
      show(py, clstm.net->inputs, 411);
      show(py, clstm.net->outputs, 412);
      show(py, clstm.targets, 413);
      show(py, clstm.aligned, 414);
    }
#endif

    if (test_trigger(trial)) {
      auto tse = test_set_error(clstm, testset);
      double errors = tse.first;
      double count = tse.second;
      test_error = errors / count;
      print("ERROR", trial, test_error, "   ", errors, count);
      if (test_error < best_error) {
        best_error = test_error;
        string fname = save_name + ".clstm";
        print("saving best performing network so far", fname, "error rate: ",
              best_error);
        clstm.net->attr.set("trial", trial);
        clstm.save(fname);
      }
    }

    if (save_trigger(trial)) {
      string fname = save_name + "-" + to_string(trial) + ".clstm";
      print("saving", fname);
      clstm.net->attr.set("trial", trial);
      clstm.save(fname);
    }
  }

  return 0;
}

int main(int argc, char **argv) {
  TRY { main1(argc, argv); }
  CATCH(const char *message) { cerr << "FATAL: " << message << endl; }
}
<commit_msg>clstmocrtrain: Allow two argument call<commit_after>#include "clstm.h"
#include <assert.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <iostream>
#include <memory>
#include <regex>
#include <set>
#include <sstream>
#include <vector>
#include "clstmhl.h"
#include "extras.h"
#include "pstring.h"
#include "utils.h"

using namespace Eigen;
using namespace ocropus;
using std::vector;
using std::map;
using std::make_pair;
using std::shared_ptr;
using std::unique_ptr;
using std::cout;
using std::ifstream;
using std::set;
using std::to_string;
using std_string = std::string;
using std_wstring = std::wstring;
using std::regex;
using std::regex_replace;
#define string std_string
#define wstring std_wstring

#ifndef NODISPLAY
void show(PyServer &py, Sequence &s, int subplot = 0, int batch = 0) {
  Tensor<float, 2> temp;
  temp.resize(s.size(), s.rows());
  for (int i = 0; i < s.size(); i++)
    for (int j = 0; j < s.rows(); j++) temp(i, j) = s[i].v(j, batch);
  if (subplot > 0) py.evalf("subplot(%d)", subplot);
  py.imshowT(temp, "cmap=cm.hot");
}
#endif

wstring separate_chars(const wstring &s, const wstring &charsep) {
  if (charsep == L"") return s;
  wstring result;
  for (int i = 0; i < s.size(); i++) {
    if (i > 0) result.push_back(charsep[0]);
    result.push_back(s[i]);
  }
  return result;
}

struct Dataset {
  vector<string> fnames;
  wstring charsep = utf8_to_utf32(getsenv("charsep", ""));
  int size() { return fnames.size(); }
  Dataset() {}
  Dataset(string file_list) { readFileList(file_list); }
  void readFileList(string file_list) { read_lines(fnames, file_list); }
  void getCodec(Codec &codec) {
    vector<string> gtnames;
    for (auto s : fnames) gtnames.push_back(basename(s) + ".gt.txt");
    codec.build(gtnames, charsep);
  }
  void readSample(Tensor2 &raw, wstring &gt, int index) {
    string fname = fnames[index];
    string base = basename(fname);
    gt = separate_chars(read_text32(base + ".gt.txt"), charsep);
    read_png(raw, fname.c_str());
    raw() = -raw() + Float(1);
  }
};

pair<double, double> test_set_error(CLSTMOCR &clstm, Dataset &testset) {
  double count = 0.0;
  double errors = 0.0;
  for (int test = 0; test < testset.size(); test++) {
    Tensor2 raw;
    wstring gt;
    testset.readSample(raw, gt, test);
    wstring pred = clstm.predict(raw());
    count += gt.size();
    errors += levenshtein(pred, gt);
  }
  return make_pair(count, errors);
}

int print_usage(char **argv) {
    cerr << "Usage: [VAR=VAL...] " << argv[0] << " TRAININGLIST [TESTLIST]\n";
    cerr << "\n";
    cerr << "  Arguments:\n";
    cerr << "    TRAININGLIST     File with filenames to train with\n";
    cerr << "    TESTLIST         File with filenames to evaluate training\n";
    cerr << "  \n";
    cerr << "  Variables:\n";
    cerr << "     load            Filename of model file to load. Default: ''\n";
    cerr << "     save_name       Basename of model file to save. Default: '_ocr'\n";
    cerr << "     nhidden         Number of hidden Default: 100\n";
    cerr << "     lrate           Learning rate. Default: 1e-4\n";
    cerr << "     momentum        Momentum. Default: 0.9\n";
    cerr << "     target_height   Line height to normalize. Default: 48\n";
    cerr << "     ntrain          Number of iterations. Default: 10000000\n";
    cerr << "     start           Initial iteration. Default: -1\n";
    cerr << "     charsep         Separator between characters in ground truth. Default: ''\n";
    cerr << "     report_time     Set to 1 to report time. Default: 0\n";
    cerr << "     test_every      Evaluate model every n-th iteration. Default: 10000\n";
    cerr << "     report_every    Log current state every n-th iteration. Default: 100\n";
    cerr << "     save_every      Save model with iteration as suffix every n-th\n";
    cerr << "                     iteration. Default: 10000\n";
    cerr << "     display_every   Update display every n-th iteration. Requires compilation\n";
    cerr << "                     with 'scons display=1'. Default: 0\n";
    cerr << "     params          Whether to report variable values on read. Default: 1\n";
}

int main1(int argc, char **argv) {
  if (argc < 2 || argc > 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
      return print_usage(argv);
  int ntrain = getienv("ntrain", 10000000);
  string save_name = getsenv("save_name", "_ocr");
  int report_time = getienv("report_time", 0);

  Dataset trainingset(argv[1]);
  assert(trainingset.size() > 0);
  Dataset testset;
  if (argc > 2) testset.readFileList(argv[2]);
  print("got", trainingset.size(), "files,", testset.size(), "tests");

  string load_name = getsenv("load", "");

  CLSTMOCR clstm;

  if (load_name != "") {
    clstm.load(load_name);
  } else {
    Codec codec;
    trainingset.getCodec(codec);
    print("got", codec.size(), "classes");

    clstm.target_height = int(getrenv("target_height", 48));
    clstm.createBidi(codec.codec, getienv("nhidden", 100));
    clstm.setLearningRate(getdenv("lrate", 1e-4), getdenv("momentum", 0.9));
  }
  network_info(clstm.net, "");

  double test_error = 9999.0;
  double best_error = 1e38;

#ifndef NODISPLAY
  PyServer py;
  if (display_every > 0) py.open();
#endif
  double start_time = now();
  int start = clstm.net->attr.get("trial", getienv("start", -1)) + 1;
  if (start > 0) print("start", start);

  Trigger test_trigger(getienv("test_every", 10000), -1, start);
  test_trigger.skip0();
  Trigger save_trigger(getienv("save_every", 10000), ntrain, start);
  save_trigger.enable(save_name != "").skip0();
  Trigger report_trigger(getienv("report_every", 100), ntrain, start);
  Trigger display_trigger(getienv("display_every", 0), ntrain, start);

  for (int trial = start; trial < ntrain; trial++) {
    int sample = lrand48() % trainingset.size();
    Tensor2 raw;
    wstring gt;
    trainingset.readSample(raw, gt, sample);
    wstring pred = clstm.train(raw(), gt);

    if (report_trigger(trial)) {
      print(trial);
      print("TRU", gt);
      print("ALN", clstm.aligned_utf8());
      print("OUT", utf32_to_utf8(pred));
      if (trial > 0 && report_time)
        print("steptime", (now() - start_time) / report_trigger.since());
      start_time = now();
    }

#ifndef NODISPLAY
    if (display_trigger(trial)) {
      py.evalf("clf");
      show(py, clstm.net->inputs, 411);
      show(py, clstm.net->outputs, 412);
      show(py, clstm.targets, 413);
      show(py, clstm.aligned, 414);
    }
#endif

    if (test_trigger(trial)) {
      auto tse = test_set_error(clstm, testset);
      double errors = tse.first;
      double count = tse.second;
      test_error = errors / count;
      print("ERROR", trial, test_error, "   ", errors, count);
      if (test_error < best_error) {
        best_error = test_error;
        string fname = save_name + ".clstm";
        print("saving best performing network so far", fname, "error rate: ",
              best_error);
        clstm.net->attr.set("trial", trial);
        clstm.save(fname);
      }
    }

    if (save_trigger(trial)) {
      string fname = save_name + "-" + to_string(trial) + ".clstm";
      print("saving", fname);
      clstm.net->attr.set("trial", trial);
      clstm.save(fname);
    }
  }

  return 0;
}

int main(int argc, char **argv) {
  TRY { main1(argc, argv); }
  CATCH(const char *message) { cerr << "FATAL: " << message << endl; }
}
<|endoftext|>