<commit_before>/*-
 * Copyright 2017 Shivansh Rai
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <dirent.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <memory>
#include <pthread.h>
#include <signal.h>
#include <stdexcept>
#include <sys/stat.h>
#include <thread>
#include <unordered_set>

#include "add_testcase.h"
#include "fetch_groff.h"
#include "generate_license.h"
#include "generate_test.h"
#include "read_annotations.h"

const char *tests_dir = "generated_tests/";  /* Directory to collect generated tests. */

void
generatetest::IntHandler(int dummmy)
{
	std::cerr << "\nExiting...\n";
	/* Remove the temporary directory. */
	remove(utils::tmpdir);
	exit(EXIT_FAILURE);
}

/* Generate a test for the given utility. */
void
generatetest::GenerateTest(std::string utility,
			   std::string section,
			   std::string& license)
{
	std::list<utils::OptRelation *> identified_opt_list;  /* List of identified option relations. */
	std::vector<std::string> usage_messages;         /* Vector of usage messages. Used for validating
							  * their consistency across different runs.
							  */
	std::string command;                             /* (Utility-specific) command to be executed. */
	std::string testcase_list;                       /* List of testcases. */
	std::string testcase_buffer;                     /* Buffer for (temporarily) holding testcase data. */
	std::string test_file;                           /* atf-sh test name. */
	std::string util_with_section;                   /* Section number appended to utility. */
	std::ofstream test_fstream;                      /* Output stream for the atf-sh test. */
	std::pair<std::string, int> output;              /* Return value type for `Execute()`. */
	std::unordered_set<std::string> annotation_set;  /* Hashset of utility specific annotations. */
	/* Number of options for which a testcase has been generated. */
	int progress = 0;

	/* Read annotations and populate hash set "annotation_set". */
	annotations::read_annotations(utility, annotation_set);

	util_with_section = utility + '(' + section + ')';

	utils::OptDefinition opt_def;
	identified_opt_list = opt_def.CheckOpts(utility);
	test_file = tests_dir + utility + "_test.sh";

	/* Indicate the start of test generation for current utility. */
	if (isatty(fileno(stderr))) {
		std::cerr << std::setw(18) << util_with_section << " | "
			  << progress << "/" << opt_def.opt_list.size() << "\r";
	}

	/* Add license in the generated test scripts. */
	test_fstream.open(test_file, std::ios::out);
	test_fstream << license;

	/*
	 * If a known option was encountered (i.e. `identified_opt_list` is
	 * populated), produce a testcase to check the validity of the
	 * result of that option. If no known option was encountered,
	 * produce testcases to verify the correct (generated) usage
	 * message when using the supported options incorrectly.
	 */

	/* Add testcases for known options. */
	if (!identified_opt_list.empty()) {
		for (const auto &i : identified_opt_list) {
			command = utility + " -" + i->value + " 2>&1 </dev/null";
			output = utils::Execute(command);
			if (boost::iequals(output.first.substr(0, 6), "usage:")) {
				/* A usage message was produced => our guessed usage is incorrect. */
				addtestcase::UnknownTestcase(i->value, util_with_section, output.first,
								   output.second, testcase_buffer);
			} else {
				addtestcase::KnownTestcase(i->value, util_with_section,
								 "", output.first, test_fstream);
			}
			testcase_list.append("\tatf_add_test_case " + i->value + "_flag\n");
		}
	}

	/* Add testcases for the options whose usage is not yet known. */
	if (!opt_def.opt_list.empty()) {
		/*
		 * For the purpose of adding a "$usage_output" variable,
		 * we choose the option which produces one.
		 * TODO(shivansh) Avoid double executions of an option, i.e. one while
		 * selecting usage message and another while generating testcase.
		 */

		if (opt_def.opt_list.size() == 1) {
			/* Utility supports a single option, check if it produces a usage message. */
			command = utility + " -" + opt_def.opt_list.front() + " 2>&1 </dev/null";
			output = utils::Execute(command);

			if (output.second && !output.first.empty())
				test_fstream << "usage_output=\'" + output.first + "\'\n\n";
		} else {
			/*
			 * Utility supports multiple options. In case the usage message
			 * is consistent for atleast "two" options, we reduce duplication
			 * by assigning a variable "usage_output" in the test script.
			 */
			for (const auto &i : opt_def.opt_list) {
				command = utility + " -" + i + " 2>&1 </dev/null";
				output = utils::Execute(command);

				if (output.second && usage_messages.size() < 3)
					usage_messages.push_back(output.first);
			}

			for (int j = 0; j < usage_messages.size(); j++) {
				if (!(usage_messages.at(j)).compare(usage_messages.at((j+1) % usage_messages.size())) &&
					!output.first.empty()) {
					test_fstream << "usage_output=\'"
						  + output.first.substr(0, 7 + utility.size())
						  + "\'\n\n";
					break;
				}
			}
		}

		/*
		 * Execute the utility with supported options
		 * and add (+ve)/(-ve) testcases accordingly.
		 */
		for (const auto &i : opt_def.opt_list) {
			/* If the option is annotated, ignore it. */
			if (annotation_set.find(i) != annotation_set.end())
				continue;

			command = utility + " -" + i + " 2>&1 </dev/null";
			output = utils::Execute(command);
			if (isatty(fileno(stderr))) {
				std::cerr << std::setw(18) << util_with_section << " | "
					  << ++progress << "/" << opt_def.opt_list.size() << "\r";
			}

			if (output.second) {
				/* Non-zero exit status was encountered. */
				addtestcase::UnknownTestcase(i, util_with_section, output.first,
							     output.second, testcase_buffer);
			} else {
				/*
				 * EXIT_SUCCESS was encountered. Hence,
				 * the guessed usage was correct.
				 */
				addtestcase::KnownTestcase(i, util_with_section, "",
							   output.first, test_fstream);
				testcase_list.append(std::string("\tatf_add_test_case ")
						     + i + "_flag\n");
			}
		}

		std::cerr << std::endl;

		testcase_list.append("\tatf_add_test_case invalid_usage\n");
		test_fstream << std::string("atf_test_case invalid_usage\ninvalid_usage_head()\n")
			  + "{\n\tatf_set \"descr\" \"Verify that an invalid usage "
			  + "with a supported option \" \\\n\t\t\t\"produces a valid error message"
			  + "\"\n}\n\ninvalid_usage_body()\n{";

		test_fstream << testcase_buffer + "\n}\n\n";
	}

	/*
	 * Add a testcase under "no_arguments" for
	 * running the utility without any arguments.
	 */
	if (annotation_set.find("*") == annotation_set.end()) {
		command = utility + " 2>&1 </dev/null";
		output = utils::Execute(command);
		addtestcase::NoArgsTestcase(util_with_section, output, test_fstream);
		testcase_list.append("\tatf_add_test_case no_arguments\n");
	}

	test_fstream << "atf_init_test_cases()\n{\n" + testcase_list + "}\n";
	test_fstream.close();
}

int
main(int argc, char **argv)
{
	std::ifstream groff_list;
	std::list<std::pair<std::string, std::string>> utility_list;
	std::string test_file;  /* atf-sh test name. */
	std::string util_name;  /* Utility name. */
	struct stat sb;
	struct dirent *ent;
	DIR *groff_dir_ptr;
	char answer;          	/* User input to determine updation of groff directory. */
	std::string license;  	/* Customized license generated during runtime. */
	/* Directory for collecting groff scripts for utilities with failed test generation. */
	const char *failed_groff_dir = "failed_groff/";
	const char *groff_dir = "groff/";  /* Directory of groff scripts. */

	/* Handle interrupts. */
	signal(SIGINT, generatetest::IntHandler);

	/*
	 * Create a temporary directory where all the
	 * side-effects introduced by utility-specific
	 * commands are restricted.
	 */
	boost::filesystem::create_directory(utils::tmpdir);

	/* Check if the directory "groff/" is populated with groff scripts. */
	std::cout << "Update groff directory ? (y/n) ";
	std::cin >> answer;

	if (answer == 'y')
		if (groff::FetchGroffScripts() == -1)
			return EXIT_FAILURE;

	/*
	 * For testing (or generating tests for only selected utilities),
	 * the utility_list can be populated above during declaration.
	 */
	if (utility_list.empty()) {
		if ((groff_dir_ptr = opendir(groff_dir))) {
			readdir(groff_dir_ptr); 	/* Skip directory entry for "." */
			readdir(groff_dir_ptr); 	/* Skip directory entry for ".." */
			while ((ent = readdir(groff_dir_ptr))) {
				util_name = ent->d_name;
				utility_list.push_back(std::make_pair<std::string, std::string>
						      (util_name.substr(0, util_name.length() - 2),
						       util_name.substr(util_name.length() - 1, 1)));
			}
			closedir(groff_dir_ptr);
		} else {
			fprintf(stderr, "Could not open the directory: groff/");
			return EXIT_FAILURE;
		}
	}

	/* Check if the directory "tests_dir" exists. */
	if (stat(tests_dir, &sb) || !S_ISDIR(sb.st_mode)) {
		boost::filesystem::path dir(tests_dir);
		if (boost::filesystem::create_directory(dir))
			std::cout << "Directory created: " << tests_dir << std::endl;
		else {
			std::cerr << "Unable to create directory: " << tests_dir << std::endl;
			return EXIT_FAILURE;
		}
	}

	/* Generate a license to be added in the generated scripts. */
	license = generatelicense::GenerateLicense(argc, argv);

	remove(failed_groff_dir);
	boost::filesystem::create_directory(failed_groff_dir);

	/* Generate a tabular-like format. */
	std::cout << std::endl;
	std::cout << std::setw(21) << "Utility | " << "Progress\n";
	std::cout << std::setw(32) << "----------+-----------\n";

	for (const auto &util : utility_list) {
		/* TODO(shivansh) Check before overwriting existing test scripts. */
		test_file = tests_dir + util.first + "_test.sh";
		fflush(stdout); 	/* Useful in debugging. */
		generatetest::GenerateTest(util.first, util.second, license);
	}

	/* Remove the temporary directory. */
	remove(utils::tmpdir);

	return EXIT_SUCCESS;
}
<commit_msg>Add "batch mode" for test generation<commit_after>/*-
 * Copyright 2017 Shivansh Rai
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <dirent.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <memory>
#include <pthread.h>
#include <signal.h>
#include <stdexcept>
#include <sys/stat.h>
#include <thread>
#include <unordered_set>

#include "add_testcase.h"
#include "fetch_groff.h"
#include "generate_license.h"
#include "generate_test.h"
#include "read_annotations.h"

const char *tests_dir = "generated_tests/";  /* Directory to collect generated tests. */

void
generatetest::IntHandler(int dummmy)
{
	std::cerr << "\nExiting...\n";
	/* Remove the temporary directory. */
	remove(utils::tmpdir);
	exit(EXIT_FAILURE);
}

/* Generate a test for the given utility. */
void
generatetest::GenerateTest(std::string utility,
			   std::string section,
			   std::string& license)
{
	std::list<utils::OptRelation *> identified_opt_list;  /* List of identified option relations. */
	/*
	 * Vector of usage messages -- used for validating
	 * their consistency across different runs.
	 */
	std::vector<std::string> usage_messages;
	std::string command;                             /* (Utility-specific) command to be executed. */
	std::string testcase_list;                       /* List of testcases. */
	std::string testcase_buffer;                     /* Buffer for (temporarily) holding testcase data. */
	std::string test_file;                           /* atf-sh test name. */
	std::string util_with_section;                   /* Section number appended to utility. */
	std::ofstream test_fstream;                      /* Output stream for the atf-sh test. */
	std::pair<std::string, int> output;              /* Return value type for `Execute()`. */
	std::unordered_set<std::string> annotation_set;  /* Hashset of utility specific annotations. */
	/* Number of options for which a testcase has been generated. */
	int progress = 0;

	/* Read annotations and populate hash set "annotation_set". */
	annotations::read_annotations(utility, annotation_set);

	util_with_section = utility + '(' + section + ')';

	utils::OptDefinition opt_def;
	identified_opt_list = opt_def.CheckOpts(utility);
	test_file = tests_dir + utility + "_test.sh";

	/* Indicate the start of test generation for current utility. */
	if (isatty(fileno(stderr))) {
		std::cerr << std::setw(18) << util_with_section << " | "
			  << progress << "/" << opt_def.opt_list.size() << "\r";
	}

	/* Add license in the generated test scripts. */
	test_fstream.open(test_file, std::ios::out);
	test_fstream << license;

	/*
	 * If a known option was encountered (i.e. `identified_opt_list` is
	 * populated), produce a testcase to check the validity of the
	 * result of that option. If no known option was encountered,
	 * produce testcases to verify the correct (generated) usage
	 * message when using the supported options incorrectly.
	 */

	/* Add testcases for known options. */
	if (!identified_opt_list.empty()) {
		for (const auto &i : identified_opt_list) {
			command = utility + " -" + i->value + " 2>&1 </dev/null";
			output = utils::Execute(command);
			if (boost::iequals(output.first.substr(0, 6), "usage:")) {
				/* A usage message was produced, i.e. our guessed usage is incorrect. */
				addtestcase::UnknownTestcase(i->value, util_with_section, output.first,
								   output.second, testcase_buffer);
			} else {
				addtestcase::KnownTestcase(i->value, util_with_section,
								 "", output.first, test_fstream);
			}
			testcase_list.append("\tatf_add_test_case " + i->value + "_flag\n");
		}
	}

	/* Add testcases for the options whose usage is not yet known. */
	if (!opt_def.opt_list.empty()) {
		/*
		 * For the purpose of adding a "$usage_output" variable,
		 * we choose the option which produces one.
		 * TODO(shivansh) Avoid double executions of an option, i.e. one while
		 * selecting usage message and another while generating testcase.
		 */
		if (opt_def.opt_list.size() == 1) {
			/* Utility supports a single option, check if it produces a usage message. */
			command = utility + " -" + opt_def.opt_list.front() + " 2>&1 </dev/null";
			output = utils::Execute(command);

			if (output.second && !output.first.empty())
				test_fstream << "usage_output=\'" + output.first + "\'\n\n";
		} else {
			/*
			 * Utility supports multiple options. In case the usage message
			 * is consistent for atleast "two" options, we reduce duplication
			 * by assigning a variable "usage_output" in the test script.
			 */
			for (const auto &i : opt_def.opt_list) {
				command = utility + " -" + i + " 2>&1 </dev/null";
				output = utils::Execute(command);

				if (output.second && usage_messages.size() < 3)
					usage_messages.push_back(output.first);
			}

			for (int j = 0; j < usage_messages.size(); j++) {
				if (!(usage_messages.at(j)).compare(usage_messages.at((j+1) % usage_messages.size())) &&
					!output.first.empty()) {
					test_fstream << "usage_output=\'"
						  + output.first.substr(0, 7 + utility.size())
						  + "\'\n\n";
					break;
				}
			}
		}

		/*
		 * Execute the utility with supported options
		 * and add (+ve)/(-ve) testcases accordingly.
		 */
		for (const auto &i : opt_def.opt_list) {
			/* If the option is annotated, ignore it. */
			if (annotation_set.find(i) != annotation_set.end())
				continue;

			command = utility + " -" + i + " 2>&1 </dev/null";
			output = utils::Execute(command);
			if (isatty(fileno(stderr))) {
				std::cerr << std::setw(18) << util_with_section << " | "
					  << ++progress << "/" << opt_def.opt_list.size() << "\r";
			}

			if (output.second) {
				/* Non-zero exit status was encountered. */
				addtestcase::UnknownTestcase(i, util_with_section, output.first,
							     output.second, testcase_buffer);
			} else {
				/*
				 * EXIT_SUCCESS was encountered. Hence,
				 * the guessed usage is correct.
				 */
				addtestcase::KnownTestcase(i, util_with_section, "",
							   output.first, test_fstream);
				testcase_list.append(std::string("\tatf_add_test_case ")
						     + i + "_flag\n");
			}
		}
		std::cerr << std::endl;

		testcase_list.append("\tatf_add_test_case invalid_usage\n");
		test_fstream << std::string("atf_test_case invalid_usage\ninvalid_usage_head()\n")
			  + "{\n\tatf_set \"descr\" \"Verify that an invalid usage "
			  + "with a supported option \" \\\n\t\t\t\"produces a valid error message"
			  + "\"\n}\n\ninvalid_usage_body()\n{";

		test_fstream << testcase_buffer + "\n}\n\n";
	}

	/*
	 * Add a testcase under "no_arguments" for
	 * running the utility without any arguments.
	 */
	if (annotation_set.find("*") == annotation_set.end()) {
		command = utility + " 2>&1 </dev/null";
		output = utils::Execute(command);
		addtestcase::NoArgsTestcase(util_with_section, output, test_fstream);
		testcase_list.append("\tatf_add_test_case no_arguments\n");
	}

	test_fstream << "atf_init_test_cases()\n{\n" + testcase_list + "}\n";
	test_fstream.close();
}

int
main(int argc, char **argv)
{
	std::ifstream groff_list;
	std::vector<std::pair<std::string, std::string>> util_vector;
	std::vector<std::pair<std::string, std::string>>::iterator util_vector_iter;
	std::string test_file;  /* atf-sh test name. */
	std::string util_name;  /* Utility name. */
	struct stat sb;
	struct dirent *ent;
	DIR *groff_dir_ptr;
	char answer;          	/* User input to determine actions to be taken. */
	std::string license;  	/* Customized license generated during runtime. */
	/* Directory for collecting groff scripts for utilities with failed test generation. */
	const char *failed_groff_dir = "failed_groff/";
	const char *groff_dir = "groff/";  /* Directory of groff scripts. */
	/*
	 * Instead of generating tests for all the utilities, "batch mode"
	 * allows generation of tests for first "batch_limit" number of
	 * utilities selected from "scripts/utils_list".
	 */
	bool batch_mode = false;
	int batch_limit = 8;    	   /* Number of tests to be generated in batch mode. */

	/* Handle interrupts. */
	signal(SIGINT, generatetest::IntHandler);

	/*
	 * Create a temporary directory where all the
	 * side-effects introduced by utility-specific
	 * commands are restricted.
	 */
	boost::filesystem::create_directory(utils::tmpdir);

	/* Check if the directory "groff/" is populated with groff scripts. */
	std::cout << "Update groff directory ? [y/N] ";
	std::cin.get(answer);

	switch(answer) {
		case 'y':
		case 'Y':
			if (groff::FetchGroffScripts() == -1)
				return EXIT_FAILURE;
			break;
		case '\n':
		default:
			break;
	}

	std::cout << "\nInstead of generating tests for all the utilities,\n"
		     "'batch mode' allows generation of tests for first "
		     + std::to_string(batch_limit) + "\nnumber of utilities "
		     "selected from 'scripts/utils_list'.\n"
		     "Run in 'batch mode' ? [y/N] ";
	std::cin.get(answer);

	switch(answer) {
		case 'y':
		case 'Y':
			batch_mode = true;
			break;
		case '\n':
		default:
			break;
	}

	/*
	 * For testing (or generating tests for only selected utilities),
	 * "util_vector" can be populated above during declaration.
	 */
	if (util_vector.empty()) {
		if ((groff_dir_ptr = opendir(groff_dir))) {
			readdir(groff_dir_ptr); 	/* Skip directory entry for "." */
			readdir(groff_dir_ptr); 	/* Skip directory entry for ".." */
			while ((ent = readdir(groff_dir_ptr))) {
				util_name = ent->d_name;
				util_vector.push_back(std::make_pair<std::string, std::string>
						      (util_name.substr(0, util_name.length() - 2),
						       util_name.substr(util_name.length() - 1, 1)));
			}
			closedir(groff_dir_ptr);
		} else {
			fprintf(stderr, "Could not open the directory: groff/");
			return EXIT_FAILURE;
		}
	}

	/* Check if the directory "tests_dir" exists. */
	if (stat(tests_dir, &sb) || !S_ISDIR(sb.st_mode)) {
		boost::filesystem::path dir(tests_dir);
		if (boost::filesystem::create_directory(dir))
			std::cout << "Directory created: " << tests_dir << std::endl;
		else {
			std::cerr << "Unable to create directory: " << tests_dir << std::endl;
			return EXIT_FAILURE;
		}
	}

	/* Generate a license to be added in the generated scripts. */
	license = generatelicense::GenerateLicense(argc, argv);

	remove(failed_groff_dir);
	boost::filesystem::create_directory(failed_groff_dir);

	/* Generate a tabular-like format. */
	std::cout << std::endl;
	std::cout << std::setw(21) << "Utility | " << "Progress\n";
	std::cout << std::setw(32) << "----------+-----------\n";

	if (batch_mode) {
		/*
		 * Generate tests for first "batch_limit" number of
		 * utilities selected from "scripts/utils_list".
		 */
		for (util_vector_iter = util_vector.begin();
		     util_vector_iter <= util_vector.begin() + batch_limit;
		     util_vector_iter++) {
			test_file = tests_dir + util_vector_iter->first + "_test.sh";
			generatetest::GenerateTest(util_vector_iter->first,
						   util_vector_iter->second, license);
		}
	} else {
		for (const auto &util : util_vector) {
			/* TODO(shivansh) Check before overwriting existing test scripts. */
			test_file = tests_dir + util.first + "_test.sh";
			generatetest::GenerateTest(util.first, util.second, license);
		}
	}

	/* Remove the temporary directory. */
	remove(utils::tmpdir);

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* get_inchi_data.cc
 * Copyright 2014 Cubane Canada, Inc.
 *
 * Released under the MIT license -- see MIT-LICENSE for details
 */
#include <cstring>

#include "./get_inchi_data.h"
#include "./inchi_lock.h"

/**
   "Tear-off" class that contains inchi_Input and inchi_Output
   structures for calling GetINCHI.

   Also stores result value and calculates InChIKey on success.

   @module Internal
   @class GetINCHIData
 */
/**

   @property in_
   @type inchi_Input
*/
/**

   @property out_
   @type inchi_Output
*/
/**
   The result code from calling GetINCHI

   @property result_
   @type RetValGetIchi
*/
/**
   InChIKey calculated from returned InChI only when
   return code indicates success

   @property inchikey_
   @type inchi_Input
*/

/**
 Constructor, creates empty data

 @constructor
 @method GetINCHIData
*/
GetINCHIData::GetINCHIData() {
  memset(&in_, 0, sizeof(in_));
  memset(&out_, 0, sizeof(out_));
  strncpy(inchikey, "", INCHIKEY_SIZE);
  result_ = inchi_Ret_UNKNOWN;
}

/**
 Destructor; calls FreeINCHI and delete

 @method ~GetINCHIData
*/
GetINCHIData::~GetINCHIData() {
  FreeINCHI(&out_);
  delete[] in_.atom;
  delete[] in_.stereo0D;
}

/**
   calculate INCHI from structure

   @method GetInchi
   @for GetINCHIData
   @return {RetValGetInchi} result code from GetINCHI API call
 */
int GetINCHIData::GetInchi() {
  Inchi_Global_Lock __lock;

  this->result_ = GetINCHI(&(this->in_), &(this->out_));

  if (this->result_ == inchi_Ret_OKAY) {
    GetINCHIKeyFromINCHI(this->out_.szInChI, 0, 0,
                         this->inchikey, 0, 0);
  }

  return this->result_;
}
<commit_msg>inchilib: calculate inchikey even if warning<commit_after>/* get_inchi_data.cc
 * Copyright 2014 Cubane Canada, Inc.
 *
 * Released under the MIT license -- see MIT-LICENSE for details
 */
#include <cstring>

#include "./get_inchi_data.h"
#include "./inchi_lock.h"

/**
   "Tear-off" class that contains inchi_Input and inchi_Output
   structures for calling GetINCHI.

   Also stores result value and calculates InChIKey on success.

   @module Internal
   @class GetINCHIData
 */
/**

   @property in_
   @type inchi_Input
*/
/**

   @property out_
   @type inchi_Output
*/
/**
   The result code from calling GetINCHI

   @property result_
   @type RetValGetIchi
*/
/**
   InChIKey calculated from returned InChI only when
   return code indicates success

   @property inchikey_
   @type inchi_Input
*/

/**
 Constructor, creates empty data

 @constructor
 @method GetINCHIData
*/
GetINCHIData::GetINCHIData() {
  memset(&in_, 0, sizeof(in_));
  memset(&out_, 0, sizeof(out_));
  strncpy(inchikey, "", INCHIKEY_SIZE);
  result_ = inchi_Ret_UNKNOWN;
}

/**
 Destructor; calls FreeINCHI and delete

 @method ~GetINCHIData
*/
GetINCHIData::~GetINCHIData() {
  FreeINCHI(&out_);
  delete[] in_.atom;
  delete[] in_.stereo0D;
}

/**
   calculate INCHI from structure

   @method GetInchi
   @for GetINCHIData
   @return {RetValGetInchi} result code from GetINCHI API call
 */
int GetINCHIData::GetInchi() {
  Inchi_Global_Lock __lock;

  this->result_ = GetINCHI(&(this->in_), &(this->out_));

  if (this->result_ == inchi_Ret_OKAY ||
      this->result_ == inchi_Ret_WARNING) {
    GetINCHIKeyFromINCHI(this->out_.szInChI, 0, 0,
                         this->inchikey, 0, 0);
  }

  return this->result_;
}
<|endoftext|>


<commit_before>#include "viewer.hpp"

#include <SDL_ttf.h>
#include <SDL_image.h>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/rotate_vector.hpp>

#include <algorithm>
#include <iostream>

Viewer::~Viewer() {
    TTF_Quit();
    SDL_DestroyTexture(m_render_tex);
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    IMG_Quit();
    SDL_Quit();
}

int Viewer::init() {
    std::cout << "Start init" << std::endl;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 600;
    int height = 400;

    m_window = SDL_CreateWindow("trac0r", 100, 100, width, height, SDL_WINDOW_SHOWN);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
    m_render_tex = SDL_CreateTexture(m_render, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
    m_pixels.resize(width*height, 0);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf error: " << SDL_GetError() << std::endl;
        return 1;
    }

    // Setup scene
    SDL_SetRelativeMouseMode(SDL_TRUE);
    setup_scene();

    std::cout << "Finish init" << std::endl;

    return 0;
}

void Viewer::setup_scene() {
    auto triangle = std::make_unique<Triangle>(glm::vec3{0.f, 5.f, 0.f}, glm::vec3{5.f, 5.f, 0.f}, glm::vec3{5.f, 5.f, 5.f}, glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    m_scene.push_back(std::move(triangle));
    // for (auto i = 0; i < 2; i++) {
    //     auto triangle = std::make_unique<Triangle>(glm::ballRand(5.f), glm::ballRand(5.f), glm::ballRand(5.f), glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    //     m_scene.push_back(std::move(triangle));
    // }

    m_camera.pos = {0, 0, 0};
    m_camera.dir = {0, 1, 0};
    m_camera.up = {0, 0, 1};
    m_camera.fov = 45.f;
    m_camera.near_plane_dist = 0.1f;
    m_camera.far_plane_dist = 100.f;
}

glm::vec3 Viewer::intersect_scene(glm::vec3 &ray_pos, glm::vec3 &ray_dir, int depth) {
    const auto MAX_DEPTH = 5;

    if (depth == MAX_DEPTH)
        return {0, 0, 0};

    // check all triangles for collision
    bool collided = false;
    glm::vec3 ret_color;
    for (const auto& tri : m_scene) {
        glm::vec3 bary_pos;
        collided = glm::intersectRayTriangle(ray_pos, ray_dir, tri->m_v1, tri->m_v2, tri->m_v3, bary_pos);

        if (collided) {
            glm::vec3 new_ray_pos = ray_pos + ray_dir * bary_pos.z;
            auto new_ray_dir = tri->m_normal;
            new_ray_dir = glm::rotateX(tri->m_normal, glm::linearRand(-90.f, 90.f));
            new_ray_dir = glm::rotateY(tri->m_normal, glm::linearRand(-90.f, 90.f));

            float cos_theta = glm::dot(new_ray_dir, tri->m_normal);
            glm::vec3 brdf = 2.f * tri->m_reflectance * cos_theta;
            glm::vec3 reflected = intersect_scene(new_ray_pos, new_ray_dir, depth + 1);

            ret_color = tri->m_color + (brdf * reflected);
            break;
        }
    }

    if (collided) {
        return ret_color;
    }
    else {
        return {0, 0, 0};
    }
}

void Viewer::mainloop() {
    // Input
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        if (e.type == SDL_QUIT) {
            shutdown();
        }
        if (e.type == SDL_KEYDOWN) {
            if (e.key.keysym.sym == SDLK_ESCAPE) {
                shutdown();
            }
        }
    }

    glm::vec3 cam_velocity{0};
    const uint8_t *keystates = SDL_GetKeyboardState(0);
    if (keystates[SDL_SCANCODE_A])
        cam_velocity.x += -1;
    else if (keystates[SDL_SCANCODE_D])
        cam_velocity.x += 1;

    if (keystates[SDL_SCANCODE_W])
        cam_velocity.y += -1;
    else if (keystates[SDL_SCANCODE_S])
        cam_velocity.y += 1;

    m_camera.pos += cam_velocity;

    // Rendering here
    int width;
    int height;
    SDL_GetWindowSize(m_window, &width, &height);
    auto aspect_ratio = (float)width/(float)height;

    int mouse_x;
    int mouse_y;
    SDL_GetRelativeMouseState(&mouse_x, &mouse_y);

    m_camera.dir = glm::rotateX(m_camera.dir, mouse_y * 0.001f);
    m_camera.dir = glm::rotateZ(m_camera.dir, mouse_x * -0.001f);

    std::cout << glm::to_string(m_camera.pos) << std::endl;
    std::cout << glm::to_string(m_camera.dir) << std::endl;

    glm::mat4 projection_matrix = glm::perspective(m_camera.fov, aspect_ratio, m_camera.near_plane_dist, m_camera.far_plane_dist);
    glm::mat4 view_matrix = glm::lookAt(m_camera.pos, m_camera.pos + m_camera.dir, m_camera.up);

    // Sort by distance to camera
    std::sort(m_scene.begin(), m_scene.end(), [this](const auto &tri1, const auto &tri2){return glm::distance(m_camera.pos, tri1->m_centroid) < glm::distance(m_camera.pos, tri2->m_centroid);});
    for (auto sample_cnt = 0; sample_cnt < 2; sample_cnt++) {
        for (auto x = 0; x < width; x++) {
            for (auto y = 0; y < height; y++) {
                glm::vec3 win_coords{x, y, 0};
                glm::mat4 model{1.0f};
                glm::vec4 viewport{0, 0, width, height};
                glm::vec3 object_coords = glm::unProject(win_coords, model * view_matrix, projection_matrix, viewport);
                glm::vec3 color = intersect_scene(object_coords, m_camera.dir, 0);
                // std::cout << "r: " << color.r << " g: " << color.g << " b: " << color.b << std::endl;
                m_pixels[y * width + x] = 0xff << 24 | int(color.r * 255) << 16 | int(color.g * 255) << 8 | int(color.b * 255);
            }
        }
    }

    SDL_SetRenderDrawColor(m_render, glm::linearRand(0, 255), glm::linearRand(0, 255), glm::linearRand(0, 255), 255);
    SDL_RenderClear(m_render);
    SDL_UpdateTexture(m_render_tex, 0, m_pixels.data(), width * sizeof(uint32_t));
    SDL_RenderCopy(m_render, m_render_tex, 0, 0);

    SDL_RenderPresent(m_render);

    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    (void)dt;
    m_last_frame_time = current_time;

    std::cout << "FPS: " << 1./dt << std::endl;
}

SDL_Renderer *Viewer::renderer() {
    return m_render;
}

SDL_Window *Viewer::window() {
    return m_window;
}

bool Viewer::is_running() {
    return m_running;
}

void Viewer::shutdown() {
    m_running = false;
}
<commit_msg>Change FOV to 90.f<commit_after>#include "viewer.hpp"

#include <SDL_ttf.h>
#include <SDL_image.h>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/rotate_vector.hpp>

#include <algorithm>
#include <iostream>

Viewer::~Viewer() {
    TTF_Quit();
    SDL_DestroyTexture(m_render_tex);
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    IMG_Quit();
    SDL_Quit();
}

int Viewer::init() {
    std::cout << "Start init" << std::endl;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 600;
    int height = 400;

    m_window = SDL_CreateWindow("trac0r", 100, 100, width, height, SDL_WINDOW_SHOWN);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
    m_render_tex = SDL_CreateTexture(m_render, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
    m_pixels.resize(width*height, 0);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf error: " << SDL_GetError() << std::endl;
        return 1;
    }

    // Setup scene
    SDL_SetRelativeMouseMode(SDL_TRUE);
    setup_scene();

    std::cout << "Finish init" << std::endl;

    return 0;
}

void Viewer::setup_scene() {
    auto triangle = std::make_unique<Triangle>(glm::vec3{0.f, 5.f, 0.f}, glm::vec3{5.f, 5.f, 0.f}, glm::vec3{5.f, 5.f, 5.f}, glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    m_scene.push_back(std::move(triangle));
    // for (auto i = 0; i < 2; i++) {
    //     auto triangle = std::make_unique<Triangle>(glm::ballRand(5.f), glm::ballRand(5.f), glm::ballRand(5.f), glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    //     m_scene.push_back(std::move(triangle));
    // }

    m_camera.pos = {0, 0, 0};
    m_camera.dir = {0, 1, 0};
    m_camera.up = {0, 0, 1};
    m_camera.fov = 90.f;
    m_camera.near_plane_dist = 0.1f;
    m_camera.far_plane_dist = 100.f;
}

glm::vec3 Viewer::intersect_scene(glm::vec3 &ray_pos, glm::vec3 &ray_dir, int depth) {
    const auto MAX_DEPTH = 5;

    if (depth == MAX_DEPTH)
        return {0, 0, 0};

    // check all triangles for collision
    bool collided = false;
    glm::vec3 ret_color;
    for (const auto& tri : m_scene) {
        glm::vec3 bary_pos;
        collided = glm::intersectRayTriangle(ray_pos, ray_dir, tri->m_v1, tri->m_v2, tri->m_v3, bary_pos);

        if (collided) {
            glm::vec3 new_ray_pos = ray_pos + ray_dir * bary_pos.z;
            auto new_ray_dir = tri->m_normal;
            new_ray_dir = glm::rotateX(tri->m_normal, glm::linearRand(-90.f, 90.f));
            new_ray_dir = glm::rotateY(tri->m_normal, glm::linearRand(-90.f, 90.f));

            float cos_theta = glm::dot(new_ray_dir, tri->m_normal);
            glm::vec3 brdf = 2.f * tri->m_reflectance * cos_theta;
            glm::vec3 reflected = intersect_scene(new_ray_pos, new_ray_dir, depth + 1);

            ret_color = tri->m_color + (brdf * reflected);
            break;
        }
    }

    if (collided) {
        return ret_color;
    }
    else {
        return {0, 0, 0};
    }
}

void Viewer::mainloop() {
    // Input
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        if (e.type == SDL_QUIT) {
            shutdown();
        }
        if (e.type == SDL_KEYDOWN) {
            if (e.key.keysym.sym == SDLK_ESCAPE) {
                shutdown();
            }
        }
    }

    glm::vec3 cam_velocity{0};
    const uint8_t *keystates = SDL_GetKeyboardState(0);
    if (keystates[SDL_SCANCODE_A])
        cam_velocity.x += -1;
    else if (keystates[SDL_SCANCODE_D])
        cam_velocity.x += 1;

    if (keystates[SDL_SCANCODE_W])
        cam_velocity.y += -1;
    else if (keystates[SDL_SCANCODE_S])
        cam_velocity.y += 1;

    m_camera.pos += cam_velocity;

    // Rendering here
    int width;
    int height;
    SDL_GetWindowSize(m_window, &width, &height);
    auto aspect_ratio = (float)width/(float)height;

    int mouse_x;
    int mouse_y;
    SDL_GetRelativeMouseState(&mouse_x, &mouse_y);

    m_camera.dir = glm::rotateX(m_camera.dir, mouse_y * 0.001f);
    m_camera.dir = glm::rotateZ(m_camera.dir, mouse_x * -0.001f);

    std::cout << glm::to_string(m_camera.pos) << std::endl;
    std::cout << glm::to_string(m_camera.dir) << std::endl;

    glm::mat4 projection_matrix = glm::perspective(m_camera.fov, aspect_ratio, m_camera.near_plane_dist, m_camera.far_plane_dist);
    glm::mat4 view_matrix = glm::lookAt(m_camera.pos, m_camera.pos + m_camera.dir, m_camera.up);

    // Sort by distance to camera
    std::sort(m_scene.begin(), m_scene.end(), [this](const auto &tri1, const auto &tri2){return glm::distance(m_camera.pos, tri1->m_centroid) < glm::distance(m_camera.pos, tri2->m_centroid);});
    for (auto sample_cnt = 0; sample_cnt < 2; sample_cnt++) {
        for (auto x = 0; x < width; x++) {
            for (auto y = 0; y < height; y++) {
                glm::vec3 win_coords{x, y, 0};
                glm::mat4 model{1.0f};
                glm::vec4 viewport{0, 0, width, height};
                glm::vec3 object_coords = glm::unProject(win_coords, model * view_matrix, projection_matrix, viewport);
                glm::vec3 color = intersect_scene(object_coords, m_camera.dir, 0);
                // std::cout << "r: " << color.r << " g: " << color.g << " b: " << color.b << std::endl;
                m_pixels[y * width + x] = 0xff << 24 | int(color.r * 255) << 16 | int(color.g * 255) << 8 | int(color.b * 255);
            }
        }
    }

    SDL_SetRenderDrawColor(m_render, glm::linearRand(0, 255), glm::linearRand(0, 255), glm::linearRand(0, 255), 255);
    SDL_RenderClear(m_render);
    SDL_UpdateTexture(m_render_tex, 0, m_pixels.data(), width * sizeof(uint32_t));
    SDL_RenderCopy(m_render, m_render_tex, 0, 0);

    SDL_RenderPresent(m_render);

    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    (void)dt;
    m_last_frame_time = current_time;

    std::cout << "FPS: " << 1./dt << std::endl;
}

SDL_Renderer *Viewer::renderer() {
    return m_render;
}

SDL_Window *Viewer::window() {
    return m_window;
}

bool Viewer::is_running() {
    return m_running;
}

void Viewer::shutdown() {
    m_running = false;
}
<|endoftext|>


<commit_before>#include <miopen/handle.hpp>
#include <miopen/errors.hpp>
#include <miopen/device_name.hpp>
#include <miopen/kernel_cache.hpp>
#include <algorithm>

#ifndef _WIN32
#include <unistd.h>
#endif

#include <cassert>
#include <chrono>
#include <thread>

namespace miopen {

hipDevice_t get_device(int id)
{
    hipDevice_t device;
    auto status = hipDeviceGet(&device, id);
    if (status != hipSuccess) MIOPEN_THROW("No device");
    return device;
}

int get_device_id() // Get random device
{
    int device;
    auto status = hipGetDevice(&device);
    if (status != hipSuccess) MIOPEN_THROW("No device");
    return device;
}

void set_device(int id)
{
    auto status = hipSetDevice(id);
    if (status != hipSuccess) MIOPEN_THROW("Error setting device");
}

void set_default_device()
{
    int n;
    auto status = hipGetDeviceCount(&n);
    if (status != hipSuccess) MIOPEN_THROW("Error getting device count");
    // Pick device based on process id
    auto pid = ::getpid();
    assert(pid > 0);
    set_device(pid % n);
}

struct HandleImpl
{
    // typedef MIOPEN_MANAGE_PTR(hipStream_t, hipStreamDestroy) StreamPtr;
    using StreamPtr = std::shared_ptr<typename std::remove_pointer<hipStream_t>::type>;

    HandleImpl()
    {}

    StreamPtr create_stream()
    {
        hipStream_t result;
        auto status = hipStreamCreate(&result);
        if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Failed to allocate stream");
        return StreamPtr{result, &hipStreamDestroy};
    }

    static StreamPtr reference_stream(hipStream_t s)
    {
        return StreamPtr{s, null_deleter{}};
    }

    void elapsed_time(hipEvent_t start, hipEvent_t stop)
    {
        hipEventElapsedTime(&this->profiling_result, start, stop);
    }

    std::function<void(hipEvent_t, hipEvent_t)> elapsed_time_handler()
    {
        return std::bind(&HandleImpl::elapsed_time, this, std::placeholders::_1, std::placeholders::_2);
    }

    bool enable_profiling = false;
    StreamPtr stream;
    float profiling_result = 0.0;
    KernelCache cache;
};

Handle::Handle (miopenAcceleratorQueue_t stream)
: impl(new HandleImpl())
{
    if (stream == nullptr) this->impl->stream = HandleImpl::reference_stream(nullptr);
    else this->impl->stream = HandleImpl::reference_stream(stream);
}

Handle::Handle ()
: impl(new HandleImpl())
{
    set_default_device();
    // this->impl->stream = impl->create_stream();
    this->impl->stream = HandleImpl::reference_stream(nullptr);
}

Handle::~Handle() {}

miopenAcceleratorQueue_t Handle::GetStream() const
{
    return impl->stream.get();
}

void Handle::EnableProfiling(bool enable)
{
    this->impl->enable_profiling = enable;
}

float Handle::GetKernelTime() const
{
    return this->impl->profiling_result;
}

ManageDataPtr Handle::Create(int sz)
{
    this->Finish();
    void * result;
    auto status = hipMalloc(&result, sz);
    if (status != hipSuccess)
    {
        status = hipHostMalloc(&result, sz);
        if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error creating buffer " + std::to_string(sz) + ": ");
    }
    return ManageDataPtr{result};
}
ManageDataPtr& Handle::WriteTo(const void* data, ManageDataPtr& ddata, int sz)
{
    this->Finish();
    auto status = hipMemcpy(ddata.get(), data, sz, hipMemcpyHostToDevice);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error writing to buffer: ");
    return ddata;
}
void Handle::ReadTo(void* data, const ManageDataPtr& ddata, int sz)
{
    this->Finish();
    auto status = hipMemcpy(data, ddata.get(), sz, hipMemcpyDeviceToHost);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error reading from buffer: ");
}

void Handle::Copy(ConstData_t src, Data_t dest, int size)
{
    auto status = hipMemcpy(dest, src, size, hipMemcpyDeviceToDevice);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error copying buffer: ");
}

KernelInvoke Handle::GetKernel(
        const std::string& algorithm,
        const std::string& network_config,
        const std::string& program_name,
        const std::string& kernel_name,
        const std::vector<size_t>& vld,
        const std::vector<size_t>& vgd,
        const std::string& params)
{
    auto k = this->impl->cache.GetKernel(*this,
            algorithm,
            network_config,
            program_name,
            kernel_name,
            vld,
            vgd,
            params);
    if (this->impl->enable_profiling) return k.Invoke(this->GetStream(), this->impl->elapsed_time_handler());
    else return k.Invoke(this->GetStream());
}

KernelInvoke Handle::GetKernel(
    const std::string& algorithm,
    const std::string& network_config)
{
    auto k = this->impl->cache.GetKernel(
            algorithm,
            network_config);
    if (this->impl->enable_profiling) return k.Invoke(this->GetStream(), this->impl->elapsed_time_handler());
    else return k.Invoke(this->GetStream());
}

Program Handle::LoadProgram(const std::string &program_name, std::string params, bool is_kernel_str)
{
    params += " -mcpu=" + this->GetDeviceName();
    return HIPOCProgram{program_name, params, is_kernel_str};
}

void Handle::Finish() const
{
#if MIOPEN_BUILD_DEV
    auto start = std::chrono::system_clock::now();
    auto ev = make_hip_event();
    hipEventRecord(ev.get(), this->GetStream());
    while(hipEventQuery(ev.get()) == hipErrorNotReady)
    {
        std::this_thread::yield();
        if ((std::chrono::system_clock::now()-start) > std::chrono::seconds(60))
        {
            std::cerr << "Timeout: Handle::Finish" << std::endl;
            std::abort();
        }
    }
#else
    auto status = hipStreamSynchronize(this->GetStream());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Failed hip sychronization");
#endif
}
void Handle::Flush() const
{

}

bool Handle::IsProfilingEnabled() const
{
	return this->impl->enable_profiling;
}

void Handle::ResetKernelTime()
{
    this->impl->profiling_result = 0.0;
}
void Handle::AccumKernelTime(float x)
{
    this->impl->profiling_result += x;
}

std::size_t Handle::GetLocalMemorySize()
{
    int result;
    auto status = hipDeviceGetAttribute(&result, hipDeviceAttributeMaxSharedMemoryPerBlock, get_device_id());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status);

    return result;
}

std::size_t Handle::GetMaxComputeUnits()
{
    int result;
    auto status = hipDeviceGetAttribute(&result, hipDeviceAttributeMultiprocessorCount, get_device_id());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status);

    return result;
}

std::string Handle::GetDeviceName()
{
    hipDeviceProp_t props;
    hipGetDeviceProperties(&props, get_device_id());
    std::string n("gfx"+std::to_string(props.gcnArch));
	return GetDeviceNameFromMap(n);
}
} // namespace miopen
<commit_msg>Check free memory<commit_after>#include <miopen/handle.hpp>
#include <miopen/errors.hpp>
#include <miopen/device_name.hpp>
#include <miopen/kernel_cache.hpp>
#include <algorithm>

#ifndef _WIN32
#include <unistd.h>
#endif

#include <cassert>
#include <chrono>
#include <thread>

namespace miopen {

hipDevice_t get_device(int id)
{
    hipDevice_t device;
    auto status = hipDeviceGet(&device, id);
    if (status != hipSuccess) MIOPEN_THROW("No device");
    return device;
}

int get_device_id() // Get random device
{
    int device;
    auto status = hipGetDevice(&device);
    if (status != hipSuccess) MIOPEN_THROW("No device");
    return device;
}

void set_device(int id)
{
    auto status = hipSetDevice(id);
    if (status != hipSuccess) MIOPEN_THROW("Error setting device");
}

void set_default_device()
{
    int n;
    auto status = hipGetDeviceCount(&n);
    if (status != hipSuccess) MIOPEN_THROW("Error getting device count");
    // Pick device based on process id
    auto pid = ::getpid();
    assert(pid > 0);
    set_device(pid % n);
}

struct HandleImpl
{
    // typedef MIOPEN_MANAGE_PTR(hipStream_t, hipStreamDestroy) StreamPtr;
    using StreamPtr = std::shared_ptr<typename std::remove_pointer<hipStream_t>::type>;

    HandleImpl()
    {}

    StreamPtr create_stream()
    {
        hipStream_t result;
        auto status = hipStreamCreate(&result);
        if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Failed to allocate stream");
        return StreamPtr{result, &hipStreamDestroy};
    }

    static StreamPtr reference_stream(hipStream_t s)
    {
        return StreamPtr{s, null_deleter{}};
    }

    void elapsed_time(hipEvent_t start, hipEvent_t stop)
    {
        hipEventElapsedTime(&this->profiling_result, start, stop);
    }

    std::function<void(hipEvent_t, hipEvent_t)> elapsed_time_handler()
    {
        return std::bind(&HandleImpl::elapsed_time, this, std::placeholders::_1, std::placeholders::_2);
    }

    bool enable_profiling = false;
    StreamPtr stream;
    float profiling_result = 0.0;
    KernelCache cache;
};

Handle::Handle (miopenAcceleratorQueue_t stream)
: impl(new HandleImpl())
{
    if (stream == nullptr) this->impl->stream = HandleImpl::reference_stream(nullptr);
    else this->impl->stream = HandleImpl::reference_stream(stream);
}

Handle::Handle ()
: impl(new HandleImpl())
{
    set_default_device();
    // this->impl->stream = impl->create_stream();
    this->impl->stream = HandleImpl::reference_stream(nullptr);
}

Handle::~Handle() {}

miopenAcceleratorQueue_t Handle::GetStream() const
{
    return impl->stream.get();
}

void Handle::EnableProfiling(bool enable)
{
    this->impl->enable_profiling = enable;
}

float Handle::GetKernelTime() const
{
    return this->impl->profiling_result;
}

std::size_t GetAvailableMemory()
{
    size_t free, total;
    auto status = hipMemGetInfo(&free, &total);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Failed getting available memory");
    return free;
}

ManageDataPtr Handle::Create(int sz)
{
    this->Finish();
    if (sz > GetAvailableMemory()) MIOPEN_THROW("Memory not available to allocate buffer " + std::to_string(sz));
    void * result;
    auto status = hipMalloc(&result, sz);
    if (status != hipSuccess)
    {
        status = hipHostMalloc(&result, sz);
        if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error creating buffer " + std::to_string(sz) + ": ");
    }
    return ManageDataPtr{result};
}
ManageDataPtr& Handle::WriteTo(const void* data, ManageDataPtr& ddata, int sz)
{
    this->Finish();
    auto status = hipMemcpy(ddata.get(), data, sz, hipMemcpyHostToDevice);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error writing to buffer: ");
    return ddata;
}
void Handle::ReadTo(void* data, const ManageDataPtr& ddata, int sz)
{
    this->Finish();
    auto status = hipMemcpy(data, ddata.get(), sz, hipMemcpyDeviceToHost);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error reading from buffer: ");
}

void Handle::Copy(ConstData_t src, Data_t dest, int size)
{
    auto status = hipMemcpy(dest, src, size, hipMemcpyDeviceToDevice);
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Hip error copying buffer: ");
}

KernelInvoke Handle::GetKernel(
        const std::string& algorithm,
        const std::string& network_config,
        const std::string& program_name,
        const std::string& kernel_name,
        const std::vector<size_t>& vld,
        const std::vector<size_t>& vgd,
        const std::string& params)
{
    auto k = this->impl->cache.GetKernel(*this,
            algorithm,
            network_config,
            program_name,
            kernel_name,
            vld,
            vgd,
            params);
    if (this->impl->enable_profiling) return k.Invoke(this->GetStream(), this->impl->elapsed_time_handler());
    else return k.Invoke(this->GetStream());
}

KernelInvoke Handle::GetKernel(
    const std::string& algorithm,
    const std::string& network_config)
{
    auto k = this->impl->cache.GetKernel(
            algorithm,
            network_config);
    if (this->impl->enable_profiling) return k.Invoke(this->GetStream(), this->impl->elapsed_time_handler());
    else return k.Invoke(this->GetStream());
}

Program Handle::LoadProgram(const std::string &program_name, std::string params, bool is_kernel_str)
{
    params += " -mcpu=" + this->GetDeviceName();
    return HIPOCProgram{program_name, params, is_kernel_str};
}

void Handle::Finish() const
{
#if MIOPEN_BUILD_DEV
    auto start = std::chrono::system_clock::now();
    auto ev = make_hip_event();
    hipEventRecord(ev.get(), this->GetStream());
    while(hipEventQuery(ev.get()) == hipErrorNotReady)
    {
        std::this_thread::yield();
        if ((std::chrono::system_clock::now()-start) > std::chrono::seconds(60))
        {
            std::cerr << "Timeout: Handle::Finish" << std::endl;
            std::abort();
        }
    }
#else
    auto status = hipStreamSynchronize(this->GetStream());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status, "Failed hip sychronization");
#endif
}
void Handle::Flush() const
{

}

bool Handle::IsProfilingEnabled() const
{
	return this->impl->enable_profiling;
}

void Handle::ResetKernelTime()
{
    this->impl->profiling_result = 0.0;
}
void Handle::AccumKernelTime(float x)
{
    this->impl->profiling_result += x;
}

std::size_t Handle::GetLocalMemorySize()
{
    int result;
    auto status = hipDeviceGetAttribute(&result, hipDeviceAttributeMaxSharedMemoryPerBlock, get_device_id());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status);

    return result;
}

std::size_t Handle::GetMaxComputeUnits()
{
    int result;
    auto status = hipDeviceGetAttribute(&result, hipDeviceAttributeMultiprocessorCount, get_device_id());
    if (status != hipSuccess) MIOPEN_THROW_HIP_STATUS(status);

    return result;
}

std::string Handle::GetDeviceName()
{
    hipDeviceProp_t props;
    hipGetDeviceProperties(&props, get_device_id());
    std::string n("gfx"+std::to_string(props.gcnArch));
	return GetDeviceNameFromMap(n);
}
} // namespace miopen
<|endoftext|>


<commit_before>#include "yta_http.hpp"

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <vector>

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <unistd.h>

#include <http_parser.h>

namespace yta {
namespace http {

char* serve_200(char* buf, int content_length, time_t* last_modified) {
    const char base_buf[] = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\n";
    std::size_t base_buf_size = sizeof(base_buf) - 1;

    const char last_modified_buf[] = "Last-Modified: ";
    std::size_t last_modified_size = sizeof(last_modified_buf) - 1;
    const char content_length_buf[] = "\r\nContent-Length: ";
    std::size_t content_length_buf_size = sizeof(content_length_buf) - 1;

    const char linefeed[] = "\r\n\r\n";

    buf = std::copy(base_buf, base_buf + base_buf_size, buf);
    buf = std::copy(last_modified_buf, last_modified_buf + last_modified_size, buf);
    buf += strftime(buf, 512, http_time_format(), gmtime(last_modified));
    buf = std::copy(content_length_buf, content_length_buf + content_length_buf_size,
                       buf);
    buf += sprintf(buf, "%d", content_length);
    buf = std::copy(linefeed, linefeed + 4, buf);

    return buf;
}

char* serve_304(char* buf) {
    const char result[] = "HTTP/1.1 304 Not Modified\r\nConnection: "
                          "keep-alive\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

char* serve_206(char* buf, int content_length,
                time_t* last_modified, int range_start, int range_end, int file_size) {
    const char base_buf[] = "HTTP/1.1 206 Partial Content\r\nAccept-Ranges: bytes";
    std::size_t base_buf_size = sizeof(base_buf) - 1;

    const char last_modified_buf[] = "\r\nLast-Modified: ";
    std::size_t last_modified_size = sizeof(last_modified_buf) - 1;

    const char content_range_buf[] = "\r\nContent-Range: bytes ";
    std::size_t content_range_buf_size = sizeof(content_range_buf) - 1;

        const char content_length_buf[] = "\r\nContent-Length: ";
    std::size_t content_length_buf_size = sizeof(content_length_buf) - 1;

    const char linefeed[] = "\r\n\r\n";

    buf = std::copy(base_buf, base_buf + base_buf_size, buf);

    buf = std::copy(last_modified_buf, last_modified_buf + last_modified_size, buf);
    buf +=
        strftime(buf, 512, http_time_format(), gmtime(last_modified));
    buf = std::copy(content_range_buf, content_range_buf + content_range_buf_size, buf);
    buf += sprintf(buf, "%d", range_start);
    *(buf++) = '-';
    buf += sprintf(buf, "%d", range_end);
    *buf++ = '/';
    buf += sprintf(buf, "%d", file_size);
    buf = std::copy(content_length_buf, content_length_buf + content_length_buf_size,
                       buf);
    buf += sprintf(buf, "%d", content_length);

    buf = std::copy(linefeed, linefeed + 4, buf);

    return buf;
}

char* serve_400(char* buf) {
    const char result[] = "HTTP/1.1 400 Bad Request\r\nConnection: "
                          "close\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

char* serve_404(char* buf) {
    const char result[] = "HTTP/1.1 404 Not Found\r\nConnection: "
                          "keep-alive\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

// translated from Go source
// Cleans path from .. etc; returns new path size
std::size_t clean_path(char* path, std::size_t length) {
    char temp_buf[512];
    char* output = temp_buf;

    if (length == 0) {
        *path = '.';
        return 1;
    }

    std::size_t r = 0;
    std::size_t dotdot = 0;

    bool rooted = (path[0] == '/');
    if (rooted) {
        *output++ = '/';
        r = 1;
        dotdot = 1;
    }

    while (r < length) {
        if (path[r] == '/') {
            ++r;
        } else if (path[r] == '.' && (r+1 == length || path[r+1] == '/')) {
            ++r;
        } else if (path[r] == '.' && path[r+1] == '.' && (r+2 == length || path[r+2] == '/')) {
            r += 2;

            if (std::size_t(output - temp_buf) > dotdot) {
                --output;
                while (std::size_t(output - temp_buf) > dotdot && *output != '/') {
                    --output;
                }
            } else if(!rooted) {
                if (output - temp_buf > 0) {
                    *output++ = '/';
                }
                *output++ = '.';
                *output++ = '.';
                dotdot = output - &temp_buf[0];
            }
        } else {
            if ((rooted && (std::size_t(output - temp_buf) != 1)) || (!rooted && (output - temp_buf != 0))) {
                *output++ = '/';
            }

            for(; r < length && path[r] != '/'; ++r) {
                *output++ = path[r];
            }
        }
    }

    if (output - temp_buf == 0) {
        *output++ = '.';
    }

    std::copy(&temp_buf[0], output, path);
    return output - &temp_buf[0];
}

}
}
<commit_msg>removed legacy include<commit_after>#include "yta_http.hpp"

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <vector>

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <unistd.h>

namespace yta {
namespace http {

char* serve_200(char* buf, int content_length, time_t* last_modified) {
    const char base_buf[] = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\n";
    std::size_t base_buf_size = sizeof(base_buf) - 1;

    const char last_modified_buf[] = "Last-Modified: ";
    std::size_t last_modified_size = sizeof(last_modified_buf) - 1;
    const char content_length_buf[] = "\r\nContent-Length: ";
    std::size_t content_length_buf_size = sizeof(content_length_buf) - 1;

    const char linefeed[] = "\r\n\r\n";

    buf = std::copy(base_buf, base_buf + base_buf_size, buf);
    buf = std::copy(last_modified_buf, last_modified_buf + last_modified_size, buf);
    buf += strftime(buf, 512, http_time_format(), gmtime(last_modified));
    buf = std::copy(content_length_buf, content_length_buf + content_length_buf_size,
                       buf);
    buf += sprintf(buf, "%d", content_length);
    buf = std::copy(linefeed, linefeed + 4, buf);

    return buf;
}

char* serve_304(char* buf) {
    const char result[] = "HTTP/1.1 304 Not Modified\r\nConnection: "
                          "keep-alive\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

char* serve_206(char* buf, int content_length,
                time_t* last_modified, int range_start, int range_end, int file_size) {
    const char base_buf[] = "HTTP/1.1 206 Partial Content\r\nAccept-Ranges: bytes";
    std::size_t base_buf_size = sizeof(base_buf) - 1;

    const char last_modified_buf[] = "\r\nLast-Modified: ";
    std::size_t last_modified_size = sizeof(last_modified_buf) - 1;

    const char content_range_buf[] = "\r\nContent-Range: bytes ";
    std::size_t content_range_buf_size = sizeof(content_range_buf) - 1;

        const char content_length_buf[] = "\r\nContent-Length: ";
    std::size_t content_length_buf_size = sizeof(content_length_buf) - 1;

    const char linefeed[] = "\r\n\r\n";

    buf = std::copy(base_buf, base_buf + base_buf_size, buf);

    buf = std::copy(last_modified_buf, last_modified_buf + last_modified_size, buf);
    buf +=
        strftime(buf, 512, http_time_format(), gmtime(last_modified));
    buf = std::copy(content_range_buf, content_range_buf + content_range_buf_size, buf);
    buf += sprintf(buf, "%d", range_start);
    *(buf++) = '-';
    buf += sprintf(buf, "%d", range_end);
    *buf++ = '/';
    buf += sprintf(buf, "%d", file_size);
    buf = std::copy(content_length_buf, content_length_buf + content_length_buf_size,
                       buf);
    buf += sprintf(buf, "%d", content_length);

    buf = std::copy(linefeed, linefeed + 4, buf);

    return buf;
}

char* serve_400(char* buf) {
    const char result[] = "HTTP/1.1 400 Bad Request\r\nConnection: "
                          "close\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

char* serve_404(char* buf) {
    const char result[] = "HTTP/1.1 404 Not Found\r\nConnection: "
                          "keep-alive\r\nContent-Length: 0\r\n\r\n";
    return std::copy(result, result + sizeof(result) - 1, buf);
}

// translated from Go source
// Cleans path from .. etc; returns new path size
std::size_t clean_path(char* path, std::size_t length) {
    char temp_buf[512];
    char* output = temp_buf;

    if (length == 0) {
        *path = '.';
        return 1;
    }

    std::size_t r = 0;
    std::size_t dotdot = 0;

    bool rooted = (path[0] == '/');
    if (rooted) {
        *output++ = '/';
        r = 1;
        dotdot = 1;
    }

    while (r < length) {
        if (path[r] == '/') {
            ++r;
        } else if (path[r] == '.' && (r+1 == length || path[r+1] == '/')) {
            ++r;
        } else if (path[r] == '.' && path[r+1] == '.' && (r+2 == length || path[r+2] == '/')) {
            r += 2;

            if (std::size_t(output - temp_buf) > dotdot) {
                --output;
                while (std::size_t(output - temp_buf) > dotdot && *output != '/') {
                    --output;
                }
            } else if(!rooted) {
                if (output - temp_buf > 0) {
                    *output++ = '/';
                }
                *output++ = '.';
                *output++ = '.';
                dotdot = output - &temp_buf[0];
            }
        } else {
            if ((rooted && (std::size_t(output - temp_buf) != 1)) || (!rooted && (output - temp_buf != 0))) {
                *output++ = '/';
            }

            for(; r < length && path[r] != '/'; ++r) {
                *output++ = path[r];
            }
        }
    }

    if (output - temp_buf == 0) {
        *output++ = '.';
    }

    std::copy(&temp_buf[0], output, path);
    return output - &temp_buf[0];
}

}
}
<|endoftext|>


<commit_before>#ifndef COLOSHELL_HPP
#define COLOSHELL_HPP

#include "platform.h"
#include "rpexception.hpp"
#include <iostream>
#include <iomanip>

#ifdef WINDOWS
#include <windows.h>
#endif

#define COLORS_ENABLED                     // remove this define if you don't want color in your shell

/* Here you will find all you need to display the data in a cute way on a windows/unix terminal */

#ifdef WINDOWS
    enum Colors
    {
        COLO_RED = FOREGROUND_RED | FOREGROUND_INTENSITY,
        COLO_GREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
        COLO_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
        COLO_DEFAULT = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
    };

#else
    enum Colors
    {
        COLO_RED = 0,
        COLO_GREEN = 1,
        COLO_YELLOW = 2,
        COLO_DEFAULT = 3
    };

#endif

/**
 * \fn static void enable_color(const Colors colo)
 * \brief Enable a color in your shell
 *
 * \param colo: the color you want to activate
 */
static void enable_color(const Colors colo)
{
#ifdef COLORS_ENABLED
#ifdef WINDOWS
    HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    if(hStdOutput == INVALID_HANDLE_VALUE)
        RAISE_EXCEPTION("Cannot find a STD_OUTPUT_HANDLE valid value");

    SetConsoleTextAttribute(
        hStdOutput,
        colo
        );
#else
    const char *colors[] = {
        "\x1b[91m", "\x1b[92m",
        "\x1b[93m", "\x1b[0m"
    };
    std::cout << colors[colo];
#endif

#else
#endif
}

/**
 * \fn static void disable_color(const Colors colo)
 * \brief Unset the color you have previously set
 */
static void disable_color(void)
{
#ifdef COLORS_ENABLED
#ifdef WINDOWS
    HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    if(hStdOutput == INVALID_HANDLE_VALUE)
        RAISE_EXCEPTION("Cannot find a STD_OUTPUT_HANDLE valid value");

    SetConsoleTextAttribute(
        hStdOutput,
        COLO_DEFAULT
        );
#else
    const char *colors[] = {
        "\x1b[91m", "\x1b[92m",
        "\x1b[93m", "\x1b[0m"
    };
    std::cout << colors[COLO_DEFAULT];
#endif
#else
#endif
}

/**
 * \fn static void coloshell(const T t, const Colors colo)
 * \brief Display "t" on the stdout with the color "colo"
 *
 * \param t: the thing you want to output
 * \param colo: the color you want to enable
 */
template<class T>
static void coloshell(const T t, const Colors colo)
{
    enable_color(colo);
    std::cout << t;
    disable_color();
}

/**
 * \def w_red(text)
 * \brief Display text in red on stdout
 *
 * \param text: the text you want to display
 */
#define w_red(text) {          \
    coloshell(text, COLO_RED); \
}

/**
 * \def w_yel(text)
 * \brief Display text in yellow on stdout
 *
 * \param text: the text you want to display
 */
#define w_yel(text) {              \
    coloshell(text, COLO_YELLOW);  \
}

/**
 * \def w_gre(text)
 * \brief Display text in green on stdout
 *
 * \param text: the text you want to display
 */
#define w_gre(text) {            \
    coloshell(text, COLO_GREEN); \
}

/**
 * \def w_red_lf(text)
 * \brief Display text in red on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_red_lf(text) {     \
    w_red(text);             \
    std::cout << std::endl;  \
}

/**
 * \def w_yel_lf(text)
 * \brief Display text in yellow on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_yel_lf(text) {     \
    w_yel(text);             \
    std::cout << std::endl;  \
}

/**
 * \def w_gre_lf(text)
 * \brief Display text in green on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_gre_lf(text) {     \
    w_gre_lf(text);          \
    std::cout << std::endl;  \
}

/**
 * \def display_hex_field(field, n)
 * \brief Display an hex value in red with 0 filling etc.
 *
 * \param field: It is the hex value you want to output
 * \param n: It is the size of the column
 */
#define display_hex_field(field, n) {                                                         \
    std::cout << std::setw(n) << std::left << std::setfill(' ') << " "#field << ": ";         \
    enable_color(COLO_RED);                                                                   \
    std::cout << "0x" << std::setw(sizeof(field) * 2) << std::right << std::setfill('0');     \
    std::cout << std::hex << field;                                                           \
    disable_color();                                                                          \
}

/**
 * \def display_hex_field_lf(field, n)
 * \brief Display an hex value in red with 0 filling, a line feed and 25b column.
 *
 * \param field: It is the hex value you want to output
 */
#define display_hex_field_lf(field) { \
    display_hex_field(field, 25);     \
    std::cout << std::endl;           \
}

/**
 * \def display_hex_2fields_lf(field1, field2)
 * \brief Display two hex values in red on a same line.
 *
 * \param field1: It is the first hex value you want to output
 * \param field2: It is the second hex value you want to output
 */
#define display_hex_2fields_lf(field1, field2) { \
    display_hex_field(field1, 25);               \
    display_hex_field(field2, 25);               \
    std::cout << std::endl;                      \
}

/**
 * \def display_short_hex_field(field)
 * \brief Display a short hex value in red.
 *
 * \param field: It is the short hex value you want to output
 */
#define display_short_hex_field(field) {    \
    display_hex_field(field, 14);           \
}

/**
 * \def display_short_hex_field_lf(field)
 * \brief Display a short hex value in red with a line feed.
 *
 * \param field: It is the short hex value you want to output
 */
#define display_short_hex_field_lf(field) { \
    display_short_hex_field(field);         \
    std::cout << std::endl;                 \
}

/**
 * \def display_short_hex_2fields_lf(field1, field2)
 * \brief Display two short hex values in red with a line feed.
 *
 * \param field1: It is the first short hex value you want to output
 * \param field2: It is the second short hex value you want to output
 */
#define display_short_hex_2fields_lf(field1, field2) { \
    display_short_hex_field(field1);                   \
    display_short_hex_field(field2);                   \
    std::cout << std::endl;                            \
}

/**
 * \def display_string(field_name, field)
 * \brief Display a field with its name.
 *
 * \param field_name: It is the field name
 * \param field: It is the field
 */
#define display_string(field_name, field) {                                      \
    std::cout << std::setw(15) << std::right << std::setfill(' ') << field_name; \
    std::cout << ": " << field;                                                  \
}

/**
 * \def display_string_lf(field_name, field)
 * \brief Display a field with its name and a line feed.
 *
 * \param field_name: It is the field name
 * \param field: It is the field
 */
#define display_string_lf(field_name, field) { \
    display_string(field_name, field);         \
    std::cout << std::endl;                    \
}

/**
 * \def display_2strings_lf(field_name1, field1, field_name2, field2)
 * \brief Display two fields with their names and a line feed.
 *
 * \param field_name1: It is the first field name
 * \param field1: It is the first field
 * \param field_name2: It is the second field name
 * \param field2: It is the second field
 */
#define display_2strings_lf(field_name1, field1, field_name2, field2) { \
    display_string(field_name1, field1);                                \
    display_string(field_name2, field2);                                \
    std::cout << std::endl;                                             \
}

/**
 * \def display_gadget_lf(va, gadget)
 * \brief Display a gadget with a line feed and its VA.
 *
 * \param va: It is the gadget VA
 * \param gadget: It is the gadget you want to output
 */
#define display_gadget_lf(va, gadget) {                                                                         \
    enable_color(COLO_RED);                                                                                \
    std::cout << "0x" << std::setw(sizeof(va)) << std::right << std::setfill('0');                              \
    std::cout << std::hex << va;                                                                                \
    disable_color();                                                                                \
    std::cout << ": ";                                                                                \
    enable_color(COLO_GREEN);                                                                                \
    std::cout << (gadget)->first << " (" << std::dec << (gadget)->second->get_nb() << " found)" << std::endl;   \
    disable_color();                                                                                \
}

/**
 * \def display_offset_lf(va, hex_val, size)
 * \brief Display an offset with a line feed and the hex values.
 *
 * \param va: It is the gadget VA
 * \param hex_val: It is the hex values
 * \param size: It is the size of the hex values
 */
#define display_offset_lf(va, hex_val, size) {                                                            \
    enable_color(COLO_RED);                                                                               \
    std::cout << "0x" << std::setw(sizeof(va)) << std::right << std::setfill('0');                        \
    std::cout << std::hex << va;                                                                          \
    disable_color();                                                                                \
    std::cout << ": ";                                                                                \
    enable_color(COLO_GREEN);                                                                             \
    for(unsigned int i = 0, b = 0; i < size; ++i)                                                         \
    {                                                                                \
        b = hex_val[i];                                                                                \
        std::cout << "\\x" << std::setw(2) << std::left << std::setfill('0') << std::hex << b;            \
    }                                                                                \
    std::cout << std::endl;                                                                               \
    disable_color();                                                                                \
}

#endif<commit_msg>coloshell: remove the \brief in the macro comments<commit_after>#ifndef COLOSHELL_HPP
#define COLOSHELL_HPP

#include "platform.h"
#include "rpexception.hpp"
#include <iostream>
#include <iomanip>

#ifdef WINDOWS
#include <windows.h>
#endif

#define COLORS_ENABLED                     // remove this define if you don't want color in your shell

/* Here you will find all you need to display the data in a cute way on a windows/unix terminal */

#ifdef WINDOWS
    enum Colors
    {
        COLO_RED = FOREGROUND_RED | FOREGROUND_INTENSITY,
        COLO_GREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
        COLO_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
        COLO_DEFAULT = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
    };

#else
    enum Colors
    {
        COLO_RED = 0,
        COLO_GREEN = 1,
        COLO_YELLOW = 2,
        COLO_DEFAULT = 3
    };

#endif

/**
 * \fn static void enable_color(const Colors colo)
 * \brief Enable a color in your shell
 *
 * \param colo: the color you want to activate
 */
static void enable_color(const Colors colo)
{
#ifdef COLORS_ENABLED
#ifdef WINDOWS
    HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    if(hStdOutput == INVALID_HANDLE_VALUE)
        RAISE_EXCEPTION("Cannot find a STD_OUTPUT_HANDLE valid value");

    SetConsoleTextAttribute(
        hStdOutput,
        colo
        );
#else
    const char *colors[] = {
        "\x1b[91m", "\x1b[92m",
        "\x1b[93m", "\x1b[0m"
    };
    std::cout << colors[colo];
#endif

#else
#endif
}

/**
 * \fn static void disable_color(const Colors colo)
 * \brief Unset the color you have previously set
 */
static void disable_color(void)
{
#ifdef COLORS_ENABLED
#ifdef WINDOWS
    HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    if(hStdOutput == INVALID_HANDLE_VALUE)
        RAISE_EXCEPTION("Cannot find a STD_OUTPUT_HANDLE valid value");

    SetConsoleTextAttribute(
        hStdOutput,
        COLO_DEFAULT
        );
#else
    const char *colors[] = {
        "\x1b[91m", "\x1b[92m",
        "\x1b[93m", "\x1b[0m"
    };
    std::cout << colors[COLO_DEFAULT];
#endif
#else
#endif
}

/**
 * \fn static void coloshell(const T t, const Colors colo)
 * \brief Display "t" on the stdout with the color "colo"
 *
 * \param t: the thing you want to output
 * \param colo: the color you want to enable
 */
template<class T>
static void coloshell(const T t, const Colors colo)
{
    enable_color(colo);
    std::cout << t;
    disable_color();
}

/**
 * \def w_red(text)
 *  Display text in red on stdout
 *
 * \param text: the text you want to display
 */
#define w_red(text) {          \
    coloshell(text, COLO_RED); \
}

/**
 * \def w_yel(text)
 *  Display text in yellow on stdout
 *
 * \param text: the text you want to display
 */
#define w_yel(text) {              \
    coloshell(text, COLO_YELLOW);  \
}

/**
 * \def w_gre(text)
 *  Display text in green on stdout
 *
 * \param text: the text you want to display
 */
#define w_gre(text) {            \
    coloshell(text, COLO_GREEN); \
}

/**
 * \def w_red_lf(text)
 *  Display text in red on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_red_lf(text) {     \
    w_red(text);             \
    std::cout << std::endl;  \
}

/**
 * \def w_yel_lf(text)
 *  Display text in yellow on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_yel_lf(text) {     \
    w_yel(text);             \
    std::cout << std::endl;  \
}

/**
 * \def w_gre_lf(text)
 *  Display text in green on stdout with a line feed
 *
 * \param text: the text you want to display
 */
#define w_gre_lf(text) {     \
    w_gre_lf(text);          \
    std::cout << std::endl;  \
}

/**
 * \def display_hex_field(field, n)
 *  Display an hex value in red with 0 filling etc.
 *
 * \param field: It is the hex value you want to output
 * \param n: It is the size of the column
 */
#define display_hex_field(field, n) {                                                         \
    std::cout << std::setw(n) << std::left << std::setfill(' ') << " "#field << ": ";         \
    enable_color(COLO_RED);                                                                   \
    std::cout << "0x" << std::setw(sizeof(field) * 2) << std::right << std::setfill('0');     \
    std::cout << std::hex << field;                                                           \
    disable_color();                                                                          \
}

/**
 * \def display_hex_field_lf(field, n)
 *  Display an hex value in red with 0 filling, a line feed and 25b column.
 *
 * \param field: It is the hex value you want to output
 */
#define display_hex_field_lf(field) { \
    display_hex_field(field, 25);     \
    std::cout << std::endl;           \
}

/**
 * \def display_hex_2fields_lf(field1, field2)
 *  Display two hex values in red on a same line.
 *
 * \param field1: It is the first hex value you want to output
 * \param field2: It is the second hex value you want to output
 */
#define display_hex_2fields_lf(field1, field2) { \
    display_hex_field(field1, 25);               \
    display_hex_field(field2, 25);               \
    std::cout << std::endl;                      \
}

/**
 * \def display_short_hex_field(field)
 *  Display a short hex value in red.
 *
 * \param field: It is the short hex value you want to output
 */
#define display_short_hex_field(field) {    \
    display_hex_field(field, 14);           \
}

/**
 * \def display_short_hex_field_lf(field)
 *  Display a short hex value in red with a line feed.
 *
 * \param field: It is the short hex value you want to output
 */
#define display_short_hex_field_lf(field) { \
    display_short_hex_field(field);         \
    std::cout << std::endl;                 \
}

/**
 * \def display_short_hex_2fields_lf(field1, field2)
 *  Display two short hex values in red with a line feed.
 *
 * \param field1: It is the first short hex value you want to output
 * \param field2: It is the second short hex value you want to output
 */
#define display_short_hex_2fields_lf(field1, field2) { \
    display_short_hex_field(field1);                   \
    display_short_hex_field(field2);                   \
    std::cout << std::endl;                            \
}

/**
 * \def display_string(field_name, field)
 *  Display a field with its name.
 *
 * \param field_name: It is the field name
 * \param field: It is the field
 */
#define display_string(field_name, field) {                                      \
    std::cout << std::setw(15) << std::right << std::setfill(' ') << field_name; \
    std::cout << ": " << field;                                                  \
}

/**
 * \def display_string_lf(field_name, field)
 *  Display a field with its name and a line feed.
 *
 * \param field_name: It is the field name
 * \param field: It is the field
 */
#define display_string_lf(field_name, field) { \
    display_string(field_name, field);         \
    std::cout << std::endl;                    \
}

/**
 * \def display_2strings_lf(field_name1, field1, field_name2, field2)
 *  Display two fields with their names and a line feed.
 *
 * \param field_name1: It is the first field name
 * \param field1: It is the first field
 * \param field_name2: It is the second field name
 * \param field2: It is the second field
 */
#define display_2strings_lf(field_name1, field1, field_name2, field2) { \
    display_string(field_name1, field1);                                \
    display_string(field_name2, field2);                                \
    std::cout << std::endl;                                             \
}

/**
 * \def display_gadget_lf(va, gadget)
 *  Display a gadget with a line feed and its VA.
 *
 * \param va: It is the gadget VA
 * \param gadget: It is the gadget you want to output
 */
#define display_gadget_lf(va, gadget) {                                                                         \
    enable_color(COLO_RED);                                                                                \
    std::cout << "0x" << std::setw(sizeof(va)) << std::right << std::setfill('0');                              \
    std::cout << std::hex << va;                                                                                \
    disable_color();                                                                                \
    std::cout << ": ";                                                                                \
    enable_color(COLO_GREEN);                                                                                \
    std::cout << (gadget)->first << " (" << std::dec << (gadget)->second->get_nb() << " found)" << std::endl;   \
    disable_color();                                                                                \
}

/**
 * \def display_offset_lf(va, hex_val, size)
 *  Display an offset with a line feed and the hex values.
 *
 * \param va: It is the gadget VA
 * \param hex_val: It is the hex values
 * \param size: It is the size of the hex values
 */
#define display_offset_lf(va, hex_val, size) {                                                            \
    enable_color(COLO_RED);                                                                               \
    std::cout << "0x" << std::setw(sizeof(va)) << std::right << std::setfill('0');                        \
    std::cout << std::hex << va;                                                                          \
    disable_color();                                                                                \
    std::cout << ": ";                                                                                \
    enable_color(COLO_GREEN);                                                                             \
    for(unsigned int i = 0, b = 0; i < size; ++i)                                                         \
    {                                                                                \
        b = hex_val[i];                                                                                \
        std::cout << "\\x" << std::setw(2) << std::left << std::setfill('0') << std::hex << b;            \
    }                                                                                \
    std::cout << std::endl;                                                                               \
    disable_color();                                                                                \
}

#endif<|endoftext|>