<commit_before>///
/// @file   primecount.cpp
/// @brief  primecount C++ API
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primecount.hpp>
#include <calculator.hpp>
#include <int128.hpp>
#include <pmath.hpp>

#include <algorithm>
#include <ctime>
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include <stdint.h>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;

namespace {

int threads_ = primecount::MAX_THREADS;

double alpha_ = -1;

}

namespace primecount {

int64_t pi(int64_t x)
{
  return pi(x, threads_);
}

int64_t pi(int64_t x, int threads)
{
  return pi_deleglise_rivat(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi(int128_t x)
{
  return pi(x, threads_);
}

int128_t pi(int128_t x, int threads)
{
  return pi_deleglise_rivat(x, threads);
}

#endif

/// Alias for the fastest prime counting function in primecount.
/// @param x  integer or arithmetic expression like "10^12".
/// @pre   x  <= get_max_x().
///
string pi(const string& x)
{
  return pi(x, threads_);
}

/// Alias for the fastest prime counting function in primecount.
/// @param x  integer or arithmetic expression like "10^12".
/// @pre   x  <= get_max_x().
///
string pi(const string& x, int threads)
{
  maxint_t n = to_maxint(x);
  maxint_t pin = pi(n, threads);
  ostringstream oss;
  oss << pin;
  return oss.str();
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x)
{
  return pi_deleglise_rivat(x, threads_);
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x, int threads)
{
  return pi_deleglise_rivat_parallel2(x, threads);
}

#ifdef HAVE_INT128_T

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat(int128_t x)
{
  return pi_deleglise_rivat(x, threads_);
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi_deleglise_rivat((int64_t) x, threads);

  return pi_deleglise_rivat_parallel3(x, threads);
}

#endif

/// Calculate the number of primes below x using Legendre's formula.
/// Run time: O(x) operations, O(x^(1/2)) space.
///
int64_t pi_legendre(int64_t x)
{
  return pi_legendre(x, threads_);
}

/// Calculate the number of primes below x using Lehmer's formula.
/// Run time: O(x/(log x)^4) operations, O(x^(1/2)) space.
///
int64_t pi_lehmer(int64_t x)
{
  return pi_lehmer(x, threads_);
}

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x)
{
  return pi_lmo(x, threads_);
}

/// Parallel implementation of the Lagarias-Miller-Odlyzko
/// prime counting algorithm using OpenMP.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x, int threads)
{
  if (threads <= 1)
    return pi_lmo5(x);

  return pi_lmo_parallel3(x, threads);
}

/// Calculate the number of primes below x using Meissel's formula.
/// Run time: O(x/(log x)^3) operations, O(x^(1/2) / log x) space.
///
int64_t pi_meissel(int64_t x)
{
  return pi_meissel(x, threads_);
}

/// Calculate the number of primes below x using an optimized
/// segmented sieve of Eratosthenes implementation.
/// Run time: O(x log log x) operations, O(x^(1/2)) space.
///
int64_t pi_primesieve(int64_t x)
{
  return pi_primesieve(x, threads_);
}

/// Calculate the nth prime using a combination of an efficient prime
/// counting function implementation and the sieve of Eratosthenes.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/2)) space.
///
int64_t nth_prime(int64_t n)
{
  return nth_prime(n, threads_);
}

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a)
{
  return phi(x, a, threads_);
}

/// Returns the largest integer that can be used with
/// pi(string x). The return type is a string as max may be a
/// 128-bit integer which is not supported by all compilers.
///
string get_max_x(double alpha)
{
  ostringstream oss;

#ifdef HAVE_INT128_T
  // primecount is limited by:
  // z < 2^62, with z = x^(2/3) / alpha
  // x^(2/3) / alpha < 2^62
  // x < (2^62 * alpha)^(3/2)

  // safety buffer: use 61 instead of 62
  double max_x = pow(pow(2.0, 61.0) * alpha, 3.0 / 2.0);
  oss << (int128_t) max_x;
#else
  unused_param(alpha);
  oss << numeric_limits<int64_t>::max();
#endif

  return oss.str();
}

/// Get the wall time in seconds.
double get_wtime()
{
#ifdef _OPENMP
  return omp_get_wtime();
#else
  return static_cast<double>(std::clock()) / CLOCKS_PER_SEC;
#endif
}

int validate_threads(int threads)
{
#ifdef _OPENMP
  if (threads == MAX_THREADS)
    threads = omp_get_max_threads();
  return in_between(1, threads, omp_get_max_threads());
#else
  threads = 1;
  return threads;
#endif
}

int validate_threads(int threads, int64_t sieve_limit, int64_t thread_threshold)
{
  threads = validate_threads(threads);
  thread_threshold = max((int64_t) 1, thread_threshold);
  threads = (int) min((int64_t) threads, sieve_limit / thread_threshold);
  threads = max(1, threads);
  return threads;
}

void set_alpha(double alpha)
{
  alpha_ = alpha;
}

double get_alpha()
{
  return alpha_;
}

double get_alpha(maxint_t x, int64_t y)
{
  // y = x13 * alpha, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Calculate the Lagarias-Miller-Odlyzko alpha tuning factor.
/// alpha = a log(x)^2 + b log(x) + c
/// a, b and c are constants that should be determined empirically.
/// @see ../doc/alpha-factor-tuning.pdf
///
double get_alpha_lmo(maxint_t x)
{
  double alpha = get_alpha();

  if (alpha < 1)
  {
    double a = 0.00156512;
    double b = -0.0261411;
    double c = 0.990948;
    double logx = log((double) x);

    alpha = a * pow(logx, 2) + b * logx + c;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// Calculate the Deleglise-Rivat alpha tuning factor.
/// alpha = a log(x)^3 + b log(x)^2 + c log(x) + d
/// a, b, c and d are constants that should be determined empirically.
/// @see ../doc/alpha-factor-tuning.pdf
///
double get_alpha_deleglise_rivat(maxint_t x)
{
  double alpha = get_alpha();

  if (alpha < 1)
  {
    double a = 0.0017154;
    double b = -0.0508992;
    double c = 0.483613;
    double d = 0.0672202;
    double logx = log((double) x);

    alpha = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
  }

  return in_between(1, alpha, iroot<6>(x));
}

void set_num_threads(int threads)
{
  threads_ = validate_threads(threads);
}

int get_num_threads()
{
  return validate_threads(threads_);
}

maxint_t to_maxint(const string& expr)
{
  maxint_t n = calculator::eval<maxint_t>(expr);
  return n;
}

} // namespace primecount
<commit_msg>alpha factor tuning<commit_after>///
/// @file   primecount.cpp
/// @brief  primecount C++ API
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primecount.hpp>
#include <calculator.hpp>
#include <int128.hpp>
#include <pmath.hpp>

#include <algorithm>
#include <ctime>
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include <stdint.h>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;

namespace {

int threads_ = primecount::MAX_THREADS;

double alpha_ = -1;

}

namespace primecount {

int64_t pi(int64_t x)
{
  return pi(x, threads_);
}

int64_t pi(int64_t x, int threads)
{
  return pi_deleglise_rivat(x, threads);
}

#ifdef HAVE_INT128_T

int128_t pi(int128_t x)
{
  return pi(x, threads_);
}

int128_t pi(int128_t x, int threads)
{
  return pi_deleglise_rivat(x, threads);
}

#endif

/// Alias for the fastest prime counting function in primecount.
/// @param x  integer or arithmetic expression like "10^12".
/// @pre   x  <= get_max_x().
///
string pi(const string& x)
{
  return pi(x, threads_);
}

/// Alias for the fastest prime counting function in primecount.
/// @param x  integer or arithmetic expression like "10^12".
/// @pre   x  <= get_max_x().
///
string pi(const string& x, int threads)
{
  maxint_t n = to_maxint(x);
  maxint_t pin = pi(n, threads);
  ostringstream oss;
  oss << pin;
  return oss.str();
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x)
{
  return pi_deleglise_rivat(x, threads_);
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x, int threads)
{
  return pi_deleglise_rivat_parallel2(x, threads);
}

#ifdef HAVE_INT128_T

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat(int128_t x)
{
  return pi_deleglise_rivat(x, threads_);
}

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int128_t pi_deleglise_rivat(int128_t x, int threads)
{
  // use 64-bit if possible
  if (x <= numeric_limits<int64_t>::max())
    return pi_deleglise_rivat((int64_t) x, threads);

  return pi_deleglise_rivat_parallel3(x, threads);
}

#endif

/// Calculate the number of primes below x using Legendre's formula.
/// Run time: O(x) operations, O(x^(1/2)) space.
///
int64_t pi_legendre(int64_t x)
{
  return pi_legendre(x, threads_);
}

/// Calculate the number of primes below x using Lehmer's formula.
/// Run time: O(x/(log x)^4) operations, O(x^(1/2)) space.
///
int64_t pi_lehmer(int64_t x)
{
  return pi_lehmer(x, threads_);
}

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x)
{
  return pi_lmo(x, threads_);
}

/// Parallel implementation of the Lagarias-Miller-Odlyzko
/// prime counting algorithm using OpenMP.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x, int threads)
{
  if (threads <= 1)
    return pi_lmo5(x);

  return pi_lmo_parallel3(x, threads);
}

/// Calculate the number of primes below x using Meissel's formula.
/// Run time: O(x/(log x)^3) operations, O(x^(1/2) / log x) space.
///
int64_t pi_meissel(int64_t x)
{
  return pi_meissel(x, threads_);
}

/// Calculate the number of primes below x using an optimized
/// segmented sieve of Eratosthenes implementation.
/// Run time: O(x log log x) operations, O(x^(1/2)) space.
///
int64_t pi_primesieve(int64_t x)
{
  return pi_primesieve(x, threads_);
}

/// Calculate the nth prime using a combination of an efficient prime
/// counting function implementation and the sieve of Eratosthenes.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/2)) space.
///
int64_t nth_prime(int64_t n)
{
  return nth_prime(n, threads_);
}

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a)
{
  return phi(x, a, threads_);
}

/// Returns the largest integer that can be used with
/// pi(string x). The return type is a string as max may be a
/// 128-bit integer which is not supported by all compilers.
///
string get_max_x(double alpha)
{
  ostringstream oss;

#ifdef HAVE_INT128_T
  // primecount is limited by:
  // z < 2^62, with z = x^(2/3) / alpha
  // x^(2/3) / alpha < 2^62
  // x < (2^62 * alpha)^(3/2)

  // safety buffer: use 61 instead of 62
  double max_x = pow(pow(2.0, 61.0) * alpha, 3.0 / 2.0);
  oss << (int128_t) max_x;
#else
  unused_param(alpha);
  oss << numeric_limits<int64_t>::max();
#endif

  return oss.str();
}

/// Get the wall time in seconds.
double get_wtime()
{
#ifdef _OPENMP
  return omp_get_wtime();
#else
  return static_cast<double>(std::clock()) / CLOCKS_PER_SEC;
#endif
}

int validate_threads(int threads)
{
#ifdef _OPENMP
  if (threads == MAX_THREADS)
    threads = omp_get_max_threads();
  return in_between(1, threads, omp_get_max_threads());
#else
  threads = 1;
  return threads;
#endif
}

int validate_threads(int threads, int64_t sieve_limit, int64_t thread_threshold)
{
  threads = validate_threads(threads);
  thread_threshold = max((int64_t) 1, thread_threshold);
  threads = (int) min((int64_t) threads, sieve_limit / thread_threshold);
  threads = max(1, threads);
  return threads;
}

void set_alpha(double alpha)
{
  alpha_ = alpha;
}

double get_alpha()
{
  return alpha_;
}

double get_alpha(maxint_t x, int64_t y)
{
  // y = x13 * alpha, thus alpha = y / x13
  double x13 = (double) iroot<3>(x);
  return (double) y / x13;
}

/// Calculate the Lagarias-Miller-Odlyzko alpha tuning factor.
/// alpha = a log(x)^2 + b log(x) + c
/// a, b and c are constants that should be determined empirically.
/// @see ../doc/alpha-factor-tuning.pdf
///
double get_alpha_lmo(maxint_t x)
{
  double alpha = get_alpha();

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    double a = 0.00156512;
    double b = -0.0261411;
    double c = 0.990948;
    double logx = log((double) x);

    alpha = a * pow(logx, 2) + b * logx + c;
  }

  return in_between(1, alpha, iroot<6>(x));
}

/// Calculate the Deleglise-Rivat alpha tuning factor.
/// alpha = a log(x)^3 + b log(x)^2 + c log(x) + d
/// a, b, c and d are constants that should be determined empirically.
/// @see ../doc/alpha-factor-tuning.pdf
///
double get_alpha_deleglise_rivat(maxint_t x)
{
  double alpha = get_alpha();
  double x2 = (double) x;

  // use default alpha if no command-line alpha provided
  if (alpha < 1)
  {
    if (x2 <= 1e21)
    {
      double a = 0.000711339;
      double b = -0.0160586;
      double c = 0.123034;
      double d = 0.802942;
      double logx = log(x2);

      alpha = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
    }
    else
    {
      // Because of CPU cache misses sieving (S2_hard(x) and P2(x))
      // becomes the main bottleneck above 10^21 . Hence we use a
      // different alpha formula when x > 10^21 which returns a larger
      // alpha which reduces sieving but increases S2_easy(x) work.
      double a = 0.0017154;
      double b = -0.0508992;
      double c = 0.483613;
      double d = 0.0672202;
      double logx = log(x2);

      alpha = a * pow(logx, 3) + b * pow(logx, 2) + c * logx + d;
    }
  }

  return in_between(1, alpha, iroot<6>(x));
}

void set_num_threads(int threads)
{
  threads_ = validate_threads(threads);
}

int get_num_threads()
{
  return validate_threads(threads_);
}

maxint_t to_maxint(const string& expr)
{
  maxint_t n = calculator::eval<maxint_t>(expr);
  return n;
}

} // namespace primecount
<|endoftext|>


<commit_before>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/V1.hpp"

#include "layers/fileread.h"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv);

   Image * image = new Image("Image", hc, hc->inputFile());

   // construct layers
   HyPerLayer * retina  = new Retina("Retina", hc, image);
   HyPerLayer * l1      = new V1("L1", hc);

   // connect the layers
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   retina->writeActivity(OUTPUT_PATH "retina_last.jpg");
   retina->writeActivity(OUTPUT_PATH "l1_last.jpg");

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<commit_msg>Removed output of final state as is done automatically now.<commit_after>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/V1.hpp"

#include "layers/fileread.h"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv);

   Image * image = new Image("Image", hc, hc->inputFile());

   // construct layers
   HyPerLayer * retina  = new Retina("Retina", hc, image);
   HyPerLayer * l1      = new V1("L1", hc);

   // connect the layers
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<|endoftext|>


<commit_before>

#define DISABLE_LOGGER
// 单线程的话禁用一些锁提高效率
//#define SINGLE_THREAD

#include <cinatra/cinatra.hpp>
#include <fstream>

struct CheckLoginAspect
{
	void before(Request& req, Response& res)
	{
 		if (!req.session().exists("uid")	//如果session没有uid
 			&& req.path() != "/login.html"	//且访问的不是login
 			&& req.path() != "/test_post"	//和test_post页面
 			&& req.path().compare(0, 7, "/public"))	//也不是 public文件夹下的东西
 		{
 			// 跳转到登陆页面
 			res.redirect("/login.html");
 		}
	}

	void after(Request& /* req */, Response& /* res */)
	{

	}
};

struct MyStruct
{
	void hello(cinatra::Request& req, cinatra::Response& res)
	{
		res.end("Hello " + req.session().get<std::string>("uid") + "!");
	}
};

int main()
{
	cinatra::Cinatra<CheckLoginAspect> app;
	app.route("/", [](cinatra::Request& /* req */, cinatra::Response& res)
	{
		res.end("Hello Cinatra");
	});

	// 访问/login.html进行登录.
	app.route("/test_post", [](cinatra::Request& req, cinatra::Response& res)
	{
		if (req.method() != Request::method_t::POST)
		{
			res.set_status_code(404);
			res.end("404 Not found");
			return;
		}

		auto body = cinatra::body_parser(req.body());
		req.session().set("uid", body.get_val("uid"));
		res.end("Hello " + body.get_val("uid") + "! Your password is " + body.get_val("pwd") + "...hahahahaha...");
	});

	MyStruct t;
	// 访问/hello
	app.route("/hello", &MyStruct::hello, &t);
	// 访问类似于/hello/jone/10/xxx
	// joen、10和xxx会分别作为a、b和c三个参数传入handler
	app.route("/hello/:name/:age/:test", [](cinatra::Request& /*req */, cinatra::Response& res, const std::string& a, int b, double c)
	{
		res.end("Name: " + a + " Age: " + boost::lexical_cast<std::string>(b)+"Test: " + boost::lexical_cast<std::string>(c));
	});
	//
	app.route("/hello/:name/:age", [](cinatra::Request& /* req */, cinatra::Response& res, const std::string& a, int b)
	{
		res.end("Name: " + a + " Age: " + boost::lexical_cast<std::string>(b));
	});

	// example: /test_query?a=asdf&b=sdfg
	app.route("/test_query", [](cinatra::Request& req, cinatra::Response& res)
	{
		res.write("<title>test query</title >");
		res.write("Total " + boost::lexical_cast<std::string>(req.query().size()) + "queries
");
		for (auto it : req.query())
		{
			res.write(it.first + ": " + it.second + "
");
		}

		res.end("");
	});

	//设置cookie
	app.route("/set_cookies", [](cinatra::Request& /* req */, cinatra::Response& res)
	{
		res.cookies().new_cookie() // 会话cookie
			.add("foo", "bar")
			.new_cookie().max_age(24 * 60 * 60) //这个cookie会保存一天的时间
			.add("longtime", "test");
		res.write("<title>Set cookies</title >");
		res.write("Please visit show cookies page");
		res.end("");
	});
	//列出所有的cookie
	app.route("/show_cookies", [](cinatra::Request& req, cinatra::Response& res)
	{
		res.write("<title>Show cookies</title >");
		res.write("Total " + boost::lexical_cast<std::string>(req.cookie().size()) + "cookies
");
		for (auto it : req.cookie())
		{
			res.write(it.first + ": " + it.second + "
");
		}

		res.end("");
	});

	app.error_handler(
		[](int code, const std::string&, cinatra::Request&, cinatra::Response& res)
	{
		if (code != 404)
		{
			return false;
		}

		res.set_status_code(404);
		res.write(
			R"(

				<meta charset="UTF-8">
				<title>404</title>

			)"
		);

		return true;
	});

	app.static_dir("./static")
#ifndef SINGLE_THREAD
		.threads(8)
#endif // SINGLE_THREAD
		.listen("0.0.0.0", "http").run();

	return 0;
}
<commit_msg>cinatra示例里CheckLoginAspect结构体的方法参数添加cinatra命名空间<commit_after>

#define DISABLE_LOGGER
// 单线程的话禁用一些锁提高效率
//#define SINGLE_THREAD

#include <cinatra/cinatra.hpp>
#include <fstream>

struct CheckLoginAspect
{
	void before(cinatra::Request& req, cinatra::Response& res)
	{
 		if (!req.session().exists("uid")	//如果session没有uid
 			&& req.path() != "/login.html"	//且访问的不是login
 			&& req.path() != "/test_post"	//和test_post页面
 			&& req.path().compare(0, 7, "/public"))	//也不是 public文件夹下的东西
 		{
 			// 跳转到登陆页面
 			res.redirect("/login.html");
 		}
	}

	void after(cinatra::Request& /* req */, cinatra::Response& /* res */)
	{

	}
};

struct MyStruct
{
	void hello(cinatra::Request& req, cinatra::Response& res)
	{
		res.end("Hello " + req.session().get<std::string>("uid") + "!");
	}
};

int main()
{
	cinatra::Cinatra<CheckLoginAspect> app;
	app.route("/", [](cinatra::Request& /* req */, cinatra::Response& res)
	{
		res.end("Hello Cinatra");
	});

	// 访问/login.html进行登录.
	app.route("/test_post", [](cinatra::Request& req, cinatra::Response& res)
	{
		if (req.method() != Request::method_t::POST)
		{
			res.set_status_code(404);
			res.end("404 Not found");
			return;
		}

		auto body = cinatra::body_parser(req.body());
		req.session().set("uid", body.get_val("uid"));
		res.end("Hello " + body.get_val("uid") + "! Your password is " + body.get_val("pwd") + "...hahahahaha...");
	});

	MyStruct t;
	// 访问/hello
	app.route("/hello", &MyStruct::hello, &t);
	// 访问类似于/hello/jone/10/xxx
	// joen、10和xxx会分别作为a、b和c三个参数传入handler
	app.route("/hello/:name/:age/:test", [](cinatra::Request& /*req */, cinatra::Response& res, const std::string& a, int b, double c)
	{
		res.end("Name: " + a + " Age: " + boost::lexical_cast<std::string>(b)+"Test: " + boost::lexical_cast<std::string>(c));
	});
	//
	app.route("/hello/:name/:age", [](cinatra::Request& /* req */, cinatra::Response& res, const std::string& a, int b)
	{
		res.end("Name: " + a + " Age: " + boost::lexical_cast<std::string>(b));
	});

	// example: /test_query?a=asdf&b=sdfg
	app.route("/test_query", [](cinatra::Request& req, cinatra::Response& res)
	{
		res.write("<title>test query</title >");
		res.write("Total " + boost::lexical_cast<std::string>(req.query().size()) + "queries
");
		for (auto it : req.query())
		{
			res.write(it.first + ": " + it.second + "
");
		}

		res.end("");
	});

	//设置cookie
	app.route("/set_cookies", [](cinatra::Request& /* req */, cinatra::Response& res)
	{
		res.cookies().new_cookie() // 会话cookie
			.add("foo", "bar")
			.new_cookie().max_age(24 * 60 * 60) //这个cookie会保存一天的时间
			.add("longtime", "test");
		res.write("<title>Set cookies</title >");
		res.write("Please visit show cookies page");
		res.end("");
	});
	//列出所有的cookie
	app.route("/show_cookies", [](cinatra::Request& req, cinatra::Response& res)
	{
		res.write("<title>Show cookies</title >");
		res.write("Total " + boost::lexical_cast<std::string>(req.cookie().size()) + "cookies
");
		for (auto it : req.cookie())
		{
			res.write(it.first + ": " + it.second + "
");
		}

		res.end("");
	});

	app.error_handler(
		[](int code, const std::string&, cinatra::Request&, cinatra::Response& res)
	{
		if (code != 404)
		{
			return false;
		}

		res.set_status_code(404);
		res.write(
			R"(

				<meta charset="UTF-8">
				<title>404</title>

			)"
		);

		return true;
	});

	app.static_dir("./static")
#ifndef SINGLE_THREAD
		.threads(8)
#endif // SINGLE_THREAD
		.listen("0.0.0.0", "http").run();

	return 0;
}
<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright (C) 2017, James R. Barlow (https://github.com/jbarlow83/)
 */

#include "utils.h"

/* Convert a Python object to a filesystem encoded path
 * Use Python's os.fspath() which accepts os.PathLike (str, bytes, pathlib.Path)
 * and returns bytes encoded in the filesystem encoding.
 * Cast to a string without transcoding.
 */

#if PY_VERSION_HEX < 0x03060000

    py::object fspath(py::object filename)
    {
        auto py_fspath = py::module::import("pikepdf._cpphelpers").attr("fspath");
        return py_fspath(filename);
    }

#else

    py::object fspath(py::object filename)
    {
        py::handle handle = PyOS_FSPath(filename.ptr());
        if (!handle)
            throw py::error_already_set();
        return py::reinterpret_steal<py::object>(handle);
    }

#endif

/* Open a file, accounting for encoding of the filename
 *
 * First use fspath to resolve the object to a str/bytes, if it is a fancy
 * path like pathlib.Path. Then ask Python to open it.
 *
 * This is surprisingly hard to get right. Filename could be PathLike or str
 * or bytes. If on Windows, filename needs to be wchar_t and we need to use
 * _wfopen. Some environment variables factor in. So this awkward approach
 * let us delegate all the details to Python.
 *
 * Ideally we would just use _Py_fopen_obj, but that is a private API.
 */
FILE *portable_fopen(py::object filename, const char* mode)
{
    auto path = fspath(filename);
    auto io_open = py::module::import("io").attr("open");
    py::object pyfile;
    py::int_ filedes = {-1};
    py::int_ filedes_dup = {-1};

    // Use Python's builtin open to open the file, since it takes care of
    // all of filename encoding issues and interprets mode
    pyfile = io_open(path, mode);
    try {
        // Get file descriptor, and dup() it
        filedes = pyfile.attr("fileno")();
        filedes_dup = py::module::import("os").attr("dup")(filedes);
    } catch (const std::exception &e) {
        pyfile.attr("close")();
        throw;
    }

    try {
        // Close original, releasing Python's buffers. We still have the duplicate
        // descriptor.
        pyfile.attr("close")();

        // Now use stdlib to wrap descriptor as a FILE
        FILE *file = fdopen(filedes_dup, mode);
        if (!file)
            throw std::system_error(errno, std::generic_category());
        return file;
    } catch (const std::exception &e) {
        if (filedes_dup.cast<int>() >= 0)
            close(filedes_dup);
        throw;
    }
}
<commit_msg>portable_fopen: different headers needed for gcc-4.8<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright (C) 2017, James R. Barlow (https://github.com/jbarlow83/)
 */

#include <cstdlib>
#include <system_error>

#include "utils.h"

/* Convert a Python object to a filesystem encoded path
 * Use Python's os.fspath() which accepts os.PathLike (str, bytes, pathlib.Path)
 * and returns bytes encoded in the filesystem encoding.
 * Cast to a string without transcoding.
 */

#if PY_VERSION_HEX < 0x03060000

    py::object fspath(py::object filename)
    {
        auto py_fspath = py::module::import("pikepdf._cpphelpers").attr("fspath");
        return py_fspath(filename);
    }

#else

    py::object fspath(py::object filename)
    {
        py::handle handle = PyOS_FSPath(filename.ptr());
        if (!handle)
            throw py::error_already_set();
        return py::reinterpret_steal<py::object>(handle);
    }

#endif

/* Open a file, accounting for encoding of the filename
 *
 * First use fspath to resolve the object to a str/bytes, if it is a fancy
 * path like pathlib.Path. Then ask Python to open it.
 *
 * This is surprisingly hard to get right. Filename could be PathLike or str
 * or bytes. If on Windows, filename needs to be wchar_t and we need to use
 * _wfopen. Some environment variables factor in. So this awkward approach
 * let us delegate all the details to Python.
 *
 * Ideally we would just use _Py_fopen_obj, but that is a private API.
 */
FILE *portable_fopen(py::object filename, const char* mode)
{
    auto path = fspath(filename);
    auto io_open = py::module::import("io").attr("open");
    py::object pyfile;
    py::int_ filedes = {-1};
    py::int_ filedes_dup = {-1};

    // Use Python's builtin open to open the file, since it takes care of
    // all of filename encoding issues and interprets mode
    pyfile = io_open(path, mode);
    try {
        // Get file descriptor, and dup() it
        filedes = pyfile.attr("fileno")();
        filedes_dup = py::module::import("os").attr("dup")(filedes);
    } catch (const std::exception &e) {
        pyfile.attr("close")();
        throw;
    }

    try {
        // Close original, releasing Python's buffers. We still have the duplicate
        // descriptor.
        pyfile.attr("close")();

        // Now use stdlib to wrap descriptor as a FILE
        FILE *file = fdopen(filedes_dup, mode);
        if (!file)
            throw std::system_error(errno, std::generic_category());
        return file;
    } catch (const std::exception &e) {
        if (filedes_dup.cast<int>() >= 0)
            close(filedes_dup);
        throw;
    }
}
<|endoftext|>


<commit_before>/// UNCLASSIFIED
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "qtuiotouch.hpp"
#include "qasioioservice.hpp"
#include "dosc/asio/udp_receiver.hpp"
#include "tuio/tuio.hpp"
#include <string>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/asio.hpp>
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
#include <QtGui/qpa/qwindowsysteminterface.h>
// based on implementation of qevdevtouch.cpp from Qt 5.0 Beta 1

namespace qtuio {
namespace detail {
//static float hw_width() { return 2560.0f; }
//static float hw_height() { return 1440.0f; }

struct tuio_impl {
        QAsioIOService asio;
        tuio::frame_decoder decoder;
        boost::shared_ptr<dosc::udp_receiver> recv;
        QMap<std::string, QTouchDevice*> devices;
        QMap<int, QWindowSystemInterface::TouchPoint> points;

        tuio_impl(QObject* parent, const boost::asio::ip::udp::endpoint& endpoint);

        void register_device(const std::string& name);
        void handle_frame(const tuio::frame& frm);
        void report_points(const tuio::frame& frm);

        QRectF get_screen_rect();
        QRectF get_window_rect();
        QWindowSystemInterface::TouchPoint& fill_qws_touch_point(const tuio::touch_point& tuio_tp, QWindowSystemInterface::TouchPoint& qws_tp);
        QWindowSystemInterface::TouchPoint make_qws_touch_point(const tuio::touch_point& tp);
        QWindowSystemInterface::TouchPoint& update_qws_touch_point(const tuio::touch_point&tp, QWindowSystemInterface::TouchPoint& existing);

        void add_touch_point(const tuio::touch_point& tp);
        void update_touch_point(const tuio::touch_point& tp);
        void remove_touch_point(const tuio::touch_point& tp);
        void drop_touch_point(const tuio::touch_point& tp);
};

tuio_impl::tuio_impl(QObject* parent, const boost::asio::ip::udp::endpoint& endpoint)
        : asio(parent)
        , decoder()
        , recv(boost::make_shared<dosc::udp_receiver>(boost::ref(asio.get_io_service()), endpoint))
        , devices()
        , points()
{
        decoder.set_frame_callback(boost::bind(&tuio_impl::handle_frame, this, _1));
        /// \todo Register explicitly for the tuio 2d profile
        dosc::add_method(*recv, dosc::decoder::all, boost::ref(decoder));
}

// this is hard coded for the perceptive pixel hardware (27" touch screen)
// I don't think that the TUIO protocol advertises the hardware capabilities
void
tuio_impl::register_device(const std::string& name)
{
        /// calling QWindowSystemInterface::registerTouchDevice() takes ownership of the pointer
        QScopedPointer<QTouchDevice> device(new QTouchDevice);
        if (device) {
                device->setName(QString::fromStdString(name));
                device->setType(QTouchDevice::TouchScreen);
                device->setCapabilities(QTouchDevice::Position |
                                        QTouchDevice::Area |
                                        QTouchDevice::Pressure |
                                        QTouchDevice::Velocity |
                                        QTouchDevice::RawPositions |
                                        QTouchDevice::NormalizedPosition);
                devices.insert(name, device.data());
                QWindowSystemInterface::registerTouchDevice(device.take());
                qDebug() << "Registered TUIO device " << QString::fromStdString(name);
        } else {
                /// \todo Throw!
        }
        Q_ASSERT(devices.contains(name));
}

void
tuio_impl::handle_frame(const tuio::frame& frm)
{
        // check if the device has been registered...
        if (!devices.contains(frm.source)) {
                register_device(frm.source);
        }
        boost::for_each(frm.added, boost::bind(&tuio_impl::add_touch_point, this, _1));
        boost::for_each(frm.updated, boost::bind(&tuio_impl::update_touch_point, this, _1));
        boost::for_each(frm.removed, boost::bind(&tuio_impl::remove_touch_point, this, _1));
        report_points(frm);
        boost::for_each(frm.removed, boost::bind(&tuio_impl::drop_touch_point, this, _1));
}

void
tuio_impl::drop_touch_point(const tuio::touch_point& tp)
{
        points.remove(tp.session_id);
}

QRectF
tuio_impl::get_screen_rect()
{
        /// \todo add support for multiple screens...
        return QGuiApplication::primaryScreen()->geometry();
}

QRectF
tuio_impl::get_window_rect()
{
#if 0
        // qevdevtouch has this "m_forceToActiveWindow" member; not sure why...
        if (m_forceToActiveWindow) {
                if (QWindow *win = QGuiApplication::focusWindow()) {
                        return win->geometry();
                }
        }
#endif
        return get_screen_rect();
}

QWindowSystemInterface::TouchPoint&
tuio_impl::fill_qws_touch_point(const tuio::touch_point& tuio_tp, QWindowSystemInterface::TouchPoint& qws_tp)
{
        qws_tp.id = tuio_tp.session_id;

        /// The TUIO touch point arrives in normalized hardware coordinates
        const QRectF screenRect = get_screen_rect();
        //const QRectF winRect = get_window_rect();
        // Generate a screen position that is always within the active window
        // const qreal
        //         xScaleFactor = screenRect.width()  / winRect.width(),
        //         yScaleFactor = screenRect.height() / winRect.height();
        const QPointF screenPos(tuio_tp.position.x * screenRect.width(), tuio_tp.position.y * screenRect.height());

        // QWindowSystemInterface::TouchPoint wants the normalPosition in normalized touch device coordinates (same as TUIO)
        qws_tp.normalPosition = QPointF(tuio_tp.position.x, tuio_tp.position.y);
        // QWindowSystemInterface::TouchPoint wants the area in screen coordinates
        qws_tp.area = QRectF(0, 0, tuio_tp.dims.width * screenRect.width(), tuio_tp.dims.height * screenRect.height());
        qws_tp.area.moveCenter(screenPos);
        qws_tp.pressure = tuio_tp.area;
        // again, the velocity is reported in the screen coordinate system (pixels per second)
        qws_tp.velocity = QVector2D(tuio_tp.velocity.X * screenRect.width(), tuio_tp.velocity.Y * screenRect.height());
        if (tuio_tp.type == tuio::token_touch) {
                qws_tp.flags = QTouchEvent::TouchPoint::Pen;
        }
        QVector<QPointF> myRawPositions = qws_tp.rawPositions;
        myRawPositions << screenPos;
        qws_tp.rawPositions = myRawPositions;
        return qws_tp;
}

QWindowSystemInterface::TouchPoint
tuio_impl::make_qws_touch_point(const tuio::touch_point& tp)
{
        QWindowSystemInterface::TouchPoint touch;
        fill_qws_touch_point(tp, touch);
        touch.state = Qt::TouchPointPressed;
        return touch;
}

QWindowSystemInterface::TouchPoint&
tuio_impl::update_qws_touch_point(const tuio::touch_point& tp, QWindowSystemInterface::TouchPoint& existing)
{
        Q_ASSERT(tp.session_id == existing.id);

        const QPointF normPos(tp.position.x, tp.position.y);
        if (normPos == existing.normalPosition) {
                fill_qws_touch_point(tp, existing);
                existing.state = Qt::TouchPointStationary;
                existing.velocity = QVector2D();
                return existing;
        }
        fill_qws_touch_point(tp, existing);
        existing.state = Qt::TouchPointMoved;
        return existing;
}

void
tuio_impl::add_touch_point(const tuio::touch_point& tp)
{
        QWindowSystemInterface::TouchPoint touch = make_qws_touch_point(tp);
        Q_ASSERT(!points.contains(touch.id));
        points.insert(touch.id, touch);
}

void
tuio_impl::update_touch_point(const tuio::touch_point& tp)
{
        Q_ASSERT(points.contains(tp.session_id));
        if (!points.contains(tp.session_id)) return;

        update_qws_touch_point(tp, points[tp.session_id]);
}

void
tuio_impl::remove_touch_point(const tuio::touch_point& tp)
{
        Q_ASSERT(points.contains(tp.session_id));
        QWindowSystemInterface::TouchPoint& existing = update_qws_touch_point(tp, points[tp.session_id]);
        existing.state = Qt::TouchPointReleased;
}

void
tuio_impl::report_points(const tuio::frame& frm)
{
        QWindowSystemInterface::handleTouchEvent(0, devices.value(frm.source), points.values());
}

} // namespace detail

QTuioTouchScreenHandler::QTuioTouchScreenHandler(const QString& spec, QObject* parent)
        : QObject(parent)
        , spec_(spec)
        , tuio_()
{
        setObjectName(QLatin1String("TUIO Touch Handler"));
}

QTuioTouchScreenHandler::~QTuioTouchScreenHandler()
{
}

void
QTuioTouchScreenHandler::start()
{
        {
                /// \todo read the desired address out of spec_ and resolve it with ASIO;
                const boost::asio::ip::udp::endpoint my_endpoint(boost::asio::ip::udp::v4(), 3333);
                QScopedPointer<detail::tuio_impl> my_tuio(new detail::tuio_impl(this, my_endpoint));
                if (!my_tuio) {
                        // \todo throw!
                }
                tuio_.swap(my_tuio);
        }
        Q_ASSERT(tuio_);

        tuio_->recv->start();
        tuio_->asio.start();
}

void
QTuioTouchScreenHandler::stop()
{
        if (tuio_) {
                tuio_->recv->stop();
                tuio_->asio.stop();
        }
}

} // namespace qtuio
<commit_msg>Handle errors in the TUIO input functions.<commit_after>/// UNCLASSIFIED
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "qtuiotouch.hpp"
#include "qasioioservice.hpp"
#include "dosc/asio/udp_receiver.hpp"
#include "tuio/tuio.hpp"
#include <string>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/asio.hpp>
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
#include <QtGui/qpa/qwindowsysteminterface.h>
// based on implementation of qevdevtouch.cpp from Qt 5.0 Beta 1

namespace qtuio {
namespace detail {
//static float hw_width() { return 2560.0f; }
//static float hw_height() { return 1440.0f; }

struct tuio_impl {
        QAsioIOService asio;
        tuio::frame_decoder decoder;
        boost::shared_ptr<dosc::udp_receiver> recv;
        QMap<std::string, QTouchDevice*> devices;
        QMap<int, QWindowSystemInterface::TouchPoint> points;

        tuio_impl(QObject* parent, const boost::asio::ip::udp::endpoint& endpoint);

        void register_device(const std::string& name);
        void handle_frame(const tuio::frame& frm);
        void report_points(const tuio::frame& frm);

        QRectF get_screen_rect();
        QRectF get_window_rect();
        QWindowSystemInterface::TouchPoint& fill_qws_touch_point(const tuio::touch_point& tuio_tp, QWindowSystemInterface::TouchPoint& qws_tp);
        QWindowSystemInterface::TouchPoint make_qws_touch_point(const tuio::touch_point& tp);
        QWindowSystemInterface::TouchPoint& update_qws_touch_point(const tuio::touch_point&tp, QWindowSystemInterface::TouchPoint& existing);

        void add_touch_point(const tuio::touch_point& tp);
        void update_touch_point(const tuio::touch_point& tp);
        void remove_touch_point(const tuio::touch_point& tp);
        void drop_touch_point(const tuio::touch_point& tp);
};

tuio_impl::tuio_impl(QObject* parent, const boost::asio::ip::udp::endpoint& endpoint)
        : asio(parent)
        , decoder()
        , recv(boost::make_shared<dosc::udp_receiver>(boost::ref(asio.get_io_service()), endpoint))
        , devices()
        , points()
{
        decoder.set_frame_callback(boost::bind(&tuio_impl::handle_frame, this, _1));
        /// \todo Register explicitly for the tuio 2d profile
        dosc::add_method(*recv, dosc::decoder::all, boost::ref(decoder));
}

// this is hard coded for the perceptive pixel hardware (27" touch screen)
// I don't think that the TUIO protocol advertises the hardware capabilities
void
tuio_impl::register_device(const std::string& name)
{
        /// calling QWindowSystemInterface::registerTouchDevice() takes ownership of the pointer
        QScopedPointer<QTouchDevice> device(new QTouchDevice);
        if (device) {
                device->setName(QString::fromStdString(name));
                device->setType(QTouchDevice::TouchScreen);
                device->setCapabilities(QTouchDevice::Position |
                                        QTouchDevice::Area |
                                        QTouchDevice::Pressure |
                                        QTouchDevice::Velocity |
                                        QTouchDevice::RawPositions |
                                        QTouchDevice::NormalizedPosition);
                devices.insert(name, device.data());
                QWindowSystemInterface::registerTouchDevice(device.take());
                qDebug() << "Registered TUIO device " << QString::fromStdString(name);
        } else {
                /// \todo Throw!
        }
        Q_ASSERT(devices.contains(name));
}

void
tuio_impl::handle_frame(const tuio::frame& frm)
{
        // check if the device has been registered...
        if (!devices.contains(frm.source)) {
                register_device(frm.source);
        }
        boost::for_each(frm.added, boost::bind(&tuio_impl::add_touch_point, this, _1));
        boost::for_each(frm.updated, boost::bind(&tuio_impl::update_touch_point, this, _1));
        boost::for_each(frm.removed, boost::bind(&tuio_impl::remove_touch_point, this, _1));
        report_points(frm);
        boost::for_each(frm.removed, boost::bind(&tuio_impl::drop_touch_point, this, _1));
}

void
tuio_impl::drop_touch_point(const tuio::touch_point& tp)
{
        points.remove(tp.session_id);
}

QRectF
tuio_impl::get_screen_rect()
{
        /// \todo add support for multiple screens...
        return QGuiApplication::primaryScreen()->geometry();
}

QRectF
tuio_impl::get_window_rect()
{
#if 0
        // qevdevtouch has this "m_forceToActiveWindow" member; not sure why...
        if (m_forceToActiveWindow) {
                if (QWindow *win = QGuiApplication::focusWindow()) {
                        return win->geometry();
                }
        }
#endif
        return get_screen_rect();
}

QWindowSystemInterface::TouchPoint&
tuio_impl::fill_qws_touch_point(const tuio::touch_point& tuio_tp, QWindowSystemInterface::TouchPoint& qws_tp)
{
        qws_tp.id = tuio_tp.session_id;

        /// The TUIO touch point arrives in normalized hardware coordinates
        const QRectF screenRect = get_screen_rect();
        //const QRectF winRect = get_window_rect();
        // Generate a screen position that is always within the active window
        // const qreal
        //         xScaleFactor = screenRect.width()  / winRect.width(),
        //         yScaleFactor = screenRect.height() / winRect.height();
        const QPointF screenPos(tuio_tp.position.x * screenRect.width(), tuio_tp.position.y * screenRect.height());

        // QWindowSystemInterface::TouchPoint wants the normalPosition in normalized touch device coordinates (same as TUIO)
        qws_tp.normalPosition = QPointF(tuio_tp.position.x, tuio_tp.position.y);
        // QWindowSystemInterface::TouchPoint wants the area in screen coordinates
        qws_tp.area = QRectF(0, 0, tuio_tp.dims.width * screenRect.width(), tuio_tp.dims.height * screenRect.height());
        qws_tp.area.moveCenter(screenPos);
        qws_tp.pressure = tuio_tp.area;
        // again, the velocity is reported in the screen coordinate system (pixels per second)
        qws_tp.velocity = QVector2D(tuio_tp.velocity.X * screenRect.width(), tuio_tp.velocity.Y * screenRect.height());
        if (tuio_tp.type == tuio::token_touch) {
                qws_tp.flags = QTouchEvent::TouchPoint::Pen;
        }
        QVector<QPointF> myRawPositions = qws_tp.rawPositions;
        myRawPositions << screenPos;
        qws_tp.rawPositions = myRawPositions;
        return qws_tp;
}

QWindowSystemInterface::TouchPoint
tuio_impl::make_qws_touch_point(const tuio::touch_point& tp)
{
        QWindowSystemInterface::TouchPoint touch;
        fill_qws_touch_point(tp, touch);
        touch.state = Qt::TouchPointPressed;
        return touch;
}

QWindowSystemInterface::TouchPoint&
tuio_impl::update_qws_touch_point(const tuio::touch_point& tp, QWindowSystemInterface::TouchPoint& existing)
{
        Q_ASSERT(tp.session_id == existing.id);

        const QPointF normPos(tp.position.x, tp.position.y);
        if (normPos == existing.normalPosition) {
                fill_qws_touch_point(tp, existing);
                existing.state = Qt::TouchPointStationary;
                existing.velocity = QVector2D();
                return existing;
        }
        fill_qws_touch_point(tp, existing);
        existing.state = Qt::TouchPointMoved;
        return existing;
}

void
tuio_impl::add_touch_point(const tuio::touch_point& tp)
{
    if (points.contains(tp.session_id)) {
        qWarning() << "Ignoring ADD command for existing session ID" << tp.session_id;
        return;
    }
    QWindowSystemInterface::TouchPoint touch = make_qws_touch_point(tp);
    points.insert(touch.id, touch);
}

void
tuio_impl::update_touch_point(const tuio::touch_point& tp)
{
    if (!points.contains(tp.session_id)) {
        qWarning() << "Ignoring UPDATE command for missiong session ID" << tp.session_id;
        return;
    }
    update_qws_touch_point(tp, points[tp.session_id]);
}

void
tuio_impl::remove_touch_point(const tuio::touch_point& tp)
{
    if (!points.contains(tp.session_id)) {
        qWarning() << "Ignoring REMOVE command for missing session ID" << tp.session_id;
        return;
    }
    QWindowSystemInterface::TouchPoint& existing = update_qws_touch_point(tp, points[tp.session_id]);
    existing.state = Qt::TouchPointReleased;
}

void
tuio_impl::report_points(const tuio::frame& frm)
{
        QWindowSystemInterface::handleTouchEvent(0, devices.value(frm.source), points.values());
}

} // namespace detail

QTuioTouchScreenHandler::QTuioTouchScreenHandler(const QString& spec, QObject* parent)
        : QObject(parent)
        , spec_(spec)
        , tuio_()
{
        setObjectName(QLatin1String("TUIO Touch Handler"));
}

QTuioTouchScreenHandler::~QTuioTouchScreenHandler()
{
}

void
QTuioTouchScreenHandler::start()
{
        {
                /// \todo read the desired address out of spec_ and resolve it with ASIO;
                const boost::asio::ip::udp::endpoint my_endpoint(boost::asio::ip::udp::v4(), 3333);
                QScopedPointer<detail::tuio_impl> my_tuio(new detail::tuio_impl(this, my_endpoint));
                if (!my_tuio) {
                        // \todo throw!
                }
                tuio_.swap(my_tuio);
        }
        Q_ASSERT(tuio_);

        tuio_->recv->start();
        tuio_->asio.start();
}

void
QTuioTouchScreenHandler::stop()
{
        if (tuio_) {
                tuio_->recv->stop();
                tuio_->asio.stop();
        }
}

} // namespace qtuio
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <fstream>
#include <iterator>
#include <iomanip>

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc != 2)
	{
		std::cerr << "usage: dump_torrent torrent-file\n";
		return 1;
	}
#if BOOST_VERSION < 103400
	boost::filesystem::path::default_name_check(boost::filesystem::no_check);
#endif

	try
	{
		std::ifstream in(argv[1], std::ios_base::binary);
		in.unsetf(std::ios_base::skipws);
		entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());

		std::cout << "\n\n----- raw info -----\n\n";
		e.print(std::cout);

		torrent_info t(e);

		// print info about torrent
		std::cout << "\n\n----- torrent file info -----\n\n";
		std::cout << "nodes:\n";
		typedef std::vector<std::pair<std::string, int> > node_vec;
		node_vec const& nodes = t.nodes();
		for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
			i != end; ++i)
		{
			std::cout << i->first << ":" << i->second << "\n";
		}
		std::cout << "trackers:\n";
		for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
			i != t.trackers().end(); ++i)
		{
			std::cout << i->tier << ": " << i->url << "\n";
		}

		std::cout << "number of pieces: " << t.num_pieces() << "\n";
		std::cout << "piece length: " << t.piece_length() << "\n";
		std::cout << "info hash: " << t.info_hash() << "\n";
		std::cout << "comment: " << t.comment() << "\n";
		std::cout << "created by: " << t.creator() << "\n";
		std::cout << "files:\n";
		for (torrent_info::file_iterator i = t.begin_files();
			i != t.end_files(); ++i)
		{
			std::cout << "  " << std::setw(11) << i->size
			<< " " << i->path.string() << "\n";
		}

	}
	catch (std::exception& e)
	{
  		std::cout << e.what() << "\n";
	}

	return 0;
}

<commit_msg>added first and last piece to dump_torrent<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>
#include <fstream>
#include <iterator>
#include <iomanip>

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc != 2)
	{
		std::cerr << "usage: dump_torrent torrent-file\n";
		return 1;
	}
#if BOOST_VERSION < 103400
	boost::filesystem::path::default_name_check(boost::filesystem::no_check);
#endif

	try
	{
		std::ifstream in(argv[1], std::ios_base::binary);
		in.unsetf(std::ios_base::skipws);
		entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());

		std::cout << "\n\n----- raw info -----\n\n";
		e.print(std::cout);

		torrent_info t(e);

		// print info about torrent
		std::cout << "\n\n----- torrent file info -----\n\n";
		std::cout << "nodes:\n";
		typedef std::vector<std::pair<std::string, int> > node_vec;
		node_vec const& nodes = t.nodes();
		for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
			i != end; ++i)
		{
			std::cout << i->first << ":" << i->second << "\n";
		}
		std::cout << "trackers:\n";
		for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
			i != t.trackers().end(); ++i)
		{
			std::cout << i->tier << ": " << i->url << "\n";
		}

		std::cout << "number of pieces: " << t.num_pieces() << "\n";
		std::cout << "piece length: " << t.piece_length() << "\n";
		std::cout << "info hash: " << t.info_hash() << "\n";
		std::cout << "comment: " << t.comment() << "\n";
		std::cout << "created by: " << t.creator() << "\n";
		std::cout << "files:\n";
		int index = 0;
		for (torrent_info::file_iterator i = t.begin_files();
			i != t.end_files(); ++i, ++index)
		{
			int first = t.map_file(index, 0, 1).piece;
			int last = t.map_file(index, i->size - 1, 1).piece;
			std::cout << "  " << std::setw(11) << i->size
				<< " " << i->path.string() << "[ " << first << ", "
				<< last << " ]\n";
		}

	}
	catch (std::exception& e)
	{
  		std::cout << e.what() << "\n";
	}

	return 0;
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/create_torrent.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/file_pool.hpp"

#include <boost/bind.hpp>

using namespace libtorrent;

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

std::string branch_path(std::string const& f)
{
	if (f.empty()) return f;

#ifdef TORRENT_WINDOWS
	if (f == "\\\\") return "";
#endif
	if (f == "/") return "";

	int len = f.size();
	// if the last character is / or \ ignore it
	if (f[len-1] == '/' || f[len-1] == '\\') --len;
	while (len > 0)
	{
		--len;
		if (f[len] == '/' || f[len] == '\\')
			break;
	}

	if (f[len] == '/' || f[len] == '\\') ++len;
	return std::string(f.c_str(), len);
}

// do not include files and folders whose
// name starts with a .
bool file_filter(std::string const& f)
{
	if (f.empty()) return false;

	char const* first = f.c_str();
	char const* sep = strrchr(first, '/');
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
	char const* altsep = strrchr(first, '\\');
	if (sep == 0 || altsep > sep) sep = altsep;
#endif
	// return false if the first character of the filename is a .
	if (sep == 0 && f[0] == '.') return false;
	if (sep[1] == '.') return false;

	fprintf(stderr, "%s\n", f.c_str());
	return true;
}

void print_progress(int i, int num)
{
	fprintf(stderr, "\r%d/%d", i+1, num);
}

void print_usage()
{
	fputs("usage: make_torrent FILE [OPTIONS]\n"
		"\n"
		"Generates a torrent file from the specified file\n"
		"or directory and writes it to standard out\n\n"
		"OPTIONS:\n"
		"-m file     generate a merkle hash tree torrent.\n"
		"            merkle torrents require client support\n"
		"            the resulting full merkle tree is written to\n"
		"            the specified file\n"
		"-w url      adds a web seed to the torrent with\n"
		"            the specified url\n"
		"-t url      adds the specified tracker to the\n"
		"            torrent. For multiple trackers, specify more\n"
		"            -t options\n"
		"-c comment  sets the comment to the specified string\n"
		"-C creator  sets the created-by field to the specified string\n"
		"-p bytes    enables padding files. Files larger\n"
		"            than bytes will be piece-aligned\n"
		"-s bytes    specifies a piece size for the torrent\n"
		"            This has to be a multiple of 16 kiB\n"
		"-l          Don't follow symlinks, instead encode them as\n"
		"            links in the torrent file\n"
		"-o file     specifies the output filename of the torrent file\n"
		"            If this is not specified, the torrent file is\n"
		"            printed to the standard out, except on windows\n"
		"            where the filename defaults to a.torrent\n"
		"-r file     add root certificate to the torrent, to verify\n"
		"            the HTTPS tracker\n"
		, stderr);
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	std::string creator_str = "libtorrent";
	std::string comment_str;

	if (argc < 2)
	{
		print_usage();
		return 1;
	}

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		std::vector<std::string> web_seeds;
		std::vector<std::string> trackers;
		int pad_file_limit = -1;
		int piece_size = 0;
		int flags = 0;
		std::string root_cert;

		std::string outfile;
		std::string merklefile;
#ifdef TORRENT_WINDOWS
		// don't ever write binary data to the console on windows
		// it will just be interpreted as text and corrupted
		outfile = "a.torrent";
#endif

		for (int i = 2; i < argc; ++i)
		{
			if (argv[i][0] != '-')
			{
				print_usage();
				return 1;
			}

			switch (argv[i][1])
			{
				case 'w':
					++i;
					web_seeds.push_back(argv[i]);
					break;
				case 't':
					++i;
					trackers.push_back(argv[i]);
					break;
				case 'p':
					++i;
					pad_file_limit = atoi(argv[i]);
					flags |= create_torrent::optimize;
					break;
				case 's':
					++i;
					piece_size = atoi(argv[i]);
					break;
				case 'm':
					++i;
					merklefile = argv[i];
					flags |= create_torrent::merkle;
					break;
				case 'o':
					++i;
					outfile = argv[i];
					break;
				case 'l':
					flags |= create_torrent::symlinks;
					break;
				case 'C':
					++i;
					creator_str = argv[i];
					break;
				case 'c':
					++i;
					comment_str = argv[i];
					break;
				case 'r':
					++i;
					root_cert = argv[i];
					break;
				default:
					print_usage();
					return 1;
			}
		}

		file_storage fs;
		std::string full_path = argv[1];
#ifdef TORRENT_WINDOWS
		if (full_path[1] != ':')
#else
		if (full_path[0] != '/')
#endif
		{
			char cwd[TORRENT_MAX_PATH];
			getcwd(cwd, sizeof(cwd));
#ifdef TORRENT_WINDOWS
			full_path = cwd + ("\\" + full_path);
#else
			full_path = cwd + ("/" + full_path);
#endif
		}

		add_files(fs, full_path, file_filter, flags);
		if (fs.num_files() == 0)
		{
			fputs("no files specified.\n", stderr);
			return 1;
		}

		create_torrent t(fs, piece_size, pad_file_limit, flags);
		int tier = 0;
		for (std::vector<std::string>::iterator i = trackers.begin()
			, end(trackers.end()); i != end; ++i, ++tier)
			t.add_tracker(*i, tier);

		for (std::vector<std::string>::iterator i = web_seeds.begin()
			, end(web_seeds.end()); i != end; ++i)
			t.add_url_seed(*i);

		error_code ec;
		set_piece_hashes(t, branch_path(full_path)
			, boost::bind(&print_progress, _1, t.num_pieces()), ec);
		if (ec)
		{
			fprintf(stderr, "%s\n", ec.message().c_str());
			return 1;
		}

		fprintf(stderr, "\n");
		t.set_creator(creator_str.c_str());
		if (!comment_str.empty())
			t.set_comment(comment_str.c_str());

		if (!root_cert.empty())
		{
			std::vector<char> pem;
			load_file(root_cert, pem, ec, 10000);
			if (ec)
			{
				fprintf(stderr, "failed to load root certificate for tracker: %s\n", ec.message().c_str());
			}
			else
			{
				t.set_root_cert(std::string(&pem[0], pem.size()));
			}
		}

		// create the torrent and print it to stdout
		std::vector<char> torrent;
		bencode(back_inserter(torrent), t.generate());
		FILE* output = stdout;
		if (!outfile.empty())
			output = fopen(outfile.c_str(), "wb+");
		if (output == NULL)
		{
			fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
				, outfile.c_str(), errno, strerror(errno));
			return 1;
		}
		fwrite(&torrent[0], 1, torrent.size(), output);

		if (output != stdout)
			fclose(output);

		if (!merklefile.empty())
		{
			output = fopen(merklefile.c_str(), "wb+");
			if (output == NULL)
			{
				fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
					, merklefile.c_str(), errno, strerror(errno));
				return 1;
			}
			int ret = fwrite(&t.merkle_tree()[0], 20, t.merkle_tree().size(), output);
			if (ret != int(t.merkle_tree().size()))
			{
				fprintf(stderr, "failed to write %s: (%d) %s\n"
					, merklefile.c_str(), errno, strerror(errno));
			}
			fclose(output);
		}

#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception& e)
	{
		fprintf(stderr, "%s\n", e.what());
	}
#endif

	return 0;
}

<commit_msg>fix use of getcwd in make_torrent on windows<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/create_torrent.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/file_pool.hpp"

#include <boost/bind.hpp>

#ifdef TORRENT_WINDOWS
#include <direct.h> // for _getcwd
#endif

using namespace libtorrent;

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

std::string branch_path(std::string const& f)
{
	if (f.empty()) return f;

#ifdef TORRENT_WINDOWS
	if (f == "\\\\") return "";
#endif
	if (f == "/") return "";

	int len = f.size();
	// if the last character is / or \ ignore it
	if (f[len-1] == '/' || f[len-1] == '\\') --len;
	while (len > 0)
	{
		--len;
		if (f[len] == '/' || f[len] == '\\')
			break;
	}

	if (f[len] == '/' || f[len] == '\\') ++len;
	return std::string(f.c_str(), len);
}

// do not include files and folders whose
// name starts with a .
bool file_filter(std::string const& f)
{
	if (f.empty()) return false;

	char const* first = f.c_str();
	char const* sep = strrchr(first, '/');
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
	char const* altsep = strrchr(first, '\\');
	if (sep == 0 || altsep > sep) sep = altsep;
#endif
	// return false if the first character of the filename is a .
	if (sep == 0 && f[0] == '.') return false;
	if (sep[1] == '.') return false;

	fprintf(stderr, "%s\n", f.c_str());
	return true;
}

void print_progress(int i, int num)
{
	fprintf(stderr, "\r%d/%d", i+1, num);
}

void print_usage()
{
	fputs("usage: make_torrent FILE [OPTIONS]\n"
		"\n"
		"Generates a torrent file from the specified file\n"
		"or directory and writes it to standard out\n\n"
		"OPTIONS:\n"
		"-m file     generate a merkle hash tree torrent.\n"
		"            merkle torrents require client support\n"
		"            the resulting full merkle tree is written to\n"
		"            the specified file\n"
		"-w url      adds a web seed to the torrent with\n"
		"            the specified url\n"
		"-t url      adds the specified tracker to the\n"
		"            torrent. For multiple trackers, specify more\n"
		"            -t options\n"
		"-c comment  sets the comment to the specified string\n"
		"-C creator  sets the created-by field to the specified string\n"
		"-p bytes    enables padding files. Files larger\n"
		"            than bytes will be piece-aligned\n"
		"-s bytes    specifies a piece size for the torrent\n"
		"            This has to be a multiple of 16 kiB\n"
		"-l          Don't follow symlinks, instead encode them as\n"
		"            links in the torrent file\n"
		"-o file     specifies the output filename of the torrent file\n"
		"            If this is not specified, the torrent file is\n"
		"            printed to the standard out, except on windows\n"
		"            where the filename defaults to a.torrent\n"
		"-r file     add root certificate to the torrent, to verify\n"
		"            the HTTPS tracker\n"
		, stderr);
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	std::string creator_str = "libtorrent";
	std::string comment_str;

	if (argc < 2)
	{
		print_usage();
		return 1;
	}

#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		std::vector<std::string> web_seeds;
		std::vector<std::string> trackers;
		int pad_file_limit = -1;
		int piece_size = 0;
		int flags = 0;
		std::string root_cert;

		std::string outfile;
		std::string merklefile;
#ifdef TORRENT_WINDOWS
		// don't ever write binary data to the console on windows
		// it will just be interpreted as text and corrupted
		outfile = "a.torrent";
#endif

		for (int i = 2; i < argc; ++i)
		{
			if (argv[i][0] != '-')
			{
				print_usage();
				return 1;
			}

			switch (argv[i][1])
			{
				case 'w':
					++i;
					web_seeds.push_back(argv[i]);
					break;
				case 't':
					++i;
					trackers.push_back(argv[i]);
					break;
				case 'p':
					++i;
					pad_file_limit = atoi(argv[i]);
					flags |= create_torrent::optimize;
					break;
				case 's':
					++i;
					piece_size = atoi(argv[i]);
					break;
				case 'm':
					++i;
					merklefile = argv[i];
					flags |= create_torrent::merkle;
					break;
				case 'o':
					++i;
					outfile = argv[i];
					break;
				case 'l':
					flags |= create_torrent::symlinks;
					break;
				case 'C':
					++i;
					creator_str = argv[i];
					break;
				case 'c':
					++i;
					comment_str = argv[i];
					break;
				case 'r':
					++i;
					root_cert = argv[i];
					break;
				default:
					print_usage();
					return 1;
			}
		}

		file_storage fs;
		std::string full_path = argv[1];
#ifdef TORRENT_WINDOWS
		if (full_path[1] != ':')
#else
		if (full_path[0] != '/')
#endif
		{
			char cwd[TORRENT_MAX_PATH];
#ifdef TORRENT_WINDOWS
			_getcwd(cwd, sizeof(cwd));
			full_path = cwd + ("\\" + full_path);
#else
			getcwd(cwd, sizeof(cwd));
			full_path = cwd + ("/" + full_path);
#endif
		}

		add_files(fs, full_path, file_filter, flags);
		if (fs.num_files() == 0)
		{
			fputs("no files specified.\n", stderr);
			return 1;
		}

		create_torrent t(fs, piece_size, pad_file_limit, flags);
		int tier = 0;
		for (std::vector<std::string>::iterator i = trackers.begin()
			, end(trackers.end()); i != end; ++i, ++tier)
			t.add_tracker(*i, tier);

		for (std::vector<std::string>::iterator i = web_seeds.begin()
			, end(web_seeds.end()); i != end; ++i)
			t.add_url_seed(*i);

		error_code ec;
		set_piece_hashes(t, branch_path(full_path)
			, boost::bind(&print_progress, _1, t.num_pieces()), ec);
		if (ec)
		{
			fprintf(stderr, "%s\n", ec.message().c_str());
			return 1;
		}

		fprintf(stderr, "\n");
		t.set_creator(creator_str.c_str());
		if (!comment_str.empty())
			t.set_comment(comment_str.c_str());

		if (!root_cert.empty())
		{
			std::vector<char> pem;
			load_file(root_cert, pem, ec, 10000);
			if (ec)
			{
				fprintf(stderr, "failed to load root certificate for tracker: %s\n", ec.message().c_str());
			}
			else
			{
				t.set_root_cert(std::string(&pem[0], pem.size()));
			}
		}

		// create the torrent and print it to stdout
		std::vector<char> torrent;
		bencode(back_inserter(torrent), t.generate());
		FILE* output = stdout;
		if (!outfile.empty())
			output = fopen(outfile.c_str(), "wb+");
		if (output == NULL)
		{
			fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
				, outfile.c_str(), errno, strerror(errno));
			return 1;
		}
		fwrite(&torrent[0], 1, torrent.size(), output);

		if (output != stdout)
			fclose(output);

		if (!merklefile.empty())
		{
			output = fopen(merklefile.c_str(), "wb+");
			if (output == NULL)
			{
				fprintf(stderr, "failed to open file \"%s\": (%d) %s\n"
					, merklefile.c_str(), errno, strerror(errno));
				return 1;
			}
			int ret = fwrite(&t.merkle_tree()[0], 20, t.merkle_tree().size(), output);
			if (ret != int(t.merkle_tree().size()))
			{
				fprintf(stderr, "failed to write %s: (%d) %s\n"
					, merklefile.c_str(), errno, strerror(errno));
			}
			fclose(output);
		}

#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception& e)
	{
		fprintf(stderr, "%s\n", e.what());
	}
#endif

	return 0;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "dll/neural/dense_layer.hpp"
#include "dll/test.hpp"
#include "dll/network.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

int main(int /*argc*/, char* /*argv*/ []) {
    // Load the dataset
    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 28 * 28>>();

    // Build the network

    using network_t = dll::dyn_network_desc<
        dll::network_layers<
            dll::dense_desc<28 * 28, 32>::layer_t,
            dll::dense_desc<32, 28 * 28>::layer_t
        >
        , dll::batch_size<256>                                 // The mini-batch size
        , dll::shuffle                                         // Shuffle the dataset before each epoch
        , dll::loss<dll::loss_function::BINARY_CROSS_ENTROPY>  // Use a Binary Cross Entropy Loss
        , dll::scale_pre<255>                                  // Scale the images (divide by 255)
        , dll::autoencoder                                     // Indicate auto-encoder
    >::network_t;

    auto net = std::make_unique<network_t>();

    // Display the network
    net->display();

    // Train the network as auto-encoder
    net->fine_tune_ae(dataset.training_images, 50);

    // Test the network on test set
    net->evaluate_ae(dataset.test_images);

    return 0;
}
<commit_msg>Cleanup the auto-encoder example<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "dll/neural/dense_layer.hpp"
#include "dll/test.hpp"
#include "dll/network.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

int main(int /*argc*/, char* /*argv*/ []) {
    // Load the dataset
    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 28 * 28>>();

    // Build the network

    using network_t = dll::dyn_network_desc<
        dll::network_layers<
            dll::dense_desc<28 * 28, 32, dll::relu>::layer_t,
            dll::dense_desc<32, 28 * 28, dll::sigmoid>::layer_t
        >
        , dll::batch_size<256>       // The mini-batch size
        , dll::shuffle               // Shuffle the dataset before each epoch
        , dll::binary_cross_entropy  // Use a Binary Cross Entropy Loss
        , dll::scale_pre<255>        // Scale the images (divide by 255)
        , dll::autoencoder           // Indicate auto-encoder
        , dll::adadelta              // Adadelta updates for gradient descent
    >::network_t;

    auto net = std::make_unique<network_t>();

    // Display the network
    net->display();

    // Train the network as auto-encoder
    net->fine_tune_ae(dataset.training_images, 50);

    // Test the network on test set
    net->evaluate_ae(dataset.test_images);

    return 0;
}
<|endoftext|>


<commit_before>//===- toyc.cpp - The Toy Compiler ----------------------------------------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements the entry point for the Toy compiler.
//
//===----------------------------------------------------------------------===//

#include "toy/Dialect.h"
#include "toy/Lowering.h"
#include "toy/MLIRGen.h"
#include "toy/Parser.h"
#include "toy/Passes.h"

#include "linalg1/Dialect.h"
#include "mlir/ExecutionEngine/ExecutionEngine.h"
#include "mlir/ExecutionEngine/OptUtils.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Module.h"
#include "mlir/Parser.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Transforms/Passes.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"

using namespace toy;
namespace cl = llvm::cl;

static cl::opt<std::string> inputFilename(cl::Positional,
                                          cl::desc("<input toy file>"),
                                          cl::init("-"),
                                          cl::value_desc("filename"));

namespace {
enum InputType { Toy, MLIR };
}
static cl::opt<enum InputType> inputType(
    "x", cl::init(Toy), cl::desc("Decided the kind of output desired"),
    cl::values(clEnumValN(Toy, "toy", "load the input file as a Toy source.")),
    cl::values(clEnumValN(MLIR, "mlir",
                          "load the input file as an MLIR file")));

namespace {
enum Action {
  None,
  DumpAST,
  DumpMLIR,
  DumpMLIRLinalg,
  DumpLLVMDialect,
  DumpLLVMIR,
  RunJIT
};
}
static cl::opt<enum Action> emitAction(
    "emit", cl::desc("Select the kind of output desired"),
    cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")),
    cl::values(clEnumValN(DumpMLIR, "mlir", "output the MLIR dump")),
    cl::values(clEnumValN(DumpMLIRLinalg, "mlir-linalg",
                          "output the MLIR dump after linalg lowering")),
    cl::values(clEnumValN(DumpLLVMDialect, "llvm-dialect",
                          "output the LLVM MLIR Dialect dump")),
    cl::values(clEnumValN(DumpLLVMIR, "llvm-ir", "output the LLVM IR dump")),
    cl::values(
        clEnumValN(RunJIT, "jit",
                   "JIT the code and run it by invoking the main function")));

static cl::opt<bool> EnableOpt("opt", cl::desc("Enable optimizations"));

/// Returns a Toy AST resulting from parsing the file or a nullptr on error.
std::unique_ptr<toy::ModuleAST> parseInputFile(llvm::StringRef filename) {
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
      llvm::MemoryBuffer::getFileOrSTDIN(filename);
  if (std::error_code EC = FileOrErr.getError()) {
    llvm::errs() << "Could not open input file: " << EC.message() << "\n";
    return nullptr;
  }
  auto buffer = FileOrErr.get()->getBuffer();
  LexerBuffer lexer(buffer.begin(), buffer.end(), filename);
  Parser parser(lexer);
  return parser.ParseModule();
}

mlir::LogicalResult optimize(mlir::Module &module) {
  mlir::PassManager pm;
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(createShapeInferencePass());
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(mlir::createCSEPass());

  // Apply any generic pass manager command line options.
  applyPassManagerCLOptions(pm);

  return pm.run(&module);
}

mlir::LogicalResult lowerDialect(mlir::Module &module, bool OnlyLinalg) {
  mlir::PassManager pm;
  pm.addPass(createEarlyLoweringPass());
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(mlir::createCSEPass());
  if (!OnlyLinalg) {
    pm.addPass(createLateLoweringPass());
    pm.addPass(mlir::createCanonicalizerPass());
    pm.addPass(mlir::createCSEPass());
  }
  // Apply any generic pass manager command line options.
  applyPassManagerCLOptions(pm);

  return pm.run(&module);
}

mlir::LogicalResult lowerLLVMModule(mlir::Module &module) {
  mlir::PassManager pm;
  pm.addPass(createEarlyLoweringPass());
  pm.addPass(createLateLoweringPass());

  // Apply any generic pass manager command line options.
  applyPassManagerCLOptions(pm);

  return pm.run(&module);
}

std::unique_ptr<mlir::Module> loadFileAndProcessModule(
    mlir::MLIRContext &context, bool EnableLinalgLowering = false,
    bool EnableLLVMLowering = false, bool EnableOpt = false) {

  std::unique_ptr<mlir::Module> module;
  if (inputType == InputType::MLIR ||
      llvm::StringRef(inputFilename).endswith(".mlir")) {
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
        llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);
    if (std::error_code EC = fileOrErr.getError()) {
      llvm::errs() << "Could not open input file: " << EC.message() << "\n";
      return nullptr;
    }
    llvm::SourceMgr sourceMgr;
    sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc());
    module.reset(mlir::parseSourceFile(sourceMgr, &context));
    if (!module) {
      llvm::errs() << "Error can't load file " << inputFilename << "\n";
      return nullptr;
    }
    if (failed(module->verify())) {
      llvm::errs() << "Error verifying MLIR module\n";
      return nullptr;
    }
  } else {
    auto moduleAST = parseInputFile(inputFilename);
    module = mlirGen(context, *moduleAST);
  }
  if (!module)
    return nullptr;
  if (EnableOpt) {
    if (failed(optimize(*module))) {
      llvm::errs() << "Module optimization failed\n";
      return nullptr;
    }
  }
  if (EnableLLVMLowering || EnableLinalgLowering) {
    if (failed(lowerDialect(*module, !EnableLLVMLowering))) {
      llvm::errs() << "Module lowering failed\n";
      return nullptr;
    }
  }
  return module;
}

int dumpMLIR() {
  mlir::MLIRContext context;
  auto module =
      loadFileAndProcessModule(context, /*EnableLinalgLowering=*/false,
                               /*EnableLLVMLowering=*/false, EnableOpt);
  if (!module)
    return -1;
  module->dump();
  return 0;
}

int dumpMLIRLinalg() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(context, /*EnableLinalgLowering=*/true,
                                         /*EnableLLVMLowering=*/false,
                                         /* EnableOpt=*/true);
  if (!module)
    return -1;
  module->dump();
  return 0;
}

int dumpLLVMDialect() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);
  if (!module) {
    llvm::errs() << "Failed to load/lower MLIR module\n";
    return -1;
  }
  module->dump();
  return 0;
}

int dumpLLVMIR() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);
  if (!module) {
    llvm::errs() << "Failed to load/lower MLIR module\n";
    return -1;
  }
  auto llvmModule = translateModuleToLLVMIR(*module);
  if (!llvmModule) {
    llvm::errs() << "Failed to emit LLVM IR\n";
    return -1;
  }
  // Initialize LLVM targets.
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  mlir::ExecutionEngine::setupTargetTriple(llvmModule.get());
  auto optPipeline = mlir::makeOptimizingTransformer(
      /* optLevel=*/EnableOpt ? 3 : 0, /* sizeLevel=*/0);
  if (auto err = optPipeline(llvmModule.get())) {
    llvm::errs() << "Failed to optimize LLVM IR " << err << "\n";
    return -1;
  }
  llvm::errs() << *llvmModule << "\n";
  return 0;
}

int runJit() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);

  // Initialize LLVM targets.
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();

  // Create an MLIR execution engine. The execution engine eagerly JIT-compiles
  // the module.
  auto optPipeline = mlir::makeOptimizingTransformer(
      /* optLevel=*/EnableOpt ? 3 : 0, /* sizeLevel=*/0);
  auto maybeEngine = mlir::ExecutionEngine::create(module.get(), optPipeline);
  assert(maybeEngine && "failed to construct an execution engine");
  auto &engine = maybeEngine.get();

  // Invoke the JIT-compiled function with the arguments.  Note that, for API
  // uniformity reasons, it takes a list of type-erased pointers to arguments.
  auto invocationResult = engine->invoke("main");
  if (invocationResult) {
    llvm::errs() << "JIT invocation failed\n";
    return -1;
  }

  return 0;
}

int dumpAST() {
  if (inputType == InputType::MLIR) {
    llvm::errs() << "Can't dump a Toy AST when the input is MLIR\n";
    return 5;
  }

  auto moduleAST = parseInputFile(inputFilename);
  if (!moduleAST)
    return 1;

  dump(*moduleAST);
  return 0;
}

int main(int argc, char **argv) {
  // Register our Dialects with MLIR
  mlir::registerDialect<ToyDialect>();
  mlir::registerDialect<linalg::LinalgDialect>();

  mlir::registerPassManagerCLOptions();
  cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");

  switch (emitAction) {
  case Action::DumpAST:
    return dumpAST();
  case Action::DumpMLIR:
    return dumpMLIR();
  case Action::DumpMLIRLinalg:
    return dumpMLIRLinalg();
  case Action::DumpLLVMDialect:
    return dumpLLVMDialect();
  case Action::DumpLLVMIR:
    return dumpLLVMIR();
  case Action::RunJIT:
    return runJit();
  default:
    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";
    return -1;
  }

  return 0;
}
<commit_msg>Remove dead code.<commit_after>//===- toyc.cpp - The Toy Compiler ----------------------------------------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements the entry point for the Toy compiler.
//
//===----------------------------------------------------------------------===//

#include "toy/Dialect.h"
#include "toy/Lowering.h"
#include "toy/MLIRGen.h"
#include "toy/Parser.h"
#include "toy/Passes.h"

#include "linalg1/Dialect.h"
#include "mlir/ExecutionEngine/ExecutionEngine.h"
#include "mlir/ExecutionEngine/OptUtils.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Module.h"
#include "mlir/Parser.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR.h"
#include "mlir/Transforms/Passes.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"

using namespace toy;
namespace cl = llvm::cl;

static cl::opt<std::string> inputFilename(cl::Positional,
                                          cl::desc("<input toy file>"),
                                          cl::init("-"),
                                          cl::value_desc("filename"));

namespace {
enum InputType { Toy, MLIR };
}
static cl::opt<enum InputType> inputType(
    "x", cl::init(Toy), cl::desc("Decided the kind of output desired"),
    cl::values(clEnumValN(Toy, "toy", "load the input file as a Toy source.")),
    cl::values(clEnumValN(MLIR, "mlir",
                          "load the input file as an MLIR file")));

namespace {
enum Action {
  None,
  DumpAST,
  DumpMLIR,
  DumpMLIRLinalg,
  DumpLLVMDialect,
  DumpLLVMIR,
  RunJIT
};
}
static cl::opt<enum Action> emitAction(
    "emit", cl::desc("Select the kind of output desired"),
    cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")),
    cl::values(clEnumValN(DumpMLIR, "mlir", "output the MLIR dump")),
    cl::values(clEnumValN(DumpMLIRLinalg, "mlir-linalg",
                          "output the MLIR dump after linalg lowering")),
    cl::values(clEnumValN(DumpLLVMDialect, "llvm-dialect",
                          "output the LLVM MLIR Dialect dump")),
    cl::values(clEnumValN(DumpLLVMIR, "llvm-ir", "output the LLVM IR dump")),
    cl::values(
        clEnumValN(RunJIT, "jit",
                   "JIT the code and run it by invoking the main function")));

static cl::opt<bool> EnableOpt("opt", cl::desc("Enable optimizations"));

/// Returns a Toy AST resulting from parsing the file or a nullptr on error.
std::unique_ptr<toy::ModuleAST> parseInputFile(llvm::StringRef filename) {
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
      llvm::MemoryBuffer::getFileOrSTDIN(filename);
  if (std::error_code EC = FileOrErr.getError()) {
    llvm::errs() << "Could not open input file: " << EC.message() << "\n";
    return nullptr;
  }
  auto buffer = FileOrErr.get()->getBuffer();
  LexerBuffer lexer(buffer.begin(), buffer.end(), filename);
  Parser parser(lexer);
  return parser.ParseModule();
}

mlir::LogicalResult optimize(mlir::Module &module) {
  mlir::PassManager pm;
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(createShapeInferencePass());
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(mlir::createCSEPass());

  // Apply any generic pass manager command line options.
  applyPassManagerCLOptions(pm);

  return pm.run(&module);
}

mlir::LogicalResult lowerDialect(mlir::Module &module, bool OnlyLinalg) {
  mlir::PassManager pm;
  pm.addPass(createEarlyLoweringPass());
  pm.addPass(mlir::createCanonicalizerPass());
  pm.addPass(mlir::createCSEPass());
  if (!OnlyLinalg) {
    pm.addPass(createLateLoweringPass());
    pm.addPass(mlir::createCanonicalizerPass());
    pm.addPass(mlir::createCSEPass());
  }
  // Apply any generic pass manager command line options.
  applyPassManagerCLOptions(pm);

  return pm.run(&module);
}

std::unique_ptr<mlir::Module> loadFileAndProcessModule(
    mlir::MLIRContext &context, bool EnableLinalgLowering = false,
    bool EnableLLVMLowering = false, bool EnableOpt = false) {

  std::unique_ptr<mlir::Module> module;
  if (inputType == InputType::MLIR ||
      llvm::StringRef(inputFilename).endswith(".mlir")) {
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
        llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);
    if (std::error_code EC = fileOrErr.getError()) {
      llvm::errs() << "Could not open input file: " << EC.message() << "\n";
      return nullptr;
    }
    llvm::SourceMgr sourceMgr;
    sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc());
    module.reset(mlir::parseSourceFile(sourceMgr, &context));
    if (!module) {
      llvm::errs() << "Error can't load file " << inputFilename << "\n";
      return nullptr;
    }
    if (failed(module->verify())) {
      llvm::errs() << "Error verifying MLIR module\n";
      return nullptr;
    }
  } else {
    auto moduleAST = parseInputFile(inputFilename);
    module = mlirGen(context, *moduleAST);
  }
  if (!module)
    return nullptr;
  if (EnableOpt) {
    if (failed(optimize(*module))) {
      llvm::errs() << "Module optimization failed\n";
      return nullptr;
    }
  }
  if (EnableLLVMLowering || EnableLinalgLowering) {
    if (failed(lowerDialect(*module, !EnableLLVMLowering))) {
      llvm::errs() << "Module lowering failed\n";
      return nullptr;
    }
  }
  return module;
}

int dumpMLIR() {
  mlir::MLIRContext context;
  auto module =
      loadFileAndProcessModule(context, /*EnableLinalgLowering=*/false,
                               /*EnableLLVMLowering=*/false, EnableOpt);
  if (!module)
    return -1;
  module->dump();
  return 0;
}

int dumpMLIRLinalg() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(context, /*EnableLinalgLowering=*/true,
                                         /*EnableLLVMLowering=*/false,
                                         /* EnableOpt=*/true);
  if (!module)
    return -1;
  module->dump();
  return 0;
}

int dumpLLVMDialect() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);
  if (!module) {
    llvm::errs() << "Failed to load/lower MLIR module\n";
    return -1;
  }
  module->dump();
  return 0;
}

int dumpLLVMIR() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);
  if (!module) {
    llvm::errs() << "Failed to load/lower MLIR module\n";
    return -1;
  }
  auto llvmModule = translateModuleToLLVMIR(*module);
  if (!llvmModule) {
    llvm::errs() << "Failed to emit LLVM IR\n";
    return -1;
  }
  // Initialize LLVM targets.
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  mlir::ExecutionEngine::setupTargetTriple(llvmModule.get());
  auto optPipeline = mlir::makeOptimizingTransformer(
      /* optLevel=*/EnableOpt ? 3 : 0, /* sizeLevel=*/0);
  if (auto err = optPipeline(llvmModule.get())) {
    llvm::errs() << "Failed to optimize LLVM IR " << err << "\n";
    return -1;
  }
  llvm::errs() << *llvmModule << "\n";
  return 0;
}

int runJit() {
  mlir::MLIRContext context;
  auto module = loadFileAndProcessModule(
      context, /*EnableLinalgLowering=*/false, /* EnableLLVMLowering=*/true,
      /* EnableOpt=*/true);

  // Initialize LLVM targets.
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();

  // Create an MLIR execution engine. The execution engine eagerly JIT-compiles
  // the module.
  auto optPipeline = mlir::makeOptimizingTransformer(
      /* optLevel=*/EnableOpt ? 3 : 0, /* sizeLevel=*/0);
  auto maybeEngine = mlir::ExecutionEngine::create(module.get(), optPipeline);
  assert(maybeEngine && "failed to construct an execution engine");
  auto &engine = maybeEngine.get();

  // Invoke the JIT-compiled function with the arguments.  Note that, for API
  // uniformity reasons, it takes a list of type-erased pointers to arguments.
  auto invocationResult = engine->invoke("main");
  if (invocationResult) {
    llvm::errs() << "JIT invocation failed\n";
    return -1;
  }

  return 0;
}

int dumpAST() {
  if (inputType == InputType::MLIR) {
    llvm::errs() << "Can't dump a Toy AST when the input is MLIR\n";
    return 5;
  }

  auto moduleAST = parseInputFile(inputFilename);
  if (!moduleAST)
    return 1;

  dump(*moduleAST);
  return 0;
}

int main(int argc, char **argv) {
  // Register our Dialects with MLIR
  mlir::registerDialect<ToyDialect>();
  mlir::registerDialect<linalg::LinalgDialect>();

  mlir::registerPassManagerCLOptions();
  cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");

  switch (emitAction) {
  case Action::DumpAST:
    return dumpAST();
  case Action::DumpMLIR:
    return dumpMLIR();
  case Action::DumpMLIRLinalg:
    return dumpMLIRLinalg();
  case Action::DumpLLVMDialect:
    return dumpLLVMDialect();
  case Action::DumpLLVMIR:
    return dumpLLVMIR();
  case Action::RunJIT:
    return runJit();
  default:
    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";
    return -1;
  }

  return 0;
}
<|endoftext|>