<commit_before>#include "styleContext.h"
#include "platform.h"
#include "builders.h"
#include "scene/scene.h"
#include "data/propertyItem.h"

#define DUMP(...) //do { logMsg(__VA_ARGS__); duk_dump_context_stderr(m_ctx); } while(0)

namespace Tangram {

const static char DATA_ID[] = "\xff""\xff""data";
const static char ATTR_ID[] = "\xff""\xff""attr";
const static char FUNC_ID[] = "\xff""\xff""fns";

StyleContext::StyleContext() {
    m_ctx = duk_create_heap_default();

    // add empty feature_object
    duk_push_object(m_ctx);

    // assign instance to feature_object
    duk_push_pointer(m_ctx, this);
    if (!duk_put_prop_string(m_ctx, -2, DATA_ID)) {
        LOGE("Ctx not assigned");
    }

    // put object in global scope
    if (!duk_put_global_string(m_ctx, "feature")) {
        LOGE("Feature not assigned");
    }

    DUMP("init\n");
}

StyleContext::~StyleContext() {
    duk_destroy_heap(m_ctx);
}

void StyleContext::initFunctions(const Scene& _scene) {

    if (_scene.id == m_sceneId) {
        return;
    }
    m_sceneId = _scene.id;

    auto arr_idx = duk_push_array(m_ctx);
    int id = 0;

    for (auto& function : _scene.functions()) {
        LOGD("compile '%s'", function.c_str());
        duk_push_string(m_ctx, function.c_str());
        duk_push_string(m_ctx, "");

        if (duk_pcompile(m_ctx, DUK_COMPILE_FUNCTION) == 0) {
            duk_put_prop_index(m_ctx, arr_idx, id);
        } else {
            LOGE("Compile failed: %s", duk_safe_to_string(m_ctx, -1));
            duk_pop(m_ctx);
        }
        id++;
    }

    if (!duk_put_global_string(m_ctx, FUNC_ID)) {
        LOGE("'fns' object not set");
    }

    DUMP("setScene - %d functions\n", id);
}

void StyleContext::setFeature(const Feature& _feature) {
    m_feature = &_feature;

    for (auto& item : _feature.props.items()) {
        addAccessor(item.key);
    }
}

void StyleContext::setGlobalZoom(float _zoom) {
    static const std::string _key("$zoom");
    if (_zoom != m_globalZoom) {
        setGlobal(_key, _zoom);
    }
}

void StyleContext::setGlobal(const std::string& _key, const Value& _val) {
    Value& entry = m_globals[_key];
    if (entry == _val) { return; }

    entry = _val;

    if (_val.is<float>()) {
        duk_push_number(m_ctx, _val.get<float>());
        duk_put_global_string(m_ctx, _key.c_str());

        if (_key == "$zoom") { m_globalZoom = _val.get<float>(); }

    } else if (_val.is<std::string>()) {
        duk_push_string(m_ctx, _val.get<std::string>().c_str());
        duk_put_global_string(m_ctx, _key.c_str());
    }
}

const Value& StyleContext::getGlobal(const std::string& _key) const {

    const static Value NOT_FOUND(none_type{});

    auto it = m_globals.find(_key);
    if (it != m_globals.end()) {
        return it->second;
    }
    return NOT_FOUND;
}

void StyleContext::clear() {
    m_feature = nullptr;
}

bool StyleContext::addFunction(const std::string& _name, const std::string& _func) {

    duk_push_string(m_ctx, _func.c_str());
    duk_push_string(m_ctx, _name.c_str());

    if (duk_pcompile(m_ctx, DUK_COMPILE_FUNCTION) != 0) {
        LOGE("Compile failed: %s", duk_safe_to_string(m_ctx, -1));
        return false;
    }

    // Put function in global scope
    duk_put_global_string(m_ctx, _name.c_str());

    DUMP("addFunction\n");
    return true;
}

bool StyleContext::evalFilter(FunctionID _id) const {
    if (!duk_get_global_string(m_ctx, FUNC_ID)) {
        LOGE("EvalFilterFn - functions not initialized");
        return false;
    }

    if (!duk_get_prop_index(m_ctx, -1, _id)) {
        LOGE("EvalFilterFn - function %d not set", _id);
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
    }

    bool result = false;

    if (duk_is_boolean(m_ctx, -1)) {
        result = duk_get_boolean(m_ctx, -1);
    }

    // pop result
    duk_pop(m_ctx);
    // pop fns obj
    duk_pop(m_ctx);

    DUMP("evalFilterFn\n");
    return result;
}

bool StyleContext::evalFilterFn(const std::string& _name) {
    if (!duk_get_global_string(m_ctx, _name.c_str())) {
        LOGE("EvalFilter %s", _name.c_str());
        return false;
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
    }

    bool result = false;

    if (duk_is_boolean(m_ctx, -1)) {
        result = duk_get_boolean(m_ctx, -1);
    }

    // pop result
    duk_pop(m_ctx);

    DUMP("evalFilterFn\n");
    return result;
}

bool StyleContext::parseStyleResult(StyleParamKey _key, StyleParam::Value& _val) const {
    _val = none_type{};

    if (duk_is_string(m_ctx, -1)) {
        std::string value(duk_get_string(m_ctx, -1));
        _val = StyleParam::parseString(_key, value);

    } else if (duk_is_boolean(m_ctx, -1)) {
        bool value = duk_get_boolean(m_ctx, -1);

        switch (_key) {
            case StyleParamKey::interactive:
            case StyleParamKey::visible:
                _val = value;
                break;
            case StyleParamKey::extrude:
                _val = value ? glm::vec2(NAN, NAN) : glm::vec2(0.0f, 0.0f);
                break;
            default:
                break;
        }

    } else if (duk_is_array(m_ctx, -1)) {
        duk_get_prop_string(m_ctx, -1, "length");
        int len = duk_get_int(m_ctx, -1);
        duk_pop(m_ctx);

        switch (_key) {
            case StyleParamKey::extrude: {
                if (len != 2) {
                    LOGW("Wrong array size for extrusion: '%d'.", len);
                    break;
                }

                duk_get_prop_index(m_ctx, -1, 0);
                double v1 = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 1);
                double v2 = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                _val = glm::vec2(v1, v2);
                break;
            }
            case StyleParamKey::color:
            case StyleParamKey::outline_color:
            case StyleParamKey::font_fill:
            case StyleParamKey::font_stroke_color: {
                if (len < 3 || len > 4) {
                    LOGW("Wrong array size for color: '%d'.", len);
                    break;
                }
                duk_get_prop_index(m_ctx, -1, 0);
                double r = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 1);
                double g = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 2);
                double b = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                double a = 1.0;
                if (len == 4) {
                    duk_get_prop_index(m_ctx, -1, 3);
                    a = duk_get_number(m_ctx, -1);
                    duk_pop(m_ctx);
                }

                _val = (((uint32_t)(255.0 * a) & 0xff) << 24) |
                       (((uint32_t)(255.0 * r) & 0xff)<< 16) |
                       (((uint32_t)(255.0 * g) & 0xff)<< 8) |
                       (((uint32_t)(255.0 * b) & 0xff));
                break;
            }
            default:
                break;
        }

    } else if (duk_is_number(m_ctx, -1)) {

        switch (_key) {
            case StyleParamKey::width:
            case StyleParamKey::outline_width: {
                // TODO more efficient way to return pixels.
                // atm this only works by return value as string
                double v = duk_get_number(m_ctx, -1);
                _val = StyleParam::Width{static_cast<float>(v)};
                break;
            }
            case StyleParamKey::font_stroke_width: {
                _val = static_cast<float>(duk_get_number(m_ctx, -1));
                break;
            }
            case StyleParamKey::order:
            case StyleParamKey::priority:
            case StyleParamKey::color:
            case StyleParamKey::outline_color:
            case StyleParamKey::font_fill:
            case StyleParamKey::font_stroke_color: {
                _val = static_cast<uint32_t>(duk_get_uint(m_ctx, -1));
                break;
            }
            default:
                break;
        }
    } else {
        LOGW("Unhandled return type from Javascript function.");
    }

    duk_pop(m_ctx);

    DUMP("parseStyleResult\n");
    return !_val.is<none_type>();
}

bool StyleContext::evalStyle(FunctionID _id, StyleParamKey _key, StyleParam::Value& _val) const {
    if (!duk_get_global_string(m_ctx, FUNC_ID)) {
        LOGE("EvalFilterFn - functions array not initialized");
        return false;
    }

    if (!duk_get_prop_index(m_ctx, -1, _id)) {
        LOGE("EvalFilterFn - function %d not set", _id);
    }

    // pop fns array
    duk_remove(m_ctx, -2);

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
        duk_pop(m_ctx);
        return false;
    }

    return parseStyleResult(_key, _val);
}

bool StyleContext::evalStyleFn(const std::string& name, StyleParamKey _key, StyleParam::Value& _val) {
    if (!duk_get_global_string(m_ctx, name.c_str())) {
        LOGE("EvalFilter %s", name.c_str());
        return false;
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalStyleFn: %s", duk_safe_to_string(m_ctx, -1));
        duk_pop(m_ctx);
        return false;
    }

    return parseStyleResult(_key, _val);
}

void StyleContext::addAccessor(const std::string& _name) {

    auto it = m_accessors.find(_name);
    if (it != m_accessors.end()) {
        return;
    }

    auto entry = m_accessors.emplace(_name, Accessor{_name, this});
    if (!entry.second) {
        return; // hmm, already added..
    }

    Accessor& attr = (*entry.first).second;

    // push 'feature' obj onto stack
    if (!duk_get_global_string(m_ctx, "feature")) {
        LOGE("'feature' not in global scope");
        return;
    }

    // push property name
    duk_push_string(m_ctx, _name.c_str());

    // push getter function
    duk_push_c_function(m_ctx, jsPropertyGetter, 0 /*nargs*/);
    duk_push_pointer(m_ctx, (void*)&attr);
    duk_put_prop_string(m_ctx, -2, ATTR_ID);

    // push setter function
    // duk_push_c_function(m_ctx, jsPropertySetter, 1 /*nargs*/);
    // duk_push_pointer(m_ctx, (void*)&attr);
    // duk_put_prop_string(m_ctx, -2, ATTR_ID);

    // stack: [ feature_obj, name, getter, setter ] -> [ feature_obj.name ]
    duk_def_prop(m_ctx, -3,
                 DUK_DEFPROP_HAVE_GETTER |
                 // DUK_DEFPROP_HAVE_SETTER |
                 // DUK_DEFPROP_WRITABLE |
                 // DUK_DEFPROP_HAVE_ENUMERABLE |
                 // DUK_DEFPROP_ENUMERABLE |
                 // DUK_DEFPROP_HAVE_CONFIGURABLE |
                 0);

    // pop feature obj
    duk_pop(m_ctx);

    DUMP("addAccessor\n");
}

duk_ret_t StyleContext::jsPropertyGetter(duk_context *_ctx) {

    // Storing state for a Duktape/C function:
    // http://duktape.org/guide.html#programming.9
    duk_push_current_function(_ctx);
    duk_get_prop_string(_ctx, -1, ATTR_ID);
    auto* attr = static_cast<const Accessor*> (duk_to_pointer(_ctx, -1));

    if (!attr || !attr->ctx || !attr->ctx->m_feature) {
        LOGE("Error: no context set %p %p",
               attr,
               attr ? attr->ctx : nullptr);

        duk_pop(_ctx);
        return 0;
    }

    auto it = attr->ctx->m_feature->props.get(attr->key);

    if (it.is<std::string>()) {
        duk_push_string(_ctx, it.get<std::string>().c_str());
    } else if (it.is<float>()) {
        duk_push_number(_ctx, it.get<float>());
    } else {
        duk_push_undefined(_ctx);
    }

    return 1;
}

duk_ret_t StyleContext::jsPropertySetter(duk_context *_ctx) {
    return 0;
}

}
<commit_msg>fix: StyleContext, cleanup stack on error<commit_after>#include "styleContext.h"
#include "platform.h"
#include "builders.h"
#include "scene/scene.h"
#include "data/propertyItem.h"

#define DUMP(...) // do { logMsg(__VA_ARGS__); duk_dump_context_stderr(m_ctx); } while(0)
#define DBG(...) do { logMsg(__VA_ARGS__); duk_dump_context_stderr(m_ctx); } while(0)

namespace Tangram {

const static char DATA_ID[] = "\xff""\xff""data";
const static char ATTR_ID[] = "\xff""\xff""attr";
const static char FUNC_ID[] = "\xff""\xff""fns";

StyleContext::StyleContext() {
    m_ctx = duk_create_heap_default();

    // add empty feature_object
    duk_push_object(m_ctx);

    // assign instance to feature_object
    duk_push_pointer(m_ctx, this);
    if (!duk_put_prop_string(m_ctx, -2, DATA_ID)) {
        LOGE("Ctx not assigned");
    }

    // put object in global scope
    if (!duk_put_global_string(m_ctx, "feature")) {
        LOGE("Feature not assigned");
    }

    DUMP("init\n");
}

StyleContext::~StyleContext() {
    duk_destroy_heap(m_ctx);
}

void StyleContext::initFunctions(const Scene& _scene) {

    if (_scene.id == m_sceneId) {
        return;
    }
    m_sceneId = _scene.id;

    auto arr_idx = duk_push_array(m_ctx);
    int id = 0;

    for (auto& function : _scene.functions()) {
        LOGD("compile '%s'", function.c_str());
        duk_push_string(m_ctx, function.c_str());
        duk_push_string(m_ctx, "");

        if (duk_pcompile(m_ctx, DUK_COMPILE_FUNCTION) == 0) {
            duk_put_prop_index(m_ctx, arr_idx, id);
        } else {
            LOGE("Compile failed: %s", duk_safe_to_string(m_ctx, -1));
            duk_pop(m_ctx);
        }
        id++;
    }

    if (!duk_put_global_string(m_ctx, FUNC_ID)) {
        LOGE("'fns' object not set");
    }

    DUMP("setScene - %d functions\n", id);
}

void StyleContext::setFeature(const Feature& _feature) {
    m_feature = &_feature;

    for (auto& item : _feature.props.items()) {
        addAccessor(item.key);
    }
}

void StyleContext::setGlobalZoom(float _zoom) {
    static const std::string _key("$zoom");
    if (_zoom != m_globalZoom) {
        setGlobal(_key, _zoom);
    }
}

void StyleContext::setGlobal(const std::string& _key, const Value& _val) {
    Value& entry = m_globals[_key];
    if (entry == _val) { return; }

    entry = _val;

    if (_val.is<float>()) {
        duk_push_number(m_ctx, _val.get<float>());
        duk_put_global_string(m_ctx, _key.c_str());

        if (_key == "$zoom") { m_globalZoom = _val.get<float>(); }

    } else if (_val.is<std::string>()) {
        duk_push_string(m_ctx, _val.get<std::string>().c_str());
        duk_put_global_string(m_ctx, _key.c_str());
    }
}

const Value& StyleContext::getGlobal(const std::string& _key) const {

    const static Value NOT_FOUND(none_type{});

    auto it = m_globals.find(_key);
    if (it != m_globals.end()) {
        return it->second;
    }
    return NOT_FOUND;
}

void StyleContext::clear() {
    m_feature = nullptr;
}

bool StyleContext::addFunction(const std::string& _name, const std::string& _func) {

    duk_push_string(m_ctx, _func.c_str());
    duk_push_string(m_ctx, _name.c_str());

    if (duk_pcompile(m_ctx, DUK_COMPILE_FUNCTION) != 0) {
        LOGE("Compile failed: %s", duk_safe_to_string(m_ctx, -1));
        return false;
    }

    // Put function in global scope
    duk_put_global_string(m_ctx, _name.c_str());

    DUMP("addFunction\n");
    return true;
}

bool StyleContext::evalFilter(FunctionID _id) const {

    if (!duk_get_global_string(m_ctx, FUNC_ID)) {
        LOGE("EvalFilterFn - functions not initialized");
        return false;
    }

    if (!duk_get_prop_index(m_ctx, -1, _id)) {
        LOGE("EvalFilterFn - function %d not set", _id);
        duk_pop(m_ctx);
        DBG("evalFilterFn\n");
        return false;
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
        duk_pop(m_ctx);
        duk_pop(m_ctx);
        DBG("evalFilterFn\n");
        return false;
    }

    bool result = false;

    if (duk_is_boolean(m_ctx, -1)) {
        result = duk_get_boolean(m_ctx, -1);
    }

    // pop result
    duk_pop(m_ctx);
    // pop fns obj
    duk_pop(m_ctx);

    DUMP("evalFilterFn\n");
    return result;
}

bool StyleContext::evalFilterFn(const std::string& _name) {
    if (!duk_get_global_string(m_ctx, _name.c_str())) {
        LOGE("EvalFilter %s", _name.c_str());
        return false;
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
    }

    bool result = false;

    if (duk_is_boolean(m_ctx, -1)) {
        result = duk_get_boolean(m_ctx, -1);
    }

    // pop result
    duk_pop(m_ctx);

    DUMP("evalFilterFn\n");
    return result;
}

bool StyleContext::parseStyleResult(StyleParamKey _key, StyleParam::Value& _val) const {
    _val = none_type{};

    if (duk_is_string(m_ctx, -1)) {
        std::string value(duk_get_string(m_ctx, -1));
        _val = StyleParam::parseString(_key, value);

    } else if (duk_is_boolean(m_ctx, -1)) {
        bool value = duk_get_boolean(m_ctx, -1);

        switch (_key) {
            case StyleParamKey::interactive:
            case StyleParamKey::visible:
                _val = value;
                break;
            case StyleParamKey::extrude:
                _val = value ? glm::vec2(NAN, NAN) : glm::vec2(0.0f, 0.0f);
                break;
            default:
                break;
        }

    } else if (duk_is_array(m_ctx, -1)) {
        duk_get_prop_string(m_ctx, -1, "length");
        int len = duk_get_int(m_ctx, -1);
        duk_pop(m_ctx);

        switch (_key) {
            case StyleParamKey::extrude: {
                if (len != 2) {
                    LOGW("Wrong array size for extrusion: '%d'.", len);
                    break;
                }

                duk_get_prop_index(m_ctx, -1, 0);
                double v1 = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 1);
                double v2 = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                _val = glm::vec2(v1, v2);
                break;
            }
            case StyleParamKey::color:
            case StyleParamKey::outline_color:
            case StyleParamKey::font_fill:
            case StyleParamKey::font_stroke_color: {
                if (len < 3 || len > 4) {
                    LOGW("Wrong array size for color: '%d'.", len);
                    break;
                }
                duk_get_prop_index(m_ctx, -1, 0);
                double r = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 1);
                double g = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                duk_get_prop_index(m_ctx, -1, 2);
                double b = duk_get_number(m_ctx, -1);
                duk_pop(m_ctx);

                double a = 1.0;
                if (len == 4) {
                    duk_get_prop_index(m_ctx, -1, 3);
                    a = duk_get_number(m_ctx, -1);
                    duk_pop(m_ctx);
                }

                _val = (((uint32_t)(255.0 * a) & 0xff) << 24) |
                       (((uint32_t)(255.0 * r) & 0xff)<< 16) |
                       (((uint32_t)(255.0 * g) & 0xff)<< 8) |
                       (((uint32_t)(255.0 * b) & 0xff));
                break;
            }
            default:
                break;
        }

    } else if (duk_is_number(m_ctx, -1)) {

        switch (_key) {
            case StyleParamKey::width:
            case StyleParamKey::outline_width: {
                // TODO more efficient way to return pixels.
                // atm this only works by return value as string
                double v = duk_get_number(m_ctx, -1);
                _val = StyleParam::Width{static_cast<float>(v)};
                break;
            }
            case StyleParamKey::font_stroke_width: {
                _val = static_cast<float>(duk_get_number(m_ctx, -1));
                break;
            }
            case StyleParamKey::order:
            case StyleParamKey::priority:
            case StyleParamKey::color:
            case StyleParamKey::outline_color:
            case StyleParamKey::font_fill:
            case StyleParamKey::font_stroke_color: {
                _val = static_cast<uint32_t>(duk_get_uint(m_ctx, -1));
                break;
            }
            default:
                break;
        }
    } else {
        LOGW("Unhandled return type from Javascript function.");
    }

    duk_pop(m_ctx);

    DUMP("parseStyleResult\n");
    return !_val.is<none_type>();
}

bool StyleContext::evalStyle(FunctionID _id, StyleParamKey _key, StyleParam::Value& _val) const {
    if (!duk_get_global_string(m_ctx, FUNC_ID)) {
        LOGE("EvalFilterFn - functions array not initialized");
        return false;
    }

    if (!duk_get_prop_index(m_ctx, -1, _id)) {
        LOGE("EvalFilterFn - function %d not set", _id);
    }

    // pop fns array
    duk_remove(m_ctx, -2);

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1));
        duk_pop(m_ctx);
        return false;
    }

    return parseStyleResult(_key, _val);
}

bool StyleContext::evalStyleFn(const std::string& name, StyleParamKey _key, StyleParam::Value& _val) {
    if (!duk_get_global_string(m_ctx, name.c_str())) {
        LOGE("EvalFilter %s", name.c_str());
        return false;
    }

    if (duk_pcall(m_ctx, 0) != 0) {
        LOGE("EvalStyleFn: %s", duk_safe_to_string(m_ctx, -1));
        duk_pop(m_ctx);
        return false;
    }

    return parseStyleResult(_key, _val);
}

void StyleContext::addAccessor(const std::string& _name) {

    auto it = m_accessors.find(_name);
    if (it != m_accessors.end()) {
        return;
    }

    auto entry = m_accessors.emplace(_name, Accessor{_name, this});
    if (!entry.second) {
        return; // hmm, already added..
    }

    Accessor& attr = (*entry.first).second;

    // push 'feature' obj onto stack
    if (!duk_get_global_string(m_ctx, "feature")) {
        LOGE("'feature' not in global scope");
        return;
    }

    // push property name
    duk_push_string(m_ctx, _name.c_str());

    // push getter function
    duk_push_c_function(m_ctx, jsPropertyGetter, 0 /*nargs*/);
    duk_push_pointer(m_ctx, (void*)&attr);
    duk_put_prop_string(m_ctx, -2, ATTR_ID);

    // push setter function
    // duk_push_c_function(m_ctx, jsPropertySetter, 1 /*nargs*/);
    // duk_push_pointer(m_ctx, (void*)&attr);
    // duk_put_prop_string(m_ctx, -2, ATTR_ID);

    // stack: [ feature_obj, name, getter, setter ] -> [ feature_obj.name ]
    duk_def_prop(m_ctx, -3,
                 DUK_DEFPROP_HAVE_GETTER |
                 // DUK_DEFPROP_HAVE_SETTER |
                 // DUK_DEFPROP_WRITABLE |
                 // DUK_DEFPROP_HAVE_ENUMERABLE |
                 // DUK_DEFPROP_ENUMERABLE |
                 // DUK_DEFPROP_HAVE_CONFIGURABLE |
                 0);

    // pop feature obj
    duk_pop(m_ctx);

    DUMP("addAccessor\n");
}

duk_ret_t StyleContext::jsPropertyGetter(duk_context *_ctx) {

    // Storing state for a Duktape/C function:
    // http://duktape.org/guide.html#programming.9
    duk_push_current_function(_ctx);
    duk_get_prop_string(_ctx, -1, ATTR_ID);
    auto* attr = static_cast<const Accessor*> (duk_to_pointer(_ctx, -1));

    if (!attr || !attr->ctx || !attr->ctx->m_feature) {
        LOGE("Error: no context set %p %p",
               attr,
               attr ? attr->ctx : nullptr);

        duk_pop(_ctx);
        return 0;
    }

    auto it = attr->ctx->m_feature->props.get(attr->key);

    if (it.is<std::string>()) {
        duk_push_string(_ctx, it.get<std::string>().c_str());
    } else if (it.is<float>()) {
        duk_push_number(_ctx, it.get<float>());
    } else {
        duk_push_undefined(_ctx);
    }

    return 1;
}

duk_ret_t StyleContext::jsPropertySetter(duk_context *_ctx) {
    return 0;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Games/GameManager.hpp>

namespace Hearthstonepp
{
void GameManager::ProcessNextStep(Game& game, Step step)
{
    switch (step)
    {
        case Step::BEGIN_FIRST:
            game.step = step;
            game.BeginFirst();
            break;
        default:
            break;
    }
}
}  // namespace Hearthstonepp<commit_msg>[ci skip] feat(game-state): Add code to process BEGIN_SHUFFLE step<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Games/GameManager.hpp>

namespace Hearthstonepp
{
void GameManager::ProcessNextStep(Game& game, Step step)
{
    switch (step)
    {
        case Step::BEGIN_FIRST:
            game.step = step;
            game.BeginFirst();
            break;
        case Step::BEGIN_SHUFFLE:
            game.step = step;
            game.BeginShuffle();
            break;
        default:
            break;
    }
}
}  // namespace Hearthstonepp<|endoftext|>


<commit_before>#include <stdio.h>
#include <opencv2/video/background_segm.hpp>
#include "opencv2/opencv.hpp"
#include "physics.h"

using namespace cv;
using namespace std;

const char *win = "Flying Pancake";
static bool reverseMirror = true;

int main(int argc, char **argv)
{
    if (argc > 2) {
        fprintf(stderr, "Error: Please limit arguments to 1 or none.\n");
        exit(1);
    }
    else if (argc == 2) {
        if (!strcmp(argv[1], "-r"))
            reverseMirror = false;
        else {
            fprintf(stderr, "Usage: videoBall [-r]\n");
            exit(1);
        }
    }

    int cam = 0; // default camera
    VideoCapture cap(cam);
    if (!cap.isOpened()) {
        fprintf(stderr, "Error: Cannot open camera %d\n", cam);
        exit(1);
    }

    namedWindow(win, CV_WINDOW_AUTOSIZE);

    Mat fgMaskMOG;
    BackgroundSubtractorMOG2 MOG;

    Mat inputFrame, outFrame;
    cap >> inputFrame;

    int height = inputFrame.rows;
    int width = inputFrame.cols;

    // initial position
    Point pt;
    pt.x = width / 2;
    pt.y = height / 2;

    // initial momentum
    Point momentum;
    momentum.x = 0;
    momentum.y = 0;

    Mat circ;
    cvtColor(inputFrame, outFrame, CV_LOAD_IMAGE_COLOR);
    cvtColor(inputFrame, circ, CV_BGR2GRAY);

    int count = 0;
    int sum;
    Mat reverseFrame;
    Mat ballFrame, handFrame;
    Mat foregroundMask, backgroundMask;
    Point small;
    int score=0, left=0, right=0;
    int timer = 50; // 50 frames between points are scored
    while(++count) {
        cap >> inputFrame;

        if (reverseMirror) {
            inputFrame.copyTo(reverseFrame);
            flip(reverseFrame, inputFrame, 1);
        }
        cvtColor(inputFrame, outFrame, CV_LOAD_IMAGE_COLOR);
        MOG(inputFrame, fgMaskMOG);

        foregroundMask = fgMaskMOG > THRESH;
        backgroundMask = fgMaskMOG <= THRESH;
        score = pongDir(&momentum, &pt, height, width);
        if (!score) {   // still moving
            // blank canvas
            circ.setTo(Scalar(0, 0, 0));
            Rect ballRegion(pt.x - RADIUS, pt.y - RADIUS, 2 * RADIUS, 2 * RADIUS);
            ballFrame = circ(ballRegion);

            fgMaskMOG.setTo(Scalar(255, 255, 255), foregroundMask);     // clean up
            fgMaskMOG.setTo(Scalar(0, 0, 0), backgroundMask);
            handFrame = fgMaskMOG(ballRegion);

            int halfRad = RADIUS / 2;
            // top left
            small.x = halfRad;   small.y = halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x < width / 2 ? sum : 0;
            momentum.y += sum;

            // top right
            small.x = 3 * halfRad;  small.y = halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x >= width / 2 ? -sum : 0;
            momentum.y += sum;

            // bottom left
            small.x = halfRad;    small.y = 3 * halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x < width / 2 ? sum : 0;
            momentum.y -= sum;

            // bottom right
            small.x = 3 * halfRad;   small.y = 3 * halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x >= width / 2 ? -sum : 0;
            momentum.y -= sum;

        }else if (!timer--){
          //someone scored, so decrement timer and reset when timer = 0
          timer = 50;
          reset_board(&pt, &momentum, width, height);
          if (score >0){ left +=1; }
          else{         right += 1; }

        }else if ( right >= 5 || left >= 5){
          //Game over, stop playing

        }
        // outFrame -= Scalar(50,50,50);
        // cvtColor(foregroundMask, inputFrame, CV_LOAD_IMAGE_COLOR);

        // outFrame.setTo(Scalar(0, 0, 0));
        // outFrame.setTo(Scalar(255, 255, 255), foregroundMask);

        //Set the color of the ball here.
        cvtColor(foregroundMask,foregroundMask ,COLOR_GRAY2BGR);
        addWeighted(outFrame, 0.75, foregroundMask, 0.25, 1, outFrame, -1);
        drawCircle(outFrame, pt, RADIUS, Scalar( 0, 0, 255 ));

        // imshow(win, outFrame);
        imshow(win,outFrame);

        // listening for key press
        char c = waitKey(30);
        if (c >= 0) {
            if (c == 'r') {
                pt.x = width / 2;
                pt.y = height / 2;
                continue;
            }
            else
                break;
        }
    }

    return 0;
}
<commit_msg>Working game<commit_after>#include <stdio.h>
#include <opencv2/video/background_segm.hpp>
#include "opencv2/opencv.hpp"
#include "physics.h"

using namespace cv;
using namespace std;

const char *win = "Flying Pancake";
static bool reverseMirror = true;

int main(int argc, char **argv)
{
    if (argc > 2) {
        fprintf(stderr, "Error: Please limit arguments to 1 or none.\n");
        exit(1);
    }
    else if (argc == 2) {
        if (!strcmp(argv[1], "-r"))
            reverseMirror = false;
        else {
            fprintf(stderr, "Usage: videoBall [-r]\n");
            exit(1);
        }
    }

    int cam = 0; // default camera
    VideoCapture cap(cam);
    if (!cap.isOpened()) {
        fprintf(stderr, "Error: Cannot open camera %d\n", cam);
        exit(1);
    }

    namedWindow(win, CV_WINDOW_AUTOSIZE);

    Mat fgMaskMOG;
    BackgroundSubtractorMOG2 MOG;

    Mat inputFrame, outFrame, scoreFrame;
    cap >> inputFrame;

    int height = inputFrame.rows;
    int width = inputFrame.cols;

    // initial position
    Point pt;
    pt.x = width / 2;
    pt.y = height / 2;

    // initial momentum
    Point momentum;
    momentum.x = 0;
    momentum.y = 0;

    Mat circ;
    cvtColor(inputFrame, outFrame, CV_LOAD_IMAGE_COLOR);
    cvtColor(inputFrame, scoreFrame, CV_LOAD_IMAGE_COLOR);
    cvtColor(inputFrame, circ, CV_BGR2GRAY);

    int count = 0;
    int sum;
    Mat reverseFrame;
    Mat ballFrame, handFrame;
    Mat foregroundMask, backgroundMask;

    Point small;
    int score=0, left=0, right=0;
    int timer = 50; // 50 frames between points are scored

    //Initialize the scoreFrame here
    scoreFrame = scoreFrame > 256;
    putText(scoreFrame, to_string(left), Point(50,height-50), FONT_HERSHEY_SCRIPT_SIMPLEX, 3, Scalar(255,255,255), 1, 8, false );
    // Put right score on right
    putText(scoreFrame, to_string(right), Point(width-50,height-50), FONT_HERSHEY_SCRIPT_SIMPLEX, 3, Scalar(255,255,255), 1, 8, false );

    while(++count) {
        cap >> inputFrame;

        if (reverseMirror) {
            inputFrame.copyTo(reverseFrame);
            flip(reverseFrame, inputFrame, 1);
        }
        cvtColor(inputFrame, outFrame, CV_LOAD_IMAGE_COLOR);
        MOG(inputFrame, fgMaskMOG);

        foregroundMask = fgMaskMOG > THRESH;
        backgroundMask = fgMaskMOG <= THRESH;
        score = pongDir(&momentum, &pt, height, width);
        if (!score) {   // still moving
            // blank canvas
            circ.setTo(Scalar(0, 0, 0));
            Rect ballRegion(pt.x - RADIUS, pt.y - RADIUS, 2 * RADIUS, 2 * RADIUS);
            ballFrame = circ(ballRegion);

            fgMaskMOG.setTo(Scalar(255, 255, 255), foregroundMask);     // clean up
            fgMaskMOG.setTo(Scalar(0, 0, 0), backgroundMask);
            handFrame = fgMaskMOG(ballRegion);

            int halfRad = RADIUS / 2;
            // top left
            small.x = halfRad;   small.y = halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x < width / 2 ? sum : 0;
            momentum.y += sum;

            // top right
            small.x = 3 * halfRad;  small.y = halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x >= width / 2 ? -sum : 0;
            momentum.y += sum;

            // bottom left
            small.x = halfRad;    small.y = 3 * halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x < width / 2 ? sum : 0;
            momentum.y -= sum;

            // bottom right
            small.x = 3 * halfRad;   small.y = 3 * halfRad;
            sum = getOverlap(&ballFrame, &handFrame, &small);
            momentum.x += pt.x >= width / 2 ? -sum : 0;
            momentum.y -= sum;

        }else if (!timer--){
          //someone scored, so decrement timer and reset when timer = 0
          timer = 50;
          reset_board(&pt, &momentum, width, height);
          if (score >0){ left +=1; }
          else{         right += 1; }
          scoreFrame = scoreFrame > 256;
          putText(scoreFrame, to_string(left), Point(50,height-50), FONT_HERSHEY_SCRIPT_SIMPLEX, 2, Scalar(255,255,255), 1, 8, false );
          // Put right score on right
          putText(scoreFrame, to_string(right), Point(width-50,height-50), FONT_HERSHEY_SCRIPT_SIMPLEX, 2, Scalar(255,255,255), 1, 8, false );

          if ( right >= 5 || left >= 5){
            //Game over, stop playing
            // game_over(right,left);
            break;
          }
        }
        // outFrame -= Scalar(50,50,50);
        // cvtColor(foregroundMask, inputFrame, CV_LOAD_IMAGE_COLOR);

        // outFrame.setTo(Scalar(0, 0, 0));
        // outFrame.setTo(Scalar(255, 255, 255), foregroundMask);

        //Set the color of the ball here.
        cvtColor(foregroundMask,foregroundMask ,COLOR_GRAY2BGR);
        addWeighted(outFrame, 0.75, foregroundMask, 0.25, 1, outFrame, -1);
        drawCircle(outFrame, pt, RADIUS, Scalar( 0, 0, 255 ));

        // Put score frame onto image
        addWeighted(outFrame, 0.75, scoreFrame, 1.0, 1, outFrame, -1);

        imshow(win,outFrame);

        // listening for key press
        char c = waitKey(30);
        if (c >= 0) {
            if (c == 'r') {
                pt.x = width / 2;
                pt.y = height / 2;
                continue;
            }
            else
                break;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <Python.h>

#include <google/protobuf/pyext/message.h>
#include <google/protobuf/proto_api.h>

#include <google/protobuf/message_lite.h>

namespace {

// C++ API.  Clients get at this via proto_api.h
struct ApiImplementation : google::protobuf::python::PyProto_API {
  const google::protobuf::Message*
      GetMessagePointer(PyObject* msg) const override {
    return google::protobuf::python::PyMessage_GetMessagePointer(msg);
  }
  google::protobuf::Message*
      GetMutableMessagePointer(PyObject* msg) const override {
    return google::protobuf::python::PyMessage_GetMutableMessagePointer(msg);
  }
};

}  // namespace

static PyObject* GetPythonProto3PreserveUnknownsDefault(
    PyObject* /*m*/, PyObject* /*args*/) {
  if (google::protobuf::internal::GetProto3PreserveUnknownsDefault()) {
    Py_RETURN_TRUE;
  } else {
    Py_RETURN_FALSE;
  }
}

static PyObject* SetPythonProto3PreserveUnknownsDefault(
    PyObject* /*m*/, PyObject* arg) {
  if (!arg || !PyBool_Check(arg)) {
    PyErr_SetString(
        PyExc_TypeError,
        "Argument to SetPythonProto3PreserveUnknownsDefault must be boolean");
    return NULL;
  }
  google::protobuf::internal::SetProto3PreserveUnknownsDefault(PyObject_IsTrue(arg));
  Py_RETURN_NONE;
}

static const char module_docstring[] =
"python-proto2 is a module that can be used to enhance proto2 Python API\n"
"performance.\n"
"\n"
"It provides access to the protocol buffers C++ reflection API that\n"
"implements the basic protocol buffer functions.";

static PyMethodDef ModuleMethods[] = {
  {"SetAllowOversizeProtos",
    (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos,
    METH_O, "Enable/disable oversize proto parsing."},
  // DO NOT USE: For migration and testing only.
  {"GetPythonProto3PreserveUnknownsDefault",
    (PyCFunction)GetPythonProto3PreserveUnknownsDefault,
    METH_NOARGS, "Get Proto3 preserve unknowns default."},
  // DO NOT USE: For migration and testing only.
  {"SetPythonProto3PreserveUnknownsDefault",
    (PyCFunction)SetPythonProto3PreserveUnknownsDefault,
    METH_O, "Enable/disable proto3 unknowns preservation."},
  { NULL, NULL}
};

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef _module = {
  PyModuleDef_HEAD_INIT,
  "_message",
  module_docstring,
  -1,
  ModuleMethods,  /* m_methods */
  NULL,
  NULL,
  NULL,
  NULL
};
#define INITFUNC PyInit__message
#define INITFUNC_ERRORVAL NULL
#else  // Python 2
#define INITFUNC init_message
#define INITFUNC_ERRORVAL
#endif

extern "C" {
  PyMODINIT_FUNC INITFUNC(void) {
    PyObject* m;
#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&_module);
#else
    m = Py_InitModule3("_message", ModuleMethods,
                       module_docstring);
#endif
    if (m == NULL) {
      return INITFUNC_ERRORVAL;
    }

    if (!google::protobuf::python::InitProto2MessageModule(m)) {
      Py_DECREF(m);
      return INITFUNC_ERRORVAL;
    }

#if PY_MAJOR_VERSION >= 3
    return m;
#endif
  }
}
<commit_msg>Update message_module.cc (#4835)<commit_after>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <Python.h>

#include <google/protobuf/pyext/message.h>
#include <google/protobuf/proto_api.h>

#include <google/protobuf/message_lite.h>

namespace {

// C++ API.  Clients get at this via proto_api.h
struct ApiImplementation : google::protobuf::python::PyProto_API {
  const google::protobuf::Message*
      GetMessagePointer(PyObject* msg) const override {
    return google::protobuf::python::PyMessage_GetMessagePointer(msg);
  }
  google::protobuf::Message*
      GetMutableMessagePointer(PyObject* msg) const override {
    return google::protobuf::python::PyMessage_GetMutableMessagePointer(msg);
  }
};

}  // namespace

static PyObject* GetPythonProto3PreserveUnknownsDefault(
    PyObject* /*m*/, PyObject* /*args*/) {
  if (google::protobuf::internal::GetProto3PreserveUnknownsDefault()) {
    Py_RETURN_TRUE;
  } else {
    Py_RETURN_FALSE;
  }
}

static PyObject* SetPythonProto3PreserveUnknownsDefault(
    PyObject* /*m*/, PyObject* arg) {
  if (!arg || !PyBool_Check(arg)) {
    PyErr_SetString(
        PyExc_TypeError,
        "Argument to SetPythonProto3PreserveUnknownsDefault must be boolean");
    return NULL;
  }
  google::protobuf::internal::SetProto3PreserveUnknownsDefault(PyObject_IsTrue(arg));
  Py_RETURN_NONE;
}

static const char module_docstring[] =
"python-proto2 is a module that can be used to enhance proto2 Python API\n"
"performance.\n"
"\n"
"It provides access to the protocol buffers C++ reflection API that\n"
"implements the basic protocol buffer functions.";

static PyMethodDef ModuleMethods[] = {
  {"SetAllowOversizeProtos",
    (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos,
    METH_O, "Enable/disable oversize proto parsing."},
  // DO NOT USE: For migration and testing only.
  {"GetPythonProto3PreserveUnknownsDefault",
    (PyCFunction)GetPythonProto3PreserveUnknownsDefault,
    METH_NOARGS, "Get Proto3 preserve unknowns default."},
  // DO NOT USE: For migration and testing only.
  {"SetPythonProto3PreserveUnknownsDefault",
    (PyCFunction)SetPythonProto3PreserveUnknownsDefault,
    METH_O, "Enable/disable proto3 unknowns preservation."},
  { NULL, NULL}
};

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef _module = {
  PyModuleDef_HEAD_INIT,
  "_message",
  module_docstring,
  -1,
  ModuleMethods,  /* m_methods */
  NULL,
  NULL,
  NULL,
  NULL
};
#define INITFUNC PyInit__message
#define INITFUNC_ERRORVAL NULL
#else  // Python 2
#define INITFUNC init_message
#define INITFUNC_ERRORVAL
#endif

extern "C" {
  PyMODINIT_FUNC INITFUNC(void) {
    PyObject* m;
#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&_module);
#else
    m = Py_InitModule3("_message", ModuleMethods,
                       module_docstring);
#endif
    if (m == NULL) {
      return INITFUNC_ERRORVAL;
    }

    if (!google::protobuf::python::InitProto2MessageModule(m)) {
      Py_DECREF(m);
      return INITFUNC_ERRORVAL;
    }

    // Adds the C++ API
    if (PyObject* api =
            PyCapsule_New(new ApiImplementation(),
                          google::protobuf::python::PyProtoAPICapsuleName(), NULL)) {
      PyModule_AddObject(m, "proto_API", api);
    } else {
      return INITFUNC_ERRORVAL;
    }

#if PY_MAJOR_VERSION >= 3
    return m;
#endif
  }
}
<|endoftext|>


<commit_before>/**
 * @file MelFilter.cpp
 *
 * Triangular filters in Mel frequency scale.
 *
 * This file is part of the Aquila DSP library.
 * Aquila is free software, licensed under the MIT/X11 License. A copy of
 * the license is provided with the library in the LICENSE file.
 *
 * @package Aquila
 * @version 3.0.0-dev
 * @author Zbigniew Siciarz
 * @date 2007-2013
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @since 0.3.3
 */

#include "MelFilter.h"
#include <utility>

namespace Aquila
{
    /**
     * Creates the filter and sets sample frequency.
     *
     * @param sampleFrequency sample frequency in Hz
     */
    MelFilter::MelFilter(FrequencyType sampleFrequency):
        m_sampleFrequency(sampleFrequency)
    {
    }

    /**
     * Move constructor.
     *
     * @param other other filter to be moved from
     */
    MelFilter::MelFilter(MelFilter&& other):
        m_sampleFrequency(other.m_sampleFrequency),
        m_spectrum(std::move(other.m_spectrum))
    {
    }

    /**
     * Designs the Mel filter and creates triangular spectrum.
     *
     * @param filterNum which filter in a sequence it is
     * @param melFilterWidth filter width in Mel scale (eg. 200)
     * @param N filter spectrum size (must be the same as filtered spectrum)
     */
    void MelFilter::createFilter(unsigned short filterNum,
                                 std::size_t melFilterWidth, std::size_t N)
    {
        // calculate frequencies in Mel scale
        FrequencyType melMinFreq = filterNum * melFilterWidth / 2.0;
        FrequencyType melCenterFreq = melMinFreq + melFilterWidth / 2.0;
        FrequencyType melMaxFreq = melMinFreq + melFilterWidth;

        // convert frequencies to linear scale
        FrequencyType minFreq = melToLinear(melMinFreq);
        FrequencyType centerFreq = melToLinear(melCenterFreq);
        FrequencyType maxFreq = melToLinear(melMaxFreq);

        // generate filter spectrum in linear scale
        generateFilterSpectrum(minFreq, centerFreq, maxFreq, N);
    }

    /**
     * Returns a single value computed by multiplying signal spectrum with
     * Mel filter spectrum and summing all the products.
     *
     * @param dataSpectrum complex signal spectrum
     * @return dot product of the spectra
     */
    double MelFilter::apply(const SpectrumType& dataSpectrum) const
    {
        double value = 0.0;
        const std::size_t N = dataSpectrum.size();
        // iteration over first half of the spectrum
        for (unsigned int i = 0; i < N / 2 - 1; ++i)
        {
            value += std::abs(dataSpectrum[i]) * m_spectrum[i];
        }
        return value;
    }

    void MelFilter::generateFilterSpectrum(FrequencyType minFreq,
                                           FrequencyType centerFreq,
                                           FrequencyType maxFreq, std::size_t N)
    {
        m_spectrum.clear();
        m_spectrum.resize(N, 0.0);

        // find spectral peak positions corresponding to frequencies
        std::size_t minPos = static_cast<std::size_t>(N * minFreq / m_sampleFrequency);
        std::size_t centerPos = static_cast<std::size_t>(N * centerFreq / m_sampleFrequency);
        std::size_t maxPos = static_cast<std::size_t>(N * maxFreq / m_sampleFrequency);

        const double max = 1.0;

        // outside the triangle spectrum values are 0, guaranteed by
        // earlier call to resize
        for (unsigned int k = minPos; k <= maxPos; ++k)
        {
            if (k < centerPos)
            {
                // in the triangle on the ascending slope
                m_spectrum[k] = (k - minPos) * max / (centerPos - minPos);
            }
            else
            {
                // in the triangle on the descending slope
                m_spectrum[k] = (maxPos - k) * max / (maxPos - centerPos);
            }
        }
    }
}
<commit_msg>Added a descriptive comment for generateFilterSpectrum.<commit_after>/**
 * @file MelFilter.cpp
 *
 * Triangular filters in Mel frequency scale.
 *
 * This file is part of the Aquila DSP library.
 * Aquila is free software, licensed under the MIT/X11 License. A copy of
 * the license is provided with the library in the LICENSE file.
 *
 * @package Aquila
 * @version 3.0.0-dev
 * @author Zbigniew Siciarz
 * @date 2007-2013
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @since 0.3.3
 */

#include "MelFilter.h"
#include <utility>

namespace Aquila
{
    /**
     * Creates the filter and sets sample frequency.
     *
     * @param sampleFrequency sample frequency in Hz
     */
    MelFilter::MelFilter(FrequencyType sampleFrequency):
        m_sampleFrequency(sampleFrequency)
    {
    }

    /**
     * Move constructor.
     *
     * @param other other filter to be moved from
     */
    MelFilter::MelFilter(MelFilter&& other):
        m_sampleFrequency(other.m_sampleFrequency),
        m_spectrum(std::move(other.m_spectrum))
    {
    }

    /**
     * Designs the Mel filter and creates triangular spectrum.
     *
     * @param filterNum which filter in a sequence it is
     * @param melFilterWidth filter width in Mel scale (eg. 200)
     * @param N filter spectrum size (must be the same as filtered spectrum)
     */
    void MelFilter::createFilter(unsigned short filterNum,
                                 std::size_t melFilterWidth, std::size_t N)
    {
        // calculate frequencies in Mel scale
        FrequencyType melMinFreq = filterNum * melFilterWidth / 2.0;
        FrequencyType melCenterFreq = melMinFreq + melFilterWidth / 2.0;
        FrequencyType melMaxFreq = melMinFreq + melFilterWidth;

        // convert frequencies to linear scale
        FrequencyType minFreq = melToLinear(melMinFreq);
        FrequencyType centerFreq = melToLinear(melCenterFreq);
        FrequencyType maxFreq = melToLinear(melMaxFreq);

        // generate filter spectrum in linear scale
        generateFilterSpectrum(minFreq, centerFreq, maxFreq, N);
    }

    /**
     * Returns a single value computed by multiplying signal spectrum with
     * Mel filter spectrum and summing all the products.
     *
     * @param dataSpectrum complex signal spectrum
     * @return dot product of the spectra
     */
    double MelFilter::apply(const SpectrumType& dataSpectrum) const
    {
        double value = 0.0;
        const std::size_t N = dataSpectrum.size();
        // iteration over first half of the spectrum
        for (unsigned int i = 0; i < N / 2 - 1; ++i)
        {
            value += std::abs(dataSpectrum[i]) * m_spectrum[i];
        }
        return value;
    }

    /**
     * Generates a vector of values shaped as a triangular filter.
     *
     * ^                       [2]
     * |                        /\
     * |                       /  \
     * |                      /    \
     * |_____________________/      \__________________
     * +--------------------[1]----[3]---------------------> f
     *
     * @param minFreq frequency at [1] in linear scale
     * @param centerFreq frequency at [2] in linear scale
     * @param maxFreq frequency at [3] in linear scale
     * @param N length of the spectrum
     */
    void MelFilter::generateFilterSpectrum(FrequencyType minFreq,
                                           FrequencyType centerFreq,
                                           FrequencyType maxFreq, std::size_t N)
    {
        m_spectrum.clear();
        m_spectrum.resize(N, 0.0);

        // find spectral peak positions corresponding to frequencies
        std::size_t minPos = static_cast<std::size_t>(N * minFreq / m_sampleFrequency);
        std::size_t centerPos = static_cast<std::size_t>(N * centerFreq / m_sampleFrequency);
        std::size_t maxPos = static_cast<std::size_t>(N * maxFreq / m_sampleFrequency);

        const double max = 1.0;

        // outside the triangle spectrum values are 0, guaranteed by
        // earlier call to resize
        for (unsigned int k = minPos; k <= maxPos; ++k)
        {
            if (k < centerPos)
            {
                // in the triangle on the ascending slope
                m_spectrum[k] = (k - minPos) * max / (centerPos - minPos);
            }
            else
            {
                // in the triangle on the descending slope
                m_spectrum[k] = (maxPos - k) * max / (maxPos - centerPos);
            }
        }
    }
}
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/kernels/data/experimental/sampling_dataset_op.h"
#include "tensorflow/core/framework/dataset.h"
#include "tensorflow/core/framework/partial_tensor_shape.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/kernels/data/name_utils.h"
#include "tensorflow/core/lib/random/philox_random.h"
#include "tensorflow/core/lib/random/random.h"
#include "tensorflow/core/lib/random/random_distributions.h"
#include "tensorflow/core/lib/random/simple_philox.h"

namespace tensorflow {
namespace data {
namespace experimental {

// Constants declared in sampling_dataset_op.h and used both here and in test
// cases.
/* static */ constexpr const char* const SamplingDatasetOp::kDatasetType;
/* static */ constexpr const char* const SamplingDatasetOp::kInputDataset;
/* static */ constexpr const char* const SamplingDatasetOp::kRate;
/* static */ constexpr const char* const SamplingDatasetOp::kSeed;
/* static */ constexpr const char* const SamplingDatasetOp::kSeed2;
/* static */ constexpr const char* const SamplingDatasetOp::kOutputTypes;
/* static */ constexpr const char* const SamplingDatasetOp::kOutputShapes;

class SamplingDatasetOp::Dataset : public DatasetBase {
 public:
  Dataset(OpKernelContext* ctx, float rate, int64 seed, int64 seed2,
          const DatasetBase* input)
      : DatasetBase(DatasetContext(ctx)),
        rate_(rate),
        seed_(seed),
        seed2_(seed2),
        input_(input) {
    input_->Ref();
  }

  ~Dataset() override { input_->Unref(); }

  std::unique_ptr<IteratorBase> MakeIteratorInternal(
      const string& prefix) const override {
    return std::unique_ptr<IteratorBase>(
        new Iterator({this, name_utils::IteratorPrefix(kDatasetType, prefix)},
                     seed_, seed2_));
  }

  const DataTypeVector& output_dtypes() const override {
    return input_->output_dtypes();
  }

  const std::vector<PartialTensorShape>& output_shapes() const override {
    return input_->output_shapes();
  }

  string DebugString() const override {
    return name_utils::DatasetDebugString(kDatasetType);
  }

  Status CheckExternalState() const override {
    return input_->CheckExternalState();
  }

  bool IsStateful() const override { return input_->IsStateful(); }

 protected:
  Status AsGraphDefInternal(SerializationContext* ctx,
                            DatasetGraphDefBuilder* b,
                            Node** output) const override {
    Node* input_graph_node = nullptr;
    TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node));
    Node* rate = nullptr;
    Node* seed = nullptr;
    Node* seed2 = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(rate_, &rate));
    TF_RETURN_IF_ERROR(b->AddScalar(seed_, &seed));
    TF_RETURN_IF_ERROR(b->AddScalar(seed2_, &seed2));
    TF_RETURN_IF_ERROR(
        b->AddDataset(this, {input_graph_node, rate, seed, seed2}, output));
    return Status::OK();
  }

 private:
  class Iterator : public DatasetIterator<Dataset> {
   public:
    explicit Iterator(const Params& params, int64 seed, int64 seed2)
        : DatasetIterator<Dataset>(params),
          seed_(seed),
          seed2_(seed2),
          parent_generator_(seed, seed2),
          generator_(&parent_generator_) {}

    Status Initialize(IteratorContext* ctx) override {
      return dataset()->input_->MakeIterator(ctx, prefix(), &input_impl_);
    }

    Status GetNextInternal(IteratorContext* ctx,
                           std::vector<Tensor>* out_tensors,
                           bool* end_of_sequence) override {
      bool rand_val_hit;
      do {
        {
          tf_shared_lock l(mu_);
          if (!input_impl_) {
            *end_of_sequence = true;
            return Status::OK();
          }
          TF_RETURN_IF_ERROR(
              input_impl_->GetNext(ctx, out_tensors, end_of_sequence));
        }
        if (*end_of_sequence) {
          mutex_lock l(mu_);
          input_impl_.reset();
          return Status::OK();
        }

        // generate a number from random uniform [0, 1)
        float rand_val = Random();
        rand_val_hit = rand_val < dataset()->rate_;
        if (!rand_val_hit) {
          // Clear the output tensor list since it doesn't match.
          out_tensors->clear();
        }
      } while (!rand_val_hit);
      *end_of_sequence = false;
      return Status::OK();
    }

   protected:
    void ResetRngs() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
      // Reset the generators based on the current iterator seeds.
      parent_generator_ = random::PhiloxRandom(seed_, seed2_);
      generator_ =
          random::SingleSampleAdapter<random::PhiloxRandom>(&parent_generator_);
      generator_.Skip(num_random_samples_);
    }

    Status SaveInternal(IteratorStateWriter* writer) override {
      mutex_lock l(mu_);
      // Save state needed to restore the random number generators.
      TF_RETURN_IF_ERROR(writer->WriteScalar(
          this->full_name("num_random_samples"), num_random_samples_));
      TF_RETURN_IF_ERROR(writer->WriteScalar(this->full_name("seed"), seed_));
      TF_RETURN_IF_ERROR(writer->WriteScalar(this->full_name("seed2"), seed2_));

      if (input_impl_) {
        TF_RETURN_IF_ERROR(SaveInput(writer, input_impl_));
      } else {
        TF_RETURN_IF_ERROR(
            writer->WriteScalar(full_name("input_impl_empty"), ""));
      }
      return Status::OK();
    }

    Status RestoreInternal(IteratorContext* ctx,
                           IteratorStateReader* reader) override {
      mutex_lock l(mu_);
      // Restore the random number generators.
      TF_RETURN_IF_ERROR(reader->ReadScalar(
          this->full_name("num_random_samples"), &num_random_samples_));
      TF_RETURN_IF_ERROR(reader->ReadScalar(this->full_name("seed"), &seed_));
      TF_RETURN_IF_ERROR(reader->ReadScalar(this->full_name("seed2"), &seed2_));
      ResetRngs();

      if (!reader->Contains(full_name("input_impl_empty"))) {
        TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_));
      } else {
        input_impl_.reset();
      }
      return Status::OK();
    }

    mutex mu_;
    int64 seed_ GUARDED_BY(mu_);
    int64 seed2_ GUARDED_BY(mu_);

   private:
    std::unique_ptr<IteratorBase> input_impl_ GUARDED_BY(mu_);

    float Random() {
      mutex_lock l(mu_);
      num_random_samples_++;
      uint32 random_uint = generator_();

      // PhiloxRandom returns 32-bit unsigned ints. Convert to float in [0,1)
      // using the same method that the RandomUniform op uses.
      return random::Uint32ToFloat(random_uint);
    }

    // random util
    random::PhiloxRandom parent_generator_ GUARDED_BY(mu_);
    random::SingleSampleAdapter<random::PhiloxRandom> generator_
        GUARDED_BY(mu_);
    int64 num_random_samples_ GUARDED_BY(mu_) = 0;
  };

  const float rate_;
  const int64 seed_, seed2_;
  const DatasetBase* const input_;
};  // SamplingDatasetOp::Dataset

SamplingDatasetOp::SamplingDatasetOp(OpKernelConstruction* ctx)
    : UnaryDatasetOpKernel(ctx) {}

// Create a new SamplingDatasetOp::Dataset, and return it as the output.
void SamplingDatasetOp::MakeDataset(OpKernelContext* ctx, DatasetBase* input,
                                    DatasetBase** output) {
  float rate;
  int64 seed;
  int64 seed2;
  OP_REQUIRES_OK(ctx, ParseScalarArgument<float>(ctx, kRate, &rate));
  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kSeed, &seed));
  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kSeed2, &seed2));

  if (seed == 0 && seed2 == 0) {
    seed = random::New64();
    seed2 = random::New64();
  }
  *output = new Dataset(ctx, rate, seed, seed2, input);
}

namespace {
REGISTER_KERNEL_BUILDER(Name("SamplingDataset").Device(DEVICE_CPU),
                        SamplingDatasetOp);
}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<commit_msg>Clean-up after merge<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/kernels/data/experimental/sampling_dataset_op.h"
#include "tensorflow/core/framework/dataset.h"
#include "tensorflow/core/framework/partial_tensor_shape.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/kernels/data/name_utils.h"
#include "tensorflow/core/lib/random/philox_random.h"
#include "tensorflow/core/lib/random/random.h"
#include "tensorflow/core/lib/random/random_distributions.h"
#include "tensorflow/core/lib/random/simple_philox.h"

namespace tensorflow {
namespace data {
namespace experimental {

// Constants declared in sampling_dataset_op.h and used both here and in test
// cases.
/* static */ constexpr const char* const SamplingDatasetOp::kDatasetType;
/* static */ constexpr const char* const SamplingDatasetOp::kInputDataset;
/* static */ constexpr const char* const SamplingDatasetOp::kRate;
/* static */ constexpr const char* const SamplingDatasetOp::kSeed;
/* static */ constexpr const char* const SamplingDatasetOp::kSeed2;
/* static */ constexpr const char* const SamplingDatasetOp::kOutputTypes;
/* static */ constexpr const char* const SamplingDatasetOp::kOutputShapes;

class SamplingDatasetOp::Dataset : public DatasetBase {
 public:
  Dataset(OpKernelContext* ctx, float rate, int64 seed, int64 seed2,
          const DatasetBase* input)
      : DatasetBase(DatasetContext(ctx)),
        rate_(rate),
        seed_(seed),
        seed2_(seed2),
        input_(input) {
    input_->Ref();
  }

  ~Dataset() override { input_->Unref(); }

  std::unique_ptr<IteratorBase> MakeIteratorInternal(
      const string& prefix) const override {
    return std::unique_ptr<IteratorBase>(
        new Iterator({this, name_utils::IteratorPrefix(kDatasetType, prefix)},
                     seed_, seed2_));
  }

  const DataTypeVector& output_dtypes() const override {
    return input_->output_dtypes();
  }

  const std::vector<PartialTensorShape>& output_shapes() const override {
    return input_->output_shapes();
  }

  string DebugString() const override {
    return name_utils::DatasetDebugString(kDatasetType);
  }

  Status CheckExternalState() const override {
    return input_->CheckExternalState();
  }

 protected:
  Status AsGraphDefInternal(SerializationContext* ctx,
                            DatasetGraphDefBuilder* b,
                            Node** output) const override {
    Node* input_graph_node = nullptr;
    TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node));
    Node* rate = nullptr;
    Node* seed = nullptr;
    Node* seed2 = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(rate_, &rate));
    TF_RETURN_IF_ERROR(b->AddScalar(seed_, &seed));
    TF_RETURN_IF_ERROR(b->AddScalar(seed2_, &seed2));
    TF_RETURN_IF_ERROR(
        b->AddDataset(this, {input_graph_node, rate, seed, seed2}, output));
    return Status::OK();
  }

 private:
  class Iterator : public DatasetIterator<Dataset> {
   public:
    explicit Iterator(const Params& params, int64 seed, int64 seed2)
        : DatasetIterator<Dataset>(params),
          seed_(seed),
          seed2_(seed2),
          parent_generator_(seed, seed2),
          generator_(&parent_generator_) {}

    Status Initialize(IteratorContext* ctx) override {
      return dataset()->input_->MakeIterator(ctx, prefix(), &input_impl_);
    }

    Status GetNextInternal(IteratorContext* ctx,
                           std::vector<Tensor>* out_tensors,
                           bool* end_of_sequence) override {
      bool rand_val_hit;
      do {
        {
          tf_shared_lock l(mu_);
          if (!input_impl_) {
            *end_of_sequence = true;
            return Status::OK();
          }
          TF_RETURN_IF_ERROR(
              input_impl_->GetNext(ctx, out_tensors, end_of_sequence));
        }
        if (*end_of_sequence) {
          mutex_lock l(mu_);
          input_impl_.reset();
          return Status::OK();
        }

        // generate a number from random uniform [0, 1)
        float rand_val = Random();
        rand_val_hit = rand_val < dataset()->rate_;
        if (!rand_val_hit) {
          // Clear the output tensor list since it doesn't match.
          out_tensors->clear();
        }
      } while (!rand_val_hit);
      *end_of_sequence = false;
      return Status::OK();
    }

   protected:
    void ResetRngs() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
      // Reset the generators based on the current iterator seeds.
      parent_generator_ = random::PhiloxRandom(seed_, seed2_);
      generator_ =
          random::SingleSampleAdapter<random::PhiloxRandom>(&parent_generator_);
      generator_.Skip(num_random_samples_);
    }

    Status SaveInternal(IteratorStateWriter* writer) override {
      mutex_lock l(mu_);
      // Save state needed to restore the random number generators.
      TF_RETURN_IF_ERROR(writer->WriteScalar(
          this->full_name("num_random_samples"), num_random_samples_));
      TF_RETURN_IF_ERROR(writer->WriteScalar(this->full_name("seed"), seed_));
      TF_RETURN_IF_ERROR(writer->WriteScalar(this->full_name("seed2"), seed2_));

      if (input_impl_) {
        TF_RETURN_IF_ERROR(SaveInput(writer, input_impl_));
      } else {
        TF_RETURN_IF_ERROR(
            writer->WriteScalar(full_name("input_impl_empty"), ""));
      }
      return Status::OK();
    }

    Status RestoreInternal(IteratorContext* ctx,
                           IteratorStateReader* reader) override {
      mutex_lock l(mu_);
      // Restore the random number generators.
      TF_RETURN_IF_ERROR(reader->ReadScalar(
          this->full_name("num_random_samples"), &num_random_samples_));
      TF_RETURN_IF_ERROR(reader->ReadScalar(this->full_name("seed"), &seed_));
      TF_RETURN_IF_ERROR(reader->ReadScalar(this->full_name("seed2"), &seed2_));
      ResetRngs();

      if (!reader->Contains(full_name("input_impl_empty"))) {
        TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_));
      } else {
        input_impl_.reset();
      }
      return Status::OK();
    }

    mutex mu_;
    int64 seed_ GUARDED_BY(mu_);
    int64 seed2_ GUARDED_BY(mu_);

   private:
    std::unique_ptr<IteratorBase> input_impl_ GUARDED_BY(mu_);

    float Random() {
      mutex_lock l(mu_);
      num_random_samples_++;
      uint32 random_uint = generator_();

      // PhiloxRandom returns 32-bit unsigned ints. Convert to float in [0,1)
      // using the same method that the RandomUniform op uses.
      return random::Uint32ToFloat(random_uint);
    }

    // random util
    random::PhiloxRandom parent_generator_ GUARDED_BY(mu_);
    random::SingleSampleAdapter<random::PhiloxRandom> generator_
        GUARDED_BY(mu_);
    int64 num_random_samples_ GUARDED_BY(mu_) = 0;
  };

  const float rate_;
  const int64 seed_, seed2_;
  const DatasetBase* const input_;
};  // SamplingDatasetOp::Dataset

SamplingDatasetOp::SamplingDatasetOp(OpKernelConstruction* ctx)
    : UnaryDatasetOpKernel(ctx) {}

// Create a new SamplingDatasetOp::Dataset, and return it as the output.
void SamplingDatasetOp::MakeDataset(OpKernelContext* ctx, DatasetBase* input,
                                    DatasetBase** output) {
  float rate;
  int64 seed;
  int64 seed2;
  OP_REQUIRES_OK(ctx, ParseScalarArgument<float>(ctx, kRate, &rate));
  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kSeed, &seed));
  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kSeed2, &seed2));

  if (seed == 0 && seed2 == 0) {
    seed = random::New64();
    seed2 = random::New64();
  }
  *output = new Dataset(ctx, rate, seed, seed2, input);
}

namespace {
REGISTER_KERNEL_BUILDER(Name("SamplingDataset").Device(DEVICE_CPU),
                        SamplingDatasetOp);
}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<|endoftext|>


<commit_before>// @(#)root/graf:$Name:  $:$Id: TASPluginGS.cxx,v 1.1 2005/07/05 12:36:05 brun Exp $
//  Author: Valeriy Onuchin   23/06/05

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TASPluginGS - allows to read PS/EPS/PDF files via GhostScript        //
//                                                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TASPluginGS.h"
#include "TSystem.h"

#ifndef WIN32
#   include <X11/Xlib.h>
#else
#   include "Windows4root.h"
#endif

extern "C" {
#ifndef WIN32
#   include <afterbase.h>
#else
#   include <win32/config.h>
#   include <win32/afterbase.h>
#   define X_DISPLAY_MISSING 1
#endif
#   include <import.h>
}

ClassImp(TASPluginGS)

//______________________________________________________________________________
TASPluginGS::TASPluginGS(const char *ext) : TASImagePlugin(ext)
{
   // ctor

   fInterpreter = gSystem->Which(gSystem->Getenv("PATH"), "gs", kExecutePermission);
}

//______________________________________________________________________________
TASPluginGS::~TASPluginGS()
{
   // dtor

   delete fInterpreter;
   fInterpreter = 0;
}

//______________________________________________________________________________
ASImage *TASPluginGS::File2ASImage(const char *filename)
{
   // read PS/EPS/PDF file and convert it to ASImage

   if (!fInterpreter) {
      Warning("File2ASImage", "GhostScript is not available");
      return 0;
   }

   if (gSystem->AccessPathName(filename)) {
      Warning("File2ASImage", "input file %s is not accessible", filename);
      return 0;
   }

   // command line to execute
   TString cmd = fInterpreter;
   cmd += " -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -dGraphicsAlphaBits=4 -sOutputFile=- ";
   cmd += filename;
   FILE *in = gSystem->OpenPipe(cmd.Data(), "r");

   if (!in) {
      return 0;
   }

   const UInt_t kBuffLength = 32768;
   static char buf[kBuffLength];
   TString raw;

   do {
      Long_t r = fread(&buf, 1, kBuffLength, in);
      raw.Append((const char*)&buf, r);
   } while (!feof(in));

   gSystem->ClosePipe(in);

   ASImageImportParams params;
   params.flags = 0;
   params.width = 0;
   params.height = 0 ;
   params.filter = SCL_DO_ALL;
   params.gamma = 0;
   params.gamma_table = 0;
   params.compression = 0;
   params.format = ASA_ASImage;
   params.search_path = 0;
   params.subimage = 0;

   ASImage *ret = PNGBuff2ASimage((CARD8 *)raw.Data(), &params);
   return ret;
}

<commit_msg>From Valeriy Onuchin:   When image is created from EPS file the size of image   is taken from BoundingBox values.<commit_after>// @(#)root/graf:$Name:  $:$Id: TASPluginGS.cxx,v 1.2 2005/07/05 18:09:22 brun Exp $
//  Author: Valeriy Onuchin   23/06/05

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TASPluginGS - allows to read PS/EPS/PDF files via GhostScript        //
//                                                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TASPluginGS.h"
#include "TSystem.h"

#ifndef WIN32
#   include <X11/Xlib.h>
#else
#   include "Windows4root.h"
#endif

extern "C" {
#ifndef WIN32
#   include <afterbase.h>
#else
#   include <win32/config.h>
#   include <win32/afterbase.h>
#   define X_DISPLAY_MISSING 1
#endif
#   include <import.h>
}

ClassImp(TASPluginGS)

//______________________________________________________________________________
TASPluginGS::TASPluginGS(const char *ext) : TASImagePlugin(ext)
{
   // ctor

   fInterpreter = gSystem->Which(gSystem->Getenv("PATH"), "gs", kExecutePermission);
}

//______________________________________________________________________________
TASPluginGS::~TASPluginGS()
{
   // dtor

   delete fInterpreter;
   fInterpreter = 0;
}

//______________________________________________________________________________
ASImage *TASPluginGS::File2ASImage(const char *filename)
{
   // read PS/EPS/PDF file and convert it to ASImage

   if (!fInterpreter) {
      Warning("File2ASImage", "GhostScript is not available");
      return 0;
   }

   if (gSystem->AccessPathName(filename)) {
      Warning("File2ASImage", "input file %s is not accessible", filename);
      return 0;
   }

   TString ext = (strrchr(filename, '.') + 1);
   ext.Strip();
   ext.ToLower();

   UInt_t width = 0;
   UInt_t height = 0;
   Bool_t eps = kFALSE;

   if (ext == "eps") {
      eps = kTRUE;
      FILE *fd = fopen(filename, "r");
      if (!fd) {
         Warning("File2ASImage", "input file %s is not readable", filename);
         return 0;
      }

      do {
         char buf[128];
         TString line = fgets(buf, 128, fd);
         if (line.IsNull() || !line.BeginsWith("%")) break;

         if (line.BeginsWith("%%BoundingBox:")) {
            int lx, ly, ux, uy;
            line = line(14, line.Length());
            sscanf(line.Data(), "%d %d %d %d", &lx, &ly, &ux, &uy);
            width = TMath::Abs(ux - lx);
            height = TMath::Abs(uy - ly);
            break;
         }
      } while (!feof(fd));

      fclose(fd);
   }

   // command line to execute
   TString cmd = fInterpreter;
   if (eps) {
      cmd += Form(" -g%dx%d", width, height);
   }
   cmd += " -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -dGraphicsAlphaBits=4 -sOutputFile=- ";
   cmd += filename;
   FILE *in = gSystem->OpenPipe(cmd.Data(), "r");

   if (!in) {
      return 0;
   }

   const UInt_t kBuffLength = 32768;
   static char buf[kBuffLength];
   TString raw;

   do {
      Long_t r = fread(&buf, 1, kBuffLength, in);
      raw.Append((const char*)&buf, r);
   } while (!feof(in));

   gSystem->ClosePipe(in);

   ASImageImportParams params;
   params.flags = width;
   params.width = height;
   params.height = 0 ;
   params.filter = SCL_DO_ALL;
   params.gamma = 0;
   params.gamma_table = 0;
   params.compression = 0;
   params.format = ASA_ASImage;
   params.search_path = 0;
   params.subimage = 0;

   ASImage *ret = PNGBuff2ASimage((CARD8 *)raw.Data(), &params);
   return ret;
}

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  imgui-metal.c
//  Since this will only need to compile with clang we can use
//  mix designated initializers and C++ code.
//------------------------------------------------------------------------------
#include "osxentry.h"
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "imgui.h"

const int WIDTH = 1024;
const int HEIGHT = 768;
const int MaxVertices = (1<<16);
const int MaxIndices = MaxVertices * 3;

uint64_t last_time = 0;
bool show_test_window = true;
bool show_another_window = false;

sg_pass_action pass_action;
sg_pipeline pip;
sg_bindings bind;

typedef struct {
    ImVec2 disp_size;
} vs_params_t;

static void draw_imgui(ImDrawData*);

void init(const void* mtl_device) {
    // setup sokol_gfx and sokol_time
    sg_desc desc = {
        .mtl_device = mtl_device,
        .mtl_renderpass_descriptor_cb = osx_mtk_get_render_pass_descriptor,
        .mtl_drawable_cb = osx_mtk_get_drawable
    };
    sg_setup(&desc);
    stm_setup();

    // setup the imgui environment
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGuiIO& io = ImGui::GetIO();
    io.IniFilename = nullptr;
    io.Fonts->AddFontDefault();
    io.KeyMap[ImGuiKey_Tab] = 0x30;
    io.KeyMap[ImGuiKey_LeftArrow] = 0x7B;
    io.KeyMap[ImGuiKey_RightArrow] = 0x7C;
    io.KeyMap[ImGuiKey_DownArrow] = 0x7D;
    io.KeyMap[ImGuiKey_UpArrow] = 0x7E;
    io.KeyMap[ImGuiKey_Home] = 0x73;
    io.KeyMap[ImGuiKey_End] = 0x77;
    io.KeyMap[ImGuiKey_Delete] = 0x75;
    io.KeyMap[ImGuiKey_Backspace] = 0x33;
    io.KeyMap[ImGuiKey_Enter] = 0x24;
    io.KeyMap[ImGuiKey_Escape] = 0x35;
    io.KeyMap[ImGuiKey_A] = 0x00;
    io.KeyMap[ImGuiKey_C] = 0x08;
    io.KeyMap[ImGuiKey_V] = 0x09;
    io.KeyMap[ImGuiKey_X] = 0x07;
    io.KeyMap[ImGuiKey_Y] = 0x10;
    io.KeyMap[ImGuiKey_Z] = 0x06;

    // OSX => ImGui input forwarding
    osx_mouse_pos([] (float x, float y) { ImGui::GetIO().MousePos = ImVec2(x, y); });
    osx_mouse_btn_down([] (int btn)     { ImGui::GetIO().MouseDown[btn] = true; });
    osx_mouse_btn_up([] (int btn)       { ImGui::GetIO().MouseDown[btn] = false; });
    osx_mouse_wheel([] (float v)        { ImGui::GetIO().MouseWheel = 0.25f * v; });
    osx_key_down([] (int key)           { if (key < 512) ImGui::GetIO().KeysDown[key] = true; });
    osx_key_up([] (int key)             { if (key < 512) ImGui::GetIO().KeysDown[key] = false; });
    osx_char([] (wchar_t c)             { ImGui::GetIO().AddInputCharacter(c); });

    // dynamic vertex- and index-buffers for ImGui-generated geometry
    sg_buffer_desc vbuf_desc = {
        .usage = SG_USAGE_STREAM,
        .size = MaxVertices * sizeof(ImDrawVert)
    };
    bind.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);
    sg_buffer_desc ibuf_desc = {
        .type = SG_BUFFERTYPE_INDEXBUFFER,
        .usage = SG_USAGE_STREAM,
        .size = MaxIndices * sizeof(ImDrawIdx)
    };
    bind.index_buffer = sg_make_buffer(&ibuf_desc);

    // font texture for ImGui's default font
    unsigned char* font_pixels;
    int font_width, font_height;
    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
    sg_image_desc img_desc = {
        .width = font_width,
        .height = font_height,
        .pixel_format = SG_PIXELFORMAT_RGBA8,
        .wrap_u = SG_WRAP_CLAMP_TO_EDGE,
        .wrap_v = SG_WRAP_CLAMP_TO_EDGE,
        .min_filter = SG_FILTER_LINEAR,
        .mag_filter = SG_FILTER_LINEAR,
        .content.subimage[0][0] = {
            .ptr = font_pixels,
            .size = font_width * font_height * 4
        }
    };
    bind.fs_images[0] = sg_make_image(&img_desc);

    // shader object for imgui renering
    sg_shader_desc shd_desc = {
        .vs.uniform_blocks[0].size = sizeof(vs_params_t),
        .vs.source =
            "#include <metal_stdlib>\n"
            "using namespace metal;\n"
            "struct params_t {\n"
            "  float2 disp_size;\n"
            "};\n"
            "struct vs_in {\n"
            "  float2 pos [[attribute(0)]];\n"
            "  float2 uv [[attribute(1)]];\n"
            "  float4 color [[attribute(2)]];\n"
            "};\n"
            "struct vs_out {\n"
            "  float4 pos [[position]];\n"
            "  float2 uv;\n"
            "  float4 color;\n"
            "};\n"
            "vertex vs_out _main(vs_in in [[stage_in]], constant params_t& params [[buffer(0)]]) {\n"
            "  vs_out out;\n"
            "  out.pos = float4(((in.pos / params.disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
            "  out.uv = in.uv;\n"
            "  out.color = in.color;\n"
            "  return out;\n"
            "}\n",
        .fs.images[0].type = SG_IMAGETYPE_2D,
        .fs.source =
            "#include <metal_stdlib>\n"
            "using namespace metal;\n"
            "struct fs_in {\n"
            "  float2 uv;\n"
            "  float4 color;\n"
            "};\n"
            "fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n"
            "  return tex.sample(smp, in.uv) * in.color;\n"
            "}\n"
    };
    sg_shader shd = sg_make_shader(&shd_desc);

    // pipeline object for imgui rendering
    sg_pipeline_desc pip_desc = {
        .layout = {
            .buffers[0].stride = sizeof(ImDrawVert),
            .attrs = {
                [0] = { .offset=offsetof(ImDrawVert,pos), .format=SG_VERTEXFORMAT_FLOAT2 },
                [1] = { .offset=offsetof(ImDrawVert,uv), .format=SG_VERTEXFORMAT_FLOAT2 },
                [2] = { .offset=offsetof(ImDrawVert,col), .format=SG_VERTEXFORMAT_UBYTE4N }
            }
        },
        .shader = shd,
        .index_type = SG_INDEXTYPE_UINT16,
        .blend = {
            .enabled = true,
            .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
            .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
            .color_write_mask = SG_COLORMASK_RGB
        }
    };
    pip = sg_make_pipeline(&pip_desc);

    // initial clear color
    pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.0f, 0.5f, 0.7f, 1.0f } }
    };
}

void frame() {
    const int width = osx_width();
    const int height = osx_height();

    ImGuiIO& io = ImGui::GetIO();
    io.DisplaySize = ImVec2(width, height);
    io.DeltaTime = (float) stm_sec(stm_laptime(&last_time));
    ImGui::NewFrame();

    // 1. Show a simple window
    // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
    static float f = 0.0f;
    ImGui::Text("Hello, world!");
    ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
    ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
    if (ImGui::Button("Test Window")) show_test_window ^= 1;
    if (ImGui::Button("Another Window")) show_another_window ^= 1;
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    // 2. Show another simple window, this time using an explicit Begin/End pair
    if (show_another_window) {
        ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver);
        ImGui::Begin("Another Window", &show_another_window);
        ImGui::Text("Hello");
        ImGui::End();
    }

    // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
    if (show_test_window) {
        ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiCond_FirstUseEver);
        ImGui::ShowTestWindow();
    }

    // the sokol draw pass
    sg_begin_default_pass(&pass_action, width, height);
    ImGui::Render();
    draw_imgui(ImGui::GetDrawData());
    sg_end_pass();
    sg_commit();
}

void shutdown() {
    ImGui::DestroyContext();
    sg_shutdown();
}

int main() {
    osx_start(WIDTH, HEIGHT, 1, "Sokol Dear ImGui (Metal)", init, frame, shutdown);
    return 0;
}

void draw_imgui(ImDrawData* draw_data) {
    assert(draw_data);
    if (draw_data->CmdListsCount == 0) {
        return;
    }

    // render the command list
    sg_apply_pipeline(pip);
    vs_params_t vs_params;
    vs_params.disp_size.x = ImGui::GetIO().DisplaySize.x;
    vs_params.disp_size.y = ImGui::GetIO().DisplaySize.y;
    sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
    for (int cl_index = 0; cl_index < draw_data->CmdListsCount; cl_index++) {
        const ImDrawList* cl = draw_data->CmdLists[cl_index];

        // append vertices and indices to buffers, record start offsets in bindings
        const int vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
        const int idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
        const int vb_offset = sg_append_buffer(bind.vertex_buffers[0], &cl->VtxBuffer.front(), vtx_size);
        const int ib_offset = sg_append_buffer(bind.index_buffer, &cl->IdxBuffer.front(), idx_size);
        /* don't render anything if the buffer is in overflow state (this is also
            checked internally in sokol_gfx, draw calls that attempt from
            overflowed buffers will be silently dropped)
        */
        if (sg_query_buffer_overflow(bind.vertex_buffers[0]) ||
            sg_query_buffer_overflow(bind.index_buffer))
        {
            continue;
        }
        bind.vertex_buffer_offsets[0] = vb_offset;
        bind.index_buffer_offset = ib_offset;
        sg_apply_bindings(&bind);

        int base_element = 0;
        for (const ImDrawCmd& pcmd : cl->CmdBuffer) {
            if (pcmd.UserCallback) {
                pcmd.UserCallback(cl, &pcmd);
            }
            else {
                const int scissor_x = (int) (pcmd.ClipRect.x);
                const int scissor_y = (int) (pcmd.ClipRect.y);
                const int scissor_w = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
                const int scissor_h = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
                sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
                sg_draw(base_element, pcmd.ElemCount, 1);
            }
            base_element += pcmd.ElemCount;
        }
    }
}
<commit_msg>fix the imgui-metal sample to use sokol_imgui.h with SOKOL_IMGUI_NO_SOKOL_APP<commit_after>//------------------------------------------------------------------------------
//  imgui-metal.c
//  Since this will only need to compile with clang we can
//  mix C99 designated initializers and C++ code.
//
//  NOTE: this demo is using the sokol_imgui.h utility header which
//  implements a renderer for Dear ImGui on top of sokol_gfx.h, but without
//  sokol_app.h (via the config define SOKOL_IMGUI_NO_SOKOL_APP).
//------------------------------------------------------------------------------
#include "osxentry.h"
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "imgui.h"
#define SOKOL_METAL
#define SOKOL_IMGUI_IMPL
#define SOKOL_IMGUI_NO_SOKOL_APP
#include "sokol_imgui.h"

static const int WIDTH = 1024;
static const int HEIGHT = 768;

static uint64_t last_time = 0;
static bool show_test_window = true;
static bool show_another_window = false;
static sg_pass_action pass_action;

void init(const void* mtl_device) {
    // setup sokol_gfx and sokol_time
    sg_desc desc = {
        .mtl_device = mtl_device,
        .mtl_renderpass_descriptor_cb = osx_mtk_get_render_pass_descriptor,
        .mtl_drawable_cb = osx_mtk_get_drawable
    };
    sg_setup(&desc);
    stm_setup();
    simgui_desc_t simgui_desc = { };
    simgui_setup(&simgui_desc);

    // setup the imgui environment
    ImGuiIO& io = ImGui::GetIO();
    io.KeyMap[ImGuiKey_Tab] = 0x30;
    io.KeyMap[ImGuiKey_LeftArrow] = 0x7B;
    io.KeyMap[ImGuiKey_RightArrow] = 0x7C;
    io.KeyMap[ImGuiKey_DownArrow] = 0x7D;
    io.KeyMap[ImGuiKey_UpArrow] = 0x7E;
    io.KeyMap[ImGuiKey_Home] = 0x73;
    io.KeyMap[ImGuiKey_End] = 0x77;
    io.KeyMap[ImGuiKey_Delete] = 0x75;
    io.KeyMap[ImGuiKey_Backspace] = 0x33;
    io.KeyMap[ImGuiKey_Enter] = 0x24;
    io.KeyMap[ImGuiKey_Escape] = 0x35;
    io.KeyMap[ImGuiKey_A] = 0x00;
    io.KeyMap[ImGuiKey_C] = 0x08;
    io.KeyMap[ImGuiKey_V] = 0x09;
    io.KeyMap[ImGuiKey_X] = 0x07;
    io.KeyMap[ImGuiKey_Y] = 0x10;
    io.KeyMap[ImGuiKey_Z] = 0x06;

    // OSX => ImGui input forwarding
    osx_mouse_pos([] (float x, float y) { ImGui::GetIO().MousePos = ImVec2(x, y); });
    osx_mouse_btn_down([] (int btn)     { ImGui::GetIO().MouseDown[btn] = true; });
    osx_mouse_btn_up([] (int btn)       { ImGui::GetIO().MouseDown[btn] = false; });
    osx_mouse_wheel([] (float v)        { ImGui::GetIO().MouseWheel = 0.25f * v; });
    osx_key_down([] (int key)           { if (key < 512) ImGui::GetIO().KeysDown[key] = true; });
    osx_key_up([] (int key)             { if (key < 512) ImGui::GetIO().KeysDown[key] = false; });
    osx_char([] (wchar_t c)             { ImGui::GetIO().AddInputCharacter(c); });

    // initial clear color
    pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.0f, 0.5f, 0.7f, 1.0f } }
    };
}

void frame() {
    const int width = osx_width();
    const int height = osx_height();
    simgui_new_frame(width, height, stm_laptime(&last_time));

    // 1. Show a simple window
    // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
    static float f = 0.0f;
    ImGui::Text("Hello, world!");
    ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
    ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
    if (ImGui::Button("Test Window")) show_test_window ^= 1;
    if (ImGui::Button("Another Window")) show_another_window ^= 1;
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    // 2. Show another simple window, this time using an explicit Begin/End pair
    if (show_another_window) {
        ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver);
        ImGui::Begin("Another Window", &show_another_window);
        ImGui::Text("Hello");
        ImGui::End();
    }

    // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
    if (show_test_window) {
        ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiCond_FirstUseEver);
        ImGui::ShowTestWindow();
    }

    // the sokol draw pass
    sg_begin_default_pass(&pass_action, width, height);
    simgui_render();
    sg_end_pass();
    sg_commit();
}

void shutdown() {
    simgui_shutdown();
    sg_shutdown();
}

int main() {
    osx_start(WIDTH, HEIGHT, 1, "Sokol Dear ImGui (Metal)", init, frame, shutdown);
    return 0;
}
<|endoftext|>


<commit_before>#include "Queen.h"

Queen::Queen(std::string url)
:
	current_depth(0),
	max_depth(Manager::instance().Config->depth)
{
	url_pool.push_back(url);
	crawl();
	save_data();
}

void Queen::crawl()
{
	while (current_depth++ <= max_depth && !(url_pool.empty()))
	{
		if (Manager::instance().Config->debug)
		{
			std::cout << "Crawling depth: " << current_depth << " out of " << max_depth << '\n';
		}
		check_url_pool();
		bool gather_urls = (current_depth < max_depth? true : false);
		add_to_visited();
		string_deque urls_to_send;
		std::copy(url_pool.begin(), url_pool.end(), std::back_inserter(urls_to_send));
		url_pool.clear();
		Spider child(urls_to_send, &url_pool, &data_pool, gather_urls);
		child.crawl_list();
	}

}

void Queen::check_url_pool()
{
	for (auto it = url_pool.begin(); it != url_pool.end(); ++it)
	{
		// If we are being polite
		if (Manager::instance().Config->polite)
		{
			std::string host = utility_tools::get_host(*it);
			auto exclusion_search = exclusion_list.find(host);
			if (exclusion_search != exclusion_list.end())
			{
				std::string path = utility_tools::get_path(*it);
				for (auto i : exclusion_search->second)
				{
					if (path.substr(0, i.length()) == i)
					{
						it = url_pool.erase(it);
						std::cout << "Host: " << host << " Path: " << path << " found in exclusion list. Skipping...\n";
						break;
					}
				}
			}
			else
			{
				std::cout << "Fetching robots.txt from " << host<< '\n';
				read_robots_txt(*it);
			}
		}
		// Remove duplicates
		auto visited_search = urls_visited.find(*it);
		if (visited_search != urls_visited.end())
		{
			it = url_pool.erase(it);
		}
	}
}

void Queen::read_robots_txt(std::string url)
{
	std::string host = utility_tools::get_host(url);
	Robot_Spider robo(host, &exclusion_list);
}

void Queen::add_to_visited()
{
	std::copy(url_pool.begin(), url_pool.end(), std::inserter(urls_visited, urls_visited.end()));
}

void Queen::save_data()
{
	Manager::instance().WriteToFile(data_pool);
}

<commit_msg>Avoiding loops with links<commit_after>#include "Queen.h"

Queen::Queen(std::string url)
:
	current_depth(0),
	max_depth(Manager::instance().Config->depth)
{
	url_pool.push_back(url);
	crawl();
	save_data();
}

void Queen::crawl()
{
	while (current_depth++ <= max_depth && !(url_pool.empty()))
	{
		if (Manager::instance().Config->debug)
		{
			std::cout << "Crawling depth: " << current_depth << " out of " << max_depth << '\n';
		}
		check_url_pool();
		bool gather_urls = (current_depth < max_depth? true : false);
		add_to_visited();
		string_deque urls_to_send;
		std::copy(url_pool.begin(), url_pool.end(), std::back_inserter(urls_to_send));
		url_pool.clear();
		Spider child(urls_to_send, &url_pool, &data_pool, gather_urls);
		child.crawl_list();
	}

}

void Queen::check_url_pool()
{
	for (auto it = url_pool.begin(); it != url_pool.end(); ++it)
	{
		// Remove duplicates
		auto visited_search = urls_visited.find(*it);
		if (visited_search != urls_visited.end())
		{
			it = url_pool.erase(it);
		}
		// If we are being polite
		else if (Manager::instance().Config->polite)
		{
			std::string host = utility_tools::get_host(*it);
			auto exclusion_search = exclusion_list.find(host);
			if (exclusion_search != exclusion_list.end())
			{
				std::string path = utility_tools::get_path(*it);
				for (auto i : exclusion_search->second)
				{
					if (path.compare(0, i.length(), i) == 0)
					{
						it = url_pool.erase(it);
						std::cout << "Host: " << host << " Path: " << path << " found in exclusion list. Skipping...\n";
						break;
					}
				}
			}
			else
			{
				std::cout << "Fetching robots.txt from " << host<< '\n';
				read_robots_txt(*it);
				urls_visited.insert(host +"/robots.txt");

			}
		}
	}
}

void Queen::read_robots_txt(std::string url)
{
	std::string host = utility_tools::get_host(url);
	Robot_Spider robo(host, &exclusion_list);
}

void Queen::add_to_visited()
{
	std::copy(url_pool.begin(), url_pool.end(), std::inserter(urls_visited, urls_visited.end()));
}

void Queen::save_data()
{
	Manager::instance().WriteToFile(data_pool);
}

<|endoftext|>


<commit_before>#ifndef MJOLNIR_READ_OBSERVER
#define MJOLNIR_READ_OBSERVER
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/Observer.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

template<typename traitsT>
Observer<traitsT>
read_observer(const toml::table& root)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_observer(), 0);

    const auto& files  = toml::find<toml::value>(root, "files");
    const auto& output = toml::find<toml::value>(files, "output");

    std::string output_path("./");
    if(toml::get<toml::table>(output).count("path") == 1)
    {
        output_path = toml::find<std::string>(output, "path");
        if(output_path.back() != '/') {output_path += '/';}
    }
    const auto output_prefix = toml::find<std::string>(output, "prefix");
    MJOLNIR_LOG_NOTICE("output files are `", output_path, output_prefix, ".*`");

    return Observer<traitsT>(output_path + output_prefix);
}

} // mjolnir
#endif// MJOLNIR_READ_OBSERVER
<commit_msg>read files.output.progress_bar = true/false<commit_after>#ifndef MJOLNIR_READ_OBSERVER
#define MJOLNIR_READ_OBSERVER
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/Observer.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

template<typename traitsT>
Observer<traitsT>
read_observer(const toml::table& root)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_observer(), 0);

    const auto& files  = toml::find<toml::value>(root, "files");
    const auto& output = toml::find<toml::value>(files, "output");

    const auto progress_bar = toml::expect<bool>(output, "progress_bar")
                                                .unwrap_or(true);

    std::string output_path("./");
    if(toml::get<toml::table>(output).count("path") == 1)
    {
        output_path = toml::find<std::string>(output, "path");
        if(output_path.back() != '/') {output_path += '/';}
    }
    const auto output_prefix = toml::find<std::string>(output, "prefix");
    MJOLNIR_LOG_NOTICE("output files are `", output_path, output_prefix, ".*`");

    return Observer<traitsT>(output_path + output_prefix, progress_bar);
}

} // mjolnir
#endif// MJOLNIR_READ_OBSERVER
<|endoftext|>