<commit_before>#pragma once
/**
	@file
	@brief frequency of elements in a sequence
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <assert.h>
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
#include <cybozu/exception.hpp>
#include <cybozu/unordered_map.hpp>

namespace cybozu {

namespace freq_local {

template<class T>
union ci {
	T i;
	char c[sizeof(T)];
};

template<class T> void load(T& t, std::istream& is) { t.load(is); }
template<class T> void save(std::ostream& os, const T& t) { t.save(os); }

template<class T>
void load(T *t, size_t n, std::istream& is, const char *msg)
{
	const std::streamsize size = sizeof(T) * n;
	if (!is.read((char*)t, size) || is.gcount() != size) {
		throw cybozu::Exception("Frequency:load") << msg;
	}
}
template<class T>
void save(std::ostream& os, const T *t, size_t n, const char *msg)
{
	if (!os.write((const char*)t, sizeof(T) * n)) {
		throw cybozu::Exception("Frequency:save") << msg;
	}
}

#define CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(type) \
template<>void load(type& t, std::istream& is) { load(&t, 1, is, #type); } \
template<>void save(std::ostream& os, const type& t) { save(os, &t, 1, #type); }

CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(char)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(unsigned char)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(int)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(unsigned int)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(long)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(unsigned long)
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(wchar_t)
#ifdef _MSC_VER
CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE(size_t)
#endif

#undef CYBOZU_FREQUENCY_DEFINE_LOAD_SAVE

template<>
void load(std::string& t, std::istream& is)
{
	size_t size;
	load(size, is);
	t.resize(size);
	load(&t[0], size, is, "string");
}

template<>
void save(std::ostream& os, const std::string& t)
{
	save(os, t.size());
	save(os, &t[0], t.size(), "string");
}

template<class Element, class Int = size_t>
class FrequencyVec {
	static const size_t N = size_t(1) << (sizeof(Element) * 8);
	size_t size_;
	Int freqTbl_[N];
	uint8_t char2idx_[N];
	uint8_t idx2char_[N];
	struct Greater {
		const Int *p_;
		explicit Greater(const Int *p) : p_(p) {}
		bool operator()(uint8_t lhs, uint8_t rhs) const
		{
			Int a = p_[lhs];
			Int b = p_[rhs];
			if (a > b) return true;
			if (a < b) return false;
			return a > b;
		}
	};
public:
	typedef Element value_type;
	typedef Int size_type;

	FrequencyVec() { clear(); }
	template<class Iter>
	FrequencyVec(Iter begin, Iter end)
	{
		clear();
		init(begin, end);
	}
	void clear()
	{
		size_ = 0;
		memset(freqTbl_, 0, sizeof(freqTbl_));
	}
	template<class Iter>
	void init(Iter begin, Iter end)
	{
		while (begin != end) {
			append(*begin);
			++begin;
		}
		ready();
	}
	void append(const Element e)
	{
		freqTbl_[uint8_t(e)]++;
	}
	void ready()
	{
		for (size_t i = 0; i < N; i++) idx2char_[i] = uint8_t(i);
		Greater greater(freqTbl_);
		std::sort(idx2char_, idx2char_ + N, greater);
		size_ = 0;
		for (size_t i = 0; i < N; i++) {
			uint8_t c = idx2char_[i];
			char2idx_[c] = (uint8_t)i;
			if (freqTbl_[c]) size_++;
		}
	}
	/*
		element -> freq
	*/
	Int getFrequency(Element e) const { return freqTbl_[uint8_t(e)]; }
	/*
		element -> idx
	*/
	Int getIndex(Element e) const { return char2idx_[uint8_t(e)]; }
	/*
		idx -> element
	*/
	Element getElement(size_t idx) const
	{
//		if (idx >= N) throw cybozu::Exception("Frequency:getElement:bad idx") << idx;
		assert(idx < N);
		return Element(idx2char_[idx]);
	}
	size_t size() const { return size_; }
	void load(std::istream& is)
	{
		freq_local::load(&size_, 1u, is, "size");
		freq_local::load(freqTbl_, N, is, "freqTbl");
		freq_local::load(char2idx_, N, is, "char2idx");
		freq_local::load(idx2char_, N, is, "idx2char");
	}
	void save(std::ostream& os) const
	{
		freq_local::save(os, &size_, 1, "size");
		freq_local::save(os, freqTbl_, N, "freqTbl");
		freq_local::save(os, char2idx_, N, "char2idx");
		freq_local::save(os, idx2char_, N, "idx2char");
	}
	void put() const
	{
		for (size_t i = 0; i < size_; i++) {
			uint8_t c = idx2char_[i];
			printf("%d %d %d\n", (int)i, c, freqTbl_[c]);
		}
	}
};

} // cybozu::freq_local

/*
	count Element
	Element : type of element
	Int : type of counter
*/
template<class Element, class Int = size_t>
class Frequency {
	struct FreqIdx {
		Int freq;
		mutable Int idx;
		void load(std::istream& is)
		{
			freq_local::load(freq, is);
			freq_local::load(idx, is);
		}
		void save(std::ostream& os) const
		{
			freq_local::save(os, freq);
			freq_local::save(os, idx);
		}
	};
	typedef CYBOZU_NAMESPACE_STD::unordered_map<Element, FreqIdx> Map;
	typedef Element value_type;
	typedef Int size_type;
	typedef std::vector<typename Map::const_iterator> Idx2Ref;
	static inline bool greater(typename Map::const_iterator i, typename Map::const_iterator j)
	{
		const Int a = i->second.freq;
		const Int b = j->second.freq;
		if (a > b) return true;
		if (a < b) return false;
		return i->first > j->first;
	}
	Map m_;
	Idx2Ref idx2ref_;
	void initIdx2Ref()
	{
		idx2ref_.resize(m_.size());
		size_t pos = 0;
		for (typename Map::const_iterator i = m_.begin(), ie = m_.end(); i != ie; ++i) {
			idx2ref_[pos++] = i;
		}
		std::sort(idx2ref_.begin(), idx2ref_.end(), greater);
	}
public:
	Frequency(){ clear(); }
	template<class Iter>
	Frequency(Iter begin, Iter end)
	{
		clear();
		init(begin, end);
	}
	void clear()
	{
		m_.clear();
		idx2ref_.clear();
	}
	template<class Iter>
	void init(Iter begin, Iter end)
	{
		while (begin != end) {
			append(*begin);
			++begin;
		}
		ready();
	}
	void append(const Element& e)
	{
		m_[e].freq++;
	}
	void ready()
	{
		initIdx2Ref();
		for (size_t i = 0, ie = idx2ref_.size(); i < ie; i++) {
			idx2ref_[i]->second.idx = (Int)i;
		}
	}
	/*
		element -> freq
	*/
	Int getFrequency(const Element& e) const
	{
		typename Map::const_iterator i = m_.find(e);
		return (i != m_.end()) ? i->second.freq : 0;
	}
	/*
		element -> idx
	*/
	Int getIndex(const Element& e) const
	{
		typename Map::const_iterator i = m_.find(e);
		if (i == m_.end()) throw cybozu::Exception("Frequency:getIndex:not found") << e;
		return i->second.idx;
	}
	/*
		idx -> element
	*/
	const Element& getElement(size_t idx) const
	{
		if (idx >= idx2ref_.size()) throw cybozu::Exception("Frequency:getElement:bad idx") << idx;
		return idx2ref_[idx]->first;
	}
	size_t size() const { return idx2ref_.size(); }
	void load(std::istream& is)
	{
		size_t size;
		freq_local::load(size, is);
		for (size_t i = 0; i < size; i++) {
			typename Map::key_type k;
			freq_local::load(k, is);
			FreqIdx freqIdx;
			freq_local::load(freqIdx, is);
			m_.insert(typename Map::value_type(k, freqIdx));
		}
		initIdx2Ref();
	}
	void save(std::ostream& os) const
	{
		freq_local::save(os, m_.size());
		for (typename Map::const_iterator i = m_.begin(), ie = m_.end(); i != ie; ++i) {
			freq_local::save(os, i->first);
			freq_local::save(os, i->second);
		}
	}
	void put() const
	{
		for (size_t i = 0, n = idx2ref_.size(); i < n; i++) {
			typename Map::const_iterator j = idx2ref_[i];
			std::cout << i << ' ' << j->first << ' ' << j->second.freq << std::endl;
		}
	}
};

template<class Int>
struct Frequency<uint8_t, Int> : freq_local::FrequencyVec<uint8_t, Int> {
	Frequency() {}
	template<class Iterator>
	Frequency(Iterator begin, Iterator end) : freq_local::FrequencyVec<uint8_t, Int>(begin, end) {}
};
template<class Int>
struct Frequency<char, Int> : freq_local::FrequencyVec<char, Int> {
	Frequency() {}
	template<class Iterator>
	Frequency(Iterator begin, Iterator end) : freq_local::FrequencyVec<char, Int>(begin, end) {}
};

} // cybozu
<commit_msg>Frequency use cybozu::stream<commit_after>#pragma once
/**
	@file
	@brief frequency of elements in a sequence
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <assert.h>
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
#include <cybozu/exception.hpp>
#include <cybozu/unordered_map.hpp>
#include <cybozu/serializer.hpp>

namespace cybozu {

namespace freq_local {

template<class Element, class Int = size_t>
class FrequencyVec {
	static const size_t N = size_t(1) << (sizeof(Element) * 8);
	size_t size_;
	Int freqTbl_[N];
	uint8_t char2idx_[N];
	uint8_t idx2char_[N];
	struct Greater {
		const Int *p_;
		explicit Greater(const Int *p) : p_(p) {}
		bool operator()(uint8_t lhs, uint8_t rhs) const
		{
			Int a = p_[lhs];
			Int b = p_[rhs];
			if (a > b) return true;
			if (a < b) return false;
			return a > b;
		}
	};
public:
	typedef Element value_type;
	typedef Int size_type;

	FrequencyVec() { clear(); }
	template<class Iter>
	FrequencyVec(Iter begin, Iter end)
	{
		clear();
		init(begin, end);
	}
	void clear()
	{
		size_ = 0;
		memset(freqTbl_, 0, sizeof(freqTbl_));
	}
	template<class Iter>
	void init(Iter begin, Iter end)
	{
		while (begin != end) {
			append(*begin);
			++begin;
		}
		ready();
	}
	void append(const Element e)
	{
		freqTbl_[uint8_t(e)]++;
	}
	void ready()
	{
		for (size_t i = 0; i < N; i++) idx2char_[i] = uint8_t(i);
		Greater greater(freqTbl_);
		std::sort(idx2char_, idx2char_ + N, greater);
		size_ = 0;
		for (size_t i = 0; i < N; i++) {
			uint8_t c = idx2char_[i];
			char2idx_[c] = (uint8_t)i;
			if (freqTbl_[c]) size_++;
		}
	}
	/*
		element -> freq
	*/
	Int getFrequency(Element e) const { return freqTbl_[uint8_t(e)]; }
	/*
		element -> idx
	*/
	Int getIndex(Element e) const { return char2idx_[uint8_t(e)]; }
	/*
		idx -> element
	*/
	Element getElement(size_t idx) const
	{
//		if (idx >= N) throw cybozu::Exception("Frequency:getElement:bad idx") << idx;
		assert(idx < N);
		return Element(idx2char_[idx]);
	}
	size_t size() const { return size_; }
	template<class InputStream>
	void load(InputStream& is)
	{
		cybozu::load(size_, is);
		cybozu::loadRange(freqTbl_, N, is);
		cybozu::loadRange(char2idx_, N, is);
		cybozu::loadRange(idx2char_, N, is);
	}
	void save(std::ostream& os) const
	{
		cybozu::save(os, size_);
		cybozu::saveRange(os, freqTbl_, N);
		cybozu::saveRange(os, char2idx_, N);
		cybozu::saveRange(os, idx2char_, N);
	}
	void put() const
	{
		for (size_t i = 0; i < size_; i++) {
			uint8_t c = idx2char_[i];
			printf("%d %d %d\n", (int)i, c, freqTbl_[c]);
		}
	}
};

} // cybozu::freq_local

/*
	count Element
	Element : type of element
	Int : type of counter
*/
template<class Element, class Int = size_t>
class Frequency {
	struct FreqIdx {
		Int freq;
		mutable Int idx;
		template<class InputStream>
		void load(InputStream& is)
		{
			cybozu::load(freq, is);
			cybozu::load(idx, is);
		}
		template<class OutputStream>
		void save(OutputStream& os) const
		{
			cybozu::save(os, freq);
			cybozu::save(os, idx);
		}
	};
	typedef CYBOZU_NAMESPACE_STD::unordered_map<Element, FreqIdx> Map;
	typedef Element value_type;
	typedef Int size_type;
	typedef std::vector<typename Map::const_iterator> Idx2Ref;
	static inline bool greater(typename Map::const_iterator i, typename Map::const_iterator j)
	{
		const Int a = i->second.freq;
		const Int b = j->second.freq;
		if (a > b) return true;
		if (a < b) return false;
		return i->first > j->first;
	}
	Map m_;
	Idx2Ref idx2ref_;
	void initIdx2Ref()
	{
		idx2ref_.resize(m_.size());
		size_t pos = 0;
		for (typename Map::const_iterator i = m_.begin(), ie = m_.end(); i != ie; ++i) {
			idx2ref_[pos++] = i;
		}
		std::sort(idx2ref_.begin(), idx2ref_.end(), greater);
	}
public:
	Frequency(){ clear(); }
	template<class Iter>
	Frequency(Iter begin, Iter end)
	{
		clear();
		init(begin, end);
	}
	void clear()
	{
		m_.clear();
		idx2ref_.clear();
	}
	template<class Iter>
	void init(Iter begin, Iter end)
	{
		while (begin != end) {
			append(*begin);
			++begin;
		}
		ready();
	}
	void append(const Element& e)
	{
		m_[e].freq++;
	}
	void ready()
	{
		initIdx2Ref();
		for (size_t i = 0, ie = idx2ref_.size(); i < ie; i++) {
			idx2ref_[i]->second.idx = (Int)i;
		}
	}
	/*
		element -> freq
	*/
	Int getFrequency(const Element& e) const
	{
		typename Map::const_iterator i = m_.find(e);
		return (i != m_.end()) ? i->second.freq : 0;
	}
	/*
		element -> idx
	*/
	Int getIndex(const Element& e) const
	{
		typename Map::const_iterator i = m_.find(e);
		if (i == m_.end()) throw cybozu::Exception("Frequency:getIndex:not found") << e;
		return i->second.idx;
	}
	/*
		idx -> element
	*/
	const Element& getElement(size_t idx) const
	{
		if (idx >= idx2ref_.size()) throw cybozu::Exception("Frequency:getElement:bad idx") << idx;
		return idx2ref_[idx]->first;
	}
	size_t size() const { return idx2ref_.size(); }
	template<class InputStream>
	void load(InputStream& is)
	{
		cybozu::load(m_, is);
		initIdx2Ref();
	}
	template<class OutputStream>
	void save(OutputStream& os) const
	{
		cybozu::save(os, m_);
	}
	void put() const
	{
		for (size_t i = 0, n = idx2ref_.size(); i < n; i++) {
			typename Map::const_iterator j = idx2ref_[i];
			std::cout << i << ' ' << j->first << ' ' << j->second.freq << std::endl;
		}
	}
};

template<class Int>
struct Frequency<uint8_t, Int> : freq_local::FrequencyVec<uint8_t, Int> {
	Frequency() {}
	template<class Iterator>
	Frequency(Iterator begin, Iterator end) : freq_local::FrequencyVec<uint8_t, Int>(begin, end) {}
};
template<class Int>
struct Frequency<char, Int> : freq_local::FrequencyVec<char, Int> {
	Frequency() {}
	template<class Iterator>
	Frequency(Iterator begin, Iterator end) : freq_local::FrequencyVec<char, Int>(begin, end) {}
};

} // cybozu
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <vector>
#include "tensorflow/cc/framework/grad_op_registry.h"
#include "tensorflow/cc/framework/gradients.h"
#include "tensorflow/cc/ops/image_ops_internal.h"
#include "tensorflow/cc/ops/standard_ops.h"

namespace tensorflow {
namespace ops {
namespace {

Status ResizeNearestNeighborGradHelper(const Scope& scope, const Operation& op,
                                       const std::vector<Output>& grad_inputs,
                                       std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));
  // The internal gradient implementation needs the shape of the input image.
  // x_shape = shape(x)[1:3]
  //         = slice(shape(x), {1}, {3 - 1})
  auto x_shape = Slice(scope, Shape(scope, op.input(0)), {1}, {2});
  grad_outputs->push_back(internal::ResizeNearestNeighborGrad(
      scope, grad_inputs[0], x_shape,
      internal::ResizeNearestNeighborGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeNearestNeighbor", ResizeNearestNeighborGradHelper);

Status ResizeBilinearGradHelper(const Scope& scope, const Operation& op,
                                const std::vector<Output>& grad_inputs,
                                std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));
  grad_outputs->push_back(internal::ResizeBilinearGrad(
      scope, grad_inputs[0], op.input(0),
      internal::ResizeBilinearGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeBilinear", ResizeBilinearGradHelper);

Status ResizeBicubicGradHelper(const Scope& scope, const Operation& op,
                               const std::vector<Output>& grad_inputs,
                               std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));

  grad_outputs->push_back(internal::ResizeBicubicGrad(
      scope, grad_inputs[0], op.input(0),
      internal::ResizeBicubicGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeBicubic", ResizeBicubicGradHelper);

Status ScaleAndTranslateGradHelper(const Scope& scope, const Operation& op,
                                   const std::vector<Output>& grad_inputs,
                                   std::vector<Output>* grad_outputs) {
  string kernel_type;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "kernel_type", &kernel_type));
  bool antialias;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "antialias", &antialias));
  grad_outputs->push_back(internal::ScaleAndTranslateGrad(
      scope, grad_inputs[0], op.input(0), op.input(2), op.input(3),
      internal::ScaleAndTranslateGrad::KernelType(kernel_type)
          .Antialias(antialias)));

  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  return scope.status();
}

REGISTER_GRADIENT_OP("ScaleAndTranslate", ScaleAndTranslateGradHelper);

Status CropAndResizeGradHelper(const Scope& scope, const Operation& op,
                               const std::vector<Output>& grad_inputs,
                               std::vector<Output>* grad_outputs) {
  DataType input_type;
  string method;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "method", &method));
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "T", &input_type));
  auto image_shape = Shape(scope, op.input(0));
  grad_outputs->push_back(CropAndResizeGradImage(
      scope, grad_inputs[0], op.input(1), op.input(2), image_shape, input_type,
      CropAndResizeGradImage::Method(method)));
  grad_outputs->push_back(CropAndResizeGradBoxes(
      scope, grad_inputs[0], op.input(0), op.input(1), op.input(2)));
  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  return scope.status();
}

REGISTER_GRADIENT_OP("CropAndResize", CropAndResizeGradHelper);
}  // anonymous namespace
}  // namespace ops
}  // namespace tensorflow
<commit_msg>Mark NonMaxSuppression ops non differentiable in C++<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <vector>
#include "tensorflow/cc/framework/grad_op_registry.h"
#include "tensorflow/cc/framework/gradients.h"
#include "tensorflow/cc/ops/image_ops_internal.h"
#include "tensorflow/cc/ops/standard_ops.h"

namespace tensorflow {
namespace ops {
namespace {

REGISTER_NO_GRADIENT_OP("NonMaxSuppression");
REGISTER_NO_GRADIENT_OP("NonMaxSuppressionV2");
REGISTER_NO_GRADIENT_OP("NonMaxSuppressionV3");
REGISTER_NO_GRADIENT_OP("NonMaxSuppressionV4");
REGISTER_NO_GRADIENT_OP("NonMaxSuppressionV5");

Status ResizeNearestNeighborGradHelper(const Scope& scope, const Operation& op,
                                       const std::vector<Output>& grad_inputs,
                                       std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));
  // The internal gradient implementation needs the shape of the input image.
  // x_shape = shape(x)[1:3]
  //         = slice(shape(x), {1}, {3 - 1})
  auto x_shape = Slice(scope, Shape(scope, op.input(0)), {1}, {2});
  grad_outputs->push_back(internal::ResizeNearestNeighborGrad(
      scope, grad_inputs[0], x_shape,
      internal::ResizeNearestNeighborGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeNearestNeighbor", ResizeNearestNeighborGradHelper);

Status ResizeBilinearGradHelper(const Scope& scope, const Operation& op,
                                const std::vector<Output>& grad_inputs,
                                std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));
  grad_outputs->push_back(internal::ResizeBilinearGrad(
      scope, grad_inputs[0], op.input(0),
      internal::ResizeBilinearGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeBilinear", ResizeBilinearGradHelper);

Status ResizeBicubicGradHelper(const Scope& scope, const Operation& op,
                               const std::vector<Output>& grad_inputs,
                               std::vector<Output>* grad_outputs) {
  bool align_corners;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "align_corners", &align_corners));
  bool half_pixel_centers;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "half_pixel_centers",
                                 &half_pixel_centers));

  grad_outputs->push_back(internal::ResizeBicubicGrad(
      scope, grad_inputs[0], op.input(0),
      internal::ResizeBicubicGrad::AlignCorners(align_corners)
          .HalfPixelCenters(half_pixel_centers)));
  grad_outputs->push_back(NoGradient());
  return scope.status();
}
REGISTER_GRADIENT_OP("ResizeBicubic", ResizeBicubicGradHelper);

Status ScaleAndTranslateGradHelper(const Scope& scope, const Operation& op,
                                   const std::vector<Output>& grad_inputs,
                                   std::vector<Output>* grad_outputs) {
  string kernel_type;
  TF_RETURN_IF_ERROR(
      GetNodeAttr(op.node()->attrs(), "kernel_type", &kernel_type));
  bool antialias;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "antialias", &antialias));
  grad_outputs->push_back(internal::ScaleAndTranslateGrad(
      scope, grad_inputs[0], op.input(0), op.input(2), op.input(3),
      internal::ScaleAndTranslateGrad::KernelType(kernel_type)
          .Antialias(antialias)));

  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  return scope.status();
}

REGISTER_GRADIENT_OP("ScaleAndTranslate", ScaleAndTranslateGradHelper);

Status CropAndResizeGradHelper(const Scope& scope, const Operation& op,
                               const std::vector<Output>& grad_inputs,
                               std::vector<Output>* grad_outputs) {
  DataType input_type;
  string method;
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "method", &method));
  TF_RETURN_IF_ERROR(GetNodeAttr(op.node()->attrs(), "T", &input_type));
  auto image_shape = Shape(scope, op.input(0));
  grad_outputs->push_back(CropAndResizeGradImage(
      scope, grad_inputs[0], op.input(1), op.input(2), image_shape, input_type,
      CropAndResizeGradImage::Method(method)));
  grad_outputs->push_back(CropAndResizeGradBoxes(
      scope, grad_inputs[0], op.input(0), op.input(1), op.input(2)));
  grad_outputs->push_back(NoGradient());
  grad_outputs->push_back(NoGradient());
  return scope.status();
}

REGISTER_GRADIENT_OP("CropAndResize", CropAndResizeGradHelper);
}  // anonymous namespace
}  // namespace ops
}  // namespace tensorflow
<|endoftext|>


<commit_before>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_EXCEPTION_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_EXCEPTION_HPP

/** @file
*
* @brief Exception Base Class.
* @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
*/
#include <gbBase/config.hpp>

#include <exception>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <typeinfo>
#include <type_traits>

namespace GHULBUS_BASE_NAMESPACE
{
    /** Decorator type.
     * An exception type derived from `Exception` may have an arbitrary number of decorator types attached to it
     * using `operator<<`. The data attached this way may then be retrieved from the exception object by
     * calling `getErrorInfo()`.
     */
    template<typename Tag_T, typename T>
    class GHULBUS_BASE_API ErrorInfo {
    public:
        using ValueType = T;
        using TagType = Tag_T;
    private:
        T m_data;
    public:
        template<typename... Args>
        ErrorInfo(Args&&... args)
            :m_data(std::forward<Args>(args)...)
        {}

        T const& getData() const & {
            return m_data;
        }

        T&& getData() && {
            return std::move(m_data);
        }
    };

    /** Trait for detecting instantiations of `ErrorInfo`.
     */
    template<typename T>
    struct IsErrorInfo : public std::false_type {};
    template<typename Tag_T, typename T>
    struct IsErrorInfo<ErrorInfo<Tag_T, T>> : public std::true_type {};

    namespace impl {
    /** @cond
     */
    /** Helper functor for converting arbitrary types to string for printing.
     * - if `T` is std::string acts as the identity function
     * - if `T` has an overload of `to_string` found through an unqualified call, uses `to_string`
     * - if `T` has an ostream inserter defined, uses `operator<<` to insert to a `std::stringstream`
     * - otherwise use `typeid(T).name()`.
     */
    template<typename T, typename = void>
    struct toStringHelper;

    using std::to_string;

    template<typename T, typename = void>
    struct hasToString : public std::false_type {};
    template<typename T>
    struct hasToString<T, std::void_t<decltype(to_string(std::declval<T>()))>> : public std::true_type {};

    template<typename T, typename = void>
    struct hasOstreamInserter : public std::false_type {};
    template<typename T>
    struct hasOstreamInserter<T, std::void_t<decltype(std::declval<std::stringstream>() << std::declval<T>())>> : public std::true_type {};

    template<>
    struct toStringHelper<std::string> {
        std::string const& operator()(std::string const& s) {
            return s;
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> && hasToString<T>::value>> {
        std::string operator()(T const& v) {
            return to_string(v);
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> &&
                                              !hasToString<T>::value &&
                                              hasOstreamInserter<T>::value>>
    {
        std::string operator()(T const& v) {
            std::stringstream sstr;
            sstr << v;
            return std::move(sstr.str());
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> &&
                                              !hasToString<T>::value &&
                                              !hasOstreamInserter<T>::value>>
    {
        std::string operator()(T const& v) {
            return typeid(T).name();
        }
    };
    /** @endcond
    */
    }

    /** Base class for all Ghulbus exceptions.
     * Any exception can be decorated with additional info. Instantiate an Info object from the
     * Exception_Info namespace and use `operator<<` to assign it to an exception.
     * All exceptions thrown through \ref GHULBUS_THROW are decorated with Exception_Info::description and a
     * decorator for the location of the throw site of the exception, see `Exception_Info::Records::location`.
     * Individual decorators can be retrieved from an exception object with `getErrorInfo()`.
     * To obtain a textual representation of all the information for an exception,
     * use `getDiagnosticMessage`.
     *
     */
    class GHULBUS_BASE_API Exception : public virtual std::exception {
    private:
        /** Type-erased storage for ErrorInfo (base class).
         */
        class ErrorInfoConcept {
        private:
            std::unique_ptr<ErrorInfoConcept> m_next;
        public:
            ErrorInfoConcept() = default;

            explicit ErrorInfoConcept(std::unique_ptr<ErrorInfoConcept>&& next)
                :m_next(std::move(next))
            {}

            virtual ~ErrorInfoConcept() noexcept = default;
            virtual std::unique_ptr<ErrorInfoConcept> clone() const = 0;
            virtual std::type_info const& getTypeInfo() const = 0;
            virtual std::string dataString() const = 0;

            ErrorInfoConcept const* next() const {
                return m_next.get();
            }

            ErrorInfoConcept* next() {
                return m_next.get();
            }
        };

        /** Type-erased storage for ErrorInfo.
        */
        template<typename ErrorInfo_T>
        class ErrorInfoModel : public ErrorInfoConcept {
        public:
            static_assert(IsErrorInfo<ErrorInfo_T>::value,
                          "Only ErrorInfo types can be used to decorate Exception.");
            using ValueType = typename ErrorInfo_T::ValueType;
            using TagType = typename ErrorInfo_T::TagType;
        private:
            ValueType m_data;
        public:
            ErrorInfoModel(std::unique_ptr<ErrorInfoConcept>&& next, ErrorInfo_T data)
                :ErrorInfoConcept(std::move(next)), m_data(std::move(data).getData())
            {}

            ~ErrorInfoModel() noexcept override = default;

            std::unique_ptr<ErrorInfoConcept> clone() const override {
                ErrorInfoConcept const* next_ei = next();
                return std::make_unique<ErrorInfoModel>((next_ei == nullptr) ? nullptr : next_ei->clone(), m_data);
            }

            std::type_info const& getTypeInfo() const override {
                return typeid(TagType);
            }

            ValueType const& data() const {
                return m_data;
            }

            std::string dataString() const override {
                return impl::toStringHelper<decltype(data())>{}(data());
            }
        };

        std::unique_ptr<ErrorInfoConcept> mutable m_errorInfos;
        mutable char const* m_throwFile = nullptr;
        mutable char const* m_throwFunction = nullptr;
        mutable long m_throwLine = -1;
        mutable std::string m_message;
    protected:
        Exception() = default;
        virtual ~Exception() = default;

        Exception(Exception&&) noexcept = default;
        Exception& operator=(Exception&&) noexcept  = default;

        Exception(Exception const& rhs)
            :m_errorInfos(rhs.m_errorInfos->clone()),
             m_throwFile(rhs.m_throwFile), m_throwFunction(rhs.m_throwFunction), m_throwLine(rhs.m_throwLine)
        {}

        Exception& operator=(Exception const& rhs) {
            if (&rhs != this) {
                m_errorInfos = rhs.m_errorInfos->clone();
                m_throwFile = rhs.m_throwFile;
                m_throwFunction = rhs.m_throwFunction;
                m_throwLine = rhs.m_throwLine;
            }
            return *this;
        }

    public:
        /** Redeclare std::exception::what() as pure virtual.
         * We do this here so that Exception becomes abstract and to force inheriting classes to give
         * the noexcept guarantee.
         */
        virtual char const* what() const noexcept = 0;

        template<typename ErrorInfo_T>
        std::enable_if_t<IsErrorInfo<std::decay_t<ErrorInfo_T>>::value, void>
        addErrorInfo(ErrorInfo_T&& error_info) const {
            m_errorInfos = std::make_unique<
                ErrorInfoModel<std::decay_t<ErrorInfo_T>>>(std::move(m_errorInfos),
                                                           std::forward<ErrorInfo_T>(error_info));
        }

        void setExceptionLocation(char const* throw_file, char const* throw_function, long throw_line) const {
            m_throwFile = throw_file;
            m_throwFunction = throw_function;
            m_throwLine = throw_line;
        }

        template<typename ErrorInfo_T>
        typename ErrorInfo_T::ValueType const* getErrorInfo() const {
            using TagType = typename ErrorInfo_T::TagType;
            for (ErrorInfoConcept const* it = m_errorInfos.get(); it != nullptr; it = it->next()) {
                if (it->getTypeInfo() == typeid(TagType)) {
                    return &dynamic_cast<ErrorInfoModel<ErrorInfo_T> const&>(*it).data();
                }
            }
            return nullptr;
        }

        char const* getDiagnosticMessage() const {
            /*
            <file>(<line>): Throw in function <func>
            Dynamic exception type: bla
            [<TagType #1>] = <data #1>
             ...
            [<TagType #n>] = <data #n>
            */
            m_message =
                std::string((m_throwFile) ? m_throwFile : "<unknown file>") +
                '(' + std::to_string(m_throwLine) + "): Throw in function " +
                (m_throwFunction ? m_throwFunction : "<unknown function>") +
                "\nDynamic exception type: " + typeid(*this).name();
            for (ErrorInfoConcept const* it = m_errorInfos.get(); it != nullptr; it = it->next()) {
                m_message += std::string("\n[") + it->getTypeInfo().name() + "] = " + it->dataString();
            }
            return m_message.c_str();
        }
    };

    /** Exception decorators.
     * Place all exception decorators in this namespace.
     * A decorator is an instance of the boost::error_info template with a unique (empty) tag type and a record type
     * that provides storage for the information.
     * For non-trivial record-types, provide a std::ostream inserter to allow for nice automatic error messages.
     */
    namespace Exception_Info {
        /** Decorator Tags.
         * Tags are empty types used to uniquely identify a decoratory type.
         */
        namespace Tags
        {
            struct GHULBUS_BASE_API location { };
            struct GHULBUS_BASE_API description { };
            struct GHULBUS_BASE_API filename { };
        }
        /** Decorator record types.
         */
        namespace Records
        {
            struct location {
                char const* file;
                char const* function;
                long line;

                location(char const* nfile, char const* nfunc, long nline)
                    :file(nfile), function(nfunc), line(nline)
                {}
            };
        }

        /** @name Decorators
         * @{
         */
        /** A user-provided string describing the error.
         */
        using location = ErrorInfo<Tags::location, Records::location>;
        using description = ErrorInfo<Tags::description, std::string>;
        using filename = ErrorInfo<Tags::filename, std::string>;
        /// @}
    }

    /** Decorate an exception with an ErrorInfo.
     */
    template<typename Exception_T, typename ErrorInfo_T>
    inline std::enable_if_t<IsErrorInfo<std::decay_t<ErrorInfo_T>>::value &&
                            std::is_base_of_v<Exception, Exception_T>, Exception_T> const&
    operator<<(Exception_T const& e, ErrorInfo_T&& error_info) {
        e.addErrorInfo(std::forward<ErrorInfo_T>(error_info));
        return e;
    }

    /** Decorate an exception with an the Exception_Info::location error info.
     */
    template<typename Exception_T>
    inline std::enable_if_t<std::is_base_of_v<Exception, Exception_T>, Exception_T> const&
    operator<<(Exception_T const& e, Exception_Info::location l) {
        Exception_Info::Records::location const loc = l.getData();
        e.setExceptionLocation(loc.file, loc.function, loc.line);
        return e;
    }

    /** Attempts to retrieve the error decoration of type `ErrorInfo_T` from the exception `e`.
     * @return A pointer to the decorator record if it could be retrieved; `nullptr` otherwise.
     *         Retrieval may fail if `Exception_T` is not a class derived from `Exception` or
     *         if the exception does not contain a decorator of the requested type.
     */
    template<typename ErrorInfo_T, typename Exception_T>
    inline typename ErrorInfo_T::ValueType const* getErrorInfo(Exception_T const& e) {
        if (Exception const* exc = dynamic_cast<Exception const*>(&e); exc != nullptr) {
            return exc->getErrorInfo<ErrorInfo_T>();
        }
        return nullptr;
    }

    /** Helper function for retrieving a diagnostic information string about the exception.
     */
    inline char const* getDiagnosticMessage(Exception const& e) {
        return e.getDiagnosticMessage();
    }

    /** Helper function applying a variadic number of decorators to an exception.
     * @param e An exception object.
     * @param args The decorators that will be applied to the exception object e.
     * @return A reference to the exception object e.
     */
    template<typename Exception_T, typename... ExceptionInfo_Ts>
    inline auto decorate_exception(Exception_T const& e, ExceptionInfo_Ts const&... args)
    {
        return (e << ... << args);
    }

    /** Concrete exception objects.
     */
    namespace Exceptions
    {
        namespace impl
        {
            /** Mixin class for implementing Ghulbus::Exceptions.
            * This class provides a default implementation for what() that gives a detailed error message.
            */
            class GHULBUS_BASE_API ExceptionImpl : public virtual ::GHULBUS_BASE_NAMESPACE::Exception
            {
            public:
                char const* what() const noexcept override {
                    return ::GHULBUS_BASE_NAMESPACE::getDiagnosticMessage(*this);
                }
            };
        }

        /** Thrown by Assert::failThrow in case of a failing exception.
         */
        class GHULBUS_BASE_API AssertFailed : public impl::ExceptionImpl
        {
        };

        /** Thrown by interfaces that have not yet been implemented.
         */
        class GHULBUS_BASE_API NotImplemented : public impl::ExceptionImpl
        {
        };

        /** Thrown when an I/O operation fails.
         */
        class GHULBUS_BASE_API IOError : public impl::ExceptionImpl
        {
        };

        /** Thrown when an invalid argument was passed to a function.
         * This is used if an argument does not violate a function's precondition but is nonetheless invalid in the
         * given context. Precondition violations are undefined behavior and may only be signaled using GHULBUS_ASSERT.
         */
        class GHULBUS_BASE_API InvalidArgument : public impl::ExceptionImpl
        {
        };

        /** Thrown when a function call violates protocol.
         * This is used if a function call does not violate a function's precondition but is nonetheless invalid in the
         * given context. Precondition violations are undefined behavior and may only be signaled using GHULBUS_ASSERT.
         * @note Use this exception with care. Most of the time, a protocol violation is a precondition violation.
         */
        class GHULBUS_BASE_API ProtocolViolation : public impl::ExceptionImpl
        {
        };
    }
}

/** @cond
 */
#if defined _MSC_VER
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __FUNCSIG__
#elif defined __clang__
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __PRETTY_FUNCTION__
#elif defined __GNUC__
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __PRETTY_FUNCTION__
#else
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __func__
#endif
/** @endcond
 */

/** Throw a Ghulbus::Exception.
 * All exceptions thrown with this macro will be decorated with the supplied string description and information
 * about the source code location that triggered the throw.
 * @param exc An exception object inheriting from Ghulbus::Exception.
 * @param str A std::string or null-terminated C-string to attach to the exception as description.
 */
#define GHULBUS_THROW(exc, str) \
    throw ( (exc) <<                                                                            \
        ::GHULBUS_BASE_NAMESPACE::Exception_Info::location(__FILE__,                            \
                                                           GHULBUS_INTERNAL_HELPER_FUNCTION_2,  \
                                                           __LINE__) <<                         \
        ::GHULBUS_BASE_NAMESPACE::Exception_Info::description(str) )

#endif
<commit_msg>removed unnecessary std::move<commit_after>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_EXCEPTION_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_EXCEPTION_HPP

/** @file
*
* @brief Exception Base Class.
* @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
*/
#include <gbBase/config.hpp>

#include <exception>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <typeinfo>
#include <type_traits>

namespace GHULBUS_BASE_NAMESPACE
{
    /** Decorator type.
     * An exception type derived from `Exception` may have an arbitrary number of decorator types attached to it
     * using `operator<<`. The data attached this way may then be retrieved from the exception object by
     * calling `getErrorInfo()`.
     */
    template<typename Tag_T, typename T>
    class GHULBUS_BASE_API ErrorInfo {
    public:
        using ValueType = T;
        using TagType = Tag_T;
    private:
        T m_data;
    public:
        template<typename... Args>
        ErrorInfo(Args&&... args)
            :m_data(std::forward<Args>(args)...)
        {}

        T const& getData() const & {
            return m_data;
        }

        T&& getData() && {
            return std::move(m_data);
        }
    };

    /** Trait for detecting instantiations of `ErrorInfo`.
     */
    template<typename T>
    struct IsErrorInfo : public std::false_type {};
    template<typename Tag_T, typename T>
    struct IsErrorInfo<ErrorInfo<Tag_T, T>> : public std::true_type {};

    namespace impl {
    /** @cond
     */
    /** Helper functor for converting arbitrary types to string for printing.
     * - if `T` is std::string acts as the identity function
     * - if `T` has an overload of `to_string` found through an unqualified call, uses `to_string`
     * - if `T` has an ostream inserter defined, uses `operator<<` to insert to a `std::stringstream`
     * - otherwise use `typeid(T).name()`.
     */
    template<typename T, typename = void>
    struct toStringHelper;

    using std::to_string;

    template<typename T, typename = void>
    struct hasToString : public std::false_type {};
    template<typename T>
    struct hasToString<T, std::void_t<decltype(to_string(std::declval<T>()))>> : public std::true_type {};

    template<typename T, typename = void>
    struct hasOstreamInserter : public std::false_type {};
    template<typename T>
    struct hasOstreamInserter<T, std::void_t<decltype(std::declval<std::stringstream>() << std::declval<T>())>> : public std::true_type {};

    template<>
    struct toStringHelper<std::string> {
        std::string const& operator()(std::string const& s) {
            return s;
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> && hasToString<T>::value>> {
        std::string operator()(T const& v) {
            return to_string(v);
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> &&
                                              !hasToString<T>::value &&
                                              hasOstreamInserter<T>::value>>
    {
        std::string operator()(T const& v) {
            std::stringstream sstr;
            sstr << v;
            return sstr.str();
        }
    };

    template<typename T>
    struct toStringHelper<T, std::enable_if_t<!std::is_same_v<T, std::string> &&
                                              !hasToString<T>::value &&
                                              !hasOstreamInserter<T>::value>>
    {
        std::string operator()(T const& v) {
            return typeid(T).name();
        }
    };
    /** @endcond
    */
    }

    /** Base class for all Ghulbus exceptions.
     * Any exception can be decorated with additional info. Instantiate an Info object from the
     * Exception_Info namespace and use `operator<<` to assign it to an exception.
     * All exceptions thrown through \ref GHULBUS_THROW are decorated with Exception_Info::description and a
     * decorator for the location of the throw site of the exception, see `Exception_Info::Records::location`.
     * Individual decorators can be retrieved from an exception object with `getErrorInfo()`.
     * To obtain a textual representation of all the information for an exception,
     * use `getDiagnosticMessage`.
     *
     */
    class GHULBUS_BASE_API Exception : public virtual std::exception {
    private:
        /** Type-erased storage for ErrorInfo (base class).
         */
        class ErrorInfoConcept {
        private:
            std::unique_ptr<ErrorInfoConcept> m_next;
        public:
            ErrorInfoConcept() = default;

            explicit ErrorInfoConcept(std::unique_ptr<ErrorInfoConcept>&& next)
                :m_next(std::move(next))
            {}

            virtual ~ErrorInfoConcept() noexcept = default;
            virtual std::unique_ptr<ErrorInfoConcept> clone() const = 0;
            virtual std::type_info const& getTypeInfo() const = 0;
            virtual std::string dataString() const = 0;

            ErrorInfoConcept const* next() const {
                return m_next.get();
            }

            ErrorInfoConcept* next() {
                return m_next.get();
            }
        };

        /** Type-erased storage for ErrorInfo.
        */
        template<typename ErrorInfo_T>
        class ErrorInfoModel : public ErrorInfoConcept {
        public:
            static_assert(IsErrorInfo<ErrorInfo_T>::value,
                          "Only ErrorInfo types can be used to decorate Exception.");
            using ValueType = typename ErrorInfo_T::ValueType;
            using TagType = typename ErrorInfo_T::TagType;
        private:
            ValueType m_data;
        public:
            ErrorInfoModel(std::unique_ptr<ErrorInfoConcept>&& next, ErrorInfo_T data)
                :ErrorInfoConcept(std::move(next)), m_data(std::move(data).getData())
            {}

            ~ErrorInfoModel() noexcept override = default;

            std::unique_ptr<ErrorInfoConcept> clone() const override {
                ErrorInfoConcept const* next_ei = next();
                return std::make_unique<ErrorInfoModel>((next_ei == nullptr) ? nullptr : next_ei->clone(), m_data);
            }

            std::type_info const& getTypeInfo() const override {
                return typeid(TagType);
            }

            ValueType const& data() const {
                return m_data;
            }

            std::string dataString() const override {
                return impl::toStringHelper<decltype(data())>{}(data());
            }
        };

        std::unique_ptr<ErrorInfoConcept> mutable m_errorInfos;
        mutable char const* m_throwFile = nullptr;
        mutable char const* m_throwFunction = nullptr;
        mutable long m_throwLine = -1;
        mutable std::string m_message;
    protected:
        Exception() = default;
        virtual ~Exception() = default;

        Exception(Exception&&) noexcept = default;
        Exception& operator=(Exception&&) noexcept  = default;

        Exception(Exception const& rhs)
            :m_errorInfos(rhs.m_errorInfos->clone()),
             m_throwFile(rhs.m_throwFile), m_throwFunction(rhs.m_throwFunction), m_throwLine(rhs.m_throwLine)
        {}

        Exception& operator=(Exception const& rhs) {
            if (&rhs != this) {
                m_errorInfos = rhs.m_errorInfos->clone();
                m_throwFile = rhs.m_throwFile;
                m_throwFunction = rhs.m_throwFunction;
                m_throwLine = rhs.m_throwLine;
            }
            return *this;
        }

    public:
        /** Redeclare std::exception::what() as pure virtual.
         * We do this here so that Exception becomes abstract and to force inheriting classes to give
         * the noexcept guarantee.
         */
        virtual char const* what() const noexcept = 0;

        template<typename ErrorInfo_T>
        std::enable_if_t<IsErrorInfo<std::decay_t<ErrorInfo_T>>::value, void>
        addErrorInfo(ErrorInfo_T&& error_info) const {
            m_errorInfos = std::make_unique<
                ErrorInfoModel<std::decay_t<ErrorInfo_T>>>(std::move(m_errorInfos),
                                                           std::forward<ErrorInfo_T>(error_info));
        }

        void setExceptionLocation(char const* throw_file, char const* throw_function, long throw_line) const {
            m_throwFile = throw_file;
            m_throwFunction = throw_function;
            m_throwLine = throw_line;
        }

        template<typename ErrorInfo_T>
        typename ErrorInfo_T::ValueType const* getErrorInfo() const {
            using TagType = typename ErrorInfo_T::TagType;
            for (ErrorInfoConcept const* it = m_errorInfos.get(); it != nullptr; it = it->next()) {
                if (it->getTypeInfo() == typeid(TagType)) {
                    return &dynamic_cast<ErrorInfoModel<ErrorInfo_T> const&>(*it).data();
                }
            }
            return nullptr;
        }

        char const* getDiagnosticMessage() const {
            /*
            <file>(<line>): Throw in function <func>
            Dynamic exception type: bla
            [<TagType #1>] = <data #1>
             ...
            [<TagType #n>] = <data #n>
            */
            m_message =
                std::string((m_throwFile) ? m_throwFile : "<unknown file>") +
                '(' + std::to_string(m_throwLine) + "): Throw in function " +
                (m_throwFunction ? m_throwFunction : "<unknown function>") +
                "\nDynamic exception type: " + typeid(*this).name();
            for (ErrorInfoConcept const* it = m_errorInfos.get(); it != nullptr; it = it->next()) {
                m_message += std::string("\n[") + it->getTypeInfo().name() + "] = " + it->dataString();
            }
            return m_message.c_str();
        }
    };

    /** Exception decorators.
     * Place all exception decorators in this namespace.
     * A decorator is an instance of the boost::error_info template with a unique (empty) tag type and a record type
     * that provides storage for the information.
     * For non-trivial record-types, provide a std::ostream inserter to allow for nice automatic error messages.
     */
    namespace Exception_Info {
        /** Decorator Tags.
         * Tags are empty types used to uniquely identify a decoratory type.
         */
        namespace Tags
        {
            struct GHULBUS_BASE_API location { };
            struct GHULBUS_BASE_API description { };
            struct GHULBUS_BASE_API filename { };
        }
        /** Decorator record types.
         */
        namespace Records
        {
            struct location {
                char const* file;
                char const* function;
                long line;

                location(char const* nfile, char const* nfunc, long nline)
                    :file(nfile), function(nfunc), line(nline)
                {}
            };
        }

        /** @name Decorators
         * @{
         */
        /** A user-provided string describing the error.
         */
        using location = ErrorInfo<Tags::location, Records::location>;
        using description = ErrorInfo<Tags::description, std::string>;
        using filename = ErrorInfo<Tags::filename, std::string>;
        /// @}
    }

    /** Decorate an exception with an ErrorInfo.
     */
    template<typename Exception_T, typename ErrorInfo_T>
    inline std::enable_if_t<IsErrorInfo<std::decay_t<ErrorInfo_T>>::value &&
                            std::is_base_of_v<Exception, Exception_T>, Exception_T> const&
    operator<<(Exception_T const& e, ErrorInfo_T&& error_info) {
        e.addErrorInfo(std::forward<ErrorInfo_T>(error_info));
        return e;
    }

    /** Decorate an exception with an the Exception_Info::location error info.
     */
    template<typename Exception_T>
    inline std::enable_if_t<std::is_base_of_v<Exception, Exception_T>, Exception_T> const&
    operator<<(Exception_T const& e, Exception_Info::location l) {
        Exception_Info::Records::location const loc = l.getData();
        e.setExceptionLocation(loc.file, loc.function, loc.line);
        return e;
    }

    /** Attempts to retrieve the error decoration of type `ErrorInfo_T` from the exception `e`.
     * @return A pointer to the decorator record if it could be retrieved; `nullptr` otherwise.
     *         Retrieval may fail if `Exception_T` is not a class derived from `Exception` or
     *         if the exception does not contain a decorator of the requested type.
     */
    template<typename ErrorInfo_T, typename Exception_T>
    inline typename ErrorInfo_T::ValueType const* getErrorInfo(Exception_T const& e) {
        if (Exception const* exc = dynamic_cast<Exception const*>(&e); exc != nullptr) {
            return exc->getErrorInfo<ErrorInfo_T>();
        }
        return nullptr;
    }

    /** Helper function for retrieving a diagnostic information string about the exception.
     */
    inline char const* getDiagnosticMessage(Exception const& e) {
        return e.getDiagnosticMessage();
    }

    /** Helper function applying a variadic number of decorators to an exception.
     * @param e An exception object.
     * @param args The decorators that will be applied to the exception object e.
     * @return A reference to the exception object e.
     */
    template<typename Exception_T, typename... ExceptionInfo_Ts>
    inline auto decorate_exception(Exception_T const& e, ExceptionInfo_Ts const&... args)
    {
        return (e << ... << args);
    }

    /** Concrete exception objects.
     */
    namespace Exceptions
    {
        namespace impl
        {
            /** Mixin class for implementing Ghulbus::Exceptions.
            * This class provides a default implementation for what() that gives a detailed error message.
            */
            class GHULBUS_BASE_API ExceptionImpl : public virtual ::GHULBUS_BASE_NAMESPACE::Exception
            {
            public:
                char const* what() const noexcept override {
                    return ::GHULBUS_BASE_NAMESPACE::getDiagnosticMessage(*this);
                }
            };
        }

        /** Thrown by Assert::failThrow in case of a failing exception.
         */
        class GHULBUS_BASE_API AssertFailed : public impl::ExceptionImpl
        {
        };

        /** Thrown by interfaces that have not yet been implemented.
         */
        class GHULBUS_BASE_API NotImplemented : public impl::ExceptionImpl
        {
        };

        /** Thrown when an I/O operation fails.
         */
        class GHULBUS_BASE_API IOError : public impl::ExceptionImpl
        {
        };

        /** Thrown when an invalid argument was passed to a function.
         * This is used if an argument does not violate a function's precondition but is nonetheless invalid in the
         * given context. Precondition violations are undefined behavior and may only be signaled using GHULBUS_ASSERT.
         */
        class GHULBUS_BASE_API InvalidArgument : public impl::ExceptionImpl
        {
        };

        /** Thrown when a function call violates protocol.
         * This is used if a function call does not violate a function's precondition but is nonetheless invalid in the
         * given context. Precondition violations are undefined behavior and may only be signaled using GHULBUS_ASSERT.
         * @note Use this exception with care. Most of the time, a protocol violation is a precondition violation.
         */
        class GHULBUS_BASE_API ProtocolViolation : public impl::ExceptionImpl
        {
        };
    }
}

/** @cond
 */
#if defined _MSC_VER
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __FUNCSIG__
#elif defined __clang__
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __PRETTY_FUNCTION__
#elif defined __GNUC__
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __PRETTY_FUNCTION__
#else
#   define GHULBUS_INTERNAL_HELPER_FUNCTION_2 __func__
#endif
/** @endcond
 */

/** Throw a Ghulbus::Exception.
 * All exceptions thrown with this macro will be decorated with the supplied string description and information
 * about the source code location that triggered the throw.
 * @param exc An exception object inheriting from Ghulbus::Exception.
 * @param str A std::string or null-terminated C-string to attach to the exception as description.
 */
#define GHULBUS_THROW(exc, str) \
    throw ( (exc) <<                                                                            \
        ::GHULBUS_BASE_NAMESPACE::Exception_Info::location(__FILE__,                            \
                                                           GHULBUS_INTERNAL_HELPER_FUNCTION_2,  \
                                                           __LINE__) <<                         \
        ::GHULBUS_BASE_NAMESPACE::Exception_Info::description(str) )

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef IL_TARGET_MACHINE_H
#define IL_TARGET_MACHINE_H

namespace eddic {

struct TargetMachine {
    int availableRegisters();
};

} //end of eddic

#endif
<commit_msg>Remove target machine<commit_after><|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg, Daniel Wallin
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.

*/

#ifndef TORRENT_ALERT_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED

#include <memory>
#include <queue>
#include <string>
#include <typeinfo>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>

#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15
#endif

namespace libtorrent {

	class TORRENT_EXPORT alert
	{
	public:

		// only here for backwards compatibility
		enum severity_t { debug, info, warning, critical, fatal, none };

		enum category_t
		{
			error_notification = 0x1,
			peer_notification = 0x2,
			port_mapping_notification = 0x4,
			storage_notification = 0x8,
			tracker_notification = 0x10,
			debug_notification = 0x20,
			status_notification = 0x40,
			progress_notification = 0x80,
			ip_block_notification = 0x100,

			all_categories = 0xffffffff
		};

		alert();
		virtual ~alert();

		// a timestamp is automatically created in the constructor
		ptime timestamp() const;

		virtual char const* what() const = 0;
		virtual std::string message() const = 0;
		virtual int category() const = 0;

		severity_t severity() const TORRENT_DEPRECATED { return warning; }

		virtual std::auto_ptr<alert> clone() const = 0;

	private:
		ptime m_timestamp;
	};

	class TORRENT_EXPORT alert_manager
	{
	public:
		alert_manager();
		~alert_manager();

		void post_alert(const alert& alert_);
		bool pending() const;
		std::auto_ptr<alert> get();

		template <class T>
		bool should_post() const { return m_alert_mask & T::static_category; }

		alert const* wait_for_alert(time_duration max_wait);

		void set_alert_mask(int m) { m_alert_mask = m; }

	private:
		std::queue<alert*> m_alerts;
		mutable boost::mutex m_mutex;
		boost::condition m_condition;
		int m_alert_mask;
	};

	struct TORRENT_EXPORT unhandled_alert : std::exception
	{
		unhandled_alert() {}
	};

	namespace detail {

		struct void_;

		template<class Handler
			, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, class T)>
		void handle_alert_dispatch(
			const std::auto_ptr<alert>& alert_, const Handler& handler
			, const std::type_info& typeid_
			, BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p))
		{
			if (typeid_ == typeid(T0))
				handler(*static_cast<T0*>(alert_.get()));
			else
				handle_alert_dispatch(alert_, handler, typeid_
					, BOOST_PP_ENUM_SHIFTED_PARAMS(
					TORRENT_MAX_ALERT_TYPES, p), (void_*)0);
		}

		template<class Handler>
		void handle_alert_dispatch(
			const std::auto_ptr<alert>& alert_
			, const Handler& handler
			, const std::type_info& typeid_
			, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT))
		{
			throw unhandled_alert();
		}

	} // namespace detail

	template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
		TORRENT_MAX_ALERT_TYPES, class T, detail::void_)>
	struct TORRENT_EXPORT handle_alert
	{
		template<class Handler>
		handle_alert(const std::auto_ptr<alert>& alert_
			, const Handler& handler)
		{
			#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0

			detail::handle_alert_dispatch(alert_, handler, typeid(*alert_)
				, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _));

			#undef ALERT_POINTER_TYPE
		}
	};

} // namespace libtorrent

#endif // TORRENT_ALERT_HPP_INCLUDED

<commit_msg>fixed msvc warning<commit_after>/*

Copyright (c) 2003, Arvid Norberg, Daniel Wallin
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.

*/

#ifndef TORRENT_ALERT_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED

#include <memory>
#include <queue>
#include <string>
#include <typeinfo>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>

#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15
#endif

namespace libtorrent {

	class TORRENT_EXPORT alert
	{
	public:

		// only here for backwards compatibility
		enum severity_t { debug, info, warning, critical, fatal, none };

		enum category_t
		{
			error_notification = 0x1,
			peer_notification = 0x2,
			port_mapping_notification = 0x4,
			storage_notification = 0x8,
			tracker_notification = 0x10,
			debug_notification = 0x20,
			status_notification = 0x40,
			progress_notification = 0x80,
			ip_block_notification = 0x100,

			all_categories = 0xffffffff
		};

		alert();
		virtual ~alert();

		// a timestamp is automatically created in the constructor
		ptime timestamp() const;

		virtual char const* what() const = 0;
		virtual std::string message() const = 0;
		virtual int category() const = 0;

		severity_t severity() const TORRENT_DEPRECATED { return warning; }

		virtual std::auto_ptr<alert> clone() const = 0;

	private:
		ptime m_timestamp;
	};

	class TORRENT_EXPORT alert_manager
	{
	public:
		alert_manager();
		~alert_manager();

		void post_alert(const alert& alert_);
		bool pending() const;
		std::auto_ptr<alert> get();

		template <class T>
		bool should_post() const { return (m_alert_mask & T::static_category) != 0; }

		alert const* wait_for_alert(time_duration max_wait);

		void set_alert_mask(int m) { m_alert_mask = m; }

	private:
		std::queue<alert*> m_alerts;
		mutable boost::mutex m_mutex;
		boost::condition m_condition;
		int m_alert_mask;
	};

	struct TORRENT_EXPORT unhandled_alert : std::exception
	{
		unhandled_alert() {}
	};

	namespace detail {

		struct void_;

		template<class Handler
			, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, class T)>
		void handle_alert_dispatch(
			const std::auto_ptr<alert>& alert_, const Handler& handler
			, const std::type_info& typeid_
			, BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p))
		{
			if (typeid_ == typeid(T0))
				handler(*static_cast<T0*>(alert_.get()));
			else
				handle_alert_dispatch(alert_, handler, typeid_
					, BOOST_PP_ENUM_SHIFTED_PARAMS(
					TORRENT_MAX_ALERT_TYPES, p), (void_*)0);
		}

		template<class Handler>
		void handle_alert_dispatch(
			const std::auto_ptr<alert>& alert_
			, const Handler& handler
			, const std::type_info& typeid_
			, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT))
		{
			throw unhandled_alert();
		}

	} // namespace detail

	template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
		TORRENT_MAX_ALERT_TYPES, class T, detail::void_)>
	struct TORRENT_EXPORT handle_alert
	{
		template<class Handler>
		handle_alert(const std::auto_ptr<alert>& alert_
			, const Handler& handler)
		{
			#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0

			detail::handle_alert_dispatch(alert_, handler, typeid(*alert_)
				, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _));

			#undef ALERT_POINTER_TYPE
		}
	};

} // namespace libtorrent

#endif // TORRENT_ALERT_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
 * udpmulticast.hpp
 *
 *  Created on: 2015. 10. 26.
 *      Author: hwang
 */

#ifndef INCLUDE_NET_UDPMULTICAST_HPP_
#define INCLUDE_NET_UDPMULTICAST_HPP_

#include "sock.hpp"
#include <exception.hpp>

namespace cossb {
namespace net {

class udpmulticast : public sock {
public:
	udpmulticast(netType type, const char* ipv4, int port):sock(type) {
		switch(type)
		{
		case netType::CLIENT: break;
		case netType::HOST:
		{
			if((this->sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
				throw net::exception(net::excode::SOCKET_CREATE_FAIL);
			else {
				memset(&_address, 0, sizeof(_address));
				_address.sin_family = AF_INET;
				_address.sin_addr.s_addr = htonl(INADDR_ANY);
				_address.sin_port = htons(port);

				struct ip_mreq	_mreq;
				_mreq.imr_multiaddr.s_addr = inet_addr(ipv4);
				_mreq.imr_interface.s_addr = htonl(INADDR_ANY);

				//join network group
				if(::setsockopt(this->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &_mreq, sizeof(_mreq))<0)
					throw net::exception(net::excode::SOCKET_SET_ADDMEMBERSHIP_FAIL);

				//receive timeout 3 sec
				struct timeval timeout = {3, 0};
				if(setsockopt(this->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout))<0)
					throw net::exception(net::excode::SOCKET_SET_TIMEOUT_FAIL);

				//socket reuse
				unsigned int reuse = 1;
				if(setsockopt(this->sockfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
					throw net::exception(net::excode::SOCKET_SET_REUSE_FAIL);

				if(::bind(this->sockfd, (struct sockaddr*)&_address, sizeof(_address))<0) {
					throw net::exception(net::excode::SOCKET_BIND_FAIL);
				}
			}
		}
			break;
		}
	}
	virtual ~udpmulticast() { }

};

} /* namespace net */
} /* namespace cossb */

#endif /* INCLUDE_NET_UDPMULTICAST_HPP_ */
<commit_msg>remove udpmulticast class<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2021 midnightBITS
// This code is licensed under MIT license (see LICENSE for details)

#pragma once

#include <cctype>
#include <string_view>

namespace tangle {
	// Under libstdc++, std::isspace is visible as an overload set
	// consisting of more, than one function. This alias narrows this down
	// to single-function overload set available for base_parser::skip<>.
	//
	// Additionally, this gives us the possibility to slap a noexcept on this
	// one.
	inline int is_space(int c) noexcept { return std::isspace(c); }

	struct base_parser {
		std::string_view text;
		char const* pos = text.data();
		char const* end = pos + text.size();

		base_parser(std::string_view text) : text{text} {}

		bool eof() const noexcept { return pos == end; }

		template <typename Pred>
		void skip(Pred pred) noexcept(
		    noexcept(pred(std::declval<unsigned char>()))) {
			while (pos < end && pred(static_cast<unsigned char>(*pos)))
				++pos;
		}

		template <typename Pred>
		void skip_until(Pred pred) noexcept(
		    noexcept(pred(std::declval<unsigned char>()))) {
			while (pos < end && !pred(static_cast<unsigned char>(*pos)))
				++pos;
		}

		template <char... C>
		void look_for() noexcept {
			skip_until([](int c) noexcept { return ((C == c) || ...); });
		}

		template <char... C>
		std::string_view text_until() noexcept {
			return substr<base_parser>([](auto& self) noexcept {
				self.template look_for<C...>();
			});
		}

		template <typename Final, typename Oper>
		std::string_view substr(Oper op) noexcept(
		    noexcept(op(std::declval<Final&>()))) {
			auto start = pos;
			op(*static_cast<Final*>(this));
			return {start, static_cast<size_t>(pos - start)};
		}

		void skip_ws() noexcept { skip(is_space); }

		bool peek(char c) noexcept { return pos < end && *pos == c; }
		bool get(char c) noexcept {
			auto const result = peek(c);
			if (result) ++pos;
			return result;
		}
	};
}  // namespace tangle
<commit_msg>Add is<Pred>() and index() to base_parser<commit_after>// Copyright (c) 2021 midnightBITS
// This code is licensed under MIT license (see LICENSE for details)

#pragma once

#include <cctype>
#include <string_view>

namespace tangle {
	// Under libstdc++, std::isspace is visible as an overload set
	// consisting of more, than one function. This alias narrows this down
	// to single-function overload set available for base_parser::skip<>.
	//
	// Additionally, this gives us the possibility to slap a noexcept on this
	// one.
	inline int is_space(int c) noexcept { return std::isspace(c); }

	struct base_parser {
		std::string_view text;
		char const* pos = text.data();
		char const* end = pos + text.size();

		base_parser(std::string_view text) : text{text} {}

		bool eof() const noexcept { return pos == end; }

		template <typename Pred>
		bool is(Pred pred) const
		    noexcept(noexcept(pred(std::declval<unsigned char>()))) {
			return pos < end && pred(static_cast<unsigned char>(*pos));
		}

		template <typename Pred>
		void skip(Pred pred) noexcept(
		    noexcept(pred(std::declval<unsigned char>()))) {
			while (pos < end && pred(static_cast<unsigned char>(*pos)))
				++pos;
		}

		template <typename Pred>
		void skip_until(Pred pred) noexcept(
		    noexcept(pred(std::declval<unsigned char>()))) {
			while (pos < end && !pred(static_cast<unsigned char>(*pos)))
				++pos;
		}

		template <char... C>
		void look_for() noexcept {
			skip_until([](int c) noexcept { return ((C == c) || ...); });
		}

		template <char... C>
		std::string_view text_until() noexcept {
			return substr<base_parser>([](auto& self) noexcept {
				self.template look_for<C...>();
			});
		}

		template <typename Final, typename Oper>
		std::string_view substr(Oper op) noexcept(
		    noexcept(op(std::declval<Final&>()))) {
			auto start = pos;
			op(*static_cast<Final*>(this));
			return {start, static_cast<size_t>(pos - start)};
		}

		void skip_ws() noexcept { skip(is_space); }

		bool peek(char c) const noexcept { return pos < end && *pos == c; }
		bool get(char c) noexcept {
			auto const result = peek(c);
			if (result) ++pos;
			return result;
		}

		size_t index_of(char const* ptr) const noexcept {
			return static_cast<size_t>(ptr - text.data());
		}

		size_t index() const noexcept { return index_of(pos); }
	};
}  // namespace tangle
<|endoftext|>


<commit_before>/* Definition of the pqxx::stream_from class.
 *
 * pqxx::stream_from enables optimized batch reads from a database table.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_STREAM_FROM
#define PQXX_H_STREAM_FROM

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cassert>
#include <functional>
#include <variant>

#include "pqxx/except.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/internal/stream_iterator.hxx"
#include "pqxx/internal/transaction_focus.hxx"
#include "pqxx/separated_list.hxx"
#include "pqxx/transaction_base.hxx"

namespace pqxx
{
/// Pass this to a @c stream_from constructor to stream table contents.
constexpr from_table_t from_table;
/// Pass this to a @c stream_from constructor to stream query results.
constexpr from_query_t from_query;

/// Stream data from the database.
/** Retrieving data this way is likely to be faster than executing a query and
 * then iterating and converting the rows fields.  You will also be able to
 * start processing before all of the data has come in.
 *
 * There are also downsides.  If there's an error, it may leave the entire
 * connection in an unusable state, so you'll have to give the whole thing up.
 * Also, your connection to the database may break before you've received all
 * the data, so you may end up processing only part of the data.  Finally,
 * opening a stream puts the connection in a special state, so you won't be
 * able to do many other things with the connection or the transaction while
 * the stream is open.
 *
 * There are two ways of starting a stream: you stream either all rows in a
 * table (in which case, use a constructor which accepts @c pqxx::from_table),
 * or the results of a query (in which case, use a concstructor which accepts
 * @c pqxx::from_query).
 *
 * Usually you'll want the @c stream convenience wrapper in transaction_base,
 * so you don't need to deal with this class directly.
 */
class PQXX_LIBEXPORT stream_from : internal::transactionfocus
{
public:
  using raw_line =
    std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;

  /// Execute query, and stream over the results.
  /** The query can be a SELECT query or a VALUES query; or it can be an
   * UPDATE, INSERT, or DELETE with a RETURNING clause.
   *
   * The query is executed as part of a COPY statement, so there are additional
   * restrictions on what kind of query you can use here.  See the PostgreSQL
   * documentation for the COPY command:
   *
   *     https://www.postgresql.org/docs/current/sql-copy.html
   */
  stream_from(transaction_base &, from_query_t, std::string_view query);

  /// Stream all rows in table, all columns.
  stream_from(transaction_base &, from_table_t, std::string_view table);

  /// Stream given columns from all rows in table.
  template<typename Iter>
  stream_from(
    transaction_base &, from_table_t, std::string_view table,
    Iter columns_begin, Iter columns_end);

  /// Stream given columns from all rows in table.
  template<typename Columns>
  stream_from(
    transaction_base &tx, from_table_t, std::string_view table,
    Columns const &columns);

  /// @deprecated Use the @c from_table_t overload instead.
  stream_from(transaction_base &tx, std::string_view table) :
          stream_from{tx, from_table, table}
  {}

  /// @deprecated Use the @c from_table_t overload instead.
  template<typename Columns>
  stream_from(
    transaction_base &tx, std::string_view table, Columns const &columns) :
          stream_from{tx, from_table, table, columns}
  {}

  /// @deprecated Use the @c from_table_t overload instead.
  template<typename Iter>
  stream_from(
    transaction_base &, std::string_view table, Iter columns_begin,
    Iter columns_end);

  ~stream_from() noexcept;

  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
  [[nodiscard]] bool operator!() const noexcept { return m_finished; }

  /// Finish this stream.  Call this before continuing to use the connection.
  /** Consumes all remaining lines, and closes the stream.
   *
   * This may take a while if you're abandoning the stream before it's done, so
   * skip it in error scenarios where you're not planning to use the connection
   * again afterwards.
   */
  void complete();

  /// Read one row into a tuple.
  /** Converts the row's fields into the fields making up the tuple.
   *
   * For a column which can contain nulls, be sure to give the corresponding
   * tuple field a type which can be null.  For example, to read a field as
   * @c int when it may contain nulls, read it as @c std::optional<int>.
   * Using @c std::shared_ptr or @c std::unique_ptr will also work.
   */
  template<typename Tuple> stream_from &operator>>(Tuple &);

  /// Doing this with a @c std::variant is going to be horrifically borked.
  template<typename... Vs>
  stream_from &operator>>(std::variant<Vs...> &) = delete;

  /// Iterate over this stream.  Supports range-based "for" loops.
  /** Produces an input iterator over the stream.
   *
   * Do not call this yourself.  Use it like "for (auto data : stream.iter())".
   */
  template<typename... TYPE>[[nodiscard]] auto iter()
  {
    return pqxx::internal::stream_input_iteration<TYPE...>{*this};
  }

  /// Read a row.  Return fields as views, valid until you read the next row.
  /** Do not access the vector, or the storage referenced by the views, after
   * closing or completing the stream, or after reading a next row.
   *
   * A @c pqxx::zview is like a @c std::string_view, but with the added
   * guarantee that if its data pointer is non-null, the string is followed by
   * a terminating zero (which falls just outside the view itself).
   *
   * If any of the views' data pointer is null, that means that the
   * corresponding SQL field is null.
   */
  std::vector<zview> const &read_row();

  /// Read a raw line of text from the COPY command.
  /** @warn Do not use this unless you really know what you're doing. */
  raw_line get_raw_line();

private:
  stream_from(
    transaction_base &tx, std::string_view table, std::string &&columns,
    from_table_t);

  template<typename Tuple, std::size_t... indexes>
  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
  {
    (extract_value<Tuple, indexes>(t), ...);
  }

  static std::string compose_query(
    transaction_base const &tx, std::string_view table,
    std::string const &columns);

  pqxx::internal::glyph_scanner_func *m_glyph_scanner;

  /// Current row's fields' text, combined into one reusable string.
  std::string m_row;

  /// The current row's fields.
  std::vector<zview> m_fields;

  bool m_finished = false;

  void close();

  template<typename Tuple, std::size_t index>
  void extract_value(Tuple &) const;

  /// Read a line of COPY data, write @c m_row and @c m_fields.
  void parse_line();
};

template<typename Columns>
inline stream_from::stream_from(
  transaction_base &tb, from_table_t, std::string_view table_name,
  Columns const &columns) :
        stream_from{
          tb, from_table, table_name, std::begin(columns), std::end(columns)}
{}

template<typename Iter>
inline stream_from::stream_from(
  transaction_base &tx, from_table_t, std::string_view table,
  Iter columns_begin, Iter columns_end) :
        stream_from{
          tx, table, separated_list(",", columns_begin, columns_end),
          from_table}
{}

template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
{
  if (m_finished)
    return *this;
  constexpr auto tup_size{std::tuple_size_v<Tuple>};
  m_fields.reserve(tup_size);
  parse_line();
  if (m_finished)
    return *this;

  if (m_fields.size() != tup_size)
    throw usage_error{
      "Tried to extract " + to_string(tup_size) +
      " field(s) from a stream of " + to_string(m_fields.size()) + "."};

  extract_fields(t, std::make_index_sequence<tup_size>{});
  return *this;
}

template<typename Tuple, std::size_t index>
inline void stream_from::extract_value(Tuple &t) const
{
  using field_type = strip_t<decltype(std::get<index>(t))>;
  using nullity = nullness<field_type>;
  assert(index < m_fields.size());
  if constexpr (nullity::always_null)
  {
    if (m_fields[index].data() != nullptr)
      throw conversion_error{"Streaming non-null value into null field."};
  }
  else if (m_fields[index].data() == nullptr)
  {
    if constexpr (nullity::has_null)
      std::get<index>(t) = nullity::null();
    else
      internal::throw_null_conversion(type_name<field_type>);
  }
  else
  {
    // Don't ever try to convert a non-null value to nullptr_t!
    std::get<index>(t) = from_string<field_type>(m_fields[index]);
  }
}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<commit_msg>Document: `stream_from` tables and schemas.<commit_after>/* Definition of the pqxx::stream_from class.
 *
 * pqxx::stream_from enables optimized batch reads from a database table.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
 *
 * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this
 * mistake, or contact the author.
 */
#ifndef PQXX_H_STREAM_FROM
#define PQXX_H_STREAM_FROM

#include "pqxx/compiler-public.hxx"
#include "pqxx/internal/compiler-internal-pre.hxx"

#include <cassert>
#include <functional>
#include <variant>

#include "pqxx/except.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/internal/stream_iterator.hxx"
#include "pqxx/internal/transaction_focus.hxx"
#include "pqxx/separated_list.hxx"
#include "pqxx/transaction_base.hxx"

namespace pqxx
{
/// Pass this to a @c stream_from constructor to stream table contents.
constexpr from_table_t from_table;
/// Pass this to a @c stream_from constructor to stream query results.
constexpr from_query_t from_query;

/// Stream data from the database.
/** Retrieving data this way is likely to be faster than executing a query and
 * then iterating and converting the rows fields.  You will also be able to
 * start processing before all of the data has come in.
 *
 * There are also downsides.  If there's an error, it may leave the entire
 * connection in an unusable state, so you'll have to give the whole thing up.
 * Also, your connection to the database may break before you've received all
 * the data, so you may end up processing only part of the data.  Finally,
 * opening a stream puts the connection in a special state, so you won't be
 * able to do many other things with the connection or the transaction while
 * the stream is open.
 *
 * There are two ways of starting a stream: you stream either all rows in a
 * table (in which case, use a constructor which accepts @c pqxx::from_table),
 * or the results of a query (in which case, use a concstructor which accepts
 * @c pqxx::from_query).
 *
 * Usually you'll want the @c stream convenience wrapper in transaction_base,
 * so you don't need to deal with this class directly.
 */
class PQXX_LIBEXPORT stream_from : internal::transactionfocus
{
public:
  using raw_line =
    std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;

  /// Execute query, and stream over the results.
  /** The query can be a SELECT query or a VALUES query; or it can be an
   * UPDATE, INSERT, or DELETE with a RETURNING clause.
   *
   * The query is executed as part of a COPY statement, so there are additional
   * restrictions on what kind of query you can use here.  See the PostgreSQL
   * documentation for the COPY command:
   *
   *     https://www.postgresql.org/docs/current/sql-copy.html
   */
  stream_from(transaction_base &, from_query_t, std::string_view query);

  /// Stream all rows in table, all columns.
  /** The table name cannot include a schema name.  If you need to specify a
   * schema name, stream from a query rather than from a table.
   */
  stream_from(transaction_base &, from_table_t, std::string_view table);

  /// Stream given columns from all rows in table.
  /** The table name cannot include a schema name.  If you need to specify a
   * schema name, stream from a query rather than from a table.
   */
  template<typename Iter>
  stream_from(
    transaction_base &, from_table_t, std::string_view table,
    Iter columns_begin, Iter columns_end);

  /// Stream given columns from all rows in table.
  /** The table name cannot include a schema name.  If you need to specify a
   * schema name, stream from a query rather than from a table.
   */
  template<typename Columns>
  stream_from(
    transaction_base &tx, from_table_t, std::string_view table,
    Columns const &columns);

  /// @deprecated Use the @c from_table_t overload instead.
  stream_from(transaction_base &tx, std::string_view table) :
          stream_from{tx, from_table, table}
  {}

  /// @deprecated Use the @c from_table_t overload instead.
  template<typename Columns>
  stream_from(
    transaction_base &tx, std::string_view table, Columns const &columns) :
          stream_from{tx, from_table, table, columns}
  {}

  /// @deprecated Use the @c from_table_t overload instead.
  template<typename Iter>
  stream_from(
    transaction_base &, std::string_view table, Iter columns_begin,
    Iter columns_end);

  ~stream_from() noexcept;

  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
  [[nodiscard]] bool operator!() const noexcept { return m_finished; }

  /// Finish this stream.  Call this before continuing to use the connection.
  /** Consumes all remaining lines, and closes the stream.
   *
   * This may take a while if you're abandoning the stream before it's done, so
   * skip it in error scenarios where you're not planning to use the connection
   * again afterwards.
   */
  void complete();

  /// Read one row into a tuple.
  /** Converts the row's fields into the fields making up the tuple.
   *
   * For a column which can contain nulls, be sure to give the corresponding
   * tuple field a type which can be null.  For example, to read a field as
   * @c int when it may contain nulls, read it as @c std::optional<int>.
   * Using @c std::shared_ptr or @c std::unique_ptr will also work.
   */
  template<typename Tuple> stream_from &operator>>(Tuple &);

  /// Doing this with a @c std::variant is going to be horrifically borked.
  template<typename... Vs>
  stream_from &operator>>(std::variant<Vs...> &) = delete;

  /// Iterate over this stream.  Supports range-based "for" loops.
  /** Produces an input iterator over the stream.
   *
   * Do not call this yourself.  Use it like "for (auto data : stream.iter())".
   */
  template<typename... TYPE>[[nodiscard]] auto iter()
  {
    return pqxx::internal::stream_input_iteration<TYPE...>{*this};
  }

  /// Read a row.  Return fields as views, valid until you read the next row.
  /** Do not access the vector, or the storage referenced by the views, after
   * closing or completing the stream, or after reading a next row.
   *
   * A @c pqxx::zview is like a @c std::string_view, but with the added
   * guarantee that if its data pointer is non-null, the string is followed by
   * a terminating zero (which falls just outside the view itself).
   *
   * If any of the views' data pointer is null, that means that the
   * corresponding SQL field is null.
   */
  std::vector<zview> const &read_row();

  /// Read a raw line of text from the COPY command.
  /** @warn Do not use this unless you really know what you're doing. */
  raw_line get_raw_line();

private:
  stream_from(
    transaction_base &tx, std::string_view table, std::string &&columns,
    from_table_t);

  template<typename Tuple, std::size_t... indexes>
  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
  {
    (extract_value<Tuple, indexes>(t), ...);
  }

  static std::string compose_query(
    transaction_base const &tx, std::string_view table,
    std::string const &columns);

  pqxx::internal::glyph_scanner_func *m_glyph_scanner;

  /// Current row's fields' text, combined into one reusable string.
  std::string m_row;

  /// The current row's fields.
  std::vector<zview> m_fields;

  bool m_finished = false;

  void close();

  template<typename Tuple, std::size_t index>
  void extract_value(Tuple &) const;

  /// Read a line of COPY data, write @c m_row and @c m_fields.
  void parse_line();
};

template<typename Columns>
inline stream_from::stream_from(
  transaction_base &tb, from_table_t, std::string_view table_name,
  Columns const &columns) :
        stream_from{
          tb, from_table, table_name, std::begin(columns), std::end(columns)}
{}

template<typename Iter>
inline stream_from::stream_from(
  transaction_base &tx, from_table_t, std::string_view table,
  Iter columns_begin, Iter columns_end) :
        stream_from{
          tx, table, separated_list(",", columns_begin, columns_end),
          from_table}
{}

template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
{
  if (m_finished)
    return *this;
  constexpr auto tup_size{std::tuple_size_v<Tuple>};
  m_fields.reserve(tup_size);
  parse_line();
  if (m_finished)
    return *this;

  if (m_fields.size() != tup_size)
    throw usage_error{
      "Tried to extract " + to_string(tup_size) +
      " field(s) from a stream of " + to_string(m_fields.size()) + "."};

  extract_fields(t, std::make_index_sequence<tup_size>{});
  return *this;
}

template<typename Tuple, std::size_t index>
inline void stream_from::extract_value(Tuple &t) const
{
  using field_type = strip_t<decltype(std::get<index>(t))>;
  using nullity = nullness<field_type>;
  assert(index < m_fields.size());
  if constexpr (nullity::always_null)
  {
    if (m_fields[index].data() != nullptr)
      throw conversion_error{"Streaming non-null value into null field."};
  }
  else if (m_fields[index].data() == nullptr)
  {
    if constexpr (nullity::has_null)
      std::get<index>(t) = nullity::null();
    else
      internal::throw_null_conversion(type_name<field_type>);
  }
  else
  {
    // Don't ever try to convert a non-null value to nullptr_t!
    std::get<index>(t) = from_string<field_type>(m_fields[index]);
  }
}
} // namespace pqxx

#include "pqxx/internal/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2007-2008, Python File Format Interface
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 Python File Format Interface
     project 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.

*/

#ifndef __EXCEPTIONS_HPP
#define __EXCEPTIONS_HPP

#include <stdexcept>

namespace pyffi {

//! Thrown on name mismatch.
class name_error : public std::runtime_error {
public:
	name_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on type mismatch.
class type_error : public std::runtime_error {
public:
	type_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on value mismatch.
class value_error : public std::runtime_error {
public:
	value_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

}; // namespace pyffi

#endif
<commit_msg>new exceptions<commit_after>/*

Copyright (c) 2007-2008, Python File Format Interface
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 Python File Format Interface
     project 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.

*/

#ifndef __EXCEPTIONS_HPP
#define __EXCEPTIONS_HPP

#include <stdexcept>

namespace pyffi {

//! Thrown on name mismatch.
class name_error : public std::runtime_error {
public:
	name_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on type mismatch.
class type_error : public std::runtime_error {
public:
	type_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on value mismatch.
class value_error : public std::runtime_error {
public:
	value_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on attribute mismatch.
class attribute_error : public std::runtime_error {
public:
	attribute_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

//! Thrown on key mismatch.
class key_error : public std::runtime_error {
public:
	key_error(const std::string & msg)
			: std::runtime_error(msg) {};
};

}; // namespace pyffi

#endif
<|endoftext|>