<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <limits>

#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>

#include <sal/types.h>

#include <rtl/ref.hxx>

#include <osl/file.hxx>
#include <osl/thread.h>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/io/XStreamListener.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
#include <com/sun/star/xml/xslt/XSLTTransformer.hpp>

#include <cppuhelper/implbase1.hxx>

#include <test/bootstrapfixture.hxx>

using namespace std;
using namespace ::com::sun::star;

namespace {

class XsltFilterTest
    : public test::BootstrapFixture
{
public:
    void testXsltCopyOld();
    void testXsltCopyNew();

    CPPUNIT_TEST_SUITE(XsltFilterTest);
    CPPUNIT_TEST(testXsltCopyOld);
    CPPUNIT_TEST(testXsltCopyNew);
    CPPUNIT_TEST_SUITE_END();
};

struct Listener : public ::cppu::WeakImplHelper1<io::XStreamListener>
{
    bool m_bDone;

    Listener() : m_bDone(false) {}

    virtual void disposing(const lang::EventObject&) throw() SAL_OVERRIDE {}
    virtual void SAL_CALL started() throw() SAL_OVERRIDE { m_bDone = false; }
    virtual void SAL_CALL closed() throw() SAL_OVERRIDE { m_bDone = true; }
    virtual void SAL_CALL terminated() throw() SAL_OVERRIDE { m_bDone = true; }
    virtual void SAL_CALL error(const uno::Any& e) throw() SAL_OVERRIDE
    {
        m_bDone = true; // set on error too, otherwise main thread waits forever
        SAL_WARN("filter.xslt", "exception " << e);
        CPPUNIT_FAIL("exception while in XSLT");
    }
};

void XsltFilterTest::testXsltCopyNew()
{
    OUString tempDirURL;
    osl_getTempDirURL(&tempDirURL.pData);
    oslFileHandle tempFile;
    OUString tempURL;
    osl::File::RC rc = osl::File::createTempFile(0, &tempFile, &tempURL);
    CPPUNIT_ASSERT(osl::FileBase::E_None == rc);

    OUString source(
            getURLFromSrc("/filter/source/xsltfilter/xsltfilter.component"));
    uno::Sequence<uno::Any> args(7);
    args[0] <<= beans::NamedValue("StylesheetURL",
        uno::makeAny(getURLFromSrc("/filter/qa/cppunit/data/xslt/copy.xslt")));
    args[1] <<= beans::NamedValue("SourceURL", uno::makeAny(source));
    args[2] <<= beans::NamedValue("TargetURL", uno::makeAny(tempURL));
    args[3] <<= beans::NamedValue("SourceBaseURL",
        uno::makeAny(getURLFromSrc("/filter/source/xsltfilter/")));
    args[4] <<= beans::NamedValue("TargetBaseURL", uno::makeAny(tempDirURL));
    args[5] <<= beans::NamedValue("SystemType", uno::makeAny(OUString()));
    args[6] <<= beans::NamedValue("PublicType", uno::makeAny(OUString()));

    uno::Reference<ucb::XSimpleFileAccess3> xSFA =
        ucb::SimpleFileAccess::create(getComponentContext());

    uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
    uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);

    rtl::Reference<Listener> xListener = new Listener();

    uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
            xml::xslt::XSLTTransformer::create(getComponentContext(), args));

    xXslt->addListener(uno::Reference<io::XStreamListener>(xListener.get()));
    xXslt->setInputStream(xIn);
    xXslt->setOutputStream(xOut);

    xXslt->start();

    TimeValue delay;
    delay.Seconds = 0;
    delay.Nanosec = 1000000;
    while (!xListener->m_bDone) { osl_waitThread(&delay); }

    xIn->closeInput();
    xOut->closeOutput();

    osl::File foo(tempURL); // apparently it's necessary to open it again?
    foo.open(osl_File_OpenFlag_Read);
    sal_uInt64 size(0);
    foo.getSize(size);
    CPPUNIT_ASSERT(size > 1000); // check that something happened
}

void XsltFilterTest::testXsltCopyOld()
{
    OUString tempDirURL;
    osl_getTempDirURL(&tempDirURL.pData);
    oslFileHandle tempFile;
    OUString tempURL;
    osl::File::RC rc = osl::File::createTempFile(0, &tempFile, &tempURL);
    CPPUNIT_ASSERT(osl::FileBase::E_None == rc);

    OUString source(
            getURLFromSrc("/filter/source/xsltfilter/xsltfilter.component"));
    uno::Sequence<uno::Any> args(7);
    args[0] <<= beans::NamedValue("StylesheetURL",
        uno::makeAny(getURLFromSrc("/filter/qa/cppunit/data/xslt/copy.xslt")));
    args[1] <<= beans::NamedValue("SourceURL", uno::makeAny(source));
    args[2] <<= beans::NamedValue("TargetURL", uno::makeAny(tempURL));
    args[3] <<= beans::NamedValue("SourceBaseURL",
        uno::makeAny(getURLFromSrc("/filter/source/xsltfilter/")));
    args[4] <<= beans::NamedValue("TargetBaseURL", uno::makeAny(tempDirURL));
    args[5] <<= beans::NamedValue("SystemType", uno::makeAny(OUString()));
    args[6] <<= beans::NamedValue("PublicType", uno::makeAny(OUString()));

    uno::Reference<ucb::XSimpleFileAccess3> xSFA =
        ucb::SimpleFileAccess::create(getComponentContext());

    uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
    uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);

    rtl::Reference<Listener> xListener = new Listener();

    uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
        getMultiServiceFactory()->createInstance(
            "com.sun.star.comp.documentconversion.LibXSLTTransformer"),
        uno::UNO_QUERY_THROW);

    uno::Reference<lang::XInitialization> xInit(xXslt, uno::UNO_QUERY_THROW);
    xInit->initialize(args);
    xXslt->addListener(uno::Reference<io::XStreamListener>(xListener.get()));
    xXslt->setInputStream(xIn);
    xXslt->setOutputStream(xOut);

    xXslt->start();

    TimeValue delay;
    delay.Seconds = 0;
    delay.Nanosec = 1000000;
    while (!xListener->m_bDone) { osl_waitThread(&delay); }

    xIn->closeInput();
    xOut->closeOutput();

    osl::File foo(tempURL); // apparently it's necessary to open it again?
    foo.open(osl_File_OpenFlag_Read);
    sal_uInt64 size(0);
    foo.getSize(size);
    CPPUNIT_ASSERT(size > 1000); // check that something happened
}

CPPUNIT_TEST_SUITE_REGISTRATION(XsltFilterTest);

}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>I imagine this should have a SAL_CALL decoration<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <limits>

#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>

#include <sal/types.h>

#include <rtl/ref.hxx>

#include <osl/file.hxx>
#include <osl/thread.h>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/io/XStreamListener.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
#include <com/sun/star/xml/xslt/XSLTTransformer.hpp>

#include <cppuhelper/implbase1.hxx>

#include <test/bootstrapfixture.hxx>

using namespace std;
using namespace ::com::sun::star;

namespace {

class XsltFilterTest
    : public test::BootstrapFixture
{
public:
    void testXsltCopyOld();
    void testXsltCopyNew();

    CPPUNIT_TEST_SUITE(XsltFilterTest);
    CPPUNIT_TEST(testXsltCopyOld);
    CPPUNIT_TEST(testXsltCopyNew);
    CPPUNIT_TEST_SUITE_END();
};

struct Listener : public ::cppu::WeakImplHelper1<io::XStreamListener>
{
    bool m_bDone;

    Listener() : m_bDone(false) {}

    virtual void SAL_CALL disposing(const lang::EventObject&) throw() SAL_OVERRIDE {}
    virtual void SAL_CALL started() throw() SAL_OVERRIDE { m_bDone = false; }
    virtual void SAL_CALL closed() throw() SAL_OVERRIDE { m_bDone = true; }
    virtual void SAL_CALL terminated() throw() SAL_OVERRIDE { m_bDone = true; }
    virtual void SAL_CALL error(const uno::Any& e) throw() SAL_OVERRIDE
    {
        m_bDone = true; // set on error too, otherwise main thread waits forever
        SAL_WARN("filter.xslt", "exception " << e);
        CPPUNIT_FAIL("exception while in XSLT");
    }
};

void XsltFilterTest::testXsltCopyNew()
{
    OUString tempDirURL;
    osl_getTempDirURL(&tempDirURL.pData);
    oslFileHandle tempFile;
    OUString tempURL;
    osl::File::RC rc = osl::File::createTempFile(0, &tempFile, &tempURL);
    CPPUNIT_ASSERT(osl::FileBase::E_None == rc);

    OUString source(
            getURLFromSrc("/filter/source/xsltfilter/xsltfilter.component"));
    uno::Sequence<uno::Any> args(7);
    args[0] <<= beans::NamedValue("StylesheetURL",
        uno::makeAny(getURLFromSrc("/filter/qa/cppunit/data/xslt/copy.xslt")));
    args[1] <<= beans::NamedValue("SourceURL", uno::makeAny(source));
    args[2] <<= beans::NamedValue("TargetURL", uno::makeAny(tempURL));
    args[3] <<= beans::NamedValue("SourceBaseURL",
        uno::makeAny(getURLFromSrc("/filter/source/xsltfilter/")));
    args[4] <<= beans::NamedValue("TargetBaseURL", uno::makeAny(tempDirURL));
    args[5] <<= beans::NamedValue("SystemType", uno::makeAny(OUString()));
    args[6] <<= beans::NamedValue("PublicType", uno::makeAny(OUString()));

    uno::Reference<ucb::XSimpleFileAccess3> xSFA =
        ucb::SimpleFileAccess::create(getComponentContext());

    uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
    uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);

    rtl::Reference<Listener> xListener = new Listener();

    uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
            xml::xslt::XSLTTransformer::create(getComponentContext(), args));

    xXslt->addListener(uno::Reference<io::XStreamListener>(xListener.get()));
    xXslt->setInputStream(xIn);
    xXslt->setOutputStream(xOut);

    xXslt->start();

    TimeValue delay;
    delay.Seconds = 0;
    delay.Nanosec = 1000000;
    while (!xListener->m_bDone) { osl_waitThread(&delay); }

    xIn->closeInput();
    xOut->closeOutput();

    osl::File foo(tempURL); // apparently it's necessary to open it again?
    foo.open(osl_File_OpenFlag_Read);
    sal_uInt64 size(0);
    foo.getSize(size);
    CPPUNIT_ASSERT(size > 1000); // check that something happened
}

void XsltFilterTest::testXsltCopyOld()
{
    OUString tempDirURL;
    osl_getTempDirURL(&tempDirURL.pData);
    oslFileHandle tempFile;
    OUString tempURL;
    osl::File::RC rc = osl::File::createTempFile(0, &tempFile, &tempURL);
    CPPUNIT_ASSERT(osl::FileBase::E_None == rc);

    OUString source(
            getURLFromSrc("/filter/source/xsltfilter/xsltfilter.component"));
    uno::Sequence<uno::Any> args(7);
    args[0] <<= beans::NamedValue("StylesheetURL",
        uno::makeAny(getURLFromSrc("/filter/qa/cppunit/data/xslt/copy.xslt")));
    args[1] <<= beans::NamedValue("SourceURL", uno::makeAny(source));
    args[2] <<= beans::NamedValue("TargetURL", uno::makeAny(tempURL));
    args[3] <<= beans::NamedValue("SourceBaseURL",
        uno::makeAny(getURLFromSrc("/filter/source/xsltfilter/")));
    args[4] <<= beans::NamedValue("TargetBaseURL", uno::makeAny(tempDirURL));
    args[5] <<= beans::NamedValue("SystemType", uno::makeAny(OUString()));
    args[6] <<= beans::NamedValue("PublicType", uno::makeAny(OUString()));

    uno::Reference<ucb::XSimpleFileAccess3> xSFA =
        ucb::SimpleFileAccess::create(getComponentContext());

    uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
    uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);

    rtl::Reference<Listener> xListener = new Listener();

    uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
        getMultiServiceFactory()->createInstance(
            "com.sun.star.comp.documentconversion.LibXSLTTransformer"),
        uno::UNO_QUERY_THROW);

    uno::Reference<lang::XInitialization> xInit(xXslt, uno::UNO_QUERY_THROW);
    xInit->initialize(args);
    xXslt->addListener(uno::Reference<io::XStreamListener>(xListener.get()));
    xXslt->setInputStream(xIn);
    xXslt->setOutputStream(xOut);

    xXslt->start();

    TimeValue delay;
    delay.Seconds = 0;
    delay.Nanosec = 1000000;
    while (!xListener->m_bDone) { osl_waitThread(&delay); }

    xIn->closeInput();
    xOut->closeOutput();

    osl::File foo(tempURL); // apparently it's necessary to open it again?
    foo.open(osl_File_OpenFlag_Read);
    sal_uInt64 size(0);
    foo.getSize(size);
    CPPUNIT_ASSERT(size > 1000); // check that something happened
}

CPPUNIT_TEST_SUITE_REGISTRATION(XsltFilterTest);

}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "vtkAbstractArray.h"
#include "vtkExodusIIReader.h"
#include "vtkDataObject.h"
#include "vtkDataSet.h"
#include "vtkDataSetAttributes.h"
#include "vtkIdTypeArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPExodusIIReader.h"
#include "vtkSmartPointer.h"

#include <vtkTestUtilities.h>
#include <vtkTesting.h>

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New ();

int TestExodusImplicitArrays(int argc, char *argv[])
{
  const char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/disk_out_ref.ex2");
  VTK_CREATE (vtkExodusIIReader, reader);
  reader->SetFileName (fname);
  reader->GenerateImplicitElementIdArrayOn ();
  reader->GenerateImplicitNodeIdArrayOn ();
  reader->Update ();

  vtkMultiBlockDataSet *mb = reader->GetOutput ();

  if (!mb)
    {
    return vtkTesting::FAILED;
    }
  vtkMultiBlockDataSet *elems = vtkMultiBlockDataSet::SafeDownCast (mb->GetBlock (0));

  if (!elems)
    {
    return vtkTesting::FAILED;
    }
  vtkDataObject *obj = elems->GetBlock (0);

  if (!obj)
    {
    return vtkTesting::FAILED;
    }
  vtkIdTypeArray *ie = vtkIdTypeArray::SafeDownCast (
                  obj->GetAttributes (vtkDataSet::CELL)->GetAbstractArray ("ImplicitElementId"));
  vtkIdTypeArray *in = vtkIdTypeArray::SafeDownCast (
                  obj->GetAttributes (vtkDataSet::POINT)->GetAbstractArray ("ImplicitNodeId"));
  if (!ie || !in)
    {
    return vtkTesting::FAILED;
    }

  for (int id = 0; id < ie->GetNumberOfTuples (); id ++)
    {
    if (ie->GetValue (id) != (id + 1))
      {
      return vtkTesting::FAILED;
      }
    }

  if (in->GetValue (0) != 143 || in->GetValue (1) != 706 || in->GetValue (2) != 3173)
    {
    return vtkTesting::FAILED;
    }

  return vtkTesting::PASSED;
}
<commit_msg>BUG: Wrong return values<commit_after>#include "vtkAbstractArray.h"
#include "vtkExodusIIReader.h"
#include "vtkDataObject.h"
#include "vtkDataSet.h"
#include "vtkDataSetAttributes.h"
#include "vtkIdTypeArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPExodusIIReader.h"
#include "vtkSmartPointer.h"

#include <vtkTestUtilities.h>
#include <vtkTesting.h>

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New ();

int TestExodusImplicitArrays(int argc, char *argv[])
{
  const char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/disk_out_ref.ex2");
  VTK_CREATE (vtkExodusIIReader, reader);
  reader->SetFileName (fname);
  reader->GenerateImplicitElementIdArrayOn ();
  reader->GenerateImplicitNodeIdArrayOn ();
  reader->Update ();

  vtkMultiBlockDataSet *mb = reader->GetOutput ();

  if (!mb)
    {
    return 1;
    }
  vtkMultiBlockDataSet *elems = vtkMultiBlockDataSet::SafeDownCast (mb->GetBlock (0));

  if (!elems)
    {
    return 1;
    }
  vtkDataObject *obj = elems->GetBlock (0);

  if (!obj)
    {
    return 1;
    }
  vtkIdTypeArray *ie = vtkIdTypeArray::SafeDownCast (
                  obj->GetAttributes (vtkDataSet::CELL)->GetAbstractArray ("ImplicitElementId"));
  vtkIdTypeArray *in = vtkIdTypeArray::SafeDownCast (
                  obj->GetAttributes (vtkDataSet::POINT)->GetAbstractArray ("ImplicitNodeId"));
  if (!ie || !in)
    {
    return 1;
    }

  for (int id = 0; id < ie->GetNumberOfTuples (); id ++)
    {
    if (ie->GetValue (id) != (id + 1))
      {
      return 1;
      }
    }

  if (in->GetValue (0) != 143 || in->GetValue (1) != 706 || in->GetValue (2) != 3173)
    {
    return 1;
    }

  return 0;
}
<|endoftext|>


<commit_before>/**
 * @file image.c
 *
 * Implementation of the image type.
 *
 * The following formats are supported:
 * - binary PGM (P5)
 * - binary PPM (P6)
 */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "image.h"

/**
 * Construct a PPM image.
 *
 * @return pointer to empty PPM image
 */
image_t * image_construct()
{
	image_t *image = (image_t *)malloc(sizeof(image_t));
	image->channels = 0;
	image->height = 0;
	image->width = 0;
	image->max_value = 0;
	image->pixels = NULL;

	return image;
}

/**
 * Destruct an image.
 *
 * @param image  pointer to image
 */
void image_destruct(image_t *image)
{
	free(image->pixels);
	free(image);
}

/**
 * Helper function to skip comments in a PGM/PPM image.
 */
void skip_to_next_value(FILE* in)
{
	char c = fgetc(in);
	while ( c == '#' || isspace(c) ) {
		if ( c == '#' ) {
			while ( c != '\n' ) {
				c = fgetc(in);
			}
		}
		else {
			while ( isspace(c) ) {
				c = fgetc(in);
			}
		}
	}

	ungetc(c, in);
}

/**
 * Read an image from a PGM/PPM file.
 *
 * @param image  pointer to image
 * @param path   image filename
 */
void image_read(image_t *image, const char *path)
{
	FILE *in = fopen(path, "r");

	char header[4];

	fscanf(in, "%s", header);
	if ( strcmp(header, "P5") == 0 ) {
		image->channels = 1;
	}
	else if ( strcmp(header, "P6") == 0 ) {
		image->channels = 3;
	}
	else {
		fprintf(stderr, "error: cannot read image \'%s\'\n", path);
		exit(1);
	}

	skip_to_next_value(in);
	fscanf(in, "%d", &image->height);

	skip_to_next_value(in);
	fscanf(in, "%d", &image->width);

	skip_to_next_value(in);
	fscanf(in, "%d", &image->max_value);

	int num = image->channels * image->height * image->width;

	if ( image->pixels == NULL ) {
		image->pixels = (unsigned char *)malloc(num * sizeof(unsigned char));
	}

	fread(image->pixels, sizeof(unsigned char), num, in);

	fclose(in);
}

/**
 * Write an image to a PGM/PPM file.
 *
 * @param image  pointer to image
 * @param path   image filename
 */
void image_write(image_t *image, const char *path)
{
	FILE *out = fopen(path, "w");

	// write image header
	if ( image->channels == 1 ) {
		fprintf(out, "P5");
	}
	else if ( image->channels == 3 ) {
		fprintf(out, "P6");
	}
	else {
		fprintf(stderr, "error: cannot write image \'%s\'\n", path);
		exit(1);
	}

	fprintf(out, "%d %d %d\n", image->height, image->width, image->max_value);

	// write pixel data
	fwrite(image->pixels, sizeof(unsigned char), image->channels * image->height * image->width, out);

	fclose(out);
}
<commit_msg>Fixed bug in image_read() where newline was not being skipped<commit_after>/**
 * @file image.c
 *
 * Implementation of the image type.
 *
 * The following formats are supported:
 * - binary PGM (P5)
 * - binary PPM (P6)
 */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "image.h"

/**
 * Construct a PPM image.
 *
 * @return pointer to empty PPM image
 */
image_t * image_construct()
{
	image_t *image = (image_t *)malloc(sizeof(image_t));
	image->channels = 0;
	image->height = 0;
	image->width = 0;
	image->max_value = 0;
	image->pixels = NULL;

	return image;
}

/**
 * Destruct an image.
 *
 * @param image  pointer to image
 */
void image_destruct(image_t *image)
{
	free(image->pixels);
	free(image);
}

/**
 * Helper function to skip comments in a PGM/PPM image.
 */
void skip_to_next_value(FILE* in)
{
	char c = fgetc(in);
	while ( c == '#' || isspace(c) ) {
		if ( c == '#' ) {
			while ( c != '\n' ) {
				c = fgetc(in);
			}
		}
		else {
			while ( isspace(c) ) {
				c = fgetc(in);
			}
		}
	}

	ungetc(c, in);
}

/**
 * Read an image from a PGM/PPM file.
 *
 * @param image  pointer to image
 * @param path   image filename
 */
void image_read(image_t *image, const char *path)
{
	FILE *in = fopen(path, "r");

	char header[4];

	fscanf(in, "%s", header);
	if ( strcmp(header, "P5") == 0 ) {
		image->channels = 1;
	}
	else if ( strcmp(header, "P6") == 0 ) {
		image->channels = 3;
	}
	else {
		fprintf(stderr, "error: cannot read image \'%s\'\n", path);
		exit(1);
	}

	skip_to_next_value(in);

	fscanf(in, "%d", &image->height);
	skip_to_next_value(in);

	fscanf(in, "%d", &image->width);
	skip_to_next_value(in);

	fscanf(in, "%d", &image->max_value);
	fgetc(in);

	int num = image->channels * image->height * image->width;

	if ( image->pixels == NULL ) {
		image->pixels = (unsigned char *)malloc(num * sizeof(unsigned char));
	}

	fread(image->pixels, sizeof(unsigned char), num, in);

	fclose(in);
}

/**
 * Write an image to a PGM/PPM file.
 *
 * @param image  pointer to image
 * @param path   image filename
 */
void image_write(image_t *image, const char *path)
{
	FILE *out = fopen(path, "w");

	// write image header
	if ( image->channels == 1 ) {
		fprintf(out, "P5");
	}
	else if ( image->channels == 3 ) {
		fprintf(out, "P6");
	}
	else {
		fprintf(stderr, "error: cannot write image \'%s\'\n", path);
		exit(1);
	}

	fprintf(out, "%d %d %d\n", image->height, image->width, image->max_value);

	// write pixel data
	fwrite(image->pixels, sizeof(unsigned char), image->channels * image->height * image->width, out);

	fclose(out);
}
<|endoftext|>


<commit_before><commit_msg>warning C4628: digraphs not supported with -Ze...<commit_after><|endoftext|>


<commit_before>#include "ofxAlembicType.h"

using namespace ofxAlembic;
using namespace Alembic::AbcGeom;

#pragma mark - XForm

void XForm::draw()
{
	ofDrawAxis(10);
}

#pragma mark - Points

Points::Points(const vector<ofVec3f>& ofpoints)
{
	for (int i = 0; i < ofpoints.size(); i++)
	{
		points.push_back(ofpoints[i]);
	}
}

void Points::get(OPointsSchema &schema) const
{
	int num = points.size();

	vector<V3f> positions(num);
	vector<uint64_t> ids(num);

	for (int i = 0; i < num; i++)
	{
		positions[i] = toAbc(points[i].pos);
		ids[i] = points[i].id;
	}

	OPointsSchema::Sample sample((P3fArraySample(positions)),
								 UInt64ArraySample(ids));
	schema.set(sample);
}

void Points::set(IPointsSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	IPointsSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_positions = sample.getPositions();

	size_t num_points = m_positions->size();
	const V3f *src = m_positions->get();
	V3f dst;

	points.resize(num_points);

	for (int i = 0; i < num_points; i++)
	{
		const V3f& v = src[i];
		points[i].pos.set(v.x, v.y, v.z);
	}
}

void Points::draw()
{
	glBegin(GL_POINTS);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex3fv(points[i].pos.getPtr());
	}
	glEnd();
}

#pragma mark - PolyMesh

void PolyMesh::get(OPolyMeshSchema &schema) const
{
	vector<V3f> positions;
	vector<int32_t> indexes;
	vector<int32_t> counts;
	vector<V2f> uvs;
	vector<N3f> norms;

	OV2fGeomParam::Sample uv_sample;
	ON3fGeomParam::Sample norm_sample;

	if (mesh.getNumIndices())
	{
		const int num_samples = mesh.getNumIndices();

		const vector<ofIndexType>& idx = mesh.getIndices();

		{
			indexes.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				indexes[i] = i;
		}

		{
			const vector<ofVec3f>& verts = mesh.getVertices();
			positions.resize(num_samples);

			for (int i = 0; i < num_samples; i++)
				positions[i] = toAbc(verts[idx[i]]);
		}

		if (mesh.getNumTexCoords() == mesh.getNumVertices())
		{
			const vector<ofVec2f> &v = mesh.getTexCoords();

			uvs.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				uvs[i] = toAbc(v[idx[i]]);
		}
		assert(uvs.size() == 0 || uvs.size() == num_samples);

		if (mesh.getNumNormals() == mesh.getNumVertices())
		{
			const vector<ofVec3f> &v = mesh.getNormals();

			norms.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				norms[i] = toAbc(v[idx[i]].getNormalized() * -1);
		}
		assert(norms.size() == 0 || norms.size() == num_samples);
	}
	else
	{
		const int num_samples = mesh.getNumVertices();

		{
			indexes.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				indexes[i] = i;
		}

		{
			const vector<ofVec3f>& verts = mesh.getVertices();
			positions.resize(num_samples);

			for (int i = 0; i < num_samples; i++)
				positions[i] = toAbc(verts[i]);
		}

		if (mesh.getNumTexCoords() == num_samples)
		{
			const vector<ofVec2f> &v = mesh.getTexCoords();

			uvs.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				uvs[i] = toAbc(v[i]);
		}
		assert(uvs.size() == 0 || uvs.size() == num_samples);

		if (mesh.getNumNormals() == num_samples)
		{
			const vector<ofVec3f> &v = mesh.getNormals();

			norms.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				norms[i] = toAbc(v[i].getNormalized() * -1);
		}
		assert(norms.size() == 0 || norms.size() == num_samples);
	}

	// supports only triangles
	{
		int num_tris = indexes.size() / 3;
		counts.resize(num_tris);
		for (int i = 0; i < num_tris; i++)
			counts[i] = 3;
	}

	if (!uvs.empty())
	{
		uv_sample.setScope(kVertexScope);
		uv_sample.setVals(V2fArraySample(uvs));
	}

	if (!norms.empty())
	{
		norm_sample.setScope(kVertexScope);
		norm_sample.setVals(N3fArraySample(norms));
	}

	OPolyMeshSchema::Sample sample((P3fArraySample(positions)),
								   Int32ArraySample(indexes),
								   Int32ArraySample(counts),
								   uv_sample,
								   norm_sample);
	schema.set(sample);
}

void PolyMesh::set(IPolyMeshSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	IPolyMeshSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_meshP = sample.getPositions();
	Int32ArraySamplePtr m_meshIndices = sample.getFaceIndices();
	Int32ArraySamplePtr m_meshCounts = sample.getFaceCounts();

	mesh.clear();

	size_t numFaces = m_meshCounts->size();
	size_t numIndices = m_meshIndices->size();
	size_t numPoints = m_meshP->size();
	if (numFaces < 1 ||
		numIndices < 1 ||
		numPoints < 1)
	{
		return;
	}

	// TODO: organaize face index
	// make Triangle and Quad class

	typedef Imath::Vec3<unsigned int> Tri;
	typedef std::vector<Tri> TriArray;

	TriArray m_triangles;

	size_t faceIndexBegin = 0;
	size_t faceIndexEnd = 0;
	for (size_t face = 0; face < numFaces; ++face)
	{
		faceIndexBegin = faceIndexEnd;
		size_t count = (*m_meshCounts)[face];
		faceIndexEnd = faceIndexBegin + count;

		// Check this face is valid
		if (faceIndexEnd > numIndices ||
			faceIndexEnd < faceIndexBegin)
		{
			ofLogError("ofxAlembic") << "Mesh update quitting on face: "
			<< face
			<< " because of wonky numbers"
			<< ", faceIndexBegin = " << faceIndexBegin
			<< ", faceIndexEnd = " << faceIndexEnd
			<< ", numIndices = " << numIndices
			<< ", count = " << count;

			// Just get out, make no more triangles.
			break;
		}

		// Make triangles to fill this face.
		if (count >= 3)
		{
			m_triangles.push_back(Tri((unsigned int)faceIndexBegin + 0,
									  (unsigned int)faceIndexBegin + 1,
									  (unsigned int)faceIndexBegin + 2));
			for (size_t c = 3; c < count; ++c)
			{
				m_triangles.push_back(Tri((unsigned int)faceIndexBegin + 0,
										  (unsigned int)faceIndexBegin + c - 1,
										  (unsigned int)faceIndexBegin + c));
			}
		}
	}

	{
		const V3f *points = m_meshP->get();
		const int32_t *indices = m_meshIndices->get();

		V3f dst;
		vector<ofVec3f> verts;

		for (int i = 0; i < numPoints; i++)
		{
			const V3f& v = points[i];
			verts.push_back(ofVec3f(v.x, v.y, v.z));
		}

		for (int i = 0; i < m_triangles.size(); i++)
		{
			Tri &t = m_triangles[i];
			mesh.addVertex(verts[indices[t[0]]]);
			mesh.addVertex(verts[indices[t[1]]]);
			mesh.addVertex(verts[indices[t[2]]]);
		}
	}

	{
		IN3fGeomParam N = schema.getNormalsParam();
		if (N.valid())
		{
			if (N.isIndexed())
			{
				ofLogError("ofxAlembic::PolyMesh") << "indexed normal is not supported";
			}
			else
			{
				N3fArraySamplePtr norm_ptr = N.getExpandedValue(ss).getVals();
				N3f norm;
				vector<ofVec3f> norms;

				for (int i = 0; i < norm_ptr->size(); i++)
				{
					const N3f& v = (*norm_ptr)[i];
					norms.push_back(ofVec3f(v.x, v.y, v.z));
				}

				for (int i = 0; i < m_triangles.size(); i++)
				{
					Tri &t = m_triangles[i];
					mesh.addNormal(norms[t[0]]);
					mesh.addNormal(norms[t[1]]);
					mesh.addNormal(norms[t[2]]);
				}
			}
		}
	}

	{
		IV2fGeomParam UV = schema.getUVsParam();
		if (UV.valid())
		{
			if (UV.isIndexed())
			{
				ofLogError("ofxAlembic::PolyMesh") << "indexed uv is not supported";
			}
			else
			{
				V2fArraySamplePtr uv_ptr = UV.getExpandedValue(ss).getVals();

				for (int i = 0; i < m_triangles.size(); i++)
				{
					Tri &t = m_triangles[i];
					mesh.addTexCoord(toOf((*uv_ptr)[t[0]]));
					mesh.addTexCoord(toOf((*uv_ptr)[t[1]]));
					mesh.addTexCoord(toOf((*uv_ptr)[t[2]]));
				}
			}
		}
	}
}

void PolyMesh::draw()
{
	if (ofGetStyle().bFill)
	{
		mesh.draw();
	}
	else
	{
		mesh.drawWireframe();
	}
}

#pragma mark - Curves

void Curves::get(OCurvesSchema &schema) const
{
	vector<V3f> positions;
	vector<int32_t> num_vertices;

	for (int n = 0; n < curves.size(); n++)
	{
		const ofPolyline &polyline = curves[n];

		for (int i = 0; i < polyline.size(); i++)
		{
			positions.push_back(toAbc(polyline[i]));
		}

		num_vertices.push_back(polyline.size());
	}

	OCurvesSchema::Sample sample((P3fArraySample(positions)),
								 Int32ArraySample(num_vertices),
								 kLinear,
								 kNonPeriodic);
	schema.set(sample);
}

void Curves::set(ICurvesSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	ICurvesSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_positions = sample.getPositions();
	std::size_t m_nCurves = sample.getNumCurves();

	const V3f *src = m_positions->get();
	const Alembic::Util::int32_t *nVertices = sample.getCurvesNumVertices()->get();
	V3f dst;

	curves.resize(m_nCurves);

	for (int i = 0; i < m_nCurves; i++)
	{
		ofPolyline &polyline = curves[i];
		const int num = nVertices[i];

		polyline.clear();

		for (int n = 0; n < num; n++)
		{
			const V3f& v = *src;
			polyline.addVertex(ofVec3f(v.x, v.y, v.z));
			src++;
		}
	}
}

void Curves::draw()
{
	for (int i = 0; i < curves.size(); i++)
	{
		curves[i].draw();
	}
}

#pragma mark - Camera

void Camera::get(OCameraSchema &schema) const
{
	ofLogError("ofxAlembic::Camera") << "not implemented";
}

void Camera::set(ICameraSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	schema.get(sample, ss);
}

void Camera::updateParams(ofCamera &camera, ofMatrix4x4 xform)
{
	float w, h;
	if (width == 0 || height == 0)
	{
		w = ofGetViewportWidth();
		h = ofGetViewportHeight();
	}
	else
	{
		w = width;
		h = height;
	}

	float fovH = sample.getFieldOfView();
	float fovV = ofRadToDeg(2 * atanf(tanf(ofDegToRad(fovH) / 2) * (h / w)));
	camera.setFov(fovV);
	camera.setTransformMatrix(xform);

	// TODO: lens offset
}

void Camera::draw()
{
}
<commit_msg>Improve mesh read performance<commit_after>#include "ofxAlembicType.h"

using namespace ofxAlembic;
using namespace Alembic::AbcGeom;

#pragma mark - XForm

void XForm::draw()
{
	ofDrawAxis(10);
}

#pragma mark - Points

Points::Points(const vector<ofVec3f>& ofpoints)
{
	for (int i = 0; i < ofpoints.size(); i++)
	{
		points.push_back(ofpoints[i]);
	}
}

void Points::get(OPointsSchema &schema) const
{
	int num = points.size();

	vector<V3f> positions(num);
	vector<uint64_t> ids(num);

	for (int i = 0; i < num; i++)
	{
		positions[i] = toAbc(points[i].pos);
		ids[i] = points[i].id;
	}

	OPointsSchema::Sample sample((P3fArraySample(positions)),
								 UInt64ArraySample(ids));
	schema.set(sample);
}

void Points::set(IPointsSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	IPointsSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_positions = sample.getPositions();

	size_t num_points = m_positions->size();
	const V3f *src = m_positions->get();
	V3f dst;

	points.resize(num_points);

	for (int i = 0; i < num_points; i++)
	{
		const V3f& v = src[i];
		points[i].pos.set(v.x, v.y, v.z);
	}
}

void Points::draw()
{
	glBegin(GL_POINTS);
	for (int i = 0; i < points.size(); i++)
	{
		glVertex3fv(points[i].pos.getPtr());
	}
	glEnd();
}

#pragma mark - PolyMesh

void PolyMesh::get(OPolyMeshSchema &schema) const
{
	vector<V3f> positions;
	vector<int32_t> indexes;
	vector<int32_t> counts;
	vector<V2f> uvs;
	vector<N3f> norms;

	OV2fGeomParam::Sample uv_sample;
	ON3fGeomParam::Sample norm_sample;

	if (mesh.getNumIndices())
	{
		const int num_samples = mesh.getNumIndices();

		const vector<ofIndexType>& idx = mesh.getIndices();

		{
			indexes.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				indexes[i] = i;
		}

		{
			const vector<ofVec3f>& verts = mesh.getVertices();
			positions.resize(num_samples);

			for (int i = 0; i < num_samples; i++)
				positions[i] = toAbc(verts[idx[i]]);
		}

		if (mesh.getNumTexCoords() == mesh.getNumVertices())
		{
			const vector<ofVec2f> &v = mesh.getTexCoords();

			uvs.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				uvs[i] = toAbc(v[idx[i]]);
		}
		assert(uvs.size() == 0 || uvs.size() == num_samples);

		if (mesh.getNumNormals() == mesh.getNumVertices())
		{
			const vector<ofVec3f> &v = mesh.getNormals();

			norms.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				norms[i] = toAbc(v[idx[i]].getNormalized() * -1);
		}
		assert(norms.size() == 0 || norms.size() == num_samples);
	}
	else
	{
		const int num_samples = mesh.getNumVertices();

		{
			indexes.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				indexes[i] = i;
		}

		{
			const vector<ofVec3f>& verts = mesh.getVertices();
			positions.resize(num_samples);

			for (int i = 0; i < num_samples; i++)
				positions[i] = toAbc(verts[i]);
		}

		if (mesh.getNumTexCoords() == num_samples)
		{
			const vector<ofVec2f> &v = mesh.getTexCoords();

			uvs.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				uvs[i] = toAbc(v[i]);
		}
		assert(uvs.size() == 0 || uvs.size() == num_samples);

		if (mesh.getNumNormals() == num_samples)
		{
			const vector<ofVec3f> &v = mesh.getNormals();

			norms.resize(num_samples);
			for (int i = 0; i < num_samples; i++)
				norms[i] = toAbc(v[i].getNormalized() * -1);
		}
		assert(norms.size() == 0 || norms.size() == num_samples);
	}

	// supports only triangles
	{
		int num_tris = indexes.size() / 3;
		counts.resize(num_tris);
		for (int i = 0; i < num_tris; i++)
			counts[i] = 3;
	}

	if (!uvs.empty())
	{
		uv_sample.setScope(kVertexScope);
		uv_sample.setVals(V2fArraySample(uvs));
	}

	if (!norms.empty())
	{
		norm_sample.setScope(kVertexScope);
		norm_sample.setVals(N3fArraySample(norms));
	}

	OPolyMeshSchema::Sample sample((P3fArraySample(positions)),
								   Int32ArraySample(indexes),
								   Int32ArraySample(counts),
								   uv_sample,
								   norm_sample);
	schema.set(sample);
}

void PolyMesh::set(IPolyMeshSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	IPolyMeshSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_meshP = sample.getPositions();
	Int32ArraySamplePtr m_meshIndices = sample.getFaceIndices();
	Int32ArraySamplePtr m_meshCounts = sample.getFaceCounts();

	mesh.clear();

	size_t numFaces = m_meshCounts->size();
	size_t numIndices = m_meshIndices->size();
	size_t numPoints = m_meshP->size();
	if (numFaces < 1 ||
		numIndices < 1 ||
		numPoints < 1)
	{
		return;
	}

	// TODO: organaize face index
	// make Triangle and Quad class

	typedef Imath::Vec3<unsigned int> Tri;
	typedef std::vector<Tri> TriArray;

	TriArray m_triangles;

	size_t faceIndexBegin = 0;
	size_t faceIndexEnd = 0;
	for (size_t face = 0; face < numFaces; ++face)
	{
		faceIndexBegin = faceIndexEnd;
		size_t count = (*m_meshCounts)[face];
		faceIndexEnd = faceIndexBegin + count;

		// Check this face is valid
		if (faceIndexEnd > numIndices ||
			faceIndexEnd < faceIndexBegin)
		{
			ofLogError("ofxAlembic") << "Mesh update quitting on face: "
			<< face
			<< " because of wonky numbers"
			<< ", faceIndexBegin = " << faceIndexBegin
			<< ", faceIndexEnd = " << faceIndexEnd
			<< ", numIndices = " << numIndices
			<< ", count = " << count;

			// Just get out, make no more triangles.
			break;
		}

		// Make triangles to fill this face.
		if (count >= 3)
		{
			m_triangles.push_back(Tri((unsigned int)faceIndexBegin + 0,
									  (unsigned int)faceIndexBegin + 1,
									  (unsigned int)faceIndexBegin + 2));
			for (size_t c = 3; c < count; ++c)
			{
				m_triangles.push_back(Tri((unsigned int)faceIndexBegin + 0,
										  (unsigned int)faceIndexBegin + c - 1,
										  (unsigned int)faceIndexBegin + c));
			}
		}
	}

	{
		const V3f* points = m_meshP->get();
		const int32_t* indices = m_meshIndices->get();
		vector<ofVec3f>& dst = mesh.getVertices();
		dst.resize(m_triangles.size() * 3);

		ofVec3f* dst_ptr = dst.data();

		for (int i = 0; i < m_triangles.size(); i++)
		{
			Tri &t = m_triangles[i];

			const V3f& v0 = points[indices[t[0]]];
			memmove(dst_ptr++, &v0.x, sizeof(float) * 3);

			const V3f& v1 = points[indices[t[1]]];
			memmove(dst_ptr++, &v1.x, sizeof(float) * 3);

			const V3f& v2 = points[indices[t[2]]];
			memmove(dst_ptr++, &v2.x, sizeof(float) * 3);
		}
	}

	{
		IN3fGeomParam N = schema.getNormalsParam();
		if (N.valid())
		{
			if (N.isIndexed())
			{
				ofLogError("ofxAlembic::PolyMesh") << "indexed normal is not supported";
			}
			else
			{
				N3fArraySamplePtr norm_ptr = N.getExpandedValue(ss).getVals();
				const N3f* src = norm_ptr->get();
				vector<ofVec3f>& dst = mesh.getNormals();
				dst.resize(m_triangles.size() * 3);

				ofVec3f* dst_ptr = dst.data();

				for (int i = 0; i < m_triangles.size(); i++)
				{
					Tri &t = m_triangles[i];

					const N3f& n0 = src[t[0]];
					memmove(dst_ptr++, &n0.x, sizeof(float) * 3);

					const N3f& n1 = src[t[1]];
					memmove(dst_ptr++, &n1.x, sizeof(float) * 3);

					const N3f& n2 = src[t[2]];
					memmove(dst_ptr++, &n2.x, sizeof(float) * 3);
				}
			}
		}
	}

	{
		IV2fGeomParam UV = schema.getUVsParam();
		if (UV.valid())
		{
			if (UV.isIndexed())
			{
				ofLogError("ofxAlembic::PolyMesh") << "indexed uv is not supported";
			}
			else
			{
				V2fArraySamplePtr uv_ptr = UV.getExpandedValue(ss).getVals();
				const V2f* src = uv_ptr->get();
				vector<ofVec2f>& dst = mesh.getTexCoords();
				dst.resize(m_triangles.size() * 3);

				ofVec2f* dst_ptr = dst.data();

				for (int i = 0; i < m_triangles.size(); i++)
				{
					Tri &t = m_triangles[i];

					const V2f& t0 = src[t[0]];
					memmove(dst_ptr++, &t0.x, sizeof(float) * 2);

					const V2f& t1 = src[t[1]];
					memmove(dst_ptr++, &t1.x, sizeof(float) * 2);

					const V2f& t2 = src[t[2]];
					memmove(dst_ptr++, &t2.x, sizeof(float) * 2);
				}
			}
		}
	}
}

void PolyMesh::draw()
{
	if (ofGetStyle().bFill)
	{
		mesh.draw();
	}
	else
	{
		mesh.drawWireframe();
	}
}

#pragma mark - Curves

void Curves::get(OCurvesSchema &schema) const
{
	vector<V3f> positions;
	vector<int32_t> num_vertices;

	for (int n = 0; n < curves.size(); n++)
	{
		const ofPolyline &polyline = curves[n];

		for (int i = 0; i < polyline.size(); i++)
		{
			positions.push_back(toAbc(polyline[i]));
		}

		num_vertices.push_back(polyline.size());
	}

	OCurvesSchema::Sample sample((P3fArraySample(positions)),
								 Int32ArraySample(num_vertices),
								 kLinear,
								 kNonPeriodic);
	schema.set(sample);
}

void Curves::set(ICurvesSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	ICurvesSchema::Sample sample;
	schema.get(sample, ss);

	P3fArraySamplePtr m_positions = sample.getPositions();
	std::size_t m_nCurves = sample.getNumCurves();

	const V3f *src = m_positions->get();
	const Alembic::Util::int32_t *nVertices = sample.getCurvesNumVertices()->get();
	V3f dst;

	curves.resize(m_nCurves);

	for (int i = 0; i < m_nCurves; i++)
	{
		ofPolyline &polyline = curves[i];
		const int num = nVertices[i];

		polyline.clear();

		for (int n = 0; n < num; n++)
		{
			const V3f& v = *src;
			polyline.addVertex(ofVec3f(v.x, v.y, v.z));
			src++;
		}
	}
}

void Curves::draw()
{
	for (int i = 0; i < curves.size(); i++)
	{
		curves[i].draw();
	}
}

#pragma mark - Camera

void Camera::get(OCameraSchema &schema) const
{
	ofLogError("ofxAlembic::Camera") << "not implemented";
}

void Camera::set(ICameraSchema &schema, float time)
{
	ISampleSelector ss(time, ISampleSelector::kNearIndex);
	schema.get(sample, ss);
}

void Camera::updateParams(ofCamera &camera, ofMatrix4x4 xform)
{
	float w, h;
	if (width == 0 || height == 0)
	{
		w = ofGetViewportWidth();
		h = ofGetViewportHeight();
	}
	else
	{
		w = width;
		h = height;
	}

	float fovH = sample.getFieldOfView();
	float fovV = ofRadToDeg(2 * atanf(tanf(ofDegToRad(fovH) / 2) * (h / w)));
	camera.setFov(fovV);
	camera.setTransformMatrix(xform);

	// TODO: lens offset
}

void Camera::draw()
{
}
<|endoftext|>


<commit_before>//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the clang::ParseAST method.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
#include <memory>

using namespace clang;

namespace {

/// If a crash happens while the parser is active, an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
  const Parser &P;
public:
  PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
  void print(raw_ostream &OS) const override;
};

/// If a crash happens while the parser is active, print out a line indicating
/// what the current token is.
void PrettyStackTraceParserEntry::print(raw_ostream &OS) const {
  const Token &Tok = P.getCurToken();
  if (Tok.is(tok::eof)) {
    OS << "<eof> parser at end of file\n";
    return;
  }

  if (Tok.getLocation().isInvalid()) {
    OS << "<unknown> parser at unknown location\n";
    return;
  }

  const Preprocessor &PP = P.getPreprocessor();
  Tok.getLocation().print(OS, PP.getSourceManager());
  if (Tok.isAnnotation()) {
    OS << ": at annotation token\n";
  } else {
    // Do the equivalent of PP.getSpelling(Tok) except for the parts that would
    // allocate memory.
    bool Invalid = false;
    const SourceManager &SM = P.getPreprocessor().getSourceManager();
    unsigned Length = Tok.getLength();
    const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid);
    if (Invalid) {
      OS << ": unknown current parser token\n";
      return;
    }
    OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n";
  }
}

}  // namespace

//===----------------------------------------------------------------------===//
// Public interface to the file
//===----------------------------------------------------------------------===//

/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.  This inserts the parsed decls into the translation unit
/// held by Ctx.
///
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
                     ASTContext &Ctx, bool PrintStats,
                     TranslationUnitKind TUKind,
                     CodeCompleteConsumer *CompletionConsumer,
                     bool SkipFunctionBodies) {

  std::unique_ptr<Sema> S(
      new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());

  ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}

void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::EnableStatistics();
    Stmt::EnableStatistics();
  }

  // Also turn on collection of stats inside of the Sema object.
  bool OldCollectStats = PrintStats;
  std::swap(OldCollectStats, S.CollectStats);

  ASTConsumer *Consumer = &S.getASTConsumer();

  std::unique_ptr<Parser> ParseOP(
      new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
  Parser &P = *ParseOP.get();

  PrettyStackTraceParserEntry CrashInfo(P);

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Parser>
    CleanupParser(ParseOP.get());

  S.getPreprocessor().EnterMainSourceFile();
  P.Initialize();

  // C11 6.9p1 says translation units must have at least one top-level
  // declaration. C++ doesn't have this restriction. We also don't want to
  // complain if we have a precompiled header, although technically if the PCH
  // is empty we should still emit the (pedantic) diagnostic.
  Parser::DeclGroupPtrTy ADecl;
  ExternalASTSource *External = S.getASTContext().getExternalSource();
  if (External)
    External->StartTranslationUnit(Consumer);

  if (P.ParseTopLevelDecl(ADecl)) {
    if (!External && !S.getLangOpts().CPlusPlus)
      P.Diag(diag::ext_empty_translation_unit);
  } else {
    do {
      // If we got a null return and something *was* parsed, ignore it.  This
      // is due to a top-level semicolon, an action override, or a parse error
      // skipping something.
      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
        return;
    } while (!P.ParseTopLevelDecl(ADecl));
  }

  // Process any TopLevelDecls generated by #pragma weak.
  for (Decl *D : S.WeakTopLevelDecls())
    Consumer->HandleTopLevelDecl(DeclGroupRef(D));

  Consumer->HandleTranslationUnit(S.getASTContext());

  std::swap(OldCollectStats, S.CollectStats);
  if (PrintStats) {
    llvm::errs() << "\nSTATISTICS:\n";
    P.getActions().PrintStats();
    S.getASTContext().PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();
  }
}
<commit_msg>Restore PrettyStackTrace state on crash.<commit_after>//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the clang::ParseAST method.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
#include <memory>

using namespace clang;

namespace {

/// Resets LLVM's pretty stack state so that stack traces are printed correctly
/// when there are nested CrashRecoveryContexts and the inner one recovers from
/// a crash.
class ResetStackCleanup
    : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup,
                                                   const void> {
public:
  ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top)
      : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>(
            Context, Top) {}
  void recoverResources() override {
    llvm::RestorePrettyStackState(resource);
  }
};

/// If a crash happens while the parser is active, an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
  const Parser &P;
public:
  PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
  void print(raw_ostream &OS) const override;
};

/// If a crash happens while the parser is active, print out a line indicating
/// what the current token is.
void PrettyStackTraceParserEntry::print(raw_ostream &OS) const {
  const Token &Tok = P.getCurToken();
  if (Tok.is(tok::eof)) {
    OS << "<eof> parser at end of file\n";
    return;
  }

  if (Tok.getLocation().isInvalid()) {
    OS << "<unknown> parser at unknown location\n";
    return;
  }

  const Preprocessor &PP = P.getPreprocessor();
  Tok.getLocation().print(OS, PP.getSourceManager());
  if (Tok.isAnnotation()) {
    OS << ": at annotation token\n";
  } else {
    // Do the equivalent of PP.getSpelling(Tok) except for the parts that would
    // allocate memory.
    bool Invalid = false;
    const SourceManager &SM = P.getPreprocessor().getSourceManager();
    unsigned Length = Tok.getLength();
    const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid);
    if (Invalid) {
      OS << ": unknown current parser token\n";
      return;
    }
    OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n";
  }
}

}  // namespace

//===----------------------------------------------------------------------===//
// Public interface to the file
//===----------------------------------------------------------------------===//

/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.  This inserts the parsed decls into the translation unit
/// held by Ctx.
///
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
                     ASTContext &Ctx, bool PrintStats,
                     TranslationUnitKind TUKind,
                     CodeCompleteConsumer *CompletionConsumer,
                     bool SkipFunctionBodies) {

  std::unique_ptr<Sema> S(
      new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());

  ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}

void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::EnableStatistics();
    Stmt::EnableStatistics();
  }

  // Also turn on collection of stats inside of the Sema object.
  bool OldCollectStats = PrintStats;
  std::swap(OldCollectStats, S.CollectStats);

  ASTConsumer *Consumer = &S.getASTConsumer();

  std::unique_ptr<Parser> ParseOP(
      new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
  Parser &P = *ParseOP.get();

  llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup>
      CleanupPrettyStack(llvm::SavePrettyStackState());
  PrettyStackTraceParserEntry CrashInfo(P);

  // Recover resources if we crash before exiting this method.
  llvm::CrashRecoveryContextCleanupRegistrar<Parser>
    CleanupParser(ParseOP.get());

  S.getPreprocessor().EnterMainSourceFile();
  P.Initialize();

  // C11 6.9p1 says translation units must have at least one top-level
  // declaration. C++ doesn't have this restriction. We also don't want to
  // complain if we have a precompiled header, although technically if the PCH
  // is empty we should still emit the (pedantic) diagnostic.
  Parser::DeclGroupPtrTy ADecl;
  ExternalASTSource *External = S.getASTContext().getExternalSource();
  if (External)
    External->StartTranslationUnit(Consumer);

  if (P.ParseTopLevelDecl(ADecl)) {
    if (!External && !S.getLangOpts().CPlusPlus)
      P.Diag(diag::ext_empty_translation_unit);
  } else {
    do {
      // If we got a null return and something *was* parsed, ignore it.  This
      // is due to a top-level semicolon, an action override, or a parse error
      // skipping something.
      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
        return;
    } while (!P.ParseTopLevelDecl(ADecl));
  }

  // Process any TopLevelDecls generated by #pragma weak.
  for (Decl *D : S.WeakTopLevelDecls())
    Consumer->HandleTopLevelDecl(DeclGroupRef(D));

  Consumer->HandleTranslationUnit(S.getASTContext());

  std::swap(OldCollectStats, S.CollectStats);
  if (PrintStats) {
    llvm::errs() << "\nSTATISTICS:\n";
    P.getActions().PrintStats();
    S.getASTContext().PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();
  }
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include <ports/node_aware.hpp>
#include <ports/pure_ports.hpp>

using namespace fc;

BOOST_AUTO_TEST_SUITE(test_parallle_region);

BOOST_AUTO_TEST_CASE(test_region_aware_node)
{
	root_node root;
	typedef node_aware<pure::event_sink<int>> test_in_port;

	int test_value = 0;
	auto write_param = [&](int i) {test_value = i;};
	test_in_port test_in(&root, write_param);

	BOOST_CHECK_EQUAL(test_value, 0);
	test_in(1);
	BOOST_CHECK_EQUAL(test_value, 1);
}

BOOST_AUTO_TEST_CASE(test_same_region)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;

	root_node root;

	std::vector<int> test_sink;
	auto write_param = [&](int i) {test_sink.push_back(i);};
	test_in_port test_in(&root, write_param);
	test_out_port test_out(&root);

	static_assert(is_passive_sink<test_in_port>{}, "");
	static_assert(has_result<test_out_port>{},
			"its an out port, that has result_t defined");

	test_out >> test_in;

	BOOST_CHECK_EQUAL(test_sink.size(), 0);
	test_out.fire(1);
	BOOST_CHECK_EQUAL(test_sink.size(), 1);
	BOOST_CHECK_EQUAL(test_sink.at(0), 1);

	auto tmp = test_out >> [](int i ){ return ++i;};

	static_assert(is_instantiation_of<node_aware, test_in_port>{}, "");
	static_assert(not is_active_sink   <test_in_port>{}, "");
	static_assert(not is_active_source <test_in_port>{}, "");
	static_assert(    is_passive_sink  <test_in_port>{}, "");
	static_assert(not is_passive_source<test_in_port>{}, "");
	static_assert(not is_passive_source<decltype(tmp)>{}, "");
	static_assert(not is_passive_sink  <decltype(tmp)>{}, "");
	static_assert(    is_active_source <decltype(tmp)>{}, "");
	static_assert(not is_active_sink   <decltype(tmp)>{}, "");

	tmp >> test_in;

	test_out.fire(1);
	BOOST_CHECK_EQUAL(test_sink.at(1), 1);
	BOOST_CHECK_EQUAL(test_sink.at(2), 2);
}

BOOST_AUTO_TEST_CASE(test_different_region)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	test_out >> test_in;

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 1);
}

BOOST_AUTO_TEST_CASE(test_connectable_in_between)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	test_out >> [](int i){ return i+1;} >> test_in;

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 2);

	// test more than one lambda in between
	auto region_3 = std::make_shared<parallel_region>("r3");
	root_node root_3("3", region_3);

	test_in_port test_in_2(&root_3, write_param);
	test_out
			>> [](int i){ return i+1;}
			>> [](int i){ return i*2;}
			>> test_in_2;

	test_out.fire(1);
	region_1->ticks.in_switch_buffers()();
	region_2->ticks.in_work()();
	// wrong region ticked, expect no change
	BOOST_CHECK_EQUAL(test_value, 2);

	region_3->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 4);
}

BOOST_AUTO_TEST_CASE(test_multiple_connectable_in_between)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	auto inc = [](int i){ return i + 1; };

	(test_out >> inc) >> inc >> (inc >> test_in);

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 4);

	// check the same for states
	typedef node_aware<pure::state_sink<int>> test_in_state;
	typedef node_aware<pure::state_source<int>> test_out_state;

	test_out_state state_out{&root_1, [](){ return 1; }};
	test_in_state state_in{&root_2};

	(state_out >> inc) >> inc >> (inc >> state_in);
   //                          ^^^ buffer is here

	BOOST_CHECK_EQUAL(state_in.get(), 1); //one increment after buffer
	region_1->ticks.in_work()();
	BOOST_CHECK_EQUAL(state_in.get(), 1); //one increment after buffer
	region_2->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(state_in.get(), 4);
}

BOOST_AUTO_TEST_CASE(test_state_transition)
{
	typedef node_aware<pure::state_sink<int>> test_in_port;
	typedef node_aware<pure::state_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	test_out_port source(&root_1, [](){ return 1; });
	test_in_port sink(&root_2);

	static_assert(is_instantiation_of<node_aware, test_in_port>{}, "");
	static_assert(is_instantiation_of<node_aware, test_out_port>{}, "");
	static_assert(    is_active_sink   <test_in_port>{}, "");
	static_assert(not is_active_source <test_in_port>{}, "");
	static_assert(not is_passive_sink  <test_in_port>{}, "");
	static_assert(not is_passive_source<test_in_port>{}, "");
	static_assert(    is_passive_source<test_out_port>{}, "");
	static_assert(not is_passive_sink  <test_out_port>{}, "");
	static_assert(not is_active_source <test_out_port>{}, "");
	static_assert(not is_active_sink   <test_out_port>{}, "");

	static_assert(std::is_same<int,
			result_of_t<test_out_port>>{},
			"return value of source is defined to be int");
	source >> sink;

	BOOST_CHECK_EQUAL(sink.get(), 0);

	region_1->ticks.in_work()();
	BOOST_CHECK_EQUAL(sink.get(), 0);
	region_2->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(sink.get(), 1);
}

BOOST_AUTO_TEST_CASE(test_state_same_region)
{
	typedef node_aware<pure::state_sink<int>> test_in_port;
	typedef node_aware<pure::state_source<int>> test_out_port;
	root_node root;

	test_out_port source(&root, [](){ return 1; });
	test_in_port sink(&root);

	source >> sink;

	//expect result to be available immediately without switch tick,
	//since we are in the same region
	BOOST_CHECK_EQUAL(sink.get(), 1);
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>tests: FIX test for node_aware.<commit_after>#include <boost/test/unit_test.hpp>

#include <ports/node_aware.hpp>
#include <ports/pure_ports.hpp>

using namespace fc;

BOOST_AUTO_TEST_SUITE(test_parallle_region);

BOOST_AUTO_TEST_CASE(test_region_aware_node)
{
	root_node root;
	typedef node_aware<pure::event_sink<int>> test_in_port;

	int test_value = 0;
	auto write_param = [&](int i) {test_value = i;};
	test_in_port test_in(&root, write_param);

	BOOST_CHECK_EQUAL(test_value, 0);
	test_in(1);
	BOOST_CHECK_EQUAL(test_value, 1);
}

BOOST_AUTO_TEST_CASE(test_same_region)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;

	root_node root;

	std::vector<int> test_sink;
	auto write_param = [&](int i) {test_sink.push_back(i);};
	test_in_port test_in(&root, write_param);
	test_out_port test_out(&root);

	static_assert(is_passive_sink<test_in_port>{}, "");
	static_assert(has_result<test_out_port>{},
			"its an out port, that has result_t defined");

	test_out >> test_in;

	BOOST_CHECK_EQUAL(test_sink.size(), 0);
	test_out.fire(1);
	BOOST_CHECK_EQUAL(test_sink.size(), 1);
	BOOST_CHECK_EQUAL(test_sink.at(0), 1);

	auto tmp = test_out >> [](int i ){ return ++i;};

	static_assert(is_instantiation_of<node_aware, test_in_port>{}, "");
	static_assert(not is_active_sink   <test_in_port>{}, "");
	static_assert(not is_active_source <test_in_port>{}, "");
	static_assert(    is_passive_sink  <test_in_port>{}, "");
	static_assert(not is_passive_source<test_in_port>{}, "");
	static_assert(not is_passive_source<decltype(tmp)>{}, "");
	static_assert(not is_passive_sink  <decltype(tmp)>{}, "");
	static_assert(    is_active_source <decltype(tmp)>{}, "");
	static_assert(not is_active_sink   <decltype(tmp)>{}, "");

	tmp >> test_in;

	test_out.fire(1);
	BOOST_CHECK_EQUAL(test_sink.at(1), 1);
	BOOST_CHECK_EQUAL(test_sink.at(2), 2);
}

BOOST_AUTO_TEST_CASE(test_different_region)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	test_out >> test_in;

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 1);
}

BOOST_AUTO_TEST_CASE(test_connectable_in_between)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	test_out >> [](int i){ return i+1;} >> test_in;

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 2);

	// test more than one lambda in between
	auto region_3 = std::make_shared<parallel_region>("r3");
	root_node root_3("3", region_3);

	test_in_port test_in_2(&root_3, write_param);
	test_out
			>> [](int i){ return i+1;}
			>> [](int i){ return i*2;}
			>> test_in_2;

	test_out.fire(1);
	region_1->ticks.in_switch_buffers()();
	region_2->ticks.in_work()();
	// wrong region ticked, expect no change
	BOOST_CHECK_EQUAL(test_value, 2);

	region_3->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 4);
}

BOOST_AUTO_TEST_CASE(test_multiple_connectable_in_between)
{
	typedef node_aware<pure::event_sink<int>> test_in_port;
	typedef node_aware<pure::event_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	int test_value = 0;
	auto write_param = [&test_value](int i) {test_value = i;};
	test_in_port test_in(&root_2, write_param);
	test_out_port test_out(&root_1);

	auto inc = [](int i){ return i + 1; };

	(test_out >> inc) >> inc >> (inc >> test_in);

	BOOST_CHECK_EQUAL(test_value, 0);
	test_out.fire(1);
	//since we have a region transition, we need a switch tick
	BOOST_CHECK_EQUAL(test_value, 0);

	region_1->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(test_value, 0);
	region_2->ticks.in_work()();
	BOOST_CHECK_EQUAL(test_value, 4);

	// check the same for states
	typedef node_aware<pure::state_sink<int>> test_in_state;
	typedef node_aware<pure::state_source<int>> test_out_state;

	test_out_state state_out{&root_1, [](){ return 1; }};
	test_in_state state_in{&root_2};

	(state_out >> inc) >> inc >> (inc >> state_in);
	//                                 ^^^ buffer is here

	BOOST_CHECK_EQUAL(state_in.get(), 0); //one increment after buffer
	region_1->ticks.in_work()();
	BOOST_CHECK_EQUAL(state_in.get(), 0); //one increment after buffer
	region_2->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(state_in.get(), 4);
}

BOOST_AUTO_TEST_CASE(test_state_transition)
{
	typedef node_aware<pure::state_sink<int>> test_in_port;
	typedef node_aware<pure::state_source<int>> test_out_port;
	auto region_1 = std::make_shared<parallel_region>("r1");
	auto region_2 = std::make_shared<parallel_region>("r2");
	root_node root_1("1", region_1);
	root_node root_2("2", region_2);

	test_out_port source(&root_1, [](){ return 1; });
	test_in_port sink(&root_2);

	static_assert(is_instantiation_of<node_aware, test_in_port>{}, "");
	static_assert(is_instantiation_of<node_aware, test_out_port>{}, "");
	static_assert(    is_active_sink   <test_in_port>{}, "");
	static_assert(not is_active_source <test_in_port>{}, "");
	static_assert(not is_passive_sink  <test_in_port>{}, "");
	static_assert(not is_passive_source<test_in_port>{}, "");
	static_assert(    is_passive_source<test_out_port>{}, "");
	static_assert(not is_passive_sink  <test_out_port>{}, "");
	static_assert(not is_active_source <test_out_port>{}, "");
	static_assert(not is_active_sink   <test_out_port>{}, "");

	static_assert(std::is_same<int,
			result_of_t<test_out_port>>{},
			"return value of source is defined to be int");
	source >> sink;

	BOOST_CHECK_EQUAL(sink.get(), 0);

	region_1->ticks.in_work()();
	BOOST_CHECK_EQUAL(sink.get(), 0);
	region_2->ticks.in_switch_buffers()();
	BOOST_CHECK_EQUAL(sink.get(), 1);
}

BOOST_AUTO_TEST_CASE(test_state_same_region)
{
	typedef node_aware<pure::state_sink<int>> test_in_port;
	typedef node_aware<pure::state_source<int>> test_out_port;
	root_node root;

	test_out_port source(&root, [](){ return 1; });
	test_in_port sink(&root);

	source >> sink;

	//expect result to be available immediately without switch tick,
	//since we are in the same region
	BOOST_CHECK_EQUAL(sink.get(), 1);
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Andrew Manson <g.real.ate@gmail.com>
// Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
//

#include "GeoTagWriter.h"

#include "GeoWriter.h"

#include <QtCore/QDebug>

namespace Marble
{

GeoTagWriter::TagHash* GeoTagWriter::s_tagWriterHash = 0;

GeoTagWriter::GeoTagWriter()
{
}

GeoTagWriter::~GeoTagWriter()
{
}

bool GeoTagWriter::writeElement( const GeoNode *object,
                                 GeoWriter &writer) const
{
    return writer.writeElement( object );
}

void GeoTagWriter::registerWriter(const QualifiedName& name,
                                  const GeoTagWriter* writer )
{
    TagHash* tagHash = tagWriterHash();

    if ( !tagHash->contains( name ) ) {
        qWarning() << "Warning: The tag" << name << "is already registered. Often this indicates that multiple versions of the marblewidget library are loaded at the same time. This will likely lead to problems. Please check your installation, especially internal Marble plugins and external applications that install Marble plugins.";
    }
    Q_ASSERT( !tagHash->contains( name ) );
    tagHash->insert( name, writer );
    Q_ASSERT( tagHash->contains( name ) );
}

GeoTagWriter::TagHash* GeoTagWriter::tagWriterHash()
{
    if( !s_tagWriterHash ) {
        s_tagWriterHash = new TagHash();
    }

    Q_ASSERT( s_tagWriterHash );
    return s_tagWriterHash;
}

const GeoTagWriter* GeoTagWriter::recognizes( const QualifiedName &qname )
{
    TagHash* hash = tagWriterHash();

    if( !hash->contains( qname ) ) {
        return 0;
    }

    return hash->value( qname );
}

}
<commit_msg>Fix check<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Andrew Manson <g.real.ate@gmail.com>
// Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
//

#include "GeoTagWriter.h"

#include "GeoWriter.h"

#include <QtCore/QDebug>

namespace Marble
{

GeoTagWriter::TagHash* GeoTagWriter::s_tagWriterHash = 0;

GeoTagWriter::GeoTagWriter()
{
}

GeoTagWriter::~GeoTagWriter()
{
}

bool GeoTagWriter::writeElement( const GeoNode *object,
                                 GeoWriter &writer) const
{
    return writer.writeElement( object );
}

void GeoTagWriter::registerWriter(const QualifiedName& name,
                                  const GeoTagWriter* writer )
{
    TagHash* tagHash = tagWriterHash();

    if ( tagHash->contains( name ) ) {
        qWarning() << "Warning: The tag" << name << "is already registered. Often this indicates that multiple versions of the marblewidget library are loaded at the same time. This will likely lead to problems. Please check your installation, especially internal Marble plugins and external applications that install Marble plugins.";
    }
    Q_ASSERT( !tagHash->contains( name ) );
    tagHash->insert( name, writer );
    Q_ASSERT( tagHash->contains( name ) );
}

GeoTagWriter::TagHash* GeoTagWriter::tagWriterHash()
{
    if( !s_tagWriterHash ) {
        s_tagWriterHash = new TagHash();
    }

    Q_ASSERT( s_tagWriterHash );
    return s_tagWriterHash;
}

const GeoTagWriter* GeoTagWriter::recognizes( const QualifiedName &qname )
{
    TagHash* hash = tagWriterHash();

    if( !hash->contains( qname ) ) {
        return 0;
    }

    return hash->value( qname );
}

}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2019 Carsten Burstedde, Donna Calhoun, Scott Aiton, Grady Wright
  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.

  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 "mgtest_user.h"

#include <fclaw2d_include_all.h>

#include <fclaw2d_output.h>
#include <fclaw2d_diagnostics.h>

#include <fclaw2d_elliptic_solver.h>

#include <fclaw2d_clawpatch_options.h>
#include <fclaw2d_clawpatch.h>

#include <fc2d_multigrid.h>
#include <fc2d_multigrid_options.h>

static
fclaw2d_domain_t* create_domain(sc_MPI_Comm mpicomm, fclaw_options_t* fclaw_opt)
{
    /* Mapped, multi-block domain */
    p4est_connectivity_t     *conn = NULL;
    fclaw2d_domain_t         *domain;
    fclaw2d_map_context_t    *cont = NULL, *brick = NULL;

    int mi = fclaw_opt->mi;
    int mj = fclaw_opt->mj;

    int a = fclaw_opt->periodic_x;
    int b = fclaw_opt->periodic_y;

    /* Map unit square to disk using mapc2m_disk.f */
    conn = p4est_connectivity_new_brick(mi,mj,a,b);
    brick = fclaw2d_map_new_brick(conn,mi,mj);
    cont = fclaw2d_map_new_nomap_brick(brick);

    domain = fclaw2d_domain_new_conn_map (mpicomm, fclaw_opt->minlevel, conn, cont);
    fclaw2d_domain_list_levels(domain, FCLAW_VERBOSITY_ESSENTIAL);
    fclaw2d_domain_list_neighbors(domain, FCLAW_VERBOSITY_DEBUG);
    return domain;
}

static
void run_program(fclaw2d_global_t* glob)
{
    // const mgtest_options_t           *user_opt;

    // user_opt = mgtest_get_options(glob);

    /* ---------------------------------------------------------------
       Set domain data.
       --------------------------------------------------------------- */
    fclaw2d_domain_data_new(glob->domain);

    /* Initialize virtual table for ForestClaw */
    fclaw2d_vtables_initialize(glob);

    /* Test multigrid solver */
    fc2d_multigrid_solver_initialize();

    /* set up elliptic solver to use the multigrid solver */
    mgtest_link_solvers(glob);

    /* ---------------------------------------------------------------
       Run
       --------------------------------------------------------------- */

    /* Set up grid and RHS */
    fclaw2d_initialize(glob);

    /* Output rhs */
    int Frame = 0;
    fclaw2d_output_frame(glob,Frame);

    /* Compute sum of RHS; reset error accumulators */
    int init_flag = 1;
    fclaw2d_diagnostics_gather(glob,init_flag);
    init_flag = 0;

    /* Solve the elliptic problem */
    fclaw2d_elliptic_solve(glob);

    /* Compute error, compute conservation */
    fclaw2d_diagnostics_gather(glob, init_flag);

    /* Output solution */
    Frame = 2;
    fclaw2d_output_frame(glob,Frame);

    /* ---------------------------------------------------------------
       Finalize
       --------------------------------------------------------------- */
    fclaw2d_finalize(glob);
}

int
main (int argc, char **argv)
{
    fclaw_app_t *app;
    int first_arg;
    fclaw_exit_type_t vexit;

    /* Options */
    sc_options_t                *options;
    fclaw_options_t             *fclaw_opt;

    fclaw2d_clawpatch_options_t *clawpatch_opt;
    fc2d_multigrid_options_t    *mg_opt;
    mgtest_options_t              *user_opt;

    fclaw2d_global_t            *glob;
    fclaw2d_domain_t            *domain;
    sc_MPI_Comm mpicomm;

    int retval;

    /* Initialize application */
    app = fclaw_app_new (&argc, &argv, NULL);

    /* Create new options packages */
    fclaw_opt =                   fclaw_options_register(app,"fclaw_options.ini");
    clawpatch_opt =   fclaw2d_clawpatch_options_register(app,"fclaw_options.ini");
    mg_opt =        fc2d_multigrid_options_register(app,"fclaw_options.ini");
    user_opt =                    mgtest_options_register(app,"fclaw_options.ini");

    /* Read configuration file(s) and command line, and process options */
    options = fclaw_app_get_options (app);
    retval = fclaw_options_read_from_file(options);
    vexit =  fclaw_app_options_parse (app, &first_arg,"fclaw_options.ini.used");

    /* Run the program */
    if (!retval & !vexit)
    {
        /* Options have been checked and are valid */

        mpicomm = fclaw_app_get_mpi_size_rank (app, NULL, NULL);
        domain = create_domain(mpicomm, fclaw_opt);

        /* Create global structure which stores the domain, timers, etc */
        glob = fclaw2d_global_new();
        fclaw2d_global_store_domain(glob, domain);

        /* Store option packages in glob */
        fclaw2d_options_store           (glob, fclaw_opt);
        fclaw2d_clawpatch_options_store (glob, clawpatch_opt);
        fc2d_multigrid_options_store    (glob, mg_opt);
        mgtest_options_store            (glob, user_opt);

        run_program(glob);

        fclaw2d_global_destroy(glob);
    }

    fclaw_app_destroy (app);

    return 0;
}
<commit_msg>(elliptic/mgtest) Don't output RHS until error/soln have been computed<commit_after>/*
  Copyright (c) 2019 Carsten Burstedde, Donna Calhoun, Scott Aiton, Grady Wright
  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.

  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 "mgtest_user.h"

#include <fclaw2d_include_all.h>

#include <fclaw2d_output.h>
#include <fclaw2d_diagnostics.h>

#include <fclaw2d_elliptic_solver.h>

#include <fclaw2d_clawpatch_options.h>
#include <fclaw2d_clawpatch.h>

#include <fc2d_multigrid.h>
#include <fc2d_multigrid_options.h>

static
fclaw2d_domain_t* create_domain(sc_MPI_Comm mpicomm, fclaw_options_t* fclaw_opt)
{
    /* Mapped, multi-block domain */
    p4est_connectivity_t     *conn = NULL;
    fclaw2d_domain_t         *domain;
    fclaw2d_map_context_t    *cont = NULL, *brick = NULL;

    int mi = fclaw_opt->mi;
    int mj = fclaw_opt->mj;

    int a = fclaw_opt->periodic_x;
    int b = fclaw_opt->periodic_y;

    /* Map unit square to disk using mapc2m_disk.f */
    conn = p4est_connectivity_new_brick(mi,mj,a,b);
    brick = fclaw2d_map_new_brick(conn,mi,mj);
    cont = fclaw2d_map_new_nomap_brick(brick);

    domain = fclaw2d_domain_new_conn_map (mpicomm, fclaw_opt->minlevel, conn, cont);
    fclaw2d_domain_list_levels(domain, FCLAW_VERBOSITY_ESSENTIAL);
    fclaw2d_domain_list_neighbors(domain, FCLAW_VERBOSITY_DEBUG);
    return domain;
}

static
void run_program(fclaw2d_global_t* glob)
{
    // const mgtest_options_t           *user_opt;

    // user_opt = mgtest_get_options(glob);

    /* ---------------------------------------------------------------
       Set domain data.
       --------------------------------------------------------------- */
    fclaw2d_domain_data_new(glob->domain);

    /* Initialize virtual table for ForestClaw */
    fclaw2d_vtables_initialize(glob);

    /* Test multigrid solver */
    fc2d_multigrid_solver_initialize();

    /* set up elliptic solver to use the multigrid solver */
    mgtest_link_solvers(glob);

    /* ---------------------------------------------------------------
       Run
       --------------------------------------------------------------- */

    /* Set up grid and RHS */
    fclaw2d_initialize(glob);

    /* Compute sum of RHS; reset error accumulators */
    int init_flag = 1;
    fclaw2d_diagnostics_gather(glob,init_flag);
    init_flag = 0;

    /* Output rhs */
    int Frame = 0;
    fclaw2d_output_frame(glob,Frame);

    /* Solve the elliptic problem */
    fclaw2d_elliptic_solve(glob);

    /* Compute error, compute conservation */
    fclaw2d_diagnostics_gather(glob, init_flag);

    /* Output solution */
    Frame = 2;
    fclaw2d_output_frame(glob,Frame);

    /* ---------------------------------------------------------------
       Finalize
       --------------------------------------------------------------- */
    fclaw2d_finalize(glob);
}

int
main (int argc, char **argv)
{
    fclaw_app_t *app;
    int first_arg;
    fclaw_exit_type_t vexit;

    /* Options */
    sc_options_t                *options;
    fclaw_options_t             *fclaw_opt;

    fclaw2d_clawpatch_options_t *clawpatch_opt;
    fc2d_multigrid_options_t    *mg_opt;
    mgtest_options_t              *user_opt;

    fclaw2d_global_t            *glob;
    fclaw2d_domain_t            *domain;
    sc_MPI_Comm mpicomm;

    int retval;

    /* Initialize application */
    app = fclaw_app_new (&argc, &argv, NULL);

    /* Create new options packages */
    fclaw_opt =                   fclaw_options_register(app,"fclaw_options.ini");
    clawpatch_opt =   fclaw2d_clawpatch_options_register(app,"fclaw_options.ini");
    mg_opt =        fc2d_multigrid_options_register(app,"fclaw_options.ini");
    user_opt =                    mgtest_options_register(app,"fclaw_options.ini");

    /* Read configuration file(s) and command line, and process options */
    options = fclaw_app_get_options (app);
    retval = fclaw_options_read_from_file(options);
    vexit =  fclaw_app_options_parse (app, &first_arg,"fclaw_options.ini.used");

    /* Run the program */
    if (!retval & !vexit)
    {
        /* Options have been checked and are valid */

        mpicomm = fclaw_app_get_mpi_size_rank (app, NULL, NULL);
        domain = create_domain(mpicomm, fclaw_opt);

        /* Create global structure which stores the domain, timers, etc */
        glob = fclaw2d_global_new();
        fclaw2d_global_store_domain(glob, domain);

        /* Store option packages in glob */
        fclaw2d_options_store           (glob, fclaw_opt);
        fclaw2d_clawpatch_options_store (glob, clawpatch_opt);
        fc2d_multigrid_options_store    (glob, mg_opt);
        mgtest_options_store            (glob, user_opt);

        run_program(glob);

        fclaw2d_global_destroy(glob);
    }

    fclaw_app_destroy (app);

    return 0;
}
<|endoftext|>