<commit_before>#ifndef TAMER_HTTP_HH
#define TAMER_HTTP_HH 1
#include "fd.hh"
#include "http_parser.h"
#include <vector>
#include <string>
#include <sstream>
#include <memory>
#include <unordered_map>
#include <time.h>
namespace tamer {
class http_parser;

struct http_header {
    std::string name;
    std::string value;
    inline http_header(std::string n, std::string v)
        : name(TAMER_MOVE(n)), value(TAMER_MOVE(v)) {
    }
    inline bool is(const char* s, size_t len) const {
        return name.length() == len && memcmp(name.data(), s, len) == 0;
    }
    inline bool is(const std::string& s) const {
        return is(s.data(), s.length());
    }
    inline bool is_canonical(const char* s, size_t len) const {
        if (name.length() != len)
            return false;
        const char* names = name.data();
        const char* end = s + len;
        for (; s != end; ++s, ++names)
            if (*s != *names
                && (*names < 'A' || *names > 'Z' || (*names - 'A' + 'a') != *s))
                return false;
        return true;
    }
    inline bool is_canonical(const std::string& s) const {
        return is_canonical(s.data(), s.length());
    }
    inline bool is_content_length() const {
        return is_canonical("content-length", 14);
    }
};

class http_message {
  public:
    typedef std::vector<http_header>::const_iterator header_iterator;

    inline http_message();

    inline bool ok() const;
    inline bool operator!() const;
    inline enum http_errno error() const;

    inline unsigned http_major() const;
    inline unsigned http_minor() const;

    inline unsigned status_code() const;
    inline const std::string& status_message() const;
    inline enum http_method method() const;
    inline const std::string& url() const;
    header_iterator find_canonical_header(const std::string& name) const;
    inline header_iterator find_header(const std::string& name) const;
    inline bool has_canonical_header(const std::string& name) const;
    inline bool has_header(const std::string& name) const;
    inline const std::string& body() const;

    std::string host() const;
    inline std::string url_schema() const;
    inline std::string url_host() const;
    std::string url_host_port() const;
    inline std::string url_path() const;
    inline bool has_query() const;
    inline std::string query() const;
    bool has_query(const std::string& name) const;
    std::string query(const std::string& name) const;

    inline header_iterator header_begin() const;
    inline header_iterator header_end() const;
    inline header_iterator query_begin() const;
    inline header_iterator query_end() const;

    inline http_message& clear();
    void add_header(std::string key, std::string value);

    inline http_message& http_major(unsigned v);
    inline http_message& http_minor(unsigned v);
    inline http_message& error(enum http_errno e);
    inline http_message& status_code(unsigned code);
    inline http_message& status_code(unsigned code, std::string message);
    inline http_message& method(enum http_method method);
    inline http_message& url(std::string url);
    inline http_message& header(std::string key, std::string value);
    inline http_message& header(std::string key, size_t value);
    inline http_message& date_header(std::string key, time_t value);
    inline http_message& body(std::string body);

    static std::string canonicalize(std::string x);
    static const char* default_status_message(unsigned code);

  private:
    enum {
        info_url = 1, info_query = 2
    };

    struct info_type {
        unsigned flags;
        struct http_parser_url urlp;
        std::vector<http_header> raw_query;
        inline info_type()
            : flags(0) {
        }
    };

    unsigned short major_;
    unsigned short minor_;
    unsigned status_code_ : 16;
    unsigned method_ : 8;
    unsigned error_ : 7;
    unsigned upgrade_ : 1;

    std::string url_;
    std::string status_message_;
    std::vector<http_header> raw_headers_;
    std::string body_;

    mutable std::shared_ptr<info_type> info_;

    inline void kill_info(unsigned f) const;
    inline info_type& info(unsigned f) const;
    void make_info(unsigned f) const;
    inline bool has_url_field(int field) const;
    inline std::string url_field(int field) const;
    void do_clear();
    friend class http_parser;
};

class http_parser : public tamed_class {
  public:
    http_parser(enum http_parser_type type);

    void clear();
    inline bool ok() const;
    inline enum http_errno error() const;
    inline bool should_keep_alive() const;

    void receive(fd f, event<http_message> done);
    void send(fd f, const http_message& m, event<> done);
    static void send_request(fd f, const http_message& m, event<> done);
    static void send_response(fd f, const http_message& m, event<> done);
    static void send_response_headers(fd f, const http_message& m, event<> done);
    static void send_response_chunk(fd f, std::string s, event<> done);
    static void send_response_end(fd f, event<> done);

    inline void clear_should_keep_alive();

  private:
    ::http_parser hp_;

    struct message_data {
        http_message hm;
        std::string key;
        std::ostringstream sbuf;
        bool done;
    };

    static const http_parser_settings settings;
    static http_parser* get_parser(::http_parser* hp);
    static message_data* get_message_data(::http_parser* hp);
    static int on_message_begin(::http_parser* hp);
    static int on_url(::http_parser* hp, const char* s, size_t len);
    static int on_status(::http_parser* hp, const char* s, size_t len);
    static int on_header_field(::http_parser* hp, const char* s, size_t len);
    static int on_header_value(::http_parser* hp, const char* s, size_t len);
    static int on_headers_complete(::http_parser* hp);
    static int on_body(::http_parser* hp, const char* s, size_t len);
    static int on_message_complete(::http_parser* hp);
    inline void copy_parser_status(message_data& md);
    static void unparse_request_headers(std::ostringstream& buf,
                                        const http_message& m);
    static void unparse_response_headers(std::ostringstream& buf,
                                         const http_message& m,
                                         bool include_content_length);

    class closure__receive__2fdQ12http_message_; void receive(closure__receive__2fdQ12http_message_&);
    class closure__send_request__2fdRK12http_messageQ_; static void send_request(closure__send_request__2fdRK12http_messageQ_&);
    class closure__send_response__2fdRK12http_messageQ_; static void send_response(closure__send_response__2fdRK12http_messageQ_&);
    class closure__send_response_chunk__2fdSsQ_; static void send_response_chunk(closure__send_response_chunk__2fdSsQ_&);
};

inline http_message::http_message()
    : major_(1), minor_(1), status_code_(200), method_(HTTP_GET),
      error_(HPE_OK), upgrade_(0) {
}

inline void http_message::kill_info(unsigned f) const {
    if (info_)
        info_->flags &= ~f;
}

inline unsigned http_message::http_major() const {
    return major_;
}

inline unsigned http_message::http_minor() const {
    return minor_;
}

inline bool http_message::ok() const {
    return error_ == HPE_OK;
}

inline bool http_message::operator!() const {
    return !ok();
}

inline enum http_errno http_message::error() const {
    return (enum http_errno) error_;
}

inline unsigned http_message::status_code() const {
    return status_code_;
}

inline const std::string& http_message::status_message() const {
    return status_message_;
}

inline enum http_method http_message::method() const {
    return (enum http_method) method_;
}

inline const std::string& http_message::url() const {
    return url_;
}

inline http_message::header_iterator http_message::find_header(const std::string& key) const {
    return find_canonical_header(canonicalize(key));
}

inline bool http_message::has_canonical_header(const std::string& key) const {
    return find_canonical_header(key) != header_end();
}

inline bool http_message::has_header(const std::string& key) const {
    return has_canonical_header(canonicalize(key));
}

inline const std::string& http_message::body() const {
    return body_;
}

inline bool http_message::has_url_field(int field) const {
    return info(info_url).urlp.field_set & (1 << field);
}

inline std::string http_message::url_field(int field) const {
    const info_type& i = info(info_url);
    if (i.urlp.field_set & (1 << field))
        return url_.substr(i.urlp.field_data[field].off,
                           i.urlp.field_data[field].len);
    else
        return std::string();
}

inline bool http_message::has_query() const {
    return has_url_field(UF_QUERY);
}

inline std::string http_message::query() const {
    return url_field(UF_QUERY);
}

inline std::string http_message::url_schema() const {
    return url_field(UF_SCHEMA);
}

inline std::string http_message::url_host() const {
    return url_field(UF_HOST);
}

inline std::string http_message::url_path() const {
    return url_field(UF_PATH);
}

inline http_message& http_message::http_major(unsigned v) {
    major_ = v;
    return *this;
}

inline http_message& http_message::http_minor(unsigned v) {
    minor_ = v;
    return *this;
}

inline http_message& http_message::clear() {
    do_clear();
    return *this;
}

inline http_message& http_message::error(enum http_errno e) {
    error_ = e;
    return *this;
}

inline http_message& http_message::status_code(unsigned code) {
    status_code_ = code;
    status_message_ = std::string();
    return *this;
}

inline http_message& http_message::status_code(unsigned code, std::string message) {
    status_code_ = code;
    status_message_ = TAMER_MOVE(message);
    return *this;
}

inline http_message& http_message::method(enum http_method method) {
    method_ = (unsigned) method;
    return *this;
}

inline http_message& http_message::url(std::string url) {
    url_ = TAMER_MOVE(url);
    kill_info(info_url | info_query);
    return *this;
}

inline http_message& http_message::header(std::string key, std::string value) {
    add_header(TAMER_MOVE(key), TAMER_MOVE(value));
    return *this;
}

inline http_message& http_message::header(std::string key, size_t value) {
    std::ostringstream buf;
    buf << value;
    add_header(TAMER_MOVE(key), buf.str());
    return *this;
}

inline http_message& http_message::date_header(std::string key, time_t value) {
    char buf[128];
    // XXX current locale
    strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&value));
    add_header(TAMER_MOVE(key), std::string(buf));
    return *this;
}

inline http_message& http_message::body(std::string body) {
    body_ = TAMER_MOVE(body);
    return *this;
}

inline http_message::info_type& http_message::info(unsigned f) const {
    if (!info_ || !info_.unique() || (info_->flags & f) != f)
        make_info(f);
    return *info_.get();
}

inline http_message::header_iterator http_message::header_begin() const {
    return raw_headers_.begin();
}

inline http_message::header_iterator http_message::header_end() const {
    return raw_headers_.end();
}

inline http_message::header_iterator http_message::query_begin() const {
    return info(info_query).raw_query.begin();
}

inline http_message::header_iterator http_message::query_end() const {
    return info(info_query).raw_query.end();
}

inline bool http_parser::ok() const {
    return hp_.http_errno == (unsigned) HPE_OK;
}

inline enum http_errno http_parser::error() const {
    return (enum http_errno) hp_.http_errno;
}

inline bool http_parser::should_keep_alive() const {
    return http_should_keep_alive(&hp_);
}

inline void http_parser::clear_should_keep_alive() {
    hp_.flags = (hp_.flags & ~F_CONNECTION_KEEP_ALIVE) | F_CONNECTION_CLOSE;
}

} // namespace tamer
#endif
<commit_msg>Add http_message::append_body.<commit_after>#ifndef TAMER_HTTP_HH
#define TAMER_HTTP_HH 1
#include "fd.hh"
#include "http_parser.h"
#include <vector>
#include <string>
#include <sstream>
#include <memory>
#include <unordered_map>
#include <time.h>
namespace tamer {
class http_parser;

struct http_header {
    std::string name;
    std::string value;
    inline http_header(std::string n, std::string v)
        : name(TAMER_MOVE(n)), value(TAMER_MOVE(v)) {
    }
    inline bool is(const char* s, size_t len) const {
        return name.length() == len && memcmp(name.data(), s, len) == 0;
    }
    inline bool is(const std::string& s) const {
        return is(s.data(), s.length());
    }
    inline bool is_canonical(const char* s, size_t len) const {
        if (name.length() != len)
            return false;
        const char* names = name.data();
        const char* end = s + len;
        for (; s != end; ++s, ++names)
            if (*s != *names
                && (*names < 'A' || *names > 'Z' || (*names - 'A' + 'a') != *s))
                return false;
        return true;
    }
    inline bool is_canonical(const std::string& s) const {
        return is_canonical(s.data(), s.length());
    }
    inline bool is_content_length() const {
        return is_canonical("content-length", 14);
    }
};

class http_message {
  public:
    typedef std::vector<http_header>::const_iterator header_iterator;

    inline http_message();

    inline bool ok() const;
    inline bool operator!() const;
    inline enum http_errno error() const;

    inline unsigned http_major() const;
    inline unsigned http_minor() const;

    inline unsigned status_code() const;
    inline const std::string& status_message() const;
    inline enum http_method method() const;
    inline const std::string& url() const;
    header_iterator find_canonical_header(const std::string& name) const;
    inline header_iterator find_header(const std::string& name) const;
    inline bool has_canonical_header(const std::string& name) const;
    inline bool has_header(const std::string& name) const;
    inline const std::string& body() const;

    std::string host() const;
    inline std::string url_schema() const;
    inline std::string url_host() const;
    std::string url_host_port() const;
    inline std::string url_path() const;
    inline bool has_query() const;
    inline std::string query() const;
    bool has_query(const std::string& name) const;
    std::string query(const std::string& name) const;

    inline header_iterator header_begin() const;
    inline header_iterator header_end() const;
    inline header_iterator query_begin() const;
    inline header_iterator query_end() const;

    inline http_message& clear();
    void add_header(std::string key, std::string value);

    inline http_message& http_major(unsigned v);
    inline http_message& http_minor(unsigned v);
    inline http_message& error(enum http_errno e);
    inline http_message& status_code(unsigned code);
    inline http_message& status_code(unsigned code, std::string message);
    inline http_message& method(enum http_method method);
    inline http_message& url(std::string url);
    inline http_message& header(std::string key, std::string value);
    inline http_message& header(std::string key, size_t value);
    inline http_message& date_header(std::string key, time_t value);
    inline http_message& body(std::string body);
    inline http_message& append_body(const std::string& x);

    static std::string canonicalize(std::string x);
    static const char* default_status_message(unsigned code);

  private:
    enum {
        info_url = 1, info_query = 2
    };

    struct info_type {
        unsigned flags;
        struct http_parser_url urlp;
        std::vector<http_header> raw_query;
        inline info_type()
            : flags(0) {
        }
    };

    unsigned short major_;
    unsigned short minor_;
    unsigned status_code_ : 16;
    unsigned method_ : 8;
    unsigned error_ : 7;
    unsigned upgrade_ : 1;

    std::string url_;
    std::string status_message_;
    std::vector<http_header> raw_headers_;
    std::string body_;

    mutable std::shared_ptr<info_type> info_;

    inline void kill_info(unsigned f) const;
    inline info_type& info(unsigned f) const;
    void make_info(unsigned f) const;
    inline bool has_url_field(int field) const;
    inline std::string url_field(int field) const;
    void do_clear();
    friend class http_parser;
};

class http_parser : public tamed_class {
  public:
    http_parser(enum http_parser_type type);

    void clear();
    inline bool ok() const;
    inline enum http_errno error() const;
    inline bool should_keep_alive() const;

    void receive(fd f, event<http_message> done);
    void send(fd f, const http_message& m, event<> done);
    static void send_request(fd f, const http_message& m, event<> done);
    static void send_response(fd f, const http_message& m, event<> done);
    static void send_response_headers(fd f, const http_message& m, event<> done);
    static void send_response_chunk(fd f, std::string s, event<> done);
    static void send_response_end(fd f, event<> done);

    inline void clear_should_keep_alive();

  private:
    ::http_parser hp_;

    struct message_data {
        http_message hm;
        std::string key;
        std::ostringstream sbuf;
        bool done;
    };

    static const http_parser_settings settings;
    static http_parser* get_parser(::http_parser* hp);
    static message_data* get_message_data(::http_parser* hp);
    static int on_message_begin(::http_parser* hp);
    static int on_url(::http_parser* hp, const char* s, size_t len);
    static int on_status(::http_parser* hp, const char* s, size_t len);
    static int on_header_field(::http_parser* hp, const char* s, size_t len);
    static int on_header_value(::http_parser* hp, const char* s, size_t len);
    static int on_headers_complete(::http_parser* hp);
    static int on_body(::http_parser* hp, const char* s, size_t len);
    static int on_message_complete(::http_parser* hp);
    inline void copy_parser_status(message_data& md);
    static void unparse_request_headers(std::ostringstream& buf,
                                        const http_message& m);
    static void unparse_response_headers(std::ostringstream& buf,
                                         const http_message& m,
                                         bool include_content_length);

    class closure__receive__2fdQ12http_message_; void receive(closure__receive__2fdQ12http_message_&);
    class closure__send_request__2fdRK12http_messageQ_; static void send_request(closure__send_request__2fdRK12http_messageQ_&);
    class closure__send_response__2fdRK12http_messageQ_; static void send_response(closure__send_response__2fdRK12http_messageQ_&);
    class closure__send_response_chunk__2fdSsQ_; static void send_response_chunk(closure__send_response_chunk__2fdSsQ_&);
};

inline http_message::http_message()
    : major_(1), minor_(1), status_code_(200), method_(HTTP_GET),
      error_(HPE_OK), upgrade_(0) {
}

inline void http_message::kill_info(unsigned f) const {
    if (info_)
        info_->flags &= ~f;
}

inline unsigned http_message::http_major() const {
    return major_;
}

inline unsigned http_message::http_minor() const {
    return minor_;
}

inline bool http_message::ok() const {
    return error_ == HPE_OK;
}

inline bool http_message::operator!() const {
    return !ok();
}

inline enum http_errno http_message::error() const {
    return (enum http_errno) error_;
}

inline unsigned http_message::status_code() const {
    return status_code_;
}

inline const std::string& http_message::status_message() const {
    return status_message_;
}

inline enum http_method http_message::method() const {
    return (enum http_method) method_;
}

inline const std::string& http_message::url() const {
    return url_;
}

inline http_message::header_iterator http_message::find_header(const std::string& key) const {
    return find_canonical_header(canonicalize(key));
}

inline bool http_message::has_canonical_header(const std::string& key) const {
    return find_canonical_header(key) != header_end();
}

inline bool http_message::has_header(const std::string& key) const {
    return has_canonical_header(canonicalize(key));
}

inline const std::string& http_message::body() const {
    return body_;
}

inline bool http_message::has_url_field(int field) const {
    return info(info_url).urlp.field_set & (1 << field);
}

inline std::string http_message::url_field(int field) const {
    const info_type& i = info(info_url);
    if (i.urlp.field_set & (1 << field))
        return url_.substr(i.urlp.field_data[field].off,
                           i.urlp.field_data[field].len);
    else
        return std::string();
}

inline bool http_message::has_query() const {
    return has_url_field(UF_QUERY);
}

inline std::string http_message::query() const {
    return url_field(UF_QUERY);
}

inline std::string http_message::url_schema() const {
    return url_field(UF_SCHEMA);
}

inline std::string http_message::url_host() const {
    return url_field(UF_HOST);
}

inline std::string http_message::url_path() const {
    return url_field(UF_PATH);
}

inline http_message& http_message::http_major(unsigned v) {
    major_ = v;
    return *this;
}

inline http_message& http_message::http_minor(unsigned v) {
    minor_ = v;
    return *this;
}

inline http_message& http_message::clear() {
    do_clear();
    return *this;
}

inline http_message& http_message::error(enum http_errno e) {
    error_ = e;
    return *this;
}

inline http_message& http_message::status_code(unsigned code) {
    status_code_ = code;
    status_message_ = std::string();
    return *this;
}

inline http_message& http_message::status_code(unsigned code, std::string message) {
    status_code_ = code;
    status_message_ = TAMER_MOVE(message);
    return *this;
}

inline http_message& http_message::method(enum http_method method) {
    method_ = (unsigned) method;
    return *this;
}

inline http_message& http_message::url(std::string url) {
    url_ = TAMER_MOVE(url);
    kill_info(info_url | info_query);
    return *this;
}

inline http_message& http_message::header(std::string key, std::string value) {
    add_header(TAMER_MOVE(key), TAMER_MOVE(value));
    return *this;
}

inline http_message& http_message::header(std::string key, size_t value) {
    std::ostringstream buf;
    buf << value;
    add_header(TAMER_MOVE(key), buf.str());
    return *this;
}

inline http_message& http_message::date_header(std::string key, time_t value) {
    char buf[128];
    // XXX current locale
    strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&value));
    add_header(TAMER_MOVE(key), std::string(buf));
    return *this;
}

inline http_message& http_message::body(std::string body) {
    body_ = TAMER_MOVE(body);
    return *this;
}

inline http_message& http_message::append_body(const std::string& x) {
    body_ += x;
    return *this;
}

inline http_message::info_type& http_message::info(unsigned f) const {
    if (!info_ || !info_.unique() || (info_->flags & f) != f)
        make_info(f);
    return *info_.get();
}

inline http_message::header_iterator http_message::header_begin() const {
    return raw_headers_.begin();
}

inline http_message::header_iterator http_message::header_end() const {
    return raw_headers_.end();
}

inline http_message::header_iterator http_message::query_begin() const {
    return info(info_query).raw_query.begin();
}

inline http_message::header_iterator http_message::query_end() const {
    return info(info_query).raw_query.end();
}

inline bool http_parser::ok() const {
    return hp_.http_errno == (unsigned) HPE_OK;
}

inline enum http_errno http_parser::error() const {
    return (enum http_errno) hp_.http_errno;
}

inline bool http_parser::should_keep_alive() const {
    return http_should_keep_alive(&hp_);
}

inline void http_parser::clear_should_keep_alive() {
    hp_.flags = (hp_.flags & ~F_CONNECTION_KEEP_ALIVE) | F_CONNECTION_CLOSE;
}

} // namespace tamer
#endif
<|endoftext|>


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

#include <inviwo/qt/widgets/properties/ordinalpropertywidgetqt.h>

namespace inviwo {

BaseOrdinalPropertyWidgetQt::BaseOrdinalPropertyWidgetQt(Property* property)
    : PropertyWidgetQt(property), settingsWidget_(nullptr), contextMenu_(nullptr) {}

BaseOrdinalPropertyWidgetQt::~BaseOrdinalPropertyWidgetQt() {
    if (settingsWidget_) {
        settingsWidget_->hide();
        property_->deregisterWidget(settingsWidget_);
        delete settingsWidget_;
    }
}

void BaseOrdinalPropertyWidgetQt::generateWidget() {
    signalMapperSetPropertyValue_ = new QSignalMapper(this);
    signalMapperContextMenu_ = new QSignalMapper(this);

    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setContentsMargins(0,0,0,0);
    hLayout->setSpacing(7);
    setLayout(hLayout);

    label_ = new EditableLabelQt(this, property_->getDisplayName());
    hLayout->addWidget(label_);
    connect(label_, SIGNAL(textChanged()),this, SLOT(setPropertyDisplayName()));

    QWidget* sliderWidget = new QWidget();

    sliderWidgets_ = makeSliders(sliderWidget);

    for(size_t i = 0; i < sliderWidgets_.size(); i++) {
        sliderWidgets_[i]->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(sliderWidgets_[i],
                SIGNAL(customContextMenuRequested(const QPoint&)),
                signalMapperContextMenu_,
                SLOT(map()));

        connect(sliderWidgets_[i],
                SIGNAL(valueChanged()),
                signalMapperSetPropertyValue_,
                SLOT(map()));

        signalMapperContextMenu_->setMapping(sliderWidgets_[i], static_cast<int>(i));
        signalMapperSetPropertyValue_->setMapping(sliderWidgets_[i], static_cast<int>(i));
    }

    hLayout->addWidget(sliderWidget);

    sliderWidget->setMinimumHeight(sliderWidget->sizeHint().height());
    QSizePolicy sp = sliderWidget->sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    sliderWidget->setSizePolicy(sp);

    connect(signalMapperContextMenu_,
            SIGNAL(mapped(int)),
            this,
            SLOT(showContextMenuSlider(int)));

    connect(signalMapperSetPropertyValue_,
            SIGNAL(mapped(int)),
            this,
            SLOT(setPropertyValue(int)));

    this->setEnabled(!property_->getReadOnly());

    setFixedHeight(sizeHint().height());
    sp = sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    setSizePolicy(sp);
}

void BaseOrdinalPropertyWidgetQt::generatesSettingsWidget() {

    settingsAction_ = new QAction(tr("&Property settings..."), this);
    settingsAction_->setToolTip(tr("&Open the property settings dialog to adjust min, max, and increment values"));
    minAction_ = new QAction(tr("&Set as Min"), this);
    minAction_->setToolTip(tr("&Use the current value as the min value for the property"));
    maxAction_ = new QAction(tr("&Set as Max"), this);
    maxAction_->setToolTip(tr("&Use the current value as the max value for the property"));

    connect(settingsAction_,
            SIGNAL(triggered()),
            this,
            SLOT(showSettings()));

    connect(minAction_,
            SIGNAL(triggered()),
            this,
            SLOT(setAsMin()));

    connect(maxAction_,
            SIGNAL(triggered()),
            this,
            SLOT(setAsMax()));

    contextMenu_ = new QMenu();
    contextMenu_->addActions(PropertyWidgetQt::getContextMenu()->actions());
    contextMenu_->addAction(settingsAction_);
    contextMenu_->addAction(minAction_);
    contextMenu_->addAction(maxAction_);
    minAction_->setVisible(false);
    maxAction_->setVisible(false);
}

QMenu* BaseOrdinalPropertyWidgetQt::getContextMenu() {
    if (!contextMenu_) {
        generatesSettingsWidget();
    }
    return contextMenu_;
}

/****************************************************************************/
// Slots:

void BaseOrdinalPropertyWidgetQt::showContextMenu(const QPoint& pos) {
    showContextMenuSlider(-1);
}

// Connected to label_ textChanged
void BaseOrdinalPropertyWidgetQt::setPropertyDisplayName() {
    property_->setDisplayName(label_->getText());
}

// connected to sliderWidget_ customContextMenuRequested
void BaseOrdinalPropertyWidgetQt::showContextMenuSlider(int sliderId) {
    sliderId_ = sliderId;

    if (!contextMenu_) {
        generatesSettingsWidget();
    }

    PropertyWidgetQt::updateContextMenu();
    UsageMode appVisibilityMode = getApplicationUsageMode();

    if (appVisibilityMode == DEVELOPMENT) {
        settingsAction_->setVisible(true);
    } else {
        settingsAction_->setVisible(false);
    }

    if (appVisibilityMode == DEVELOPMENT && sliderId_ >= 0) {
        minAction_->setVisible(true);
        maxAction_->setVisible(true);
    } else {
        minAction_->setVisible(false);
        maxAction_->setVisible(false);
    }

    if (property_->getReadOnly()) {
        settingsAction_->setEnabled(false);
        minAction_->setEnabled(false);
        maxAction_->setEnabled(false);
    } else {
        settingsAction_->setEnabled(true);
        minAction_->setEnabled(true);
        maxAction_->setEnabled(true);
    }
    contextMenu_->exec(QCursor::pos());

    minAction_->setVisible(false);
    maxAction_->setVisible(false);
}

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

#include <inviwo/qt/widgets/properties/ordinalpropertywidgetqt.h>

namespace inviwo {

BaseOrdinalPropertyWidgetQt::BaseOrdinalPropertyWidgetQt(Property* property)
    : PropertyWidgetQt(property), settingsWidget_(nullptr), contextMenu_(nullptr) {}

BaseOrdinalPropertyWidgetQt::~BaseOrdinalPropertyWidgetQt() {
    if (settingsWidget_) {
        settingsWidget_->hide();
        property_->deregisterWidget(settingsWidget_);
        delete settingsWidget_;
    }
}

void BaseOrdinalPropertyWidgetQt::generateWidget() {
    signalMapperSetPropertyValue_ = new QSignalMapper(this);
    signalMapperContextMenu_ = new QSignalMapper(this);

    QHBoxLayout* hLayout = new QHBoxLayout();
    hLayout->setContentsMargins(0,0,0,0);
    hLayout->setSpacing(7);
    setLayout(hLayout);

    label_ = new EditableLabelQt(this, property_->getDisplayName());
    hLayout->addWidget(label_);
    connect(label_, SIGNAL(textChanged()),this, SLOT(setPropertyDisplayName()));

    QWidget* sliderWidget = new QWidget();

    sliderWidgets_ = makeSliders(sliderWidget);

    for(size_t i = 0; i < sliderWidgets_.size(); i++) {
        sliderWidgets_[i]->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(sliderWidgets_[i],
                SIGNAL(customContextMenuRequested(const QPoint&)),
                signalMapperContextMenu_,
                SLOT(map()));

        connect(sliderWidgets_[i],
                SIGNAL(valueChanged()),
                signalMapperSetPropertyValue_,
                SLOT(map()));

        signalMapperContextMenu_->setMapping(sliderWidgets_[i], static_cast<int>(i));
        signalMapperSetPropertyValue_->setMapping(sliderWidgets_[i], static_cast<int>(i));
    }

    hLayout->addWidget(sliderWidget);

    sliderWidget->setMinimumHeight(sliderWidget->sizeHint().height());
    QSizePolicy sp = sliderWidget->sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    sliderWidget->setSizePolicy(sp);

    connect(signalMapperContextMenu_,
            SIGNAL(mapped(int)),
            this,
            SLOT(showContextMenuSlider(int)));

    connect(signalMapperSetPropertyValue_,
            SIGNAL(mapped(int)),
            this,
            SLOT(setPropertyValue(int)));

    this->setEnabled(!property_->getReadOnly());

    setFixedHeight(sizeHint().height());
    sp = sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    setSizePolicy(sp);
}

void BaseOrdinalPropertyWidgetQt::generatesSettingsWidget() {

    settingsAction_ = new QAction(tr("&Property settings..."), this);
    settingsAction_->setToolTip(tr("&Open the property settings dialog to adjust min, max, and increment values"));
    minAction_ = new QAction(tr("&Set as Min"), this);
    minAction_->setToolTip(tr("&Use the current value as the min value for the property"));
    maxAction_ = new QAction(tr("&Set as Max"), this);
    maxAction_->setToolTip(tr("&Use the current value as the max value for the property"));

    connect(settingsAction_,
            SIGNAL(triggered()),
            this,
            SLOT(showSettings()));

    connect(minAction_,
            SIGNAL(triggered()),
            this,
            SLOT(setAsMin()));

    connect(maxAction_,
            SIGNAL(triggered()),
            this,
            SLOT(setAsMax()));

    contextMenu_ = new QMenu(this);
    contextMenu_->addActions(PropertyWidgetQt::getContextMenu()->actions());
    contextMenu_->addAction(settingsAction_);
    contextMenu_->addAction(minAction_);
    contextMenu_->addAction(maxAction_);
    minAction_->setVisible(false);
    maxAction_->setVisible(false);
}

QMenu* BaseOrdinalPropertyWidgetQt::getContextMenu() {
    if (!contextMenu_) {
        generatesSettingsWidget();
    }
    return contextMenu_;
}

/****************************************************************************/
// Slots:

void BaseOrdinalPropertyWidgetQt::showContextMenu(const QPoint& pos) {
    showContextMenuSlider(-1);
}

// Connected to label_ textChanged
void BaseOrdinalPropertyWidgetQt::setPropertyDisplayName() {
    property_->setDisplayName(label_->getText());
}

// connected to sliderWidget_ customContextMenuRequested
void BaseOrdinalPropertyWidgetQt::showContextMenuSlider(int sliderId) {
    sliderId_ = sliderId;

    if (!contextMenu_) {
        generatesSettingsWidget();
    }

    PropertyWidgetQt::updateContextMenu();
    UsageMode appVisibilityMode = getApplicationUsageMode();

    if (appVisibilityMode == DEVELOPMENT) {
        settingsAction_->setVisible(true);
    } else {
        settingsAction_->setVisible(false);
    }

    if (appVisibilityMode == DEVELOPMENT && sliderId_ >= 0) {
        minAction_->setVisible(true);
        maxAction_->setVisible(true);
    } else {
        minAction_->setVisible(false);
        maxAction_->setVisible(false);
    }

    if (property_->getReadOnly()) {
        settingsAction_->setEnabled(false);
        minAction_->setEnabled(false);
        maxAction_->setEnabled(false);
    } else {
        settingsAction_->setEnabled(true);
        minAction_->setEnabled(true);
        maxAction_->setEnabled(true);
    }
    contextMenu_->exec(QCursor::pos());

    minAction_->setVisible(false);
    maxAction_->setVisible(false);
}

} // namespace
<|endoftext|>


<commit_before>#include "core.h"
#include "move.h"
#include "multipole.h"
#include "mpi.h"
#include "docopt.h"
#include <cstdlib>
#include "ProgressBar.hpp"

using namespace Faunus;
using namespace std;

typedef Geometry::Cuboid Tgeometry;
typedef Particle<Charge> Tparticle;

static const char USAGE[] =
R"(Hoth - the Monte Carlo code you're looking for!

    http://github.com/mlund/faunus

    Usage:
      faunus [-q] [--nobar] [--input=<file>] [--output=<file>]
      faunus (-h | --help)
      faunus --version

    Options:

      -i <file> --input <file>   Input file [default: /dev/stdin].
      -o <file> --output <file>  Output file [default: out.json].
      --nobar                    No progress bar.
      -q --quiet                 Less verbose output.
      -h --help                  Show this screen.
      --version                  Show version.
)";

int main( int argc, char **argv )
{
    Faunus::MPI::MPIController mpi; // OK also if MPI is unavailable

    try {
        auto args = docopt::docopt( USAGE,
                { argv + 1, argv + argc }, true, "Faunus 2.0.0");

        bool showProgress = !args["--nobar"].asBool();

        bool quiet = args["--quiet"].asBool();
        if (quiet) {
            cout.setstate( std::ios_base::failbit ); // hold kæft!
            showProgress = false;
        }

        json j;
        auto inputFile = args["--input"].asString();
        if (inputFile=="/dev/stdin")
            std::cin >> j;
        else
            j = openjson(mpi.prefix + inputFile);

        pc::temperature = j.at("temperature").get<double>() * 1.0_K;
        MCSimulation<Tgeometry,Tparticle> sim(j);
        Analysis::CombinedAnalysis analysis(j, sim.space(), sim.pot());

        auto& loop = j.at("mcloop");
        int macro = loop.at("macro");
        int micro = loop.at("micro");

        ProgressBar progressBar(macro*micro, 70);
        for (int i=0; i<macro; i++) {
            for (int j=0; j<micro; j++) {

                if (showProgress && mpi.isMaster()) {
                    ++progressBar;
                    if (j % 10 == 0)
                        progressBar.display();
                }

                sim.move();
                analysis.sample();
            }
        }
        progressBar.done();

        if (!quiet) {
            mpi.cout << "relative drift = " << sim.drift() << endl;
            mpi.cout << json(mpi) << endl;
        }

        std::ofstream f(mpi.prefix + args["--output"].asString());
        if (f) {
            json j = sim;
            j["analysis"] = analysis;
            f << std::setw(4) << j << endl;
        }

    } catch (std::exception &e) {
        std::cerr << e.what() << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<commit_msg>update<commit_after>#include "core.h"
#include "move.h"
#include "multipole.h"
#include "mpi.h"
#include "docopt.h"
#include <cstdlib>
#include "ProgressBar.hpp"

using namespace Faunus;
using namespace std;

typedef Geometry::Cuboid Tgeometry;
typedef Particle<Charge> Tparticle;

static const char USAGE[] =
R"(Hoth - the Monte Carlo game you're looking for!

    http://github.com/mlund/faunus

    Usage:
      faunus [-q] [--nobar] [--input=<file>] [--output=<file>]
      faunus (-h | --help)
      faunus --version

    Options:

      -i <file> --input <file>   Input file [default: /dev/stdin].
      -o <file> --output <file>  Output file [default: out.json].
      --nobar                    No progress bar.
      -q --quiet                 Less verbose output.
      -h --help                  Show this screen.
      --version                  Show version.
)";

int main( int argc, char **argv )
{
    Faunus::MPI::MPIController mpi; // OK also if MPI is unavailable

    try {
        auto args = docopt::docopt( USAGE,
                { argv + 1, argv + argc }, true, "Faunus 2.0.0");

        bool showProgress = !args["--nobar"].asBool();

        bool quiet = args["--quiet"].asBool();
        if (quiet) {
            cout.setstate( std::ios_base::failbit ); // hold kæft
            showProgress = false;
        }

        json j;
        auto input = args["--input"].asString();
        if (input=="/dev/stdin")
            std::cin >> j;
        else
            j = openjson(mpi.prefix + input);

        pc::temperature = j.at("temperature").get<double>() * 1.0_K;
        MCSimulation<Tgeometry,Tparticle> sim(j);
        Analysis::CombinedAnalysis analysis(j, sim.space(), sim.pot());

        auto& loop = j.at("mcloop");
        int macro = loop.at("macro");
        int micro = loop.at("micro");

        ProgressBar progressBar(macro*micro, 70);
        for (int i=0; i<macro; i++) {
            for (int j=0; j<micro; j++) {

                if (showProgress && mpi.isMaster()) {
                    ++progressBar;
                    if (j % 10 == 0)
                        progressBar.display();
                }

                sim.move();
                analysis.sample();
            }
        }
        progressBar.done();

        if (!quiet)
            mpi.cout << "relative drift = " << sim.drift() << endl;

        std::ofstream f(mpi.prefix + args["--output"].asString());
        if (f) {
            json j = sim;
            j["analysis"] = analysis;
            if (mpi.nproc()>1)
                j["mpi"] = mpi;
            f << std::setw(4) << j << endl;
        }

    } catch (std::exception &e) {
        std::cerr << e.what() << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// MSVC no, I do not want to use localtime_s
#define _CRT_SECURE_NO_WARNINGS

#include "benchmark.hpp"

#include "asg_benchmark.hpp"
#include "bs1_benchmark.hpp"
#include "bs2_benchmark.hpp"
#include "evf_benchmark.hpp"
#include "evl_benchmark.hpp"
#include "evs_benchmark.hpp"
#include "jls_benchmark.hpp"
#include "nss_benchmark.hpp"
#include "psg_benchmark.hpp"
#include "sss_benchmark.hpp"
#include "wsg_benchmark.hpp"

#include "lib/jl_signal/Signal.h"
#include "lib/jl_signal/StaticSignalConnectionAllocators.h"

#include <iostream>
#include <fstream>
#include <iomanip>
#include <numeric>
//#include <sstream>
//#include <vector>
#include <map>

const char* construction = "construct";
const char* destruction = "destruct";
const char* connection = "connect";
const char* emission = "emission";
const char* combined = "combined";

using ImmediateResults = std::map<const char*, std::vector<double>>;
using RelativeResults = std::map<const char*, double>;
using ImmediateData = std::map<const char*, ImmediateResults>;
using RelativeData = std::map<const char*, RelativeResults>;

//std::size_t g_limit = Timer_u(Limit_u(4)).count();
std::size_t g_limit = 100000;

void outputReports(ImmediateData const&);
template <typename T> void outputReportTxt(ImmediateData const&, T&);
template <typename T> void outputReportCsv(ImmediateData const&, T&);

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

int main(int argc, char* argv[])
{
    using namespace Benchmark;

    jl::StaticSignalConnectionAllocator<c_jlsignal_max> signal_con_allocator;
    jl::StaticObserverConnectionAllocator<c_jlsignal_max> observer_con_allocator;
    jl::SignalBase::SetCommonConnectionAllocator(&signal_con_allocator);
    jl::SignalObserver::SetCommonConnectionAllocator(&observer_con_allocator);

    ImmediateData records;

    std::size_t start_n = round_2_down(8);
    std::size_t maximum_n = round_2_up(64);

    std::cout << "Set CPU Priority: [paused]" << std::endl;
    std::cin.get();

    for(std::size_t N = start_n; N <= maximum_n; N *= 2)
    {
        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& wsg = records["winglot Signals"];
        wsg[construction].emplace_back(Wsg::construction(N));
        wsg[destruction].emplace_back(Wsg::destruction(N));
        wsg[connection].emplace_back(Wsg::connection(N));
        wsg[emission].emplace_back(Wsg::emission(N));
        wsg[combined].emplace_back(Wsg::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& sss = records["supergrover sigslot"];
        sss[construction].emplace_back(Sss::construction(N));
        sss[destruction].emplace_back(Sss::destruction(N));
        sss[connection].emplace_back(Sss::connection(N));
        sss[emission].emplace_back(Sss::emission(N));
        sss[combined].emplace_back(Sss::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& psg = records["pbhogan Signals"];
        psg[construction].emplace_back(Psg::construction(N));
        psg[destruction].emplace_back(Psg::destruction(N));
        psg[connection].emplace_back(Psg::connection(N));
        psg[emission].emplace_back(Psg::emission(N));
        psg[combined].emplace_back(Psg::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& jls = records["Jl_signal"];
        jls[construction].emplace_back(Jls::construction(N));
        jls[destruction].emplace_back(Jls::destruction(N));
        jls[connection].emplace_back(Jls::connection(N));
        jls[emission].emplace_back(Jls::emission(N));
        jls[combined].emplace_back(Jls::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& nss = records["Nano-signal-slot"];
        nss[construction].emplace_back(Nss::construction(N));
        nss[destruction].emplace_back(Nss::destruction(N));
        nss[connection].emplace_back(Nss::connection(N));
        nss[emission].emplace_back(Nss::emission(N));
        nss[combined].emplace_back(Nss::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& bs1 = records["Boost Signals"];
        bs1[construction].emplace_back(Bs1::construction(N));
        bs1[destruction].emplace_back(Bs1::destruction(N));
        bs1[connection].emplace_back(Bs1::connection(N));
        bs1[emission].emplace_back(Bs1::emission(N));
        bs1[combined].emplace_back(Bs1::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& bs2 = records["Boost Signals2"];
        bs2[construction].emplace_back(Bs2::construction(N));
        bs2[destruction].emplace_back(Bs2::destruction(N));
        bs2[connection].emplace_back(Bs2::connection(N));
        bs2[emission].emplace_back(Bs2::emission(N));
        bs2[combined].emplace_back(Bs2::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& evl = records["EvilTwin Observer"];
        evl[construction].emplace_back(Evl::construction(N));
        evl[destruction].emplace_back(Evl::destruction(N));
        evl[connection].emplace_back(Evl::connection(N));
        evl[emission].emplace_back(Evl::emission(N));
        evl[combined].emplace_back(Evl::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& evf = records["EvilTwin Obs Fork"];
        evf[construction].emplace_back(Evf::construction(N));
        evf[destruction].emplace_back(Evf::destruction(N));
        evf[connection].emplace_back(Evf::connection(N));
        evf[emission].emplace_back(Evf::emission(N));
        evf[combined].emplace_back(Evf::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& evs = records["EvilTwin Obs Safe"];
        evs[construction].emplace_back(Evs::construction(N));
        evs[destruction].emplace_back(Evs::destruction(N));
        evs[connection].emplace_back(Evs::connection(N));
        evs[emission].emplace_back(Evs::emission(N));
        evs[combined].emplace_back(Evs::combined(N));

        std::cout << "size: " << N << ", line: " << __LINE__ << std::endl;

        auto& s11 = records["amc522 Signal11"];
        s11[construction].emplace_back(Asg::construction(N));
        s11[destruction].emplace_back(Asg::destruction(N));
        s11[connection].emplace_back(Asg::connection(N));
        s11[emission].emplace_back(Asg::emission(N));
        s11[combined].emplace_back(Asg::combined(N));
    }
    outputReports(records);

    std::size_t numImplementations = records.size();
    std::size_t numOperations = records.begin()->second.size();
    std::size_t numSamples = records.begin()->second.begin()->second.size();
    std::size_t numBenchmarks = numImplementations * numOperations * numSamples;

    std::cout << "\n" << numBenchmarks << " Benchmarks Completed: [paused]" << std::endl;
    std::cin.get();
}

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

void outputReports(ImmediateData const& records)
{
    if (std::ofstream ofs { "report.txt", std::ios::app })
    {
        auto tee = std::tie(std::cout, ofs);

        auto now = std::chrono::system_clock::now();
        auto now_c = std::chrono::system_clock::to_time_t(now);
        tee << std::put_time(std::localtime(&now_c), "%c") << '\n';

        outputReportTxt(records, tee);

        ofs << "\n//--------------------------------------"
            << "----------------------------------------\n" << std::endl;
    }
    else
    {
        std::cerr << "Unable to append report.txt: [error]" << std::endl;
    }
    if (std::ofstream ofs { "report.csv" })
    {
        outputReportCsv(records, ofs);
    }
    else
    {
        std::cerr << "Unable to create report.csv: [error]" << std::endl;
    }
}

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

template <typename T>
void outputReportTxt(ImmediateData const& records, T& ost)
{
    using namespace std;

    for(auto const& table : records)
    {
        auto const& tableName = table.first;

        ost << "\n    " << tableName << ":";

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& data = record.second;

            double avg = accumulate(begin(data),
                end(data), 1.0) / (double) data.size();

            ost << "\n ++ " << setw(40) << setfill('_')
                << recordName << ": " << setprecision(2) << fixed << avg;
        }
        ost << "\n";
    }
}

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

template <typename T>
void outputReportCsv(ImmediateData const& records, T& ost)
{
    using namespace std;

    ost << "Library," << construction << "," << destruction << ","
        << connection << "," << emission << "," << combined << endl;

    for(auto const& table : records)
    {
        ost << table.first;

        for(auto const& record : table.second)
        {
            auto const& data = record.second;

            double avg = accumulate(begin(data),
                end(data), 1.0) / (double) data.size();

            ost << "," << setprecision(2) << fixed << avg;
        }
        ost << endl;
    }
}

//-------------------------------------------------------------CAUTION YOUR EYES

/*
template <typename T>
void outputReportNew(ImmediateData const& records, T& ost)
{
    RelativeResults maxAverage;
    RelativeData averages;

    const std::size_t maxOutputLength = 80;
    std::size_t maxNameLength = 0;

    std::map<std::string, std::size_t> maxColumnLength;

    for(auto const& table : records)
    {
        auto const& tableName = table.first;

        maxNameLength = std::max(maxNameLength, tableName.size() + 2);

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& data = record.second;

            double avg = std::accumulate(std::begin(data),
                std::end(data), 1.0) / (double) data.size();

            averages[tableName][recordName] = avg;

            maxAverage[recordName] = std::max(maxAverage[recordName], avg);

            std::stringstream sts;
            sts << std::setprecision(2) << std::fixed << avg;
            maxColumnLength[recordName] = std::max(maxColumnLength[recordName], sts.str().size() + 2);
        }
    }

    for(auto const& table : averages)
    {
        auto const& tableName = table.first;

        ost << "+" << std::string(maxNameLength, '-') << "+\n|";

        std::size_t currentNameLength = tableName.size();
        std::size_t namePaddingLength = maxNameLength / currentNameLength;
        bool extraSpace = (namePaddingLength * currentNameLength == maxNameLength);
        std::string namePadding(namePaddingLength, ' ');

        ost << namePadding << tableName << namePadding + (extraSpace ? " |" : "|");

        std::vector<double> dt;

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& average = record.second;

            dt.emplace_back((average / maxAverage[recordName]) * 100.0);

            std::size_t columnLength = maxColumnLength[recordName];
            std::size_t valuePaddingLength = columnLength / recordName.size();

        }
    }
}
*/
<commit_msg>minor output change<commit_after>// MSVC no, I do not want to use localtime_s
#define _CRT_SECURE_NO_WARNINGS

#include "benchmark.hpp"

#include "asg_benchmark.hpp"
#include "bs1_benchmark.hpp"
#include "bs2_benchmark.hpp"
#include "evf_benchmark.hpp"
#include "evl_benchmark.hpp"
#include "evs_benchmark.hpp"
#include "jls_benchmark.hpp"
#include "nss_benchmark.hpp"
#include "psg_benchmark.hpp"
#include "sss_benchmark.hpp"
#include "wsg_benchmark.hpp"

#include "lib/jl_signal/Signal.h"
#include "lib/jl_signal/StaticSignalConnectionAllocators.h"

#include <iostream>
#include <fstream>
#include <iomanip>
#include <numeric>
//#include <sstream>
//#include <vector>
#include <map>

const char* construction = "construct";
const char* destruction = "destruct";
const char* connection = "connect";
const char* emission = "emission";
const char* combined = "combined";

using ImmediateResults = std::map<const char*, std::vector<double>>;
using RelativeResults = std::map<const char*, double>;
using ImmediateData = std::map<const char*, ImmediateResults>;
using RelativeData = std::map<const char*, RelativeResults>;

//std::size_t g_limit = Timer_u(Limit_u(4)).count();
std::size_t g_limit = 10000000;

void outputReports(ImmediateData const&);
template <typename T> void outputReportTxt(ImmediateData const&, T&);
template <typename T> void outputReportCsv(ImmediateData const&, T&);

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

int main(int argc, char* argv[])
{
    using namespace Benchmark;

    jl::StaticSignalConnectionAllocator<c_jlsignal_max> signal_con_allocator;
    jl::StaticObserverConnectionAllocator<c_jlsignal_max> observer_con_allocator;
    jl::SignalBase::SetCommonConnectionAllocator(&signal_con_allocator);
    jl::SignalObserver::SetCommonConnectionAllocator(&observer_con_allocator);

    ImmediateData records;

    std::size_t start_n = round_2_down(8);
    std::size_t maximum_n = round_2_up(64);

    std::cout << "Set CPU Priority: [paused]" << std::endl;
    std::cin.get();

    for(std::size_t N = start_n; N <= maximum_n; N *= 2)
    {
        std::cout << "[Test Size: " << N << "] BEGIN\n" << std::endl;

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& wsg = records["winglot Signals"];
        wsg[construction].emplace_back(Wsg::construction(N));
        wsg[destruction].emplace_back(Wsg::destruction(N));
        wsg[connection].emplace_back(Wsg::connection(N));
        wsg[emission].emplace_back(Wsg::emission(N));
        wsg[combined].emplace_back(Wsg::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& sss = records["supergrover sigslot"];
        sss[construction].emplace_back(Sss::construction(N));
        sss[destruction].emplace_back(Sss::destruction(N));
        sss[connection].emplace_back(Sss::connection(N));
        sss[emission].emplace_back(Sss::emission(N));
        sss[combined].emplace_back(Sss::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& psg = records["pbhogan Signals"];
        psg[construction].emplace_back(Psg::construction(N));
        psg[destruction].emplace_back(Psg::destruction(N));
        psg[connection].emplace_back(Psg::connection(N));
        psg[emission].emplace_back(Psg::emission(N));
        psg[combined].emplace_back(Psg::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& jls = records["Jl_signal"];
        jls[construction].emplace_back(Jls::construction(N));
        jls[destruction].emplace_back(Jls::destruction(N));
        jls[connection].emplace_back(Jls::connection(N));
        jls[emission].emplace_back(Jls::emission(N));
        jls[combined].emplace_back(Jls::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& nss = records["Nano-signal-slot"];
        nss[construction].emplace_back(Nss::construction(N));
        nss[destruction].emplace_back(Nss::destruction(N));
        nss[connection].emplace_back(Nss::connection(N));
        nss[emission].emplace_back(Nss::emission(N));
        nss[combined].emplace_back(Nss::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& bs1 = records["Boost Signals"];
        bs1[construction].emplace_back(Bs1::construction(N));
        bs1[destruction].emplace_back(Bs1::destruction(N));
        bs1[connection].emplace_back(Bs1::connection(N));
        bs1[emission].emplace_back(Bs1::emission(N));
        bs1[combined].emplace_back(Bs1::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& bs2 = records["Boost Signals2"];
        bs2[construction].emplace_back(Bs2::construction(N));
        bs2[destruction].emplace_back(Bs2::destruction(N));
        bs2[connection].emplace_back(Bs2::connection(N));
        bs2[emission].emplace_back(Bs2::emission(N));
        bs2[combined].emplace_back(Bs2::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& evl = records["EvilTwin Observer"];
        evl[construction].emplace_back(Evl::construction(N));
        evl[destruction].emplace_back(Evl::destruction(N));
        evl[connection].emplace_back(Evl::connection(N));
        evl[emission].emplace_back(Evl::emission(N));
        evl[combined].emplace_back(Evl::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& evf = records["EvilTwin Obs Fork"];
        evf[construction].emplace_back(Evf::construction(N));
        evf[destruction].emplace_back(Evf::destruction(N));
        evf[connection].emplace_back(Evf::connection(N));
        evf[emission].emplace_back(Evf::emission(N));
        evf[combined].emplace_back(Evf::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& evs = records["EvilTwin Obs Safe"];
        evs[construction].emplace_back(Evs::construction(N));
        evs[destruction].emplace_back(Evs::destruction(N));
        evs[connection].emplace_back(Evs::connection(N));
        evs[emission].emplace_back(Evs::emission(N));
        evs[combined].emplace_back(Evs::combined(N));

        std::cout << "[Line: " << __LINE__ << "]" << std::endl;

        auto& s11 = records["amc522 Signal11"];
        s11[construction].emplace_back(Asg::construction(N));
        s11[destruction].emplace_back(Asg::destruction(N));
        s11[connection].emplace_back(Asg::connection(N));
        s11[emission].emplace_back(Asg::emission(N));
        s11[combined].emplace_back(Asg::combined(N));

        std::cout << "\n[Test Size: " << N << "] END" << std::endl;
    }
    outputReports(records);

    std::size_t numImplementations = records.size();
    std::size_t numOperations = records.begin()->second.size();
    std::size_t numRounds = records.begin()->second.begin()->second.size();
    std::size_t numBenchmarks = numImplementations * numOperations * numRounds;

    std::cout << "\n" << numBenchmarks << " Benchmarks Completed: [paused]" << std::endl;
    std::cin.get();
}

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

void outputReports(ImmediateData const& records)
{
    if (std::ofstream ofs { "report.txt", std::ios::app })
    {
        auto tee = std::tie(std::cout, ofs);

        auto now = std::chrono::system_clock::now();
        auto now_c = std::chrono::system_clock::to_time_t(now);
        tee << std::put_time(std::localtime(&now_c), "%c") << '\n';

        outputReportTxt(records, tee);

        ofs << "\n//--------------------------------------"
            << "----------------------------------------\n" << std::endl;
    }
    else
    {
        std::cerr << "Unable to append report.txt: [error]" << std::endl;
    }
    if (std::ofstream ofs { "report.csv" })
    {
        outputReportCsv(records, ofs);
    }
    else
    {
        std::cerr << "Unable to create report.csv: [error]" << std::endl;
    }
}

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

template <typename T>
void outputReportTxt(ImmediateData const& records, T& ost)
{
    using namespace std;

    for(auto const& table : records)
    {
        auto const& tableName = table.first;

        ost << "\n    " << tableName << ":";

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& data = record.second;

            double avg = accumulate(begin(data),
                end(data), 1.0) / (double) data.size();

            ost << "\n ++ " << setw(40) << setfill('_')
                << recordName << ": " << setprecision(2) << fixed << avg;
        }
        ost << "\n";
    }
}

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

template <typename T>
void outputReportCsv(ImmediateData const& records, T& ost)
{
    using namespace std;

    ost << "Library," << construction << "," << destruction << ","
        << connection << "," << emission << "," << combined << endl;

    for(auto const& table : records)
    {
        ost << table.first;

        for(auto const& record : table.second)
        {
            auto const& data = record.second;

            double avg = accumulate(begin(data),
                end(data), 1.0) / (double) data.size();

            ost << "," << setprecision(2) << fixed << avg;
        }
        ost << endl;
    }
}

//-------------------------------------------------------------CAUTION YOUR EYES

/*
template <typename T>
void outputReportNew(ImmediateData const& records, T& ost)
{
    RelativeResults maxAverage;
    RelativeData averages;

    const std::size_t maxOutputLength = 80;
    std::size_t maxNameLength = 0;

    std::map<std::string, std::size_t> maxColumnLength;

    for(auto const& table : records)
    {
        auto const& tableName = table.first;

        maxNameLength = std::max(maxNameLength, tableName.size() + 2);

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& data = record.second;

            double avg = std::accumulate(std::begin(data),
                std::end(data), 1.0) / (double) data.size();

            averages[tableName][recordName] = avg;

            maxAverage[recordName] = std::max(maxAverage[recordName], avg);

            std::stringstream sts;
            sts << std::setprecision(2) << std::fixed << avg;
            maxColumnLength[recordName] = std::max(maxColumnLength[recordName], sts.str().size() + 2);
        }
    }

    for(auto const& table : averages)
    {
        auto const& tableName = table.first;

        ost << "+" << std::string(maxNameLength, '-') << "+\n|";

        std::size_t currentNameLength = tableName.size();
        std::size_t namePaddingLength = maxNameLength / currentNameLength;
        bool extraSpace = (namePaddingLength * currentNameLength == maxNameLength);
        std::string namePadding(namePaddingLength, ' ');

        ost << namePadding << tableName << namePadding + (extraSpace ? " |" : "|");

        std::vector<double> dt;

        for(auto const& record : table.second)
        {
            auto const& recordName = record.first;
            auto const& average = record.second;

            dt.emplace_back((average / maxAverage[recordName]) * 100.0);

            std::size_t columnLength = maxColumnLength[recordName];
            std::size_t valuePaddingLength = columnLength / recordName.size();

        }
    }
}
*/
<|endoftext|>


<commit_before>#include <string>
#include <cstring>
#include <cassert>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <getopt.h>
#include "rolling.h"
#include "city.h"

/* as per instructions at top of stb_image_write.h */
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

using namespace std;

#define PROGRAM "collision"

static const char USAGE_MESSAGE[] =
"Usage:" PROGRAM " [OPTIONS] [FASTA]...\n"
"Measure number of hash collisions using CityHash64 or rolling hash.\n"
"K-mers from [FASTA] are hashed to positions within a fixed-size\n"
"window (using the modulus operator).\n"
"\n"
"Options:\n"
"     -d, --max-density N     stop hashing k-mers when\n"
"                             DISTINCT_KMERS / WINDOW_SIZE > N [0.05]\n"
"     -h, --help              show this message\n"
"     -H, --hash HASH         hash function to use ('city' or 'rolling')\n"
"                             [rolling]\n"
"     -k, --kmer-size         size of k-mer [20]\n"
"     -p, --png FILE          write bitmap of hash positions\n"
"                             to FILE; dimensions of output PNG are\n"
"                             approximately sqrt(WINDOW_SIZE) by \n"
"                             sqrt(WINDOW_SIZE)\n"
"     -P, --progress-step N   show progress message after hashing\n"
"                             every N k-mers [10000]\n"
"     -v, --verbose           show progress messages\n"
"     -w, --window-size N     window size; this should normally\n"
"                             be a prime number [1048573]\n";

namespace opt {
	static float maxDensity = 0.05f;
	static int help = 0;
	static string hashFunc("rolling");
	static unsigned k = 20;
	static string pngPath;
	static size_t progressStep = 10000;
	static int verbose = 0;
	static size_t windowSize = 1048573;
}

static const char shortopts[] = "d:hH:k:p:P:vw:";

static const struct option longopts[] = {
	{ "max-density", required_argument, NULL, 'd' },
	{ "help", no_argument, NULL, 'h' },
	{ "hash", required_argument, NULL, 'H' },
	{ "kmer-size", required_argument, NULL, 'k' },
	{ "png", required_argument, NULL, 'p' },
	{ "progress-step", required_argument, NULL, 'P' },
	{ "verbose", no_argument, NULL, 'v' },
	{ "window-size", required_argument, NULL, 'w' },
	{ NULL, 0, NULL, 0 }
};

#define RGB_FORMAT 3
#define BYTES_PER_PIXEL 3

/** Dimensions and pixel data for output PNG file */
struct PNG {

	int width;
	int height;
	/* 3 bytes per pixel: R,G,B */
	void* data;

	void setPixel(unsigned x, unsigned y, uint8_t r, uint8_t g, uint8_t b) {
		size_t offset = (y * width + x) * BYTES_PER_PIXEL;
		uint8_t* bytes = (uint8_t*)data;
		bytes[offset] = r;
		bytes[offset + 1] = g;
		bytes[offset + 2] = b;
	}
};

typedef unordered_map<uint64_t, uint8_t> HashCountMap;

static inline bool hashSeq(string seq, unordered_set<string>& kmers,
	HashCountMap& hashCounts)
{
	transform(seq.begin(), seq.end(), seq.begin(), ::toupper);
	uint64_t fwdHash, rcHash, hash;
	string prevKmer;
	for (unsigned i = 0; i < seq.length() - opt::k + 1; ++i) {
		string kmer = seq.substr(i, opt::k);
		size_t pos = kmer.find_first_not_of("ACGT");
		if (pos != string::npos) {
			i += pos;
			prevKmer.clear();
			continue;
		}
		if (opt::hashFunc == "city") {
			hash = CityHash64(kmer.c_str(), kmer.length());
		} else {
			/* hashFunc == "rolling" */
			if (prevKmer.empty()) {
				hash = initHashes(kmer, fwdHash, rcHash);
			} else {
				hash = rollHashesRight(fwdHash, rcHash,
					prevKmer.at(0), kmer.at(opt::k-1), opt::k);
			}
		}
		hash %= opt::windowSize;
		kmers.insert(kmer);
		hashCounts[hash]++;
		prevKmer = kmer;
		if ((float)kmers.size() / opt::windowSize > opt::maxDensity)
			return false;
		if (opt::verbose && kmers.size() % opt::progressStep == 0) {
			cerr << "hashed " << kmers.size() << " k-mers" << endl;
		}
	}
	return true;
}

static inline void drawPNG(HashCountMap& hashCounts, PNG& png)
{
	/* white background */
	memset(png.data, 255, png.width * png.height * BYTES_PER_PIXEL);

	for(HashCountMap::iterator it = hashCounts.begin();
		it != hashCounts.end(); ++it) {
		uint64_t hash = it->first;
		uint8_t count = it->second;
		unsigned x = hash % png.width;
		unsigned y = hash / png.width;
		if (y >= png.height) {
			cerr << "y >= png.height!" << endl;
			cerr << "hash: " << hash << endl;
			cerr << "y: " << y << endl;
			cerr << "png.width: " << png.width << endl;
			cerr << "png.height: " << png.height << endl;
		}
		assert(y < png.height);
		assert(count > 0);
		if (count > 1) {
			/* red to indicate collision */
			png.setPixel(x, y, 255, 0, 0);
		} else {
			/* black to indicate non-collision */
			png.setPixel(x, y, 0, 0, 0);
		}
	}
}

int main(int argc, char** argv)
{
	bool die = false;
	for (int c; (c = getopt_long(argc, argv,
		shortopts, longopts, NULL)) != -1;) {
		istringstream arg(optarg != NULL ? optarg : "");
		switch (c) {
			case 'd':
				arg >> opt::maxDensity; break;
			case 'h':
				cout << USAGE_MESSAGE;
				exit(EXIT_SUCCESS);
			case 'H':
				arg >> opt::hashFunc; break;
			case 'k':
				arg >> opt::k; break;
			case 'p':
				arg >> opt::pngPath; break;
			case 'P':
				arg >> opt::progressStep; break;
			case 'v':
				opt::verbose++; break;
			case 'w':
				arg >> opt::windowSize; break;
			case '?':
				die = true; break;
		}
		if (optarg != NULL && !arg.eof()) {
			cerr << PROGRAM ": invalid option: `-"
				<< (char)c << optarg << "'\n";
			exit(EXIT_FAILURE);
		}
	}

	if (opt::maxDensity < 0.0f || opt::maxDensity > 1.0f) {
		cerr << "error: value for -d (--max-density) must be in "
			" range [0,1]" << endl;
		die = true;
	}

	if (opt::hashFunc != "rolling" && opt::hashFunc != "city") {
		cerr << "error: unrecognized argument for -h (--hash); "
			" legal values are: 'rolling', 'city'" << endl;
	}

	if (die) {
		cerr << USAGE_MESSAGE;
		exit(EXIT_FAILURE);
	}

	ifstream fin;
	if (argc > optind)
		fin.open(argv[optind]);
	istream& in = (argc > optind) ? fin : cin;
	assert(in);

	/* k-mers inserted so far */
	unordered_set<string> kmers;
	/* number of occurrences of each hash value (usually 1) */
	HashCountMap hashCounts;

	/* read and hash FASTA sequences */
	string line;
	while(getline(in, line)) {
		if (line.empty() || line.at(0) == '>')
			continue;
		/* return false when window exceeds opt::maxDensity */
		if(!hashSeq(line, kmers, hashCounts))
			break;
	}

	/* count collisions */
	uint64_t collisions = kmers.size() - hashCounts.size();
	cout << "distinct k-mers hashed: " << kmers.size() << endl;
	cout << "hash collisions: " << collisions << endl;

	/* create PNG image */
	if (!opt::pngPath.empty()) {
		PNG png;
		png.width = (int)ceil(sqrt(opt::windowSize));
		png.height = (int)ceil((double)opt::windowSize / png.width);
		png.data = malloc(png.width * png.height * BYTES_PER_PIXEL);
		drawPNG(hashCounts, png);
		stbi_write_png(opt::pngPath.c_str(), png.width, png.height,
			RGB_FORMAT, png.data, png.width*BYTES_PER_PIXEL);
	}

	return 0;
}
<commit_msg>collision: change output format to TSV<commit_after>#include <string>
#include <cstring>
#include <cassert>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <getopt.h>
#include "rolling.h"
#include "city.h"

/* as per instructions at top of stb_image_write.h */
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

using namespace std;

#define PROGRAM "collision"

static const char USAGE_MESSAGE[] =
"Usage:" PROGRAM " [OPTIONS] [FASTA]...\n"
"Measure number of hash collisions using CityHash64 or rolling hash.\n"
"K-mers from [FASTA] are hashed to positions within a fixed-size\n"
"window (using the modulus operator).\n"
"\n"
"Options:\n"
"     -d, --max-density N     stop hashing k-mers when\n"
"                             DISTINCT_KMERS / WINDOW_SIZE > N [0.05]\n"
"     -h, --help              show this message\n"
"     -H, --hash HASH         hash function to use ('city' or 'rolling')\n"
"                             [rolling]\n"
"     -k, --kmer-size         size of k-mer [20]\n"
"     -p, --png FILE          write bitmap of hash positions\n"
"                             to FILE; dimensions of output PNG are\n"
"                             approximately sqrt(WINDOW_SIZE) by \n"
"                             sqrt(WINDOW_SIZE)\n"
"     -P, --progress-step N   show progress message after hashing\n"
"                             every N k-mers [10000]\n"
"     -v, --verbose           show progress messages\n"
"     -w, --window-size N     window size; this should normally\n"
"                             be a prime number [1048573]\n";

namespace opt {
	static float maxDensity = 0.05f;
	static int help = 0;
	static string hashFunc("rolling");
	static unsigned k = 20;
	static string pngPath;
	static size_t progressStep = 10000;
	static int verbose = 0;
	static size_t windowSize = 1048573;
}

static const char shortopts[] = "d:hH:k:p:P:vw:";

static const struct option longopts[] = {
	{ "max-density", required_argument, NULL, 'd' },
	{ "help", no_argument, NULL, 'h' },
	{ "hash", required_argument, NULL, 'H' },
	{ "kmer-size", required_argument, NULL, 'k' },
	{ "png", required_argument, NULL, 'p' },
	{ "progress-step", required_argument, NULL, 'P' },
	{ "verbose", no_argument, NULL, 'v' },
	{ "window-size", required_argument, NULL, 'w' },
	{ NULL, 0, NULL, 0 }
};

#define RGB_FORMAT 3
#define BYTES_PER_PIXEL 3

/** Dimensions and pixel data for output PNG file */
struct PNG {

	int width;
	int height;
	/* 3 bytes per pixel: R,G,B */
	void* data;

	void setPixel(unsigned x, unsigned y, uint8_t r, uint8_t g, uint8_t b) {
		size_t offset = (y * width + x) * BYTES_PER_PIXEL;
		uint8_t* bytes = (uint8_t*)data;
		bytes[offset] = r;
		bytes[offset + 1] = g;
		bytes[offset + 2] = b;
	}
};

typedef unordered_map<uint64_t, uint8_t> HashCountMap;

static inline bool hashSeq(string seq, unordered_set<string>& kmers,
	HashCountMap& hashCounts)
{
	transform(seq.begin(), seq.end(), seq.begin(), ::toupper);
	uint64_t fwdHash, rcHash, hash;
	string prevKmer;
	for (unsigned i = 0; i < seq.length() - opt::k + 1; ++i) {
		string kmer = seq.substr(i, opt::k);
		size_t pos = kmer.find_first_not_of("ACGT");
		if (pos != string::npos) {
			i += pos;
			prevKmer.clear();
			continue;
		}
		if (opt::hashFunc == "city") {
			hash = CityHash64(kmer.c_str(), kmer.length());
		} else {
			/* hashFunc == "rolling" */
			if (prevKmer.empty()) {
				hash = initHashes(kmer, fwdHash, rcHash);
			} else {
				hash = rollHashesRight(fwdHash, rcHash,
					prevKmer.at(0), kmer.at(opt::k-1), opt::k);
			}
		}
		hash %= opt::windowSize;
		kmers.insert(kmer);
		hashCounts[hash]++;
		prevKmer = kmer;
		if ((float)kmers.size() / opt::windowSize > opt::maxDensity)
			return false;
		if (opt::verbose && kmers.size() % opt::progressStep == 0) {
			cerr << "hashed " << kmers.size() << " k-mers" << endl;
		}
	}
	return true;
}

static inline void drawPNG(HashCountMap& hashCounts, PNG& png)
{
	/* white background */
	memset(png.data, 255, png.width * png.height * BYTES_PER_PIXEL);

	for(HashCountMap::iterator it = hashCounts.begin();
		it != hashCounts.end(); ++it) {
		uint64_t hash = it->first;
		uint8_t count = it->second;
		unsigned x = hash % png.width;
		unsigned y = hash / png.width;
		if (y >= png.height) {
			cerr << "y >= png.height!" << endl;
			cerr << "hash: " << hash << endl;
			cerr << "y: " << y << endl;
			cerr << "png.width: " << png.width << endl;
			cerr << "png.height: " << png.height << endl;
		}
		assert(y < png.height);
		assert(count > 0);
		if (count > 1) {
			/* red to indicate collision */
			png.setPixel(x, y, 255, 0, 0);
		} else {
			/* black to indicate non-collision */
			png.setPixel(x, y, 0, 0, 0);
		}
	}
}

int main(int argc, char** argv)
{
	bool die = false;
	for (int c; (c = getopt_long(argc, argv,
		shortopts, longopts, NULL)) != -1;) {
		istringstream arg(optarg != NULL ? optarg : "");
		switch (c) {
			case 'd':
				arg >> opt::maxDensity; break;
			case 'h':
				cout << USAGE_MESSAGE;
				exit(EXIT_SUCCESS);
			case 'H':
				arg >> opt::hashFunc; break;
			case 'k':
				arg >> opt::k; break;
			case 'p':
				arg >> opt::pngPath; break;
			case 'P':
				arg >> opt::progressStep; break;
			case 'v':
				opt::verbose++; break;
			case 'w':
				arg >> opt::windowSize; break;
			case '?':
				die = true; break;
		}
		if (optarg != NULL && !arg.eof()) {
			cerr << PROGRAM ": invalid option: `-"
				<< (char)c << optarg << "'\n";
			exit(EXIT_FAILURE);
		}
	}

	if (opt::maxDensity < 0.0f || opt::maxDensity > 1.0f) {
		cerr << "error: value for -d (--max-density) must be in "
			" range [0,1]" << endl;
		die = true;
	}

	if (opt::hashFunc != "rolling" && opt::hashFunc != "city") {
		cerr << "error: unrecognized argument for -h (--hash); "
			" legal values are: 'rolling', 'city'" << endl;
	}

	if (die) {
		cerr << USAGE_MESSAGE;
		exit(EXIT_FAILURE);
	}

	ifstream fin;
	if (argc > optind)
		fin.open(argv[optind]);
	istream& in = (argc > optind) ? fin : cin;
	assert(in);

	/* k-mers inserted so far */
	unordered_set<string> kmers;
	/* number of occurrences of each hash value (usually 1) */
	HashCountMap hashCounts;

	/* read and hash FASTA sequences */
	string line;
	while(getline(in, line)) {
		if (line.empty() || line.at(0) == '>')
			continue;
		/* return false when window exceeds opt::maxDensity */
		if(!hashSeq(line, kmers, hashCounts))
			break;
	}

	/* count collisions */
	uint64_t collisions = kmers.size() - hashCounts.size();
	cout << "distinct_kmers\tcollisions\n";
	cout << kmers.size() << "\t" << collisions << "\n";

	/* create PNG image */
	if (!opt::pngPath.empty()) {
		PNG png;
		png.width = (int)ceil(sqrt(opt::windowSize));
		png.height = (int)ceil((double)opt::windowSize / png.width);
		png.data = malloc(png.width * png.height * BYTES_PER_PIXEL);
		drawPNG(hashCounts, png);
		stbi_write_png(opt::pngPath.c_str(), png.width, png.height,
			RGB_FORMAT, png.data, png.width*BYTES_PER_PIXEL);
	}

	return 0;
}
<|endoftext|>


<commit_before>// Images.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"

#include "Images.h"
#include "../interface/HeeksObj.h"

Images::Images(){
	m_image_list = NULL;
}

int Images::GetImage(HeeksObj *object)
{
	int image_index = -1;

	if(m_image_list && object->GetType() != UnknownType)
	{
		std::map<wxString, int>::iterator FindIt;

		wxString icon_str = object->GetIcon();

		if (image_map.size()>0) FindIt = image_map.find(icon_str);
		if (image_map.size() == 0 || FindIt == image_map.end())
		{
			image_index = m_image_list->Add(wxIcon(icon_str + _T(".png"), wxBITMAP_TYPE_PNG));
			FindIt = image_map.insert(std::pair<wxString, int>(icon_str, image_index)).first;
			image_index = FindIt->second;
		}
		else image_index = FindIt->second;
	}
	return image_index;
}

bool Images::InitializeImageList(int width, int height){
	if(m_image_list == NULL){
		m_image_list = new wxImageList(width, height);
		return true;
	}
	return false;
}
<commit_msg>face list and edge list icons were not working<commit_after>// Images.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"

#include "Images.h"
#include "../interface/HeeksObj.h"

Images::Images(){
	m_image_list = NULL;
}

int Images::GetImage(HeeksObj *object)
{
	int image_index = -1;

	if(m_image_list)
	{
		std::map<wxString, int>::iterator FindIt;

		wxString icon_str = object->GetIcon();

		if (image_map.size()>0) FindIt = image_map.find(icon_str);
		if (image_map.size() == 0 || FindIt == image_map.end())
		{
			image_index = m_image_list->Add(wxIcon(icon_str + _T(".png"), wxBITMAP_TYPE_PNG));
			FindIt = image_map.insert(std::pair<wxString, int>(icon_str, image_index)).first;
			image_index = FindIt->second;
		}
		else image_index = FindIt->second;
	}
	return image_index;
}

bool Images::InitializeImageList(int width, int height){
	if(m_image_list == NULL){
		m_image_list = new wxImageList(width, height);
		return true;
	}
	return false;
}
<|endoftext|>


<commit_before>//===- StackSlots.cpp  - Specialize LLVM code for target machine ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass adds 2 empty slots at the top of function stack.  These two slots
// are later used during code reoptimization for spilling the register values
// when rewriting branches.
//
//===----------------------------------------------------------------------===//

#include "SparcInternals.h"
#include "llvm/Constant.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"

namespace {
  class StackSlots : public MachineFunctionPass {
    const TargetMachine &Target;
  public:
    StackSlots(const TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "Stack Slot Insertion for profiling code";
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
    }

    bool runOnMachineFunction(MachineFunction &MF) {
      const Type *PtrInt = PointerType::get(Type::IntTy);
      unsigned Size = Target.getTargetData().getTypeSize(PtrInt);

      Value *V = Constant::getNullValue(Type::IntTy);
      MF.getInfo()->allocateLocalVar(V, 2*Size);
      return true;
    }
  };
}

Pass *createStackSlotsPass(const TargetMachine &Target) {
  return new StackSlots(Target);
}
<commit_msg>* Make the comment header 80 columns long * Alphabetize #includes<commit_after>//===- StackSlots.cpp  - Specialize LLVM code for target machine ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass adds 2 empty slots at the top of function stack.  These two slots
// are later used during code reoptimization for spilling the register values
// when rewriting branches.
//
//===----------------------------------------------------------------------===//

#include "SparcInternals.h"
#include "llvm/Constant.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"

namespace {
  class StackSlots : public MachineFunctionPass {
    const TargetMachine &Target;
  public:
    StackSlots(const TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "Stack Slot Insertion for profiling code";
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
    }

    bool runOnMachineFunction(MachineFunction &MF) {
      const Type *PtrInt = PointerType::get(Type::IntTy);
      unsigned Size = Target.getTargetData().getTypeSize(PtrInt);

      Value *V = Constant::getNullValue(Type::IntTy);
      MF.getInfo()->allocateLocalVar(V, 2*Size);
      return true;
    }
  };
}

Pass *createStackSlotsPass(const TargetMachine &Target) {
  return new StackSlots(Target);
}
<|endoftext|>