<commit_before>/** \file   SimpleXmlParser.cc
 *  \brief  A non-validating XML parser class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  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 "SimpleXmlParser.h"
#include <stdexcept>
#include "Compiler.h"
#include "StringUtil.h"
#include "TextUtil.h"

namespace {

bool DecodeEnity(const std::string &entity_string, std::string * const decoded_char) {
    if (unlikely(entity_string.empty()))
        return false;

    if (unlikely(entity_string[0] == '#')) {
        if (entity_string.length() < 2)
            return false;

        unsigned code_point;
        if (entity_string[1] == 'x') {
            if (entity_string.length() < 3 or entity_string.length() > 6)
                return false;
            if (not StringUtil::ToUnsigned(entity_string.substr(2), &code_point, 16))
                return false;
        } else {
            if (entity_string.length() < 2 or entity_string.length() > 6)
                return false;
            if (not StringUtil::ToUnsigned(entity_string.substr(1), &code_point))
                return false;
        }

        if (not TextUtil::WCharToUTF8String(std::wstring(1, static_cast<wchar_t>(code_point)), decoded_char))
            return false;
    } else if (entity_string == "quot")
        *decoded_char = "\"";
    else if (entity_string =="amp")
        *decoded_char = "&";
    else if (entity_string =="apos")
        *decoded_char = "'";
    else if (entity_string =="lt")
        *decoded_char = "<";
    else if (entity_string =="gt")
        *decoded_char = ">";
    else
        return false;

    return true;
}

inline bool DecodeEntities(const std::string &raw_string, std::string * const decoded_string) {
    bool in_entity(false);
    std::string entity;
    for (const auto ch : raw_string) {
        if (unlikely(in_entity)) {
            if (ch == ';') {
                std::string decoded_char;
                if (not DecodeEnity(entity, &decoded_char))
                    return false;
                *decoded_string += decoded_char;
                in_entity = false;
            } else
                entity += ch;
        } else if (unlikely(ch == '&')) {
            in_entity = true;
            entity.clear();
        } else
            *decoded_string += ch;
    }

    return not in_entity;
}

} // unnamed namespace

bool SimpleXmlParser::getNext(Type * const type, std::map<std::string, std::string> * const attrib_map,
                              std::string * const data)
{
    if (unlikely(last_type_ == ERROR))
        throw std::runtime_error("in SimpleXmlParser::getNext: previous call already indicated an error!");

    attrib_map->clear();
    data->clear();

    if (last_element_was_empty_) {
        last_type_ = *type = CLOSING_TAG;
        data->swap(last_tag_name_);
        last_element_was_empty_ = false;
        last_type_ = CLOSING_TAG;
        return true;
    }

    int ch;
    if (last_type_ == OPENING_TAG) {
        last_type_ = *type = CHARACTERS;

        std::string raw_string;
        while ((ch = input_->get()) != '<') {
            if (unlikely(ch == EOF)) {
                last_error_message_ = "Unexpected EOF while looking for the start of a closing tag!";
                return false;
            }
            if (unlikely(ch == '\n'))
                ++line_no_;
            raw_string += static_cast<char>(ch);
        }
        input_->putback(ch); // Putting back the '<'.

        if (not DecodeEntities(raw_string, data)) {
            last_type_ = *type = ERROR;
            last_error_message_ = "Invalid entity in character data ending on line " + std::to_string(line_no_) + "!";
            return false;
        }
    } else { // end-of-document or opening or closing tag
        skipWhiteSpace();

        ch = input_->get();
        if (unlikely(ch == EOF)) {
            last_type_ = *type = END_OF_DOCUMENT;
            return true;
        }

        if (ch != '<') {
            last_type_ = *type = ERROR;
            last_error_message_ = "Expected '<' on line " + std::to_string(line_no_) + ", found '"
                                  + std::string(1, static_cast<char>(ch)) + "' instead!";
            return false;
        }

        // If we're at the beginning, we may have an XML prolog:
        if (unlikely(last_type_ == UNINITIALISED) and input_->peek() == '?') {
            if (not parseProlog()) {
                last_type_ = *type = ERROR;
                return false;
            }
            last_type_ = *type = START_OF_DOCUMENT;
            return true;
        }

        ch = input_->get();
        if (ch == '/') { // A closing tag.
            if (unlikely(not parseClosingTag(data))) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing a closing tag on line " + std::to_string(line_no_) + "!";
                return false;
            }

            last_type_ = *type = CLOSING_TAG;
        } else { // An opening tag.
            input_->putback(ch);

            std::string error_message;
            if (unlikely(not parseOpeningTag(data, attrib_map, &error_message))) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing an opening tag on line " + std::to_string(line_no_) + "! ("
                                      + error_message + ")";
                return false;
            }

            ch = input_->get();
            if (ch == '/') {
                last_element_was_empty_ = true;
                last_tag_name_ = *data;
                ch = input_->get();
            }

            if (unlikely(ch != '>')) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing a opening tag on line " + std::to_string(line_no_) + "! ("
                                      "Closing angle bracket not found.)";
                return false;
            }

            last_type_ = *type = OPENING_TAG;
        }
    }

    return true;
}

void SimpleXmlParser::skipWhiteSpace() {
    for (;;) {
        const int ch(input_->get());
        if (unlikely(ch == EOF))
            return;
        if (ch != ' ' and ch != '\t' and ch != '\n' and ch != '\r') {
            input_->putback(ch);
            return;
        } else if (ch == '\n')
            ++line_no_;
    }
}

bool SimpleXmlParser::extractName(std::string * const name) {
    name->clear();

    int ch(input_->get());
    if (unlikely(ch == EOF or (not StringUtil::IsAsciiLetter(ch) and ch != '_' and ch != ':'))) {
        input_->putback(ch);
        return false;
    }

    *name += static_cast<char>(ch);
    for (;;) {
        ch = input_->get();
        if (unlikely(ch == EOF))
            return false;
        if (not (StringUtil::IsAsciiLetter(ch) or StringUtil::IsDigit(ch) or ch == '_' or ch == ':' or ch == '.')) {
            input_->putback(ch);
            return true;
        }
        *name += static_cast<char>(ch);
    }
}

bool SimpleXmlParser::extractQuotedString(const int closing_quote, std::string * const s) {
    s->clear();

    for (;;) {
        const int ch(input_->get());
        if (unlikely(ch == EOF))
            return false;
        if (unlikely(ch == closing_quote))
            return true;
        *s += static_cast<char>(ch);
    }
}

bool SimpleXmlParser::parseProlog() {
    if (input_->peek() != '?')
        return true;
    input_->get();

    std::string prolog_tag_name;
    std::map<std::string, std::string> prolog_attrib_map;
    std::string error_message;
    if (not parseOpeningTag(&prolog_tag_name, &prolog_attrib_map, &error_message)) {
        last_error_message_ = "Error in prolog! (" + error_message + ")";
        return false;
    }

    int ch(input_->get());
    if (unlikely(ch != '?')) {
        last_error_message_ = "Error in prolog, expected '?' but found '" + std::string(1, static_cast<char>(ch)) + "'!";
        return false;
    }

    ch = input_->get();
    if (unlikely(ch != '>')) {
        last_error_message_ = "Error in prolog, closing angle bracket not found!";
        return false;
    }

    const auto encoding(prolog_attrib_map.find("encoding"));
    if (encoding != prolog_attrib_map.cend()) {
        if (::strcasecmp(encoding->second.c_str(), "utf-8") != 0) {
            last_error_message_ = "Error in prolog: We only support the UTF-8 encoding!";
            return false;
        }
    }

    return true;
}

bool SimpleXmlParser::parseOpeningTag(std::string * const tag_name,
                                      std::map<std::string, std::string> * const attrib_map,
                                      std::string * const error_message)
{
    attrib_map->clear();
    error_message->clear();

    if (unlikely(not extractName(tag_name))) {
        *error_message = "Failed to extract the tag name.";
        return false;
    }
    skipWhiteSpace();

    std::string attrib_name;
    while (extractName(&attrib_name)) {
        if (unlikely(attrib_map->find(attrib_name) != attrib_map->cend())) { // Duplicate attribute name?
            *error_message = "Found a duplicate tag name.";
            return false;
        }

        skipWhiteSpace();
        const int ch(input_->get());
        if (unlikely(ch != '=')) {
            *error_message = "Could not find an equal sign as part of an attribute.";
            return false;
        }

        skipWhiteSpace();
        const int quote(input_->get());
        if (unlikely(quote != '"' and quote != '\'')) {
            *error_message = "Found neither a single- nor a double-quote starting an attribute value.";
            return false;
        }
        std::string attrib_value;
        if (unlikely(not extractQuotedString(quote, &attrib_value))) {
            *error_message = "Failed to extract the attribute value.";
            return false;
        }

        (*attrib_map)[attrib_name] = attrib_value;

        skipWhiteSpace();
    }

    return true;
}

bool SimpleXmlParser::parseClosingTag(std::string * const tag_name) {
    tag_name->clear();

    if (not extractName(tag_name))
        return false;

    skipWhiteSpace();
    return input_->get() == '>';
}

std::string SimpleXmlParser::TypeToString(const Type type) {
    switch (type) {
    case UNINITIALISED:     return "UNINITIALISED";
    case START_OF_DOCUMENT: return "START_OF_DOCUMENT";
    case END_OF_DOCUMENT:   return "END_OF_DOCUMENT";
    case ERROR:             return "ERROR";
    case OPENING_TAG:       return "OPENING_TAG";
    case CLOSING_TAG:       return "CLOSING_TAG";
    case CHARACTERS:        return "CHARACTERS";
    }

    __builtin_unreachable();
}
<commit_msg>Further small speed improvements.<commit_after>/** \file   SimpleXmlParser.cc
 *  \brief  A non-validating XML parser class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  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 "SimpleXmlParser.h"
#include <stdexcept>
#include "Compiler.h"
#include "StringUtil.h"
#include "TextUtil.h"

namespace {

bool DecodeEnity(const std::string &entity_string, std::string * const decoded_char) {
    if (unlikely(entity_string.empty()))
        return false;

    if (unlikely(entity_string[0] == '#')) {
        if (entity_string.length() < 2)
            return false;

        unsigned code_point;
        if (entity_string[1] == 'x') {
            if (entity_string.length() < 3 or entity_string.length() > 6)
                return false;
            if (not StringUtil::ToUnsigned(entity_string.substr(2), &code_point, 16))
                return false;
        } else {
            if (entity_string.length() < 2 or entity_string.length() > 6)
                return false;
            if (not StringUtil::ToUnsigned(entity_string.substr(1), &code_point))
                return false;
        }

        if (not TextUtil::WCharToUTF8String(std::wstring(1, static_cast<wchar_t>(code_point)), decoded_char))
            return false;
    } else if (entity_string == "quot")
        *decoded_char = "\"";
    else if (entity_string =="amp")
        *decoded_char = "&";
    else if (entity_string =="apos")
        *decoded_char = "'";
    else if (entity_string =="lt")
        *decoded_char = "<";
    else if (entity_string =="gt")
        *decoded_char = ">";
    else
        return false;

    return true;
}

inline bool DecodeEntities(const std::string &raw_string, std::string * const decoded_string) {
    bool in_entity(false);
    std::string entity;
    for (const auto ch : raw_string) {
        if (unlikely(in_entity)) {
            if (ch == ';') {
                std::string decoded_char;
                if (not DecodeEnity(entity, &decoded_char))
                    return false;
                *decoded_string += decoded_char;
                in_entity = false;
            } else
                entity += ch;
        } else if (unlikely(ch == '&')) {
            in_entity = true;
            entity.clear();
        } else
            *decoded_string += ch;
    }

    return not in_entity;
}

} // unnamed namespace

inline void SimpleXmlParser::skipWhiteSpace() {
    for (;;) {
        const int ch(input_->get());
        if (unlikely(ch == EOF))
            return;
        if (ch != ' ' and ch != '\t' and ch != '\n' and ch != '\r') {
            input_->putback(ch);
            return;
        } else if (ch == '\n')
            ++line_no_;
    }
}

inline bool SimpleXmlParser::extractName(std::string * const name) {
    name->clear();

    int ch(input_->get());
    if (unlikely(ch == EOF or (not StringUtil::IsAsciiLetter(ch) and ch != '_' and ch != ':'))) {
        input_->putback(ch);
        return false;
    }

    *name += static_cast<char>(ch);
    for (;;) {
        ch = input_->get();
        if (unlikely(ch == EOF))
            return false;
        if (not (StringUtil::IsAsciiLetter(ch) or StringUtil::IsDigit(ch) or ch == '_' or ch == ':' or ch == '.')) {
            input_->putback(ch);
            return true;
        }
        *name += static_cast<char>(ch);
    }
}

inline bool SimpleXmlParser::extractQuotedString(const int closing_quote, std::string * const s) {
    s->clear();

    for (;;) {
        const int ch(input_->get());
        if (unlikely(ch == EOF))
            return false;
        if (unlikely(ch == closing_quote))
            return true;
        *s += static_cast<char>(ch);
    }
}

bool SimpleXmlParser::getNext(Type * const type, std::map<std::string, std::string> * const attrib_map,
                              std::string * const data)
{
    if (unlikely(last_type_ == ERROR))
        throw std::runtime_error("in SimpleXmlParser::getNext: previous call already indicated an error!");

    attrib_map->clear();
    data->clear();

    if (last_element_was_empty_) {
        last_type_ = *type = CLOSING_TAG;
        data->swap(last_tag_name_);
        last_element_was_empty_ = false;
        last_type_ = CLOSING_TAG;
        return true;
    }

    int ch;
    if (last_type_ == OPENING_TAG) {
        last_type_ = *type = CHARACTERS;

        std::string raw_string;
        while ((ch = input_->get()) != '<') {
            if (unlikely(ch == EOF)) {
                last_error_message_ = "Unexpected EOF while looking for the start of a closing tag!";
                return false;
            }
            if (unlikely(ch == '\n'))
                ++line_no_;
            raw_string += static_cast<char>(ch);
        }
        input_->putback(ch); // Putting back the '<'.

        if (not DecodeEntities(raw_string, data)) {
            last_type_ = *type = ERROR;
            last_error_message_ = "Invalid entity in character data ending on line " + std::to_string(line_no_) + "!";
            return false;
        }
    } else { // end-of-document or opening or closing tag
        skipWhiteSpace();

        ch = input_->get();
        if (unlikely(ch == EOF)) {
            last_type_ = *type = END_OF_DOCUMENT;
            return true;
        }

        if (ch != '<') {
            last_type_ = *type = ERROR;
            last_error_message_ = "Expected '<' on line " + std::to_string(line_no_) + ", found '"
                                  + std::string(1, static_cast<char>(ch)) + "' instead!";
            return false;
        }

        // If we're at the beginning, we may have an XML prolog:
        if (unlikely(last_type_ == UNINITIALISED) and input_->peek() == '?') {
            if (not parseProlog()) {
                last_type_ = *type = ERROR;
                return false;
            }
            last_type_ = *type = START_OF_DOCUMENT;
            return true;
        }

        ch = input_->get();
        if (ch == '/') { // A closing tag.
            if (unlikely(not parseClosingTag(data))) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing a closing tag on line " + std::to_string(line_no_) + "!";
                return false;
            }

            last_type_ = *type = CLOSING_TAG;
        } else { // An opening tag.
            input_->putback(ch);

            std::string error_message;
            if (unlikely(not parseOpeningTag(data, attrib_map, &error_message))) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing an opening tag on line " + std::to_string(line_no_) + "! ("
                                      + error_message + ")";
                return false;
            }

            ch = input_->get();
            if (ch == '/') {
                last_element_was_empty_ = true;
                last_tag_name_ = *data;
                ch = input_->get();
            }

            if (unlikely(ch != '>')) {
                last_type_ = *type = ERROR;
                last_error_message_ = "Error while parsing a opening tag on line " + std::to_string(line_no_) + "! ("
                                      "Closing angle bracket not found.)";
                return false;
            }

            last_type_ = *type = OPENING_TAG;
        }
    }

    return true;
}

bool SimpleXmlParser::parseProlog() {
    if (input_->peek() != '?')
        return true;
    input_->get();

    std::string prolog_tag_name;
    std::map<std::string, std::string> prolog_attrib_map;
    std::string error_message;
    if (not parseOpeningTag(&prolog_tag_name, &prolog_attrib_map, &error_message)) {
        last_error_message_ = "Error in prolog! (" + error_message + ")";
        return false;
    }

    int ch(input_->get());
    if (unlikely(ch != '?')) {
        last_error_message_ = "Error in prolog, expected '?' but found '" + std::string(1, static_cast<char>(ch)) + "'!";
        return false;
    }

    ch = input_->get();
    if (unlikely(ch != '>')) {
        last_error_message_ = "Error in prolog, closing angle bracket not found!";
        return false;
    }

    const auto encoding(prolog_attrib_map.find("encoding"));
    if (encoding != prolog_attrib_map.cend()) {
        if (::strcasecmp(encoding->second.c_str(), "utf-8") != 0) {
            last_error_message_ = "Error in prolog: We only support the UTF-8 encoding!";
            return false;
        }
    }

    return true;
}

bool SimpleXmlParser::parseOpeningTag(std::string * const tag_name,
                                      std::map<std::string, std::string> * const attrib_map,
                                      std::string * const error_message)
{
    attrib_map->clear();
    error_message->clear();

    if (unlikely(not extractName(tag_name))) {
        *error_message = "Failed to extract the tag name.";
        return false;
    }
    skipWhiteSpace();

    std::string attrib_name;
    while (extractName(&attrib_name)) {
        if (unlikely(attrib_map->find(attrib_name) != attrib_map->cend())) { // Duplicate attribute name?
            *error_message = "Found a duplicate tag name.";
            return false;
        }

        skipWhiteSpace();
        const int ch(input_->get());
        if (unlikely(ch != '=')) {
            *error_message = "Could not find an equal sign as part of an attribute.";
            return false;
        }

        skipWhiteSpace();
        const int quote(input_->get());
        if (unlikely(quote != '"' and quote != '\'')) {
            *error_message = "Found neither a single- nor a double-quote starting an attribute value.";
            return false;
        }
        std::string attrib_value;
        if (unlikely(not extractQuotedString(quote, &attrib_value))) {
            *error_message = "Failed to extract the attribute value.";
            return false;
        }

        (*attrib_map)[attrib_name] = attrib_value;

        skipWhiteSpace();
    }

    return true;
}

bool SimpleXmlParser::parseClosingTag(std::string * const tag_name) {
    tag_name->clear();

    if (not extractName(tag_name))
        return false;

    skipWhiteSpace();
    return input_->get() == '>';
}

std::string SimpleXmlParser::TypeToString(const Type type) {
    switch (type) {
    case UNINITIALISED:     return "UNINITIALISED";
    case START_OF_DOCUMENT: return "START_OF_DOCUMENT";
    case END_OF_DOCUMENT:   return "END_OF_DOCUMENT";
    case ERROR:             return "ERROR";
    case OPENING_TAG:       return "OPENING_TAG";
    case CLOSING_TAG:       return "CLOSING_TAG";
    case CHARACTERS:        return "CHARACTERS";
    }

    __builtin_unreachable();
}
<|endoftext|>


<commit_before>// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: clang-tidy %t.cpp -fix -checks=llvm.* --
// RUN: FileCheck -input-file=%t.cpp %s

namespace i {
}
// CHECK: } // namespace i

class A { A(int i); }; // Not fixing this, because the check is in google-.
// CHECK: class A { A(int i); };
<commit_msg>Use more specific checks filter in the test.<commit_after>// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: clang-tidy %t.cpp -fix -checks=^llvm-.* --
// RUN: FileCheck -input-file=%t.cpp %s

namespace i {
}
// CHECK: } // namespace i

class A { A(int i); }; // Not fixing this, because the check is in google-.
// CHECK: class A { A(int i); };
<|endoftext|>


<commit_before>/** \file   TranslationUtil.cc
 *  \brief  Implementation of the DbConnection class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "TranslationUtil.h"
#include <map>
#include "Compiler.h"
#include "File.h"
#include "StringUtil.h"
#include "util.h"

namespace TranslationUtil {

std::string GetId(DbConnection * const connection, const std::string &german_text) {
    const std::string SELECT_EXISTING("SELECT id FROM translations WHERE text=\"" + connection->escapeString(german_text)
                                      + "\" AND language_code=\"deu\"");
    if (not connection->query(SELECT_EXISTING))
        LOG_ERROR("SELECT failed: " + SELECT_EXISTING + " (" + connection->getLastErrorMessage() + ")");
    DbResultSet id_result_set(connection->getLastResultSet());
    std::string id;
    if (not id_result_set.empty())
        return id_result_set.getNextRow()["id"];
    else { // We don't have any entries for this German term yet.
        const std::string SELECT_MAX_ID("SELECT MAX(id) FROM translations");
        if (not connection->query(SELECT_MAX_ID))
            logger->error("in TranslationUtil::GetId: SELECT failed: " + SELECT_MAX_ID + " (" + connection->getLastErrorMessage() + ")");
        DbResultSet max_id_result_set(connection->getLastResultSet());
        if (max_id_result_set.empty())
            return "1";

        const std::string max_id(max_id_result_set.getNextRow()["MAX(id)"]); // Apparently SQL NULL can be  returned
                                                                             // which leads to an empty string here.
        return std::to_string(max_id.empty() ? 1 : StringUtil::ToUnsigned(max_id) + 1);
    }
}

const std::map<std::string, std::string> international_2letter_code_to_german_3or4letter_code{
    { "af", "afr" },
    { "an", "arg" },
    { "ar", "ara" },
    { "br", "bre" },
    { "ca", "cat" },
    { "cs", "cze" },
    { "cy", "cym" },
    { "da", "dan" },
    { "de", "deu" },
    { "el", "gre" },
    { "en", "eng" },
    { "es", "spa" },
    { "et", "est" },
    { "eu", "eus" },
    { "fi", "fin" },
    { "fr", "fra" },
    { "ga", "gaa" },
    { "gl", "glg" },
    { "ht", "hat" },
    { "hr", "hrv" },
    { "hu", "hun" },
    { "id", "ind" },
    { "is", "ice" },
    { "it", "ita" },
    { "lv", "lav" },
    { "lt", "lit" },
    { "ms", "msa" },
    { "mt", "mlt" },
    { "nl", "nld" },
    { "no", "nor" },
    { "oc", "oci" },
    { "pl", "pol" },
    { "pt", "por" },
    { "ro", "rum" },
    { "ru", "rus" },
    { "sk", "slo" },
    { "sl", "slv" },
    { "so", "som" },
    { "sr", "srp" },
    { "sv", "swe" },
    { "sw", "swa" },
    { "tl", "tgl" },
    { "tr", "tur" },
    { "vi", "vie" },
};

std::string MapInternational2LetterCodeToGerman3Or4LetterCode(const std::string &international_2letter_code) {
    const auto _2letter_and_3letter_codes(international_2letter_code_to_german_3or4letter_code.find(international_2letter_code));
    if (unlikely(_2letter_and_3letter_codes == international_2letter_code_to_german_3or4letter_code.cend()))
        logger->error(
            "in TranslationUtil::MapInternational2LetterCodeToGerman3LetterCode: unknown international "
            "2-letter code \""
            + international_2letter_code + "\"!");
    return _2letter_and_3letter_codes->second;
}

bool IsValidInternational2LetterCode(const std::string &international_2letter_code_candidate) {
    if (international_2letter_code_candidate.length() != 2)
        return false;

    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.first == international_2letter_code_candidate)
            return true;
    }

    return false;
}

std::string MapGerman3Or4LetterCodeToInternational2LetterCode(const std::string &german_3or4letter_code) {
    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.second == german_3or4letter_code)
            return _2letter_and_3letter_codes.first;
    }
    LOG_ERROR("unknown German 3-letter code \"" + german_3or4letter_code + "\"!");
}

bool IsValidGerman3Or4LetterCode(const std::string &german_3or4letter_code_candidate) {
    if (german_3or4letter_code_candidate.length() != 3 and german_3or4letter_code_candidate.length() != 4)
        return false;

    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.second == german_3or4letter_code_candidate)
            return true;
    }

    return false;
}

void ReadIniFile(const std::string &ini_filename,
                 std::unordered_map<std::string, std::pair<unsigned, std::string>> * const token_to_line_no_and_other_map) {
    File input(ini_filename, "r");
    if (not input)
        throw std::runtime_error("can't open \"" + ini_filename + "\" for reading!");

    unsigned line_no(0);
    while (not input.eof()) {
        ++line_no;
        std::string line;
        if (input.getline(&line) == 0 or line.empty())
            continue;

        const std::string::size_type first_equal_pos(line.find('='));
        if (unlikely(first_equal_pos == std::string::npos))
            throw std::runtime_error("missing equal-sign in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");

        const std::string key(StringUtil::Trim(line.substr(0, first_equal_pos)));
        if (unlikely(key.empty()))
            throw std::runtime_error("missing token or English key in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");

        const std::string rest(StringUtil::Trim(StringUtil::Trim(line.substr(first_equal_pos + 1)), '"'));
        if (unlikely(rest.empty()))
            throw std::runtime_error("missing translation in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");
        (*token_to_line_no_and_other_map)[key] = std::make_pair(line_no, rest);
    }
}

static std::map<std::string, std::string> german_to_3or4letter_english_codes{
    { "afr", "afr" },
    { "ara", "ara" },
    { "arg", "arg" },
    { "ast", "ast" },
    { "bre", "bre" },
    { "cat", "cat" },
    { "cym", "wel" },
    { "cze", "ces" },
    { "dan", "dan" },
    { "deu", "ger" },
    { "eng", "eng" },
    { "est", "est" },
    { "eus", "baq" },
    { "fin", "fin" },
    { "fra", "fre" },
    { "gaa", "gaa" },
    { "glg", "glg" },
    { "gre", "gre" },
    { "hat", "hat" },
    { "hrv", "hrv" },
    { "hun", "hun" },
    { "ice", "isl" },
    { "ind", "ind" },
    { "ita", "ita" },
    { "lav", "lav" },
    { "lit", "lit" },
    { "mlt", "mlt" },
    { "msa", "may" },
    { "nld", "dut" },
    { "nor", "nor" },
    { "oci", "oci" },
    { "pol", "pol" },
    { "por", "por" },
    { "rum", "ron" },
    { "rus", "rus" },
    { "slo", "slk" },
    { "slv", "slv" },
    { "som", "som" },
    { "spa", "spa" },
    { "srp", "srp" },
    { "swa", "swa" },
    { "swe", "swe" },
    { "tgl", "tgl" },
    { "tur", "tur" },
    { "vie", "vie" },
    { "hans", "hans" },
    { "hant", "hant" }
};

std::string MapGermanLanguageCodesToFake3LetterEnglishLanguagesCodes(const std::string &german_code) {
    const auto ger_and_eng_code(german_to_3or4letter_english_codes.find(german_code));
    if (ger_and_eng_code == german_to_3or4letter_english_codes.cend())
        return "???";
    return ger_and_eng_code->second;
}

std::string MapFake3LetterEnglishLanguagesCodesToGermanLanguageCodes(const std::string &english_3or4letter_code) {
    for (const auto &ger_and_eng_code : german_to_3or4letter_english_codes) {
        if (ger_and_eng_code.second == english_3or4letter_code)
            return ger_and_eng_code.first;
    }

    return "???";
}

bool IsValidFake3Or4LetterEnglishLanguagesCode(const std::string &english_3or4letter_code_candidate) {
    if (english_3or4letter_code_candidate.length() != 3 and english_3or4letter_code_candidate.length() != 4)
        return false;

    for (const auto &german_and_english_codes : german_to_3or4letter_english_codes) {
        if (german_and_english_codes.second == english_3or4letter_code_candidate)
            return true;
    }
    return false;
}

} // namespace TranslationUtil
<commit_msg>Add new language<commit_after>/** \file   TranslationUtil.cc
 *  \brief  Implementation of the DbConnection class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "TranslationUtil.h"
#include <map>
#include "Compiler.h"
#include "File.h"
#include "StringUtil.h"
#include "util.h"

namespace TranslationUtil {

std::string GetId(DbConnection * const connection, const std::string &german_text) {
    const std::string SELECT_EXISTING("SELECT id FROM translations WHERE text=\"" + connection->escapeString(german_text)
                                      + "\" AND language_code=\"deu\"");
    if (not connection->query(SELECT_EXISTING))
        LOG_ERROR("SELECT failed: " + SELECT_EXISTING + " (" + connection->getLastErrorMessage() + ")");
    DbResultSet id_result_set(connection->getLastResultSet());
    std::string id;
    if (not id_result_set.empty())
        return id_result_set.getNextRow()["id"];
    else { // We don't have any entries for this German term yet.
        const std::string SELECT_MAX_ID("SELECT MAX(id) FROM translations");
        if (not connection->query(SELECT_MAX_ID))
            logger->error("in TranslationUtil::GetId: SELECT failed: " + SELECT_MAX_ID + " (" + connection->getLastErrorMessage() + ")");
        DbResultSet max_id_result_set(connection->getLastResultSet());
        if (max_id_result_set.empty())
            return "1";

        const std::string max_id(max_id_result_set.getNextRow()["MAX(id)"]); // Apparently SQL NULL can be  returned
                                                                             // which leads to an empty string here.
        return std::to_string(max_id.empty() ? 1 : StringUtil::ToUnsigned(max_id) + 1);
    }
}

const std::map<std::string, std::string> international_2letter_code_to_german_3or4letter_code{
    { "af", "afr" },
    { "an", "arg" },
    { "ar", "ara" },
    { "br", "bre" },
    { "ca", "cat" },
    { "cs", "cze" },
    { "cy", "cym" },
    { "da", "dan" },
    { "de", "deu" },
    { "el", "gre" },
    { "en", "eng" },
    { "es", "spa" },
    { "et", "est" },
    { "eu", "eus" },
    { "fi", "fin" },
    { "fr", "fra" },
    { "ga", "gaa" },
    { "gl", "glg" },
    { "ht", "hat" },
    { "hr", "hrv" },
    { "hu", "hun" },
    { "id", "ind" },
    { "is", "ice" },
    { "it", "ita" },
    { "la", "lat" },
    { "lv", "lav" },
    { "lt", "lit" },
    { "ms", "msa" },
    { "mt", "mlt" },
    { "nl", "nld" },
    { "no", "nor" },
    { "oc", "oci" },
    { "pl", "pol" },
    { "pt", "por" },
    { "ro", "rum" },
    { "ru", "rus" },
    { "sk", "slo" },
    { "sl", "slv" },
    { "so", "som" },
    { "sr", "srp" },
    { "sv", "swe" },
    { "sw", "swa" },
    { "tl", "tgl" },
    { "tr", "tur" },
    { "vi", "vie" },
};

std::string MapInternational2LetterCodeToGerman3Or4LetterCode(const std::string &international_2letter_code) {
    const auto _2letter_and_3letter_codes(international_2letter_code_to_german_3or4letter_code.find(international_2letter_code));
    if (unlikely(_2letter_and_3letter_codes == international_2letter_code_to_german_3or4letter_code.cend()))
        logger->error(
            "in TranslationUtil::MapInternational2LetterCodeToGerman3LetterCode: unknown international "
            "2-letter code \""
            + international_2letter_code + "\"!");
    return _2letter_and_3letter_codes->second;
}

bool IsValidInternational2LetterCode(const std::string &international_2letter_code_candidate) {
    if (international_2letter_code_candidate.length() != 2)
        return false;

    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.first == international_2letter_code_candidate)
            return true;
    }

    return false;
}

std::string MapGerman3Or4LetterCodeToInternational2LetterCode(const std::string &german_3or4letter_code) {
    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.second == german_3or4letter_code)
            return _2letter_and_3letter_codes.first;
    }
    LOG_ERROR("unknown German 3-letter code \"" + german_3or4letter_code + "\"!");
}

bool IsValidGerman3Or4LetterCode(const std::string &german_3or4letter_code_candidate) {
    if (german_3or4letter_code_candidate.length() != 3 and german_3or4letter_code_candidate.length() != 4)
        return false;

    for (const auto &_2letter_and_3letter_codes : international_2letter_code_to_german_3or4letter_code) {
        if (_2letter_and_3letter_codes.second == german_3or4letter_code_candidate)
            return true;
    }

    return false;
}

void ReadIniFile(const std::string &ini_filename,
                 std::unordered_map<std::string, std::pair<unsigned, std::string>> * const token_to_line_no_and_other_map) {
    File input(ini_filename, "r");
    if (not input)
        throw std::runtime_error("can't open \"" + ini_filename + "\" for reading!");

    unsigned line_no(0);
    while (not input.eof()) {
        ++line_no;
        std::string line;
        if (input.getline(&line) == 0 or line.empty())
            continue;

        const std::string::size_type first_equal_pos(line.find('='));
        if (unlikely(first_equal_pos == std::string::npos))
            throw std::runtime_error("missing equal-sign in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");

        const std::string key(StringUtil::Trim(line.substr(0, first_equal_pos)));
        if (unlikely(key.empty()))
            throw std::runtime_error("missing token or English key in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");

        const std::string rest(StringUtil::Trim(StringUtil::Trim(line.substr(first_equal_pos + 1)), '"'));
        if (unlikely(rest.empty()))
            throw std::runtime_error("missing translation in \"" + ini_filename + "\" on line " + std::to_string(line_no) + "!");
        (*token_to_line_no_and_other_map)[key] = std::make_pair(line_no, rest);
    }
}

static std::map<std::string, std::string> german_to_3or4letter_english_codes{
    { "afr", "afr" },
    { "ara", "ara" },
    { "arg", "arg" },
    { "ast", "ast" },
    { "bre", "bre" },
    { "cat", "cat" },
    { "cym", "wel" },
    { "cze", "ces" },
    { "dan", "dan" },
    { "deu", "ger" },
    { "eng", "eng" },
    { "est", "est" },
    { "eus", "baq" },
    { "fin", "fin" },
    { "fra", "fre" },
    { "gaa", "gaa" },
    { "glg", "glg" },
    { "gre", "gre" },
    { "hat", "hat" },
    { "hrv", "hrv" },
    { "hun", "hun" },
    { "ice", "isl" },
    { "ind", "ind" },
    { "ita", "ita" },
    { "lat", "lat" },
    { "lav", "lav" },
    { "lit", "lit" },
    { "mlt", "mlt" },
    { "msa", "may" },
    { "nld", "dut" },
    { "nor", "nor" },
    { "oci", "oci" },
    { "pol", "pol" },
    { "por", "por" },
    { "rum", "ron" },
    { "rus", "rus" },
    { "slo", "slk" },
    { "slv", "slv" },
    { "som", "som" },
    { "spa", "spa" },
    { "srp", "srp" },
    { "swa", "swa" },
    { "swe", "swe" },
    { "tgl", "tgl" },
    { "tur", "tur" },
    { "vie", "vie" },
    { "hans", "hans" },
    { "hant", "hant" }
};

std::string MapGermanLanguageCodesToFake3LetterEnglishLanguagesCodes(const std::string &german_code) {
    const auto ger_and_eng_code(german_to_3or4letter_english_codes.find(german_code));
    if (ger_and_eng_code == german_to_3or4letter_english_codes.cend())
        return "???";
    return ger_and_eng_code->second;
}

std::string MapFake3LetterEnglishLanguagesCodesToGermanLanguageCodes(const std::string &english_3or4letter_code) {
    for (const auto &ger_and_eng_code : german_to_3or4letter_english_codes) {
        if (ger_and_eng_code.second == english_3or4letter_code)
            return ger_and_eng_code.first;
    }

    return "???";
}

bool IsValidFake3Or4LetterEnglishLanguagesCode(const std::string &english_3or4letter_code_candidate) {
    if (english_3or4letter_code_candidate.length() != 3 and english_3or4letter_code_candidate.length() != 4)
        return false;

    for (const auto &german_and_english_codes : german_to_3or4letter_english_codes) {
        if (german_and_english_codes.second == english_3or4letter_code_candidate)
            return true;
    }
    return false;
}

} // namespace TranslationUtil
<|endoftext|>


<commit_before>/*
* Blake2b
* (C) 2016 cynecx
* (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/blake2b.h>
#include <botan/exceptn.h>
#include <botan/mem_ops.h>
#include <botan/loadstor.h>
#include <botan/rotate.h>
#include <algorithm>

namespace Botan {

namespace {

enum blake2b_constant {
  BLAKE2B_BLOCKBYTES = 128,
  BLAKE2B_IVU64COUNT = 8
};

const uint64_t blake2b_IV[BLAKE2B_IVU64COUNT] = {
   0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
   0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
   0x510e527fade682d1, 0x9b05688c2b3e6c1f,
   0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
};

}

Blake2b::Blake2b(size_t output_bits) :
   m_output_bits(output_bits),
   m_buffer(BLAKE2B_BLOCKBYTES),
   m_bufpos(0),
   m_H(BLAKE2B_IVU64COUNT)
   {
   if(output_bits == 0 || output_bits > 512 || output_bits % 8 != 0)
      {
      throw Invalid_Argument("Bad output bits size for Blake2b");
      }

   state_init();
   }

void Blake2b::state_init()
   {
   copy_mem(m_H.data(), blake2b_IV, BLAKE2B_IVU64COUNT);
   m_H[0] ^= 0x01010000 ^ static_cast<uint8_t>(output_length());
   m_T[0] = m_T[1] = 0;
   m_F[0] = m_F[1] = 0;
   }

void Blake2b::compress(const uint8_t* input, size_t blocks, size_t increment)
   {
   for(size_t b = 0; b != blocks; ++b)
      {
      m_T[0] += increment;
      if(m_T[0] < increment)
         {
         m_T[1]++;
         }

      uint64_t M[16];
      uint64_t v[16];
      load_le(M, input, 16);

      input += BLAKE2B_BLOCKBYTES;

      for(size_t i = 0; i < 8; i++)
         v[i] = m_H[i];
      for(size_t i = 0; i != 8; ++i)
         v[i + 8] = blake2b_IV[i];

      v[12] ^= m_T[0];
      v[13] ^= m_T[1];
      v[14] ^= m_F[0];
      v[15] ^= m_F[1];

#define G(a, b, c, d, M0, M1)                   \
   do {                                         \
   a = a + b + M0;                              \
   d = rotr<32>(d ^ a);                         \
   c = c + d;                                   \
   b = rotr<24>(b ^ c);                         \
   a = a + b + M1;                              \
   d = rotr<16>(d ^ a);                         \
   c = c + d;                                   \
   b = rotr<63>(b ^ c);                         \
   } while(0)

#define ROUND(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, iA, iB, iC, iD, iE, iF) \
   do {                                                     \
      G(v[ 0], v[ 4], v[ 8], v[12], M[i0], M[i1]);          \
      G(v[ 1], v[ 5], v[ 9], v[13], M[i2], M[i3]);          \
      G(v[ 2], v[ 6], v[10], v[14], M[i4], M[i5]);          \
      G(v[ 3], v[ 7], v[11], v[15], M[i6], M[i7]);          \
      G(v[ 0], v[ 5], v[10], v[15], M[i8], M[i9]);          \
      G(v[ 1], v[ 6], v[11], v[12], M[iA], M[iB]);          \
      G(v[ 2], v[ 7], v[ 8], v[13], M[iC], M[iD]);          \
      G(v[ 3], v[ 4], v[ 9], v[14], M[iE], M[iF]);          \
   } while(0)

      ROUND( 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15);
      ROUND(14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3);
      ROUND(11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4);
      ROUND( 7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8);
      ROUND( 9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13);
      ROUND( 2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9);
      ROUND(12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11);
      ROUND(13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10);
      ROUND( 6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5);
      ROUND(10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0);
      ROUND( 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15);
      ROUND(14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3);

      for(size_t i = 0; i < 8; i++)
         {
         m_H[i] ^= v[i] ^ v[i + 8];
         }
      }

#undef G
#undef ROUND
   }

void Blake2b::add_data(const uint8_t input[], size_t length)
   {
   if(m_bufpos > 0)
      {
      const size_t take = std::min(BLAKE2B_BLOCKBYTES - m_bufpos, length);
      copy_mem(&m_buffer[m_bufpos], input, take);
      m_bufpos += take;
      length -= take;
      input += take;

      if(m_bufpos == m_buffer.size() && length > 0)
         {
         compress(m_buffer.data(), 1, BLAKE2B_BLOCKBYTES);
         m_bufpos = 0;
         }
      }

   if(length > BLAKE2B_BLOCKBYTES)
      {
      const size_t full_blocks = ((length-1) / BLAKE2B_BLOCKBYTES);
      compress(input, full_blocks, BLAKE2B_BLOCKBYTES);

      input += full_blocks * BLAKE2B_BLOCKBYTES;
      length -= full_blocks * BLAKE2B_BLOCKBYTES;
      }

   copy_mem(&m_buffer[m_bufpos], input, length);
   m_bufpos += length;
   }

void Blake2b::final_result(uint8_t output[])
   {
   clear_mem(&m_buffer[m_bufpos], BLAKE2B_BLOCKBYTES - m_bufpos);
   m_F[0] = 0xFFFFFFFFFFFFFFFF;
   compress(m_buffer.data(), 1, m_bufpos);
   copy_out_vec_le(output, output_length(), m_H);
   clear();
   }

std::string Blake2b::name() const
   {
   return "Blake2b(" + std::to_string(m_output_bits) + ")";
   }

HashFunction* Blake2b::clone() const
   {
   return new Blake2b(m_output_bits);
   }

std::unique_ptr<HashFunction> Blake2b::copy_state() const
   {
   return std::unique_ptr<HashFunction>(new Blake2b(*this));
   }

void Blake2b::clear()
   {
   zeroise(m_H);
   zeroise(m_buffer);
   m_bufpos = 0;
   state_init();
   }

}
<commit_msg>Avoid invalid iterator woes<commit_after>/*
* Blake2b
* (C) 2016 cynecx
* (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/blake2b.h>
#include <botan/exceptn.h>
#include <botan/mem_ops.h>
#include <botan/loadstor.h>
#include <botan/rotate.h>
#include <algorithm>

namespace Botan {

namespace {

enum blake2b_constant {
  BLAKE2B_BLOCKBYTES = 128,
  BLAKE2B_IVU64COUNT = 8
};

const uint64_t blake2b_IV[BLAKE2B_IVU64COUNT] = {
   0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
   0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
   0x510e527fade682d1, 0x9b05688c2b3e6c1f,
   0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
};

}

Blake2b::Blake2b(size_t output_bits) :
   m_output_bits(output_bits),
   m_buffer(BLAKE2B_BLOCKBYTES),
   m_bufpos(0),
   m_H(BLAKE2B_IVU64COUNT)
   {
   if(output_bits == 0 || output_bits > 512 || output_bits % 8 != 0)
      {
      throw Invalid_Argument("Bad output bits size for Blake2b");
      }

   state_init();
   }

void Blake2b::state_init()
   {
   copy_mem(m_H.data(), blake2b_IV, BLAKE2B_IVU64COUNT);
   m_H[0] ^= 0x01010000 ^ static_cast<uint8_t>(output_length());
   m_T[0] = m_T[1] = 0;
   m_F[0] = m_F[1] = 0;
   }

void Blake2b::compress(const uint8_t* input, size_t blocks, size_t increment)
   {
   for(size_t b = 0; b != blocks; ++b)
      {
      m_T[0] += increment;
      if(m_T[0] < increment)
         {
         m_T[1]++;
         }

      uint64_t M[16];
      uint64_t v[16];
      load_le(M, input, 16);

      input += BLAKE2B_BLOCKBYTES;

      for(size_t i = 0; i < 8; i++)
         v[i] = m_H[i];
      for(size_t i = 0; i != 8; ++i)
         v[i + 8] = blake2b_IV[i];

      v[12] ^= m_T[0];
      v[13] ^= m_T[1];
      v[14] ^= m_F[0];
      v[15] ^= m_F[1];

#define G(a, b, c, d, M0, M1)                   \
   do {                                         \
   a = a + b + M0;                              \
   d = rotr<32>(d ^ a);                         \
   c = c + d;                                   \
   b = rotr<24>(b ^ c);                         \
   a = a + b + M1;                              \
   d = rotr<16>(d ^ a);                         \
   c = c + d;                                   \
   b = rotr<63>(b ^ c);                         \
   } while(0)

#define ROUND(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, iA, iB, iC, iD, iE, iF) \
   do {                                                     \
      G(v[ 0], v[ 4], v[ 8], v[12], M[i0], M[i1]);          \
      G(v[ 1], v[ 5], v[ 9], v[13], M[i2], M[i3]);          \
      G(v[ 2], v[ 6], v[10], v[14], M[i4], M[i5]);          \
      G(v[ 3], v[ 7], v[11], v[15], M[i6], M[i7]);          \
      G(v[ 0], v[ 5], v[10], v[15], M[i8], M[i9]);          \
      G(v[ 1], v[ 6], v[11], v[12], M[iA], M[iB]);          \
      G(v[ 2], v[ 7], v[ 8], v[13], M[iC], M[iD]);          \
      G(v[ 3], v[ 4], v[ 9], v[14], M[iE], M[iF]);          \
   } while(0)

      ROUND( 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15);
      ROUND(14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3);
      ROUND(11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4);
      ROUND( 7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8);
      ROUND( 9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13);
      ROUND( 2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9);
      ROUND(12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11);
      ROUND(13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10);
      ROUND( 6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5);
      ROUND(10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0);
      ROUND( 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15);
      ROUND(14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3);

      for(size_t i = 0; i < 8; i++)
         {
         m_H[i] ^= v[i] ^ v[i + 8];
         }
      }

#undef G
#undef ROUND
   }

void Blake2b::add_data(const uint8_t input[], size_t length)
   {
   if(length == 0)
      return;

   if(m_bufpos > 0)
      {
      if(m_bufpos < BLAKE2B_BLOCKBYTES)
         {
         const size_t take = std::min(BLAKE2B_BLOCKBYTES - m_bufpos, length);
         copy_mem(&m_buffer[m_bufpos], input, take);
         m_bufpos += take;
         length -= take;
         input += take;
         }

      if(m_bufpos == m_buffer.size() && length > 0)
         {
         compress(m_buffer.data(), 1, BLAKE2B_BLOCKBYTES);
         m_bufpos = 0;
         }
      }

   if(length > BLAKE2B_BLOCKBYTES)
      {
      const size_t full_blocks = ((length-1) / BLAKE2B_BLOCKBYTES);
      compress(input, full_blocks, BLAKE2B_BLOCKBYTES);

      input += full_blocks * BLAKE2B_BLOCKBYTES;
      length -= full_blocks * BLAKE2B_BLOCKBYTES;
      }

   if(length > 0)
      {
      copy_mem(&m_buffer[m_bufpos], input, length);
      m_bufpos += length;
      }
   }

void Blake2b::final_result(uint8_t output[])
   {
   if(m_bufpos != BLAKE2B_BLOCKBYTES)
      clear_mem(&m_buffer[m_bufpos], BLAKE2B_BLOCKBYTES - m_bufpos);
   m_F[0] = 0xFFFFFFFFFFFFFFFF;
   compress(m_buffer.data(), 1, m_bufpos);
   copy_out_vec_le(output, output_length(), m_H);
   clear();
   }

std::string Blake2b::name() const
   {
   return "Blake2b(" + std::to_string(m_output_bits) + ")";
   }

HashFunction* Blake2b::clone() const
   {
   return new Blake2b(m_output_bits);
   }

std::unique_ptr<HashFunction> Blake2b::copy_state() const
   {
   return std::unique_ptr<HashFunction>(new Blake2b(*this));
   }

void Blake2b::clear()
   {
   zeroise(m_H);
   zeroise(m_buffer);
   m_bufpos = 0;
   state_init();
   }

}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2013   Utku Aydın <utkuaydin34@gmail.com>
//

#include "ConflictDialog.h"

#include "MergeItem.h"
#include "GeoDataPlacemark.h"

#include <QLabel>
#include <QVariant>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>

namespace Marble {

ConflictDialog::ConflictDialog( QWidget *parent ) :
    QDialog( parent ),
    m_mergeItem( 0 ),
    m_box( 0 )
{
    m_autoResolve = ConflictDialog::Manual;
}

void ConflictDialog::setMergeItem( MergeItem *item )
{
    m_mergeItem = item;
}

void ConflictDialog::stopAutoResolve()
{
    m_autoResolve = ConflictDialog::Manual;
}

void ConflictDialog::open()
{
    if( m_mergeItem == 0 ) {
        return;
    }

    switch( m_autoResolve ) {
    case ConflictDialog::Manual:
        prepareLayout();
        QDialog::open();
        break;
    case ConflictDialog::PreferLocal:
        m_mergeItem->setResolution( MergeItem::A );
        emit resolveConflict( m_mergeItem );
        break;
    case ConflictDialog::PreferCloud:
        m_mergeItem->setResolution( MergeItem::B );
        emit resolveConflict( m_mergeItem );
        break;
    }
}

void ConflictDialog::resolveConflict( QAbstractButton *button )
{
    accept();

    QDialogButtonBox::StandardButton standardButton = m_box->standardButton( button );
    switch(standardButton) {
    case QDialogButtonBox::Cancel:
        break;

    case QDialogButtonBox::NoButton:
       int actionRole = button->property( "ActionRole" ).toInt();
       switch( actionRole ) {
       case ConflictDialog::Local:
           m_mergeItem->setResolution( MergeItem::A );
           emit resolveConflict( m_mergeItem );
           break;
       case ConflictDialog::Cloud:
           m_mergeItem->setResolution( MergeItem::B );
           emit resolveConflict( m_mergeItem );
           break;
       case ConflictDialog::AllLocal:
           m_mergeItem->setResolution( MergeItem::A );
           m_autoResolve = ConflictDialog::PreferLocal;
           emit resolveConflict( m_mergeItem );
           break;
       case ConflictDialog::AllCloud:
           m_mergeItem->setResolution( MergeItem::B );
           m_autoResolve = ConflictDialog::PreferCloud;
           emit resolveConflict( m_mergeItem );
           break;
      default:
           break;
       }
    }
}

void ConflictDialog::prepareLayout()
{
    delete layout();
    qDeleteAll( children() );
    m_box = new QDialogButtonBox( QDialogButtonBox::Cancel );

    QPushButton *localButton = new QPushButton( tr( "Use local" ) );
    QPushButton *cloudButton = new QPushButton( tr( "Use cloud" ) );
    QPushButton *allLocalButton = new QPushButton( tr( "Always use local" ) );
    QPushButton *allCloudButton = new QPushButton( tr( "Always use cloud" ) );

    localButton->setDefault( true );
    localButton->setProperty( "ActionRole", ConflictDialog::Local );
    cloudButton->setProperty( "ActionRole", ConflictDialog::Cloud );
    allLocalButton->setProperty( "ActionRole", ConflictDialog::AllLocal );
    allCloudButton->setProperty( "ActionRole", ConflictDialog::AllCloud );

    m_box->addButton( localButton, QDialogButtonBox::ActionRole );
    m_box->addButton( cloudButton, QDialogButtonBox::ActionRole );
    m_box->addButton( allLocalButton, QDialogButtonBox::ActionRole );
    m_box->addButton( allCloudButton, QDialogButtonBox::ActionRole );

    QVBoxLayout *leftLayout = new QVBoxLayout();
    QString localHeaderText = tr( "Local placemark" );
    QString localDetailText = tr( "Path: %0
 Name: %1" )
            .arg( m_mergeItem->pathA(), m_mergeItem->placemarkA().name() );
    QLabel *localHeaderLabel = new QLabel( localHeaderText );
    QLabel *localDetailLabel = new QLabel( localDetailText );
    leftLayout->addWidget( localHeaderLabel );
    leftLayout->addWidget( localDetailLabel );

    QVBoxLayout *rightLayout = new QVBoxLayout();
    QString cloudHeaderText = tr( "Cloud placemark" );
    QString cloudDetailText = tr( "Path: %0
 Name: %1" )
            .arg( m_mergeItem->pathB(), m_mergeItem->placemarkB().name() );
    QLabel *cloudHeaderLabel = new QLabel( cloudHeaderText );
    QLabel *cloudDetailLabel = new QLabel( cloudDetailText );
    rightLayout->addWidget( cloudHeaderLabel );
    rightLayout->addWidget( cloudDetailLabel );

    QHBoxLayout *detailLayout = new QHBoxLayout();
    detailLayout->addLayout( leftLayout );
    detailLayout->addLayout( rightLayout );

    QLabel *descriptionLabel = new QLabel();
    QString descriptionText = tr( "A bookmark on this device conflicts " \
                                  "with a cloud bookmark. Which one do " \
                                  "you want to keep?" );
    descriptionLabel->setText( descriptionText );

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->addWidget( descriptionLabel );
    mainLayout->addLayout( detailLayout );
    mainLayout->addWidget( m_box );

    setLayout( mainLayout );
    setWindowTitle( tr( "Synchronization Conflict" ) );

    connect( m_box, SIGNAL(clicked(QAbstractButton*)),
             this, SLOT(resolveConflict(QAbstractButton*)) );
}

}

#include "ConflictDialog.moc"
<commit_msg>Make use of switch's default case<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2013   Utku Aydın <utkuaydin34@gmail.com>
//

#include "ConflictDialog.h"

#include "MergeItem.h"
#include "GeoDataPlacemark.h"

#include <QLabel>
#include <QVariant>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>

namespace Marble {

ConflictDialog::ConflictDialog( QWidget *parent ) :
    QDialog( parent ),
    m_mergeItem( 0 ),
    m_box( 0 )
{
    m_autoResolve = ConflictDialog::Manual;
}

void ConflictDialog::setMergeItem( MergeItem *item )
{
    m_mergeItem = item;
}

void ConflictDialog::stopAutoResolve()
{
    m_autoResolve = ConflictDialog::Manual;
}

void ConflictDialog::open()
{
    if( m_mergeItem == 0 ) {
        return;
    }

    switch( m_autoResolve ) {
    case ConflictDialog::Manual:
        prepareLayout();
        QDialog::open();
        break;
    case ConflictDialog::PreferLocal:
        m_mergeItem->setResolution( MergeItem::A );
        emit resolveConflict( m_mergeItem );
        break;
    case ConflictDialog::PreferCloud:
        m_mergeItem->setResolution( MergeItem::B );
        emit resolveConflict( m_mergeItem );
        break;
    }
}

void ConflictDialog::resolveConflict( QAbstractButton *button )
{
    accept();

    QDialogButtonBox::StandardButton standardButton = m_box->standardButton( button );
    switch(standardButton) {
    case QDialogButtonBox::NoButton:
    {
        int actionRole = button->property( "ActionRole" ).toInt();
        switch( actionRole ) {
        case ConflictDialog::Local:
            m_mergeItem->setResolution( MergeItem::A );
            emit resolveConflict( m_mergeItem );
            break;
        case ConflictDialog::Cloud:
            m_mergeItem->setResolution( MergeItem::B );
            emit resolveConflict( m_mergeItem );
            break;
        case ConflictDialog::AllLocal:
            m_mergeItem->setResolution( MergeItem::A );
            m_autoResolve = ConflictDialog::PreferLocal;
            emit resolveConflict( m_mergeItem );
            break;
        case ConflictDialog::AllCloud:
            m_mergeItem->setResolution( MergeItem::B );
            m_autoResolve = ConflictDialog::PreferCloud;
            emit resolveConflict( m_mergeItem );
            break;
        default:
            break;
        }
    }

    default:
        break;
    }
}

void ConflictDialog::prepareLayout()
{
    delete layout();
    qDeleteAll( children() );
    m_box = new QDialogButtonBox( QDialogButtonBox::Cancel );

    QPushButton *localButton = new QPushButton( tr( "Use local" ) );
    QPushButton *cloudButton = new QPushButton( tr( "Use cloud" ) );
    QPushButton *allLocalButton = new QPushButton( tr( "Always use local" ) );
    QPushButton *allCloudButton = new QPushButton( tr( "Always use cloud" ) );

    localButton->setDefault( true );
    localButton->setProperty( "ActionRole", ConflictDialog::Local );
    cloudButton->setProperty( "ActionRole", ConflictDialog::Cloud );
    allLocalButton->setProperty( "ActionRole", ConflictDialog::AllLocal );
    allCloudButton->setProperty( "ActionRole", ConflictDialog::AllCloud );

    m_box->addButton( localButton, QDialogButtonBox::ActionRole );
    m_box->addButton( cloudButton, QDialogButtonBox::ActionRole );
    m_box->addButton( allLocalButton, QDialogButtonBox::ActionRole );
    m_box->addButton( allCloudButton, QDialogButtonBox::ActionRole );

    QVBoxLayout *leftLayout = new QVBoxLayout();
    QString localHeaderText = tr( "Local placemark" );
    QString localDetailText = tr( "Path: %0
 Name: %1" )
            .arg( m_mergeItem->pathA(), m_mergeItem->placemarkA().name() );
    QLabel *localHeaderLabel = new QLabel( localHeaderText );
    QLabel *localDetailLabel = new QLabel( localDetailText );
    leftLayout->addWidget( localHeaderLabel );
    leftLayout->addWidget( localDetailLabel );

    QVBoxLayout *rightLayout = new QVBoxLayout();
    QString cloudHeaderText = tr( "Cloud placemark" );
    QString cloudDetailText = tr( "Path: %0
 Name: %1" )
            .arg( m_mergeItem->pathB(), m_mergeItem->placemarkB().name() );
    QLabel *cloudHeaderLabel = new QLabel( cloudHeaderText );
    QLabel *cloudDetailLabel = new QLabel( cloudDetailText );
    rightLayout->addWidget( cloudHeaderLabel );
    rightLayout->addWidget( cloudDetailLabel );

    QHBoxLayout *detailLayout = new QHBoxLayout();
    detailLayout->addLayout( leftLayout );
    detailLayout->addLayout( rightLayout );

    QLabel *descriptionLabel = new QLabel();
    QString descriptionText = tr( "A bookmark on this device conflicts " \
                                  "with a cloud bookmark. Which one do " \
                                  "you want to keep?" );
    descriptionLabel->setText( descriptionText );

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->addWidget( descriptionLabel );
    mainLayout->addLayout( detailLayout );
    mainLayout->addWidget( m_box );

    setLayout( mainLayout );
    setWindowTitle( tr( "Synchronization Conflict" ) );

    connect( m_box, SIGNAL(clicked(QAbstractButton*)),
             this, SLOT(resolveConflict(QAbstractButton*)) );
}

}

#include "ConflictDialog.moc"
<|endoftext|>


<commit_before>/*!
 * \page SimulationTestSuite_cpp Command-Line Test to Demonstrate How To Test DSim
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE DSimTest
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/stdair_exceptions.hpp>
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/service/Logger.hpp>
// Dsim
#include <dsim/DSIM_Types.hpp>
#include <dsim/DSIM_Service.hpp>
#include <dsim/config/dsim-paths.hpp>

namespace boost_utf = boost::unit_test;

// (Boost) Unit Test XML Report
std::ofstream utfReportStream ("SimulationTestSuite_utfresults.xml");

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    boost_utf::unit_test_log.set_stream (utfReportStream);
    boost_utf::unit_test_log.set_format (boost_utf::XML);
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }
  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test a simple simulation
 */
BOOST_AUTO_TEST_CASE (simple_simulation_test) {

  // Schedule input file name
  const stdair::Filename_T lScheduleInputFilename (STDAIR_SAMPLE_DIR
                                                   "/schedule01.csv");

  // O&D input file name
  const stdair::Filename_T lODInputFilename (STDAIR_SAMPLE_DIR "/ond01.csv");

  // Demand input file name
  const stdair::Filename_T lDemandInputFilename (STDAIR_SAMPLE_DIR
                                                 "/demand01.csv");

  // Fare input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fare01.csv");

  // Check that the file path given as input corresponds to an actual file
  bool doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lScheduleInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lScheduleInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lODInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lODInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lDemandInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lDemandInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lFareInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lFareInputFilename
                       << "' input file can not be open and read");

  // Output log File
  const stdair::Filename_T lLogFilename ("SimulationTestSuite.log");

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the simulation context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
  const stdair::BasDBParams lDBParams ("dsim", "dsim", "localhost", "3306",
                                       "sim_dsim");
  DSIM::DSIM_Service dsimService (lLogParams, lDBParams,
                                  lScheduleInputFilename, lODInputFilename,
                                  lFareInputFilename, lDemandInputFilename);

  // Perform a simulation
  // TODO: understand why there is an exception raised here
  // BOOST_CHECK_NO_THROW (dsimService.simulate());
  BOOST_CHECK_THROW (dsimService.simulate(), stdair::EventException);

  // Close the log file
  logOutputFile.close();
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<commit_msg>[DSim][Test] The test no longer raises an exception.<commit_after>/*!
 * \page SimulationTestSuite_cpp Command-Line Test to Demonstrate How To Test DSim
 * \code
 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <string>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE DSimTest
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/stdair_exceptions.hpp>
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/service/Logger.hpp>
// Dsim
#include <dsim/DSIM_Types.hpp>
#include <dsim/DSIM_Service.hpp>
#include <dsim/config/dsim-paths.hpp>

namespace boost_utf = boost::unit_test;

// (Boost) Unit Test XML Report
std::ofstream utfReportStream ("SimulationTestSuite_utfresults.xml");

/**
 * Configuration for the Boost Unit Test Framework (UTF)
 */
struct UnitTestConfig {
  /** Constructor. */
  UnitTestConfig() {
    boost_utf::unit_test_log.set_stream (utfReportStream);
    boost_utf::unit_test_log.set_format (boost_utf::XML);
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }
  /** Destructor. */
  ~UnitTestConfig() {
  }
};

// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)

/**
 * Test a simple simulation
 */
BOOST_AUTO_TEST_CASE (simple_simulation_test) {

  // Schedule input file name
  const stdair::Filename_T lScheduleInputFilename (STDAIR_SAMPLE_DIR
                                                   "/schedule01.csv");

  // O&D input file name
  const stdair::Filename_T lODInputFilename (STDAIR_SAMPLE_DIR "/ond01.csv");

  // Demand input file name
  const stdair::Filename_T lDemandInputFilename (STDAIR_SAMPLE_DIR
                                                 "/demand01.csv");

  // Fare input file name
  const stdair::Filename_T lFareInputFilename (STDAIR_SAMPLE_DIR "/fare01.csv");

  // Check that the file path given as input corresponds to an actual file
  bool doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lScheduleInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lScheduleInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lODInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lODInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lDemandInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lDemandInputFilename
                       << "' input file can not be open and read");

  // Check that the file path given as input corresponds to an actual file
  doesExistAndIsReadable =
    stdair::BasFileMgr::doesExistAndIsReadable (lFareInputFilename);
  BOOST_CHECK_MESSAGE (doesExistAndIsReadable == true,
                       "The '" << lFareInputFilename
                       << "' input file can not be open and read");

  // Output log File
  const stdair::Filename_T lLogFilename ("SimulationTestSuite.log");

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the simulation context
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
  const stdair::BasDBParams lDBParams ("dsim", "dsim", "localhost", "3306",
                                       "sim_dsim");
  DSIM::DSIM_Service dsimService (lLogParams, lDBParams,
                                  lScheduleInputFilename, lODInputFilename,
                                  lFareInputFilename, lDemandInputFilename);

  // Perform a simulation
  // BOOST_CHECK_THROW (dsimService.simulate(), stdair::EventException);
  BOOST_CHECK_NO_THROW (dsimService.simulate());

  // Close the log file
  logOutputFile.close();
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!
 * \endcode
 */
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <sstream>
#include <raul/Path.hpp>
//#include "lv2_osc_print.h"
#include "PluginModel.hpp"
#include "PatchModel.hpp"
#include "PluginUI.hpp"

using namespace std;
using Ingen::Shared::EngineInterface;

namespace Ingen {
namespace Client {

#ifdef HAVE_SLV2
SLV2World   PluginModel::_slv2_world   = NULL;
SLV2Plugins PluginModel::_slv2_plugins = NULL;
#endif

Redland::World* PluginModel::_rdf_world = NULL;

string
PluginModel::default_node_name()
{
	return Raul::Path::nameify(_symbol);
}

#ifdef HAVE_SLV2
SharedPtr<PluginUI>
PluginModel::ui(Ingen::Shared::World* world, SharedPtr<NodeModel> node) const
{
	if (_type != LV2)
		return SharedPtr<PluginUI>();

	Glib::Mutex::Lock lock(_rdf_world->mutex());
	SharedPtr<PluginUI> ret = PluginUI::create(world, node, _slv2_plugin);
	return ret;
}

const string&
PluginModel::icon_path() const
{
	if (_icon_path == "" && _type == LV2) {
		Glib::Mutex::Lock lock(_rdf_world->mutex());
		_icon_path = get_lv2_icon_path(_slv2_plugin);
	}

	return _icon_path;
}

/** RDF world mutex must be held by the caller */
string
PluginModel::get_lv2_icon_path(SLV2Plugin plugin)
{
	string result;
	SLV2Value svg_icon_pred = slv2_value_new_uri(_slv2_world,
		"http://ll-plugins.nongnu.org/lv2/namespace#svgIcon");

	SLV2Values paths = slv2_plugin_get_value(plugin, svg_icon_pred);

	if (slv2_values_size(paths) > 0) {
		SLV2Value value = slv2_values_get_at(paths, 0);
		if (slv2_value_is_uri(value))
			result = slv2_uri_to_path(slv2_value_as_string(value));
		slv2_values_free(paths);
	}

	slv2_value_free(svg_icon_pred);
	return result;
}

#endif

} // namespace Client
} // namespace Ingen
<commit_msg>Fix deadlock on LV2 GUI show.<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <sstream>
#include <raul/Path.hpp>
//#include "lv2_osc_print.h"
#include "PluginModel.hpp"
#include "PatchModel.hpp"
#include "PluginUI.hpp"

using namespace std;
using Ingen::Shared::EngineInterface;

namespace Ingen {
namespace Client {

#ifdef HAVE_SLV2
SLV2World   PluginModel::_slv2_world   = NULL;
SLV2Plugins PluginModel::_slv2_plugins = NULL;
#endif

Redland::World* PluginModel::_rdf_world = NULL;

string
PluginModel::default_node_name()
{
	return Raul::Path::nameify(_symbol);
}

#ifdef HAVE_SLV2
SharedPtr<PluginUI>
PluginModel::ui(Ingen::Shared::World* world, SharedPtr<NodeModel> node) const
{
	if (_type != LV2)
		return SharedPtr<PluginUI>();

	SharedPtr<PluginUI> ret = PluginUI::create(world, node, _slv2_plugin);
	return ret;
}

const string&
PluginModel::icon_path() const
{
	if (_icon_path == "" && _type == LV2) {
		Glib::Mutex::Lock lock(_rdf_world->mutex());
		_icon_path = get_lv2_icon_path(_slv2_plugin);
	}

	return _icon_path;
}

/** RDF world mutex must be held by the caller */
string
PluginModel::get_lv2_icon_path(SLV2Plugin plugin)
{
	string result;
	SLV2Value svg_icon_pred = slv2_value_new_uri(_slv2_world,
		"http://ll-plugins.nongnu.org/lv2/namespace#svgIcon");

	SLV2Values paths = slv2_plugin_get_value(plugin, svg_icon_pred);

	if (slv2_values_size(paths) > 0) {
		SLV2Value value = slv2_values_get_at(paths, 0);
		if (slv2_value_is_uri(value))
			result = slv2_uri_to_path(slv2_value_as_string(value));
		slv2_values_free(paths);
	}

	slv2_value_free(svg_icon_pred);
	return result;
}

#endif

} // namespace Client
} // namespace Ingen
<|endoftext|>


<commit_before>#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>

#define THRESHOLD 35000000000
#define PI 3.1416

using namespace cv;
using namespace std;

struct MotionVector
{
	float vel_x;
	float vel_y;

	MotionVector() :vel_x(0.0),vel_y(0.0){};
};

class MotionField
{
	std::vector<MotionVector> motion_field;
        cv::Mat motion_field_image;
	int rows;
	int cols;

  public:

	MotionField(int num_rows, int num_cols, const Mat& previous_frame)
	{
		rows = num_rows;
		cols = num_cols;
		motion_field_image = previous_frame.clone();
		motion_field.resize(rows*cols);
	}

	void set(int row, int col, const MotionVector& motion_vector)
	{

		if(row >= rows || row < 0)
		{
			cout<<"Row index out of bounds of the height of motion field"<<endl;
			return ;
		}

		if(col >= cols || col < 0 )
		{
			cout<<"Col index out of bounds of the width of motion field"<<endl;
			return;
		}

		int index = row*cols + col;
		motion_field[index] = motion_vector;
	}

	MotionVector& get(int row, int col)
	{
		if(row >= rows || row < 0)
		{
			cout<<"Row index out of bounds of the height of motion field"<<endl;
			row = rows-1;
		}

		if(col >= cols || col < 0 )
		{
			cout<<"Col index out of bounds of the width of motion field"<<endl;
			col = cols-1;
		}
		return motion_field[row*cols+col];
	}

	void print(int resolution=10)
	{
          cout << "Printing Motion Field"<<endl;
	   for(int j = 0; j < rows ; j+=resolution)
	   {
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   cout<<"("<<dx<<","<<dy<<") ";
		}
		cout<<endl;
	   }
	}

	void quiver(const Mat& image, int resolution)
	{

	   float max_length = -1000;

	   for(int j = 0; j < rows ; j+=resolution)
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   float length = sqrt(pow(dx,2)+pow(dy,2));

		   if(length > max_length)
			max_length = length;

		}

	   for(int j = 0; j < rows ; j+=resolution)
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   cv::Point p1(i,j);

		   float length = sqrt(pow(dx,2)+pow(dy,2));

		   if(length > 0)
		   {
			float arrow_size = 5.0*length/max_length;

			cv::Point p2((int)(p1.x+dx),(int)(p1.y+dy));

			arrowedLine(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0,0.2);

//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA);

//			float angle = atan2((float) p1.y - p2.y, (float) p1.x -p2.x);

//		        p1.x = (int) (p2.x + arrow_size * cos(angle + PI / 4));
//		        p1.y = (int) (p2.y + arrow_size * sin(angle + PI / 4));
//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0);

//		        p1.x = (int) (p2.x + arrow_size * cos(angle - PI / 4));
//		        p1.y = (int) (p2.y + arrow_size * sin(angle - PI / 4));
//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0);
		   }

		   else
		   {
			circle(  image, Point( i, j ), 0.2,  Scalar(0,255,0), 0.1, 8, 0 );
		   }

		}

	}

	std::vector<MotionVector> getMotionField()
	{
		return motion_field;
	}

	Mat getImage(int resolution=10)
	{
		quiver(motion_field_image,resolution);
		return motion_field_image;

	}

};

MotionField estimateMotionByBlockMatching(const Mat& previousFrame, const Mat& currentFrame, int block_size = 8, int search_window_size = 32)
{

	Mat previous_frame_resized, current_frame_resized;

	float width_offset = (float)currentFrame.cols/(float)block_size;
	int new_width = currentFrame.cols + (cvRound(width_offset) - width_offset)*block_size;

	float height_offset = (float)currentFrame.rows/(float)block_size;
	int new_height = currentFrame.rows + (cvRound(height_offset) - height_offset)*block_size;

	Mat previous_grayscale_image, current_grayscale_image;

	if(new_width == currentFrame.cols && new_height == currentFrame.rows )
	{
		previous_frame_resized = previousFrame.clone();
		current_frame_resized = currentFrame.clone();
	}

	else
	{
		resize(previousFrame, previous_frame_resized, Size(new_height,new_width));
		resize(currentFrame, current_frame_resized, Size(new_height,new_width));
	}

	cvtColor( previous_frame_resized , previous_grayscale_image, CV_BGR2GRAY );
	cvtColor( current_frame_resized , current_grayscale_image, CV_BGR2GRAY );

	MotionField motion_field(new_height, new_width, previous_frame_resized);

	if(search_window_size <= block_size || search_window_size%block_size != 0)
	{
		cout<<"Search window size must be greater than the block size and must be a multiple of block size  ";
		return motion_field;
	}

	int number_of_blocks_cols = new_width/block_size;

	int number_of_blocks_rows = new_height/block_size;

	cv::Mat currentFrameBlocks[number_of_blocks_rows][number_of_blocks_cols];

 	//Parse through each block in current image
	for(int j = 0; j < number_of_blocks_rows ; j++)
	{
		for(int i = 0; i < number_of_blocks_cols ; i++)
		{

			currentFrameBlocks[j][i] = Mat::zeros( block_size, block_size, CV_8UC1 );

			int start_row_index = j*block_size;
			int start_col_index = i*block_size;

			int stop_row_index = start_row_index +block_size;
			int stop_col_index = start_col_index +block_size;

			int row = 0;
			int col = 0;

			//Filling up each block with the values in current frame
			for(int m=start_row_index; m < stop_row_index; m++)
			{
				col = 0;
				for(int n=start_col_index ; n < stop_col_index; n++)
				{
					currentFrameBlocks[j][i].at<uchar>(row,col) = current_grayscale_image.at<uchar>(m,n);
					col++;
				}
				row++;
			}

			int center_x = (start_row_index+stop_row_index)/2;
			int center_y = (start_col_index+stop_col_index)/2;

//			cout<<"current_center x = "<<center_x<<" , y="<<center_y<<endl;

			int start_row_search_index = center_x - search_window_size/2 ;
			int start_col_search_index = center_y - search_window_size/2 ;

			int stop_row_search_index = center_x + search_window_size/2;
			int stop_col_search_index = center_y + search_window_size/2;

			if(start_row_search_index < 0)
				start_row_search_index = 0;

			if(start_col_search_index < 0)
				start_col_search_index = 0;

			if(stop_row_search_index > new_height)
				stop_row_search_index = new_height;

			if(stop_col_search_index > new_width)
				stop_col_search_index = new_width;

			float best_ssd = 10000;

			MotionVector best_motion_vector;

			//Parse through the search window in previous frame and find the best motion vector
			for(int m=start_row_search_index; m < stop_row_search_index; m++)
			{
				for(int n=start_col_search_index ; n < stop_col_search_index; n++)
				{

					float ssd = 0.0;

					//Compute Sum of Squared Differences
					for(int q=0; q < block_size; q++)
					{
						for(int r=0 ; r < block_size; r++)
						{

							int current_frame_pixel = currentFrameBlocks[j][i].at<uchar>(q,r);
							int previous_frame_pixel = previous_grayscale_image.at<uchar>(m+q,r+n);
							ssd += abs(current_frame_pixel - previous_frame_pixel);

							//ssd += sqrt(pow(current_frame_pixel-previous_frame_pixel,2));

							//cout<<"current index q="<<q<<", r= "<<r<<" , value="<<current_frame_pixel<<" previous index m+q="<<m+q<<" ,r+n="<<r+n<<" ,value ="<<previous_frame_pixel<<endl;

						}
					}

					int center_x_search_window = m+block_size/2;
					int center_y_search_window = n+block_size/2;

					//cout<<"search window x = "<<center_x_search_window<<" , y="<<center_y_search_window<<endl;
					//cout<<"block x = "<<center_x<<" , y="<<center_y<<" , ssd="<<ssd<<endl;

					if(ssd<best_ssd)
					{
						best_ssd = ssd;
						best_motion_vector.vel_y = center_x - center_x_search_window;
						best_motion_vector.vel_x = center_y - center_y_search_window;
					}
				}
			}

			//Fill the values in motion field
			for(int m=start_row_index; m < stop_row_index; m++)
			{
				for(int n=start_col_index ; n < stop_col_index; n++)
				{
					motion_field.set(m,n,best_motion_vector);

				}
			}

			//cout<<"best motion_vector ssd = "<<best_ssd<<" x ="<<best_motion_vector.vel_x<<" , y= "<<best_motion_vector.vel_y<<endl;

			//cout<<"block j="<<j<<" , i= "<<i<<endl;

			//return;

		}

	}

	return motion_field;

}

int main(int argc, char** argv )
{
    Mat grayscale_image1, grayscale_image2;

    Mat image1 = imread( "../images/foreman/fm0001.tif", 1 );
    Mat image2 = imread( "../images/foreman/fm0002.tif", 1 );

    if ( !image1.data || !image2.data )
     {
        printf("No image data \n");
        return -1;
     }

   MotionField motion_field = estimateMotionByBlockMatching(image1,image2);

   Mat motion_estimated_image = motion_field.getImage();

   //motion_field.print();

   namedWindow("Estimated Motion Field", WINDOW_AUTOSIZE);
   imshow("Estimated Motion Field", motion_estimated_image);
   imwrite( "../results/motion_estimation/foreman/sad/estimated_motion_field.jpg", motion_estimated_image);

    waitKey(0);

    return 0;
}

<commit_msg>Provide option to use either SSD or SAD as matching criteria<commit_after>#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>

#define THRESHOLD 35000000000
#define PI 3.1416

#define SAD 0
#define SSD 1

using namespace cv;
using namespace std;

struct MotionVector
{
	float vel_x;
	float vel_y;

	MotionVector() :vel_x(0.0),vel_y(0.0){};
};

class MotionField
{
	std::vector<MotionVector> motion_field;
        cv::Mat motion_field_image;
	int matching_criteria;

  public:
	int rows;
	int cols;
	MotionField(int num_rows, int num_cols, const Mat& previous_frame)
	{
		rows = num_rows;
		cols = num_cols;
		motion_field.resize(rows*cols);
		motion_field_image = previous_frame.clone();
	}

	void set(int row, int col, const MotionVector& motion_vector)
	{

		if(row >= rows || row < 0)
		{
			cout<<"Row index out of bounds of the height of motion field"<<endl;
			return ;
		}

		if(col >= cols || col < 0 )
		{
			cout<<"Col index out of bounds of the width of motion field"<<endl;
			return;
		}

		int index = row*cols + col;
		motion_field[index] = motion_vector;
	}

	MotionVector& get(int row, int col)
	{
		if(row >= rows || row < 0)
		{
			cout<<"Row index out of bounds of the height of motion field"<<endl;
			row = rows-1;
		}

		if(col >= cols || col < 0 )
		{
			cout<<"Col index out of bounds of the width of motion field"<<endl;
			col = cols-1;
		}
		return motion_field[row*cols+col];
	}

	void print(int resolution=10)
	{
          cout << "Printing Motion Field"<<endl;
	   for(int j = 0; j < rows ; j+=resolution)
	   {
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   cout<<"("<<dx<<","<<dy<<") ";
		}
		cout<<endl;
	   }
	}

	void quiver(const Mat& image, int resolution)
	{

	   float max_length = -1000;

	   for(int j = 0; j < rows ; j+=resolution)
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   float length = sqrt(pow(dx,2)+pow(dy,2));

		   if(length > max_length)
			max_length = length;

		}

	   for(int j = 0; j < rows ; j+=resolution)
		for(int i = 0; i < cols; i+=resolution)
		{
		   MotionVector motion_vector = get(j,i);
		   float dx = motion_vector.vel_x;
		   float dy = motion_vector.vel_y;

		   cv::Point p1(i,j);

		   float length = sqrt(pow(dx,2)+pow(dy,2));

		   if(length > 0)
		   {
			float arrow_size = 5.0*length/max_length;

			cv::Point p2((int)(p1.x+dx),(int)(p1.y+dy));

			arrowedLine(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0,0.2);

//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA);

//			float angle = atan2((float) p1.y - p2.y, (float) p1.x -p2.x);

//		        p1.x = (int) (p2.x + arrow_size * cos(angle + PI / 4));
//		        p1.y = (int) (p2.y + arrow_size * sin(angle + PI / 4));
//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0);

//		        p1.x = (int) (p2.x + arrow_size * cos(angle - PI / 4));
//		        p1.y = (int) (p2.y + arrow_size * sin(angle - PI / 4));
//			cv::line(image,p1,p2,CV_RGB(0,255,0),1,CV_AA,0);
		   }

		   else
		   {
			circle(  image, Point( i, j ), 0.2,  Scalar(0,255,0), 0.1, 8, 0 );
		   }

		}

	}

	std::vector<MotionVector> getMotionField()
	{
		return motion_field;
	}

	Mat getImage(int resolution=10)
	{
		quiver(motion_field_image,resolution);
		return motion_field_image;

	}

};

MotionField estimateMotionByBlockMatching(const Mat& previousFrame, const Mat& currentFrame,int matching_criteria = SAD, int block_size = 8, int search_window_size = 32)
{

	Mat previous_frame_resized, current_frame_resized;

	float width_offset = (float)currentFrame.cols/(float)block_size;
	int new_width = currentFrame.cols + (cvRound(width_offset) - width_offset)*block_size;

	float height_offset = (float)currentFrame.rows/(float)block_size;
	int new_height = currentFrame.rows + (cvRound(height_offset) - height_offset)*block_size;

	Mat previous_grayscale_image, current_grayscale_image;

	if(new_width == currentFrame.cols && new_height == currentFrame.rows )
	{
		previous_frame_resized = previousFrame.clone();
		current_frame_resized = currentFrame.clone();
	}

	else
	{
		resize(previousFrame, previous_frame_resized, Size(new_height,new_width));
		resize(currentFrame, current_frame_resized, Size(new_height,new_width));
	}

	cvtColor( previous_frame_resized , previous_grayscale_image, CV_BGR2GRAY );
	cvtColor( current_frame_resized , current_grayscale_image, CV_BGR2GRAY );

	MotionField motion_field(new_height, new_width, previous_frame_resized);

	if(search_window_size <= block_size || search_window_size%block_size != 0)
	{
		cout<<"Search window size must be greater than the block size and must be a multiple of block size  ";
		return motion_field;
	}

	int number_of_blocks_cols = new_width/block_size;

	int number_of_blocks_rows = new_height/block_size;

	cv::Mat currentFrameBlocks[number_of_blocks_rows][number_of_blocks_cols];

 	//Parse through each block in current image
	for(int j = 0; j < number_of_blocks_rows ; j++)
	{
		for(int i = 0; i < number_of_blocks_cols ; i++)
		{

			currentFrameBlocks[j][i] = Mat::zeros( block_size, block_size, CV_8UC1 );

			int start_row_index = j*block_size;
			int start_col_index = i*block_size;

			int stop_row_index = start_row_index +block_size;
			int stop_col_index = start_col_index +block_size;

			int row = 0;
			int col = 0;

			//Filling up each block with the values in current frame
			for(int m=start_row_index; m < stop_row_index; m++)
			{
				col = 0;
				for(int n=start_col_index ; n < stop_col_index; n++)
				{
					currentFrameBlocks[j][i].at<uchar>(row,col) = current_grayscale_image.at<uchar>(m,n);
					col++;
				}
				row++;
			}

			int center_x = (start_row_index+stop_row_index)/2;
			int center_y = (start_col_index+stop_col_index)/2;

//			cout<<"current_center x = "<<center_x<<" , y="<<center_y<<endl;

			int start_row_search_index = center_x - search_window_size/2 ;
			int start_col_search_index = center_y - search_window_size/2 ;

			int stop_row_search_index = center_x + search_window_size/2;
			int stop_col_search_index = center_y + search_window_size/2;

			if(start_row_search_index < 0)
				start_row_search_index = 0;

			if(start_col_search_index < 0)
				start_col_search_index = 0;

			if(stop_row_search_index > new_height)
				stop_row_search_index = new_height;

			if(stop_col_search_index > new_width)
				stop_col_search_index = new_width;

			float best_matching_function = 10000;

			MotionVector best_motion_vector;

			//Parse through the search window in previous frame and find the best motion vector
			for(int m=start_row_search_index; m < stop_row_search_index; m++)
			{
				for(int n=start_col_search_index ; n < stop_col_search_index; n++)
				{

					float matching_function = 0.0;

					//Compute Sum of Squared Differences
					for(int q=0; q < block_size; q++)
					{
						for(int r=0 ; r < block_size; r++)
						{

							int current_frame_pixel = currentFrameBlocks[j][i].at<uchar>(q,r);
							int previous_frame_pixel = previous_grayscale_image.at<uchar>(m+q,r+n);

							if(matching_criteria == SAD)
								matching_function += abs(current_frame_pixel - previous_frame_pixel);

							else
								matching_function += sqrt(pow(current_frame_pixel-previous_frame_pixel,2));

							//cout<<"current index q="<<q<<", r= "<<r<<" , value="<<current_frame_pixel<<" previous index m+q="<<m+q<<" ,r+n="<<r+n<<" ,value ="<<previous_frame_pixel<<endl;

						}
					}

					int center_x_search_window = m+block_size/2;
					int center_y_search_window = n+block_size/2;

					//cout<<"search window x = "<<center_x_search_window<<" , y="<<center_y_search_window<<endl;
					//cout<<"block x = "<<center_x<<" , y="<<center_y<<" , ssd="<<ssd<<endl;

					if(matching_function<best_matching_function)
					{
						best_matching_function = matching_function;
						best_motion_vector.vel_y = center_x - center_x_search_window;
						best_motion_vector.vel_x = center_y - center_y_search_window;
					}
				}
			}

			//Fill the values in motion field
			for(int m=start_row_index; m < stop_row_index; m++)
			{
				for(int n=start_col_index ; n < stop_col_index; n++)
				{
					motion_field.set(m,n,best_motion_vector);

				}
			}

			//cout<<"best motion_vector ssd = "<<best_ssd<<" x ="<<best_motion_vector.vel_x<<" , y= "<<best_motion_vector.vel_y<<endl;

			//cout<<"block j="<<j<<" , i= "<<i<<endl;

			//return;

		}

	}

	return motion_field;

}

int main(int argc, char** argv )
{
    Mat grayscale_image1, grayscale_image2;

    Mat image1 = imread( "../images/foreman/fm0001.tif", 1 );
    Mat image2 = imread( "../images/foreman/fm0002.tif", 1 );

    if ( !image1.data || !image2.data )
     {
        printf("No image data \n");
        return -1;
     }

   MotionField motion_field = estimateMotionByBlockMatching(image1,image2,SAD);

   Mat motion_estimated_image = motion_field.getImage();

   //motion_field.print();

   namedWindow("Estimated Motion Field", WINDOW_AUTOSIZE);
   imshow("Estimated Motion Field", motion_estimated_image);
   imwrite( "../results/motion_estimation/foreman/sad/estimated_motion_field.jpg", motion_estimated_image);

    waitKey(0);

    return 0;
}

<|endoftext|>