<commit_before>#include "gaf/gen_pugixml.h"

#include <array>
#include <cassert>
#include "fmt/format.h"

#include "gaf/generator.h"
#include "gaf/args.h"
#include "gaf/array.h"

namespace xml
{
    void add_enum_function(const Enum& e, Out* sources)
    {
        // const auto enum_type = e.name;
        // const auto value_prefix = get_value_prefix_opt(e);
        // const auto arg = ", const std::string& gaf_path";

        const auto signature =
            fmt::format("std::string ParseEnumString({}* c, const char* value)", e.name);
        sources->header.addf("{};", signature);
        sources->source.add(signature);
        sources->source.add("{");
        for (const auto& v : e.values)
        {
            sources->source.addf(
                "if(strcmp(value, \"{value}\") == 0) {{ *c = {type}::{value}; return \"\"; }}",
                fmt::arg("type", e.name), fmt::arg("value", v));
        }
        // todo(Gustav): add list of valid values with a could_be_fun
        sources->source.addf("return fmt::format(\"{{}} is not a valid name for enum {}\", value);",
                             e.name);
        sources->source.add("}");
        sources->source.add("");
    }

    void add_member_failure_to_read(Out* sources, const Member& m)
    {
        if (m.missing_is_fail || m.is_optional)
        {
            sources->source.add("else");
            sources->source.add("{");
            if (m.is_optional)
            {
                sources->source.addf("c->{}.reset();", m.name);
            }
            else
            {
                sources->source.addf("return \"{} is missing\";", m.name);
            }
            sources->source.add("}");
        }
    }

    bool is_basic_type(const Type& t)
    {
        switch (t.standard_type)
        {
        case StandardType::Int8:
        case StandardType::Int16:
        case StandardType::Int32:
        case StandardType::Int64:
        case StandardType::Uint8:
        case StandardType::Uint16:
        case StandardType::Uint32:
        case StandardType::Uint64:
        case StandardType::Float:
        case StandardType::Double:
        case StandardType::Byte:
        case StandardType::Bool:
        case StandardType::String: return true;
        default: return false;
        }
    }

    void add_member_variable_array(Out* sources, const Member& m)
    {
        if (m.type_name.is_enum)
        {
            sources->source.addf("for(const auto el: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            sources->addf("auto em = {}{{}};", m.type_name.get_cpp_type());
            sources->source.add(
                "if(const auto error = ParseEnumString(&em, el.child_value()); error.empty() == "
                "false)");
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.addf("c->{}.emplace_back(em)", m.name);
            sources->source.add("}");
        }
        else if (is_basic_type(m.type_name))
        {
            sources->source.addf("for(const auto el: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            switch (m.type_name.standard_type)
            {
            case StandardType::Bool:
                sources->source.add("bool b = false;");
                sources->source.add("if(gaf::parse_bool(&b, el.child_value()) == false)");
                sources->source.add("{");
                sources->source.addf(
                    "return fmt::format(\"Invalid bool for {}: {{}}\", el.child_value());", m.name);
                sources->source.add("}");
                sources->source.addf("c->{}.emplace_back(b);", m.name);
                break;
            case StandardType::String:
                sources->source.addf("c->{}.emplace_back(el.child_value());", m.name);
                break;
            default:
                sources->source.addf("{} v = 0;", m.type_name.get_cpp_type());
                sources->source.add("std::istringstream ss(el.child_value());");
                sources->source.add("ss >> v;");
                sources->source.add("if(ss.good() == false)");
                sources->source.add("{");
                sources->source.addf(
                    "return fmt::format(\"Invalid format for {}: {{}}\", el.child_value());", m.name);
                sources->source.add("}");
                sources->source.addf("c->{}.emplace_back(v);", m.name);
                break;
            }
            sources->source.add("}");
        }
        else
        {
            sources->source.addf("for(const auto child: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            sources->source.addf("auto v = {}{{}};", m.type_name.get_cpp_type());
            sources->source.addf(
                "if(const auto error = ReadXmlElement(&v, value); error.empty() == false)", m.name);
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.addf("c->{}.emplace_back(v);", m.name);
            sources->source.add("}");
        }
    }

    void add_member_variable_single(Out* sources, const Member& m)
    {
        if (m.type_name.is_enum)
        {
            sources->source.addf("if(const auto el = value.attribute(\"{}\"); el)", m.name);
            sources->source.add("{");
            sources->source.addf(
                "if(const auto error = ParseEnumString(&c->{}, el.value()); error.empty() == false)",
                m.name);
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
        else if (is_basic_type(m.type_name))
        {
            sources->source.addf("if(const auto el = value.attribute(\"{}\"); el)", m.name);
            sources->source.add("{");
            switch (m.type_name.standard_type)
            {
            case StandardType::Bool:
                sources->source.addf("if(gaf::parse_bool(&c->{}, el.value()) == false)", m.name);
                sources->source.add("{");
                sources->source.addf("return fmt::format(\"Invalid bool for {}: {{}}\", el.value());",
                                     m.name);
                sources->source.add("}");
                break;
            case StandardType::String: sources->source.addf("c->{} = el.value();", m.name); break;
            default:
                sources->source.add("std::istringstream ss(el.value());");
                sources->source.addf("ss >> c->{};", m.name);
                sources->source.add("if(ss.good() == false)");
                sources->source.add("{");
                sources->source.addf("return fmt::format(\"Invalid format for {}: {{}}\", el.value());",
                                     m.name);
                sources->source.add("}");
                break;
            }
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
        else
        {
            sources->source.addf("if(const auto child = value.child(\"{}\"); child)", m.name);
            sources->source.add("{");
            sources->source.addf(
                "if(const auto error = ReadXmlElement(&c->{}, value); error.empty() == false)", m.name);
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
    }

    void add_member_variable(Out* sources, const Member& m)
    {
        if (m.is_dynamic_array)
        {
            add_member_variable_array(sources, m);
        }
        else
        {
            add_member_variable_single(sources, m);
        }
    }

    void add_struct_function(Out* sources, const Struct& s)
    {
        const auto signature =
            fmt::format("std::string ReadXmlElement({}* c, const pugi::xml_node& value)", s.name);
        sources->header.addf("{};", signature);
        sources->source.add(signature);
        sources->source.add("{");
        for (const auto& m : s.members) { add_member_variable(sources, m); }
        sources->source.add("return \"\";");
        sources->source.add("}");
        sources->source.add("");
    }

    Out generate_xml(const File& f, const std::string& name)
    {
        auto sources = Out{};

        sources.header.add("#pragma once");
        sources.header.add("");
        sources.header.add("#include <string>");
        sources.header.add("#include \"pugixml.hpp\"");
        sources.header.add("");
        sources.header.addf("#include \"gaf_{}.h\"", name);

        sources.source.add("#include <cstring>");
        sources.source.add("#include <sstream>");
        sources.source.add("#include \"fmt/format.h\"");
        sources.source.add("#include \"gaf/lib_pugixml.h\"");

        sources.add("");

        if (f.package_name.empty() == false)
        {
            sources.addf("namespace {}", f.package_name);
            sources.add("{");
        }

        for (const auto& e : f.enums) { add_enum_function(*e, &sources); }

        for (const auto& s : f.structs) { add_struct_function(&sources, *s); }

        if (f.package_name.empty() == false)
        {
            sources.add("}");
            sources.add("");
        }

        return sources;
    }
}

std::string PugiXmlPlugin::get_name() { return "pugixml"; }

int PugiXmlPlugin::run_plugin(const File& file, Writer* writer, std::string& output_folder, Args& args,
                              const std::string& name)
{
    if (auto r = no_arguments(args); r != 0)
    {
        return r;
    }

    auto out = xml::generate_xml(file, name);
    write_cpp(&out, writer, output_folder, name, "gaf_pugixml_");

    return 0;
}
<commit_msg>fix: generated xml code compiles now<commit_after>#include "gaf/gen_pugixml.h"

#include <array>
#include <cassert>
#include "fmt/format.h"

#include "gaf/generator.h"
#include "gaf/args.h"
#include "gaf/array.h"

namespace xml
{
    void add_enum_function(const Enum& e, Out* sources)
    {
        // const auto enum_type = e.name;
        // const auto value_prefix = get_value_prefix_opt(e);
        // const auto arg = ", const std::string& gaf_path";

        const auto signature =
            fmt::format("std::string ParseEnumString({}* c, const char* value)", e.name);
        sources->header.addf("{};", signature);
        sources->source.add(signature);
        sources->source.add("{");
        for (const auto& v : e.values)
        {
            sources->source.addf(
                "if(strcmp(value, \"{value}\") == 0) {{ *c = {type}::{value}; return \"\"; }}",
                fmt::arg("type", e.name), fmt::arg("value", v));
        }
        // todo(Gustav): add list of valid values with a could_be_fun
        sources->source.addf("return fmt::format(\"{{}} is not a valid name for enum {}\", value);",
                             e.name);
        sources->source.add("}");
        sources->source.add("");
    }

    void add_member_failure_to_read(Out* sources, const Member& m)
    {
        if (m.missing_is_fail || m.is_optional)
        {
            sources->source.add("else");
            sources->source.add("{");
            if (m.is_optional)
            {
                sources->source.addf("c->{}.reset();", m.name);
            }
            else
            {
                sources->source.addf("return \"{} is missing\";", m.name);
            }
            sources->source.add("}");
        }
    }

    bool is_basic_type(const Type& t)
    {
        switch (t.standard_type)
        {
        case StandardType::Int8:
        case StandardType::Int16:
        case StandardType::Int32:
        case StandardType::Int64:
        case StandardType::Uint8:
        case StandardType::Uint16:
        case StandardType::Uint32:
        case StandardType::Uint64:
        case StandardType::Float:
        case StandardType::Double:
        case StandardType::Byte:
        case StandardType::Bool:
        case StandardType::String: return true;
        default: return false;
        }
    }

    void add_member_variable_array(Out* sources, const Member& m)
    {
        if (m.type_name.is_enum)
        {
            sources->source.addf("for(const auto el: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            sources->source.addf("auto em = {}{{}};", m.type_name.get_cpp_type());
            sources->source.add(
                "if(const auto error = ParseEnumString(&em, el.child_value()); error.empty() == "
                "false)");
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.addf("c->{}.emplace_back(em);", m.name);
            sources->source.add("}");
        }
        else if (is_basic_type(m.type_name))
        {
            sources->source.addf("for(const auto el: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            switch (m.type_name.standard_type)
            {
            case StandardType::Bool:
                sources->source.add("bool b = false;");
                sources->source.add("if(gaf::parse_bool(&b, el.child_value()) == false)");
                sources->source.add("{");
                sources->source.addf(
                    "return fmt::format(\"Invalid bool for {}: {{}}\", el.child_value());", m.name);
                sources->source.add("}");
                sources->source.addf("c->{}.emplace_back(b);", m.name);
                break;
            case StandardType::String:
                sources->source.addf("c->{}.emplace_back(el.child_value());", m.name);
                break;
            default:
                sources->source.addf("{} v = 0;", m.type_name.get_cpp_type());
                sources->source.add("std::istringstream ss(el.child_value());");
                sources->source.add("ss >> v;");
                sources->source.add("if(ss.good() == false)");
                sources->source.add("{");
                sources->source.addf(
                    "return fmt::format(\"Invalid format for {}: {{}}\", el.child_value());", m.name);
                sources->source.add("}");
                sources->source.addf("c->{}.emplace_back(v);", m.name);
                break;
            }
            sources->source.add("}");
        }
        else
        {
            sources->source.addf("for(const auto el: value.children(\"{}\"))", m.name);
            sources->source.add("{");
            sources->source.addf("auto v = {}{{}};", m.type_name.get_cpp_type());
            sources->source.addf("if(const auto error = ReadXmlElement(&v, el); error.empty() == false)",
                                 m.name);
            sources->source.add("{");
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.addf("c->{}.emplace_back(v);", m.name);
            sources->source.add("}");
        }
    }

    void add_member_variable_single(Out* sources, const Member& m)
    {
        auto ptr = m.is_optional ? fmt::format("c->{}.get()", m.name) : fmt::format("&c->{}", m.name);
        auto val = m.is_optional ? fmt::format("*c->{}", m.name) : fmt::format("c->{}", m.name);
        auto create_mem = [sources, m]() {
            if (m.is_optional)
            {
                sources->source.addf("c->{} = std::make_shared<{}>();", m.name,
                                     m.type_name.get_cpp_type());
            }
        };
        auto clear_mem = [sources, m]() {
            if (m.is_optional)
            {
                sources->source.addf("c->{}.reset();", m.name);
            }
        };
        if (m.type_name.is_enum)
        {
            sources->source.addf("if(const auto el = value.attribute(\"{}\"); el)", m.name);
            sources->source.add("{");
            create_mem();
            sources->source.addf(
                "if(const auto error = ParseEnumString({}, el.value()); error.empty() == false)", ptr);
            sources->source.add("{");
            clear_mem();
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
        else if (is_basic_type(m.type_name))
        {
            sources->source.addf("if(const auto el = value.attribute(\"{}\"); el)", m.name);
            sources->source.add("{");
            create_mem();
            switch (m.type_name.standard_type)
            {
            case StandardType::Bool:
                sources->source.addf("if(gaf::parse_bool({}, el.value()) == false)", ptr);
                sources->source.add("{");
                clear_mem();
                sources->source.addf("return fmt::format(\"Invalid bool for {}: {{}}\", el.value());",
                                     m.name);
                sources->source.add("}");
                break;
            case StandardType::String: sources->source.addf("{} = el.value();", val); break;
            default:
                sources->source.add("std::istringstream ss(el.value());");
                sources->source.addf("ss >> {};", val);
                sources->source.add("if(ss.good() == false)");
                sources->source.add("{");
                clear_mem();
                sources->source.addf("return fmt::format(\"Invalid format for {}: {{}}\", el.value());",
                                     m.name);
                sources->source.add("}");
                break;
            }
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
        else
        {
            sources->source.addf("if(const auto child = value.child(\"{}\"); child)", m.name);
            sources->source.add("{");
            create_mem();
            sources->source.addf(
                "if(const auto error = ReadXmlElement({}, value); error.empty() == false)", ptr);
            sources->source.add("{");
            clear_mem();
            sources->source.add("return error;");
            sources->source.add("}");
            sources->source.add("}");
            add_member_failure_to_read(sources, m);
        }
    }

    void add_member_variable(Out* sources, const Member& m)
    {
        if (m.is_dynamic_array)
        {
            add_member_variable_array(sources, m);
        }
        else
        {
            add_member_variable_single(sources, m);
        }
    }

    void add_struct_function(Out* sources, const Struct& s)
    {
        const auto signature =
            fmt::format("std::string ReadXmlElement({}* c, const pugi::xml_node& value)", s.name);
        sources->header.addf("{};", signature);
        sources->source.add(signature);
        sources->source.add("{");
        for (const auto& m : s.members) { add_member_variable(sources, m); }
        sources->source.add("return \"\";");
        sources->source.add("}");
        sources->source.add("");
    }

    Out generate_xml(const File& f, const std::string& name)
    {
        auto sources = Out{};

        sources.header.add("#pragma once");
        sources.header.add("");
        sources.header.add("#include <string>");
        sources.header.add("#include \"pugixml.hpp\"");
        sources.header.add("");
        sources.header.addf("#include \"gaf_{}.h\"", name);

        sources.source.add("#include <cstring>");
        sources.source.add("#include <sstream>");
        sources.source.add("#include \"fmt/format.h\"");
        sources.source.add("#include \"gaf/lib_pugixml.h\"");

        sources.add("");

        if (f.package_name.empty() == false)
        {
            sources.addf("namespace {}", f.package_name);
            sources.add("{");
        }

        for (const auto& e : f.enums) { add_enum_function(*e, &sources); }

        for (const auto& s : f.structs) { add_struct_function(&sources, *s); }

        if (f.package_name.empty() == false)
        {
            sources.add("}");
            sources.add("");
        }

        return sources;
    }
}

std::string PugiXmlPlugin::get_name() { return "pugixml"; }

int PugiXmlPlugin::run_plugin(const File& file, Writer* writer, std::string& output_folder, Args& args,
                              const std::string& name)
{
    if (auto r = no_arguments(args); r != 0)
    {
        return r;
    }

    auto out = xml::generate_xml(file, name);
    write_cpp(&out, writer, output_folder, name, "gaf_pugixml_");

    return 0;
}
<|endoftext|>


<commit_before>#ifndef CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_
#define CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_

#include <map>

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/query/metadata.hpp"
#include "containers/archive/order_token.hpp"
#include "containers/uuid.hpp"

template<class protocol_t>
class master_t {
public:
    class ack_checker_t {
    public:
        virtual bool is_acceptable_ack_set(const std::set<peer_id_t> &acks) = 0;

        ack_checker_t() { }
    protected:
        virtual ~ack_checker_t() { }

    private:
        DISABLE_COPYING(ack_checker_t);
    };

    master_t(
            mailbox_manager_t *mm,
            ack_checker_t *ac,
            watchable_variable_t<std::map<master_id_t, master_business_card_t<protocol_t> > > *md,
            mutex_assertion_t *mdl,
            typename protocol_t::region_t region,
            broadcaster_t<protocol_t> *b)
            THROWS_ONLY(interrupted_exc_t) :
        mailbox_manager(mm),
        ack_checker(ac),
        broadcaster(b),
        read_mailbox(mailbox_manager, boost::bind(&master_t<protocol_t>::on_read,
                                                  this, _1, _2, _3, _4, _5, auto_drainer_t::lock_t(&drainer))),
        write_mailbox(mailbox_manager, boost::bind(&master_t<protocol_t>::on_write,
                                                   this, _1, _2, _3, _4, _5, auto_drainer_t::lock_t(&drainer))),
        registrar(mm, this),
        master_directory(md), master_directory_lock(mdl),
        uuid(generate_uuid()) {

        rassert(ack_checker);

        master_business_card_t<protocol_t> bcard(
            region,
            read_mailbox.get_address(), write_mailbox.get_address(),
            registrar.get_business_card());
        mutex_assertion_t::acq_t master_directory_lock_acq(master_directory_lock);
        std::map<master_id_t, master_business_card_t<protocol_t> > master_map = master_directory->get_watchable()->get();
        master_map.insert(std::make_pair(uuid, bcard));
        master_directory->set_value(master_map);
    }

    ~master_t() {
        mutex_assertion_t::acq_t master_directory_lock_acq(master_directory_lock);
        std::map<master_id_t, master_business_card_t<protocol_t> > master_map = master_directory->get_watchable()->get();
        master_map.erase(uuid);
        master_directory->set_value(master_map);
    }

private:

    struct parser_lifetime_t {
        parser_lifetime_t(master_t *m, namespace_interface_business_card_t bc) : m_(m), namespace_interface_id_(bc.namespace_interface_id) {
            m->sink_map.insert(std::pair<namespace_interface_id_t, parser_lifetime_t *>(bc.namespace_interface_id, this));
            send(m->mailbox_manager, bc.ack_address);
        }
        ~parser_lifetime_t() {
            m_->sink_map.erase(namespace_interface_id_);
        }

        auto_drainer_t *drainer() { return &drainer_; }
        fifo_enforcer_sink_t *sink() { return &sink_; }
    private:
        master_t *m_;
        namespace_interface_id_t namespace_interface_id_;
        fifo_enforcer_sink_t sink_;
        auto_drainer_t drainer_;

        DISABLE_COPYING(parser_lifetime_t);
    };

    void on_read(namespace_interface_id_t parser_id, typename protocol_t::read_t read, order_token_t otok, fifo_enforcer_read_token_t token,
            mailbox_addr_t<void(boost::variant<typename protocol_t::read_response_t, std::string>)> response_address,
            auto_drainer_t::lock_t keepalive)
            THROWS_NOTHING
    {
        keepalive.assert_is_holding(&drainer);
        boost::variant<typename protocol_t::read_response_t, std::string> reply;
        try {
            typename std::map<namespace_interface_id_t, parser_lifetime_t *>::iterator it = sink_map.find(parser_id);
            // TODO: Remove this assertion.  Out-of-order operations (which allegedly can happen) could cause it to be wrong?
            rassert(it != sink_map.end());

            auto_drainer_t::lock_t auto_drainer_lock(it->second->drainer());
            fifo_enforcer_sink_t::exit_read_t exiter(it->second->sink(), token);
            reply = broadcaster->read(read, &exiter, otok, auto_drainer_lock.get_drain_signal());
        } catch (cannot_perform_query_exc_t e) {
            reply = e.what();
        }
        send(mailbox_manager, response_address, reply);
    }

    void on_write(namespace_interface_id_t parser_id, typename protocol_t::write_t write, order_token_t otok, fifo_enforcer_write_token_t token,
                  mailbox_addr_t<void(boost::variant<typename protocol_t::write_response_t, std::string>)> response_address,
                  auto_drainer_t::lock_t keepalive)
        THROWS_NOTHING
    {
        keepalive.assert_is_holding(&drainer);
        boost::variant<typename protocol_t::write_response_t, std::string> reply;
        try {
            typename std::map<namespace_interface_id_t, parser_lifetime_t *>::iterator it = sink_map.find(parser_id);
            // TODO: Remove this assertion.  Out-of-order operations (which allegedly can hoppen) could cause it to be wrong?
            rassert(it != sink_map.end());

            class ac_t : public broadcaster_t<protocol_t>::ack_callback_t {
            public:
                explicit ac_t(master_t *p) : parent(p) { }
                bool on_ack(peer_id_t peer) {
                    ack_set.insert(peer);
                    return parent->ack_checker->is_acceptable_ack_set(ack_set);
                }
                master_t *parent;
                std::set<peer_id_t> ack_set;
            } ack_checker(this);

            auto_drainer_t::lock_t auto_drainer_lock(it->second->drainer());
            fifo_enforcer_sink_t::exit_write_t exiter(it->second->sink(), token);
            reply = broadcaster->write(write, &exiter, &ack_checker, otok, auto_drainer_lock.get_drain_signal());
        } catch (cannot_perform_query_exc_t e) {
            reply = e.what();
        }
        send(mailbox_manager, response_address, reply);
    }

    mailbox_manager_t *mailbox_manager;
    ack_checker_t *ack_checker;
    broadcaster_t<protocol_t> *broadcaster;
    std::map<namespace_interface_id_t, parser_lifetime_t *> sink_map;
    auto_drainer_t drainer;

    typename master_business_card_t<protocol_t>::read_mailbox_t read_mailbox;
    typename master_business_card_t<protocol_t>::write_mailbox_t write_mailbox;

    registrar_t<namespace_interface_business_card_t, master_t *, parser_lifetime_t> registrar;

    watchable_variable_t<std::map<master_id_t, master_business_card_t<protocol_t> > > *master_directory;
    mutex_assertion_t *master_directory_lock;
    master_id_t uuid;
};

#endif /* CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_ */
<commit_msg>Added DISABLE_COPYING to master_t.<commit_after>#ifndef CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_
#define CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_

#include <map>

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/query/metadata.hpp"
#include "containers/archive/order_token.hpp"
#include "containers/uuid.hpp"

template<class protocol_t>
class master_t {
public:
    class ack_checker_t {
    public:
        virtual bool is_acceptable_ack_set(const std::set<peer_id_t> &acks) = 0;

        ack_checker_t() { }
    protected:
        virtual ~ack_checker_t() { }

    private:
        DISABLE_COPYING(ack_checker_t);
    };

    master_t(
            mailbox_manager_t *mm,
            ack_checker_t *ac,
            watchable_variable_t<std::map<master_id_t, master_business_card_t<protocol_t> > > *md,
            mutex_assertion_t *mdl,
            typename protocol_t::region_t region,
            broadcaster_t<protocol_t> *b)
            THROWS_ONLY(interrupted_exc_t) :
        mailbox_manager(mm),
        ack_checker(ac),
        broadcaster(b),
        read_mailbox(mailbox_manager, boost::bind(&master_t<protocol_t>::on_read,
                                                  this, _1, _2, _3, _4, _5, auto_drainer_t::lock_t(&drainer))),
        write_mailbox(mailbox_manager, boost::bind(&master_t<protocol_t>::on_write,
                                                   this, _1, _2, _3, _4, _5, auto_drainer_t::lock_t(&drainer))),
        registrar(mm, this),
        master_directory(md), master_directory_lock(mdl),
        uuid(generate_uuid()) {

        rassert(ack_checker);

        master_business_card_t<protocol_t> bcard(
            region,
            read_mailbox.get_address(), write_mailbox.get_address(),
            registrar.get_business_card());
        mutex_assertion_t::acq_t master_directory_lock_acq(master_directory_lock);
        std::map<master_id_t, master_business_card_t<protocol_t> > master_map = master_directory->get_watchable()->get();
        master_map.insert(std::make_pair(uuid, bcard));
        master_directory->set_value(master_map);
    }

    ~master_t() {
        mutex_assertion_t::acq_t master_directory_lock_acq(master_directory_lock);
        std::map<master_id_t, master_business_card_t<protocol_t> > master_map = master_directory->get_watchable()->get();
        master_map.erase(uuid);
        master_directory->set_value(master_map);
    }

private:

    struct parser_lifetime_t {
        parser_lifetime_t(master_t *m, namespace_interface_business_card_t bc) : m_(m), namespace_interface_id_(bc.namespace_interface_id) {
            m->sink_map.insert(std::pair<namespace_interface_id_t, parser_lifetime_t *>(bc.namespace_interface_id, this));
            send(m->mailbox_manager, bc.ack_address);
        }
        ~parser_lifetime_t() {
            m_->sink_map.erase(namespace_interface_id_);
        }

        auto_drainer_t *drainer() { return &drainer_; }
        fifo_enforcer_sink_t *sink() { return &sink_; }
    private:
        master_t *m_;
        namespace_interface_id_t namespace_interface_id_;
        fifo_enforcer_sink_t sink_;
        auto_drainer_t drainer_;

        DISABLE_COPYING(parser_lifetime_t);
    };

    void on_read(namespace_interface_id_t parser_id, typename protocol_t::read_t read, order_token_t otok, fifo_enforcer_read_token_t token,
            mailbox_addr_t<void(boost::variant<typename protocol_t::read_response_t, std::string>)> response_address,
            auto_drainer_t::lock_t keepalive)
            THROWS_NOTHING
    {
        keepalive.assert_is_holding(&drainer);
        boost::variant<typename protocol_t::read_response_t, std::string> reply;
        try {
            typename std::map<namespace_interface_id_t, parser_lifetime_t *>::iterator it = sink_map.find(parser_id);
            // TODO: Remove this assertion.  Out-of-order operations (which allegedly can happen) could cause it to be wrong?
            rassert(it != sink_map.end());

            auto_drainer_t::lock_t auto_drainer_lock(it->second->drainer());
            fifo_enforcer_sink_t::exit_read_t exiter(it->second->sink(), token);
            reply = broadcaster->read(read, &exiter, otok, auto_drainer_lock.get_drain_signal());
        } catch (cannot_perform_query_exc_t e) {
            reply = e.what();
        }
        send(mailbox_manager, response_address, reply);
    }

    void on_write(namespace_interface_id_t parser_id, typename protocol_t::write_t write, order_token_t otok, fifo_enforcer_write_token_t token,
                  mailbox_addr_t<void(boost::variant<typename protocol_t::write_response_t, std::string>)> response_address,
                  auto_drainer_t::lock_t keepalive)
        THROWS_NOTHING
    {
        keepalive.assert_is_holding(&drainer);
        boost::variant<typename protocol_t::write_response_t, std::string> reply;
        try {
            typename std::map<namespace_interface_id_t, parser_lifetime_t *>::iterator it = sink_map.find(parser_id);
            // TODO: Remove this assertion.  Out-of-order operations (which allegedly can hoppen) could cause it to be wrong?
            rassert(it != sink_map.end());

            class ac_t : public broadcaster_t<protocol_t>::ack_callback_t {
            public:
                explicit ac_t(master_t *p) : parent(p) { }
                bool on_ack(peer_id_t peer) {
                    ack_set.insert(peer);
                    return parent->ack_checker->is_acceptable_ack_set(ack_set);
                }
                master_t *parent;
                std::set<peer_id_t> ack_set;
            } ack_checker(this);

            auto_drainer_t::lock_t auto_drainer_lock(it->second->drainer());
            fifo_enforcer_sink_t::exit_write_t exiter(it->second->sink(), token);
            reply = broadcaster->write(write, &exiter, &ack_checker, otok, auto_drainer_lock.get_drain_signal());
        } catch (cannot_perform_query_exc_t e) {
            reply = e.what();
        }
        send(mailbox_manager, response_address, reply);
    }

    mailbox_manager_t *mailbox_manager;
    ack_checker_t *ack_checker;
    broadcaster_t<protocol_t> *broadcaster;
    std::map<namespace_interface_id_t, parser_lifetime_t *> sink_map;
    auto_drainer_t drainer;

    typename master_business_card_t<protocol_t>::read_mailbox_t read_mailbox;
    typename master_business_card_t<protocol_t>::write_mailbox_t write_mailbox;

    registrar_t<namespace_interface_business_card_t, master_t *, parser_lifetime_t> registrar;

    watchable_variable_t<std::map<master_id_t, master_business_card_t<protocol_t> > > *master_directory;
    mutex_assertion_t *master_directory_lock;
    master_id_t uuid;

    DISABLE_COPYING(master_t);
};

#endif /* CLUSTERING_IMMEDIATE_CONSISTENCY_QUERY_MASTER_HPP_ */
<|endoftext|>


<commit_before>#include <ghost.h>
#include <ghost_util.h>
#include <ghost_vec.h>
#include <cmath>
#include <cstdio>
#include "ghost_complex.h"
#include <omp.h>

double conjugate(double& c) {
	return c;
}

float conjugate(float& c) {
	return c;
}

template <typename T>
ghost_complex<T> conjugate(ghost_complex<T>& c) {
	return ghost_complex<T>(std::real(c),-std::imag(c));
}

template <typename v_t> void ghost_normalizeVector_tmpl(ghost_vec_t *vec)
{
	v_t s;
	ghost_vec_dotprod_tmpl<v_t>(vec,vec,&s);
	s = (v_t)sqrt(s);
	s = (v_t)(((v_t)1.)/s);
	vec->scale(vec,&s);

#ifdef GHOST_HAVE_OPENCL
	vec->CLupload(vec);
#endif
#ifdef GHOST_HAVE_CUDA
	vec->CUupload(vec);
#endif
}

template <typename v_t> void ghost_vec_dotprod_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ // the parallelization is done manually because reduction does not work with ghost_complex numbers
	if (vec->traits->nrows != vec2->traits->nrows) {
		WARNING_LOG("The input vectors of the dot product have different numbers of rows");
	}
	if (vec->traits->nvecs != vec2->traits->nvecs) {
		WARNING_LOG("The input vectors of the dot product have different numbers of columns");
	}
	ghost_vidx_t i,v;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	int nthreads;
#pragma omp parallel
	nthreads = ghost_ompGetNumThreads();

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
		v_t sum = 0;
		v_t partsums[nthreads];
		for (i=0; i<nthreads; i++) partsums[i] = (v_t)0.;

#pragma omp parallel for
		for (i=0; i<nr; i++) {
			partsums[ghost_ompGetThreadNum()] +=
				((v_t *)(vec->val))[i+vec->traits->nrowspadded*v]*
				conjugate(((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v]);
		}

		for (i=0; i<nthreads; i++) sum += partsums[i];

		((v_t *)res)[v] = sum;
	}

}

template <typename v_t> void ghost_vec_vaxpy_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
#pragma omp parallel for
		for (i=0; i<nr; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] += ((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v] * s[v];
		}
	}
}

template <typename v_t> void ghost_vec_vaxpby_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b_)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;
	v_t *b = (v_t *)b_;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
#pragma omp parallel for
		for (i=0; i<nr; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] = ((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v] * s[v] +
				((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] * b[v];
		}
	}
}

template<typename v_t> void ghost_vec_vscale_tmpl(ghost_vec_t *vec, void *scale)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;

	for (v=0; v<vec->traits->nvecs; v++) {
#pragma omp parallel for
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] *= s[v];
		}
	}
}

template <typename v_t> void ghost_vec_fromRand_tmpl(ghost_vec_t *vec)
{
	vec_malloc(vec);
	DEBUG_LOG(1,"Filling vector with random values");
	size_t sizeofdt = ghost_sizeofDataType(vec->traits->datatype);

	vec->val = ghost_malloc(vec->traits->nvecs*vec->traits->nrowspadded*sizeofdt);
	int i,v;

	// TODO fuse loops but preserve randomness

	if (vec->traits->nvecs > 1) {
#pragma omp parallel for schedule(runtime) private(i)
		for (v=0; v<vec->traits->nvecs; v++) {
			for (i=0; i<vec->traits->nrows; i++) {
				((v_t *)(vec->val))[v*vec->traits->nrowspadded+i] = (v_t)0;
			}
		}
	} else {
#pragma omp parallel for schedule(runtime)
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[i] = (v_t)0;
		}
	}

	for (v=0; v<vec->traits->nvecs; v++) {
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[v*vec->traits->nrowspadded+i] = (v_t)(rand()*1./RAND_MAX); // TODO imag
		}
	}
	vec->upload(vec);

}

extern "C" void d_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< double >(vec); }

extern "C" void s_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< float >(vec); }

extern "C" void z_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< ghost_complex<double> >(vec); }

extern "C" void c_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< ghost_complex<float> >(vec); }

extern "C" void d_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< double >(vec,vec2,res); }

extern "C" void s_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< float >(vec,vec2,res); }

extern "C" void z_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< ghost_complex<double> >(vec,vec2,res); }

extern "C" void c_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< ghost_complex<float> >(vec,vec2,res); }

extern "C" void d_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< double >(vec, scale); }

extern "C" void s_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< float  >(vec, scale); }

extern "C" void z_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< ghost_complex<double> >(vec, scale); }

extern "C" void c_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< ghost_complex<float> >(vec, scale); }

extern "C" void d_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< double >(vec, vec2, scale); }

extern "C" void s_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< float >(vec, vec2, scale); }

extern "C" void z_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< ghost_complex<double> >(vec, vec2, scale); }

extern "C" void c_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< ghost_complex<float> >(vec, vec2, scale); }

extern "C" void d_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< double >(vec, vec2, scale, b); }

extern "C" void s_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< float >(vec, vec2, scale, b); }

extern "C" void z_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< ghost_complex<double> >(vec, vec2, scale, b); }

extern "C" void c_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< ghost_complex<float> >(vec, vec2, scale, b); }

extern "C" void d_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< double >(vec); }

extern "C" void s_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< float >(vec); }

extern "C" void z_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< ghost_complex<double> >(vec); }

extern "C" void c_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< ghost_complex<float> >(vec); }

<commit_msg>bugfix: vec->fromRand() was always re-allocating vector data, fixes #5<commit_after>#include <ghost.h>
#include <ghost_util.h>
#include <ghost_vec.h>
#include <cmath>
#include <cstdio>
#include "ghost_complex.h"
#include <omp.h>

double conjugate(double& c) {
	return c;
}

float conjugate(float& c) {
	return c;
}

template <typename T>
ghost_complex<T> conjugate(ghost_complex<T>& c) {
	return ghost_complex<T>(std::real(c),-std::imag(c));
}

template <typename v_t> void ghost_normalizeVector_tmpl(ghost_vec_t *vec)
{
	v_t s;
	ghost_vec_dotprod_tmpl<v_t>(vec,vec,&s);
	s = (v_t)sqrt(s);
	s = (v_t)(((v_t)1.)/s);
	vec->scale(vec,&s);

#ifdef GHOST_HAVE_OPENCL
	vec->CLupload(vec);
#endif
#ifdef GHOST_HAVE_CUDA
	vec->CUupload(vec);
#endif
}

template <typename v_t> void ghost_vec_dotprod_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ // the parallelization is done manually because reduction does not work with ghost_complex numbers
	if (vec->traits->nrows != vec2->traits->nrows) {
		WARNING_LOG("The input vectors of the dot product have different numbers of rows");
	}
	if (vec->traits->nvecs != vec2->traits->nvecs) {
		WARNING_LOG("The input vectors of the dot product have different numbers of columns");
	}
	ghost_vidx_t i,v;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	int nthreads;
#pragma omp parallel
	nthreads = ghost_ompGetNumThreads();

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
		v_t sum = 0;
		v_t partsums[nthreads];
		for (i=0; i<nthreads; i++) partsums[i] = (v_t)0.;

#pragma omp parallel for
		for (i=0; i<nr; i++) {
			partsums[ghost_ompGetThreadNum()] +=
				((v_t *)(vec->val))[i+vec->traits->nrowspadded*v]*
				conjugate(((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v]);
		}

		for (i=0; i<nthreads; i++) sum += partsums[i];

		((v_t *)res)[v] = sum;
	}

}

template <typename v_t> void ghost_vec_vaxpy_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
#pragma omp parallel for
		for (i=0; i<nr; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] += ((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v] * s[v];
		}
	}
}

template <typename v_t> void ghost_vec_vaxpby_tmpl(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b_)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;
	v_t *b = (v_t *)b_;
	ghost_vidx_t nr = MIN(vec->traits->nrows,vec2->traits->nrows);

	for (v=0; v<MIN(vec->traits->nvecs,vec2->traits->nvecs); v++) {
#pragma omp parallel for
		for (i=0; i<nr; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] = ((v_t *)(vec2->val))[i+vec->traits->nrowspadded*v] * s[v] +
				((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] * b[v];
		}
	}
}

template<typename v_t> void ghost_vec_vscale_tmpl(ghost_vec_t *vec, void *scale)
{
	ghost_vidx_t i,v;
	v_t *s = (v_t *)scale;

	for (v=0; v<vec->traits->nvecs; v++) {
#pragma omp parallel for
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[i+vec->traits->nrowspadded*v] *= s[v];
		}
	}
}

template <typename v_t> void ghost_vec_fromRand_tmpl(ghost_vec_t *vec)
{
	vec_malloc(vec);
	DEBUG_LOG(1,"Filling vector with random values");
	size_t sizeofdt = ghost_sizeofDataType(vec->traits->datatype);

	int i,v;

	// TODO fuse loops but preserve randomness

	if (vec->traits->nvecs > 1) {
#pragma omp parallel for schedule(runtime) private(i)
		for (v=0; v<vec->traits->nvecs; v++) {
			for (i=0; i<vec->traits->nrows; i++) {
				((v_t *)(vec->val))[v*vec->traits->nrowspadded+i] = (v_t)0;
			}
		}
	} else {
#pragma omp parallel for schedule(runtime)
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[i] = (v_t)0;
		}
	}

	for (v=0; v<vec->traits->nvecs; v++) {
		for (i=0; i<vec->traits->nrows; i++) {
			((v_t *)(vec->val))[v*vec->traits->nrowspadded+i] = (v_t)(rand()*1./RAND_MAX); // TODO imag
		}
	}
	vec->upload(vec);

}

extern "C" void d_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< double >(vec); }

extern "C" void s_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< float >(vec); }

extern "C" void z_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< ghost_complex<double> >(vec); }

extern "C" void c_ghost_normalizeVector(ghost_vec_t *vec)
{ return ghost_normalizeVector_tmpl< ghost_complex<float> >(vec); }

extern "C" void d_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< double >(vec,vec2,res); }

extern "C" void s_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< float >(vec,vec2,res); }

extern "C" void z_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< ghost_complex<double> >(vec,vec2,res); }

extern "C" void c_ghost_vec_dotprod(ghost_vec_t *vec, ghost_vec_t *vec2, void *res)
{ return ghost_vec_dotprod_tmpl< ghost_complex<float> >(vec,vec2,res); }

extern "C" void d_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< double >(vec, scale); }

extern "C" void s_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< float  >(vec, scale); }

extern "C" void z_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< ghost_complex<double> >(vec, scale); }

extern "C" void c_ghost_vec_vscale(ghost_vec_t *vec, void *scale)
{ return ghost_vec_vscale_tmpl< ghost_complex<float> >(vec, scale); }

extern "C" void d_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< double >(vec, vec2, scale); }

extern "C" void s_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< float >(vec, vec2, scale); }

extern "C" void z_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< ghost_complex<double> >(vec, vec2, scale); }

extern "C" void c_ghost_vec_vaxpy(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale)
{ return ghost_vec_vaxpy_tmpl< ghost_complex<float> >(vec, vec2, scale); }

extern "C" void d_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< double >(vec, vec2, scale, b); }

extern "C" void s_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< float >(vec, vec2, scale, b); }

extern "C" void z_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< ghost_complex<double> >(vec, vec2, scale, b); }

extern "C" void c_ghost_vec_vaxpby(ghost_vec_t *vec, ghost_vec_t *vec2, void *scale, void *b)
{ return ghost_vec_vaxpby_tmpl< ghost_complex<float> >(vec, vec2, scale, b); }

extern "C" void d_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< double >(vec); }

extern "C" void s_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< float >(vec); }

extern "C" void z_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< ghost_complex<double> >(vec); }

extern "C" void c_ghost_vec_fromRand(ghost_vec_t *vec)
{ return ghost_vec_fromRand_tmpl< ghost_complex<float> >(vec); }

<|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2015 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of rand.h
 */
#include "../rand.h"
#include <fstream>
#include <cassert>
#include <cstring>
#include <sys/time.h>

using namespace std;

bool pws_os::InitRandomDataFunction()
{
  // For starters, we won't rely on /dev/urandom, only on /dev/random for
  // the seed. Returning false indicates this decision.
  // Perhaps we can check for a hardware rng in future versions, and change
  // the returned value accordingly?
  return false;
}

bool pws_os::GetRandomData(void *p, unsigned long len)
{
  // Return data from /dev/urandom
  // Will not be used by PasswordSafe when InitRandomDataFunction()
  // returns false!

  ifstream is("/dev/urandom");
  if (!is)
    return false;
  return is.read(static_cast<char *>(p), len);
}

static void get_failsafe_rnd(char * &p, unsigned &slen)
{
  // This function will be called
  // iff we couldn't get a minimal amount of entropy
  // from the kernel's entropy pool.
  slen = sizeof(suseconds_t);
  p = new char[slen];
  struct timeval tv;
  gettimeofday(&tv, NULL);
  memcpy(p, &tv.tv_usec, slen);
}

void pws_os::GetRandomSeed(void *p, unsigned &slen)
{
  /**
   * Return a cryptographically strong seed
   * from /dev/random, if possible.
   *
   * When called with p == NULL, return nuber of bytes currently
   * in entropy pool.
   * To minimize TOCTTOU, we also read the data at this time,
   * and deliver it when called with non-NULL p.
   *
   * This implies a strict calling pattern, but hey, it's
   * our application...
   */
  const unsigned MAX_ENT_BITS = 256;
  static char *data = NULL;
  if (p == NULL) {
    delete[] data;
    data = NULL;

    ifstream ent_avail("/proc/sys/kernel/random/entropy_avail");
    if (ent_avail) {
      unsigned ent_bits;
      if (ent_avail >> ent_bits && ent_bits >= 32) {
        slen = ent_bits >= MAX_ENT_BITS ? MAX_ENT_BITS/8 : ent_bits/8;
        data = new char[slen];
        ifstream rnd;
        rnd.rdbuf()->pubsetbuf(0, 0);
        rnd.open("/dev/random");
        if (rnd.read(data, slen))
          return;
        else { // trouble reading
          delete[] data;
          data = NULL;
          // will get randomness from failsafe.
        }
      }
    }
    // here if we had any trouble getting data from /dev/random
    get_failsafe_rnd(data, slen);
  } else { // called with non-NULL p, just return our hard-earned entropy
    assert(data != NULL); // MUST call with p == NULL first!
    memcpy(p, data, slen);
    delete[] data;
    data = NULL;
  }
}
<commit_msg>Fix for Fedora 22, applicable to all Linux builds<commit_after>/*
* Copyright (c) 2003-2015 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of rand.h
 */
#include "../rand.h"
#include <fstream>
#include <cassert>
#include <cstring>
#include <sys/time.h>

using namespace std;

bool pws_os::InitRandomDataFunction()
{
  // For starters, we won't rely on /dev/urandom, only on /dev/random for
  // the seed. Returning false indicates this decision.
  // Perhaps we can check for a hardware rng in future versions, and change
  // the returned value accordingly?
  return false;
}

bool pws_os::GetRandomData(void *p, unsigned long len)
{
  // Return data from /dev/urandom
  // Will not be used by PasswordSafe when InitRandomDataFunction()
  // returns false!

  ifstream is("/dev/urandom");
  if (!is)
    return false;
  return is.read(static_cast<char *>(p), len).good();
}

static void get_failsafe_rnd(char * &p, unsigned &slen)
{
  // This function will be called
  // iff we couldn't get a minimal amount of entropy
  // from the kernel's entropy pool.
  slen = sizeof(suseconds_t);
  p = new char[slen];
  struct timeval tv;
  gettimeofday(&tv, NULL);
  memcpy(p, &tv.tv_usec, slen);
}

void pws_os::GetRandomSeed(void *p, unsigned &slen)
{
  /**
   * Return a cryptographically strong seed
   * from /dev/random, if possible.
   *
   * When called with p == NULL, return nuber of bytes currently
   * in entropy pool.
   * To minimize TOCTTOU, we also read the data at this time,
   * and deliver it when called with non-NULL p.
   *
   * This implies a strict calling pattern, but hey, it's
   * our application...
   */
  const unsigned MAX_ENT_BITS = 256;
  static char *data = NULL;
  if (p == NULL) {
    delete[] data;
    data = NULL;

    ifstream ent_avail("/proc/sys/kernel/random/entropy_avail");
    if (ent_avail) {
      unsigned ent_bits;
      if (ent_avail >> ent_bits && ent_bits >= 32) {
        slen = ent_bits >= MAX_ENT_BITS ? MAX_ENT_BITS/8 : ent_bits/8;
        data = new char[slen];
        ifstream rnd;
        rnd.rdbuf()->pubsetbuf(0, 0);
        rnd.open("/dev/random");
        if (rnd.read(data, slen))
          return;
        else { // trouble reading
          delete[] data;
          data = NULL;
          // will get randomness from failsafe.
        }
      }
    }
    // here if we had any trouble getting data from /dev/random
    get_failsafe_rnd(data, slen);
  } else { // called with non-NULL p, just return our hard-earned entropy
    assert(data != NULL); // MUST call with p == NULL first!
    memcpy(p, data, slen);
    delete[] data;
    data = NULL;
  }
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Camera.h"

#include "../base/Logger.h"
#include "../base/Exception.h"
#include "../base/ScopeTimer.h"
#include "../graphics/Filterfliprgb.h"

#if defined(AVG_ENABLE_1394_2)
#include "../imaging/FWCamera.h"
#endif
#ifdef AVG_ENABLE_V4L2
#include "../imaging/V4LCamera.h"
#endif
#ifdef AVG_ENABLE_CMU1394
#include "../imaging/CMUCamera.h"
#endif
#ifdef AVG_ENABLE_DSHOW
#include "../imaging/DSCamera.h"
#endif
#include "../imaging/FakeCamera.h"

#include <cstdlib>
#include <string.h>

#ifdef WIN32
#define strtoll(p, e, b) _strtoi64(p, e, b)
#endif

namespace avg {

using namespace std;

Camera::Camera(PixelFormat camPF, PixelFormat destPF, IntPoint size, float frameRate)
    : m_CamPF(camPF),
      m_DestPF(destPF),
      m_Size(size),
      m_FrameRate(frameRate)
{
//    cerr << "Camera: " << getPixelFormatString(camPF) << "-->"
//        << getPixelFormatString(destPF) << endl;
}

PixelFormat Camera::getCamPF() const
{
    return m_CamPF;
}

void Camera::setCamPF(PixelFormat pf)
{
    m_CamPF = pf;
}

PixelFormat Camera::getDestPF() const
{
    return m_DestPF;
}

static ProfilingZoneID CameraConvertProfilingZone("Camera format conversion", true);

BitmapPtr Camera::convertCamFrameToDestPF(BitmapPtr pCamBmp)
{
    ScopeTimer Timer(CameraConvertProfilingZone);
    BitmapPtr pDestBmp = BitmapPtr(new Bitmap(pCamBmp->getSize(), m_DestPF));
    pDestBmp->copyPixels(*pCamBmp);
    if (m_CamPF == R8G8B8 && m_DestPF == B8G8R8X8) {
        pDestBmp->setPixelFormat(R8G8B8X8);
        FilterFlipRGB().applyInPlace(pDestBmp);
    }

    return pDestBmp;
}

IntPoint Camera::getImgSize()
{
    return m_Size;
}

float Camera::getFrameRate() const
{
    return m_FrameRate;
}

PixelFormat Camera::fwBayerStringToPF(unsigned long reg)
{
    string sBayerFormat((char*)&reg, 4);
    if (sBayerFormat == "RGGB") {
        return BAYER8_RGGB;
    } else if (sBayerFormat == "GBRG") {
        return BAYER8_GBRG;
    } else if (sBayerFormat == "GRBG") {
        return BAYER8_GRBG;
    } else if (sBayerFormat == "BGGR") {
        return BAYER8_BGGR;
    } else if (sBayerFormat == "YYYY") {
        return I8;
    } else {
        AVG_ASSERT(false);
        return I8;
    }
}

void Camera::setImgSize(const IntPoint& size)
{
    m_Size = size;
}

string cameraFeatureToString(CameraFeature feature)
{
    switch (feature) {
        case CAM_FEATURE_BRIGHTNESS:
            return "brightness";
        case CAM_FEATURE_EXPOSURE:
            return "exposure";
        case CAM_FEATURE_SHARPNESS:
            return "sharpness";
        case CAM_FEATURE_WHITE_BALANCE:
            return "white balance";
        case CAM_FEATURE_HUE:
            return "hue";
        case CAM_FEATURE_SATURATION:
            return "saturation";
        case CAM_FEATURE_GAMMA:
            return "gamma";
        case CAM_FEATURE_SHUTTER:
            return "shutter";
        case CAM_FEATURE_GAIN:
            return "gain";
        case CAM_FEATURE_IRIS:
            return "iris";
        case CAM_FEATURE_FOCUS:
            return "focus";
        case CAM_FEATURE_TEMPERATURE:
            return "temperature";
        case CAM_FEATURE_TRIGGER:
            return "trigger";
        case CAM_FEATURE_TRIGGER_DELAY:
            return "trigger delay";
        case CAM_FEATURE_WHITE_SHADING:
            return "white shading";
        case CAM_FEATURE_ZOOM:
            return "zoom";
        case CAM_FEATURE_PAN:
            return "pan";
        case CAM_FEATURE_TILT:
            return "tilt";
        case CAM_FEATURE_OPTICAL_FILTER:
            return "optical filter";
        case CAM_FEATURE_CAPTURE_SIZE:
            return "capture size";
        case CAM_FEATURE_CAPTURE_QUALITY:
            return "capture quality";
        case CAM_FEATURE_CONTRAST:
            return "contrast";
        case CAM_FEATURE_STROBE_DURATION:
            return "strobe duration";
        default:
            return "unknown";
    }
}

CameraPtr createCamera(const string& sDriver, const string& sDevice, int unit,
        bool bFW800, const IntPoint& captureSize, PixelFormat camPF, PixelFormat destPF,
        float frameRate)
{
    CameraPtr pCamera;
    try {
        if (sDriver == "firewire") {
            char * pszErr;
            long long guid = strtoll(sDevice.c_str(), &pszErr, 16);
            if (strlen(pszErr)) {
                throw Exception(AVG_ERR_INVALID_ARGS, "'"+sDevice
                        +"' is not a valid GUID.");
            }
#if defined(AVG_ENABLE_1394_2)
            pCamera = CameraPtr(new FWCamera(guid, unit, bFW800, captureSize, camPF,
                    destPF, frameRate));
#elif defined(AVG_ENABLE_CMU1394)
            if (unit != -1) {
                throw Exception(AVG_ERR_INVALID_ARGS,
                        "camera 'unit' attribute is not supported when using the cmu firewire driver.");
            }
            pCamera = CameraPtr(new CMUCamera(guid, bFW800, captureSize, camPF, destPF,
                    frameRate));
#else
            guid = 0; // Silence compiler warning
            AVG_TRACE(Logger::WARNING, "Firewire camera specified, but firewire "
                    "support not compiled in.");
#endif
        } else if (sDriver == "video4linux") {
#if defined(AVG_ENABLE_V4L2)
            pCamera = CameraPtr(new V4LCamera(sDevice, unit, captureSize, camPF,
                    destPF, frameRate));
#else
            AVG_TRACE(Logger::WARNING, "Video4Linux camera specified, but "
                    "Video4Linux support not compiled in.");
#endif
        } else if (sDriver == "directshow") {
#if defined(AVG_ENABLE_DSHOW)
            if (unit != -1) {
                throw Exception(AVG_ERR_INVALID_ARGS,
                        "camera 'unit' attribute is not supported when using the directshow driver.");
            }
            pCamera = CameraPtr(new DSCamera(sDevice, captureSize, camPF, destPF,
                frameRate));
#else
            AVG_TRACE(Logger::WARNING, "DirectShow camera specified, but "
                    "DirectShow is only available under windows.");
#endif
        } else {
            throw Exception(AVG_ERR_INVALID_ARGS,
                    "Unable to set up camera. Camera source '"+sDriver+"' unknown.");
        }
    } catch (const Exception& e) {
        if (e.getCode() == AVG_ERR_CAMERA_NONFATAL) {
            AVG_TRACE(Logger::WARNING, e.getStr());
        } else {
            throw;
        }

    }
    if (!pCamera) {
        pCamera = CameraPtr(new FakeCamera(camPF, destPF));
    }
    return pCamera;

}

std::vector<CameraInfo> getCamerasInfos()
{
    std::vector<CameraInfo> camerasInfo;

#ifdef AVG_ENABLE_1394_2
    int amountFWCameras = FWCamera::countCameras();
    for (int i = 0; i < amountFWCameras; i++) {
        CameraInfo* camInfo = FWCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_CMU1394
    int amountCMUCameras = CMUCamera::countCameras();
    for (int i = 0; i < amountCMUCameras; i++) {
        CameraInfo* camInfo = CMUCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_DSHOW
    int amountDSCameras = DSCamera::countCameras();
    for (int i = 0; i < amountDSCameras; i++) {
        CameraInfo* camInfo = DSCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_V4L2
    int amountV4LCameras = V4LCamera::countCameras();
    for (int i = 0; i < amountV4LCameras; i++) {
        CameraInfo* camInfo = V4LCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
    return camerasInfo;
}

}
<commit_msg>egl2 branch: Fix compiler warning.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Camera.h"

#include "../base/Logger.h"
#include "../base/Exception.h"
#include "../base/ScopeTimer.h"
#include "../graphics/Filterfliprgb.h"

#if defined(AVG_ENABLE_1394_2)
#include "../imaging/FWCamera.h"
#endif
#ifdef AVG_ENABLE_V4L2
#include "../imaging/V4LCamera.h"
#endif
#ifdef AVG_ENABLE_CMU1394
#include "../imaging/CMUCamera.h"
#endif
#ifdef AVG_ENABLE_DSHOW
#include "../imaging/DSCamera.h"
#endif
#include "../imaging/FakeCamera.h"

#include <cstdlib>
#include <string.h>

#ifdef WIN32
#define strtoll(p, e, b) _strtoi64(p, e, b)
#endif

namespace avg {

using namespace std;

Camera::Camera(PixelFormat camPF, PixelFormat destPF, IntPoint size, float frameRate)
    : m_CamPF(camPF),
      m_DestPF(destPF),
      m_Size(size),
      m_FrameRate(frameRate)
{
//    cerr << "Camera: " << getPixelFormatString(camPF) << "-->"
//        << getPixelFormatString(destPF) << endl;
}

PixelFormat Camera::getCamPF() const
{
    return m_CamPF;
}

void Camera::setCamPF(PixelFormat pf)
{
    m_CamPF = pf;
}

PixelFormat Camera::getDestPF() const
{
    return m_DestPF;
}

static ProfilingZoneID CameraConvertProfilingZone("Camera format conversion", true);

BitmapPtr Camera::convertCamFrameToDestPF(BitmapPtr pCamBmp)
{
    ScopeTimer Timer(CameraConvertProfilingZone);
    BitmapPtr pDestBmp = BitmapPtr(new Bitmap(pCamBmp->getSize(), m_DestPF));
    pDestBmp->copyPixels(*pCamBmp);
    if (m_CamPF == R8G8B8 && m_DestPF == B8G8R8X8) {
        pDestBmp->setPixelFormat(R8G8B8X8);
        FilterFlipRGB().applyInPlace(pDestBmp);
    }

    return pDestBmp;
}

IntPoint Camera::getImgSize()
{
    return m_Size;
}

float Camera::getFrameRate() const
{
    return m_FrameRate;
}

PixelFormat Camera::fwBayerStringToPF(unsigned long reg)
{
    string sBayerFormat((char*)&reg, 4);
    if (sBayerFormat == "RGGB") {
        return BAYER8_RGGB;
    } else if (sBayerFormat == "GBRG") {
        return BAYER8_GBRG;
    } else if (sBayerFormat == "GRBG") {
        return BAYER8_GRBG;
    } else if (sBayerFormat == "BGGR") {
        return BAYER8_BGGR;
    } else if (sBayerFormat == "YYYY") {
        return I8;
    } else {
        AVG_ASSERT(false);
        return I8;
    }
}

void Camera::setImgSize(const IntPoint& size)
{
    m_Size = size;
}

string cameraFeatureToString(CameraFeature feature)
{
    switch (feature) {
        case CAM_FEATURE_BRIGHTNESS:
            return "brightness";
        case CAM_FEATURE_EXPOSURE:
            return "exposure";
        case CAM_FEATURE_SHARPNESS:
            return "sharpness";
        case CAM_FEATURE_WHITE_BALANCE:
            return "white balance";
        case CAM_FEATURE_HUE:
            return "hue";
        case CAM_FEATURE_SATURATION:
            return "saturation";
        case CAM_FEATURE_GAMMA:
            return "gamma";
        case CAM_FEATURE_SHUTTER:
            return "shutter";
        case CAM_FEATURE_GAIN:
            return "gain";
        case CAM_FEATURE_IRIS:
            return "iris";
        case CAM_FEATURE_FOCUS:
            return "focus";
        case CAM_FEATURE_TEMPERATURE:
            return "temperature";
        case CAM_FEATURE_TRIGGER:
            return "trigger";
        case CAM_FEATURE_TRIGGER_DELAY:
            return "trigger delay";
        case CAM_FEATURE_WHITE_SHADING:
            return "white shading";
        case CAM_FEATURE_ZOOM:
            return "zoom";
        case CAM_FEATURE_PAN:
            return "pan";
        case CAM_FEATURE_TILT:
            return "tilt";
        case CAM_FEATURE_OPTICAL_FILTER:
            return "optical filter";
        case CAM_FEATURE_CAPTURE_SIZE:
            return "capture size";
        case CAM_FEATURE_CAPTURE_QUALITY:
            return "capture quality";
        case CAM_FEATURE_CONTRAST:
            return "contrast";
        case CAM_FEATURE_STROBE_DURATION:
            return "strobe duration";
        default:
            return "unknown";
    }
}

CameraPtr createCamera(const string& sDriver, const string& sDevice, int unit,
        bool bFW800, const IntPoint& captureSize, PixelFormat camPF, PixelFormat destPF,
        float frameRate)
{
    CameraPtr pCamera;
    try {
        if (sDriver == "firewire") {
            char * pszErr;
            long long guid = strtoll(sDevice.c_str(), &pszErr, 16);
            if (strlen(pszErr)) {
                throw Exception(AVG_ERR_INVALID_ARGS, "'"+sDevice
                        +"' is not a valid GUID.");
            }
#if defined(AVG_ENABLE_1394_2)
            pCamera = CameraPtr(new FWCamera(guid, unit, bFW800, captureSize, camPF,
                    destPF, frameRate));
#elif defined(AVG_ENABLE_CMU1394)
            if (unit != -1) {
                throw Exception(AVG_ERR_INVALID_ARGS,
                        "camera 'unit' attribute is not supported when using the cmu firewire driver.");
            }
            pCamera = CameraPtr(new CMUCamera(guid, bFW800, captureSize, camPF, destPF,
                    frameRate));
#else
            (void)guid; // Silence compiler warning
            AVG_TRACE(Logger::WARNING, "Firewire camera specified, but firewire "
                    "support not compiled in.");
#endif
        } else if (sDriver == "video4linux") {
#if defined(AVG_ENABLE_V4L2)
            pCamera = CameraPtr(new V4LCamera(sDevice, unit, captureSize, camPF,
                    destPF, frameRate));
#else
            AVG_TRACE(Logger::WARNING, "Video4Linux camera specified, but "
                    "Video4Linux support not compiled in.");
#endif
        } else if (sDriver == "directshow") {
#if defined(AVG_ENABLE_DSHOW)
            if (unit != -1) {
                throw Exception(AVG_ERR_INVALID_ARGS,
                        "camera 'unit' attribute is not supported when using the directshow driver.");
            }
            pCamera = CameraPtr(new DSCamera(sDevice, captureSize, camPF, destPF,
                frameRate));
#else
            AVG_TRACE(Logger::WARNING, "DirectShow camera specified, but "
                    "DirectShow is only available under windows.");
#endif
        } else {
            throw Exception(AVG_ERR_INVALID_ARGS,
                    "Unable to set up camera. Camera source '"+sDriver+"' unknown.");
        }
    } catch (const Exception& e) {
        if (e.getCode() == AVG_ERR_CAMERA_NONFATAL) {
            AVG_TRACE(Logger::WARNING, e.getStr());
        } else {
            throw;
        }

    }
    if (!pCamera) {
        pCamera = CameraPtr(new FakeCamera(camPF, destPF));
    }
    return pCamera;

}

std::vector<CameraInfo> getCamerasInfos()
{
    std::vector<CameraInfo> camerasInfo;

#ifdef AVG_ENABLE_1394_2
    int amountFWCameras = FWCamera::countCameras();
    for (int i = 0; i < amountFWCameras; i++) {
        CameraInfo* camInfo = FWCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_CMU1394
    int amountCMUCameras = CMUCamera::countCameras();
    for (int i = 0; i < amountCMUCameras; i++) {
        CameraInfo* camInfo = CMUCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_DSHOW
    int amountDSCameras = DSCamera::countCameras();
    for (int i = 0; i < amountDSCameras; i++) {
        CameraInfo* camInfo = DSCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
#ifdef AVG_ENABLE_V4L2
    int amountV4LCameras = V4LCamera::countCameras();
    for (int i = 0; i < amountV4LCameras; i++) {
        CameraInfo* camInfo = V4LCamera::getCameraInfos(i);
        if (camInfo != NULL) {
            camInfo->checkAddBayer8();
            camerasInfo.push_back(*camInfo);
        }
    }
#endif
    return camerasInfo;
}

}
<|endoftext|>


<commit_before>/*
 * ceph_fs.cc - Some Ceph functions that are shared between kernel space and
 * user space.
 *
 */

/*
 * Some non-inline ceph helpers
 */
#include "types.h"

/*
 * return true if @layout appears to be valid
 */
int ceph_file_layout_is_valid(const struct ceph_file_layout *layout)
{
	__u32 su = le32_to_cpu(layout->fl_stripe_unit);
	__u32 sc = le32_to_cpu(layout->fl_stripe_count);
	__u32 os = le32_to_cpu(layout->fl_object_size);

	/* stripe unit, object size must be non-zero, 64k increment */
	if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1)))
		return 0;
	if (!os || (os & (CEPH_MIN_STRIPE_UNIT-1)))
		return 0;
	/* object size must be a multiple of stripe unit */
	if (os < su || os % su)
		return 0;
	/* stripe count must be non-zero */
	if (!sc)
		return 0;
	return 1;
}

int ceph_flags_to_mode(int flags)
{
	int mode;

#ifdef O_DIRECTORY  /* fixme */
	if ((flags & O_DIRECTORY) == O_DIRECTORY)
		return CEPH_FILE_MODE_PIN;
#endif
	if ((flags & O_APPEND) == O_APPEND)
		flags |= O_WRONLY;

	if ((flags & O_ACCMODE) == O_RDWR)
		mode = CEPH_FILE_MODE_RDWR;
	else if ((flags & O_ACCMODE) == O_WRONLY)
		mode = CEPH_FILE_MODE_WR;
	else
		mode = CEPH_FILE_MODE_RD;

#ifdef O_LAZY
	if (flags & O_LAZY)
		mode |= CEPH_FILE_MODE_LAZY;
#endif

	return mode;
}

int ceph_caps_for_mode(int mode)
{
	int caps = CEPH_CAP_PIN;

	if (mode & CEPH_FILE_MODE_RD)
		caps |= CEPH_CAP_FILE_SHARED |
			CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE;
	if (mode & CEPH_FILE_MODE_WR)
		caps |= CEPH_CAP_FILE_EXCL |
			CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |
			CEPH_CAP_AUTH_SHARED | CEPH_CAP_AUTH_EXCL |
			CEPH_CAP_XATTR_SHARED | CEPH_CAP_XATTR_EXCL;
	if (mode & CEPH_FILE_MODE_LAZY)
		caps |= CEPH_CAP_FILE_LAZYIO;

	return caps;
}
<commit_msg>mds: fix O_APPEND file mode calculation<commit_after>/*
 * ceph_fs.cc - Some Ceph functions that are shared between kernel space and
 * user space.
 *
 */

/*
 * Some non-inline ceph helpers
 */
#include "types.h"

/*
 * return true if @layout appears to be valid
 */
int ceph_file_layout_is_valid(const struct ceph_file_layout *layout)
{
	__u32 su = le32_to_cpu(layout->fl_stripe_unit);
	__u32 sc = le32_to_cpu(layout->fl_stripe_count);
	__u32 os = le32_to_cpu(layout->fl_object_size);

	/* stripe unit, object size must be non-zero, 64k increment */
	if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1)))
		return 0;
	if (!os || (os & (CEPH_MIN_STRIPE_UNIT-1)))
		return 0;
	/* object size must be a multiple of stripe unit */
	if (os < su || os % su)
		return 0;
	/* stripe count must be non-zero */
	if (!sc)
		return 0;
	return 1;
}

int ceph_flags_to_mode(int flags)
{
	int mode;

#ifdef O_DIRECTORY  /* fixme */
	if ((flags & O_DIRECTORY) == O_DIRECTORY)
		return CEPH_FILE_MODE_PIN;
#endif
	if ((flags & O_APPEND) &&
	    (flags & O_ACCMODE) == 0)
		flags |= O_WRONLY;

	if ((flags & O_ACCMODE) == O_RDWR)
		mode = CEPH_FILE_MODE_RDWR;
	else if ((flags & O_ACCMODE) == O_WRONLY)
		mode = CEPH_FILE_MODE_WR;
	else
		mode = CEPH_FILE_MODE_RD;

#ifdef O_LAZY
	if (flags & O_LAZY)
		mode |= CEPH_FILE_MODE_LAZY;
#endif

	return mode;
}

int ceph_caps_for_mode(int mode)
{
	int caps = CEPH_CAP_PIN;

	if (mode & CEPH_FILE_MODE_RD)
		caps |= CEPH_CAP_FILE_SHARED |
			CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE;
	if (mode & CEPH_FILE_MODE_WR)
		caps |= CEPH_CAP_FILE_EXCL |
			CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |
			CEPH_CAP_AUTH_SHARED | CEPH_CAP_AUTH_EXCL |
			CEPH_CAP_XATTR_SHARED | CEPH_CAP_XATTR_EXCL;
	if (mode & CEPH_FILE_MODE_LAZY)
		caps |= CEPH_CAP_FILE_LAZYIO;

	return caps;
}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/io/stream_base.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/blob.hpp"
#include <boost/scoped_array.hpp>
#include <cstdlib>

using namespace flusspferd;
using namespace flusspferd::io;

stream_base::stream_base(object const &o, std::streambuf *p)
  : native_object_base(o), streambuf(p)
{
  register_native_method("readWhole", &stream_base::read_whole);
  register_native_method("read", &stream_base::read);
  register_native_method("readWholeBlob", &stream_base::read_whole_blob);
  register_native_method("readBlob", &stream_base::read_blob);
  register_native_method("write", &stream_base::write);
  register_native_method("print", &stream_base::print);
  register_native_method("flush", &stream_base::flush);

  define_property("fieldSeparator", string(" "));
  define_property("recordSeparator", string("\n"));
  define_property("autoflush", false);
}

stream_base::~stream_base()
{}

void stream_base::set_streambuf(std::streambuf *p) {
  streambuf = p;
}

std::streambuf *stream_base::get_streambuf() {
  return streambuf;
}

object stream_base::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object();

  create_native_method(proto, "readWhole", 0);
  create_native_method(proto, "read", 1);
  create_native_method(proto, "readWholeBlob", 0);
  create_native_method(proto, "readBlob", 1);
  create_native_method(proto, "write", 1);
  create_native_method(proto, "print", 0);
  create_native_method(proto, "flush", 0);

  return proto;
}

string stream_base::read_whole() {
  std::string data;
  char buf[4096];

  std::streamsize length;

  do {
    length = streambuf->sgetn(buf, sizeof(buf));
    if (length < 0)
      length = 0;
    data.append(buf, length);
  } while (length > 0);

  return string(data);
}

object stream_base::read_whole_blob() {
  unsigned const N = 4096;

  std::vector<char> data;

  std::streamsize length;

  do {
    data.resize(data.size() + N);
    length = streambuf->sgetn(&data[data.size() - N], N);
    if (length < 0)
      length = 0;
    data.resize(data.size() - N + length);
  } while (length > 0);

  return create_native_object<blob>(
      object(), (unsigned char const *)&data[0], data.size());
}

string stream_base::read(unsigned size) {
  if (!size)
    size = 4096;

  boost::scoped_array<char> buf(new char[size + 1]);

  std::streamsize length = streambuf->sgetn(buf.get(), size);
  if (length < 0)
    length = 0;
  buf[length] = '\0';

  return string(buf.get());
}

object stream_base::read_blob(unsigned size) {
  if (!size)
    size = 4096;

  boost::scoped_array<char> buf(new char[size]);

  std::streamsize length = streambuf->sgetn(buf.get(), size);
  if (length < 0)
    length = 0;

  return create_native_object<blob>(
      object(),
      (unsigned char const *) buf.get(),
      length);
}

void stream_base::write(value const &data) {
  if (data.is_string()) {
    string text = data.get_string();
    char const *str = text.c_str();
    streambuf->sputn(text.c_str(), std::strlen(str));
  } else if (data.is_object()) {
    native_object_base *ptr = native_object_base::get_native(data.get_object());
    blob &b = dynamic_cast<blob&>(*ptr);
    streambuf->sputn((char const*) b.get_data(), b.size());
  }
  //TODO slow?
  if (get_property("autoflush").to_boolean())
    flush();
}

void stream_base::print(call_context &x) {
  local_root_scope scope;

  value delim_v = get_property("fieldSeparator");
  string delim;
  if (!delim_v.is_void_or_null())
    delim = delim_v.to_string();

  std::size_t n = x.arg.size();
  for (std::size_t i = 0; i < n; ++i) {
    write(x.arg[i].to_string());
    if (i < n - 1)
      write(delim);
  }

  value record_v = get_property("recordSeparator");
  if (!record_v.is_void_or_null())
    write(record_v.to_string());

  flush();
}

void stream_base::flush() {
  streambuf->pubsync();
}
<commit_msg>IO: throw exception in write<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/io/stream_base.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/blob.hpp"
#include <boost/scoped_array.hpp>
#include <cstdlib>

using namespace flusspferd;
using namespace flusspferd::io;

stream_base::stream_base(object const &o, std::streambuf *p)
  : native_object_base(o), streambuf(p)
{
  register_native_method("readWhole", &stream_base::read_whole);
  register_native_method("read", &stream_base::read);
  register_native_method("readWholeBlob", &stream_base::read_whole_blob);
  register_native_method("readBlob", &stream_base::read_blob);
  register_native_method("write", &stream_base::write);
  register_native_method("print", &stream_base::print);
  register_native_method("flush", &stream_base::flush);

  define_property("fieldSeparator", string(" "));
  define_property("recordSeparator", string("\n"));
  define_property("autoflush", false);
}

stream_base::~stream_base()
{}

void stream_base::set_streambuf(std::streambuf *p) {
  streambuf = p;
}

std::streambuf *stream_base::get_streambuf() {
  return streambuf;
}

object stream_base::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object();

  create_native_method(proto, "readWhole", 0);
  create_native_method(proto, "read", 1);
  create_native_method(proto, "readWholeBlob", 0);
  create_native_method(proto, "readBlob", 1);
  create_native_method(proto, "write", 1);
  create_native_method(proto, "print", 0);
  create_native_method(proto, "flush", 0);

  return proto;
}

string stream_base::read_whole() {
  std::string data;
  char buf[4096];

  std::streamsize length;

  do {
    length = streambuf->sgetn(buf, sizeof(buf));
    if (length < 0)
      length = 0;
    data.append(buf, length);
  } while (length > 0);

  return string(data);
}

object stream_base::read_whole_blob() {
  unsigned const N = 4096;

  std::vector<char> data;

  std::streamsize length;

  do {
    data.resize(data.size() + N);
    length = streambuf->sgetn(&data[data.size() - N], N);
    if (length < 0)
      length = 0;
    data.resize(data.size() - N + length);
  } while (length > 0);

  return create_native_object<blob>(
      object(), (unsigned char const *)&data[0], data.size());
}

string stream_base::read(unsigned size) {
  if (!size)
    size = 4096;

  boost::scoped_array<char> buf(new char[size + 1]);

  std::streamsize length = streambuf->sgetn(buf.get(), size);
  if (length < 0)
    length = 0;
  buf[length] = '\0';

  return string(buf.get());
}

object stream_base::read_blob(unsigned size) {
  if (!size)
    size = 4096;

  boost::scoped_array<char> buf(new char[size]);

  std::streamsize length = streambuf->sgetn(buf.get(), size);
  if (length < 0)
    length = 0;

  return create_native_object<blob>(
      object(),
      (unsigned char const *) buf.get(),
      length);
}

void stream_base::write(value const &data) {
  if (data.is_string()) {
    string text = data.get_string();
    char const *str = text.c_str();
    streambuf->sputn(text.c_str(), std::strlen(str));
  } else if (data.is_object()) {
    native_object_base *ptr = native_object_base::get_native(data.get_object());
    blob &b = dynamic_cast<blob&>(*ptr);
    streambuf->sputn((char const*) b.get_data(), b.size());
  } else {
    throw exception("Cannot write non-object non-string value to Stream");
  }
  //TODO slow?
  if (get_property("autoflush").to_boolean())
    flush();
}

void stream_base::print(call_context &x) {
  local_root_scope scope;

  value delim_v = get_property("fieldSeparator");
  string delim;
  if (!delim_v.is_void_or_null())
    delim = delim_v.to_string();

  std::size_t n = x.arg.size();
  for (std::size_t i = 0; i < n; ++i) {
    write(x.arg[i].to_string());
    if (i < n - 1)
      write(delim);
  }

  value record_v = get_property("recordSeparator");
  if (!record_v.is_void_or_null())
    write(record_v.to_string());

  flush();
}

void stream_base::flush() {
  streambuf->pubsync();
}
<|endoftext|>


<commit_before>#ifndef PARSE_LITERAL_HPP_
#define PARSE_LITERAL_HPP_

#include "symbol.hpp"
#include "parse_error.hpp"

#include <boost/optional.hpp>

namespace parse_literal_detail
{

inline bool is_digit(char c)
{
    return '0' <= c && c <= '9';
}

}

template <class State>
boost::optional<symbol> parse_literal(State& state)
{
    using namespace parse_literal_detail;

    if(state.empty())
        return boost::none;
    else if(state.front() == '"')
    {
        source_position begin = state.position();
        symbol::literal result; // std::string

        state.pop_front();
        while(true)
        {
            if(state.empty() || state.front() == '\n')
                throw parse_error("unmatched \"", begin, state.file());
            if(state.front() == '"')
                break;
            else
            {
                result += state.front();
                state.pop_front();
            }
        }

        state.pop_front();

        source_position end = state.position();
        return symbol{result, source_range{begin, end, state.file()}};
    }
    else if(is_digit(state.front()))
    {
        source_position begin = state.position();
        symbol::literal result; // std::string
        result += state.front();

        state.pop_front();
        while(!state.empty() && is_digit(state.front()))
        {
            result += state.front();
            state.pop_front();
        }
        source_position end = state.position();
        return symbol{result, source_range{begin, end, state.file()}};
    }
    else
        return boost::none;
}

#endif

<commit_msg>add missing move<commit_after>#ifndef PARSE_LITERAL_HPP_
#define PARSE_LITERAL_HPP_

#include "symbol.hpp"
#include "parse_error.hpp"

#include <boost/optional.hpp>

namespace parse_literal_detail
{

inline bool is_digit(char c)
{
    return '0' <= c && c <= '9';
}

}

template <class State>
boost::optional<symbol> parse_literal(State& state)
{
    using namespace parse_literal_detail;

    if(state.empty())
        return boost::none;
    else if(state.front() == '"')
    {
        source_position begin = state.position();
        symbol::literal result; // std::string

        state.pop_front();
        while(true)
        {
            if(state.empty() || state.front() == '\n')
                throw parse_error("unmatched \"", begin, state.file());
            if(state.front() == '"')
                break;
            else
            {
                result += state.front();
                state.pop_front();
            }
        }

        state.pop_front();

        source_position end = state.position();
        return symbol{std::move(result), source_range{begin, end, state.file()}};
    }
    else if(is_digit(state.front()))
    {
        source_position begin = state.position();
        symbol::literal result; // std::string
        result += state.front();

        state.pop_front();
        while(!state.empty() && is_digit(state.front()))
        {
            result += state.front();
            state.pop_front();
        }
        source_position end = state.position();
        return symbol{std::move(result), source_range{begin, end, state.file()}};
    }
    else
        return boost::none;
}

#endif

<|endoftext|>


<commit_before>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include "compare.h"
#include "keyword.h"
#include "token.h"
#include "symbol.h"

namespace sqltoast {

kw_jump_table_t _init_kw_jump_table(char lead_char) {
    kw_jump_table_t t;

    switch (lead_char) {
        case 'a':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_AUTHORIZATION, SYMBOL_AUTHORIZATION, "AUTHORIZATION"));
            return t;
        case 'c':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CREATE, SYMBOL_CREATE, "CREATE"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CHARACTER, SYMBOL_CHARACTER, "CHARACTER"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CASCADE, SYMBOL_CASCADE, "CASCADE"));
            return t;
        case 'd':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_DEFAULT, SYMBOL_DEFAULT, "DEFAULT"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_DROP, SYMBOL_DROP, "DROP"));
            return t;
        case 'r':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_RESTRICT, SYMBOL_RESTRICT, "RESTRICT"));
            return t;
        case 's':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_SCHEMA, SYMBOL_SCHEMA, "SCHEMA"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_SET, SYMBOL_SET, "SET"));
            return t;
    }
    return t;
}

kw_jump_table_t kw_jump_tables::a = _init_kw_jump_table('a');
kw_jump_table_t kw_jump_tables::c = _init_kw_jump_table('c');
kw_jump_table_t kw_jump_tables::d = _init_kw_jump_table('d');
kw_jump_table_t kw_jump_tables::r = _init_kw_jump_table('r');
kw_jump_table_t kw_jump_tables::s = _init_kw_jump_table('s');

bool token_keyword(parse_context_t& ctx) {
    kw_jump_table_t* jump_tbl;
    switch (*ctx.cursor) {
        case 'a':
        case 'A':
            jump_tbl = &kw_jump_tables::a;
            break;
        case 'c':
        case 'C':
            jump_tbl = &kw_jump_tables::c;
            break;
        case 'd':
        case 'D':
            jump_tbl = &kw_jump_tables::d;
            break;
        case 'r':
        case 'R':
            jump_tbl = &kw_jump_tables::r;
            break;
        case 's':
        case 'S':
            jump_tbl = &kw_jump_tables::s;
            break;
        default:
            return false;
    }

    parse_cursor_t start = ctx.cursor;

    for (auto entry : *jump_tbl) {
        const std::string to_end(parse_position_t(ctx.cursor), ctx.end_pos);
        if (ci_find_substr(to_end, entry.kw_str) != -1) {
            token_t tok(TOKEN_TYPE_KEYWORD, entry.symbol, start, parse_position_t(ctx.cursor));
            ctx.push_token(tok);
            ctx.cursor += entry.kw_str.size();
            return true;
        }
    }
    return false;
}

} // namespace sqltoast
<commit_msg>ensure keyword token compares lengths of lexeme<commit_after>/*
 * Use and distribution licensed under the Apache license version 2.
 *
 * See the COPYING file in the root project directory for full text.
 */

#include "compare.h"
#include "keyword.h"
#include "token.h"
#include "symbol.h"

namespace sqltoast {

kw_jump_table_t _init_kw_jump_table(char lead_char) {
    kw_jump_table_t t;

    switch (lead_char) {
        case 'a':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_AUTHORIZATION, SYMBOL_AUTHORIZATION, "AUTHORIZATION"));
            return t;
        case 'c':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CREATE, SYMBOL_CREATE, "CREATE"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CHARACTER, SYMBOL_CHARACTER, "CHARACTER"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_CASCADE, SYMBOL_CASCADE, "CASCADE"));
            return t;
        case 'd':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_DEFAULT, SYMBOL_DEFAULT, "DEFAULT"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_DROP, SYMBOL_DROP, "DROP"));
            return t;
        case 'r':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_RESTRICT, SYMBOL_RESTRICT, "RESTRICT"));
            return t;
        case 's':
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_SCHEMA, SYMBOL_SCHEMA, "SCHEMA"));
            t.emplace_back(kw_jump_table_entry_t(KEYWORD_SET, SYMBOL_SET, "SET"));
            return t;
    }
    return t;
}

kw_jump_table_t kw_jump_tables::a = _init_kw_jump_table('a');
kw_jump_table_t kw_jump_tables::c = _init_kw_jump_table('c');
kw_jump_table_t kw_jump_tables::d = _init_kw_jump_table('d');
kw_jump_table_t kw_jump_tables::r = _init_kw_jump_table('r');
kw_jump_table_t kw_jump_tables::s = _init_kw_jump_table('s');

bool token_keyword(parse_context_t& ctx) {
    kw_jump_table_t* jump_tbl;
    switch (*ctx.cursor) {
        case 'a':
        case 'A':
            jump_tbl = &kw_jump_tables::a;
            break;
        case 'c':
        case 'C':
            jump_tbl = &kw_jump_tables::c;
            break;
        case 'd':
        case 'D':
            jump_tbl = &kw_jump_tables::d;
            break;
        case 'r':
        case 'R':
            jump_tbl = &kw_jump_tables::r;
            break;
        case 's':
        case 'S':
            jump_tbl = &kw_jump_tables::s;
            break;
        default:
            return false;
    }

    parse_position_t start = ctx.cursor;
    parse_cursor_t end = ctx.cursor;
    // Find the next space character...
    while (end != ctx.end_pos && ! std::isspace(*end))
        end++;

    const std::string lexeme(start, parse_position_t(end));
    size_t lexeme_len = lexeme.size();
    for (auto entry : *jump_tbl) {
        size_t entry_len = entry.kw_str.size();
        if (lexeme_len != entry_len)
            continue;
        if (ci_find_substr(lexeme, entry.kw_str) == 0) {
            token_t tok(TOKEN_TYPE_KEYWORD, entry.symbol, start, end);
            ctx.push_token(tok);
            ctx.cursor += entry_len;
            return true;
        }
    }
    return false;
}

} // namespace sqltoast
<|endoftext|>