<commit_before>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
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 author 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/file.hpp"
#include "libtorrent/utf8.hpp"

#include <sstream>
#include <windows.h>

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_localfree
	{
	public:
		auto_localfree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_localfree()
		{
			if (m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	std::wstring safe_convert(std::string const& s)
	{
		try
		{
			return libtorrent::utf8_wchar(s);
		}
		catch (std::exception)
		{
			std::wstring ret;
			for (const char* i = &*s.begin(); i < &*s.end(); ++i)
			{
				wchar_t c;
				c = '.';
				std::mbtowc(&c, i, 1);
				ret += c;
			}
			return ret;
		}
	}

	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			ret.resize(size-1);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}

	void throw_exception(const char* thrower)
	{
		DWORD err = GetLastError();

#ifdef UNICODE
		wchar_t *wbuffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
		auto_localfree auto_free(wbuffer);
		std::string tmp_utf8;
		libtorrent::wchar_utf8(wbuffer, tmp_utf8);
		char const* buffer = tmp_utf8.c_str();
#else
		char* buffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPSTR)&buffer, 0, 0);
		auto_localfree auto_free(buffer);
#endif

		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

		#ifdef UNICODE
			std::wstring wfile_name(safe_convert(file_name));
			HANDLE new_handle = CreateFile(
				(LPCWSTR)wfile_name.c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#else
			HANDLE new_handle = CreateFile(
				utf8_native(file_name).c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#endif

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				throw_exception(file_name);
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
				throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		assert(p.is_complete());
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Magnus Jonsson & Arvid Norberg
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 author 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/file.hpp"
#include "libtorrent/utf8.hpp"

#include <sstream>
#include <windows.h>

namespace
{
	// must be used to not leak memory in case something would throw
	class auto_localfree
	{
	public:
		auto_localfree(HLOCAL memory)
			: m_memory(memory)
		{
		}
		~auto_localfree()
		{
			if (m_memory)
				LocalFree(m_memory);
		}
	private:
		HLOCAL m_memory;
	};

	std::wstring safe_convert(std::string const& s)
	{
		try
		{
			return libtorrent::utf8_wchar(s);
		}
		catch (std::exception)
		{
			std::wstring ret;
			for (const char* i = &*s.begin(); i < &*s.end(); ++i)
			{
				wchar_t c;
				c = '.';
				std::mbtowc(&c, i, 1);
				ret += c;
			}
			return ret;
		}
	}

	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}

	void throw_exception(const char* thrower)
	{
		DWORD err = GetLastError();

#ifdef UNICODE
		wchar_t *wbuffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
		auto_localfree auto_free(wbuffer);
		std::string tmp_utf8;
		libtorrent::wchar_utf8(wbuffer, tmp_utf8);
		char const* buffer = tmp_utf8.c_str();
#else
		char* buffer = 0;
		FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM
			|FORMAT_MESSAGE_ALLOCATE_BUFFER
			, 0, err, 0, (LPSTR)&buffer, 0, 0);
		auto_localfree auto_free(buffer);
#endif

		std::stringstream s;
		s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");

		throw libtorrent::file_error(s.str());
	}
}

namespace libtorrent
{

	struct file::impl : boost::noncopyable
	{
		enum open_flags
		{
			read_flag = 1,
			write_flag = 2
		};

		enum seek_mode
		{
			seek_begin = FILE_BEGIN,
			seek_from_here = FILE_CURRENT,
			seek_end = FILE_END
		};

		impl()
		{
			m_file_handle = INVALID_HANDLE_VALUE;
		}

		void open(const char *file_name, open_flags flags)
		{
			assert(file_name);
			assert(flags & (read_flag | write_flag));

			DWORD access_mask = 0;
			if (flags & read_flag)
				access_mask |= GENERIC_READ;
			if (flags & write_flag)
				access_mask |= GENERIC_WRITE;

			assert(access_mask & (GENERIC_READ | GENERIC_WRITE));

		#ifdef UNICODE
			std::wstring wfile_name(safe_convert(file_name));
			HANDLE new_handle = CreateFile(
				(LPCWSTR)wfile_name.c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#else
			HANDLE new_handle = CreateFile(
				utf8_native(file_name).c_str()
				, access_mask
				, FILE_SHARE_READ
				, 0
				, (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING
				, FILE_ATTRIBUTE_NORMAL
				, 0);
		#endif

			if (new_handle == INVALID_HANDLE_VALUE)
			{
				std::stringstream s;
				throw_exception(file_name);
			}
			// will only close old file if the open succeeded
			close();
			m_file_handle = new_handle;
		}

		void close()
		{
			if (m_file_handle != INVALID_HANDLE_VALUE)
			{
				CloseHandle(m_file_handle);
				m_file_handle = INVALID_HANDLE_VALUE;
			}
		}

		~impl()
		{
			close();
		}

		size_type write(const char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);
			DWORD bytes_written = 0;
			if (num_bytes != 0)
			{
				if (FALSE == WriteFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_written
					, 0))
				{
					throw_exception("file::write");
				}
			}
			return bytes_written;
		}

		size_type read(char* buffer, size_type num_bytes)
		{
			assert(buffer);
			assert(num_bytes > 0);
			assert((DWORD)num_bytes == num_bytes);

			DWORD bytes_read = 0;
			if (num_bytes != 0)
			{
				if (FALSE == ReadFile(
					m_file_handle
					, buffer
					, (DWORD)num_bytes
					, &bytes_read
					, 0))
				{
					throw_exception("file::read");
				}
			}
			return bytes_read;
		}

		void seek(size_type pos, seek_mode from_where)
		{
			assert(pos >= 0 || from_where != seek_begin);
			assert(pos <= 0 || from_where != seek_end);
			LARGE_INTEGER offs;
			offs.QuadPart = pos;
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, from_where))
			{
				throw_exception("file::seek");
			}
		}

		size_type tell()
		{
			LARGE_INTEGER offs;
			offs.QuadPart = 0;

			// is there any other way to get offset?
			if (FALSE == SetFilePointerEx(
				m_file_handle
				, offs
				, &offs
				, FILE_CURRENT))
			{
				throw_exception("file::tell");
			}

			size_type pos=offs.QuadPart;
			assert(pos>=0);
			return pos;
		}
/*
		size_type size()
		{
			LARGE_INTEGER s;
			if (FALSE == GetFileSizeEx(m_file_handle, &s))
			{
				throw_exception("file::size");
			}

			size_type size = s.QuadPart;
			assert(size >= 0);
			return size;
		}
*/
	private:

		HANDLE m_file_handle;

	};
}

namespace libtorrent
{

	const file::seek_mode file::begin(file::impl::seek_begin);
	const file::seek_mode file::end(file::impl::seek_end);

	const file::open_mode file::in(file::impl::read_flag);
	const file::open_mode file::out(file::impl::write_flag);

	file::file()
		: m_impl(new libtorrent::file::impl())
	{
	}
	file::file(boost::filesystem::path const& p, open_mode m)
		: m_impl(new libtorrent::file::impl())
	{
		open(p,m);
	}

	file::~file()
	{
	}

	void file::open(boost::filesystem::path const& p, open_mode m)
	{
		assert(p.is_complete());
		m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buffer, size_type num_bytes)
	{
		return m_impl->write(buffer, num_bytes);
	}

	size_type file::read(char* buffer, size_type num_bytes)
	{
		return m_impl->read(buffer, num_bytes);
	}

	void file::seek(size_type pos, seek_mode m)
	{
		m_impl->seek(pos,impl::seek_mode(m.m_val));
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}
}
<|endoftext|>


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

#include "openmc/bank.h"
#include "openmc/capi.h"
#include "openmc/cmfd_solver.h"
#include "openmc/constants.h"
#include "openmc/cross_sections.h"
#include "openmc/dagmc.h"
#include "openmc/eigenvalue.h"
#include "openmc/geometry.h"
#include "openmc/geometry_aux.h"
#include "openmc/material.h"
#include "openmc/mesh.h"
#include "openmc/message_passing.h"
#include "openmc/nuclide.h"
#include "openmc/photon.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/source.h"
#include "openmc/surface.h"
#include "openmc/thermal.h"
#include "openmc/timer.h"
#include "openmc/tallies/tally.h"
#include "openmc/volume_calc.h"

#include "xtensor/xview.hpp"

namespace openmc {

void free_memory()
{
  free_memory_geometry();
  free_memory_surfaces();
  free_memory_material();
  free_memory_volume();
  free_memory_simulation();
  free_memory_photon();
  free_memory_settings();
  free_memory_thermal();
  library_clear();
  nuclides_clear();
  free_memory_source();
  free_memory_mesh();
  free_memory_tally();
  free_memory_bank();
  free_memory_cmfd();
#ifdef DAGMC
  free_memory_dagmc();
#endif
}

}

using namespace openmc;

int openmc_finalize()
{
  // Clear results
  openmc_reset();

  // Reset timers
  reset_timers();

  // Reset global variables
  settings::assume_separate = false;
  settings::check_overlaps = false;
  settings::confidence_intervals = false;
  settings::create_fission_neutrons = true;
  settings::electron_treatment = ELECTRON_LED;
  settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0};
  settings::entropy_on = false;
  settings::gen_per_batch = 1;
  settings::legendre_to_tabular = true;
  settings::legendre_to_tabular_points = -1;
  settings::n_particles = -1;
  settings::output_summary = true;
  settings::output_tallies = true;
  settings::particle_restart_run = false;
  settings::photon_transport = false;
  settings::reduce_tallies = true;
  settings::res_scat_on = false;
  settings::res_scat_method = ResScatMethod::rvs;
  settings::res_scat_energy_min = 0.01;
  settings::res_scat_energy_max = 1000.0;
  settings::restart_run = false;
  settings::run_CE = true;
  settings::run_mode = -1;
  settings::dagmc = false;
  settings::source_latest = false;
  settings::source_separate = false;
  settings::source_write = true;
  settings::survival_biasing = false;
  settings::temperature_default = 293.6;
  settings::temperature_method = TEMPERATURE_NEAREST;
  settings::temperature_multipole = false;
  settings::temperature_range = {0.0, 0.0};
  settings::temperature_tolerance = 10.0;
  settings::trigger_on = false;
  settings::trigger_predict = false;
  settings::trigger_batch_interval = 1;
  settings::ufs_on = false;
  settings::urr_ptables_on = true;
  settings::verbosity = 7;
  settings::weight_cutoff = 0.25;
  settings::weight_survive = 1.0;
  settings::write_all_tracks = false;
  settings::write_initial_source = false;

  simulation::keff = 1.0;
  simulation::n_lost_particles = 0;
  simulation::satisfy_triggers = false;
  simulation::total_gen = 0;

  simulation::entropy_mesh = nullptr;
  simulation::ufs_mesh = nullptr;

  data::energy_max = {INFTY, INFTY};
  data::energy_min = {0.0, 0.0};
  data::temperature_min = 0.0;
  data::temperature_max = INFTY;
  model::root_universe = -1;
  openmc::openmc_set_seed(DEFAULT_SEED);

  // Deallocate arrays
  free_memory();

  // Free all MPI types
#ifdef OPENMC_MPI
  int init_called;
  MPI_Initialized(&init_called);
  if (init_called) MPI_Type_free(&mpi::bank);
#endif

  return 0;
}

int openmc_reset()
{
  for (auto& t : model::tallies) {
    t->reset();
  }

  // Reset global tallies
  simulation::n_realizations = 0;
  xt::view(simulation::global_tallies, xt::all()) = 0.0;

  simulation::k_col_abs = 0.0;
  simulation::k_col_tra = 0.0;
  simulation::k_abs_tra = 0.0;
  simulation::k_sum = {0.0, 0.0};

  return 0;
}

int openmc_hard_reset()
{
  // Reset all tallies and timers
  openmc_reset();
  reset_timers();

  // Reset total generations and keff guess
  simulation::keff = 1.0;
  simulation::total_gen = 0;

  // Reset the random number generator state
  openmc::openmc_set_seed(DEFAULT_SEED);
  return 0;
}
<commit_msg>Better conditional for call to MPI_Type_free (thanks Cliff Dugal)<commit_after>#include "openmc/finalize.h"

#include "openmc/bank.h"
#include "openmc/capi.h"
#include "openmc/cmfd_solver.h"
#include "openmc/constants.h"
#include "openmc/cross_sections.h"
#include "openmc/dagmc.h"
#include "openmc/eigenvalue.h"
#include "openmc/geometry.h"
#include "openmc/geometry_aux.h"
#include "openmc/material.h"
#include "openmc/mesh.h"
#include "openmc/message_passing.h"
#include "openmc/nuclide.h"
#include "openmc/photon.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/source.h"
#include "openmc/surface.h"
#include "openmc/thermal.h"
#include "openmc/timer.h"
#include "openmc/tallies/tally.h"
#include "openmc/volume_calc.h"

#include "xtensor/xview.hpp"

namespace openmc {

void free_memory()
{
  free_memory_geometry();
  free_memory_surfaces();
  free_memory_material();
  free_memory_volume();
  free_memory_simulation();
  free_memory_photon();
  free_memory_settings();
  free_memory_thermal();
  library_clear();
  nuclides_clear();
  free_memory_source();
  free_memory_mesh();
  free_memory_tally();
  free_memory_bank();
  free_memory_cmfd();
#ifdef DAGMC
  free_memory_dagmc();
#endif
}

}

using namespace openmc;

int openmc_finalize()
{
  // Clear results
  openmc_reset();

  // Reset timers
  reset_timers();

  // Reset global variables
  settings::assume_separate = false;
  settings::check_overlaps = false;
  settings::confidence_intervals = false;
  settings::create_fission_neutrons = true;
  settings::electron_treatment = ELECTRON_LED;
  settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0};
  settings::entropy_on = false;
  settings::gen_per_batch = 1;
  settings::legendre_to_tabular = true;
  settings::legendre_to_tabular_points = -1;
  settings::n_particles = -1;
  settings::output_summary = true;
  settings::output_tallies = true;
  settings::particle_restart_run = false;
  settings::photon_transport = false;
  settings::reduce_tallies = true;
  settings::res_scat_on = false;
  settings::res_scat_method = ResScatMethod::rvs;
  settings::res_scat_energy_min = 0.01;
  settings::res_scat_energy_max = 1000.0;
  settings::restart_run = false;
  settings::run_CE = true;
  settings::run_mode = -1;
  settings::dagmc = false;
  settings::source_latest = false;
  settings::source_separate = false;
  settings::source_write = true;
  settings::survival_biasing = false;
  settings::temperature_default = 293.6;
  settings::temperature_method = TEMPERATURE_NEAREST;
  settings::temperature_multipole = false;
  settings::temperature_range = {0.0, 0.0};
  settings::temperature_tolerance = 10.0;
  settings::trigger_on = false;
  settings::trigger_predict = false;
  settings::trigger_batch_interval = 1;
  settings::ufs_on = false;
  settings::urr_ptables_on = true;
  settings::verbosity = 7;
  settings::weight_cutoff = 0.25;
  settings::weight_survive = 1.0;
  settings::write_all_tracks = false;
  settings::write_initial_source = false;

  simulation::keff = 1.0;
  simulation::n_lost_particles = 0;
  simulation::satisfy_triggers = false;
  simulation::total_gen = 0;

  simulation::entropy_mesh = nullptr;
  simulation::ufs_mesh = nullptr;

  data::energy_max = {INFTY, INFTY};
  data::energy_min = {0.0, 0.0};
  data::temperature_min = 0.0;
  data::temperature_max = INFTY;
  model::root_universe = -1;
  openmc::openmc_set_seed(DEFAULT_SEED);

  // Deallocate arrays
  free_memory();

  // Free all MPI types
#ifdef OPENMC_MPI
  if (mpi::bank != MPI_DATATYPE_NULL) MPI_Type_free(&mpi::bank);
#endif

  return 0;
}

int openmc_reset()
{
  for (auto& t : model::tallies) {
    t->reset();
  }

  // Reset global tallies
  simulation::n_realizations = 0;
  xt::view(simulation::global_tallies, xt::all()) = 0.0;

  simulation::k_col_abs = 0.0;
  simulation::k_col_tra = 0.0;
  simulation::k_abs_tra = 0.0;
  simulation::k_sum = {0.0, 0.0};

  return 0;
}

int openmc_hard_reset()
{
  // Reset all tallies and timers
  openmc_reset();
  reset_timers();

  // Reset total generations and keff guess
  simulation::keff = 1.0;
  simulation::total_gen = 0;

  // Reset the random number generator state
  openmc::openmc_set_seed(DEFAULT_SEED);
  return 0;
}
<|endoftext|>


<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 2
 * of the License, or 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

#include "image_reader.hh"
#include <tiffio.h>
#include <iostream>

namespace mapnik
{

    class TiffReader : public ImageReader
    {
    private:
        std::string file_name_;
        int read_method_;
        unsigned width_;
        unsigned height_;
        int rows_per_strip_;
        int tile_width_;
        int tile_height_;
    public:
        enum
	{
	    generic=1,
	    stripped,
	    tiled
	};
        explicit TiffReader(const std::string& file_name);
        virtual ~TiffReader();
        unsigned width() const;
        unsigned height() const;
        void read(unsigned x,unsigned y,ImageData32& image);
    private:
        TiffReader(const TiffReader&);
        TiffReader& operator=(const TiffReader&);
        void init();
        void read_generic(unsigned x,unsigned y,ImageData32& image);
        void read_stripped(unsigned x,unsigned y,ImageData32& image);
        void read_tiled(unsigned x,unsigned y,ImageData32& image);
    };

    namespace
    {
	ImageReader* createTiffReader(const std::string& file)
	{
	    return new TiffReader(file);
	}

	const bool registered = register_image_reader("tiff",createTiffReader);
    }

    TiffReader::TiffReader(const std::string& file_name)
	: file_name_(file_name),
	  read_method_(generic),
	  width_(0),
	  height_(0),
	  rows_per_strip_(0),
	  tile_width_(0),
	  tile_height_(0)
    {
	try
	{
	    init();
	}
	catch (ImageReaderException& ex)
	{
	    std::cerr<<ex.what()<<std::endl;
	    throw;
	}
    }

    void TiffReader::init()
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (!tif) throw ImageReaderException("cannot open "+file_name_);
	char msg[1024];

	if (TIFFRGBAImageOK(tif,msg))
	{
	    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_);
	    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_);
	    if (TIFFIsTiled(tif))
	    {
		TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width_);
		TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height_);
		read_method_=tiled;
	    }
	    else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0)
	    {
		read_method_=stripped;
	    }
	    TIFFClose(tif);
	}
	else
	{
	    TIFFClose(tif);
	    throw ImageReaderException(msg);
	}
    }

    TiffReader::~TiffReader()
    {
	//
    }

    unsigned TiffReader::width() const
    {
	return width_;
    }

    unsigned TiffReader::height() const
    {
	return height_;
    }

    void TiffReader::read(unsigned x,unsigned y,ImageData32& image)
    {
	if (read_method_==stripped)
	{
	    read_stripped(x,y,image);
	}
	else if (read_method_==tiled)
	{
	    read_tiled(x,y,image);
	}
	else
	{
	    read_generic(x,y,image);
	}
    }

    void TiffReader::read_generic(unsigned x,unsigned y,ImageData32& image)
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    //todo
	    TIFFClose(tif);
	}
    }

    void TiffReader::read_tiled(unsigned x0,unsigned y0,ImageData32& image)
    {

	TIFF* tif=TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    uint32* buf = (uint32*)_TIFFmalloc(tile_width_*tile_height_*sizeof(uint32));
	    int width=image.width();
	    int height=image.height();

	    int start_y=(y0/tile_height_)*tile_height_;
	    int end_y=((y0+height)/tile_height_+1)*tile_height_;

	    int start_x=(x0/tile_width_)*tile_width_;
	    int end_x=((x0+width)/tile_width_+1)*tile_width_;

	    int row=0;
	    int tx0,tx1,ty0,ty1;
	    for (int y=start_y;y<end_y;y+=tile_height_)
	    {
		ty0=std::max(y0,(unsigned)y)-y;
		ty1=std::min(height+y0,(unsigned)(y+tile_height_))-y;
		for (int x=start_x;x<end_x;x+=tile_width_)
		{

		    if (!TIFFReadRGBATile(tif,x,y,buf)) break;

		    tx0=std::max(x0,(unsigned)x)-x;
		    tx1=std::min(width+x0,(unsigned)(x+tile_width_))-x;

		    row=y+ty0-y0;
		    for (int n=tile_height_-ty0-1;n>=tile_height_-ty1;--n)
		    {
			image.setRow(row,x+tx0-x0,x+tx1-x0,(const unsigned*)&buf[n*tile_width_+tx0]);
			++row;
		    }
		}
	    }
	    _TIFFfree(buf);
	    TIFFClose(tif);
	}
    }

    void TiffReader::read_stripped(unsigned x,unsigned  y,ImageData32& image)
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    uint32* buf = (uint32*)_TIFFmalloc(width_*rows_per_strip_*sizeof(uint32));
	    int width=image.width();
	    int height=image.height();

	    int start=(y/rows_per_strip_)*rows_per_strip_;
	    int end=((y+height)/rows_per_strip_+1)*rows_per_strip_;
	    int extra=y%rows_per_strip_;
	    int j=-extra;
	    int w=std::min(width_,(unsigned)width);//todo should be unsigned
	    for (int row=start; row < end; row+=rows_per_strip_)
	    {
		if (!TIFFReadRGBAStrip(tif,row,buf)) break;
		for (int i=rows_per_strip_-1;i>=0;--i)
		{
		    if (j>=0 && j<height)
		    {
			image.setRow(j,(const unsigned*)&buf[i*width_+x],
				     w*sizeof(uint32));
		    }
		    ++j;
		}
	    }
	    _TIFFfree(buf);
	    TIFFClose(tif);
	}
    }
}

<commit_msg>fixed: reading tiled and stripped TIFFs<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 2
 * of the License, or 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

#include "image_reader.hh"
#include <tiffio.h>
#include <iostream>

namespace mapnik
{

    class TiffReader : public ImageReader
    {
    private:
        std::string file_name_;
        int read_method_;
        unsigned width_;
        unsigned height_;
        int rows_per_strip_;
        int tile_width_;
        int tile_height_;
    public:
        enum
	{
	    generic=1,
	    stripped,
	    tiled
	};
        explicit TiffReader(const std::string& file_name);
        virtual ~TiffReader();
        unsigned width() const;
        unsigned height() const;
        void read(unsigned x,unsigned y,ImageData32& image);
    private:
        TiffReader(const TiffReader&);
        TiffReader& operator=(const TiffReader&);
        void init();
        void read_generic(unsigned x,unsigned y,ImageData32& image);
        void read_stripped(unsigned x,unsigned y,ImageData32& image);
        void read_tiled(unsigned x,unsigned y,ImageData32& image);
    };

    namespace
    {
	ImageReader* createTiffReader(const std::string& file)
	{
	    return new TiffReader(file);
	}

	const bool registered = register_image_reader("tiff",createTiffReader);
    }

    TiffReader::TiffReader(const std::string& file_name)
	: file_name_(file_name),
	  read_method_(generic),
	  width_(0),
	  height_(0),
	  rows_per_strip_(0),
	  tile_width_(0),
	  tile_height_(0)
    {
	try
	{
	    init();
	}
	catch (ImageReaderException& ex)
	{
	    std::cerr<<ex.what()<<std::endl;
	    throw;
	}
    }

    void TiffReader::init()
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (!tif) throw ImageReaderException("cannot open "+file_name_);
	char msg[1024];

	if (TIFFRGBAImageOK(tif,msg))
	{
	    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_);
	    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_);
	    if (TIFFIsTiled(tif))
	    {
		TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width_);
		TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height_);
		read_method_=tiled;
	    }
	    else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0)
	    {
		read_method_=stripped;
	    }
	    TIFFClose(tif);
	}
	else
	{
	    TIFFClose(tif);
	    throw ImageReaderException(msg);
	}
    }

    TiffReader::~TiffReader()
    {
	//
    }

    unsigned TiffReader::width() const
    {
	return width_;
    }

    unsigned TiffReader::height() const
    {
	return height_;
    }

    void TiffReader::read(unsigned x,unsigned y,ImageData32& image)
    {
	if (read_method_==stripped)
	{
	    read_stripped(x,y,image);
	}
	else if (read_method_==tiled)
	{
	    read_tiled(x,y,image);
	}
	else
	{
	    read_generic(x,y,image);
	}
    }

    void TiffReader::read_generic(unsigned x,unsigned y,ImageData32& image)
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    std::cerr<<"TODO:tiff is not stripped or tiled\n";
	    TIFFClose(tif);
	}
    }

    void TiffReader::read_tiled(unsigned x0,unsigned y0,ImageData32& image)
    {
	TIFF* tif=TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    uint32* buf = (uint32*)_TIFFmalloc(tile_width_*tile_height_*sizeof(uint32));
	    int width=image.width();
	    int height=image.height();

	    int start_y=(y0/tile_height_)*tile_height_;
	    int end_y=((y0+height)/tile_height_+1)*tile_height_;
	    bool bottomtiles=((unsigned)end_y > height_)?true:false;

	    int start_x=(x0/tile_width_)*tile_width_;
	    int end_x=((x0+width)/tile_width_+1)*tile_width_;

	    int row,tx0,tx1,ty0,ty1;
	    for (int y=start_y;y<end_y;y+=tile_height_)
	    {
		ty0=std::max(y0,(unsigned)y)-y;
		ty1=std::min(height+y0,(unsigned)(y+tile_height_))-y;

		int n0=bottomtiles ? 0:(tile_height_-ty1);
		int n1=bottomtiles ? (ty1-ty0-1):(tile_height_-ty0-1);

		for (int x=start_x;x<end_x;x+=tile_width_)
		{

		    if (!TIFFReadRGBATile(tif,x,y,buf)) break;

		    tx0=std::max(x0,(unsigned)x);
		    tx1=std::min(width+x0,(unsigned)(x+tile_width_));

		    row=y+ty0-y0;
		    for (int n=n1;n>=n0;--n)
		    {
			image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*tile_width_+tx0-x]);
			++row;
		    }
		}
	    }
	    _TIFFfree(buf);
	    TIFFClose(tif);
	}
    }

    void TiffReader::read_stripped(unsigned x0,unsigned y0,ImageData32& image)
    {
	TIFF* tif = TIFFOpen(file_name_.c_str(), "r");
	if (tif)
	{
	    uint32* buf = (uint32*)_TIFFmalloc(width_*rows_per_strip_*sizeof(uint32));

	    int width=image.width();
	    int height=image.height();

	    int start_y=(y0/rows_per_strip_)*rows_per_strip_;
	    int end_y=((y0+height)/rows_per_strip_+1)*rows_per_strip_;
	    bool laststrip=((unsigned)end_y > height_)?true:false;
	    int row,tx0,tx1,ty0,ty1;

	    tx0=x0;
	    tx1=std::min(width+x0,(unsigned)width_);

	    for (unsigned y=start_y; y < end_y; y+=rows_per_strip_)
	    {
		ty0=std::max(y0,y)-y;
		ty1=std::min(height+y0,y+rows_per_strip_)-y;
		memset(buf,0xff,width_*rows_per_strip_*sizeof(uint32));
		if (!TIFFReadRGBAStrip(tif,y,buf)) break;

		row=y+ty0-y0;

		int n0=laststrip ? 0:(rows_per_strip_-ty1);
		int n1=laststrip ? (ty1-ty0-1):(rows_per_strip_-ty0-1);
		for (int n=n1;n>=n0;--n)
		{
		    image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*width_+tx0]);
		    ++row;
		}
	    }
	    _TIFFfree(buf);
	    TIFFClose(tif);
	}
    }
}

<|endoftext|>


<commit_before>#include <algorithm>

#include <QFileDialog>
#include <QMessageBox>

#include "fish_annotator/common/species_dialog.h"
#include "fish_annotator/image_annotator/mainwindow.h"
#include "ui_mainwindow.h"

namespace fish_annotator { namespace image_annotator {

namespace fs = boost::filesystem;

namespace { //anonymous

static const std::vector<std::string> kDirExtensions = {
  ".jpg", ".png", ".bmp", ".tif", ".jpeg",
  ".JPG", ".PNG", ".BMP", ".TIF", ".JPEG"};

} // anonymous namespace

MainWindow::MainWindow(QWidget *parent)
  : annotations_(new ImageAnnotationList)
  , scene_(new QGraphicsScene)
  , ui_(new Ui::MainWidget)
  , species_controls_(new SpeciesControls(this))
  , image_files_() {
  ui_->setupUi(this);
#ifdef _WIN32
  setWindowIcon(QIcon(":/icons/FishAnnotator.ico"));
#endif
  setStyleSheet("QPushButton { background-color: rgb(230, 230, 230);"
	  "border-style: outset; border-radius: 5px; border-width: 2px; "
    "border-color: grey; padding: 6px;}"
	  "QPushButton:pressed{background-color: rgb(190, 190, 190); "
    "border-style: outset; border-radius: 5px;"
	  "border-width: 2px; border-color: grey; padding: 6px;}");
  ui_->next->setEnabled(false);
  ui_->prev->setEnabled(false);
  ui_->saveAnnotations->setEnabled(false);
  ui_->imageSlider->setEnabled(false);
  ui_->sideBarLayout->addWidget(species_controls_.get());
  QObject::connect(species_controls_.get(),
      SIGNAL(individualAdded(std::string, std::string)),
      this, SLOT(addIndividual(std::string, std::string)));
}

void MainWindow::on_next_clicked() {
  int next_val = ui_->imageSlider->value() + 1;
  if(next_val <= ui_->imageSlider->maximum()) {
    ui_->imageSlider->setValue(next_val);
  }
}

void MainWindow::on_prev_clicked() {
  int prev_val = ui_->imageSlider->value() - 1;
  if(prev_val >= ui_->imageSlider->minimum()) {
    ui_->imageSlider->setValue(prev_val);
  }
}

void MainWindow::on_loadImageDir_clicked() {
  QString image_dir = QFileDialog::getExistingDirectory(this,
    "Select an image directory.");
  if(!image_dir.isEmpty()) {
    onLoadDirectorySuccess(image_dir);
  }
}

void MainWindow::on_saveAnnotations_clicked() {
  if(image_files_.size() > 0) {
    annotations_->write(image_files_);
  }
}

void MainWindow::on_imageSlider_valueChanged() {
  scene_->clear();
  ui_->idSelection->clear();
  ui_->speciesValue->setText("");
  ui_->subspeciesValue->setText("");
#ifdef _WIN32
  QString filename(image_files_[ui_->imageSlider->value()].string().c_str());
#else
  QString filename(image_files_[ui_->imageSlider->value()].c_str());
#endif
  QImage current(filename);
  if(!current.isNull()) {
    scene_->addPixmap(QPixmap::fromImage(current));
    scene_->setSceneRect(current.rect());
    ui_->imageWindow->setScene(scene_.get());
    ui_->imageWindow->fitInView(scene_->sceneRect(), Qt::KeepAspectRatio);
    ui_->imageWindow->show();
    ui_->fileNameValue->setText(filename);
    fs::path img_path(filename.toStdString());
    auto annotations =
      annotations_->getImageAnnotations(img_path.filename());
    for(auto annotation : annotations) {
      if(ui_->showAnnotations->isChecked()) {
          auto region = new AnnotatedRegion<ImageAnnotation>(
                annotation->id_, annotation, current.rect());
          scene_->addItem(region);
      }
      ui_->idSelection->addItem(QString::number(annotation->id_));
    }
    species_controls_->resetCounts();
    auto counts = annotations_->getCounts(filename.toStdString());
    for(auto it = counts.begin(); it != counts.end(); it++) {
      species_controls_->setCount(it->second, it->first);
    }
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", std::string(
        std::string("Error loading image ")
      + filename.toStdString()
      + std::string(".")).c_str());
  }
}

void MainWindow::on_showAnnotations_stateChanged() {
  on_imageSlider_valueChanged();
}

void MainWindow::on_idSelection_currentIndexChanged(const QString &id) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    auto annotations =
      annotations_->getImageAnnotations(current_image);
    for(auto annotation : annotations) {
      if(annotation->id_ == id.toInt()) {
        ui_->speciesValue->setText(annotation->species_.c_str());
        ui_->subspeciesValue->setText(annotation->subspecies_.c_str());
      }
    }
  }
}

void MainWindow::on_removeAnnotation_clicked() {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    int id = ui_->idSelection->currentText().toInt();
    annotations_->remove(current_image, id);
    on_imageSlider_valueChanged();
  }
}

void MainWindow::addIndividual(std::string species, std::string subspecies) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    uint64_t id = annotations_->nextId(current_image);
    auto annotation = std::make_shared<ImageAnnotation>(
      current_image.filename().string(), species, subspecies, id,
      Rect(0, 0, 0, 0));
    annotations_->insert(annotation);
    on_imageSlider_valueChanged();
  }
}

void MainWindow::onLoadDirectorySuccess(const QString &image_dir) {
  image_files_.clear();
  fs::directory_iterator dir_it(image_dir.toStdString());
  fs::directory_iterator dir_end;
  for(; dir_it != dir_end; ++dir_it) {
    fs::path ext(dir_it->path().extension());
    for(auto &ok_ext : kDirExtensions) {
      if(ext == ok_ext) {
        image_files_.push_back(dir_it->path());
      }
    }
  }
  std::sort(image_files_.begin(), image_files_.end());
  if(image_files_.size() > 0) {
    ui_->next->setEnabled(true);
    ui_->prev->setEnabled(true);
    ui_->saveAnnotations->setEnabled(true);
    ui_->imageSlider->setEnabled(true);
    ui_->imageSlider->setMinimum(0);
    ui_->imageSlider->setMaximum(static_cast<int>(image_files_.size() - 1));
    ui_->imageSlider->setSingleStep(1);
    ui_->imageSlider->setValue(0);
    annotations_->read(image_files_);
    species_controls_->loadFromVector(annotations_->getAllSpecies());
    on_imageSlider_valueChanged();
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", "No images found in this directory.");
  }
}

#include "../../include/fish_annotator/image_annotator/moc_mainwindow.cpp"

}} // namespace fish_annotator::image_annotator
<commit_msg>Set icons on buttons, fill in values for type and subtype menus<commit_after>#include <algorithm>

#include <QFileDialog>
#include <QMessageBox>

#include "fish_annotator/common/species_dialog.h"
#include "fish_annotator/image_annotator/mainwindow.h"
#include "ui_mainwindow.h"

namespace fish_annotator { namespace image_annotator {

namespace fs = boost::filesystem;

namespace { //anonymous

static const std::vector<std::string> kDirExtensions = {
  ".jpg", ".png", ".bmp", ".tif", ".jpeg",
  ".JPG", ".PNG", ".BMP", ".TIF", ".JPEG"};

} // anonymous namespace

MainWindow::MainWindow(QWidget *parent)
  : annotations_(new ImageAnnotationList)
  , scene_(new QGraphicsScene)
  , ui_(new Ui::MainWidget)
  , species_controls_(new SpeciesControls(this))
  , image_files_() {
  ui_->setupUi(this);
#ifdef _WIN32
  setWindowIcon(QIcon(":/icons/FishAnnotator.ico"));
#endif
  setStyleSheet("QPushButton { background-color: rgb(230, 230, 230);"
	  "border-style: outset; border-radius: 5px; border-width: 2px; "
    "border-color: grey; padding: 6px;}"
	  "QPushButton:pressed{background-color: rgb(190, 190, 190); "
    "border-style: outset; border-radius: 5px;"
	  "border-width: 2px; border-color: grey; padding: 6px;}");
  ui_->next->setIcon(":/icons/image_controls/next.svg");
  ui_->prev->setIcon(":/icons/image_controls/prev.svg");
  ui_->sideBarLayout->addWidget(species_controls_.get());
  QObject::connect(species_controls_.get(),
      SIGNAL(individualAdded(std::string, std::string)),
      this, SLOT(addIndividual(std::string, std::string)));
}

void MainWindow::on_next_clicked() {
  int next_val = ui_->imageSlider->value() + 1;
  if(next_val <= ui_->imageSlider->maximum()) {
    ui_->imageSlider->setValue(next_val);
  }
}

void MainWindow::on_prev_clicked() {
  int prev_val = ui_->imageSlider->value() - 1;
  if(prev_val >= ui_->imageSlider->minimum()) {
    ui_->imageSlider->setValue(prev_val);
  }
}

void MainWindow::on_loadImageDir_triggered() {
  QString image_dir = QFileDialog::getExistingDirectory(this,
    "Select an image directory.");
  if(!image_dir.isEmpty()) {
    onLoadDirectorySuccess(image_dir);
  }
}

void MainWindow::on_saveAnnotations_triggered() {
  if(image_files_.size() > 0) {
    annotations_->write(image_files_);
  }
}

void MainWindow::on_imageSlider_valueChanged() {
  scene_->clear();
  ui_->idSelection->clear();
#ifdef _WIN32
  QString filename(image_files_[ui_->imageSlider->value()].string().c_str());
#else
  QString filename(image_files_[ui_->imageSlider->value()].c_str());
#endif
  QImage current(filename);
  if(!current.isNull()) {
    scene_->addPixmap(QPixmap::fromImage(current));
    scene_->setSceneRect(current.rect());
    ui_->imageWindow->setScene(scene_.get());
    ui_->imageWindow->fitInView(scene_->sceneRect(), Qt::KeepAspectRatio);
    ui_->imageWindow->show();
    ui_->fileNameValue->setText(filename);
    fs::path img_path(filename.toStdString());
    auto annotations =
      annotations_->getImageAnnotations(img_path.filename());
    for(auto annotation : annotations) {
      if(ui_->showAnnotations->isChecked()) {
          auto region = new AnnotatedRegion<ImageAnnotation>(
                annotation->id_, annotation, current.rect());
          scene_->addItem(region);
      }
      ui_->idSelection->addItem(QString::number(annotation->id_));
    }
    species_controls_->resetCounts();
    auto counts = annotations_->getCounts(filename.toStdString());
    for(auto it = counts.begin(); it != counts.end(); it++) {
      species_controls_->setCount(it->second, it->first);
    }
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", std::string(
        std::string("Error loading image ")
      + filename.toStdString()
      + std::string(".")).c_str());
  }
}

void MainWindow::on_showAnnotations_stateChanged() {
  on_imageSlider_valueChanged();
}

void MainWindow::on_idSelection_currentIndexChanged(const QString &id) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    auto annotations =
      annotations_->getImageAnnotations(current_image);
    for(auto annotation : annotations) {
      if(annotation->id_ == id.toInt()) {
        ui_->typeMenu->clear();
        ui_->subTypeMenu->clear();
        auto species = species_controls_->getSpecies();
        for(auto &s : species) {
          ui_->typeMenu->addItem(s.getName().c_str());
          if(s.getName() == annotation->species_) {
            ui_->typeMenu->setCurrentText(s.getName().c_str());
            auto subspecies = s.getSubspecies();
            for(auto &sub : subspecies) {
              ui_->subTypeMenu->addItem(sub.c_str());
              if(sub == annotation->subspecies_) {
                ui_->subTypeMenu->setCurrentText(sub.c_str());
              }
            }
          }
        }
      }
    }
  }
}

void on_typeMenu_activated(const QString &text) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    auto annotations =
      annotations_->getImageAnnotations(current_image);
    for(auto annotation : annotations) {
      if(annotation->id_ == id.toInt()) {
        ui_->subTypeMenu->clear();
        auto species = species_controls_->getSpecies();
        annotation->species_ = ui_->typeMenu->text().toStdString();
      }
    }
  }
}

void on_subTypeMenu_activated(const QString &text) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    auto annotations =
      annotations_->getImageAnnotations(current_image);
    for(auto annotation : annotations) {
      if(annotation->id_ == id.toInt()) {
        annotation->subspecies_ = ui_->subTypeMenu->text().toStdString();
      }
    }
  }
}

void MainWindow::on_removeAnnotation_clicked() {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    int id = ui_->idSelection->currentText().toInt();
    annotations_->remove(current_image, id);
    on_imageSlider_valueChanged();
  }
}

void MainWindow::addIndividual(std::string species, std::string subspecies) {
  if(image_files_.size() > 0 && ui_->imageSlider->isEnabled()) {
    auto current_image = image_files_[ui_->imageSlider->value()];
    uint64_t id = annotations_->nextId(current_image);
    auto annotation = std::make_shared<ImageAnnotation>(
      current_image.filename().string(), species, subspecies, id,
      Rect(0, 0, 0, 0));
    annotations_->insert(annotation);
    on_imageSlider_valueChanged();
  }
}

void MainWindow::onLoadDirectorySuccess(const QString &image_dir) {
  image_files_.clear();
  fs::directory_iterator dir_it(image_dir.toStdString());
  fs::directory_iterator dir_end;
  for(; dir_it != dir_end; ++dir_it) {
    fs::path ext(dir_it->path().extension());
    for(auto &ok_ext : kDirExtensions) {
      if(ext == ok_ext) {
        image_files_.push_back(dir_it->path());
      }
    }
  }
  std::sort(image_files_.begin(), image_files_.end());
  if(image_files_.size() > 0) {
    ui_->idLabel->setEnabled(true);
    ui_->speciesLabel->setEnabled(true);
    ui_->subspeciesLabel->setEnabled(true);
    ui_->idSelection->setEnabled(true);
    ui_->typeMenu->setEnabled(true);
    ui_->subTypeMenu->setEnabled(true);
    ui_->removeAnnotation->setEnabled(true);
    ui_->showAnnotations->setEnabled(true);
    ui_->setMetadata->setEnabled(true);
    ui_->next->setEnabled(true);
    ui_->prev->setEnabled(true);
    ui_->saveAnnotations->setEnabled(true);
    ui_->imageSlider->setEnabled(true);
    ui_->imageSlider->setMinimum(0);
    ui_->imageSlider->setMaximum(static_cast<int>(image_files_.size() - 1));
    ui_->imageSlider->setSingleStep(1);
    ui_->imageSlider->setValue(0);
    annotations_->read(image_files_);
    species_controls_->loadFromVector(annotations_->getAllSpecies());
    on_imageSlider_valueChanged();
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", "No images found in this directory.");
  }
}

#include "../../include/fish_annotator/image_annotator/moc_mainwindow.cpp"

}} // namespace fish_annotator::image_annotator
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.8  2000/09/06 14:26:24  morsch
Decayer functionality of AliPythia has been moved to AliDecayerPythia.
Class is now a singleton.

Revision 1.7  2000/06/09 20:34:50  morsch
All coding rule violations except RS3 corrected

Revision 1.6  1999/11/09 07:38:48  fca
Changes for compatibility with version 2.23 of ROOT

Revision 1.5  1999/11/03 17:43:20  fca
New version from G.Martinez & A.Morsch

Revision 1.4  1999/09/29 09:24:14  fca
Introduction of the Copyright and cvs Log

*/

#include "AliPythia.h"
#include "AliRun.h"

ClassImp(AliPythia)

//_____________________________________________________________________________

AliPythia* AliPythia::fgAliPythia=NULL;

AliPythia::AliPythia()
{
// Default Constructor
}

void AliPythia::ProcInit(Process_t process, Float_t energy, StrucFunc_t strucfunc)
{
// Initialise the process to generate
    fProcess = process;
    fEcms = energy;
    fStrucFunc = strucfunc;
//  don't decay p0
    SetMDCY(Pycomp(111),1,0);
//  select structure function
    SetMSTP(52,2);
    SetMSTP(51,strucfunc);
//
// Pythia initialisation for selected processes//
//
// Make MSEL clean
//
    for (Int_t i=1; i<= 200; i++) {
	SetMSUB(i,0);
    }
//  select charm production
    switch (process)
    {
    case charm:
	SetMSEL(4);
//
//  heavy quark masses

	SetPMAS(4,1,1.2);

//
//    primordial pT
	SetMSTP(91,1);
	SetPARP(91,1);
	SetPARP(93,3);
//
	break;
    case beauty:
	SetMSEL(5);
	SetPMAS(5,1,4.75);
	break;
    case jpsi:
	SetMSEL(0);
// gg->J/Psi g
	SetMSUB(86,1);
	break;
    case jpsi_chi:
	SetMSEL(0);
// gg->J/Psi g
	SetMSUB(86,1);
// gg-> chi_0c g
	SetMSUB(87,1);
// gg-> chi_1c g
	SetMSUB(88,1);
// gg-> chi_2c g
	SetMSUB(89,1);
    case charm_unforced:
	SetMSEL(0);
// gq->qg
	SetMSUB(28,1);
// gg->qq
	SetMSUB(53,1);
// gg->gg
	SetMSUB(68,1);
    case beauty_unforced:
	SetMSEL(0);
// gq->qg
	SetMSUB(28,1);
// gg->qq
	SetMSUB(53,1);
// gg->gg
	SetMSUB(68,1);
	break;
    case mb:
// Minimum Bias pp-Collisions
//
// Tuning of parameters descibed in G. Ciapetti and A. Di Ciaccio
// Proc. of the LHC Workshop, Aachen 1990, Vol. II p. 155
//
//      select Pythia min. bias model
	SetMSEL(2);
	SetMSUB(92,1);
	SetMSUB(93,1);
	SetMSUB(94,1);
	SetMSUB(95,1);
//      Multiple interactions switched on
	SetMSTP(81,1);
	SetMSTP(82,1);
//      Low-pT cut-off for hard scattering
	SetPARP(81,1.9);
//      model for subsequent non-hardest interaction
//      90% gg->gg 10% gg->qq
	SetPARP(86,0.9);
//      90% of gluon interactions have minimum string length
	SetPARP(85,0.9);
    }
//
//  Initialize PYTHIA
    SetMSTP(41,1);

    Initialize("CMS","p","p",fEcms);
}

Int_t AliPythia::CheckedLuComp(Int_t kf)
{
// Check Lund particle code (for debugging)
    Int_t kc=Pycomp(kf);
    printf("\n Lucomp kf,kc %d %d",kf,kc);
    return kc;
}

void AliPythia::SetNuclei(Int_t a1, Int_t a2)
{
// Treat protons as inside nuclei with mass numbers a1 and a2
//    The MSTP array in the PYPARS common block is used to enable and
//    select the nuclear structure functions.
//    MSTP(52)  : (D=1) choice of proton and nuclear structure-function library
//            =1: internal PYTHIA acording to MSTP(51)
//            =2: PDFLIB proton  s.f., with MSTP(51)  = 1000xNGROUP+NSET
//            =3: PDFLIB proton  s.f. with nuclar correction:
//                MSTP( 51)  = 1000xNPGROUP+NPSET
//                MSTP(151)  = 1000xNAGROUP+NASET
//    MSTP(192) : Mass number of nucleus side 1
//    MSTP(193) : Mass number of nucleus side 2

    SetMSTP(52,3);
    SetMSTP(191, 1001);
    SetMSTP(192, a1);
    SetMSTP(193, a2);
}

AliPythia* AliPythia::Instance()
{
    if (fgAliPythia) {
	return fgAliPythia;
    } else {
	fgAliPythia = new AliPythia();
	return fgAliPythia;
    }
}
void AliPythia::Streamer(TBuffer &R__b) {}

<commit_msg>Upper cut of prim. pT distribution set to 5. GeV<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.9  2000/09/18 10:41:35  morsch
Add possibility to use nuclear structure functions from PDF library V8.

Revision 1.8  2000/09/06 14:26:24  morsch
Decayer functionality of AliPythia has been moved to AliDecayerPythia.
Class is now a singleton.

Revision 1.7  2000/06/09 20:34:50  morsch
All coding rule violations except RS3 corrected

Revision 1.6  1999/11/09 07:38:48  fca
Changes for compatibility with version 2.23 of ROOT

Revision 1.5  1999/11/03 17:43:20  fca
New version from G.Martinez & A.Morsch

Revision 1.4  1999/09/29 09:24:14  fca
Introduction of the Copyright and cvs Log

*/

#include "AliPythia.h"
#include "AliRun.h"

ClassImp(AliPythia)

//_____________________________________________________________________________

AliPythia* AliPythia::fgAliPythia=NULL;

AliPythia::AliPythia()
{
// Default Constructor
}

void AliPythia::ProcInit(Process_t process, Float_t energy, StrucFunc_t strucfunc)
{
// Initialise the process to generate
    fProcess = process;
    fEcms = energy;
    fStrucFunc = strucfunc;
//  don't decay p0
    SetMDCY(Pycomp(111),1,0);
//  select structure function
    SetMSTP(52,2);
    SetMSTP(51,strucfunc);
//
// Pythia initialisation for selected processes//
//
// Make MSEL clean
//
    for (Int_t i=1; i<= 200; i++) {
	SetMSUB(i,0);
    }
//  select charm production
    switch (process)
    {
    case charm:
	SetMSEL(4);
//
//  heavy quark masses

	SetPMAS(4,1,1.2);

//
//    primordial pT
	SetMSTP(91,1);
	SetPARP(91,1.);
	SetPARP(93,5.);
//
	break;
    case beauty:
	SetMSEL(5);
	SetPMAS(5,1,4.75);
	break;
    case jpsi:
	SetMSEL(0);
// gg->J/Psi g
	SetMSUB(86,1);
	break;
    case jpsi_chi:
	SetMSEL(0);
// gg->J/Psi g
	SetMSUB(86,1);
// gg-> chi_0c g
	SetMSUB(87,1);
// gg-> chi_1c g
	SetMSUB(88,1);
// gg-> chi_2c g
	SetMSUB(89,1);
    case charm_unforced:
	SetMSEL(0);
// gq->qg
	SetMSUB(28,1);
// gg->qq
	SetMSUB(53,1);
// gg->gg
	SetMSUB(68,1);
    case beauty_unforced:
	SetMSEL(0);
// gq->qg
	SetMSUB(28,1);
// gg->qq
	SetMSUB(53,1);
// gg->gg
	SetMSUB(68,1);
	break;
    case mb:
// Minimum Bias pp-Collisions
//
// Tuning of parameters descibed in G. Ciapetti and A. Di Ciaccio
// Proc. of the LHC Workshop, Aachen 1990, Vol. II p. 155
//
//      select Pythia min. bias model
	SetMSEL(2);
	SetMSUB(92,1);
	SetMSUB(93,1);
	SetMSUB(94,1);
	SetMSUB(95,1);
//      Multiple interactions switched on
	SetMSTP(81,1);
	SetMSTP(82,1);
//      Low-pT cut-off for hard scattering
	SetPARP(81,1.9);
//      model for subsequent non-hardest interaction
//      90% gg->gg 10% gg->qq
	SetPARP(86,0.9);
//      90% of gluon interactions have minimum string length
	SetPARP(85,0.9);
    }
//
//  Initialize PYTHIA
    SetMSTP(41,1);

    Initialize("CMS","p","p",fEcms);
}

Int_t AliPythia::CheckedLuComp(Int_t kf)
{
// Check Lund particle code (for debugging)
    Int_t kc=Pycomp(kf);
    printf("\n Lucomp kf,kc %d %d",kf,kc);
    return kc;
}

void AliPythia::SetNuclei(Int_t a1, Int_t a2)
{
// Treat protons as inside nuclei with mass numbers a1 and a2
//    The MSTP array in the PYPARS common block is used to enable and
//    select the nuclear structure functions.
//    MSTP(52)  : (D=1) choice of proton and nuclear structure-function library
//            =1: internal PYTHIA acording to MSTP(51)
//            =2: PDFLIB proton  s.f., with MSTP(51)  = 1000xNGROUP+NSET
//            =3: PDFLIB proton  s.f. with nuclar correction:
//                MSTP( 51)  = 1000xNPGROUP+NPSET
//                MSTP(151)  = 1000xNAGROUP+NASET
//    MSTP(192) : Mass number of nucleus side 1
//    MSTP(193) : Mass number of nucleus side 2

    SetMSTP(52,3);
    SetMSTP(191, 1001);
    SetMSTP(192, a1);
    SetMSTP(193, a2);
}

AliPythia* AliPythia::Instance()
{
    if (fgAliPythia) {
	return fgAliPythia;
    } else {
	fgAliPythia = new AliPythia();
	return fgAliPythia;
    }
}
void AliPythia::Streamer(TBuffer &R__b) {}

<|endoftext|>


<commit_before>// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <map>
#include <vector>
#include <assert.h>
#include <crypto/common.h>

namespace {

constexpr uint32_t INVALID = 0xFFFFFFFF;

uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes)
{
    uint32_t val = minval;
    bool bit;
    for (std::vector<uint8_t>::const_iterator bit_sizes_it = bit_sizes.begin();
        bit_sizes_it != bit_sizes.end(); ++bit_sizes_it) {
        if (bit_sizes_it + 1 != bit_sizes.end()) {
            if (bitpos == endpos) break;
            bit = *bitpos;
            bitpos++;
        } else {
            bit = 0;
        }
        if (bit) {
            val += (1 << *bit_sizes_it);
        } else {
            for (int b = 0; b < *bit_sizes_it; b++) {
                if (bitpos == endpos) return INVALID; // Reached EOF in mantissa
                bit = *bitpos;
                bitpos++;
                val += bit << (*bit_sizes_it - 1 - b);
            }
            return val;
        }
    }
    return INVALID; // Reached EOF in exponent
}

enum class Instruction : uint32_t
{
    RETURN = 0,
    JUMP = 1,
    MATCH = 2,
    DEFAULT = 3,
};

const std::vector<uint8_t> TYPE_BIT_SIZES{0, 0, 1};
Instruction DecodeType(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return Instruction(DecodeBits(bitpos, endpos, 0, TYPE_BIT_SIZES));
}

const std::vector<uint8_t> ASN_BIT_SIZES{15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 1, ASN_BIT_SIZES);
}

const std::vector<uint8_t> MATCH_BIT_SIZES{1, 2, 3, 4, 5, 6, 7, 8};
uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 2, MATCH_BIT_SIZES);
}

const std::vector<uint8_t> JUMP_BIT_SIZES{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 17, JUMP_BIT_SIZES);
}

}

uint32_t Interpret(const std::vector<bool> &asmap, const std::vector<bool> &ip)
{
    std::vector<bool>::const_iterator pos = asmap.begin();
    const std::vector<bool>::const_iterator endpos = asmap.end();
    uint8_t bits = ip.size();
    uint32_t default_asn = 0;
    uint32_t jump, match, matchlen;
    Instruction opcode;
    while (pos != endpos) {
        opcode = DecodeType(pos, endpos);
        if (opcode == Instruction::RETURN) {
            default_asn = DecodeASN(pos, endpos);
            if (default_asn == INVALID) break; // ASN straddles EOF
            return default_asn;
        } else if (opcode == Instruction::JUMP) {
            jump = DecodeJump(pos, endpos);
            if (jump == INVALID) break; // Jump offset straddles EOF
            if (bits == 0) break; // No input bits left
            if (jump >= endpos - pos) break; // Jumping past EOF
            if (ip[ip.size() - bits]) {
                pos += jump;
            }
            bits--;
        } else if (opcode == Instruction::MATCH) {
            match = DecodeMatch(pos, endpos);
            if (match == INVALID) break; // Match bits straddle EOF
            matchlen = CountBits(match) - 1;
            if (bits < matchlen) break; // Not enough input bits
            for (uint32_t bit = 0; bit < matchlen; bit++) {
                if ((ip[ip.size() - bits]) != ((match >> (matchlen - 1 - bit)) & 1)) {
                    return default_asn;
                }
                bits--;
            }
        } else if (opcode == Instruction::DEFAULT) {
            default_asn = DecodeASN(pos, endpos);
            if (default_asn == INVALID) break; // ASN straddles EOF
        } else {
            break; // Instruction straddles EOF
        }
    }
    assert(false); // Reached EOF without RETURN, or aborted (see any of the breaks above) - should have been caught by SanityCheckASMap below
    return 0; // 0 is not a valid ASN
}

bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
{
    const std::vector<bool>::const_iterator begin = asmap.begin(), endpos = asmap.end();
    std::vector<bool>::const_iterator pos = begin;
    std::vector<std::pair<uint32_t, int>> jumps; // All future positions we may jump to (bit offset in asmap -> bits to consume left)
    jumps.reserve(bits);
    Instruction prevopcode = Instruction::JUMP;
    bool had_incomplete_match = false;
    while (pos != endpos) {
        uint32_t offset = pos - begin;
        if (!jumps.empty() && offset >= jumps.back().first) return false; // There was a jump into the middle of the previous instruction
        Instruction opcode = DecodeType(pos, endpos);
        if (opcode == Instruction::RETURN) {
            if (prevopcode == Instruction::DEFAULT) return false; // There should not be any RETURN immediately after a DEFAULT (could be combined into just RETURN)
            uint32_t asn = DecodeASN(pos, endpos);
            if (asn == INVALID) return false; // ASN straddles EOF
            if (jumps.empty()) {
                // Nothing to execute anymore
                if (endpos - pos > 7) return false; // Excessive padding
                while (pos != endpos) {
                    if (*pos) return false; // Nonzero padding bit
                    ++pos;
                }
                return true; // Sanely reached EOF
            } else {
                // Continue by pretending we jumped to the next instruction
                offset = pos - begin;
                if (offset != jumps.back().first) return false; // Unreachable code
                bits = jumps.back().second; // Restore the number of bits we would have had left after this jump
                jumps.pop_back();
                prevopcode = Instruction::JUMP;
            }
        } else if (opcode == Instruction::JUMP) {
            uint32_t jump = DecodeJump(pos, endpos);
            if (jump == INVALID) return false; // Jump offset straddles EOF
            if (jump > endpos - pos) return false; // Jump out of range
            if (bits == 0) return false; // Consuming bits past the end of the input
            --bits;
            uint32_t jump_offset = pos - begin + jump;
            if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
            jumps.emplace_back(jump_offset, bits);
            prevopcode = Instruction::JUMP;
        } else if (opcode == Instruction::MATCH) {
            uint32_t match = DecodeMatch(pos, endpos);
            if (match == INVALID) return false; // Match bits straddle EOF
            int matchlen = CountBits(match) - 1;
            if (prevopcode != Instruction::MATCH) had_incomplete_match = false;
            if (matchlen < 8 && had_incomplete_match) return false; // Within a sequence of matches only at most one should be incomplete
            had_incomplete_match = (matchlen < 8);
            if (bits < matchlen) return false; // Consuming bits past the end of the input
            bits -= matchlen;
            prevopcode = Instruction::MATCH;
        } else if (opcode == Instruction::DEFAULT) {
            if (prevopcode == Instruction::DEFAULT) return false; // There should not be two successive DEFAULTs (they could be combined into one)
            uint32_t asn = DecodeASN(pos, endpos);
            if (asn == INVALID) return false; // ASN straddles EOF
            prevopcode = Instruction::DEFAULT;
        } else {
            return false; // Instruction straddles EOF
        }
    }
    return false; // Reached EOF without RETURN instruction
}
<commit_msg>refactor: Rework asmap Interpret to avoid ptrdiff_t<commit_after>// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <map>
#include <vector>
#include <assert.h>
#include <crypto/common.h>

namespace {

constexpr uint32_t INVALID = 0xFFFFFFFF;

uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes)
{
    uint32_t val = minval;
    bool bit;
    for (std::vector<uint8_t>::const_iterator bit_sizes_it = bit_sizes.begin();
        bit_sizes_it != bit_sizes.end(); ++bit_sizes_it) {
        if (bit_sizes_it + 1 != bit_sizes.end()) {
            if (bitpos == endpos) break;
            bit = *bitpos;
            bitpos++;
        } else {
            bit = 0;
        }
        if (bit) {
            val += (1 << *bit_sizes_it);
        } else {
            for (int b = 0; b < *bit_sizes_it; b++) {
                if (bitpos == endpos) return INVALID; // Reached EOF in mantissa
                bit = *bitpos;
                bitpos++;
                val += bit << (*bit_sizes_it - 1 - b);
            }
            return val;
        }
    }
    return INVALID; // Reached EOF in exponent
}

enum class Instruction : uint32_t
{
    RETURN = 0,
    JUMP = 1,
    MATCH = 2,
    DEFAULT = 3,
};

const std::vector<uint8_t> TYPE_BIT_SIZES{0, 0, 1};
Instruction DecodeType(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return Instruction(DecodeBits(bitpos, endpos, 0, TYPE_BIT_SIZES));
}

const std::vector<uint8_t> ASN_BIT_SIZES{15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 1, ASN_BIT_SIZES);
}

const std::vector<uint8_t> MATCH_BIT_SIZES{1, 2, 3, 4, 5, 6, 7, 8};
uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 2, MATCH_BIT_SIZES);
}

const std::vector<uint8_t> JUMP_BIT_SIZES{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos)
{
    return DecodeBits(bitpos, endpos, 17, JUMP_BIT_SIZES);
}

}

uint32_t Interpret(const std::vector<bool> &asmap, const std::vector<bool> &ip)
{
    std::vector<bool>::const_iterator pos = asmap.begin();
    const std::vector<bool>::const_iterator endpos = asmap.end();
    uint8_t bits = ip.size();
    uint32_t default_asn = 0;
    uint32_t jump, match, matchlen;
    Instruction opcode;
    while (pos != endpos) {
        opcode = DecodeType(pos, endpos);
        if (opcode == Instruction::RETURN) {
            default_asn = DecodeASN(pos, endpos);
            if (default_asn == INVALID) break; // ASN straddles EOF
            return default_asn;
        } else if (opcode == Instruction::JUMP) {
            jump = DecodeJump(pos, endpos);
            if (jump == INVALID) break; // Jump offset straddles EOF
            if (bits == 0) break; // No input bits left
            if (pos + jump < pos) break; // overflow
            if (pos + jump >= endpos) break; // Jumping past EOF
            if (ip[ip.size() - bits]) {
                pos += jump;
            }
            bits--;
        } else if (opcode == Instruction::MATCH) {
            match = DecodeMatch(pos, endpos);
            if (match == INVALID) break; // Match bits straddle EOF
            matchlen = CountBits(match) - 1;
            if (bits < matchlen) break; // Not enough input bits
            for (uint32_t bit = 0; bit < matchlen; bit++) {
                if ((ip[ip.size() - bits]) != ((match >> (matchlen - 1 - bit)) & 1)) {
                    return default_asn;
                }
                bits--;
            }
        } else if (opcode == Instruction::DEFAULT) {
            default_asn = DecodeASN(pos, endpos);
            if (default_asn == INVALID) break; // ASN straddles EOF
        } else {
            break; // Instruction straddles EOF
        }
    }
    assert(false); // Reached EOF without RETURN, or aborted (see any of the breaks above) - should have been caught by SanityCheckASMap below
    return 0; // 0 is not a valid ASN
}

bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
{
    const std::vector<bool>::const_iterator begin = asmap.begin(), endpos = asmap.end();
    std::vector<bool>::const_iterator pos = begin;
    std::vector<std::pair<uint32_t, int>> jumps; // All future positions we may jump to (bit offset in asmap -> bits to consume left)
    jumps.reserve(bits);
    Instruction prevopcode = Instruction::JUMP;
    bool had_incomplete_match = false;
    while (pos != endpos) {
        uint32_t offset = pos - begin;
        if (!jumps.empty() && offset >= jumps.back().first) return false; // There was a jump into the middle of the previous instruction
        Instruction opcode = DecodeType(pos, endpos);
        if (opcode == Instruction::RETURN) {
            if (prevopcode == Instruction::DEFAULT) return false; // There should not be any RETURN immediately after a DEFAULT (could be combined into just RETURN)
            uint32_t asn = DecodeASN(pos, endpos);
            if (asn == INVALID) return false; // ASN straddles EOF
            if (jumps.empty()) {
                // Nothing to execute anymore
                if (endpos - pos > 7) return false; // Excessive padding
                while (pos != endpos) {
                    if (*pos) return false; // Nonzero padding bit
                    ++pos;
                }
                return true; // Sanely reached EOF
            } else {
                // Continue by pretending we jumped to the next instruction
                offset = pos - begin;
                if (offset != jumps.back().first) return false; // Unreachable code
                bits = jumps.back().second; // Restore the number of bits we would have had left after this jump
                jumps.pop_back();
                prevopcode = Instruction::JUMP;
            }
        } else if (opcode == Instruction::JUMP) {
            uint32_t jump = DecodeJump(pos, endpos);
            if (jump == INVALID) return false; // Jump offset straddles EOF
            if (pos + jump < pos) return false; // overflow
            if (pos + jump > endpos) return false; // Jump out of range
            if (bits == 0) return false; // Consuming bits past the end of the input
            --bits;
            uint32_t jump_offset = pos - begin + jump;
            if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
            jumps.emplace_back(jump_offset, bits);
            prevopcode = Instruction::JUMP;
        } else if (opcode == Instruction::MATCH) {
            uint32_t match = DecodeMatch(pos, endpos);
            if (match == INVALID) return false; // Match bits straddle EOF
            int matchlen = CountBits(match) - 1;
            if (prevopcode != Instruction::MATCH) had_incomplete_match = false;
            if (matchlen < 8 && had_incomplete_match) return false; // Within a sequence of matches only at most one should be incomplete
            had_incomplete_match = (matchlen < 8);
            if (bits < matchlen) return false; // Consuming bits past the end of the input
            bits -= matchlen;
            prevopcode = Instruction::MATCH;
        } else if (opcode == Instruction::DEFAULT) {
            if (prevopcode == Instruction::DEFAULT) return false; // There should not be two successive DEFAULTs (they could be combined into one)
            uint32_t asn = DecodeASN(pos, endpos);
            if (asn == INVALID) return false; // ASN straddles EOF
            prevopcode = Instruction::DEFAULT;
        } else {
            return false; // Instruction straddles EOF
        }
    }
    return false; // Reached EOF without RETURN instruction
}
<|endoftext|>


<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP
#define OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP

#include <system_error>
#include <CoreVideo/CVDisplayLink.h>
#include "CoreVideoErrorCategory.hpp"

namespace ouzel::platform::corevideo
{
    class DisplayLink final
    {
    public:
        explicit DisplayLink(CGDirectDisplayID displayId)
        {
            if (const auto result = CVDisplayLinkCreateWithCGDisplay(displayId, &displayLink); result != kCVReturnSuccess)
                throw std::system_error(result, platform::corevideo::getErrorCategory(), "Failed to create display link");
        }

        ~DisplayLink()
        {
            if (displayLink) CVDisplayLinkRelease(displayLink);
        }

        DisplayLink(DisplayLink&& other) noexcept:
            displayLink{other.displayLink}
        {
            other.displayLink = nullptr;
        }

        DisplayLink(const DisplayLink& other):
            displayLink{other.displayLink}
        {
            if (displayLink) CVDisplayLinkRetain(displayLink);
        }

        DisplayLink& operator=(DisplayLink&& other) noexcept
        {
            if (&other == this) return *this;
            if (displayLink) CVDisplayLinkRelease(displayLink);
            displayLink = other.displayLink;
            other.displayLink = nullptr;
            return *this;
        }

        DisplayLink& operator=(const DisplayLink& other) noexcept
        {
            if (&other == this) return *this;
            if (displayLink) CVDisplayLinkRelease(displayLink);
            displayLink = other.displayLink;
            if (displayLink) CVDisplayLinkRetain(displayLink);
            return *this;
        }

        void setCallback(CVDisplayLinkOutputCallback callback, void* userInfo)
        {
            if (const auto result = CVDisplayLinkSetOutputCallback(displayLink, callback, userInfo); result != kCVReturnSuccess)
                throw std::system_error(result, platform::corevideo::getErrorCategory(), "Failed to set output callback for the display link");
        }

        void start()
        {
            if (displayLink)
                if (const auto result = CVDisplayLinkStart(displayLink); result != kCVReturnSuccess)
                    throw std::system_error(result, platform::corevideo::getErrorCategory(), "Failed to start display link");
        }

        void stop()
        {
            if (displayLink)
                if (const auto result = CVDisplayLinkStop(displayLink); result != kCVReturnSuccess)
                    throw std::system_error(result, platform::corevideo::getErrorCategory(), "Failed to stop display link");
        }

    private:
        CVDisplayLinkRef displayLink = nullptr;
    };
}

#endif // OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP
<commit_msg>Remove the unneeded namespaces<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP
#define OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP

#include <system_error>
#include <CoreVideo/CVDisplayLink.h>
#include "CoreVideoErrorCategory.hpp"

namespace ouzel::platform::corevideo
{
    class DisplayLink final
    {
    public:
        explicit DisplayLink(CGDirectDisplayID displayId)
        {
            if (const auto result = CVDisplayLinkCreateWithCGDisplay(displayId, &displayLink); result != kCVReturnSuccess)
                throw std::system_error(result, getErrorCategory(), "Failed to create display link");
        }

        ~DisplayLink()
        {
            if (displayLink) CVDisplayLinkRelease(displayLink);
        }

        DisplayLink(DisplayLink&& other) noexcept:
            displayLink{other.displayLink}
        {
            other.displayLink = nullptr;
        }

        DisplayLink(const DisplayLink& other):
            displayLink{other.displayLink}
        {
            if (displayLink) CVDisplayLinkRetain(displayLink);
        }

        DisplayLink& operator=(DisplayLink&& other) noexcept
        {
            if (&other == this) return *this;
            if (displayLink) CVDisplayLinkRelease(displayLink);
            displayLink = other.displayLink;
            other.displayLink = nullptr;
            return *this;
        }

        DisplayLink& operator=(const DisplayLink& other) noexcept
        {
            if (&other == this) return *this;
            if (displayLink) CVDisplayLinkRelease(displayLink);
            displayLink = other.displayLink;
            if (displayLink) CVDisplayLinkRetain(displayLink);
            return *this;
        }

        void setCallback(CVDisplayLinkOutputCallback callback, void* userInfo)
        {
            if (const auto result = CVDisplayLinkSetOutputCallback(displayLink, callback, userInfo); result != kCVReturnSuccess)
                throw std::system_error(result, getErrorCategory(), "Failed to set output callback for the display link");
        }

        void start()
        {
            if (displayLink)
                if (const auto result = CVDisplayLinkStart(displayLink); result != kCVReturnSuccess)
                    throw std::system_error(result, getErrorCategory(), "Failed to start display link");
        }

        void stop()
        {
            if (displayLink)
                if (const auto result = CVDisplayLinkStop(displayLink); result != kCVReturnSuccess)
                    throw std::system_error(result, getErrorCategory(), "Failed to stop display link");
        }

    private:
        CVDisplayLinkRef displayLink = nullptr;
    };
}

#endif // OUZEL_PLATFORM_COREVIDEO_DISPLAYLINK_HPP
<|endoftext|>


<commit_before>// FFModule.cc

// This file is part of bes, A C++ back-end server implementation framework
// for the OPeNDAP Data Access Protocol.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>

#include <iostream>

using std::endl ;

#include "FFModule.h"
#include "BESRequestHandlerList.h"
#include "FFRequestHandler.h"
#include "BESContainerStorageList.h"
#include "BESContainerStorageCatalog.h"
#include "BESCatalogDirectory.h"
#include "BESCatalogList.h"
#include "BESDebug.h"

#define FF_CATALOG "catalog"

void
FFModule::initialize( const string &modname )
{
    BESDEBUG( "Initializing FF module " << modname << endl )

    BESDEBUG( "    adding " << modname << " request handler" << endl )
    BESRequestHandler *handler = new FFRequestHandler( modname ) ;
    BESRequestHandlerList::TheList()->add_handler( modname, handler ) ;

    BESDEBUG( "    adding " << FF_CATALOG << " catalog" << endl )
    BESCatalogList::TheCatalogList()->add_catalog( new BESCatalogDirectory( FF_CATALOG ) ) ;

    BESDEBUG( "    adding catalog container storage" << FF_CATALOG << endl )
    BESContainerStorageCatalog *csc = new BESContainerStorageCatalog( FF_CATALOG ) ;
    BESContainerStorageList::TheList()->add_persistence( csc ) ;

    BESDEBUG( "Done Initializing FF module " << modname << endl )
}

void
FFModule::terminate( const string &modname )
{
    BESDEBUG( "Cleaning FF module " << modname << endl )

    BESDEBUG( "    removing FF Handler" << modname << endl )
    BESRequestHandler *rh = BESRequestHandlerList::TheList()->remove_handler( modname ) ;
    if( rh ) delete rh ;

    BESDEBUG( "    removing catalog container storage" << FF_CATALOG << endl )
    BESContainerStorageList::TheList()->del_persistence( FF_CATALOG ) ;

    BESDEBUG( "    removing " << FF_CATALOG << " catalog" << endl )
    BESCatalogList::TheCatalogList()->del_catalog( FF_CATALOG ) ;

    BESDEBUG( "Done Cleaning FF module " << modname << endl )
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance
 *
 * @param strm C++ i/o stream to dump the information to
 */
void
FFModule::dump( ostream &strm ) const
{
    strm << BESIndent::LMarg << "FFModule::dump - ("
			     << (void *)this << ")" << endl ;
}

extern "C"
{
    BESAbstractModule *maker()
    {
        return new FFModule ;
    }
}

<commit_msg>BESDebug modifications, passing context to BESDEBUG and registering debug context in Module classes.<commit_after>// FFModule.cc

// This file is part of bes, A C++ back-end server implementation framework
// for the OPeNDAP Data Access Protocol.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>

#include <iostream>

using std::endl ;

#include "FFModule.h"
#include "BESRequestHandlerList.h"
#include "FFRequestHandler.h"
#include "BESContainerStorageList.h"
#include "BESContainerStorageCatalog.h"
#include "BESCatalogDirectory.h"
#include "BESCatalogList.h"
#include "BESDebug.h"

#define FF_CATALOG "catalog"

void
FFModule::initialize( const string &modname )
{
    BESDEBUG( "ff", "Initializing FF module " << modname << endl )

    BESDEBUG( "ff", "    adding " << modname << " request handler" << endl )
    BESRequestHandler *handler = new FFRequestHandler( modname ) ;
    BESRequestHandlerList::TheList()->add_handler( modname, handler ) ;

    BESDEBUG( "ff", "    adding " << FF_CATALOG << " catalog" << endl )
    BESCatalogList::TheCatalogList()->add_catalog( new BESCatalogDirectory( FF_CATALOG ) ) ;

    BESDEBUG( "ff", "    adding catalog container storage" << FF_CATALOG << endl )
    BESContainerStorageCatalog *csc = new BESContainerStorageCatalog( FF_CATALOG ) ;
    BESContainerStorageList::TheList()->add_persistence( csc ) ;

    BESDEBUG( "ff", "    adding ff debug context" << endl )
    BESDebug::Register( "ff" ) ;

    BESDEBUG( "ff", "Done Initializing FF module " << modname << endl )
}

void
FFModule::terminate( const string &modname )
{
    BESDEBUG( "ff", "Cleaning FF module " << modname << endl )

    BESDEBUG( "ff", "    removing FF Handler" << modname << endl )
    BESRequestHandler *rh = BESRequestHandlerList::TheList()->remove_handler( modname ) ;
    if( rh ) delete rh ;

    BESDEBUG( "ff", "    removing catalog container storage" << FF_CATALOG << endl )
    BESContainerStorageList::TheList()->del_persistence( FF_CATALOG ) ;

    BESDEBUG( "ff", "    removing " << FF_CATALOG << " catalog" << endl )
    BESCatalogList::TheCatalogList()->del_catalog( FF_CATALOG ) ;

    BESDEBUG( "ff", "Done Cleaning FF module " << modname << endl )
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance
 *
 * @param strm C++ i/o stream to dump the information to
 */
void
FFModule::dump( ostream &strm ) const
{
    strm << BESIndent::LMarg << "FFModule::dump - ("
			     << (void *)this << ")" << endl ;
}

extern "C"
{
    BESAbstractModule *maker()
    {
        return new FFModule ;
    }
}

<|endoftext|>