<commit_before>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2020 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"
#include "str_helpers.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        try
        {
            std::wsregex_iterator next(s.begin(), s.end(), m_re);
            std::wsregex_iterator end;
            while (next != end)
            {
                auto match = *next++;
                if (match.empty())
                    continue;
                int pos = static_cast<int>(match.position());
                highlight(pos, pos + static_cast<int>(match.length()), m_kind);
            }
        }
        catch (std::regex_error& e)
        {
            switch (e.code())
            {
                case std::regex_constants::error_complexity:
                case std::regex_constants::error_stack:
                    // MSVC version of std::regex in particular can fail to match
                    // e.g. HTML regex with backreferences on insanely large strings;
                    // in that case, don't highlight instead of failing outright.
                    return;
                default:
                    throw;
            }
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"((<\/?[a-zA-Z0-9:-]+(\s+[-:\w]+(=([-:\w+]|"[^"]*"|'[^']*'))?)*\s*\/?>)|(&[^ ;]+;))",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

// variables expansion for %foo% (Twig), {foo} and {{foo}}
std::wregex RE_COMMON_PLACEHOLDERS(LR"((%[0-9a-zA-Z_.-]+%)|(\{[0-9a-zA-Z_.-]+\})|(\{\{[0-9a-zA-Z_.-]+\}\}))",
                    std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = std::regex_search(str::to_wstring(item.GetString()), RE_HTML_MARKUP);
    bool needsPlaceholders = std::regex_search(str::to_wstring(item.GetString()), RE_COMMON_PLACEHOLDERS);

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && !needsPlaceholders && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    if (needsPlaceholders)
    {
        // If no format specified, heuristically apply highlighting of common variable markers
        static auto placeholders = std::make_shared<RegexSyntaxHighlighter>(RE_COMMON_PLACEHOLDERS, TextKind::Format);
        all->Add(placeholders);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<commit_msg>Support Ruby placeholders<commit_after>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2020 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"
#include "str_helpers.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        try
        {
            std::wsregex_iterator next(s.begin(), s.end(), m_re);
            std::wsregex_iterator end;
            while (next != end)
            {
                auto match = *next++;
                if (match.empty())
                    continue;
                int pos = static_cast<int>(match.position());
                highlight(pos, pos + static_cast<int>(match.length()), m_kind);
            }
        }
        catch (std::regex_error& e)
        {
            switch (e.code())
            {
                case std::regex_constants::error_complexity:
                case std::regex_constants::error_stack:
                    // MSVC version of std::regex in particular can fail to match
                    // e.g. HTML regex with backreferences on insanely large strings;
                    // in that case, don't highlight instead of failing outright.
                    return;
                default:
                    throw;
            }
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"((<\/?[a-zA-Z0-9:-]+(\s+[-:\w]+(=([-:\w+]|"[^"]*"|'[^']*'))?)*\s*\/?>)|(&[^ ;]+;))",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

// ruby-format per https://ruby-doc.org/core-2.7.1/Kernel.html#method-i-sprintf
std::wregex RE_RUBY_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// variables expansion for %foo% (Twig), %{foo} (Ruby), {foo} and {{foo}}
std::wregex RE_COMMON_PLACEHOLDERS(LR"((%[0-9a-zA-Z_.-]+%)|(%?\{[0-9a-zA-Z_.-]+\})|(\{\{[0-9a-zA-Z_.-]+\}\}))",
                    std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = std::regex_search(str::to_wstring(item.GetString()), RE_HTML_MARKUP);
    bool needsPlaceholders = std::regex_search(str::to_wstring(item.GetString()), RE_COMMON_PLACEHOLDERS);

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && !needsPlaceholders && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    if (needsPlaceholders)
    {
        // If no format specified, heuristically apply highlighting of common variable markers
        static auto placeholders = std::make_shared<RegexSyntaxHighlighter>(RE_COMMON_PLACEHOLDERS, TextKind::Format);
        all->Add(placeholders);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }
    else if (formatFlag == "ruby")
    {
        static auto ruby_format = std::make_shared<RegexSyntaxHighlighter>(RE_RUBY_FORMAT, TextKind::Format);
        all->Add(ruby_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2018 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        std::wsregex_iterator next(s.begin(), s.end(), m_re);
        std::wsregex_iterator end;
        while (next != end)
        {
            auto match = *next++;
            if (match.empty())
                continue;
            int pos = static_cast<int>(match.position());
            highlight(pos, pos + static_cast<int>(match.length()), m_kind);
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"(<\/?[a-zA-Z]+(\s+\w+(=(\w+|"[^"]*"|'[^']*'))?)*\s*\/?>)",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = item.GetString().Contains('<');

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<commit_msg>Fix highlighting of HTML tags with - in attributes<commit_after>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2018 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        std::wsregex_iterator next(s.begin(), s.end(), m_re);
        std::wsregex_iterator end;
        while (next != end)
        {
            auto match = *next++;
            if (match.empty())
                continue;
            int pos = static_cast<int>(match.position());
            highlight(pos, pos + static_cast<int>(match.length()), m_kind);
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"(<\/?[a-zA-Z]+(\s+[-\w]+(=([-\w+]|"[^"]*"|'[^']*'))?)*\s*\/?>)",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = item.GetString().Contains('<');

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <string>

#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>

#include "cyber/common/file.h"
#include "cyber/record/record_reader.h"
#include "cyber/record/record_writer.h"
#include "modules/audio/common/audio_gflags.h"
#include "modules/audio/common/message_process.h"
#include "modules/audio/proto/audio_conf.pb.h"
#include "modules/audio/proto/audio_event.pb.h"
#include "modules/localization/proto/localization.pb.h"
#include "modules/perception/proto/perception_obstacle.pb.h"

namespace apollo {
namespace audio {

using apollo::cyber::record::RecordReader;
using apollo::cyber::record::RecordMessage;
using apollo::cyber::record::RecordWriter;
using apollo::drivers::microphone::config::AudioData;
using apollo::localization::LocalizationEstimate;
using apollo::perception::PerceptionObstacles;

void GetRecordFileNames(const boost::filesystem::path& p,
                        std::vector<std::string>* record_files) {
  if (!boost::filesystem::exists(p)) {
    return;
  }
  if (boost::filesystem::is_regular_file(p)) {
    AINFO << "Found record file: " << p.c_str();
    record_files->push_back(p.c_str());
    return;
  }
  if (boost::filesystem::is_directory(p)) {
    for (auto& entry : boost::make_iterator_range(
             boost::filesystem::directory_iterator(p), {})) {
      GetRecordFileNames(entry.path(), record_files);
    }
  }
}

void ProcessSingleRecordFile(const AudioConf& audio_conf,
    const std::string& input_record_filepath,
    const std::string& output_record_filepath,
    AudioInfo* audio_info,
    DirectionDetection* direction_detection,
    MovingDetection* moving_detection,
    SirenDetection* siren_detection) {
  RecordReader reader(input_record_filepath);
  RecordMessage message;
  RecordWriter writer;
  writer.Open(output_record_filepath);
  while (reader.ReadMessage(&message)) {
    if (message.channel_name ==
        audio_conf.topic_conf().audio_data_topic_name()) {
      AudioData audio_data;
      if (audio_data.ParseFromString(message.content)) {
        AudioDetection audio_detection;
        std::string respeaker_extrinsics_file =
            audio_conf.respeaker_extrinsics_path();
        MessageProcess::OnMicrophone(audio_data, respeaker_extrinsics_file,
            audio_info, direction_detection, moving_detection, siren_detection,
            &audio_detection);
        writer.WriteMessage<AudioDetection>(
            audio_conf.topic_conf().audio_detection_topic_name(),
            audio_detection, message.time);
        AINFO << "Generate a new audio detection message.";
      }
    } else if (message.channel_name ==
               audio_conf.topic_conf().audio_event_topic_name()) {
      AudioEvent audio_event;
      if (audio_event.ParseFromString(message.content)) {
        writer.WriteMessage<AudioEvent>(message.channel_name, audio_event,
                                        message.time);
        AINFO << "Save an audio even message.";
      } else if (message.channel_name ==
                 audio_conf.topic_conf().localization_topic_name()) {
        LocalizationEstimate localization;
        if (localization.ParseFromString(message.content)) {
          writer.WriteMessage<LocalizationEstimate>(
              message.channel_name, localization, message.time);
          AINFO << "Save a localization message.";
        }
      } else if (message.channel_name ==
                 audio_conf.topic_conf().perception_topic_name()) {
        PerceptionObstacles perception_obstacles;
        if (perception_obstacles.ParseFromString(message.content)) {
          writer.WriteMessage<PerceptionObstacles>(
              message.channel_name, perception_obstacles, message.time);
          AINFO << "Save a perception message.";
        }
      }
    }
  }
  writer.Close();
}

void ProcessFolder() {
  if (FLAGS_audio_records_dir.empty()) {
    AERROR << "The input folder is empty";
    return;
  }
  AudioConf audio_conf;
  if (!cyber::common::GetProtoFromFile(FLAGS_audio_conf_file,
                                       &audio_conf)) {
    return;
  }
  AudioInfo audio_info;
  DirectionDetection direction_detection;
  MovingDetection moving_detection;
  SirenDetection siren_detection;
  std::vector<std::string> offline_bags;
  GetRecordFileNames(boost::filesystem::path(FLAGS_audio_records_dir),
                     &offline_bags);
  std::sort(offline_bags.begin(), offline_bags.end());
  for (std::size_t i = 0; i < offline_bags.size(); ++i) {
    const std::string& input_record_filepath = offline_bags[i];
    std::string output_record_filepath =
        input_record_filepath + ".new_audio_detection";
    ProcessSingleRecordFile(audio_conf, input_record_filepath,
        output_record_filepath, &audio_info, &direction_detection,
        &moving_detection, &siren_detection);
  }
}

}  // namespace audio
}  // namespace apollo

int main(int argc, char* argv[]) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  apollo::audio::ProcessFolder();
  return 0;
}
<commit_msg>audio: fix if else indention<commit_after>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <string>

#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>

#include "cyber/common/file.h"
#include "cyber/record/record_reader.h"
#include "cyber/record/record_writer.h"
#include "modules/audio/common/audio_gflags.h"
#include "modules/audio/common/message_process.h"
#include "modules/audio/proto/audio_conf.pb.h"
#include "modules/audio/proto/audio_event.pb.h"
#include "modules/localization/proto/localization.pb.h"
#include "modules/perception/proto/perception_obstacle.pb.h"

namespace apollo {
namespace audio {

using apollo::cyber::record::RecordReader;
using apollo::cyber::record::RecordMessage;
using apollo::cyber::record::RecordWriter;
using apollo::drivers::microphone::config::AudioData;
using apollo::localization::LocalizationEstimate;
using apollo::perception::PerceptionObstacles;

void GetRecordFileNames(const boost::filesystem::path& p,
                        std::vector<std::string>* record_files) {
  if (!boost::filesystem::exists(p)) {
    return;
  }
  if (boost::filesystem::is_regular_file(p)) {
    AINFO << "Found record file: " << p.c_str();
    record_files->push_back(p.c_str());
    return;
  }
  if (boost::filesystem::is_directory(p)) {
    for (auto& entry : boost::make_iterator_range(
             boost::filesystem::directory_iterator(p), {})) {
      GetRecordFileNames(entry.path(), record_files);
    }
  }
}

void ProcessSingleRecordFile(const AudioConf& audio_conf,
    const std::string& input_record_filepath,
    const std::string& output_record_filepath,
    AudioInfo* audio_info,
    DirectionDetection* direction_detection,
    MovingDetection* moving_detection,
    SirenDetection* siren_detection) {
  RecordReader reader(input_record_filepath);
  RecordMessage message;
  RecordWriter writer;
  writer.Open(output_record_filepath);
  while (reader.ReadMessage(&message)) {
    if (message.channel_name ==
        audio_conf.topic_conf().audio_data_topic_name()) {
      AudioData audio_data;
      if (audio_data.ParseFromString(message.content)) {
        AudioDetection audio_detection;
        std::string respeaker_extrinsics_file =
            audio_conf.respeaker_extrinsics_path();
        MessageProcess::OnMicrophone(audio_data, respeaker_extrinsics_file,
            audio_info, direction_detection, moving_detection, siren_detection,
            &audio_detection);
        writer.WriteMessage<AudioDetection>(
            audio_conf.topic_conf().audio_detection_topic_name(),
            audio_detection, message.time);
        AINFO << "Generate a new audio detection message.";
      }
    } else if (message.channel_name ==
               audio_conf.topic_conf().audio_event_topic_name()) {
      AudioEvent audio_event;
      if (audio_event.ParseFromString(message.content)) {
        writer.WriteMessage<AudioEvent>(message.channel_name, audio_event,
                                        message.time);
        AINFO << "Save an audio even message.";
      }
    } else if (message.channel_name ==
                 audio_conf.topic_conf().localization_topic_name()) {
      LocalizationEstimate localization;
      if (localization.ParseFromString(message.content)) {
        writer.WriteMessage<LocalizationEstimate>(
            message.channel_name, localization, message.time);
        AINFO << "Save a localization message.";
      }
    } else if (message.channel_name ==
                 audio_conf.topic_conf().perception_topic_name()) {
      PerceptionObstacles perception_obstacles;
      if (perception_obstacles.ParseFromString(message.content)) {
        writer.WriteMessage<PerceptionObstacles>(
            message.channel_name, perception_obstacles, message.time);
        AINFO << "Save a perception message.";
      }
    }
  }
  writer.Close();
}

void ProcessFolder() {
  if (FLAGS_audio_records_dir.empty()) {
    AERROR << "The input folder is empty";
    return;
  }
  AudioConf audio_conf;
  if (!cyber::common::GetProtoFromFile(FLAGS_audio_conf_file,
                                       &audio_conf)) {
    return;
  }
  AudioInfo audio_info;
  DirectionDetection direction_detection;
  MovingDetection moving_detection;
  SirenDetection siren_detection;
  std::vector<std::string> offline_bags;
  GetRecordFileNames(boost::filesystem::path(FLAGS_audio_records_dir),
                     &offline_bags);
  std::sort(offline_bags.begin(), offline_bags.end());
  for (std::size_t i = 0; i < offline_bags.size(); ++i) {
    const std::string& input_record_filepath = offline_bags[i];
    std::string output_record_filepath =
        input_record_filepath + ".new_audio_detection";
    ProcessSingleRecordFile(audio_conf, input_record_filepath,
        output_record_filepath, &audio_info, &direction_detection,
        &moving_detection, &siren_detection);
  }
}

}  // namespace audio
}  // namespace apollo

int main(int argc, char* argv[]) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  apollo::audio::ProcessFolder();
  return 0;
}
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>

#include <Observation.hpp>

#ifndef GENERATOR_HPP
#define GENERATOR_HPP

namespace AstroData {

template< typename T > void generatePulsar(const unsigned int period, const unsigned int width, const float DM, const AstroData::Observation & observation, std::vector< std::vector< T > * > & data, const bool random = false);

// Implementations
template< typename T > void generatePulsar(const unsigned int period, const unsigned int width, const float DM, const AstroData::Observation & observation, std::vector< std::vector< T > * > & data, const bool random) {
  std::srand(std::time(0));
  // Generate the  "noise"
  for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
    data[second] = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
    if ( random ) {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + sample) = std::rand() % 100;
        }
      }
    } else {
      std::fill(data[second]->begin(), data[second]->end(), 1);
    }
  }
  // Generate the pulsar
	float inverseHighFreq = 1.0f / (observation.getMaxFreq() * observation.getMaxFreq());
  float kDM = 4148.808f * DM;
  for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
    float inverseFreq = 1.0f / ((observation.getMinFreq() + (channel * observation.getChannelBandwidth())) * (observation.getMinFreq() + (channel * observation.getChannelBandwidth())));
    float delta = kDM * (inverseFreq - inverseHighFreq);
    unsigned int shift = static_cast< unsigned int >(delta * observation.getNrSamplesPerSecond());

    for ( unsigned int sample = shift; sample < observation.getNrSeconds() * observation.getNrSamplesPerSecond(); sample += period ) {
      for ( unsigned int i = 0; i < width; i++ ) {
        if ( sample + i >= observation.getNrSeconds() * observation.getNrSamplesPerSecond() ) {
        break;
        }
        unsigned int second = (sample + i) / observation.getNrSamplesPerSecond();
        unsigned int internalSample = (sample + i) % observation.getNrSamplesPerSecond();

        if ( random ) {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + internalSample) = std::rand() % 10000;
        } else {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + internalSample) = 42;
        }
      }
    }
  }
}

} // AstroData

#endif // GENERATOR_HPP

<commit_msg>New values, less skewedness.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>

#include <Observation.hpp>

#ifndef GENERATOR_HPP
#define GENERATOR_HPP

namespace AstroData {

template< typename T > void generatePulsar(const unsigned int period, const unsigned int width, const float DM, const AstroData::Observation & observation, std::vector< std::vector< T > * > & data, const bool random = false);

// Implementations
template< typename T > void generatePulsar(const unsigned int period, const unsigned int width, const float DM, const AstroData::Observation & observation, std::vector< std::vector< T > * > & data, const bool random) {
  std::srand(std::time(0));
  // Generate the  "noise"
  for ( unsigned int second = 0; second < observation.getNrSeconds(); second++ ) {
    data[second] = new std::vector< T >(observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond());
    if ( random ) {
      for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
        for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + sample) = std::rand() % 100;
        }
      }
    } else {
      std::fill(data[second]->begin(), data[second]->end(), 8);
    }
  }
  // Generate the pulsar
	float inverseHighFreq = 1.0f / (observation.getMaxFreq() * observation.getMaxFreq());
  float kDM = 4148.808f * DM;
  for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
    float inverseFreq = 1.0f / ((observation.getMinFreq() + (channel * observation.getChannelBandwidth())) * (observation.getMinFreq() + (channel * observation.getChannelBandwidth())));
    float delta = kDM * (inverseFreq - inverseHighFreq);
    unsigned int shift = static_cast< unsigned int >(delta * observation.getNrSamplesPerSecond());

    for ( unsigned int sample = shift; sample < observation.getNrSeconds() * observation.getNrSamplesPerSecond(); sample += period ) {
      for ( unsigned int i = 0; i < width; i++ ) {
        if ( sample + i >= observation.getNrSeconds() * observation.getNrSamplesPerSecond() ) {
        break;
        }
        unsigned int second = (sample + i) / observation.getNrSamplesPerSecond();
        unsigned int internalSample = (sample + i) % observation.getNrSamplesPerSecond();

        if ( random ) {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + internalSample) = std::rand() % 500;
        } else {
          data[second]->at((channel * observation.getNrSamplesPerPaddedSecond()) + internalSample) = 42;
        }
      }
    }
  }
}

} // AstroData

#endif // GENERATOR_HPP

<|endoftext|>


<commit_before>/*********************************************************************************
*
* Inviwo - Interactive Visualization Workshop
*
* Copyright (c) 2012-2018 Inviwo Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************/

#pragma once

#include "datachannel.h"
#include "bufferchannel.h"

namespace inviwo {
namespace dd {

template<typename T, ind N>
T* BufferGetter<T, N>::get(ind index) {
    auto& buffer = dynamic_cast<BufferChannel<T, N>&>(*this->parent_);
    std::array<T, N>& data = buffer.template get<std::array<T, N>>(index);
    return reinterpret_cast<T*>(&data);
}

template<typename T, ind N>
const T* BufferGetter<T, N>::get(ind index) const {
    const auto& buffer = dynamic_cast<const BufferChannel<T, N>&>(*this->parent_);
    const std::array<T, N>& data = buffer.template get<std::array<T, N>>(index);
    return reinterpret_cast<const T*>(&data);
}

template<typename T, ind N>
ChannelGetter<T, N>* BufferGetter<T, N>::New() const  {
    return new BufferGetter<T, N>(dynamic_cast<BufferChannel<T, N>*>(this->parent_));
}

template<typename T, ind N>
T* CachedGetter<T, N>::get(ind index) {
    ivwAssert(this->parent_, "No channel to iterate is set.");

    // No buffer, evaluate analytics.
    // Is the data up to date?
    if (DataIndex != index) {
        delete Data;
        Data = new std::array<T,N>();
        // Note: we could use the old memory again, but numCOmponents might change (improbable).
        // Also, we want segfaults when old data is accessed.

        this->parent_->fill(*Data, index);
        DataIndex = index;
    }

    // Always return data.
    // If the iterator is changed and dereferenced, the pointer becomes invalid.
    return reinterpret_cast<T*>(Data);
}

template<typename T, ind N>
const T* CachedGetter<T, N>::get(ind index) const {
    ivwAssert(this->parent_, "No channel to iterate is set.");

    // No buffer, evaluate analytics.
    // Is the data up to date?
    if (DataIndex != index) {
        delete Data;
        Data = new std::array<T,N>();
        // Note: we could use the old memory again, but numCOmponents might change (improbable).
        // Also, we want segfaults when old data is accessed.

        this->parent_->fill(Data, index);
        DataIndex = index;
    }

    // Always return data.
    // If the iterator is changed and dereferenced, the pointer becomes invalid.
    return reinterpret_cast<T*>(Data);
}

}  // namespace
}<commit_msg>Fixing/simplifying buffer access by friending BufferGetter and BufferChannel<commit_after>/*********************************************************************************
*
* Inviwo - Interactive Visualization Workshop
*
* Copyright (c) 2012-2018 Inviwo Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************/

#pragma once

#include "datachannel.h"
#include "bufferchannel.h"

namespace inviwo {
namespace dd {

template<typename T, ind N>
T* BufferGetter<T, N>::get(ind index) {
    auto& buffer = dynamic_cast<BufferChannel<T, N>&>(*this->parent_);
    T& data = buffer.buffer_[index * N];
    return &data;
}

template<typename T, ind N>
const T* BufferGetter<T, N>::get(ind index) const {
    const BufferChannel<T, N>& buffer = dynamic_cast<const BufferChannel<T, N>&>(*this->parent_);
    const T& data = buffer.buffer_[index * N];
    return &data;
}

template<typename T, ind N>
ChannelGetter<T, N>* BufferGetter<T, N>::New() const  {
    return new BufferGetter<T, N>(dynamic_cast<BufferChannel<T, N>*>(this->parent_));
}

template<typename T, ind N>
T* CachedGetter<T, N>::get(ind index) {
    ivwAssert(this->parent_, "No channel to iterate is set.");

    // No buffer, evaluate analytics.
    // Is the data up to date?
    if (DataIndex != index) {
        delete Data;
        Data = new std::array<T,N>();
        // Note: we could use the old memory again, but numCOmponents might change (improbable).
        // Also, we want segfaults when old data is accessed.

        this->parent_->fill(*Data, index);
        DataIndex = index;
    }

    // Always return data.
    // If the iterator is changed and dereferenced, the pointer becomes invalid.
    return reinterpret_cast<T*>(Data);
}

template<typename T, ind N>
const T* CachedGetter<T, N>::get(ind index) const {
    ivwAssert(this->parent_, "No channel to iterate is set.");

    // No buffer, evaluate analytics.
    // Is the data up to date?
    if (DataIndex != index) {
        delete Data;
        Data = new std::array<T,N>();
        // Note: we could use the old memory again, but numCOmponents might change (improbable).
        // Also, we want segfaults when old data is accessed.

        this->parent_->fill(*Data, index);
        DataIndex = index;
    }

    // Always return data.
    // If the iterator is changed and dereferenced, the pointer becomes invalid.
    return reinterpret_cast<T*>(Data);
}

}  // namespace
}<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef AST_WHILE_H
#define AST_WHILE_H

#include <vector>

#include <boost/fusion/include/adapt_struct.hpp>

#include "ast/Node.hpp"
#include "ast/While.hpp"
#include "ast/Condition.hpp"

namespace eddic {

struct ASTWhile : public virtual Node {
    ASTCondition condition;
    std::vector<ASTInstruction> instructions;
};

} //end of eddic

//Adapt the struct for the AST
BOOST_FUSION_ADAPT_STRUCT(
    eddic::ASTWhile,
    (eddic::ASTCondition, condition)
    (std::vector<eddic::ASTInstruction>, instructions)
)

#endif
<commit_msg>context is not necessary for a while node<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef AST_WHILE_H
#define AST_WHILE_H

#include <vector>

#include <boost/fusion/include/adapt_struct.hpp>

#include "ast/While.hpp"
#include "ast/Condition.hpp"

namespace eddic {

struct ASTWhile {
    ASTCondition condition;
    std::vector<ASTInstruction> instructions;
};

} //end of eddic

//Adapt the struct for the AST
BOOST_FUSION_ADAPT_STRUCT(
    eddic::ASTWhile,
    (eddic::ASTCondition, condition)
    (std::vector<eddic::ASTInstruction>, instructions)
)

#endif
<|endoftext|>


<commit_before>#include <math.h>
#include <stdlib.h>

#include "simulator.h"
#include "network_model_analytical.h"
#include "network_model_analytical_params.h"
#include "message_types.h"
#include "config.h"
#include "core.h"
#include "performance_model.h"
#include "transport.h"
#include "lock.h"
#include "log.h"

#define IS_NAN(x) (!((x < 0.0) || (x >= 0.0)))

#define GET_INT(s) ( Sim()->getCfg()->getInt("network/analytical/" s) )

using namespace std;

NetworkModelAnalytical::NetworkModelAnalytical(Network *net, EStaticNetwork net_type)
      : NetworkModel(net)
      , _bytesSent(0)
      , _cyclesProc(0)
      , _cyclesLatency(0)
      , _cyclesContention(0)
      , _globalUtilization(0)
      , _localUtilizationLastUpdate(0)
      , _localUtilizationFlitsSent(0)
      , m_enabled(true)
{
   getNetwork()->registerCallback(MCP_UTILIZATION_UPDATE_TYPE,
                                  receiveMCPUpdate,
                                  this);

   try
     {
       // Create network parameters
       m_params.Tw2 = GET_INT("Tw2"); // single cycle between nodes in 2d mesh
       m_params.s = GET_INT("s"); // single cycle switching time
       m_params.n = GET_INT("n"); // 2-d mesh network
       m_params.W = GET_INT("W"); // 32-bit wide channels
       m_params.update_interval = GET_INT("update_interval");
       m_params.proc_cost = (net_type == STATIC_NETWORK_MEMORY) ? 0 : GET_INT("processing_cost");
     }
   catch (...)
     {
       LOG_PRINT_ERROR("Some analytical network parameters not available.");
     }
}

NetworkModelAnalytical::~NetworkModelAnalytical()
{
   getNetwork()->unregisterCallback(MCP_UTILIZATION_UPDATE_TYPE);
}

void NetworkModelAnalytical::routePacket(const NetPacket &pkt,
      std::vector<Hop> &nextHops)
{
   ScopedLock sl(_lock);

   // basic magic network routing, with two additions
   // (1) compute latency of packet
   // (2) update utilization

   PerformanceModel *perf = getNetwork()->getCore()->getPerformanceModel();

   Hop h;
   h.dest = pkt.receiver;

   UInt64 network_latency = computeLatency(pkt);
   LOG_PRINT ("Network Latency = %llu", network_latency);
   h.time = pkt.time + network_latency;

   nextHops.push_back(h);

   if (m_params.proc_cost > 0)
      perf->queueDynamicInstruction(new DynamicInstruction(m_params.proc_cost));
   _cyclesProc += m_params.proc_cost;

   updateUtilization();

   _bytesSent += pkt.length;
}

UInt64 NetworkModelAnalytical::computeLatency(const NetPacket &packet)
{
   if (!m_enabled)
      return 0;

   // self-sends incur no cost
   if (packet.sender == packet.receiver)
     return 0;

   // We model a unidirectional network with end-around connections
   // using the network model in "Limits on Interconnect Performance"
   // (by Anant). Currently, this ignores communication locality and
   // sets static values for all parameters. We also assume uniform
   // packet distribution, so we do not take the packet destination
   // into account.
   //
   // We combine the contention model (eq. 12) with the model for
   // limited bisection width (sec. 4.2).

   // TODO: Fix (if necessary) distance calculation for uneven
   // topologies, i.e. 8-node 2d mesh or 10-node 3d mesh.

   // TODO: Confirm model for latency computed based on actual number
   // of network hops.

   // Retrieve parameters
   double Tw2 = m_params.Tw2;
   double s = m_params.s;
   int n = m_params.n;
   double W = m_params.W;
   double p = _globalUtilization;
   LOG_ASSERT_ERROR(!IS_NAN(_globalUtilization) && 0 <= _globalUtilization && _globalUtilization < 1, "Recv'd invalid global utilization value: %f", _globalUtilization);

   // This lets us derive the latency, ignoring contention

   int N;                    // number of nodes in the network
   double k;                 // length of mesh in one dimension
   double kd;                // number of hops per dimension
   double time_per_hop;      // time spent in one hop through the network
   double B;                 // number of flits for packet
   double hops_in_network;   // number of nodes visited
   double Tb;                // latency, without contention

   N = Config::getSingleton()->getTotalCores();
   k = pow(N, 1./n);                  // pg 5
   kd = k/2.;                         // pg 5 (note this will be
   // different for different network configurations...say,
   // bidirectional networks)
   time_per_hop = s + pow(k, n/2.-1.);  // pg 6
   B = ceil(packet.length * 8. / W);

   // Compute the number of hops based on src, dest
   // Based on this eqn:
   // node number = x1 + x2 k + x3 k^2 + ... + xn k^(n-1)
   int network_distance = 0;
   int src = packet.sender;
   int dest = packet.receiver;
   int ki = (int)k;
   for (int i = 0; i < n; i++)
   {
      div_t q1, q2;
      q1 = div(src, ki);
      q2 = div(dest, ki);
      // This models a unidirectional network distance
      // Should use abs() for bidirectional.
      if (q1.rem > q2.rem)
         network_distance += ki - (q1.rem - q2.rem);
      else
         network_distance += q2.rem - q1.rem;
      src = q1.quot;
      dest = q2.quot;
   }
   hops_in_network = network_distance + B; // B flits must be sent
   // (with wormhole routing, this adds B hops)

   Tb = Tw2 * time_per_hop * hops_in_network; // pg 5

   // Now to model contention... (sec 3.2)
   double w;                 // delay due to contention

   w  = p * B / (1. - p);
   w *= (kd-1.)/(kd*kd);
   w *= 1.+1./((double)n);

   if (w < 0) w = 0; // correct negative contention values for small
   // networks

   double hops_with_contention;
   double Tc;                // latency, with contention
   hops_with_contention = network_distance * (1. + w) + B;
   Tc = Tw2 * time_per_hop * hops_with_contention;

   // Computation finished...
   UInt64 Tci = (UInt64)(ceil(Tc));
   _cyclesLatency += Tci;
   _cyclesContention += (UInt64)(Tc - Tb);

   // ** update utilization counter **
   // we must account for the usage throughout the mesh
   // which means that we must include the # of hops
   _localUtilizationFlitsSent += (UInt64)(B * hops_in_network);

   return Tci;
}

void NetworkModelAnalytical::outputSummary(ostream &out)
{
   out << "    bytes sent: " << _bytesSent << endl;
   out << "    cycles spent proc: " << _cyclesProc << endl;
   out << "    cycles spent latency: " << _cyclesLatency << endl;
   out << "    cycles spent contention: " << _cyclesContention << endl;
}

struct UtilizationMessage
{
   double ut;
   NetworkModelAnalytical *model;
};

struct UtilizationMCPMessage
{
   int msg_type;
   UtilizationMessage msg;
};

// we send and receive updates asynchronously for performance and
// because the MCP is unable to reply to itself.

void NetworkModelAnalytical::updateUtilization()
{
   // ** send updates

   // don't lock because this is all approximate anyway
   UInt64 core_time = getNetwork()->getCore()->getPerformanceModel()->getCycleCount();
   UInt64 elapsed_time = core_time - _localUtilizationLastUpdate;

   if (elapsed_time < m_params.update_interval)
      return;

   // FIXME: This assumes one cycle per flit, might not be accurate.
   double local_utilization = ((double)_localUtilizationFlitsSent) / ((double)elapsed_time);

   LOG_ASSERT_WARNING(0 <= local_utilization && local_utilization < 1, "Unusual local utilization value: %f", local_utilization);

   _localUtilizationLastUpdate = core_time;
   _localUtilizationFlitsSent = 0;

   // build packet
   UtilizationMCPMessage m;
   m.msg_type = MCP_MESSAGE_UTILIZATION_UPDATE;
   m.msg.ut = local_utilization;
   m.msg.model = this;

   NetPacket update;
   update.sender = getNetwork()->getCore()->getId();
   update.receiver = Config::getSingleton()->getMCPCoreNum();
   update.length = sizeof(m);
   update.type = MCP_SYSTEM_TYPE;
   update.data = &m;

//   getNetwork()->netSend(update);
}

void NetworkModelAnalytical::receiveMCPUpdate(void *obj, NetPacket response)
{
   assert(response.length == sizeof(UtilizationMessage));

   UtilizationMessage *pr = (UtilizationMessage*) response.data;

   ScopedLock sl(pr->model->_lock);

   LOG_ASSERT_ERROR(!IS_NAN(pr->ut) && 0 <= pr->ut && pr->ut < 1, "Recv'd invalid global utilization value: %f", pr->ut);
//   fprintf(stderr, "Recv'd global utilization: %f\n", pr->ut);

   pr->model->_globalUtilization = pr->ut;
}

void NetworkModelAnalytical::enable()
{
   m_enabled = true;
}

void NetworkModelAnalytical::disable()
{
   m_enabled = false;
}
<commit_msg>[network model] Changes to network_model_analytical.cc for supporting 2 shared mem networks<commit_after>#include <math.h>
#include <stdlib.h>

#include "simulator.h"
#include "network_model_analytical.h"
#include "network_model_analytical_params.h"
#include "message_types.h"
#include "config.h"
#include "core.h"
#include "performance_model.h"
#include "transport.h"
#include "lock.h"
#include "log.h"

#define IS_NAN(x) (!((x < 0.0) || (x >= 0.0)))

#define GET_INT(s) ( Sim()->getCfg()->getInt("network/analytical/" s) )

using namespace std;

NetworkModelAnalytical::NetworkModelAnalytical(Network *net, EStaticNetwork net_type)
      : NetworkModel(net)
      , _bytesSent(0)
      , _cyclesProc(0)
      , _cyclesLatency(0)
      , _cyclesContention(0)
      , _globalUtilization(0)
      , _localUtilizationLastUpdate(0)
      , _localUtilizationFlitsSent(0)
      , m_enabled(true)
{
   getNetwork()->registerCallback(MCP_UTILIZATION_UPDATE_TYPE,
                                  receiveMCPUpdate,
                                  this);

   try
     {
       // Create network parameters
       m_params.Tw2 = GET_INT("Tw2"); // single cycle between nodes in 2d mesh
       m_params.s = GET_INT("s"); // single cycle switching time
       m_params.n = GET_INT("n"); // 2-d mesh network
       m_params.W = GET_INT("W"); // 32-bit wide channels
       m_params.update_interval = GET_INT("update_interval");
       m_params.proc_cost = (net_type == STATIC_NETWORK_MEMORY_NET1) ? 0 : GET_INT("processing_cost");
     }
   catch (...)
     {
       LOG_PRINT_ERROR("Some analytical network parameters not available.");
     }
}

NetworkModelAnalytical::~NetworkModelAnalytical()
{
   getNetwork()->unregisterCallback(MCP_UTILIZATION_UPDATE_TYPE);
}

void NetworkModelAnalytical::routePacket(const NetPacket &pkt,
      std::vector<Hop> &nextHops)
{
   ScopedLock sl(_lock);

   // basic magic network routing, with two additions
   // (1) compute latency of packet
   // (2) update utilization

   PerformanceModel *perf = getNetwork()->getCore()->getPerformanceModel();

   Hop h;
   h.dest = pkt.receiver;

   UInt64 network_latency = computeLatency(pkt);
   LOG_PRINT ("Network Latency = %llu", network_latency);
   h.time = pkt.time + network_latency;

   nextHops.push_back(h);

   if (m_params.proc_cost > 0)
      perf->queueDynamicInstruction(new DynamicInstruction(m_params.proc_cost));
   _cyclesProc += m_params.proc_cost;

   updateUtilization();

   _bytesSent += pkt.length;
}

UInt64 NetworkModelAnalytical::computeLatency(const NetPacket &packet)
{
   if (!m_enabled)
      return 0;

   // self-sends incur no cost
   if (packet.sender == packet.receiver)
     return 0;

   // We model a unidirectional network with end-around connections
   // using the network model in "Limits on Interconnect Performance"
   // (by Anant). Currently, this ignores communication locality and
   // sets static values for all parameters. We also assume uniform
   // packet distribution, so we do not take the packet destination
   // into account.
   //
   // We combine the contention model (eq. 12) with the model for
   // limited bisection width (sec. 4.2).

   // TODO: Fix (if necessary) distance calculation for uneven
   // topologies, i.e. 8-node 2d mesh or 10-node 3d mesh.

   // TODO: Confirm model for latency computed based on actual number
   // of network hops.

   // Retrieve parameters
   double Tw2 = m_params.Tw2;
   double s = m_params.s;
   int n = m_params.n;
   double W = m_params.W;
   double p = _globalUtilization;
   LOG_ASSERT_ERROR(!IS_NAN(_globalUtilization) && 0 <= _globalUtilization && _globalUtilization < 1, "Recv'd invalid global utilization value: %f", _globalUtilization);

   // This lets us derive the latency, ignoring contention

   int N;                    // number of nodes in the network
   double k;                 // length of mesh in one dimension
   double kd;                // number of hops per dimension
   double time_per_hop;      // time spent in one hop through the network
   double B;                 // number of flits for packet
   double hops_in_network;   // number of nodes visited
   double Tb;                // latency, without contention

   N = Config::getSingleton()->getTotalCores();
   k = pow(N, 1./n);                  // pg 5
   kd = k/2.;                         // pg 5 (note this will be
   // different for different network configurations...say,
   // bidirectional networks)
   time_per_hop = s + pow(k, n/2.-1.);  // pg 6
   B = ceil(packet.length * 8. / W);

   // Compute the number of hops based on src, dest
   // Based on this eqn:
   // node number = x1 + x2 k + x3 k^2 + ... + xn k^(n-1)
   int network_distance = 0;
   int src = packet.sender;
   int dest = packet.receiver;
   int ki = (int)k;
   for (int i = 0; i < n; i++)
   {
      div_t q1, q2;
      q1 = div(src, ki);
      q2 = div(dest, ki);
      // This models a unidirectional network distance
      // Should use abs() for bidirectional.
      if (q1.rem > q2.rem)
         network_distance += ki - (q1.rem - q2.rem);
      else
         network_distance += q2.rem - q1.rem;
      src = q1.quot;
      dest = q2.quot;
   }
   hops_in_network = network_distance + B; // B flits must be sent
   // (with wormhole routing, this adds B hops)

   Tb = Tw2 * time_per_hop * hops_in_network; // pg 5

   // Now to model contention... (sec 3.2)
   double w;                 // delay due to contention

   w  = p * B / (1. - p);
   w *= (kd-1.)/(kd*kd);
   w *= 1.+1./((double)n);

   if (w < 0) w = 0; // correct negative contention values for small
   // networks

   double hops_with_contention;
   double Tc;                // latency, with contention
   hops_with_contention = network_distance * (1. + w) + B;
   Tc = Tw2 * time_per_hop * hops_with_contention;

   // Computation finished...
   UInt64 Tci = (UInt64)(ceil(Tc));
   _cyclesLatency += Tci;
   _cyclesContention += (UInt64)(Tc - Tb);

   // ** update utilization counter **
   // we must account for the usage throughout the mesh
   // which means that we must include the # of hops
   _localUtilizationFlitsSent += (UInt64)(B * hops_in_network);

   return Tci;
}

void NetworkModelAnalytical::outputSummary(ostream &out)
{
   out << "    bytes sent: " << _bytesSent << endl;
   out << "    cycles spent proc: " << _cyclesProc << endl;
   out << "    cycles spent latency: " << _cyclesLatency << endl;
   out << "    cycles spent contention: " << _cyclesContention << endl;
}

struct UtilizationMessage
{
   double ut;
   NetworkModelAnalytical *model;
};

struct UtilizationMCPMessage
{
   int msg_type;
   UtilizationMessage msg;
};

// we send and receive updates asynchronously for performance and
// because the MCP is unable to reply to itself.

void NetworkModelAnalytical::updateUtilization()
{
   // ** send updates

   // don't lock because this is all approximate anyway
   UInt64 core_time = getNetwork()->getCore()->getPerformanceModel()->getCycleCount();
   UInt64 elapsed_time = core_time - _localUtilizationLastUpdate;

   if (elapsed_time < m_params.update_interval)
      return;

   // FIXME: This assumes one cycle per flit, might not be accurate.
   double local_utilization = ((double)_localUtilizationFlitsSent) / ((double)elapsed_time);

   LOG_ASSERT_WARNING(0 <= local_utilization && local_utilization < 1, "Unusual local utilization value: %f", local_utilization);

   _localUtilizationLastUpdate = core_time;
   _localUtilizationFlitsSent = 0;

   // build packet
   UtilizationMCPMessage m;
   m.msg_type = MCP_MESSAGE_UTILIZATION_UPDATE;
   m.msg.ut = local_utilization;
   m.msg.model = this;

   NetPacket update;
   update.sender = getNetwork()->getCore()->getId();
   update.receiver = Config::getSingleton()->getMCPCoreNum();
   update.length = sizeof(m);
   update.type = MCP_SYSTEM_TYPE;
   update.data = &m;

//   getNetwork()->netSend(update);
}

void NetworkModelAnalytical::receiveMCPUpdate(void *obj, NetPacket response)
{
   assert(response.length == sizeof(UtilizationMessage));

   UtilizationMessage *pr = (UtilizationMessage*) response.data;

   ScopedLock sl(pr->model->_lock);

   LOG_ASSERT_ERROR(!IS_NAN(pr->ut) && 0 <= pr->ut && pr->ut < 1, "Recv'd invalid global utilization value: %f", pr->ut);
//   fprintf(stderr, "Recv'd global utilization: %f\n", pr->ut);

   pr->model->_globalUtilization = pr->ut;
}

void NetworkModelAnalytical::enable()
{
   m_enabled = true;
}

void NetworkModelAnalytical::disable()
{
   m_enabled = false;
}
<|endoftext|>


<commit_before>
#pragma once

#include "data_model.hpp"

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <map>
#include <sstream>
#include <string>
#include <optional>

namespace verilog
{
  namespace bdd {
    using std::vector;

    struct Node {
      /**
       * Index of the node's input in the symbol table
       * s == 0 -> for the special node 0.
       * s == 1 -> for the special node 1.
       * s >= 2 -> for any regular variable.
       */
      const int s;

      /**
       * If this node is a representative, r_t stores it.
       */
      std::optional<int>  r_t;
      /**
       * The positive edge for this node.
       */
      Node * p;
      /**
       * The negative edge for this node.
       */
      Node * n;

      Node(const int s_, const int r_t_, Node * p_, Node * n_):
        s(s_), r_t(r_t_), p(p_), n(n_)
      {}

      Node(const int s_, Node * p_, Node * n_):
        s(s_), p(p_), n(n_)
      {}

      /**
       * This constructor should only be used to build zero or one
       */
      Node(const int s_): s(s_)
        {
            p = this;
            n = this;
        }

    };

    struct BDD {
      //vector<Node> graph;
      Node * zero;
      Node * one;
      vector<vector<Node*>> layers;
      int index = 2;
      std::map<std::string, int> symbol_table;
      std::map<int, std::string> symbol_table_rev;

      int number_of_nodes = 0;

      BDD():zero(new Node(0)), one(new Node(1)), layers(2) {
        layers[0].push_back(zero);
        layers[1].push_back(one);
        symbol_table_rev[0] = "Zero";
        symbol_table_rev[1] = "One";
      }

      Node * add_simple_input(const std::string & variable) {
        auto x = symbol_table.find(variable);
        if(x == symbol_table.end()) {
          symbol_table[variable] = index++;
        }
        int s = symbol_table[variable];
        symbol_table_rev[s] = variable;
        return create_node(s, s, one, zero);
      }

      Node * negate(Node * x) {
        if(x == zero) return one;
        if(x == one) return zero;

        return create_node(x->s, negate(x->p), negate(x->n));
      }

      Node * land(Node * x, Node * y) {
        if(x == one) return copy_of(y);
        if(y == one) return copy_of(x);
        if(x == zero) return zero;
        if(y == zero) return zero;

        if(x->s == y->s) {
          Node * p = land(x->p, y->p);
          Node * n = land(x->n, y->n);
          return create_node(x->s, p, n);
        }
        else if(x->s > y->s) {
          Node * p = land(x->p, y);
          Node * n = land(x->n, y);
          return create_node(x->s, p, n);
        }
        else { // x < y
          Node * p = land(y->p, x);
          Node * n = land(y->n, x);
          return create_node(y->s, p, n);
        }
      }

      Node * copy_of(Node * x) {
        return x;
        // TODO check if this is good or bad.
        //return create_node(x->s, x->p, x->n);
      }

      Node * lor(Node * x, Node * y) {
        if(x == one) return one;
        if(y == one) return one;
        if(x == zero) return copy_of(y);
        if(y == zero) return copy_of(x);

        if(x->s == y->s) {
          Node * p = lor(x->p, y->p);
          Node * n = lor(x->n, y->n);
          return create_node(x->s, p, n);
        }
        else if(x->s > y->s) {
          Node * p = lor(x->p, y);
          Node * n = lor(x->n, y);
          return create_node(x->s, p, n);
        }
        else { // x < y
          Node * p = lor(y->p, x);
          Node * n = lor(y->n, x);
          return create_node(y->s, p, n);
        }
      }

      Node * create_node(int s, int r, Node * p, Node * n) {
        number_of_nodes++;
        Node * x = new Node(s, r, p, n);
        if(layers.size() < s+1) layers.resize(s+1);
        layers[s].push_back(x);
        return x;
      }

      Node * create_node(int s, Node * p, Node * n) {
        number_of_nodes++;
        Node * x = new Node(s, p, n);
        if(layers.size() < s+1) layers.resize(s+1);
        layers[s].push_back(x);
        return x;
      }

      friend std::ostream& operator<<(std::ostream & out, const BDD & b) {
        out << "digraph G {\n";
        for(auto layer : b.layers) {
          for(const Node * x : layer) {
            const void * p = x;
            std::string fill = x->r_t.has_value() ? "style=filled," : "";
            std::string shape = x ==b.zero || x == b.one ? "shape=rectangle," : "";
            std::string variable = b.symbol_table_rev.find(x->s)->second;
            out << "  \"" << p << "\" [" << fill << shape << "label=\"" << variable << /*","<< p<< */"\"];\n";
          }
          for(const Node * x : layer) {
            if(x!=b.zero && x != b.one) {
              out << "  \"" << x << "\"->\"" << x->p << "\"\n";
              out << "  \"" << x << "\"->\"" << x->n << "\"[style=dotted];\n";
            }
          }
        }
        out << "}\n";
        return out;
      }
    };
  }
}
<commit_msg>need new paradigm<commit_after>
#pragma once

#include "data_model.hpp"

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <map>
#include <sstream>
#include <string>
#include <optional>

namespace verilog
{
  namespace bdd {
    using std::vector;
    using std::map;
    using std::pair;
    using std::optional;
    // using std::set;

    struct Node {
      //

      // key get_key() {
      //   return key(s, {p, n});
      // }

      /**
       * Index of the node's input in the symbol table
       * s == 0 -> for the special node 0.
       * s == 1 -> for the special node 1.
       * s >= 2 -> for any regular variable.
       */
      const int s;

      /**
       * If this node is a representative, r_t stores it.
       */
      optional<int>  r_t;
      /**
       * The positive edge for this node.
       */
      Node * p;
      /**
       * The negative edge for this node.
       */
      Node * n;

      Node(const int s_, Node * p_, Node * n_, optional<int> r_t_ = optional<int>()):
        s(s_), r_t(r_t_), p(p_), n(n_)
      {}

      /**
       * This constructor should only be used to build zero or one
       */
      Node(const int s_): s(s_)
        {
            p = this;
            n = this;
        }

    };

    typedef pair<Node*, Node*> sib;

    struct BDD {
      //vector<Node> graph;
      Node * zero;
      Node * one;
      vector<map<sib, Node*>> layers;
      int index = 2;
      map<std::string, int> symbol_table;
      map<int, std::string> symbol_table_rev;

      int number_of_nodes = 0;

      BDD():zero(new Node(0)), one(new Node(1)), layers(2) {
        layers[0][{zero,zero}] = zero;
        layers[1][{one,one}] = one;
        symbol_table_rev[0] = "Zero";
        symbol_table_rev[1] = "One";
      }

      Node * add_simple_input(const std::string & variable) {
        auto x = symbol_table.find(variable);
        if(x == symbol_table.end()) {
          symbol_table[variable] = index++;
        }
        int s = symbol_table[variable];
        symbol_table_rev[s] = variable;
        return create_node(s, one, zero, s);
      }

      Node * negate(Node * x) {
        if(x == zero) return one;
        if(x == one) return zero;

        return create_node(x->s, negate(x->p), negate(x->n));
      }

      Node * land(Node * x, Node * y) {
        if(x == one) return copy_of(y);
        if(y == one) return copy_of(x);
        if(x == zero) return zero;
        if(y == zero) return zero;

        if(x->s == y->s) {
          Node * p = land(x->p, y->p);
          Node * n = land(x->n, y->n);
          return create_node(x->s, p, n);
        }
        else if(x->s > y->s) {
          Node * p = land(x->p, y);
          Node * n = land(x->n, y);
          return create_node(x->s, p, n);
        }
        else { // x < y
          Node * p = land(y->p, x);
          Node * n = land(y->n, x);
          return create_node(y->s, p, n);
        }
      }

      Node * copy_of(Node * x) {
        return x;
        // TODO check if this is good or bad.
        //return create_node(x->s, x->p, x->n);
      }

      int height(Node*x) {
        return layers.size();
      }

//       def get_items(self):
// if self.x == 0 or self.x == 1:
//   return [self.get_item()]
// return [self.get_item()] + self.neg.get_items() + self.pos.get_items()

      /**
       *
       */
      Node * check_equivalent(Node * x) {
        if (x == one || x == zero) return x;
        if (x->p == x->n) return x->p;
        return x;
      }

      void check_sons(Node * x) {
        if(x == one || x == zero) return;
        Node *xp = check_equivalent(x->p);
        Node *xn = check_equivalent(x->n);
        if(x->p != xp || x->n != xn){
          x->p = xp;
          x->n = xp;
          layers[x->s].erase(sib{x->p, x->n});
          layers[x->s][sib{xp, xn}] = x; // TODO this may overwrite a node
        }
      }

      /**
       * WARNING: This is really slow O(2^n)
       */

      void simplify_slow(Node * z) {
      // vector<vector<Node*>> layers;
        for(int l = 1; l < layers.size(); ++l) {
          for(int i = 0; i < layers[l].size(); ++i) {
          }
        }

    // def simplify(z):
    //   for h in range(z.height()):
    //     #phase 1: remove redundant
    //     z = z.remove_redundant()
    //
    //     #phase 2: remove equals
    //     bdds = z.get_items()
    //     x = {}
    //     for k, v in bdds:
    //       if not k in bdds:
    //         x[k] = v
    //     for k, v in x.items():
    //       v.pos = x[v.pos.get_key()]
    //       v.neg = x[v.neg.get_key()]
    //
    //     return z
      }

      Node * lor(Node * x, Node * y) {
        if(x == one) return one;
        if(y == one) return one;
        if(x == zero) return copy_of(y);
        if(y == zero) return copy_of(x);

        if(x->s == y->s) {
          Node * p = lor(x->p, y->p);
          Node * n = lor(x->n, y->n);
          return create_node(x->s, p, n);
        }
        else if(x->s > y->s) {
          Node * p = lor(x->p, y);
          Node * n = lor(x->n, y);
          return create_node(x->s, p, n);
        }
        else { // x < y
          Node * p = lor(y->p, x);
          Node * n = lor(y->n, x);
          return create_node(y->s, p, n);
        }
      }

      /**
      * Won't actually create a node if not needed.
      */

      Node * create_node(int s, Node * p, Node * n, optional<int> r = optional<int>()) {
        if(layers.size() < s+1) layers.resize(s+1);
        auto it = layers[s].find(sib{p,n});
        if(it == layers[s].end()) {
          Node * x = new Node(s, p, n, r);
          number_of_nodes++;
          layers[s][sib{p,n}] = x;
          return x;
        }
        else {
          if(r) {
            if(it->second->r_t) {
              // TODO Both have representatives!
            }
            else {
              it->second->r_t = r;
            }
          }
          return it->second;
        }
      }

      friend std::ostream& operator<<(std::ostream & out, const BDD & b) {
        out << "digraph G {\n";
        for(auto layer : b.layers) {
          for(auto [k, x] : layer) {
            const void * p = x;
            std::string fill = x->r_t.has_value() ? "style=filled," : "";
            std::string shape = x ==b.zero || x == b.one ? "shape=rectangle," : "";
            std::string variable = b.symbol_table_rev.find(x->s)->second;
            out << "  \"" << p << "\" [" << fill << shape << "label=\"" << variable << /*","<< p<< */"\"];\n";
          }
          for(auto [k,x] : layer) {
            if(x!=b.zero && x != b.one) {
              out << "  \"" << x << "\"->\"" << x->p << "\"\n";
              out << "  \"" << x << "\"->\"" << x->n << "\"[style=dotted];\n";
            }
          }
        }
        out << "}\n";
        return out;
      }
    };
  }
}
<|endoftext|>


<commit_before>/**
 * @file		sqlite.hpp
 * @brief		database class using sqlite
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 7. 29
 * @details	Sqlite database
 */

#ifndef _COSSB_DB_SQLITE_HPP_
#define _COSSB_DB_SQLITE_HPP_

#include <sqlite3.h>

namespace cossb {
namespace db {

class sqlite {
public:
	sqlite();
	virtual ~sqlite();
};

} /* naemspace db */
} /* namespace cossb */

#endif /* _COSSB_DB_SQLITE_HPP_ */
<commit_msg>add default database class with sqlite<commit_after>/**
 * @file		sqlite.hpp
 * @brief		database class using sqlite
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 7. 29
 * @details	Sqlite database
 */

#ifndef _COSSB_DB_SQLITE_HPP_
#define _COSSB_DB_SQLITE_HPP_

#include <sqlite3.h>
#include "../interface/isql.hpp"

namespace cossb {
namespace db {

class sqlite : public interface::iSQL {
public:
	sqlite();
	virtual ~sqlite();
};

} /* naemspace db */
} /* namespace cossb */

#endif /* _COSSB_DB_SQLITE_HPP_ */
<|endoftext|>


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

#ifndef ETL_PRINT_HPP
#define ETL_PRINT_HPP

#include<string>

#include "traits.hpp"

namespace etl {

template<typename T, enable_if_u<etl_traits<T>::is_value> = detail::dummy>
std::ostream& operator<<(std::ostream& stream, const T& v){
    return stream << to_string(v);
}

template<typename T, enable_if_u<etl_traits<T>::is_vector> = detail::dummy>
std::string to_string(const T& vec){
    return to_octave(vec);
}

template<typename T, enable_if_u<etl_traits<T>::is_vector> = detail::dummy>
std::string to_octave(const T& vec){
    std::string v = "[";
    std::string comma = "";
    for(std::size_t i = 0; i < size(vec); ++i){
        v += comma + std::to_string(vec(i));
        comma = ",";
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<etl_traits<T>::is_matrix> = detail::dummy>
std::string to_string(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < rows(m); ++i){
        v += "[";
        std::string comma = "";
        for(std::size_t j = 0; j  < columns(m); ++j){
            v += comma + std::to_string(m(i, j));
            comma = ",";
        }
        v += "]";
        if(i < rows(m) - 1){
            v += "\n";
        }
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<etl_traits<T>::is_matrix> = detail::dummy>
std::string to_octave(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < rows(m); ++i){
        std::string comma = "";
        for(std::size_t j = 0; j  < columns(m); ++j){
            v += comma + std::to_string(m(i, j));
            comma = ",";
        }
        if(i < rows(m) - 1){
            v += ";";
        }
    }
    v += "]";
    return v;
}

} //end of namespace etl

#endif
<commit_msg>Implement print for deep matrix<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_PRINT_HPP
#define ETL_PRINT_HPP

#include<string>

#include "traits.hpp"

namespace etl {

template<typename T, enable_if_u<etl_traits<T>::is_value> = detail::dummy>
std::ostream& operator<<(std::ostream& stream, const T& v){
    return stream << to_string(v);
}

template<typename T, enable_if_u<etl_traits<T>::is_vector> = detail::dummy>
std::string to_string(const T& vec){
    return to_octave(vec);
}

template<typename T, enable_if_u<etl_traits<T>::is_vector> = detail::dummy>
std::string to_octave(const T& vec){
    std::string v = "[";
    std::string comma = "";
    for(std::size_t i = 0; i < size(vec); ++i){
        v += comma + std::to_string(vec(i));
        comma = ",";
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<and_u<etl_traits<T>::is_matrix, not_u<etl_traits<T>::is_fast>::value>::value> = detail::dummy>
std::string to_string(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < rows(m); ++i){
        v += "[";
        std::string comma = "";
        for(std::size_t j = 0; j  < columns(m); ++j){
            v += comma + std::to_string(m(i, j));
            comma = ",";
        }
        v += "]";
        if(i < rows(m) - 1){
            v += "\n";
        }
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<and_u<etl_traits<T>::is_matrix, etl_traits<T>::is_fast, (etl_traits<T>::dimensions() > 2)>::value> = detail::dummy>
std::string to_string(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < etl_traits<T>::template dim<0>(); ++i){
        v += to_string(sub(m, i));

        if(i < etl_traits<T>::template dim<0>() - 1){
            v += "\n";
        }
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<and_u<etl_traits<T>::is_matrix, etl_traits<T>::is_fast, etl_traits<T>::dimensions() == 2>::value> = detail::dummy>
std::string to_string(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < etl_traits<T>::template dim<0>(); ++i){
        v += "[";
        std::string comma = "";
        for(std::size_t j = 0; j  < etl_traits<T>::template dim<1>(); ++j){
            v += comma + std::to_string(m(i, j));
            comma = ",";
        }
        v += "]";
        if(i < etl_traits<T>::template dim<0>() - 1){
            v += "\n";
        }
    }
    v += "]";
    return v;
}

template<typename T, enable_if_u<etl_traits<T>::is_matrix> = detail::dummy>
std::string to_octave(const T& m){
    std::string v = "[";
    for(std::size_t i = 0; i < rows(m); ++i){
        std::string comma = "";
        for(std::size_t j = 0; j  < columns(m); ++j){
            v += comma + std::to_string(m(i, j));
            comma = ",";
        }
        if(i < rows(m) - 1){
            v += ";";
        }
    }
    v += "]";
    return v;
}

} //end of namespace etl

#endif
<|endoftext|>