<commit_before>/*
* utility/KHR.cpp
*
* Copyright (C) 2017 by MegaMol Team
* Alle Rechte vorbehalten.
*/

#include "stdafx.h"
#include "KHR.h"
#include "vislib/graphics/gl/IncludeAllGL.h"
#include "GLFW/glfw3.h"
#include "vislib/sys/Log.h"

using namespace megamol::console::utility;

int KHR::startDebug() {
#if !defined(_WIN32) && !defined(HAS_LIBUNWIND)
    vislib::sys::Log::DefaultLog.WriteError("Libunwind is required to use KHR debug.");
    vislib::sys::Log::DefaultLog.WriteError("You need to set the compilerflag USE_LIBUNWIND=true.");
    return 1;
#else
    GLint numExt;
    glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
    for (int x = 0; x < numExt; x++) {
        const GLubyte *str = glGetStringi(GL_EXTENSIONS, x);
        if (strcmp(reinterpret_cast<const char *>(str), "GL_KHR_debug") == 0) {
            glEnable(GL_DEBUG_OUTPUT);
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
            glDebugMessageCallback((GLDEBUGPROC)DebugCallback, NULL);
            glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
            GLuint ignorethis;
            ignorethis = 131185;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
            ignorethis = 131184;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
            ignorethis = 131204;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
        }
    }
    return 0;
#endif
}

void KHR::DebugCallback(unsigned int source, unsigned int type, unsigned int id,
    unsigned int severity, int length, const char* message, void* userParam) {
    const char *sourceText, *typeText, *severityText;
    switch (source) {
    case GL_DEBUG_SOURCE_API:
        sourceText = "API";
        break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
        sourceText = "Window System";
        break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER:
        sourceText = "Shader Compiler";
        break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:
        sourceText = "Third Party";
        break;
    case GL_DEBUG_SOURCE_APPLICATION:
        sourceText = "Application";
        break;
    case GL_DEBUG_SOURCE_OTHER:
        sourceText = "Other";
        break;
    default:
        sourceText = "Unknown";
        break;
    }
    switch (type) {
    case GL_DEBUG_TYPE_ERROR:
        typeText = "Error";
        break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
        typeText = "Deprecated Behavior";
        break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
        typeText = "Undefined Behavior";
        break;
    case GL_DEBUG_TYPE_PORTABILITY:
        typeText = "Portability";
        break;
    case GL_DEBUG_TYPE_PERFORMANCE:
        typeText = "Performance";
        break;
    case GL_DEBUG_TYPE_OTHER:
        typeText = "Other";
        break;
    case GL_DEBUG_TYPE_MARKER:
        typeText = "Marker";
        break;
    default:
        typeText = "Unknown";
        break;
    }
    switch (severity) {
    case GL_DEBUG_SEVERITY_HIGH:
        severityText = "High";
        break;
    case GL_DEBUG_SEVERITY_MEDIUM:
        severityText = "Medium";
        break;
    case GL_DEBUG_SEVERITY_LOW:
        severityText = "Low";
        break;
    case GL_DEBUG_SEVERITY_NOTIFICATION:
        severityText = "Notification";
        break;
    default:
        severityText = "Unknown";
        break;
    }
    const int outputlength = 8192;
    static char outputstring[outputlength];
    std::string stack = getStack();
#ifdef _WIN32
    sprintf_s(outputstring, outputlength, "[%s %s] (%s %u) %s\nstack trace:\n%s\n", sourceText, severityText, typeText, id, message, stack.c_str());
    OutputDebugStringA(outputstring);
#else
    sprintf(outputstring, "[%s %s] (%s %u) %s\nstack trace:\n%s\n", sourceText, severityText, typeText, id, message, stack.c_str());
#endif
    if (type == GL_DEBUG_TYPE_ERROR) {
        vislib::sys::Log::DefaultLog.WriteError("%s", outputstring);
    } else if (type == GL_DEBUG_TYPE_OTHER || type == GL_DEBUG_TYPE_MARKER) {
        vislib::sys::Log::DefaultLog.WriteInfo("%s", outputstring);
    } else {
        vislib::sys::Log::DefaultLog.WriteWarn("%s", outputstring);
    }
}

#ifdef _WIN32
std::string KHR::getStack() {
    unsigned int   i;
    void         * stack[100];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;
    std::stringstream output;

    process = GetCurrentProcess();

    SymSetOptions(SYMOPT_LOAD_LINES);

    SymInitialize(process, NULL, TRUE);

    frames = CaptureStackBackTrace(0, 200, stack, NULL);
    symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    for (i = 0; i < frames; i++) {
        SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
        DWORD  dwDisplacement;
        IMAGEHLP_LINE64 line;

        line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
        if (!strstr(symbol->Name, "khr::getStack") &&
            !strstr(symbol->Name, "khr::DebugCallback") &&
            SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) {

            output << "function: " << symbol->Name <<
                " - line: " << line.LineNumber << "\n";

        }
        if (0 == strcmp(symbol->Name, "main"))
            break;
    }

    free(symbol);
    return output.str();
}
#else
#ifdef HAS_LIBUNWIND
int KHR::getFileAndLine(unw_word_t addr, char* file, size_t flen, int* line) {
    static char buf[256];
    char *p;

    // prepare command to be executed
    // our program need to be passed after the -e parameter
    sprintf(buf, "/usr/bin/addr2line -C -e ./%s -f -i %lx", program_invocation_short_name, addr);

    FILE* f = popen(buf, "r");

    if (f == NULL) {
        vislib::sys::Log::DefaultLog.WriteError("%s", buf);
        return 0;
    }

    // get function name
    fgets(buf, 256, f);

    // get file and line
    fgets(buf, 256, f);

    if (buf[0] != '?') {
        int l;
        char *p = buf;

        // file name is until ':'
        while (*p != ':') {
            p++;
        }

        *p++ = 0;
        // after file name follows line number
        strcpy(file, buf);
        sscanf(p, "%d", line);
    } else {
        strcpy(file, "unknown");
        *line = -1;
    }

    pclose(f);
    return 1;
}

std::string KHR::getStack() {

    unw_cursor_t cursor;
    unw_context_t uc;
    unw_word_t ip, sp, off;
    unw_proc_info_t pi;
    char file[256], name[256];
    int line;
    int status;
    std::stringstream output;

    unw_getcontext(&uc);
    unw_init_local(&cursor, &uc);
    while (unw_step(&cursor) > 0) {
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        unw_get_reg(&cursor, UNW_REG_SP, &sp);

        unw_get_proc_name(&cursor, name, sizeof(name), &off);
        getFileAndLine((long)ip, file, 256, &line);

        if (line >= 0) {
            char *realname;
            realname = abi::__cxa_demangle(name, 0, 0, &status);

            if (realname) {
	        output << realname << ": " << file << ", " << line << std::endl;
                free(realname);
            } else {
	        output << name << ": " << file << ", " << line << std::endl;
            }
        }
    }
    return output.str();
}
#endif
#endif

<commit_msg>fixed console to build without KHR<commit_after>/*
* utility/KHR.cpp
*
* Copyright (C) 2017 by MegaMol Team
* Alle Rechte vorbehalten.
*/

#include "stdafx.h"
#include "KHR.h"
#include "vislib/graphics/gl/IncludeAllGL.h"
#include "GLFW/glfw3.h"
#include "vislib/sys/Log.h"

using namespace megamol::console::utility;

int KHR::startDebug() {
#if (!defined(_WIN32) && !defined(HAS_LIBUNWIND))
    vislib::sys::Log::DefaultLog.WriteError("Libunwind is required to use KHR debug.");
    vislib::sys::Log::DefaultLog.WriteError("You need to set the compilerflag USE_LIBUNWIND=true.");
    return 1;
}
#else
    GLint numExt;
    glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
    for (int x = 0; x < numExt; x++) {
        const GLubyte *str = glGetStringi(GL_EXTENSIONS, x);
        if (strcmp(reinterpret_cast<const char *>(str), "GL_KHR_debug") == 0) {
            glEnable(GL_DEBUG_OUTPUT);
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
            glDebugMessageCallback((GLDEBUGPROC)DebugCallback, NULL);
            glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
            GLuint ignorethis;
            ignorethis = 131185;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
            ignorethis = 131184;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
            ignorethis = 131204;
            glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1, &ignorethis, GL_FALSE);
        }
    }
    return 0;
}

void KHR::DebugCallback(unsigned int source, unsigned int type, unsigned int id,
    unsigned int severity, int length, const char* message, void* userParam) {
    const char *sourceText, *typeText, *severityText;
    switch (source) {
    case GL_DEBUG_SOURCE_API:
        sourceText = "API";
        break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
        sourceText = "Window System";
        break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER:
        sourceText = "Shader Compiler";
        break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:
        sourceText = "Third Party";
        break;
    case GL_DEBUG_SOURCE_APPLICATION:
        sourceText = "Application";
        break;
    case GL_DEBUG_SOURCE_OTHER:
        sourceText = "Other";
        break;
    default:
        sourceText = "Unknown";
        break;
    }
    switch (type) {
    case GL_DEBUG_TYPE_ERROR:
        typeText = "Error";
        break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
        typeText = "Deprecated Behavior";
        break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
        typeText = "Undefined Behavior";
        break;
    case GL_DEBUG_TYPE_PORTABILITY:
        typeText = "Portability";
        break;
    case GL_DEBUG_TYPE_PERFORMANCE:
        typeText = "Performance";
        break;
    case GL_DEBUG_TYPE_OTHER:
        typeText = "Other";
        break;
    case GL_DEBUG_TYPE_MARKER:
        typeText = "Marker";
        break;
    default:
        typeText = "Unknown";
        break;
    }
    switch (severity) {
    case GL_DEBUG_SEVERITY_HIGH:
        severityText = "High";
        break;
    case GL_DEBUG_SEVERITY_MEDIUM:
        severityText = "Medium";
        break;
    case GL_DEBUG_SEVERITY_LOW:
        severityText = "Low";
        break;
    case GL_DEBUG_SEVERITY_NOTIFICATION:
        severityText = "Notification";
        break;
    default:
        severityText = "Unknown";
        break;
    }
    const int outputlength = 8192;
    static char outputstring[outputlength];
    std::string stack = getStack();
#ifdef _WIN32
    sprintf_s(outputstring, outputlength, "[%s %s] (%s %u) %s\nstack trace:\n%s\n", sourceText, severityText, typeText, id, message, stack.c_str());
    OutputDebugStringA(outputstring);
#else
    sprintf(outputstring, "[%s %s] (%s %u) %s\nstack trace:\n%s\n", sourceText, severityText, typeText, id, message, stack.c_str());
#endif
    if (type == GL_DEBUG_TYPE_ERROR) {
        vislib::sys::Log::DefaultLog.WriteError("%s", outputstring);
    } else if (type == GL_DEBUG_TYPE_OTHER || type == GL_DEBUG_TYPE_MARKER) {
        vislib::sys::Log::DefaultLog.WriteInfo("%s", outputstring);
    } else {
        vislib::sys::Log::DefaultLog.WriteWarn("%s", outputstring);
    }
}

#ifdef _WIN32
std::string KHR::getStack() {
    unsigned int   i;
    void         * stack[100];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;
    std::stringstream output;

    process = GetCurrentProcess();

    SymSetOptions(SYMOPT_LOAD_LINES);

    SymInitialize(process, NULL, TRUE);

    frames = CaptureStackBackTrace(0, 200, stack, NULL);
    symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    for (i = 0; i < frames; i++) {
        SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
        DWORD  dwDisplacement;
        IMAGEHLP_LINE64 line;

        line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
        if (!strstr(symbol->Name, "khr::getStack") &&
            !strstr(symbol->Name, "khr::DebugCallback") &&
            SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) {

            output << "function: " << symbol->Name <<
                " - line: " << line.LineNumber << "\n";

        }
        if (0 == strcmp(symbol->Name, "main"))
            break;
    }

    free(symbol);
    return output.str();
}
#else
#ifdef HAS_LIBUNWIND
int KHR::getFileAndLine(unw_word_t addr, char* file, size_t flen, int* line) {
    static char buf[256];
    char *p;

    // prepare command to be executed
    // our program need to be passed after the -e parameter
    sprintf(buf, "/usr/bin/addr2line -C -e ./%s -f -i %lx", program_invocation_short_name, addr);

    FILE* f = popen(buf, "r");

    if (f == NULL) {
        vislib::sys::Log::DefaultLog.WriteError("%s", buf);
        return 0;
    }

    // get function name
    fgets(buf, 256, f);

    // get file and line
    fgets(buf, 256, f);

    if (buf[0] != '?') {
        int l;
        char *p = buf;

        // file name is until ':'
        while (*p != ':') {
            p++;
        }

        *p++ = 0;
        // after file name follows line number
        strcpy(file, buf);
        sscanf(p, "%d", line);
    } else {
        strcpy(file, "unknown");
        *line = -1;
    }

    pclose(f);
    return 1;
}

std::string KHR::getStack() {

    unw_cursor_t cursor;
    unw_context_t uc;
    unw_word_t ip, sp, off;
    unw_proc_info_t pi;
    char file[256], name[256];
    int line;
    int status;
    std::stringstream output;

    unw_getcontext(&uc);
    unw_init_local(&cursor, &uc);
    while (unw_step(&cursor) > 0) {
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        unw_get_reg(&cursor, UNW_REG_SP, &sp);

        unw_get_proc_name(&cursor, name, sizeof(name), &off);
        getFileAndLine((long)ip, file, 256, &line);

        if (line >= 0) {
            char *realname;
            realname = abi::__cxa_demangle(name, 0, 0, &status);

            if (realname) {
	        output << realname << ": " << file << ", " << line << std::endl;
                free(realname);
            } else {
	        output << name << ": " << file << ", " << line << std::endl;
            }
        }
    }
    return output.str();
}
#endif
#endif
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "versionbits.h"

#include "consensus/params.h"

const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
    {
        /*.name =*/ "testdummy",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "csv",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "segwit",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "segsignal",
        /*.gbt_force =*/ true,
    }
};

ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
    int nPeriod = Period(params);
    int nThreshold = Threshold(params);
    int64_t nTimeStart = BeginTime(params);
    int64_t nTimeTimeout = EndTime(params);

    // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
    if (pindexPrev != NULL) {
        pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
    }

    // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
    std::vector<const CBlockIndex*> vToCompute;
    while (cache.count(pindexPrev) == 0) {
        if (pindexPrev == NULL) {
            // The genesis block is by definition defined.
            cache[pindexPrev] = THRESHOLD_DEFINED;
            break;
        }
        if (pindexPrev->GetMedianTimePast() < nTimeStart) {
            // Optimization: don't recompute down further, as we know every earlier block will be before the start time
            cache[pindexPrev] = THRESHOLD_DEFINED;
            break;
        }
        vToCompute.push_back(pindexPrev);
        pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
    }

    // At this point, cache[pindexPrev] is known
    assert(cache.count(pindexPrev));
    ThresholdState state = cache[pindexPrev];

    // Now walk forward and compute the state of descendants of pindexPrev
    while (!vToCompute.empty()) {
        ThresholdState stateNext = state;
        pindexPrev = vToCompute.back();
        vToCompute.pop_back();

        switch (state) {
            case THRESHOLD_DEFINED: {
                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
                    stateNext = THRESHOLD_FAILED;
                } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
                    stateNext = THRESHOLD_STARTED;
                }
                break;
            }
            case THRESHOLD_STARTED: {
                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
                    stateNext = THRESHOLD_FAILED;
                    break;
                }
                // We need to count
                const CBlockIndex* pindexCount = pindexPrev;
                int count = 0;
                for (int i = 0; i < nPeriod; i++) {
                    if (Condition(pindexCount, params)) {
                        count++;
                    }
                    pindexCount = pindexCount->pprev;
                }
                if (count >= nThreshold) {
                    stateNext = THRESHOLD_LOCKED_IN;
                }
                break;
            }
            case THRESHOLD_LOCKED_IN: {
                // Always progresses into ACTIVE.
                stateNext = THRESHOLD_ACTIVE;
                break;
            }
            case THRESHOLD_FAILED:
            case THRESHOLD_ACTIVE: {
                // Nothing happens, these are terminal states.
                break;
            }
        }
        cache[pindexPrev] = state = stateNext;
    }

    return state;
}

int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
    const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);

    // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
    if (initialState == THRESHOLD_DEFINED) {
        return 0;
    }

    const int nPeriod = Period(params);

    // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
    // To ease understanding of the following height calculation, it helps to remember that
    // right now pindexPrev points to the block prior to the block that we are computing for, thus:
    // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
    // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
    // The parent of the genesis block is represented by NULL.
    pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));

    const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);

    while (previousPeriodParent != NULL && GetStateFor(previousPeriodParent, params, cache) == initialState) {
        pindexPrev = previousPeriodParent;
        previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
    }

    // Adjust the result because right now we point to the parent block.
    return pindexPrev->nHeight + 1;
}

namespace
{
/**
 * Class to implement versionbits logic.
 */
class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
private:
    const Consensus::DeploymentPos id;

protected:
    int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
    int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
    int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
    int Threshold(const Consensus::Params& params) const {
        if (params.vDeployments[id].bit == params.vDeployments[Consensus::DEPLOYMENT_SEGSIGNAL].bit &&
            params.vDeployments[id].nStartTime == params.vDeployments[Consensus::DEPLOYMENT_SEGSIGNAL].nStartTime) {
            return 1612; // 80% threshold for SEGSIGNAL only
        }
        return params.nRuleChangeActivationThreshold;
    }

    bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
    {
        return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
    }

public:
    VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
    uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
};

}

ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
    return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
}

int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
    return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
}

uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
    return VersionBitsConditionChecker(pos).Mask(params);
}

void VersionBitsCache::Clear()
{
    for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
        caches[d].clear();
    }
}
<commit_msg>Use BIP91 activation threshold only on networks with a 95% BIP9 activation threshold.<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "versionbits.h"

#include "consensus/params.h"

const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
    {
        /*.name =*/ "testdummy",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "csv",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "segwit",
        /*.gbt_force =*/ true,
    },
    {
        /*.name =*/ "segsignal",
        /*.gbt_force =*/ true,
    }
};

ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
    int nPeriod = Period(params);
    int nThreshold = Threshold(params);
    int64_t nTimeStart = BeginTime(params);
    int64_t nTimeTimeout = EndTime(params);

    // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
    if (pindexPrev != NULL) {
        pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
    }

    // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
    std::vector<const CBlockIndex*> vToCompute;
    while (cache.count(pindexPrev) == 0) {
        if (pindexPrev == NULL) {
            // The genesis block is by definition defined.
            cache[pindexPrev] = THRESHOLD_DEFINED;
            break;
        }
        if (pindexPrev->GetMedianTimePast() < nTimeStart) {
            // Optimization: don't recompute down further, as we know every earlier block will be before the start time
            cache[pindexPrev] = THRESHOLD_DEFINED;
            break;
        }
        vToCompute.push_back(pindexPrev);
        pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
    }

    // At this point, cache[pindexPrev] is known
    assert(cache.count(pindexPrev));
    ThresholdState state = cache[pindexPrev];

    // Now walk forward and compute the state of descendants of pindexPrev
    while (!vToCompute.empty()) {
        ThresholdState stateNext = state;
        pindexPrev = vToCompute.back();
        vToCompute.pop_back();

        switch (state) {
            case THRESHOLD_DEFINED: {
                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
                    stateNext = THRESHOLD_FAILED;
                } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
                    stateNext = THRESHOLD_STARTED;
                }
                break;
            }
            case THRESHOLD_STARTED: {
                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
                    stateNext = THRESHOLD_FAILED;
                    break;
                }
                // We need to count
                const CBlockIndex* pindexCount = pindexPrev;
                int count = 0;
                for (int i = 0; i < nPeriod; i++) {
                    if (Condition(pindexCount, params)) {
                        count++;
                    }
                    pindexCount = pindexCount->pprev;
                }
                if (count >= nThreshold) {
                    stateNext = THRESHOLD_LOCKED_IN;
                }
                break;
            }
            case THRESHOLD_LOCKED_IN: {
                // Always progresses into ACTIVE.
                stateNext = THRESHOLD_ACTIVE;
                break;
            }
            case THRESHOLD_FAILED:
            case THRESHOLD_ACTIVE: {
                // Nothing happens, these are terminal states.
                break;
            }
        }
        cache[pindexPrev] = state = stateNext;
    }

    return state;
}

int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
    const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);

    // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
    if (initialState == THRESHOLD_DEFINED) {
        return 0;
    }

    const int nPeriod = Period(params);

    // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
    // To ease understanding of the following height calculation, it helps to remember that
    // right now pindexPrev points to the block prior to the block that we are computing for, thus:
    // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
    // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
    // The parent of the genesis block is represented by NULL.
    pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));

    const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);

    while (previousPeriodParent != NULL && GetStateFor(previousPeriodParent, params, cache) == initialState) {
        pindexPrev = previousPeriodParent;
        previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
    }

    // Adjust the result because right now we point to the parent block.
    return pindexPrev->nHeight + 1;
}

namespace
{
/**
 * Class to implement versionbits logic.
 */
class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
private:
    const Consensus::DeploymentPos id;

protected:
    int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
    int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
    int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
    int Threshold(const Consensus::Params& params) const {
        if (params.nRuleChangeActivationThreshold == 1916 && params.nMinerConfirmationWindow == 2016 &&
            params.vDeployments[id].bit == params.vDeployments[Consensus::DEPLOYMENT_SEGSIGNAL].bit &&
            params.vDeployments[id].nStartTime == params.vDeployments[Consensus::DEPLOYMENT_SEGSIGNAL].nStartTime) {
            return 1612; // 80% threshold for SEGSIGNAL only
        }
        return params.nRuleChangeActivationThreshold;
    }

    bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
    {
        return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
    }

public:
    VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
    uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
};

}

ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
    return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
}

int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
    return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
}

uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
    return VersionBitsConditionChecker(pos).Mask(params);
}

void VersionBitsCache::Clear()
{
    for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
        caches[d].clear();
    }
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////
//
// CoinVault
//
// versioninfo.cpp
//
// Copyright (c) 2013 Eric Lombrozo
//
// All Rights Reserved.

#include "versioninfo.h"
#include "../BuildInfo.h"

#include <CoinDB/Schema.h>

#include <openssl/opensslv.h>

// Definitions
const int VERSIONPADDINGRIGHT = 20;
const int VERSIONPADDINGBOTTOM = 30;

const QString VERSIONTEXT("0.7.3 beta");

const QString commitHash(COMMIT_HASH);
const QString shortCommitHash(QString(COMMIT_HASH).left(7));

const uint32_t schemaVersion(SCHEMA_VERSION);
const QString schemaVersionText(QString::number(SCHEMA_VERSION));

const uint32_t openSSLVersionNumber(OPENSSL_VERSION_NUMBER);
const QString openSSLVersionText(OPENSSL_VERSION_TEXT);

// Accessors
int getVersionPaddingRight() { return VERSIONPADDINGRIGHT; }
int getVersionPaddingBottom() { return VERSIONPADDINGBOTTOM; }

const QString& getVersionText() { return VERSIONTEXT; }

const QString& getCommitHash() { return commitHash; }
const QString& getShortCommitHash() { return shortCommitHash; }

uint32_t getSchemaVersion() { return schemaVersion; }
const QString& getSchemaVersionText() { return schemaVersionText; }

uint32_t getOpenSSLVersionNumber() { return OPENSSL_VERSION_NUMBER; }
const QString& getOpenSSLVersionText() { return openSSLVersionText; }

<commit_msg>v0.7.4<commit_after>///////////////////////////////////////////////////////////////////
//
// CoinVault
//
// versioninfo.cpp
//
// Copyright (c) 2013 Eric Lombrozo
//
// All Rights Reserved.

#include "versioninfo.h"
#include "../BuildInfo.h"

#include <CoinDB/Schema.h>

#include <openssl/opensslv.h>

// Definitions
const int VERSIONPADDINGRIGHT = 20;
const int VERSIONPADDINGBOTTOM = 30;

const QString VERSIONTEXT("0.7.4 beta");

const QString commitHash(COMMIT_HASH);
const QString shortCommitHash(QString(COMMIT_HASH).left(7));

const uint32_t schemaVersion(SCHEMA_VERSION);
const QString schemaVersionText(QString::number(SCHEMA_VERSION));

const uint32_t openSSLVersionNumber(OPENSSL_VERSION_NUMBER);
const QString openSSLVersionText(OPENSSL_VERSION_TEXT);

// Accessors
int getVersionPaddingRight() { return VERSIONPADDINGRIGHT; }
int getVersionPaddingBottom() { return VERSIONPADDINGBOTTOM; }

const QString& getVersionText() { return VERSIONTEXT; }

const QString& getCommitHash() { return commitHash; }
const QString& getShortCommitHash() { return shortCommitHash; }

uint32_t getSchemaVersion() { return schemaVersion; }
const QString& getSchemaVersionText() { return schemaVersionText; }

uint32_t getOpenSSLVersionNumber() { return openSSLVersionNumber; }
const QString& getOpenSSLVersionText() { return openSSLVersionText; }

<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <vlCore/Time.hpp>
#include <ctime>
#include <cmath>

#if defined(VL_PLATFORM_LINUX) || defined(VL_PLATFORM_MACOSX)
  #include <sys/time.h> // gettimeofday()
  #include <unistd.h>   // usleep()
#endif

using namespace vl;

//-----------------------------------------------------------------------------
// Time
//-----------------------------------------------------------------------------
Time::Time()
{
  VL_DEBUG_SET_OBJECT_NAME()

  for(int i=0; i<VL_MAX_TIMERS; ++i)
    mStart[i] = -1;

  #if defined(VL_PLATFORM_WINDOWS)
    SYSTEMTIME local_time;
    GetLocalTime(&local_time);
    mYear = local_time.wYear;
    mMonth = local_time.wMonth;
    mDayOfWeek = local_time.wDayOfWeek;
    mDayOfMonth = local_time.wDay;
    mHour = local_time.wHour;
    mMinute = local_time.wMinute;
    mSecond = local_time.wSecond;
    mMicrosecond = local_time.wMilliseconds * 1000;
  #elif defined(__GNUG__)
    time_t secs;
    ::time(&secs);
    tm* date = localtime( &secs );

    mYear = date->tm_year + 1900;
    mMonth = date->tm_mon;
    mDayOfWeek = date->tm_wday;
    mDayOfMonth = date->tm_mday;
    mHour = date->tm_hour;
    mMinute = date->tm_min;
    mSecond = date->tm_sec;

    struct timeval tv;
    gettimeofday( &tv, NULL );
    mMicrosecond = tv.tv_usec;
  #endif
}
//-----------------------------------------------------------------------------
namespace vl
{
  unsigned long long gStartTime = 0;

  void initStartTime()
  {
    #if defined(VL_PLATFORM_WINDOWS)
      LARGE_INTEGER Frequency;
      LARGE_INTEGER PerformanceCount;
      BOOL has_timer = QueryPerformanceFrequency( &Frequency );
      if (has_timer)
      {
        QueryPerformanceCounter( &PerformanceCount );
        gStartTime = PerformanceCount.QuadPart;
      }
      else
      {
        gStartTime = GetTickCount();
      }
    #elif defined(__GNUG__)
      struct timeval tv;
      gettimeofday( &tv, NULL );
      gStartTime = (unsigned long long)tv.tv_sec * 1000000 + (unsigned long long)tv.tv_usec;
    #endif
  }
}
//-----------------------------------------------------------------------------
//! Seconds passed from an arbitrary origin
//! QueryPerformanceFrequency should be called only once in the application lifetime
Real Time::currentTime()
{
  if (gStartTime == 0)
    initStartTime();

  VL_CHECK(gStartTime);

  #if defined(VL_PLATFORM_WINDOWS)
    // Win32
    LARGE_INTEGER Frequency;
    LARGE_INTEGER PerformanceCount;
    BOOL has_timer = QueryPerformanceFrequency( &Frequency );
    if (has_timer)
    {
      QueryPerformanceCounter( &PerformanceCount );
      return (Real)(PerformanceCount.QuadPart-gStartTime)/Frequency.QuadPart;
    }
    else
    {
      return (GetTickCount()-gStartTime) / 1000.0f;
    }
  #elif defined(__GNUG__)
    struct timeval tv;
    gettimeofday( &tv, NULL );
    return ((unsigned long long)tv.tv_sec * 1000000 + (unsigned long long)tv.tv_usec - gStartTime) * 0.000001f;
  #endif
}
//-----------------------------------------------------------------------------
void Time::sleep(unsigned int milliseconds)
{
  #if defined(VL_PLATFORM_WINDOWS)
    Sleep(milliseconds);
  #elif defined(__GNUG__)
    usleep(milliseconds*1000);
  #endif
}
//-----------------------------------------------------------------------------
<commit_msg>Added use of SetThreadAffinityMask in vl::Time under Win32<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <vlCore/Time.hpp>
#include <ctime>
#include <cmath>

#if defined(VL_PLATFORM_LINUX) || defined(VL_PLATFORM_MACOSX)
  #include <sys/time.h> // gettimeofday()
  #include <unistd.h>   // usleep()
#endif

using namespace vl;

//-----------------------------------------------------------------------------
// Time
//-----------------------------------------------------------------------------
Time::Time()
{
  VL_DEBUG_SET_OBJECT_NAME()

  for(int i=0; i<VL_MAX_TIMERS; ++i)
    mStart[i] = -1;

  #if defined(VL_PLATFORM_WINDOWS)
    SYSTEMTIME local_time;
    GetLocalTime(&local_time);
    mYear = local_time.wYear;
    mMonth = local_time.wMonth;
    mDayOfWeek = local_time.wDayOfWeek;
    mDayOfMonth = local_time.wDay;
    mHour = local_time.wHour;
    mMinute = local_time.wMinute;
    mSecond = local_time.wSecond;
    mMicrosecond = local_time.wMilliseconds * 1000;
  #elif defined(__GNUG__)
    time_t secs;
    ::time(&secs);
    tm* date = localtime( &secs );

    mYear = date->tm_year + 1900;
    mMonth = date->tm_mon;
    mDayOfWeek = date->tm_wday;
    mDayOfMonth = date->tm_mday;
    mHour = date->tm_hour;
    mMinute = date->tm_min;
    mSecond = date->tm_sec;

    struct timeval tv;
    gettimeofday( &tv, NULL );
    mMicrosecond = tv.tv_usec;
  #endif
}
//-----------------------------------------------------------------------------
namespace vl
{
  unsigned long long gStartTime = 0;

  void initStartTime()
  {
    #if defined(VL_PLATFORM_WINDOWS)
      LARGE_INTEGER Frequency;
      LARGE_INTEGER PerformanceCount;
      BOOL has_timer = QueryPerformanceFrequency( &Frequency );
      if (has_timer)
      {
        DWORD_PTR oldmask = ::SetThreadAffinityMask(::GetCurrentThread(), 0);
        QueryPerformanceCounter( &PerformanceCount );
        ::SetThreadAffinityMask(::GetCurrentThread(), oldmask);
        gStartTime = PerformanceCount.QuadPart;
      }
      else
      {
        gStartTime = GetTickCount();
      }
    #elif defined(__GNUG__)
      struct timeval tv;
      gettimeofday( &tv, NULL );
      gStartTime = (unsigned long long)tv.tv_sec * 1000000 + (unsigned long long)tv.tv_usec;
    #endif
  }
}
//-----------------------------------------------------------------------------
//! Seconds passed from an arbitrary origin
//! QueryPerformanceFrequency should be called only once in the application lifetime
Real Time::currentTime()
{
  if (gStartTime == 0)
    initStartTime();

  VL_CHECK(gStartTime);

  #if defined(VL_PLATFORM_WINDOWS)
    // Win32
    LARGE_INTEGER Frequency;
    LARGE_INTEGER PerformanceCount;
    BOOL has_timer = QueryPerformanceFrequency( &Frequency );
    if (has_timer)
    {
      DWORD_PTR oldmask = ::SetThreadAffinityMask(::GetCurrentThread(), 0);
      QueryPerformanceCounter( &PerformanceCount );
      ::SetThreadAffinityMask(::GetCurrentThread(), oldmask);
      return (Real)(PerformanceCount.QuadPart-gStartTime)/Frequency.QuadPart;
    }
    else
    {
      return (GetTickCount()-gStartTime) / 1000.0f;
    }
  #elif defined(__GNUG__)
    struct timeval tv;
    gettimeofday( &tv, NULL );
    return ((unsigned long long)tv.tv_sec * 1000000 + (unsigned long long)tv.tv_usec - gStartTime) * 0.000001f;
  #endif
}
//-----------------------------------------------------------------------------
void Time::sleep(unsigned int milliseconds)
{
  #if defined(VL_PLATFORM_WINDOWS)
    Sleep(milliseconds);
  #elif defined(__GNUG__)
    usleep(milliseconds*1000);
  #endif
}
//-----------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "wallOverlap.h"

#include <cmath> // isfinite

#include "debug.h"
#include "utils/AABB.h" // for debug output svg html
#include "utils/SVG.h"

namespace cura
{

void WallOverlapComputation::findOverlapPoints()
{
    for (unsigned int poly_idx = 0; poly_idx < list_polygons.size(); poly_idx++)
    {
        ListPolygon& poly = list_polygons[poly_idx];
        for (unsigned int poly2_idx = 0; poly2_idx <= poly_idx; poly2_idx++)
        {
            for (ListPolygon::iterator it = poly.begin(); it != poly.end(); ++it)
            {
                ListPolyIt lpi(poly, it);
                if (poly_idx == poly2_idx)
                {
//                     ListPolygon::iterator it2(it);
//                     ++it2;
//                     if (it2 != poly.end())
                    {
                        findOverlapPoints(lpi, poly2_idx, it);
                    }
                }
                else
                {
                    findOverlapPoints(lpi, poly2_idx);
                }
            }
        }
    }
}

void WallOverlapComputation::convertPolygonsToLists(Polygons& polys, ListPolygons& result)
{
    for (PolygonRef poly : polys)
    {
        result.emplace_back();
        for (Point& p : poly)
        {
            result.back().push_back(p);
        }
    }
}

void WallOverlapComputation::convertListPolygonsToPolygons(ListPolygons& list_polygons, Polygons& polygons)
{
    for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
    {
        polygons[poly_idx].clear();
        for (Point& p : list_polygons[poly_idx])
        {
            polygons[poly_idx].add(p);
        }
    }
}

void WallOverlapComputation::findOverlapPoints(ListPolyIt from, unsigned int to_list_poly_idx)
{
    findOverlapPoints(from, to_list_poly_idx, list_polygons[to_list_poly_idx].begin());
}

void WallOverlapComputation::findOverlapPoints(ListPolyIt from_it, unsigned int to_list_poly_idx, const ListPolygon::iterator start)
{
    ListPolygon& to_list_poly = list_polygons[to_list_poly_idx];
    Point& from = from_it.p();
    ListPolygon::iterator last_it = to_list_poly.end();
    last_it--;
    for (ListPolygon::iterator it = start; it != to_list_poly.end(); ++it)
    {
        Point& last_point = *last_it;
        Point& point = *it;

        if (&from_it.poly == &to_list_poly
            && (
                (from_it.it == last_it || from_it.it == it) // we currently consider a linesegment directly connected to [from]
                || (from_it.prev().it == it || from_it.next().it == last_it) // line segment from [last_point] to [point] is connected to line segment of which [from] is the other end
                )
           )
        {
            last_it = it;
            continue;
        }
        Point closest = LinearAlg2D::getClosestOnLineSegment(from, last_point, point);

        int64_t dist2 = vSize2(closest - from);

        if (dist2 > line_width * line_width
            || (&from_it.poly == &to_list_poly
                && dot(from_it.next().p() - from, point - last_point) > 0
                && dot(from - from_it.prev().p(), point - last_point) > 0  ) // line segments are likely connected, because the winding order is in the same general direction
        )
        { // line segment too far away to have overlap
            last_it = it;
            continue;
        }

        int64_t dist = sqrt(dist2);

        if (closest == last_point)
        {
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, last_it), dist);
        }
        else if (closest == point)
        {
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, it), dist);
        }
        else
        {
            ListPolygon::iterator new_it = to_list_poly.insert(it, closest);
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, new_it), dist);
        }

        last_it = it;
    }

}

bool WallOverlapComputation::addOverlapPoint(ListPolyIt from, ListPolyIt to, int64_t dist)
{
    WallOverlapPointLink link(from, to);
    WallOverlapPointLinkAttributes attr(dist, false);
    std::pair<WallOverlapPointLinks::iterator, bool> result =
        overlap_point_links.emplace(link, attr);

    if (! result.second)
    {
//         DEBUG_PRINTLN("couldn't emplace in overlap_point_links! : ");
        result.first->second = attr;
    }

    WallOverlapPointLinks::iterator it = result.first;
    addToPoint2LinkMap(*it->first.a.it, it);
    addToPoint2LinkMap(*it->first.b.it, it);

    return result.second;
}

bool WallOverlapComputation::addOverlapPoint_endings(ListPolyIt from, ListPolyIt to, int64_t dist)
{
    WallOverlapPointLink link(from, to);
    WallOverlapPointLinkAttributes attr(dist, false);
    std::pair<WallOverlapPointLinks::iterator, bool> result =
        overlap_point_links_endings.emplace(link, attr);

    if (! result.second)
    {
//         DEBUG_PRINTLN("couldn't emplace in overlap_point_links! : ");
        result.first->second = attr;
    }

    WallOverlapPointLinks::iterator it = result.first;
    addToPoint2LinkMap(*it->first.a.it, it);
    addToPoint2LinkMap(*it->first.b.it, it);

    return result.second;
}

void WallOverlapComputation::addOverlapEndings()
{
    for (std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> link_pair : overlap_point_links)
    {

        if (link_pair.second.dist == line_width)
        { // its ending itself
            continue;
        }
        WallOverlapPointLink& link = link_pair.first;
        const ListPolyIt& a_1 = link.a;
        const ListPolyIt& b_1 = link.b;
        // an overlap segment can be an ending in two directions
        {
            ListPolyIt a_2 = a_1.next();
            ListPolyIt b_2 = b_1.prev();
            addOverlapEnding(link_pair, a_2, b_2, a_2, b_1);
        }
        {
            ListPolyIt a_2 = a_1.prev();
            ListPolyIt b_2 = b_1.next();
            addOverlapEnding(link_pair, a_2, b_2, a_1, b_2);
        }
    }
}

void WallOverlapComputation::addOverlapEnding(std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> link_pair, const ListPolyIt& a2_it, const ListPolyIt& b2_it, const ListPolyIt& a_after_middle, const ListPolyIt& b_after_middle)
{
    WallOverlapPointLink& link = link_pair.first;
    Point& a1 = link.a.p();
    Point& a2 = a2_it.p();
    Point& b1 = link.b.p();
    Point& b2 = b2_it.p();
    Point a = a2-a1;
    Point b = b2-b1;

    if (point_to_link.find(a2_it.p()) == point_to_link.end()
        || point_to_link.find(b2_it.p()) == point_to_link.end())
    {
        int64_t dist = overlapEndingDistance(a1, a2, b1, b2, link_pair.second.dist);
        if (dist < 0) { return; }
        int64_t a_length2 = vSize2(a);
        int64_t b_length2 = vSize2(b);
        if (dist*dist > std::min(a_length2, b_length2) )
        { // TODO remove this /\ case if error below is never shown
//             DEBUG_PRINTLN("Next point should have been linked already!!");
            dist = std::sqrt(std::min(a_length2, b_length2));
            if (a_length2 < b_length2)
            {
                Point b_p = b1 + normal(b, dist);
                ListPolygon::iterator new_b = link.b.poly.insert(b_after_middle.it, b_p);
                addOverlapPoint_endings(a2_it, ListPolyIt(link.b.poly, new_b), line_width);
            }
            else if (b_length2 < a_length2)
            {
                Point a_p = a1 + normal(a, dist);
                ListPolygon::iterator new_a = link.a.poly.insert(a_after_middle.it, a_p);
                addOverlapPoint_endings(ListPolyIt(link.a.poly, new_a), b2_it, line_width);
            }
            else // equal
            {
                addOverlapPoint_endings(a2_it, b2_it, line_width);
            }
        }
        if (dist > 0)
        {
            Point a_p = a1 + normal(a, dist);
            ListPolygon::iterator new_a = link.a.poly.insert(a_after_middle.it, a_p);
            Point b_p = b1 + normal(b, dist);
            ListPolygon::iterator new_b = link.b.poly.insert(b_after_middle.it, b_p);
            addOverlapPoint_endings(ListPolyIt(link.a.poly, new_a), ListPolyIt(link.b.poly, new_b), line_width);
        }
        else if (dist == 0)
        {
            addOverlapPoint_endings(link.a, link.b, line_width);
        }
    }
}

int64_t WallOverlapComputation::overlapEndingDistance(Point& a1, Point& a2, Point& b1, Point& b2, int a1b1_dist)
{
    int overlap = line_width - a1b1_dist;
    Point a = a2-a1;
    Point b = b2-b1;
    double cos_angle = INT2MM2(dot(a, b)) / vSizeMM(a) / vSizeMM(b);
    // result == .5*overlap / tan(.5*angle) == .5*overlap / tan(.5*acos(cos_angle))
    // [wolfram alpha] == 0.5*overlap * sqrt(cos_angle+1)/sqrt(1-cos_angle)
    // [assuming positive x] == 0.5*overlap / sqrt( 2 / (cos_angle + 1) - 1 )
    if (cos_angle <= 0
        || ! std::isfinite(cos_angle) )
    {
        return -1; // line_width / 2;
    }
    else if (cos_angle > .9999) // values near 1 can lead too large numbers  for 1/x
    {
        return std::min(vSize(b), vSize(a));
    }
    else
    {
        int64_t dist = overlap * double ( 1.0 / (2.0 * sqrt(2.0 / (cos_angle+1.0) - 1.0)) );
        return dist;
    }

}

void WallOverlapComputation::addSharpCorners()
{

}

void WallOverlapComputation::addToPoint2LinkMap(Point p, WallOverlapPointLinks::iterator it)
{
    point_to_link.emplace(p, it);
    // TODO: what to do if the map already contained a link? > three-way overlap
}

float WallOverlapComputation::getFlow(Point& from, Point& to)
{
    Point2Link::iterator from_link_pair = point_to_link.find(from);
    if (from_link_pair == point_to_link.end()) { return 1; }
    WallOverlapPointLinks::iterator from_link = from_link_pair->second;
    if (!from_link->second.passed)// || !to_link->second.passed)
    {
        from_link->second.passed = true;
//         to_link->second.passed = true;
        return 1;
    }
    from_link->second.passed = true;

    Point2Link::iterator to_link_pair = point_to_link.find(to);
    if (to_link_pair == point_to_link.end()) { return 1; }
    WallOverlapPointLinks::iterator to_link = to_link_pair->second;
//     to_link->second = true;

    // both points have already been passed

    float avg_link_dist = 0.5 * ( INT2MM(from_link->second.dist) + INT2MM(to_link->second.dist) );

    float ratio = avg_link_dist / INT2MM(line_width);

    if (ratio > 1.0) { return 1.0; }

    return ratio;
}

void WallOverlapComputation::debugCheck()
{
    for (std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> pair : overlap_point_links)
    {
        if (std::abs(vSize( pair.first.a.p() - pair.first.b.p()) - pair.second.dist) > 10)
            DEBUG_PRINTLN(vSize( pair.first.a.p() - pair.first.b.p())<<" != " << pair.second.dist);

    }
}

void WallOverlapComputation::wallOverlaps2HTML(const char* filename)
{
    AABB aabb(polygons);

    SVG svg(filename, aabb);

    svg.writeAreas(polygons);
    /*
    for(PolygonsPart part : polygons.splitIntoParts())
    {
        for (unsigned int j = 0; j < part.size(); j++)
        {
            fprintf(out, "<polygon points=\"");
            for(Point& p : part[j])
            {
                Point pf = transform(p);
                fprintf(out, "%lli,%lli ", pf.Y, pf.X);
            }
            if (j == 0)
                fprintf(out, "\" style=\"fill:gray; stroke:black;stroke-width:1\" />\n");
            else
                fprintf(out, "\" style=\"fill:white; stroke:black;stroke-width:1\" />\n");
        }
    }*/

    for (ListPolygon poly : list_polygons)
    {
        for (Point& p : poly)
        {
            svg.writePoint(p, true);
        }
    }

    for (std::pair<WallOverlapPointLink , WallOverlapPointLinkAttributes> link_pair : overlap_point_links)
    {
        WallOverlapPointLink& link = link_pair.first;
        Point a = svg.transform(link.a.p());
        Point b = svg.transform(link.b.p());
        svg.printf("<line x1=\"%lli\" y1=\"%lli\" x2=\"%lli\" y2=\"%lli\" style=\"stroke:rgb(%d,%d,0);stroke-width:1\" />", a.Y, a.X, b.Y, b.X, link_pair.second.dist == line_width? 0 : 255, link_pair.second.dist==line_width? 255 : 0);
    }

    for (std::pair<WallOverlapPointLink , WallOverlapPointLinkAttributes> link_pair : overlap_point_links_endings)
    {
        WallOverlapPointLink& link = link_pair.first;
        Point a = svg.transform(link.a.p());
        Point b = svg.transform(link.b.p());
        svg.printf("<line x1=\"%lli\" y1=\"%lli\" x2=\"%lli\" y2=\"%lli\" style=\"stroke:rgb(%d,%d,0);stroke-width:1\" />", a.Y, a.X, b.Y, b.X, link_pair.second.dist == line_width? 0 : 255, link_pair.second.dist==line_width? 255 : 0);
    }
}

}//namespace cura
<commit_msg>lil debug fix for WallOverlapComputation<commit_after>#include "wallOverlap.h"

#include <cmath> // isfinite

#include "debug.h"
#include "utils/AABB.h" // for debug output svg html
#include "utils/SVG.h"

namespace cura
{

void WallOverlapComputation::findOverlapPoints()
{
    for (unsigned int poly_idx = 0; poly_idx < list_polygons.size(); poly_idx++)
    {
        ListPolygon& poly = list_polygons[poly_idx];
        for (unsigned int poly2_idx = 0; poly2_idx <= poly_idx; poly2_idx++)
        {
            for (ListPolygon::iterator it = poly.begin(); it != poly.end(); ++it)
            {
                ListPolyIt lpi(poly, it);
                if (poly_idx == poly2_idx)
                {
//                     ListPolygon::iterator it2(it);
//                     ++it2;
//                     if (it2 != poly.end())
                    {
                        findOverlapPoints(lpi, poly2_idx, it);
                    }
                }
                else
                {
                    findOverlapPoints(lpi, poly2_idx);
                }
            }
        }
    }
}

void WallOverlapComputation::convertPolygonsToLists(Polygons& polys, ListPolygons& result)
{
    for (PolygonRef poly : polys)
    {
        result.emplace_back();
        for (Point& p : poly)
        {
            result.back().push_back(p);
        }
    }
}

void WallOverlapComputation::convertListPolygonsToPolygons(ListPolygons& list_polygons, Polygons& polygons)
{
    for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
    {
        polygons[poly_idx].clear();
        for (Point& p : list_polygons[poly_idx])
        {
            polygons[poly_idx].add(p);
        }
    }
}

void WallOverlapComputation::findOverlapPoints(ListPolyIt from, unsigned int to_list_poly_idx)
{
    findOverlapPoints(from, to_list_poly_idx, list_polygons[to_list_poly_idx].begin());
}

void WallOverlapComputation::findOverlapPoints(ListPolyIt from_it, unsigned int to_list_poly_idx, const ListPolygon::iterator start)
{
    ListPolygon& to_list_poly = list_polygons[to_list_poly_idx];
    Point& from = from_it.p();
    ListPolygon::iterator last_it = to_list_poly.end();
    last_it--;
    for (ListPolygon::iterator it = start; it != to_list_poly.end(); ++it)
    {
        Point& last_point = *last_it;
        Point& point = *it;

        if (&from_it.poly == &to_list_poly
            && (
                (from_it.it == last_it || from_it.it == it) // we currently consider a linesegment directly connected to [from]
                || (from_it.prev().it == it || from_it.next().it == last_it) // line segment from [last_point] to [point] is connected to line segment of which [from] is the other end
                )
           )
        {
            last_it = it;
            continue;
        }
        Point closest = LinearAlg2D::getClosestOnLineSegment(from, last_point, point);

        int64_t dist2 = vSize2(closest - from);

        if (dist2 > line_width * line_width
            || (&from_it.poly == &to_list_poly
                && dot(from_it.next().p() - from, point - last_point) > 0
                && dot(from - from_it.prev().p(), point - last_point) > 0  ) // line segments are likely connected, because the winding order is in the same general direction
        )
        { // line segment too far away to have overlap
            last_it = it;
            continue;
        }

        int64_t dist = sqrt(dist2);

        if (closest == last_point)
        {
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, last_it), dist);
        }
        else if (closest == point)
        {
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, it), dist);
        }
        else
        {
            ListPolygon::iterator new_it = to_list_poly.insert(it, closest);
            addOverlapPoint(from_it, ListPolyIt(to_list_poly, new_it), dist);
        }

        last_it = it;
    }

}

bool WallOverlapComputation::addOverlapPoint(ListPolyIt from, ListPolyIt to, int64_t dist)
{
    WallOverlapPointLink link(from, to);
    WallOverlapPointLinkAttributes attr(dist, false);
    std::pair<WallOverlapPointLinks::iterator, bool> result =
        overlap_point_links.emplace(link, attr);

    if (! result.second)
    {
//         DEBUG_PRINTLN("couldn't emplace in overlap_point_links! : ");
        result.first->second = attr;
    }

    WallOverlapPointLinks::iterator it = result.first;
    addToPoint2LinkMap(*it->first.a.it, it);
    addToPoint2LinkMap(*it->first.b.it, it);

    return result.second;
}

bool WallOverlapComputation::addOverlapPoint_endings(ListPolyIt from, ListPolyIt to, int64_t dist)
{
    WallOverlapPointLink link(from, to);
    WallOverlapPointLinkAttributes attr(dist, false);
    std::pair<WallOverlapPointLinks::iterator, bool> result =
        overlap_point_links_endings.emplace(link, attr);

    if (! result.second)
    {
//         DEBUG_PRINTLN("couldn't emplace in overlap_point_links! : ");
        result.first->second = attr;
    }

    WallOverlapPointLinks::iterator it = result.first;
    addToPoint2LinkMap(*it->first.a.it, it);
    addToPoint2LinkMap(*it->first.b.it, it);

    return result.second;
}

void WallOverlapComputation::addOverlapEndings()
{
    for (std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> link_pair : overlap_point_links)
    {

        if (link_pair.second.dist == line_width)
        { // its ending itself
            continue;
        }
        WallOverlapPointLink& link = link_pair.first;
        const ListPolyIt& a_1 = link.a;
        const ListPolyIt& b_1 = link.b;
        // an overlap segment can be an ending in two directions
        {
            ListPolyIt a_2 = a_1.next();
            ListPolyIt b_2 = b_1.prev();
            addOverlapEnding(link_pair, a_2, b_2, a_2, b_1);
        }
        {
            ListPolyIt a_2 = a_1.prev();
            ListPolyIt b_2 = b_1.next();
            addOverlapEnding(link_pair, a_2, b_2, a_1, b_2);
        }
    }
}

void WallOverlapComputation::addOverlapEnding(std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> link_pair, const ListPolyIt& a2_it, const ListPolyIt& b2_it, const ListPolyIt& a_after_middle, const ListPolyIt& b_after_middle)
{
    WallOverlapPointLink& link = link_pair.first;
    Point& a1 = link.a.p();
    Point& a2 = a2_it.p();
    Point& b1 = link.b.p();
    Point& b2 = b2_it.p();
    Point a = a2-a1;
    Point b = b2-b1;

    if (point_to_link.find(a2_it.p()) == point_to_link.end()
        || point_to_link.find(b2_it.p()) == point_to_link.end())
    {
        int64_t dist = overlapEndingDistance(a1, a2, b1, b2, link_pair.second.dist);
        if (dist < 0) { return; }
        int64_t a_length2 = vSize2(a);
        int64_t b_length2 = vSize2(b);
        if (dist*dist > std::min(a_length2, b_length2) )
        { // TODO remove this /\ case if error below is never shown
//             DEBUG_PRINTLN("Next point should have been linked already!!");
            dist = std::sqrt(std::min(a_length2, b_length2));
            if (a_length2 < b_length2)
            {
                Point b_p = b1 + normal(b, dist);
                ListPolygon::iterator new_b = link.b.poly.insert(b_after_middle.it, b_p);
                addOverlapPoint_endings(a2_it, ListPolyIt(link.b.poly, new_b), line_width);
            }
            else if (b_length2 < a_length2)
            {
                Point a_p = a1 + normal(a, dist);
                ListPolygon::iterator new_a = link.a.poly.insert(a_after_middle.it, a_p);
                addOverlapPoint_endings(ListPolyIt(link.a.poly, new_a), b2_it, line_width);
            }
            else // equal
            {
                addOverlapPoint_endings(a2_it, b2_it, line_width);
            }
        }
        if (dist > 0)
        {
            Point a_p = a1 + normal(a, dist);
            ListPolygon::iterator new_a = link.a.poly.insert(a_after_middle.it, a_p);
            Point b_p = b1 + normal(b, dist);
            ListPolygon::iterator new_b = link.b.poly.insert(b_after_middle.it, b_p);
            addOverlapPoint_endings(ListPolyIt(link.a.poly, new_a), ListPolyIt(link.b.poly, new_b), line_width);
        }
        else if (dist == 0)
        {
            addOverlapPoint_endings(link.a, link.b, line_width);
        }
    }
}

int64_t WallOverlapComputation::overlapEndingDistance(Point& a1, Point& a2, Point& b1, Point& b2, int a1b1_dist)
{
    int overlap = line_width - a1b1_dist;
    Point a = a2-a1;
    Point b = b2-b1;
    double cos_angle = INT2MM2(dot(a, b)) / vSizeMM(a) / vSizeMM(b);
    // result == .5*overlap / tan(.5*angle) == .5*overlap / tan(.5*acos(cos_angle))
    // [wolfram alpha] == 0.5*overlap * sqrt(cos_angle+1)/sqrt(1-cos_angle)
    // [assuming positive x] == 0.5*overlap / sqrt( 2 / (cos_angle + 1) - 1 )
    if (cos_angle <= 0
        || ! std::isfinite(cos_angle) )
    {
        return -1; // line_width / 2;
    }
    else if (cos_angle > .9999) // values near 1 can lead too large numbers  for 1/x
    {
        return std::min(vSize(b), vSize(a));
    }
    else
    {
        int64_t dist = overlap * double ( 1.0 / (2.0 * sqrt(2.0 / (cos_angle+1.0) - 1.0)) );
        return dist;
    }

}

void WallOverlapComputation::addSharpCorners()
{

}

void WallOverlapComputation::addToPoint2LinkMap(Point p, WallOverlapPointLinks::iterator it)
{
    point_to_link.emplace(p, it);
    // TODO: what to do if the map already contained a link? > three-way overlap
}

float WallOverlapComputation::getFlow(Point& from, Point& to)
{
    Point2Link::iterator from_link_pair = point_to_link.find(from);
    if (from_link_pair == point_to_link.end()) { return 1; }
    WallOverlapPointLinks::iterator from_link = from_link_pair->second;
    if (!from_link->second.passed)// || !to_link->second.passed)
    {
        from_link->second.passed = true;
//         to_link->second.passed = true;
        return 1;
    }
    from_link->second.passed = true;

    Point2Link::iterator to_link_pair = point_to_link.find(to);
    if (to_link_pair == point_to_link.end()) { return 1; }
    WallOverlapPointLinks::iterator to_link = to_link_pair->second;
//     to_link->second = true;

    // both points have already been passed

    float avg_link_dist = 0.5 * ( INT2MM(from_link->second.dist) + INT2MM(to_link->second.dist) );

    float ratio = avg_link_dist / INT2MM(line_width);

    if (ratio > 1.0) { return 1.0; }

    return ratio;
}

void WallOverlapComputation::debugCheck()
{
    for (std::pair<WallOverlapPointLink, WallOverlapPointLinkAttributes> pair : overlap_point_links)
    {
        if (std::abs(vSize( pair.first.a.p() - pair.first.b.p()) - pair.second.dist) > 10)
            DEBUG_PRINTLN(vSize( pair.first.a.p() - pair.first.b.p())<<" != " << pair.second.dist);

    }
}

void WallOverlapComputation::wallOverlaps2HTML(const char* filename)
{
    AABB aabb(polygons);

    SVG svg(filename, aabb, Point(1024 * 2, 1024 * 2));

    svg.writeAreas(polygons);
    /*
    for(PolygonsPart part : polygons.splitIntoParts())
    {
        for (unsigned int j = 0; j < part.size(); j++)
        {
            fprintf(out, "<polygon points=\"");
            for(Point& p : part[j])
            {
                Point pf = transform(p);
                fprintf(out, "%lli,%lli ", pf.Y, pf.X);
            }
            if (j == 0)
                fprintf(out, "\" style=\"fill:gray; stroke:black;stroke-width:1\" />\n");
            else
                fprintf(out, "\" style=\"fill:white; stroke:black;stroke-width:1\" />\n");
        }
    }*/

    for (ListPolygon poly : list_polygons)
    {
        for (Point& p : poly)
        {
            svg.writePoint(p, true);
        }
    }

    for (std::pair<WallOverlapPointLink , WallOverlapPointLinkAttributes> link_pair : overlap_point_links)
    {
        WallOverlapPointLink& link = link_pair.first;
        Point a = svg.transform(link.a.p());
        Point b = svg.transform(link.b.p());
        svg.printf("<line x1=\"%lli\" y1=\"%lli\" x2=\"%lli\" y2=\"%lli\" style=\"stroke:rgb(%d,%d,0);stroke-width:1\" />", a.X, a.Y, b.X, b.Y, link_pair.second.dist == line_width? 0 : 255, link_pair.second.dist==line_width? 255 : 0);
    }

    for (std::pair<WallOverlapPointLink , WallOverlapPointLinkAttributes> link_pair : overlap_point_links_endings)
    {
        WallOverlapPointLink& link = link_pair.first;
        Point a = svg.transform(link.a.p());
        Point b = svg.transform(link.b.p());
        svg.printf("<line x1=\"%lli\" y1=\"%lli\" x2=\"%lli\" y2=\"%lli\" style=\"stroke:rgb(%d,%d,0);stroke-width:1\" />", a.X, a.Y, b.X, b.Y, link_pair.second.dist == line_width? 0 : 255, link_pair.second.dist==line_width? 255 : 0);
    }
}

}//namespace cura
<|endoftext|>


<commit_before>#pragma comment(lib, "Shlwapi.lib")

#pragma warning(disable:4996)

#include "Observer.h"

#include <cstdio>
#include <cstdlib>
#include <tchar.h>
#include <string>
#include <utility>
#include <functional>
#include <concurrent_unordered_map.h>

#include <Windows.h>
#include <Shlwapi.h>
#include "bass.h"
#include "bass_fx.h"
#include "Hooker.h"
#include "Server.h"

#define AUDIO_FILE_INFO_TOKEN "AudioFilename:"

std::shared_ptr<Observer> Observer::instance;
std::once_flag Observer::once_flag;

BOOL WINAPI Observer::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
    if (!instance->hookerReadFile.GetFunction()(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped))
    {
        return FALSE;
    }

    TCHAR szFilePath[MAX_PATH];
    DWORD nFilePathLength = GetFinalPathNameByHandle(hFile, szFilePath, MAX_PATH, VOLUME_NAME_DOS);
    //                  1: \\?\D:\Games\osu!\...
    DWORD dwFilePosition = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - (*lpNumberOfBytesRead);
    //  д  Ʈ ̰ պκ оٸ    :
    // AudioFilename պκп  /  ڵ       !
    if (wcsncmp(L".osu", &szFilePath[nFilePathLength - 4], 4) == 0 && dwFilePosition == 0)
    {
        // strtok ҽ ϹǷ ϴ
        // .osu  UTF-8(Multibyte) ڵ

		/* ٸ strtok ߶󳻼 AudioFilename:  ã. */
        char *buffer = strdup((const char*)(lpBuffer));

		for (char *line = strtok(buffer, "\n"); line != NULL; line = strtok(NULL, "\n"))
        {
            if (strnicmp(line, AUDIO_FILE_INFO_TOKEN, 14) != 0)
            {
                continue;
            }

            // AudioFilename
            TCHAR szAudioFileName[MAX_PATH];

            mbstowcs(szAudioFileName, &line[14], MAX_PATH);
            StrTrimW(szAudioFileName, L" \r");

            TCHAR szAudioFilePath[MAX_PATH];

			/* պκ ̻ ڸ ϱ 4° ں . */
            wcscpy(szAudioFilePath, &szFilePath[4]);
            PathRemoveFileSpecW(szAudioFilePath);
            PathCombineW(szAudioFilePath, szAudioFilePath, szAudioFileName);

			EnterCriticalSection(&instance->hCritiaclSection);

			instance->currentPlaying.audioPath = tstring(szAudioFilePath);
			/* պκ ̻ ڸ ϱ 4° ں . */
			instance->currentPlaying.beatmapPath = (tstring(&szFilePath[4]));

			LeaveCriticalSection(&instance->hCritiaclSection);

            break;
        }

        free(buffer);
    }
    return TRUE;
}

inline long long GetCurrentSysTime()
{
    long long t;
    GetSystemTimeAsFileTime(reinterpret_cast<LPFILETIME>(&t));
    return t;
}

BOOL WINAPI Observer::BASS_ChannelPlay(DWORD handle, BOOL restart)
{
    if (!instance->hookerBASS_ChannelPlay.GetFunction()(handle, restart))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTimePos = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        float tempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        instance->SendInfomation(GetCurrentSysTime(), currentTimePos, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetPosition(DWORD handle, QWORD pos, DWORD mode)
{
    if (!instance->hookerBASS_ChannelSetPosition.GetFunction()(handle, pos, mode))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, pos);
        float CurrentTempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &CurrentTempo);
        // !! pos   ,
        // ϸ BASS_ChannelPlay  Լ ȣǰ,
        // BASS_ChannelIsActive  BASS_ACTIVE_PAUSED.
        if (BASS_ChannelIsActive(handle) == BASS_ACTIVE_PAUSED)
        {
            CurrentTempo = -100;
        }

        instance->SendInfomation(GetCurrentSysTime(), currentTime, CurrentTempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetAttribute(DWORD handle, DWORD attrib, float value)
{
    if (!instance->hookerBASS_ChannelSetAttribute.GetFunction()(handle, attrib, value))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if ((info.ctype & BASS_CTYPE_STREAM) && attrib == BASS_ATTRIB_TEMPO)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        instance->SendInfomation(GetCurrentSysTime(), currentTime, value);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelPause(DWORD handle)
{
    if (!instance->hookerBASS_ChannelPause.GetFunction()(handle))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        instance->SendInfomation(GetCurrentSysTime(), currentTime, -100);
    }
    return TRUE;
}

void Observer::SendInfomation(long long calledAt, double currentTime, float tempo)
{
    TCHAR message[Server::nMessageLength];

	/* Get Current Playing */
    EnterCriticalSection(&instance->hCritiaclSection);
    swprintf(message, L"%llx|%s|%lf|%f|%s\n",
		calledAt,
		instance->currentPlaying.audioPath.c_str(),
		currentTime,
		tempo,
		instance->currentPlaying.beatmapPath.c_str());
	LeaveCriticalSection(&instance->hCritiaclSection);

    Server::GetInstance()->PushMessage(message);
}

void Observer::Initalize()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

    this->hookerReadFile.Hook();

    this->hookerBASS_ChannelPlay.Hook();
    this->hookerBASS_ChannelSetPosition.Hook();
    this->hookerBASS_ChannelSetAttribute.Hook();
    this->hookerBASS_ChannelPause.Hook();

	DetourTransactionCommit();
}

void Observer::Release()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

    this->hookerBASS_ChannelPause.Unhook();
    this->hookerBASS_ChannelSetAttribute.Unhook();
    this->hookerBASS_ChannelSetPosition.Unhook();
    this->hookerBASS_ChannelPlay.Unhook();

    this->hookerReadFile.Unhook();

	DetourTransactionCommit();
}
<commit_msg>필요없는 헤더파일 제거<commit_after>#pragma comment(lib, "Shlwapi.lib")

#pragma warning(disable:4996)

#include "Observer.h"

#include <cstdio>
#include <tchar.h>
#include <string>

#include <Windows.h>
#include <Shlwapi.h>
#include "bass.h"
#include "bass_fx.h"
#include "Hooker.h"
#include "Server.h"

#define AUDIO_FILE_INFO_TOKEN "AudioFilename:"

std::shared_ptr<Observer> Observer::instance;
std::once_flag Observer::once_flag;

BOOL WINAPI Observer::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
    if (!instance->hookerReadFile.GetFunction()(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped))
    {
        return FALSE;
    }

    TCHAR szFilePath[MAX_PATH];
    DWORD nFilePathLength = GetFinalPathNameByHandle(hFile, szFilePath, MAX_PATH, VOLUME_NAME_DOS);
    //                  1: \\?\D:\Games\osu!\...
    DWORD dwFilePosition = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - (*lpNumberOfBytesRead);
    //  д  Ʈ ̰ պκ оٸ    :
    // AudioFilename պκп  /  ڵ       !
    if (wcsncmp(L".osu", &szFilePath[nFilePathLength - 4], 4) == 0 && dwFilePosition == 0)
    {
        // strtok ҽ ϹǷ ϴ
        // .osu  UTF-8(Multibyte) ڵ

		/* ٸ strtok ߶󳻼 AudioFilename:  ã. */
        char *buffer = strdup((const char*)(lpBuffer));

		for (char *line = strtok(buffer, "\n"); line != NULL; line = strtok(NULL, "\n"))
        {
            if (strnicmp(line, AUDIO_FILE_INFO_TOKEN, 14) != 0)
            {
                continue;
            }

            // AudioFilename
            TCHAR szAudioFileName[MAX_PATH];

            mbstowcs(szAudioFileName, &line[14], MAX_PATH);
            StrTrimW(szAudioFileName, L" \r");

            TCHAR szAudioFilePath[MAX_PATH];

			/* պκ ̻ ڸ ϱ 4° ں . */
            wcscpy(szAudioFilePath, &szFilePath[4]);
            PathRemoveFileSpecW(szAudioFilePath);
            PathCombineW(szAudioFilePath, szAudioFilePath, szAudioFileName);

			EnterCriticalSection(&instance->hCritiaclSection);

			instance->currentPlaying.audioPath = tstring(szAudioFilePath);
			/* պκ ̻ ڸ ϱ 4° ں . */
			instance->currentPlaying.beatmapPath = (tstring(&szFilePath[4]));

			LeaveCriticalSection(&instance->hCritiaclSection);

            break;
        }

        free(buffer);
    }
    return TRUE;
}

inline long long GetCurrentSysTime()
{
    long long t;
    GetSystemTimeAsFileTime(reinterpret_cast<LPFILETIME>(&t));
    return t;
}

BOOL WINAPI Observer::BASS_ChannelPlay(DWORD handle, BOOL restart)
{
    if (!instance->hookerBASS_ChannelPlay.GetFunction()(handle, restart))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTimePos = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        float tempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        instance->SendInfomation(GetCurrentSysTime(), currentTimePos, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetPosition(DWORD handle, QWORD pos, DWORD mode)
{
    if (!instance->hookerBASS_ChannelSetPosition.GetFunction()(handle, pos, mode))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, pos);
        float CurrentTempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &CurrentTempo);
        // !! pos   ,
        // ϸ BASS_ChannelPlay  Լ ȣǰ,
        // BASS_ChannelIsActive  BASS_ACTIVE_PAUSED.
        if (BASS_ChannelIsActive(handle) == BASS_ACTIVE_PAUSED)
        {
            CurrentTempo = -100;
        }

        instance->SendInfomation(GetCurrentSysTime(), currentTime, CurrentTempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetAttribute(DWORD handle, DWORD attrib, float value)
{
    if (!instance->hookerBASS_ChannelSetAttribute.GetFunction()(handle, attrib, value))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);

    if ((info.ctype & BASS_CTYPE_STREAM) && attrib == BASS_ATTRIB_TEMPO)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        instance->SendInfomation(GetCurrentSysTime(), currentTime, value);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelPause(DWORD handle)
{
    if (!instance->hookerBASS_ChannelPause.GetFunction()(handle))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        instance->SendInfomation(GetCurrentSysTime(), currentTime, -100);
    }
    return TRUE;
}

void Observer::SendInfomation(long long calledAt, double currentTime, float tempo)
{
    TCHAR message[Server::nMessageLength];

	/* Get Current Playing */
    EnterCriticalSection(&instance->hCritiaclSection);
    swprintf(message, L"%llx|%s|%lf|%f|%s\n",
		calledAt,
		instance->currentPlaying.audioPath.c_str(),
		currentTime,
		tempo,
		instance->currentPlaying.beatmapPath.c_str());
	LeaveCriticalSection(&instance->hCritiaclSection);

    Server::GetInstance()->PushMessage(message);
}

void Observer::Initalize()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

    this->hookerReadFile.Hook();

    this->hookerBASS_ChannelPlay.Hook();
    this->hookerBASS_ChannelSetPosition.Hook();
    this->hookerBASS_ChannelSetAttribute.Hook();
    this->hookerBASS_ChannelPause.Hook();

	DetourTransactionCommit();
}

void Observer::Release()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

    this->hookerBASS_ChannelPause.Unhook();
    this->hookerBASS_ChannelSetAttribute.Unhook();
    this->hookerBASS_ChannelSetPosition.Unhook();
    this->hookerBASS_ChannelPlay.Unhook();

    this->hookerReadFile.Unhook();

	DetourTransactionCommit();
}
<|endoftext|>