<commit_before>#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <utility>
#include <stdexcept>
#include <string.h>
#include <algorithm>

#include <xf86drm.h>
#include <xf86drmMode.h>

#include "kms++.h"

#ifndef DRM_CLIENT_CAP_ATOMIC
#define DRM_CLIENT_CAP_ATOMIC 3
#endif

using namespace std;

namespace kms
{

Card::Card()
{
	const char *card = "/dev/dri/card0";

	int fd = open(card, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		throw invalid_argument(string(strerror(errno)) + " opening " +
				       card);
	m_fd = fd;

	int r;

	r = drmSetMaster(fd);
	m_master = r == 0;

	r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
	m_has_universal_planes = r == 0;

	r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1);
	m_has_atomic = r == 0;

	uint64_t has_dumb;
	r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
	if (r || !has_dumb)
		throw invalid_argument("Dumb buffers not available");

	auto res = drmModeGetResources(m_fd);
	if (!res)
		throw invalid_argument("Can't get card resources");

	for (int i = 0; i < res->count_connectors; ++i) {
		uint32_t id = res->connectors[i];
		m_obmap[id] = new Connector(*this, id, i);
	}

	for (int i = 0; i < res->count_crtcs; ++i) {
		uint32_t id = res->crtcs[i];
		m_obmap[id] = new Crtc(*this, id, i);
	}

	for (int i = 0; i < res->count_encoders; ++i) {
		uint32_t id = res->encoders[i];
		m_obmap[id] = new Encoder(*this, id);
	}

	drmModeFreeResources(res);

	auto planeRes = drmModeGetPlaneResources(m_fd);

	for (uint i = 0; i < planeRes->count_planes; ++i) {
		uint32_t id = planeRes->planes[i];
		m_obmap[id] = new Plane(*this, id);
	}

	drmModeFreePlaneResources(planeRes);

	// collect all possible props
	for (auto ob : get_objects()) {
		auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type());

		if (props == nullptr)
			continue;

		for (unsigned i = 0; i < props->count_props; ++i) {
			uint32_t prop_id = props->props[i];

			if (m_obmap.find(prop_id) == m_obmap.end())
				m_obmap[prop_id] = new Property(*this, prop_id);
		}

		drmModeFreeObjectProperties(props);
	}

	for (auto pair : m_obmap)
		pair.second->setup();
}

Card::~Card()
{
	for (auto pair : m_obmap)
		delete pair.second;

	close(m_fd);
}

template <class T> static void print_obs(const map<uint32_t, DrmObject*>& obmap)
{
	for (auto pair : obmap) {
		auto ob = pair.second;
		if (dynamic_cast<T*>(ob)) {
			ob->print_short();
			//ob->print_props();
		}
	}
}

void Card::print_short() const
{
	print_obs<Connector>(m_obmap);
	print_obs<Encoder>(m_obmap);
	print_obs<Crtc>(m_obmap);
	print_obs<Plane>(m_obmap);
}

Property* Card::get_prop(const char *name) const
{
	for (auto pair : m_obmap) {
		auto prop = dynamic_cast<Property*>(pair.second);
		if (!prop)
			continue;

		if (strcmp(name, prop->name()) == 0)
			return prop;
	}

	throw invalid_argument(string("Card property ") + name + " not found");
}

Connector* Card::get_first_connected_connector() const
{
	for(auto pair : m_obmap) {
		auto c = dynamic_cast<Connector*>(pair.second);

		if (c && c->connected())
			return c;
	}

	throw invalid_argument("no connected connectors");
}

DrmObject* Card::get_object(uint32_t id) const
{
	return m_obmap.at(id);
}

vector<Connector*> Card::get_connectors() const
{
	vector<Connector*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Connector*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<Plane*> Card::get_planes() const
{
	vector<Plane*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Plane*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<DrmObject*> Card::get_objects() const
{
	vector<DrmObject*> v;
	for(auto pair : m_obmap)
		v.push_back(pair.second);
	return v;
}

Crtc* Card::get_crtc_by_index(uint32_t idx) const
{
	for(auto pair : m_obmap) {
		auto crtc = dynamic_cast<Crtc*>(pair.second);
		if (crtc && crtc->idx() == idx)
			return crtc;
	}
	throw invalid_argument(string("Crtc #") + to_string(idx) + "not found");
}

Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast<Crtc*>(get_object(id)); }
Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast<Encoder*>(get_object(id)); }
Property* Card::get_prop(uint32_t id) const { return dynamic_cast<Property*>(get_object(id)); }

std::vector<kms::Pipeline> Card::get_connected_pipelines()
{
	vector<Pipeline> outputs;

	for (auto conn : get_connectors())
	{
		if (conn->connected() == false)
			continue;

		Crtc* crtc = conn->get_current_crtc();

		if (!crtc) {
			for (auto possible : conn->get_possible_crtcs()) {
				if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) {
					crtc = possible;
					break;
				}
			}
		}

		if (!crtc)
			throw invalid_argument(string("Connector #") +
					       to_string(conn->idx()) +
					       " has no possible crtcs");

		outputs.push_back(Pipeline { crtc, conn });
	}

	return outputs;
}

}
<commit_msg>Allow disabling atomic modeset with LIBKMSXX_DISABLE_ATOMIC<commit_after>#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <utility>
#include <stdexcept>
#include <string.h>
#include <algorithm>

#include <xf86drm.h>
#include <xf86drmMode.h>

#include "kms++.h"

#ifndef DRM_CLIENT_CAP_ATOMIC
#define DRM_CLIENT_CAP_ATOMIC 3
#endif

using namespace std;

namespace kms
{

Card::Card()
{
	const char *card = "/dev/dri/card0";

	int fd = open(card, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		throw invalid_argument(string(strerror(errno)) + " opening " +
				       card);
	m_fd = fd;

	int r;

	r = drmSetMaster(fd);
	m_master = r == 0;

	r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
	m_has_universal_planes = r == 0;

	if (getenv("LIBKMSXX_DISABLE_ATOMIC") == 0) {
		r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1);
		m_has_atomic = r == 0;
	} else {
		m_has_atomic = false;
	}

	uint64_t has_dumb;
	r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
	if (r || !has_dumb)
		throw invalid_argument("Dumb buffers not available");

	auto res = drmModeGetResources(m_fd);
	if (!res)
		throw invalid_argument("Can't get card resources");

	for (int i = 0; i < res->count_connectors; ++i) {
		uint32_t id = res->connectors[i];
		m_obmap[id] = new Connector(*this, id, i);
	}

	for (int i = 0; i < res->count_crtcs; ++i) {
		uint32_t id = res->crtcs[i];
		m_obmap[id] = new Crtc(*this, id, i);
	}

	for (int i = 0; i < res->count_encoders; ++i) {
		uint32_t id = res->encoders[i];
		m_obmap[id] = new Encoder(*this, id);
	}

	drmModeFreeResources(res);

	auto planeRes = drmModeGetPlaneResources(m_fd);

	for (uint i = 0; i < planeRes->count_planes; ++i) {
		uint32_t id = planeRes->planes[i];
		m_obmap[id] = new Plane(*this, id);
	}

	drmModeFreePlaneResources(planeRes);

	// collect all possible props
	for (auto ob : get_objects()) {
		auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type());

		if (props == nullptr)
			continue;

		for (unsigned i = 0; i < props->count_props; ++i) {
			uint32_t prop_id = props->props[i];

			if (m_obmap.find(prop_id) == m_obmap.end())
				m_obmap[prop_id] = new Property(*this, prop_id);
		}

		drmModeFreeObjectProperties(props);
	}

	for (auto pair : m_obmap)
		pair.second->setup();
}

Card::~Card()
{
	for (auto pair : m_obmap)
		delete pair.second;

	close(m_fd);
}

template <class T> static void print_obs(const map<uint32_t, DrmObject*>& obmap)
{
	for (auto pair : obmap) {
		auto ob = pair.second;
		if (dynamic_cast<T*>(ob)) {
			ob->print_short();
			//ob->print_props();
		}
	}
}

void Card::print_short() const
{
	print_obs<Connector>(m_obmap);
	print_obs<Encoder>(m_obmap);
	print_obs<Crtc>(m_obmap);
	print_obs<Plane>(m_obmap);
}

Property* Card::get_prop(const char *name) const
{
	for (auto pair : m_obmap) {
		auto prop = dynamic_cast<Property*>(pair.second);
		if (!prop)
			continue;

		if (strcmp(name, prop->name()) == 0)
			return prop;
	}

	throw invalid_argument(string("Card property ") + name + " not found");
}

Connector* Card::get_first_connected_connector() const
{
	for(auto pair : m_obmap) {
		auto c = dynamic_cast<Connector*>(pair.second);

		if (c && c->connected())
			return c;
	}

	throw invalid_argument("no connected connectors");
}

DrmObject* Card::get_object(uint32_t id) const
{
	return m_obmap.at(id);
}

vector<Connector*> Card::get_connectors() const
{
	vector<Connector*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Connector*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<Plane*> Card::get_planes() const
{
	vector<Plane*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Plane*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<DrmObject*> Card::get_objects() const
{
	vector<DrmObject*> v;
	for(auto pair : m_obmap)
		v.push_back(pair.second);
	return v;
}

Crtc* Card::get_crtc_by_index(uint32_t idx) const
{
	for(auto pair : m_obmap) {
		auto crtc = dynamic_cast<Crtc*>(pair.second);
		if (crtc && crtc->idx() == idx)
			return crtc;
	}
	throw invalid_argument(string("Crtc #") + to_string(idx) + "not found");
}

Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast<Crtc*>(get_object(id)); }
Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast<Encoder*>(get_object(id)); }
Property* Card::get_prop(uint32_t id) const { return dynamic_cast<Property*>(get_object(id)); }

std::vector<kms::Pipeline> Card::get_connected_pipelines()
{
	vector<Pipeline> outputs;

	for (auto conn : get_connectors())
	{
		if (conn->connected() == false)
			continue;

		Crtc* crtc = conn->get_current_crtc();

		if (!crtc) {
			for (auto possible : conn->get_possible_crtcs()) {
				if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) {
					crtc = possible;
					break;
				}
			}
		}

		if (!crtc)
			throw invalid_argument(string("Connector #") +
					       to_string(conn->idx()) +
					       " has no possible crtcs");

		outputs.push_back(Pipeline { crtc, conn });
	}

	return outputs;
}

}
<|endoftext|>


<commit_before>// [WriteFile Name=ExportTiles, Category=Layers]
// [Legal]
// Copyright 2016 Esri.

// 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.
// [Legal]

#include "ExportTiles.h"

#include <QUrl>

#include "Map.h"
#include "MapQuickView.h"
#include "Basemap.h"
#include "ExportTiles.h"
#include "ArcGISTiledLayer.h"
#include "ExportTileCacheTask.h"
#include "Envelope.h"
#include "GeometryEngine.h"
#include "SpatialReference.h"
#include "TileCache.h"

using namespace Esri::ArcGISRuntime;

ExportTiles::ExportTiles(QQuickItem* parent) :
    QQuickItem(parent),
    m_map(nullptr),
    m_mapView(nullptr),
    m_serviceUrl("http://sampleserver6.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer"),
    m_exportTileCacheTask(nullptr)
{
}

ExportTiles::~ExportTiles()
{
}

void ExportTiles::componentComplete()
{
    QQuickItem::componentComplete();

    // find QML MapView component
    m_mapView = findChild<MapQuickView*>("mapView");

    // create a tiled basemap
    ArcGISTiledLayer* tiledLayer = new ArcGISTiledLayer(m_serviceUrl);
    Basemap* basemap = new Basemap(tiledLayer, this);

    // create a new map instance
    m_map = new Map(basemap, this);

    // set map on the map view
    m_mapView->setMap(m_map);

    // create the task from the tiled layer's map service info once it is loaded
    connect(tiledLayer, &ArcGISTiledLayer::doneLoading, [this, tiledLayer](Error)
    {
        m_exportTileCacheTask = new ExportTileCacheTask(tiledLayer->mapServiceInfo(), this);
    });
}

void ExportTiles::exportTileCacheFromCorners(double xCorner1, double yCorner1, double xCorner2, double yCorner2, QString dataPath)
{
    // create an envelope from the QML rectangle corners
    auto corner1 = m_mapView->screenToLocation(xCorner1, yCorner1);
    auto corner2 = m_mapView->screenToLocation(xCorner2, yCorner2);
    auto extent = Envelope(corner1, corner2);
    auto tileCacheExtent = GeometryEngine::project(extent, SpatialReference::webMercator());

    // generate parameters
    auto params = m_exportTileCacheTask->createDefaultExportTileCacheParameters(tileCacheExtent, m_mapView->mapScale(), m_exportTileCacheTask->mapServiceInfo()->maxScale());

    // execute the task and obtain the job
    auto exportJob = m_exportTileCacheTask->exportTileCacheWithParameters(params, dataPath);

    // check if there is a valid job
    if (exportJob)
    {
        // connect to the job's status changed signal
        connect(exportJob, &ExportTileCacheJob::jobStatusChanged, [this, exportJob]()
        {
            // connect to the job's status changed signal to know once it is done
            switch (exportJob->jobStatus()) {
            case JobStatus::Failed:
                emit updateStatus("Export failed");
                emit hideWindow(5000, false);
                break;
            case JobStatus::NotStarted:
                emit updateStatus("Job not started");
                break;
            case JobStatus::Paused:
                emit updateStatus("Job paused");
                break;
            case JobStatus::Started:
                emit updateStatus("In progress...");
                break;
            case JobStatus::Succeeded:
                emit updateStatus("Adding TPK...");
                emit hideWindow(1500, true);
                displayOutputTileCache(exportJob->result());
                break;
            default:
                break;
            }
        });

        // start the export job
        exportJob->start();
    }
    else
    {
        emit updateStatus("Export failed");
        emit hideWindow(5000, false);
    }
}

// display the tile cache once the task is complete
void ExportTiles::displayOutputTileCache(TileCache* tileCache)
{
    // create a new tiled layer from the output tile cache
    auto tiledLayer = new ArcGISTiledLayer(tileCache, this);

    // add the new layer to a basemap
    auto basemap = new Basemap(tiledLayer, this);

    // set the new basemap on the map
    m_map->setBasemap(basemap);

    // zoom to the new layer and hide window once loaded
    connect(tiledLayer, &ArcGISTiledLayer::doneLoading, [this, tiledLayer]()
    {
        if (tiledLayer->loadStatus() == LoadStatus::Loaded)
        {
            m_mapView->setViewpointScale(m_mapView->mapScale() * 0.5);
        }
    });
}
<commit_msg>Sample updates for API change<commit_after>// [WriteFile Name=ExportTiles, Category=Layers]
// [Legal]
// Copyright 2016 Esri.

// 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.
// [Legal]

#include "ExportTiles.h"

#include <QUrl>

#include "Map.h"
#include "MapQuickView.h"
#include "Basemap.h"
#include "ExportTiles.h"
#include "ArcGISTiledLayer.h"
#include "ExportTileCacheTask.h"
#include "Envelope.h"
#include "GeometryEngine.h"
#include "SpatialReference.h"
#include "TileCache.h"

using namespace Esri::ArcGISRuntime;

ExportTiles::ExportTiles(QQuickItem* parent) :
    QQuickItem(parent),
    m_map(nullptr),
    m_mapView(nullptr),
    m_serviceUrl("http://sampleserver6.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer"),
    m_exportTileCacheTask(nullptr)
{
}

ExportTiles::~ExportTiles()
{
}

void ExportTiles::componentComplete()
{
    QQuickItem::componentComplete();

    // find QML MapView component
    m_mapView = findChild<MapQuickView*>("mapView");

    // create a tiled basemap
    ArcGISTiledLayer* tiledLayer = new ArcGISTiledLayer(m_serviceUrl);
    Basemap* basemap = new Basemap(tiledLayer, this);

    // create a new map instance
    m_map = new Map(basemap, this);

    // set map on the map view
    m_mapView->setMap(m_map);

    // create the task from the tiled layer's map service info once it is loaded
    connect(tiledLayer, &ArcGISTiledLayer::doneLoading, [this, tiledLayer](Error)
    {
        m_exportTileCacheTask = new ExportTileCacheTask(tiledLayer->mapServiceInfo(), this);
    });
}

void ExportTiles::exportTileCacheFromCorners(double xCorner1, double yCorner1, double xCorner2, double yCorner2, QString dataPath)
{
    // create an envelope from the QML rectangle corners
    auto corner1 = m_mapView->screenToLocation(xCorner1, yCorner1);
    auto corner2 = m_mapView->screenToLocation(xCorner2, yCorner2);
    auto extent = Envelope(corner1, corner2);
    auto tileCacheExtent = GeometryEngine::project(extent, SpatialReference::webMercator());

    // generate parameters
    auto params = m_exportTileCacheTask->createDefaultExportTileCacheParameters(tileCacheExtent, m_mapView->mapScale(), m_exportTileCacheTask->mapServiceInfo()->maxScale());

    // execute the task and obtain the job
    auto exportJob = m_exportTileCacheTask->exportTileCache(params, dataPath);

    // check if there is a valid job
    if (exportJob)
    {
        // connect to the job's status changed signal
        connect(exportJob, &ExportTileCacheJob::jobStatusChanged, [this, exportJob]()
        {
            // connect to the job's status changed signal to know once it is done
            switch (exportJob->jobStatus()) {
            case JobStatus::Failed:
                emit updateStatus("Export failed");
                emit hideWindow(5000, false);
                break;
            case JobStatus::NotStarted:
                emit updateStatus("Job not started");
                break;
            case JobStatus::Paused:
                emit updateStatus("Job paused");
                break;
            case JobStatus::Started:
                emit updateStatus("In progress...");
                break;
            case JobStatus::Succeeded:
                emit updateStatus("Adding TPK...");
                emit hideWindow(1500, true);
                displayOutputTileCache(exportJob->result());
                break;
            default:
                break;
            }
        });

        // start the export job
        exportJob->start();
    }
    else
    {
        emit updateStatus("Export failed");
        emit hideWindow(5000, false);
    }
}

// display the tile cache once the task is complete
void ExportTiles::displayOutputTileCache(TileCache* tileCache)
{
    // create a new tiled layer from the output tile cache
    auto tiledLayer = new ArcGISTiledLayer(tileCache, this);

    // add the new layer to a basemap
    auto basemap = new Basemap(tiledLayer, this);

    // set the new basemap on the map
    m_map->setBasemap(basemap);

    // zoom to the new layer and hide window once loaded
    connect(tiledLayer, &ArcGISTiledLayer::doneLoading, [this, tiledLayer]()
    {
        if (tiledLayer->loadStatus() == LoadStatus::Loaded)
        {
            m_mapView->setViewpointScale(m_mapView->mapScale() * 0.5);
        }
    });
}
<|endoftext|>


<commit_before>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "ArticyFlowPlayer.h"
#include "ArticyRuntime.h"
#include "ArticyFlowObject.h"
#include "ArticyObjectWithSpeaker.h"
#include "ArticyExpressoScripts.h"
#include "ArticyInputPinsProvider.h"
#include "ArticyOutputPinsProvider.h"

TScriptInterface<IArticyFlowObject> FArticyBranch::GetTarget() const
{
	return Path.Num() > 0 ? Path.Last() : nullptr;
}

void UArticyFlowPlayer::BeginPlay()
{
	Super::BeginPlay();

	//update Cursor to object referenced by StartOn
	SetCursorToStartNode();
}

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

void UArticyFlowPlayer::SetStartNode(FArticyRef StartNodeId)
{
	StartOn.SetId(StartNodeId.GetId());
	SetCursorToStartNode();
}

void UArticyFlowPlayer::SetStartNodeWithFlowObject(TScriptInterface<IArticyFlowObject> Node)
{
	FArticyRef ArticyRef;
	ArticyRef.SetReference(Cast<UArticyPrimitive>(Node.GetObject()));
	SetStartNode(ArticyRef);
}

void UArticyFlowPlayer::SetStartNodeById(FArticyId NewId)
{
	StartOn.SetId(NewId);
	SetCursorToStartNode();
}

void UArticyFlowPlayer::SetCursorTo(TScriptInterface<IArticyFlowObject> Node)
{
	Cursor = Node;
	UpdateAvailableBranches();
}

void UArticyFlowPlayer::Play(int BranchIndex)
{
	TArray<FArticyBranch> branches;
	if (IgnoresInvalidBranches())
	{
		for (auto branch : AvailableBranches)
			if (branch.bIsValid)
				branches.Add(branch);
	}
	else
	{
		branches = AvailableBranches;
	}

	//check if the specified branch exists
	if(!branches.IsValidIndex(BranchIndex))
	{
		UE_LOG(LogArticyRuntime, Error, TEXT("Branch with index %d does not exist!"), BranchIndex)
		return;
	}

	PlayBranch(branches[BranchIndex]);
}

void UArticyFlowPlayer::FinishCurrentPausedObject(int PinIndex)
{
	IArticyOutputPinsProvider* outputPinOwner = Cast<IArticyOutputPinsProvider>(Cursor.GetObject());
	if (outputPinOwner)
	{
		auto outputPins = outputPinOwner->GetOutputPinsPtr();

		if (outputPins->Num() > 0)
		{
			if (PinIndex < outputPins->Num())
			{
				(*outputPins)[PinIndex]->Execute(GetGVs(), GetMethodsProvider());
			}
			else
				UE_LOG(LogArticyRuntime, Warning, TEXT("FinishCurrentPausedObject: The index was out of bounds: Index: %d, PinCount: %d"), PinIndex, outputPins->Num());
		}
	}
}

bool UArticyFlowPlayer::ShouldPauseOn(IArticyFlowObject* Node) const
{
	return Node && (1 << static_cast<uint8>(Node->GetType()) & PauseOn);
}

UArticyDatabase* UArticyFlowPlayer::GetDB() const
{
	return UArticyDatabase::Get(this);
}

UArticyGlobalVariables* UArticyFlowPlayer::GetGVs() const
{
	return OverrideGV ? OverrideGV : UArticyGlobalVariables::GetDefault(this);
}

UObject* UArticyFlowPlayer::GetMethodsProvider() const
{
	auto expressoInstance = GetDB()->GetExpressoInstance();
	auto provider = expressoInstance->GetUserMethodsProviderInterface();

	if (expressoInstance->UserMethodsProvider != nullptr && UserMethodsProvider == nullptr)//MM_CHANGE
		UserMethodsProvider = expressoInstance->UserMethodsProvider;

	if(ensure(provider))
	{
		//check if the set provider implements the required interface
		if(!UserMethodsProvider || !ensure(UserMethodsProvider->GetClass()->ImplementsInterface(provider)))
		{

			//no valid UserMethodsProvider set, search for it

			//check if the flow player itself implements it
			if(GetClass()->ImplementsInterface(provider))
				UserMethodsProvider = const_cast<UArticyFlowPlayer*>(this);
			else
			{
				auto actor = GetOwner();
				if(ensure(actor))
				{
					//check if the flow player's owning actor implements it
					if(actor->GetClass()->ImplementsInterface(provider))
						UserMethodsProvider = actor;
					else
					{
						//check if any other component implements it
						auto components = actor->GetComponents();
						for(auto comp : components)
						{
							if(comp->GetClass()->ImplementsInterface(provider))
							{
								UserMethodsProvider = comp;
								break;
							}
						}

						//and finally we check for a default methods provider, which we can use as fallback
						auto defaultUserMethodsProvider = expressoInstance->DefaultUserMethodsProvider;
						if(defaultUserMethodsProvider && ensure(defaultUserMethodsProvider->GetClass()->ImplementsInterface(provider)))
							UserMethodsProvider = defaultUserMethodsProvider;
					}
				}
			}
		}
	}

	return UserMethodsProvider;
}

IArticyFlowObject* UArticyFlowPlayer::GetUnshadowedNode(IArticyFlowObject* Node)
{
	auto db = UArticyDatabase::Get(this);
	auto unshadowedObject = db->GetObjectUnshadowed(Cast<UArticyPrimitive>(Node)->GetId());

	// handle pins, because we can not request them directly from the db
	if (!unshadowedObject)
	{
		auto pinOwner = db->GetObjectUnshadowed(Cast<UArticyFlowPin>(Node)->GetOwner()->GetId());

		TArray<UArticyFlowPin*> pins;
		auto inputPinsOwner = Cast<IArticyInputPinsProvider>(pinOwner);
		pins.Append(*inputPinsOwner->GetInputPins());
		auto outputPinsOwner = Cast<IArticyOutputPinsProvider>(pinOwner);
		pins.Append(*outputPinsOwner->GetOutputPinsPtr());

		auto targetId = Cast<UArticyPrimitive>(Node)->GetId();
		for (auto pin : pins)
		{
			if (pin->GetId() == targetId)
			{
				unshadowedObject = pin;
				break;
			}
		}
	}

	return Cast<IArticyFlowObject>(unshadowedObject);
}

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

TArray<FArticyBranch> UArticyFlowPlayer::Explore(IArticyFlowObject* Node, bool bShadowed, int32 Depth)
{
	TArray<FArticyBranch> OutBranches;

	//check stop condition
	if((Depth > ExploreDepthLimit || !Node || (Node != Cursor.GetInterface() && ShouldPauseOn(Node))))
	{
		if(Depth > ExploreDepthLimit)
			UE_LOG(LogArticyRuntime, Warning, TEXT("ExploreDepthLimit (%d) reached, stopping exploration!"), ExploreDepthLimit);
		if(!Node)
			UE_LOG(LogArticyRuntime, Warning, TEXT("Found a nullptr Node when exploring a branch!"));

		/* TODO where should I put this?
		if(OutBranches.Num() >= BranchLimit)
		{
			UE_LOG(LogArticyRuntime, Warning, TEXT("BranchLimit (%d) reached, cannot add another branch!"), BranchLimit);
			return;
		}*/

		//target reached, create a branch
		auto branch = FArticyBranch{};
		if(Node)
		{
			/* NOTE: This check must not be done, as the last node in a branch never affects
			* validity of the branch. A branch is only invalidated if it runs THROUGH a node
			* with invalid condition, instead of just UP TO that node.
			branch.bIsValid = Node->Execute(this); */

			auto unshadowedNode = GetUnshadowedNode(Node);

			TScriptInterface<IArticyFlowObject> ptr;
			ptr.SetObject(unshadowedNode->_getUObject());
			ptr.SetInterface(unshadowedNode);
			branch.Path.Add(ptr);
		}

		OutBranches.Add(branch);
	}
	else
	{
		//set speaker on expresso scripts
		auto xp = GetDB()->GetExpressoInstance();
		if(ensure(xp))
		{
			auto obj = Cast<UArticyPrimitive>(Node);
			if(obj)
			{
				xp->SetCurrentObject(obj);

				IArticyObjectWithSpeaker* speaker;
				if (auto flowPin = Cast<UArticyFlowPin>(Node))
					speaker = Cast<IArticyObjectWithSpeaker>(flowPin->GetOwner());
				else
					speaker = Cast<IArticyObjectWithSpeaker>(obj);

				if(speaker)
					xp->SetSpeaker(speaker->GetSpeaker());
			}
		}

		//if this is the first node, try to submerge
		bool bSubmerged = false;
		if(Depth == 0)
		{
			auto inputPinProvider = Cast<IArticyInputPinsProvider>(Node);
			if(inputPinProvider)
				bSubmerged = inputPinProvider->TrySubmerge(this, OutBranches, Depth + 1, bShadowed); //NOTE: bShadowed will always be true if Depth == 0
		}

		//explore this node
		if(!bSubmerged)
		{
			if(bShadowed)
			{
				//explore the node inside a shadowed operation
				ShadowedOperation([&] { Node->Explore(this, OutBranches, Depth + 1); });
			}
			else
			{
				//non-shadowed explore
				Node->Explore(this, OutBranches, Depth + 1);
			}
		}

		//add this node to the head of all the branches
		for(auto& branch : OutBranches)
		{
			auto unshadowedNode = GetUnshadowedNode(Node);
			TScriptInterface<IArticyFlowObject> ptr;
			ptr.SetObject(unshadowedNode->_getUObject());
			ptr.SetInterface(unshadowedNode);

			branch.Path.Insert(ptr, 0); //TODO inserting at front is not ideal performance wise
		}
	}

	return OutBranches;
}

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

void UArticyFlowPlayer::UpdateAvailableBranches()
{
	AvailableBranches.Reset();

	if(PauseOn == 0)
		UE_LOG(LogArticyRuntime, Warning, TEXT("PauseOn is not set, not exploring the Flow as it would not pause on any node."))
	else if(!Cursor)
		UE_LOG(LogArticyRuntime, Warning, TEXT("Cannot explore flow, cursor is not set!"))
	else
	{
		const bool bMustBeShadowed = true;
		AvailableBranches = Explore(&*Cursor, bMustBeShadowed, 0);

		// NP: Every branch needs the index so that Play() can actually take a branch as input
		for (int32 i = 0; i < AvailableBranches.Num(); i++)
			AvailableBranches[i].Index = i;

		//if the cursor is at the StartOn node, check if we should fast-forward
		if(Cursor.GetObject() == StartOn.GetObject(this) && FastForwardToPause())
		{
			//fast-forwarding will call UpdateAvailableBranches again, can abort here
			return;
		}

		//broadcast and return result
		OnPlayerPaused.Broadcast(Cursor);
		OnBranchesUpdated.Broadcast(AvailableBranches);
	}
}

void UArticyFlowPlayer::SetCursorToStartNode()
{
	const auto obj = StartOn.GetObject(this);

	TScriptInterface<IArticyFlowObject> ptr;
	ptr.SetObject(obj);
	ptr.SetInterface(Cast<IArticyFlowObject>(obj));

	SetCursorTo(ptr);
}

bool UArticyFlowPlayer::FastForwardToPause()
{
	checkNoRecursion(); //this cannot recurse!

	if(AvailableBranches.Num() <= 0)
		return false;

	const auto& firstPath = AvailableBranches[0].Path;
	if(!ensure(firstPath.Num() > 0))
		return false;

	int ffwdIndex;
	for(ffwdIndex = 0; ffwdIndex < firstPath.Num(); ++ffwdIndex)
	{
		const auto node = firstPath[ffwdIndex];
		if(ShouldPauseOn(&*node))
		{
			//pause on this node
			break;
		}

		auto bSplitFound = false;
		for(int b = 1; b < AvailableBranches.Num(); ++b)
		{
			const auto path = AvailableBranches[b].Path;
			//it shouldn't be possible that one path is a subset of the other one
			//(shorter but all nodes equal to the other path)
			if(!ensure(path.IsValidIndex(ffwdIndex)) || path[ffwdIndex] != node)
			{
				bSplitFound = true;
				break;
			}
		}

		if(bSplitFound)
		{
			//pause on the node BEFORE
			--ffwdIndex;
			break;
		}
	}

	if(ffwdIndex <= 0 || ffwdIndex >= firstPath.Num())
	{
		//no need to fast-forward
		return false;
	}

	//create the fast-forward branch
	auto newBranch = FArticyBranch{};
	newBranch.bIsValid = AvailableBranches[0].bIsValid;
	for(int i = 0; i <= ffwdIndex; ++i)
	{
		//add node to branch
		newBranch.Path.Add(firstPath[i]);
	}

	//this also calls UpdateAvailableBranches again
	PlayBranch(newBranch);

	return true;
}

void UArticyFlowPlayer::PlayBranch(const FArticyBranch& Branch)
{
	if(!ensure(ShadowLevel == 0))
	{
		UE_LOG(LogArticyRuntime, Error, TEXT("ArticyFlowPlayer::Traverse was called inside a ShadowedOperation! Aborting Play."))
		return;
	}

	if (!bDisableExecutingOutputPins)
	{
		for (auto node : Branch.Path)
			node->Execute(GetGVs(), GetMethodsProvider());
	}

	bDisableExecutingOutputPins = false;
	Cursor = Branch.Path.Last();
	UpdateAvailableBranches();
}
<commit_msg>Added a nullptr check & log when setting the cursor of the flowplayer<commit_after>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "ArticyFlowPlayer.h"
#include "ArticyRuntime.h"
#include "ArticyFlowObject.h"
#include "ArticyObjectWithSpeaker.h"
#include "ArticyExpressoScripts.h"
#include "ArticyInputPinsProvider.h"
#include "ArticyOutputPinsProvider.h"

TScriptInterface<IArticyFlowObject> FArticyBranch::GetTarget() const
{
	return Path.Num() > 0 ? Path.Last() : nullptr;
}

void UArticyFlowPlayer::BeginPlay()
{
	Super::BeginPlay();

	//update Cursor to object referenced by StartOn
	SetCursorToStartNode();
}

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

void UArticyFlowPlayer::SetStartNode(FArticyRef StartNodeId)
{
	StartOn.SetId(StartNodeId.GetId());
	SetCursorToStartNode();
}

void UArticyFlowPlayer::SetStartNodeWithFlowObject(TScriptInterface<IArticyFlowObject> Node)
{
	FArticyRef ArticyRef;
	ArticyRef.SetReference(Cast<UArticyPrimitive>(Node.GetObject()));
	SetStartNode(ArticyRef);
}

void UArticyFlowPlayer::SetStartNodeById(FArticyId NewId)
{
	StartOn.SetId(NewId);
	SetCursorToStartNode();
}

void UArticyFlowPlayer::SetCursorTo(TScriptInterface<IArticyFlowObject> Node)
{
	if(!Node.GetObject())
	{
		UE_LOG(LogArticyRuntime, Warning, TEXT("Could not set cursor in flow player of actor %s: invalid node"), *this->GetOwner()->GetName());
		return;
	}

	Cursor = Node;
	UpdateAvailableBranches();
}

void UArticyFlowPlayer::Play(int BranchIndex)
{
	TArray<FArticyBranch> branches;
	if (IgnoresInvalidBranches())
	{
		for (auto branch : AvailableBranches)
			if (branch.bIsValid)
				branches.Add(branch);
	}
	else
	{
		branches = AvailableBranches;
	}

	//check if the specified branch exists
	if(!branches.IsValidIndex(BranchIndex))
	{
		UE_LOG(LogArticyRuntime, Error, TEXT("Branch with index %d does not exist!"), BranchIndex)
		return;
	}

	PlayBranch(branches[BranchIndex]);
}

void UArticyFlowPlayer::FinishCurrentPausedObject(int PinIndex)
{
	IArticyOutputPinsProvider* outputPinOwner = Cast<IArticyOutputPinsProvider>(Cursor.GetObject());
	if (outputPinOwner)
	{
		auto outputPins = outputPinOwner->GetOutputPinsPtr();

		if (outputPins->Num() > 0)
		{
			if (PinIndex < outputPins->Num())
			{
				(*outputPins)[PinIndex]->Execute(GetGVs(), GetMethodsProvider());
			}
			else
				UE_LOG(LogArticyRuntime, Warning, TEXT("FinishCurrentPausedObject: The index was out of bounds: Index: %d, PinCount: %d"), PinIndex, outputPins->Num());
		}
	}
}

bool UArticyFlowPlayer::ShouldPauseOn(IArticyFlowObject* Node) const
{
	return Node && (1 << static_cast<uint8>(Node->GetType()) & PauseOn);
}

UArticyDatabase* UArticyFlowPlayer::GetDB() const
{
	return UArticyDatabase::Get(this);
}

UArticyGlobalVariables* UArticyFlowPlayer::GetGVs() const
{
	return OverrideGV ? OverrideGV : UArticyGlobalVariables::GetDefault(this);
}

UObject* UArticyFlowPlayer::GetMethodsProvider() const
{
	auto expressoInstance = GetDB()->GetExpressoInstance();
	auto provider = expressoInstance->GetUserMethodsProviderInterface();

	if (expressoInstance->UserMethodsProvider != nullptr && UserMethodsProvider == nullptr)//MM_CHANGE
		UserMethodsProvider = expressoInstance->UserMethodsProvider;

	if(ensure(provider))
	{
		//check if the set provider implements the required interface
		if(!UserMethodsProvider || !ensure(UserMethodsProvider->GetClass()->ImplementsInterface(provider)))
		{

			//no valid UserMethodsProvider set, search for it

			//check if the flow player itself implements it
			if(GetClass()->ImplementsInterface(provider))
				UserMethodsProvider = const_cast<UArticyFlowPlayer*>(this);
			else
			{
				auto actor = GetOwner();
				if(ensure(actor))
				{
					//check if the flow player's owning actor implements it
					if(actor->GetClass()->ImplementsInterface(provider))
						UserMethodsProvider = actor;
					else
					{
						//check if any other component implements it
						auto components = actor->GetComponents();
						for(auto comp : components)
						{
							if(comp->GetClass()->ImplementsInterface(provider))
							{
								UserMethodsProvider = comp;
								break;
							}
						}

						//and finally we check for a default methods provider, which we can use as fallback
						auto defaultUserMethodsProvider = expressoInstance->DefaultUserMethodsProvider;
						if(defaultUserMethodsProvider && ensure(defaultUserMethodsProvider->GetClass()->ImplementsInterface(provider)))
							UserMethodsProvider = defaultUserMethodsProvider;
					}
				}
			}
		}
	}

	return UserMethodsProvider;
}

IArticyFlowObject* UArticyFlowPlayer::GetUnshadowedNode(IArticyFlowObject* Node)
{
	auto db = UArticyDatabase::Get(this);
	auto unshadowedObject = db->GetObjectUnshadowed(Cast<UArticyPrimitive>(Node)->GetId());

	// handle pins, because we can not request them directly from the db
	if (!unshadowedObject)
	{
		auto pinOwner = db->GetObjectUnshadowed(Cast<UArticyFlowPin>(Node)->GetOwner()->GetId());

		TArray<UArticyFlowPin*> pins;
		auto inputPinsOwner = Cast<IArticyInputPinsProvider>(pinOwner);
		pins.Append(*inputPinsOwner->GetInputPins());
		auto outputPinsOwner = Cast<IArticyOutputPinsProvider>(pinOwner);
		pins.Append(*outputPinsOwner->GetOutputPinsPtr());

		auto targetId = Cast<UArticyPrimitive>(Node)->GetId();
		for (auto pin : pins)
		{
			if (pin->GetId() == targetId)
			{
				unshadowedObject = pin;
				break;
			}
		}
	}

	return Cast<IArticyFlowObject>(unshadowedObject);
}

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

TArray<FArticyBranch> UArticyFlowPlayer::Explore(IArticyFlowObject* Node, bool bShadowed, int32 Depth)
{
	TArray<FArticyBranch> OutBranches;

	//check stop condition
	if((Depth > ExploreDepthLimit || !Node || (Node != Cursor.GetInterface() && ShouldPauseOn(Node))))
	{
		if(Depth > ExploreDepthLimit)
			UE_LOG(LogArticyRuntime, Warning, TEXT("ExploreDepthLimit (%d) reached, stopping exploration!"), ExploreDepthLimit);
		if(!Node)
			UE_LOG(LogArticyRuntime, Warning, TEXT("Found a nullptr Node when exploring a branch!"));

		/* TODO where should I put this?
		if(OutBranches.Num() >= BranchLimit)
		{
			UE_LOG(LogArticyRuntime, Warning, TEXT("BranchLimit (%d) reached, cannot add another branch!"), BranchLimit);
			return;
		}*/

		//target reached, create a branch
		auto branch = FArticyBranch{};
		if(Node)
		{
			/* NOTE: This check must not be done, as the last node in a branch never affects
			* validity of the branch. A branch is only invalidated if it runs THROUGH a node
			* with invalid condition, instead of just UP TO that node.
			branch.bIsValid = Node->Execute(this); */

			auto unshadowedNode = GetUnshadowedNode(Node);

			TScriptInterface<IArticyFlowObject> ptr;
			ptr.SetObject(unshadowedNode->_getUObject());
			ptr.SetInterface(unshadowedNode);
			branch.Path.Add(ptr);
		}

		OutBranches.Add(branch);
	}
	else
	{
		//set speaker on expresso scripts
		auto xp = GetDB()->GetExpressoInstance();
		if(ensure(xp))
		{
			auto obj = Cast<UArticyPrimitive>(Node);
			if(obj)
			{
				xp->SetCurrentObject(obj);

				IArticyObjectWithSpeaker* speaker;
				if (auto flowPin = Cast<UArticyFlowPin>(Node))
					speaker = Cast<IArticyObjectWithSpeaker>(flowPin->GetOwner());
				else
					speaker = Cast<IArticyObjectWithSpeaker>(obj);

				if(speaker)
					xp->SetSpeaker(speaker->GetSpeaker());
			}
		}

		//if this is the first node, try to submerge
		bool bSubmerged = false;
		if(Depth == 0)
		{
			auto inputPinProvider = Cast<IArticyInputPinsProvider>(Node);
			if(inputPinProvider)
				bSubmerged = inputPinProvider->TrySubmerge(this, OutBranches, Depth + 1, bShadowed); //NOTE: bShadowed will always be true if Depth == 0
		}

		//explore this node
		if(!bSubmerged)
		{
			if(bShadowed)
			{
				//explore the node inside a shadowed operation
				ShadowedOperation([&] { Node->Explore(this, OutBranches, Depth + 1); });
			}
			else
			{
				//non-shadowed explore
				Node->Explore(this, OutBranches, Depth + 1);
			}
		}

		//add this node to the head of all the branches
		for(auto& branch : OutBranches)
		{
			auto unshadowedNode = GetUnshadowedNode(Node);
			TScriptInterface<IArticyFlowObject> ptr;
			ptr.SetObject(unshadowedNode->_getUObject());
			ptr.SetInterface(unshadowedNode);

			branch.Path.Insert(ptr, 0); //TODO inserting at front is not ideal performance wise
		}
	}

	return OutBranches;
}

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

void UArticyFlowPlayer::UpdateAvailableBranches()
{
	AvailableBranches.Reset();

	if(PauseOn == 0)
		UE_LOG(LogArticyRuntime, Warning, TEXT("PauseOn is not set, not exploring the Flow as it would not pause on any node."))
	else if(!Cursor)
		UE_LOG(LogArticyRuntime, Warning, TEXT("Cannot explore flow, cursor is not set!"))
	else
	{
		const bool bMustBeShadowed = true;
		AvailableBranches = Explore(&*Cursor, bMustBeShadowed, 0);

		// NP: Every branch needs the index so that Play() can actually take a branch as input
		for (int32 i = 0; i < AvailableBranches.Num(); i++)
			AvailableBranches[i].Index = i;

		//if the cursor is at the StartOn node, check if we should fast-forward
		if(Cursor.GetObject() == StartOn.GetObject(this) && FastForwardToPause())
		{
			//fast-forwarding will call UpdateAvailableBranches again, can abort here
			return;
		}

		//broadcast and return result
		OnPlayerPaused.Broadcast(Cursor);
		OnBranchesUpdated.Broadcast(AvailableBranches);
	}
}

void UArticyFlowPlayer::SetCursorToStartNode()
{
	const auto obj = StartOn.GetObject(this);

	TScriptInterface<IArticyFlowObject> ptr;
	ptr.SetObject(obj);
	ptr.SetInterface(Cast<IArticyFlowObject>(obj));

	SetCursorTo(ptr);
}

bool UArticyFlowPlayer::FastForwardToPause()
{
	checkNoRecursion(); //this cannot recurse!

	if(AvailableBranches.Num() <= 0)
		return false;

	const auto& firstPath = AvailableBranches[0].Path;
	if(!ensure(firstPath.Num() > 0))
		return false;

	int ffwdIndex;
	for(ffwdIndex = 0; ffwdIndex < firstPath.Num(); ++ffwdIndex)
	{
		const auto node = firstPath[ffwdIndex];
		if(ShouldPauseOn(&*node))
		{
			//pause on this node
			break;
		}

		auto bSplitFound = false;
		for(int b = 1; b < AvailableBranches.Num(); ++b)
		{
			const auto path = AvailableBranches[b].Path;
			//it shouldn't be possible that one path is a subset of the other one
			//(shorter but all nodes equal to the other path)
			if(!ensure(path.IsValidIndex(ffwdIndex)) || path[ffwdIndex] != node)
			{
				bSplitFound = true;
				break;
			}
		}

		if(bSplitFound)
		{
			//pause on the node BEFORE
			--ffwdIndex;
			break;
		}
	}

	if(ffwdIndex <= 0 || ffwdIndex >= firstPath.Num())
	{
		//no need to fast-forward
		return false;
	}

	//create the fast-forward branch
	auto newBranch = FArticyBranch{};
	newBranch.bIsValid = AvailableBranches[0].bIsValid;
	for(int i = 0; i <= ffwdIndex; ++i)
	{
		//add node to branch
		newBranch.Path.Add(firstPath[i]);
	}

	//this also calls UpdateAvailableBranches again
	PlayBranch(newBranch);

	return true;
}

void UArticyFlowPlayer::PlayBranch(const FArticyBranch& Branch)
{
	if(!ensure(ShadowLevel == 0))
	{
		UE_LOG(LogArticyRuntime, Error, TEXT("ArticyFlowPlayer::Traverse was called inside a ShadowedOperation! Aborting Play."))
		return;
	}

	if (!bDisableExecutingOutputPins)
	{
		for (auto node : Branch.Path)
			node->Execute(GetGVs(), GetMethodsProvider());
	}

	bDisableExecutingOutputPins = false;
	Cursor = Branch.Path.Last();
	UpdateAvailableBranches();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2008 Google Inc.
 * Copyright 2006, 2007 Nintendo Co., Ltd.
 *
 * 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.
 */

#define VERBOSE

#include <es.h>
#include "cpu.h"
#include "io.h"
#include "mps.h"

bool Mps::ConfigurationTableHeader::
accept(Visitor& visitor)
{
    u8* ptr = reinterpret_cast<u8*>(this);
    ptr += sizeof(ConfigurationTableHeader);
    bool cont = true;
    for (int i = 0; cont && i < entryCount; ++i)
    {
        switch (*ptr)
        {
        case PROCESSOR:
            cont = visitor.at(reinterpret_cast<Processor*>(ptr));
            ptr += sizeof(Processor);
            break;
        case BUS:
            cont = visitor.at(reinterpret_cast<Bus*>(ptr));
            ptr += sizeof(Bus);
            break;
        case IO_APIC:
            cont = visitor.at(reinterpret_cast<IOApic*>(ptr));
            ptr += sizeof(IOApic);
            break;
        case IO_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<InterruptAssignment*>(ptr));
            ptr += sizeof(InterruptAssignment);
            break;
        case LOCAL_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<LocalInterruptAssignment*>(ptr));
            ptr += sizeof(LocalInterruptAssignment);
            break;
        default:
            cont = false;
            break;
        }
    }
    return true;
}

Mps::FloatingPointerStructure* Mps::
lookup(void* base, int len)
{
#ifdef VERBOSE
    esReport("Mps::lookup() at %p, %u\n", base, len);
#endif
    u8* ptr = static_cast<u8*>(base);
    while (sizeof(FloatingPointerStructure) <= len--)
    {
        if (ptr[0] == '_' && ptr[1] == 'M' && ptr[2] == 'P' && ptr[3] == '_')
        {
            u8 sum = 0;
            for (int i = 0; i < 16; i++)
            {
                sum += ptr[i];
            }
            if (sum == 0)
            {
                return reinterpret_cast<FloatingPointerStructure*>(ptr);
            }
        }
        ++ptr;
    }
    return 0;
}

Mps::FloatingPointerStructure* Mps::
lookup()
{
    FloatingPointerStructure* fps;
    u16* ebda = reinterpret_cast<u16*>(0x40e);  // for EBDA segment

    if (*ebda)
    {
        // Lookup the first kilobyte of Extended BIOS Data Area.
        fps = lookup(reinterpret_cast<void*>(*ebda * 16), 1024);
        if (fps)
        {
            return fps;
        }
    }
    else
    {
        // Lookup the last kilobyte of system base memory.
        fps = lookup(reinterpret_cast<void*>(*reinterpret_cast<u16*>(0x413) * 1024), 1024);
        if (fps)
        {
            return fps;
        }
    }

    // Lookup the BIOS ROM address space between 0F0000h and 0FFFFFh.
    fps = lookup((void*) 0xf0000, 0x10000);
    if (fps)
    {
        return fps;
    }

    return 0;
}

Mps::
Mps() :
    fps(lookup()),
    cth(0)
{
    ASSERT(sizeof(FloatingPointerStructure) == 16);
    ASSERT(sizeof(ConfigurationTableHeader) == 44);
    ASSERT(sizeof(Processor) == 20);
    ASSERT(sizeof(Bus) == 8);
    ASSERT(sizeof(IOApic) == 8);
    ASSERT(sizeof(InterruptAssignment) == 8);
    ASSERT(sizeof(LocalInterruptAssignment) == 8);

    if (fps == 0)
    {
        return;
    }
#ifdef VERBOSE
    fps->print();
#endif

    cth = reinterpret_cast<ConfigurationTableHeader*>(fps->address);
    if (!cth)
    {
        processorCount = 2;
    }
    else
    {
        cth->accept(processorCount);
#ifdef VERBOSE
        cth->print();
        Printer printer;
        cth->accept(printer);
#endif
    }
    ASSERT(0 < processorCount);
#ifdef VERBOSE
    esReport("MPS %d.%d (%d processor%s)\n",
             1 + fps->specRev / 10, fps->specRev % 10,
             static_cast<int>(processorCount),
             (1 < processorCount) ? "s" : "");
#endif

    fps = reinterpret_cast<FloatingPointerStructure*>(0x80000000 |reinterpret_cast<unsigned long>(fps));
    if (cth)
    {
        cth = reinterpret_cast<ConfigurationTableHeader*>(0x80000000 |reinterpret_cast<unsigned long>(cth));
    }
}

volatile u32* Mps::
getInterruptAssignment(unsigned int bus, unsigned int irq, InterruptAssignment& assignment)
{
    if (cth == 0)
    {
        if (16 <= irq || irq == 2)
        {
            return 0;
        }
        assignment.entryType = IO_INTERRUPT_ASSIGNMENT;
        assignment.type = 0;    // INT
        assignment.flags = 0;
        assignment.busID = 0;
        assignment.busIRQ = irq;
        assignment.apicID = 0;
        assignment.apicINTINn = (irq == 0) ? 2 : irq;
        return reinterpret_cast<u32*>(0xfec00000);
    }

    LookupAssignment entry(bus, irq);
    cth->accept(entry);
    if (!entry)
    {
        return 0;
    }

    LookupIoApic apic(entry->apicID);
    cth->accept(apic);
    if (!apic || !apic->isUsable())
    {
        return 0;
    }

    assignment = *entry;
    return reinterpret_cast<u32*>(apic->address);
}
<commit_msg>(Mps()) : Add a workaround for qemu/Fedora 11.<commit_after>/*
 * Copyright 2008 Google Inc.
 * Copyright 2006, 2007 Nintendo Co., Ltd.
 *
 * 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.
 */

#define VERBOSE

#include <es.h>
#include "cpu.h"
#include "io.h"
#include "mps.h"

bool Mps::ConfigurationTableHeader::
accept(Visitor& visitor)
{
    u8* ptr = reinterpret_cast<u8*>(this);
    ptr += sizeof(ConfigurationTableHeader);
    bool cont = true;
    for (int i = 0; cont && i < entryCount; ++i)
    {
        switch (*ptr)
        {
        case PROCESSOR:
            cont = visitor.at(reinterpret_cast<Processor*>(ptr));
            ptr += sizeof(Processor);
            break;
        case BUS:
            cont = visitor.at(reinterpret_cast<Bus*>(ptr));
            ptr += sizeof(Bus);
            break;
        case IO_APIC:
            cont = visitor.at(reinterpret_cast<IOApic*>(ptr));
            ptr += sizeof(IOApic);
            break;
        case IO_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<InterruptAssignment*>(ptr));
            ptr += sizeof(InterruptAssignment);
            break;
        case LOCAL_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<LocalInterruptAssignment*>(ptr));
            ptr += sizeof(LocalInterruptAssignment);
            break;
        default:
            cont = false;
            break;
        }
    }
    return true;
}

Mps::FloatingPointerStructure* Mps::
lookup(void* base, int len)
{
#ifdef VERBOSE
    esReport("Mps::lookup() at %p, %u\n", base, len);
#endif
    u8* ptr = static_cast<u8*>(base);
    while (sizeof(FloatingPointerStructure) <= len--)
    {
        if (ptr[0] == '_' && ptr[1] == 'M' && ptr[2] == 'P' && ptr[3] == '_')
        {
            u8 sum = 0;
            for (int i = 0; i < 16; i++)
            {
                sum += ptr[i];
            }
            if (sum == 0)
            {
                return reinterpret_cast<FloatingPointerStructure*>(ptr);
            }
        }
        ++ptr;
    }
    return 0;
}

Mps::FloatingPointerStructure* Mps::
lookup()
{
    FloatingPointerStructure* fps;
    u16* ebda = reinterpret_cast<u16*>(0x40e);  // for EBDA segment

    if (*ebda)
    {
        // Lookup the first kilobyte of Extended BIOS Data Area.
        fps = lookup(reinterpret_cast<void*>(*ebda * 16), 1024);
        if (fps)
        {
            return fps;
        }
    }
    else
    {
        // Lookup the last kilobyte of system base memory.
        fps = lookup(reinterpret_cast<void*>(*reinterpret_cast<u16*>(0x413) * 1024), 1024);
        if (fps)
        {
            return fps;
        }
    }

    // Lookup the BIOS ROM address space between 0F0000h and 0FFFFFh.
    fps = lookup((void*) 0xf0000, 0x10000);
    if (fps)
    {
        return fps;
    }

    return 0;
}

Mps::
Mps() :
    fps(lookup()),
    cth(0)
{
    ASSERT(sizeof(FloatingPointerStructure) == 16);
    ASSERT(sizeof(ConfigurationTableHeader) == 44);
    ASSERT(sizeof(Processor) == 20);
    ASSERT(sizeof(Bus) == 8);
    ASSERT(sizeof(IOApic) == 8);
    ASSERT(sizeof(InterruptAssignment) == 8);
    ASSERT(sizeof(LocalInterruptAssignment) == 8);

    if (fps == 0)
    {
        return;
    }
#ifdef VERBOSE
    fps->print();
#endif

    cth = reinterpret_cast<ConfigurationTableHeader*>(fps->address);
    if (!cth)
    {
        processorCount = 2;
    }
    else
    {
        cth->accept(processorCount);
#ifdef VERBOSE
        cth->print();
        Printer printer;
        cth->accept(printer);
#endif
    }
    ASSERT(0 < processorCount);
#ifdef VERBOSE
    esReport("MPS %d.%d (%d processor%s)\n",
             1 + fps->specRev / 10, fps->specRev % 10,
             static_cast<int>(processorCount),
             (1 < processorCount) ? "s" : "");
#endif

    // TODO: The following block is a workaround for qemu/Fedora 11
    //       so as not to use APIC. This should be removed in future.
    if (static_cast<int>(processorCount) == 1)
    {
        fps = 0;
        cth = 0;
        return;
    }

    fps = reinterpret_cast<FloatingPointerStructure*>(0x80000000 |reinterpret_cast<unsigned long>(fps));
    if (cth)
    {
        cth = reinterpret_cast<ConfigurationTableHeader*>(0x80000000 |reinterpret_cast<unsigned long>(cth));
    }
}

volatile u32* Mps::
getInterruptAssignment(unsigned int bus, unsigned int irq, InterruptAssignment& assignment)
{
    if (cth == 0)
    {
        if (16 <= irq || irq == 2)
        {
            return 0;
        }
        assignment.entryType = IO_INTERRUPT_ASSIGNMENT;
        assignment.type = 0;    // INT
        assignment.flags = 0;
        assignment.busID = 0;
        assignment.busIRQ = irq;
        assignment.apicID = 0;
        assignment.apicINTINn = (irq == 0) ? 2 : irq;
        return reinterpret_cast<u32*>(0xfec00000);
    }

    LookupAssignment entry(bus, irq);
    cth->accept(entry);
    if (!entry)
    {
        return 0;
    }

    LookupIoApic apic(entry->apicID);
    cth->accept(apic);
    if (!apic || !apic->isUsable())
    {
        return 0;
    }

    assignment = *entry;
    return reinterpret_cast<u32*>(apic->address);
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2013 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
 **      derived from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "expression_editor/tree_builder/ExpressionTreeBuilder.h"

#include "expression_editor/tree_builder/ExpressionTreeBuildInstruction.h"
#include "expression_editor/tree_builder/AddErrorOperator.h"
#include "expression_editor/tree_builder/AddOperator.h"
#include "expression_editor/tree_builder/FinishOperator.h"

namespace Interaction {

ExpressionTreeBuilder::ExpressionTreeBuilder() : top_(nullptr), left_(nullptr)
{
}

Expression* ExpressionTreeBuilder::build(QVector<ExpressionTreeBuildInstruction*> instructions)
{
	Q_ASSERT(!instructions.isEmpty());

	// Concatenate errors in a single node
	for (int i = instructions.size() - 1; i > 0; --i)
	{
		AddErrorOperator* instr = dynamic_cast<AddErrorOperator*> (instructions[i]);
		AddErrorOperator* prev = dynamic_cast<AddErrorOperator*> (instructions[i-1]);

		if (instr && prev)
		{
			prev->setText(prev->text() + instr->text() );
			instructions.remove(i);

			// The corresponding FinishOperator also needs to be removed
			int num_intermediate_ops = 0;
			for (int x = i; x < instructions.size(); ++x)
			{
				if (dynamic_cast<FinishOperator*> (instructions[x]))
				{
					if (num_intermediate_ops == 0)
					{
						instructions.remove(x);
						break;
					}
					else --num_intermediate_ops;
				} else if( dynamic_cast<AddOperator*> (instructions[x]) || dynamic_cast<AddErrorOperator*> (instructions[x]))
				{
					++num_intermediate_ops;
				}
			}
		}
	}

	// Build the tree
	for (ExpressionTreeBuildInstruction* i : instructions)
		i->perform(*this);

	return top_;
}

} /* namespace InteractionBase */
<commit_msg>Delete unused objects<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2013 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
 **      derived from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "expression_editor/tree_builder/ExpressionTreeBuilder.h"

#include "expression_editor/tree_builder/ExpressionTreeBuildInstruction.h"
#include "expression_editor/tree_builder/AddErrorOperator.h"
#include "expression_editor/tree_builder/AddOperator.h"
#include "expression_editor/tree_builder/FinishOperator.h"

namespace Interaction {

ExpressionTreeBuilder::ExpressionTreeBuilder() : top_(nullptr), left_(nullptr)
{
}

Expression* ExpressionTreeBuilder::build(QVector<ExpressionTreeBuildInstruction*> instructions)
{
	Q_ASSERT(!instructions.isEmpty());

	// Concatenate errors in a single node
	for (int i = instructions.size() - 1; i > 0; --i)
	{
		AddErrorOperator* instr = dynamic_cast<AddErrorOperator*> (instructions[i]);
		AddErrorOperator* prev = dynamic_cast<AddErrorOperator*> (instructions[i-1]);

		if (instr && prev)
		{
			prev->setText(prev->text() + instr->text() );
			SAFE_DELETE(instructions[i]);
			instructions.remove(i);

			// The corresponding FinishOperator also needs to be removed
			int num_intermediate_ops = 0;
			for (int x = i; x < instructions.size(); ++x)
			{
				if (dynamic_cast<FinishOperator*> (instructions[x]))
				{
					if (num_intermediate_ops == 0)
					{
						SAFE_DELETE(instructions[x]);
						instructions.remove(x);
						break;
					}
					else --num_intermediate_ops;
				} else if( dynamic_cast<AddOperator*> (instructions[x]) || dynamic_cast<AddErrorOperator*> (instructions[x]))
				{
					++num_intermediate_ops;
				}
			}
		}
	}

	// Build the tree
	for (ExpressionTreeBuildInstruction* i : instructions)
	{
		i->perform(*this);
		SAFE_DELETE(i);
	}

	return top_;
}

} /* namespace InteractionBase */
<|endoftext|>


<commit_before>//
// Jet trigger rejection analysis task.
//
// Author: M.Verweij

#include <TClonesArray.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH3F.h>
#include <TProfile.h>
#include <THnSparse.h>
#include <TList.h>
#include <TLorentzVector.h>

#include "AliVVZERO.h"
#include "AliEmcalJet.h"
#include "AliRhoParameter.h"
#include "AliLog.h"
#include "AliJetContainer.h"
#include "AliEmcalTriggerPatchInfo.h"
#include "AliPicoTrack.h"

#include "AliAnalysisTaskTriggerRejection.h"

ClassImp(AliAnalysisTaskTriggerRejection)

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::AliAnalysisTaskTriggerRejection() :
  AliAnalysisTaskEmcalJet("AliAnalysisTaskTriggerRejection", kTRUE),
  fContainerFull(0),
  fContainerCharged(1),
  fMaxPatch(0),
  fhnTriggerInfo(0)
{
  // Default constructor.
  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::AliAnalysisTaskTriggerRejection(const char *name) :
  AliAnalysisTaskEmcalJet(name, kTRUE),
  fContainerFull(0),
  fContainerCharged(1),
  fMaxPatch(0),
  fhnTriggerInfo(0)
{
  // Standard constructor.
  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::~AliAnalysisTaskTriggerRejection()
{
  // Destructor.
}

//________________________________________________________________________
void AliAnalysisTaskTriggerRejection::UserCreateOutputObjects()
{
  // Create user output.

  AliAnalysisTaskEmcalJet::UserCreateOutputObjects();

  Bool_t oldStatus = TH1::AddDirectoryStatus();
  TH1::AddDirectory(kFALSE);

  Int_t fgkNCentBins = 21;
  Float_t kMinCent   = 0.;
  Float_t kMaxCent   = 105.;

  Int_t fgkNPtBins = 170;
  Float_t kMinPt   = -50.;
  Float_t kMaxPt   = 120.;

  Int_t fgkNVZEROBins = 100;
  Float_t kMinVZERO   = 0.;
  Float_t kMaxVZERO   = 25000;

  const Int_t fgkNEPatch = 100;
  Float_t kMinEPatch = 0.;
  Float_t kMaxEPatch = 200.;

  const Int_t fgkNADC = 100;
  Float_t kMinADC = 0.;
  Float_t kMaxADC = 1500.;

  const Int_t fgkNEta = 10;
  const Int_t fgkNPhi = 10;

  const Int_t nDim = 8;//cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch
  const Int_t nBins[nDim] = {fgkNCentBins,fgkNVZEROBins,fgkNPtBins,fgkNPtBins,fgkNEPatch,fgkNADC,fgkNEta,fgkNPhi};
  const Double_t xmin0[nDim]  = {kMinCent,kMinVZERO,kMinPt,kMinPt,kMinEPatch,kMinADC,-0.7,1.4};
  const Double_t xmax0[nDim]  = {kMaxCent,kMaxVZERO,kMaxPt,kMaxPt,kMaxEPatch,kMaxADC, 0.7,3.14};
   fhnTriggerInfo = new THnSparseF("fhnTriggerInfo",
				   "hnTriggerInfo;cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch",nDim,nBins,xmin0,xmax0);
   fOutput->Add(fhnTriggerInfo);

  // =========== Switch on Sumw2 for all histos ===========
  for (Int_t i=0; i<fOutput->GetEntries(); ++i) {
    TH1 *h1 = dynamic_cast<TH1*>(fOutput->At(i));
    if (h1){
      h1->Sumw2();
      continue;
    }
    TH2 *h2 = dynamic_cast<TH2*>(fOutput->At(i));
    if (h2){
      h2->Sumw2();
      continue;
    }
    TH3 *h3 = dynamic_cast<TH3*>(fOutput->At(i));
    if (h3){
      h3->Sumw2();
      continue;
    }
    THnSparse *hn = dynamic_cast<THnSparse*>(fOutput->At(i));
    if(hn)hn->Sumw2();
  }

  TH1::AddDirectory(oldStatus);

  PostData(1, fOutput); // Post data for ALL output slots > 0 here.
}

//________________________________________________________________________
void AliAnalysisTaskTriggerRejection::ExtractMainPatch() {

  //Find main trigger
  if(!fTriggerPatchInfo)
    return;

  //number of patches in event
  Int_t nPatch = fTriggerPatchInfo->GetEntriesFast();

  //extract main trigger patch
  Double_t emax = -1.;
  for (Int_t iPatch = 0; iPatch < nPatch; iPatch++) {
    AliEmcalTriggerPatchInfo *patch = (AliEmcalTriggerPatchInfo*)fTriggerPatchInfo->At( iPatch );
    if(patch->GetPatchE()>emax) {
      fMaxPatch = patch;
      emax = patch->GetPatchE();
    }
  }
}
//________________________________________________________________________
Bool_t AliAnalysisTaskTriggerRejection::FillHistograms()
{
  // Fill histograms.

  if(!GetJetContainer(fContainerFull) || !GetJetContainer(fContainerCharged) || !fMaxPatch)
    return kFALSE;

  //Get leading jets
  AliEmcalJet *leadJet1 = GetJetContainer(fContainerFull)->GetLeadingJet("rho");
  AliEmcalJet *leadJet2 = GetJetContainer(fContainerCharged)->GetLeadingJet("rho");

  Double_t ptLeadJet1 = -999;
  Double_t ptLeadJet2 = -999;

  if(leadJet1) ptLeadJet1 = leadJet1->Pt() - GetRhoVal(fContainerFull)*leadJet1->Area();
  if(leadJet2) ptLeadJet2 = leadJet2->Pt() - GetRhoVal(fContainerCharged)*leadJet2->Area();

  Double_t VZEROAmp = (Double_t)(InputEvent()->GetVZEROData()->GetTriggerChargeA() + InputEvent()->GetVZEROData()->GetTriggerChargeC());

  //cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch
  Double_t var[8] = {
    fCent,
    VZEROAmp,
    ptLeadJet1,
    ptLeadJet2,
    fMaxPatch->GetPatchE(),
    fMaxPatch->GetADCAmp(),
    fMaxPatch->GetEtaGeo(),
    fMaxPatch->GetPhiGeo()
  };
  fhnTriggerInfo->Fill(var);

  return kTRUE;
}

//________________________________________________________________________
Bool_t AliAnalysisTaskTriggerRejection::Run()
{
  // Run analysis code here, if needed. It will be executed before FillHistograms().

  if(fTriggerPatchInfo)
    ExtractMainPatch();

  return kTRUE;  // If return kFALSE FillHistogram() will NOT be executed.
}

//_______________________________________________________________________
void AliAnalysisTaskTriggerRejection::Terminate(Option_t *)
{
  // Called once at the end of the analysis.
}
<commit_msg>coverity fix<commit_after>//
// Jet trigger rejection analysis task.
//
// Author: M.Verweij

#include <TClonesArray.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH3F.h>
#include <TProfile.h>
#include <THnSparse.h>
#include <TList.h>
#include <TLorentzVector.h>

#include "AliVVZERO.h"
#include "AliEmcalJet.h"
#include "AliRhoParameter.h"
#include "AliLog.h"
#include "AliJetContainer.h"
#include "AliEmcalTriggerPatchInfo.h"
#include "AliPicoTrack.h"

#include "AliAnalysisTaskTriggerRejection.h"

ClassImp(AliAnalysisTaskTriggerRejection)

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::AliAnalysisTaskTriggerRejection() :
  AliAnalysisTaskEmcalJet("AliAnalysisTaskTriggerRejection", kTRUE),
  fContainerFull(0),
  fContainerCharged(1),
  fMaxPatch(0),
  fhnTriggerInfo(0)
{
  // Default constructor.
  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::AliAnalysisTaskTriggerRejection(const char *name) :
  AliAnalysisTaskEmcalJet(name, kTRUE),
  fContainerFull(0),
  fContainerCharged(1),
  fMaxPatch(0),
  fhnTriggerInfo(0)
{
  // Standard constructor.
  SetMakeGeneralHistograms(kTRUE);
}

//________________________________________________________________________
AliAnalysisTaskTriggerRejection::~AliAnalysisTaskTriggerRejection()
{
  // Destructor.
}

//________________________________________________________________________
void AliAnalysisTaskTriggerRejection::UserCreateOutputObjects()
{
  // Create user output.

  AliAnalysisTaskEmcalJet::UserCreateOutputObjects();

  Bool_t oldStatus = TH1::AddDirectoryStatus();
  TH1::AddDirectory(kFALSE);

  Int_t fgkNCentBins = 21;
  Float_t kMinCent   = 0.;
  Float_t kMaxCent   = 105.;

  Int_t fgkNPtBins = 170;
  Float_t kMinPt   = -50.;
  Float_t kMaxPt   = 120.;

  Int_t fgkNVZEROBins = 100;
  Float_t kMinVZERO   = 0.;
  Float_t kMaxVZERO   = 25000;

  const Int_t fgkNEPatch = 100;
  Float_t kMinEPatch = 0.;
  Float_t kMaxEPatch = 200.;

  const Int_t fgkNADC = 100;
  Float_t kMinADC = 0.;
  Float_t kMaxADC = 1500.;

  const Int_t fgkNEta = 10;
  const Int_t fgkNPhi = 10;

  const Int_t nDim = 8;//cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch
  const Int_t nBins[nDim] = {fgkNCentBins,fgkNVZEROBins,fgkNPtBins,fgkNPtBins,fgkNEPatch,fgkNADC,fgkNEta,fgkNPhi};
  const Double_t xmin0[nDim]  = {kMinCent,kMinVZERO,kMinPt,kMinPt,kMinEPatch,kMinADC,-0.7,1.4};
  const Double_t xmax0[nDim]  = {kMaxCent,kMaxVZERO,kMaxPt,kMaxPt,kMaxEPatch,kMaxADC, 0.7,3.14};
   fhnTriggerInfo = new THnSparseF("fhnTriggerInfo",
				   "hnTriggerInfo;cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch",nDim,nBins,xmin0,xmax0);
   fOutput->Add(fhnTriggerInfo);

  // =========== Switch on Sumw2 for all histos ===========
  for (Int_t i=0; i<fOutput->GetEntries(); ++i) {
    TH1 *h1 = dynamic_cast<TH1*>(fOutput->At(i));
    if (h1){
      h1->Sumw2();
      continue;
    }
    TH2 *h2 = dynamic_cast<TH2*>(fOutput->At(i));
    if (h2){
      h2->Sumw2();
      continue;
    }
    TH3 *h3 = dynamic_cast<TH3*>(fOutput->At(i));
    if (h3){
      h3->Sumw2();
      continue;
    }
    THnSparse *hn = dynamic_cast<THnSparse*>(fOutput->At(i));
    if(hn)hn->Sumw2();
  }

  TH1::AddDirectory(oldStatus);

  PostData(1, fOutput); // Post data for ALL output slots > 0 here.
}

//________________________________________________________________________
void AliAnalysisTaskTriggerRejection::ExtractMainPatch() {

  //Find main trigger
  if(!fTriggerPatchInfo)
    return;

  //number of patches in event
  Int_t nPatch = fTriggerPatchInfo->GetEntriesFast();

  //extract main trigger patch
  Double_t emax = -1.;
  for (Int_t iPatch = 0; iPatch < nPatch; iPatch++) {
    AliEmcalTriggerPatchInfo *patch = (AliEmcalTriggerPatchInfo*)fTriggerPatchInfo->At( iPatch );
    if(patch->GetPatchE()>emax) {
      fMaxPatch = patch;
      emax = patch->GetPatchE();
    }
  }
}
//________________________________________________________________________
Bool_t AliAnalysisTaskTriggerRejection::FillHistograms()
{
  // Fill histograms.

  if(!GetJetContainer(fContainerFull) || !GetJetContainer(fContainerCharged) || !fMaxPatch)
    return kFALSE;

  //Get leading jets
  AliEmcalJet *leadJet1 = GetJetContainer(fContainerFull)->GetLeadingJet("rho");
  AliEmcalJet *leadJet2 = GetJetContainer(fContainerCharged)->GetLeadingJet("rho");

  Double_t ptLeadJet1 = -999;
  Double_t ptLeadJet2 = -999;

  if(leadJet1) ptLeadJet1 = leadJet1->Pt() - GetRhoVal(fContainerFull)*leadJet1->Area();
  if(leadJet2) ptLeadJet2 = leadJet2->Pt() - GetRhoVal(fContainerCharged)*leadJet2->Area();

  Double_t VZEROAmp = (Double_t)(InputEvent()->GetVZEROData()->GetTriggerChargeA() + InputEvent()->GetVZEROData()->GetTriggerChargeC());

  //cent;V0mult;ptjet1;ptjet2;Epatch;ADCpatch;EtaPatch;PhiPatch
  Double_t var[8] = {
    fCent,
    VZEROAmp,
    ptLeadJet1,
    ptLeadJet2,
    fMaxPatch->GetPatchE(),
    (Double_t)fMaxPatch->GetADCAmp(),
    fMaxPatch->GetEtaGeo(),
    fMaxPatch->GetPhiGeo()
  };
  fhnTriggerInfo->Fill(var);

  return kTRUE;
}

//________________________________________________________________________
Bool_t AliAnalysisTaskTriggerRejection::Run()
{
  // Run analysis code here, if needed. It will be executed before FillHistograms().

  if(fTriggerPatchInfo)
    ExtractMainPatch();

  return kTRUE;  // If return kFALSE FillHistogram() will NOT be executed.
}

//_______________________________________________________________________
void AliAnalysisTaskTriggerRejection::Terminate(Option_t *)
{
  // Called once at the end of the analysis.
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_
#define _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_  1

#include    "../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Private {

                /*
                 ********************************************************************************
                 *IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR,PATCHABLE_CONTAINER_VALUE> *
                 ********************************************************************************
                 */
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                inline  IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::IteratorImplHelper_ (IteratorOwnerID owner, PATCHABLE_CONTAINER* data)
                    : inherited ()
                    , fIterator (owner, data)
                {
                    RequireNotNull (data);
                    fIterator.More (static_cast<DataStructureImplValueType_*> (nullptr), true);   //tmphack cuz current backend iterators require a first more() - fix that!
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                inline  IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::~IteratorImplHelper_ ()
                {
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_START (fIterator.fPatchableContainer->fLockSupport) {
                        // must do PatchableContainerHelper<...>::PatchableIteratorMixIn::DTOR login inside lock
                        fIterator.fPatchableContainer->RemoveIterator (&fIterator);
                        Assert (fIterator.fPatchableContainer == nullptr);
                        Assert (fIterator.fNextActiveIterator == nullptr);
                        // could assert owner  - fPatchableContainer - doenst contian us in list
                    }
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                typename Iterator<T>::SharedIRepPtr IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::Clone () const
                {
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_START (fIterator.fPatchableContainer->fLockSupport) {
                        return Iterator<T>::template MakeSharedPtr<IteratorImplHelper_> (*this);
                    }
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                IteratorOwnerID IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::GetOwner () const
                {
                    return fIterator.GetOwner ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More (Memory::Optional<T>* result, bool advance)
                {
                    RequireNotNull (result);
                    More_SFINAE_ (result, advance);
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if<is_same<T, CHECK_KEY>::value>::type*)
                {
                    RequireNotNull (result);
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        fIterator.More (result, advance);
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if < !is_same<T, CHECK_KEY>::value >::type*)
                {
                    RequireNotNull (result);
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        Memory::Optional<DataStructureImplValueType_> tmp;
                        fIterator.More (&tmp, advance);
                        if (tmp.IsPresent ()) {
                            *result = *tmp;
                        }
                        else {
                            result->clear ();
                        }
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                bool    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::Equals (const typename Iterator<T>::IRep* rhs) const
                {
                    RequireNotNull (rhs);
                    using   ActualIterImplType_ =   IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>;
                    RequireMember (rhs, ActualIterImplType_);
                    const ActualIterImplType_* rrhs =   dynamic_cast<const ActualIterImplType_*> (rhs);
                    AssertNotNull (rrhs);
                    AssertNotNull (fIterator.fPatchableContainer);
                    // @todo - FIX to use lock-2-at-a-time lock stuff on LHS and RHS
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        return fIterator.Equals (rrhs->fIterator);
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }

                /*
                 ********************************************************************************
                 **IteratorImplHelper_ExternalSync_<T,CONTAINER, CONTAINER_ITERATOR,CONTAINER_VALUE>**
                 ********************************************************************************
                 */
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                inline  IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::IteratorImplHelper_ExternalSync_ (IteratorOwnerID owner, const CONTAINER* data)
                    : inherited ()
                    , fOwner_ (owner)
                    , fIterator (data)
                {
                    RequireNotNull (data);
                    fIterator.More (static_cast<DataStructureImplValueType_*> (nullptr), true);   //tmphack cuz current backend iterators require a first more() - fix that!
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                typename Iterator<T>::SharedIRepPtr IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::Clone () const
                {
                    return Iterator<T>::template MakeSharedPtr<IteratorImplHelper_ExternalSync_> (*this);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                IteratorOwnerID IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::GetOwner () const
                {
                    return fOwner_;
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More (Memory::Optional<T>* result, bool advance)
                {
                    RequireNotNull (result);
                    More_SFINAE_ (result, advance);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if<is_same<T, CHECK_KEY>::value>::type*)
                {
                    RequireNotNull (result);
                    fIterator.More (result, advance);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if < !is_same<T, CHECK_KEY>::value >::type*)
                {
                    RequireNotNull (result);
                    Memory::Optional<DataStructureImplValueType_> tmp;
                    fIterator.More (&tmp, advance);
                    if (tmp.IsPresent ()) {
                        *result = *tmp;
                    }
                    else {
                        result->clear ();
                    }
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                bool    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::Equals (const typename Iterator<T>::IRep* rhs) const
                {
                    RequireNotNull (rhs);
                    using   ActualIterImplType_ =   IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_ITERATOR>;
                    RequireMember (rhs, ActualIterImplType_);
                    const ActualIterImplType_* rrhs =   dynamic_cast<const ActualIterImplType_*> (rhs);
                    AssertNotNull (rrhs);
                    return fIterator.Equals (rrhs->fIterator);
                }

            }
        }
    }
}

#endif /* _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_ */
<commit_msg>fixed serious typo with IteratorImplHelper_ExternalSync_<T, ><commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_
#define _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_  1

#include    "../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Private {

                /*
                 ********************************************************************************
                 *IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR,PATCHABLE_CONTAINER_VALUE> *
                 ********************************************************************************
                 */
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                inline  IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::IteratorImplHelper_ (IteratorOwnerID owner, PATCHABLE_CONTAINER* data)
                    : inherited ()
                    , fIterator (owner, data)
                {
                    RequireNotNull (data);
                    fIterator.More (static_cast<DataStructureImplValueType_*> (nullptr), true);   //tmphack cuz current backend iterators require a first more() - fix that!
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                inline  IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::~IteratorImplHelper_ ()
                {
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_START (fIterator.fPatchableContainer->fLockSupport) {
                        // must do PatchableContainerHelper<...>::PatchableIteratorMixIn::DTOR login inside lock
                        fIterator.fPatchableContainer->RemoveIterator (&fIterator);
                        Assert (fIterator.fPatchableContainer == nullptr);
                        Assert (fIterator.fNextActiveIterator == nullptr);
                        // could assert owner  - fPatchableContainer - doenst contian us in list
                    }
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                typename Iterator<T>::SharedIRepPtr IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::Clone () const
                {
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_START (fIterator.fPatchableContainer->fLockSupport) {
                        return Iterator<T>::template MakeSharedPtr<IteratorImplHelper_> (*this);
                    }
                    CONTAINER_LOCK_HELPER_ITERATORLISTUPDATE_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                IteratorOwnerID IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::GetOwner () const
                {
                    return fIterator.GetOwner ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More (Memory::Optional<T>* result, bool advance)
                {
                    RequireNotNull (result);
                    More_SFINAE_ (result, advance);
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if<is_same<T, CHECK_KEY>::value>::type*)
                {
                    RequireNotNull (result);
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        fIterator.More (result, advance);
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if < !is_same<T, CHECK_KEY>::value >::type*)
                {
                    RequireNotNull (result);
                    AssertNotNull (fIterator.fPatchableContainer);
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        Memory::Optional<DataStructureImplValueType_> tmp;
                        fIterator.More (&tmp, advance);
                        if (tmp.IsPresent ()) {
                            *result = *tmp;
                        }
                        else {
                            result->clear ();
                        }
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }
                template    <typename T, typename PATCHABLE_CONTAINER, typename PATCHABLE_CONTAINER_ITERATOR, typename PATCHABLE_CONTAINER_VALUE>
                bool    IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>::Equals (const typename Iterator<T>::IRep* rhs) const
                {
                    RequireNotNull (rhs);
                    using   ActualIterImplType_ =   IteratorImplHelper_<T, PATCHABLE_CONTAINER, PATCHABLE_CONTAINER_ITERATOR, PATCHABLE_CONTAINER_VALUE>;
                    RequireMember (rhs, ActualIterImplType_);
                    const ActualIterImplType_* rrhs =   dynamic_cast<const ActualIterImplType_*> (rhs);
                    AssertNotNull (rrhs);
                    AssertNotNull (fIterator.fPatchableContainer);
                    // @todo - FIX to use lock-2-at-a-time lock stuff on LHS and RHS
                    CONTAINER_LOCK_HELPER_START (fIterator.fPatchableContainer->fLockSupport) {
                        return fIterator.Equals (rrhs->fIterator);
                    }
                    CONTAINER_LOCK_HELPER_END ();
                }

                /*
                 ********************************************************************************
                 **IteratorImplHelper_ExternalSync_<T,CONTAINER, CONTAINER_ITERATOR,CONTAINER_VALUE>**
                 ********************************************************************************
                 */
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                inline  IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::IteratorImplHelper_ExternalSync_ (IteratorOwnerID owner, const CONTAINER* data)
                    : inherited ()
                    , fOwner_ (owner)
                    , fIterator (data)
                {
                    RequireNotNull (data);
                    fIterator.More (static_cast<DataStructureImplValueType_*> (nullptr), true);   //tmphack cuz current backend iterators require a first more() - fix that!
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                typename Iterator<T>::SharedIRepPtr IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::Clone () const
                {
                    return Iterator<T>::template MakeSharedPtr<IteratorImplHelper_ExternalSync_> (*this);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                IteratorOwnerID IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::GetOwner () const
                {
                    return fOwner_;
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More (Memory::Optional<T>* result, bool advance)
                {
                    RequireNotNull (result);
                    More_SFINAE_ (result, advance);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if<is_same<T, CHECK_KEY>::value>::type*)
                {
                    RequireNotNull (result);
                    fIterator.More (result, advance);
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                template    <typename CHECK_KEY>
                inline  void    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::More_SFINAE_ (Memory::Optional<T>* result, bool advance, typename std::enable_if < !is_same<T, CHECK_KEY>::value >::type*)
                {
                    RequireNotNull (result);
                    Memory::Optional<DataStructureImplValueType_> tmp;
                    fIterator.More (&tmp, advance);
                    if (tmp.IsPresent ()) {
                        *result = *tmp;
                    }
                    else {
                        result->clear ();
                    }
                }
                template    <typename T, typename CONTAINER, typename CONTAINER_ITERATOR, typename CONTAINER_VALUE>
                bool    IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>::Equals (const typename Iterator<T>::IRep* rhs) const
                {
                    RequireNotNull (rhs);
                    using   ActualIterImplType_ =   IteratorImplHelper_ExternalSync_<T, CONTAINER, CONTAINER_ITERATOR, CONTAINER_VALUE>;
                    RequireMember (rhs, ActualIterImplType_);
                    const ActualIterImplType_* rrhs =   dynamic_cast<const ActualIterImplType_*> (rhs);
                    AssertNotNull (rrhs);
                    return fIterator.Equals (rrhs->fIterator);
                }

            }
        }
    }
}

#endif /* _Stroika_Foundation_Containers_Private_IteratorImplHelper_inl_ */
<|endoftext|>