<commit_before>/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <time.h>
#include "ir.h"
#include "lib/log.h"

class Visitor::ChangeTracker {
    // FIXME -- this code is really incomprehensible due to all the pairs/first/second stuff
    // unfortunatelly maps use pairs all over the place, which is where they come from.
    typedef unordered_map<const IR::Node *, std::pair<bool, const IR::Node *>>  visited_t;
    visited_t           visited;

 public:
    struct change_t {
        bool                                    valid;
        std::pair<visited_t::iterator, bool>    state;  // result of visited.emplace
        change_t() : valid(false) {}
        change_t(visited_t *visited, const IR::Node *n) : valid(true),
            state(visited->emplace(n, std::make_pair(false, n))) {
                if (!state.second && !state.first->second.first)
                    BUG("IR loop detected "); }
        explicit operator bool() { return valid; }
        bool done() { return !state.second; }
        const IR::Node *orig() { return state.first->first; }
        const IR::Node *result() { return state.first->second.second; }
    };
    bool done(const IR::Node *n) const { return visited.count(n) && visited.at(n).first; }
    const IR::Node *result(IR::Node *n) const { return visited.at(n).second; }
    change_t track(const IR::Node *n) { return change_t(&visited, n); }
    void start(change_t &change) { change.state.first->second.first = false; }
    bool finish(change_t &change, const IR::Node *orig, const IR::Node *final) {
        if (!change.valid || (change.state.first = visited.find(orig)) == visited.end())
            BUG("visitor state tracker corrupted");
        change.state.first->second.first = true;
        if (!final || *final != *orig) {
            change.state.first->second.second = final;
            visited.emplace(final, std::make_pair(true, final));
            return true;
        } else {
            // FIXME -- not safe if the visitor resurrects the node (which it shouldn't)
            // if (final && final->id == IR::Node::currentId - 1)
            //     --IR::Node::currentId;
            return false; } }
    const IR::Node *result(const IR::Node *n) const {
        auto it = visited.find(n);
        if (it == visited.end())
            return n;
        if (!it->second.first) BUG("IR loop detected");
        return it->second.second; }
    void revisit_visited() {
        for (auto it = visited.begin(); it != visited.end();) {
            if (it->second.first)
                it = visited.erase(it);
            else
                ++it; } }
};

Visitor::profile_t Visitor::init_apply(const IR::Node *root) {
    if (ctxt) BUG("previous use of visitor did not clean up properly");
    ctxt = nullptr;
    if (joinFlows) init_join_flows(root);
    return profile_t(*this);
}
Visitor::profile_t Modifier::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new ChangeTracker();
    return rv; }
Visitor::profile_t Inspector::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new visited_t();
    return rv; }
Visitor::profile_t Transform::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new ChangeTracker();
    return rv; }
void Visitor::end_apply() {}
void Visitor::end_apply(const IR::Node*) {}

static indent_t profile_indent;
Visitor::profile_t::profile_t(Visitor &v_) : v(v_) {
    struct timespec ts;
#ifdef CLOCK_MONOTONIC
    clock_gettime(CLOCK_MONOTONIC, &ts);
#else
    // FIXME -- figure out how to do this on OSX/Mach
    ts.tv_sec = ts.tv_nsec = 0;
#endif
    start = ts.tv_sec*1000000000UL + ts.tv_nsec + 1;
    assert(start);
    ++profile_indent;
}
Visitor::profile_t::profile_t(profile_t &&a) : v(a.v), start(a.start) {
    a.start = 0;
}
Visitor::profile_t::~profile_t() {
    if (start) {
        v.end_apply();
        --profile_indent;
        struct timespec ts;
#ifdef CLOCK_MONOTONIC
        clock_gettime(CLOCK_MONOTONIC, &ts);
#else
        // FIXME -- figure out how to do this on OSX/Mach
        ts.tv_sec = ts.tv_nsec = 0;
#endif
        uint64_t end = ts.tv_sec*1000000000UL + ts.tv_nsec + 1;
        LOG1(profile_indent << v.name() << ' ' << (end-start)/1000.0 << " usec"); }
}

void Visitor::print_context() const {
    std::ostream &out = std::cout;
    out << "Context:" << std::endl;
    auto ctx = getContext();
    if (ctx == nullptr) {
        out << "<nullptr>" << std::endl;
        return;
    }

    while (ctx != nullptr) {
        out << ctx->node << " (" << ctx->original << ")" << std::endl;
        ctx = ctx->parent;
    }
}

void Visitor::visitor_const_error() {
    BUG("const Visitor wants to change IR"); }
void Modifier::visitor_const_error() {
    BUG("Modifier called const visit function -- missing template "
                            "instantiation in gen-tree-macro.h?"); }
void Transform::visitor_const_error() {
    BUG("Transform called const visit function -- missing template "
                            "instantiation in gen-tree-macro.h?"); }

struct PushContext {
    Visitor::Context current;
    const Visitor::Context *&stack;
    PushContext(const Visitor::Context *&stck, const IR::Node *node) : stack(stck) {
        current.parent = stack;
        current.node = current.original = node;
        current.child_index = 0;
        current.depth = stack ? stack->depth+1 : 1;
        assert(current.depth < 10000);    // stack overflow?
        stack = &current; }
    ~PushContext() { stack = current.parent; }
};

namespace {
class ForwardChildren : public Visitor {
    const ChangeTracker &visited;
    const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) {
        return visited.result(n); }
 public:
    explicit ForwardChildren(const ChangeTracker &v) : visited(v) {}
};
}

const IR::Node *Modifier::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n) {
        PushContext local(ctxt, n);
        auto track = visited->track(n);
        if (track.done() && visitDagOnce) {
            track.orig()->apply_visitor_revisit(*this, track.result());
            n = track.result();
        } else {
            visited->start(track);
            IR::Node *copy = n->clone();
            local.current.node = copy;
            if (visitDagOnce && !dontForwardChildrenBeforePreorder) {
                ForwardChildren forward_children(*visited);
                copy->visit_children(forward_children); }
            if (copy->apply_visitor_preorder(*this)) {
                copy->visit_children(*this);
                copy->apply_visitor_postorder(*this); }
            if (visited->finish(track, n, copy))
                (n = copy)->validate(); } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

const IR::Node *Inspector::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n && !join_flows(n)) {
        PushContext local(ctxt, n);
        auto vp = visited->emplace(n, false);
        if (!vp.second && !vp.first->second)
            BUG("IR loop detected");
        if (!vp.second && visitDagOnce) {
            n->apply_visitor_revisit(*this);
        } else {
            vp.first->second = false;
            if (n->apply_visitor_preorder(*this)) {
                n->visit_children(*this);
                n->apply_visitor_postorder(*this); }
            vp.first = visited->find(n);  // iterator may have been invalidated
            if (vp.first == visited->end())
                BUG("visitor state tracker corrupted");
            vp.first->second = true; } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

const IR::Node *Transform::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n) {
        PushContext local(ctxt, n);
        auto track = visited->track(n);
        if (track.done() && visitDagOnce) {
            track.orig()->apply_visitor_revisit(*this, track.result());
            n = track.result();
        } else {
            visited->start(track);
            auto copy = n->clone();
            local.current.node = copy;
            if (visitDagOnce && !dontForwardChildrenBeforePreorder) {
                ForwardChildren forward_children(*visited);
                copy->visit_children(forward_children); }
            prune_flag = false;
            auto preorder_result = copy->apply_visitor_preorder(*this);
            ChangeTracker::change_t preorder_result_track;
            assert(preorder_result != n);  // should never happen
            auto final = preorder_result;
            if (preorder_result != copy) {
                // FIXME -- not safe if the visitor resurrects the node (which it shouldn't)
                // if (copy->id == IR::Node::currentId - 1)
                //     --IR::Node::currentId;
                if (!preorder_result) {
                    prune_flag = true;
                } else if (visited->done(preorder_result) && visitDagOnce) {
                    final = visited->result(preorder_result);
                    prune_flag = true;
                } else {
                    preorder_result_track = visited->track(preorder_result);
                    visited->start(preorder_result_track);
                    local.current.node = copy = preorder_result->clone(); } }
            if (!prune_flag) {
                copy->visit_children(*this);
                final = copy->apply_visitor_postorder(*this); }
            if (final && final != preorder_result && *final == *preorder_result)
                final = preorder_result;
            if (visited->finish(track, n, final) && (n = final))
                final->validate();
            if (preorder_result_track)
                visited->finish(preorder_result_track, preorder_result, final); } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

void Inspector::revisit_visited() {
    for (auto it = visited->begin(); it != visited->end();) {
        if (it->second)
            it = visited->erase(it);
        else
            ++it; }
}
void Modifier::revisit_visited() {
    visited->revisit_visited();
}
void Transform::revisit_visited() {
    visited->revisit_visited();
}

#define DEFINE_VISIT_FUNCTIONS(CLASS, BASE)                                             \
bool Modifier::preorder(IR::CLASS *n) {                                                 \
    return preorder(static_cast<IR::BASE *>(n)); }                                      \
void Modifier::postorder(IR::CLASS *n) {                                                \
    postorder(static_cast<IR::BASE *>(n)); }                                            \
void Modifier::revisit(const IR::CLASS *o, const IR::CLASS *n) {                        \
    revisit(static_cast<const IR::BASE *>(o), static_cast<const IR::BASE *>(n)); }      \
bool Inspector::preorder(const IR::CLASS *n) {                                          \
    return preorder(static_cast<const IR::BASE *>(n)); }                                \
void Inspector::postorder(const IR::CLASS *n) {                                         \
    postorder(static_cast<const IR::BASE *>(n)); }                                      \
void Inspector::revisit(const IR::CLASS *n) {                                           \
    revisit(static_cast<const IR::BASE *>(n)); }                                        \
const IR::Node *Transform::preorder(IR::CLASS *n) {                                     \
    return preorder(static_cast<IR::BASE *>(n)); }                                      \
const IR::Node *Transform::postorder(IR::CLASS *n) {                                    \
    return postorder(static_cast<IR::BASE *>(n)); }                                     \
void Transform::revisit(const IR::CLASS *o, const IR::Node *n) {                        \
    return revisit(static_cast<const IR::BASE *>(o), n); }                              \

IRNODE_ALL_SUBCLASSES(DEFINE_VISIT_FUNCTIONS)

class SetupJoinPoints : public Inspector {
    map<const IR::Node *, std::pair<ControlFlowVisitor *, int>> &join_points;
    bool preorder(const IR::Node *n) override {
        return ++join_points[n].second == 1; }
 public:
    explicit SetupJoinPoints(decltype(join_points) &fjp)
    : join_points(fjp) { visitDagOnce = false; }
};

void ControlFlowVisitor::init_join_flows(const IR::Node *root) {
    if (!dynamic_cast<Inspector *>(this))
        BUG("joinFlows only works for Inspector passes currently, not Modifier or Transform");
    if (flow_join_points)
        flow_join_points->clear();
    else
        flow_join_points = new std::remove_reference<decltype(*flow_join_points)>::type;
    root->apply(SetupJoinPoints(*flow_join_points));
    for (auto it = flow_join_points->begin(); it != flow_join_points->end(); ) {
        if (it->second.second > 1 && !filter_join_point(it->first)) {
            ++it;
        } else {
            it = flow_join_points->erase(it); } }
}

bool ControlFlowVisitor::join_flows(const IR::Node *n) {
    if (flow_join_points && flow_join_points->count(n)) {
        auto &status = flow_join_points->at(n);
        if (!--status.second) {
            flow_merge(*status.first);
            return false;
        } else if (status.first) {
            status.first->flow_merge(*this);
            return true;
        } else {
            status.first = clone();
            return true; } }
    return false;
}

void Inspector::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Inspector *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}
void Modifier::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Modifier *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}
void Transform::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Transform *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}

ControlFlowVisitor &ControlFlowVisitor::flow_clone() {
    auto *rv = clone();
    rv->check_clone(this);
    return *rv;
}
<commit_msg>Work around dynamic_cast bug in clang<commit_after>/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <time.h>
#include "ir.h"
#include "lib/log.h"

class Visitor::ChangeTracker {
    // FIXME -- this code is really incomprehensible due to all the pairs/first/second stuff
    // unfortunatelly maps use pairs all over the place, which is where they come from.
    typedef unordered_map<const IR::Node *, std::pair<bool, const IR::Node *>>  visited_t;
    visited_t           visited;

 public:
    struct change_t {
        bool                                    valid;
        std::pair<visited_t::iterator, bool>    state;  // result of visited.emplace
        change_t() : valid(false) {}
        change_t(visited_t *visited, const IR::Node *n) : valid(true),
            state(visited->emplace(n, std::make_pair(false, n))) {
                if (!state.second && !state.first->second.first)
                    BUG("IR loop detected "); }
        explicit operator bool() { return valid; }
        bool done() { return !state.second; }
        const IR::Node *orig() { return state.first->first; }
        const IR::Node *result() { return state.first->second.second; }
    };
    bool done(const IR::Node *n) const { return visited.count(n) && visited.at(n).first; }
    const IR::Node *result(IR::Node *n) const { return visited.at(n).second; }
    change_t track(const IR::Node *n) { return change_t(&visited, n); }
    void start(change_t &change) { change.state.first->second.first = false; }
    bool finish(change_t &change, const IR::Node *orig, const IR::Node *final) {
        if (!change.valid || (change.state.first = visited.find(orig)) == visited.end())
            BUG("visitor state tracker corrupted");
        change.state.first->second.first = true;
        if (!final || *final != *orig) {
            change.state.first->second.second = final;
            visited.emplace(final, std::make_pair(true, final));
            return true;
        } else {
            // FIXME -- not safe if the visitor resurrects the node (which it shouldn't)
            // if (final && final->id == IR::Node::currentId - 1)
            //     --IR::Node::currentId;
            return false; } }
    const IR::Node *result(const IR::Node *n) const {
        auto it = visited.find(n);
        if (it == visited.end())
            return n;
        if (!it->second.first) BUG("IR loop detected");
        return it->second.second; }
    void revisit_visited() {
        for (auto it = visited.begin(); it != visited.end();) {
            if (it->second.first)
                it = visited.erase(it);
            else
                ++it; } }
};

Visitor::profile_t Visitor::init_apply(const IR::Node *root) {
    if (ctxt) BUG("previous use of visitor did not clean up properly");
    ctxt = nullptr;
    if (joinFlows) init_join_flows(root);
    return profile_t(*this);
}
Visitor::profile_t Modifier::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new ChangeTracker();
    return rv; }
Visitor::profile_t Inspector::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new visited_t();
    return rv; }
Visitor::profile_t Transform::init_apply(const IR::Node *root) {
    auto rv = Visitor::init_apply(root);
    visited = new ChangeTracker();
    return rv; }
void Visitor::end_apply() {}
void Visitor::end_apply(const IR::Node*) {}

static indent_t profile_indent;
Visitor::profile_t::profile_t(Visitor &v_) : v(v_) {
    struct timespec ts;
#ifdef CLOCK_MONOTONIC
    clock_gettime(CLOCK_MONOTONIC, &ts);
#else
    // FIXME -- figure out how to do this on OSX/Mach
    ts.tv_sec = ts.tv_nsec = 0;
#endif
    start = ts.tv_sec*1000000000UL + ts.tv_nsec + 1;
    assert(start);
    ++profile_indent;
}
Visitor::profile_t::profile_t(profile_t &&a) : v(a.v), start(a.start) {
    a.start = 0;
}
Visitor::profile_t::~profile_t() {
    if (start) {
        v.end_apply();
        --profile_indent;
        struct timespec ts;
#ifdef CLOCK_MONOTONIC
        clock_gettime(CLOCK_MONOTONIC, &ts);
#else
        // FIXME -- figure out how to do this on OSX/Mach
        ts.tv_sec = ts.tv_nsec = 0;
#endif
        uint64_t end = ts.tv_sec*1000000000UL + ts.tv_nsec + 1;
        LOG1(profile_indent << v.name() << ' ' << (end-start)/1000.0 << " usec"); }
}

void Visitor::print_context() const {
    std::ostream &out = std::cout;
    out << "Context:" << std::endl;
    auto ctx = getContext();
    if (ctx == nullptr) {
        out << "<nullptr>" << std::endl;
        return;
    }

    while (ctx != nullptr) {
        out << ctx->node << " (" << ctx->original << ")" << std::endl;
        ctx = ctx->parent;
    }
}

void Visitor::visitor_const_error() {
    BUG("const Visitor wants to change IR"); }
void Modifier::visitor_const_error() {
    BUG("Modifier called const visit function -- missing template "
                            "instantiation in gen-tree-macro.h?"); }
void Transform::visitor_const_error() {
    BUG("Transform called const visit function -- missing template "
                            "instantiation in gen-tree-macro.h?"); }

struct PushContext {
    Visitor::Context current;
    const Visitor::Context *&stack;
    PushContext(const Visitor::Context *&stck, const IR::Node *node) : stack(stck) {
        current.parent = stack;
        current.node = current.original = node;
        current.child_index = 0;
        current.depth = stack ? stack->depth+1 : 1;
        assert(current.depth < 10000);    // stack overflow?
        stack = &current; }
    ~PushContext() { stack = current.parent; }
};

namespace {
class ForwardChildren : public Visitor {
    const ChangeTracker &visited;
    const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) {
        return visited.result(n); }
 public:
    explicit ForwardChildren(const ChangeTracker &v) : visited(v) {}
};
}

const IR::Node *Modifier::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n) {
        PushContext local(ctxt, n);
        auto track = visited->track(n);
        if (track.done() && visitDagOnce) {
            track.orig()->apply_visitor_revisit(*this, track.result());
            n = track.result();
        } else {
            visited->start(track);
            IR::Node *copy = n->clone();
            local.current.node = copy;
            if (visitDagOnce && !dontForwardChildrenBeforePreorder) {
                ForwardChildren forward_children(*visited);
                copy->visit_children(forward_children); }
            if (copy->apply_visitor_preorder(*this)) {
                copy->visit_children(*this);
                copy->apply_visitor_postorder(*this); }
            if (visited->finish(track, n, copy))
                (n = copy)->validate(); } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

const IR::Node *Inspector::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n && !join_flows(n)) {
        PushContext local(ctxt, n);
        auto vp = visited->emplace(n, false);
        if (!vp.second && !vp.first->second)
            BUG("IR loop detected");
        if (!vp.second && visitDagOnce) {
            n->apply_visitor_revisit(*this);
        } else {
            vp.first->second = false;
            if (n->apply_visitor_preorder(*this)) {
                n->visit_children(*this);
                n->apply_visitor_postorder(*this); }
            vp.first = visited->find(n);  // iterator may have been invalidated
            if (vp.first == visited->end())
                BUG("visitor state tracker corrupted");
            vp.first->second = true; } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

const IR::Node *Transform::apply_visitor(const IR::Node *n, const char *name) {
    if (ctxt) ctxt->child_name = name;
    if (n) {
        PushContext local(ctxt, n);
        auto track = visited->track(n);
        if (track.done() && visitDagOnce) {
            track.orig()->apply_visitor_revisit(*this, track.result());
            n = track.result();
        } else {
            visited->start(track);
            auto copy = n->clone();
            local.current.node = copy;
            if (visitDagOnce && !dontForwardChildrenBeforePreorder) {
                ForwardChildren forward_children(*visited);
                copy->visit_children(forward_children); }
            prune_flag = false;
            auto preorder_result = copy->apply_visitor_preorder(*this);
            ChangeTracker::change_t preorder_result_track;
            assert(preorder_result != n);  // should never happen
            auto final = preorder_result;
            if (preorder_result != copy) {
                // FIXME -- not safe if the visitor resurrects the node (which it shouldn't)
                // if (copy->id == IR::Node::currentId - 1)
                //     --IR::Node::currentId;
                if (!preorder_result) {
                    prune_flag = true;
                } else if (visited->done(preorder_result) && visitDagOnce) {
                    final = visited->result(preorder_result);
                    prune_flag = true;
                } else {
                    preorder_result_track = visited->track(preorder_result);
                    visited->start(preorder_result_track);
                    local.current.node = copy = preorder_result->clone(); } }
            if (!prune_flag) {
                copy->visit_children(*this);
                final = copy->apply_visitor_postorder(*this); }
            if (final && final != preorder_result && *final == *preorder_result)
                final = preorder_result;
            if (visited->finish(track, n, final) && (n = final))
                final->validate();
            if (preorder_result_track)
                visited->finish(preorder_result_track, preorder_result, final); } }
    if (ctxt)
        ctxt->child_index++;
    else
        visited = nullptr;
    return n;
}

void Inspector::revisit_visited() {
    for (auto it = visited->begin(); it != visited->end();) {
        if (it->second)
            it = visited->erase(it);
        else
            ++it; }
}
void Modifier::revisit_visited() {
    visited->revisit_visited();
}
void Transform::revisit_visited() {
    visited->revisit_visited();
}

#define DEFINE_VISIT_FUNCTIONS(CLASS, BASE)                                             \
bool Modifier::preorder(IR::CLASS *n) {                                                 \
    return preorder(static_cast<IR::BASE *>(n)); }                                      \
void Modifier::postorder(IR::CLASS *n) {                                                \
    postorder(static_cast<IR::BASE *>(n)); }                                            \
void Modifier::revisit(const IR::CLASS *o, const IR::CLASS *n) {                        \
    revisit(static_cast<const IR::BASE *>(o), static_cast<const IR::BASE *>(n)); }      \
bool Inspector::preorder(const IR::CLASS *n) {                                          \
    return preorder(static_cast<const IR::BASE *>(n)); }                                \
void Inspector::postorder(const IR::CLASS *n) {                                         \
    postorder(static_cast<const IR::BASE *>(n)); }                                      \
void Inspector::revisit(const IR::CLASS *n) {                                           \
    revisit(static_cast<const IR::BASE *>(n)); }                                        \
const IR::Node *Transform::preorder(IR::CLASS *n) {                                     \
    return preorder(static_cast<IR::BASE *>(n)); }                                      \
const IR::Node *Transform::postorder(IR::CLASS *n) {                                    \
    return postorder(static_cast<IR::BASE *>(n)); }                                     \
void Transform::revisit(const IR::CLASS *o, const IR::Node *n) {                        \
    return revisit(static_cast<const IR::BASE *>(o), n); }                              \

IRNODE_ALL_SUBCLASSES(DEFINE_VISIT_FUNCTIONS)

class SetupJoinPoints : public Inspector {
    map<const IR::Node *, std::pair<ControlFlowVisitor *, int>> &join_points;
    bool preorder(const IR::Node *n) override {
        return ++join_points[n].second == 1; }
 public:
    explicit SetupJoinPoints(decltype(join_points) &fjp)
    : join_points(fjp) { visitDagOnce = false; }
};

void ControlFlowVisitor::init_join_flows(const IR::Node *root) {
    if (!dynamic_cast<Inspector *>(static_cast<Visitor *>(this)))
        BUG("joinFlows only works for Inspector passes currently, not Modifier or Transform");
    if (flow_join_points)
        flow_join_points->clear();
    else
        flow_join_points = new std::remove_reference<decltype(*flow_join_points)>::type;
    root->apply(SetupJoinPoints(*flow_join_points));
    for (auto it = flow_join_points->begin(); it != flow_join_points->end(); ) {
        if (it->second.second > 1 && !filter_join_point(it->first)) {
            ++it;
        } else {
            it = flow_join_points->erase(it); } }
}

bool ControlFlowVisitor::join_flows(const IR::Node *n) {
    if (flow_join_points && flow_join_points->count(n)) {
        auto &status = flow_join_points->at(n);
        if (!--status.second) {
            flow_merge(*status.first);
            return false;
        } else if (status.first) {
            status.first->flow_merge(*this);
            return true;
        } else {
            status.first = clone();
            return true; } }
    return false;
}

void Inspector::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Inspector *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}
void Modifier::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Modifier *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}
void Transform::check_clone(const Visitor *v) {
    auto *t = dynamic_cast<const Transform *>(v);
    BUG_CHECK(t && t->visited == visited, "Clone failed to copy base object");
}

ControlFlowVisitor &ControlFlowVisitor::flow_clone() {
    auto *rv = clone();
    rv->check_clone(this);
    return *rv;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlbrsh.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 22:27:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "hintids.hxx"
#include <tools/debug.hxx>

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#include <xmloff/nmspmap.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmltkmap.hxx>
#ifndef _XMLOFF_XMLBASE64IMPORTCONTEXT_HXX
#include <xmloff/XMLBase64ImportContext.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif

#ifndef _SVX_UNOMID_HXX
#include <svx/unomid.hxx>
#endif
#ifndef _SVX_BRSHITEM_HXX
#include <svx/brshitem.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif

#include "xmlbrshi.hxx"
#include "xmlbrshe.hxx"
#include "xmlexp.hxx"
#include "xmlimpit.hxx"
#include "xmlexpit.hxx"

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

enum SvXMLTokenMapAttrs
{
    XML_TOK_BGIMG_HREF,
    XML_TOK_BGIMG_TYPE,
    XML_TOK_BGIMG_ACTUATE,
    XML_TOK_BGIMG_SHOW,
    XML_TOK_BGIMG_POSITION,
    XML_TOK_BGIMG_REPEAT,
    XML_TOK_BGIMG_FILTER,
    XML_TOK_NGIMG_END=XML_TOK_UNKNOWN
};

static __FAR_DATA SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] =
{
    { XML_NAMESPACE_XLINK, XML_HREF,        XML_TOK_BGIMG_HREF      },
    { XML_NAMESPACE_XLINK, XML_TYPE,        XML_TOK_BGIMG_TYPE      },
    { XML_NAMESPACE_XLINK, XML_ACTUATE,     XML_TOK_BGIMG_ACTUATE   },
    { XML_NAMESPACE_XLINK, XML_SHOW,        XML_TOK_BGIMG_SHOW      },
    { XML_NAMESPACE_STYLE, XML_POSITION,    XML_TOK_BGIMG_POSITION  },
    { XML_NAMESPACE_STYLE, XML_REPEAT,      XML_TOK_BGIMG_REPEAT    },
    { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER    },
    XML_TOKEN_MAP_END
};

TYPEINIT1( SwXMLBrushItemImportContext, SvXMLImportContext );

void SwXMLBrushItemImportContext::ProcessAttrs(
        const Reference< xml::sax::XAttributeList >& xAttrList,
        const SvXMLUnitConverter& rUnitConv )
{
    SvXMLTokenMap aTokenMap( aBGImgAttributesAttrTokenMap );

    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        switch( aTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_BGIMG_HREF:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, GetImport().ResolveGraphicObjectURL( rValue,sal_False),
                MID_GRAPHIC_LINK, rUnitConv );
            break;
        case XML_TOK_BGIMG_TYPE:
        case XML_TOK_BGIMG_ACTUATE:
        case XML_TOK_BGIMG_SHOW:
            break;
        case XML_TOK_BGIMG_POSITION:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_POSITION, rUnitConv );
            break;
        case XML_TOK_BGIMG_REPEAT:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_REPEAT, rUnitConv );
            break;
        case XML_TOK_BGIMG_FILTER:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_FILTER, rUnitConv );
            break;
        }
    }

}

SvXMLImportContext *SwXMLBrushItemImportContext::CreateChildContext(
        sal_uInt16 nPrefix, const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    if( xmloff::token::IsXMLToken( rLocalName,
                                        xmloff::token::XML_BINARY_DATA ) )
    {
        if( !xBase64Stream.is() && !pItem->GetGraphicLink() )
        {
            const GraphicObject *pGrObj = pItem->GetGraphicObject();
            if( !pGrObj || GRAPHIC_NONE == pGrObj->GetType() )
            {
                xBase64Stream =
                    GetImport().GetStreamForGraphicObjectURLFromBase64();
                if( xBase64Stream.is() )
                    pContext = new XMLBase64ImportContext( GetImport(), nPrefix,
                                                        rLocalName, xAttrList,
                                                        xBase64Stream );
            }
        }
    }
    if( !pContext )
    {
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    }

    return pContext;
}

void SwXMLBrushItemImportContext::EndElement()
{
    if( xBase64Stream.is() )
    {
        OUString sURL( GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream ) );
        xBase64Stream = 0;
        SvXMLImportItemMapper::PutXMLValue( *pItem, sURL, MID_GRAPHIC_LINK, GetImport().GetMM100UnitConverter() );
    }

    if( !(pItem->GetGraphicLink() || pItem->GetGraphic() ) )
        pItem->SetGraphicPos( GPOS_NONE );
    else if( GPOS_NONE == pItem->GetGraphicPos() )
        pItem->SetGraphicPos( GPOS_TILED );
}

SwXMLBrushItemImportContext::SwXMLBrushItemImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList >& xAttrList,
        const SvXMLUnitConverter& rUnitConv,
        const SvxBrushItem& rItem ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    pItem( new SvxBrushItem( rItem ) )
{
    // delete any grephic that is existing
    pItem->SetGraphicPos( GPOS_NONE );

    ProcessAttrs( xAttrList, rUnitConv );
}

SwXMLBrushItemImportContext::SwXMLBrushItemImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        const SvXMLUnitConverter& rUnitConv,
        sal_uInt16 nWhich ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    pItem( new SvxBrushItem( nWhich ) )
{
    ProcessAttrs( xAttrList, rUnitConv );
}

SwXMLBrushItemImportContext::~SwXMLBrushItemImportContext()
{
    delete pItem;
}

SwXMLBrushItemExport::SwXMLBrushItemExport( SwXMLExport& rExp ) :
    rExport( rExp )
{
}

SwXMLBrushItemExport::~SwXMLBrushItemExport()
{
}

void SwXMLBrushItemExport::exportXML( const SvxBrushItem& rItem )
{
    GetExport().CheckAttrList();

    OUString sValue, sURL;
    const SvXMLUnitConverter& rUnitConv = GetExport().GetTwipUnitConverter();
    if( SvXMLExportItemMapper::QueryXMLValue(
            rItem, sURL, MID_GRAPHIC_LINK, rUnitConv ) )
    {
        sValue = GetExport().AddEmbeddedGraphicObject( sURL );
        if( sValue.getLength() )
        {
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sValue );
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
    //      AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, ACP2WS(sXML_embed) );
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
        }

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_POSITION, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_POSITION, sValue );

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_REPEAT, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REPEAT, sValue );

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_FILTER, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FILTER_NAME, sValue );
    }

    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE,
                                  sal_True, sal_True );
        if( sURL.getLength() )
        {
            // optional office:binary-data
            GetExport().AddEmbeddedGraphicObjectAsBase64( sURL );
        }
    }
}

<commit_msg>INTEGRATION: CWS swwarnings (1.13.222); FILE MERGED 2007/04/11 07:03:10 tl 1.13.222.1: #i69287# warning-free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlbrsh.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 10:09:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "hintids.hxx"
#include <tools/debug.hxx>

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#include <xmloff/nmspmap.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmltkmap.hxx>
#ifndef _XMLOFF_XMLBASE64IMPORTCONTEXT_HXX
#include <xmloff/XMLBase64ImportContext.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif

#ifndef _SVX_UNOMID_HXX
#include <svx/unomid.hxx>
#endif
#ifndef _SVX_BRSHITEM_HXX
#include <svx/brshitem.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif

#include "xmlbrshi.hxx"
#include "xmlbrshe.hxx"
#include "xmlexp.hxx"
#include "xmlimpit.hxx"
#include "xmlexpit.hxx"

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

enum SvXMLTokenMapAttrs
{
    XML_TOK_BGIMG_HREF,
    XML_TOK_BGIMG_TYPE,
    XML_TOK_BGIMG_ACTUATE,
    XML_TOK_BGIMG_SHOW,
    XML_TOK_BGIMG_POSITION,
    XML_TOK_BGIMG_REPEAT,
    XML_TOK_BGIMG_FILTER,
    XML_TOK_NGIMG_END=XML_TOK_UNKNOWN
};

static __FAR_DATA SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] =
{
    { XML_NAMESPACE_XLINK, XML_HREF,        XML_TOK_BGIMG_HREF      },
    { XML_NAMESPACE_XLINK, XML_TYPE,        XML_TOK_BGIMG_TYPE      },
    { XML_NAMESPACE_XLINK, XML_ACTUATE,     XML_TOK_BGIMG_ACTUATE   },
    { XML_NAMESPACE_XLINK, XML_SHOW,        XML_TOK_BGIMG_SHOW      },
    { XML_NAMESPACE_STYLE, XML_POSITION,    XML_TOK_BGIMG_POSITION  },
    { XML_NAMESPACE_STYLE, XML_REPEAT,      XML_TOK_BGIMG_REPEAT    },
    { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER    },
    XML_TOKEN_MAP_END
};

TYPEINIT1( SwXMLBrushItemImportContext, SvXMLImportContext );

void SwXMLBrushItemImportContext::ProcessAttrs(
        const Reference< xml::sax::XAttributeList >& xAttrList,
        const SvXMLUnitConverter& rUnitConv )
{
    SvXMLTokenMap aTokenMap( aBGImgAttributesAttrTokenMap );

    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        switch( aTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_BGIMG_HREF:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, GetImport().ResolveGraphicObjectURL( rValue,sal_False),
                MID_GRAPHIC_LINK, rUnitConv );
            break;
        case XML_TOK_BGIMG_TYPE:
        case XML_TOK_BGIMG_ACTUATE:
        case XML_TOK_BGIMG_SHOW:
            break;
        case XML_TOK_BGIMG_POSITION:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_POSITION, rUnitConv );
            break;
        case XML_TOK_BGIMG_REPEAT:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_REPEAT, rUnitConv );
            break;
        case XML_TOK_BGIMG_FILTER:
            SvXMLImportItemMapper::PutXMLValue(
                *pItem, rValue, MID_GRAPHIC_FILTER, rUnitConv );
            break;
        }
    }

}

SvXMLImportContext *SwXMLBrushItemImportContext::CreateChildContext(
        sal_uInt16 nPrefix, const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    if( xmloff::token::IsXMLToken( rLocalName,
                                        xmloff::token::XML_BINARY_DATA ) )
    {
        if( !xBase64Stream.is() && !pItem->GetGraphicLink() )
        {
            const GraphicObject *pGrObj = pItem->GetGraphicObject();
            if( !pGrObj || GRAPHIC_NONE == pGrObj->GetType() )
            {
                xBase64Stream =
                    GetImport().GetStreamForGraphicObjectURLFromBase64();
                if( xBase64Stream.is() )
                    pContext = new XMLBase64ImportContext( GetImport(), nPrefix,
                                                        rLocalName, xAttrList,
                                                        xBase64Stream );
            }
        }
    }
    if( !pContext )
    {
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    }

    return pContext;
}

void SwXMLBrushItemImportContext::EndElement()
{
    if( xBase64Stream.is() )
    {
        OUString sURL( GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream ) );
        xBase64Stream = 0;
        SvXMLImportItemMapper::PutXMLValue( *pItem, sURL, MID_GRAPHIC_LINK, GetImport().GetMM100UnitConverter() );
    }

    if( !(pItem->GetGraphicLink() || pItem->GetGraphic() ) )
        pItem->SetGraphicPos( GPOS_NONE );
    else if( GPOS_NONE == pItem->GetGraphicPos() )
        pItem->SetGraphicPos( GPOS_TILED );
}

SwXMLBrushItemImportContext::SwXMLBrushItemImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList >& xAttrList,
        const SvXMLUnitConverter& rUnitConv,
        const SvxBrushItem& rItem ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    pItem( new SvxBrushItem( rItem ) )
{
    // delete any grephic that is existing
    pItem->SetGraphicPos( GPOS_NONE );

    ProcessAttrs( xAttrList, rUnitConv );
}

SwXMLBrushItemImportContext::SwXMLBrushItemImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        const SvXMLUnitConverter& rUnitConv,
        sal_uInt16 nWhich ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    pItem( new SvxBrushItem( nWhich ) )
{
    ProcessAttrs( xAttrList, rUnitConv );
}

SwXMLBrushItemImportContext::~SwXMLBrushItemImportContext()
{
    delete pItem;
}

SwXMLBrushItemExport::SwXMLBrushItemExport( SwXMLExport& rExp ) :
    rExport( rExp )
{
}

SwXMLBrushItemExport::~SwXMLBrushItemExport()
{
}

void SwXMLBrushItemExport::exportXML( const SvxBrushItem& rItem )
{
    GetExport().CheckAttrList();

    OUString sValue, sURL;
    const SvXMLUnitConverter& rUnitConv = GetExport().GetTwipUnitConverter();
    if( SvXMLExportItemMapper::QueryXMLValue(
            rItem, sURL, MID_GRAPHIC_LINK, rUnitConv ) )
    {
        sValue = GetExport().AddEmbeddedGraphicObject( sURL );
        if( sValue.getLength() )
        {
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sValue );
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
    //      AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, ACP2WS(sXML_embed) );
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
        }

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_POSITION, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_POSITION, sValue );

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_REPEAT, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REPEAT, sValue );

        if( SvXMLExportItemMapper::QueryXMLValue(
                rItem, sValue, MID_GRAPHIC_FILTER, rUnitConv ) )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FILTER_NAME, sValue );
    }

    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE,
                                  sal_True, sal_True );
        if( sURL.getLength() )
        {
            // optional office:binary-data
            GetExport().AddEmbeddedGraphicObjectAsBase64( sURL );
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>fdo#34800 sw: small cleanup<commit_after><|endoftext|>


<commit_before>
/*
 * arg_test.cpp - Tests argument analyzer which is part of the test suite
 *                of this project, and could extended further to be
 *                user in other projects
 */

#include "test_suite.h"

/*
 * TestArgBasic() - Tests basic functionality
 */
void TestArgBasic() {
  PrintTestName("TestArgBasic");

  int argc = 6;
  char v1[] = "test";
  char v2[] = "-1";
  char v3[] = "--second_key=2nd_value";
  char v4[] = "-3";
  char v5[] = "--fourth_key";
  char v6[] = "--b";

  char *argv[] = {v1, v2, v3, v4, v5, v6};

  Argv args{argc, argv};
  const auto &kv_map = args.GetKVMap();

  dbg_printf("kv_list content: \n");
  for(auto it = kv_map.begin();it != kv_map.end();it++) {
    dbg_printf("%s -> %s\n", it->first.c_str(), it->second.c_str());
  }

  const auto &arg_list = args.GetArgList();
  dbg_printf("arg_list content: \n");
  for(auto it = arg_list.begin();it != arg_list.end();it++) {
    dbg_printf("%s\n", it->c_str());
  }

  return;
}

int main() {
  return 0;
}
<commit_msg>Adding arg test<commit_after>
/*
 * arg_test.cpp - Tests argument analyzer which is part of the test suite
 *                of this project, and could extended further to be
 *                user in other projects
 */

#include "test_suite.h"

/*
 * TestArgBasic() - Tests basic functionality
 */
void TestArgBasic() {
  PrintTestName("TestArgBasic");

  char v1[] = "test";
  char v2[] = "-1";
  char v3[] = "--second_key=2nd_value";
  char v4[] = "--3";
  char v5[] = "--fourth_key";
  char vv[] = "--";
  char v6[] = "--b=nonsense";
  char v7[] = "value_1";
  char v8[] = "value_2";

  char *argv[] = {v1, v2, v3, v4, v5, vv, v6, v7, v8};
  int argc = static_cast<int>(sizeof(argv) / sizeof(char *));

  dbg_printf("*** Command line input: \n");
  dbg_printf("");
  for(int i = 0;i < argc;i++) {
    printf("%s ", argv[i]);
  }
  putchar('\n');

  Argv args{argc, argv};
  const auto &kv_map = args.GetKVMap();

  dbg_printf("*** kv_list content: \n\n");
  for(auto it = kv_map.begin();it != kv_map.end();it++) {
    dbg_printf("%s -> %s\n", it->first.c_str(), it->second.c_str());
  }

  const auto &arg_list = args.GetArgList();
  dbg_printf("*** arg_list content: \n\n");
  for(auto it = arg_list.begin();it != arg_list.end();it++) {
    dbg_printf("%s\n", it->c_str());
  }

  return;
}

int main() {
  TestArgBasic();

  return 0;
}
<|endoftext|>


<commit_before>// g++ j.cc -o j -L/usr/local/lib -lroaring
#include <vector>
#include <string>
#include <array>
#include <map>
#include "roaring.hh"

enum FieldType {
  TIMESTAMP,
  DIMENSION,
  BOOL,
  METRIC_INT,
  METRIC_FLOAT
};

class FieldBase {};

template <FieldType, typename T>
class Field : FieldBase {
 private:
  std::string name;
  std::vector<T> vals;
  std::vector< std::vector<T> > mvals;
  std::map<T, Roaring *> dict_;
  Roaring *roar_;
  int count_;
  FieldType type_;
 public:
  Field(std::string name);
  void insert(T &val);
  std::map<std::string, Roaring *> &dict();
  Roaring *roar() {
    return roar_;
  }
};

template <FieldType type, typename T>
Field<type, T>::Field(std::string name):
    type_(type), name(name) {
  switch (type) {
    case METRIC_INT:
    case METRIC_FLOAT: {
    } break;
    default:
      throw std::runtime_error("invalid field type for Field<>");
  }
}

template <>
Field<DIMENSION, std::string>::Field(std::string name):
    type_(DIMENSION), name(name) {
  // switch (type) {
  //   case DIMENSION: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for string");
  // }
}

template <>
Field<TIMESTAMP, int64_t>::Field(std::string name):
    type_(TIMESTAMP), name(name) {
  // switch (type) {
  //   case TIMESTAMP: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for int64");
  // }
}

template <>
Field<BOOL, bool>::Field(std::string name):
    type_(BOOL), name(name) {
  roar_ = new Roaring();
  // switch (type) {
  //   case BOOL: {
  //     roar_ = new Roaring();
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for bool");
  // }
}

template <FieldType type, typename T>
void Field<type, T>::insert(T &val) {
  switch (type_) {
    case TIMESTAMP:
    case METRIC_INT:
    case METRIC_FLOAT: {
      vals.push_back(val);
    } break;
    case DIMENSION: {
      Roaring *roar;
      if (dict_.count(val) > 0) {
        roar = dict_[val];
      } else {
        roar = new Roaring();
        dict_[val] = roar;
      }
      roar->add(count_);
    } break;
    default:
      throw std::runtime_error("can not insert val to field with unknown type");
  }

  count_++;
}

template<>
std::map<std::string, Roaring *> &Field<DIMENSION, std::string>::dict() {
  return dict_;
}

class DimensionField {
 public:
  Field<DIMENSION, std::string> *strdim;
  Field<BOOL, bool> *booldim;
  bool isBoolDim;
  DimensionField(Field<DIMENSION, std::string> *strdim_): strdim(strdim_), isBoolDim(false) {}
  DimensionField(Field<BOOL, bool> *booldim_): booldim(booldim_), isBoolDim(true) {}
};

class Query {
 private:
 public:
  Query();
  ~Query();
};

struct GroupByResult {
  std::vector<std::string> key;
  Roaring roaring;
};

static void genGroups(std::vector<GroupByResult> &groups, std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields, std::vector<std::string> currKey, int index) {
  bool genGroup = index == (groupByKeys.size() - 1);
  std::string key = groupByKeys[index];
  FieldBase *fieldRef = fields[key];
  Field<DIMENSION, std::string> *field = (Field<DIMENSION, std::string> *)fieldRef;
  std::map<std::string, Roaring *> &dict = field->dict();
  for (std::map<std::string, Roaring *>::iterator it = dict.begin(); it != dict.end(); it++) {}
}

std::vector<GroupByResult> genGroupByResult(std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields) {
  std::vector<GroupByResult> groups;
  genGroups(groups, groupByKeys, fields, std::vector<std::string>(), 0);
  return groups;
}

int main(int argc, char *argv[]) {
  Field<TIMESTAMP, int64_t> *timestamp = new Field<TIMESTAMP, int64_t>("timestamp");
  Field<DIMENSION, std::string> *publisher = new Field<DIMENSION, std::string>("publisher");
  Field<DIMENSION, std::string> *advertiser = new Field<DIMENSION, std::string>("advertiser");
  Field<DIMENSION, std::string> *gender = new Field<DIMENSION, std::string>("gender");
  Field<DIMENSION, std::string> *country = new Field<DIMENSION, std::string>("country");
  Field<BOOL, bool> *click = new Field<BOOL, bool>("click");
  Field<METRIC_FLOAT, float> *price = new Field<METRIC_FLOAT, float>("price");
  std::map<std::string, FieldBase*> fields;

  fields["timestamp"] = (FieldBase*)timestamp;
  fields["publisher"] = (FieldBase*)publisher;
  fields["advertiser"] = (FieldBase*)advertiser;
  fields["gender"] = (FieldBase*)gender;
  fields["country"] = (FieldBase*)country;
  fields["click"] = (FieldBase*)click;
  fields["price"] = (FieldBase*)price;

  // select count(*) from logs where click = 1 group by country,gender
  {
    // generate new bitmap of all elements. so we need segment wide count variable
    int count = 3;
    Roaring roar(roaring_bitmap_from_range(0, count, 1));

    //////////////////////////////////////////////////////////////////////
    /////////// FILTERING STATE //////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // do bitwise AND with click = 1
    // roar.printf();
    roar &= click->roar();
    // roar.printf();

    //////////////////////////////////////////////////////////////////////
    /////////// GROUPING STATE ///////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // generate groups for every group by term
    std::vector< GroupByResult > groups;
    std::vector<std::string> groupByKeys;
    groupByKeys.push_back("advertiser");
    groupByKeys.push_back("gender");
    groupByKeys.push_back("country");
  }

  return 0;
}

<commit_msg>generate GroupByResult struct by grouping keys and their values<commit_after>// g++ j.cc -o j -L/usr/local/lib -lroaring
#include <vector>
#include <string>
#include <array>
#include <map>
#include "roaring.hh"

enum FieldType {
  TIMESTAMP,
  DIMENSION,
  BOOL,
  METRIC_INT,
  METRIC_FLOAT
};

class FieldBase {};

template <FieldType, typename T>
class Field : FieldBase {
 private:
  std::string name;
  std::vector<T> vals;
  std::vector< std::vector<T> > mvals;
  std::map<T, Roaring *> dict_;
  Roaring *roar_;
  int count_;
  FieldType type_;
 public:
  Field(std::string name);
  void insert(T &val);
  std::map<std::string, Roaring *> &dict();
  Roaring *roar() {
    return roar_;
  }
};

template <FieldType type, typename T>
Field<type, T>::Field(std::string name):
    type_(type), name(name) {
  switch (type) {
    case METRIC_INT:
    case METRIC_FLOAT: {
    } break;
    default:
      throw std::runtime_error("invalid field type for Field<>");
  }
}

template <>
Field<DIMENSION, std::string>::Field(std::string name):
    type_(DIMENSION), name(name) {
  // switch (type) {
  //   case DIMENSION: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for string");
  // }
}

template <>
Field<TIMESTAMP, int64_t>::Field(std::string name):
    type_(TIMESTAMP), name(name) {
  // switch (type) {
  //   case TIMESTAMP: {
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for int64");
  // }
}

template <>
Field<BOOL, bool>::Field(std::string name):
    type_(BOOL), name(name) {
  roar_ = new Roaring();
  // switch (type) {
  //   case BOOL: {
  //     roar_ = new Roaring();
  //   } break;
  //   default:
  //     throw std::runtime_error("invalid field type for bool");
  // }
}

template <FieldType type, typename T>
void Field<type, T>::insert(T &val) {
  switch (type_) {
    case TIMESTAMP:
    case METRIC_INT:
    case METRIC_FLOAT: {
      vals.push_back(val);
    } break;
    case DIMENSION: {
      Roaring *roar;
      if (dict_.count(val) > 0) {
        roar = dict_[val];
      } else {
        roar = new Roaring();
        dict_[val] = roar;
      }
      roar->add(count_);
    } break;
    default:
      throw std::runtime_error("can not insert val to field with unknown type");
  }

  count_++;
}

template<>
std::map<std::string, Roaring *> &Field<DIMENSION, std::string>::dict() {
  return dict_;
}

class DimensionField {
 public:
  Field<DIMENSION, std::string> *strdim;
  Field<BOOL, bool> *booldim;
  bool isBoolDim;
  DimensionField(Field<DIMENSION, std::string> *strdim_): strdim(strdim_), isBoolDim(false) {}
  DimensionField(Field<BOOL, bool> *booldim_): booldim(booldim_), isBoolDim(true) {}
};

class Query {
 private:
 public:
  Query();
  ~Query();
};

struct GroupByResult {
  std::vector<std::string> key;
  Roaring roaring;
};

static void genGroups(std::vector<GroupByResult> &groups, std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields, std::vector<std::string> currKey, int index) {
  bool genGroup = index == (groupByKeys.size() - 1);
  std::string key = groupByKeys[index];
  FieldBase *fieldRef = fields[key];
  Field<DIMENSION, std::string> *field = (Field<DIMENSION, std::string> *)fieldRef;
  std::map<std::string, Roaring *> &dict = field->dict();
  for (std::map<std::string, Roaring *>::iterator it = dict.begin(); it != dict.end(); it++) {
    std::vector<std::string> groupKey = currKey;
    groupKey.push_back(it->first);

    if (genGroup) {
      GroupByResult gres;
      gres.key = groupKey;
      groups.push_back(gres);
    } else {
      genGroups(groups, groupByKeys, fields, groupKey, index + 1);
    }
  }
}

std::vector<GroupByResult> genGroupByResult(std::vector<std::string> &groupByKeys, std::map<std::string, FieldBase*> &fields) {
  std::vector<GroupByResult> groups;
  genGroups(groups, groupByKeys, fields, std::vector<std::string>(), 0);
  return groups;
}

int main(int argc, char *argv[]) {
  Field<TIMESTAMP, int64_t> *timestamp = new Field<TIMESTAMP, int64_t>("timestamp");
  Field<DIMENSION, std::string> *publisher = new Field<DIMENSION, std::string>("publisher");
  Field<DIMENSION, std::string> *advertiser = new Field<DIMENSION, std::string>("advertiser");
  Field<DIMENSION, std::string> *gender = new Field<DIMENSION, std::string>("gender");
  Field<DIMENSION, std::string> *country = new Field<DIMENSION, std::string>("country");
  Field<BOOL, bool> *click = new Field<BOOL, bool>("click");
  Field<METRIC_FLOAT, float> *price = new Field<METRIC_FLOAT, float>("price");
  std::map<std::string, FieldBase*> fields;

  fields["timestamp"] = (FieldBase*)timestamp;
  fields["publisher"] = (FieldBase*)publisher;
  fields["advertiser"] = (FieldBase*)advertiser;
  fields["gender"] = (FieldBase*)gender;
  fields["country"] = (FieldBase*)country;
  fields["click"] = (FieldBase*)click;
  fields["price"] = (FieldBase*)price;

  // select count(*) from logs where click = 1 group by country,gender
  {
    // generate new bitmap of all elements. so we need segment wide count variable
    int count = 3;
    Roaring roar(roaring_bitmap_from_range(0, count, 1));

    //////////////////////////////////////////////////////////////////////
    /////////// FILTERING STATE //////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // do bitwise AND with click = 1
    // roar.printf();
    roar &= click->roar();
    // roar.printf();

    //////////////////////////////////////////////////////////////////////
    /////////// GROUPING STATE ///////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    // generate groups for every group by term
    std::vector< GroupByResult > groups;
    std::vector<std::string> groupByKeys;
    groupByKeys.push_back("advertiser");
    groupByKeys.push_back("gender");
    groupByKeys.push_back("country");
  }

  return 0;
}

<|endoftext|>


<commit_before>/*
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
**     * Redistributions of source code must retain the above copyright
**       notice, this list of conditions and the following disclaimer.
**     * Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in
**       the documentation and/or other materials provided with the
**       distribution.
**     * Neither the author nor the names of any contributors may be used
**       to endorse or promote products derived from this software without
**       specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <sndfile.h>

int main() {
    const double pi = 3.14159265358979323846264338;
    const double freq = 440.0;
    const double duration = 1/freq;
    const int channels = 1;
    const int samplerate = 48000;
    const double sample_duration = 1.0/samplerate;
    const int sample_count = samplerate * duration;
    // 0x2F000000 => 788529152
    const double amplitude = 1.0 * 0x2F000000;

    printf("duration=%f\n", duration);
    printf("channels=%d\n", channels);
    printf("samplerate=%d\n", samplerate);
    printf("sample_count=%d\n", sample_count);
    printf("sample_duration=%f\n", sample_duration);
    printf("amplitude=%f\n", amplitude);
    printf("freq=%f\n", freq);

    SNDFILE *file;
    SF_INFO sfinfo;
    int *buffer;

    if (!(buffer = static_cast<int *>(malloc(2 * sample_count * sizeof *buffer)))) {
        printf("Error : Malloc failed.\n");
        return 1;
    };

    memset(&sfinfo, 0, sizeof(sfinfo));

    sfinfo.samplerate = samplerate;
    sfinfo.frames = sample_count;
    sfinfo.channels = channels;
    sfinfo.format = (SF_FORMAT_WAV | SF_FORMAT_PCM_32);

    if (!(file = sf_open("sine.wav", SFM_WRITE, &sfinfo))) {
        printf("Error : Not able to open output file.\n");
        free(buffer);
        return 1;
    };

    if (sfinfo.channels == 1) {
        for (int k = 0; k < sample_count; k++) {
            buffer[k] = amplitude * sin(freq * 2 * k * pi / samplerate);
            printf("%d: %f: %d\n", k, sample_duration*k, buffer[k]);
        }
    } else {
        printf("Error : make_sine can only generate mono files.\n");
	sf_close(file);
	free(buffer);
        return 1;
    };

    if (sf_write_int(file, buffer, sfinfo.channels * sample_count) !=
        sfinfo.channels * sample_count)
        puts(sf_strerror(file));

    sf_close(file);
    free(buffer);
    return 0;
} /* main */
<commit_msg>Use a SndfileHandle.<commit_after>/*
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
**     * Redistributions of source code must retain the above copyright
**       notice, this list of conditions and the following disclaimer.
**     * Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in
**       the documentation and/or other materials provided with the
**       distribution.
**     * Neither the author nor the names of any contributors may be used
**       to endorse or promote products derived from this software without
**       specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <sndfile.hh>

int main() {
    const char * filename = "sine.wav";
    const double pi = 3.14159265358979323846264338;
    const double freq = 440.0;
    const double duration = 1/freq;
    const int channels = 1;
    const int samplerate = 48000;
    const double sample_duration = 1.0/samplerate;
    const int sample_count = samplerate * duration;
    // 0x2F000000 => 788529152
    const double amplitude = 1.0 * 0x2F000000;

    printf("duration=%f\n", duration);
    printf("channels=%d\n", channels);
    printf("samplerate=%d\n", samplerate);
    printf("sample_count=%d\n", sample_count);
    printf("sample_duration=%f\n", sample_duration);
    printf("amplitude=%f\n", amplitude);
    printf("freq=%f\n", freq);

    SndfileHandle sndfilehandle(filename, SFM_WRITE, (SF_FORMAT_WAV | SF_FORMAT_PCM_32), channels, samplerate);

    int *buffer;
    if (!(buffer = static_cast<int *>(malloc(2 * sample_count * sizeof *buffer)))) {
        printf("Error : Malloc failed.\n");
        return 1;
    };

    if (sndfilehandle.channels() == 1) {
        for (int k = 0; k < sample_count; k++) {
            buffer[k] = amplitude * sin(freq * 2 * k * pi / samplerate);
            printf("%d: %f: %d\n", k, sample_duration*k, buffer[k]);
        }
    } else {
        printf("Error : make_sine can only generate mono files.\n");
	free(buffer);
        return 1;
    };

    sndfilehandle.write(buffer, sndfilehandle.channels() * sample_count);

    free(buffer);
    return 0;
} /* main */
<|endoftext|>


<commit_before>#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory>

namespace Frogs
{
    enum class Frog  { None, Brown, Green };
    enum class Step  { None, JumpLeft, LeapLeft, JumpRight, LeapRight };

    class State
    {
        std::vector<Frog> lilies;
        int count, blankPos;

    public:
        State(): count(0), blankPos(-1)
        {
        }
        State(int count): lilies(2 * count + 1), count(count), blankPos(count)
        {
            for (int i = 0; i < count; ++i)
            {
                lilies[i] = Frog::Brown;
                lilies[2 * count - i] = Frog::Green;
            }

            lilies[blankPos] = Frog::None;
        }

        bool operator==(const State& other) const
        {
            return count == other.count && lilies == other.lilies && blankPos == other.blankPos;
        }

        bool IsStuckJumpLeft()  const  { return blankPos >= (int)lilies.size() - 1 || lilies[blankPos + 1] != Frog::Green; }
        bool IsStuckLeapLeft()  const  { return blankPos >= (int)lilies.size() - 2 || lilies[blankPos + 2] != Frog::Green; }
        bool IsStuckJumpRight() const  { return blankPos < 1                       || lilies[blankPos - 1] != Frog::Brown; }
        bool IsStuckLeapRight() const  { return blankPos < 2                       || lilies[blankPos - 2] != Frog::Brown; }

        bool WasTargetReached() const
        {
            for (int i = 0; i < count; ++i)
                if (lilies[i] != Frog::Green || lilies[2 * count - i] != Frog::Brown)
                    return false;

            return lilies[count] == Frog::None;
        }

        std::shared_ptr<State> Move(Step step) const
        {
            bool canMove = false;
            auto moved = std::make_shared<State>(*this);

            switch (step)
            {
                case Step::JumpLeft:
                    if (!moved->IsStuckJumpLeft())
                    {
                        moved->lilies[moved->blankPos] = Frog::Green;
                        moved->blankPos++;
                        canMove = true;
                    }
                    break;

                case Step::LeapLeft:
                    if (!moved->IsStuckLeapLeft())
                    {
                        moved->lilies[moved->blankPos] = Frog::Green;
                        moved->blankPos += 2;
                        canMove = true;
                    }
                    break;

                case Step::JumpRight:
                    if (!moved->IsStuckJumpRight())
                    {
                        moved->lilies[moved->blankPos] = Frog::Brown;
                        moved->blankPos--;
                        canMove = true;
                    }
                    break;

                case Step::LeapRight:
                    if (!moved->IsStuckLeapRight())
                    {
                        moved->lilies[moved->blankPos] = Frog::Brown;
                        moved->blankPos -= 2;
                        canMove = true;
                    }
                    break;

                default:
                    break;
            }

            if (canMove)
                moved->lilies[moved->blankPos] = Frog::None;
            return canMove ? moved : nullptr;
        }

        void Print() const
        {
            for (const auto& frog: lilies)
                switch (frog)
                {
                    case Frog::Brown:
                        printf(">");
                        break;

                    case Frog::Green:
                        printf("<");
                        break;

                    case Frog::None:
                        printf("_");
                        break;
                }

            printf("\n");
        }
    };
}

int main()
{
    int count;
    scanf("%u", &count);

    if (count < 0)
        return 1;

    std::vector<std::shared_ptr<Frogs::State> > visited;
    std::stack<std::shared_ptr<Frogs::State> > trace;
    trace.push(std::make_shared<Frogs::State>(count));

    while (!trace.empty() && !trace.top()->WasTargetReached())
    {
        auto state = trace.top();
        trace.pop();

        auto move = [&](Frogs::Step step)
        {
            auto newState = state->Move(step);
            if (newState)
                trace.push(newState);
        };

        if (!state)
            continue;

        if (visited.crend() == std::find(visited.crbegin(), visited.crend(), state))
        {
            visited.push_back(state);
            move(Frogs::Step::JumpLeft);
            move(Frogs::Step::LeapLeft);
            move(Frogs::Step::JumpRight);
            move(Frogs::Step::LeapRight);

            state->Print();
        }
    }

    if (!trace.empty())
        trace.top()->Print();

    return 0;
}
<commit_msg>frogs: dropped a redundant check<commit_after>#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
#include <memory>

namespace Frogs
{
    enum class Frog  { None, Brown, Green };
    enum class Step  { None, JumpLeft, LeapLeft, JumpRight, LeapRight };

    class State
    {
        std::vector<Frog> lilies;
        int count, blankPos;

    public:
        State(): count(0), blankPos(-1)
        {
        }
        State(int count): lilies(2 * count + 1), count(count), blankPos(count)
        {
            for (int i = 0; i < count; ++i)
            {
                lilies[i] = Frog::Brown;
                lilies[2 * count - i] = Frog::Green;
            }

            lilies[blankPos] = Frog::None;
        }

        bool operator==(const State& other) const
        {
            return count == other.count && lilies == other.lilies && blankPos == other.blankPos;
        }

        bool IsStuckJumpLeft()  const  { return blankPos >= (int)lilies.size() - 1 || lilies[blankPos + 1] != Frog::Green; }
        bool IsStuckLeapLeft()  const  { return blankPos >= (int)lilies.size() - 2 || lilies[blankPos + 2] != Frog::Green; }
        bool IsStuckJumpRight() const  { return blankPos < 1                       || lilies[blankPos - 1] != Frog::Brown; }
        bool IsStuckLeapRight() const  { return blankPos < 2                       || lilies[blankPos - 2] != Frog::Brown; }

        bool WasTargetReached() const
        {
            for (int i = 0; i < count; ++i)
                if (lilies[i] != Frog::Green || lilies[2 * count - i] != Frog::Brown)
                    return false;

            return lilies[count] == Frog::None;
        }

        std::shared_ptr<State> Move(Step step) const
        {
            bool canMove = false;
            auto moved = std::make_shared<State>(*this);

            switch (step)
            {
                case Step::JumpLeft:
                    if (!moved->IsStuckJumpLeft())
                    {
                        moved->lilies[moved->blankPos] = Frog::Green;
                        moved->blankPos++;
                        canMove = true;
                    }
                    break;

                case Step::LeapLeft:
                    if (!moved->IsStuckLeapLeft())
                    {
                        moved->lilies[moved->blankPos] = Frog::Green;
                        moved->blankPos += 2;
                        canMove = true;
                    }
                    break;

                case Step::JumpRight:
                    if (!moved->IsStuckJumpRight())
                    {
                        moved->lilies[moved->blankPos] = Frog::Brown;
                        moved->blankPos--;
                        canMove = true;
                    }
                    break;

                case Step::LeapRight:
                    if (!moved->IsStuckLeapRight())
                    {
                        moved->lilies[moved->blankPos] = Frog::Brown;
                        moved->blankPos -= 2;
                        canMove = true;
                    }
                    break;

                default:
                    break;
            }

            if (canMove)
                moved->lilies[moved->blankPos] = Frog::None;
            return canMove ? moved : nullptr;
        }

        void Print() const
        {
            for (const auto& frog: lilies)
                switch (frog)
                {
                    case Frog::Brown:
                        printf(">");
                        break;

                    case Frog::Green:
                        printf("<");
                        break;

                    case Frog::None:
                        printf("_");
                        break;
                }

            printf("\n");
        }
    };
}

int main()
{
    int count;
    scanf("%u", &count);

    if (count < 0)
        return 1;

    std::vector<std::shared_ptr<Frogs::State> > visited;
    std::stack<std::shared_ptr<Frogs::State> > trace;
    trace.push(std::make_shared<Frogs::State>(count));

    while (!trace.empty() && !trace.top()->WasTargetReached())
    {
        auto state = trace.top();
        trace.pop();

        auto move = [&](Frogs::Step step)
        {
            auto newState = state->Move(step);
            if (newState)
                trace.push(newState);
        };

        if (visited.crend() == std::find(visited.crbegin(), visited.crend(), state))
        {
            visited.push_back(state);
            move(Frogs::Step::JumpLeft);
            move(Frogs::Step::LeapLeft);
            move(Frogs::Step::JumpRight);
            move(Frogs::Step::LeapRight);

            state->Print();
        }
    }

    if (!trace.empty())
        trace.top()->Print();

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <array>
#include <vector>
#include <set>
#include <map>
#include <random>
#include <chrono>
#include <functional>
#include <algorithm>

#include <cmath>

#define NUM_FIELDS 16

using Entry = std::array<double, NUM_FIELDS>;

int main(int argc, char** argv)
{
    // smoothing factor
    const double alpha = 1.0;
    // decision rule
    const int decision = 1;

    if (argc < 2)
        return 1;

    // preparing data
    int total = 0, correct = 0, totalClassified = 0;
    std::map<std::string, std::vector<Entry> > data;
    std::map<std::string, int> n;
    std::map<std::string, double> priors;
    std::map<std::string, std::vector<double> > multinomialLikelihoods;
    std::map<std::string, int> multinomialSums;
    std::map<std::string, Entry > sumX;
    std::map<std::string, std::vector<double> > means;
    std::map<std::string, std::vector<double> > variances;

    auto classify = [&](const std::string& label, const Entry& entry)
    {
        std::string predlabel;
        double maxlikelihood = 0.0;
        double denom = 0.0;
        std::vector<double> probs;
        for (auto it = priors.begin(); it != priors.end(); it++)
        {
            double numer = priors[it->first];
            const auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
            const auto& firstMean = means[it->first];
            const auto& firstVariance = variances[it->first];
            for (int j = 0; j < NUM_FIELDS; j++)
                switch (decision)
                {
                    case 2:
                        // Multinomial
                        if (entry[j])
                            numer *= pow(firstMultinomialLikelihood[j], entry[j]);
                        break;

                    case 3:
                        // Bernoulli
                        numer *= pow(firstMean[j], entry[j]) * pow(1.0 - firstMean[j], 1.0 - entry[j]);
                        break;

                    default:
                        // Gaussian
                        numer *= 1 / sqrt(2 * M_PI * firstVariance[j]) * exp((-1 * (entry[j] - firstMean[j]) * (entry[j] -firstMean[j])) / (2 * firstVariance[j]));
                        break;
                }

            if (numer > maxlikelihood)
            {
                maxlikelihood = numer;
                predlabel = it->first;
            }
            denom += numer;
            probs.push_back(numer);
        }

        std::cout << predlabel << "\t" << std::setw(1) << std::setprecision(3) << maxlikelihood/denom << "\t";
        if ("" == label)
            std::cout << "<no label>" << std::endl;
        else if (predlabel == label)
        {
            std::cout << "correct" << std::endl;
            correct++;
        }
        else
            std::cout << "incorrect" << std::endl;

        totalClassified++;
    };

    auto readFromFile = [&](const char* filename, bool isClassification)
    {
        std::ifstream file(argv[1]);
        if (!file.is_open())
            return 1;

        while (!file.eof())
        {
            std::string line;
            std::getline(file, line);
            if ("" == line)
                continue;
            std::istringstream linein(std::move(line));
            std::string label;
            std::getline(linein, label, ',');
            Entry entry;
            auto setField = [&entry, &label, &sumX, &multinomialSums, isClassification](int i, const std::string& field)
            {
                switch (field[0])
                {
                    case 'y':
                        entry[i] = 1.0;
                        break;

                    case 'n':
                        entry[i] = 0.0;
                        break;

                    case '?':
                        entry[i] = 0.5;
                        break;
                }
                if (!isClassification)
                {
                    sumX[label][i] += entry[i];
                    multinomialSums[label] += entry[i];
                }
            };
            for (int i = 0; i < NUM_FIELDS; i++)
            {
                std::string field;
                std::getline(linein, field, ',');
                setField(i, field);
            }
            std::string field;
            std::getline(linein, field);
            setField(NUM_FIELDS - 1, field);
            if (!isClassification)
            {
                data[label].push_back(std::move(entry));
                n[label]++;
                total++;
            }
            else
                classify(label, entry);
        }

        return 0;
    };

    int errcode = readFromFile(argv[1], false);
    if (errcode)
        return errcode;

    for (auto it = sumX.begin(); it != sumX.end(); it++)
    {
        priors[it->first] = (double)n[it->first] / total;

        std::cout << "Class " << it->first << ", prior: " << std::setw(1) << std::setprecision(3) << priors[it->first] << std::endl;
        std::cout << "feature\tmean\tvar\tstddev\tmnl" << std::endl;

        // calculate means
        std::vector<double> featureMeans(NUM_FIELDS);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureMeans[i] = sumX[it->first][i] / n[it->first];

        // calculate variances
        std::vector<double> featureVariances(NUM_FIELDS);
        const auto& firstData = data[it->first];
        for (int i = 0; i < (int)firstData.size(); i++)
            for (int j = 0; j < NUM_FIELDS; j++)
                featureVariances[j] += (firstData[i][j] - featureMeans[j]) * (firstData[i][j] - featureMeans[j]);
        for (int i = 0; i < NUM_FIELDS; i++)
            featureVariances[i] /= firstData.size();

        const auto& firstSumX = sumX[it->first];
        auto firstMultinomialSum = multinomialSums[it->first];
        auto& firstMultinomialLikelihood = multinomialLikelihoods[it->first];
        // calculate multinomial likelihoods
        for (int i = 0; i < NUM_FIELDS; i++)
        {
            double mnl = (firstSumX[i] + alpha) / (firstMultinomialSum + (alpha * featureMeans.size()));
            firstMultinomialLikelihood.push_back(mnl);
        }

        for (unsigned int i = 0; i < NUM_FIELDS; i++)
            printf("%i\t%2.3f\t%2.3f\t%2.3f\t%2.3f\n",i+1,featureMeans[i],featureVariances[i],sqrt(featureVariances[i]),firstMultinomialLikelihood[i]);

        means[it->first] = std::move(featureMeans);
        variances[it->first] = std::move(featureVariances);
    }

    // classify
    std::cout << "Classifying:" << std::endl;
    std::cout << "class\tprob\tresult" << std::endl;

    errcode = readFromFile(argv[2], true);
    if (errcode)
        return errcode;
    printf("Accuracy: %3.2f %% (%i/%i)\n", 100.0 * correct / totalClassified, correct, totalClassified);

    return 0;
}
<commit_msg>bayes: added function that splits dataset into sets; split off parts of the program into their own functions<commit_after>#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <array>
#include <vector>
#include <set>
#include <map>
#include <random>
#include <chrono>
#include <functional>
#include <algorithm>

#include <cmath>

#define NUM_FIELDS 16
#define NUM_SETS   10

namespace NaiveBayesClassifier
{
    using Entry = std::array<double, NUM_FIELDS>;

    struct State
    {
        std::map<std::string, std::vector<Entry> > data;
        std::map<std::string, int> n;
        std::map<std::string, double> priors;
        std::map<std::string, std::vector<double> > multinomialLikelihoods;
        std::map<std::string, int> multinomialSums;
        std::map<std::string, Entry > sumX;
        std::map<std::string, std::vector<double> > means;
        std::map<std::string, std::vector<double> > variances;
    };

    bool LoadDataset(const char* filename, State& state, int& total)
    {
        std::ifstream filein(filename);
        if (!filein.is_open())
            return false;

        while (!filein.eof())
        {
            std::string line;
            std::getline(filein, line);
            if ("" == line)
                continue;
            std::istringstream linein(std::move(line));
            std::string label;
            std::getline(linein, label, ',');
            Entry entry;
            auto setField = [&entry, &label, &state](int i, const std::string& field)
            {
                switch (field[0])
                {
                    case 'y':
                        entry[i] = 1.0;
                        break;

                    case 'n':
                        entry[i] = 0.0;
                        break;

                    case '?':
                        entry[i] = 0.5;
                        break;
                }
                state.sumX[label][i] += entry[i];
                state.multinomialSums[label] += entry[i];
            };
            for (int i = 0; i < NUM_FIELDS; i++)
            {
                std::string value;
                std::getline(linein, value, ',');
                setField(i, value);
            }
            std::string value;
            std::getline(linein, value);
            setField(NUM_FIELDS - 1, value);
            state.data[label].push_back(std::move(entry));
            state.n[label]++;
            total++;
        }

        return true;
    }

    void SplitData(const State& state, std::vector<std::set<int> >& dataSets)
    {
        std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
        std::uniform_int_distribution<> distribution(0, (int)state.data.size() - 1);
        auto addNextSet = [&generator, &distribution, &dataSets](int i, int size)
        {
            std::set<int> currentSet;

            while (currentSet.size() < size)
            {
                int index = distribution(generator);
                for (const auto& dataSet: dataSets)
                    if (dataSet.count(index))
                        continue;
                currentSet.insert(index);
            }

            dataSets.push_back(std::move(currentSet));
        };
        for (int i = 0; i < NUM_SETS - 1; ++i)
            addNextSet(i, state.data.size() / NUM_SETS);
        addNextSet(NUM_SETS - 1, state.data.size() % NUM_SETS);
    }

    void Train(const State& state)
    {
        for (auto it = state.sumX.begin(); it != state.sumX.end(); it++)
        {
            state.priors[it->first] = (double)state.n[it->first] / total;

            std::cout << "Class " << it->first << ", prior: " << std::setw(1) << std::setprecision(3) << priors[it->first] << std::endl;
            std::cout << "feature\tmean\tvar\tstddev\tmnl" << std::endl;

            // calculate means
            std::vector<double> featureMeans(NUM_FIELDS);
            for (int i = 0; i < NUM_FIELDS; i++)
                featureMeans[i] = state.sumX[it->first][i] / state.n[it->first];

            // calculate variances
            std::vector<double> featureVariances(NUM_FIELDS);
            const auto& firstData = state.data[it->first];
            for (int i = 0; i < (int)firstData.size(); i++)
                for (int j = 0; j < NUM_FIELDS; j++)
                    featureVariances[j] += (firstData[i][j] - featureMeans[j]) * (firstData[i][j] - featureMeans[j]);
            for (int i = 0; i < NUM_FIELDS; i++)
                featureVariances[i] /= firstData.size();

            const auto& firstSumX = state.sumX[it->first];
            auto firstMultinomialSum = state.multinomialSums[it->first];
            auto& firstMultinomialLikelihood = state.multinomialLikelihoods[it->first];
            // calculate multinomial likelihoods
            for (int i = 0; i < NUM_FIELDS; i++)
            {
                double mnl = (firstSumX[i] + state.alpha) / (firstMultinomialSum + (state.alpha * featureMeans.size()));
                firstMultinomialLikelihood.push_back(mnl);
            }

            for (unsigned int i = 0; i < NUM_FIELDS; i++)
                printf("%i\t%2.3f\t%2.3f\t%2.3f\t%2.3f\n",i+1,featureMeans[i],featureVariances[i],sqrt(featureVariances[i]),firstMultinomialLikelihood[i]);

            state.means[it->first] = std::move(featureMeans);
            state.variances[it->first] = std::move(featureVariances);
        }
    }

    void Classify(const State& state, const std::string& label, const Entry& entry)
    {
        std::string predlabel;
        double maxlikelihood = 0.0;
        double denom = 0.0;
        std::vector<double> probs;
        for (auto it = state.priors.begin(); it != state.priors.end(); it++)
        {
            double numer = priors[it->first];
            const auto& firstMultinomialLikelihood = atate.multinomialLikelihoods[it->first];
            const auto& firstMean = state.means[it->first];
            const auto& firstVariance = state.variances[it->first];
            for (int j = 0; j < NUM_FIELDS; j++)
                switch (state,decision)
                {
                    case 2:
                        // Multinomial
                        if (entry[j])
                            numer *= pow(firstMultinomialLikelihood[j], entry[j]);
                        break;

                    case 3:
                        // Bernoulli
                        numer *= pow(firstMean[j], entry[j]) * pow(1.0 - firstMean[j], 1.0 - entry[j]);
                        break;

                    default:
                        // Gaussian
                        numer *= 1 / sqrt(2 * M_PI * firstVariance[j]) * exp((-1 * (entry[j] - firstMean[j]) * (entry[j] -firstMean[j])) / (2 * firstVariance[j]));
                        break;
                }

            if (numer > maxlikelihood)
            {
                maxlikelihood = numer;
                predlabel = it->first;
            }
            denom += numer;
            probs.push_back(numer);
        }

        std::cout << predlabel << "\t" << std::setw(1) << std::setprecision(3) << maxlikelihood/denom << "\t";
        if ("" == label)
            std::cout << "<no label>" << std::endl;
        else if (predlabel == label)
        {
            std::cout << "correct" << std::endl;
            correct++;
        }
        else
            std::cout << "incorrect" << std::endl;

        totalClassified++;
    }
}

int main(int argc, char** argv)
{
    // smoothing factor
    const double alpha = 1.0;
    // decision rule
    const int decision = 1;

    if (argc < 2)
        return 1;

    // preparing data
    int total = 0, correct = 0, totalClassified = 0;

    int errcode = readFromFile(argv[1], false);
    if (errcode)
        return errcode;

    // classify
    std::cout << "Classifying:" << std::endl;
    std::cout << "class\tprob\tresult" << std::endl;

    errcode = readFromFile(argv[2], true);
    if (errcode)
        return errcode;
    printf("Accuracy: %3.2f %% (%i/%i)\n", 100.0 * correct / totalClassified, correct, totalClassified);

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 *
 */

#include "ip.hh"

namespace net {

uint16_t ip_checksum(void* data, size_t len) {
    uint64_t csum = 0;
    auto p64 = reinterpret_cast<uint64_t*>(data);
    while (len >= 8) {
        auto old = csum;
        csum += ntohq(*p64++);
        csum += (csum < old);
        len -= 8;
    }
    auto p16 = reinterpret_cast<uint16_t*>(p64);
    while (len >= 2) {
        auto old = csum;
        csum += ntohs(*p16++);
        csum += (csum < old);
        len -= 2;
    }
    auto p8 = reinterpret_cast<uint16_t*>(p16);
    if (len) {
        auto old = csum;
        csum += *p8++;
        csum += (csum < old);
        len -= 1;
    }
    csum = (csum & 0xffff) + ((csum >> 16) & 0xffff) + ((csum >> 32) & 0xffff) + (csum >> 48);
    csum += csum >> 16;
    return htons(~csum);
}

}
<commit_msg>ip: fix checksum for odd-sized packets<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 *
 */

#include "ip.hh"

namespace net {

uint16_t ip_checksum(void* data, size_t len) {
    uint64_t csum = 0;
    auto p64 = reinterpret_cast<uint64_t*>(data);
    while (len >= 8) {
        auto old = csum;
        csum += ntohq(*p64++);
        csum += (csum < old);
        len -= 8;
    }
    auto p16 = reinterpret_cast<uint16_t*>(p64);
    while (len >= 2) {
        auto old = csum;
        csum += ntohs(*p16++);
        csum += (csum < old);
        len -= 2;
    }
    auto p8 = reinterpret_cast<uint8_t*>(p16);
    if (len) {
        auto old = csum;
        csum += *p8++;
        csum += (csum < old);
        len -= 1;
    }
    csum = (csum & 0xffff) + ((csum >> 16) & 0xffff) + ((csum >> 32) & 0xffff) + (csum >> 48);
    csum += csum >> 16;
    return htons(~csum);
}

}
<|endoftext|>


<commit_before>/*c++11*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;

int main(int args, char *argc[]){

  return 0;
}
<commit_msg>change template<commit_after>/*c++11*/
#include <iostream>

using namespace std;

int main(int args, char *argc[]){

  return 0;
}
<|endoftext|>