<commit_before>// Run configuration class
// Author: Matthew Raso-Barnett  18/11/2010
#include <iostream>
#include <cassert>
#include <stdexcept>

#include "Constants.h"
#include "Units.h"

#include "RunConfig.h"
#include "ConfigFile.h"

using namespace std;

ClassImp(RunConfig);

//__________________________________________________________________________
RunConfig::RunConfig()
          :TObject(), fRunName(""), fGeomFile(""), fGeomVisFile(""), fInputDataFile(""),
           fOutputDataFile(""), fFieldsFile(""), fInputRunName(""),
           fParticlesToLoad(""), fLoadAllParticles(true), fRestartParticles(false),
           fGravFieldOn(true), fMagFieldOn(false), fWallLossesOn(true), fRunTime(0.),
           fMaxStepTime(0.), fSpinStepTime(0.), fObsSpin(false), fObsBounces(false),
           fObsTracks(false), fObsField(false), fTrackMeasInterval(0.), fSpinMeasInterval(0.),
           fFieldMeasInterval(0.)
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Default Constructor" << endl;
   #endif
}

//__________________________________________________________________________
RunConfig::RunConfig(const ConfigFile& masterConfig, int runNumber)
          :TObject()
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Constructor" << endl;
   #endif
   // Extract full path to config files
   const string compressedfolderpath = masterConfig.GetString("Path","Folder");
   const string folderpath = masterConfig.ExpandFilePath(compressedfolderpath);
   // Use full folder path to fetch the run config file
   Char_t runID[6];
   sprintf(runID,"Run%d",runNumber);
   string runConfigFileName = folderpath + masterConfig.GetString("Config", runID);
   if (runConfigFileName.empty() == kTRUE) {
      cout << "Unable to read in Run Configuration file name" << endl;
      throw runtime_error("Error fetching name of Run Config file");
   }

   ConfigFile runConfigFile(runConfigFileName);
   fRunName = runConfigFile.GetString("RunName","Name");

   fGeomFile = folderpath + runConfigFile.GetString("GeomFile","Files");
   string geomVisFileName = runConfigFile.GetString("GeomVisFile","Files");
   if (geomVisFileName.empty() == false) {fGeomVisFile = folderpath + geomVisFileName;}

   fInputDataFile = folderpath + runConfigFile.GetString("InputDataFile","Files");
   fOutputDataFile = folderpath + runConfigFile.GetString("OutputDataFile","Files");

   fInputRunName = runConfigFile.GetString("InputRunName","Particles");
   fParticlesToLoad = runConfigFile.GetString("WhichParticles","Particles");
   fLoadAllParticles = runConfigFile.GetBool("AllParticles","Particles");
   fRestartParticles = runConfigFile.GetBool("RunFromBeginning","Particles");

   fGravFieldOn = runConfigFile.GetBool("GravField","Properties");
   fWallLossesOn = runConfigFile.GetBool("WallLosses","Properties");

   fRunTime = runConfigFile.GetFloat("RunTime(s)","Properties");
   fMaxStepTime = runConfigFile.GetFloat("MaxStepTime(s)","Properties");

   fObsBounces = runConfigFile.GetBool("RecordBounces","Observables");
   fObsTracks = runConfigFile.GetBool("RecordTracks","Observables");
   double trackMeasFreq = runConfigFile.GetFloat("TrackMeasureFrequency(Hz)","Observables");
   fTrackMeasInterval = (trackMeasFreq == 0.0 ? 0.0 : (1.0/trackMeasFreq));

   fFieldsFile = folderpath + runConfigFile.GetString("FieldsFile","Files");
   fMagFieldOn = runConfigFile.GetBool("MagFields","Properties");
   fSpinStepTime = runConfigFile.GetFloat("SpinStepTime(s)","Properties");

   fObsSpin = runConfigFile.GetBool("RecordSpin","Observables");
   double spinMeasFreq = runConfigFile.GetFloat("SpinMeasureFrequency(Hz)","Observables");
   fSpinMeasInterval = (spinMeasFreq == 0.0 ? 0.0 : (1.0/spinMeasFreq));

   fObsField = runConfigFile.GetBool("RecordField","Observables");
   double fieldMeasFreq = runConfigFile.GetFloat("FieldMeasureFrequency(Hz)","Observables");
   fFieldMeasInterval = (fieldMeasFreq == 0.0 ? 0.0 : (1.0/fieldMeasFreq));

   // Check for inconsistencies in RunConfig File
   if (fFieldsFile.empty() && fMagFieldOn == true) {
      throw runtime_error("Incompatible options in RunConfig: Check FieldsFile and MagFieldOn");
   } else if (fMagFieldOn == true && fSpinStepTime == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check MagFieldOn and SpinStepTime");
   } else if (fObsSpin == true && fSpinMeasInterval == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check RecordSpin and SpinMeasFreq");
   } else if (fObsField == true && fFieldMeasInterval == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check RecordField and FieldMeasFreq");
   } else if (fMagFieldOn == false) {
      fSpinStepTime = 0.0;
      fObsSpin = false;
      fObsField = false;
      fSpinMeasInterval = 0.0;
      fFieldMeasInterval = 0.0;
   }
   this->Print();
}

//__________________________________________________________________________
RunConfig::RunConfig(const RunConfig& other)
              :TObject(other),
               fRunName(other.fRunName),
               fGeomFile(other.fGeomFile),
               fGeomVisFile(other.fGeomVisFile),
               fInputDataFile(other.fInputDataFile),
               fOutputDataFile(other.fOutputDataFile),
               fFieldsFile(other.fFieldsFile),
               fInputRunName(other.fInputRunName),
               fParticlesToLoad(other.fParticlesToLoad),
               fLoadAllParticles(other.fLoadAllParticles),
               fRestartParticles(other.fRestartParticles),
               fGravFieldOn(other.fGravFieldOn),
               fMagFieldOn(other.fMagFieldOn),
               fWallLossesOn(other.fWallLossesOn),
               fRunTime(other.fRunTime),
               fMaxStepTime(other.fMaxStepTime),
               fSpinStepTime(other.fSpinStepTime),
               fObsSpin(other.fObsSpin),
               fObsBounces(other.fObsBounces),
               fObsTracks(other.fObsTracks),
               fObsField(other.fObsField),
               fTrackMeasInterval(other.fTrackMeasInterval),
               fSpinMeasInterval(other.fSpinMeasInterval),
               fFieldMeasInterval(other.fFieldMeasInterval)
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Copy Constructor" << endl;
   #endif
}

//__________________________________________________________________________
RunConfig::~RunConfig()
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Destructor" << endl;
   #endif
}

//__________________________________________________________________________
void RunConfig::Print(Option_t* /*option*/) const
{
   cout << "-------------------------------------------" << endl;
   cout << "Run Configuration Settings" << endl;
   cout << "Name: " << fRunName << endl;
   cout << "GeomFile: " << fGeomFile << endl;
   cout << "GeomVisFile: " << fGeomVisFile << endl;
   cout << "InputDataFile: " << fInputDataFile << endl;
   cout << "OutputDataFile: " << fOutputDataFile << endl;
   cout << "FieldsFile: " << fFieldsFile << endl;
   cout << "InputRunName: " << fInputRunName << endl;
   cout << "InitialParticleBranch: " << fParticlesToLoad << endl;
   cout << "LoadAllParticles: " << fLoadAllParticles << endl;
   cout << "RestartParticles: " << fRestartParticles << endl;
   cout << "GravFieldOn: " << fGravFieldOn << endl;
   cout << "MagFieldOn: " << fMagFieldOn << endl;
   cout << "WallLossesOn: " << fWallLossesOn << endl;
   cout << "RunTime: " << fRunTime << " s"<< endl;
   cout << "MaxStepTime: " << fMaxStepTime << " s"<< endl;
   cout << "SpinStepTime: " << fSpinStepTime << " s"<< endl;
   cout << "Observe Spin: " << fObsSpin << endl;
   cout << "Observe Bounces: " << fObsBounces << endl;
   cout << "Observe Tracks: " << fObsTracks << endl;
   cout << "Observe Field: " << fObsField << endl;
   cout << "Track Measurement Interval: " << fTrackMeasInterval << endl;
   cout << "Spin Measurement Interval: " << fSpinMeasInterval << endl;
   cout << "Field Measurement Interval: " << fFieldMeasInterval << endl;
   cout << "-------------------------------------------" << endl;
}
<commit_msg>Improve error checking in RunConfig constructor<commit_after>// Run configuration class
// Author: Matthew Raso-Barnett  18/11/2010
#include <iostream>
#include <cassert>
#include <stdexcept>

#include "Algorithms.h"
#include "Constants.h"
#include "Units.h"

#include "RunConfig.h"
#include "ConfigFile.h"

using namespace std;

ClassImp(RunConfig);

//__________________________________________________________________________
RunConfig::RunConfig()
          :TObject(), fRunName(""), fGeomFile(""), fGeomVisFile(""), fInputDataFile(""),
           fOutputDataFile(""), fFieldsFile(""), fInputRunName(""),
           fParticlesToLoad(""), fLoadAllParticles(true), fRestartParticles(false),
           fGravFieldOn(true), fMagFieldOn(false), fWallLossesOn(true), fRunTime(0.),
           fMaxStepTime(0.), fSpinStepTime(0.), fObsSpin(false), fObsBounces(false),
           fObsTracks(false), fObsField(false), fTrackMeasInterval(0.), fSpinMeasInterval(0.),
           fFieldMeasInterval(0.)
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Default Constructor" << endl;
   #endif
}

//__________________________________________________________________________
RunConfig::RunConfig(const ConfigFile& masterConfig, int runNumber)
          :TObject(), fRunName(""), fGeomFile(""), fGeomVisFile(""), fInputDataFile(""),
           fOutputDataFile(""), fFieldsFile(""), fInputRunName(""),
           fParticlesToLoad(""), fLoadAllParticles(true), fRestartParticles(false),
           fGravFieldOn(true), fMagFieldOn(false), fWallLossesOn(true), fRunTime(0.),
           fMaxStepTime(0.), fSpinStepTime(0.), fObsSpin(false), fObsBounces(false),
           fObsTracks(false), fObsField(false), fTrackMeasInterval(0.), fSpinMeasInterval(0.),
           fFieldMeasInterval(0.)
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Constructor" << endl;
   #endif
   //////////////////////////////////////////////////////////////////
   // -- Extract full path to directory containing configuration files
   const string compressedfolderpath = masterConfig.GetString("Path","Folder");
   const string folderpath = masterConfig.ExpandFilePath(compressedfolderpath);
   //////////////////////////////////////////////////////////////////
   // -- Use full folder path to find and build the run-config file
   Char_t runID[6];
   sprintf(runID,"Run%d",runNumber);
   string runConfigFileName = folderpath + masterConfig.GetString("Config", runID);
   if (runConfigFileName.empty() == kTRUE) {
      cout << "Error: Run Configuration file name specified is either empty of invalid" << endl;
      throw runtime_error("Error fetching name of Run Config file");
   }
   ConfigFile runConfigFile(runConfigFileName);
   //////////////////////////////////////////////////////////////////
   // -- Search the Run Config file for parameters
   // -----------------------------------
   // Name of Run object
   fInputRunName = runConfigFile.GetString("InputRunName","Particles");
   // -----------------------------------
   // -- Files to Load
   // Name of Run
   fRunName = runConfigFile.GetString("RunName","Name");
   // Name of Input Geometry
   string geomFileName = runConfigFile.GetString("GeomFile","Files");
   if (geomFileName.empty() == true) {
      throw runtime_error("No GeomFile specified in runconfig");
   }
   fGeomFile = folderpath + geomFileName;
   // Name of Visualisation Geometry
   string geomVisFileName = runConfigFile.GetString("GeomVisFile","Files");
   if (geomVisFileName.empty() == true) {
      throw runtime_error("No GeomVisFile specified in runconfig");
   }
   fGeomVisFile = folderpath + geomVisFileName;
   // Name of Input particle data file
   string inputDataFileName = runConfigFile.GetString("InputDataFile","Files");
   if (inputDataFileName.empty() == true) {
      throw runtime_error("No InputDataFile specified in runconfig");
   }
   fInputDataFile = folderpath + inputDataFileName;
   // Name of Output data file
   string outputDataFileName = runConfigFile.GetString("OutputDataFile","Files");
   if (outputDataFileName.empty() == true) {
      throw runtime_error("No OutputDataFile specified in runconfig");
   }
   fOutputDataFile = folderpath + outputDataFileName;
   // Name of Fields input file -- Not required to be set
   string fieldsFileName = runConfigFile.GetString("FieldsFile","Files");
   if (fieldsFileName.empty() == false) {fFieldsFile = folderpath + fieldsFileName;}
   else {fFieldsFile = "";}
   // -----------------------------------
   // -- Input Particles options
   // Name of state folder to load particles from
   fParticlesToLoad = runConfigFile.GetString("WhichParticles","Particles");
   if (Algorithms::DataFile::ValidateStateNames(fParticlesToLoad) == false) {
      throw runtime_error("Invalid InputParticleState specified in runconfig");
   }
   // Option for whether to load all particles in input folder
   fLoadAllParticles = runConfigFile.GetBool("AllParticles","Particles");
   // Option for whether to restart particles from their initial states (obviously this is
   // only relevant if ParticlesToLoad is not already the initial states)
   fRestartParticles = runConfigFile.GetBool("RunFromBeginning","Particles");
   // -----------------------------------
   // -- Run Options
   // Option for whether gravity is turned on
   fGravFieldOn = runConfigFile.GetBool("GravField","Properties");
   // Option for whether wall losses are turned on
   fWallLossesOn = runConfigFile.GetBool("WallLosses","Properties");
   // Option for whether magnetic field is turned on
   fMagFieldOn = runConfigFile.GetBool("MagFields","Properties");
   // Parameter to be set; Specifies time to simulate neutrons to
   fRunTime = runConfigFile.GetFloat("RunTime(s)","Properties");
   if (fRunTime <= 0.) {throw runtime_error("Invalid RunTime specified in runconfig");}
   // Parameter to be set; Maximum geometrical step allowed in simulation
   fMaxStepTime = runConfigFile.GetFloat("MaxStepTime(s)","Properties");
   if (fMaxStepTime <= 0.) {fMaxStepTime = 1.0*Units::s;}
   // Parameter to be set; Maximum spin step allowed in simulation
   fSpinStepTime = runConfigFile.GetFloat("SpinStepTime(s)","Properties");
   if (fSpinStepTime <= 0.) {throw runtime_error("Invalid SpinStepTime specified in runconfig");}
   // -----------------------------------
   // -- Observer Options
   // Option for whether to record numbers of Bounces
   fObsBounces = runConfigFile.GetBool("RecordBounces","Observables");
   // Option for whether to record particle tracks
   fObsTracks = runConfigFile.GetBool("RecordTracks","Observables");
   // Parameter to be set; Specify frequency of track measurements (if desired -
   // by default it will measure all track points)
   double trackMeasFreq = runConfigFile.GetFloat("TrackMeasureFrequency(Hz)","Observables");
   fTrackMeasInterval = (trackMeasFreq == 0.0 ? 0.0 : (1.0/trackMeasFreq));
   // Option for whether to record spin states
   fObsSpin = runConfigFile.GetBool("RecordSpin","Observables");
   // Parameter to be set; Specify frequency of spin measurements
   double spinMeasFreq = runConfigFile.GetFloat("SpinMeasureFrequency(Hz)","Observables");
   fSpinMeasInterval = (spinMeasFreq == 0.0 ? 0.0 : (1.0/spinMeasFreq));
   // Option for whether to record field seen by particles
   fObsField = runConfigFile.GetBool("RecordField","Observables");
   // Parameter to be set; Specify frequency of field measurements
   double fieldMeasFreq = runConfigFile.GetFloat("FieldMeasureFrequency(Hz)","Observables");
   fFieldMeasInterval = (fieldMeasFreq == 0.0 ? 0.0 : (1.0/fieldMeasFreq));
   // -----------------------------------
   // -----------------------------------
   // Check for inconsistencies in RunConfig File
   if (fFieldsFile.empty() && fMagFieldOn == true) {
      throw runtime_error("Incompatible options in RunConfig: Check FieldsFile and MagFieldOn");
   } else if (fMagFieldOn == true && fSpinStepTime == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check MagFieldOn and SpinStepTime");
   } else if (fObsSpin == true && fSpinMeasInterval == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check RecordSpin and SpinMeasFreq");
   } else if (fObsField == true && fFieldMeasInterval == 0.0) {
      throw runtime_error("Incompatible options in RunConfig: Check RecordField and FieldMeasFreq");
   } else if (fMagFieldOn == false) {
      fSpinStepTime = 0.0;
      fObsSpin = false;
      fObsField = false;
      fSpinMeasInterval = 0.0;
      fFieldMeasInterval = 0.0;
   }
   this->Print();
}

//__________________________________________________________________________
RunConfig::RunConfig(const RunConfig& other)
              :TObject(other),
               fRunName(other.fRunName),
               fGeomFile(other.fGeomFile),
               fGeomVisFile(other.fGeomVisFile),
               fInputDataFile(other.fInputDataFile),
               fOutputDataFile(other.fOutputDataFile),
               fFieldsFile(other.fFieldsFile),
               fInputRunName(other.fInputRunName),
               fParticlesToLoad(other.fParticlesToLoad),
               fLoadAllParticles(other.fLoadAllParticles),
               fRestartParticles(other.fRestartParticles),
               fGravFieldOn(other.fGravFieldOn),
               fMagFieldOn(other.fMagFieldOn),
               fWallLossesOn(other.fWallLossesOn),
               fRunTime(other.fRunTime),
               fMaxStepTime(other.fMaxStepTime),
               fSpinStepTime(other.fSpinStepTime),
               fObsSpin(other.fObsSpin),
               fObsBounces(other.fObsBounces),
               fObsTracks(other.fObsTracks),
               fObsField(other.fObsField),
               fTrackMeasInterval(other.fTrackMeasInterval),
               fSpinMeasInterval(other.fSpinMeasInterval),
               fFieldMeasInterval(other.fFieldMeasInterval)
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Copy Constructor" << endl;
   #endif
}

//__________________________________________________________________________
RunConfig::~RunConfig()
{
   #ifdef PRINT_CONSTRUCTORS
      cout << "RunConfig::Destructor" << endl;
   #endif
}

//__________________________________________________________________________
void RunConfig::Print(Option_t* /*option*/) const
{
   cout << "-------------------------------------------" << endl;
   cout << "Run Configuration Settings" << endl;
   cout << "Name: " << fRunName << endl;
   cout << "GeomFile: " << fGeomFile << endl;
   cout << "GeomVisFile: " << fGeomVisFile << endl;
   cout << "InputDataFile: " << fInputDataFile << endl;
   cout << "OutputDataFile: " << fOutputDataFile << endl;
   cout << "FieldsFile: " << fFieldsFile << endl;
   cout << "InputRunName: " << fInputRunName << endl;
   cout << "InitialParticleBranch: " << fParticlesToLoad << endl;
   cout << "LoadAllParticles: " << fLoadAllParticles << endl;
   cout << "RestartParticles: " << fRestartParticles << endl;
   cout << "GravFieldOn: " << fGravFieldOn << endl;
   cout << "MagFieldOn: " << fMagFieldOn << endl;
   cout << "WallLossesOn: " << fWallLossesOn << endl;
   cout << "RunTime: " << fRunTime << " s"<< endl;
   cout << "MaxStepTime: " << fMaxStepTime << " s"<< endl;
   cout << "SpinStepTime: " << fSpinStepTime << " s"<< endl;
   cout << "Observe Spin: " << fObsSpin << endl;
   cout << "Observe Bounces: " << fObsBounces << endl;
   cout << "Observe Tracks: " << fObsTracks << endl;
   cout << "Observe Field: " << fObsField << endl;
   cout << "Track Measurement Interval: " << fTrackMeasInterval << endl;
   cout << "Spin Measurement Interval: " << fSpinMeasInterval << endl;
   cout << "Field Measurement Interval: " << fFieldMeasInterval << endl;
   cout << "-------------------------------------------" << endl;
}
<|endoftext|>


<commit_before>#include "appcontroller.hpp"
#include "window.hpp"
#include "resourcemanager.hpp"
#include <lib/draw/scenemanager.hpp>
#include <lib/draw/rendermanager.hpp>
#include "utilprovider.hpp"
#include "log.hpp"
#include "exceptionmanager.hpp"
#include "filesystem.hpp"
#include "configuration.hpp"
#include "servicesmanager.hpp"
#include "shareddata.hpp"
#include "input.hpp"

namespace lib
{
	namespace core
	{
		AppController::AppController(uptr<IApp> iapp, sptr<Driver> driverInstance)
			: m_iapp{ std::move(iapp) }, m_driver{ driverInstance }, m_servicesManager{ new ServicesManager{ this } }
		{
			LOG_CONSTRUCT_NOPARAMS;
			m_iapp->setAppContext(this);
			LOG_DEBUG("Starting app " << appId() << "...");
			m_state = AppState::ReadyToStart;
		}

		AppController::~AppController()
		{
			LOG_DESTRUCT("Name: " + appId());
		}

		bool AppController::update()
		{
			switch (m_state)
			{
			case AppState::NotInitialized:
				break;
			case AppState::ReadyToStart:
			{
				// Create the scene manager
				LOG_DEBUG_(appId() + ":  Starting initialization...");
				m_state = AppState::Executing;

				//TO DO: Ask via requests
				m_servicesManager->addService(sptr<ExceptionManager>{new ExceptionManager{}});
				m_servicesManager->addService(sptr<FileSystem>{ new FileSystem{} });
				m_servicesManager->addService(sptr<Configuration>{ new Configuration{} });
				m_servicesManager->addService(sptr<Configuration>{ new Configuration{} });
				m_servicesManager->addService(sptr<SharedData>{ new SharedData{} });
				m_servicesManager->addService(sptr<UtilProvider>{new UtilProvider{}});
				m_servicesManager->addService(sptr<ResourceManager>{ new ResourceManager{} });
				m_servicesManager->addService(sptr<draw::SceneManager>{ new draw::SceneManager{} });
				m_servicesManager->addService(sptr<draw::RenderManager>{ new draw::RenderManager{} });
				m_servicesManager->addService(sptr<Window>{ new Window{ m_iapp->getAppDescriptor().wcp }});
				m_servicesManager->addService(sptr<Input>{new Input{}});

				m_servicesManager->setupAllServices();
				m_servicesManager->initializeServices();

				m_servicesManager->service<draw::SceneManager>()->addScenes(m_iapp->scenesVector());

				m_iapp->onInit();
				LOG_DEBUG(appId() << ": " << " is now executing");
			}
				break;
			case AppState::Executing:
			{
				if (loopStep())
				{
					m_state = AppState::ReadyToTerminate;
					LOG_DEBUG(appId() << ": " << " is now ready to terminate");
				}
			}
				break;
			case AppController::AppState::ReadyToTerminate:
				LOG_DEBUG(appId() << ": " << " started termination");
				m_state = AppState::Terminated;
//				m_iapp->onFinish();

				m_servicesManager->stopServices();
				LOG_DEBUG_(appId() + ": terminated");
				return true;
				break;
			case AppState::Terminated:
				return true;
				break;
			default:
				break;
			}
			return false;
		}

		bool AppController::loopStep()
		{
			bool windowWants2Close = m_servicesManager->service<Window>()->preLoop();
			m_servicesManager->service<draw::SceneManager>()->update();
			windowWants2Close |= m_servicesManager->service<Window>()->postLoop();
			return windowWants2Close;
		}

		const std::string AppController::appId() const
		{
			if (m_iapp)
			{
				return std::string(m_iapp->getAppDescriptor().Name + ":" + std::to_string(m_iapp->getAppDescriptor().Version) +
					"." + std::to_string(m_iapp->getAppDescriptor().SubVersion) + "."+std::to_string(m_iapp->getAppDescriptor().Patch));
			}
			return "NoApp:0.0.0";
		}

		AppController * toController(PIAppContext context)
		{
			return dynamic_cast<AppController*>(context);
		}
	}
}
<commit_msg>Removed duplicated service<commit_after>#include "appcontroller.hpp"
#include "window.hpp"
#include "resourcemanager.hpp"
#include <lib/draw/scenemanager.hpp>
#include <lib/draw/rendermanager.hpp>
#include "utilprovider.hpp"
#include "log.hpp"
#include "exceptionmanager.hpp"
#include "filesystem.hpp"
#include "configuration.hpp"
#include "servicesmanager.hpp"
#include "shareddata.hpp"
#include "input.hpp"

namespace lib
{
	namespace core
	{
		AppController::AppController(uptr<IApp> iapp, sptr<Driver> driverInstance)
			: m_iapp{ std::move(iapp) }, m_driver{ driverInstance }, m_servicesManager{ new ServicesManager{ this } }
		{
			LOG_CONSTRUCT_NOPARAMS;
			m_iapp->setAppContext(this);
			LOG_DEBUG("Starting app " << appId() << "...");
			m_state = AppState::ReadyToStart;
		}

		AppController::~AppController()
		{
			LOG_DESTRUCT("Name: " + appId());
		}

		bool AppController::update()
		{
			switch (m_state)
			{
			case AppState::NotInitialized:
				break;
			case AppState::ReadyToStart:
			{
				// Create the scene manager
				LOG_DEBUG_(appId() + ":  Starting initialization...");
				m_state = AppState::Executing;

				//TO DO: Ask via requests
				m_servicesManager->addService(sptr<ExceptionManager>{new ExceptionManager{}});
				m_servicesManager->addService(sptr<FileSystem>{ new FileSystem{} });
				m_servicesManager->addService(sptr<Configuration>{ new Configuration{} });
				m_servicesManager->addService(sptr<SharedData>{ new SharedData{} });
				m_servicesManager->addService(sptr<UtilProvider>{new UtilProvider{}});
				m_servicesManager->addService(sptr<ResourceManager>{ new ResourceManager{} });
				m_servicesManager->addService(sptr<draw::SceneManager>{ new draw::SceneManager{} });
				m_servicesManager->addService(sptr<draw::RenderManager>{ new draw::RenderManager{} });
				m_servicesManager->addService(sptr<Window>{ new Window{ m_iapp->getAppDescriptor().wcp }});
				m_servicesManager->addService(sptr<Input>{new Input{}});

				m_servicesManager->setupAllServices();
				m_servicesManager->initializeServices();

				m_servicesManager->service<draw::SceneManager>()->addScenes(m_iapp->scenesVector());

				m_iapp->onInit();
				LOG_DEBUG(appId() << ": " << " is now executing");
			}
				break;
			case AppState::Executing:
			{
				if (loopStep())
				{
					m_state = AppState::ReadyToTerminate;
					LOG_DEBUG(appId() << ": " << " is now ready to terminate");
				}
			}
				break;
			case AppController::AppState::ReadyToTerminate:
				LOG_DEBUG(appId() << ": " << " started termination");
				m_state = AppState::Terminated;
//				m_iapp->onFinish();

				m_servicesManager->stopServices();
				LOG_DEBUG_(appId() + ": terminated");
				return true;
				break;
			case AppState::Terminated:
				return true;
				break;
			default:
				break;
			}
			return false;
		}

		bool AppController::loopStep()
		{
			bool windowWants2Close = m_servicesManager->service<Window>()->preLoop();
			m_servicesManager->service<draw::SceneManager>()->update();
			windowWants2Close |= m_servicesManager->service<Window>()->postLoop();
			return windowWants2Close;
		}

		const std::string AppController::appId() const
		{
			if (m_iapp)
			{
				return std::string(m_iapp->getAppDescriptor().Name + ":" + std::to_string(m_iapp->getAppDescriptor().Version) +
					"." + std::to_string(m_iapp->getAppDescriptor().SubVersion) + "."+std::to_string(m_iapp->getAppDescriptor().Patch));
			}
			return "NoApp:0.0.0";
		}

		AppController * toController(PIAppContext context)
		{
			return dynamic_cast<AppController*>(context);
		}
	}
}
<|endoftext|>


<commit_before>/* $Id: OSBlockSolverFactory.cpp 3038 2009-11-07 11:43:44Z Gassmann $ */
/** @file OSBlockSolverFactory.cpp
 *
 *
 * @author  Gus Gassmann, Jun Ma, Kipp Martin,
 * @version 1.0, 21/July/2008
 * @since   OS1.1
 *
 * \remarks
 * Copyright (C) 2005-2008, Gus Gassmann, Jun Ma, Kipp Martin,
 * Dalhousie University,  Northwestern University, and the University of Chicago.
 * All Rights Reserved.
 * This software is licensed under the Common Public License.
 * Please see the accompanying LICENSE file in root directory for terms.
 *
 */

// --------------------------------------------------------------------- //
#include "OSInstance.h"
#include "OSResult.h"
#include "OSDataStructures.h"
#include "OSErrorClass.h"
#include <vector>
#include <string>
#include <map>

#include "OSDipBlockSolverFactory.h"

std::map<std::string, OSDipBlockSolverFactory*> OSDipBlockSolverFactory::factories;

OSDipBlockSolver* OSDipBlockSolverFactory::createOSDipBlockSolver(const string &solverName) throw(ErrorClass){

	if( factories.find(solverName) != factories.end() ){

		return factories[ solverName]->create();

	}else{
		throw ErrorClass( solverName + " is not a valid OSDipBlockSolver");
	}

}//end

/**
 *
 * Default Constructor.
 */
OSDipBlockSolverFactory::OSDipBlockSolverFactory(){

}

 OSDipBlockSolverFactory::~OSDipBlockSolverFactory(){
 }
 <commit_msg>add another newline in OSDipBlockSolverFactory.cpp for Matt<commit_after>/* $Id: OSBlockSolverFactory.cpp 3038 2009-11-07 11:43:44Z Gassmann $ */
/** @file OSBlockSolverFactory.cpp
 *
 *
 * @author  Gus Gassmann, Jun Ma, Kipp Martin,
 * @version 1.0, 21/July/2008
 * @since   OS1.1
 *
 * \remarks
 * Copyright (C) 2005-2008, Gus Gassmann, Jun Ma, Kipp Martin,
 * Dalhousie University,  Northwestern University, and the University of Chicago.
 * All Rights Reserved.
 * This software is licensed under the Common Public License.
 * Please see the accompanying LICENSE file in root directory for terms.
 *
 */

// --------------------------------------------------------------------- //
#include "OSInstance.h"
#include "OSResult.h"
#include "OSDataStructures.h"
#include "OSErrorClass.h"
#include <vector>
#include <string>
#include <map>

#include "OSDipBlockSolverFactory.h"

std::map<std::string, OSDipBlockSolverFactory*> OSDipBlockSolverFactory::factories;

OSDipBlockSolver* OSDipBlockSolverFactory::createOSDipBlockSolver(const string &solverName) throw(ErrorClass){

	if( factories.find(solverName) != factories.end() ){

		return factories[ solverName]->create();

	}else{
		throw ErrorClass( solverName + " is not a valid OSDipBlockSolver");
	}

}//end

/**
 *
 * Default Constructor.
 */
OSDipBlockSolverFactory::OSDipBlockSolverFactory(){

}

 OSDipBlockSolverFactory::~OSDipBlockSolverFactory(){
 }

<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "TaskSys.h"
//ospray
#include "common/sysinfo.h"
#include "common/thread.h"
//stl
#include <thread>
#include <vector>

namespace ospray {
  struct TaskSys {
    bool initialized;
    bool running;

    void init(size_t maxNumRenderTasks);
    static TaskSys global;
    static void *threadStub(void *);
    inline Ref<Task> getNextActiveTask();

    //! Queue of tasks that have ALREADY been acitvated, and that are ready
    //! to run
    __aligned(64) Task *volatile activeListFirst;
    __aligned(64) Task *volatile activeListLast;

    Mutex     __aligned(64) mutex;
    Condition __aligned(64) tasksAvailable;

    void threadFunction();

    std::vector<thread_t> threads;

    TaskSys()
      : activeListFirst(nullptr), activeListLast(nullptr),
        initialized(false), running(false)
    {}

    ~TaskSys();
  };

  TaskSys __aligned(64) TaskSys::global;

  inline void Task::workOnIt()
  {
    size_t myCompleted = 0;
    while (1) {
      const size_t thisJobID = numJobsStarted++;
      if (thisJobID >= numJobsInTask)
       break;

      run(thisJobID);
      ++myCompleted;
    }

    if (myCompleted != 0) {
      const size_t nowCompleted = (numJobsCompleted += myCompleted);
      if (nowCompleted == numJobsInTask) {
        SCOPED_LOCK(mutex);
        status = Task::COMPLETED;
        allJobsCompletedCond.notify_all();
      }
    }
  }

  void Task::wait(bool workOnIt)
  {
    if (status == Task::COMPLETED) {
      return;
    }

    if (workOnIt) {
      this->workOnIt();
    }

    std::unique_lock<std::mutex> lock(mutex);
    allJobsCompletedCond.wait(lock, [&](){return status == Task::COMPLETED;});
  }

  void Task::scheduleAndWait(size_t numJobs, ScheduleOrder order)
  {
    schedule(numJobs,order);
    wait();
  }

  inline Ref<Task> TaskSys::getNextActiveTask()
  {
    while (1) {
      std::unique_lock<std::mutex> lock(mutex);
      tasksAvailable.wait(lock, [&](){
        return !(activeListFirst == nullptr && running);
      });

      if (!running) {
        return nullptr;
      }

      Ref<Task> front = activeListFirst;
      if (front->numJobsStarted >= front->numJobsInTask) {
        if (activeListFirst == activeListLast) {
          activeListFirst = activeListLast = nullptr;
        } else {
          activeListFirst = activeListFirst->next;
        }
        continue;
      }
      assert(front.ptr());
      return front;
    }
  }

  void Task::initTaskSystem(const size_t maxNumRenderTasks)
  {
    TaskSys::global.init(maxNumRenderTasks);
  }

  void Task::schedule(size_t numJobs, ScheduleOrder order)
  {
    refInc();
    this->order = order;
    numJobsInTask = numJobs;
    status = Task::SCHEDULED;
    if (numMissingDependencies == 0)
      activate();
  }

  inline void Task::activate()
  {
    if (!TaskSys::global.initialized)
      throw std::runtime_error("TASK SYSTEM NOT YET INITIALIZED");
    {
      SCOPED_LOCK(TaskSys::global.mutex);
      bool wasEmpty = TaskSys::global.activeListFirst == nullptr;
      if (wasEmpty) {
        TaskSys::global.activeListFirst = TaskSys::global.activeListLast = this;
        this->next = nullptr;
        TaskSys::global.tasksAvailable.notify_all();
      } else {
        if (order == Task::BACK_OF_QUEUE) {
          this->next = nullptr;
          TaskSys::global.activeListLast->next = this;
          TaskSys::global.activeListLast = this;
        } else {
          this->next = TaskSys::global.activeListFirst;
          TaskSys::global.activeListFirst = this;
        }
      }
      status = Task::ACTIVE;
    }
  }

  void TaskSys::threadFunction()
  {
    while (1) {
      Ref<Task> task = getNextActiveTask();
      if (!running) {
        return;
      }
      assert(task);
      task->workOnIt();
    }
  }

  TaskSys::~TaskSys()
  {
    running = false;
    tasksAvailable.notify_all();
    for (int i = 0; i < threads.size(); ++i) {
      join(threads[i]);
    }
  }

  void *TaskSys::threadStub(void *)
  {
    TaskSys::global.threadFunction();
    return nullptr;
  }

  void TaskSys::init(size_t numThreads)
  {
    if (initialized)
      throw std::runtime_error("#osp: task system initialized twice!");
    initialized = true;
    running = true;

    if (numThreads != 0) {
#if defined(__MIC__)
      numThreads = std::min(numThreads,
                            (size_t)std::thread::hardware_concurrency()-4);
#else
      numThreads = std::min(numThreads,
                            (size_t)std::thread::hardware_concurrency());
#endif
    }

    /* generate all threads */
    for (size_t t=1; t<numThreads; t++) {
      threads.push_back(createThread((thread_func)TaskSys::threadStub,
                                     (void*)-1,4*1024*1024,-1));
    }

#if ~defined(__MIC__)
    setAffinity(0);
#endif
  }
}//namespace ospray
<commit_msg>fix debug compile error<commit_after>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "TaskSys.h"
//ospray
#include "common/sysinfo.h"
#include "common/thread.h"
//stl
#include <thread>
#include <vector>

namespace ospray {
  struct TaskSys {
    bool initialized;
    bool running;

    void init(size_t maxNumRenderTasks);
    static TaskSys global;
    static void *threadStub(void *);
    inline Ref<Task> getNextActiveTask();

    //! Queue of tasks that have ALREADY been acitvated, and that are ready
    //! to run
    __aligned(64) Task *volatile activeListFirst;
    __aligned(64) Task *volatile activeListLast;

    Mutex     __aligned(64) mutex;
    Condition __aligned(64) tasksAvailable;

    void threadFunction();

    std::vector<thread_t> threads;

    TaskSys()
      : activeListFirst(nullptr), activeListLast(nullptr),
        initialized(false), running(false)
    {}

    ~TaskSys();
  };

  TaskSys __aligned(64) TaskSys::global;

  inline void Task::workOnIt()
  {
    size_t myCompleted = 0;
    while (1) {
      const size_t thisJobID = numJobsStarted++;
      if (thisJobID >= numJobsInTask)
       break;

      run(thisJobID);
      ++myCompleted;
    }

    if (myCompleted != 0) {
      const size_t nowCompleted = (numJobsCompleted += myCompleted);
      if (nowCompleted == numJobsInTask) {
        SCOPED_LOCK(mutex);
        status = Task::COMPLETED;
        allJobsCompletedCond.notify_all();
      }
    }
  }

  void Task::wait(bool workOnIt)
  {
    if (status == Task::COMPLETED) {
      return;
    }

    if (workOnIt) {
      this->workOnIt();
    }

    std::unique_lock<std::mutex> lock(mutex);
    allJobsCompletedCond.wait(lock, [&](){return status == Task::COMPLETED;});
  }

  void Task::scheduleAndWait(size_t numJobs, ScheduleOrder order)
  {
    schedule(numJobs,order);
    wait();
  }

  inline Ref<Task> TaskSys::getNextActiveTask()
  {
    while (1) {
      std::unique_lock<std::mutex> lock(mutex);
      tasksAvailable.wait(lock, [&](){
        return !(activeListFirst == nullptr && running);
      });

      if (!running) {
        return nullptr;
      }

      Ref<Task> front = activeListFirst;
      if (front->numJobsStarted >= front->numJobsInTask) {
        if (activeListFirst == activeListLast) {
          activeListFirst = activeListLast = nullptr;
        } else {
          activeListFirst = activeListFirst->next;
        }
        continue;
      }
      assert(front.ptr);
      return front;
    }
  }

  void Task::initTaskSystem(const size_t maxNumRenderTasks)
  {
    TaskSys::global.init(maxNumRenderTasks);
  }

  void Task::schedule(size_t numJobs, ScheduleOrder order)
  {
    refInc();
    this->order = order;
    numJobsInTask = numJobs;
    status = Task::SCHEDULED;
    if (numMissingDependencies == 0)
      activate();
  }

  inline void Task::activate()
  {
    if (!TaskSys::global.initialized)
      throw std::runtime_error("TASK SYSTEM NOT YET INITIALIZED");
    {
      SCOPED_LOCK(TaskSys::global.mutex);
      bool wasEmpty = TaskSys::global.activeListFirst == nullptr;
      if (wasEmpty) {
        TaskSys::global.activeListFirst = TaskSys::global.activeListLast = this;
        this->next = nullptr;
        TaskSys::global.tasksAvailable.notify_all();
      } else {
        if (order == Task::BACK_OF_QUEUE) {
          this->next = nullptr;
          TaskSys::global.activeListLast->next = this;
          TaskSys::global.activeListLast = this;
        } else {
          this->next = TaskSys::global.activeListFirst;
          TaskSys::global.activeListFirst = this;
        }
      }
      status = Task::ACTIVE;
    }
  }

  void TaskSys::threadFunction()
  {
    while (1) {
      Ref<Task> task = getNextActiveTask();
      if (!running) {
        return;
      }
      assert(task);
      task->workOnIt();
    }
  }

  TaskSys::~TaskSys()
  {
    running = false;
    tasksAvailable.notify_all();
    for (int i = 0; i < threads.size(); ++i) {
      join(threads[i]);
    }
  }

  void *TaskSys::threadStub(void *)
  {
    TaskSys::global.threadFunction();
    return nullptr;
  }

  void TaskSys::init(size_t numThreads)
  {
    if (initialized)
      throw std::runtime_error("#osp: task system initialized twice!");
    initialized = true;
    running = true;

    if (numThreads != 0) {
#if defined(__MIC__)
      numThreads = std::min(numThreads,
                            (size_t)std::thread::hardware_concurrency()-4);
#else
      numThreads = std::min(numThreads,
                            (size_t)std::thread::hardware_concurrency());
#endif
    }

    /* generate all threads */
    for (size_t t=1; t<numThreads; t++) {
      threads.push_back(createThread((thread_func)TaskSys::threadStub,
                                     (void*)-1,4*1024*1024,-1));
    }

#if ~defined(__MIC__)
    setAffinity(0);
#endif
  }
}//namespace ospray
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCodecPriv.h"
#include "SkWebpCodec.h"
#include "SkTemplates.h"

// A WebP decoder on top of (subset of) libwebp
// For more information on WebP image format, and libwebp library, see:
//   https://code.google.com/speed/webp/
//   http://www.webmproject.org/code/#libwebp-webp-image-library
//   https://chromium.googlesource.com/webm/libwebp

// If moving libwebp out of skia source tree, path for webp headers must be
// updated accordingly. Here, we enforce using local copy in webp sub-directory.
#include "webp/decode.h"
#include "webp/encode.h"

bool SkWebpCodec::IsWebp(const void* buf, size_t bytesRead) {
    // WEBP starts with the following:
    // RIFFXXXXWEBPVP
    // Where XXXX is unspecified.
    const char* bytes = static_cast<const char*>(buf);
    return bytesRead >= 14 && !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6);
}

// Parse headers of RIFF container, and check for valid Webp (VP8) content.
// NOTE: This calls peek instead of read, since onGetPixels will need these
// bytes again.
static bool webp_parse_header(SkStream* stream, SkImageInfo* info) {
    unsigned char buffer[WEBP_VP8_HEADER_SIZE];
    SkASSERT(WEBP_VP8_HEADER_SIZE <= SkCodec::MinBufferedBytesNeeded());

    const size_t bytesPeeked = stream->peek(buffer, WEBP_VP8_HEADER_SIZE);
    if (bytesPeeked != WEBP_VP8_HEADER_SIZE) {
        // Use read + rewind as a backup
        if (stream->read(buffer, WEBP_VP8_HEADER_SIZE) != WEBP_VP8_HEADER_SIZE
            || !stream->rewind())
        return false;
    }

    WebPBitstreamFeatures features;
    VP8StatusCode status = WebPGetFeatures(buffer, WEBP_VP8_HEADER_SIZE, &features);
    if (VP8_STATUS_OK != status) {
        return false; // Invalid WebP file.
    }

    // sanity check for image size that's about to be decoded.
    {
        const int64_t size = sk_64_mul(features.width, features.height);
        if (!sk_64_isS32(size)) {
            return false;
        }
        // now check that if we are 4-bytes per pixel, we also don't overflow
        if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) {
            return false;
        }
    }

    if (info) {
        // FIXME: Is N32 the right type?
        // Is unpremul the right type? Clients of SkCodec may assume it's the
        // best type, when Skia currently cannot draw unpremul (and raster is faster
        // with premul).
        *info = SkImageInfo::Make(features.width, features.height, kN32_SkColorType,
                                  SkToBool(features.has_alpha) ? kUnpremul_SkAlphaType
                                                              : kOpaque_SkAlphaType);
    }
    return true;
}

SkCodec* SkWebpCodec::NewFromStream(SkStream* stream) {
    SkAutoTDelete<SkStream> streamDeleter(stream);
    SkImageInfo info;
    if (webp_parse_header(stream, &info)) {
        return new SkWebpCodec(info, streamDeleter.release());
    }
    return nullptr;
}

// This version is slightly different from SkCodecPriv's version of conversion_possible. It
// supports both byte orders for 8888.
static bool webp_conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
    if (dst.profileType() != src.profileType()) {
        return false;
    }

    if (!valid_alpha(dst.alphaType(), src.alphaType())) {
        return false;
    }

    switch (dst.colorType()) {
        // Both byte orders are supported.
        case kBGRA_8888_SkColorType:
        case kRGBA_8888_SkColorType:
            return true;
        case kRGB_565_SkColorType:
            return src.alphaType() == kOpaque_SkAlphaType;
        default:
            return false;
    }
}

SkISize SkWebpCodec::onGetScaledDimensions(float desiredScale) const {
    SkISize dim = this->getInfo().dimensions();
    // SkCodec treats zero dimensional images as errors, so the minimum size
    // that we will recommend is 1x1.
    dim.fWidth = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fWidth));
    dim.fHeight = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fHeight));
    return dim;
}

bool SkWebpCodec::onDimensionsSupported(const SkISize& dim) {
    const SkImageInfo& info = this->getInfo();
    return dim.width() >= 1 && dim.width() <= info.width()
            && dim.height() >= 1 && dim.height() <= info.height();
}

static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) {
    switch (ct) {
        case kBGRA_8888_SkColorType:
            return premultiply ? MODE_bgrA : MODE_BGRA;
        case kRGBA_8888_SkColorType:
            return premultiply ? MODE_rgbA : MODE_RGBA;
        case kRGB_565_SkColorType:
            return MODE_RGB_565;
        default:
            return MODE_LAST;
    }
}

// The WebP decoding API allows us to incrementally pass chunks of bytes as we receive them to the
// decoder with WebPIAppend. In order to do so, we need to read chunks from the SkStream. This size
// is arbitrary.
static const size_t BUFFER_SIZE = 4096;

bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const {
    if (!desiredSubset) {
        return false;
    }

    SkIRect dimensions  = SkIRect::MakeSize(this->getInfo().dimensions());
    if (!dimensions.contains(*desiredSubset)) {
        return false;
    }

    // As stated below, libwebp snaps to even left and top. Make sure top and left are even, so we
    // decode this exact subset.
    // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested.
    desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1;
    desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1;
    return true;
}

SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
                                         const Options& options, SkPMColor*, int*,
                                         int* rowsDecoded) {
    if (!webp_conversion_possible(dstInfo, this->getInfo())) {
        return kInvalidConversion;
    }

    WebPDecoderConfig config;
    if (0 == WebPInitDecoderConfig(&config)) {
        // ABI mismatch.
        // FIXME: New enum for this?
        return kInvalidInput;
    }

    // Free any memory associated with the buffer. Must be called last, so we declare it first.
    SkAutoTCallVProc<WebPDecBuffer, WebPFreeDecBuffer> autoFree(&(config.output));

    SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions());
    if (options.fSubset) {
        // Caller is requesting a subset.
        if (!bounds.contains(*options.fSubset)) {
            // The subset is out of bounds.
            return kInvalidParameters;
        }

        bounds = *options.fSubset;

        // This is tricky. libwebp snaps the top and left to even values. We could let libwebp
        // do the snap, and return a subset which is a different one than requested. The problem
        // with that approach is that the caller may try to stitch subsets together, and if we
        // returned different subsets than requested, there would be artifacts at the boundaries.
        // Instead, we report that we cannot support odd values for top and left..
        if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) {
            return kInvalidParameters;
        }

#ifdef SK_DEBUG
        {
            // Make a copy, since getValidSubset can change its input.
            SkIRect subset(bounds);
            // That said, getValidSubset should *not* change its input, in this case; otherwise
            // getValidSubset does not match the actual subsets we can do.
            SkASSERT(this->getValidSubset(&subset) && subset == bounds);
        }
#endif

        config.options.use_cropping = 1;
        config.options.crop_left = bounds.fLeft;
        config.options.crop_top = bounds.fTop;
        config.options.crop_width = bounds.width();
        config.options.crop_height = bounds.height();
    }

    SkISize dstDimensions = dstInfo.dimensions();
    if (bounds.size() != dstDimensions) {
        // Caller is requesting scaling.
        config.options.use_scaling = 1;
        config.options.scaled_width = dstDimensions.width();
        config.options.scaled_height = dstDimensions.height();
    }

    config.output.colorspace = webp_decode_mode(dstInfo.colorType(),
            dstInfo.alphaType() == kPremul_SkAlphaType);
    config.output.u.RGBA.rgba = (uint8_t*) dst;
    config.output.u.RGBA.stride = (int) rowBytes;
    config.output.u.RGBA.size = dstInfo.getSafeSize(rowBytes);
    config.output.is_external_memory = 1;

    SkAutoTCallVProc<WebPIDecoder, WebPIDelete> idec(WebPIDecode(nullptr, 0, &config));
    if (!idec) {
        return kInvalidInput;
    }

    SkAutoTMalloc<uint8_t> storage(BUFFER_SIZE);
    uint8_t* buffer = storage.get();
    while (true) {
        const size_t bytesRead = stream()->read(buffer, BUFFER_SIZE);
        if (0 == bytesRead) {
            WebPIDecGetRGB(idec, rowsDecoded, NULL, NULL, NULL);
            return kIncompleteInput;
        }

        switch (WebPIAppend(idec, buffer, bytesRead)) {
            case VP8_STATUS_OK:
                return kSuccess;
            case VP8_STATUS_SUSPENDED:
                // Break out of the switch statement. Continue the loop.
                break;
            default:
                return kInvalidInput;
        }
    }
}

SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream)
    : INHERITED(info, stream) {}
<commit_msg>Mark webps as sRGB<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCodecPriv.h"
#include "SkWebpCodec.h"
#include "SkTemplates.h"

// A WebP decoder on top of (subset of) libwebp
// For more information on WebP image format, and libwebp library, see:
//   https://code.google.com/speed/webp/
//   http://www.webmproject.org/code/#libwebp-webp-image-library
//   https://chromium.googlesource.com/webm/libwebp

// If moving libwebp out of skia source tree, path for webp headers must be
// updated accordingly. Here, we enforce using local copy in webp sub-directory.
#include "webp/decode.h"
#include "webp/encode.h"

bool SkWebpCodec::IsWebp(const void* buf, size_t bytesRead) {
    // WEBP starts with the following:
    // RIFFXXXXWEBPVP
    // Where XXXX is unspecified.
    const char* bytes = static_cast<const char*>(buf);
    return bytesRead >= 14 && !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6);
}

// Parse headers of RIFF container, and check for valid Webp (VP8) content.
// NOTE: This calls peek instead of read, since onGetPixels will need these
// bytes again.
static bool webp_parse_header(SkStream* stream, SkImageInfo* info) {
    unsigned char buffer[WEBP_VP8_HEADER_SIZE];
    SkASSERT(WEBP_VP8_HEADER_SIZE <= SkCodec::MinBufferedBytesNeeded());

    const size_t bytesPeeked = stream->peek(buffer, WEBP_VP8_HEADER_SIZE);
    if (bytesPeeked != WEBP_VP8_HEADER_SIZE) {
        // Use read + rewind as a backup
        if (stream->read(buffer, WEBP_VP8_HEADER_SIZE) != WEBP_VP8_HEADER_SIZE
            || !stream->rewind())
        return false;
    }

    WebPBitstreamFeatures features;
    VP8StatusCode status = WebPGetFeatures(buffer, WEBP_VP8_HEADER_SIZE, &features);
    if (VP8_STATUS_OK != status) {
        return false; // Invalid WebP file.
    }

    // sanity check for image size that's about to be decoded.
    {
        const int64_t size = sk_64_mul(features.width, features.height);
        if (!sk_64_isS32(size)) {
            return false;
        }
        // now check that if we are 4-bytes per pixel, we also don't overflow
        if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) {
            return false;
        }
    }

    if (info) {
        // FIXME: Is N32 the right type?
        // Is unpremul the right type? Clients of SkCodec may assume it's the
        // best type, when Skia currently cannot draw unpremul (and raster is faster
        // with premul).
        *info = SkImageInfo::Make(features.width, features.height, kN32_SkColorType,
                                  SkToBool(features.has_alpha) ? kUnpremul_SkAlphaType
                                                              : kOpaque_SkAlphaType);
    }
    return true;
}

SkCodec* SkWebpCodec::NewFromStream(SkStream* stream) {
    SkAutoTDelete<SkStream> streamDeleter(stream);
    SkImageInfo info;
    if (webp_parse_header(stream, &info)) {
        return new SkWebpCodec(info, streamDeleter.release());
    }
    return nullptr;
}

// This version is slightly different from SkCodecPriv's version of conversion_possible. It
// supports both byte orders for 8888.
static bool webp_conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
    // FIXME: skbug.com/4895
    // Currently, we ignore the SkColorProfileType on the SkImageInfo.  We
    // will treat the encoded data as linear regardless of what the client
    // requests.

    if (!valid_alpha(dst.alphaType(), src.alphaType())) {
        return false;
    }

    switch (dst.colorType()) {
        // Both byte orders are supported.
        case kBGRA_8888_SkColorType:
        case kRGBA_8888_SkColorType:
            return true;
        case kRGB_565_SkColorType:
            return src.alphaType() == kOpaque_SkAlphaType;
        default:
            return false;
    }
}

SkISize SkWebpCodec::onGetScaledDimensions(float desiredScale) const {
    SkISize dim = this->getInfo().dimensions();
    // SkCodec treats zero dimensional images as errors, so the minimum size
    // that we will recommend is 1x1.
    dim.fWidth = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fWidth));
    dim.fHeight = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fHeight));
    return dim;
}

bool SkWebpCodec::onDimensionsSupported(const SkISize& dim) {
    const SkImageInfo& info = this->getInfo();
    return dim.width() >= 1 && dim.width() <= info.width()
            && dim.height() >= 1 && dim.height() <= info.height();
}

static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) {
    switch (ct) {
        case kBGRA_8888_SkColorType:
            return premultiply ? MODE_bgrA : MODE_BGRA;
        case kRGBA_8888_SkColorType:
            return premultiply ? MODE_rgbA : MODE_RGBA;
        case kRGB_565_SkColorType:
            return MODE_RGB_565;
        default:
            return MODE_LAST;
    }
}

// The WebP decoding API allows us to incrementally pass chunks of bytes as we receive them to the
// decoder with WebPIAppend. In order to do so, we need to read chunks from the SkStream. This size
// is arbitrary.
static const size_t BUFFER_SIZE = 4096;

bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const {
    if (!desiredSubset) {
        return false;
    }

    SkIRect dimensions  = SkIRect::MakeSize(this->getInfo().dimensions());
    if (!dimensions.contains(*desiredSubset)) {
        return false;
    }

    // As stated below, libwebp snaps to even left and top. Make sure top and left are even, so we
    // decode this exact subset.
    // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested.
    desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1;
    desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1;
    return true;
}

SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
                                         const Options& options, SkPMColor*, int*,
                                         int* rowsDecoded) {
    if (!webp_conversion_possible(dstInfo, this->getInfo())) {
        return kInvalidConversion;
    }

    WebPDecoderConfig config;
    if (0 == WebPInitDecoderConfig(&config)) {
        // ABI mismatch.
        // FIXME: New enum for this?
        return kInvalidInput;
    }

    // Free any memory associated with the buffer. Must be called last, so we declare it first.
    SkAutoTCallVProc<WebPDecBuffer, WebPFreeDecBuffer> autoFree(&(config.output));

    SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions());
    if (options.fSubset) {
        // Caller is requesting a subset.
        if (!bounds.contains(*options.fSubset)) {
            // The subset is out of bounds.
            return kInvalidParameters;
        }

        bounds = *options.fSubset;

        // This is tricky. libwebp snaps the top and left to even values. We could let libwebp
        // do the snap, and return a subset which is a different one than requested. The problem
        // with that approach is that the caller may try to stitch subsets together, and if we
        // returned different subsets than requested, there would be artifacts at the boundaries.
        // Instead, we report that we cannot support odd values for top and left..
        if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) {
            return kInvalidParameters;
        }

#ifdef SK_DEBUG
        {
            // Make a copy, since getValidSubset can change its input.
            SkIRect subset(bounds);
            // That said, getValidSubset should *not* change its input, in this case; otherwise
            // getValidSubset does not match the actual subsets we can do.
            SkASSERT(this->getValidSubset(&subset) && subset == bounds);
        }
#endif

        config.options.use_cropping = 1;
        config.options.crop_left = bounds.fLeft;
        config.options.crop_top = bounds.fTop;
        config.options.crop_width = bounds.width();
        config.options.crop_height = bounds.height();
    }

    SkISize dstDimensions = dstInfo.dimensions();
    if (bounds.size() != dstDimensions) {
        // Caller is requesting scaling.
        config.options.use_scaling = 1;
        config.options.scaled_width = dstDimensions.width();
        config.options.scaled_height = dstDimensions.height();
    }

    config.output.colorspace = webp_decode_mode(dstInfo.colorType(),
            dstInfo.alphaType() == kPremul_SkAlphaType);
    config.output.u.RGBA.rgba = (uint8_t*) dst;
    config.output.u.RGBA.stride = (int) rowBytes;
    config.output.u.RGBA.size = dstInfo.getSafeSize(rowBytes);
    config.output.is_external_memory = 1;

    SkAutoTCallVProc<WebPIDecoder, WebPIDelete> idec(WebPIDecode(nullptr, 0, &config));
    if (!idec) {
        return kInvalidInput;
    }

    SkAutoTMalloc<uint8_t> storage(BUFFER_SIZE);
    uint8_t* buffer = storage.get();
    while (true) {
        const size_t bytesRead = stream()->read(buffer, BUFFER_SIZE);
        if (0 == bytesRead) {
            WebPIDecGetRGB(idec, rowsDecoded, NULL, NULL, NULL);
            return kIncompleteInput;
        }

        switch (WebPIAppend(idec, buffer, bytesRead)) {
            case VP8_STATUS_OK:
                return kSuccess;
            case VP8_STATUS_SUSPENDED:
                // Break out of the switch statement. Continue the loop.
                break;
            default:
                return kInvalidInput;
        }
    }
}

SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream)
    // The spec says an unmarked image is sRGB, so we return that space here.
    // TODO: Add support for parsing ICC profiles from webps.
    : INHERITED(info, stream, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)) {}
<|endoftext|>


<commit_before>/*
 NUI3 - C++ cross-platform GUI framework for OpenGL based applications
 Copyright (C) 2002-2003 Sebastien Metrot & Vincent Caron

 licence: see nui3/LICENCE.TXT
 */

#include "nui.h"
#include "nuiChunkSampleReader.h"

#define CHUNK_ID_BYTES 4
#define CHUNK_SIZE_BYTES 4
#define CHUNK_HEADER_BYTES (CHUNK_ID_BYTES + CHUNK_SIZE_BYTES)
#define FIRST_CHUNK_DATA_BYTES 4 //4 bytes to represent RIFF type (WAVE, AIFF...)
//
//
//nuiChunkSampleReader
//
//

nuiChunkSampleReader::nuiChunkSampleReader(nglIStream& rStream) :
nuiSampleReader(rStream)
{
}

nuiChunkSampleReader::nuiChunkSampleReader(const nuiChunkSampleReader& rReader, nglIStream& rStream) :
nuiSampleReader(rReader, rStream)
{
  for (uint32 i = 0; i < rReader.mChunks.size(); i++)
  {
    Chunk* pChunk = new Chunk(rReader.mChunks[i]->mPosition, rReader.mChunks[i]->mDataSize, rReader.mChunks[i]->mDataPosition, rReader.mChunks[i]->mId);
    mChunks.push_back(pChunk);
  }
}

nuiChunkSampleReader::~nuiChunkSampleReader()
{
  ClearChunks();
}

bool nuiChunkSampleReader::GoToChunk(char* pId)
{
  bool found = false;
  uint32 index = 0;
  for (uint32 i = 0; i < mChunks.size() && !found; i++)
  {
    found = mChunks[i]->CompareId(pId);
    if (found)
      index = i;
  }

  if (found)
  {
    //Set Stream position
    nglFileOffset pos = mChunks[index]->mDataPosition;
    mrStream.SetPos(pos);
  }

  return found;
}

nuiChunkSampleReader::Chunk* nuiChunkSampleReader::GetChunk(char* Id)
{
  bool found = false;
  uint32 index = 0;
  for (uint32 i = 0; i < mChunks.size() && !found; i++)
  {
    found = mChunks[i]->CompareId(Id);
    if (found)
      index = i;
  }

  if (found)
  {
    Chunk* pChunk = mChunks[index];
    return pChunk;
  }

  return NULL;
}

bool nuiChunkSampleReader::ScanAllChunks()
{
  ClearChunks();

  /////////////
  //FIRST CHUNK
  mrStream.SetPos(0);

  //get Id
  //std::vector<char> Id(4);
  char* Id = new char[5];
  for(uint32 k = 0; k < 4; k++)
  {
    if( 1 != mrStream.ReadUInt8((uint8*)&(Id[k]), 1))
      return false;
  }
  Id[4] = '\0';
  //get first chunk size
  uint32 utilSize = 0; // = (total size of the stream) - (first chunk header size)
  if (1 != mrStream.ReadUInt32(&utilSize, 1))
    return false;
  uint32 firstChunkSize = FIRST_CHUNK_DATA_BYTES;

  Chunk* pFirstChunk = new Chunk(0, firstChunkSize, CHUNK_HEADER_BYTES, Id);
  mChunks.push_back(pFirstChunk);
  nglFileOffset TotalSize = CHUNK_HEADER_BYTES  + firstChunkSize + utilSize;

  do
  {
    ////////////
    //NEXT CHUNK
    nglFileOffset ChunkPosition = mChunks.back()->mDataPosition + mChunks.back()->mDataSize;
    mrStream.SetPos(ChunkPosition);
    uint32 ChunkSize = 0;
    for(uint32 k = 0; k < 4; k++)
    {
      if( 1 != mrStream.ReadUInt8((uint8*)&(Id[k]), 1))
        return false;
    }
    //get chunk size
    if (1 != mrStream.ReadUInt32(&ChunkSize, 1))
      return false;
    if (0 != ChunkSize % 2)
          ChunkSize += 1; // the chunk size is always even
    Chunk* pNextChunk = new Chunk(ChunkPosition, ChunkSize, ChunkPosition + CHUNK_HEADER_BYTES, Id);
    mChunks.push_back(pNextChunk);
  }
  while (mChunks.back()->mDataPosition + mChunks.back()->mDataSize < TotalSize);

  delete[] Id;
  return true;
}

void nuiChunkSampleReader::ClearChunks()
{
  for (uint32 i = 0; i < mChunks.size(); i++)
  {
    delete mChunks[i];
    mChunks[i] = NULL;
  }
  mChunks.clear();
}

uint32 nuiChunkSampleReader::ReadDE(std::vector<void*> buffers, uint32 sampleframes, nuiSampleBitFormat format)
{
  //don't increment mPosition: it's already done in ReadIN
  const uint32 channels = mInfo.GetChannels();
  uint32 length = mInfo.GetSampleFrames();
  if (mPosition >= length)
    return 0;
  sampleframes = MIN(sampleframes, length - mPosition);

  if (buffers.size() != channels)
  {
    return 0;
  }

  bool deleteBuffer = false;
  uint32 SampleFramesRead = 0;
  switch (format)
  {
    case eSampleFloat32:
    {
      float* pFloatBuffer = NULL;
      if (channels == 1)
      {
        pFloatBuffer = (float*)(buffers[0]);
        deleteBuffer = false;
      }
      else
      {
        pFloatBuffer = new float[sampleframes * channels];
        deleteBuffer = true;
      }

      SampleFramesRead = ReadIN((void*)pFloatBuffer, sampleframes, format); //mPosition is incremented inside
      for (uint32 s = 0; s < SampleFramesRead; s++)
      {
        for (uint32 c = 0; c < channels; c++)
        {
          float* pDest = (float*)buffers[c];
          pDest[s] = pFloatBuffer[channels * s + c];
        }
      }
      if (deleteBuffer)
        delete[] pFloatBuffer;
    }
      break;

    case eSampleInt16:
    {
      int16* pIntBuffer = NULL;
      if (channels == 1)
      {
        pIntBuffer = (int16*)(buffers[0]);
        deleteBuffer = false;
      }
      else
      {
        pIntBuffer = new int16[sampleframes * channels];
        deleteBuffer = true;
      }

      SampleFramesRead = ReadIN((void*)pIntBuffer, sampleframes, format);//mPosition is incremented inside
      for (uint32 s = 0; s < SampleFramesRead; s++)
      {
        for (uint32 c = 0; c < channels; c++)
        {
            ((int16*)(buffers[c]))[s] = pIntBuffer[channels * s + c];
        }
      }
      if (deleteBuffer)
        delete[] pIntBuffer;
    }
      break;

    default:
      break;
  }

  //don't increment mPosition: it's already done in ReadIN
  return SampleFramesRead;
}

//
//
//Chunk
//
//
nuiChunkSampleReader::Chunk::Chunk():
mPosition(0),
mDataSize(0),
mDataPosition(0),
mId(NULL)
{
}

nuiChunkSampleReader::Chunk::Chunk(nglFileOffset position, nglFileOffset dataSize, nglFileOffset dataPosition, const char* Id):
mPosition(position),
mDataSize(dataSize),
mDataPosition(dataPosition),
mId(NULL)
{
  if (Id)
  {
    mId = new char[strlen(Id) + 1];
    char* res = strcpy(mId, Id);
    int i = 0;
  }
}

nuiChunkSampleReader::Chunk::~Chunk()
{
  if (mId)
  {
    delete[] mId;
    mId = NULL;
  }
}

bool nuiChunkSampleReader::Chunk::CompareId(const char* Id) const
{
  const int compare = strcmp(mId, Id);
  return (compare == 0);
}

<commit_msg>fixed memory leak in nuiChunkSampleReader (from meeloo)<commit_after>/*
 NUI3 - C++ cross-platform GUI framework for OpenGL based applications
 Copyright (C) 2002-2003 Sebastien Metrot & Vincent Caron

 licence: see nui3/LICENCE.TXT
 */

#include "nui.h"
#include "nuiChunkSampleReader.h"

#define CHUNK_ID_BYTES 4
#define CHUNK_SIZE_BYTES 4
#define CHUNK_HEADER_BYTES (CHUNK_ID_BYTES + CHUNK_SIZE_BYTES)
#define FIRST_CHUNK_DATA_BYTES 4 //4 bytes to represent RIFF type (WAVE, AIFF...)
//
//
//nuiChunkSampleReader
//
//

nuiChunkSampleReader::nuiChunkSampleReader(nglIStream& rStream) :
nuiSampleReader(rStream)
{
}

nuiChunkSampleReader::nuiChunkSampleReader(const nuiChunkSampleReader& rReader, nglIStream& rStream) :
nuiSampleReader(rReader, rStream)
{
  for (uint32 i = 0; i < rReader.mChunks.size(); i++)
  {
    Chunk* pChunk = new Chunk(rReader.mChunks[i]->mPosition, rReader.mChunks[i]->mDataSize, rReader.mChunks[i]->mDataPosition, rReader.mChunks[i]->mId);
    mChunks.push_back(pChunk);
  }
}

nuiChunkSampleReader::~nuiChunkSampleReader()
{
  ClearChunks();
}

bool nuiChunkSampleReader::GoToChunk(char* pId)
{
  bool found = false;
  uint32 index = 0;
  for (uint32 i = 0; i < mChunks.size() && !found; i++)
  {
    found = mChunks[i]->CompareId(pId);
    if (found)
      index = i;
  }

  if (found)
  {
    //Set Stream position
    nglFileOffset pos = mChunks[index]->mDataPosition;
    mrStream.SetPos(pos);
  }

  return found;
}

nuiChunkSampleReader::Chunk* nuiChunkSampleReader::GetChunk(char* Id)
{
  bool found = false;
  uint32 index = 0;
  for (uint32 i = 0; i < mChunks.size() && !found; i++)
  {
    found = mChunks[i]->CompareId(Id);
    if (found)
      index = i;
  }

  if (found)
  {
    Chunk* pChunk = mChunks[index];
    return pChunk;
  }

  return NULL;
}

bool nuiChunkSampleReader::ScanAllChunks()
{
  ClearChunks();

  /////////////
  //FIRST CHUNK
  mrStream.SetPos(0);

  //get Id
  //std::vector<char> Id(4);
  char* Id = new char[5];
  for(uint32 k = 0; k < 4; k++)
  {
    if( 1 != mrStream.ReadUInt8((uint8*)&(Id[k]), 1))
    {
      delete[] Id;
      return false;
    }
  }
  Id[4] = '\0';
  //get first chunk size
  uint32 utilSize = 0; // = (total size of the stream) - (first chunk header size)
  if (1 != mrStream.ReadUInt32(&utilSize, 1))
  {
    delete[] Id;
    return false;
  }
  uint32 firstChunkSize = FIRST_CHUNK_DATA_BYTES;

  Chunk* pFirstChunk = new Chunk(0, firstChunkSize, CHUNK_HEADER_BYTES, Id);
  mChunks.push_back(pFirstChunk);
  nglFileOffset TotalSize = CHUNK_HEADER_BYTES  + firstChunkSize + utilSize;

  do
  {
    ////////////
    //NEXT CHUNK
    nglFileOffset ChunkPosition = mChunks.back()->mDataPosition + mChunks.back()->mDataSize;
    mrStream.SetPos(ChunkPosition);
    uint32 ChunkSize = 0;
    for(uint32 k = 0; k < 4; k++)
    {
      if( 1 != mrStream.ReadUInt8((uint8*)&(Id[k]), 1))
      {
        delete[] Id;
        return false;
      }
    }
    //get chunk size
    if (1 != mrStream.ReadUInt32(&ChunkSize, 1))
    {
      delete[] Id;
      return false;
    }
    if (0 != ChunkSize % 2)
          ChunkSize += 1; // the chunk size is always even
    Chunk* pNextChunk = new Chunk(ChunkPosition, ChunkSize, ChunkPosition + CHUNK_HEADER_BYTES, Id);
    mChunks.push_back(pNextChunk);
  }
  while (mChunks.back()->mDataPosition + mChunks.back()->mDataSize < TotalSize);

  delete[] Id;
  return true;
}

void nuiChunkSampleReader::ClearChunks()
{
  for (uint32 i = 0; i < mChunks.size(); i++)
  {
    delete mChunks[i];
    mChunks[i] = NULL;
  }
  mChunks.clear();
}

uint32 nuiChunkSampleReader::ReadDE(std::vector<void*> buffers, uint32 sampleframes, nuiSampleBitFormat format)
{
  //don't increment mPosition: it's already done in ReadIN
  const uint32 channels = mInfo.GetChannels();
  uint32 length = mInfo.GetSampleFrames();
  if (mPosition >= length)
    return 0;
  sampleframes = MIN(sampleframes, length - mPosition);

  if (buffers.size() != channels)
  {
    return 0;
  }

  bool deleteBuffer = false;
  uint32 SampleFramesRead = 0;
  switch (format)
  {
    case eSampleFloat32:
    {
      float* pFloatBuffer = NULL;
      if (channels == 1)
      {
        pFloatBuffer = (float*)(buffers[0]);
        deleteBuffer = false;
      }
      else
      {
        pFloatBuffer = new float[sampleframes * channels];
        deleteBuffer = true;
      }

      SampleFramesRead = ReadIN((void*)pFloatBuffer, sampleframes, format); //mPosition is incremented inside
      for (uint32 s = 0; s < SampleFramesRead; s++)
      {
        for (uint32 c = 0; c < channels; c++)
        {
          float* pDest = (float*)buffers[c];
          pDest[s] = pFloatBuffer[channels * s + c];
        }
      }
      if (deleteBuffer)
        delete[] pFloatBuffer;
    }
      break;

    case eSampleInt16:
    {
      int16* pIntBuffer = NULL;
      if (channels == 1)
      {
        pIntBuffer = (int16*)(buffers[0]);
        deleteBuffer = false;
      }
      else
      {
        pIntBuffer = new int16[sampleframes * channels];
        deleteBuffer = true;
      }

      SampleFramesRead = ReadIN((void*)pIntBuffer, sampleframes, format);//mPosition is incremented inside
      for (uint32 s = 0; s < SampleFramesRead; s++)
      {
        for (uint32 c = 0; c < channels; c++)
        {
            ((int16*)(buffers[c]))[s] = pIntBuffer[channels * s + c];
        }
      }
      if (deleteBuffer)
        delete[] pIntBuffer;
    }
      break;

    default:
      break;
  }

  //don't increment mPosition: it's already done in ReadIN
  return SampleFramesRead;
}

//
//
//Chunk
//
//
nuiChunkSampleReader::Chunk::Chunk():
mPosition(0),
mDataSize(0),
mDataPosition(0),
mId(NULL)
{
}

nuiChunkSampleReader::Chunk::Chunk(nglFileOffset position, nglFileOffset dataSize, nglFileOffset dataPosition, const char* Id):
mPosition(position),
mDataSize(dataSize),
mDataPosition(dataPosition),
mId(NULL)
{
  if (Id)
  {
    mId = new char[strlen(Id) + 1];
    char* res = strcpy(mId, Id);
    int i = 0;
  }
}

nuiChunkSampleReader::Chunk::~Chunk()
{
  if (mId)
  {
    delete[] mId;
    mId = NULL;
  }
}

bool nuiChunkSampleReader::Chunk::CompareId(const char* Id) const
{
  const int compare = strcmp(mId, Id);
  return (compare == 0);
}

<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// bzflag common header
#include "common.h"

// class interface header
#include "URLManager.h"
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif

// system headers
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

bool URLManager::getURL(const std::string URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#ifdef HAVE_CURL
  CURLcode curlResult;
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
#endif
}

URLManager::~URLManager()
{
  clearInternal();

#ifdef HAVE_CURL
  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);
  curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

#ifdef HAVE_CURL
bool URLManager::beginGet(const std::string URL)
#else
bool URLManager::beginGet(const std::string)
#endif
{
#ifdef HAVE_CURL
  CURLcode result;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
#else
  return false;
#endif // HAVE_CURL
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}
#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>if the timeout is reached, default curl behavior is to throw a SIGALRM.  this happens on Mac OS X regardless (there was list chatter hinting at it being multithreaded related (which cocoa apps are)) so we need to enable another option that disables throwing the signal.  This requires curl 7.10 so may need some version wrapping if older versions are in common use.<commit_after>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// bzflag common header
#include "common.h"

// class interface header
#include "URLManager.h"
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif

// system headers
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);
#endif // HAVE_CURL

bool URLManager::getURL(const std::string URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#ifdef HAVE_CURL
  CURLcode curlResult;
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
#endif
}

URLManager::~URLManager()
{
  clearInternal();

#ifdef HAVE_CURL
  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);
  curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

#ifdef HAVE_CURL
bool URLManager::beginGet(const std::string URL)
#else
bool URLManager::beginGet(const std::string)
#endif
{
#ifdef HAVE_CURL
  CURLcode result = 0;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
#else
  return false;
#endif // HAVE_CURL
}

#ifdef HAVE_CURL
static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}
#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <mesos/mesos.hpp>
#include <mesos/resources.hpp>

#include "common/attributes.hpp"
#include "common/type_utils.hpp"

namespace mesos {

bool operator == (const Environment& left, const Environment& right)
{
  if (left.variables().size() != right.variables().size()) {
    return false;
  }

  for (int i = 0; i < left.variables().size(); i++) {
    const std::string& name = left.variables().Get(i).name();
    const std::string& value = left.variables().Get(i).value();
    bool found = false;
    for (int j = 0; j < right.variables().size(); j++) {
      if (name == right.variables().Get(j).name() &&
          value == right.variables().Get(j).value()) {
        found = true;
        break;
      }
    }
    if (!found) {
      return false;
    }
  }

  return true;
}

bool operator == (const CommandInfo& left, const CommandInfo& right)
{
  if (left.uris().size() != right.uris().size()) {
    return false;
  }

  for (int i=0; i<left.uris().size(); i++) {
    bool found = false;
    for (int j=0; j<right.uris().size(); j++) {
      if (left.uris().Get(i) == right.uris().Get(j)) {
        found = true;
        break;
      }
    }
    if (!found) {
      return false;
    }
  }

  return left.has_environment() == right.has_environment() &&
    (!left.has_environment() || (left.environment() == right.environment())) &&
    left.value() == right.value();
}

bool operator == (const ExecutorInfo& left, const ExecutorInfo& right)
{
  return left.executor_id() == right.executor_id() &&
    left.has_framework_id() == right.has_framework_id() &&
    (!left.has_framework_id() ||
    (left.framework_id() == right.framework_id())) &&
    left.command() == right.command() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    left.has_name() == right.has_name() &&
    (!left.has_name() || (left.name() == right.name())) &&
    left.has_source() == right.has_source() &&
    (!left.has_source() || (left.source() == right.source())) &&
    left.has_data() == right.has_data() &&
    (!left.has_data() || (left.data() == right.data()));
}

bool operator == (const SlaveInfo& left, const SlaveInfo& right)
{
  // NOTE: We don't compare 'webui_hostname' and 'webui_port' since
  // they're deprecated and do not carry any semantic meaning.
  return left.hostname() == right.hostname() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    internal::Attributes(left.attributes()) ==
    internal::Attributes(right.attributes()) &&
    left.has_id() == right.has_id() &&
    (!left.has_id() || (left.id() == right.id())) &&
    left.has_checkpoint() == right.has_checkpoint() &&
    (!left.has_checkpoint() || (left.checkpoint() == right.checkpoint()));
}

bool operator == (const MasterInfo& left, const MasterInfo& right)
{
  return left.id() == right.id() &&
    left.ip() == right.ip() &&
    left.port() == right.port() &&
    left.has_pid() == right.has_pid() &&
    (!left.has_pid() || (left.pid() == right.pid())) &&
    left.has_hostname() == right.has_hostname() &&
    (!left.has_hostname() || (left.hostname() == right.hostname()));
}

namespace internal {

bool operator == (const Task& left, const Task& right)
{
  return left.name() == right.name() &&
    left.task_id() == right.task_id() &&
    left.framework_id() == right.framework_id() &&
    left.slave_id() == right.slave_id() &&
    left.state() == right.state() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    left.has_executor_id() == right.has_executor_id() &&
    (!left.has_executor_id() || (left.executor_id() == right.executor_id()));
}

std::ostream& operator << (
    std::ostream& stream,
    const StatusUpdate& update)
{
  stream
    << update.status().state()
    << " (UUID: " << UUID::fromBytes(update.uuid())
    << ") for task " << update.status().task_id();

  if (update.status().has_healthy()) {
    stream
      << " in health state "
      << (update.status().healthy() ? "healthy" : "unhealthy");
  }

  return stream
    << " of framework " << update.framework_id();
}

} // namespace internal {

} // namespace mesos {
<commit_msg>Updated equality check for CommandInfo.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <mesos/mesos.hpp>
#include <mesos/resources.hpp>

#include "common/attributes.hpp"
#include "common/type_utils.hpp"

namespace mesos {

bool operator == (const Environment& left, const Environment& right)
{
  if (left.variables().size() != right.variables().size()) {
    return false;
  }

  for (int i = 0; i < left.variables().size(); i++) {
    const std::string& name = left.variables().Get(i).name();
    const std::string& value = left.variables().Get(i).value();
    bool found = false;
    for (int j = 0; j < right.variables().size(); j++) {
      if (name == right.variables().Get(j).name() &&
          value == right.variables().Get(j).value()) {
        found = true;
        break;
      }
    }
    if (!found) {
      return false;
    }
  }

  return true;
}

bool operator == (const CommandInfo& left, const CommandInfo& right)
{
  if (left.uris().size() != right.uris().size()) {
    return false;
  }

  for (int i = 0; i < left.uris().size(); i++) {
    bool found = false;
    for (int j = 0; j < right.uris().size(); j++) {
      if (left.uris().Get(i) == right.uris().Get(j)) {
        found = true;
        break;
      }
    }
    if (!found) {
      return false;
    }
  }

  if (left.argv().size() != right.argv().size()) {
    return false;
  }

  // The order of argv is important.
  for (int i = 0; i < left.argv().size(); i++) {
    if (left.argv().Get(i) != right.argv().Get(i)) {
      return false;
    }
  }

  return left.has_environment() == right.has_environment() &&
    (!left.has_environment() || (left.environment() == right.environment())) &&
    left.has_value() == right.has_value() &&
    (!left.has_value() || (left.value() == right.value())) &&
    left.has_shell() == right.has_shell() &&
    (!left.has_shell() || (left.shell() == right.shell()));
}

bool operator == (const ExecutorInfo& left, const ExecutorInfo& right)
{
  return left.executor_id() == right.executor_id() &&
    left.has_framework_id() == right.has_framework_id() &&
    (!left.has_framework_id() ||
    (left.framework_id() == right.framework_id())) &&
    left.command() == right.command() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    left.has_name() == right.has_name() &&
    (!left.has_name() || (left.name() == right.name())) &&
    left.has_source() == right.has_source() &&
    (!left.has_source() || (left.source() == right.source())) &&
    left.has_data() == right.has_data() &&
    (!left.has_data() || (left.data() == right.data()));
}

bool operator == (const SlaveInfo& left, const SlaveInfo& right)
{
  // NOTE: We don't compare 'webui_hostname' and 'webui_port' since
  // they're deprecated and do not carry any semantic meaning.
  return left.hostname() == right.hostname() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    internal::Attributes(left.attributes()) ==
    internal::Attributes(right.attributes()) &&
    left.has_id() == right.has_id() &&
    (!left.has_id() || (left.id() == right.id())) &&
    left.has_checkpoint() == right.has_checkpoint() &&
    (!left.has_checkpoint() || (left.checkpoint() == right.checkpoint()));
}

bool operator == (const MasterInfo& left, const MasterInfo& right)
{
  return left.id() == right.id() &&
    left.ip() == right.ip() &&
    left.port() == right.port() &&
    left.has_pid() == right.has_pid() &&
    (!left.has_pid() || (left.pid() == right.pid())) &&
    left.has_hostname() == right.has_hostname() &&
    (!left.has_hostname() || (left.hostname() == right.hostname()));
}

namespace internal {

bool operator == (const Task& left, const Task& right)
{
  return left.name() == right.name() &&
    left.task_id() == right.task_id() &&
    left.framework_id() == right.framework_id() &&
    left.slave_id() == right.slave_id() &&
    left.state() == right.state() &&
    Resources(left.resources()) == Resources(right.resources()) &&
    left.has_executor_id() == right.has_executor_id() &&
    (!left.has_executor_id() || (left.executor_id() == right.executor_id()));
}

std::ostream& operator << (
    std::ostream& stream,
    const StatusUpdate& update)
{
  stream
    << update.status().state()
    << " (UUID: " << UUID::fromBytes(update.uuid())
    << ") for task " << update.status().task_id();

  if (update.status().has_healthy()) {
    stream
      << " in health state "
      << (update.status().healthy() ? "healthy" : "unhealthy");
  }

  return stream
    << " of framework " << update.framework_id();
}

} // namespace internal {

} // namespace mesos {
<|endoftext|>