<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dvp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			case 'v':
				Log::info("version 0.0.3");
				exit(0);
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
			delete dent;
			delete dir;
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<commit_msg>[fix] Segv.<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino {

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<"[debug] "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<"[info] "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dvp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			case 'v':
				Log::info("version 0.0.3");
				exit(0);
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + move(filename);
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
			if(dir!=NULL){
		    	closedir(dir);
				//delete dent;
				//delete dir;
			}
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef SUPPORT_NASTY_MACROS_HPP
#define SUPPORT_NASTY_MACROS_HPP

#define NASTY_MACRO This should not be expanded!!!
#define _A NASTY_MACRO
#define _B NASTY_MACRO
#define _C NASTY_MACRO
#define _D NASTY_MACRO
#define _E NASTY_MACRO
#define _F NASTY_MACRO
#define _G NASTY_MACRO
#define _H NASTY_MACRO
#define _I NASTY_MACRO
#define _J NASTY_MACRO
#define _K NASTY_MACRO
#define _L NASTY_MACRO
#define _M NASTY_MACRO
#define _N NASTY_MACRO
#define _O NASTY_MACRO
#define _P NASTY_MACRO
#define _Q NASTY_MACRO
#define _R NASTY_MACRO
#define _S NASTY_MACRO
#define _T NASTY_MACRO
#define _U NASTY_MACRO
#define _V NASTY_MACRO
#define _W NASTY_MACRO
#define _X NASTY_MACRO
#define _Y NASTY_MACRO
#define _Z NASTY_MACRO

// tchar.h defines these macros on Windows.
#define _UI   NASTY_MACRO
#define _PUC  NASTY_MACRO
#define _CPUC NASTY_MACRO
#define _PC   NASTY_MACRO
#define _CRPC NASTY_MACRO
#define _CPC  NASTY_MACRO

// Test that libc++ doesn't use names reserved by WIN32 API Macros.
// NOTE: Obviously we can only define these on non-windows platforms.
#ifndef _WIN32
#define __deallocate NASTY_MACRO
#define __out NASTY_MACRO
#endif

#define __output NASTY_MACRO
#define __input NASTY_MACRO

#endif // SUPPORT_NASTY_MACROS_HPP
<commit_msg>For FreeBSD, don't define _M in nasty_macros.hpp<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef SUPPORT_NASTY_MACROS_HPP
#define SUPPORT_NASTY_MACROS_HPP

#define NASTY_MACRO This should not be expanded!!!
#define _A NASTY_MACRO
#define _B NASTY_MACRO
#define _C NASTY_MACRO
#define _D NASTY_MACRO
#define _E NASTY_MACRO
#define _F NASTY_MACRO
#define _G NASTY_MACRO
#define _H NASTY_MACRO
#define _I NASTY_MACRO
#define _J NASTY_MACRO
#define _K NASTY_MACRO
#define _L NASTY_MACRO
// Because FreeBSD uses _M in its <sys/types.h>, and it is hard to avoid
// including that header, only define _M for other operating systems.
#ifndef __FreeBSD__
#define _M NASTY_MACRO
#endif
#define _N NASTY_MACRO
#define _O NASTY_MACRO
#define _P NASTY_MACRO
#define _Q NASTY_MACRO
#define _R NASTY_MACRO
#define _S NASTY_MACRO
#define _T NASTY_MACRO
#define _U NASTY_MACRO
#define _V NASTY_MACRO
#define _W NASTY_MACRO
#define _X NASTY_MACRO
#define _Y NASTY_MACRO
#define _Z NASTY_MACRO

// tchar.h defines these macros on Windows.
#define _UI   NASTY_MACRO
#define _PUC  NASTY_MACRO
#define _CPUC NASTY_MACRO
#define _PC   NASTY_MACRO
#define _CRPC NASTY_MACRO
#define _CPC  NASTY_MACRO

// Test that libc++ doesn't use names reserved by WIN32 API Macros.
// NOTE: Obviously we can only define these on non-windows platforms.
#ifndef _WIN32
#define __deallocate NASTY_MACRO
#define __out NASTY_MACRO
#endif

#define __output NASTY_MACRO
#define __input NASTY_MACRO

#endif // SUPPORT_NASTY_MACROS_HPP
<|endoftext|>


<commit_before>#pragma once

#include "acmacs-base/fmt.hh"
#include "acmacs-base/rjson.hh"
#include "acmacs-base/flat-map.hh"

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

namespace acmacs::settings::inline v2
{
    class error : public std::runtime_error
    {
        using std::runtime_error::runtime_error;
    };

    class Settings
    {
      public:
        Settings() = default;
        Settings(const std::vector<std::string_view>& filenames) { load(filenames); }
        virtual ~Settings() = default;

        // read settings from files, upon reading each file apply "init" in it (if found)
        void load(const std::vector<std::string_view>& filenames)
        {
            for (const auto& filename : filenames)
                load(filename);
        }
        void load(std::string_view filename);

        // substitute vars in name, find name in environment or in data_ or in built-in and apply it
        // if name starts with ? do nothing
        // if name not found, throw
        virtual void apply(std::string_view name = "main") const;
        void apply(const char* name) const { apply(std::string_view{name}); }

        // substitute vars in name, find name in the top of data_ and apply it
        // do nothing if name starts with ? or if it is not found in top of data_
        virtual void apply_top(std::string_view name) const;

        virtual bool apply_built_in(std::string_view name) const; // returns true if built-in command with that name found and applied

        void setenv_from_string(std::string_view key, std::string_view value);
        template <typename T> void setenv(std::string_view key, T&& value) { setenv(key, rjson::value{std::forward<T>(value)}); }

        template <typename T> T getenv(std::string_view key, T&& a_default) const
        {
            if (const auto& val = environment_.get(static_cast<std::string>(environment_.substitute(key))); !val.is_const_null())
                return static_cast<T>(val);
            else
                return std::move(a_default);
        }

        std::string getenv(std::string_view key, const char* a_default) const { return getenv(key, std::string{a_default}); }

      protected:
        template <typename... Key> const rjson::value& get(Key&&... keys) const;
        void apply(const rjson::value& entry) const;

      private:
        class Environment
        {
          public:
            Environment() { push(); }

            const rjson::value& get(std::string_view key) const;
            void push() { data_.emplace_back(); }
            void pop() { data_.erase(std::prev(std::end(data_))); }
            size_t size() const { return data_.size(); }
            void add(std::string_view key, const rjson::value& val) { data_.rbegin()->emplace_or_replace(std::string{key}, val); }
            void add(std::string_view key, rjson::value&& val) { data_.rbegin()->emplace_or_replace(std::string{key}, std::move(val)); }
            void print() const;
            void print_key_value() const;

            rjson::value substitute(std::string_view source) const;

          private:
            std::vector<acmacs::flat_map_t<std::string, rjson::value>> data_;

            rjson::value substitute(const rjson::value& source) const;
        };

        std::vector<rjson::value> data_;
        mutable Environment environment_;

        void push_and_apply(const rjson::object& entry) const;

        friend class Subenvironment;
    };
} // namespace acmacs::settings::inline v2

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

namespace acmacs::settings::inline v2
{
    template <typename... Key> const rjson::value& Settings::get(Key && ... keys) const
    {
        for (auto it = data_.rbegin(); it != data_.rend(); ++it) {
            if (const auto& val = it->get(std::forward<Key>(keys)...); !val.is_const_null())
                return val;
        }
        return rjson::ConstNull;

    } // acmacs::settings::v2::Settings::get

    template <> inline void Settings::setenv(std::string_view key, const rjson::value& value) { environment_.add(key, value); }
    template <> inline void Settings::setenv(std::string_view key, rjson::value && value) { environment_.add(key, std::move(value)); }

} // namespace acmacs::settings::inline v2

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>settings-v2<commit_after>#pragma once

#include "acmacs-base/fmt.hh"
#include "acmacs-base/rjson.hh"
#include "acmacs-base/flat-map.hh"

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

namespace acmacs::settings::inline v2
{
    class error : public std::runtime_error
    {
        using std::runtime_error::runtime_error;
    };

    class Settings
    {
      public:
        Settings() = default;
        Settings(const std::vector<std::string_view>& filenames) { load(filenames); }
        virtual ~Settings() = default;

        // read settings from files, upon reading each file apply "init" in it (if found)
        void load(const std::vector<std::string_view>& filenames)
        {
            for (const auto& filename : filenames)
                load(filename);
        }
        void load(std::string_view filename);

        // substitute vars in name, find name in environment or in data_ or in built-in and apply it
        // if name starts with ? do nothing
        // if name not found, throw
        virtual void apply(std::string_view name = "main") const;
        void apply(const char* name) const { apply(std::string_view{name}); }

        // substitute vars in name, find name in the top of data_ and apply it
        // do nothing if name starts with ? or if it is not found in top of data_
        virtual void apply_top(std::string_view name) const;

        virtual bool apply_built_in(std::string_view name) const; // returns true if built-in command with that name found and applied

        void setenv_from_string(std::string_view key, std::string_view value);
        template <typename T> void setenv(std::string_view key, T&& value) { setenv(key, rjson::value{std::forward<T>(value)}); }

        template <typename T> T getenv(std::string_view key, T&& a_default) const
        {
            if (const auto& val = environment_.get(static_cast<std::string>(environment_.substitute(key))); !val.is_const_null())
                return static_cast<T>(val);
            else
                return std::move(a_default);
        }

        std::string getenv(std::string_view key, const char* a_default) const { return getenv(key, std::string{a_default}); }
        void printenv() const { environment_.print(); }

      protected:
        template <typename... Key> const rjson::value& get(Key&&... keys) const;
        void apply(const rjson::value& entry) const;

      private:
        class Environment
        {
          public:
            Environment() { push(); }

            const rjson::value& get(std::string_view key) const;
            void push() { data_.emplace_back(); }
            void pop() { data_.erase(std::prev(std::end(data_))); }
            size_t size() const { return data_.size(); }
            void add(std::string_view key, const rjson::value& val) { data_.rbegin()->emplace_or_replace(std::string{key}, val); }
            void add(std::string_view key, rjson::value&& val) { data_.rbegin()->emplace_or_replace(std::string{key}, std::move(val)); }
            void print() const;
            void print_key_value() const;

            rjson::value substitute(std::string_view source) const;

          private:
            std::vector<acmacs::flat_map_t<std::string, rjson::value>> data_;

            rjson::value substitute(const rjson::value& source) const;
        };

        std::vector<rjson::value> data_;
        mutable Environment environment_;

        void push_and_apply(const rjson::object& entry) const;

        friend class Subenvironment;
    };
} // namespace acmacs::settings::inline v2

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

namespace acmacs::settings::inline v2
{
    template <typename... Key> const rjson::value& Settings::get(Key && ... keys) const
    {
        for (auto it = data_.rbegin(); it != data_.rend(); ++it) {
            if (const auto& val = it->get(std::forward<Key>(keys)...); !val.is_const_null())
                return val;
        }
        return rjson::ConstNull;

    } // acmacs::settings::v2::Settings::get

    template <> inline void Settings::setenv(std::string_view key, const rjson::value& value) { environment_.add(key, value); }
    template <> inline void Settings::setenv(std::string_view key, rjson::value && value) { environment_.add(key, std::move(value)); }

} // namespace acmacs::settings::inline v2

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <algorithm>
#include <functional>
#include <iomanip>

#include "hidb.hh"
#include "variant-id.hh"
#include "vaccines.hh"

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

#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#endif

static std::map<std::string, std::vector<hidb::Vaccine>> sVaccines = {
    {"A(H1N1)", {
            {"CALIFORNIA/7/2009",        hidb::Vaccine::Previous},
            {"MICHIGAN/45/2015",         hidb::Vaccine::Current},
        }},
    {"A(H3N2)", {
            {"BRISBANE/10/2007",         hidb::Vaccine::Previous},
            {"PERTH/16/2009",            hidb::Vaccine::Previous},
            {"VICTORIA/361/2011",        hidb::Vaccine::Previous},
            {"TEXAS/50/2012",            hidb::Vaccine::Previous},
            {"SWITZERLAND/9715293/2013", hidb::Vaccine::Previous},
            {"HONG KONG/4801/2014",      hidb::Vaccine::Current},
            {"SAITAMA/103/2014",         hidb::Vaccine::Surrogate},
            {"HONG KONG/7295/2014",      hidb::Vaccine::Surrogate},
        }},
    {"BVICTORIA", {
            {"MALAYSIA/2506/2004",       hidb::Vaccine::Previous},
            {"BRISBANE/60/2008",         hidb::Vaccine::Current},
              // {"PARIS/1762/2009",          hidb::Vaccine::Current}, // not used by Crick anymore, B/Ireland/3154/2016 is used instead (2017-08-21)
            {"SOUTH AUSTRALIA/81/2012",  hidb::Vaccine::Surrogate},
            {"IRELAND/3154/2016",  hidb::Vaccine::Surrogate},
        }},
    {"BYAMAGATA", {
            {"FLORIDA/4/2006",           hidb::Vaccine::Previous},
            {"WISCONSIN/1/2010",         hidb::Vaccine::Previous},
            {"MASSACHUSETTS/2/2012",     hidb::Vaccine::Previous},
            {"PHUKET/3073/2013",         hidb::Vaccine::Current},
        }},
};

#pragma GCC diagnostic pop

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

std::string hidb::Vaccine::type_as_string(hidb::Vaccine::Type aType)
{
    switch (aType) {
      case Previous:
          return "previous";
      case Current:
          return "current";
      case Surrogate:
          return "surrogate";
    }
    return {};

} // hidb::Vaccine::type_as_string

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

hidb::Vaccine::Type hidb::Vaccine::type_from_string(std::string aType)
{
    if (aType == "previous")
        return Previous;
    else if (aType == "current")
        return Current;
    else if (aType == "surrogate")
        return Surrogate;
    return Previous;

} // hidb::Vaccine::type_from_string

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

const std::vector<hidb::Vaccine>& hidb::vaccines(std::string aSubtype, std::string aLineage)
{
    return sVaccines.at(aSubtype + aLineage);

} // hidb::vaccines

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

const std::vector<hidb::Vaccine>& hidb::vaccines(const Chart& aChart)
{
    return vaccines(aChart.chart_info().virus_type(), aChart.lineage());

} // hidb::vaccines

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

std::string hidb::Vaccine::type_as_string() const
{
    return type_as_string(type);

} // hidb::Vaccine::type_as_string

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

inline bool hidb::Vaccines::Entry::operator < (const hidb::Vaccines::Entry& a) const
{
    const auto a_nt = a.antigen_data->number_of_tables(), t_nt = antigen_data->number_of_tables();
    return t_nt == a_nt ? most_recent_table_date > a.most_recent_table_date : t_nt > a_nt;
}

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

bool hidb::Vaccines::HomologousSerum::operator < (const hidb::Vaccines::HomologousSerum& a) const
{
    bool result = true;
    if (serum->serum_species() == "SHEEP") { // avoid using sheep serum as homologous (NIMR)
        result = false;
    }
    else {
        const auto s_nt = a.serum_data->number_of_tables(), t_nt = serum_data->number_of_tables();
        result = t_nt == s_nt ? most_recent_table_date > a.most_recent_table_date : t_nt > s_nt;
    }
    return result;

} // hidb::Vaccines::HomologousSerum::operator <

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

size_t hidb::Vaccines::HomologousSerum::number_of_tables() const
{
    return serum_data->number_of_tables();

} // hidb::Vaccines::HomologousSerum::number_of_tables

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

std::string hidb::Vaccines::report(size_t aIndent) const
{
    std::ostringstream out;
    if (!empty()) {
        out << std::string(aIndent, ' ') << "Vaccine " << type_as_string() << ' ' << mNameType.name << std::endl;
        for_each_passage_type([&](PassageType pt) { out << this->report(pt, aIndent + 2); });
    }
    return out.str();

} // hidb::Vaccines::report

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

std::string hidb::Vaccines::report(PassageType aPassageType, size_t aIndent, size_t aMark) const
{
    std::ostringstream out;
    const std::string indent(aIndent, ' ');
    auto entry_report = [&](size_t aNo, const auto& entry, bool aMarkIt) {
        out << indent << (aMarkIt ? ">>" : "  ") << std::setw(2) << aNo << ' ' << entry.antigen_index << ' ' << entry.antigen->full_name() << " tables:" << entry.antigen_data->number_of_tables() << " recent:" << entry.antigen_data->most_recent_table().table_id() << std::endl;
        for (const auto& hs: entry.homologous_sera)
            out << indent << "      " << hs.serum->serum_id() << ' ' << hs.serum->annotations().join() << " tables:" << hs.serum_data->number_of_tables() << " recent:" << hs.serum_data->most_recent_table().table_id() << std::endl;
    };

    const auto& entry = mEntries[aPassageType];
    if (!entry.empty()) {
        out << indent << passage_type_name(aPassageType) << " (" << entry.size() << ')' << std::endl;
        for (size_t no = 0; no < entry.size(); ++no)
            entry_report(no, entry[no], aMark == no);
    }
    return out.str();

} // hidb::Vaccines::report

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

void hidb::vaccines_for_name(Vaccines& aVaccines, std::string aName, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    std::vector<size_t> by_name;
    aChart.antigens().find_by_name(aName, by_name);
    for (size_t ag_no: by_name) {
        try {
            const auto& ag = static_cast<const Antigen&>(aChart.antigen(ag_no));
              // std::cerr << ag.full_name() << std::endl;
            const auto& data = aHiDb.find_antigen_of_chart(ag);
            std::vector<hidb::Vaccines::HomologousSerum> homologous_sera;
            for (const auto* sd: aHiDb.find_homologous_sera(data)) {
                const size_t sr_no = aChart.sera().find_by_full_name(hidb::name_for_exact_matching(sd->data()));
                  // std::cerr << "   " << sd->data().name_for_exact_matching() << " " << (serum ? "Y" : "N") << std::endl;
                if (sr_no != static_cast<size_t>(-1))
                    homologous_sera.emplace_back(sr_no, static_cast<const Serum*>(&aChart.serum(sr_no)), sd, aHiDb.charts()[sd->most_recent_table().table_id()].chart_info().date());
            }
            aVaccines.add(ag_no, ag, &data, std::move(homologous_sera), aHiDb.charts()[data.most_recent_table().table_id()].chart_info().date());
        }
        catch (hidb::HiDb::NotFound&) {
        }
    }
    aVaccines.sort();

} // hidb::vaccines_for_name

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

hidb::Vaccines* hidb::find_vaccines_in_chart(std::string aName, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    Vaccines* result = new Vaccines(Vaccine(aName, hidb::Vaccine::Previous));
    vaccines_for_name(*result, aName, aChart, aHiDb);
    return result;

} // find_vaccines_in_chart

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

void hidb::vaccines(VaccinesOfChart& aVaccinesOfChart, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    for (const auto& name_type: vaccines(aChart)) {
        aVaccinesOfChart.emplace_back(name_type);
        vaccines_for_name(aVaccinesOfChart.back(), name_type.name, aChart, aHiDb);
    }

} // hidb::vaccines

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

std::string hidb::VaccinesOfChart::report(size_t aIndent) const
{
    std::string result;
    for (const auto& v: *this)
        result += v.report(aIndent);
    return result;

} // hidb::VaccinesOfChart::report

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

// void hidb::VaccinesOfChart::remove(std::string aName, std::string aType, std::string aPassageType)
// {
//     for (auto& v: *this) {
//         if (v.match(aName, aType))
//             v.remove(aPassageType);
//     }
//     erase(std::remove_if(begin(), end(), std::mem_fn<bool() const>(&hidb::Vaccines::empty)), end());

// } // hidb::VaccinesOfChart::remove

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

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>find_by_full_name<commit_after>#include <algorithm>
#include <functional>
#include <iomanip>

#include "hidb.hh"
#include "variant-id.hh"
#include "vaccines.hh"

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

#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#endif

static std::map<std::string, std::vector<hidb::Vaccine>> sVaccines = {
    {"A(H1N1)", {
            {"CALIFORNIA/7/2009",        hidb::Vaccine::Previous},
            {"MICHIGAN/45/2015",         hidb::Vaccine::Current},
        }},
    {"A(H3N2)", {
            {"BRISBANE/10/2007",         hidb::Vaccine::Previous},
            {"PERTH/16/2009",            hidb::Vaccine::Previous},
            {"VICTORIA/361/2011",        hidb::Vaccine::Previous},
            {"TEXAS/50/2012",            hidb::Vaccine::Previous},
            {"SWITZERLAND/9715293/2013", hidb::Vaccine::Previous},
            {"HONG KONG/4801/2014",      hidb::Vaccine::Current},
            {"SAITAMA/103/2014",         hidb::Vaccine::Surrogate},
            {"HONG KONG/7295/2014",      hidb::Vaccine::Surrogate},
        }},
    {"BVICTORIA", {
            {"MALAYSIA/2506/2004",       hidb::Vaccine::Previous},
            {"BRISBANE/60/2008",         hidb::Vaccine::Current},
              // {"PARIS/1762/2009",          hidb::Vaccine::Current}, // not used by Crick anymore, B/Ireland/3154/2016 is used instead (2017-08-21)
            {"SOUTH AUSTRALIA/81/2012",  hidb::Vaccine::Surrogate},
            {"IRELAND/3154/2016",  hidb::Vaccine::Surrogate},
        }},
    {"BYAMAGATA", {
            {"FLORIDA/4/2006",           hidb::Vaccine::Previous},
            {"WISCONSIN/1/2010",         hidb::Vaccine::Previous},
            {"MASSACHUSETTS/2/2012",     hidb::Vaccine::Previous},
            {"PHUKET/3073/2013",         hidb::Vaccine::Current},
        }},
};

#pragma GCC diagnostic pop

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

std::string hidb::Vaccine::type_as_string(hidb::Vaccine::Type aType)
{
    switch (aType) {
      case Previous:
          return "previous";
      case Current:
          return "current";
      case Surrogate:
          return "surrogate";
    }
    return {};

} // hidb::Vaccine::type_as_string

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

hidb::Vaccine::Type hidb::Vaccine::type_from_string(std::string aType)
{
    if (aType == "previous")
        return Previous;
    else if (aType == "current")
        return Current;
    else if (aType == "surrogate")
        return Surrogate;
    return Previous;

} // hidb::Vaccine::type_from_string

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

const std::vector<hidb::Vaccine>& hidb::vaccines(std::string aSubtype, std::string aLineage)
{
    return sVaccines.at(aSubtype + aLineage);

} // hidb::vaccines

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

const std::vector<hidb::Vaccine>& hidb::vaccines(const Chart& aChart)
{
    return vaccines(aChart.chart_info().virus_type(), aChart.lineage());

} // hidb::vaccines

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

std::string hidb::Vaccine::type_as_string() const
{
    return type_as_string(type);

} // hidb::Vaccine::type_as_string

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

inline bool hidb::Vaccines::Entry::operator < (const hidb::Vaccines::Entry& a) const
{
    const auto a_nt = a.antigen_data->number_of_tables(), t_nt = antigen_data->number_of_tables();
    return t_nt == a_nt ? most_recent_table_date > a.most_recent_table_date : t_nt > a_nt;
}

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

bool hidb::Vaccines::HomologousSerum::operator < (const hidb::Vaccines::HomologousSerum& a) const
{
    bool result = true;
    if (serum->serum_species() == "SHEEP") { // avoid using sheep serum as homologous (NIMR)
        result = false;
    }
    else {
        const auto s_nt = a.serum_data->number_of_tables(), t_nt = serum_data->number_of_tables();
        result = t_nt == s_nt ? most_recent_table_date > a.most_recent_table_date : t_nt > s_nt;
    }
    return result;

} // hidb::Vaccines::HomologousSerum::operator <

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

size_t hidb::Vaccines::HomologousSerum::number_of_tables() const
{
    return serum_data->number_of_tables();

} // hidb::Vaccines::HomologousSerum::number_of_tables

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

std::string hidb::Vaccines::report(size_t aIndent) const
{
    std::ostringstream out;
    if (!empty()) {
        out << std::string(aIndent, ' ') << "Vaccine " << type_as_string() << ' ' << mNameType.name << std::endl;
        for_each_passage_type([&](PassageType pt) { out << this->report(pt, aIndent + 2); });
    }
    return out.str();

} // hidb::Vaccines::report

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

std::string hidb::Vaccines::report(PassageType aPassageType, size_t aIndent, size_t aMark) const
{
    std::ostringstream out;
    const std::string indent(aIndent, ' ');
    auto entry_report = [&](size_t aNo, const auto& entry, bool aMarkIt) {
        out << indent << (aMarkIt ? ">>" : "  ") << std::setw(2) << aNo << ' ' << entry.antigen_index << ' ' << entry.antigen->full_name() << " tables:" << entry.antigen_data->number_of_tables() << " recent:" << entry.antigen_data->most_recent_table().table_id() << std::endl;
        for (const auto& hs: entry.homologous_sera)
            out << indent << "      " << hs.serum->serum_id() << ' ' << hs.serum->annotations().join() << " tables:" << hs.serum_data->number_of_tables() << " recent:" << hs.serum_data->most_recent_table().table_id() << std::endl;
    };

    const auto& entry = mEntries[aPassageType];
    if (!entry.empty()) {
        out << indent << passage_type_name(aPassageType) << " (" << entry.size() << ')' << std::endl;
        for (size_t no = 0; no < entry.size(); ++no)
            entry_report(no, entry[no], aMark == no);
    }
    return out.str();

} // hidb::Vaccines::report

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

void hidb::vaccines_for_name(Vaccines& aVaccines, std::string aName, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    std::vector<size_t> by_name;
    aChart.antigens().find_by_name(aName, by_name);
    for (size_t ag_no: by_name) {
        try {
            const auto& ag = static_cast<const Antigen&>(aChart.antigen(ag_no));
              // std::cerr << ag.full_name() << std::endl;
            const auto& data = aHiDb.find_antigen_of_chart(ag);
            std::vector<hidb::Vaccines::HomologousSerum> homologous_sera;
            for (const auto* sd: aHiDb.find_homologous_sera(data)) {
                if (const auto sr_no = aChart.sera().find_by_full_name(hidb::name_for_exact_matching(sd->data())))
                    homologous_sera.emplace_back(*sr_no, static_cast<const Serum*>(&aChart.serum(sr_no)), sd, aHiDb.charts()[sd->most_recent_table().table_id()].chart_info().date());
            }
            aVaccines.add(ag_no, ag, &data, std::move(homologous_sera), aHiDb.charts()[data.most_recent_table().table_id()].chart_info().date());
        }
        catch (hidb::HiDb::NotFound&) {
        }
    }
    aVaccines.sort();

} // hidb::vaccines_for_name

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

hidb::Vaccines* hidb::find_vaccines_in_chart(std::string aName, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    Vaccines* result = new Vaccines(Vaccine(aName, hidb::Vaccine::Previous));
    vaccines_for_name(*result, aName, aChart, aHiDb);
    return result;

} // find_vaccines_in_chart

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

void hidb::vaccines(VaccinesOfChart& aVaccinesOfChart, const Chart& aChart, const hidb::HiDb& aHiDb)
{
    for (const auto& name_type: vaccines(aChart)) {
        aVaccinesOfChart.emplace_back(name_type);
        vaccines_for_name(aVaccinesOfChart.back(), name_type.name, aChart, aHiDb);
    }

} // hidb::vaccines

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

std::string hidb::VaccinesOfChart::report(size_t aIndent) const
{
    std::string result;
    for (const auto& v: *this)
        result += v.report(aIndent);
    return result;

} // hidb::VaccinesOfChart::report

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

// void hidb::VaccinesOfChart::remove(std::string aName, std::string aType, std::string aPassageType)
// {
//     for (auto& v: *this) {
//         if (v.match(aName, aType))
//             v.remove(aPassageType);
//     }
//     erase(std::remove_if(begin(), end(), std::mem_fn<bool() const>(&hidb::Vaccines::empty)), end());

// } // hidb::VaccinesOfChart::remove

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

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "RenderCameraSystem.hpp"

#include <Components/CameraComponent.hpp>
#include <Components/SpotLight.hh>
#include <Components/DirectionalLightComponent.hh>
#include <Components/Light.hh>

#include <Core/Engine.hh>
#include <Core/AScene.hh>

#include <glm/gtc/matrix_transform.hpp>

#include <BFC/BFCLinkTracker.hpp>
#include <BFC/BFCBlockManagerFactory.hpp>
#include <BFC/BFCCullableObject.hpp>

#include <Graphic/DRBCameraDrawableList.hpp>
#include <Graphic/DRBSpotLightData.hpp>
#include <Graphic/BFCCullableTypes.hpp>
#include <Graphic/DRBMeshData.hpp>

#include <Threads/ThreadManager.hpp>
#include <Threads/RenderThread.hpp>
#include <Threads/MainThread.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>

#include "Utils/Frustum.hh"
#include "Utils/AABoundingBox.hh"

#include <Render/OcclusionTools/DepthMap.hpp>
#include <Render/OcclusionTools/DepthMapManager.hpp>
#include <Render/OcclusionTools/DepthMapHandle.hpp>

#include <Threads/TaskScheduler.hpp>
#include <Threads/Tasks/BasicTasks.hpp>

//temp
#include <chrono>

namespace AGE
{
	RenderCameraSystem::RenderCameraSystem(AScene *scene) :
		System(std::move(scene)),
		_cameras(std::move(scene)),
		_spotLights(std::move(scene)),
		_directionnalLights(std::move(scene)),
		_pointLights(std::move(scene))
	{
		_name = "Camera system";
	}

	bool RenderCameraSystem::initialize()
	{
		_cameras.requireComponent<CameraComponent>();
		_spotLights.requireComponent<SpotLightComponent>();
		_directionnalLights.requireComponent<DirectionalLightComponent>();
		_pointLights.requireComponent<PointLightComponent>();
		return (true);
	}

	void RenderCameraSystem::updateBegin(float time)
	{

	}

	void occlusionCulling(std::list<std::shared_ptr<DRBData>> &list)
	{
		SCOPE_profile_cpu_function("Camera system");

		auto depthMap = GetRenderThread()->getDepthMapManager().getReadableMap();
		//for (auto &e : cameraList->meshs)
		//{
		//	readableDepthMap->testBox()
		//}

		if (depthMap.isValid() == false)
		{
			return;
		}

		auto j = list.begin();
		while (j != std::end(list))
		{
			auto &d = *j;
			auto BB = std::static_pointer_cast<DRBMeshData>(d)->getAABB();

			glm::vec2 minPoint = glm::vec2(1);
			glm::vec2 maxPoint = glm::vec2(-1);

			float minZ = std::numeric_limits<float>::max();

			for (std::size_t i = 0; i < 8; ++i)
			{
				auto point = depthMap->getMV() * d->getTransformation() * glm::vec4(BB.getCornerPoint(i), 1.0f);
				point /= point.w;

				if (point.x < -1)
				{
					point.x = -1;
				}
				if (point.y < -1)
				{
					point.y = -1;
				}
				if (point.x > 1)
				{
					point.x = 1;
				}
				if (point.y > 1)
				{
					point.y = 1;
				}

				minPoint.x = std::min(minPoint.x, point.x);
				minPoint.y = std::min(minPoint.y, point.y);
				maxPoint.x = std::max(maxPoint.x, point.x);
				maxPoint.y = std::max(maxPoint.y, point.y);

				point.z = (point.z + 1.0f) * 0.5f;
				minZ = std::min(minZ, point.z);
			}

			glm::uvec2 screenMin(((minPoint + glm::vec2(1)) / glm::vec2(2)) * glm::vec2(depthMap->getMipmapWidth(), depthMap->getMipmapHeight()));
			glm::uvec2 screenMax(((maxPoint + glm::vec2(1)) / glm::vec2(2)) * glm::vec2(depthMap->getMipmapWidth(), depthMap->getMipmapHeight()));

			if (minZ < 0)
			{
				minZ = 0;
			}

			if (depthMap->testBox((uint32_t)(minZ * (1 << 24)), screenMin, screenMax) == false)
			{
				list.erase(j++);
			}
			else
			{
				GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DQuad>(glm::vec2(minPoint.x, minPoint.y), glm::vec2(minPoint.x, maxPoint.y), glm::vec2(maxPoint.x, maxPoint.y), glm::vec2(maxPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));

				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(minPoint.x, minPoint.y), glm::vec2(minPoint.x, maxPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(minPoint.x, maxPoint.y), glm::vec2(maxPoint.x, maxPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(maxPoint.x, maxPoint.y), glm::vec2(maxPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(maxPoint.x, minPoint.y), glm::vec2(minPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				++j;
			}
		}
	}

	void RenderCameraSystem::mainUpdate(float time)
	{
		SCOPE_profile_cpu_function("Camera system");
		_scene->getBfcLinkTracker()->reset();

		// check if the render thread does not already have stuff to draw
		if (GetMainThread()->isRenderFrame() == false)
		{
			return;
		}

		std::list<std::shared_ptr<DRBSpotLightDrawableList>> spotLightList;
		std::list<std::shared_ptr<DRBData>> pointLightList;

		for (auto &spotEntity : _spotLights.getCollection())
		{
			auto spot = spotEntity->getComponent<SpotLightComponent>();
			auto spotDrawableList = std::make_shared<DRBSpotLightDrawableList>();
			spotDrawableList->spotLight = spot->getCullableHandle().getPtr()->getDatas();

			auto spotData = std::static_pointer_cast<DRBSpotLightData>(spotDrawableList->spotLight);

			glm::mat4 spotViewProj = spot->updateShadowMatrix();

			Frustum spotlightFrustum;
			spotlightFrustum.setMatrix(spotViewProj);

			// Draw spotlight frustum debug:
			glm::vec4 worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, -1, 1.0f);
			glm::vec3 aNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, -1, 1.0f);
			glm::vec3 bNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, -1, 1.0f);
			glm::vec3 cNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, -1, 1.0f);
			glm::vec3 dNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, 1, 1.0f);
			glm::vec3 aFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, 1, 1.0f);
			glm::vec3 bFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, 1, 1.0f);
			glm::vec3 cFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, 1, 1.0f);
			glm::vec3 dFar = glm::vec3(worldPos / worldPos.w);

			glm::vec3 color = glm::vec3(1, 0, 0);
			bool activateDepth = true;

			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aNear, bNear, cNear, dNear, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aFar, bFar, cFar, dFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(aNear, aFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(bNear, bFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(cNear, cFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(dNear, dFar, color, activateDepth);

			std::atomic_size_t counter = 0;

			LFList<BFCItem> meshInLightList;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);

			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &spotlightFrustum, &counter, &meshInLightList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshInLightList, spotlightFrustum, i);
					counter.fetch_add(1);
				});
			}

			GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, meshBlocksToCullNumber]() {
				return counter >= meshBlocksToCullNumber;
			}));

			while (meshInLightList.getSize() > 0)
			{
				spotDrawableList->meshs.push_back(meshInLightList.pop()->getDrawable()->getDatas());
			}

			spotLightList.push_back(spotDrawableList);
		}
		for (auto &pointLightEntity : _pointLights.getCollection())
		{
			auto point = pointLightEntity->getComponent<PointLightComponent>();

			pointLightList.push_back(point->getCullableHandle().getPtr()->getDatas());
		}

		for (auto &cameraEntity : _cameras.getCollection())
		{
			Frustum cameraFrustum;
			auto camera = cameraEntity->getComponent<CameraComponent>();

			std::atomic_size_t counter = 0;

			auto cameraList = std::make_shared<DRBCameraDrawableList>();
			cameraList->cameraInfos.data = camera->getData();
			cameraList->cameraInfos.view = glm::inverse(cameraEntity->getLink().getGlobalTransform());

			cameraFrustum.setMatrix(camera->getProjection() * cameraList->cameraInfos.view);

			LFList<BFCItem> meshList;
			LFList<BFCItem> pointLightListToCull;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);
			std::size_t pointLightBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullablePointLight);
			std::size_t totalToCullNumber = meshBlocksToCullNumber + pointLightBlocksToCullNumber;

			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &meshList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshList, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			for (std::size_t i = 0; i < pointLightBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &pointLightListToCull](){
					bf->cullOnBlock(BFCCullableType::CullablePointLight, pointLightListToCull, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, totalToCullNumber]() {
				return counter >= totalToCullNumber;
			}));

			{
				SCOPE_profile_cpu_i("Camera system", "Copy LFList to std");
				while (meshList.getSize() > 0)
				{
					cameraList->meshs.push_back(meshList.pop()->getDrawable()->getDatas());
				}

				while (pointLightListToCull.getSize() > 0)
				{
					cameraList->pointLights.push_back(pointLightListToCull.pop()->getDrawable()->getDatas());
				}
			}
			occlusionCulling(cameraList->meshs);

			cameraList->spotLights = spotLightList;
			cameraList->pointLights = pointLightList;
			AGE::GetRenderThread()->getQueue()->emplaceTask<AGE::DRBCameraDrawableListCommand>(cameraList);
		}
	}

	void RenderCameraSystem::updateEnd(float time)
	{
	}
}<commit_msg>Profiling on camera system<commit_after>#include "RenderCameraSystem.hpp"

#include <Components/CameraComponent.hpp>
#include <Components/SpotLight.hh>
#include <Components/DirectionalLightComponent.hh>
#include <Components/Light.hh>

#include <Core/Engine.hh>
#include <Core/AScene.hh>

#include <glm/gtc/matrix_transform.hpp>

#include <BFC/BFCLinkTracker.hpp>
#include <BFC/BFCBlockManagerFactory.hpp>
#include <BFC/BFCCullableObject.hpp>

#include <Graphic/DRBCameraDrawableList.hpp>
#include <Graphic/DRBSpotLightData.hpp>
#include <Graphic/BFCCullableTypes.hpp>
#include <Graphic/DRBMeshData.hpp>

#include <Threads/ThreadManager.hpp>
#include <Threads/RenderThread.hpp>
#include <Threads/MainThread.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>

#include "Utils/Frustum.hh"
#include "Utils/AABoundingBox.hh"

#include <Render/OcclusionTools/DepthMap.hpp>
#include <Render/OcclusionTools/DepthMapManager.hpp>
#include <Render/OcclusionTools/DepthMapHandle.hpp>

#include <Threads/TaskScheduler.hpp>
#include <Threads/Tasks/BasicTasks.hpp>

//temp
#include <chrono>

namespace AGE
{
	RenderCameraSystem::RenderCameraSystem(AScene *scene) :
		System(std::move(scene)),
		_cameras(std::move(scene)),
		_spotLights(std::move(scene)),
		_directionnalLights(std::move(scene)),
		_pointLights(std::move(scene))
	{
		_name = "Camera system";
	}

	bool RenderCameraSystem::initialize()
	{
		_cameras.requireComponent<CameraComponent>();
		_spotLights.requireComponent<SpotLightComponent>();
		_directionnalLights.requireComponent<DirectionalLightComponent>();
		_pointLights.requireComponent<PointLightComponent>();
		return (true);
	}

	void RenderCameraSystem::updateBegin(float time)
	{

	}

	void occlusionCulling(std::list<std::shared_ptr<DRBData>> &list)
	{
		SCOPE_profile_cpu_function("Camera system");

		auto depthMap = GetRenderThread()->getDepthMapManager().getReadableMap();
		//for (auto &e : cameraList->meshs)
		//{
		//	readableDepthMap->testBox()
		//}

		if (depthMap.isValid() == false)
		{
			return;
		}

		auto j = list.begin();
		while (j != std::end(list))
		{
			auto &d = *j;
			auto BB = std::static_pointer_cast<DRBMeshData>(d)->getAABB();

			glm::vec2 minPoint = glm::vec2(1);
			glm::vec2 maxPoint = glm::vec2(-1);

			float minZ = std::numeric_limits<float>::max();

			for (std::size_t i = 0; i < 8; ++i)
			{
				auto point = depthMap->getMV() * d->getTransformation() * glm::vec4(BB.getCornerPoint(i), 1.0f);
				point /= point.w;

				if (point.x < -1)
				{
					point.x = -1;
				}
				if (point.y < -1)
				{
					point.y = -1;
				}
				if (point.x > 1)
				{
					point.x = 1;
				}
				if (point.y > 1)
				{
					point.y = 1;
				}

				minPoint.x = std::min(minPoint.x, point.x);
				minPoint.y = std::min(minPoint.y, point.y);
				maxPoint.x = std::max(maxPoint.x, point.x);
				maxPoint.y = std::max(maxPoint.y, point.y);

				point.z = (point.z + 1.0f) * 0.5f;
				minZ = std::min(minZ, point.z);
			}

			glm::uvec2 screenMin(((minPoint + glm::vec2(1)) / glm::vec2(2)) * glm::vec2(depthMap->getMipmapWidth(), depthMap->getMipmapHeight()));
			glm::uvec2 screenMax(((maxPoint + glm::vec2(1)) / glm::vec2(2)) * glm::vec2(depthMap->getMipmapWidth(), depthMap->getMipmapHeight()));

			if (minZ < 0)
			{
				minZ = 0;
			}

			if (depthMap->testBox((uint32_t)(minZ * (1 << 24)), screenMin, screenMax) == false)
			{
				list.erase(j++);
			}
			else
			{
				GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DQuad>(glm::vec2(minPoint.x, minPoint.y), glm::vec2(minPoint.x, maxPoint.y), glm::vec2(maxPoint.x, maxPoint.y), glm::vec2(maxPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));

				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(minPoint.x, minPoint.y), glm::vec2(minPoint.x, maxPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(minPoint.x, maxPoint.y), glm::vec2(maxPoint.x, maxPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(maxPoint.x, maxPoint.y), glm::vec2(maxPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				//GetRenderThread()->getQueue()->emplaceTask<AGE::Commands::ToRender::Draw2DLine>(glm::vec2(maxPoint.x, minPoint.y), glm::vec2(minPoint.x, minPoint.y), glm::vec3(0.2666, 0.73725, 0.9921));
				++j;
			}
		}
	}

	void RenderCameraSystem::mainUpdate(float time)
	{
		SCOPE_profile_cpu_function("Camera system");
		_scene->getBfcLinkTracker()->reset();

		// check if the render thread does not already have stuff to draw
		if (GetMainThread()->isRenderFrame() == false)
		{
			return;
		}

		std::list<std::shared_ptr<DRBSpotLightDrawableList>> spotLightList;
		std::list<std::shared_ptr<DRBData>> pointLightList;

		for (auto &spotEntity : _spotLights.getCollection())
		{
			auto spot = spotEntity->getComponent<SpotLightComponent>();
			auto spotDrawableList = std::make_shared<DRBSpotLightDrawableList>();
			spotDrawableList->spotLight = spot->getCullableHandle().getPtr()->getDatas();

			auto spotData = std::static_pointer_cast<DRBSpotLightData>(spotDrawableList->spotLight);

			glm::mat4 spotViewProj = spot->updateShadowMatrix();

			Frustum spotlightFrustum;
			spotlightFrustum.setMatrix(spotViewProj);

			// Draw spotlight frustum debug:
			glm::vec4 worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, -1, 1.0f);
			glm::vec3 aNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, -1, 1.0f);
			glm::vec3 bNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, -1, 1.0f);
			glm::vec3 cNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, -1, 1.0f);
			glm::vec3 dNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, 1, 1.0f);
			glm::vec3 aFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, 1, 1.0f);
			glm::vec3 bFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, 1, 1.0f);
			glm::vec3 cFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, 1, 1.0f);
			glm::vec3 dFar = glm::vec3(worldPos / worldPos.w);

			glm::vec3 color = glm::vec3(1, 0, 0);
			bool activateDepth = true;

			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aNear, bNear, cNear, dNear, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aFar, bFar, cFar, dFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(aNear, aFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(bNear, bFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(cNear, cFar, color, activateDepth);
			AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(dNear, dFar, color, activateDepth);

			std::atomic_size_t counter = 0;

			LFList<BFCItem> meshInLightList;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);

			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &spotlightFrustum, &counter, &meshInLightList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshInLightList, spotlightFrustum, i);
					counter.fetch_add(1);
				});
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Cull for spots");
				GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, meshBlocksToCullNumber]() {
					return counter >= meshBlocksToCullNumber;
				}));
			}

			while (meshInLightList.getSize() > 0)
			{
				spotDrawableList->meshs.push_back(meshInLightList.pop()->getDrawable()->getDatas());
			}

			spotLightList.push_back(spotDrawableList);
		}
		for (auto &pointLightEntity : _pointLights.getCollection())
		{
			auto point = pointLightEntity->getComponent<PointLightComponent>();

			pointLightList.push_back(point->getCullableHandle().getPtr()->getDatas());
		}

		for (auto &cameraEntity : _cameras.getCollection())
		{
			Frustum cameraFrustum;
			auto camera = cameraEntity->getComponent<CameraComponent>();

			std::atomic_size_t counter = 0;

			auto cameraList = std::make_shared<DRBCameraDrawableList>();
			cameraList->cameraInfos.data = camera->getData();
			cameraList->cameraInfos.view = glm::inverse(cameraEntity->getLink().getGlobalTransform());

			cameraFrustum.setMatrix(camera->getProjection() * cameraList->cameraInfos.view);

			LFList<BFCItem> meshList;
			LFList<BFCItem> pointLightListToCull;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);
			std::size_t pointLightBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullablePointLight);
			std::size_t totalToCullNumber = meshBlocksToCullNumber + pointLightBlocksToCullNumber;

			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &meshList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshList, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			for (std::size_t i = 0; i < pointLightBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &pointLightListToCull](){
					bf->cullOnBlock(BFCCullableType::CullablePointLight, pointLightListToCull, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Cull for cam");
				GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, totalToCullNumber]() {
					return counter >= totalToCullNumber;
				}));
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Copy LFList to std");
				while (meshList.getSize() > 0)
				{
					cameraList->meshs.push_back(meshList.pop()->getDrawable()->getDatas());
				}

				while (pointLightListToCull.getSize() > 0)
				{
					cameraList->pointLights.push_back(pointLightListToCull.pop()->getDrawable()->getDatas());
				}
			}
			occlusionCulling(cameraList->meshs);

			cameraList->spotLights = spotLightList;
			cameraList->pointLights = pointLightList;
			AGE::GetRenderThread()->getQueue()->emplaceTask<AGE::DRBCameraDrawableListCommand>(cameraList);
		}
	}

	void RenderCameraSystem::updateEnd(float time)
	{
	}
}<|endoftext|>


<commit_before>enum Atom
{
    atomRegister,
    atomSum,
    atomDereference,

    atomByte,
    atomWord,

    atomMov,
    atomPop,
    atomALU,
    atomOut,
    atomXchg,
    atomSegmentOverride,
    atomInc,
    atomJCond,
    atomJmp
};

#include "unity/symbol.h"

static const int c = 52;
static const int s = 22;
static const int b = 21;

int state = 0;
// States:
//   0 = Block start
//   1 = Mixing
//   2 = Block finish
//   3 = Frame update
int mixingSample = 0;
int block = 0;
int voice = 0;

class InstructionByte
{
private:
    Instruction* _instruction;
    int _byte;
};

class InstructionCycle
{
private:
    Instruction* _instruction;
    int _cycle;
};

Symbol parseRegister(CharacterSource* source)
{
    static String ax("ax");
    static String bx("bx");
    static String cx("cx");
    static String dx("dx");
    static String si("si");
    static String di("di");
    static String sp("sp");
    static String bp("bp");
    static String al("al");
    static String bl("bl");
    static String cl("cl");
    static String dl("dl");
    static String ah("ah");
    static String bh("bh");
    static String ch("ch");
    static String dh("dh");
    static String cs("cs");
    static String ss("ss");
    static String es("es");
    static String ds("ds");
    Span span;
    if (Space::parseKeyword(source, ax, &span))
        return Symbol(atomRegister, Symbol(atomWord), 0);
    if (Space::parseKeyword(source, cx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 1);
    if (Space::parseKeyword(source, dx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 2);
    if (Space::parseKeyword(source, bx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 3);
    if (Space::parseKeyword(source, sp, &span))
        return Symbol(atomRegister, Symbol(atomWord), 4);
    if (Space::parseKeyword(source, bp, &span))
        return Symbol(atomRegister, Symbol(atomWord), 5);
    if (Space::parseKeyword(source, si, &span))
        return Symbol(atomRegister, Symbol(atomWord), 6);
    if (Space::parseKeyword(source, di, &span))
        return Symbol(atomRegister, Symbol(atomWord), 7);

    if (Space::parseKeyword(source, al, &span))
        return Symbol(atomRegister, Symbol(atomWord), 0);
    if (Space::parseKeyword(source, cl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 1);
    if (Space::parseKeyword(source, dl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 2);
    if (Space::parseKeyword(source, bl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 3);
    if (Space::parseKeyword(source, ah, &span))
        return Symbol(atomRegister, Symbol(atomWord), 4);
    if (Space::parseKeyword(source, ch, &span))
        return Symbol(atomRegister, Symbol(atomWord), 5);
    if (Space::parseKeyword(source, dh, &span))
        return Symbol(atomRegister, Symbol(atomWord), 6);
    if (Space::parseKeyword(source, bh, &span))
        return Symbol(atomRegister, Symbol(atomWord), 7);

    if (Space::parseKeyword(source, es, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 0);
    if (Space::parseKeyword(source, cs, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 1);
    if (Space::parseKeyword(source, ss, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 2);
    if (Space::parseKeyword(source, ds, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 3);
    return Symbol();
}

Symbol parseMemory(CharacterSource* source)
{

}

int parseHexadecimalCharacter(CharacterSource* source, Span* span)
{
    CharacterSource s = *source;
    int c = s.get(span);
    if (c >= '0' && c <= '9') {
        *source = s;
        return c - '0';
    }
    if (c >= 'A' && c <= 'F') {
        *source = s;
        return c + 10 - 'A';
    }
    if (c >= 'a' && c <= 'f') {
        *source = s;
        return c + 10 - 'a';
    }
    return -1;
}

Symbol parseInteger(CharacterSource* source)
{
    CharacterSource s = *source;
    int n = 0;
    Span span;
    int c = s.get(&span);
    if (c < '0' || c > '9')
        return Symbol();
    if (c == '0') {
        do {
            Span span2;
            int d = parseHexadecimalCharacter(source, &span2);
            if (d == -1)
                break;
            n = n*16 + d;
            span += span2;
        } while (true);
    }
    do {
        n = n*10 + c - '0';
        *source = s;
        Span span2;
        c = s.get(&span2);
        if (c < '0' || c > '9')
            break;
        span += span2;
    } while (true);
    Space::parse(source);
    return Symbol(atomIntegerConstant, n);
}

Symbol parseLValue(CharacterSource* source)
{
    Symbol l = parseRegister(source);
    if (l.valid())
        return l;
    l = parseMemory(source);
    if (l.valid())
        return l;
    throw Exception();
}

Symbol parseExpression(CharacterSource* source)
{
    Symbol e = parseInteger(source);
    if (e.valid())
        return e;
    return parseLValue(source);
}

class Instruction
{
public:
    Instruction(String text)
    {
        CharacterSource source(text, "");
        Space::parse(&source);
        Span span;
        static String mov("mov");
        if (Space::parseKeyword(source, mov, &span)) {
            Symbol left = parseLValue(&source);
            if (!Space::parseCharacter(&source, ',', &span))
                throw Exception();
            Symbol right = parseExpression(&source);

/*
   88 /r          MOV rmb,rb             2  5+EA+4
   89 /r          MOV rmw,rw             2  5+EA+8
   8A /r          MOV rb,rmb             2  4+EA+4
   8B /r          MOV rw,rmw             2  4+EA+8
   A0 iw          MOV AL,xb              6+4
   A1 iw          MOV AX,xw              6+8
   A2 iw          MOV xb,AL              6+4
   A3 iw          MOV xw,AX              6+8
   B? ib          MOV rb,ib              4
   B? iw          MOV rw,iw              4
   C6 /0 ib       MOV rmb,ib             4  6+EA+4
   C6 /r ib       MOV rmb,ib             4  6+EA+4
   C7 /0 iw       MOV rmw,iw             4  6+EA+8
   C7 /r iw       MOV rmw,iw             4  6+EA+8
   8C /r          MOV rmw,segreg         2  5+EA+8
   8E /r          MOV segreg,rmw         2  4+EA+8
*/
        }
        static String pop("pop");
/*
   5?             POP rw                 4+8
*/
        static String add("add");
        static String adc("adc");
        static String sub("sub");
        static String cmp("cmp");
/*
   ?? /r          alu rmb,rb             3  8+EA+4+4
   ?? /r          alu rmw,rw             3  8+EA+8+8
   ?? /r          alu rb,rmb             3  5+EA+4
   ?? /r          alu rw,rmw             3  5+EA+8
   ?? ib          alu AL,ib              4
   ?? iw          alu AX,iw              4
   80 /? ib       alu rmb,ib             4  9+EA+4+4
   81 /0 iw       alu rmw,iw             4  9+EA+8+8
   83 /? ib       alu rmw,ib             4  9+EA+8+8
   38 /r          CMP rmb,rb             3  5+EA+4
   39 /r          CMP rmw,rw             3  5+EA+8
   80 /7 ib       CMP rmb,ib             4  6+EA+4
   81 /7 iw       CMP rmw,iw             4  6+EA+8
   83 /7 ib       CMP rmw,ib             4  6+EA+8
*/
        static String out("out");
/*
   E6 ib          OUT ib,AL              6+4
*/
        static String xchg("xchg");
/*
   86 /r          XCHG rmb,rb            4  9+EA+4+4
*/
        static String es("es:");
/*
   ??             segreg:
*/
        static String inc("inc");
/*
   4?             INC rw                 2
*/
        static String je("je");
/*
   7? cb          Jcond cb               4/16
*/
        static String jmp("jmp");
/*
   E9 cw          JMP cw                15
*/

    }
private:
    String _text;
    int _bytes;
    Byte _data[5];
    int _ios;
    int _position;
    int _cycle;
};

Instruction getNextInstruction()
{
    do {
        Instruction i;
        switch (state) {
            case 0:
                i = getNextInstructionMixing();
                if (i.valid())
                    return i;

                state = 1;
                break;
            case 1:
                i = getNextInstruction

}

int main()
{
}
<commit_msg>MOD player assembler<commit_after>enum Atom
{
    atomRegister,
    atomSum,
    atomDereference,

    atomByte,
    atomWord,

    atomMov,
    atomPop,
    atomALU,
    atomOut,
    atomXchg,
    atomSegmentOverride,
    atomInc,
    atomJCond,
    atomJmp
};

#include "unity/symbol.h"

static const int c = 52;
static const int s = 22;
static const int b = 21;

int state = 0;
// States:
//   0 = Block start
//   1 = Mixing
//   2 = Block finish
//   3 = Frame update
int mixingSample = 0;
int block = 0;
int voice = 0;

class InstructionByte
{
private:
    Instruction* _instruction;
    int _byte;
};

class InstructionCycle
{
private:
    Instruction* _instruction;
    int _cycle;
};

Symbol parseRegister(CharacterSource* source)
{
    static String ax("ax");
    static String bx("bx");
    static String cx("cx");
    static String dx("dx");
    static String si("si");
    static String di("di");
    static String sp("sp");
    static String bp("bp");
    static String al("al");
    static String bl("bl");
    static String cl("cl");
    static String dl("dl");
    static String ah("ah");
    static String bh("bh");
    static String ch("ch");
    static String dh("dh");
    static String cs("cs");
    static String ss("ss");
    static String es("es");
    static String ds("ds");
    Span span;
    if (Space::parseKeyword(source, ax, &span))
        return Symbol(atomRegister, Symbol(atomWord), 0);
    if (Space::parseKeyword(source, cx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 1);
    if (Space::parseKeyword(source, dx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 2);
    if (Space::parseKeyword(source, bx, &span))
        return Symbol(atomRegister, Symbol(atomWord), 3);
    if (Space::parseKeyword(source, sp, &span))
        return Symbol(atomRegister, Symbol(atomWord), 4);
    if (Space::parseKeyword(source, bp, &span))
        return Symbol(atomRegister, Symbol(atomWord), 5);
    if (Space::parseKeyword(source, si, &span))
        return Symbol(atomRegister, Symbol(atomWord), 6);
    if (Space::parseKeyword(source, di, &span))
        return Symbol(atomRegister, Symbol(atomWord), 7);

    if (Space::parseKeyword(source, al, &span))
        return Symbol(atomRegister, Symbol(atomWord), 0);
    if (Space::parseKeyword(source, cl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 1);
    if (Space::parseKeyword(source, dl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 2);
    if (Space::parseKeyword(source, bl, &span))
        return Symbol(atomRegister, Symbol(atomWord), 3);
    if (Space::parseKeyword(source, ah, &span))
        return Symbol(atomRegister, Symbol(atomWord), 4);
    if (Space::parseKeyword(source, ch, &span))
        return Symbol(atomRegister, Symbol(atomWord), 5);
    if (Space::parseKeyword(source, dh, &span))
        return Symbol(atomRegister, Symbol(atomWord), 6);
    if (Space::parseKeyword(source, bh, &span))
        return Symbol(atomRegister, Symbol(atomWord), 7);

    if (Space::parseKeyword(source, es, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 0);
    if (Space::parseKeyword(source, cs, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 1);
    if (Space::parseKeyword(source, ss, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 2);
    if (Space::parseKeyword(source, ds, &span))
        return Symbol(atomRegister, Symbol(atomSegmentOverride), 3);
    return Symbol();
}

Symbol parseMemory(CharacterSource* source, Span* span)
{
    CharacterSource s = *source;
    Span span;
    Span span2;
    int c = s.get(span);
    int size = 0;
    if (c == 'b' || c == 'B') {
        Space::parse(&s);
        size = 1;
        c = s.get(span2);
        span += span2;
    }
    else
        if (c == 'w' || c == 'W') {
            Space::parse(&s);
            size = 2;
            c = s.get(span2);
            span += span2;
        }
    if (c != '[')
        return Symbol();
    Space::parse(&s);
    Symbol expression = parseExpression(&s, &span2);
    if (!expression.valid())
        throw Exception();
    span += span2;
    c = s.get(span);
    if (c != ']')
        throw Exception();
    Space::parse(&s);
    span += span2;
    *source = s;
    return Symbol(atomDereference, size, expression);
}

int parseHexadecimalCharacter(CharacterSource* source, Span* span)
{
    CharacterSource s = *source;
    int c = s.get(span);
    if (c >= '0' && c <= '9') {
        *source = s;
        return c - '0';
    }
    if (c >= 'A' && c <= 'F') {
        *source = s;
        return c + 10 - 'A';
    }
    if (c >= 'a' && c <= 'f') {
        *source = s;
        return c + 10 - 'a';
    }
    return -1;
}

Symbol parseInteger(CharacterSource* source)
{
    CharacterSource s = *source;
    int n = 0;
    Span span;
    int c = s.get(&span);
    if (c < '0' || c > '9')
        return Symbol();
    if (c == '0') {
        do {
            Span span2;
            int d = parseHexadecimalCharacter(source, &span2);
            if (d == -1)
                break;
            n = n*16 + d;
            span += span2;
        } while (true);
    }
    do {
        n = n*10 + c - '0';
        *source = s;
        Span span2;
        c = s.get(&span2);
        if (c < '0' || c > '9')
            break;
        span += span2;
    } while (true);
    Space::parse(source);
    return Symbol(atomIntegerConstant, n);
}

Symbol parseLValue(CharacterSource* source)
{
    Symbol l = parseRegister(source);
    if (l.valid())
        return l;
    l = parseMemory(source);
    if (l.valid())
        return l;
    throw Exception();
}

Symbol parseExpression(CharacterSource* source)
{
    Symbol e = parseInteger(source);
    if (e.valid())
        return e;
    return parseLValue(source);
}

class Instruction
{
public:
    Instruction(String text)
    {
        CharacterSource source(text, "");
        Space::parse(&source);
        Span span;
        static String mov("mov");
        if (Space::parseKeyword(source, mov, &span)) {
            Symbol left = parseLValue(&source);
            if (!Space::parseCharacter(&source, ',', &span))
                throw Exception();
            Symbol right = parseExpression(&source);

/*
   88 /r          MOV rmb,rb             2  5+EA+4
   89 /r          MOV rmw,rw             2  5+EA+8
   8A /r          MOV rb,rmb             2  4+EA+4
   8B /r          MOV rw,rmw             2  4+EA+8
   A0 iw          MOV AL,xb              6+4
   A1 iw          MOV AX,xw              6+8
   A2 iw          MOV xb,AL              6+4
   A3 iw          MOV xw,AX              6+8
   B? ib          MOV rb,ib              4
   B? iw          MOV rw,iw              4
   C6 /0 ib       MOV rmb,ib             4  6+EA+4
   C6 /r ib       MOV rmb,ib             4  6+EA+4
   C7 /0 iw       MOV rmw,iw             4  6+EA+8
   C7 /r iw       MOV rmw,iw             4  6+EA+8
   8C /r          MOV rmw,segreg         2  5+EA+8
   8E /r          MOV segreg,rmw         2  4+EA+8
*/
        }
        static String pop("pop");
/*
   5?             POP rw                 4+8
*/
        static String add("add");
        static String adc("adc");
        static String sub("sub");
        static String cmp("cmp");
/*
   ?? /r          alu rmb,rb             3  8+EA+4+4
   ?? /r          alu rmw,rw             3  8+EA+8+8
   ?? /r          alu rb,rmb             3  5+EA+4
   ?? /r          alu rw,rmw             3  5+EA+8
   ?? ib          alu AL,ib              4
   ?? iw          alu AX,iw              4
   80 /? ib       alu rmb,ib             4  9+EA+4+4
   81 /0 iw       alu rmw,iw             4  9+EA+8+8
   83 /? ib       alu rmw,ib             4  9+EA+8+8
   38 /r          CMP rmb,rb             3  5+EA+4
   39 /r          CMP rmw,rw             3  5+EA+8
   80 /7 ib       CMP rmb,ib             4  6+EA+4
   81 /7 iw       CMP rmw,iw             4  6+EA+8
   83 /7 ib       CMP rmw,ib             4  6+EA+8
*/
        static String out("out");
/*
   E6 ib          OUT ib,AL              6+4
*/
        static String xchg("xchg");
/*
   86 /r          XCHG rmb,rb            4  9+EA+4+4
*/
        static String es("es:");
/*
   ??             segreg:
*/
        static String inc("inc");
/*
   4?             INC rw                 2
*/
        static String je("je");
/*
   7? cb          Jcond cb               4/16
*/
        static String jmp("jmp");
/*
   E9 cw          JMP cw                15
*/

    }
private:
    String _text;
    int _bytes;
    Byte _data[5];
    int _ios;
    int _position;
    int _cycle;
};

Instruction getNextInstruction()
{
    do {
        Instruction i;
        switch (state) {
            case 0:
                i = getNextInstructionMixing();
                if (i.valid())
                    return i;

                state = 1;
                break;
            case 1:
                i = getNextInstruction

}

int main()
{
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <cstdio>

#if     qPlatform_POSIX
#include    <unistd.h>
#include    <sys/types.h>
#include    <sys/socket.h>
#include    <sys/ioctl.h>
#include    <net/if.h>
#include    <netinet/in.h>
#include    <netdb.h>
#include    <arpa/inet.h>
#include    <netinet/in.h>
#include    <linux/netlink.h>
#include    <linux/rtnetlink.h>
#elif   qPlatform_Windows
#include    <WinSock2.h>
#include    <WS2tcpip.h>
#include    <Iphlpapi.h>
#include    <netioapi.h>
#endif

#include    "../../Characters/CString/Utilities.h"
#include    "../../Containers/Collection.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Thread.h"
#if     qPlatform_Windows
#include    "../../../Foundation/Execution/Platform/Windows/Exception.h"
#endif

#include    "Socket.h"

#include    "Interface.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;

Traversal::Iterable<Interface>  Network::GetInterfaces ()
{
    Collection<Interface>   result;
#if     qPlatform_POSIX
    auto getFlags = [] (int sd, const char* name) {
        char buf[1024];

        struct ifreq ifreq;
        memset(&ifreq, 0, sizeof (ifreq));
        strcpy (ifreq.ifr_name, name);

        int r = ioctl (sd, SIOCGIFFLAGS, (char*)&ifreq);
        Assert (r == 0);
        return (ifreq.ifr_flags);
    };

    struct ifreq ifreqs[64];
    struct ifconf ifconf;
    memset (&ifconf, 0, sizeof(ifconf));
    ifconf.ifc_req = ifreqs;
    ifconf.ifc_len = sizeof(ifreqs);

    int sd = socket (PF_INET, SOCK_STREAM, 0);
    Assert (sd >= 0);

    int r = ioctl (sd, SIOCGIFCONF, (char*)&ifconf);
    Assert (r == 0);

    InternetAddress result;
    for (int i = 0; i < ifconf.ifc_len / sizeof(struct ifreq); ++i) {
        Interface   newInterface;
        newInterface.fInterfaceName = String::FromSDKString (ifreqs[i].ifr_name);
        int flags = getFlags (sd, ifreqs[i].ifr_name);

        if (flags & IFF_LOOPBACK) {
            newInterface.fType = Interface::Type::eLoopback;
        }
        else {
            // NYI
            newInterface.fType = Interface::Type::eEthernet;    // WAY - not the right way to tell!
        }

        {
            Containers::Set<Interface::Status>  status;
            if (flags & IFF_RUNNING) {
                // not right!!! But a start...
                status.Add (Interface::Status::eConnected);
                status.Add (Interface::Status::eRunning);
            }
            newInterface.fStatus = status;
        }
        newInterface.fBindings.Add (InternetAddress (((struct sockaddr_in*)&ifreqs[i].ifr_addr)->sin_addr));
    }
    close (sd);
#else
    AssertNotImplemented ();
#endif

    return result;
}<commit_msg>minor poxix tweaks on recent changes<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <cstdio>

#if     qPlatform_POSIX
#include    <unistd.h>
#include    <sys/types.h>
#include    <sys/socket.h>
#include    <sys/ioctl.h>
#include    <net/if.h>
#include    <netinet/in.h>
#include    <netdb.h>
#include    <arpa/inet.h>
#include    <netinet/in.h>
#include    <linux/netlink.h>
#include    <linux/rtnetlink.h>
#elif   qPlatform_Windows
#include    <WinSock2.h>
#include    <WS2tcpip.h>
#include    <Iphlpapi.h>
#include    <netioapi.h>
#endif

#include    "../../Characters/CString/Utilities.h"
#include    "../../Containers/Collection.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Thread.h"
#if     qPlatform_Windows
#include    "../../../Foundation/Execution/Platform/Windows/Exception.h"
#endif

#include    "Socket.h"

#include    "Interface.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;

Traversal::Iterable<Interface>  Network::GetInterfaces ()
{
    Collection<Interface>   result;
#if     qPlatform_POSIX
    auto getFlags = [] (int sd, const char* name) {
        char buf[1024];

        struct ifreq ifreq;
        memset(&ifreq, 0, sizeof (ifreq));
        strcpy (ifreq.ifr_name, name);

        int r = ioctl (sd, SIOCGIFFLAGS, (char*)&ifreq);
        Assert (r == 0);
        return (ifreq.ifr_flags);
    };

    struct ifreq ifreqs[64];
    struct ifconf ifconf;
    memset (&ifconf, 0, sizeof(ifconf));
    ifconf.ifc_req = ifreqs;
    ifconf.ifc_len = sizeof(ifreqs);

    int sd = socket (PF_INET, SOCK_STREAM, 0);
    Assert (sd >= 0);

    int r = ioctl (sd, SIOCGIFCONF, (char*)&ifconf);
    Assert (r == 0);

    for (int i = 0; i < ifconf.ifc_len / sizeof(struct ifreq); ++i) {
        Interface   newInterface;
        newInterface.fInterfaceName = String::FromSDKString (ifreqs[i].ifr_name);
        int flags = getFlags (sd, ifreqs[i].ifr_name);

        if (flags & IFF_LOOPBACK) {
            newInterface.fType = Interface::Type::eLoopback;
        }
        else {
            // NYI
            newInterface.fType = Interface::Type::eWiredEthernet;    // WAY - not the right way to tell!
        }

        {
            Containers::Set<Interface::Status>  status;
            if (flags & IFF_RUNNING) {
                // not right!!! But a start...
                status.Add (Interface::Status::eConnected);
                status.Add (Interface::Status::eRunning);
            }
            newInterface.fStatus = status;
        }
        newInterface.fBindings.Add (InternetAddress (((struct sockaddr_in*)&ifreqs[i].ifr_addr)->sin_addr));
    }
    close (sd);
#else
    AssertNotImplemented ();
#endif

    return result;
}
<|endoftext|>