<commit_before>/**
 * @file    Database.cpp
 * @ingroup SQLiteCpp
 * @brief   Management of a SQLite Database Connection.
 *
 * Copyright (c) 2012-2016 Sebastien Rombauts (sebastien.rombauts@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */
#include <SQLiteCpp/Database.h>

#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>

#include <sqlite3.h>
#include <fstream>
#include <string.h>

#ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC

namespace SQLite
{

const int   OPEN_READONLY   = SQLITE_OPEN_READONLY;
const int   OPEN_READWRITE  = SQLITE_OPEN_READWRITE;
const int   OPEN_CREATE     = SQLITE_OPEN_CREATE;
const int   OPEN_URI        = SQLITE_OPEN_URI;

const int   OK              = SQLITE_OK;

const char* VERSION         = SQLITE_VERSION;
const int   VERSION_NUMBER  = SQLITE_VERSION_NUMBER;

// Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept // nothrow
{
    return sqlite3_libversion();
}

// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept // nothrow
{
    return sqlite3_libversion_number();
}

// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const char* apFilename,
                   const int   aFlags         /* = SQLite::OPEN_READONLY*/,
                   const int   aBusyTimeoutMs /* = 0 */,
                   const char* apVfs          /* = NULL*/) :
    mpSQLite(NULL),
    mFilename(apFilename)
{
    const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs);
    if (SQLITE_OK != ret)
    {
        const SQLite::Exception exception(mpSQLite, ret); // must create before closing
        sqlite3_close(mpSQLite); // close is required even in case of error on opening
        throw exception;
    }
    if (aBusyTimeoutMs > 0)
    {
        setBusyTimeout(aBusyTimeoutMs);
    }
}

// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const std::string& aFilename,
                   const int          aFlags         /* = SQLite::OPEN_READONLY*/,
                   const int          aBusyTimeoutMs /* = 0 */,
                   const std::string& aVfs           /* = "" */) :
    mpSQLite(NULL),
    mFilename(aFilename)
{
    const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? NULL : aVfs.c_str());
    if (SQLITE_OK != ret)
    {
        const SQLite::Exception exception(mpSQLite, ret); // must create before closing
        sqlite3_close(mpSQLite); // close is required even in case of error on opening
        throw exception;
    }
    if (aBusyTimeoutMs > 0)
    {
        setBusyTimeout(aBusyTimeoutMs);
    }
}

// Close the SQLite database connection.
Database::~Database() noexcept // nothrow
{
    const int ret = sqlite3_close(mpSQLite);

    // Avoid unreferenced variable warning when build in release mode
    (void) ret;

    // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
    // Never throw an exception in a destructor :
    SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked");  // See SQLITECPP_ENABLE_ASSERT_HANDLER
}

/**
 * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
 *
 *  This is useful in multithreaded program to handle case where a table is locked for writting by a thread.
 *  Any other thread cannot access the table and will receive a SQLITE_BUSY error:
 *  setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error.
 *  Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;".
 *  Default busy timeout is 0ms.
 *
 * @param[in] aBusyTimeoutMs    Amount of milliseconds to wait before returning SQLITE_BUSY
 *
 * @throw SQLite::Exception in case of error
 */
void Database::setBusyTimeout(const int aBusyTimeoutMs) noexcept // nothrow
{
    const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs);
    check(ret);
}

// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries)
{
    const int ret = sqlite3_exec(mpSQLite, apQueries, NULL, NULL, NULL);
    check(ret);

    // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
    return sqlite3_changes(mpSQLite);
}

// Shortcut to execute a one step query and fetch the first column of the result.
// WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line
// (when the underlying temporary Statement and Column objects are destroyed)
// this is an issue only for pointer type result (ie. char* and blob)
// (use the Column copy-constructor)
Column Database::execAndGet(const char* apQuery)
{
    Statement query(*this, apQuery);
    (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
    return query.getColumn(0);
}

// Shortcut to test if a table exists.
bool Database::tableExists(const char* apTableName)
{
    Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?");
    query.bind(1, apTableName);
    (void)query.executeStep(); // Cannot return false, as the above query always return a result
    return (1 == query.getColumn(0).getInt());
}

// Get the rowid of the most recent successful INSERT into the database from the current connection.
long long Database::getLastInsertRowid() const noexcept // nothrow
{
    return sqlite3_last_insert_rowid(mpSQLite);
}

// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept // nothrow
{
    return sqlite3_total_changes(mpSQLite);
}

// Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept // nothrow
{
    return sqlite3_errcode(mpSQLite);
}

// Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept // nothrow
{
    return sqlite3_extended_errcode(mpSQLite);
}

// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept // nothrow
{
    return sqlite3_errmsg(mpSQLite);
}

// Attach a custom function to your sqlite database. Assumes UTF8 text representation.
// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html
void Database::createFunction(const char*   apFuncName,
                              int           aNbArg,
                              bool          abDeterministic,
                              void*         apApp,
                              void        (*apFunc)(sqlite3_context *, int, sqlite3_value **),
                              void        (*apStep)(sqlite3_context *, int, sqlite3_value **),
                              void        (*apFinal)(sqlite3_context *),   // NOLINT(readability/casting)
                              void        (*apDestroy)(void *))
{
    int TextRep = SQLITE_UTF8;
    // optimization if deterministic function (e.g. of nondeterministic function random())
    if (abDeterministic) {
        TextRep = TextRep|SQLITE_DETERMINISTIC;
    }
    const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep,
                                               apApp, apFunc, apStep, apFinal, apDestroy);
    check(ret);
}

// Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
{
#ifdef SQLITE_OMIT_LOAD_EXTENSION
    throw std::runtime_error("sqlite extensions are disabled");
#else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
    // Security warning:
    // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface.
    // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension()
    // disabled and prevent SQL injections from giving attackers access to extension loading capabilities.
    int ret = sqlite3_db_config(mpSQLite, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
#else
    int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif
    check(ret);

    ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0);
    check(ret);
#endif
}

// Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const
{
    int pass_len = static_cast<int>(aKey.length());
#ifdef SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const int ret = sqlite3_key(mpSQLite, aKey.c_str(), pass_len);
        check(ret);
    }
#else // SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
        throw exception;
    }
#endif // SQLITE_HAS_CODEC
}

// Reset the key for the current sqlite database instance.
void Database::rekey(const std::string& aNewKey) const
{
#ifdef SQLITE_HAS_CODEC
    int pass_len = aNewKey.length();
    if (pass_len > 0) {
        const int ret = sqlite3_rekey(mpSQLite, aNewKey.c_str(), pass_len);
        check(ret);
    } else {
        const int ret = sqlite3_rekey(mpSQLite, nullptr, 0);
        check(ret);
    }
#else // SQLITE_HAS_CODEC
    static_cast<void>(aNewKey); // silence unused parameter warning
    const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
    throw exception;
#endif // SQLITE_HAS_CODEC
}

// Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename)
{
    if (aFilename.length() > 0) {
        std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
        char header[16];
        if (fileBuffer.is_open()) {
            fileBuffer.seekg(0, std::ios::beg);
            fileBuffer.getline(header, 16);
            fileBuffer.close();
        } else {
            const SQLite::Exception exception("Error opening file: " + aFilename);
            throw exception;
        }
        return strncmp(header, "SQLite format 3\000", 16) == 0;
    }
    const SQLite::Exception exception("Could not open database, the aFilename parameter was empty.");
    throw exception;
}

}  // namespace SQLite
<commit_msg>Fixing unused parameter warning under Clang.<commit_after>/**
 * @file    Database.cpp
 * @ingroup SQLiteCpp
 * @brief   Management of a SQLite Database Connection.
 *
 * Copyright (c) 2012-2016 Sebastien Rombauts (sebastien.rombauts@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */
#include <SQLiteCpp/Database.h>

#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>

#include <sqlite3.h>
#include <fstream>
#include <string.h>

#ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC

namespace SQLite
{

const int   OPEN_READONLY   = SQLITE_OPEN_READONLY;
const int   OPEN_READWRITE  = SQLITE_OPEN_READWRITE;
const int   OPEN_CREATE     = SQLITE_OPEN_CREATE;
const int   OPEN_URI        = SQLITE_OPEN_URI;

const int   OK              = SQLITE_OK;

const char* VERSION         = SQLITE_VERSION;
const int   VERSION_NUMBER  = SQLITE_VERSION_NUMBER;

// Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept // nothrow
{
    return sqlite3_libversion();
}

// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept // nothrow
{
    return sqlite3_libversion_number();
}

// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const char* apFilename,
                   const int   aFlags         /* = SQLite::OPEN_READONLY*/,
                   const int   aBusyTimeoutMs /* = 0 */,
                   const char* apVfs          /* = NULL*/) :
    mpSQLite(NULL),
    mFilename(apFilename)
{
    const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs);
    if (SQLITE_OK != ret)
    {
        const SQLite::Exception exception(mpSQLite, ret); // must create before closing
        sqlite3_close(mpSQLite); // close is required even in case of error on opening
        throw exception;
    }
    if (aBusyTimeoutMs > 0)
    {
        setBusyTimeout(aBusyTimeoutMs);
    }
}

// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const std::string& aFilename,
                   const int          aFlags         /* = SQLite::OPEN_READONLY*/,
                   const int          aBusyTimeoutMs /* = 0 */,
                   const std::string& aVfs           /* = "" */) :
    mpSQLite(NULL),
    mFilename(aFilename)
{
    const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? NULL : aVfs.c_str());
    if (SQLITE_OK != ret)
    {
        const SQLite::Exception exception(mpSQLite, ret); // must create before closing
        sqlite3_close(mpSQLite); // close is required even in case of error on opening
        throw exception;
    }
    if (aBusyTimeoutMs > 0)
    {
        setBusyTimeout(aBusyTimeoutMs);
    }
}

// Close the SQLite database connection.
Database::~Database() noexcept // nothrow
{
    const int ret = sqlite3_close(mpSQLite);

    // Avoid unreferenced variable warning when build in release mode
    (void) ret;

    // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
    // Never throw an exception in a destructor :
    SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked");  // See SQLITECPP_ENABLE_ASSERT_HANDLER
}

/**
 * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
 *
 *  This is useful in multithreaded program to handle case where a table is locked for writting by a thread.
 *  Any other thread cannot access the table and will receive a SQLITE_BUSY error:
 *  setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error.
 *  Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;".
 *  Default busy timeout is 0ms.
 *
 * @param[in] aBusyTimeoutMs    Amount of milliseconds to wait before returning SQLITE_BUSY
 *
 * @throw SQLite::Exception in case of error
 */
void Database::setBusyTimeout(const int aBusyTimeoutMs) noexcept // nothrow
{
    const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs);
    check(ret);
}

// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries)
{
    const int ret = sqlite3_exec(mpSQLite, apQueries, NULL, NULL, NULL);
    check(ret);

    // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
    return sqlite3_changes(mpSQLite);
}

// Shortcut to execute a one step query and fetch the first column of the result.
// WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line
// (when the underlying temporary Statement and Column objects are destroyed)
// this is an issue only for pointer type result (ie. char* and blob)
// (use the Column copy-constructor)
Column Database::execAndGet(const char* apQuery)
{
    Statement query(*this, apQuery);
    (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
    return query.getColumn(0);
}

// Shortcut to test if a table exists.
bool Database::tableExists(const char* apTableName)
{
    Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?");
    query.bind(1, apTableName);
    (void)query.executeStep(); // Cannot return false, as the above query always return a result
    return (1 == query.getColumn(0).getInt());
}

// Get the rowid of the most recent successful INSERT into the database from the current connection.
long long Database::getLastInsertRowid() const noexcept // nothrow
{
    return sqlite3_last_insert_rowid(mpSQLite);
}

// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept // nothrow
{
    return sqlite3_total_changes(mpSQLite);
}

// Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept // nothrow
{
    return sqlite3_errcode(mpSQLite);
}

// Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept // nothrow
{
    return sqlite3_extended_errcode(mpSQLite);
}

// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept // nothrow
{
    return sqlite3_errmsg(mpSQLite);
}

// Attach a custom function to your sqlite database. Assumes UTF8 text representation.
// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html
void Database::createFunction(const char*   apFuncName,
                              int           aNbArg,
                              bool          abDeterministic,
                              void*         apApp,
                              void        (*apFunc)(sqlite3_context *, int, sqlite3_value **),
                              void        (*apStep)(sqlite3_context *, int, sqlite3_value **),
                              void        (*apFinal)(sqlite3_context *),   // NOLINT(readability/casting)
                              void        (*apDestroy)(void *))
{
    int TextRep = SQLITE_UTF8;
    // optimization if deterministic function (e.g. of nondeterministic function random())
    if (abDeterministic) {
        TextRep = TextRep|SQLITE_DETERMINISTIC;
    }
    const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep,
                                               apApp, apFunc, apStep, apFinal, apDestroy);
    check(ret);
}

// Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
{
#ifdef SQLITE_OMIT_LOAD_EXTENSION
	// Unused
	(void)apExtensionName;
	(void)apEntryPointName;

    throw std::runtime_error("sqlite extensions are disabled");
#else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
    // Security warning:
    // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface.
    // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension()
    // disabled and prevent SQL injections from giving attackers access to extension loading capabilities.
    int ret = sqlite3_db_config(mpSQLite, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
#else
    int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif
    check(ret);

    ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0);
    check(ret);
#endif
}

// Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const
{
    int pass_len = static_cast<int>(aKey.length());
#ifdef SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const int ret = sqlite3_key(mpSQLite, aKey.c_str(), pass_len);
        check(ret);
    }
#else // SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
        throw exception;
    }
#endif // SQLITE_HAS_CODEC
}

// Reset the key for the current sqlite database instance.
void Database::rekey(const std::string& aNewKey) const
{
#ifdef SQLITE_HAS_CODEC
    int pass_len = aNewKey.length();
    if (pass_len > 0) {
        const int ret = sqlite3_rekey(mpSQLite, aNewKey.c_str(), pass_len);
        check(ret);
    } else {
        const int ret = sqlite3_rekey(mpSQLite, nullptr, 0);
        check(ret);
    }
#else // SQLITE_HAS_CODEC
    static_cast<void>(aNewKey); // silence unused parameter warning
    const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
    throw exception;
#endif // SQLITE_HAS_CODEC
}

// Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename)
{
    if (aFilename.length() > 0) {
        std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
        char header[16];
        if (fileBuffer.is_open()) {
            fileBuffer.seekg(0, std::ios::beg);
            fileBuffer.getline(header, 16);
            fileBuffer.close();
        } else {
            const SQLite::Exception exception("Error opening file: " + aFilename);
            throw exception;
        }
        return strncmp(header, "SQLite format 3\000", 16) == 0;
    }
    const SQLite::Exception exception("Could not open database, the aFilename parameter was empty.");
    throw exception;
}

}  // namespace SQLite
<|endoftext|>


<commit_before>#pragma once

#include <experimental/optional>
#include "keys.hh"
#include "dht/i_partitioner.hh"
#include "enum_set.hh"

namespace query {

// A range which can have inclusive, exclusive or open-ended bounds on each end.
template<typename T>
class range {
    template <typename U>
    using optional = std::experimental::optional<U>;
public:
    class bound {
        T _value;
        bool _inclusive;
    public:
        bound(T value, bool inclusive = true)
            : _value(std::move(value))
            , _inclusive(inclusive)
        { }
        const T& value() const & { return _value; }
        T&& value() && { return std::move(_value); }
        bool is_inclusive() const { return _inclusive; }
    };
private:
    optional<bound> _start;
    optional<bound> _end;
    bool _singular;
public:
    range(optional<bound> start, optional<bound> end, bool singular = false)
        : _start(std::move(start))
        , _end(std::move(end))
        , _singular(singular)
    { }
    range(T value)
        : _start(bound(std::move(value), true))
        , _end()
        , _singular(true)
    { }
    range() : range({}, {}) {}
public:
    // the point is before the range (works only for non wrapped ranges)
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool before(const T& point, Comparator&& cmp) const {
        assert(!is_wrap_around(cmp));
        if (!start()) {
            return false; //open start, no points before
        }
        auto r = cmp(point, start()->value());
        if (r < 0) {
            return true;
        }
        if (!start()->is_inclusive() && r == 0) {
            return true;
        }
        return false;
    }
    // the point is after the range (works only for non wrapped ranges)
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool after(const T& point, Comparator&& cmp) const {
        assert(!is_wrap_around(cmp));
        if (!end()) {
            return false; //open end, no points after
        }
        auto r = cmp(end()->value(), point);
        if (r < 0) {
            return true;
        }
        if (!end()->is_inclusive() && r == 0) {
            return true;
        }
        return false;
    }
    static range make(bound start, bound end) {
        return range({std::move(start)}, {std::move(end)});
    }
    static range make_open_ended_both_sides() {
        return {{}, {}};
    }
    static range make_singular(T value) {
        return {std::move(value)};
    }
    static range make_starting_with(bound b) {
        return {{std::move(b)}, {}};
    }
    static range make_ending_with(bound b) {
        return {{}, {std::move(b)}};
    }
    bool is_singular() const {
        return _singular;
    }
    bool is_full() const {
        return !_start && !_end;
    }
    void reverse() {
        if (!_singular) {
            std::swap(_start, _end);
        }
    }
    const optional<bound>& start() const {
        return _start;
    }
    const optional<bound>& end() const {
        return _singular ? _start : _end;
    }
    // end is smaller than start
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool is_wrap_around(Comparator&& cmp) const {
        if (_end && _start) {
            return cmp(end()->value(), start()->value()) < 0;
        } else {
            return false; // open ended range never wraps around
        }
    }
    // Converts a wrap-around range to two non-wrap-around ranges.
    // Call only when is_wrap_around().
    std::pair<range, range> unwrap() const {
        return {
            { start(), {} },
            { {}, end() }
        };
    }
    // the point is inside the range
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool contains(const T& point, Comparator&& cmp) const {
        if (is_wrap_around(cmp)) {
            // wrapped range contains point if reverse does not contain it
            return !range::make({end()->value(), !_end->is_inclusive()}, {start()->value(), !_start->is_inclusive()}).contains(point, cmp);
        } else {
            return !before(point, cmp) && !after(point, cmp);
        }
    }
    // split range in two around a split_point. split_point has to be inside the range
    // split_point will belong to first range
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    std::pair<range<T>, range<T>> split(const T& split_point, Comparator&& cmp) const {
        assert(contains(split_point, std::forward<Comparator>(cmp)));
        range left(start(), bound(split_point));
        range right(bound(split_point, false), end());
        return std::make_pair(std::move(left), std::move(right));
    }
    // Transforms this range into a new range of a different value type
    // Supplied transformer should transform value of type T (the old type) into value of type U (the new type).
    template<typename U, typename Transformer>
    range<U> transform(Transformer&& transformer) && {
        auto t = [&transformer] (std::experimental::optional<bound>&& b)
            -> std::experimental::optional<typename query::range<U>::bound>
        {
            if (!b) {
                return {};
            }
            return { { transformer(std::move(*b).value()), b->is_inclusive() } };
        };
        return range<U>(t(std::move(_start)), t(std::move(_end)), _singular);
    }

private:
    template<typename U>
    static auto serialized_size(U& t) -> decltype(t.serialized_size()) {
        return t.serialized_size();
    }
    template<typename U>
    static auto serialized_size(U& t) -> decltype(t.representation().size()) {
        return t.representation().size() + serialize_int32_size;
    }
    template<typename U>
    static auto serialize(bytes::iterator& out, const U& t) -> decltype(t.serialize(out)) {
        return t.serialize(out);
    }
    template<typename U>
    static auto serialize(bytes::iterator& out, const U& t) -> decltype(t.representation(), void()) {
        auto v = t.representation();
        serialize_int32(out, v.size());
        out = std::copy(v.begin(), v.end(), out);
    }
    template<typename U>
    static auto deserialize_type(bytes_view& in) -> decltype(U::deserialize(in)) {
        return U::deserialize(in);
    }
    template<typename U>
    static auto deserialize_type(bytes_view& in) -> decltype(U::from_bytes(bytes())) {
        bytes v;
        uint32_t size = read_simple<uint32_t>(in);
        return U::from_bytes(to_bytes(read_simple_bytes(in, size)));
    }
public:
    size_t serialized_size() const {
        auto bound_size = [this] (const optional<bound>& b) {
            size_t size = serialize_bool_size; // if optional is armed
            if (b) {
                size += serialized_size(b.value().value());
                size += serialize_bool_size; // _inclusive
            }
            return size;
        };
        return serialize_bool_size // singular
                + bound_size(_start) + bound_size(_end);
    }

    void serialize(bytes::iterator& out) const {
        auto serialize_bound = [this] (bytes::iterator& out, const optional<bound>& b) {
            if (b) {
                serialize_bool(out, true);
                serialize(out, b.value().value());
                serialize_bool(out, b.value().is_inclusive());
            } else {
                serialize_bool(out, false);
            }
        };
        serialize_bound(out, _start);
        serialize_bound(out, _end);
        serialize_bool(out, is_singular());
    }

    static range deserialize(bytes_view& in) {
        auto deserialize_bound = [](bytes_view& in) {
            optional<bound> b;
            bool armed = read_simple<bool>(in);
            if (!armed) {
                return b;
            } else {
                T t = deserialize_type<T>(in);
                bool inc = read_simple<bool>(in);
                b.emplace(std::move(t), inc);
            }
            return b;
        };
        auto s = deserialize_bound(in);
        auto e = deserialize_bound(in);
        bool singular = read_simple<bool>(in);
        return range(std::move(s), std::move(e), singular);
    }

    template<typename U>
    friend std::ostream& operator<<(std::ostream& out, const range<U>& r);
};

template<typename U>
std::ostream& operator<<(std::ostream& out, const range<U>& r) {
    if (r.is_singular()) {
        return out << "==" << r.start()->value();
    }

    if (!r.start()) {
        out << "(-inf, ";
    } else {
        if (r.start()->is_inclusive()) {
            out << "[";
        } else {
            out << "(";
        }
        out << r.start()->value() << ", ";
    }

    if (!r.end()) {
        out << "+inf)";
    } else {
        out << r.end()->value();
        if (r.end()->is_inclusive()) {
            out << "]";
        } else {
            out << ")";
        }
    }

    return out;
}

using ring_position = dht::ring_position;
using partition_range = range<ring_position>;
using clustering_range = range<clustering_key_prefix>;

extern const partition_range full_partition_range;

// FIXME: Move this to i_partitioner.hh after query::range<> is moved to utils/range.hh
query::partition_range to_partition_range(query::range<dht::token>);

inline
bool is_wrap_around(const query::partition_range& range, const schema& s) {
    return range.is_wrap_around(dht::ring_position_comparator(s));
}

// Specifies subset of rows, columns and cell attributes to be returned in a query.
// Can be accessed across cores.
class partition_slice {
public:
    enum class option { send_clustering_key, send_partition_key, send_timestamp_and_expiry, reversed };
    using option_set = enum_set<super_enum<option,
        option::send_clustering_key,
        option::send_partition_key,
        option::send_timestamp_and_expiry,
        option::reversed>>;
public:
    std::vector<clustering_range> row_ranges;
    std::vector<column_id> static_columns; // TODO: consider using bitmap
    std::vector<column_id> regular_columns;  // TODO: consider using bitmap
    option_set options;
public:
    partition_slice(std::vector<clustering_range> row_ranges, std::vector<column_id> static_columns,
        std::vector<column_id> regular_columns, option_set options)
        : row_ranges(std::move(row_ranges))
        , static_columns(std::move(static_columns))
        , regular_columns(std::move(regular_columns))
        , options(options)
    { }
    friend std::ostream& operator<<(std::ostream& out, const partition_slice& ps);
};

constexpr auto max_rows = std::numeric_limits<uint32_t>::max();

// Full specification of a query to the database.
// Intended for passing across replicas.
// Can be accessed across cores.
class read_command {
public:
    utils::UUID cf_id;
    partition_slice slice;
    uint32_t row_limit;
    gc_clock::time_point timestamp;
public:
    read_command(const utils::UUID& cf_id, partition_slice slice, uint32_t row_limit = max_rows, gc_clock::time_point now = gc_clock::now())
        : cf_id(cf_id)
        , slice(std::move(slice))
        , row_limit(row_limit)
        , timestamp(now)
    { }

    size_t serialized_size() const;
    void serialize(bytes::iterator& out) const;
    static read_command deserialize(bytes_view& v);

    friend std::ostream& operator<<(std::ostream& out, const read_command& r);
};

}
<commit_msg>range: Fix is_wrap_around()<commit_after>#pragma once

#include <experimental/optional>
#include "keys.hh"
#include "dht/i_partitioner.hh"
#include "enum_set.hh"

namespace query {

// A range which can have inclusive, exclusive or open-ended bounds on each end.
template<typename T>
class range {
    template <typename U>
    using optional = std::experimental::optional<U>;
public:
    class bound {
        T _value;
        bool _inclusive;
    public:
        bound(T value, bool inclusive = true)
            : _value(std::move(value))
            , _inclusive(inclusive)
        { }
        const T& value() const & { return _value; }
        T&& value() && { return std::move(_value); }
        bool is_inclusive() const { return _inclusive; }
    };
private:
    optional<bound> _start;
    optional<bound> _end;
    bool _singular;
public:
    range(optional<bound> start, optional<bound> end, bool singular = false)
        : _start(std::move(start))
        , _end(std::move(end))
        , _singular(singular)
    { }
    range(T value)
        : _start(bound(std::move(value), true))
        , _end()
        , _singular(true)
    { }
    range() : range({}, {}) {}
public:
    // the point is before the range (works only for non wrapped ranges)
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool before(const T& point, Comparator&& cmp) const {
        assert(!is_wrap_around(cmp));
        if (!start()) {
            return false; //open start, no points before
        }
        auto r = cmp(point, start()->value());
        if (r < 0) {
            return true;
        }
        if (!start()->is_inclusive() && r == 0) {
            return true;
        }
        return false;
    }
    // the point is after the range (works only for non wrapped ranges)
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool after(const T& point, Comparator&& cmp) const {
        assert(!is_wrap_around(cmp));
        if (!end()) {
            return false; //open end, no points after
        }
        auto r = cmp(end()->value(), point);
        if (r < 0) {
            return true;
        }
        if (!end()->is_inclusive() && r == 0) {
            return true;
        }
        return false;
    }
    static range make(bound start, bound end) {
        return range({std::move(start)}, {std::move(end)});
    }
    static range make_open_ended_both_sides() {
        return {{}, {}};
    }
    static range make_singular(T value) {
        return {std::move(value)};
    }
    static range make_starting_with(bound b) {
        return {{std::move(b)}, {}};
    }
    static range make_ending_with(bound b) {
        return {{}, {std::move(b)}};
    }
    bool is_singular() const {
        return _singular;
    }
    bool is_full() const {
        return !_start && !_end;
    }
    void reverse() {
        if (!_singular) {
            std::swap(_start, _end);
        }
    }
    const optional<bound>& start() const {
        return _start;
    }
    const optional<bound>& end() const {
        return _singular ? _start : _end;
    }
    // Range is a wrap around if end value is smaller than the start value
    // or they're equal and at least one bound is not inclusive.
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool is_wrap_around(Comparator&& cmp) const {
        if (_end && _start) {
            auto r = cmp(end()->value(), start()->value());
            return r < 0
                   || (r == 0 && (!start()->is_inclusive() || !end()->is_inclusive()));
        } else {
            return false; // open ended range or singular range don't wrap around
        }
    }
    // Converts a wrap-around range to two non-wrap-around ranges.
    // Call only when is_wrap_around().
    std::pair<range, range> unwrap() const {
        return {
            { start(), {} },
            { {}, end() }
        };
    }
    // the point is inside the range
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    bool contains(const T& point, Comparator&& cmp) const {
        if (is_wrap_around(cmp)) {
            auto unwrapped = unwrap();
            return unwrapped.first.contains(point, cmp)
                   || unwrapped.second.contains(point, cmp);
        } else {
            return !before(point, cmp) && !after(point, cmp);
        }
    }
    // split range in two around a split_point. split_point has to be inside the range
    // split_point will belong to first range
    // Comparator must define a total ordering on T.
    template<typename Comparator>
    std::pair<range<T>, range<T>> split(const T& split_point, Comparator&& cmp) const {
        assert(contains(split_point, std::forward<Comparator>(cmp)));
        range left(start(), bound(split_point));
        range right(bound(split_point, false), end());
        return std::make_pair(std::move(left), std::move(right));
    }
    // Transforms this range into a new range of a different value type
    // Supplied transformer should transform value of type T (the old type) into value of type U (the new type).
    template<typename U, typename Transformer>
    range<U> transform(Transformer&& transformer) && {
        auto t = [&transformer] (std::experimental::optional<bound>&& b)
            -> std::experimental::optional<typename query::range<U>::bound>
        {
            if (!b) {
                return {};
            }
            return { { transformer(std::move(*b).value()), b->is_inclusive() } };
        };
        return range<U>(t(std::move(_start)), t(std::move(_end)), _singular);
    }

private:
    template<typename U>
    static auto serialized_size(U& t) -> decltype(t.serialized_size()) {
        return t.serialized_size();
    }
    template<typename U>
    static auto serialized_size(U& t) -> decltype(t.representation().size()) {
        return t.representation().size() + serialize_int32_size;
    }
    template<typename U>
    static auto serialize(bytes::iterator& out, const U& t) -> decltype(t.serialize(out)) {
        return t.serialize(out);
    }
    template<typename U>
    static auto serialize(bytes::iterator& out, const U& t) -> decltype(t.representation(), void()) {
        auto v = t.representation();
        serialize_int32(out, v.size());
        out = std::copy(v.begin(), v.end(), out);
    }
    template<typename U>
    static auto deserialize_type(bytes_view& in) -> decltype(U::deserialize(in)) {
        return U::deserialize(in);
    }
    template<typename U>
    static auto deserialize_type(bytes_view& in) -> decltype(U::from_bytes(bytes())) {
        bytes v;
        uint32_t size = read_simple<uint32_t>(in);
        return U::from_bytes(to_bytes(read_simple_bytes(in, size)));
    }
public:
    size_t serialized_size() const {
        auto bound_size = [this] (const optional<bound>& b) {
            size_t size = serialize_bool_size; // if optional is armed
            if (b) {
                size += serialized_size(b.value().value());
                size += serialize_bool_size; // _inclusive
            }
            return size;
        };
        return serialize_bool_size // singular
                + bound_size(_start) + bound_size(_end);
    }

    void serialize(bytes::iterator& out) const {
        auto serialize_bound = [this] (bytes::iterator& out, const optional<bound>& b) {
            if (b) {
                serialize_bool(out, true);
                serialize(out, b.value().value());
                serialize_bool(out, b.value().is_inclusive());
            } else {
                serialize_bool(out, false);
            }
        };
        serialize_bound(out, _start);
        serialize_bound(out, _end);
        serialize_bool(out, is_singular());
    }

    static range deserialize(bytes_view& in) {
        auto deserialize_bound = [](bytes_view& in) {
            optional<bound> b;
            bool armed = read_simple<bool>(in);
            if (!armed) {
                return b;
            } else {
                T t = deserialize_type<T>(in);
                bool inc = read_simple<bool>(in);
                b.emplace(std::move(t), inc);
            }
            return b;
        };
        auto s = deserialize_bound(in);
        auto e = deserialize_bound(in);
        bool singular = read_simple<bool>(in);
        return range(std::move(s), std::move(e), singular);
    }

    template<typename U>
    friend std::ostream& operator<<(std::ostream& out, const range<U>& r);
};

template<typename U>
std::ostream& operator<<(std::ostream& out, const range<U>& r) {
    if (r.is_singular()) {
        return out << "==" << r.start()->value();
    }

    if (!r.start()) {
        out << "(-inf, ";
    } else {
        if (r.start()->is_inclusive()) {
            out << "[";
        } else {
            out << "(";
        }
        out << r.start()->value() << ", ";
    }

    if (!r.end()) {
        out << "+inf)";
    } else {
        out << r.end()->value();
        if (r.end()->is_inclusive()) {
            out << "]";
        } else {
            out << ")";
        }
    }

    return out;
}

using ring_position = dht::ring_position;
using partition_range = range<ring_position>;
using clustering_range = range<clustering_key_prefix>;

extern const partition_range full_partition_range;

// FIXME: Move this to i_partitioner.hh after query::range<> is moved to utils/range.hh
query::partition_range to_partition_range(query::range<dht::token>);

inline
bool is_wrap_around(const query::partition_range& range, const schema& s) {
    return range.is_wrap_around(dht::ring_position_comparator(s));
}

// Specifies subset of rows, columns and cell attributes to be returned in a query.
// Can be accessed across cores.
class partition_slice {
public:
    enum class option { send_clustering_key, send_partition_key, send_timestamp_and_expiry, reversed };
    using option_set = enum_set<super_enum<option,
        option::send_clustering_key,
        option::send_partition_key,
        option::send_timestamp_and_expiry,
        option::reversed>>;
public:
    std::vector<clustering_range> row_ranges;
    std::vector<column_id> static_columns; // TODO: consider using bitmap
    std::vector<column_id> regular_columns;  // TODO: consider using bitmap
    option_set options;
public:
    partition_slice(std::vector<clustering_range> row_ranges, std::vector<column_id> static_columns,
        std::vector<column_id> regular_columns, option_set options)
        : row_ranges(std::move(row_ranges))
        , static_columns(std::move(static_columns))
        , regular_columns(std::move(regular_columns))
        , options(options)
    { }
    friend std::ostream& operator<<(std::ostream& out, const partition_slice& ps);
};

constexpr auto max_rows = std::numeric_limits<uint32_t>::max();

// Full specification of a query to the database.
// Intended for passing across replicas.
// Can be accessed across cores.
class read_command {
public:
    utils::UUID cf_id;
    partition_slice slice;
    uint32_t row_limit;
    gc_clock::time_point timestamp;
public:
    read_command(const utils::UUID& cf_id, partition_slice slice, uint32_t row_limit = max_rows, gc_clock::time_point now = gc_clock::now())
        : cf_id(cf_id)
        , slice(std::move(slice))
        , row_limit(row_limit)
        , timestamp(now)
    { }

    size_t serialized_size() const;
    void serialize(bytes::iterator& out) const;
    static read_command deserialize(bytes_view& v);

    friend std::ostream& operator<<(std::ostream& out, const read_command& r);
};

}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2013, Taiga Nomi
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "tiny_dnn/tiny_dnn.h"

using namespace tiny_dnn;
using namespace tiny_dnn::activation;

static void construct_net(network<sequential>& nn) {
    // connection table [Y.Lecun, 1998 Table.1]
#define O true
#define X false
    static const bool tbl[] = {
        O, X, X, X, O, O, O, X, X, O, O, O, O, X, O, O,
        O, O, X, X, X, O, O, O, X, X, O, O, O, O, X, O,
        O, O, O, X, X, X, O, O, O, X, X, O, X, O, O, O,
        X, O, O, O, X, X, O, O, O, O, X, X, O, X, O, O,
        X, X, O, O, O, X, X, O, O, O, O, X, O, O, X, O,
        X, X, X, O, O, O, X, X, O, O, O, O, X, O, O, O
    };
#undef O
#undef X

    // by default will use backend_t::tiny_dnn unless you compiled
    // with -DUSE_AVX=ON and your device supports AVX intrinsics
    core::backend_t backend_type = core::default_engine();

    // construct nets
    //
    // C : convolution
    // S : sub-sampling
    // F : fully connected
    nn << convolutional_layer<tan_h>(32, 32, 5, 1, 6,  // C1, 1@32x32-in, 6@28x28-out
            padding::valid, true, 1, 1, backend_type)
       << average_pooling_layer<tan_h>(28, 28, 6, 2)   // S2, 6@28x28-in, 6@14x14-out
       << convolutional_layer<tan_h>(14, 14, 5, 6, 16, // C3, 6@14x14-in, 16@10x10-in
            connection_table(tbl, 6, 16),
            padding::valid, true, 1, 1, backend_type)
       << average_pooling_layer<tan_h>(10, 10, 16, 2)  // S4, 16@10x10-in, 16@5x5-out
       << convolutional_layer<tan_h>(5, 5, 5, 16, 120, // C5, 16@5x5-in, 120@1x1-out
            padding::valid, true, 1, 1, backend_type)
       << fully_connected_layer<tan_h>(120, 10,        // F6, 120-in, 10-out
            true, backend_type)
    ;
}

static void train_lenet(const std::string& data_dir_path) {
    // specify loss-function and learning strategy
    network<sequential> nn;
    adagrad optimizer;

    construct_net(nn);

    std::cout << "load models..." << std::endl;

    // load MNIST dataset
    std::vector<label_t> train_labels, test_labels;
    std::vector<vec_t> train_images, test_images;

    parse_mnist_labels(data_dir_path + "/train-labels.idx1-ubyte",
                       &train_labels);
    parse_mnist_images(data_dir_path + "/train-images.idx3-ubyte",
                       &train_images, -1.0, 1.0, 2, 2);
    parse_mnist_labels(data_dir_path + "/t10k-labels.idx1-ubyte",
                       &test_labels);
    parse_mnist_images(data_dir_path + "/t10k-images.idx3-ubyte",
                       &test_images, -1.0, 1.0, 2, 2);

    std::cout << "start training" << std::endl;

    progress_display disp(static_cast<unsigned long>(train_images.size()));
    timer t;
    int minibatch_size = 10;
    int num_epochs = 30;

    optimizer.alpha *= static_cast<tiny_dnn::float_t>(std::sqrt(minibatch_size));

    // create callback
    auto on_enumerate_epoch = [&](){
        std::cout << t.elapsed() << "s elapsed." << std::endl;
        tiny_dnn::result res = nn.test(test_images, test_labels);
        std::cout << res.num_success << "/" << res.num_total << std::endl;

        disp.restart(static_cast<unsigned long>(train_images.size()));
        t.restart();
    };

    auto on_enumerate_minibatch = [&](){
        disp += minibatch_size;
    };

    // training
    nn.train<mse>(optimizer, train_images, train_labels, minibatch_size, num_epochs,
             on_enumerate_minibatch, on_enumerate_epoch);

    std::cout << "end training." << std::endl;

    // test and show results
    nn.test(test_images, test_labels).print_detail(std::cout);

    // save network model & trained weights
    nn.save("LeNet-model");
}

int main(int argc, char **argv) {
    if (argc != 2) {
        std::cerr << "Usage : " << argv[0]
                  << " path_to_data (example:../data)" << std::endl;
        return -1;
    }
    train_lenet(argv[1]);
    return 0;
}
<commit_msg>Typo fix (#404)<commit_after>/*
    Copyright (c) 2013, Taiga Nomi
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "tiny_dnn/tiny_dnn.h"

using namespace tiny_dnn;
using namespace tiny_dnn::activation;

static void construct_net(network<sequential>& nn) {
    // connection table [Y.Lecun, 1998 Table.1]
#define O true
#define X false
    static const bool tbl[] = {
        O, X, X, X, O, O, O, X, X, O, O, O, O, X, O, O,
        O, O, X, X, X, O, O, O, X, X, O, O, O, O, X, O,
        O, O, O, X, X, X, O, O, O, X, X, O, X, O, O, O,
        X, O, O, O, X, X, O, O, O, O, X, X, O, X, O, O,
        X, X, O, O, O, X, X, O, O, O, O, X, O, O, X, O,
        X, X, X, O, O, O, X, X, O, O, O, O, X, O, O, O
    };
#undef O
#undef X

    // by default will use backend_t::tiny_dnn unless you compiled
    // with -DUSE_AVX=ON and your device supports AVX intrinsics
    core::backend_t backend_type = core::default_engine();

    // construct nets
    //
    // C : convolution
    // S : sub-sampling
    // F : fully connected
    nn << convolutional_layer<tan_h>(32, 32, 5, 1, 6,  // C1, 1@32x32-in, 6@28x28-out
            padding::valid, true, 1, 1, backend_type)
       << average_pooling_layer<tan_h>(28, 28, 6, 2)   // S2, 6@28x28-in, 6@14x14-out
       << convolutional_layer<tan_h>(14, 14, 5, 6, 16, // C3, 6@14x14-in, 16@10x10-out
            connection_table(tbl, 6, 16),
            padding::valid, true, 1, 1, backend_type)
       << average_pooling_layer<tan_h>(10, 10, 16, 2)  // S4, 16@10x10-in, 16@5x5-out
       << convolutional_layer<tan_h>(5, 5, 5, 16, 120, // C5, 16@5x5-in, 120@1x1-out
            padding::valid, true, 1, 1, backend_type)
       << fully_connected_layer<tan_h>(120, 10,        // F6, 120-in, 10-out
            true, backend_type)
    ;
}

static void train_lenet(const std::string& data_dir_path) {
    // specify loss-function and learning strategy
    network<sequential> nn;
    adagrad optimizer;

    construct_net(nn);

    std::cout << "load models..." << std::endl;

    // load MNIST dataset
    std::vector<label_t> train_labels, test_labels;
    std::vector<vec_t> train_images, test_images;

    parse_mnist_labels(data_dir_path + "/train-labels.idx1-ubyte",
                       &train_labels);
    parse_mnist_images(data_dir_path + "/train-images.idx3-ubyte",
                       &train_images, -1.0, 1.0, 2, 2);
    parse_mnist_labels(data_dir_path + "/t10k-labels.idx1-ubyte",
                       &test_labels);
    parse_mnist_images(data_dir_path + "/t10k-images.idx3-ubyte",
                       &test_images, -1.0, 1.0, 2, 2);

    std::cout << "start training" << std::endl;

    progress_display disp(static_cast<unsigned long>(train_images.size()));
    timer t;
    int minibatch_size = 10;
    int num_epochs = 30;

    optimizer.alpha *= static_cast<tiny_dnn::float_t>(std::sqrt(minibatch_size));

    // create callback
    auto on_enumerate_epoch = [&](){
        std::cout << t.elapsed() << "s elapsed." << std::endl;
        tiny_dnn::result res = nn.test(test_images, test_labels);
        std::cout << res.num_success << "/" << res.num_total << std::endl;

        disp.restart(static_cast<unsigned long>(train_images.size()));
        t.restart();
    };

    auto on_enumerate_minibatch = [&](){
        disp += minibatch_size;
    };

    // training
    nn.train<mse>(optimizer, train_images, train_labels, minibatch_size, num_epochs,
             on_enumerate_minibatch, on_enumerate_epoch);

    std::cout << "end training." << std::endl;

    // test and show results
    nn.test(test_images, test_labels).print_detail(std::cout);

    // save network model & trained weights
    nn.save("LeNet-model");
}

int main(int argc, char **argv) {
    if (argc != 2) {
        std::cerr << "Usage : " << argv[0]
                  << " path_to_data (example:../data)" << std::endl;
        return -1;
    }
    train_lenet(argv[1]);
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <petro/parser.hpp>
#include <petro/box/all.hpp>

#include <fstream>
#include <sstream>
#include <string>
#include <memory>

uint32_t read_sample_size(std::istream& file)
{
    std::vector<uint8_t> data(4);
    file.read((char*)data.data(), data.size());

    uint32_t result =
       (uint32_t) data[0] << 24 |
       (uint32_t) data[1] << 16 |
       (uint32_t) data[2] << 8  |
       (uint32_t) data[3];
    return result;
}

int main(int argc, char* argv[])
{
    if (argc != 3 || std::string(argv[1]) == "--help")
    {
        auto usage = "./mp4_to_h264 MP4_INPUT H264_OUTPUT";
        std::cout << usage << std::endl;
        return 0;
    }

    auto filename = std::string(argv[1]);

    std::ifstream check(filename, std::ios::binary);

    if (!check.is_open() || !check.good())
    {
        std::cerr << "Error reading file: " << filename << std::endl;
        return 1;
    }

    petro::parser<
        petro::box::moov<petro::parser<
            petro::box::trak<petro::parser<
                petro::box::mdia<petro::parser<
                    petro::box::hdlr,
                    petro::box::minf<petro::parser<
                        petro::box::stbl<petro::parser<
                            petro::box::stsd,
                            petro::box::stsc,
                            petro::box::stco,
                            petro::box::co64
                        >>
                    >>
                >>
            >>
        >>
    > parser;

    auto root = std::make_shared<petro::box::root>();
    petro::byte_stream bs(filename);

    parser.read(root, bs);

    // get needed boxes
    auto avc1 = root->get_child("avc1");
    assert(avc1 != nullptr);

    auto avcc = avc1->get_child<petro::box::avcc>();
    assert(avcc != nullptr);

    auto trak = avc1->get_parent("trak");
    assert(trak != nullptr);

    std::vector<uint64_t> chunk_offsets;
    auto stco = trak->get_child<petro::box::stco>();
    if (stco != nullptr)
    {
        chunk_offsets.resize(stco->entry_count());
        std::copy(
            stco->entries().begin(),
            stco->entries().end(),
            chunk_offsets.begin());
    }
    else
    {
        auto co64 = trak->get_child<petro::box::co64>();
        assert(co64 != nullptr);
        chunk_offsets.resize(co64->entry_count());
        std::copy(
            co64->entries().begin(),
            co64->entries().end(),
            chunk_offsets.begin());
    }

    auto stsc = trak->get_child<petro::box::stsc>();
    assert(stsc != nullptr);

    // create output file
    std::ofstream h264_file(argv[2], std::ios::binary);

    // write sps and pps
    std::vector<char> nalu_seperator = {0, 0, 0, 1};
    auto sps = avcc->sequence_parameter_set(0);
    h264_file.write(nalu_seperator.data(), nalu_seperator.size());
    h264_file.write((char*)sps->data(), sps->size());
    auto pps = avcc->picture_parameter_set(0);
    h264_file.write(nalu_seperator.data(), nalu_seperator.size());
    h264_file.write((char*)pps->data(), pps->size());

    // write video data
    std::ifstream mp4_file(filename, std::ios::binary);
    for (uint32_t i = 0; i < chunk_offsets.size(); ++i)
    {
        mp4_file.seekg(chunk_offsets[i]);
        for (uint32_t j = 0; j < stsc->samples_for_chunk(i); ++j)
        {
            h264_file.write(nalu_seperator.data(), nalu_seperator.size());

            auto sample_size = read_sample_size(mp4_file);

            std::vector<char> temp(sample_size);
            mp4_file.read(temp.data(), sample_size);
            h264_file.write(temp.data(), sample_size);
        }
    }

    h264_file.close();
    return 0;
}
<commit_msg>fix h264 extraction<commit_after>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <petro/parser.hpp>
#include <petro/box/all.hpp>

#include <fstream>
#include <sstream>
#include <string>
#include <memory>

uint32_t read_sample_size(std::istream& file, uint8_t length_size)
{
    std::vector<uint8_t> data(length_size);
    file.read((char*)data.data(), data.size());

    uint32_t result = 0;
    for (uint8_t i = 0; i < length_size; ++i)
    {
        result |= data[i] << ((length_size - 1) - i) * 8;
    }

    return result;
}

int main(int argc, char* argv[])
{
    if (argc != 3 || std::string(argv[1]) == "--help")
    {
        auto usage = "./mp4_to_h264 MP4_INPUT H264_OUTPUT";
        std::cout << usage << std::endl;
        return 0;
    }

    auto filename = std::string(argv[1]);

    std::ifstream check(filename, std::ios::binary);

    if (!check.is_open() || !check.good())
    {
        std::cerr << "Error reading file: " << filename << std::endl;
        return 1;
    }

    petro::parser<
        petro::box::moov<petro::parser<
            petro::box::trak<petro::parser<
                petro::box::mdia<petro::parser<
                    petro::box::hdlr,
                    petro::box::minf<petro::parser<
                        petro::box::stbl<petro::parser<
                            petro::box::stsd,
                            petro::box::stsc,
                            petro::box::stco,
                            petro::box::co64,
                            petro::box::stsz
                        >>
                    >>
                >>
            >>
        >>
    > parser;

    auto root = std::make_shared<petro::box::root>();
    petro::byte_stream bs(filename);

    parser.read(root, bs);

    // get needed boxes
    auto avc1 = root->get_child("avc1");
    assert(avc1 != nullptr);

    auto avcc = avc1->get_child<petro::box::avcc>();
    assert(avcc != nullptr);

    auto trak = avc1->get_parent("trak");
    assert(trak != nullptr);

    std::vector<uint64_t> chunk_offsets;
    auto stco = trak->get_child<petro::box::stco>();
    if (stco != nullptr)
    {
        chunk_offsets.resize(stco->entry_count());
        std::copy(
            stco->entries().begin(),
            stco->entries().end(),
            chunk_offsets.begin());
    }
    else
    {
        auto co64 = trak->get_child<petro::box::co64>();
        assert(co64 != nullptr);
        chunk_offsets.resize(co64->entry_count());
        std::copy(
            co64->entries().begin(),
            co64->entries().end(),
            chunk_offsets.begin());
    }

    auto stsc = trak->get_child<petro::box::stsc>();
    assert(stsc != nullptr);

    auto stsz = trak->get_child<petro::box::stsz>();
    assert(stsz != nullptr);

    // create output file
    std::ofstream h264_file(argv[2], std::ios::binary);

    // write sps and pps
    std::vector<char> nalu_seperator = {0, 0, 0, 1};
    auto sps = avcc->sequence_parameter_set(0);
    h264_file.write(nalu_seperator.data(), nalu_seperator.size());
    h264_file.write((char*)sps->data(), sps->size());
    auto pps = avcc->picture_parameter_set(0);
    h264_file.write(nalu_seperator.data(), nalu_seperator.size());
    h264_file.write((char*)pps->data(), pps->size());

    // write video data
    std::ifstream mp4_file(filename, std::ios::binary);
    uint32_t found_samples = 0;
    for (uint32_t chunk = 0; chunk < chunk_offsets.size(); ++chunk)
    {
        mp4_file.seekg(chunk_offsets[chunk]);
        for (uint32_t sample = 0; sample < stsc->samples_for_chunk(chunk); ++sample)
        {
            // The sample size describes the size of the access unit (AU) of the
            // h264 data. This means multiple nalus can be in the same "sample".
            // Each of these nalus needs a preceeding nalu seperator.
            uint16_t sample_size = stsz->sample_size(found_samples);
            while(sample_size != 0)
            {
                auto length_size = avcc->length_size();
                auto nalu_size = read_sample_size(mp4_file, length_size);
                sample_size -= length_size;
                h264_file.write(nalu_seperator.data(), nalu_seperator.size());
                std::vector<char> temp(nalu_size);
                mp4_file.read(temp.data(), nalu_size);
                sample_size -= nalu_size;
                h264_file.write(temp.data(), nalu_size);
            }
            found_samples++;
        }
    }

    h264_file.close();
    return 0;
}
<|endoftext|>


<commit_before>#ifndef GNR_DISPATCH_HPP
# define GNR_DISPATCH_HPP
# pragma once

#include <type_traits>

#include <utility>

#include "invoke.hpp"

namespace gnr
{

namespace detail::dispatch
{

template <std::size_t I, typename ...T>
using at_t = std::tuple_element_t<I, std::tuple<T...>>;

template <typename R>
using result_t = std::conditional_t<
  std::is_array_v<std::remove_reference_t<R>> &&
  (1 == std::rank_v<std::remove_reference_t<R>>) &&
  std::is_same_v<
    char,
    std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
  >,
  std::remove_extent_t<std::remove_reference_t<R>>(*)[],
  std::conditional_t<
    std::is_reference_v<R>,
    std::remove_reference_t<R>*,
    R
  >
>;

template <typename F>
constexpr auto is_noexcept_dispatchable() noexcept
{
  auto const f(static_cast<std::remove_reference_t<F>*>(nullptr));

  if constexpr(std::is_void_v<decltype(F(*f)())> ||
    std::is_reference_v<decltype(F(*f)())>)
  {
    return noexcept(F(*f)());
  }
  else
  {
    return noexcept(std::declval<decltype(F(*f)())&>() = F(*f)());
  }
}

template <typename T, bool = std::is_enum_v<T>>
struct underlying_type : std::underlying_type<T> {};

template <typename T>
struct underlying_type<T, false> { using type = T; };

template <typename T>
using underlying_type_t = underlying_type<T>::type;

}

constexpr decltype(auto) dispatch(auto const i, auto&& ...f)
  noexcept((detail::dispatch::is_noexcept_dispatchable<decltype(f)>() && ...))
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(
            std::declval<detail::dispatch::at_t<0, decltype(f)...>>()()
          )
        >,
        std::decay_t<decltype(std::declval<decltype(f)>()())>
      >...
    >
  )
{
  using int_t =
    detail::dispatch::underlying_type_t<std::remove_const_t<decltype(i)>>;

  using R = decltype(
    std::declval<detail::dispatch::at_t<0, decltype(f)...>>()()
  );

  return [&]<auto ...I>(std::integer_sequence<int_t, I...>)
    noexcept(
      (detail::dispatch::is_noexcept_dispatchable<decltype(f)>() && ...)
    ) -> decltype(auto)
  {
    if constexpr(std::is_void_v<R>)
    {
      (void)((I == int_t(i) && (f(), true)) || ...);
    }
    else if constexpr(
      (
        std::is_array_v<std::remove_reference_t<R>> &&
        (1 == std::rank_v<std::remove_reference_t<R>>) &&
        std::is_same_v<
          char,
          std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
        >
      ) ||
      std::is_reference_v<R>
    )
    {
      detail::dispatch::result_t<R> r;

      (void)((I == int_t(i) &&
        (r = reinterpret_cast<decltype(r)>(&f()))) || ...);

      return *r;
    }
    else
    {
      R r;

      (void)(((I == int_t(i)) && (r = f(), true)) || ...);

      return r;
    }
  }(std::make_integer_sequence<int_t, sizeof...(f)>());
}

constexpr decltype(auto) dispatch2(auto const i, auto&& ...a)
#ifndef __clang__
  noexcept(noexcept(
      gnr::invoke_split<2>(
        [](auto&&, auto&& f)
        {
          detail::dispatch::is_noexcept_dispatchable<decltype(f)>();
        },
        std::forward<decltype(a)>(a)...
      )
    )
  )
#endif // __clang__
{
  using R = decltype(
    std::declval<detail::dispatch::at_t<1, decltype(a)...>>()()
  );

  if constexpr(std::is_void_v<R>)
  {
    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        return (e == i) && (f(), true);
      },
      std::forward<decltype(a)>(a)...
    );
  }
  else if constexpr(
    (
      std::is_array_v<std::remove_reference_t<R>> &&
      (1 == std::rank_v<std::remove_reference_t<R>>) &&
      std::is_same_v<
        char,
        std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
      >
    ) ||
    std::is_reference_v<R>
  )
  {
    detail::dispatch::result_t<R> r;

    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        return (e == i) && (r = reinterpret_cast<decltype(r)>(&f()));
      },
      std::forward<decltype(a)>(a)...
    );

    return *r;
  }
  else
  {
    R r;

    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(std::declval<R&>() = f()))
      {
        return (e == i) && (r = f(), true);
      },
      std::forward<decltype(a)>(a)...
    );

    return r;
  }
}

constexpr decltype(auto) select(auto const i, auto&& ...v) noexcept
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::dispatch::at_t<0, decltype(v)...>>())
        >,
        std::decay_t<decltype(std::declval<decltype(v)>())>
      >...
    >
  )
{
  return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> decltype(auto)
  {
    detail::dispatch::result_t<detail::dispatch::at_t<0, decltype(v)...>> r;

    (void)(((I == i) && (r = reinterpret_cast<decltype(r)>(&v))) || ...);

    return *r;
  }(std::make_index_sequence<sizeof...(v)>());
}

constexpr decltype(auto) select2(auto const i, auto&& ...a) noexcept
{
  detail::dispatch::result_t<detail::dispatch::at_t<1, decltype(a)...>> r;

  gnr::invoke_split_cond<2>(
    [&](auto&& e, auto&& v) noexcept
    {
      return (e == i) && (r = reinterpret_cast<decltype(r)>(&v));
    },
    std::forward<decltype(a)>(a)...
  );

  return *r;
}

}

#endif // GNR_DISPATCH_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_DISPATCH_HPP
# define GNR_DISPATCH_HPP
# pragma once

#include <type_traits>

#include <utility>

#include "invoke.hpp"

namespace gnr
{

namespace detail::dispatch
{

template <std::size_t I, typename ...T>
using at_t = std::tuple_element_t<I, std::tuple<T...>>;

template <typename R>
using result_t = std::conditional_t<
  std::is_array_v<std::remove_reference_t<R>> &&
  (1 == std::rank_v<std::remove_reference_t<R>>) &&
  std::is_same_v<
    char,
    std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
  >,
  std::remove_extent_t<std::remove_reference_t<R>>(*)[],
  std::conditional_t<
    std::is_reference_v<R>,
    std::remove_reference_t<R>*,
    R
  >
>;

template <typename F>
constexpr auto is_noexcept_dispatchable() noexcept
{
  auto const f(static_cast<std::remove_reference_t<F>*>(nullptr));

  if constexpr(std::is_void_v<decltype(F(*f)())> ||
    std::is_reference_v<decltype(F(*f)())>)
  {
    return noexcept(F(*f)());
  }
  else
  {
    return noexcept(std::declval<decltype(F(*f)())&>() = F(*f)());
  }
}

template <typename T, bool = std::is_enum_v<T>>
struct underlying_type : std::underlying_type<T> {};

template <typename T>
struct underlying_type<T, false> { using type = T; };

template <typename T>
using underlying_type_t = typename underlying_type<T>::type;

}

constexpr decltype(auto) dispatch(auto const i, auto&& ...f)
  noexcept((detail::dispatch::is_noexcept_dispatchable<decltype(f)>() && ...))
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(
            std::declval<detail::dispatch::at_t<0, decltype(f)...>>()()
          )
        >,
        std::decay_t<decltype(std::declval<decltype(f)>()())>
      >...
    >
  )
{
  using int_t =
    detail::dispatch::underlying_type_t<std::remove_const_t<decltype(i)>>;

  using R = decltype(
    std::declval<detail::dispatch::at_t<0, decltype(f)...>>()()
  );

  return [&]<auto ...I>(std::integer_sequence<int_t, I...>)
    noexcept(
      (detail::dispatch::is_noexcept_dispatchable<decltype(f)>() && ...)
    ) -> decltype(auto)
  {
    if constexpr(std::is_void_v<R>)
    {
      (void)((I == int_t(i) && (f(), true)) || ...);
    }
    else if constexpr(
      (
        std::is_array_v<std::remove_reference_t<R>> &&
        (1 == std::rank_v<std::remove_reference_t<R>>) &&
        std::is_same_v<
          char,
          std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
        >
      ) ||
      std::is_reference_v<R>
    )
    {
      detail::dispatch::result_t<R> r;

      (void)((I == int_t(i) &&
        (r = reinterpret_cast<decltype(r)>(&f()))) || ...);

      return *r;
    }
    else
    {
      R r;

      (void)(((I == int_t(i)) && (r = f(), true)) || ...);

      return r;
    }
  }(std::make_integer_sequence<int_t, sizeof...(f)>());
}

constexpr decltype(auto) dispatch2(auto const i, auto&& ...a)
#ifndef __clang__
  noexcept(noexcept(
      gnr::invoke_split<2>(
        [](auto&&, auto&& f)
        {
          detail::dispatch::is_noexcept_dispatchable<decltype(f)>();
        },
        std::forward<decltype(a)>(a)...
      )
    )
  )
#endif // __clang__
{
  using R = decltype(
    std::declval<detail::dispatch::at_t<1, decltype(a)...>>()()
  );

  if constexpr(std::is_void_v<R>)
  {
    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        return (e == i) && (f(), true);
      },
      std::forward<decltype(a)>(a)...
    );
  }
  else if constexpr(
    (
      std::is_array_v<std::remove_reference_t<R>> &&
      (1 == std::rank_v<std::remove_reference_t<R>>) &&
      std::is_same_v<
        char,
        std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
      >
    ) ||
    std::is_reference_v<R>
  )
  {
    detail::dispatch::result_t<R> r;

    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        return (e == i) && (r = reinterpret_cast<decltype(r)>(&f()));
      },
      std::forward<decltype(a)>(a)...
    );

    return *r;
  }
  else
  {
    R r;

    gnr::invoke_split_cond<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(std::declval<R&>() = f()))
      {
        return (e == i) && (r = f(), true);
      },
      std::forward<decltype(a)>(a)...
    );

    return r;
  }
}

constexpr decltype(auto) select(auto const i, auto&& ...v) noexcept
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::dispatch::at_t<0, decltype(v)...>>())
        >,
        std::decay_t<decltype(std::declval<decltype(v)>())>
      >...
    >
  )
{
  return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> decltype(auto)
  {
    detail::dispatch::result_t<detail::dispatch::at_t<0, decltype(v)...>> r;

    (void)(
      ((I == i) && (r = reinterpret_cast<decltype(r)>(&v), true)) || ...
    );

    return *r;
  }(std::make_index_sequence<sizeof...(v)>());
}

constexpr decltype(auto) select2(auto const i, auto&& ...a) noexcept
{
  detail::dispatch::result_t<detail::dispatch::at_t<1, decltype(a)...>> r;

  gnr::invoke_split_cond<2>(
    [&](auto&& e, auto&& v) noexcept
    {
      return (e == i) && (r = reinterpret_cast<decltype(r)>(&v), true);
    },
    std::forward<decltype(a)>(a)...
  );

  return *r;
}

}

#endif // GNR_DISPATCH_HPP
<|endoftext|>


<commit_before>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

#include <mapper/mapper.h>

#include "pwm_synth/pwm.h"

int done = 0;

void ctrlc(int)
{
    done = 1;
}

void handler_freq(mapper_signal sig, int instance_id, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pfreq = (float*)value;
        set_freq(*pfreq);
    }
}

void handler_gain(mapper_signal sig, int instance_id, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pgain = (float*)value;
        set_gain(*pgain);
    }
    else
        set_gain(0);
}

void handler_duty(mapper_signal sig, int instance_id, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pduty = (float*)value;
        set_duty(*pduty);
    }
}

int main()
{
    signal(SIGINT, ctrlc);

    mapper_device dev = mapper_device_new("pwm", 9000, 0);

    float min0 = 0;
    float max1 = 1;
    float max1000 = 1000;

    mapper_device_add_input(dev, "/freq", 1, 'f', "Hz", &min0, &max1000,
                            handler_freq, 0);
    mapper_device_add_input(dev, "/gain", 1, 'f', "Hz", &min0, &max1,
                            handler_gain, 0);
    mapper_device_add_input(dev, "/duty", 1, 'f', "Hz", &min0, &max1,
                            handler_duty, 0);

    run_synth();

    set_duty(0.1);
    set_freq(110.0);
    set_gain(0.1);

    printf("Press Ctrl-C to quit.\n");

    while (!done)
        mapper_device_poll(dev, 10);

    mapper_device_free(dev);

    set_freq(0);
    sleep(1);

    stop_synth();
}
<commit_msg>Update pwm example<commit_after>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

#include <mapper/mapper.h>

#include "pwm_synth/pwm.h"

int done = 0;

void ctrlc(int)
{
    done = 1;
}

void handler_freq(mapper_signal sig, mapper_id instance, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pfreq = (float*)value;
        set_freq(*pfreq);
    }
}

void handler_gain(mapper_signal sig, mapper_id instance, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pgain = (float*)value;
        set_gain(*pgain);
    }
    else
        set_gain(0);
}

void handler_duty(mapper_signal sig, mapper_id instance, const void *value,
                  int count, mapper_timetag_t *timetag)
{
    if (value) {
        float *pduty = (float*)value;
        set_duty(*pduty);
    }
}

int main()
{
    signal(SIGINT, ctrlc);

    mapper_device dev = mapper_device_new("pwm", 9000, 0);

    float min0 = 0;
    float max1 = 1;
    float max1000 = 1000;

    mapper_device_add_input(dev, "/freq", 1, 'f', "Hz", &min0, &max1000,
                            handler_freq, 0);
    mapper_device_add_input(dev, "/gain", 1, 'f', "Hz", &min0, &max1,
                            handler_gain, 0);
    mapper_device_add_input(dev, "/duty", 1, 'f', "Hz", &min0, &max1,
                            handler_duty, 0);

    run_synth();

    set_duty(0.1);
    set_freq(110.0);
    set_gain(0.1);

    printf("Press Ctrl-C to quit.\n");

    while (!done)
        mapper_device_poll(dev, 10);

    mapper_device_free(dev);

    set_freq(0);
    sleep(1);

    stop_synth();
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <list>
#include <vector>

#include "catch.hpp"

#include "cpp_utils/tmp.hpp"

TEST_CASE( "tmp/variadic_contains/1", "[tmp]" ) {
    REQUIRE((cpp::variadic_contains<double, std::string, int, double>::value));
    REQUIRE(!(cpp::variadic_contains<double, std::string, int, long double>::value));
    REQUIRE((cpp::variadic_contains<std::string, std::string>::value));
    REQUIRE(!(cpp::variadic_contains<std::string>::value));
    REQUIRE(!(cpp::variadic_contains<std::string, double>::value));
}

TEST_CASE( "tmp/type_list/1", "[tmp]" ) {
    REQUIRE((cpp::type_list<std::string, double, int>::contains<int>()));
    REQUIRE(!(cpp::type_list<std::string, double, int>::contains<long int>()));
    REQUIRE((cpp::type_list<std::string>::contains<std::string>()));
    REQUIRE(!(cpp::type_list<>::contains<std::string>()));
}

TEST_CASE( "tmp/is_homogeneous/1", "[tmp]" ) {
    REQUIRE((cpp::is_homogeneous<std::size_t, std::size_t, unsigned long>::value));
    REQUIRE((cpp::is_homogeneous<int, int>::value));
    REQUIRE(!(cpp::is_homogeneous<int, long>::value));
    REQUIRE(!(cpp::is_homogeneous<std::string, long>::value));
    REQUIRE((cpp::is_homogeneous<long>::value));
}

TEST_CASE( "tmp/is_sub_homogeneous/1", "[tmp]" ) {
    REQUIRE(!(cpp::is_sub_homogeneous<>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, int>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, double>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, double, double>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, int, double>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, int, int, double>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, int, double, double>::value));
}

TEST_CASE( "tmp/first_value/1", "[tmp]" ) {
    REQUIRE(cpp::first_value(1,"str",true) == 1);
    REQUIRE(cpp::first_value(std::string("str"),1,true) == "str");
    REQUIRE(cpp::first_value(false,"str",1,true) == false);
}

TEST_CASE( "tmp/last_value/1", "[tmp]" ) {
    REQUIRE(cpp::last_value(1,"str",true) == true);
    REQUIRE(cpp::last_value("str",1,1) == 1);
    REQUIRE(cpp::last_value(false,"str",1,std::string("str2")) == "str2");
}

TEST_CASE( "tmp/nth_value/1", "[tmp]" ) {
    REQUIRE(cpp::nth_value<0>(1,"str",true) == 1);
    REQUIRE(cpp::nth_value<1>(1,std::string("str"),true) == "str");
    REQUIRE(cpp::nth_value<2>(1,std::string("str"),true) == true);
}

TEST_CASE( "tmp/first_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::first_type<int, char*, bool>::type, int>::value));
    REQUIRE((std::is_same<cpp::first_type<char*, int, bool>::type, char*>::value));
    REQUIRE((std::is_same<cpp::first_type<bool, int, int*>::type, bool>::value));
    REQUIRE((std::is_same<cpp::first_type<bool>::type, bool>::value));
}

TEST_CASE( "tmp/first_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::first_type_t<int, char*, bool>, int>::value));
    REQUIRE((std::is_same<cpp::first_type_t<char*, int, bool>, char*>::value));
    REQUIRE((std::is_same<cpp::first_type_t<bool, int, int*>, bool>::value));
    REQUIRE((std::is_same<cpp::first_type_t<bool>, bool>::value));
}

TEST_CASE( "tmp/last_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::last_type<int, char*, bool>::type, bool>::value));
    REQUIRE((std::is_same<cpp::last_type<char*, int, int*>::type, int*>::value));
    REQUIRE((std::is_same<cpp::last_type<bool, int, std::string>::type, std::string>::value));
    REQUIRE((std::is_same<cpp::last_type<bool>::type, bool>::value));
}

TEST_CASE( "tmp/last_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::last_type_t<int, char*, bool>, bool>::value));
    REQUIRE((std::is_same<cpp::last_type_t<char*, int, int*>, int*>::value));
    REQUIRE((std::is_same<cpp::last_type_t<bool, int, std::string>, std::string>::value));
    REQUIRE((std::is_same<cpp::last_type_t<bool>, bool>::value));
}

TEST_CASE( "tmp/nth_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::nth_type<0, int, char*, bool>::type, int>::value));
    REQUIRE((std::is_same<cpp::nth_type<1, int, char*, bool>::type, char*>::value));
    REQUIRE((std::is_same<cpp::nth_type<2, int, char*, bool>::type, bool>::value));
}

TEST_CASE( "tmp/nth_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::nth_type_t<0, int, char*, bool>, int>::value));
    REQUIRE((std::is_same<cpp::nth_type_t<1, int, char*, bool>, char*>::value));
    REQUIRE((std::is_same<cpp::nth_type_t<2, int, char*, bool>, bool>::value));
}

TEST_CASE( "tmp/is_specialization/1", "[tmp]" ) {
    REQUIRE((cpp::is_specialization_of<std::vector,std::vector<double>>::value));
    REQUIRE((cpp::is_specialization_of<std::vector,std::vector<std::string>>::value));
    REQUIRE((cpp::is_specialization_of<std::list,std::list<std::string>>::value));
}

TEST_CASE( "tmp/add_const_lvalue_t/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<int>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<char>, const char&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<std::string>, const std::string&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<const int>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<const int&>, const int&>::value));
}

TEST_CASE( "tmp/add_const_rvalue_t/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<int>, const int&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<char>, const char&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<std::string>, const std::string&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int>, const int&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int&>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int&&>, const int&&>::value));
}

struct test_op {
    std::size_t int_op = 0;
    std::size_t double_op = 0;
    std::size_t string_op = 0;

    template<typename O>
    void operator()(){
        if(std::is_same<int, O>::value){
            ++int_op;
        }

        if(std::is_same<double, O>::value){
            ++double_op;
        }

        if(std::is_same<std::string, O>::value){
            ++string_op;
        }
    }
};

TEST_CASE( "tmp/for_each_tuple_t/1", "[tmp]" ) {
    test_op oo;

    using tuple_t_1 = std::tuple<int, std::string, int, char, char, double, double, std::string, std::string>;
    using tuple_t_2 = std::tuple<int, double>;
    using tuple_t_3 = std::tuple<>;

    cpp::for_each_tuple_t<tuple_t_1>(oo);

    REQUIRE(oo.int_op == 2);
    REQUIRE(oo.double_op == 2);
    REQUIRE(oo.string_op == 3);

    cpp::for_each_tuple_t<tuple_t_2>(oo);

    REQUIRE(oo.int_op == 3);
    REQUIRE(oo.double_op == 3);
    REQUIRE(oo.string_op == 3);

    cpp::for_each_tuple_t<tuple_t_3>(oo);

    REQUIRE(oo.int_op == 3);
    REQUIRE(oo.double_op == 3);
    REQUIRE(oo.string_op == 3);
}
<commit_msg>Fix tests<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <list>
#include <vector>

#include "catch.hpp"

#include "cpp_utils/tmp.hpp"

TEST_CASE( "tmp/variadic_contains/1", "[tmp]" ) {
    REQUIRE((cpp::variadic_contains<double, std::string, int, double>::value));
    REQUIRE(!(cpp::variadic_contains<double, std::string, int, long double>::value));
    REQUIRE((cpp::variadic_contains<std::string, std::string>::value));
    REQUIRE(!(cpp::variadic_contains<std::string>::value));
    REQUIRE(!(cpp::variadic_contains<std::string, double>::value));
}

TEST_CASE( "tmp/type_list/1", "[tmp]" ) {
    REQUIRE((cpp::type_list<std::string, double, int>::contains<int>()));
    REQUIRE(!(cpp::type_list<std::string, double, int>::contains<long int>()));
    REQUIRE((cpp::type_list<std::string>::contains<std::string>()));
    REQUIRE(!(cpp::type_list<>::contains<std::string>()));
}

TEST_CASE( "tmp/is_homogeneous/1", "[tmp]" ) {
    REQUIRE((cpp::is_homogeneous<std::size_t, std::size_t, unsigned long>::value));
    REQUIRE((cpp::is_homogeneous<int, int>::value));
    REQUIRE(!(cpp::is_homogeneous<int, long>::value));
    REQUIRE(!(cpp::is_homogeneous<std::string, long>::value));
    REQUIRE((cpp::is_homogeneous<long>::value));
}

TEST_CASE( "tmp/is_sub_homogeneous/1", "[tmp]" ) {
    REQUIRE(!(cpp::is_sub_homogeneous<>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, int>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, double>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, double, double>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, int, double>::value));
    REQUIRE((cpp::is_sub_homogeneous<int, int, int, double>::value));
    REQUIRE(!(cpp::is_sub_homogeneous<int, int, double, double>::value));
}

TEST_CASE( "tmp/first_value/1", "[tmp]" ) {
    REQUIRE(cpp::first_value(1,"str",true) == 1);
    REQUIRE(cpp::first_value(std::string("str"),1,true) == "str");
    REQUIRE(!cpp::first_value(false,"str",1,true));
}

TEST_CASE( "tmp/last_value/1", "[tmp]" ) {
    REQUIRE(cpp::last_value(1,"str",true));
    REQUIRE(cpp::last_value("str",1,1) == 1);
    REQUIRE(cpp::last_value(false,"str",1,std::string("str2")) == "str2");
}

TEST_CASE( "tmp/nth_value/1", "[tmp]" ) {
    REQUIRE(cpp::nth_value<0>(1,"str",true) == 1);
    REQUIRE(cpp::nth_value<1>(1,std::string("str"),true) == "str");
    REQUIRE(cpp::nth_value<2>(1,std::string("str"),true));
}

TEST_CASE( "tmp/first_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::first_type<int, char*, bool>::type, int>::value));
    REQUIRE((std::is_same<cpp::first_type<char*, int, bool>::type, char*>::value));
    REQUIRE((std::is_same<cpp::first_type<bool, int, int*>::type, bool>::value));
    REQUIRE((std::is_same<cpp::first_type<bool>::type, bool>::value));
}

TEST_CASE( "tmp/first_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::first_type_t<int, char*, bool>, int>::value));
    REQUIRE((std::is_same<cpp::first_type_t<char*, int, bool>, char*>::value));
    REQUIRE((std::is_same<cpp::first_type_t<bool, int, int*>, bool>::value));
    REQUIRE((std::is_same<cpp::first_type_t<bool>, bool>::value));
}

TEST_CASE( "tmp/last_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::last_type<int, char*, bool>::type, bool>::value));
    REQUIRE((std::is_same<cpp::last_type<char*, int, int*>::type, int*>::value));
    REQUIRE((std::is_same<cpp::last_type<bool, int, std::string>::type, std::string>::value));
    REQUIRE((std::is_same<cpp::last_type<bool>::type, bool>::value));
}

TEST_CASE( "tmp/last_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::last_type_t<int, char*, bool>, bool>::value));
    REQUIRE((std::is_same<cpp::last_type_t<char*, int, int*>, int*>::value));
    REQUIRE((std::is_same<cpp::last_type_t<bool, int, std::string>, std::string>::value));
    REQUIRE((std::is_same<cpp::last_type_t<bool>, bool>::value));
}

TEST_CASE( "tmp/nth_type/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::nth_type<0, int, char*, bool>::type, int>::value));
    REQUIRE((std::is_same<cpp::nth_type<1, int, char*, bool>::type, char*>::value));
    REQUIRE((std::is_same<cpp::nth_type<2, int, char*, bool>::type, bool>::value));
}

TEST_CASE( "tmp/nth_type/2", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::nth_type_t<0, int, char*, bool>, int>::value));
    REQUIRE((std::is_same<cpp::nth_type_t<1, int, char*, bool>, char*>::value));
    REQUIRE((std::is_same<cpp::nth_type_t<2, int, char*, bool>, bool>::value));
}

TEST_CASE( "tmp/is_specialization/1", "[tmp]" ) {
    REQUIRE((cpp::is_specialization_of<std::vector,std::vector<double>>::value));
    REQUIRE((cpp::is_specialization_of<std::vector,std::vector<std::string>>::value));
    REQUIRE((cpp::is_specialization_of<std::list,std::list<std::string>>::value));
}

TEST_CASE( "tmp/add_const_lvalue_t/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<int>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<char>, const char&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<std::string>, const std::string&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<const int>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_lvalue_t<const int&>, const int&>::value));
}

TEST_CASE( "tmp/add_const_rvalue_t/1", "[tmp]" ) {
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<int>, const int&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<char>, const char&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<std::string>, const std::string&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int>, const int&&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int&>, const int&>::value));
    REQUIRE((std::is_same<cpp::add_const_rvalue_t<const int&&>, const int&&>::value));
}

struct test_op {
    std::size_t int_op = 0;
    std::size_t double_op = 0;
    std::size_t string_op = 0;

    template<typename O>
    void operator()(){
        if(std::is_same<int, O>::value){
            ++int_op;
        }

        if(std::is_same<double, O>::value){
            ++double_op;
        }

        if(std::is_same<std::string, O>::value){
            ++string_op;
        }
    }
};

TEST_CASE( "tmp/for_each_tuple_t/1", "[tmp]" ) {
    test_op oo;

    using tuple_t_1 = std::tuple<int, std::string, int, char, char, double, double, std::string, std::string>;
    using tuple_t_2 = std::tuple<int, double>;
    using tuple_t_3 = std::tuple<>;

    cpp::for_each_tuple_t<tuple_t_1>(oo);

    REQUIRE(oo.int_op == 2);
    REQUIRE(oo.double_op == 2);
    REQUIRE(oo.string_op == 3);

    cpp::for_each_tuple_t<tuple_t_2>(oo);

    REQUIRE(oo.int_op == 3);
    REQUIRE(oo.double_op == 3);
    REQUIRE(oo.string_op == 3);

    cpp::for_each_tuple_t<tuple_t_3>(oo);

    REQUIRE(oo.int_op == 3);
    REQUIRE(oo.double_op == 3);
    REQUIRE(oo.string_op == 3);
}
<|endoftext|>