<commit_before>#include <cstdint>

#include <Mapper1.h>

uint8_t Mapper1::readPrg(uint16_t addr) {
    if (addr > 0x8000) {
	int index = decodePrgRomAddress(addr);
	return prg[index];
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	return ram[index];
    }
    else {
	return 0;
    }
}

void Mapper1::writePrg(uint16_t addr, uint8_t value) {
    if (addr > 0x8000) {
	if (value & 0x80) {
	    shiftRegister = 0x10;
	}
	else {
	    if (shiftRegister & 1) {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
		loadRegister(addr, value);
		shiftRegister = 0x10;
	    }
	    else {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
	    }
	}
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	ram[index] = value;
    }
}

uint8_t Mapper1::readChr(uint16_t addr) {
    int index = decodeChrRomAddress(addr);
    return chr[index];
}

void Mapper1::writeChr(uint16_t addr, uint8_t value) {
    if (chrIsRam) {
	int index = addr % chr.size();
        chr[index] = value;
    }
}

void Mapper1::loadRegister(uint16_t addr, uint8_t value) {
    if (addr >= 0xE000) {
	prgRomBank = value & 0b01111;
	prgRamDisable = !!(value & 0b10000);
    }
    else if (addr >= 0xC000) {
	chrRomBank1 = value & 0x1F;
    }
    else if (addr >= 0xA000) {
	chrRomBank0 = value & 0x1F;
    }
    else if (addr >= 0x8000) {
	switch(value & 0b00011) {
	case 0: mirroring = Mirroring::MIRROR_LOWER_BANK; break;
	case 1: mirroring = Mirroring::MIRROR_UPPER_BANK; break;
	case 2: mirroring = Mirroring::MIRROR_VERTICAL;   break;
	case 3: mirroring = Mirroring::MIRROR_HORIZONTAL; break;
	}
	switch(value & 0b01100) {
	case 0:
	case 1: prgMode = PrgMode::PRG_32KB;           break;
	case 2: prgMode = PrgMode::PRG_FIX_FIRST_16KB; break;
	case 3: prgMode = PrgMode::PRG_FIX_LAST_16KB;  break;
	}
	switch(value & 0b10000) {
	case 0: chrMode = ChrMode::CHR_8KB; break;
	case 1: chrMode = ChrMode::CHR_4KB; break;
	}
    }
    updateBankAddresses();
}

void Mapper1::updateBankAddresses() {
    switch (prgMode) {
    case PrgMode::PRG_32KB:
	prg16kBankAddresses[0] = (prgRomBank & 0xFFFE) * 0x4000;
	prg16kBankAddresses[1] = (prgRomBank | 1) * 0x4000;
	break;
    case PrgMode::PRG_FIX_FIRST_16KB:
	prg16kBankAddresses[0] = 0;
	prg16kBankAddresses[1] = prgRomBank * 0x4000;
	break;
    case PrgMode::PRG_FIX_LAST_16KB:
	prg16kBankAddresses[0] = prgRomBank * 0x4000;
	prg16kBankAddresses[1] = prg.size() - 0x4000;
	break;
    }

    switch(chrMode) {
    case ChrMode::CHR_8KB:
	chr4kBankAddresses[0] = (chrRomBank0 & 0xFFFE) * 0x1000;
	chr4kBankAddresses[1] = (chrRomBank0 | 1) * 0x1000;
	break;
    case ChrMode::CHR_4KB:
	chr4kBankAddresses[0] = chrRomBank0 * 0x1000;
	chr4kBankAddresses[1] = chrRomBank1 * 0x1000;
	break;
    }
}

int Mapper1::decodePrgRomAddress(uint16_t addr) {
    return prg16kBankAddresses[addr & 0x4000] + (addr % 0x4000);
}

int Mapper1::decodeChrRomAddress(uint16_t addr) {
    return chr4kBankAddresses[addr & 0x1000] + (addr % 0x1000);
}
<commit_msg>Fix mapper 1 mode switches<commit_after>#include <cstdint>

#include <Mapper1.h>

uint8_t Mapper1::readPrg(uint16_t addr) {
    if (addr > 0x8000) {
	int index = decodePrgRomAddress(addr);
	return prg[index];
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	return ram[index];
    }
    else {
	return 0;
    }
}

void Mapper1::writePrg(uint16_t addr, uint8_t value) {
    if (addr > 0x8000) {
	if (value & 0x80) {
	    shiftRegister = 0x10;
	}
	else {
	    if (shiftRegister & 1) {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
		loadRegister(addr, value);
		shiftRegister = 0x10;
	    }
	    else {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
	    }
	}
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	ram[index] = value;
    }
}

uint8_t Mapper1::readChr(uint16_t addr) {
    int index = decodeChrRomAddress(addr);
    return chr[index];
}

void Mapper1::writeChr(uint16_t addr, uint8_t value) {
    if (chrIsRam) {
	int index = addr % chr.size();
        chr[index] = value;
    }
}

void Mapper1::loadRegister(uint16_t addr, uint8_t value) {
    if (addr >= 0xE000) {
	prgRomBank = value & 0b01111;
	prgRamDisable = !!(value & 0b10000);
    }
    else if (addr >= 0xC000) {
	chrRomBank1 = value & 0x1F;
    }
    else if (addr >= 0xA000) {
	chrRomBank0 = value & 0x1F;
    }
    else if (addr >= 0x8000) {
	switch(value & 0b00011) {
	case 0: mirroring = Mirroring::MIRROR_LOWER_BANK; break;
	case 1: mirroring = Mirroring::MIRROR_UPPER_BANK; break;
	case 2: mirroring = Mirroring::MIRROR_VERTICAL;   break;
	case 3: mirroring = Mirroring::MIRROR_HORIZONTAL; break;
	}
	switch((value & 0b01100) >> 2) {
	case 0:
	case 1: prgMode = PrgMode::PRG_32KB;           break;
	case 2: prgMode = PrgMode::PRG_FIX_FIRST_16KB; break;
	case 3: prgMode = PrgMode::PRG_FIX_LAST_16KB;  break;
	}
	switch((value & 0b10000) >> 4) {
	case 0: chrMode = ChrMode::CHR_8KB; break;
	case 1: chrMode = ChrMode::CHR_4KB; break;
	}
    }
    updateBankAddresses();
}

void Mapper1::updateBankAddresses() {
    switch (prgMode) {
    case PrgMode::PRG_32KB:
	prg16kBankAddresses[0] = (prgRomBank & 0xFFFE) * 0x4000;
	prg16kBankAddresses[1] = (prgRomBank | 1) * 0x4000;
	break;
    case PrgMode::PRG_FIX_FIRST_16KB:
	prg16kBankAddresses[0] = 0;
	prg16kBankAddresses[1] = prgRomBank * 0x4000;
	break;
    case PrgMode::PRG_FIX_LAST_16KB:
	prg16kBankAddresses[0] = prgRomBank * 0x4000;
	prg16kBankAddresses[1] = prg.size() - 0x4000;
	break;
    }

    switch(chrMode) {
    case ChrMode::CHR_8KB:
	chr4kBankAddresses[0] = (chrRomBank0 & 0xFFFE) * 0x1000;
	chr4kBankAddresses[1] = (chrRomBank0 | 1) * 0x1000;
	break;
    case ChrMode::CHR_4KB:
	chr4kBankAddresses[0] = chrRomBank0 * 0x1000;
	chr4kBankAddresses[1] = chrRomBank1 * 0x1000;
	break;
    }
}

int Mapper1::decodePrgRomAddress(uint16_t addr) {
    return prg16kBankAddresses[addr & 0x4000] + (addr % 0x4000);
}

int Mapper1::decodeChrRomAddress(uint16_t addr) {
    return chr4kBankAddresses[addr & 0x1000] + (addr % 0x1000);
}
<|endoftext|>


<commit_before>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
/**
 * \file tensorTool.cpp
 * \brief Tool to view and edit Tensor contents
 *
 * \author Clemens-Alexander Brust (ikosa dot de at gmail dot com)
 */

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

#include <cn24.h>

bool parseCommand ( Conv::Tensor& tensor, std::string filename );
void help();

int main ( int argc, char* argv[] ) {
  if ( argc < 2 ) {
    LOGERROR << "USAGE: " << argv[0] << " <tensor file> <tensor id in file>";
    LOGEND;
    return -1;
  }

  Conv::System::Init();

  // Read tensor id from command line
  std::string s_tid;

  if ( argc < 3 )
    s_tid = argv[2];
  else
    s_tid = "0";

  unsigned int tid = atoi ( s_tid.c_str() );

  // Open tensor stream
  std::ifstream file ( std::string ( argv[1] ), std::ios::in | std::ios::binary );

  // Seek until id is hit
  Conv::Tensor tensor;

  for ( unsigned int t = 0; t < ( tid + 1 ); t++ ) {
    tensor.Deserialize ( file );
  }

  file.close();

  LOGINFO << "Tensor: " << tensor;
  LOGINFO << "Enter \"help\" for information on how to use this program";
  LOGEND;

  bool result;

  do {
    std::cout << "VIS> ";
    result = parseCommand ( tensor, argv[1] );
  } while ( result );

  LOGEND;
  return 0;
}

bool parseCommand ( Conv::Tensor& tensor, std::string filename ) {
  std::string entry;
  std::cin >> entry;

  if ( entry.compare ( "q" ) == 0 || entry.compare ( "quit" ) == 0 )
    return false;

  else if ( entry.compare ( "help" ) ==0 )
    help();

  else if ( entry.compare ( "size" ) == 0 )
    std::cout << tensor << std::endl;

  else if ( entry.compare ( "transpose" ) == 0 )
    tensor.Transpose();

  else if ( entry.compare ( "reshape" ) == 0 ) {
    unsigned int w, h, m, s;
    std::cout << "New width   : ";
    std::cin >> w;
    std::cout << "New height  : ";
    std::cin >> h;
    std::cout << "New maps    : ";
    std::cin >> m;
    std::cout << "New samples : ";
    std::cin >> s;
    std::cout << "Reshaping... ";
    bool result = tensor.Reshape ( s, w, h, m );
    std::cout << result << std::endl;
  }

  else if ( entry.compare ( "extractpatches" ) == 0 ) {
    unsigned int psx, psy, s = 0;
    if(tensor.samples() != 1) {
      std::cout << "Extract patches from sample [0-" << tensor.samples() - 1 << "]: "; std::cin >> s;
    }
    std::cout << "Patch size (x): "; std::cin >> psx;
    std::cout << "Patch size (y): "; std::cin >> psy;
    std::cout << "Extracting...\n";
    Conv::Tensor* target = new Conv::Tensor();
    Conv::Tensor* helper = new Conv::Tensor();
    Conv::Segmentation::ExtractPatches ( psx, psy, *target, *helper, tensor, s );
    tensor.Shadow ( *target );
  }

  else if ( entry.compare ( "write" ) == 0 ) {
    std::ofstream o ( filename, std::ios::out | std::ios::binary );
    tensor.Serialize ( o );
    o.close();
  }

  else if ( entry.compare ( "bin" ) == 0 ) {
    std::ofstream o ( "binoutput.data", std::ios::out | std::ios::binary );

    if ( !o.good() ) {
      std::cout << "Did not work." << std::endl;
      return true;
    }

    tensor.Serialize ( o, true );
    o.close();
  }

#ifdef BUILD_GUI
  else if ( entry.compare ( "show" ) == 0 ) {
    unsigned int s = 0, m = 0;

    if ( tensor.samples() != 1 ) {
      std::cout << "Show sample [0-" << tensor.samples() - 1 << "]: ";
      std::cin >> s;
    }

    if ( tensor.maps() != 1 && tensor.maps() != 3 ) {
      std::cout << "Show map [0-"<< tensor.maps() - 1 << "]: ";
      std::cin >> m;
    }

    Conv::System::viewer->show ( &tensor, filename, false, m, s );
  }

#endif

  else {
    std::cout << "Command not recognized: " << entry << std::endl;
  }

  return true;
}

void help() {
  std::cout << "You can use the following commands:\n";
  std::cout << "  transpose       Transposes every map in every\n"
            << "                  sample (width becomes height)\n"
            << "  bin             Writes the tensors maps to a binary\n"
            << "                  file \"binoutput.data\" using 8 bits per channel\n"
            << "  size            Display the size of the tensor\n"
            << "  reshape         Change the size of the tensor while\n"
            << "                  keeping the number of elements constant\n"
            << "  write		  Writes the tensor back to the file\n"
#ifdef BUILD_GUI
            << "  show            Displays the tensor in a window\n"
#endif
            << "  extractpatches  Extracts patches from the tensor\n"
            << "  help            Displays this information\n"
            << "  q, quit         Quits this program\n"
            << "";

}
<commit_msg>Small tensorTool fix<commit_after>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
/**
 * \file tensorTool.cpp
 * \brief Tool to view and edit Tensor contents
 *
 * \author Clemens-Alexander Brust (ikosa dot de at gmail dot com)
 */

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

#include <cn24.h>

bool parseCommand ( Conv::Tensor& tensor, std::string filename );
void help();

int main ( int argc, char* argv[] ) {
  if ( argc < 2 ) {
    LOGERROR << "USAGE: " << argv[0] << " <tensor stream file> <tensor id in file>";
    LOGEND;
    return -1;
  }

  Conv::System::Init();

  // Read tensor id from command line
  std::string s_tid;

  if ( argc > 2 )
    s_tid = argv[2];
  else
    s_tid = "0";

  unsigned int tid = atoi ( s_tid.c_str() );

  // Open tensor stream
  std::ifstream file ( std::string ( argv[1] ), std::ios::in | std::ios::binary );

  // Seek until id is hit
  Conv::Tensor tensor;

  for ( unsigned int t = 0; t < ( tid + 1 ); t++ ) {
    tensor.Deserialize ( file );
  }

  file.close();

  LOGINFO << "Tensor: " << tensor;
  LOGINFO << "Enter \"help\" for information on how to use this program";
  LOGEND;

  bool result;

  do {
    std::cout << "VIS> ";
    result = parseCommand ( tensor, argv[1] );
  } while ( result );

  LOGEND;
  return 0;
}

bool parseCommand ( Conv::Tensor& tensor, std::string filename ) {
  std::string entry;
  std::cin >> entry;

  if ( entry.compare ( "q" ) == 0 || entry.compare ( "quit" ) == 0 )
    return false;

  else if ( entry.compare ( "help" ) ==0 )
    help();

  else if ( entry.compare ( "size" ) == 0 )
    std::cout << tensor << std::endl;

  else if ( entry.compare ( "transpose" ) == 0 )
    tensor.Transpose();

  else if ( entry.compare ( "reshape" ) == 0 ) {
    unsigned int w, h, m, s;
    std::cout << "New width   : ";
    std::cin >> w;
    std::cout << "New height  : ";
    std::cin >> h;
    std::cout << "New maps    : ";
    std::cin >> m;
    std::cout << "New samples : ";
    std::cin >> s;
    std::cout << "Reshaping... ";
    bool result = tensor.Reshape ( s, w, h, m );
    std::cout << result << std::endl;
  }

  else if ( entry.compare ( "extractpatches" ) == 0 ) {
    unsigned int psx, psy, s = 0;
    if(tensor.samples() != 1) {
      std::cout << "Extract patches from sample [0-" << tensor.samples() - 1 << "]: "; std::cin >> s;
    }
    std::cout << "Patch size (x): "; std::cin >> psx;
    std::cout << "Patch size (y): "; std::cin >> psy;
    std::cout << "Extracting...\n";
    Conv::Tensor* target = new Conv::Tensor();
    Conv::Tensor* helper = new Conv::Tensor();
    Conv::Segmentation::ExtractPatches ( psx, psy, *target, *helper, tensor, s );
    tensor.Shadow ( *target );
  }

  else if ( entry.compare ( "write" ) == 0 ) {
    std::ofstream o ( filename, std::ios::out | std::ios::binary );
    tensor.Serialize ( o );
    o.close();
  }

  else if ( entry.compare ( "bin" ) == 0 ) {
    std::ofstream o ( "binoutput.data", std::ios::out | std::ios::binary );

    if ( !o.good() ) {
      std::cout << "Did not work." << std::endl;
      return true;
    }

    tensor.Serialize ( o, true );
    o.close();
  }

#ifdef BUILD_GUI
  else if ( entry.compare ( "show" ) == 0 ) {
    unsigned int s = 0, m = 0;

    if ( tensor.samples() != 1 ) {
      std::cout << "Show sample [0-" << tensor.samples() - 1 << "]: ";
      std::cin >> s;
    }

    if ( tensor.maps() != 1 && tensor.maps() != 3 ) {
      std::cout << "Show map [0-"<< tensor.maps() - 1 << "]: ";
      std::cin >> m;
    }

    Conv::System::viewer->show ( &tensor, filename, false, m, s );
  }

#endif

  else {
    std::cout << "Command not recognized: " << entry << std::endl;
  }

  return true;
}

void help() {
  std::cout << "You can use the following commands:\n";
  std::cout << "  transpose       Transposes every map in every\n"
            << "                  sample (width becomes height)\n"
            << "  bin             Writes the tensors maps to a binary\n"
            << "                  file \"binoutput.data\" using 8 bits per channel\n"
            << "  size            Display the size of the tensor\n"
            << "  reshape         Change the size of the tensor while\n"
            << "                  keeping the number of elements constant\n"
            << "  write		  Writes the tensor back to the file\n"
#ifdef BUILD_GUI
            << "  show            Displays the tensor in a window\n"
#endif
            << "  extractpatches  Extracts patches from the tensor\n"
            << "  help            Displays this information\n"
            << "  q, quit         Quits this program\n"
            << "";

}
<|endoftext|>


<commit_before>#include "core/assert.hpp"
#include "core/types.hpp"
#include <filesystem>
#include <cstring>
#include <cerrno>
#include <fstream>
#include <string>
#include <string_view>
#include <regex>

std::string std_bytenise(std::string_view binary_data)
{
	std::string res;
	for(std::size_t i = 0; i < binary_data.size(); i++)
	{
		res += std::to_string(static_cast<std::int8_t>(binary_data[i]));
		if(i != binary_data.size() - 1)
		{
			res += ",";
		}
	}
	return res;
}

namespace textc
{
	namespace detail
	{
		using SourceMatchIteratorType = std::vector<std::string>::iterator;
	}
	template<typename F>
	concept SourceReplaceAction = tz::Function<F, std::string, detail::SourceMatchIteratorType, detail::SourceMatchIteratorType>;
	bool transform(std::string& source, std::regex reg, SourceReplaceAction auto transform_function)
	{
		using ReplaceJob = std::pair<std::pair<std::size_t, std::size_t>, std::string>;
		std::vector<ReplaceJob> replacements;

		std::string src_copy = source;
		std::smatch sm;
		std::size_t src_pos_counter = 0;

		bool did_any_work = false;

		while(std::regex_search(src_copy, sm, reg))
		{
			// Found a match!
			std::size_t pos = sm.position() + src_pos_counter;
			tz_assert(pos < source.size(), "Match result has position %zu in source which is out of range. Size: %zu", pos, source.size());
			std::size_t len = sm.length();
			std::vector<std::string> inner_matches;
			for(std::size_t i = 1; i < sm.size(); i++)
				inner_matches.push_back(sm[i]);
			src_copy = sm.suffix();
			src_pos_counter = source.find(src_copy);
			//src_pos_counter += pos + len;
			// get the transformed string.
			std::string replacement = transform_function(inner_matches.begin(), inner_matches.end());
			// register this source replacement.
			ReplaceJob job{{pos, len}, replacement};
			replacements.push_back(job);
		}

		did_any_work = !replacements.empty();

		// Invoke all replacements (in reverse-order)
		for(auto i = replacements.rbegin(); i != replacements.rend(); i++)
		{
			std::string replacement = i->second;
			std::size_t pos = i->first.first;
			std::size_t len = i->first.second;
			source.replace(pos, len, replacement);
		}

		return did_any_work;
	}
}

void headerify(std::string_view filename, std::string& text)
{
	std::string filename_cpy{filename};
	// filename is a full path e.g "root/path_parent/filename.txt"
	// we want to get filename_txt.
	const char* regex_str =  ".*[\\/\\\\]([a-zA-Z_]+)\\.([a-zA-Z]+)";
	textc::transform(filename_cpy, std::regex{regex_str}, [&](auto beg, auto end)->std::string
	{
		std::string part_we_want = *beg;
		std::string extension = *(beg + 1);
		return part_we_want + "_" + extension;
	});
	// If we have multiple file extensions, there will be dots sitting in the variable name. Let's change these all to underscores.
	filename_cpy = std::regex_replace(filename_cpy, std::regex{"\\."}, "_");

	std::size_t byte_count = text.size();
	std::string buffer_array_literal = std_bytenise(text);
	text = std::string("#include <cstdint>\n#include <array>\n/*textc_gen_header*/constexpr std::array<std::int8_t, " + std::to_string(byte_count) + "> " + filename_cpy + "{") + buffer_array_literal + "};";
}

FILE* get_output_stream(int argc, char** argv)
{
	// We're either writing to stdout or a specific file. Return the relevant filestream
	FILE* output = stdout;
	for(std::size_t i = 0; i < argc - 1; i++)
	{
		std::string_view arg{argv[i]};
		std::string_view arg_next{argv[i + 1]};
		if(arg == "-o")
		{
			std::filesystem::path out_path{arg_next.data()};
			std::filesystem::path parent = out_path.parent_path();
			if(!std::filesystem::exists(parent))
			{
				std::filesystem::create_directories(parent);
			}
			output = fopen(arg_next.data(), "w");
			tz_assert(output != nullptr, "Failed to open output stream. Perhaps missing intermediate directory, or no write permissions for this area of the filesystem?\nOutput was %s.\nErrno says: %s", arg_next.data(), std::strerror(errno));
		}
	}
	return output;
}

int main(int argc, char** argv)
{
	tz_assert(argc >= 2, "Not enough arguments (%d). At least 2. Usage: `textc <file-path> [-o <output_file_path>]`", argc);
	const char* txt_filename = argv[1];
	FILE* out = get_output_stream(argc, argv);

	std::ifstream file{txt_filename, std::ios::ate | std::ios::binary};
	tz_assert(file.is_open(), "Cannot open text file %s", txt_filename);

	auto file_size_bytes = static_cast<std::size_t>(file.tellg());
	file.seekg(0);
	std::string buffer;
	buffer.resize(file_size_bytes);
	file.read(buffer.data(), file_size_bytes);
	file.close();

	headerify(txt_filename, buffer);
	for(char c : buffer)
	{
		std::fprintf(out, "%c", c);
	}
	if(out != stdout)
	{
		fclose(out);
	}
}
<commit_msg>* TEXTC: Embedded text files can now have numbers in the filename. Previously this was causing parse errors<commit_after>#include "core/assert.hpp"
#include "core/types.hpp"
#include <filesystem>
#include <cstring>
#include <cerrno>
#include <fstream>
#include <string>
#include <string_view>
#include <regex>

std::string std_bytenise(std::string_view binary_data)
{
	std::string res;
	for(std::size_t i = 0; i < binary_data.size(); i++)
	{
		res += std::to_string(static_cast<std::int8_t>(binary_data[i]));
		if(i != binary_data.size() - 1)
		{
			res += ",";
		}
	}
	return res;
}

namespace textc
{
	namespace detail
	{
		using SourceMatchIteratorType = std::vector<std::string>::iterator;
	}
	template<typename F>
	concept SourceReplaceAction = tz::Function<F, std::string, detail::SourceMatchIteratorType, detail::SourceMatchIteratorType>;
	bool transform(std::string& source, std::regex reg, SourceReplaceAction auto transform_function)
	{
		using ReplaceJob = std::pair<std::pair<std::size_t, std::size_t>, std::string>;
		std::vector<ReplaceJob> replacements;

		std::string src_copy = source;
		std::smatch sm;
		std::size_t src_pos_counter = 0;

		bool did_any_work = false;

		while(std::regex_search(src_copy, sm, reg))
		{
			// Found a match!
			std::size_t pos = sm.position() + src_pos_counter;
			tz_assert(pos < source.size(), "Match result has position %zu in source which is out of range. Size: %zu", pos, source.size());
			std::size_t len = sm.length();
			std::vector<std::string> inner_matches;
			for(std::size_t i = 1; i < sm.size(); i++)
				inner_matches.push_back(sm[i]);
			src_copy = sm.suffix();
			src_pos_counter = source.find(src_copy);
			//src_pos_counter += pos + len;
			// get the transformed string.
			std::string replacement = transform_function(inner_matches.begin(), inner_matches.end());
			// register this source replacement.
			ReplaceJob job{{pos, len}, replacement};
			replacements.push_back(job);
		}

		did_any_work = !replacements.empty();

		// Invoke all replacements (in reverse-order)
		for(auto i = replacements.rbegin(); i != replacements.rend(); i++)
		{
			std::string replacement = i->second;
			std::size_t pos = i->first.first;
			std::size_t len = i->first.second;
			source.replace(pos, len, replacement);
		}

		return did_any_work;
	}
}

void headerify(std::string_view filename, std::string& text)
{
	std::string filename_cpy{filename};
	// filename is a full path e.g "root/path_parent/filename.txt"
	// we want to get filename_txt.
	const char* regex_str =  ".*[\\/\\\\]([a-zA-Z_0-9]+)\\.([a-zA-Z]+)";
	textc::transform(filename_cpy, std::regex{regex_str}, [&](auto beg, auto end)->std::string
	{
		std::string part_we_want = *beg;
		std::string extension = *(beg + 1);
		return part_we_want + "_" + extension;
	});
	// If we have multiple file extensions, there will be dots sitting in the variable name. Let's change these all to underscores.
	filename_cpy = std::regex_replace(filename_cpy, std::regex{"\\."}, "_");

	std::size_t byte_count = text.size();
	std::string buffer_array_literal = std_bytenise(text);
	text = std::string("#include <cstdint>\n#include <array>\n/*textc_gen_header*/constexpr std::array<std::int8_t, " + std::to_string(byte_count) + "> " + filename_cpy + "{") + buffer_array_literal + "};";
}

FILE* get_output_stream(int argc, char** argv)
{
	// We're either writing to stdout or a specific file. Return the relevant filestream
	FILE* output = stdout;
	for(std::size_t i = 0; i < argc - 1; i++)
	{
		std::string_view arg{argv[i]};
		std::string_view arg_next{argv[i + 1]};
		if(arg == "-o")
		{
			std::filesystem::path out_path{arg_next.data()};
			std::filesystem::path parent = out_path.parent_path();
			if(!std::filesystem::exists(parent))
			{
				std::filesystem::create_directories(parent);
			}
			output = fopen(arg_next.data(), "w");
			tz_assert(output != nullptr, "Failed to open output stream. Perhaps missing intermediate directory, or no write permissions for this area of the filesystem?\nOutput was %s.\nErrno says: %s", arg_next.data(), std::strerror(errno));
		}
	}
	return output;
}

int main(int argc, char** argv)
{
	tz_assert(argc >= 2, "Not enough arguments (%d). At least 2. Usage: `textc <file-path> [-o <output_file_path>]`", argc);
	const char* txt_filename = argv[1];
	FILE* out = get_output_stream(argc, argv);

	std::ifstream file{txt_filename, std::ios::ate | std::ios::binary};
	tz_assert(file.is_open(), "Cannot open text file %s", txt_filename);

	auto file_size_bytes = static_cast<std::size_t>(file.tellg());
	file.seekg(0);
	std::string buffer;
	buffer.resize(file_size_bytes);
	file.read(buffer.data(), file_size_bytes);
	file.close();

	headerify(txt_filename, buffer);
	for(char c : buffer)
	{
		std::fprintf(out, "%c", c);
	}
	if(out != stdout)
	{
		fclose(out);
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
long long f(long long c,long long d){
	if(c<(2*d)) return 4*d;
	else return 4*(c-d);
}
long long mx(long c,long d){
	return 4*(c+d);
}
int main(int argc, char const *argv[]) {
	int t;
	cin>>t;
	while(t--){
		long long int c,d,l;
		cin>>c>>d>>l;
		if(l%4!=0){cout<<"no\n";continue;}
		if(l>=f(c,d) && l<=mx(c,d)) cout<<"yes\n";
		else cout<<"no\n";
	}
	 return 0;
}
<commit_msg>adding<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
long long f(long long c,long long d){
	if(c<(2*d)) return 4*d;
	else return 4*(c-d);
}
long long mx(long c,long d){
	return 4*(c+d);
}
int main(int argc, char const *argv[]) {
	int t;
	cin>>t;
	while(t--){
		long long c,d,l;
		cin>>c>>d>>l;
		if(l%4!=0){cout<<"no\n";continue;}
		if(l>=f(c,d) && l<=mx(c,d)) cout<<"yes\n";
		else cout<<"no\n";
	}
	 return 0;
}
<|endoftext|>


<commit_before><?hh //strict

/**
 * This file is part of hhpack/migrate.
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace HHPack\Migrate;

use HHPack\Migrate\Event\{ EventPublisher };
use HHPack\Migrate\Migration\{ MigrationManager, MigrationLoader, MigrationLogger, MigrationResult, MigrationNotFoundException };
use HHPack\Migrate\Database\{ Connection };

final class Migrator implements Migratable
{

    private MigratorAgent $agent;
    private MigrationManager $manager;
    private EventPublisher $publisher;

    public function __construct(
        private MigrationLoader $loader,
        Connection $connection,
        Logger $logger
    )
    {
        $this->publisher = new EventPublisher([
            new MigrationLogger($logger)
        ]);
        $this->manager = new MigrationManager($connection);
        $this->agent = new MigratorAgent($connection, $this->publisher);
    }

    public async function upgrade(?MigrationName $name = null): Awaitable<MigrationResult>
    {
        $migrations = $this->loader->loadUpgradeMigrations();

        await $this->manager->setUp();
        $diffMigrations = await $this->manager->diff($migrations);
        $takeHandler = $migration ==> true;

        if ($name !== null) {
            $takeHandler = $migration ==> $migration->name() === $name;
        }

        $upgradeMigrations = $diffMigrations->takeWhile($takeHandler);

        await $this->publisher->migrationLoaded($upgradeMigrations);

        return await $this->upgradeScheme($upgradeMigrations);
    }

    public async function downgrade(?MigrationName $name = null): Awaitable<MigrationResult>
    {
        $appliedMigrations = await $this->manager->loadMigrations();
        $downgradeMigrations = $this->loader->loadDowngradeMigrations($appliedMigrations);

        $migrations = $downgradeMigrations;

        if (!is_null($name)) {
            $orderedMigrations = ($order, $migration) ==> Pair { $migration->name(), $order };
            $registry = ImmMap::fromItems($downgradeMigrations->mapWithKey($orderedMigrations));

            if (!$registry->containsKey($name)) {
                throw new MigrationNotFoundException("Migration $name is not found");
            }

            $orderIndex = $registry->at($name);
            $migrations = $downgradeMigrations->slice(0, $orderIndex + 1);
        }

        await $this->publisher->migrationLoaded($migrations);

        return await $this->downgradeScheme($migrations);
    }

    private async function downgradeScheme(ImmVector<Migration> $migrations): Awaitable<MigrationResult>
    {
        $results = Map {};

        foreach ($migrations->items() as $migration) {
            $changeResults = await $migration->change($this->agent);
            await $this->manager->remove($migration);
            $results->set($migration->name(), $changeResults);
        }

        return new MigrationResult( $results->toImmMap() );
    }

    private async function upgradeScheme(ImmVector<Migration> $migrations): Awaitable<MigrationResult>
    {
        $results = Map {};

        foreach ($migrations->items() as $migration) {
            $changeResults = await $migration->change($this->agent);
            await $this->manager->save($migration);
            $results->set($migration->name(), $changeResults);
        }

        return new MigrationResult( $results->toImmMap() );
    }

}
<commit_msg>fix Scheme to Schema<commit_after><?hh //strict

/**
 * This file is part of hhpack/migrate.
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace HHPack\Migrate;

use HHPack\Migrate\Event\{ EventPublisher };
use HHPack\Migrate\Migration\{ MigrationManager, MigrationLoader, MigrationLogger, MigrationResult, MigrationNotFoundException };
use HHPack\Migrate\Database\{ Connection };

final class Migrator implements Migratable
{

    private MigratorAgent $agent;
    private MigrationManager $manager;
    private EventPublisher $publisher;

    public function __construct(
        private MigrationLoader $loader,
        Connection $connection,
        Logger $logger
    )
    {
        $this->publisher = new EventPublisher([
            new MigrationLogger($logger)
        ]);
        $this->manager = new MigrationManager($connection);
        $this->agent = new MigratorAgent($connection, $this->publisher);
    }

    public async function upgrade(?MigrationName $name = null): Awaitable<MigrationResult>
    {
        $migrations = $this->loader->loadUpgradeMigrations();

        await $this->manager->setUp();
        $diffMigrations = await $this->manager->diff($migrations);
        $takeHandler = $migration ==> true;

        if ($name !== null) {
            $takeHandler = $migration ==> $migration->name() === $name;
        }

        $upgradeMigrations = $diffMigrations->takeWhile($takeHandler);

        await $this->publisher->migrationLoaded($upgradeMigrations);

        return await $this->upgradeSchema($upgradeMigrations);
    }

    public async function downgrade(?MigrationName $name = null): Awaitable<MigrationResult>
    {
        $appliedMigrations = await $this->manager->loadMigrations();
        $downgradeMigrations = $this->loader->loadDowngradeMigrations($appliedMigrations);

        $migrations = $downgradeMigrations;

        if (!is_null($name)) {
            $orderedMigrations = ($order, $migration) ==> Pair { $migration->name(), $order };
            $registry = ImmMap::fromItems($downgradeMigrations->mapWithKey($orderedMigrations));

            if (!$registry->containsKey($name)) {
                throw new MigrationNotFoundException("Migration $name is not found");
            }

            $orderIndex = $registry->at($name);
            $migrations = $downgradeMigrations->slice(0, $orderIndex + 1);
        }

        await $this->publisher->migrationLoaded($migrations);

        return await $this->downgradeSchema($migrations);
    }

    private async function downgradeSchema(ImmVector<Migration> $migrations): Awaitable<MigrationResult>
    {
        $results = Map {};

        foreach ($migrations->items() as $migration) {
            $changeResults = await $migration->change($this->agent);
            await $this->manager->remove($migration);
            $results->set($migration->name(), $changeResults);
        }

        return new MigrationResult( $results->toImmMap() );
    }

    private async function upgradeSchema(ImmVector<Migration> $migrations): Awaitable<MigrationResult>
    {
        $results = Map {};

        foreach ($migrations->items() as $migration) {
            $changeResults = await $migration->change($this->agent);
            await $this->manager->save($migration);
            $results->set($migration->name(), $changeResults);
        }

        return new MigrationResult( $results->toImmMap() );
    }

}
<|endoftext|>


<commit_before>//-----------------------------------------------------//
//                                                     //
//                                                     //
//  Date   : August 05 2003                            //
//                                                     //
//  Store recpoints for ALICE-PMD                      //
//                                                     //
//-----------------------------------------------------//

#include "AliPMDrecpoint.h"
#include <stdio.h>

ClassImp(AliPMDrecpoint)

AliPMDrecpoint::AliPMDrecpoint()
{
  for (Int_t i = 0; i < 7; i++)
    {
      fClusData[i] = 0.;
    }
}

AliPMDrecpoint::AliPMDrecpoint(Float_t *clusdata)
{
  for (Int_t i = 0; i < 7; i++)
    {
      fClusData[i] = clusdata[i];
    }
}
AliPMDrecpoint::~AliPMDrecpoint()
{

}

Float_t AliPMDrecpoint::GetDetector() const
{
  return fClusData[0];
}
Float_t AliPMDrecpoint::GetSMNumber() const
{
  return fClusData[1];
}
Float_t AliPMDrecpoint::GetClusX() const
{
  return fClusData[2];
}

Float_t AliPMDrecpoint::GetClusY() const
{
  return fClusData[3];
}

Float_t AliPMDrecpoint::GetClusADC() const
{
  return fClusData[4];
}
Float_t AliPMDrecpoint::GetClusCells() const
{
  return fClusData[5];
}
Float_t AliPMDrecpoint::GetClusRadius() const
{
  return fClusData[6];
}

<commit_msg>Fixing problem with previous checkin...<commit_after>//-----------------------------------------------------//
//                                                     //
//                                                     //
//  Date   : August 05 2003                            //
//                                                     //
//  Store recpoints for ALICE-PMD                      //
//                                                     //
//-----------------------------------------------------//

#include "AliPMDrecpoint1.h"
#include <stdio.h>

ClassImp(AliPMDrecpoint)

AliPMDrecpoint::AliPMDrecpoint()
{
  for (Int_t i = 0; i < 7; i++)
    {
      fClusData[i] = 0.;
    }
}

AliPMDrecpoint::AliPMDrecpoint(Float_t *clusdata)
{
  for (Int_t i = 0; i < 7; i++)
    {
      fClusData[i] = clusdata[i];
    }
}
AliPMDrecpoint::~AliPMDrecpoint()
{

}

Float_t AliPMDrecpoint::GetDetector() const
{
  return fClusData[0];
}
Float_t AliPMDrecpoint::GetSMNumber() const
{
  return fClusData[1];
}
Float_t AliPMDrecpoint::GetClusX() const
{
  return fClusData[2];
}

Float_t AliPMDrecpoint::GetClusY() const
{
  return fClusData[3];
}

Float_t AliPMDrecpoint::GetClusADC() const
{
  return fClusData[4];
}
Float_t AliPMDrecpoint::GetClusCells() const
{
  return fClusData[5];
}
Float_t AliPMDrecpoint::GetClusRadius() const
{
  return fClusData[6];
}

<|endoftext|>


<commit_before>#include "Grid.h"

#include <cassert>
#include "Tile.h"

Grid::Grid(const Grid& other)
{

}

int Grid::getWidth()
{
    return -1;
}

int Grid::getHeight()
{
    return -1;
}

void Grid::expandGrid()
{
#ifdef DEBUG
    //check the grid is rectangular and not jagged
    //i.e. all sublists are the same size
    //note that the number of sublists does not have to be equal to the number of columns
    for(std::list<bool>& thisSubList : tiles)
    {
        for(std::list<bool>& otherSubList : tiles)
        {
            assert(thisSubList.size() == otherSubList.size());
        }
    }
#endif
    //add 1 tile to the beginning of each sublist (prepending a column)
    for(std::list<bool>& thisSubList : tiles)
    {
        thisSubList.push_front(TILE_DEAD);
    }

    //add 1 tile to the end of each sublist (appending a column)
    //

    //add 1 row to the beginning of the tiles list (prepending a row)

    //add 1 row to the end of the tiles list (appending a column)

#ifdef DEBUG
    //check the size is correct

#endif
}

bool Grid::touchingEdges()
{
    //TODO: IMPLEMENT
    return true;
}
<commit_msg>implemented row expansion<commit_after>#include "Grid.h"

#include <cassert>
#include "Tile.h"

Grid::Grid(const Grid& other)
{

}

int Grid::getWidth()
{
    return -1;
}

int Grid::getHeight()
{
    return -1;
}

void Grid::expandGrid()
{
#ifdef DEBUG
    //check the grid is rectangular and not jagged
    //i.e. all sublists are the same size
    //note that the number of sublists does not have to be equal to the number of columns
    for(std::list<bool>& thisSubList : tiles)
    {
        for(std::list<bool>& otherSubList : tiles)
        {
            assert(thisSubList.size() == otherSubList.size());
        }
    }
#endif
    //add 1 tile to the beginning of each sublist (prepending a column)
    //add 1 tile to the end of each sublist (appending a column)
    for(std::list<bool>& thisSubList : tiles)
    {
        thisSubList.push_front(TILE_DEAD);
        thisSubList.push_back(TILE_DEAD);
    }

    //add 1 row to the beginning of the tiles list (prepending a row)
    //add 1 row to the end of the tiles list (appending a column)

#ifdef DEBUG
    //check the size is correct

#endif
}

bool Grid::touchingEdges()
{
    //TODO: IMPLEMENT
    return true;
}
<|endoftext|>


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

#include "org_apache_harmony_drlvm_VMHelperFastPath.h"

#include "Class.h"
#include "vtable.h"
#include "open/vm.h"
#include <assert.h>

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getObjectVtableOffset(JNIEnv *e, jclass c)
{
    return object_get_vtable_offset();
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableIntfTypeOffset(JNIEnv *e, jclass c, jint i)
{
#if defined  (_EM64T_) || defined (_IPF_)
    assert(0);
    return 0;
#else
    assert(i>=0 && i<=2);
    if (i==0) return (jint)&((VTable*)0)->intfc_class_0;
    if (i==1) return (jint)&((VTable*)0)->intfc_class_1;
    return (jint)&((VTable*)0)->intfc_class_2;
#endif
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableIntfTableOffset(JNIEnv *e, jclass c, jint i)
{
#if defined  (_EM64T_) || defined (_IPF_)
    assert(0);
    return 0;
#else

    assert(i>=0 && i<=2);
    if (i==0) return (jint)&((VTable*)0)->intfc_table_0;
    if (i==1) return (jint)&((VTable*)0)->intfc_table_1;
    return (jint)&((VTable*)0)->intfc_table_2;
    return 0;
#endif
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableClassOffset(JNIEnv *e, jclass c)
{
    return (jint)&((VTable*)0)->clss;
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableSuperclassesOffset(JNIEnv *e, jclass c)
{
    return (jint)&((VTable*)0)->superclasses;
}

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

#include "org_apache_harmony_drlvm_VMHelperFastPath.h"

#include "Class.h"
#include "vtable.h"
#include "open/vm.h"
#include <assert.h>

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getObjectVtableOffset(JNIEnv *e, jclass c)
{
    return object_get_vtable_offset();
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableIntfTypeOffset(JNIEnv *e, jclass c, jint i)
{
#if defined  (_EM64T_) || defined (_IPF_)
    assert(0);
    return 0;
#else
    assert(i>=0 && i<=2);
    if (i==0) return (jint)&((VTable*)0)->intfc_class_0;
    if (i==1) return (jint)&((VTable*)0)->intfc_class_1;
    return (jint)&((VTable*)0)->intfc_class_2;
#endif
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableIntfTableOffset(JNIEnv *e, jclass c, jint i)
{
#if defined  (_EM64T_) || defined (_IPF_)
    assert(0);
    return 0;
#else

    assert(i>=0 && i<=2);
    if (i==0) return (jint)&((VTable*)0)->intfc_table_0;
    if (i==1) return (jint)&((VTable*)0)->intfc_table_1;
    return (jint)&((VTable*)0)->intfc_table_2;
    return 0;
#endif
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableClassOffset(JNIEnv *e, jclass c)
{
    return static_cast<jint>(reinterpret_cast<jlong>(&((VTable*)0)->clss));
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getVtableSuperclassesOffset(JNIEnv *e, jclass c)
{
    return static_cast<jint>(reinterpret_cast<jlong>(&((VTable*)0)->superclasses));
}

JNIEXPORT jint JNICALL Java_org_apache_harmony_drlvm_VMHelperFastPath_getClassDepthOffset(JNIEnv *, jclass)
{
    return Class::get_offset_of_depth();
}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <cmath>
#include <tclap/CmdLine.h>

#include "capability_map/CapabilityOcTree.h"

bool getMarkerFromCapIterator(visualization_msgs::Marker* marker, const CapabilityOcTree::leaf_iterator &it)
{
    // nothing to do, return false
    if (it->getCapability().getType() == EMPTY)
    {
        return false;
    }

    bool retVal;

    double size = it.getSize();

    // phi and theta in rad for sin, cos computation
    double phiInRad = it->getCapability().getPhi() * M_PI / 180.0;
    double thetaInRad = it->getCapability().getTheta() * M_PI / 180.0;

    double halfOpeningAngle = it->getCapability().getHalfOpeningAngle();

    // cone needs special treatment if halfOpeningAngle is greater than 90.0°
    if (it->getCapability().getType() == CONE && it->getCapability().getHalfOpeningAngle() > 90.0)
    {
        phiInRad = M_PI + phiInRad;
        if (phiInRad > 2.0 * M_PI)
        {
            phiInRad -= 2.0 * M_PI;
        }
        thetaInRad = M_PI - thetaInRad;
        halfOpeningAngle = 180.0 - halfOpeningAngle;
    }

    // for setting correct scale of capability shapes
    double tanHalfOpeningAngle;

    // be sure tan(halfOpeningAngle) doesn't get too high and does not reach infinity
    if (halfOpeningAngle > 89.5)
    {
        // cylinders can't have a halfOpeningAngle >= 90° (90° means it is a sphere). Cones can't be displayed with >= 90°.
        // setting halfOpeningAngle to 89.5° is accurate enough without getting too large marker shapes.
        tanHalfOpeningAngle = tan(89.5 * M_PI / 180.0);
    }
    else
    {
        tanHalfOpeningAngle = tan(halfOpeningAngle * M_PI / 180.0);
    }
    double scalingFactor = tanHalfOpeningAngle > 1.0 ? 1.0 / tanHalfOpeningAngle : 1.0;

    // start and end points of arrow (used by cone)
    geometry_msgs::Point start, end;

    switch (it->getCapability().getType())
    {
        case SPHERE:
            marker->type = visualization_msgs::Marker::SPHERE;

            marker->pose.position.x = it.getX();
            marker->pose.position.y = it.getY();
            marker->pose.position.z = it.getZ();

            marker->scale.x = size;
            marker->scale.y = size;
            marker->scale.z = size;

            retVal = true;
            break;

        case CONE:
            // TODO: cones with halfOpeningAngle > 90° can't be displayed (for now those are clamped to ~ 89.5°)
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (size / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (size / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (size / 2.0) * cos(thetaInRad);

            end.x = it.getX();
            end.y = it.getY();
            end.z = it.getZ();

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = 0.0;
            marker->scale.y = tanHalfOpeningAngle * size * scalingFactor;
            marker->scale.z = size * scalingFactor / 2.0;

            retVal = true;
            break;

        case CYLINDER_1:
            // as marker type for cylinder_1 a arrow without head is used, which is faster than computing a quaternion
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (size * scalingFactor / 2.0) * cos(thetaInRad);

            end.x = it.getX() + (size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            end.y = it.getY() + (size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            end.z = it.getZ() + (size * scalingFactor / 2.0) * cos(thetaInRad);

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = tanHalfOpeningAngle * size * scalingFactor;
            marker->scale.y = 0.0;
            marker->scale.z = 0.001;

            retVal = true;
            break;

        case CYLINDER_2:
            // as marker type for cylinder_2 a arrow without head is used, which is faster than computing a quaternion
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * cos(thetaInRad);

            end.x = it.getX() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            end.y = it.getY() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            end.z = it.getZ() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * cos(thetaInRad);

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = size * scalingFactor;
            marker->scale.y = 0.0;
            marker->scale.z = 0.001;

            retVal = true;
            break;

        default:
            retVal = false;
    }

    // set color according to shape fit error
    marker->color.r = it->getCapability().getShapeFitError() / 100.0;
    marker->color.g = 0.5 - it->getCapability().getShapeFitError() / 200.0;
    marker->color.b = 1.0 - it->getCapability().getShapeFitError() / 100.0;
    marker->color.a = 1.0;

    return retVal;
}

int main(int argc, char** argv )
{
    ros::init(argc, argv, "capability_shapes");

    // arguments
    TCLAP::CmdLine cmd("Visualizes the capability map given by argument", ' ', "1.0");

    TCLAP::ValueArg<std::string> pathNameArg("p", "path", "Path and filename of the capability map to be visualized.\n\
                                             Example: -p mydir/mysubdir/filename.cpm", true, "./capability_map.cpm", "string");
    TCLAP::ValueArg<std::string> frameArg("f", "frame", "Frame to which the capability map belongs.\n\
                                             Example for the PR2: -f /torso_lift_link", true, "/torso_lift_link", "string");

    cmd.add(pathNameArg);
    cmd.add(frameArg);

    // parse arguments with TCLAP
    try
    {
        cmd.parse(argc, argv);
    }
    catch (TCLAP::ArgException &e)  // catch any exceptions
    {
        ROS_ERROR("Error: %s for argument %s", e.error().c_str(), e.argId().c_str());
        ros::shutdown();
        exit(1);
    }

    std::string pathName = pathNameArg.getValue();
    std::string frame = frameArg.getValue();

    // create a dummy CapabilityOcTree to ensure CapabilityOcTree is in classIDMappping
    CapabilityOcTree dummy(0.1);
    CapabilityOcTree* visTree = dynamic_cast<CapabilityOcTree*>(AbstractOcTree::read(pathName));

    ros::NodeHandle n;
    ros::Rate r(1);

    ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("capability_marker", 1);

    // TODO: remove tree when done debugging
    /*CapabilityOcTree tree(0.1);

    Capability emptyCap;
    Capability cap1(SPHERE, 0.0, 0.0, 0.0);
    Capability cap2(CONE, 0.0, 90.0, 10.0);
    Capability cap3(CONE, 90.0, 0.0, 45.0);
    Capability cap4(CONE, 40.0, 20.0, 100.0);
    Capability cap5(CONE, 180.0, 120.0, 70.0);
    Capability cap6(CYLINDER_1, 0.0, 0.0, 10.0);
    Capability cap7(CYLINDER_1, 0.0, 0.0, 90.0);
    Capability cap8(CYLINDER_1, 40.0, 50.0, 45.0);
    Capability cap9(CYLINDER_2, 0.0, 0.0, 10.0);
    Capability cap10(CYLINDER_2, 0.0, 0.0, 45.0);
    Capability cap11(CYLINDER_2, 90.0, 90.0, 89.0);

    tree.setNodeCapability(0.0, 0.0, 1.0, emptyCap);
    tree.setNodeCapability(0.2, 0.0, 1.0, cap1);
    tree.setNodeCapability(0.4, 0.0, 1.0, cap2);
    tree.setNodeCapability(0.6, 0.0, 1.0, cap3);
    tree.setNodeCapability(0.8, 0.0, 1.0, cap4);
    tree.setNodeCapability(1.0, 0.0, 1.0, cap5);
    tree.setNodeCapability(1.2, 0.0, 1.0, cap6);
    tree.setNodeCapability(1.4, 0.0, 1.0, cap7);
    tree.setNodeCapability(1.6, 0.0, 1.0, cap8);
    tree.setNodeCapability(1.8, 0.0, 1.0, cap9);
    tree.setNodeCapability(2.0, 0.0, 1.0, cap10);
    tree.setNodeCapability(2.2, 0.0, 1.0, cap11);*/

    while (ros::ok())
    {
        unsigned int count = 0;
        /*for(CapabilityOcTree::leaf_iterator it = tree.begin_leafs(), end = tree.end_leafs(); it != end; ++it)
        {
            visualization_msgs::Marker marker;

            marker.header.frame_id = "/l_shoulder_pan_link";
            marker.header.stamp = ros::Time::now();

            marker.ns = "capability_shapes";
            marker.id = count++;

            marker.action = visualization_msgs::Marker::ADD;
            marker.lifetime = ros::Duration();

            if (!getMarkerFromCapIterator(&marker, it))
            {
                continue;
            }
            // Publish the marker
            marker_pub.publish(marker);

            // draw a cube around the capability marker to see the volume
            visualization_msgs::Marker cubeMarker;

            cubeMarker.header.frame_id = "/base_link";
            cubeMarker.header.stamp = ros::Time::now();

            cubeMarker.ns = "capability_shapes";
            cubeMarker.id = count++;

            cubeMarker.action = visualization_msgs::Marker::ADD;
            cubeMarker.lifetime = ros::Duration();

            cubeMarker.type = visualization_msgs::Marker::CUBE;

            cubeMarker.color.r = 1.0;
            cubeMarker.color.g = 1.0;
            cubeMarker.color.b = 1.0;
            cubeMarker.color.a = 0.2;

            cubeMarker.pose.position.x = it.getX();
            cubeMarker.pose.position.y = it.getY();
            cubeMarker.pose.position.z = it.getZ();

            cubeMarker.scale.x = it.getSize();
            cubeMarker.scale.y = it.getSize();
            cubeMarker.scale.z = it.getSize();

            // Publish the marker
            marker_pub.publish(cubeMarker);
        }*/
        for(CapabilityOcTree::leaf_iterator it = visTree->begin_leafs(), end = visTree->end_leafs(); it != end; ++it)
        {
            visualization_msgs::Marker marker;

            marker.header.frame_id = frame;
            marker.header.stamp = ros::Time::now();

            marker.ns = "capability_shapes";
            marker.id = count++;

            marker.action = visualization_msgs::Marker::ADD;
            marker.lifetime = ros::Duration();

            if (!getMarkerFromCapIterator(&marker, it))
            {
                continue;
            }
            // Publish the marker
            marker_pub.publish(marker);

            if (it->getCapability().getType() == CONE && it->getCapability().getHalfOpeningAngle() > 90.0)
            {
                marker.id = count++;

                marker.type = visualization_msgs::Marker::SPHERE;

                marker.pose.position.x = it.getX();
                marker.pose.position.y = it.getY();
                marker.pose.position.z = it.getZ();

                marker.scale.x = it.getSize();
                marker.scale.y = it.getSize();
                marker.scale.z = it.getSize();

                marker.color.a = 0.5;

                marker_pub.publish(marker);
            }
        }

      r.sleep();
    }
    delete visTree;
}

<commit_msg>publish marker array instead of single markers<commit_after>#include <ros/ros.h>
#include <visualization_msgs/MarkerArray.h>
#include <cmath>
#include <tclap/CmdLine.h>

#include "capability_map/CapabilityOcTree.h"

bool getMarkerFromCapIterator(visualization_msgs::Marker* marker, const CapabilityOcTree::leaf_iterator &it)
{
    // nothing to do, return false
    if (it->getCapability().getType() == EMPTY)
    {
        return false;
    }

    bool retVal;

    double size = it.getSize();

    // phi and theta in rad for sin, cos computation
    double phiInRad = it->getCapability().getPhi() * M_PI / 180.0;
    double thetaInRad = it->getCapability().getTheta() * M_PI / 180.0;

    double halfOpeningAngle = it->getCapability().getHalfOpeningAngle();

    // cone needs special treatment if halfOpeningAngle is greater than 90.0°
    if (it->getCapability().getType() == CONE && it->getCapability().getHalfOpeningAngle() > 90.0)
    {
        phiInRad = M_PI + phiInRad;
        if (phiInRad > 2.0 * M_PI)
        {
            phiInRad -= 2.0 * M_PI;
        }
        thetaInRad = M_PI - thetaInRad;
        halfOpeningAngle = 180.0 - halfOpeningAngle;
    }

    // for setting correct scale of capability shapes
    double tanHalfOpeningAngle;

    // be sure tan(halfOpeningAngle) doesn't get too high and does not reach infinity
    if (halfOpeningAngle > 89.5)
    {
        // cylinders can't have a halfOpeningAngle >= 90° (90° means it is a sphere). Cones can't be displayed with >= 90°.
        // setting halfOpeningAngle to 89.5° is accurate enough without getting too large marker shapes.
        tanHalfOpeningAngle = tan(89.5 * M_PI / 180.0);
    }
    else
    {
        tanHalfOpeningAngle = tan(halfOpeningAngle * M_PI / 180.0);
    }
    double scalingFactor = tanHalfOpeningAngle > 1.0 ? 1.0 / tanHalfOpeningAngle : 1.0;

    // start and end points of arrow (used by cone)
    geometry_msgs::Point start, end;

    switch (it->getCapability().getType())
    {
        case SPHERE:
            marker->type = visualization_msgs::Marker::SPHERE;

            marker->pose.position.x = it.getX();
            marker->pose.position.y = it.getY();
            marker->pose.position.z = it.getZ();

            marker->scale.x = size;
            marker->scale.y = size;
            marker->scale.z = size;

            retVal = true;
            break;

        case CONE:
            // TODO: cones with halfOpeningAngle > 90° can't be displayed (for now those are clamped to ~ 89.5°)
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (size / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (size / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (size / 2.0) * cos(thetaInRad);

            end.x = it.getX();
            end.y = it.getY();
            end.z = it.getZ();

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = 0.0;
            marker->scale.y = tanHalfOpeningAngle * size * scalingFactor;
            marker->scale.z = size * scalingFactor / 2.0;

            retVal = true;
            break;

        case CYLINDER_1:
            // as marker type for cylinder_1 a arrow without head is used, which is faster than computing a quaternion
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (size * scalingFactor / 2.0) * cos(thetaInRad);

            end.x = it.getX() + (size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            end.y = it.getY() + (size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            end.z = it.getZ() + (size * scalingFactor / 2.0) * cos(thetaInRad);

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = tanHalfOpeningAngle * size * scalingFactor;
            marker->scale.y = 0.0;
            marker->scale.z = 0.001;

            retVal = true;
            break;

        case CYLINDER_2:
            // as marker type for cylinder_2 a arrow without head is used, which is faster than computing a quaternion
            marker->type = visualization_msgs::Marker::ARROW;

            start.x = it.getX() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            start.y = it.getY() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            start.z = it.getZ() - (tanHalfOpeningAngle * size * scalingFactor / 2.0) * cos(thetaInRad);

            end.x = it.getX() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * cos(phiInRad);
            end.y = it.getY() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * sin(thetaInRad) * sin(phiInRad);
            end.z = it.getZ() + (tanHalfOpeningAngle * size * scalingFactor / 2.0) * cos(thetaInRad);

            marker->points.push_back(start);
            marker->points.push_back(end);

            marker->scale.x = size * scalingFactor;
            marker->scale.y = 0.0;
            marker->scale.z = 0.001;

            retVal = true;
            break;

        default:
            retVal = false;
    }

    // set color according to shape fit error
    marker->color.r = it->getCapability().getShapeFitError() / 100.0;
    marker->color.g = 0.5 - it->getCapability().getShapeFitError() / 200.0;
    marker->color.b = 1.0 - it->getCapability().getShapeFitError() / 100.0;
    marker->color.a = 1.0;

    return retVal;
}

int main(int argc, char** argv )
{
    ros::init(argc, argv, "capability_shapes");

    // arguments
    TCLAP::CmdLine cmd("Visualizes the capability map given by argument", ' ', "1.0");

    TCLAP::ValueArg<std::string> pathNameArg("p", "path", "Path and filename of the capability map to be visualized.\n\
                                             Example: -p mydir/mysubdir/filename.cpm", true, "./capability_map.cpm", "string");
    TCLAP::ValueArg<std::string> frameArg("f", "frame", "Frame to which the capability map belongs.\n\
                                             Example for the PR2: -f /torso_lift_link", true, "/torso_lift_link", "string");

    cmd.add(pathNameArg);
    cmd.add(frameArg);

    // parse arguments with TCLAP
    try
    {
        cmd.parse(argc, argv);
    }
    catch (TCLAP::ArgException &e)  // catch any exceptions
    {
        ROS_ERROR("Error: %s for argument %s", e.error().c_str(), e.argId().c_str());
        ros::shutdown();
        exit(1);
    }

    std::string pathName = pathNameArg.getValue();
    std::string frame = frameArg.getValue();

    // create a dummy CapabilityOcTree to ensure CapabilityOcTree is in classIDMappping
    CapabilityOcTree dummy(0.1);
    CapabilityOcTree* visTree = dynamic_cast<CapabilityOcTree*>(AbstractOcTree::read(pathName));

    ros::NodeHandle n;
    ros::Rate r(0.1);

    ros::Publisher marker_pub = n.advertise<visualization_msgs::MarkerArray>("capability_marker", 1, true);

    // TODO: remove tree when done debugging
    /*CapabilityOcTree tree(0.1);

    Capability emptyCap;
    Capability cap1(SPHERE, 0.0, 0.0, 0.0);
    Capability cap2(CONE, 0.0, 90.0, 10.0);
    Capability cap3(CONE, 90.0, 0.0, 45.0);
    Capability cap4(CONE, 40.0, 20.0, 100.0);
    Capability cap5(CONE, 180.0, 120.0, 70.0);
    Capability cap6(CYLINDER_1, 0.0, 0.0, 10.0);
    Capability cap7(CYLINDER_1, 0.0, 0.0, 90.0);
    Capability cap8(CYLINDER_1, 40.0, 50.0, 45.0);
    Capability cap9(CYLINDER_2, 0.0, 0.0, 10.0);
    Capability cap10(CYLINDER_2, 0.0, 0.0, 45.0);
    Capability cap11(CYLINDER_2, 90.0, 90.0, 89.0);

    tree.setNodeCapability(0.0, 0.0, 1.0, emptyCap);
    tree.setNodeCapability(0.2, 0.0, 1.0, cap1);
    tree.setNodeCapability(0.4, 0.0, 1.0, cap2);
    tree.setNodeCapability(0.6, 0.0, 1.0, cap3);
    tree.setNodeCapability(0.8, 0.0, 1.0, cap4);
    tree.setNodeCapability(1.0, 0.0, 1.0, cap5);
    tree.setNodeCapability(1.2, 0.0, 1.0, cap6);
    tree.setNodeCapability(1.4, 0.0, 1.0, cap7);
    tree.setNodeCapability(1.6, 0.0, 1.0, cap8);
    tree.setNodeCapability(1.8, 0.0, 1.0, cap9);
    tree.setNodeCapability(2.0, 0.0, 1.0, cap10);
    tree.setNodeCapability(2.2, 0.0, 1.0, cap11);*/

    while (ros::ok())
    {
        unsigned int count = 0;
        /*for(CapabilityOcTree::leaf_iterator it = tree.begin_leafs(), end = tree.end_leafs(); it != end; ++it)
        {
            visualization_msgs::Marker marker;

            marker.header.frame_id = "/l_shoulder_pan_link";
            marker.header.stamp = ros::Time::now();

            marker.ns = "capability_shapes";
            marker.id = count++;

            marker.action = visualization_msgs::Marker::ADD;
            marker.lifetime = ros::Duration();

            if (!getMarkerFromCapIterator(&marker, it))
            {
                continue;
            }
            // Publish the marker
            marker_pub.publish(marker);

            // draw a cube around the capability marker to see the volume
            visualization_msgs::Marker cubeMarker;

            cubeMarker.header.frame_id = "/base_link";
            cubeMarker.header.stamp = ros::Time::now();

            cubeMarker.ns = "capability_shapes";
            cubeMarker.id = count++;

            cubeMarker.action = visualization_msgs::Marker::ADD;
            cubeMarker.lifetime = ros::Duration();

            cubeMarker.type = visualization_msgs::Marker::CUBE;

            cubeMarker.color.r = 1.0;
            cubeMarker.color.g = 1.0;
            cubeMarker.color.b = 1.0;
            cubeMarker.color.a = 0.2;

            cubeMarker.pose.position.x = it.getX();
            cubeMarker.pose.position.y = it.getY();
            cubeMarker.pose.position.z = it.getZ();

            cubeMarker.scale.x = it.getSize();
            cubeMarker.scale.y = it.getSize();
            cubeMarker.scale.z = it.getSize();

            // Publish the marker
            marker_pub.publish(cubeMarker);
        }*/
        visualization_msgs::MarkerArray markerArray;
        for(CapabilityOcTree::leaf_iterator it = visTree->begin_leafs(), end = visTree->end_leafs(); it != end; ++it)
        {
            visualization_msgs::Marker marker;

            marker.header.frame_id = frame;
            marker.header.stamp = ros::Time(0);

            marker.ns = "capability_shapes";
            marker.id = count++;

            marker.action = visualization_msgs::Marker::ADD;
            marker.lifetime = ros::Duration();

            if (!getMarkerFromCapIterator(&marker, it))
            {
                continue;
            }
            markerArray.markers.push_back(marker);

            if (it->getCapability().getType() == CONE && it->getCapability().getHalfOpeningAngle() > 90.0)
            {
                marker.id = count++;

                marker.type = visualization_msgs::Marker::SPHERE;

                marker.pose.position.x = it.getX();
                marker.pose.position.y = it.getY();
                marker.pose.position.z = it.getZ();

                marker.scale.x = it.getSize();
                marker.scale.y = it.getSize();
                marker.scale.z = it.getSize();

                marker.color.a = 0.5;

                markerArray.markers.push_back(marker);
            }
        }
        // Publish the marker
        marker_pub.publish(markerArray);

      r.sleep();
    }
    delete visTree;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Martin Preisler <martin@preisler.me>
 *
 * This file is part of oclcrypto.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "oclcrypto/Program.h"
#include "oclcrypto/CLError.h"
#include "oclcrypto/Device.h"
#include "oclcrypto/Kernel.h"

#include <algorithm>

namespace oclcrypto
{

Program::Program(Device& device, const std::string& source):
    mDevice(device),
    mSource(source)
{
    {
        const char* src = source.c_str();
        const size_t length = source.length();

        cl_int err;
        mCLProgram = clCreateProgramWithSource(
            device.getCLContext(), 1,
            (const char** const)&src, &length,
            &err
        );

        CLErrorGuard(err);
    }

    const cl_device_id deviceId = device.getCLDeviceID();
    const cl_int err = clBuildProgram(mCLProgram, 1, &deviceId, nullptr, nullptr, nullptr);

    if (err != CL_SUCCESS)
    {
        size_t size;
        clGetProgramBuildInfo(mCLProgram, deviceId, CL_PROGRAM_BUILD_LOG, 0, nullptr, &size);
        std::unique_ptr<char[]> buf(new char[size + 1]);
        clGetProgramBuildInfo(mCLProgram, deviceId, CL_PROGRAM_BUILD_LOG, size, buf.get(), nullptr);

        // OpenCL should append \0 but it never hurts to safe-guard ourselves
        buf[size] = '\0';

        CLProgramCompilationErrorThrow(err, std::string(buf.get()));
    }
}

Program::~Program()
{
    for (KernelVector::const_iterator it = mKernels.begin();
         it != mKernels.end(); ++it)
    {
        delete *it;
    }

    mKernels.clear();

    clReleaseProgram(mCLProgram);
}

Device& Program::getDevice() const
{
    return mDevice;
}

const std::string& Program::getSource() const
{
    return mSource;
}

Kernel& Program::createKernel(const std::string& name)
{
    Kernel* ret = new Kernel(*this, name);
    mKernels.push_back(ret);
    return *ret;
}

void Program::destroyKernel(Kernel& kernel)
{
    KernelVector::iterator it = std::find(mKernels.begin(), mKernels.end(), &kernel);

    if (it == mKernels.end())
        throw std::invalid_argument("Given kernel has already been destroyed or doesn't belong in this Program.");

    mKernels.erase(it);
    delete &kernel;
}

size_t Program::getKernelCount() const
{
    return mKernels.size();
}

cl_program Program::getCLProgram() const
{
    return mCLProgram;
}

ScopedProgram::ScopedProgram(Program& program):
    mProgram(program)
{}

ScopedProgram::~ScopedProgram()
{
    mProgram.getDevice().destroyProgram(mProgram);
}

}
<commit_msg>Compile with strict-aliasing<commit_after>/*
 * Copyright (C) 2014 Martin Preisler <martin@preisler.me>
 *
 * This file is part of oclcrypto.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "oclcrypto/Program.h"
#include "oclcrypto/CLError.h"
#include "oclcrypto/Device.h"
#include "oclcrypto/Kernel.h"

#include <algorithm>

namespace oclcrypto
{

Program::Program(Device& device, const std::string& source):
    mDevice(device),
    mSource(source)
{
    {
        const char* src = source.c_str();
        const size_t length = source.length();

        cl_int err;
        mCLProgram = clCreateProgramWithSource(
            device.getCLContext(), 1,
            (const char** const)&src, &length,
            &err
        );

        CLErrorGuard(err);
    }

    const cl_device_id deviceId = device.getCLDeviceID();
    const char* options = "-cl-strict-aliasing";
    const cl_int err = clBuildProgram(mCLProgram, 1, &deviceId, options, nullptr, nullptr);

    if (err != CL_SUCCESS)
    {
        size_t size;
        clGetProgramBuildInfo(mCLProgram, deviceId, CL_PROGRAM_BUILD_LOG, 0, nullptr, &size);
        std::unique_ptr<char[]> buf(new char[size + 1]);
        clGetProgramBuildInfo(mCLProgram, deviceId, CL_PROGRAM_BUILD_LOG, size, buf.get(), nullptr);

        // OpenCL should append \0 but it never hurts to safe-guard ourselves
        buf[size] = '\0';

        CLProgramCompilationErrorThrow(err, std::string(buf.get()));
    }
}

Program::~Program()
{
    for (KernelVector::const_iterator it = mKernels.begin();
         it != mKernels.end(); ++it)
    {
        delete *it;
    }

    mKernels.clear();

    clReleaseProgram(mCLProgram);
}

Device& Program::getDevice() const
{
    return mDevice;
}

const std::string& Program::getSource() const
{
    return mSource;
}

Kernel& Program::createKernel(const std::string& name)
{
    Kernel* ret = new Kernel(*this, name);
    mKernels.push_back(ret);
    return *ret;
}

void Program::destroyKernel(Kernel& kernel)
{
    KernelVector::iterator it = std::find(mKernels.begin(), mKernels.end(), &kernel);

    if (it == mKernels.end())
        throw std::invalid_argument("Given kernel has already been destroyed or doesn't belong in this Program.");

    mKernels.erase(it);
    delete &kernel;
}

size_t Program::getKernelCount() const
{
    return mKernels.size();
}

cl_program Program::getCLProgram() const
{
    return mCLProgram;
}

ScopedProgram::ScopedProgram(Program& program):
    mProgram(program)
{}

ScopedProgram::~ScopedProgram()
{
    mProgram.getDevice().destroyProgram(mProgram);
}

}
<|endoftext|>


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

#include "Json.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

Variant Json::parse(std::string &string)
{
    std::stringstream ss;
    ss << string;
    bool error = false;
    Variant v = parseValue(ss, error);

    if(error)
        return Variant();

    return v;

}

std::string Json::stringify(Variant &v)
{
    std::ostringstream str;

    if(v.isNull()) {
        str << "null";
        return str.str();
    }

    Variant::VariantType type = v.type();

    if(type == Variant::VARIANT_BOOL) {
        str << (v.toBool() ? "true" : "false");
        return str.str();
    }
    else if(type == Variant::VARIANT_INT) {
        str << v.toInt();
        return str.str();
    }
    else if(type == Variant::VARIANT_DOUBLE) {
        str << v.toDouble();
        return str.str();
    }
    else if(type == Variant::VARIANT_STRING) {
        str << "\"";
        str << v.toString();
         str << "\"";
        return str.str();
    }
    else if(type == Variant::VARIANT_MAP) {
        str << "{";

        VariantMap m = v.toVariantMap();
        typedef VariantMap::iterator it_type;
        for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
            // iterator->first = key
            // iterator->second = value
            // Repeat if you also want to iterate through the second map.

            str << "\"";
            str << iterator->first;
            str << "\":";
            str << stringify(iterator->second);
            str << ",";

        }
        std::string json = str.str();
        if(json.length() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "}";

        return str2.str();
    }
    else if(type == Variant::VARIANT_LIST) {
        str << "[";
        VariantList l = v.toList();

        for(VariantList::iterator it = l.begin(); it != l.end(); ++it)
        {
            str << stringify(*it);
        }

        std::string json = str.str();
        if(json.length() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "]";

        return str2.str();
    }
    else if(type == Variant::VARIANT_STRINGLIST) {
        str << "[";
        StringList l = v.toStringList();

        for(StringList::iterator it = l.begin(); it != l.end(); ++it)
        {
            str << "\"";
            str << *it;
            str << "\"";
        }

        std::string json = str.str();
        if(json.length() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "]";

        return str2.str();
    }

    return std::string();
}

Variant Json::parseValue(std::stringstream &s, bool &error)
{
    char c;

    while(!s.eof() && !error) {
        s >> std::hex >> c;

        if(c == '{') {
            return parseObject(s, error);
        }
        else if(c == '"') {
            return parseString(s, error);
        }
        else if(c == '[') {
            return parseArray(s, error);
        }
        else {
            return parseLiteral(s, error);
        }
    }

    return Variant();
}

VariantMap Json::parseObject(std::stringstream &s, bool &error)
{
    VariantMap o;
    std::string key;
    bool atVal=false;

    char c;
    while(!s.eof() &&!error) {
        s >> std::hex >> c;

        if(c == '}') {
            return o;
        }
        else if(c== ',' || c== ':') {
            //nothing to do
        }
        else if (c=='"') {
            if(atVal) {
                Variant v = Variant(parseString(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            } else {
                key = parseString(s, error);
                atVal = true;
            }
        }
        else if (c=='[') {
            if(atVal) {
                Variant v = Variant(parseArray(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }

        }
        else if (c=='{') {
            if(atVal) {
                Variant v = Variant(parseObject(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }
        }
        else {
            if(atVal) {
                s.putback(c);
                Variant v = Variant(parseLiteral(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }

        }
    }

    error = true;
    return VariantMap();
}

std::string Json::parseString(std::stringstream &ss, bool &error)
{
    std::ostringstream str;
    char c;

    while(!ss.eof() && !error) {
        ss >> std::hex >> c;

        if(c == '"') {
            return str.str();
        }
        else if(c == '\\') {
            ss >> std::hex >> c;
            if(c=='b') {
                str << '\b';
            } else if(c=='f') {
                str << '\f';
            } else if(c=='n') {
                str << '\n';
            } else if(c=='r') {
                str << '\r';
            } else if(c=='t') {
                str << '\t';
            } else if(c=='u') {
                char buf[4];
                ss.read(buf, 4);
                str << strtoul(buf, NULL, 16);

            } else {
                str << c;
            }
        } else {
            str << c;
        }
    }
    error = true;
    return std::string();
}

VariantList Json::parseArray(std::stringstream &ss, bool &error)
{
    VariantList l;
    char c;

    while(!ss.eof() && !error) {
        ss >> std::hex >> c;
        if (c==']') {
            return l;
        } else if (c==',') {
        } else if (c=='"') {
            Variant v = Variant(parseString(ss, error));
            l.push_back(v);
        } else if (c=='[') {
            Variant v = Variant(parseArray(ss, error));
            l.push_back(v);
        } else if (c=='{') {
            Variant v = Variant(parseObject(ss, error));
            l.push_back(v);
        } else {
            Variant v = Variant(parseLiteral(ss, error));
            l.push_back(v);
        }
    }

    error = true;
    return VariantList();
}

Variant Json::parseLiteral(std::stringstream &s, bool &error)
{

    char c;
    while(!s.eof() && !error) {
        s >> std::hex >> c;
        if (c=='t') {
            s >> std::hex >> c;//r
            s >> std::hex >> c;//u
            s >> std::hex >> c;//e
            Variant v = Variant(true);
            return v;
        } else if (c=='f') {
            s >> std::hex >> c;//a
            s >> std::hex >> c;//l
            s >> std::hex >> c;//s
            s >> std::hex >> c;//e
            Variant v = Variant(false);
            return v;
        } else if (c=='n') {
            s >> std::hex >> c;//u
            s >> std::hex >> c;//l
            s >> std::hex >> c;//l
            return Variant();
        }
        else if (c == '-' || isdigit(c)) {
             std::ostringstream str;

            while((isdigit(c) || (c == '.') || (c == 'E') || (c == 'e') || (c == '-') || (c == '+'))) {
                str << c;
                if(s.eof() || error) {
                    break;
                }
                s >> std::hex >> c;
            }
            s.putback(c);
            std::string val = str.str();
            if(val.find('.') != std::string::npos) {
                Variant v = Variant(atof(val.c_str()));
                return v;
            }
            else {
                Variant v = Variant(atoi(val.c_str()));
                return v;
            }
        }
    }

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

#include "Json.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

Variant Json::parse(std::string &string)
{
    std::stringstream ss;
    ss << string;
    bool error = false;
    Variant v = parseValue(ss, error);

    if(error)
        return Variant();

    return v;

}

std::string Json::stringify(Variant &v)
{
    std::ostringstream str;

    if(v.isNull()) {
        str << "null";
        return str.str();
    }

    Variant::VariantType type = v.type();

    if(type == Variant::VARIANT_BOOL) {
        str << (v.toBool() ? "true" : "false");
        return str.str();
    }
    else if(type == Variant::VARIANT_INT) {
        str << v.toInt();
        return str.str();
    }
    else if(type == Variant::VARIANT_DOUBLE) {
        str << v.toDouble();
        return str.str();
    }
    else if(type == Variant::VARIANT_STRING) {
        str << "\"";
        str << v.toString();
         str << "\"";
        return str.str();
    }
    else if(type == Variant::VARIANT_MAP) {
        str << "{";

        VariantMap m = v.toVariantMap();
        typedef VariantMap::iterator it_type;
        for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
            // iterator->first = key
            // iterator->second = value
            // Repeat if you also want to iterate through the second map.

            str << "\"";
            str << iterator->first;
            str << "\":";
            str << stringify(iterator->second);
            str << ",";

        }
        std::string json = str.str();
        if(json.length() > 1 && m.size() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "}";

        return str2.str();
    }
    else if(type == Variant::VARIANT_LIST) {
        str << "[";
        VariantList l = v.toList();

        for(VariantList::iterator it = l.begin(); it != l.end(); ++it)
        {
            str << stringify(*it);
        }

        std::string json = str.str();
        if(json.length() > 1 && l.size() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "]";

        return str2.str();
    }
    else if(type == Variant::VARIANT_STRINGLIST) {
        str << "[";
        StringList l = v.toStringList();

        for(StringList::iterator it = l.begin(); it != l.end(); ++it)
        {
            str << "\"";
            str << *it;
            str << "\"";
        }

        std::string json = str.str();
        if(json.length() > 1 && l.size() > 1) {
            json = json.substr(0, json.size()-1);
        }
        std::ostringstream str2;
        str2 << json;
        str2 << "]";

        return str2.str();
    }

    return std::string();
}

Variant Json::parseValue(std::stringstream &s, bool &error)
{
    char c;

    while(!s.eof() && !error) {
        s >> std::hex >> c;

        if(c == '{') {
            return parseObject(s, error);
        }
        else if(c == '"') {
            return parseString(s, error);
        }
        else if(c == '[') {
            return parseArray(s, error);
        }
        else {
            return parseLiteral(s, error);
        }
    }

    return Variant();
}

VariantMap Json::parseObject(std::stringstream &s, bool &error)
{
    VariantMap o;
    std::string key;
    bool atVal=false;

    char c;
    while(!s.eof() &&!error) {
        s >> std::hex >> c;

        if(c == '}') {
            return o;
        }
        else if(c== ',' || c== ':') {
            //nothing to do
        }
        else if (c=='"') {
            if(atVal) {
                Variant v = Variant(parseString(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            } else {
                key = parseString(s, error);
                atVal = true;
            }
        }
        else if (c=='[') {
            if(atVal) {
                Variant v = Variant(parseArray(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }

        }
        else if (c=='{') {
            if(atVal) {
                Variant v = Variant(parseObject(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }
        }
        else {
            if(atVal) {
                s.putback(c);
                Variant v = Variant(parseLiteral(s, error));
                o.insert(std::pair<std::string, Variant>(key, v));
                atVal = false;
            }
            else {
                error = true;
                return VariantMap();
            }

        }
    }

    error = true;
    return VariantMap();
}

std::string Json::parseString(std::stringstream &ss, bool &error)
{
    std::ostringstream str;
    char c;

    while(!ss.eof() && !error) {
        ss >> std::hex >> c;

        if(c == '"') {
            return str.str();
        }
        else if(c == '\\') {
            ss >> std::hex >> c;
            if(c=='b') {
                str << '\b';
            } else if(c=='f') {
                str << '\f';
            } else if(c=='n') {
                str << '\n';
            } else if(c=='r') {
                str << '\r';
            } else if(c=='t') {
                str << '\t';
            } else if(c=='u') {
                char buf[4];
                ss.read(buf, 4);
                str << strtoul(buf, NULL, 16);

            } else {
                str << c;
            }
        } else {
            str << c;
        }
    }
    error = true;
    return std::string();
}

VariantList Json::parseArray(std::stringstream &ss, bool &error)
{
    VariantList l;
    char c;

    while(!ss.eof() && !error) {
        ss >> std::hex >> c;
        if (c==']') {
            return l;
        } else if (c==',') {
        } else if (c=='"') {
            Variant v = Variant(parseString(ss, error));
            l.push_back(v);
        } else if (c=='[') {
            Variant v = Variant(parseArray(ss, error));
            l.push_back(v);
        } else if (c=='{') {
            Variant v = Variant(parseObject(ss, error));
            l.push_back(v);
        } else {
            Variant v = Variant(parseLiteral(ss, error));
            l.push_back(v);
        }
    }

    error = true;
    return VariantList();
}

Variant Json::parseLiteral(std::stringstream &s, bool &error)
{

    char c;
    while(!s.eof() && !error) {
        s >> std::hex >> c;
        if (c=='t') {
            s >> std::hex >> c;//r
            s >> std::hex >> c;//u
            s >> std::hex >> c;//e
            Variant v = Variant(true);
            return v;
        } else if (c=='f') {
            s >> std::hex >> c;//a
            s >> std::hex >> c;//l
            s >> std::hex >> c;//s
            s >> std::hex >> c;//e
            Variant v = Variant(false);
            return v;
        } else if (c=='n') {
            s >> std::hex >> c;//u
            s >> std::hex >> c;//l
            s >> std::hex >> c;//l
            return Variant();
        }
        else if (c == '-' || isdigit(c)) {
             std::ostringstream str;

            while((isdigit(c) || (c == '.') || (c == 'E') || (c == 'e') || (c == '-') || (c == '+'))) {
                str << c;
                if(s.eof() || error) {
                    break;
                }
                s >> std::hex >> c;
            }
            s.putback(c);
            std::string val = str.str();
            if(val.find('.') != std::string::npos) {
                Variant v = Variant(atof(val.c_str()));
                return v;
            }
            else {
                Variant v = Variant(atoi(val.c_str()));
                return v;
            }
        }
    }

    error = true;
    return Variant();
}
<|endoftext|>