<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Full-stack compiler that converts a source code string to bytecode.
 */

#include <libsolidity/AST.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/GlobalContext.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/CompilerStack.h>

#include <jsonrpc/json/json.h>

using namespace std;

namespace dev
{
namespace solidity
{

void CompilerStack::setSource(string const& _sourceCode)
{
	reset();
	m_scanner = make_shared<Scanner>(CharStream(_sourceCode));
}

void CompilerStack::parse()
{
	if (!m_scanner)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
	m_contractASTNode = Parser().parse(m_scanner);
	m_globalContext = make_shared<GlobalContext>();
	m_globalContext->setCurrentContract(*m_contractASTNode);
	NameAndTypeResolver(m_globalContext->getDeclarations()).resolveNamesAndTypes(*m_contractASTNode);
	m_parseSuccessful = true;
}

void CompilerStack::parse(string const& _sourceCode)
{
	setSource(_sourceCode);
	parse();
}

bytes const& CompilerStack::compile(bool _optimize)
{
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
	m_bytecode.clear();
	m_compiler = make_shared<Compiler>();
	m_compiler->compileContract(*m_contractASTNode, m_globalContext->getMagicVariables());
	return m_bytecode = m_compiler->getAssembledBytecode(_optimize);
}

bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
{
	parse(_sourceCode);
	return compile(_optimize);
}

void CompilerStack::streamAssembly(ostream& _outStream)
{
	if (!m_compiler || m_bytecode.empty())
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
	m_compiler->streamAssembly(_outStream);
}

string const& CompilerStack::getInterface()
{
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
	if (m_interface.empty())
	{
		stringstream interface;
		interface << '[';
		vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
		unsigned functionsCount = exportedFunctions.size();
		for (FunctionDefinition const* f: exportedFunctions)
		{
			auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars)
			{
				unsigned varCount = _vars.size();
				for (ASTPointer<VariableDeclaration> const& var: _vars)
				{
					interface << "{"
							  << "\"name\":" << escaped(var->getName(), false) << ","
							  << "\"type\":" << escaped(var->getType()->toString(), false)
							  << "}";
					if (--varCount > 0)
						interface << ",";
				}
			};

			interface << '{'
					  << "\"name\":" << escaped(f->getName(), false) << ","
					  << "\"inputs\":[";
			streamVariables(f->getParameters());
			interface << "],"
					  << "\"outputs\":[";
			streamVariables(f->getReturnParameters());
			interface << "]"
					  << "}";
			if (--functionsCount > 0)
				interface << ",";
		}
		interface << ']';
		m_interface = interface.str();
	}
	return m_interface;
}

string const& CompilerStack::getDocumentation()
{

	Json::StyledWriter writer;
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
	if (m_documentation.empty())
	{
		Json::Value doc;
		Json::Value methods;

		vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
		for (FunctionDefinition const* f: exportedFunctions)
		{
			Json::Value user;
			user["user"] = Json::Value(*f->getDocumentation());
			methods[f->getName()] = user;
		}
		doc["methods"] = methods;
		m_documentation = writer.write(doc);
	}
	return m_documentation;
}

bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
{
	CompilerStack stack;
	return stack.compile(_sourceCode, _optimize);
}

}
}
<commit_msg>Using jsoncpp for exporting ABI interface from solidity<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Full-stack compiler that converts a source code string to bytecode.
 */

#include <libsolidity/AST.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/GlobalContext.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/CompilerStack.h>

#include <jsonrpc/json/json.h>

using namespace std;

namespace dev
{
namespace solidity
{

void CompilerStack::setSource(string const& _sourceCode)
{
	reset();
	m_scanner = make_shared<Scanner>(CharStream(_sourceCode));
}

void CompilerStack::parse()
{
	if (!m_scanner)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
	m_contractASTNode = Parser().parse(m_scanner);
	m_globalContext = make_shared<GlobalContext>();
	m_globalContext->setCurrentContract(*m_contractASTNode);
	NameAndTypeResolver(m_globalContext->getDeclarations()).resolveNamesAndTypes(*m_contractASTNode);
	m_parseSuccessful = true;
}

void CompilerStack::parse(string const& _sourceCode)
{
	setSource(_sourceCode);
	parse();
}

bytes const& CompilerStack::compile(bool _optimize)
{
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
	m_bytecode.clear();
	m_compiler = make_shared<Compiler>();
	m_compiler->compileContract(*m_contractASTNode, m_globalContext->getMagicVariables());
	return m_bytecode = m_compiler->getAssembledBytecode(_optimize);
}

bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
{
	parse(_sourceCode);
	return compile(_optimize);
}

void CompilerStack::streamAssembly(ostream& _outStream)
{
	if (!m_compiler || m_bytecode.empty())
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
	m_compiler->streamAssembly(_outStream);
}

string const& CompilerStack::getInterface()
{
	Json::StyledWriter writer;
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));

	if (m_interface.empty())
	{
		Json::Value methods(Json::arrayValue);

		vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
		for (FunctionDefinition const* f: exportedFunctions)
		{
			Json::Value method;
			Json::Value inputs(Json::arrayValue);
			Json::Value outputs(Json::arrayValue);

			auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars,
									   Json::Value &json)
			{
				for (ASTPointer<VariableDeclaration> const& var: _vars)
				{
					Json::Value input;
					input["name"] = var->getName();
					input["type"] = var->getType()->toString();
					json.append(input);
				}
			};

			method["name"] = f->getName();
			streamVariables(f->getParameters(), inputs);
			method["inputs"] = inputs;
			streamVariables(f->getReturnParameters(), outputs);
			method["outputs"] = outputs;

			methods.append(method);
		}
		m_interface = writer.write(methods);
	}
	return m_interface;
}

string const& CompilerStack::getDocumentation()
{
	Json::StyledWriter writer;
	if (!m_parseSuccessful)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));

	if (m_documentation.empty())
	{
		Json::Value doc;
		Json::Value methods;

		vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions();
		for (FunctionDefinition const* f: exportedFunctions)
		{
			Json::Value user;
			user["user"] = Json::Value(*f->getDocumentation());
			methods[f->getName()] = user;
		}
		doc["methods"] = methods;
		m_documentation = writer.write(doc);
	}
	return m_documentation;
}

bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
{
	CompilerStack stack;
	return stack.compile(_sourceCode, _optimize);
}

}
}
<|endoftext|>


<commit_before>//
//  AmstradCPC.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 30/07/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../../Storage/Disk/Parsers/CPM.hpp"
#include "../../Storage/Disk/Encodings/MFM.hpp"

static bool strcmp_insensitive(const char *a, const char *b) {
	if(strlen(a) != strlen(b)) return false;
	while(*a) {
		if(tolower(*a) != towlower(*b)) return false;
		a++;
		b++;
	}
	return true;
}

static std::string RunCommandFor(const Storage::Disk::CPM::File &file) {
	return "run\"" + file.name + "\n";
}

static void InspectDataCatalogue(
	const Storage::Disk::CPM::Catalogue &catalogue,
	StaticAnalyser::Target &target) {
	// Make a copy of all files and filter out any that are marked as system.
	std::vector<Storage::Disk::CPM::File> candidate_files = catalogue.files;
	candidate_files.erase(
		std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) {
			return file.system;
		}),
		candidate_files.end());

	// If there's just one file, run that.
	if(candidate_files.size() == 1) {
		target.loadingCommand = RunCommandFor(candidate_files[0]);
		return;
	}

	// If only one file is [potentially] BASIC, run that one; otherwise if only one has a suffix
	// that AMSDOS allows to be omitted, pick that one.
	int basic_files = 0;
	int implicit_suffixed_files = 0;

	size_t last_basic_file = 0;
	size_t last_implicit_suffixed_file = 0;

	for(size_t c = 0; c < candidate_files.size(); c++) {
		// Files with nothing but spaces in their name can't be loaded by the user, so disregard them.
		if(candidate_files[c].type == "   " && candidate_files[c].name == "        ")
			continue;

		// Check for whether this is [potentially] BASIC.
		if(candidate_files[c].data.size() >= 128 && !((candidate_files[c].data[18] >> 1) & 7)) {
			basic_files++;
			last_basic_file = c;
		}

		// Check suffix for emptiness.
		if(
			candidate_files[c].type == "   " ||
			strcmp_insensitive(candidate_files[c].type.c_str(), "BAS") ||
			strcmp_insensitive(candidate_files[c].type.c_str(), "BIN")
		) {
			implicit_suffixed_files++;
			last_implicit_suffixed_file = c;
		}
	}
	if(basic_files == 1 || implicit_suffixed_files == 1) {
		size_t selected_file = (basic_files == 1) ? last_basic_file : last_implicit_suffixed_file;
		target.loadingCommand = RunCommandFor(candidate_files[selected_file]);
		return;
	}

	// Desperation.
	target.loadingCommand = "cat\n";
}

static void InspectSystemCatalogue(
	const std::shared_ptr<Storage::Disk::Disk> &disk,
	const Storage::Disk::CPM::Catalogue &catalogue,
	StaticAnalyser::Target &target) {
	Storage::Encodings::MFM::Parser parser(true, disk);

	// Check that the boot sector exists and looks like it had content written to it.
	std::shared_ptr<Storage::Encodings::MFM::Sector> boot_sector = parser.get_sector(0, 0, 0x41);
	if(boot_sector != nullptr) {
		// Check that the first 64 bytes of the sector aren't identical; if they are then probably
		// this disk was formatted and the filler byte never replaced.
		bool matched = true;
		for(size_t c = 1; c < 64; c++) {
			if(boot_sector->data[c] != boot_sector->data[0]) {
				matched = false;
				break;
			}
		}

		// This is a system disk, then launch it as though it were CP/M.
		if(!matched) {
			target.loadingCommand = "|cpm\n";
			return;
		}
	}

	InspectDataCatalogue(catalogue, target);
}

void StaticAnalyser::AmstradCPC::AddTargets(
	const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
	const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
	const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
	std::list<StaticAnalyser::Target> &destination) {
	Target target;
	target.machine = Target::AmstradCPC;
	target.probability = 1.0;
	target.disks = disks;
	target.tapes = tapes;
	target.cartridges = cartridges;

	target.amstradcpc.model = AmstradCPCModel::CPC6128;

	if(!target.tapes.empty()) {
		// Ugliness flows here: assume the CPC isn't smart enough to pause between pressing
		// enter and responding to the follow-on prompt to press a key, so just type for
		// a while. Yuck!
		target.loadingCommand = "|tape\nrun\"\n1234567890";
	}

	if(!target.disks.empty()) {
		Storage::Disk::CPM::ParameterBlock data_format;
		data_format.sectors_per_track = 9;
		data_format.tracks = 40;
		data_format.block_size = 1024;
		data_format.first_sector = 0xc1;
		data_format.catalogue_allocation_bitmap = 0xc000;
		data_format.reserved_tracks = 0;

		std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), data_format);
		if(data_catalogue) {
			InspectDataCatalogue(*data_catalogue, target);
		} else {
			Storage::Disk::CPM::ParameterBlock system_format;
			system_format.sectors_per_track = 9;
			system_format.tracks = 40;
			system_format.block_size = 1024;
			system_format.first_sector = 0x41;
			system_format.catalogue_allocation_bitmap = 0xc000;
			system_format.reserved_tracks = 2;

			std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), system_format);
			if(system_catalogue) {
				InspectSystemCatalogue(target.disks.front(), *system_catalogue, target);
			}
		}
	}

	destination.push_back(target);
}
<commit_msg>Adjusted rules so as not to type unnecessary spaces in the name, and to include the extension if AMSDOS won't imply it.<commit_after>//
//  AmstradCPC.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 30/07/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../../Storage/Disk/Parsers/CPM.hpp"
#include "../../Storage/Disk/Encodings/MFM.hpp"

static bool strcmp_insensitive(const char *a, const char *b) {
	if(strlen(a) != strlen(b)) return false;
	while(*a) {
		if(tolower(*a) != towlower(*b)) return false;
		a++;
		b++;
	}
	return true;
}

static bool is_implied_extension(const std::string &extension) {
	return
		extension == "   " ||
		strcmp_insensitive(extension.c_str(), "BAS") ||
		strcmp_insensitive(extension.c_str(), "BIN");
}

static std::string RunCommandFor(const Storage::Disk::CPM::File &file) {
	// Trim spaces from the name.
	std::string name = file.name;
	name.erase(std::find_if(name.rbegin(), name.rend(), [](int ch) {
        return !std::isspace(ch);
    }).base(), name.end());

	// Form the basic command.
	std::string command = "run\"" + name;

	// Consider whether the extension is required.
	if(!is_implied_extension(file.type)) {
		command += "." + file.type;
	}

	// Add a newline and return.
	return command + "\n";
}

static void InspectDataCatalogue(
	const Storage::Disk::CPM::Catalogue &catalogue,
	StaticAnalyser::Target &target) {
	// Make a copy of all files and filter out any that are marked as system.
	std::vector<Storage::Disk::CPM::File> candidate_files = catalogue.files;
	candidate_files.erase(
		std::remove_if(candidate_files.begin(), candidate_files.end(), [](const Storage::Disk::CPM::File &file) {
			return file.system;
		}),
		candidate_files.end());

	// If there's just one file, run that.
	if(candidate_files.size() == 1) {
		target.loadingCommand = RunCommandFor(candidate_files[0]);
		return;
	}

	// If only one file is [potentially] BASIC, run that one; otherwise if only one has a suffix
	// that AMSDOS allows to be omitted, pick that one.
	int basic_files = 0;
	int implicit_suffixed_files = 0;

	size_t last_basic_file = 0;
	size_t last_implicit_suffixed_file = 0;

	for(size_t c = 0; c < candidate_files.size(); c++) {
		// Files with nothing but spaces in their name can't be loaded by the user, so disregard them.
		if(candidate_files[c].type == "   " && candidate_files[c].name == "        ")
			continue;

		// Check for whether this is [potentially] BASIC.
		if(candidate_files[c].data.size() >= 128 && !((candidate_files[c].data[18] >> 1) & 7)) {
			basic_files++;
			last_basic_file = c;
		}

		// Check suffix for emptiness.
		if(is_implied_extension(candidate_files[c].type)) {
			implicit_suffixed_files++;
			last_implicit_suffixed_file = c;
		}
	}
	if(basic_files == 1 || implicit_suffixed_files == 1) {
		size_t selected_file = (basic_files == 1) ? last_basic_file : last_implicit_suffixed_file;
		target.loadingCommand = RunCommandFor(candidate_files[selected_file]);
		return;
	}

	// Desperation.
	target.loadingCommand = "cat\n";
}

static void InspectSystemCatalogue(
	const std::shared_ptr<Storage::Disk::Disk> &disk,
	const Storage::Disk::CPM::Catalogue &catalogue,
	StaticAnalyser::Target &target) {
	Storage::Encodings::MFM::Parser parser(true, disk);

	// Check that the boot sector exists and looks like it had content written to it.
	std::shared_ptr<Storage::Encodings::MFM::Sector> boot_sector = parser.get_sector(0, 0, 0x41);
	if(boot_sector != nullptr) {
		// Check that the first 64 bytes of the sector aren't identical; if they are then probably
		// this disk was formatted and the filler byte never replaced.
		bool matched = true;
		for(size_t c = 1; c < 64; c++) {
			if(boot_sector->data[c] != boot_sector->data[0]) {
				matched = false;
				break;
			}
		}

		// This is a system disk, then launch it as though it were CP/M.
		if(!matched) {
			target.loadingCommand = "|cpm\n";
			return;
		}
	}

	InspectDataCatalogue(catalogue, target);
}

void StaticAnalyser::AmstradCPC::AddTargets(
	const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
	const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
	const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
	std::list<StaticAnalyser::Target> &destination) {
	Target target;
	target.machine = Target::AmstradCPC;
	target.probability = 1.0;
	target.disks = disks;
	target.tapes = tapes;
	target.cartridges = cartridges;

	target.amstradcpc.model = AmstradCPCModel::CPC6128;

	if(!target.tapes.empty()) {
		// Ugliness flows here: assume the CPC isn't smart enough to pause between pressing
		// enter and responding to the follow-on prompt to press a key, so just type for
		// a while. Yuck!
		target.loadingCommand = "|tape\nrun\"\n1234567890";
	}

	if(!target.disks.empty()) {
		Storage::Disk::CPM::ParameterBlock data_format;
		data_format.sectors_per_track = 9;
		data_format.tracks = 40;
		data_format.block_size = 1024;
		data_format.first_sector = 0xc1;
		data_format.catalogue_allocation_bitmap = 0xc000;
		data_format.reserved_tracks = 0;

		std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), data_format);
		if(data_catalogue) {
			InspectDataCatalogue(*data_catalogue, target);
		} else {
			Storage::Disk::CPM::ParameterBlock system_format;
			system_format.sectors_per_track = 9;
			system_format.tracks = 40;
			system_format.block_size = 1024;
			system_format.first_sector = 0x41;
			system_format.catalogue_allocation_bitmap = 0xc000;
			system_format.reserved_tracks = 2;

			std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), system_format);
			if(system_catalogue) {
				InspectSystemCatalogue(target.disks.front(), *system_catalogue, target);
			}
		}
	}

	destination.push_back(target);
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"

#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <string>

#include "third_party/boringssl/src/include/openssl/siphash.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"

namespace quic {

namespace {

// QuicConnectionIdHasher can be used to generate a stable connection ID hash
// function that will return the same value for two equal connection IDs for
// the duration of process lifetime. It is meant to be used as input to data
// structures that do not outlast process lifetime. A new key is generated once
// per process to prevent attackers from crafting connection IDs in such a way
// that they always land in the same hash bucket.
class QuicConnectionIdHasher {
 public:
  explicit inline QuicConnectionIdHasher()
      : QuicConnectionIdHasher(QuicRandom::GetInstance()) {}

  explicit inline QuicConnectionIdHasher(QuicRandom* random) {
    random->RandBytes(&sip_hash_key_, sizeof(sip_hash_key_));
  }

  inline size_t Hash(const char* input, size_t input_len) const {
    return static_cast<size_t>(SIPHASH_24(
        sip_hash_key_, reinterpret_cast<const uint8_t*>(input), input_len));
  }

 private:
  uint64_t sip_hash_key_[2];
};

}  // namespace

QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {}

QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
  static_assert(
      kQuicMaxConnectionIdLength <= std::numeric_limits<uint8_t>::max(),
      "kQuicMaxConnectionIdLength too high");
  if (length > kQuicMaxConnectionIdLength) {
    QUIC_BUG << "Attempted to create connection ID of length " << length;
    length = kQuicMaxConnectionIdLength;
  }
  length_ = length;
  if (length_ == 0) {
    return;
  }
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    memcpy(data_, data, length_);
    return;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 1, 6);
  if (length_ <= sizeof(data_short_)) {
    memcpy(data_short_, data, length_);
    return;
  }
  data_long_ = reinterpret_cast<char*>(malloc(length_));
  CHECK_NE(nullptr, data_long_);
  memcpy(data_long_, data, length_);
}

QuicConnectionId::~QuicConnectionId() {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 2, 6);
  if (length_ > sizeof(data_short_)) {
    free(data_long_);
    data_long_ = nullptr;
  }
}

QuicConnectionId::QuicConnectionId(const QuicConnectionId& other)
    : QuicConnectionId(other.data(), other.length()) {}

QuicConnectionId& QuicConnectionId::operator=(const QuicConnectionId& other) {
  set_length(other.length());
  memcpy(mutable_data(), other.data(), length_);
  return *this;
}

const char* QuicConnectionId::data() const {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return data_;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 3, 6);
  if (length_ <= sizeof(data_short_)) {
    return data_short_;
  }
  return data_long_;
}

char* QuicConnectionId::mutable_data() {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return data_;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 4, 6);
  if (length_ <= sizeof(data_short_)) {
    return data_short_;
  }
  return data_long_;
}

uint8_t QuicConnectionId::length() const {
  return length_;
}

void QuicConnectionId::set_length(uint8_t length) {
  if (GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 5, 6);
    char temporary_data[sizeof(data_short_)];
    if (length > sizeof(data_short_)) {
      if (length_ <= sizeof(data_short_)) {
        // Copy data from data_short_ to data_long_.
        memcpy(temporary_data, data_short_, length_);
        data_long_ = reinterpret_cast<char*>(malloc(length));
        CHECK_NE(nullptr, data_long_);
        memcpy(data_long_, temporary_data, length_);
      } else {
        // Resize data_long_.
        char* realloc_result =
            reinterpret_cast<char*>(realloc(data_long_, length));
        CHECK_NE(nullptr, realloc_result);
        data_long_ = realloc_result;
      }
    } else if (length_ > sizeof(data_short_)) {
      // Copy data from data_long_ to data_short_.
      memcpy(temporary_data, data_long_, length);
      free(data_long_);
      data_long_ = nullptr;
      memcpy(data_short_, temporary_data, length);
    }
  }
  length_ = length;
}

bool QuicConnectionId::IsEmpty() const {
  return length_ == 0;
}

size_t QuicConnectionId::Hash() const {
  if (!GetQuicRestartFlag(quic_connection_id_use_siphash)) {
    uint64_t data_bytes[3] = {0, 0, 0};
    static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength,
                  "kQuicMaxConnectionIdLength changed");
    memcpy(data_bytes, data(), length_);
    // This Hash function is designed to return the same value as the host byte
    // order representation when the connection ID length is 64 bits.
    return QuicEndian::NetToHost64(kQuicDefaultConnectionIdLength ^ length_ ^
                                   data_bytes[0] ^ data_bytes[1] ^
                                   data_bytes[2]);
  }
  QUIC_RESTART_FLAG_COUNT(quic_connection_id_use_siphash);
  static const QuicConnectionIdHasher hasher = QuicConnectionIdHasher();
  return hasher.Hash(data(), length_);
}

std::string QuicConnectionId::ToString() const {
  if (IsEmpty()) {
    return std::string("0");
  }
  return QuicTextUtils::HexEncode(data(), length_);
}

std::ostream& operator<<(std::ostream& os, const QuicConnectionId& v) {
  os << v.ToString();
  return os;
}

bool QuicConnectionId::operator==(const QuicConnectionId& v) const {
  return length_ == v.length_ && memcmp(data(), v.data(), length_) == 0;
}

bool QuicConnectionId::operator!=(const QuicConnectionId& v) const {
  return !(v == *this);
}

bool QuicConnectionId::operator<(const QuicConnectionId& v) const {
  if (length_ < v.length_) {
    return true;
  }
  if (length_ > v.length_) {
    return false;
  }
  return memcmp(data(), v.data(), length_) < 0;
}

QuicConnectionId EmptyQuicConnectionId() {
  return QuicConnectionId();
}

static_assert(kQuicDefaultConnectionIdLength == sizeof(uint64_t),
              "kQuicDefaultConnectionIdLength changed");
static_assert(kQuicDefaultConnectionIdLength == PACKET_8BYTE_CONNECTION_ID,
              "kQuicDefaultConnectionIdLength changed");

}  // namespace quic
<commit_msg>Remove redundant use of keyword explicit on QuicConnectionIdHasher default constructor<commit_after>// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"

#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <string>

#include "third_party/boringssl/src/include/openssl/siphash.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"

namespace quic {

namespace {

// QuicConnectionIdHasher can be used to generate a stable connection ID hash
// function that will return the same value for two equal connection IDs for
// the duration of process lifetime. It is meant to be used as input to data
// structures that do not outlast process lifetime. A new key is generated once
// per process to prevent attackers from crafting connection IDs in such a way
// that they always land in the same hash bucket.
class QuicConnectionIdHasher {
 public:
  inline QuicConnectionIdHasher()
      : QuicConnectionIdHasher(QuicRandom::GetInstance()) {}

  explicit inline QuicConnectionIdHasher(QuicRandom* random) {
    random->RandBytes(&sip_hash_key_, sizeof(sip_hash_key_));
  }

  inline size_t Hash(const char* input, size_t input_len) const {
    return static_cast<size_t>(SIPHASH_24(
        sip_hash_key_, reinterpret_cast<const uint8_t*>(input), input_len));
  }

 private:
  uint64_t sip_hash_key_[2];
};

}  // namespace

QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {}

QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
  static_assert(
      kQuicMaxConnectionIdLength <= std::numeric_limits<uint8_t>::max(),
      "kQuicMaxConnectionIdLength too high");
  if (length > kQuicMaxConnectionIdLength) {
    QUIC_BUG << "Attempted to create connection ID of length " << length;
    length = kQuicMaxConnectionIdLength;
  }
  length_ = length;
  if (length_ == 0) {
    return;
  }
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    memcpy(data_, data, length_);
    return;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 1, 6);
  if (length_ <= sizeof(data_short_)) {
    memcpy(data_short_, data, length_);
    return;
  }
  data_long_ = reinterpret_cast<char*>(malloc(length_));
  CHECK_NE(nullptr, data_long_);
  memcpy(data_long_, data, length_);
}

QuicConnectionId::~QuicConnectionId() {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 2, 6);
  if (length_ > sizeof(data_short_)) {
    free(data_long_);
    data_long_ = nullptr;
  }
}

QuicConnectionId::QuicConnectionId(const QuicConnectionId& other)
    : QuicConnectionId(other.data(), other.length()) {}

QuicConnectionId& QuicConnectionId::operator=(const QuicConnectionId& other) {
  set_length(other.length());
  memcpy(mutable_data(), other.data(), length_);
  return *this;
}

const char* QuicConnectionId::data() const {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return data_;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 3, 6);
  if (length_ <= sizeof(data_short_)) {
    return data_short_;
  }
  return data_long_;
}

char* QuicConnectionId::mutable_data() {
  if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    return data_;
  }
  QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 4, 6);
  if (length_ <= sizeof(data_short_)) {
    return data_short_;
  }
  return data_long_;
}

uint8_t QuicConnectionId::length() const {
  return length_;
}

void QuicConnectionId::set_length(uint8_t length) {
  if (GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
    QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 5, 6);
    char temporary_data[sizeof(data_short_)];
    if (length > sizeof(data_short_)) {
      if (length_ <= sizeof(data_short_)) {
        // Copy data from data_short_ to data_long_.
        memcpy(temporary_data, data_short_, length_);
        data_long_ = reinterpret_cast<char*>(malloc(length));
        CHECK_NE(nullptr, data_long_);
        memcpy(data_long_, temporary_data, length_);
      } else {
        // Resize data_long_.
        char* realloc_result =
            reinterpret_cast<char*>(realloc(data_long_, length));
        CHECK_NE(nullptr, realloc_result);
        data_long_ = realloc_result;
      }
    } else if (length_ > sizeof(data_short_)) {
      // Copy data from data_long_ to data_short_.
      memcpy(temporary_data, data_long_, length);
      free(data_long_);
      data_long_ = nullptr;
      memcpy(data_short_, temporary_data, length);
    }
  }
  length_ = length;
}

bool QuicConnectionId::IsEmpty() const {
  return length_ == 0;
}

size_t QuicConnectionId::Hash() const {
  if (!GetQuicRestartFlag(quic_connection_id_use_siphash)) {
    uint64_t data_bytes[3] = {0, 0, 0};
    static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength,
                  "kQuicMaxConnectionIdLength changed");
    memcpy(data_bytes, data(), length_);
    // This Hash function is designed to return the same value as the host byte
    // order representation when the connection ID length is 64 bits.
    return QuicEndian::NetToHost64(kQuicDefaultConnectionIdLength ^ length_ ^
                                   data_bytes[0] ^ data_bytes[1] ^
                                   data_bytes[2]);
  }
  QUIC_RESTART_FLAG_COUNT(quic_connection_id_use_siphash);
  static const QuicConnectionIdHasher hasher = QuicConnectionIdHasher();
  return hasher.Hash(data(), length_);
}

std::string QuicConnectionId::ToString() const {
  if (IsEmpty()) {
    return std::string("0");
  }
  return QuicTextUtils::HexEncode(data(), length_);
}

std::ostream& operator<<(std::ostream& os, const QuicConnectionId& v) {
  os << v.ToString();
  return os;
}

bool QuicConnectionId::operator==(const QuicConnectionId& v) const {
  return length_ == v.length_ && memcmp(data(), v.data(), length_) == 0;
}

bool QuicConnectionId::operator!=(const QuicConnectionId& v) const {
  return !(v == *this);
}

bool QuicConnectionId::operator<(const QuicConnectionId& v) const {
  if (length_ < v.length_) {
    return true;
  }
  if (length_ > v.length_) {
    return false;
  }
  return memcmp(data(), v.data(), length_) < 0;
}

QuicConnectionId EmptyQuicConnectionId() {
  return QuicConnectionId();
}

static_assert(kQuicDefaultConnectionIdLength == sizeof(uint64_t),
              "kQuicDefaultConnectionIdLength changed");
static_assert(kQuicDefaultConnectionIdLength == PACKET_8BYTE_CONNECTION_ID,
              "kQuicDefaultConnectionIdLength changed");

}  // namespace quic
<|endoftext|>


<commit_before>#include <string>

#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>

#include <boost/format.hpp>
#include <SDL2/SDL.h>

static const int   WIDTH        = 32 * 6;
static const int   HEIGHT       = 64 * 3;
static const int   WHEEL_DIA    = 16;
static const int   TIMEOUT      = 3000;
static const float PI           = 3.14159265358979f;
static const float DIST_PER_REV = WHEEL_DIA * PI / 5280 / 12;
static const float VELO_FALLOFF = 0.0005f;

// TODO pass at runtime
static const std::string SERIAL = "/dev/cu.usbmodem12341";

struct Stats {
  float dist, time, velo;
  unsigned long last_rev, next_rev;
};

void draw_text(SDL_Renderer* renderer, SDL_Texture* texture, int x, int y, std::string text) {
  SDL_Rect source = { 0, 0, 0, 64 };
  SDL_Rect dest   = { x, y, 0, 64 };

  for (std::string::iterator i = text.begin(); i != text.end(); ++i) {
    if ((*i) >= '0' && (*i) <= '9') {
      source.x = ((*i) - '/') * 32;
      source.w = dest.w = 32;
    } else if ((*i) == ' ') {
      source.x = 0;
      source.w = dest.w = 32;
    } else if ((*i) == ':') {
      source.x = 352;
      source.w = dest.w = 16;
    } else if ((*i) == '.') {
      source.x = 368;
      source.w = dest.w = 16;
    }

    SDL_RenderCopy(renderer, texture, &source, &dest);
    dest.x += source.w;
  }
}

void draw_rect(SDL_Renderer* renderer, SDL_Texture* texture, int dx, int dy, int sx, int sy, int w, int h) {
  SDL_Rect source = {sx, sy, w, h};
  SDL_Rect dest = {dx, dy, w, h};
  SDL_RenderCopy(renderer, texture, &source, &dest);
}

void draw(SDL_Renderer* renderer, SDL_Texture* texture, Stats* stats) {
  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  SDL_RenderClear(renderer);

  long sec = lroundf(stats->time);

  draw_text(renderer, texture, 0, 0, boost::str(boost::format("%4.1f") % stats->velo));
  draw_text(renderer, texture, 0, 64, boost::str(boost::format("%5.2f") % stats->dist));
  draw_text(renderer, texture, 0, 128, boost::str(boost::format("%u:%02u:%02u") % (sec / 3600) % ((sec / 60) % 60) % (sec % 60)));

  draw_rect(renderer, texture, 132, 0, 384, 0, 64, 64);
  draw_rect(renderer, texture, 160, 64, 448, 0, 32, 64);

  SDL_RenderPresent(renderer);
}

void handle_rev(int rpm, Stats* stats) {
  unsigned long current = SDL_GetTicks();
  long elapsed = current - stats->last_rev;

  if (elapsed < TIMEOUT) {
    stats->dist += DIST_PER_REV;
    stats->velo = rpm * 60 * DIST_PER_REV;

    fprintf(stderr, "Revolution!  v:%.2f\n", stats->velo);

    if (stats->velo > 0.0f) {
      float next = DIST_PER_REV / stats->velo;
      fprintf(stderr, "Next rev in %.3f seconds\n", next * 3600);
      stats->next_rev = current + lroundf(next * 3600000);
    } else {
      stats->next_rev = 0;
    }

  } else {
    stats->velo = 0;
    fprintf(stderr, "Timeout!\n");
  }

  stats->last_rev = current;
}

int main() {
  SDL_Window* window = SDL_CreateWindow("Bike Stats", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
  SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

  SDL_Surface* surface = SDL_LoadBMP("sprites.bmp");
  SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

  SDL_Event event;
  bool running = true;

  int serial = open(SERIAL.c_str(), O_RDONLY | O_NONBLOCK);
  if (serial == -1) {
    fprintf(stderr, "Error opening serial device %s: %u\n", SERIAL.c_str(), errno);
    return -1;
  }

  long last_tick = 0;

  Stats stats = { 0.0f, 0.0f, 0.0f, 0, 0 };
  char buffer[256];

  while (running) {
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_QUIT) running = false;
    }

    ssize_t bytes = read(serial, buffer, 256);

    if (bytes > 0) {
      int rpm = atoi(buffer);
      fprintf(stderr, "Got RPM %u\n", rpm);
      handle_rev(rpm, &stats);
    } else if (bytes == 0) {
      // ignore this and continue
      // fprintf(stderr, "EOF on serial device\n");
      // break;
    } else if (errno != EAGAIN) {
      fprintf(stderr, "Error reading from serial device: %u\n", errno);
      break;
    }

    long current = SDL_GetTicks();
    long elapsed = current - last_tick;

    if (stats.velo > 0.0f) stats.time += elapsed / 1000.0f;

    last_tick = current;

    if (current > stats.next_rev) {
      stats.velo -= VELO_FALLOFF;
      if (stats.velo < 0.0f) stats.velo = 0.0f;
    }

    draw(renderer, texture, &stats);
  }

  SDL_DestroyTexture(texture);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);

  return 0;
}
<commit_msg>Fix signed compare warning<commit_after>#include <string>

#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>

#include <boost/format.hpp>
#include <SDL2/SDL.h>

static const int   WIDTH        = 32 * 6;
static const int   HEIGHT       = 64 * 3;
static const int   WHEEL_DIA    = 16;
static const int   TIMEOUT      = 3000;
static const float PI           = 3.14159265358979f;
static const float DIST_PER_REV = WHEEL_DIA * PI / 5280 / 12;
static const float VELO_FALLOFF = 0.0005f;

// TODO pass at runtime
static const std::string SERIAL = "/dev/cu.usbmodem12341";

struct Stats {
  float dist, time, velo;
  unsigned long last_rev, next_rev;
};

void draw_text(SDL_Renderer* renderer, SDL_Texture* texture, int x, int y, std::string text) {
  SDL_Rect source = { 0, 0, 0, 64 };
  SDL_Rect dest   = { x, y, 0, 64 };

  for (std::string::iterator i = text.begin(); i != text.end(); ++i) {
    if ((*i) >= '0' && (*i) <= '9') {
      source.x = ((*i) - '/') * 32;
      source.w = dest.w = 32;
    } else if ((*i) == ' ') {
      source.x = 0;
      source.w = dest.w = 32;
    } else if ((*i) == ':') {
      source.x = 352;
      source.w = dest.w = 16;
    } else if ((*i) == '.') {
      source.x = 368;
      source.w = dest.w = 16;
    }

    SDL_RenderCopy(renderer, texture, &source, &dest);
    dest.x += source.w;
  }
}

void draw_rect(SDL_Renderer* renderer, SDL_Texture* texture, int dx, int dy, int sx, int sy, int w, int h) {
  SDL_Rect source = {sx, sy, w, h};
  SDL_Rect dest = {dx, dy, w, h};
  SDL_RenderCopy(renderer, texture, &source, &dest);
}

void draw(SDL_Renderer* renderer, SDL_Texture* texture, Stats* stats) {
  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  SDL_RenderClear(renderer);

  long sec = lroundf(stats->time);

  draw_text(renderer, texture, 0, 0, boost::str(boost::format("%4.1f") % stats->velo));
  draw_text(renderer, texture, 0, 64, boost::str(boost::format("%5.2f") % stats->dist));
  draw_text(renderer, texture, 0, 128, boost::str(boost::format("%u:%02u:%02u") % (sec / 3600) % ((sec / 60) % 60) % (sec % 60)));

  draw_rect(renderer, texture, 132, 0, 384, 0, 64, 64);
  draw_rect(renderer, texture, 160, 64, 448, 0, 32, 64);

  SDL_RenderPresent(renderer);
}

void handle_rev(int rpm, Stats* stats) {
  unsigned long current = SDL_GetTicks();
  long elapsed = current - stats->last_rev;

  if (elapsed < TIMEOUT) {
    stats->dist += DIST_PER_REV;
    stats->velo = rpm * 60 * DIST_PER_REV;

    fprintf(stderr, "Revolution!  v:%.2f\n", stats->velo);

    if (stats->velo > 0.0f) {
      float next = DIST_PER_REV / stats->velo;
      fprintf(stderr, "Next rev in %.3f seconds\n", next * 3600);
      stats->next_rev = current + lroundf(next * 3600000);
    } else {
      stats->next_rev = 0;
    }

  } else {
    stats->velo = 0;
    fprintf(stderr, "Timeout!\n");
  }

  stats->last_rev = current;
}

int main() {
  SDL_Window* window = SDL_CreateWindow("Bike Stats", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
  SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

  SDL_Surface* surface = SDL_LoadBMP("sprites.bmp");
  SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

  SDL_Event event;
  bool running = true;

  int serial = open(SERIAL.c_str(), O_RDONLY | O_NONBLOCK);
  if (serial == -1) {
    fprintf(stderr, "Error opening serial device %s: %u\n", SERIAL.c_str(), errno);
    return -1;
  }

  long last_tick = 0;

  Stats stats = { 0.0f, 0.0f, 0.0f, 0, 0 };
  char buffer[256];

  while (running) {
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_QUIT) running = false;
    }

    ssize_t bytes = read(serial, buffer, 256);

    if (bytes > 0) {
      int rpm = atoi(buffer);
      fprintf(stderr, "Got RPM %u\n", rpm);
      handle_rev(rpm, &stats);
    } else if (bytes == 0) {
      // ignore this and continue
      // fprintf(stderr, "EOF on serial device\n");
      // break;
    } else if (errno != EAGAIN) {
      fprintf(stderr, "Error reading from serial device: %u\n", errno);
      break;
    }

    unsigned long current = SDL_GetTicks();
    unsigned long elapsed = current - last_tick;

    if (stats.velo > 0.0f) stats.time += elapsed / 1000.0f;

    last_tick = current;

    if (current > stats.next_rev) {
      stats.velo -= VELO_FALLOFF;
      if (stats.velo < 0.0f) stats.velo = 0.0f;
    }

    draw(renderer, texture, &stats);
  }

  SDL_DestroyTexture(texture);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);

  return 0;
}
<|endoftext|>


<commit_before>#include "mdist.hpp"
#include <cstdlib>

TilesMdist::TilesMdist(FILE *in) : Tiles(in) {
	initmd();
	initincr();
}

TilesMdist::State TilesMdist::initialstate(void) {
	State s;
	s.h = 0;
	for (unsigned int i = 0; i < Ntiles; i++) {
		if (init[i] == 0)
			s.b = i;
		else
			s.h += md[init[i]][i];
		s.ts[i] = init[i];
	}
	return s;
}

void TilesMdist::initmd(void) {
	for (unsigned int t = 1; t < Ntiles; t++) {
		unsigned int row = goalpos[t] / Width;
		unsigned int col = goalpos[t] % Width;
		for (int i = 0; i < Ntiles; i++) {
			unsigned int r = i / Width;
			unsigned int c = i % Width;
			md[t][i] = abs(r - row) + abs(c - col);
		}
	}
}

void TilesMdist::initincr(void) {
	for (unsigned int t = 1; t < Ntiles; t++) {
	for (unsigned int old = 0; old < Ntiles; old++) {
		unsigned int cur = md[t][old];
		for (unsigned int n = 0; n <ops[old].n; n++) {
			unsigned int nw = ops[old].mvs[n];
			incr[t][old][nw] = md[t][nw] - cur;
		}
	}
	}
}<commit_msg>tiles: rename some local varaibles that were named wrong.<commit_after>#include "mdist.hpp"
#include <cstdlib>

TilesMdist::TilesMdist(FILE *in) : Tiles(in) {
	initmd();
	initincr();
}

TilesMdist::State TilesMdist::initialstate(void) {
	State s;
	s.h = 0;
	for (unsigned int i = 0; i < Ntiles; i++) {
		if (init[i] == 0)
			s.b = i;
		else
			s.h += md[init[i]][i];
		s.ts[i] = init[i];
	}
	return s;
}

void TilesMdist::initmd(void) {
	for (unsigned int t = 1; t < Ntiles; t++) {
		unsigned int row = goalpos[t] / Width;
		unsigned int col = goalpos[t] % Width;
		for (int i = 0; i < Ntiles; i++) {
			unsigned int r = i / Width;
			unsigned int c = i % Width;
			md[t][i] = abs(r - row) + abs(c - col);
		}
	}
}

void TilesMdist::initincr(void) {
	for (unsigned int t = 1; t < Ntiles; t++) {
	for (unsigned int nw = 0; nw < Ntiles; nw++) {
		unsigned int next = md[t][nw];
		for (unsigned int n = 0; n <ops[nw].n; n++) {
			unsigned int old = ops[nw].mvs[n];
			incr[t][nw][old] = md[t][old] - next;
		}
	}
	}
}<|endoftext|>


<commit_before>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 of the
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "module.hh"
#include "agent.hh"
#include "event.hh"
#include "transaction.hh"
#include "apn/pushnotification.h"
#include "apn/pushnotificationservice.h"

using namespace ::std;

class PushNotificationContext {
private:
	su_timer_t* mTimer;
	PushNotificationService * mPNS;
	shared_ptr<PushNotificationRequest> mPushNotificationRequest;
public:
	PushNotificationContext(shared_ptr<OutgoingTransaction> &transaction, PushNotificationService * pns, const shared_ptr<PushNotificationRequest> &pnr);
	~PushNotificationContext();

	void start(int seconds);

	void onTimeout();

	static void __timer_callback(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg);
};

PushNotificationContext::PushNotificationContext(shared_ptr<OutgoingTransaction> &transaction, PushNotificationService * pns, const shared_ptr<PushNotificationRequest> &pnr) :
		mPNS(pns), mPushNotificationRequest(pnr) {
	LOGD("New PushNotificationContext %p", this);
	mTimer = su_timer_create(su_root_task(transaction->getAgent()->getRoot()), 0);
}

PushNotificationContext::~PushNotificationContext() {
	su_timer_destroy(mTimer);
	LOGD("Destroy PushNotificationContext %p", this);
}

void PushNotificationContext::start(int seconds) {
	su_timer_set_interval(mTimer, &PushNotificationContext::__timer_callback, this, seconds * 1000);
}

void PushNotificationContext::onTimeout() {
	LOGD("PushNotificationContext timeout!");
	mPNS->sendRequest(mPushNotificationRequest);
}

void PushNotificationContext::__timer_callback(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg) {
	PushNotificationContext *context = (PushNotificationContext*) arg;
	context->onTimeout();
}

class PushNotification: public Module, public ModuleToolbox {
public:
	PushNotification(Agent *ag);
	virtual ~PushNotification();
	void onDeclare(GenericStruct *module_config);
	virtual void onTransactionEvent(const shared_ptr<Transaction> &transaction, Transaction::Event event);
	virtual void onRequest(std::shared_ptr<RequestSipEvent> &ev);
	virtual void onResponse(std::shared_ptr<ResponseSipEvent> &ev);
	virtual void onLoad(const GenericStruct *mc);

private:
	shared_ptr<PushNotificationRequest> makePushNotification(const shared_ptr<MsgSip> &ms);
	static ModuleInfo<PushNotification> sInfo;
	int mTimeout;
	PushNotificationService *mAPNS;
};

ModuleInfo<PushNotification> PushNotification::sInfo("PushNotification", "This module performs push notifications", ModuleInfoBase::ModuleOid::PushNotification);

PushNotification::PushNotification(Agent *ag) :
		Module(ag), mAPNS(NULL) {
}

PushNotification::~PushNotification() {
	if (mAPNS != NULL) {
		mAPNS->stop();
		delete mAPNS;
	}
}

void PushNotification::onDeclare(GenericStruct *module_config) {
	module_config->get<ConfigBoolean>("enabled")->setDefault("false");
	ConfigItemDescriptor items[] = {
			{ Integer, "timeout", "Number of second to wait before sending a push notification to device(if <=0 then disabled)", "5" },
			{ Boolean, "apple", "Enable push notificaction for apple devices", "true" },
			{ String, "apple-certificate-dir", "Path to directory where to find Apple Push Notification service certificates. They should bear the appid of the application, suffixed by the release mode and .pem extension. For example: org.linphone.dev.pem org.linphone.prod.pem com.somephone.dev.pem etc..."
			" The files should be .pem format, and made of certificate followed by private key." , "/etc/flexisip/apn" },
			config_item_end };
	module_config->addChildrenValues(items);
}

void PushNotification::onLoad(const GenericStruct *mc) {
	mTimeout = mc->get<ConfigInt>("timeout")->read();
	string cafile = mc->get<ConfigString>("apple-ca")->read();
	string certdir = mc->get<ConfigString>("apple-certificate-dir")->read();
	mAPNS = new PushNotificationService( certdir, cafile);
	mAPNS->start();
}

shared_ptr<PushNotificationRequest> PushNotification::makePushNotification(const shared_ptr<MsgSip> &ms){
	sip_t *sip=ms->getSip();
	if (sip->sip_request->rq_url != NULL && sip->sip_request->rq_url->url_params != NULL){
		char type[12];
		char deviceToken[65];
		char appId[256]={0};
		char msg_str[64];
		char call_str[64];
		char call_snd[64];
		char msg_snd[64];

		char const *params=sip->sip_request->rq_url->url_params;
		/*extract all parameters required to make the push notification */
		if (!url_param(params, "pn-type", type, sizeof(type)))
			return 0;
		if (!url_param(params, "app-id", appId, sizeof(appId)))
			return 0;
		if (url_param(params, "pn-tok", deviceToken, sizeof(deviceToken)) != sizeof(deviceToken))
			return 0;
		if (!url_param(params, "pn-msg-str", msg_str, sizeof(msg_str))) {
			return 0;
		}
		if (!url_param(params, "pn-call-str", call_str, sizeof(call_str))){
			return 0;
		}
		if (!url_param(params, "pn-call-snd", call_snd, sizeof(call_snd))){
			return 0;
		}
		if (!url_param(params, "pn-msg-snd", msg_snd, sizeof(msg_snd))){
			return 0;
		}
		string contact;
		if(sip->sip_from->a_display != NULL && strlen(sip->sip_from->a_display) > 0) {
			contact = sip->sip_from->a_display;
		} else {
			contact = url_as_string(ms->getHome(), sip->sip_from->a_url);
		}
		if (strcmp(type,"apple")==0){
			return make_shared<ApplePushNotificationRequest>(appId,deviceToken,
					(sip->sip_request->rq_method == sip_method_invite) ? call_str : msg_str,
					contact,
					(sip->sip_request->rq_method == sip_method_invite) ? call_snd : msg_snd);
		}else if (strcmp(type,"google")==0){
			//TODO
		}
	}
	return 0;
}

void PushNotification::onRequest(std::shared_ptr<RequestSipEvent> &ev) {
	const shared_ptr<MsgSip> &ms = ev->getMsgSip();
	sip_t *sip=ms->getSip();
	if ((sip->sip_request->rq_method == sip_method_invite ||
		sip->sip_request->rq_method == sip_method_message) &&
		sip->sip_to && sip->sip_to->a_tag==NULL){
		shared_ptr<OutgoingTransaction> transaction = dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
		if (transaction != NULL) {
			sip_t *sip = ms->getSip();
			if (sip->sip_request->rq_url != NULL && sip->sip_request->rq_url->url_params != NULL) {
				try{
					shared_ptr<PushNotificationRequest> request = makePushNotification(ms);
					if (request){
						shared_ptr<PushNotificationContext> context = make_shared<PushNotificationContext>(transaction, mAPNS, request);
						context->start(mTimeout);
						transaction->setProperty(getModuleName(), context);
					}
				}catch(exception &e){
					LOGE("Could not create push notification.");
				}
			}
		}
	}
}

void PushNotification::onResponse(std::shared_ptr<ResponseSipEvent> &ev) {
	shared_ptr<OutgoingTransaction> transaction = dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
	if (transaction != NULL) {
		transaction->removeProperty(getModuleName());
	}
}

void PushNotification::onTransactionEvent(const shared_ptr<Transaction> &transaction, Transaction::Event event) {
	shared_ptr<OutgoingTransaction> ot = dynamic_pointer_cast<OutgoingTransaction>(transaction);
	if (ot != NULL) {
		switch (event) {
		case Transaction::Destroy:
			transaction->removeProperty(getModuleName());
			break;

		case Transaction::Create:
			break;
		}
	}
}
<commit_msg>fix invalid read of parameter<commit_after>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 of the
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "module.hh"
#include "agent.hh"
#include "event.hh"
#include "transaction.hh"
#include "apn/pushnotification.h"
#include "apn/pushnotificationservice.h"

using namespace ::std;

class PushNotificationContext {
private:
	su_timer_t* mTimer;
	PushNotificationService * mPNS;
	shared_ptr<PushNotificationRequest> mPushNotificationRequest;
public:
	PushNotificationContext(shared_ptr<OutgoingTransaction> &transaction, PushNotificationService * pns, const shared_ptr<PushNotificationRequest> &pnr);
	~PushNotificationContext();

	void start(int seconds);

	void onTimeout();

	static void __timer_callback(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg);
};

PushNotificationContext::PushNotificationContext(shared_ptr<OutgoingTransaction> &transaction, PushNotificationService * pns, const shared_ptr<PushNotificationRequest> &pnr) :
		mPNS(pns), mPushNotificationRequest(pnr) {
	LOGD("New PushNotificationContext %p", this);
	mTimer = su_timer_create(su_root_task(transaction->getAgent()->getRoot()), 0);
}

PushNotificationContext::~PushNotificationContext() {
	su_timer_destroy(mTimer);
	LOGD("Destroy PushNotificationContext %p", this);
}

void PushNotificationContext::start(int seconds) {
	su_timer_set_interval(mTimer, &PushNotificationContext::__timer_callback, this, seconds * 1000);
}

void PushNotificationContext::onTimeout() {
	LOGD("PushNotificationContext timeout!");
	mPNS->sendRequest(mPushNotificationRequest);
}

void PushNotificationContext::__timer_callback(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg) {
	PushNotificationContext *context = (PushNotificationContext*) arg;
	context->onTimeout();
}

class PushNotification: public Module, public ModuleToolbox {
public:
	PushNotification(Agent *ag);
	virtual ~PushNotification();
	void onDeclare(GenericStruct *module_config);
	virtual void onTransactionEvent(const shared_ptr<Transaction> &transaction, Transaction::Event event);
	virtual void onRequest(std::shared_ptr<RequestSipEvent> &ev);
	virtual void onResponse(std::shared_ptr<ResponseSipEvent> &ev);
	virtual void onLoad(const GenericStruct *mc);

private:
	shared_ptr<PushNotificationRequest> makePushNotification(const shared_ptr<MsgSip> &ms);
	static ModuleInfo<PushNotification> sInfo;
	int mTimeout;
	PushNotificationService *mAPNS;
};

ModuleInfo<PushNotification> PushNotification::sInfo("PushNotification", "This module performs push notifications", ModuleInfoBase::ModuleOid::PushNotification);

PushNotification::PushNotification(Agent *ag) :
		Module(ag), mAPNS(NULL) {
}

PushNotification::~PushNotification() {
	if (mAPNS != NULL) {
		mAPNS->stop();
		delete mAPNS;
	}
}

void PushNotification::onDeclare(GenericStruct *module_config) {
	module_config->get<ConfigBoolean>("enabled")->setDefault("false");
	ConfigItemDescriptor items[] = {
			{ Integer, "timeout", "Number of second to wait before sending a push notification to device(if <=0 then disabled)", "5" },
			{ Boolean, "apple", "Enable push notificaction for apple devices", "true" },
			{ String, "apple-certificate-dir", "Path to directory where to find Apple Push Notification service certificates. They should bear the appid of the application, suffixed by the release mode and .pem extension. For example: org.linphone.dev.pem org.linphone.prod.pem com.somephone.dev.pem etc..."
			" The files should be .pem format, and made of certificate followed by private key." , "/etc/flexisip/apn" },
			config_item_end };
	module_config->addChildrenValues(items);
}

void PushNotification::onLoad(const GenericStruct *mc) {
	mTimeout = mc->get<ConfigInt>("timeout")->read();
	string certdir = mc->get<ConfigString>("apple-certificate-dir")->read();
	mAPNS = new PushNotificationService( certdir, "");
	mAPNS->start();
}

shared_ptr<PushNotificationRequest> PushNotification::makePushNotification(const shared_ptr<MsgSip> &ms){
	sip_t *sip=ms->getSip();
	if (sip->sip_request->rq_url != NULL && sip->sip_request->rq_url->url_params != NULL){
		char type[12];
		char deviceToken[65];
		char appId[256]={0};
		char msg_str[64];
		char call_str[64];
		char call_snd[64];
		char msg_snd[64];

		char const *params=sip->sip_request->rq_url->url_params;
		/*extract all parameters required to make the push notification */
		if (!url_param(params, "pn-type", type, sizeof(type)))
			return 0;
		if (!url_param(params, "app-id", appId, sizeof(appId)))
			return 0;
		if (url_param(params, "pn-tok", deviceToken, sizeof(deviceToken)) != sizeof(deviceToken))
			return 0;
		if (!url_param(params, "pn-msg-str", msg_str, sizeof(msg_str))) {
			return 0;
		}
		if (!url_param(params, "pn-call-str", call_str, sizeof(call_str))){
			return 0;
		}
		if (!url_param(params, "pn-call-snd", call_snd, sizeof(call_snd))){
			return 0;
		}
		if (!url_param(params, "pn-msg-snd", msg_snd, sizeof(msg_snd))){
			return 0;
		}
		string contact;
		if(sip->sip_from->a_display != NULL && strlen(sip->sip_from->a_display) > 0) {
			contact = sip->sip_from->a_display;
		} else {
			contact = url_as_string(ms->getHome(), sip->sip_from->a_url);
		}
		if (strcmp(type,"apple")==0){
			return make_shared<ApplePushNotificationRequest>(appId,deviceToken,
					(sip->sip_request->rq_method == sip_method_invite) ? call_str : msg_str,
					contact,
					(sip->sip_request->rq_method == sip_method_invite) ? call_snd : msg_snd);
		}else if (strcmp(type,"google")==0){
			//TODO
		}
	}
	return 0;
}

void PushNotification::onRequest(std::shared_ptr<RequestSipEvent> &ev) {
	const shared_ptr<MsgSip> &ms = ev->getMsgSip();
	sip_t *sip=ms->getSip();
	if ((sip->sip_request->rq_method == sip_method_invite ||
		sip->sip_request->rq_method == sip_method_message) &&
		sip->sip_to && sip->sip_to->a_tag==NULL){
		shared_ptr<OutgoingTransaction> transaction = dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
		if (transaction != NULL) {
			sip_t *sip = ms->getSip();
			if (sip->sip_request->rq_url != NULL && sip->sip_request->rq_url->url_params != NULL) {
				try{
					shared_ptr<PushNotificationRequest> request = makePushNotification(ms);
					if (request){
						shared_ptr<PushNotificationContext> context = make_shared<PushNotificationContext>(transaction, mAPNS, request);
						context->start(mTimeout);
						transaction->setProperty(getModuleName(), context);
					}
				}catch(exception &e){
					LOGE("Could not create push notification.");
				}
			}
		}
	}
}

void PushNotification::onResponse(std::shared_ptr<ResponseSipEvent> &ev) {
	shared_ptr<OutgoingTransaction> transaction = dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
	if (transaction != NULL) {
		transaction->removeProperty(getModuleName());
	}
}

void PushNotification::onTransactionEvent(const shared_ptr<Transaction> &transaction, Transaction::Event event) {
	shared_ptr<OutgoingTransaction> ot = dynamic_pointer_cast<OutgoingTransaction>(transaction);
	if (ot != NULL) {
		switch (event) {
		case Transaction::Destroy:
			transaction->removeProperty(getModuleName());
			break;

		case Transaction::Create:
			break;
		}
	}
}
<|endoftext|>


<commit_before>#include "openmc/source.h"

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#define HAS_DYNAMIC_LINKING
#endif

#include <algorithm> // for move

#ifdef HAS_DYNAMIC_LINKING
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
#endif

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

std::vector<SourceDistribution> external_sources;

}

namespace {

using sample_t = Particle::Bank (*)(uint64_t* seed);
sample_t custom_source_function;
void* custom_source_library;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
    settings::path_source_library = get_node_value(node, "library", false, true);
    if (!file_exists(settings::path_source_library)) {
      fatal_error(fmt::format("Source library '{}' does not exist.",
        settings::path_source_library));
    }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (!settings::path_source.empty()) {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if (!settings::path_source_library.empty()) {

    write_message(fmt::format("Sampling from library source {}...",
      settings::path_source), 6);

    fill_source_bank_custom_source();

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // return values from custom source if using
  if (!settings::path_source_library.empty()) {
    return sample_custom_source_library(seed);
  }

  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

void load_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING

  // Open the library
  custom_source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY);
  if (!custom_source_library) {
    fatal_error("Couldn't open source library " + settings::path_source_library);
  }

  // reset errors
  dlerror();

  // get the function from the library
  using sample_t = Particle::Bank (*)(uint64_t* seed);
  custom_source_function = reinterpret_cast<sample_t>(dlsym(custom_source_library, "sample_source"));

  // check for any dlsym errors
  auto dlsym_error = dlerror();
  if (dlsym_error) {
    dlclose(custom_source_library);
    fatal_error(fmt::format("Couldn't open the sample_source symbol: {}", dlsym_error));
  }

#else
  fatal_error("Custom source libraries have not yet been implemented for "
    "non-POSIX systems");
#endif
}

void close_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING
  dlclose(custom_source_library);
#else
  fatal_error("Custom source libraries have not yet been implemented for "
              "non-POSIX systems");
#endif
}

Particle::Bank sample_custom_source_library(uint64_t* seed)
{
  return custom_source_function(seed);
}

void fill_source_bank_custom_source()
{
  // Load the custom library
  load_custom_source_library();

  // Generation source sites from specified distribution in the
  // library source
  for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
    // initialize random number seed
    int64_t id = (simulation::total_gen + overall_generation()) *
      settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
     uint64_t seed = init_seed(id, STREAM_SOURCE);

    // sample custom library source
    simulation::source_bank[i] = sample_custom_source_library(&seed);
  }

  // release the library
  close_custom_source_library();
}

} // namespace openmc
<commit_msg>Load new serializable form of source function<commit_after>#include "openmc/source.h"

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#define HAS_DYNAMIC_LINKING
#endif

#include <algorithm> // for move

#ifdef HAS_DYNAMIC_LINKING
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
#endif

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

std::vector<SourceDistribution> external_sources;

}

namespace {

using sample_t = Particle::Bank (*)(uint64_t* seed);
sample_t custom_source_function;
std::string serialization;
using serialized_sample_t = Particle::Bank (*)(uint64_t* seed, const char* serialization);
serialized_sample_t custom_serialized_source_function;
void* custom_source_library;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
    settings::path_source_library = get_node_value(node, "library", false, true);
    if (!file_exists(settings::path_source_library)) {
      fatal_error(fmt::format("Source library '{}' does not exist.",
        settings::path_source_library));
    }

    if (check_for_node(node, "serialization")) {
      serialization = get_node_value(node, "serialization", false, true);
    }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (!settings::path_source.empty()) {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if (!settings::path_source_library.empty()) {

    write_message(fmt::format("Sampling from library source {}...",
      settings::path_source), 6);

    fill_source_bank_custom_source();

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // return values from custom source if using
  if (!settings::path_source_library.empty()) {
    return sample_custom_source_library(seed);
  }

  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

void load_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING

  // Open the library
  custom_source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY);
  if (!custom_source_library) {
    fatal_error("Couldn't open source library " + settings::path_source_library);
  }

  // reset errors
  dlerror();

  if (serialization.empty()) {
    // get the function from the library
    using sample_t = Particle::Bank (*)(uint64_t* seed);
    custom_source_function = reinterpret_cast<sample_t>(dlsym(custom_source_library, "sample_source"));
  } else {
    // get the function from the library using the provided serialization
    using sample_t = Particle::Bank (*)(uint64_t* seed, const char* serialization);
    custom_serialized_source_function = reinterpret_cast<sample_t>(dlsym(custom_source_library, "sample_source"));
  }

  // check for any dlsym errors
  auto dlsym_error = dlerror();
  if (dlsym_error) {
    dlclose(custom_source_library);
    fatal_error(fmt::format("Couldn't open the sample_source symbol: {}", dlsym_error));
  }

#else
  fatal_error("Custom source libraries have not yet been implemented for "
    "non-POSIX systems");
#endif
}

void close_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING
  dlclose(custom_source_library);
#else
  fatal_error("Custom source libraries have not yet been implemented for "
              "non-POSIX systems");
#endif
}

Particle::Bank sample_custom_source_library(uint64_t* seed)
{
  if (serialization.empty()) {
    return custom_source_function(seed);
  } else {
    return custom_serialized_source_function(seed, serialization.c_str());
  }
}

void fill_source_bank_custom_source()
{
  // Load the custom library
  load_custom_source_library();

  // Generation source sites from specified distribution in the
  // library source
  for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
    // initialize random number seed
    int64_t id = (simulation::total_gen + overall_generation()) *
      settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
     uint64_t seed = init_seed(id, STREAM_SOURCE);

    // sample custom library source
    simulation::source_bank[i] = sample_custom_source_library(&seed);
  }

  // release the library
  close_custom_source_library();
}

} // namespace openmc
<|endoftext|>