<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "WrapHelper.h"

#include "../base/GeomHelper.h"
#include "../base/OSHelper.h"
#include "../base/XMLHelper.h"
#include "../base/Logger.h"
#include "../player/MessageID.h"
#include "../player/TestHelper.h"
#include "../player/VideoWriter.h"
#include "../player/SVG.h"

using namespace boost::python;
using namespace avg;
using namespace std;

namespace bp = boost::python;

// [todo] - remove after releasing libavg-v2.0.0
size_t getMemoryUsageDeprecated()
{
    avgDeprecationWarning("1.9.0", "avg.getMemoryUsage", "player.getMemoryUsage");
    return getMemoryUsage();
}

bool pointInPolygonDepcrecated(const glm::vec2& pt, const std::vector<glm::vec2>& poly)
{
    avgDeprecationWarning("1.9.0", "avg.pointInPolygon", "Point2D.isInPolygon");
    return pointInPolygon(pt, poly);
}
// end remove

class SeverityScopeHelper{};
class CategoryScopeHelper{};

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(TestHelper_fakeTouchEvent_overloads,
        fakeTouchEvent, 4, 5)

void export_misc()
{
    // [todo] - remove after releasing libavg-v2.0.0
    def("getMemoryUsage", getMemoryUsageDeprecated);
    def("pointInPolygon", pointInPolygonDepcrecated);
    // end remove

    def("validateXml", validateXml);

    class_<MessageID>("MessageID", no_init)
        .def("__repr__", &MessageID::getRepr)
    ;

    {
       scope loggerScope = class_<Logger, boost::noncopyable>("Logger", no_init)
            .def("addSink", addPythonLogger)
            .def("removeSink", removePythonLogger)
            .def("removeStdLogSink", &Logger::removeStdLogSink)
            .def("configureCategory", &Logger::configureCategory,
                    (bp::arg("severity")=Logger::severity::NONE))
            .def("getCategories", &Logger::getCategories)
            .def("trace", pytrace,
                    (bp::arg("severity")=Logger::severity::INFO))
            .def("debug", &Logger::logDebug,
                    (bp::arg("category")=Logger::category::APP))
            .def("info", &Logger::logInfo,
                    (bp::arg("category")=Logger::category::APP))
            .def("warning", &Logger::logWarning,
                    (bp::arg("category")=Logger::category::APP))
            .def("error", &Logger::logError,
                    (bp::arg("category")=Logger::category::APP))
            .def("critical", &Logger::logCritical,
                    (bp::arg("category")=Logger::category::APP))
            .def("log", &Logger::log,
                    (bp::arg("category")=Logger::category::APP,
                     bp::arg("severity")=Logger::severity::INFO))
       ;
        {
            scope severityScope = class_<SeverityScopeHelper>("Severity");
            severityScope.attr("CRIT") = Logger::severity::CRITICAL;
            severityScope.attr("ERR") = Logger::severity::ERROR;
            severityScope.attr("WARN") = Logger::severity::WARNING;
            severityScope.attr("INFO") = Logger::severity::INFO;
            severityScope.attr("DBG") = Logger::severity::DEBUG;
            severityScope.attr("NONE") = Logger::severity::NONE;
        }
        {
            scope categoryScope = class_<CategoryScopeHelper>("Category");
            categoryScope.attr("APP") = Logger::category::APP;
            categoryScope.attr("CONFIG") = Logger::category::CONFIG;
            categoryScope.attr("DEPREC") = Logger::category::DEPRECATION;
            categoryScope.attr("EVENTS") = Logger::category::EVENTS;
            categoryScope.attr("MEMORY") = Logger::category::MEMORY;
            categoryScope.attr("NONE") = Logger::category::NONE;
            categoryScope.attr("PROFILE") = Logger::category::PROFILE;
            categoryScope.attr("PROFILE_V") = Logger::category::PROFILE_VIDEO;
            categoryScope.attr("PLUGIN") = Logger::category::PLUGIN;
            categoryScope.attr("PLAYER") = Logger::category::PLAYER;
            categoryScope.attr("SHADER") = Logger::category::SHADER;
        }
    }

    scope().attr("logger") = boost::python::ptr(Logger::get());

    class_<TestHelper>("TestHelper", no_init)
        .def("fakeMouseEvent", &TestHelper::fakeMouseEvent)
        .def("fakeMouseWheelEvent", &TestHelper::fakeMouseWheelEvent)
        .def("fakeTouchEvent", &TestHelper::fakeTouchEvent,
                TestHelper_fakeTouchEvent_overloads())
        .def("fakeTangibleEvent", &TestHelper::fakeTangibleEvent)
        .def("fakeKeyEvent", &TestHelper::fakeKeyEvent)
        .def("dumpObjects", &TestHelper::dumpObjects)
        .def("getObjectCount", &TestHelper::getObjectCount)
    ;

    class_<VideoWriter, boost::shared_ptr<VideoWriter>, boost::noncopyable>
            ("VideoWriter", no_init)
        .def(init<CanvasPtr, const std::string&, int, int, int, bool>())
        .def(init<CanvasPtr, const std::string&, int, int, int>())
        .def(init<CanvasPtr, const std::string&, int>())
        .def("stop", &VideoWriter::stop)
        .def("pause", &VideoWriter::pause)
        .def("play", &VideoWriter::play)
        .add_property("filename", &VideoWriter::getFileName)
        .add_property("framerate", &VideoWriter::getFramerate)
        .add_property("qmin", &VideoWriter::getQMin)
        .add_property("qmax", &VideoWriter::getQMax)
    ;

    BitmapPtr (SVG::*renderElement1)(const UTF8String&) = &SVG::renderElement;
    BitmapPtr (SVG::*renderElement2)(const UTF8String&, const glm::vec2&) =
            &SVG::renderElement;
    BitmapPtr (SVG::*renderElement3)(const UTF8String&, float) =
            &SVG::renderElement;
    NodePtr (SVG::*createImageNode1)(const UTF8String&, const dict&) =
            &SVG::createImageNode;
    NodePtr (SVG::*createImageNode2)(const UTF8String&, const dict&, const glm::vec2&) =
            &SVG::createImageNode;
    NodePtr (SVG::*createImageNode3)(const UTF8String&, const dict&, float) =
            &SVG::createImageNode;

    class_<SVG, boost::noncopyable>("SVG", no_init)
        .def(init<const UTF8String&>())
        .def(init<const UTF8String&, bool>())
        .def("renderElement", renderElement1)
        .def("renderElement", renderElement2)
        .def("renderElement", renderElement3)
        .def("createImageNode", createImageNode1)
        .def("createImageNode", createImageNode2)
        .def("createImageNode", createImageNode3)
        .def("getElementPos", &SVG::getElementPos)
        .def("getElementSize", &SVG::getElementSize)
        ;

}

<commit_msg>Make VideoWriter framerate optional (as stated in reference)<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "WrapHelper.h"

#include "../base/GeomHelper.h"
#include "../base/OSHelper.h"
#include "../base/XMLHelper.h"
#include "../base/Logger.h"
#include "../player/MessageID.h"
#include "../player/TestHelper.h"
#include "../player/VideoWriter.h"
#include "../player/SVG.h"

using namespace boost::python;
using namespace avg;
using namespace std;

namespace bp = boost::python;

// [todo] - remove after releasing libavg-v2.0.0
size_t getMemoryUsageDeprecated()
{
    avgDeprecationWarning("1.9.0", "avg.getMemoryUsage", "player.getMemoryUsage");
    return getMemoryUsage();
}

bool pointInPolygonDepcrecated(const glm::vec2& pt, const std::vector<glm::vec2>& poly)
{
    avgDeprecationWarning("1.9.0", "avg.pointInPolygon", "Point2D.isInPolygon");
    return pointInPolygon(pt, poly);
}
// end remove

class SeverityScopeHelper{};
class CategoryScopeHelper{};

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(TestHelper_fakeTouchEvent_overloads,
        fakeTouchEvent, 4, 5)

void export_misc()
{
    // [todo] - remove after releasing libavg-v2.0.0
    def("getMemoryUsage", getMemoryUsageDeprecated);
    def("pointInPolygon", pointInPolygonDepcrecated);
    // end remove

    def("validateXml", validateXml);

    class_<MessageID>("MessageID", no_init)
        .def("__repr__", &MessageID::getRepr)
    ;

    {
       scope loggerScope = class_<Logger, boost::noncopyable>("Logger", no_init)
            .def("addSink", addPythonLogger)
            .def("removeSink", removePythonLogger)
            .def("removeStdLogSink", &Logger::removeStdLogSink)
            .def("configureCategory", &Logger::configureCategory,
                    (bp::arg("severity")=Logger::severity::NONE))
            .def("getCategories", &Logger::getCategories)
            .def("trace", pytrace,
                    (bp::arg("severity")=Logger::severity::INFO))
            .def("debug", &Logger::logDebug,
                    (bp::arg("category")=Logger::category::APP))
            .def("info", &Logger::logInfo,
                    (bp::arg("category")=Logger::category::APP))
            .def("warning", &Logger::logWarning,
                    (bp::arg("category")=Logger::category::APP))
            .def("error", &Logger::logError,
                    (bp::arg("category")=Logger::category::APP))
            .def("critical", &Logger::logCritical,
                    (bp::arg("category")=Logger::category::APP))
            .def("log", &Logger::log,
                    (bp::arg("category")=Logger::category::APP,
                     bp::arg("severity")=Logger::severity::INFO))
       ;
        {
            scope severityScope = class_<SeverityScopeHelper>("Severity");
            severityScope.attr("CRIT") = Logger::severity::CRITICAL;
            severityScope.attr("ERR") = Logger::severity::ERROR;
            severityScope.attr("WARN") = Logger::severity::WARNING;
            severityScope.attr("INFO") = Logger::severity::INFO;
            severityScope.attr("DBG") = Logger::severity::DEBUG;
            severityScope.attr("NONE") = Logger::severity::NONE;
        }
        {
            scope categoryScope = class_<CategoryScopeHelper>("Category");
            categoryScope.attr("APP") = Logger::category::APP;
            categoryScope.attr("CONFIG") = Logger::category::CONFIG;
            categoryScope.attr("DEPREC") = Logger::category::DEPRECATION;
            categoryScope.attr("EVENTS") = Logger::category::EVENTS;
            categoryScope.attr("MEMORY") = Logger::category::MEMORY;
            categoryScope.attr("NONE") = Logger::category::NONE;
            categoryScope.attr("PROFILE") = Logger::category::PROFILE;
            categoryScope.attr("PROFILE_V") = Logger::category::PROFILE_VIDEO;
            categoryScope.attr("PLUGIN") = Logger::category::PLUGIN;
            categoryScope.attr("PLAYER") = Logger::category::PLAYER;
            categoryScope.attr("SHADER") = Logger::category::SHADER;
        }
    }

    scope().attr("logger") = boost::python::ptr(Logger::get());

    class_<TestHelper>("TestHelper", no_init)
        .def("fakeMouseEvent", &TestHelper::fakeMouseEvent)
        .def("fakeMouseWheelEvent", &TestHelper::fakeMouseWheelEvent)
        .def("fakeTouchEvent", &TestHelper::fakeTouchEvent,
                TestHelper_fakeTouchEvent_overloads())
        .def("fakeTangibleEvent", &TestHelper::fakeTangibleEvent)
        .def("fakeKeyEvent", &TestHelper::fakeKeyEvent)
        .def("dumpObjects", &TestHelper::dumpObjects)
        .def("getObjectCount", &TestHelper::getObjectCount)
    ;

    class_<VideoWriter, boost::shared_ptr<VideoWriter>, boost::noncopyable>
            ("VideoWriter", no_init)
        .def(init<CanvasPtr, const std::string&, int, int, int, bool>())
        .def(init<CanvasPtr, const std::string&, int, int, int>())
        .def(init<CanvasPtr, const std::string&, int>())
        .def(init<CanvasPtr, const std::string&>())
        .def("stop", &VideoWriter::stop)
        .def("pause", &VideoWriter::pause)
        .def("play", &VideoWriter::play)
        .add_property("filename", &VideoWriter::getFileName)
        .add_property("framerate", &VideoWriter::getFramerate)
        .add_property("qmin", &VideoWriter::getQMin)
        .add_property("qmax", &VideoWriter::getQMax)
    ;

    BitmapPtr (SVG::*renderElement1)(const UTF8String&) = &SVG::renderElement;
    BitmapPtr (SVG::*renderElement2)(const UTF8String&, const glm::vec2&) =
            &SVG::renderElement;
    BitmapPtr (SVG::*renderElement3)(const UTF8String&, float) =
            &SVG::renderElement;
    NodePtr (SVG::*createImageNode1)(const UTF8String&, const dict&) =
            &SVG::createImageNode;
    NodePtr (SVG::*createImageNode2)(const UTF8String&, const dict&, const glm::vec2&) =
            &SVG::createImageNode;
    NodePtr (SVG::*createImageNode3)(const UTF8String&, const dict&, float) =
            &SVG::createImageNode;

    class_<SVG, boost::noncopyable>("SVG", no_init)
        .def(init<const UTF8String&>())
        .def(init<const UTF8String&, bool>())
        .def("renderElement", renderElement1)
        .def("renderElement", renderElement2)
        .def("renderElement", renderElement3)
        .def("createImageNode", createImageNode1)
        .def("createImageNode", createImageNode2)
        .def("createImageNode", createImageNode3)
        .def("getElementPos", &SVG::getElementPos)
        .def("getElementSize", &SVG::getElementSize)
        ;

}

<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee Modules --- Error Page
 *
 * The Error Page module allows the user to select a custom error page.
 *
 * @author Sam Baskinger <sbaskinger@qualys.com>
 */

#include "ironbee_config_auto.h"

#include <ironbeepp/configuration_directives.hpp>
#include <ironbeepp/configuration_parser.hpp>
#include <ironbeepp/c_trampoline.hpp>
#include <ironbeepp/module.hpp>
#include <ironbeepp/module_bootstrap.hpp>
#include <ironbeepp/module_delegate.hpp>
#include <ironbeepp/transaction.hpp>

#include <ironbee/rule_engine.h>
#include <ironbee/string.h>
#include <ironbee/path.h>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/iostreams/device/mapped_file.hpp>

/* Enable PRId64 printf. */
extern "C" {
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
}

/**
 * Error Page Module implementation.
 */
class ErrorPageModule : public IronBee::ModuleDelegate
{
public:
    /**
     * A version of @ref ib_rule_error_page_fn_t without the callback data.
     *
     * This will be used by @ref IronBee::make_c_trampoline to replace
     * IronBee's default error page function.
     *
     * @param[in] tx The transaction.
     * @param[out] page A pointer to the error page.
     * @param[out] page_sz The length of @a page.
     */
    typedef ib_status_t(error_page_fn_t)(
        ib_tx_t        *tx,
        const uint8_t **page,
        size_t         *page_sz);
    /**
     * Constructor.
     *
     * @param[in] module The IronBee++ module.
     */
    explicit ErrorPageModule(IronBee::Module module);

private:

    /**
     * Member to store the C trampoline information.
     *
     * Note that m_trampoline_pair.second must be destroyed.
     */
    std::pair<ib_rule_error_page_fn_t, void*> m_trampoline_pair;

    /**
     * Holds callback data associated with @ref ib_rule_error_page_fn_t.
     *
     * This member ensures that IronBee::delete_c_trampoline is called.
     */
    boost::shared_ptr<void> m_trampoline_data;

    /**
     * Produce an error page for the given transaction.
     *
     * @param[in] tx The transaction.
     * @param[out] page The page data is placed here.
     * @param[out] page_sz The page size is placed here.
     *
     * @returns
     * - IB_OK On success.
     * - IB_DECLINED If the error page is not available but not because
     *               of an error.
     * - Other on error.
     */
    ib_status_t error_page_fn(
        ib_tx_t        *tx,
        const uint8_t **page,
        size_t         *page_sz);

    /**
     * Implement the HTTP Status Code directive.
     *
     * @param[in] cp Configuration parser.
     * @param[in] name The directive.
     * @param[in] param1 The status code.
     * @param[in] param2 The error page file name.
     *
     * @throws @ref IronBee::exception.
     */
    void httpStatusCodeContentsDirective(
        IronBee::ConfigurationParser  cp,
        const char                   *name,
        const char                   *param1,
        const char                   *param2);
};

IBPP_BOOTSTRAP_MODULE_DELEGATE("ErrorPageModule", ErrorPageModule);

/**
 * A map from the status number to a file name.
 */
typedef std::map<ib_num_t, std::string> status_to_file_map_t;

/**
 * Context configuration value for the ErrorPageModule.
 */
struct ErrorPageCtxConfig {

    /**
     * The mapping from an HTTP status code to the file to return.
     */
    status_to_file_map_t status_to_file;

    /**
     * The mapping from an HTTP status code to the memory mapped file.
     */
    std::map<ib_num_t, boost::iostreams::mapped_file_source>
        status_to_mapped_file_source;
};

/* Implementation */

ErrorPageModule::ErrorPageModule(IronBee::Module module):
    /* Initialize the parent. */
    IronBee::ModuleDelegate(module),

    /* Build the C callback for ib_rule_set_error_page_fn(). */
    m_trampoline_pair(
        IronBee::make_c_trampoline<error_page_fn_t>(
            boost::bind(&ErrorPageModule::error_page_fn, this, _1, _2, _3))),

    m_trampoline_data(
        m_trampoline_pair.second,
        IronBee::delete_c_trampoline)
{

    /* Register the callback with the IronBee engine. */
    ib_rule_set_error_page_fn(
        module.engine().ib(),
        m_trampoline_pair.first,
        m_trampoline_pair.second);

    /* Setup the directive callbacks. */
    module.engine().register_configuration_directives().
        param2(
            "HttpStatusCodeContents",
            boost::bind(
                &ErrorPageModule::httpStatusCodeContentsDirective,
                this, _1, _2, _3, _4));

    module.set_configuration_data<ErrorPageCtxConfig>();
}

void ErrorPageModule::httpStatusCodeContentsDirective(
        IronBee::ConfigurationParser  cp,
        const char                   *name,
        const char                   *param1,
        const char                   *param2)
{
    ib_num_t     num;

    ErrorPageCtxConfig &cfg =
        module().configuration_data<ErrorPageCtxConfig>(cp.current_context());

    /* Convert the incoming parameter. */
    IronBee::throw_if_error(ib_string_to_num(param1, 10, &num));

    /* Set the mapping in the context configuration. */
    cfg.status_to_file[num] = ib_util_relative_file(
        ib_engine_pool_config_get(cp.engine().ib()),
        cp.current_file(),
        param2
    );

    try {
        cfg.status_to_mapped_file_source[num] =
            boost::iostreams::mapped_file_source(cfg.status_to_file[num]);
    }
    catch (const std::exception& e) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent()
                << IronBee::errinfo_what(e.what()));
    }
}

ib_status_t ErrorPageModule::error_page_fn(
    ib_tx_t *tx,
    const uint8_t **page,
    size_t *len)
{
    IronBee::Transaction ib_tx(tx);

    ErrorPageCtxConfig &cfg =
        module().configuration_data<ErrorPageCtxConfig>(
            ib_tx.context());

    status_to_file_map_t::iterator itr =
        cfg.status_to_file.find(ib_tx.ib()->block_status);

    /* If we can't find a mapping, decline. The default will take over. */
    if (itr == cfg.status_to_file.end()) {
        ib_log_debug2_tx(
            ib_tx.ib(),
            "No custom page mapped for status %" PRId64 " and context %s. "
            "Declining.",
            ib_tx.ib()->block_status,
            ib_tx.context().name());
        return IB_DECLINED;
    }

    const std::string& file = itr->second;
    const boost::iostreams::mapped_file_source &source =
        cfg.status_to_mapped_file_source[tx->block_status];

    ib_log_debug2_tx(
        ib_tx.ib(),
        "Using custom error page file %.*s.",
        static_cast<int>(file.length()),
        file.data());

    *page = reinterpret_cast<const uint8_t*>(source.data());
    *len = source.size();

    return IB_OK;
}
<commit_msg>modules/error_page.cpp: Include order<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee Modules --- Error Page
 *
 * The Error Page module allows the user to select a custom error page.
 *
 * @author Sam Baskinger <sbaskinger@qualys.com>
 */

#include "ironbee_config_auto.h"

#include <ironbeepp/configuration_directives.hpp>
#include <ironbeepp/configuration_parser.hpp>
#include <ironbeepp/c_trampoline.hpp>
#include <ironbeepp/module.hpp>
#include <ironbeepp/module_bootstrap.hpp>
#include <ironbeepp/module_delegate.hpp>
#include <ironbeepp/transaction.hpp>

#include <ironbee/path.h>
#include <ironbee/rule_engine.h>
#include <ironbee/string.h>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/iostreams/device/mapped_file.hpp>

/* Enable PRId64 printf. */
extern "C" {
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
}

/**
 * Error Page Module implementation.
 */
class ErrorPageModule : public IronBee::ModuleDelegate
{
public:
    /**
     * A version of @ref ib_rule_error_page_fn_t without the callback data.
     *
     * This will be used by @ref IronBee::make_c_trampoline to replace
     * IronBee's default error page function.
     *
     * @param[in] tx The transaction.
     * @param[out] page A pointer to the error page.
     * @param[out] page_sz The length of @a page.
     */
    typedef ib_status_t(error_page_fn_t)(
        ib_tx_t        *tx,
        const uint8_t **page,
        size_t         *page_sz);
    /**
     * Constructor.
     *
     * @param[in] module The IronBee++ module.
     */
    explicit ErrorPageModule(IronBee::Module module);

private:

    /**
     * Member to store the C trampoline information.
     *
     * Note that m_trampoline_pair.second must be destroyed.
     */
    std::pair<ib_rule_error_page_fn_t, void*> m_trampoline_pair;

    /**
     * Holds callback data associated with @ref ib_rule_error_page_fn_t.
     *
     * This member ensures that IronBee::delete_c_trampoline is called.
     */
    boost::shared_ptr<void> m_trampoline_data;

    /**
     * Produce an error page for the given transaction.
     *
     * @param[in] tx The transaction.
     * @param[out] page The page data is placed here.
     * @param[out] page_sz The page size is placed here.
     *
     * @returns
     * - IB_OK On success.
     * - IB_DECLINED If the error page is not available but not because
     *               of an error.
     * - Other on error.
     */
    ib_status_t error_page_fn(
        ib_tx_t        *tx,
        const uint8_t **page,
        size_t         *page_sz);

    /**
     * Implement the HTTP Status Code directive.
     *
     * @param[in] cp Configuration parser.
     * @param[in] name The directive.
     * @param[in] param1 The status code.
     * @param[in] param2 The error page file name.
     *
     * @throws @ref IronBee::exception.
     */
    void httpStatusCodeContentsDirective(
        IronBee::ConfigurationParser  cp,
        const char                   *name,
        const char                   *param1,
        const char                   *param2);
};

IBPP_BOOTSTRAP_MODULE_DELEGATE("ErrorPageModule", ErrorPageModule);

/**
 * A map from the status number to a file name.
 */
typedef std::map<ib_num_t, std::string> status_to_file_map_t;

/**
 * Context configuration value for the ErrorPageModule.
 */
struct ErrorPageCtxConfig {

    /**
     * The mapping from an HTTP status code to the file to return.
     */
    status_to_file_map_t status_to_file;

    /**
     * The mapping from an HTTP status code to the memory mapped file.
     */
    std::map<ib_num_t, boost::iostreams::mapped_file_source>
        status_to_mapped_file_source;
};

/* Implementation */

ErrorPageModule::ErrorPageModule(IronBee::Module module):
    /* Initialize the parent. */
    IronBee::ModuleDelegate(module),

    /* Build the C callback for ib_rule_set_error_page_fn(). */
    m_trampoline_pair(
        IronBee::make_c_trampoline<error_page_fn_t>(
            boost::bind(&ErrorPageModule::error_page_fn, this, _1, _2, _3))),

    m_trampoline_data(
        m_trampoline_pair.second,
        IronBee::delete_c_trampoline)
{

    /* Register the callback with the IronBee engine. */
    ib_rule_set_error_page_fn(
        module.engine().ib(),
        m_trampoline_pair.first,
        m_trampoline_pair.second);

    /* Setup the directive callbacks. */
    module.engine().register_configuration_directives().
        param2(
            "HttpStatusCodeContents",
            boost::bind(
                &ErrorPageModule::httpStatusCodeContentsDirective,
                this, _1, _2, _3, _4));

    module.set_configuration_data<ErrorPageCtxConfig>();
}

void ErrorPageModule::httpStatusCodeContentsDirective(
        IronBee::ConfigurationParser  cp,
        const char                   *name,
        const char                   *param1,
        const char                   *param2)
{
    ib_num_t     num;

    ErrorPageCtxConfig &cfg =
        module().configuration_data<ErrorPageCtxConfig>(cp.current_context());

    /* Convert the incoming parameter. */
    IronBee::throw_if_error(ib_string_to_num(param1, 10, &num));

    /* Set the mapping in the context configuration. */
    cfg.status_to_file[num] = ib_util_relative_file(
        ib_engine_pool_config_get(cp.engine().ib()),
        cp.current_file(),
        param2
    );

    try {
        cfg.status_to_mapped_file_source[num] =
            boost::iostreams::mapped_file_source(cfg.status_to_file[num]);
    }
    catch (const std::exception& e) {
        BOOST_THROW_EXCEPTION(
            IronBee::enoent()
                << IronBee::errinfo_what(e.what()));
    }
}

ib_status_t ErrorPageModule::error_page_fn(
    ib_tx_t *tx,
    const uint8_t **page,
    size_t *len)
{
    IronBee::Transaction ib_tx(tx);

    ErrorPageCtxConfig &cfg =
        module().configuration_data<ErrorPageCtxConfig>(
            ib_tx.context());

    status_to_file_map_t::iterator itr =
        cfg.status_to_file.find(ib_tx.ib()->block_status);

    /* If we can't find a mapping, decline. The default will take over. */
    if (itr == cfg.status_to_file.end()) {
        ib_log_debug2_tx(
            ib_tx.ib(),
            "No custom page mapped for status %" PRId64 " and context %s. "
            "Declining.",
            ib_tx.ib()->block_status,
            ib_tx.context().name());
        return IB_DECLINED;
    }

    const std::string& file = itr->second;
    const boost::iostreams::mapped_file_source &source =
        cfg.status_to_mapped_file_source[tx->block_status];

    ib_log_debug2_tx(
        ib_tx.ib(),
        "Using custom error page file %.*s.",
        static_cast<int>(file.length()),
        file.data());

    *page = reinterpret_cast<const uint8_t*>(source.data());
    *len = source.size();

    return IB_OK;
}
<|endoftext|>


<commit_before>// 574D_blocks.cc - Codeforces.com/problemset/problem/574/D Blocks program by Sergey 2015

#include <bits/stdc++.h>
using namespace std;

///////////////////////////////////////////////////////////////////////////////
// Unit tests base Class
///////////////////////////////////////////////////////////////////////////////

class Unittest { public:
    #define CHECK(a,b)  check<long long>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    #define CHECKT(a)   check<int>(a, 1, #a, "true", __FILE__, __LINE__, __FUNCTION__);
    #define CHECKS(a,b) check<cs>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    typedef const string& cs;
    int checks, fails; ostringstream serr; istringstream *in;
    Unittest() { checks = fails = 0;}
    void test_cin(cs s){ in = new istringstream(s); cin.rdbuf(in->rdbuf()); }
    void fail_hdr(cs stra, cs strb, cs file, int line, cs func) {
        serr << "==================================================" << endl;
        serr << "FAIL: " << func << endl;
        serr << "--------------------------------------------------" << endl;
        serr << "File \"" << file << "\", line " << line << " in " << func << endl;
        serr << "  Checking " << stra << " == " << strb << endl;
    }
    template <typename T> void check(T a, T b, cs stra, cs strb, cs file, int line, cs func) {
        checks++; if (a == b) { cout << "."; return; }
        fails++; cout << "F"; fail_hdr(stra, strb, file, line, func);
        serr << "  Error: \"" << a << "\" ! = \"" << b << "\"" << endl << endl;
    }
    virtual void single_test() {}
    virtual void test_list() { single_test(); }
    double dclock() { return double(clock()) / CLOCKS_PER_SEC; }
    status() {
        cout << endl; if (fails) cout << serr.str();
        cout << "--------------------------------------------------" << endl;
        cout << "Ran " << checks << " checks in " << dclock() << "s" << endl << endl;
        if (fails) cout << "FAILED (failures=" << fails << ")"; else cout << "OK" << endl;
        return fails > 0;
    }
    run() { streambuf* ocin = cin.rdbuf(); test_list(); cin.rdbuf(ocin); return status(); }
};

///////////////////////////////////////////////////////////////////////////////
// Blocks Class (Main Program)
///////////////////////////////////////////////////////////////////////////////

class Blocks { public:

    typedef long long ll;
    int n, m;
    vector <int> nums, left, right;
    int mmax;

    Blocks(){

        // Reading single elements
        cin >> n;

        // Reading a single line of multiple elements
        mmax = 0;
        for(int i=0; i<n; i++) {
            int s; cin >> s; nums.push_back(s);
        }
    }

    string calculate(){

        for(int i=0; i<n; i++) left.push_back(min(i == 0 ? 1 : left[i-1]+1, nums[i]));
        for(int i=0; i<n; i++) right.push_back(min(i == 0 ? 1 : right[i-1]+1, nums[n-i-1]));
        for(int i=0; i<n; i++) mmax = max(mmax, min(left[n-i-1], right[i]));

        // Converting result to string
        ostringstream resstr;
        resstr << mmax;
        return resstr.str();
    }
};

///////////////////////////////////////////////////////////////////////////////
// Local Unit tests
///////////////////////////////////////////////////////////////////////////////

class LocalUnittest: public Unittest {

    Blocks* d;

    void single_test() {

        // Constructor test
        string test = "6\n2 1 4 6 2 2";
        test_cin(test);
        d = new Blocks;
        CHECK(d->n, 6);
        CHECK(d->nums[0], 2);

        // Sample test
        test_cin(test);
        CHECKS((new Blocks)->calculate(), "3");

        // Sample test
        test_cin("7\n3 3 3 1 3 3 3");
        CHECKS((new Blocks)->calculate(), "2");

        // Sample test
        test_cin("5\n0 1 2 1 0");
        CHECKS((new Blocks)->calculate(), "2");

        // My test
        test_cin("");
        //CHECKS((new Blocks)->calculate(), "0");

        // Time limit test
        time_limit_test(100000);
    }

    void time_limit_test(int nmax){

        ostringstream stest;

        // Random inputs
        stest << nmax << endl;
        for(int i = 0; i < nmax; i++) stest << 1000000000 << " ";

        // Run the test
        double start = dclock();
        test_cin(stest.str());
        d = new Blocks;
        double calc = dclock();
        d->calculate();
        double stop = dclock();
        cout << endl << "Timelimit Test: " << stop - start << "s (init ";
        cout << calc - start << "s calc " << stop - calc << "s)" << endl;
    }
};

///////////////////////////////////////////////////////////////////////////////
// Main Execution
///////////////////////////////////////////////////////////////////////////////

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

    // Faster cin and cout
    ios_base::sync_with_stdio(0);cin.tie(0);

    if (argc > 1 && !strcmp(argv[1], "-ut")) {
        LocalUnittest lut;
        return lut.run();
    }
    cout << (new Blocks)->calculate() << endl;
    return 0;
}

<commit_msg>New format<commit_after>// 574D_blocks.cc - Codeforces.com/problemset/problem/574/D Blocks program by Sergey 2015

#include <bits/stdc++.h>
using namespace std;

// Cppunit - C++ Unit testing TDD framework (github.com/cppunit/cppunit)
class Cppunit { public:
    #define CHECK(a,b)  check<long long>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    #define CHECKT(a)   check<bool>(a, true, #a, "true", __FILE__, __LINE__, __FUNCTION__);
    #define CHECKS(a,b) check<cs>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    typedef const std::string& cs;
    int checks, fails; std::ostringstream serr; std::istringstream *in;
    Cppunit() { checks = fails = 0;}
    void test_cin(cs s){ in = new std::istringstream(s); std::cin.rdbuf(in->rdbuf()); }
    void fail_hdr(cs stra, cs strb, cs file, int line, cs func) {
        serr << "==================================================" << std::endl;
        serr << "FAIL: " << func << std::endl;
        serr << "--------------------------------------------------" << std::endl;
        serr << "File \"" << file << "\", line " << line << " in " << func << std::endl;
        serr << "  Checking " << stra << " == " << strb << std::endl;
    }
    template <typename T> void check(T a, T b, cs stra, cs strb, cs file, int line, cs func) {
        checks++; if (a == b) { std::cout << "."; return; }
        fails++; std::cout << "F"; fail_hdr(stra, strb, file, line, func);
        serr << "  Error: \"" << a << "\" ! = \"" << b << "\"" << std::endl << std::endl;
    }
    virtual void single_test() {}
    virtual void test_list() { single_test(); }
    double dclock() { return double(clock()) / CLOCKS_PER_SEC; }
    status() {
        std::cout << std::endl; if (fails) std::cout << serr.str();
        std::cout << "--------------------------------------------------" << std::endl;
        std::cout << "Ran " << checks << " checks in " << dclock() << "s" << std::endl << std::endl;
        if (fails) std::cout << "FAILED (failures=" << fails << ")"; else std::cout << "OK" << std::endl;
        return fails > 0;
    }
    run() { std::streambuf* ocin = std::cin.rdbuf(); test_list(); std::cin.rdbuf(ocin); return status(); }
};

///////////////////////////////////////////////////////////////////////////////
// Blocks Class (Main Program)
///////////////////////////////////////////////////////////////////////////////

class Blocks { public:

    typedef long long ll;
    int n, m;
    vector <int> nums, left, right;
    int mmax;

    Blocks(){

        // Reading single elements
        cin >> n;

        // Reading a single line of multiple elements
        mmax = 0;
        for(int i=0; i<n; i++) {
            int s; cin >> s; nums.push_back(s);
        }
    }

    string calculate(){

        for(int i=0; i<n; i++)
            left.push_back(min(i == 0 ? 1 : left[i-1]+1, nums[i]));
        for(int i=0; i<n; i++)
            right.push_back(min(i == 0 ? 1 : right[i-1]+1, nums[n-i-1]));
        for(int i=0; i<n; i++)
            mmax = max(mmax, min(left[n-i-1], right[i]));

        // Converting result to string
        ostringstream resstr;
        resstr << mmax;
        return resstr.str();
    }
};

///////////////////////////////////////////////////////////////////////////////
// Unit tests
///////////////////////////////////////////////////////////////////////////////

class MyCppunit: public Cppunit {

    Blocks* d;

    void single_test() {

        // Constructor test
        string test = "6\n2 1 4 6 2 2";
        test_cin(test);
        d = new Blocks;
        CHECK(d->n, 6);
        CHECK(d->nums[0], 2);

        // Sample test
        test_cin(test);
        CHECKS((new Blocks)->calculate(), "3");

        // Sample test
        test_cin("7\n3 3 3 1 3 3 3");
        CHECKS((new Blocks)->calculate(), "2");

        // Sample test
        test_cin("5\n0 1 2 1 0");
        CHECKS((new Blocks)->calculate(), "2");

        // My test
        test_cin("");
        //CHECKS((new Blocks)->calculate(), "0");

        // Time limit test
        time_limit_test(100000);
    }

    void time_limit_test(int nmax){

        ostringstream stest;

        // Random inputs
        stest << nmax << endl;
        for(int i = 0; i < nmax; i++) stest << 1000000000 << " ";

        // Run the test
        double start = dclock();
        test_cin(stest.str());
        d = new Blocks;
        double calc = dclock();
        d->calculate();
        double stop = dclock();
        cout << endl << "Timelimit Test: " << stop - start << "s (init ";
        cout << calc - start << "s calc " << stop - calc << "s)" << endl;
    }
};

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

    // Faster cin and cout
    ios_base::sync_with_stdio(0);cin.tie(0);

    if (argc > 1 && !strcmp(argv[1], "-ut"))
        return (new MyCppunit)->run();

    cout << (new Blocks)->calculate() << endl;
    return 0;
}

<|endoftext|>


<commit_before>#include "canvas.hh"

CanvasPipe::CanvasPipe(CanvasBlock *from, CanvasBlock *to) : from(from), to(to) {

}

CanvasPipe::~CanvasPipe() {

}

QRectF CanvasPipe::boundingRect() const {
	return from->boundingRect() | to->boundingRect();
}

void CanvasPipe::paint(QPainter *p, const QStyleOptionGraphicsItem *sogi, QWidget *w) {

}

<commit_msg>Drawing the line in the wrong place<commit_after>#include "app.hh"
#include "canvas.hh"

CanvasPipe::CanvasPipe(CanvasBlock *from, CanvasBlock *to) : from(from), to(to) {

}

CanvasPipe::~CanvasPipe() {

}

QRectF CanvasPipe::boundingRect() const {
	return from->boundingRect() | to->boundingRect();
}

void CanvasPipe::paint(QPainter *p, const QStyleOptionGraphicsItem *sogi, QWidget *w) {
	p->drawLine(from->boundingRect().bottomRight(), to->boundingRect().topRight());
}

<|endoftext|>


<commit_before>#include "DrawPolygonCMPT.h"
#include "EditPolylineWithCopyNodeOP.h"
#include "PolygonShape.h"
#include "DrawPencilPolygonCMPT.h"

#include <ee/SelectShapesOP.h>
#include <ee/MultiShapesImpl.h>
#include <ee/ShapeSelection.h>
#include <ee/EmptyVerifyVisitor.h>
#include <ee/FetchAllVisitor.h>
#include <ee/RGBColorSettingDlg.h>
#include <ee/SymbolMgr.h>
#include <ee/panel_msg.h>
#include <ee/ImageSymbol.h>

namespace eshape
{

DrawPolygonCMPT::DrawPolygonCMPT(wxWindow* parent, const std::string& name, wxWindow* stage_wnd,
								 ee::EditPanelImpl* stage, ee::MultiShapesImpl* shapes_impl,
								 ee::PropertySettingPanel* property)
	: ee::OneFloatValueCMPT(parent, name, stage, "node capture", 5, 30, 10)
	, m_stage_wnd(stage_wnd)
	, m_shapes_impl(shapes_impl)
	, m_color(*wxBLACK)
{
	m_editop = NULL;
	// draw polygon with pen, node capture
	{
		ee::OneFloatValueCMPT* cmpt = new ee::OneFloatValueCMPT(this, "pen", stage, "node capture", 5, 30, 10);
		ee::EditOP* op = new EditPolylineOP<DrawPolygonOP, ee::SelectShapesOP>
			(stage_wnd, stage, shapes_impl, property, cmpt, /*cmpt*/this);
		cmpt->SetEditOP(op);
		AddChild(cmpt);
	}
	// draw polygon with pencil, simplify threshold
	{
		AddChild(new DrawPencilPolygonCMPT(this, "pencil", stage_wnd, stage, shapes_impl));
	}
}

void DrawPolygonCMPT::UpdateControlValue()
{
	bool empty;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::EmptyVerifyVisitor(empty));
	m_btn_trigger->Enable(!empty);
}

wxSizer* DrawPolygonCMPT::InitLayout()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	sizer->Add(ee::OneFloatValueCMPT::InitLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitChildrenLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitPreviewButtonPanel());

	sizer->AddSpacer(10);

	m_btn_trigger = new wxButton(this, wxID_ANY, wxT(""));
	Connect(m_btn_trigger->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnTriggerFillingColor));
	sizer->Add(m_btn_trigger);
	m_btn_trigger->Enable(false);

	return sizer;
}

wxSizer* DrawPolygonCMPT::InitPreviewButtonPanel()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	wxArrayString choices;
	choices.Add(wxT("ɫ"));
	choices.Add(wxT(""));
	m_filling_type_choice = new wxRadioBox(this, wxID_ANY, wxT("䷽ʽ"), wxDefaultPosition, wxDefaultSize, choices, 1, wxRA_SPECIFY_COLS);
	Connect(m_filling_type_choice->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(DrawPolygonCMPT::OnChangeFillingType));
	sizer->Add(m_filling_type_choice);

	sizer->AddSpacer(10);

	m_btn_review = new wxButton(this, wxID_ANY);
	Connect(m_btn_review->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnSetColor));
	sizer->Add(m_btn_review);
	FillingButton();

	return sizer;
}

void DrawPolygonCMPT::OnSetColor(wxCommandEvent& event)
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
// 		{
// 			// todo trans between wxColor and ee::Colorf
// 			ee::Colorf col;
// 			col.r = m_color.Red() / 255.0f;
// 			col.g = m_color.Green() / 255.0f;
// 			col.b = m_color.Blue() / 255.0f;
// 			ee::HSLColorSettingDlg dlg(m_stage_wnd, NULL, col);
// 			if (dlg.ShowModal() == wxID_OK) {
// 				col = dlg.GetColor();
// 				m_color.Set(col.r * 255, col.g * 255, col.b * 255);
// 			}
// 		}
		{
			// todo trans between wxColor and ee::Colorf
			ee::Colorf col;
			col.r = m_color.Red() / 255.0f;
			col.g = m_color.Green() / 255.0f;
			col.b = m_color.Blue() / 255.0f;
			ee::RGBColorSettingDlg dlg(m_stage_wnd, NULL, col);
			if (dlg.ShowModal() == wxID_OK) {
				col = dlg.GetColor();
				m_color.Set(col.r * 255, col.g * 255, col.b * 255);
			}
		}
		break;
	case 1:
		{
			wxFileDialog dlg(this, wxT("ѡ"), wxEmptyString, wxEmptyString, wxT("*.png;*.jpg"), wxFD_OPEN);
			if (dlg.ShowModal() == wxID_OK)
			{
				m_filepath = dlg.GetPath();
				m_bitmap.LoadFromFile(m_filepath);
			}
		}
		break;
	}
	FillingButton();
}

void DrawPolygonCMPT::OnChangeFillingType(wxCommandEvent& event)
{
	FillingButton();
}

void DrawPolygonCMPT::OnTriggerFillingColor(wxCommandEvent& event)
{
	std::vector<PolygonShape*> polys;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<PolygonShape>(polys));

	for (size_t i = 0, n = polys.size(); i < n; ++i)
	{
		PolygonShape* poly = polys[i];
		switch (m_filling_type_choice->GetSelection())
		{
		case 0:
			poly->SetMaterialColor(ee::Colorf(m_color.Red() / 255.0f, m_color.Green() / 255.0f, m_color.Blue() / 255.0f));
			break;
		case 1:
			poly->SetMaterialTexture(static_cast<ee::ImageSymbol*>(ee::SymbolMgr::Instance()->FetchSymbol(m_filepath)));
			break;
		}
		ee::SetCanvasDirtySJ::Instance()->SetDirty();
	}
}

void DrawPolygonCMPT::FillingButton()
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		{
			wxImage img(m_btn_review->GetSize().GetWidth(), m_btn_review->GetSize().GetHeight());
			img.SetRGB(wxRect(m_btn_review->GetSize()), m_color.Red(), m_color.Green(), m_color.Blue());
			wxBitmap bitmap(img);
			m_btn_review->SetBitmap(bitmap);
		}
		break;
	case 1:
		if (const wxBitmap* bmp = m_bitmap.GetLargeBmp()) {
			m_btn_review->SetBitmap(*bmp);
		}
		break;
	}
}

}<commit_msg>[ADDED] config color setting for etexture<commit_after>#include "DrawPolygonCMPT.h"
#include "EditPolylineWithCopyNodeOP.h"
#include "PolygonShape.h"
#include "DrawPencilPolygonCMPT.h"

#include <ee/SelectShapesOP.h>
#include <ee/MultiShapesImpl.h>
#include <ee/ShapeSelection.h>
#include <ee/EmptyVerifyVisitor.h>
#include <ee/FetchAllVisitor.h>
#include <ee/RGBColorSettingDlg.h>
#include <ee/HSLColorSettingDlg.h>
#include <ee/SymbolMgr.h>
#include <ee/panel_msg.h>
#include <ee/ImageSymbol.h>
#include <ee/Config.h>
#include <ee/SettingData.h>

namespace eshape
{

DrawPolygonCMPT::DrawPolygonCMPT(wxWindow* parent, const std::string& name, wxWindow* stage_wnd,
								 ee::EditPanelImpl* stage, ee::MultiShapesImpl* shapes_impl,
								 ee::PropertySettingPanel* property)
	: ee::OneFloatValueCMPT(parent, name, stage, "node capture", 5, 30, 10)
	, m_stage_wnd(stage_wnd)
	, m_shapes_impl(shapes_impl)
	, m_color(*wxBLACK)
{
	m_editop = NULL;
	// draw polygon with pen, node capture
	{
		ee::OneFloatValueCMPT* cmpt = new ee::OneFloatValueCMPT(this, "pen", stage, "node capture", 5, 30, 10);
		ee::EditOP* op = new EditPolylineOP<DrawPolygonOP, ee::SelectShapesOP>
			(stage_wnd, stage, shapes_impl, property, cmpt, /*cmpt*/this);
		cmpt->SetEditOP(op);
		AddChild(cmpt);
	}
	// draw polygon with pencil, simplify threshold
	{
		AddChild(new DrawPencilPolygonCMPT(this, "pencil", stage_wnd, stage, shapes_impl));
	}
}

void DrawPolygonCMPT::UpdateControlValue()
{
	bool empty;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::EmptyVerifyVisitor(empty));
	m_btn_trigger->Enable(!empty);
}

wxSizer* DrawPolygonCMPT::InitLayout()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	sizer->Add(ee::OneFloatValueCMPT::InitLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitChildrenLayout());

	sizer->AddSpacer(20);

	sizer->Add(InitPreviewButtonPanel());

	sizer->AddSpacer(10);

	m_btn_trigger = new wxButton(this, wxID_ANY, wxT(""));
	Connect(m_btn_trigger->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnTriggerFillingColor));
	sizer->Add(m_btn_trigger);
	m_btn_trigger->Enable(false);

	return sizer;
}

wxSizer* DrawPolygonCMPT::InitPreviewButtonPanel()
{
	wxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	wxArrayString choices;
	choices.Add(wxT("ɫ"));
	choices.Add(wxT(""));
	m_filling_type_choice = new wxRadioBox(this, wxID_ANY, wxT("䷽ʽ"), wxDefaultPosition, wxDefaultSize, choices, 1, wxRA_SPECIFY_COLS);
	Connect(m_filling_type_choice->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(DrawPolygonCMPT::OnChangeFillingType));
	sizer->Add(m_filling_type_choice);

	sizer->AddSpacer(10);

	m_btn_review = new wxButton(this, wxID_ANY);
	Connect(m_btn_review->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DrawPolygonCMPT::OnSetColor));
	sizer->Add(m_btn_review);
	FillingButton();

	return sizer;
}

void DrawPolygonCMPT::OnSetColor(wxCommandEvent& event)
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		if (ee::Config::Instance()->GetSettings().color_setting_dlg_type == ee::CSDT_HSL)
		{
 			// todo trans between wxColor and ee::Colorf
 			ee::Colorf col;
 			col.r = m_color.Red() / 255.0f;
 			col.g = m_color.Green() / 255.0f;
 			col.b = m_color.Blue() / 255.0f;
 			ee::HSLColorSettingDlg dlg(m_stage_wnd, NULL, col);
 			if (dlg.ShowModal() == wxID_OK) {
 				col = dlg.GetColor();
 				m_color.Set(col.r * 255, col.g * 255, col.b * 255);
 			}
		}
		else
		{
			// todo trans between wxColor and ee::Colorf
			ee::Colorf col;
			col.r = m_color.Red() / 255.0f;
			col.g = m_color.Green() / 255.0f;
			col.b = m_color.Blue() / 255.0f;
			ee::RGBColorSettingDlg dlg(m_stage_wnd, NULL, col);
			if (dlg.ShowModal() == wxID_OK) {
				col = dlg.GetColor();
				m_color.Set(col.r * 255, col.g * 255, col.b * 255);
			}
		}
		break;
	case 1:
		{
			wxFileDialog dlg(this, wxT("ѡ"), wxEmptyString, wxEmptyString, wxT("*.png;*.jpg"), wxFD_OPEN);
			if (dlg.ShowModal() == wxID_OK)
			{
				m_filepath = dlg.GetPath();
				m_bitmap.LoadFromFile(m_filepath);
			}
		}
		break;
	}
	FillingButton();
}

void DrawPolygonCMPT::OnChangeFillingType(wxCommandEvent& event)
{
	FillingButton();
}

void DrawPolygonCMPT::OnTriggerFillingColor(wxCommandEvent& event)
{
	std::vector<PolygonShape*> polys;
	m_shapes_impl->GetShapeSelection()->Traverse(ee::FetchAllVisitor<PolygonShape>(polys));

	for (size_t i = 0, n = polys.size(); i < n; ++i)
	{
		PolygonShape* poly = polys[i];
		switch (m_filling_type_choice->GetSelection())
		{
		case 0:
			poly->SetMaterialColor(ee::Colorf(m_color.Red() / 255.0f, m_color.Green() / 255.0f, m_color.Blue() / 255.0f));
			break;
		case 1:
			poly->SetMaterialTexture(static_cast<ee::ImageSymbol*>(ee::SymbolMgr::Instance()->FetchSymbol(m_filepath)));
			break;
		}
		ee::SetCanvasDirtySJ::Instance()->SetDirty();
	}
}

void DrawPolygonCMPT::FillingButton()
{
	switch (m_filling_type_choice->GetSelection())
	{
	case 0:
		{
			wxImage img(m_btn_review->GetSize().GetWidth(), m_btn_review->GetSize().GetHeight());
			img.SetRGB(wxRect(m_btn_review->GetSize()), m_color.Red(), m_color.Green(), m_color.Blue());
			wxBitmap bitmap(img);
			m_btn_review->SetBitmap(bitmap);
		}
		break;
	case 1:
		if (const wxBitmap* bmp = m_bitmap.GetLargeBmp()) {
			m_btn_review->SetBitmap(*bmp);
		}
		break;
	}
}

}<|endoftext|>


<commit_before>#include "SparseMatrix.h"
#include <string.h>
#include <iostream>

using namespace std;

SparseMatrix::SparseMatrix() {
	// TODO Auto-generated constructor stub
	m_rowStartsMarked = false;
}

SparseMatrix::~SparseMatrix() {
	// TODO Auto-generated destructor stub
}

void SparseMatrix::printSummary() {
	cout << "Matrix summary" << endl;
	cout << "name = " << m_name << endl;
	cout << "#rows = " << m_rows << endl;
	cout << "#cols = " << m_cols << endl;
	cout << "#nz = " << m_nz << endl;
}

bool SparseMatrix::isSquare() {
	return m_cols == m_rows;
}

SparseMatrix* SparseMatrix::fromMemory(unsigned int metaDataBase) {
	CompressedSparseMetadata * metadata = (CompressedSparseMetadata *) metaDataBase;

	if(metadata->numCols == 0 || metadata->numRows == 0 || metadata->numNZ == 0) {
		cerr << "Error: matrix data at " << hex << metaDataBase << dec << " is invalid" << endl;
		return 0;
	}

	SparseMatrix * ret = new SparseMatrix();
	ret->m_cols = metadata->numCols;
	ret->m_rows = metadata->numRows;
	ret->m_nz = metadata->numNZ;
	ret->m_indPtrs = (SpMVIndex*) (metadata->indPtrBase);
	ret->m_inds = (SpMVIndex*) (metadata->indBase);
	ret->m_nzData = (SpMVData*) (metadata->nzDataBase);
	ret->m_rowStartsMarked = false;

	return ret;
}

void SparseMatrix::markRowStarts() {
	if(!m_rowStartsMarked) {
		m_rowStartsMarked = true;
		// flags to mark encountered row indices
		char * encounteredRow = new char[m_rows];
		// set all encountered flags to zero
		memset(encounteredRow, 0, m_rows);

		for(SpMVIndex nz = 0; nz < m_nz; nz++) {
			SpMVIndex rowInd = m_inds[nz];
			if(!encounteredRow[rowInd]) {
				// set as encountered + add cold miss bit at highest position
				encounteredRow[rowInd] = 1;
				m_inds[nz] = rowInd | (1 << 31);
			}
		}

		delete [] encounteredRow;
	}
}
<commit_msg>use bitmaps for markRowStarts<commit_after>#include "SparseMatrix.h"
#include <string.h>
#include <iostream>
#include <vector>

using namespace std;

SparseMatrix::SparseMatrix() {
	// TODO Auto-generated constructor stub
	m_rowStartsMarked = false;
}

SparseMatrix::~SparseMatrix() {
	// TODO Auto-generated destructor stub
}

void SparseMatrix::printSummary() {
	cout << "Matrix summary" << endl;
	cout << "name = " << m_name << endl;
	cout << "#rows = " << m_rows << endl;
	cout << "#cols = " << m_cols << endl;
	cout << "#nz = " << m_nz << endl;
}

bool SparseMatrix::isSquare() {
	return m_cols == m_rows;
}

SparseMatrix* SparseMatrix::fromMemory(unsigned int metaDataBase) {
	CompressedSparseMetadata * metadata = (CompressedSparseMetadata *) metaDataBase;

	if(metadata->numCols == 0 || metadata->numRows == 0 || metadata->numNZ == 0) {
		cerr << "Error: matrix data at " << hex << metaDataBase << dec << " is invalid" << endl;
		return 0;
	}

	SparseMatrix * ret = new SparseMatrix();
	ret->m_cols = metadata->numCols;
	ret->m_rows = metadata->numRows;
	ret->m_nz = metadata->numNZ;
	ret->m_indPtrs = (SpMVIndex*) (metadata->indPtrBase);
	ret->m_inds = (SpMVIndex*) (metadata->indBase);
	ret->m_nzData = (SpMVData*) (metadata->nzDataBase);
	ret->m_rowStartsMarked = false;

	return ret;
}

void SparseMatrix::markRowStarts() {
	if(!m_rowStartsMarked) {
		m_rowStartsMarked = true;
		// flags to mark encountered row indices
		// packed as 32-bit fields for smaller memory/cache footprint
		unsigned int encSize = (m_rows/32)+1;
		unsigned int * encounteredRow = new unsigned int[encSize];

		// set all encountered flags to zero
		memset(encounteredRow, 0, sizeof(unsigned int)*encSize);

		for(SpMVIndex nz = 0; nz < m_nz; nz++) {
			SpMVIndex rowInd = m_inds[nz];
			unsigned int bitInd = rowInd / 32;
			unsigned int bitMod = rowInd % 32;
			unsigned int bVal = encounteredRow[bitInd];
			if((bVal & (1 << bitMod)) == 0) {
				// set as encountered + add cold miss bit at highest position
				encounteredRow[bitInd] = bVal | (1 << bitMod);
				m_inds[nz] = rowInd | (1 << 31);
			}
		}

		delete [] encounteredRow;
	}
}
<|endoftext|>


<commit_before>#include "SmartCardWrapper.hh"

#include <nan.h>

namespace helios
{

NAN_MODULE_INIT(ModuleInit)
{
    auto cls = "SmartCardReader";
    auto tpl = Nan::New<v8::FunctionTemplate>(SmartCardWrapper::New);

    tpl->SetClassName(Nan::New(cls).ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    SetPrototypeMethod(tpl, "poll", SmartCardWrapper::Poll);
    SetPrototypeMethod(tpl, "query", SmartCardWrapper::Query);

    Nan::Set(target, Nan::New(cls).ToLocalChecked(), tpl->GetFunction());
};

}

NODE_MODULE(SmartCardReader, helios::ModuleInit)
<commit_msg>Expose setup and reconnect in SmartCardModule.cc<commit_after>#include "SmartCardWrapper.hh"

#include <nan.h>

namespace helios
{

NAN_MODULE_INIT(ModuleInit)
{
    auto cls = "SmartCardReader";
    auto tpl = Nan::New<v8::FunctionTemplate>(SmartCardWrapper::New);

    tpl->SetClassName(Nan::New(cls).ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    SetPrototypeMethod(tpl, "poll", SmartCardWrapper::Poll);
    SetPrototypeMethod(tpl, "query", SmartCardWrapper::Query);
    SetPrototypeMethod(tpl, "setup", SmartCardWrapper::Setup);
    SetPrototypeMethod(tpl, "release", SmartCardWrapper::Release);

    Nan::Set(target, Nan::New(cls).ToLocalChecked(), tpl->GetFunction());
};

}

NODE_MODULE(SmartCardReader, helios::ModuleInit)
<|endoftext|>


<commit_before>//   Copyright 2016-2020 Jean-Francois Poilpret
//
//   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.

/*
 * Simple example, checking all get methods of VL53L0X Time-of-flight range
 * sensor I2C device.
 *
 * Wiring:
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to VL53L0X SDA pin
 *   - A5 (PC5, SCL): connected to VL53L0X SCL pin
 *   - direct USB access
 */

#include <fastarduino/time.h>
#include <fastarduino/uart.h>
#include <fastarduino/i2c_handler.h>
#include <fastarduino/i2c_debug.h>
#include <fastarduino/i2c_status.h>
#include <fastarduino/devices/vl53l0x.h>
#include <fastarduino/memory.h>

#define DEBUG_I2C
// #define FORCE_SYNC

// static constexpr const i2c::I2CMode MODE = i2c::I2CMode::FAST;
static constexpr const i2c::I2CMode MODE = i2c::I2CMode::STANDARD;

static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 128;
static char output_buffer[OUTPUT_BUFFER_SIZE];

REGISTER_UATX_ISR(0)

#ifdef DEBUG_I2C
static constexpr const uint8_t DEBUG_SIZE = 96;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using DEBUGGER = i2c::debug::I2CDebugStatusRecorder<DEBUG_SIZE, DEBUG_SIZE>;
#define DEBUG(OUT) debugger.trace(OUT)
#define RESET_DEBUG() debugger.reset()
using MANAGER = i2c::I2CAsyncStatusDebugManager<
	MODE, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, DEBUGGER&, DEBUGGER&>;
static constexpr const uint8_t I2C_BUFFER_SIZE = 32;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using DEBUGGER = i2c::debug::I2CDebugStatusLiveLogger;
#define DEBUG(OUT)
#define RESET_DEBUG()
using MANAGER = i2c::I2CSyncStatusDebugManager<MODE, DEBUGGER&, DEBUGGER&>;
#	endif

#else

#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncManager<
	MODE, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS>;
static constexpr const uint8_t I2C_BUFFER_SIZE = 32;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncManager<MODE>;
#	endif
#define DEBUG(OUT)
#define RESET_DEBUG()

#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
REGISTER_I2C_ISR(MANAGER)
#endif

using streams::dec;
using streams::hex;
using streams::fixed;
using streams::endl;
using streams::flush;

using namespace devices::vl53l0x;
using TOF = VL53L0X<MANAGER>;

void display_memory(streams::ostream& out)
{
	out << F("free mem=") << dec << memory::free_mem() << endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();

	// open UART for traces
	serial::hard::UATX<UART> uart{output_buffer};
	streams::ostream out = uart.out();
	// uart.begin(115200);
	uart.begin(230400);
	out << streams::boolalpha;
	out << F("Start") << endl;

	// Initialize I2C async handler
#ifdef DEBUG_I2C
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
	DEBUGGER debugger;
#	else
	DEBUGGER debugger{out};
#	endif
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
#	ifdef DEBUG_I2C
	MANAGER manager{i2c_buffer, debugger, debugger};
#	else
	MANAGER manager{i2c_buffer};
#	endif
#else
#	ifdef DEBUG_I2C
	MANAGER manager{debugger, debugger};
#	else
	MANAGER manager;
#	endif
#endif

	display_memory(out);

	out << F("Instantiate VL53L0X") << endl;
	TOF tof{manager};
	display_memory(out);

	out << F("Start I2C manager") << endl;
	manager.begin();
	display_memory(out);

	out << F("Read VL53L0X status") << endl;
	uint8_t result = 0;
	bool ok = tof.get_revision(result);
	display_memory(out);
	out << F("tof.get_revision(result) = ") << ok << F(", result = ") << hex << result << endl;
	DEBUG(out);

	ok = tof.get_model(result);
	display_memory(out);
	out << F("tof.get_model(result) = ") << ok << F(", result = ") << hex << result << endl;
	DEBUG(out);

	PowerMode mode = PowerMode::STANDBY;
	ok = tof.get_power_mode(mode);
	display_memory(out);
	out << F("tof.get_power_mode(mode) = ") << ok << F(", mode = ") << mode << endl;
	DEBUG(out);

	DeviceStatus status;
	ok = tof.get_range_status(status);
	display_memory(out);
	out << F("tof.get_range_status(status) = ") << ok
		<< F(", status = ") << status << endl;
	DEBUG(out);

	SequenceSteps steps1;
	ok = tof.get_sequence_steps(steps1);
	display_memory(out);
	out << F("tof.get_sequence_steps(status) = ") << ok << F(", steps =") << steps1 << endl;
	DEBUG(out);

	uint8_t period = 0;
	ok = tof.get_vcsel_pulse_period<VcselPeriodType::PRE_RANGE>(period);
	display_memory(out);
	out << F("tof.get_vcsel_pulse_period<PRE_RANGE>(period) = ") << ok << F(", period = ") << dec << period << endl;
	ok = tof.get_vcsel_pulse_period<VcselPeriodType::FINAL_RANGE>(period);
	display_memory(out);
	out << F("tof.get_vcsel_pulse_period<FINAL_RANGE>(period) = ") << ok << F(", period = ") << dec << period << endl;
	DEBUG(out);

	// The following block adds 3KB to program size (float arithmetic libs)
	float signal_rate = 0.0;
	ok = tof.get_signal_rate_limit(signal_rate);
	display_memory(out);
	out << F("tof.get_signal_rate_limit(signal_rate) = ") << ok << F(", signal_rate = ")
		<< fixed << signal_rate << endl;
	DEBUG(out);

	TOF::GetSPADInfoFuture future3{};
	int error = tof.get_SPAD_info(future3);
	// while (true)
	// 	display_memory(out);
	//FIXME the following LOC gets executed then nothing!
	out << F("tof.get_SPAD_info(future) = ") << dec << error << endl;
	// for (uint8_t i = 0; i < 10; ++i)
	// {
	// 	out << '.' << flush;
	// 	time::delay_ms(100);
	// }
	// out << endl;
	time::delay_ms(1000);
	// time::delay_us(50);
	DEBUG(out);
	out << F("future.status() = ") << future3.status() << endl;
	SPADInfo SPAD_info{};
	future3.get(SPAD_info);
	out << F("SPADInfo = ") << SPAD_info << endl;
	DEBUG(out);

	// TOF::GetSequenceStepsTimeoutFuture future2{};
	// error = tof.get_sequence_steps_timeout(future2);
	// out << F("tof.get_sequence_steps_timeout(future) = ") << dec << error << endl;
	// time::delay_ms(100);
	// DEBUG(out);
	// out << F("future.status() = ") << future2.status() << endl;
	// SequenceStepsTimeout timeouts{};
	// future2.get(timeouts);
	// out << F("tof.get_sequence_steps_timeout(timeouts) = ") << ok << flush
	// 	<< F(", pre_range_vcsel_period_pclks = ") << dec << timeouts.pre_range_vcsel_period_pclks() << flush
	// 	<< F(", final_range_vcsel_period_pclks = ") << dec << timeouts.final_range_vcsel_period_pclks() << flush
	// 	<< F(", msrc_dss_tcc_mclks = ") << dec << timeouts.msrc_dss_tcc_mclks() << flush
	// 	<< F(", pre_range_mclks = ") << dec << timeouts.pre_range_mclks() << flush
	// 	<< F(", final_range_mclks = ") << dec << timeouts.final_range_mclks() << endl;
	// // check calculated values
	// out << F("timeouts.msrc_dss_tcc_us() = ") << dec << timeouts.msrc_dss_tcc_us() << flush
	// 	<< F(", timeouts.pre_range_us() = ") << dec << timeouts.pre_range_us() << flush
	// 	<< F(", timeouts.final_range_us() = ") << dec << timeouts.final_range_us() << endl;
	// DEBUG(out);

	manager.end();
}
<commit_msg>Scope all API calls in example. Add GPIO checks.<commit_after>//   Copyright 2016-2020 Jean-Francois Poilpret
//
//   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.

/*
 * Simple example, checking all get methods of VL53L0X Time-of-flight range
 * sensor I2C device.
 *
 * Wiring:
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to VL53L0X SDA pin
 *   - A5 (PC5, SCL): connected to VL53L0X SCL pin
 *   - direct USB access
 */

#include <fastarduino/time.h>
#include <fastarduino/uart.h>
#include <fastarduino/i2c_handler.h>
#include <fastarduino/i2c_debug.h>
#include <fastarduino/i2c_status.h>
#include <fastarduino/devices/vl53l0x.h>
#include <fastarduino/memory.h>

#define DEBUG_I2C
// #define FORCE_SYNC

// static constexpr const i2c::I2CMode MODE = i2c::I2CMode::FAST;
static constexpr const i2c::I2CMode MODE = i2c::I2CMode::STANDARD;

static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 128;
static char output_buffer[OUTPUT_BUFFER_SIZE];

REGISTER_UATX_ISR(0)

#ifdef DEBUG_I2C
static constexpr const uint8_t DEBUG_SIZE = 96;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using DEBUGGER = i2c::debug::I2CDebugStatusRecorder<DEBUG_SIZE, DEBUG_SIZE>;
#define DEBUG(OUT) debugger.trace(OUT)
#define RESET_DEBUG() debugger.reset()
using MANAGER = i2c::I2CAsyncStatusDebugManager<
	MODE, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, DEBUGGER&, DEBUGGER&>;
static constexpr const uint8_t I2C_BUFFER_SIZE = 32;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using DEBUGGER = i2c::debug::I2CDebugStatusLiveLogger;
#define DEBUG(OUT)
#define RESET_DEBUG()
using MANAGER = i2c::I2CSyncStatusDebugManager<MODE, DEBUGGER&, DEBUGGER&>;
#	endif

#else

#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncManager<
	MODE, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS>;
static constexpr const uint8_t I2C_BUFFER_SIZE = 32;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncManager<MODE>;
#	endif
#define DEBUG(OUT)
#define RESET_DEBUG()

#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
REGISTER_I2C_ISR(MANAGER)
#endif

using streams::dec;
using streams::hex;
using streams::fixed;
using streams::endl;
using streams::flush;

using namespace devices::vl53l0x;
using TOF = VL53L0X<MANAGER>;

void display_memory(streams::ostream& out)
{
	out << F("free mem=") << dec << memory::free_mem() << endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();

	// open UART for traces
	serial::hard::UATX<UART> uart{output_buffer};
	streams::ostream out = uart.out();
	// uart.begin(115200);
	uart.begin(230400);
	out << streams::boolalpha;
	out << F("Start") << endl;

	// Initialize I2C async handler
#ifdef DEBUG_I2C
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
	DEBUGGER debugger;
#	else
	DEBUGGER debugger{out};
#	endif
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
#	ifdef DEBUG_I2C
	MANAGER manager{i2c_buffer, debugger, debugger};
#	else
	MANAGER manager{i2c_buffer};
#	endif
#else
#	ifdef DEBUG_I2C
	MANAGER manager{debugger, debugger};
#	else
	MANAGER manager;
#	endif
#endif

	display_memory(out);

	out << F("Instantiate VL53L0X") << endl;
	TOF tof{manager};
	display_memory(out);

	out << F("Start I2C manager") << endl;
	manager.begin();
	display_memory(out);

	uint8_t result = 0;
	bool ok = false;
	int error = 0;

	{
		out << F("Read VL53L0X status") << endl;
		ok = tof.get_revision(result);
		display_memory(out);
		out << F("tof.get_revision(result) = ") << ok << F(", result = ") << hex << result << endl;
		DEBUG(out);
	}

	{
		ok = tof.get_model(result);
		display_memory(out);
		out << F("tof.get_model(result) = ") << ok << F(", result = ") << hex << result << endl;
		DEBUG(out);
	}

	{
		PowerMode mode = PowerMode::STANDBY;
		ok = tof.get_power_mode(mode);
		display_memory(out);
		out << F("tof.get_power_mode(mode) = ") << ok << F(", mode = ") << mode << endl;
		DEBUG(out);
	}

	{
		DeviceStatus status;
		ok = tof.get_range_status(status);
		display_memory(out);
		out << F("tof.get_range_status(status) = ") << ok
			<< F(", status = ") << status << endl;
		DEBUG(out);
	}

	{
		SequenceSteps steps1;
		ok = tof.get_sequence_steps(steps1);
		display_memory(out);
		out << F("tof.get_sequence_steps(status) = ") << ok << F(", steps =") << steps1 << endl;
		DEBUG(out);
	}

	{
		uint8_t period = 0;
		ok = tof.get_vcsel_pulse_period<VcselPeriodType::PRE_RANGE>(period);
		display_memory(out);
		out << F("tof.get_vcsel_pulse_period<PRE_RANGE>(period) = ") << ok << F(", period = ") << dec << period << endl;
		ok = tof.get_vcsel_pulse_period<VcselPeriodType::FINAL_RANGE>(period);
		display_memory(out);
		out << F("tof.get_vcsel_pulse_period<FINAL_RANGE>(period) = ") << ok << F(", period = ") << dec << period << endl;
		DEBUG(out);
	}

	{
		// The following block adds 3KB to program size (float arithmetic libs)
		float signal_rate = 0.0;
		ok = tof.get_signal_rate_limit(signal_rate);
		display_memory(out);
		out << F("tof.get_signal_rate_limit(signal_rate) = ") << ok << F(", signal_rate = ")
			<< fixed << signal_rate << endl;
		DEBUG(out);
	}

	{
		TOF::GetSPADInfoFuture future3{};
		error = tof.get_SPAD_info(future3);
		display_memory(out);
		out << F("tof.get_SPAD_info(future) = ") << dec << error << endl;
		time::delay_ms(500);
		DEBUG(out);
		out << F("future.status() = ") << future3.status() << endl;
		SPADInfo SPAD_info{};
		future3.get(SPAD_info);
		out << F("SPADInfo = ") << SPAD_info << endl;
		DEBUG(out);
	}

	{
		TOF::GetSequenceStepsTimeoutFuture future2{};
		error = tof.get_sequence_steps_timeout(future2);
		display_memory(out);
		out << F("tof.get_sequence_steps_timeout(future) = ") << dec << error << endl;
		time::delay_ms(100);
		DEBUG(out);
		out << F("future.status() = ") << future2.status() << endl;
		SequenceStepsTimeout timeouts{};
		future2.get(timeouts);
		out << F("tof.get_sequence_steps_timeout(timeouts) = ") << ok << flush
			<< F(", pre_range_vcsel_period_pclks = ") << dec << timeouts.pre_range_vcsel_period_pclks() << flush
			<< F(", final_range_vcsel_period_pclks = ") << dec << timeouts.final_range_vcsel_period_pclks() << flush
			<< F(", msrc_dss_tcc_mclks = ") << dec << timeouts.msrc_dss_tcc_mclks() << flush
			<< F(", pre_range_mclks = ") << dec << timeouts.pre_range_mclks() << flush
			<< F(", final_range_mclks = ") << dec << timeouts.final_range_mclks() << endl;
		// check calculated values
		out << F("timeouts.msrc_dss_tcc_us() = ") << dec << timeouts.msrc_dss_tcc_us() << flush
			<< F(", timeouts.pre_range_us() = ") << dec << timeouts.pre_range_us() << flush
			<< F(", timeouts.final_range_us() = ") << dec << timeouts.final_range_us() << endl;
		DEBUG(out);
	}

	{
		TOF::GetGPIOSettingsFuture future{};
		error = tof.get_GPIO_settings(future);
		display_memory(out);
		out << F("tof.get_GPIO_settings(future) = ") << dec << error << endl;
		time::delay_ms(100);
		DEBUG(out);
		out << F("future.status() = ") << future.status() << endl;
		GPIOSettings settings{};
		future.get(settings);
		out << F("GPIO setting=") << settings << endl;
	}

	{
		uint8_t status = 0;
		ok = tof.get_interrupt_status(status);
		display_memory(out);
		out << F("tof.get_interrupt_status(status) = ") << ok
			<< F(", status = ") << hex << status << endl;
	}

	manager.end();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

//TESTED_COMPONENT=src/systeminfo

#include <QtTest/QtTest>
 #include <QDesktopWidget>

#include "qsysteminfo.h"

QTM_USE_NAMESPACE
class tst_QSystemScreenSaver : public QObject
{
    Q_OBJECT

private slots:
   void initTestCase();
    void tst_screenSaverInhibited();
    void tst_setScreenSaverInhibit();
    void tst_setScreenSaverInhibited();

};

 void tst_QSystemScreenSaver::initTestCase()
 {

 }

void tst_QSystemScreenSaver::tst_screenSaverInhibited()
{
    QSystemScreenSaver si;
    bool enabled = si.screenSaverInhibited();
    QVERIFY( enabled || !enabled);
}

void tst_QSystemScreenSaver::tst_setScreenSaverInhibit()
{
    QSystemScreenSaver si;
    bool enabled = si.setScreenSaverInhibit();
    QVERIFY( enabled || !enabled);
}

void tst_QSystemScreenSaver::tst_setScreenSaverInhibited()
{
    QSystemScreenSaver si;
    QDesktopWidget wid;
    si.setScreenSaverInhibited(true);
    if(wid.screenCount() > 0) {
        QVERIFY(si.screenSaverInhibited());
    }
    si.setScreenSaverInhibited(false);
    QVERIFY(!si.screenSaverInhibited());
}

QTEST_MAIN(tst_QSystemScreenSaver)
#include "tst_qsystemscreensaver.moc"
<commit_msg>enhance autotest a bit<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

//TESTED_COMPONENT=src/systeminfo

#include <QtTest/QtTest>
 #include <QDesktopWidget>

#include "qsysteminfo.h"

QTM_USE_NAMESPACE
class tst_QSystemScreenSaver : public QObject
{
    Q_OBJECT

private slots:
   void initTestCase();
    void tst_screenSaverInhibited();
    void tst_setScreenSaverInhibit();
    void tst_setScreenSaverInhibited();

};

 void tst_QSystemScreenSaver::initTestCase()
 {

 }

void tst_QSystemScreenSaver::tst_screenSaverInhibited()
{
    QSystemScreenSaver si;
    QDesktopWidget wid;
   bool enabled = si.setScreenSaverInhibit();
    if(wid.screenCount() > 0) {
        QVERIFY( si.screenSaverInhibited() && enabled);
    } else{
        QVERIFY(!si.screenSaverInhibited() && !enabled);
    }
}

void tst_QSystemScreenSaver::tst_setScreenSaverInhibit()
{
    QSystemScreenSaver si;
    QDesktopWidget wid;
    bool enabled = si.setScreenSaverInhibit();
    if(wid.screenCount() > 0) {
        QVERIFY(enabled);
    } else{
        QVERIFY(!enabled);
    }
}

void tst_QSystemScreenSaver::tst_setScreenSaverInhibited()
{
    QSystemScreenSaver si;
    QDesktopWidget wid;
    si.setScreenSaverInhibited(true);
    if(wid.screenCount() > 0) {
        QVERIFY(si.screenSaverInhibited());
    } else{
        QVERIFY(!si.screenSaverInhibited());
    }
    si.setScreenSaverInhibited(false);
    QVERIFY(!si.screenSaverInhibited());
}

QTEST_MAIN(tst_QSystemScreenSaver)
#include "tst_qsystemscreensaver.moc"
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: wininetbackend.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 14:17:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _FIXEDVALUEBACKEND_HXX_
#define _FIXEDVALUEBACKEND_HXX_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XSINGLELAYERSTRATUM_HPP_
#include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XBACKENDCHANGESNOTIFIER_HPP_
#include <com/sun/star/configuration/backend/XBackendChangesNotifier.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#ifndef _RTL_STRING_HXX_
#include <rtl/string.hxx>
#endif

#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include <wininet.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace backend = css::configuration::backend ;

/**
  Implements the SingleLayerStratum service.
  */
class WinInetBackend : public ::cppu::WeakImplHelper2 <
        backend::XSingleLayerStratum,
        lang::XServiceInfo > {

    public :

        static WinInetBackend* createInstance(const uno::Reference<uno::XComponentContext>& xContext);

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

        virtual sal_Bool SAL_CALL
            supportsService( const rtl::OUString& aServiceName )
                throw (uno::RuntimeException) ;

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

        /**
          Provides the implementation name.

          @return   implementation name
          */
        static rtl::OUString SAL_CALL getBackendName(void) ;
        /**
          Provides the supported services names

          @return   service names
          */
        static uno::Sequence<rtl::OUString> SAL_CALL getBackendServiceNames(void) ;
        /**
          Provides the supported component nodes

          @return supported component nodes
        */
        static uno::Sequence<rtl::OUString> SAL_CALL getSupportedComponents(void) ;

        //XSingleLayerStratum
        virtual uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException,
                   lang::IllegalArgumentException) ;

        virtual uno::Reference<backend::XUpdatableLayer> SAL_CALL
        getUpdatableLayer( const rtl::OUString& aLayerId )
            throw (backend::BackendAccessException,
                   lang::NoSupportException,
                   lang::IllegalArgumentException) ;
    protected:
        /**
          Service constructor from a service factory.

          @param xContext   component context
          */
        WinInetBackend(const uno::Reference<uno::XComponentContext>& xContext)
            throw (backend::BackendAccessException);

        /** Destructor */
        ~WinInetBackend(void) ;

    private:

        uno::Reference<uno::XComponentContext> m_xContext ;
        uno::Reference<backend::XLayer> m_xSystemLayer ;

        // The wininet.dll module handle
        HMODULE m_hWinInetDll;
} ;

#endif // _FIXEDVALUEBACKEND_HXX_
<commit_msg>INTEGRATION: CWS changefileheader (1.4.154); FILE MERGED 2008/04/01 15:40:15 thb 1.4.154.3: #i85898# Stripping all external header guards 2008/04/01 12:41:11 thb 1.4.154.2: #i85898# Stripping all external header guards 2008/03/31 13:17:08 rt 1.4.154.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: wininetbackend.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _FIXEDVALUEBACKEND_HXX_
#define _FIXEDVALUEBACKEND_HXX_

#include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/configuration/backend/XBackendChangesNotifier.hpp>
#include <cppuhelper/implbase2.hxx>
#include <rtl/string.hxx>

#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include <wininet.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace backend = css::configuration::backend ;

/**
  Implements the SingleLayerStratum service.
  */
class WinInetBackend : public ::cppu::WeakImplHelper2 <
        backend::XSingleLayerStratum,
        lang::XServiceInfo > {

    public :

        static WinInetBackend* createInstance(const uno::Reference<uno::XComponentContext>& xContext);

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

        virtual sal_Bool SAL_CALL
            supportsService( const rtl::OUString& aServiceName )
                throw (uno::RuntimeException) ;

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

        /**
          Provides the implementation name.

          @return   implementation name
          */
        static rtl::OUString SAL_CALL getBackendName(void) ;
        /**
          Provides the supported services names

          @return   service names
          */
        static uno::Sequence<rtl::OUString> SAL_CALL getBackendServiceNames(void) ;
        /**
          Provides the supported component nodes

          @return supported component nodes
        */
        static uno::Sequence<rtl::OUString> SAL_CALL getSupportedComponents(void) ;

        //XSingleLayerStratum
        virtual uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException,
                   lang::IllegalArgumentException) ;

        virtual uno::Reference<backend::XUpdatableLayer> SAL_CALL
        getUpdatableLayer( const rtl::OUString& aLayerId )
            throw (backend::BackendAccessException,
                   lang::NoSupportException,
                   lang::IllegalArgumentException) ;
    protected:
        /**
          Service constructor from a service factory.

          @param xContext   component context
          */
        WinInetBackend(const uno::Reference<uno::XComponentContext>& xContext)
            throw (backend::BackendAccessException);

        /** Destructor */
        ~WinInetBackend(void) ;

    private:

        uno::Reference<uno::XComponentContext> m_xContext ;
        uno::Reference<backend::XLayer> m_xSystemLayer ;

        // The wininet.dll module handle
        HMODULE m_hWinInetDll;
} ;

#endif // _FIXEDVALUEBACKEND_HXX_
<|endoftext|>


<commit_before>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "cpputil.hh"
#include "ns.hh"
#include "errno.h"
#include "condvar.h"
#include "proc.hh"
#include "cpu.hh"
#include "percpu.hh"

//
// futexkey
//
// XXX(sbw) this uses kernel addresses as keys and probably
// isn't complete.  For example, a user thread might wait
// on a user address, then another thread might unmap that
// address.

typedef u64* futexkey_t;

u64
futexkey_hash(futexkey_t const& key)
{
  return (u64)key;
}

u64
futexkey_val(futexkey_t const& key)
{
  return *key;
}

int
futexkey(const u64* useraddr, vmap* vmap, futexkey_t* key)
{
  u64* kaddr;

  kaddr = (u64*)pagelookup(vmap, (uptr)useraddr);
  if (kaddr == nullptr) {
    cprintf("futexkey: pagelookup failed\n");
    return -1;
  }
  *key = kaddr;
  return 0;
}

//
// nscache
//
struct nscache {
  struct spinlock lock_;
  volatile u64 head_;
  volatile u64 tail_;
  xns<u32, proc*, proc::hash>* ns_[16];

  nscache();
  xns<u32, proc*, proc::hash>* alloc();
  bool cache(xns<u32, proc*, proc::hash>* ns);

  NEW_DELETE_OPS(nscache);
};

percpu<nscache> nscache_;

nscache::nscache(void)
{
  initlock(&lock_, "nscache::lock_", LOCKSTAT_FUTEX);
  head_ = 0;
  tail_ = 0;
}

xns<u32, proc*, proc::hash>*
nscache::alloc(void)
{
  xns<u32, proc*, proc::hash>* ns = nullptr;

  acquire(&lock_);
  if (head_ - tail_ > 0) {
    u64 i = tail_%NELEM(ns_);
    ++tail_;
    ns = ns_[i];
  }
  release(&lock_);
  return ns;
}

bool
nscache::cache(xns<u32, proc*, proc::hash>* ns)
{
  bool cached = false;

  acquire(&lock_);
  if (head_ - tail_ < NELEM(ns_)) {
    u64 i = head_%NELEM(ns_);
    ++head_;
    ns_[i] = ns;
    cached = true;
  }
  release(&lock_);
  return cached;
}

//
// futexaddr
//
struct futexaddr : public referenced, public rcu_freed
{
  static futexaddr* alloc(futexkey_t key);

  virtual void do_gc();
  virtual void onzero() const;

  futexkey_t key_;
  bool inserted_;
  struct spinlock lock_;

  xns<u32, proc*, proc::hash>* const nspid_;

private:
  futexaddr(futexkey_t key, xns<u32, proc*, proc::hash>* nspid);
  NEW_DELETE_OPS(futexaddr);
};

xns<futexkey_t, futexaddr*, futexkey_hash> *nsfutex __mpalign__;

futexaddr*
futexaddr::alloc(futexkey_t key)
{
  xns<u32, proc*, proc::hash>* nspid;
  futexaddr* fa;

  nspid = nscache_->alloc();
  if (nspid == nullptr)
    nspid = new xns<u32, proc*, proc::hash>(false);

  if (nspid == nullptr)
    return nullptr;
  fa = new futexaddr(key, nspid);
  if (fa == nullptr) {
    delete nspid;
    return nullptr;
  }

  return fa;
}

futexaddr::futexaddr(futexkey_t key, xns<u32, proc*, proc::hash>* nspid)
  : rcu_freed("futexaddr"), key_(key), inserted_(false), nspid_(nspid)
{
  initlock(&lock_, "futexaddr::lock_", LOCKSTAT_FUTEX);
}

void
futexaddr::do_gc(void)
{
  delete this;
}

void
futexaddr::onzero(void) const
{
  if (inserted_)
    assert(nsfutex->remove(key_, nullptr));
  // Normally deallocate members in the destructor, but in this case
  // we don't want to wait for the gc to fill the cache
  if (!nscache_->cache(nspid_))
    delete nspid_;
  gc_delayed((futexaddr*)this);
}

long
futexwait(futexkey_t key, u64 val, u64 timer)
{
  futexaddr* fa;

  {
    scoped_gc_epoch gc;
  again:
    fa = nsfutex->lookup(key);
    if (fa == nullptr) {
      fa = futexaddr::alloc(key);
      if (fa == nullptr) {
        cprintf("futexwait futexaddr::alloc failed\n");
        return -1;
      }
      if (nsfutex->insert(key, fa) < 0) {
        fa->dec();
        goto again;
      }
      fa->inserted_ = true;
    } else {
      if (!fa->tryinc()) {
        goto again;
      }
    }
  }
  assert(fa->key_ == key);

  acquire(&myproc()->futex_lock);
  auto cleanup = scoped_cleanup([&fa](){
    release(&myproc()->futex_lock);
    fa->dec();
  });

  // This first check is an optimization
  if (futexkey_val(fa->key_) != val)
    return -EWOULDBLOCK;

  if (fa->nspid_->insert(myproc()->pid, myproc()) < 0)
    return -1;

  if (futexkey_val(fa->key_) != val) {
    fa->nspid_->remove(myproc()->pid, nullptr);
    return -EWOULDBLOCK;
  }

  u64 nsecto = timer == 0 ? 0 : timer+nsectime();
  cv_sleepto(&myproc()->cv, &myproc()->futex_lock, nsecto);

  assert(fa->nspid_->remove(myproc()->pid, nullptr));
  return 0;
}

long
futexwake(futexkey_t key, u64 nwake)
{
  futexaddr* fa;
  u64 nwoke = 0;

  if (nwake == 0)
    return -1;

  scoped_gc_epoch gc;
  fa = nsfutex->lookup(key);
  if (fa == nullptr || !fa->tryinc())
    return 0;

  auto cleanup = scoped_cleanup([&fa](){
    fa->dec();
  });

  fa->nspid_->enumerate([&nwoke, &nwake](u32 pid, proc* p) {
    acquire(&p->futex_lock);
    cv_wakeup(&p->cv);
    release(&p->futex_lock);
    ++nwoke;
    if (nwoke >= nwake)
      return 1;
    return 0;
  });

  return 0;
}

void
initfutex(void)
{
  nsfutex = new xns<futexkey_t, futexaddr*, futexkey_hash>(false);
  if (nsfutex == 0)
    panic("initfutex");

  for (int i = 0; i < NCPU; i++)
    new (&nscache_[i]) nscache();
}
<commit_msg>Don't need futexaddr::lock_<commit_after>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "cpputil.hh"
#include "ns.hh"
#include "errno.h"
#include "condvar.h"
#include "proc.hh"
#include "cpu.hh"
#include "percpu.hh"

//
// futexkey
//
// XXX(sbw) this uses kernel addresses as keys and probably
// isn't complete.  For example, a user thread might wait
// on a user address, then another thread might unmap that
// address.

typedef u64* futexkey_t;

u64
futexkey_hash(futexkey_t const& key)
{
  return (u64)key;
}

u64
futexkey_val(futexkey_t const& key)
{
  return *key;
}

int
futexkey(const u64* useraddr, vmap* vmap, futexkey_t* key)
{
  u64* kaddr;

  kaddr = (u64*)pagelookup(vmap, (uptr)useraddr);
  if (kaddr == nullptr) {
    cprintf("futexkey: pagelookup failed\n");
    return -1;
  }
  *key = kaddr;
  return 0;
}

//
// nscache
//
struct nscache {
  struct spinlock lock_;
  volatile u64 head_;
  volatile u64 tail_;
  xns<u32, proc*, proc::hash>* ns_[16];

  nscache();
  xns<u32, proc*, proc::hash>* alloc();
  bool cache(xns<u32, proc*, proc::hash>* ns);

  NEW_DELETE_OPS(nscache);
};

percpu<nscache> nscache_;

nscache::nscache(void)
{
  initlock(&lock_, "nscache::lock_", LOCKSTAT_FUTEX);
  head_ = 0;
  tail_ = 0;
}

xns<u32, proc*, proc::hash>*
nscache::alloc(void)
{
  xns<u32, proc*, proc::hash>* ns = nullptr;

  acquire(&lock_);
  if (head_ - tail_ > 0) {
    u64 i = tail_%NELEM(ns_);
    ++tail_;
    ns = ns_[i];
  }
  release(&lock_);
  return ns;
}

bool
nscache::cache(xns<u32, proc*, proc::hash>* ns)
{
  bool cached = false;

  acquire(&lock_);
  if (head_ - tail_ < NELEM(ns_)) {
    u64 i = head_%NELEM(ns_);
    ++head_;
    ns_[i] = ns;
    cached = true;
  }
  release(&lock_);
  return cached;
}

//
// futexaddr
//
struct futexaddr : public referenced, public rcu_freed
{
  static futexaddr* alloc(futexkey_t key);

  virtual void do_gc();
  virtual void onzero() const;

  futexkey_t key_;
  bool inserted_;
  xns<u32, proc*, proc::hash>* const nspid_;

private:
  futexaddr(futexkey_t key, xns<u32, proc*, proc::hash>* nspid);
  NEW_DELETE_OPS(futexaddr);
};

xns<futexkey_t, futexaddr*, futexkey_hash> *nsfutex __mpalign__;

futexaddr*
futexaddr::alloc(futexkey_t key)
{
  xns<u32, proc*, proc::hash>* nspid;
  futexaddr* fa;

  nspid = nscache_->alloc();
  if (nspid == nullptr)
    nspid = new xns<u32, proc*, proc::hash>(false);

  if (nspid == nullptr)
    return nullptr;
  fa = new futexaddr(key, nspid);
  if (fa == nullptr) {
    delete nspid;
    return nullptr;
  }

  return fa;
}

futexaddr::futexaddr(futexkey_t key, xns<u32, proc*, proc::hash>* nspid)
  : rcu_freed("futexaddr"), key_(key), inserted_(false), nspid_(nspid)
{
}

void
futexaddr::do_gc(void)
{
  delete this;
}

void
futexaddr::onzero(void) const
{
  if (inserted_)
    assert(nsfutex->remove(key_, nullptr));
  // Normally deallocate members in the destructor, but in this case
  // we don't want to wait for the gc to fill the cache
  if (!nscache_->cache(nspid_))
    delete nspid_;
  gc_delayed((futexaddr*)this);
}

long
futexwait(futexkey_t key, u64 val, u64 timer)
{
  futexaddr* fa;

  {
    scoped_gc_epoch gc;
  again:
    fa = nsfutex->lookup(key);
    if (fa == nullptr) {
      fa = futexaddr::alloc(key);
      if (fa == nullptr) {
        cprintf("futexwait futexaddr::alloc failed\n");
        return -1;
      }
      if (nsfutex->insert(key, fa) < 0) {
        fa->dec();
        goto again;
      }
      fa->inserted_ = true;
    } else {
      if (!fa->tryinc()) {
        goto again;
      }
    }
  }
  assert(fa->key_ == key);

  acquire(&myproc()->futex_lock);
  auto cleanup = scoped_cleanup([&fa](){
    release(&myproc()->futex_lock);
    fa->dec();
  });

  // This first check is an optimization
  if (futexkey_val(fa->key_) != val)
    return -EWOULDBLOCK;

  if (fa->nspid_->insert(myproc()->pid, myproc()) < 0)
    return -1;

  if (futexkey_val(fa->key_) != val) {
    fa->nspid_->remove(myproc()->pid, nullptr);
    return -EWOULDBLOCK;
  }

  u64 nsecto = timer == 0 ? 0 : timer+nsectime();
  cv_sleepto(&myproc()->cv, &myproc()->futex_lock, nsecto);

  assert(fa->nspid_->remove(myproc()->pid, nullptr));
  return 0;
}

long
futexwake(futexkey_t key, u64 nwake)
{
  futexaddr* fa;
  u64 nwoke = 0;

  if (nwake == 0)
    return -1;

  scoped_gc_epoch gc;
  fa = nsfutex->lookup(key);
  if (fa == nullptr || !fa->tryinc())
    return 0;

  auto cleanup = scoped_cleanup([&fa](){
    fa->dec();
  });

  fa->nspid_->enumerate([&nwoke, &nwake](u32 pid, proc* p) {
    acquire(&p->futex_lock);
    cv_wakeup(&p->cv);
    release(&p->futex_lock);
    ++nwoke;
    if (nwoke >= nwake)
      return 1;
    return 0;
  });

  return 0;
}

void
initfutex(void)
{
  nsfutex = new xns<futexkey_t, futexaddr*, futexkey_hash>(false);
  if (nsfutex == 0)
    panic("initfutex");

  for (int i = 0; i < NCPU; i++)
    new (&nscache_[i]) nscache();
}
<|endoftext|>