<commit_before>/**
 * computeDifferenceImage
 *
 * This program computes the difference between images.
 *
 *
 * authors:				Marius Staring
 *
 */

#include <iostream>
#include "itkImageFileReader.h"

/** In order to determine if argv[1] is a directory or a file,
 * so that we can distinguish between dicom and other files.
 */
#include <itksys/SystemTools.hxx>

extern int ComputeScalarDifferenceImage( const std::string &inputPixelComponentType1,
	const std::string &inputPixelComponentType2, const std::string &outputPixelComponentType,
	const std::string &image1FileName, const std::string &image2FileName,
	const std::string &outputFileName, int inputDimension);

extern int ComputeVectorDifferenceImage( const std::string &inputPixelComponentType1,
	const std::string &inputPixelComponentType2, const std::string &outputPixelComponentType,
	const std::string &image1FileName, const std::string &image2FileName,
	const std::string &outputFileName, int inputDimension, int vectorDimension);

//-------------------------------------------------------------------------------------

int  main(  int  argc,  char *argv[] )
{
	/** TASK 1:
	 * Check arguments.
	 * *******************************************************************
	 */
	if ( argc  < 3 || argv[ 1 ] == "--help" )
	{
		std::cout  << "Usage:"  << std::endl;
		std::cout  << "\tpxcomputedifferenceimage inputimage1filename inputimage2filename [outputimagefilename] [outputPixelComponentType]" << std::endl;
		std::cout  << "\twhere outputPixelComponentType is one of:" << std::endl;
		std::cout  << "\t\t- unsigned_char" << std::endl;
		std::cout  << "\t\t- char" << std::endl;
		std::cout  << "\t\t- unsigned_short" << std::endl;
		std::cout  << "\t\t- short" << std::endl;
		std::cout  << "\t\t- unsigned_int" << std::endl;
		std::cout  << "\t\t- int" << std::endl;
		std::cout  << "\t\t- unsigned_long" << std::endl;
		std::cout  << "\t\t- long" << std::endl;
		std::cout  << "\t\t- float" << std::endl;
		std::cout  << "\t\t- double" << std::endl;
		std::cout  << "\tprovided that the outputPixelComponentType is supported by the output file format." << std::endl;
		std::cout  << "\tBy default the outputPixelComponentType is set to the inputPixelComponentType of image1." << std::endl;
		return 1;
	}

	/** Print arguments. */
	std::cout << "pxcomputedifferenceimage ";
	for ( unsigned int i = 1; i < argc; i++ )
	{
		std::cout << argv[ i ] << " ";
	}
	std::cout << std::endl;

	/** Get the image names. */
	std::string image1FileName = argv[ 1 ];
	std::string image2FileName = argv[ 2 ];
	std::string outputFileName = "";
	std::string outputPixelComponentType = "";
	if ( argc == 3 )
	{
		std::string::size_type slash = image2FileName.find_last_of( "/" ) + 1;
    outputFileName = image1FileName.substr( 0, image1FileName.rfind( "." ) );
		outputFileName += "MINUS";
		outputFileName += image2FileName.substr( slash, image2FileName.rfind( "." ) - slash );
		outputFileName += ".mhd";
	}
	else if ( argc == 4 )
	{
		outputFileName = argv[ 3 ];
	}
	else if ( argc == 5 )
	{
		outputFileName = argv[ 3 ];
		outputPixelComponentType = argv[ 4 ];
	}

	/** Check if image1FileName and image2FileName exist. */
	bool exists1 = itksys::SystemTools::FileExists( image1FileName.c_str() );
	bool exists2 = itksys::SystemTools::FileExists( image2FileName.c_str() );

	if ( !exists1 || !exists2 )
	{
		/** Something is wrong. */
		std::cerr << "ERROR: first input argument does not exist!" << std::endl;
		return 1;
	}

	/** Check outputPixelType. */
	if ( outputPixelComponentType != ""
		&& outputPixelComponentType != "unsigned_char"
		&& outputPixelComponentType != "char"
		&& outputPixelComponentType != "unsigned_short"
		&& outputPixelComponentType != "short"
		&& outputPixelComponentType != "unsigned_int"
		&& outputPixelComponentType != "int"
		&& outputPixelComponentType != "unsigned_long"
		&& outputPixelComponentType != "long"
		&& outputPixelComponentType != "float"
		&& outputPixelComponentType != "double" )
	{
		/** In this case an illegal outputPixelComponentType is given. */
		std::cerr << "The given outputPixelComponentType is \"" << outputPixelComponentType
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** TASK 2:
	 * Typedefs and test reading to determine correct image types.
	 * *******************************************************************
	 */

	/** Initial image type. */
	const unsigned int		Dimension  =  3;
	typedef short					PixelType;

	/** Some typedef's. */
	typedef itk::Image< PixelType, Dimension >			ImageType;
	typedef itk::ImageFileReader< ImageType >				ReaderType;
	typedef itk::ImageIOBase												ImageIOBaseType;

	/** Create testReaders. */
	ReaderType::Pointer testReader1 = ReaderType::New();
	ReaderType::Pointer testReader2 = ReaderType::New();

	/** Setup the testReaders. */
	testReader1->SetFileName( image1FileName.c_str() );
	testReader2->SetFileName( image2FileName.c_str() );

	/** Generate all information. */
	testReader1->GenerateOutputInformation();
	testReader2->GenerateOutputInformation();

	/** Extract the ImageIO from the testReaders. */
	ImageIOBaseType::Pointer testImageIOBase1 = testReader1->GetImageIO();
	ImageIOBaseType::Pointer testImageIOBase2 = testReader2->GetImageIO();

	/** Get the component type, number of components, dimension and pixel type of image1. */
	unsigned int inputDimension1 = testImageIOBase1->GetNumberOfDimensions();
	unsigned int numberOfComponents1 = testImageIOBase1->GetNumberOfComponents();
	std::string inputPixelComponentType1 = testImageIOBase1->GetComponentTypeAsString(
		testImageIOBase1->GetComponentType() );
	std::string pixelType1 = testImageIOBase1->GetPixelTypeAsString(
		testImageIOBase1->GetPixelType() );

	/** Get the component type, number of components, dimension and pixel type of image2. */
	unsigned int inputDimension2 = testImageIOBase2->GetNumberOfDimensions();
	unsigned int numberOfComponents2 = testImageIOBase2->GetNumberOfComponents();
	std::string inputPixelComponentType2 = testImageIOBase2->GetComponentTypeAsString(
		testImageIOBase2->GetComponentType() );
	std::string pixelType2 = testImageIOBase2->GetPixelTypeAsString(
		testImageIOBase2->GetPixelType() );

	/** TASK 3:
	 * Do some preparations and checks.
	 * *******************************************************************
	 */

	/** Check dimension equality. */
	if ( inputDimension1 != inputDimension2 )
	{
		std::cerr << "The dimensions of the input images are "
			<< inputDimension1 << " and "
			<< inputDimension2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check equality of the pixel type. */
	if ( pixelType1 != pixelType2 )
	{
		std::cerr << "The pixel type of the input images are "
			<< pixelType1 << " and "
			<< pixelType2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check equality of the number of components. */
	if ( numberOfComponents1 != numberOfComponents2 )
	{
		std::cerr << "The number of components of the input images are "
			<< numberOfComponents1 << " and "
			<< numberOfComponents2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check inputPixelType1. */
	if ( inputPixelComponentType1 != "unsigned_char"
		&& inputPixelComponentType1 != "char"
		&& inputPixelComponentType1 != "unsigned_short"
		&& inputPixelComponentType1 != "short"
		&& inputPixelComponentType1 != "unsigned_int"
		&& inputPixelComponentType1 != "int"
		&& inputPixelComponentType1 != "unsigned_long"
		&& inputPixelComponentType1 != "long"
		&& inputPixelComponentType1 != "float"
		&& inputPixelComponentType1 != "double" )
	{
		/** In this case an illegal inputPixelComponentType is found. */
		std::cerr << "The found inputPixelComponentType of image1 is \"" << inputPixelComponentType1
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** Check inputPixelType2. */
	if ( inputPixelComponentType2 != "unsigned_char"
		&& inputPixelComponentType2 != "char"
		&& inputPixelComponentType2 != "unsigned_short"
		&& inputPixelComponentType2 != "short"
		&& inputPixelComponentType2 != "unsigned_int"
		&& inputPixelComponentType2 != "int"
		&& inputPixelComponentType2 != "unsigned_long"
		&& inputPixelComponentType2 != "long"
		&& inputPixelComponentType2 != "float"
		&& inputPixelComponentType2 != "double" )
	{
		/** In this case an illegal inputPixelComponentType is found. */
		std::cerr << "The found inputPixelComponentType of image2 is \"" << inputPixelComponentType2
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** Check outputPixelType. */
	if ( outputPixelComponentType == "" )
	{
		/** In this case this option is not given, and by default
		* we set it to the inputPixelComponentType.
		*/
		outputPixelComponentType = inputPixelComponentType1;
	}

	/** Get rid of the "_" in inputPixelComponentTypes and outputPixelComponentType. */
	std::basic_string<char>::size_type pos = inputPixelComponentType1.find( "_" );
	static const std::basic_string<char>::size_type npos = std::basic_string<char>::npos;
	if ( pos != npos )
	{
		inputPixelComponentType1.replace( pos, 1, " " );
	}
	pos = inputPixelComponentType2.find( "_" );
	if ( pos != npos )
	{
		inputPixelComponentType2.replace( pos, 1, " " );
	}
	pos = outputPixelComponentType.find( "_" );
	if ( pos != npos )
	{
		outputPixelComponentType.replace( pos, 1, " " );
	}

	/** TASK 4:
	 * Now we are ready to check on image type and subsequently call the
	 * correct ComputeDifference-function.
	 * *******************************************************************
	 */

	try
	{
		/**
		 * ****************** Support for SCALAR pixel types. **********************************
		 */
		if ( strcmp( pixelType1.c_str(), "scalar" ) == 0 && numberOfComponents1 == 1 )
		{
			const int ret_value = ComputeScalarDifferenceImage(
				inputPixelComponentType1, inputPixelComponentType2,
				outputPixelComponentType, image1FileName, image2FileName,
				outputFileName, inputDimension1 );
			if ( ret_value != 0 )
			{
				return ret_value;
			}
		} // end scalar support
		/**
		 * ****************** Support for VECTOR pixel types. **********************************
		 */
		else if ( strcmp( pixelType1.c_str(), "vector" ) == 0 )
		{
			const int ret_value = ComputeVectorDifferenceImage(
				inputPixelComponentType1, inputPixelComponentType2,
				outputPixelComponentType, image1FileName, image2FileName,
				outputFileName, inputDimension1, numberOfComponents1 );
			if ( ret_value != 0 )
			{
				return ret_value;
			}
		} // end vector support
		else
		{
			std::cerr << "Pixel types are " << pixelType1
				<< ", component types are " << inputPixelComponentType1
				<< " and number of components equals " << numberOfComponents1 << "." << std::endl;
			std::cerr << "ERROR: This image type is not supported." << std::endl;
			return 1;
		}
	} // end try

	/** If any errors have occurred, catch and print the exception and return false. */
	catch( itk::ExceptionObject  &  err  )
	{
		std::cerr  << "ExceptionObject caught !"  << std::endl;
		std::cerr  << err <<  std::endl;
		return 1;
	}

	/** End  program. Return succes. */
	return 0;

}  // end main
<commit_msg>------------------------------------------------------------ MS:<commit_after>/**
 * computeDifferenceImage
 *
 * This program computes the difference between images.
 *
 *
 * authors:				Marius Staring
 *
 */

#include <iostream>
#include "itkImageFileReader.h"

/** In order to determine if argv[1] is a directory or a file,
 * so that we can distinguish between dicom and other files.
 */
#include <itksys/SystemTools.hxx>

extern int ComputeScalarDifferenceImage( const std::string &inputPixelComponentType1,
	const std::string &inputPixelComponentType2, const std::string &outputPixelComponentType,
	const std::string &image1FileName, const std::string &image2FileName,
	const std::string &outputFileName, int inputDimension);

extern int ComputeVectorDifferenceImage( const std::string &inputPixelComponentType1,
	const std::string &inputPixelComponentType2, const std::string &outputPixelComponentType,
	const std::string &image1FileName, const std::string &image2FileName,
	const std::string &outputFileName, int inputDimension, int vectorDimension);

//-------------------------------------------------------------------------------------

int  main(  int  argc,  char *argv[] )
{
	/** TASK 1:
	 * Check arguments.
	 * *******************************************************************
	 */
	if ( argc  < 3 || argv[ 1 ] == "--help" )
	{
		std::cout  << "Usage:"  << std::endl;
		std::cout  << "\tpxcomputedifferenceimage inputimage1filename inputimage2filename [outputimagefilename] [outputPixelComponentType]" << std::endl;
		std::cout  << "\twhere outputPixelComponentType is one of:" << std::endl;
		std::cout  << "\t\t- unsigned_char" << std::endl;
		std::cout  << "\t\t- char" << std::endl;
		std::cout  << "\t\t- unsigned_short" << std::endl;
		std::cout  << "\t\t- short" << std::endl;
		std::cout  << "\t\t- unsigned_int" << std::endl;
		std::cout  << "\t\t- int" << std::endl;
		std::cout  << "\t\t- unsigned_long" << std::endl;
		std::cout  << "\t\t- long" << std::endl;
		std::cout  << "\t\t- float" << std::endl;
		std::cout  << "\t\t- double" << std::endl;
		std::cout  << "\tprovided that the outputPixelComponentType is supported by the output file format." << std::endl;
		std::cout  << "\tBy default the outputPixelComponentType is set to the inputPixelComponentType of image1." << std::endl;
		return 1;
	}

	/** Print arguments. */
	std::cout << "pxcomputedifferenceimage ";
	for ( unsigned int i = 1; i < argc; i++ )
	{
		std::cout << argv[ i ] << " ";
	}
	std::cout << std::endl;

	/** Get the image names. */
	std::string image1FileName = argv[ 1 ];
	std::string image2FileName = argv[ 2 ];
	std::string outputFileName = "";
	std::string outputPixelComponentType = "";
	if ( argc == 3 )
	{
		std::string::size_type slash = image2FileName.find_last_of( "/" ) + 1;
    outputFileName = image1FileName.substr( 0, image1FileName.rfind( "." ) );
		outputFileName += "MINUS";
		outputFileName += image2FileName.substr( slash, image2FileName.rfind( "." ) - slash );
		outputFileName += ".mhd";
	}
	else if ( argc == 4 )
	{
		outputFileName = argv[ 3 ];
	}
	else if ( argc == 5 )
	{
		outputFileName = argv[ 3 ];
		outputPixelComponentType = argv[ 4 ];
	}

	/** Check if image1FileName and image2FileName exist. */
	bool exists1 = itksys::SystemTools::FileExists( image1FileName.c_str() );
	bool exists2 = itksys::SystemTools::FileExists( image2FileName.c_str() );

	if ( !exists1 || !exists2 )
	{
		/** Something is wrong. */
		std::cerr << "ERROR: first input argument does not exist!" << std::endl;
		return 1;
	}

	/** Check outputPixelType. */
	if ( outputPixelComponentType != ""
		&& outputPixelComponentType != "unsigned_char"
		&& outputPixelComponentType != "char"
		&& outputPixelComponentType != "unsigned_short"
		&& outputPixelComponentType != "short"
		&& outputPixelComponentType != "unsigned_int"
		&& outputPixelComponentType != "int"
		&& outputPixelComponentType != "unsigned_long"
		&& outputPixelComponentType != "long"
		&& outputPixelComponentType != "float"
		&& outputPixelComponentType != "double" )
	{
		/** In this case an illegal outputPixelComponentType is given. */
		std::cerr << "The given outputPixelComponentType is \"" << outputPixelComponentType
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** TASK 2:
	 * Typedefs and test reading to determine correct image types.
	 * *******************************************************************
	 */

	/** Initial image type. */
	const unsigned int		Dimension  =  3;
	typedef short					PixelType;

	/** Some typedef's. */
	typedef itk::Image< PixelType, Dimension >			ImageType;
	typedef itk::ImageFileReader< ImageType >				ReaderType;
	typedef itk::ImageIOBase												ImageIOBaseType;

	/** Create testReaders. */
	ReaderType::Pointer testReader1 = ReaderType::New();
	ReaderType::Pointer testReader2 = ReaderType::New();

	/** Setup the testReaders. */
	testReader1->SetFileName( image1FileName.c_str() );
	testReader2->SetFileName( image2FileName.c_str() );

	/** Generate all information. */
	testReader1->GenerateOutputInformation();
	testReader2->GenerateOutputInformation();

	/** Extract the ImageIO from the testReaders. */
	ImageIOBaseType::Pointer testImageIOBase1 = testReader1->GetImageIO();
	ImageIOBaseType::Pointer testImageIOBase2 = testReader2->GetImageIO();

	/** Get the component type, number of components, dimension and pixel type of image1. */
	unsigned int inputDimension1 = testImageIOBase1->GetNumberOfDimensions();
	unsigned int numberOfComponents1 = testImageIOBase1->GetNumberOfComponents();
	std::string inputPixelComponentType1 = testImageIOBase1->GetComponentTypeAsString(
		testImageIOBase1->GetComponentType() );
	std::string pixelType1 = testImageIOBase1->GetPixelTypeAsString(
		testImageIOBase1->GetPixelType() );

	/** Get the component type, number of components, dimension and pixel type of image2. */
	unsigned int inputDimension2 = testImageIOBase2->GetNumberOfDimensions();
	unsigned int numberOfComponents2 = testImageIOBase2->GetNumberOfComponents();
	std::string inputPixelComponentType2 = testImageIOBase2->GetComponentTypeAsString(
		testImageIOBase2->GetComponentType() );
	std::string pixelType2 = testImageIOBase2->GetPixelTypeAsString(
		testImageIOBase2->GetPixelType() );

	/** TASK 3:
	 * Do some preparations and checks.
	 * *******************************************************************
	 */

	/** Check dimension equality. */
	if ( inputDimension1 != inputDimension2 )
	{
		std::cerr << "The dimensions of the input images are "
			<< inputDimension1 << " and "
			<< inputDimension2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check equality of the pixel type. */
	if ( pixelType1 != pixelType2 )
	{
		std::cerr << "The pixel type of the input images are "
			<< pixelType1 << " and "
			<< pixelType2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check equality of the number of components. */
	if ( numberOfComponents1 != numberOfComponents2 )
	{
		std::cerr << "The number of components of the input images are "
			<< numberOfComponents1 << " and "
			<< numberOfComponents2 << "." << std::endl;
		std::cerr << "They should match!" << std::endl;
		return 1;
	}

	/** Check inputPixelType1. */
	if ( inputPixelComponentType1 != "unsigned_char"
		&& inputPixelComponentType1 != "char"
		&& inputPixelComponentType1 != "unsigned_short"
		&& inputPixelComponentType1 != "short"
		&& inputPixelComponentType1 != "unsigned_int"
		&& inputPixelComponentType1 != "int"
		&& inputPixelComponentType1 != "unsigned_long"
		&& inputPixelComponentType1 != "long"
		&& inputPixelComponentType1 != "float"
		&& inputPixelComponentType1 != "double" )
	{
		/** In this case an illegal inputPixelComponentType is found. */
		std::cerr << "The found inputPixelComponentType of image1 is \"" << inputPixelComponentType1
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** Check inputPixelType2. */
	if ( inputPixelComponentType2 != "unsigned_char"
		&& inputPixelComponentType2 != "char"
		&& inputPixelComponentType2 != "unsigned_short"
		&& inputPixelComponentType2 != "short"
		&& inputPixelComponentType2 != "unsigned_int"
		&& inputPixelComponentType2 != "int"
		&& inputPixelComponentType2 != "unsigned_long"
		&& inputPixelComponentType2 != "long"
		&& inputPixelComponentType2 != "float"
		&& inputPixelComponentType2 != "double" )
	{
		/** In this case an illegal inputPixelComponentType is found. */
		std::cerr << "The found inputPixelComponentType of image2 is \"" << inputPixelComponentType2
			<< "\", which is not supported." << std::endl;
		return 1;
	}

	/** Check outputPixelType. */
	if ( outputPixelComponentType == "" )
	{
		/** In this case this option is not given, and by default
		* we set it to the inputPixelComponentType.
		*/
		outputPixelComponentType = inputPixelComponentType1;
	}

	/** Get rid of the "_" in inputPixelComponentTypes and outputPixelComponentType. */
	std::basic_string<char>::size_type pos = inputPixelComponentType1.find( "_" );
	static const std::basic_string<char>::size_type npos = std::basic_string<char>::npos;
	if ( pos != npos )
	{
		inputPixelComponentType1.replace( pos, 1, " " );
	}
	pos = inputPixelComponentType2.find( "_" );
	if ( pos != npos )
	{
		inputPixelComponentType2.replace( pos, 1, " " );
	}
	pos = outputPixelComponentType.find( "_" );
	if ( pos != npos )
	{
		outputPixelComponentType.replace( pos, 1, " " );
	}

	/** TASK 4:
	 * Now we are ready to check on image type and subsequently call the
	 * correct ComputeDifference-function.
	 * *******************************************************************
	 */

	try
	{
		/**
		 * ****************** Support for SCALAR pixel types. **********************************
		 */
		if ( strcmp( pixelType1.c_str(), "scalar" ) == 0 && numberOfComponents1 == 1 )
		{
			const int ret_value = ComputeScalarDifferenceImage(
				inputPixelComponentType1, inputPixelComponentType2,
				outputPixelComponentType, image1FileName, image2FileName,
				outputFileName, inputDimension1 );
			if ( ret_value != 0 )
			{
				return ret_value;
			}
		} // end scalar support
		/**
		 * ****************** Support for VECTOR pixel types. **********************************
		 */
		//else if ( strcmp( pixelType1.c_str(), "vector" ) == 0 )
		else if ( numberOfComponents1 > 1 )
		{
			const int ret_value = ComputeVectorDifferenceImage(
				inputPixelComponentType1, inputPixelComponentType2,
				outputPixelComponentType, image1FileName, image2FileName,
				outputFileName, inputDimension1, numberOfComponents1 );
			if ( ret_value != 0 )
			{
				return ret_value;
			}
		} // end vector support
		else
		{
			std::cerr << "Pixel types are " << pixelType1
				<< ", component types are " << inputPixelComponentType1
				<< " and number of components equals " << numberOfComponents1 << "." << std::endl;
			std::cerr << "ERROR: This image type is not supported." << std::endl;
			return 1;
		}
	} // end try

	/** If any errors have occurred, catch and print the exception and return false. */
	catch( itk::ExceptionObject  &  err  )
	{
		std::cerr  << "ExceptionObject caught !"  << std::endl;
		std::cerr  << err <<  std::endl;
		return 1;
	}

	/** End  program. Return succes. */
	return 0;

}  // end main
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "jstreamsconfig.h"
#include <CLucene.h>
#include <CLucene/store/Lock.h>
#include "cluceneindexwriter.h"
#include "cluceneindexmanager.h"
#include "stringreader.h"
#include "inputstreamreader.h"
#include "indexable.h"
#include "PrefixFilter.h"
#include <sstream>
#include <assert.h>

#ifdef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
#include "gzipcompressstream.h"
#endif

//comment this out if you have clucene 0.9.17 or later
#include "PrefixFilter.h"

using lucene::document::Document;
using lucene::document::Field;
using lucene::index::IndexWriter;
using lucene::index::Term;
using lucene::index::TermDocs;
using lucene::search::IndexSearcher;
using lucene::search::Hits;
using lucene::search::PrefixFilter;
using lucene::util::BitSet;

using lucene::util::Reader;
using namespace std;
using namespace jstreams;

struct CLuceneDocData {
    lucene::document::Document doc;
    std::string content;
};

CLuceneIndexWriter::CLuceneIndexWriter(CLuceneIndexManager* m):
    manager(m), doccount(0)
{
}
CLuceneIndexWriter::~CLuceneIndexWriter() {
}
void
CLuceneIndexWriter::addText(const Indexable* idx, const char* text,
        int32_t length) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
    doc->content.append(text, length);
}

#ifdef _UCS2
typedef map<wstring,wstring> CLuceneIndexWriterFieldMapType;;
#else
typedef map<string,string> CLuceneIndexWriterFieldMapType;
#endif
CLuceneIndexWriterFieldMapType CLuceneIndexWriterFieldMap;

void CLuceneIndexWriter::addMapping(const TCHAR* from, const TCHAR* to){
    CLuceneIndexWriterFieldMap[from] = to;
}
const TCHAR*
CLuceneIndexWriter::mapId(const TCHAR* id) {
    if ( CLuceneIndexWriterFieldMap.size() == 0 ){
        addMapping(_T(""),_T("content"));
    }
    if (id==0 ) id = _T("");
    CLuceneIndexWriterFieldMapType::iterator itr = CLuceneIndexWriterFieldMap.find(id);
    if ( itr == CLuceneIndexWriterFieldMap.end() )
        return id;
    else
        return itr->second.c_str();
}
void
setField(const jstreams::Indexable* idx, const TCHAR* fn,
        const std::string& value) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
#if defined(_UCS2)
    doc->doc.add( *Field::Keyword(CLuceneIndexWriter::mapId(fn), utf8toucs2(value).c_str()) );
#else
    doc->doc.add( *Field::Keyword(CLuceneIndexWriter::mapId(fn), value.c_str()) );
#endif
}
void
CLuceneIndexWriter::setField(const Indexable* idx, const string& fieldname,
        const string& value) {
#if defined(_UCS2)
    ::setField(idx, utf8toucs2(fieldname).c_str(), value);
#else
    ::setField(idx, fieldname.c_str(), value);
#endif
}
void
CLuceneIndexWriter::startIndexable(Indexable* idx) {
    doccount++;
    CLuceneDocData*doc = new CLuceneDocData();
    idx->setWriterData(doc);
}
/*
    Close all left open indexwriters for this path.
*/
void
CLuceneIndexWriter::finishIndexable(const Indexable* idx) {
    ::setField(idx, _T("path"), idx->getPath());
    string field = idx->getEncoding();
    if (field.length()) ::setField(idx, _T("encoding"), field);
    field = idx->getMimeType();
    if (field.length()) ::setField(idx, _T("mimetype"), field);
    field = idx->getFileName();
    if (field.length()) ::setField(idx, _T("filename"), field);
    field = idx->getExtension();
    if (field.length()) ::setField(idx, _T("ext"), field);
    ostringstream o;
    o << (int)idx->getDepth();
    ::setField(idx, _T("depth"), o.str());
    o.str("");
    {
        char tmp[100];
        snprintf(tmp,100,"%llu",(uint64_t)idx->getMTime());
        o << tmp;
    }
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
    ::setField(idx, _T("mtime"), o.str());
    wstring c(utf8toucs2(doc->content));
    StringReader<char>* sr = NULL; //we use this for compressed streams

    if (doc->content.length() > 0) {
        const TCHAR* mappedFn = mapId(_T(""));
#if defined(_UCS2)
    #ifndef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
        doc->doc.add(*Field::Text(mappedFn, c.c_str(), false));
    #else
        //lets store the content as utf8. remember, the stream is required
        //until the document is added, so a static construction of stringreader is not good enough
        sr = new StringReader<char>(doc->content.c_str(), doc->content.length(), false);

    //add the stored field with the zipstream
    doc->doc.add(*new Field(mappedFn,
        new GZipCompressInputStream(sr),
        Field::STORE_YES ) );

    //add add the tokenized/indexed field
    doc->doc.add(*new Field::Text(mappedFn, c.c_str(),
            Field::STORE_NO | Field::INDEX_TOKENIZED));
    #endif
#else //_UCS2
        doc->doc.add(*Field::Text(mappedFn, doc->content.c_str()) );
#endif
    }
    lucene::index::IndexWriter* writer = manager->refWriter();
    if (writer) {
        try {
            writer->addDocument(&doc->doc);
        } catch (CLuceneError& err) {
            fprintf(stderr, "%s: %s\n", idx->getPath().c_str(), err.what());
        }
    }
    manager->derefWriter();
    delete doc;
    if ( sr )
        delete sr;
}
void
CLuceneIndexWriter::deleteEntries(const std::vector<std::string>& entries) {
    for (uint i=0; i<entries.size(); ++i) {
        deleteEntry(entries[i]);
    }
}
void
CLuceneIndexWriter::deleteEntry(const string& entry) {
    lucene::index::IndexReader* reader = manager->refReader();

    wstring tstr(utf8toucs2(entry));
    Term term(_T("path"), tstr.c_str());
    PrefixFilter filter(&term);
    BitSet* bits;
    try {
        bits = filter.bits(reader);
    } catch (CLuceneError& err) {
        fprintf(stderr, "error creating filter %s: %s\n", entry.c_str(),
            err.what());
        bits = 0;
    }
    if (bits) {
        for (int32_t i = 0; i < bits->size(); ++i) {
            if (bits->get(i) && !reader->isDeleted(i)) {
                reader->deleteDocument(i);
            }
        }
        _CLDELETE(bits);
    }

    manager->derefReader();
}
void
CLuceneIndexWriter::deleteAllEntries() {
    manager->deleteIndex();
}

//this function is in 0.9.17, which we dont have yet...
bool isLuceneFile(const char* filename){
    if ( !filename )
        return false;
    size_t len = strlen(filename);
    if ( len < 6 ) //need at least x.frx
        return false;
    const char* ext = filename + len;
    while ( *ext != '.' && ext != filename )
        ext--;

    if ( strcmp(ext, ".cfs") == 0 )
        return true;
    else if ( strcmp(ext, ".fnm") == 0 )
        return true;
    else if ( strcmp(ext, ".fdx") == 0 )
        return true;
    else if ( strcmp(ext, ".fdt") == 0 )
        return true;
    else if ( strcmp(ext, ".tii") == 0 )
        return true;
    else if ( strcmp(ext, ".tis") == 0 )
        return true;
    else if ( strcmp(ext, ".frq") == 0 )
        return true;
    else if ( strcmp(ext, ".prx") == 0 )
        return true;
    else if ( strcmp(ext, ".del") == 0 )
        return true;
    else if ( strcmp(ext, ".tvx") == 0 )
        return true;
    else if ( strcmp(ext, ".tvd") == 0 )
        return true;
    else if ( strcmp(ext, ".tvf") == 0 )
        return true;
    else if ( strcmp(ext, ".tvp") == 0 )
        return true;

    else if ( strcmp(filename, "segments") == 0 )
        return true;
    else if ( strcmp(filename, "segments.new") == 0 )
        return true;
    else if ( strcmp(filename, "deletable") == 0 )
        return true;

    else if ( strncmp(ext,".f",2)==0 ){
        const char* n = ext+2;
        if ( *n && _istdigit(*n) )
            return true;
    }

    return false;
}

void
CLuceneIndexWriter::cleanUp() {
    //remove all unused lucene file elements... unused elements are the result of unexpected shutdowns...
    //this can add up to a lot of after a while.

    lucene::index::IndexReader* reader = manager->refReader();
    if (!reader) {
        return;
    }
    lucene::store::Directory* directory = reader->getDirectory();

    //Instantiate SegmentInfos
    lucene::store::LuceneLock* lock = directory->makeLock("commit.lock");
#ifdef LUCENE_COMMIT_LOCK_TIMEOUT
    //version <0.9.16
    bool locked = lock->obtain(LUCENE_COMMIT_LOCK_TIMEOUT);
#else
    bool locked = lock->obtain(lucene::index::IndexWriter::COMMIT_LOCK_TIMEOUT);
#endif
    if (!locked) {
        return;
    }
    lucene::index::SegmentInfos infos;
    try {
        //Have SegmentInfos read the segments file in directory
        infos.read(directory);
    } catch(...) {
        lock->release();
        return; //todo: this may suggest an error...
    }
    lock->release();

    int i;
    set<string> segments;
    for (i = 0; i < infos.size(); i++) {
            lucene::index::SegmentInfo* info = infos.info(i);
            segments.insert(info->name);
    }

    char** files = directory->list();
    char tmp[CL_MAX_PATH];
    for (i = 0; files[i] != NULL; ++i) {
        char* file = files[i];

        int fileLength = strlen(file);
        if ( fileLength < 6 ) {
            continue;
        }

        if (strncmp(file,"segments", 8) == 0
                || strncmp(file, "deletable", 9) == 0) {
            continue;
        }
        if (!isLuceneFile(file)) {
            continue;
        }

        strcpy(tmp, file);
        tmp[fileLength-4] = '\0';

        if (segments.find(tmp) != segments.end()) {
            continue;
        }

        directory->deleteFile(file, false);
    }
    for (i = 0; files[i] != NULL; i++) {
        _CLDELETE_CaARRAY(files[i]);
    }
    _CLDELETE_ARRAY(files)

    manager->derefReader();
}

<commit_msg>Fix deadlock bug in clucene writer.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "jstreamsconfig.h"
#include <CLucene.h>
#include <CLucene/store/Lock.h>
#include "cluceneindexwriter.h"
#include "cluceneindexmanager.h"
#include "stringreader.h"
#include "inputstreamreader.h"
#include "indexable.h"
#include "PrefixFilter.h"
#include <sstream>
#include <assert.h>

#ifdef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
#include "gzipcompressstream.h"
#endif

//comment this out if you have clucene 0.9.17 or later
#include "PrefixFilter.h"

using lucene::document::Document;
using lucene::document::Field;
using lucene::index::IndexWriter;
using lucene::index::Term;
using lucene::index::TermDocs;
using lucene::search::IndexSearcher;
using lucene::search::Hits;
using lucene::search::PrefixFilter;
using lucene::util::BitSet;

using lucene::util::Reader;
using namespace std;
using namespace jstreams;

struct CLuceneDocData {
    lucene::document::Document doc;
    std::string content;
};

CLuceneIndexWriter::CLuceneIndexWriter(CLuceneIndexManager* m):
    manager(m), doccount(0)
{
}
CLuceneIndexWriter::~CLuceneIndexWriter() {
}
void
CLuceneIndexWriter::addText(const Indexable* idx, const char* text,
        int32_t length) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
    doc->content.append(text, length);
}

#ifdef _UCS2
typedef map<wstring,wstring> CLuceneIndexWriterFieldMapType;;
#else
typedef map<string,string> CLuceneIndexWriterFieldMapType;
#endif
CLuceneIndexWriterFieldMapType CLuceneIndexWriterFieldMap;

void CLuceneIndexWriter::addMapping(const TCHAR* from, const TCHAR* to){
    CLuceneIndexWriterFieldMap[from] = to;
}
const TCHAR*
CLuceneIndexWriter::mapId(const TCHAR* id) {
    if ( CLuceneIndexWriterFieldMap.size() == 0 ){
        addMapping(_T(""),_T("content"));
    }
    if (id==0 ) id = _T("");
    CLuceneIndexWriterFieldMapType::iterator itr = CLuceneIndexWriterFieldMap.find(id);
    if ( itr == CLuceneIndexWriterFieldMap.end() )
        return id;
    else
        return itr->second.c_str();
}
void
setField(const jstreams::Indexable* idx, const TCHAR* fn,
        const std::string& value) {
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
#if defined(_UCS2)
    doc->doc.add( *Field::Keyword(CLuceneIndexWriter::mapId(fn), utf8toucs2(value).c_str()) );
#else
    doc->doc.add( *Field::Keyword(CLuceneIndexWriter::mapId(fn), value.c_str()) );
#endif
}
void
CLuceneIndexWriter::setField(const Indexable* idx, const string& fieldname,
        const string& value) {
#if defined(_UCS2)
    ::setField(idx, utf8toucs2(fieldname).c_str(), value);
#else
    ::setField(idx, fieldname.c_str(), value);
#endif
}
void
CLuceneIndexWriter::startIndexable(Indexable* idx) {
    doccount++;
    CLuceneDocData*doc = new CLuceneDocData();
    idx->setWriterData(doc);
}
/*
    Close all left open indexwriters for this path.
*/
void
CLuceneIndexWriter::finishIndexable(const Indexable* idx) {
    ::setField(idx, _T("path"), idx->getPath());
    string field = idx->getEncoding();
    if (field.length()) ::setField(idx, _T("encoding"), field);
    field = idx->getMimeType();
    if (field.length()) ::setField(idx, _T("mimetype"), field);
    field = idx->getFileName();
    if (field.length()) ::setField(idx, _T("filename"), field);
    field = idx->getExtension();
    if (field.length()) ::setField(idx, _T("ext"), field);
    ostringstream o;
    o << (int)idx->getDepth();
    ::setField(idx, _T("depth"), o.str());
    o.str("");
    {
        char tmp[100];
        snprintf(tmp,100,"%llu",(uint64_t)idx->getMTime());
        o << tmp;
    }
    CLuceneDocData* doc = static_cast<CLuceneDocData*>(idx->getWriterData());
    ::setField(idx, _T("mtime"), o.str());
    wstring c(utf8toucs2(doc->content));
    StringReader<char>* sr = NULL; //we use this for compressed streams

    if (doc->content.length() > 0) {
        const TCHAR* mappedFn = mapId(_T(""));
#if defined(_UCS2)
    #ifndef STRIGI_USE_CLUCENE_COMPRESSEDFIELDS
        doc->doc.add(*Field::Text(mappedFn, c.c_str(), false));
    #else
        //lets store the content as utf8. remember, the stream is required
        //until the document is added, so a static construction of stringreader is not good enough
        sr = new StringReader<char>(doc->content.c_str(), doc->content.length(), false);

    //add the stored field with the zipstream
    doc->doc.add(*new Field(mappedFn,
        new GZipCompressInputStream(sr),
        Field::STORE_YES ) );

    //add add the tokenized/indexed field
    doc->doc.add(*new Field::Text(mappedFn, c.c_str(),
            Field::STORE_NO | Field::INDEX_TOKENIZED));
    #endif
#else //_UCS2
        doc->doc.add(*Field::Text(mappedFn, doc->content.c_str()) );
#endif
    }
    lucene::index::IndexWriter* writer = manager->refWriter();
    if (writer) {
        try {
            writer->addDocument(&doc->doc);
        } catch (CLuceneError& err) {
            fprintf(stderr, "%s: %s\n", idx->getPath().c_str(), err.what());
        }
    }
    manager->derefWriter();
    delete doc;
    if ( sr )
        delete sr;
}
void
CLuceneIndexWriter::deleteEntries(const std::vector<std::string>& entries) {
    for (uint i=0; i<entries.size(); ++i) {
        deleteEntry(entries[i]);
    }
}
void
CLuceneIndexWriter::deleteEntry(const string& entry) {
    lucene::index::IndexReader* reader = manager->refReader();

    wstring tstr(utf8toucs2(entry));
    Term term(_T("path"), tstr.c_str());
    PrefixFilter filter(&term);
    BitSet* bits;
    try {
        bits = filter.bits(reader);
    } catch (CLuceneError& err) {
        fprintf(stderr, "error creating filter %s: %s\n", entry.c_str(),
            err.what());
        bits = 0;
    }
    if (bits) {
        for (int32_t i = 0; i < bits->size(); ++i) {
            if (bits->get(i) && !reader->isDeleted(i)) {
                reader->deleteDocument(i);
            }
        }
        _CLDELETE(bits);
    }

    manager->derefReader();
}
void
CLuceneIndexWriter::deleteAllEntries() {
    manager->deleteIndex();
}

//this function is in 0.9.17, which we dont have yet...
bool isLuceneFile(const char* filename){
    if ( !filename )
        return false;
    size_t len = strlen(filename);
    if ( len < 6 ) //need at least x.frx
        return false;
    const char* ext = filename + len;
    while ( *ext != '.' && ext != filename )
        ext--;

    if ( strcmp(ext, ".cfs") == 0 )
        return true;
    else if ( strcmp(ext, ".fnm") == 0 )
        return true;
    else if ( strcmp(ext, ".fdx") == 0 )
        return true;
    else if ( strcmp(ext, ".fdt") == 0 )
        return true;
    else if ( strcmp(ext, ".tii") == 0 )
        return true;
    else if ( strcmp(ext, ".tis") == 0 )
        return true;
    else if ( strcmp(ext, ".frq") == 0 )
        return true;
    else if ( strcmp(ext, ".prx") == 0 )
        return true;
    else if ( strcmp(ext, ".del") == 0 )
        return true;
    else if ( strcmp(ext, ".tvx") == 0 )
        return true;
    else if ( strcmp(ext, ".tvd") == 0 )
        return true;
    else if ( strcmp(ext, ".tvf") == 0 )
        return true;
    else if ( strcmp(ext, ".tvp") == 0 )
        return true;

    else if ( strcmp(filename, "segments") == 0 )
        return true;
    else if ( strcmp(filename, "segments.new") == 0 )
        return true;
    else if ( strcmp(filename, "deletable") == 0 )
        return true;

    else if ( strncmp(ext,".f",2)==0 ){
        const char* n = ext+2;
        if ( *n && _istdigit(*n) )
            return true;
    }

    return false;
}

void
CLuceneIndexWriter::cleanUp() {
    //remove all unused lucene file elements... unused elements are the result of unexpected shutdowns...
    //this can add up to a lot of after a while.

    lucene::index::IndexReader* reader = manager->refReader();
    if (!reader) {
        manager->derefReader();
        return;
    }
    lucene::store::Directory* directory = reader->getDirectory();

    //Instantiate SegmentInfos
    lucene::store::LuceneLock* lock = directory->makeLock("commit.lock");
#ifdef LUCENE_COMMIT_LOCK_TIMEOUT
    //version <0.9.16
    bool locked = lock->obtain(LUCENE_COMMIT_LOCK_TIMEOUT);
#else
    bool locked = lock->obtain(lucene::index::IndexWriter::COMMIT_LOCK_TIMEOUT);
#endif
    if (!locked) {
        manager->derefReader();
        return;
    }
    lucene::index::SegmentInfos infos;
    try {
        //Have SegmentInfos read the segments file in directory
        infos.read(directory);
    } catch(...) {
        lock->release();
        manager->derefReader();
        return; //todo: this may suggest an error...
    }
    lock->release();

    int i;
    set<string> segments;
    for (i = 0; i < infos.size(); i++) {
            lucene::index::SegmentInfo* info = infos.info(i);
            segments.insert(info->name);
    }

    char** files = directory->list();
    char tmp[CL_MAX_PATH];
    for (i = 0; files[i] != NULL; ++i) {
        char* file = files[i];

        int fileLength = strlen(file);
        if ( fileLength < 6 ) {
            continue;
        }

        if (strncmp(file,"segments", 8) == 0
                || strncmp(file, "deletable", 9) == 0) {
            continue;
        }
        if (!isLuceneFile(file)) {
            continue;
        }

        strcpy(tmp, file);
        tmp[fileLength-4] = '\0';

        if (segments.find(tmp) != segments.end()) {
            continue;
        }

        directory->deleteFile(file, false);
    }
    for (i = 0; files[i] != NULL; i++) {
        _CLDELETE_CaARRAY(files[i]);
    }
    _CLDELETE_ARRAY(files)

    manager->derefReader();
}

<|endoftext|>


<commit_before>/**
 * YAHMS - Yet Another Home Management System
 *
 * (C) John McKerrell 2011
 * Probably some open source license when I get around to choosing one
 */

 /**
Do we have the current time or is it a while since we updated?
	Update the time - similar choice of sync vs async as below

Do we have any config, or is the config too old?
	Download a config
	?? Does this happen asynchronously or not? First time it might as well be sync but otherwise perhaps not
	What does config contain?
		Instructions on which digital pins are: Xbee Serial, Input, Output
		"On blocks" - blocks of time that a relay should be set to on
		+1 Hour - could simply be an extra On block
		Not sure about advance blocks - perhaps also an On block, these and +1 hour could be a special type that you only have one of, so a later +1 or advance discards the previous

Read in all of the local samples
Check the Xbee for any samples

Iterate over outputs, check whether we’re inside an On block, update pin status accordingly

Check the last time we sent back a sample, if it’s been too long then send the latest values, don’t send a sample that’s too old
*/

#include "YAHMS_Sampler.h"
#include <Flash.h>

#ifdef LOGGING
FLASH_STRING(HAVE_XBEE_PACKET_FROM_NODE,"Xbee from ");
FLASH_STRING(XBEE_SAMPLES_FOR_NODE,"Xbee Samples for ");
FLASH_STRING(PROG_PIN," pin ");
FLASH_STRING(SMOOTHED_OUT_TO," smoothed to ");
FLASH_STRING(NO_XBEE_PACKET,"No xbee\n");
FLASH_STRING(PROG_SAMPLE,"Sample ");
FLASH_STRING(PROG_EQUALS," = ");
FLASH_STRING(SUBMITTING_SAMPLES_TO,"Submitting to http://");
FLASH_STRING(HTTP_SUBMIT_CONNECTION_FAILED,"HTTP Connection Failed\n");
FLASH_STRING(HTTP_SUBMIT_REQUEST_FAILED,"HTTP Request Failed with: ");
#endif
//FLASH_STRING(CONTENT_LENGTH,"Content-Length: ");
//FLASH_STRING(SAMPLE_CONTENT_TYPE,"Content-Type: application/x-www-form-urlencoded");
#define CONTENT_LENGTH "Content-Length"
#define SAMPLE_CONTENT_TYPE "Content-Type: application/x-www-form-urlencoded"

unsigned long int lastSampleSubmission = 0;
byte samplesBeforeSubmit = NUM_SAMPLES * 2;

int analogSamples[NUM_ANALOG_PINS][NUM_SAMPLES];
char inputSamples[NUM_INPUT_PINS][NUM_SAMPLES];
int xbeeSamples[MAX_XBEE_NODES][NUM_XBEE_PINS];

void SetupSampler() {
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      analogSamples[i][j] = -1;
    }
  }
  for (int i = 0; i < NUM_INPUT_PINS; ++i) {
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      inputSamples[i][j] = -1;
    }
  }
  for (int i = 0; i < MAX_XBEE_NODES; ++i) {
    for (int j = 0; j < NUM_XBEE_PINS; ++j) {
      xbeeSamples[i][j] = -1;
    }
  }
}

void TakeSamples() {
  boolean loggedSample = false;
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    loggedSample = false;
    if (analogPins[i] == -1) {
      continue;
    }
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      if ((j == LAST_SAMPLE || analogSamples[i][j] == -1) && ! loggedSample) {
        analogSamples[i][j] = analogRead(analogPins[i]);
        loggedSample = true;
      } else if (analogSamples[i][LAST_SAMPLE] != -1 && j < LAST_SAMPLE) {
        // Shift samples down the array
        analogSamples[i][j] = analogSamples[i][j+1];
      }
    }
  }
  for (int i = 0; i < NUM_INPUT_PINS; ++i) {
    loggedSample = false;
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      if ((j == LAST_SAMPLE || inputSamples[i][j] == -1) && ! loggedSample) {
        inputSamples[i][j] = digitalRead(analogPins[i]);
        loggedSample = true;
      } else if (inputSamples[i][LAST_SAMPLE] != -1 && j < LAST_SAMPLE) {
        // Shift samples down the array
        inputSamples[i][j] = inputSamples[i][j+1];
      }
    }
  }
  if (xbee.readPacket(5000)) {
    XBeeResponse response = xbee.getResponse();
    if (response.getApiId() == RX_16_IO_RESPONSE) {
      Rx16IoSampleResponse ioSample;
      xbee.getResponse().getRx16IoSampleResponse(ioSample);

      byte xbeeNode = ioSample.getRemoteAddress16();
      #ifdef LOGGING
      HAVE_XBEE_PACKET_FROM_NODE.print(Serial);
      Serial.println(xbeeNode,DEC);
      #endif
      if (xbeeNode < MAX_XBEE_NODES) {
        for (int i = 0; i < NUM_XBEE_PINS; ++i ) {
          int sampleSize = ioSample.getSampleSize();
          if (ioSample.isAnalogEnabled(i)) {
            int samples[sampleSize];
            for (int k = 0; k < sampleSize; ++k) {
              samples[k] = ioSample.getAnalog(i, k);
            }
            xbeeSamples[xbeeNode][i] = smoothSamples(samples,sampleSize);
            #ifdef LOGGING
            XBEE_SAMPLES_FOR_NODE.print(Serial);
            Serial.print(xbeeNode,DEC);
            PROG_PIN.print(Serial);
            Serial.print(i);
            SMOOTHED_OUT_TO.print(Serial);
            Serial.println(xbeeSamples[xbeeNode][i]);
            #endif
          } else if (ioSample.isDigitalEnabled(i)) {
            if (xbeeSamples[xbeeNode][i] == -1)
              xbeeSamples[xbeeNode][i] = 0;
            for (int k = 0; k < sampleSize; ++k) {
              xbeeSamples[xbeeNode][i] += ioSample.getAnalog(i, k) ? 1 : 0;
            }
          }
        }
      }
    }
  } else {
    #ifdef LOGGING
    NO_XBEE_PACKET.print(Serial);
    #endif
  }
}

void CheckAndSubmitSamples() {
  if (samplesBeforeSubmit > 0) {
    --samplesBeforeSubmit;
    return;
  }
  if ((now() - lastSampleSubmission) < SAMPLE_SUBMIT_FREQUENCY) {
    return;
  }

  int submitSamples[NUM_ANALOG_PINS];

  int contentLength = 0;
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    submitSamples[i] = -1;
    if (analogPins[i] == -1) {
      continue;
    }
    submitSamples[i] = smoothSamples(analogSamples[i], NUM_SAMPLES);
    #ifdef LOGGING
    PROG_SAMPLE.print(Serial);
    Serial.print(i);
    PROG_EQUALS.print(Serial);
    Serial.println(submitSamples[i]);
    #endif
    if (submitSamples[i] != -1) {
      contentLength += 7; // A0=FFF& or A10=FFF&
      if (analogPins[i] >= 10 )
        ++contentLength;
    }
  }

  for (int i = 0; i < MAX_XBEE_NODES; ++i) {
      for (int j = 0; j < NUM_XBEE_PINS; ++j) {
        if (xbeeSamples[i][j] != -1) {
          // X0P1=FFF&
          contentLength += 9;
        }
      }
  }

  EthernetClient c;
  HttpClient http(c);

  char configPath[22] = "/api/s/";
  const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  const unsigned long int divisors [4] = { 0xFFFFFF, 0xFFFF, 0xFF, 0x01 };
  // Append the MAC address
  for (int i =0; i < 6; i++)
  {
    configPath[7+(2*i)] = hexDigits[(mac[i] >> 4) & 0x0f];
    configPath[8+(2*i)] = hexDigits[mac[i] & 0x0f];
  }
  // And now the config version number
  configPath[19] = '/';
  configPath[20] = hexDigits[YAHMS_API_VERSION];
  // And finally append the timestamp for when we last updated the config
  configPath[21] = '\0';

  #ifdef LOGGING
  SUBMITTING_SAMPLES_TO.print(Serial);
  Serial.print(YAHMS_SERVER);
  Serial.println(configPath);
  #endif
  http.beginRequest();
  if (http.post(YAHMS_SERVER, 80, configPath, USERAGENT) == 0)
  {
    // Request sent okay
//    #ifdef LOGGING
//    CONTENT_LENGTH.print(Serial);
//    Serial.println(contentLength);
//    #endif
//    CONTENT_LENGTH.print(http);
//    http.println(contentLength);
//    SAMPLE_CONTENT_TYPE.print(http);
//    http.println();
    http.sendHeader(CONTENT_LENGTH,contentLength);
    http.sendHeader(SAMPLE_CONTENT_TYPE);
    http.endRequest();

    for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
      if (submitSamples[i] != -1) {
        http.print("A");
        http.print(analogPins[i],DEC);
        http.print("=");
        http.print(hexDigits[submitSamples[i]>>8 & 0x0F]);
        http.print(hexDigits[submitSamples[i]>>4 & 0x0F]);
        http.print(hexDigits[submitSamples[i] & 0x0F]);
        http.print("&");
      }
    }

    for (int i = 0; i < MAX_XBEE_NODES; ++i) {
      for (int j = 0; j < NUM_XBEE_PINS; ++j) {
        if (xbeeSamples[i][j] != -1) {
          // X0P1=FFF&
          http.print("X");
          http.print(i);
          http.print("P");
          http.print(j);
          http.print("=");
          http.print(hexDigits[xbeeSamples[i][j]>>8 & 0x0F]);
          http.print(hexDigits[xbeeSamples[i][j]>>4 & 0x0F]);
          http.print(hexDigits[xbeeSamples[i][j] & 0x0F]);
          http.print("&");
          xbeeSamples[i][j] = -1;
        }
      }
    }

    int err = http.responseStatusCode();
    if ((err >= 200) && (err < 300))
    {
      // We've got a successful response
      // And we're not interested in any of the headers
      err = http.skipResponseHeaders();
      if (err >= 0)
      {
      }
    } else {
      #ifdef LOGGING
      HTTP_SUBMIT_REQUEST_FAILED.print(Serial);
      Serial.println(err);
      #endif

    }
    http.stop();
    c.stop();
  } else {
    #ifdef LOGGING
    HTTP_SUBMIT_CONNECTION_FAILED.print(Serial);
    #endif
  }

  // Have to assume it worked really
  lastSampleSubmission = now();

}

int smoothSamples( int samples[], int numSamples) {

  int diff = 0, total = 0, average = 0, number = 0, deviation = 0;

  for (int j = 0; j < numSamples; ++j) {
    if (samples[j] != -1) {
      total += samples[j];
      ++number;
    }
  }
  if (number > 0) {
    average = total / number;
    for (int j = 0; j < numSamples; ++j) {
      if (samples[j] != -1) {
        deviation += abs(samples[j] - average);
      }
    }
    deviation = deviation / number;
    number = 0;
    total = 0;
    for (int j = 0; j < numSamples; ++j) {
      if (samples[j] != -1) {
        diff = abs(samples[j] - average);
        if ( deviation == 0 || diff <= deviation) {
          total += samples[j];
          ++number;
        }
      }
    }
    average = total / number;
    return average;
  } else {
    return -1;
  }
}
<commit_msg>Fixing bug with xbee code when no xbee present.<commit_after>/**
 * YAHMS - Yet Another Home Management System
 *
 * (C) John McKerrell 2011
 * Probably some open source license when I get around to choosing one
 */

 /**
Do we have the current time or is it a while since we updated?
	Update the time - similar choice of sync vs async as below

Do we have any config, or is the config too old?
	Download a config
	?? Does this happen asynchronously or not? First time it might as well be sync but otherwise perhaps not
	What does config contain?
		Instructions on which digital pins are: Xbee Serial, Input, Output
		"On blocks" - blocks of time that a relay should be set to on
		+1 Hour - could simply be an extra On block
		Not sure about advance blocks - perhaps also an On block, these and +1 hour could be a special type that you only have one of, so a later +1 or advance discards the previous

Read in all of the local samples
Check the Xbee for any samples

Iterate over outputs, check whether we’re inside an On block, update pin status accordingly

Check the last time we sent back a sample, if it’s been too long then send the latest values, don’t send a sample that’s too old
*/

#include "YAHMS_Sampler.h"
#include <Flash.h>

#ifdef LOGGING
FLASH_STRING(HAVE_XBEE_PACKET_FROM_NODE,"Xbee from ");
FLASH_STRING(XBEE_SAMPLES_FOR_NODE,"Xbee Samples for ");
FLASH_STRING(PROG_PIN," pin ");
FLASH_STRING(SMOOTHED_OUT_TO," smoothed to ");
FLASH_STRING(NO_XBEE_PACKET,"No xbee\n");
FLASH_STRING(PROG_SAMPLE,"Sample ");
FLASH_STRING(PROG_EQUALS," = ");
FLASH_STRING(SUBMITTING_SAMPLES_TO,"Submitting to http://");
FLASH_STRING(HTTP_SUBMIT_CONNECTION_FAILED,"HTTP Connection Failed\n");
FLASH_STRING(HTTP_SUBMIT_REQUEST_FAILED,"HTTP Request Failed with: ");
#endif
//FLASH_STRING(CONTENT_LENGTH,"Content-Length: ");
//FLASH_STRING(SAMPLE_CONTENT_TYPE,"Content-Type: application/x-www-form-urlencoded");
#define CONTENT_LENGTH "Content-Length"
#define SAMPLE_CONTENT_TYPE "Content-Type: application/x-www-form-urlencoded"

unsigned long int lastSampleSubmission = 0;
byte samplesBeforeSubmit = NUM_SAMPLES * 2;

int analogSamples[NUM_ANALOG_PINS][NUM_SAMPLES];
char inputSamples[NUM_INPUT_PINS][NUM_SAMPLES];
int xbeeSamples[MAX_XBEE_NODES][NUM_XBEE_PINS];

void SetupSampler() {
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      analogSamples[i][j] = -1;
    }
  }
  for (int i = 0; i < NUM_INPUT_PINS; ++i) {
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      inputSamples[i][j] = -1;
    }
  }
  for (int i = 0; i < MAX_XBEE_NODES; ++i) {
    for (int j = 0; j < NUM_XBEE_PINS; ++j) {
      xbeeSamples[i][j] = -1;
    }
  }
}

void TakeSamples() {
  boolean loggedSample = false;
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    loggedSample = false;
    if (analogPins[i] == -1) {
      continue;
    }
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      if ((j == LAST_SAMPLE || analogSamples[i][j] == -1) && ! loggedSample) {
        analogSamples[i][j] = analogRead(analogPins[i]);
        loggedSample = true;
      } else if (analogSamples[i][LAST_SAMPLE] != -1 && j < LAST_SAMPLE) {
        // Shift samples down the array
        analogSamples[i][j] = analogSamples[i][j+1];
      }
    }
  }
  for (int i = 0; i < NUM_INPUT_PINS; ++i) {
    loggedSample = false;
    for (int j = 0; j < NUM_SAMPLES; ++j) {
      if ((j == LAST_SAMPLE || inputSamples[i][j] == -1) && ! loggedSample) {
        inputSamples[i][j] = digitalRead(analogPins[i]);
        loggedSample = true;
      } else if (inputSamples[i][LAST_SAMPLE] != -1 && j < LAST_SAMPLE) {
        // Shift samples down the array
        inputSamples[i][j] = inputSamples[i][j+1];
      }
    }
  }
  if (!xbeeSerial) {
    delay(5000);
  } else if (xbee.readPacket(5000)) {
    XBeeResponse response = xbee.getResponse();
    if (response.getApiId() == RX_16_IO_RESPONSE) {
      Rx16IoSampleResponse ioSample;
      xbee.getResponse().getRx16IoSampleResponse(ioSample);

      byte xbeeNode = ioSample.getRemoteAddress16();
      #ifdef LOGGING
      HAVE_XBEE_PACKET_FROM_NODE.print(Serial);
      Serial.println(xbeeNode,DEC);
      #endif
      if (xbeeNode < MAX_XBEE_NODES) {
        for (int i = 0; i < NUM_XBEE_PINS; ++i ) {
          int sampleSize = ioSample.getSampleSize();
          if (ioSample.isAnalogEnabled(i)) {
            int samples[sampleSize];
            for (int k = 0; k < sampleSize; ++k) {
              samples[k] = ioSample.getAnalog(i, k);
            }
            xbeeSamples[xbeeNode][i] = smoothSamples(samples,sampleSize);
            #ifdef LOGGING
            XBEE_SAMPLES_FOR_NODE.print(Serial);
            Serial.print(xbeeNode,DEC);
            PROG_PIN.print(Serial);
            Serial.print(i);
            SMOOTHED_OUT_TO.print(Serial);
            Serial.println(xbeeSamples[xbeeNode][i]);
            #endif
          } else if (ioSample.isDigitalEnabled(i)) {
            if (xbeeSamples[xbeeNode][i] == -1)
              xbeeSamples[xbeeNode][i] = 0;
            for (int k = 0; k < sampleSize; ++k) {
              xbeeSamples[xbeeNode][i] += ioSample.getAnalog(i, k) ? 1 : 0;
            }
          }
        }
      }
    }
  } else {
    #ifdef LOGGING
    NO_XBEE_PACKET.print(Serial);
    #endif
  }
}

void CheckAndSubmitSamples() {
  if (samplesBeforeSubmit > 0) {
    --samplesBeforeSubmit;
    return;
  }
  if ((now() - lastSampleSubmission) < SAMPLE_SUBMIT_FREQUENCY) {
    return;
  }

  int submitSamples[NUM_ANALOG_PINS];

  int contentLength = 0;
  for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
    submitSamples[i] = -1;
    if (analogPins[i] == -1) {
      continue;
    }
    submitSamples[i] = smoothSamples(analogSamples[i], NUM_SAMPLES);
    #ifdef LOGGING
    PROG_SAMPLE.print(Serial);
    Serial.print(i);
    PROG_EQUALS.print(Serial);
    Serial.println(submitSamples[i]);
    #endif
    if (submitSamples[i] != -1) {
      contentLength += 7; // A0=FFF& or A10=FFF&
      if (analogPins[i] >= 10 )
        ++contentLength;
    }
  }

  for (int i = 0; i < MAX_XBEE_NODES; ++i) {
      for (int j = 0; j < NUM_XBEE_PINS; ++j) {
        if (xbeeSamples[i][j] != -1) {
          // X0P1=FFF&
          contentLength += 9;
        }
      }
  }

  EthernetClient c;
  HttpClient http(c);

  char configPath[22] = "/api/s/";
  const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  const unsigned long int divisors [4] = { 0xFFFFFF, 0xFFFF, 0xFF, 0x01 };
  // Append the MAC address
  for (int i =0; i < 6; i++)
  {
    configPath[7+(2*i)] = hexDigits[(mac[i] >> 4) & 0x0f];
    configPath[8+(2*i)] = hexDigits[mac[i] & 0x0f];
  }
  // And now the config version number
  configPath[19] = '/';
  configPath[20] = hexDigits[YAHMS_API_VERSION];
  // And finally append the timestamp for when we last updated the config
  configPath[21] = '\0';

  #ifdef LOGGING
  SUBMITTING_SAMPLES_TO.print(Serial);
  Serial.print(YAHMS_SERVER);
  Serial.println(configPath);
  #endif
  http.beginRequest();
  if (http.post(YAHMS_SERVER, 80, configPath, USERAGENT) == 0)
  {
    // Request sent okay
//    #ifdef LOGGING
//    CONTENT_LENGTH.print(Serial);
//    Serial.println(contentLength);
//    #endif
//    CONTENT_LENGTH.print(http);
//    http.println(contentLength);
//    SAMPLE_CONTENT_TYPE.print(http);
//    http.println();
    http.sendHeader(CONTENT_LENGTH,contentLength);
    http.sendHeader(SAMPLE_CONTENT_TYPE);
    http.endRequest();

    for (int i = 0; i < NUM_ANALOG_PINS; ++i) {
      if (submitSamples[i] != -1) {
        http.print("A");
        http.print(analogPins[i],DEC);
        http.print("=");
        http.print(hexDigits[submitSamples[i]>>8 & 0x0F]);
        http.print(hexDigits[submitSamples[i]>>4 & 0x0F]);
        http.print(hexDigits[submitSamples[i] & 0x0F]);
        http.print("&");
      }
    }

    for (int i = 0; i < MAX_XBEE_NODES; ++i) {
      for (int j = 0; j < NUM_XBEE_PINS; ++j) {
        if (xbeeSamples[i][j] != -1) {
          // X0P1=FFF&
          http.print("X");
          http.print(i);
          http.print("P");
          http.print(j);
          http.print("=");
          http.print(hexDigits[xbeeSamples[i][j]>>8 & 0x0F]);
          http.print(hexDigits[xbeeSamples[i][j]>>4 & 0x0F]);
          http.print(hexDigits[xbeeSamples[i][j] & 0x0F]);
          http.print("&");
          xbeeSamples[i][j] = -1;
        }
      }
    }

    int err = http.responseStatusCode();
    if ((err >= 200) && (err < 300))
    {
      // We've got a successful response
      // And we're not interested in any of the headers
      err = http.skipResponseHeaders();
      if (err >= 0)
      {
      }
    } else {
      #ifdef LOGGING
      HTTP_SUBMIT_REQUEST_FAILED.print(Serial);
      Serial.println(err);
      #endif

    }
    http.stop();
    c.stop();
  } else {
    #ifdef LOGGING
    HTTP_SUBMIT_CONNECTION_FAILED.print(Serial);
    #endif
  }

  // Have to assume it worked really
  lastSampleSubmission = now();

}

int smoothSamples( int samples[], int numSamples) {

  int diff = 0, total = 0, average = 0, number = 0, deviation = 0;

  for (int j = 0; j < numSamples; ++j) {
    if (samples[j] != -1) {
      total += samples[j];
      ++number;
    }
  }
  if (number > 0) {
    average = total / number;
    for (int j = 0; j < numSamples; ++j) {
      if (samples[j] != -1) {
        deviation += abs(samples[j] - average);
      }
    }
    deviation = deviation / number;
    number = 0;
    total = 0;
    for (int j = 0; j < numSamples; ++j) {
      if (samples[j] != -1) {
        diff = abs(samples[j] - average);
        if ( deviation == 0 || diff <= deviation) {
          total += samples[j];
          ++number;
        }
      }
    }
    average = total / number;
    return average;
  } else {
    return -1;
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix for i#95158: Don't reset selected colour on tab switch<commit_after><|endoftext|>


<commit_before>/*
 * PImpl.hpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant to the terms of a commercial license agreement
 * with RStudio, then this program is licensed to you under the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#ifndef SHARED_CORE_P_IMPL_HPP
#define SHARED_CORE_P_IMPL_HPP

#include <memory>

/**
 * @brief Shared start of the macro to define a private implementation for a class.
 */
#define PRIVATE_IMPL_START                            \
   struct Impl;

/**
 * @brief Macro to define a private implementation for a non-copyable class.
 *
 * Class which use this macro must either be non-copyable or define a custom deep-copy constructor and operator which
 * performs a deep copy of the impl.
 *
 * This macro should be included in the private or protected section of a classes declaration.
 * The PRIVATE_IMPL_DELETER_IMPL macro must be used in the definition file, after the definition of the Impl struct.
 * struct OwningClass::Impl should be defined in the definition file before defining OwningClass.
 *
 * @param in_memberName    The name of the private implementation member variable (e.g. m_impl).
 */
#define PRIVATE_IMPL(in_memberName)                      \
   PRIVATE_IMPL_START                                    \
   struct ImplDeleter { void operator()(Impl*); };       \
   std::unique_ptr<Impl, ImplDeleter> in_memberName;

/**
 * @brief Macro to define a private implementation which would be shared with copied instances.
 *
 * This macro should be included in the private or protected section of a classes declaration.
 * struct OwningClass::Impl should be defined in the definition file before defining OwningClass.
 *
 * @param in_memeberName    The name of the private implementation member variable (e.g. m_impl).
 */
#define PRIVATE_IMPL_SHARED(in_memberName) \
   PRIVATE_IMPL_START                        \
   std::shared_ptr<Impl> in_memberName;

/**
 * @brief Macro which implements the deleter for the class's private implementation. This macro must be used after the
 *        implementation of the Impl struct in the definition file.
 *
 * @param in_owningClass    The name of the class which owns the private implementation (e.g. Error).
 */
#define PRIVATE_IMPL_DELETER_IMPL(in_owningClass)                                   \
void in_owningClass::ImplDeleter::operator()(in_owningClass::Impl* io_toDelete)     \
{                                                                                \
   delete io_toDelete;                                                              \
}

#endif
<commit_msg>fix another whitespace issue<commit_after>/*
 * PImpl.hpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant to the terms of a commercial license agreement
 * with RStudio, then this program is licensed to you under the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#ifndef SHARED_CORE_P_IMPL_HPP
#define SHARED_CORE_P_IMPL_HPP

#include <memory>

/**
 * @brief Shared start of the macro to define a private implementation for a class.
 */
#define PRIVATE_IMPL_START                            \
   struct Impl;

/**
 * @brief Macro to define a private implementation for a non-copyable class.
 *
 * Class which use this macro must either be non-copyable or define a custom deep-copy constructor and operator which
 * performs a deep copy of the impl.
 *
 * This macro should be included in the private or protected section of a classes declaration.
 * The PRIVATE_IMPL_DELETER_IMPL macro must be used in the definition file, after the definition of the Impl struct.
 * struct OwningClass::Impl should be defined in the definition file before defining OwningClass.
 *
 * @param in_memberName    The name of the private implementation member variable (e.g. m_impl).
 */
#define PRIVATE_IMPL(in_memberName)                      \
   PRIVATE_IMPL_START                                    \
   struct ImplDeleter { void operator()(Impl*); };       \
   std::unique_ptr<Impl, ImplDeleter> in_memberName;

/**
 * @brief Macro to define a private implementation which would be shared with copied instances.
 *
 * This macro should be included in the private or protected section of a classes declaration.
 * struct OwningClass::Impl should be defined in the definition file before defining OwningClass.
 *
 * @param in_memeberName    The name of the private implementation member variable (e.g. m_impl).
 */
#define PRIVATE_IMPL_SHARED(in_memberName)   \
   PRIVATE_IMPL_START                        \
   std::shared_ptr<Impl> in_memberName;

/**
 * @brief Macro which implements the deleter for the class's private implementation. This macro must be used after the
 *        implementation of the Impl struct in the definition file.
 *
 * @param in_owningClass    The name of the class which owns the private implementation (e.g. Error).
 */
#define PRIVATE_IMPL_DELETER_IMPL(in_owningClass)                                   \
void in_owningClass::ImplDeleter::operator()(in_owningClass::Impl* io_toDelete)     \
{                                                                                \
   delete io_toDelete;                                                              \
}

#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/common/utils/imageProcs/common_ringId.C $    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <common_ringId.H>

namespace P9_RID
{
#include <p9_ringId.H>
};
namespace CEN_RID
{
#include <cen_ringId.H>
};
#include <p9_infrastruct_help.H>

// These strings must adhere precisely to the enum of ppeType.
const char* ppeTypeName[] = { "SBE",
                              "CME",
                              "SGPE"
                            };

// These strings must adhere precisely to the enum of RingVariant.
const char* ringVariantName[] = { "BASE",
                                  "CC",
                                  "RL",
                                  "OVRD",
                                  "OVLY"
                                };

int ringid_get_noof_chiplets( ChipType_t  i_chipType,
                              uint32_t    i_torMagic,
                              uint8_t*    o_numChiplets )
{
    switch (i_chipType)
    {
        case CT_P9N:
        case CT_P9C:
            if ( i_torMagic == TOR_MAGIC_SBE  ||
                 i_torMagic == TOR_MAGIC_OVRD ||
                 i_torMagic == TOR_MAGIC_OVLY )
            {
                *o_numChiplets = P9_RID::SBE_NOOF_CHIPLETS;
            }
            else if ( i_torMagic == TOR_MAGIC_CME )
            {
                *o_numChiplets = P9_RID::CME_NOOF_CHIPLETS;
            }
            else if ( i_torMagic == TOR_MAGIC_SGPE )
            {
                *o_numChiplets = P9_RID::SGPE_NOOF_CHIPLETS;
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType (=CT_P9x=%d)\n", i_torMagic, i_chipType);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            break;

        case CT_CEN:
            if ( i_torMagic == TOR_MAGIC_CEN ||
                 i_torMagic == TOR_MAGIC_OVRD )
            {
                *o_numChiplets = CEN_RID::CEN_NOOF_CHIPLETS;
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType (=CT_CEN)\n", i_torMagic);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            break;

        default:
            MY_ERR("Invalid chipType (=0x%02x)\n", i_chipType);
            return TOR_INVALID_CHIPTYPE;
    }

    return TOR_SUCCESS;
}

int  ringid_get_properties( ChipType_t         i_chipType,
                            uint32_t           i_torMagic,
                            ChipletType_t      i_chiplet,
                            ChipletData_t**    o_chipletData,
                            GenRingIdList**    o_ringIdListCommon,
                            GenRingIdList**    o_ringIdListInstance,
                            RingVariantOrder** o_ringVariantOrder,
                            RingProperties_t** o_ringProps,
                            uint8_t*           o_numVariants )
{
    switch (i_chipType)
    {
        case CT_P9N:
        case CT_P9C:
            if ( i_torMagic == TOR_MAGIC_SBE  ||
                 i_torMagic == TOR_MAGIC_OVRD ||
                 i_torMagic == TOR_MAGIC_OVLY )
            {
                P9_RID::ringid_get_chiplet_properties(
                    i_chiplet,
                    o_chipletData,
                    o_ringIdListCommon,
                    o_ringIdListInstance,
                    o_ringVariantOrder,
                    o_numVariants );

                if ( i_torMagic == TOR_MAGIC_OVRD ||
                     i_torMagic == TOR_MAGIC_OVLY )
                {
                    *o_numVariants = 1;
                }
            }
            else if ( i_torMagic == TOR_MAGIC_CME )
            {
                *o_chipletData        = (ChipletData_t*)&P9_RID::EC::g_chipletData;
                *o_ringIdListCommon   = (GenRingIdList*)P9_RID::EC::RING_ID_LIST_COMMON;
                *o_ringIdListInstance = (GenRingIdList*)P9_RID::EC::RING_ID_LIST_INSTANCE;
                *o_ringVariantOrder   = (RingVariantOrder*)P9_RID::EC::RING_VARIANT_ORDER;
                *o_numVariants        = P9_RID::EC::g_chipletData.iv_num_ring_variants;
            }
            else if ( i_torMagic == TOR_MAGIC_SGPE )
            {
                *o_chipletData        = (ChipletData_t*)&P9_RID::EQ::g_chipletData;
                *o_ringIdListCommon   = (GenRingIdList*)P9_RID::EQ::RING_ID_LIST_COMMON;
                *o_ringIdListInstance = (GenRingIdList*)P9_RID::EQ::RING_ID_LIST_INSTANCE;
                *o_ringVariantOrder   = (RingVariantOrder*)P9_RID::EQ::RING_VARIANT_ORDER;
                *o_numVariants        = P9_RID::EQ::g_chipletData.iv_num_ring_variants;
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType=CT_P9x=%d\n", i_torMagic, i_chipType);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            *o_ringProps = (RingProperties_t*)P9_RID::RING_PROPERTIES;

            break;

        case CT_CEN:
            if ( i_torMagic == TOR_MAGIC_CEN ||
                 i_torMagic == TOR_MAGIC_OVRD )
            {
                CEN_RID::ringid_get_chiplet_properties(
                    i_chiplet,
                    o_chipletData,
                    o_ringIdListCommon,
                    o_ringIdListInstance,
                    o_ringVariantOrder,
                    o_numVariants );

                if ( i_torMagic == TOR_MAGIC_OVRD)
                {
                    *o_numVariants = 1;
                }
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType=CT_CEN\n", i_torMagic);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            *o_ringProps = (RingProperties_t*)CEN_RID::RING_PROPERTIES;

            break;

        default:
            MY_ERR("Invalid chipType (=0x%02x)\n", i_chipType);
            return TOR_INVALID_CHIPTYPE;

    }

    return TOR_SUCCESS;
}
<commit_msg>Additional risk level support - (step 1) Backward compatibility<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/common/utils/imageProcs/common_ringId.C $    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <common_ringId.H>

namespace P9_RID
{
#include <p9_ringId.H>
};
namespace CEN_RID
{
#include <cen_ringId.H>
};
#include <p9_infrastruct_help.H>

// These strings must adhere precisely to the enum of ppeType.
const char* ppeTypeName[] = { "SBE",
                              "CME",
                              "SGPE"
                            };

// These strings must adhere precisely to the enum of RingVariant.
const char* ringVariantName[] = { "BASE",
                                  "CC",
                                  "RL",
                                  "RL2",
                                };

#ifndef __HOSTBOOT_MODULE  // This is only used by ring_apply in EKB

static int get_ipl_base_param( char*& l_ringPath )
{
    l_ringPath = getenv("IPL_BASE");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: IPL_BASE environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}

static int get_ipl_cache_contained_param( char*& l_ringPath)
{
    l_ringPath = getenv("IPL_CACHE_CONTAINED");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: IPL_CACHE_CONTAINED environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}

static int get_ipl_risk_param( char*& l_ringPath)
{
    l_ringPath = getenv("IPL_RISK");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: IPL_RISK environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}

static int get_runtime_base_param( char*& l_ringPath)
{
    l_ringPath = getenv("RUNTIME_BASE");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: RUNTIME_BASE environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}
static int get_runtime_risk_param( char*& l_ringPath)
{
    l_ringPath = getenv("RUNTIME_RISK");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: RUNTIME_RISK environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}

static int get_runtime_risk2_param( char*& l_ringPath)
{
    l_ringPath = getenv("RUNTIME_RISK2");

    if (l_ringPath == NULL)
    {
        MY_ERR("p9_ring_apply.C: ring path: RUNTIME_RISK2 environment parameter not set.\n");
        return INFRASTRUCT_RC_ENV_ERROR;
    }

    return INFRASTRUCT_RC_SUCCESS;
}

int ringid_get_raw_ring_file_path( uint32_t        i_magic,
                                   RingVariant_t   i_ringVariant,
                                   char*           io_ringPath )
{
    int   rc = INFRASTRUCT_RC_SUCCESS;
    char* l_ringDir = NULL;

    do
    {

        if ( i_magic == TOR_MAGIC_SBE )
        {
            if ( i_ringVariant == RV_BASE )
            {
                rc = get_ipl_base_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_CC )
            {
                rc = get_ipl_cache_contained_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_RL )
            {
                rc = get_ipl_risk_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_RL2 )
            {
                // Valid RV for Quad chiplets but there's just no RL2 rings for SBE phase (by convention).
                rc = TOR_NO_RINGS_FOR_VARIANT;
                break;
            }
            else
            {
                MY_ERR("Invalid ringVariant(=%d) for TOR magic=0x%08x\n",
                       i_ringVariant, i_magic);
                rc = TOR_INVALID_VARIANT;
            }

            if (rc)
            {
                break;
            }

            strcat(io_ringPath, l_ringDir);
            strcat(io_ringPath, "/");
        }
        else if ( i_magic == TOR_MAGIC_CME ||
                  i_magic == TOR_MAGIC_SGPE )
        {
            if ( i_ringVariant == RV_BASE )
            {
                rc = get_runtime_base_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_CC )
            {
                // Valid RV for Quad chiplets but there's just no CC rings for runtime phases (by convention).
                rc = TOR_NO_RINGS_FOR_VARIANT;
                break;
            }
            else if ( i_ringVariant == RV_RL )
            {
                rc = get_runtime_risk_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_RL2 )
            {
                rc = get_runtime_risk2_param(l_ringDir);
            }
            else
            {
                MY_ERR("Invalid ringVariant(=%d) for TOR magic=0x%08x\n",
                       i_ringVariant, i_magic);
                rc = TOR_INVALID_VARIANT;
            }

            if (rc)
            {
                break;
            }

            strcat(io_ringPath, l_ringDir);
            strcat(io_ringPath, "/");
        }
        else if ( i_magic == TOR_MAGIC_CEN )
        {
            if ( i_ringVariant == RV_BASE )
            {
                rc = get_ipl_base_param(l_ringDir);
            }
            else if ( i_ringVariant == RV_RL )
            {
                rc = get_ipl_risk_param(l_ringDir);
            }
            else
            {
                MY_ERR("Invalid ringVariant(=%d) for TOR magic=0x%08x\n",
                       i_ringVariant, i_magic);
                rc = TOR_INVALID_VARIANT;
            }

            if (rc)
            {
                break;
            }

            strcat(io_ringPath, l_ringDir);
            strcat(io_ringPath, "/");
        }
        else if ( i_magic == TOR_MAGIC_OVRD ||
                  i_magic == TOR_MAGIC_OVLY )
        {
            // Path already fully qualified. Return io_ringPath as is.
        }
        else
        {
            MY_ERR("Unsupported value of TOR magic(=0x%X)\n", i_magic);
            rc = TOR_INVALID_MAGIC_NUMBER;
        }

    }
    while(0);

    return rc;
}

#endif // End of  ifndef __HOSTBOOT_MODULE

int ringid_get_noof_chiplets( ChipType_t  i_chipType,
                              uint32_t    i_torMagic,
                              uint8_t*    o_numChiplets )
{
    switch (i_chipType)
    {
        case CT_P9N:
        case CT_P9C:
        case CT_P9A:
            if ( i_torMagic == TOR_MAGIC_SBE  ||
                 i_torMagic == TOR_MAGIC_OVRD ||
                 i_torMagic == TOR_MAGIC_OVLY )
            {
                *o_numChiplets = P9_RID::SBE_NOOF_CHIPLETS;
            }
            else if ( i_torMagic == TOR_MAGIC_CME )
            {
                *o_numChiplets = P9_RID::CME_NOOF_CHIPLETS;
            }
            else if ( i_torMagic == TOR_MAGIC_SGPE )
            {
                *o_numChiplets = P9_RID::SGPE_NOOF_CHIPLETS;
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType (=CT_P9x=%d)\n", i_torMagic, i_chipType);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            break;

        case CT_CEN:
            if ( i_torMagic == TOR_MAGIC_CEN ||
                 i_torMagic == TOR_MAGIC_OVRD )
            {
                *o_numChiplets = CEN_RID::CEN_NOOF_CHIPLETS;
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType (=CT_CEN)\n", i_torMagic);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            break;

        default:
            MY_ERR("Invalid chipType (=0x%02x)\n", i_chipType);
            return TOR_INVALID_CHIPTYPE;
    }

    return TOR_SUCCESS;
}

int  ringid_get_properties( ChipType_t         i_chipType,
                            uint32_t           i_torMagic,
                            uint8_t            i_torVersion,
                            ChipletType_t      i_chipletType,
                            ChipletData_t**    o_chipletData,
                            GenRingIdList**    o_ringIdListCommon,
                            GenRingIdList**    o_ringIdListInstance,
                            RingVariantOrder** o_ringVariantOrder,
                            RingProperties_t** o_ringProps,
                            uint8_t*           o_numVariants )
{
    switch (i_chipType)
    {
        case CT_P9N:
        case CT_P9C:
        case CT_P9A:
            if ( i_torMagic == TOR_MAGIC_SBE  ||
                 i_torMagic == TOR_MAGIC_OVRD ||
                 i_torMagic == TOR_MAGIC_OVLY )
            {
                P9_RID::ringid_get_chiplet_properties(
                    i_chipletType,
                    o_chipletData,
                    o_ringIdListCommon,
                    o_ringIdListInstance,
                    o_ringVariantOrder,
                    o_numVariants );

                if ( i_torVersion < 6 &&
                     (i_chipletType == P9_RID::EQ_TYPE || i_chipletType == P9_RID::EC_TYPE) )
                {
                    *o_numVariants = *o_numVariants - 1;
                }

                if ( i_torMagic == TOR_MAGIC_OVRD ||
                     i_torMagic == TOR_MAGIC_OVLY )
                {
                    *o_numVariants = 1;
                }
            }
            else if ( i_torMagic == TOR_MAGIC_CME )
            {
                *o_chipletData        = (ChipletData_t*)&P9_RID::EC::g_chipletData;
                *o_ringIdListCommon   = (GenRingIdList*)P9_RID::EC::RING_ID_LIST_COMMON;
                *o_ringIdListInstance = (GenRingIdList*)P9_RID::EC::RING_ID_LIST_INSTANCE;
                *o_ringVariantOrder   = (RingVariantOrder*)P9_RID::EC::RING_VARIANT_ORDER;
                *o_numVariants        = P9_RID::EC::g_chipletData.iv_num_ring_variants;

                if (i_torVersion < 6)
                {
                    *o_numVariants = *o_numVariants - 1;
                }
            }
            else if ( i_torMagic == TOR_MAGIC_SGPE )
            {
                *o_chipletData        = (ChipletData_t*)&P9_RID::EQ::g_chipletData;
                *o_ringIdListCommon   = (GenRingIdList*)P9_RID::EQ::RING_ID_LIST_COMMON;
                *o_ringIdListInstance = (GenRingIdList*)P9_RID::EQ::RING_ID_LIST_INSTANCE;
                *o_ringVariantOrder   = (RingVariantOrder*)P9_RID::EQ::RING_VARIANT_ORDER;
                *o_numVariants        = P9_RID::EQ::g_chipletData.iv_num_ring_variants;

                if (i_torVersion < 6)
                {
                    *o_numVariants = *o_numVariants - 1;
                }
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType=CT_P9x=%d\n", i_torMagic, i_chipType);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            *o_ringProps = (RingProperties_t*)P9_RID::RING_PROPERTIES;

            break;

        case CT_CEN:
            if ( i_torMagic == TOR_MAGIC_CEN ||
                 i_torMagic == TOR_MAGIC_OVRD )
            {
                CEN_RID::ringid_get_chiplet_properties(
                    i_chipletType,
                    o_chipletData,
                    o_ringIdListCommon,
                    o_ringIdListInstance,
                    o_ringVariantOrder,
                    o_numVariants );

                if ( i_torMagic == TOR_MAGIC_OVRD)
                {
                    *o_numVariants = 1;
                }
            }
            else
            {
                MY_ERR("Invalid torMagic (=0x%08x) for chipType=CT_CEN\n", i_torMagic);
                return TOR_INVALID_MAGIC_NUMBER;
            }

            *o_ringProps = (RingProperties_t*)CEN_RID::RING_PROPERTIES;

            break;

        default:
            MY_ERR("Invalid chipType (=0x%02x)\n", i_chipType);
            return TOR_INVALID_CHIPTYPE;

    }

    return TOR_SUCCESS;
}
<|endoftext|>