<commit_before>/**
 * @file
 */
#pragma once
#if ENABLE_LAZY_DEEP_CLONE

#include "libbirch/clone.hpp"
#include "libbirch/LazyAny.hpp"
#include "libbirch/LazyContext.hpp"
#include "libbirch/Nil.hpp"
#include "libbirch/ContextPtr.hpp"

namespace libbirch {
template<class T> class Optional;

/**
 * Wraps another pointer type to apply lazy deep clone semantics.
 *
 * @ingroup libbirch
 *
 * @tparam P Pointer type.
 */
template<class P>
class LazyPtr {
  template<class U> friend class LazyPtr;
public:
  using T = typename P::value_type;
  template<class U> using cast_type = LazyPtr<typename P::template cast_type<U>>;

  /**
   * Constructor.
   */
  LazyPtr(const Nil& = nil) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(T* object) :
      object(object),
      to(object ? currentContext : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(const P& object) :
      object(object),
      to(object ? currentContext : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(T* object, LazyContext* to) :
      object(object),
      to(object ? to : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(const P& object, LazyContext* to) :
      object(object),
      to(object ? to : nullptr) {
    //
  }

  /**
   * Copy constructor.
   */
  LazyPtr(const LazyPtr<P>& o) :
      object(nullptr),
      to(cloneUnderway ? currentContext : o.to) {
    if (o.object) {
      if (cloneUnderway) {
        if (o.isCross()) {
          o.finish();
        }
        object = o.object;
      } else {
        object = o.object->isSingular() ? o.get() : o.object;
      }
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr(const LazyPtr<Q>& o) :
      object((o.object && o.object->isSingular()) ? o.get() : o.object),
      to(o.object ? o.to : nullptr) {
    //
  }

  /**
   * Move constructor.
   */
  LazyPtr(LazyPtr<P> && o) = default;

  /**
   * Generic move constructor.
   */
  template<class Q>
  LazyPtr(LazyPtr<Q> && o) :
      object(std::move(o.object)),
      to(std::move(o.to)) {
    //
  }

  /**
   * Copy assignment.
   */
  LazyPtr<P>& operator=(const LazyPtr<P>& o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = o.to;
    object = (o.object && o.object->isSingular()) ? o.get() : o.object;
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(const LazyPtr<Q>& o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = o.to;
    object = (o.object && o.object->isSingular()) ? o.get() : o.object;
    return *this;
  }

  /**
   * Move assignment.
   */
  LazyPtr<P>& operator=(LazyPtr<P> && o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = std::move(o.to);
    object = std::move(o.object);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(LazyPtr<Q> && o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = std::move(o.to);
    object = std::move(o.object);
    return *this;
  }

  /**
   * Raw pointer assignment.
   */
  LazyPtr<P>& operator=(T* o) {
    assert(!o || !o->isSingular());
    to = o ? currentContext : nullptr;
    object = o;
    return *this;
  }

  /**
   * Nil assignment.
   */
  LazyPtr<P>& operator=(const Nil&) {
    to = nullptr;
    object = nullptr;
    return *this;
  }

  /**
   * Nullptr assignment.
   */
  LazyPtr<P>& operator=(const std::nullptr_t&) {
    to = nullptr;
    object = nullptr;
    return *this;
  }

  /**
   * Optional assignment.
   */
  LazyPtr<P>& operator=(const Optional<LazyPtr<P>>& o) {
    if (o.query()) {
      *this = o.get();
    } else {
      *this = nullptr;
    }
    return *this;
  }

  /**
   * Generic optional assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(const Optional<LazyPtr<Q>>& o) {
    if (o.query()) {
      *this = o.get();
    } else {
      *this = nullptr;
    }
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U>
  LazyPtr<P>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value conversion.
   */
  template<class U, typename = std::enable_if_t<std::is_convertible<T,U>::value>>
  operator U() const {
    return static_cast<U>(*get());
  }

  /**
   * Is the pointer not null?
   */
  bool query() const {
    return static_cast<bool>(object);
  }

  /**
   * Get the raw pointer, with lazy cloning.
   */
  T* get() {
    auto raw = object.get();
    if (raw && raw->isFrozen()) {
      raw = static_cast<T*>(to->get(raw));
      object = raw;
    }
    return raw;
  }

  /**
   * Get the raw pointer, with lazy cloning.
   */
  T* get() const {
    return const_cast<LazyPtr<P>*>(this)->get();
  }

  /**
   * Get the raw pointer for read-only use, without cloning.
   */
  const T* pull() {
    #if ENABLE_READ_ONLY_OPTIMIZATION
    auto raw = object.get();
    if (raw && raw->isFrozen()) {
      raw = static_cast<T*>(to->pull(raw));
      object = raw;
    }
    return raw;
    #else
    return get();
    #endif
  }

  /**
   * Get the raw pointer for read-only use, without cloning.
   */
  const T* pull() const {
    return const_cast<LazyPtr<P>*>(this)->pull();
  }

  /**
   * Deep clone.
   */
  LazyPtr<P> clone() const {
    LazyContext* context = nullptr;
    if (object) {
      freeze();
      context = to->fork();
    }
    return LazyPtr<P>(object, context);
  }

  /**
   * Freeze.
   */
  void freeze() {
    if (object) {
      object->freeze();
      to->freeze();
    }
  }

  /**
   * Freeze.
   */
  void freeze() const {
    return const_cast<LazyPtr<P>*>(this)->freeze();
  }

  /**
   * Finish.
   */
  void finish() {
    auto raw = object.get();
    if (raw) {
      if (raw->isFrozen()) {
        raw = static_cast<T*>(to->get(raw));
        object = raw;
      }
      raw->finish();
    }
  }

  /**
   * Finish.
   */
  void finish() const {
    return const_cast<LazyPtr<P>*>(this)->finish();
  }

  /**
   * Does this pointer result from a cross copy?
   */
  bool isCross() const {
    return to.get() != to.getContext();
  }

  /**
   * Get the context of the object.
   */
  LazyContext* getContext() const {
    return to.get();
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Equal comparison.
   */
  template<class U>
  bool operator==(const LazyPtr<U>& o) const {
    return get() == o.get();
  }

  /**
   * Not equal comparison.
   */
  template<class U>
  bool operator!=(const LazyPtr<U>& o) const {
    return get() != o.get();
  }

  /**
   * Dynamic cast. Returns `nullptr` if unsuccessful.
   */
  template<class U>
  auto dynamic_pointer_cast() const {
    return cast_type<U>(dynamic_cast<U*>(object.get()), to.get());
  }

  /**
   * Static cast. Undefined if unsuccessful.
   */
  template<class U>
  auto static_pointer_cast() const {
    return cast_type<U>(static_cast<U*>(object.get()), to.get());
  }

protected:
  /**
   * Object.
   */
  P object;

  /**
   * Context to which to map the object.
   */
  ContextPtr to;
};
}

#endif
<commit_msg>Corrected finish (previously-deleted pull() actually needed for clone()).<commit_after>/**
 * @file
 */
#pragma once
#if ENABLE_LAZY_DEEP_CLONE

#include "libbirch/clone.hpp"
#include "libbirch/LazyAny.hpp"
#include "libbirch/LazyContext.hpp"
#include "libbirch/Nil.hpp"
#include "libbirch/ContextPtr.hpp"

namespace libbirch {
template<class T> class Optional;

/**
 * Wraps another pointer type to apply lazy deep clone semantics.
 *
 * @ingroup libbirch
 *
 * @tparam P Pointer type.
 */
template<class P>
class LazyPtr {
  template<class U> friend class LazyPtr;
public:
  using T = typename P::value_type;
  template<class U> using cast_type = LazyPtr<typename P::template cast_type<U>>;

  /**
   * Constructor.
   */
  LazyPtr(const Nil& = nil) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(T* object) :
      object(object),
      to(object ? currentContext : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(const P& object) :
      object(object),
      to(object ? currentContext : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(T* object, LazyContext* to) :
      object(object),
      to(object ? to : nullptr) {
    //
  }

  /**
   * Constructor.
   */
  LazyPtr(const P& object, LazyContext* to) :
      object(object),
      to(object ? to : nullptr) {
    //
  }

  /**
   * Copy constructor.
   */
  LazyPtr(const LazyPtr<P>& o) :
      object(nullptr),
      to(cloneUnderway ? currentContext : o.to) {
    if (o.object) {
      if (cloneUnderway) {
        if (o.isCross()) {
          o.finish();
        }
        object = o.object;
      } else {
        object = o.object->isSingular() ? o.get() : o.object;
      }
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr(const LazyPtr<Q>& o) :
      object((o.object && o.object->isSingular()) ? o.get() : o.object),
      to(o.object ? o.to : nullptr) {
    //
  }

  /**
   * Move constructor.
   */
  LazyPtr(LazyPtr<P> && o) = default;

  /**
   * Generic move constructor.
   */
  template<class Q>
  LazyPtr(LazyPtr<Q> && o) :
      object(std::move(o.object)),
      to(std::move(o.to)) {
    //
  }

  /**
   * Copy assignment.
   */
  LazyPtr<P>& operator=(const LazyPtr<P>& o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = o.to;
    object = (o.object && o.object->isSingular()) ? o.get() : o.object;
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(const LazyPtr<Q>& o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = o.to;
    object = (o.object && o.object->isSingular()) ? o.get() : o.object;
    return *this;
  }

  /**
   * Move assignment.
   */
  LazyPtr<P>& operator=(LazyPtr<P> && o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = std::move(o.to);
    object = std::move(o.object);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(LazyPtr<Q> && o) {
    /* it's possible that object = o.object actually destroys the referent
     * of o, so do the to = o.to first */
    to = std::move(o.to);
    object = std::move(o.object);
    return *this;
  }

  /**
   * Raw pointer assignment.
   */
  LazyPtr<P>& operator=(T* o) {
    assert(!o || !o->isSingular());
    to = o ? currentContext : nullptr;
    object = o;
    return *this;
  }

  /**
   * Nil assignment.
   */
  LazyPtr<P>& operator=(const Nil&) {
    to = nullptr;
    object = nullptr;
    return *this;
  }

  /**
   * Nullptr assignment.
   */
  LazyPtr<P>& operator=(const std::nullptr_t&) {
    to = nullptr;
    object = nullptr;
    return *this;
  }

  /**
   * Optional assignment.
   */
  LazyPtr<P>& operator=(const Optional<LazyPtr<P>>& o) {
    if (o.query()) {
      *this = o.get();
    } else {
      *this = nullptr;
    }
    return *this;
  }

  /**
   * Generic optional assignment.
   */
  template<class Q, typename = std::enable_if_t<std::is_base_of<T,
      typename Q::value_type>::value>>
  LazyPtr<P>& operator=(const Optional<LazyPtr<Q>>& o) {
    if (o.query()) {
      *this = o.get();
    } else {
      *this = nullptr;
    }
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U>
  LazyPtr<P>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value conversion.
   */
  template<class U, typename = std::enable_if_t<std::is_convertible<T,U>::value>>
  operator U() const {
    return static_cast<U>(*get());
  }

  /**
   * Is the pointer not null?
   */
  bool query() const {
    return static_cast<bool>(object);
  }

  /**
   * Get the raw pointer, with lazy cloning.
   */
  T* get() {
    auto raw = object.get();
    if (raw && raw->isFrozen()) {
      raw = static_cast<T*>(to->get(raw));
      object = raw;
    }
    return raw;
  }

  /**
   * Get the raw pointer, with lazy cloning.
   */
  T* get() const {
    return const_cast<LazyPtr<P>*>(this)->get();
  }

  /**
   * Get the raw pointer for read-only use, without cloning.
   */
  const T* pull() {
    #if ENABLE_READ_ONLY_OPTIMIZATION
    auto raw = object.get();
    if (raw && raw->isFrozen()) {
      raw = static_cast<T*>(to->pull(raw));
      object = raw;
    }
    return raw;
    #else
    return get();
    #endif
  }

  /**
   * Get the raw pointer for read-only use, without cloning.
   */
  const T* pull() const {
    return const_cast<LazyPtr<P>*>(this)->pull();
  }

  /**
   * Deep clone.
   */
  LazyPtr<P> clone() const {
    LazyContext* context = nullptr;
    if (object) {
      freeze();
      context = to->fork();
    }
    return LazyPtr<P>(object, context);
  }

  /**
   * Freeze.
   */
  void freeze() {
    if (object) {
      pull();
      object->freeze();
      to->freeze();
    }
  }

  /**
   * Freeze.
   */
  void freeze() const {
    return const_cast<LazyPtr<P>*>(this)->freeze();
  }

  /**
   * Finish.
   */
  void finish() {
    if (object) {
      get();
      object->finish();
    }
  }

  /**
   * Finish.
   */
  void finish() const {
    return const_cast<LazyPtr<P>*>(this)->finish();
  }

  /**
   * Does this pointer result from a cross copy?
   */
  bool isCross() const {
    return to.get() != to.getContext();
  }

  /**
   * Get the context of the object.
   */
  LazyContext* getContext() const {
    return to.get();
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Equal comparison.
   */
  template<class U>
  bool operator==(const LazyPtr<U>& o) const {
    return get() == o.get();
  }

  /**
   * Not equal comparison.
   */
  template<class U>
  bool operator!=(const LazyPtr<U>& o) const {
    return get() != o.get();
  }

  /**
   * Dynamic cast. Returns `nullptr` if unsuccessful.
   */
  template<class U>
  auto dynamic_pointer_cast() const {
    return cast_type<U>(dynamic_cast<U*>(object.get()), to.get());
  }

  /**
   * Static cast. Undefined if unsuccessful.
   */
  template<class U>
  auto static_pointer_cast() const {
    return cast_type<U>(static_cast<U*>(object.get()), to.get());
  }

protected:
  /**
   * Object.
   */
  P object;

  /**
   * Context to which to map the object.
   */
  ContextPtr to;
};
}

#endif
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate
                             // to one LUT6 (instead of a LUT5 + LUT2)

struct SynthXilinxPass : public ScriptPass
{
	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_xilinx [options]\n");
		log("\n");
		log("This command runs synthesis for Xilinx FPGAs. This command does not operate on\n");
		log("partly selected designs. At the moment this command creates netlists that are\n");
		log("compatible with 7-Series Xilinx devices.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -family {xcup|xcu|xc7|xc6s}\n");
		log("        run synthesis for the specified Xilinx architecture\n");
		log("        generate the synthesis netlist for the specified family.\n");
		log("        default: xc7\n");
		log("\n");
		log("    -edif <file>\n");
		log("        write the design to the specified edif file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -blif <file>\n");
		log("        write the design to the specified BLIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -vpr\n");
		log("        generate an output netlist (and BLIF file) suitable for VPR\n");
		log("        (this feature is experimental and incomplete)\n");
		log("\n");
		log("    -nocarry\n");
		log("        disable inference of carry chains\n");
		log("\n");
		log("    -nobram\n");
		log("        disable inference of block rams\n");
		log("\n");
		log("    -nodram\n");
		log("        disable inference of distributed rams\n");
		log("\n");
		log("    -nosrl\n");
		log("        disable inference of shift registers\n");
		log("\n");
		log("    -nocarry\n");
		log("        do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
		log("\n");
		log("    -nowidelut\n");
		log("        do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -flatten\n");
		log("        flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("    -abc9\n");
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	std::string top_opt, edif_file, blif_file, family;
	bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9;

	void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		edif_file.clear();
		blif_file.clear();
		family = "xc7";
		flatten = false;
		retime = false;
		vpr = false;
		nocarry = false;
		nobram = false;
		nodram = false;
		nosrl = false;
		nocarry = false;
		nowidelut = false;
		abc9 = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		std::string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
				family = args[++argidx];
				continue;
			}
			if (args[argidx] == "-edif" && argidx+1 < args.size()) {
				edif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-blif" && argidx+1 < args.size()) {
				blif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nowidelut") {
				nowidelut = true;
				continue;
			}
			if (args[argidx] == "-vpr") {
				vpr = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-nodram") {
				nodram = true;
				continue;
			}
			if (args[argidx] == "-nosrl") {
				nosrl = true;
				continue;
			}
			if (args[argidx] == "-abc9") {
				abc9 = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")
			log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str());

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH_XILINX pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() YS_OVERRIDE
	{
		if (check_label("begin")) {
			if (vpr)
				run("read_verilog -lib -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
			else
				run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v");

			run("read_verilog -lib +/xilinx/cells_xtra.v");

			if (!nobram || help_mode)
				run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')");

			run(stringf("hierarchy -check %s", top_opt.c_str()));
		}

		if (check_label("flatten", "(with '-flatten' only)")) {
			if (flatten || help_mode) {
				run("proc");
				run("flatten");
			}
		}

		if (check_label("coarse")) {
			run("synth -run coarse");

			// shregmap -tech xilinx can cope with $shiftx and $mux
			//   cells for identifying variable-length shift registers,
			//   so attempt to convert $pmux-es to the former
			if (!nosrl || help_mode)
				run("pmux2shiftx", "(skip if '-nosrl')");

			// Run a number of peephole optimisations, including one
			//   that optimises $mul cells driving $shiftx's B input
			//   and that aids wide mux analysis
			run("peepopt");
		}

		if (check_label("bram", "(skip if '-nobram')")) {
			if (!nobram || help_mode) {
				run("memory_bram -rules +/xilinx/brams.txt");
				run("techmap -map +/xilinx/brams_map.v");
			}
		}

		if (check_label("dram", "(skip if '-nodram')")) {
			if (!nodram || help_mode) {
				run("memory_bram -rules +/xilinx/drams.txt");
				run("techmap -map +/xilinx/drams_map.v");
			}
		}

		if (check_label("fine")) {
			run("opt -fast -full");
			run("memory_map");
			run("dffsr2dff");
			run("dff2dffe");
			run("opt -full");

			if (!nosrl || help_mode) {
				// shregmap operates on bit-level flops, not word-level,
				//   so break those down here
				run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')");
				// shregmap with '-tech xilinx' infers variable length shift regs
				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
			}

			std::string techmap_files = " -map +/techmap.v";
			if (help_mode)
				techmap_files += " [-map +/xilinx/arith_map.v]";
			else if (!nocarry) {
				techmap_files += " -map +/xilinx/arith_map.v";
				if (vpr)
					techmap_files += " -D _EXPLICIT_CARRY";
				else if (abc9)
					techmap_files += " -D _CLB_CARRY";
			}
			run("techmap " + techmap_files);
			run("opt -fast");
		}

		if (check_label("map_cells")) {
			run("techmap -map +/techmap.v -map +/xilinx/cells_map.v");
			run("clean");
		}

		if (check_label("map_luts")) {
			run("opt_expr -mux_undef");
			if (help_mode)
				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')");
			else if (abc9) {
				if (family != "xc7")
					log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
				if (nowidelut)
					run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
				else
					run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
			}
			else {
				if (nowidelut)
					run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
				else
					run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
			}
			run("clean");

			// This shregmap call infers fixed length shift registers after abc
			//   has performed any necessary retiming
			if (!nosrl || help_mode)
				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
			run("clean");
		}

		if (check_label("check")) {
			run("hierarchy -check");
			run("stat -tech xilinx");
			run("check -noinit");
		}

		if (check_label("edif")) {
			if (!edif_file.empty() || help_mode)
				run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
		}

		if (check_label("blif")) {
			if (!blif_file.empty() || help_mode)
				run(stringf("write_blif %s", edif_file.c_str()));
		}
	}
} SynthXilinxPass;

PRIVATE_NAMESPACE_END
<commit_msg>Remove redundant doc<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate
                             // to one LUT6 (instead of a LUT5 + LUT2)

struct SynthXilinxPass : public ScriptPass
{
	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_xilinx [options]\n");
		log("\n");
		log("This command runs synthesis for Xilinx FPGAs. This command does not operate on\n");
		log("partly selected designs. At the moment this command creates netlists that are\n");
		log("compatible with 7-Series Xilinx devices.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -family {xcup|xcu|xc7|xc6s}\n");
		log("        run synthesis for the specified Xilinx architecture\n");
		log("        generate the synthesis netlist for the specified family.\n");
		log("        default: xc7\n");
		log("\n");
		log("    -edif <file>\n");
		log("        write the design to the specified edif file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -blif <file>\n");
		log("        write the design to the specified BLIF file. writing of an output file\n");
		log("        is omitted if this parameter is not specified.\n");
		log("\n");
		log("    -vpr\n");
		log("        generate an output netlist (and BLIF file) suitable for VPR\n");
		log("        (this feature is experimental and incomplete)\n");
		log("\n");
		log("    -nobram\n");
		log("        disable inference of block rams\n");
		log("\n");
		log("    -nodram\n");
		log("        disable inference of distributed rams\n");
		log("\n");
		log("    -nosrl\n");
		log("        disable inference of shift registers\n");
		log("\n");
		log("    -nocarry\n");
		log("        do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
		log("\n");
		log("    -nowidelut\n");
		log("        do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -flatten\n");
		log("        flatten design before synthesis\n");
		log("\n");
		log("    -retime\n");
		log("        run 'abc' with -dff option\n");
		log("\n");
		log("    -abc9\n");
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	std::string top_opt, edif_file, blif_file, family;
	bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9;

	void clear_flags() YS_OVERRIDE
	{
		top_opt = "-auto-top";
		edif_file.clear();
		blif_file.clear();
		family = "xc7";
		flatten = false;
		retime = false;
		vpr = false;
		nocarry = false;
		nobram = false;
		nodram = false;
		nosrl = false;
		nocarry = false;
		nowidelut = false;
		abc9 = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		std::string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
				family = args[++argidx];
				continue;
			}
			if (args[argidx] == "-edif" && argidx+1 < args.size()) {
				edif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-blif" && argidx+1 < args.size()) {
				blif_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos+1);
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-retime") {
				retime = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nowidelut") {
				nowidelut = true;
				continue;
			}
			if (args[argidx] == "-vpr") {
				vpr = true;
				continue;
			}
			if (args[argidx] == "-nocarry") {
				nocarry = true;
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-nodram") {
				nodram = true;
				continue;
			}
			if (args[argidx] == "-nosrl") {
				nosrl = true;
				continue;
			}
			if (args[argidx] == "-abc9") {
				abc9 = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")
			log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str());

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH_XILINX pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() YS_OVERRIDE
	{
		if (check_label("begin")) {
			if (vpr)
				run("read_verilog -lib -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
			else
				run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v");

			run("read_verilog -lib +/xilinx/cells_xtra.v");

			if (!nobram || help_mode)
				run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')");

			run(stringf("hierarchy -check %s", top_opt.c_str()));
		}

		if (check_label("flatten", "(with '-flatten' only)")) {
			if (flatten || help_mode) {
				run("proc");
				run("flatten");
			}
		}

		if (check_label("coarse")) {
			run("synth -run coarse");

			// shregmap -tech xilinx can cope with $shiftx and $mux
			//   cells for identifying variable-length shift registers,
			//   so attempt to convert $pmux-es to the former
			if (!nosrl || help_mode)
				run("pmux2shiftx", "(skip if '-nosrl')");

			// Run a number of peephole optimisations, including one
			//   that optimises $mul cells driving $shiftx's B input
			//   and that aids wide mux analysis
			run("peepopt");
		}

		if (check_label("bram", "(skip if '-nobram')")) {
			if (!nobram || help_mode) {
				run("memory_bram -rules +/xilinx/brams.txt");
				run("techmap -map +/xilinx/brams_map.v");
			}
		}

		if (check_label("dram", "(skip if '-nodram')")) {
			if (!nodram || help_mode) {
				run("memory_bram -rules +/xilinx/drams.txt");
				run("techmap -map +/xilinx/drams_map.v");
			}
		}

		if (check_label("fine")) {
			run("opt -fast -full");
			run("memory_map");
			run("dffsr2dff");
			run("dff2dffe");
			run("opt -full");

			if (!nosrl || help_mode) {
				// shregmap operates on bit-level flops, not word-level,
				//   so break those down here
				run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')");
				// shregmap with '-tech xilinx' infers variable length shift regs
				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
			}

			std::string techmap_files = " -map +/techmap.v";
			if (help_mode)
				techmap_files += " [-map +/xilinx/arith_map.v]";
			else if (!nocarry) {
				techmap_files += " -map +/xilinx/arith_map.v";
				if (vpr)
					techmap_files += " -D _EXPLICIT_CARRY";
				else if (abc9)
					techmap_files += " -D _CLB_CARRY";
			}
			run("techmap " + techmap_files);
			run("opt -fast");
		}

		if (check_label("map_cells")) {
			run("techmap -map +/techmap.v -map +/xilinx/cells_map.v");
			run("clean");
		}

		if (check_label("map_luts")) {
			run("opt_expr -mux_undef");
			if (help_mode)
				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')");
			else if (abc9) {
				if (family != "xc7")
					log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
				if (nowidelut)
					run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
				else
					run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
			}
			else {
				if (nowidelut)
					run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
				else
					run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
			}
			run("clean");

			// This shregmap call infers fixed length shift registers after abc
			//   has performed any necessary retiming
			if (!nosrl || help_mode)
				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
			run("clean");
		}

		if (check_label("check")) {
			run("hierarchy -check");
			run("stat -tech xilinx");
			run("check -noinit");
		}

		if (check_label("edif")) {
			if (!edif_file.empty() || help_mode)
				run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
		}

		if (check_label("blif")) {
			if (!blif_file.empty() || help_mode)
				run(stringf("write_blif %s", edif_file.c_str()));
		}
	}
} SynthXilinxPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_EDITOR_HPP
#define RJ_GAME_EDITOR_EDITOR_HPP

#include "background_editor.hpp"
#include "editor_entity.hpp"
#include "itembar.hpp"
#include "mouse.hpp"
#include "settingsbar.hpp"
#include <rectojump/game/components/platform.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/game/world.hpp>

namespace rj
{
	template<typename Game_Handler, typename Game>
	class editor
	{
	public:
		using gh_type = Game_Handler;

	private:
		Game_Handler& m_gamehandler;
		Game& m_game;
		world<Game_Handler>& m_gameworld;
		entity_handler& m_entityhandler;
		level_manager& m_levelmgr;

		camera m_editarea_camera;
		camera m_itembar_camera;
		camera m_settingsbar_camera;

		editor_mouse<Game_Handler> m_mouse;
		background_editor<editor> m_background{*this};
		itembar<Game_Handler> m_itembar;
		settingsbar<editor> m_settingsbar;

	public:
		editor(Game_Handler& gh) :
			m_gamehandler{gh},
			m_game{gh.get_game()},
			m_gameworld{m_game.get_world()},
			m_entityhandler{m_gameworld.get_entityhandler()},
			m_levelmgr{gh.get_levelmgr()},
			m_editarea_camera{m_gamehandler.get_gamewindow()},
			m_itembar_camera{m_gamehandler.get_gamewindow()},
			m_settingsbar_camera{m_gamehandler.get_gamewindow()},
			m_mouse{gh},
			m_itembar{gh, {settings::get_window_size<vec2f>().x, 100.f}},
			m_settingsbar{*this, {300.f, settings::get_window_size<vec2f>().y - m_itembar.get_size().y}}
		{this->init();}

		void update(dur duration)
		{
			// editareacamera move
			if(is_btn_pressed(btn::Middle)) // TODO: impl this better
				m_editarea_camera.set_center(get_mousepos());

			// edit area
			m_editarea_camera.activate();
			m_mouse.update(duration);

			// itembar
			m_itembar_camera.activate();
			m_itembar.update(duration);

			// settingsbar
			m_settingsbar_camera.activate();
			m_settingsbar.update(duration);
		}

		void update_input()
		{
			m_settingsbar.update_input();
		}

		void render()
		{
			// edit area
			m_editarea_camera.activate();
			m_entityhandler.render();
			m_mouse.render();

			// itembar
			m_itembar_camera.activate();
			m_itembar.render();

			// settingsbar
			m_settingsbar_camera.activate();
			m_settingsbar.render();
		}

		void on_activate()
		{
			m_background.reset();
		}

		void handle_save(const level_id& level_name)
		{
			if(!this->check_level_name(level_name))
				return;

			// level background
			level_background lv_bg
			{
				m_settingsbar.get_tb_startcolor_text(),
				m_settingsbar.get_tb_endcolor_text(),
				mlk::stl_string::to_int<std::size_t>(m_settingsbar.get_tb_pointcount_text())
			};

			// level data
			level_data lv_data;
			for(auto& a : m_entityhandler)
			{
				auto ent(this->to_editor_entity(a));
				lv_data.add_entity(ent->get_figure(), entity_propertie::solid, ent->pos());
			}

			level_info lv_info{level_name, m_settingsbar.get_tb_lvcreator_text(), mlk::tm::time_str()};
			music_data lv_music{'M', 'U', 'S', 'I', 'C'};
			level_packer<packer_mode::pack> lv_packer{lv_music, lv_bg, lv_data, lv_info};

			m_levelmgr.save_level(lv_packer, level_name);
		}

		void handle_load(const level_id& level_name)
		{
			if(!this->check_level_name(level_name))
				return;

//			auto& lv(m_levelmgr.get_level(level_name));
//			m_gameworld.load_level(lv.entities);
		}

		void reset_zoom() noexcept
		{m_editarea_camera.reset_zoom();}

		auto get_gamehandler() noexcept
		-> decltype(m_gamehandler)&
		{return m_gamehandler;}

		camera& editarea_camera() noexcept
		{return m_editarea_camera;}

		camera& itembar_camera() noexcept
		{return m_itembar_camera;}

		camera& settingsbar_camera() noexcept
		{return m_settingsbar_camera;}

	private:
		void init()
		{
			// change mousetexture on itembar-item click
			m_itembar.on_item_click =
			[this](ui::base_btn_ptr& b)
			{
				m_mouse.set_texture(b->get_texture());
				m_mouse.deactivate_selection();
				m_mouse.set_mouse_visible(true);
			};

			// init mouse texture
			m_itembar.deselect_all();

			this->init_input();
			this->init_cameras();
		}

		void init_input()
		{
			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos){this->on_mouse_left(pos);}, btn::Left);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos){this->on_mouse_right(pos);}, btn::Right);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(!is_key_pressed(key::LShift))
					m_editarea_camera.move({settings::get_editor_scroll_step(), 0.f});
			}, wheel::down);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(!is_key_pressed(key::LShift))
					if(m_editarea_camera.get_center().x >= m_editarea_camera.get_startcenter().x)
						m_editarea_camera.move({-settings::get_editor_scroll_step(), 0.f});
			}, wheel::up);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(is_key_pressed(key::LShift))
					m_editarea_camera.zoom(0.9);
			}, wheel::up);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(is_key_pressed(key::LShift))
					m_editarea_camera.zoom(1.1);
			}, wheel::down);
		}

		void init_cameras() noexcept
		{
			auto window_size(settings::get_window_size<vec2f>());
			auto& itembar_size(m_itembar.get_size());
			auto& settingsbar_size(m_settingsbar.get_size());

			auto itembar_top((window_size.y - itembar_size.y) / window_size.y);
			auto itembar_height(itembar_size.y / window_size.y);
			auto editarea_height((window_size.y - itembar_size.y) / window_size.y);

			sf::View editarea_view{vec2f{window_size.x, window_size.y - itembar_size.y} / 2.f, {window_size.x, window_size.y - itembar_size.y}};
			editarea_view.setViewport({0.f, 0.f, 1.f ,editarea_height});
			m_editarea_camera.set_view(editarea_view);

			sf::View itembar_view{vec2f{window_size.x, itembar_size.y} / 2.f, {window_size.x, itembar_size.y}};
			itembar_view.setViewport({0.f, itembar_top, 1.f, itembar_height});
			m_itembar_camera.set_view(itembar_view);

			sf::View settingsbar_view{vec2f{settingsbar_size.x, window_size.y} / 2.f, {settingsbar_size.x, window_size.y}};
			settingsbar_view.setViewport({(window_size.x - settingsbar_size.x) / window_size.x, 0.f, settingsbar_size.x / window_size.x, 1.f});
			m_settingsbar_camera.set_view(settingsbar_view);
		}

		void on_mouse_left(const vec2f&)
		{
			// check the itembar and settingsbar bounds
			auto itembar_mouse_bounds(bounds_from_vec(m_itembar_camera.get_mapped_mousepos()));
			auto settingsbar_mouse_bounds(bounds_from_vec(m_settingsbar_camera.get_mapped_mousepos()));
			if(itembar_mouse_bounds.intersects(m_itembar.get_bounds()) ||
			   settingsbar_mouse_bounds.intersects(m_settingsbar.get_bounds()))
				return;

			m_editarea_camera.activate();

			if(m_mouse.is_selection_visible())
			{
				auto& selected(m_mouse.get_selected());
				if(selected.size() == 0)
				{
					auto bounds(m_mouse.get_selectionshape_bounds());
					this->delete_editor_entity({bounds.left, bounds.top}, {bounds.width, bounds.height});
				}

				for(auto& a : selected)
					if(!m_gameworld.get_entityhandler().exists_entity_at(a.pos()))
						this->create_editor_entity(a.pos(), a.get_texture(), a.get_figure());
			}
			else if(m_mouse.is_mouse_visible())
			{
				float f{48.f};
				vec2f new_pos{round_to(m_editarea_camera.get_mapped_mousepos().x, f), round_to(m_editarea_camera.get_mapped_mousepos().y, f)};

				// set entity at pos
				if(m_mouse.get_texture() && !m_gameworld.get_entityhandler().exists_entity_at(new_pos))
					this->create_editor_entity(new_pos, m_mouse.get_texture(), m_itembar.get_current_figure());
			}
			else
				m_mouse.selection_start();
		}

		void on_mouse_right(const vec2f&)
		{
			m_itembar.deselect_all();
			m_mouse.clear();
			this->delete_editor_entity(m_editarea_camera.get_mapped_mousepos());
		}

		auto create_editor_entity(const vec2f& pos, const sf::Texture* tx, entity_figure f)
		-> decltype(m_gameworld.template create_entity<editor_entity>(pos))
		{
			auto ptr(m_gameworld.template create_entity<editor_entity>(pos));
			ptr->set_texture(tx);
			ptr->set_figure(f);
			return ptr;
		}

		void delete_editor_entity(const vec2f& pos, const vec2f& size = {1.f, 1.f})
		{
			auto iters(m_entityhandler.get_entities_at(pos, size));
			m_entityhandler.delete_entities(iters);
		}

		template<typename Ent_Ptr>
		auto to_editor_entity(const Ent_Ptr& ptr)
		-> decltype(std::static_pointer_cast<editor_entity>(ptr))
		{return std::static_pointer_cast<editor_entity>(ptr);}

		bool check_level_name(const level_id& id) const noexcept
		{
			if(!id.empty())
				return true;
			m_gamehandler.get_popupmgr().template create_popup<popup_type::error>("Couldn't save level: " + mlk::lerr_i().error_str(errors::lv_bad_name));
			return false;
		}
	};
}

#endif // RJ_GAME_EDITOR_EDITOR_HPP
<commit_msg>editor: implemented the camera 'drag' better<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_EDITOR_HPP
#define RJ_GAME_EDITOR_EDITOR_HPP

#include "background_editor.hpp"
#include "editor_entity.hpp"
#include "itembar.hpp"
#include "mouse.hpp"
#include "settingsbar.hpp"
#include <rectojump/game/components/platform.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/game/world.hpp>

namespace rj
{
	template<typename Game_Handler, typename Game>
	class editor
	{
	public:
		using gh_type = Game_Handler;

	private:
		Game_Handler& m_gamehandler;
		Game& m_game;
		world<Game_Handler>& m_gameworld;
		entity_handler& m_entityhandler;
		level_manager& m_levelmgr;

		camera m_editarea_camera;
		camera m_itembar_camera;
		camera m_settingsbar_camera;

		editor_mouse<Game_Handler> m_mouse;
		background_editor<editor> m_background{*this};
		itembar<Game_Handler> m_itembar;
		settingsbar<editor> m_settingsbar;

	public:
		editor(Game_Handler& gh) :
			m_gamehandler{gh},
			m_game{gh.get_game()},
			m_gameworld{m_game.get_world()},
			m_entityhandler{m_gameworld.get_entityhandler()},
			m_levelmgr{gh.get_levelmgr()},
			m_editarea_camera{m_gamehandler.get_gamewindow()},
			m_itembar_camera{m_gamehandler.get_gamewindow()},
			m_settingsbar_camera{m_gamehandler.get_gamewindow()},
			m_mouse{gh},
			m_itembar{gh, {settings::get_window_size<vec2f>().x, 100.f}},
			m_settingsbar{*this, {300.f, settings::get_window_size<vec2f>().y - m_itembar.get_size().y}}
		{this->init();}

		void update(dur duration)
		{
			// editareacamera move
			if(is_btn_pressed(btn::Middle))
				m_editarea_camera.move(((get_lastmousepos() - get_mousepos()) / 4.f) * duration); // * duration ???

			// edit area
			m_editarea_camera.activate();
			m_mouse.update(duration);

			// itembar
			m_itembar_camera.activate();
			m_itembar.update(duration);

			// settingsbar
			m_settingsbar_camera.activate();
			m_settingsbar.update(duration);
		}

		void update_input()
		{
			m_settingsbar.update_input();
		}

		void render()
		{
			// edit area
			m_editarea_camera.activate();
			m_entityhandler.render();
			m_mouse.render();

			// itembar
			m_itembar_camera.activate();
			m_itembar.render();

			// settingsbar
			m_settingsbar_camera.activate();
			m_settingsbar.render();
		}

		void on_activate()
		{
			m_background.reset();
		}

		void handle_save(const level_id& level_name)
		{
			if(!this->check_level_name(level_name))
				return;

			// level background
			level_background lv_bg
			{
				m_settingsbar.get_tb_startcolor_text(),
				m_settingsbar.get_tb_endcolor_text(),
				mlk::stl_string::to_int<std::size_t>(m_settingsbar.get_tb_pointcount_text())
			};

			// level data
			level_data lv_data;
			for(auto& a : m_entityhandler)
			{
				auto ent(this->to_editor_entity(a));
				lv_data.add_entity(ent->get_figure(), entity_propertie::solid, ent->pos());
			}

			level_info lv_info{level_name, m_settingsbar.get_tb_lvcreator_text(), mlk::tm::time_str()};
			music_data lv_music{'M', 'U', 'S', 'I', 'C'};
			level_packer<packer_mode::pack> lv_packer{lv_music, lv_bg, lv_data, lv_info};

			m_levelmgr.save_level(lv_packer, level_name);
		}

		void handle_load(const level_id& level_name)
		{
			if(!this->check_level_name(level_name))
				return;

//			auto& lv(m_levelmgr.get_level(level_name));
//			m_gameworld.load_level(lv.entities);
		}

		void reset_zoom() noexcept
		{m_editarea_camera.reset_zoom();}

		auto get_gamehandler() noexcept
		-> decltype(m_gamehandler)&
		{return m_gamehandler;}

		camera& editarea_camera() noexcept
		{return m_editarea_camera;}

		camera& itembar_camera() noexcept
		{return m_itembar_camera;}

		camera& settingsbar_camera() noexcept
		{return m_settingsbar_camera;}

	private:
		void init()
		{
			// change mousetexture on itembar-item click
			m_itembar.on_item_click =
			[this](ui::base_btn_ptr& b)
			{
				m_mouse.set_texture(b->get_texture());
				m_mouse.deactivate_selection();
				m_mouse.set_mouse_visible(true);
			};

			// init mouse texture
			m_itembar.deselect_all();

			this->init_input();
			this->init_cameras();
		}

		void init_input()
		{
			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos){this->on_mouse_left(pos);}, btn::Left);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos){this->on_mouse_right(pos);}, btn::Right);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(!is_key_pressed(key::LShift))
					m_editarea_camera.move({settings::get_editor_scroll_step(), 0.f});
			}, wheel::down);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(!is_key_pressed(key::LShift))
					if(m_editarea_camera.get_center().x >= m_editarea_camera.get_startcenter().x)
						m_editarea_camera.move({-settings::get_editor_scroll_step(), 0.f});
			}, wheel::up);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(is_key_pressed(key::LShift))
					m_editarea_camera.zoom(0.9);
			}, wheel::up);

			m_gamehandler.template add_input<state::editor>(
			[this](const vec2f& pos)
			{
				if(is_key_pressed(key::LShift))
					m_editarea_camera.zoom(1.1);
			}, wheel::down);
		}

		void init_cameras() noexcept
		{
			auto window_size(settings::get_window_size<vec2f>());
			auto& itembar_size(m_itembar.get_size());
			auto& settingsbar_size(m_settingsbar.get_size());

			auto itembar_top((window_size.y - itembar_size.y) / window_size.y);
			auto itembar_height(itembar_size.y / window_size.y);
			auto editarea_height((window_size.y - itembar_size.y) / window_size.y);

			sf::View editarea_view{vec2f{window_size.x, window_size.y - itembar_size.y} / 2.f, {window_size.x, window_size.y - itembar_size.y}};
			editarea_view.setViewport({0.f, 0.f, 1.f ,editarea_height});
			m_editarea_camera.set_view(editarea_view);

			sf::View itembar_view{vec2f{window_size.x, itembar_size.y} / 2.f, {window_size.x, itembar_size.y}};
			itembar_view.setViewport({0.f, itembar_top, 1.f, itembar_height});
			m_itembar_camera.set_view(itembar_view);

			sf::View settingsbar_view{vec2f{settingsbar_size.x, window_size.y} / 2.f, {settingsbar_size.x, window_size.y}};
			settingsbar_view.setViewport({(window_size.x - settingsbar_size.x) / window_size.x, 0.f, settingsbar_size.x / window_size.x, 1.f});
			m_settingsbar_camera.set_view(settingsbar_view);
		}

		void on_mouse_left(const vec2f&)
		{
			// check the itembar and settingsbar bounds
			auto itembar_mouse_bounds(bounds_from_vec(m_itembar_camera.get_mapped_mousepos()));
			auto settingsbar_mouse_bounds(bounds_from_vec(m_settingsbar_camera.get_mapped_mousepos()));
			if(itembar_mouse_bounds.intersects(m_itembar.get_bounds()) ||
			   settingsbar_mouse_bounds.intersects(m_settingsbar.get_bounds()))
				return;

			m_editarea_camera.activate();

			if(m_mouse.is_selection_visible())
			{
				auto& selected(m_mouse.get_selected());
				if(selected.size() == 0)
				{
					auto bounds(m_mouse.get_selectionshape_bounds());
					this->delete_editor_entity({bounds.left, bounds.top}, {bounds.width, bounds.height});
				}

				for(auto& a : selected)
					if(!m_gameworld.get_entityhandler().exists_entity_at(a.pos()))
						this->create_editor_entity(a.pos(), a.get_texture(), a.get_figure());
			}
			else if(m_mouse.is_mouse_visible())
			{
				float f{48.f};
				vec2f new_pos{round_to(m_editarea_camera.get_mapped_mousepos().x, f), round_to(m_editarea_camera.get_mapped_mousepos().y, f)};

				// set entity at pos
				if(m_mouse.get_texture() && !m_gameworld.get_entityhandler().exists_entity_at(new_pos))
					this->create_editor_entity(new_pos, m_mouse.get_texture(), m_itembar.get_current_figure());
			}
			else
				m_mouse.selection_start();
		}

		void on_mouse_right(const vec2f&)
		{
			m_itembar.deselect_all();
			m_mouse.clear();
			this->delete_editor_entity(m_editarea_camera.get_mapped_mousepos());
		}

		auto create_editor_entity(const vec2f& pos, const sf::Texture* tx, entity_figure f)
		-> decltype(m_gameworld.template create_entity<editor_entity>(pos))
		{
			auto ptr(m_gameworld.template create_entity<editor_entity>(pos));
			ptr->set_texture(tx);
			ptr->set_figure(f);
			return ptr;
		}

		void delete_editor_entity(const vec2f& pos, const vec2f& size = {1.f, 1.f})
		{
			auto iters(m_entityhandler.get_entities_at(pos, size));
			m_entityhandler.delete_entities(iters);
		}

		template<typename Ent_Ptr>
		auto to_editor_entity(const Ent_Ptr& ptr)
		-> decltype(std::static_pointer_cast<editor_entity>(ptr))
		{return std::static_pointer_cast<editor_entity>(ptr);}

		bool check_level_name(const level_id& id) const noexcept
		{
			if(!id.empty())
				return true;
			m_gamehandler.get_popupmgr().template create_popup<popup_type::error>("Couldn't save level: " + mlk::lerr_i().error_str(errors::lv_bad_name));
			return false;
		}
	};
}

#endif // RJ_GAME_EDITOR_EDITOR_HPP
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_POPUP_MANAGER_HPP
#define RJ_GAME_POPUP_MANAGER_HPP

#include "popup.hpp"
#include <rectojump/shared/data_manager.hpp>

#include <mlk/containers/container_utl.h>

namespace rj
{
	template<typename Game_Handler>
	class popup_manager
	{
		game& m_game;
		sf::Font m_font;

		std::vector<popup> m_popups;

	public:
		popup_manager(Game_Handler& gh) :
			m_game{gh.get_game()},
			m_font{gh.get_datamgr().template get_as<sf::Font>("Fipps-Regular.otf")}
		{ }

		void update(dur duration)
		{
			for(auto& a : m_popups)
				a.update(duration);
			this->erase_destroyed();
		}

		void render()
		{
			for(auto& a : m_popups)
				a.render();
		}

		template<typename... Args>
		void create_popup(const std::string& text, const vec2f& pos = {settings::get_window_size<vec2f>().x / 2.f, settings::get_window_size<vec2f>().y - 100.f}, Args&&... args = {})
		{m_popups.emplace_back(&m_game, m_font, text, pos, std::forward<Args>(args)...);}

		std::size_t num_popups() const noexcept
		{return m_popups.size();}

	private:
		void erase_destroyed() noexcept
		{
			mlk::cnt::remove_all_if(
			[](const popup& p){return p.is_destroyed();}, m_popups);
		}
	};
}

#endif // RJ_GAME_POPUP_MANAGER_HPP
<commit_msg>added popup_creator<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_POPUP_MANAGER_HPP
#define RJ_GAME_POPUP_MANAGER_HPP

#include "popup.hpp"
#include <rectojump/shared/data_manager.hpp>

#include <mlk/containers/container_utl.h>

namespace rj
{
	enum class popup_type : char
	{normal, info, error};

	template<popup_type, typename>
	struct popup_creator;

	template<typename Game_Handler>
	class popup_manager
	{
		game& m_game;
		sf::Font m_font;

		std::vector<popup> m_popups;

	public:
		popup_manager(Game_Handler& gh) :
			m_game{gh.get_game()},
			m_font{gh.get_datamgr().template get_as<sf::Font>("Fipps-Regular.otf")}
		{ }

		void update(dur duration)
		{
			for(auto& a : m_popups)
				a.update(duration);
			this->erase_destroyed();
		}

		void render()
		{
			for(auto& a : m_popups)
				a.render();
		}

		template<popup_type type = popup_type::normal, typename... Args>
		void create_popup(const std::string& text, const vec2f& pos = {settings::get_window_size<vec2f>().x / 2.f, settings::get_window_size<vec2f>().y - 100.f}, Args&&... args = {})
		{popup_creator<type, Game_Handler>{*this, text, pos, std::forward<Args>(args)...};}

		template<typename... Args>
		void create_popup_impl(Args&&... args)
		{m_popups.emplace_back(&m_game, m_font, std::forward<Args>(args)...);}

		std::size_t num_popups() const noexcept
		{return m_popups.size();}

	private:
		void erase_destroyed() noexcept
		{
			mlk::cnt::remove_all_if(
			[](const popup& p){return p.is_destroyed();}, m_popups);
		}
	};

	template<popup_type type, typename Game_Handler>
	struct popup_creator
	{
		template<typename... Args>
		popup_creator(popup_manager<Game_Handler>& pm, Args&&... args)
		{pm.create_popup_impl(std::forward<Args>(args)...);}
	};

	template<typename Game_Handler>
	struct popup_creator<popup_type::info, Game_Handler>
	{
		popup_creator(popup_manager<Game_Handler>& pm, const std::string& text, const vec2f& pos)
		{pm.create_popup_impl(text, pos, 3000, to_rgb("#000375", 200), to_rgb("#000352"), to_rgb("#e3e3e3"));}
	};

	template<typename Game_Handler>
	struct popup_creator<popup_type::error, Game_Handler>
	{
		popup_creator(popup_manager<Game_Handler>& pm, const std::string& text, const vec2f& pos)
		{pm.create_popup_impl(text, pos, 3000, to_rgb("#820006", 200), to_rgb("#d80042"), to_rgb("#e3e3e3"));}
	};
}

#endif // RJ_GAME_POPUP_MANAGER_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_HPP

#include <cassert>
#include <memory>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>

#include "../config.hpp"
#include "../memory_input.hpp"
#include "../normal.hpp"
#include "../nothing.hpp"
#include "../parse.hpp"

#include "../analysis/counted.hpp"
#include "../analysis/generic.hpp"
#include "../internal/conditional.hpp"
#include "../internal/demangle.hpp"
#include "../internal/iterator.hpp"

namespace tao
{
   namespace TAO_PEGTL_NAMESPACE
   {
      namespace parse_tree
      {
         template< typename T >
         struct basic_node
         {
            using node_t = T;
            using children_t = std::vector< std::unique_ptr< node_t > >;
            children_t children;

            const std::type_info* id = nullptr;
            std::string source;

            TAO_PEGTL_NAMESPACE::internal::iterator m_begin;
            TAO_PEGTL_NAMESPACE::internal::iterator m_end;

            // each node will be default constructed
            basic_node() = default;

            // no copy/move is necessary
            // (nodes are always owned/handled by a std::unique_ptr)
            basic_node( const basic_node& ) = delete;
            basic_node( basic_node&& ) = delete;

            ~basic_node() = default;

            // no assignment either
            basic_node& operator=( const basic_node& ) = delete;
            basic_node& operator=( basic_node&& ) = delete;

            bool is_root() const noexcept
            {
               return id == nullptr;
            }

            template< typename U >
            bool is() const noexcept
            {
               return id == &typeid( U );
            }

            std::string name() const
            {
               assert( !is_root() );
               return TAO_PEGTL_NAMESPACE::internal::demangle( id->name() );
            }

            position begin() const
            {
               return position( m_begin, source );
            }

            position end() const
            {
               return position( m_end, source );
            }

            bool has_content() const noexcept
            {
               return m_end.data != nullptr;
            }

            std::string content() const
            {
               assert( has_content() );
               return std::string( m_begin.data, m_end.data );
            }

            template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf >
            memory_input< P, Eol > as_memory_input() const
            {
               assert( has_content() );
               return memory_input< P, Eol >( m_begin.data, m_end.data - m_begin.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line );
            }

            template< typename... States >
            void remove_content( States&&... /*unused*/ ) noexcept
            {
               m_end.reset();
            }

            // all non-root nodes are initialized by calling this method
            template< typename Rule, typename Input, typename... States >
            void start( const Input& in, States&&... /*unused*/ )
            {
               id = &typeid( Rule );
               source = in.source();
               m_begin = in.iterator();
            }

            // if parsing of the rule succeeded, this method is called
            template< typename Rule, typename Input, typename... States >
            void success( const Input& in, States&&... /*unused*/ ) noexcept
            {
               m_end = in.iterator();
            }

            // if parsing of the rule failed, this method is called
            template< typename Rule, typename Input, typename... States >
            void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept
            {
            }

            // if parsing succeeded and the (optional) transform call
            // did not discard the node, it is appended to its parent.
            // note that "child" is the node whose Rule just succeeded
            // and "*this" is the parent where the node should be appended.
            template< typename... States >
            void emplace_back( std::unique_ptr< node_t > child, States&&... /*unused*/ )
            {
               assert( child );
               children.emplace_back( std::move( child ) );
            }
         };

         struct node
            : basic_node< node >
         {
         };

         namespace internal
         {
            template< typename Node >
            struct state
            {
               std::vector< std::unique_ptr< Node > > stack;

               state()
               {
                  emplace_back();
               }

               void emplace_back()
               {
                  stack.emplace_back( std::unique_ptr< Node >( new Node ) );  // NOLINT: std::make_unique requires C++14
               }

               std::unique_ptr< Node >& back() noexcept
               {
                  return stack.back();
               }

               void pop_back() noexcept
               {
                  return stack.pop_back();
               }
            };

            template< typename Selector, typename... States >
            void transform( States&&... /*unused*/ ) noexcept
            {
            }

            template< typename Selector, typename Node, typename... States >
            auto transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) )
               -> decltype( Selector::transform( n, st... ), void() )
            {
               Selector::transform( n, st... );
            }

            template< unsigned Level, typename Analyse, template< typename... > class Selector >
            struct is_leaf
               : std::false_type
            {
            };

            template< analysis::rule_type Type, template< typename... > class Selector >
            struct is_leaf< 0, analysis::generic< Type >, Selector >
               : std::true_type
            {
            };

            template< analysis::rule_type Type, unsigned Count, template< typename... > class Selector >
            struct is_leaf< 0, analysis::counted< Type, Count >, Selector >
               : std::true_type
            {
            };

            template< analysis::rule_type Type, typename... Rules, template< typename... > class Selector >
            struct is_leaf< 0, analysis::generic< Type, Rules... >, Selector >
               : std::false_type
            {
            };

            template< analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector >
            struct is_leaf< 0, analysis::counted< Type, Count, Rules... >, Selector >
               : std::false_type
            {
            };

            template< bool... >
            struct bool_sequence;

            template< bool... Bs >
            using is_all = std::is_same< bool_sequence< Bs..., true >, bool_sequence< true, Bs... > >;

            template< unsigned Level, typename Rule, template< typename... > class Selector >
            using is_unselected_leaf = std::integral_constant< bool, !Selector< Rule >::value && is_leaf< Level, typename Rule::analyze_t, Selector >::value >;

            template< unsigned Level, analysis::rule_type Type, typename... Rules, template< typename... > class Selector >
            struct is_leaf< Level, analysis::generic< Type, Rules... >, Selector >
               : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... >
            {
            };

            template< unsigned Level, analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector >
            struct is_leaf< Level, analysis::counted< Type, Count, Rules... >, Selector >
               : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... >
            {
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            struct make_control
            {
               template< typename Rule, bool, bool >
               struct control;

               template< typename Rule >
               using type = control< Rule, Selector< Rule >::value, is_leaf< 8, typename Rule::analyze_t, Selector >::value >;
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule >
            struct make_control< Node, Selector, Control >::control< Rule, false, true >
               : Control< Rule >
            {
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule >
            struct make_control< Node, Selector, Control >::control< Rule, false, false >
               : Control< Rule >
            {
               template< typename Input, typename... States >
               static void start( const Input& in, States&&... st )
               {
                  Control< Rule >::start( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.emplace_back();
               }

               template< typename Input, typename... States >
               static void success( const Input& in, States&&... st )
               {
                  Control< Rule >::success( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  auto n = std::move( state.back() );
                  state.pop_back();
                  for( auto& c : n->children ) {
                     state.back()->children.emplace_back( std::move( c ) );
                  }
               }

               template< typename Input, typename... States >
               static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) )
               {
                  Control< Rule >::failure( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.pop_back();
               }
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule, bool B >
            struct make_control< Node, Selector, Control >::control< Rule, true, B >
               : Control< Rule >
            {
               template< typename Input, typename... States >
               static void start( const Input& in, States&&... st )
               {
                  Control< Rule >::start( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.emplace_back();
                  state.back()->template start< Rule >( in, st... );
               }

               template< typename Input, typename... States >
               static void success( const Input& in, States&&... st )
               {
                  Control< Rule >::success( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  auto n = std::move( state.back() );
                  state.pop_back();
                  n->template success< Rule >( in, st... );
                  transform< Selector< Rule > >( n, st... );
                  if( n ) {
                     state.back()->emplace_back( std::move( n ), st... );
                  }
               }

               template< typename Input, typename... States >
               static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< node& >().template failure< Rule >( in, st... ) ) )
               {
                  Control< Rule >::failure( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.back()->template failure< Rule >( in, st... );
                  state.pop_back();
               }
            };

            template< typename >
            struct element
            {
            };

            template< typename >
            struct store_all : std::true_type
            {
            };

         }  // namespace internal

         using store_content = std::true_type;

         // some nodes don't need to store their content
         struct remove_content : std::true_type
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) )
            {
               n->remove_content( st... );
            }
         };

         // if a node has only one child, replace the node with its child, otherwise apply B
         template< typename Base >
         struct fold_one_or : Base
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), Base::transform( n, st... ) ) )
            {
               if( n->children.size() == 1 ) {
                  n = std::move( n->children.front() );
               }
               else {
                  Base::transform( n, st... );
               }
            }
         };

         // if a node has no children, discard the node, otherwise apply B
         template< typename Base >
         struct discard_empty_or : Base
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), Base::transform( n, st... ) ) )
            {
               if( n->children.empty() ) {
                  n.reset();
               }
               else {
                  Base::transform( n, st... );
               }
            }
         };

         using fold_one = fold_one_or< remove_content >;
         using discard_empty = discard_empty_or< remove_content >;

         template< typename Rule, typename... Collections >
         struct selector : std::false_type
         {
         };

         // TODO: Implement in a non-recursive way
         // TODO: Check for multiple matches (currently: first match wins)
         template< typename Rule, typename Collection, typename... Collections >
         struct selector< Rule, Collection, Collections... >
            : TAO_PEGTL_NAMESPACE::internal::conditional< Collection::template contains< Rule >::value >::template type< typename Collection::type, selector< Rule, Collections... > >
         {
         };

         template< typename Base >
         struct apply
         {
            template< typename... Rules >
            struct to
               : internal::element< Rules >...
            {
               using type = Base;

               template< typename Rule >
               using contains = std::is_base_of< internal::element< Rule >, to >;
            };
         };

         using apply_store_content = apply< store_content >;
         using apply_remove_content = apply< remove_content >;
         using apply_fold_one = apply< fold_one >;
         using apply_discard_empty = apply< discard_empty >;

         template< typename Rule,
                   typename Node,
                   template< typename... > class Selector = internal::store_all,
                   template< typename... > class Action = nothing,
                   template< typename... > class Control = normal,
                   typename Input,
                   typename... States >
         std::unique_ptr< Node > parse( Input&& in, States&&... st )
         {
            internal::state< Node > state;
            if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) {
               return nullptr;
            }
            assert( state.stack.size() == 1 );
            return std::move( state.back() );
         }

         template< typename Rule,
                   template< typename... > class Selector = internal::store_all,
                   template< typename... > class Action = nothing,
                   template< typename... > class Control = normal,
                   typename Input,
                   typename... States >
         std::unique_ptr< node > parse( Input&& in, States&&... st )
         {
            return parse< Rule, node, Selector, Action, Control >( in, st... );
         }

      }  // namespace parse_tree

   }  // namespace TAO_PEGTL_NAMESPACE

}  // namespace tao

#endif
<commit_msg>Fix as_memory_input()<commit_after>// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_HPP

#include <cassert>
#include <memory>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>

#include "../config.hpp"
#include "../memory_input.hpp"
#include "../normal.hpp"
#include "../nothing.hpp"
#include "../parse.hpp"

#include "../analysis/counted.hpp"
#include "../analysis/generic.hpp"
#include "../internal/conditional.hpp"
#include "../internal/demangle.hpp"
#include "../internal/iterator.hpp"

namespace tao
{
   namespace TAO_PEGTL_NAMESPACE
   {
      namespace parse_tree
      {
         template< typename T >
         struct basic_node
         {
            using node_t = T;
            using children_t = std::vector< std::unique_ptr< node_t > >;
            children_t children;

            const std::type_info* id = nullptr;
            std::string source;

            TAO_PEGTL_NAMESPACE::internal::iterator m_begin;
            TAO_PEGTL_NAMESPACE::internal::iterator m_end;

            // each node will be default constructed
            basic_node() = default;

            // no copy/move is necessary
            // (nodes are always owned/handled by a std::unique_ptr)
            basic_node( const basic_node& ) = delete;
            basic_node( basic_node&& ) = delete;

            ~basic_node() = default;

            // no assignment either
            basic_node& operator=( const basic_node& ) = delete;
            basic_node& operator=( basic_node&& ) = delete;

            bool is_root() const noexcept
            {
               return id == nullptr;
            }

            template< typename U >
            bool is() const noexcept
            {
               return id == &typeid( U );
            }

            std::string name() const
            {
               assert( !is_root() );
               return TAO_PEGTL_NAMESPACE::internal::demangle( id->name() );
            }

            position begin() const
            {
               return position( m_begin, source );
            }

            position end() const
            {
               return position( m_end, source );
            }

            bool has_content() const noexcept
            {
               return m_end.data != nullptr;
            }

            std::string content() const
            {
               assert( has_content() );
               return std::string( m_begin.data, m_end.data );
            }

            template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf >
            memory_input< P, Eol > as_memory_input() const
            {
               assert( has_content() );
               return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line };
            }

            template< typename... States >
            void remove_content( States&&... /*unused*/ ) noexcept
            {
               m_end.reset();
            }

            // all non-root nodes are initialized by calling this method
            template< typename Rule, typename Input, typename... States >
            void start( const Input& in, States&&... /*unused*/ )
            {
               id = &typeid( Rule );
               source = in.source();
               m_begin = in.iterator();
            }

            // if parsing of the rule succeeded, this method is called
            template< typename Rule, typename Input, typename... States >
            void success( const Input& in, States&&... /*unused*/ ) noexcept
            {
               m_end = in.iterator();
            }

            // if parsing of the rule failed, this method is called
            template< typename Rule, typename Input, typename... States >
            void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept
            {
            }

            // if parsing succeeded and the (optional) transform call
            // did not discard the node, it is appended to its parent.
            // note that "child" is the node whose Rule just succeeded
            // and "*this" is the parent where the node should be appended.
            template< typename... States >
            void emplace_back( std::unique_ptr< node_t > child, States&&... /*unused*/ )
            {
               assert( child );
               children.emplace_back( std::move( child ) );
            }
         };

         struct node
            : basic_node< node >
         {
         };

         namespace internal
         {
            template< typename Node >
            struct state
            {
               std::vector< std::unique_ptr< Node > > stack;

               state()
               {
                  emplace_back();
               }

               void emplace_back()
               {
                  stack.emplace_back( std::unique_ptr< Node >( new Node ) );  // NOLINT: std::make_unique requires C++14
               }

               std::unique_ptr< Node >& back() noexcept
               {
                  return stack.back();
               }

               void pop_back() noexcept
               {
                  return stack.pop_back();
               }
            };

            template< typename Selector, typename... States >
            void transform( States&&... /*unused*/ ) noexcept
            {
            }

            template< typename Selector, typename Node, typename... States >
            auto transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) )
               -> decltype( Selector::transform( n, st... ), void() )
            {
               Selector::transform( n, st... );
            }

            template< unsigned Level, typename Analyse, template< typename... > class Selector >
            struct is_leaf
               : std::false_type
            {
            };

            template< analysis::rule_type Type, template< typename... > class Selector >
            struct is_leaf< 0, analysis::generic< Type >, Selector >
               : std::true_type
            {
            };

            template< analysis::rule_type Type, unsigned Count, template< typename... > class Selector >
            struct is_leaf< 0, analysis::counted< Type, Count >, Selector >
               : std::true_type
            {
            };

            template< analysis::rule_type Type, typename... Rules, template< typename... > class Selector >
            struct is_leaf< 0, analysis::generic< Type, Rules... >, Selector >
               : std::false_type
            {
            };

            template< analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector >
            struct is_leaf< 0, analysis::counted< Type, Count, Rules... >, Selector >
               : std::false_type
            {
            };

            template< bool... >
            struct bool_sequence;

            template< bool... Bs >
            using is_all = std::is_same< bool_sequence< Bs..., true >, bool_sequence< true, Bs... > >;

            template< unsigned Level, typename Rule, template< typename... > class Selector >
            using is_unselected_leaf = std::integral_constant< bool, !Selector< Rule >::value && is_leaf< Level, typename Rule::analyze_t, Selector >::value >;

            template< unsigned Level, analysis::rule_type Type, typename... Rules, template< typename... > class Selector >
            struct is_leaf< Level, analysis::generic< Type, Rules... >, Selector >
               : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... >
            {
            };

            template< unsigned Level, analysis::rule_type Type, unsigned Count, typename... Rules, template< typename... > class Selector >
            struct is_leaf< Level, analysis::counted< Type, Count, Rules... >, Selector >
               : is_all< is_unselected_leaf< Level - 1, Rules, Selector >::value... >
            {
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            struct make_control
            {
               template< typename Rule, bool, bool >
               struct control;

               template< typename Rule >
               using type = control< Rule, Selector< Rule >::value, is_leaf< 8, typename Rule::analyze_t, Selector >::value >;
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule >
            struct make_control< Node, Selector, Control >::control< Rule, false, true >
               : Control< Rule >
            {
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule >
            struct make_control< Node, Selector, Control >::control< Rule, false, false >
               : Control< Rule >
            {
               template< typename Input, typename... States >
               static void start( const Input& in, States&&... st )
               {
                  Control< Rule >::start( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.emplace_back();
               }

               template< typename Input, typename... States >
               static void success( const Input& in, States&&... st )
               {
                  Control< Rule >::success( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  auto n = std::move( state.back() );
                  state.pop_back();
                  for( auto& c : n->children ) {
                     state.back()->children.emplace_back( std::move( c ) );
                  }
               }

               template< typename Input, typename... States >
               static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) )
               {
                  Control< Rule >::failure( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.pop_back();
               }
            };

            template< typename Node, template< typename... > class Selector, template< typename... > class Control >
            template< typename Rule, bool B >
            struct make_control< Node, Selector, Control >::control< Rule, true, B >
               : Control< Rule >
            {
               template< typename Input, typename... States >
               static void start( const Input& in, States&&... st )
               {
                  Control< Rule >::start( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.emplace_back();
                  state.back()->template start< Rule >( in, st... );
               }

               template< typename Input, typename... States >
               static void success( const Input& in, States&&... st )
               {
                  Control< Rule >::success( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  auto n = std::move( state.back() );
                  state.pop_back();
                  n->template success< Rule >( in, st... );
                  transform< Selector< Rule > >( n, st... );
                  if( n ) {
                     state.back()->emplace_back( std::move( n ), st... );
                  }
               }

               template< typename Input, typename... States >
               static void failure( const Input& in, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< node& >().template failure< Rule >( in, st... ) ) )
               {
                  Control< Rule >::failure( in, st... );
                  auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
                  state.back()->template failure< Rule >( in, st... );
                  state.pop_back();
               }
            };

            template< typename >
            struct element
            {
            };

            template< typename >
            struct store_all : std::true_type
            {
            };

         }  // namespace internal

         using store_content = std::true_type;

         // some nodes don't need to store their content
         struct remove_content : std::true_type
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) )
            {
               n->remove_content( st... );
            }
         };

         // if a node has only one child, replace the node with its child, otherwise apply B
         template< typename Base >
         struct fold_one_or : Base
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), Base::transform( n, st... ) ) )
            {
               if( n->children.size() == 1 ) {
                  n = std::move( n->children.front() );
               }
               else {
                  Base::transform( n, st... );
               }
            }
         };

         // if a node has no children, discard the node, otherwise apply B
         template< typename Base >
         struct discard_empty_or : Base
         {
            template< typename Node, typename... States >
            static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), Base::transform( n, st... ) ) )
            {
               if( n->children.empty() ) {
                  n.reset();
               }
               else {
                  Base::transform( n, st... );
               }
            }
         };

         using fold_one = fold_one_or< remove_content >;
         using discard_empty = discard_empty_or< remove_content >;

         template< typename Rule, typename... Collections >
         struct selector : std::false_type
         {
         };

         // TODO: Implement in a non-recursive way
         // TODO: Check for multiple matches (currently: first match wins)
         template< typename Rule, typename Collection, typename... Collections >
         struct selector< Rule, Collection, Collections... >
            : TAO_PEGTL_NAMESPACE::internal::conditional< Collection::template contains< Rule >::value >::template type< typename Collection::type, selector< Rule, Collections... > >
         {
         };

         template< typename Base >
         struct apply
         {
            template< typename... Rules >
            struct to
               : internal::element< Rules >...
            {
               using type = Base;

               template< typename Rule >
               using contains = std::is_base_of< internal::element< Rule >, to >;
            };
         };

         using apply_store_content = apply< store_content >;
         using apply_remove_content = apply< remove_content >;
         using apply_fold_one = apply< fold_one >;
         using apply_discard_empty = apply< discard_empty >;

         template< typename Rule,
                   typename Node,
                   template< typename... > class Selector = internal::store_all,
                   template< typename... > class Action = nothing,
                   template< typename... > class Control = normal,
                   typename Input,
                   typename... States >
         std::unique_ptr< Node > parse( Input&& in, States&&... st )
         {
            internal::state< Node > state;
            if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) {
               return nullptr;
            }
            assert( state.stack.size() == 1 );
            return std::move( state.back() );
         }

         template< typename Rule,
                   template< typename... > class Selector = internal::store_all,
                   template< typename... > class Action = nothing,
                   template< typename... > class Control = normal,
                   typename Input,
                   typename... States >
         std::unique_ptr< node > parse( Input&& in, States&&... st )
         {
            return parse< Rule, node, Selector, Action, Control >( in, st... );
         }

      }  // namespace parse_tree

   }  // namespace TAO_PEGTL_NAMESPACE

}  // namespace tao

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 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_GEOMETRY_TO_PATH_HPP
#define MAPNIK_GEOMETRY_TO_PATH_HPP

#include <mapnik/geometry.hpp>
#include <mapnik/path.hpp>

namespace mapnik { namespace geometry { namespace detail {

//template <typename Transformer>
struct geometry_to_path
{
    geometry_to_path(path_type & p)
        : p_(p) {}

    void operator() (geometry_collection const& collection) const
    {
        // fixme
    }

    void operator() (geometry const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    // point
    void operator() (point const& pt) const
    {
        //point pt_new;
        //Transformer::apply(pt, pt_new);
        p_.move_to(pt.x, pt.y);
    }

    // line_string
    void operator() (line_string const& line) const
    {
        bool first = true;
        for (auto const& pt : line)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
    }

    // polygon
    void operator() (polygon const& poly) const
    {
        // exterior
        bool first = true;
        for (auto const& pt : poly.exterior_ring)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
        // interior
        for (auto const& ring : poly.interior_rings)
        {
            first = true;
            for (auto const& pt : ring)
            {
                //point pt_new;
                //Transformer::apply(pt, pt_new);
                if (first) { p_.move_to(pt.x, pt.y); first=false;}
                else p_.line_to(pt.x, pt.y);
            }
        }
    }

    template <typename T>
    void operator() (T const& geom) const
    {
        // no-op
    }

    path_type & p_;

};
} // ns detail

template <typename T>
void to_path(T const& geom, path_type & p)
{
    detail::geometry_to_path func(p);
    func(geom);
}

}}

#endif // MAPNIK_GEOMETRY_TO_PATH_HPP
<commit_msg>support all geomtry types<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 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_GEOMETRY_TO_PATH_HPP
#define MAPNIK_GEOMETRY_TO_PATH_HPP

#include <mapnik/geometry.hpp>
#include <mapnik/path.hpp>

namespace mapnik { namespace geometry { namespace detail {

//template <typename Transformer>
struct geometry_to_path
{
    geometry_to_path(path_type & p)
        : p_(p) {}

    void operator() (geometry const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    // point
    void operator() (point const& pt) const
    {
        //point pt_new;
        //Transformer::apply(pt, pt_new);
        p_.move_to(pt.x, pt.y);
    }

    // line_string
    void operator() (line_string const& line) const
    {
        bool first = true;
        for (auto const& pt : line)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
    }

    // polygon
    void operator() (polygon const& poly) const
    {
        // exterior
        bool first = true;
        for (auto const& pt : poly.exterior_ring)
        {
            //point pt_new;
            //Transformer::apply(pt, pt_new);
            if (first) { p_.move_to(pt.x, pt.y); first=false;}
            else p_.line_to(pt.x, pt.y);
        }
        // interior
        for (auto const& ring : poly.interior_rings)
        {
            first = true;
            for (auto const& pt : ring)
            {
                //point pt_new;
                //Transformer::apply(pt, pt_new);
                if (first) { p_.move_to(pt.x, pt.y); first=false;}
                else p_.line_to(pt.x, pt.y);
            }
        }
    }

    // multi point
    void operator() (multi_point const& multi_pt) const
    {
        for (auto const& pt : multi_pt)
        {
            (*this)(pt);
        }
    }
    // multi_line_string
    void operator() (multi_line_string const& multi_line) const
    {
        for (auto const& line : multi_line)
        {
            (*this)(line);
        }
    }

    // multi_polygon
    void operator() (multi_polygon const& multi_poly) const
    {
        for (auto const& poly : multi_poly)
        {
            (*this)(poly);
        }
    }

    void operator() (geometry_collection const& collection) const
    {
        for (auto const& geom :  collection)
        {
            (*this)(geom);
        }
    }

    path_type & p_;

};
} // ns detail

template <typename T>
void to_path(T const& geom, path_type & p)
{
    detail::geometry_to_path func(p);
    func(geom);
}

}}

#endif // MAPNIK_GEOMETRY_TO_PATH_HPP
<|endoftext|>