<commit_before>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-11-23 GONG Chen <chen.sst@gmail.com>
//
#include <algorithm>
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/key_table.h>
#include <rime/schema.h>
#include <rime/switcher.h>
#include <rime/gear/key_binder.h>

using namespace std::placeholders;

namespace rime {

enum KeyBindingCondition {
  kNever,
  kWhenPaging,     // user has changed page
  kWhenHasMenu,    // at least one candidate
  kWhenComposing,  // input string is not empty
  kAlways,
};

static struct KeyBindingConditionDef {
  KeyBindingCondition condition;
  const char* name;
} condition_definitions[] = {
  { kWhenPaging,    "paging"    },
  { kWhenHasMenu,   "has_menu"  },
  { kWhenComposing, "composing" },
  { kAlways,        "always"    },
  { kNever,         NULL        }
};

static KeyBindingCondition translate_condition(const string& str) {
  for (auto* d = condition_definitions; d->name; ++d) {
    if (str == d->name)
      return d->condition;
  }
  return kNever;
}

struct KeyBinding {
  KeyBindingCondition whence;
  KeyEvent target;
  function<void (Engine* engine)> action;

  bool operator< (const KeyBinding& o) const {
    return whence < o.whence;
  }
};

class KeyBindings : public map<KeyEvent,
                                    vector<KeyBinding>> {
 public:
  void LoadBindings(const an<ConfigList>& bindings);
  void Bind(const KeyEvent& key, const KeyBinding& binding);
};

static void toggle_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, !ctx->get_option(option));
}
static void set_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, 1);
}
static void unset_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, 0);
}

static void select_schema(Engine* engine, const string& schema) {
  if (!engine)
    return;
  if (schema == ".next") {
    Switcher switcher(engine);
    switcher.SelectNextSchema();
  }
  else {
    engine->ApplySchema(new Schema(schema));
  }
}

void KeyBindings::LoadBindings(const an<ConfigList>& bindings) {
  if (!bindings)
    return;
  for (size_t i = 0; i < bindings->size(); ++i) {
    auto map = As<ConfigMap>(bindings->GetAt(i));
    if (!map)
      continue;
    auto whence = map->GetValue("when");
    if (!whence)
      continue;
    auto pattern = map->GetValue("accept");
    if (!pattern)
      continue;
    KeyBinding binding;
    binding.whence = translate_condition(whence->str());
    if (binding.whence == kNever) {
      continue;
    }
    KeyEvent key;
    if (!key.Parse(pattern->str())) {
      LOG(WARNING) << "invalid key binding #" << i << ".";
      continue;
    }
    if (auto target = map->GetValue("send")) {
      if (!binding.target.Parse(target->str())) {
        LOG(WARNING) << "invalid key binding #" << i << ".";
        continue;
      }
    }
    else if (auto option = map->GetValue("toggle")) {
      binding.action = std::bind(&toggle_option, _1, option->str());
    }
    else if (auto option = map->GetValue("set")) {
      binding.action = std::bind(&set_option, _1, option->str());
    }
    else if (auto option = map->GetValue("unset")) {
      binding.action = std::bind(&unset_option, _1, option->str());
    }
    else if (auto schema = map->GetValue("select")) {
      binding.action = std::bind(&select_schema, _1, schema->str());
    }
    else {
      LOG(WARNING) << "invalid key binding #" << i << ".";
      continue;
    }
    Bind(key, binding);
  }
}

void KeyBindings::Bind(const KeyEvent& key, const KeyBinding& binding) {
  auto& vec = (*this)[key];
  // insert before existing binding of the same condition
  auto lb = std::lower_bound(vec.begin(), vec.end(), binding);
  vec.insert(lb, binding);
}

KeyBinder::KeyBinder(const Ticket& ticket) : Processor(ticket),
                                             key_bindings_(new KeyBindings),
                                             redirecting_(false),
                                             last_key_(0) {
  LoadConfig();
}

class KeyBindingConditions : public set<KeyBindingCondition> {
 public:
  explicit KeyBindingConditions(Context* ctx);
};

KeyBindingConditions::KeyBindingConditions(Context* ctx) {
  insert(kAlways);

  if (ctx->IsComposing()) {
    insert(kWhenComposing);
  }

  if (ctx->HasMenu() && !ctx->get_option("ascii_mode")) {
    insert(kWhenHasMenu);
  }

  Composition& comp = ctx->composition();
  if (!comp.empty() && comp.back().HasTag("paging")) {
    insert(kWhenPaging);
  }
}

ProcessResult KeyBinder::ProcessKeyEvent(const KeyEvent& key_event) {
  if (redirecting_ || !key_bindings_ || key_bindings_->empty())
    return kNoop;
  if (ReinterpretPagingKey(key_event))
    return kNoop;
  if (key_bindings_->find(key_event) == key_bindings_->end())
    return kNoop;
  KeyBindingConditions conditions(engine_->context());
  for (const KeyBinding& binding : (*key_bindings_)[key_event]) {
    if (conditions.find(binding.whence) == conditions.end())
      continue;
    PerformKeyBinding(binding);
    return kAccepted;
  }
  // not handled
  return kNoop;
}

void KeyBinder::PerformKeyBinding(const KeyBinding& binding) {
  if (binding.action) {
    binding.action(engine_);
  }
  else {
    redirecting_ = true;
    engine_->ProcessKey(binding.target);
    redirecting_ = false;
  }
}

void KeyBinder::LoadConfig() {
  if (!engine_)
    return;
  Config* config = engine_->schema()->config();
  string preset;
  if (config->GetString("key_binder/import_preset", &preset)) {
    the<Config> preset_config(Config::Require("config")->Create(preset));
    if (!preset_config) {
      LOG(ERROR) << "Error importing preset key bindings '" << preset << "'.";
      return;
    }
    if (auto bindings = preset_config->GetList("key_binder/bindings"))
      key_bindings_->LoadBindings(bindings);
    else
      LOG(WARNING) << "missing preset key bindings.";
  }
  // per schema configuration, overriding preset bindings
  if (auto bindings = config->GetList("key_binder/bindings"))
    key_bindings_->LoadBindings(bindings);
}

bool KeyBinder::ReinterpretPagingKey(const KeyEvent& key_event) {
  if (key_event.release())
    return false;
  bool ret = false;
  int ch = (key_event.modifier() == 0) ? key_event.keycode() : 0;
  // reinterpret period key followed by alphabetic keys
  // unless period/comma key has been used multiple times
  if (ch == '.' && (last_key_ == '.' || last_key_ == ',')) {
    last_key_ = 0;
    return ret;
  }
  if (last_key_ == '.' && ch >= 'a' && ch <= 'z') {
    Context* ctx = engine_->context();
    const string& input(ctx->input());
    if (!input.empty() && input[input.length() - 1] != '.') {
      LOG(INFO) << "reinterpreted key: '" << last_key_
                << "', successor: '" << (char)ch << "'";
      ctx->PushInput(last_key_);
      ret = true;
    }
  }
  last_key_ = ch;
  return ret;
}

}  // namespace rime
<commit_msg>Update key_binder.cc<commit_after>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-11-23 GONG Chen <chen.sst@gmail.com>
//
#include <algorithm>
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/key_table.h>
#include <rime/schema.h>
#include <rime/switcher.h>
#include <rime/gear/key_binder.h>

using namespace std::placeholders;

namespace rime {

enum KeyBindingCondition {
  kNever,
  kWhenPaging,     // user has changed page
  kWhenHasMenu,    // at least one candidate
  kWhenComposing,  // input string is not empty
  kAlways,
};

static struct KeyBindingConditionDef {
  KeyBindingCondition condition;
  const char* name;
} condition_definitions[] = {
  { kWhenPaging,    "paging"    },
  { kWhenHasMenu,   "has_menu"  },
  { kWhenComposing, "composing" },
  { kAlways,        "always"    },
  { kNever,         NULL        }
};

static KeyBindingCondition translate_condition(const string& str) {
  for (auto* d = condition_definitions; d->name; ++d) {
    if (str == d->name)
      return d->condition;
  }
  return kNever;
}

struct KeyBinding {
  KeyBindingCondition whence;
  KeyEvent target;
  function<void (Engine* engine)> action;

  bool operator< (const KeyBinding& o) const {
    return whence < o.whence;
  }
};

class KeyBindings : public map<KeyEvent,
                                    vector<KeyBinding>> {
 public:
  void LoadBindings(const an<ConfigList>& bindings);
  void Bind(const KeyEvent& key, const KeyBinding& binding);
};

static void toggle_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, !ctx->get_option(option));
}
static void set_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, 1);
}
static void unset_option(Engine* engine, const string& option) {
  if (!engine)
    return;
  Context* ctx = engine->context();
  ctx->set_option(option, 0);
}

static void select_schema(Engine* engine, const string& schema) {
  if (!engine)
    return;
  if (schema == ".next") {
    Switcher switcher(engine);
    switcher.SelectNextSchema();
  }
  else {
    engine->ApplySchema(new Schema(schema));
  }
}

void KeyBindings::LoadBindings(const an<ConfigList>& bindings) {
  if (!bindings)
    return;
  for (size_t i = 0; i < bindings->size(); ++i) {
    auto map = As<ConfigMap>(bindings->GetAt(i));
    if (!map)
      continue;
    auto whence = map->GetValue("when");
    if (!whence)
      continue;
    auto pattern = map->GetValue("accept");
    if (!pattern)
      continue;
    KeyBinding binding;
    binding.whence = translate_condition(whence->str());
    if (binding.whence == kNever) {
      continue;
    }
    KeyEvent key;
    if (!key.Parse(pattern->str())) {
      LOG(WARNING) << "invalid key binding #" << i << ".";
      continue;
    }
    if (auto target = map->GetValue("send")) {
      if (!binding.target.Parse(target->str())) {
        LOG(WARNING) << "invalid key binding #" << i << ".";
        continue;
      }
    }
    else if (auto option = map->GetValue("toggle")) {
      binding.action = std::bind(&toggle_option, _1, option->str());
    }
    else if (auto option = map->GetValue("set_option")) {
      binding.action = std::bind(&set_option, _1, option->str());
    }
    else if (auto option = map->GetValue("unset_option")) {
      binding.action = std::bind(&unset_option, _1, option->str());
    }
    else if (auto schema = map->GetValue("select")) {
      binding.action = std::bind(&select_schema, _1, schema->str());
    }
    else {
      LOG(WARNING) << "invalid key binding #" << i << ".";
      continue;
    }
    Bind(key, binding);
  }
}

void KeyBindings::Bind(const KeyEvent& key, const KeyBinding& binding) {
  auto& vec = (*this)[key];
  // insert before existing binding of the same condition
  auto lb = std::lower_bound(vec.begin(), vec.end(), binding);
  vec.insert(lb, binding);
}

KeyBinder::KeyBinder(const Ticket& ticket) : Processor(ticket),
                                             key_bindings_(new KeyBindings),
                                             redirecting_(false),
                                             last_key_(0) {
  LoadConfig();
}

class KeyBindingConditions : public set<KeyBindingCondition> {
 public:
  explicit KeyBindingConditions(Context* ctx);
};

KeyBindingConditions::KeyBindingConditions(Context* ctx) {
  insert(kAlways);

  if (ctx->IsComposing()) {
    insert(kWhenComposing);
  }

  if (ctx->HasMenu() && !ctx->get_option("ascii_mode")) {
    insert(kWhenHasMenu);
  }

  Composition& comp = ctx->composition();
  if (!comp.empty() && comp.back().HasTag("paging")) {
    insert(kWhenPaging);
  }
}

ProcessResult KeyBinder::ProcessKeyEvent(const KeyEvent& key_event) {
  if (redirecting_ || !key_bindings_ || key_bindings_->empty())
    return kNoop;
  if (ReinterpretPagingKey(key_event))
    return kNoop;
  if (key_bindings_->find(key_event) == key_bindings_->end())
    return kNoop;
  KeyBindingConditions conditions(engine_->context());
  for (const KeyBinding& binding : (*key_bindings_)[key_event]) {
    if (conditions.find(binding.whence) == conditions.end())
      continue;
    PerformKeyBinding(binding);
    return kAccepted;
  }
  // not handled
  return kNoop;
}

void KeyBinder::PerformKeyBinding(const KeyBinding& binding) {
  if (binding.action) {
    binding.action(engine_);
  }
  else {
    redirecting_ = true;
    engine_->ProcessKey(binding.target);
    redirecting_ = false;
  }
}

void KeyBinder::LoadConfig() {
  if (!engine_)
    return;
  Config* config = engine_->schema()->config();
  string preset;
  if (config->GetString("key_binder/import_preset", &preset)) {
    the<Config> preset_config(Config::Require("config")->Create(preset));
    if (!preset_config) {
      LOG(ERROR) << "Error importing preset key bindings '" << preset << "'.";
      return;
    }
    if (auto bindings = preset_config->GetList("key_binder/bindings"))
      key_bindings_->LoadBindings(bindings);
    else
      LOG(WARNING) << "missing preset key bindings.";
  }
  // per schema configuration, overriding preset bindings
  if (auto bindings = config->GetList("key_binder/bindings"))
    key_bindings_->LoadBindings(bindings);
}

bool KeyBinder::ReinterpretPagingKey(const KeyEvent& key_event) {
  if (key_event.release())
    return false;
  bool ret = false;
  int ch = (key_event.modifier() == 0) ? key_event.keycode() : 0;
  // reinterpret period key followed by alphabetic keys
  // unless period/comma key has been used multiple times
  if (ch == '.' && (last_key_ == '.' || last_key_ == ',')) {
    last_key_ = 0;
    return ret;
  }
  if (last_key_ == '.' && ch >= 'a' && ch <= 'z') {
    Context* ctx = engine_->context();
    const string& input(ctx->input());
    if (!input.empty() && input[input.length() - 1] != '.') {
      LOG(INFO) << "reinterpreted key: '" << last_key_
                << "', successor: '" << (char)ch << "'";
      ctx->PushInput(last_key_);
      ret = true;
    }
  }
  last_key_ = ch;
  return ret;
}

}  // namespace rime
<|endoftext|>


<commit_before>#pragma once
#include <stddef.h>
#include <string>
#include <vector>

namespace ase
{
namespace ColorType
{
template< std::size_t Channels >
struct Colorf32
{
	float Channel[Channels];

	float& operator[](std::size_t Index)
	{
		return Channel[Index];
	}
};

using Gray = Colorf32<1>;
using RGB = Colorf32<3>;
using LAB = Colorf32<3>;
using CMYK = Colorf32<4>;
}

class ColorCallback
{
public:
	virtual void GroupBegin(
		const std::u16string &Name
	)
	{
	}

	virtual void GroupEnd()
	{
	}

	virtual void ColorGray(
		const std::u16string &Name,
		ColorType::Gray Lightness
	)
	{
	};

	virtual void ColorRGB(
		const std::u16string &Name,
		ColorType::RGB Color
	)
	{
	};

	virtual void ColorLAB(
		const std::u16string &Name,
		ColorType::LAB Color
	)
	{
	};

	virtual void ColorCMYK(
		const std::u16string &Name,
		ColorType::CMYK Color
	)
	{
	};
};

bool LoadFromFile(
	ColorCallback& Callback,
	const char* FileName
);

bool LoadFromStream(
	ColorCallback& Callback,
	std::istream &Stream
);

bool LoadFromMemory(
	ColorCallback& Callback,
	const void* Buffer,
	std::size_t Size
);
}<commit_msg>Add virtual destructor to interface<commit_after>#pragma once
#include <stddef.h>
#include <string>
#include <vector>

namespace ase
{
namespace ColorType
{
template< std::size_t Channels >
struct Colorf32
{
	float Channel[Channels];

	float& operator[](std::size_t Index)
	{
		return Channel[Index];
	}
};

using Gray = Colorf32<1>;
using RGB = Colorf32<3>;
using LAB = Colorf32<3>;
using CMYK = Colorf32<4>;
}

class ColorCallback
{
public:
	virtual ~ColorCallback() = default;

	virtual void GroupBegin(
		const std::u16string &Name
	)
	{
	}

	virtual void GroupEnd()
	{
	}

	virtual void ColorGray(
		const std::u16string &Name,
		ColorType::Gray Lightness
	)
	{
	};

	virtual void ColorRGB(
		const std::u16string &Name,
		ColorType::RGB Color
	)
	{
	};

	virtual void ColorLAB(
		const std::u16string &Name,
		ColorType::LAB Color
	)
	{
	};

	virtual void ColorCMYK(
		const std::u16string &Name,
		ColorType::CMYK Color
	)
	{
	};
};

bool LoadFromFile(
	ColorCallback& Callback,
	const char* FileName
);

bool LoadFromStream(
	ColorCallback& Callback,
	std::istream &Stream
);

bool LoadFromMemory(
	ColorCallback& Callback,
	const void* Buffer,
	std::size_t Size
);
}<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_MERKLE_BUNDLE_HPP_
#define _SNARKFRONT_MERKLE_BUNDLE_HPP_

#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>
#include <set>
#include <vector>
#include "DSL_utility.hpp"
#include "MerkleAuthPath.hpp"
#include "MerkleTree.hpp"

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// Merkle tree with authentication paths
//

template <typename TREE, typename PATH, typename COUNT>
class MerkleBundle
{
public:
    typedef typename TREE::HashType HashType;
    typedef typename TREE::DigType DigType;
    typedef PATH AuthPath;
    typedef COUNT Count;

    MerkleBundle()
        : m_treeSize(0)
    {}

    MerkleBundle(const std::size_t depth)
        : m_tree(depth),
          m_treeSize(0)
    {}

    bool isFull() const {
        return m_tree.isFull();
    }

    COUNT treeSize() const {
        return m_treeSize;
    }

    const DigType& rootHash() const {
        return m_tree.authPath().rootHash();
    }

    void addLeaf(const DigType& cm, const bool keepPath = true) {
        m_tree.updatePath(cm, m_authPath);

        if (keepPath) {
            m_authLeaf.emplace_back(cm);
            m_authPath.emplace_back(m_tree.authPath());
        }

        m_tree.updateSiblings(cm);

        ++m_treeSize;
    }

    const std::vector<DigType>& authLeaf() const {
        return m_authLeaf;
    }

    const std::vector<PATH>& authPath() const {
        return m_authPath;
    }

    void authGC(const std::set<DigType>& markedLeaf) {
        std::vector<DigType> keepLeaf;
        std::vector<PATH> keepPath;

        for (std::size_t i = 0; i < m_authLeaf.size(); ++i) {
            const auto& cm = m_authLeaf[i];
            if (markedLeaf.count(cm)) {
                keepLeaf.emplace_back(cm);
                keepPath.emplace_back(m_authPath[i]);
            }
        }

        m_authLeaf = keepLeaf;
        m_authPath = keepPath;
    }

    void marshal_out(std::ostream& os) const {
        os << m_tree
           << m_treeSize << std::endl
           << m_authLeaf;

        for (const auto& r : m_authPath)
            os << r;
    }

    bool marshal_in(std::istream& is) {
        if (!m_tree.marshal_in(is) || !(is >> m_treeSize) || !(is >> m_authLeaf))
            return false;

        m_authPath.resize(m_authLeaf.size());
        for (auto& r : m_authPath) {
            if (! r.marshal_in(is)) return false;
        }

        return true;
    }

    void clear() {
        m_tree.clear();
        m_treeSize = 0;
        m_authLeaf.clear();
        m_authPath.clear();
    }

    bool empty() const {
        return
            m_tree.empty() ||
            0 == m_treeSize ||
            m_authLeaf.empty() ||
            m_authPath.empty();
    }

private:
    TREE m_tree;
    COUNT m_treeSize;

    std::vector<DigType> m_authLeaf;
    std::vector<PATH> m_authPath;
};

template <typename TREE, typename PATH, typename COUNT>
std::ostream& operator<< (std::ostream& os,
                          const MerkleBundle<TREE, PATH, COUNT>& a) {
    a.marshal_out(os);
    return os;
}

template <typename TREE, typename PATH, typename COUNT>
std::istream& operator>> (std::istream& is,
                          MerkleBundle<TREE, PATH, COUNT>& a) {
    if (! a.marshal_in(is)) a.clear();
    return is;
}

////////////////////////////////////////////////////////////////////////////////
// typedefs
//

template <typename COUNT> using
MerkleBundle_SHA256 = MerkleBundle<MerkleTree_SHA256, eval::MerkleAuthPath_SHA256, COUNT>;

template <typename COUNT> using
MerkleBundle_SHA512 = MerkleBundle<MerkleTree_SHA512, eval::MerkleAuthPath_SHA512, COUNT>;

} // namespace snarkfront

#endif
<commit_msg>addLeaf() keep path default, auth path cleanup<commit_after>#ifndef _SNARKFRONT_MERKLE_BUNDLE_HPP_
#define _SNARKFRONT_MERKLE_BUNDLE_HPP_

#include <cstdint>
#include <functional>
#include <iostream>
#include <istream>
#include <ostream>
#include <set>
#include <vector>

#include <snarkfront/DSL_utility.hpp>
#include <snarkfront/MerkleAuthPath.hpp>
#include <snarkfront/MerkleTree.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// Merkle tree with authentication paths
//

template <typename TREE, typename PATH, typename COUNT>
class MerkleBundle
{
public:
    typedef typename TREE::HashType HashType;
    typedef typename TREE::DigType DigType;
    typedef PATH AuthPath;
    typedef COUNT Count;

    MerkleBundle()
        : m_treeSize(0)
    {}

    MerkleBundle(const std::size_t depth)
        : m_tree(depth),
          m_treeSize(0)
    {}

    bool isFull() const {
        return m_tree.isFull();
    }

    COUNT treeSize() const {
        return m_treeSize;
    }

    const DigType& rootHash() const {
        return m_tree.authPath().rootHash();
    }

    void addLeaf(const DigType& cm, const bool keepPath = false) {
        m_tree.updatePath(cm, m_authPath);

        if (keepPath) {
            m_authLeaf.emplace_back(cm);
            m_authPath.emplace_back(m_tree.authPath());
        }

        m_tree.updateSiblings(cm);

        ++m_treeSize;
    }

    const std::vector<DigType>& authLeaf() const {
        return m_authLeaf;
    }

    const std::vector<PATH>& authPath() const {
        return m_authPath;
    }

    void cleanup(std::function<bool (const DigType&)> func) {
        std::vector<DigType> keepLeaf;
        std::vector<PATH> keepPath;

        for (std::size_t i = 0; i < m_authLeaf.size(); ++i) {
            const auto& cm = m_authLeaf[i];
            if (func(cm)) {
                keepLeaf.emplace_back(cm);
                keepPath.emplace_back(m_authPath[i]);
            }
        }

        m_authLeaf = keepLeaf;
        m_authPath = keepPath;
    }

    void marshal_out(std::ostream& os) const {
        os << m_tree
           << m_treeSize << std::endl
           << m_authLeaf;

        for (const auto& r : m_authPath)
            os << r;
    }

    bool marshal_in(std::istream& is) {
        if (!m_tree.marshal_in(is) || !(is >> m_treeSize) || !(is >> m_authLeaf))
            return false;

        m_authPath.resize(m_authLeaf.size());
        for (auto& r : m_authPath) {
            if (! r.marshal_in(is)) return false;
        }

        return true;
    }

    void clear() {
        m_tree.clear();
        m_treeSize = 0;
        m_authLeaf.clear();
        m_authPath.clear();
    }

    bool empty() const {
        return
            m_tree.empty() ||
            0 == m_treeSize ||
            m_authLeaf.empty() ||
            m_authPath.empty();
    }

private:
    TREE m_tree;
    COUNT m_treeSize;

    std::vector<DigType> m_authLeaf;
    std::vector<PATH> m_authPath;
};

template <typename TREE, typename PATH, typename COUNT>
std::ostream& operator<< (std::ostream& os,
                          const MerkleBundle<TREE, PATH, COUNT>& a) {
    a.marshal_out(os);
    return os;
}

template <typename TREE, typename PATH, typename COUNT>
std::istream& operator>> (std::istream& is,
                          MerkleBundle<TREE, PATH, COUNT>& a) {
    if (! a.marshal_in(is)) a.clear();
    return is;
}

////////////////////////////////////////////////////////////////////////////////
// typedefs
//

template <typename COUNT> using
MerkleBundle_SHA256 = MerkleBundle<MerkleTree_SHA256, eval::MerkleAuthPath_SHA256, COUNT>;

template <typename COUNT> using
MerkleBundle_SHA512 = MerkleBundle<MerkleTree_SHA512, eval::MerkleAuthPath_SHA512, COUNT>;

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>/*******************************************************************************
 * c7a/net/dispatcher_thread.cpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/net/dispatcher.hpp>
#include <c7a/net/dispatcher_thread.hpp>

#include <unistd.h>

#include <csignal>
#include <deque>
#include <string>
#include <vector>

namespace c7a {
namespace net {

DispatcherThread::DispatcherThread(const std::string& thread_name)
    : dispatcher_(new Dispatcher),
      name_(thread_name) {
    // allocate self-pipe
    int r = ::pipe(self_pipe_);
    die_unless(r == 0);
    // start thread
    thread_ = std::thread(&DispatcherThread::Work, this);
}

DispatcherThread::~DispatcherThread() {
    Terminate();

    close(self_pipe_[0]);
    close(self_pipe_[1]);

    delete dispatcher_;
}

//! Terminate the dispatcher thread (if now already done).
void DispatcherThread::Terminate() {
    if (terminate_) return;

    // set termination flags.
    terminate_ = true;
    // interrupt select().
    WakeUpThread();
    // wait for last round to finish.
    thread_.join();
}

//! Register a relative timeout callback
void DispatcherThread::AddTimer(
    const std::chrono::milliseconds& timeout, const TimerCallback& cb) {
    Enqueue([=]() {
                dispatcher_->AddTimer(timeout, cb);
            });
    WakeUpThread();
}

//! Register a buffered read callback and a default exception callback.
void DispatcherThread::AddRead(
    Connection& c, const ConnectionCallback& read_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AddRead(c, read_cb);
            });
    WakeUpThread();
}

//! Register a buffered write callback and a default exception callback.
void DispatcherThread::AddWrite(
    Connection& c, const ConnectionCallback& write_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AddWrite(c, write_cb);
            });
    WakeUpThread();
}

//! Cancel all callbacks on a given connection.
void DispatcherThread::Cancel(Connection& c) {
    int fd = c.GetSocket().fd();
    Enqueue([this, fd]() {
                dispatcher_->Cancel(fd);
            });
    WakeUpThread();
}

//! asynchronously read n bytes and deliver them to the callback
void DispatcherThread::AsyncRead(
    Connection& c, size_t n, AsyncReadCallback done_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AsyncRead(c, n, done_cb);
            });
    WakeUpThread();
}

//! asynchronously read the full ByteBlock and deliver it to the callback
void DispatcherThread::AsyncRead(Connection& c, const data::ByteBlockPtr& block,
                                 AsyncReadByteBlockCallback done_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AsyncRead(c, block, done_cb);
            });
    WakeUpThread();
}

//! asynchronously write TWO buffers and callback when delivered. The
//! buffer2 are MOVED into the async writer. This is most useful to write a
//! header and a payload Buffers that are hereby guaranteed to be written in
//! order.
void DispatcherThread::AsyncWrite(
    Connection& c, Buffer&& buffer, AsyncWriteCallback done_cb) {
    // the following captures the move-only buffer in a lambda.
    Enqueue([=, &c, b = std::move(buffer)]() mutable {
                dispatcher_->AsyncWrite(c, std::move(b), done_cb);
            });
    WakeUpThread();
}

//! asynchronously write buffer and callback when delivered. The buffer is
//! MOVED into the async writer.
void DispatcherThread::AsyncWrite(Connection& c, Buffer&& buffer,
                                  const data::Block& block,
                                  AsyncWriteCallback done_cb) {
    // the following captures the move-only buffer in a lambda.
    Enqueue([=, &c,
              b1 = std::move(buffer), b2 = block]() mutable {
                dispatcher_->AsyncWrite(c, std::move(b1));
                dispatcher_->AsyncWrite(c, b2, done_cb);
            });
    WakeUpThread();
}

//! asynchronously write buffer and callback when delivered. COPIES the data
//! into a Buffer!
void DispatcherThread::AsyncWriteCopy(Connection& c, const void* buffer, size_t size,
                                      AsyncWriteCallback done_cb) {
    return AsyncWrite(c, Buffer(buffer, size), done_cb);
}

//! asynchronously write buffer and callback when delivered. COPIES the data
//! into a Buffer!
void DispatcherThread::AsyncWriteCopy(Connection& c, const std::string& str,
                                      AsyncWriteCallback done_cb) {
    return AsyncWriteCopy(c, str.data(), str.size(), done_cb);
}

//! Enqueue job in queue for dispatching thread to run at its discretion.
void DispatcherThread::Enqueue(Job&& job) {
    return jobqueue_.push(std::move(job));
}

//! What happens in the dispatcher thread
void DispatcherThread::Work() {
    common::NameThisThread(name_);

    // Ignore PIPE signals (received when writing to closed sockets)
    signal(SIGPIPE, SIG_IGN);

    // wait interrupts via self-pipe.
    dispatcher_->dispatcher_.AddRead(
        self_pipe_[0], [this]() {
            ssize_t rb;
            while ((rb = read(self_pipe_[0], &self_pipe_buffer_, 1)) == 0) {
                LOG1 << "Work: error reading from self-pipe: " << errno;
            }
            die_unless(rb == 1);
            return true;
        });

    while (!terminate_ ||
           dispatcher_->HasAsyncWrites() || !jobqueue_.empty())
    {
        // process jobs in jobqueue_
        {
            Job job;
            while (jobqueue_.try_pop(job))
                job();
        }

        // run one dispatch
        dispatcher_->Dispatch();
    }
}

//! wake up select() in dispatching thread.
void DispatcherThread::WakeUpThread() {
    // there are multiple very platform-dependent ways to do this. we'll try
    // to use the self-pipe trick for now. The select() method waits on
    // another fd, which we write one byte to when we need to interrupt the
    // select().

    // another method would be to send a signal() via pthread_kill() to the
    // select thread, but that had a race condition for waking up the other
    // thread. -tb

    // send one byte to wake up the select() handler.
    ssize_t wb;
    while ((wb = write(self_pipe_[1], this, 1)) == 0) {
        LOG1 << "WakeUp: error sending to self-pipe: " << errno;
    }
    die_unless(wb == 1);
}

} // namespace net
} // namespace c7a

/******************************************************************************/
<commit_msg>If pipe() call fails, print error before dying, there are too many open files on MacOSX sometimes.<commit_after>/*******************************************************************************
 * c7a/net/dispatcher_thread.cpp
 *
 * Part of Project c7a.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#include <c7a/net/dispatcher.hpp>
#include <c7a/net/dispatcher_thread.hpp>

#include <unistd.h>

#include <csignal>
#include <deque>
#include <string>
#include <vector>

namespace c7a {
namespace net {

DispatcherThread::DispatcherThread(const std::string& thread_name)
    : dispatcher_(new Dispatcher),
      name_(thread_name) {
    // allocate self-pipe
    int r = ::pipe(self_pipe_);
    if (r != 0) {
        LOG1 << "Error opening self-pipe: " << strerror(errno);
    }
    die_unless(r == 0);
    // start thread
    thread_ = std::thread(&DispatcherThread::Work, this);
}

DispatcherThread::~DispatcherThread() {
    Terminate();

    close(self_pipe_[0]);
    close(self_pipe_[1]);

    delete dispatcher_;
}

//! Terminate the dispatcher thread (if now already done).
void DispatcherThread::Terminate() {
    if (terminate_) return;

    // set termination flags.
    terminate_ = true;
    // interrupt select().
    WakeUpThread();
    // wait for last round to finish.
    thread_.join();
}

//! Register a relative timeout callback
void DispatcherThread::AddTimer(
    const std::chrono::milliseconds& timeout, const TimerCallback& cb) {
    Enqueue([=]() {
                dispatcher_->AddTimer(timeout, cb);
            });
    WakeUpThread();
}

//! Register a buffered read callback and a default exception callback.
void DispatcherThread::AddRead(
    Connection& c, const ConnectionCallback& read_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AddRead(c, read_cb);
            });
    WakeUpThread();
}

//! Register a buffered write callback and a default exception callback.
void DispatcherThread::AddWrite(
    Connection& c, const ConnectionCallback& write_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AddWrite(c, write_cb);
            });
    WakeUpThread();
}

//! Cancel all callbacks on a given connection.
void DispatcherThread::Cancel(Connection& c) {
    int fd = c.GetSocket().fd();
    Enqueue([this, fd]() {
                dispatcher_->Cancel(fd);
            });
    WakeUpThread();
}

//! asynchronously read n bytes and deliver them to the callback
void DispatcherThread::AsyncRead(
    Connection& c, size_t n, AsyncReadCallback done_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AsyncRead(c, n, done_cb);
            });
    WakeUpThread();
}

//! asynchronously read the full ByteBlock and deliver it to the callback
void DispatcherThread::AsyncRead(Connection& c, const data::ByteBlockPtr& block,
                                 AsyncReadByteBlockCallback done_cb) {
    Enqueue([=, &c]() {
                dispatcher_->AsyncRead(c, block, done_cb);
            });
    WakeUpThread();
}

//! asynchronously write TWO buffers and callback when delivered. The
//! buffer2 are MOVED into the async writer. This is most useful to write a
//! header and a payload Buffers that are hereby guaranteed to be written in
//! order.
void DispatcherThread::AsyncWrite(
    Connection& c, Buffer&& buffer, AsyncWriteCallback done_cb) {
    // the following captures the move-only buffer in a lambda.
    Enqueue([=, &c, b = std::move(buffer)]() mutable {
                dispatcher_->AsyncWrite(c, std::move(b), done_cb);
            });
    WakeUpThread();
}

//! asynchronously write buffer and callback when delivered. The buffer is
//! MOVED into the async writer.
void DispatcherThread::AsyncWrite(Connection& c, Buffer&& buffer,
                                  const data::Block& block,
                                  AsyncWriteCallback done_cb) {
    // the following captures the move-only buffer in a lambda.
    Enqueue([=, &c,
              b1 = std::move(buffer), b2 = block]() mutable {
                dispatcher_->AsyncWrite(c, std::move(b1));
                dispatcher_->AsyncWrite(c, b2, done_cb);
            });
    WakeUpThread();
}

//! asynchronously write buffer and callback when delivered. COPIES the data
//! into a Buffer!
void DispatcherThread::AsyncWriteCopy(Connection& c, const void* buffer, size_t size,
                                      AsyncWriteCallback done_cb) {
    return AsyncWrite(c, Buffer(buffer, size), done_cb);
}

//! asynchronously write buffer and callback when delivered. COPIES the data
//! into a Buffer!
void DispatcherThread::AsyncWriteCopy(Connection& c, const std::string& str,
                                      AsyncWriteCallback done_cb) {
    return AsyncWriteCopy(c, str.data(), str.size(), done_cb);
}

//! Enqueue job in queue for dispatching thread to run at its discretion.
void DispatcherThread::Enqueue(Job&& job) {
    return jobqueue_.push(std::move(job));
}

//! What happens in the dispatcher thread
void DispatcherThread::Work() {
    common::NameThisThread(name_);

    // Ignore PIPE signals (received when writing to closed sockets)
    signal(SIGPIPE, SIG_IGN);

    // wait interrupts via self-pipe.
    dispatcher_->dispatcher_.AddRead(
        self_pipe_[0], [this]() {
            ssize_t rb;
            while ((rb = read(self_pipe_[0], &self_pipe_buffer_, 1)) == 0) {
                LOG1 << "Work: error reading from self-pipe: " << errno;
            }
            die_unless(rb == 1);
            return true;
        });

    while (!terminate_ ||
           dispatcher_->HasAsyncWrites() || !jobqueue_.empty())
    {
        // process jobs in jobqueue_
        {
            Job job;
            while (jobqueue_.try_pop(job))
                job();
        }

        // run one dispatch
        dispatcher_->Dispatch();
    }
}

//! wake up select() in dispatching thread.
void DispatcherThread::WakeUpThread() {
    // there are multiple very platform-dependent ways to do this. we'll try
    // to use the self-pipe trick for now. The select() method waits on
    // another fd, which we write one byte to when we need to interrupt the
    // select().

    // another method would be to send a signal() via pthread_kill() to the
    // select thread, but that had a race condition for waking up the other
    // thread. -tb

    // send one byte to wake up the select() handler.
    ssize_t wb;
    while ((wb = write(self_pipe_[1], this, 1)) == 0) {
        LOG1 << "WakeUp: error sending to self-pipe: " << errno;
    }
    die_unless(wb == 1);
}

} // namespace net
} // namespace c7a

/******************************************************************************/
<|endoftext|>


<commit_before>#ifndef b9core_hpp_
#define b9core_hpp_

#include <string>
#include <cstdint>

namespace b9 {

#define NO_MORE_BYTECODES 0x0
#define NO_MORE_FUNCTIONS 0x0

// ByteCodes

// Each Intruction is 32 bits: The first 8 bits are the ByteCode The second 24
// bits may be an argument to the opcode

typedef uint8_t ByteCodeSize;
typedef int32_t Parameter;  // even though only 24 bits used
typedef uint32_t Instruction;
typedef int64_t StackElement;

enum class ByteCode : ByteCodeSize {
    // Generic ByteCodes

    // Drop the top element of the stack
    drop = 0x1,
    // Duplicate the top element on the stack
    duplicate = 0x2,
    // Return from a function
    functionReturn = 0x3,
    // Call a Base9 function
    functionCall  = 0x4,
    // Call a native C function
    primitiveCall = 0x5,
    // Jump unconditionally by the offset
    jmp = 0x6,
    // Push from a local variable
    pushFromVar = 0x7,
    // Push into a local variable
    popIntoVar = 0x8,

    // Integer bytecodes

    // Push a constant
    intPushConstant = 0x9,
    // Subtract two integers
    intSub = 0xa,
    // Add two integers
    intAdd = 0xb,
    // Jump if two integers are equal
    intJmpEq = 0xc,
    // Jump if two integer are not equal
    intJmpNeq = 0xd,
    // Jump if the first integer is greater than the second
    intJmpGt = 0xe,
    // Jump if the first integer is greater than or equal to the second
    intJmpGe = 0xf,
    // Jump if the first integer is less than to the second
    intJmpLt = 0x10,
    // Jump if the first integer is less than or equal to the second
    intJmpLe = 0x11,

    // String ByteCodes

    // Push a string from this module's constant pool
    strPushConstant = 0x12,
    // Jump if two strings are equal
    strJmpEq = 0x13,
    // Jump if two integer are not equal
    strJmpNeq = 0x14,
};

class ByteCodes final {
 public:
  static ByteCode fromByte(uint8_t byte) { return static_cast<ByteCode>(byte); }
  static uint8_t toByte(ByteCode byteCode) { return static_cast<uint8_t>(byteCode); }

};

class Instructions final {
public:
    static Instruction create(ByteCode byteCode, Parameter parameter) {
        uint8_t byte = ByteCodes::toByte(byteCode);
        return byte << 24 | (parameter & 0xFFFFFF);
    }

    static ByteCode getByteCode (Instruction instruction) {
        return static_cast<ByteCode>(instruction >> 24);
    }

    static Parameter getParameter(Instruction instruction) {
        return static_cast<Parameter>(instruction & 0x800000 ? instruction | 0xFF000000: instruction & 0xFFFFFF);
    }
};

static constexpr Instruction
decl(uint16_t argCount, uint16_t tmpCount)
{
    return argCount << 16 | tmpCount;
}

static constexpr uint16_t
progArgCount(Instruction a)
{
    return a >> 16;
}

static constexpr uint16_t
progTmpCount(Instruction a)
{
    return a & 0xFFFF;
}

class VirtualMachine;
class ExecutionContext;

// Primitive Function from Interpreter call
extern "C" typedef void (PrimitiveFunction)(VirtualMachine *virtualMachine);

void
bc_primitive(VirtualMachine *context, Parameter value);

struct PrimitiveData {
    const char * name;
    PrimitiveFunction *address;
};

class FunctionSpecification {
public:
    const char* name_ ;
    uint32_t nargs_;
    Instruction *byteCodes_;
    uint64_t jitAddress_;
};

class ExportedFunctionData {
public:
    int functionCount_;
    FunctionSpecification *functionTable_;
};

//typedef StackElement (*Interpret) (ExecutionContext* context, Instruction* program);

#if defined(B9JIT)

// define C callable Interpret API for each arg call
// if args are passed to the function, they are not passed
// on the intepreter stack
typedef StackElement (*Interpret_0_args) (ExecutionContext* context, Instruction* program);
typedef StackElement (*Interpret_1_args) (ExecutionContext* context, Instruction* program, StackElement p1);
typedef StackElement (*Interpret_2_args) (ExecutionContext* context, Instruction* program,
    StackElement p1, StackElement p2);
typedef StackElement (*Interpret_3_args) (ExecutionContext* context, Instruction* program,
    StackElement p1, StackElement p2,  StackElement p3);

typedef StackElement (*JIT_0_args)();
typedef StackElement (*JIT_1_args)(StackElement p1);
typedef StackElement (*JIT_2_args)(StackElement p1, StackElement p2);
typedef StackElement (*JIT_3_args)(StackElement p1, StackElement p2, StackElement p3);

#endif // defined(B9JIT)

/* B9 Interpreter */
int parseArguments(ExecutionContext *context, int argc, char *argv[]);

Instruction *getFunctionAddress(ExecutionContext *context, const char *functionName);
//StackElement interpret(ExecutionContext* context, Instruction* program);
StackElement timeFunction(VirtualMachine *virtualMachine, Instruction *function, int loopCount, long* runningTime);

void b9PrintStack(ExecutionContext *context);

bool hasJITAddress(Instruction *p);
void generateCode(ExecutionContext *context, int32_t functionIndex);
void generateAllCode(ExecutionContext *context);
void removeAllGeneratedCode(ExecutionContext *context);
void
setJitAddress(ExecutionContext *context, int32_t functionIndex, uint64_t value);

StackElement
interpret_0(ExecutionContext *context, Instruction *program);
StackElement
interpret_1(ExecutionContext *context, Instruction *program, StackElement p1);
StackElement
interpret_2(ExecutionContext *context, Instruction *program, StackElement p1, StackElement p2);
StackElement
interpret_3(ExecutionContext *context, Instruction *program, StackElement p1, StackElement p2, StackElement p3 );

/* Debug Helpers */
void
b9PrintStack(ExecutionContext *context);

const char *
b9ByteCodeName(ByteCode bc);

} // namespace b9
#endif // b9core_hpp_
<commit_msg>Remove now unused NO_MORE_FUNCTIONS constant<commit_after>#ifndef b9core_hpp_
#define b9core_hpp_

#include <string>
#include <cstdint>

namespace b9 {

#define NO_MORE_BYTECODES 0x0

// ByteCodes

// Each Intruction is 32 bits: The first 8 bits are the ByteCode The second 24
// bits may be an argument to the opcode

typedef uint8_t ByteCodeSize;
typedef int32_t Parameter;  // even though only 24 bits used
typedef uint32_t Instruction;
typedef int64_t StackElement;

enum class ByteCode : ByteCodeSize {
    // Generic ByteCodes

    // Drop the top element of the stack
    drop = 0x1,
    // Duplicate the top element on the stack
    duplicate = 0x2,
    // Return from a function
    functionReturn = 0x3,
    // Call a Base9 function
    functionCall  = 0x4,
    // Call a native C function
    primitiveCall = 0x5,
    // Jump unconditionally by the offset
    jmp = 0x6,
    // Push from a local variable
    pushFromVar = 0x7,
    // Push into a local variable
    popIntoVar = 0x8,

    // Integer bytecodes

    // Push a constant
    intPushConstant = 0x9,
    // Subtract two integers
    intSub = 0xa,
    // Add two integers
    intAdd = 0xb,
    // Jump if two integers are equal
    intJmpEq = 0xc,
    // Jump if two integer are not equal
    intJmpNeq = 0xd,
    // Jump if the first integer is greater than the second
    intJmpGt = 0xe,
    // Jump if the first integer is greater than or equal to the second
    intJmpGe = 0xf,
    // Jump if the first integer is less than to the second
    intJmpLt = 0x10,
    // Jump if the first integer is less than or equal to the second
    intJmpLe = 0x11,

    // String ByteCodes

    // Push a string from this module's constant pool
    strPushConstant = 0x12,
    // Jump if two strings are equal
    strJmpEq = 0x13,
    // Jump if two integer are not equal
    strJmpNeq = 0x14,
};

class ByteCodes final {
 public:
  static ByteCode fromByte(uint8_t byte) { return static_cast<ByteCode>(byte); }
  static uint8_t toByte(ByteCode byteCode) { return static_cast<uint8_t>(byteCode); }

};

class Instructions final {
public:
    static Instruction create(ByteCode byteCode, Parameter parameter) {
        uint8_t byte = ByteCodes::toByte(byteCode);
        return byte << 24 | (parameter & 0xFFFFFF);
    }

    static ByteCode getByteCode (Instruction instruction) {
        return static_cast<ByteCode>(instruction >> 24);
    }

    static Parameter getParameter(Instruction instruction) {
        return static_cast<Parameter>(instruction & 0x800000 ? instruction | 0xFF000000: instruction & 0xFFFFFF);
    }
};

static constexpr Instruction
decl(uint16_t argCount, uint16_t tmpCount)
{
    return argCount << 16 | tmpCount;
}

static constexpr uint16_t
progArgCount(Instruction a)
{
    return a >> 16;
}

static constexpr uint16_t
progTmpCount(Instruction a)
{
    return a & 0xFFFF;
}

class VirtualMachine;
class ExecutionContext;

// Primitive Function from Interpreter call
extern "C" typedef void (PrimitiveFunction)(VirtualMachine *virtualMachine);

void
bc_primitive(VirtualMachine *context, Parameter value);

struct PrimitiveData {
    const char * name;
    PrimitiveFunction *address;
};

class FunctionSpecification {
public:
    const char* name_ ;
    uint32_t nargs_;
    Instruction *byteCodes_;
    uint64_t jitAddress_;
};

class ExportedFunctionData {
public:
    int functionCount_;
    FunctionSpecification *functionTable_;
};

//typedef StackElement (*Interpret) (ExecutionContext* context, Instruction* program);

#if defined(B9JIT)

// define C callable Interpret API for each arg call
// if args are passed to the function, they are not passed
// on the intepreter stack
typedef StackElement (*Interpret_0_args) (ExecutionContext* context, Instruction* program);
typedef StackElement (*Interpret_1_args) (ExecutionContext* context, Instruction* program, StackElement p1);
typedef StackElement (*Interpret_2_args) (ExecutionContext* context, Instruction* program,
    StackElement p1, StackElement p2);
typedef StackElement (*Interpret_3_args) (ExecutionContext* context, Instruction* program,
    StackElement p1, StackElement p2,  StackElement p3);

typedef StackElement (*JIT_0_args)();
typedef StackElement (*JIT_1_args)(StackElement p1);
typedef StackElement (*JIT_2_args)(StackElement p1, StackElement p2);
typedef StackElement (*JIT_3_args)(StackElement p1, StackElement p2, StackElement p3);

#endif // defined(B9JIT)

/* B9 Interpreter */
int parseArguments(ExecutionContext *context, int argc, char *argv[]);

Instruction *getFunctionAddress(ExecutionContext *context, const char *functionName);
//StackElement interpret(ExecutionContext* context, Instruction* program);
StackElement timeFunction(VirtualMachine *virtualMachine, Instruction *function, int loopCount, long* runningTime);

void b9PrintStack(ExecutionContext *context);

bool hasJITAddress(Instruction *p);
void generateCode(ExecutionContext *context, int32_t functionIndex);
void generateAllCode(ExecutionContext *context);
void removeAllGeneratedCode(ExecutionContext *context);
void
setJitAddress(ExecutionContext *context, int32_t functionIndex, uint64_t value);

StackElement
interpret_0(ExecutionContext *context, Instruction *program);
StackElement
interpret_1(ExecutionContext *context, Instruction *program, StackElement p1);
StackElement
interpret_2(ExecutionContext *context, Instruction *program, StackElement p1, StackElement p2);
StackElement
interpret_3(ExecutionContext *context, Instruction *program, StackElement p1, StackElement p2, StackElement p3 );

/* Debug Helpers */
void
b9PrintStack(ExecutionContext *context);

const char *
b9ByteCodeName(ByteCode bc);

} // namespace b9
#endif // b9core_hpp_
<|endoftext|>


<commit_before>#ifndef INC_BENCODE_HPP
#define INC_BENCODE_HPP

#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

// Try to use N4082's any and string_view classes, or fall back to Boost's.
#ifdef __has_include
#  if __has_include(<experimental/any>)
#    include <experimental/any>
#    define BENCODE_ANY_NS std::experimental
#  else
#    include <boost/any.hpp>
#    define BENCODE_ANY_NS boost
#  endif
#  if __has_include(<experimental/string_view>)
#    include <experimental/string_view>
#    define BENCODE_STRING_VIEW std::experimental::string_view
#  else
#    include <boost/utility/string_ref.hpp>
#    define BENCODE_STRING_VIEW boost::string_ref
#  endif
#else
#  include <boost/any.hpp>
#  include <boost/utility/string_ref.hpp>
#  define BENCODE_ANY_NS boost
#  define BENCODE_STRING_VIEW boost::string_ref
#endif

namespace bencode {

  using string = std::string;
  using integer = long long;
  using list = std::vector<BENCODE_ANY_NS::any>;
  using dict = std::map<std::string, BENCODE_ANY_NS::any>;

  using string_view = BENCODE_STRING_VIEW;
  using dict_view = std::map<BENCODE_STRING_VIEW, BENCODE_ANY_NS::any>;

  enum eof_behavior {
    check_eof,
    no_check_eof
  };

  template<typename T>
  BENCODE_ANY_NS::any decode(T &begin, T end);

  namespace detail {
    template<bool View, typename T>
    BENCODE_ANY_NS::any decode_data(T &begin, T end);

    template<typename T>
    integer decode_int_real(T &begin, T end) {
      assert(*begin == 'i');
      ++begin;

      bool positive = true;
      if(*begin == '-') {
        positive = false;
        ++begin;
      }

      // TODO: handle overflow
      integer value = 0;
      for(; begin != end && std::isdigit(*begin); ++begin)
        value = value * 10 + *begin - '0';
      if(begin == end)
        throw std::invalid_argument("unexpected end of string");
      if(*begin != 'e')
        throw std::invalid_argument("expected 'e'");

      ++begin;
      return positive ? value : -value;
    }

    template<bool View, typename T>
    inline integer decode_int(T &begin, T end) {
      return decode_int_real(begin, end);
    }

    template<bool View>
    class str_reader {
    public:
      template<typename Iter, typename Size>
      inline string operator ()(Iter &begin, Iter end, Size len) {
        return call(
          begin, end, len,
          typename std::iterator_traits<Iter>::iterator_category()
        );
      }
    private:
      template<typename Iter, typename Size>
      string call(Iter &begin, Iter end, Size len, std::forward_iterator_tag) {
        if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len))
          throw std::invalid_argument("unexpected end of string");

        std::string value(len, 0);
        std::copy_n(begin, len, value.begin());
        std::advance(begin, len);
        return value;
      }

      template<typename Iter, typename Size>
      string call(Iter &begin, Iter end, Size len, std::input_iterator_tag) {
        std::string value(len, 0);
        for(Size i = 0; i < len; i++) {
          if(begin == end)
            throw std::invalid_argument("unexpected end of string");
          value[i] = *begin;
          ++begin;
        }
        return value;
      }
    };

    template<>
    class str_reader<true> {
    public:
      template<typename Iter, typename Size>
      string_view operator ()(Iter &begin, Iter end, Size len) {
        if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len))
          throw std::invalid_argument("unexpected end of string");

        string_view value(begin, len);
        std::advance(begin, len);
        return value;
      }
    };

    template<bool View, typename T>
    typename std::conditional<View, string_view, string>::type
    decode_str(T &begin, T end) {
      assert(std::isdigit(*begin));
      std::size_t len = 0;
      for(; begin != end && std::isdigit(*begin); ++begin)
        len = len * 10 + *begin - '0';

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");
      if(*begin != ':')
        throw std::invalid_argument("expected ':'");
      ++begin;

      return str_reader<View>{}(begin, end, len);
    }

    template<bool View, typename T>
    list decode_list(T &begin, T end) {
      assert(*begin == 'l');
      ++begin;

      list value;
      while(begin != end && *begin != 'e') {
        value.push_back(decode_data<View>(begin, end));
      }

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");

      ++begin;
      return value;
    }

    template<bool View, typename T>
    typename std::conditional<View, dict_view, dict>::type
    decode_dict(T &begin, T end) {
      assert(*begin == 'd');
      ++begin;

      typename std::conditional<View, dict_view, dict>::type value;
      while(begin != end && *begin != 'e') {
        if(!std::isdigit(*begin))
          throw std::invalid_argument("expected string token");

        auto k = decode_str<View>(begin, end);
        auto v = decode_data<View>(begin, end);
        auto result = value.emplace(std::move(k), std::move(v));
        if(!result.second) {
          throw std::invalid_argument(
            "duplicated key in dict: " + std::string(result.first->first)
          );
        }
      }

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");

      ++begin;
      return value;
    }

    template<bool View, typename T>
    BENCODE_ANY_NS::any decode_data(T &begin, T end) {
      if(begin == end)
        return BENCODE_ANY_NS::any();

      if(*begin == 'i')
        return decode_int<View>(begin, end);
      else if(*begin == 'l')
        return decode_list<View>(begin, end);
      else if(*begin == 'd')
        return decode_dict<View>(begin, end);
      else if(std::isdigit(*begin))
        return decode_str<View>(begin, end);

      throw std::invalid_argument("unexpected type");
    }

  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode(T &begin, T end) {
    return detail::decode_data<false>(begin, end);
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode(const T &begin, T end) {
    T b(begin);
    return detail::decode_data<false>(b, end);
  }

  inline BENCODE_ANY_NS::any decode(const BENCODE_STRING_VIEW &s) {
    return decode(s.begin(), s.end());
  }

  inline BENCODE_ANY_NS::any
  decode(std::istream &s, eof_behavior e = check_eof) {
    std::istreambuf_iterator<char> begin(s), end;
    auto result = decode(begin, end);
    // If we hit EOF, update the parent stream.
    if(e == check_eof && begin == end)
      s.setstate(std::ios_base::eofbit);
    return result;
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode_view(T &begin, T end) {
    return detail::decode_data<true>(begin, end);
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode_view(const T &begin, T end) {
    T b(begin);
    return detail::decode_data<true>(b, end);
  }

  inline BENCODE_ANY_NS::any decode_view(const BENCODE_STRING_VIEW &s) {
    return decode_view(s.begin(), s.end());
  }

  class list_encoder {
  public:
    inline list_encoder(std::ostream &os) : os(os) {
      os.put('l');
    }

    template<typename T>
    inline list_encoder & add(T &&value);

    inline void end() {
      os.put('e');
    }
  private:
    std::ostream &os;
  };

  class dict_encoder {
  public:
    inline dict_encoder(std::ostream &os) : os(os) {
      os.put('d');
    }

    template<typename T>
    inline dict_encoder & add(const BENCODE_STRING_VIEW &key, T &&value);

    inline void end() {
      os.put('e');
    }
  private:
    std::ostream &os;
  };

  // TODO: make these use unformatted output?
  inline void encode(std::ostream &os, integer value) {
    os << "i" << value << "e";
  }

  inline void encode(std::ostream &os, const BENCODE_STRING_VIEW &value) {
    os << value.size() << ":" << value;
  }

  template<typename T>
  void encode(std::ostream &os, const std::vector<T> &value) {
    list_encoder e(os);
    for(auto &&i : value)
      e.add(i);
    e.end();
  }

  template<typename T>
  void encode(std::ostream &os, const std::map<std::string, T> &value) {
    dict_encoder e(os);
    for(auto &&i : value)
      e.add(i.first, i.second);
    e.end();
  }

#ifdef BENCODE_HAS_STRING_VIEW
  template<typename T>
  void encode(std::ostream &os, const std::map<BENCODE_STRING_VIEW, T> &value) {
    dict_encoder e(os);
    for(auto &&i : value)
      e.add(i.first, i.second);
    e.end();
  }
#endif

  // Overload for `any`, but only if the passed-in type is already `any`. Don't
  // accept an implicit conversion!
  template<typename T>
  auto encode(std::ostream &os, const T &value) ->
  typename std::enable_if<std::is_same<T, BENCODE_ANY_NS::any>::value>::type {
    using BENCODE_ANY_NS::any_cast;
    auto &type = value.type();

    if(type == typeid(integer))
      encode(os, any_cast<integer>(value));
    else if(type == typeid(string))
      encode(os, any_cast<string>(value));
    else if(type == typeid(list))
      encode(os, any_cast<list>(value));
    else if(type == typeid(dict))
      encode(os, any_cast<dict>(value));
#ifdef BENCODE_HAS_STRING_VIEW
    else if(type == typeid(string_view))
      encode(os, any_cast<string_view>(value));
    else if(type == typeid(dict_view))
      encode(os, any_cast<dict_view>(value));
#endif
    else
      throw std::invalid_argument("unexpected type");
  }

  namespace detail {
    inline void encode_list_items(list_encoder &) {}

    template<typename T, typename ...Rest>
    void encode_list_items(list_encoder &enc, T &&t, Rest &&...rest) {
      enc.add(std::forward<T>(t));
      encode_list_items(enc, std::forward<Rest>(rest)...);
    }

    inline void encode_dict_items(dict_encoder &) {}

    template<typename Key, typename Value, typename ...Rest>
    void encode_dict_items(dict_encoder &enc, Key &&key, Value &&value,
                           Rest &&...rest) {
      enc.add(std::forward<Key>(key), std::forward<Value>(value));
      encode_dict_items(enc, std::forward<Rest>(rest)...);
    }
  }

  template<typename ...T>
  void encode_list(std::ostream &os, T &&...t) {
    list_encoder enc(os);
    detail::encode_list_items(enc, std::forward<T>(t)...);
    enc.end();
  }

  template<typename ...T>
  void encode_dict(std::ostream &os, T &&...t) {
    dict_encoder enc(os);
    detail::encode_dict_items(enc, std::forward<T>(t)...);
    enc.end();
  }

  template<typename T>
  inline list_encoder & list_encoder::add(T &&value) {
    encode(os, std::forward<T>(value));
    return *this;
  }

  template<typename T>
  inline dict_encoder &
  dict_encoder::add(const BENCODE_STRING_VIEW &key, T &&value) {
    encode(os, key);
    encode(os, std::forward<T>(value));
    return *this;
  }

  template<typename T>
  std::string encode(T &&t) {
    std::stringstream ss;
    encode(ss, std::forward<T>(t));
    return ss.str();
  }

}

#endif
<commit_msg>Add missing #include<commit_after>#ifndef INC_BENCODE_HPP
#define INC_BENCODE_HPP

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

// Try to use N4082's any and string_view classes, or fall back to Boost's.
#ifdef __has_include
#  if __has_include(<experimental/any>)
#    include <experimental/any>
#    define BENCODE_ANY_NS std::experimental
#  else
#    include <boost/any.hpp>
#    define BENCODE_ANY_NS boost
#  endif
#  if __has_include(<experimental/string_view>)
#    include <experimental/string_view>
#    define BENCODE_STRING_VIEW std::experimental::string_view
#  else
#    include <boost/utility/string_ref.hpp>
#    define BENCODE_STRING_VIEW boost::string_ref
#  endif
#else
#  include <boost/any.hpp>
#  include <boost/utility/string_ref.hpp>
#  define BENCODE_ANY_NS boost
#  define BENCODE_STRING_VIEW boost::string_ref
#endif

namespace bencode {

  using string = std::string;
  using integer = long long;
  using list = std::vector<BENCODE_ANY_NS::any>;
  using dict = std::map<std::string, BENCODE_ANY_NS::any>;

  using string_view = BENCODE_STRING_VIEW;
  using dict_view = std::map<BENCODE_STRING_VIEW, BENCODE_ANY_NS::any>;

  enum eof_behavior {
    check_eof,
    no_check_eof
  };

  template<typename T>
  BENCODE_ANY_NS::any decode(T &begin, T end);

  namespace detail {
    template<bool View, typename T>
    BENCODE_ANY_NS::any decode_data(T &begin, T end);

    template<typename T>
    integer decode_int_real(T &begin, T end) {
      assert(*begin == 'i');
      ++begin;

      bool positive = true;
      if(*begin == '-') {
        positive = false;
        ++begin;
      }

      // TODO: handle overflow
      integer value = 0;
      for(; begin != end && std::isdigit(*begin); ++begin)
        value = value * 10 + *begin - '0';
      if(begin == end)
        throw std::invalid_argument("unexpected end of string");
      if(*begin != 'e')
        throw std::invalid_argument("expected 'e'");

      ++begin;
      return positive ? value : -value;
    }

    template<bool View, typename T>
    inline integer decode_int(T &begin, T end) {
      return decode_int_real(begin, end);
    }

    template<bool View>
    class str_reader {
    public:
      template<typename Iter, typename Size>
      inline string operator ()(Iter &begin, Iter end, Size len) {
        return call(
          begin, end, len,
          typename std::iterator_traits<Iter>::iterator_category()
        );
      }
    private:
      template<typename Iter, typename Size>
      string call(Iter &begin, Iter end, Size len, std::forward_iterator_tag) {
        if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len))
          throw std::invalid_argument("unexpected end of string");

        std::string value(len, 0);
        std::copy_n(begin, len, value.begin());
        std::advance(begin, len);
        return value;
      }

      template<typename Iter, typename Size>
      string call(Iter &begin, Iter end, Size len, std::input_iterator_tag) {
        std::string value(len, 0);
        for(Size i = 0; i < len; i++) {
          if(begin == end)
            throw std::invalid_argument("unexpected end of string");
          value[i] = *begin;
          ++begin;
        }
        return value;
      }
    };

    template<>
    class str_reader<true> {
    public:
      template<typename Iter, typename Size>
      string_view operator ()(Iter &begin, Iter end, Size len) {
        if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len))
          throw std::invalid_argument("unexpected end of string");

        string_view value(begin, len);
        std::advance(begin, len);
        return value;
      }
    };

    template<bool View, typename T>
    typename std::conditional<View, string_view, string>::type
    decode_str(T &begin, T end) {
      assert(std::isdigit(*begin));
      std::size_t len = 0;
      for(; begin != end && std::isdigit(*begin); ++begin)
        len = len * 10 + *begin - '0';

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");
      if(*begin != ':')
        throw std::invalid_argument("expected ':'");
      ++begin;

      return str_reader<View>{}(begin, end, len);
    }

    template<bool View, typename T>
    list decode_list(T &begin, T end) {
      assert(*begin == 'l');
      ++begin;

      list value;
      while(begin != end && *begin != 'e') {
        value.push_back(decode_data<View>(begin, end));
      }

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");

      ++begin;
      return value;
    }

    template<bool View, typename T>
    typename std::conditional<View, dict_view, dict>::type
    decode_dict(T &begin, T end) {
      assert(*begin == 'd');
      ++begin;

      typename std::conditional<View, dict_view, dict>::type value;
      while(begin != end && *begin != 'e') {
        if(!std::isdigit(*begin))
          throw std::invalid_argument("expected string token");

        auto k = decode_str<View>(begin, end);
        auto v = decode_data<View>(begin, end);
        auto result = value.emplace(std::move(k), std::move(v));
        if(!result.second) {
          throw std::invalid_argument(
            "duplicated key in dict: " + std::string(result.first->first)
          );
        }
      }

      if(begin == end)
        throw std::invalid_argument("unexpected end of string");

      ++begin;
      return value;
    }

    template<bool View, typename T>
    BENCODE_ANY_NS::any decode_data(T &begin, T end) {
      if(begin == end)
        return BENCODE_ANY_NS::any();

      if(*begin == 'i')
        return decode_int<View>(begin, end);
      else if(*begin == 'l')
        return decode_list<View>(begin, end);
      else if(*begin == 'd')
        return decode_dict<View>(begin, end);
      else if(std::isdigit(*begin))
        return decode_str<View>(begin, end);

      throw std::invalid_argument("unexpected type");
    }

  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode(T &begin, T end) {
    return detail::decode_data<false>(begin, end);
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode(const T &begin, T end) {
    T b(begin);
    return detail::decode_data<false>(b, end);
  }

  inline BENCODE_ANY_NS::any decode(const BENCODE_STRING_VIEW &s) {
    return decode(s.begin(), s.end());
  }

  inline BENCODE_ANY_NS::any
  decode(std::istream &s, eof_behavior e = check_eof) {
    std::istreambuf_iterator<char> begin(s), end;
    auto result = decode(begin, end);
    // If we hit EOF, update the parent stream.
    if(e == check_eof && begin == end)
      s.setstate(std::ios_base::eofbit);
    return result;
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode_view(T &begin, T end) {
    return detail::decode_data<true>(begin, end);
  }

  template<typename T>
  inline BENCODE_ANY_NS::any decode_view(const T &begin, T end) {
    T b(begin);
    return detail::decode_data<true>(b, end);
  }

  inline BENCODE_ANY_NS::any decode_view(const BENCODE_STRING_VIEW &s) {
    return decode_view(s.begin(), s.end());
  }

  class list_encoder {
  public:
    inline list_encoder(std::ostream &os) : os(os) {
      os.put('l');
    }

    template<typename T>
    inline list_encoder & add(T &&value);

    inline void end() {
      os.put('e');
    }
  private:
    std::ostream &os;
  };

  class dict_encoder {
  public:
    inline dict_encoder(std::ostream &os) : os(os) {
      os.put('d');
    }

    template<typename T>
    inline dict_encoder & add(const BENCODE_STRING_VIEW &key, T &&value);

    inline void end() {
      os.put('e');
    }
  private:
    std::ostream &os;
  };

  // TODO: make these use unformatted output?
  inline void encode(std::ostream &os, integer value) {
    os << "i" << value << "e";
  }

  inline void encode(std::ostream &os, const BENCODE_STRING_VIEW &value) {
    os << value.size() << ":" << value;
  }

  template<typename T>
  void encode(std::ostream &os, const std::vector<T> &value) {
    list_encoder e(os);
    for(auto &&i : value)
      e.add(i);
    e.end();
  }

  template<typename T>
  void encode(std::ostream &os, const std::map<std::string, T> &value) {
    dict_encoder e(os);
    for(auto &&i : value)
      e.add(i.first, i.second);
    e.end();
  }

#ifdef BENCODE_HAS_STRING_VIEW
  template<typename T>
  void encode(std::ostream &os, const std::map<BENCODE_STRING_VIEW, T> &value) {
    dict_encoder e(os);
    for(auto &&i : value)
      e.add(i.first, i.second);
    e.end();
  }
#endif

  // Overload for `any`, but only if the passed-in type is already `any`. Don't
  // accept an implicit conversion!
  template<typename T>
  auto encode(std::ostream &os, const T &value) ->
  typename std::enable_if<std::is_same<T, BENCODE_ANY_NS::any>::value>::type {
    using BENCODE_ANY_NS::any_cast;
    auto &type = value.type();

    if(type == typeid(integer))
      encode(os, any_cast<integer>(value));
    else if(type == typeid(string))
      encode(os, any_cast<string>(value));
    else if(type == typeid(list))
      encode(os, any_cast<list>(value));
    else if(type == typeid(dict))
      encode(os, any_cast<dict>(value));
#ifdef BENCODE_HAS_STRING_VIEW
    else if(type == typeid(string_view))
      encode(os, any_cast<string_view>(value));
    else if(type == typeid(dict_view))
      encode(os, any_cast<dict_view>(value));
#endif
    else
      throw std::invalid_argument("unexpected type");
  }

  namespace detail {
    inline void encode_list_items(list_encoder &) {}

    template<typename T, typename ...Rest>
    void encode_list_items(list_encoder &enc, T &&t, Rest &&...rest) {
      enc.add(std::forward<T>(t));
      encode_list_items(enc, std::forward<Rest>(rest)...);
    }

    inline void encode_dict_items(dict_encoder &) {}

    template<typename Key, typename Value, typename ...Rest>
    void encode_dict_items(dict_encoder &enc, Key &&key, Value &&value,
                           Rest &&...rest) {
      enc.add(std::forward<Key>(key), std::forward<Value>(value));
      encode_dict_items(enc, std::forward<Rest>(rest)...);
    }
  }

  template<typename ...T>
  void encode_list(std::ostream &os, T &&...t) {
    list_encoder enc(os);
    detail::encode_list_items(enc, std::forward<T>(t)...);
    enc.end();
  }

  template<typename ...T>
  void encode_dict(std::ostream &os, T &&...t) {
    dict_encoder enc(os);
    detail::encode_dict_items(enc, std::forward<T>(t)...);
    enc.end();
  }

  template<typename T>
  inline list_encoder & list_encoder::add(T &&value) {
    encode(os, std::forward<T>(value));
    return *this;
  }

  template<typename T>
  inline dict_encoder &
  dict_encoder::add(const BENCODE_STRING_VIEW &key, T &&value) {
    encode(os, key);
    encode(os, std::forward<T>(value));
    return *this;
  }

  template<typename T>
  std::string encode(T &&t) {
    std::stringstream ss;
    encode(ss, std::forward<T>(t));
    return ss.str();
  }

}

#endif
<|endoftext|>


<commit_before>#include "mainwindow.h"

#include <QCloseEvent>
#include <QToolBar>
#include <QLayout>

namespace NeovimQt {

MainWindow::MainWindow(NeovimConnector *c, ShellOptions opts, QWidget *parent)
:QMainWindow(parent), m_nvim(0), m_errorWidget(0), m_shell(0),
	m_delayedShow(DelayedShow::Disabled), m_tabline(0), m_tabline_bar(0),
	m_shell_options(opts), m_neovim_requested_close(false)
{
	m_errorWidget = new ErrorWidget();
	m_stack.addWidget(m_errorWidget);
	connect(m_errorWidget, &ErrorWidget::reconnectNeovim,
			this, &MainWindow::reconnectNeovim);
	setCentralWidget(&m_stack);

	init(c);
}

void MainWindow::init(NeovimConnector *c)
{
	if (m_shell) {
		m_shell->deleteLater();
		m_stack.removeWidget(m_shell);
	}
	if (m_nvim) {
		m_nvim->deleteLater();
	}

	m_tabline_bar = addToolBar("tabline");
	m_tabline_bar->setObjectName("tabline");
	m_tabline_bar->setAllowedAreas(Qt::TopToolBarArea);
	m_tabline_bar->setMovable(false);
	m_tabline_bar->setFloatable(false);
	// Avoid margins around the tabbar
	m_tabline_bar->layout()->setContentsMargins(0, 0, 0, 0);

	m_tabline = new QTabBar(m_tabline_bar);
	m_tabline->setDrawBase(false);
	m_tabline->setExpanding(false);
	m_tabline->setDocumentMode(true);
	m_tabline->setFocusPolicy(Qt::NoFocus);
	connect(m_tabline, &QTabBar::currentChanged,
			this, &MainWindow::changeTab);

	m_tabline_bar->addWidget(m_tabline);
	m_tabline_bar->setVisible(m_shell_options.enable_ext_tabline);

	m_nvim = c;

	m_tree = new TreeView(c);
	m_shell = new Shell(c, m_shell_options);

	m_window = new QSplitter();
	m_window->addWidget(m_tree);
	m_tree->hide();
	m_window->addWidget(m_shell);

	m_stack.insertWidget(1, m_window);
	m_stack.setCurrentIndex(1);

	connect(m_shell, SIGNAL(neovimAttached(bool)),
			this, SLOT(neovimAttachmentChanged(bool)));
	connect(m_shell, SIGNAL(neovimTitleChanged(const QString &)),
			this, SLOT(neovimSetTitle(const QString &)));
	connect(m_shell, &Shell::neovimResized,
			this, &MainWindow::neovimWidgetResized);
	connect(m_shell, &Shell::neovimMaximized,
			this, &MainWindow::neovimMaximized);
	connect(m_shell, &Shell::neovimSuspend,
			this, &MainWindow::neovimSuspend);
	connect(m_shell, &Shell::neovimFullScreen,
			this, &MainWindow::neovimFullScreen);
	connect(m_shell, &Shell::neovimGuiCloseRequest,
			this, &MainWindow::neovimGuiCloseRequest);
	connect(m_nvim, &NeovimConnector::processExited,
			this, &MainWindow::neovimExited);
	connect(m_nvim, &NeovimConnector::error,
			this, &MainWindow::neovimError);
	connect(m_shell, &Shell::neovimIsUnsupported,
			this, &MainWindow::neovimIsUnsupported);
	connect(m_shell, &Shell::neovimExtTablineSet,
			this, &MainWindow::extTablineSet);
	connect(m_shell, &Shell::neovimTablineUpdate,
			this, &MainWindow::neovimTablineUpdate);
	connect(m_shell, &Shell::neovimShowtablineSet,
			this, &MainWindow::neovimShowtablineSet);
	m_shell->setFocus(Qt::OtherFocusReason);

	if (m_nvim->errorCause()) {
		neovimError(m_nvim->errorCause());
	}
}

bool MainWindow::neovimAttached() const
{
	return (m_shell != NULL && m_shell->neovimAttached());
}

/** The Neovim process has exited */
void MainWindow::neovimExited(int status)
{
	showIfDelayed();

	if (m_nvim->errorCause() != NeovimConnector::NoError) {
		m_errorWidget->setText(m_nvim->errorString());
		m_errorWidget->showReconnect(m_nvim->canReconnect());
		m_stack.setCurrentIndex(0);
	} else if (status != 0) {
		m_errorWidget->setText(QString("Neovim exited with status code (%1)").arg(status));
		m_errorWidget->showReconnect(m_nvim->canReconnect());
		m_stack.setCurrentIndex(0);
	} else {
		close();
	}
}
void MainWindow::neovimError(NeovimConnector::NeovimError err)
{
	showIfDelayed();

	switch(err) {
	case NeovimConnector::FailedToStart:
		m_errorWidget->setText("Unable to start nvim: " + m_nvim->errorString());
		break;
	default:
		m_errorWidget->setText(m_nvim->errorString());
	}
	m_errorWidget->showReconnect(m_nvim->canReconnect());
	m_stack.setCurrentIndex(0);
}
void MainWindow::neovimIsUnsupported()
{
	showIfDelayed();
	m_errorWidget->setText(QString("Cannot connect to this Neovim, required API version 1, found [%1-%2]")
			.arg(m_nvim->apiCompatibility())
			.arg(m_nvim->apiLevel()));
	m_errorWidget->showReconnect(m_nvim->canReconnect());
	m_stack.setCurrentIndex(0);
}

void MainWindow::neovimSetTitle(const QString &title)
{
	this->setWindowTitle(title);
}

void MainWindow::neovimWidgetResized()
{
	// Neovim finished resizing, resize it back to the actual
	// widget size - this avoids situations when neovim wants a size that
	// exceeds the available widget size i.e. the GUI tells neovim its
	// size, not the other way around.
	if (isMaximized() || isFullScreen()) {
		QSize size = geometry().size();
        if (m_tabline_bar->isVisible()) {
            size.setHeight(size.height() - m_tabline_bar->geometry().size().height());
        }
		if (m_tree->isVisible()) {
			size.scale(size.width() - m_tree->geometry().size().width(),
				size.height(), Qt::IgnoreAspectRatio);
		}
		m_shell->resizeNeovim(size);
	} else {
		m_shell->resizeNeovim(m_shell->size());
	}
}

void MainWindow::neovimMaximized(bool set)
{
	if (set) {
		setWindowState(windowState() | Qt::WindowMaximized);
	} else {
		setWindowState(windowState() & ~Qt::WindowMaximized);
	}
}

void MainWindow::neovimSuspend()
{
	qDebug() << "Minimizing window";
	setWindowState(windowState() | Qt::WindowMinimized);
}

void MainWindow::neovimFullScreen(bool set)
{
	if (set) {
		setWindowState(windowState() | Qt::WindowFullScreen);
	} else {
		setWindowState(windowState() & ~Qt::WindowFullScreen);
	}
}

void MainWindow::neovimGuiCloseRequest()
{
	m_neovim_requested_close = true;
	QMainWindow::close();
	m_neovim_requested_close = false;
}

void MainWindow::reconnectNeovim()
{
	if (m_nvim->canReconnect()) {
		init(m_nvim->reconnect());
	}
	m_stack.setCurrentIndex(1);
}

void MainWindow::closeEvent(QCloseEvent *ev)
{
	if (m_neovim_requested_close) {
		// If this was requested by nvim, shutdown
		QWidget::closeEvent(ev);
	} else if (m_shell->close()) {
		// otherwise only if the Neovim shell closes too
		QWidget::closeEvent(ev);
	} else {
		ev->ignore();
	}
}
void MainWindow::changeEvent( QEvent *ev)
{
	if (ev->type() == QEvent::WindowStateChange && isWindow()) {
		m_shell->updateGuiWindowState(windowState());
	}
	QWidget::changeEvent(ev);
}

/// Call show() after a 1s delay or when Neovim attachment
/// is complete, whichever comes first
void MainWindow::delayedShow(DelayedShow type)
{
	m_delayedShow = type;
	if (m_nvim->errorCause() != NeovimConnector::NoError) {
		showIfDelayed();
		return;
	}

	if (type != DelayedShow::Disabled) {
		QTimer *t = new QTimer(this);
		t->setSingleShot(true);
		t->setInterval(1000);
		connect(m_shell, &Shell::neovimResized, this, &MainWindow::showIfDelayed);
		connect(t, &QTimer::timeout, this, &MainWindow::showIfDelayed);
		t->start();
	}
}

void MainWindow::showIfDelayed()
{
	if (!isVisible()) {
		if (m_delayedShow == DelayedShow::Normal) {
			show();
		} else if (m_delayedShow == DelayedShow::Maximized) {
			showMaximized();
		} else if (m_delayedShow == DelayedShow::FullScreen) {
			showFullScreen();
		}
	}
	m_delayedShow = DelayedShow::Disabled;
}

void MainWindow::neovimAttachmentChanged(bool attached)
{
	emit neovimAttached(attached);
	if (attached) {
		if (isWindow() && m_shell != NULL) {
			m_shell->updateGuiWindowState(windowState());
		}
	} else {
		m_tabline->deleteLater();
		m_tabline_bar->deleteLater();
	}
}

Shell* MainWindow::shell()
{
	return m_shell;
}

void MainWindow::extTablineSet(bool val)
{
	bool old = m_shell_options.enable_ext_tabline;
	m_shell_options.enable_ext_tabline = val;
	// redraw if state changed
	if (old != m_shell_options.enable_ext_tabline) {
		if (!val) m_tabline_bar->setVisible(false);
		m_nvim->api0()->vim_command("silent! redraw!");
	}
}

void MainWindow::neovimShowtablineSet(int val)
{
	m_shell_options.nvim_show_tabline = val;
}

void MainWindow::neovimTablineUpdate(int64_t curtab, QList<Tab> tabs)
{
	if (!m_shell_options.enable_ext_tabline) {
		return;
	}

	// remove extra tabs
	for (int index=tabs.size(); index<m_tabline->count(); index++) {
		m_tabline->removeTab(index);
	}

	for (int index=0; index<tabs.size(); index++) {
		// Escape & in tab name otherwise it will be interpreted as
		// a keyboard shortcut (#357) - escaping is done using &&
		QString text = tabs[index].name;
		text.replace("&", "&&");

		if (m_tabline->count() <= index) {
			m_tabline->addTab(text);
		} else {
			m_tabline->setTabText(index, text);
		}

		m_tabline->setTabData(index, QVariant::fromValue(tabs[index].tab));

		if (curtab == tabs[index].tab) {
			m_tabline->setCurrentIndex(index);
		}
	}

	// hide/show the tabline toolbar
	if (m_shell_options.nvim_show_tabline==0) {
		m_tabline_bar->setVisible(false);
	} else if (m_shell_options.nvim_show_tabline==2) {
		m_tabline_bar->setVisible(true);
	} else {
		m_tabline_bar->setVisible(tabs.size() > 1);
	}

	Q_ASSERT(tabs.size() == m_tabline->count());
}

void MainWindow::changeTab(int index)
{
	if (!m_shell_options.enable_ext_tabline) {
		return;
	}

	if (m_nvim->api2() == NULL) {
		return;
	}

	int64_t tab = m_tabline->tabData(index).toInt();
	m_nvim->api2()->nvim_set_current_tabpage(tab);
}
}  // namespace NeovimQt
<commit_msg>added tooltip  information for a tab<commit_after>#include "mainwindow.h"

#include <QCloseEvent>
#include <QToolBar>
#include <QLayout>

namespace NeovimQt {

MainWindow::MainWindow(NeovimConnector *c, ShellOptions opts, QWidget *parent)
:QMainWindow(parent), m_nvim(0), m_errorWidget(0), m_shell(0),
	m_delayedShow(DelayedShow::Disabled), m_tabline(0), m_tabline_bar(0),
	m_shell_options(opts), m_neovim_requested_close(false)
{
	m_errorWidget = new ErrorWidget();
	m_stack.addWidget(m_errorWidget);
	connect(m_errorWidget, &ErrorWidget::reconnectNeovim,
			this, &MainWindow::reconnectNeovim);
	setCentralWidget(&m_stack);

	init(c);
}

void MainWindow::init(NeovimConnector *c)
{
	if (m_shell) {
		m_shell->deleteLater();
		m_stack.removeWidget(m_shell);
	}
	if (m_nvim) {
		m_nvim->deleteLater();
	}

	m_tabline_bar = addToolBar("tabline");
	m_tabline_bar->setObjectName("tabline");
	m_tabline_bar->setAllowedAreas(Qt::TopToolBarArea);
	m_tabline_bar->setMovable(false);
	m_tabline_bar->setFloatable(false);
	// Avoid margins around the tabbar
	m_tabline_bar->layout()->setContentsMargins(0, 0, 0, 0);

	m_tabline = new QTabBar(m_tabline_bar);
	m_tabline->setDrawBase(false);
	m_tabline->setExpanding(false);
	m_tabline->setDocumentMode(true);
	m_tabline->setFocusPolicy(Qt::NoFocus);
	connect(m_tabline, &QTabBar::currentChanged,
			this, &MainWindow::changeTab);

	m_tabline_bar->addWidget(m_tabline);
	m_tabline_bar->setVisible(m_shell_options.enable_ext_tabline);

	m_nvim = c;

	m_tree = new TreeView(c);
	m_shell = new Shell(c, m_shell_options);

	m_window = new QSplitter();
	m_window->addWidget(m_tree);
	m_tree->hide();
	m_window->addWidget(m_shell);

	m_stack.insertWidget(1, m_window);
	m_stack.setCurrentIndex(1);

	connect(m_shell, SIGNAL(neovimAttached(bool)),
			this, SLOT(neovimAttachmentChanged(bool)));
	connect(m_shell, SIGNAL(neovimTitleChanged(const QString &)),
			this, SLOT(neovimSetTitle(const QString &)));
	connect(m_shell, &Shell::neovimResized,
			this, &MainWindow::neovimWidgetResized);
	connect(m_shell, &Shell::neovimMaximized,
			this, &MainWindow::neovimMaximized);
	connect(m_shell, &Shell::neovimSuspend,
			this, &MainWindow::neovimSuspend);
	connect(m_shell, &Shell::neovimFullScreen,
			this, &MainWindow::neovimFullScreen);
	connect(m_shell, &Shell::neovimGuiCloseRequest,
			this, &MainWindow::neovimGuiCloseRequest);
	connect(m_nvim, &NeovimConnector::processExited,
			this, &MainWindow::neovimExited);
	connect(m_nvim, &NeovimConnector::error,
			this, &MainWindow::neovimError);
	connect(m_shell, &Shell::neovimIsUnsupported,
			this, &MainWindow::neovimIsUnsupported);
	connect(m_shell, &Shell::neovimExtTablineSet,
			this, &MainWindow::extTablineSet);
	connect(m_shell, &Shell::neovimTablineUpdate,
			this, &MainWindow::neovimTablineUpdate);
	connect(m_shell, &Shell::neovimShowtablineSet,
			this, &MainWindow::neovimShowtablineSet);
	m_shell->setFocus(Qt::OtherFocusReason);

	if (m_nvim->errorCause()) {
		neovimError(m_nvim->errorCause());
	}
}

bool MainWindow::neovimAttached() const
{
	return (m_shell != NULL && m_shell->neovimAttached());
}

/** The Neovim process has exited */
void MainWindow::neovimExited(int status)
{
	showIfDelayed();

	if (m_nvim->errorCause() != NeovimConnector::NoError) {
		m_errorWidget->setText(m_nvim->errorString());
		m_errorWidget->showReconnect(m_nvim->canReconnect());
		m_stack.setCurrentIndex(0);
	} else if (status != 0) {
		m_errorWidget->setText(QString("Neovim exited with status code (%1)").arg(status));
		m_errorWidget->showReconnect(m_nvim->canReconnect());
		m_stack.setCurrentIndex(0);
	} else {
		close();
	}
}
void MainWindow::neovimError(NeovimConnector::NeovimError err)
{
	showIfDelayed();

	switch(err) {
	case NeovimConnector::FailedToStart:
		m_errorWidget->setText("Unable to start nvim: " + m_nvim->errorString());
		break;
	default:
		m_errorWidget->setText(m_nvim->errorString());
	}
	m_errorWidget->showReconnect(m_nvim->canReconnect());
	m_stack.setCurrentIndex(0);
}
void MainWindow::neovimIsUnsupported()
{
	showIfDelayed();
	m_errorWidget->setText(QString("Cannot connect to this Neovim, required API version 1, found [%1-%2]")
			.arg(m_nvim->apiCompatibility())
			.arg(m_nvim->apiLevel()));
	m_errorWidget->showReconnect(m_nvim->canReconnect());
	m_stack.setCurrentIndex(0);
}

void MainWindow::neovimSetTitle(const QString &title)
{
	this->setWindowTitle(title);
}

void MainWindow::neovimWidgetResized()
{
	// Neovim finished resizing, resize it back to the actual
	// widget size - this avoids situations when neovim wants a size that
	// exceeds the available widget size i.e. the GUI tells neovim its
	// size, not the other way around.
	if (isMaximized() || isFullScreen()) {
		QSize size = geometry().size();
        if (m_tabline_bar->isVisible()) {
            size.setHeight(size.height() - m_tabline_bar->geometry().size().height());
        }
		if (m_tree->isVisible()) {
			size.scale(size.width() - m_tree->geometry().size().width(),
				size.height(), Qt::IgnoreAspectRatio);
		}
		m_shell->resizeNeovim(size);
	} else {
		m_shell->resizeNeovim(m_shell->size());
	}
}

void MainWindow::neovimMaximized(bool set)
{
	if (set) {
		setWindowState(windowState() | Qt::WindowMaximized);
	} else {
		setWindowState(windowState() & ~Qt::WindowMaximized);
	}
}

void MainWindow::neovimSuspend()
{
	qDebug() << "Minimizing window";
	setWindowState(windowState() | Qt::WindowMinimized);
}

void MainWindow::neovimFullScreen(bool set)
{
	if (set) {
		setWindowState(windowState() | Qt::WindowFullScreen);
	} else {
		setWindowState(windowState() & ~Qt::WindowFullScreen);
	}
}

void MainWindow::neovimGuiCloseRequest()
{
	m_neovim_requested_close = true;
	QMainWindow::close();
	m_neovim_requested_close = false;
}

void MainWindow::reconnectNeovim()
{
	if (m_nvim->canReconnect()) {
		init(m_nvim->reconnect());
	}
	m_stack.setCurrentIndex(1);
}

void MainWindow::closeEvent(QCloseEvent *ev)
{
	if (m_neovim_requested_close) {
		// If this was requested by nvim, shutdown
		QWidget::closeEvent(ev);
	} else if (m_shell->close()) {
		// otherwise only if the Neovim shell closes too
		QWidget::closeEvent(ev);
	} else {
		ev->ignore();
	}
}
void MainWindow::changeEvent( QEvent *ev)
{
	if (ev->type() == QEvent::WindowStateChange && isWindow()) {
		m_shell->updateGuiWindowState(windowState());
	}
	QWidget::changeEvent(ev);
}

/// Call show() after a 1s delay or when Neovim attachment
/// is complete, whichever comes first
void MainWindow::delayedShow(DelayedShow type)
{
	m_delayedShow = type;
	if (m_nvim->errorCause() != NeovimConnector::NoError) {
		showIfDelayed();
		return;
	}

	if (type != DelayedShow::Disabled) {
		QTimer *t = new QTimer(this);
		t->setSingleShot(true);
		t->setInterval(1000);
		connect(m_shell, &Shell::neovimResized, this, &MainWindow::showIfDelayed);
		connect(t, &QTimer::timeout, this, &MainWindow::showIfDelayed);
		t->start();
	}
}

void MainWindow::showIfDelayed()
{
	if (!isVisible()) {
		if (m_delayedShow == DelayedShow::Normal) {
			show();
		} else if (m_delayedShow == DelayedShow::Maximized) {
			showMaximized();
		} else if (m_delayedShow == DelayedShow::FullScreen) {
			showFullScreen();
		}
	}
	m_delayedShow = DelayedShow::Disabled;
}

void MainWindow::neovimAttachmentChanged(bool attached)
{
	emit neovimAttached(attached);
	if (attached) {
		if (isWindow() && m_shell != NULL) {
			m_shell->updateGuiWindowState(windowState());
		}
	} else {
		m_tabline->deleteLater();
		m_tabline_bar->deleteLater();
	}
}

Shell* MainWindow::shell()
{
	return m_shell;
}

void MainWindow::extTablineSet(bool val)
{
	bool old = m_shell_options.enable_ext_tabline;
	m_shell_options.enable_ext_tabline = val;
	// redraw if state changed
	if (old != m_shell_options.enable_ext_tabline) {
		if (!val) m_tabline_bar->setVisible(false);
		m_nvim->api0()->vim_command("silent! redraw!");
	}
}

void MainWindow::neovimShowtablineSet(int val)
{
	m_shell_options.nvim_show_tabline = val;
}

void MainWindow::neovimTablineUpdate(int64_t curtab, QList<Tab> tabs)
{
	if (!m_shell_options.enable_ext_tabline) {
		return;
	}

	// remove extra tabs
	for (int index=tabs.size(); index<m_tabline->count(); index++) {
		m_tabline->removeTab(index);
	}

	for (int index=0; index<tabs.size(); index++) {
		// Escape & in tab name otherwise it will be interpreted as
		// a keyboard shortcut (#357) - escaping is done using &&
		QString text = tabs[index].name;
		text.replace("&", "&&");

		if (m_tabline->count() <= index) {
			m_tabline->addTab(text);
		} else {
			m_tabline->setTabText(index, text);
		}

		m_tabline->setTabToolTip(index, text);
		m_tabline->setTabData(index, QVariant::fromValue(tabs[index].tab));

		if (curtab == tabs[index].tab) {
			m_tabline->setCurrentIndex(index);
		}
	}

	// hide/show the tabline toolbar
	if (m_shell_options.nvim_show_tabline==0) {
		m_tabline_bar->setVisible(false);
	} else if (m_shell_options.nvim_show_tabline==2) {
		m_tabline_bar->setVisible(true);
	} else {
		m_tabline_bar->setVisible(tabs.size() > 1);
	}

	Q_ASSERT(tabs.size() == m_tabline->count());
}

void MainWindow::changeTab(int index)
{
	if (!m_shell_options.enable_ext_tabline) {
		return;
	}

	if (m_nvim->api2() == NULL) {
		return;
	}

	int64_t tab = m_tabline->tabData(index).toInt();
	m_nvim->api2()->nvim_set_current_tabpage(tab);
}
}  // namespace NeovimQt
<|endoftext|>


<commit_before>// This binary provides an easy way to open a zeromq server and feeds data to
// clients connect to it. It uses the Caffe2 db as the backend, thus allowing
// one to convert any db-compliant storage to a zeromq service.

#include <atomic>

#include "caffe2/core/db.h"
#include "caffe2/utils/zmq.hpp"
#include "glog/logging.h"

DEFINE_string(server, "tcp://*:5555", "The server address.");
DEFINE_string(input_db, "", "The input db.");
DEFINE_string(input_db_type, "", "The input db type.");

using caffe2::db::DB;
using caffe2::db::Cursor;
using caffe2::string;

std::unique_ptr<DB> in_db;
std::unique_ptr<Cursor> cursor;

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  google::SetUsageMessage("Runs a given plan.");
  google::ParseCommandLineFlags(&argc, &argv, true);

  LOG(INFO) << "Opening DB...";
  in_db.reset(caffe2::db::CreateDB(
      FLAGS_input_db_type, FLAGS_input_db, caffe2::db::READ));
  CHECK(in_db.get() != nullptr) << "Cannot load input db.";
  cursor.reset(in_db->NewCursor());
  LOG(INFO) << "DB opened.";

  LOG(INFO) << "Starting ZeroMQ server...";
  try {
    //  Socket to talk to clients
    zmq::context_t context(1);
    zmq::socket_t sender(context, ZMQ_PUSH);
    sender.bind(FLAGS_server);
    LOG(INFO) << "Server created at " << FLAGS_server;
  } catch (const zmq::error_t& ze) {
    LOG(FATAL) << "ZeroMQ error: " << ze.num() << " " << ze.what();
  }

  while (1) {
    VLOG(1) << "Sending " << cursor->key();

    string key = cursor->key();
    zmq::message_t key_msg(key.size());
    memcpy(key_msg.data(), key.data(), key.size());
    while (!sender.send(key_msg, ZMQ_SNDMORE)) {
      VLOG(1) << "Trying re-sending key...";
    }

    string value = cursor->value();
    zmq::message_t value_msg(value.size());
    memcpy(value_msg.data(), value.data(), value.size());
    while(!sender.send(value_msg)) {
      VLOG(1) << "Trying re-sending...";
    }
    cursor->Next();
    if (!cursor->Valid()) {
      cursor->SeekToFirst();
    }
  }
  // We do not do an elegant quit since this binary is going to be terminated by
  // control+C.
  return 0;
}
<commit_msg>zmq feeder bugfix<commit_after>// This binary provides an easy way to open a zeromq server and feeds data to
// clients connect to it. It uses the Caffe2 db as the backend, thus allowing
// one to convert any db-compliant storage to a zeromq service.

#include <atomic>

#include "caffe2/core/db.h"
#include "caffe2/utils/zmq.hpp"
#include "gflags/gflags.h"
#include "glog/logging.h"

DEFINE_string(server, "tcp://*:5555", "The server address.");
DEFINE_string(input_db, "", "The input db.");
DEFINE_string(input_db_type, "", "The input db type.");

using caffe2::db::DB;
using caffe2::db::Cursor;
using caffe2::string;

std::unique_ptr<DB> in_db;
std::unique_ptr<Cursor> cursor;

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  gflags::SetUsageMessage("Runs a given plan.");
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  LOG(INFO) << "Opening DB...";
  in_db.reset(caffe2::db::CreateDB(
      FLAGS_input_db_type, FLAGS_input_db, caffe2::db::READ));
  CHECK(in_db.get() != nullptr) << "Cannot load input db.";
  cursor.reset(in_db->NewCursor());
  LOG(INFO) << "DB opened.";

  LOG(INFO) << "Starting ZeroMQ server...";

  //  Socket to talk to clients
  zmq::context_t context(1);
  zmq::socket_t sender(context, ZMQ_PUSH);
  try {
    sender.bind(FLAGS_server);
    LOG(INFO) << "Server created at " << FLAGS_server;
  } catch (const zmq::error_t& ze) {
    LOG(FATAL) << "ZeroMQ error: " << ze.num() << " " << ze.what();
  }

  while (1) {
    VLOG(1) << "Sending " << cursor->key();

    string key = cursor->key();
    zmq::message_t key_msg(key.size());
    memcpy(key_msg.data(), key.data(), key.size());
    while (!sender.send(key_msg, ZMQ_SNDMORE)) {
      VLOG(1) << "Trying re-sending key...";
    }

    string value = cursor->value();
    zmq::message_t value_msg(value.size());
    memcpy(value_msg.data(), value.data(), value.size());
    while(!sender.send(value_msg)) {
      VLOG(1) << "Trying re-sending...";
    }
    cursor->Next();
    if (!cursor->Valid()) {
      cursor->SeekToFirst();
    }
  }
  // We do not do an elegant quit since this binary is going to be terminated by
  // control+C.
  return 0;
}
<|endoftext|>