<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 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
<commit_msg>Win: fix log message<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, status = %d)",
                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|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <sstream>

#include "slitherlink/sl_dictionary.h"
#include "slitherlink/sl_generator.h"
#include "slitherlink/sl_generator_option.h"
#include "slitherlink/sl_clue_placement.h"
#include "slitherlink/sl_problem.h"

namespace
{
void ShowUsage(int argc, char** argv)
{
	std::cerr << "Usage: " << argv[0] << " [options] [file]" << std::endl;
	std::cerr << "Options:\n\
  --help         Display this information\n\
  -o <file>      Place the output into <file>\n\
  -a             Generate the clue placement automatically\n\
  -h <height>    Set the height of the problem <height>\n\
  -w <width>     Set the width of the problem <width>\n\
  -c <num>       Set the minimum number of the clues <num>\n\
  -C <num>       Set the maximum number of the clues <num>\n\
  -s <symmetry>  Specify the symmetry of the clue placement\n\
\n\
Options -h, -w, -c, -C and -s are valid only if -a is specified.\n\
If -a is not specified, the input file should be specified for the clue placement." << std::endl;
}
bool GenerateWithCluePlacement(
	penciloid::slitherlink::CluePlacement &placement,
	penciloid::slitherlink::GeneratorOption &opt,
	std::mt19937 *rnd,
	penciloid::slitherlink::Problem *problem,
	int n_trial = -1)
{
	if (n_trial < 0) {
		while (!penciloid::slitherlink::GenerateByLocalSearch(placement, opt, rnd, problem));
		return true;
	}
	while (n_trial) {
		if (penciloid::slitherlink::GenerateByLocalSearch(placement, opt, rnd, problem)) {
			return true;
		}
		--n_trial;
	}
	return false;
}
void GenerateAuto(
	int height,
	int width,
	int n_clue_lo,
	int n_clue_hi,
	int symmetry,
	penciloid::slitherlink::GeneratorOption &opt,
	std::mt19937 *rnd,
	penciloid::slitherlink::Problem *problem)
{
	using namespace penciloid;
	using namespace slitherlink;
	for (;;) {
		int n_clues = std::uniform_int_distribution<int>(n_clue_lo, n_clue_hi)(*rnd);
		CluePlacement placement = GenerateCluePlacement(Y(height), X(width), n_clues, symmetry, rnd);
		if (GenerateWithCluePlacement(placement, opt, rnd, problem, 3)) {
			break;
		}
	}
}
int ParseSymmetry(std::string str)
{
	int ret = 0;
	std::istringstream iss(str);
	std::string token;
	while (std::getline(iss, token, ',')) {
		if (token == "h" || token == "horizontal") {
			ret |= penciloid::slitherlink::kSymmetryHorizontalLine;
		} else if (token == "v" || token == "vertical") {
			ret |= penciloid::slitherlink::kSymmetryVerticalLine;
		} else if (token == "90" || token == "t" || token == "tetrad") {
			ret |= penciloid::slitherlink::kSymmetryTetrad;
		} else if (token == "180" || token == "d" || token == "dyad") {
			ret |= penciloid::slitherlink::kSymmetryDyad;
		} else {
			std::cerr << "error: unrecognized symmetry '" << token << "'" << std::endl;
			exit(0);
		}
	}
	return ret;
}
}

int main(int argc, char** argv)
{
	if (argc < 2) {
		ShowUsage(argc, argv);
		return 0;
	}

	std::string in_filename = "", out_filename = "";
	int height = -1, width = -1, n_clue_lo = -1, n_clue_hi = -1, symmetry = 0;
	bool gen_clue_auto = false;

	// parse options
	int arg_idx = 1;
	for (; arg_idx < argc; ++arg_idx) {
		if (argv[arg_idx][0] != '-') {
			// option ended
			break;
		}
		std::string opt = argv[arg_idx];
		if (opt[1] == 'o') {
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -o" << std::endl;
					return 0;
				}
				out_filename = argv[arg_idx + 1];
				++arg_idx;
			} else {
				out_filename = opt.substr(2);
			}
		} else if (opt == "-a") {
			gen_clue_auto = true;
		} else if (opt[1] == 's') {
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -s" << std::endl;
					return 0;
				}
				symmetry = ParseSymmetry(argv[arg_idx + 1]);
				++arg_idx;
			} else {
				symmetry = ParseSymmetry(opt.substr(2));
			}
		} else if (opt[1] == 'h' || opt[1] == 'w' || opt[1] == 'c' || opt[1] == 'C') {
			std::istringstream iss;
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -" << opt[1] << std::endl;
					return 0;
				}
				iss.str(argv[arg_idx + 1]);
				++arg_idx;
			} else {
				iss.str(opt.substr(2));
			}
			int val;
			iss >> val;
			if (iss.fail()) {
				std::cerr << "error: missing value after -" << opt[1] << std::endl;
				return 0;
			}

			switch (opt[1]) {
			case 'h': height = val; break;
			case 'w': width = val; break;
			case 'c': n_clue_lo = val; break;
			case 'C': n_clue_hi = val; break;
			}
		} else if (opt == "--help") {
			ShowUsage(argc, argv);
			return 0;
		} else {
			std::cerr << "error: unrecognized option '" << argv[arg_idx] << "'" << std::endl;
			return 0;
		}
	}
	if (gen_clue_auto) {
		if (out_filename.empty()) {
			std::cerr << "error: -o must be specified if -a is specified." << std::endl;
			return 0;
		}
	}
	if (!gen_clue_auto) {
		if (arg_idx < argc) {
			in_filename = argv[arg_idx];
		} else {
			std::cerr << "error: no input file" << std::endl;
			return 0;
		}
	}

	using namespace penciloid;
	using namespace slitherlink;

	GeneratorOption opt;
	Dictionary dic;
	dic.CreateDefault();
	opt.field_dictionary = &dic;

	Problem problem;
	std::random_device dev;
	std::mt19937 rnd(dev());

	if (!gen_clue_auto) {
		std::ifstream ifs(in_filename);
		if (ifs.fail()) {
			std::cerr << "error: couldn't open file '" << in_filename << "'" << std::endl;
			return 0;
		}
		ifs >> height >> width;
		if (ifs.fail() || height <= 0 || width <= 0) {
			std::cerr << "error: invalid input format" << std::endl;
			return 0;
		}
		CluePlacement clue_placement{ Y(height), X(width) };
		for (Y y(0); y < height; ++y) {
			for (X x(0); x < width; ++x) {
				std::string token;
				ifs >> token;
				if (ifs.fail()) {
					std::cerr << "error: invalid input format" << std::endl;
					return 0;
				}

				if (token[0] >= '0' && token[0] <= '3') {
					clue_placement.SetClue(CellPosition(y, x), Clue(static_cast<int>(token[0] - '0')));
				} else if (token[0] == '5') {
					clue_placement.SetClue(CellPosition(y, x), kSomeClue);
				} else if (token[0] != '.') {
					std::cerr << "error: invalid input format" << std::endl;
					return 0;
				}
			}
		}

		GenerateWithCluePlacement(clue_placement, opt, &rnd, &problem);
	} else {
		if (n_clue_lo == -1 || n_clue_hi == -1) {
			n_clue_lo = static_cast<int>(height * width * 0.3);
			n_clue_hi = static_cast<int>(height * width * 0.4);
		}
		GenerateAuto(height, width, n_clue_lo, n_clue_hi, symmetry, opt, &rnd, &problem);
	}

	if (out_filename.empty()) {
		out_filename = in_filename + ".generated.txt";
	}
	std::ofstream ofs(out_filename);
	if (!ofs.good()) {
		std::cerr << "error: couldn't open file '" << in_filename << "'" << std::endl;
		return 0;
	}
	ofs << height << std::endl;
	ofs << width << std::endl;
	for (Y y(0); y < height; ++y) {
		for (X x(0); x < width; ++x) {
			Clue c = problem.GetClue(CellPosition(y, x));
			if (c == kNoClue) ofs << ". ";
			else ofs << static_cast<int>(c) << " ";
		}
		ofs << std::endl;
	}
	return 0;
}
<commit_msg>frontend_slitherlink_generator: support Penciloid format in addition to PencilBox format<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <sstream>

#include "slitherlink/sl_dictionary.h"
#include "slitherlink/sl_generator.h"
#include "slitherlink/sl_generator_option.h"
#include "slitherlink/sl_clue_placement.h"
#include "slitherlink/sl_problem.h"

namespace
{
void ShowUsage(int argc, char** argv)
{
	std::cerr << "Usage: " << argv[0] << " [options] [file]" << std::endl;
	std::cerr << "Options:\n\
  --help         Display this information\n\
  -o <file>      Place the output into <file>\n\
  -pb            Output in the PencilBox format (default)\n\
  -pl            Output in the Penciloid format\n\
  -a             Generate the clue placement automatically\n\
  -h <height>    Set the height of the problem <height>\n\
  -w <width>     Set the width of the problem <width>\n\
  -c <num>       Set the minimum number of the clues <num>\n\
  -C <num>       Set the maximum number of the clues <num>\n\
  -s <symmetry>  Specify the symmetry of the clue placement\n\
\n\
Options -h, -w, -c, -C and -s are valid only if -a is specified.\n\
If -a is not specified, the input file should be specified for the clue placement." << std::endl;
}
bool GenerateWithCluePlacement(
	penciloid::slitherlink::CluePlacement &placement,
	penciloid::slitherlink::GeneratorOption &opt,
	std::mt19937 *rnd,
	penciloid::slitherlink::Problem *problem,
	int n_trial = -1)
{
	if (n_trial < 0) {
		while (!penciloid::slitherlink::GenerateByLocalSearch(placement, opt, rnd, problem));
		return true;
	}
	while (n_trial) {
		if (penciloid::slitherlink::GenerateByLocalSearch(placement, opt, rnd, problem)) {
			return true;
		}
		--n_trial;
	}
	return false;
}
void GenerateAuto(
	int height,
	int width,
	int n_clue_lo,
	int n_clue_hi,
	int symmetry,
	penciloid::slitherlink::GeneratorOption &opt,
	std::mt19937 *rnd,
	penciloid::slitherlink::Problem *problem)
{
	using namespace penciloid;
	using namespace slitherlink;
	for (;;) {
		int n_clues = std::uniform_int_distribution<int>(n_clue_lo, n_clue_hi)(*rnd);
		CluePlacement placement = GenerateCluePlacement(Y(height), X(width), n_clues, symmetry, rnd);
		if (GenerateWithCluePlacement(placement, opt, rnd, problem, 3)) {
			break;
		}
	}
}
int ParseSymmetry(std::string str)
{
	int ret = 0;
	std::istringstream iss(str);
	std::string token;
	while (std::getline(iss, token, ',')) {
		if (token == "h" || token == "horizontal") {
			ret |= penciloid::slitherlink::kSymmetryHorizontalLine;
		} else if (token == "v" || token == "vertical") {
			ret |= penciloid::slitherlink::kSymmetryVerticalLine;
		} else if (token == "90" || token == "t" || token == "tetrad") {
			ret |= penciloid::slitherlink::kSymmetryTetrad;
		} else if (token == "180" || token == "d" || token == "dyad") {
			ret |= penciloid::slitherlink::kSymmetryDyad;
		} else {
			std::cerr << "error: unrecognized symmetry '" << token << "'" << std::endl;
			exit(0);
		}
	}
	return ret;
}
}

int main(int argc, char** argv)
{
	if (argc < 2) {
		ShowUsage(argc, argv);
		return 0;
	}

	std::string in_filename = "", out_filename = "";
	int height = -1, width = -1, n_clue_lo = -1, n_clue_hi = -1, symmetry = 0;
	bool gen_clue_auto = false;
	bool output_in_penciloid_format = false;

	// parse options
	int arg_idx = 1;
	for (; arg_idx < argc; ++arg_idx) {
		if (argv[arg_idx][0] != '-') {
			// option ended
			break;
		}
		std::string opt = argv[arg_idx];
		if (opt[1] == 'o') {
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -o" << std::endl;
					return 0;
				}
				out_filename = argv[arg_idx + 1];
				++arg_idx;
			} else {
				out_filename = opt.substr(2);
			}
		} else if (opt == "-pb") {
			output_in_penciloid_format = false;
		} else if (opt == "-pl") {
			output_in_penciloid_format = true;
		} else if (opt == "-a") {
			gen_clue_auto = true;
		} else if (opt[1] == 's') {
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -s" << std::endl;
					return 0;
				}
				symmetry = ParseSymmetry(argv[arg_idx + 1]);
				++arg_idx;
			} else {
				symmetry = ParseSymmetry(opt.substr(2));
			}
		} else if (opt[1] == 'h' || opt[1] == 'w' || opt[1] == 'c' || opt[1] == 'C') {
			std::istringstream iss;
			if (opt.size() == 2) {
				if (arg_idx + 1 >= argc) {
					std::cerr << "error: missing value after -" << opt[1] << std::endl;
					return 0;
				}
				iss.str(argv[arg_idx + 1]);
				++arg_idx;
			} else {
				iss.str(opt.substr(2));
			}
			int val;
			iss >> val;
			if (iss.fail()) {
				std::cerr << "error: missing value after -" << opt[1] << std::endl;
				return 0;
			}

			switch (opt[1]) {
			case 'h': height = val; break;
			case 'w': width = val; break;
			case 'c': n_clue_lo = val; break;
			case 'C': n_clue_hi = val; break;
			}
		} else if (opt == "--help") {
			ShowUsage(argc, argv);
			return 0;
		} else {
			std::cerr << "error: unrecognized option '" << argv[arg_idx] << "'" << std::endl;
			return 0;
		}
	}
	if (gen_clue_auto) {
		if (out_filename.empty()) {
			std::cerr << "error: -o must be specified if -a is specified." << std::endl;
			return 0;
		}
	}
	if (!gen_clue_auto) {
		if (arg_idx < argc) {
			in_filename = argv[arg_idx];
		} else {
			std::cerr << "error: no input file" << std::endl;
			return 0;
		}
	}

	using namespace penciloid;
	using namespace slitherlink;

	GeneratorOption opt;
	Dictionary dic;
	dic.CreateDefault();
	opt.field_dictionary = &dic;

	Problem problem;
	std::random_device dev;
	std::mt19937 rnd(dev());

	if (!gen_clue_auto) {
		std::ifstream ifs(in_filename);
		if (ifs.fail()) {
			std::cerr << "error: couldn't open file '" << in_filename << "'" << std::endl;
			return 0;
		}
		ifs >> height >> width;
		if (ifs.fail() || height <= 0 || width <= 0) {
			std::cerr << "error: invalid input format" << std::endl;
			return 0;
		}
		CluePlacement clue_placement{ Y(height), X(width) };
		for (Y y(0); y < height; ++y) {
			for (X x(0); x < width; ++x) {
				std::string token;
				ifs >> token;
				if (ifs.fail()) {
					std::cerr << "error: invalid input format" << std::endl;
					return 0;
				}

				if (token[0] >= '0' && token[0] <= '3') {
					clue_placement.SetClue(CellPosition(y, x), Clue(static_cast<int>(token[0] - '0')));
				} else if (token[0] == '5') {
					clue_placement.SetClue(CellPosition(y, x), kSomeClue);
				} else if (token[0] != '.') {
					std::cerr << "error: invalid input format" << std::endl;
					return 0;
				}
			}
		}

		GenerateWithCluePlacement(clue_placement, opt, &rnd, &problem);
	} else {
		if (n_clue_lo == -1 || n_clue_hi == -1) {
			n_clue_lo = static_cast<int>(height * width * 0.3);
			n_clue_hi = static_cast<int>(height * width * 0.4);
		}
		GenerateAuto(height, width, n_clue_lo, n_clue_hi, symmetry, opt, &rnd, &problem);
	}

	if (out_filename.empty()) {
		out_filename = in_filename + ".generated.txt";
	}
	std::ofstream ofs(out_filename);
	if (!ofs.good()) {
		std::cerr << "error: couldn't open file '" << in_filename << "'" << std::endl;
		return 0;
	}
	if (output_in_penciloid_format) {
		ofs << height << " " << width << std::endl;
		for (Y y(0); y < height; ++y) {
			for (X x(0); x < width; ++x) {
				Clue c = problem.GetClue(CellPosition(y, x));
				if (c == kNoClue) ofs << ".";
				else ofs << static_cast<int>(c);
			}
			ofs << std::endl;
		}
		ofs << std::endl;
	} else {
		ofs << height << std::endl;
		ofs << width << std::endl;
		for (Y y(0); y < height; ++y) {
			for (X x(0); x < width; ++x) {
				Clue c = problem.GetClue(CellPosition(y, x));
				if (c == kNoClue) ofs << ". ";
				else ofs << static_cast<int>(c) << " ";
			}
			ofs << std::endl;
		}
	}
	return 0;
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrStencilAndCoverPathRenderer.h"
#include "GrAAHairLinePathRenderer.h"
#include "GrAAConvexPathRenderer.h"
#include "GrAADistanceFieldPathRenderer.h"
#include "GrTessellatingPathRenderer.h"
#if GR_STROKE_PATH_RENDERING
#include "../../experimental/StrokePathRenderer/GrStrokePathRenderer.h"
#endif
#if GR_ANDROID_PATH_RENDERING
#include "../../experimental/AndroidPathRenderer/GrAndroidPathRenderer.h"
#endif

#ifndef GR_TESSELLATING_PATH_RENDERING
#define GR_TESSELLATING_PATH_RENDERING 1
#endif

void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
#if GR_STROKE_PATH_RENDERING
    chain->addPathRenderer(SkNEW(GrStrokePathRenderer))->unref();
#endif
#if GR_ANDROID_PATH_RENDERING
    chain->addPathRenderer(SkNEW(GrAndroidPathRenderer))->unref();
#endif
#if GR_TESSELLATING_PATH_RENDERING
    chain->addPathRenderer(new GrTessellatingPathRenderer)->unref();
#endif
    if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) {
        chain->addPathRenderer(pr)->unref();
    }
    if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) {
        chain->addPathRenderer(pr)->unref();
    }
    chain->addPathRenderer(SkNEW(GrAAConvexPathRenderer))->unref();
    chain->addPathRenderer(SkNEW_ARGS(GrAADistanceFieldPathRenderer, (ctx)))->unref();
}
<commit_msg>Revert "Enable tessellating GPU path renderer."<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrStencilAndCoverPathRenderer.h"
#include "GrAAHairLinePathRenderer.h"
#include "GrAAConvexPathRenderer.h"
#include "GrAADistanceFieldPathRenderer.h"
#include "GrTessellatingPathRenderer.h"
#if GR_STROKE_PATH_RENDERING
#include "../../experimental/StrokePathRenderer/GrStrokePathRenderer.h"
#endif
#if GR_ANDROID_PATH_RENDERING
#include "../../experimental/AndroidPathRenderer/GrAndroidPathRenderer.h"
#endif

#ifndef GR_TESSELLATING_PATH_RENDERING
#define GR_TESSELLATING_PATH_RENDERING 0
#endif

void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
#if GR_STROKE_PATH_RENDERING
    chain->addPathRenderer(SkNEW(GrStrokePathRenderer))->unref();
#endif
#if GR_ANDROID_PATH_RENDERING
    chain->addPathRenderer(SkNEW(GrAndroidPathRenderer))->unref();
#endif
#if GR_TESSELLATING_PATH_RENDERING
    chain->addPathRenderer(new GrTessellatingPathRenderer)->unref();
#endif
    if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) {
        chain->addPathRenderer(pr)->unref();
    }
    if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) {
        chain->addPathRenderer(pr)->unref();
    }
    chain->addPathRenderer(SkNEW(GrAAConvexPathRenderer))->unref();
    chain->addPathRenderer(SkNEW_ARGS(GrAADistanceFieldPathRenderer, (ctx)))->unref();
}
<|endoftext|>


<commit_before>/*
TIGRE (https://gitorious.org/tigre) is made available under the MIT License.

Copyright (c) 2012 - 2013 Aurélien Cavelan (razlock)

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef OPENGL_CONTEXT_H
#define OPENGL_CONTEXT_H

#include <vector>

#include "config/os.hpp"

#if defined(OS_LINUX)
	#include <GL/gl.h>
	#include <GL/glext.h>
#elif defined(OS_ANDROID)
	#include <GLES2/gl2.h>
	#include <GLES2/gl2ext.h>
#endif

#include "../Display.hpp"
#include "../Context.hpp"
#include "../../utils/Logger.hpp"

namespace tigre
{
	namespace graphics
	{
		class OpenGLShader
		{
			public:

				GLuint program;
				GLuint ports[shader::count];
		};

		class OpenGLContext : public Context
		{
			public:

				OpenGLContext(Display *display);
				~OpenGLContext();

				void init();
				void destroy();

				void printGLString(GLenum s, const utils::Logger *log);
				void checkGlError(const char* op, const utils::Logger *log);

				void setViewport(int x, int y, int width, int height);
				void setViewport(int width, int height);

				int getX() const;
				int getY() const;

				int getWidth() const;
				int getHeight() const;

				void setMatrix4(int port, const glm::mat4 &mat);
				void setColor4(int port, const Color &color);

				void setColor(const Color &color);

				void clear(const Color &color);

				Shader* createShader(ShaderSource *shaderSource);
				void destroy(Shader *shader);
				void setShader(Shader *shader);

				OpenGLShader *getCurrentShader();

			private:

				GLuint createShader(GLenum shaderType, const char *source);
				GLuint createShaderProgram(GLuint vertexShader, GLuint fragmentShader);

				Display *_display;

				OpenGLShader *_currentShader;
				std::vector<OpenGLShader*> _glShaders;

				int _x, _y;
				int _width, _height;

		};
	}
}

#endif
<commit_msg>fix GLuint to GLint in OpenGLShader<commit_after>/*
TIGRE (https://gitorious.org/tigre) is made available under the MIT License.

Copyright (c) 2012 - 2013 Aurélien Cavelan (razlock)

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef OPENGL_CONTEXT_H
#define OPENGL_CONTEXT_H

#include <vector>

#include "config/os.hpp"

#if defined(OS_LINUX)
	#include <GL/gl.h>
	#include <GL/glext.h>
#elif defined(OS_ANDROID)
	#include <GLES2/gl2.h>
	#include <GLES2/gl2ext.h>
#endif

#include "../Display.hpp"
#include "../Context.hpp"
#include "../../utils/Logger.hpp"

namespace tigre
{
	namespace graphics
	{
		class OpenGLShader
		{
			public:

				GLint program;
				GLint ports[shader::count];
		};

		class OpenGLContext : public Context
		{
			public:

				OpenGLContext(Display *display);
				~OpenGLContext();

				void init();
				void destroy();

				void printGLString(GLenum s, const utils::Logger *log);
				void checkGlError(const char* op, const utils::Logger *log);

				void setViewport(int x, int y, int width, int height);
				void setViewport(int width, int height);

				int getX() const;
				int getY() const;

				int getWidth() const;
				int getHeight() const;

				void setMatrix4(int port, const glm::mat4 &mat);
				void setColor4(int port, const Color &color);

				void setColor(const Color &color);

				void clear(const Color &color);

				Shader* createShader(ShaderSource *shaderSource);
				void destroy(Shader *shader);
				void setShader(Shader *shader);

				OpenGLShader *getCurrentShader();

			private:

				GLuint createShader(GLenum shaderType, const char *source);
				GLuint createShaderProgram(GLuint vertexShader, GLuint fragmentShader);

				Display *_display;

				OpenGLShader *_currentShader;
				std::vector<OpenGLShader*> _glShaders;

				int _x, _y;
				int _width, _height;

		};
	}
}

#endif
<|endoftext|>


<commit_before>
#include <eagle_soc.h>
#include <stdlib.h>
#include "dfu.h"
#include "dfu-internal.h"
#include "gpio.h"
#include "esp8266-serial.h"

#include "Arduino.h"

/*
 * Arduino star otto board.
 * ESP8266 CONSOLE: Serial1
 * STM32 PROGRAMMING SERIAL: Serial
 * GPIO4  -> BOOT0
 * GPIO12 -> #RST
 *
 * THIS FILE IS FOR THE ARDUINO VERSION OF THE LIBRARY, DO NOT TRY TO BUILD IT
 * OUTSIDE THE ARDUINO ENVIRONMENT
 */

static int esp8266_serial_star8_open(struct dfu_interface *iface,
				     const char *path,
				     const void *pars)
{
	static const struct dfu_serial_pars _pars = {
		.parity = PARITY_EVEN,
	};

	/* Close serial port and replace low level serial driver with ours */
	Serial.end();
	return esp8266_serial_open(iface, path, pars ? pars : &_pars);
}

static int
esp8266_serial_star8_target_reset(struct dfu_interface *iface)
{

	/*
	 * BOOT0  ----+        +--------
	 *            |        |
	 *            +--------+
	 *
	 * RST    ----+            +----
	 *            |            |
	 *            +------------+
	 */
	pinMode(4, OUTPUT);
	pinMode(12, OUTPUT);
	delay(5);
	digitalWrite(4, 1);
	digitalWrite(12, 0);
	delay(2);
	digitalWrite(4, 0);
	digitalWrite(12, 1);
	delay(5);
	digitalWrite(4, 1);
	delay(10);
	digitalWrite(12, 0);
	delay(200);
	return 0;
}

static int
esp8266_serial_star8_target_run(struct dfu_interface *iface)
{
	pinMode(4, OUTPUT);
	pinMode(12, OUTPUT);
	digitalWrite(4, 0);
	digitalWrite(12, 0);
	delay(1);
	digitalWrite(12, 1);
	delay(1);
	digitalWrite(12, 0);
	return 0;
}

const struct dfu_interface_ops
esp8266_serial_star8_interface_ops = {
	.open = esp8266_serial_star8_open,
	.write = esp8266_serial_write,
	.read = esp8266_serial_read,
	.write_read = NULL,
	.target_reset = esp8266_serial_star8_target_reset,
	.target_run = esp8266_serial_star8_target_run,
	.poll_idle = esp8266_serial_poll_idle,
	.done = NULL,
	.fini = esp8266_serial_fini,
};
<commit_msg>interface, esp8266-serial-star8.cpp: simplify BOOT0 waveform<commit_after>
#include <eagle_soc.h>
#include <stdlib.h>
#include "dfu.h"
#include "dfu-internal.h"
#include "gpio.h"
#include "esp8266-serial.h"

#include "Arduino.h"

/*
 * Arduino star otto board.
 * ESP8266 CONSOLE: Serial1
 * STM32 PROGRAMMING SERIAL: Serial
 * GPIO4  -> BOOT0
 * GPIO12 -> #RST
 *
 * THIS FILE IS FOR THE ARDUINO VERSION OF THE LIBRARY, DO NOT TRY TO BUILD IT
 * OUTSIDE THE ARDUINO ENVIRONMENT
 */

static int esp8266_serial_star8_open(struct dfu_interface *iface,
				     const char *path,
				     const void *pars)
{
	static const struct dfu_serial_pars _pars = {
		.parity = PARITY_EVEN,
	};

	/* Close serial port and replace low level serial driver with ours */
	Serial.end();
	return esp8266_serial_open(iface, path, pars ? pars : &_pars);
}

static int
esp8266_serial_star8_target_reset(struct dfu_interface *iface)
{

	/*
	 * BOOT0               +--------
	 *                     |
	 *        -------------+
	 *
	 * RST    ----+            +----
	 *            |            |
	 *            +------------+
	 */
	pinMode(4, OUTPUT);
	pinMode(12, OUTPUT);
	delay(5);
	digitalWrite(4, 0);
	digitalWrite(12, 0);
	delay(2);
	digitalWrite(12, 1);
	delay(5);
	digitalWrite(4, 1);
	delay(10);
	digitalWrite(12, 0);
	delay(200);
	return 0;
}

static int
esp8266_serial_star8_target_run(struct dfu_interface *iface)
{
	pinMode(4, OUTPUT);
	pinMode(12, OUTPUT);
	digitalWrite(4, 0);
	digitalWrite(12, 0);
	delay(1);
	digitalWrite(12, 1);
	delay(1);
	digitalWrite(12, 0);
	return 0;
}

const struct dfu_interface_ops
esp8266_serial_star8_interface_ops = {
	.open = esp8266_serial_star8_open,
	.write = esp8266_serial_write,
	.read = esp8266_serial_read,
	.write_read = NULL,
	.target_reset = esp8266_serial_star8_target_reset,
	.target_run = esp8266_serial_star8_target_run,
	.poll_idle = esp8266_serial_poll_idle,
	.done = NULL,
	.fini = esp8266_serial_fini,
};
<|endoftext|>


<commit_before>#include "RS.h"

#include <cmath>

#include "DoubleArray.h"

#include "Math.h"

using namespace TexturalAnalysis;

PointArray RS::calculatePoints(const Image& image, const int x1, const int y1, const int x2, const int y2) {
    const int deltaX = fabs(x2 - x1);
    const int deltaY = fabs(y2 - y1);

    const int signX = x1 < x2 ? 1 : -1;
    const int signY = y1 < y2 ? 1 : -1;

    const int N = deltaX > deltaY ? deltaX + 1 : deltaY + 1;

    DoubleArray h(N);

    int count = 0;

    h.set(count, image.get(y2, x2));

    int error = deltaX - deltaY;

    double currentX = x1;
    double currentY = y1;

    while ((currentX != x2) || (currentY != y2)) {
        count++;

        h.set(count, image.get(currentY, currentX));

        int error2 = error * 2;

        if(error2 > -deltaY) {
            error -= deltaY;

            currentX += signX;
        }

        if(error2 < deltaX) {
            error += deltaX;

            currentY += signY;
        }
    }

    DoubleArray H(h.size());

    H.set(0, h.get(0));

    for (int i = 1; i < h.size(); i++) {
        H.set(i, H.get(i - 1) + h.get(i));
    }

    DoubleArray averageH(H.size());

    for (int i = 0; i < H.size(); i++) {
        averageH.set(i, H.get(i) / (i + 1));
    }

    DoubleArray r(h.size());

    r.set(0, 0);

    for (int n = 1; n < h.size(); n++) {
        for (int k = 0; k < n; k++) {
            double sum = 0;

            double Max = 0;
            double Min = 0;

            for (int i = 0; i <= k; i++) {
                sum += h.get(i) - averageH.get(n);

                if (sum < Min) { Min = sum; }

                if (sum > Max) { Max = sum; }

            }

            r.set(n, Max - Min);
        }
    }

    DoubleArray s(h.size());

    for (int n = 0; n < h.size(); n++) {
        double sum = 0;

        for (int i = 0; i < n; i++){
            sum += pow((h.get(i) - averageH.get(n)), 2.0);
        }

        s.set(n, sqrt(sum / (n + 1)));
    }

    DoubleArray rs(h.size());

    rs.set(0, 0);

    for (int i = 1; i < r.size(); i++) {
        rs.set(i, r.get(i) / s.get(i));
    }

    PointArray points(rs.size());

    for (int i = 1; i < rs.size(); i++) {
        double pointX = Math::ln(i);
        double pointY = Math::ln(rs.get(i));

        points.set(i, Point(pointX, pointY));
    }

    return points;
}

HirstValues RS::calculateHirstValues(const PointArray& rsPoints) {
    double c1 = 0;
    double c2 = 0;
    double g1 = 0;
    double g2 = 0;

    for (int i = 0; i < rsPoints.size(); i++) {
        Point point = rsPoints.get(i);

        c1 += pow(point.x(), 2.0);
        c2 += point.x();
        g1 += point.x() * point.y();
        g2 += point.y();
    }

    int size = rsPoints.size();

    HirstValues hirstValues;
    hirstValues.coefficient = ((size - 1) * g1 - c2 * g2) / ((size - 1) * c1 - pow(c2, 2.0));
    hirstValues.offset = (1.0 / (size - 1)) * (g2 - hirstValues.coefficient * c2);

    return hirstValues;
}<commit_msg>Issue #1.   Заменила использование fabs на std::abs<commit_after>#include "RS.h"

#include <cmath>

#include "DoubleArray.h"

#include "Math.h"

using namespace TexturalAnalysis;

PointArray RS::calculatePoints(const Image& image, const int x1, const int y1, const int x2, const int y2) {
    const int deltaX = std::abs(x2 - x1);
    const int deltaY = std::abs(y2 - y1);

    const int signX = x1 < x2 ? 1 : -1;
    const int signY = y1 < y2 ? 1 : -1;

    const int N = deltaX > deltaY ? deltaX + 1 : deltaY + 1;

    DoubleArray h(N);

    int count = 0;

    h.set(count, image.get(y2, x2));

    int error = deltaX - deltaY;

    double currentX = x1;
    double currentY = y1;

    while ((currentX != x2) || (currentY != y2)) {
        count++;

        h.set(count, image.get(currentY, currentX));

        int error2 = error * 2;

        if(error2 > -deltaY) {
            error -= deltaY;

            currentX += signX;
        }

        if(error2 < deltaX) {
            error += deltaX;

            currentY += signY;
        }
    }

    DoubleArray H(h.size());

    H.set(0, h.get(0));

    for (int i = 1; i < h.size(); i++) {
        H.set(i, H.get(i - 1) + h.get(i));
    }

    DoubleArray averageH(H.size());

    for (int i = 0; i < H.size(); i++) {
        averageH.set(i, H.get(i) / (i + 1));
    }

    DoubleArray r(h.size());

    r.set(0, 0);

    for (int n = 1; n < h.size(); n++) {
        for (int k = 0; k < n; k++) {
            double sum = 0;

            double Max = 0;
            double Min = 0;

            for (int i = 0; i <= k; i++) {
                sum += h.get(i) - averageH.get(n);

                if (sum < Min) { Min = sum; }

                if (sum > Max) { Max = sum; }

            }

            r.set(n, Max - Min);
        }
    }

    DoubleArray s(h.size());

    for (int n = 0; n < h.size(); n++) {
        double sum = 0;

        for (int i = 0; i < n; i++){
            sum += pow((h.get(i) - averageH.get(n)), 2.0);
        }

        s.set(n, sqrt(sum / (n + 1)));
    }

    DoubleArray rs(h.size());

    rs.set(0, 0);

    for (int i = 1; i < r.size(); i++) {
        rs.set(i, r.get(i) / s.get(i));
    }

    PointArray points(rs.size());

    for (int i = 1; i < rs.size(); i++) {
        double pointX = Math::ln(i);
        double pointY = Math::ln(rs.get(i));

        points.set(i, Point(pointX, pointY));
    }

    return points;
}

HirstValues RS::calculateHirstValues(const PointArray& rsPoints) {
    double c1 = 0;
    double c2 = 0;
    double g1 = 0;
    double g2 = 0;

    for (int i = 0; i < rsPoints.size(); i++) {
        Point point = rsPoints.get(i);

        c1 += pow(point.x(), 2.0);
        c2 += point.x();
        g1 += point.x() * point.y();
        g2 += point.y();
    }

    int size = rsPoints.size();

    HirstValues hirstValues;
    hirstValues.coefficient = ((size - 1) * g1 - c2 * g2) / ((size - 1) * c1 - pow(c2, 2.0));
    hirstValues.offset = (1.0 / (size - 1)) * (g2 - hirstValues.coefficient * c2);

    return hirstValues;
}<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "http_server/http_server.hxx"
#include "http_server/Request.hxx"
#include "http_server/Handler.hxx"
#include "http_headers.hxx"
#include "duplex.hxx"
#include "direct.hxx"
#include "istream/sink_null.hxx"
#include "istream/ByteIstream.hxx"
#include "istream/DelayedIstream.hxx"
#include "istream/HeadIstream.hxx"
#include "istream/istream_hold.hxx"
#include "istream/istream_memory.hxx"
#include "istream/ZeroIstream.hxx"
#include "istream/istream.hxx"
#include "istream/UnusedHoldPtr.hxx"
#include "PInstance.hxx"
#include "pool/pool.hxx"
#include "event/TimerEvent.hxx"
#include "event/ShutdownListener.hxx"
#include "fb_pool.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "util/Cancellable.hxx"
#include "util/PrintException.hxx"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Instance final : PInstance, HttpServerConnectionHandler, Cancellable {
    ShutdownListener shutdown_listener;

    enum class Mode {
        MODE_NULL,
        MIRROR,

        /**
         * Response body of unknown length with keep-alive disabled.
         * Response body ends when socket is closed.
         */
        CLOSE,

        DUMMY,
        FIXED,
        HUGE_,
        HOLD,
    } mode;

    HttpServerConnection *connection;

    UnusedHoldIstreamPtr request_body;

    TimerEvent timer;

    Instance()
        :shutdown_listener(event_loop, BIND_THIS_METHOD(ShutdownCallback)),
         timer(event_loop, BIND_THIS_METHOD(OnTimer)) {}

    void ShutdownCallback() noexcept;

    void OnTimer() noexcept;

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override {
        request_body.Clear();
        timer.Cancel();
    }

    /* virtual methods from class HttpServerConnectionHandler */
    void HandleHttpRequest(HttpServerRequest &request,
                           CancellablePointer &cancel_ptr) override;

    void LogHttpRequest(HttpServerRequest &,
                        http_status_t, int64_t,
                        uint64_t, uint64_t) override {}

    void HttpConnectionError(std::exception_ptr e) override;
    void HttpConnectionClosed() override;
};

void
Instance::ShutdownCallback() noexcept
{
    http_server_connection_close(connection);
}

void
Instance::OnTimer() noexcept
{
    http_server_connection_close(connection);
    shutdown_listener.Disable();
}

/*
 * http_server handler
 *
 */

void
Instance::HandleHttpRequest(HttpServerRequest &request,
                            gcc_unused CancellablePointer &cancel_ptr)
{
    switch (mode) {
        http_status_t status;
        static char data[0x100];

    case Instance::Mode::MODE_NULL:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_NO_CONTENT,
                             HttpHeaders(request.pool), nullptr);
        break;

    case Instance::Mode::MIRROR:
        status = request.body
            ? HTTP_STATUS_OK
            : HTTP_STATUS_NO_CONTENT;
        http_server_response(&request, status,
                             HttpHeaders(request.pool),
                             std::move(request.body));
        break;

    case Instance::Mode::CLOSE:
        /* disable keep-alive */
        http_server_connection_graceful(&request.connection);

        /* fall through */

    case Instance::Mode::DUMMY:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        {
            auto body = istream_head_new(request.pool,
                                         istream_zero_new(request.pool),
                                         256, false);
            body = istream_byte_new(request.pool, std::move(body));

            http_server_response(&request, HTTP_STATUS_OK,
                                 HttpHeaders(request.pool),
                                 std::move(body));
        }

        break;

    case Instance::Mode::FIXED:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_OK, HttpHeaders(request.pool),
                             istream_memory_new(request.pool,
                                                data, sizeof(data)));
        break;

    case Instance::Mode::HUGE_:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_OK,
                             HttpHeaders(request.pool),
                             istream_head_new(request.pool,
                                              istream_zero_new(request.pool),
                                              512 * 1024, true));
        break;

    case Instance::Mode::HOLD:
        request_body = UnusedHoldIstreamPtr(request.pool,
                                            std::move(request.body));

        {
            auto delayed = istream_delayed_new(request.pool, event_loop);
            delayed.second.cancel_ptr = *this;

            http_server_response(&request, HTTP_STATUS_OK,
                                 HttpHeaders(request.pool),
                                 std::move(delayed.first));
        }

        static constexpr struct timeval t{0,0};
        timer.Add(t);
        break;
    }
}

void
Instance::HttpConnectionError(std::exception_ptr e)
{
    timer.Cancel();
    shutdown_listener.Disable();

    PrintException(e);
}

void
Instance::HttpConnectionClosed()
{
    timer.Cancel();
    shutdown_listener.Disable();
}

/*
 * main
 *
 */

int
main(int argc, char **argv)
try {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s INFD OUTFD {null|mirror|close|dummy|fixed|huge|hold}\n", argv[0]);
        return EXIT_FAILURE;
    }

    int in_fd, out_fd;

    if (strcmp(argv[1], "accept") == 0) {
        const int listen_fd = atoi(argv[2]);
        in_fd = out_fd = accept(listen_fd, nullptr, 0);
        if (in_fd < 0) {
            perror("accept() failed");
            return EXIT_FAILURE;
        }
    } else {
        in_fd = atoi(argv[1]);
        out_fd = atoi(argv[2]);
    }

    direct_global_init();
    const ScopeFbPoolInit fb_pool_init;

    Instance instance;
    instance.shutdown_listener.Enable();

    UniqueSocketDescriptor sockfd;
    if (in_fd != out_fd) {
        sockfd = duplex_new(instance.event_loop, instance.root_pool,
                            UniqueFileDescriptor(in_fd),
                            UniqueFileDescriptor(out_fd));
    } else
        sockfd = UniqueSocketDescriptor(in_fd);

    const char *mode = argv[3];
    if (strcmp(mode, "null") == 0)
        instance.mode = Instance::Mode::MODE_NULL;
    else if (strcmp(mode, "mirror") == 0)
        instance.mode = Instance::Mode::MIRROR;
    else if (strcmp(mode, "close") == 0)
        instance.mode = Instance::Mode::CLOSE;
    else if (strcmp(mode, "dummy") == 0)
        instance.mode = Instance::Mode::DUMMY;
    else if (strcmp(mode, "fixed") == 0)
        instance.mode = Instance::Mode::FIXED;
    else if (strcmp(mode, "huge") == 0)
        instance.mode = Instance::Mode::HUGE_;
    else if (strcmp(mode, "hold") == 0)
        instance.mode = Instance::Mode::HOLD;
    else {
        fprintf(stderr, "Unknown mode: %s\n", mode);
        return EXIT_FAILURE;
    }

    instance.connection = http_server_connection_new(instance.root_pool,
                                                     instance.event_loop,
                                                     sockfd,
                                                     FdType::FD_SOCKET,
                                                     nullptr,
                                                     nullptr, nullptr,
                                                     true, instance);

    instance.event_loop.Dispatch();

    return EXIT_SUCCESS;
} catch (...) {
    PrintException(std::current_exception());
    return EXIT_FAILURE;
}
<commit_msg>test/run_http_server: move enum Mode out of struct Instance<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "http_server/http_server.hxx"
#include "http_server/Request.hxx"
#include "http_server/Handler.hxx"
#include "http_headers.hxx"
#include "duplex.hxx"
#include "direct.hxx"
#include "istream/sink_null.hxx"
#include "istream/ByteIstream.hxx"
#include "istream/DelayedIstream.hxx"
#include "istream/HeadIstream.hxx"
#include "istream/istream_hold.hxx"
#include "istream/istream_memory.hxx"
#include "istream/ZeroIstream.hxx"
#include "istream/istream.hxx"
#include "istream/UnusedHoldPtr.hxx"
#include "PInstance.hxx"
#include "pool/pool.hxx"
#include "event/TimerEvent.hxx"
#include "event/ShutdownListener.hxx"
#include "fb_pool.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "util/Cancellable.hxx"
#include "util/PrintException.hxx"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum class Mode {
    MODE_NULL,
    MIRROR,

    /**
     * Response body of unknown length with keep-alive disabled.
     * Response body ends when socket is closed.
     */
    CLOSE,

    DUMMY,
    FIXED,
    HUGE_,
    HOLD,
};

struct Instance final : PInstance, HttpServerConnectionHandler, Cancellable {
    ShutdownListener shutdown_listener;

    Mode mode;

    HttpServerConnection *connection;

    UnusedHoldIstreamPtr request_body;

    TimerEvent timer;

    Instance()
        :shutdown_listener(event_loop, BIND_THIS_METHOD(ShutdownCallback)),
         timer(event_loop, BIND_THIS_METHOD(OnTimer)) {}

    void ShutdownCallback() noexcept;

    void OnTimer() noexcept;

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override {
        request_body.Clear();
        timer.Cancel();
    }

    /* virtual methods from class HttpServerConnectionHandler */
    void HandleHttpRequest(HttpServerRequest &request,
                           CancellablePointer &cancel_ptr) override;

    void LogHttpRequest(HttpServerRequest &,
                        http_status_t, int64_t,
                        uint64_t, uint64_t) override {}

    void HttpConnectionError(std::exception_ptr e) override;
    void HttpConnectionClosed() override;
};

void
Instance::ShutdownCallback() noexcept
{
    http_server_connection_close(connection);
}

void
Instance::OnTimer() noexcept
{
    http_server_connection_close(connection);
    shutdown_listener.Disable();
}

/*
 * http_server handler
 *
 */

void
Instance::HandleHttpRequest(HttpServerRequest &request,
                            gcc_unused CancellablePointer &cancel_ptr)
{
    switch (mode) {
        http_status_t status;
        static char data[0x100];

    case Mode::MODE_NULL:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_NO_CONTENT,
                             HttpHeaders(request.pool), nullptr);
        break;

    case Mode::MIRROR:
        status = request.body
            ? HTTP_STATUS_OK
            : HTTP_STATUS_NO_CONTENT;
        http_server_response(&request, status,
                             HttpHeaders(request.pool),
                             std::move(request.body));
        break;

    case Mode::CLOSE:
        /* disable keep-alive */
        http_server_connection_graceful(&request.connection);

        /* fall through */

    case Mode::DUMMY:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        {
            auto body = istream_head_new(request.pool,
                                         istream_zero_new(request.pool),
                                         256, false);
            body = istream_byte_new(request.pool, std::move(body));

            http_server_response(&request, HTTP_STATUS_OK,
                                 HttpHeaders(request.pool),
                                 std::move(body));
        }

        break;

    case Mode::FIXED:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_OK, HttpHeaders(request.pool),
                             istream_memory_new(request.pool,
                                                data, sizeof(data)));
        break;

    case Mode::HUGE_:
        if (request.body)
            sink_null_new(request.pool, std::move(request.body));

        http_server_response(&request, HTTP_STATUS_OK,
                             HttpHeaders(request.pool),
                             istream_head_new(request.pool,
                                              istream_zero_new(request.pool),
                                              512 * 1024, true));
        break;

    case Mode::HOLD:
        request_body = UnusedHoldIstreamPtr(request.pool,
                                            std::move(request.body));

        {
            auto delayed = istream_delayed_new(request.pool, event_loop);
            delayed.second.cancel_ptr = *this;

            http_server_response(&request, HTTP_STATUS_OK,
                                 HttpHeaders(request.pool),
                                 std::move(delayed.first));
        }

        static constexpr struct timeval t{0,0};
        timer.Add(t);
        break;
    }
}

void
Instance::HttpConnectionError(std::exception_ptr e)
{
    timer.Cancel();
    shutdown_listener.Disable();

    PrintException(e);
}

void
Instance::HttpConnectionClosed()
{
    timer.Cancel();
    shutdown_listener.Disable();
}

/*
 * main
 *
 */

int
main(int argc, char **argv)
try {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s INFD OUTFD {null|mirror|close|dummy|fixed|huge|hold}\n", argv[0]);
        return EXIT_FAILURE;
    }

    int in_fd, out_fd;

    if (strcmp(argv[1], "accept") == 0) {
        const int listen_fd = atoi(argv[2]);
        in_fd = out_fd = accept(listen_fd, nullptr, 0);
        if (in_fd < 0) {
            perror("accept() failed");
            return EXIT_FAILURE;
        }
    } else {
        in_fd = atoi(argv[1]);
        out_fd = atoi(argv[2]);
    }

    direct_global_init();
    const ScopeFbPoolInit fb_pool_init;

    Instance instance;
    instance.shutdown_listener.Enable();

    UniqueSocketDescriptor sockfd;
    if (in_fd != out_fd) {
        sockfd = duplex_new(instance.event_loop, instance.root_pool,
                            UniqueFileDescriptor(in_fd),
                            UniqueFileDescriptor(out_fd));
    } else
        sockfd = UniqueSocketDescriptor(in_fd);

    const char *mode = argv[3];
    if (strcmp(mode, "null") == 0)
        instance.mode = Mode::MODE_NULL;
    else if (strcmp(mode, "mirror") == 0)
        instance.mode = Mode::MIRROR;
    else if (strcmp(mode, "close") == 0)
        instance.mode = Mode::CLOSE;
    else if (strcmp(mode, "dummy") == 0)
        instance.mode = Mode::DUMMY;
    else if (strcmp(mode, "fixed") == 0)
        instance.mode = Mode::FIXED;
    else if (strcmp(mode, "huge") == 0)
        instance.mode = Mode::HUGE_;
    else if (strcmp(mode, "hold") == 0)
        instance.mode = Mode::HOLD;
    else {
        fprintf(stderr, "Unknown mode: %s\n", mode);
        return EXIT_FAILURE;
    }

    instance.connection = http_server_connection_new(instance.root_pool,
                                                     instance.event_loop,
                                                     sockfd,
                                                     FdType::FD_SOCKET,
                                                     nullptr,
                                                     nullptr, nullptr,
                                                     true, instance);

    instance.event_loop.Dispatch();

    return EXIT_SUCCESS;
} catch (...) {
    PrintException(std::current_exception());
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#pragma once

#include <cc/node.hpp>

namespace pip
{
  // The kinds of types.
  enum type_kind : int
  {
    tk_int,
    tk_range,
    tk_wild,
  };

  /// Represents a type.
  struct type : cc::node
  {
    type(type_kind k)
      : cc::node(k, {})
    { }
  };

  /// The type of integer values.
  ///
  /// TODO: I think we also need to represent integer encoding.
  struct int_type : type
  {
    int_type(int w)
      : type(tk_int), width(w)
    { }

    /// The width (precision) of integer values.
    int width;
  };

  /// A range over an integer type.
  struct range_type : type
  {
    range_type(type* t)
      : type(tk_range), value(t)
    { }

    /// The underlying integer type.
    type* value;
  };

  /// The type of wildcard values.
  struct wild_type : type
  {
    wild_type(int w)
      : type(tk_wild), width(w)
    { }

    /// The width (precision) of wildcard values.
    int width;
  };

// -------------------------------------------------------------------------- //
// Operations

  /// Returns the name of a type node.
  const char* get_node_name(type_kind k);

  // Returns the kind of a type.
  inline type_kind
  get_type_kind(const type* t)
  {
    return static_cast<type_kind>(t->kind);
  }

  /// Returns the node name of a program.
  inline const char*
  get_node_name(const type* t)
  {
    return get_node_name(get_type_kind(t));
  }

} // namespace pip
<commit_msg>added new types<commit_after>#pragma once

#include <cc/node.hpp>

namespace pip
{
  // The kinds of types.
  enum type_kind : int
  {
    tk_int,
    tk_range,
    tk_wild,
    tk_miss,
    tk_port,
    tk_loc,
  };

  /// Represents a type.
  struct type : cc::node
  {
    type(type_kind k)
      : cc::node(k, {})
    { }
  };

  /// The type of integer values.
  ///
  /// TODO: I think we also need to represent integer encoding.
  struct int_type : type
  {
    int_type(int w)
      : type(tk_int), width(w)
    { }

  /// The width (precision) of integer values.
    int width;
  };

  /// A range over an integer type.
  struct range_type : type
  {
    range_type(type* t)
      : type(tk_range), value(t)
    { }

  /// The underlying integer type.
    type* value;
  };

  /// The type of wildcard values.
  struct wild_type : type
  {
    wild_type(int w)
      : type(tk_wild), width(w)
    { }

  /// The width (precision) of wildcard values.
    int width;
  };

  /// The type of a miss expression; this is temporary.
  /// miss expressions may change to have the type of
  /// the key that was missed, or unit type
  struct miss_type : type
  {
    miss_type()
      : type(tk_miss)
    {}
  };

  /// The type of a port expression
  struct port_type : type
  {
    port_type()
      : type(tk_port)
    {}
  };

  /// The type of a location or field
  struct loc_type : type
  {
    loc_type()
      : type(tk_loc)
    {}
  };

// -------------------------------------------------------------------------- //
// Operations

  /// Returns the name of a type node.
  const char* get_node_name(type_kind k);

  // Returns the kind of a type.
  inline type_kind
  get_type_kind(const type* t)
  {
    return static_cast<type_kind>(t->kind);
  }

  /// Returns the node name of a program.
  inline const char*
  get_node_name(const type* t)
  {
    return get_node_name(get_type_kind(t));
  }
} // namespace pip
<|endoftext|>


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

#include <mlk/filesystem/filesystem.h>

int main()
{
	mlk::fs::fs_handle<mlk::fs::fs_type::file> my_file{"/path/to/file"};

	if(my_file.exists())
		return 1;

	my_file.create();
	my_file.open_io(std::ios::out);
	my_file.write_line("some line");
	my_file.write("more text in same line");

	mlk::fs::fs_handle<mlk::fs::fs_type::dir> my_dir{"/path/to/dir"};

	if(!my_dir.exists())
		my_dir.create();
}
<commit_msg>adapted test_filesystem.cpp<commit_after>//
// Copyright (c) 2013 Christoph Malek
// See LICENSE for more information.
//

#include <mlk/filesystem/filesystem.h>

int main()
{
	mlk::fs::fs_handle<mlk::fs::fs_type::file> my_file{"/path/to/file"};
	// shortcut: mlk::fs::file_handle

	if(my_file.exists())
		return 1;

	my_file.create();
	my_file.open_io(std::ios::out);
	my_file.write_line("some line");
	my_file.write("more text in same line");

	mlk::fs::fs_handle<mlk::fs::fs_type::dir> my_dir{"/path/to/dir"};
	// shortcut: mlk::fs::dir_handle

	if(!my_dir.exists())
		my_dir.create();

	// get contents of dir:
	auto content(my_dir.get_content<true>()); // true: recursive or not
	for(auto& a : content) // 'a' is from type 'mlk::fs::dir_item'
		std::cout << a.path << std::endl;
}
<|endoftext|>


<commit_before>/**
 * Copyright © 2016 IBM Corporation
 *
 * 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.
 */
#include <iostream>
#include <exception>
#include "manager.hpp"

namespace phosphor
{
namespace inventory
{
namespace manager
{
namespace details
{

/** @brief Fowrarding signal callback.
 *
 *  Extracts per-signal specific context and forwards the call to the manager
 *  instance.
 */
auto _signal(sd_bus_message *m, void *data, sd_bus_error *e) noexcept
{
    try {
        auto msg = sdbusplus::message::message(m);
        auto &args = *static_cast<Manager::SigArg*>(data);
        sd_bus_message_ref(m);
        auto &mgr = *std::get<0>(args);
        mgr.signal(
                msg,
                static_cast<const details::DbusSignal &>(
                    *std::get<1>(args)),
                *std::get<2>(args));
    }
    catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

} // namespace details

Manager::Manager(
        sdbusplus::bus::bus &&bus,
        const char *busname,
        const char *root,
        const char *iface) :
    details::ServerObject<details::ManagerIface>(bus, root),
    _shutdown(false),
    _root(root),
    _bus(std::move(bus)),
    _manager(sdbusplus::server::manager::manager(_bus, root))
{
    for (auto &group: _events)
    {
        for (auto pEvent: std::get<0>(group))
        {
            if (pEvent->type !=
                    details::Event::Type::DBUS_SIGNAL)
                continue;

            // Create a callback context for this event group.
            auto dbusEvent = static_cast<details::DbusSignal *>(
                    pEvent.get());

            // Go ahead and store an iterator pointing at
            // the event data to avoid lookups later since
            // additional signal callbacks aren't added
            // after the manager is constructed.
            _sigargs.emplace_back(
                    std::make_unique<SigArg>(
                        std::make_tuple(
                            this,
                            dbusEvent,
                            &group)));

            // Register our callback and the context for
            // each signal event.
            _matches.emplace_back(
                    sdbusplus::server::match::match(
                        _bus,
                        std::get<0>(*dbusEvent),
                        details::_signal,
                        _sigargs.back().get()));
        }
    }

    _bus.request_name(busname);
}

void Manager::shutdown() noexcept
{
    _shutdown = true;
}

void Manager::run() noexcept
{
    while(!_shutdown) {
        try {
            _bus.process_discard();
            _bus.wait(5000000);
        }
        catch (const std::exception &e) {
            std::cerr << e.what() << std::endl;
        }
    }
}

void Manager::notify(std::string path, Object object)
{
    try {
        if(object.cbegin() == object.cend())
            throw std::runtime_error(
                    "No interfaces in " + path);

        path.insert(0, _root);

        auto obj = _refs.find(path);
        if(obj != _refs.end())
            throw std::runtime_error(
                    obj->first + " already exists");

        // Create an interface holder for each interface
        // provided by the client and group them into
        // a container.
        InterfaceComposite ref;

        for (auto &x: object) {
            auto maker = _makers.find(x.first.c_str());

            if(maker == _makers.end())
                throw std::runtime_error(
                        "Unimplemented interface: " + x.first);

            ref.emplace(
                    std::make_pair(
                        x.first,
                        (maker->second)(_bus, path.c_str())));
        }

        // Hang on to a reference to the object (interfaces)
        // so it stays on the bus, and so we can make calls
        // to it if needed.
        _refs.emplace(
                std::make_pair(
                    path, std::move(ref)));
    }
    catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
}

void Manager::signal(
        sdbusplus::message::message &msg,
        const details::DbusSignal &event,
        const EventInfo &info)
{
    auto &filter = *std::get<1>(event);
    auto &actions = std::get<1>(info);

    if(filter(msg, *this)) {
        for (auto &action: actions)
            (*action)(*this);
    }
}

void Manager::destroyObject(const char *path)
{
    std::string p{path};
    _refs.erase(_root + p);
}

details::holder::Base& Manager::getInterfaceHolder(
        const char *path, const char *interface)
{
    return const_cast<const Manager *>(
            this)->getInterfaceHolder(path, interface);
}

details::holder::Base& Manager::getInterfaceHolder(
        const char *path, const char *interface) const
{
    std::string p{path};
    auto oit = _refs.find(_root + p);
    if(oit == _refs.end())
        throw std::runtime_error(
                _root + p + " was not found");

    auto &obj = oit->second;
    auto iit = obj.find(interface);
    if(iit == obj.end())
        throw std::runtime_error(
                "interface was not found");

    return *iit->second;
}

} // namespace manager
} // namespace inventory
} // namespace phosphor

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>Fix broken usage of emplace<commit_after>/**
 * Copyright © 2016 IBM Corporation
 *
 * 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.
 */
#include <iostream>
#include <exception>
#include "manager.hpp"

namespace phosphor
{
namespace inventory
{
namespace manager
{
namespace details
{

/** @brief Fowrarding signal callback.
 *
 *  Extracts per-signal specific context and forwards the call to the manager
 *  instance.
 */
auto _signal(sd_bus_message *m, void *data, sd_bus_error *e) noexcept
{
    try {
        auto msg = sdbusplus::message::message(m);
        auto &args = *static_cast<Manager::SigArg*>(data);
        sd_bus_message_ref(m);
        auto &mgr = *std::get<0>(args);
        mgr.signal(
                msg,
                static_cast<const details::DbusSignal &>(
                    *std::get<1>(args)),
                *std::get<2>(args));
    }
    catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

} // namespace details

Manager::Manager(
        sdbusplus::bus::bus &&bus,
        const char *busname,
        const char *root,
        const char *iface) :
    details::ServerObject<details::ManagerIface>(bus, root),
    _shutdown(false),
    _root(root),
    _bus(std::move(bus)),
    _manager(sdbusplus::server::manager::manager(_bus, root))
{
    for (auto &group: _events)
    {
        for (auto pEvent: std::get<0>(group))
        {
            if (pEvent->type !=
                    details::Event::Type::DBUS_SIGNAL)
                continue;

            // Create a callback context for this event group.
            auto dbusEvent = static_cast<details::DbusSignal *>(
                    pEvent.get());

            // Go ahead and store an iterator pointing at
            // the event data to avoid lookups later since
            // additional signal callbacks aren't added
            // after the manager is constructed.
            _sigargs.emplace_back(
                    std::make_unique<SigArg>(
                            this,
                            dbusEvent,
                            &group));

            // Register our callback and the context for
            // each signal event.
            _matches.emplace_back(
                        _bus,
                        std::get<0>(*dbusEvent),
                        details::_signal,
                        _sigargs.back().get());
        }
    }

    _bus.request_name(busname);
}

void Manager::shutdown() noexcept
{
    _shutdown = true;
}

void Manager::run() noexcept
{
    while(!_shutdown) {
        try {
            _bus.process_discard();
            _bus.wait(5000000);
        }
        catch (const std::exception &e) {
            std::cerr << e.what() << std::endl;
        }
    }
}

void Manager::notify(std::string path, Object object)
{
    try {
        if(object.cbegin() == object.cend())
            throw std::runtime_error(
                    "No interfaces in " + path);

        path.insert(0, _root);

        auto obj = _refs.find(path);
        if(obj != _refs.end())
            throw std::runtime_error(
                    obj->first + " already exists");

        // Create an interface holder for each interface
        // provided by the client and group them into
        // a container.
        InterfaceComposite ref;

        for (auto &x: object) {
            auto maker = _makers.find(x.first.c_str());

            if(maker == _makers.end())
                throw std::runtime_error(
                        "Unimplemented interface: " + x.first);

            ref.emplace(x.first,
                    (maker->second)(_bus, path.c_str()));
        }

        // Hang on to a reference to the object (interfaces)
        // so it stays on the bus, and so we can make calls
        // to it if needed.
        _refs.emplace(
                path, std::move(ref));
    }
    catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
}

void Manager::signal(
        sdbusplus::message::message &msg,
        const details::DbusSignal &event,
        const EventInfo &info)
{
    auto &filter = *std::get<1>(event);
    auto &actions = std::get<1>(info);

    if(filter(msg, *this)) {
        for (auto &action: actions)
            (*action)(*this);
    }
}

void Manager::destroyObject(const char *path)
{
    std::string p{path};
    _refs.erase(_root + p);
}

details::holder::Base& Manager::getInterfaceHolder(
        const char *path, const char *interface)
{
    return const_cast<const Manager *>(
            this)->getInterfaceHolder(path, interface);
}

details::holder::Base& Manager::getInterfaceHolder(
        const char *path, const char *interface) const
{
    std::string p{path};
    auto oit = _refs.find(_root + p);
    if(oit == _refs.end())
        throw std::runtime_error(
                _root + p + " was not found");

    auto &obj = oit->second;
    auto iit = obj.find(interface);
    if(iit == obj.end())
        throw std::runtime_error(
                "interface was not found");

    return *iit->second;
}

} // namespace manager
} // namespace inventory
} // namespace phosphor

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>