<commit_before>#pragma once

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include "common.hpp"
#include "components/logger.hpp"
#include "components/x11/xresources.hpp"
#include "utils/file.hpp"
#include "utils/string.hpp"

LEMONBUDDY_NS

#define GET_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name, var)
#define REQ_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name)

using ptree = boost::property_tree::ptree;

DEFINE_ERROR(value_error);
DEFINE_ERROR(key_error);

class config {
 public:
  /**
   * Construct config
   */
  explicit config(const logger& logger, const xresource_manager& xrm)
      : m_logger(logger), m_xrm(xrm) {}

  /**
   * Load configuration and validate bar section
   *
   * This is done outside the constructor due to boost::di noexcept
   */
  void load(string file, string barname) {
    m_file = file;
    m_current_bar = barname;

    if (!file_util::exists(file))
      throw application_error("Could not find config file: " + file);

    try {
      boost::property_tree::read_ini(file, m_ptree);
    } catch (const std::exception& e) {
      throw application_error(e.what());
    }

    auto bars = defined_bars();
    if (std::find(bars.begin(), bars.end(), m_current_bar) == bars.end())
      throw application_error("Undefined bar: " + m_current_bar);

    if (has_env("XDG_CONFIG_HOME"))
      file = string_util::replace(file, read_env("XDG_CONFIG_HOME"), "$XDG_CONFIG_HOME");
    if (has_env("HOME"))
      file = string_util::replace(file, read_env("HOME"), "~");
    m_logger.trace("config: Loaded %s", file);
    m_logger.trace("config: Current bar section: [%s]", bar_section());
  }

  /**
   * Get path of loaded file
   */
  string filepath() const {
    return m_file;
  }

  /**
   * Get the section name of the bar in use
   */
  string bar_section() const {
    return "bar/" + m_current_bar;
  }

  /**
   * Get a list of defined bar sections in the current config
   */
  vector<string> defined_bars() const {
    vector<string> bars;

    for (auto&& p : m_ptree) {
      if (p.first.compare(0, 4, "bar/") == 0)
        bars.emplace_back(p.first.substr(4));
    }

    return bars;
  }

  /**
   * Build path used to find a parameter in the given section
   */
  string build_path(const string& section, const string& key) const {
    return section + "." + key;
  }

  /**
   * Get parameter for the current bar by name
   */
  template <typename T>
  T get(string key) const {
    return get<T>(bar_section(), key);
  }

  /**
   * Get value of a variable by section and parameter name
   */
  template <typename T>
  T get(string section, string key) const {
    auto val = m_ptree.get_optional<T>(build_path(section, key));

    if (val == boost::none)
      throw key_error("Missing parameter [" + section + "." + key + "]");

    auto str_val = m_ptree.get<string>(build_path(section, key));

    return dereference_var<T>(section, key, str_val, val.get());
  }

  /**
   * Get value of a variable by section and parameter name
   * with a default value in case the parameter isn't defined
   */
  template <typename T>
  T get(string section, string key, T default_value) const {
    auto val = m_ptree.get_optional<T>(build_path(section, key));
    auto str_val = m_ptree.get_optional<string>(build_path(section, key));

    return dereference_var<T>(
        section, key, str_val.get_value_or(""), val.get_value_or(default_value));
  }

  /**
   * Get list of values for the current bar by name
   */
  template <typename T>
  T get_list(string key) const {
    return get_list<T>(bar_section(), key);
  }

  /**
   * Get list of values by section and parameter name
   */
  template <typename T>
  vector<T> get_list(string section, string key) const {
    vector<T> vec;
    optional<T> value;

    while ((value = m_ptree.get_optional<T>(
                build_path(section, key) + "-" + to_string(vec.size()))) != boost::none) {
      auto str_val = m_ptree.get<string>(build_path(section, key) + "-" + to_string(vec.size()));
      vec.emplace_back(dereference_var<T>(section, key, str_val, value.get()));
    }

    if (vec.empty())
      throw key_error("Missing parameter [" + section + "." + key + "-0]");

    return vec;
  }

  /**
   * Get list of values by section and parameter name
   * with a default list in case the list isn't defined
   */
  template <typename T>
  vector<T> get_list(string section, string key, vector<T> default_value) const {
    vector<T> vec;
    optional<T> value;

    while ((value = m_ptree.get_optional<T>(
                build_path(section, key) + "-" + to_string(vec.size()))) != boost::none) {
      auto str_val = m_ptree.get<string>(build_path(section, key) + "-" + to_string(vec.size()));
      vec.emplace_back(dereference_var<T>(section, key, str_val, value.get()));
    }

    if (vec.empty())
      return default_value;
    else
      return vec;
  }

  /**
   * Configure injection module
   */
  template <typename T = const config&>
  static di::injector<T> configure() {
    return di::make_injector(logger::configure(), xresource_manager::configure());
  }

 protected:
  /**
   * Find value of a config parameter defined as a reference
   * variable using ${section.param} or ${env:VAR}
   * ${self.key} may be used to reference the current bar section
   *
   * @deprecated: ${BAR.key} has been replaced with ${self.key}
   * but the former is kept to avoid breaking current configs
   */
  template <typename T>
  T dereference_var(string ref_section, string ref_key, string var, const T ref_val) const {
    auto n = var.find("${");
    auto m = var.find("}");

    if (n != 0 || m != var.length() - 1)
      return ref_val;

    auto path = var.substr(2, m - 2);

    if (path.find("env:") == 0) {
      if (has_env(path.substr(4).c_str()))
        return boost::lexical_cast<T>(read_env(path.substr(4).c_str()));
      return ref_val;
    }

    if (path.find("xrdb:") == 0) {
      if (std::is_same<string, T>())
        return boost::lexical_cast<T>(m_xrm.get_string(path.substr(5)));
      else if (std::is_same<float, T>())
        return boost::lexical_cast<T>(m_xrm.get_float(path.substr(5)));
      else if (std::is_same<int, T>())
        return boost::lexical_cast<T>(m_xrm.get_int(path.substr(5)));
    }

    auto ref_path = build_path(ref_section, ref_key);

    if ((n = path.find(".")) == string::npos)
      throw value_error("Invalid reference defined at [" + ref_path + "]");

    auto section = path.substr(0, n);

    section = string_util::replace(section, "BAR", bar_section());
    section = string_util::replace(section, "self", bar_section());

    auto key = path.substr(n + 1, path.length() - n - 1);
    auto val = m_ptree.get_optional<T>(build_path(section, key));

    if (val == boost::none)
      throw value_error("Unexisting reference defined at [" + ref_path + "]");

    auto str_val = m_ptree.get<string>(build_path(section, key));

    return dereference_var<T>(section, key, str_val, val.get());
  }

 private:
  const logger& m_logger;
  const xresource_manager& m_xrm;
  ptree m_ptree;
  string m_file;
  string m_current_bar;
};

LEMONBUDDY_NS_END
<commit_msg>fix(config): Test type and not value<commit_after>#pragma once

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include "common.hpp"
#include "components/logger.hpp"
#include "components/x11/xresources.hpp"
#include "utils/file.hpp"
#include "utils/string.hpp"

LEMONBUDDY_NS

#define GET_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name, var)
#define REQ_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name)

using ptree = boost::property_tree::ptree;

DEFINE_ERROR(value_error);
DEFINE_ERROR(key_error);

class config {
 public:
  /**
   * Construct config
   */
  explicit config(const logger& logger, const xresource_manager& xrm)
      : m_logger(logger), m_xrm(xrm) {}

  /**
   * Load configuration and validate bar section
   *
   * This is done outside the constructor due to boost::di noexcept
   */
  void load(string file, string barname) {
    m_file = file;
    m_current_bar = barname;

    if (!file_util::exists(file))
      throw application_error("Could not find config file: " + file);

    try {
      boost::property_tree::read_ini(file, m_ptree);
    } catch (const std::exception& e) {
      throw application_error(e.what());
    }

    auto bars = defined_bars();
    if (std::find(bars.begin(), bars.end(), m_current_bar) == bars.end())
      throw application_error("Undefined bar: " + m_current_bar);

    if (has_env("XDG_CONFIG_HOME"))
      file = string_util::replace(file, read_env("XDG_CONFIG_HOME"), "$XDG_CONFIG_HOME");
    if (has_env("HOME"))
      file = string_util::replace(file, read_env("HOME"), "~");
    m_logger.trace("config: Loaded %s", file);
    m_logger.trace("config: Current bar section: [%s]", bar_section());
  }

  /**
   * Get path of loaded file
   */
  string filepath() const {
    return m_file;
  }

  /**
   * Get the section name of the bar in use
   */
  string bar_section() const {
    return "bar/" + m_current_bar;
  }

  /**
   * Get a list of defined bar sections in the current config
   */
  vector<string> defined_bars() const {
    vector<string> bars;

    for (auto&& p : m_ptree) {
      if (p.first.compare(0, 4, "bar/") == 0)
        bars.emplace_back(p.first.substr(4));
    }

    return bars;
  }

  /**
   * Build path used to find a parameter in the given section
   */
  string build_path(const string& section, const string& key) const {
    return section + "." + key;
  }

  /**
   * Get parameter for the current bar by name
   */
  template <typename T>
  T get(string key) const {
    return get<T>(bar_section(), key);
  }

  /**
   * Get value of a variable by section and parameter name
   */
  template <typename T>
  T get(string section, string key) const {
    auto val = m_ptree.get_optional<T>(build_path(section, key));

    if (val == boost::none)
      throw key_error("Missing parameter [" + section + "." + key + "]");

    auto str_val = m_ptree.get<string>(build_path(section, key));

    return dereference_var<T>(section, key, str_val, val.get());
  }

  /**
   * Get value of a variable by section and parameter name
   * with a default value in case the parameter isn't defined
   */
  template <typename T>
  T get(string section, string key, T default_value) const {
    auto val = m_ptree.get_optional<T>(build_path(section, key));
    auto str_val = m_ptree.get_optional<string>(build_path(section, key));

    return dereference_var<T>(
        section, key, str_val.get_value_or(""), val.get_value_or(default_value));
  }

  /**
   * Get list of values for the current bar by name
   */
  template <typename T>
  T get_list(string key) const {
    return get_list<T>(bar_section(), key);
  }

  /**
   * Get list of values by section and parameter name
   */
  template <typename T>
  vector<T> get_list(string section, string key) const {
    vector<T> vec;
    optional<T> value;

    while ((value = m_ptree.get_optional<T>(
                build_path(section, key) + "-" + to_string(vec.size()))) != boost::none) {
      auto str_val = m_ptree.get<string>(build_path(section, key) + "-" + to_string(vec.size()));
      vec.emplace_back(dereference_var<T>(section, key, str_val, value.get()));
    }

    if (vec.empty())
      throw key_error("Missing parameter [" + section + "." + key + "-0]");

    return vec;
  }

  /**
   * Get list of values by section and parameter name
   * with a default list in case the list isn't defined
   */
  template <typename T>
  vector<T> get_list(string section, string key, vector<T> default_value) const {
    vector<T> vec;
    optional<T> value;

    while ((value = m_ptree.get_optional<T>(
                build_path(section, key) + "-" + to_string(vec.size()))) != boost::none) {
      auto str_val = m_ptree.get<string>(build_path(section, key) + "-" + to_string(vec.size()));
      vec.emplace_back(dereference_var<T>(section, key, str_val, value.get()));
    }

    if (vec.empty())
      return default_value;
    else
      return vec;
  }

  /**
   * Configure injection module
   */
  template <typename T = const config&>
  static di::injector<T> configure() {
    return di::make_injector(logger::configure(), xresource_manager::configure());
  }

 protected:
  /**
   * Find value of a config parameter defined as a reference
   * variable using ${section.param} or ${env:VAR}
   * ${self.key} may be used to reference the current bar section
   *
   * @deprecated: ${BAR.key} has been replaced with ${self.key}
   * but the former is kept to avoid breaking current configs
   */
  template <typename T>
  T dereference_var(string ref_section, string ref_key, string var, const T ref_val) const {
    auto n = var.find("${");
    auto m = var.find("}");

    if (n != 0 || m != var.length() - 1)
      return ref_val;

    auto path = var.substr(2, m - 2);

    if (path.find("env:") == 0) {
      if (has_env(path.substr(4).c_str()))
        return boost::lexical_cast<T>(read_env(path.substr(4).c_str()));
      return ref_val;
    }

    if (path.find("xrdb:") == 0) {
      if (std::is_same<string, T>::value)
        return boost::lexical_cast<T>(m_xrm.get_string(path.substr(5)));
      else if (std::is_same<float, T>::value)
        return boost::lexical_cast<T>(m_xrm.get_float(path.substr(5)));
      else if (std::is_same<int, T>::value)
        return boost::lexical_cast<T>(m_xrm.get_int(path.substr(5)));
      return ref_val;
    }

    auto ref_path = build_path(ref_section, ref_key);

    if ((n = path.find(".")) == string::npos)
      throw value_error("Invalid reference defined at [" + ref_path + "]");

    auto section = path.substr(0, n);

    section = string_util::replace(section, "BAR", bar_section());
    section = string_util::replace(section, "self", bar_section());

    auto key = path.substr(n + 1, path.length() - n - 1);
    auto val = m_ptree.get_optional<T>(build_path(section, key));

    if (val == boost::none)
      throw value_error("Unexisting reference defined at [" + ref_path + "]");

    auto str_val = m_ptree.get<string>(build_path(section, key));

    return dereference_var<T>(section, key, str_val, val.get());
  }

 private:
  const logger& m_logger;
  const xresource_manager& m_xrm;
  ptree m_ptree;
  string m_file;
  string m_current_bar;
};

LEMONBUDDY_NS_END
<|endoftext|>


<commit_before>#pragma once
/*
* Covariant Script Version Info
*
* 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.
*
* Copyright (C) 2018 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*
* Version Format:
*   1 . 0 . 0 [Version Code](Preview/Unstable/Stable) Build 1
*   |   |   |                           |
*   |   | Minor                       Status
*   | Major
* Master
*
*/
#define COVSCRIPT_VERSION_NUM 3,0,1,2
#define COVSCRIPT_VERSION_STR "3.0.1 Acipenser sinensis(Stable) Build 2"
#define COVSCRIPT_STD_VERSION 190101
#define COVSCRIPT_ABI_VERSION 190101
#if defined(_WIN32) || defined(WIN32)
#define COVSCRIPT_PLATFORM_WIN32
#endif
<commit_msg>Update version.hpp<commit_after>#pragma once
/*
* Covariant Script Version Info
*
* 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.
*
* Copyright (C) 2018 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*
* Version Format:
*   1 . 0 . 0 [Version Code](Preview/Unstable/Stable) Build 1
*   |   |   |                           |
*   |   | Minor                       Status
*   | Major
* Master
*
*/
#define COVSCRIPT_VERSION_NUM 3,0,2,2
#define COVSCRIPT_VERSION_STR "3.0.2 Acipenser sinensis(Unstable) Build 2"
#define COVSCRIPT_STD_VERSION 190101
#define COVSCRIPT_ABI_VERSION 190101
#if defined(_WIN32) || defined(WIN32)
#define COVSCRIPT_PLATFORM_WIN32
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Mar 10, 2014
 */

#ifndef MethodMock_h__
#define MethodMock_h__

#include <vector>
#include <functional>
#include <atomic>
#include <tuple>

#include "mockutils/TupleDispatcher.hpp"
#include "fakeit/DomainObjects.hpp"
#include "fakeit/ActualInvocation.hpp"
#include "fakeit/Behavior.hpp"

namespace fakeit {

static std::atomic_int invocationOrdinal;

template<typename R, typename ... arglist>
struct MethodInvocationMock: public ActualInvocation<arglist...>::Matcher, public MethodInvocationHandler<R, arglist...> {

	virtual std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> getMatcher()= 0;

};

class finally {
private:
	std::function<void()> finallyClause;
	finally(const finally &);
	finally& operator=(const finally &);
public:
	explicit finally(std::function<void()> f) :
			finallyClause(f) {
	}

	~finally() {
		finallyClause();
	}
};

class NoMoreRecordedBehaviorException : public std::exception {

};

template<typename R, typename ... arglist>
struct RecordedMethodBody: public MethodInvocationHandler<R, arglist...> {

	RecordedMethodBody(Method & method): method(method) {
		clear();
	}

	void AppendDo(std::function<R(arglist...)> method) {
		std::shared_ptr<Behavior<R, arglist...>> doMock = std::shared_ptr<Behavior<R, arglist...>> { new Repeat<R, arglist...>(
				method) };
		AppendDo(doMock);
	}

	void LastDo(std::function<R(arglist...)> method) {
		std::shared_ptr<Behavior<R, arglist...>> doMock = std::shared_ptr<Behavior<R, arglist...>> { new Repeat<R, arglist...>(
				method) };
		LastDo(doMock);
	}

	void AppendDo(std::shared_ptr<Behavior<R, arglist...> > doMock) {
		append(doMock);
	}

	void LastDo(std::shared_ptr<Behavior<R, arglist...> > doMock) {
		append(doMock);
		behaviorMocks.pop_back();
	}

	R handleMethodInvocation(arglist&... args) override {
		std::shared_ptr<Behavior<R, arglist...>> behavior = behaviorMocks.front();
		std::function < void() > finallyClause = [&]()->void {
			if (behavior->isDone())
			behaviorMocks.erase(behaviorMocks.begin());
		};
		finally onExit(finallyClause);
		return behavior->invoke(args...);
	}

private:

	struct ThrowUnexpectedMethodCall: public Behavior<R, arglist...> {

		virtual ~ThrowUnexpectedMethodCall() = default;

		virtual R invoke(arglist&... args) override {
			NoMoreRecordedBehaviorException e;
			throw e;
		}

		virtual bool isDone() override {
			return false;
		}
	};

	Method & method;

	void append(std::shared_ptr<Behavior<R, arglist...>> mock) {
		behaviorMocks.insert(behaviorMocks.end() - 1, mock);
	}

	void clear() {
		behaviorMocks.clear();
		auto doMock = std::shared_ptr<Behavior<R, arglist...>> { new ThrowUnexpectedMethodCall() };
		behaviorMocks.push_back(doMock);
	}

	std::vector<std::shared_ptr<Behavior<R, arglist...>>>behaviorMocks;
};

template<typename R, typename ... arglist>
struct MethodInvocationMockBase: public virtual MethodInvocationMock<R, arglist...> {

	MethodInvocationMockBase(const Method& method, std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> matcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) :
			method(method), matcher { matcher }, invocationHandler { invocationHandler } {
	}

	R handleMethodInvocation(arglist&... args) override {
		return invocationHandler->handleMethodInvocation(args...);
	}

	virtual bool matches(ActualInvocation<arglist...>& actualInvocation) {
		return matcher->matches(actualInvocation);
	}

	std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> getMatcher() override {
		return matcher;
	}

private:
	const Method& method;
	std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> matcher;
	std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler;
};

template<typename ... arglist>
struct ExpectedArgumentsInvocationMatcher: public ActualInvocation<arglist...>::Matcher {
	ExpectedArgumentsInvocationMatcher(const arglist&... args) :
			expectedArguments(args...) {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		if (invocation.getActualMatcher().get() == this)
			return true;
		return matches(invocation.getActualArguments());
	}
private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return expectedArguments == actualArgs;
	}
	const std::tuple<arglist...> expectedArguments;
};

template<typename ... arglist>
struct UserDefinedInvocationMatcher: public ActualInvocation<arglist...>::Matcher {
	UserDefinedInvocationMatcher(std::function<bool(arglist...)> matcher) :
			matcher { matcher } {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		if (invocation.getActualMatcher().get() == this)
			return true;
		return matches(invocation.getActualArguments());
	}
private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return invoke<arglist...>(matcher, std::tuple<arglist...> { actualArgs });
	}
	std::function<bool(arglist...)> matcher;
};

template<typename ... arglist>
struct DefaultInvocationMatcher: public ActualInvocation<arglist...>::Matcher {
	DefaultInvocationMatcher() {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		return matches(invocation.getActualArguments());
	}

private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return true;
	}
};

template<typename C, typename R, typename ... arglist>
class MethodMock: public virtual MethodInvocationHandler<R, arglist...>, public virtual ActualInvocationsSource {

	class MethodImpl : public Method {
		std::string _name;
	public:
		MethodImpl(std::string name):_name(name){}

		virtual std::string name() const override {
			return _name;
		}

		void setName(const std::string& name){
			_name = name;
		}
	};

	MockObject<C>& mock;
	R (C::*vMethod)(arglist...);
	MethodImpl method;
	std::vector<std::shared_ptr<MethodInvocationMock<R, arglist...>>>methodInvocationMocks;
	std::vector<std::shared_ptr<ActualInvocation<arglist...>>> actualInvocations;

	std::shared_ptr<MethodInvocationMockBase<R, arglist...>> buildMethodInvocationMock(
			std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> invocationMatcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) {
		return std::shared_ptr<MethodInvocationMockBase<R, arglist...>> {
			new MethodInvocationMockBase<R, arglist...>(this->getMethod(), invocationMatcher,
					invocationHandler)};
	}

	std::shared_ptr<MethodInvocationMock<R, arglist...>> getMethodInvocationMockForActualArgs(ActualInvocation<arglist...>& invocation) {
		for (auto i = methodInvocationMocks.rbegin(); i != methodInvocationMocks.rend(); ++i) {
			if ((*i)->matches(invocation)) {
				return (*i);
			}
		}
		return nullptr;
	}

public:

	MethodMock(MockObject<C>& mock, R (C::*vMethod)(arglist...)) :
			mock(mock), vMethod(vMethod), method{typeid(vMethod).name()} {
	}

	virtual ~MethodMock() {
	}

	Method& getMethod() {
		return method;
	}

	void stubMethodInvocation(std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> invocationMatcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) {
		auto mock = buildMethodInvocationMock(invocationMatcher, invocationHandler);
		methodInvocationMocks.push_back(mock);
	}

	void clear() {
		methodInvocationMocks.clear();
	}

	R handleMethodInvocation(arglist&... args) override {
		int ordinal = invocationOrdinal++;
		auto actualInvoaction = std::shared_ptr<ActualInvocation<arglist...>> { new ActualInvocation<arglist...>(ordinal, this->getMethod(),
				args...) };
		auto methodInvocationMock = getMethodInvocationMockForActualArgs(*actualInvoaction);
		if (!methodInvocationMock) {
			UnexpectedMethodCallException e(this->method);
			FakeIt::log(e);
			throw e;
		}
		auto matcher = methodInvocationMock->getMatcher();
		actualInvoaction->setActualMatcher(matcher);
		actualInvocations.push_back(actualInvoaction);
		try {
			return methodInvocationMock->handleMethodInvocation(args...);
		} catch (NoMoreRecordedBehaviorException&){
			UnexpectedMethodCallException e(this->method);
			FakeIt::log(e);
			throw e;
		}
	}

	std::vector<std::shared_ptr<ActualInvocation<arglist...>> > getActualInvocations(
			typename ActualInvocation<arglist...>::Matcher& matcher) {
		std::vector < std::shared_ptr<ActualInvocation<arglist...>> > result;
		for (auto actualInvocation : actualInvocations) {
			if (matcher.matches(*actualInvocation)) {
				result.push_back(actualInvocation);
			}
		}
		return result;
	}

	void getActualInvocations(std::unordered_set<Invocation*>& into) const {
		for (auto invocation : actualInvocations) {
			into.insert(invocation.get());
		}
	}

	void setMethodDetails(const std::string& mockName, const std::string& methodName) {
		const std::string fullName {mockName + "." + methodName};
		method.setName(fullName);
	}

};

}

#endif // MethodMock_h__
<commit_msg>Refactor. Improve class names.<commit_after>/*
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Mar 10, 2014
 */

#ifndef MethodMock_h__
#define MethodMock_h__

#include <vector>
#include <functional>
#include <atomic>
#include <tuple>

#include "mockutils/TupleDispatcher.hpp"
#include "fakeit/DomainObjects.hpp"
#include "fakeit/ActualInvocation.hpp"
#include "fakeit/Behavior.hpp"

namespace fakeit {

static std::atomic_int invocationOrdinal;

template<typename R, typename ... arglist>
struct MethodInvocationMock: public ActualInvocation<arglist...>::Matcher, public MethodInvocationHandler<R, arglist...> {

	virtual ~MethodInvocationMock() = default;

	virtual std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> getMatcher()= 0;

};

class finally {
private:
	std::function<void()> finallyClause;
	finally(const finally &);
	finally& operator=(const finally &);
public:
	explicit finally(std::function<void()> f) :
			finallyClause(f) {
	}

	~finally() {
		finallyClause();
	}
};

class NoMoreRecordedBehaviorException : public std::exception {

};

template<typename R, typename ... arglist>
struct RecordedMethodBody: public MethodInvocationHandler<R, arglist...> {

	RecordedMethodBody(Method & method): method(method) {
		clear();
	}

	void AppendDo(std::function<R(arglist...)> method) {
		std::shared_ptr<Behavior<R, arglist...>> doMock = std::shared_ptr<Behavior<R, arglist...>> { new Repeat<R, arglist...>(
				method) };
		AppendDo(doMock);
	}

	void LastDo(std::function<R(arglist...)> method) {
		std::shared_ptr<Behavior<R, arglist...>> doMock = std::shared_ptr<Behavior<R, arglist...>> { new Repeat<R, arglist...>(
				method) };
		LastDo(doMock);
	}

	void AppendDo(std::shared_ptr<Behavior<R, arglist...> > doMock) {
		append(doMock);
	}

	void LastDo(std::shared_ptr<Behavior<R, arglist...> > doMock) {
		append(doMock);
		behaviorMocks.pop_back();
	}

	R handleMethodInvocation(arglist&... args) override {
		std::shared_ptr<Behavior<R, arglist...>> behavior = behaviorMocks.front();
		std::function < void() > finallyClause = [&]()->void {
			if (behavior->isDone())
			behaviorMocks.erase(behaviorMocks.begin());
		};
		finally onExit(finallyClause);
		return behavior->invoke(args...);
	}

private:

	struct NoMoreRecordedBehavior: public Behavior<R, arglist...> {

		virtual ~NoMoreRecordedBehavior() = default;

		virtual R invoke(arglist&... args) override {
			NoMoreRecordedBehaviorException e;
			throw e;
		}

		virtual bool isDone() override {
			return false;
		}
	};

	Method & method;

	void append(std::shared_ptr<Behavior<R, arglist...>> mock) {
		behaviorMocks.insert(behaviorMocks.end() - 1, mock);
	}

	void clear() {
		behaviorMocks.clear();
		auto doMock = std::shared_ptr<Behavior<R, arglist...>> { new NoMoreRecordedBehavior() };
		behaviorMocks.push_back(doMock);
	}

	std::vector<std::shared_ptr<Behavior<R, arglist...>>>behaviorMocks;
};

template<typename R, typename ... arglist>
struct MethodInvocationMockBase: public virtual MethodInvocationMock<R, arglist...> {

	virtual ~MethodInvocationMockBase() = default;

	MethodInvocationMockBase(const Method& method, std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> matcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) :
			method(method), matcher { matcher }, invocationHandler { invocationHandler } {
	}

	R handleMethodInvocation(arglist&... args) override {
		return invocationHandler->handleMethodInvocation(args...);
	}

	virtual bool matches(ActualInvocation<arglist...>& actualInvocation) {
		return matcher->matches(actualInvocation);
	}

	std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> getMatcher() override {
		return matcher;
	}

private:
	const Method& method;
	std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> matcher;
	std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler;
};

template<typename ... arglist>
struct ExpectedArgumentsInvocationMatcher: public ActualInvocation<arglist...>::Matcher {

	virtual ~ExpectedArgumentsInvocationMatcher() = default;

	ExpectedArgumentsInvocationMatcher(const arglist&... args) :
			expectedArguments(args...) {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		if (invocation.getActualMatcher().get() == this)
			return true;
		return matches(invocation.getActualArguments());
	}

private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return expectedArguments == actualArgs;
	}
	const std::tuple<arglist...> expectedArguments;
};

template<typename ... arglist>
struct UserDefinedInvocationMatcher: public ActualInvocation<arglist...>::Matcher {
	virtual ~UserDefinedInvocationMatcher() = default;

	UserDefinedInvocationMatcher(std::function<bool(arglist...)> matcher) :
			matcher { matcher } {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		if (invocation.getActualMatcher().get() == this)
			return true;
		return matches(invocation.getActualArguments());
	}
private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return invoke<arglist...>(matcher, std::tuple<arglist...> { actualArgs });
	}
	std::function<bool(arglist...)> matcher;
};

template<typename ... arglist>
struct DefaultInvocationMatcher: public ActualInvocation<arglist...>::Matcher {

	virtual ~DefaultInvocationMatcher() = default;

	DefaultInvocationMatcher() {
	}

	virtual bool matches(ActualInvocation<arglist...>& invocation) override {
		return matches(invocation.getActualArguments());
	}

private:
	virtual bool matches(const std::tuple<arglist...>& actualArgs) {
		return true;
	}
};

template<typename C, typename R, typename ... arglist>
class MethodMock: public virtual MethodInvocationHandler<R, arglist...>, public virtual ActualInvocationsSource {

	class MethodImpl : public Method {
		std::string _name;
	public:
		MethodImpl(std::string name):_name(name){}

		virtual std::string name() const override {
			return _name;
		}

		void setName(const std::string& name){
			_name = name;
		}
	};

	MockObject<C>& mock;
	R (C::*vMethod)(arglist...);
	MethodImpl method;
	std::vector<std::shared_ptr<MethodInvocationMock<R, arglist...>>>methodInvocationMocks;
	std::vector<std::shared_ptr<ActualInvocation<arglist...>>> actualInvocations;

	std::shared_ptr<MethodInvocationMockBase<R, arglist...>> buildMethodInvocationMock(
			std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> invocationMatcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) {
		return std::shared_ptr<MethodInvocationMockBase<R, arglist...>> {
			new MethodInvocationMockBase<R, arglist...>(this->getMethod(), invocationMatcher,
					invocationHandler)};
	}

	std::shared_ptr<MethodInvocationMock<R, arglist...>> getMethodInvocationMockForActualArgs(ActualInvocation<arglist...>& invocation) {
		for (auto i = methodInvocationMocks.rbegin(); i != methodInvocationMocks.rend(); ++i) {
			if ((*i)->matches(invocation)) {
				return (*i);
			}
		}
		return nullptr;
	}

public:

	MethodMock(MockObject<C>& mock, R (C::*vMethod)(arglist...)) :
			mock(mock), vMethod(vMethod), method{typeid(vMethod).name()} {
	}

	virtual ~MethodMock() {
	}

	Method& getMethod() {
		return method;
	}

	void stubMethodInvocation(std::shared_ptr<typename ActualInvocation<arglist...>::Matcher> invocationMatcher,
			std::shared_ptr<MethodInvocationHandler<R, arglist...>> invocationHandler) {
		auto mock = buildMethodInvocationMock(invocationMatcher, invocationHandler);
		methodInvocationMocks.push_back(mock);
	}

	void clear() {
		methodInvocationMocks.clear();
	}

	R handleMethodInvocation(arglist&... args) override {
		int ordinal = invocationOrdinal++;
		auto actualInvoaction = std::shared_ptr<ActualInvocation<arglist...>> { new ActualInvocation<arglist...>(ordinal, this->getMethod(),
				args...) };
		auto methodInvocationMock = getMethodInvocationMockForActualArgs(*actualInvoaction);
		if (!methodInvocationMock) {
			UnexpectedMethodCallException e(this->method);
			FakeIt::log(e);
			throw e;
		}
		auto matcher = methodInvocationMock->getMatcher();
		actualInvoaction->setActualMatcher(matcher);
		actualInvocations.push_back(actualInvoaction);
		try {
			return methodInvocationMock->handleMethodInvocation(args...);
		} catch (NoMoreRecordedBehaviorException&){
			UnexpectedMethodCallException e(this->method);
			FakeIt::log(e);
			throw e;
		}
	}

	std::vector<std::shared_ptr<ActualInvocation<arglist...>> > getActualInvocations(
			typename ActualInvocation<arglist...>::Matcher& matcher) {
		std::vector < std::shared_ptr<ActualInvocation<arglist...>> > result;
		for (auto actualInvocation : actualInvocations) {
			if (matcher.matches(*actualInvocation)) {
				result.push_back(actualInvocation);
			}
		}
		return result;
	}

	void getActualInvocations(std::unordered_set<Invocation*>& into) const {
		for (auto invocation : actualInvocations) {
			into.insert(invocation.get());
		}
	}

	void setMethodDetails(const std::string& mockName, const std::string& methodName) {
		const std::string fullName {mockName + "." + methodName};
		method.setName(fullName);
	}

};

}

#endif // MethodMock_h__
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_METAWRITER_HPP
#define MAPNIK_METAWRITER_HPP

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/projection.hpp>

// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/concept_check.hpp>

// stl
#include <set>
#include <string>

namespace mapnik {

class text_placement_info;
class text_path;

/** Implementation of std::map that also returns const& for operator[]. */
class metawriter_property_map
{
public:
    typedef std::map<std::string, UnicodeString> property_map;
    typedef property_map::const_iterator const_iterator;

    metawriter_property_map() :
        m_(),
        not_found_() {}

    UnicodeString const& operator[](std::string const& key) const;
    UnicodeString& operator[](std::string const& key) {return m_[key];}

    std::map<std::string, UnicodeString>::const_iterator find(std::string const& key) const
    {
        return m_.find(key);
    }

    std::map<std::string, UnicodeString>::const_iterator end() const
    {
        return m_.end();
    }

    UnicodeString const& get(std::string const& key) const
    {
        return (*this)[key];
    }

private:
    property_map m_;
    UnicodeString not_found_;
};

/** All properties to be output by a metawriter. */
class metawriter_properties : public std::set<std::string>
{
public:
    metawriter_properties(boost::optional<std::string> str);
    metawriter_properties() {}
    template <class InputIterator> metawriter_properties(
        InputIterator first, InputIterator last) : std::set<std::string>(first, last) {}
    std::string to_string() const;
};

/** Abstract baseclass for all metawriter classes. */
class metawriter
{
public:
    typedef coord_transform<CoordTransform,geometry_type> path_type;
    metawriter(metawriter_properties dflt_properties) :
        dflt_properties_(dflt_properties),
        width_(0),
        height_(0) {}
    virtual ~metawriter() {}
    /** Output a rectangular area.
     * \param box Area (in pixel coordinates)
     * \param feature The feature being processed
     * \param prj_trans Projection transformation
     * \param t Coordinate transformation
     * \param properties List of properties to output
     */
    virtual void add_box(box2d<double> const& box, Feature const& feature,
                         CoordTransform const& t,
                         metawriter_properties const& properties)=0;
    virtual void add_text(boost::ptr_vector<text_path> &placements,
                          box2d<double> const& extents,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties)=0;
    virtual void add_polygon(path_type & path,
                             Feature const& feature,
                             CoordTransform const& t,
                             metawriter_properties const& properties)=0;
    virtual void add_line(path_type & path,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties)=0;

    /** Start processing.
     * Write file header, init database connection, ...
     *
     * \param properties metawriter_property_map object with userdefined values.
     *        Useful for setting filename etc.
     */
    virtual void start(metawriter_property_map const& properties)
    {
        boost::ignore_unused_variable_warning(properties);
    }

    /** Stop processing.
     * Write file footer, close database connection, ...
     */
    virtual void stop() {}
    /** Set output size (pixels).
     * All features that are completely outside this size are discarded.
     */
    void set_size(int width, int height) { width_ = width; height_ = height; }
    /** Set Map object's srs. */
    virtual void set_map_srs(projection const& proj) { /* Not required when working with image coordinates. */ }
    /** Return the list of default properties. */
    metawriter_properties const& get_default_properties() const { return dflt_properties_;}
protected:
    metawriter_properties dflt_properties_;
    /** Output width (pixels). */
    int width_;
    /** Output height (pixels). */
    int height_;
};

/** Shared pointer to metawriter object. */
typedef boost::shared_ptr<metawriter> metawriter_ptr;
/** Metawriter object + properties. */
typedef std::pair<metawriter_ptr, metawriter_properties> metawriter_with_properties;

}

#endif // MAPNIK_METAWRITER_HPP
<commit_msg>+ fix unused parameter warning<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_METAWRITER_HPP
#define MAPNIK_METAWRITER_HPP

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/projection.hpp>

// boost
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/concept_check.hpp>

// stl
#include <set>
#include <string>

namespace mapnik {

class text_placement_info;
class text_path;

/** Implementation of std::map that also returns const& for operator[]. */
class metawriter_property_map
{
public:
    typedef std::map<std::string, UnicodeString> property_map;
    typedef property_map::const_iterator const_iterator;

    metawriter_property_map() :
        m_(),
        not_found_() {}

    UnicodeString const& operator[](std::string const& key) const;
    UnicodeString& operator[](std::string const& key) {return m_[key];}

    std::map<std::string, UnicodeString>::const_iterator find(std::string const& key) const
    {
        return m_.find(key);
    }

    std::map<std::string, UnicodeString>::const_iterator end() const
    {
        return m_.end();
    }

    UnicodeString const& get(std::string const& key) const
    {
        return (*this)[key];
    }

private:
    property_map m_;
    UnicodeString not_found_;
};

/** All properties to be output by a metawriter. */
class metawriter_properties : public std::set<std::string>
{
public:
    metawriter_properties(boost::optional<std::string> str);
    metawriter_properties() {}
    template <class InputIterator> metawriter_properties(
        InputIterator first, InputIterator last) : std::set<std::string>(first, last) {}
    std::string to_string() const;
};

/** Abstract baseclass for all metawriter classes. */
class metawriter
{
public:
    typedef coord_transform<CoordTransform,geometry_type> path_type;
    metawriter(metawriter_properties dflt_properties) :
        dflt_properties_(dflt_properties),
        width_(0),
        height_(0) {}
    virtual ~metawriter() {}
    /** Output a rectangular area.
     * \param box Area (in pixel coordinates)
     * \param feature The feature being processed
     * \param prj_trans Projection transformation
     * \param t Coordinate transformation
     * \param properties List of properties to output
     */
    virtual void add_box(box2d<double> const& box, Feature const& feature,
                         CoordTransform const& t,
                         metawriter_properties const& properties)=0;
    virtual void add_text(boost::ptr_vector<text_path> &placements,
                          box2d<double> const& extents,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties)=0;
    virtual void add_polygon(path_type & path,
                             Feature const& feature,
                             CoordTransform const& t,
                             metawriter_properties const& properties)=0;
    virtual void add_line(path_type & path,
                          Feature const& feature,
                          CoordTransform const& t,
                          metawriter_properties const& properties)=0;

    /** Start processing.
     * Write file header, init database connection, ...
     *
     * \param properties metawriter_property_map object with userdefined values.
     *        Useful for setting filename etc.
     */
    virtual void start(metawriter_property_map const& properties)
    {
        boost::ignore_unused_variable_warning(properties);
    }

    /** Stop processing.
     * Write file footer, close database connection, ...
     */
    virtual void stop() {}
    /** Set output size (pixels).
     * All features that are completely outside this size are discarded.
     */
    void set_size(int width, int height) { width_ = width; height_ = height; }
    /** Set Map object's srs. */
    virtual void set_map_srs(projection const& proj)
    {
        boost::ignore_unused_variable_warning(proj);
    }

    /** Return the list of default properties. */
    metawriter_properties const& get_default_properties() const { return dflt_properties_;}
protected:
    metawriter_properties dflt_properties_;
    /** Output width (pixels). */
    int width_;
    /** Output height (pixels). */
    int height_;
};

/** Shared pointer to metawriter object. */
typedef boost::shared_ptr<metawriter> metawriter_ptr;
/** Metawriter object + properties. */
typedef std::pair<metawriter_ptr, metawriter_properties> metawriter_with_properties;

}

#endif // MAPNIK_METAWRITER_HPP
<|endoftext|>


<commit_before>/******************************************************************************

  nomlib - C++11 cross-platform game engine

Copyright (c) 2013, 2014 Jeffrey Carpenter <i8degrees@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE 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 NOMLIB_MATH_SIZE2_HEADERS
#define NOMLIB_MATH_SIZE2_HEADERS

#include <iostream>
#include <algorithm>

#include "nomlib/config.hpp"

// FIXME: The following declaration is necessary in order to avoid a very
// nasty compiling conflict that can happen under Windows anytime the
// windef.h header file is included (commonly from windows.h), due to min and
// max macros being declared there. This is why macros are evil.
//
// http://support.microsoft.com/kb/143208
// http://stackoverflow.com/questions/5004858/stdmin-gives-error
#if defined( NOM_PLATFORM_WINDOWS )
  #undef min
  #undef max
#endif

namespace nom {

/// \brief Delimiter character to use with << operator
const std::string SIZE2_DELIMITER = ", ";

/// \brief Size coordinates (width & height) container
template <typename T>
struct Size2
{
  /// Default constructor; initialize values to Size2<T>::null
  Size2 ( void ) :
    w ( -1 ),
    h ( -1 )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// Destructor
  ~Size2 ( void )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// Constructor variant for initializing width & height at construction
  Size2 ( T w, T h ) :
    w ( w ),
    h ( h )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// \brief Construct an object using a specified value for both members.
  Size2( T factor )
  {
    this->w = factor;
    this->h = factor;
  }

  /// \brief Copy constructor
  ///
  /// \remarks The explicit keyword here will result in compile-time errors
  /// in any instance that it finds incompatible casting occurring, such as if
  /// you try to down-cast a Size2<int> to a Size2<float>.
  template <typename U>
  explicit Size2 ( const Size2<U>& copy ) :
    w { static_cast<T> ( copy.w ) },
    h { static_cast<T> ( copy.h ) }
  {
    this->w = static_cast<T> ( copy.w );
    this->h = static_cast<T> ( copy.h );
  }

  /// \brief Compare two Size2 objects and return the larger width and height
  /// of the two objects.
  template <typename U>
  Size2 max( const Size2<U>& rhs )
  {
    return Size2<T>( std::max( this->w, rhs.w ), std::max( this->h, rhs.h ) );
  }

  /// \brief Compare two Size2 objects and return the smaller width and height
  /// of the two objects.
  template <typename U>
  Size2 min( const Size2<U>& rhs )
  {
    return Size2<T>( std::min( this->w, rhs.w ), std::min( this->h, rhs.h ) );
  }

  /// \brief Transpose width and height dimensions.
  void swap( void )
  {
    std::swap( this->w, this->h );
  }

  /// \brief Null value
  ///
  /// \remarks  Null value implementation depends on signed (negative) numbers.
  static const Size2 null;

  /// \brief Zero value constant.
  static const Size2 zero;

  /// Represents the width coordinate point
  T w;

  /// Represents the height coordinate point
  T h;
};

/// Pretty print a Size2 object using the following formatting:
///
///     <Size2.x>, <Size2.y>
///
/// An example print:
///
///     128, 144
template <typename T>
inline std::ostream& operator <<( std::ostream& os, const Size2<T>& pos )
{
  os
  << pos.w
  << SIZE2_DELIMITER
  << pos.h;

  return os;
}

template <typename T>
inline bool operator ==( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( lhs.w == rhs.w )  &&  ( lhs.h == rhs.h );
}

template <typename T>
inline bool operator !=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return ! ( lhs == rhs );
}

/// \brief Method overload of binary operator + (Addition)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \returns Addition of both objects.
template <typename T>
inline Size2<T> operator +( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> (
                    lhs.w + rhs.w,
                    lhs.h + rhs.h
                  );
}

/// \brief Method overload of binary operator ++ (Addition by 1)
///
/// \param rhs Right operand.
///
/// \returns Addition of the right operand.
template <typename T>
inline Size2<T> operator ++( const Size2<T>& rhs )
{
  return Size2<T> (
                    ++rhs.w,
                    ++rhs.h
                  );
}

/// \brief Method overload of binary operator - (subtraction)
///
/// \param rhs Right operand.
///
/// \returns Opposite of the object.
template <typename T>
inline Size2<T> operator -( const Size2<T>& rhs )
{
  return Size2<T> (
                    -rhs.w
                    -rhs.h
                  );
}

/// \brief Method overload of binary operator - (subtraction)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \returns Subtraction of both objects.
template <typename T>
inline Size2<T> operator -( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> (
                    lhs.w - rhs.w,
                    lhs.h - rhs.h
                  );
}

/// \brief Method overload of binary operator -- (subtraction by 1)
///
/// \param rhs Right operand.
///
/// \returns Subtraction of the right operand.
template <typename T>
inline Size2<T> operator --( const Size2<T>& rhs )
{
  return Size2<T> (
                    --rhs.w,
                    --rhs.h
                  );
}

/// \brief Method overload of binary operator * (Multiplication)
///
/// \param rhs Left operand.
/// \param rhs Right operand.
///
/// \returns Multiplication of the right operand.
template <typename T>
inline Size2<T> operator *( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> ( lhs.w * rhs.w,
                    lhs.h * rhs.h
                  );
}

/// \brief Method overload of binary operator += (Addition)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Addition of both objects; result is assigned to the left
/// operand.
///
/// \returns Reference to left operand,
template <typename T>
inline Size2<T>& operator +=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w += rhs.w;
  lhs.h += rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator -= (Subtraction)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Subtraction of both objects; result is assigned to the left
/// operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator -=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w -= rhs.w;
  lhs.h -= rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator *= (Multiplication)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Multiplication of both objects; result is assigned to the
/// left operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator *=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w *= rhs.w;
  lhs.h *= rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator /= (Division)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Division of both objects; result is assigned to the
/// left operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator /=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w /= rhs.w;
  lhs.h /= rhs.h;

  return lhs;
}

/// \brief Lesser than comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator <( const Size2<T> lhs, const Size2<T>& rhs )
{
  return  ( lhs.w < rhs.w ) && ( lhs.h < rhs.h );
}

/// \brief Greater than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator >( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( rhs.w < lhs.w ) && ( rhs.h < lhs.h );
}

/// \brief Lesser than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator <=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( lhs.w <= rhs.w ) && ( lhs.h <= rhs.h );
}

/// \brief Greater than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator >=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( rhs.w <= lhs.w ) && ( rhs.h <= lhs.h );
}

/// Size2 object defined using signed integers
typedef Size2<int> Size2i;

/// Size2 object defined using floating point numbers
typedef Size2<float> Size2f;

/// Size2 object defined using double-precision floating point numbers
typedef Size2<double> Size2d;

} // namespace nom

#endif // include guard defined
<commit_msg>Introduce Size2 division operator<commit_after>/******************************************************************************

  nomlib - C++11 cross-platform game engine

Copyright (c) 2013, 2014 Jeffrey Carpenter <i8degrees@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE 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 NOMLIB_MATH_SIZE2_HEADERS
#define NOMLIB_MATH_SIZE2_HEADERS

#include <iostream>
#include <algorithm>

#include "nomlib/config.hpp"

// FIXME: The following declaration is necessary in order to avoid a very
// nasty compiling conflict that can happen under Windows anytime the
// windef.h header file is included (commonly from windows.h), due to min and
// max macros being declared there. This is why macros are evil.
//
// http://support.microsoft.com/kb/143208
// http://stackoverflow.com/questions/5004858/stdmin-gives-error
#if defined( NOM_PLATFORM_WINDOWS )
  #undef min
  #undef max
#endif

namespace nom {

/// \brief Delimiter character to use with << operator
const std::string SIZE2_DELIMITER = ", ";

/// \brief Size coordinates (width & height) container
template <typename T>
struct Size2
{
  /// Default constructor; initialize values to Size2<T>::null
  Size2 ( void ) :
    w ( -1 ),
    h ( -1 )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// Destructor
  ~Size2 ( void )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// Constructor variant for initializing width & height at construction
  Size2 ( T w, T h ) :
    w ( w ),
    h ( h )
  {
    //NOM_LOG_TRACE(NOM);
  }

  /// \brief Construct an object using a specified value for both members.
  Size2( T factor )
  {
    this->w = factor;
    this->h = factor;
  }

  /// \brief Copy constructor
  ///
  /// \remarks The explicit keyword here will result in compile-time errors
  /// in any instance that it finds incompatible casting occurring, such as if
  /// you try to down-cast a Size2<int> to a Size2<float>.
  template <typename U>
  explicit Size2 ( const Size2<U>& copy ) :
    w { static_cast<T> ( copy.w ) },
    h { static_cast<T> ( copy.h ) }
  {
    this->w = static_cast<T> ( copy.w );
    this->h = static_cast<T> ( copy.h );
  }

  /// \brief Compare two Size2 objects and return the larger width and height
  /// of the two objects.
  template <typename U>
  Size2 max( const Size2<U>& rhs )
  {
    return Size2<T>( std::max( this->w, rhs.w ), std::max( this->h, rhs.h ) );
  }

  /// \brief Compare two Size2 objects and return the smaller width and height
  /// of the two objects.
  template <typename U>
  Size2 min( const Size2<U>& rhs )
  {
    return Size2<T>( std::min( this->w, rhs.w ), std::min( this->h, rhs.h ) );
  }

  /// \brief Transpose width and height dimensions.
  void swap( void )
  {
    std::swap( this->w, this->h );
  }

  /// \brief Null value
  ///
  /// \remarks  Null value implementation depends on signed (negative) numbers.
  static const Size2 null;

  /// \brief Zero value constant.
  static const Size2 zero;

  /// Represents the width coordinate point
  T w;

  /// Represents the height coordinate point
  T h;
};

/// Pretty print a Size2 object using the following formatting:
///
///     <Size2.x>, <Size2.y>
///
/// An example print:
///
///     128, 144
template <typename T>
inline std::ostream& operator <<( std::ostream& os, const Size2<T>& pos )
{
  os
  << pos.w
  << SIZE2_DELIMITER
  << pos.h;

  return os;
}

template <typename T>
inline bool operator ==( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( lhs.w == rhs.w )  &&  ( lhs.h == rhs.h );
}

template <typename T>
inline bool operator !=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return ! ( lhs == rhs );
}

/// \brief Method overload of binary operator + (Addition)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \returns Addition of both objects.
template <typename T>
inline Size2<T> operator +( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> (
                    lhs.w + rhs.w,
                    lhs.h + rhs.h
                  );
}

/// \brief Method overload of binary operator ++ (Addition by 1)
///
/// \param rhs Right operand.
///
/// \returns Addition of the right operand.
template <typename T>
inline Size2<T> operator ++( const Size2<T>& rhs )
{
  return Size2<T> (
                    ++rhs.w,
                    ++rhs.h
                  );
}

/// \brief Method overload of binary operator - (subtraction)
///
/// \param rhs Right operand.
///
/// \returns Opposite of the object.
template <typename T>
inline Size2<T> operator -( const Size2<T>& rhs )
{
  return Size2<T> (
                    -rhs.w
                    -rhs.h
                  );
}

/// \brief Method overload of binary operator - (subtraction)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \returns Subtraction of both objects.
template <typename T>
inline Size2<T> operator -( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> (
                    lhs.w - rhs.w,
                    lhs.h - rhs.h
                  );
}

/// \brief Method overload of binary operator -- (subtraction by 1)
///
/// \param rhs Right operand.
///
/// \returns Subtraction of the right operand.
template <typename T>
inline Size2<T> operator --( const Size2<T>& rhs )
{
  return Size2<T> (
                    --rhs.w,
                    --rhs.h
                  );
}

/// \brief Method overload of binary operator * (Multiplication)
///
/// \param rhs Left operand.
/// \param rhs Right operand.
///
/// \returns Multiplication of the right operand.
template <typename T>
inline Size2<T> operator *( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return Size2<T> ( lhs.w * rhs.w,
                    lhs.h * rhs.h
                  );
}

/// \brief Method overload of binary operator += (Addition)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Addition of both objects; result is assigned to the left
/// operand.
///
/// \returns Reference to left operand,
template <typename T>
inline Size2<T>& operator +=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w += rhs.w;
  lhs.h += rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator -= (Subtraction)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Subtraction of both objects; result is assigned to the left
/// operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator -=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w -= rhs.w;
  lhs.h -= rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator *= (Multiplication)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Multiplication of both objects; result is assigned to the
/// left operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator *=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w *= rhs.w;
  lhs.h *= rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator /= (Division assignment)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \remarks Division of both objects; result is assigned to the
/// left operand.
///
/// \returns Reference to left operand.
template <typename T>
inline Size2<T>& operator /=( Size2<T>& lhs, const Size2<T>& rhs )
{
  lhs.w /= rhs.w;
  lhs.h /= rhs.h;

  return lhs;
}

/// \brief Method overload of binary operator / (Division)
///
/// \param lhs Left operand.
/// \param rhs Right operand.
///
/// \returns Size2 template type returned by value
template <typename T>
inline Size2<T> operator /( const Size2<T>& lhs, const Size2<T>& rhs )
{
  Size2<T> ret;
  ret.w = lhs.w / rhs.w;
  ret.h = lhs.h / rhs.h;

  return ret;
}

/// \brief Lesser than comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator <( const Size2<T> lhs, const Size2<T>& rhs )
{
  return  ( lhs.w < rhs.w ) && ( lhs.h < rhs.h );
}

/// \brief Greater than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator >( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( rhs.w < lhs.w ) && ( rhs.h < lhs.h );
}

/// \brief Lesser than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator <=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( lhs.w <= rhs.w ) && ( lhs.h <= rhs.h );
}

/// \brief Greater than or equal to comparison operator.
///
/// \param lhs Left operand.
/// \param rhs Right operand.
template <typename T>
inline bool operator >=( const Size2<T>& lhs, const Size2<T>& rhs )
{
  return  ( rhs.w <= lhs.w ) && ( rhs.h <= lhs.h );
}

/// Size2 object defined using signed integers
typedef Size2<int> Size2i;

/// Size2 object defined using floating point numbers
typedef Size2<float> Size2f;

/// Size2 object defined using double-precision floating point numbers
typedef Size2<double> Size2d;

} // namespace nom

#endif // include guard defined
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  variant_tree.hpp
//----------------------------------------------------------------------------
/// \brief This file contains a tree class that can hold variant values.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-07-10
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file may be included in various open-source projects.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_VARIANT_TREE_HPP_
#define _UTIL_VARIANT_TREE_HPP_

#include <util/variant.hpp>
#include <util/typeinfo.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/throw_exception.hpp>

namespace boost {
namespace property_tree {
    // Custom translator that works with util::variant instead of std::string.
    // This translator is used to read/write values from files.
    template <>
    struct translator_between<util::variant, std::string>
    {
        typedef translator_between<util::variant, std::string> type;
        typedef std::string     external_type;
        typedef util::variant   internal_type;

        boost::optional<external_type> get_value(const internal_type& value) const {
            return boost::optional<external_type>(
                value.type() == internal_type::TYPE_NULL ? "" : value.to_string());
        }

        boost::optional<internal_type> put_value(const external_type& value) const {
            try {
                long n = lexical_cast<long>(value);
                for(external_type::const_iterator it=value.begin(), end=value.end(); it!=end; ++it)
                    if (*it < '0' || *it > '9')
                        throw false;
                return boost::optional<internal_type>(n);
            } catch (...) {}
            try {
                double n = lexical_cast<double>(value);
                return boost::optional<internal_type>(n);
            } catch (...) {}
            if (value == "true" || value == "false")
                return boost::optional<internal_type>(value[0] == 't');
            return boost::optional<internal_type>(value);
        }
    };

} // namespace property_tree
} // namespace boost

namespace util {

namespace detail {

    // Custom translator that works with variant instead of std::string
    // This translator is used to get/put values through explicit get/put calls.
    template <class Ext>
    struct variant_translator
    {
        typedef Ext external_type;
        typedef variant internal_type;

        /*
        typedef boost::mpl::joint_view<variant::int_types,
                boost::mpl::vector<bool,double>
            > valid_non_string_types;
        */
        typedef variant::valid_types valid_types;

        external_type get_value(const internal_type& value) const {
            return value.get<external_type>();
        }

        template<typename T>
        typename boost::disable_if<
            boost::is_same<
                boost::mpl::end<valid_types>::type,
                boost::mpl::find<variant::valid_types, T>
            >,
            internal_type>::type
        put_value(T value) const {
            return variant(value);
        }
    };

    typedef boost::property_tree::basic_ptree<
            std::string,                    // Key type
            variant,                        // Data type
            std::less<std::string>          // Key comparison
    > basic_variant_tree;

} // namespace detail

class variant_tree : public detail::basic_variant_tree
{
    typedef detail::basic_variant_tree base;
    typedef variant_tree self_type;
public:
    typedef boost::property_tree::ptree_bad_path bad_path;
    typedef std::pair<const std::string, base> value_type;

    variant_tree() {}
    variant_tree(const detail::basic_variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}
    variant_tree(const variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}

    template <typename Source>
    static void read_info(Source& src, variant_tree& tree) {
        boost::property_tree::info_parser::read_info(src, static_cast<base&>(tree));
        boost::property_tree::translator_between<util::variant, std::string> tr;
        translate_data(tr, tree);
    }

    template <typename T>
    static void translate_data(T& tr, base& tree) {
        for (variant_tree::iterator it=tree.begin(); it != tree.end(); it++)
            translate_data(tr, it->second);
        tree.data() = *tr.put_value(tree.get_value<std::string>());
    }

    template <typename Target>
    static void write_info(Target& tar, variant_tree& tree) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree));
    }

    template <typename Target, typename Settings>
    static void write_info(Target& tar, variant_tree& tree, const Settings& tt) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree), tt);
    }

    template <class T>
    T get_value() const {
        using boost::throw_exception;

        if(boost::optional<T> o =
                base::get_value_optional<T>(detail::variant_translator<T>())) {
            return *o;
        }
        BOOST_PROPERTY_TREE_THROW(boost::property_tree::ptree_bad_data(
            std::string("conversion of data to type \"") +
            typeid(T).name() + "\" failed", base::data()));
    }

    template <class T>
    T get_value(const T& default_value) const {
        return base::get_value(default_value, detail::variant_translator<T>());
    }

    std::string get_value(const char* default_value) const {
        return base::get_value(std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_value_optional() const {
        return base::get_value(detail::variant_translator<T>());
    }

    template <class T>
    void put_value(const T& value) {
        base::put_value(value, detail::variant_translator<T>());
    }

    template <class T>
    T get(const path_type& path) const {
        try {
            return base::get_child(path).BOOST_NESTED_TEMPLATE
                get_value<T>(detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            std::stringstream s;
            s << "Cannot convert value to type '" << type_to_string<T>() << "'";
            throw bad_path(s.str(), path);
        }
    }

    template <class T>
    T get(const path_type& path, const T& default_value) const {
        try {
            return base::get(path, default_value, detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            throw bad_path("Wrong or missing value type", path);
        }
    }

    std::string get(const path_type& path, const char* default_value) const {
        return base::get(path, std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_optional(const path_type& path) const {
        return base::get_optional(path, detail::variant_translator<T>());
    }

    template <class T>
    void put(const path_type& path, const T& value) {
        base::put(path, value, detail::variant_translator<T>());
    }

    template <class T>
    self_type& add(const path_type& path, const T& value) {
        return static_cast<self_type&>(
            base::add(path, value, detail::variant_translator<T>()));
    }

    void swap(variant_tree& rhs) {
        base::swap(static_cast<base&>(rhs));
    }
    void swap(boost::property_tree::basic_ptree<
        std::string, variant, std::less<std::string> >& rhs) {
        base::swap(rhs);
    }

    self_type &get_child(const path_type &path) {
        return static_cast<self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or throw @c ptree_bad_path. */
    const self_type &get_child(const path_type &path) const {
        return static_cast<const self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or return @p default_value. */
    self_type &get_child(const path_type &path, self_type &default_value) {
        return static_cast<self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return @p default_value. */
    const self_type &get_child(const path_type &path,
                               const self_type &default_value) const {
        return static_cast<const self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<self_type &> get_child_optional(const path_type &path) {
        boost::optional<base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<self_type&>();
        return boost::optional<self_type&>(static_cast<self_type&>(*o));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<const self_type &>
    get_child_optional(const path_type &path) const {
        boost::optional<const base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<const self_type&>();
        return boost::optional<const self_type&>(static_cast<const self_type&>(*o));
    }

    self_type &put_child(const path_type &path, const self_type &value) {
        return static_cast<self_type&>(base::put_child(path, value));
    }
};

} // namespace util

#endif // _UTIL_VARIANT_TREE_HPP_
<commit_msg>translate method made protected<commit_after>//----------------------------------------------------------------------------
/// \file  variant_tree.hpp
//----------------------------------------------------------------------------
/// \brief This file contains a tree class that can hold variant values.
//----------------------------------------------------------------------------
// Author:  Serge Aleynikov
// Created: 2010-07-10
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file may be included in various open-source projects.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_VARIANT_TREE_HPP_
#define _UTIL_VARIANT_TREE_HPP_

#include <util/variant.hpp>
#include <util/typeinfo.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/throw_exception.hpp>

namespace boost {
namespace property_tree {
    // Custom translator that works with util::variant instead of std::string.
    // This translator is used to read/write values from files.
    template <>
    struct translator_between<util::variant, std::string>
    {
        typedef translator_between<util::variant, std::string> type;
        typedef std::string     external_type;
        typedef util::variant   internal_type;

        boost::optional<external_type> get_value(const internal_type& value) const {
            return boost::optional<external_type>(
                value.type() == internal_type::TYPE_NULL ? "" : value.to_string());
        }

        boost::optional<internal_type> put_value(const external_type& value) const {
            try {
                long n = lexical_cast<long>(value);
                for(external_type::const_iterator it=value.begin(), end=value.end(); it!=end; ++it)
                    if (*it < '0' || *it > '9')
                        throw false;
                return boost::optional<internal_type>(n);
            } catch (...) {}
            try {
                double n = lexical_cast<double>(value);
                return boost::optional<internal_type>(n);
            } catch (...) {}
            if (value == "true" || value == "false")
                return boost::optional<internal_type>(value[0] == 't');
            return boost::optional<internal_type>(value);
        }
    };

} // namespace property_tree
} // namespace boost

namespace util {

namespace detail {

    // Custom translator that works with variant instead of std::string
    // This translator is used to get/put values through explicit get/put calls.
    template <class Ext>
    struct variant_translator
    {
        typedef Ext external_type;
        typedef variant internal_type;

        /*
        typedef boost::mpl::joint_view<variant::int_types,
                boost::mpl::vector<bool,double>
            > valid_non_string_types;
        */
        typedef variant::valid_types valid_types;

        external_type get_value(const internal_type& value) const {
            return value.get<external_type>();
        }

        template<typename T>
        typename boost::disable_if<
            boost::is_same<
                boost::mpl::end<valid_types>::type,
                boost::mpl::find<variant::valid_types, T>
            >,
            internal_type>::type
        put_value(T value) const {
            return variant(value);
        }
    };

    typedef boost::property_tree::basic_ptree<
            std::string,                    // Key type
            variant,                        // Data type
            std::less<std::string>          // Key comparison
    > basic_variant_tree;

} // namespace detail

class variant_tree : public detail::basic_variant_tree
{
    typedef detail::basic_variant_tree base;
    typedef variant_tree self_type;
public:
    typedef boost::property_tree::ptree_bad_path bad_path;
    typedef std::pair<const std::string, base> value_type;

    variant_tree() {}
    variant_tree(const detail::basic_variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}
    variant_tree(const variant_tree& a_rhs)
        : detail::basic_variant_tree(a_rhs)
    {}

    template <typename Source>
    static void read_info(Source& src, variant_tree& tree) {
        boost::property_tree::info_parser::read_info(src, static_cast<base&>(tree));
        boost::property_tree::translator_between<util::variant, std::string> tr;
        translate_data(tr, tree);
    }

    template <typename Target>
    static void write_info(Target& tar, variant_tree& tree) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree));
    }

    template <typename Target, typename Settings>
    static void write_info(Target& tar, variant_tree& tree, const Settings& tt) {
        boost::property_tree::info_parser::write_info(tar, static_cast<base&>(tree), tt);
    }

    template <class T>
    T get_value() const {
        using boost::throw_exception;

        if(boost::optional<T> o =
                base::get_value_optional<T>(detail::variant_translator<T>())) {
            return *o;
        }
        BOOST_PROPERTY_TREE_THROW(boost::property_tree::ptree_bad_data(
            std::string("conversion of data to type \"") +
            typeid(T).name() + "\" failed", base::data()));
    }

    template <class T>
    T get_value(const T& default_value) const {
        return base::get_value(default_value, detail::variant_translator<T>());
    }

    std::string get_value(const char* default_value) const {
        return base::get_value(std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_value_optional() const {
        return base::get_value(detail::variant_translator<T>());
    }

    template <class T>
    void put_value(const T& value) {
        base::put_value(value, detail::variant_translator<T>());
    }

    template <class T>
    T get(const path_type& path) const {
        try {
            return base::get_child(path).BOOST_NESTED_TEMPLATE
                get_value<T>(detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            std::stringstream s;
            s << "Cannot convert value to type '" << type_to_string<T>() << "'";
            throw bad_path(s.str(), path);
        }
    }

    template <class T>
    T get(const path_type& path, const T& default_value) const {
        try {
            return base::get(path, default_value, detail::variant_translator<T>());
        } catch (boost::bad_get& e) {
            throw bad_path("Wrong or missing value type", path);
        }
    }

    std::string get(const path_type& path, const char* default_value) const {
        return base::get(path, std::string(default_value),
            detail::variant_translator<std::string>());
    }

    template <class T>
    boost::optional<T> get_optional(const path_type& path) const {
        return base::get_optional(path, detail::variant_translator<T>());
    }

    template <class T>
    void put(const path_type& path, const T& value) {
        base::put(path, value, detail::variant_translator<T>());
    }

    template <class T>
    self_type& add(const path_type& path, const T& value) {
        return static_cast<self_type&>(
            base::add(path, value, detail::variant_translator<T>()));
    }

    void swap(variant_tree& rhs) {
        base::swap(static_cast<base&>(rhs));
    }
    void swap(boost::property_tree::basic_ptree<
        std::string, variant, std::less<std::string> >& rhs) {
        base::swap(rhs);
    }

    self_type &get_child(const path_type &path) {
        return static_cast<self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or throw @c ptree_bad_path. */
    const self_type &get_child(const path_type &path) const {
        return static_cast<const self_type&>(base::get_child(path));
    }

    /** Get the child at the given path, or return @p default_value. */
    self_type &get_child(const path_type &path, self_type &default_value) {
        return static_cast<self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return @p default_value. */
    const self_type &get_child(const path_type &path,
                               const self_type &default_value) const {
        return static_cast<const self_type&>(base::get_child(path, default_value));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<self_type &> get_child_optional(const path_type &path) {
        boost::optional<base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<self_type&>();
        return boost::optional<self_type&>(static_cast<self_type&>(*o));
    }

    /** Get the child at the given path, or return boost::null. */
    boost::optional<const self_type &>
    get_child_optional(const path_type &path) const {
        boost::optional<const base&> o = base::get_child_optional(path);
        if (!o)
            return boost::optional<const self_type&>();
        return boost::optional<const self_type&>(static_cast<const self_type&>(*o));
    }

    self_type &put_child(const path_type &path, const self_type &value) {
        return static_cast<self_type&>(base::put_child(path, value));
    }

protected:
    template <typename T>
    static void translate_data(T& tr, base& tree) {
        for (variant_tree::iterator it=tree.begin(); it != tree.end(); it++)
            translate_data(tr, it->second);
        tree.data() = *tr.put_value(tree.get_value<std::string>());
    }
};

} // namespace util

#endif // _UTIL_VARIANT_TREE_HPP_
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file   signal_block.hpp
/// \author Serge ALeynikov <saleyn@gmail.com>
/// \author Peter Simons <simons@cryp.to> (signal_block/unblock)
//----------------------------------------------------------------------------
/// \brief Signal blocking class.
//----------------------------------------------------------------------------
// Copyright (c) 2014 Serge Aleynikov <saleyn@gmail.com>
// Copyright (c) 2010 Peter Simons <simons@cryp.to> (signal_block/unblock)
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (c) 2014 Serge Aleynikov

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <boost/noncopyable.hpp>
#include <utxx/error.hpp>
#include <signal.h>

namespace utxx
{

/// Block all POSIX signals in the current scope.
/// \sa signal_unblock
class signal_block : private boost::noncopyable {
    sigset_t m_orig_mask;
    bool     m_restore;

    static sigset_t full()  { sigset_t s; ::sigfillset(&s);  return s; }
    static sigset_t empty() { sigset_t s; ::sigemptyset(&s); return s; }
public:

    explicit signal_block(bool a_block = true, bool a_restore = true)
        : signal_block(a_block ? full() : empty(), a_restore)
    {}

    explicit signal_block(sigset_t const& a_block, bool a_restore = true)
        : m_restore(a_restore)
    {
        if (sigisemptyset(&a_block))
            ::sigemptyset(&m_orig_mask);
        else
            block();
    }

    void block() {
        sigset_t block_all;
        if (::sigfillset(&block_all) < 0)
            UTXX_THROW_IO_ERROR(errno, "sigfillset(3)");
        if (::sigprocmask(SIG_SETMASK, &block_all, &m_orig_mask))
            UTXX_THROW_IO_ERROR(errno, "sigprocmask(2)");
    }

    ~signal_block() {
        if (!sigisemptyset(&m_orig_mask) && m_restore)
            ::sigprocmask(SIG_SETMASK, &m_orig_mask, static_cast<sigset_t*>(0));
    }
};

/// Unblock all POSIX signals in the current scope.
/// \sa signal_block
class signal_unblock : private boost::noncopyable {
    sigset_t m_orig_mask;
    bool     m_restore;
public:
    signal_unblock(bool a_restore = true)
        : m_restore(a_restore)
    {
        sigset_t l_unblock_all;
        if (::sigemptyset(&l_unblock_all) < 0)
            UTXX_THROW_IO_ERROR(errno, "sigfillset(3)");
        if (::sigprocmask(SIG_SETMASK, &l_unblock_all, &m_orig_mask))
            UTXX_THROW_IO_ERROR(errno, "sigprocmask(2)");
    }

    ~signal_unblock() {
        if (m_restore)
            ::sigprocmask(SIG_SETMASK, &m_orig_mask, static_cast<sigset_t*>(0));
    }
};

/// Get a list of all known signal names.
/// @return list of char strings that can be iterated until NULL.
const char** sig_names();

/// Total number of "well-known" signal names in the sig_names() array
static constexpr size_t sig_names_count() { return 64; }

/// Get the name of an OS signal number.
/// @return signal name or "<UNDEFINED>" if the name is not defined.
const char* sig_name(int a_signum);

/// Convert signal set to string
std::string sig_members(const sigset_t& a_set);

/// Initialize a signal set from an argument list
template <class... Signals>
sigset_t sig_init_set(Signals&&... args) {
    sigset_t sset;
    sigemptyset(&sset);
    int sigs[] = { args... };
    for (uint i=0; i < sizeof...(Signals); ++i)
        if (sigaddset(&sset, sigs[i]) < 0)
            UTXX_THROW_IO_ERROR(errno, "Error in sigaddset[", sigs[i], ']');
    return sset;
}

/// Parse a string containing pipe/comma/column/space delimited signal names.
/// The signal names are case insensitive and not required to begin with "SIG".
sigset_t sig_members_parse(const std::string& a_signals, src_info&& a_si);

/// Convert a vector of integer signal numbers to sigset
sigset_t sig_vector_to_set(const std::vector<int>& a_signals);

/// Return a formatted string containing current signals
inline std::string curr_signals_to_str(utxx::src_info&& si = utxx::src_info(), bool decode=false) {
    sigset_t old;
    char res[1024], buf[64];
    if (sigprocmask(SIG_SETMASK, NULL, &old) < 0)
        strcpy(buf, "<error>");
    else
        snprintf(buf, sizeof(buf), "%lx", reinterpret_cast<uint64_t&>(old));

    auto n = snprintf(res, sizeof(res), "%sPID: %d SigMask: %s",
                      si.empty() ? "" : si.to_string("[","] ").c_str(), getpid(), res);
    if (decode)
      snprintf(res+n, sizeof(res)-n, " %s", utxx::sig_members(old).c_str());

    return res;
}

} // namespace utxx
<commit_msg>Fix bug<commit_after>//----------------------------------------------------------------------------
/// \file   signal_block.hpp
/// \author Serge ALeynikov <saleyn@gmail.com>
/// \author Peter Simons <simons@cryp.to> (signal_block/unblock)
//----------------------------------------------------------------------------
/// \brief Signal blocking class.
//----------------------------------------------------------------------------
// Copyright (c) 2014 Serge Aleynikov <saleyn@gmail.com>
// Copyright (c) 2010 Peter Simons <simons@cryp.to> (signal_block/unblock)
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (c) 2014 Serge Aleynikov

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <boost/noncopyable.hpp>
#include <utxx/error.hpp>
#include <signal.h>

namespace utxx
{

/// Block all POSIX signals in the current scope.
/// \sa signal_unblock
class signal_block : private boost::noncopyable {
    sigset_t m_orig_mask;
    bool     m_restore;

    static sigset_t full()  { sigset_t s; ::sigfillset(&s);  return s; }
    static sigset_t empty() { sigset_t s; ::sigemptyset(&s); return s; }
public:

    explicit signal_block(bool a_block = true, bool a_restore = true)
        : signal_block(a_block ? full() : empty(), a_restore)
    {}

    explicit signal_block(sigset_t const& a_block, bool a_restore = true)
        : m_restore(a_restore)
    {
        if (sigisemptyset(&a_block))
            ::sigemptyset(&m_orig_mask);
        else
            block();
    }

    void block() {
        sigset_t block_all;
        if (::sigfillset(&block_all) < 0)
            UTXX_THROW_IO_ERROR(errno, "sigfillset(3)");
        if (::sigprocmask(SIG_SETMASK, &block_all, &m_orig_mask))
            UTXX_THROW_IO_ERROR(errno, "sigprocmask(2)");
    }

    ~signal_block() {
        if (!sigisemptyset(&m_orig_mask) && m_restore)
            ::sigprocmask(SIG_SETMASK, &m_orig_mask, static_cast<sigset_t*>(0));
    }
};

/// Unblock all POSIX signals in the current scope.
/// \sa signal_block
class signal_unblock : private boost::noncopyable {
    sigset_t m_orig_mask;
    bool     m_restore;
public:
    signal_unblock(bool a_restore = true)
        : m_restore(a_restore)
    {
        sigset_t l_unblock_all;
        if (::sigemptyset(&l_unblock_all) < 0)
            UTXX_THROW_IO_ERROR(errno, "sigfillset(3)");
        if (::sigprocmask(SIG_SETMASK, &l_unblock_all, &m_orig_mask))
            UTXX_THROW_IO_ERROR(errno, "sigprocmask(2)");
    }

    ~signal_unblock() {
        if (m_restore)
            ::sigprocmask(SIG_SETMASK, &m_orig_mask, static_cast<sigset_t*>(0));
    }
};

/// Get a list of all known signal names.
/// @return list of char strings that can be iterated until NULL.
const char** sig_names();

/// Total number of "well-known" signal names in the sig_names() array
static constexpr size_t sig_names_count() { return 64; }

/// Get the name of an OS signal number.
/// @return signal name or "<UNDEFINED>" if the name is not defined.
const char* sig_name(int a_signum);

/// Convert signal set to string
std::string sig_members(const sigset_t& a_set);

/// Initialize a signal set from an argument list
template <class... Signals>
sigset_t sig_init_set(Signals&&... args) {
    sigset_t sset;
    sigemptyset(&sset);
    int sigs[] = { args... };
    for (uint i=0; i < sizeof...(Signals); ++i)
        if (sigaddset(&sset, sigs[i]) < 0)
            UTXX_THROW_IO_ERROR(errno, "Error in sigaddset[", sigs[i], ']');
    return sset;
}

/// Parse a string containing pipe/comma/column/space delimited signal names.
/// The signal names are case insensitive and not required to begin with "SIG".
sigset_t sig_members_parse(const std::string& a_signals, src_info&& a_si);

/// Convert a vector of integer signal numbers to sigset
sigset_t sig_vector_to_set(const std::vector<int>& a_signals);

/// Return a formatted string containing current signals
inline std::string curr_signals_to_str(utxx::src_info&& si = utxx::src_info(), bool decode=false) {
    sigset_t old;
    char res[1024], buf[64];
    if (sigprocmask(SIG_SETMASK, NULL, &old) < 0)
        strcpy(buf, "<error>");
    else
        snprintf(buf, sizeof(buf), "%lx", reinterpret_cast<uint64_t&>(old));

    auto n = snprintf(res, sizeof(res), "%sPID: %d SigMask: %s",
                      si.empty() ? "" : si.to_string("[","] ").c_str(), getpid(), buf);
    if (decode)
      snprintf(res+n, sizeof(res)-n, " %s", utxx::sig_members(old).c_str());

    return res;
}

} // namespace utxx
<|endoftext|>