<commit_before>//
//  main_test.cpp
//  RosterDesNurses
//
//  Created by Jeremy Omer on 04/03/2015.
//  Copyright (c) 2015 Jeremy Omer. All rights reserved.
//

#include "main_test.h"
#include "ReadWrite.h"
#include "Greedy.h"
#include "MasterProblem.h"
#include "SubProblem.h"
#include "CbcModeler.h"
#include "MyTools.h"

void main_test()
{
	//testFunction_Antoine();
	testFunction_Jeremy();
	//testFunction_Samuel();
}

// Function for testing parts of the code (Antoine)
void testFunction_Antoine(){

   // Time the complete execution of the algorithm
   Tools::Timer* timertotal = new Tools::Timer();
   timertotal->init();
   timertotal->start();

   // Create a log file
   string logFile = "logs/test.log";
   Tools::LogOutput logStream(logFile);

   //Create an output file
   string outFile = "outfiles/test.out";
   Tools::LogOutput outStream(outFile);

   string data = "testdatasets/";// testdatasets datasets
   const char* inst = "n005w4";// n100w4 n030w4 n005w4

   string scenarPath = data + inst + "/Sc-" + inst + ".txt";
   //n005w4: {1, 2, 3, 3}
   //n012w8: {3, 5, 0, 2, 0, 4, 5, 2}
   vector<int> numberWeek = {1, 2, 3, 3};
   vector<string> weekPaths(numberWeek.size());
   for(int i=0; i<numberWeek.size(); ++i){
      string path = data + inst + "/WD-" + inst + "-"+std::to_string(numberWeek[i])+".txt";
      weekPaths[i] = path;
   }
   string firstHistoryPath = data + inst + "/H0-" + inst + "-0.txt";

   // Read the input data from files
   Scenario* pScen = ReadWrite::readScenario(scenarPath);
   Preferences preferences;
   Demand* pWeekDemand = ReadWrite::readWeeks(weekPaths, pScen);
   ReadWrite::readHistory(firstHistoryPath,pScen);

   // Check that the scenario was read properly
   //
   // logStream << *pScen << std::endl;
   logStream << pScen->toString() << std::endl;
   logStream << pWeekDemand->toString(true) << std::endl;

   // Write the aggregate information on the demand
   //

   // Write aggregate information on the cover capacity of the staff
   // (TBD)

   //Compute initial solution
   //
   Greedy* pGreedy =
      new Greedy(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();
   outStream << pGreedy->solutionToLogString();

   // Instantiate the solver class as a test
   //
   MasterProblem* pBCP =
      new MasterProblem(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState(), S_BCP, pGreedy->getSolution());
   pBCP->solve();

   // Write the solution in the required output format
   vector<string> solutions = pBCP->solutionToString(pScen->nbWeeks());
   for(int w=0; w<pScen->nbWeeks(); ++w){
      int thisWeek = w+pScen->thisWeek();
      char solutionFile[30];
      snprintf ( solutionFile, 30, "outfiles/Sol-%s-%d-%d.txt", inst, numberWeek[w], thisWeek );
      Tools::LogOutput solutionStream(solutionFile);
      solutionStream << solutions[w];
   }

   // Write the solution in an output file
   outStream << pBCP->solutionToLogString();

   // Display the total time spent in the algorithm
   timertotal->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertotal->dSinceInit());
   logStream.print("\n");

   // free the allocated pointers
   //
   //   delete vrp;
   delete timertotal;
   delete pWeekDemand;
   delete pScen;
   delete pGreedy;
   delete pBCP;
}

// Function for testing parts of the code (Jeremy)
void testFunction_Jeremy(){

   // Time the complete execution of the algorithm
   Tools::Timer* timertotal = new Tools::Timer();
   timertotal->init();
   timertotal->start();

   // Create a log file
   string logFile = "logfiles/test.log";
   Tools::LogOutput logStream(logFile);

	/************************************************************************
	* Go through the demands of the directory to find invariants in the demand
	*************************************************************************/

	ReadWrite::compareDemands("testdatasets/n005w4");

	/************************************************************************
	* Initialize the week scenario by reading the input files
	*************************************************************************/

	Scenario* pScen(0);
	pScen = initializeScenario("datasets/n030w4/Sc-n030w4.txt",
		"datasets/n030w4/WD-n030w4-1.txt", "datasets/n030w4/H0-n030w4-0.txt");

	// Check that the scenario was read properly
	logStream << pScen->toString() << std::endl;
	logStream << pScen->pWeekDemand()->toString(true) << std::endl;

	/****************************************
	* Run the greedy to get an initial solution
	*****************************************/

   Greedy* pGreedy =
      new Greedy(pScen, pScen->pWeekDemand(),	pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();

	// Write the solution in the required output format
	string greedyFile = "outfiles/greedy.out";
	Tools::LogOutput greedyStream(greedyFile);
	greedyStream << pGreedy->solutionToString();

	// Write the solution and advanced information in a more convenient format
	string greedyLog = "outfiles/greedylog.out";
	Tools::LogOutput greedyLogStream(greedyLog);
	greedyLogStream << pGreedy->solutionToLogString();

	/****************************************
	* Test the CBC modeler
	*****************************************/
	std::vector<Roster> solIni = pGreedy->getSolution();
	testCbc(pScen, pScen->pWeekDemand(), pScen->pWeekPreferences(), pScen->pInitialState(),solIni);

   // Display the total time spent in the tests
	//
   timertotal->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertotal->dSinceInit());
   logStream.print("\n");

   // free the allocated pointers
   //
   delete timertotal;
   delete pScen;
   delete pGreedy;
}

// Function for testing parts of the code (Samuel)
void testFunction_Samuel(){

   Tools::Timer* timertest = new Tools::Timer();
   timertest->init();
   timertest->start();

   // log + output
   //
   string logFile = "../logfiles/samuel_test.log";
   Tools::LogOutput logStream(logFile);
   string outFile = "outfiles/test.out";
   Tools::LogOutput outStream(outFile);

   // Instances
   //
   string data = "datasets/";
   string inst = "n100w4";			// n100w4 n030w4 n005w4

   // Paths
   //
   string scenarPath = data + inst + "/Sc-" + inst + ".txt";
   vector<int> numberWeek = {1, 2, 3, 3};
   vector<string> weekPaths(numberWeek.size());
   for(int i=0; i<numberWeek.size(); ++i){
      string path = data + inst + "/WD-" + inst + "-"+std::to_string(numberWeek[i])+".txt";
      weekPaths[i] = path;
   }
   string firstHistoryPath = data + inst + "/H0-" + inst + "-0.txt";

   // Read the input data from files
   //
   Scenario* pScen = ReadWrite::readScenario(scenarPath);
   Preferences preferences;
   Demand* pWeekDemand = ReadWrite::readWeeks(weekPaths, pScen);
   ReadWrite::readHistory(firstHistoryPath,pScen);

   // Check that the scenario was read properly
   //
   logStream << pScen->toString() << std::endl;
   logStream << pWeekDemand->toString(true) << std::endl;

   //Compute initial solution
   //
   Greedy* pGreedy =
      new Greedy(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();
   outStream << pGreedy->solutionToLogString();

   // Instantiate solver + solve the instance
   //
   MasterProblem* pSolverTest = new MasterProblem(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState(), S_BCP, pGreedy->getSolution());
   pSolverTest->solve();

   // Write the solution in an output file
   //
   outStream << pSolverTest->solutionToLogString();

   // Display the total time spent in the algorithm
   //
   timertest->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertest->dSinceInit());
   logStream.print("\n");

   // Delete
   //
   delete timertest;
   delete pWeekDemand;
   delete pScen;
   delete pGreedy;
   delete pSolverTest;
}

/************************************************************************
* Initialize the week scenario by reading the input files
*************************************************************************/

Scenario* initializeScenario(string scenFile, string demandFile, string historyFile) {

	Demand* pDemand(0);
	Preferences* pPref(0);

	// Read the scenario
	Scenario* pScen = ReadWrite::readScenario(scenFile);

	// Read the demand and preferences and link them with the scenario
	ReadWrite::readWeek(demandFile, pScen,&pDemand,&pPref);
	pScen->linkWithDemand(pDemand);
	pScen->linkWithPreferences(*pPref);

	// Read the history
	ReadWrite::readHistory(historyFile, pScen);

	return pScen;
}

/****************************************
* Test the CBC modeler
*****************************************/
void testCbc(Scenario* pScen, Demand* pDemand, Preferences* pPref,
	std::vector<State>* pStateIni, std::vector<Roster>& solIni) {
		// First method: directly instantiate a master problem equipped with a Cbc
		// modeler as input
		//
		MasterProblem* pMPCbc;
		pMPCbc = new MasterProblem(pScen, pDemand, pPref, pStateIni, S_CBC, solIni);
		pMPCbc->solve();

		// Write the solution in the required output format
		string outFile = "outfiles/cbctest1.out";
		Tools::LogOutput outStream(outFile);
		outStream << pMPCbc->solutionToString();

		// Second method, load the Cbc modeler from the model of the MP
		//
		CoinModeler* coinModel = (CoinModeler*) pMPCbc->getModel();
		CbcModeler* cbcModel =
			new CbcModeler(coinModel->getCoreVars(),coinModel->getColumns(),coinModel->getCons());
		cbcModel->solve();

		// a new method is needed to get the solution in the proper format from this
		// external Cbc model
}
<commit_msg>AL: test<commit_after>//
//  main_test.cpp
//  RosterDesNurses
//
//  Created by Jeremy Omer on 04/03/2015.
//  Copyright (c) 2015 Jeremy Omer. All rights reserved.
//

#include "main_test.h"
#include "ReadWrite.h"
#include "Greedy.h"
#include "MasterProblem.h"
#include "SubProblem.h"
#include "CbcModeler.h"
#include "MyTools.h"

void main_test()
{
	testFunction_Antoine();
//	testFunction_Jeremy();
	//testFunction_Samuel();
}

// Function for testing parts of the code (Antoine)
void testFunction_Antoine(){

   // Time the complete execution of the algorithm
   Tools::Timer* timertotal = new Tools::Timer();
   timertotal->init();
   timertotal->start();

   // Create a log file
   string logFile = "logs/test.log";
   Tools::LogOutput logStream(logFile);

   //Create an output file
   string outFile = "outfiles/test.out";
   Tools::LogOutput outStream(outFile);

   string data = "testdatasets/";// testdatasets datasets
   const char* inst = "n005w4";// n100w4 n030w4 n005w4

   string scenarPath = data + inst + "/Sc-" + inst + ".txt";
   //n005w4: {1, 2, 3, 3}
   //n012w8: {3, 5, 0, 2, 0, 4, 5, 2}
   vector<int> numberWeek = {1, 2, 3, 3};
   vector<string> weekPaths(numberWeek.size());
   for(int i=0; i<numberWeek.size(); ++i){
      string path = data + inst + "/WD-" + inst + "-"+std::to_string(numberWeek[i])+".txt";
      weekPaths[i] = path;
   }
   string firstHistoryPath = data + inst + "/H0-" + inst + "-0.txt";

   // Read the input data from files
   Scenario* pScen = ReadWrite::readScenario(scenarPath);
   Preferences preferences;
   Demand* pWeekDemand = ReadWrite::readWeeks(weekPaths, pScen);
   ReadWrite::readHistory(firstHistoryPath,pScen);

   // Check that the scenario was read properly
   //
   // logStream << *pScen << std::endl;
   logStream << pScen->toString() << std::endl;
   logStream << pWeekDemand->toString(true) << std::endl;

   // Write the aggregate information on the demand
   //

   // Write aggregate information on the cover capacity of the staff
   // (TBD)

   //Compute initial solution
   //
   Greedy* pGreedy =
      new Greedy(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();
   outStream << pGreedy->solutionToLogString();

   // Instantiate the solver class as a test
   //
   MasterProblem* pBCP =
      new MasterProblem(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState(), S_BCP, pGreedy->getSolution());
   pBCP->solve();

   // Write the solution in the required output format
   vector<string> solutions = pBCP->solutionToString(pScen->nbWeeks());
   for(int w=0; w<pScen->nbWeeks(); ++w){
      int thisWeek = w+pScen->thisWeek();
      char solutionFile[30];
      snprintf ( solutionFile, 30, "outfiles/Sol-%s-%d-%d.txt", inst, numberWeek[w], thisWeek );
      Tools::LogOutput solutionStream(solutionFile);
      solutionStream << solutions[w];
   }

   // Write the solution in an output file
   outStream << pBCP->solutionToLogString();

   // Display the total time spent in the algorithm
   timertotal->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertotal->dSinceInit());
   logStream.print("\n");

   // free the allocated pointers
   //
   //   delete vrp;
   delete timertotal;
   delete pWeekDemand;
   delete pScen;
   delete pGreedy;
   delete pBCP;
}

// Function for testing parts of the code (Jeremy)
void testFunction_Jeremy(){

   // Time the complete execution of the algorithm
   Tools::Timer* timertotal = new Tools::Timer();
   timertotal->init();
   timertotal->start();

   // Create a log file
   string logFile = "logfiles/test.log";
   Tools::LogOutput logStream(logFile);

	/************************************************************************
	* Go through the demands of the directory to find invariants in the demand
	*************************************************************************/

	ReadWrite::compareDemands("testdatasets/n005w4");

	/************************************************************************
	* Initialize the week scenario by reading the input files
	*************************************************************************/

	Scenario* pScen(0);
	pScen = initializeScenario("datasets/n030w4/Sc-n030w4.txt",
		"datasets/n030w4/WD-n030w4-1.txt", "datasets/n030w4/H0-n030w4-0.txt");

	// Check that the scenario was read properly
	logStream << pScen->toString() << std::endl;
	logStream << pScen->pWeekDemand()->toString(true) << std::endl;

	/****************************************
	* Run the greedy to get an initial solution
	*****************************************/

   Greedy* pGreedy =
      new Greedy(pScen, pScen->pWeekDemand(),	pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();

	// Write the solution in the required output format
	string greedyFile = "outfiles/greedy.out";
	Tools::LogOutput greedyStream(greedyFile);
	greedyStream << pGreedy->solutionToString();

	// Write the solution and advanced information in a more convenient format
	string greedyLog = "outfiles/greedylog.out";
	Tools::LogOutput greedyLogStream(greedyLog);
	greedyLogStream << pGreedy->solutionToLogString();

	/****************************************
	* Test the CBC modeler
	*****************************************/
	std::vector<Roster> solIni = pGreedy->getSolution();
	testCbc(pScen, pScen->pWeekDemand(), pScen->pWeekPreferences(), pScen->pInitialState(),solIni);

   // Display the total time spent in the tests
	//
   timertotal->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertotal->dSinceInit());
   logStream.print("\n");

   // free the allocated pointers
   //
   delete timertotal;
   delete pScen;
   delete pGreedy;
}

// Function for testing parts of the code (Samuel)
void testFunction_Samuel(){

   Tools::Timer* timertest = new Tools::Timer();
   timertest->init();
   timertest->start();

   // log + output
   //
   string logFile = "../logfiles/samuel_test.log";
   Tools::LogOutput logStream(logFile);
   string outFile = "outfiles/test.out";
   Tools::LogOutput outStream(outFile);

   // Instances
   //
   string data = "datasets/";
   string inst = "n100w4";			// n100w4 n030w4 n005w4

   // Paths
   //
   string scenarPath = data + inst + "/Sc-" + inst + ".txt";
   vector<int> numberWeek = {1, 2, 3, 3};
   vector<string> weekPaths(numberWeek.size());
   for(int i=0; i<numberWeek.size(); ++i){
      string path = data + inst + "/WD-" + inst + "-"+std::to_string(numberWeek[i])+".txt";
      weekPaths[i] = path;
   }
   string firstHistoryPath = data + inst + "/H0-" + inst + "-0.txt";

   // Read the input data from files
   //
   Scenario* pScen = ReadWrite::readScenario(scenarPath);
   Preferences preferences;
   Demand* pWeekDemand = ReadWrite::readWeeks(weekPaths, pScen);
   ReadWrite::readHistory(firstHistoryPath,pScen);

   // Check that the scenario was read properly
   //
   logStream << pScen->toString() << std::endl;
   logStream << pWeekDemand->toString(true) << std::endl;

   //Compute initial solution
   //
   Greedy* pGreedy =
      new Greedy(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState());
   pGreedy->constructiveGreedy();
   outStream << pGreedy->solutionToLogString();

   // Instantiate solver + solve the instance
   //
   MasterProblem* pSolverTest = new MasterProblem(pScen, pWeekDemand,   pScen->pWeekPreferences(), pScen->pInitialState(), S_BCP, pGreedy->getSolution());
   pSolverTest->solve();

   // Write the solution in an output file
   //
   outStream << pSolverTest->solutionToLogString();

   // Display the total time spent in the algorithm
   //
   timertest->stop();
   logStream.print("Total time spent in the algorithm : ");
   logStream.print(timertest->dSinceInit());
   logStream.print("\n");

   // Delete
   //
   delete timertest;
   delete pWeekDemand;
   delete pScen;
   delete pGreedy;
   delete pSolverTest;
}

/************************************************************************
* Initialize the week scenario by reading the input files
*************************************************************************/

Scenario* initializeScenario(string scenFile, string demandFile, string historyFile) {

	Demand* pDemand(0);
	Preferences* pPref(0);

	// Read the scenario
	Scenario* pScen = ReadWrite::readScenario(scenFile);

	// Read the demand and preferences and link them with the scenario
	ReadWrite::readWeek(demandFile, pScen,&pDemand,&pPref);
	pScen->linkWithDemand(pDemand);
	pScen->linkWithPreferences(*pPref);

	// Read the history
	ReadWrite::readHistory(historyFile, pScen);

	return pScen;
}

/****************************************
* Test the CBC modeler
*****************************************/
void testCbc(Scenario* pScen, Demand* pDemand, Preferences* pPref,
	std::vector<State>* pStateIni, std::vector<Roster>& solIni) {
		// First method: directly instantiate a master problem equipped with a Cbc
		// modeler as input
		//
		MasterProblem* pMPCbc;
		pMPCbc = new MasterProblem(pScen, pDemand, pPref, pStateIni, S_CBC, solIni);
		pMPCbc->solve();

		// Write the solution in the required output format
		string outFile = "outfiles/cbctest1.out";
		Tools::LogOutput outStream(outFile);
		outStream << pMPCbc->solutionToString();

		// Second method, load the Cbc modeler from the model of the MP
		//
		CoinModeler* coinModel = (CoinModeler*) pMPCbc->getModel();
		CbcModeler* cbcModel =
			new CbcModeler(coinModel->getCoreVars(),coinModel->getColumns(),coinModel->getCons());
		cbcModel->solve();

		// a new method is needed to get the solution in the proper format from this
		// external Cbc model
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"
#include "../../../src/system/task.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace GTF;
#include <vector>

static std::vector<int> veve;
template<typename T, class B>
class CTekitou2 : public B
{
public:
	CTekitou2(T init) : hogehoge(init)
	{

	}
	~CTekitou2()
	{}

	T hogehoge;

	bool Execute(double e) override{ veve.push_back(hogehoge); return true; }
	unsigned int GetID()const override{ return hogehoge; }
};

namespace GTFTest
{
	TEST_CLASS(UnitTest1)
	{
	public:

		template<typename T, class B>
		class CTekitou : public B
		{
		public:
			CTekitou(T init) : hogehoge(init)
			{

			}
			~CTekitou()
			{}

			T hogehoge;
			unsigned int GetID()const{ return 1; }
			int GetDrawPriority()const{ return 1; }
		};

		TEST_METHOD(TestMethod1)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CTaskBase>(1)).lock();
			Assert::AreEqual((void*)task.FindTask(ptr->GetID()).lock().get(), (void*)ptr.get());
		}

		TEST_METHOD(TestMethod2)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CBackgroundTaskBase>(1)).lock();
			Assert::AreNotEqual((void*)(task.FindTask<CBackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			Assert::AreEqual((void*)(task.FindBGTask<CBackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			auto ptr2 = task.AddTask(static_cast<CTaskBase*>(new CTekitou<int, CBackgroundTaskBase>(1))).lock();
			Assert::AreNotEqual((void*)task.FindTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
			Assert::AreEqual((void*)task.FindBGTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
		}

		TEST_METHOD(TestMethod3)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CExclusiveTaskBase>(1)).lock();
			Assert::AreNotEqual((void*)(task.FindTask<CExclusiveTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			auto ptr2 = task.AddTask(static_cast<CTaskBase*>(new CTekitou<int, CExclusiveTaskBase>(1))).lock();
			Assert::AreNotEqual((void*)task.FindTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
		}

		TEST_METHOD(s)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			veve.clear();
			auto ptr = task.AddTask(new CTekitou2<int, CExclusiveTaskBase>(1));
			auto ptr2 = task.AddTask(new CTekitou2<int, CTaskBase>(2));
			task.Execute(0);
			Assert::AreEqual(2, veve[0]);
		}

		TEST_METHOD(s2)
		{
			// TODO: eXg R[hɑ}܂
			static CTaskManager task;
			class ct : public CTekitou2 < int, CExclusiveTaskBase >
			{
			public:
				ct(int init) : CTekitou2 < int, CExclusiveTaskBase >(init)
				{

				}
				void Initialize()
				{
					task.AddTask(new CTekitou2<int, CTaskBase>(2));
				}
			};

			veve.clear();
			auto ptr = task.AddTask(new ct(1));
			task.Execute(0);
			task.Execute(1);
			Assert::AreEqual(1, veve[0]);
			Assert::AreEqual(2, veve[1]);
		}

		TEST_METHOD(TestMethod4)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			for (int i = 1; i < 257;i++)
			{
				task.AddTask(new CTekitou2<int, CExclusiveTaskBase>(i));
				task.AddTask(static_cast<CTaskBase*>(new CTekitou<int, CExclusiveTaskBase>(2)));
			}
			task.RemoveTaskByID(1);
			for (int i = 0; i < 256;i++)
				task.Draw();
		}

		TEST_METHOD(^XN̈ˑ֌W)
		{
			// TODO: eXg R[hɑ}܂
			static CTaskManager task;
			class ct : public CTekitou2 < int, CExclusiveTaskBase >
			{
			public:
				ct(int init) : CTekitou2 < int, CExclusiveTaskBase >(init)
				{

				}
				void Initialize()
				{
					task.AddTask(new CTekitou2<int, CTaskBase>(hogehoge+20));
				}
				virtual bool Inactivate(unsigned int nextTaskID){ return true; }//!< ̔r^XNJnƂɌĂ΂
			};

			veve.clear();
			auto ptr = task.AddTask(new ct(1));
			task.Execute(0);
			auto ptr2 = task.AddTask(new ct(3));
			task.Execute(1);
			Assert::AreEqual(1, veve[0]);
			Assert::AreEqual(1+20, veve[1]);
			task.Execute(2);
			Assert::AreEqual(3, veve[2]);
			Assert::AreEqual(3+20, veve[3]);
			task.RevertExclusiveTaskByID(1);
			task.Execute(3);
			Assert::AreEqual(1, veve[4]);
			Assert::AreEqual(1+20, veve[5]);
			ptr2 = task.AddTask(new ct(4));
			task.Execute(4);
			task.RemoveTaskByID(21);
			task.Execute(5);
			Assert::AreEqual(4, veve[8]);
			Assert::AreEqual(4+20, veve[9]);

		}

	};
}<commit_msg>テストケース修正（現状未通過）<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"
#include "../../../src/system/task.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace GTF;
#include <vector>

static std::vector<int> veve;
template<typename T, class B>
class CTekitou2 : public B
{
public:
	CTekitou2(T init) : hogehoge(init)
	{

	}
	~CTekitou2()
	{}

	T hogehoge;

	bool Execute(double e) override{ veve.push_back(hogehoge); return true; }
	unsigned int GetID()const override{ return hogehoge; }
};

namespace GTFTest
{
	TEST_CLASS(UnitTest1)
	{
	public:

		template<typename T, class B>
		class CTekitou : public B
		{
		public:
			CTekitou(T init) : hogehoge(init)
			{

			}
			~CTekitou()
			{}

			T hogehoge;
			unsigned int GetID()const{ return hogehoge; }
			int GetDrawPriority()const{ return 1; }
			void Draw() override{ veve.push_back(hogehoge); }
		};

		TEST_METHOD(TestMethod1)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CTaskBase>(1)).lock();
			Assert::AreEqual((void*)task.FindTask(ptr->GetID()).lock().get(), (void*)ptr.get());
		}

		TEST_METHOD(TestMethod2)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CBackgroundTaskBase>(1)).lock();
			Assert::AreNotEqual((void*)(task.FindTask<CBackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			Assert::AreEqual((void*)(task.FindBGTask<CBackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			auto ptr2 = task.AddTask(static_cast<CTaskBase*>(new CTekitou<int, CBackgroundTaskBase>(1))).lock();
			Assert::AreNotEqual((void*)task.FindTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
			Assert::AreEqual((void*)task.FindBGTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
		}

		TEST_METHOD(TestMethod3)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			auto ptr = task.AddTask(new CTekitou<int, CExclusiveTaskBase>(1)).lock();
			Assert::AreNotEqual((void*)(task.FindTask<CExclusiveTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
			auto ptr2 = task.AddTask(static_cast<CTaskBase*>(new CTekitou<int, CExclusiveTaskBase>(1))).lock();
			Assert::AreNotEqual((void*)task.FindTask(ptr2->GetID()).lock().get(), (void*)ptr2.get());
		}

		TEST_METHOD(s)
		{
			// TODO: eXg R[hɑ}܂
			CTaskManager task;

			veve.clear();
			auto ptr = task.AddTask(new CTekitou2<int, CExclusiveTaskBase>(1));
			auto ptr2 = task.AddTask(new CTekitou2<int, CTaskBase>(2));
			task.Execute(0);
			Assert::AreEqual(2, veve[0]);
		}

		TEST_METHOD(s2)
		{
			// TODO: eXg R[hɑ}܂
			static CTaskManager task;
			class ct : public CTekitou2 < int, CExclusiveTaskBase >
			{
			public:
				ct(int init) : CTekitou2 < int, CExclusiveTaskBase >(init)
				{

				}
				void Initialize()
				{
					task.AddTask(new CTekitou2<int, CTaskBase>(2));
				}
			};

			veve.clear();
			auto ptr = task.AddTask(new ct(1));
			task.Execute(0);
			task.Execute(1);
			Assert::AreEqual(1, veve[0]);
			Assert::AreEqual(2, veve[1]);
		}

		TEST_METHOD(`)
		{
			// TODO: eXg R[hɑ}܂
			static CTaskManager task;
			class ct2 : public CTekitou2 < int, CExclusiveTaskBase >
			{
			public:
				ct2(int init) : CTekitou2 < int, CExclusiveTaskBase >(init)
				{

				}
				void Initialize()
				{
					task.AddTask(new CTekitou<int, CTaskBase>(hogehoge + 1));
				}
			};

			for (int i = 1; i < 257; i++)
			{
				task.AddTask(new ct2(i * 2));
				task.Execute(0);
			}
			veve.clear();
			task.RemoveTaskByID(1);
			for (int i = 0; i < 256; i++)
				task.Draw();

			Assert::AreEqual(513, veve[0]);
		}

		TEST_METHOD(^XN̈ˑ֌W)
		{
			// TODO: eXg R[hɑ}܂
			static CTaskManager task;
			class ct : public CTekitou2 < int, CExclusiveTaskBase >
			{
			public:
				ct(int init) : CTekitou2 < int, CExclusiveTaskBase >(init)
				{

				}
				void Initialize()
				{
					task.AddTask(new CTekitou2<int, CTaskBase>(hogehoge + 20));
				}
				virtual bool Inactivate(unsigned int nextTaskID){ return true; }//!< ̔r^XNJnƂɌĂ΂
			};

			veve.clear();
			auto ptr = task.AddTask(new ct(1));
			task.Execute(0);
			auto ptr2 = task.AddTask(new ct(3));
			task.Execute(1);
			Assert::AreEqual(1, veve[0]);
			Assert::AreEqual(1 + 20, veve[1]);
			task.Execute(2);
			Assert::AreEqual(3, veve[2]);
			Assert::AreEqual(3 + 20, veve[3]);
			task.RevertExclusiveTaskByID(1);
			task.Execute(3);
			Assert::AreEqual(1, veve[4]);
			Assert::AreEqual(1 + 20, veve[5]);
			ptr2 = task.AddTask(new ct(4));
			task.Execute(4);
			task.RemoveTaskByID(21);
			task.Execute(5);
			Assert::AreEqual(4, veve[8]);
			Assert::AreEqual(4 + 20, veve[9]);

		}

	};
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "n900lightsensor.h"
#include <QFile>
#include <QDebug>
#include <time.h>

const char *n900lightsensor::id("n900.ambientlight");
const char *n900lightsensor::filename("/sys/class/i2c-adapter/i2c-2/2-0029/lux");

n900lightsensor::n900lightsensor(QSensor *sensor)
    : n900filebasedsensor(sensor)
{
    setReading<QAmbientLightReading>(&m_reading);
    // Sensor takes 12-400ms to complete one reading and is triggered by
    // a read of the /sys file (no interrupt/timing loop/etc. is used).
    // Since no continuous operation is possible, don't set a data rate.
    //addDataRate(2, 2); // Approx 2Hz operation.
    setDescription(QLatin1String("tsl2563"));
}

void n900lightsensor::start()
{
    if (!QFile::exists(QLatin1String(filename)))
        goto error;

    n900filebasedsensor::start();
    return;

error:
    sensorStopped();
}

void n900lightsensor::poll()
{
    FILE *fd = fopen(filename, "r");
    if (!fd) return;
    int lux;
    int rs = fscanf(fd, "%i", &lux);
    fclose(fd);
    if (rs != 1) return;

    QAmbientLightReading::LightLevel lightLevel = QAmbientLightReading::Undefined;
    if (lux < 10)
        lightLevel = QAmbientLightReading::Dark;
    else if (lux < 50)
        lightLevel = QAmbientLightReading::Twilight;
    else if (lux < 100)
        lightLevel = QAmbientLightReading::Light;
    else if (lux < 150)
        lightLevel = QAmbientLightReading::Bright;
    else
        lightLevel = QAmbientLightReading::Sunny;

    m_reading.setTimestamp(clock());
    m_reading.setLightLevel(lightLevel);

    newReadingAvailable();
}

<commit_msg>Refactor the N900 light sensor.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "n900lightsensor.h"
#include <QFile>
#include <QDebug>
#include <time.h>

const char *n900lightsensor::id("n900.ambientlight");
const char *n900lightsensor::filename("/sys/class/i2c-adapter/i2c-2/2-0029/lux");

n900lightsensor::n900lightsensor(QSensor *sensor)
    : n900filebasedsensor(sensor)
{
    setReading<QAmbientLightReading>(&m_reading);
    // Sensor takes 12-400ms to complete one reading and is triggered by
    // a read of the /sys file (no interrupt/timing loop/etc. is used).
    // Since no continuous operation is possible, don't set a data rate.
    //addDataRate(2, 2); // Approx 2Hz operation.
    setDescription(QLatin1String("tsl2563"));
}

void n900lightsensor::start()
{
    if (!QFile::exists(QLatin1String(filename)))
        goto error;

    n900filebasedsensor::start();
    return;

error:
    sensorStopped();
}

struct lux_limit {
    int min;
    int max;
};

// Defines the min and max lux values that a given level has.
// These are used to add histeresis to the sensor.
// If the previous level is below a level, the lux must be at or above the minimum.
// If the previous level is above a level, the lux muyt be at or below the maximum.
static lux_limit limits[] = {
    { 0,    0    }, // Undefined (not used)
    { 0,    5    }, // Dark
    { 10,   50   }, // Twilight
    { 100,  200  }, // Light
    { 500,  2000 }, // Bright
    { 5000, 0    }  // Sunny
};

#if 0
// Used for debugging
static QString light_level(int level)
{
    switch (level) {
    case 1:
        return QLatin1String("Dark");
    case 2:
        return QLatin1String("Twilight");
    case 3:
        return QLatin1String("Light");
    case 4:
        return QLatin1String("Bright");
    case 5:
        return QLatin1String("Sunny");
    default:
        return QLatin1String("Undefined");
    }
}
#endif

void n900lightsensor::poll()
{
    FILE *fd = fopen(filename, "r");
    if (!fd) return;
    int lux;
    int rs = fscanf(fd, "%i", &lux);
    fclose(fd);
    if (rs != 1) return;

    // It's unweildly dealing with these constants so make some
    // local aliases that are shorter. This makes the code below
    // much easier to read.
    enum {
        Undefined = QAmbientLightReading::Undefined,
        Dark = QAmbientLightReading::Dark,
        Twilight = QAmbientLightReading::Twilight,
        Light = QAmbientLightReading::Light,
        Bright = QAmbientLightReading::Bright,
        Sunny = QAmbientLightReading::Sunny
    };

    int lightLevel = m_reading.lightLevel();
    // Check for change direction to allow for histeresis
    if      (lightLevel < Sunny    && lux >= limits[Sunny   ].min) lightLevel = Sunny;
    else if (lightLevel < Bright   && lux >= limits[Bright  ].min) lightLevel = Bright;
    else if (lightLevel < Light    && lux >= limits[Light   ].min) lightLevel = Light;
    else if (lightLevel < Twilight && lux >= limits[Twilight].min) lightLevel = Twilight;
    else if (lightLevel < Dark     && lux >= limits[Dark    ].min) lightLevel = Dark;
    else if (lightLevel > Dark     && lux <= limits[Dark    ].max) lightLevel = Dark;
    else if (lightLevel > Twilight && lux <= limits[Twilight].max) lightLevel = Twilight;
    else if (lightLevel > Light    && lux <= limits[Light   ].max) lightLevel = Light;
    else if (lightLevel > Bright   && lux <= limits[Bright  ].max) lightLevel = Bright;

    //qDebug() << "lightLevel" << light_level(lightLevel) << "lux" << lux;

    if (static_cast<int>(m_reading.lightLevel()) != lightLevel) {
        m_reading.setTimestamp(clock());
        m_reading.setLightLevel(static_cast<QAmbientLightReading::LightLevel>(lightLevel));

        newReadingAvailable();
    }
}

<|endoftext|>


<commit_before>/*
    Copyright (C) 1998, 1999 by Jorrit Tyberghein

    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; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "soundraw.h"

SCF_IMPLEMENT_IBASE(csSoundDataRaw);
  SCF_IMPLEMENTS_INTERFACE(iSoundData);
SCF_IMPLEMENT_IBASE_END;

csSoundDataRaw::csSoundDataRaw(iBase *p, void *d, long n, csSoundFormat f)
{
  SCF_CONSTRUCT_IBASE(p);
  Data = d;
  NumSamples = n;
  Format = f;
}

csSoundDataRaw::~csSoundDataRaw()
{
  unsigned char* const p = (unsigned char*)Data;
  delete[] p;
  SCF_DESTRUCT_IBASE();
}

const csSoundFormat *csSoundDataRaw::GetFormat()
{
  return &Format;
}

bool csSoundDataRaw::IsStatic()
{
  return true;
}

long csSoundDataRaw::GetStaticSampleCount()
{
  return NumSamples;
}

void *csSoundDataRaw::GetStaticData()
{
  return Data;
}

void csSoundDataRaw::ResetStreamed()
{
}

void *csSoundDataRaw::ReadStreamed(long &)
{
  return 0;
}

/*** format conversion functions follow ***/

#define REPLACE_DATA(x)				 \
{                        			 \
  unsigned char* const p = (unsigned char*)Data; \
  Data = x;                                      \
  delete[] p;                                    \
}

void *ConvertBuffer8To16Bit(void *buf, unsigned long Num)
{
  unsigned char *in=(unsigned char *)buf;
  short *out=new short[Num];
  for (unsigned long i=0;i<Num;i++)
  {
    out[i]=((short)in[i]-128)*256;
  }
  return out;
}

void *ConvertBuffer16To8Bit(void *buf, unsigned long Num)
{
  short *in=(short *)buf;
  unsigned char *out=new unsigned char[Num];
  for (unsigned long i=0;i<Num;i++)
  {
    out[i]=(in[i]/256)+128;
  }
  return out;
}

#define CONVERT_CHANNELS_TYPE(Type)		    \
{               				    \
  Type *OldData=(Type*)d;                           \
  if (newfmt->Channels==1)			    \
  {                        			    \
    Type *NewData=new Type[NumSamples];             \
    for (long i=0;i<NumSamples;i++)		    \
    {      					    \
      NewData[i]=(OldData[2*i]+OldData[2*i+1])/2;   \
    }                                               \
    return NewData;                                 \
  }						    \
  else						    \
  {                                          	    \
    Type *NewData=new Type[NumSamples*2];           \
    for (long i=0;i<NumSamples;i++)		    \
    {      					    \
      NewData[2*i]=NewData[2*i+1]=OldData[i];       \
    }                                               \
    return NewData;                                 \
  }                                                 \
}

void *ConvertChannels(void *d, const csSoundFormat *oldfmt,
  const csSoundFormat *newfmt, long NumSamples)
{
  if (oldfmt->Bits == 8)
  {
    CONVERT_CHANNELS_TYPE(unsigned char);
  }
  else
  {
    CONVERT_CHANNELS_TYPE(short);
  }
}

// @@@ ConvertFreq() : quality loss! Need to use a filter.

#define CONVERT_FREQ_TYPE(Type,Channels)			\
{                      						\
  Type *NewData=new Type[NewNumSamples*Channels];               \
  Type *OldData=(Type*)d;                                       \
  for (unsigned long i=0;i<NewNumSamples;i++)			\
  {                 						\
    int samppos = (int)(i/Factor);                              \
    if (Channels==1)						\
    {                                          			\
      NewData[i]=OldData[samppos];                              \
    }								\
    else							\
    {                                                    	\
      NewData[2*i]=OldData[2*samppos];                          \
      NewData[2*i+1]=OldData[2*samppos+1];                      \
    }                                                           \
  }                                                             \
  NumSamples = NewNumSamples;                                   \
  return NewData;                                               \
}

void *ConvertFreq(void *d, const csSoundFormat *oldfmt,
  const csSoundFormat *newfmt, long &NumSamples)
  {
  float Factor=newfmt->Freq/oldfmt->Freq;
  unsigned long NewNumSamples=(unsigned long)(NumSamples*Factor);
  if (oldfmt->Bits==16)
  {
    CONVERT_FREQ_TYPE(short,oldfmt->Channels);
  }
  else
  {
    CONVERT_FREQ_TYPE(unsigned char,oldfmt->Channels);
  }
}

bool csSoundDataRaw::Initialize(const csSoundFormat *RequestFormat)
{
  if (Format.Bits==16 && RequestFormat->Bits==8)
  {
    REPLACE_DATA(ConvertBuffer16To8Bit(Data, NumSamples * Format.Channels));
    Format.Bits = 8;
  }
  else if (Format.Bits==8 && RequestFormat->Bits==16)
  {
    REPLACE_DATA(ConvertBuffer8To16Bit(Data, NumSamples * Format.Channels));
    Format.Bits = 16;
  }

  if (Format.Channels != RequestFormat->Channels &&
      RequestFormat->Channels != -1)
  {
    REPLACE_DATA(ConvertChannels(Data, &Format, RequestFormat, NumSamples));
    Format.Channels = RequestFormat->Channels;
  }

  if (RequestFormat->Freq != Format.Freq && RequestFormat->Freq != -1)
  {
    REPLACE_DATA(ConvertFreq(Data, &Format, RequestFormat, NumSamples));
    Format.Freq = RequestFormat->Freq;
  }

  return true;
}
<commit_msg>In frequence conversion the scaling factor of float type was determined by dividing two integers. That couldn't play out well.<commit_after>/*
    Copyright (C) 1998, 1999 by Jorrit Tyberghein

    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; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "soundraw.h"

SCF_IMPLEMENT_IBASE(csSoundDataRaw);
  SCF_IMPLEMENTS_INTERFACE(iSoundData);
SCF_IMPLEMENT_IBASE_END;

csSoundDataRaw::csSoundDataRaw(iBase *p, void *d, long n, csSoundFormat f)
{
  SCF_CONSTRUCT_IBASE(p);
  Data = d;
  NumSamples = n;
  Format = f;
}

csSoundDataRaw::~csSoundDataRaw()
{
  unsigned char* const p = (unsigned char*)Data;
  delete[] p;
  SCF_DESTRUCT_IBASE();
}

const csSoundFormat *csSoundDataRaw::GetFormat()
{
  return &Format;
}

bool csSoundDataRaw::IsStatic()
{
  return true;
}

long csSoundDataRaw::GetStaticSampleCount()
{
  return NumSamples;
}

void *csSoundDataRaw::GetStaticData()
{
  return Data;
}

void csSoundDataRaw::ResetStreamed()
{
}

void *csSoundDataRaw::ReadStreamed(long &)
{
  return 0;
}

/*** format conversion functions follow ***/

#define REPLACE_DATA(x)				 \
{                        			 \
  unsigned char* const p = (unsigned char*)Data; \
  Data = x;                                      \
  delete[] p;                                    \
}

void *ConvertBuffer8To16Bit(void *buf, unsigned long Num)
{
  unsigned char *in=(unsigned char *)buf;
  short *out=new short[Num];
  for (unsigned long i=0;i<Num;i++)
  {
    out[i]=((short)in[i]-128)*256;
  }
  return out;
}

void *ConvertBuffer16To8Bit(void *buf, unsigned long Num)
{
  short *in=(short *)buf;
  unsigned char *out=new unsigned char[Num];
  for (unsigned long i=0;i<Num;i++)
  {
    out[i]=(in[i]/256)+128;
  }
  return out;
}

#define CONVERT_CHANNELS_TYPE(Type)		    \
{               				    \
  Type *OldData=(Type*)d;                           \
  if (newfmt->Channels==1)			    \
  {                        			    \
    Type *NewData=new Type[NumSamples];             \
    for (long i=0;i<NumSamples;i++)		    \
    {      					    \
      NewData[i]=(OldData[2*i]+OldData[2*i+1])/2;   \
    }                                               \
    return NewData;                                 \
  }						    \
  else						    \
  {                                          	    \
    Type *NewData=new Type[NumSamples*2];           \
    for (long i=0;i<NumSamples;i++)		    \
    {      					    \
      NewData[2*i]=NewData[2*i+1]=OldData[i];       \
    }                                               \
    return NewData;                                 \
  }                                                 \
}

void *ConvertChannels(void *d, const csSoundFormat *oldfmt,
  const csSoundFormat *newfmt, long NumSamples)
{
  if (oldfmt->Bits == 8)
  {
    CONVERT_CHANNELS_TYPE(unsigned char);
  }
  else
  {
    CONVERT_CHANNELS_TYPE(short);
  }
}

// @@@ ConvertFreq() : quality loss! Need to use a filter.

#define CONVERT_FREQ_TYPE(Type,Channels)			\
{                      						\
  Type *NewData=new Type[NewNumSamples*Channels];               \
  Type *OldData=(Type*)d;                                       \
  for (unsigned long i=0;i<NewNumSamples;i++)			\
  {                 						\
    int samppos = (int)(i/Factor);                              \
    if (Channels==1)						\
    {                                          			\
      NewData[i]=OldData[samppos];                              \
    }								\
    else							\
    {                                                    	\
      NewData[2*i]=OldData[2*samppos];                          \
      NewData[2*i+1]=OldData[2*samppos+1];                      \
    }                                                           \
  }                                                             \
  NumSamples = NewNumSamples;                                   \
  return NewData;                                               \
}

void *ConvertFreq(void *d, const csSoundFormat *oldfmt,
  const csSoundFormat *newfmt, long &NumSamples)
  {
  float Factor=newfmt->Freq/(float)oldfmt->Freq;
  unsigned long NewNumSamples=(unsigned long)(NumSamples*Factor);

  if (oldfmt->Bits==16)
  {
    CONVERT_FREQ_TYPE(short,oldfmt->Channels);
  }
  else
  {
    CONVERT_FREQ_TYPE(unsigned char,oldfmt->Channels);
  }
}

bool csSoundDataRaw::Initialize(const csSoundFormat *RequestFormat)
{
  if (Format.Bits==16 && RequestFormat->Bits==8)
  {
    REPLACE_DATA(ConvertBuffer16To8Bit(Data, NumSamples * Format.Channels));
    Format.Bits = 8;
  }
  else if (Format.Bits==8 && RequestFormat->Bits==16)
  {
    REPLACE_DATA(ConvertBuffer8To16Bit(Data, NumSamples * Format.Channels));
    Format.Bits = 16;
  }

  if (Format.Channels != RequestFormat->Channels &&
      RequestFormat->Channels != -1)
  {
    REPLACE_DATA(ConvertChannels(Data, &Format, RequestFormat, NumSamples));
    Format.Channels = RequestFormat->Channels;
  }

  if (RequestFormat->Freq != Format.Freq && RequestFormat->Freq != -1)
  {
    REPLACE_DATA(ConvertFreq(Data, &Format, RequestFormat, NumSamples));
    Format.Freq = RequestFormat->Freq;
  }

  return true;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer)
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */
#ifndef _STARMATHIMPORTUTILS_HXX
#define _STARMATHIMPORTUTILS_HXX

#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
#include <oox/token/tokens.hxx>
#include <map>
#include <vector>

#include <oox/dllapi.h>

namespace oox
{

namespace formulaimport
{

const int TAG_OPENING = 1 << 29;
const int TAG_CLOSING = 1 << 30;

// used to differentiate between tags that open or close
// TODO
//inline int OPENING( int token ) { return TAG_OPENING | token; }
//inline int CLOSING( int token ) { return TAG_CLOSING | token; }
#define OPENING( token ) ( TAG_OPENING | token )
#define CLOSING( token ) ( TAG_CLOSING | token )

/**
 Class for storing a stream of xml tokens.

 A part of an XML file can be parsed and stored in this stream, from which it can be read
 as if parsed linearly. The purpose of this class is to allow simpler handling of XML
 files, unlike the usual LO way of using callbacks, context handlers and similar needlesly
 complicated stuff (YMMV).

 @since 3.5.0
*/
class OOX_DLLPUBLIC XmlStream
{
public:
    XmlStream();
    /**
     Structure representing a list of attributes.
    */
    // One could theoretically use oox::AttributeList, but that complains if the passed reference is empty,
    // which would be complicated to avoid here. Also, parsers apparently reuse the same instance of XFastAttributeList,
    // which means using oox::AttributeList would make them all point to the one instance.
    struct AttributeList
    {
        bool hasAttribute( int token ) const;
        rtl::OUString attribute( int token, const rtl::OUString& def = rtl::OUString()) const;
        bool attribute( int token, bool def ) const;
    protected:
        std::map< int, rtl::OUString > attrs;
    };
    /**
     Structure representing a tag, including its attributes and content text immediatelly following it.
    */
    struct Tag
    {
        Tag( int token = XML_TOKEN_INVALID,
            const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& attributes = com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >(),
            const rtl::OUString& text = rtl::OUString());
        int token; ///< tag type, or XML_TOKEN_INVALID
        AttributeList attributes;
        rtl::OUString text;
        /**
         Converts to true if the tag has a valid token, false otherwise. Allows simple
         usage in if(), for example 'if( XmlStream::Tag foo = stream.checkOpeningTag( footoken ))'.
        */
        operator bool() const;
    };
    /**
     @return true if current position is at the end of the XML stream
    */
    bool atEnd() const;
    /**
     @return data about the current tag
    */
    Tag currentTag() const;
    /**
     @return the token for the current tag
    */
    int currentToken() const;
    /**
     Moves position to the next tag.
    */
    void moveToNextTag();
    /**
     Ensures that an opening tag with the given token is read. If the current tag does not match,
     writes out a warning and tries to recover by skipping tags until found (or until the current element would end).
     If found, the position in the stream is afterwards moved to the next tag.
     @return the matching found opening tag, or empty tag if not found
    */
    Tag ensureOpeningTag( int token );
    /**
     Tries to find an opening tag with the given token. Works similarly like ensureOpeningTag(),
     but if a matching tag is not found, the position in the stream is not altered. The primary
     use of this function is to check for optional elements.
     @return the matching found opening tag, or empty tag if not found
    */
    Tag checkOpeningTag( int token );
    /**
     Ensures that a closing tag with the given token is read. Like ensureOpeningTag(),
     if not, writes out a warning and tries to recover by skiping tags until found (or until the current element would end).
     If found, the position in the stream is afterwards moved to the next tag.
    */
    void ensureClosingTag( int token );
    /**
     Tries to find the given token, until either found (returns true) or end of current element.
     Position in the stream is set to make the tag current.
    */
    bool recoverAndFindTag( int token );
    /**
     Skips the given element (i.e. reads up to and including the matching closing tag).
    */
    void skipElement( int token );
    /**
     Handle the current (unexpected) tag.
    */
    void handleUnexpectedTag();
protected:
    Tag checkTag( int token, bool optional, const char* txt );
    std::vector< Tag > tags;
    unsigned int pos;
};

/**
 This class is used for creating XmlStream.

 Simply use this class and then pass it as XmlStream to the consumer.

 @since 3.5.0
*/
class OOX_DLLPUBLIC XmlStreamBuilder
: public XmlStream
{
public:
    void appendOpeningTag( int token,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& attributes );
    void appendClosingTag( int token );
    // appends the characters after the last appended token
    void appendCharacters( const rtl::OUString& characters );
};

} // namespace
} // namespace

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Fix visibility problem on Windows.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer)
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */
#ifndef _STARMATHIMPORTUTILS_HXX
#define _STARMATHIMPORTUTILS_HXX

#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
#include <oox/token/tokens.hxx>
#include <map>
#include <vector>

#include <oox/dllapi.h>

namespace oox
{

namespace formulaimport
{

const int TAG_OPENING = 1 << 29;
const int TAG_CLOSING = 1 << 30;

// used to differentiate between tags that open or close
// TODO
//inline int OPENING( int token ) { return TAG_OPENING | token; }
//inline int CLOSING( int token ) { return TAG_CLOSING | token; }
#define OPENING( token ) ( TAG_OPENING | token )
#define CLOSING( token ) ( TAG_CLOSING | token )

/**
 Class for storing a stream of xml tokens.

 A part of an XML file can be parsed and stored in this stream, from which it can be read
 as if parsed linearly. The purpose of this class is to allow simpler handling of XML
 files, unlike the usual LO way of using callbacks, context handlers and similar needlesly
 complicated stuff (YMMV).

 @since 3.5.0
*/
class OOX_DLLPUBLIC XmlStream
{
public:
    XmlStream();
    /**
     Structure representing a list of attributes.
    */
    // One could theoretically use oox::AttributeList, but that complains if the passed reference is empty,
    // which would be complicated to avoid here. Also, parsers apparently reuse the same instance of XFastAttributeList,
    // which means using oox::AttributeList would make them all point to the one instance.
    struct OOX_DLLPUBLIC AttributeList
    {
        bool hasAttribute( int token ) const;
        rtl::OUString attribute( int token, const rtl::OUString& def = rtl::OUString()) const;
        bool attribute( int token, bool def ) const;
    protected:
        std::map< int, rtl::OUString > attrs;
    };
    /**
     Structure representing a tag, including its attributes and content text immediatelly following it.
    */
    struct OOX_DLLPUBLIC Tag
    {
        Tag( int token = XML_TOKEN_INVALID,
            const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& attributes = com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >(),
            const rtl::OUString& text = rtl::OUString());
        int token; ///< tag type, or XML_TOKEN_INVALID
        AttributeList attributes;
        rtl::OUString text;
        /**
         Converts to true if the tag has a valid token, false otherwise. Allows simple
         usage in if(), for example 'if( XmlStream::Tag foo = stream.checkOpeningTag( footoken ))'.
        */
        operator bool() const;
    };
    /**
     @return true if current position is at the end of the XML stream
    */
    bool atEnd() const;
    /**
     @return data about the current tag
    */
    Tag currentTag() const;
    /**
     @return the token for the current tag
    */
    int currentToken() const;
    /**
     Moves position to the next tag.
    */
    void moveToNextTag();
    /**
     Ensures that an opening tag with the given token is read. If the current tag does not match,
     writes out a warning and tries to recover by skipping tags until found (or until the current element would end).
     If found, the position in the stream is afterwards moved to the next tag.
     @return the matching found opening tag, or empty tag if not found
    */
    Tag ensureOpeningTag( int token );
    /**
     Tries to find an opening tag with the given token. Works similarly like ensureOpeningTag(),
     but if a matching tag is not found, the position in the stream is not altered. The primary
     use of this function is to check for optional elements.
     @return the matching found opening tag, or empty tag if not found
    */
    Tag checkOpeningTag( int token );
    /**
     Ensures that a closing tag with the given token is read. Like ensureOpeningTag(),
     if not, writes out a warning and tries to recover by skiping tags until found (or until the current element would end).
     If found, the position in the stream is afterwards moved to the next tag.
    */
    void ensureClosingTag( int token );
    /**
     Tries to find the given token, until either found (returns true) or end of current element.
     Position in the stream is set to make the tag current.
    */
    bool recoverAndFindTag( int token );
    /**
     Skips the given element (i.e. reads up to and including the matching closing tag).
    */
    void skipElement( int token );
    /**
     Handle the current (unexpected) tag.
    */
    void handleUnexpectedTag();
protected:
    Tag checkTag( int token, bool optional, const char* txt );
    std::vector< Tag > tags;
    unsigned int pos;
};

/**
 This class is used for creating XmlStream.

 Simply use this class and then pass it as XmlStream to the consumer.

 @since 3.5.0
*/
class OOX_DLLPUBLIC XmlStreamBuilder
: public XmlStream
{
public:
    void appendOpeningTag( int token,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XFastAttributeList >& attributes );
    void appendClosingTag( int token );
    // appends the characters after the last appended token
    void appendCharacters( const rtl::OUString& characters );
};

} // namespace
} // namespace

#endif

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


<commit_before>/*************************************************************************
 *
 *  $RCSfile: gsub.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2004-03-17 10:49:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

extern "C"
{
#include "sft.h"
#undef true
#undef false

#include "gsub.h"
}

#include <vector>
#include <map>
#include <algorithm>

typedef sal_uInt32 ULONG;
typedef sal_uInt16 USHORT;
typedef sal_uInt8 FT_Byte;

typedef std::map<USHORT,USHORT> GlyphSubstitution;

inline long NEXT_Long( const unsigned char* &p )
{
    long nVal = (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
    p += 4;
    return nVal;
}

inline USHORT NEXT_UShort( const unsigned char* &p )
{
    USHORT nVal = (p[0]<<8) + p[1];
    p += 2;
    return nVal;
}

#define MKTAG(s) ((((((s[0]<<8)+s[1])<<8)+s[2])<<8)+s[3])

int ReadGSUB( struct _TrueTypeFont* pTTFile, unsigned char* pGsubBase,
              int nRequestedScript, int nRequestedLangsys )
{
    if( !pGsubBase )
        return -1;

    // parse GSUB header
    const FT_Byte* pGsubHeader = pGsubBase;
    const ULONG nVersion            = NEXT_Long( pGsubHeader );
    const USHORT nOfsScriptList     = NEXT_UShort( pGsubHeader );
    const USHORT nOfsFeatureTable   = NEXT_UShort( pGsubHeader );
    const USHORT nOfsLookupList     = NEXT_UShort( pGsubHeader );

    // sanity check the GSUB header
    if( nVersion != 0x00010000 )
        if( nVersion != 0x00001000 )    // workaround for SunBatang etc.
            return -1;                  // unknown format or broken

    typedef std::vector<ULONG> ReqFeatureTagList;
    ReqFeatureTagList aReqFeatureTagList;

    aReqFeatureTagList.push_back( MKTAG("vert") );

    typedef std::vector<USHORT> UshortList;
    UshortList aFeatureIndexList;
    UshortList aFeatureOffsetList;

    // parse Script Table
    const FT_Byte* pScriptHeader = pGsubBase + nOfsScriptList;
    const USHORT nCntScript = NEXT_UShort( pScriptHeader );
    for( USHORT nScriptIndex = 0; nScriptIndex < nCntScript; ++nScriptIndex )
    {
        const ULONG nTag            = NEXT_Long( pScriptHeader ); // e.g. hani/arab/kana/hang
        const USHORT nOfsScriptTable= NEXT_UShort( pScriptHeader );
        if( (nTag != (USHORT)nRequestedScript) && (nRequestedScript != 0) )
            continue;

        const FT_Byte* pScriptTable     = pGsubBase + nOfsScriptList + nOfsScriptTable;
        const USHORT nDefaultLangsysOfs = NEXT_UShort( pScriptTable );
        const USHORT nCntLangSystem     = NEXT_UShort( pScriptTable );
        USHORT nLangsysOffset = 0;
        for( USHORT nLangsysIndex = 0; nLangsysIndex < nCntLangSystem; ++nLangsysIndex )
        {
            const ULONG nTag    = NEXT_Long( pScriptTable );    // e.g. KOR/ZHS/ZHT/JAN
            const USHORT nOffset= NEXT_UShort( pScriptTable );
            if( (nTag != (USHORT)nRequestedLangsys) && (nRequestedLangsys != 0) )
                continue;
            nLangsysOffset = nOffset;
            break;
        }

        if( (nDefaultLangsysOfs != 0) && (nDefaultLangsysOfs != nLangsysOffset) )
        {
            const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nDefaultLangsysOfs;
            /*const USHORT nLookupOrder   =*/ NEXT_UShort( pLangSys );
            const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
            const USHORT nCntFeature    = NEXT_UShort( pLangSys );
            aFeatureIndexList.push_back( nReqFeatureIdx );
            for( USHORT i = 0; i < nCntFeature; ++i )
            {
                const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
                aFeatureIndexList.push_back( nFeatureIndex );
            }
        }

        if( nLangsysOffset != 0 )
        {
            const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nLangsysOffset;
            /*const USHORT nLookupOrder   =*/ NEXT_UShort( pLangSys );
            const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
            const USHORT nCntFeature    = NEXT_UShort( pLangSys );
            aFeatureIndexList.push_back( nReqFeatureIdx );
            for( USHORT i = 0; i < nCntFeature; ++i )
            {
                const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
                aFeatureIndexList.push_back( nFeatureIndex );
            }
        }
    }

    if( !aFeatureIndexList.size() )
        return true;

    UshortList aLookupIndexList;
    UshortList aLookupOffsetList;

    // parse Feature Table
    const FT_Byte* pFeatureHeader = pGsubBase + nOfsFeatureTable;
    const USHORT nCntFeature = NEXT_UShort( pFeatureHeader );
    for( USHORT nFeatureIndex = 0; nFeatureIndex < nCntFeature; ++nFeatureIndex )
    {
        const ULONG nTag    = NEXT_Long( pFeatureHeader ); // e.g. locl/vert/trad/smpl/liga/fina/...
        const USHORT nOffset= NEXT_UShort( pFeatureHeader );

        // feature (required && (requested || available))?
        if( (aFeatureIndexList[0] != nFeatureIndex)
            &&  (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag))
            ||  (!std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex) ) )
            continue;

        const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset;
        const USHORT nCntLookups = NEXT_UShort( pFeatureTable );
        for( USHORT i = 0; i < nCntLookups; ++i )
        {
            const USHORT nLookupIndex = NEXT_UShort( pFeatureTable );
            aLookupIndexList.push_back( nLookupIndex );
        }
        if( nCntLookups == 0 ) //### hack needed by Mincho/Gothic/Mingliu/Simsun/...
            aLookupIndexList.push_back( 0 );
    }

    // parse Lookup List
    const FT_Byte* pLookupHeader = pGsubBase + nOfsLookupList;
    const USHORT nCntLookupTable = NEXT_UShort( pLookupHeader );
    for( USHORT nLookupIdx = 0; nLookupIdx < nCntLookupTable; ++nLookupIdx )
    {
        const USHORT nOffset = NEXT_UShort( pLookupHeader );
        if( std::count( aLookupIndexList.begin(), aLookupIndexList.end(), nLookupIdx ) )
            aLookupOffsetList.push_back( nOffset );
    }

    UshortList::const_iterator it = aLookupOffsetList.begin();
    for(; it != aLookupOffsetList.end(); ++it )
    {
        const USHORT nOfsLookupTable = *it;
        const FT_Byte* pLookupTable = pGsubBase + nOfsLookupList + nOfsLookupTable;
        const USHORT eLookupType        = NEXT_UShort( pLookupTable );
        /*const USHORT eLookupFlag        =*/ NEXT_UShort( pLookupTable );
        const USHORT nCntLookupSubtable = NEXT_UShort( pLookupTable );

        // TODO: switch( eLookupType )
        if( eLookupType != 1 )  // TODO: once we go beyond SingleSubst
            continue;

        for( USHORT nSubTableIdx = 0; nSubTableIdx < nCntLookupSubtable; ++nSubTableIdx )
        {
            const USHORT nOfsSubLookupTable = NEXT_UShort( pLookupTable );
            const FT_Byte* pSubLookup = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable;

            const USHORT nFmtSubstitution   = NEXT_UShort( pSubLookup );
            const USHORT nOfsCoverage       = NEXT_UShort( pSubLookup );

            typedef std::pair<USHORT,USHORT> GlyphSubst;
            typedef std::vector<GlyphSubst> SubstVector;
            SubstVector aSubstVector;

            const FT_Byte* pCoverage    = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable + nOfsCoverage;
            const USHORT nFmtCoverage   = NEXT_UShort( pCoverage );
            switch( nFmtCoverage )
            {
                case 1:         // Coverage Format 1
                {
                    const USHORT nCntGlyph = NEXT_UShort( pCoverage );
                    aSubstVector.reserve( nCntGlyph );
                    for( USHORT i = 0; i < nCntGlyph; ++i )
                    {
                        const USHORT nGlyphId = NEXT_UShort( pCoverage );
                        aSubstVector.push_back( GlyphSubst( nGlyphId, 0 ) );
                    }
                }
                break;

                case 2:         // Coverage Format 2
                {
                    const USHORT nCntRange = NEXT_UShort( pCoverage );
                    for( int i = nCntRange; --i >= 0; )
                    {
                        const USHORT nGlyph0 = NEXT_UShort( pCoverage );
                        const USHORT nGlyph1 = NEXT_UShort( pCoverage );
                        const USHORT nCovIdx = NEXT_UShort( pCoverage );
                        for( USHORT j = nGlyph0; j <= nGlyph1; ++j )
                            aSubstVector.push_back( GlyphSubst( j + nCovIdx, 0 ) );
                    }
                }
                break;
            }

            SubstVector::iterator it( aSubstVector.begin() );

            switch( nFmtSubstitution )
            {
                case 1:     // Single Substitution Format 1
                {
                    const USHORT nDeltaGlyphId = NEXT_UShort( pSubLookup );

                    for(; it != aSubstVector.end(); ++it )
                        (*it).second = (*it).first + nDeltaGlyphId;
                }
                break;

                case 2:     // Single Substitution Format 2
                {
                    const USHORT nCntGlyph = NEXT_UShort( pSubLookup );
                    for( int i = nCntGlyph; (it != aSubstVector.end()) && (--i>=0); ++it )
                    {
                        const USHORT nGlyphId = NEXT_UShort( pSubLookup );
                        (*it).second = nGlyphId;
                    }
                }
                break;
            }

            // now apply the glyph substitutions that have been collected in this subtable
            if( aSubstVector.size() > 0 )
            {
                GlyphSubstitution* pGSubstitution = new GlyphSubstitution;
                pTTFile->pGSubstitution = (void*)pGSubstitution;
                for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it )
                    (*pGSubstitution)[ (*it).first ] =  (*it).second;
            }
        }
    }

    return true;
}

int UseGSUB( struct _TrueTypeFont* pTTFile, int nGlyph, int wmode )
{
    GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution;
    if( pGlyphSubstitution != 0 )
    {
        GlyphSubstitution::const_iterator it( pGlyphSubstitution->find( nGlyph ) );
        if( it != pGlyphSubstitution->end() )
            nGlyph = (*it).second;
    }

    return nGlyph;
}

int HasVerticalGSUB( struct _TrueTypeFont* pTTFile )
{
    GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution;
    return pGlyphSubstitution ? +1 : 0;
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.88); FILE MERGED 2005/09/05 12:06:36 rt 1.6.88.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gsub.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:38:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

extern "C"
{
#include "sft.h"
#undef true
#undef false

#include "gsub.h"
}

#include <vector>
#include <map>
#include <algorithm>

typedef sal_uInt32 ULONG;
typedef sal_uInt16 USHORT;
typedef sal_uInt8 FT_Byte;

typedef std::map<USHORT,USHORT> GlyphSubstitution;

inline long NEXT_Long( const unsigned char* &p )
{
    long nVal = (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
    p += 4;
    return nVal;
}

inline USHORT NEXT_UShort( const unsigned char* &p )
{
    USHORT nVal = (p[0]<<8) + p[1];
    p += 2;
    return nVal;
}

#define MKTAG(s) ((((((s[0]<<8)+s[1])<<8)+s[2])<<8)+s[3])

int ReadGSUB( struct _TrueTypeFont* pTTFile, unsigned char* pGsubBase,
              int nRequestedScript, int nRequestedLangsys )
{
    if( !pGsubBase )
        return -1;

    // parse GSUB header
    const FT_Byte* pGsubHeader = pGsubBase;
    const ULONG nVersion            = NEXT_Long( pGsubHeader );
    const USHORT nOfsScriptList     = NEXT_UShort( pGsubHeader );
    const USHORT nOfsFeatureTable   = NEXT_UShort( pGsubHeader );
    const USHORT nOfsLookupList     = NEXT_UShort( pGsubHeader );

    // sanity check the GSUB header
    if( nVersion != 0x00010000 )
        if( nVersion != 0x00001000 )    // workaround for SunBatang etc.
            return -1;                  // unknown format or broken

    typedef std::vector<ULONG> ReqFeatureTagList;
    ReqFeatureTagList aReqFeatureTagList;

    aReqFeatureTagList.push_back( MKTAG("vert") );

    typedef std::vector<USHORT> UshortList;
    UshortList aFeatureIndexList;
    UshortList aFeatureOffsetList;

    // parse Script Table
    const FT_Byte* pScriptHeader = pGsubBase + nOfsScriptList;
    const USHORT nCntScript = NEXT_UShort( pScriptHeader );
    for( USHORT nScriptIndex = 0; nScriptIndex < nCntScript; ++nScriptIndex )
    {
        const ULONG nTag            = NEXT_Long( pScriptHeader ); // e.g. hani/arab/kana/hang
        const USHORT nOfsScriptTable= NEXT_UShort( pScriptHeader );
        if( (nTag != (USHORT)nRequestedScript) && (nRequestedScript != 0) )
            continue;

        const FT_Byte* pScriptTable     = pGsubBase + nOfsScriptList + nOfsScriptTable;
        const USHORT nDefaultLangsysOfs = NEXT_UShort( pScriptTable );
        const USHORT nCntLangSystem     = NEXT_UShort( pScriptTable );
        USHORT nLangsysOffset = 0;
        for( USHORT nLangsysIndex = 0; nLangsysIndex < nCntLangSystem; ++nLangsysIndex )
        {
            const ULONG nTag    = NEXT_Long( pScriptTable );    // e.g. KOR/ZHS/ZHT/JAN
            const USHORT nOffset= NEXT_UShort( pScriptTable );
            if( (nTag != (USHORT)nRequestedLangsys) && (nRequestedLangsys != 0) )
                continue;
            nLangsysOffset = nOffset;
            break;
        }

        if( (nDefaultLangsysOfs != 0) && (nDefaultLangsysOfs != nLangsysOffset) )
        {
            const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nDefaultLangsysOfs;
            /*const USHORT nLookupOrder   =*/ NEXT_UShort( pLangSys );
            const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
            const USHORT nCntFeature    = NEXT_UShort( pLangSys );
            aFeatureIndexList.push_back( nReqFeatureIdx );
            for( USHORT i = 0; i < nCntFeature; ++i )
            {
                const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
                aFeatureIndexList.push_back( nFeatureIndex );
            }
        }

        if( nLangsysOffset != 0 )
        {
            const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nLangsysOffset;
            /*const USHORT nLookupOrder   =*/ NEXT_UShort( pLangSys );
            const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
            const USHORT nCntFeature    = NEXT_UShort( pLangSys );
            aFeatureIndexList.push_back( nReqFeatureIdx );
            for( USHORT i = 0; i < nCntFeature; ++i )
            {
                const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
                aFeatureIndexList.push_back( nFeatureIndex );
            }
        }
    }

    if( !aFeatureIndexList.size() )
        return true;

    UshortList aLookupIndexList;
    UshortList aLookupOffsetList;

    // parse Feature Table
    const FT_Byte* pFeatureHeader = pGsubBase + nOfsFeatureTable;
    const USHORT nCntFeature = NEXT_UShort( pFeatureHeader );
    for( USHORT nFeatureIndex = 0; nFeatureIndex < nCntFeature; ++nFeatureIndex )
    {
        const ULONG nTag    = NEXT_Long( pFeatureHeader ); // e.g. locl/vert/trad/smpl/liga/fina/...
        const USHORT nOffset= NEXT_UShort( pFeatureHeader );

        // feature (required && (requested || available))?
        if( (aFeatureIndexList[0] != nFeatureIndex)
            &&  (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag))
            ||  (!std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex) ) )
            continue;

        const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset;
        const USHORT nCntLookups = NEXT_UShort( pFeatureTable );
        for( USHORT i = 0; i < nCntLookups; ++i )
        {
            const USHORT nLookupIndex = NEXT_UShort( pFeatureTable );
            aLookupIndexList.push_back( nLookupIndex );
        }
        if( nCntLookups == 0 ) //### hack needed by Mincho/Gothic/Mingliu/Simsun/...
            aLookupIndexList.push_back( 0 );
    }

    // parse Lookup List
    const FT_Byte* pLookupHeader = pGsubBase + nOfsLookupList;
    const USHORT nCntLookupTable = NEXT_UShort( pLookupHeader );
    for( USHORT nLookupIdx = 0; nLookupIdx < nCntLookupTable; ++nLookupIdx )
    {
        const USHORT nOffset = NEXT_UShort( pLookupHeader );
        if( std::count( aLookupIndexList.begin(), aLookupIndexList.end(), nLookupIdx ) )
            aLookupOffsetList.push_back( nOffset );
    }

    UshortList::const_iterator it = aLookupOffsetList.begin();
    for(; it != aLookupOffsetList.end(); ++it )
    {
        const USHORT nOfsLookupTable = *it;
        const FT_Byte* pLookupTable = pGsubBase + nOfsLookupList + nOfsLookupTable;
        const USHORT eLookupType        = NEXT_UShort( pLookupTable );
        /*const USHORT eLookupFlag        =*/ NEXT_UShort( pLookupTable );
        const USHORT nCntLookupSubtable = NEXT_UShort( pLookupTable );

        // TODO: switch( eLookupType )
        if( eLookupType != 1 )  // TODO: once we go beyond SingleSubst
            continue;

        for( USHORT nSubTableIdx = 0; nSubTableIdx < nCntLookupSubtable; ++nSubTableIdx )
        {
            const USHORT nOfsSubLookupTable = NEXT_UShort( pLookupTable );
            const FT_Byte* pSubLookup = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable;

            const USHORT nFmtSubstitution   = NEXT_UShort( pSubLookup );
            const USHORT nOfsCoverage       = NEXT_UShort( pSubLookup );

            typedef std::pair<USHORT,USHORT> GlyphSubst;
            typedef std::vector<GlyphSubst> SubstVector;
            SubstVector aSubstVector;

            const FT_Byte* pCoverage    = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable + nOfsCoverage;
            const USHORT nFmtCoverage   = NEXT_UShort( pCoverage );
            switch( nFmtCoverage )
            {
                case 1:         // Coverage Format 1
                {
                    const USHORT nCntGlyph = NEXT_UShort( pCoverage );
                    aSubstVector.reserve( nCntGlyph );
                    for( USHORT i = 0; i < nCntGlyph; ++i )
                    {
                        const USHORT nGlyphId = NEXT_UShort( pCoverage );
                        aSubstVector.push_back( GlyphSubst( nGlyphId, 0 ) );
                    }
                }
                break;

                case 2:         // Coverage Format 2
                {
                    const USHORT nCntRange = NEXT_UShort( pCoverage );
                    for( int i = nCntRange; --i >= 0; )
                    {
                        const USHORT nGlyph0 = NEXT_UShort( pCoverage );
                        const USHORT nGlyph1 = NEXT_UShort( pCoverage );
                        const USHORT nCovIdx = NEXT_UShort( pCoverage );
                        for( USHORT j = nGlyph0; j <= nGlyph1; ++j )
                            aSubstVector.push_back( GlyphSubst( j + nCovIdx, 0 ) );
                    }
                }
                break;
            }

            SubstVector::iterator it( aSubstVector.begin() );

            switch( nFmtSubstitution )
            {
                case 1:     // Single Substitution Format 1
                {
                    const USHORT nDeltaGlyphId = NEXT_UShort( pSubLookup );

                    for(; it != aSubstVector.end(); ++it )
                        (*it).second = (*it).first + nDeltaGlyphId;
                }
                break;

                case 2:     // Single Substitution Format 2
                {
                    const USHORT nCntGlyph = NEXT_UShort( pSubLookup );
                    for( int i = nCntGlyph; (it != aSubstVector.end()) && (--i>=0); ++it )
                    {
                        const USHORT nGlyphId = NEXT_UShort( pSubLookup );
                        (*it).second = nGlyphId;
                    }
                }
                break;
            }

            // now apply the glyph substitutions that have been collected in this subtable
            if( aSubstVector.size() > 0 )
            {
                GlyphSubstitution* pGSubstitution = new GlyphSubstitution;
                pTTFile->pGSubstitution = (void*)pGSubstitution;
                for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it )
                    (*pGSubstitution)[ (*it).first ] =  (*it).second;
            }
        }
    }

    return true;
}

int UseGSUB( struct _TrueTypeFont* pTTFile, int nGlyph, int wmode )
{
    GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution;
    if( pGlyphSubstitution != 0 )
    {
        GlyphSubstitution::const_iterator it( pGlyphSubstitution->find( nGlyph ) );
        if( it != pGlyphSubstitution->end() )
            nGlyph = (*it).second;
    }

    return nGlyph;
}

int HasVerticalGSUB( struct _TrueTypeFont* pTTFile )
{
    GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution;
    return pGlyphSubstitution ? +1 : 0;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "<WebSig>" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Institute for
 * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
 * The development of this software was partly funded by the European
 * Commission in the <WebSig> project in the ISIS Programme.
 * For more information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * XSEC
 *
 * DSIGTransformBase64 := Class that holds a Base64 transform structure
 *
 * $Id$
 *
 */

// XSEC

#include <xsec/dsig/DSIGTransformBase64.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMXPath.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/framework/XSECError.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Constructors and Destructors
// --------------------------------------------------------------------------------

DSIGTransformBase64::DSIGTransformBase64(const XSECEnv * env, DOMNode * node) :
DSIGTransform(env, node) {};

DSIGTransformBase64::DSIGTransformBase64(const XSECEnv * env) :
DSIGTransform(env) {};

DSIGTransformBase64::~DSIGTransformBase64() {};

// --------------------------------------------------------------------------------
//           Interface Methods
// --------------------------------------------------------------------------------

transformType DSIGTransformBase64::getTransformType() {

	return TRANSFORM_BASE64;

}

void DSIGTransformBase64::appendTransformer(TXFMChain * input) {

	// If the input is a Nodeset then we need to find the text from the input

	if (input->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {

		if (input->getLastTxfm()->getNodeType() != TXFMBase::DOM_NODE_XPATH_NODESET) {

#ifdef XSEC_NO_XPATH

			throw XSECException(XSECException::UnsupportedFunction,
				"Unable to extract Base64 text from Nodes without XPath support");

#else

			// Use an XPath transform to get "Self::text()" from the nodeset

			TXFMXPath *x;

			XSECnew(x, TXFMXPath(mp_txfmNode->getOwnerDocument()));
			input->appendTxfm(x);
			((TXFMXPath *) x)->evaluateExpr(mp_txfmNode, "self::text()");

		}

		TXFMC14n *c;

		// Now use c14n to translate to BYTES

		XSECnew(c, TXFMC14n(mp_txfmNode->getOwnerDocument()));
		input->appendTxfm(c);
#endif

	}

	// Now the actual Base64

	TXFMBase64 *b;
	XSECnew(b, TXFMBase64(mp_txfmNode->getOwnerDocument()));
	input->appendTxfm(b);

}

DOMElement * DSIGTransformBase64::createBlankTransform(DOMDocument * parentDoc) {

	safeBuffer str;
	const XMLCh * prefix;
	DOMElement *ret;
	DOMDocument *doc = mp_env->getParentDocument();

	prefix = mp_env->getDSIGNSPrefix();

	// Create the transform node
	makeQName(str, prefix, "Transform");
	ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	ret->setAttribute(DSIGConstants::s_unicodeStrAlgorithm, DSIGConstants::s_unicodeStrURIBASE64);

	mp_txfmNode = ret;

	return ret;

}

void DSIGTransformBase64::load(void) {

	// Do nothing for a Base64 transform

}
<commit_msg>Mismatches parentheses when building without Xalan<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "<WebSig>" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Institute for
 * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
 * The development of this software was partly funded by the European
 * Commission in the <WebSig> project in the ISIS Programme.
 * For more information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * XSEC
 *
 * DSIGTransformBase64 := Class that holds a Base64 transform structure
 *
 * $Id$
 *
 */

// XSEC

#include <xsec/dsig/DSIGTransformBase64.hpp>
#include <xsec/dsig/DSIGSignature.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMXPath.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/framework/XSECError.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Constructors and Destructors
// --------------------------------------------------------------------------------

DSIGTransformBase64::DSIGTransformBase64(const XSECEnv * env, DOMNode * node) :
DSIGTransform(env, node) {};

DSIGTransformBase64::DSIGTransformBase64(const XSECEnv * env) :
DSIGTransform(env) {};

DSIGTransformBase64::~DSIGTransformBase64() {};

// --------------------------------------------------------------------------------
//           Interface Methods
// --------------------------------------------------------------------------------

transformType DSIGTransformBase64::getTransformType() {

	return TRANSFORM_BASE64;

}

void DSIGTransformBase64::appendTransformer(TXFMChain * input) {

	// If the input is a Nodeset then we need to find the text from the input

	if (input->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {

		if (input->getLastTxfm()->getNodeType() != TXFMBase::DOM_NODE_XPATH_NODESET) {

#ifdef XSEC_NO_XPATH

			throw XSECException(XSECException::UnsupportedFunction,
				"Unable to extract Base64 text from Nodes without XPath support");

		}

#else

			// Use an XPath transform to get "Self::text()" from the nodeset

			TXFMXPath *x;

			XSECnew(x, TXFMXPath(mp_txfmNode->getOwnerDocument()));
			input->appendTxfm(x);
			((TXFMXPath *) x)->evaluateExpr(mp_txfmNode, "self::text()");

		}

		TXFMC14n *c;

		// Now use c14n to translate to BYTES

		XSECnew(c, TXFMC14n(mp_txfmNode->getOwnerDocument()));
		input->appendTxfm(c);
#endif

	}

	// Now the actual Base64

	TXFMBase64 *b;
	XSECnew(b, TXFMBase64(mp_txfmNode->getOwnerDocument()));
	input->appendTxfm(b);

}

DOMElement * DSIGTransformBase64::createBlankTransform(DOMDocument * parentDoc) {

	safeBuffer str;
	const XMLCh * prefix;
	DOMElement *ret;
	DOMDocument *doc = mp_env->getParentDocument();

	prefix = mp_env->getDSIGNSPrefix();

	// Create the transform node
	makeQName(str, prefix, "Transform");
	ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
	ret->setAttribute(DSIGConstants::s_unicodeStrAlgorithm, DSIGConstants::s_unicodeStrURIBASE64);

	mp_txfmNode = ret;

	return ret;

}

void DSIGTransformBase64::load(void) {

	// Do nothing for a Base64 transform

}
<|endoftext|>