<commit_before>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    api_numeral.cpp

Abstract:
    API for handling numerals in Z3

Author:

    Leonardo de Moura (leonardo) 2012-02-29.

Revision History:

--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"api_util.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"algebraic_numbers.h"
#include"float_decl_plugin.h"

bool is_numeral_sort(Z3_context c, Z3_sort ty) {
    sort * _ty = to_sort(ty);
    family_id fid  = _ty->get_family_id();
    if (fid != mk_c(c)->get_arith_fid() &&
        fid != mk_c(c)->get_bv_fid() &&
        fid != mk_c(c)->get_datalog_fid() &&
        fid != mk_c(c)->get_fpa_fid()) {
        return false;
    }
    return true;
}

bool check_numeral_sort(Z3_context c, Z3_sort ty) {
    bool is_num = is_numeral_sort(c, ty);
    if (!is_num) {
        SET_ERROR_CODE(Z3_INVALID_ARG);
    }
    return is_num;
}

extern "C" {

    Z3_ast Z3_API Z3_mk_numeral(Z3_context c, const char* n, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_numeral(c, n, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        if (!n) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            RETURN_Z3(0);
        }
        std::string fixed_num;
        char const* m = n;
        while (*m) {
            if (!(('0' <= *m && *m <= '9') ||
                  ('/' == *m) || ('-' == *m) ||
                  (' ' == *m) || ('\n' == *m) ||
                  ('.' == *m) || ('e' == *m) ||
                  ('E' == *m))) {
                SET_ERROR_CODE(Z3_PARSER_ERROR);
                return 0;
            }
            ++m;
        }
        ast * a = 0;
        sort * _ty = to_sort(ty);
        if (_ty->get_family_id() == mk_c(c)->get_fpa_fid())
        {
            // avoid expanding floats into huge rationals.
            float_util & fu = mk_c(c)->float_util();
            scoped_mpf t(fu.fm());
            fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n);
            a = fu.mk_value(t);
            mk_c(c)->save_ast_trail(a);
        }
        else
            a = mk_c(c)->mk_numeral_core(rational(n), _ty);
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_int(Z3_context c, int value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_int(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_unsigned_int(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_int64(Z3_context c, long long value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_int64(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        rational n(value, rational::i64());
        ast* a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_unsigned_int64(Z3_context c, unsigned long long value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_unsigned_int64(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        rational n(value, rational::ui64());
        ast * a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_bool Z3_API Z3_is_numeral_ast(Z3_context c, Z3_ast a) {
        Z3_TRY;
        LOG_Z3_is_numeral_ast(c, a);
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        return
            mk_c(c)->autil().is_numeral(e) ||
            mk_c(c)->bvutil().is_numeral(e) ||
            mk_c(c)->float_util().is_value(e);
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_rational(Z3_context c, Z3_ast a, rational& r) {
        Z3_TRY;
        // This function is not part of the public API
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        if (!e) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        if (mk_c(c)->autil().is_numeral(e, r)) {
            return Z3_TRUE;
        }
        unsigned bv_size;
        if (mk_c(c)->bvutil().is_numeral(e, r, bv_size)) {
            return Z3_TRUE;
        }
        uint64 v;
        if (mk_c(c)->datalog_util().is_numeral(e, v)) {
            r = rational(v, rational::ui64());
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_string Z3_API Z3_get_numeral_string(Z3_context c, Z3_ast a) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_string(c, a);
        RESET_ERROR_CODE();
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            return mk_c(c)->mk_external_string(r.to_string());
        }
        else {
            // floats are separated from all others to avoid huge rationals.
            float_util & fu = mk_c(c)->float_util();
            scoped_mpf tmp(fu.fm());
            if (mk_c(c)->float_util().is_numeral(to_expr(a), tmp)) {
                return mk_c(c)->mk_external_string(fu.fm().to_string(tmp));
            }
            else {
                SET_ERROR_CODE(Z3_INVALID_ARG);
                return "";
            }
        }
        Z3_CATCH_RETURN("");
    }

    Z3_string Z3_API Z3_get_numeral_decimal_string(Z3_context c, Z3_ast a, unsigned precision) {
        Z3_TRY;
        LOG_Z3_get_numeral_decimal_string(c, a, precision);
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        if (!e) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return "";
        }
        rational r;
        arith_util & u = mk_c(c)->autil();
        if (u.is_numeral(e, r) && !r.is_int()) {
            std::ostringstream buffer;
            r.display_decimal(buffer, precision);
            return mk_c(c)->mk_external_string(buffer.str());
        }
        if (u.is_irrational_algebraic_numeral(e)) {
            algebraic_numbers::anum const & n = u.to_irrational_algebraic_numeral(e);
            algebraic_numbers::manager & am   = u.am();
            std::ostringstream buffer;
            am.display_decimal(buffer, n, precision);
            return mk_c(c)->mk_external_string(buffer.str());
        }
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            return mk_c(c)->mk_external_string(r.to_string());
        }
        else {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return "";
        }
        Z3_CATCH_RETURN("");
    }

    Z3_bool Z3_API Z3_get_numeral_small(Z3_context c, Z3_ast a, long long* num, long long* den) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_small(c, a, num, den);
        RESET_ERROR_CODE();
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            rational n = numerator(r);
            rational d = denominator(r);
            if (n.is_int64() && d.is_int64()) {
                *num = n.get_int64();
                *den = d.get_int64();
                return Z3_TRUE;
            }
            else {
                return Z3_FALSE;
            }
        }
        SET_ERROR_CODE(Z3_INVALID_ARG);
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_int(Z3_context c, Z3_ast v, int* i) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_int64, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_int(c, v, i);
        RESET_ERROR_CODE();
        if (!i) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        long long l;
        if (Z3_get_numeral_int64(c, v, &l) && l >= INT_MIN && l <= INT_MAX) {
            *i = static_cast<int>(l);
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_uint(Z3_context c, Z3_ast v, unsigned* u) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_uint64, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_uint(c, v, u);
        RESET_ERROR_CODE();
        if (!u) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        unsigned long long l;
        if (Z3_get_numeral_uint64(c, v, &l) && (l <= 0xFFFFFFFF)) {
            *u = static_cast<unsigned>(l);
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_uint64(Z3_context c, Z3_ast v, unsigned long long* u) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_uint64(c, v, u);
        RESET_ERROR_CODE();
        if (!u) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        SASSERT(u);
        if (ok == Z3_TRUE && r.is_uint64()) {
            *u = r.get_uint64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_int64(Z3_context c, Z3_ast v, long long* i) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_int64(c, v, i);
        RESET_ERROR_CODE();
        if (!i) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        if (ok == Z3_TRUE && r.is_int64()) {
            *i = r.get_int64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_rational_int64(Z3_context c, Z3_ast v, long long* num, long long* den) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_rational_int64(c, v, num, den);
        RESET_ERROR_CODE();
        if (!num || !den) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        if (ok != Z3_TRUE) {
            return ok;
        }
        rational n = numerator(r);
        rational d = denominator(r);
        if (n.is_int64() && d.is_int64()) {
            *num = n.get_int64();
            *den = d.get_int64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

};
<commit_msg>Numeral API: added floating-point numeral cases.<commit_after>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    api_numeral.cpp

Abstract:
    API for handling numerals in Z3

Author:

    Leonardo de Moura (leonardo) 2012-02-29.

Revision History:

--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"api_util.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"algebraic_numbers.h"
#include"float_decl_plugin.h"

bool is_numeral_sort(Z3_context c, Z3_sort ty) {
    sort * _ty = to_sort(ty);
    family_id fid  = _ty->get_family_id();
    if (fid != mk_c(c)->get_arith_fid() &&
        fid != mk_c(c)->get_bv_fid() &&
        fid != mk_c(c)->get_datalog_fid() &&
        fid != mk_c(c)->get_fpa_fid()) {
        return false;
    }
    return true;
}

bool check_numeral_sort(Z3_context c, Z3_sort ty) {
    bool is_num = is_numeral_sort(c, ty);
    if (!is_num) {
        SET_ERROR_CODE(Z3_INVALID_ARG);
    }
    return is_num;
}

extern "C" {

    Z3_ast Z3_API Z3_mk_numeral(Z3_context c, const char* n, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_numeral(c, n, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        if (!n) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            RETURN_Z3(0);
        }
        sort * _ty = to_sort(ty);
        bool is_float = mk_c(c)->float_util().is_float(_ty);
        std::string fixed_num;
        char const* m = n;
        while (*m) {
            if (!(('0' <= *m && *m <= '9') ||
                  ('/' == *m) || ('-' == *m) ||
                  (' ' == *m) || ('\n' == *m) ||
                  ('.' == *m) || ('e' == *m) ||
                  ('E' == *m) ||
                  (('p' == *m) && is_float) ||
                  (('P' == *m)) && is_float)) {
                SET_ERROR_CODE(Z3_PARSER_ERROR);
                return 0;
            }
            ++m;
        }
        ast * a = 0;
        if (_ty->get_family_id() == mk_c(c)->get_fpa_fid())
        {
            // avoid expanding floats into huge rationals.
            float_util & fu = mk_c(c)->float_util();
            scoped_mpf t(fu.fm());
            fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n);
            a = fu.mk_value(t);
            mk_c(c)->save_ast_trail(a);
        }
        else
            a = mk_c(c)->mk_numeral_core(rational(n), _ty);
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_int(Z3_context c, int value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_int(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_unsigned_int(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_int64(Z3_context c, long long value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_int64(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        rational n(value, rational::i64());
        ast* a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_ast Z3_API Z3_mk_unsigned_int64(Z3_context c, unsigned long long value, Z3_sort ty) {
        Z3_TRY;
        LOG_Z3_mk_unsigned_int64(c, value, ty);
        RESET_ERROR_CODE();
        if (!check_numeral_sort(c, ty)) {
            RETURN_Z3(0);
        }
        rational n(value, rational::ui64());
        ast * a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
        RETURN_Z3(of_ast(a));
        Z3_CATCH_RETURN(0);
    }

    Z3_bool Z3_API Z3_is_numeral_ast(Z3_context c, Z3_ast a) {
        Z3_TRY;
        LOG_Z3_is_numeral_ast(c, a);
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        return
            mk_c(c)->autil().is_numeral(e) ||
            mk_c(c)->bvutil().is_numeral(e) ||
            mk_c(c)->float_util().is_value(e);
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_rational(Z3_context c, Z3_ast a, rational& r) {
        Z3_TRY;
        // This function is not part of the public API
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        if (!e) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        if (mk_c(c)->autil().is_numeral(e, r)) {
            return Z3_TRUE;
        }
        unsigned bv_size;
        if (mk_c(c)->bvutil().is_numeral(e, r, bv_size)) {
            return Z3_TRUE;
        }
        uint64 v;
        if (mk_c(c)->datalog_util().is_numeral(e, v)) {
            r = rational(v, rational::ui64());
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_string Z3_API Z3_get_numeral_string(Z3_context c, Z3_ast a) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_string(c, a);
        RESET_ERROR_CODE();
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            return mk_c(c)->mk_external_string(r.to_string());
        }
        else {
            // floats are separated from all others to avoid huge rationals.
            float_util & fu = mk_c(c)->float_util();
            scoped_mpf tmp(fu.fm());
            if (mk_c(c)->float_util().is_numeral(to_expr(a), tmp)) {
                return mk_c(c)->mk_external_string(fu.fm().to_string(tmp));
            }
            else {
                SET_ERROR_CODE(Z3_INVALID_ARG);
                return "";
            }
        }
        Z3_CATCH_RETURN("");
    }

    Z3_string Z3_API Z3_get_numeral_decimal_string(Z3_context c, Z3_ast a, unsigned precision) {
        Z3_TRY;
        LOG_Z3_get_numeral_decimal_string(c, a, precision);
        RESET_ERROR_CODE();
        expr* e = to_expr(a);
        if (!e) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return "";
        }
        rational r;
        arith_util & u = mk_c(c)->autil();
        if (u.is_numeral(e, r) && !r.is_int()) {
            std::ostringstream buffer;
            r.display_decimal(buffer, precision);
            return mk_c(c)->mk_external_string(buffer.str());
        }
        if (u.is_irrational_algebraic_numeral(e)) {
            algebraic_numbers::anum const & n = u.to_irrational_algebraic_numeral(e);
            algebraic_numbers::manager & am   = u.am();
            std::ostringstream buffer;
            am.display_decimal(buffer, n, precision);
            return mk_c(c)->mk_external_string(buffer.str());
        }
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            return mk_c(c)->mk_external_string(r.to_string());
        }
        else {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return "";
        }
        Z3_CATCH_RETURN("");
    }

    Z3_bool Z3_API Z3_get_numeral_small(Z3_context c, Z3_ast a, long long* num, long long* den) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_small(c, a, num, den);
        RESET_ERROR_CODE();
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, a, r);
        if (ok == Z3_TRUE) {
            rational n = numerator(r);
            rational d = denominator(r);
            if (n.is_int64() && d.is_int64()) {
                *num = n.get_int64();
                *den = d.get_int64();
                return Z3_TRUE;
            }
            else {
                return Z3_FALSE;
            }
        }
        SET_ERROR_CODE(Z3_INVALID_ARG);
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_int(Z3_context c, Z3_ast v, int* i) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_int64, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_int(c, v, i);
        RESET_ERROR_CODE();
        if (!i) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        long long l;
        if (Z3_get_numeral_int64(c, v, &l) && l >= INT_MIN && l <= INT_MAX) {
            *i = static_cast<int>(l);
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_uint(Z3_context c, Z3_ast v, unsigned* u) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_uint64, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_uint(c, v, u);
        RESET_ERROR_CODE();
        if (!u) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        unsigned long long l;
        if (Z3_get_numeral_uint64(c, v, &l) && (l <= 0xFFFFFFFF)) {
            *u = static_cast<unsigned>(l);
            return Z3_TRUE;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_uint64(Z3_context c, Z3_ast v, unsigned long long* u) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_uint64(c, v, u);
        RESET_ERROR_CODE();
        if (!u) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        SASSERT(u);
        if (ok == Z3_TRUE && r.is_uint64()) {
            *u = r.get_uint64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_int64(Z3_context c, Z3_ast v, long long* i) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_int64(c, v, i);
        RESET_ERROR_CODE();
        if (!i) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        if (ok == Z3_TRUE && r.is_int64()) {
            *i = r.get_int64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

    Z3_bool Z3_API Z3_get_numeral_rational_int64(Z3_context c, Z3_ast v, long long* num, long long* den) {
        Z3_TRY;
        // This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
        LOG_Z3_get_numeral_rational_int64(c, v, num, den);
        RESET_ERROR_CODE();
        if (!num || !den) {
            SET_ERROR_CODE(Z3_INVALID_ARG);
            return Z3_FALSE;
        }
        rational r;
        Z3_bool ok = Z3_get_numeral_rational(c, v, r);
        if (ok != Z3_TRUE) {
            return ok;
        }
        rational n = numerator(r);
        rational d = denominator(r);
        if (n.is_int64() && d.is_int64()) {
            *num = n.get_int64();
            *den = d.get_int64();
            return ok;
        }
        return Z3_FALSE;
        Z3_CATCH_RETURN(Z3_FALSE);
    }

};
<|endoftext|>


<commit_before>/*
 * Author Seabass
 * Purpose -- Read in a particular Mordor data file, MDATA11.MDR
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include "mordorBinaryReader.hpp" // bring in the binary ready definitions
#include "mdataTools.hpp"         // constants, simple data file checks
#include "readMData11.hpp"
#include "assert.h"

using namespace std;

const int RECORD_SIZE = 20;
int numLevels = -1;

struct mapHeader{
  WORD numLevels;
  int *levelOffsets;
};

struct countHeader { //area, teleport, chute header
  int count;
};

void printFieldRecord(fieldRecord *ret){
  cout << "Spawn Area ID: " << ret->spawnAreaID << endl
       << "Mask: " << ret->fieldMask << endl;
}

fieldRecord readFieldRecord(ifstream *mdata){
  fieldRecord ret;
  ret.spawnAreaID = readWord(mdata);

  for(int i = 0; i < 8; i++){
    ret.fieldMask[i] = readByte(mdata);
  }

  //  printFieldRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printMonsterLair(monsterLair *ret){
  cout << "MonsterType: " << ret->monsterType << endl
       << "MonsterID:   " << ret->monsterID << endl;
}

monsterLair readMonsterLair(ifstream *mdata){
  monsterLair ret;
  ret.monsterType = readDWord(mdata);
  ret.monsterID = readWord(mdata);
  //printMonsterLair(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printCountHeader(countHeader *ret){
  cout << "Count: " << ret->count << endl;
}

countHeader readCountHeader(ifstream *mdata){
  countHeader ret;
  ret.count = readWord(mdata);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printAreaRecord(areaRecord *ret){
  cout << "SpawnTypeMask: " << ret->spawnTypeMask << endl
       << "Lair ID: " << ret->lairID << endl;
}

areaRecord readAreaRecord(ifstream *mdata){
  areaRecord ret;
  ret.spawnTypeMask = readDWord(mdata);
  ret.lairID = readWord(mdata);
  printAreaRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printTeleporterRecord(teleporterRecord *ret){
  cout << "X: " << ret->srcX << "\tY: " << ret->srcY << endl
       << "X': " << ret->destX << "\tY': " << ret->destY << endl
       << "Z: " << ret-> destZ << endl;
}

teleporterRecord readTeleporterRecord(ifstream *mdata){
  teleporterRecord ret;

  //build the teleporter
  ret.srcX = readWord(mdata);
  ret.srcY = readWord(mdata);
  ret.destX = readWord(mdata);
  ret.destY = readWord(mdata);
  ret.destZ = readWord(mdata);

  // make sure the teleporter is sane
  assert(MAX_WIDTH >= ret.destX >= 0);
  assert(MAX_HEIGHT >= ret.destY >= 0);
  assert(numLevels >= ret.destZ >= 0);

  //display and return
  printTeleporterRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printChuteRecord(chuteRecord *ret){
  cout << "X: " << ret->x << "\tY: " << ret->y << "\tZ: " << ret->dropDepth << endl;
}

chuteRecord readChuteRecord(ifstream *mdata){
  chuteRecord ret;
  ret.x = readWord(mdata);
  ret.y = readWord(mdata);
  ret.dropDepth = readWord(mdata);
  printChuteRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printLevelHeader(levelHeader *lh){
  cout << dec << "Width:\t\t" << lh->width << endl;
  cout << "Height:\t\t" << lh->height << endl;
  cout << "Level:\t\t" << lh->levelNumber << endl;
  cout << "Areas:\t\t" << lh->numLairs << endl;
  cout << "Chutes:\t\t" << lh->numChutes << endl;
  cout << "Teleports:\t" << lh->numTeleports << endl;
}

levelHeader readLevelHeader(ifstream *mdata_input){
  // width       -- word
  // height      -- word
  // level #     -- word
  // # areas     -- word
  // # chutes    -- word
  // # teleports -- word

  levelHeader thisLevel;

  thisLevel.width = readWord(mdata_input);
  thisLevel.height = readWord(mdata_input);
  thisLevel.levelNumber = readWord(mdata_input);
  thisLevel.numLairs = readWord(mdata_input);
  thisLevel.numChutes = readWord(mdata_input);
  thisLevel.numTeleports = readWord(mdata_input);

  assert(thisLevel.width == MAX_WIDTH);
  assert(thisLevel.height == MAX_HEIGHT);

  printLevelHeader(&thisLevel);
  seekTo(mdata_input, RECORD_SIZE);
  return thisLevel;
}

void readLevel(ifstream *mdata_input, levelHeader *lh){

  int num_fields = lh->width * lh->height;
  fieldRecord fieldRecords[num_fields];
  int i;

  // read the map cells
  cout << "Number of Map Cells: " << num_fields << endl;
  for(i = 0; i < num_fields; i++){
    fieldRecords[i] = readFieldRecord(mdata_input);
  }

  // read monster lair records
  countHeader monsterLairHeader = readCountHeader(mdata_input);
  monsterLair monsterLairs[monsterLairHeader.count];
  cout << "Num Lairs: " << monsterLairHeader.count << endl;
  assert(monsterLairHeader.count == lh->numLairs);
  assert(monsterLairHeader.count <= MAX_LAIRS_PER_LEVEL);

  for(i = 0; i < monsterLairHeader.count; i++){
    monsterLairs[i] = readMonsterLair(mdata_input);
  }

  // now that I've read the meningful lairs, clear out the rest of the set.
  // the setis bounded from  above by 200.
  for(; i < MAX_LAIRS_PER_LEVEL; i++){
    seekTo(mdata_input, RECORD_SIZE);
  }

  // I have to strip off an additional record here, and I don't know why.
  seekTo(mdata_input, RECORD_SIZE);

  //teleport header
  countHeader teleportHeader = readCountHeader(mdata_input);
  cout << "Num Teleporters: " << teleportHeader.count << endl;
  assert(teleportHeader.count == lh->numTeleports);
  teleporterRecord teleportRecords[teleportHeader.count];
  for(i = 0; i < teleportHeader.count; i++){
    teleportRecords[i] = readTeleporterRecord(mdata_input);
  }

  //chute header
  countHeader chuteHeader = readCountHeader(mdata_input);
  cout << "Num Chutes: " << chuteHeader.count << endl;
  assert(chuteHeader.count == lh->numChutes);
  chuteRecord chuteRecords[chuteHeader.count];
  for(i = 0; i < chuteHeader.count; i++){
    chuteRecords[i] = readChuteRecord(mdata_input);
  }

  //and here is wher we would construct the level object
}

mapHeader readMapHeader(ifstream *mdata){
  mapHeader ret;
  ret.numLevels = readWord(mdata);
  seekTo(mdata,RECORD_SIZE);
  ret.levelOffsets = new int[ret.numLevels];
  for(int i = 0; i < ret.numLevels; i++){
    WORD read = readWord(mdata);
    ret.levelOffsets[i] = RECORD_SIZE * (read - 1); // -1 taken from wabbits editor
    seekTo(mdata, RECORD_SIZE);
  }
  // set global num levels by side effect.
  numLevels = ret.numLevels;
  return ret;
}

// testing main point -- this won't be compiled on it's own
int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr
      << "Expected exactly one argument -- the absolute path to the MDAT11.MDR"
      << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA11)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA11.MDR" << endl;
    return 1;
  }

  ifstream mdata_input(datAbsolutePath, ios::binary | ios::in);
  mapHeader mh = readMapHeader(&mdata_input);

  cout << "Num levels: " << mh.numLevels << endl;

  // try to read the first map
  for(int i = 0; i < mh.numLevels; i++){
    cout << endl;
    mdata_input.seekg(mh.levelOffsets[i], ios_base::beg);
    levelHeader lh = readLevelHeader(&mdata_input);
    readLevel(&mdata_input, &lh);
  }

  return 0;
}
<commit_msg>might as well check the source x / y while I'm at it.<commit_after>/*
 * Author Seabass
 * Purpose -- Read in a particular Mordor data file, MDATA11.MDR
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include "mordorBinaryReader.hpp" // bring in the binary ready definitions
#include "mdataTools.hpp"         // constants, simple data file checks
#include "readMData11.hpp"
#include "assert.h"

using namespace std;

const int RECORD_SIZE = 20;
int numLevels = -1;

struct mapHeader{
  WORD numLevels;
  int *levelOffsets;
};

struct countHeader { //area, teleport, chute header
  int count;
};

void printFieldRecord(fieldRecord *ret){
  cout << "Spawn Area ID: " << ret->spawnAreaID << endl
       << "Mask: " << ret->fieldMask << endl;
}

fieldRecord readFieldRecord(ifstream *mdata){
  fieldRecord ret;
  ret.spawnAreaID = readWord(mdata);

  for(int i = 0; i < 8; i++){
    ret.fieldMask[i] = readByte(mdata);
  }

  //  printFieldRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printMonsterLair(monsterLair *ret){
  cout << "MonsterType: " << ret->monsterType << endl
       << "MonsterID:   " << ret->monsterID << endl;
}

monsterLair readMonsterLair(ifstream *mdata){
  monsterLair ret;
  ret.monsterType = readDWord(mdata);
  ret.monsterID = readWord(mdata);
  //printMonsterLair(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printCountHeader(countHeader *ret){
  cout << "Count: " << ret->count << endl;
}

countHeader readCountHeader(ifstream *mdata){
  countHeader ret;
  ret.count = readWord(mdata);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printAreaRecord(areaRecord *ret){
  cout << "SpawnTypeMask: " << ret->spawnTypeMask << endl
       << "Lair ID: " << ret->lairID << endl;
}

areaRecord readAreaRecord(ifstream *mdata){
  areaRecord ret;
  ret.spawnTypeMask = readDWord(mdata);
  ret.lairID = readWord(mdata);
  printAreaRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printTeleporterRecord(teleporterRecord *ret){
  cout << "X: " << ret->srcX << "\tY: " << ret->srcY << endl
       << "X': " << ret->destX << "\tY': " << ret->destY << endl
       << "Z: " << ret-> destZ << endl;
}

teleporterRecord readTeleporterRecord(ifstream *mdata){
  teleporterRecord ret;

  //build the teleporter
  ret.srcX = readWord(mdata);
  ret.srcY = readWord(mdata);
  ret.destX = readWord(mdata);
  ret.destY = readWord(mdata);
  ret.destZ = readWord(mdata);

  // make sure the teleporter is sane
  assert(MAX_WIDTH >= ret.srcX >= 0);
  assert(MAX_HEIGHT >= ret.srcY >= 0);
  assert(MAX_WIDTH >= ret.destX >= 0);
  assert(MAX_HEIGHT >= ret.destY >= 0);
  assert(numLevels >= ret.destZ >= 0);

  //display and return
  printTeleporterRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printChuteRecord(chuteRecord *ret){
  cout << "X: " << ret->x << "\tY: " << ret->y << "\tZ: " << ret->dropDepth << endl;
}

chuteRecord readChuteRecord(ifstream *mdata){
  chuteRecord ret;
  ret.x = readWord(mdata);
  ret.y = readWord(mdata);
  ret.dropDepth = readWord(mdata);
  printChuteRecord(&ret);
  seekTo(mdata, RECORD_SIZE);
  return ret;
}

void printLevelHeader(levelHeader *lh){
  cout << dec << "Width:\t\t" << lh->width << endl;
  cout << "Height:\t\t" << lh->height << endl;
  cout << "Level:\t\t" << lh->levelNumber << endl;
  cout << "Areas:\t\t" << lh->numLairs << endl;
  cout << "Chutes:\t\t" << lh->numChutes << endl;
  cout << "Teleports:\t" << lh->numTeleports << endl;
}

levelHeader readLevelHeader(ifstream *mdata_input){
  // width       -- word
  // height      -- word
  // level #     -- word
  // # areas     -- word
  // # chutes    -- word
  // # teleports -- word

  levelHeader thisLevel;

  thisLevel.width = readWord(mdata_input);
  thisLevel.height = readWord(mdata_input);
  thisLevel.levelNumber = readWord(mdata_input);
  thisLevel.numLairs = readWord(mdata_input);
  thisLevel.numChutes = readWord(mdata_input);
  thisLevel.numTeleports = readWord(mdata_input);

  assert(thisLevel.width == MAX_WIDTH);
  assert(thisLevel.height == MAX_HEIGHT);

  printLevelHeader(&thisLevel);
  seekTo(mdata_input, RECORD_SIZE);
  return thisLevel;
}

void readLevel(ifstream *mdata_input, levelHeader *lh){

  int num_fields = lh->width * lh->height;
  fieldRecord fieldRecords[num_fields];
  int i;

  // read the map cells
  cout << "Number of Map Cells: " << num_fields << endl;
  for(i = 0; i < num_fields; i++){
    fieldRecords[i] = readFieldRecord(mdata_input);
  }

  // read monster lair records
  countHeader monsterLairHeader = readCountHeader(mdata_input);
  monsterLair monsterLairs[monsterLairHeader.count];
  cout << "Num Lairs: " << monsterLairHeader.count << endl;
  assert(monsterLairHeader.count == lh->numLairs);
  assert(monsterLairHeader.count <= MAX_LAIRS_PER_LEVEL);

  for(i = 0; i < monsterLairHeader.count; i++){
    monsterLairs[i] = readMonsterLair(mdata_input);
  }

  // now that I've read the meningful lairs, clear out the rest of the set.
  // the setis bounded from  above by 200.
  for(; i < MAX_LAIRS_PER_LEVEL; i++){
    seekTo(mdata_input, RECORD_SIZE);
  }

  // I have to strip off an additional record here, and I don't know why.
  seekTo(mdata_input, RECORD_SIZE);

  //teleport header
  countHeader teleportHeader = readCountHeader(mdata_input);
  cout << "Num Teleporters: " << teleportHeader.count << endl;
  assert(teleportHeader.count == lh->numTeleports);
  teleporterRecord teleportRecords[teleportHeader.count];
  for(i = 0; i < teleportHeader.count; i++){
    teleportRecords[i] = readTeleporterRecord(mdata_input);
  }

  //chute header
  countHeader chuteHeader = readCountHeader(mdata_input);
  cout << "Num Chutes: " << chuteHeader.count << endl;
  assert(chuteHeader.count == lh->numChutes);
  chuteRecord chuteRecords[chuteHeader.count];
  for(i = 0; i < chuteHeader.count; i++){
    chuteRecords[i] = readChuteRecord(mdata_input);
  }

  //and here is wher we would construct the level object
}

mapHeader readMapHeader(ifstream *mdata){
  mapHeader ret;
  ret.numLevels = readWord(mdata);
  seekTo(mdata,RECORD_SIZE);
  ret.levelOffsets = new int[ret.numLevels];
  for(int i = 0; i < ret.numLevels; i++){
    WORD read = readWord(mdata);
    ret.levelOffsets[i] = RECORD_SIZE * (read - 1); // -1 taken from wabbits editor
    seekTo(mdata, RECORD_SIZE);
  }
  // set global num levels by side effect.
  numLevels = ret.numLevels;
  return ret;
}

// testing main point -- this won't be compiled on it's own
int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr
      << "Expected exactly one argument -- the absolute path to the MDAT11.MDR"
      << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA11)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA11.MDR" << endl;
    return 1;
  }

  ifstream mdata_input(datAbsolutePath, ios::binary | ios::in);
  mapHeader mh = readMapHeader(&mdata_input);

  cout << "Num levels: " << mh.numLevels << endl;

  // try to read the first map
  for(int i = 0; i < mh.numLevels; i++){
    cout << endl;
    mdata_input.seekg(mh.levelOffsets[i], ios_base::beg);
    levelHeader lh = readLevelHeader(&mdata_input);
    readLevel(&mdata_input, &lh);
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "Repeat.hpp"

namespace tweencc
{
RepeatPtr Repeat::create(cocos2d::Node *target, unsigned int times, IFiniteTimePtr tween)
{
    auto r = std::make_shared<Repeat>(target, times, tween);

    return std::move(r);
}

Repeat::Repeat(cocos2d::Node *target, unsigned int times, IFiniteTimePtr tween) : Player(this, target), _times(times), _tween(tween)
{
}

cocos2d::ActionInterval *Repeat::generateAction()
{
    auto action = _tween->generateAction();

    return cocos2d::Repeat::create(action, _times);
}
} // namespace
<commit_msg>generateAction() with null target in Repeat.<commit_after>#include "Repeat.hpp"

namespace tweencc
{
RepeatPtr Repeat::create(cocos2d::Node *target, unsigned int times, IFiniteTimePtr tween)
{
    auto r = std::make_shared<Repeat>(target, times, tween);

    return std::move(r);
}

Repeat::Repeat(cocos2d::Node *target, unsigned int times, IFiniteTimePtr tween) : Player(this, target), _times(times), _tween(tween)
{
}

cocos2d::ActionInterval *Repeat::generateAction()
{
    cocos2d::ActionInterval *action = cocos2d::Repeat::create(_tween->generateAction(), _times);

    auto target = getTarget();
    if (target) {
        action = cocos2d::TargetedAction::create(target, action);
    }

    return action;
}
} // namespace
<|endoftext|>


<commit_before>#ifndef POWERUP_HPP_
#define POWERUP_HPP_

#include "GraphMap.hpp"
#include "vertex.hpp"
#include "Actor.hpp"
#include <unordered_set>
#include <unordered_map>
#include <functional>

using namespace std;

class Powerup : public Actor {
	private:
		unordered_set< Vertex, hash_vertex > v_set;
		unordered_map< Vertex, int, hash_vertex > distances;

		bool visited( const Vertex& v ) const;
		size_t dist( const Vertex& v );
	public:
		Powerup( int type );
		Powerup* duplicate();

		const char* getActorId();
		const char* getNetId();
		int selectNeighbor( GraphMap* map, int x, int y );
};

#endif<commit_msg>dist now properly returns an int instead of a size_t<commit_after>#ifndef POWERUP_HPP_
#define POWERUP_HPP_

#include "GraphMap.hpp"
#include "vertex.hpp"
#include "Actor.hpp"
#include <unordered_set>
#include <unordered_map>
#include <functional>

using namespace std;

class Powerup : public Actor {
	private:
		unordered_set< Vertex, hash_vertex > v_set;
		unordered_map< Vertex, int, hash_vertex > distances;

		bool visited( const Vertex& v ) const;
		int& dist( const Vertex& v );
	public:
		Powerup( int type );
		Powerup* duplicate();

		const char* getActorId();
		const char* getNetId();
		int selectNeighbor( GraphMap* map, int x, int y );
};

#endif<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "qbstool.h"

#include <tools/hostosinfo.h>

#include <QCoreApplication>
#include <QDir>
#include <QProcess>

#include <iostream>

static QString toolPrefix() { return QLatin1String("qbs-"); }
static QString qbsBinDir() { return QCoreApplication::applicationDirPath(); }

static QString qbsToolFilePath(const QString &toolName)
{
    return qbsBinDir() + QLatin1Char('/') + toolPrefix()
            + qbs::Internal::HostOsInfo::appendExecutableSuffix(toolName);
}

void QbsTool::runTool(const QString &toolName, const QStringList &arguments)
{
    m_failedToStart = false;
    m_exitCode = -1;
    QProcess toolProc;
    toolProc.start(qbsToolFilePath(toolName), arguments);
    if (!toolProc.waitForStarted())
        m_failedToStart = true;
    toolProc.waitForFinished(-1);
    m_exitCode = toolProc.exitCode();
    m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput());
    m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError());
}

bool QbsTool::tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode)
{
    QbsTool tool;
    tool.runTool(toolName, arguments);
    if (exitCode)
        *exitCode = tool.exitCode();
    if (tool.failedToStart())
        return false;
    std::cout << qPrintable(tool.stdOut());
    std::cerr << qPrintable(tool.stdErr());
    return true;
}

QStringList QbsTool::allToolNames()
{
    const QString suffix = QLatin1String(QTC_HOST_EXE_SUFFIX);
    QStringList toolFileNames = QDir(qbsBinDir()).entryList(QStringList(toolPrefix()
            + QString::fromLocal8Bit("*%1").arg(suffix)), QDir::Files, QDir::Name);
    QStringList toolNames;
    const int prefixLength = toolPrefix().count();
    foreach (const QString &toolFileName, toolFileNames) {
        toolNames << toolFileName.mid(prefixLength,
                                      toolFileName.count() - prefixLength - suffix.count());
    }
    return toolNames;
}
<commit_msg>check for existence before execution of a tool<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "qbstool.h"

#include <tools/hostosinfo.h>

#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QProcess>

#include <iostream>

static QString toolPrefix() { return QLatin1String("qbs-"); }
static QString qbsBinDir() { return QCoreApplication::applicationDirPath(); }

static QString qbsToolFilePath(const QString &toolName)
{
    return qbsBinDir() + QLatin1Char('/') + toolPrefix()
            + qbs::Internal::HostOsInfo::appendExecutableSuffix(toolName);
}

void QbsTool::runTool(const QString &toolName, const QStringList &arguments)
{
    m_failedToStart = false;
    m_exitCode = -1;
    const QString filePath = qbsToolFilePath(toolName);
    const QFileInfo fi(filePath);
    if (!fi.exists() || !fi.isFile() || !fi.isExecutable()) {
        m_failedToStart = true;
        return;
    }
    QProcess toolProc;
    toolProc.start(filePath, arguments);
    if (!toolProc.waitForStarted())
        m_failedToStart = true;
    toolProc.waitForFinished(-1);
    m_exitCode = toolProc.exitCode();
    m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput());
    m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError());
}

bool QbsTool::tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode)
{
    QbsTool tool;
    tool.runTool(toolName, arguments);
    if (exitCode)
        *exitCode = tool.exitCode();
    if (tool.failedToStart())
        return false;
    std::cout << qPrintable(tool.stdOut());
    std::cerr << qPrintable(tool.stdErr());
    return true;
}

QStringList QbsTool::allToolNames()
{
    const QString suffix = QLatin1String(QTC_HOST_EXE_SUFFIX);
    QStringList toolFileNames = QDir(qbsBinDir()).entryList(QStringList(toolPrefix()
            + QString::fromLocal8Bit("*%1").arg(suffix)), QDir::Files, QDir::Name);
    QStringList toolNames;
    const int prefixLength = toolPrefix().count();
    foreach (const QString &toolFileName, toolFileNames) {
        toolNames << toolFileName.mid(prefixLength,
                                      toolFileName.count() - prefixLength - suffix.count());
    }
    return toolNames;
}
<|endoftext|>


<commit_before>#include "pd_view.h"
#include "pd_view.h"
#include "pd_backend.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <vector>

#if defined(_WIN32)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif

#ifdef __clang__
#pragma clang diagnostic ignored "-Wformat-nonliteral" //error: format string is not a string literal [-Werror,-Wformat-nonliteral]

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct ConsoleData
{
	ConsoleData() : historyPos(0), scrollToBottom(0)
	{
		memset(inputBuffer, 0, sizeof(inputBuffer));
	}

    char inputBuffer[256];
    std::vector<char*> items;
    std::vector<char*> commands;
    std::vector<char*> history;
    std::vector<char*> scripts; // TODO: Temp, for testing
    int historyPos; // -1: New Line, 0...history.size()-1 Browsing History
    bool scrollToBottom;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void clearLog(ConsoleData* consoleData)
{
    for (size_t i = 0; i < consoleData->items.size(); ++i)
        free(consoleData->items[i]);
    consoleData->items.clear();
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void addLog(ConsoleData* consoleData, const char* fmt, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buffer, 1024, fmt, args);
    (void)w;
    buffer[1024 - 1] = 0;
    va_end(args);
    consoleData->items.push_back(strdup(buffer));
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void execCommand(ConsoleData* consoleData, const char* commandLine)
{
    // TODO: Hook up as PD event

    addLog(consoleData, "# %s\n", commandLine);

    // Insert history. First find match and delete it, so it can be pushed to the back.
    consoleData->historyPos = -1;
    for (int i = int(consoleData->history.size()) - 1; i >= 0; --i)
    {
        if (strcasecmp(consoleData->history[(size_t)i], commandLine) == 0)
        {
            free(consoleData->history[(size_t)i]);
            consoleData->history.erase(consoleData->history.begin() + i);
            break;
        }
    }

    consoleData->history.push_back(strdup(commandLine));

    // Process the command

    if (strcasecmp(commandLine, "clear") == 0)
    {
        clearLog(consoleData);
    }
    else if (strcasecmp(commandLine, "help") == 0)
    {
        addLog(consoleData, "Commands:");
        for (size_t i = 0; i < consoleData->commands.size(); i++)
            addLog(consoleData, "- %s", consoleData->commands[i]);
    }
    else if (strcasecmp(commandLine, "history") == 0)
    {
        for (size_t i = consoleData->history.size() >= 10 ? consoleData->history.size() - 10 : 0; i < consoleData->history.size(); i++)
            addLog(consoleData, "%3d: %s\n", i, consoleData->history[i]);
    }
    else if (strcasecmp(commandLine, "testText") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "Some text\nSome more text\nDisplay very important message here!\n");
    }
    else if (strcasecmp(commandLine, "testError") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "[Error] Something went wrong!\n");
    }
    else if (strcasecmp(commandLine, "testScript") == 0) // TODO: Temp for testing
    {
        consoleData->scripts.push_back((char*)"print(\"Hello ProDBG Lua World!\")");
    }
    else
    {
        addLog(consoleData, "Unknown command: '%s'\n", commandLine);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void textEditCallbackStub(PDInputTextCallbackData* data)
{
    ConsoleData* consoleData = (ConsoleData*)data->userData;

    //addLog(consoleData, "Cursor: %d, EventKey: %d, Selection: %d-%d", data->cursorPos, data->eventKey, data->selectionStart, data->selectionEnd);

    std::vector<const char*> candidates;
    const char* wordEnd   = nullptr;
    const char* wordStart = nullptr;
    switch (data->eventKey)
    {
        default:
            break;

        // Tab Completion
        case PDKEY_TAB:
		{
            // Locate beginning of current word
            wordEnd   = data->buffer + data->cursorPos;
            wordStart = wordEnd;
            while (wordStart > data->buffer)
            {
                const char c = wordStart[-1];
                if (c == ' ' || c == '\t' || c == ',' || c == ';')
                    break;
                wordStart--;
            }

            // Build a list of candidates

            for (size_t i = 0; i < consoleData->commands.size(); ++i)
                if (strncasecmp(consoleData->commands[i], wordStart, (size_t)(int(wordEnd - wordStart))) == 0)
                    candidates.push_back(consoleData->commands[i]);

            if (candidates.size() == 0)
            {
                // No match
                addLog(consoleData, "No match for \"%.*s\"!\n", wordEnd - wordStart, wordStart);
            }
            else if (candidates.size() == 1)
            {
                // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing

                data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                data->insertChars(data, data->cursorPos, candidates[0], 0);
                data->insertChars(data, data->cursorPos, " ", 0);
            }
            else
            {
                // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                int matchLen = int(wordEnd - wordStart);
                while (true)
                {
                    int c = 0;
                    bool allCandidatesMatches = true;
                    for (size_t i = 0; i < candidates.size() && allCandidatesMatches; i++)
                    {
                        if (i == 0)
                            c = toupper(candidates[i][matchLen]);
                        else if (c != toupper(candidates[i][matchLen]))
                            allCandidatesMatches = false;
                    }

                    if (!allCandidatesMatches)
                        break;

                    matchLen++;
                }

                if (matchLen > 0)
                {
                    data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                    data->insertChars(data, data->cursorPos, candidates[0], candidates[0] + matchLen);
                }

                // List matches
                addLog(consoleData, "Possible matches:\n");
                for (size_t i = 0; i < candidates.size(); i++)
                    addLog(consoleData, "- %s\n", candidates[i]);
            }

            break;
        }

        // Command History
        case PDKEY_UP:
        case PDKEY_DOWN:
		{
            const int prevHistoryPos = consoleData->historyPos;
            if (data->eventKey == PDKEY_UP)
            {
                if (consoleData->historyPos == -1)
                    consoleData->historyPos = int(consoleData->history.size()) - 1;
                else if (consoleData->historyPos > 0)
                    consoleData->historyPos--;
            }
            else if (data->eventKey == PDKEY_DOWN)
            {
                if (consoleData->historyPos != -1)
                {
                    if (++consoleData->historyPos >= int(consoleData->history.size()))
                        consoleData->historyPos = -1;
                }
            }

            // TODO: A better implementation would preserve the data on the current input line along with cursor position
            if (prevHistoryPos != consoleData->historyPos)
            {
                strcpy(data->buffer, (consoleData->historyPos >= 0) ? consoleData->history[(size_t)consoleData->historyPos] : "");
                data->bufferDirty = true;
                data->cursorPos = data->selectionStart = data->selectionEnd = int(strlen(data->buffer));
            }

            break;
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void* createInstance(PDUI* uiFuncs, ServiceFunc* serviceFunc)
{
    (void)serviceFunc;
    (void)uiFuncs;

    ConsoleData* consoleData = new ConsoleData;
    clearLog(consoleData);

    consoleData->historyPos = -1;
    consoleData->commands.push_back((char*)"HELP");
    consoleData->commands.push_back((char*)"HISTORY");
    consoleData->commands.push_back((char*)"CLEAR");
    consoleData->commands.push_back((char*)"CLASSIFY");   // TODO: "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
    consoleData->commands.push_back((char*)"TESTTEXT");   // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTERROR");  // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTSCRIPT"); // TODO: Temp, for testing

    return consoleData;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void destroyInstance(void* userData)
{
    ConsoleData* consoleData = (ConsoleData*)userData;
    clearLog(consoleData);
    free(consoleData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void showInUI(ConsoleData* consoleData, PDReader* reader, PDUI* uiFuncs)
{
    (void)consoleData;
    (void)reader;

    uiFuncs->textWrapped("ProDBG Scripting Console");
    uiFuncs->textWrapped("Enter 'HELP' for help. Press TAB to use text completion.");

    // TODO: display from bottom
    // TODO: clip manually

    if (PDUI_buttonSmall(uiFuncs, "Clear"))
        clearLog(consoleData);

    uiFuncs->sameLine(0, -1);
    uiFuncs->separator();

    PDVec2 pad = { 0.0f, 0.0f };

    uiFuncs->pushStyleVarV(PDStyleVar_FramePadding, pad);

    //static ImGuiTextFilter filter;
    //filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover

    uiFuncs->popStyleVar(1);

    uiFuncs->separator();

    PDVec2 spacing = { 0, -uiFuncs->getTextLineSpacing() * 2 };
    PDVec2 itemSpacing = { 4.0f, 1.0f };

    uiFuncs->beginChild("ScrollingRegion", spacing, false, PDWindowFlags(0));
    uiFuncs->pushStyleVarV(PDStyleVar_ItemSpacing, itemSpacing); // Tighten spacing

    for (size_t i = 0; i < consoleData->items.size(); i++)
    {
        const char* item = consoleData->items[i];
        //if (!filter.PassFilter(item))
        //    continue;
        PDVec4 col = { 1.0f, 1.0f, 1.0f, 1.0f }; // A better implementation may store a type per-item. For now let's just parse the text.
        if (strstr(item, "[Error]"))
            col = { 1.0f, 0.4f, 0.4f, 1.0f };
        else if (strncmp(item, "# ", 2) == 0)
            col = { 1.0f, 0.8f, 0.6f, 1.0f };
        uiFuncs->textColored(col, item);
    }

    if (consoleData->scrollToBottom)
        uiFuncs->setScrollHere();

    consoleData->scrollToBottom = false;

    uiFuncs->popStyleVar(1);
    uiFuncs->endChild();
    uiFuncs->separator();

    // Command Line

    if (uiFuncs->inputText("Input", consoleData->inputBuffer, sizeof(consoleData->inputBuffer), PDInputTextFlags_EnterReturnsTrue | PDInputTextFlags_CallbackCompletion | PDInputTextFlags_CallbackHistory, &textEditCallbackStub, (void*)consoleData))
    {
        char* inputEnd = consoleData->inputBuffer + strlen(consoleData->inputBuffer);

        while (inputEnd > consoleData->inputBuffer && inputEnd[-1] == ' ')
            inputEnd--;

        *inputEnd = 0;

        if (consoleData->inputBuffer[0])
            execCommand(consoleData, consoleData->inputBuffer);

        strcpy(consoleData->inputBuffer, "");
    }

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents)
{
    ConsoleData* consoleData = (ConsoleData*)userData;

    uint32_t event = 0;
    (void)event;

	//oe oesuth
	// dummy
    // dummy
    // sotehusoeth
    // soethusoeth
    // sotehusoe
    // stoehuso
    // eusths

    /*while ((event = PDRead_getEvent(inEvents)) != 0)
       {
        switch (event)
        {
            case PDEventType_setConsole:
            {
                //showInUI((ConsoleData*)userData, inEvents, uiFuncs);
                break;
            }
        }
       }*/

    showInUI(consoleData, inEvents, uiFuncs);

    for (size_t i = 0; i < consoleData->scripts.size(); ++i)
    {
        PDWrite_eventBegin(outEvents, PDEventType_executeConsole);
        PDWrite_string(outEvents, "command", consoleData->scripts[i]);   // TODO: Remove me
        PDWrite_eventEnd(outEvents);
        //free(consoleData->scripts[i]);
    }

    consoleData->scripts.clear();

    // Request console data

    PDWrite_eventBegin(outEvents, PDEventType_getConsole);
    PDWrite_u8(outEvents, "dummy_remove", 0);   // TODO: Remove me
    PDWrite_eventEnd(outEvents);

    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static PDViewPlugin plugin =
{
    "Console",
    createInstance,
    destroyInstance,
    update,
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern "C"
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PD_EXPORT void InitPlugin(RegisterPlugin* registerPlugin, void* privateData)
{
	registerPlugin(PD_VIEW_API_VERSION, &plugin, privateData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}

<commit_msg>testing<commit_after>#include "pd_view.h"
#include "pd_view.h"
#include "pd_backend.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <vector>

#if defined(_WIN32)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif

#ifdef __clang__
#pragma clang diagnostic ignored "-Wformat-nonliteral" //error: format string is not a string literal [-Werror,-Wformat-nonliteral]

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct ConsoleData
{
	ConsoleData() : historyPos(0), scrollToBottom(0)
	{
		memset(inputBuffer, 0, sizeof(inputBuffer));
	}

    char inputBuffer[256];
    std::vector<char*> items;
    std::vector<char*> commands;
    std::vector<char*> history;
    std::vector<char*> scripts; // TODO: Temp, for testing
    int historyPos; // -1: New Line, 0...history.size()-1 Browsing History
    bool scrollToBottom;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void clearLog(ConsoleData* consoleData)
{
    for (size_t i = 0; i < consoleData->items.size(); ++i)
        free(consoleData->items[i]);
    consoleData->items.clear();
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void addLog(ConsoleData* consoleData, const char* fmt, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buffer, 1024, fmt, args);
    (void)w;
    buffer[1024 - 1] = 0;
    va_end(args);
    consoleData->items.push_back(strdup(buffer));
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void execCommand(ConsoleData* consoleData, const char* commandLine)
{
    // TODO: Hook up as PD event

    addLog(consoleData, "# %s\n", commandLine);

    // Insert history. First find match and delete it, so it can be pushed to the back.
    consoleData->historyPos = -1;
    for (int i = int(consoleData->history.size()) - 1; i >= 0; --i)
    {
        if (strcasecmp(consoleData->history[(size_t)i], commandLine) == 0)
        {
            free(consoleData->history[(size_t)i]);
            consoleData->history.erase(consoleData->history.begin() + i);
            break;
        }
    }

    consoleData->history.push_back(strdup(commandLine));

    // Process the command

    if (strcasecmp(commandLine, "clear") == 0)
    {
        clearLog(consoleData);
    }
    else if (strcasecmp(commandLine, "help") == 0)
    {
        addLog(consoleData, "Commands:");
        for (size_t i = 0; i < consoleData->commands.size(); i++)
            addLog(consoleData, "- %s", consoleData->commands[i]);
    }
    else if (strcasecmp(commandLine, "history") == 0)
    {
        for (size_t i = consoleData->history.size() >= 10 ? consoleData->history.size() - 10 : 0; i < consoleData->history.size(); i++)
            addLog(consoleData, "%3d: %s\n", i, consoleData->history[i]);
    }
    else if (strcasecmp(commandLine, "testText") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "Some text\nSome more text\nDisplay very important message here!\n");
    }
    else if (strcasecmp(commandLine, "testError") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "[Error] Something went wrong!\n");
    }
    else if (strcasecmp(commandLine, "testScript") == 0) // TODO: Temp for testing
    {
        consoleData->scripts.push_back((char*)"print(\"Hello ProDBG Lua World!\")");
    }
    else
    {
        addLog(consoleData, "Unknown command: '%s'\n", commandLine);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void textEditCallbackStub(PDInputTextCallbackData* data)
{
    ConsoleData* consoleData = (ConsoleData*)data->userData;

    //addLog(consoleData, "Cursor: %d, EventKey: %d, Selection: %d-%d", data->cursorPos, data->eventKey, data->selectionStart, data->selectionEnd);

    std::vector<const char*> candidates;
    const char* wordEnd   = nullptr;
    const char* wordStart = nullptr;
    switch (data->eventKey)
    {
        default:
            break;

        // Tab Completion
        case PDKEY_TAB:
		{
            // Locate beginning of current word
            wordEnd   = data->buffer + data->cursorPos;
            wordStart = wordEnd;
            while (wordStart > data->buffer)
            {
                const char c = wordStart[-1];
                if (c == ' ' || c == '\t' || c == ',' || c == ';')
                    break;
                wordStart--;
            }

            // Build a list of candidates

            for (size_t i = 0; i < consoleData->commands.size(); ++i)
                if (strncasecmp(consoleData->commands[i], wordStart, (size_t)(int(wordEnd - wordStart))) == 0)
                    candidates.push_back(consoleData->commands[i]);

            if (candidates.size() == 0)
            {
                // No match
                addLog(consoleData, "No match for \"%.*s\"!\n", wordEnd - wordStart, wordStart);
            }
            else if (candidates.size() == 1)
            {
                // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing

                data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                data->insertChars(data, data->cursorPos, candidates[0], 0);
                data->insertChars(data, data->cursorPos, " ", 0);
            }
            else
            {
                // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                int matchLen = int(wordEnd - wordStart);
                while (true)
                {
                    int c = 0;
                    bool allCandidatesMatches = true;
                    for (size_t i = 0; i < candidates.size() && allCandidatesMatches; i++)
                    {
                        if (i == 0)
                            c = toupper(candidates[i][matchLen]);
                        else if (c != toupper(candidates[i][matchLen]))
                            allCandidatesMatches = false;
                    }

                    if (!allCandidatesMatches)
                        break;

                    matchLen++;
                }

                if (matchLen > 0)
                {
                    data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                    data->insertChars(data, data->cursorPos, candidates[0], candidates[0] + matchLen);
                }

                // List matches
                addLog(consoleData, "Possible matches:\n");
                for (size_t i = 0; i < candidates.size(); i++)
                    addLog(consoleData, "- %s\n", candidates[i]);
            }

            break;
        }

        // Command History
        case PDKEY_UP:
        case PDKEY_DOWN:
		{
            const int prevHistoryPos = consoleData->historyPos;
            if (data->eventKey == PDKEY_UP)
            {
                if (consoleData->historyPos == -1)
                    consoleData->historyPos = int(consoleData->history.size()) - 1;
                else if (consoleData->historyPos > 0)
                    consoleData->historyPos--;
            }
            else if (data->eventKey == PDKEY_DOWN)
            {
                if (consoleData->historyPos != -1)
                {
                    if (++consoleData->historyPos >= int(consoleData->history.size()))
                        consoleData->historyPos = -1;
                }
            }

            // TODO: A better implementation would preserve the data on the current input line along with cursor position
            if (prevHistoryPos != consoleData->historyPos)
            {
                strcpy(data->buffer, (consoleData->historyPos >= 0) ? consoleData->history[(size_t)consoleData->historyPos] : "");
                data->bufferDirty = true;
                data->cursorPos = data->selectionStart = data->selectionEnd = int(strlen(data->buffer));
            }

            break;
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void* createInstance(PDUI* uiFuncs, ServiceFunc* serviceFunc)
{
    (void)serviceFunc;
    (void)uiFuncs;

    ConsoleData* consoleData = new ConsoleData;
    clearLog(consoleData);

    consoleData->historyPos = -1;
    consoleData->commands.push_back((char*)"HELP");
    consoleData->commands.push_back((char*)"HISTORY");
    consoleData->commands.push_back((char*)"CLEAR");
    consoleData->commands.push_back((char*)"CLASSIFY");   // TODO: "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
    consoleData->commands.push_back((char*)"TESTTEXT");   // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTERROR");  // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTSCRIPT"); // TODO: Temp, for testing

    return consoleData;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void destroyInstance(void* userData)
{
    ConsoleData* consoleData = (ConsoleData*)userData;
    clearLog(consoleData);
    free(consoleData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void showInUI(ConsoleData* consoleData, PDReader* reader, PDUI* uiFuncs)
{
    (void)consoleData;
    (void)reader;

    uiFuncs->textWrapped("ProDBG Scripting Console");
    uiFuncs->textWrapped("Enter 'HELP' for help. Press TAB to use text completion.");

    // TODO: display from bottom
    // TODO: clip manually

    if (PDUI_buttonSmall(uiFuncs, "Clear"))
        clearLog(consoleData);

    uiFuncs->sameLine(0, -1);
    uiFuncs->separator();

    PDVec2 pad = { 0.0f, 0.0f };

    uiFuncs->pushStyleVarV(PDStyleVar_FramePadding, pad);

    //static ImGuiTextFilter filter;
    //filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover

    uiFuncs->popStyleVar(1);

    uiFuncs->separator();

    PDVec2 spacing = { 0, -uiFuncs->getTextLineSpacing() * 2 };
    PDVec2 itemSpacing = { 4.0f, 1.0f };

    uiFuncs->beginChild("ScrollingRegion", spacing, false, PDWindowFlags(0));
    uiFuncs->pushStyleVarV(PDStyleVar_ItemSpacing, itemSpacing); // Tighten spacing

    for (size_t i = 0; i < consoleData->items.size(); i++)
    {
        const char* item = consoleData->items[i];
        //if (!filter.PassFilter(item))
        //    continue;
        PDVec4 col = { 1.0f, 1.0f, 1.0f, 1.0f }; // A better implementation may store a type per-item. For now let's just parse the text.
        if (strstr(item, "[Error]"))
            col = { 1.0f, 0.4f, 0.4f, 1.0f };
        else if (strncmp(item, "# ", 2) == 0)
            col = { 1.0f, 0.8f, 0.6f, 1.0f };
        uiFuncs->textColored(col, item);
    }

    if (consoleData->scrollToBottom)
        uiFuncs->setScrollHere();

    consoleData->scrollToBottom = false;

    uiFuncs->popStyleVar(1);
    uiFuncs->endChild();
    uiFuncs->separator();

    // Command Line

    if (uiFuncs->inputText("Input", consoleData->inputBuffer, sizeof(consoleData->inputBuffer), PDInputTextFlags_EnterReturnsTrue | PDInputTextFlags_CallbackCompletion | PDInputTextFlags_CallbackHistory, &textEditCallbackStub, (void*)consoleData))
    {
        char* inputEnd = consoleData->inputBuffer + strlen(consoleData->inputBuffer);

        while (inputEnd > consoleData->inputBuffer && inputEnd[-1] == ' ')
            inputEnd--;

        *inputEnd = 0;

        if (consoleData->inputBuffer[0])
            execCommand(consoleData, consoleData->inputBuffer);

        strcpy(consoleData->inputBuffer, "");
    }

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents)
{
    ConsoleData* consoleData = (ConsoleData*)userData;

    uint32_t event = 0;
    (void)event;

	// testing
	//oe oesuth
	// dummy
    // dummy
    // sotehusoeth
    // soethusoeth
    // sotehusoe
    // stoehuso
    // eusths

    /*while ((event = PDRead_getEvent(inEvents)) != 0)
       {
        switch (event)
        {
            case PDEventType_setConsole:
            {
                //showInUI((ConsoleData*)userData, inEvents, uiFuncs);
                break;
            }
        }
       }*/

    showInUI(consoleData, inEvents, uiFuncs);

    for (size_t i = 0; i < consoleData->scripts.size(); ++i)
    {
        PDWrite_eventBegin(outEvents, PDEventType_executeConsole);
        PDWrite_string(outEvents, "command", consoleData->scripts[i]);   // TODO: Remove me
        PDWrite_eventEnd(outEvents);
        //free(consoleData->scripts[i]);
    }

    consoleData->scripts.clear();

    // Request console data

    PDWrite_eventBegin(outEvents, PDEventType_getConsole);
    PDWrite_u8(outEvents, "dummy_remove", 0);   // TODO: Remove me
    PDWrite_eventEnd(outEvents);

    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static PDViewPlugin plugin =
{
    "Console",
    createInstance,
    destroyInstance,
    update,
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern "C"
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PD_EXPORT void InitPlugin(RegisterPlugin* registerPlugin, void* privateData)
{
	registerPlugin(PD_VIEW_API_VERSION, &plugin, privateData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}

<|endoftext|>


<commit_before>/*!
    \file cpu.cpp
    \brief CPU management implementation
    \author Ivan Shynkarenka
    \date 27.07.2016
    \copyright MIT License
*/

#include "system/cpu.h"
#include "utility/resource.h"

#if defined(__APPLE__)
#include <sys/sysctl.h>
#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
#include <unistd.h>
#include <fstream>
#include <regex>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

namespace CppCommon {

//! @cond INTERNALS
namespace Internals {

#if defined(_WIN32) || defined(_WIN64)
// Helper function to count set bits in the processor mask
DWORD CountSetBits(ULONG_PTR pBitMask)
{
    DWORD dwLeftShift = sizeof(ULONG_PTR) * 8 - 1;
    DWORD dwBitSetCount = 0;
    ULONG_PTR pBitTest = (ULONG_PTR)1 << dwLeftShift;

    for (DWORD i = 0; i <= dwLeftShift; ++i)
    {
        dwBitSetCount += ((pBitMask & pBitTest) ? 1 : 0);
        pBitTest /= 2;
    }

    return dwBitSetCount;
}
#endif

} // namespace Internals
//! @endcond

std::string CPU::Architecture()
{
#if defined(__APPLE__)
    char result[1024];
    size_t size = sizeof(result);
    if (sysctlbyname("machdep.cpu.brand_string", result, &size, nullptr, 0) == 0)
        return result;

    return "<unknown>";
#elif defined(unix) || defined(__unix) || defined(__unix__)
    static std::regex pattern("model name(.*): (.*)");

    std::string line;
    std::ifstream stream("/proc/cpuinfo");
    while (getline(stream, line))
    {
        std::smatch matches;
        if (std::regex_match(line, matches, pattern))
            return matches[2];
    }

    return "<unknown>";
#elif defined(_WIN32) || defined(_WIN64)
    HKEY hKeyProcessor;
    LONG lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKeyProcessor);
    if (lError != ERROR_SUCCESS)
        return "<unknown>";

    // Smart resource cleaner pattern
    auto key = resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });

    CHAR pBuffer[_MAX_PATH] = { 0 };
    DWORD dwBufferSize = sizeof(pBuffer);
    lError = RegQueryValueExA(key.get(), "ProcessorNameString", nullptr, nullptr, (LPBYTE)pBuffer, &dwBufferSize);
    if (lError != ERROR_SUCCESS)
        return "<unknown>";

    return std::string(pBuffer);
#else
    #error Unsupported platform
#endif
}

int CPU::Affinity()
{
#if defined(__APPLE__)
    int logical = 0;
    size_t logical_size = sizeof(logical);
    if (sysctlbyname("hw.logicalcpu", &logical, &logical_size, nullptr, 0) != 0)
        logical = -1;

    return logical;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    long processors = sysconf(_SC_NPROCESSORS_ONLN);
    return processors;
#elif defined(_WIN32) || defined(_WIN64)
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    return si.dwNumberOfProcessors;
#else
    #error Unsupported platform
#endif
}

int CPU::LogicalCores()
{
    return TotalCores().first;
}

int CPU::PhysicalCores()
{
    return TotalCores().second;
}

std::pair<int, int> CPU::TotalCores()
{
#if defined(__APPLE__)
    int logical = 0;
    size_t logical_size = sizeof(logical);
    if (sysctlbyname("hw.logicalcpu", &logical, &logical_size, nullptr, 0) != 0)
        logical = -1;

    int physical = 0;
    size_t physical_size = sizeof(physical);
    if (sysctlbyname("hw.physicalcpu", &physical, &physical_size, nullptr, 0) != 0)
        physical = -1;

    return std::make_pair(logical, physical);
#elif defined(unix) || defined(__unix) || defined(__unix__)
    long processors = sysconf(_SC_NPROCESSORS_ONLN);
    return std::make_pair(processors, processors);
#elif defined(_WIN32) || defined(_WIN64)
    BOOL allocated = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pBuffer = nullptr;
    DWORD dwLength = 0;

    while (!allocated)
    {
        BOOL bResult = GetLogicalProcessorInformation(pBuffer, &dwLength);
        if (bResult == FALSE)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                if (pBuffer != nullptr)
                    std::free(pBuffer);
                pBuffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)std::malloc(dwLength);
                if (pBuffer == nullptr)
                    return std::make_pair(-1, -1);
            }
            else
                return std::make_pair(-1, -1);
        }
        else
            allocated = TRUE;
    }

    std::pair<int, int> result(0, 0);
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pCurrent = pBuffer;
    DWORD dwOffset = 0;

    while (dwOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= dwLength)
    {
        switch (pCurrent->Relationship)
        {
            case RelationProcessorCore:
                result.first += Internals::CountSetBits(pCurrent->ProcessorMask);
                result.second += 1;
                break;
            case RelationNumaNode:
            case RelationCache:
            case RelationProcessorPackage:
                break;
            default:
                return std::make_pair(-1, -1);
        }
        dwOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        pCurrent++;
    }

    std::free(pBuffer);

    return result;
#else
    #error Unsupported platform
#endif
}

int64_t CPU::ClockSpeed()
{
#if defined(__APPLE__)
    uint64_t frequency = 0;
    size_t size = sizeof(frequency);
    if (sysctlbyname("hw.cpufrequency", &frequency, &size, nullptr, 0) == 0)
        return frequency;

    return -1;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    static std::regex pattern("cpu MHz(.*): (.*)");

    std::string line;
    std::ifstream stream("/proc/cpuinfo");
    while (getline(stream, line))
    {
        std::smatch matches;
        if (std::regex_match(line, matches, pattern))
            return (int64_t)(atof(matches[2].str().c_str()) * 1000000);
    }

    return -1;
#elif defined(_WIN32) || defined(_WIN64)
    HKEY hKeyProcessor;
    long lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKeyProcessor);
    if (lError != ERROR_SUCCESS)
        return -1;

    // Smart resource cleaner pattern
    auto key = resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });

    DWORD dwMHz = 0;
    DWORD dwBufferSize = sizeof(DWORD);
    lError = RegQueryValueExA(key.get(), "~MHz", nullptr, nullptr, (LPBYTE)&dwMHz, &dwBufferSize);
    if (lError != ERROR_SUCCESS)
        return -1;

    return dwMHz * 1000000;
#else
    #error Unsupported platform
#endif
}

bool CPU::HyperThreading()
{
    std::pair<int, int> cores = TotalCores();
    return (cores.first != cores.second);
}

} // namespace CppCommon
<commit_msg>update<commit_after>/*!
    \file cpu.cpp
    \brief CPU management implementation
    \author Ivan Shynkarenka
    \date 27.07.2016
    \copyright MIT License
*/

#include "system/cpu.h"
#include "utility/resource.h"

#if defined(__APPLE__)
#include <sys/sysctl.h>
#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
#include <unistd.h>
#include <fstream>
#include <regex>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

namespace CppCommon {

//! @cond INTERNALS
namespace Internals {

#if defined(_WIN32) || defined(_WIN64)
// Helper function to count set bits in the processor mask
DWORD CountSetBits(ULONG_PTR pBitMask)
{
    DWORD dwLeftShift = sizeof(ULONG_PTR) * 8 - 1;
    DWORD dwBitSetCount = 0;
    ULONG_PTR pBitTest = (ULONG_PTR)1 << dwLeftShift;

    for (DWORD i = 0; i <= dwLeftShift; ++i)
    {
        dwBitSetCount += ((pBitMask & pBitTest) ? 1 : 0);
        pBitTest /= 2;
    }

    return dwBitSetCount;
}
#endif

} // namespace Internals
//! @endcond

std::string CPU::Architecture()
{
#if defined(__APPLE__)
    char result[1024];
    size_t size = sizeof(result);
    if (sysctlbyname("machdep.cpu.brand_string", result, &size, nullptr, 0) == 0)
        return result;

    return "<unknown>";
#elif defined(unix) || defined(__unix) || defined(__unix__)
    static std::regex pattern("model name(.*): (.*)");

    std::string line;
    std::ifstream stream("/proc/cpuinfo", '\n');
    while (getline(stream, line))
    {
        std::smatch matches;
        if (std::regex_match(line, matches, pattern))
            return matches[2];
    }

    return "<unknown>";
#elif defined(_WIN32) || defined(_WIN64)
    HKEY hKeyProcessor;
    LONG lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKeyProcessor);
    if (lError != ERROR_SUCCESS)
        return "<unknown>";

    // Smart resource cleaner pattern
    auto key = resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });

    CHAR pBuffer[_MAX_PATH] = { 0 };
    DWORD dwBufferSize = sizeof(pBuffer);
    lError = RegQueryValueExA(key.get(), "ProcessorNameString", nullptr, nullptr, (LPBYTE)pBuffer, &dwBufferSize);
    if (lError != ERROR_SUCCESS)
        return "<unknown>";

    return std::string(pBuffer);
#else
    #error Unsupported platform
#endif
}

int CPU::Affinity()
{
#if defined(__APPLE__)
    int logical = 0;
    size_t logical_size = sizeof(logical);
    if (sysctlbyname("hw.logicalcpu", &logical, &logical_size, nullptr, 0) != 0)
        logical = -1;

    return logical;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    long processors = sysconf(_SC_NPROCESSORS_ONLN);
    return processors;
#elif defined(_WIN32) || defined(_WIN64)
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    return si.dwNumberOfProcessors;
#else
    #error Unsupported platform
#endif
}

int CPU::LogicalCores()
{
    return TotalCores().first;
}

int CPU::PhysicalCores()
{
    return TotalCores().second;
}

std::pair<int, int> CPU::TotalCores()
{
#if defined(__APPLE__)
    int logical = 0;
    size_t logical_size = sizeof(logical);
    if (sysctlbyname("hw.logicalcpu", &logical, &logical_size, nullptr, 0) != 0)
        logical = -1;

    int physical = 0;
    size_t physical_size = sizeof(physical);
    if (sysctlbyname("hw.physicalcpu", &physical, &physical_size, nullptr, 0) != 0)
        physical = -1;

    return std::make_pair(logical, physical);
#elif defined(unix) || defined(__unix) || defined(__unix__)
    long processors = sysconf(_SC_NPROCESSORS_ONLN);
    return std::make_pair(processors, processors);
#elif defined(_WIN32) || defined(_WIN64)
    BOOL allocated = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pBuffer = nullptr;
    DWORD dwLength = 0;

    while (!allocated)
    {
        BOOL bResult = GetLogicalProcessorInformation(pBuffer, &dwLength);
        if (bResult == FALSE)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                if (pBuffer != nullptr)
                    std::free(pBuffer);
                pBuffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)std::malloc(dwLength);
                if (pBuffer == nullptr)
                    return std::make_pair(-1, -1);
            }
            else
                return std::make_pair(-1, -1);
        }
        else
            allocated = TRUE;
    }

    std::pair<int, int> result(0, 0);
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pCurrent = pBuffer;
    DWORD dwOffset = 0;

    while (dwOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= dwLength)
    {
        switch (pCurrent->Relationship)
        {
            case RelationProcessorCore:
                result.first += Internals::CountSetBits(pCurrent->ProcessorMask);
                result.second += 1;
                break;
            case RelationNumaNode:
            case RelationCache:
            case RelationProcessorPackage:
                break;
            default:
                return std::make_pair(-1, -1);
        }
        dwOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        pCurrent++;
    }

    std::free(pBuffer);

    return result;
#else
    #error Unsupported platform
#endif
}

int64_t CPU::ClockSpeed()
{
#if defined(__APPLE__)
    uint64_t frequency = 0;
    size_t size = sizeof(frequency);
    if (sysctlbyname("hw.cpufrequency", &frequency, &size, nullptr, 0) == 0)
        return frequency;

    return -1;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    static std::regex pattern("cpu MHz(.*): (.*)");

    std::string line;
    std::ifstream stream("/proc/cpuinfo", '\n');
    while (getline(stream, line))
    {
        std::smatch matches;
        if (std::regex_match(line, matches, pattern))
            return (int64_t)(atof(matches[2].str().c_str()) * 1000000);
    }

    return -1;
#elif defined(_WIN32) || defined(_WIN64)
    HKEY hKeyProcessor;
    long lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKeyProcessor);
    if (lError != ERROR_SUCCESS)
        return -1;

    // Smart resource cleaner pattern
    auto key = resource(hKeyProcessor, [](HKEY hKey) { RegCloseKey(hKey); });

    DWORD dwMHz = 0;
    DWORD dwBufferSize = sizeof(DWORD);
    lError = RegQueryValueExA(key.get(), "~MHz", nullptr, nullptr, (LPBYTE)&dwMHz, &dwBufferSize);
    if (lError != ERROR_SUCCESS)
        return -1;

    return dwMHz * 1000000;
#else
    #error Unsupported platform
#endif
}

bool CPU::HyperThreading()
{
    std::pair<int, int> cores = TotalCores();
    return (cores.first != cores.second);
}

} // namespace CppCommon
<|endoftext|>


<commit_before>//Author: Timur Pocheptsov, 4/02/2014

//Another demo to show transparency with TMultiGraph
//(and the really interesting curve/equation). + point compression in
//TPadPainter :))
//You can see all three flowers ONLY with Cococa (transparency).

//The equation by Paul Burke: http://paulbourke.net/geometry/

#include <cassert>
#include <vector>

#include "TMultiGraph.h"
#include "TVirtualX.h"
#include "TCanvas.h"
#include "TGraph.h"
#include "TColor.h"
#include "TMath.h"

#include "customcolor.h"

namespace {

typedef std::vector<Double_t> vector_type;
typedef vector_type::size_type size_type;

//______________________________________________________________________
void create_flower(vector_type &xs, vector_type &ys, size_type nPoints, Double_t r)
{
   assert(nPoints > 100 && "create_flower, number of points is too small");

   xs.resize(nPoints + 1);
   ys.resize(nPoints + 1);

   for (size_type i = 0; i <= nPoints; ++i) {
      const Double_t u = i * 21. * TMath::Pi() / nPoints;
      const Double_t p4 = TMath::Sin(17 * u / 3);
      const Double_t p8 = TMath::Sin(2 * TMath::Cos(3 * u) - 28 * u);
      const Double_t rr = r * (1 + TMath::Sin(11 * u / 5)) - 4 * p4 * p4 * p4 * p4 * p8 * p8 * p8 * p8 * p8 * p8 * p8 * p8;

      xs[i] = rr * TMath::Cos(u);
      ys[i] = rr * TMath::Sin(u);
   }
}

}//unnamed namespace.

void flower()
{
   //0. Indices for custom colors.
   Int_t indices[3] = {};
   if (ROOT::CocoaTutorials::FindFreeCustomColorIndices(indices) != 3) {
      Error("flower", "failed to create custom colors");
      return;
   }

   //1. I have to create a canvas to initialize gVirtualX.
   TCanvas * const cnv = new TCanvas("Chrysanthemum", "Chrysanthemum", 900, 900);
   if (gVirtualX && !gVirtualX->InheritsFrom("TGCocoa")) {
      Warning("flower", "You can see the transparency ONLY in a pdf or png output (\"File\"->\"Save As\" ->...)\n"
                        "To have transparency in a canvas graphics, you need OS X version of ROOT with cocoa enabled");
   }

   cnv->cd();//Just to suppress a warning if compiled.

   vector_type xs, ys;

   //2. Create graphs and custom colors for each graph.
   create_flower(xs, ys, 300, 6);
   TGraph * const gr1 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);
   new TColor(indices[0], 0., 0., 0.5, "custom_blue", 0.7);
   gr1->SetFillColor(indices[0]);
   gr1->SetName("part1");
   gr1->SetTitle("part1");

   create_flower(xs, ys, 500000, 8);
   TGraph * const gr2 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);
   new TColor(indices[1], 0.5, 0., 0.5, "custom_purple", 0.5);
   gr2->SetFillColor(indices[1]);
   gr2->SetName("part2");
   gr2->SetTitle("part2");

   create_flower(xs, ys, 100000, 10);
   TGraph * const gr3 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);

   //If you want to see the difference, change 0.2 to 1 in the next call:
   new TColor(indices[2], 1., 0., 0.4, "custom_magenta", 0.2);
   gr3->SetFillColor(indices[2]);
   gr3->SetName("part3");
   gr3->SetTitle("part3");

   //3. Create a final multigraph.

   //Otcveli, uzh davno ... nu ti ponEl.

   TMultiGraph * const flower = new TMultiGraph("Chrysanthemum", "Chrysanthemum");
   flower->Add(gr1);
   flower->Add(gr2);
   flower->Add(gr3);

   flower->Draw("AFP");
}
<commit_msg>To deal with my terrific polygons, Quartz is required.<commit_after>//Author: Timur Pocheptsov, 4/02/2014

//Another demo to show transparency with TMultiGraph
//(and the really interesting curve/equation). + point compression in
//TPadPainter :))
//You can see all three flowers ONLY with Cococa (transparency).

//The equation by Paul Burke: http://paulbourke.net/geometry/

#include <cassert>
#include <vector>

#include "TMultiGraph.h"
#include "TVirtualX.h"
#include "TCanvas.h"
#include "TGraph.h"
#include "TColor.h"
#include "TMath.h"

#include "customcolor.h"

namespace {

typedef std::vector<Double_t> vector_type;
typedef vector_type::size_type size_type;

//______________________________________________________________________
void create_flower(vector_type &xs, vector_type &ys, size_type nPoints, Double_t r)
{
   assert(nPoints > 100 && "create_flower, number of points is too small");

   xs.resize(nPoints + 1);
   ys.resize(nPoints + 1);

   for (size_type i = 0; i <= nPoints; ++i) {
      const Double_t u = i * 21. * TMath::Pi() / nPoints;
      const Double_t p4 = TMath::Sin(17 * u / 3);
      const Double_t p8 = TMath::Sin(2 * TMath::Cos(3 * u) - 28 * u);
      const Double_t rr = r * (1 + TMath::Sin(11 * u / 5)) - 4 * p4 * p4 * p4 * p4 * p8 * p8 * p8 * p8 * p8 * p8 * p8 * p8;

      xs[i] = rr * TMath::Cos(u);
      ys[i] = rr * TMath::Sin(u);
   }
}

}//unnamed namespace.

void flower()
{
   //0. Indices for custom colors.
   Int_t indices[3] = {};
   if (ROOT::CocoaTutorials::FindFreeCustomColorIndices(indices) != 3) {
      Error("flower", "failed to create custom colors");
      return;
   }

   //1. I have to create a canvas to initialize gVirtualX.
   TCanvas * const cnv = new TCanvas("Chrysanthemum", "Chrysanthemum", 900, 900);
   if (gVirtualX && !gVirtualX->InheritsFrom("TGCocoa")) {
      ::Error("flower", "This macro requires OS X version of ROOT with cocoa enabled");
      delete cnv;
      return;
   }

   cnv->cd();//Just to suppress a warning if compiled.

   vector_type xs, ys;

   //2. Create graphs and custom colors for each graph.
   create_flower(xs, ys, 300, 6);
   TGraph * const gr1 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);
   new TColor(indices[0], 0., 0., 0.5, "custom_blue", 0.7);
   gr1->SetFillColor(indices[0]);
   gr1->SetName("part1");
   gr1->SetTitle("part1");

   create_flower(xs, ys, 500000, 8);
   TGraph * const gr2 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);
   new TColor(indices[1], 0.5, 0., 0.5, "custom_purple", 0.5);
   gr2->SetFillColor(indices[1]);
   gr2->SetName("part2");
   gr2->SetTitle("part2");

   create_flower(xs, ys, 100000, 10);
   TGraph * const gr3 = new TGraph(Int_t(xs.size()), &xs[0], &ys[0]);

   //If you want to see the difference, change 0.2 to 1 in the next call:
   new TColor(indices[2], 1., 0., 0.4, "custom_magenta", 0.2);
   gr3->SetFillColor(indices[2]);
   gr3->SetName("part3");
   gr3->SetTitle("part3");

   //3. Create a final multigraph.

   //Otcveli, uzh davno ... nu ti ponEl.

   TMultiGraph * const flower = new TMultiGraph("Chrysanthemum", "Chrysanthemum");
   flower->Add(gr1);
   flower->Add(gr2);
   flower->Add(gr3);

   flower->Draw("AFP");
}
<|endoftext|>