<commit_before>/*
 * Copyright (c) 2016, The Bifrost Authors. 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 Bifrost Authors 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 ``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 OWNER 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 <bifrost/proclog.h>
#include "trace.hpp"
#include "proclog.hpp"

#include <fstream>
#include <cstdlib>     // For system
#include <cstdarg>     // For va_start, va_list, va_end
#include <sys/file.h>  // For flock
#include <sys/stat.h>  // For fstat
#include <sys/types.h> // For getpid
#include <dirent.h>    // For opendir, readdir, closedir
#include <unistd.h>    // For getpid
#include <system_error>
#include <set>
#include <mutex>

void make_dir(std::string path, int perms=775) {
	if( std::system(("mkdir -p "+path+" -m "+std::to_string(perms)).c_str()) ) {
		throw std::runtime_error("Failed to create path: "+path);
	}
}
void remove_all(std::string path) {
	if( std::system(("rm -rf "+path).c_str()) ) {
		throw std::runtime_error("Failed to remove all: "+path);
	}
}
void remove_dir(std::string path) {
	if( std::system(("rmdir "+path+" 2> /dev/null").c_str()) ) {
		throw std::runtime_error("Failed to remove dir: "+path);
	}
}
void remove_file(std::string path) {
	if( std::system(("rm -f "+path).c_str()) ) {
		throw std::runtime_error("Failed to remove file: "+path);
	}
}
bool process_exists(pid_t pid) {
	struct stat s;
	return !(stat(("/proc/"+std::to_string(pid)).c_str(), &s) == -1
	         && errno == ENOENT);
}

std::string get_dirname(std::string filename) {
	// TODO: This is crude, but works for our proclog use-case
	return filename.substr(0, filename.find_last_of("/"));
}

class LockFile {
	std::string _lockfile;
	int         _fd;
public:
	LockFile(LockFile const& ) = delete;
	LockFile& operator=(LockFile const& ) = delete;
	LockFile(std::string lockfile) : _lockfile(lockfile) {
		while( true ) {
			_fd = open(_lockfile.c_str(), O_CREAT, 600);
			flock(_fd, LOCK_EX);
			struct stat fd_stat, lockfile_stat;
			fstat(_fd, &fd_stat);
			stat(_lockfile.c_str(), &lockfile_stat);
			// Compare inodes
			if( fd_stat.st_ino == lockfile_stat.st_ino ) {
				// Got the lock
				break;
			}
			close(_fd);
		}
	}
	~LockFile() {
		unlink(_lockfile.c_str());
		flock(_fd, LOCK_UN);
	}
};

class ProcLogMgr {
	static constexpr const char* base_logdir = "/dev/shm/bifrost";
	std::string            _logdir;
	std::set<std::string>  _logs;
	std::set<std::string>  _created_dirs;
	mutable std::mutex     _mutex;
	void try_base_logdir_cleanup() {
		// Do this with a file lock to avoid interference from other processes
		LockFile lock(std::string(base_logdir) + ".lock");
		DIR* dp;
		// Remove pid dirs for which a corresponding process does not exist
		if( (dp = opendir(base_logdir)) ) {
			struct dirent* ep;
			while( (ep = readdir(dp)) ) {
				pid_t pid = atoi(ep->d_name);
				if( pid && !process_exists(pid) ) {
					remove_all(std::string(base_logdir) + "/" +
					           std::to_string(pid));
				}
			}
			closedir(dp);
		}
		// Remove the base_logdir if it's empty
		try { remove_dir(base_logdir); }
		catch( std::exception ) {}
	}
	ProcLogMgr()
		: _logdir(std::string(base_logdir) + "/" + std::to_string(getpid())) {
		this->try_base_logdir_cleanup();
		make_dir(base_logdir, 777);
		make_dir(_logdir);
	}
	~ProcLogMgr() {
		try {
			remove_all(_logdir);
			this->try_base_logdir_cleanup();
		} catch( std::exception ) {}
	}
	FILE* open_file(std::string filename) {
		// Note: Individual log dirs and files are only created if they are
		//         actually updated with data.
		// Note: name may contain subdirs, so we must ensure they exist first
		this->ensure_dir_exists(filename);
		FILE* logfile = (FILE*)fopen(filename.c_str(), "w");
		if( !logfile ) {
			throw std::runtime_error("fopen(\""+filename+"\", \"w\") failed");
		}
		return logfile;
	}
public:
	ProcLogMgr(ProcLogMgr& ) = delete;
	ProcLogMgr& operator=(ProcLogMgr& ) = delete;
	static ProcLogMgr& get() {
		static ProcLogMgr proclog;
		return proclog;
	}
	void ensure_dir_exists(std::string filename) {
		std::string dirname = get_dirname(filename);
		if( !_created_dirs.count(dirname) ) {
			// Note: make_dir is really slow, so we ensure we call it only once
			make_dir(dirname);
			_created_dirs.insert(dirname);
		}
	}
	std::string create_log(std::string name) {
		std::lock_guard<std::mutex> lock(_mutex);
		std::string origname = name;
		int i = 1;
		while( _logs.count(name) ) {
			// Disambiguate by adding suffix to name
			name = origname + "_" + std::to_string(++i);
		}
		std::string filename = _logdir + "/" + name;
		_logs.insert(filename);
		return filename;
	}
	void destroy_log(std::string filename) {
		std::lock_guard<std::mutex> lock(_mutex);
		remove_file(filename);
		_logs.erase(filename);
	}
	void update_log_s(std::string filename, const char* str) {
		std::lock_guard<std::mutex> lock(_mutex);
		FILE* logfile = this->open_file(filename);
		fputs(str, logfile);
		fclose(logfile);
	}
	void update_log_v(std::string filename, const char* fmt, va_list args) {
		std::lock_guard<std::mutex> lock(_mutex);
		FILE* logfile = this->open_file(filename);
		vfprintf(logfile, fmt, args);
		fclose(logfile);
	}
};

BFproclog_impl::BFproclog_impl(std::string name)
	: _filename(ProcLogMgr::get().create_log(name)) {}
BFproclog_impl::~BFproclog_impl() {
	ProcLogMgr::get().destroy_log(_filename);
}
void BFproclog_impl::update_s(const char* str) {
	ProcLogMgr::get().update_log_s(_filename, str);
}
void BFproclog_impl::update_v(const char* fmt, va_list args) {
	ProcLogMgr::get().update_log_v(_filename, fmt, args);
}
void BFproclog_impl::update(const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	this->update_v(fmt, args);
	va_end(args);
}
movable_ofstream_WAR BFproclog_impl::update() {
	ProcLogMgr::get().ensure_dir_exists(_filename);
	// TODO: gcc < 5 has a bug where std streams are not movable
	//return std::ofstream(_filename);
	return movable_ofstream_WAR(_filename);
}

BFstatus bfProcLogCreate(BFproclog* log_ptr, const char* name) {
	BF_ASSERT(log_ptr, BF_STATUS_INVALID_POINTER);
	BF_ASSERT(name,    BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN_ELSE(*log_ptr = new BFproclog_impl(name),
	                   *log_ptr = 0);
}
BFstatus bfProcLogDestroy(BFproclog log) {
	BF_ASSERT(log, BF_STATUS_INVALID_HANDLE);
	delete log;
	return BF_STATUS_SUCCESS;
}
BFstatus bfProcLogUpdate(BFproclog log, const char* str) {
	BF_ASSERT(log, BF_STATUS_INVALID_HANDLE);
	BF_ASSERT(str, BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN(log->update_s(str));
}
<commit_msg>Cleaned up proclog.cpp to better deal with pipelines using multiple version of the same block. This is done by looking for a '/' in the logname and splitting on that character to get the block name for de-duplication purposes.<commit_after>/*
 * Copyright (c) 2016, The Bifrost Authors. 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 Bifrost Authors 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 ``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 OWNER 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 <bifrost/proclog.h>
#include "trace.hpp"
#include "proclog.hpp"

#include <fstream>
#include <cstdlib>     // For system
#include <cstdarg>     // For va_start, va_list, va_end
#include <sys/file.h>  // For flock
#include <sys/stat.h>  // For fstat
#include <sys/types.h> // For getpid
#include <dirent.h>    // For opendir, readdir, closedir
#include <unistd.h>    // For getpid
#include <system_error>
#include <set>
#include <mutex>

void make_dir(std::string path, int perms=775) {
	if( std::system(("mkdir -p "+path+" -m "+std::to_string(perms)).c_str()) ) {
		throw std::runtime_error("Failed to create path: "+path);
	}
}
void remove_all(std::string path) {
	if( std::system(("rm -rf "+path).c_str()) ) {
		throw std::runtime_error("Failed to remove all: "+path);
	}
}
void remove_dir(std::string path) {
	if( std::system(("rmdir "+path+" 2> /dev/null").c_str()) ) {
		throw std::runtime_error("Failed to remove dir: "+path);
	}
}
void remove_file(std::string path) {
	if( std::system(("rm -f "+path).c_str()) ) {
		throw std::runtime_error("Failed to remove file: "+path);
	}
}
bool process_exists(pid_t pid) {
	struct stat s;
	return !(stat(("/proc/"+std::to_string(pid)).c_str(), &s) == -1
	         && errno == ENOENT);
}

std::string get_dirname(std::string filename) {
	// TODO: This is crude, but works for our proclog use-case
	return filename.substr(0, filename.find_last_of("/"));
}

class LockFile {
	std::string _lockfile;
	int         _fd;
public:
	LockFile(LockFile const& ) = delete;
	LockFile& operator=(LockFile const& ) = delete;
	LockFile(std::string lockfile) : _lockfile(lockfile) {
		while( true ) {
			_fd = open(_lockfile.c_str(), O_CREAT, 600);
			flock(_fd, LOCK_EX);
			struct stat fd_stat, lockfile_stat;
			fstat(_fd, &fd_stat);
			stat(_lockfile.c_str(), &lockfile_stat);
			// Compare inodes
			if( fd_stat.st_ino == lockfile_stat.st_ino ) {
				// Got the lock
				break;
			}
			close(_fd);
		}
	}
	~LockFile() {
		unlink(_lockfile.c_str());
		flock(_fd, LOCK_UN);
	}
};

class ProcLogMgr {
	static constexpr const char* base_logdir = "/dev/shm/bifrost";
	std::string            _logdir;
	std::set<std::string>  _logs;
	std::set<std::string>  _created_dirs;
	mutable std::mutex     _mutex;
	void try_base_logdir_cleanup() {
		// Do this with a file lock to avoid interference from other processes
		LockFile lock(std::string(base_logdir) + ".lock");
		DIR* dp;
		// Remove pid dirs for which a corresponding process does not exist
		if( (dp = opendir(base_logdir)) ) {
			struct dirent* ep;
			while( (ep = readdir(dp)) ) {
				pid_t pid = atoi(ep->d_name);
				if( pid && !process_exists(pid) ) {
					remove_all(std::string(base_logdir) + "/" +
					           std::to_string(pid));
				}
			}
			closedir(dp);
		}
		// Remove the base_logdir if it's empty
		try { remove_dir(base_logdir); }
		catch( std::exception ) {}
	}
	ProcLogMgr()
		: _logdir(std::string(base_logdir) + "/" + std::to_string(getpid())) {
		this->try_base_logdir_cleanup();
		make_dir(base_logdir, 777);
		make_dir(_logdir);
	}
	~ProcLogMgr() {
		try {
			remove_all(_logdir);
			this->try_base_logdir_cleanup();
		} catch( std::exception ) {}
	}
	FILE* open_file(std::string filename) {
		// Note: Individual log dirs and files are only created if they are
		//         actually updated with data.
		// Note: name may contain subdirs, so we must ensure they exist first
		this->ensure_dir_exists(filename);
		FILE* logfile = (FILE*)fopen(filename.c_str(), "w");
		if( !logfile ) {
			throw std::runtime_error("fopen(\""+filename+"\", \"w\") failed");
		}
		return logfile;
	}
public:
	ProcLogMgr(ProcLogMgr& ) = delete;
	ProcLogMgr& operator=(ProcLogMgr& ) = delete;
	static ProcLogMgr& get() {
		static ProcLogMgr proclog;
		return proclog;
	}
	void ensure_dir_exists(std::string filename) {
		std::string dirname = get_dirname(filename);
		if( !_created_dirs.count(dirname) ) {
			// Note: make_dir is really slow, so we ensure we call it only once
			make_dir(dirname);
			_created_dirs.insert(dirname);
		}
	}
	std::string create_log(std::string name) {
		std::lock_guard<std::mutex> lock(_mutex);
		std::string origname = name;
		std::string modname = name.substr(0, name.find("/"));
		std::string logname = name.substr(name.find("/"), name.length());
		std::string filename = _logdir + "/" + name;

		int i = 1;
		while( _logs.count(filename) ) {
			// Disambiguate by adding suffix to name
			name = modname + "_" + std::to_string(++i);
			if( logname.length() > 0 ) {
				name = name + "/" + logname;
			}
			filename = _logdir + "/" + name;
		}
		_logs.insert(filename);
		return filename;
	}
	void destroy_log(std::string filename) {
		std::lock_guard<std::mutex> lock(_mutex);
		remove_file(filename);
		_logs.erase(filename);
	}
	void update_log_s(std::string filename, const char* str) {
		std::lock_guard<std::mutex> lock(_mutex);
		FILE* logfile = this->open_file(filename);
		fputs(str, logfile);
		fclose(logfile);
	}
	void update_log_v(std::string filename, const char* fmt, va_list args) {
		std::lock_guard<std::mutex> lock(_mutex);
		FILE* logfile = this->open_file(filename);
		vfprintf(logfile, fmt, args);
		fclose(logfile);
	}
};

BFproclog_impl::BFproclog_impl(std::string name)
	: _filename(ProcLogMgr::get().create_log(name)) {}
BFproclog_impl::~BFproclog_impl() {
	ProcLogMgr::get().destroy_log(_filename);
}
void BFproclog_impl::update_s(const char* str) {
	ProcLogMgr::get().update_log_s(_filename, str);
}
void BFproclog_impl::update_v(const char* fmt, va_list args) {
	ProcLogMgr::get().update_log_v(_filename, fmt, args);
}
void BFproclog_impl::update(const char* fmt, ...) {
	va_list args;
	va_start(args, fmt);
	this->update_v(fmt, args);
	va_end(args);
}
movable_ofstream_WAR BFproclog_impl::update() {
	ProcLogMgr::get().ensure_dir_exists(_filename);
	// TODO: gcc < 5 has a bug where std streams are not movable
	//return std::ofstream(_filename);
	return movable_ofstream_WAR(_filename);
}

BFstatus bfProcLogCreate(BFproclog* log_ptr, const char* name) {
	BF_ASSERT(log_ptr, BF_STATUS_INVALID_POINTER);
	BF_ASSERT(name,    BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN_ELSE(*log_ptr = new BFproclog_impl(name),
	                   *log_ptr = 0);
}
BFstatus bfProcLogDestroy(BFproclog log) {
	BF_ASSERT(log, BF_STATUS_INVALID_HANDLE);
	delete log;
	return BF_STATUS_SUCCESS;
}
BFstatus bfProcLogUpdate(BFproclog log, const char* str) {
	BF_ASSERT(log, BF_STATUS_INVALID_HANDLE);
	BF_ASSERT(str, BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN(log->update_s(str));
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014, Alberto Corona <alberto@0x1a.us>
// All rights reserved. This file is part of yabs, distributed under the BSD
// 3-Clause license. For full terms please see the LICENSE file.

#include <regex.h>
#include <string.h>
#include <yaml.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include "profile.h"

Profile::Profile()
{
	DocNum = 0;
}

void Profile::IncDocNum()
{
	DocNum++;
}

int Profile::AssertConfig(unsigned char *value)
{
	if (CompValid(value) != 1) {
		printf("Error: invalid configuration option: %s\n", value);
		return -1;
	}
	return 0;
}

const char *Profile::ConvValue(unsigned char *conv_value)
{
	std::string temp_value;
	temp_value.append(reinterpret_cast<const char *>(conv_value));
	return temp_value.c_str();
}

int Profile::CompValid(unsigned char *comp_value)
{
	for (int i = 0; i <= MAX_OPT - 1; i++) {
		if (strcasecmp(STDValues[i], ConvValue(comp_value)) == 0) {
			return 1;
		}
	}
	return 0;
}

const char *Profile::PrependLink(const char *string, const char *pre)
{
	std::string temp_string = string;
	std::string temp_pre = pre;
	std::string n_pre = " ";
	size_t start_pos = 0;
	while ((start_pos = temp_string.find(n_pre, start_pos)) != std::string::npos) {
		temp_string.replace(start_pos, n_pre.length(), temp_pre);
		start_pos += temp_pre.length();
	}
	return temp_string.c_str();
}

void Profile::OpenInclude(const char *file)
{
	inc_conf = fopen(file, "r");
	if (inc_conf == NULL) {
		printf("Error: Couldn't open included file: %s\n", file);
	}
}

void Profile::PopValidValue(std::string &k_value, const char *v_value)
{
	if (strcasecmp("os", k_value.c_str()) == 0) {
		OSList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("arch", k_value.c_str()) == 0) {
		ArchList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("cc", k_value.c_str()) == 0) {
		CCList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("cxx", k_value.c_str()) == 0) {
		CXXList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("include", k_value.c_str()) == 0) {
		ConfIncList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("lang", k_value.c_str()) == 0) {
		LangList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("dist", k_value.c_str()) == 0) {
		DistList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("before-script", k_value.c_str()) == 0) {
		BeforeScriptList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("after-script", k_value.c_str()) == 0) {
		AfterScriptList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("libs", k_value.c_str()) == 0) {
		LibsList.push_back(PrependLink(v_value, " -l"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("incdir", k_value.c_str()) == 0) {
		IncDirList.push_back(PrependLink(v_value, " -I"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("libdir", k_value.c_str()) == 0) {
		LibDirList.push_back(PrependLink(v_value, " -L"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("target", k_value.c_str()) == 0) {
		TargetList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("remote", k_value.c_str()) == 0) {
		RemoteList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("defines", k_value.c_str()) == 0) {
		DefinesList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
}
<commit_msg>profile: remove unused headers<commit_after>// Copyright (c) 2013-2014, Alberto Corona <alberto@0x1a.us>
// All rights reserved. This file is part of yabs, distributed under the BSD
// 3-Clause license. For full terms please see the LICENSE file.

#include <string.h>
#include <yaml.h>
#include <iostream>
#include <string>
#include <vector>
#include "profile.h"

Profile::Profile()
{
	DocNum = 0;
}

void Profile::IncDocNum()
{
	DocNum++;
}

int Profile::AssertConfig(unsigned char *value)
{
	if (CompValid(value) != 1) {
		printf("Error: invalid configuration option: %s\n", value);
		return -1;
	}
	return 0;
}

const char *Profile::ConvValue(unsigned char *conv_value)
{
	std::string temp_value;
	temp_value.append(reinterpret_cast<const char *>(conv_value));
	return temp_value.c_str();
}

int Profile::CompValid(unsigned char *comp_value)
{
	for (int i = 0; i <= MAX_OPT - 1; i++) {
		if (strcasecmp(STDValues[i], ConvValue(comp_value)) == 0) {
			return 1;
		}
	}
	return 0;
}

const char *Profile::PrependLink(const char *string, const char *pre)
{
	std::string temp_string = string;
	std::string temp_pre = pre;
	std::string n_pre = " ";
	size_t start_pos = 0;
	while ((start_pos = temp_string.find(n_pre, start_pos)) != std::string::npos) {
		temp_string.replace(start_pos, n_pre.length(), temp_pre);
		start_pos += temp_pre.length();
	}
	return temp_string.c_str();
}

void Profile::OpenInclude(const char *file)
{
	inc_conf = fopen(file, "r");
	if (inc_conf == NULL) {
		printf("Error: Couldn't open included file: %s\n", file);
	}
}

void Profile::PopValidValue(std::string &k_value, const char *v_value)
{
	if (strcasecmp("os", k_value.c_str()) == 0) {
		OSList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("arch", k_value.c_str()) == 0) {
		ArchList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("cc", k_value.c_str()) == 0) {
		CCList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("cxx", k_value.c_str()) == 0) {
		CXXList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("include", k_value.c_str()) == 0) {
		ConfIncList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("lang", k_value.c_str()) == 0) {
		LangList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("dist", k_value.c_str()) == 0) {
		DistList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("before-script", k_value.c_str()) == 0) {
		BeforeScriptList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("after-script", k_value.c_str()) == 0) {
		AfterScriptList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("libs", k_value.c_str()) == 0) {
		LibsList.push_back(PrependLink(v_value, " -l"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("incdir", k_value.c_str()) == 0) {
		IncDirList.push_back(PrependLink(v_value, " -I"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("libdir", k_value.c_str()) == 0) {
		LibDirList.push_back(PrependLink(v_value, " -L"));
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("target", k_value.c_str()) == 0) {
		TargetList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("remote", k_value.c_str()) == 0) {
		RemoteList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
	if (strcasecmp("defines", k_value.c_str()) == 0) {
		DefinesList.push_back(v_value);
		printf("Adding value: %s to key: %s\n", v_value, k_value.c_str());
	}
}
<|endoftext|>


<commit_before>#include <agency/execution_policy.hpp>
#include <mutex>
#include <iostream>
#include <thread>
#include <cassert>

// this is just like std::mutex, except it has a move constructor
// the move constructor just acts like the default constructor
class movable_mutex
{
  public:
    constexpr movable_mutex() = default;

    movable_mutex(const movable_mutex&) = delete;

    movable_mutex(movable_mutex&&)
      : mut_()
    {}

    void lock()
    {
      mut_.lock();
    }

    void unlock()
    {
      mut_.unlock();
    }

  private:
    std::mutex mut_;
};

// this function implements a single concurrent ping pong match
size_t ping_pong_match(agency::concurrent_agent& self, const std::vector<std::string>& names, int num_volleys, movable_mutex& mut, int& ball)
{
  // agent 0 initializes the ball
  if(self.index() == 0)
  {
    ball = 0;
  }

  self.wait();

  auto name = names[self.index()];

  for(int next_state = self.index();
      (next_state < num_volleys) && (ball >= 0);
      next_state += 2)
  {
    // wait for the next volley
    while(ball >= 0 && ball != next_state)
    {
      mut.lock();
      std::cout << name << " waiting for return" << std::endl;
      mut.unlock();

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    mut.lock();
    if(ball == -1)
    {
      std::cout << name << " wins!" << std::endl;
    }
    else
    {
      // try to return the ball
      if(std::rand() % 10 == 0)
      {
        // whiff -- declare outself the loser
        ball = -self.index() - 1;
        std::cout << "whiff... " << name << " loses!" << std::endl;
      }
      else
      {
        // successful return
        ball += 1;
        std::cout << name << "! ball is now " << ball << std::endl;
      }
    }
    mut.unlock();

    std::this_thread::sleep_for(std::chrono::seconds(1));
  }

  // decode who lost the match
  int loser = (ball > 0) ? 1 : -(ball + 1);

  // return the winner
  return loser ^ 1;
}

// this function implements a two concurrent semifinals ping pong matches
// followed by a single final ping pong match
void ping_pong_tournament(agency::concurrent_group<agency::concurrent_agent>& self,
                          const std::vector<std::vector<std::string>>& semifinalists,
                          int num_volleys,
                          movable_mutex& mut,
                          std::vector<std::string>& finalists,
                          int& ball)
{
  if(self.inner().index() == 0)
  {
    if(self.outer().index() == 0)
    {
      std::cout << "Starting semifinal matches..." << std::endl;
    }

    self.outer().wait();
  }

  self.inner().wait();

  // play the semifinals matches
  auto semifinal_winner_idx = ping_pong_match(self.inner(), semifinalists[self.outer().index()], num_volleys, mut, ball);

  if(self.inner().index() == 0)
  {
    // the first agent of each group reports who won the semifinal match
    auto semifinal_winner = semifinalists[self.outer().index()][semifinal_winner_idx];
    finalists[self.outer().index()] = semifinal_winner;

    // have the first player of each group wait for the other group
    self.outer().wait();
  }

  // have each inner group wait for each other
  self.inner().wait();

  // group 0 plays the final match while group 1 sits it out
  if(self.outer().index() == 0)
  {
    // agent 0 initializes the contestant names for the final match
    if(self.inner().index() == 0)
    {
      std::cout << std::endl << finalists[0] << " and " << finalists[1] << " starting the final match..." << std::endl;
    }

    // wait until agent 0 initializes the contestant names before starting the final match
    self.inner().wait();

    // play the final match
    auto final_winner_idx = ping_pong_match(self.inner(), finalists, num_volleys, mut, ball);

    // have agent 0 of group 0 report the winner
    if(self.inner().index() == 0)
    {
      std::cout << std::endl << finalists[final_winner_idx] << " is the tournament champion!" << std::endl;
    }
  }
}

int main()
{
  using namespace agency;
  using namespace std;

  size_t num_volleys = 20;
  vector<vector<string>> semifinalists = {{"ping", "pong"}, {"foo", "bar"}};

  bulk_invoke(con(2, con(2)), ping_pong_tournament, semifinalists, num_volleys, share<0,movable_mutex>(), share<0,vector<string>>(2), share<1,int>());

  return 0;
}

<commit_msg>Use the newer share syntax<commit_after>#include <agency/execution_policy.hpp>
#include <mutex>
#include <iostream>
#include <thread>
#include <cassert>

// this is just like std::mutex, except it has a move constructor
// the move constructor just acts like the default constructor
class movable_mutex
{
  public:
    constexpr movable_mutex() = default;

    movable_mutex(const movable_mutex&) = delete;

    movable_mutex(movable_mutex&&)
      : mut_()
    {}

    void lock()
    {
      mut_.lock();
    }

    void unlock()
    {
      mut_.unlock();
    }

  private:
    std::mutex mut_;
};

// this function implements a single concurrent ping pong match
size_t ping_pong_match(agency::concurrent_agent& self, const std::vector<std::string>& names, int num_volleys, movable_mutex& mut, int& ball)
{
  // agent 0 initializes the ball
  if(self.index() == 0)
  {
    ball = 0;
  }

  self.wait();

  auto name = names[self.index()];

  for(int next_state = self.index();
      (next_state < num_volleys) && (ball >= 0);
      next_state += 2)
  {
    // wait for the next volley
    while(ball >= 0 && ball != next_state)
    {
      mut.lock();
      std::cout << name << " waiting for return" << std::endl;
      mut.unlock();

      std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    mut.lock();
    if(ball == -1)
    {
      std::cout << name << " wins!" << std::endl;
    }
    else
    {
      // try to return the ball
      if(std::rand() % 10 == 0)
      {
        // whiff -- declare outself the loser
        ball = -self.index() - 1;
        std::cout << "whiff... " << name << " loses!" << std::endl;
      }
      else
      {
        // successful return
        ball += 1;
        std::cout << name << "! ball is now " << ball << std::endl;
      }
    }
    mut.unlock();

    std::this_thread::sleep_for(std::chrono::seconds(1));
  }

  // decode who lost the match
  int loser = (ball > 0) ? 1 : -(ball + 1);

  // return the winner
  return loser ^ 1;
}

// this function implements a two concurrent semifinals ping pong matches
// followed by a single final ping pong match
void ping_pong_tournament(agency::concurrent_group<agency::concurrent_agent>& self,
                          const std::vector<std::vector<std::string>>& semifinalists,
                          int num_volleys,
                          movable_mutex& mut,
                          std::vector<std::string>& finalists,
                          int& ball)
{
  if(self.inner().index() == 0)
  {
    if(self.outer().index() == 0)
    {
      std::cout << "Starting semifinal matches..." << std::endl;
    }

    self.outer().wait();
  }

  self.inner().wait();

  // play the semifinals matches
  auto semifinal_winner_idx = ping_pong_match(self.inner(), semifinalists[self.outer().index()], num_volleys, mut, ball);

  if(self.inner().index() == 0)
  {
    // the first agent of each group reports who won the semifinal match
    auto semifinal_winner = semifinalists[self.outer().index()][semifinal_winner_idx];
    finalists[self.outer().index()] = semifinal_winner;

    // have the first player of each group wait for the other group
    self.outer().wait();
  }

  // have each inner group wait for each other
  self.inner().wait();

  // group 0 plays the final match while group 1 sits it out
  if(self.outer().index() == 0)
  {
    // agent 0 initializes the contestant names for the final match
    if(self.inner().index() == 0)
    {
      std::cout << std::endl << finalists[0] << " and " << finalists[1] << " starting the final match..." << std::endl;
    }

    // wait until agent 0 initializes the contestant names before starting the final match
    self.inner().wait();

    // play the final match
    auto final_winner_idx = ping_pong_match(self.inner(), finalists, num_volleys, mut, ball);

    // have agent 0 of group 0 report the winner
    if(self.inner().index() == 0)
    {
      std::cout << std::endl << finalists[final_winner_idx] << " is the tournament champion!" << std::endl;
    }
  }
}

int main()
{
  using namespace agency;
  using namespace std;

  size_t num_volleys = 20;
  vector<vector<string>> semifinalists = {{"ping", "pong"}, {"foo", "bar"}};

  bulk_invoke(con(2, con(2)), ping_pong_tournament, semifinalists, num_volleys, share<movable_mutex>(), share<vector<string>>(2), share_at_scope<1,int>());

  return 0;
}

<|endoftext|>


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

#include <iostream>
#include <string>
#include <ignition/transport.hh>
#include "msg/stringmsg.pb.h"

//////////////////////////////////////////////////
/// \brief Service response callback.
void responseCb(const std::string &_topic,
  const example::mymsgs::StringMsg &_rep, bool _result)
{
  if (_result)
    std::cout << "Response: [" << _rep.data() << "]" << std::endl;
  else
    std::cerr << "Service call failed" << std::endl;
}

//////////////////////////////////////////////////
int main(int argc, char **argv)
{
  // Create a transport node.
  ignition::transport::Node node;

  // Prepare the input parameters.
  example::mymsgs::StringMsg req;
  req.set_data("HELLO");

  // Request the "/echo" service.
  node.Request("/echo", req, responseCb);

  std::this_thread::sleep_for(std::chrono::milliseconds(300));

  // Request the "/echo" service.
  node.Request("/echo", req, responseCb);

  // Wait for the response.
  std::cout << "Press <ENTER> to exit" << std::endl;
  getchar();
}
<commit_msg>Restoring examples.<commit_after>/*
 * Copyright (C) 2014 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

#include <iostream>
#include <string>
#include <ignition/transport.hh>
#include "msg/stringmsg.pb.h"

//////////////////////////////////////////////////
/// \brief Service response callback.
void responseCb(const std::string &_topic,
  const example::mymsgs::StringMsg &_rep, bool _result)
{
  if (_result)
    std::cout << "Response: [" << _rep.data() << "]" << std::endl;
  else
    std::cerr << "Service call failed" << std::endl;
}

//////////////////////////////////////////////////
int main(int argc, char **argv)
{
  // Create a transport node.
  ignition::transport::Node node;

  // Prepare the input parameters.
  example::mymsgs::StringMsg req;
  req.set_data("HELLO");

  // Request the "/echo" service.
  node.Request("/echo", req, responseCb);

  // Wait for the response.
  std::cout << "Press <ENTER> to exit" << std::endl;
  getchar();
}
<|endoftext|>


<commit_before>#include <boost/python.hpp>
#include "ModelInterface.h"
#include "pyToCppModelInterfaceCache.h"

#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <stdexcept>
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <numpy/noprefix.h>

namespace threeML {

template<typename T>
inline
std::vector<T> to_std_vector(const boost::python::object &iterable) {
  return std::vector<T>(boost::python::stl_input_iterator<T>(iterable),
                        boost::python::stl_input_iterator<T>());
}

void pyToCppModelInterfaceCache::setExtSourceBoundaries(const int id, const float lon_min, const float lon_max,
                                                        const float lat_min, const float lat_max)
{

  BoundingBox this_boundingBox;

  this_boundingBox.lon_min = lon_min;
  this_boundingBox.lon_max = lon_max;
  this_boundingBox.lat_min = lat_min;
  this_boundingBox.lat_max = lat_max;

  m_boundingBoxes[id] = this_boundingBox;

}

void pyToCppModelInterfaceCache::setExtSourceCube(const int id, const numeric::array &cube,
                                                  const numeric::array &lon, const numeric::array &lat)
{

  // Add an extended source to the cache (a map)

  PyArrayObject* cube__ = (PyArrayObject*) cube.ptr();

  unsigned int n_points = (unsigned int) *(cube__->dimensions);
  unsigned int n_energies = (unsigned int) *(cube__->dimensions+1);

  // This is n_points * n_energies in size

  double* cube_ = (double *) cube__->data;

  // These are both n_points in size

  double* lon_ = (double *) ((PyArrayObject*) lon.ptr())->data;
  double* lat_ = (double *) ((PyArrayObject*) lat.ptr())->data;

  ExtSrcCube this_srcCube;

  for(unsigned int i=0; i < n_points; ++i)
  {

    float this_lon = (float) lon_[i];
    float this_lat = (float) lat_[i];

    SkyCoord this_coord(this_lon, this_lat);

    // A little of pointer algebra

    int this_data_start = i * n_energies;
    int this_data_stop = this_data_start + n_energies;

    // Note how this construct avoid the double copy which would
    // occur if we were to first create a vector and then
    // copy it into a standard map. Here instead the operator
    // [] creates an empty vector, which is then filled with
    // the assign method

    this_srcCube[this_coord].assign(cube_ + this_data_start, cube_ + this_data_stop);

  }

  // Finally add to the map

  m_extSources[id] = this_srcCube;

}

bool pyToCppModelInterfaceCache::isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const {
  return true;
}

int pyToCppModelInterfaceCache::getNumberOfPointSources() const {

  return m_nPtSources;

}

void pyToCppModelInterfaceCache::getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const {

  throw std::runtime_error("ModelInterfaceCache: point source not yet implemented");
}

void pyToCppModelInterfaceCache::reset() {

  //Empty the cache
  /*
  m_extSources.clear();
  m_boundingBoxes.clear();
  m_nExtSources = 0;
  m_nPtSources = 0;*/

}

std::vector<double>
pyToCppModelInterfaceCache::getPointSourceFluxes(int srcid, std::vector<double> energies) const {

  throw std::runtime_error("ModelInterfaceCache: point source not yet implemented");

}

int pyToCppModelInterfaceCache::getNumberOfExtendedSources() const {

  // We use the size of bounding boxes and not of m_extSources because the latter
  // could get filled in a second moment
  return m_boundingBoxes.size();

}

std::vector<double>
pyToCppModelInterfaceCache::getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                               std::vector<double> energies) const {

  SkyCoord sky_pos(j2000_ra, j2000_dec);

  try {

    return m_extSources.at(srcid).at(sky_pos);

  } catch (...) {

    std::cerr << "Cache failure" << std::endl;

    std::cerr << "Requested id " << srcid << " at position " << j2000_ra << ", " << j2000_dec << std::endl;

  }
}

std::vector<double>
pyToCppModelInterfaceCache::getExtendedSourceFluxes_test(int srcid, double j2000_ra, double j2000_dec) const {

  SkyCoord sky_pos(j2000_ra, j2000_dec);

  try {

    return m_extSources.at(srcid).at(sky_pos);

  } catch (...) {

    std::cerr << "Cache failure" << std::endl;

    std::cerr << "Requested id " << srcid << " at position " << j2000_ra << ", " << j2000_dec << std::endl;

  }

}

std::string pyToCppModelInterfaceCache::getPointSourceName(int srcid) const {

  //TODO: implement a mechanism to actually keep the true name

  std::stringstream name;

  name << "Point source " << srcid;

  return name.str();
}

std::string pyToCppModelInterfaceCache::getExtendedSourceName(int srcid) const {

  //TODO: implement a mechanism to actually keep the true name

  std::stringstream name;

  name << "Extended source " << srcid;

  return name.str();
}

void pyToCppModelInterfaceCache::getExtendedSourceBoundaries(int srcid, double *j2000_ra_min,
                                                        double *j2000_ra_max,
                                                        double *j2000_dec_min,
                                                        double *j2000_dec_max) const {

  const BoundingBox *this_boundingBox = &m_boundingBoxes.at(srcid);

  *j2000_ra_min = this_boundingBox->lon_min;
  *j2000_ra_max = this_boundingBox->lon_max;
  *j2000_dec_min = this_boundingBox->lat_min;
  *j2000_dec_max = this_boundingBox->lat_max;

}

}

using namespace threeML;
using namespace boost::python;

//This is needed to wrap the interface (i.e., all methods are virtual)
//contained in ModelInterface.h
struct ModelInterfaceCacheWrap: ModelInterface, wrapper<ModelInterface> {
  int getNumberOfPointSources() const { return this->get_override("getNumberOfPointSources")(); }

  void getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const {
    this->get_override("getPointSourcePosition")();
  }

  std::vector<double> getPointSourceFluxes(int srcid, std::vector<double> energies) const {
    return this->get_override("getPointSourceFluxes")();
  }

  std::string getPointSourceName(int srcid) const { return this->get_override("getPointSourceName")(); }

  int getNumberOfExtendedSources() const { return this->get_override("getNumberOfExtendedSources")(); }

  std::vector<double> getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                              std::vector<double> energies) const {
    return this->get_override("getExtendedSourceFluxes")();
  }

  std::string getExtendedSourceName(int srcid) const { return this->get_override("getExtendedSourceName")(); }

  bool isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const {
    return this->get_override("isInsideAnyExtendedSource")();
  }

  void getExtendedSourceBoundaries(int srcid, double *j2000_ra_min,
                                   double *j2000_ra_max,
                                   double *j2000_dec_min,
                                   double *j2000_dec_max) const { this->get_override("getExtendedSourceBoundaries")(); }
};

template<class T>
struct VecToList {
  static PyObject *convert(const std::vector<T> &vec) {
    boost::python::list *l = new boost::python::list();

    for (size_t i = 0; i < vec.size(); i++)
      (*l).append(vec[i]);

    return l->ptr();
  }
};

BOOST_PYTHON_MODULE (pyModelInterfaceCache) {
  //hello
  to_python_converter<std::vector<double, std::allocator<double> >, VecToList<double> >();

  class_<ModelInterfaceCacheWrap, boost::noncopyable>("ModelInterface")
      .def("getNumberOfPointSources", pure_virtual(&ModelInterface::getNumberOfPointSources))
      .def("getPointSourcePosition", pure_virtual(&ModelInterface::getPointSourcePosition))
      .def("getPointSourceFluxes", pure_virtual(&ModelInterface::getPointSourceFluxes))
      .def("getPointSourceName", pure_virtual(&ModelInterface::getPointSourceName))
      .def("getNumberOfExtendedSources", pure_virtual(&ModelInterface::getNumberOfExtendedSources))
      .def("getExtendedSourceFluxes", pure_virtual(&ModelInterface::getExtendedSourceFluxes))
      .def("getExtendedSourceName", pure_virtual(&ModelInterface::getExtendedSourceName))
      .def("isInsideAnyExtendedSource", pure_virtual(&ModelInterface::isInsideAnyExtendedSource))
      .def("getExtendedSourceBoundaries", pure_virtual(&ModelInterface::getExtendedSourceBoundaries));

  numeric::array::set_module_and_type("numpy", "ndarray");

  class_<pyToCppModelInterfaceCache, bases<ModelInterface> >("pyToCppModelInterfaceCache", init< >())
      .def("getNumberOfPointSources", &pyToCppModelInterfaceCache::getNumberOfPointSources)
      .def("getPointSourcePosition", &pyToCppModelInterfaceCache::getPointSourcePosition)
      .def("getPointSourceFluxes", &pyToCppModelInterfaceCache::getPointSourceFluxes)
      .def("getPointSourceName", &pyToCppModelInterfaceCache::getPointSourceName)
      .def("getNumberOfExtendedSources", &pyToCppModelInterfaceCache::getNumberOfExtendedSources)
      .def("getExtendedSourceFluxes", &pyToCppModelInterfaceCache::getExtendedSourceFluxes)
      .def("getExtendedSourceName", &pyToCppModelInterfaceCache::getExtendedSourceName)
      .def("isInsideAnyExtendedSource", &pyToCppModelInterfaceCache::isInsideAnyExtendedSource)
      .def("getExtendedSourceBoundaries", &pyToCppModelInterfaceCache::getExtendedSourceBoundaries)
      .def("setExtSourceBoundaries", &pyToCppModelInterfaceCache::setExtSourceBoundaries)
      .def("setExtSourceCube",&pyToCppModelInterfaceCache::setExtSourceCube)
      .def("getExtendedSourceFluxes_test",&pyToCppModelInterfaceCache::getExtendedSourceFluxes_test)
      .def("reset",&pyToCppModelInterfaceCache::reset);
}
<commit_msg>Now reset() empties the extended source pointer map<commit_after>#include <boost/python.hpp>
#include "ModelInterface.h"
#include "pyToCppModelInterfaceCache.h"

#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <stdexcept>
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <numpy/noprefix.h>

namespace threeML {

template<typename T>
inline
std::vector<T> to_std_vector(const boost::python::object &iterable) {
  return std::vector<T>(boost::python::stl_input_iterator<T>(iterable),
                        boost::python::stl_input_iterator<T>());
}

void pyToCppModelInterfaceCache::setExtSourceBoundaries(const int id, const float lon_min, const float lon_max,
                                                        const float lat_min, const float lat_max)
{

  BoundingBox this_boundingBox;

  this_boundingBox.lon_min = lon_min;
  this_boundingBox.lon_max = lon_max;
  this_boundingBox.lat_min = lat_min;
  this_boundingBox.lat_max = lat_max;

  m_boundingBoxes[id] = this_boundingBox;

}

void pyToCppModelInterfaceCache::setExtSourceCube(const int id, const numeric::array &cube,
                                                  const numeric::array &lon, const numeric::array &lat)
{

  // Add an extended source to the cache (a map)

  PyArrayObject* cube__ = (PyArrayObject*) cube.ptr();

  unsigned int n_points = (unsigned int) *(cube__->dimensions);
  unsigned int n_energies = (unsigned int) *(cube__->dimensions+1);

  // This is n_points * n_energies in size

  double* cube_ = (double *) cube__->data;

  // These are both n_points in size

  double* lon_ = (double *) ((PyArrayObject*) lon.ptr())->data;
  double* lat_ = (double *) ((PyArrayObject*) lat.ptr())->data;

  ExtSrcCube this_srcCube;

  for(unsigned int i=0; i < n_points; ++i)
  {

    float this_lon = (float) lon_[i];
    float this_lat = (float) lat_[i];

    SkyCoord this_coord(this_lon, this_lat);

    // A little of pointer algebra

    int this_data_start = i * n_energies;
    int this_data_stop = this_data_start + n_energies;

    // Note how this construct avoid the double copy which would
    // occur if we were to first create a vector and then
    // copy it into a standard map. Here instead the operator
    // [] creates an empty vector, which is then filled with
    // the assign method

    this_srcCube[this_coord].assign(cube_ + this_data_start, cube_ + this_data_stop);

  }

  // Finally add to the map

  m_extSources[id] = this_srcCube;

}

bool pyToCppModelInterfaceCache::isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const {
  return true;
}

int pyToCppModelInterfaceCache::getNumberOfPointSources() const {

  return m_nPtSources;

}

void pyToCppModelInterfaceCache::getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const {

  throw std::runtime_error("ModelInterfaceCache: point source not yet implemented");
}

void pyToCppModelInterfaceCache::reset() {

  //Empty the cache

  m_extSources.clear();
  /*
  m_boundingBoxes.clear();
  m_nExtSources = 0;
  m_nPtSources = 0;*/

}

std::vector<double>
pyToCppModelInterfaceCache::getPointSourceFluxes(int srcid, std::vector<double> energies) const {

  throw std::runtime_error("ModelInterfaceCache: point source not yet implemented");

}

int pyToCppModelInterfaceCache::getNumberOfExtendedSources() const {

  // We use the size of bounding boxes and not of m_extSources because the latter
  // could get filled in a second moment
  return m_boundingBoxes.size();

}

std::vector<double>
pyToCppModelInterfaceCache::getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                               std::vector<double> energies) const {

  SkyCoord sky_pos(j2000_ra, j2000_dec);

  try {

    return m_extSources.at(srcid).at(sky_pos);

  } catch (...) {

    std::cerr << "Cache failure" << std::endl;

    std::cerr << "Requested id " << srcid << " at position " << j2000_ra << ", " << j2000_dec << std::endl;

  }
}

std::vector<double>
pyToCppModelInterfaceCache::getExtendedSourceFluxes_test(int srcid, double j2000_ra, double j2000_dec) const {

  SkyCoord sky_pos(j2000_ra, j2000_dec);

  try {

    return m_extSources.at(srcid).at(sky_pos);

  } catch (...) {

    std::cerr << "Cache failure" << std::endl;

    std::cerr << "Requested id " << srcid << " at position " << j2000_ra << ", " << j2000_dec << std::endl;

  }

}

std::string pyToCppModelInterfaceCache::getPointSourceName(int srcid) const {

  //TODO: implement a mechanism to actually keep the true name

  std::stringstream name;

  name << "Point source " << srcid;

  return name.str();
}

std::string pyToCppModelInterfaceCache::getExtendedSourceName(int srcid) const {

  //TODO: implement a mechanism to actually keep the true name

  std::stringstream name;

  name << "Extended source " << srcid;

  return name.str();
}

void pyToCppModelInterfaceCache::getExtendedSourceBoundaries(int srcid, double *j2000_ra_min,
                                                        double *j2000_ra_max,
                                                        double *j2000_dec_min,
                                                        double *j2000_dec_max) const {

  const BoundingBox *this_boundingBox = &m_boundingBoxes.at(srcid);

  *j2000_ra_min = this_boundingBox->lon_min;
  *j2000_ra_max = this_boundingBox->lon_max;
  *j2000_dec_min = this_boundingBox->lat_min;
  *j2000_dec_max = this_boundingBox->lat_max;

}

}

using namespace threeML;
using namespace boost::python;

//This is needed to wrap the interface (i.e., all methods are virtual)
//contained in ModelInterface.h
struct ModelInterfaceCacheWrap: ModelInterface, wrapper<ModelInterface> {
  int getNumberOfPointSources() const { return this->get_override("getNumberOfPointSources")(); }

  void getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const {
    this->get_override("getPointSourcePosition")();
  }

  std::vector<double> getPointSourceFluxes(int srcid, std::vector<double> energies) const {
    return this->get_override("getPointSourceFluxes")();
  }

  std::string getPointSourceName(int srcid) const { return this->get_override("getPointSourceName")(); }

  int getNumberOfExtendedSources() const { return this->get_override("getNumberOfExtendedSources")(); }

  std::vector<double> getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                              std::vector<double> energies) const {
    return this->get_override("getExtendedSourceFluxes")();
  }

  std::string getExtendedSourceName(int srcid) const { return this->get_override("getExtendedSourceName")(); }

  bool isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const {
    return this->get_override("isInsideAnyExtendedSource")();
  }

  void getExtendedSourceBoundaries(int srcid, double *j2000_ra_min,
                                   double *j2000_ra_max,
                                   double *j2000_dec_min,
                                   double *j2000_dec_max) const { this->get_override("getExtendedSourceBoundaries")(); }
};

template<class T>
struct VecToList {
  static PyObject *convert(const std::vector<T> &vec) {
    boost::python::list *l = new boost::python::list();

    for (size_t i = 0; i < vec.size(); i++)
      (*l).append(vec[i]);

    return l->ptr();
  }
};

BOOST_PYTHON_MODULE (pyModelInterfaceCache) {
  //hello
  to_python_converter<std::vector<double, std::allocator<double> >, VecToList<double> >();

  class_<ModelInterfaceCacheWrap, boost::noncopyable>("ModelInterface")
      .def("getNumberOfPointSources", pure_virtual(&ModelInterface::getNumberOfPointSources))
      .def("getPointSourcePosition", pure_virtual(&ModelInterface::getPointSourcePosition))
      .def("getPointSourceFluxes", pure_virtual(&ModelInterface::getPointSourceFluxes))
      .def("getPointSourceName", pure_virtual(&ModelInterface::getPointSourceName))
      .def("getNumberOfExtendedSources", pure_virtual(&ModelInterface::getNumberOfExtendedSources))
      .def("getExtendedSourceFluxes", pure_virtual(&ModelInterface::getExtendedSourceFluxes))
      .def("getExtendedSourceName", pure_virtual(&ModelInterface::getExtendedSourceName))
      .def("isInsideAnyExtendedSource", pure_virtual(&ModelInterface::isInsideAnyExtendedSource))
      .def("getExtendedSourceBoundaries", pure_virtual(&ModelInterface::getExtendedSourceBoundaries));

  numeric::array::set_module_and_type("numpy", "ndarray");

  class_<pyToCppModelInterfaceCache, bases<ModelInterface> >("pyToCppModelInterfaceCache", init< >())
      .def("getNumberOfPointSources", &pyToCppModelInterfaceCache::getNumberOfPointSources)
      .def("getPointSourcePosition", &pyToCppModelInterfaceCache::getPointSourcePosition)
      .def("getPointSourceFluxes", &pyToCppModelInterfaceCache::getPointSourceFluxes)
      .def("getPointSourceName", &pyToCppModelInterfaceCache::getPointSourceName)
      .def("getNumberOfExtendedSources", &pyToCppModelInterfaceCache::getNumberOfExtendedSources)
      .def("getExtendedSourceFluxes", &pyToCppModelInterfaceCache::getExtendedSourceFluxes)
      .def("getExtendedSourceName", &pyToCppModelInterfaceCache::getExtendedSourceName)
      .def("isInsideAnyExtendedSource", &pyToCppModelInterfaceCache::isInsideAnyExtendedSource)
      .def("getExtendedSourceBoundaries", &pyToCppModelInterfaceCache::getExtendedSourceBoundaries)
      .def("setExtSourceBoundaries", &pyToCppModelInterfaceCache::setExtSourceBoundaries)
      .def("setExtSourceCube",&pyToCppModelInterfaceCache::setExtSourceCube)
      .def("getExtendedSourceFluxes_test",&pyToCppModelInterfaceCache::getExtendedSourceFluxes_test)
      .def("reset",&pyToCppModelInterfaceCache::reset);
}
<|endoftext|>


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

#include "GrCoverageCountingPathRenderer.h"

#include "GrCaps.h"
#include "GrClip.h"
#include "GrProxyProvider.h"
#include "SkMakeUnique.h"
#include "SkPathOps.h"
#include "ccpr/GrCCClipProcessor.h"
#include "ccpr/GrCCDrawPathsOp.h"
#include "ccpr/GrCCPathParser.h"

using PathInstance = GrCCPathProcessor::Instance;

// If a path spans more pixels than this, we need to crop it or else analytic AA can run out of fp32
// precision.
static constexpr float kPathCropThreshold = 1 << 16;

static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
    SkPath cropboxPath;
    cropboxPath.addRect(SkRect::Make(cropbox));
    if (!Op(cropboxPath, path, kIntersect_SkPathOp, out)) {
        // This can fail if the PathOps encounter NaN or infinities.
        out->reset();
    }
    out->setIsVolatile(true);
}

bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
    const GrShaderCaps& shaderCaps = *caps.shaderCaps();
    return shaderCaps.integerSupport() && shaderCaps.flatInterpolationSupport() &&
           caps.instanceAttribSupport() && GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
           caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
           caps.isConfigRenderable(kAlpha_half_GrPixelConfig) &&
           !caps.blacklistCoverageCounting();
}

sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSupported(
        const GrCaps& caps, bool drawCachablePaths) {
    auto ccpr = IsSupported(caps) ? new GrCoverageCountingPathRenderer(drawCachablePaths) : nullptr;
    return sk_sp<GrCoverageCountingPathRenderer>(ccpr);
}

GrCCPerOpListPaths* GrCoverageCountingPathRenderer::lookupPendingPaths(uint32_t opListID) {
    auto it = fPendingPaths.find(opListID);
    if (fPendingPaths.end() == it) {
        auto paths = skstd::make_unique<GrCCPerOpListPaths>();
        it = fPendingPaths.insert(std::make_pair(opListID, std::move(paths))).first;
    }
    return it->second.get();
}

void GrCoverageCountingPathRenderer::adoptAndRecordOp(GrCCDrawPathsOp* op,
                                                      const DrawPathArgs& args) {
    GrRenderTargetContext* rtc = args.fRenderTargetContext;
    if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::unique_ptr<GrDrawOp>(op))) {
        // If the Op wasn't dropped or combined, give it a pointer to its owning GrCCPerOpListPaths.
        op->wasRecorded(this->lookupPendingPaths(opListID));
    }
}

GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
        const CanDrawPathArgs& args) const {
    if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) {
        return CanDrawPath::kNo;
    }

    if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() ||
        args.fViewMatrix->hasPerspective() || GrAAType::kCoverage != args.fAAType) {
        return CanDrawPath::kNo;
    }

    SkPath path;
    args.fShape->asPath(&path);
    SkRect devBounds;
    SkIRect devIBounds;
    args.fViewMatrix->mapRect(&devBounds, path.getBounds());
    devBounds.roundOut(&devIBounds);
    if (!devIBounds.intersect(*args.fClipConservativeBounds)) {
        // Path is completely clipped away. Our code will eventually notice this before doing any
        // real work.
        return CanDrawPath::kYes;
    }

    if (devIBounds.height() * devIBounds.width() > 256 * 256) {
        // Large paths can blow up the atlas fast. And they are not ideal for a two-pass rendering
        // algorithm. Give the simpler direct renderers a chance before we commit to drawing it.
        return CanDrawPath::kAsBackup;
    }

    if (args.fShape->hasUnstyledKey() && path.countVerbs() > 50) {
        // Complex paths do better cached in an SDF, if the renderer will accept them.
        return CanDrawPath::kAsBackup;
    }

    return CanDrawPath::kYes;
}

bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) {
    SkASSERT(!fFlushing);

    SkIRect clipIBounds;
    GrRenderTargetContext* rtc = args.fRenderTargetContext;
    args.fClip->getConservativeBounds(rtc->width(), rtc->height(), &clipIBounds, nullptr);

    SkPath path;
    args.fShape->asPath(&path);

    SkRect devBounds;
    args.fViewMatrix->mapRect(&devBounds, path.getBounds());

    if (SkTMax(devBounds.height(), devBounds.width()) > kPathCropThreshold) {
        // The path is too large. Crop it or analytic AA can run out of fp32 precision.
        SkPath croppedPath;
        path.transform(*args.fViewMatrix, &croppedPath);
        crop_path(croppedPath, clipIBounds, &croppedPath);
        this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                                   SkMatrix::I(), croppedPath,
                                                   croppedPath.getBounds()), args);
        return true;
    }

    this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                               *args.fViewMatrix, path, devBounds), args);
    return true;
}

std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
        GrProxyProvider* proxyProvider,
        uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
        int rtWidth, int rtHeight) {
    using MustCheckBounds = GrCCClipProcessor::MustCheckBounds;

    SkASSERT(!fFlushing);

    GrCCClipPath& clipPath =
            this->lookupPendingPaths(opListID)->fClipPaths[deviceSpacePath.getGenerationID()];
    if (!clipPath.isInitialized()) {
        // This ClipPath was just created during lookup. Initialize it.
        const SkRect& pathDevBounds = deviceSpacePath.getBounds();
        if (SkTMax(pathDevBounds.height(), pathDevBounds.width()) > kPathCropThreshold) {
            // The path is too large. Crop it or analytic AA can run out of fp32 precision.
            SkPath croppedPath;
            int maxRTSize = proxyProvider->caps()->maxRenderTargetSize();
            crop_path(deviceSpacePath, SkIRect::MakeWH(maxRTSize, maxRTSize), &croppedPath);
            clipPath.init(proxyProvider, croppedPath, accessRect, rtWidth, rtHeight);
        } else {
            clipPath.init(proxyProvider, deviceSpacePath, accessRect, rtWidth, rtHeight);
        }
    } else {
        clipPath.addAccess(accessRect);
    }

    bool mustCheckBounds = !clipPath.pathDevIBounds().contains(accessRect);
    return skstd::make_unique<GrCCClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds),
                                                 deviceSpacePath.getFillType());
}

void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP,
                                              const uint32_t* opListIDs, int numOpListIDs,
                                              SkTArray<sk_sp<GrRenderTargetContext>>* atlasDraws) {
    SkASSERT(!fFlushing);
    SkASSERT(fFlushingPaths.empty());
    SkDEBUGCODE(fFlushing = true);

    if (fPendingPaths.empty()) {
        return;  // Nothing to draw.
    }

    // Move the per-opList paths that are about to be flushed from fPendingPaths to fFlushingPaths,
    // and count up the paths about to be flushed so we can preallocate buffers.
    int numPathDraws = 0;
    int numClipPaths = 0;
    GrCCPathParser::PathStats flushingPathStats;
    fFlushingPaths.reserve(numOpListIDs);
    for (int i = 0; i < numOpListIDs; ++i) {
        auto iter = fPendingPaths.find(opListIDs[i]);
        if (fPendingPaths.end() == iter) {
            continue;  // No paths on this opList.
        }

        fFlushingPaths.push_back(std::move(iter->second)).get();
        fPendingPaths.erase(iter);

        for (const GrCCDrawPathsOp* op : fFlushingPaths.back()->fDrawOps) {
            numPathDraws += op->countPaths(&flushingPathStats);
        }
        for (const auto& clipsIter : fFlushingPaths.back()->fClipPaths) {
            flushingPathStats.statPath(clipsIter.second.deviceSpacePath());
        }
        numClipPaths += fFlushingPaths.back()->fClipPaths.size();
    }

    if (0 == numPathDraws + numClipPaths) {
        return;  // Nothing to draw.
    }

    auto resources = sk_make_sp<GrCCPerFlushResources>(onFlushRP, numPathDraws, numClipPaths,
                                                       flushingPathStats);
    if (!resources->isMapped()) {
        return;  // Some allocation failed.
    }

    // Layout atlas(es) and parse paths.
    SkDEBUGCODE(int numSkippedPaths = 0);
    for (const auto& flushingPaths : fFlushingPaths) {
        for (GrCCDrawPathsOp* op : flushingPaths->fDrawOps) {
            op->setupResources(resources.get(), onFlushRP);
            SkDEBUGCODE(numSkippedPaths += op->numSkippedInstances_debugOnly());
        }
        for (auto& clipsIter : flushingPaths->fClipPaths) {
            clipsIter.second.renderPathInAtlas(resources.get(), onFlushRP);
        }
    }
    SkASSERT(resources->nextPathInstanceIdx() == numPathDraws - numSkippedPaths);

    // Allocate the atlases and create instance buffers to draw them.
    if (!resources->finalize(onFlushRP, atlasDraws)) {
        return;
    }

    // Commit flushing paths to the resources once they are successfully completed.
    for (auto& flushingPaths : fFlushingPaths) {
        flushingPaths->fFlushResources = resources;
    }
}

void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint32_t* opListIDs,
                                               int numOpListIDs) {
    SkASSERT(fFlushing);
    // We wait to erase these until after flush, once Ops and FPs are done accessing their data.
    fFlushingPaths.reset();
    SkDEBUGCODE(fFlushing = false);
}
<commit_msg>Drop unneeded .get() in GrCoverageCountingPathRenderer.cpp<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrCoverageCountingPathRenderer.h"

#include "GrCaps.h"
#include "GrClip.h"
#include "GrProxyProvider.h"
#include "SkMakeUnique.h"
#include "SkPathOps.h"
#include "ccpr/GrCCClipProcessor.h"
#include "ccpr/GrCCDrawPathsOp.h"
#include "ccpr/GrCCPathParser.h"

using PathInstance = GrCCPathProcessor::Instance;

// If a path spans more pixels than this, we need to crop it or else analytic AA can run out of fp32
// precision.
static constexpr float kPathCropThreshold = 1 << 16;

static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
    SkPath cropboxPath;
    cropboxPath.addRect(SkRect::Make(cropbox));
    if (!Op(cropboxPath, path, kIntersect_SkPathOp, out)) {
        // This can fail if the PathOps encounter NaN or infinities.
        out->reset();
    }
    out->setIsVolatile(true);
}

bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
    const GrShaderCaps& shaderCaps = *caps.shaderCaps();
    return shaderCaps.integerSupport() && shaderCaps.flatInterpolationSupport() &&
           caps.instanceAttribSupport() && GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
           caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
           caps.isConfigRenderable(kAlpha_half_GrPixelConfig) &&
           !caps.blacklistCoverageCounting();
}

sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSupported(
        const GrCaps& caps, bool drawCachablePaths) {
    auto ccpr = IsSupported(caps) ? new GrCoverageCountingPathRenderer(drawCachablePaths) : nullptr;
    return sk_sp<GrCoverageCountingPathRenderer>(ccpr);
}

GrCCPerOpListPaths* GrCoverageCountingPathRenderer::lookupPendingPaths(uint32_t opListID) {
    auto it = fPendingPaths.find(opListID);
    if (fPendingPaths.end() == it) {
        auto paths = skstd::make_unique<GrCCPerOpListPaths>();
        it = fPendingPaths.insert(std::make_pair(opListID, std::move(paths))).first;
    }
    return it->second.get();
}

void GrCoverageCountingPathRenderer::adoptAndRecordOp(GrCCDrawPathsOp* op,
                                                      const DrawPathArgs& args) {
    GrRenderTargetContext* rtc = args.fRenderTargetContext;
    if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::unique_ptr<GrDrawOp>(op))) {
        // If the Op wasn't dropped or combined, give it a pointer to its owning GrCCPerOpListPaths.
        op->wasRecorded(this->lookupPendingPaths(opListID));
    }
}

GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
        const CanDrawPathArgs& args) const {
    if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) {
        return CanDrawPath::kNo;
    }

    if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() ||
        args.fViewMatrix->hasPerspective() || GrAAType::kCoverage != args.fAAType) {
        return CanDrawPath::kNo;
    }

    SkPath path;
    args.fShape->asPath(&path);
    SkRect devBounds;
    SkIRect devIBounds;
    args.fViewMatrix->mapRect(&devBounds, path.getBounds());
    devBounds.roundOut(&devIBounds);
    if (!devIBounds.intersect(*args.fClipConservativeBounds)) {
        // Path is completely clipped away. Our code will eventually notice this before doing any
        // real work.
        return CanDrawPath::kYes;
    }

    if (devIBounds.height() * devIBounds.width() > 256 * 256) {
        // Large paths can blow up the atlas fast. And they are not ideal for a two-pass rendering
        // algorithm. Give the simpler direct renderers a chance before we commit to drawing it.
        return CanDrawPath::kAsBackup;
    }

    if (args.fShape->hasUnstyledKey() && path.countVerbs() > 50) {
        // Complex paths do better cached in an SDF, if the renderer will accept them.
        return CanDrawPath::kAsBackup;
    }

    return CanDrawPath::kYes;
}

bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) {
    SkASSERT(!fFlushing);

    SkIRect clipIBounds;
    GrRenderTargetContext* rtc = args.fRenderTargetContext;
    args.fClip->getConservativeBounds(rtc->width(), rtc->height(), &clipIBounds, nullptr);

    SkPath path;
    args.fShape->asPath(&path);

    SkRect devBounds;
    args.fViewMatrix->mapRect(&devBounds, path.getBounds());

    if (SkTMax(devBounds.height(), devBounds.width()) > kPathCropThreshold) {
        // The path is too large. Crop it or analytic AA can run out of fp32 precision.
        SkPath croppedPath;
        path.transform(*args.fViewMatrix, &croppedPath);
        crop_path(croppedPath, clipIBounds, &croppedPath);
        this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                                   SkMatrix::I(), croppedPath,
                                                   croppedPath.getBounds()), args);
        return true;
    }

    this->adoptAndRecordOp(new GrCCDrawPathsOp(std::move(args.fPaint), clipIBounds,
                                               *args.fViewMatrix, path, devBounds), args);
    return true;
}

std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
        GrProxyProvider* proxyProvider,
        uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
        int rtWidth, int rtHeight) {
    using MustCheckBounds = GrCCClipProcessor::MustCheckBounds;

    SkASSERT(!fFlushing);

    GrCCClipPath& clipPath =
            this->lookupPendingPaths(opListID)->fClipPaths[deviceSpacePath.getGenerationID()];
    if (!clipPath.isInitialized()) {
        // This ClipPath was just created during lookup. Initialize it.
        const SkRect& pathDevBounds = deviceSpacePath.getBounds();
        if (SkTMax(pathDevBounds.height(), pathDevBounds.width()) > kPathCropThreshold) {
            // The path is too large. Crop it or analytic AA can run out of fp32 precision.
            SkPath croppedPath;
            int maxRTSize = proxyProvider->caps()->maxRenderTargetSize();
            crop_path(deviceSpacePath, SkIRect::MakeWH(maxRTSize, maxRTSize), &croppedPath);
            clipPath.init(proxyProvider, croppedPath, accessRect, rtWidth, rtHeight);
        } else {
            clipPath.init(proxyProvider, deviceSpacePath, accessRect, rtWidth, rtHeight);
        }
    } else {
        clipPath.addAccess(accessRect);
    }

    bool mustCheckBounds = !clipPath.pathDevIBounds().contains(accessRect);
    return skstd::make_unique<GrCCClipProcessor>(&clipPath, MustCheckBounds(mustCheckBounds),
                                                 deviceSpacePath.getFillType());
}

void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP,
                                              const uint32_t* opListIDs, int numOpListIDs,
                                              SkTArray<sk_sp<GrRenderTargetContext>>* atlasDraws) {
    SkASSERT(!fFlushing);
    SkASSERT(fFlushingPaths.empty());
    SkDEBUGCODE(fFlushing = true);

    if (fPendingPaths.empty()) {
        return;  // Nothing to draw.
    }

    // Move the per-opList paths that are about to be flushed from fPendingPaths to fFlushingPaths,
    // and count up the paths about to be flushed so we can preallocate buffers.
    int numPathDraws = 0;
    int numClipPaths = 0;
    GrCCPathParser::PathStats flushingPathStats;
    fFlushingPaths.reserve(numOpListIDs);
    for (int i = 0; i < numOpListIDs; ++i) {
        auto iter = fPendingPaths.find(opListIDs[i]);
        if (fPendingPaths.end() == iter) {
            continue;  // No paths on this opList.
        }

        fFlushingPaths.push_back(std::move(iter->second));
        fPendingPaths.erase(iter);

        for (const GrCCDrawPathsOp* op : fFlushingPaths.back()->fDrawOps) {
            numPathDraws += op->countPaths(&flushingPathStats);
        }
        for (const auto& clipsIter : fFlushingPaths.back()->fClipPaths) {
            flushingPathStats.statPath(clipsIter.second.deviceSpacePath());
        }
        numClipPaths += fFlushingPaths.back()->fClipPaths.size();
    }

    if (0 == numPathDraws + numClipPaths) {
        return;  // Nothing to draw.
    }

    auto resources = sk_make_sp<GrCCPerFlushResources>(onFlushRP, numPathDraws, numClipPaths,
                                                       flushingPathStats);
    if (!resources->isMapped()) {
        return;  // Some allocation failed.
    }

    // Layout atlas(es) and parse paths.
    SkDEBUGCODE(int numSkippedPaths = 0);
    for (const auto& flushingPaths : fFlushingPaths) {
        for (GrCCDrawPathsOp* op : flushingPaths->fDrawOps) {
            op->setupResources(resources.get(), onFlushRP);
            SkDEBUGCODE(numSkippedPaths += op->numSkippedInstances_debugOnly());
        }
        for (auto& clipsIter : flushingPaths->fClipPaths) {
            clipsIter.second.renderPathInAtlas(resources.get(), onFlushRP);
        }
    }
    SkASSERT(resources->nextPathInstanceIdx() == numPathDraws - numSkippedPaths);

    // Allocate the atlases and create instance buffers to draw them.
    if (!resources->finalize(onFlushRP, atlasDraws)) {
        return;
    }

    // Commit flushing paths to the resources once they are successfully completed.
    for (auto& flushingPaths : fFlushingPaths) {
        flushingPaths->fFlushResources = resources;
    }
}

void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint32_t* opListIDs,
                                               int numOpListIDs) {
    SkASSERT(fFlushing);
    // We wait to erase these until after flush, once Ops and FPs are done accessing their data.
    fFlushingPaths.reset();
    SkDEBUGCODE(fFlushing = false);
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is 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.
// __END_LICENSE__

#include <vw/Camera/CameraSolve.h>
#include <asp/Core/StereoSettings.h>
#include <asp/Camera/PeruSatXML.h>
#include <asp/Camera/LinescanPeruSatModel.h>

namespace asp {

using vw::Vector3;
using vw::Matrix3x3;

// TODO: Port these changes to the base class

vw::Vector2 PeruSatCameraModel::point_to_pixel(Vector3 const& point, double starty) const {

  // Use the generic solver to find the pixel
  // - This method will be slower but works for more complicated geometries
  vw::camera::CameraGenericLMA model(this, point);
  int status;
  vw::Vector2 start = m_image_size / 2.0; // Use the center as the initial guess
  if (starty >= 0) // If the user provided a line number guess, use it.
    start[1] = starty;

  // Solver constants
  const double ABS_TOL = 1e-16;
  const double REL_TOL = 1e-16;
  const int    MAX_ITERATIONS = 1e+5;
  const double MAX_ERROR = 0.01;

  Vector3 objective(0, 0, 0);
  vw::Vector2 solution = vw::math::levenberg_marquardtFixed<vw::camera::CameraGenericLMA, 2,3>
    (model, start, objective, status, ABS_TOL, REL_TOL, MAX_ITERATIONS);

  double  error = norm_2(model(solution));

  VW_ASSERT( (status > 0) && (error < MAX_ERROR),
             vw::camera::PointToPixelErr()
             << "Unable to project point into LinescanPeruSat model" );

  return solution;
}

void PeruSatCameraModel::check_time(double time, std::string const& location) const {
  if ((time < m_min_time) || (time > m_max_time))
    vw::vw_throw(vw::ArgumentErr() << "PeruSatCameraModel::"<<location
                 << ": Requested time "<<time<<" is out of bounds ("
                 << m_min_time << " <-> "<<m_max_time<<")\n");
}

vw::Vector3 PeruSatCameraModel::get_camera_center_at_time(double time) const {
  check_time(time, "get_camera_center_at_time");
  return m_position_func(time);
}
vw::Vector3 PeruSatCameraModel::get_camera_velocity_at_time(double time) const {
  check_time(time, "get_camera_velocity_at_time");
  return m_velocity_func(time);
}
vw::Quat PeruSatCameraModel::get_camera_pose_at_time(double time) const {
  check_time(time, "get_camera_pose_at_time");
 return m_pose_func(time);
}

double PeruSatCameraModel::get_time_at_line(double line) const {
  // Allow finding the time at any line, even negative ones.  Here a
  // simple slope-intercept formula is used rather than a table so one
  // cannot run out of bounds.
  return m_time_func(line);
}

Vector3 PeruSatCameraModel::get_local_pixel_vector(vw::Vector2 const& pix) const {

  // According to Modelo%20Orbital%20PeruSAT-1.pdf:

  // psi_x = tan_psi_x[0] * (col - col_ref) + tan_psi_x[1]
  // psi_y = tan_psi_y[0] * (col - col_ref) + tan_psi_y[1]

  // where those coefficients are given in LINE_OF_SIGHT_TANPSIX
  // and LINE_OF_SIGHT_TANPSIY.

  // The doc says col_ref is 1, so for us it will be 0 since our
  // columns start form 0.

  double col     = pix[0];
  double psi_x   = m_tan_psi_x[0] * col + m_tan_psi_x[1];
  double psi_y   = m_tan_psi_y[0] * col + m_tan_psi_y[1];
  Vector3 result = Vector3(tan(psi_y), -tan(psi_x), 1.0);

  // Make the direction have unit length
  result = normalize(result);

  // Go from sensor coordinates to satellite body coordinates.
  // The instrument biases were not documented at all and took a while
  // to figure out.
  result = m_inverse_instrument_biases.rotate(result);

  return result;
}

boost::shared_ptr<PeruSatCameraModel> load_perusat_camera_model_from_xml(std::string const& path){

  vw_out(vw::DebugMessage,"asp") << "Loading PeruSat camera file: " << path << std::endl;
  // Parse the PeruSat XML file
  PeruSatXML xml_reader;
  xml_reader.read_xml(path);

  // Get all the initial functors
  vw::camera::LinearTimeInterpolation
    time_func      = xml_reader.setup_time_func();
  vw::camera::LagrangianInterpolation
    position_func  = xml_reader.setup_position_func(time_func);
  vw::camera::LagrangianInterpolation
    velocity_func  = xml_reader.setup_velocity_func(time_func);
  vw::camera::SLERPPoseInterpolation
    pose_func      = xml_reader.setup_pose_func(time_func);

  // Find the range of times for which we can solve for position and pose

  double min_position_time = position_func.get_t0();
  double max_position_time = position_func.get_tend();

  double min_velocity_time = velocity_func.get_t0();
  double max_velocity_time = velocity_func.get_tend();

  double min_pose_time = pose_func.get_t0();
  double max_pose_time = pose_func.get_tend();

  double min_time = std::max(min_position_time, std::max(min_velocity_time, min_pose_time));
  double max_time = std::min(max_position_time, std::min(max_velocity_time, max_pose_time));

  std::cout << "--disable velocity aberration is "
            << stereo_settings().disable_correct_velocity_aberration << std::endl;

  std::cout << "--disable correct atmospheric refraction is "
            << stereo_settings().disable_correct_atmospheric_refraction << std::endl;

  // Feed everything into a new camera model.
  return boost::shared_ptr<PeruSatCameraModel>
    (new PeruSatCameraModel(position_func, velocity_func,
                            pose_func, time_func,
                            xml_reader.m_tan_psi_x,
                            xml_reader.m_tan_psi_y,
                            xml_reader.m_instrument_biases,
                            xml_reader.m_image_size,
                            min_time, max_time,
                            !stereo_settings().disable_correct_velocity_aberration,
                            !stereo_settings().disable_correct_atmospheric_refraction));

} // End function load_perusat_camera_model()

} // end namespace asp

<commit_msg>perusat: Turn off for now velocity aberation and atmospheric refraction and print a message about that<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is 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.
// __END_LICENSE__

#include <vw/Camera/CameraSolve.h>
#include <asp/Core/StereoSettings.h>
#include <asp/Camera/PeruSatXML.h>
#include <asp/Camera/LinescanPeruSatModel.h>

namespace asp {

// While static variables are not thread-safe, this will be changed only once,
// the first time a PeruSatCameraModel is loaded, and model loading is a serial
// process.
static bool perusat_correction_note_printed = false;

using vw::Vector3;
using vw::Matrix3x3;

// TODO: Port these changes to the base class

vw::Vector2 PeruSatCameraModel::point_to_pixel(Vector3 const& point, double starty) const {

  // Use the generic solver to find the pixel
  // - This method will be slower but works for more complicated geometries
  vw::camera::CameraGenericLMA model(this, point);
  int status;
  vw::Vector2 start = m_image_size / 2.0; // Use the center as the initial guess
  if (starty >= 0) // If the user provided a line number guess, use it.
    start[1] = starty;

  // Solver constants
  const double ABS_TOL = 1e-16;
  const double REL_TOL = 1e-16;
  const int    MAX_ITERATIONS = 1e+5;
  const double MAX_ERROR = 0.01;

  Vector3 objective(0, 0, 0);
  vw::Vector2 solution = vw::math::levenberg_marquardtFixed<vw::camera::CameraGenericLMA, 2,3>
    (model, start, objective, status, ABS_TOL, REL_TOL, MAX_ITERATIONS);

  double  error = norm_2(model(solution));

  VW_ASSERT( (status > 0) && (error < MAX_ERROR),
             vw::camera::PointToPixelErr()
             << "Unable to project point into LinescanPeruSat model" );

  return solution;
}

void PeruSatCameraModel::check_time(double time, std::string const& location) const {
  if ((time < m_min_time) || (time > m_max_time))
    vw::vw_throw(vw::ArgumentErr() << "PeruSatCameraModel::"<<location
                 << ": Requested time "<<time<<" is out of bounds ("
                 << m_min_time << " <-> "<<m_max_time<<")\n");
}

vw::Vector3 PeruSatCameraModel::get_camera_center_at_time(double time) const {
  check_time(time, "get_camera_center_at_time");
  return m_position_func(time);
}
vw::Vector3 PeruSatCameraModel::get_camera_velocity_at_time(double time) const {
  check_time(time, "get_camera_velocity_at_time");
  return m_velocity_func(time);
}
vw::Quat PeruSatCameraModel::get_camera_pose_at_time(double time) const {
  check_time(time, "get_camera_pose_at_time");
 return m_pose_func(time);
}

double PeruSatCameraModel::get_time_at_line(double line) const {
  // Allow finding the time at any line, even negative ones.  Here a
  // simple slope-intercept formula is used rather than a table so one
  // cannot run out of bounds.
  return m_time_func(line);
}

Vector3 PeruSatCameraModel::get_local_pixel_vector(vw::Vector2 const& pix) const {

  // According to Modelo%20Orbital%20PeruSAT-1.pdf:

  // psi_x = tan_psi_x[0] * (col - col_ref) + tan_psi_x[1]
  // psi_y = tan_psi_y[0] * (col - col_ref) + tan_psi_y[1]

  // where those coefficients are given in LINE_OF_SIGHT_TANPSIX
  // and LINE_OF_SIGHT_TANPSIY.

  // The doc says col_ref is 1, so for us it will be 0 since our
  // columns start form 0.

  double col     = pix[0];
  double psi_x   = m_tan_psi_x[0] * col + m_tan_psi_x[1];
  double psi_y   = m_tan_psi_y[0] * col + m_tan_psi_y[1];
  Vector3 result = Vector3(tan(psi_y), -tan(psi_x), 1.0);

  // Make the direction have unit length
  result = normalize(result);

  // Go from sensor coordinates to satellite body coordinates.
  // The instrument biases were not documented at all and took a while
  // to figure out.
  result = m_inverse_instrument_biases.rotate(result);

  return result;
}

boost::shared_ptr<PeruSatCameraModel> load_perusat_camera_model_from_xml(std::string const& path){

  vw_out(vw::DebugMessage,"asp") << "Loading PeruSat camera file: " << path << std::endl;
  // Parse the PeruSat XML file
  PeruSatXML xml_reader;
  xml_reader.read_xml(path);

  // Get all the initial functors
  vw::camera::LinearTimeInterpolation
    time_func      = xml_reader.setup_time_func();
  vw::camera::LagrangianInterpolation
    position_func  = xml_reader.setup_position_func(time_func);
  vw::camera::LagrangianInterpolation
    velocity_func  = xml_reader.setup_velocity_func(time_func);
  vw::camera::SLERPPoseInterpolation
    pose_func      = xml_reader.setup_pose_func(time_func);

  // Find the range of times for which we can solve for position and pose
  double min_position_time = position_func.get_t0();
  double max_position_time = position_func.get_tend();
  double min_velocity_time = velocity_func.get_t0();
  double max_velocity_time = velocity_func.get_tend();
  double min_pose_time = pose_func.get_t0();
  double max_pose_time = pose_func.get_tend();
  double min_time = std::max(min_position_time, std::max(min_velocity_time, min_pose_time));
  double max_time = std::min(max_position_time, std::min(max_velocity_time, max_pose_time));

  // See note on this below
  bool correct_velocity_aberration = false;
  bool correct_atmospheric_refraction = false;

  // Create the model. This can throw an exception.
  boost::shared_ptr<PeruSatCameraModel> cam
    (new PeruSatCameraModel(position_func, velocity_func,
                            pose_func, time_func,
                            xml_reader.m_tan_psi_x,
                            xml_reader.m_tan_psi_y,
                            xml_reader.m_instrument_biases,
                            xml_reader.m_image_size,
                            min_time, max_time,
                            correct_velocity_aberration,
                            correct_atmospheric_refraction));

  // Print this note only if PeruSat model loading was successful, as
  // sometimes this camera loading function is invoked when querying
  // an unknown XML model and we may not end up using this session if
  // loading fails.
  if (!perusat_correction_note_printed) {
    vw::vw_out() << "Not using atmospheric and velocity aberration correction "
             << "with PeruSat cameras to maintain closer agreement with "
             << "the RPC approximation to this model.\n";
    perusat_correction_note_printed = true;
  }

  return cam;
} // End function load_perusat_camera_model()

} // end namespace asp

<|endoftext|>


<commit_before>
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif

#define ELM_INTERNAL_API_ARGESFSDFEFC
#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
#define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
#define ELM_INTERFACE_ATSPI_ACTION_PROTECTED
#define ELM_INTERFACE_ATSPI_VALUE_PROTECTED
#define ELM_INTERFACE_ATSPI_EDITABLE_TEXT_PROTECTED
#define ELM_INTERFACE_ATSPI_TEXT_PROTECTED
#define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED
#define ELM_INTERFACE_ATSPI_IMAGE_PROTECTED
#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED

#include <Eo.h>
#include <Evas.h>
#include <Elementary.h>
#include <elm_widget.h>
#include <elm_interface_atspi_accessible.h>

#include <elc_ctxpopup.eo.hh>
#include <elc_fileselector_button.eo.hh>
#include <elc_fileselector_entry.eo.hh>
#include <elc_fileselector.eo.hh>
#include <elc_hoversel.eo.hh>
#include <elc_multibuttonentry.eo.hh>
#include <elc_naviframe.eo.hh>
#include <elc_player.eo.hh>
#include <elc_popup.eo.hh>
#include <elm_access.eo.hh>
#include <elm_actionslider.eo.hh>
#include <elm_app_client.eo.hh>
#include <elm_app_client_view.eo.hh>
#include <elm_app_server.eo.hh>
#include <elm_app_server_view.eo.hh>
#include <elm_atspi_app_object.eo.hh>
#include <elm_bg.eo.hh>
#include <elm_box.eo.hh>
#include <elm_bubble.eo.hh>
#include <elm_button.eo.hh>
#include <elm_calendar.eo.hh>
#include <elm_check.eo.hh>
#include <elm_clock.eo.hh>
#include <elm_colorselector.eo.hh>
#include <elm_conformant.eo.hh>
#include <elm_container.eo.hh>
#include <elm_datetime.eo.hh>
#include <elm_dayselector.eo.hh>
#include <elm_diskselector.eo.hh>
#include <elm_entry.eo.hh>
#include <elm_flip.eo.hh>
#include <elm_flipselector.eo.hh>
#include <elm_frame.eo.hh>
#include <elm_gengrid.eo.hh>
#include <elm_gengrid_pan.eo.hh>
#include <elm_genlist.eo.hh>
#include <elm_genlist_pan.eo.hh>
#include <elm_gesture_layer.eo.hh>
#include <elm_glview.eo.hh>
#include <elm_grid.eo.hh>
#include <elm_hover.eo.hh>
#include <elm_icon.eo.hh>
#include <elm_image.eo.hh>
#include <elm_index.eo.hh>
#include <elm_interface_atspi_accessible.eo.hh>
#include <elm_interface_atspi_action.eo.hh>
#include <elm_interface_atspi_component.eo.hh>
#include <elm_interface_atspi_editable_text.eo.hh>
#include <elm_interface_atspi_image.eo.hh>
#include <elm_interface_atspi_selection.eo.hh>
#include <elm_interface_atspi_text.eo.hh>
#include <elm_interface_atspi_value.eo.hh>
#include <elm_interface_atspi_widget_action.eo.hh>
#include <elm_interface_atspi_widget.eo.hh>
#include <elm_interface_atspi_window.eo.hh>
#include <elm_interface_fileselector.eo.hh>
#include <elm_interface_scrollable.eo.hh>
#include <elm_inwin.eo.hh>
#include <elm_label.eo.hh>
#include <elm_layout.eo.hh>
#include <elm_list.eo.hh>
#include <elm_mapbuf.eo.hh>
#include <elm_map.eo.hh>
#include <elm_map_pan.eo.hh>
#include <elm_menu.eo.hh>
#include <elm_notify.eo.hh>
#include <elm_panel.eo.hh>
#include <elm_pan.eo.hh>
#include <elm_panes.eo.hh>
#include <elm_photocam.eo.hh>
#include <elm_photocam_pan.eo.hh>
#include <elm_photo.eo.hh>
#include <elm_plug.eo.hh>
#include <elm_prefs.eo.hh>
#include <elm_progressbar.eo.hh>
#include <elm_radio.eo.hh>
#include <elm_route.eo.hh>
#include <elm_scroller.eo.hh>
#include <elm_segment_control.eo.hh>
#include <elm_separator.eo.hh>
#include <elm_slider.eo.hh>
#include <elm_slideshow.eo.hh>
#include <elm_spinner.eo.hh>
#include <elm_systray.eo.hh>
#include <elm_table.eo.hh>
#include <elm_thumb.eo.hh>
#include <elm_toolbar.eo.hh>
#include <elm_video.eo.hh>
#include <elm_web.eo.hh>
#include <elm_widget.eo.hh>
#include <elm_win.eo.hh>

int main()
{
}
<commit_msg>elementary++: Added missing includes.<commit_after>
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif

#define ELM_INTERNAL_API_ARGESFSDFEFC
#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
#define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
#define ELM_INTERFACE_ATSPI_ACTION_PROTECTED
#define ELM_INTERFACE_ATSPI_VALUE_PROTECTED
#define ELM_INTERFACE_ATSPI_EDITABLE_TEXT_PROTECTED
#define ELM_INTERFACE_ATSPI_TEXT_PROTECTED
#define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED
#define ELM_INTERFACE_ATSPI_IMAGE_PROTECTED
#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED

#include <Eo.h>
#include <Evas.h>
#include <Elementary.h>

#include <elm_widget.h>
#include <elm_interface_scrollable.h>
#include <elm_interface_atspi_text.h>
#include <elm_interface_atspi_accessible.h>

#include <elc_ctxpopup.eo.hh>
#include <elc_fileselector_button.eo.hh>
#include <elc_fileselector_entry.eo.hh>
#include <elc_fileselector.eo.hh>
#include <elc_hoversel.eo.hh>
#include <elc_multibuttonentry.eo.hh>
#include <elc_naviframe.eo.hh>
#include <elc_player.eo.hh>
#include <elc_popup.eo.hh>
#include <elm_access.eo.hh>
#include <elm_actionslider.eo.hh>
#include <elm_app_client.eo.hh>
#include <elm_app_client_view.eo.hh>
#include <elm_app_server.eo.hh>
#include <elm_app_server_view.eo.hh>
#include <elm_atspi_app_object.eo.hh>
#include <elm_bg.eo.hh>
#include <elm_box.eo.hh>
#include <elm_bubble.eo.hh>
#include <elm_button.eo.hh>
#include <elm_calendar.eo.hh>
#include <elm_check.eo.hh>
#include <elm_clock.eo.hh>
#include <elm_colorselector.eo.hh>
#include <elm_conformant.eo.hh>
#include <elm_container.eo.hh>
#include <elm_datetime.eo.hh>
#include <elm_dayselector.eo.hh>
#include <elm_diskselector.eo.hh>
#include <elm_entry.eo.hh>
#include <elm_flip.eo.hh>
#include <elm_flipselector.eo.hh>
#include <elm_frame.eo.hh>
#include <elm_gengrid.eo.hh>
#include <elm_gengrid_pan.eo.hh>
#include <elm_genlist.eo.hh>
#include <elm_genlist_pan.eo.hh>
#include <elm_gesture_layer.eo.hh>
#include <elm_glview.eo.hh>
#include <elm_grid.eo.hh>
#include <elm_hover.eo.hh>
#include <elm_icon.eo.hh>
#include <elm_image.eo.hh>
#include <elm_index.eo.hh>
#include <elm_interface_atspi_accessible.eo.hh>
#include <elm_interface_atspi_action.eo.hh>
#include <elm_interface_atspi_component.eo.hh>
#include <elm_interface_atspi_editable_text.eo.hh>
#include <elm_interface_atspi_image.eo.hh>
#include <elm_interface_atspi_selection.eo.hh>
#include <elm_interface_atspi_text.eo.hh>
#include <elm_interface_atspi_value.eo.hh>
#include <elm_interface_atspi_widget_action.eo.hh>
#include <elm_interface_atspi_widget.eo.hh>
#include <elm_interface_atspi_window.eo.hh>
#include <elm_interface_fileselector.eo.hh>
#include <elm_interface_scrollable.eo.hh>
#include <elm_inwin.eo.hh>
#include <elm_label.eo.hh>
#include <elm_layout.eo.hh>
#include <elm_list.eo.hh>
#include <elm_mapbuf.eo.hh>
#include <elm_map.eo.hh>
#include <elm_map_pan.eo.hh>
#include <elm_menu.eo.hh>
#include <elm_notify.eo.hh>
#include <elm_panel.eo.hh>
#include <elm_pan.eo.hh>
#include <elm_panes.eo.hh>
#include <elm_photocam.eo.hh>
#include <elm_photocam_pan.eo.hh>
#include <elm_photo.eo.hh>
#include <elm_plug.eo.hh>
#include <elm_prefs.eo.hh>
#include <elm_progressbar.eo.hh>
#include <elm_radio.eo.hh>
#include <elm_route.eo.hh>
#include <elm_scroller.eo.hh>
#include <elm_segment_control.eo.hh>
#include <elm_separator.eo.hh>
#include <elm_slider.eo.hh>
#include <elm_slideshow.eo.hh>
#include <elm_spinner.eo.hh>
#include <elm_systray.eo.hh>
#include <elm_table.eo.hh>
#include <elm_thumb.eo.hh>
#include <elm_toolbar.eo.hh>
#include <elm_video.eo.hh>
#include <elm_web.eo.hh>
#include <elm_widget.eo.hh>
#include <elm_win.eo.hh>

int main()
{
}
<|endoftext|>