<commit_before>/** \file    bib_ref_to_codes_tool.cc
 *  \brief   A tool for converting bible references to numeric codes.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2017,2019 Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include "BibleUtil.h"
#include "MapIO.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--debug|--query] [--map-file-directory=path] bible_reference_candidate\n";
    std::cerr << "          bible_aliases_map books_of_the_bible_to_code_map\n";
    std::cerr << "          books_of_the_bible_to_canonical_form_map pericopes_to_codes_map\n";
    std::cerr << '\n';
    std::cerr << "          When --debug has been specified additional tracing output will be generated.\n";
    std::cerr << "          When --query has been specified SOLR search queries will be output.\n";
    std::cerr << "          If --map-file-directory=... has been specified, the provided path will be prefixed to all\n";
    std::cerr << "          map-file arguments.\n";
    std::exit(EXIT_FAILURE);
}

void HandlePericopes(const bool verbose, const bool generate_solr_query, const std::string &bible_reference_candidate,
                     const std::string &pericopes_to_codes_map_filename)
{
    if (verbose)
        std::cout << "Entering HandlePericopes().\n";

    std::unordered_multimap<std::string, std::string> pericopes_to_codes_map;
    MapIO::DeserialiseMap(pericopes_to_codes_map_filename, &pericopes_to_codes_map);

    if (verbose)
        std::cout << "In HandlePericopes: looking for \"" << bible_reference_candidate << "\".\n";
    const auto begin_end(pericopes_to_codes_map.equal_range(bible_reference_candidate));
    if (begin_end.first != begin_end.second) {
        if (verbose)
            std::cerr << "Found a pericope to codes mapping.\n";
        std::string query;
        for (auto pair(begin_end.first); pair != begin_end.second; ++pair) {
            if (generate_solr_query) {
                if (not query.empty())
                    query += ' ';
                query += StringUtil::Map(pair->second, ':', '_');
            } else
                std::cout << pair->second << '\n';
        }
        if (generate_solr_query)
            std::cout << query << '\n';

        std::exit(EXIT_SUCCESS);
    }
}

void HandleBookRanges(const bool verbose, const bool generate_solr_query,
                      const std::string &books_of_the_bible_to_canonical_form_map_filename,
                      const std::string &books_of_the_bible_to_code_map_filename,
                      const std::string &bible_reference_candidate)
{
    RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory("^([12])-([23])\\s*([A-ZÖa-zö]+)\\s*$"));
    if (not matcher->matched(bible_reference_candidate))
        return;

    unsigned starting_volume;
    if (not StringUtil::ToUnsigned((*matcher)[1], &starting_volume) or starting_volume > 2)
        logger->error("\"" + (*matcher)[1] + "\" is not a valid starting volume!");

    unsigned ending_volume;
    if (not StringUtil::ToUnsigned((*matcher)[2], &ending_volume) or ending_volume > 3
        or ending_volume <= starting_volume)
        LOG_ERROR("\"" + (*matcher)[2] + "\" is not a valid ending volume!");

    const std::string non_canonical_book_name((*matcher)[3]);
    BibleUtil::BibleBookCanoniser bible_book_canoniser(books_of_the_bible_to_canonical_form_map_filename);
    const std::string starting_bible_book_candidate(bible_book_canoniser.canonise(
        std::to_string(starting_volume) + non_canonical_book_name, verbose));

    const std::string ending_bible_book_candidate(bible_book_canoniser.canonise(
        std::to_string(ending_volume) + non_canonical_book_name, verbose));

    if (verbose) {
        std::cout << "Identified a bible book range.  Starting volume " << starting_volume << ", ending volume "
                  << ending_volume << ", book is \"" << non_canonical_book_name << "\".\n";
    }

    BibleUtil::BibleBookToCodeMapper bible_book_to_code_mapper(books_of_the_bible_to_code_map_filename);
    const std::string first_book_code(bible_book_to_code_mapper.mapToCode(starting_bible_book_candidate, verbose));
    if (first_book_code.empty())
        logger->error("failed to map \"" + starting_bible_book_candidate + "\" to a bible code!");
    const std::string second_book_code(bible_book_to_code_mapper.mapToCode(ending_bible_book_candidate, verbose));
    if (second_book_code.empty())
        logger->error("failed to map \"" + ending_bible_book_candidate + "\" to a bible code!");

    std::cout << (first_book_code + std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '0'))
              << (generate_solr_query ? '_' : ':')
              << (second_book_code + std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '9'))
              << '\n';

    std::exit(EXIT_SUCCESS);
}

void GenerateQuery(const bool verbose, const bool generate_solr_query, std::string book_candidate,
                   const std::string &chapters_and_verses_candidate,
                              const std::string &books_of_the_bible_to_code_map_filename,
                   const std::string &books_of_the_bible_to_canonical_form_map_filename)
{
    BibleUtil::BibleBookCanoniser bible_book_canoniser(books_of_the_bible_to_canonical_form_map_filename);
    book_candidate = bible_book_canoniser.canonise(book_candidate, verbose);
    BibleUtil::BibleBookToCodeMapper bible_book_to_code_mapper(books_of_the_bible_to_code_map_filename);
    const std::string book_code(bible_book_to_code_mapper.mapToCode(book_candidate, verbose));
    if (book_code.empty())
        LOG_ERROR("failed to map \"" + book_candidate + "\" to a bible code!");
    if (verbose)
        std::cerr << "book code = \"" << book_code << "\"\n";
    if (chapters_and_verses_candidate.empty()) {
        std::cout << book_code
                  << std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '0')
                  << (generate_solr_query ? '_' : ':') << book_code
                  << std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '9')
                  << '\n';

        std::exit(EXIT_SUCCESS);
    }

    std::set<std::pair<std::string, std::string>> start_end;
    if (not BibleUtil::ParseBibleReference(chapters_and_verses_candidate, book_code, &start_end)) {
        if (verbose)
            std::cerr << "The parsing of \"" << chapters_and_verses_candidate
                      << "\" as chapters and verses failed!\n";
        std::exit(EXIT_FAILURE);
    }

    std::string query;
    for (const auto &pair : start_end) {
        if (generate_solr_query) {
            if (not query.empty())
                query += ' ';
            query += pair.first + "_" + pair.second;
        } else
            std::cout << pair.first << ':' << pair.second << '\n';
    }
}

void HandleOrdinaryReferences(const bool verbose, const bool generate_solr_query,
                              const std::string &bible_reference_candidate,
                              const std::string &books_of_the_bible_to_code_map_filename,
                              const std::string &books_of_the_bible_to_canonical_form_map_filename)
{
    std::vector<std::string> book_candidate, chapters_and_verses_candidate;
    BibleUtil::SplitIntoBooksAndChaptersAndVerses(bible_reference_candidate, &book_candidate, &chapters_and_verses_candidate);
    if (verbose) {
        for (unsigned i(0); i < book_candidate.size(); ++i) {
            std::cerr << "book_candidate[" << i << "] = \"" << book_candidate[i] << "\"\n";
            std::cerr << "chapters_and_verses_candidate[" << i << "] = \"" << chapters_and_verses_candidate[i] << "\"\n";
        }
    }

    for (unsigned i(0); i < book_candidate.size(); ++i)
        GenerateQuery(verbose, generate_solr_query, book_candidate[i], chapters_and_verses_candidate[i],
                      books_of_the_bible_to_code_map_filename, books_of_the_bible_to_canonical_form_map_filename);

    if (generate_solr_query)
        std::cout << '\n';
}

} // unnamed namespace

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc < 2)
        Usage();

    bool verbose(false), generate_solr_query(false);
    if (std::strcmp(argv[1], "--debug") == 0) {
        verbose = true;
        ++argv, --argc;
    } else if (std::strcmp(argv[1], "--query") == 0) {
        generate_solr_query = true;
        ++argv, --argc;
    }

    if (argc < 2)
        Usage();

    std::string map_file_path;
    if (StringUtil::StartsWith(argv[1], "--map-file-directory=")) {
        map_file_path = argv[1] + __builtin_strlen("--map-file-directory=");
        map_file_path += '/';
        ++argv, --argc;
    }

    if (argc != 6)
        Usage();

    std::string query(argv[1]);
    TextUtil::NormaliseDashes(&query);
    std::string bible_reference_candidate(StringUtil::Trim(TextUtil::CollapseWhitespace(TextUtil::UTF8ToLower(query))));
    const std::string bible_aliases_map_filename(map_file_path + argv[2]);
    const std::string books_of_the_bible_to_code_map_filename(map_file_path + argv[3]);
    const std::string books_of_the_bible_to_canonical_form_map_filename(map_file_path + argv[4]);
    const std::string pericopes_to_codes_map(map_file_path + argv[5]);

    const BibleUtil::BibleAliasMapper alias_mapper(bible_aliases_map_filename);
    bible_reference_candidate = alias_mapper.map(bible_reference_candidate, verbose);

    HandleBookRanges(verbose, generate_solr_query, books_of_the_bible_to_canonical_form_map_filename,
                     books_of_the_bible_to_code_map_filename, bible_reference_candidate);
    HandlePericopes(verbose, generate_solr_query, bible_reference_candidate, pericopes_to_codes_map);
    HandleOrdinaryReferences(verbose, generate_solr_query, bible_reference_candidate,
                             books_of_the_bible_to_code_map_filename,
                             books_of_the_bible_to_canonical_form_map_filename);
}
<commit_msg>Simpilfied comman-line invocation.<commit_after>/** \file    bib_ref_to_codes_tool.cc
 *  \brief   A tool for converting bible references to numeric codes.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2017,2019 Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include "BibleUtil.h"
#include "MapIO.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--debug|--query] [--map-file-directory=path] bible_reference_candidate\n";
    std::cerr << "          bible_aliases_map books_of_the_bible_to_code_map\n";
    std::cerr << "          books_of_the_bible_to_canonical_form_map pericopes_to_codes_map\n";
    std::cerr << '\n';
    std::cerr << "          When --debug has been specified additional tracing output will be generated.\n";
    std::cerr << "          When --query has been specified SOLR search queries will be output.\n";
    std::cerr << "          If --map-file-directory=... has been specified, the provided path will be prefixed to all\n";
    std::cerr << "          map-file arguments and, if the map arguments are left off, the default names will be used.\n";
    std::exit(EXIT_FAILURE);
}

void HandlePericopes(const bool verbose, const bool generate_solr_query, const std::string &bible_reference_candidate,
                     const std::string &pericopes_to_codes_map_filename)
{
    if (verbose)
        std::cout << "Entering HandlePericopes().\n";

    std::unordered_multimap<std::string, std::string> pericopes_to_codes_map;
    MapIO::DeserialiseMap(pericopes_to_codes_map_filename, &pericopes_to_codes_map);

    if (verbose)
        std::cout << "In HandlePericopes: looking for \"" << bible_reference_candidate << "\".\n";
    const auto begin_end(pericopes_to_codes_map.equal_range(bible_reference_candidate));
    if (begin_end.first != begin_end.second) {
        if (verbose)
            std::cerr << "Found a pericope to codes mapping.\n";
        std::string query;
        for (auto pair(begin_end.first); pair != begin_end.second; ++pair) {
            if (generate_solr_query) {
                if (not query.empty())
                    query += ' ';
                query += StringUtil::Map(pair->second, ':', '_');
            } else
                std::cout << pair->second << '\n';
        }
        if (generate_solr_query)
            std::cout << query << '\n';

        std::exit(EXIT_SUCCESS);
    }
}

void HandleBookRanges(const bool verbose, const bool generate_solr_query,
                      const std::string &books_of_the_bible_to_canonical_form_map_filename,
                      const std::string &books_of_the_bible_to_code_map_filename, const std::string &bible_reference_candidate)
{
    RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory("^([12])-([23])\\s*([A-ZÖa-zö]+)\\s*$"));
    if (not matcher->matched(bible_reference_candidate))
        return;

    unsigned starting_volume;
    if (not StringUtil::ToUnsigned((*matcher)[1], &starting_volume) or starting_volume > 2)
        LOG_ERROR("\"" + (*matcher)[1] + "\" is not a valid starting volume!");

    unsigned ending_volume;
    if (not StringUtil::ToUnsigned((*matcher)[2], &ending_volume) or ending_volume > 3
        or ending_volume <= starting_volume)
        LOG_ERROR("\"" + (*matcher)[2] + "\" is not a valid ending volume!");

    const std::string non_canonical_book_name((*matcher)[3]);
    BibleUtil::BibleBookCanoniser bible_book_canoniser(books_of_the_bible_to_canonical_form_map_filename);
    const std::string starting_bible_book_candidate(bible_book_canoniser.canonise(
        std::to_string(starting_volume) + non_canonical_book_name, verbose));

    const std::string ending_bible_book_candidate(bible_book_canoniser.canonise(
        std::to_string(ending_volume) + non_canonical_book_name, verbose));

    if (verbose) {
        std::cout << "Identified a bible book range.  Starting volume " << starting_volume << ", ending volume "
                  << ending_volume << ", book is \"" << non_canonical_book_name << "\".\n";
    }

    BibleUtil::BibleBookToCodeMapper bible_book_to_code_mapper(books_of_the_bible_to_code_map_filename);
    const std::string first_book_code(bible_book_to_code_mapper.mapToCode(starting_bible_book_candidate, verbose));
    if (first_book_code.empty())
        LOG_ERROR("failed to map \"" + starting_bible_book_candidate + "\" to a bible code!");
    const std::string second_book_code(bible_book_to_code_mapper.mapToCode(ending_bible_book_candidate, verbose));
    if (second_book_code.empty())
        LOG_ERROR("failed to map \"" + ending_bible_book_candidate + "\" to a bible code!");

    std::cout << (first_book_code + std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '0'))
              << (generate_solr_query ? '_' : ':')
              << (second_book_code + std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '9'))
              << '\n';

    std::exit(EXIT_SUCCESS);
}

void GenerateQuery(const bool verbose, const bool generate_solr_query, std::string book_candidate,
                   const std::string &chapters_and_verses_candidate,
                              const std::string &books_of_the_bible_to_code_map_filename,
                   const std::string &books_of_the_bible_to_canonical_form_map_filename)
{
    BibleUtil::BibleBookCanoniser bible_book_canoniser(books_of_the_bible_to_canonical_form_map_filename);
    book_candidate = bible_book_canoniser.canonise(book_candidate, verbose);
    BibleUtil::BibleBookToCodeMapper bible_book_to_code_mapper(books_of_the_bible_to_code_map_filename);
    const std::string book_code(bible_book_to_code_mapper.mapToCode(book_candidate, verbose));
    if (book_code.empty())
        LOG_ERROR("failed to map \"" + book_candidate + "\" to a bible code!");
    if (verbose)
        std::cerr << "book code = \"" << book_code << "\"\n";
    if (chapters_and_verses_candidate.empty()) {
        std::cout << book_code
                  << std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '0')
                  << (generate_solr_query ? '_' : ':') << book_code
                  << std::string(BibleUtil::MAX_CHAPTER_LENGTH + BibleUtil::MAX_VERSE_LENGTH, '9')
                  << '\n';

        std::exit(EXIT_SUCCESS);
    }

    std::set<std::pair<std::string, std::string>> start_end;
    if (not BibleUtil::ParseBibleReference(chapters_and_verses_candidate, book_code, &start_end)) {
        if (verbose)
            std::cerr << "The parsing of \"" << chapters_and_verses_candidate
                      << "\" as chapters and verses failed!\n";
        std::exit(EXIT_FAILURE);
    }

    std::string query;
    for (const auto &pair : start_end) {
        if (generate_solr_query) {
            if (not query.empty())
                query += ' ';
            query += pair.first + "_" + pair.second;
        } else
            std::cout << pair.first << ':' << pair.second << '\n';
    }
}

void HandleOrdinaryReferences(const bool verbose, const bool generate_solr_query,
                              const std::string &bible_reference_candidate,
                              const std::string &books_of_the_bible_to_code_map_filename,
                              const std::string &books_of_the_bible_to_canonical_form_map_filename)
{
    std::vector<std::string> book_candidate, chapters_and_verses_candidate;
    BibleUtil::SplitIntoBooksAndChaptersAndVerses(bible_reference_candidate, &book_candidate, &chapters_and_verses_candidate);
    if (verbose) {
        for (unsigned i(0); i < book_candidate.size(); ++i) {
            std::cerr << "book_candidate[" << i << "] = \"" << book_candidate[i] << "\"\n";
            std::cerr << "chapters_and_verses_candidate[" << i << "] = \"" << chapters_and_verses_candidate[i] << "\"\n";
        }
    }

    for (unsigned i(0); i < book_candidate.size(); ++i)
        GenerateQuery(verbose, generate_solr_query, book_candidate[i], chapters_and_verses_candidate[i],
                      books_of_the_bible_to_code_map_filename, books_of_the_bible_to_canonical_form_map_filename);

    if (generate_solr_query)
        std::cout << '\n';
}

} // unnamed namespace

int Main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc < 2)
        Usage();

    bool verbose(false), generate_solr_query(false);
    if (std::strcmp(argv[1], "--debug") == 0) {
        verbose = true;
        ++argv, --argc;
    } else if (std::strcmp(argv[1], "--query") == 0) {
        generate_solr_query = true;
        ++argv, --argc;
    }

    if (argc < 2)
        Usage();

    std::string map_file_path;
    if (StringUtil::StartsWith(argv[1], "--map-file-directory=")) {
        map_file_path = argv[1] + __builtin_strlen("--map-file-directory=");
        map_file_path += '/';
        ++argv, --argc;
    }

    if (argc != 6 and not (not map_file_path.empty() and argc == 2))
        Usage();

    std::string query(argv[1]);
    TextUtil::NormaliseDashes(&query);
    std::string bible_reference_candidate(StringUtil::Trim(TextUtil::CollapseWhitespace(TextUtil::UTF8ToLower(query))));
    const std::string bible_aliases_map_filename(map_file_path + (argc == 2 ? "bible_aliases.map" : argv[2]));
    const std::string books_of_the_bible_to_code_map_filename(map_file_path + (argc == 2 ? "books_of_the_bible_to_code.map" : argv[3]));
    const std::string books_of_the_bible_to_canonical_form_map_filename(
        map_file_path + (argc == 2 ? "books_of_the_bible_to_canonical_form.map" : argv[4]));
    const std::string pericopes_to_codes_map_filename(map_file_path + (argc == 2 ? "pericopes_to_codes.map" : argv[5]));

    const BibleUtil::BibleAliasMapper alias_mapper(bible_aliases_map_filename);
    bible_reference_candidate = alias_mapper.map(bible_reference_candidate, verbose);

    HandleBookRanges(verbose, generate_solr_query, books_of_the_bible_to_canonical_form_map_filename,
                     books_of_the_bible_to_code_map_filename, bible_reference_candidate);
    HandlePericopes(verbose, generate_solr_query, bible_reference_candidate, pericopes_to_codes_map_filename);
    HandleOrdinaryReferences(verbose, generate_solr_query, bible_reference_candidate,
                             books_of_the_bible_to_code_map_filename,
                             books_of_the_bible_to_canonical_form_map_filename);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "pong/game_world.hpp"

#include "Random.hpp"

namespace pong {

void GameWorld::create() {
    b2Vec2 gravity(0, 0);
    world_.reset(new b2World(gravity));
    world_->SetAllowSleeping(true);

    topWall_ = createTopWall();
    bottomWall_ = createBottomWall();
    ball_ = createBall();
    leftRaquet_ = createLeftRaquet();
    rightRaquet_ = createRightRaquet();
    gameArea_ = createGameArea();

    leftRaquetJoint_ = createLeftRaquetJoint();
    rightRaquetJoint_ = createRightRaquetJoint();

    world_->SetContactListener(this);
}

void GameWorld::update() {
    world_->Step(GAME_TIME_STEP, GAME_VELOCITY_ITERATIONS,
                 GAME_POSITION_ITERATIONS);

    if (hardReset_) {
        hardReset_ = false;
    } else if (softReset_) {
        world_->DestroyBody(ball_);
        ball_ = createBall();
        softReset_ = false;
    }
}

void GameWorld::EndContact(b2Contact* contact) {
    b2Fixture* fixtureA = contact->GetFixtureA();
    b2Fixture* fixtureB = contact->GetFixtureB();
    uint16 categoryA = fixtureA->GetFilterData().categoryBits;
    uint16 categoryB = fixtureB->GetFilterData().categoryBits;
    b2Body* ball = nullptr;
    b2Body* gameArea = nullptr;

    if (categoryA == BALL && categoryB == GAME_AREA) {
        ball = fixtureA->GetBody();
        gameArea = fixtureB->GetBody();
    } else if(categoryA == GAME_AREA && categoryB == BALL) {
        ball = fixtureB->GetBody();
        gameArea = fixtureA->GetBody();
    } else {
        return;
    }

    b2Vec2 ballPosition = ball->GetPosition();
    b2Vec2 gameAreaPosition = gameArea->GetPosition();

    if (ballPosition.x < gameAreaPosition.x) {
        fireScoreRight();
    } else if (ballPosition.x > gameAreaPosition.x) {
        fireScoreLeft();
    }
}

b2Body* GameWorld::createTopWall() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.filter.categoryBits = WALL;
    fixtureDef.filter.maskBits = BALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createBottomWall() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT - halfHeight) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.filter.categoryBits = WALL;
    fixtureDef.filter.maskBits = BALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createBall() {
    Random random;
    float halfWidth = 5.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(
        (WINDOW_WIDTH / 2.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    bodyDef.linearVelocity.x = random.nextInt() % 2 == 0 ? -1 : 1;
    bodyDef.linearVelocity.y = random.nextFloat(-1, 1);
    bodyDef.linearVelocity *= BALL_MIN_SPEED;
    bodyDef.angularVelocity = random.nextFloat(
        BALL_MIN_ROTATION_SPEED,
        BALL_MAX_ROTATION_SPEED
    );

    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.1f;
    fixtureDef.restitution = 1.0f;
    fixtureDef.filter.categoryBits = BALL;
    fixtureDef.filter.maskBits = ALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createLeftRaquet() {
    float halfWidth = 10.0f;
    float halfHeight = 40.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.fixedRotation = true;
    bodyDef.position.Set(
        15.0f / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.friction = 1.0f;
    fixtureDef.density = 1.0f;
    fixtureDef.filter.categoryBits = RAQUET;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createRightRaquet() {
    float halfWidth = 10.0f;
    float halfHeight = 40.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.fixedRotation = true;
    bodyDef.position.Set(
        (WINDOW_WIDTH - 15.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.friction = 1.0f;
    fixtureDef.density = 1.0f;
    fixtureDef.filter.categoryBits = RAQUET;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createGameArea() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = WINDOW_HEIGHT / 2.0f - 10.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        (WINDOW_WIDTH / 2.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.isSensor = true;
    fixtureDef.filter.categoryBits = GAME_AREA;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Joint* GameWorld::createLeftRaquetJoint() {
    float margin = 50.0f;
    float limit = (WINDOW_HEIGHT / 2.0f) - margin;

    b2PrismaticJointDef jointDef;
    b2Vec2 axis(0.0f, 1.0f);

    jointDef.Initialize(gameArea_, leftRaquet_, gameArea_->GetWorldCenter(), axis);
    jointDef.collideConnected = false;
    jointDef.lowerTranslation = -limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.upperTranslation = limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.enableLimit = true;

    return world_->CreateJoint(&jointDef);
}

b2Joint* GameWorld::createRightRaquetJoint() {
    float margin = 50.0f;
    float limit = (WINDOW_HEIGHT / 2.0f) - margin;

    b2PrismaticJointDef jointDef;
    b2Vec2 axis(0.0f, 1.0f);

    jointDef.Initialize(gameArea_, rightRaquet_, gameArea_->GetWorldCenter(), axis);
    jointDef.collideConnected = false;
    jointDef.lowerTranslation = -limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.upperTranslation = limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.enableLimit = true;

    return world_->CreateJoint(&jointDef);
}

void GameWorld::fireScoreLeft() {
    if (scoreListener_ != nullptr) {
        scoreListener_->leftScored(*this);
    }
}

void GameWorld::fireScoreRight() {
    if (scoreListener_ != nullptr) {
        scoreListener_->rightScored(*this);
    }
}

} /* namespace pong */
<commit_msg>Restart on hard reset<commit_after>#include "pong/game_world.hpp"

#include "Random.hpp"

namespace pong {

void GameWorld::create() {
    b2Vec2 gravity(0, 0);
    world_.reset(new b2World(gravity));
    world_->SetAllowSleeping(true);

    topWall_ = createTopWall();
    bottomWall_ = createBottomWall();
    ball_ = createBall();
    leftRaquet_ = createLeftRaquet();
    rightRaquet_ = createRightRaquet();
    gameArea_ = createGameArea();

    leftRaquetJoint_ = createLeftRaquetJoint();
    rightRaquetJoint_ = createRightRaquetJoint();

    world_->SetContactListener(this);
}

void GameWorld::update() {
    world_->Step(GAME_TIME_STEP, GAME_VELOCITY_ITERATIONS,
                 GAME_POSITION_ITERATIONS);

    if (hardReset_) {
        create();
        hardReset_ = false;
    } else if (softReset_) {
        world_->DestroyBody(ball_);
        ball_ = createBall();
        softReset_ = false;
    }
}

void GameWorld::EndContact(b2Contact* contact) {
    b2Fixture* fixtureA = contact->GetFixtureA();
    b2Fixture* fixtureB = contact->GetFixtureB();
    uint16 categoryA = fixtureA->GetFilterData().categoryBits;
    uint16 categoryB = fixtureB->GetFilterData().categoryBits;
    b2Body* ball = nullptr;
    b2Body* gameArea = nullptr;

    if (categoryA == BALL && categoryB == GAME_AREA) {
        ball = fixtureA->GetBody();
        gameArea = fixtureB->GetBody();
    } else if(categoryA == GAME_AREA && categoryB == BALL) {
        ball = fixtureB->GetBody();
        gameArea = fixtureA->GetBody();
    } else {
        return;
    }

    b2Vec2 ballPosition = ball->GetPosition();
    b2Vec2 gameAreaPosition = gameArea->GetPosition();

    if (ballPosition.x < gameAreaPosition.x) {
        fireScoreRight();
    } else if (ballPosition.x > gameAreaPosition.x) {
        fireScoreLeft();
    }
}

b2Body* GameWorld::createTopWall() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.filter.categoryBits = WALL;
    fixtureDef.filter.maskBits = BALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createBottomWall() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT - halfHeight) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.filter.categoryBits = WALL;
    fixtureDef.filter.maskBits = BALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createBall() {
    Random random;
    float halfWidth = 5.0f;
    float halfHeight = 5.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(
        (WINDOW_WIDTH / 2.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    bodyDef.linearVelocity.x = random.nextInt() % 2 == 0 ? -1 : 1;
    bodyDef.linearVelocity.y = random.nextFloat(-1, 1);
    bodyDef.linearVelocity *= BALL_MIN_SPEED;
    bodyDef.angularVelocity = random.nextFloat(
        BALL_MIN_ROTATION_SPEED,
        BALL_MAX_ROTATION_SPEED
    );

    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.1f;
    fixtureDef.restitution = 1.0f;
    fixtureDef.filter.categoryBits = BALL;
    fixtureDef.filter.maskBits = ALL;
    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createLeftRaquet() {
    float halfWidth = 10.0f;
    float halfHeight = 40.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.fixedRotation = true;
    bodyDef.position.Set(
        15.0f / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.friction = 1.0f;
    fixtureDef.density = 1.0f;
    fixtureDef.filter.categoryBits = RAQUET;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createRightRaquet() {
    float halfWidth = 10.0f;
    float halfHeight = 40.0f;

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.fixedRotation = true;
    bodyDef.position.Set(
        (WINDOW_WIDTH - 15.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.friction = 1.0f;
    fixtureDef.density = 1.0f;
    fixtureDef.filter.categoryBits = RAQUET;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Body* GameWorld::createGameArea() {
    float halfWidth = WINDOW_WIDTH / 2.0f;
    float halfHeight = WINDOW_HEIGHT / 2.0f - 10.0f;

    b2BodyDef bodyDef;
    bodyDef.position.Set(
        (WINDOW_WIDTH / 2.0f) / static_cast<float>(PIXELS_PER_METER),
        (WINDOW_HEIGHT / 2.0f) / static_cast<float>(PIXELS_PER_METER)
    );
    b2Body* body = world_->CreateBody(&bodyDef);
    b2PolygonShape shape;
    shape.SetAsBox(
        halfWidth / static_cast<float>(PIXELS_PER_METER),
        halfHeight / static_cast<float>(PIXELS_PER_METER)
    );
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.isSensor = true;
    fixtureDef.filter.categoryBits = GAME_AREA;
    fixtureDef.filter.maskBits = BALL;

    body->CreateFixture(&fixtureDef);

    return body;
}

b2Joint* GameWorld::createLeftRaquetJoint() {
    float margin = 50.0f;
    float limit = (WINDOW_HEIGHT / 2.0f) - margin;

    b2PrismaticJointDef jointDef;
    b2Vec2 axis(0.0f, 1.0f);

    jointDef.Initialize(gameArea_, leftRaquet_, gameArea_->GetWorldCenter(), axis);
    jointDef.collideConnected = false;
    jointDef.lowerTranslation = -limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.upperTranslation = limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.enableLimit = true;

    return world_->CreateJoint(&jointDef);
}

b2Joint* GameWorld::createRightRaquetJoint() {
    float margin = 50.0f;
    float limit = (WINDOW_HEIGHT / 2.0f) - margin;

    b2PrismaticJointDef jointDef;
    b2Vec2 axis(0.0f, 1.0f);

    jointDef.Initialize(gameArea_, rightRaquet_, gameArea_->GetWorldCenter(), axis);
    jointDef.collideConnected = false;
    jointDef.lowerTranslation = -limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.upperTranslation = limit / static_cast<float>(PIXELS_PER_METER);
    jointDef.enableLimit = true;

    return world_->CreateJoint(&jointDef);
}

void GameWorld::fireScoreLeft() {
    if (scoreListener_ != nullptr) {
        scoreListener_->leftScored(*this);
    }
}

void GameWorld::fireScoreRight() {
    if (scoreListener_ != nullptr) {
        scoreListener_->rightScored(*this);
    }
}

} /* namespace pong */
<|endoftext|>


<commit_before>#include "AFE-Data-Access.h"

AFEDataAccess::AFEDataAccess() {}

DEVICE AFEDataAccess::getDeviceConfiguration() {
  DEVICE configuration;

  Eeprom.read(9, 16).toCharArray(configuration.name,
                                 sizeof(configuration.name));
  configuration.isLED[0] = Eeprom.read(366);
  configuration.isRelay[0] = Eeprom.read(368);
  configuration.isSwitch[0] = Eeprom.read(394);
  configuration.isSwitch[1] = Eeprom.read(401);
  configuration.httpAPI = Eeprom.read(25);
  configuration.mqttAPI = Eeprom.read(228);

  return configuration;
}

FIRMWARE AFEDataAccess::getFirmwareConfiguration() {
  FIRMWARE configuration;

  Eeprom.read(0, 7).toCharArray(configuration.version,
                                sizeof(configuration.version));
  Eeprom.read(28, 120).toCharArray(configuration.upgradeURL,
                                   sizeof(configuration.upgradeURL));
  configuration.type = Eeprom.readUInt8(7);
  configuration.autoUpgrade = Eeprom.readUInt8(27);
  return configuration;
}

NETWORK AFEDataAccess::getNetworkConfiguration() {
  NETWORK configuration;

  Eeprom.read(148, 32).toCharArray(configuration.ssid,
                                   sizeof(configuration.ssid));
  Eeprom.read(180, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));

  configuration.isDHCP = Eeprom.read(212);
  configuration.ip = Eeprom.readIP(213);
  configuration.gateway = Eeprom.readIP(217);
  configuration.subnet = Eeprom.readIP(221);
  configuration.noConnectionAttempts = Eeprom.readUInt8(225);
  configuration.waitTimeConnections = Eeprom.readUInt8(226);
  configuration.waitTimeSeries = Eeprom.readUInt8(227);
  return configuration;
}

MQTT AFEDataAccess::getMQTTConfiguration() {
  MQTT configuration;

  Eeprom.read(229, 32).toCharArray(configuration.host,
                                   sizeof(configuration.host));
  configuration.ip = Eeprom.readIP(261);
  configuration.port = Eeprom.read(265, 5).toInt();
  Eeprom.read(270, 32).toCharArray(configuration.user,
                                   sizeof(configuration.user));
  Eeprom.read(302, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));
  Eeprom.read(334, 32).toCharArray(configuration.topic,
                                   sizeof(configuration.topic));

  return configuration;
}

LED AFEDataAccess::getLEDConfiguration(uint8_t id) {
  LED configuration;
  uint8_t nextLED = 0;
  configuration.gpio = Eeprom.readUInt8(367 + id * nextLED);
  return configuration;
}

RELAY AFEDataAccess::getRelayConfiguration(uint8_t id) {
  RELAY configuration;
  MQTT configurationMQTT;
  uint8_t nextRelay = 26;
  char mqttTopic[49];
  configuration.gpio = Eeprom.readUInt8(369 + id * nextRelay);
  configuration.timeToOff = Eeprom.read(371 + id * nextRelay, 5).toFloat();
  configuration.statePowerOn = Eeprom.readUInt8(376 + id * nextRelay);

  Eeprom.read(377 + id * nextRelay, 16)
      .toCharArray(configuration.name, sizeof(configuration.name));

  configuration.stateMQTTConnected = Eeprom.readUInt8(393 + id * nextRelay);

  Eeprom.read(334, 32).toCharArray(configurationMQTT.topic,
                                   sizeof(configurationMQTT.topic));

  sprintf(configuration.mqttTopic, "%s%s/", configurationMQTT.topic,
          configuration.name);

  /* @TODO DOMOTICZ
    configuration.idx = Eeprom.read(376 + id * next, 5).toInt();
    configuration.publishToDomoticz = Eeprom.readUInt8(382 + id * next); */

  return configuration;
}

SWITCH AFEDataAccess::getSwitchConfiguration(uint8_t id) {
  SWITCH configuration;
  uint8_t nextSwitch = 7;
  configuration.gpio = Eeprom.readUInt8(395 + id * nextSwitch);
  configuration.type = Eeprom.readUInt8(396 + id * nextSwitch);
  configuration.sensitiveness = Eeprom.read(397 + id * nextSwitch, 3).toInt();
  configuration.functionality = Eeprom.readUInt8(400 + id * nextSwitch);

  return configuration;
}

void AFEDataAccess::saveConfiguration(DEVICE configuration) {
  Eeprom.write(9, 16, configuration.name);
  Eeprom.write(368, configuration.isRelay[0]);
  Eeprom.write(394, configuration.isSwitch[0]);
  Eeprom.write(401, configuration.isSwitch[1]);
  Eeprom.write(366, configuration.isLED[0]);
  Eeprom.write(25, configuration.httpAPI);
  Eeprom.write(228, configuration.mqttAPI);
  // Eeprom.write(413, configuration.isDS18B20);
}

void AFEDataAccess::saveConfiguration(FIRMWARE configuration) {
  Eeprom.write(0, 7, configuration.version);
  Eeprom.writeUInt8(7, configuration.type);
  Eeprom.writeUInt8(27, configuration.autoUpgrade);
  Eeprom.write(28, 120, configuration.upgradeURL);
}

void AFEDataAccess::saveConfiguration(NETWORK configuration) {
  Eeprom.write(148, 32, configuration.ssid);
  Eeprom.write(180, 32, configuration.password);
  Eeprom.write(212, configuration.isDHCP);
  Eeprom.writeIP(213, configuration.ip);
  Eeprom.writeIP(217, configuration.gateway);
  Eeprom.writeIP(221, configuration.subnet);
  Eeprom.writeUInt8(225, configuration.noConnectionAttempts);
  Eeprom.writeUInt8(226, configuration.waitTimeConnections);
  Eeprom.writeUInt8(227, configuration.waitTimeSeries);
}

void AFEDataAccess::saveConfiguration(MQTT configuration) {
  Eeprom.write(229, 32, configuration.host);
  Eeprom.writeIP(261, configuration.ip);
  Eeprom.write(265, 5, (long)configuration.port);
  Eeprom.write(270, 32, configuration.user);
  Eeprom.write(302, 32, configuration.password);
  Eeprom.write(334, 32, configuration.topic);
}

void AFEDataAccess::saveConfiguration(uint8_t id, RELAY configuration) {
  uint8_t nextRelay = 26;

  Eeprom.writeUInt8(369 + id * nextRelay, configuration.gpio);
  Eeprom.write(371 + id * nextRelay, 5, configuration.timeToOff);
  Eeprom.writeUInt8(376 + id * nextRelay, configuration.statePowerOn);
  /* @TODO For MQTT only */
  Eeprom.write(377 + id * nextRelay, 16, configuration.name);
  Eeprom.writeUInt8(393 + id * nextRelay, configuration.stateMQTTConnected);
  /* @TODO DOMOTICZ
    Eeprom.write(376 + id * nextRelay, 5, (long)configuration.idx);
    Eeprom.writeUInt8(382 + id * nextRelay, configuration.publishToDomoticz);
    */
}

void AFEDataAccess::saveConfiguration(uint8_t id, LED configuration) {
  uint8_t nextLED = 0;
  Eeprom.writeUInt8(367 + id * nextLED, configuration.gpio);
}

void AFEDataAccess::saveConfiguration(uint8_t id, SWITCH configuration) {
  uint8_t nextSwitch = 7;
  Eeprom.writeUInt8(395 + id * nextSwitch, configuration.gpio);
  Eeprom.writeUInt8(396 + id * nextSwitch, configuration.type);
  Eeprom.write(397 + id * nextSwitch, 3, (long)configuration.sensitiveness);
  Eeprom.writeUInt8(400 + id * nextSwitch, configuration.functionality);
}

const char AFEDataAccess::getVersion() {
  char version[7];
  Eeprom.read(0, 7).toCharArray(version, sizeof(version));
  return *version;
}

void AFEDataAccess::saveVersion(String version) { Eeprom.write(0, 7, version); }

boolean AFEDataAccess::getRelayState(uint8_t id) {
  uint8_t nextRelay = 26;
  return Eeprom.read(370 + id * nextRelay);
}

void AFEDataAccess::saveRelayState(uint8_t id, boolean state) {
  uint8_t nextRelay = 26;
  Eeprom.write(370 + id * nextRelay, state);
}

uint8_t AFEDataAccess::getDeviceMode() { return Eeprom.readUInt8(26); }

void AFEDataAccess::saveDeviceMode(uint8_t mode) {
  Eeprom.writeUInt8(26, mode);
}

uint8_t AFEDataAccess::getLanguage() { return Eeprom.readUInt8(8); }

void AFEDataAccess::saveLanguage(uint8_t language) {
  Eeprom.writeUInt8(8, language);
}

/* @TODO DOMOTICZ
DOMOTICZ AFEDataAccess::getDomoticzConfiguration() {
  DOMOTICZ configuration;

  Eeprom.read(228, 32).toCharArray(configuration.host,
                                   sizeof(configuration.host));
  configuration.ip = Eeprom.readIP(260);
  configuration.port = Eeprom.read(264, 5).toInt();
  Eeprom.read(269, 32).toCharArray(configuration.user,
                                   sizeof(configuration.user));
  Eeprom.read(301, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));

  Serial << endl << "INFO: Requested : Domoticz";
  Serial << endl << "    - Host : " << configuration.host;
  Serial << endl << "    - IP : " << configuration.ip;
  Serial << endl << "    - Port : " << configuration.port;
  Serial << endl << "    - User : " << configuration.user;
  Serial << endl << "    - Password : " << configuration.password;

  return configuration;
}
*/
/* @TODO DS18B20
DS18B20 AFEDataAccess::getDS18B20Configuration() {
  DS18B20 configuration;

  configuration.present = Eeprom.read(400);
  configuration.gpio = Eeprom.readUInt8(401);
  configuration.correction = Eeprom.read(402, 5).toFloat();
  configuration.interval = Eeprom.read(407, 5).toInt();
  configuration.unit = Eeprom.readUInt8(412);
  Serial << endl << "INFO: Requested : DS18B20 : ";
  Serial << endl << "    - Present : " << configuration.present;
  Serial << endl << "    - GPIO : " << configuration.gpio;
  Serial << endl << "    - Correction by : " << configuration.correction;
  Serial << endl << "    - Read interval : " << configuration.interval;
  Serial << endl << "    - Unit : " << configuration.unit;
  return configuration;
}

*/
/* @TODO DOMOTICZ
void AFEDataAccess::saveConfiguration(DOMOTICZ configuration) {
  Eeprom.write(228, 32, configuration.host);
  Eeprom.writeIP(260, configuration.ip);
  Eeprom.write(264, 5, (long)configuration.port);
  Eeprom.write(269, 32, configuration.user);
  Eeprom.write(301, 32, configuration.password);
}
*/
/* @TODO DS18B20
void AFEDataAccess::saveConfiguration(DS18B20 configuration) {
  Eeprom.writeUInt8(401, configuration.gpio);
  Eeprom.write(402, 5, (float)configuration.correction);
  Eeprom.write(407, 5, (long)configuration.interval);
  Eeprom.writeUInt8(412, configuration.unit);
} */
<commit_msg>changed EEPROM mappning<commit_after>#include "AFE-Data-Access.h"

AFEDataAccess::AFEDataAccess() {}

DEVICE AFEDataAccess::getDeviceConfiguration() {
  DEVICE configuration;

  Eeprom.read(9, 16).toCharArray(configuration.name,
                                 sizeof(configuration.name));
  configuration.isLED[0] = Eeprom.read(366);
  configuration.isRelay[0] = Eeprom.read(369);
  configuration.isSwitch[0] = Eeprom.read(395);
  configuration.isSwitch[1] = Eeprom.read(402);
  configuration.httpAPI = Eeprom.read(25);
  configuration.mqttAPI = Eeprom.read(228);

  return configuration;
}

FIRMWARE AFEDataAccess::getFirmwareConfiguration() {
  FIRMWARE configuration;

  Eeprom.read(0, 7).toCharArray(configuration.version,
                                sizeof(configuration.version));
  Eeprom.read(28, 120).toCharArray(configuration.upgradeURL,
                                   sizeof(configuration.upgradeURL));
  configuration.type = Eeprom.readUInt8(7);
  configuration.autoUpgrade = Eeprom.readUInt8(27);
  return configuration;
}

NETWORK AFEDataAccess::getNetworkConfiguration() {
  NETWORK configuration;

  Eeprom.read(148, 32).toCharArray(configuration.ssid,
                                   sizeof(configuration.ssid));
  Eeprom.read(180, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));

  configuration.isDHCP = Eeprom.read(212);
  configuration.ip = Eeprom.readIP(213);
  configuration.gateway = Eeprom.readIP(217);
  configuration.subnet = Eeprom.readIP(221);
  configuration.noConnectionAttempts = Eeprom.readUInt8(225);
  configuration.waitTimeConnections = Eeprom.readUInt8(226);
  configuration.waitTimeSeries = Eeprom.readUInt8(227);
  return configuration;
}

MQTT AFEDataAccess::getMQTTConfiguration() {
  MQTT configuration;

  Eeprom.read(229, 32).toCharArray(configuration.host,
                                   sizeof(configuration.host));
  configuration.ip = Eeprom.readIP(261);
  configuration.port = Eeprom.read(265, 5).toInt();
  Eeprom.read(270, 32).toCharArray(configuration.user,
                                   sizeof(configuration.user));
  Eeprom.read(302, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));
  Eeprom.read(334, 32).toCharArray(configuration.topic,
                                   sizeof(configuration.topic));

  return configuration;
}

LED AFEDataAccess::getLEDConfiguration(uint8_t id) {
  LED configuration;
  uint8_t nextLED = 0;
  configuration.gpio = Eeprom.readUInt8(367 + id * nextLED);
  configuration.changeToOppositeValue = Eeprom.read(368 + id * nextLED);

  return configuration;
}

RELAY AFEDataAccess::getRelayConfiguration(uint8_t id) {
  RELAY configuration;
  MQTT configurationMQTT;
  uint8_t nextRelay = 26;
  char mqttTopic[49];
  configuration.gpio = Eeprom.readUInt8(370 + id * nextRelay);
  configuration.timeToOff = Eeprom.read(372 + id * nextRelay, 5).toFloat();
  configuration.statePowerOn = Eeprom.readUInt8(377 + id * nextRelay);

  Eeprom.read(378 + id * nextRelay, 16)
      .toCharArray(configuration.name, sizeof(configuration.name));

  configuration.stateMQTTConnected = Eeprom.readUInt8(394 + id * nextRelay);

  Eeprom.read(334, 32).toCharArray(configurationMQTT.topic,
                                   sizeof(configurationMQTT.topic));

  sprintf(configuration.mqttTopic, "%s%s/", configurationMQTT.topic,
          configuration.name);

  /* @TODO DOMOTICZ
    configuration.idx = Eeprom.read(376 + id * next, 5).toInt();
    configuration.publishToDomoticz = Eeprom.readUInt8(382 + id * next); */

  return configuration;
}

SWITCH AFEDataAccess::getSwitchConfiguration(uint8_t id) {
  SWITCH configuration;
  uint8_t nextSwitch = 7;
  configuration.gpio = Eeprom.readUInt8(396 + id * nextSwitch);
  configuration.type = Eeprom.readUInt8(397 + id * nextSwitch);
  configuration.sensitiveness = Eeprom.read(398 + id * nextSwitch, 3).toInt();
  configuration.functionality = Eeprom.readUInt8(401 + id * nextSwitch);

  return configuration;
}

void AFEDataAccess::saveConfiguration(DEVICE configuration) {
  Eeprom.write(9, 16, configuration.name);
  Eeprom.write(369, configuration.isRelay[0]);
  Eeprom.write(395, configuration.isSwitch[0]);
  Eeprom.write(402, configuration.isSwitch[1]);
  Eeprom.write(367, configuration.isLED[0]);
  Eeprom.write(25, configuration.httpAPI);
  Eeprom.write(228, configuration.mqttAPI);
  // Eeprom.write(413, configuration.isDS18B20);
}

void AFEDataAccess::saveConfiguration(FIRMWARE configuration) {
  Eeprom.write(0, 7, configuration.version);
  Eeprom.writeUInt8(7, configuration.type);
  Eeprom.writeUInt8(27, configuration.autoUpgrade);
  Eeprom.write(28, 120, configuration.upgradeURL);
}

void AFEDataAccess::saveConfiguration(NETWORK configuration) {
  Eeprom.write(148, 32, configuration.ssid);
  Eeprom.write(180, 32, configuration.password);
  Eeprom.write(212, configuration.isDHCP);
  Eeprom.writeIP(213, configuration.ip);
  Eeprom.writeIP(217, configuration.gateway);
  Eeprom.writeIP(221, configuration.subnet);
  Eeprom.writeUInt8(225, configuration.noConnectionAttempts);
  Eeprom.writeUInt8(226, configuration.waitTimeConnections);
  Eeprom.writeUInt8(227, configuration.waitTimeSeries);
}

void AFEDataAccess::saveConfiguration(MQTT configuration) {
  Eeprom.write(229, 32, configuration.host);
  Eeprom.writeIP(261, configuration.ip);
  Eeprom.write(265, 5, (long)configuration.port);
  Eeprom.write(270, 32, configuration.user);
  Eeprom.write(302, 32, configuration.password);
  Eeprom.write(334, 32, configuration.topic);
}

void AFEDataAccess::saveConfiguration(uint8_t id, RELAY configuration) {
  uint8_t nextRelay = 26;

  Eeprom.writeUInt8(370 + id * nextRelay, configuration.gpio);
  Eeprom.write(372 + id * nextRelay, 5, configuration.timeToOff);
  Eeprom.writeUInt8(377 + id * nextRelay, configuration.statePowerOn);
  /* @TODO For MQTT only */
  Eeprom.write(378 + id * nextRelay, 16, configuration.name);
  Eeprom.writeUInt8(394 + id * nextRelay, configuration.stateMQTTConnected);
  /* @TODO DOMOTICZ
    Eeprom.write(376 + id * nextRelay, 5, (long)configuration.idx);
    Eeprom.writeUInt8(382 + id * nextRelay, configuration.publishToDomoticz);
    */
}

void AFEDataAccess::saveConfiguration(uint8_t id, LED configuration) {
  uint8_t nextLED = 2;
  Eeprom.writeUInt8(367 + id * nextLED, configuration.gpio);
  Eeprom.write(368 + id * nextLED, configuration.changeToOppositeValue);
}

void AFEDataAccess::saveConfiguration(uint8_t id, SWITCH configuration) {
  uint8_t nextSwitch = 7;
  Eeprom.writeUInt8(396 + id * nextSwitch, configuration.gpio);
  Eeprom.writeUInt8(397 + id * nextSwitch, configuration.type);
  Eeprom.write(398 + id * nextSwitch, 3, (long)configuration.sensitiveness);
  Eeprom.writeUInt8(401 + id * nextSwitch, configuration.functionality);
}

const char AFEDataAccess::getVersion() {
  char version[7];
  Eeprom.read(0, 7).toCharArray(version, sizeof(version));
  return *version;
}

void AFEDataAccess::saveVersion(String version) { Eeprom.write(0, 7, version); }

boolean AFEDataAccess::getRelayState(uint8_t id) {
  uint8_t nextRelay = 26;
  return Eeprom.read(371 + id * nextRelay);
}

void AFEDataAccess::saveRelayState(uint8_t id, boolean state) {
  uint8_t nextRelay = 26;
  Eeprom.write(371 + id * nextRelay, state);
}

uint8_t AFEDataAccess::getDeviceMode() { return Eeprom.readUInt8(26); }

void AFEDataAccess::saveDeviceMode(uint8_t mode) {
  Eeprom.writeUInt8(26, mode);
}

uint8_t AFEDataAccess::getLanguage() { return Eeprom.readUInt8(8); }

void AFEDataAccess::saveLanguage(uint8_t language) {
  Eeprom.writeUInt8(8, language);
}

/* @TODO DOMOTICZ
DOMOTICZ AFEDataAccess::getDomoticzConfiguration() {
  DOMOTICZ configuration;

  Eeprom.read(228, 32).toCharArray(configuration.host,
                                   sizeof(configuration.host));
  configuration.ip = Eeprom.readIP(260);
  configuration.port = Eeprom.read(264, 5).toInt();
  Eeprom.read(269, 32).toCharArray(configuration.user,
                                   sizeof(configuration.user));
  Eeprom.read(301, 32).toCharArray(configuration.password,
                                   sizeof(configuration.password));

  Serial << endl << "INFO: Requested : Domoticz";
  Serial << endl << "    - Host : " << configuration.host;
  Serial << endl << "    - IP : " << configuration.ip;
  Serial << endl << "    - Port : " << configuration.port;
  Serial << endl << "    - User : " << configuration.user;
  Serial << endl << "    - Password : " << configuration.password;

  return configuration;
}
*/
/* @TODO DS18B20
DS18B20 AFEDataAccess::getDS18B20Configuration() {
  DS18B20 configuration;

  configuration.present = Eeprom.read(400);
  configuration.gpio = Eeprom.readUInt8(401);
  configuration.correction = Eeprom.read(402, 5).toFloat();
  configuration.interval = Eeprom.read(407, 5).toInt();
  configuration.unit = Eeprom.readUInt8(412);
  Serial << endl << "INFO: Requested : DS18B20 : ";
  Serial << endl << "    - Present : " << configuration.present;
  Serial << endl << "    - GPIO : " << configuration.gpio;
  Serial << endl << "    - Correction by : " << configuration.correction;
  Serial << endl << "    - Read interval : " << configuration.interval;
  Serial << endl << "    - Unit : " << configuration.unit;
  return configuration;
}

*/
/* @TODO DOMOTICZ
void AFEDataAccess::saveConfiguration(DOMOTICZ configuration) {
  Eeprom.write(228, 32, configuration.host);
  Eeprom.writeIP(260, configuration.ip);
  Eeprom.write(264, 5, (long)configuration.port);
  Eeprom.write(269, 32, configuration.user);
  Eeprom.write(301, 32, configuration.password);
}
*/
/* @TODO DS18B20
void AFEDataAccess::saveConfiguration(DS18B20 configuration) {
  Eeprom.writeUInt8(401, configuration.gpio);
  Eeprom.write(402, 5, (float)configuration.correction);
  Eeprom.write(407, 5, (long)configuration.interval);
  Eeprom.writeUInt8(412, configuration.unit);
} */
<|endoftext|>


<commit_before>//===- NameHashTable.cpp - PDB Name Hash Table ------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/PDB/Raw/ByteStream.h"
#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"
#include "llvm/Support/Endian.h"

using namespace llvm;
using namespace llvm::support;
using namespace llvm::pdb;

typedef uint32_t *PUL;
typedef uint16_t *PUS;

static inline uint32_t HashStringV1(StringRef Str) {
  uint32_t Result = 0;
  uint32_t Size = Str.size();

  ArrayRef<ulittle32_t> Longs(reinterpret_cast<const ulittle32_t *>(Str.data()),
                              Size / 4);

  for (auto Value : Longs)
    Result ^= Value;

  const uint8_t *Remainder = reinterpret_cast<const uint8_t *>(Longs.end());
  uint32_t RemainderSize = Size - Longs.size() * 4;

  // Maximum of 3 bytes left.  Hash a 2 byte word if possible, then hash the
  // possibly remaining 1 byte.
  if (RemainderSize >= 2) {
    Result ^= *reinterpret_cast<const ulittle16_t *>(Remainder);
    Remainder += 2;
    RemainderSize -= 2;
  }

  // hash possible odd byte
  if (RemainderSize == 1) {
    Result ^= *(Remainder++);
  }

  const uint32_t toLowerMask = 0x20202020;
  Result |= toLowerMask;
  Result ^= (Result >> 11);

  return Result ^ (Result >> 16);
}

static inline uint32_t HashStringV2(StringRef Str) {
  uint32_t Hash = 0xb170a1bf;

  ArrayRef<char> Buffer(Str.begin(), Str.end());

  ArrayRef<ulittle32_t> Items(
      reinterpret_cast<const ulittle32_t *>(Buffer.data()),
      Buffer.size() / sizeof(ulittle32_t));
  for (ulittle32_t Item : Items) {
    Hash += Item;
    Hash += (Hash << 10);
    Hash ^= (Hash >> 6);
  }
  Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t));
  for (uint8_t Item : Buffer) {
    Hash += Item;
    Hash += (Hash << 10);
    Hash ^= (Hash >> 6);
  }

  return Hash * 1664525L + 1013904223L;
}

NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {}

std::error_code NameHashTable::load(StreamReader &Stream) {
  struct Header {
    support::ulittle32_t Signature;
    support::ulittle32_t HashVersion;
    support::ulittle32_t ByteSize;
  };

  Header H;
  Stream.readObject(&H);
  if (H.Signature != 0xEFFEEFFE)
    return std::make_error_code(std::errc::illegal_byte_sequence);
  if (H.HashVersion != 1 && H.HashVersion != 2)
    return std::make_error_code(std::errc::not_supported);

  Signature = H.Signature;
  HashVersion = H.HashVersion;
  NamesBuffer.initialize(Stream, H.ByteSize);

  support::ulittle32_t HashCount;
  Stream.readObject(&HashCount);
  std::vector<support::ulittle32_t> BucketArray(HashCount);
  Stream.readArray<support::ulittle32_t>(BucketArray);
  IDs.assign(BucketArray.begin(), BucketArray.end());

  if (Stream.bytesRemaining() < sizeof(support::ulittle32_t))
    return std::make_error_code(std::errc::illegal_byte_sequence);

  Stream.readInteger(NameCount);
  return std::error_code();
}

StringRef NameHashTable::getStringForID(uint32_t ID) const {
  if (ID == IDs[0])
    return StringRef();

  return StringRef(NamesBuffer.str().begin() + ID);
}

uint32_t NameHashTable::getIDForString(StringRef Str) const {
  uint32_t Hash = (HashVersion == 1) ? HashStringV1(Str) : HashStringV2(Str);
  size_t Count = IDs.size();
  uint32_t Start = Hash % Count;
  for (size_t I = 0; I < Count; ++I) {
    // The hash is just a starting point for the search, but if it
    // doesn't work we should find the string no matter what, because
    // we iterate the entire array.
    uint32_t Index = (Start + I) % Count;

    uint32_t ID = IDs[Index];
    StringRef S = getStringForID(ID);
    if (S == Str)
      return ID;
  }
  // IDs[0] contains the ID of the "invalid" entry.
  return IDs[0];
}

ArrayRef<uint32_t> NameHashTable::name_ids() const {
  return ArrayRef<uint32_t>(IDs).slice(1, NameCount);
}
<commit_msg>Fix build breakage due to implicit conversion.<commit_after>//===- NameHashTable.cpp - PDB Name Hash Table ------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/PDB/Raw/ByteStream.h"
#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"
#include "llvm/Support/Endian.h"

using namespace llvm;
using namespace llvm::support;
using namespace llvm::pdb;

typedef uint32_t *PUL;
typedef uint16_t *PUS;

static inline uint32_t HashStringV1(StringRef Str) {
  uint32_t Result = 0;
  uint32_t Size = Str.size();

  ArrayRef<ulittle32_t> Longs(reinterpret_cast<const ulittle32_t *>(Str.data()),
                              Size / 4);

  for (auto Value : Longs)
    Result ^= Value;

  const uint8_t *Remainder = reinterpret_cast<const uint8_t *>(Longs.end());
  uint32_t RemainderSize = Size - Longs.size() * 4;

  // Maximum of 3 bytes left.  Hash a 2 byte word if possible, then hash the
  // possibly remaining 1 byte.
  if (RemainderSize >= 2) {
    uint16_t Value = *reinterpret_cast<const ulittle16_t *>(Remainder);
    Result ^= static_cast<uint32_t>(Value);
    Remainder += 2;
    RemainderSize -= 2;
  }

  // hash possible odd byte
  if (RemainderSize == 1) {
    Result ^= *(Remainder++);
  }

  const uint32_t toLowerMask = 0x20202020;
  Result |= toLowerMask;
  Result ^= (Result >> 11);

  return Result ^ (Result >> 16);
}

static inline uint32_t HashStringV2(StringRef Str) {
  uint32_t Hash = 0xb170a1bf;

  ArrayRef<char> Buffer(Str.begin(), Str.end());

  ArrayRef<ulittle32_t> Items(
      reinterpret_cast<const ulittle32_t *>(Buffer.data()),
      Buffer.size() / sizeof(ulittle32_t));
  for (ulittle32_t Item : Items) {
    Hash += Item;
    Hash += (Hash << 10);
    Hash ^= (Hash >> 6);
  }
  Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t));
  for (uint8_t Item : Buffer) {
    Hash += Item;
    Hash += (Hash << 10);
    Hash ^= (Hash >> 6);
  }

  return Hash * 1664525L + 1013904223L;
}

NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {}

std::error_code NameHashTable::load(StreamReader &Stream) {
  struct Header {
    support::ulittle32_t Signature;
    support::ulittle32_t HashVersion;
    support::ulittle32_t ByteSize;
  };

  Header H;
  Stream.readObject(&H);
  if (H.Signature != 0xEFFEEFFE)
    return std::make_error_code(std::errc::illegal_byte_sequence);
  if (H.HashVersion != 1 && H.HashVersion != 2)
    return std::make_error_code(std::errc::not_supported);

  Signature = H.Signature;
  HashVersion = H.HashVersion;
  NamesBuffer.initialize(Stream, H.ByteSize);

  support::ulittle32_t HashCount;
  Stream.readObject(&HashCount);
  std::vector<support::ulittle32_t> BucketArray(HashCount);
  Stream.readArray<support::ulittle32_t>(BucketArray);
  IDs.assign(BucketArray.begin(), BucketArray.end());

  if (Stream.bytesRemaining() < sizeof(support::ulittle32_t))
    return std::make_error_code(std::errc::illegal_byte_sequence);

  Stream.readInteger(NameCount);
  return std::error_code();
}

StringRef NameHashTable::getStringForID(uint32_t ID) const {
  if (ID == IDs[0])
    return StringRef();

  return StringRef(NamesBuffer.str().begin() + ID);
}

uint32_t NameHashTable::getIDForString(StringRef Str) const {
  uint32_t Hash = (HashVersion == 1) ? HashStringV1(Str) : HashStringV2(Str);
  size_t Count = IDs.size();
  uint32_t Start = Hash % Count;
  for (size_t I = 0; I < Count; ++I) {
    // The hash is just a starting point for the search, but if it
    // doesn't work we should find the string no matter what, because
    // we iterate the entire array.
    uint32_t Index = (Start + I) % Count;

    uint32_t ID = IDs[Index];
    StringRef S = getStringForID(ID);
    if (S == Str)
      return ID;
  }
  // IDs[0] contains the ID of the "invalid" entry.
  return IDs[0];
}

ArrayRef<uint32_t> NameHashTable::name_ids() const {
  return ArrayRef<uint32_t>(IDs).slice(1, NameCount);
}
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE MediaElement
#include <boost/test/unit_test.hpp>
#include <MediaPipelineImpl.hpp>
#include <MediaElementImpl.hpp>
#include <ElementConnectionData.hpp>
#include <MediaType.hpp>
#include <KurentoException.hpp>
#include <GstreamerDotDetails.hpp>
#include <MediaSet.hpp>
#include <ModuleManager.hpp>

using namespace kurento;

ModuleManager moduleManager;
boost::property_tree::ptree config;

static std::shared_ptr <MediaElementImpl>
createDummyElement (std::string name, std::string mediaPipelineId)
{
  std::shared_ptr <MediaElementImpl> element = std::dynamic_pointer_cast
      <MediaElementImpl> (MediaSet::getMediaSet()->ref (new  MediaElementImpl (
                            boost::property_tree::ptree(),
                            MediaSet::getMediaSet()->getMediaObject (mediaPipelineId),
                            name) ) );

  return element;
}

BOOST_AUTO_TEST_CASE (connection_test)
{
  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);

  std::shared_ptr <MediaType> VIDEO (new MediaType (MediaType::VIDEO) );
  std::shared_ptr <MediaType> AUDIO (new MediaType (MediaType::AUDIO) );

  src->setName ("SOURCE");
  sink->setName ("SINK");

  src->connect (sink);
  auto connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 2);

  for (auto it : connections) {
    BOOST_CHECK (it->getSource()->getId() == src->getId() );
  }

  g_object_set (src->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);
  g_object_set (sink->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);

  connections = src->getSinkConnections ();
  BOOST_CHECK (connections.size() == 2);

  for (auto it : connections) {
    BOOST_CHECK (it->getSource()->getId() == src->getId() );
  }

  connections = sink->getSourceConnections (AUDIO);
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (AUDIO, "");
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (AUDIO, "test");
  BOOST_CHECK (connections.size() == 0);

  connections = sink->getSourceConnections (VIDEO);
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "");
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "test");
  BOOST_CHECK (connections.size() == 0);

  src->disconnect (sink);

  connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 0);

  src->connect (sink, AUDIO);

  connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 1);

  connections = src->getSinkConnections ();
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "");
  BOOST_CHECK (connections.size() == 0);

  src->release();
  src.reset();

  connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 0);

  sink->release();
}

BOOST_AUTO_TEST_CASE (release_before_real_connection)
{
  GstElement *srcElement;

  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);

  src->setName ("SOURCE");
  sink->setName ("SINK");

  g_object_set (sink->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);
  srcElement = (GstElement *) g_object_ref (src->getGstreamerElement() );
  g_object_set (srcElement, "audio", TRUE, NULL);

  src->connect (sink);

  src->disconnect (sink);

  g_object_set (srcElement, "audio", TRUE, "video", TRUE, NULL);
  g_object_unref (srcElement);

  src->release();
  sink->release();
}

BOOST_AUTO_TEST_CASE (loopback)
{
  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> duplex = createDummyElement ("dummyduplex",
      mediaPipelineId);

  duplex->setName ("DUPLEX");

  g_object_set (duplex->getGstreamerElement(), "src-audio", TRUE, "src-video",
                TRUE, "sink-audio", TRUE, "sink-video", TRUE, NULL);

  duplex->connect (duplex);

  duplex->release();
}

BOOST_AUTO_TEST_CASE (no_common_pipeline)
{
  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");

  std::string mediaPipelineId1 =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::string mediaPipelineId2 =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId1);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId2);

  src->setName ("SOURCE");
  sink->setName ("SINK");

  try {
    src->connect (sink);
    BOOST_FAIL ("Previous operation should raise an exception");
  } catch (KurentoException e) {
    BOOST_CHECK (e.getCode () == CONNECT_ERROR);
  }

  sink->release();
  src->release();
}

BOOST_AUTO_TEST_CASE (dot_test)
{
  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);
  std::shared_ptr <MediaPipelineImpl> pipe = std::dynamic_pointer_cast
      <MediaPipelineImpl> (MediaSet::getMediaSet()->getMediaObject (
                             mediaPipelineId) );

  GstElement *gstSrc;
  GstElement *gstSink;

  gstSrc = (GstElement *) g_object_ref ( src->getGstreamerElement() );
  g_object_set (gstSrc, "audio", TRUE, "video", TRUE, NULL);
  gstSink = (GstElement *) g_object_ref ( src->getGstreamerElement() );
  g_object_set (gstSink, "audio", TRUE, "video", TRUE, NULL);

  src->connect (sink);

  std::string dot = sink->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  dot = src->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  dot = pipe->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  std::shared_ptr<kurento::GstreamerDotDetails> details (new
      kurento::GstreamerDotDetails (kurento::GstreamerDotDetails::SHOW_STATES) );
  dot = pipe->getGstreamerDot (details);

  BOOST_CHECK (!dot.empty() );
}
<commit_msg>mediaElement: Fix mediaElement tests<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE MediaElement
#include <boost/test/unit_test.hpp>
#include <MediaPipelineImpl.hpp>
#include <MediaElementImpl.hpp>
#include <ElementConnectionData.hpp>
#include <MediaType.hpp>
#include <KurentoException.hpp>
#include <GstreamerDotDetails.hpp>
#include <MediaSet.hpp>
#include <ModuleManager.hpp>

using namespace kurento;

ModuleManager moduleManager;
boost::property_tree::ptree config;

std::atomic<bool> finished;
std::condition_variable cv;
std::mutex mtx;
std::unique_lock<std::mutex> lck (mtx);

static void
init_test ()
{
  gst_init (NULL, NULL);
  moduleManager.loadModulesFromDirectories ("../../src/server");
  finished = false;

  MediaSet::getMediaSet()->signalEmpty.connect ([] () {
    finished = true;
    cv.notify_one();
  });
}

static void
end_test ()
{
  cv.wait_for (lck, std::chrono::seconds (5), [&] () {

    return finished.load();
  });

  if (!finished) {
    BOOST_ERROR ("MediaSet empty signal not raised");
  }

  BOOST_CHECK (MediaSet::getMediaSet ()->empty() );
}

static std::shared_ptr <MediaElementImpl>
createDummyElement (const std::string &name, const std::string &mediaPipelineId)
{
  auto mediaObject = MediaSet::getMediaSet()->ref (new  MediaElementImpl (
                       boost::property_tree::ptree(),
                       MediaSet::getMediaSet()->getMediaObject (mediaPipelineId),
                       name) );
  std::shared_ptr <MediaElementImpl> element = std::dynamic_pointer_cast
      <MediaElementImpl> (mediaObject);
  MediaSet::getMediaSet()->ref ("", mediaObject);

  return element;
}

static void
releaseMediaObject (const std::string &id)
{
  MediaSet::getMediaSet ()->release (id);
}

BOOST_AUTO_TEST_CASE (connection_test)
{
  init_test ();

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);

  std::shared_ptr <MediaType> VIDEO (new MediaType (MediaType::VIDEO) );
  std::shared_ptr <MediaType> AUDIO (new MediaType (MediaType::AUDIO) );

  src->setName ("SOURCE");
  sink->setName ("SINK");

  src->connect (sink);
  auto connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 2);

  for (auto it : connections) {
    BOOST_CHECK (it->getSource()->getId() == src->getId() );
  }

  g_object_set (src->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);
  g_object_set (sink->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);

  connections = src->getSinkConnections ();
  BOOST_CHECK (connections.size() == 2);

  for (auto it : connections) {
    BOOST_CHECK (it->getSource()->getId() == src->getId() );
  }

  connections = sink->getSourceConnections (AUDIO);
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (AUDIO, "");
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (AUDIO, "test");
  BOOST_CHECK (connections.size() == 0);

  connections = sink->getSourceConnections (VIDEO);
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "");
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "test");
  BOOST_CHECK (connections.size() == 0);

  src->disconnect (sink);

  connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 0);

  src->connect (sink, AUDIO);

  connections = sink->getSourceConnections ();
  BOOST_CHECK (connections.size() == 1);

  connections = src->getSinkConnections ();
  BOOST_CHECK (connections.size() == 1);

  connections = sink->getSourceConnections (VIDEO, "");
  BOOST_CHECK (connections.size() == 0);

  releaseMediaObject (src->getId() );
  releaseMediaObject (sink->getId() );
  releaseMediaObject (mediaPipelineId);

  sink.reset();
  src.reset();

  end_test ();
}

BOOST_AUTO_TEST_CASE (release_before_real_connection)
{
  GstElement *srcElement;

  init_test ();

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);

  src->setName ("SOURCE");
  sink->setName ("SINK");

  g_object_set (sink->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);
  srcElement = (GstElement *) g_object_ref (src->getGstreamerElement() );
  g_object_set (srcElement, "audio", TRUE, NULL);

  src->connect (sink);

  src->disconnect (sink);

  g_object_set (srcElement, "audio", TRUE, "video", TRUE, NULL);
  g_object_unref (srcElement);

  releaseMediaObject (src->getId() );
  releaseMediaObject (sink->getId() );
  releaseMediaObject (mediaPipelineId);

  src.reset();
  sink.reset();

  end_test ();
}

BOOST_AUTO_TEST_CASE (loopback)
{
  init_test ();

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> duplex = createDummyElement ("dummyduplex",
      mediaPipelineId);

  duplex->setName ("DUPLEX");

  g_object_set (duplex->getGstreamerElement(), "src-audio", TRUE, "src-video",
                TRUE, "sink-audio", TRUE, "sink-video", TRUE, NULL);

  duplex->connect (duplex);

  releaseMediaObject (duplex->getId() );
  releaseMediaObject (mediaPipelineId);

  duplex.reset();

  end_test ();
}

BOOST_AUTO_TEST_CASE (no_common_pipeline)
{
  init_test ();

  std::string mediaPipelineId1 =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();
  std::string mediaPipelineId2 =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId1);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId2);

  src->setName ("SOURCE");
  sink->setName ("SINK");

  try {
    src->connect (sink);
    BOOST_FAIL ("Previous operation should raise an exception");
  } catch (KurentoException e) {
    BOOST_CHECK (e.getCode () == CONNECT_ERROR);
  }

  releaseMediaObject (sink->getId() );
  releaseMediaObject (src->getId() );
  releaseMediaObject (mediaPipelineId1);
  releaseMediaObject (mediaPipelineId2);

  sink.reset();
  src.reset();

  end_test ();
}

BOOST_AUTO_TEST_CASE (dot_test)
{
  init_test ();

  std::string mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  std::shared_ptr <MediaElementImpl> sink = createDummyElement ("dummysink",
      mediaPipelineId);
  std::shared_ptr <MediaElementImpl> src = createDummyElement ("dummysrc",
      mediaPipelineId);
  std::shared_ptr <MediaPipelineImpl> pipe = std::dynamic_pointer_cast
      <MediaPipelineImpl> (MediaSet::getMediaSet()->getMediaObject (
                             mediaPipelineId) );

  g_object_set (src->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);
  g_object_set (sink->getGstreamerElement(), "audio", TRUE, "video", TRUE, NULL);

  src->connect (sink);

  std::string dot = sink->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  dot = src->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  dot = pipe->getGstreamerDot();

  BOOST_CHECK (!dot.empty() );

  std::shared_ptr<kurento::GstreamerDotDetails> details (new
      kurento::GstreamerDotDetails (kurento::GstreamerDotDetails::SHOW_STATES) );
  dot = pipe->getGstreamerDot (details);

  BOOST_CHECK (!dot.empty() );

  releaseMediaObject (sink->getId() );
  releaseMediaObject (src->getId() );
  releaseMediaObject (mediaPipelineId);

  sink.reset();
  src.reset();
  pipe.reset();

  end_test ();
}
<|endoftext|>


<commit_before>#include "catch/catch.hpp"
#include "json/json.hpp"

#include "Seer.hpp"

#include "Util/PipeSpy.hpp"
#include "Util/TestHelper.hpp"

TEST_CASE("ScopeTimer sends data on to network", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto construction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	});
	auto destruction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 1;
	});
	SECTION("ScopeTimer sends to network")
	{
		Seer::ScopeTimer("test");
		auto json_construction = TestHelper::get_with_timeout<nlohmann::json>(construction_promise);
	}
	auto json_destruction = TestHelper::get_with_timeout<nlohmann::json>(destruction_promise);
}

TEST_CASE("ScopeTimer sends the correct data", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto construction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	});
	auto destruction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 1;
	});
	nlohmann::json json_construction;
	SECTION("ScopeTimer sends to network")
	{
		Seer::ScopeTimer("test");
		json_construction = TestHelper::get_with_timeout<nlohmann::json>(construction_promise);
	}
	auto json_destruction = TestHelper::get_with_timeout<nlohmann::json>(destruction_promise);
	// contrustion
	REQUIRE(json_construction["n"] == "test");
	REQUIRE(json_construction["p"] == 0);

	// destruction
	REQUIRE(json_destruction["n"] == "test");
	REQUIRE(json_destruction["p"] == 1);

	// related fields
	REQUIRE(json_construction["t_id"] == json_destruction["t_id"]);
}

TEST_CASE("ScopeTimer is isolated by threads", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto time_point_promise = [](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	};
	SECTION("when both ScopeTimers have the same name")
	{
		auto thread_1_promise = spy->get_match(time_point_promise);
		auto thread_1 = std::thread([]() { Seer::ScopeTimer("test"); });
		auto thread_1_json = TestHelper::get_with_timeout<nlohmann::json>(thread_1_promise);

		auto thread_2_promise = spy->get_match(time_point_promise);
		auto thread_2 = std::thread([]() { Seer::ScopeTimer("test"); });
		auto thread_2_json = TestHelper::get_with_timeout<nlohmann::json>(thread_2_promise);

		thread_1.join();
		thread_2.join();

		REQUIRE(thread_1_json["t_id"] != thread_2_json["t_id"]);
	}

	SECTION("when both ScopeTimers have different names")
	{
		auto thread_1_promise = spy->get_match(time_point_promise);
		std::thread([]() { Seer::ScopeTimer("test1"); }).join();
		auto thread_1_json = TestHelper::get_with_timeout<nlohmann::json>(thread_1_promise);
		auto thread_2_promise = spy->get_match(time_point_promise);
		std::thread([]() { Seer::ScopeTimer("test2"); }).join();
		auto thread_2_json = TestHelper::get_with_timeout<nlohmann::json>(thread_2_promise);

		REQUIRE(thread_1_json["t_id"] != thread_2_json["t_id"]);
	}
}
<commit_msg>Looks like I was right. or just a happy coincidence.<commit_after>#include "catch/catch.hpp"
#include "json/json.hpp"

#include "Seer.hpp"

#include "Util/PipeSpy.hpp"
#include "Util/TestHelper.hpp"

TEST_CASE("ScopeTimer sends data on to network", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto construction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	});
	auto destruction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 1;
	});
	SECTION("ScopeTimer sends to network")
	{
		Seer::ScopeTimer("test");
		auto json_construction = TestHelper::get_with_timeout<nlohmann::json>(construction_promise);
	}
	auto json_destruction = TestHelper::get_with_timeout<nlohmann::json>(destruction_promise);
}

TEST_CASE("ScopeTimer sends the correct data", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto construction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	});
	auto destruction_promise = spy->get_match([](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 1;
	});
	nlohmann::json json_construction;
	SECTION("ScopeTimer sends to network")
	{
		Seer::ScopeTimer("test");
		json_construction = TestHelper::get_with_timeout<nlohmann::json>(construction_promise);
	}
	auto json_destruction = TestHelper::get_with_timeout<nlohmann::json>(destruction_promise);
	// contrustion
	REQUIRE(json_construction["n"] == "test");
	REQUIRE(json_construction["p"] == 0);

	// destruction
	REQUIRE(json_destruction["n"] == "test");
	REQUIRE(json_destruction["p"] == 1);

	// related fields
	REQUIRE(json_construction["t_id"] == json_destruction["t_id"]);
}

TEST_CASE("ScopeTimer is isolated by threads", "[scope_timer]")
{
	Seer::Sink<PipeSpy> spy_sink;
	auto spy = spy_sink.get_sink();
	auto time_point_promise = [](const nlohmann::json& json) {
		return json["#"] == "tp" && json["p"] == 0;
	};
	SECTION("when both ScopeTimers have the same name")
	{
		auto thread_1_promise = spy->get_match(time_point_promise);
		auto thread_1 = std::thread([]() { Seer::ScopeTimer("test"); });
		auto thread_1_json = TestHelper::get_with_timeout<nlohmann::json>(thread_1_promise);

		auto thread_2_promise = spy->get_match(time_point_promise);
		auto thread_2 = std::thread([]() { Seer::ScopeTimer("test"); });
		auto thread_2_json = TestHelper::get_with_timeout<nlohmann::json>(thread_2_promise);

		thread_1.join();
		thread_2.join();

		REQUIRE(thread_1_json["t_id"] != thread_2_json["t_id"]);
	}

	SECTION("when both ScopeTimers have different names")
	{
		auto thread_1_promise = spy->get_match(time_point_promise);
		auto thread_1 = std::thread([]() { Seer::ScopeTimer("test1"); });
		auto thread_1_json = TestHelper::get_with_timeout<nlohmann::json>(thread_1_promise);

		auto thread_2_promise = spy->get_match(time_point_promise);
		auto thread_2 = std::thread([]() { Seer::ScopeTimer("test2"); });
		auto thread_2_json = TestHelper::get_with_timeout<nlohmann::json>(thread_2_promise);

		thread_1.join();
		thread_2.join();

		REQUIRE(thread_1_json["t_id"] != thread_2_json["t_id"]);
	}
}
<|endoftext|>


<commit_before>#include "Arduino.h"
#include "md5.h"
#include "MD5Builder.h"

#define hex_char_to_byte(c) (((c)>='a'&&(c)<='f')?((c)-87):((c)>='A'&&(c)<='F')?((c)-55):((c)>='0'&&(c)<='9')?((c)-48):0)

void MD5Builder::begin(void){
  memset(_buf, 0x00, 16);
  MD5Init(&_ctx);
}

void MD5Builder::add(uint8_t * data, uint16_t len){
  MD5Update(&_ctx, data, len);
}

void MD5Builder::addHexString(const char * data){
  uint16_t i, len = strlen(data);
  uint8_t * tmp = (uint8_t*)malloc(len/2);
  if(tmp == NULL)
    return;
  for(i=0; i<len; i+=2) tmp[i/2] = (hex_char_to_byte(data[i]) & 0x0F) << 4 | (hex_char_to_byte(data[i+1]) & 0x0F);
  add(tmp, len/2);
  free(tmp);
}

bool MD5Builder::addStream(Stream & stream, const size_t total_len) {
    const int buf_size = 512;
    int bytesleft = total_len;
    uint8_t * buf = (uint8_t*) malloc(buf_size);
    if(buf) {
        while((stream.available() > -1) && (bytesleft > 0)) {

            // get available data size
            int sizeAvailable = stream.available();
            if(sizeAvailable) {
                int readBytes = sizeAvailable;

                // read only the asked bytes
                if(readBytes > bytesleft) {
                    readBytes = bytesleft ;
                }

                // not read more the buffer can handle
                if(readBytes > buf_size) {
                    readBytes = buf_size;
                }

                // read data
                int bytesread = stream.readBytes(buf, readBytes);
                bytesleft -= bytesread;
                if(bytesread > 0) {
                    MD5Update(&_ctx, buf, bytesread);
                }
            }
            // time for network streams
            delay(0);
        }
        // not free null ptr
        free(buf);
        return (bytesleft == 0);
    } else {
        return false;
    }
}

void MD5Builder::calculate(void){
  MD5Final(_buf, &_ctx);
}

void MD5Builder::getBytes(uint8_t * output){
  memcpy(output, _buf, 16);
}

void MD5Builder::getChars(char * output){
  for(uint8_t i = 0; i < 16; i++)
    sprintf(output + (i * 2), "%02x", _buf[i]);
}

String MD5Builder::toString(void){
  char out[32];
  getChars(out);
  return String(out);
}<commit_msg>Fix buffer overflow and formatting<commit_after>#include "Arduino.h"
#include "md5.h"
#include "MD5Builder.h"

#define hex_char_to_byte(c) (((c)>='a'&&(c)<='f')?((c)-87):((c)>='A'&&(c)<='F')?((c)-55):((c)>='0'&&(c)<='9')?((c)-48):0)

void MD5Builder::begin(void){
  memset(_buf, 0x00, 16);
  MD5Init(&_ctx);
}

void MD5Builder::add(uint8_t * data, uint16_t len){
  MD5Update(&_ctx, data, len);
}

void MD5Builder::addHexString(const char * data){
  uint16_t i, len = strlen(data);
  uint8_t * tmp = (uint8_t*)malloc(len/2);
  if(tmp == NULL)
    return;
  for(i=0; i<len; i+=2) tmp[i/2] = (hex_char_to_byte(data[i]) & 0x0F) << 4 | (hex_char_to_byte(data[i+1]) & 0x0F);
  add(tmp, len/2);
  free(tmp);
}

bool MD5Builder::addStream(Stream & stream, const size_t total_len) {
  const int buf_size = 512;
  int bytesleft = total_len;
  uint8_t * buf = (uint8_t*) malloc(buf_size);
  if(buf) {
    while((stream.available() > -1) && (bytesleft > 0)) {
      // get available data size
      int sizeAvailable = stream.available();
      if(sizeAvailable) {
        int readBytes = sizeAvailable;

        // read only the asked bytes
        if(readBytes > bytesleft) {
          readBytes = bytesleft ;
        }

        // not read more the buffer can handle
        if(readBytes > buf_size) {
          readBytes = buf_size;
        }

        // read data
        int bytesread = stream.readBytes(buf, readBytes);
        bytesleft -= bytesread;
        if(bytesread > 0) {
          MD5Update(&_ctx, buf, bytesread);
        }
      }
      // time for network streams
      delay(0);
    }
    // guaranteed not null
    free(buf);
    return (bytesleft == 0);
  } else {
    return false;
  }
}

void MD5Builder::calculate(void){
  MD5Final(_buf, &_ctx);
}

void MD5Builder::getBytes(uint8_t * output){
  memcpy(output, _buf, 16);
}

void MD5Builder::getChars(char * output){
  for(uint8_t i = 0; i < 16; i++)
    sprintf(output + (i * 2), "%02x", _buf[i]);
}

String MD5Builder::toString(void){
  char out[33];
  getChars(out);
  return String(out);
}<|endoftext|>


<commit_before>// Conventions:
//  O is the stack pointer (post-decrement)
//  B is the (so far only) return register
//  C is the (so far only) argument register
//  N is the relative-jump temp register

#ifndef ARGUMENT
#define ARGUMENT 10
#endif

#include "common.th"

_start:
    prologue            // sets up base/stack pointer
    c <- ARGUMENT       // argument
    call(fib)
    illegal

fib:
    push(d)
    d <- 1
    d <- d < c          // zero or one ?
    jnzrel(d,_recurse)  // not-zero is true (c >= 2)
    b <- c
    pop(d)
    ret

_recurse:
    push(c)
    c <- c - 1
    call(fib)
    pop(c)
    push(b)
    c <- c - 2
    call(fib)
    d <- b
    pop(b)
    b <- d + b

    pop(d)
    ret

<commit_msg>Simplify fib by one instruction<commit_after>// Conventions:
//  O is the stack pointer (post-decrement)
//  B is the (so far only) return register
//  C is the (so far only) argument register
//  N is the relative-jump temp register

#ifndef ARGUMENT
#define ARGUMENT 10
#endif

#include "common.th"

_start:
    prologue            // sets up base/stack pointer
    c <- ARGUMENT       // argument
    call(fib)
    illegal

fib:
    push(d)
    d <- c > 1          // not zero or one ?
    jnzrel(d,_recurse)  // not-zero is true (c >= 2)
    b <- c
    pop(d)
    ret

_recurse:
    push(c)
    c <- c - 1
    call(fib)
    pop(c)
    push(b)
    c <- c - 2
    call(fib)
    d <- b
    pop(b)
    b <- d + b

    pop(d)
    ret

<|endoftext|>