<commit_before>// Copyright (c) 2020 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER 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.
#pragma once

#include <algorithm>
#include <tuple>
#include "helper.hh"

namespace wrencc::tree {

using ColorType = bool;
static constexpr ColorType kColorRed = false;
static constexpr ColorType kColorBlk = true;
static constexpr int kHeightMark = 0xff;

struct NodeBase;
struct AVLNodeBase;
struct RBNodeBase;
using BasePtr       = NodeBase*;
using ConstBasePtr  = const NodeBase*;

namespace impl::avl {
  void insert(bool insert_left, BasePtr x, BasePtr p, NodeBase& header) noexcept;
  void erase(BasePtr x, NodeBase& root) noexcept;
}

namespace impl::rb {
  void insert(bool insert_left, BasePtr x, BasePtr p, NodeBase& header) noexcept;
  void erase(BasePtr x, NodeBase& header) noexcept;
}

struct NodeBase {
  BasePtr parent;
  BasePtr left;
  BasePtr right;

  template <typename AVL = AVLNodeBase> inline AVL* as_avl() noexcept {
    return static_cast<AVL*>(this);
  }

  template <typename RB = AVLNodeBase> inline RB* as_rb() noexcept {
    return static_cast<RB*>(this);
  }

  static BasePtr successor(BasePtr x) noexcept {
    if (x->right != nullptr) {
      x = x->right;
      while (x->left != nullptr)
        x = x->left;
    }
    else {
      BasePtr y = x->parent;
      while (x == y->right) {
        x = y;
        y = y->parent;
      }
      if (x->right != y)
        x = y;
    }
    return x;
  }

  template <typename HeadChecker>
  static BasePtr predecessor(BasePtr x, HeadChecker&& checker) noexcept {
    if (checker(x) && x->parent->parent == x) {
      x = x->right;
    }
    else if (x->left != nullptr) {
      x = x->left;
      while (x->right != nullptr)
        x = x->right;
    }
    else {
      BasePtr y = x->parent;
      while (x == y->left) {
        x = y;
        y = y->parent;
      }
      x = y;
    }
    return x;
  }
};

struct AVLNodeBase : public NodeBase {
  int height;

  inline void set_marker() noexcept { height = kHeightMark; }
  inline bool is_marker() const noexcept { return height == kHeightMark; }
  inline void set_height(int h) noexcept { height = h; }

  inline int lheight() const noexcept {
    return left != nullptr ? left->as_avl()->height : 0;
  }

  inline int rheight() const noexcept {
    return right != nullptr ? right->as_avl()->height : 0;
  }

  inline void update_height() noexcept {
    height = std::max(lheight(), rheight()) + 1;
  }
};

struct RBNodeBase : public NodeBase {
  ColorType color;

  inline void set_marker() noexcept { as_red(); }
  inline bool is_marker() const noexcept { return is_red(); }

  inline bool is_red() const noexcept { return color == kColorRed; }
  inline bool is_blk() const noexcept { return color == kColorBlk; }
  inline void as_red() noexcept { color = kColorRed; }
  inline void as_blk() noexcept { color = kColorBlk; }
  inline void set_color(ColorType c) noexcept { color = c; }
};

template <typename Value> struct AVLNode : public AVLNodeBase {
  Value value;
};

template <typename Value> struct RBNode : public RBNodeBase {
  Value value;
};

template <typename _Tp, typename _Ref, typename _Ptr, typename _Node>
struct TreeIter {
  using Iter = TreeIter<_Tp, _Tp&, _Tp*, _Node>;
  using Self = TreeIter<_Tp, _Ref, _Ptr, _Node>;
  using Ref  = _Ref;
  using Ptr  = _Ptr;
  using Link = _Node*;

  BasePtr _node{};

  TreeIter() noexcept {}
  TreeIter(BasePtr x) noexcept : _node(x) {}
  TreeIter(ConstBasePtr x) noexcept : _node(const_cast<BasePtr>(x)) {}
  TreeIter(const Iter& x) noexcept : _node(x._node) {}

  inline void increment() noexcept { _node = NodeBase::successor(_node); }

  template <typename HeadChecker>
  inline void decrement(HeadChecker&& checker) noexcept {
    _node = NodeBase::predecessor(_node, std::move(checker));
  }

  inline Link node() const noexcept { return Link(_node); }
  inline Ref operator*() const noexcept { return Link(_node)->value; }
  inline Ptr operator->() const noexcept { return &Link(_node)->value; }

  inline bool operator==(const Self& r) const noexcept {
    return _node == r._node;
  }

  inline bool operator!=(const Self& r) const noexcept {
    return _node != r._node;
  }

  Self& operator++() noexcept { increment(); return *this; }
  Self operator++(int) noexcept { Self tmp(*this); increment(); return tmp; }

  Self& operator--() noexcept {
    decrement([](BasePtr x) { return Link(x)->is_marker(); });
    return *this;
  }

  Self operator--(int) noexcept {
    Self tmp(*this);
    decrement([](BasePtr x) { return Link(x)->is_marker(); });
    return tmp;
  }
};

template <typename Tp,
          typename Node,
          typename Less = std::less<Tp>,
          typename Equal = std::equal_to<Tp>>
class TreeBase : private UnCopyable {
public:
  using ValueType = Tp;
  using Iter      = TreeIter<Tp, Tp&, Tp*, Node>;
  using ConstIter = TreeIter<Tp, const Tp&, const Tp*, Node>;
  using Ref       = Tp&;
  using ConstRef  = const Tp&;
protected:
  using Link      = Node*;
  using ConstLink = const Node*;
  using Alloc     = wrencc::SimpleAlloc<Node>;

  sz_t size_{};
  Node head_{};
  Less lt_comp_{};
  Equal eq_comp_{};

  static inline Link _parent(BasePtr x) noexcept { return Link(x)->parent; }
  static inline ConstLink _parent(ConstBasePtr x) noexcept { return ConstLink(x)->parent; }
  static inline Link _left(BasePtr x) noexcept { return Link(x)->left; }
  static inline ConstLink _left(ConstBasePtr x) noexcept { return ConstLink(x)->left; }
  static inline Link _right(BasePtr x) noexcept { return Link(x)->right; }
  static inline ConstLink _right(ConstBasePtr x) noexcept { return ConstLink(x)->right; }

  inline void init() noexcept {
    size_ = 0;
    head_.parent = nullptr;
    head_.left = head_.right = &head_;
    head_.set_marker();
  }

  inline Link root() noexcept { return Link(head_.parent); }
  inline ConstLink root() const noexcept { return ConstLink(head_.parent); }
  inline Link tail() noexcept { return Link(&head_); }
  inline ConstLink tail() const noexcept { return ConstLink(&head_); }
  inline Link lmost() noexcept { return Link(head_.left); }
  inline ConstLink lmost() noexcept { return ConstLink(head_.left); }
  inline Link rmost() noexcept { return Link(head_.right); }
  inline ConstLink rmost() const noexcept { return ConstLink(head_.right); }

  inline Link get_node() noexcept { return Alloc::allocate(); }
  inline void put_node(Link p) noexcept { Alloc::deallocate(p); }

  Link create_node(const ValueType& val) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, val);
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  Link create_node(ValueType&& val) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, std::move(val));
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  template <typename... Args> Link create_node(Args&&... args) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, std::forward<Args>(args)...);
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  void destroy_node(Link p) {
    destroy(&p->value);
    put_node(p);
  }

  inline std::tuple<bool, Link, bool> find_insertion_pos(const ValueType& key) {
    Link x = root();
    Link p = tail();
    while (x != nullptr) {
      if (eq_comp_(key, x->value))
        return std::make_tuple(false, nullptr, false);

      p = x;
      x = lt_comp_(key, x->value) ? _left(x) : _right(x);
    }
    bool insert_left = x != nullptr || p == tail() || lt_comp_(key, p->value);

    return std::make_tuple(true, p, insert_left);
  }

  template <typename Insertion>
  inline void insert_aux(Insertion&& insert_fn, const ValueType& value) {
    auto [r, p, insert_left] = find_insertion_pos(value);
    if (r) {
      insert_fn(insert_left, create_node(value), p, head_);
      ++size_;
    }
  }

  template <typename Insertion>
  inline void insert_aux(Insertion&& insert_fn, ValueType&& value) {
    auto [r, p, insert_left] = find_insertion_pos(value);
    if (r) {
      insert_fn(insert_left, create_node(std::move(value)), p, head_);
      ++size_;
    }
  }

  template <typename Insertion, typename... Args>
  inline void insert_aux(Insertion&& insert_fn, Args&&... args) {
    Link tmp = create_node(std::forward<Args>(args)...);
    auto [r, p, insert_left] = find_insertion_pos(tmp->value);
    if (r) {
      insert_fn(insert_left, tmp, p, head_);
      ++size_;
    }
    else {
      destroy_node(tmp);
    }
  }

  template <typename Eraser> inline void erase_aux(Eraser&& erase_fn, Link p) {
    if (size_ != 0) {
      erase_fn(p, head_);
      destroy_node(p);
      --size_;
    }
  }

  void erase_subtree(Link x) {
    while (x != nullptr) {
      erase_subtree(_right(x));
      Link y = _left(x);
      destroy_node(x);
      x = y;
    }
  }

  inline ConstLink find_aux(const ValueType& key) const noexcept {
    ConstLink x = root();
    ConstLink y = tail();
    while (x != nullptr) {
      if (eq_comp_(key, x->value)) {
        y = x;
        break;
      }
      x = lt_comp_(key, x->value) ? _left(x) : _right(x);
    }
    return y;
  }
public:
  TreeBase() noexcept { init(); }
  ~TreeBase() noexcept { clear(); }

  inline bool empty() const noexcept { return size_ == 0; }
  inline sz_t size() const noexcept { return size_; }
  inline Iter begin() noexcept { return head_.left; }
  inline ConstIter begin() const noexcept { return head_.left; }
  inline Iter end() noexcept { return &head_; }
  inline ConstIter end() const noexcept { return &head_; }
  inline Ref get_head() noexcept { return *begin(); }
  inline ConstRef get_head() const noexcept { return *begin(); }
  inline Ref get_tail() noexcept { return *(--end()); }
  inline ConstRef get_tail() const noexcept { return *(--end()); }

  inline void clear() {
    erase_subtree(root());
    init();
  }

  inline Iter find(const ValueType& key) noexcept {
    return find_aux(key);
  }

  inline ConstIter find(const ValueType& key) const noexcept {
    return find_aux(key);
  }

  template <typename Visitor> inline void for_each(Visitor&& visitor) {
    for (auto i = begin(); i != end(); ++i)
      visitor(*i);
  }
};

}

namespace wrencc {

template <typename Tp>
class AVLTree final : public tree::TreeBase<Tp, tree::AVLNode<Tp>> {
};

template <typename Tp>
class RBTree final : public tree::TreeBase<Tp, tree::RBNode<Tp>> {
};

}
<commit_msg>:construction: chore(tree): finished avl-tree and rb-tree methods<commit_after>// Copyright (c) 2020 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER 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.
#pragma once

#include <algorithm>
#include <tuple>
#include "helper.hh"

namespace wrencc::tree {

using ColorType = bool;
static constexpr ColorType kColorRed = false;
static constexpr ColorType kColorBlk = true;
static constexpr int kHeightMark = 0xff;

struct NodeBase;
struct AVLNodeBase;
struct RBNodeBase;
using BasePtr       = NodeBase*;
using ConstBasePtr  = const NodeBase*;

namespace impl::avl {
  void insert(bool insert_left, BasePtr x, BasePtr p, NodeBase& header) noexcept;
  void erase(BasePtr x, NodeBase& root) noexcept;
}

namespace impl::rb {
  void insert(bool insert_left, BasePtr x, BasePtr p, NodeBase& header) noexcept;
  void erase(BasePtr x, NodeBase& header) noexcept;
}

struct NodeBase {
  BasePtr parent;
  BasePtr left;
  BasePtr right;

  template <typename AVL = AVLNodeBase> inline AVL* as_avl() noexcept {
    return static_cast<AVL*>(this);
  }

  template <typename RB = AVLNodeBase> inline RB* as_rb() noexcept {
    return static_cast<RB*>(this);
  }

  static BasePtr successor(BasePtr x) noexcept {
    if (x->right != nullptr) {
      x = x->right;
      while (x->left != nullptr)
        x = x->left;
    }
    else {
      BasePtr y = x->parent;
      while (x == y->right) {
        x = y;
        y = y->parent;
      }
      if (x->right != y)
        x = y;
    }
    return x;
  }

  template <typename HeadChecker>
  static BasePtr predecessor(BasePtr x, HeadChecker&& checker) noexcept {
    if (checker(x) && x->parent->parent == x) {
      x = x->right;
    }
    else if (x->left != nullptr) {
      x = x->left;
      while (x->right != nullptr)
        x = x->right;
    }
    else {
      BasePtr y = x->parent;
      while (x == y->left) {
        x = y;
        y = y->parent;
      }
      x = y;
    }
    return x;
  }
};

struct AVLNodeBase : public NodeBase {
  int height;

  inline void set_marker() noexcept { height = kHeightMark; }
  inline bool is_marker() const noexcept { return height == kHeightMark; }
  inline void set_height(int h) noexcept { height = h; }

  inline int lheight() const noexcept {
    return left != nullptr ? left->as_avl()->height : 0;
  }

  inline int rheight() const noexcept {
    return right != nullptr ? right->as_avl()->height : 0;
  }

  inline void update_height() noexcept {
    height = std::max(lheight(), rheight()) + 1;
  }
};

struct RBNodeBase : public NodeBase {
  ColorType color;

  inline void set_marker() noexcept { as_red(); }
  inline bool is_marker() const noexcept { return is_red(); }

  inline bool is_red() const noexcept { return color == kColorRed; }
  inline bool is_blk() const noexcept { return color == kColorBlk; }
  inline void as_red() noexcept { color = kColorRed; }
  inline void as_blk() noexcept { color = kColorBlk; }
  inline void set_color(ColorType c) noexcept { color = c; }
};

template <typename Value> struct AVLNode : public AVLNodeBase {
  Value value;
};

template <typename Value> struct RBNode : public RBNodeBase {
  Value value;
};

template <typename _Tp, typename _Ref, typename _Ptr, typename _Node>
struct TreeIter {
  using Iter = TreeIter<_Tp, _Tp&, _Tp*, _Node>;
  using Self = TreeIter<_Tp, _Ref, _Ptr, _Node>;
  using Ref  = _Ref;
  using Ptr  = _Ptr;
  using Link = _Node*;

  BasePtr _node{};

  TreeIter() noexcept {}
  TreeIter(BasePtr x) noexcept : _node(x) {}
  TreeIter(ConstBasePtr x) noexcept : _node(const_cast<BasePtr>(x)) {}
  TreeIter(const Iter& x) noexcept : _node(x._node) {}

  inline void increment() noexcept { _node = NodeBase::successor(_node); }

  template <typename HeadChecker>
  inline void decrement(HeadChecker&& checker) noexcept {
    _node = NodeBase::predecessor(_node, std::move(checker));
  }

  inline Link node() const noexcept { return Link(_node); }
  inline Ref operator*() const noexcept { return Link(_node)->value; }
  inline Ptr operator->() const noexcept { return &Link(_node)->value; }

  inline bool operator==(const Self& r) const noexcept {
    return _node == r._node;
  }

  inline bool operator!=(const Self& r) const noexcept {
    return _node != r._node;
  }

  Self& operator++() noexcept { increment(); return *this; }
  Self operator++(int) noexcept { Self tmp(*this); increment(); return tmp; }

  Self& operator--() noexcept {
    decrement([](BasePtr x) { return Link(x)->is_marker(); });
    return *this;
  }

  Self operator--(int) noexcept {
    Self tmp(*this);
    decrement([](BasePtr x) { return Link(x)->is_marker(); });
    return tmp;
  }
};

template <typename Tp,
          typename Node,
          typename Less = std::less<Tp>,
          typename Equal = std::equal_to<Tp>>
class TreeBase : private UnCopyable {
public:
  using ValueType = Tp;
  using Iter      = TreeIter<Tp, Tp&, Tp*, Node>;
  using ConstIter = TreeIter<Tp, const Tp&, const Tp*, Node>;
  using Ref       = Tp&;
  using ConstRef  = const Tp&;
protected:
  using Link      = Node*;
  using ConstLink = const Node*;
  using Alloc     = wrencc::SimpleAlloc<Node>;

  sz_t size_{};
  Node head_{};
  Less lt_comp_{};
  Equal eq_comp_{};

  static inline Link _parent(BasePtr x) noexcept { return Link(x)->parent; }
  static inline ConstLink _parent(ConstBasePtr x) noexcept { return ConstLink(x)->parent; }
  static inline Link _left(BasePtr x) noexcept { return Link(x)->left; }
  static inline ConstLink _left(ConstBasePtr x) noexcept { return ConstLink(x)->left; }
  static inline Link _right(BasePtr x) noexcept { return Link(x)->right; }
  static inline ConstLink _right(ConstBasePtr x) noexcept { return ConstLink(x)->right; }

  inline void init() noexcept {
    size_ = 0;
    head_.parent = nullptr;
    head_.left = head_.right = &head_;
    head_.set_marker();
  }

  inline Link root() noexcept { return Link(head_.parent); }
  inline ConstLink root() const noexcept { return ConstLink(head_.parent); }
  inline Link tail() noexcept { return Link(&head_); }
  inline ConstLink tail() const noexcept { return ConstLink(&head_); }
  inline Link lmost() noexcept { return Link(head_.left); }
  inline ConstLink lmost() noexcept { return ConstLink(head_.left); }
  inline Link rmost() noexcept { return Link(head_.right); }
  inline ConstLink rmost() const noexcept { return ConstLink(head_.right); }

  inline Link get_node() noexcept { return Alloc::allocate(); }
  inline void put_node(Link p) noexcept { Alloc::deallocate(p); }

  Link create_node(const ValueType& val) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, val);
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  Link create_node(ValueType&& val) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, std::move(val));
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  template <typename... Args> Link create_node(Args&&... args) {
    Link tmp = get_node();
    try {
      construct(&tmp->value, std::forward<Args>(args)...);
    }
    catch (...) {
      put_node(tmp);
      throw;
    }
    return tmp;
  }

  void destroy_node(Link p) {
    destroy(&p->value);
    put_node(p);
  }

  inline std::tuple<bool, Link, bool> find_insertion_pos(const ValueType& key) {
    Link x = root();
    Link p = tail();
    while (x != nullptr) {
      if (eq_comp_(key, x->value))
        return std::make_tuple(false, nullptr, false);

      p = x;
      x = lt_comp_(key, x->value) ? _left(x) : _right(x);
    }
    bool insert_left = x != nullptr || p == tail() || lt_comp_(key, p->value);

    return std::make_tuple(true, p, insert_left);
  }

  template <typename Insertion>
  inline void insert_aux(Insertion&& insert_fn, const ValueType& value) {
    auto [r, p, insert_left] = find_insertion_pos(value);
    if (r) {
      insert_fn(insert_left, create_node(value), p, head_);
      ++size_;
    }
  }

  template <typename Insertion>
  inline void insert_aux(Insertion&& insert_fn, ValueType&& value) {
    auto [r, p, insert_left] = find_insertion_pos(value);
    if (r) {
      insert_fn(insert_left, create_node(std::move(value)), p, head_);
      ++size_;
    }
  }

  template <typename Insertion, typename... Args>
  inline void insert_aux(Insertion&& insert_fn, Args&&... args) {
    Link tmp = create_node(std::forward<Args>(args)...);
    auto [r, p, insert_left] = find_insertion_pos(tmp->value);
    if (r) {
      insert_fn(insert_left, tmp, p, head_);
      ++size_;
    }
    else {
      destroy_node(tmp);
    }
  }

  template <typename Eraser> inline void erase_aux(Eraser&& erase_fn, Link p) {
    if (size_ != 0) {
      erase_fn(p, head_);
      destroy_node(p);
      --size_;
    }
  }

  void erase_subtree(Link x) {
    while (x != nullptr) {
      erase_subtree(_right(x));
      Link y = _left(x);
      destroy_node(x);
      x = y;
    }
  }

  inline ConstLink find_aux(const ValueType& key) const noexcept {
    ConstLink x = root();
    ConstLink y = tail();
    while (x != nullptr) {
      if (eq_comp_(key, x->value)) {
        y = x;
        break;
      }
      x = lt_comp_(key, x->value) ? _left(x) : _right(x);
    }
    return y;
  }
public:
  TreeBase() noexcept { init(); }
  ~TreeBase() noexcept { clear(); }

  inline bool empty() const noexcept { return size_ == 0; }
  inline sz_t size() const noexcept { return size_; }
  inline Iter begin() noexcept { return head_.left; }
  inline ConstIter begin() const noexcept { return head_.left; }
  inline Iter end() noexcept { return &head_; }
  inline ConstIter end() const noexcept { return &head_; }
  inline Ref get_head() noexcept { return *begin(); }
  inline ConstRef get_head() const noexcept { return *begin(); }
  inline Ref get_tail() noexcept { return *(--end()); }
  inline ConstRef get_tail() const noexcept { return *(--end()); }

  inline void clear() {
    erase_subtree(root());
    init();
  }

  inline Iter find(const ValueType& key) noexcept {
    return find_aux(key);
  }

  inline ConstIter find(const ValueType& key) const noexcept {
    return find_aux(key);
  }

  template <typename Visitor> inline void for_each(Visitor&& visitor) {
    for (auto i = begin(); i != end(); ++i)
      visitor(*i);
  }
};

}

namespace wrencc {

template <typename Tp>
class AVLTree final : public tree::TreeBase<Tp, tree::AVLNode<Tp>> {
  using Base      = tree::TreeBase<Tp, tree::AVLNode<Tp>>;
  using ValueType = typename Base::ValueType;
  using ConstIter = typename Base::ConstIter;
public:
  void insert(const ValueType&& x) {
    insert_aux(tree::impl::avl::insert, x);
  }

  void insert(ValueType&& x) {
    insert_aux(tree::impl::avl::insert, std::move(x));
  }

  template <typename... Args> void insert(Args&&... args) {
    insert_aux(tree::impl::avl::insert, std::forward<Args>(args)...);
  }

  void erase(ConstIter pos) {
    erase_aux(tree::impl::avl::erase, pos.node());
  }
};

template <typename Tp>
class RBTree final : public tree::TreeBase<Tp, tree::RBNode<Tp>> {
  using Base      = tree::TreeBase<Tp, tree::RBNode<Tp>>;
  using ValueType = typename Base::ValueType;
  using ConstIter = typename Base::ConstIter;
public:
  void insert(const ValueType& x) {
    insert_aux(tree::impl::rb::insert, x);
  }

  void insert(ValueType&& x) {
    insert_aux(tree::impl::rb::insert, std::move(x));
  }

  template <typename... Args> void insert(Args&&... args) {
    insert_aux(tree::impl::rb::insert, std::forward<Args>(args)...);
  }

  void erase(ConstIter pos) {
    erase_aux(tree::impl::rb::erase, pos.node());
  }
};

}
<|endoftext|>


<commit_before>#include "MacauPrior.h"

#include <SmurffCpp/Utils/Distribution.h>
#include <Utils/Error.h>
#include <Utils/counters.h>

#include <ios>

namespace smurff {

MacauPrior::MacauPrior(TrainSession &trainSession, uint32_t mode)
    : NormalPrior(trainSession, mode, "MacauPrior")
{
    beta_precision = SideInfoConfig::BETA_PRECISION_DEFAULT_VALUE;
    tol = SideInfoConfig::TOL_DEFAULT_VALUE;

    enable_beta_precision_sampling = Config::ENABLE_BETA_PRECISION_SAMPLING_DEFAULT_VALUE;
}

MacauPrior::~MacauPrior()
{
}

void MacauPrior::init()
{
   NormalPrior::init();

   THROWERROR_ASSERT_MSG(Features->rows() == num_item(), "Number of rows in train must be equal to number of rows in features");

   if (use_FtF)
   {
      std::uint64_t dim = num_feat();
      FtF_plus_precision.resize(dim, dim);
      Features->At_mul_A(FtF_plus_precision);
      FtF_plus_precision.diagonal().array() += beta_precision;
   }

   Uhat.resize(num_item(), num_latent());
   Uhat.setZero();

   beta().resize(num_feat(), num_latent());
   beta().setZero();

   BtB = beta().transpose() * beta();
}

void MacauPrior::update_prior()
{
    /*
>> compute_uhat:                     0.5012     (12%) in        110
>> main:                             4.1396     (100%) in       1
>> rest of update_prior:             0.1684     (4%) in 110
>> sample hyper mu/Lambda:           0.3804     (9%) in 110
>> sample_beta:                      1.4927     (36%) in        110
>> sample_latents:                   3.8824     (94%) in        220
>> step:                             3.9824     (96%) in        111
>> update_prior:                     2.5436     (61%) in        110
*/
    COUNTER("update_prior");
    {
        COUNTER("rest of update_prior");

    }

    // sampling Gaussian
    {
        COUNTER("sample hyper mu/Lambda");
        //uses: U, Uhat
        // writes: Udelta
        // complexity: num_latent x num_items
        Udelta = U() - Uhat;
        // uses: Udelta
        // complexity: num_latent x num_items
        std::tie(mu(), Lambda) = CondNormalWishart(Udelta, mu0, b0, WI + beta_precision * BtB, df + num_feat());
    }

    // uses: U, F
    // writes: Ft_y
    // uses: U, F
    // writes: Ft_y
    // complexity: num_latent x num_feat x num_item
    compute_Ft_y(Ft_y);

    sample_beta();

    {
        COUNTER("compute_uhat");
        // Uhat = beta * F
        // uses: beta, F
        // output: Uhat
        // complexity: num_feat x num_latent x num_item
        Features->compute_uhat(Uhat, beta());
    }

    if (enable_beta_precision_sampling)
    {
        // uses: beta
        // writes: FtF
        COUNTER("sample_beta_precision");
        double old_beta = beta_precision;
        beta_precision = sample_beta_precision(BtB, Lambda, beta_precision_nu0, beta_precision_mu0, beta().rows());
        FtF_plus_precision.diagonal().array() += beta_precision - old_beta;
   }
}

void MacauPrior::sample_beta()
{
    COUNTER("sample_beta");
    if (use_FtF)
    {
        // uses: FtF, Ft_y,
        // writes: beta()
        // complexity: num_feat^3
        beta() = FtF_plus_precision.llt().solve(Ft_y);
    }
    else
    {
        // uses: Features, beta_precision, Ft_y,
        // writes: beta
        // complexity: num_feat x num_feat x num_iter
        blockcg_iter = Features->solve_blockcg(beta(), beta_precision, Ft_y, tol, 32, 8, throw_on_cholesky_error);
    }
    // complexity: num_feat x num_feat x num_latent
    BtB = beta().transpose() * beta();
}

const Vector MacauPrior::fullMu(int n) const
{
   return mu() + Uhat.row(n);
}

void MacauPrior::compute_Ft_y(Matrix& Ft_y)
{
    COUNTER("compute Ft_y");
   // Ft_y = (U .- mu + Normal(0, Lambda^-1)) * F + std::sqrt(beta_precision) * Normal(0, Lambda^-1)
   // Ft_y is [ num_latent x num_feat ] matrix

   //HyperU: num_latent x num_item
   HyperU = (U() + MvNormal(Lambda, num_item())).rowwise() - mu();
   Ft_y = Features->A_mul_B(HyperU); // num_latent x num_feat

   //--  add beta_precision
   HyperU2 = MvNormal(Lambda, num_feat()); // num_latent x num_feat
   Ft_y += std::sqrt(beta_precision) * HyperU2;
}

void MacauPrior::addSideInfo(const std::shared_ptr<ISideInfo>& side, double bp, double to, bool di, bool sa, bool th)
{
    Features = side;
    beta_precision = bp;
    tol = to;
    use_FtF = di;
    enable_beta_precision_sampling = sa;
    throw_on_cholesky_error = th;

    // Hyper-prior for beta_precision (mean 1.0, var of 1e+3):
    beta_precision_mu0 = 1.0;
    beta_precision_nu0 = 1e-3;
}

std::ostream& MacauPrior::info(std::ostream &os, std::string indent)
{
   NormalPrior::info(os, indent);
   os << indent << " SideInfo: ";
   Features->print(os);
   os << indent << " Method: ";
   if (use_FtF)
   {
      os << "Cholesky Decomposition";
      double needs_gb = (double)num_feat() / 1024. * (double)num_feat() / 1024. / 1024.;
      if (needs_gb > 1.0) os << " (needing " << needs_gb << " GB of memory)";
      os << std::endl;
   } else {
      os << "CG Solver with tolerance: " << std::scientific << tol << std::fixed << std::endl;
   }
   os << indent << " BetaPrecision: ";
   if (enable_beta_precision_sampling)
   {
       os << "sampled around ";
   }
   else
   {
       os << "fixed at ";
   }
   os << beta_precision << std::endl;
   return os;
}

std::ostream &MacauPrior::status(std::ostream &os, std::string indent) const
{
   os << indent << m_name << ": " << std::endl;
   indent += "  ";
   os << indent << "mu           = " <<  mu() << std::endl;
   os << indent << "Uhat mean    = " <<  Uhat.rowwise().mean().transpose() << std::endl;
   os << indent << "blockcg iter = " << blockcg_iter << std::endl;
   os << indent << "FtF_plus_prec= " << FtF_plus_precision.norm() << std::endl;
   os << indent << "HyperU       = " << HyperU.norm() << std::endl;
   os << indent << "HyperU2      = " << HyperU2.norm() << std::endl;
   os << indent << "Beta         = " << beta().norm() << std::endl;
   os << indent << "beta_precision  = " << beta_precision << std::endl;
   os << indent << "Ft_y         = " << Ft_y.norm() << std::endl;
   return os;
}

std::pair<double, double> MacauPrior::posterior_beta_precision(const Matrix & BtB, Matrix & Lambda_u, double nu, double mu, int N)
{
   double nux = nu + N * BtB.cols();
   double mux = mu * nux / (nu + mu * (BtB.selfadjointView<Eigen::Lower>() * Lambda_u).trace());
   double b = nux / 2;
   double c = 2 * mux / nux;
   return std::make_pair(b, c);
}

double MacauPrior::sample_beta_precision(const Matrix & BtB, Matrix & Lambda_u, double nu, double mu, int N)
{
   auto gamma_post = posterior_beta_precision(BtB, Lambda_u, nu, mu, N);
   return rand_gamma(gamma_post.first, gamma_post.second);
}
} // end namespace smurff
<commit_msg>FIX: print Uhat mean accross cols<commit_after>#include "MacauPrior.h"

#include <SmurffCpp/Utils/Distribution.h>
#include <Utils/Error.h>
#include <Utils/counters.h>

#include <ios>

namespace smurff {

MacauPrior::MacauPrior(TrainSession &trainSession, uint32_t mode)
    : NormalPrior(trainSession, mode, "MacauPrior")
{
    beta_precision = SideInfoConfig::BETA_PRECISION_DEFAULT_VALUE;
    tol = SideInfoConfig::TOL_DEFAULT_VALUE;

    enable_beta_precision_sampling = Config::ENABLE_BETA_PRECISION_SAMPLING_DEFAULT_VALUE;
}

MacauPrior::~MacauPrior()
{
}

void MacauPrior::init()
{
   NormalPrior::init();

   THROWERROR_ASSERT_MSG(Features->rows() == num_item(), "Number of rows in train must be equal to number of rows in features");

   if (use_FtF)
   {
      std::uint64_t dim = num_feat();
      FtF_plus_precision.resize(dim, dim);
      Features->At_mul_A(FtF_plus_precision);
      FtF_plus_precision.diagonal().array() += beta_precision;
   }

   Uhat.resize(num_item(), num_latent());
   Uhat.setZero();

   beta().resize(num_feat(), num_latent());
   beta().setZero();

   BtB = beta().transpose() * beta();
}

void MacauPrior::update_prior()
{
    /*
>> compute_uhat:                     0.5012     (12%) in        110
>> main:                             4.1396     (100%) in       1
>> rest of update_prior:             0.1684     (4%) in 110
>> sample hyper mu/Lambda:           0.3804     (9%) in 110
>> sample_beta:                      1.4927     (36%) in        110
>> sample_latents:                   3.8824     (94%) in        220
>> step:                             3.9824     (96%) in        111
>> update_prior:                     2.5436     (61%) in        110
*/
    COUNTER("update_prior");
    {
        COUNTER("rest of update_prior");

    }

    // sampling Gaussian
    {
        COUNTER("sample hyper mu/Lambda");
        //uses: U, Uhat
        // writes: Udelta
        // complexity: num_latent x num_items
        Udelta = U() - Uhat;
        // uses: Udelta
        // complexity: num_latent x num_items
        std::tie(mu(), Lambda) = CondNormalWishart(Udelta, mu0, b0, WI + beta_precision * BtB, df + num_feat());
    }

    // uses: U, F
    // writes: Ft_y
    // uses: U, F
    // writes: Ft_y
    // complexity: num_latent x num_feat x num_item
    compute_Ft_y(Ft_y);

    sample_beta();

    {
        COUNTER("compute_uhat");
        // Uhat = beta * F
        // uses: beta, F
        // output: Uhat
        // complexity: num_feat x num_latent x num_item
        Features->compute_uhat(Uhat, beta());
    }

    if (enable_beta_precision_sampling)
    {
        // uses: beta
        // writes: FtF
        COUNTER("sample_beta_precision");
        double old_beta = beta_precision;
        beta_precision = sample_beta_precision(BtB, Lambda, beta_precision_nu0, beta_precision_mu0, beta().rows());
        FtF_plus_precision.diagonal().array() += beta_precision - old_beta;
   }
}

void MacauPrior::sample_beta()
{
    COUNTER("sample_beta");
    if (use_FtF)
    {
        // uses: FtF, Ft_y,
        // writes: beta()
        // complexity: num_feat^3
        beta() = FtF_plus_precision.llt().solve(Ft_y);
    }
    else
    {
        // uses: Features, beta_precision, Ft_y,
        // writes: beta
        // complexity: num_feat x num_feat x num_iter
        blockcg_iter = Features->solve_blockcg(beta(), beta_precision, Ft_y, tol, 32, 8, throw_on_cholesky_error);
    }
    // complexity: num_feat x num_feat x num_latent
    BtB = beta().transpose() * beta();
}

const Vector MacauPrior::fullMu(int n) const
{
   return mu() + Uhat.row(n);
}

void MacauPrior::compute_Ft_y(Matrix& Ft_y)
{
    COUNTER("compute Ft_y");
   // Ft_y = (U .- mu + Normal(0, Lambda^-1)) * F + std::sqrt(beta_precision) * Normal(0, Lambda^-1)
   // Ft_y is [ num_latent x num_feat ] matrix

   //HyperU: num_latent x num_item
   HyperU = (U() + MvNormal(Lambda, num_item())).rowwise() - mu();
   Ft_y = Features->A_mul_B(HyperU); // num_latent x num_feat

   //--  add beta_precision
   HyperU2 = MvNormal(Lambda, num_feat()); // num_latent x num_feat
   Ft_y += std::sqrt(beta_precision) * HyperU2;
}

void MacauPrior::addSideInfo(const std::shared_ptr<ISideInfo>& side, double bp, double to, bool di, bool sa, bool th)
{
    Features = side;
    beta_precision = bp;
    tol = to;
    use_FtF = di;
    enable_beta_precision_sampling = sa;
    throw_on_cholesky_error = th;

    // Hyper-prior for beta_precision (mean 1.0, var of 1e+3):
    beta_precision_mu0 = 1.0;
    beta_precision_nu0 = 1e-3;
}

std::ostream& MacauPrior::info(std::ostream &os, std::string indent)
{
   NormalPrior::info(os, indent);
   os << indent << " SideInfo: ";
   Features->print(os);
   os << indent << " Method: ";
   if (use_FtF)
   {
      os << "Cholesky Decomposition";
      double needs_gb = (double)num_feat() / 1024. * (double)num_feat() / 1024. / 1024.;
      if (needs_gb > 1.0) os << " (needing " << needs_gb << " GB of memory)";
      os << std::endl;
   } else {
      os << "CG Solver with tolerance: " << std::scientific << tol << std::fixed << std::endl;
   }
   os << indent << " BetaPrecision: ";
   if (enable_beta_precision_sampling)
   {
       os << "sampled around ";
   }
   else
   {
       os << "fixed at ";
   }
   os << beta_precision << std::endl;
   return os;
}

std::ostream &MacauPrior::status(std::ostream &os, std::string indent) const
{
   os << indent << m_name << ": " << std::endl;
   indent += "  ";
   os << indent << "mu           = " <<  mu() << std::endl;
   os << indent << "Uhat mean    = " <<  Uhat.colwise().mean() << std::endl;
   os << indent << "blockcg iter = " << blockcg_iter << std::endl;
   os << indent << "FtF_plus_prec= " << FtF_plus_precision.norm() << std::endl;
   os << indent << "HyperU       = " << HyperU.norm() << std::endl;
   os << indent << "HyperU2      = " << HyperU2.norm() << std::endl;
   os << indent << "Beta         = " << beta().norm() << std::endl;
   os << indent << "beta_precision  = " << beta_precision << std::endl;
   os << indent << "Ft_y         = " << Ft_y.norm() << std::endl;
   return os;
}

std::pair<double, double> MacauPrior::posterior_beta_precision(const Matrix & BtB, Matrix & Lambda_u, double nu, double mu, int N)
{
   double nux = nu + N * BtB.cols();
   double mux = mu * nux / (nu + mu * (BtB.selfadjointView<Eigen::Lower>() * Lambda_u).trace());
   double b = nux / 2;
   double c = 2 * mux / nux;
   return std::make_pair(b, c);
}

double MacauPrior::sample_beta_precision(const Matrix & BtB, Matrix & Lambda_u, double nu, double mu, int N)
{
   auto gamma_post = posterior_beta_precision(BtB, Lambda_u, nu, mu, N);
   return rand_gamma(gamma_post.first, gamma_post.second);
}
} // end namespace smurff
<|endoftext|>


<commit_before>#ifndef __FONT_HPP_INCLUDED
#define __FONT_HPP_INCLUDED

#include "cpp/ylikuutio/common/globals.hpp"
#include "render_templates.hpp"
#include "material.hpp"
#include "cpp/ylikuutio/hierarchy/hierarchy_templates.hpp"

// Include standard headers
#include <iostream>      // std::cout, std::cin, std::cerr
#include <queue>         // std::queue
#include <stdint.h>      // uint32_t etc.
#include <string>        // std::string
#include <vector>        // std::vector
#include <unordered_map> // std::unordered_map

namespace model
{
    class Material;
    class Glyph;

    class VectorFont
    {
        public:
            // constructor.
            // TODO: `VectorFont` constructor also creates each `Glyph` and binds them to the `VectorFont`.
            VectorFont(VectorFontStruct vector_font_struct);

            // destructor.
            // Destroying a `VectorFont` destroys also all `Text3D` entities, and after that all `Glyph` entities.
            ~VectorFont();

            // this method sets a text3D pointer.
            void set_text3D_pointer(uint32_t childID, void* parent_pointer);

            // this method sets a glyph pointer.
            void set_glyph_pointer(uint32_t childID, void* parent_pointer);

            // this method sets pointer to this species to nullptr, sets `parent_pointer` according to the input, and requests a new `childID` from the new material.
            void bind_to_new_parent(model::Material *new_material_pointer);

            // The rest fields are created in the constructor.
            uint32_t image_width;
            uint32_t image_height;

            model::Material* parent_pointer; // pointer to `Material`.

            friend class Glyph;
            friend class Text3D;
            template<class T1>
                friend void render_children(std::vector<void*> &child_pointer_vector);
            template<class T1>
                friend void hierarchy::bind_child_to_parent(T1 child_pointer, std::vector<void*> &child_pointer_vector, std::queue<uint32_t> &free_childID_queue);
            template<class T1, class T2>
                friend void hierarchy::bind_child_to_new_parent(T1 child_pointer, T2 new_parent_pointer, std::vector<void*> &old_child_pointer_vector, std::queue<uint32_t> &old_free_childID_queue);

        private:
            void bind_to_parent();

            // this method returns a pointer to `Glyph` that matches the given `unicode_string`,
            // and `nullptr` if this `VectorFont` does not such a `Glyph`.
            model::Glyph* get_glyph_pointer(std::string unicode_string);

            // this method renders all glyphs of this `VectorFont`.
            void render();

            std::string font_file_format;          // type of the model file, eg. `"bmp"`.
            std::string font_filename;             // filename of the model file.
            GLfloat vertex_scaling_factor;
            uint32_t childID;                      // species ID, returned by `model::Material->get_speciesID()`.
            const char* char_font_file_format;
            const char* char_font_filename;

            std::vector<std::vector<std::vector<glm::vec2>>> glyph_vertex_data;
            std::vector<std::vector<glm::vec2>> glyph_UV_data;
            std::vector<std::vector<glm::vec2>> glyph_normal_data;
            std::vector<std::string> glyph_names;
            std::vector<std::string> unicode_strings;

            std::vector<void*> glyph_pointer_vector;
            std::vector<void*> text3D_pointer_vector;
            std::queue<uint32_t> free_glyphID_queue;
            std::queue<uint32_t> free_text3D_ID_queue;

            std::unordered_map<std::string, model::Glyph*> unicode_glyph_map;
    };
}

#endif
<commit_msg>Reordered code lines.<commit_after>#ifndef __FONT_HPP_INCLUDED
#define __FONT_HPP_INCLUDED

#include "cpp/ylikuutio/common/globals.hpp"
#include "render_templates.hpp"
#include "material.hpp"
#include "cpp/ylikuutio/hierarchy/hierarchy_templates.hpp"

// Include standard headers
#include <iostream>      // std::cout, std::cin, std::cerr
#include <queue>         // std::queue
#include <stdint.h>      // uint32_t etc.
#include <string>        // std::string
#include <vector>        // std::vector
#include <unordered_map> // std::unordered_map

namespace model
{
    class Material;
    class Glyph;

    class VectorFont
    {
        public:
            // constructor.
            // TODO: `VectorFont` constructor also creates each `Glyph` and binds them to the `VectorFont`.
            VectorFont(VectorFontStruct vector_font_struct);

            // destructor.
            // Destroying a `VectorFont` destroys also all `Text3D` entities, and after that all `Glyph` entities.
            ~VectorFont();

            // this method sets `Glyph` pointer.
            void set_glyph_pointer(uint32_t childID, void* parent_pointer);

            // this method sets `Text3D` pointer.
            void set_text3D_pointer(uint32_t childID, void* parent_pointer);

            // this method sets pointer to this species to nullptr, sets `parent_pointer` according to the input, and requests a new `childID` from the new material.
            void bind_to_new_parent(model::Material *new_material_pointer);

            // The rest fields are created in the constructor.
            uint32_t image_width;
            uint32_t image_height;

            model::Material* parent_pointer; // pointer to `Material`.

            friend class Glyph;
            friend class Text3D;
            template<class T1>
                friend void render_children(std::vector<void*> &child_pointer_vector);
            template<class T1>
                friend void hierarchy::bind_child_to_parent(T1 child_pointer, std::vector<void*> &child_pointer_vector, std::queue<uint32_t> &free_childID_queue);
            template<class T1, class T2>
                friend void hierarchy::bind_child_to_new_parent(T1 child_pointer, T2 new_parent_pointer, std::vector<void*> &old_child_pointer_vector, std::queue<uint32_t> &old_free_childID_queue);

        private:
            void bind_to_parent();

            // this method returns a pointer to `Glyph` that matches the given `unicode_string`,
            // and `nullptr` if this `VectorFont` does not such a `Glyph`.
            model::Glyph* get_glyph_pointer(std::string unicode_string);

            // this method renders all glyphs of this `VectorFont`.
            void render();

            std::string font_file_format;          // type of the model file, eg. `"bmp"`.
            std::string font_filename;             // filename of the model file.
            GLfloat vertex_scaling_factor;
            uint32_t childID;                      // species ID, returned by `model::Material->get_speciesID()`.
            const char* char_font_file_format;
            const char* char_font_filename;

            std::vector<std::vector<std::vector<glm::vec2>>> glyph_vertex_data;
            std::vector<std::vector<glm::vec2>> glyph_UV_data;
            std::vector<std::vector<glm::vec2>> glyph_normal_data;
            std::vector<std::string> glyph_names;
            std::vector<std::string> unicode_strings;

            std::vector<void*> glyph_pointer_vector;
            std::vector<void*> text3D_pointer_vector;
            std::queue<uint32_t> free_glyphID_queue;
            std::queue<uint32_t> free_text3D_ID_queue;

            std::unordered_map<std::string, model::Glyph*> unicode_glyph_map;
    };
}

#endif
<|endoftext|>


<commit_before>//============================================================================
// Name        : SerialPortTest.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <string.h>

#include "ASIOSerialPort.h"
#include <iostream>

using namespace std;

int main() {
	std::cout << "Testing serial API..." << std::endl;
	ASIOSerialPort serialPort("/dev/arduino", 9600);
	for(int i=0; i < 6; i++) {
		serialPort.write("T");
		sleep(1);
	}
	while(true) {
		std::cout << serialPort.readln() << std::endl;
	}
	serialPort.close();
}
<commit_msg>Removed unecessary std using.<commit_after>//============================================================================
// Name        : SerialPortTest.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <string.h>

#include "ASIOSerialPort.h"
#include <iostream>

int main() {
	std::cout << "Testing serial API..." << std::endl;
	ASIOSerialPort serialPort("/dev/arduino", 9600);
	for(int i=0; i < 6; i++) {
		serialPort.write("T");
		sleep(1);
	}
	while(true) {
		std::cout << serialPort.readln() << std::endl;
	}
	serialPort.close();
}
<|endoftext|>


<commit_before>/*
 *  eventlistview.cpp  -  base class for widget showing list of alarms
 *  Program:  kalarm
 *  Copyright © 2007 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <QHeaderView>
#include <QMouseEvent>
#include <QApplication>

#include <kdebug.h>

#include "eventlistmodel.h"
#include "templatelistfiltermodel.h"
#include "eventlistview.moc"

EventListView::EventListView(QWidget* parent)
	: QTreeView(parent)
{
	setRootIsDecorated(false);    // don't show expander icons for child-less items
	setSortingEnabled(true);
	setAllColumnsShowFocus(true);
	setSelectionMode(ExtendedSelection);
	setSelectionBehavior(SelectRows);
	setTextElideMode(Qt::ElideRight);
}

/******************************************************************************
* Return the event referred to by an index.
*/
KCal::Event* EventListView::event(const QModelIndex& index) const
{
	return eventFilterModel()->event(index);
}

KCal::Event* EventListView::event(int row) const
{
	return eventFilterModel()->event(row);
}

/******************************************************************************
* Select one event and make it the current item.
*/
void EventListView::select(const QString& eventId)
{
	select(eventModel()->eventIndex(eventId));
}

void EventListView::select(const QModelIndex& index)
{
	selectionModel()->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}

/******************************************************************************
* Return the single selected item.
* Reply = invalid if no items are selected, or if multiple items are selected.
*/
QModelIndex EventListView::selectedIndex() const
{
	QModelIndexList list = selectionModel()->selectedRows();
	if (list.count() != 1)
		return QModelIndex();
	return list[0];
}

/******************************************************************************
* Return the single selected event.
* Reply = null if no items are selected, or if multiple items are selected.
*/
KCal::Event* EventListView::selectedEvent() const
{
	QModelIndexList list = selectionModel()->selectedRows();
	if (list.count() != 1)
		return 0;
kDebug()<<"SelectedEvent() count="<<list.count()<<endl;
	QAbstractProxyModel* proxy = static_cast<const QAbstractProxyModel*>(list[0].model());
	QModelIndex source = proxy->mapToSource(list[0]);
	return static_cast<KCal::Event*>(source.internalPointer());
}

/******************************************************************************
* Return the selected events.
*/
KCal::Event::List EventListView::selectedEvents() const
{
	KCal::Event::List elist;
	QModelIndexList ilist = selectionModel()->selectedRows();
	int count = ilist.count();
	if (count)
	{
		QAbstractProxyModel* proxy = static_cast<const QAbstractProxyModel*>(ilist[0].model());
		for (int i = 0;  i < count;  ++i)
		{
			QModelIndex source = proxy->mapToSource(ilist[i]);
			elist += static_cast<KCal::Event*>(source.internalPointer());
		}
	}
	return elist;
}

/******************************************************************************
* Called when a mouse button is released.
*/
void EventListView::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == Qt::RightButton)
		emit rightButtonClicked(e->globalPos());
	else
		QTreeView::mouseReleaseEvent(e);
}
<commit_msg>Fix compile error for some compilers<commit_after>/*
 *  eventlistview.cpp  -  base class for widget showing list of alarms
 *  Program:  kalarm
 *  Copyright © 2007 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <QHeaderView>
#include <QMouseEvent>
#include <QApplication>

#include <kdebug.h>

#include "eventlistmodel.h"
#include "templatelistfiltermodel.h"
#include "eventlistview.moc"

EventListView::EventListView(QWidget* parent)
	: QTreeView(parent)
{
	setRootIsDecorated(false);    // don't show expander icons for child-less items
	setSortingEnabled(true);
	setAllColumnsShowFocus(true);
	setSelectionMode(ExtendedSelection);
	setSelectionBehavior(SelectRows);
	setTextElideMode(Qt::ElideRight);
}

/******************************************************************************
* Return the event referred to by an index.
*/
KCal::Event* EventListView::event(const QModelIndex& index) const
{
	return eventFilterModel()->event(index);
}

KCal::Event* EventListView::event(int row) const
{
	return eventFilterModel()->event(row);
}

/******************************************************************************
* Select one event and make it the current item.
*/
void EventListView::select(const QString& eventId)
{
	select(eventModel()->eventIndex(eventId));
}

void EventListView::select(const QModelIndex& index)
{
	selectionModel()->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}

/******************************************************************************
* Return the single selected item.
* Reply = invalid if no items are selected, or if multiple items are selected.
*/
QModelIndex EventListView::selectedIndex() const
{
	QModelIndexList list = selectionModel()->selectedRows();
	if (list.count() != 1)
		return QModelIndex();
	return list[0];
}

/******************************************************************************
* Return the single selected event.
* Reply = null if no items are selected, or if multiple items are selected.
*/
KCal::Event* EventListView::selectedEvent() const
{
	QModelIndexList list = selectionModel()->selectedRows();
	if (list.count() != 1)
		return 0;
kDebug()<<"SelectedEvent() count="<<list.count()<<endl;
	const QAbstractProxyModel* proxy = static_cast<const QAbstractProxyModel*>(list[0].model());
	QModelIndex source = proxy->mapToSource(list[0]);
	return static_cast<KCal::Event*>(source.internalPointer());
}

/******************************************************************************
* Return the selected events.
*/
KCal::Event::List EventListView::selectedEvents() const
{
	KCal::Event::List elist;
	QModelIndexList ilist = selectionModel()->selectedRows();
	int count = ilist.count();
	if (count)
	{
		const QAbstractProxyModel* proxy = static_cast<const QAbstractProxyModel*>(ilist[0].model());
		for (int i = 0;  i < count;  ++i)
		{
			QModelIndex source = proxy->mapToSource(ilist[i]);
			elist += static_cast<KCal::Event*>(source.internalPointer());
		}
	}
	return elist;
}

/******************************************************************************
* Called when a mouse button is released.
*/
void EventListView::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == Qt::RightButton)
		emit rightButtonClicked(e->globalPos());
	else
		QTreeView::mouseReleaseEvent(e);
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef ITEM_HH
#define ITEM_HH
#include "config.h"

#include <string>
#include <string.h>
#include <stdio.h>
#include <memcached/engine.h>

#include "mutex.hh"
#include "locks.hh"
#include "atomic.hh"
#include "objectregistry.hh"
#include "stats.hh"

/**
 * A blob is a minimal sized storage for data up to 2^32 bytes long.
 */
class Blob {
public:

    // Constructors.

    /**
     * Create a new Blob holding the given data.
     *
     * @param start the beginning of the data to copy into this blob
     * @param len the amount of data to copy in
     *
     * @return the new Blob instance
     */
    static Blob* New(const char *start, const size_t len) {
        size_t total_len = len + sizeof(Blob);
        Blob *t = new (::operator new(total_len)) Blob(start, len);
        assert(t->length() == len);
        return t;
    }

    /**
     * Create a new Blob holding the contents of the given string.
     *
     * @param s the string whose contents go into the blob
     *
     * @return the new Blob instance
     */
    static Blob* New(const std::string& s) {
        return New(s.data(), s.length());
    }

    /**
     * Create a new Blob pre-filled with the given character.
     *
     * @param len the size of the blob
     * @param c the character to fill the blob with
     *
     * @return the new Blob instance
     */
    static Blob* New(const size_t len, const char c) {
        size_t total_len = len + sizeof(Blob);
        Blob *t = new (::operator new(total_len)) Blob(c, len);
        assert(t->length() == len);
        return t;
    }

    // Actual accessorish things.

    /**
     * Get the pointer to the contents of this Blob.
     */
    const char* getData() const {
        return data;
    }

    /**
     * Get the length of this Blob.
     */
    size_t length() const {
        return size;
    }

    /**
     * Get a std::string representation of this blob.
     */
    const std::string to_s() const {
        return std::string(data, size);
    }

    // This is necessary for making C++ happy when I'm doing a
    // placement new on fairly "normal" c++ heap allocations, just
    // with variable-sized objects.
    void operator delete(void* p) { ::operator delete(p); }

    ~Blob() {
        ObjectRegistry::onDeleteBlob(this);
    }

private:

    explicit Blob(const char *start, const size_t len) :
        size(static_cast<uint32_t>(len))
    {
        std::memcpy(data, start, len);
        ObjectRegistry::onCreateBlob(this);
    }

    explicit Blob(const char c, const size_t len) :
        size(static_cast<uint32_t>(len))
    {
        std::memset(data, c, len);
        ObjectRegistry::onCreateBlob(this);
    }

    const uint32_t size;
    char data[1];

    DISALLOW_COPY_AND_ASSIGN(Blob);
};

typedef shared_ptr<const Blob> value_t;

/**
 * The Item structure we use to pass information between the memcached
 * core and the backend. Please note that the kvstore don't store these
 * objects, so we do have an extra layer of memory copying :(
 */
class Item {
public:
    Item(const void* k, const size_t nk, const size_t nb,
         const int fl, const time_t exp, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        key.assign(static_cast<const char*>(k), nk);
        assert(id != 0);
        setData(NULL, nb);
    }

    Item(const std::string &k, const int fl, const time_t exp,
         const void *dta, const size_t nb, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        key.assign(k);
        assert(id != 0);
        setData(static_cast<const char*>(dta), nb);
    }

    Item(const std::string &k, const int fl, const time_t exp,
         value_t val, uint64_t theCas = 0,  int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), value(val), cas(theCas), id(i), vbucketId(vbid)
    {
        assert(id != 0);
        key.assign(k);
    }

    Item(const void *k, uint16_t nk, const int fl, const time_t exp,
         const void *dta, const size_t nb, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        assert(id != 0);
        key.assign(static_cast<const char*>(k), nk);
        setData(static_cast<const char*>(dta), nb);
    }

    ~Item() {}

    const char *getData() const {
        return value->getData();
    }

    value_t getValue() const {
        return value;
    }

    const std::string &getKey() const {
        return key;
    }

    int64_t getId() const {
        return id;
    }

    void setId(int64_t to) {
        id = to;
    }

    int getNKey() const {
        return static_cast<int>(key.length());
    }

    uint32_t getNBytes() const {
        return static_cast<uint32_t>(value->length());
    }

    time_t getExptime() const {
        return exptime;
    }

    int getFlags() const {
        return flags;
    }

    uint64_t getCas() const {
        return cas;
    }

    void setCas() {
        cas = nextCas();
    }

    void setCas(uint64_t ncas) {
        cas = ncas;
    }

    /**
     * Append another item to this item
     *
     * @param item the item to append to this one
     * @return true if success
     */
    bool append(const Item &item);

    /**
     * Prepend another item to this item
     *
     * @param item the item to prepend to this one
     * @return true if success
     */
    bool prepend(const Item &item);

    uint16_t getVBucketId(void) const {
        return vbucketId;
    }

    void setVBucketId(uint16_t to) {
        vbucketId = to;
    }

    /**
     * Check if this item is expired or not.
     *
     * @param asOf the time to be compared with this item's expiry time
     * @return true if this item's expiry time < asOf
     */
    bool isExpired(time_t asOf) const {
        if (getExptime() != 0 && getExptime() < asOf) {
            return true;
        }
        return false;
    }

    size_t size() {
        return sizeof(Item) + key.size() + value->length();
    }

private:
    /**
     * Set the item's data. This is only used by constructors, so we
     * make it private.
     */
    void setData(const char *dta, const size_t nb) {
        Blob *data;
        if (dta == NULL) {
            data = Blob::New(nb, '\0');
        } else {
            data = Blob::New(dta, nb);
        }

        assert(data);
        value.reset(data);
    }

    int flags;
    time_t exptime;
    std::string key;
    value_t value;
    uint64_t cas;
    int64_t id;
    uint16_t vbucketId;

    static uint64_t nextCas(void) {
        uint64_t ret;
        ret = casCounter++;

        return ret;
    }

    static Atomic<uint64_t> casCounter;
    DISALLOW_COPY_AND_ASSIGN(Item);
};

#endif
<commit_msg>MB-3587 Fix to the overflow of a flag value in Item class.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef ITEM_HH
#define ITEM_HH
#include "config.h"

#include <string>
#include <string.h>
#include <stdio.h>
#include <memcached/engine.h>

#include "mutex.hh"
#include "locks.hh"
#include "atomic.hh"
#include "objectregistry.hh"
#include "stats.hh"

/**
 * A blob is a minimal sized storage for data up to 2^32 bytes long.
 */
class Blob {
public:

    // Constructors.

    /**
     * Create a new Blob holding the given data.
     *
     * @param start the beginning of the data to copy into this blob
     * @param len the amount of data to copy in
     *
     * @return the new Blob instance
     */
    static Blob* New(const char *start, const size_t len) {
        size_t total_len = len + sizeof(Blob);
        Blob *t = new (::operator new(total_len)) Blob(start, len);
        assert(t->length() == len);
        return t;
    }

    /**
     * Create a new Blob holding the contents of the given string.
     *
     * @param s the string whose contents go into the blob
     *
     * @return the new Blob instance
     */
    static Blob* New(const std::string& s) {
        return New(s.data(), s.length());
    }

    /**
     * Create a new Blob pre-filled with the given character.
     *
     * @param len the size of the blob
     * @param c the character to fill the blob with
     *
     * @return the new Blob instance
     */
    static Blob* New(const size_t len, const char c) {
        size_t total_len = len + sizeof(Blob);
        Blob *t = new (::operator new(total_len)) Blob(c, len);
        assert(t->length() == len);
        return t;
    }

    // Actual accessorish things.

    /**
     * Get the pointer to the contents of this Blob.
     */
    const char* getData() const {
        return data;
    }

    /**
     * Get the length of this Blob.
     */
    size_t length() const {
        return size;
    }

    /**
     * Get a std::string representation of this blob.
     */
    const std::string to_s() const {
        return std::string(data, size);
    }

    // This is necessary for making C++ happy when I'm doing a
    // placement new on fairly "normal" c++ heap allocations, just
    // with variable-sized objects.
    void operator delete(void* p) { ::operator delete(p); }

    ~Blob() {
        ObjectRegistry::onDeleteBlob(this);
    }

private:

    explicit Blob(const char *start, const size_t len) :
        size(static_cast<uint32_t>(len))
    {
        std::memcpy(data, start, len);
        ObjectRegistry::onCreateBlob(this);
    }

    explicit Blob(const char c, const size_t len) :
        size(static_cast<uint32_t>(len))
    {
        std::memset(data, c, len);
        ObjectRegistry::onCreateBlob(this);
    }

    const uint32_t size;
    char data[1];

    DISALLOW_COPY_AND_ASSIGN(Blob);
};

typedef shared_ptr<const Blob> value_t;

/**
 * The Item structure we use to pass information between the memcached
 * core and the backend. Please note that the kvstore don't store these
 * objects, so we do have an extra layer of memory copying :(
 */
class Item {
public:
    Item(const void* k, const size_t nk, const size_t nb,
         const uint32_t fl, const time_t exp, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        key.assign(static_cast<const char*>(k), nk);
        assert(id != 0);
        setData(NULL, nb);
    }

    Item(const std::string &k, const uint32_t fl, const time_t exp,
         const void *dta, const size_t nb, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        key.assign(k);
        assert(id != 0);
        setData(static_cast<const char*>(dta), nb);
    }

    Item(const std::string &k, const uint32_t fl, const time_t exp,
         value_t val, uint64_t theCas = 0,  int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), value(val), cas(theCas), id(i), vbucketId(vbid)
    {
        assert(id != 0);
        key.assign(k);
    }

    Item(const void *k, uint16_t nk, const uint32_t fl, const time_t exp,
         const void *dta, const size_t nb, uint64_t theCas = 0,
         int64_t i = -1, uint16_t vbid = 0) :
        flags(fl), exptime(exp), cas(theCas), id(i), vbucketId(vbid)
    {
        assert(id != 0);
        key.assign(static_cast<const char*>(k), nk);
        setData(static_cast<const char*>(dta), nb);
    }

    ~Item() {}

    const char *getData() const {
        return value->getData();
    }

    value_t getValue() const {
        return value;
    }

    const std::string &getKey() const {
        return key;
    }

    int64_t getId() const {
        return id;
    }

    void setId(int64_t to) {
        id = to;
    }

    int getNKey() const {
        return static_cast<int>(key.length());
    }

    uint32_t getNBytes() const {
        return static_cast<uint32_t>(value->length());
    }

    time_t getExptime() const {
        return exptime;
    }

    uint32_t getFlags() const {
        return flags;
    }

    uint64_t getCas() const {
        return cas;
    }

    void setCas() {
        cas = nextCas();
    }

    void setCas(uint64_t ncas) {
        cas = ncas;
    }

    /**
     * Append another item to this item
     *
     * @param item the item to append to this one
     * @return true if success
     */
    bool append(const Item &item);

    /**
     * Prepend another item to this item
     *
     * @param item the item to prepend to this one
     * @return true if success
     */
    bool prepend(const Item &item);

    uint16_t getVBucketId(void) const {
        return vbucketId;
    }

    void setVBucketId(uint16_t to) {
        vbucketId = to;
    }

    /**
     * Check if this item is expired or not.
     *
     * @param asOf the time to be compared with this item's expiry time
     * @return true if this item's expiry time < asOf
     */
    bool isExpired(time_t asOf) const {
        if (getExptime() != 0 && getExptime() < asOf) {
            return true;
        }
        return false;
    }

    size_t size() {
        return sizeof(Item) + key.size() + value->length();
    }

private:
    /**
     * Set the item's data. This is only used by constructors, so we
     * make it private.
     */
    void setData(const char *dta, const size_t nb) {
        Blob *data;
        if (dta == NULL) {
            data = Blob::New(nb, '\0');
        } else {
            data = Blob::New(dta, nb);
        }

        assert(data);
        value.reset(data);
    }

    uint32_t flags;
    time_t exptime;
    std::string key;
    value_t value;
    uint64_t cas;
    int64_t id;
    uint16_t vbucketId;

    static uint64_t nextCas(void) {
        uint64_t ret;
        ret = casCounter++;

        return ret;
    }

    static Atomic<uint64_t> casCounter;
    DISALLOW_COPY_AND_ASSIGN(Item);
};

#endif
<|endoftext|>


<commit_before><commit_msg>Init every ColorDialog instance with Qt::red<commit_after><|endoftext|>


<commit_before>//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include <assert.h>
#include "state_file.h"

static char *divider = "========================================================================";

// Just for the iofunctions

#define LOG_THIS this->log->

int Allocio=0;

void
iofunctions::flush(void) {
	if(logfd && magic == MAGIC_LOGNUM) {
		fflush(logfd);
	}
}

void
iofunctions::init(void) {
	// iofunctions methods must not be called before this magic
	// number is set.
	magic=MAGIC_LOGNUM;
	showtick = 1;
	n_logfn = 0;
	init_log(stderr);
	log = new logfunc_t(this);
	LOG_THIS put("IO");
	LOG_THIS settype(IOLOG);
	BX_DEBUG(("Init(log file: '%s').",logfn));
}

void
iofunctions::add_logfn (logfunc_t *fn)
{
  assert (n_logfn < MAX_LOGFNS);
  logfn_list[n_logfn++] = fn;
}

void
iofunctions::set_log_action (int loglevel, int action)
{
  for (int i=0; i<n_logfn; i++)
    logfn_list[i]->setonoff(loglevel, action);
}

void
iofunctions::init_log(char *fn)
{
	assert (magic==MAGIC_LOGNUM);
	// use newfd/newfn so that we can log the message to the OLD log
	// file descriptor.
	FILE *newfd = stderr;
	char *newfn = "/dev/stderr";
	if( strcmp( fn, "-" ) != 0 ) {
		newfd = fopen(fn, "w");
		if(newfd != NULL) {
			newfn = strdup(fn);
			BX_DEBUG(("Opened log file '%s'.", fn ));
		} else {
			BX_DEBUG(("Log file '%s' not there?", fn));
			newfd = NULL;
			logfn = "(none)";
		}
	}
	logfd = newfd;
	logfn = newfn;
}

void
iofunctions::init_log(FILE *fs)
{
	assert (magic==MAGIC_LOGNUM);
	logfd = fs;

	if(fs == stderr) {
		logfn = "/dev/stderr";
	} else if(fs == stdout) {
		logfn = "/dev/stdout";
	} else {
		logfn = "(unknown)";
	}
}

void
iofunctions::init_log(int fd)
{
	assert (magic==MAGIC_LOGNUM);
	FILE *tmpfd;
	if( (tmpfd = fdopen(fd,"w")) == NULL ) {
	  BX_PANIC(("Couldn't open fd %d as a stream for writing", fd));
	  return;
	}

	init_log(tmpfd);
	return;
};

//  iofunctions::out( class, level, prefix, fmt, ap)
//  DO NOT nest out() from ::info() and the like.
//    fmt and ap retained for direct printinf from iofunctions only!

void
iofunctions::out(int f, int l, char *prefix, char *fmt, va_list ap)
{
	assert (magic==MAGIC_LOGNUM);
	assert (this != NULL);
	assert (logfd != NULL);

	if( showtick )
		fprintf(logfd, "%011lld ", bx_pc_system.time_ticks());

	if(prefix != NULL)
		fprintf(logfd, "%s ", prefix);

	if(l==LOGLEV_PANIC)
		fprintf(logfd, ">>PANIC<< ");

	vfprintf(logfd, fmt, ap);
	fprintf(logfd, "\n");
	fflush(logfd);

	return;
}

iofunctions::iofunctions(FILE *fs)
{
	init();
	init_log(fs);
}

iofunctions::iofunctions(char *fn)
{
	init();
	init_log(fn);
}

iofunctions::iofunctions(int fd)
{
	init();
	init_log(fd);
}

iofunctions::iofunctions(void)
{
	this->init();
}

iofunctions::~iofunctions(void)
{
	// flush before erasing magic number, or flush does nothing.
	this->flush();
	this->magic=0;
}

#undef LOG_THIS
#define LOG_THIS genlog->

logfunctions::logfunctions(void)
{
	put(" ");
	settype(GENLOG);
	if(io == NULL && Allocio == 0) {
		Allocio = 1;
		io = new iofunc_t(stderr);
	}
	setio(io);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::logfunctions(iofunc_t *iofunc)
{
	put(" ");
	settype(GENLOG);
	setio(iofunc);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::~logfunctions(void)
{
}

void
logfunctions::setio(iofunc_t *i)
{
  	// add pointer to iofunction object to use
	this->logio = i;
	// give iofunction a pointer to me
	i->add_logfn (this);
}

void
logfunctions::put(char *p)
{
	char *tmpbuf;
	tmpbuf=strdup("[     ]");// if we ever have more than 32 chars,
						   //  we need to rethink this
	int len=strlen(p);
	for(int i=1;i<len+1;i++) {
		tmpbuf[i]=p[i-1];
	}

	switch(len) {
	case  1: tmpbuf[2]=' ';
	case  2: tmpbuf[3]=' ';
	case  3: tmpbuf[4]=' ';
	case  4: tmpbuf[5]=' ';
	default: tmpbuf[6]=']'; tmpbuf[7]='\0'; break;
	}

	this->prefix=tmpbuf;
}

void
logfunctions::settype(int t)
{
	type=t;
}

void
logfunctions::info(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_INFO]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_ASK)
	  ask (LOGLEV_INFO, this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);

}

void
logfunctions::error(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_ERROR]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_ASK)
	  ask (LOGLEV_ERROR, this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::panic(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_PANIC]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_ASK)
	  ask (LOGLEV_PANIC, this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ldebug(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_DEBUG]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_ASK)
	  ask (LOGLEV_DEBUG, this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ask (int level, char *prefix, char *fmt, va_list ap)
{
  char buf1[1024], buf2[1024];
  vsprintf (buf1, fmt, ap);
  sprintf (buf2, "%s %s", prefix, buf1);
  // FIXME: facility set to 0 because it's unknown.
  int val = SIM->LOCAL_log_msg (prefix, level, buf2);
  switch (val)
  {
    case 0:   // user chose continue
      break;
    case 1:   // user said continue, and don't ask for this facility again.
      setonoff (level, ACT_REPORT);
      break;
    case 2:   // user chose die
      fatal (prefix, fmt, ap);
  }
}

void
logfunctions::fatal (char *prefix, char *fmt, va_list ap)
{
  static int fatal_reentry = 0;
  if (fatal_reentry) return;
  fatal_reentry++;
  bx_atexit();
  fprintf (stderr, "%s\n", divider);
  fprintf (stderr, "Bochs is exiting with the following message:\n");
  fprintf (stderr, "%s ", prefix);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n%s\n", divider);
#if 0 && defined(WIN32)
#error disabled because it  is not working yet!
  // wait for a keypress before quitting.  Depending on how bochs is
  // installed, the console window can disappear before the user has
  // a chance to read the final message.
  fprintf (stderr, "\n\nPress Enter to exit...\n");
  char buf[8];
  fgets (buf, 8, stdin);
#endif
#if !BX_DEBUGGER
  exit(1);
#else
  static Boolean dbg_exit_called = 0;
  if (dbg_exit_called == 0) {
    dbg_exit_called = 1;
    bx_dbg_exit(1);
    }
#endif
  fatal_reentry--;
}

iofunc_t *io = NULL;
logfunc_t *genlog = NULL;

void bx_center_print (FILE *file, char *line, int maxwidth)
{
  int imax;
  imax = (maxwidth - strlen(line)) >> 1;
  for (int i=0; i<imax; i++) fputc (' ', file);
  fputs (line, file);
}

<commit_msg>- if log file cannot be fopened, do not allow logfd to become a NULL   pointer.  For now, panic instead to avoid inexplicable segfaults.<commit_after>//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include <assert.h>
#include "state_file.h"

static char *divider = "========================================================================";

// Just for the iofunctions

#define LOG_THIS this->log->

int Allocio=0;

void
iofunctions::flush(void) {
	if(logfd && magic == MAGIC_LOGNUM) {
		fflush(logfd);
	}
}

void
iofunctions::init(void) {
	// iofunctions methods must not be called before this magic
	// number is set.
	magic=MAGIC_LOGNUM;
	showtick = 1;
	n_logfn = 0;
	init_log(stderr);
	log = new logfunc_t(this);
	LOG_THIS put("IO");
	LOG_THIS settype(IOLOG);
	BX_DEBUG(("Init(log file: '%s').",logfn));
}

void
iofunctions::add_logfn (logfunc_t *fn)
{
  assert (n_logfn < MAX_LOGFNS);
  logfn_list[n_logfn++] = fn;
}

void
iofunctions::set_log_action (int loglevel, int action)
{
  for (int i=0; i<n_logfn; i++)
    logfn_list[i]->setonoff(loglevel, action);
}

void
iofunctions::init_log(char *fn)
{
	assert (magic==MAGIC_LOGNUM);
	// use newfd/newfn so that we can log the message to the OLD log
	// file descriptor.
	FILE *newfd = stderr;
	char *newfn = "/dev/stderr";
	if( strcmp( fn, "-" ) != 0 ) {
		newfd = fopen(fn, "w");
		if(newfd != NULL) {
			newfn = strdup(fn);
			BX_DEBUG(("Opened log file '%s'.", fn ));
		} else {
		  	BX_PANIC(("Couldn't open log file: %s", fn));
		}
	}
	logfd = newfd;
	logfn = newfn;
}

void
iofunctions::init_log(FILE *fs)
{
	assert (magic==MAGIC_LOGNUM);
	logfd = fs;

	if(fs == stderr) {
		logfn = "/dev/stderr";
	} else if(fs == stdout) {
		logfn = "/dev/stdout";
	} else {
		logfn = "(unknown)";
	}
}

void
iofunctions::init_log(int fd)
{
	assert (magic==MAGIC_LOGNUM);
	FILE *tmpfd;
	if( (tmpfd = fdopen(fd,"w")) == NULL ) {
	  BX_PANIC(("Couldn't open fd %d as a stream for writing", fd));
	  return;
	}

	init_log(tmpfd);
	return;
};

//  iofunctions::out( class, level, prefix, fmt, ap)
//  DO NOT nest out() from ::info() and the like.
//    fmt and ap retained for direct printinf from iofunctions only!

void
iofunctions::out(int f, int l, char *prefix, char *fmt, va_list ap)
{
	assert (magic==MAGIC_LOGNUM);
	assert (this != NULL);
	assert (logfd != NULL);

	if( showtick )
		fprintf(logfd, "%011lld ", bx_pc_system.time_ticks());

	if(prefix != NULL)
		fprintf(logfd, "%s ", prefix);

	if(l==LOGLEV_PANIC)
		fprintf(logfd, ">>PANIC<< ");

	vfprintf(logfd, fmt, ap);
	fprintf(logfd, "\n");
	fflush(logfd);

	return;
}

iofunctions::iofunctions(FILE *fs)
{
	init();
	init_log(fs);
}

iofunctions::iofunctions(char *fn)
{
	init();
	init_log(fn);
}

iofunctions::iofunctions(int fd)
{
	init();
	init_log(fd);
}

iofunctions::iofunctions(void)
{
	this->init();
}

iofunctions::~iofunctions(void)
{
	// flush before erasing magic number, or flush does nothing.
	this->flush();
	this->magic=0;
}

#undef LOG_THIS
#define LOG_THIS genlog->

logfunctions::logfunctions(void)
{
	put(" ");
	settype(GENLOG);
	if(io == NULL && Allocio == 0) {
		Allocio = 1;
		io = new iofunc_t(stderr);
	}
	setio(io);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::logfunctions(iofunc_t *iofunc)
{
	put(" ");
	settype(GENLOG);
	setio(iofunc);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::~logfunctions(void)
{
}

void
logfunctions::setio(iofunc_t *i)
{
  	// add pointer to iofunction object to use
	this->logio = i;
	// give iofunction a pointer to me
	i->add_logfn (this);
}

void
logfunctions::put(char *p)
{
	char *tmpbuf;
	tmpbuf=strdup("[     ]");// if we ever have more than 32 chars,
						   //  we need to rethink this
	int len=strlen(p);
	for(int i=1;i<len+1;i++) {
		tmpbuf[i]=p[i-1];
	}

	switch(len) {
	case  1: tmpbuf[2]=' ';
	case  2: tmpbuf[3]=' ';
	case  3: tmpbuf[4]=' ';
	case  4: tmpbuf[5]=' ';
	default: tmpbuf[6]=']'; tmpbuf[7]='\0'; break;
	}

	this->prefix=tmpbuf;
}

void
logfunctions::settype(int t)
{
	type=t;
}

void
logfunctions::info(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_INFO]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_ASK)
	  ask (LOGLEV_INFO, this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);

}

void
logfunctions::error(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_ERROR]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_ASK)
	  ask (LOGLEV_ERROR, this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::panic(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_PANIC]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_ASK)
	  ask (LOGLEV_PANIC, this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ldebug(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_DEBUG]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_ASK)
	  ask (LOGLEV_DEBUG, this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ask (int level, char *prefix, char *fmt, va_list ap)
{
  char buf1[1024], buf2[1024];
  vsprintf (buf1, fmt, ap);
  sprintf (buf2, "%s %s", prefix, buf1);
  // FIXME: facility set to 0 because it's unknown.
  int val = SIM->LOCAL_log_msg (prefix, level, buf2);
  switch (val)
  {
    case 0:   // user chose continue
      break;
    case 1:   // user said continue, and don't ask for this facility again.
      setonoff (level, ACT_REPORT);
      break;
    case 2:   // user chose die
      fatal (prefix, fmt, ap);
  }
}

void
logfunctions::fatal (char *prefix, char *fmt, va_list ap)
{
  static int fatal_reentry = 0;
  if (fatal_reentry) return;
  fatal_reentry++;
  bx_atexit();
  fprintf (stderr, "%s\n", divider);
  fprintf (stderr, "Bochs is exiting with the following message:\n");
  fprintf (stderr, "%s ", prefix);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n%s\n", divider);
#if 0 && defined(WIN32)
#error disabled because it  is not working yet!
  // wait for a keypress before quitting.  Depending on how bochs is
  // installed, the console window can disappear before the user has
  // a chance to read the final message.
  fprintf (stderr, "\n\nPress Enter to exit...\n");
  char buf[8];
  fgets (buf, 8, stdin);
#endif
#if !BX_DEBUGGER
  exit(1);
#else
  static Boolean dbg_exit_called = 0;
  if (dbg_exit_called == 0) {
    dbg_exit_called = 1;
    bx_dbg_exit(1);
    }
#endif
  fatal_reentry--;
}

iofunc_t *io = NULL;
logfunc_t *genlog = NULL;

void bx_center_print (FILE *file, char *line, int maxwidth)
{
  int imax;
  imax = (maxwidth - strlen(line)) >> 1;
  for (int i=0; i<imax; i++) fputc (' ', file);
  fputs (line, file);
}

<|endoftext|>


<commit_before>/*
 * this module converts messages into a format able to be displayed by the UI.
 *
 * it can currently convert messages and me messages that the user sends, as well
 * as the same types of messages received by the antenna.
 * it then converts them into a display_message, which will be used by the UI and Logger.
 */

#include <QtCore>
#include <QSettings>

#include "edict_messages.h"
#include "display_messages.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "lirch_plugin.h"
#include "lirch_constants.h"

using namespace std;

void run(plugin_pipe p, string name)
{
	//register for the message types the display adapter can handle
	p.write(registration_message::create(-30000, name, "received"));
	p.write(registration_message::create(-30000, name, "notify"));

	//needed to send nick with your messages
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, "Lirch");
	settings.beginGroup("UserData");

	while(true)
	{
		//waits until any messages are sent to it
		message m=p.blocking_read();

		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;
			//Retry 2000 times until we succeed
			if (!s->status && s->priority<-28000)
				p.write(registration_message::create(s->priority+1, name, s->type));
		}

		//message parsing is simple, just putting the right things in the right fields.
		else if (m.type=="received")
		{
			auto castMessage=dynamic_cast<received_message *>(m.getdata());

			//if it's not actually a received message, ignore it and move on
			if (!castMessage)
				continue;

			if(castMessage->subtype==received_message_subtype::NORMAL)
				p.write(display_message::create(display_message_subtype::NORMAL,castMessage->channel,castMessage->nick,castMessage->contents));
			else if(castMessage->subtype==received_message_subtype::ME)
				p.write(display_message::create(display_message_subtype::ME,castMessage->channel,castMessage->nick,castMessage->contents));
			else if(castMessage->subtype==received_message_subtype::NOTIFY)
				p.write(display_message::create(display_message_subtype::NOTIFY,castMessage->channel,castMessage->nick,castMessage->contents));
			else
				p.write(m.decrement_priority());
		}
		else if (m.type=="notify")
		{
			auto castMessage=dynamic_cast<notify_message *>(m.getdata());

			//if it's not actually a notify me message, ignore it and move on
			if (!castMessage)
				continue;

			p.write(display_message::create(display_message_subtype::NOTIFY,castMessage->channel,"",castMessage->contents));
		}

		//what is this doing here? take it back, i don't want it.
		else
		{
			p.write(m.decrement_priority());
		}
	}
}
<commit_msg>Masseuse now bounces back all 'received' type messages<commit_after>/*
 * this module converts messages into a format able to be displayed by the UI.
 *
 * it can currently convert messages and me messages that the user sends, as well
 * as the same types of messages received by the antenna.
 * it then converts them into a display_message, which will be used by the UI and Logger.
 */

#include <QtCore>
#include <QSettings>

#include "edict_messages.h"
#include "display_messages.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "lirch_plugin.h"
#include "lirch_constants.h"

using namespace std;

void run(plugin_pipe p, string name)
{
	//register for the message types the display adapter can handle
	p.write(registration_message::create(-30000, name, "received"));
	p.write(registration_message::create(-30000, name, "notify"));

	//needed to send nick with your messages
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, "Lirch");
	settings.beginGroup("UserData");

	while(true)
	{
		//waits until any messages are sent to it
		message m=p.blocking_read();

		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;
			//Retry 2000 times until we succeed
			if (!s->status && s->priority<-28000)
				p.write(registration_message::create(s->priority+1, name, s->type));
		}

		//message parsing is simple, just putting the right things in the right fields.
		else if (m.type=="received")
		{
			auto castMessage=dynamic_cast<received_message *>(m.getdata());

			//if it's not actually a received message, ignore it and move on
			if (!castMessage)
				continue;

			if(castMessage->subtype==received_message_subtype::NORMAL)
				p.write(display_message::create(display_message_subtype::NORMAL,castMessage->channel,castMessage->nick,castMessage->contents));
			else if(castMessage->subtype==received_message_subtype::ME)
				p.write(display_message::create(display_message_subtype::ME,castMessage->channel,castMessage->nick,castMessage->contents));
			else if(castMessage->subtype==received_message_subtype::NOTIFY)
				p.write(display_message::create(display_message_subtype::NOTIFY,castMessage->channel,castMessage->nick,castMessage->contents));
			p.write(m.decrement_priority());
		}
		else if (m.type=="notify")
		{
			auto castMessage=dynamic_cast<notify_message *>(m.getdata());

			//if it's not actually a notify me message, ignore it and move on
			if (!castMessage)
				continue;

			p.write(display_message::create(display_message_subtype::NOTIFY,castMessage->channel,"",castMessage->contents));
		}

		//what is this doing here? take it back, i don't want it.
		else
		{
			p.write(m.decrement_priority());
		}
	}
}
<|endoftext|>


<commit_before>#ifndef ENTITY_HPP
#define ENTITY_HPP

class Entity
{
public:
    Entity(float x, float y, float width, float height);
    virtual ~Entity() {};

    virtual void update() = 0;
    virtual void render() = 0;

    float getX() const;
    float getY() const;
    float getWidth() const;
    float getHeight() const;

protected:
    float m_X;
    float m_Y;
    float m_Width;
    float m_Height;
};

#endif // ENTITY_HPP
<commit_msg>Added delta parameter to Entity::update()<commit_after>#ifndef ENTITY_HPP
#define ENTITY_HPP

class Entity
{
public:
    Entity(float x, float y, float width, float height);
    virtual ~Entity() {};

    virtual void update(int delta) = 0;
    virtual void render() = 0;

    float getX() const;
    float getY() const;
    float getWidth() const;
    float getHeight() const;

protected:
    float m_X;
    float m_Y;
    float m_Width;
    float m_Height;
};

#endif // ENTITY_HPP
<|endoftext|>


<commit_before>#include "slist.h"
#include <cstdlib>

namespace
{
	void parse_arguments(int argc, char **argv);
}

int main(int argc, char **argv)
{
	using namespace slist;

	parse_arguments(argc, argv);

	node_ptr n = parse(

		// "(+ 1 2 3)"
		// "(- 1 2 3)"
		// "(* 1 2 3)"
		// "(/ 1.0 2 3)"

		// "(define (make-adder x) (lambda (a) (___add x a)))"
		// "(define add-1 (make-adder 1))"
		// "(define add-2 (make-adder 2))"
		// "(println (add-1 1))"
		// "(println (add-2 1))"
		// "(println (add-1 3))"

		// "(define (add x y) (+ x y))"
		// "(apply add (list 1 2))"

		// "(define (f x y) (begin (println x) (println y)))"
		// "(f 1 2)"

		"(define variadic-test-1 (lambda values (apply + values)))"
		"(variadic-test-1 1 2 3)"

		);

	if (get_log_level() >= log_level::trace)
	{
		log_traceln("");
		debug_print_node(n);
		log_traceln("");
	}

	context ctx;
	while (n != nullptr)
	{
		auto r = eval(ctx, n->car);
		if (r != nullptr)
		{
			outputln("", r);
		}
		n = n->cdr;
	}
}

namespace
{
	void parse_arguments(int argc, char **argv)
	{
		using namespace std;
		using namespace slist;

		for (int i = 0; i < argc; ++i)
		{
			char *arg = argv[i];
			if (strcmp(arg, "-l") == 0 || strcmp(arg, "--log-level") == 0)
			{
				++i;
				if (i < argc && argv[i] != nullptr)
				{
					arg = argv[i];
					log_level level = (log_level)atoi(arg);
					set_log_level(level);
				}
				else
				{
					log_error("Invalid argument to '-v'/'--log-level'\n");
				}
			}
		}
	}
}<commit_msg>Variadic tests working perfectly.<commit_after>#include "slist.h"
#include <cstdlib>

namespace
{
	void parse_arguments(int argc, char **argv);
}

int main(int argc, char **argv)
{
	using namespace slist;

	parse_arguments(argc, argv);

	node_ptr n = parse(

		// "(+ 1 2 3)"
		// "(- 1 2 3)"
		// "(* 1 2 3)"
		// "(/ 1.0 2 3)"

		// "(define (make-adder x) (lambda (a) (___add x a)))"
		// "(define add-1 (make-adder 1))"
		// "(define add-2 (make-adder 2))"
		// "(println (add-1 1))"
		// "(println (add-2 1))"
		// "(println (add-1 3))"

		// "(define (add x y) (+ x y))"
		// "(apply add (list 1 2))"

		// "(define (f x y) (begin (println x) (println y)))"
		// "(f 1 2)"

		// "(define variadic-test-1 (lambda values (apply + values)))"
		// "(variadic-test-1 1 2 3)"

		// "(define my-add (lambda values (apply + values)))"
		// "(define variadic-test-2 (lambda values (apply my-add values)))"
		// "(variadic-test-2 1 2 3)"

		// "(define (variadic-test-3 . values) (apply + values))"
		// "(variadic-test-3 1 2 3)"

		"(define (variadic-test-4 x . rest) (begin (println x) (apply + rest)))"
		"(variadic-test-4 9 1 2 3)"

		);

	if (get_log_level() >= log_level::trace)
	{
		log_traceln("");
		debug_print_node(n);
		log_traceln("");
	}

	context ctx;
	while (n != nullptr)
	{
		auto r = eval(ctx, n->car);
		if (r != nullptr)
		{
			outputln("", r);
		}
		n = n->cdr;
	}
}

namespace
{
	void parse_arguments(int argc, char **argv)
	{
		using namespace std;
		using namespace slist;

		for (int i = 0; i < argc; ++i)
		{
			char *arg = argv[i];
			if (strcmp(arg, "-l") == 0 || strcmp(arg, "--log-level") == 0)
			{
				++i;
				if (i < argc && argv[i] != nullptr)
				{
					arg = argv[i];
					log_level level = (log_level)atoi(arg);
					set_log_level(level);
				}
				else
				{
					log_error("Invalid argument to '-v'/'--log-level'\n");
				}
			}
		}
	}
}<|endoftext|>