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

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "accounts.hpp"
#include "budget_exception.hpp"
#include "args.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "money.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "earnings.hpp"
#include "expenses.hpp"

using namespace budget;

namespace {

static data_handler<account> accounts;

void show_accounts(){
    std::vector<std::string> columns = {"ID", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;

    for(auto& account : accounts.data){
        if(account.until == boost::gregorian::date(2099,12,31)){
            contents.push_back({to_string(account.id), account.name, to_string(account.amount)});

            total += account.amount;
        }
    }

    contents.push_back({"", "Total", to_string(total)});

    display_table(columns, contents);
}

void show_all_accounts(){
    std::vector<std::string> columns = {"ID", "Name", "Amount", "Since", "Until"};
    std::vector<std::vector<std::string>> contents;

    for(auto& account : accounts.data){
        contents.push_back({to_string(account.id), account.name, to_string(account.amount), to_string(account.since), to_string(account.until)});
    }

    display_table(columns, contents);
}

boost::gregorian::date find_new_since(){
    boost::gregorian::date date(1400,1,1);

    for(auto& account : all_accounts()){
        if(account.until != boost::gregorian::date(2099,12,31)){
            if(account.until - boost::gregorian::date_duration(1) > date){
                date = account.until - boost::gregorian::date_duration(1);
            }
        }
    }

    return date;
}

} //end of anonymous namespace

void budget::accounts_module::load(){
    load_accounts();
    load_expenses();
    load_earnings();
}

void budget::accounts_module::unload(){
    save_accounts();
}

void budget::accounts_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        show_accounts();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            show_accounts();
        } else if(subcommand == "all"){
            show_all_accounts();
        } else if(subcommand == "add"){
            enough_args(args, 4);

            account account;
            account.guid = generate_guid();
            account.name = args[2];
            account.since = find_new_since();
            account.until = boost::gregorian::date(2099,12,31);

            if(account_exists(account.name)){
                throw budget_exception("An account with this name already exists");
            }

            account.amount = parse_money(args[3]);
            not_negative(account.amount);

            add_data(accounts, std::move(account));
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(accounts, id)){
                throw budget_exception("There are no account with id " + args[2]);
            }

            for(auto& expense : all_expenses()){
                if(expense.account == id){
                    throw budget_exception("There are still some expenses linked to this account, cannot delete it");
                }
            }

            for(auto& earning : all_earnings()){
                if(earning.account == id){
                    throw budget_exception("There are still some earnings linked to this account, cannot delete it");
                }
            }

            remove(accounts, id);

            std::cout << "Account " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(accounts, id)){
                throw budget_exception("There are no account with id " + args[2]);
            }

            auto& account = get(accounts, id);

            edit_string(account.name, "Name");
            edit_money(account.amount, "Amount");

            std::cout << "Account " << id << " has been modified" << std::endl;
        } else if(subcommand == "archive"){
            std::cout << "This command will create new accounts that will be used starting from the beginning of the current month. Are you sure you want to proceed ? [yes/no] ? ";

            std::string answer;
            std::cin >> answer;

            if(answer == "yes" || answer == "y"){
                std::vector<budget::account> copies;

                auto tmp = boost::gregorian::day_clock::local_day() - boost::gregorian::months(1);
                boost::gregorian::date until_date(tmp.year(), tmp.month(), tmp.end_of_month().day());

                for(auto& account : all_accounts()){
                    if(account.until == boost::gregorian::date(2099,12,31)){
                        budget::account copy;
                        copy.guid = generate_guid();
                        copy.name = account.name;
                        copy.amount = account.amount;
                        copy.until = boost::gregorian::date(2099,12,31);
                        copy.since = until_date + boost::gregorian::date_duration(1);

                        account.until = until_date;

                        copies.push_back(std::move(copy));
                    }
                }

                for(auto& copy : copies){
                    add_data(accounts, std::move(copy));
                }
            } else {
                //No need to save anything
                return;
            }
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_accounts(){
    load_data(accounts, "accounts.data");
}

void budget::save_accounts(){
    save_data(accounts, "accounts.data");
}

budget::account& budget::get_account(std::size_t id){
    return get(accounts, id);
}

budget::account& budget::get_account(std::string name){
    for(auto& account : accounts.data){
        if(account.name == name){
            return account;
        }
    }

    budget_unreachable("The account does not exist");
}

std::ostream& budget::operator<<(std::ostream& stream, const account& account){
    return stream << account.id  << ':' << account.guid << ':' << account.name << ':' << account.amount << ':' << to_string(account.since) << ':' << to_string(account.until);
}

void budget::operator>>(const std::vector<std::string>& parts, account& account){
    account.id = to_number<std::size_t>(parts[0]);
    account.guid = parts[1];
    account.name = parts[2];
    account.amount = parse_money(parts[3]);
    account.since = boost::gregorian::from_string(parts[4]);
    account.until = boost::gregorian::from_string(parts[5]);
}

bool budget::account_exists(const std::string& name){
    for(auto& account : accounts.data){
        if(account.name == name){
            return true;
        }
    }

    return false;
}

std::vector<account>& budget::all_accounts(){
    return accounts.data;
}

std::vector<account> budget::all_accounts(boost::gregorian::greg_year year, boost::gregorian::greg_month month){
    std::vector<account> accounts;

    boost::gregorian::date date(year, month, 5);

    for(auto& account : all_accounts()){
        if(account.since < date && account.until > date){
            accounts.push_back(account);
        }
    }

    return std::move(accounts);
}

void budget::validate_account(const std::string& account){
    if(!account_exists(account)){
        throw budget_exception("The account " + account + " does not exist");
    }
}
<commit_msg>Cleanup error message<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "accounts.hpp"
#include "budget_exception.hpp"
#include "args.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "money.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "earnings.hpp"
#include "expenses.hpp"

using namespace budget;

namespace {

static data_handler<account> accounts;

void show_accounts(){
    std::vector<std::string> columns = {"ID", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;

    for(auto& account : accounts.data){
        if(account.until == boost::gregorian::date(2099,12,31)){
            contents.push_back({to_string(account.id), account.name, to_string(account.amount)});

            total += account.amount;
        }
    }

    contents.push_back({"", "Total", to_string(total)});

    display_table(columns, contents);
}

void show_all_accounts(){
    std::vector<std::string> columns = {"ID", "Name", "Amount", "Since", "Until"};
    std::vector<std::vector<std::string>> contents;

    for(auto& account : accounts.data){
        contents.push_back({to_string(account.id), account.name, to_string(account.amount), to_string(account.since), to_string(account.until)});
    }

    display_table(columns, contents);
}

boost::gregorian::date find_new_since(){
    boost::gregorian::date date(1400,1,1);

    for(auto& account : all_accounts()){
        if(account.until != boost::gregorian::date(2099,12,31)){
            if(account.until - boost::gregorian::date_duration(1) > date){
                date = account.until - boost::gregorian::date_duration(1);
            }
        }
    }

    return date;
}

} //end of anonymous namespace

void budget::accounts_module::load(){
    load_accounts();
    load_expenses();
    load_earnings();
}

void budget::accounts_module::unload(){
    save_accounts();
}

void budget::accounts_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        show_accounts();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            show_accounts();
        } else if(subcommand == "all"){
            show_all_accounts();
        } else if(subcommand == "add"){
            enough_args(args, 4);

            account account;
            account.guid = generate_guid();
            account.name = args[2];
            account.since = find_new_since();
            account.until = boost::gregorian::date(2099,12,31);

            if(account_exists(account.name)){
                throw budget_exception("An account with this name already exists");
            }

            account.amount = parse_money(args[3]);
            not_negative(account.amount);

            add_data(accounts, std::move(account));
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(accounts, id)){
                throw budget_exception("There are no account with id " + args[2]);
            }

            for(auto& expense : all_expenses()){
                if(expense.account == id){
                    throw budget_exception("There are still some expenses linked to this account, cannot delete it");
                }
            }

            for(auto& earning : all_earnings()){
                if(earning.account == id){
                    throw budget_exception("There are still some earnings linked to this account, cannot delete it");
                }
            }

            remove(accounts, id);

            std::cout << "Account " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(accounts, id)){
                throw budget_exception("There are no account with id " + args[2]);
            }

            auto& account = get(accounts, id);

            edit_string(account.name, "Name");
            edit_money(account.amount, "Amount");

            std::cout << "Account " << id << " has been modified" << std::endl;
        } else if(subcommand == "archive"){
            std::cout << "This command will create new accounts that will be used starting from the beginning of the current month. Are you sure you want to proceed ? [yes/no] ? ";

            std::string answer;
            std::cin >> answer;

            if(answer == "yes" || answer == "y"){
                std::vector<budget::account> copies;

                auto tmp = boost::gregorian::day_clock::local_day() - boost::gregorian::months(1);
                boost::gregorian::date until_date(tmp.year(), tmp.month(), tmp.end_of_month().day());

                for(auto& account : all_accounts()){
                    if(account.until == boost::gregorian::date(2099,12,31)){
                        budget::account copy;
                        copy.guid = generate_guid();
                        copy.name = account.name;
                        copy.amount = account.amount;
                        copy.until = boost::gregorian::date(2099,12,31);
                        copy.since = until_date + boost::gregorian::date_duration(1);

                        account.until = until_date;

                        copies.push_back(std::move(copy));
                    }
                }

                for(auto& copy : copies){
                    add_data(accounts, std::move(copy));
                }
            } else {
                //No need to save anything
                return;
            }
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_accounts(){
    load_data(accounts, "accounts.data");
}

void budget::save_accounts(){
    save_data(accounts, "accounts.data");
}

budget::account& budget::get_account(std::size_t id){
    return get(accounts, id);
}

budget::account& budget::get_account(std::string name){
    for(auto& account : accounts.data){
        if(account.name == name){
            return account;
        }
    }

    budget_unreachable("The account does not exist");
}

std::ostream& budget::operator<<(std::ostream& stream, const account& account){
    return stream << account.id  << ':' << account.guid << ':' << account.name << ':' << account.amount << ':' << to_string(account.since) << ':' << to_string(account.until);
}

void budget::operator>>(const std::vector<std::string>& parts, account& account){
    account.id = to_number<std::size_t>(parts[0]);
    account.guid = parts[1];
    account.name = parts[2];
    account.amount = parse_money(parts[3]);
    account.since = boost::gregorian::from_string(parts[4]);
    account.until = boost::gregorian::from_string(parts[5]);
}

bool budget::account_exists(const std::string& name){
    for(auto& account : accounts.data){
        if(account.name == name){
            return true;
        }
    }

    return false;
}

std::vector<account>& budget::all_accounts(){
    return accounts.data;
}

std::vector<account> budget::all_accounts(boost::gregorian::greg_year year, boost::gregorian::greg_month month){
    std::vector<account> accounts;

    boost::gregorian::date date(year, month, 5);

    for(auto& account : all_accounts()){
        if(account.since < date && account.until > date){
            accounts.push_back(account);
        }
    }

    return std::move(accounts);
}

void budget::validate_account(const std::string& account){
    if(!account_exists(account)){
        throw budget_exception("The account \"" + account + "\" does not exist");
    }
}
<|endoftext|>


<commit_before>/**
 * @file
 * @author Jason Lingle
 * @brief Contains the ShipIO interface
 *
 * ShipIO is the next-generation (replacing ShipParse) method of storing Ships
 * to files. Unlike ShipParse, which used a custom, non-extensible format, this
 * utilizes libconfig++ to allow new features to be added without breaking old
 * files.
 *
 * ShipIO represents the ship as a table of cells with interconnections, instead of
 * a tree with implicit connections. In order to allow the new(er) ShipEditor
 * to easily add and remove cells, cells are given names instead of indices.
 *
 * From the top-level of the file, the format is:
 * \verbatim
 * info                 Group
 * info.name            String, name of ship
 * info.version         Version number, in case of incompatible changes
 *                      (current=0)
 * info.alliance        String array, alliances the ship can be a part of.
 *                      This is obsolete, but still required until TestState is
 *                      entirely eliminated (the array ["EUF","WADR"] is
 *                      recommended.)
 * info.class           String, class of ship (ie, "C", "B", or "A")
 * info.bridge          Name of bridge cell.
 * info.reinforcement   Float, reinforcement level
 * info.mass            Optional flaot. Mass of ship. This is automatically set
 *                      upon load.
 * info.author          String, name of creator
 * info.time            Optional group
 * info.time.creation   Optional string, format YYYY.MM.DD HH:mm:ss
 * info.time.modification Optional string, format YYYY.MM.DD HH:mm:ss
 * info.revision        Optional integer, number of times ship has been saved
 * info.old_format      Optional string, contents of ShipParse .ship file if
 *                      converted
 * info.ownerid         Optional integer, userid of owner on Abendstern Network.
 * info.fileid          Optional integer, fileid of ship file on Abendstern
 *                      Network.
 * info.energy_levels   Optional integer group; each child indicates a weapon
 *                      and a preferred energy level for that weapon.
 * info.verificgtion_signature  Optional integer, internally used
 * info.original_filvname       Optional string, name of file before uploading
 * info.guid            Optional string (mandatory on Abendstern Network);
 *                      globally-unique identifier for this ship.
 * cells                Group
 * cells.<name>         Group for cell <name>
 * cells.*.type         String, type of cell (square, circle, right, equil).
 * cells.*.neighbours   String array, listing names of neighbours in order.
 * cells.*.s0           Optional group for system 0
 * cells.*.s1           Optional group for system 1
 * cells.*.s*.type      String, typename of the system.
 * cells.*.s*.orient    Integer, orientation of the system.
 * cells.*.s*.capacity  Integer; for capacitors, capacity.
 * cells.*.s*.radius    Float; for shields, radius
 * cells.*.s*.strength  Float; for shields, strength
 * cells.*.s*.turbo     Boolean; indicates the turbo status of GatlingPlasmaBurstLaunchers
 * \endverbatim
 */

/*
 * shipio.hxx
 *
 *  Created on: 18.07.2010
 *      Author: Jason Lingle
 */

#ifndef SHIPIO_HXX_
#define SHIPIO_HXX_

class Ship;
class GameField;

/** The current version of ShipIO.
 *
 * 0 = Prerelease
 *
 * Any version can read anything before it.
 */
#define SHIPIO_VERSION 0

/** Loads a ship from the given mounted libconfig++ file.
 * @param field The field in which the Ship will live
 * @param root The ConfReg root to use
 * @return The ship loaded
 * @throw NoSuchSettingException if ConfRegi indicates a problem
 * @throw libconfig::SettingException on invalid configuration
 * @throw std::runtime_error if logical problems are encountered
 */
Ship* loadShip(GameField* field, const char* root);

/** Saves a ship into the given mounted libconfig++ file, first deleting
 * everything in that mount. This does not sync the mount.
 * The information written is minimal. Name and alliance are nondescriptive
 * name determined from the mountpoint. Class is determined automatically by
 * the highest-class system present.
 * Due to the cell naming system used, no more than 26^4 = 456,976 cells
 * can be present in the Ship.
 */
void saveShip(Ship*, const char*);
#endif /* SHIPIO_HXX_ */
<commit_msg>Add missing enable_sharing and needs_uploading fields to ShipIO documentation.<commit_after>/**
 * @file
 * @author Jason Lingle
 * @brief Contains the ShipIO interface
 *
 * ShipIO is the next-generation (replacing ShipParse) method of storing Ships
 * to files. Unlike ShipParse, which used a custom, non-extensible format, this
 * utilizes libconfig++ to allow new features to be added without breaking old
 * files.
 *
 * ShipIO represents the ship as a table of cells with interconnections, instead of
 * a tree with implicit connections. In order to allow the new(er) ShipEditor
 * to easily add and remove cells, cells are given names instead of indices.
 *
 * From the top-level of the file, the format is:
 * \verbatim
 * info                 Group
 * info.name            String, name of ship
 * info.version         Version number, in case of incompatible changes
 *                      (current=0)
 * info.alliance        String array, alliances the ship can be a part of.
 *                      This is obsolete, but still required until TestState is
 *                      entirely eliminated (the array ["EUF","WADR"] is
 *                      recommended.)
 * info.class           String, class of ship (ie, "C", "B", or "A")
 * info.bridge          Name of bridge cell.
 * info.reinforcement   Float, reinforcement level
 * info.mass            Optional flaot. Mass of ship. This is automatically set
 *                      upon load.
 * info.author          String, name of creator
 * info.time            Optional group
 * info.time.creation   Optional string, format YYYY.MM.DD HH:mm:ss
 * info.time.modification Optional string, format YYYY.MM.DD HH:mm:ss
 * info.revision        Optional integer, number of times ship has been saved
 * info.old_format      Optional string, contents of ShipParse .ship file if
 *                      converted
 * info.ownerid         Optional integer, userid of owner on Abendstern Network.
 * info.fileid          Optional integer, fileid of ship file on Abendstern
 *                      Network.
 * info.energy_levels   Optional integer group; each child indicates a weapon
 *                      and a preferred energy level for that weapon.
 * info.verificgtion_signature  Optional integer, internally used
 * info.original_filvname       Optional string, name of file before uploading
 * info.guid            Optional string (mandatory on Abendstern Network);
 *                      globally-unique identifier for this ship.
 * info.enable_sharing  Optional boolean; whether to allow users other than the
 *                      owner to download the ship on the Abendstern Network.
 * info.needs_uploading Optional boolean; true if the ship has changed since
 *                      its last upload to the Abendstern Network.
 *                      (This is generally meaningless for downloaded ships.)
 * cells                Group
 * cells.<name>         Group for cell <name>
 * cells.*.type         String, type of cell (square, circle, right, equil).
 * cells.*.neighbours   String array, listing names of neighbours in order.
 * cells.*.s0           Optional group for system 0
 * cells.*.s1           Optional group for system 1
 * cells.*.s*.type      String, typename of the system.
 * cells.*.s*.orient    Integer, orientation of the system.
 * cells.*.s*.capacity  Integer; for capacitors, capacity.
 * cells.*.s*.radius    Float; for shields, radius
 * cells.*.s*.strength  Float; for shields, strength
 * cells.*.s*.turbo     Boolean; indicates the turbo status of GatlingPlasmaBurstLaunchers
 * \endverbatim
 */

/*
 * shipio.hxx
 *
 *  Created on: 18.07.2010
 *      Author: Jason Lingle
 */

#ifndef SHIPIO_HXX_
#define SHIPIO_HXX_

class Ship;
class GameField;

/** The current version of ShipIO.
 *
 * 0 = Prerelease
 *
 * Any version can read anything before it.
 */
#define SHIPIO_VERSION 0

/** Loads a ship from the given mounted libconfig++ file.
 * @param field The field in which the Ship will live
 * @param root The ConfReg root to use
 * @return The ship loaded
 * @throw NoSuchSettingException if ConfRegi indicates a problem
 * @throw libconfig::SettingException on invalid configuration
 * @throw std::runtime_error if logical problems are encountered
 */
Ship* loadShip(GameField* field, const char* root);

/** Saves a ship into the given mounted libconfig++ file, first deleting
 * everything in that mount. This does not sync the mount.
 * The information written is minimal. Name and alliance are nondescriptive
 * name determined from the mountpoint. Class is determined automatically by
 * the highest-class system present.
 * Due to the cell naming system used, no more than 26^4 = 456,976 cells
 * can be present in the Ship.
 */
void saveShip(Ship*, const char*);
#endif /* SHIPIO_HXX_ */
<|endoftext|>


<commit_before>#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>

#include <tf/transform_listener.h>

#include <geometry_msgs/PointStamped.h>
#include <art_msgs/ObjectsCentroids.h>

#include <ar_track_alvar_msgs/AlvarMarkers.h>
#include <ar_track_alvar_msgs/AlvarMarker.h>
#include <geometry_msgs/Pose.h>
#include <tf/tf.h>
#include <exception>
#include <tf/transform_broadcaster.h>

class NoMainMarker: public std::exception {
public:
    virtual const char* what() const throw() {
        return "No main marker!";
    }
};

class ArtCalibration {
public:
    ArtCalibration() {
        table_marker_sub = nh_.subscribe ("/table/ar_pose_marker", 1, &ArtCalibration::table_marker_cb, this);
        pr2_marker_sub = nh_.subscribe ("/pr2/ar_pose_marker", 1, &ArtCalibration::pr2_marker_cb, this);
        ros_init();
    }

    ~ArtCalibration() {

    }

    void ros_init() {
        nh_.param<std::string>("robot_frame", robot_frame_, "odom_combined");
        nh_.param<std::string>("table_frame", table_frame_, "kinect2_link");
        nh_.param<std::string>("world_frame", world_frame_, "table");
    }

private:

    tf::StampedTransform tr_table_, tr_pr2_;
    tf::TransformBroadcaster br_;
    ros::Timer tr_timer_;

    ros::Subscriber table_marker_sub, pr2_marker_sub;
    ros::NodeHandle nh_;

    std::string world_frame_, robot_frame_, table_frame_;

    bool table_calibration_done_ = false, pr2_calibration_done_ = false;

    static const int MAIN_MARKER_SIZE = 10;

    void table_marker_cb(ar_track_alvar_msgs::AlvarMarkersConstPtr markers) {
        geometry_msgs::Pose pose;
        try {
            pose = get_main_marker_pose(*markers);
        }
        catch (NoMainMarker& e) {
            std::cout << e.what() << std::endl;
            return;
        }
        tr_table_ = create_transform_from_pose(pose, table_frame_);
        table_marker_sub.shutdown();
        table_calibration_done_ = true;
        tr_timer_ = nh_.createTimer(ros::Duration(0.1), &ArtCalibration::trCallback, this);
    }

    void pr2_marker_cb(ar_track_alvar_msgs::AlvarMarkersConstPtr markers) {
        geometry_msgs::Pose pose;
        try {
            pose = get_main_marker_pose(*markers);
        }
        catch (NoMainMarker& e) {
            std::cout << e.what() << std::endl;
            return;
        }
        tr_pr2_ = create_transform_from_pose(pose, robot_frame_);
        pr2_marker_sub.shutdown();
        pr2_calibration_done_ = true;
        tr_timer_ = nh_.createTimer(ros::Duration(0.1), &ArtCalibration::trCallback, this);
    }

    tf::StampedTransform create_transform_from_pose(geometry_msgs::Pose pose, std::string output_frame) {
        tf::Transform tr;
        tf::Quaternion q;
        tr.setOrigin(tf::Vector3(pose.position.x, pose.position.y, pose.position.z));
        tf::quaternionMsgToTF(pose.orientation, q);
        q.normalize();
        tr.setRotation(q);
        return tf::StampedTransform(tr.inverse(), ros::Time::now(), world_frame_, output_frame);
    }

    geometry_msgs::Pose get_main_marker_pose(ar_track_alvar_msgs::AlvarMarkers marker) {
        for (int i = 0; i < marker.markers.size(); ++i) {
            if (marker.markers[i].id == MAIN_MARKER_SIZE) {
                return marker.markers[i].pose.pose;
            }
        }
        return geometry_msgs::Pose();
    }

    void trCallback(const ros::TimerEvent& event) {
        if (table_calibration_done_) {
            tr_table_.stamp_ = ros::Time::now();
            br_.sendTransform(tr_table_);
        }
        if (pr2_calibration_done_) {
            tr_pr2_.stamp_ = ros::Time::now();
            br_.sendTransform(tr_pr2_);
        }
    }

};

int main (int argc, char** argv)
{
  // Initialize ROS
  ros::init (argc, argv, "art_calibration");

  ArtCalibration calibration;

  // Spin
  ros::spin();

}
<commit_msg>filtrovani (tezko rict zda funkcni)<commit_after>#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>

#include <tf/transform_listener.h>

#include <geometry_msgs/PointStamped.h>
#include <art_msgs/ObjectsCentroids.h>

#include <ar_track_alvar_msgs/AlvarMarkers.h>
#include <ar_track_alvar_msgs/AlvarMarker.h>
#include <geometry_msgs/Pose.h>
#include <tf/tf.h>
#include <exception>
#include <tf/transform_broadcaster.h>

class NoMainMarker: public std::exception {
public:
    virtual const char* what() const throw() {
        return "No main marker!";
    }
};

class ArtCalibration {
public:
    ArtCalibration() {
        table_marker_sub = nh_.subscribe ("/table/ar_pose_marker", 1, &ArtCalibration::table_marker_cb, this);
        pr2_marker_sub = nh_.subscribe ("/pr2/ar_pose_marker", 1, &ArtCalibration::pr2_marker_cb, this);
        ros_init();
    }

    ~ArtCalibration() {

    }

    void ros_init() {
        nh_.param<std::string>("robot_frame", robot_frame_, "odom_combined");
        nh_.param<std::string>("table_frame", table_frame_, "kinect2_link");
        nh_.param<std::string>("world_frame", world_frame_, "table");
    }

private:

    tf::StampedTransform tr_table_, tr_pr2_;
    tf::TransformBroadcaster br_;
    ros::Timer tr_timer_;

    ros::Subscriber table_marker_sub, pr2_marker_sub;
    ros::NodeHandle nh_;

    std::string world_frame_, robot_frame_, table_frame_;

    std::vector<geometry_msgs::Pose> table_poses, pr2_poses;

    bool table_calibration_done_ = false, pr2_calibration_done_ = false, table_calibration_enough_poses_ = false;

    static const int MAIN_MARKER_SIZE = 10, POSES_COUNT = 20;

    void table_marker_cb(ar_track_alvar_msgs::AlvarMarkersConstPtr markers) {
        geometry_msgs::Pose pose;
        try {
            pose = get_main_marker_pose(*markers);
        }
        catch (NoMainMarker& e) {
            std::cout << e.what() << std::endl;
            return;
        }
        table_poses.push_back(pose);
        if (table_poses.size() > POSES_COUNT) {
            table_calibration_enough_poses_ = true;
            table_marker_sub.shutdown();
        }

        //tr_table_ = create_transform_from_pose(pose, table_frame_);
        //table_marker_sub.shutdown();
        //table_calibration_done_ = true;
        //tr_timer_ = nh_.createTimer(ros::Duration(0.1), &ArtCalibration::trCallback, this);
    }

    tf::StampedTransform create_transform_from_poses_vector(std::vector<geometry_msgs::Pose> poses, std::string output_frame) {
        geometry_msgs::Pose avg_pose, std_mean_pose;
        avg_pose.position.x = 0;
        avg_pose.position.y = 0;
        avg_pose.position.z = 0;
        avg_pose.orientation.x = 0;
        avg_pose.orientation.y = 0;
        avg_pose.orientation.z = 0;
        avg_pose.orientation.w = 0;

        for (int i = 0; i < poses.size(); i++) {
            avg_pose.position.x += poses[i].position.x;
            avg_pose.position.y += poses[i].position.y;
            avg_pose.position.z += poses[i].position.z;
            avg_pose.orientation.x += poses[i].orientation.x;
            avg_pose.orientation.y += poses[i].orientation.y;
            avg_pose.orientation.z += poses[i].orientation.z;
            avg_pose.orientation.w += poses[i].orientation.w;
        }

        avg_pose.position.x /= poses.size();
        avg_pose.position.y /= poses.size();
        avg_pose.position.z /= poses.size();
        avg_pose.orientation.x /= poses.size();
        avg_pose.orientation.y /= poses.size();
        avg_pose.orientation.z /= poses.size();
        avg_pose.orientation.w /= poses.size();

        for (int i = 0; i < poses.size(); i++) {
            std_mean_pose.position.x += poses[i].position.x*poses[i].position.x - avg_pose.position.x*avg_pose.position.x;
            std_mean_pose.position.y += poses[i].position.y*poses[i].position.y - avg_pose.position.y*avg_pose.position.y;
            std_mean_pose.position.z += poses[i].position.z*poses[i].position.z - avg_pose.position.z*avg_pose.position.z;
            std_mean_pose.orientation.x += poses[i].orientation.x*poses[i].orientation.x - avg_pose.orientation.x*avg_pose.orientation.x;
            std_mean_pose.orientation.y += poses[i].orientation.y*poses[i].orientation.y - avg_pose.orientation.y*avg_pose.orientation.y;
            std_mean_pose.orientation.z += poses[i].orientation.z*poses[i].orientation.z - avg_pose.orientation.z*avg_pose.orientation.z;
            std_mean_pose.orientation.w += poses[i].orientation.w*poses[i].orientation.w - avg_pose.orientation.w*avg_pose.orientation.w;
        }

        std_mean_pose.position.x /= (poses.size() - 1);
        std_mean_pose.position.y /= (poses.size() - 1);
        std_mean_pose.position.z /= (poses.size() - 1);
        std_mean_pose.orientation.x /= (poses.size() - 1);
        std_mean_pose.orientation.y /= (poses.size() - 1);
        std_mean_pose.orientation.z /= (poses.size() - 1);
        std_mean_pose.orientation.w /= (poses.size() - 1);

        std_mean_pose.position.x = sqrt(std_mean_pose.position.x);
        std_mean_pose.position.y = sqrt(std_mean_pose.position.y);
        std_mean_pose.position.z = sqrt(std_mean_pose.position.z);
        std_mean_pose.orientation.x = sqrt(std_mean_pose.orientation.x);
        std_mean_pose.orientation.y = sqrt(std_mean_pose.orientation.y);
        std_mean_pose.orientation.z = sqrt(std_mean_pose.orientation.z);
        std_mean_pose.orientation.w = sqrt(std_mean_pose.orientation.w);

        std::vector<geometry_msgs::Pose> new_poses;
        for (int i = 0; i < poses.size(); i++) {
            float std_mean_len = sqrt(std_mean_pose.position.x*std_mean_pose.position.x +
                                      std_mean_pose.position.y*std_mean_pose.position.y +
                                      std_mean_pose.position.z*std_mean_pose.position.z);

            float pose_len = sqrt(poses[i].position.x*poses[i].position.x +
                                  poses[i].position.y*poses[i].position.y +
                                  poses[i].position.z*poses[i].position.z);

            if (pose_len <= std_mean_len) {
                new_poses.push_back(poses[i]);
            }

        }

        return create_transform_from_pose(avg_pose, output_frame);
    }

    void pr2_marker_cb(ar_track_alvar_msgs::AlvarMarkersConstPtr markers) {
        geometry_msgs::Pose pose;
        try {
            pose = get_main_marker_pose(*markers);
        }
        catch (NoMainMarker& e) {
            std::cout << e.what() << std::endl;
            return;
        }
        tr_pr2_ = create_transform_from_pose(pose, robot_frame_);
        pr2_marker_sub.shutdown();
        pr2_calibration_done_ = true;
        tr_timer_ = nh_.createTimer(ros::Duration(0.1), &ArtCalibration::trCallback, this);
    }

    tf::StampedTransform create_transform_from_pose(geometry_msgs::Pose pose, std::string output_frame) {
        tf::Transform tr;
        tf::Quaternion q;
        tr.setOrigin(tf::Vector3(pose.position.x, pose.position.y, pose.position.z));
        tf::quaternionMsgToTF(pose.orientation, q);
        q.normalize();
        tr.setRotation(q);
        return tf::StampedTransform(tr.inverse(), ros::Time::now(), world_frame_, output_frame);
    }

    geometry_msgs::Pose get_main_marker_pose(ar_track_alvar_msgs::AlvarMarkers marker) {
        for (int i = 0; i < marker.markers.size(); ++i) {
            if (marker.markers[i].id == MAIN_MARKER_SIZE) {
                return marker.markers[i].pose.pose;
            }
        }
        return geometry_msgs::Pose();
    }

    void trCallback(const ros::TimerEvent& event) {
        if (table_calibration_done_) {
            tr_table_.stamp_ = ros::Time::now();
            br_.sendTransform(tr_table_);
        }
        if (pr2_calibration_done_) {
            tr_pr2_.stamp_ = ros::Time::now();
            br_.sendTransform(tr_pr2_);
        }
    }

};

int main (int argc, char** argv)
{
  // Initialize ROS
  ros::init (argc, argv, "art_calibration");

  ArtCalibration calibration;

  // Spin
  ros::spin();

}
<|endoftext|>


<commit_before>#include "PoissonRand.h"

PoissonRand::PoissonRand(double rate)
{
    setRate(rate);
}

std::string PoissonRand::name()
{
    return "Poisson(" + toStringWithPrecision(getRate()) + ")";
}

void PoissonRand::setRate(double rate)
{
    lambda = std::max(rate, MIN_POSITIVE);
    expLambda = std::exp(-lambda);
}

double PoissonRand::P(int k) const
{
    return (k >= 0) ? expLambda * std::pow(lambda, k) / RandMath::factorial(k) : 0;
}

double PoissonRand::F(double x) const
{
    if (x <= 0)
        return 0;
    int k = std::floor(x);
    return RandMath::upperIncGamma(k + 1, lambda) / RandMath::factorial(k);
}

double PoissonRand::variate() const
{
    int y = 0;
    double u = UniformRand::standardVariate();
    double p = expLambda, s = p;
    while (s < u) {
        ++y;
        p *= lambda / y;
        s += p;
    }
    return y;
}

double PoissonRand::variate(double rate)
{
    int y = -1;
    double s = 0;
    do {
        s += ExponentialRand::standardVariate();
        ++y;
    } while (s < rate);
    return y;
}

std::complex<double> PoissonRand::CF(double t) const
{
    std::complex<double> y(0.0, t);
    y = std::exp(y) - 1.0;
    y *= lambda;
    return std::exp(y);
}

double PoissonRand::Median() const
{
    /// this value is approximate
    return std::floor(lambda + 1.0 / 3 - 0.02 / lambda);
}

double PoissonRand::Mode() const
{
    return std::floor(lambda);
}

double PoissonRand::Skewness() const
{
    return 1.0 / std::sqrt(lambda);
}

double PoissonRand::ExcessKurtosis() const
{
    return 1.0 / lambda;
}
<commit_msg>Update PoissonRand.cpp<commit_after>#include "PoissonRand.h"

PoissonRand::PoissonRand(double rate)
{
    setRate(rate);
}

std::string PoissonRand::name()
{
    return "Poisson(" + toStringWithPrecision(getRate()) + ")";
}

void PoissonRand::setRate(double rate)
{
    lambda = rate;
    if (lambda <= 0)
        lambda = MIN_POSITIVE;
    expLambda = std::exp(-lambda);
}

double PoissonRand::P(int k) const
{
    return (k >= 0) ? expLambda * std::pow(lambda, k) / RandMath::factorial(k) : 0;
}

double PoissonRand::F(double x) const
{
    if (x <= 0)
        return 0;
    int k = std::floor(x);
    return RandMath::upperIncGamma(k + 1, lambda) / RandMath::factorial(k);
}

double PoissonRand::variate() const
{
    int y = 0;
    double u = UniformRand::standardVariate();
    double p = expLambda, s = p;
    while (s < u) {
        ++y;
        p *= lambda / y;
        s += p;
    }
    return y;
}

double PoissonRand::variate(double rate)
{
    int y = -1;
    double s = 0;
    do {
        s += ExponentialRand::standardVariate();
        ++y;
    } while (s < rate);
    return y;
}

std::complex<double> PoissonRand::CF(double t) const
{
    std::complex<double> y(0.0, t);
    y = std::exp(y) - 1.0;
    y *= lambda;
    return std::exp(y);
}

double PoissonRand::Median() const
{
    /// this value is approximate
    return std::floor(lambda + 1.0 / 3 - 0.02 / lambda);
}

double PoissonRand::Mode() const
{
    return std::floor(lambda);
}

double PoissonRand::Skewness() const
{
    return 1.0 / std::sqrt(lambda);
}

double PoissonRand::ExcessKurtosis() const
{
    return 1.0 / lambda;
}
<|endoftext|>


<commit_before><commit_msg>improve debug message for shader compilatione errors<commit_after><|endoftext|>


<commit_before>#include "iApp.h"
#include "bbcConfig.h"

#include "Poco/DateTimeParser.h"

string iApp::app_name = "iApp";
string iApp::app_version = "1.0.0";

// Archive (compress) logs that are 1MB
#define IAPP_DEF_LOG_SIZE_ARCH_KB_MAX 1024

using namespace bbc::utils;

iApp::iApp(string _app_name, string _app_version, bool _log_to_file, bool _archive_logs) {

    if(!Config::instance()->load_success){
        ofLogError("Config XML failed to load") << Config::data_file_path;
    }else{
        ofLogNotice("Config XML loaded!") << Config::data_file_path;
    }

	auto_hide_cursor = true;
    cursor_visible = true;

    keep_cursor_hidden = false; // a lock

    header_logged = false;

	cursor_duration_ms = 3000;

    if(_app_name != "") app_name = _app_name;
    if(_app_version != "") app_version = _app_version;

    log_to_file = _log_to_file;
    archive_logs = _archive_logs;

    if(CONFIG_GET("log", "to_file", false)) {
        if(!log_to_file) { // not already setup
            log_to_file = true;
            logSetup(CONFIG_GET("log", "append", true));
            logHeader(); // relog header so it gets to file
        }
    }else{
        logSetup();
        logHeader();
    }

    ofSetLogLevel((ofLogLevel)CONFIG_GET("log", "level", (int)OF_LOG_NOTICE));

    if(Config::instance()->attributeExists("config:window", "fps")) {
		int fps = CONFIG_GET("window", "fps", 60);
        ofSetFrameRate(fps);
        ofLogNotice("iApp set") << "fps=" << fps;
    }

	bool vs = CONFIG_GET("window", "vertical_sync", true);

    ofSetVerticalSync(vs);
    ofLogNotice("iApp set") << "vertical_sync=" << vs;

    // NOTE: to get full fps, dont specify fps and set vertical_sync="0"

    if(CONFIG_GET("window", "fullscreen", true)){
		ofToggleFullscreen();
    }

    cursor_timer = ofGetElapsedTimeMillis() + cursor_duration_ms;

    if(CONFIG_GET("mouse", "hide", false)) { // override auto hide cursor
        auto_hide_cursor = false;
        hideCursor(true);
    }

    auto_shutdown = CONFIG_GET("shutdown", "enabled", false);

    if(auto_shutdown) { // override auto hide cursor

        string time_str = CONFIG_GET("shutdown", "time", "20:20");

        ofLogNotice("auto_shutdown setting up with time") << time_str;

        Poco::LocalDateTime now;

        int time_zone_dif = now.tzd();

        Poco::DateTime t = Poco::DateTimeParser::parse("%H:%M:%S", time_str, time_zone_dif);

        Poco::LocalDateTime next(now.year(), now.month(), now.day(), t.hour(), t.minute(), t.second());

        if(next < now) {
            ofLogNotice("Shutdown time already elapsed for today making it for tomorrow");

            // Add a day
            Poco::Timespan dif(0, 24, 0, 0, 0);
            shutdown_time = next + dif;

        }else{
            shutdown_time = next;
        }

    }

}

void iApp::setup() {
    ofBaseApp::setup();
    ofLogNotice("iApp:setup");
    // NOT SURE THIS WILL WORK?

}

void iApp::draw(ofEventArgs & args) {
    ofBaseApp::draw(args);

}

void iApp::update(ofEventArgs& args) {
    ofBaseApp::update(args);

    if(auto_hide_cursor) cursorCheck();

    if(keep_cursor_hidden) hideCursor();

    if(auto_shutdown) {
        Poco::LocalDateTime now;

        if( now > shutdown_time && canAutoShutdownNow() ) {
            ofLogWarning("iApp: AUTO SHUTDOWN was scheduled for now. Terminating app.");
            ofExit();
        }
    }

}

bool iApp::canAutoShutdownNow() {
    return true;
}

void iApp::cursorCheck() {

    // cout << "check cursor " << ofGetElapsedTimeMillis() << endl;

    if(cursor_visible) {
        if(ofGetElapsedTimeMillis() >= cursor_timer) { // its been still long enough to auto hide it
            hideCursor();
           // cout << " hideCursor " << ofGetElapsedTimeMillis() << endl;
            // cursor_visible = false;
        }
    }

}

void iApp::toggleCursor() {

    if(cursor_visible) {
        hideCursor();
    }else{
        showCursor();
    }
}

void iApp::hideCursor(bool permanent) {

   // ofLogNotice("iApp::hideCursor");

    // Cursor show and hide not working on mac in 0.8.0 : using workaroud from http://forum.openframeworks.cc/t/ofhidecursor-not-working-on-osx-10-8-v0-8-0/13379/3
    // Is working in 0.8.1 so do a OF compile check here
    #ifdef __APPLE__
        CGDisplayHideCursor(NULL);
    #else
        ofHideCursor();
    #endif

    cursor_visible = false;

    if(permanent) keep_cursor_hidden = true;

}

void iApp::showCursor() {

    //ofLogNotice("iApp::showCursor");

    #ifdef __APPLE__
        CGDisplayShowCursor(NULL);
    #else
        ofShowCursor();
    #endif

    cursor_visible = true;

    if(keep_cursor_hidden) keep_cursor_hidden = false;

}

void iApp::cursorUpdate() {

    // reset the timer that was counting down to when it restarts

    //  cout << "cursorUpdate " << ofGetElapsedTimeMillis() << endl;

    if(!cursor_visible) { // >> why??
        // cursor_visible = true;
        showCursor();
    }

    cursor_timer = ofGetElapsedTimeMillis() + cursor_duration_ms; // reset timer hid it after 3 seconds of no movement
}

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

void iApp::keyPressed(ofKeyEventArgs & key) {
    ofBaseApp::keyPressed(key);

}

void iApp::keyReleased(ofKeyEventArgs & key) {
    ofBaseApp::keyReleased(key);

}

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

void iApp::mouseMoved( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseMoved(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mouseDragged( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseDragged(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mousePressed( ofMouseEventArgs & mouse ) {
    ofBaseApp::mousePressed(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mouseReleased( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseReleased(mouse);
}

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

void iApp::windowResized(ofResizeEventArgs & resize) {
    ofBaseApp::windowResized(resize);

}

void iApp::dragEvent(ofDragInfo dragInfo) {
    ofBaseApp::dragEvent(dragInfo);

}

void iApp::gotMessage(ofMessage msg){
    ofBaseApp::gotMessage(msg);

}

void iApp::exit(ofEventArgs & args) {
    ofBaseApp::exit(args);
    logFooter();
    ofLogToConsole(); // reset logging to file
}

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

void iApp::drawCalibration(int alpha) {

    /*
     Draw a screen calibration graphic, useful for projection calibration,
     */

    ofPushStyle();

    float sw = 2.0f;
    ofSetLineWidth(sw);

    float w = ofGetWidth();
    float h = ofGetHeight();

    float cx = w / 2.0;
    float cy = h / 2.0;

    float hsw = sw / 2.0;

    ofSetCircleResolution(36);

    ofSetColor(255, alpha);
    ofNoFill();

    // border
    ofRectMode(OF_RECTMODE_CORNER);
    ofRect(hsw, hsw, w-sw, h-sw);

    // diagonal lines
    ofLine(hsw, hsw, w+hsw, h-hsw);
    ofLine(-hsw, h-hsw, w-hsw, hsw);

    // centre lines
    ofLine(cx, 0, cx, h);
    ofLine(0, cy, w, cy);

    // horizontal 1/4 lines
    ofLine(0, h/4, w, h/4);
    ofLine(0, h-h/4, w, h-h/4);

    // Draw centre rect & circle
    ofRectMode(OF_RECTMODE_CENTER);

    float dim = min(w, h) * .66f;

    ofEllipse(cx, cy, dim, dim);

    ofSetLineWidth(1.0f);

    // Draw circles at the sides
    int n = 8;
    float mini_rad = h / n;
    float y;

    for(int i = 0; i<n-1; i++) {
        y = (mini_rad)+(i*mini_rad);
        int c = i % 4;
        switch(c) {
            case 0: ofSetColor(255, alpha); break;
            case 1: ofSetColor(255,0,0, alpha); break;
            case 2: ofSetColor(0,255,0, alpha); break;
            case 3: ofSetColor(0,0,255, alpha); break;
        }

        ofEllipse(0, y, mini_rad, mini_rad); // LHS
        ofEllipse(w, y, mini_rad, mini_rad); // RHS
    }

    // Draw more comprehensive grid

    // do this at the ratio of the screen?
    // TODO: make the ratio dynamic too reading getWidth and getHeight
    float wc = 16.0f;
    float hc = 9.0f;

    float grid_x = w / wc;
    float grid_y = h / hc;

    ofSetColor(255, alpha);

    // vertical lines
    for(int col = 1; col < wc; col++) {
        int gx = round(col * grid_x);
        ofLine(gx, 0, gx, h);
    }

    // horizontal lines
    for(int row = 1; row < hc; row++) {
        int gy = round(row * grid_y);
        ofLine(0, gy, w, gy);
    }

    ofPopStyle();

}

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

void iApp::logSetup(bool appending) {

    if(log_to_file) {

        string log_name = app_name + ".log";

        if(archive_logs) {

            ofFile f("logs/" + log_name);

            if(f.exists()) {

                uint64_t sz_kb = f.getSize() / 1024;

                if(sz_kb >= IAPP_DEF_LOG_SIZE_ARCH_KB_MAX) {

                    ofFile parent_dir(f.getEnclosingDirectory());

                    #if defined(TARGET_OSX)
                        string zip_cmd = "gzip '" + f.getAbsolutePath() + "'";
                        ofLogNotice("ARCHIVING LOG with") << zip_cmd;
                        string zip_result = ofSystem(zip_cmd);
                        ofLogNotice("zip_result") << zip_result;

                        string rename_cmd =  "mv '" + f.getAbsolutePath() + ".gz' '" + parent_dir.getAbsolutePath() + "/" + ofGetTimestampString("%Y-%m-%d-%H-%M-%S") + "_" + app_name + ".log.gz'";
                        ofLogNotice("RENAMING LOG ARCHIVE with") << rename_cmd;
                        string rename_result = ofSystem(rename_cmd);
                        ofLogNotice("rename_result") << rename_result;
                    #endif

                    #if defined(TARGET_WIN32)
                        // TODO: Win could use: win7 cmd option: http://superuser.com/questions/110991/can-you-zip-a-file-from-the-command-prompt-using-only-windows-built-in-capabili
                    #endif

                }

            }

        }

        ofLogToFile("logs/" + log_name, appending);
    }

    int level = CONFIG_GET("log", "level", 1);
    // VERBOSE = 0  NOTICE = 1 WARNING = 2 ERROR = 3 FATAL_ERROR = 4 SILENT = 5

    if(level >= 0 && level <= (int)OF_LOG_SILENT) {
        ofSetLogLevel( (ofLogLevel)level );
    }

}

void iApp::logHeader() {
    ofLogNotice("");
    ofLogNotice("--------------------------------------");
    ofLogNotice("--- START ") << app_name << " app v" << app_version << " @ " << ofGetTimestampString("%H:%M:%S %d-%m-%Y");
    ofLogNotice("--- ") << "oF:" << OF_VERSION_MAJOR << "." << OF_VERSION_MINOR << "." << OF_VERSION_PATCH << " platform:" << ofGetTargetPlatform();
    // TODO: log OS version and name + opengl properties, free gpu memory?
    ofLogNotice("--------------------------------------");

    header_logged = true;
}

void iApp::logFooter() {
    ofLogNotice("--------------------------------------");
    ofLogNotice("--- STOP ") << app_name << " app v" << app_version << " @ " << ofGetTimestampString("%H:%M:%S %d-%m-%Y");
    ofLogNotice("--------------------------------------");
}

//-----------------------------------------------------------------------------<commit_msg>iApp Cursor shenanigans begin again<commit_after>#include "iApp.h"
#include "bbcConfig.h"

#include "Poco/DateTimeParser.h"

string iApp::app_name = "iApp";
string iApp::app_version = "1.0.0";

// Archive (compress) logs that are 1MB
#define IAPP_DEF_LOG_SIZE_ARCH_KB_MAX 1024

using namespace bbc::utils;

iApp::iApp(string _app_name, string _app_version, bool _log_to_file, bool _archive_logs) {

    if(!Config::instance()->load_success){
        ofLogError("Config XML failed to load") << Config::data_file_path;
    }else{
        ofLogNotice("Config XML loaded!") << Config::data_file_path;
    }

	auto_hide_cursor = true;
    cursor_visible = true;

    keep_cursor_hidden = false; // a lock

    header_logged = false;

	cursor_duration_ms = 3000;

    if(_app_name != "") app_name = _app_name;
    if(_app_version != "") app_version = _app_version;

    log_to_file = _log_to_file;
    archive_logs = _archive_logs;

    if(CONFIG_GET("log", "to_file", false)) {
        if(!log_to_file) { // not already setup
            log_to_file = true;
            logSetup(CONFIG_GET("log", "append", true));
            logHeader(); // relog header so it gets to file
        }
    }else{
        logSetup();
        logHeader();
    }

    ofSetLogLevel((ofLogLevel)CONFIG_GET("log", "level", (int)OF_LOG_NOTICE));

    if(Config::instance()->attributeExists("config:window", "fps")) {
		int fps = CONFIG_GET("window", "fps", 60);
        ofSetFrameRate(fps);
        ofLogNotice("iApp set") << "fps=" << fps;
    }

	bool vs = CONFIG_GET("window", "vertical_sync", true);

    ofSetVerticalSync(vs);
    ofLogNotice("iApp set") << "vertical_sync=" << vs;

    // NOTE: to get full fps, dont specify fps and set vertical_sync="0"

    if(CONFIG_GET("window", "fullscreen", true)){
		ofToggleFullscreen();
    }

    cursor_timer = ofGetElapsedTimeMillis() + cursor_duration_ms;

    if(CONFIG_GET("mouse", "hide", false)) { // override auto hide cursor
        auto_hide_cursor = false;
        hideCursor(true);
    }else{
      //  showCursor(); // work around 0.8.4 bug: https://github.com/openframeworks/openFrameworks/issues/3052#issuecomment-63941074
    }

    auto_shutdown = CONFIG_GET("shutdown", "enabled", false);

    if(auto_shutdown) { // override auto hide cursor

        string time_str = CONFIG_GET("shutdown", "time", "20:20");

        ofLogNotice("auto_shutdown setting up with time") << time_str;

        Poco::LocalDateTime now;

        int time_zone_dif = now.tzd();

        Poco::DateTime t = Poco::DateTimeParser::parse("%H:%M:%S", time_str, time_zone_dif);

        Poco::LocalDateTime next(now.year(), now.month(), now.day(), t.hour(), t.minute(), t.second());

        if(next < now) {
            ofLogNotice("Shutdown time already elapsed for today making it for tomorrow");

            // Add a day
            Poco::Timespan dif(0, 24, 0, 0, 0);
            shutdown_time = next + dif;

        }else{
            shutdown_time = next;
        }

    }

}

void iApp::setup() {
    ofBaseApp::setup();
    ofLogNotice("iApp:setup");
    // NOT SURE THIS WILL WORK?

}

void iApp::draw(ofEventArgs & args) {
    ofBaseApp::draw(args);

}

void iApp::update(ofEventArgs& args) {
    ofBaseApp::update(args);

    if(auto_hide_cursor) cursorCheck();

    if(keep_cursor_hidden) hideCursor();

    if(auto_shutdown) {
        Poco::LocalDateTime now;

        if( now > shutdown_time && canAutoShutdownNow() ) {
            ofLogWarning("iApp: AUTO SHUTDOWN was scheduled for now. Terminating app.");
            ofExit();
        }
    }

}

bool iApp::canAutoShutdownNow() {
    return true;
}

void iApp::cursorCheck() {

    // cout << "check cursor " << ofGetElapsedTimeMillis() << endl;

    if(cursor_visible) {
        if(ofGetElapsedTimeMillis() >= cursor_timer) { // its been still long enough to auto hide it
            hideCursor();
           // cout << " hideCursor " << ofGetElapsedTimeMillis() << endl;
            // cursor_visible = false;
        }
    }

}

void iApp::toggleCursor() {

    if(cursor_visible) {
        hideCursor();
    }else{
        showCursor();
    }
}

void iApp::hideCursor(bool permanent) {

    // ofLogNotice("iApp::hideCursor");

    // Cursor show and hide not working on mac in 0.8.0 : using workaroud from http://forum.openframeworks.cc/t/ofhidecursor-not-working-on-osx-10-8-v0-8-0/13379/3
    // Is working in 0.8.1 so do a OF compile check here
    //#ifdef __APPLE__
   //     CGDisplayHideCursor(NULL);
   // #else
        ofHideCursor();
   // #endif

    cursor_visible = false;

    if(permanent) keep_cursor_hidden = true;

}

void iApp::showCursor() {

    ofLogNotice("iApp::showCursor");

    //#ifdef __APPLE__
   //     CGDisplayShowCursor(NULL);
   // #else
        ofShowCursor();
    //#endif

    cursor_visible = true;

    if(keep_cursor_hidden) keep_cursor_hidden = false;

}

void iApp::cursorUpdate() {

    // reset the timer that was counting down to when it restarts

    //  cout << "cursorUpdate " << ofGetElapsedTimeMillis() << endl;

    if(!cursor_visible) { // >> why??
        // cursor_visible = true;
        showCursor();
    }

    cursor_timer = ofGetElapsedTimeMillis() + cursor_duration_ms; // reset timer hid it after 3 seconds of no movement
}

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

void iApp::keyPressed(ofKeyEventArgs & key) {
    ofBaseApp::keyPressed(key);

}

void iApp::keyReleased(ofKeyEventArgs & key) {
    ofBaseApp::keyReleased(key);

}

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

void iApp::mouseMoved( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseMoved(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mouseDragged( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseDragged(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mousePressed( ofMouseEventArgs & mouse ) {
    ofBaseApp::mousePressed(mouse);

    if(auto_hide_cursor) cursorUpdate();

}

void iApp::mouseReleased( ofMouseEventArgs & mouse ) {
    ofBaseApp::mouseReleased(mouse);
}

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

void iApp::windowResized(ofResizeEventArgs & resize) {
    ofBaseApp::windowResized(resize);

}

void iApp::dragEvent(ofDragInfo dragInfo) {
    ofBaseApp::dragEvent(dragInfo);

}

void iApp::gotMessage(ofMessage msg){
    ofBaseApp::gotMessage(msg);

}

void iApp::exit(ofEventArgs & args) {
    ofBaseApp::exit(args);
    logFooter();
    ofLogToConsole(); // reset logging to file
}

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

void iApp::drawCalibration(int alpha) {

    /*
     Draw a screen calibration graphic, useful for projection calibration,
     */

    ofPushStyle();

    float sw = 2.0f;
    ofSetLineWidth(sw);

    float w = ofGetWidth();
    float h = ofGetHeight();

    float cx = w / 2.0;
    float cy = h / 2.0;

    float hsw = sw / 2.0;

    ofSetCircleResolution(36);

    ofSetColor(255, alpha);
    ofNoFill();

    // border
    ofRectMode(OF_RECTMODE_CORNER);
    ofRect(hsw, hsw, w-sw, h-sw);

    // diagonal lines
    ofLine(hsw, hsw, w+hsw, h-hsw);
    ofLine(-hsw, h-hsw, w-hsw, hsw);

    // centre lines
    ofLine(cx, 0, cx, h);
    ofLine(0, cy, w, cy);

    // horizontal 1/4 lines
    ofLine(0, h/4, w, h/4);
    ofLine(0, h-h/4, w, h-h/4);

    // Draw centre rect & circle
    ofRectMode(OF_RECTMODE_CENTER);

    float dim = min(w, h) * .66f;

    ofEllipse(cx, cy, dim, dim);

    ofSetLineWidth(1.0f);

    // Draw circles at the sides
    int n = 8;
    float mini_rad = h / n;
    float y;

    for(int i = 0; i<n-1; i++) {
        y = (mini_rad)+(i*mini_rad);
        int c = i % 4;
        switch(c) {
            case 0: ofSetColor(255, alpha); break;
            case 1: ofSetColor(255,0,0, alpha); break;
            case 2: ofSetColor(0,255,0, alpha); break;
            case 3: ofSetColor(0,0,255, alpha); break;
        }

        ofEllipse(0, y, mini_rad, mini_rad); // LHS
        ofEllipse(w, y, mini_rad, mini_rad); // RHS
    }

    // Draw more comprehensive grid

    // do this at the ratio of the screen?
    // TODO: make the ratio dynamic too reading getWidth and getHeight
    float wc = 16.0f;
    float hc = 9.0f;

    float grid_x = w / wc;
    float grid_y = h / hc;

    ofSetColor(255, alpha);

    // vertical lines
    for(int col = 1; col < wc; col++) {
        int gx = round(col * grid_x);
        ofLine(gx, 0, gx, h);
    }

    // horizontal lines
    for(int row = 1; row < hc; row++) {
        int gy = round(row * grid_y);
        ofLine(0, gy, w, gy);
    }

    ofPopStyle();

}

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

void iApp::logSetup(bool appending) {

    if(log_to_file) {

        string log_name = app_name + ".log";

        if(archive_logs) {

            ofFile f("logs/" + log_name);

            if(f.exists()) {

                uint64_t sz_kb = f.getSize() / 1024;

                if(sz_kb >= IAPP_DEF_LOG_SIZE_ARCH_KB_MAX) {

                    ofFile parent_dir(f.getEnclosingDirectory());

                    #if defined(TARGET_OSX)
                        string zip_cmd = "gzip '" + f.getAbsolutePath() + "'";
                        ofLogNotice("ARCHIVING LOG with") << zip_cmd;
                        string zip_result = ofSystem(zip_cmd);
                        ofLogNotice("zip_result") << zip_result;

                        string rename_cmd =  "mv '" + f.getAbsolutePath() + ".gz' '" + parent_dir.getAbsolutePath() + "/" + ofGetTimestampString("%Y-%m-%d-%H-%M-%S") + "_" + app_name + ".log.gz'";
                        ofLogNotice("RENAMING LOG ARCHIVE with") << rename_cmd;
                        string rename_result = ofSystem(rename_cmd);
                        ofLogNotice("rename_result") << rename_result;
                    #endif

                    #if defined(TARGET_WIN32)
                        // TODO: Win could use: win7 cmd option: http://superuser.com/questions/110991/can-you-zip-a-file-from-the-command-prompt-using-only-windows-built-in-capabili
                    #endif

                }

            }

        }

        ofLogToFile("logs/" + log_name, appending);
    }

    int level = CONFIG_GET("log", "level", 1);
    // VERBOSE = 0  NOTICE = 1 WARNING = 2 ERROR = 3 FATAL_ERROR = 4 SILENT = 5

    if(level >= 0 && level <= (int)OF_LOG_SILENT) {
        ofSetLogLevel( (ofLogLevel)level );
    }

}

void iApp::logHeader() {
    ofLogNotice("");
    ofLogNotice("--------------------------------------");
    ofLogNotice("--- START ") << app_name << " app v" << app_version << " @ " << ofGetTimestampString("%H:%M:%S %d-%m-%Y");
    ofLogNotice("--- ") << "oF:" << OF_VERSION_MAJOR << "." << OF_VERSION_MINOR << "." << OF_VERSION_PATCH << " platform:" << ofGetTargetPlatform();
    // TODO: log OS version and name + opengl properties, free gpu memory?
    ofLogNotice("--------------------------------------");

    header_logged = true;
}

void iApp::logFooter() {
    ofLogNotice("--------------------------------------");
    ofLogNotice("--- STOP ") << app_name << " app v" << app_version << " @ " << ofGetTimestampString("%H:%M:%S %d-%m-%Y");
    ofLogNotice("--------------------------------------");
}

//-----------------------------------------------------------------------------<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief tests for datafile structure sizes
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "arangod/VocBase/datafile.h"
#include "arangod/VocBase/primary-collection.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CStructureSizeSetup {
  CStructureSizeSetup () {
  }

  ~CStructureSizeSetup () {
  }
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CStructureSizeTest, CStructureSizeSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof some basic elements
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_basic_elements) {
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_cid_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_rid_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_tick_t));

  BOOST_CHECK_EQUAL(4, sizeof(TRI_voc_crc_t));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_marker) {
  size_t s = sizeof(TRI_df_marker_t);

  BOOST_CHECK_EQUAL(24, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL(0, offsetof(struct TRI_df_marker_s, _size));
  BOOST_CHECK_EQUAL(4, offsetof(struct TRI_df_marker_s, _crc));
  BOOST_CHECK_EQUAL(8, offsetof(struct TRI_df_marker_s, _type));

  // TODO: fix alignment in struct TRI_df_marker_s. it is currently not portable!
  // BOOST_CHECK_EQUAL(16, offsetof(struct TRI_df_marker_s, _tick));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_header_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_header_marker) {
  size_t s = sizeof(TRI_df_header_marker_t);

  BOOST_CHECK_EQUAL(24 + 16, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_footer_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_footer_marker) {
  size_t s = sizeof(TRI_df_footer_marker_t);

  BOOST_CHECK_EQUAL(24 + 8, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_document_key_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_document_key_marker) {
  size_t s = sizeof(TRI_doc_document_key_marker_t);

  BOOST_CHECK_EQUAL(24 + 32, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<commit_msg>added tests for offsets<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief tests for datafile structure sizes
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "arangod/VocBase/datafile.h"
#include "arangod/VocBase/primary-collection.h"
#include "arangod/VocBase/voc-shaper.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CStructureSizeSetup {
  CStructureSizeSetup () {
  }

  ~CStructureSizeSetup () {
  }
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CStructureSizeTest, CStructureSizeSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof some basic elements
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_basic_elements) {
  BOOST_CHECK_EQUAL(4, sizeof(TRI_col_type_t));
  BOOST_CHECK_EQUAL(4, sizeof(TRI_df_marker_type_t));
  BOOST_CHECK_EQUAL(4, sizeof(TRI_df_version_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_shape_aid_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_shape_sid_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_shape_size_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_cid_t));
  BOOST_CHECK_EQUAL(4, sizeof(TRI_voc_crc_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_eid_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_rid_t));
  BOOST_CHECK_EQUAL(4, sizeof(TRI_voc_size_t));
  BOOST_CHECK_EQUAL(8, sizeof(TRI_voc_tick_t));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_marker) {
  size_t s = sizeof(TRI_df_marker_t);

  BOOST_CHECK_EQUAL(24, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_marker_s, _size));
  BOOST_CHECK_EQUAL( 4, offsetof(struct TRI_df_marker_s, _crc));
  BOOST_CHECK_EQUAL( 8, offsetof(struct TRI_df_marker_s, _type));
  BOOST_CHECK_EQUAL(16, offsetof(struct TRI_df_marker_s, _tick));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_header_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_header_marker) {
  size_t s = sizeof(TRI_df_header_marker_t);

  BOOST_CHECK_EQUAL(24 + 16, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_header_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_df_header_marker_s, _version));
  BOOST_CHECK_EQUAL(28, offsetof(struct TRI_df_header_marker_s, _maximalSize));
  BOOST_CHECK_EQUAL(32, offsetof(struct TRI_df_header_marker_s, _fid));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_footer_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_footer_marker) {
  size_t s = sizeof(TRI_df_footer_marker_t);

  BOOST_CHECK_EQUAL(24 + 8, s);
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_footer_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_df_footer_marker_s, _maximalSize));
  BOOST_CHECK_EQUAL(28, offsetof(struct TRI_df_footer_marker_s, _totalSize));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_document_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_document_marker) {
  size_t s = sizeof(TRI_df_document_marker_t);

  BOOST_CHECK_EQUAL(24, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_document_marker_s, base));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_skip_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_skip_marker) {
  size_t s = sizeof(TRI_df_skip_marker_t);

  BOOST_CHECK_EQUAL(24, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_skip_marker_s, base));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_col_header_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_col_header_marker) {
  size_t s = sizeof(TRI_col_header_marker_t);

  BOOST_CHECK_EQUAL(24 + 16, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_col_header_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_col_header_marker_s, _type));
  BOOST_CHECK_EQUAL(32, offsetof(struct TRI_col_header_marker_s, _cid));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_document_key_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_doc_document_key_marker) {
  size_t s = sizeof(TRI_doc_document_key_marker_t);

  BOOST_CHECK_EQUAL(24 + 32, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_doc_document_key_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_doc_document_key_marker_s, _rid));
  BOOST_CHECK_EQUAL(32, offsetof(struct TRI_doc_document_key_marker_s, _sid));
  BOOST_CHECK_EQUAL(40, offsetof(struct TRI_doc_document_key_marker_s, _shape));
  BOOST_CHECK_EQUAL(48, offsetof(struct TRI_doc_document_key_marker_s, _offsetKey));
  BOOST_CHECK_EQUAL(50, offsetof(struct TRI_doc_document_key_marker_s, _offsetJson));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_edge_key_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_doc_edge_key_marker) {
  size_t s = sizeof(TRI_doc_edge_key_marker_t);

  BOOST_CHECK_EQUAL(24 + 56, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_doc_edge_key_marker_s, base));
  BOOST_CHECK_EQUAL(56, offsetof(struct TRI_doc_edge_key_marker_s, _toCid));
  BOOST_CHECK_EQUAL(64, offsetof(struct TRI_doc_edge_key_marker_s, _fromCid));
  BOOST_CHECK_EQUAL(72, offsetof(struct TRI_doc_edge_key_marker_s, _offsetToKey));
  BOOST_CHECK_EQUAL(74, offsetof(struct TRI_doc_edge_key_marker_s, _offsetFromKey));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_begin_transaction_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_doc_begin_transaction_marker) {
  size_t s = sizeof(TRI_doc_begin_transaction_marker_t);

  BOOST_CHECK_EQUAL(24 + 8, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_doc_begin_transaction_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_doc_begin_transaction_marker_s, _tid));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_commit_transaction_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_doc_commit_transaction_marker) {
  size_t s = sizeof(TRI_doc_commit_transaction_marker_t);

  BOOST_CHECK_EQUAL(24 + 8, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_doc_commit_transaction_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_doc_commit_transaction_marker_s, _tid));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_doc_abort_transaction_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_doc_abort_transaction_marker) {
  size_t s = sizeof(TRI_doc_abort_transaction_marker_t);

  BOOST_CHECK_EQUAL(24 + 8, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_doc_abort_transaction_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_doc_abort_transaction_marker_s, _tid));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_attribute_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_attribute_marker) {
  size_t s = sizeof(TRI_df_attribute_marker_t);

  BOOST_CHECK_EQUAL(24 + 16, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_attribute_marker_s, base));
  BOOST_CHECK_EQUAL(24, offsetof(struct TRI_df_attribute_marker_s, _aid));
  BOOST_CHECK_EQUAL(32, offsetof(struct TRI_df_attribute_marker_s, _size));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test sizeof TRI_df_shape_marker_t
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_df_shape_marker) {
  size_t s = sizeof(TRI_df_shape_marker_t);

  BOOST_CHECK_EQUAL(24, s); // base + own size
  BOOST_CHECK_EQUAL(true, s % 8 == 0);

  BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_shape_marker_s, base));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<|endoftext|>


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

#ifndef __STOUT_NUMIFY_HPP__
#define __STOUT_NUMIFY_HPP__

#include <sstream>
#include <string>

#include <boost/lexical_cast.hpp>

#include "error.hpp"
#include "none.hpp"
#include "option.hpp"
#include "result.hpp"
#include "strings.hpp"
#include "try.hpp"

template <typename T>
Try<T> numify(const std::string& s)
{
  try {
    return boost::lexical_cast<T>(s);
  } catch (const boost::bad_lexical_cast&) {
    // Unfortunately boost::lexical_cast cannot cast a hexadecimal
    // number even with a "0x" prefix, we have to workaround this
    // issue here. We also process negative hexadecimal number "-0x"
    // here to keep it consistent with non-hexadecimal numbers.
    if (strings::startsWith(s, "0x") || strings::startsWith(s, "0X") ||
        strings::startsWith(s, "-0x") || strings::startsWith(s, "-0X")) {
      // NOTE: Hexadecimal floating-point constants (e.g., 0x1p-5,
      // 0x10.0), are allowed in C99, but cannot be used as floating
      // point literals in standard C++. Some C++ compilers might
      // accept them as an extension; for consistency, we always
      // disallow them.  See:
      // https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
      if (!strings::contains(s, ".") && !strings::contains(s, "p")) {
        T result;
        std::stringstream ss;
        // Process negative hexadecimal numbers.
        if (strings::startsWith(s, "-")) {
          ss << std::hex << s.substr(1);
          ss >> result;
          result = -result;
        } else {
          ss << std::hex << s;
          ss >> result;
        }
        // Make sure we really hit the end of the string.
        if (!ss.fail() && ss.eof()) {
          return result;
        }
      }
    }

    return Error("Failed to convert '" + s + "' to number");
  }
}

template <typename T>
Try<T> numify(const char* s)
{
  return numify<T>(std::string(s));
}

template <typename T>
Result<T> numify(const Option<std::string>& s)
{
  if (s.isSome()) {
    Try<T> t = numify<T>(s.get());
    if (t.isSome()) {
      return t.get();
    } else if (t.isError()) {
      return Error(t.error());
    }
  }

  return None();
}

#endif // __STOUT_NUMIFY_HPP__
<commit_msg>Fixed warnings in `numify.hpp`.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_NUMIFY_HPP__
#define __STOUT_NUMIFY_HPP__

#include <sstream>
#include <string>

#include <boost/lexical_cast.hpp>

#include "error.hpp"
#include "none.hpp"
#include "option.hpp"
#include "result.hpp"
#include "strings.hpp"
#include "try.hpp"

template <typename T>
Try<T> numify(const std::string& s)
{
  try {
    return boost::lexical_cast<T>(s);
  } catch (const boost::bad_lexical_cast&) {
    // Unfortunately boost::lexical_cast cannot cast a hexadecimal
    // number even with a "0x" prefix, we have to workaround this
    // issue here. We also process negative hexadecimal number "-0x"
    // here to keep it consistent with non-hexadecimal numbers.
    if (strings::startsWith(s, "0x") || strings::startsWith(s, "0X") ||
        strings::startsWith(s, "-0x") || strings::startsWith(s, "-0X")) {
      // NOTE: Hexadecimal floating-point constants (e.g., 0x1p-5,
      // 0x10.0), are allowed in C99, but cannot be used as floating
      // point literals in standard C++. Some C++ compilers might
      // accept them as an extension; for consistency, we always
      // disallow them.  See:
      // https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
      if (!strings::contains(s, ".") && !strings::contains(s, "p")) {
        T result;
        std::stringstream ss;
        // Process negative hexadecimal numbers.
        if (strings::startsWith(s, "-")) {
          ss << std::hex << s.substr(1);
          ss >> result;
          // Note: When numify is instantiated with unsigned scalars
          // the expected behaviour is as follow:
          // numify<T>("-1") == std::numeric_limits<T>::max();
          // Disabled unary negation warning for all types.
#ifdef __WINDOWS__
          #pragma warning(disable:4146)
#endif
          result = -result;
#ifdef __WINDOWS__
          #pragma warning(default:4146)
#endif
        } else {
          ss << std::hex << s;
          ss >> result;
        }
        // Make sure we really hit the end of the string.
        if (!ss.fail() && ss.eof()) {
          return result;
        }
      }
    }

    return Error("Failed to convert '" + s + "' to number");
  }
}

template <typename T>
Try<T> numify(const char* s)
{
  return numify<T>(std::string(s));
}

template <typename T>
Result<T> numify(const Option<std::string>& s)
{
  if (s.isSome()) {
    Try<T> t = numify<T>(s.get());
    if (t.isSome()) {
      return t.get();
    } else if (t.isError()) {
      return Error(t.error());
    }
  }

  return None();
}

#endif // __STOUT_NUMIFY_HPP__
<|endoftext|>