<commit_before>#include "catch.hpp"
#include "expected.hpp"

#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define STATIC_REQUIRE(e)                                                      \
  constexpr bool TOKENPASTE2(rqure, __LINE__) = e;                             \
  REQUIRE(e);

TEST_CASE("Map extensions", "[extensions.map]") {
  auto mul2 = [](auto a) { return a * 2; };
  auto ret_void = [](auto a) {};

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }
}

TEST_CASE("Map error extensions", "[extensions.map_error]") {
  auto mul2 = [](auto a) { return a * 2; };
  auto ret_void = [](auto a) {};

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }
}

TEST_CASE("And then extensions", "[extensions.and_then]") {
  auto succeed = [](auto a) { return tl::expected<int, int>(21 * 2); };
  auto fail = [](auto a) { return tl::expected<int, int>(tl::unexpect, 17); };

  {
    tl::expected<int, int> e = 21;
    auto ret = e.and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }
}
<commit_msg>Fix tests<commit_after>#include "catch.hpp"
#include "expected.hpp"

#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define STATIC_REQUIRE(e)                                                      \
  constexpr bool TOKENPASTE2(rqure, __LINE__) = e;                             \
  REQUIRE(e);

TEST_CASE("Map extensions", "[extensions.map]") {
  auto mul2 = [](int a) { return a * 2; };
  auto ret_void = [](int a) {};

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map(ret_void);
    REQUIRE(ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map(ret_void);
    REQUIRE(!ret);
    STATIC_REQUIRE(
        (std::is_same<decltype(ret), tl::expected<tl::monostate, int>>::value));
  }
}

TEST_CASE("Map error extensions", "[extensions.map_error]") {
  auto mul2 = [](auto a) { return a * 2; };
  auto ret_void = [](auto a) {};

  {
    tl::expected<int, int> e = 21;
    auto ret = e.map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(ret);
    REQUIRE(*ret == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).map_error(mul2);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 42);
  }
}

TEST_CASE("And then extensions", "[extensions.and_then]") {
  auto succeed = [](auto a) { return tl::expected<int, int>(21 * 2); };
  auto fail = [](auto a) { return tl::expected<int, int>(tl::unexpect, 17); };

  {
    tl::expected<int, int> e = 21;
    auto ret = e.and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(ret);
    REQUIRE(*ret == 42);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    const tl::expected<int, int> e = 21;
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 17);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(succeed);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = e.and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }

  {
    const tl::expected<int, int> e(tl::unexpect, 21);
    auto ret = std::move(e).and_then(fail);
    REQUIRE(!ret);
    REQUIRE(ret.error() == 21);
  }
}
<|endoftext|>


<commit_before>
#include "dirs.h"

#include <iostream>

#ifdef __WIN32__
#include <windows.h>
#include <shlwapi.h>
#include <shlobj.h>
#else
#include <libproc.h>
#include <unistd.h>
#include <pwd.h>
#endif

#include <boost/filesystem.hpp>

#include "process.h"
#include "utils.h"
#include "version.h"

using namespace std;
using namespace boost::filesystem;

string Dirs::appDataDir()
{
	static string p = "";

	if (p != "")
		return p;

	string dir;

#ifdef __WIN32__
	TCHAR buffer[MAX_PATH];
	if ( ! SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, buffer)))
	{
		std::cerr << "App Data dir could not be retrieved\n";
		std::cerr.flush();

		return "";
	}

	dir = Utils::ws2s(buffer);

#else

	dir = string(getpwuid(getuid())->pw_dir);

#endif

	dir += "/JASP/" + string(APP_VERSION);

	if ( ! exists(dir))
	{
		if (create_directories(dir) == false)
		{
			std::cout << dir << " could not be created\n";
			std::cout.flush();

			return "";
		}
	}

	p = path(dir).generic_string();

	return p;
}

string Dirs::tempDir()
{
	static string p = "";
	if (p != "")
		return p;

	string dir;
	string appData = appDataDir();

	if (appData == "")
		return "";

	dir = appData + "/temp";

	if ( ! exists(dir))
	{
		if (create_directories(dir) == false)
		{
			std::cout << dir << " could not be created\n";
			std::cout.flush();

			return "";
		}
	}

	p = path(dir).generic_string();

	return p;
}

string Dirs::exeDir()
{
	static string p = "";
	if (p != "")
		return p;

#ifdef __WIN32__
	HMODULE hModule = GetModuleHandleW(NULL);
	WCHAR path[MAX_PATH];
	GetModuleFileNameW(hModule, path, MAX_PATH);

	wstring s(path);
	string r = Utils::ws2s(path);

	char *pathbuf = new char[MAX_PATH];
	r.copy(pathbuf, MAX_PATH);

	int last = 0;

	for (int i = 0; i < r.length(); i++)
	{
		if (pathbuf[i] == '\\')
		{
			pathbuf[i] = '/';
			last = i;
		}
	}

	r = string(pathbuf, last);

	delete[] pathbuf;

	p = r;

	return r;

#else

	unsigned long pid = Process::currentPID();

	char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
	int ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf));

	if (ret <= 0)
	{
		cout << "Could not retrieve exe location\n";
		cout.flush();

		throw exception();
	}
	else
	{
		int last = strlen(pathbuf);

		for (int i = last - 1; i > 0; i--)
		{
			if (pathbuf[i] == '/')
			{
				pathbuf[i] = '\0';
				break;
			}
		}

		p = string(pathbuf);

		return p;
	}

#endif

}

string Dirs::rHomeDir()
{
	string dir = exeDir();

#ifdef __WIN32__
	dir += "/R";
#elif __APPLE__
	dir += "/../Frameworks/R.framework/Versions/3.1/Resources";
#else
	dir += "/R";
#endif

	return dir;
}

<commit_msg>Changes to App dir on linux and OSX<commit_after>
#include "dirs.h"

#include <iostream>

#ifdef __WIN32__
#include <windows.h>
#include <shlwapi.h>
#include <shlobj.h>
#else
#include <libproc.h>
#include <unistd.h>
#include <pwd.h>
#endif

#include <boost/filesystem.hpp>

#include "process.h"
#include "utils.h"
#include "version.h"

using namespace std;
using namespace boost::filesystem;

string Dirs::appDataDir()
{
	static string p = "";

	if (p != "")
		return p;

	string dir;

#ifdef __WIN32__
	TCHAR buffer[MAX_PATH];
	if ( ! SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, buffer)))
	{
		std::cerr << "App Data dir could not be retrieved\n";
		std::cerr.flush();

		throw std::exception();
	}

	dir = Utils::ws2s(buffer);
	dir += "/JASP/" + string(APP_VERSION);

#else

	dir = string(getpwuid(getuid())->pw_dir);
	dir += "/.JASP/" + string(APP_VERSION);

#endif

	if ( ! exists(dir))
	{
		if (create_directories(dir) == false)
		{
			std::cerr << dir << " could not be created\n";
			std::cerr.flush();

			throw std::exception();
		}
	}

	p = path(dir).generic_string();

	return p;
}

string Dirs::tempDir()
{
	static string p = "";
	if (p != "")
		return p;

	string dir;
	string appData = appDataDir();

	dir = appData + "/temp";

	if ( ! exists(dir))
	{
		if (create_directories(dir) == false)
		{
			std::cerr << dir << " could not be created\n";
			std::cerr.flush();

			throw exception();
		}
	}

	p = path(dir).generic_string();

	return p;
}

string Dirs::exeDir()
{
	static string p = "";
	if (p != "")
		return p;

#ifdef __WIN32__
	HMODULE hModule = GetModuleHandleW(NULL);
	WCHAR path[MAX_PATH];
	GetModuleFileNameW(hModule, path, MAX_PATH);

	wstring s(path);
	string r = Utils::ws2s(path);

	char *pathbuf = new char[MAX_PATH];
	r.copy(pathbuf, MAX_PATH);

	int last = 0;

	for (int i = 0; i < r.length(); i++)
	{
		if (pathbuf[i] == '\\')
		{
			pathbuf[i] = '/';
			last = i;
		}
	}

	r = string(pathbuf, last);

	delete[] pathbuf;

	p = r;

	return r;

#else

	unsigned long pid = Process::currentPID();

	char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
	int ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf));

	if (ret <= 0)
	{
		cerr << "Could not retrieve exe location\n";
		cerr.flush();

		throw exception();
	}
	else
	{
		int last = strlen(pathbuf);

		for (int i = last - 1; i > 0; i--)
		{
			if (pathbuf[i] == '/')
			{
				pathbuf[i] = '\0';
				break;
			}
		}

		p = string(pathbuf);

		return p;
	}

#endif

}

string Dirs::rHomeDir()
{
	string dir = exeDir();

#ifdef __WIN32__
	dir += "/R";
#elif __APPLE__
	dir += "/../Frameworks/R.framework/Versions/3.1/Resources";
#else
	dir += "/R";
#endif

	return dir;
}

<|endoftext|>


<commit_before>
/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <boost/test/unit_test.hpp>

#include "tests/test-utils.hh"
#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"
#include "core/reactor.hh"
#include "service/storage_service.hh"
#include "core/distributed.hh"
#include "database.hh"
#include "db/system_distributed_keyspace.hh"

SEASTAR_TEST_CASE(test_boot_shutdown){
    return seastar::async([] {
        distributed<database> db;
        sharded<auth::service> auth_service;
        sharded<db::system_distributed_keyspace> sys_dist_ks;
        utils::fb_utilities::set_broadcast_address(gms::inet_address("127.0.0.1"));
        locator::i_endpoint_snitch::create_snitch("SimpleSnitch").get();
        service::get_storage_service().start(std::ref(db), std::ref(auth_service), std::ref(sys_dist_ks)).get();
        db.start().get();
        netw::get_messaging_service().start(gms::inet_address("127.0.0.1"), 7000, false /* don't bind */).get();
        gms::get_failure_detector().start().get();

        gms::get_gossiper().start().get();
        gms::get_gossiper().stop().get();
        gms::get_failure_detector().stop().get();
        db.stop().get();
        service::get_storage_service().stop().get();
        netw::get_messaging_service().stop().get();
        locator::i_endpoint_snitch::stop_snitch().get();
    });
}
<commit_msg>tests/gossip_test: Use RAII for orderly destruction<commit_after>
/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <boost/test/unit_test.hpp>

#include <seastar/util/defer.hh>

#include "tests/test-utils.hh"
#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"
#include "core/reactor.hh"
#include "service/storage_service.hh"
#include "core/distributed.hh"
#include "database.hh"
#include "db/system_distributed_keyspace.hh"

SEASTAR_TEST_CASE(test_boot_shutdown){
    return seastar::async([] {
        distributed<database> db;
        sharded<auth::service> auth_service;
        sharded<db::system_distributed_keyspace> sys_dist_ks;
        utils::fb_utilities::set_broadcast_address(gms::inet_address("127.0.0.1"));

        locator::i_endpoint_snitch::create_snitch("SimpleSnitch").get();
        auto stop_snitch = defer([&] { gms::get_failure_detector().stop().get(); });

        netw::get_messaging_service().start(gms::inet_address("127.0.0.1"), 7000, false /* don't bind */).get();
        auto stop_messaging_service = defer([&] { netw::get_messaging_service().stop().get(); });

        service::get_storage_service().start(std::ref(db), std::ref(auth_service), std::ref(sys_dist_ks)).get();
        auto stop_ss = defer([&] { service::get_storage_service().stop().get(); });

        db.start().get();
        auto stop_db = defer([&] { db.stop().get(); });

        gms::get_failure_detector().start().get();
        auto stop_failure_detector = defer([&] { gms::get_failure_detector().stop().get(); });

        gms::get_gossiper().start().get();
        auto stop_gossiper = defer([&] { gms::get_gossiper().stop().get(); });
    });
}
<|endoftext|>


<commit_before>
#include "gtest.h"

#include <curl/curl.h>

namespace Test {

#include "../libpubnub/crypto.h"
#include "../libpubnub/pubnub.h"
#include "../libpubnub/pubnub-priv.h"

#undef PUBNUB_API
#define PUBNUB_API

static bool curlInit = false;

CURLM *curl_multi_init(void)
{
	curlInit = true;
	return ::curl_multi_init();
}

CURLMsg *curl_multi_info_read( CURLM *multi_handle,   int *msgs_in_queue)
{
	return NULL;
}

CURLMcode curl_multi_socket_action(CURLM * multi_handle,
                                    curl_socket_t sockfd, int ev_bitmask,
                                    int *running_handles)
{
	return CURLM_OK;
}

#include "../libpubnub/pubnub.c"

class PubnubTest : public ::testing::Test
{
protected:
	pubnub_callbacks cb;
	pubnub *p;
	char *url;

	static int addSock;
	static int addSockMode;

	static void
	pubnub_test_add_socket(struct pubnub *p, void *ctx_data, int fd, int mode,
			void (*cb)(struct pubnub *p, int fd, int mode, void *cb_data), void *cb_data)
	{
		addSock = fd;
		addSockMode = mode;
	}

	static int remSock;

	static void
	pubnub_test_rem_socket(struct pubnub *p, void *ctx_data, int fd)
	{
		remSock = fd;
	}

	static void
	pubnub_test_timeout(struct pubnub *p, void *ctx_data, const struct timespec *ts,
			void (*cb)(struct pubnub *p, void *cb_data), void *cb_data)
	{
	}

	static void
	pubnub_test_wait(struct pubnub *p, void *ctx_data)
	{
	}

	virtual void SetUp() {

		memset(&cb, 0, sizeof(cb));
		cb.add_socket = pubnub_test_add_socket;
		cb.rem_socket = pubnub_test_rem_socket;
		cb.timeout = pubnub_test_timeout;
		cb.wait = pubnub_test_wait;

		curlInit = false;

		p = pubnub_init("demo", "demo", &cb, NULL);

		addSock = remSock = 0;
		addSockMode = 0;
	}
	virtual void TearDown() {
		pubnub_done(p);
	}
};

int PubnubTest::addSock, PubnubTest::addSockMode, PubnubTest::remSock;

TEST_F(PubnubTest, Publish) {
	ASSERT_TRUE(curlInit);
	json_object *msg;
	msg = json_object_new_object();
	json_object_object_add(msg, "str", json_object_new_string("test"));
	pubnub_publish(p, "channel", msg, -1, NULL, NULL);
	json_object_put(msg);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/publish/demo/demo/0/channel/0/%7B%20%22str%22%3A%20%22test%22%20%7D", url);
}

TEST_F(PubnubTest, Subscribe) {
	ASSERT_TRUE(curlInit);
	pubnub_subscribe(p, "channel", -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	char *t = strchr(url,'=');
	ASSERT_TRUE(t != NULL);
	char *s = strdup(url);
	s[t - url] = 0;
	EXPECT_STREQ("http://pubsub.pubnub.com/subscribe/demo/channel/0/0?uuid", s);
	free(s);
	pubnub_connection_cancel(p);
}

TEST_F(PubnubTest, SubscribeMulti) {
	ASSERT_TRUE(curlInit);
	const char *channels[] = {"channel1", "channel2"};
	pubnub_subscribe_multi(p, channels, 2, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	char *t = strchr(url,'=');
	ASSERT_TRUE(t != NULL);
	char *s = strdup(url);
	s[t - url] = 0;
	EXPECT_STREQ("http://pubsub.pubnub.com/subscribe/demo/channel1%2Cchannel2/0/0?uuid", s);
	free(s);
	pubnub_connection_cancel(p);
}

TEST_F(PubnubTest, History) {
	ASSERT_TRUE(curlInit);
	pubnub_history(p, "channel", 10, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/history/demo/channel/0/10", url);
}

TEST_F(PubnubTest, HereNow) {
	ASSERT_TRUE(curlInit);
	pubnub_here_now(p, "channel", -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/v2/presence/sub-key/demo/channel/channel", url);
}

TEST_F(PubnubTest, Time) {
	ASSERT_TRUE(curlInit);
	pubnub_time(p, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/time/0", url);
}

TEST(ChannelSetTest, AddRemove) {
	struct channelset cs = {NULL, 0};
	EXPECT_EQ(0, channelset_add(&cs, &cs));
	const char *ch1[] = {"abc", "cde"};
	struct channelset cs1 = {ch1, 2};
	EXPECT_EQ(0, channelset_add(&cs1, &cs1));
	const char *ch2[] = {"abc", "fgh", "cde"};
	struct channelset cs2 = {ch2, 3};
	struct channelset *cs3 = (struct channelset*)calloc(1, sizeof(struct channelset));
	EXPECT_EQ(2, channelset_add(cs3, &cs1));
	EXPECT_EQ(1, channelset_add(cs3, &cs2));
	EXPECT_EQ(2, channelset_rm(cs3, &cs1));
	EXPECT_EQ(0, channelset_rm(cs3, &cs1));
	EXPECT_STREQ(ch2[1], cs3->set[0]);
	EXPECT_EQ(1, channelset_rm(cs3, &cs2));
	free(cs3);
}

}

<commit_msg>tests: Add stderr capture & some minor fixes<commit_after>
#include "gtest.h"

#include <curl/curl.h>
#include <fcntl.h>

namespace Test {

#include "../libpubnub/crypto.h"
#include "../libpubnub/pubnub.h"
#include "../libpubnub/pubnub-priv.h"

#undef PUBNUB_API
#define PUBNUB_API

static bool curlInit = false;

CURLM *curl_multi_init(void)
{
	curlInit = true;
	return ::curl_multi_init();
}

CURLMsg *curl_multi_info_read( CURLM *multi_handle,   int *msgs_in_queue)
{
	return NULL;
}

CURLMcode curl_multi_socket_action(CURLM * multi_handle,
                                    curl_socket_t sockfd, int ev_bitmask,
                                    int *running_handles)
{
	return CURLM_OK;
}

#include "../libpubnub/pubnub.c"

class PubnubTest : public ::testing::Test
{
protected:
	pubnub_callbacks cb;
	pubnub *p;
	char *url;

	int _err_pipe[2];
	int _old_err;
	std::string _err;

	static int addSock;
	static int addSockMode;

	static void
	pubnub_test_add_socket(struct pubnub *p, void *ctx_data, int fd, int mode,
			void (*cb)(struct pubnub *p, int fd, int mode, void *cb_data), void *cb_data)
	{
		addSock = fd;
		addSockMode = mode;
	}

	static int remSock;

	static void
	pubnub_test_rem_socket(struct pubnub *p, void *ctx_data, int fd)
	{
		remSock = fd;
	}

	static void
	pubnub_test_timeout(struct pubnub *p, void *ctx_data, const struct timespec *ts,
			void (*cb)(struct pubnub *p, void *cb_data), void *cb_data)
	{
	}

	static void
	pubnub_test_wait(struct pubnub *p, void *ctx_data)
	{
	}

	void GetErr() {
        fflush(stderr);
        std::string buf;
        const int bufSize = 1024;
        buf.resize(bufSize);
        int bytesRead = 0;
        if (!eof(_err_pipe[0])) {
            bytesRead = read(_err_pipe[0], &(*buf.begin()), bufSize);
        }
        while(bytesRead == bufSize) {
            _err += buf;
            bytesRead = 0;
            if (!eof(_err_pipe[0])) {
                bytesRead = read(_err_pipe[0], &(*buf.begin()), bufSize);
            }
        }
        if (bytesRead > 0) {
            buf.resize(bytesRead);
            _err += buf;
        }
	}

	virtual void SetUp() {
		memset(&cb, 0, sizeof(cb));
		cb.add_socket = pubnub_test_add_socket;
		cb.rem_socket = pubnub_test_rem_socket;
		cb.timeout = pubnub_test_timeout;
		cb.wait = pubnub_test_wait;

		curlInit = false;

        _err_pipe[0] = 0;
        _err_pipe[1] = 0;
		_old_err = 0;

		_err.clear();
        if (_pipe(_err_pipe, 65536, O_BINARY) != -1) {
			_old_err = dup(fileno(stderr));
			fflush(stderr);
			dup2(_err_pipe[1], fileno(stderr));
		}

		p = pubnub_init("demo", "demo", &cb, NULL);

		addSock = remSock = 0;
		addSockMode = 0;
	}

	virtual void TearDown() {
        if (_old_err > 0) {
			dup2(_old_err, fileno(stderr));
            close(_old_err);
		}
        if (_err_pipe[0] > 0) {
            close(_err_pipe[0]);
		}
        if (_err_pipe[1] > 0) {
            close(_err_pipe[1]);
		}
		pubnub_done(p);
	}
};

int PubnubTest::addSock, PubnubTest::addSockMode, PubnubTest::remSock;

TEST_F(PubnubTest, Publish) {
	ASSERT_TRUE(curlInit);
	json_object *msg;
	msg = json_object_new_object();
	json_object_object_add(msg, "str", json_object_new_string("test"));
	pubnub_publish(p, "channel", msg, -1, NULL, NULL);
	json_object_put(msg);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/publish/demo/demo/0/channel/0/%7B%20%22str%22%3A%20%22test%22%20%7D", url);
}

TEST_F(PubnubTest, Subscribe) {
	ASSERT_TRUE(curlInit);
	pubnub_subscribe(p, "channel", -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	char *t = strchr(url, '=');
	ASSERT_TRUE(t != NULL);
	char *s = strdup(url);
	s[t - url] = 0;
	EXPECT_STREQ("http://pubsub.pubnub.com/subscribe/demo/channel/0/0?uuid", s);
	free(s);
	pubnub_connection_cancel(p);
}

TEST_F(PubnubTest, Unsubscribe) {
	ASSERT_TRUE(curlInit);
	const char *channel = "channel";
	pubnub_subscribe(p, channel, -1, NULL, NULL);
	pubnub_unsubscribe(p, &channel, 1, -1, NULL, NULL);
	EXPECT_EQ(1, p->channelset.n);
	pubnub_connection_cancel(p);
	pubnub_subscribe(p, channel, -1, NULL, NULL);
	pubnub_unsubscribe(p, &channel, 1, -1, NULL, NULL);
	EXPECT_EQ(0, p->channelset.n);
}

TEST_F(PubnubTest, SubscribeMulti) {
	ASSERT_TRUE(curlInit);
	const char *channels[] = {"channel1", "channel2"};
	pubnub_subscribe_multi(p, channels, 2, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	char *t = strchr(url,'=');
	ASSERT_TRUE(t != NULL);
	char *s = strdup(url);
	s[t - url] = 0;
	EXPECT_STREQ("http://pubsub.pubnub.com/subscribe/demo/channel1%2Cchannel2/0/0?uuid", s);
	free(s);
	pubnub_connection_cancel(p);
}

TEST_F(PubnubTest, History) {
	ASSERT_TRUE(curlInit);
	pubnub_history(p, "channel", 10, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/history/demo/channel/0/10", url);
}

TEST_F(PubnubTest, HereNow) {
	ASSERT_TRUE(curlInit);
	pubnub_here_now(p, "channel", -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/v2/presence/sub-key/demo/channel/channel", url);
}

TEST_F(PubnubTest, Time) {
	ASSERT_TRUE(curlInit);
	pubnub_time(p, -1, NULL, NULL);
	curl_easy_getinfo(p->curl, CURLINFO_EFFECTIVE_URL, &url);
	EXPECT_STREQ("http://pubsub.pubnub.com/time/0", url);
}

TEST(ChannelSetTest, AddRemove) {
	struct channelset cs = {NULL, 0};
	EXPECT_EQ(0, channelset_add(&cs, &cs));
	const char *ch1[] = {"abc", "cde"};
	struct channelset cs1 = {ch1, 2};
	EXPECT_EQ(2, channelset_add(&cs, &cs1));
	EXPECT_STREQ(ch1[1], cs.set[1]);
	channelset_done(&cs);
	EXPECT_EQ(0, channelset_add(&cs1, &cs1));
	const char *ch2[] = {"abc", "fgh", "cde"};
	struct channelset cs2 = {ch2, 3};
	struct channelset cs3 = {NULL, 0};
	EXPECT_EQ(2, channelset_add(&cs3, &cs1));
	EXPECT_EQ(1, channelset_add(&cs3, &cs2));
	EXPECT_EQ(2, channelset_rm(&cs3, &cs1));
	EXPECT_EQ(0, channelset_rm(&cs3, &cs1));
	EXPECT_STREQ(ch2[1], cs3.set[0]);
	EXPECT_EQ(1, channelset_rm(&cs3, &cs2));
	channelset_done(&cs3);
}

}

<|endoftext|>


<commit_before>// clickStoreRGB.cpp : ̨Ӧóڵ㡣
//

#include "stdafx.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <Windows.h>

#include "RGBRecord.h"

using namespace::std;
using namespace::cv;

Mat img;		// ͼƬ
int frameNum = -1;	// ֡
string filename;	// ǰͼƬ·
char sc[500];		// ǰͼƬ·ת
vector<RGBRecord> rgbVec;

static void onMouse( int event, int x, int y, int, void* )
{
	if( event == CV_EVENT_LBUTTONUP )
	{
		Mat_<Vec3b> _img = img;
		RGBRecord record( _img(y,x)[2], _img(y,x)[1], _img(y,x)[0],
						  y, x, frameNum, filename);
		rgbVec.push_back(record);
		cout << record << endl;
		img = _img;

		return;
	}
	else if ( event == CV_EVENT_RBUTTONUP )
	{
		if(!rgbVec.empty()) // do nothing if empty
		{
			RGBRecord record;
			record = rgbVec.back();
			rgbVec.pop_back();
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |
									FOREGROUND_RED);
			cout << "deleted: "<< record << endl;
			// reset the font color
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x7);
		}
	}
}

void writeVec()
{
	if (rgbVec.empty())
	{
		return;
	}

	// write to txt
	ofstream outfile("rgbStat.txt", ofstream::out | ofstream::app);
	if(!outfile)
	{
		cerr << "unable to open outfile" << endl;
		return ;
	}
	else
	{
		if(outfile)
		{
			// write every record
			for (vector<RGBRecord>::iterator iter = rgbVec.begin() ;
					iter != rgbVec.end() ; ++iter)
			{
				outfile << *iter << endl;
			}
		}
		// close the file
		outfile.close();
		outfile.clear();
	}
}

string ext(string strFile)
{
	string::size_type found = strFile.rfind(".");
	if( found != string ::npos)
	{
		++found;
		string strExt =  strFile.substr(found);
		// ȫתСд
		transform(strExt.begin(), strExt.end(), strExt.begin(), ::tolower);
		return strExt;
	}
	return string();
}

bool isImage(string filename)
{
	string strExt = ext(filename);
	if(strExt == "jpg" || strExt == "bmp" || strExt == "jpeg" ||
		strExt == "png" )
	{
		cout << "ext is: " << strExt << endl;
		return true;
	}
	return false;
}

bool isVideo(string filename)
{
	string strExt = ext(filename);
	if( strExt == "avi" || strExt == "3gp" || strExt == "rmvb" || strExt == "flv" ||
		strExt == "mp4" || strExt == "wmv" || strExt == "mkv" )
	{
		cout << "ext is: " << strExt << endl;
		return true;
	}
	return false;
}

void dealImage()
{
	img = imread(filename);
	if(! img.data )                              // Check for invalid input
	{
		cout <<  "Could not open or no such image file." << std::endl ;
		return ;
	}
	for (;;)
	{
		const string WIN_SRC  = "src_pic";
		namedWindow( WIN_SRC, CV_WINDOW_AUTOSIZE );// Create a window for display.
		setMouseCallback(WIN_SRC, onMouse);
		imshow( WIN_SRC, img );                   // Show our image inside it.

		char c = (char)waitKey();
		if (c==27) // ESC pressed
		{
			writeVec();
			break;
		}
	}
}

void dealVideo()
{
	VideoCapture capt(filename);
	if(!capt.isOpened())
	{
		cout << "Can't open video file : " << filename << endl;
		return;
	}
	for(;;)
	{
		capt >> img;
		++frameNum ;
		if (img.empty())
		{
			cout << "Video is over." << endl;
			writeVec();
			return;
		}
		cout << "frame = " <<  frameNum << endl;
		const char *WIN_CAP = "src_vid";
		namedWindow(WIN_CAP);
		setMouseCallback(WIN_CAP, onMouse);
		imshow (WIN_CAP, img);

		char c = (char)waitKey();
		// ignore other input keys
		while ( (c!=13) && (c != 27) )
		{
			c = (char)waitKey();
		}
		if (c==13) // ENTER to forward
		{
			continue;
		}
		if (c==27) // ESC to EXIT
		{
			writeVec();
			break;
		}
	}

}

string& replace_all_distinct(string& str, const string& old_value, const string& new_value)
{
    for(string::size_type pos = 0; pos != string::npos;
		pos += new_value.length() )
	{
		pos=str.find(old_value, pos);
        if( pos != string::npos )
		{
			str.replace(pos, old_value.length(), new_value);
		}
        else
		{
			break;
		}
	}
	return str;
}

int _tmain(int argc, _TCHAR* argv[])
{
	while (filename.empty())
	{
		if ( argc == 2 ) // drag file input
		{
			wcout << "drag file: " << argv[1] << endl;
			// Converts Unicode string to ANSI
			sprintf(sc,"%S", argv[1]);
			filename = string(sc);
		}
		else // enter the filepath
		{
			cout << "input an file: " <<ends;
			getline(cin, filename);
		}
	} // end while

	replace_all_distinct(filename, string("\\"), string("\\\\") );
	cout << "file accepted: " << filename << endl;

	if(isImage(filename)) // if it's an image
	{
		cout << "This is an image." << endl;
		dealImage();
	}
	else if(isVideo(filename))
	{
		cout << "This is a video." << endl;
		dealVideo();
	}
	else
	{
		cout << "Unknown-type file." << endl;
	}

	// show the results
	getchar();

	return 0;
}

<commit_msg>修正了能够识别的格式播放完时候退出未响应的bug<commit_after>// clickStoreRGB.cpp : ̨Ӧóڵ㡣
//

#include "stdafx.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <Windows.h>

#include "RGBRecord.h"

using namespace::std;
using namespace::cv;

Mat img;		// ͼƬ
int frameNum = -1;	// ֡
string filename;	// ǰͼƬ·
char sc[500];		// ǰͼƬ·ת
vector<RGBRecord> rgbVec;

static void onMouse( int event, int x, int y, int, void* )
{
	if( event == CV_EVENT_LBUTTONUP )
	{
		Mat_<Vec3b> _img = img;
		RGBRecord record( _img(y,x)[2], _img(y,x)[1], _img(y,x)[0],
						  y, x, frameNum, filename);
		rgbVec.push_back(record);
		cout << record << endl;
		img = _img;

		return;
	}
	else if ( event == CV_EVENT_RBUTTONUP )
	{
		if(!rgbVec.empty()) // do nothing if empty
		{
			RGBRecord record;
			record = rgbVec.back();
			rgbVec.pop_back();
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |
									FOREGROUND_RED);
			cout << "deleted: "<< record << endl;
			// reset the font color
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x7);
		}
	}
}

void writeVec()
{
	if (rgbVec.empty())
	{
		return;
	}

	// write to txt
	ofstream outfile("rgbStat.txt", ofstream::out | ofstream::app);
	if(!outfile)
	{
		cerr << "unable to open outfile" << endl;
		return ;
	}
	else
	{
		if(outfile)
		{
			// write every record
			for (vector<RGBRecord>::iterator iter = rgbVec.begin() ;
					iter != rgbVec.end() ; ++iter)
			{
				outfile << *iter << endl;
			}
		}
		// close the file
		outfile.close();
		outfile.clear();
	}
}

string ext(string strFile)
{
	string::size_type found = strFile.rfind(".");
	if( found != string ::npos)
	{
		++found;
		string strExt =  strFile.substr(found);
		// ȫתСд
		transform(strExt.begin(), strExt.end(), strExt.begin(), ::tolower);
		return strExt;
	}
	return string();
}

bool isImage(string filename)
{
	string strExt = ext(filename);
	if(strExt == "jpg" || strExt == "bmp" || strExt == "jpeg" ||
		strExt == "png" )
	{
		cout << "ext is: " << strExt << endl;
		return true;
	}
	return false;
}

bool isVideo(string filename)
{
	string strExt = ext(filename);
	if( strExt == "avi" || strExt == "3gp" || strExt == "rmvb" || strExt == "flv" ||
		strExt == "mp4" || strExt == "wmv" || strExt == "mkv" )
	{
		cout << "ext is: " << strExt << endl;
		return true;
	}
	return false;
}

void dealImage()
{
	img = imread(filename);
	if(! img.data )                              // Check for invalid input
	{
		cout <<  "Could not open or no such image file." << std::endl ;
		return ;
	}
	for (;;)
	{
		const string WIN_SRC  = "src_pic";
		namedWindow( WIN_SRC, CV_WINDOW_AUTOSIZE );// Create a window for display.
		setMouseCallback(WIN_SRC, onMouse);
		imshow( WIN_SRC, img );                   // Show our image inside it.

		char c = (char)waitKey();
		if (c==27) // ESC pressed
		{
			writeVec();
			break;
		}
	}
}

void dealVideo()
{
	VideoCapture capt(filename);
	if(!capt.isOpened())
	{
		cout << "Can't open video file : " << filename << endl;
		return;
	}
	for(;;)
	{
		capt >> img;
		++frameNum ;
		if (img.empty())
		{
			cout << "Video is over." << endl;
			writeVec();
			return;
		}
		cout << "frame = " <<  frameNum << endl;
		const char *WIN_CAP = "src_vid";
		namedWindow(WIN_CAP);
		setMouseCallback(WIN_CAP, onMouse);
		imshow (WIN_CAP, img);

		char c = (char)waitKey();
		// ignore other input keys
		while ( (c!=13) && (c != 27) )
		{
			c = (char)waitKey();
		}
		if (c==13) // ENTER to forward
		{
			continue;
		}
		if (c==27) // ESC to EXIT
		{
			writeVec();
			break;
		}
	}

}

string& replace_all_distinct(string& str, const string& old_value, const string& new_value)
{
    for(string::size_type pos = 0; pos != string::npos;
		pos += new_value.length() )
	{
		pos=str.find(old_value, pos);
        if( pos != string::npos )
		{
			str.replace(pos, old_value.length(), new_value);
		}
        else
		{
			break;
		}
	}
	return str;
}

int _tmain(int argc, _TCHAR* argv[])
{
	while (filename.empty())
	{
		if ( argc == 2 ) // drag file input
		{
			wcout << "drag file: " << argv[1] << endl;
			// Converts Unicode string to ANSI
			sprintf(sc,"%S", argv[1]);
			filename = string(sc);
		}
		else // enter the filepath
		{
			cout << "input an file: " <<ends;
			getline(cin, filename);
		}
	} // end while

	replace_all_distinct(filename, string("\\"), string("\\\\") );
	cout << "file accepted: " << filename << endl;

	if(isImage(filename)) // if it's an image
	{
		cout << "This is an image." << endl;
		dealImage();
	}
	else if(isVideo(filename))
	{
		cout << "This is a video." << endl;
		dealVideo();
	}
	else
	{
		cout << "Unknown-type file." << endl;
		// show the results
		getchar();
	}

	return 0;
}

<|endoftext|>


<commit_before>#ifndef OPERATOR_HH
#define OPERATOR_HH

#include <dune/grid/common/mcmgmapper.hh>
#include <dune/grid/common/datahandleif.hh>

#include "coefficients.hh"
#include "vector.hh"

#ifdef AS_LIB
#include <boost/python.hpp>
#endif

template <class M>
class VectorExchange
    : public Dune::CommDataHandleIF<VectorExchange<M>, double>
{
public:
  typedef double DataType;

  VectorExchange (const M & mapper, Vector& u)
    : mapper_(mapper), u_(u)
  {}

  bool contains(int dim, int codim) const
  {
    return (codim == 0);
  }

  bool fixedsize (int dim, int codim) const
  {
    return true;
  }

  template < class EntityType >
  std::size_t size (EntityType & e) const
  {
    return 1;
  }

  template <class MessageBuffer, class EntityType >
  void gather(MessageBuffer& buff, const EntityType& e ) const
  {
    buff.write(u_[mapper_.map(e)]);
  }

  template <class MessageBuffer, class EntityType >
  void scatter(MessageBuffer& buff, const EntityType& e , std::size_t n)
  {
    DataType x;
    buff.read(x);
    u_[mapper_.map(e)] = x;
  }
private :
  const M& mapper_;
  Vector& u_;
};

template <class GV, typename D = char>
class SpaceOperator
{
public:
  typedef Dune::MultipleCodimMultipleGeomTypeMapper<GV, Dune::MCMGElementLayout> Mapper;
  typedef VectorExchange<Mapper> VE;

  SpaceOperator(std::shared_ptr<GV> gv, std::shared_ptr<Coefficients<GV::dimension> >& coeffs)
      : gv_(gv), coefficients_(coeffs), mapper_(*gv)
  {}

  SpaceOperator(std::shared_ptr<GV> gv, std::shared_ptr<Coefficients<GV::dimension> >& coeffs, D d)
      : gv_(gv), coefficients_(coeffs), mapper_(*gv), d_(d)
  {}

  SpaceOperator(const SpaceOperator& that) = delete;
  SpaceOperator& operator=(const SpaceOperator& that) = delete;

  void apply(const Vector& source, Vector& range, double exponent, double weight=1.) const
  {
    auto endit = gv_->template end<0>();
    for (auto it = gv_->template begin<0>(); it != endit; ++it) {

      int indInside = mapper_.map(*it);

      auto isend = gv_->iend(*it);
      for (auto is = gv_->ibegin(*it); is != isend; ++is) {

        if (is->neighbor()) {

          auto outside = is->outside();
          int indOutside = mapper_.map(*outside);

          if (indInside < indOutside) {

            const double u_s = source[indInside];
            const double u_n = source[indOutside];

            const double faceVolume = is->geometry().volume();
            const auto normal = is->centerUnitOuterNormal();

            double convectiveFlux = (normal * coefficients_->v) * (pow(u_s, exponent) + pow(u_n, exponent)) / 2;

            const double interfaceFlux = ((u_s - u_n) / (2 * coefficients_->lambda) + convectiveFlux) * faceVolume;

            range[indInside] += interfaceFlux / it->geometry().volume() * weight;
            range[indOutside] -= interfaceFlux / outside->geometry().volume() * weight;

          }
        }
      }
    }

    VE ve(mapper_, range);
    gv_->template communicate<VE>(ve, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
  }

  std::size_t dimSource()
  {
    return mapper_.size();
  }

private:
  std::shared_ptr<GV> gv_;
  std::shared_ptr<Coefficients<GV::dimension> > coefficients_;
  Mapper mapper_;
  D d_;

#ifdef AS_LIB
public:
  static void export_(const char* classname)
  {
    using boost::python::class_;
    using boost::python::no_init;

    class_<SpaceOperator, std::shared_ptr<SpaceOperator>, boost::noncopyable>(classname, no_init)
        .def("apply", &SpaceOperator::apply)
        .add_property("dimSource", &SpaceOperator::dimSource)
        .add_property("dimRange", &SpaceOperator::dimSource)
    ;
  }
#endif

};

#endif
<commit_msg>fix numerical flux for negative values<commit_after>#ifndef OPERATOR_HH
#define OPERATOR_HH

#include <dune/grid/common/mcmgmapper.hh>
#include <dune/grid/common/datahandleif.hh>

#include "coefficients.hh"
#include "vector.hh"

#ifdef AS_LIB
#include <boost/python.hpp>
#endif

template <class M>
class VectorExchange
    : public Dune::CommDataHandleIF<VectorExchange<M>, double>
{
public:
  typedef double DataType;

  VectorExchange (const M & mapper, Vector& u)
    : mapper_(mapper), u_(u)
  {}

  bool contains(int dim, int codim) const
  {
    return (codim == 0);
  }

  bool fixedsize (int dim, int codim) const
  {
    return true;
  }

  template < class EntityType >
  std::size_t size (EntityType & e) const
  {
    return 1;
  }

  template <class MessageBuffer, class EntityType >
  void gather(MessageBuffer& buff, const EntityType& e ) const
  {
    buff.write(u_[mapper_.map(e)]);
  }

  template <class MessageBuffer, class EntityType >
  void scatter(MessageBuffer& buff, const EntityType& e , std::size_t n)
  {
    DataType x;
    buff.read(x);
    u_[mapper_.map(e)] = x;
  }
private :
  const M& mapper_;
  Vector& u_;
};

template <class GV, typename D = char>
class SpaceOperator
{
public:
  typedef Dune::MultipleCodimMultipleGeomTypeMapper<GV, Dune::MCMGElementLayout> Mapper;
  typedef VectorExchange<Mapper> VE;

  SpaceOperator(std::shared_ptr<GV> gv, std::shared_ptr<Coefficients<GV::dimension> >& coeffs)
      : gv_(gv), coefficients_(coeffs), mapper_(*gv)
  {}

  SpaceOperator(std::shared_ptr<GV> gv, std::shared_ptr<Coefficients<GV::dimension> >& coeffs, D d)
      : gv_(gv), coefficients_(coeffs), mapper_(*gv), d_(d)
  {}

  SpaceOperator(const SpaceOperator& that) = delete;
  SpaceOperator& operator=(const SpaceOperator& that) = delete;

  void apply(const Vector& source, Vector& range, double exponent, double weight=1.) const
  {
    auto endit = gv_->template end<0>();
    for (auto it = gv_->template begin<0>(); it != endit; ++it) {

      int indInside = mapper_.map(*it);

      auto isend = gv_->iend(*it);
      for (auto is = gv_->ibegin(*it); is != isend; ++is) {

        if (is->neighbor()) {

          auto outside = is->outside();
          int indOutside = mapper_.map(*outside);

          if (indInside < indOutside) {

            const double u_s = source[indInside];
            const double u_n = source[indOutside];

            const double faceVolume = is->geometry().volume();
            const auto normal = is->centerUnitOuterNormal();

            const double pow_u_s = ((u_s > 0) - (u_s < 0)) * pow(fabs(u_s), exponent);
            const double pow_u_n = ((u_n > 0) - (u_n < 0)) * pow(fabs(u_n), exponent);
            double convectiveFlux = (normal * coefficients_->v) * (pow_u_s + pow_u_n) / 2;

            const double interfaceFlux = ((u_s - u_n) / (2 * coefficients_->lambda) + convectiveFlux) * faceVolume;

            range[indInside] += interfaceFlux / it->geometry().volume() * weight;
            range[indOutside] -= interfaceFlux / outside->geometry().volume() * weight;

          }
        }
      }
    }

    VE ve(mapper_, range);
    gv_->template communicate<VE>(ve, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
  }

  std::size_t dimSource()
  {
    return mapper_.size();
  }

private:
  std::shared_ptr<GV> gv_;
  std::shared_ptr<Coefficients<GV::dimension> > coefficients_;
  Mapper mapper_;
  D d_;

#ifdef AS_LIB
public:
  static void export_(const char* classname)
  {
    using boost::python::class_;
    using boost::python::no_init;

    class_<SpaceOperator, std::shared_ptr<SpaceOperator>, boost::noncopyable>(classname, no_init)
        .def("apply", &SpaceOperator::apply)
        .add_property("dimSource", &SpaceOperator::dimSource)
        .add_property("dimRange", &SpaceOperator::dimSource)
    ;
  }
#endif

};

#endif
<|endoftext|>


<commit_before>/*
 * GENERATING A FEW FONTS (SAVED IN THE DOCUMENTS FOLDER)
 *
 *
 * REQUIREMENTS:
 * - OSX
 * - FREETYPE BLOCK: https://github.com/arielm/Freetype
 *
 *
 * FONTS USED:
 * - Georgia - AVAILABLE ON OSX AND WINDOWS
 * - Roboto - AVAILABLE ON ANDROID AND AS GOOGLE-FONT: http://www.google.com/fonts/specimen/Roboto
 * - FrankRuehl - AVAILABLE ON WINDOWS (WITH HEBREW SUPPORT): http://www.microsoft.com/typography/fonts/font.aspx?FMID=1886
 */

#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"

#include "chronotext/font/FontManager.h"
#include "chronotext/text/TextHelper.h"
#include "chronotext/tools/font/XFontCreator.h"
#include "chronotext/tools/font/Characters.h"
#include "chronotext/utils/Utils.h"

using namespace std;
using namespace ci;
using namespace app;
using namespace chr;

const std::wstring HEBREW_BIBLICAL = L":,;.-\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea";

class Application : public AppNative
{
    shared_ptr<FreetypeHelper> ftHelper;
    FontManager fontManager;

    shared_ptr<XFont> font1;
    shared_ptr<XFont> font2;
    shared_ptr<XFont> font3;

public:
    void setup();
    void prepareSettings(Settings *settings);

    void draw();

    void createFontSafely(const FontDescriptor &descriptor, float size, const wstring &characters, const XParams &params);
    shared_ptr<XFont> loadFontSafely(const string &fileName);
    void drawFontSafely(shared_ptr<XFont> &font, float size, float x, float y, float direction = +1);
};

void Application::setup()
{
    ftHelper = make_shared<FreetypeHelper>();

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD FONTS LIKE Georgia ON OSX
     */
    createFontSafely(FontDescriptor("/Library/Fonts/Georgia.ttf"), 64, ISO_8859_15, XParams(3, 2));

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD A CUSTOM FONT FROM THE RESOURCE-BUNDLE
     */
    createFontSafely(FontDescriptor(getResourcePath("Roboto-Regular.ttf")), 64, ISO_8859_15, XParams(3, 2));

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD A CUSTOM FONT FROM THE DOCUMENTS FOLDER
     */
    createFontSafely(FontDescriptor(getDocumentsDirectory() / "frank.ttf"), 64, HEBREW_BIBLICAL, XParams(3, 2));

    // ---

    /*
     * LOADING OUR GENERATED FONTS
     */

    font1 = loadFontSafely("Georgia_Regular_64.fnt");
    font2 = loadFontSafely("Roboto_Regular_64.fnt");
    font3 = loadFontSafely("FrankRuehl_Regular_64.fnt");

    // ---

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
}

void Application::prepareSettings(AppBasic::Settings *settings)
{
    Area area = settings->getDisplay()->getBounds();
    settings->setWindowSize(area.getWidth(), area.getWidth() * 0.25f);
}

void Application::draw()
{
    gl::clear(Color(0.5f, 0.5f, 0.5f), false);
    glColor4f(1, 1, 1, 1);

    drawFontSafely(font1, 32, 10, getWindowHeight() * 1 / 4.0f);
    drawFontSafely(font2, 32, 10, getWindowHeight() * 2 / 4.0f);
    drawFontSafely(font3, 64, getWindowWidth() - 10, getWindowHeight() * 3 / 4.0f, -1);
}

void Application::createFontSafely(const FontDescriptor &descriptor, float size, const wstring &characters, const XParams &params)
{
    try
    {
        XFontCreator(ftHelper, descriptor, size, characters, params).writeToFolder(getDocumentsDirectory());
    }
    catch (exception &e)
    {
        LOGI << e.what() << endl;
    }
}

shared_ptr<XFont> Application::loadFontSafely(const string &fileName)
{
    try
    {
        return fontManager.getCachedFont(InputSource::getFileInDocuments(fileName), XFont::Properties::Default2D());
    }
    catch (exception &e)
    {
        LOGI << e.what() << endl;
    }

    return NULL;
}

void Application::drawFontSafely(shared_ptr<XFont> &font, float size, float x, float y, float direction)
{
    if (font)
    {
        font->setSize(size);
        font->setDirection(direction);
        TextHelper::drawText(*font, font->getCharacters(), x, y);
    }
}

CINDER_APP_NATIVE(Application, RendererGl(RendererGl::AA_NONE))
<commit_msg>TWEAKING samples/FontGenerator PROJECT<commit_after>/*
 * GENERATING A FEW FONTS (SAVED IN THE DOCUMENTS FOLDER)
 *
 *
 * REQUIREMENTS:
 * - OSX
 * - FREETYPE BLOCK: https://github.com/arielm/Freetype
 *
 *
 * FONTS USED:
 * - Georgia - AVAILABLE ON OSX AND WINDOWS
 * - Roboto - AVAILABLE ON ANDROID AND AS GOOGLE-FONT: http://www.google.com/fonts/specimen/Roboto
 * - FrankRuehl - AVAILABLE ON WINDOWS (WITH HEBREW SUPPORT): http://www.microsoft.com/typography/fonts/font.aspx?FMID=1886
 */

#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"

#include "chronotext/font/FontManager.h"
#include "chronotext/text/TextHelper.h"
#include "chronotext/tools/font/XFontCreator.h"
#include "chronotext/tools/font/Characters.h"
#include "chronotext/utils/Utils.h"

using namespace std;
using namespace ci;
using namespace app;
using namespace chr;

const std::wstring HEBREW_BIBLICAL = L":,;.-\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea";

class Application : public AppNative
{
    shared_ptr<FreetypeHelper> ftHelper;
    FontManager fontManager;

    vector<shared_ptr<XFont>> fonts;

public:
    void setup();
    void prepareSettings(Settings *settings);

    void draw();

    void createFontSafely(const FontDescriptor &descriptor, float size, const wstring &characters, const XParams &params);
    void loadFontSafely(const string &fileName, bool useMipmap = false);
    void drawFonts(float size);
};

void Application::setup()
{
    ftHelper = make_shared<FreetypeHelper>();

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD FONTS LIKE Georgia ON OSX
     */
    createFontSafely(FontDescriptor("/Library/Fonts/Georgia.ttf"), 64, ISO_8859_15, XParams(3, 2));

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD A CUSTOM FONT FROM THE RESOURCE-BUNDLE
     */
    createFontSafely(FontDescriptor(getResourcePath("Roboto-Regular.ttf")), 64, ISO_8859_15, XParams(3, 2));

    /*
     * - PROVIDING ENOUGH MARGIN AND PADDING, TO ALLOW FOR MIPMAPPING WITHOUT BLEEDING EDGES
     * - DEMONSTRATES HOW TO LOAD A CUSTOM FONT FROM THE DOCUMENTS FOLDER
     */
    createFontSafely(FontDescriptor(getDocumentsDirectory() / "frank.ttf"), 64, HEBREW_BIBLICAL, XParams(3, 2));

    // ---

    /*
     * LOADING OUR GENERATED FONTS
     */

    loadFontSafely("Georgia_Regular_64.fnt");
    loadFontSafely("Roboto_Regular_64.fnt");
    loadFontSafely("FrankRuehl_Regular_64.fnt");

    // ---

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
}

void Application::prepareSettings(AppBasic::Settings *settings)
{
    Area area = settings->getDisplay()->getBounds();
    settings->setWindowSize(area.getWidth(), area.getWidth() * 0.25f);
}

void Application::draw()
{
    gl::clear(Color(0.5f, 0.5f, 0.5f), false);
    glColor4f(1, 1, 1, 1);

    drawFonts(32);
}

void Application::createFontSafely(const FontDescriptor &descriptor, float size, const wstring &characters, const XParams &params)
{
    try
    {
        XFontCreator(ftHelper, descriptor, size, characters, params).writeToFolder(getDocumentsDirectory());
    }
    catch (exception &e)
    {
        LOGI << e.what() << endl;
    }
}

void Application::loadFontSafely(const string &fileName, bool useMipmap)
{
    try
    {
        fonts.push_back(fontManager.getCachedFont(InputSource::getFileInDocuments(fileName), XFont::Properties::Default2D()));
    }
    catch (exception &e)
    {
        LOGI << e.what() << endl;
    }
}

void Application::drawFonts(float size)
{
    int current = 0;
    int count = fonts.size();

    for (auto &font : fonts)
    {
        current++;
        float y = getWindowHeight() * current / float(count + 1);

        font->setSize(size);
        TextHelper::drawAlignedText(*font, font->getCharacters(), getWindowWidth() * 0.5f, y, XFont::ALIGN_MIDDLE, XFont::ALIGN_MIDDLE);
    }
}

CINDER_APP_NATIVE(Application, RendererGl(RendererGl::AA_NONE))
<|endoftext|>


<commit_before>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/extensions/renderer/xwalk_extension_renderer_controller.h"

#include "base/stringprintf.h"
#include "base/values.h"
#include "xwalk/extensions/common/xwalk_extension_messages.h"
#include "xwalk/extensions/renderer/xwalk_extension_render_view_handler.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
#include "v8/include/v8.h"

// This will be generated from xwalk_api.js.
extern const char kSource_xwalk_api[];

namespace xwalk {
namespace extensions {

class XWalkExtensionV8Wrapper : public v8::Extension {
 public:
  XWalkExtensionV8Wrapper();

  // v8::Extension implementation.
  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
      v8::Handle<v8::String> name);

 private:
  static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args);
  static v8::Handle<v8::Value> SendSyncMessage(const v8::Arguments& args);
};

XWalkExtensionV8Wrapper::XWalkExtensionV8Wrapper()
    : v8::Extension("xwalk", kSource_xwalk_api) {
}

v8::Handle<v8::FunctionTemplate>
XWalkExtensionV8Wrapper::GetNativeFunction(v8::Handle<v8::String> name) {
  if (name->Equals(v8::String::New("PostMessage")))
    return v8::FunctionTemplate::New(PostMessage);
  if (name->Equals(v8::String::New("SendSyncMessage")))
    return v8::FunctionTemplate::New(SendSyncMessage);
  return v8::Handle<v8::FunctionTemplate>();
}

v8::Handle<v8::Value> XWalkExtensionV8Wrapper::PostMessage(
    const v8::Arguments& args) {
  if (args.Length() != 2)
    return v8::False();

  XWalkExtensionRenderViewHandler* handler =
      XWalkExtensionRenderViewHandler::GetForCurrentContext();

  scoped_ptr<content::V8ValueConverter> converter(
      content::V8ValueConverter::create());
  scoped_ptr<base::Value> value_args(
      converter->FromV8Value(args[1], handler->GetV8Context()));

  if (!value_args.get())
    return v8::False();

  // FIXME(tmpsantos): We could serialize base::Value if it had
  // param traits for it. Instead, we always add it to a list.
  base::ListValue list_value_args;
  list_value_args.Append(value_args.release());

  std::string extension(*v8::String::Utf8Value(args[0]));
  if (!handler->PostMessageToExtension(extension, list_value_args))
    return v8::False();
  return v8::True();
}

v8::Handle<v8::Value> XWalkExtensionV8Wrapper::SendSyncMessage(
    const v8::Arguments& args) {
  if (args.Length() != 2)
    return v8::False();

  std::string extension(*v8::String::Utf8Value(args[0]));
  std::string msg(*v8::String::Utf8Value(args[1]));

  XWalkExtensionRenderViewHandler* handler =
      XWalkExtensionRenderViewHandler::GetForCurrentContext();
  std::string reply = handler->SendSyncMessageToExtension(extension, msg);
  return v8::String::New(reply.c_str(), reply.size());
}

XWalkExtensionRendererController::XWalkExtensionRendererController() {
  content::RenderThread* thread = content::RenderThread::Get();
  thread->AddObserver(this);
  thread->RegisterExtension(new XWalkExtensionV8Wrapper);
}

XWalkExtensionRendererController::~XWalkExtensionRendererController() {
  content::RenderThread::Get()->RemoveObserver(this);
}

void XWalkExtensionRendererController::RenderViewCreated(
    content::RenderView* render_view) {
  // RenderView will own this object.
  new XWalkExtensionRenderViewHandler(render_view, this);
}

void XWalkExtensionRendererController::DidCreateScriptContext(
    WebKit::WebFrame* frame) {
  InstallJavaScriptAPIs(frame);
}

bool XWalkExtensionRendererController::OnControlMessageReceived(
    const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(XWalkExtensionRendererController, message)
    IPC_MESSAGE_HANDLER(XWalkViewMsg_RegisterExtension, OnRegisterExtension)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void XWalkExtensionRendererController::OnRegisterExtension(
    const std::string& extension, const std::string& api) {
  extension_apis_[extension] = api;
}

bool XWalkExtensionRendererController::ContainsExtension(
    const std::string& extension) const {
  return extension_apis_.find(extension) != extension_apis_.end();
}

static std::string CodeToEnsureNamespace(
    const std::string& extension_name) {
  std::string result;
  size_t pos = 0;
  while (true) {
    pos = extension_name.find('.', pos);
    if (pos == std::string::npos) {
      result += extension_name + " = {};";
      break;
    }
    std::string ns = extension_name.substr(0, pos);
    result += ns + " = " + ns + " || {}; ";
    pos++;
  }
  return result;
}

static std::string WrapAPICode(const std::string& api_code,
                               const std::string& extension_name) {
  // FIXME(cmarcelo): New extension.postMessage and extension.setMessageListener
  // should be implemented in a way that we don't need to expose
  // xwalk.postMessage and xwalk.setMessageListener.

  // We take care here to make sure that line numbering for api_code after
  // wrapping doesn't change, so that syntax errors point to the correct line.
  const char* name = extension_name.c_str();

  // Note that we are using the Post to indicate an asynchronous call and the
  // term Send to indicate synchronous call.
  //
  // FIXME(cmarcelo): For now it is disabled on Windows because we jump through
  // the UI process and this is not supported in that platform. See issue
  // https://github.com/otcshare/crosswalk/issues/268 for details.
  return base::StringPrintf(
      "var %s; (function(exports, extension) {'use strict'; %s\n})"
      "(%s, "
      "{ postMessage: function(msg) { xwalk.postMessage('%s', msg); },"
      "  setMessageListener: function(listener) { "
      "                        xwalk.setMessageListener('%s', listener); }"
#if !defined(OS_WIN)
      "  , internal: {"
      "    sendSyncMessage: function(msg) {"
      "      return xwalk.sendSyncMessage('%s', msg); }"
      "  }"
#endif
      "});",
      CodeToEnsureNamespace(extension_name).c_str(),
      api_code.c_str(),
      name, name, name
#if !defined(OS_WIN)
      , name
#endif
      );
}

void XWalkExtensionRendererController::InstallJavaScriptAPIs(
    WebKit::WebFrame* frame) {
  // FIXME(cmarcelo): Load extensions sorted by name so parent comes first, so
  // that we can safely register all them.
  ExtensionAPIMap::const_iterator it = extension_apis_.begin();
  for (; it != extension_apis_.end(); ++it) {
    const std::string& extension_name = it->first;
    const std::string& api_code = it->second;
    if (!api_code.empty()) {
      std::string wrapped_api_code = WrapAPICode(api_code, extension_name);
      frame->executeScript(WebKit::WebScriptSource(
          WebKit::WebString::fromUTF8(wrapped_api_code),
          WebKit::WebURL("JS API code for " + extension_name,
                         url_parse::Parsed(), false)));
    }
  }
}

}  // namespace extensions
}  // namespace xwalk
<commit_msg>Make lint.py ignore a closing parentheses<commit_after>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/extensions/renderer/xwalk_extension_renderer_controller.h"

#include "base/stringprintf.h"
#include "base/values.h"
#include "xwalk/extensions/common/xwalk_extension_messages.h"
#include "xwalk/extensions/renderer/xwalk_extension_render_view_handler.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
#include "v8/include/v8.h"

// This will be generated from xwalk_api.js.
extern const char kSource_xwalk_api[];

namespace xwalk {
namespace extensions {

class XWalkExtensionV8Wrapper : public v8::Extension {
 public:
  XWalkExtensionV8Wrapper();

  // v8::Extension implementation.
  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
      v8::Handle<v8::String> name);

 private:
  static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args);
  static v8::Handle<v8::Value> SendSyncMessage(const v8::Arguments& args);
};

XWalkExtensionV8Wrapper::XWalkExtensionV8Wrapper()
    : v8::Extension("xwalk", kSource_xwalk_api) {
}

v8::Handle<v8::FunctionTemplate>
XWalkExtensionV8Wrapper::GetNativeFunction(v8::Handle<v8::String> name) {
  if (name->Equals(v8::String::New("PostMessage")))
    return v8::FunctionTemplate::New(PostMessage);
  if (name->Equals(v8::String::New("SendSyncMessage")))
    return v8::FunctionTemplate::New(SendSyncMessage);
  return v8::Handle<v8::FunctionTemplate>();
}

v8::Handle<v8::Value> XWalkExtensionV8Wrapper::PostMessage(
    const v8::Arguments& args) {
  if (args.Length() != 2)
    return v8::False();

  XWalkExtensionRenderViewHandler* handler =
      XWalkExtensionRenderViewHandler::GetForCurrentContext();

  scoped_ptr<content::V8ValueConverter> converter(
      content::V8ValueConverter::create());
  scoped_ptr<base::Value> value_args(
      converter->FromV8Value(args[1], handler->GetV8Context()));

  if (!value_args.get())
    return v8::False();

  // FIXME(tmpsantos): We could serialize base::Value if it had
  // param traits for it. Instead, we always add it to a list.
  base::ListValue list_value_args;
  list_value_args.Append(value_args.release());

  std::string extension(*v8::String::Utf8Value(args[0]));
  if (!handler->PostMessageToExtension(extension, list_value_args))
    return v8::False();
  return v8::True();
}

v8::Handle<v8::Value> XWalkExtensionV8Wrapper::SendSyncMessage(
    const v8::Arguments& args) {
  if (args.Length() != 2)
    return v8::False();

  std::string extension(*v8::String::Utf8Value(args[0]));
  std::string msg(*v8::String::Utf8Value(args[1]));

  XWalkExtensionRenderViewHandler* handler =
      XWalkExtensionRenderViewHandler::GetForCurrentContext();
  std::string reply = handler->SendSyncMessageToExtension(extension, msg);
  return v8::String::New(reply.c_str(), reply.size());
}

XWalkExtensionRendererController::XWalkExtensionRendererController() {
  content::RenderThread* thread = content::RenderThread::Get();
  thread->AddObserver(this);
  thread->RegisterExtension(new XWalkExtensionV8Wrapper);
}

XWalkExtensionRendererController::~XWalkExtensionRendererController() {
  content::RenderThread::Get()->RemoveObserver(this);
}

void XWalkExtensionRendererController::RenderViewCreated(
    content::RenderView* render_view) {
  // RenderView will own this object.
  new XWalkExtensionRenderViewHandler(render_view, this);
}

void XWalkExtensionRendererController::DidCreateScriptContext(
    WebKit::WebFrame* frame) {
  InstallJavaScriptAPIs(frame);
}

bool XWalkExtensionRendererController::OnControlMessageReceived(
    const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(XWalkExtensionRendererController, message)
    IPC_MESSAGE_HANDLER(XWalkViewMsg_RegisterExtension, OnRegisterExtension)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void XWalkExtensionRendererController::OnRegisterExtension(
    const std::string& extension, const std::string& api) {
  extension_apis_[extension] = api;
}

bool XWalkExtensionRendererController::ContainsExtension(
    const std::string& extension) const {
  return extension_apis_.find(extension) != extension_apis_.end();
}

static std::string CodeToEnsureNamespace(
    const std::string& extension_name) {
  std::string result;
  size_t pos = 0;
  while (true) {
    pos = extension_name.find('.', pos);
    if (pos == std::string::npos) {
      result += extension_name + " = {};";
      break;
    }
    std::string ns = extension_name.substr(0, pos);
    result += ns + " = " + ns + " || {}; ";
    pos++;
  }
  return result;
}

static std::string WrapAPICode(const std::string& api_code,
                               const std::string& extension_name) {
  // FIXME(cmarcelo): New extension.postMessage and extension.setMessageListener
  // should be implemented in a way that we don't need to expose
  // xwalk.postMessage and xwalk.setMessageListener.

  // We take care here to make sure that line numbering for api_code after
  // wrapping doesn't change, so that syntax errors point to the correct line.
  const char* name = extension_name.c_str();

  // Note that we are using the Post to indicate an asynchronous call and the
  // term Send to indicate synchronous call.
  //
  // FIXME(cmarcelo): For now it is disabled on Windows because we jump through
  // the UI process and this is not supported in that platform. See issue
  // https://github.com/otcshare/crosswalk/issues/268 for details.
  return base::StringPrintf(
      "var %s; (function(exports, extension) {'use strict'; %s\n})"
      "(%s, "
      "{ postMessage: function(msg) { xwalk.postMessage('%s', msg); },"
      "  setMessageListener: function(listener) { "
      "                        xwalk.setMessageListener('%s', listener); }"
#if !defined(OS_WIN)
      "  , internal: {"
      "    sendSyncMessage: function(msg) {"
      "      return xwalk.sendSyncMessage('%s', msg); }"
      "  }"
#endif
      "});",
      CodeToEnsureNamespace(extension_name).c_str(),
      api_code.c_str(),
      name, name, name
#if !defined(OS_WIN)
      , name
#endif
      ); // NOLINT
}

void XWalkExtensionRendererController::InstallJavaScriptAPIs(
    WebKit::WebFrame* frame) {
  // FIXME(cmarcelo): Load extensions sorted by name so parent comes first, so
  // that we can safely register all them.
  ExtensionAPIMap::const_iterator it = extension_apis_.begin();
  for (; it != extension_apis_.end(); ++it) {
    const std::string& extension_name = it->first;
    const std::string& api_code = it->second;
    if (!api_code.empty()) {
      std::string wrapped_api_code = WrapAPICode(api_code, extension_name);
      frame->executeScript(WebKit::WebScriptSource(
          WebKit::WebString::fromUTF8(wrapped_api_code),
          WebKit::WebURL("JS API code for " + extension_name,
                         url_parse::Parsed(), false)));
    }
  }
}

}  // namespace extensions
}  // namespace xwalk
<|endoftext|>


<commit_before>/*

Copyright (c) 2006-2014, 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 <boost/version.hpp>
#include <boost/bind.hpp>
#include "libtorrent/assert.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/file_storage.hpp" // for file_entry

namespace libtorrent
{
	file_pool::file_pool(int size)
		: m_size(size)
		, m_low_prio_io(true)
	{
	}

	file_pool::~file_pool()
	{
	}

#ifdef TORRENT_WINDOWS
	void set_low_priority(file_handle const& f)
	{
		// file prio is only supported on vista and up
		// so load the functions dynamically
		typedef enum _FILE_INFO_BY_HANDLE_CLASS {
			FileBasicInfo,
			FileStandardInfo,
			FileNameInfo,
			FileRenameInfo,
			FileDispositionInfo,
			FileAllocationInfo,
			FileEndOfFileInfo,
			FileStreamInfo,
			FileCompressionInfo,
			FileAttributeTagInfo,
			FileIdBothDirectoryInfo,
			FileIdBothDirectoryRestartInfo,
			FileIoPriorityHintInfo,
			FileRemoteProtocolInfo,
			MaximumFileInfoByHandleClass
		} FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;

		typedef enum _PRIORITY_HINT {
			IoPriorityHintVeryLow = 0,
			IoPriorityHintLow,
			IoPriorityHintNormal,
			MaximumIoPriorityHintType
		} PRIORITY_HINT;

		typedef struct _FILE_IO_PRIORITY_HINT_INFO {
			PRIORITY_HINT PriorityHint;
		} FILE_IO_PRIORITY_HINT_INFO, *PFILE_IO_PRIORITY_HINT_INFO;

		typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
		static SetFileInformationByHandle_t SetFileInformationByHandle = NULL;

		static bool failed_kernel_load = false;

		if (failed_kernel_load) return;

		if (SetFileInformationByHandle == NULL)
		{
			HMODULE kernel32 = LoadLibraryA("kernel32.dll");
			if (kernel32 == NULL)
			{
				failed_kernel_load = true;
				return;
			}

			SetFileInformationByHandle = (SetFileInformationByHandle_t)GetProcAddress(kernel32, "SetFileInformationByHandle");
			if (SetFileInformationByHandle == NULL)
			{
				failed_kernel_load = true;
				return;
			}
		}

		TORRENT_ASSERT(SetFileInformationByHandle);

		FILE_IO_PRIORITY_HINT_INFO io_hint;
		io_hint.PriorityHint = IoPriorityHintLow;
		SetFileInformationByHandle(f->native_handle(),
			FileIoPriorityHintInfo, &io_hint, sizeof(io_hint));
	}
#endif // TORRENT_WINDOWS

	file_handle file_pool::open_file(void* st, std::string const& p
		, int file_index, file_storage const& fs, int m, error_code& ec)
	{
		mutex::scoped_lock l(m_mutex);

#if TORRENT_USE_ASSERTS
		// we're not allowed to open a file
		// from a deleted storage!
		TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end(), std::make_pair(fs.name(), (void const*)&fs))
			== m_deleted_storages.end());
#endif

		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(is_complete(p));
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		file_set::iterator i = m_files.find(std::make_pair(st, file_index));
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = errors::file_collision;
#endif
				return file_handle();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if ((((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
				|| (e.mode & file::random_access) != (m & file::random_access))
			{
				// close the file before we open it with
				// the new read/write privilages, since windows may
				// file opening a file twice. However, since there may
				// be outstanding operations on it, we can't close the
				// file, we can only delete our reference to it.
				// if this is the only reference to the file, it will be closed
				e.file_ptr = boost::make_shared<file>();

				std::string full_path = fs.file_path(file_index, p);
				if (!e.file_ptr->open(full_path, m, ec))
				{
					m_files.erase(i);
					return file_handle();
				}
#ifdef TORRENT_WINDOWS
				if (m_low_prio_io)
					set_low_priority(e.file_ptr);
#endif

				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			return e.file_ptr;
		}

		lru_file_entry e;
		e.file_ptr = boost::make_shared<file>();
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		std::string full_path = fs.file_path(file_index, p);
		if (!e.file_ptr->open(full_path, m, ec))
			return file_handle();
#ifdef TORRENT_WINDOWS
		if (m_low_prio_io)
			set_low_priority(e.file_ptr);
#endif
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(std::make_pair(st, file_index), e));
		TORRENT_ASSERT(e.file_ptr->is_open());

		file_handle file_ptr = e.file_ptr;

		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest(l);
		}
		return file_ptr;
	}

	void file_pool::get_status(std::vector<pool_file_status>* files, void* st) const
	{
		mutex::scoped_lock l(m_mutex);

		file_set::const_iterator start = m_files.lower_bound(std::make_pair(st, 0));
		file_set::const_iterator end = m_files.upper_bound(std::make_pair(st, INT_MAX));

		for (file_set::const_iterator i = start; i != end; ++i)
		{
			pool_file_status s;
			s.file_index = i->first.second;
			s.open_mode = i->second.mode;
			s.last_use = i->second.last_use;
			files->push_back(s);
		}
	}

	void file_pool::remove_oldest(mutex::scoped_lock& l)
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;

		file_handle file_ptr = i->second.file_ptr;
		m_files.erase(i);

		// closing a file may be long running operation (mac os x)
		l.unlock();
		file_ptr.reset();
		l.lock();
	}

	void file_pool::release(void* st, int file_index)
	{
		mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(std::make_pair(st, file_index));
		if (i == m_files.end()) return;

		file_handle file_ptr = i->second.file_ptr;
		m_files.erase(i);

		// closing a file may be long running operation (mac os x)
		l.unlock();
		file_ptr.reset();
	}

	// closes files belonging to the specified
	// storage. If 0 is passed, all files are closed
	void file_pool::release(void* st)
	{
		mutex::scoped_lock l(m_mutex);

		if (st == 0)
		{
			file_set tmp;
			tmp.swap(m_files);
			l.unlock();
			return;
		}

		std::vector<file_handle> to_close;
		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
			{
				to_close.push_back(i->second.file_ptr);
				m_files.erase(i++);
			}
			else
				++i;
		}
		l.unlock();
		// the files are closed here
	}

#if TORRENT_USE_ASSERTS
	void file_pool::mark_deleted(file_storage const& fs)
	{
		mutex::scoped_lock l(m_mutex);
		m_deleted_storages.push_back(std::make_pair(fs.name(), (void const*)&fs));
		if(m_deleted_storages.size() > 100)
			m_deleted_storages.erase(m_deleted_storages.begin());
	}

	bool file_pool::assert_idle_files(void* st) const
	{
		mutex::scoped_lock l(m_mutex);

		for (file_set::const_iterator i = m_files.begin();
			i != m_files.end(); ++i)
		{
			if (i->second.key == st && !i->second.file_ptr.unique())
				return false;
		}
		return true;
	}
#endif

	void file_pool::resize(int size)
	{
		mutex::scoped_lock l(m_mutex);

		TORRENT_ASSERT(size > 0);

		if (size == m_size) return;
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest(l);
	}

}

<commit_msg>move closing of files outside of file pool mutex<commit_after>/*

Copyright (c) 2006-2014, 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 <boost/version.hpp>
#include <boost/bind.hpp>
#include "libtorrent/assert.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/file_storage.hpp" // for file_entry

namespace libtorrent
{
	file_pool::file_pool(int size)
		: m_size(size)
		, m_low_prio_io(true)
	{
	}

	file_pool::~file_pool()
	{
	}

#ifdef TORRENT_WINDOWS
	void set_low_priority(file_handle const& f)
	{
		// file prio is only supported on vista and up
		// so load the functions dynamically
		typedef enum _FILE_INFO_BY_HANDLE_CLASS {
			FileBasicInfo,
			FileStandardInfo,
			FileNameInfo,
			FileRenameInfo,
			FileDispositionInfo,
			FileAllocationInfo,
			FileEndOfFileInfo,
			FileStreamInfo,
			FileCompressionInfo,
			FileAttributeTagInfo,
			FileIdBothDirectoryInfo,
			FileIdBothDirectoryRestartInfo,
			FileIoPriorityHintInfo,
			FileRemoteProtocolInfo,
			MaximumFileInfoByHandleClass
		} FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;

		typedef enum _PRIORITY_HINT {
			IoPriorityHintVeryLow = 0,
			IoPriorityHintLow,
			IoPriorityHintNormal,
			MaximumIoPriorityHintType
		} PRIORITY_HINT;

		typedef struct _FILE_IO_PRIORITY_HINT_INFO {
			PRIORITY_HINT PriorityHint;
		} FILE_IO_PRIORITY_HINT_INFO, *PFILE_IO_PRIORITY_HINT_INFO;

		typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
		static SetFileInformationByHandle_t SetFileInformationByHandle = NULL;

		static bool failed_kernel_load = false;

		if (failed_kernel_load) return;

		if (SetFileInformationByHandle == NULL)
		{
			HMODULE kernel32 = LoadLibraryA("kernel32.dll");
			if (kernel32 == NULL)
			{
				failed_kernel_load = true;
				return;
			}

			SetFileInformationByHandle = (SetFileInformationByHandle_t)GetProcAddress(kernel32, "SetFileInformationByHandle");
			if (SetFileInformationByHandle == NULL)
			{
				failed_kernel_load = true;
				return;
			}
		}

		TORRENT_ASSERT(SetFileInformationByHandle);

		FILE_IO_PRIORITY_HINT_INFO io_hint;
		io_hint.PriorityHint = IoPriorityHintLow;
		SetFileInformationByHandle(f->native_handle(),
			FileIoPriorityHintInfo, &io_hint, sizeof(io_hint));
	}
#endif // TORRENT_WINDOWS

	file_handle file_pool::open_file(void* st, std::string const& p
		, int file_index, file_storage const& fs, int m, error_code& ec)
	{
		// potentially used to hold a reference to a file object that's
		// about to be destructed. If we have such object we assign it to
		// this member to be destructed after we release the mutex. On some
		// operating systems (such as OSX) closing a file may take a long
		// time. We don't want to hold the mutex for that.
		file_handle defer_destruction;

		mutex::scoped_lock l(m_mutex);

#if TORRENT_USE_ASSERTS
		// we're not allowed to open a file
		// from a deleted storage!
		TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end(), std::make_pair(fs.name(), (void const*)&fs))
			== m_deleted_storages.end());
#endif

		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(is_complete(p));
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		file_set::iterator i = m_files.find(std::make_pair(st, file_index));
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = errors::file_collision;
#endif
				return file_handle();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if ((((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
				|| (e.mode & file::random_access) != (m & file::random_access))
			{
				// close the file before we open it with
				// the new read/write privilages, since windows may
				// file opening a file twice. However, since there may
				// be outstanding operations on it, we can't close the
				// file, we can only delete our reference to it.
				// if this is the only reference to the file, it will be closed
				defer_destruction = e.file_ptr;
				e.file_ptr = boost::make_shared<file>();

				std::string full_path = fs.file_path(file_index, p);
				if (!e.file_ptr->open(full_path, m, ec))
				{
					m_files.erase(i);
					return file_handle();
				}
#ifdef TORRENT_WINDOWS
				if (m_low_prio_io)
					set_low_priority(e.file_ptr);
#endif

				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			return e.file_ptr;
		}

		lru_file_entry e;
		e.file_ptr = boost::make_shared<file>();
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		std::string full_path = fs.file_path(file_index, p);
		if (!e.file_ptr->open(full_path, m, ec))
			return file_handle();
#ifdef TORRENT_WINDOWS
		if (m_low_prio_io)
			set_low_priority(e.file_ptr);
#endif
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(std::make_pair(st, file_index), e));
		TORRENT_ASSERT(e.file_ptr->is_open());

		file_handle file_ptr = e.file_ptr;

		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest(l);
		}
		return file_ptr;
	}

	void file_pool::get_status(std::vector<pool_file_status>* files, void* st) const
	{
		mutex::scoped_lock l(m_mutex);

		file_set::const_iterator start = m_files.lower_bound(std::make_pair(st, 0));
		file_set::const_iterator end = m_files.upper_bound(std::make_pair(st, INT_MAX));

		for (file_set::const_iterator i = start; i != end; ++i)
		{
			pool_file_status s;
			s.file_index = i->first.second;
			s.open_mode = i->second.mode;
			s.last_use = i->second.last_use;
			files->push_back(s);
		}
	}

	void file_pool::remove_oldest(mutex::scoped_lock& l)
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;

		file_handle file_ptr = i->second.file_ptr;
		m_files.erase(i);

		// closing a file may be long running operation (mac os x)
		l.unlock();
		file_ptr.reset();
		l.lock();
	}

	void file_pool::release(void* st, int file_index)
	{
		mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(std::make_pair(st, file_index));
		if (i == m_files.end()) return;

		file_handle file_ptr = i->second.file_ptr;
		m_files.erase(i);

		// closing a file may be long running operation (mac os x)
		l.unlock();
		file_ptr.reset();
	}

	// closes files belonging to the specified
	// storage. If 0 is passed, all files are closed
	void file_pool::release(void* st)
	{
		mutex::scoped_lock l(m_mutex);

		if (st == 0)
		{
			file_set tmp;
			tmp.swap(m_files);
			l.unlock();
			return;
		}

		std::vector<file_handle> to_close;
		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
			{
				to_close.push_back(i->second.file_ptr);
				m_files.erase(i++);
			}
			else
				++i;
		}
		l.unlock();
		// the files are closed here
	}

#if TORRENT_USE_ASSERTS
	void file_pool::mark_deleted(file_storage const& fs)
	{
		mutex::scoped_lock l(m_mutex);
		m_deleted_storages.push_back(std::make_pair(fs.name(), (void const*)&fs));
		if(m_deleted_storages.size() > 100)
			m_deleted_storages.erase(m_deleted_storages.begin());
	}

	bool file_pool::assert_idle_files(void* st) const
	{
		mutex::scoped_lock l(m_mutex);

		for (file_set::const_iterator i = m_files.begin();
			i != m_files.end(); ++i)
		{
			if (i->second.key == st && !i->second.file_ptr.unique())
				return false;
		}
		return true;
	}
#endif

	void file_pool::resize(int size)
	{
		mutex::scoped_lock l(m_mutex);

		TORRENT_ASSERT(size > 0);

		if (size == m_size) return;
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest(l);
	}

}

<|endoftext|>