<commit_before>/// \file Debugger.cpp

#include "chi/Debugger.hpp"

#include <chi/Context.hpp>
#include <chi/LLVMVersion.hpp>
#include <chi/NameMangler.hpp>
#include <chi/NodeInstance.hpp>
#include <chi/Result.hpp>

#include <boost/filesystem.hpp>
#include <boost/uuid/uuid_io.hpp>

#if LLVM_VERSION_LESS_EQUAL(3, 9)
#include <llvm/Bitcode/ReaderWriter.h>
#else
#include <llvm/Bitcode/BitcodeWriter.h>
#endif

#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/Module.h>

#include <lldb/API/SBListener.h>
#include <lldb/API/SBThread.h>

#include <stdlib.h>  // for setenv

namespace fs = boost::filesystem;

namespace chi {

Debugger::Debugger(const char* pathToChig, GraphModule& mod) : mModule{&mod} {
// point it to lldb-server
#if __linux__
	auto lldbServerPath = fs::path(pathToChig).parent_path() / "lldb-server";
	setenv("LLDB_DEBUGSERVER_PATH", lldbServerPath.c_str(), 1);
#endif

	lldb::SBDebugger::Initialize();
	mDebugger = lldb::SBDebugger::Create();

	// set the logger to stderr for testing
	mDebugger.SetLoggingCallback(
	    [](const char* msg, void* dbg) {
		    std::cerr << msg;
		    std::cerr.flush();
		},
	    this);

	const char* val[] = {"api", nullptr};
	mDebugger.EnableLog("lldb", val);

	// create target
	mTarget = mDebugger.CreateTarget(pathToChig);
}

Debugger::~Debugger() { lldb::SBDebugger::Terminate(); }

Result Debugger::terminate() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Kill();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to terminate process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}

Result Debugger::processContinue() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Continue();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to continue process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}
Result Debugger::pause() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Stop();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to pause process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}

Result Debugger::setBreakpoint(NodeInstance& node, lldb::SBBreakpoint* bp) {
	Result res;

	int linenum = lineNumberFromNode(node);

	// create the breakpoint
	auto breakpoint = mTarget.BreakpointCreateByLocation(
	    node.module().sourceFilePath().string().c_str(), linenum);

	// make sure that it's good
	if (!breakpoint.IsValid()) {
		res.addEntry("EUKN", "Could not set breakpoint on node",
		             {{"nodeid", node.stringId()},
		              {"File Name", node.module().sourceFilePath().string()},
		              {"Line  Number", linenum}});

		return res;
	}

	mBreakpoints[&node] = breakpoint;

	if (bp != nullptr) { *bp = breakpoint; }

	breakpoint.SetEnabled(true);

	return res;
}

bool Debugger::removeBreakpoint(NodeInstance& node) {
	auto iter = mBreakpoints.find(&node);
	if (iter == mBreakpoints.end()) { return false; }

	return mTarget.BreakpointDelete(iter->second.GetID());
}

Result Debugger::start(const char** argv, const char** envp,
                       const boost::filesystem::path& workingDirectory) {
	Expects(boost::filesystem::is_directory(workingDirectory));

	Result res;

	if (!mTarget.IsValid()) {
		res.addEntry("EUKN", "Cannot start a debugger process with an invalid target", {});
		return res;
	}

	// generate IR
	std::unique_ptr<llvm::Module> mod;
	{
		res = module().context().compileModule(module(), &mod);
		if (!res) { return res; }
	}

	// write it to a file
	fs::path tmpIRPath;
	{
		tmpIRPath = boost::filesystem::temp_directory_path() / fs::unique_path();
		std::error_code      ec;  // TODO: use ec
		std::string errorString; // only for LLVM 3.5
		llvm::raw_fd_ostream file{tmpIRPath.string().c_str(),
#if LLVM_VERSION_LESS_EQUAL(3, 5)
			errorString
#else
			ec,
#endif
			llvm::sys::fs::F_RW};
		llvm::WriteBitcodeToFile(mod.get(), file);
	}

	// create args
	std::vector<const char*> args;
	{
		args.push_back("interpret");
		args.push_back("-i");
		args.push_back(tmpIRPath.string().c_str());
		args.push_back("-O");
		args.push_back("0");

		if (argv != nullptr) {
			for (; *argv != nullptr; ++argv) { args.push_back(*argv); }
		}

		args.push_back(nullptr);
	}

	// start the process
	{
		lldb::SBError    err;
		lldb::SBListener invalidListener;
		mProcess =
		    mTarget.Launch(invalidListener, args.data(), envp, nullptr, nullptr, nullptr,
		                   workingDirectory.string().c_str(), lldb::eLaunchFlagDebug, false, err);

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to launch process", {{"Error Message", err.GetCString()}});
		}
	}

	return res;
}

std::vector<const NodeInstance*> Debugger::listBreakpoints() const {
	std::vector<const NodeInstance*> ret;
	ret.reserve(mBreakpoints.size());
	for (const auto& bpts : mBreakpoints) { ret.push_back(bpts.first); }
	return ret;
}

lldb::SBValue Debugger::inspectNodeOutput(const NodeInstance& inst, size_t id,
                                          lldb::SBFrame frame) {
	Expects(id < inst.outputDataConnections.size());

	// if frame isn't valid, use the default
	if (!frame.IsValid()) {
		auto thread = lldbProcess().GetSelectedThread();
		if (!thread.IsValid()) { return {}; }
		frame = thread.GetSelectedFrame();
	}

	if (!frame.IsValid()) { return {}; }

	// make sure it's in scope
	auto func = &nodeFromFrame(frame)->function();
	if (func != &inst.function()) { return {}; }

	auto variableName = inst.stringId() + "__" + std::to_string(id);
	return frame.FindVariable(variableName.c_str());
}

NodeInstance* Debugger::nodeFromFrame(lldb::SBFrame frame) {
	using namespace std::string_literals;

	// if frame isn't valid, use the default
	if (!frame.IsValid()) {
		auto thread = lldbProcess().GetSelectedThread();
		if (!thread.IsValid()) { return {}; }
		frame = thread.GetSelectedFrame();
	}

	if (!frame.IsValid()) { return {}; }

	auto mangledFunctionName = frame.GetFunctionName();
	// demangle that
	std::string moduleName, functionName;
	std::tie(moduleName, functionName) = unmangleFunctionName(mangledFunctionName);

	GraphFunction* func = nullptr;

	if (mangledFunctionName == "main"s) { func = module().functionFromName("main"); }

	if (func == nullptr) {
		auto mod = static_cast<GraphModule*>(module().context().moduleByFullName(moduleName));
		if (!mod) { return nullptr; }
		func = mod->functionFromName(functionName);
	}

	unsigned lineNo = frame.GetLineEntry().GetLine();

	// create assoc TODO: cache these
	auto assoc = func->module().createLineNumberAssoc();

	auto nodeIter = assoc.left.find(lineNo);
	if (nodeIter == assoc.left.end()) { return nullptr; }

	return nodeIter->second;
}

unsigned lineNumberFromNode(NodeInstance& inst) {
	// TODO: cache these, they're kinda expensive to make
	auto lineAssoc      = inst.module().createLineNumberAssoc();
	auto lineNumberIter = lineAssoc.right.find(&inst);
	if (lineNumberIter == lineAssoc.right.end()) { return -1; }

	return lineNumberIter->second;
}

}  // namespace chi
<commit_msg>Add missing comma<commit_after>/// \file Debugger.cpp

#include "chi/Debugger.hpp"

#include <chi/Context.hpp>
#include <chi/LLVMVersion.hpp>
#include <chi/NameMangler.hpp>
#include <chi/NodeInstance.hpp>
#include <chi/Result.hpp>

#include <boost/filesystem.hpp>
#include <boost/uuid/uuid_io.hpp>

#if LLVM_VERSION_LESS_EQUAL(3, 9)
#include <llvm/Bitcode/ReaderWriter.h>
#else
#include <llvm/Bitcode/BitcodeWriter.h>
#endif

#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/Module.h>

#include <lldb/API/SBListener.h>
#include <lldb/API/SBThread.h>

#include <stdlib.h>  // for setenv

namespace fs = boost::filesystem;

namespace chi {

Debugger::Debugger(const char* pathToChig, GraphModule& mod) : mModule{&mod} {
// point it to lldb-server
#if __linux__
	auto lldbServerPath = fs::path(pathToChig).parent_path() / "lldb-server";
	setenv("LLDB_DEBUGSERVER_PATH", lldbServerPath.c_str(), 1);
#endif

	lldb::SBDebugger::Initialize();
	mDebugger = lldb::SBDebugger::Create();

	// set the logger to stderr for testing
	mDebugger.SetLoggingCallback(
	    [](const char* msg, void* dbg) {
		    std::cerr << msg;
		    std::cerr.flush();
		},
	    this);

	const char* val[] = {"api", nullptr};
	mDebugger.EnableLog("lldb", val);

	// create target
	mTarget = mDebugger.CreateTarget(pathToChig);
}

Debugger::~Debugger() { lldb::SBDebugger::Terminate(); }

Result Debugger::terminate() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Kill();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to terminate process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}

Result Debugger::processContinue() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Continue();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to continue process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}
Result Debugger::pause() {
	Result res;

	if (isAttached()) {
		auto err = mProcess.Stop();

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to pause process",
			             {{"Error Code", err.GetError()}, {"Error String", err.GetCString()}});

			return res;
		}
	}

	return res;
}

Result Debugger::setBreakpoint(NodeInstance& node, lldb::SBBreakpoint* bp) {
	Result res;

	int linenum = lineNumberFromNode(node);

	// create the breakpoint
	auto breakpoint = mTarget.BreakpointCreateByLocation(
	    node.module().sourceFilePath().string().c_str(), linenum);

	// make sure that it's good
	if (!breakpoint.IsValid()) {
		res.addEntry("EUKN", "Could not set breakpoint on node",
		             {{"nodeid", node.stringId()},
		              {"File Name", node.module().sourceFilePath().string()},
		              {"Line  Number", linenum}});

		return res;
	}

	mBreakpoints[&node] = breakpoint;

	if (bp != nullptr) { *bp = breakpoint; }

	breakpoint.SetEnabled(true);

	return res;
}

bool Debugger::removeBreakpoint(NodeInstance& node) {
	auto iter = mBreakpoints.find(&node);
	if (iter == mBreakpoints.end()) { return false; }

	return mTarget.BreakpointDelete(iter->second.GetID());
}

Result Debugger::start(const char** argv, const char** envp,
                       const boost::filesystem::path& workingDirectory) {
	Expects(boost::filesystem::is_directory(workingDirectory));

	Result res;

	if (!mTarget.IsValid()) {
		res.addEntry("EUKN", "Cannot start a debugger process with an invalid target", {});
		return res;
	}

	// generate IR
	std::unique_ptr<llvm::Module> mod;
	{
		res = module().context().compileModule(module(), &mod);
		if (!res) { return res; }
	}

	// write it to a file
	fs::path tmpIRPath;
	{
		tmpIRPath = boost::filesystem::temp_directory_path() / fs::unique_path();
		std::error_code      ec;  // TODO: use ec
		std::string errorString; // only for LLVM 3.5
		llvm::raw_fd_ostream file{tmpIRPath.string().c_str(),
#if LLVM_VERSION_LESS_EQUAL(3, 5)
			errorString,
#else
			ec,
#endif
			llvm::sys::fs::F_RW};
		llvm::WriteBitcodeToFile(mod.get(), file);
	}

	// create args
	std::vector<const char*> args;
	{
		args.push_back("interpret");
		args.push_back("-i");
		args.push_back(tmpIRPath.string().c_str());
		args.push_back("-O");
		args.push_back("0");

		if (argv != nullptr) {
			for (; *argv != nullptr; ++argv) { args.push_back(*argv); }
		}

		args.push_back(nullptr);
	}

	// start the process
	{
		lldb::SBError    err;
		lldb::SBListener invalidListener;
		mProcess =
		    mTarget.Launch(invalidListener, args.data(), envp, nullptr, nullptr, nullptr,
		                   workingDirectory.string().c_str(), lldb::eLaunchFlagDebug, false, err);

		if (err.Fail()) {
			res.addEntry("EUKN", "Failed to launch process", {{"Error Message", err.GetCString()}});
		}
	}

	return res;
}

std::vector<const NodeInstance*> Debugger::listBreakpoints() const {
	std::vector<const NodeInstance*> ret;
	ret.reserve(mBreakpoints.size());
	for (const auto& bpts : mBreakpoints) { ret.push_back(bpts.first); }
	return ret;
}

lldb::SBValue Debugger::inspectNodeOutput(const NodeInstance& inst, size_t id,
                                          lldb::SBFrame frame) {
	Expects(id < inst.outputDataConnections.size());

	// if frame isn't valid, use the default
	if (!frame.IsValid()) {
		auto thread = lldbProcess().GetSelectedThread();
		if (!thread.IsValid()) { return {}; }
		frame = thread.GetSelectedFrame();
	}

	if (!frame.IsValid()) { return {}; }

	// make sure it's in scope
	auto func = &nodeFromFrame(frame)->function();
	if (func != &inst.function()) { return {}; }

	auto variableName = inst.stringId() + "__" + std::to_string(id);
	return frame.FindVariable(variableName.c_str());
}

NodeInstance* Debugger::nodeFromFrame(lldb::SBFrame frame) {
	using namespace std::string_literals;

	// if frame isn't valid, use the default
	if (!frame.IsValid()) {
		auto thread = lldbProcess().GetSelectedThread();
		if (!thread.IsValid()) { return {}; }
		frame = thread.GetSelectedFrame();
	}

	if (!frame.IsValid()) { return {}; }

	auto mangledFunctionName = frame.GetFunctionName();
	// demangle that
	std::string moduleName, functionName;
	std::tie(moduleName, functionName) = unmangleFunctionName(mangledFunctionName);

	GraphFunction* func = nullptr;

	if (mangledFunctionName == "main"s) { func = module().functionFromName("main"); }

	if (func == nullptr) {
		auto mod = static_cast<GraphModule*>(module().context().moduleByFullName(moduleName));
		if (!mod) { return nullptr; }
		func = mod->functionFromName(functionName);
	}

	unsigned lineNo = frame.GetLineEntry().GetLine();

	// create assoc TODO: cache these
	auto assoc = func->module().createLineNumberAssoc();

	auto nodeIter = assoc.left.find(lineNo);
	if (nodeIter == assoc.left.end()) { return nullptr; }

	return nodeIter->second;
}

unsigned lineNumberFromNode(NodeInstance& inst) {
	// TODO: cache these, they're kinda expensive to make
	auto lineAssoc      = inst.module().createLineNumberAssoc();
	auto lineNumberIter = lineAssoc.right.find(&inst);
	if (lineNumberIter == lineAssoc.right.end()) { return -1; }

	return lineNumberIter->second;
}

}  // namespace chi
<|endoftext|>


<commit_before>#include "process_2d.hpp"
//#include "libcomparator.hpp"

double balance[] = {1.0, 1.0, 1.0};

class MaskIterateProcess
{
public:
	IterateProcessMask<TYPE> iterateProcessMask;

	MaskIterateProcess(cv::Mat image, cv::Mat mask, int compareDistance = 1)
	:
		iterateProcessMask
		(
			image,
			std::numeric_limits<TYPE>::lowest(),
			std::numeric_limits<double>::min(),
			std::numeric_limits<double>::max(),
			balance,
			compareDistance,
			mask
		)
	{}

	std::vector<IndexTransition> calc_transitions_with_mask()
	{
		return iterateProcessMask.iterate_HV();
	}

private:
};

namespace process2d
{
	int const blurDivisor = 100;

	cv::Mat calc_canny( cv::Mat image, int blurr = 7, int threshold1 = 80, int threshold2 = 500, int apertureSize = 5 )
	{
		cv::Mat edge;
		cv::cvtColor( image, edge, CV_BGR2GRAY );
	    cv::blur( edge, edge, cv::Size(blurr, blurr) );
	    #ifdef VERBOSE
	    cv::imshow( "calc_canny", edge );
	    cv::waitKey(0);
	    #endif
	    cv::Canny( edge, edge, threshold1, threshold2, apertureSize, true );
	    edge.convertTo(edge, CV_8U);
	    #ifdef VERBOSE
	    cv::imshow( "calc_canny", edge );
	    cv::waitKey(0);
	    #endif
	    return edge;
	}

	bool is_subset(cv::Mat cannyImage1D, cv::Mat const cannyImage, double maximumNonSubsetPercentage = 10)
	{
		cv::Mat cannyImage_ = cannyImage.clone();
		int setSize = cv::countNonZero(cannyImage_);

		int dilationSize = 10;
		cv::Mat element = cv::getStructuringElement( cv::MORPH_ELLIPSE,
                                       cv::Size( 2*dilationSize + 1, 2*dilationSize+1 ),
                                       cv::Point( dilationSize, dilationSize ) );
  		cv::morphologyEx( cannyImage_, cannyImage_, cv::MORPH_DILATE, element, cv::Point(-1,-1), 1, cv::BORDER_REFLECT );

  		#ifdef VERBOSE
  		cv::imshow( "dilatedCannyImage", cannyImage_ );
	    cv::waitKey(0);
  		#endif

  		cv::bitwise_xor(cannyImage_, cannyImage1D, cannyImage_);
  		cv::bitwise_and(cannyImage_, cannyImage1D, cannyImage_);
  		int numberOfNonSubset = cv::countNonZero(cannyImage_);

  		#ifdef VERBOSE
  		cv::imshow( "nonSubset", cannyImage_ );
	    cv::waitKey(0);
  		std::cout << "process2d::is_subset::numberOfNonSubset: " << numberOfNonSubset << " setSize: " << setSize << std::endl;
  		#endif

  		return 100.0 * numberOfNonSubset / setSize < maximumNonSubsetPercentage;
	}

	cv::Mat canny_until_1d_is_subset_of_orginal(cv::Mat const cannyImage, cv::Mat image1D, int blurr, int startThreshold, double thresholdDivisor = 1.3, int ratio = 2)
	{
		#ifdef WITH_TESTS
		static int iteration = 10;
		--iteration;
		assert(iteration);
		#endif

		cv::Mat cannyImage1D = calc_canny(image1D, blurr, startThreshold, startThreshold*ratio);
		if(is_subset(cannyImage1D, cannyImage))
		{
			startThreshold/=thresholdDivisor;
			canny_until_1d_is_subset_of_orginal(cannyImage, image1D, blurr, startThreshold);
		}
		else
		{
			startThreshold*=thresholdDivisor;
			cannyImage1D = calc_canny(image1D, blurr, startThreshold, startThreshold*ratio);
			return cannyImage1D;
		}
	}

	cv::Mat run_process2d(cv::Mat image, cv::Mat image1D)
	{
		assert( image.rows == image1D.rows && image.cols == image1D.cols );

		int startThreshold = 5;
		int startThreshold1D = startThreshold * 10;
		int blurr = image.cols / blurDivisor;
		cv::Mat cannyImage = calc_canny(image, blurr, startThreshold);
		cv::Mat cannyImage1D = canny_until_1d_is_subset_of_orginal(cannyImage, image1D, blurr, startThreshold1D);

		cv::Mat shadowEdges;
		cv::subtract(cannyImage, cannyImage1D, shadowEdges);
		#ifdef VERBOSE
	    cv::imshow( "shadowEdges", shadowEdges );
	    cv::waitKey(0);
	    #endif

		//auto idTrCluster = test_on_image( path, factor, 3.0, 1 );
		MaskIterateProcess maskIterateProcess(image, shadowEdges);
		auto idTr = maskIterateProcess.calc_transitions_with_mask();

    	Filter filter(image, idTr, 160, 3, 1, 5);
    	cv::Mat result = filter.filter_image();

		return result;
	}
}<commit_msg>2d_nonsubset_20<commit_after>#include "process_2d.hpp"
//#include "libcomparator.hpp"

double balance[] = {1.0, 1.0, 1.0};

class MaskIterateProcess
{
public:
	IterateProcessMask<TYPE> iterateProcessMask;

	MaskIterateProcess(cv::Mat image, cv::Mat mask, int compareDistance = 1)
	:
		iterateProcessMask
		(
			image,
			std::numeric_limits<TYPE>::lowest(),
			std::numeric_limits<double>::min(),
			std::numeric_limits<double>::max(),
			balance,
			compareDistance,
			mask
		)
	{}

	std::vector<IndexTransition> calc_transitions_with_mask()
	{
		return iterateProcessMask.iterate_HV();
	}

private:
};

namespace process2d
{
	int const blurDivisor = 100;

	cv::Mat calc_canny( cv::Mat image, int blurr = 7, int threshold1 = 80, int threshold2 = 500, int apertureSize = 5 )
	{
		cv::Mat edge;
		cv::cvtColor( image, edge, CV_BGR2GRAY );
	    cv::blur( edge, edge, cv::Size(blurr, blurr) );
	    #ifdef VERBOSE
	    cv::imshow( "calc_canny", edge );
	    cv::waitKey(0);
	    #endif
	    cv::Canny( edge, edge, threshold1, threshold2, apertureSize, true );
	    edge.convertTo(edge, CV_8U);
	    #ifdef VERBOSE
	    cv::imshow( "calc_canny", edge );
	    cv::waitKey(0);
	    #endif
	    return edge;
	}

	bool is_subset(cv::Mat cannyImage1D, cv::Mat const cannyImage, double maximumNonSubsetPercentage = 20)
	{
		cv::Mat cannyImage_ = cannyImage.clone();
		int setSize = cv::countNonZero(cannyImage_);

		int dilationSize = 10;
		cv::Mat element = cv::getStructuringElement( cv::MORPH_ELLIPSE,
                                       cv::Size( 2*dilationSize + 1, 2*dilationSize+1 ),
                                       cv::Point( dilationSize, dilationSize ) );
  		cv::morphologyEx( cannyImage_, cannyImage_, cv::MORPH_DILATE, element, cv::Point(-1,-1), 1, cv::BORDER_REFLECT );

  		#ifdef VERBOSE
  		cv::imshow( "dilatedCannyImage", cannyImage_ );
	    cv::waitKey(0);
  		#endif

  		cv::bitwise_xor(cannyImage_, cannyImage1D, cannyImage_);
  		cv::bitwise_and(cannyImage_, cannyImage1D, cannyImage_);
  		int numberOfNonSubset = cv::countNonZero(cannyImage_);

  		#ifdef VERBOSE
  		cv::imshow( "nonSubset", cannyImage_ );
	    cv::waitKey(0);
  		std::cout << "process2d::is_subset::numberOfNonSubset: " << numberOfNonSubset << " setSize: " << setSize << std::endl;
  		#endif

  		return 100.0 * numberOfNonSubset / setSize < maximumNonSubsetPercentage;
	}

	cv::Mat canny_until_1d_is_subset_of_orginal(cv::Mat const cannyImage, cv::Mat image1D, int blurr, int startThreshold, double thresholdDivisor = 1.3, int ratio = 2)
	{
		#ifdef WITH_TESTS
		static int iteration = 10;
		--iteration;
		assert(iteration);
		#endif

		cv::Mat cannyImage1D = calc_canny(image1D, blurr, startThreshold, startThreshold*ratio);
		if(is_subset(cannyImage1D, cannyImage))
		{
			startThreshold/=thresholdDivisor;
			canny_until_1d_is_subset_of_orginal(cannyImage, image1D, blurr, startThreshold);
		}
		else
		{
			startThreshold*=thresholdDivisor;
			cannyImage1D = calc_canny(image1D, blurr, startThreshold, startThreshold*ratio);
			return cannyImage1D;
		}
	}

	cv::Mat run_process2d(cv::Mat image, cv::Mat image1D)
	{
		assert( image.rows == image1D.rows && image.cols == image1D.cols );

		int startThreshold = 5;
		int startThreshold1D = startThreshold * 10;
		int blurr = image.cols / blurDivisor;
		cv::Mat cannyImage = calc_canny(image, blurr, startThreshold);
		cv::Mat cannyImage1D = canny_until_1d_is_subset_of_orginal(cannyImage, image1D, blurr, startThreshold1D);

		cv::Mat shadowEdges;
		cv::subtract(cannyImage, cannyImage1D, shadowEdges);
		#ifdef VERBOSE
	    cv::imshow( "shadowEdges", shadowEdges );
	    cv::waitKey(0);
	    #endif

		//auto idTrCluster = test_on_image( path, factor, 3.0, 1 );
		MaskIterateProcess maskIterateProcess(image, shadowEdges);
		auto idTr = maskIterateProcess.calc_transitions_with_mask();

    	Filter filter(image, idTr, 160, 3, 1, 5);
    	cv::Mat result = filter.filter_image();

		return result;
	}
}<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

/*
   This is some wisdom from Cygnus's web page.  If you just try to use
   the "stringify" operator on a preprocessor directive, you'd get
   "PLATFORM", not "Intel Linux" (or whatever the value of PLATFORM
   is).  That's because the stringify operator is a special case, and
   the preprocessor isn't allowed to expand things that are passed to
   it.  However, by defining two layers of macros, you get the right
   behavior, since the first pass converts:

   xstr(PLATFORM) -> str(Intel Linux)

   and the next pass gives:

   str(Intel Linux) -> "Intel Linux"

   This is exactly what we want, so we use it.  -Derek Wright and Jeff
   Ballard, 12/2/99

   Also, because the NT build system is totally different, we have to
   define the correct platform string right in here. :( -Derek 12/3/99
*/

#define xstr(s) str(s)
#define str(s) #s

#if defined(WIN32)
#define PLATFORM INTEL-WINNT50
#endif

/* Via configure, one may have specified a particular buildid string to use
	in the version string. So honor that request here. */
#if defined(BUILDID)
#define BUILDIDSTR " BuildID: " xstr(BUILDID)
#else
#define BUILDIDSTR ""
#endif

/* Here is the version string - update before a public release */
/* --- IMPORTANT!  THE FORMAT OF THE VERSION STRING IS VERY STRICT
   BECAUSE IT IS PARSED AT RUNTIME.  DO NOT ALTER THE FORMAT OR ENTER
   ANYTHING EXTRA BEFORE THE DATE.  IF YOU WISH TO ADD EXTRA INFORMATION,
   DO SO _AFTER_ THE BUILDIDSTR AND BEFORE THE TRAILING '$' CHARACTER.
   EXAMPLES:
       $CondorVersion: 6.9.5 " __DATE__ BUILDIDSTR " WinNTPreview $ [OK]
	   $CondorVersion: 6.9.5 WinNTPreview " __DATE__ BUILDIDSTR " $ [WRONG!!!]
   Any questions?  See Todd or Derek.  Note: if you mess it up, DaemonCore
   will EXCEPT at startup time.
*/

static char* CondorVersionString = "$CondorVersion: 7.2.3 " __DATE__ BUILDIDSTR " PRE-RELEASE-UWCS $";

/* Here is the platform string.  You don't need to edit this */
static char* CondorPlatformString = "$CondorPlatform: " xstr(PLATFORM) " $";

extern "C" {

const char*
CondorVersion( void )
{
	return CondorVersionString;
}

const char*
CondorPlatform( void )
{
	return CondorPlatformString;
}

} /* extern "C" */

<commit_msg>Fix version string for 7.2.3 release.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

/*
   This is some wisdom from Cygnus's web page.  If you just try to use
   the "stringify" operator on a preprocessor directive, you'd get
   "PLATFORM", not "Intel Linux" (or whatever the value of PLATFORM
   is).  That's because the stringify operator is a special case, and
   the preprocessor isn't allowed to expand things that are passed to
   it.  However, by defining two layers of macros, you get the right
   behavior, since the first pass converts:

   xstr(PLATFORM) -> str(Intel Linux)

   and the next pass gives:

   str(Intel Linux) -> "Intel Linux"

   This is exactly what we want, so we use it.  -Derek Wright and Jeff
   Ballard, 12/2/99

   Also, because the NT build system is totally different, we have to
   define the correct platform string right in here. :( -Derek 12/3/99
*/

#define xstr(s) str(s)
#define str(s) #s

#if defined(WIN32)
#define PLATFORM INTEL-WINNT50
#endif

/* Via configure, one may have specified a particular buildid string to use
	in the version string. So honor that request here. */
#if defined(BUILDID)
#define BUILDIDSTR " BuildID: " xstr(BUILDID)
#else
#define BUILDIDSTR ""
#endif

/* Here is the version string - update before a public release */
/* --- IMPORTANT!  THE FORMAT OF THE VERSION STRING IS VERY STRICT
   BECAUSE IT IS PARSED AT RUNTIME.  DO NOT ALTER THE FORMAT OR ENTER
   ANYTHING EXTRA BEFORE THE DATE.  IF YOU WISH TO ADD EXTRA INFORMATION,
   DO SO _AFTER_ THE BUILDIDSTR AND BEFORE THE TRAILING '$' CHARACTER.
   EXAMPLES:
       $CondorVersion: 6.9.5 " __DATE__ BUILDIDSTR " WinNTPreview $ [OK]
	   $CondorVersion: 6.9.5 WinNTPreview " __DATE__ BUILDIDSTR " $ [WRONG!!!]
   Any questions?  See Todd or Derek.  Note: if you mess it up, DaemonCore
   will EXCEPT at startup time.
*/

static char* CondorVersionString = "$CondorVersion: 7.2.3 " __DATE__ BUILDIDSTR " $";

/* Here is the platform string.  You don't need to edit this */
static char* CondorPlatformString = "$CondorPlatform: " xstr(PLATFORM) " $";

extern "C" {

const char*
CondorVersion( void )
{
	return CondorVersionString;
}

const char*
CondorPlatform( void )
{
	return CondorPlatformString;
}

} /* extern "C" */

<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "msceneeventeater.h"
#include "mscene.h"
#include "mscenemanager.h"

#include <QEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QDebug>
#include <float.h>

MSceneEventEater::MSceneEventEater(QGraphicsItem *parent) :
        QGraphicsWidget(parent)
{
    setFlag(QGraphicsItem::ItemHasNoContents);
    setFlag(QGraphicsItem::ItemStopsClickFocusPropagation);

    //FLT_MAX is maximal value for single precision floating-point number
    //We want this item to be on top of everything
    setZValue(FLT_MAX);
    setVisible(false);
}

bool MSceneEventEater::event(QEvent *event)
{
    if ((event->type() > QEvent::MouseButtonPress && event->type() < QEvent::MouseMove) ||
        (event->type() > QEvent::GraphicsSceneMouseMove && event->type() < QEvent::GraphicsSceneWheel) ||
        (event->type() > QEvent::HoverEnter && event->type() < QEvent::HoverMove)) {

        event->accept();
        return true;
    }
    return false;
}
<commit_msg>Fixes: NB#194075 Object menu shown on a wrong page after a page transition.<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "msceneeventeater.h"
#include "mscene.h"
#include "mscenemanager.h"

#include <QEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QDebug>
#include <float.h>

MSceneEventEater::MSceneEventEater(QGraphicsItem *parent) :
        QGraphicsWidget(parent)
{
    grabGesture(Qt::TapGesture);
    grabGesture(Qt::TapAndHoldGesture);
    grabGesture(Qt::PanGesture);
    grabGesture(Qt::PinchGesture);
    grabGesture(Qt::SwipeGesture);
    setFlag(QGraphicsItem::ItemHasNoContents);
    setFlag(QGraphicsItem::ItemStopsClickFocusPropagation);

    //FLT_MAX is maximal value for single precision floating-point number
    //We want this item to be on top of everything
    setZValue(FLT_MAX);
    setVisible(false);
}

bool MSceneEventEater::event(QEvent *event)
{
    if ((event->type() > QEvent::MouseButtonPress && event->type() < QEvent::MouseMove) ||
        (event->type() > QEvent::GraphicsSceneMouseMove && event->type() < QEvent::GraphicsSceneWheel) ||
        (event->type() > QEvent::HoverEnter && event->type() < QEvent::HoverMove) ||
        (event->type() == QEvent::Gesture)) {

        event->accept();
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/*
 * DynamicCommunityDetection.cpp
 *
 *  Created on: 10.01.2014
 *      Author: cls
 */

#include "DynamicCommunityDetection.h"

#include "DynPLP.h"
#include "DynPLM.h"
#include "../dynamics/DGSStreamParser.h"
#include "../dynamics/GraphUpdater.h"
#include "../clustering/Modularity.h"

namespace NetworKit {

DynamicCommunityDetection::DynamicCommunityDetection() {
	// TODO Auto-generated constructor stub

}

void DynamicCommunityDetection::run(std::string inputPath, std::string algoName, count interval) {
	DEBUG("reading full event stream from file");
	DGSStreamParser parser(inputPath, true, 1);
	std::vector<GraphEvent> stream = parser.getStream();
	DEBUG("setting up graph");
	Graph G;
	GraphUpdater gu(G);

	DEBUG("setting up algorithms");
	DynCommunityDetector* algo = NULL;
	if (algoName == "DynPLP") {
		algo = new DynPLP();
	} else if (algoName == "DynPLM") {
		algo = new DynPLM();
	}

	algo->attachGraph(G);

	// slicing stream
	auto i = stream.begin();
	auto j = i + interval;
	if (j > stream.end()) {
		j = stream.end();
	}

	while (i < stream.end()) { // TODO: rest of stream
		std::vector<GraphEvent> slice(i, j);
		DEBUG("updating graph");
		gu.update(slice);
		DEBUG("number of nodes: " << G.numberOfNodes());

		algo->process(slice);
		Clustering zeta = algo->retrieve();
		DEBUG("upper community id bound: " << zeta.upperBound());
		// DEBUG("zeta at time " << G.time() << ": " << Aux::vectorToString(zeta.getVector()));

		Modularity mod;
		INFO("modularity at time " << G.time() << ": " << mod.getQuality(zeta, G));

		//
		i = j;
		j = i + interval;
		if (j > stream.end()) {
			j = stream.end();
		}
	}

}

} /* namespace NetworKit */
<commit_msg>event stream now sliced by time steps<commit_after>/*
 * DynamicCommunityDetection.cpp
 *
 *  Created on: 10.01.2014
 *      Author: cls
 */

#include "DynamicCommunityDetection.h"

#include "DynPLP.h"
#include "DynPLM.h"
#include "../dynamics/DGSStreamParser.h"
#include "../dynamics/GraphUpdater.h"
#include "../clustering/Modularity.h"

namespace NetworKit {

DynamicCommunityDetection::DynamicCommunityDetection() {
	// TODO Auto-generated constructor stub

}

void DynamicCommunityDetection::run(std::string inputPath, std::string algoName, count interval) {
	DEBUG("reading full event stream from file");
	DGSStreamParser parser(inputPath, true, 1);
	std::vector<GraphEvent> stream = parser.getStream();
	DEBUG("setting up graph");
	Graph G;
	GraphUpdater gu(G);

	DEBUG("setting up algorithms");
	DynCommunityDetector* algo = NULL;
	if (algoName == "DynPLP") {
		algo = new DynPLP();
	} else if (algoName == "DynPLM") {
		algo = new DynPLM();
	}

	algo->attachGraph(G);

	// slicing stream by timesteps
	auto i = stream.begin();
	auto j = stream.begin();

	auto advance = [&](){
		count steps = 0;
		i = j;
		for (; (steps < interval) && (j < stream.end()); ++j) {
			if (j->type == GraphEvent::TIME_STEP) {
				steps++;
			}
		}
	};

	while (j != stream.end()) {
		advance(); // advance iterators
		std::vector<GraphEvent> slice(i, j);
		DEBUG("updating graph");
		gu.update(slice);
		DEBUG("number of nodes: " << G.numberOfNodes());

		algo->process(slice);
		Clustering zeta = algo->retrieve();
		DEBUG("upper community id bound: " << zeta.upperBound());
		// DEBUG("zeta at time " << G.time() << ": " << Aux::vectorToString(zeta.getVector()));

		Modularity mod;
		INFO("modularity at time " << G.time() << ": " << mod.getQuality(zeta, G));

	}

}

} /* namespace NetworKit */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: grammarchecker.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _LINGUISTIC_GRAMMARCHECKER_HXX_
#define _LINGUISTIC_GRAMMARCHECKER_HXX_

#include <cppuhelper/implbase4.hxx>
#include <com/sun/star/linguistic2/XGrammarChecker.hpp>
#include <com/sun/star/linguistic2/XGrammarCheckingResultBroadcaster.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/interfacecontainer.h>
#include <map>
#include <com/sun/star/linguistic2/SingleGrammarError.hpp>
#include <com/sun/star/linguistic2/XSupportedLocales.hpp>

class GrammarChecker:
    public cppu::WeakImplHelper4
    <
        ::com::sun::star::linguistic2::XGrammarChecker,
        ::com::sun::star::linguistic2::XGrammarCheckingResultBroadcaster,
        ::com::sun::star::lang::XComponent,
        ::com::sun::star::lang::XServiceInfo
    >
{
//    com::sun::star::uno::Reference< uno::XComponentContext > m_xContext;
    ::cppu::OInterfaceContainerHelper m_aGCListeners;
    // disallow use of copy c-tor and assignment operator
    GrammarChecker( const GrammarChecker & );
    GrammarChecker & operator = ( const GrammarChecker & );

public:
    explicit GrammarChecker( /* uno::Reference< uno::XComponentContext > const & rXContext */ );
    virtual ~GrammarChecker();

    //sal_Int32 m_Doc;

    // XSupportedLocales
    virtual ::sal_Bool SAL_CALL hasLocale( const ::com::sun::star::lang::Locale & aLocale) throw (::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getLocales(  ) throw ( ::com::sun::star::uno::RuntimeException );

    // XGrammarChecker
    virtual ::sal_Bool SAL_CALL isSpellChecker( const ::com::sun::star::lang::Locale& aLocale ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startDocument( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startParagraph( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endParagraph( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endDocument( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL doGrammarChecking( ::sal_Int32 nDocId, const ::com::sun::star::uno::Reference< ::com::sun::star::text::XFlatParagraph >& xFlatPara, const ::com::sun::star::lang::Locale& aLocale, ::sal_Int32 nStartOfSentencePos, ::sal_Int32 nSuggestedSentenceEndPos ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual ::sal_Int32 SAL_CALL getEndOfSentencePos( ::sal_Int32 nDocId, const ::rtl::OUString& aFlatParaText, const ::com::sun::star::lang::Locale& aLocale, ::sal_Int32 nStartOfSentencePos ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual ::sal_Int32 SAL_CALL getStartOfSentencePos( ::sal_Int32 nDocId, const ::rtl::OUString& aFlatParaText, const ::com::sun::star::lang::Locale& aLocale ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL requiresPreviousText(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL hasCheckingDialog(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL hasOptionsDialog(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL runCheckingDialog( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL runOptionsDialog( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);

    // XGrammarCheckingResultBroadcaster
    virtual ::sal_Bool SAL_CALL addGrammarCheckingResultListener( const ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XGrammarCheckingResultListener >& xLstnr ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL removeGrammarCheckingResultListener( const ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XGrammarCheckingResultListener >& xLstnr ) throw (::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw ( ::com::sun::star::uno::RuntimeException );

    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);

    virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

    static inline ::rtl::OUString getImplementationName_Static();

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw();

    ::com::sun::star::uno::Sequence< ::com::sun::star::linguistic2::SingleGrammarError > GrammarCheckingInDummy(
        ::sal_Int32 nDocId, const ::rtl::OUString aFlatParaText, const ::com::sun::star::lang::Locale & rLocale,
        ::sal_Int32 nStartOfSentencePos, ::sal_Int32 nSuggestedSentenceEndPos );

    inline ::osl::Mutex & GetMutex()
    {
        static osl::Mutex aMutex;
        return aMutex;
    }
};

inline ::rtl::OUString GrammarChecker::getImplementationName_Static()
{
    return A2OU( "com.sun.star.lingu2.GrammarChecker" );
}

#endif

<commit_msg>INTEGRATION: CWS tl55 (1.3.8); FILE MERGED 2008/06/25 06:03:52 tl 1.3.8.3: #158047# customer specific extension 2008/06/07 15:24:21 tl 1.3.8.2: #i85999# grammar checking framework 2008/05/27 11:17:52 tl 1.3.8.1: #i85999# improve grammar checking framework<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: grammarchecker.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _LINGUISTIC_GRAMMARCHECKER_HXX_
#define _LINGUISTIC_GRAMMARCHECKER_HXX_

#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/linguistic2/XGrammarChecker.hpp>
#include <com/sun/star/linguistic2/SingleGrammarError.hpp>
#include <com/sun/star/linguistic2/XSupportedLocales.hpp>

#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/interfacecontainer.h>

#include <map>

class GrammarChecker:
    public cppu::WeakImplHelper3
    <
        ::com::sun::star::linguistic2::XGrammarChecker,
        ::com::sun::star::lang::XComponent,
        ::com::sun::star::lang::XServiceInfo
    >
{
//    com::sun::star::uno::Reference< uno::XComponentContext > m_xContext;

    // disallow use of copy c-tor and assignment operator
    GrammarChecker( const GrammarChecker & );
    GrammarChecker & operator = ( const GrammarChecker & );

public:
    explicit GrammarChecker( /* uno::Reference< uno::XComponentContext > const & rXContext */ );
    virtual ~GrammarChecker();

    // XSupportedLocales
    virtual ::sal_Bool SAL_CALL hasLocale( const ::com::sun::star::lang::Locale & aLocale) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getLocales(  ) throw ( ::com::sun::star::uno::RuntimeException );

    // XGrammarChecker
    virtual ::sal_Bool SAL_CALL isSpellChecker(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startDocument( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL startParagraph( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endParagraph( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL endDocument( ::sal_Int32 nDocId ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::linguistic2::GrammarCheckingResult SAL_CALL doGrammarChecking( ::sal_Int32 nDocId, const ::rtl::OUString& aText, const ::com::sun::star::lang::Locale& aLocale, ::sal_Int32 nStartOfSentencePos, ::sal_Int32 nSuggestedEndOfSentencePos, const ::com::sun::star::uno::Sequence< ::sal_Int32 >& aLanguagePortions, const ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale >& aLanguagePortionsLocales ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL hasOptionsDialog(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL runOptionsDialog(  ) throw (::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw ( ::com::sun::star::uno::RuntimeException );
    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

    static inline ::rtl::OUString getImplementationName_Static();
    static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw();

    ::com::sun::star::uno::Sequence< ::com::sun::star::linguistic2::SingleGrammarError > GrammarCheckingInDummy(
        ::sal_Int32 nDocId, const ::rtl::OUString &rFlatParaText, const ::com::sun::star::lang::Locale & rLocale,
        ::sal_Int32 nStartOfSentencePos, ::sal_Int32 nSuggestedSentenceEndPos );

    inline ::osl::Mutex & GetMutex()
    {
        static osl::Mutex aMutex;
        return aMutex;
    }
};

inline ::rtl::OUString GrammarChecker::getImplementationName_Static()
{
    return A2OU( "com.sun.star.lingu2.GrammarChecker" );
}

#endif

<|endoftext|>


<commit_before>// Copyright 2015, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Björn Buchhold (buchhold@informatik.uni-freiburg.de)

#include <sstream>

#include "./QueryExecutionTree.h"
#include "TextOperationWithFilter.h"

using std::string;

// _____________________________________________________________________________
size_t TextOperationWithFilter::getResultWidth() const {
  return 1 + _nofVars + _filterResult->getResultWidth();
}

// _____________________________________________________________________________
TextOperationWithFilter::TextOperationWithFilter(
    QueryExecutionContext* qec, const string& words, size_t nofVars,
    std::shared_ptr<QueryExecutionTree> filterResult, size_t filterColumn,
    size_t textLimit) :
    Operation(qec), _words(words), _nofVars(nofVars),
    _filterResult(filterResult),
    _filterColumn(filterColumn) {
  setTextLimit(textLimit);
}

// _____________________________________________________________________________
string TextOperationWithFilter::asString(size_t indent) const {
  std::ostringstream os;
  for (size_t i = 0; i < indent; ++i) { os << " "; }
  os << "TEXT OPERATION WITH FILTER:" << " co-occurrence with words: \"" <<
     _words << "\" and " << _nofVars << " variables with textLimit = " <<
     _textLimit << " filtered by\n" <<
     _filterResult->asString(indent) << "\n";
  for (size_t i = 0; i < indent; ++i) { os << " "; }
  os << " filtered on column " << _filterColumn;
  return os.str();
}

// _____________________________________________________________________________
void TextOperationWithFilter::computeResult(ResultTable* result) const {
  LOG(DEBUG) << "TextOperationWithFilter result computation..." << endl;
  AD_CHECK_GE(_nofVars, 1);
  result->_nofColumns = 1 + _filterResult->getResultWidth() + _nofVars;
  if (_filterResult->getResultWidth() == 1) {
    AD_CHECK_GE(result->_nofColumns, 3);
    if (result->_nofColumns == 3) {
      result->_fixedSizeData = new vector<array<Id, 3>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 3>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 4) {
      result->_fixedSizeData = new vector<array<Id, 4>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 4>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 2) {
    AD_CHECK_GE(result->_nofColumns, 4);
    if (result->_nofColumns == 4) {
      result->_fixedSizeData = new vector<array<Id, 4>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 4>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 3) {
    AD_CHECK_GE(result->_nofColumns, 5);
    if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 3>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 3>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 4) {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        *static_cast<vector<array<Id, 4>>*>(_filterResult->getResult()._fixedSizeData),
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  } else if (_filterResult->getResultWidth() == 5) {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        *static_cast<vector<array<Id, 5>>*>(_filterResult->getResult()._fixedSizeData),
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  } else {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        _filterResult->getResult()._varSizeData,
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  }
  result->_status = ResultTable::FINISHED;
  LOG(DEBUG) << "TextOperationWithFilter result computation done." << endl;
}

// _____________________________________________________________________________
float TextOperationWithFilter::getMultiplicity(size_t col) {
  if (_multiplicities.size() == 0) {
    computeMultiplicities();
  }
  AD_CHECK_LT(col, _multiplicities.size());
  return _multiplicities[col];
}

// _____________________________________________________________________________
void TextOperationWithFilter::computeMultiplicities() {
  if (_executionContext) {
    // Like without filter
    vector<float> multiplicitiesNoFilter;
    for (size_t i = 0;
         i < getResultWidth() + 1 - _filterResult->getResultWidth(); ++i) {
      double nofEntitiesSingleVar;
      if (_executionContext) {
        nofEntitiesSingleVar =
            _executionContext->getIndex().getSizeEstimate(_words) *
            std::min(float(_textLimit),
                     _executionContext->getIndex().getAverageNofEntityContexts());
      } else {
        nofEntitiesSingleVar = 10000 * 0.8;
      }
      multiplicitiesNoFilter.emplace_back(
          pow(nofEntitiesSingleVar, _nofVars - 1));
    }

    assert(multiplicitiesNoFilter.size() > 2);

    // Like joins
    float _leftJcM = multiplicitiesNoFilter[2];
    float _rightJcM = _filterResult->getMultiplicity(_filterColumn);
    for (size_t i = 0; i < multiplicitiesNoFilter.size() - 1; ++i) {
      _multiplicities.emplace_back(multiplicitiesNoFilter[i] * _rightJcM);
    }
    for (size_t i = 0; i < _filterResult->getResultWidth(); ++i) {
      _multiplicities.emplace_back(
          _filterResult->getMultiplicity(i) * _leftJcM);
    }
  } else {
    for (size_t i = 0; i < getResultWidth(); ++i) {
      _multiplicities.emplace_back(1);
    }
  }
  assert(_multiplicities.size() == getResultWidth());
}

// _____________________________________________________________________________
size_t TextOperationWithFilter::getSizeEstimate() {
  if (_sizeEstimate == std::numeric_limits<size_t>::max()) {
    if (_executionContext) {
      // NEW at 05 Dec 2016:
      // Estimate the size of the result like the equivalent text without filter
      // plus join.
      double nofEntitiesSingleVar;
      if (_executionContext) {
        nofEntitiesSingleVar =
            _executionContext->getIndex().getSizeEstimate(_words) *
            std::min(float(_textLimit),
                     _executionContext->getIndex().getAverageNofEntityContexts());
      } else {
        nofEntitiesSingleVar = 10000 * 0.8;
      }

      auto estNoFil = static_cast<size_t>(pow(nofEntitiesSingleVar, _nofVars));

      size_t nofDistinctFilter = static_cast<size_t>(
          _filterResult->getSizeEstimate() /
          _filterResult->getMultiplicity(_filterColumn));

      float joinColMultiplicity = getMultiplicity(
          2 + (_nofVars - 1) + _filterColumn);

      _sizeEstimate = std::max(size_t(1), static_cast<size_t>(
          _executionContext->getCostFactor(
              "JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR") *
          joinColMultiplicity *
          std::min(nofDistinctFilter, estNoFil)));
    }
    _sizeEstimate = size_t(10000 * 0.8);
  }
  return _sizeEstimate;
}

// _____________________________________________________________________________
size_t TextOperationWithFilter::getCostEstimate() {
  if (_filterResult->knownEmptyResult()) {
    return 0;
  }
  if (_executionContext) {
    return static_cast<size_t>(
        _executionContext->getCostFactor("FILTER_PUNISH") * (
            getSizeEstimate() * _nofVars +
            _filterResult->getSizeEstimate() *
            _executionContext->getCostFactor("HASH_MAP_OPERATION_COST") +
            _filterResult->getCostEstimate()));
  } else {
    return _filterResult->getSizeEstimate() * 2 +
           _filterResult->getCostEstimate();
  }
}
<commit_msg>fixed bug (typo with bad consequences) in the size estimate of scans with filter<commit_after>// Copyright 2015, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Björn Buchhold (buchhold@informatik.uni-freiburg.de)

#include <sstream>

#include "./QueryExecutionTree.h"
#include "TextOperationWithFilter.h"

using std::string;

// _____________________________________________________________________________
size_t TextOperationWithFilter::getResultWidth() const {
  return 1 + _nofVars + _filterResult->getResultWidth();
}

// _____________________________________________________________________________
TextOperationWithFilter::TextOperationWithFilter(
    QueryExecutionContext* qec, const string& words, size_t nofVars,
    std::shared_ptr<QueryExecutionTree> filterResult, size_t filterColumn,
    size_t textLimit) :
    Operation(qec), _words(words), _nofVars(nofVars),
    _filterResult(filterResult),
    _filterColumn(filterColumn) {
  setTextLimit(textLimit);
}

// _____________________________________________________________________________
string TextOperationWithFilter::asString(size_t indent) const {
  std::ostringstream os;
  for (size_t i = 0; i < indent; ++i) { os << " "; }
  os << "TEXT OPERATION WITH FILTER:" << " co-occurrence with words: \"" <<
     _words << "\" and " << _nofVars << " variables with textLimit = " <<
     _textLimit << " filtered by\n" <<
     _filterResult->asString(indent) << "\n";
  for (size_t i = 0; i < indent; ++i) { os << " "; }
  os << " filtered on column " << _filterColumn;
  return os.str();
}

// _____________________________________________________________________________
void TextOperationWithFilter::computeResult(ResultTable* result) const {
  LOG(DEBUG) << "TextOperationWithFilter result computation..." << endl;
  AD_CHECK_GE(_nofVars, 1);
  result->_nofColumns = 1 + _filterResult->getResultWidth() + _nofVars;
  if (_filterResult->getResultWidth() == 1) {
    AD_CHECK_GE(result->_nofColumns, 3);
    if (result->_nofColumns == 3) {
      result->_fixedSizeData = new vector<array<Id, 3>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 3>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 4) {
      result->_fixedSizeData = new vector<array<Id, 4>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 4>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 1>>*>(_filterResult->getResult()._fixedSizeData),
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 2) {
    AD_CHECK_GE(result->_nofColumns, 4);
    if (result->_nofColumns == 4) {
      result->_fixedSizeData = new vector<array<Id, 4>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 4>>*>(result->_fixedSizeData));
    } else if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 2>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 3) {
    AD_CHECK_GE(result->_nofColumns, 5);
    if (result->_nofColumns == 5) {
      result->_fixedSizeData = new vector<array<Id, 5>>;
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 3>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          *reinterpret_cast<vector<array<Id, 5>>*>(result->_fixedSizeData));
    } else {
      getExecutionContext()->getIndex().getFilteredECListForWords(
          _words,
          *static_cast<vector<array<Id, 3>>*>(_filterResult->getResult()._fixedSizeData),
          _filterColumn,
          _nofVars,
          _textLimit,
          result->_varSizeData);
    }
  } else if (_filterResult->getResultWidth() == 4) {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        *static_cast<vector<array<Id, 4>>*>(_filterResult->getResult()._fixedSizeData),
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  } else if (_filterResult->getResultWidth() == 5) {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        *static_cast<vector<array<Id, 5>>*>(_filterResult->getResult()._fixedSizeData),
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  } else {
    getExecutionContext()->getIndex().getFilteredECListForWords(
        _words,
        _filterResult->getResult()._varSizeData,
        _filterColumn,
        _nofVars,
        _textLimit,
        result->_varSizeData);
  }
  result->_status = ResultTable::FINISHED;
  LOG(DEBUG) << "TextOperationWithFilter result computation done." << endl;
}

// _____________________________________________________________________________
float TextOperationWithFilter::getMultiplicity(size_t col) {
  if (_multiplicities.size() == 0) {
    computeMultiplicities();
  }
  AD_CHECK_LT(col, _multiplicities.size());
  return _multiplicities[col];
}

// _____________________________________________________________________________
void TextOperationWithFilter::computeMultiplicities() {
  if (_executionContext) {
    // Like without filter
    vector<float> multiplicitiesNoFilter;
    for (size_t i = 0;
         i < getResultWidth() + 1 - _filterResult->getResultWidth(); ++i) {
      double nofEntitiesSingleVar;
      if (_executionContext) {
        nofEntitiesSingleVar =
            _executionContext->getIndex().getSizeEstimate(_words) *
            std::min(float(_textLimit),
                     _executionContext->getIndex().getAverageNofEntityContexts());
      } else {
        nofEntitiesSingleVar = 10000 * 0.8;
      }
      multiplicitiesNoFilter.emplace_back(
          pow(nofEntitiesSingleVar, _nofVars - 1));
    }

    assert(multiplicitiesNoFilter.size() > 2);

    // Like joins
    float _leftJcM = multiplicitiesNoFilter[2];
    float _rightJcM = _filterResult->getMultiplicity(_filterColumn);
    for (size_t i = 0; i < multiplicitiesNoFilter.size() - 1; ++i) {
      _multiplicities.emplace_back(multiplicitiesNoFilter[i] * _rightJcM);
    }
    for (size_t i = 0; i < _filterResult->getResultWidth(); ++i) {
      _multiplicities.emplace_back(
          _filterResult->getMultiplicity(i) * _leftJcM);
    }
  } else {
    for (size_t i = 0; i < getResultWidth(); ++i) {
      _multiplicities.emplace_back(1);
    }
  }
  assert(_multiplicities.size() == getResultWidth());
}

// _____________________________________________________________________________
size_t TextOperationWithFilter::getSizeEstimate() {
  if (_sizeEstimate == std::numeric_limits<size_t>::max()) {
    if (_executionContext) {
      // NEW at 05 Dec 2016:
      // Estimate the size of the result like the equivalent text without filter
      // plus join.
      double nofEntitiesSingleVar =
          _executionContext->getIndex().getSizeEstimate(_words) *
          std::min(float(_textLimit),
                   _executionContext->getIndex().getAverageNofEntityContexts());

      auto estNoFil = static_cast<size_t>(pow(nofEntitiesSingleVar, _nofVars));

      size_t nofDistinctFilter = static_cast<size_t>(
          _filterResult->getSizeEstimate() /
          _filterResult->getMultiplicity(_filterColumn));

      float joinColMultiplicity = getMultiplicity(
          2 + (_nofVars - 1) + _filterColumn);

      _sizeEstimate = std::max(size_t(1), static_cast<size_t>(
          _executionContext->getCostFactor(
              "JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR") *
          joinColMultiplicity *
          std::min(nofDistinctFilter, estNoFil)));
    } else {
      _sizeEstimate = size_t(10000 * 0.8);
    }
  }
  return _sizeEstimate;
}

// _____________________________________________________________________________
size_t TextOperationWithFilter::getCostEstimate() {
  if (_filterResult->knownEmptyResult()) {
    return 0;
  }
  if (_executionContext) {
    return static_cast<size_t>(
        _executionContext->getCostFactor("FILTER_PUNISH") * (
            getSizeEstimate() * _nofVars +
            _filterResult->getSizeEstimate() *
            _executionContext->getCostFactor("HASH_MAP_OPERATION_COST") +
            _filterResult->getCostEstimate()));
  } else {
    return _filterResult->getSizeEstimate() * 2 +
           _filterResult->getCostEstimate();
  }
}
<|endoftext|>


<commit_before>class Solution {
public:
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int alen=A.size();
        int blen=B.size();

        // dp[i][j] means A[0..i) and B[0,j)'s longest common substring length
        // includes the A[i-1] and B[j-1]
        vector<int> dp(blen+1,0);

        int res=0;
        for(int i=1; i<=alen; i++){
            for(int j=blen; j>=0; j--){
                if(A[i-1]==B[j-1]){
                    dp[j]=dp[j-1]+1;
                }else{
                    dp[j]=0;
                }
                res=max(res,dp[j]);
            }
        }

        return res;
    }
};

<commit_msg>Update longestcommonsubstring_.cpp<commit_after>class Solution {
public:
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int alen=A.size();
        int blen=B.size();

        // dp[i][j] means the length of longest common substring of A[0..i) which must be ended with A[i-1] and B[0..j)'s which must be ended with B[j-1].
        // below is using 1-dim dp array
        vector<int> dp(blen+1,0);

        int res=0;
        for(int i=1; i<=alen; i++){
            for(int j=blen; j>=0; j--){
                if(A[i-1]==B[j-1]){
                    dp[j]=dp[j-1]+1;
                }else{
                    dp[j]=0;
                }
                res=max(res,dp[j]);
            }
        }

        return res;
    }
};

<|endoftext|>


<commit_before>#ifdef _WIN32

#include <assert.h>

#include "win_fsnotifier.h"

using namespace std;

//
// WatchPoint
//

WatchPoint::WatchPoint(Server* server, const u16string& path)
    : path(path)
    , status(NOT_LISTENING) {
    wstring pathW(path.begin(), path.end());
    HANDLE directoryHandle = CreateFileW(
        pathW.c_str(),          // pointer to the file name
        FILE_LIST_DIRECTORY,    // access (read/write) mode
        CREATE_SHARE,           // share mode
        NULL,                   // security descriptor
        OPEN_EXISTING,          // how to create
        CREATE_FLAGS,           // file attributes
        NULL                    // file with attributes to copy
    );
    if (directoryHandle == INVALID_HANDLE_VALUE) {
        throw FileWatcherException("Couldn't add watch", path, GetLastError());
    }
    this->directoryHandle = directoryHandle;

    this->server = server;
    this->buffer.reserve(EVENT_BUFFER_SIZE);
    ZeroMemory(&this->overlapped, sizeof(OVERLAPPED));
    this->overlapped.hEvent = this;
    listen();
}

WatchPoint::~WatchPoint() {
}

void WatchPoint::cancel() {
    if (status == LISTENING) {
        log_fine(server->getThreadEnv(), "Cancelling %s", utf16ToUtf8String(path).c_str());
        status = CANCELLED;
        BOOL ret = CancelIo(directoryHandle);
        if (!ret) {
            throw FileWatcherException("Couldn't cancel I/O", path, GetLastError());
        }
    }
}

static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransferred, LPOVERLAPPED overlapped) {
    WatchPoint* watchPoint = (WatchPoint*) overlapped->hEvent;
    watchPoint->handleEventsInBuffer(errorCode, bytesTransferred);
}

void WatchPoint::listen() {
    BOOL success = ReadDirectoryChangesW(
        directoryHandle,        // handle to directory
        &buffer[0],             // read results buffer
        EVENT_BUFFER_SIZE,      // length of buffer
        TRUE,                   // include children
        EVENT_MASK,             // filter conditions
        NULL,                   // bytes returned
        &overlapped,            // overlapped buffer
        &handleEventCallback    // completion routine
    );
    if (success) {
        status = LISTENING;
    } else {
        status = FINISHED;
        throw FileWatcherException("Couldn't start watching", path, GetLastError());
    }
}

void WatchPoint::handleEventsInBuffer(DWORD errorCode, DWORD bytesTransferred) {
    if (errorCode == ERROR_OPERATION_ABORTED) {
        log_fine(server->getThreadEnv(), "Finished watching '%s', status = %d", utf16ToUtf8String(path).c_str(), status);
        BOOL ret = CloseHandle(directoryHandle);
        if (!ret) {
            log_severe(server->getThreadEnv(), "Couldn't close handle %p for '%ls': %d", directoryHandle, utf16ToUtf8String(path).c_str(), GetLastError());
        }
        status = FINISHED;
        return;
    }

    if (status != LISTENING) {
        log_fine(server->getThreadEnv(), "Ignoring incoming events for %s as watch-point is not listening (%d bytes, errorCode = %d, status = %d)",
            utf16ToUtf8String(path).c_str(), bytesTransferred, errorCode, status);
        return;
    }
    status = NOT_LISTENING;
    server->handleEvents(this, errorCode, buffer, bytesTransferred);
}

void Server::handleEvents(WatchPoint* watchPoint, DWORD errorCode, const vector<BYTE>& buffer, DWORD bytesTransferred) {
    JNIEnv* env = getThreadEnv();
    const u16string& path = watchPoint->path;

    try {
        if (errorCode != ERROR_SUCCESS) {
            throw FileWatcherException("Error received when handling events", path, errorCode);
        }

        if (terminated) {
            log_fine(env, "Ignoring incoming events for %s because server is terminating (%d bytes)",
                utf16ToUtf8String(path).c_str(), bytesTransferred, watchPoint->status);
            return;
        }

        if (bytesTransferred == 0) {
            // Got a buffer overflow => current changes lost => send INVALIDATE on root
            log_info(env, "Detected overflow for %s", utf16ToUtf8String(path).c_str());
            reportChange(env, FILE_EVENT_INVALIDATE, path);
        } else {
            int index = 0;
            for (;;) {
                FILE_NOTIFY_INFORMATION* current = (FILE_NOTIFY_INFORMATION*) &buffer[index];
                handleEvent(env, path, current);
                if (current->NextEntryOffset == 0) {
                    break;
                }
                index += current->NextEntryOffset;
            }
        }

        watchPoint->listen();
    } catch (const exception& ex) {
        reportError(env, ex);
    }
}

bool isAbsoluteLocalPath(const u16string& path) {
    if (path.length() < 3) {
        return false;
    }
    return ((u'a' <= path[0] && path[0] <= u'z') || (u'A' <= path[0] && path[0] <= u'Z'))
        && path[1] == u':'
        && path[2] == u'\\';
}

bool isAbsoluteUncPath(const u16string& path) {
    if (path.length() < 3) {
        return false;
    }
    return path[0] == u'\\' && path[1] == u'\\';
}

bool isLongPath(const u16string& path) {
    return path.length() >= 4 && path.substr(0, 4) == u"\\\\?\\";
}

bool isUncLongPath(const u16string& path) {
    return path.length() >= 8 && path.substr(0, 8) == u"\\\\?\\UNC\\";
}

// TODO How can this be done nicer, wihtout both unnecessary copy and in-place mutation?
void convertToLongPathIfNeeded(u16string& path) {
    // Technically, this should be MAX_PATH (i.e. 260), except some Win32 API related
    // to working with directory paths are actually limited to 240. It is just
    // safer/simpler to cover both cases in one code path.
    if (path.length() <= 240) {
        return;
    }

    // It is already a long path, nothing to do here
    if (isLongPath(path)) {
        return;
    }

    if (isAbsoluteLocalPath(path)) {
        // Format: C:\... -> \\?\C:\...
        path.insert(0, u"\\\\?\\");
    } else if (isAbsoluteUncPath(path)) {
        // In this case, we need to skip the first 2 characters:
        // Format: \\server\share\... -> \\?\UNC\server\share\...
        path.erase(0, 2);
        path.insert(0, u"\\\\?\\UNC\\");
    } else {
        // It is some sort of unknown format, don't mess with it
    }
}

void Server::handleEvent(JNIEnv* env, const u16string& path, FILE_NOTIFY_INFORMATION* info) {
    wstring changedPathW = wstring(info->FileName, 0, info->FileNameLength / sizeof(wchar_t));
    u16string changedPath(changedPathW.begin(), changedPathW.end());
    if (!changedPath.empty()) {
        changedPath.insert(0, 1, u'\\');
    }
    changedPath.insert(0, path);
    // TODO Remove long prefix for path once?
    if (isLongPath(changedPath)) {
        if (isUncLongPath(changedPath)) {
            changedPath.erase(0, 8).insert(0, u"\\\\");
        } else {
            changedPath.erase(0, 4);
        }
    }

    log_fine(env, "Change detected: 0x%x '%ls'", info->Action, changedPathW.c_str());

    jint type;
    if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_NEW_NAME) {
        type = FILE_EVENT_CREATED;
    } else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
        type = FILE_EVENT_REMOVED;
    } else if (info->Action == FILE_ACTION_MODIFIED) {
        type = FILE_EVENT_MODIFIED;
    } else {
        log_warning(env, "Unknown event 0x%x for %ls", info->Action, changedPathW.c_str());
        type = FILE_EVENT_UNKNOWN;
    }

    reportChange(env, type, changedPath);
}

//
// Server
//

Server::Server(JNIEnv* env, jobject watcherCallback)
    : AbstractServer(env, watcherCallback) {
    startThread();
    // TODO Error handling
    SetThreadPriority(this->watcherThread.native_handle(), THREAD_PRIORITY_ABOVE_NORMAL);
}

void Server::terminate() {
    log_fine(getThreadEnv(), "Terminating", NULL);
    terminated = true;
}

Server::~Server() {
    executeOnThread(shared_ptr<Command>(new TerminateCommand()));

    if (watcherThread.joinable()) {
        watcherThread.join();
    }
}

void Server::runLoop(JNIEnv* env, function<void(exception_ptr)> notifyStarted) {
    notifyStarted(nullptr);

    while (!terminated) {
        SleepEx(INFINITE, true);
    }

    // We have received termination, cancel all watchers
    log_fine(env, "Finished with run loop, now cancelling remaining watch points", NULL);
    int openWatchPoints = 0;
    for (auto& it : watchPoints) {
        auto& watchPoint = it.second;
        switch (watchPoint.status) {
            case LISTENING:
                watchPoint.cancel();
                openWatchPoints++;
                break;
            case CANCELLED:
                openWatchPoints++;
                break;
            default:
                break;
        }
    }

    // If there are any remaining watchers, wait for them to be terminated
    if (openWatchPoints == 0) {
        log_fine(env, "No watch points were open upon termination", NULL);
    } else {
        log_fine(env, "Waiting for %d watch points to abort", openWatchPoints);
        SleepEx(SERVER_CLOSE_TIMEOUT_IN_MS, true);
    }

    // Check if we have any unclosed watchpoints
    for (auto& it : watchPoints) {
        auto& watchPoint = it.second;
        switch (watchPoint.status) {
            case FINISHED:
                break;
            default:
                log_severe(env, "Couldn't close watch point %s, status = %d", utf16ToUtf8String(watchPoint.path).c_str(), watchPoint.status);
                break;
        }
    }

    // Close all handles
    log_fine(env, "Closing handles for %d watch points", watchPoints.size());
    watchPoints.clear();
}

static void CALLBACK processCommandsCallback(_In_ ULONG_PTR info) {
    Server* server = (Server*) info;
    server->processCommands();
}

void Server::processCommandsOnThread() {
    QueueUserAPC(processCommandsCallback, watcherThread.native_handle(), (ULONG_PTR) this);
}

void Server::registerPath(const u16string& path) {
    u16string longPath = path;
    convertToLongPathIfNeeded(longPath);
    auto it = watchPoints.find(longPath);
    if (it != watchPoints.end()) {
        if (it->second.status != FINISHED) {
            throw FileWatcherException("Already watching path", path);
        }
        watchPoints.erase(it);
    }
    watchPoints.emplace(piecewise_construct,
        forward_as_tuple(longPath),
        forward_as_tuple(this, longPath));
}

void Server::unregisterPath(const u16string& path) {
    u16string longPath = path;
    convertToLongPathIfNeeded(longPath);
    auto it = watchPoints.find(longPath);
    if (it == watchPoints.end()) {
        log_fine(getThreadEnv(), "Path is not watched: %s", utf16ToUtf8String(path).c_str());
        return;
    }
    it->second.cancel();
}

//
// JNI calls
//

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_startWatcher(JNIEnv* env, jclass target, jobject javaCallback) {
    return wrapServer(env, [env, javaCallback]() {
        return new Server(env, javaCallback);
    });
}

#endif
<commit_msg>Polish names and log messages<commit_after>#ifdef _WIN32

#include <assert.h>

#include "win_fsnotifier.h"

using namespace std;

//
// WatchPoint
//

WatchPoint::WatchPoint(Server* server, const u16string& path)
    : path(path)
    , status(NOT_LISTENING) {
    wstring pathW(path.begin(), path.end());
    HANDLE directoryHandle = CreateFileW(
        pathW.c_str(),          // pointer to the file name
        FILE_LIST_DIRECTORY,    // access (read/write) mode
        CREATE_SHARE,           // share mode
        NULL,                   // security descriptor
        OPEN_EXISTING,          // how to create
        CREATE_FLAGS,           // file attributes
        NULL                    // file with attributes to copy
    );
    if (directoryHandle == INVALID_HANDLE_VALUE) {
        throw FileWatcherException("Couldn't add watch", path, GetLastError());
    }
    this->directoryHandle = directoryHandle;

    this->server = server;
    this->buffer.reserve(EVENT_BUFFER_SIZE);
    ZeroMemory(&this->overlapped, sizeof(OVERLAPPED));
    this->overlapped.hEvent = this;
    listen();
}

WatchPoint::~WatchPoint() {
}

void WatchPoint::cancel() {
    if (status == LISTENING) {
        log_fine(server->getThreadEnv(), "Cancelling %s", utf16ToUtf8String(path).c_str());
        status = CANCELLED;
        BOOL ret = CancelIo(directoryHandle);
        if (!ret) {
            throw FileWatcherException("Couldn't cancel I/O", path, GetLastError());
        }
    }
}

static void CALLBACK handleEventCallback(DWORD errorCode, DWORD bytesTransferred, LPOVERLAPPED overlapped) {
    WatchPoint* watchPoint = (WatchPoint*) overlapped->hEvent;
    watchPoint->handleEventsInBuffer(errorCode, bytesTransferred);
}

void WatchPoint::listen() {
    BOOL success = ReadDirectoryChangesW(
        directoryHandle,        // handle to directory
        &buffer[0],             // read results buffer
        EVENT_BUFFER_SIZE,      // length of buffer
        TRUE,                   // include children
        EVENT_MASK,             // filter conditions
        NULL,                   // bytes returned
        &overlapped,            // overlapped buffer
        &handleEventCallback    // completion routine
    );
    if (success) {
        status = LISTENING;
    } else {
        status = FINISHED;
        throw FileWatcherException("Couldn't start watching", path, GetLastError());
    }
}

void WatchPoint::handleEventsInBuffer(DWORD errorCode, DWORD bytesTransferred) {
    if (errorCode == ERROR_OPERATION_ABORTED) {
        log_fine(server->getThreadEnv(), "Finished watching '%s', status = %d", utf16ToUtf8String(path).c_str(), status);
        BOOL ret = CloseHandle(directoryHandle);
        if (!ret) {
            log_severe(server->getThreadEnv(), "Couldn't close handle %p for '%ls': %d", directoryHandle, utf16ToUtf8String(path).c_str(), GetLastError());
        }
        status = FINISHED;
        return;
    }

    if (status != LISTENING) {
        log_fine(server->getThreadEnv(), "Ignoring incoming events for %s as watch-point is not listening (%d bytes, errorCode = %d, status = %d)",
            utf16ToUtf8String(path).c_str(), bytesTransferred, errorCode, status);
        return;
    }
    status = NOT_LISTENING;
    server->handleEvents(this, errorCode, buffer, bytesTransferred);
}

void Server::handleEvents(WatchPoint* watchPoint, DWORD errorCode, const vector<BYTE>& buffer, DWORD bytesTransferred) {
    JNIEnv* env = getThreadEnv();
    const u16string& path = watchPoint->path;

    try {
        if (errorCode != ERROR_SUCCESS) {
            throw FileWatcherException("Error received when handling events", path, errorCode);
        }

        if (terminated) {
            log_fine(env, "Ignoring incoming events for %s because server is terminating (%d bytes)",
                utf16ToUtf8String(path).c_str(), bytesTransferred, watchPoint->status);
            return;
        }

        if (bytesTransferred == 0) {
            // Got a buffer overflow => current changes lost => send INVALIDATE on root
            log_info(env, "Detected overflow for %s", utf16ToUtf8String(path).c_str());
            reportChange(env, FILE_EVENT_INVALIDATE, path);
        } else {
            int index = 0;
            for (;;) {
                FILE_NOTIFY_INFORMATION* current = (FILE_NOTIFY_INFORMATION*) &buffer[index];
                handleEvent(env, path, current);
                if (current->NextEntryOffset == 0) {
                    break;
                }
                index += current->NextEntryOffset;
            }
        }

        watchPoint->listen();
    } catch (const exception& ex) {
        reportError(env, ex);
    }
}

bool isAbsoluteLocalPath(const u16string& path) {
    if (path.length() < 3) {
        return false;
    }
    return ((u'a' <= path[0] && path[0] <= u'z') || (u'A' <= path[0] && path[0] <= u'Z'))
        && path[1] == u':'
        && path[2] == u'\\';
}

bool isAbsoluteUncPath(const u16string& path) {
    if (path.length() < 3) {
        return false;
    }
    return path[0] == u'\\' && path[1] == u'\\';
}

bool isLongPath(const u16string& path) {
    return path.length() >= 4 && path.substr(0, 4) == u"\\\\?\\";
}

bool isUncLongPath(const u16string& path) {
    return path.length() >= 8 && path.substr(0, 8) == u"\\\\?\\UNC\\";
}

// TODO How can this be done nicer, wihtout both unnecessary copy and in-place mutation?
void convertToLongPathIfNeeded(u16string& path) {
    // Technically, this should be MAX_PATH (i.e. 260), except some Win32 API related
    // to working with directory paths are actually limited to 240. It is just
    // safer/simpler to cover both cases in one code path.
    if (path.length() <= 240) {
        return;
    }

    // It is already a long path, nothing to do here
    if (isLongPath(path)) {
        return;
    }

    if (isAbsoluteLocalPath(path)) {
        // Format: C:\... -> \\?\C:\...
        path.insert(0, u"\\\\?\\");
    } else if (isAbsoluteUncPath(path)) {
        // In this case, we need to skip the first 2 characters:
        // Format: \\server\share\... -> \\?\UNC\server\share\...
        path.erase(0, 2);
        path.insert(0, u"\\\\?\\UNC\\");
    } else {
        // It is some sort of unknown format, don't mess with it
    }
}

void Server::handleEvent(JNIEnv* env, const u16string& path, FILE_NOTIFY_INFORMATION* info) {
    wstring changedPathW = wstring(info->FileName, 0, info->FileNameLength / sizeof(wchar_t));
    u16string changedPath(changedPathW.begin(), changedPathW.end());
    if (!changedPath.empty()) {
        changedPath.insert(0, 1, u'\\');
    }
    changedPath.insert(0, path);
    // TODO Remove long prefix for path once?
    if (isLongPath(changedPath)) {
        if (isUncLongPath(changedPath)) {
            changedPath.erase(0, 8).insert(0, u"\\\\");
        } else {
            changedPath.erase(0, 4);
        }
    }

    log_fine(env, "Change detected: 0x%x '%ls'", info->Action, changedPathW.c_str());

    jint type;
    if (info->Action == FILE_ACTION_ADDED || info->Action == FILE_ACTION_RENAMED_NEW_NAME) {
        type = FILE_EVENT_CREATED;
    } else if (info->Action == FILE_ACTION_REMOVED || info->Action == FILE_ACTION_RENAMED_OLD_NAME) {
        type = FILE_EVENT_REMOVED;
    } else if (info->Action == FILE_ACTION_MODIFIED) {
        type = FILE_EVENT_MODIFIED;
    } else {
        log_warning(env, "Unknown event 0x%x for %ls", info->Action, changedPathW.c_str());
        type = FILE_EVENT_UNKNOWN;
    }

    reportChange(env, type, changedPath);
}

//
// Server
//

Server::Server(JNIEnv* env, jobject watcherCallback)
    : AbstractServer(env, watcherCallback) {
    startThread();
    // TODO Error handling
    SetThreadPriority(this->watcherThread.native_handle(), THREAD_PRIORITY_ABOVE_NORMAL);
}

void Server::terminate() {
    log_fine(getThreadEnv(), "Terminating", NULL);
    terminated = true;
}

Server::~Server() {
    executeOnThread(shared_ptr<Command>(new TerminateCommand()));

    if (watcherThread.joinable()) {
        watcherThread.join();
    }
}

void Server::runLoop(JNIEnv* env, function<void(exception_ptr)> notifyStarted) {
    notifyStarted(nullptr);

    while (!terminated) {
        SleepEx(INFINITE, true);
    }

    // We have received termination, cancel all watchers
    log_fine(env, "Finished with run loop, now cancelling remaining watch points", NULL);
    int pendingWatchPoints = 0;
    for (auto& it : watchPoints) {
        auto& watchPoint = it.second;
        switch (watchPoint.status) {
            case LISTENING:
                watchPoint.cancel();
                pendingWatchPoints++;
                break;
            case CANCELLED:
                pendingWatchPoints++;
                break;
            default:
                break;
        }
    }

    // If there are any pending watchers, wait for them to finish
    if (pendingWatchPoints > 0) {
        log_fine(env, "Waiting for %d pending watch points to finish", pendingWatchPoints);
        SleepEx(SERVER_CLOSE_TIMEOUT_IN_MS, true);
    }

    // Warn about  any unfinished watchpoints
    for (auto& it : watchPoints) {
        auto& watchPoint = it.second;
        switch (watchPoint.status) {
            case FINISHED:
                break;
            default:
                log_warning(env, "Watch point %s did not finish before termination timeout, status = %d",
                    utf16ToUtf8String(watchPoint.path).c_str(), watchPoint.status);
                break;
        }
    }
}

static void CALLBACK processCommandsCallback(_In_ ULONG_PTR info) {
    Server* server = (Server*) info;
    server->processCommands();
}

void Server::processCommandsOnThread() {
    QueueUserAPC(processCommandsCallback, watcherThread.native_handle(), (ULONG_PTR) this);
}

void Server::registerPath(const u16string& path) {
    u16string longPath = path;
    convertToLongPathIfNeeded(longPath);
    auto it = watchPoints.find(longPath);
    if (it != watchPoints.end()) {
        if (it->second.status != FINISHED) {
            throw FileWatcherException("Already watching path", path);
        }
        watchPoints.erase(it);
    }
    watchPoints.emplace(piecewise_construct,
        forward_as_tuple(longPath),
        forward_as_tuple(this, longPath));
}

void Server::unregisterPath(const u16string& path) {
    u16string longPath = path;
    convertToLongPathIfNeeded(longPath);
    auto it = watchPoints.find(longPath);
    if (it == watchPoints.end()) {
        log_fine(getThreadEnv(), "Path is not watched: %s", utf16ToUtf8String(path).c_str());
        return;
    }
    it->second.cancel();
}

//
// JNI calls
//

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsFileEventFunctions_startWatcher(JNIEnv* env, jclass target, jobject javaCallback) {
    return wrapServer(env, [env, javaCallback]() {
        return new Server(env, javaCallback);
    });
}

#endif
<|endoftext|>