<commit_before>#pragma once

#include <vector>

namespace acmacs
{
    using Indexes = std::vector<size_t>;

    class SortedIndexes : public Indexes
    {
     public:
        explicit SortedIndexes(const Indexes& source)
            : Indexes(source) { std::sort(begin(), end()); }
    };

    class ReverseSortedIndexes : public Indexes
    {
     public:
        explicit ReverseSortedIndexes(const Indexes& source) : Indexes(source) { sort(); }

        void add(const Indexes& to_add) { insert(end(), to_add.begin(), to_add.end()); sort(); }

     private:
        static inline bool cmp(size_t i1, size_t i2) { return i1 > i2; }
        void sort() { std::sort(begin(), end(), cmp); erase(std::unique(begin(), end()), end()); }
    };

    template <typename T> void remove(const ReverseSortedIndexes& indexes, std::vector<T>& data, size_t base_index = 0)
    {
        for (auto index : indexes)
            data.erase(data.begin() + static_cast<ReverseSortedIndexes::difference_type>(index + base_index));
    }
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>bug fix in inserting/removing sera and not updating forced column bases<commit_after>#pragma once

#include <vector>

namespace acmacs
{
    using Indexes = std::vector<size_t>;

    class SortedIndexes : public Indexes
    {
     public:
        explicit SortedIndexes(const Indexes& source)
            : Indexes(source) { std::sort(begin(), end()); }
    };

    class ReverseSortedIndexes : public Indexes
    {
     public:
        explicit ReverseSortedIndexes(const Indexes& source) : Indexes(source) { sort(); }

        void add(const Indexes& to_add) { insert(end(), to_add.begin(), to_add.end()); sort(); }

     private:
        static inline bool cmp(size_t i1, size_t i2) { return i1 > i2; }
        void sort() { std::sort(begin(), end(), cmp); erase(std::unique(begin(), end()), end()); }
    };

    template <typename T> void remove(const ReverseSortedIndexes& indexes, std::vector<T>& data, ReverseSortedIndexes::difference_type base_index = 0)
    {
        for (auto index : indexes)
            data.erase(data.begin() + static_cast<ReverseSortedIndexes::difference_type>(index) + base_index);
    }
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <map>
#include <cstdlib>
#include <optional>

#include "acmacs-base/fmt.hh"
#include "acmacs-base/sfinae.hh"
#include "acmacs-base/to-string.hh"

// ----------------------------------------------------------------------

namespace to_json
{
    inline namespace v2
    {
        class json
        {
          private:
            static constexpr auto comma_after = [](auto iter, auto first) -> bool {
                if (iter == first)
                    return false;
                switch (std::prev(iter)->back()) {
                    case '[':
                    case '{':
                    case ':':
                        return false;
                    default:
                        return true;
                }
            };

            static constexpr auto comma_before = [](auto iter) -> bool {
                switch (iter->back()) {
                    case ']':
                    case '}':
                    case ':':
                        return false;
                    default:
                        return true;
                }
            };

            static constexpr auto indent_after = [](auto iter, auto first) -> bool {
                if (iter == first)
                    return false;
                switch (std::prev(iter)->back()) {
                    case '[':
                    case '{':
                        return true;
                    default:
                        return false;
                }
            };

            static constexpr auto unindent_before = [](auto iter) -> bool {
                return iter->size() == 1 && (iter->front() == ']' || iter->front() == '}');
            };

          public:
            enum class compact_output { no, yes };
            enum class embed_space { no, yes };
            enum class escape_double_quotes { no, yes };

            std::string compact(embed_space space = embed_space::no) const
            {
                const std::string comma(space == embed_space::yes ? ", " : ",");
                fmt::memory_buffer out;
                for (auto chunk = data_.begin(); chunk != data_.end(); ++chunk) {
                    if (comma_after(chunk, data_.begin()) && comma_before(chunk))
                        fmt::format_to(out, "{}{}", comma, *chunk);
                    else if (space == embed_space::yes && chunk != data_.begin() && std::prev(chunk)->back() == ':')
                        fmt::format_to(out, " {}", *chunk);
                    else
                        fmt::format_to(out, "{}", *chunk);
                }
                return fmt::to_string(out);
            }

            std::string pretty(size_t indent) const
            {
                fmt::memory_buffer out;
                size_t current_indent = 0;
                for (auto chunk = data_.begin(); chunk != data_.end(); ++chunk) {
                    if (comma_after(chunk, data_.begin()) && comma_before(chunk)) {
                        fmt::format_to(out, ",\n{: >{}s}{}", "", current_indent, *chunk);
                    }
                    else {
                        if (const auto ia = indent_after(chunk, data_.begin()), ub = unindent_before(chunk); ia && !ub) {
                            current_indent += indent;
                            fmt::format_to(out, "\n{: >{}s}{}", "", current_indent, *chunk);
                        }
                        else if (!ia && ub) {
                            current_indent -= indent;
                            fmt::format_to(out, "\n{: >{}s}{}", "", current_indent, *chunk);
                        }
                        else if ((ia && ub) || chunk == data_.begin())
                            fmt::format_to(out, "{}", *chunk);
                        else if (chunk->front() == ':')
                            fmt::format_to(out, "{}", *chunk);
                        else
                            fmt::format_to(out, " {}", *chunk);
                    }
                }
                return fmt::to_string(out);
            }

            void move_before_end(json&& value) { std::move(value.data_.begin(), value.data_.end(), std::inserter(data_, std::prev(data_.end()))); }

          protected:
            using data_t = std::vector<std::string>;

            data_t data_;

            json() = default;
            json(char beg, char end)
            {
                push_back(beg);
                push_back(end);
            }

            void push_back(std::string_view str) { data_.emplace_back(str); }
            void push_back(const char* str) { data_.emplace_back(str); }
            void push_back(std::string&& str) { data_.push_back(std::move(str)); }
            void push_back(char c) { data_.push_back(std::string(1, c)); }
            void move(json&& value) { std::move(value.data_.begin(), value.data_.end(), std::back_inserter(data_)); }

            void make_compact()
            {
                data_[0] = compact(embed_space::yes);
                data_.erase(std::next(data_.begin()), data_.end());
            }

        }; // class json

        class val : public json
        {
          public:
            template <typename T> inline val(T&& a_val, escape_double_quotes esc = escape_double_quotes::no)
            {
                if constexpr (acmacs::sfinae::is_string_v<T>) {
                    if (esc == escape_double_quotes::yes)
                        push_back(fmt::format("\"{}\"", escape(a_val)));
                    else
                        push_back(fmt::format("\"{}\"", std::forward<T>(a_val)));
                }
                else if constexpr (std::numeric_limits<std::decay_t<T>>::is_integer || std::is_floating_point_v<std::decay_t<T>>)
                    push_back(fmt::format("{}", std::forward<T>(a_val)));
                else if constexpr (acmacs::sfinae::decay_equiv_v<T, bool>)
                    push_back(a_val ? "true" : "false");
                else
                    static_assert(std::is_same_v<int, std::decay_t<T>>, "invalid arg type for to_json::val");
            }

            static inline std::string escape(std::string_view str)
            {
                std::string result(static_cast<size_t>(str.size() * 1.2), ' ');
                auto output = std::begin(result);
                for (auto input = std::begin(str); input != std::end(str); ++input, ++output) {
                    switch (*input) {
                      case '"':
                          *output++ = '\\';
                          *output = *input;
                          break;
                      case '\n':
                          *output++ = '\\';
                          *output = 'n';
                          break;
                      case '\t':
                          *output = ' '; // old seqdb reader cannot read tabs
                          break;
                      default:
                          *output = *input;
                          break;
                    }
                }
                return result;
            }
        };

        class raw : public json
        {
          public:
            raw(std::string_view data) { push_back(data); }
            raw(std::string&& data) { push_back(std::move(data)); }
        };

        class key_val : public json
        {
          public:
            template <typename T> key_val(std::string_view key, T&& value, escape_double_quotes esc = escape_double_quotes::no)
            {
                move(val(key, esc));
                push_back(':');
                if constexpr (std::is_convertible_v<std::decay_t<T>, json>)
                    move(std::move(value));
                else
                    move(val(std::forward<T>(value)));
            }
        };

        class key_val_if
        {
          public:
            constexpr bool empty() const { return !kv_.has_value(); }
            constexpr key_val&& get() && { return std::move(kv_.value()); }

          protected:
            template <typename T> void set(std::string_view key, T&& value, json::escape_double_quotes esc = json::escape_double_quotes::no) { kv_ = key_val(key, std::move(value), esc); }

          private:
            std::optional<key_val> kv_;
        };

        class key_val_if_not_empty : public key_val_if
        {
          public:
            template <typename T> key_val_if_not_empty(std::string_view key, T&& value, json::escape_double_quotes esc = json::escape_double_quotes::no)
            {
                if (!value.empty())
                    set(key, std::move(value), esc);
            }
        };

        class key_val_if_true : public key_val_if
        {
          public:
            key_val_if_true(std::string_view key, bool value)
            {
                if (value)
                    set(key, std::move(value));
            }
        };

        class array : public json
        {
          public:
            array() : json('[', ']') {}

            template <typename... Args> array(Args&&... args) : array() { append(std::forward<Args>(args)...); }

            template <typename Iterator, typename Transformer, typename = acmacs::sfinae::iterator_t<Iterator>>
            array(Iterator first, Iterator last, Transformer transformer, compact_output co = compact_output::no, [[maybe_unused]] escape_double_quotes esc = escape_double_quotes::no)
                : array()
            {
                for (; first != last; ++first) {
                    auto value = transformer(*first);
                    if constexpr (std::is_convertible_v<std::decay_t<decltype(value)>, json>)
                        move_before_end(std::move(value));
                    else
                        move_before_end(val(std::move(value), esc));
                }
                if (co == compact_output::yes)
                    make_compact();
            }

            template <typename Iterator, typename = acmacs::sfinae::iterator_t<Iterator>> array(Iterator first, Iterator last, compact_output co = compact_output::no, escape_double_quotes esc = escape_double_quotes::no)
                : array()
            {
                for (; first != last; ++first)
                    move_before_end(val(*first, esc));
                if (co == compact_output::yes)
                    make_compact();
            }

          private:
            template <typename Arg1, typename... Args> void append(Arg1&& arg1, Args&&... args)
            {
                if constexpr (std::is_same_v<std::decay_t<Arg1>, compact_output>) {
                    if (arg1 == compact_output::yes)
                        make_compact();
                }
                else if constexpr (std::is_convertible_v<std::decay_t<Arg1>, json>)
                    move_before_end(std::move(arg1));
                else
                    move_before_end(val(std::forward<Arg1>(arg1)));
                if constexpr (sizeof...(args) > 0)
                    append(std::forward<Args>(args)...);
            }

        };

        class object : public json
        {
          public:
            object() : json('{', '}') {}
            template <typename... Args> object(Args&&... args) : object() { append(std::forward<Args>(args)...); }

            bool empty() const { return data_.size() == 2; }

            template <typename K, typename V> static object from(const std::map<K, V>& src)
            {
                object result;
                for (const auto& [key, val] : src)
                    result.move_before_end(key_val{acmacs::to_string(key), val});
                return result;
            }

          private:
            template <typename Arg1, typename... Args> void append(Arg1&& arg1, Args&&... args)
            {
                if constexpr (std::is_same_v<std::decay_t<Arg1>, compact_output>) {
                    if (arg1 == compact_output::yes)
                        make_compact();
                }
                else {
                    static_assert(std::is_convertible_v<std::decay_t<Arg1>, key_val>, "invalid arg type for to_json::object, must be to_json::key_val");
                    move_before_end(std::move(arg1));
                    if constexpr (sizeof...(args) > 0)
                        append(std::forward<Args>(args)...);
                }
            }

            friend object& operator<<(object& target, key_val&& kv);
            friend object& operator<<(object& target, key_val_if&& kv);
        };

        template <typename T> inline array& operator<<(array& target, T&& value)
        {
            if constexpr (std::is_convertible_v<std::decay_t<T>, json>)
                target.move_before_end(std::forward<T>(value));
            else
                target.move_before_end(val(std::forward<T>(value)));
            return target;
        }

        inline object& operator<<(object& target, key_val&& kv)
        {
            target.move_before_end(std::move(kv));
            return target;
        }

        inline object& operator<<(object& target, key_val_if&& kv)
        {
            if (!kv.empty())
                target.move_before_end(std::move(kv).get());
            return target;
        }

    } // namespace v2

} // namespace to_json

// ----------------------------------------------------------------------

// "{}" -> pretty(2)
// "{:4}" -> pretty(4)
// "{:0}" -> compact()
// "{:4c}" -> compact()

template <typename T> struct fmt::formatter<T, std::enable_if_t<std::is_base_of<to_json::json, T>::value, char>> : fmt::formatter<std::string>
{
    template <typename ParseContext> auto parse(ParseContext& ctx) -> decltype(ctx.begin())
    {
        auto it = ctx.begin();
        if (it != ctx.end() && *it == ':')
            ++it;
        if (it != ctx.end() && *it != '}') {
            char* end;
            indent_ = std::strtoul(&*it, &end, 10);
            it = std::next(it, end - &*it);
        }
        if (*it == 'c') {
            indent_ = 0;        // compact anyway
            ++it;
        }
        while (it != ctx.end() && *it != '}')
            ++it;
        return it;
    }

    template <typename FormatCtx> auto format(const to_json::json& js, FormatCtx& ctx)
    {
        if (indent_ > 0)
            return fmt::formatter<std::string>::format(js.pretty(indent_), ctx);
        else
            return fmt::formatter<std::string>::format(js.compact(), ctx);
    }

    size_t indent_ = 2;
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>bug fix in to_json<commit_after>#pragma once

#include <vector>
#include <map>
#include <cstdlib>
#include <optional>

#include "acmacs-base/fmt.hh"
#include "acmacs-base/sfinae.hh"
#include "acmacs-base/to-string.hh"

// ----------------------------------------------------------------------

namespace to_json
{
    inline namespace v2
    {
        class json
        {
          private:
            static constexpr auto comma_after = [](auto iter, auto first) -> bool {
                if (iter == first)
                    return false;
                switch (std::prev(iter)->back()) {
                    case '[':
                    case '{':
                    case ':':
                        return false;
                    default:
                        return true;
                }
            };

            static constexpr auto comma_before = [](auto iter) -> bool {
                switch (iter->back()) {
                    case ']':
                    case '}':
                    case ':':
                        return false;
                    default:
                        return true;
                }
            };

            static constexpr auto indent_after = [](auto iter, auto first) -> bool {
                if (iter == first)
                    return false;
                switch (std::prev(iter)->back()) {
                    case '[':
                    case '{':
                        return true;
                    default:
                        return false;
                }
            };

            static constexpr auto unindent_before = [](auto iter) -> bool {
                return iter->size() == 1 && (iter->front() == ']' || iter->front() == '}');
            };

          public:
            enum class compact_output { no, yes };
            enum class embed_space { no, yes };
            enum class escape_double_quotes { no, yes };

            std::string compact(embed_space space = embed_space::no) const
            {
                const std::string comma(space == embed_space::yes ? ", " : ",");
                fmt::memory_buffer out;
                for (auto chunk = data_.begin(); chunk != data_.end(); ++chunk) {
                    if (comma_after(chunk, data_.begin()) && comma_before(chunk))
                        fmt::format_to(out, "{}{}", comma, *chunk);
                    else if (space == embed_space::yes && chunk != data_.begin() && std::prev(chunk)->back() == ':')
                        fmt::format_to(out, " {}", *chunk);
                    else
                        fmt::format_to(out, "{}", *chunk);
                }
                return fmt::to_string(out);
            }

            std::string pretty(size_t indent) const
            {
                fmt::memory_buffer out;
                size_t current_indent = 0;
                for (auto chunk = data_.begin(); chunk != data_.end(); ++chunk) {
                    if (comma_after(chunk, data_.begin()) && comma_before(chunk)) {
                        fmt::format_to(out, ",\n{: >{}s}{}", "", current_indent, *chunk);
                    }
                    else {
                        if (const auto ia = indent_after(chunk, data_.begin()), ub = unindent_before(chunk); ia && !ub) {
                            current_indent += indent;
                            fmt::format_to(out, "\n{: >{}s}{}", "", current_indent, *chunk);
                        }
                        else if (!ia && ub) {
                            current_indent -= indent;
                            fmt::format_to(out, "\n{: >{}s}{}", "", current_indent, *chunk);
                        }
                        else if ((ia && ub) || chunk == data_.begin())
                            fmt::format_to(out, "{}", *chunk);
                        else if (chunk->front() == ':')
                            fmt::format_to(out, "{}", *chunk);
                        else
                            fmt::format_to(out, " {}", *chunk);
                    }
                }
                return fmt::to_string(out);
            }

            void move_before_end(json&& value) { std::move(value.data_.begin(), value.data_.end(), std::inserter(data_, std::prev(data_.end()))); }

          protected:
            using data_t = std::vector<std::string>;

            data_t data_;

            json() = default;
            json(char beg, char end)
            {
                push_back(beg);
                push_back(end);
            }

            void push_back(std::string_view str) { data_.emplace_back(str); }
            void push_back(const char* str) { data_.emplace_back(str); }
            void push_back(std::string&& str) { data_.push_back(std::move(str)); }
            void push_back(char c) { data_.push_back(std::string(1, c)); }
            void move(json&& value) { std::move(value.data_.begin(), value.data_.end(), std::back_inserter(data_)); }

            void make_compact()
            {
                data_[0] = compact(embed_space::yes);
                data_.erase(std::next(data_.begin()), data_.end());
            }

        }; // class json

        class val : public json
        {
          public:
            template <typename T> inline val(T&& a_val, escape_double_quotes esc = escape_double_quotes::no)
            {
                if constexpr (acmacs::sfinae::is_string_v<T>) {
                    if (esc == escape_double_quotes::yes)
                        push_back(fmt::format("\"{}\"", escape(a_val)));
                    else
                        push_back(fmt::format("\"{}\"", std::forward<T>(a_val)));
                }
                else if constexpr (std::numeric_limits<std::decay_t<T>>::is_integer || std::is_floating_point_v<std::decay_t<T>>)
                    push_back(fmt::format("{}", std::forward<T>(a_val)));
                else if constexpr (acmacs::sfinae::decay_equiv_v<T, bool>)
                    push_back(a_val ? "true" : "false");
                else
                    static_assert(std::is_same_v<int, std::decay_t<T>>, "invalid arg type for to_json::val");
            }

            static inline std::string escape(std::string_view str)
            {
                std::string result(static_cast<size_t>(str.size() * 1.2), ' ');
                auto output = std::begin(result);
                for (auto input = std::begin(str); input != std::end(str); ++input, ++output) {
                    switch (*input) {
                      case '"':
                          *output++ = '\\';
                          *output = *input;
                          break;
                      case '\n':
                          *output++ = '\\';
                          *output = 'n';
                          break;
                      case '\t':
                          *output = ' '; // old seqdb reader cannot read tabs
                          break;
                      default:
                          *output = *input;
                          break;
                    }
                }
                result.erase(output, std::end(result));
                return result;
            }
        };

        class raw : public json
        {
          public:
            raw(std::string_view data) { push_back(data); }
            raw(std::string&& data) { push_back(std::move(data)); }
        };

        class key_val : public json
        {
          public:
            template <typename T> key_val(std::string_view key, T&& value, escape_double_quotes esc = escape_double_quotes::no)
            {
                move(val(key, esc));
                push_back(':');
                if constexpr (std::is_convertible_v<std::decay_t<T>, json>)
                    move(std::move(value));
                else
                    move(val(std::forward<T>(value)));
            }
        };

        class key_val_if
        {
          public:
            constexpr bool empty() const { return !kv_.has_value(); }
            constexpr key_val&& get() && { return std::move(kv_.value()); }

          protected:
            template <typename T> void set(std::string_view key, T&& value, json::escape_double_quotes esc = json::escape_double_quotes::no) { kv_ = key_val(key, std::move(value), esc); }

          private:
            std::optional<key_val> kv_;
        };

        class key_val_if_not_empty : public key_val_if
        {
          public:
            template <typename T> key_val_if_not_empty(std::string_view key, T&& value, json::escape_double_quotes esc = json::escape_double_quotes::no)
            {
                if (!value.empty())
                    set(key, std::move(value), esc);
            }
        };

        class key_val_if_true : public key_val_if
        {
          public:
            key_val_if_true(std::string_view key, bool value)
            {
                if (value)
                    set(key, std::move(value));
            }
        };

        class array : public json
        {
          public:
            array() : json('[', ']') {}

            template <typename... Args> array(Args&&... args) : array() { append(std::forward<Args>(args)...); }

            template <typename Iterator, typename Transformer, typename = acmacs::sfinae::iterator_t<Iterator>>
            array(Iterator first, Iterator last, Transformer transformer, compact_output co = compact_output::no, [[maybe_unused]] escape_double_quotes esc = escape_double_quotes::no)
                : array()
            {
                for (; first != last; ++first) {
                    auto value = transformer(*first);
                    if constexpr (std::is_convertible_v<std::decay_t<decltype(value)>, json>)
                        move_before_end(std::move(value));
                    else
                        move_before_end(val(std::move(value), esc));
                }
                if (co == compact_output::yes)
                    make_compact();
            }

            template <typename Iterator, typename = acmacs::sfinae::iterator_t<Iterator>> array(Iterator first, Iterator last, compact_output co = compact_output::no, escape_double_quotes esc = escape_double_quotes::no)
                : array()
            {
                for (; first != last; ++first)
                    move_before_end(val(*first, esc));
                if (co == compact_output::yes)
                    make_compact();
            }

          private:
            template <typename Arg1, typename... Args> void append(Arg1&& arg1, Args&&... args)
            {
                if constexpr (std::is_same_v<std::decay_t<Arg1>, compact_output>) {
                    if (arg1 == compact_output::yes)
                        make_compact();
                }
                else if constexpr (std::is_convertible_v<std::decay_t<Arg1>, json>)
                    move_before_end(std::move(arg1));
                else
                    move_before_end(val(std::forward<Arg1>(arg1)));
                if constexpr (sizeof...(args) > 0)
                    append(std::forward<Args>(args)...);
            }

        };

        class object : public json
        {
          public:
            object() : json('{', '}') {}
            template <typename... Args> object(Args&&... args) : object() { append(std::forward<Args>(args)...); }

            bool empty() const { return data_.size() == 2; }

            template <typename K, typename V> static object from(const std::map<K, V>& src)
            {
                object result;
                for (const auto& [key, val] : src)
                    result.move_before_end(key_val{acmacs::to_string(key), val});
                return result;
            }

          private:
            template <typename Arg1, typename... Args> void append(Arg1&& arg1, Args&&... args)
            {
                if constexpr (std::is_same_v<std::decay_t<Arg1>, compact_output>) {
                    if (arg1 == compact_output::yes)
                        make_compact();
                }
                else {
                    static_assert(std::is_convertible_v<std::decay_t<Arg1>, key_val>, "invalid arg type for to_json::object, must be to_json::key_val");
                    move_before_end(std::move(arg1));
                    if constexpr (sizeof...(args) > 0)
                        append(std::forward<Args>(args)...);
                }
            }

            friend object& operator<<(object& target, key_val&& kv);
            friend object& operator<<(object& target, key_val_if&& kv);
        };

        template <typename T> inline array& operator<<(array& target, T&& value)
        {
            if constexpr (std::is_convertible_v<std::decay_t<T>, json>)
                target.move_before_end(std::forward<T>(value));
            else
                target.move_before_end(val(std::forward<T>(value)));
            return target;
        }

        inline object& operator<<(object& target, key_val&& kv)
        {
            target.move_before_end(std::move(kv));
            return target;
        }

        inline object& operator<<(object& target, key_val_if&& kv)
        {
            if (!kv.empty())
                target.move_before_end(std::move(kv).get());
            return target;
        }

    } // namespace v2

} // namespace to_json

// ----------------------------------------------------------------------

// "{}" -> pretty(2)
// "{:4}" -> pretty(4)
// "{:0}" -> compact()
// "{:4c}" -> compact()

template <typename T> struct fmt::formatter<T, std::enable_if_t<std::is_base_of<to_json::json, T>::value, char>> : fmt::formatter<std::string>
{
    template <typename ParseContext> auto parse(ParseContext& ctx) -> decltype(ctx.begin())
    {
        auto it = ctx.begin();
        if (it != ctx.end() && *it == ':')
            ++it;
        if (it != ctx.end() && *it != '}') {
            char* end;
            indent_ = std::strtoul(&*it, &end, 10);
            it = std::next(it, end - &*it);
        }
        if (*it == 'c') {
            indent_ = 0;        // compact anyway
            ++it;
        }
        while (it != ctx.end() && *it != '}')
            ++it;
        return it;
    }

    template <typename FormatCtx> auto format(const to_json::json& js, FormatCtx& ctx)
    {
        if (indent_ > 0)
            return fmt::formatter<std::string>::format(js.pretty(indent_), ctx);
        else
            return fmt::formatter<std::string>::format(js.compact(), ctx);
    }

    size_t indent_ = 2;
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "coreclrutil.h"
#include <dirent.h>
#include <dlfcn.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <set>

// The name of the CoreCLR native runtime DLL
#if defined(__APPLE__)
constexpr char coreClrDll[] = "libcoreclr.dylib";
#else
constexpr char coreClrDll[] = "libcoreclr.so";
#endif

void* coreclrLib;

// Prototype of the coreclr_initialize function from the libcoreclr.so
typedef int (*InitializeCoreCLRFunction)(
    const char* exePath,
    const char* appDomainFriendlyName,
    int propertyCount,
    const char** propertyKeys,
    const char** propertyValues,
    void** hostHandle,
    unsigned int* domainId);

// Prototype of the coreclr_shutdown function from the libcoreclr.so
typedef int (*ShutdownCoreCLRFunction)(
    void* hostHandle,
    unsigned int domainId);

InitializeCoreCLRFunction initializeCoreCLR;
ShutdownCoreCLRFunction shutdownCoreCLR;
ExecuteAssemblyFunction executeAssembly;
CreateDelegateFunction createDelegate;

//
// Below is from unixcoreruncommon/coreruncommon.cpp
//

bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
    bool result = false;

    char realPath[PATH_MAX];
    if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
    {
        absolutePath.assign(realPath);
        // realpath should return canonicalized path without the trailing slash
        assert(absolutePath.back() != '/');

        result = true;
    }

    return result;
}

// TODO use dirname
bool GetDirectory(const char* absolutePath, std::string& directory)
{
    directory.assign(absolutePath);
    size_t lastSlash = directory.rfind('/');
    if (lastSlash != std::string::npos)
    {
        directory.erase(lastSlash);
        return true;
    }

    return false;
}

// Modified to use CORE_ROOT environment variable

//
// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided,
// this function will return the absolute path to it. Otherwise, the directory of the current executable is used.
//
// Return true in case of a success, false otherwise.
//
bool GetClrFilesAbsolutePath(const char* currentExePath, std::string& clrFilesAbsolutePath)
{
    std::string clrFilesRelativePath;
    const char* clrFilesPathLocal = std::getenv("CORE_ROOT");;
    if (clrFilesPathLocal == nullptr)
    {
        // There was no CLR files path specified, use the folder of the host
        if (!GetDirectory(currentExePath, clrFilesRelativePath))
        {
            std::cerr << "Failed to get directory from currentExePath" << std::endl;
            return false;
        }

        clrFilesPathLocal = clrFilesRelativePath.c_str();
    }

    if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath))
    {
        perror("Failed to convert CLR files path to absolute path");
        return false;
    }

    return true;
}

void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
{
    const char * const tpaExtensions[] = {
        ".ni.dll",      // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
        ".dll",
        ".ni.exe",
        ".exe",
    };

    DIR* dir = opendir(directory);
    if (dir == nullptr)
    {
        return;
    }

    std::set<std::string> addedAssemblies;

    // Walk the directory for each extension separately so that we first get files with .ni.dll extension,
    // then files with .dll extension, etc.
    for (unsigned int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++)
    {
        const char* ext = tpaExtensions[extIndex];
        int extLength = strlen(ext);

        struct dirent* entry;

        // For all entries in the directory
        while ((entry = readdir(dir)) != nullptr)
        {
            // We are interested in files only
            switch (entry->d_type)
            {
            case DT_REG:
                break;

                // Handle symlinks and file systems that do not support d_type
            case DT_LNK:
            case DT_UNKNOWN:
            {
                std::string fullFilename;

                fullFilename.append(directory);
                fullFilename.append("/");
                fullFilename.append(entry->d_name);

                struct stat sb;
                if (stat(fullFilename.c_str(), &sb) == -1)
                {
                    continue;
                }

                if (!S_ISREG(sb.st_mode))
                {
                    continue;
                }
            }
            break;

            default:
                continue;
            }

            std::string filename(entry->d_name);

            // Check if the extension matches the one we are looking for
            int extPos = filename.length() - extLength;
            if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0))
            {
                continue;
            }

            std::string filenameWithoutExt(filename.substr(0, extPos));

            // Make sure if we have an assembly with multiple extensions present,
            // we insert only one version of it.
            if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
            {
                addedAssemblies.insert(filenameWithoutExt);

                tpaList.append(directory);
                tpaList.append("/");
                tpaList.append(filename);
                tpaList.append(":");
            }
        }

        // Rewind the directory stream to be able to iterate over it for the next extension
        rewinddir(dir);
    }

    closedir(dir);
}

//
// Below is our custom start/stop interface
//
int startCoreCLR(
    // Passed to propertyValues
    const char* tpaList,
    const char* appPath,
    const char* nativeDllSearchDirs,
    // Passed to InitializeCoreCLRFunction
    const char* appDomainFriendlyName,
    void** hostHandle,
    unsigned int* domainId)
{
    // get path to current executable
    char exePath[PATH_MAX] = { 0 };
    readlink("/proc/self/exe", exePath, PATH_MAX);

    std::string clrFilesAbsolutePath;
    if(!GetClrFilesAbsolutePath(exePath, clrFilesAbsolutePath))
    {
        return -1;
    }

    std::string coreClrDllPath(clrFilesAbsolutePath);
    coreClrDllPath.append("/");
    coreClrDllPath.append(coreClrDll);

    if (coreClrDllPath.size() >= PATH_MAX)
    {
        std::cerr << "Absolute path to CoreCLR library too long" << std::endl;
        return 1;
    }

    // open the shared library
    coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL);
    if (coreclrLib == nullptr)
    {
        char* error = dlerror();
        std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl;
        return 2;
    }

    // query the function pointers
    initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize");
    shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown");

    executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly");
    createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate");

    if (initializeCoreCLR == nullptr)
    {
        std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (executeAssembly == nullptr)
    {
        std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (shutdownCoreCLR == nullptr)
    {
        std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (createDelegate == nullptr)
    {
        std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl;
        return 3;
    }

    // create list of properties to initialize CoreCLR
    const char* propertyKeys[] = {
        "TRUSTED_PLATFORM_ASSEMBLIES",
        "APP_PATHS",
        "APP_NI_PATHS",
        "NATIVE_DLL_SEARCH_DIRECTORIES",
        "AppDomainCompatSwitch"
    };

    const char* propertyValues[] = {
        tpaList,
        appPath,
        appPath,
        nativeDllSearchDirs,
        "UseLatestBehaviorWhenTFMNotSpecified"
    };

    // initialize CoreCLR
    int status = initializeCoreCLR(
        exePath,
        appDomainFriendlyName,
        sizeof(propertyKeys)/sizeof(propertyKeys[0]),
        propertyKeys,
        propertyValues,
        hostHandle,
        domainId);

    if (0 > status)
    {
        std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl;
        return 4;
    }

    return status;
}

int stopCoreCLR(void* hostHandle, unsigned int domainId)
{
    // shutdown CoreCLR
    int status = shutdownCoreCLR(hostHandle, domainId);
    if (0 > status)
    {
        std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl;
    }

    // close the dynamic library
    if (0 != dlclose(coreclrLib))
    {
        std::cerr << "failed to close CoreCLR library" << std::endl;
    }

    return status;
}
<commit_msg>Refactor into GetEnvAbsolutePath()<commit_after>#include "coreclrutil.h"
#include <dirent.h>
#include <dlfcn.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <set>

// The name of the CoreCLR native runtime DLL
#if defined(__APPLE__)
constexpr char coreClrDll[] = "libcoreclr.dylib";
#else
constexpr char coreClrDll[] = "libcoreclr.so";
#endif

void* coreclrLib;

// Prototype of the coreclr_initialize function from the libcoreclr.so
typedef int (*InitializeCoreCLRFunction)(
    const char* exePath,
    const char* appDomainFriendlyName,
    int propertyCount,
    const char** propertyKeys,
    const char** propertyValues,
    void** hostHandle,
    unsigned int* domainId);

// Prototype of the coreclr_shutdown function from the libcoreclr.so
typedef int (*ShutdownCoreCLRFunction)(
    void* hostHandle,
    unsigned int domainId);

InitializeCoreCLRFunction initializeCoreCLR;
ShutdownCoreCLRFunction shutdownCoreCLR;
ExecuteAssemblyFunction executeAssembly;
CreateDelegateFunction createDelegate;

//
// Below is from unixcoreruncommon/coreruncommon.cpp
//

bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
    bool result = false;

    char realPath[PATH_MAX];
    if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
    {
        absolutePath.assign(realPath);
        // realpath should return canonicalized path without the trailing slash
        assert(absolutePath.back() != '/');

        result = true;
    }

    return result;
}

// TODO use dirname
bool GetDirectory(const char* absolutePath, std::string& directory)
{
    directory.assign(absolutePath);
    size_t lastSlash = directory.rfind('/');
    if (lastSlash != std::string::npos)
    {
        directory.erase(lastSlash);
        return true;
    }

    return false;
}

//
// Get the absolute path given the environment variable.
//
// Return true in case of a success, false otherwise.
//
bool GetEnvAbsolutePath(const char* env_var, std::string& absolutePath)
{
    const char* filesPathLocal = std::getenv(env_var);;
    if (filesPathLocal == nullptr)
    {
        std::cerr << "$" << env_var << " was empty" << std::endl;
        return false;
    }

    if (!GetAbsolutePath(filesPathLocal, absolutePath))
    {
        std::cerr << "Failed to get absolute path for " << env_var << std::endl;
        return false;
    }

    return true;
}

void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
{
    const char * const tpaExtensions[] = {
        ".ni.dll",      // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
        ".dll",
        ".ni.exe",
        ".exe",
    };

    DIR* dir = opendir(directory);
    if (dir == nullptr)
    {
        return;
    }

    std::set<std::string> addedAssemblies;

    // Walk the directory for each extension separately so that we first get files with .ni.dll extension,
    // then files with .dll extension, etc.
    for (unsigned int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++)
    {
        const char* ext = tpaExtensions[extIndex];
        int extLength = strlen(ext);

        struct dirent* entry;

        // For all entries in the directory
        while ((entry = readdir(dir)) != nullptr)
        {
            // We are interested in files only
            switch (entry->d_type)
            {
            case DT_REG:
                break;

                // Handle symlinks and file systems that do not support d_type
            case DT_LNK:
            case DT_UNKNOWN:
            {
                std::string fullFilename;

                fullFilename.append(directory);
                fullFilename.append("/");
                fullFilename.append(entry->d_name);

                struct stat sb;
                if (stat(fullFilename.c_str(), &sb) == -1)
                {
                    continue;
                }

                if (!S_ISREG(sb.st_mode))
                {
                    continue;
                }
            }
            break;

            default:
                continue;
            }

            std::string filename(entry->d_name);

            // Check if the extension matches the one we are looking for
            int extPos = filename.length() - extLength;
            if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0))
            {
                continue;
            }

            std::string filenameWithoutExt(filename.substr(0, extPos));

            // Make sure if we have an assembly with multiple extensions present,
            // we insert only one version of it.
            if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
            {
                addedAssemblies.insert(filenameWithoutExt);

                tpaList.append(directory);
                tpaList.append("/");
                tpaList.append(filename);
                tpaList.append(":");
            }
        }

        // Rewind the directory stream to be able to iterate over it for the next extension
        rewinddir(dir);
    }

    closedir(dir);
}

//
// Below is our custom start/stop interface
//
int startCoreCLR(
    const char* tpaList,
    const char* appPath,
    const char* nativeDllSearchDirs,
    const char* appDomainFriendlyName,
    void** hostHandle,
    unsigned int* domainId)
{
    // get path to current executable
    char exePath[PATH_MAX] = { 0 };
    readlink("/proc/self/exe", exePath, PATH_MAX);

    // get the CoreCLR root path
    std::string clrFilesAbsolutePath;
    if(!GetEnvAbsolutePath("CORE_ROOT", clrFilesAbsolutePath))
    {
        return -1;
    }

    // get the CoreCLR shared library path
    std::string coreClrDllPath(clrFilesAbsolutePath);
    coreClrDllPath.append("/");
    coreClrDllPath.append(coreClrDll);

    if (coreClrDllPath.size() >= PATH_MAX)
    {
        std::cerr << "Absolute path to CoreCLR library too long" << std::endl;
        return 1;
    }

    // open the shared library
    coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW|RTLD_LOCAL);
    if (coreclrLib == nullptr)
    {
        char* error = dlerror();
        std::cerr << "dlopen failed to open the CoreCLR library: " << error << std::endl;
        return 2;
    }

    // query and verify the function pointers
    initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib,"coreclr_initialize");
    shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib,"coreclr_shutdown");
    executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib,"coreclr_execute_assembly");
    createDelegate = (CreateDelegateFunction)dlsym(coreclrLib,"coreclr_create_delegate");

    if (initializeCoreCLR == nullptr)
    {
        std::cerr << "function coreclr_initialize not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (executeAssembly == nullptr)
    {
        std::cerr << "function coreclr_execute_assembly not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (shutdownCoreCLR == nullptr)
    {
        std::cerr << "function coreclr_shutdown not found in CoreCLR library" << std::endl;
        return 3;
    }
    if (createDelegate == nullptr)
    {
        std::cerr << "function coreclr_create_delegate not found in CoreCLR library" << std::endl;
        return 3;
    }

    // create list of properties to initialize CoreCLR
    const char* propertyKeys[] = {
        "TRUSTED_PLATFORM_ASSEMBLIES",
        "APP_PATHS",
        "APP_NI_PATHS",
        "NATIVE_DLL_SEARCH_DIRECTORIES",
        "AppDomainCompatSwitch"
    };

    const char* propertyValues[] = {
        tpaList,
        appPath,
        appPath,
        nativeDllSearchDirs,
        "UseLatestBehaviorWhenTFMNotSpecified"
    };

    // initialize CoreCLR
    int status = initializeCoreCLR(
        exePath,
        appDomainFriendlyName,
        sizeof(propertyKeys)/sizeof(propertyKeys[0]),
        propertyKeys,
        propertyValues,
        hostHandle,
        domainId);

    if (0 > status)
    {
        std::cerr << "coreclr_initialize failed - status: " << std::hex << status << std::endl;
        return 4;
    }

    return status;
}

int stopCoreCLR(void* hostHandle, unsigned int domainId)
{
    // shutdown CoreCLR
    int status = shutdownCoreCLR(hostHandle, domainId);
    if (0 > status)
    {
        std::cerr << "coreclr_shutdown failed - status: " << std::hex << status << std::endl;
    }

    // close the dynamic library
    if (0 != dlclose(coreclrLib))
    {
        std::cerr << "failed to close CoreCLR library" << std::endl;
    }

    return status;
}
<|endoftext|>


<commit_before>/**
 ** \file ast/parametric-ast.cc
 ** \brief Implementation of ast::ParametricAst.
 */

#include <ast/parametric-ast.hh>
#include <ast/print.hh>

#include <parser/parse.hh>
#include <parser/parse-result.hh>
#include <ast/cloner.hxx>

namespace ast
{

  ParametricAst::ParametricAst(const std::string& s)
    : exp_map_type("exp")
    , id_map_type("id")
    , exps_map_type("exps")
    , ast_(parser::parse(s)->ast_xget())
    , effective_location_()
    , count_(0)
  {
    /*  Simplify the result as much as possible
     *
     *  Typically, even when parsing "42", the result is included in a
     *  useless singleton nary and a statement.
     */

    ast::rConstNary nary = ast_.unchecked_cast<const ast::Nary>();
    passert("ParametricAst result is not a Nary", nary);

    // Remove useless nary and statement if there.s only one child
    if (nary->children_get().size() == 1)
    {
      ast::rConstStmt stmt = nary->children_get().front().unsafe_cast<const ast::Stmt>();
      passert("ParametricAst's Nary child isn't a statement", stmt);
      ast_ = stmt->expression_get();
    }
  }

  ParametricAst::~ParametricAst()
  {
    passert(*this, empty());
  }

  void
  ParametricAst::visit(const ast::MetaArgs* e)
  {
    ast::rLValue lvalue = recurse(e->lvalue_get());
    lvalue->call()->arguments_set(exps_map_type::take_(e->id_get () - 1));
    result_ = lvalue;
  }

  void
  ParametricAst::visit(const ast::MetaCall* e)
  {
    libport::Symbol name = id_map_type::take_(e->id_get () - 1);

    result_ = new ast::Call(e->location_get(),
                            recurse_collection(e->arguments_get()),
                            recurse(e->target_get()), name);
  }

  void
  ParametricAst::visit(const ast::MetaExp* e)
  {
    result_ = exp_map_type::take_(e->id_get () - 1);
    assert(result_);
  }

  void
  ParametricAst::visit(const ast::MetaLValue* e)
  {
    result_ = exp_map_type::take_(e->id_get () - 1);
    assert(result_.unsafe_cast<const ast::LValue>());
    assert(result_);
  }

  bool
  ParametricAst::empty() const
  {
    return exp_map_type::empty_()
      && id_map_type::empty_()
      && exps_map_type::empty_();
  }

  void
  ParametricAst::reset()
  {
    passert(*this, empty());
#ifndef NDEBUG
    unique_.clear();
#endif
    effective_location_.initialize(0);
    count_ = 0;
  }

  void
  ParametricAst::clear()
  {
    exp_map_type::clear_();
    id_map_type::clear_();
    exps_map_type::empty_();
    reset();
  }

  std::ostream&
  ParametricAst::dump(std::ostream& o) const
  {
    return o
      << "ParametricAst:"
      << libport::incendl
      << "Ast:"
      << libport::incendl << *ast_ << libport::decendl
      << static_cast<const exp_map_type&>(*this)
      << static_cast<const id_map_type&>(*this)
      << static_cast<const exps_map_type&>(*this)
      << libport::decendl;
  }

  /*--------------------------.
  | Free-standing functions.  |
  `--------------------------*/

  rExp
  exp(ParametricAst& a)
  {
    return a.result<Exp>();
  }

  std::ostream&
  operator<< (std::ostream& o, const ParametricAst& a)
  {
    return a.dump(o);
  }

  ParametricAst&
  ParametricAst::operator% (libport::shared_ptr<ast::Exp, true> t)
  {
#ifndef NDEBUG
    passert(libport::deref << t, unique_(t.get()));
#endif

    // Strangely, the exp_map_type qualification is required
    // here. Factoring the two % operator in a template method is thus
    // impossible.
    exp_map_type::append_(count_, t);
    // Compute the location of the source text we used.
    if (!effective_location_.begin.filename)
      effective_location_ = t->location_get();
    else
      effective_location_ = effective_location_ + t->location_get();
    return *this;
  }

  ParametricAst&
  ParametricAst::operator% (libport::Symbol id)
  {
    id_map_type::append_(count_, id);
    return *this;
  }

  ParametricAst&
  ParametricAst::operator% (ast::exps_type* exps)
  {
#ifndef NDEBUG
    passert(libport::deref << exps, unique_(exps));
#endif
    exps_map_type::append_(count_, exps);
    return *this;
  }

} // namespace ast
<commit_msg>Do not assert that Implicit are not shared, since they are.<commit_after>/**
 ** \file ast/parametric-ast.cc
 ** \brief Implementation of ast::ParametricAst.
 */

#include <ast/parametric-ast.hh>
#include <ast/print.hh>

#include <parser/parse.hh>
#include <parser/parse-result.hh>
#include <ast/cloner.hxx>

namespace ast
{

  ParametricAst::ParametricAst(const std::string& s)
    : exp_map_type("exp")
    , id_map_type("id")
    , exps_map_type("exps")
    , ast_(parser::parse(s)->ast_xget())
    , effective_location_()
    , count_(0)
  {
    /*  Simplify the result as much as possible
     *
     *  Typically, even when parsing "42", the result is included in a
     *  useless singleton nary and a statement.
     */

    ast::rConstNary nary = ast_.unchecked_cast<const ast::Nary>();
    passert("ParametricAst result is not a Nary", nary);

    // Remove useless nary and statement if there.s only one child
    if (nary->children_get().size() == 1)
    {
      ast::rConstStmt stmt = nary->children_get().front().unsafe_cast<const ast::Stmt>();
      passert("ParametricAst's Nary child isn't a statement", stmt);
      ast_ = stmt->expression_get();
    }
  }

  ParametricAst::~ParametricAst()
  {
    passert(*this, empty());
  }

  void
  ParametricAst::visit(const ast::MetaArgs* e)
  {
    ast::rLValue lvalue = recurse(e->lvalue_get());
    lvalue->call()->arguments_set(exps_map_type::take_(e->id_get () - 1));
    result_ = lvalue;
  }

  void
  ParametricAst::visit(const ast::MetaCall* e)
  {
    libport::Symbol name = id_map_type::take_(e->id_get () - 1);

    result_ = new ast::Call(e->location_get(),
                            recurse_collection(e->arguments_get()),
                            recurse(e->target_get()), name);
  }

  void
  ParametricAst::visit(const ast::MetaExp* e)
  {
    result_ = exp_map_type::take_(e->id_get () - 1);
    assert(result_);
  }

  void
  ParametricAst::visit(const ast::MetaLValue* e)
  {
    result_ = exp_map_type::take_(e->id_get () - 1);
    assert(result_.unsafe_cast<const ast::LValue>());
    assert(result_);
  }

  bool
  ParametricAst::empty() const
  {
    return exp_map_type::empty_()
      && id_map_type::empty_()
      && exps_map_type::empty_();
  }

  void
  ParametricAst::reset()
  {
    passert(*this, empty());
#ifndef NDEBUG
    unique_.clear();
#endif
    effective_location_.initialize(0);
    count_ = 0;
  }

  void
  ParametricAst::clear()
  {
    exp_map_type::clear_();
    id_map_type::clear_();
    exps_map_type::empty_();
    reset();
  }

  std::ostream&
  ParametricAst::dump(std::ostream& o) const
  {
    return o
      << "ParametricAst:"
      << libport::incendl
      << "Ast:"
      << libport::incendl << *ast_ << libport::decendl
      << static_cast<const exp_map_type&>(*this)
      << static_cast<const id_map_type&>(*this)
      << static_cast<const exps_map_type&>(*this)
      << libport::decendl;
  }

  /*--------------------------.
  | Free-standing functions.  |
  `--------------------------*/

  rExp
  exp(ParametricAst& a)
  {
    return a.result<Exp>();
  }

  std::ostream&
  operator<< (std::ostream& o, const ParametricAst& a)
  {
    return a.dump(o);
  }

  ParametricAst&
  ParametricAst::operator% (libport::shared_ptr<ast::Exp, true> t)
  {
#ifndef NDEBUG
    // Implicit are shared
    passert(libport::deref << t, t.unsafe_cast<ast::Implicit>() || unique_(t.get()));
#endif

    // Strangely, the exp_map_type qualification is required
    // here. Factoring the two % operator in a template method is thus
    // impossible.
    exp_map_type::append_(count_, t);
    // Compute the location of the source text we used.
    if (!effective_location_.begin.filename)
      effective_location_ = t->location_get();
    else
      effective_location_ = effective_location_ + t->location_get();
    return *this;
  }

  ParametricAst&
  ParametricAst::operator% (libport::Symbol id)
  {
    id_map_type::append_(count_, id);
    return *this;
  }

  ParametricAst&
  ParametricAst::operator% (ast::exps_type* exps)
  {
#ifndef NDEBUG
    passert(libport::deref << exps, unique_(exps));
#endif
    exps_map_type::append_(count_, exps);
    return *this;
  }

} // namespace ast
<|endoftext|>


<commit_before>#include "Huffman_another.h"
#include "Node_another.h"
#include <iostream>
#include <fstream>
#include <list>
#include <algorithm>

namespace Codecs {

  bool comp(Node* l, Node* r) {
    return l->getFrequency() > r->getFrequency();
  }

  void HuffmanCodec::encode(string& encoded, const string_view& raw) const {
    encoded.reserve(2 * raw.size());
    unsigned char buf = 0;
    int8_t count = CHAR_SIZE;
    size_t j = 0;
    for (size_t i = 0; i < raw.size(); ++i, j = 0) {
    size_t size_of_path = table[static_cast<uint8_t>(raw[i])].size();

      while (j < size_of_path) {
        while (j < size_of_path && count) {
          buf <<= 1;
          buf += table[static_cast<uint8_t>(raw[i])][j];
          ++j;
          --count;
        }
        if (!count) {
          count = CHAR_SIZE;
          encoded.push_back(buf);
          buf = 0;
        }
      }
    }
    if (count != CHAR_SIZE) {
      encoded.push_back(buf << count);
    }
    encoded.push_back(static_cast<uint8_t>(CHAR_SIZE - count));
  }

  void HuffmanCodec::decode(string& raw, const string_view& encoded) const {
    if (encoded.size() == 1) {
      return;
    }
    raw.reserve(2 * encoded.size());
    int64_t count = 0;
    Node* cur = root_for_decode;
    unsigned char byte = encoded[0];
    int64_t encoded_size = static_cast<int64_t>(encoded.size()) - 2;

    //till almost the last element
    for (int64_t i = 0; i < encoded_size; ++i) {
      raw += cur->to_go[byte].first;
      cur = cur->to_go[byte].second;
      byte = encoded[i + 1];
    }

    //last element
    while (true) {
      if (byte & (1 << (CHAR_SIZE - count - 1))) {
        cur = cur->right;
      } else {
        cur = cur->left;
      }
      if (!cur->left) {
        raw.push_back(cur->getData());
        cur = root_for_decode;
      }
      ++count;
      if (count == CHAR_SIZE || encoded[encoded_size + 1] == count) {
        count = 0;
        byte = encoded[encoded_size];
        break;
      }
    }

  }

  string HuffmanCodec::save() const {
    std::ofstream output("config");
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      output << static_cast<uint16_t>(c) << " " << chars[c] << std::endl;
    }
    output.close();
    return string();
  }

  void HuffmanCodec::Build_table(Node* root_for_table, std::string& code) {
    if (root_for_table->left != nullptr) {
      code.push_back(false);
      Build_table(root_for_table->left, code);
    }

    if (root_for_table->right != nullptr) {
      code.push_back(true);
      Build_table(root_for_table->right, code);
    }

    if (root_for_table->left == root_for_table->right) {
      table[static_cast<uint8_t>(root_for_table->getData())] = code;
    }

    code.pop_back();
  }

  void HuffmanCodec::load(const string_view& config) {
    std::ifstream input(config.to_string());
    for (size_t i = 0; i < (1 << CHAR_SIZE); ++i) {
      uint32_t sym;
      uint64_t cnt;
      input >> sym >> cnt;
      chars[static_cast<uint8_t>(sym)] = cnt;
    }

    std::vector<Node*> table_cur;
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      Node* p = new Node(static_cast<uint8_t>(c), chars[c]);
      table_cur.push_back(p);
    }

    while (table_cur.size() != 1) {
      std::stable_sort(table_cur.begin(), table_cur.end(), comp);
      Node* left_son = table_cur.back();
      table_cur.pop_back();
      Node* right_son = table_cur.back();
      table_cur.pop_back();
      Node* parent = new Node(left_son, right_son);
      table_cur.push_back(parent);
    }
    root_for_decode = table_cur.front();
    Node* root_for_table = root_for_decode;

    std::string code;
    Build_table(root_for_table, code);
    code.clear();

    root_for_table = root_for_decode;
    build_jumps(root_for_table);
  }

  size_t HuffmanCodec::sample_size(size_t records_total) const {
    return std::min(static_cast<size_t>(100000), records_total);
  }

  void HuffmanCodec::learn(const StringViewVector& sample) {
    size_t total_count = 0;
    table = new std::string[1 << CHAR_SIZE];
    chars = new uint32_t[1 << CHAR_SIZE];
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      chars[c] = 0;
      table[c] = "";
    }

    for (auto& cur_string : sample) {
      total_count += cur_string.size();
      for (auto& one_char : cur_string) {
        ++chars[static_cast<int32_t>(static_cast<uint8_t>(one_char))];
      }
    }
    std::vector<Node*> table_cur;
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      Node* p = new Node(static_cast<uint8_t>(c), chars[c]);
      table_cur.push_back(p);
    }
    auto it = table_cur.begin();
    while (table_cur.size() != 1) {
      std::stable_sort(it, table_cur.end(), comp);
      Node* left_son = table_cur.back();
      table_cur.pop_back();
      Node* right_son = table_cur.back();
      table_cur.pop_back();
      Node* parent = new Node(left_son, right_son);
      table_cur.push_back(parent);
    }
    root_for_encode = table_cur.front();
    Node* root_for_table = root_for_encode;

    std::string code;
    Build_table(root_for_table, code);
    code.clear();
    code.shrink_to_fit();
  }

  void HuffmanCodec::build_jumps(Node* node) {
    Node* cur;
    for (size_t byte = 0; byte < (1 << CHAR_SIZE); ++byte) {
      cur = node;
      if (!cur->right || !cur->left) {
        // cur = root_for_decode;
        continue;
      }
      for (size_t j = 0; j < CHAR_SIZE; ++j) {
        if (byte & (1 << (CHAR_SIZE - j - 1))) {
          cur = cur->right;
        } else {
          cur = cur->left;
        }
        if (!cur->left) { //is equal to cur->left == nullptr == cur->right
          node->to_go[byte].first.push_back(cur->getData());
          cur = root_for_decode;
        }
      }
      node->to_go[byte].second = cur;
    }
    if (node->left != nullptr) {
      build_jumps(node->left);
      build_jumps(node->right);
    }
  }

  void HuffmanCodec::reset() {
    delete[] table;
    delete[] chars;
    delete root_for_decode;
    delete root_for_encode;
  }
}  // namespace Codecs
<commit_msg>encode works 14% faster<commit_after>#include "Huffman_another.h"
#include "Node_another.h"
#include <fstream>
#include <algorithm>

namespace Codecs {

  bool comp(Node* l, Node* r) {
    return l->getFrequency() > r->getFrequency();
  }

  void HuffmanCodec::encode(string& encoded, const string_view& raw) const {
    encoded.reserve(2 * raw.size());
    unsigned char buf = 0;
    int8_t count = CHAR_SIZE;
    size_t j = 0;
    for (size_t i = 0; i < raw.size(); ++i, j = 0) {
    size_t size_of_path = table[static_cast<uint8_t>(raw[i])].size();

      while (j < size_of_path) {
        while (j < size_of_path && count) {
          buf <<= 1;
          buf += static_cast<uint8_t>(table[static_cast<uint8_t>(raw[i])][j]);
          ++j;
          --count;
        }
        if (!count) {
          count = CHAR_SIZE;
          encoded.push_back(buf);
          buf = 0;
        }
      }
    }
    if (count != CHAR_SIZE) {
      encoded.push_back(buf << count);
    }
    encoded.push_back(static_cast<uint8_t>(CHAR_SIZE - count));
  }

  void HuffmanCodec::decode(string& raw, const string_view& encoded) const {
    if (__builtin_expect(encoded.size() == 1, false)) {
      return;
    }
    raw.reserve(2 * encoded.size());
    int8_t count = 0;
    Node* cur = root_for_decode;
    unsigned char byte = encoded[0];
    int64_t encoded_size = static_cast<int64_t>(encoded.size()) - 2;

    //till almost the last element
    for (int64_t i = 0; i < encoded_size; ++i) {
      raw += cur->to_go[byte].first;
      cur = cur->to_go[byte].second;
      byte = encoded[i + 1];
    }

    //last element
    while (true) {
      if (byte & (1 << (CHAR_SIZE - count - 1))) {
        cur = cur->right;
      } else {
        cur = cur->left;
      }
      if (!cur->left) {
        raw.push_back(cur->getData());
        cur = root_for_decode;
      }
      ++count;
      if (count == CHAR_SIZE || encoded[encoded_size + 1] == count) {
        count = 0;
        byte = encoded[encoded_size];
        break;
      }
    }

  }

  string HuffmanCodec::save() const {
    std::ofstream output("config");
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      output << static_cast<uint16_t>(c) << " " << chars[c] << std::endl;
    }
    output.close();
    return string();
  }

  void HuffmanCodec::Build_table(Node* root_for_table, std::string& code) {
    if (root_for_table->left != nullptr) {
      code.push_back(false);
      Build_table(root_for_table->left, code);
    }

    if (root_for_table->right != nullptr) {
      code.push_back(true);
      Build_table(root_for_table->right, code);
    }

    if (root_for_table->left == root_for_table->right) {
      table[root_for_table->getData()] = code;
    }

    code.pop_back();
  }

  void HuffmanCodec::load(const string_view& config) {
    std::ifstream input(config.to_string());
    for (size_t i = 0; i < (1 << CHAR_SIZE); ++i) {
      uint32_t sym;
      uint64_t cnt;
      input >> sym >> cnt;
      chars[static_cast<uint8_t>(sym)] = cnt;
    }

    std::vector<Node*> table_cur;
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      Node* p = new Node(static_cast<uint8_t>(c), chars[c]);
      table_cur.push_back(p);
    }

    while (table_cur.size() != 1) {
      std::stable_sort(table_cur.begin(), table_cur.end(), comp);
      Node* left_son = table_cur.back();
      table_cur.pop_back();
      Node* right_son = table_cur.back();
      table_cur.pop_back();
      Node* parent = new Node(left_son, right_son);
      table_cur.push_back(parent);
    }
    root_for_decode = table_cur.front();
    Node* root_for_table = root_for_decode;

    std::string code;
    Build_table(root_for_table, code);
    code.clear();

    root_for_table = root_for_decode;
    build_jumps(root_for_table);
  }

  size_t HuffmanCodec::sample_size(size_t records_total) const {
    return std::min(static_cast<size_t>(100000), records_total);
  }

  void HuffmanCodec::learn(const StringViewVector& sample) {
    size_t total_count = 0;
    table = new std::string[1 << CHAR_SIZE];
    chars = new uint32_t[1 << CHAR_SIZE];
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      chars[c] = 0;
      table[c] = "";
    }

    for (const auto& cur_string : sample) {
      total_count += cur_string.size();
      for (const auto& one_char : cur_string) {
        ++chars[static_cast<int32_t>(static_cast<uint8_t>(one_char))];
      }
    }
    std::vector<Node*> table_cur;
    for (int32_t c = 0; c < (1 << CHAR_SIZE); ++c) {
      Node* p = new Node(static_cast<uint8_t>(c), chars[c]);
      table_cur.push_back(p);
    }
    auto it = table_cur.begin();
    while (table_cur.size() != 1) {
      std::stable_sort(it, table_cur.end(), comp);
      Node* left_son = table_cur.back();
      table_cur.pop_back();
      Node* right_son = table_cur.back();
      table_cur.pop_back();
      Node* parent = new Node(left_son, right_son);
      table_cur.push_back(parent);
    }
    root_for_encode = table_cur.front();
    Node* root_for_table = root_for_encode;

    std::string code;
    Build_table(root_for_table, code);
    code.clear();
    code.shrink_to_fit();
  }

  void HuffmanCodec::build_jumps(Node* node) {
    Node* cur;
    for (size_t byte = 0; byte < (1 << CHAR_SIZE); ++byte) {
      cur = node;
      if (!cur->right || !cur->left) {
        // cur = root_for_decode;
        continue;
      }
      for (size_t j = 0; j < CHAR_SIZE; ++j) {
        if (byte & (1 << (CHAR_SIZE - j - 1))) {
          cur = cur->right;
        } else {
          cur = cur->left;
        }
        if (!cur->left) { //is equal to cur->left == nullptr == cur->right
          node->to_go[byte].first.push_back(cur->getData());
          cur = root_for_decode;
        }
      }
      node->to_go[byte].second = cur;
    }
    if (node->left != nullptr) {
      build_jumps(node->left);
      build_jumps(node->right);
    }
  }

  void HuffmanCodec::reset() {
    delete[] table;
    delete[] chars;
    delete root_for_decode;
    delete root_for_encode;
  }
}  // namespace Codecs
<|endoftext|>


<commit_before>#include <ncurses.h>
#include <iostream>
#include <unistd.h>
#include <algorithm>

#include "display/Screen.h"
#include "display/Window.h"
#include "display/WindowManager.h"
#include "map/Level.h"
#include "map/filters/DrunkardsWalkFilter.h"
#include "actor/Actor.h"
#include "core/Rand.h"

void pause_curses(Screen& screen)
{
	screen.pause();

	std::cout << "Paused ncurses..." << std::endl;

	sleep(4);

	std::cout << "Resuming..." << std::endl;

	sleep(1);
}

bool move_pc(Actor& pc, Level& level, int& pc_x, int& pc_y, int dx, int dy)
{
	int new_x = pc_x + dx;
	int new_y = pc_y + dy;

	//Make sure it's in bounds
	if(0 <= new_x && new_x < level.getWidth() && 0 <= new_y && new_y < level.getHeight())
	{
		//Make sure it's passable terrain
		if(level[new_x][new_y].isPassable())
		{
			//Remove the PC from its old position
			level[pc_x][pc_y].removeActor();

			//Adjust PC's x,y coordinates
			pc_x += dx;
			pc_y += dy;

			//Place the PC at the new x,y coordinates
			level[pc_x][pc_y].addActor(&pc);

			return true;
		}
	}
	return false;
}

void spawn_npc(Actor& npc, Level& level, int& npc_x, int& npc_y, int pc_x, int pc_y, int max_dist = 35)
{
	Rand rand(time(NULL));

	int min_x = std::max(0, pc_x - max_dist);
	int max_x = std::min(level.getWidth()-1, pc_x + max_dist);

	int min_y = std::max(0, pc_y - max_dist);
	int max_y = std::min(level.getHeight()-1, pc_y + max_dist);

	do {
		npc_x = rand.randInt(min_x, max_x);
		npc_y = rand.randInt(min_y, max_y);
	} while(level[npc_x][npc_y] != FloorTile);
	level[npc_x][npc_y].addActor(&npc);
}

int main()
{
	Screen screen;

	int screen_y = screen.getHeight();
	int screen_x = screen.getWidth();

	//Make a map double the screen size
	int map_y = screen_y * 2;
	int map_x = screen_x * 2;
	//Generate a map
	Level cave(map_x, map_y);
	DrunkardsWalkFilter walk;
	walk.setSeed(time(NULL));
	walk.apply(cave);
	//Find a random FloorTile to put our PC on
	int pc_x, pc_y;
	Actor pc('@', "PC", 0x01);
	Rand rand(time(NULL));
	do {
		pc_x = rand.randInt(0, cave.getWidth()-1);
		pc_y = rand.randInt(0, cave.getHeight()-1);
	} while(cave[pc_x][pc_y] != FloorTile);
	cave[pc_x][pc_y].addActor(&pc);
	//Now put the map into our map window...
	Window level_window(&cave);
	//...and create a viewport looking into it.
	Window map(&level_window, screen_x-20, screen_y-3, 20, 3);

	Window top(screen_x, 3, 0, 0);
	Window left(20, screen_y-2, 0, 2);

	top.addBorder();
	left.addBorder();
	//map.addBorder(); //Dare I try it?
	//Push our windows into our WindowManager
	WindowManager wm;
	wm.addWindow(&top);
	wm.addWindow(&left);
	wm.addWindow(&map);

	wm.getWindow(0)->add(1, 0, "Message Panel");
	wm.getWindow(1)->add(1, 0, "Stat Panel");

	//Center the map viewport on the PC
	map.center(pc_x, pc_y);

	//Let's display some map display stats
	//Display our view's X and Y coordinates
	wm.getWindow(1)->add(1, 2, "View Position:");
	wm.getWindow(1)->add(1, 3, "X:     ");
	wm.getWindow(1)->addInt(4, 3, map.getViewX());
	wm.getWindow(1)->add(1, 4, "Y:     ");
	wm.getWindow(1)->addInt(4, 4, map.getViewY());

	//Display map size
	wm.getWindow(1)->add(1, 6, "Map Size:");
	wm.getWindow(1)->add(1, 7, "W:");
	wm.getWindow(1)->addInt(4, 7, cave.getWidth());
	wm.getWindow(1)->add(1, 8, "H:");
	wm.getWindow(1)->addInt(4, 8, cave.getHeight());

	//Display viewport size
	wm.getWindow(1)->add(1, 9, "View Size:");
	wm.getWindow(1)->add(1, 10, "W:");
	wm.getWindow(1)->addInt(4, 10, map.getViewWidth());
	wm.getWindow(1)->add(1, 11, "H:");
	wm.getWindow(1)->addInt(4, 11, map.getViewHeight());

	//Display PC's location
	wm.getWindow(1)->add(1, 12, "PC Position:");
	wm.getWindow(1)->add(1, 13, "X:     ");
	wm.getWindow(1)->addInt(4, 13, pc_x);
	wm.getWindow(1)->add(1, 14, "Y:     ");
	wm.getWindow(1)->addInt(4, 14, pc_y);

	//Find a random FloorTile to put our kobold on
	int npc_x, npc_y;
	Actor npc('k', "kobold", 0x00);
	spawn_npc(npc, cave, npc_x, npc_y, pc_x, pc_y, 50);

	//Now display everything
	wm.refresh();

	//Now we enter the "game loop"
	int ch;
	int key_pos = 8;
	int last_key_pos;
	int dx, dy;
	bool run = true;
	while(run)
	{
		ch = getch();

		//Display the key code
		wm.getWindow(0)->add(key_pos, 1, "                                    ");
		wm.getWindow(0)->addInt(key_pos, 1, ch);

		dx = 0;
		dy = 0;

		wm.getWindow(0)->add(1, 1, "     ");
		last_key_pos = key_pos;
		key_pos = 8;
		switch(ch)
		{
			//Viewport movement
			case KEY_UP:
				wm.getWindow(0)->add(1, 1, "Up");
				dy = -1;
				break;
			case KEY_DOWN:
				wm.getWindow(0)->add(1, 1, "Down");
				dy = 1;
				break;
			case KEY_LEFT:
				wm.getWindow(0)->add(1, 1, "Left");
				dx = -1;
				break;
			case KEY_RIGHT:
				wm.getWindow(0)->add(1, 1, "Right");
				dx = 1;
				break;
			//Orthogonal movement
			case '8':
			case 'k':
				move_pc(pc, cave, pc_x, pc_y, 0, -1);
				break;
			case '2':
			case 'j':
				move_pc(pc, cave, pc_x, pc_y, 0, 1);
				break;
			case '4':
			case 'h':
				move_pc(pc, cave, pc_x, pc_y, -1, 0);
				break;
			case '6':
			case 'l':
				move_pc(pc, cave, pc_x, pc_y, 1, 0);
				break;
			//Diagonal movement
			case '7':
			case 'y':
				move_pc(pc, cave, pc_x, pc_y, -1, -1);
				break;
			case '9':
			case 'u':
				move_pc(pc, cave, pc_x, pc_y, 1, -1);
				break;
			case '1':
			case 'b':
				move_pc(pc, cave, pc_x, pc_y, -1, 1);
				break;
			case '3':
			case 'n':
				move_pc(pc, cave, pc_x, pc_y, 1, 1);
				break;
			//Other commands
			case 'c':
			case 'C':
				//Center the view on the PC
				wm.getWindow(2)->center(pc_x, pc_y);
				break;
			case 'p':
			case 'P':
				//Pause ncurses (just a useless demo of the ability)
				pause_curses(screen);
				break;
			case 'q':
			case 'Q':
				//Quit
				run = false;
				break;
			default:
				key_pos = last_key_pos + 4;
				if(key_pos > wm.getWindow(0)->getWidth())
				{
					key_pos = 8;
				}
				break;
		}

		//If the PC "killed" the kobold, spawn another
		if(npc_x == pc_x && npc_y == pc_y)
		{
			spawn_npc(npc, cave, npc_x, npc_y, pc_x, pc_y);
		}

		//Move the viewport
		map.moveBy(dx, dy);

		//Display our view's X and Y coordinates
		wm.getWindow(1)->add(1, 3, "X:     ");
		wm.getWindow(1)->addInt(4, 3, map.getViewX());
		wm.getWindow(1)->add(1, 4, "Y:     ");
		wm.getWindow(1)->addInt(4, 4, map.getViewY());

		//Re-display PC's position
		wm.getWindow(1)->add(1, 13, "X:     ");
		wm.getWindow(1)->addInt(4, 13, pc_x);
		wm.getWindow(1)->add(1, 14, "Y:     ");
		wm.getWindow(1)->addInt(4, 14, pc_y);

		//Display NPC's position
		wm.getWindow(1)->add(1, 15, "NPC Position:");
		wm.getWindow(1)->add(1, 16, "X:     ");
		wm.getWindow(1)->addInt(4, 16, npc_x);
		wm.getWindow(1)->add(1, 17, "Y:     ");
		wm.getWindow(1)->addInt(4, 17, npc_y);

		//Refresh the display
		wm.refresh();
	}
}
<commit_msg>Refactor PC movement controls.<commit_after>#include <ncurses.h>
#include <iostream>
#include <unistd.h>
#include <algorithm>

#include "display/Screen.h"
#include "display/Window.h"
#include "display/WindowManager.h"
#include "map/Level.h"
#include "map/filters/DrunkardsWalkFilter.h"
#include "actor/Actor.h"
#include "core/Rand.h"

void pause_curses(Screen& screen)
{
	screen.pause();

	std::cout << "Paused ncurses..." << std::endl;

	sleep(4);

	std::cout << "Resuming..." << std::endl;

	sleep(1);
}

bool move_pc(Actor& pc, Level& level, int& pc_x, int& pc_y, int dx, int dy)
{
	int new_x = pc_x + dx;
	int new_y = pc_y + dy;

	//Make sure it's in bounds
	if(0 <= new_x && new_x < level.getWidth() && 0 <= new_y && new_y < level.getHeight())
	{
		//Make sure it's passable terrain
		if(level[new_x][new_y].isPassable())
		{
			//Remove the PC from its old position
			level[pc_x][pc_y].removeActor();

			//Adjust PC's x,y coordinates
			pc_x += dx;
			pc_y += dy;

			//Place the PC at the new x,y coordinates
			level[pc_x][pc_y].addActor(&pc);

			return true;
		}
	}
	return false;
}

void spawn_npc(Actor& npc, Level& level, int& npc_x, int& npc_y, int pc_x, int pc_y, int max_dist = 35)
{
	Rand rand(time(NULL));

	int min_x = std::max(0, pc_x - max_dist);
	int max_x = std::min(level.getWidth()-1, pc_x + max_dist);

	int min_y = std::max(0, pc_y - max_dist);
	int max_y = std::min(level.getHeight()-1, pc_y + max_dist);

	do {
		npc_x = rand.randInt(min_x, max_x);
		npc_y = rand.randInt(min_y, max_y);
	} while(level[npc_x][npc_y] != FloorTile);
	level[npc_x][npc_y].addActor(&npc);
}

int main()
{
	Screen screen;

	int screen_y = screen.getHeight();
	int screen_x = screen.getWidth();

	//Make a map double the screen size
	int map_y = screen_y * 2;
	int map_x = screen_x * 2;
	//Generate a map
	Level cave(map_x, map_y);
	DrunkardsWalkFilter walk;
	walk.setSeed(time(NULL));
	walk.apply(cave);
	//Find a random FloorTile to put our PC on
	int pc_x, pc_y;
	Actor pc('@', "PC", 0x01);
	Rand rand(time(NULL));
	do {
		pc_x = rand.randInt(0, cave.getWidth()-1);
		pc_y = rand.randInt(0, cave.getHeight()-1);
	} while(cave[pc_x][pc_y] != FloorTile);
	cave[pc_x][pc_y].addActor(&pc);
	//Now put the map into our map window...
	Window level_window(&cave);
	//...and create a viewport looking into it.
	Window map(&level_window, screen_x-20, screen_y-3, 20, 3);

	Window top(screen_x, 3, 0, 0);
	Window left(20, screen_y-2, 0, 2);

	top.addBorder();
	left.addBorder();
	//map.addBorder(); //Dare I try it?
	//Push our windows into our WindowManager
	WindowManager wm;
	wm.addWindow(&top);
	wm.addWindow(&left);
	wm.addWindow(&map);

	wm.getWindow(0)->add(1, 0, "Message Panel");
	wm.getWindow(1)->add(1, 0, "Stat Panel");

	//Center the map viewport on the PC
	map.center(pc_x, pc_y);

	//Let's display some map display stats
	//Display our view's X and Y coordinates
	wm.getWindow(1)->add(1, 2, "View Position:");
	wm.getWindow(1)->add(1, 3, "X:     ");
	wm.getWindow(1)->addInt(4, 3, map.getViewX());
	wm.getWindow(1)->add(1, 4, "Y:     ");
	wm.getWindow(1)->addInt(4, 4, map.getViewY());

	//Display map size
	wm.getWindow(1)->add(1, 6, "Map Size:");
	wm.getWindow(1)->add(1, 7, "W:");
	wm.getWindow(1)->addInt(4, 7, cave.getWidth());
	wm.getWindow(1)->add(1, 8, "H:");
	wm.getWindow(1)->addInt(4, 8, cave.getHeight());

	//Display viewport size
	wm.getWindow(1)->add(1, 9, "View Size:");
	wm.getWindow(1)->add(1, 10, "W:");
	wm.getWindow(1)->addInt(4, 10, map.getViewWidth());
	wm.getWindow(1)->add(1, 11, "H:");
	wm.getWindow(1)->addInt(4, 11, map.getViewHeight());

	//Display PC's location
	wm.getWindow(1)->add(1, 12, "PC Position:");
	wm.getWindow(1)->add(1, 13, "X:     ");
	wm.getWindow(1)->addInt(4, 13, pc_x);
	wm.getWindow(1)->add(1, 14, "Y:     ");
	wm.getWindow(1)->addInt(4, 14, pc_y);

	//Find a random FloorTile to put our kobold on
	int npc_x, npc_y;
	Actor npc('k', "kobold", 0x00);
	spawn_npc(npc, cave, npc_x, npc_y, pc_x, pc_y, 50);

	//Now display everything
	wm.refresh();

	//Now we enter the "game loop"
	int ch;
	int key_pos = 8;
	int last_key_pos;
	int dx, dy;
	int pc_dx, pc_dy;
	bool run = true;
	while(run)
	{
		ch = getch();

		//Display the key code
		wm.getWindow(0)->add(key_pos, 1, "                                    ");
		wm.getWindow(0)->addInt(key_pos, 1, ch);

		dx = 0;
		dy = 0;
		pc_dx = 0;
		pc_dy = 0;

		wm.getWindow(0)->add(1, 1, "     ");
		last_key_pos = key_pos;
		key_pos = 8;
		switch(ch)
		{
			//Viewport movement
			case KEY_UP:
				wm.getWindow(0)->add(1, 1, "Up");
				dy = -1;
				break;
			case KEY_DOWN:
				wm.getWindow(0)->add(1, 1, "Down");
				dy = 1;
				break;
			case KEY_LEFT:
				wm.getWindow(0)->add(1, 1, "Left");
				dx = -1;
				break;
			case KEY_RIGHT:
				wm.getWindow(0)->add(1, 1, "Right");
				dx = 1;
				break;
			//Orthogonal movement
			case '8':
			case 'k':
				pc_dx = 0;
				pc_dy = -1;
				break;
			case '2':
			case 'j':
				pc_dx = 0;
				pc_dy = 1;
				break;
			case '4':
			case 'h':
				pc_dx = -1;
				pc_dy = 0;
				break;
			case '6':
			case 'l':
				pc_dx = 1;
				pc_dy = 0;
				break;
			//Diagonal movement
			case '7':
			case 'y':
				pc_dx = -1;
				pc_dy = -1;
				break;
			case '9':
			case 'u':
				pc_dx = 1;
				pc_dy = -1;
				break;
			case '1':
			case 'b':
				pc_dx = -1;
				pc_dy = 1;
				break;
			case '3':
			case 'n':
				pc_dx = 1;
				pc_dy = 1;
				break;
			//Other commands
			case 'c':
			case 'C':
				//Center the view on the PC
				wm.getWindow(2)->center(pc_x, pc_y);
				break;
			case 'p':
			case 'P':
				//Pause ncurses (just a useless demo of the ability)
				pause_curses(screen);
				break;
			case 'q':
			case 'Q':
				//Quit
				run = false;
				break;
			default:
				key_pos = last_key_pos + 4;
				if(key_pos > wm.getWindow(0)->getWidth())
				{
					key_pos = 8;
				}
				break;
		}

		//Move the PC
		if(pc_dx != 0 || pc_dy != 0)
		{
			move_pc(pc, cave, pc_x, pc_y, pc_dx, pc_dy);
		}

		//If the PC "killed" the kobold, spawn another
		if(npc_x == pc_x && npc_y == pc_y)
		{
			spawn_npc(npc, cave, npc_x, npc_y, pc_x, pc_y);
		}

		//Move the viewport
		map.moveBy(dx, dy);

		//Display our view's X and Y coordinates
		wm.getWindow(1)->add(1, 3, "X:     ");
		wm.getWindow(1)->addInt(4, 3, map.getViewX());
		wm.getWindow(1)->add(1, 4, "Y:     ");
		wm.getWindow(1)->addInt(4, 4, map.getViewY());

		//Re-display PC's position
		wm.getWindow(1)->add(1, 13, "X:     ");
		wm.getWindow(1)->addInt(4, 13, pc_x);
		wm.getWindow(1)->add(1, 14, "Y:     ");
		wm.getWindow(1)->addInt(4, 14, pc_y);

		//Display NPC's position
		wm.getWindow(1)->add(1, 15, "NPC Position:");
		wm.getWindow(1)->add(1, 16, "X:     ");
		wm.getWindow(1)->addInt(4, 16, npc_x);
		wm.getWindow(1)->add(1, 17, "Y:     ");
		wm.getWindow(1)->addInt(4, 17, npc_y);

		//Refresh the display
		wm.refresh();
	}
}
<|endoftext|>


<commit_before>#include <vector>
#include <limits>
#include <utility>

class Stn {
public:
	typedef int Time;

	Stn(unsigned int);

	Stn(const Stn &);

	void grow(unsigned int);

	void undo(void);

	Time lower(unsigned int n) { return nodes[n].tozero; }

	Time upper(unsigned int n) { return nodes[n].fromzero; }

	unsigned int nnodes(void) { return nodes.size(); }

	struct Constraint {
		unsigned int i, j;
		Time a, b;
	};

	bool add(const Constraint &);

private:
	static Time inf(void) {
		return std::numeric_limits<Time>::max();
	}

	static Time neginf(void) {
		return std::numeric_limits<Time>::min();
	}

	static Time sub_clamp(Time a, Time b) {
		if (b >= 0) {
			Time t = Stn::neginf() + b;
			if (a < t)
				return Stn::neginf();
			return a - b;
		}
		Time t = Stn::inf() + b;
		if (a > t)
			return Stn::inf();
		return a - b;
	}

	static Time add_clamp(Time a, Time b) {
		if (b >= 0) {
			Time t = Stn::inf() - b;
			if (a > t)
				return Stn::inf();
			return a + b;
		}
		Time t = Stn::neginf() - b;
		if (a < t)
			return Stn::neginf();
		return a + b;
	}

	struct Node;
	typedef std::pair<Node*,Time> Arc;

	struct Node {
		std::vector<Arc> out;
		std::vector<Arc> in;

		unsigned int id;
		Time tozero;
		Time fromzero;

		Node(void) {
			tozero = Stn::neginf();
			fromzero = Stn::inf();
		}
	};

	struct Undo {
		std::vector<Node*> popout;
		std::vector< std::pair<Node*, Time> > prevto;
		std::vector< std::pair<Node*, Time> > prevfrom;
	};

	bool propagate(Undo&, const Constraint&);
	bool proplower(Undo&, bool[], bool[], Node&);
	bool propupper(Undo&, bool[], bool[], Node&);
	void addarcs(Undo&, const Constraint&);

	std::vector<Node> nodes;
	std::vector<Undo> undos;
};<commit_msg>Make time values longs instead of ints.<commit_after>#include <vector>
#include <limits>
#include <utility>

class Stn {
public:
	typedef long Time;

	Stn(unsigned int);

	Stn(const Stn &);

	void grow(unsigned int);

	void undo(void);

	Time lower(unsigned int n) { return nodes[n].tozero; }

	Time upper(unsigned int n) { return nodes[n].fromzero; }

	unsigned int nnodes(void) { return nodes.size(); }

	struct Constraint {
		unsigned int i, j;
		Time a, b;
	};

	bool add(const Constraint &);

private:
	static Time inf(void) {
		return std::numeric_limits<Time>::max();
	}

	static Time neginf(void) {
		return std::numeric_limits<Time>::min();
	}

	static Time sub_clamp(Time a, Time b) {
		if (b >= 0) {
			Time t = Stn::neginf() + b;
			if (a < t)
				return Stn::neginf();
			return a - b;
		}
		Time t = Stn::inf() + b;
		if (a > t)
			return Stn::inf();
		return a - b;
	}

	static Time add_clamp(Time a, Time b) {
		if (b >= 0) {
			Time t = Stn::inf() - b;
			if (a > t)
				return Stn::inf();
			return a + b;
		}
		Time t = Stn::neginf() - b;
		if (a < t)
			return Stn::neginf();
		return a + b;
	}

	struct Node;
	typedef std::pair<Node*,Time> Arc;

	struct Node {
		std::vector<Arc> out;
		std::vector<Arc> in;

		unsigned int id;
		Time tozero;
		Time fromzero;

		Node(void) {
			tozero = Stn::neginf();
			fromzero = Stn::inf();
		}
	};

	struct Undo {
		std::vector<Node*> popout;
		std::vector< std::pair<Node*, Time> > prevto;
		std::vector< std::pair<Node*, Time> > prevfrom;
	};

	bool propagate(Undo&, const Constraint&);
	bool proplower(Undo&, bool[], bool[], Node&);
	bool propupper(Undo&, bool[], bool[], Node&);
	void addarcs(Undo&, const Constraint&);

	std::vector<Node> nodes;
	std::vector<Undo> undos;
};<|endoftext|>


<commit_before>#include "../include/LaImageCrop.h"

using namespace std;

LaImageCrop::LaImageCrop()
{
	_x = 0;
    _y = 0;
    _z = 0;
    _size_x = 0;
    _size_y = 0;
    _size_z = 0;
    _image_cropped = ImageTypeInt::New();

}

LaImageCrop::~LaImageCrop() {

	// Remove memory allocated on heap
	//delete _index_image;
}

void LaImageCrop::SetStart(int x, int y, int z) {
    _x = x;
    _y = y;
    _z = z;
}

void LaImageCrop::SetSize(int size_x, int size_y, int size_z){
    _size_x = size_x;
    _size_y = size_y;
    _size_z = size_z;
}

void LaImageCrop::SetInputData(LaImage* img) {
	_image = img;

	int max_x, max_y, max_z;
	 _image->GetImageSize(max_x, max_y, max_z);

    _size_x = max_x;
    _size_y = max_y;
    _size_z = max_z;

}

LaImage* LaImageCrop::GetOutput(){
    //return _image_cropped;
}

void LaImageCrop::Update()
{

    typedef itk::ExtractImageFilter< ImageTypeInt, ImageTypeInt > FilterType;

    // copy structure for index image
 	ImageTypeInt::RegionType region;

    ImageTypeInt::IndexType start;
	start[0] = _x; start[1] = _y; start[2] = _z;

    ImageTypeInt::SizeType size;
	size[0] = _size_x; size[1] = _size_y; size[2] = _size_z;

    region.SetSize(size);
	region.SetIndex(start);

    /*FilterType::Pointer filter = FilterType::New();
    filter->SetExtractionRegion(region);
    filter->SetInput(_image->GetImage());
    #if ITK_VERSION_MAJOR >= 4
    filter->SetDirectionCollapseToIdentity(); // This is required.
    #endif
    filter->Update();

    _image_cropped = filter->GetOutput();
*/

}<commit_msg>windows compilation<commit_after>#include "../include/LaImageCrop.h"

using namespace std;

LaImageCrop::LaImageCrop()
{
	_x = 0;
    _y = 0;
    _z = 0;
    _size_x = 0;
    _size_y = 0;
    _size_z = 0;
    _image_cropped = ImageTypeInt::New();

}

LaImageCrop::~LaImageCrop() {

	// Remove memory allocated on heap
	//delete _index_image;
}

void LaImageCrop::SetStart(int x, int y, int z) {
    _x = x;
    _y = y;
    _z = z;
}

void LaImageCrop::SetSize(int size_x, int size_y, int size_z){
    _size_x = size_x;
    _size_y = size_y;
    _size_z = size_z;
}

void LaImageCrop::SetInputData(LaImage* img) {
	_image = img;

	int max_x, max_y, max_z;
	 _image->GetImageSize(max_x, max_y, max_z);

    _size_x = max_x;
    _size_y = max_y;
    _size_z = max_z;

}

void LaImageCrop::Update()
{

    typedef itk::ExtractImageFilter< ImageTypeInt, ImageTypeInt > FilterType;

    // copy structure for index image
 	ImageTypeInt::RegionType region;

    ImageTypeInt::IndexType start;
	start[0] = _x; start[1] = _y; start[2] = _z;

    ImageTypeInt::SizeType size;
	size[0] = _size_x; size[1] = _size_y; size[2] = _size_z;

    region.SetSize(size);
	region.SetIndex(start);

    /*FilterType::Pointer filter = FilterType::New();
    filter->SetExtractionRegion(region);
    filter->SetInput(_image->GetImage());
    #if ITK_VERSION_MAJOR >= 4
    filter->SetDirectionCollapseToIdentity(); // This is required.
    #endif
    filter->Update();

    _image_cropped = filter->GetOutput();
*/

}<|endoftext|>