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

  This file is distributed under the MIT License.
  See https://github.com/morzhovets/momo/blob/master/LICENSE
  for details.

  tests/SimpleTreeTester.cpp

\**********************************************************/

#include "pch.h"
#include "TestSettings.h"

#ifdef TEST_SIMPLE_TREE

#undef NDEBUG

#include "../../momo/TreeSet.h"
#include "../../momo/TreeMap.h"
#include "../../momo/stdish/pool_allocator.h"

#include <string>
#include <iostream>
#include <random>
#include <set>

class SimpleTreeTester
{
public:
	static void TestStrAll()
	{
		std::cout << "momo::TreeSet: " << std::flush;
		TestStrTreeSet();
		std::cout << "ok" << std::endl;

		std::cout << "momo::TreeMap: " << std::flush;
		TestStrTreeMap();
		std::cout << "ok" << std::endl;
	}

	static void TestStrTreeSet()
	{
		typedef momo::TreeSet<std::string> TreeSet;

		std::string s1 = "s1";
		std::string s2 = "s2";

		TreeSet set = { s2, "s3" };
		set.InsertVar(s1, "s1");

		assert(set.GetCount() == 3);
		assert(set.ContainsKey(s1));
		assert(set.ContainsKey("s2"));

		set.ResetKey(set.GetLowerBound("s1"), s1);
		set.ResetKey(set.GetUpperBound(s1), "s2");

		const auto es = set.Extract(set.Find("s1"));
		assert(es.GetItem() == s1);

		assert(set.GetCount() == 2);
		assert(*set.GetBegin() == s2);
		assert(*std::prev(set.GetEnd()) == "s3");

		TreeSet set2;
		set2 = set;
		assert(std::equal(set.GetBegin(), set.GetEnd(), set2.GetBegin()));
	}

	static void TestStrTreeMap()
	{
		typedef momo::TreeMap<std::string, std::string> TreeMap;
		typedef TreeMap::ConstIterator::Reference Reference;
		auto pred = [] (Reference ref1, Reference ref2)
			{ return ref1.key == ref2.key && ref1.value == ref2.value; };

		std::string s1 = "s1";
		std::string s2 = "s2";
		std::string s3 = "s3";
		std::string s4 = "s4";

		TreeMap map = { { "s1", "s1" }, { "s2", s2 } };
		map.InsertCrt("s3", [] (void* ptr) { ::new(ptr) std::string("s3"); });
		map.InsertCrt(s4, [] (void* ptr) { ::new(ptr) std::string("s4"); });

		map.Insert("s1", "s2");
		map.Insert("s2", s3);
		map.Insert(s3, "s4");
		map.Insert(s4, s1);

		map.ResetKey(map.GetLowerBound("s1"), s1);
		map.ResetKey(map.GetUpperBound(s1), "s2");

		assert(map.GetCount() == 4);
		for (auto ref : map)
			assert(ref.key == ref.value);

		TreeMap map2;
		map2 = map;

		const auto ep = map.Extract(map.Find("s1"));
		assert(ep.GetKey() == s1 && ep.GetValue() == s1);
		assert(map.GetCount() == 3);

		map.Insert(map2.GetBegin(), std::next(map2.GetBegin()));
		assert(std::equal(map.GetBegin(), map.GetEnd(), map2.GetBegin(), pred));

		map.Clear();
		assert(map.IsEmpty());

		map.Add(map.GetLowerBound("s1"), s1, s1);
		map.Add(map.GetUpperBound("s2"), s2, "s2");
		map.Add(map.GetLowerBound(s3), "s3", s3);
		map.Add(map.GetUpperBound(s4), "s4", "s4");
		assert(std::equal(map.GetBegin(), map.GetEnd(), map2.GetBegin(), pred));
	}

	static void TestCharAll()
	{
		std::mt19937 mt;

		TestCharTreeNode3<  1, 1, 127>(mt);
		TestCharTreeNode3<  2, 1,  66>(mt);
		TestCharTreeNode3<  3, 1,  32>(mt);
		TestCharTreeNode3<  4, 1,  15>(mt);
		TestCharTreeNode3<  5, 1,   1>(mt);
		TestCharTreeNode3< 10, 1,   3>(mt);
		TestCharTreeNode3<101, 1,   2>(mt);
		TestCharTreeNode3<255, 1,   1>(mt);

		TestCharTreeNode3<  4, 2, 127>(mt);
		TestCharTreeNode3<  5, 2,  66>(mt);
		TestCharTreeNode3<  6, 2,  32>(mt);
		TestCharTreeNode3<  7, 2,  15>(mt);
		TestCharTreeNode3< 14, 3,   1>(mt);
		TestCharTreeNode3< 77, 3,   3>(mt);
		TestCharTreeNode3<121, 3,   2>(mt);
		TestCharTreeNode3<255, 3,   1>(mt);

		TestCharTreeNode3< 37,   7, 127>(mt);
		TestCharTreeNode3< 42,  15,  66>(mt);
		TestCharTreeNode3< 65,  23,  32>(mt);
		TestCharTreeNode3< 77,  30,  15>(mt);
		TestCharTreeNode3< 88,  31,   1>(mt);
		TestCharTreeNode3<104,  33,   3>(mt);
		TestCharTreeNode3<204, 100,   2>(mt);
		TestCharTreeNode3<255, 127,   1>(mt);
	}

	template<size_t maxCapacity, size_t capacityStep, size_t memPoolBlockCount>
	static void TestCharTreeNode3(std::mt19937& mt)
	{
		static const bool useSwap = (maxCapacity + capacityStep) % 2 == 0;
		TestCharTreeNode4<maxCapacity, capacityStep, memPoolBlockCount, useSwap>(mt);
	}

	template<size_t maxCapacity, size_t capacityStep, size_t memPoolBlockCount, bool useSwap>
	static void TestCharTreeNode4(std::mt19937& mt)
	{
		std::cout << "momo::TreeNode<" << maxCapacity << ", " << capacityStep << ", "
			<< memPoolBlockCount << ", " << (useSwap ? "true" : "false") << ">: " << std::flush;

		typedef momo::TreeNode<maxCapacity, capacityStep,
			momo::MemPoolParams<memPoolBlockCount>, useSwap> TreeNode;
		typedef momo::TreeSet<unsigned char, momo::TreeTraits<unsigned char, false, TreeNode>> TreeSet;

		static const size_t count = 256;
		static unsigned char array[count];
		for (size_t i = 0; i < count; ++i)
			array[i] = static_cast<unsigned char>(i);

		if (maxCapacity > 1)
		{
			for (size_t i = 0; i <= count; ++i)
			{
				TreeSet set1, set2;
				set1.Insert(array, array + i);
				set2.Insert(array + i, array + count);
				if (i > 0)
					set1.Remove(array[i - 1]);
				if (mt() % 2 == 0)
					std::swap(set1, set2);
				set1.MergeFrom(set2);
				if (i > 0)
					set1.Insert(array[i - 1]);
				assert(set1.GetCount() == count);
				assert(set2.IsEmpty());
				assert(std::equal(set1.GetBegin(), set1.GetEnd(), array));
				set2.Insert(set1.GetBegin(), set1.GetEnd());
				assert(std::equal(set2.GetBegin(), set2.GetEnd(), array));
			}
		}

		{
			std::set<unsigned char, std::less<unsigned char>,
				momo::stdish::unsynchronized_pool_allocator<unsigned char>> sset;
			TreeSet mset;

			std::shuffle(array, array + count, mt);
			for (unsigned char c : array)
			{
				sset.insert(c);
				assert(mset.Insert(c).inserted);
				assert(mset.GetCount() == sset.size());
				assert(std::equal(mset.GetBegin(), mset.GetEnd(), sset.begin()));
			}

			std::shuffle(array, array + count, mt);
			for (unsigned char c : array)
			{
				sset.erase(c);
				auto iter = mset.Find(c);
				assert(iter != mset.GetEnd());
				if (c % 2 == 0)
					mset.Remove(iter);
				else
					mset.Extract(iter);
				assert(mset.GetCount() == sset.size());
				assert(std::equal(mset.GetBegin(), mset.GetEnd(), sset.begin()));
			}

			assert(mset.IsEmpty());
			mset.Insert(128);
			assert(mset.GetCount() == 1);
		}

		std::cout << "ok" << std::endl;
	}
};

static int testSimpleTree = (SimpleTreeTester::TestStrAll(), SimpleTreeTester::TestCharAll(), 0);

#endif // TEST_SIMPLE_TREE
<commit_msg>SimpleTreeTester<commit_after>/**********************************************************\

  This file is distributed under the MIT License.
  See https://github.com/morzhovets/momo/blob/master/LICENSE
  for details.

  tests/SimpleTreeTester.cpp

\**********************************************************/

#include "pch.h"
#include "TestSettings.h"

#ifdef TEST_SIMPLE_TREE

#undef NDEBUG

#include "../../momo/TreeSet.h"
#include "../../momo/TreeMap.h"
#include "../../momo/stdish/pool_allocator.h"

#include <string>
#include <iostream>
#include <random>
#include <map>

class SimpleTreeTester
{
private:
	template<bool isNothrowMoveConstructible, bool isNothrowSwappable, bool isNothrowCopyAssignable>
	class TemplItem
	{
	public:
		explicit TemplItem(unsigned char c = unsigned char{0}) noexcept
			: mChar(c)
		{
		}

		TemplItem(TemplItem&& item) noexcept(isNothrowMoveConstructible)
			: mChar(item.mChar)
		{
		}

		TemplItem(const TemplItem& item) noexcept(false)
			: mChar(item.mChar)
		{
		}

		~TemplItem() = default;

		//TemplItem& operator=(TemplItem&& item) = delete;

		TemplItem& operator=(const TemplItem& item) noexcept(isNothrowCopyAssignable)
		{
			mChar = item.mChar;
			return *this;
		}

		friend void swap(TemplItem& item1, TemplItem& item2) noexcept(isNothrowSwappable)
		{
			std::swap(item1.mChar, item2.mChar);
		}

		bool operator==(const TemplItem& item) const noexcept
		{
			return mChar == item.mChar;
		}

		bool operator<(const TemplItem& item) const noexcept
		{
			return mChar < item.mChar;
		}

	private:
		unsigned char mChar;
	};

public:
	static void TestStrAll()
	{
		std::cout << "momo::TreeSet: " << std::flush;
		TestStrTreeSet();
		std::cout << "ok" << std::endl;

		std::cout << "momo::TreeMap: " << std::flush;
		TestStrTreeMap();
		std::cout << "ok" << std::endl;
	}

	static void TestStrTreeSet()
	{
		typedef momo::TreeSet<std::string> TreeSet;

		std::string s1 = "s1";
		std::string s2 = "s2";

		TreeSet set = { s2, "s3" };
		set.InsertVar(s1, "s1");

		assert(set.GetCount() == 3);
		assert(set.ContainsKey(s1));
		assert(set.ContainsKey("s2"));

		set.ResetKey(set.GetLowerBound("s1"), s1);
		set.ResetKey(set.GetUpperBound(s1), "s2");

		const auto es = set.Extract(set.Find("s1"));
		assert(es.GetItem() == s1);

		assert(set.GetCount() == 2);
		assert(*set.GetBegin() == s2);
		assert(*std::prev(set.GetEnd()) == "s3");

		TreeSet set2;
		set2 = set;
		assert(std::equal(set.GetBegin(), set.GetEnd(), set2.GetBegin()));
	}

	static void TestStrTreeMap()
	{
		typedef momo::TreeMap<std::string, std::string> TreeMap;
		typedef TreeMap::ConstIterator::Reference Reference;
		auto pred = [] (Reference ref1, Reference ref2)
			{ return ref1.key == ref2.key && ref1.value == ref2.value; };

		std::string s1 = "s1";
		std::string s2 = "s2";
		std::string s3 = "s3";
		std::string s4 = "s4";

		TreeMap map = { { "s1", "s1" }, { "s2", s2 } };
		map.InsertCrt("s3", [] (void* ptr) { ::new(ptr) std::string("s3"); });
		map.InsertCrt(s4, [] (void* ptr) { ::new(ptr) std::string("s4"); });

		map.Insert("s1", "s2");
		map.Insert("s2", s3);
		map.Insert(s3, "s4");
		map.Insert(s4, s1);

		map.ResetKey(map.GetLowerBound("s1"), s1);
		map.ResetKey(map.GetUpperBound(s1), "s2");

		assert(map.GetCount() == 4);
		for (auto ref : map)
			assert(ref.key == ref.value);

		TreeMap map2;
		map2 = map;

		const auto ep = map.Extract(map.Find("s1"));
		assert(ep.GetKey() == s1 && ep.GetValue() == s1);
		assert(map.GetCount() == 3);

		map.Insert(map2.GetBegin(), std::next(map2.GetBegin()));
		assert(std::equal(map.GetBegin(), map.GetEnd(), map2.GetBegin(), pred));

		map.Clear();
		assert(map.IsEmpty());

		map.Add(map.GetLowerBound("s1"), s1, s1);
		map.Add(map.GetUpperBound("s2"), s2, "s2");
		map.Add(map.GetLowerBound(s3), "s3", s3);
		map.Add(map.GetUpperBound(s4), "s4", "s4");
		assert(std::equal(map.GetBegin(), map.GetEnd(), map2.GetBegin(), pred));
	}

	static void TestTemplAll()
	{
		std::mt19937 mt;

		TestTemplTreeNode<  1, 1, 127, 0, 0>(mt);
		TestTemplTreeNode<  2, 1,  66, 0, 1>(mt);
		TestTemplTreeNode<  3, 1,  32, 0, 2>(mt);
		TestTemplTreeNode<  4, 1,  15, 0, 3>(mt);
		TestTemplTreeNode<  5, 1,   1, 1, 0>(mt);
		TestTemplTreeNode< 10, 1,   3, 1, 1>(mt);
		TestTemplTreeNode<101, 1,   2, 1, 2>(mt);
		TestTemplTreeNode<255, 1,   1, 1, 3>(mt);

		TestTemplTreeNode<  4, 2, 127, 2, 0>(mt);
		TestTemplTreeNode<  5, 2,  66, 2, 1>(mt);
		TestTemplTreeNode<  6, 2,  32, 2, 2>(mt);
		TestTemplTreeNode<  7, 2,  15, 2, 3>(mt);
		TestTemplTreeNode< 14, 3,   1, 3, 0>(mt);
		TestTemplTreeNode< 77, 3,   3, 3, 1>(mt);
		TestTemplTreeNode<121, 3,   2, 3, 2>(mt);
		TestTemplTreeNode<255, 3,   1, 3, 3>(mt);

		TestTemplTreeNode< 37,   7, 127, 3, 3>(mt);
		TestTemplTreeNode< 42,  15,  66, 3, 3>(mt);
		TestTemplTreeNode< 65,  23,  32, 3, 3>(mt);
		TestTemplTreeNode< 77,  30,  15, 3, 3>(mt);
		TestTemplTreeNode< 88,  31,   1, 3, 3>(mt);
		TestTemplTreeNode<104,  33,   3, 3, 3>(mt);
		TestTemplTreeNode<204, 100,   2, 3, 3>(mt);
		TestTemplTreeNode<255, 127,   1, 3, 3>(mt);
	}

	template<size_t maxCapacity, size_t capacityStep, size_t memPoolBlockCount,
		size_t keyTraits, size_t valueTraits>
	static void TestTemplTreeNode(std::mt19937& mt)
	{
		std::cout << "momo::TreeNode<" << maxCapacity << ", " << capacityStep << ", "
			<< memPoolBlockCount << ">: " << std::flush;

		typedef momo::TreeNode<maxCapacity, capacityStep,
			momo::MemPoolParams<memPoolBlockCount>> TreeNode;

		static const size_t count = 256;
		static unsigned char array[count];
		for (size_t i = 0; i < count; ++i)
			array[i] = static_cast<unsigned char>(i);

		if (maxCapacity > 1)
		{
			typedef momo::TreeSet<unsigned char,
				momo::TreeTraits<unsigned char, false, TreeNode>> TreeSet;

			for (size_t i = 0; i <= count; ++i)
			{
				TreeSet set1, set2;
				set1.Insert(array, array + i);
				set2.Insert(array + i, array + count);
				if (i > 0)
					set1.Remove(array[i - 1]);
				if (mt() % 2 == 0)
					std::swap(set1, set2);
				set1.MergeFrom(set2);
				if (i > 0)
					set1.Insert(array[i - 1]);
				assert(set1.GetCount() == count);
				assert(set2.IsEmpty());
				assert(std::equal(set1.GetBegin(), set1.GetEnd(), array));
				set2.Insert(set1.GetBegin(), set1.GetEnd());
				assert(std::equal(set2.GetBegin(), set2.GetEnd(), array));
			}
		}

		{
			typedef TemplItem<(keyTraits < 2), (keyTraits % 2 == 0), false> Key;
			typedef TemplItem<(valueTraits < 2), (valueTraits % 2 == 0), false> Value;

			typedef momo::TreeTraits<Key, false, TreeNode, true> TreeTraits;
			typedef momo::TreeMap<Key, Value, TreeTraits> TreeMap;
			typedef typename TreeMap::ConstIterator::Reference ConstReference;

			std::map<Key, Value, std::less<Key>,
				momo::stdish::unsynchronized_pool_allocator<std::pair<const Key, Value>>> smap;
			TreeMap map;

			auto isEqual = [] (ConstReference ref, const std::pair<const Key, Value>& sref)
				{ return ref.key == sref.first && ref.value == sref.second; };

			for (int t = 0; t < 2; ++t)
			{
				std::shuffle(array, array + count, mt);
				for (unsigned char c : array)
				{
					smap.insert({ Key(c), Value(c) });
					assert(map.Insert(Key(c), Value(c)).inserted);
					assert(map.GetCount() == smap.size());
					assert(std::equal(map.GetBegin(), map.GetEnd(), smap.begin(), isEqual));
				}

				std::shuffle(array, array + count, mt);
				for (unsigned char c : array)
				{
					smap.erase(Key(c));
					auto iter = map.Find(Key(c));
					assert(iter != map.GetEnd());
					if (t == 0)
						map.Remove(iter);
					else
						map.Extract(iter);
					assert(map.GetCount() == smap.size());
					assert(std::equal(map.GetBegin(), map.GetEnd(), smap.begin(), isEqual));
				}
			}
		}

		std::cout << "ok" << std::endl;
	}
};

static int testSimpleTree = (SimpleTreeTester::TestStrAll(), SimpleTreeTester::TestTemplAll(), 0);

#endif // TEST_SIMPLE_TREE
<|endoftext|>


<commit_before>
#define LIBPYTHON_CPP
#include "libpython.h"

#ifndef _WIN32
#include <dlfcn.h>
#else
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <string>
#include <iostream>
#include <sstream>

namespace libpython {

namespace {

void lastDLErrorMessage(std::string* pError)
{
#ifdef _WIN32
  LPVOID lpMsgBuf;
  DWORD dw = ::GetLastError();

  DWORD length = ::FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
      FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS,
      NULL,
      dw,
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR) &lpMsgBuf,
      0, NULL );

  if (length != 0)
  {
    std::string msg((LPTSTR)lpMsgBuf);
    LocalFree(lpMsgBuf);
    pError->assign(msg);
  }
  else
  {
    pError->assign("(Unknown error)");
  }
#else
  const char* msg = ::dlerror();
  if (msg != NULL)
    pError->assign(msg);
  else
    pError->assign("(Unknown error)");
#endif
}

bool loadLibrary(const std::string& libPath, void** ppLib, std::string* pError)
{
  *ppLib = NULL;
#ifdef _WIN32
  *ppLib = (void*)::LoadLibraryEx(libPath.c_str(), NULL, 0);
#else
  *ppLib = ::dlopen(libPath.c_str(), RTLD_NOW|RTLD_GLOBAL);
#endif
  if (*ppLib == NULL)
  {
    lastDLErrorMessage(pError);
    *pError = libPath + " - " + *pError;
    return false;
  }
  else
  {
    return true;
  }
}

bool loadSymbol(void* pLib, const std::string& name, void** ppSymbol, std::string* pError)
{
  *ppSymbol = NULL;
#ifdef _WIN32
  *ppSymbol = (void*)::GetProcAddress((HINSTANCE)pLib, name.c_str());
#else
  *ppSymbol = ::dlsym(pLib, name.c_str());
#endif
  if (*ppSymbol == NULL)
  {
    lastDLErrorMessage(pError);
    *pError = name + " - " + *pError;
    return false;
  }
  else
  {
    return true;
  }
}

bool closeLibrary(void* pLib, std::string* pError)
{
#ifdef _WIN32
  if (!::FreeLibrary((HMODULE)pLib))
#else
  if (::dlclose(pLib) != 0)
#endif
  {
    lastDLErrorMessage(pError);
    return false;
  }
  else
  {
    return true;
  }
}

} // anonymous namespace

void initialize_type_objects(bool python3) {
  Py_None = Py_BuildValue("z", NULL);
  Py_Unicode = Py_BuildValue("u", L"a");
  if (python3)
    Py_String = Py_BuildValue("y", "a");
  else
    Py_String = Py_BuildValue("s", "a");
  Py_Int = PyInt_FromLong(1024L);
  Py_Long = PyLong_FromLong(1024L);
  Py_Bool = PyBool_FromLong(1L);
  Py_True = PyBool_FromLong(1L);
  Py_False = PyBool_FromLong(0L);
  Py_Dict = Py_BuildValue("{s:i}", "a", 1024);
  Py_Float = PyFloat_FromDouble(0.0);
  Py_Tuple = Py_BuildValue("(i)", 1024);
  Py_List = Py_BuildValue("[i]", 1024);
  Py_Complex = PyComplex_FromDoubles(0.0, 0.0);
}

#define LOAD_PYTHON_SYMBOL_AS(name, as)             \
if (!loadSymbol(pLib_, #name, (void**)&as, pError)) \
  return false;

#define LOAD_PYTHON_SYMBOL(name)                                \
if (!loadSymbol(pLib_, #name, (void**) &libpython::name, pError)) \
  return false;

bool SharedLibrary::load(const std::string& libPath, bool python3, std::string* pError)
{
  if (!loadLibrary(libPath, &pLib_, pError))
    return false;

  return loadSymbols(python3, pError);
}

bool LibPython::loadSymbols(bool python3, std::string* pError)
{
  bool is64bit = sizeof(size_t) >= 8;

  LOAD_PYTHON_SYMBOL(Py_Initialize)
  LOAD_PYTHON_SYMBOL(Py_IsInitialized)
  LOAD_PYTHON_SYMBOL(Py_AddPendingCall)
  LOAD_PYTHON_SYMBOL(PyErr_SetInterrupt)
  LOAD_PYTHON_SYMBOL(PyExc_KeyboardInterrupt)
  LOAD_PYTHON_SYMBOL(Py_IncRef)
  LOAD_PYTHON_SYMBOL(Py_DecRef)
  LOAD_PYTHON_SYMBOL(PyObject_GetAttrString)
  LOAD_PYTHON_SYMBOL(PyObject_HasAttrString)
  LOAD_PYTHON_SYMBOL(PyObject_SetAttrString)
  LOAD_PYTHON_SYMBOL(PyTuple_Size)
  LOAD_PYTHON_SYMBOL(PyTuple_GetItem)
  LOAD_PYTHON_SYMBOL(PyTuple_New)
  LOAD_PYTHON_SYMBOL(PyTuple_SetItem)
  LOAD_PYTHON_SYMBOL(PyTuple_GetSlice)
  LOAD_PYTHON_SYMBOL(PyList_New)
  LOAD_PYTHON_SYMBOL(PyList_Size)
  LOAD_PYTHON_SYMBOL(PyList_GetItem)
  LOAD_PYTHON_SYMBOL(PyList_SetItem)
  LOAD_PYTHON_SYMBOL(PyErr_Fetch)
  LOAD_PYTHON_SYMBOL(PyErr_Occurred)
  LOAD_PYTHON_SYMBOL(PyErr_NormalizeException)
  LOAD_PYTHON_SYMBOL(PyErr_ExceptionMatches)
  LOAD_PYTHON_SYMBOL(PyErr_GivenExceptionMatches)
  LOAD_PYTHON_SYMBOL(PyObject_Str)
  LOAD_PYTHON_SYMBOL(PyObject_Dir)
  LOAD_PYTHON_SYMBOL(PyCallable_Check)
  LOAD_PYTHON_SYMBOL(PyRun_StringFlags)
  LOAD_PYTHON_SYMBOL(Py_CompileString)
  LOAD_PYTHON_SYMBOL(PyEval_EvalCode)
  LOAD_PYTHON_SYMBOL(PyModule_GetDict)
  LOAD_PYTHON_SYMBOL(PyImport_AddModule)
  LOAD_PYTHON_SYMBOL(PyImport_ImportModule)
  LOAD_PYTHON_SYMBOL(PyImport_Import)
  LOAD_PYTHON_SYMBOL(PyImport_GetModuleDict)
  LOAD_PYTHON_SYMBOL(PyObject_GetIter)
  LOAD_PYTHON_SYMBOL(PyIter_Next)
  LOAD_PYTHON_SYMBOL(PyLong_AsLong)
  LOAD_PYTHON_SYMBOL(PyLong_FromLong)
  LOAD_PYTHON_SYMBOL(PyBool_FromLong)
  LOAD_PYTHON_SYMBOL(PyDict_New)
  LOAD_PYTHON_SYMBOL(PyDict_Contains)
  LOAD_PYTHON_SYMBOL(PyDict_GetItem)
  LOAD_PYTHON_SYMBOL(PyDict_SetItem)
  LOAD_PYTHON_SYMBOL(PyDict_SetItemString)
  LOAD_PYTHON_SYMBOL(PyDict_Next)
  LOAD_PYTHON_SYMBOL(PyDict_Keys)
  LOAD_PYTHON_SYMBOL(PyDict_Values)
  LOAD_PYTHON_SYMBOL(PyDict_Size)
  LOAD_PYTHON_SYMBOL(PyDict_Copy)
  LOAD_PYTHON_SYMBOL(PyFloat_AsDouble)
  LOAD_PYTHON_SYMBOL(PyFloat_FromDouble)
  LOAD_PYTHON_SYMBOL(PyFunction_Type)
  LOAD_PYTHON_SYMBOL(PyModule_Type)
  LOAD_PYTHON_SYMBOL(PyType_Type)
  LOAD_PYTHON_SYMBOL(PyComplex_FromDoubles)
  LOAD_PYTHON_SYMBOL(PyComplex_RealAsDouble)
  LOAD_PYTHON_SYMBOL(PyComplex_ImagAsDouble)
  LOAD_PYTHON_SYMBOL(PyObject_IsInstance)
  LOAD_PYTHON_SYMBOL(PyObject_RichCompareBool)
  LOAD_PYTHON_SYMBOL(PyObject_Call)
  LOAD_PYTHON_SYMBOL(PyObject_CallFunctionObjArgs)
  LOAD_PYTHON_SYMBOL(PyType_IsSubtype)
  LOAD_PYTHON_SYMBOL(PySys_WriteStderr)

  if (python3) {
    LOAD_PYTHON_SYMBOL(PyModule_Create2)
    LOAD_PYTHON_SYMBOL(PyImport_AppendInittab)
    LOAD_PYTHON_SYMBOL_AS(Py_SetProgramName, Py_SetProgramName_v3)
    LOAD_PYTHON_SYMBOL_AS(Py_SetPythonHome, Py_SetPythonHome_v3)
    LOAD_PYTHON_SYMBOL_AS(PySys_SetArgv, PySys_SetArgv_v3)
    LOAD_PYTHON_SYMBOL(PyUnicode_EncodeLocale)
    LOAD_PYTHON_SYMBOL(PyUnicode_AsEncodedString)
#ifdef _WIN32
    LOAD_PYTHON_SYMBOL(PyUnicode_AsMBCSString)
#endif
    LOAD_PYTHON_SYMBOL(PyBytes_AsStringAndSize)
    LOAD_PYTHON_SYMBOL(PyBytes_FromStringAndSize)
    LOAD_PYTHON_SYMBOL(PyUnicode_FromString)
    LOAD_PYTHON_SYMBOL_AS(PyLong_AsLong, PyInt_AsLong)
    LOAD_PYTHON_SYMBOL_AS(PyLong_FromLong, PyInt_FromLong)
  } else {
    if (is64bit) {
      LOAD_PYTHON_SYMBOL_AS(Py_InitModule4_64, Py_InitModule4)
    } else {
      LOAD_PYTHON_SYMBOL(Py_InitModule4)
    }
    LOAD_PYTHON_SYMBOL(PyString_AsStringAndSize)
    LOAD_PYTHON_SYMBOL(PyString_FromStringAndSize)
    LOAD_PYTHON_SYMBOL(PyString_FromString)
    LOAD_PYTHON_SYMBOL(Py_SetProgramName)
    LOAD_PYTHON_SYMBOL(Py_SetPythonHome)
    LOAD_PYTHON_SYMBOL(PySys_SetArgv)
    LOAD_PYTHON_SYMBOL(PyInt_AsLong)
    LOAD_PYTHON_SYMBOL(PyInt_FromLong)
    LOAD_PYTHON_SYMBOL(PyCObject_AsVoidPtr)
  }
  LOAD_PYTHON_SYMBOL(PyCapsule_New)
  LOAD_PYTHON_SYMBOL(PyCapsule_GetPointer)
  LOAD_PYTHON_SYMBOL(PyCapsule_SetContext)
  LOAD_PYTHON_SYMBOL(PyCapsule_GetContext)
  LOAD_PYTHON_SYMBOL(Py_BuildValue)

  return true;
}

bool SharedLibrary::unload(std::string* pError)
{
  if (pLib_ != NULL)
    return closeLibrary(pLib_, pError);
  else
    return true;
}

bool import_numpy_api(bool python3, std::string* pError) {

  PyObject* numpy = PyImport_ImportModule("numpy.core.multiarray");
  if (numpy == NULL) {
    *pError = "numpy.core.multiarray failed to import";
    return false;
  }

  PyObject* c_api = PyObject_GetAttrString(numpy, "_ARRAY_API");
  Py_DecRef(numpy);
  if (c_api == NULL) {
    *pError = "numpy.core.multiarray _ARRAY_API not found";
    return false;
  }

  // get api pointer
  if (python3)
    PyArray_API = (void **)PyCapsule_GetPointer(c_api, NULL);
  else
    PyArray_API = (void **)PyCObject_AsVoidPtr(c_api);

  Py_DecRef(c_api);
  if (PyArray_API == NULL) {
    *pError = "_ARRAY_API is NULL pointer";
    return false;
  }

  // check C API version
  if (NPY_VERSION != PyArray_GetNDArrayCVersion()) {
    std::ostringstream ostr;
    ostr << "incompatible NumPy binary version " << (int) PyArray_GetNDArrayCVersion() << " "
    "(expecting version " << (int) NPY_VERSION << ")";
    *pError = ostr.str();
    return false;
  }

  // check feature version
  if (NPY_1_6_API_VERSION > PyArray_GetNDArrayCFeatureVersion()) {
    std::ostringstream ostr;
    ostr << "incompatible NumPy feature version " << (int) PyArray_GetNDArrayCFeatureVersion() << " "
    "(expecting version " << (int) NPY_1_6_API_VERSION << " or greater)";
    *pError = ostr.str();
    return false;
  }

  return true;
}

} // namespace libpython

<commit_msg>Provide PyUnicode_FromEncodedString for all versions of Python<commit_after>
#define LIBPYTHON_CPP
#include "libpython.h"

#ifndef _WIN32
#include <dlfcn.h>
#else
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <string>
#include <vector>
#include <iostream>
#include <sstream>

namespace libpython {

namespace {

void lastDLErrorMessage(std::string* pError)
{
#ifdef _WIN32
  LPVOID lpMsgBuf;
  DWORD dw = ::GetLastError();

  DWORD length = ::FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
      FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS,
      NULL,
      dw,
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR) &lpMsgBuf,
      0, NULL );

  if (length != 0)
  {
    std::string msg((LPTSTR)lpMsgBuf);
    LocalFree(lpMsgBuf);
    pError->assign(msg);
  }
  else
  {
    pError->assign("(Unknown error)");
  }
#else
  const char* msg = ::dlerror();
  if (msg != NULL)
    pError->assign(msg);
  else
    pError->assign("(Unknown error)");
#endif
}

bool loadLibrary(const std::string& libPath, void** ppLib, std::string* pError)
{
  *ppLib = NULL;
#ifdef _WIN32
  *ppLib = (void*)::LoadLibraryEx(libPath.c_str(), NULL, 0);
#else
  *ppLib = ::dlopen(libPath.c_str(), RTLD_NOW|RTLD_GLOBAL);
#endif
  if (*ppLib == NULL)
  {
    lastDLErrorMessage(pError);
    *pError = libPath + " - " + *pError;
    return false;
  }
  else
  {
    return true;
  }
}

bool loadSymbol(void* pLib, const std::string& name, void** ppSymbol, std::string* pError)
{
  *ppSymbol = NULL;
#ifdef _WIN32
  *ppSymbol = (void*)::GetProcAddress((HINSTANCE)pLib, name.c_str());
#else
  *ppSymbol = ::dlsym(pLib, name.c_str());
#endif
  if (*ppSymbol == NULL)
  {
    lastDLErrorMessage(pError);
    *pError = name + " - " + *pError;
    return false;
  }
  else
  {
    return true;
  }
}

bool closeLibrary(void* pLib, std::string* pError)
{
#ifdef _WIN32
  if (!::FreeLibrary((HMODULE)pLib))
#else
  if (::dlclose(pLib) != 0)
#endif
  {
    lastDLErrorMessage(pError);
    return false;
  }
  else
  {
    return true;
  }
}

bool loadSymbol(void* pLib, const std::vector<std::string>& names, void** ppSymbol, std::string* pError) {

  // search for a symbol with one of the specified names
  for (size_t i = 0; i<names.size(); ++i) {
    std::string name = names[i];
    if (loadSymbol(pLib, name, ppSymbol, pError))
      return true;
  }

  // return false if nonone found
  return false;
}

} // anonymous namespace

void initialize_type_objects(bool python3) {
  Py_None = Py_BuildValue("z", NULL);
  Py_Unicode = Py_BuildValue("u", L"a");
  if (python3)
    Py_String = Py_BuildValue("y", "a");
  else
    Py_String = Py_BuildValue("s", "a");
  Py_Int = PyInt_FromLong(1024L);
  Py_Long = PyLong_FromLong(1024L);
  Py_Bool = PyBool_FromLong(1L);
  Py_True = PyBool_FromLong(1L);
  Py_False = PyBool_FromLong(0L);
  Py_Dict = Py_BuildValue("{s:i}", "a", 1024);
  Py_Float = PyFloat_FromDouble(0.0);
  Py_Tuple = Py_BuildValue("(i)", 1024);
  Py_List = Py_BuildValue("[i]", 1024);
  Py_Complex = PyComplex_FromDoubles(0.0, 0.0);
}

#define LOAD_PYTHON_SYMBOL_AS(name, as)             \
if (!loadSymbol(pLib_, #name, (void**)&as, pError)) \
  return false;

#define LOAD_PYTHON_SYMBOL(name)                                \
if (!loadSymbol(pLib_, #name, (void**) &libpython::name, pError)) \
  return false;

bool SharedLibrary::load(const std::string& libPath, bool python3, std::string* pError)
{
  if (!loadLibrary(libPath, &pLib_, pError))
    return false;

  return loadSymbols(python3, pError);
}

bool LibPython::loadSymbols(bool python3, std::string* pError)
{
  bool is64bit = sizeof(size_t) >= 8;

  LOAD_PYTHON_SYMBOL(Py_Initialize)
  LOAD_PYTHON_SYMBOL(Py_IsInitialized)
  LOAD_PYTHON_SYMBOL(Py_AddPendingCall)
  LOAD_PYTHON_SYMBOL(PyErr_SetInterrupt)
  LOAD_PYTHON_SYMBOL(PyExc_KeyboardInterrupt)
  LOAD_PYTHON_SYMBOL(Py_IncRef)
  LOAD_PYTHON_SYMBOL(Py_DecRef)
  LOAD_PYTHON_SYMBOL(PyObject_GetAttrString)
  LOAD_PYTHON_SYMBOL(PyObject_HasAttrString)
  LOAD_PYTHON_SYMBOL(PyObject_SetAttrString)
  LOAD_PYTHON_SYMBOL(PyTuple_Size)
  LOAD_PYTHON_SYMBOL(PyTuple_GetItem)
  LOAD_PYTHON_SYMBOL(PyTuple_New)
  LOAD_PYTHON_SYMBOL(PyTuple_SetItem)
  LOAD_PYTHON_SYMBOL(PyTuple_GetSlice)
  LOAD_PYTHON_SYMBOL(PyList_New)
  LOAD_PYTHON_SYMBOL(PyList_Size)
  LOAD_PYTHON_SYMBOL(PyList_GetItem)
  LOAD_PYTHON_SYMBOL(PyList_SetItem)
  LOAD_PYTHON_SYMBOL(PyErr_Fetch)
  LOAD_PYTHON_SYMBOL(PyErr_Occurred)
  LOAD_PYTHON_SYMBOL(PyErr_NormalizeException)
  LOAD_PYTHON_SYMBOL(PyErr_ExceptionMatches)
  LOAD_PYTHON_SYMBOL(PyErr_GivenExceptionMatches)
  LOAD_PYTHON_SYMBOL(PyObject_Str)
  LOAD_PYTHON_SYMBOL(PyObject_Dir)
  LOAD_PYTHON_SYMBOL(PyCallable_Check)
  LOAD_PYTHON_SYMBOL(PyRun_StringFlags)
  LOAD_PYTHON_SYMBOL(Py_CompileString)
  LOAD_PYTHON_SYMBOL(PyEval_EvalCode)
  LOAD_PYTHON_SYMBOL(PyModule_GetDict)
  LOAD_PYTHON_SYMBOL(PyImport_AddModule)
  LOAD_PYTHON_SYMBOL(PyImport_ImportModule)
  LOAD_PYTHON_SYMBOL(PyImport_Import)
  LOAD_PYTHON_SYMBOL(PyImport_GetModuleDict)
  LOAD_PYTHON_SYMBOL(PyObject_GetIter)
  LOAD_PYTHON_SYMBOL(PyIter_Next)
  LOAD_PYTHON_SYMBOL(PyLong_AsLong)
  LOAD_PYTHON_SYMBOL(PyLong_FromLong)
  LOAD_PYTHON_SYMBOL(PyBool_FromLong)
  LOAD_PYTHON_SYMBOL(PyDict_New)
  LOAD_PYTHON_SYMBOL(PyDict_Contains)
  LOAD_PYTHON_SYMBOL(PyDict_GetItem)
  LOAD_PYTHON_SYMBOL(PyDict_SetItem)
  LOAD_PYTHON_SYMBOL(PyDict_SetItemString)
  LOAD_PYTHON_SYMBOL(PyDict_Next)
  LOAD_PYTHON_SYMBOL(PyDict_Keys)
  LOAD_PYTHON_SYMBOL(PyDict_Values)
  LOAD_PYTHON_SYMBOL(PyDict_Size)
  LOAD_PYTHON_SYMBOL(PyDict_Copy)
  LOAD_PYTHON_SYMBOL(PyFloat_AsDouble)
  LOAD_PYTHON_SYMBOL(PyFloat_FromDouble)
  LOAD_PYTHON_SYMBOL(PyFunction_Type)
  LOAD_PYTHON_SYMBOL(PyModule_Type)
  LOAD_PYTHON_SYMBOL(PyType_Type)
  LOAD_PYTHON_SYMBOL(PyComplex_FromDoubles)
  LOAD_PYTHON_SYMBOL(PyComplex_RealAsDouble)
  LOAD_PYTHON_SYMBOL(PyComplex_ImagAsDouble)
  LOAD_PYTHON_SYMBOL(PyObject_IsInstance)
  LOAD_PYTHON_SYMBOL(PyObject_RichCompareBool)
  LOAD_PYTHON_SYMBOL(PyObject_Call)
  LOAD_PYTHON_SYMBOL(PyObject_CallFunctionObjArgs)
  LOAD_PYTHON_SYMBOL(PyType_IsSubtype)
  LOAD_PYTHON_SYMBOL(PySys_WriteStderr)

  // PyUnicode_AsEncodedString may have several different names depending on the Python
  // version and the UCS build type
  std::vector<std::string> names;
  names.push_back("PyUnicode_AsEncodedString");
  names.push_back("PyUnicodeUCS2_AsEncodedString");
  names.push_back("PyUnicodeUCS4_AsEncodedString");
  if (!loadSymbol(pLib_, names, (void**)&PyUnicode_AsEncodedString, pError) )
    return false;

  if (python3) {
    LOAD_PYTHON_SYMBOL(PyModule_Create2)
    LOAD_PYTHON_SYMBOL(PyImport_AppendInittab)
    LOAD_PYTHON_SYMBOL_AS(Py_SetProgramName, Py_SetProgramName_v3)
    LOAD_PYTHON_SYMBOL_AS(Py_SetPythonHome, Py_SetPythonHome_v3)
    LOAD_PYTHON_SYMBOL_AS(PySys_SetArgv, PySys_SetArgv_v3)
    LOAD_PYTHON_SYMBOL(PyUnicode_EncodeLocale)
#ifdef _WIN32
    LOAD_PYTHON_SYMBOL(PyUnicode_AsMBCSString)
#endif
    LOAD_PYTHON_SYMBOL(PyBytes_AsStringAndSize)
    LOAD_PYTHON_SYMBOL(PyBytes_FromStringAndSize)
    LOAD_PYTHON_SYMBOL(PyUnicode_FromString)
    LOAD_PYTHON_SYMBOL_AS(PyLong_AsLong, PyInt_AsLong)
    LOAD_PYTHON_SYMBOL_AS(PyLong_FromLong, PyInt_FromLong)
  } else {
    if (is64bit) {
      LOAD_PYTHON_SYMBOL_AS(Py_InitModule4_64, Py_InitModule4)
    } else {
      LOAD_PYTHON_SYMBOL(Py_InitModule4)
    }
    LOAD_PYTHON_SYMBOL(PyString_AsStringAndSize)
    LOAD_PYTHON_SYMBOL(PyString_FromStringAndSize)
    LOAD_PYTHON_SYMBOL(PyString_FromString)
    LOAD_PYTHON_SYMBOL(Py_SetProgramName)
    LOAD_PYTHON_SYMBOL(Py_SetPythonHome)
    LOAD_PYTHON_SYMBOL(PySys_SetArgv)
    LOAD_PYTHON_SYMBOL(PyInt_AsLong)
    LOAD_PYTHON_SYMBOL(PyInt_FromLong)
    LOAD_PYTHON_SYMBOL(PyCObject_AsVoidPtr)
  }
  LOAD_PYTHON_SYMBOL(PyCapsule_New)
  LOAD_PYTHON_SYMBOL(PyCapsule_GetPointer)
  LOAD_PYTHON_SYMBOL(PyCapsule_SetContext)
  LOAD_PYTHON_SYMBOL(PyCapsule_GetContext)
  LOAD_PYTHON_SYMBOL(Py_BuildValue)

  return true;
}

bool SharedLibrary::unload(std::string* pError)
{
  if (pLib_ != NULL)
    return closeLibrary(pLib_, pError);
  else
    return true;
}

bool import_numpy_api(bool python3, std::string* pError) {

  PyObject* numpy = PyImport_ImportModule("numpy.core.multiarray");
  if (numpy == NULL) {
    *pError = "numpy.core.multiarray failed to import";
    return false;
  }

  PyObject* c_api = PyObject_GetAttrString(numpy, "_ARRAY_API");
  Py_DecRef(numpy);
  if (c_api == NULL) {
    *pError = "numpy.core.multiarray _ARRAY_API not found";
    return false;
  }

  // get api pointer
  if (python3)
    PyArray_API = (void **)PyCapsule_GetPointer(c_api, NULL);
  else
    PyArray_API = (void **)PyCObject_AsVoidPtr(c_api);

  Py_DecRef(c_api);
  if (PyArray_API == NULL) {
    *pError = "_ARRAY_API is NULL pointer";
    return false;
  }

  // check C API version
  if (NPY_VERSION != PyArray_GetNDArrayCVersion()) {
    std::ostringstream ostr;
    ostr << "incompatible NumPy binary version " << (int) PyArray_GetNDArrayCVersion() << " "
    "(expecting version " << (int) NPY_VERSION << ")";
    *pError = ostr.str();
    return false;
  }

  // check feature version
  if (NPY_1_6_API_VERSION > PyArray_GetNDArrayCFeatureVersion()) {
    std::ostringstream ostr;
    ostr << "incompatible NumPy feature version " << (int) PyArray_GetNDArrayCFeatureVersion() << " "
    "(expecting version " << (int) NPY_1_6_API_VERSION << " or greater)";
    *pError = ostr.str();
    return false;
  }

  return true;
}

} // namespace libpython

<|endoftext|>


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

This file is part of the QtMediaHub project on http://www.qtmediahub.com

Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Girish Ramakrishnan girish@forwardbias.in
Contact:  Nokia Corporation donald.carr@nokia.com
Contact:  Nokia Corporation johannes.zellner@nokia.com

You may use this file under the terms of the BSD license as follows:

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 Nokia Corporation and its Subsidiary(-ies) 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 "mainwindow.h"
#include "mediaserver.h"
#include "qmh-config.h"
#include "globalsettings.h"
#include "skin.h"
#include "skinmanager.h"

#include <QApplication>
#include <QNetworkProxy>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>

#ifdef SCENEGRAPH
#include <QApplication>
#else
#include "qtsingleapplication.h"
#endif

static QNetworkSession *g_networkSession = 0;

static void setupNetwork(GlobalSettings *settings)
{
    QNetworkProxy proxy;
    if (settings->isEnabled(GlobalSettings::Proxy)) {
        QString proxyHost(settings->value(GlobalSettings::ProxyHost).toString());
        int proxyPort = settings->value(GlobalSettings::ProxyPort).toInt();
        proxy.setType(QNetworkProxy::HttpProxy);
        proxy.setHostName(proxyHost);
        proxy.setPort(proxyPort);
        QNetworkProxy::setApplicationProxy(proxy);
        qWarning() << "Using proxy host" << proxyHost << "on port" << proxyPort;
    }

    // Set Internet Access Point
    QNetworkConfigurationManager mgr;
    QList<QNetworkConfiguration> activeConfigs = mgr.allConfigurations();
    if (activeConfigs.count() <= 0)
        return;

    QNetworkConfiguration cfg = activeConfigs.at(0);
    foreach(QNetworkConfiguration config, activeConfigs) {
        if (config.type() == QNetworkConfiguration::UserChoice) {
            cfg = config;
            break;
        }
    }

    g_networkSession = new QNetworkSession(cfg);
    g_networkSession->open();
    g_networkSession->waitForOpened(-1);
}

int main(int argc, char** argv)
{
#ifdef SCENEGRAPH
    QApplication app(argc, argv);
#else

    bool overrideGraphicsSystem = false;
    for(int i = 0; i < argc; ++i) {
        if (qstrcmp(argv[i], "-graphicssystem") == 0) {
            overrideGraphicsSystem = true;
            break;
        }
    }

    if (!overrideGraphicsSystem)
        QApplication::setGraphicsSystem("raster");

    QtSingleApplication app(argc, argv);
#endif
    app.setApplicationName("qtmediahub");
    app.setOrganizationName("MediaTrolls");
    app.setOrganizationDomain("qtmediahub.com");

    GlobalSettings *settings = new GlobalSettings(&app);

    if (app.arguments().contains("--help") || app.arguments().contains("-help") || app.arguments().contains("-h")) {
        printf("Usage: qtmediahub [-option value] [-option=value]\n"
               "\n"
               "Options (default):\n");

        for (int i = 0; i < GlobalSettings::OptionLength; ++i) {
            printf("  -%-20s %s \t (%s)\n",
                   qPrintable(settings->name((GlobalSettings::Option)i)),
                   qPrintable(settings->doc((GlobalSettings::Option)i)),
                   qPrintable(settings->value((GlobalSettings::Option)i).toString()));
        }

        // try to print skin specific settings
        settings->parseArguments(app.arguments());

        SkinManager *skinManager = new SkinManager();
        if (skinManager->skins().contains(settings->value(GlobalSettings::Skin).toString())) {
            Skin *skin = skinManager->skins().value(settings->value(GlobalSettings::Skin).toString());
            if (!skin->parseManifest())
                return 1;

            printf("\n"
                   "Skin Options (default):\n");

            Settings *skinSettings = skin->settings();
            foreach (const QString &key, skinSettings->keys()) {
                printf("  -%-20s %s \t (%s)\n",
                       qPrintable(key),
                       qPrintable(skinSettings->doc(key)),
                       qPrintable(skinSettings->value(key).toString()));
            }
        }

        return 0;
    }

    // settings store order, commandline arguments rule
    settings->loadConfigFile();
    settings->parseArguments(app.arguments());

    setupNetwork(settings);

#ifndef SCENEGRAPH
    bool primarySession = !app.isRunning();
    if (!(settings->isEnabled(GlobalSettings::MultiInstance) || primarySession)) {
        qWarning() << app.applicationName() << "is already running, aborting";
        return false;
    }
#endif

    Config::init(argc, argv);

    MainWindow *mainWindow = 0;
    MediaServer *mediaServer = 0;

    if (!settings->isEnabled(GlobalSettings::Headless)) {
        mainWindow = new MainWindow(settings);
        mainWindow->setSkin(settings->value(GlobalSettings::Skin).toString());
        mainWindow->show();
    } else {
        mediaServer = new MediaServer(settings);
    }

    int ret = app.exec();

    g_networkSession->close();

    delete mainWindow;
    delete mediaServer;

    return ret;
}
<commit_msg>print skin name when issuing -help<commit_after>/****************************************************************************

This file is part of the QtMediaHub project on http://www.qtmediahub.com

Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Girish Ramakrishnan girish@forwardbias.in
Contact:  Nokia Corporation donald.carr@nokia.com
Contact:  Nokia Corporation johannes.zellner@nokia.com

You may use this file under the terms of the BSD license as follows:

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 Nokia Corporation and its Subsidiary(-ies) 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 "mainwindow.h"
#include "mediaserver.h"
#include "qmh-config.h"
#include "globalsettings.h"
#include "skin.h"
#include "skinmanager.h"

#include <QApplication>
#include <QNetworkProxy>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>

#ifdef SCENEGRAPH
#include <QApplication>
#else
#include "qtsingleapplication.h"
#endif

static QNetworkSession *g_networkSession = 0;

static void setupNetwork(GlobalSettings *settings)
{
    QNetworkProxy proxy;
    if (settings->isEnabled(GlobalSettings::Proxy)) {
        QString proxyHost(settings->value(GlobalSettings::ProxyHost).toString());
        int proxyPort = settings->value(GlobalSettings::ProxyPort).toInt();
        proxy.setType(QNetworkProxy::HttpProxy);
        proxy.setHostName(proxyHost);
        proxy.setPort(proxyPort);
        QNetworkProxy::setApplicationProxy(proxy);
        qWarning() << "Using proxy host" << proxyHost << "on port" << proxyPort;
    }

    // Set Internet Access Point
    QNetworkConfigurationManager mgr;
    QList<QNetworkConfiguration> activeConfigs = mgr.allConfigurations();
    if (activeConfigs.count() <= 0)
        return;

    QNetworkConfiguration cfg = activeConfigs.at(0);
    foreach(QNetworkConfiguration config, activeConfigs) {
        if (config.type() == QNetworkConfiguration::UserChoice) {
            cfg = config;
            break;
        }
    }

    g_networkSession = new QNetworkSession(cfg);
    g_networkSession->open();
    g_networkSession->waitForOpened(-1);
}

int main(int argc, char** argv)
{
#ifdef SCENEGRAPH
    QApplication app(argc, argv);
#else

    bool overrideGraphicsSystem = false;
    for(int i = 0; i < argc; ++i) {
        if (qstrcmp(argv[i], "-graphicssystem") == 0) {
            overrideGraphicsSystem = true;
            break;
        }
    }

    if (!overrideGraphicsSystem)
        QApplication::setGraphicsSystem("raster");

    QtSingleApplication app(argc, argv);
#endif
    app.setApplicationName("qtmediahub");
    app.setOrganizationName("MediaTrolls");
    app.setOrganizationDomain("qtmediahub.com");

    GlobalSettings *settings = new GlobalSettings(&app);

    if (app.arguments().contains("--help") || app.arguments().contains("-help") || app.arguments().contains("-h")) {
        printf("Usage: qtmediahub [-option value] [-option=value]\n"
               "\n"
               "Options (default):\n");

        for (int i = 0; i < GlobalSettings::OptionLength; ++i) {
            printf("  -%-20s %s \t (%s)\n",
                   qPrintable(settings->name((GlobalSettings::Option)i)),
                   qPrintable(settings->doc((GlobalSettings::Option)i)),
                   qPrintable(settings->value((GlobalSettings::Option)i).toString()));
        }

        // try to print skin specific settings
        settings->parseArguments(app.arguments());

        SkinManager *skinManager = new SkinManager();
        if (skinManager->skins().contains(settings->value(GlobalSettings::Skin).toString())) {
            Skin *skin = skinManager->skins().value(settings->value(GlobalSettings::Skin).toString());
            if (!skin->parseManifest())
                return 1;

            printf("\n"
                   "Skin '%s' Options (default):\n", qPrintable(skin->name()));

            Settings *skinSettings = skin->settings();
            foreach (const QString &key, skinSettings->keys()) {
                printf("  -%-20s %s \t (%s)\n",
                       qPrintable(key),
                       qPrintable(skinSettings->doc(key)),
                       qPrintable(skinSettings->value(key).toString()));
            }
        }

        return 0;
    }

    // settings store order, commandline arguments rule
    settings->loadConfigFile();
    settings->parseArguments(app.arguments());

    setupNetwork(settings);

#ifndef SCENEGRAPH
    bool primarySession = !app.isRunning();
    if (!(settings->isEnabled(GlobalSettings::MultiInstance) || primarySession)) {
        qWarning() << app.applicationName() << "is already running, aborting";
        return false;
    }
#endif

    Config::init(argc, argv);

    MainWindow *mainWindow = 0;
    MediaServer *mediaServer = 0;

    if (!settings->isEnabled(GlobalSettings::Headless)) {
        mainWindow = new MainWindow(settings);
        mainWindow->setSkin(settings->value(GlobalSettings::Skin).toString());
        mainWindow->show();
    } else {
        mediaServer = new MediaServer(settings);
    }

    int ret = app.exec();

    g_networkSession->close();

    delete mainWindow;
    delete mediaServer;

    return ret;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cmath>
#include <functional>
#include <iterator>

#include <QCoreApplication>
#include <QFile>
#include <QHash>
#include <QSet>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <QVector>

typedef QSet<int> IndexSet;
typedef QHash<QString, QSharedPointer<IndexSet> > PositionHash;

inline QSharedPointer<IndexSet> defaultSet()
{
  return QSharedPointer<IndexSet>(new IndexSet);
}

struct Positions {
  PositionHash wordPositions;
  PositionHash tagPositions;
};

struct Unigram {
  Unigram () {}
  Unigram(QString const &newType, QString const &newUnigram) :
      type(newType), unigram(newUnigram) {}
  QString type;
  QString unigram;
};

inline bool operator==(Unigram const &u1, Unigram const &u2)
{
  return u1.type == u2.type && u1.unigram == u2.unigram;
}

inline uint qHash(Unigram const &unigram)
{
  uint h1 = qHash(unigram.type);
  uint h2 = qHash(unigram.unigram);
  return ((h1 << 16) | (h1 >> 16)) ^ h2;
}

typedef QPair<Unigram, Unigram> Bigram;

typedef QHash<Bigram, QSharedPointer<IndexSet> > BigramCache;

double expansionFactor(int badFreq) {
  return 1.0 + exp(-0.5 * float(badFreq));
}

bool readCorpus(QTextStream &corpusStream, Positions *positions) {
  int position = 0;
  QString line;

  while (true) {
    line = corpusStream.readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      if (positions->wordPositions[word].isNull())
        positions->wordPositions[word] = QSharedPointer<IndexSet>(new IndexSet);
      positions->wordPositions[word]->insert(position);
      if (positions->tagPositions[tag].isNull())
        positions->tagPositions[tag] = QSharedPointer<IndexSet>(new IndexSet);
      positions->tagPositions[tag]->insert(position);

      ++position;
    }

  }

  return true;
}

double sequenceRatio(BigramCache *goodCache, BigramCache *badCache,
    Positions const &goodPositions, Positions const &badPositions,
    QVector<Unigram> seq)
{
  bool fromCache = false;

  QSharedPointer<IndexSet> goodIdx(new IndexSet);
  QSharedPointer<IndexSet> badIdx(new IndexSet);

 //   IndexSet goodIdx;
 //   IndexSet badIdx;

  if (seq.size() == 2) {
      BigramCache::iterator badIter;
      BigramCache::iterator goodIter;
      Bigram bigram(seq[0], seq[1]);
      if ((badIter = badCache->find(bigram)) !=
          badCache->end() &&
          (goodIter = goodCache->find(bigram)) !=
           goodCache->end()) {
        badIdx = *badIter;
        goodIdx = *goodIter;
        seq.pop_front();
        seq.pop_front();
        fromCache = true;
      }
  }

  for (int i = 0; i < seq.size(); ++i) {

    PositionHash const *goodHash = 0;
    PositionHash const *badHash = 0;

    if (seq[i].type == "w") {
      goodHash = &goodPositions.wordPositions;
      badHash = &badPositions.wordPositions;
    } else {
      goodHash = &goodPositions.tagPositions;
      badHash = &badPositions.tagPositions;
    }

    if (i == 0 && !fromCache) {
      goodIdx = goodHash->value(seq[i].unigram, defaultSet());
      badIdx = badHash->value(seq[i].unigram, defaultSet());
    } else {

      QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
      for (IndexSet::const_iterator iter = goodIdx->begin();
            iter != goodIdx->end(); ++iter)
        newGoodIdx->insert(*iter + 1);

      QSharedPointer<IndexSet> newBadIdx(new IndexSet);
      for (IndexSet::const_iterator iter = badIdx->begin();
            iter != badIdx->end(); ++iter)
        newBadIdx->insert(*iter + 1);

      goodIdx = QSharedPointer<IndexSet>(
          new IndexSet(newGoodIdx->intersect(*goodHash->value(seq[i].unigram,
                defaultSet())))
      );
      badIdx = QSharedPointer<IndexSet>(
          new IndexSet(newBadIdx->intersect(*badHash->value(seq[i].unigram,
                defaultSet())))
      );

      if (i == 1 && (goodIdx->size() > 5 || badIdx->size() > 5)) {
        Bigram bigram(seq[0], seq[1]);
        (*goodCache)[bigram] = goodIdx;
        (*badCache)[bigram] = badIdx;
      }
    }
  }

  if (goodIdx->size() + badIdx->size() == 0)
    return 0.0;

  return static_cast<double>(badIdx->size())
    / (goodIdx->size() + badIdx->size());
}

void expandCorpus(QTextStream *corpusStream, Positions const &goodPositions,
    Positions const &badPositions, QTextStream *sentStream)
{
  BigramCache goodBigramCache;
  BigramCache badBigramCache;

  int count = 0;

  QString line;
  while (true) {
    line = corpusStream->readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    QVector<Unigram> tags;
    QVector<Unigram> words;
    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      words.push_back(Unigram("w", word));
      tags.push_back(Unigram("t", tag));
    }

    for (int i = 0; i < words.size(); ++i) {
      // First word suspicion
      QSharedPointer<IndexSet> goodIdx =
        goodPositions.wordPositions.value(words[i].unigram, defaultSet());
      QSharedPointer<IndexSet> badIdx =
        badPositions.wordPositions.value(words[i].unigram, defaultSet());
      double susp = static_cast<double>(badIdx->size()) /
        (badIdx->size() + goodIdx->size());

      QVector<Unigram> ngram;
      ngram.push_back(words[i]);

      for (int j = i + 1; j < words.size(); ++j) {
        QSharedPointer<IndexSet> tagGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> tagBadIdx(new IndexSet);
        QSharedPointer<IndexSet> newTagGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> newTagbadIdx(new IndexSet);

        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            if ((goodIter = goodBigramCache.find(Bigram(ngram[0], tags[j]))) !=
                goodBigramCache.end())
            tagGoodIdx = *goodIter;

            BigramCache::const_iterator badIter;
            if ((badIter = badBigramCache.find(Bigram(ngram[0], tags[j]))) !=
                badBigramCache.end())
            tagBadIdx = *badIter;
        }

        if (tagGoodIdx->size() == 0 || tagBadIdx->size() == 0) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          tagGoodIdx = QSharedPointer<IndexSet>(
              new IndexSet(newGoodIdx->intersect(*goodPositions.tagPositions.value(tags[j].unigram, defaultSet())))
          );
          tagBadIdx = QSharedPointer<IndexSet>(
              new IndexSet(newBadIdx->intersect(*badPositions.tagPositions.value(tags[j].unigram, defaultSet())))
          );

          if (ngram.size() == 1 && (tagGoodIdx->size() > 5 || tagBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], tags[1]);
            goodBigramCache[bigram] = tagGoodIdx;
            badBigramCache[bigram] = tagBadIdx;
          }
        }

        double newTagSusp = 0.0;
        if (tagBadIdx->size() > 0)
          newTagSusp = static_cast<double>(tagBadIdx->size()) /
            (tagBadIdx->size() + tagGoodIdx->size());

        double ef = expansionFactor(tagBadIdx->size());

        QVector<Unigram> secondGram = ngram.mid(1);
        secondGram.push_back(tags[j]);
        double susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newTagSusp > susp * ef && newTagSusp > susp2 * ef) {
          ngram.push_back(tags[j]);
          goodIdx = tagGoodIdx;
          badIdx = tagBadIdx;
          susp = newTagSusp;
          continue;
        }

        ////////////////////
        // Word expansion //
        ////////////////////

        QSharedPointer<IndexSet> wordGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> wordBadIdx(new IndexSet);

        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            if ((goodIter = goodBigramCache.find(Bigram(ngram[0], words[j]))) !=
                goodBigramCache.end())
              wordGoodIdx = *goodIter;

            BigramCache::const_iterator badIter;
            if ((badIter = badBigramCache.find(Bigram(ngram[0], words[j]))) !=
                badBigramCache.end())
              wordBadIdx = *badIter;
        }

        if (wordGoodIdx->size() == 0 || wordBadIdx->size() == 0) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          wordGoodIdx = QSharedPointer<IndexSet>(
              new IndexSet(newGoodIdx->intersect(*goodPositions.wordPositions.value(words[j].unigram, defaultSet()))));

          wordBadIdx = QSharedPointer<IndexSet>(
              new IndexSet(newBadIdx->intersect(*badPositions.wordPositions.value(words[j].unigram, defaultSet()))));

          if (ngram.size() == 1 && (wordGoodIdx->size() > 5 || wordBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], words[1]);
            goodBigramCache[bigram] = wordGoodIdx;
            badBigramCache[bigram] = wordBadIdx;
          }
        }

        double newWordSusp = 0.0;
        if (wordBadIdx->size() > 0)
          newWordSusp = static_cast<double>(wordBadIdx->size()) /
            (wordBadIdx->size() + wordGoodIdx->size());

        ef = expansionFactor(wordBadIdx->size());

        secondGram = ngram.mid(1);
        secondGram.push_back(words[j]);
        susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newWordSusp > susp * ef && newWordSusp > susp2 * ef) {
          ngram.push_back(words[j]);
          goodIdx = wordGoodIdx;
          badIdx = wordBadIdx;
          susp = newWordSusp;
          continue;
        }

        break;
      }

      QStringList ngramFlat;
      for (QVector<Unigram>::const_iterator iter = ngram.begin();
          iter != ngram.end(); ++iter)
        ngramFlat.push_back(iter->unigram);
      QString ngramStr(ngramFlat.join("_"));

      *sentStream << ngramStr << " ";
      QTextStream out(stdout);
      out << ngramStr << " ";
    }

    count +=1;
    if (count % 2 == 0) {
      QTextStream out(stdout);
      out << ".";
     }

     *sentStream << "\n";
     QTextStream out(stdout);
     out << "\n";
  }
}

int main(int argc, char *argv[]) {
  QCoreApplication app(argc, argv);

  if (argc != 4)
    return 1;

  QFile goodCorpus(argv[1]);
  goodCorpus.open(QFile::ReadOnly);
  QTextStream goodStream(&goodCorpus);

  QFile badCorpus(argv[2]);
  badCorpus.open(QFile::ReadOnly);
  QTextStream badStream(&badCorpus);

  QFile sents(argv[3]);
  sents.open(QFile::WriteOnly);
  QTextStream sentStream(&sents);

  QTextStream err(stderr);
  err << "Constructing indextables..." << endl;
  Positions goodPositions;
  readCorpus(goodStream, &goodPositions);

  Positions badPositions;
  readCorpus(badStream, &badPositions);

  err << "Expanding..." << endl;
  badStream.seek(0);
  expandCorpus(&badStream, goodPositions, badPositions, &sentStream);
}
<commit_msg>Faster set intersection.<commit_after>#include <algorithm>
#include <cmath>
#include <functional>
#include <iterator>

#include <QCoreApplication>
#include <QFile>
#include <QHash>
#include <QSet>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <QVector>

typedef QSet<int> IndexSet;
typedef QHash<QString, QSharedPointer<IndexSet> > PositionHash;

inline QSharedPointer<IndexSet> defaultSet()
{
  return QSharedPointer<IndexSet>(new IndexSet);
}

struct Positions {
  PositionHash wordPositions;
  PositionHash tagPositions;
};

struct Unigram {
  Unigram () {}
  Unigram(QString const &newType, QString const &newUnigram) :
      type(newType), unigram(newUnigram) {}
  QString type;
  QString unigram;
};

inline bool operator==(Unigram const &u1, Unigram const &u2)
{
  return u1.type == u2.type && u1.unigram == u2.unigram;
}

inline uint qHash(Unigram const &unigram)
{
  uint h1 = qHash(unigram.type);
  uint h2 = qHash(unigram.unigram);
  return ((h1 << 16) | (h1 >> 16)) ^ h2;
}

template <typename T>
QSharedPointer<QSet<T> > intersect_set(QSharedPointer<QSet<T> > const a,
    QSharedPointer<QSet<T> > const b) {
  QSharedPointer<QSet<T> > small;
  QSharedPointer<QSet<T> > big;

  if (a->size() > b->size()) {
    big = a;
    small = b;
  } else {
    big = b;
    small = a;
  }

  QSharedPointer<QSet<T> > inter(new QSet<T>);
  for (typename QSet<T>::const_iterator iter = small->begin();
      iter != small->end();
      ++iter)
    if (big->contains(*iter))
      inter->insert(*iter);

  return inter;
}

typedef QPair<Unigram, Unigram> Bigram;

typedef QHash<Bigram, QSharedPointer<IndexSet> > BigramCache;

double expansionFactor(int badFreq) {
  return 1.0 + exp(-0.5 * float(badFreq));
}

bool readCorpus(QTextStream &corpusStream, Positions *positions) {
  int position = 0;
  QString line;

  while (true) {
    line = corpusStream.readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      if (positions->wordPositions[word].isNull())
        positions->wordPositions[word] = QSharedPointer<IndexSet>(new IndexSet);
      positions->wordPositions[word]->insert(position);
      if (positions->tagPositions[tag].isNull())
        positions->tagPositions[tag] = QSharedPointer<IndexSet>(new IndexSet);
      positions->tagPositions[tag]->insert(position);

      ++position;
    }

  }

  return true;
}

double sequenceRatio(BigramCache *goodCache, BigramCache *badCache,
    Positions const &goodPositions, Positions const &badPositions,
    QVector<Unigram> seq)
{
  bool fromCache = false;

  QSharedPointer<IndexSet> goodIdx(new IndexSet);
  QSharedPointer<IndexSet> badIdx(new IndexSet);

 //   IndexSet goodIdx;
 //   IndexSet badIdx;

  if (seq.size() == 2) {
      BigramCache::iterator badIter;
      BigramCache::iterator goodIter;
      Bigram bigram(seq[0], seq[1]);
      if ((badIter = badCache->find(bigram)) !=
          badCache->end() &&
          (goodIter = goodCache->find(bigram)) !=
           goodCache->end()) {
        badIdx = *badIter;
        goodIdx = *goodIter;
        seq.pop_front();
        seq.pop_front();
        fromCache = true;
      }
  }

  for (int i = 0; i < seq.size(); ++i) {

    PositionHash const *goodHash = 0;
    PositionHash const *badHash = 0;

    if (seq[i].type == "w") {
      goodHash = &goodPositions.wordPositions;
      badHash = &badPositions.wordPositions;
    } else {
      goodHash = &goodPositions.tagPositions;
      badHash = &badPositions.tagPositions;
    }

    if (i == 0 && !fromCache) {
      goodIdx = goodHash->value(seq[i].unigram, defaultSet());
      badIdx = badHash->value(seq[i].unigram, defaultSet());
    } else {

      QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
      for (IndexSet::const_iterator iter = goodIdx->begin();
            iter != goodIdx->end(); ++iter)
        newGoodIdx->insert(*iter + 1);

      QSharedPointer<IndexSet> newBadIdx(new IndexSet);
      for (IndexSet::const_iterator iter = badIdx->begin();
            iter != badIdx->end(); ++iter)
        newBadIdx->insert(*iter + 1);

      goodIdx = intersect_set(goodHash->value(seq[i].unigram,
        defaultSet()), newGoodIdx);

      badIdx = intersect_set(newBadIdx, badHash->value(seq[i].unigram,
        defaultSet()));

      if (i == 1 && (goodIdx->size() > 5 || badIdx->size() > 5)) {
        Bigram bigram(seq[0], seq[1]);
        (*goodCache)[bigram] = goodIdx;
        (*badCache)[bigram] = badIdx;
      }
    }
  }

  if (goodIdx->size() + badIdx->size() == 0)
    return 0.0;

  return static_cast<double>(badIdx->size())
    / (goodIdx->size() + badIdx->size());
}

void expandCorpus(QTextStream *corpusStream, Positions const &goodPositions,
    Positions const &badPositions, QTextStream *sentStream)
{
  BigramCache goodBigramCache;
  BigramCache badBigramCache;

  int count = 0;

  QString line;
  while (true) {
    line = corpusStream->readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    QVector<Unigram> tags;
    QVector<Unigram> words;
    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      words.push_back(Unigram("w", word));
      tags.push_back(Unigram("t", tag));
    }

    for (int i = 0; i < words.size(); ++i) {
      // First word suspicion
      QSharedPointer<IndexSet> goodIdx =
        goodPositions.wordPositions.value(words[i].unigram, defaultSet());
      QSharedPointer<IndexSet> badIdx =
        badPositions.wordPositions.value(words[i].unigram, defaultSet());
      double susp = static_cast<double>(badIdx->size()) /
        (badIdx->size() + goodIdx->size());

      QVector<Unigram> ngram;
      ngram.push_back(words[i]);

      for (int j = i + 1; j < words.size(); ++j) {
        QSharedPointer<IndexSet> tagGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> tagBadIdx(new IndexSet);
        QSharedPointer<IndexSet> newTagGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> newTagbadIdx(new IndexSet);

        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            if ((goodIter = goodBigramCache.find(Bigram(ngram[0], tags[j]))) !=
                goodBigramCache.end())
            tagGoodIdx = *goodIter;

            BigramCache::const_iterator badIter;
            if ((badIter = badBigramCache.find(Bigram(ngram[0], tags[j]))) !=
                badBigramCache.end())
            tagBadIdx = *badIter;
        }

        if (tagGoodIdx->size() == 0 || tagBadIdx->size() == 0) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          tagGoodIdx = intersect_set(newGoodIdx,
              goodPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          tagBadIdx = intersect_set(newBadIdx,
            badPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          if (ngram.size() == 1 && (tagGoodIdx->size() > 5 || tagBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], tags[1]);
            goodBigramCache[bigram] = tagGoodIdx;
            badBigramCache[bigram] = tagBadIdx;
          }
        }

        double newTagSusp = 0.0;
        if (tagBadIdx->size() > 0)
          newTagSusp = static_cast<double>(tagBadIdx->size()) /
            (tagBadIdx->size() + tagGoodIdx->size());

        double ef = expansionFactor(tagBadIdx->size());

        QVector<Unigram> secondGram = ngram.mid(1);
        secondGram.push_back(tags[j]);
        double susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newTagSusp > susp * ef && newTagSusp > susp2 * ef) {
          ngram.push_back(tags[j]);
          goodIdx = tagGoodIdx;
          badIdx = tagBadIdx;
          susp = newTagSusp;
          continue;
        }

        ////////////////////
        // Word expansion //
        ////////////////////

        QSharedPointer<IndexSet> wordGoodIdx(new IndexSet);
        QSharedPointer<IndexSet> wordBadIdx(new IndexSet);

        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            if ((goodIter = goodBigramCache.find(Bigram(ngram[0], words[j]))) !=
                goodBigramCache.end())
              wordGoodIdx = *goodIter;

            BigramCache::const_iterator badIter;
            if ((badIter = badBigramCache.find(Bigram(ngram[0], words[j]))) !=
                badBigramCache.end())
              wordBadIdx = *badIter;
        }

        if (wordGoodIdx->size() == 0 || wordBadIdx->size() == 0) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          wordGoodIdx = intersect_set(newGoodIdx,
            goodPositions.wordPositions.value(words[j].unigram, defaultSet()));

          wordBadIdx = intersect_set(newBadIdx,
            badPositions.wordPositions.value(words[j].unigram, defaultSet()));

          if (ngram.size() == 1 && (wordGoodIdx->size() > 5 || wordBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], words[1]);
            goodBigramCache[bigram] = wordGoodIdx;
            badBigramCache[bigram] = wordBadIdx;
          }
        }

        double newWordSusp = 0.0;
        if (wordBadIdx->size() > 0)
          newWordSusp = static_cast<double>(wordBadIdx->size()) /
            (wordBadIdx->size() + wordGoodIdx->size());

        ef = expansionFactor(wordBadIdx->size());

        secondGram = ngram.mid(1);
        secondGram.push_back(words[j]);
        susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newWordSusp > susp * ef && newWordSusp > susp2 * ef) {
          ngram.push_back(words[j]);
          goodIdx = wordGoodIdx;
          badIdx = wordBadIdx;
          susp = newWordSusp;
          continue;
        }

        break;
      }

      QStringList ngramFlat;
      for (QVector<Unigram>::const_iterator iter = ngram.begin();
          iter != ngram.end(); ++iter)
        ngramFlat.push_back(iter->unigram);
      QString ngramStr(ngramFlat.join("_"));

      *sentStream << ngramStr << " ";
      QTextStream out(stdout);
      out << ngramStr << " ";
    }

    count +=1;
    if (count % 2 == 0) {
      QTextStream out(stdout);
      out << ".";
     }

     *sentStream << "\n";
     QTextStream out(stdout);
     out << "\n";
  }
}

int main(int argc, char *argv[]) {
  QCoreApplication app(argc, argv);

  if (argc != 4)
    return 1;

  QFile goodCorpus(argv[1]);
  goodCorpus.open(QFile::ReadOnly);
  QTextStream goodStream(&goodCorpus);

  QFile badCorpus(argv[2]);
  badCorpus.open(QFile::ReadOnly);
  QTextStream badStream(&badCorpus);

  QFile sents(argv[3]);
  sents.open(QFile::WriteOnly);
  QTextStream sentStream(&sents);

  QTextStream err(stderr);
  err << "Constructing indextables..." << endl;
  Positions goodPositions;
  readCorpus(goodStream, &goodPositions);

  Positions badPositions;
  readCorpus(badStream, &badPositions);

  err << "Expanding..." << endl;
  badStream.seek(0);
  expandCorpus(&badStream, goodPositions, badPositions, &sentStream);
}
<|endoftext|>


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

#ifndef TWSM_MAIN_WINDOW_HPP
#define TWSM_MAIN_WINDOW_HPP

#include "econ.hpp"
#include "serverbrowser.hpp"
#include "ui_main_window.h"

#include <QMainWindow>
#include <QTimer>
#include <QDebug>

namespace Ui
{class main_window;}

namespace twsm
{
	class main_window : public QMainWindow
	{
		Q_OBJECT

		Ui::main_window* m_ui{new Ui::main_window};

		server_browser m_srvbrowser{*m_ui};
		econ m_econ{*m_ui};

		QTimer m_updatetimer;

	public:
		explicit main_window(QWidget* parent = nullptr) :
			QMainWindow{parent}
		{this->init();}

		~main_window()
		{delete m_ui;}

	private:
		void init()
		{
			// setup ui
			m_ui->setupUi(this);

			// setup components
			m_srvbrowser.init();
			m_econ.init();

			// setup timer
			m_updatetimer.start(0);
			this->connect(&m_updatetimer, SIGNAL(timeout()), this, SLOT(update()));
		}

	private slots:
		void update()
		{
			m_srvbrowser.update();
			m_econ.update();
		}

		// menu
		void on_m_tw_menu_itemSelectionChanged()
		{
			m_ui->m_sw_main->setCurrentIndex(m_ui->m_tw_menu->currentIndex().row() / 2);
		}
	};
}

#endif // TWSM_MAIN_WINDOW_HPP
<commit_msg>main_window: adapted to all new stuff<commit_after>//
// Copyright (c) 2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef TWSM_MAIN_WINDOW_HPP
#define TWSM_MAIN_WINDOW_HPP

#include "econ.hpp"
#include "popup_manager.hpp"
#include "serverbrowser.hpp"
#include "ui_main_window.h"

#include <QMainWindow>
#include <QTimer>
#include <QDebug>

namespace Ui
{class main_window;}

namespace twsm
{
	class main_window : public QMainWindow
	{
		Q_OBJECT

		Ui::main_window* m_ui{new Ui::main_window};

		popup_manager m_popupmgr{*this};

		server_browser m_srvbrowser{*m_ui, m_popupmgr};
		econ m_econ{*m_ui, m_popupmgr};

		QTimer m_updatetimer;

	public:
		explicit main_window(QWidget* parent = nullptr) :
			QMainWindow{parent}
		{this->init();}

		~main_window()
		{delete m_ui;}

		Ui::main_window& ui() noexcept
		{return *m_ui;}

		popup_manager& popupmgr() noexcept
		{return m_popupmgr;}

		server_browser& srvbrowser() noexcept
		{return m_srvbrowser;}

		econ& econsole() noexcept
		{return m_econ;}

	private:
		void init()
		{
			// setup ui
			m_ui->setupUi(this);

			// setup components
			m_srvbrowser.init();
			m_econ.init();

			// setup timer
			m_updatetimer.start(0);
			this->connect(&m_updatetimer, SIGNAL(timeout()), this, SLOT(update()));
		}

	private slots:
		void update()
		{
			m_popupmgr.update();
			m_srvbrowser.update();
			m_econ.update();
		}

		// menu
		void on_m_tw_menu_itemSelectionChanged()
		{
			m_ui->m_sw_main->setCurrentIndex(m_ui->m_tw_menu->currentIndex().row() / 2);
		}
	};
}

#endif // TWSM_MAIN_WINDOW_HPP
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <fstream>
#include <unistd.h>
#include "container.h"
#include "debug.h"
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef LXCTEMPLATE
	#error Must define LXCTEMPLATE as path to lxc-pelagicontain
#endif

/*
 * A directory need to exist and be set up in a special way.
 *
 * Basically something like:
 * mkdir -p <containerRoot>/late_mounts
 * mount --bind <containerRoot>/late_mounts <containerRoot>/late_mounts
 * mount --make-unbindable <containerRoot>/late_mounts
 * mount --make-shared <containerRoot>/late_mounts
 *
 */

Container::Container(const std::string &name,
                     const std::string &configFile,
                     const std::string &containerRoot) :
    m_name(name),
    m_configFile(configFile),
    m_containerRoot(containerRoot),
    m_mountDir(containerRoot + "/late_mounts")
{
	// Make sure m_mountDir exist
	if (!isDirectory(m_mountDir.c_str()))
	{
		log_error("Directory %s does not exist, shutting down.", m_mountDir.c_str());
		exit(-1);
	}

	// Create directories needed for mounting, will be removed in dtor
	std::string runDir = m_mountDir + "/" + m_name;

	bool allOk = true;
	allOk = allOk && createDirectory(runDir.c_str());
	allOk = allOk && createDirectory((runDir + "/bin").c_str());
	allOk = allOk && createDirectory((runDir + "/shared").c_str());
	allOk = allOk && createDirectory((runDir + "/home").c_str());

	if (!allOk)
	{
		log_error("Could not set up all needed directories, shutting down.");
		exit(-1);
	}
}

bool Container::createDirectory(const std::string &path)
{
	if (mkdir(path.c_str(), S_IRWXU) == -1)
	{
		log_error("Could not create directory %s, %s.", path.c_str(), strerror(errno));
		return false;
	}
	m_dirs.insert(m_dirs.begin(), path);
	return true;
}

bool Container::isDirectory(const std::string &path)
{
	bool isDir = false;
	struct stat st;
	if (stat(path.c_str(), &st) == 0)
	{
		if ((st.st_mode & S_IFDIR) != 0)
		{
			isDir = true;
		}
	}
	return isDir;
}

Container::~Container()
{
	// Unmount all mounted dirs
	for (std::vector<std::string>::const_iterator it = m_mounts.begin();
		 it != m_mounts.end();
		 ++it)
	{
		if (umount((*it).c_str()) == -1)
		{
			log_error("Could not unmount %s, %s", (*it).c_str(), strerror(errno));
		}
	}

	// Clean up all created directories
	for (std::vector<std::string>::const_iterator it = m_dirs.begin();
		 it != m_dirs.end();
		 ++it)
	{
		if (rmdir((*it).c_str()) == -1)
		{
			log_error("Could not remove dir %s, %s", (*it).c_str(), strerror(errno));
		}
	}
}

const char *Container::name()
{
	return m_name.c_str();
}

std::vector<std::string> Container::commands(const std::string &containedCommand,
	const std::vector<Gateway *> &gateways)
{
	int max_cmd_len = sysconf(_SC_ARG_MAX);
	char lxc_command[max_cmd_len];
	std::string environment;
	std::vector<std::string> commands;

	// Set up an environment
	for (std::vector<Gateway *>::const_iterator it = gateways.begin();
		it != gateways.end(); ++it) {
		std::string env = (*it)->environment();
		if (!env.empty())
			environment += env + " ";
	}
	log_debug("Using environment: %s", environment.c_str());

	// Command to create container
    sprintf(lxc_command,
            "CONTROLLER_DIR=%s GATEWAY_DIR=%s MOUNT_DIR=%s lxc-create -n %s -t %s"
            " -f %s > /tmp/lxc_%s.log",
            (m_containerRoot + "/bin").c_str(),
            (m_containerRoot + name() + "/gateways/").c_str(),
            m_mountDir.c_str(),
            name(),
            LXCTEMPLATE,
            m_configFile.c_str(),
            name());
	commands.push_back(std::string(lxc_command));

	// Create command to execute inside container
	snprintf(lxc_command, max_cmd_len, "lxc-execute -n %s -- env %s %s",
		name(), environment.c_str(), containedCommand.c_str());
	commands.push_back(std::string(lxc_command));

	// Command to destroy container
	snprintf(lxc_command, max_cmd_len, "lxc-destroy -n %s", name());
	commands.push_back(std::string(lxc_command));

	return commands;
}

bool Container::bindMountDir(const std::string &src, const std::string &dst)
{
	int mount_res = mount(src.c_str(), // source
						  dst.c_str(), // target
						  "",			  // fstype
						  MS_BIND,		  // flags
						  NULL);		  // data

	if (mount_res == 0)
	{
		// Success
		m_mounts.push_back(dst);
	} else {
		// Failure
		log_error("Could not mount dir into container: src=%s, dst=%s err=%s",
				  src.c_str(),
				  dst.c_str(),
				  strerror(errno));
	}

	return (mount_res == 0);
}

/*
 * When we know which app that will be run we need to
 * do some setup, like mount in the application bin and
 * shared directories.
 */
void Container::setApplication(const std::string &appId)
{
	// The directory(ies) to be mounted is known by convention, e.g.
	// /var/am/<appId>/bin/ and /var/am/<appId>/shared/

	// bind mount /var/am/<appId>/bin/ into /var/am/late_mounts/<contid>/bin
	// this directory will be accessible in container as according to
	// the lxc-pelagicontain template
	std::string appDirBase = "/var/am/" + appId;
	std::string dstDirBase = "/var/am/late_mounts/" + m_name;
	bindMountDir(appDirBase + "/bin", dstDirBase + "/bin");
	bindMountDir(appDirBase + "/shared", dstDirBase + "/shared");
	bindMountDir(appDirBase + "/home", dstDirBase + "/home");
}
<commit_msg>container.cpp: fix some identation<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <fstream>
#include <unistd.h>
#include "container.h"
#include "debug.h"
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef LXCTEMPLATE
	#error Must define LXCTEMPLATE as path to lxc-pelagicontain
#endif

/*
 * A directory need to exist and be set up in a special way.
 *
 * Basically something like:
 * mkdir -p <containerRoot>/late_mounts
 * mount --bind <containerRoot>/late_mounts <containerRoot>/late_mounts
 * mount --make-unbindable <containerRoot>/late_mounts
 * mount --make-shared <containerRoot>/late_mounts
 *
 */

Container::Container(const std::string &name,
                     const std::string &configFile,
                     const std::string &containerRoot) :
    m_name(name),
    m_configFile(configFile),
    m_containerRoot(containerRoot),
    m_mountDir(containerRoot + "/late_mounts")
{
	// Make sure m_mountDir exist
	if (!isDirectory(m_mountDir.c_str()))
	{
		log_error("Directory %s does not exist, shutting down.", m_mountDir.c_str());
		exit(-1);
	}

	// Create directories needed for mounting, will be removed in dtor
	std::string runDir = m_mountDir + "/" + m_name;

	bool allOk = true;
	allOk = allOk && createDirectory(runDir.c_str());
	allOk = allOk && createDirectory((runDir + "/bin").c_str());
	allOk = allOk && createDirectory((runDir + "/shared").c_str());
	allOk = allOk && createDirectory((runDir + "/home").c_str());

	if (!allOk)
	{
		log_error("Could not set up all needed directories, shutting down.");
		exit(-1);
	}
}

bool Container::createDirectory(const std::string &path)
{
	if (mkdir(path.c_str(), S_IRWXU) == -1)
	{
		log_error("Could not create directory %s, %s.", path.c_str(), strerror(errno));
		return false;
	}
	m_dirs.insert(m_dirs.begin(), path);
	return true;
}

bool Container::isDirectory(const std::string &path)
{
    bool isDir = false;
    struct stat st;
    if (stat(path.c_str(), &st) == 0)
    {
        if ((st.st_mode & S_IFDIR) != 0)
        {
            isDir = true;
        }
    }
    return isDir;
}

Container::~Container()
{
    // Unmount all mounted dirs
    for (std::vector<std::string>::const_iterator it = m_mounts.begin();
         it != m_mounts.end();
         ++it)
    {
        if (umount((*it).c_str()) == -1)
        {
            log_error("Could not unmount %s, %s", (*it).c_str(), strerror(errno));
        }
    }

    // Clean up all created directories
    for (std::vector<std::string>::const_iterator it = m_dirs.begin();
         it != m_dirs.end();
         ++it)
    {
        if (rmdir((*it).c_str()) == -1)
        {
            log_error("Could not remove dir %s, %s", (*it).c_str(), strerror(errno));
        }
    }
}

const char *Container::name()
{
	return m_name.c_str();
}

std::vector<std::string> Container::commands(const std::string &containedCommand,
	const std::vector<Gateway *> &gateways)
{
	int max_cmd_len = sysconf(_SC_ARG_MAX);
	char lxc_command[max_cmd_len];
	std::string environment;
	std::vector<std::string> commands;

	// Set up an environment
	for (std::vector<Gateway *>::const_iterator it = gateways.begin();
		it != gateways.end(); ++it) {
		std::string env = (*it)->environment();
		if (!env.empty())
			environment += env + " ";
	}
	log_debug("Using environment: %s", environment.c_str());

	// Command to create container
    sprintf(lxc_command,
            "CONTROLLER_DIR=%s GATEWAY_DIR=%s MOUNT_DIR=%s lxc-create -n %s -t %s"
            " -f %s > /tmp/lxc_%s.log",
            (m_containerRoot + "/bin").c_str(),
            (m_containerRoot + name() + "/gateways/").c_str(),
            m_mountDir.c_str(),
            name(),
            LXCTEMPLATE,
            m_configFile.c_str(),
            name());
	commands.push_back(std::string(lxc_command));

	// Create command to execute inside container
	snprintf(lxc_command, max_cmd_len, "lxc-execute -n %s -- env %s %s",
		name(), environment.c_str(), containedCommand.c_str());
	commands.push_back(std::string(lxc_command));

	// Command to destroy container
	snprintf(lxc_command, max_cmd_len, "lxc-destroy -n %s", name());
	commands.push_back(std::string(lxc_command));

	return commands;
}

bool Container::bindMountDir(const std::string &src, const std::string &dst)
{
	int mount_res = mount(src.c_str(), // source
						  dst.c_str(), // target
						  "",			  // fstype
						  MS_BIND,		  // flags
						  NULL);		  // data

	if (mount_res == 0)
	{
		// Success
		m_mounts.push_back(dst);
	} else {
		// Failure
		log_error("Could not mount dir into container: src=%s, dst=%s err=%s",
				  src.c_str(),
				  dst.c_str(),
				  strerror(errno));
	}

	return (mount_res == 0);
}

/*
 * When we know which app that will be run we need to
 * do some setup, like mount in the application bin and
 * shared directories.
 */
void Container::setApplication(const std::string &appId)
{
    // The directory(ies) to be mounted is known by convention, e.g.
    // /var/am/<appId>/bin/ and /var/am/<appId>/shared/

    // bind mount /var/am/<appId>/bin/ into /var/am/late_mounts/<contid>/bin
    // this directory will be accessible in container as according to
    // the lxc-pelagicontain template
    std::string appDirBase = m_containerRoot + "/" + appId;
    std::string dstDirBase = m_mountDir + "/" + m_name;
    bindMountDir(appDirBase + "/bin", dstDirBase + "/bin");
    bindMountDir(appDirBase + "/shared", dstDirBase + "/shared");
    bindMountDir(appDirBase + "/home", dstDirBase + "/home");
}
<|endoftext|>