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

#ifndef DATE_HPP
#define DATE_HPP

#include <ctime>

#include "utils.hpp"

namespace budget {

using date_type = unsigned short;

class date_exception: public std::exception {
    protected:
        std::string _message;

    public:
        date_exception(std::string message) : _message(message){}

        /*!
         * Return the error message.
         * \return The error message.
         */
        const std::string& message() const {
            return _message;
        }

        virtual const char* what() const throw() {
            return _message.c_str();
        }
};

struct day {
    date_type value;
    day(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct month {
    date_type value;
    month(date_type value) : value(value) {}
    operator date_type() const { return value; }

    std::string as_short_string() const {
        static constexpr const char* months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

        return months[value-1];
    }

    std::string as_long_string() const {
        static constexpr const char* months[12] = {"January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December"};

        return months[value-1];
    }
};

struct year {
    date_type value;
    year(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct days {
    date_type value;
    explicit days(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct months {
    date_type value;
    explicit months(date_type value) : value(value) {}
    operator date_type() const { return value; }

    months& operator=(date_type value){
        this->value = value;

        return *this;
    }
};

struct years {
    date_type value;
    explicit years(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct date;

std::ostream& operator<<(std::ostream& stream, const month& month);
std::ostream& operator<<(std::ostream& stream, const date& date);

struct date {
    date_type _year;
    date_type _month;
    date_type _day;

    explicit date(){}

    date(date_type year, date_type month, date_type day) : _year(year), _month(month), _day(day){
        if(year < 1400){
            throw date_exception("Year not in the valid range");
        }

        if(month == 0 || month > 12){
            throw date_exception("Invalid month");
        }

        if(day == 0 || day > days_month(year, month)){
            throw date_exception("Invalid day");
        }
    }

    date(const date& d) : _year(d._year), _month(d._month), _day(d._day) {
        //Nothing else
    }

    budget::year year() const {
        return _year;
    }

    budget::month month() const {
        return _month;
    }

    budget::day day() const {
        return _day;
    }

    static date_type days_month(date_type year, date_type month){
        static constexpr const date_type month_days[12] = {31,0,31,30,31,30,31,31,30,31,30,31};

        if(month == 2){
            return is_leap(year) ? 29 : 28;
        } else {
            return month_days[month - 1];
        }
    }

    static bool is_leap(date_type year){
        return
                ((year % 4 == 0) && year % 100 != 0)
            ||  year % 400 == 0;
    }

    bool is_leap() const {
        return is_leap(_year);
    }

    date end_of_month(){
        return {_year, _month, days_month(_year, _month)};
    }

    date& operator+=(years years){
        if(years >= std::numeric_limits<date_type>::max() - _year){
            throw date_exception("Year too high (will overflow)");
        }

        _year += years;

        return *this;
    }

    date& operator+=(months months){
        // Handle the NOP addition
        if(months == 0){
            return *this;
        }

        // First add several years if necessary
        if (months >= 12) {
            *this += years(months.value / 12);
            months = months.value % 12;
        }

        // Add the remaining months
        _month += months;

        // Update the year if necessary
        if(_month > 12){
            *this += years((_month - 1) / 12);
            _month = (_month) % 12;
        }

        // Update the day of month, if necessary
        _day = std::min(_day, days_month(_year, _month));

        return *this;
    }

    date& operator+=(days d){
        while(d > 0){
            ++_day;

            if(_day > days_month(_year, _month)){
                _day = 1;
                ++_month;

                if(_month > 12){
                    _month = 1;
                    ++_year;
                }
            }

            d = days(d - 1);
        }

        return *this;
    }

    date& operator-=(years years){
        if(_year < years){
            throw date_exception("Year too low");
        }

        _year -= years;

        return *this;
    }

    date& operator-=(months months){
        if(_month == months){
            *this -= years(1);
            _month = 12;
        } else if(_month < months){
            *this -= years(months / 12);
            _month -= months % 12;
        } else {
            _month -= months;
        }

        _day = std::min(_day, days_month(_year, _month));

        return *this;
    }

    date& operator-=(days d){
        while(d > 0){
            --_day;
            if(_day == 0){
                --_month;

                if(_month == 0){
                    --_year;
                    _month = 12;
                }

                _day = days_month(_year, _month);
            }

            d = days(d - 1);
        }

        return *this;
    }

    date operator+(years years) const {
        date d(*this);
        d += years;
        return d;
    }

    date operator+(months months) const {
        date d(*this);
        d += months;
        return d;
    }

    date operator+(days days) const {
        date d(*this);
        d += days;
        return d;
    }

    date operator-(years years) const {
        date d(*this);
        d -= years;
        return d;
    }

    date operator-(months months) const {
        date d(*this);
        d -= months;
        return d;
    }

    date operator-(days days) const {
        date d(*this);
        d -= days;
        return d;
    }

    bool operator==(const date& rhs) const {
        return _year == rhs._year && _month == rhs._month && _day == rhs._day;
    }

    bool operator!=(const date& rhs) const {
        return !(*this == rhs);
    }

    bool operator<(const date& rhs) const {
        if(_year < rhs._year){
            return true;
        } else if(_year == rhs._year){
            if(_month < rhs._month){
                return true;
            } else if(_month == rhs._month){
                return _day < rhs._day;
            }
        }

        return false;
    }

    bool operator<=(const date& rhs) const {
        return (*this == rhs) || (*this < rhs);
    }

    bool operator>(const date& rhs) const {
        if(_year > rhs._year){
            return true;
        } else if(_year == rhs._year){
            if(_month > rhs._month){
                return true;
            } else if(_month == rhs._month){
                return _day > rhs._day;
            }
        }

        return false;
    }

    bool operator>=(const date& rhs) const {
        return (*this == rhs) || (*this > rhs);
    }

    date_type operator-(const date& rhs) const {
        if(*this == rhs){
            return 0;
        }

        if(rhs > *this){
            return -(rhs - *this);
        }

        auto x = *this;
        size_t d = 0;

        while(x != rhs){
            x -= days(1);
            ++d;
        }

        return d;
    }
};

date local_day();

date from_string(const std::string& str);
date from_iso_string(const std::string& str);

std::string date_to_string(date date);

template<>
inline std::string to_string(budget::date date){
    return date_to_string(date);
}

unsigned short start_year();
unsigned short start_month(budget::year year);

} //end of namespace budget

#endif
<commit_msg>New operators for month and year<commit_after>//=======================================================================
// Copyright (c) 2013-2017 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DATE_HPP
#define DATE_HPP

#include <ctime>

#include "utils.hpp"

namespace budget {

using date_type = unsigned short;

class date_exception: public std::exception {
    protected:
        std::string _message;

    public:
        date_exception(std::string message) : _message(message){}

        /*!
         * Return the error message.
         * \return The error message.
         */
        const std::string& message() const {
            return _message;
        }

        virtual const char* what() const throw() {
            return _message.c_str();
        }
};

struct day {
    date_type value;
    day(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct month {
    date_type value;
    month(date_type value) : value(value) {}
    operator date_type() const { return value; }

    month& operator=(date_type value){
        this->value = value;

        return *this;
    }

    std::string as_short_string() const {
        static constexpr const char* months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

        return months[value-1];
    }

    std::string as_long_string() const {
        static constexpr const char* months[12] = {"January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December"};

        return months[value-1];
    }
};

struct year {
    date_type value;
    year(date_type value) : value(value) {}
    operator date_type() const { return value; }

    year& operator=(date_type value){
        this->value = value;

        return *this;
    }
};

struct days {
    date_type value;
    explicit days(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct months {
    date_type value;
    explicit months(date_type value) : value(value) {}
    operator date_type() const { return value; }

    months& operator=(date_type value){
        this->value = value;

        return *this;
    }
};

struct years {
    date_type value;
    explicit years(date_type value) : value(value) {}
    operator date_type() const { return value; }
};

struct date;

std::ostream& operator<<(std::ostream& stream, const month& month);
std::ostream& operator<<(std::ostream& stream, const date& date);

struct date {
    date_type _year;
    date_type _month;
    date_type _day;

    explicit date(){}

    date(date_type year, date_type month, date_type day) : _year(year), _month(month), _day(day){
        if(year < 1400){
            throw date_exception("Year not in the valid range");
        }

        if(month == 0 || month > 12){
            throw date_exception("Invalid month");
        }

        if(day == 0 || day > days_month(year, month)){
            throw date_exception("Invalid day");
        }
    }

    date(const date& d) : _year(d._year), _month(d._month), _day(d._day) {
        //Nothing else
    }

    budget::year year() const {
        return _year;
    }

    budget::month month() const {
        return _month;
    }

    budget::day day() const {
        return _day;
    }

    static date_type days_month(date_type year, date_type month){
        static constexpr const date_type month_days[12] = {31,0,31,30,31,30,31,31,30,31,30,31};

        if(month == 2){
            return is_leap(year) ? 29 : 28;
        } else {
            return month_days[month - 1];
        }
    }

    static bool is_leap(date_type year){
        return
                ((year % 4 == 0) && year % 100 != 0)
            ||  year % 400 == 0;
    }

    bool is_leap() const {
        return is_leap(_year);
    }

    date end_of_month(){
        return {_year, _month, days_month(_year, _month)};
    }

    date& operator+=(years years){
        if(years >= std::numeric_limits<date_type>::max() - _year){
            throw date_exception("Year too high (will overflow)");
        }

        _year += years;

        return *this;
    }

    date& operator+=(months months){
        // Handle the NOP addition
        if(months == 0){
            return *this;
        }

        // First add several years if necessary
        if (months >= 12) {
            *this += years(months.value / 12);
            months = months.value % 12;
        }

        // Add the remaining months
        _month += months;

        // Update the year if necessary
        if(_month > 12){
            *this += years((_month - 1) / 12);
            _month = (_month) % 12;
        }

        // Update the day of month, if necessary
        _day = std::min(_day, days_month(_year, _month));

        return *this;
    }

    date& operator+=(days d){
        while(d > 0){
            ++_day;

            if(_day > days_month(_year, _month)){
                _day = 1;
                ++_month;

                if(_month > 12){
                    _month = 1;
                    ++_year;
                }
            }

            d = days(d - 1);
        }

        return *this;
    }

    date& operator-=(years years){
        if(_year < years){
            throw date_exception("Year too low");
        }

        _year -= years;

        return *this;
    }

    date& operator-=(months months){
        if(_month == months){
            *this -= years(1);
            _month = 12;
        } else if(_month < months){
            *this -= years(months / 12);
            _month -= months % 12;
        } else {
            _month -= months;
        }

        _day = std::min(_day, days_month(_year, _month));

        return *this;
    }

    date& operator-=(days d){
        while(d > 0){
            --_day;
            if(_day == 0){
                --_month;

                if(_month == 0){
                    --_year;
                    _month = 12;
                }

                _day = days_month(_year, _month);
            }

            d = days(d - 1);
        }

        return *this;
    }

    date operator+(years years) const {
        date d(*this);
        d += years;
        return d;
    }

    date operator+(months months) const {
        date d(*this);
        d += months;
        return d;
    }

    date operator+(days days) const {
        date d(*this);
        d += days;
        return d;
    }

    date operator-(years years) const {
        date d(*this);
        d -= years;
        return d;
    }

    date operator-(months months) const {
        date d(*this);
        d -= months;
        return d;
    }

    date operator-(days days) const {
        date d(*this);
        d -= days;
        return d;
    }

    bool operator==(const date& rhs) const {
        return _year == rhs._year && _month == rhs._month && _day == rhs._day;
    }

    bool operator!=(const date& rhs) const {
        return !(*this == rhs);
    }

    bool operator<(const date& rhs) const {
        if(_year < rhs._year){
            return true;
        } else if(_year == rhs._year){
            if(_month < rhs._month){
                return true;
            } else if(_month == rhs._month){
                return _day < rhs._day;
            }
        }

        return false;
    }

    bool operator<=(const date& rhs) const {
        return (*this == rhs) || (*this < rhs);
    }

    bool operator>(const date& rhs) const {
        if(_year > rhs._year){
            return true;
        } else if(_year == rhs._year){
            if(_month > rhs._month){
                return true;
            } else if(_month == rhs._month){
                return _day > rhs._day;
            }
        }

        return false;
    }

    bool operator>=(const date& rhs) const {
        return (*this == rhs) || (*this > rhs);
    }

    date_type operator-(const date& rhs) const {
        if(*this == rhs){
            return 0;
        }

        if(rhs > *this){
            return -(rhs - *this);
        }

        auto x = *this;
        size_t d = 0;

        while(x != rhs){
            x -= days(1);
            ++d;
        }

        return d;
    }
};

date local_day();

date from_string(const std::string& str);
date from_iso_string(const std::string& str);

std::string date_to_string(date date);

template<>
inline std::string to_string(budget::date date){
    return date_to_string(date);
}

unsigned short start_year();
unsigned short start_month(budget::year year);

} //end of namespace budget

#endif
<|endoftext|>


<commit_before>#ifndef hSDK_HeaderPlusPlus
#define hSDK_HeaderPlusPlus
#include <string>
#include <tuple>

class mv;

namespace hSDK
{
	static_assert(sizeof(void *) == 4 && sizeof(std::size_t) == 4, "MMF2 only supports 32-bit extensions");

#ifdef UNICODE
		using char_t = wchar_t;
		#define T_ L
#else
		using char_t = char;
		#define T_
#endif
		using string = std::basic_string<char_t>;

		struct ED;
		struct RD;

		struct tuple_unpack final
		{
			template<int...> struct seq {};
			template<int N, int... S> struct gens : gens<N-1, N-1, S...> {};
			template<int... S> struct gens<0, S...>
			{
				using type = seq<S...>;
			};
		};

		template<typename T>
		struct identity final
		{
			using type = T;
		};

		template<typename T, typename... V>
		struct RAII_Set_impl final
		{
			T &t;
			std::tuple<typename identity<V T::*>::type...> mop;
			std::tuple<V...> ds;
			RAII_Set_impl(T &t_, std::tuple<V T::*, V, V>... sets)
			: t(t_)
			, mop(std::get<0>(sets)...)
			, ds(std::get<2>(sets)...)
			{
				set(std::get<1>(sets)...);
			}
			~RAII_Set_impl()
			{
				unset(typename tuple_unpack::gens<sizeof...(V)>::type());
			}
			template<typename... U>
			void set(U... u)
			{
				do_set<0, U...>(u...);
			}
			template<std::size_t i, typename First, typename... Rest>
			void do_set(First first, Rest... rest)
			{
				t.*std::get<i>(mop) = first;
				do_set<i+1, Rest...>(rest...);
			}
			template<std::size_t i, typename Last>
			void do_set(Last last)
			{
				t.*std::get<i>(mop) = last;
			}
			template<std::size_t i>
			void do_set()
			{
			}
			template<std::size_t... S>
			void unset(tuple_unpack::seq<S...>)
			{
				set(std::get<S>(ds)...);
			}
		};
		template<typename T, typename... V>
		auto RAII_Set(T &t, std::tuple<V T::*, V, V>... sets)
		-> RAII_Set_impl<T, V...>
		{
			return RAII_Set_impl<T, V...>(t, sets...);
		}
}

#endif
<commit_msg>Fix over-indentation in hSDK.hpp<commit_after>#ifndef hSDK_HeaderPlusPlus
#define hSDK_HeaderPlusPlus
#include <string>
#include <tuple>

class mv;

namespace hSDK
{
	static_assert(sizeof(void *) == 4 && sizeof(std::size_t) == 4, "MMF2 only supports 32-bit extensions");

#ifdef UNICODE
	using char_t = wchar_t;
	#define T_ L
#else
	using char_t = char;
	#define T_
#endif
	using string = std::basic_string<char_t>;

	struct ED;
	struct RD;

	struct tuple_unpack final
	{
		template<int...> struct seq {};
		template<int N, int... S> struct gens : gens<N-1, N-1, S...> {};
		template<int... S> struct gens<0, S...>
		{
			using type = seq<S...>;
		};
	};

	template<typename T>
	struct identity final
	{
		using type = T;
	};

	template<typename T, typename... V>
	struct RAII_Set_impl final
	{
		T &t;
		std::tuple<typename identity<V T::*>::type...> mop;
		std::tuple<V...> ds;
		RAII_Set_impl(T &t_, std::tuple<V T::*, V, V>... sets)
		: t(t_)
		, mop(std::get<0>(sets)...)
		, ds(std::get<2>(sets)...)
		{
			set(std::get<1>(sets)...);
		}
		~RAII_Set_impl()
		{
			unset(typename tuple_unpack::gens<sizeof...(V)>::type());
		}
		template<typename... U>
		void set(U... u)
		{
			do_set<0, U...>(u...);
		}
		template<std::size_t i, typename First, typename... Rest>
		void do_set(First first, Rest... rest)
		{
			t.*std::get<i>(mop) = first;
			do_set<i+1, Rest...>(rest...);
		}
		template<std::size_t i, typename Last>
		void do_set(Last last)
		{
			t.*std::get<i>(mop) = last;
		}
		template<std::size_t i>
		void do_set()
		{
		}
		template<std::size_t... S>
		void unset(tuple_unpack::seq<S...>)
		{
			set(std::get<S>(ds)...);
		}
	};
	template<typename T, typename... V>
	auto RAII_Set(T &t, std::tuple<V T::*, V, V>... sets)
	-> RAII_Set_impl<T, V...>
	{
		return RAII_Set_impl<T, V...>(t, sets...);
	}
}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <array>
#include <tuple>

#include "common.hpp"
#include "components/command_line.hpp"

namespace bookwyrm {

/* Default value: "this value is empty". */
enum { empty = -1 };

/*
 * For --year:
 *   -y 2157   : list items from 2157 (equal)
 *   -y =>2157 : list items from 2157 and later (eq_gt)
 *   -y =<2157 : list items from 2157 and earlier (eq_lt)
 *   -y >2157  : list items from later than 2157 (gt)
 *   -y <2157  : list items from earlier than 2157 (lt)
 */
enum class year_mod { equal, eq_gt, eq_lt, lt, gt };

struct exacts_t {
    /*
     * A POD with added index operator.
     * Useful in item::matches() where we want to
     * iterate over these values and check if they match.
     *
     * We can then get a field value by name, which we'll
     * want when printing the stuff out.
     *
     * Fields are set to "empty" (-1) during construction.
     * This makes us able to bool-check (since -1 is false)
     * whether or not a field is empty or not.
     */
    explicit exacts_t(const std::unique_ptr<cliparser> &cli);
    explicit exacts_t(const std::map<string, int> &dict);

    year_mod ymod;

    int year,
        edition,
        format, // unused for now
        volume,
        number,
        pages,  // missing flag
        lang;   // unused for now

    constexpr static int size = 7;

    std::array<int, size> store = {
        year, edition, format,
        volume, number, pages
    };

    int operator[](int i) const
    {
        return store[i];
    }
};

struct nonexacts_t {
    /*
     * As the typename suggests, this POD contains
     * data that we're not going to match exacly match
     * exactly with the wanted field. Instead, we use
     * fuzzy-matching.
     */
    explicit nonexacts_t(const std::unique_ptr<cliparser> &cli);
    explicit nonexacts_t(const std::map<string, string> &dict, const vector<string> &authors);

    vector<string> authors;
    string title;
    string serie;
    string publisher;
    string journal;
};

struct misc_t {
    /*
     * The POD for everything else and undecided
     * fields.
     */

    vector<string> isbns;
    vector<string> mirrors;
};

class item {
public:
    explicit item(const std::unique_ptr<cliparser> &cli)
        : nonexacts(cli), exacts(cli) {};
    /* Construct an item from a pybind11::tuple. */
    explicit item(const std::tuple<nonexacts_t, exacts_t> &tuple)
        : nonexacts(std::get<0>(tuple)), exacts(std::get<1>(tuple)) {};

    bool matches(const item &wanted);

    friend std::ostream& operator<<(std::ostream &os, item const &i)
    {
        os << "test printout: " + i.nonexacts.serie;
        return os;
    }

    const string& menu_order(int i) const
    {
        return menu_order_[i % menu_order_.size()]; // just in case
    }

    const nonexacts_t nonexacts;
    const exacts_t exacts;
    misc_t misc;

private:
    // TODO: we're wasting space here, I think. Investigate.
    const std::vector<string> menu_order_ = {
        nonexacts.title,
        std::to_string(exacts.year),
        nonexacts.serie,
        "authors",
        nonexacts.publisher,
        "format",
    };

};

/* ns bookwyrm */
}
<commit_msg>item: stringify nonexacts.authors<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <array>
#include <tuple>

#include "common.hpp"
#include "utils.hpp"
#include "components/command_line.hpp"

namespace bookwyrm {

/* Default value: "this value is empty". */
enum { empty = -1 };

/*
 * For --year:
 *   -y 2157   : list items from 2157 (equal)
 *   -y =>2157 : list items from 2157 and later (eq_gt)
 *   -y =<2157 : list items from 2157 and earlier (eq_lt)
 *   -y >2157  : list items from later than 2157 (gt)
 *   -y <2157  : list items from earlier than 2157 (lt)
 */
enum class year_mod { equal, eq_gt, eq_lt, lt, gt };

struct exacts_t {
    /*
     * A POD with added index operator.
     * Useful in item::matches() where we want to
     * iterate over these values and check if they match.
     *
     * We can then get a field value by name, which we'll
     * want when printing the stuff out.
     *
     * Fields are set to "empty" (-1) during construction.
     * This makes us able to bool-check (since -1 is false)
     * whether or not a field is empty or not.
     */
    explicit exacts_t(const std::unique_ptr<cliparser> &cli);
    explicit exacts_t(const std::map<string, int> &dict);

    year_mod ymod;

    int year,
        edition,
        format, // unused for now
        volume,
        number,
        pages,  // missing flag
        lang;   // unused for now

    constexpr static int size = 7;

    std::array<int, size> store = {
        year, edition, format,
        volume, number, pages
    };

    int operator[](int i) const
    {
        return store[i];
    }
};

struct nonexacts_t {
    /*
     * As the typename suggests, this POD contains
     * data that we're not going to match exacly match
     * exactly with the wanted field. Instead, we use
     * fuzzy-matching.
     */
    explicit nonexacts_t(const std::unique_ptr<cliparser> &cli);
    explicit nonexacts_t(const std::map<string, string> &dict, const vector<string> &authors);

    vector<string> authors;
    string title;
    string serie;
    string publisher;
    string journal;
};

struct misc_t {
    /*
     * The POD for everything else and undecided
     * fields.
     */

    vector<string> isbns;
    vector<string> mirrors;
};

class item {
public:
    explicit item(const std::unique_ptr<cliparser> &cli)
        : nonexacts(cli), exacts(cli) {};
    /* Construct an item from a pybind11::tuple. */
    explicit item(const std::tuple<nonexacts_t, exacts_t> &tuple)
        : nonexacts(std::get<0>(tuple)), exacts(std::get<1>(tuple)) {};

    bool matches(const item &wanted);

    friend std::ostream& operator<<(std::ostream &os, item const &i)
    {
        os << "test printout: " + i.nonexacts.serie;
        return os;
    }

    const string& menu_order(int i) const
    {
        return menu_order_[i % menu_order_.size()]; // just in case
    }

    const nonexacts_t nonexacts;
    const exacts_t exacts;
    misc_t misc;

private:
    // TODO: we're wasting space here, I think. Investigate.
    const std::vector<string> menu_order_ = {
        nonexacts.title,
        std::to_string(exacts.year),
        nonexacts.serie,
        utils::vector_to_string(nonexacts.authors),
        nonexacts.publisher,
        "format (TODO)",
    };

};

/* ns bookwyrm */
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <map>

#include "numpy_import.h"
#ifdef NO_IMPORT_ARRAY
#undef NO_IMPORT_ARRAY
#endif
#include "numpy/arrayobject.h"
#include "Python.h"

#include "datarobot2d.h"
#include "utils.h"

#define ARGS_NUM_CHECK(NUM)  if (PyTuple_GET_SIZE(cpp_args) != NUM) { \
                                 PyErr_SetString(kageext_error, "need NUM args"); \
                                 return NULL; \
                           }

const std::string EXT_VERSION = "0.1";
static PyObject *kageext_error;
static std::map<std::string, std::shared_ptr<DataRobot2D> > datarobot2ds_map;

// get cpp extension's version
static PyObject *
show_ext_version(PyObject *self, PyObject *args)
{
    return PyUnicode_FromString(EXT_VERSION.c_str());
}

static PyObject *s_parse_vector_to_pyobj(std::vector<std::string> v) {
    PyObject *pyobj = PyTuple_New(v.size());
    std::vector<std::string>::size_type index = 0;
    for (auto s : v) {
        PyObject *item = Py_BuildValue("s", s.c_str());
        PyTuple_SetItem(pyobj, index, item);
        index++;
    }
    return pyobj;
}

static std::vector<std::string> s_parse_tuple_to_vector(PyObject *tuple) {
    std::vector<std::string> result;
    if (!PyTuple_Check(tuple)) {
        PyErr_SetString(kageext_error, "Need tuple");
        return result;
    }
    auto tuple_size = PyTuple_GET_SIZE(tuple);
    for(auto i=0; i<tuple_size; i++) {
        PyObject *t_item = PyTuple_GET_ITEM(tuple, i);
        const char *t_value;
        if (!PyArg_Parse(t_item, "s", &t_value)) {
            PyErr_SetString(kageext_error, "Need string");
            return result;
        }
        result.push_back(std::string(t_value));
    }
    return result;
}

static std::shared_ptr<DataRobot2D> get_datarobot2d_from_pyobj(PyObject *id) {
    const char *datarobot2d_s;
    if(!PyArg_Parse(id, "s", &datarobot2d_s)) {
        PyErr_SetString(kageext_error, "get_datarobot2d_content with no valid obj_id");
        return NULL;
    }

    std::string datarobot2d_id(datarobot2d_s);

    if (datarobot2ds_map.find(datarobot2d_id) == datarobot2ds_map.end()) {
        PyErr_SetString(kageext_error, "no such obj_id");
        return NULL;
    }

    std::shared_ptr<DataRobot2D> dataRobot2D = datarobot2ds_map[datarobot2d_id];
    return dataRobot2D;
}

// function mapping from Python to CPP
static PyObject *
call(PyObject *self, PyObject *args)
{
    PyObject *cpp_args = nullptr;
    const char *function;
    if (!PyArg_ParseTuple(args, "sO", &function, &cpp_args)) {
        PyErr_SetString(kageext_error, "PyArg Error");
        return NULL;
    }
    if (!PyTuple_Check(cpp_args)) {
        PyErr_SetString(kageext_error, "CPP Arg not a tuple");
        return NULL;
    }

    if (strcmp(function, "create_datarobot2d") == 0) {
        // cpp_args: data(2darray), columns(list), index(list)
        PyObject *data;
        PyObject *columns;
        PyObject *index;

        ARGS_NUM_CHECK(3)

        data = PyTuple_GET_ITEM(cpp_args, 0);
        columns = PyTuple_GET_ITEM(cpp_args, 1);
        index = PyTuple_GET_ITEM(cpp_args, 2);

        std::vector<std::string> v_columns = s_parse_tuple_to_vector(columns);
        std::vector<std::string> v_index = s_parse_tuple_to_vector(index);
        if (v_columns.empty()) {
            PyErr_SetString(kageext_error, "columns is empty");
            return NULL;
        }
        if (v_index.empty()) {
            PyErr_SetString(kageext_error, "index is empty");
            return NULL;
        }

        PyArrayObject *array = (PyArrayObject *)data;
        std::shared_ptr<DataRobot2D> dataRobot2D = std::make_shared<DataRobot2D>(array, v_columns, v_index);
        std::string uuid = get_uuid();
        datarobot2ds_map[uuid] = dataRobot2D;
        return PyUnicode_FromString(uuid.c_str());
    } else if (strcmp(function, "get_datarobot2d_content") == 0) {
        PyObject *datarobot2d_id_obj;

        ARGS_NUM_CHECK(1)

        datarobot2d_id_obj = PyTuple_GET_ITEM(cpp_args, 0);
        std::shared_ptr<DataRobot2D> dataRobot2D = get_datarobot2d_from_pyobj(datarobot2d_id_obj);
        if (dataRobot2D == NULL) return NULL;

        std::vector<std::string> columns = dataRobot2D->get_columns();
        std::vector<std::string> index = dataRobot2D->get_index();
        PyObject *p_columns = s_parse_vector_to_pyobj(columns);
        PyObject *p_index = s_parse_vector_to_pyobj(index);
        PyObject *array = (PyObject *)dataRobot2D->get_array();
        return Py_BuildValue("(OOO)", array, p_columns, p_index);

    } else if (strcmp(function, "deconstruct_datarobot2d") == 0) {
        PyObject *datarobot2d_id_obj;

        ARGS_NUM_CHECK(1)

        datarobot2d_id_obj = PyTuple_GET_ITEM(cpp_args, 0);
        std::shared_ptr<DataRobot2D> dataRobot2D = get_datarobot2d_from_pyobj(datarobot2d_id_obj);
        dataRobot2D->dec_array_ref();
        // tianhuan(todo) datarobot2d still live in datarobot2ds now.
        Py_RETURN_NONE;
    }
    Py_RETURN_NONE;
}

static PyMethodDef KageExtMethods[] = {
        {"eversion",  show_ext_version, METH_VARARGS, "Get extension's version."},
        {"call", call, METH_VARARGS, "Function call entrance."},
        {NULL, NULL, 0, NULL}
};

static struct PyModuleDef kageextmodule = {
        PyModuleDef_HEAD_INIT,
        "kageext",
        NULL,
        -1,
        KageExtMethods
};

PyMODINIT_FUNC
PyInit_kageext(void)
{
    PyObject *m;

    m = PyModule_Create(&kageextmodule);
    if (m == NULL)
        return NULL;

    kageext_error = PyErr_NewException("kageext.error", NULL, NULL);
    Py_INCREF(kageext_error);
    PyModule_AddObject(m, "error", kageext_error);

    import_array();

    return m;
}<commit_msg>remove unused obj<commit_after>#include <iostream>
#include <vector>
#include <map>

#include "numpy_import.h"
#ifdef NO_IMPORT_ARRAY
#undef NO_IMPORT_ARRAY
#endif
#include "numpy/arrayobject.h"
#include "Python.h"

#include "datarobot2d.h"
#include "utils.h"

#define ARGS_NUM_CHECK(NUM)  if (PyTuple_GET_SIZE(cpp_args) != NUM) { \
                                 PyErr_SetString(kageext_error, "need NUM args"); \
                                 return NULL; \
                           }

const std::string EXT_VERSION = "0.1";
static PyObject *kageext_error;
static std::map<std::string, std::shared_ptr<DataRobot2D> > datarobot2ds_map;

// get cpp extension's version
static PyObject *
show_ext_version(PyObject *self, PyObject *args)
{
    return PyUnicode_FromString(EXT_VERSION.c_str());
}

static PyObject *s_parse_vector_to_pyobj(std::vector<std::string> v) {
    PyObject *pyobj = PyTuple_New(v.size());
    std::vector<std::string>::size_type index = 0;
    for (auto s : v) {
        PyObject *item = Py_BuildValue("s", s.c_str());
        PyTuple_SetItem(pyobj, index, item);
        index++;
    }
    return pyobj;
}

static std::vector<std::string> s_parse_tuple_to_vector(PyObject *tuple) {
    std::vector<std::string> result;
    if (!PyTuple_Check(tuple)) {
        PyErr_SetString(kageext_error, "Need tuple");
        return result;
    }
    auto tuple_size = PyTuple_GET_SIZE(tuple);
    for(auto i=0; i<tuple_size; i++) {
        PyObject *t_item = PyTuple_GET_ITEM(tuple, i);
        const char *t_value;
        if (!PyArg_Parse(t_item, "s", &t_value)) {
            PyErr_SetString(kageext_error, "Need string");
            return result;
        }
        result.push_back(std::string(t_value));
    }
    return result;
}

static std::shared_ptr<DataRobot2D> get_datarobot2d_from_pyobj(PyObject *id) {
    const char *datarobot2d_s;
    if(!PyArg_Parse(id, "s", &datarobot2d_s)) {
        PyErr_SetString(kageext_error, "get_datarobot2d_content with no valid obj_id");
        return NULL;
    }

    std::string datarobot2d_id(datarobot2d_s);

    if (datarobot2ds_map.find(datarobot2d_id) == datarobot2ds_map.end()) {
        PyErr_SetString(kageext_error, "no such obj_id");
        return NULL;
    }

    std::shared_ptr<DataRobot2D> dataRobot2D = datarobot2ds_map[datarobot2d_id];
    return dataRobot2D;
}

// function mapping from Python to CPP
static PyObject *
call(PyObject *self, PyObject *args)
{
    PyObject *cpp_args = nullptr;
    const char *function;
    if (!PyArg_ParseTuple(args, "sO", &function, &cpp_args)) {
        PyErr_SetString(kageext_error, "PyArg Error");
        return NULL;
    }
    if (!PyTuple_Check(cpp_args)) {
        PyErr_SetString(kageext_error, "CPP Arg not a tuple");
        return NULL;
    }

    if (strcmp(function, "create_datarobot2d") == 0) {
        // cpp_args: data(2darray), columns(list), index(list)
        PyObject *data;
        PyObject *columns;
        PyObject *index;

        ARGS_NUM_CHECK(3)

        data = PyTuple_GET_ITEM(cpp_args, 0);
        columns = PyTuple_GET_ITEM(cpp_args, 1);
        index = PyTuple_GET_ITEM(cpp_args, 2);

        std::vector<std::string> v_columns = s_parse_tuple_to_vector(columns);
        std::vector<std::string> v_index = s_parse_tuple_to_vector(index);
        if (v_columns.empty()) {
            PyErr_SetString(kageext_error, "columns is empty");
            return NULL;
        }
        if (v_index.empty()) {
            PyErr_SetString(kageext_error, "index is empty");
            return NULL;
        }

        PyArrayObject *array = (PyArrayObject *)data;
        std::shared_ptr<DataRobot2D> dataRobot2D = std::make_shared<DataRobot2D>(array, v_columns, v_index);
        std::string uuid = get_uuid();
        datarobot2ds_map[uuid] = dataRobot2D;
        return PyUnicode_FromString(uuid.c_str());
    } else if (strcmp(function, "get_datarobot2d_content") == 0) {
        PyObject *datarobot2d_id_obj;

        ARGS_NUM_CHECK(1)

        datarobot2d_id_obj = PyTuple_GET_ITEM(cpp_args, 0);
        std::shared_ptr<DataRobot2D> dataRobot2D = get_datarobot2d_from_pyobj(datarobot2d_id_obj);
        if (dataRobot2D == NULL) return NULL;

        std::vector<std::string> columns = dataRobot2D->get_columns();
        std::vector<std::string> index = dataRobot2D->get_index();
        PyObject *p_columns = s_parse_vector_to_pyobj(columns);
        PyObject *p_index = s_parse_vector_to_pyobj(index);
        PyObject *array = (PyObject *)dataRobot2D->get_array();
        return Py_BuildValue("(OOO)", array, p_columns, p_index);

    } else if (strcmp(function, "deconstruct_datarobot2d") == 0) {
        PyObject *datarobot2d_id_obj;

        ARGS_NUM_CHECK(1)

        datarobot2d_id_obj = PyTuple_GET_ITEM(cpp_args, 0);
        std::shared_ptr<DataRobot2D> dataRobot2D = get_datarobot2d_from_pyobj(datarobot2d_id_obj);
        dataRobot2D->dec_array_ref();
        const char *datarobot2d_s;
        if(!PyArg_Parse(datarobot2d_id_obj, "s", &datarobot2d_s)) {
            PyErr_SetString(kageext_error, "deconstruct_datarobot2d with no valid obj_id");
            return NULL;
        }
        std::string datarobot2d_id(datarobot2d_s);
        datarobot2ds_map.erase(datarobot2d_id);

        Py_RETURN_NONE;
    }
    Py_RETURN_NONE;
}

static PyMethodDef KageExtMethods[] = {
        {"eversion",  show_ext_version, METH_VARARGS, "Get extension's version."},
        {"call", call, METH_VARARGS, "Function call entrance."},
        {NULL, NULL, 0, NULL}
};

static struct PyModuleDef kageextmodule = {
        PyModuleDef_HEAD_INIT,
        "kageext",
        NULL,
        -1,
        KageExtMethods
};

PyMODINIT_FUNC
PyInit_kageext(void)
{
    PyObject *m;

    m = PyModule_Create(&kageextmodule);
    if (m == NULL)
        return NULL;

    kageext_error = PyErr_NewException("kageext.error", NULL, NULL);
    Py_INCREF(kageext_error);
    PyModule_AddObject(m, "error", kageext_error);

    import_array();

    return m;
}<|endoftext|>


<commit_before>#pragma once

// Include most Rack headers for convenience
#include <common.hpp>
#include <math.hpp>
#include <string.hpp>
#include <system.hpp>
#include <random.hpp>
#include <network.hpp>
#include <asset.hpp>
#include <window.hpp>
#include <app.hpp>
#include <midi.hpp>
#include <helpers.hpp>
#include <componentlibrary.hpp>

#include <widget/Widget.hpp>
#include <widget/TransparentWidget.hpp>
#include <widget/OpaqueWidget.hpp>
#include <widget/TransformWidget.hpp>
#include <widget/ZoomWidget.hpp>
#include <widget/SvgWidget.hpp>
#include <widget/FramebufferWidget.hpp>
#include <widget/OpenGlWidget.hpp>

#include <ui/SequentialLayout.hpp>
#include <ui/Label.hpp>
#include <ui/List.hpp>
#include <ui/MenuOverlay.hpp>
#include <ui/Tooltip.hpp>
#include <ui/TextField.hpp>
#include <ui/PasswordField.hpp>
#include <ui/ScrollWidget.hpp>
#include <ui/Slider.hpp>
#include <ui/Menu.hpp>
#include <ui/MenuEntry.hpp>
#include <ui/MenuSeparator.hpp>
#include <ui/MenuLabel.hpp>
#include <ui/MenuItem.hpp>
#include <ui/Button.hpp>
#include <ui/IconButton.hpp>
#include <ui/ChoiceButton.hpp>
#include <ui/RadioButton.hpp>
#include <ui/ProgressBar.hpp>

#include <app/AudioWidget.hpp>
#include <app/CircularShadow.hpp>
#include <app/Knob.hpp>
#include <app/LedDisplay.hpp>
#include <app/LightWidget.hpp>
#include <app/MidiWidget.hpp>
#include <app/ModuleLightWidget.hpp>
#include <app/ModuleWidget.hpp>
#include <app/MultiLightWidget.hpp>
#include <app/ParamWidget.hpp>
#include <app/PortWidget.hpp>
#include <app/RackRail.hpp>
#include <app/Scene.hpp>
#include <app/RackScrollWidget.hpp>
#include <app/RackWidget.hpp>
#include <app/SvgButton.hpp>
#include <app/SvgKnob.hpp>
#include <app/SvgPanel.hpp>
#include <app/SvgPort.hpp>
#include <app/SvgScrew.hpp>
#include <app/SvgSlider.hpp>
#include <app/SvgSwitch.hpp>
#include <app/MenuBar.hpp>
#include <app/CableWidget.hpp>

#include <engine/Engine.hpp>
#include <engine/Param.hpp>
#include <engine/Port.hpp>
#include <engine/Module.hpp>
#include <engine/Param.hpp>
#include <engine/Cable.hpp>

#include <plugin/Plugin.hpp>
#include <plugin/Model.hpp>
#include <plugin/callbacks.hpp>

#include <dsp/common.hpp>
#include <dsp/digital.hpp>
#include <dsp/fft.hpp>
#include <dsp/filter.hpp>
#include <dsp/fir.hpp>
#include <dsp/midi.hpp>
#include <dsp/minblep.hpp>
#include <dsp/ode.hpp>
#include <dsp/resampler.hpp>
#include <dsp/ringbuffer.hpp>
#include <dsp/vumeter.hpp>
#include <dsp/window.hpp>
#include <dsp/approx.hpp>

#include <simd/vector.hpp>
#include <simd/functions.hpp>

namespace rack {

/** Define this macro before including this header to prevent common namespaces from being included in the main `rack::` namespace. */
#ifndef RACK_FLATTEN_NAMESPACES
	// Import some namespaces for convenience
	using namespace logger;
	using namespace math;
	using namespace widget;
	using namespace ui;
	using namespace app;
	using plugin::Plugin;
	using plugin::Model;
	using namespace engine;
	using namespace componentlibrary;

	// Import namespace recursively to solve the problem of calling `rack::DEBUG(...)` which expands to `rack::rack::logger(...)`.
	namespace rack = rack;
#endif

} // namespace rack
<commit_msg>Remove RACK_FLATTEN_NAMESPACES since it is not known to be used.<commit_after>#pragma once

// Include most Rack headers for convenience
#include <common.hpp>
#include <math.hpp>
#include <string.hpp>
#include <system.hpp>
#include <random.hpp>
#include <network.hpp>
#include <asset.hpp>
#include <window.hpp>
#include <app.hpp>
#include <midi.hpp>
#include <helpers.hpp>
#include <componentlibrary.hpp>

#include <widget/Widget.hpp>
#include <widget/TransparentWidget.hpp>
#include <widget/OpaqueWidget.hpp>
#include <widget/TransformWidget.hpp>
#include <widget/ZoomWidget.hpp>
#include <widget/SvgWidget.hpp>
#include <widget/FramebufferWidget.hpp>
#include <widget/OpenGlWidget.hpp>

#include <ui/SequentialLayout.hpp>
#include <ui/Label.hpp>
#include <ui/List.hpp>
#include <ui/MenuOverlay.hpp>
#include <ui/Tooltip.hpp>
#include <ui/TextField.hpp>
#include <ui/PasswordField.hpp>
#include <ui/ScrollWidget.hpp>
#include <ui/Slider.hpp>
#include <ui/Menu.hpp>
#include <ui/MenuEntry.hpp>
#include <ui/MenuSeparator.hpp>
#include <ui/MenuLabel.hpp>
#include <ui/MenuItem.hpp>
#include <ui/Button.hpp>
#include <ui/IconButton.hpp>
#include <ui/ChoiceButton.hpp>
#include <ui/RadioButton.hpp>
#include <ui/ProgressBar.hpp>

#include <app/AudioWidget.hpp>
#include <app/CircularShadow.hpp>
#include <app/Knob.hpp>
#include <app/LedDisplay.hpp>
#include <app/LightWidget.hpp>
#include <app/MidiWidget.hpp>
#include <app/ModuleLightWidget.hpp>
#include <app/ModuleWidget.hpp>
#include <app/MultiLightWidget.hpp>
#include <app/ParamWidget.hpp>
#include <app/PortWidget.hpp>
#include <app/RackRail.hpp>
#include <app/Scene.hpp>
#include <app/RackScrollWidget.hpp>
#include <app/RackWidget.hpp>
#include <app/SvgButton.hpp>
#include <app/SvgKnob.hpp>
#include <app/SvgPanel.hpp>
#include <app/SvgPort.hpp>
#include <app/SvgScrew.hpp>
#include <app/SvgSlider.hpp>
#include <app/SvgSwitch.hpp>
#include <app/MenuBar.hpp>
#include <app/CableWidget.hpp>

#include <engine/Engine.hpp>
#include <engine/Param.hpp>
#include <engine/Port.hpp>
#include <engine/Module.hpp>
#include <engine/Param.hpp>
#include <engine/Cable.hpp>

#include <plugin/Plugin.hpp>
#include <plugin/Model.hpp>
#include <plugin/callbacks.hpp>

#include <dsp/common.hpp>
#include <dsp/digital.hpp>
#include <dsp/fft.hpp>
#include <dsp/filter.hpp>
#include <dsp/fir.hpp>
#include <dsp/midi.hpp>
#include <dsp/minblep.hpp>
#include <dsp/ode.hpp>
#include <dsp/resampler.hpp>
#include <dsp/ringbuffer.hpp>
#include <dsp/vumeter.hpp>
#include <dsp/window.hpp>
#include <dsp/approx.hpp>

#include <simd/vector.hpp>
#include <simd/functions.hpp>

namespace rack {

// Import some namespaces for convenience
using namespace logger;
using namespace math;
using namespace widget;
using namespace ui;
using namespace app;
using plugin::Plugin;
using plugin::Model;
using namespace engine;
using namespace componentlibrary;

// Import namespace recursively to solve the problem of calling `rack::DEBUG(...)` which expands to `rack::rack::logger(...)`.
namespace rack = rack;

} // namespace rack
<|endoftext|>


<commit_before>/**
 * binary search tree class
 * created by lisovskey
 */

#ifndef TREE_H
#define TREE_H

#define RZD_BEGIN namespace rzd {
#define RZD_END }
#define ANYWAY
#define THEN

#include <list>
#include <memory>
#include <ostream>
#include <optional>

RZD_BEGIN

using std::list;
using std::ostream;
using std::optional;
using std::make_optional;

// binary search tree
template <typename T>
class Tree
{
    // prototype
    struct Node;

    // aliases
    using pointer = std::shared_ptr<Node>;
    using pair = std::pair<int, T>;

    // unit of tree
    struct Node {
        pair data;
        pointer left;
        pointer right;
		Node(pair data) : data{ data }, left{ nullptr }, right{ nullptr } {}
    };

    // start point
    pointer root;

	// IF       CONDITION                           ACTION

    pointer _insert(pointer leaf, const pair data)
    {
        if      (!leaf)                             return leaf = pointer(new Node(data));
        else if (data.first < leaf->data.first)     leaf->left = _insert(leaf->left, data);
        else if (data.first > leaf->data.first)     leaf->right = _insert(leaf->right, data);
        else                                        leaf->data.first = data.first;
        ANYWAY                                      return leaf;
    }

    pointer _find(const pointer leaf, const int key) const
    {
        if      (!leaf || leaf->data.first == key)  return leaf;
        else if (key < leaf->data.first)            return _find(leaf->left, key);
        else                                        return _find(leaf->right, key);
    }

    pointer _min(const pointer leaf) const
    {
        if      (leaf->left)                        return _min(leaf->left);
        else                                        return leaf;
    }

    pointer _remove(pointer leaf, const int key)
    {
        if      (!leaf)                             return leaf;
        else if (key < leaf->data.first)            leaf->left = _remove(leaf->left, key);
        else if (key > leaf->data.first)            leaf->right = _remove(leaf->right, key);
        else if (leaf->left && leaf->right) {
            THEN                                    leaf->data.first = (_min(leaf->right))->data.first;
            THEN                                    leaf->right = _remove(leaf->right, leaf->data.first);
        }
        else if (leaf->left)                        leaf = leaf->left;
        else if (leaf->right)                       leaf = leaf->right;
        else                                        leaf = nullptr;
        ANYWAY                                      return leaf;
    }

    int _size(const pointer leaf) const
    {
        if      (leaf)                              return _size(leaf->left) + 1 + _size(leaf->right);
		else                                        return 0;
    }

	ostream& _view(const pointer leaf, ostream& os) const
	{
		if		(leaf) {
			THEN									_view(leaf->left, os);
			THEN									os << leaf->data.second << "\n";
			THEN									_view(leaf->right, os);
		}
		ANYWAY										return os;
	}

	list<pair>& _get_list(const pointer leaf, list<pair>& list) const
	{
		if (leaf) {
			THEN									_get_list(leaf->left, list);
			THEN									list.push_back(leaf->data);
			THEN									_get_list(leaf->right, list);
		}
		ANYWAY										return list;
	}

public:

	// operators

	optional<T> operator[](const int key)
	{
		ANYWAY										return find(key);
	}

	friend ostream& operator<<(ostream& os, const Tree& tree)
	{
		ANYWAY										return tree._view(tree.root, os);
	}

    // constructors

	Tree() : root{ nullptr } {}

	Tree(const int key, const T value) : root{ new Node(pair(key, value)) } {}

    // usable methods

	// inserts new node with key and value
    void insert(const int key, const T value)
    {
        ANYWAY                                      root = _insert(root, pair(key, value));
    }

	// returns optional value by key
    optional<T> find(const int key) const
    {
        ANYWAY                                      pointer leaf = _find(root, key);
        if      (leaf)                              return make_optional(leaf->data.second);
        else                                        return {};
    }

	// removes node by key
    void remove(const int key)
    {
        ANYWAY                                      root = _remove(root, key);
    }

	// returns number of nodes
    int size() const
    {
        ANYWAY                                      return _size(root);
    }

	// returns sorted list
	list<pair> get_list() const
	{
		ANYWAY										list<pair> list;
		ANYWAY										return _get_list(root, list);
	}

};

RZD_END

#endif<commit_msg>clear, pass by ref<commit_after>/**
* binary search tree class
* created by lisovskey
*/

#ifndef TREE_H
#define TREE_H

#define RZD_BEGIN namespace rzd {
#define RZD_END }
#define ANYWAY
#define THEN

#include <list>
#include <memory>
#include <optional>

RZD_BEGIN

using std::list;
using std::optional;

// binary search tree
template <typename T>
class Tree
{
	// prototype
	struct Node;

	// aliases
	using pointer = std::shared_ptr<Node>;
	using pair = std::pair<int, T>;

	// unit of tree
	struct Node {
		pair data;
		pointer left;
		pointer right;
		Node(pair data) : data{ data }, left{ nullptr }, right{ nullptr } {}
	};

	// start point
	pointer root;

	//	IF      CONDITION                           ACTION

	void insert(pointer& leaf, const pair data)
	{
		if      (!leaf)                             leaf = pointer{ new Node{ data } };
		else if (data.first < leaf->data.first)     insert(leaf->left, data);
		else if (data.first > leaf->data.first)     insert(leaf->right, data);
		else                                        leaf->data.first = data.first;
	}

	pointer find(const pointer& leaf, const int key) const
	{
		if      (!leaf || leaf->data.first == key)  return leaf;
		else if (key < leaf->data.first)            return find(leaf->left, key);
		else                                        return find(leaf->right, key);
	}

	pointer minimum(const pointer& leaf) const
	{
		if      (leaf->left)                        return minimum(leaf->left);
		else                                        return leaf;
	}

	void remove(pointer& leaf, const int key)
	{
		if      (!leaf)                             return;
		else if (key < leaf->data.first)            remove(leaf->left, key);
		else if (key > leaf->data.first)            remove(leaf->right, key);
		else if (leaf->left && leaf->right) {
		    THEN                                    leaf->data.first = minimum(leaf->right)->data.first;
		    THEN                                    remove(leaf->right, leaf->data.first);
		}
		else if (leaf->left)                        leaf = leaf->left;
		else if (leaf->right)                       leaf = leaf->right;
		else                                        leaf = nullptr;
	}

	void clear(pointer& leaf)
	{
		if      (leaf) {
		    THEN                                    clear(leaf->left);
		    THEN                                    clear(leaf->right);
		    THEN                                    leaf = nullptr;
		}
	}

	int size(const pointer& leaf) const
	{
		if      (leaf)                              return size(leaf->left) + 1 + size(leaf->right);
		else                                        return 0;
	}

	list<pair>& get_list(const pointer& leaf, list<pair>& list) const
	{
		if      (leaf) {
		    THEN                                    get_list(leaf->left, list);
		    THEN                                    list.push_back(leaf->data);
		    THEN                                    get_list(leaf->right, list);
		}
		ANYWAY                                      return list;
	}

public:

	// inserts new node with key and value
	inline void insert(const int key, const T& value)
	{
		ANYWAY                                      insert(root, pair{ key, value });
	}

	// returns optional value by key
	inline optional<T> find(const int key) const
	{
		if      (pointer leaf = find(root, key))    return { leaf->data.second };
		else                                        return {};
	}

	// removes node by key
	inline void remove(const int key)
	{
		ANYWAY                                      remove(root, key);
	}

	inline void clear()
	{
		ANYWAY                                      clear(root);
	}

	// returns number of nodes
	inline int size() const
	{
		ANYWAY                                      return size(root);
	}

	// returns sorted list
	inline list<pair> get_list() const
	{
		ANYWAY                                      return get_list(root, list<pair>());
	}

	// returns optional value by key
	inline optional<T> operator[](const int key)
	{
		ANYWAY                                      return find(key);
	}

	// constructors

	Tree() : root{ nullptr } {}

	Tree(const int key, const T& value) : root{ new Node{ pair{ key, value } } } {}

};

RZD_END

#endif<|endoftext|>


<commit_before>#include "util/bitmap.h"
#include <math.h>
#include <iostream>

#include "level/utils.h"
#include "network/messages.h"
#include "loading.h"
#include "util/file-system.h"
#include "util/font.h"
#include "util/funcs.h"
#include "globals.h"
#include <vector>
#include <pthread.h>
#include "util/message-queue.h"
#include "init.h"

using namespace std;

typedef struct pair{
	int x, y;
} ppair;

class Info{
public:
    Info(){
        Global::registerInfo(&messages);
    }

    bool transferMessages(Messages & box){
        bool did = false;
        while (messages.hasAny()){
            const string & str = messages.get();
            box.addMessage(str);
            did = true;
        }
        return did;
    }

    ~Info(){
        Global::unregisterInfo(&messages);
    }

private:
    MessageQueue messages;
};

void * loadingScreen( void * arg ){
    const int load_x = 80;
    const int load_y = 220;
    const int infobox_width = 200;
    const int infobox_height = 150;
    Info info;
    string name = Filesystem::find("/fonts/arial.ttf");
    const Font & myFont = Font::getFont( name, 24, 24 );
    const Font & infoFont = Font::getFont(name, 24, 24);
    Level::LevelInfo levelInfo;
    if (arg != NULL){
        levelInfo = *(Level::LevelInfo*) arg;
    }
    // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
    int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
    int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());

    const int infobox_x = load_x;
    const int infobox_y = load_y + load_height * 2;

    Global::debug( 2 ) << "loading screen" << endl;

    Bitmap work( load_width, load_height );
    Bitmap letters( load_width, load_height );

    Messages infobox(infobox_width, infobox_height);
    Bitmap infoWork(infobox_width, infobox_height);
    Bitmap infoBackground(infobox_width, infobox_height);

    letters.fill( Bitmap::MaskColor );
    myFont.printf( 0, 0, Bitmap::makeColor( 255, 255, 255 ), letters, levelInfo.loadingMessage().c_str(), 0 );

    vector< ppair > pairs;
    /* store every pixel we need to draw */
    for ( int x = 0; x < letters.getWidth(); x++ ){
        for ( int y = 0; y < letters.getHeight(); y++ ){
            int pixel = letters.getPixel( x, y );
            if ( pixel != Bitmap::MaskColor ){
                ppair p;
                p.x = x;
                p.y = y;
                pairs.push_back( p );
            }
        }
    }

    const int MAX_COLOR = 200;

    int colors[ MAX_COLOR ];
    int c1 = Bitmap::makeColor( 16, 16, 16 );
    int c2 = Bitmap::makeColor( 192, 8, 8 );
    /* blend from dark grey to light red */
    Util::blend_palette( colors, MAX_COLOR / 2, c1, c2 );
    Util::blend_palette( colors + MAX_COLOR / 2, MAX_COLOR / 2, c2, c1 );

    Global::speed_counter = 0;

    { /* force scoping */
        Bitmap background(levelInfo.loadingBackground());
        background.Blit( load_x, load_y, load_width, load_height, 0, 0, work );
        Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
        Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
        background.BlitToScreen();
        background.Blit(infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), 0, 0, infoBackground);
    }
    bool quit = false;

    /* keeps the colors moving */
    static unsigned mover = 0;

    while ( ! quit ){

        bool draw = false;
        bool drawInfo = false;
        if ( Global::speed_counter > 0 ){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while ( think > 0 ){
                mover = (mover + 1) % MAX_COLOR;
                think -= 1;
            }
            drawInfo = info.transferMessages(infobox);
        } else {
            Util::rest( 1 );
        }

        if ( draw ){
            for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
                int color = colors[ (it->x - mover + MAX_COLOR) % MAX_COLOR ];
                work.putPixel( it->x, it->y, color );
            }

            if (drawInfo){
                infoBackground.Blit(infoWork);
                infobox.draw(0, 0, infoWork, infoFont);
                infoWork.BlitAreaToScreen(infobox_x, infobox_y);
            }
            /* work already contains the correct background */
            // work.Blit( load_x, load_y, *Bitmap::Screen );
            work.BlitAreaToScreen( load_x, load_y );
        }

        pthread_mutex_lock( &Global::loading_screen_mutex );
        quit = Global::done_loading;
        pthread_mutex_unlock( &Global::loading_screen_mutex );
    }

    return NULL;
}
<commit_msg>make info font smaller<commit_after>#include "util/bitmap.h"
#include <math.h>
#include <iostream>

#include "level/utils.h"
#include "network/messages.h"
#include "loading.h"
#include "util/file-system.h"
#include "util/font.h"
#include "util/funcs.h"
#include "globals.h"
#include <vector>
#include <pthread.h>
#include "util/message-queue.h"
#include "init.h"

using namespace std;

typedef struct pair{
	int x, y;
} ppair;

class Info{
public:
    Info(){
        Global::registerInfo(&messages);
    }

    bool transferMessages(Messages & box){
        bool did = false;
        while (messages.hasAny()){
            const string & str = messages.get();
            box.addMessage(str);
            did = true;
        }
        return did;
    }

    ~Info(){
        Global::unregisterInfo(&messages);
    }

private:
    MessageQueue messages;
};

void * loadingScreen( void * arg ){
    const int load_x = 80;
    const int load_y = 220;
    const int infobox_width = 300;
    const int infobox_height = 150;
    Info info;
    string fontName = Filesystem::find("/fonts/arial.ttf");
    const Font & myFont = Font::getFont(fontName, 24, 24);
    const Font & infoFont = Font::getFont(fontName, 24, 24);
    Level::LevelInfo levelInfo;
    if (arg != NULL){
        levelInfo = *(Level::LevelInfo*) arg;
    }
    // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
    int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
    int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());

    const int infobox_x = load_x;
    const int infobox_y = load_y + load_height * 2;

    Global::debug( 2 ) << "loading screen" << endl;

    Bitmap work( load_width, load_height );
    Bitmap letters( load_width, load_height );

    Messages infobox(infobox_width, infobox_height);
    Bitmap infoWork(infobox_width, infobox_height);
    Bitmap infoBackground(infobox_width, infobox_height);

    letters.fill( Bitmap::MaskColor );
    myFont.printf( 0, 0, Bitmap::makeColor( 255, 255, 255 ), letters, levelInfo.loadingMessage().c_str(), 0 );

    vector< ppair > pairs;
    /* store every pixel we need to draw */
    for ( int x = 0; x < letters.getWidth(); x++ ){
        for ( int y = 0; y < letters.getHeight(); y++ ){
            int pixel = letters.getPixel( x, y );
            if ( pixel != Bitmap::MaskColor ){
                ppair p;
                p.x = x;
                p.y = y;
                pairs.push_back( p );
            }
        }
    }

    const int MAX_COLOR = 200;

    int colors[ MAX_COLOR ];
    int c1 = Bitmap::makeColor( 16, 16, 16 );
    int c2 = Bitmap::makeColor( 192, 8, 8 );
    /* blend from dark grey to light red */
    Util::blend_palette( colors, MAX_COLOR / 2, c1, c2 );
    Util::blend_palette( colors + MAX_COLOR / 2, MAX_COLOR / 2, c2, c1 );

    Global::speed_counter = 0;

    { /* force scoping */
        Bitmap background(levelInfo.loadingBackground());
        background.Blit( load_x, load_y, load_width, load_height, 0, 0, work );
        Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
        Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
        background.BlitToScreen();
        background.Blit(infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), 0, 0, infoBackground);
    }
    bool quit = false;

    /* keeps the colors moving */
    static unsigned mover = 0;

    while ( ! quit ){

        bool draw = false;
        bool drawInfo = false;
        if ( Global::speed_counter > 0 ){
            double think = Global::speed_counter;
            Global::speed_counter = 0;
            draw = true;

            while ( think > 0 ){
                mover = (mover + 1) % MAX_COLOR;
                think -= 1;
            }
            drawInfo = info.transferMessages(infobox);
        } else {
            Util::rest( 1 );
        }

        if ( draw ){
            for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
                int color = colors[ (it->x - mover + MAX_COLOR) % MAX_COLOR ];
                work.putPixel( it->x, it->y, color );
            }

            if (drawInfo){
                infoBackground.Blit(infoWork);

                /* cheesy hack to change the font size. the font
                 * should store the size and change it on its own
                 */
                Font::getFont(fontName, 13, 13);
                infobox.draw(0, 0, infoWork, infoFont);
                Font::getFont(fontName, 24, 24);
                infoWork.BlitAreaToScreen(infobox_x, infobox_y);
            }
            /* work already contains the correct background */
            // work.Blit( load_x, load_y, *Bitmap::Screen );
            work.BlitAreaToScreen( load_x, load_y );
        }

        pthread_mutex_lock( &Global::loading_screen_mutex );
        quit = Global::done_loading;
        pthread_mutex_unlock( &Global::loading_screen_mutex );
    }

    return NULL;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <QApplication>
#include <QtUiTools>

#include "med.hpp"

using namespace std;

class MainUi : public QObject {
  Q_OBJECT

public:
  MainUi() {
    loadUiFiles();
  }
  Med med;

private slots:
  void onProcessClicked() {
    med.listProcesses();

    processDialog->show();

    //Get the tree widget
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");

    procTreeWidget->clear(); //Remove all items

    //Add all the process into the tree widget
    for(int i=med.processes.size()-1;i>=0;i--) {
      QTreeWidgetItem* item = new QTreeWidgetItem(procTreeWidget);
      item->setText(0, med.processes[i].pid.c_str());
      item->setText(1, med.processes[i].cmdline.c_str());
    }
  }

  void onProcItemDblClicked(QTreeWidgetItem* item, int column) {
    int index = item->treeWidget()->indexOfTopLevelItem(item); //Get the current row index
    med.selectedProcess = med.processes[med.processes.size() -1 - index];

    //Make changes to the selectedProc and hide the window
    QLineEdit* line = this->mainWindow->findChild<QLineEdit*>("selectedProc");
    line->setText(QString::fromLatin1((med.selectedProcess.pid + " " + med.selectedProcess.cmdline).c_str())); //Do not use fromStdString(), it will append with some unknown characters

    processDialog->hide();
  }

  void onScanClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    scanTreeWidget->clear();

    //Get scanned type
    string scanType = mainWindow->findChild<QComboBox*>("scanType")->currentText().toStdString();

    string scanValue = mainWindow->findChild<QLineEdit*>("scanEntry")->text().toStdString();

    if(med.selectedProcess.pid == "") {
      cerr << "No process seelcted " <<endl;
      return;
    }
    try {
      med.scanEqual(scanValue, scanType);
    } catch(string e) {
      cerr << "scan: "<<e<<endl;
    }

    if(med.scanAddresses.size() <= 800) {
      addressToScanTreeWidget(med, scanType, scanTreeWidget);
    }

    updateNumberOfAddresses(mainWindow);
  }

  void onFilterClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    scanTreeWidget->clear();

    //Get scanned type
    string scanType = mainWindow->findChild<QComboBox*>("scanType")->currentText().toStdString();

    string scanValue = mainWindow->findChild<QLineEdit*>("scanEntry")->text().toStdString();

    med.scanFilter(scanValue, scanType);

    if(med.scanAddresses.size() <= 800)
      addressToScanTreeWidget(med, scanType, scanTreeWidget);

    updateNumberOfAddresses(mainWindow);
  }

  void onClearClicked() {
    mainWindow->findChild<QTreeWidget*>("scanTreeWidget")->clear();
    med.scanAddresses.clear();
    mainWindow->findChild<QStatusBar*>("statusbar")->showMessage("Scan cleared");
  }

  void onScanAddClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    QTreeWidgetItem* item = scanTreeWidget->currentItem();
    int index = scanTreeWidget->indexOfTopLevelItem(item);

    //TODO: Write this to a function
    MedAddress medAddress;
    medAddress.address = med.scanAddresses[index].address;
    medAddress.scanType = med.scanAddresses[index].scanType;
    med.addresses.push_back(medAddress);

    //Add to AddressTreeWidget
    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");
    QTreeWidgetItem* itemToAdd = new QTreeWidgetItem(addressTreeWidget);
    itemToAdd->setText(0, "Your description");
    itemToAdd->setText(1, intToHex(medAddress.address).c_str());
    itemToAdd->setText(3, med.getAddressValueByIndex(med.addresses.size()-1).c_str());
    itemToAdd->setText(4, "false");
    itemToAdd->setFlags(itemToAdd->flags() | Qt::ItemIsEditable);

    //Add combo box
    QComboBox* combo = createTypeComboBox(addressTreeWidget, medAddress.getScanType());
    combo->setProperty("tree-row", addressTreeWidget->indexOfTopLevelItem(itemToAdd));
    addressTreeWidget->setItemWidget(itemToAdd, 2, combo);

    //Add signal
    QObject::connect(combo,
                     SIGNAL(currentTextChanged(QString)),
                     this,
                     SLOT(onAddressTypeChanged(QString)));
  }

  //TODO: Complete this one
  void onScanAddAllClicked() {
  }

  void onScanItemChanged(QTreeWidgetItem* item, int column) {
    switch(column) {
    case 1: //Not available, because the 2nd column is combobox
      break;
    case 2:
      editScanValue(item, column);
      break;
    }
  }

  void onScanTypeChanged(QString text) {
    QComboBox* combo = qobject_cast<QComboBox*>(sender());

    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");

    QTreeWidgetItem* item = scanTreeWidget->topLevelItem(combo->property("tree-row").toInt());
    scanTreeWidget->setCurrentItem(item);

    editScanType(item, text.toStdString());
  }

  void onAddressTypeChanged(QString text) {
    QComboBox* combo = qobject_cast<QComboBox*>(sender());

    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");

    QTreeWidgetItem* item = addressTreeWidget->topLevelItem(combo->property("tree-row").toInt());
    addressTreeWidget->setCurrentItem(item);

    editAddressType(item, text.toStdString());
  }

private:
  QWidget* mainWindow;
  QWidget* chooseProc;
  QDialog* processDialog;

  void loadUiFiles() {
    QUiLoader loader;

    QFile file("./main-qt.ui");
    file.open(QFile::ReadOnly);
    mainWindow = loader.load(&file);
    file.close();

    //Cannot put the followings to another method
    processDialog = new QDialog(mainWindow); //If put this to another method, then I cannot set the mainWindow as the parent
    QFile processFile("./process.ui");
    processFile.open(QFile::ReadOnly);

    chooseProc = loader.load(&processFile, processDialog);
    processFile.close();

    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(chooseProc);
    processDialog->setLayout(layout);
    processDialog->setModal(true);
    processDialog->resize(400, 400);

    //Statusbar message
    QStatusBar* statusBar = mainWindow->findChild<QStatusBar*>("statusbar");
    statusBar->showMessage("Tips: Left panel is scanned address. Right panel is stored address.");

    //Add signal
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");
    QObject::connect(procTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(onProcItemDblClicked(QTreeWidgetItem*, int)));

    procTreeWidget->installEventFilter(this);

    //TODO: center
    mainWindow->show();

    //Add signal to the process
    QWidget* process = mainWindow->findChild<QWidget*>("process");
    QObject::connect(process, SIGNAL(clicked()), this, SLOT(onProcessClicked()));

    //Add signal to scan
    QWidget* scanButton = mainWindow->findChild<QWidget*>("scanButton");
    QObject::connect(scanButton, SIGNAL(clicked()), this, SLOT(onScanClicked()));

    QWidget* filterButton = mainWindow->findChild<QWidget*>("filterButton");
    QObject::connect(filterButton, SIGNAL(clicked()), this, SLOT(onFilterClicked()));

    QObject::connect(mainWindow->findChild<QWidget*>("scanClear"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onClearClicked())
                     );

    //Add signal
    QObject::connect(mainWindow->findChild<QTreeWidget*>("scanTreeWidget"),
                     SIGNAL(itemChanged(QTreeWidgetItem*, int)),
                     this,
                     SLOT(onScanItemChanged(QTreeWidgetItem*, int))
                     );

    QObject::connect(mainWindow->findChild<QPushButton*>("scanAddAll"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onScanAddAllClicked())
                     );

    QObject:: connect(mainWindow->findChild<QPushButton*>("scanAdd"),
                      SIGNAL(clicked()),
                      this,
                      SLOT(onScanAddClicked())
                      );

  }

  bool eventFilter(QObject* obj, QEvent* ev) {
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");
    if(obj == procTreeWidget && ev->type() == QEvent::KeyRelease) {
      if(static_cast<QKeyEvent*>(ev)->key() == Qt::Key_Return) { //Use Return instead of Enter
        onProcItemDblClicked(procTreeWidget->currentItem(), 0); //Just use the first column
      }
    }
  }

  void addressToScanTreeWidget(Med med, string scanType, QTreeWidget* scanTreeWidget) {
    for(int i=0;i<med.scanAddresses.size();i++) {
      char address[32];
      sprintf(address, "%p", (void*)(med.scanAddresses[i].address));

      //Get the value from address and type
      string value = med.getScanAddressValueByIndex(i, scanType);

      QTreeWidgetItem* item = new QTreeWidgetItem(scanTreeWidget);
      item->setText(0, address);
      item->setText(2, value.c_str());

      item->setFlags(item->flags() | (Qt::ItemIsEditable));
    }

    //This is how to add combobox to the item
    QTreeWidgetItemIterator it(scanTreeWidget);
    while(*it) {
      QComboBox* combo = createTypeComboBox(scanTreeWidget, scanType);

      //Add property to the combobox, so that can be used to select the tree widget's row
      // http://stackoverflow.com/questions/30484784/how-to-work-with-signals-from-qtablewidget-cell-with-cellwidget-set
      combo->setProperty("tree-row", scanTreeWidget->indexOfTopLevelItem(*it));

      scanTreeWidget->setItemWidget(*it, 1, combo);

      //Add signal
      QObject::connect(combo,
                       SIGNAL(currentTextChanged(QString)),
                       this,
                       SLOT(onScanTypeChanged(QString)));
      it++;
    }
  }

  void updateNumberOfAddresses(QWidget* mainWindow) {
    char message[128];
    sprintf(message, "%ld addresses found", med.scanAddresses.size());
    mainWindow->findChild<QStatusBar*>("statusbar")->showMessage(message);
  }

  void editScanValue(QTreeWidgetItem* item, int column) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = item->text(column).toStdString();
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.setValueByAddress(med.scanAddresses[index].address,
                            text,
                            med.scanAddresses[index].getScanType());
    } catch(string e) {
      cerr << "editScanValue: "<<e<<endl;
    }
  }

  void editScanType(QTreeWidgetItem* item, string type) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = type;
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.scanAddresses[index].setScanType(text);
      string value2 = med.getValueByAddress(med.scanAddresses[index].address, text);
      item->setText(2, value2.c_str());
    } catch(string e) {
      cerr << "editScanType: "<<e<<endl;
    }
  }

  void editAddressType(QTreeWidgetItem* item, string type) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = type;
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.addresses[index].setScanType(text);
      string value2 = med.getValueByAddress(med.addresses[index].address, text);
      item->setText(3, value2.c_str());
    } catch(string e) {
      cerr << "editScanType: "<<e<<endl;
    }
  }

  QComboBox* createTypeComboBox(QTreeWidget* widget, string type) {
    QComboBox* combo = new QComboBox(widget);
    combo->addItems(QStringList() <<
                    "int8" <<
                    "int16" <<
                    "int32" <<
                    "float32" <<
                    "float64");

    combo->setCurrentText(type.c_str());
    return combo;
  }

};

int main(int argc, char **argv) {
  QApplication app(argc, argv);
  MainUi* mainUi = new MainUi();
  return app.exec();
}

#include "main-qt.moc"
<commit_msg>Qt update value in address widget; add new address; delete address<commit_after>#include <iostream>
#include <cstdio>
#include <QApplication>
#include <QtUiTools>

#include "med.hpp"

using namespace std;

class MainUi : public QObject {
  Q_OBJECT

public:
  MainUi() {
    loadUiFiles();
  }
  Med med;

private slots:
  void onProcessClicked() {
    med.listProcesses();

    processDialog->show();

    //Get the tree widget
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");

    procTreeWidget->clear(); //Remove all items

    //Add all the process into the tree widget
    for(int i=med.processes.size()-1;i>=0;i--) {
      QTreeWidgetItem* item = new QTreeWidgetItem(procTreeWidget);
      item->setText(0, med.processes[i].pid.c_str());
      item->setText(1, med.processes[i].cmdline.c_str());
    }
  }

  void onProcItemDblClicked(QTreeWidgetItem* item, int column) {
    int index = item->treeWidget()->indexOfTopLevelItem(item); //Get the current row index
    med.selectedProcess = med.processes[med.processes.size() -1 - index];

    //Make changes to the selectedProc and hide the window
    QLineEdit* line = this->mainWindow->findChild<QLineEdit*>("selectedProc");
    line->setText(QString::fromLatin1((med.selectedProcess.pid + " " + med.selectedProcess.cmdline).c_str())); //Do not use fromStdString(), it will append with some unknown characters

    processDialog->hide();
  }

  void onScanClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    scanTreeWidget->clear();

    //Get scanned type
    string scanType = mainWindow->findChild<QComboBox*>("scanType")->currentText().toStdString();

    string scanValue = mainWindow->findChild<QLineEdit*>("scanEntry")->text().toStdString();

    if(med.selectedProcess.pid == "") {
      cerr << "No process seelcted " <<endl;
      return;
    }
    try {
      med.scanEqual(scanValue, scanType);
    } catch(string e) {
      cerr << "scan: "<<e<<endl;
    }

    if(med.scanAddresses.size() <= 800) {
      addressToScanTreeWidget(med, scanType, scanTreeWidget);
    }

    updateNumberOfAddresses(mainWindow);
  }

  void onFilterClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    scanTreeWidget->clear();

    //Get scanned type
    string scanType = mainWindow->findChild<QComboBox*>("scanType")->currentText().toStdString();

    string scanValue = mainWindow->findChild<QLineEdit*>("scanEntry")->text().toStdString();

    med.scanFilter(scanValue, scanType);

    if(med.scanAddresses.size() <= 800)
      addressToScanTreeWidget(med, scanType, scanTreeWidget);

    updateNumberOfAddresses(mainWindow);
  }

  void onClearClicked() {
    mainWindow->findChild<QTreeWidget*>("scanTreeWidget")->clear();
    med.scanAddresses.clear();
    mainWindow->findChild<QStatusBar*>("statusbar")->showMessage("Scan cleared");
  }

  void onScanAddClicked() {
    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");
    QTreeWidgetItem* item = scanTreeWidget->currentItem();
    int index = scanTreeWidget->indexOfTopLevelItem(item);

    //TODO: Write this to a function
    MedAddress medAddress;
    medAddress.address = med.scanAddresses[index].address;
    medAddress.scanType = med.scanAddresses[index].scanType;
    med.addresses.push_back(medAddress);

    //Add to AddressTreeWidget
    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");
    QTreeWidgetItem* itemToAdd = new QTreeWidgetItem(addressTreeWidget);
    itemToAdd->setText(0, "Your description");
    itemToAdd->setText(1, intToHex(medAddress.address).c_str());
    itemToAdd->setText(3, med.getAddressValueByIndex(med.addresses.size()-1).c_str());
    itemToAdd->setText(4, "false");
    itemToAdd->setFlags(itemToAdd->flags() | Qt::ItemIsEditable);

    //Add combo box
    QComboBox* combo = createTypeComboBox(addressTreeWidget, medAddress.getScanType());
    combo->setProperty("tree-row", addressTreeWidget->indexOfTopLevelItem(itemToAdd));
    addressTreeWidget->setItemWidget(itemToAdd, 2, combo);

    //Add signal
    QObject::connect(combo,
                     SIGNAL(currentTextChanged(QString)),
                     this,
                     SLOT(onAddressTypeChanged(QString)));
  }

  //TODO: Complete this one
  void onScanAddAllClicked() {
  }

  void onScanItemChanged(QTreeWidgetItem* item, int column) {
    switch(column) {
    case 1: //Not available, because the 2nd column is combobox
      break;
    case 2:
      editScanValue(item, column);
      break;
    }
  }

  void onScanTypeChanged(QString text) {
    QComboBox* combo = qobject_cast<QComboBox*>(sender());

    QTreeWidget* scanTreeWidget = mainWindow->findChild<QTreeWidget*>("scanTreeWidget");

    QTreeWidgetItem* item = scanTreeWidget->topLevelItem(combo->property("tree-row").toInt());
    scanTreeWidget->setCurrentItem(item);

    editScanType(item, text.toStdString());
  }

  void onAddressTypeChanged(QString text) {
    QComboBox* combo = qobject_cast<QComboBox*>(sender());

    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");

    QTreeWidgetItem* item = addressTreeWidget->topLevelItem(combo->property("tree-row").toInt());
    addressTreeWidget->setCurrentItem(item);

    editAddressType(item, text.toStdString());
  }

  void onAddressItemChanged(QTreeWidgetItem* item, int column) {
    switch(column) {
    case 2: //Not available, because the 2nd column is combobox
      break;
    case 3:
      editAddressValue(item, column);
      break;
    }
  }

  void onAddressNewClicked() {
    MedAddress medAddress;
    medAddress.description = "Your description";
    medAddress.address = 0;
    medAddress.setScanType("int8");
    medAddress.lock = false;
    med.addresses.push_back(medAddress);

     //Add to AddressTreeWidget
    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");
    QTreeWidgetItem* itemToAdd = new QTreeWidgetItem(addressTreeWidget);    itemToAdd->setText(0, medAddress.description.c_str());
    itemToAdd->setText(1, "0");
    itemToAdd->setText(4, "false");
    itemToAdd->setFlags(itemToAdd->flags() | Qt::ItemIsEditable);

    //Add combo box
    QComboBox* combo = createTypeComboBox(addressTreeWidget, medAddress.getScanType());
    combo->setProperty("tree-row", addressTreeWidget->indexOfTopLevelItem(itemToAdd));
    addressTreeWidget->setItemWidget(itemToAdd, 2, combo);

    //Add signal
    QObject::connect(combo,
                     SIGNAL(currentTextChanged(QString)),
                     this,
                     SLOT(onAddressTypeChanged(QString)));
  }

  void onAddressDeleteClicked() {
    QTreeWidget* addressTreeWidget = mainWindow->findChild<QTreeWidget*>("addressTreeWidget");
    QTreeWidgetItem* item = addressTreeWidget->currentItem();
    delete item;
  }

private:
  QWidget* mainWindow;
  QWidget* chooseProc;
  QDialog* processDialog;

  void loadUiFiles() {
    QUiLoader loader;

    QFile file("./main-qt.ui");
    file.open(QFile::ReadOnly);
    mainWindow = loader.load(&file);
    file.close();

    //Cannot put the followings to another method
    processDialog = new QDialog(mainWindow); //If put this to another method, then I cannot set the mainWindow as the parent
    QFile processFile("./process.ui");
    processFile.open(QFile::ReadOnly);

    chooseProc = loader.load(&processFile, processDialog);
    processFile.close();

    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(chooseProc);
    processDialog->setLayout(layout);
    processDialog->setModal(true);
    processDialog->resize(400, 400);

    //Statusbar message
    QStatusBar* statusBar = mainWindow->findChild<QStatusBar*>("statusbar");
    statusBar->showMessage("Tips: Left panel is scanned address. Right panel is stored address.");

    //Add signal
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");
    QObject::connect(procTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(onProcItemDblClicked(QTreeWidgetItem*, int)));

    procTreeWidget->installEventFilter(this);

    //TODO: center
    mainWindow->show();

    //Add signal to the process
    QWidget* process = mainWindow->findChild<QWidget*>("process");
    QObject::connect(process, SIGNAL(clicked()), this, SLOT(onProcessClicked()));

    //Add signal to scan
    QWidget* scanButton = mainWindow->findChild<QWidget*>("scanButton");
    QObject::connect(scanButton, SIGNAL(clicked()), this, SLOT(onScanClicked()));

    QWidget* filterButton = mainWindow->findChild<QWidget*>("filterButton");
    QObject::connect(filterButton, SIGNAL(clicked()), this, SLOT(onFilterClicked()));

    QObject::connect(mainWindow->findChild<QWidget*>("scanClear"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onClearClicked())
                     );

    //Add signal
    QObject::connect(mainWindow->findChild<QTreeWidget*>("scanTreeWidget"),
                     SIGNAL(itemChanged(QTreeWidgetItem*, int)),
                     this,
                     SLOT(onScanItemChanged(QTreeWidgetItem*, int))
                     );

    QObject::connect(mainWindow->findChild<QPushButton*>("scanAddAll"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onScanAddAllClicked())
                     );

    QObject::connect(mainWindow->findChild<QPushButton*>("scanAdd"),
                      SIGNAL(clicked()),
                      this,
                      SLOT(onScanAddClicked())
                      );

    QObject::connect(mainWindow->findChild<QTreeWidget*>("addressTreeWidget"),
                     SIGNAL(itemChanged(QTreeWidgetItem*, int)),
                     this,
                     SLOT(onAddressItemChanged(QTreeWidgetItem*, int))
                     );

    QObject::connect(mainWindow->findChild<QPushButton*>("addressNew"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onAddressNewClicked()));
    QObject::connect(mainWindow->findChild<QPushButton*>("addressDelete"),
                     SIGNAL(clicked()),
                     this,
                     SLOT(onAddressDeleteClicked()));

  }

  bool eventFilter(QObject* obj, QEvent* ev) {
    QTreeWidget* procTreeWidget = chooseProc->findChild<QTreeWidget*>("procTreeWidget");
    if(obj == procTreeWidget && ev->type() == QEvent::KeyRelease) {
      if(static_cast<QKeyEvent*>(ev)->key() == Qt::Key_Return) { //Use Return instead of Enter
        onProcItemDblClicked(procTreeWidget->currentItem(), 0); //Just use the first column
      }
    }
  }

  void addressToScanTreeWidget(Med med, string scanType, QTreeWidget* scanTreeWidget) {
    for(int i=0;i<med.scanAddresses.size();i++) {
      char address[32];
      sprintf(address, "%p", (void*)(med.scanAddresses[i].address));

      //Get the value from address and type
      string value = med.getScanAddressValueByIndex(i, scanType);

      QTreeWidgetItem* item = new QTreeWidgetItem(scanTreeWidget);
      item->setText(0, address);
      item->setText(2, value.c_str());

      item->setFlags(item->flags() | (Qt::ItemIsEditable));
    }

    //This is how to add combobox to the item
    QTreeWidgetItemIterator it(scanTreeWidget);
    while(*it) {
      QComboBox* combo = createTypeComboBox(scanTreeWidget, scanType);

      //Add property to the combobox, so that can be used to select the tree widget's row
      // http://stackoverflow.com/questions/30484784/how-to-work-with-signals-from-qtablewidget-cell-with-cellwidget-set
      combo->setProperty("tree-row", scanTreeWidget->indexOfTopLevelItem(*it));

      scanTreeWidget->setItemWidget(*it, 1, combo);

      //Add signal
      QObject::connect(combo,
                       SIGNAL(currentTextChanged(QString)),
                       this,
                       SLOT(onScanTypeChanged(QString)));
      it++;
    }
  }

  void updateNumberOfAddresses(QWidget* mainWindow) {
    char message[128];
    sprintf(message, "%ld addresses found", med.scanAddresses.size());
    mainWindow->findChild<QStatusBar*>("statusbar")->showMessage(message);
  }

  void editScanValue(QTreeWidgetItem* item, int column) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = item->text(column).toStdString();
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.setValueByAddress(med.scanAddresses[index].address,
                            text,
                            med.scanAddresses[index].getScanType());
    } catch(string e) {
      cerr << "editScanValue: "<<e<<endl;
    }
  }

  //TODO: Combine with editScanValue
  void editAddressValue(QTreeWidgetItem* item, int column) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = item->text(column).toStdString();
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.setValueByAddress(med.addresses[index].address,
                            text,
                            med.addresses[index].getScanType());
    } catch(string e) {
      cerr << "editAddressValue: "<<e<<endl;
    }
  }

  void editScanType(QTreeWidgetItem* item, string type) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = type;
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.scanAddresses[index].setScanType(text);
      string value2 = med.getValueByAddress(med.scanAddresses[index].address, text);
      item->setText(2, value2.c_str());
    } catch(string e) {
      cerr << "editScanType: "<<e<<endl;
    }
  }

  void editAddressType(QTreeWidgetItem* item, string type) {
    int index = item->treeWidget()->indexOfTopLevelItem(item);
    string text = type;
    if(med.selectedProcess.pid == "") {
      cerr<< "No PID" <<endl;
      return;
    }

    try {
      med.addresses[index].setScanType(text);
      string value2 = med.getValueByAddress(med.addresses[index].address, text);
      item->setText(3, value2.c_str());
    } catch(string e) {
      cerr << "editScanType: "<<e<<endl;
    }
  }

  QComboBox* createTypeComboBox(QTreeWidget* widget, string type) {
    QComboBox* combo = new QComboBox(widget);
    combo->addItems(QStringList() <<
                    "int8" <<
                    "int16" <<
                    "int32" <<
                    "float32" <<
                    "float64");

    combo->setCurrentText(type.c_str());
    return combo;
  }

};

int main(int argc, char **argv) {
  QApplication app(argc, argv);
  MainUi* mainUi = new MainUi();
  return app.exec();
}

#include "main-qt.moc"
<|endoftext|>