<commit_before>// MIT License
//
// Copyright (c) 2017-2018 Artur Wyszyński, aljen at hitomi dot pl
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "spaghetti/registry.h"

#include <vector>

#include "filesystem.h"
#include "shared_library.h"

#include "elements/all.h"
#include "nodes/all.h"
#include "spaghetti/logger.h"
#include "spaghetti/version.h"

inline void init_resources()
{
  Q_INIT_RESOURCE(icons);
}

namespace spaghetti {

struct Registry::PIMPL {
  using Plugins = std::vector<std::shared_ptr<SharedLibrary>>;
  using MetaInfos = std::vector<MetaInfo>;
  MetaInfos metaInfos{};
  Plugins plugins{};
};

Registry &Registry::get()
{
  static Registry s_registry{};
  return s_registry;
}

Registry::~Registry() = default;

Registry::Registry()
  : m_pimpl{ std::make_unique<PIMPL>() }
{
  log::init();

  log::info("Spaghetti version: {}, git: {}@{}, build date: {}, {}", version::STRING, version::BRANCH,
            version::COMMIT_SHORT_HASH, __DATE__, __TIME__);
}

void Registry::registerInternalElements()
{
  init_resources();

  using namespace elements;

  registerElement<Package>("Package", ":/logic/package.png");

  registerElement<gates::And>("AND (Bool)", ":/gates/and.png");
  registerElement<gates::Nand>("NAND (Bool)", ":/gates/nand.png");
  registerElement<gates::Nor>("NOR (Bool)", ":/gates/nor.png");
  registerElement<gates::Not>("NOT (Bool)", ":/gates/not.png");
  registerElement<gates::Or>("OR (Bool)", ":/gates/or.png");

  registerElement<logic::IfGreaterEqual>("If A >= B (Float)", ":/unknown.png");
  registerElement<logic::IfGreater>("If A > B (Float)", ":/unknown.png");
  registerElement<logic::IfEqual>("If A == B (Float)", ":/unknown.png");
  registerElement<logic::IfLower>("If A < B (Float)", ":/unknown.png");
  registerElement<logic::IfLowerEqual>("If A <= B (Float)", ":/unknown.png");

  registerElement<logic::MultiplexerInt>("Multiplexer (Int)", ":/unknown.png");
  registerElement<logic::DemultiplexerInt>("Demultiplexer (Int)", ":/unknown.png");

  registerElement<logic::Blinker, nodes::logic::Blinker>("Blinker (Bool)", ":/unknown.png");
  registerElement<logic::Clock, nodes::logic::Clock>("Clock (ms)", ":/logic/clock.png");
  registerElement<logic::Switch>("Switch (Int)", ":/logic/switch.png");

  registerElement<math::Abs>("Abs (Float)", ":/unknown.png");

  registerElement<math::Add>("Add (Float)", ":/unknown.png");
  registerElement<math::AddIf>("Add If (Float)", ":/unknown.png");
  registerElement<math::Subtract>("Subtract (Float)", ":/unknown.png");
  registerElement<math::SubtractIf>("Subtract If (Float)", ":/unknown.png");
  registerElement<math::Divide>("Divide (Float)", ":/unknown.png");
  registerElement<math::DivideIf>("Divide If (Float)", ":/unknown.png");
  registerElement<math::Multiply>("Multiply (Float)", ":/unknown.png");
  registerElement<math::MultiplyIf>("Multiply If (Float)", ":/unknown.png");

  registerElement<math::Cos>("Cos (Rad)", ":/unknown.png");
  registerElement<math::Sin>("Sin (Rad)", ":/unknown.png");

  registerElement<ui::FloatInfo, nodes::ui::FloatInfo>("Info (Float)", ":/values/const_float.png");
  registerElement<ui::IntInfo, nodes::ui::IntInfo>("Info (Int)", ":/values/const_int.png");

  registerElement<ui::PushButton, nodes::ui::PushButton>("Push Button (Bool)", ":/ui/push_button.png");
  registerElement<ui::ToggleButton, nodes::ui::ToggleButton>("Toggle Button (Bool)", ":/ui/toggle_button.png");

  registerElement<values::ConstBool, nodes::values::ConstBool>("Const value (Bool)", ":/values/const_bool.png");
  registerElement<values::ConstFloat, nodes::values::ConstFloat>("Const value (Float)", ":/values/const_float.png");
  registerElement<values::ConstInt, nodes::values::ConstInt>("Const value (Int)", ":/values/const_int.png");
  registerElement<values::RandomBool>("Random value (Bool)", ":/values/random_value.png");

  registerElement<values::Degree2Radian>("Convert angle (Deg2Rad)", ":/unknown.png");
  registerElement<values::Radian2Degree>("Convert angle (Rad2Deg)", ":/unknown.png");
  registerElement<values::Int2Float>("Convert value (Int2Float)", ":/unknown.png");
  registerElement<values::Float2Int>("Convert value (Float2Int)", ":/unknown.png");

  registerElement<values::MinInt>("Minimum value (Int)", ":/unknown.png");
  registerElement<values::MaxInt>("Maximum value (Int)", ":/unknown.png");
  registerElement<values::MinFloat>("Minimum value (Float)", ":/unknown.png");
  registerElement<values::MaxFloat>("Maximum value (Float)", ":/unknown.png");

  registerElement<values::ClampFloat>("Clamp value (Float)", ":/unknown.png");
  registerElement<values::ClampInt>("Clamp value (Int)", ":/unknown.png");
}

static std::string get_application_path()
{
#ifndef MAX_PATH
#define MAX_PATH 4098
#endif
  std::string name{};
  name.resize(MAX_PATH);
#if defined(_WIN64) || defined(_WIN32)
  GetModuleFileNameA(0, const_cast<LPSTR>(name.c_str()), MAX_PATH);
#elif defined(__linux__)
  readlink("/proc/self/exe", &name[0], MAX_PATH);
#endif
  name.resize(strlen(name.data()));

  return name;
}

void Registry::loadPlugins()
{
  fs::path const APP_PATH{ fs::path{ get_application_path() }.parent_path() };
  fs::path const LIB_PATH{ fs::canonical(fs::path{ APP_PATH.string() + "/../lib" }) };
  fs::path const SYSTEM_PLUGINS_DIR{ LIB_PATH / "spaghetti" };
  fs::path const HOME_DIR{ getenv("HOME") };
  fs::path const USER_PLUGINS_DIR{ fs::absolute(HOME_DIR / ".config/spaghetti/plugins") };

  fs::create_directories(USER_PLUGINS_DIR);

  auto loadFrom = [this](fs::path const &a_path) {
    spaghetti::log::info("Loading plugins from {}", a_path.string());
    if (!fs::is_directory(a_path)) return;
    for (auto const &ENTRY : fs::directory_iterator(a_path)) {
      spaghetti::log::info("Loading {}..", ENTRY.path().string());
      if (!(fs::is_regular_file(ENTRY) || fs::is_symlink(ENTRY))) continue;

      std::error_code error{};
      auto plugin = std::make_shared<SharedLibrary>(ENTRY, error);

      if (error.value() != 0 || !plugin->has("register_plugin")) continue;

      auto registerPlugin = plugin->get<void(Registry &)>("register_plugin");
      registerPlugin(*this);

      m_pimpl->plugins.emplace_back(std::move(plugin));
    }
  };

  loadFrom(USER_PLUGINS_DIR);
  loadFrom(SYSTEM_PLUGINS_DIR);
}

Element *Registry::createElement(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  assert(META_INFO.cloneElement);
  return META_INFO.cloneElement();
}

Node *Registry::createNode(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  assert(META_INFO.cloneNode);
  return META_INFO.cloneNode();
}

std::string Registry::elementName(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  return META_INFO.name;
}

std::string Registry::elementIcon(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  return META_INFO.icon;
}

void Registry::addElement(MetaInfo &a_metaInfo)
{
  auto &metaInfos = m_pimpl->metaInfos;
  metaInfos.push_back(std::move(a_metaInfo));
}

bool Registry::hasElement(string::hash_t const a_hash) const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  auto const IT = std::find_if(std::begin(META_INFOS), std::end(META_INFOS),
                               [a_hash](auto const &a_metaInfo) { return a_metaInfo.hash == a_hash; });
  return IT != std::end(META_INFOS);
}

size_t Registry::size() const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  return META_INFOS.size();
}

Registry::MetaInfo const &Registry::metaInfoFor(string::hash_t const a_hash) const
{
  auto &metaInfos = m_pimpl->metaInfos;
  assert(hasElement(a_hash));
  auto const IT = std::find_if(std::begin(metaInfos), std::end(metaInfos),
                               [a_hash](auto const &a_metaInfo) { return a_metaInfo.hash == a_hash; });
  return *IT;
}

Registry::MetaInfo const &Registry::metaInfoAt(size_t const a_index) const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  return META_INFOS[a_index];
}

} // namespace spaghetti
<commit_msg>Move get_application_path to the top<commit_after>// MIT License
//
// Copyright (c) 2017-2018 Artur Wyszyński, aljen at hitomi dot pl
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "spaghetti/registry.h"

#include <vector>

#include "filesystem.h"
#include "shared_library.h"

#include "elements/all.h"
#include "nodes/all.h"
#include "spaghetti/logger.h"
#include "spaghetti/version.h"

inline void init_resources()
{
  Q_INIT_RESOURCE(icons);
}

static std::string get_application_path()
{
#ifndef MAX_PATH
#define MAX_PATH 4098
#endif
  std::string name{};
  name.resize(MAX_PATH);
#if defined(_WIN64) || defined(_WIN32)
  GetModuleFileNameA(0, const_cast<LPSTR>(name.c_str()), MAX_PATH);
#elif defined(__linux__)
  readlink("/proc/self/exe", &name[0], MAX_PATH);
#endif
  name.resize(strlen(name.data()));

  return name;
}

namespace spaghetti {

struct Registry::PIMPL {
  using Plugins = std::vector<std::shared_ptr<SharedLibrary>>;
  using MetaInfos = std::vector<MetaInfo>;
  MetaInfos metaInfos{};
  Plugins plugins{};
};

Registry &Registry::get()
{
  static Registry s_registry{};
  return s_registry;
}

Registry::~Registry() = default;

Registry::Registry()
  : m_pimpl{ std::make_unique<PIMPL>() }
{
  log::init();

  log::info("Spaghetti version: {}, git: {}@{}, build date: {}, {}", version::STRING, version::BRANCH,
            version::COMMIT_SHORT_HASH, __DATE__, __TIME__);
}

void Registry::registerInternalElements()
{
  init_resources();

  using namespace elements;

  registerElement<Package>("Package", ":/logic/package.png");

  registerElement<gates::And>("AND (Bool)", ":/gates/and.png");
  registerElement<gates::Nand>("NAND (Bool)", ":/gates/nand.png");
  registerElement<gates::Nor>("NOR (Bool)", ":/gates/nor.png");
  registerElement<gates::Not>("NOT (Bool)", ":/gates/not.png");
  registerElement<gates::Or>("OR (Bool)", ":/gates/or.png");

  registerElement<logic::IfGreaterEqual>("If A >= B (Float)", ":/unknown.png");
  registerElement<logic::IfGreater>("If A > B (Float)", ":/unknown.png");
  registerElement<logic::IfEqual>("If A == B (Float)", ":/unknown.png");
  registerElement<logic::IfLower>("If A < B (Float)", ":/unknown.png");
  registerElement<logic::IfLowerEqual>("If A <= B (Float)", ":/unknown.png");

  registerElement<logic::MultiplexerInt>("Multiplexer (Int)", ":/unknown.png");
  registerElement<logic::DemultiplexerInt>("Demultiplexer (Int)", ":/unknown.png");

  registerElement<logic::Blinker, nodes::logic::Blinker>("Blinker (Bool)", ":/unknown.png");
  registerElement<logic::Clock, nodes::logic::Clock>("Clock (ms)", ":/logic/clock.png");
  registerElement<logic::Switch>("Switch (Int)", ":/logic/switch.png");

  registerElement<math::Abs>("Abs (Float)", ":/unknown.png");

  registerElement<math::Add>("Add (Float)", ":/unknown.png");
  registerElement<math::AddIf>("Add If (Float)", ":/unknown.png");
  registerElement<math::Subtract>("Subtract (Float)", ":/unknown.png");
  registerElement<math::SubtractIf>("Subtract If (Float)", ":/unknown.png");
  registerElement<math::Divide>("Divide (Float)", ":/unknown.png");
  registerElement<math::DivideIf>("Divide If (Float)", ":/unknown.png");
  registerElement<math::Multiply>("Multiply (Float)", ":/unknown.png");
  registerElement<math::MultiplyIf>("Multiply If (Float)", ":/unknown.png");

  registerElement<math::Cos>("Cos (Rad)", ":/unknown.png");
  registerElement<math::Sin>("Sin (Rad)", ":/unknown.png");

  registerElement<ui::FloatInfo, nodes::ui::FloatInfo>("Info (Float)", ":/values/const_float.png");
  registerElement<ui::IntInfo, nodes::ui::IntInfo>("Info (Int)", ":/values/const_int.png");

  registerElement<ui::PushButton, nodes::ui::PushButton>("Push Button (Bool)", ":/ui/push_button.png");
  registerElement<ui::ToggleButton, nodes::ui::ToggleButton>("Toggle Button (Bool)", ":/ui/toggle_button.png");

  registerElement<values::ConstBool, nodes::values::ConstBool>("Const value (Bool)", ":/values/const_bool.png");
  registerElement<values::ConstFloat, nodes::values::ConstFloat>("Const value (Float)", ":/values/const_float.png");
  registerElement<values::ConstInt, nodes::values::ConstInt>("Const value (Int)", ":/values/const_int.png");
  registerElement<values::RandomBool>("Random value (Bool)", ":/values/random_value.png");

  registerElement<values::Degree2Radian>("Convert angle (Deg2Rad)", ":/unknown.png");
  registerElement<values::Radian2Degree>("Convert angle (Rad2Deg)", ":/unknown.png");
  registerElement<values::Int2Float>("Convert value (Int2Float)", ":/unknown.png");
  registerElement<values::Float2Int>("Convert value (Float2Int)", ":/unknown.png");

  registerElement<values::MinInt>("Minimum value (Int)", ":/unknown.png");
  registerElement<values::MaxInt>("Maximum value (Int)", ":/unknown.png");
  registerElement<values::MinFloat>("Minimum value (Float)", ":/unknown.png");
  registerElement<values::MaxFloat>("Maximum value (Float)", ":/unknown.png");

  registerElement<values::ClampFloat>("Clamp value (Float)", ":/unknown.png");
  registerElement<values::ClampInt>("Clamp value (Int)", ":/unknown.png");
}

void Registry::loadPlugins()
{
  fs::path const APP_PATH{ fs::path{ get_application_path() }.parent_path() };
  fs::path const LIB_PATH{ fs::canonical(fs::path{ APP_PATH.string() + "/../lib" }) };
  fs::path const SYSTEM_PLUGINS_DIR{ LIB_PATH / "spaghetti" };
  fs::path const HOME_DIR{ getenv("HOME") };
  fs::path const USER_PLUGINS_DIR{ fs::absolute(HOME_DIR / ".config/spaghetti/plugins") };

  fs::create_directories(USER_PLUGINS_DIR);

  auto loadFrom = [this](fs::path const &a_path) {
    spaghetti::log::info("Loading plugins from {}", a_path.string());
    if (!fs::is_directory(a_path)) return;
    for (auto const &ENTRY : fs::directory_iterator(a_path)) {
      spaghetti::log::info("Loading {}..", ENTRY.path().string());
      if (!(fs::is_regular_file(ENTRY) || fs::is_symlink(ENTRY))) continue;

      std::error_code error{};
      auto plugin = std::make_shared<SharedLibrary>(ENTRY, error);

      if (error.value() != 0 || !plugin->has("register_plugin")) continue;

      auto registerPlugin = plugin->get<void(Registry &)>("register_plugin");
      registerPlugin(*this);

      m_pimpl->plugins.emplace_back(std::move(plugin));
    }
  };

  loadFrom(USER_PLUGINS_DIR);
  loadFrom(SYSTEM_PLUGINS_DIR);
}

Element *Registry::createElement(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  assert(META_INFO.cloneElement);
  return META_INFO.cloneElement();
}

Node *Registry::createNode(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  assert(META_INFO.cloneNode);
  return META_INFO.cloneNode();
}

std::string Registry::elementName(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  return META_INFO.name;
}

std::string Registry::elementIcon(string::hash_t const a_hash)
{
  auto const &META_INFO = metaInfoFor(a_hash);
  return META_INFO.icon;
}

void Registry::addElement(MetaInfo &a_metaInfo)
{
  auto &metaInfos = m_pimpl->metaInfos;
  metaInfos.push_back(std::move(a_metaInfo));
}

bool Registry::hasElement(string::hash_t const a_hash) const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  auto const IT = std::find_if(std::begin(META_INFOS), std::end(META_INFOS),
                               [a_hash](auto const &a_metaInfo) { return a_metaInfo.hash == a_hash; });
  return IT != std::end(META_INFOS);
}

size_t Registry::size() const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  return META_INFOS.size();
}

Registry::MetaInfo const &Registry::metaInfoFor(string::hash_t const a_hash) const
{
  auto &metaInfos = m_pimpl->metaInfos;
  assert(hasElement(a_hash));
  auto const IT = std::find_if(std::begin(metaInfos), std::end(metaInfos),
                               [a_hash](auto const &a_metaInfo) { return a_metaInfo.hash == a_hash; });
  return *IT;
}

Registry::MetaInfo const &Registry::metaInfoAt(size_t const a_index) const
{
  auto const &META_INFOS = m_pimpl->metaInfos;
  return META_INFOS[a_index];
}

} // namespace spaghetti
<|endoftext|>


<commit_before>/**
 * @file   CallableTcp.hpp
 * @brief  CallableTcp class prototype.
 * @author zer0
 * @date   2016-12-29
 * @date   2017-02-01 (Move package: libtbag/uv -> libtbag/uvpp)
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_UVPP_EX_CALLABLETCP_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_UVPP_EX_CALLABLETCP_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <libtbag/config.h>
#include <libtbag/predef.hpp>
#include <libtbag/uvpp/Loop.hpp>
#include <libtbag/uvpp/Tcp.hpp>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace uvpp {
namespace ex {

/**
 * CallableTcp class prototype.
 *
 * @author zer0
 * @date   2016-12-29
 */
class TBAG_API CallableTcp : public Tcp
{
public:
    // @formatter:off
    struct TBAG_API Callback
    {
        // Event of Tcp.
        virtual void onConnect(ConnectRequest & request, uerr code) { /* EMPTY. */ }

        // Event of Stream.
        virtual void onShutdown(ShutdownRequest & request, uerr code)         { /* EMPTY. */ }
        virtual void onConnection(uerr code)                                  { /* EMPTY. */ }
        virtual binf onAlloc(std::size_t suggested_size)                      { return binf(); }
        virtual void onRead(uerr code, char const * buffer, std::size_t size) { /* EMPTY. */ }
        virtual void onWrite(WriteRequest & request, uerr code)               { /* EMPTY. */ }

        // Event of Handle.
        virtual void onClose()          { /* EMPTY. */ }
        virtual void onWalk(void * arg) { /* EMPTY. */ }
    };
    // @formatter:on

private:
    Callback * _cb;

public:
    // @formatter:off
    CallableTcp() : Tcp(), _cb(nullptr)
    { /* EMPTY. */ }
    CallableTcp(Loop & l, Callback * c = nullptr) : Tcp(l), _cb(c)
    { /* EMPTY. */ }
    virtual ~CallableTcp()
    { /* EMPTY. */ }
    // @formatter:on

public:
    inline void setCallback(Callback * callback) TBAG_NOEXCEPT
    { _cb = callback; }

public:
    // @formatter:off
    virtual void onConnect(ConnectRequest & request, uerr code) override
    { if (_cb != nullptr) { _cb->onConnect(request, code); } }

    virtual void onShutdown(ShutdownRequest & request, uerr code) override
    { if (_cb != nullptr) { _cb->onShutdown(request, code); } }
    virtual void onConnection(uerr code) override
    { if (_cb != nullptr) { _cb->onConnection(code); } }
    virtual binf onAlloc(std::size_t suggested_size) override
    { if (_cb != nullptr) { return _cb->onAlloc(suggested_size); } return binf(); }
    virtual void onRead(uerr code, char const * buffer, std::size_t size) override
    { if (_cb != nullptr) { _cb->onRead(code, buffer, size); } }
    virtual void onWrite(WriteRequest & request, uerr code) override
    { if (_cb != nullptr) { _cb->onWrite(request, code); } }

    virtual void onClose() override
    { if (_cb != nullptr) { _cb->onClose(); } }
    virtual void onWalk(void * arg) override
    { if (_cb != nullptr) { _cb->onWalk(arg); } }
    // @formatter:on
};

} // namespace ex
} // namespace uvpp

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

#endif // __INCLUDE_LIBTBAG__LIBTBAG_UVPP_EX_CALLABLETCP_HPP__

<commit_msg>Remove unused header file.<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright 2011 Thomas Fidler
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <boost/lexical_cast.hpp>
#include <iostream>

#include "../Data.h"
#include "../Exception.h"
#include "../Node.h"
#include "../Operator.h"
#include "../Thread.h"
#include "XmlWriterImpl.h"

using namespace xercesc;

namespace stream
{
    namespace impl
    {
        XmlWriterImpl::XmlWriterImpl() : m_stream(0), m_impl(0), m_doc(0), m_strElement(0), m_filename("")
        {
            try
            {
                XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
            }
            catch (const XMLException& toCatch)
            {
                char* message = XMLString::transcode(toCatch.getMessage());
                std::cerr << "Error during initialization! :\n"
                    << message << "\n";
                XMLString::release(&message);
                return;
            }

            try
            {
                m_impl = DOMImplementationRegistry::getDOMImplementation(Str2Xml(""));
            }
            catch(DOMException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
            catch(XMLException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
        }

        const unsigned int XmlWriterImpl::translateOperatorPointerToID(const Operator* const op) const
        {
            unsigned int count_op = 0;
            for(std::vector<Operator*>::const_iterator iter_op = m_stream->operators().begin();
                    iter_op != m_stream->operators().end();
                    ++iter_op, ++count_op)
            {
                if ((*iter_op) == op)
                {
                    return count_op;
                }
            }

            throw InternalError("Operator does not exist.");
        }

        void XmlWriterImpl::createInputNodes(const Thread* const currThr, DOMElement* const thrElement)
        {
            //Add InputNode branches (tree structure: Stream:Thread:InputNode)
            //Processed for each InputNode belonging to Thread (multiple entries for each Thread possible)
            for(std::vector<Node>::const_iterator iter_inNodes = currThr->nodeSequence().begin();
                iter_inNodes != currThr->nodeSequence().end();
                ++iter_inNodes)
            {
                //Create current InputNode being child of Thread
                DOMElement* inNodeElement = m_doc->createElement(Str2Xml("InputNode"));
                thrElement->appendChild(inNodeElement);

                //Create attribute operator of current InputNode (one for each InputNode possible)
                DOMAttr* opAttr = m_doc->createAttribute(Str2Xml("operator"));
                unsigned int opId = translateOperatorPointerToID((*iter_inNodes).op());
                opAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(opId).c_str()));
                inNodeElement->setAttributeNode(opAttr);

                //Create attribute input of current InputNode (one for each InputNode possible)
                DOMAttr* inputAttr = m_doc->createAttribute(Str2Xml("input"));
                inputAttr->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_inNodes).id()).c_str()));
                inNodeElement->setAttributeNode(inputAttr);
            }
        }

        void XmlWriterImpl::createThreads(const std::vector<Thread*> threads)
        {
            //Add Thread branches (tree structure: Stream:Thread)
            //Processed for each thread belonging to the stream object (multiple entries for stream possible)
            for(std::vector<Thread*>::const_iterator iter_thr = threads.begin();
                    iter_thr != threads.end();
                    ++iter_thr)
            {
                //Create current Thread being child of Stream (one for each Thread possible)
                DOMElement* thrElement = m_doc->createElement(Str2Xml("Thread"));
                m_strElement->appendChild(thrElement);

                //Create attribute name of Thread (one for each Thread possible)
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml((*iter_thr)->name().c_str()));
                thrElement->setAttributeNode(nameAttr);

                //Create InputNodes of Thread (multiple entries for each Thread possible)
                createInputNodes((*iter_thr), thrElement);
            }
        }

        void XmlWriterImpl::createParameters(const Operator* const currOp, DOMElement* const opElement)
        {
            //Add parameter branches (tree structure: stream:operator:parameter)
            //Processed for each parameter belonging to current operator currOp (multiple entries for each operator possible)
            for(std::vector<const Parameter*>::const_iterator iter_par = currOp->info()->parameters().begin();
                        iter_par != currOp->info()->parameters().end();
                        ++iter_par)
            {
                //Create current parameter entry param being child of current operator op (one for each parameter possible)
                DOMElement* parElement = m_doc->createElement(Str2Xml("Parameter"));
                opElement->appendChild(parElement);

                //Create attribute id of current parameter param (one for each parameter possible)
                DOMAttr* id = m_doc->createAttribute(Str2Xml("id"));
                id->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_par)->id()).c_str()));
                parElement->setAttributeNode(id);

                createData(*iter_par, currOp, parElement);
            }
        }

        void XmlWriterImpl::createData(const Parameter*const currPar, const Operator*const currOp, DOMElement*const parElement)
        {
            //Add Data branch
            //Create Data entry data being child of current param (one for each parameter possible)
            DOMElement* dataElement = m_doc->createElement(Str2Xml("Data"));
            parElement->appendChild(dataElement);

            //Create attribute type of current parameter param (one for each parameter possible)
            DOMAttr* typeAttr = m_doc->createAttribute(Str2Xml("type"));
            typeAttr->setValue(Str2Xml(currOp->getParameter(currPar->id()).type().c_str()));
            dataElement->setAttributeNode(typeAttr);

            //Create attribute package of current parameter param (one for each parameter possible)
            DOMAttr* packageAttr = m_doc->createAttribute(Str2Xml("package"));
            packageAttr->setValue(Str2Xml(currOp->getParameter(currPar->id()).package().c_str()));
            dataElement->setAttributeNode(packageAttr);

            //Create value of current parameter param (one for each parameter possible)
            //First, create unique input parameter name for function Data::serialize()
            std::string str = m_stream->name() +
                                "_" + "op" + boost::lexical_cast<std::string>(translateOperatorPointerToID(currOp)) +
                                "_" + "parameter" + boost::lexical_cast<std::string>(currPar->id());
            DOMText* value = m_doc->createTextNode(Str2Xml(currOp->getParameter(currPar->id()).serialize(str, impl::XmlUtilities::computePath(m_filename)).c_str()));
            dataElement->appendChild(value);
        }

        void XmlWriterImpl::createInputs(const stream::Operator*const currOp, DOMElement*const opElement)
        {
            for(std::vector<const Description*>::const_iterator iter_in = currOp->info()->inputs().begin();
                iter_in != currOp->info()->inputs().end();
                ++iter_in)
            {
                //Get the source node
                Node node = m_stream->source(currOp, (*iter_in)->id());

                //Create Input only for connected operators
                if (! node.empty())
                {
                    //Create Input entry in being child of current operator op (one for each parameter possible)
                    DOMElement* inElement = m_doc->createElement(Str2Xml("Input"));
                    opElement->appendChild(inElement);

                    //Create attribute id of current input in (one for each input possible)
                    DOMAttr* idAttr = m_doc->createAttribute(Str2Xml("id"));
                    idAttr->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_in)->id()).c_str()));
                    inElement->setAttributeNode(idAttr);

                    //Get the id of the source operator
                    unsigned sourceOp = translateOperatorPointerToID(node.op());

                    //Write the id of the source operator
                    DOMAttr* opAttr = m_doc->createAttribute(Str2Xml("operator"));
                    opAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(sourceOp).c_str()));
                    inElement->setAttributeNode(opAttr);

                    //Write the id of the output
                    DOMAttr* outAttr = m_doc->createAttribute(Str2Xml("output"));
                    outAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(node.id()).c_str()));
                    inElement->setAttributeNode(outAttr);
                }
            }
        }

        void XmlWriterImpl::createOperators(const std::vector<Operator*> operators)
        {
            //Add operator branches (tree structure: stream:operator)
            //Processed for each operator belonging to the stream object (multiple entries for stream possible)
            for(std::vector<Operator*>::const_iterator iter_op = operators.begin();
                iter_op != operators.end();
                ++iter_op)
            {
                //Create current operator entry op being child of stream (one for each operator possible)
                DOMElement* opElement = m_doc->createElement(Str2Xml("Operator"));
                m_strElement->appendChild(opElement);

                //Create attribute id of current operator op (one for each operator possible)
                DOMAttr* idAttr = m_doc->createAttribute(Str2Xml("id"));
                idAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(translateOperatorPointerToID(*iter_op)).c_str()));
                opElement->setAttributeNode(idAttr);

                //Create attribute package of current operator op (one for each operator possible)
                DOMAttr* packAttr = m_doc->createAttribute(Str2Xml("package"));
                packAttr->setValue(Str2Xml((*iter_op)->info()->package().c_str()));
                opElement->setAttributeNode(packAttr);

                //Create attribute type of current operator op (one for each operator possible)
                DOMAttr* typeAttr = m_doc->createAttribute(Str2Xml("type"));
                typeAttr->setValue(Str2Xml((*iter_op)->info()->type().c_str()));
                opElement->setAttributeNode(typeAttr);

                //Create attribute name of current operator op (one for each operator possible)
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml((*iter_op)->name().c_str()));
                opElement->setAttributeNode(nameAttr);

                createParameters((*iter_op), opElement);
                createInputs((*iter_op), opElement);
            }
        }

        void XmlWriterImpl::write(const std::string& filename, Stream& stream)
        {
            if (filename.empty())
            {
                throw WrongArgument("Invalid file name.");
            }

            if (&stream == 0)
            {
                throw WrongArgument("Invalid argument: Null pointer.");
            }

            m_stream = &stream;
            m_filename = filename;

            try
            {
                //Create Stream branch
                m_doc = m_impl->createDocument(0, Str2Xml("Stream"), 0);
                m_strElement = m_doc->getDocumentElement();

                //Create attribute name of Stream
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml(m_stream->name().c_str()));
                m_strElement->setAttributeNode(nameAttr);

                //Create Operators of Stream (multiple entries for Stream possible)
                createOperators(m_stream->operators());
                //Create Threads of Stream (multiple entries for Stream possible)
                createThreads(m_stream->threads());

                DOMLSSerializer* serializer = m_impl->createLSSerializer();
                serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
                char* content = XMLString::transcode(serializer->writeToString(m_doc));
                std::cout << content << std::endl;
                XMLString::release(&content);
                serializer->release();

                // done with the document, must call release() to release the entire document resources
                m_doc->release();
            }
            catch(DOMException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
            catch(XMLException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }

            try
            {
                XMLPlatformUtils::Terminate();  // Terminate after release of memory
            }
            catch(XMLException&)
            {
            }
        }
    }
}
<commit_msg> XmlWriter minor changes<commit_after>/*
 *  Copyright 2011 Thomas Fidler
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <boost/lexical_cast.hpp>
#include <iostream>

#include "../Data.h"
#include "../Exception.h"
#include "../Node.h"
#include "../Operator.h"
#include "../Thread.h"
#include "XmlWriterImpl.h"

using namespace xercesc;

namespace stream
{
    namespace impl
    {
        XmlWriterImpl::XmlWriterImpl() : m_stream(0), m_impl(0), m_doc(0), m_strElement(0), m_filename("")
        {
            try
            {
                XMLPlatformUtils::Initialize();  // Initialize Xerces infrastructure
            }
            catch (const XMLException& toCatch)
            {
                char* message = XMLString::transcode(toCatch.getMessage());
                std::cerr << "Error during initialization! :\n"
                    << message << "\n";
                XMLString::release(&message);
                return;
            }

            try
            {
                m_impl = DOMImplementationRegistry::getDOMImplementation(Str2Xml(""));
            }
            catch(DOMException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
            catch(XMLException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
        }

        const unsigned int XmlWriterImpl::translateOperatorPointerToID(const Operator* const op) const
        {
            unsigned int count_op = 0;
            for(std::vector<Operator*>::const_iterator iter_op = m_stream->operators().begin();
                    iter_op != m_stream->operators().end();
                    ++iter_op, ++count_op)
            {
                if ((*iter_op) == op)
                {
                    return count_op;
                }
            }

            throw InternalError("Operator does not exist.");
        }

        void XmlWriterImpl::createInputNodes(const Thread* const currThr, DOMElement* const thrElement)
        {
            //Add InputNode branches (tree structure: Stream:Thread:InputNode)
            //Processed for each InputNode belonging to Thread (multiple entries for each Thread possible)
            for(std::vector<Node>::const_iterator iter_inNodes = currThr->nodeSequence().begin();
                iter_inNodes != currThr->nodeSequence().end();
                ++iter_inNodes)
            {
                //Create current InputNode being child of Thread
                DOMElement* inNodeElement = m_doc->createElement(Str2Xml("InputNode"));
                thrElement->appendChild(inNodeElement);

                //Create attribute operator of current InputNode (one for each InputNode possible)
                DOMAttr* opAttr = m_doc->createAttribute(Str2Xml("operator"));
                unsigned int opId = translateOperatorPointerToID((*iter_inNodes).op());
                opAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(opId).c_str()));
                inNodeElement->setAttributeNode(opAttr);

                //Create attribute input of current InputNode (one for each InputNode possible)
                DOMAttr* inputAttr = m_doc->createAttribute(Str2Xml("input"));
                inputAttr->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_inNodes).id()).c_str()));
                inNodeElement->setAttributeNode(inputAttr);
            }
        }

        void XmlWriterImpl::createThreads(const std::vector<Thread*> threads)
        {
            //Add Thread branches (tree structure: Stream:Thread)
            //Processed for each thread belonging to the stream object (multiple entries for stream possible)
            for(std::vector<Thread*>::const_iterator iter_thr = threads.begin();
                    iter_thr != threads.end();
                    ++iter_thr)
            {
                //Create current Thread being child of Stream (one for each Thread possible)
                DOMElement* thrElement = m_doc->createElement(Str2Xml("Thread"));
                m_strElement->appendChild(thrElement);

                //Create attribute name of Thread (one for each Thread possible)
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml((*iter_thr)->name().c_str()));
                thrElement->setAttributeNode(nameAttr);

                //Create InputNodes of Thread (multiple entries for each Thread possible)
                createInputNodes((*iter_thr), thrElement);
            }
        }

        void XmlWriterImpl::createParameters(const Operator* const currOp, DOMElement* const opElement)
        {
            //Add parameter branches (tree structure: stream:operator:parameter)
            //Processed for each parameter belonging to current operator currOp (multiple entries for each operator possible)
            for(std::vector<const Parameter*>::const_iterator iter_par = currOp->info()->parameters().begin();
                        iter_par != currOp->info()->parameters().end();
                        ++iter_par)
            {
                //Create current parameter entry param being child of current operator op (one for each parameter possible)
                DOMElement* parElement = m_doc->createElement(Str2Xml("Parameter"));
                opElement->appendChild(parElement);

                //Create attribute id of current parameter param (one for each parameter possible)
                DOMAttr* id = m_doc->createAttribute(Str2Xml("id"));
                id->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_par)->id()).c_str()));
                parElement->setAttributeNode(id);

                createData(*iter_par, currOp, parElement);
            }
        }

        void XmlWriterImpl::createData(const Parameter*const currPar, const Operator*const currOp, DOMElement*const parElement)
        {
            //Add Data branch
            //Create Data entry data being child of current param (one for each parameter possible)
            DOMElement* dataElement = m_doc->createElement(Str2Xml("Data"));
            parElement->appendChild(dataElement);

            //Create attribute type of current parameter param (one for each parameter possible)
            DOMAttr* typeAttr = m_doc->createAttribute(Str2Xml("type"));
            typeAttr->setValue(Str2Xml(currOp->getParameter(currPar->id()).type().c_str()));
            dataElement->setAttributeNode(typeAttr);

            //Create attribute package of current parameter param (one for each parameter possible)
            DOMAttr* packageAttr = m_doc->createAttribute(Str2Xml("package"));
            packageAttr->setValue(Str2Xml(currOp->getParameter(currPar->id()).package().c_str()));
            dataElement->setAttributeNode(packageAttr);

            //Create value of current parameter param (one for each parameter possible)
            //First, create unique input parameter name for function Data::serialize()
            std::string str = m_stream->name() +
                                "_" + "op" + boost::lexical_cast<std::string>(translateOperatorPointerToID(currOp)) +
                                "_" + "parameter" + boost::lexical_cast<std::string>(currPar->id());
            DOMText* value = m_doc->createTextNode(Str2Xml(currOp->getParameter(currPar->id()).serialize(str, impl::XmlUtilities::computePath(m_filename)).c_str()));
            dataElement->appendChild(value);
        }

        void XmlWriterImpl::createInputs(const stream::Operator*const currOp, DOMElement*const opElement)
        {
            for(std::vector<const Description*>::const_iterator iter_in = currOp->info()->inputs().begin();
                iter_in != currOp->info()->inputs().end();
                ++iter_in)
            {
                //Get the source node
                Node node = m_stream->source(currOp, (*iter_in)->id());

                //Create Input only for connected operators
                if (! node.empty())
                {
                    //Create Input entry in being child of current operator op (one for each parameter possible)
                    DOMElement* inElement = m_doc->createElement(Str2Xml("Input"));
                    opElement->appendChild(inElement);

                    //Create attribute id of current input in (one for each input possible)
                    DOMAttr* idAttr = m_doc->createAttribute(Str2Xml("id"));
                    idAttr->setValue(Str2Xml(boost::lexical_cast<std::string>((*iter_in)->id()).c_str()));
                    inElement->setAttributeNode(idAttr);

                    //Get the id of the source operator
                    unsigned sourceOp = translateOperatorPointerToID(node.op());

                    //Write the id of the source operator
                    DOMAttr* opAttr = m_doc->createAttribute(Str2Xml("operator"));
                    opAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(sourceOp).c_str()));
                    inElement->setAttributeNode(opAttr);

                    //Write the id of the output
                    DOMAttr* outAttr = m_doc->createAttribute(Str2Xml("output"));
                    outAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(node.id()).c_str()));
                    inElement->setAttributeNode(outAttr);
                }
            }
        }

        void XmlWriterImpl::createOperators(const std::vector<Operator*> operators)
        {
            //Add operator branches (tree structure: stream:operator)
            //Processed for each operator belonging to the stream object (multiple entries for stream possible)
            for(std::vector<Operator*>::const_iterator iter_op = operators.begin();
                iter_op != operators.end();
                ++iter_op)
            {
                //Create current operator entry op being child of stream (one for each operator possible)
                DOMElement* opElement = m_doc->createElement(Str2Xml("Operator"));
                m_strElement->appendChild(opElement);

                //Create attribute id of current operator op (one for each operator possible)
                DOMAttr* idAttr = m_doc->createAttribute(Str2Xml("id"));
                idAttr->setValue(Str2Xml(boost::lexical_cast<std::string>(translateOperatorPointerToID(*iter_op)).c_str()));
                opElement->setAttributeNode(idAttr);

                //Create attribute package of current operator op (one for each operator possible)
                DOMAttr* packAttr = m_doc->createAttribute(Str2Xml("package"));
                packAttr->setValue(Str2Xml((*iter_op)->info()->package().c_str()));
                opElement->setAttributeNode(packAttr);

                //Create attribute type of current operator op (one for each operator possible)
                DOMAttr* typeAttr = m_doc->createAttribute(Str2Xml("type"));
                typeAttr->setValue(Str2Xml((*iter_op)->info()->type().c_str()));
                opElement->setAttributeNode(typeAttr);

                //Create attribute name of current operator op (one for each operator possible)
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml((*iter_op)->name().c_str()));
                opElement->setAttributeNode(nameAttr);

                createParameters((*iter_op), opElement);
                createInputs((*iter_op), opElement);
            }
        }

        void XmlWriterImpl::write(const std::string& filename, Stream& stream)
        {
            if (filename.empty())
            {
                throw WrongArgument("Invalid file name.");
            }

            m_stream = &stream;
            m_filename = filename;

            try
            {
                //Create Stream branch
                m_doc = m_impl->createDocument(0, Str2Xml("Stream"), 0);
                m_strElement = m_doc->getDocumentElement();

                //Create attribute name of Stream
                DOMAttr* nameAttr = m_doc->createAttribute(Str2Xml("name"));
                nameAttr->setValue(Str2Xml(m_stream->name().c_str()));
                m_strElement->setAttributeNode(nameAttr);

                //Create Operators of Stream (multiple entries for Stream possible)
                createOperators(m_stream->operators());
                //Create Threads of Stream (multiple entries for Stream possible)
                createThreads(m_stream->threads());

                DOMLSSerializer* serializer = m_impl->createLSSerializer();
                serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
                char* content = XMLString::transcode(serializer->writeToString(m_doc));
                std::cout << content << std::endl;
                XMLString::release(&content);
                serializer->release();

                // done with the document, must call release() to release the entire document resources
                m_doc->release();
            }
            catch(DOMException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }
            catch(XMLException& e)
            {
                throw InternalError("Error in Xerces-C.");
            }

            try
            {
                XMLPlatformUtils::Terminate();  // Terminate after release of memory
            }
            catch(XMLException&)
            {
            }
        }
    }
}
<|endoftext|>


<commit_before>#include <unistd.h> // ::close

#include "event_loop.h"
#include "inet_addr.h"
#include "socket.h"
#include "connector.h"
#include "tcp_connection.h"

namespace cube {

namespace net {

int Connector::Connect(const InetAddr &server_addr, int &sockfd) {
    sockfd = sockets::CreateNonBlockStreamSocket();
    if (sockfd < 0) {
        return CUBE_ERR;
    }

    if (::connect(sockfd, server_addr.SockAddr(), sizeof(*server_addr.SockAddr()))) {
        if (errno == EINPROGRESS) {
            // it is ok.
        } else {
            // error
            ::close(sockfd);
            return CUBE_ERR;
        }
    }

    return CUBE_OK;
}

std::shared_ptr<TcpConnection> Connector::Connect(EventLoop *event_loop, const InetAddr &server_addr) {
    int sockfd;
    int ret = Connect(server_addr, sockfd);
    if (ret != CUBE_OK) {
        return NULL;
    }

    auto conn = std::make_shared<TcpConnection>(
            event_loop, sockfd,
            sockets::GetLocalAddr(sockfd),
            sockets::GetPeerAddr(sockfd));

    conn->m_state = TcpConnection::ConnState_Connecting;
    return conn;
}

}

}
<commit_msg>update connector (#8)<commit_after>#include <unistd.h> // ::close

#include "event_loop.h"
#include "inet_addr.h"
#include "socket.h"
#include "connector.h"
#include "tcp_connection.h"

namespace cube {

namespace net {

int Connector::Connect(const InetAddr &server_addr, int &sockfd) {
    sockfd = sockets::CreateNonBlockStreamSocket();
    if (sockfd < 0) {
        return CUBE_ERR;
    }

    if (::connect(sockfd, server_addr.SockAddr(), sizeof(*server_addr.SockAddr()))) {
        if (errno == EINPROGRESS) {
            // it is ok.
        } else {
            // error
            ::close(sockfd);
            return CUBE_ERR;
        }
    }

    return CUBE_OK;
}

std::shared_ptr<TcpConnection> Connector::Connect(EventLoop *event_loop, const InetAddr &server_addr) {
    int sockfd;
    int ret = Connect(server_addr, sockfd);
    if (ret != CUBE_OK) {
        return std::shared_ptr<TcpConnection>();
    }

    auto conn = std::make_shared<TcpConnection>(
            event_loop, sockfd,
            sockets::GetLocalAddr(sockfd),
            sockets::GetPeerAddr(sockfd));

    conn->m_state = TcpConnection::ConnState_Connecting;
    return conn;
}

}

}
<|endoftext|>


<commit_before>#include <netlib/channel.h>

#include <sys/epoll.h> // EPOLL*

#include <netlib/event_loop.h> // EventLoop
#include <netlib/logging.h> // Log

using std::string;
using std::shared_ptr;
using netlib::EventLoop;
using netlib::Channel;

// EPOLLIN
// fd is available for read(2): data other than high-priority data can be read.
// EPOLLPRI
// There is urgent data available for read(2): high-priority data can be read.
// EPOLLRDHUP
// Stream socket peer closes connection, or shut down writing half of connection.
// This flag is useful to detect peer shutdown when using Edge Triggered.
// EPOLLOUT
// fd is available for write(2): normal data can be read.
// EPOLLHUP
// Hang up happened on the fd. epoll_wait(2) always wait for this event;
// it is not necessary to set it in events.
// EPOLLERR
// Error condition happened on the fd. epoll_wait(2) always wait for this event,
// it is not necessary to set it in events.
// EPOLLET
// Set the Edge Triggered behavior for fd. Default is Level Triggered.
// EPOLLONESHOT
// Set the one-shot behavior for the fd(Disable monitoring after event notification).
// After an event is pulled out with epoll_wait(2), the associated fd is disabled and
// no other events will be reported by the epoll interface. The user must call epoll_ctl()
// with EPOLL_CTL_MOD to rearm the fd with a new event mask.
const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI | EPOLLRDHUP;
const int Channel::kWriteEvent = EPOLLOUT;
const int Channel::kCloseEvent = EPOLLHUP;
const int Channel::kErrorEvent = EPOLLERR;

// declaration of ‘fd’ shadows a member of 'this' [-Werror=shadow]
Channel::Channel(EventLoop *loop, int file_descriptor):
	owner_loop_(loop),
	fd_(file_descriptor),
	requested_event_(kNoneEvent),
	returned_event_(kNoneEvent),
	state_in_epoller_(-1), // Epoller::kRaw.
	tied_(false)
{}

Channel::~Channel()
{
	if(owner_loop_->IsInLoopThread() == true)
	{
		assert(owner_loop_->HasChannel(this) == false);
	}
}

void Channel::set_requested_event(RequestedEventType type)
{
	switch(type)
	{
	case READ_EVENT:
		requested_event_ |= kReadEvent;
		break;
	case NOT_READ:
		requested_event_ &= ~kReadEvent;
		break;
	case WRITE_EVENT:
		requested_event_ |= kWriteEvent;
		break;
	case NOT_WRITE:
		requested_event_ &= ~kWriteEvent;
		break;
	case NONE_EVENT:
		requested_event_ = kNoneEvent;
		break;
	default:
		LOG_FATAL("Unknown RequestedEventType");
	}
	AddOrUpdateChannel();
}
void Channel::AddOrUpdateChannel()
{
	owner_loop_->AddOrUpdateChannel(this);
	// Invoke `void Epoller::AddOrUpdateChannel(Channel*)`
}

void Channel::set_tie(const shared_ptr<void> &object)
{
	tie_ = object;
	tied_ = true;
}
void Channel::set_event_callback(EventCallbackType type, const EventCallback &callback)
{
	switch(type)
	{
	case READ_CALLBACK:
		read_callback_ = callback;
		break;
	case WRITE_CALLBACK:
		write_callback_ = callback;
		break;
	case CLOSE_CALLBACK:
		close_callback_ = callback;
		break;
	case ERROR_CALLBACK:
		error_callback_ = callback;
		break;
	default:
		LOG_FATAL("Unknown EventCallbackType!");
	}
}

bool Channel::IsRequestedArgumentEvent(RequestedEventType type)
{
	switch(type)
	{
	case READ_EVENT:
		return requested_event_ & kReadEvent;
	case WRITE_EVENT:
		return requested_event_ & kWriteEvent;
	case NONE_EVENT:
		return requested_event_ == kNoneEvent;
	default:
		LOG_FATAL("Unknown RequestedEventType");
		return true;
	}
}

void Channel::HandleEvent(TimeStamp receive_time)
{
	if(tied_ == true)
	{
		shared_ptr<void> guard = tie_.lock(); // NOTE: Not `shared_ptr<void> &`
		if(guard)
		{
			HandleEventWithGuard(receive_time);
		}
	}
	else
	{
		HandleEventWithGuard(receive_time);
	}
}
// Call different callbacks based on the value of returned_event_.
// Invoked by EventLoop::Loop().
void Channel::HandleEventWithGuard(TimeStamp receive_time)
{
	LOG_TRACE("%s", ReturnedEventToString().c_str());

	if((returned_event_ & kReadEvent) && read_callback_)
	{
		read_callback_(receive_time);
	}
	if((returned_event_ & kWriteEvent) && write_callback_)
	{
		write_callback_(receive_time);
	}
	if((returned_event_ & kCloseEvent) &&
	        !(returned_event_ & EPOLLIN) &&
	        close_callback_)
	{
		close_callback_(receive_time);
	}
	if((returned_event_ & kErrorEvent ) && error_callback_)
	{
		error_callback_(receive_time);
	}
}

void Channel::RemoveChannel()
{
	assert(IsRequestedArgumentEvent(NONE_EVENT) == true);
	owner_loop_->RemoveChannel(this);
}

string Channel::RequestedEventToString() const
{
	return EventToString(fd_, requested_event_);
}
string Channel::ReturnedEventToString() const
{
	return EventToString(fd_, returned_event_);
}
string Channel::EventToString(int fd, int event)
{
	char buffer[32] = "";
	char *ptr = buffer, *buffer_end = buffer + sizeof buffer;
	ptr += snprintf(ptr, buffer_end - ptr, "%d: ", fd);
	if(event & EPOLLIN)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "IN ");
	}
	if(event & EPOLLPRI)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "PRI ");
	}
	if(event & EPOLLRDHUP)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "RDHUP ");
	}
	if(event & EPOLLOUT)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "OUT ");
	}
	if(event & EPOLLHUP)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "HUP ");
	}
	if(event & EPOLLERR)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "ERR ");
	}
	return buffer;
}
<commit_msg>feat: add event_handling to help control the life of Channel<commit_after>#include <netlib/channel.h>

#include <sys/epoll.h> // EPOLL*

#include <netlib/event_loop.h> // EventLoop
#include <netlib/logging.h> // Log

using std::string;
using std::shared_ptr;
using netlib::EventLoop;
using netlib::Channel;

// EPOLLIN
// fd is available for read(2): data other than high-priority data can be read.
// EPOLLPRI
// There is urgent data available for read(2): high-priority data can be read.
// EPOLLRDHUP
// Stream socket peer closes connection, or shut down writing half of connection.
// This flag is useful to detect peer shutdown when using Edge Triggered.
// EPOLLOUT
// fd is available for write(2): normal data can be read.
// EPOLLHUP
// Hang up happened on the fd. epoll_wait(2) always wait for this event;
// it is not necessary to set it in events.
// EPOLLERR
// Error condition happened on the fd. epoll_wait(2) always wait for this event,
// it is not necessary to set it in events.
// EPOLLET
// Set the Edge Triggered behavior for fd. Default is Level Triggered.
// EPOLLONESHOT
// Set the one-shot behavior for the fd(Disable monitoring after event notification).
// After an event is pulled out with epoll_wait(2), the associated fd is disabled and
// no other events will be reported by the epoll interface. The user must call epoll_ctl()
// with EPOLL_CTL_MOD to rearm the fd with a new event mask.
const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI | EPOLLRDHUP;
const int Channel::kWriteEvent = EPOLLOUT;
const int Channel::kCloseEvent = EPOLLHUP;
const int Channel::kErrorEvent = EPOLLERR;

// declaration of ‘fd’ shadows a member of 'this' [-Werror=shadow]
Channel::Channel(EventLoop *loop, int file_descriptor):
	owner_loop_(loop),
	fd_(file_descriptor),
	requested_event_(kNoneEvent),
	returned_event_(kNoneEvent),
	state_in_epoller_(-1), // Epoller::kRaw.
	tied_(false),
	event_handling_(false)
{}

Channel::~Channel()
{
	// Assert that this channel object won't destruct in the process of event handling.
	assert(event_handling_ == false);
	if(owner_loop_->IsInLoopThread() == true)
	{
		assert(owner_loop_->HasChannel(this) == false);
	}
}

void Channel::set_requested_event(RequestedEventType type)
{
	switch(type)
	{
	case READ_EVENT:
		requested_event_ |= kReadEvent;
		break;
	case NOT_READ:
		requested_event_ &= ~kReadEvent;
		break;
	case WRITE_EVENT:
		requested_event_ |= kWriteEvent;
		break;
	case NOT_WRITE:
		requested_event_ &= ~kWriteEvent;
		break;
	case NONE_EVENT:
		requested_event_ = kNoneEvent;
		break;
	default:
		LOG_FATAL("Unknown RequestedEventType");
	}
	AddOrUpdateChannel();
}
void Channel::AddOrUpdateChannel()
{
	owner_loop_->AddOrUpdateChannel(this);
	// Invoke `void Epoller::AddOrUpdateChannel(Channel*)`
}

void Channel::set_tie(const shared_ptr<void> &object)
{
	tie_ = object;
	tied_ = true;
}
void Channel::set_event_callback(EventCallbackType type, const EventCallback &callback)
{
	switch(type)
	{
	case READ_CALLBACK:
		read_callback_ = callback;
		break;
	case WRITE_CALLBACK:
		write_callback_ = callback;
		break;
	case CLOSE_CALLBACK:
		close_callback_ = callback;
		break;
	case ERROR_CALLBACK:
		error_callback_ = callback;
		break;
	default:
		LOG_FATAL("Unknown EventCallbackType!");
	}
}

bool Channel::IsRequestedArgumentEvent(RequestedEventType type)
{
	switch(type)
	{
	case READ_EVENT:
		return requested_event_ & kReadEvent;
	case WRITE_EVENT:
		return requested_event_ & kWriteEvent;
	case NONE_EVENT:
		return requested_event_ == kNoneEvent;
	default:
		LOG_FATAL("Unknown RequestedEventType");
		return true;
	}
}

void Channel::HandleEvent(TimeStamp receive_time)
{
	if(tied_ == true)
	{
		shared_ptr<void> guard = tie_.lock(); // NOTE: Not `shared_ptr<void> &`
		if(guard)
		{
			HandleEventWithGuard(receive_time);
		}
	}
	else
	{
		HandleEventWithGuard(receive_time);
	}
}
// Call different callbacks based on the value of returned_event_.
// Invoked by EventLoop::Loop().
void Channel::HandleEventWithGuard(TimeStamp receive_time)
{
	event_handling_ = true;
	LOG_TRACE("%s", ReturnedEventToString().c_str());

	if((returned_event_ & kReadEvent) && read_callback_)
	{
		read_callback_(receive_time);
	}
	if((returned_event_ & kWriteEvent) && write_callback_)
	{
		write_callback_(receive_time);
	}
	if((returned_event_ & kCloseEvent) &&
	        !(returned_event_ & EPOLLIN) &&
	        close_callback_)
	{
		close_callback_(receive_time);
	}
	if((returned_event_ & kErrorEvent ) && error_callback_)
	{
		error_callback_(receive_time);
	}
	event_handling_ = false;
}

void Channel::RemoveChannel()
{
	assert(IsRequestedArgumentEvent(NONE_EVENT) == true);
	owner_loop_->RemoveChannel(this);
}

string Channel::RequestedEventToString() const
{
	return EventToString(fd_, requested_event_);
}
string Channel::ReturnedEventToString() const
{
	return EventToString(fd_, returned_event_);
}
string Channel::EventToString(int fd, int event)
{
	char buffer[32] = "";
	char *ptr = buffer, *buffer_end = buffer + sizeof buffer;
	ptr += snprintf(ptr, buffer_end - ptr, "%d: ", fd);
	if(event & EPOLLIN)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "IN ");
	}
	if(event & EPOLLPRI)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "PRI ");
	}
	if(event & EPOLLRDHUP)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "RDHUP ");
	}
	if(event & EPOLLOUT)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "OUT ");
	}
	if(event & EPOLLHUP)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "HUP ");
	}
	if(event & EPOLLERR)
	{
		ptr += snprintf(ptr, buffer_end - ptr, "%s", "ERR ");
	}
	return buffer;
}
<|endoftext|>


<commit_before><commit_msg>Refine MSE and sample increment calculations.<commit_after><|endoftext|>


<commit_before>//
// Created by Edd on 04/11/2017.
//

#include <leveldb/db.h>
#include <leveldb/filter_policy.h>
#include <unordered_set>
#include <stor/document/document.h>
#include "leveldb_driver.h"
#include "utils.h"

namespace esft {
    namespace stor {
        namespace bmark {

#pragma GCC push_options
#pragma GCC optimize ("O0")

            leveldb_driver::leveldb_driver(std::size_t key_size, std::size_t value_size, std::size_t ops):
            _home{"_leveldb_benchmark"}, _key_size{key_size}, _value_size{value_size}, _ops{ops}
            {
                mkdir(_home);
            }

            leveldb_driver::~leveldb_driver() {
                rmdir(_home);
            }

            std::unordered_map<std::string, double> leveldb_driver::writes() const {
                std::string db_name = _home + "/bmark_db";

                leveldb::Options opt;
                opt.create_if_missing = true;
                opt.filter_policy = leveldb::NewBloomFilterPolicy(10);

                leveldb::DB *db;

                try{
                    leveldb::Status conn = leveldb::DB::Open(opt, db_name,&db);

                    if (!conn.ok()){
                        throw std::runtime_error{"Failed opening LevelDB"};
                    }

                    value_generator kg1(_key_size);
                    value_generator vg1(_value_size - 7 - 1);

                    leveldb::WriteOptions wo;
                    wo.sync = false;
                    auto runner = [this, db, &wo, &kg1, &vg1]() {
                        std::size_t some_value_to_prevent_optimizaton = 0;
                        for (std::size_t i = 0; i < _ops; ++i){
                            std::string id = kg1();
                            std::string jsn = json_generator(vg1);
                            document doc(jsn, id);
                            some_value_to_prevent_optimizaton += doc.id().size();
                            auto s = db->Put(wo,id, jsn);
                            some_value_to_prevent_optimizaton += (std::size_t) &s;
                        }
                        return some_value_to_prevent_optimizaton;
                    };

                    auto elapsed = timer<std::chrono::microseconds>{}(runner);

                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);

                    return result(elapsed,_ops,_key_size+_value_size);
                }catch (...){
                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);
                    throw;
                }
            }

            std::unordered_map<std::string, double> leveldb_driver::reads_by_key() const {
                std::string db_name = _home + "/bmark_db";

                leveldb::Options opt;
                opt.create_if_missing = true;
                opt.filter_policy = leveldb::NewBloomFilterPolicy(10);

                leveldb::DB *db;

                try{
                    leveldb::Status conn = leveldb::DB::Open(opt, db_name,&db);

                    if (!conn.ok()){
                        throw std::runtime_error{"Failed opening LevelDB"};
                    }

                    //fill
                    {
                        value_generator kg1(_key_size);
                        value_generator vg1(_value_size);

                        leveldb::WriteOptions wo;
                        wo.sync = false;
                        for (std::size_t i = 0; i < _ops; ++i){
                            auto s = db->Put(wo,kg1(),json_generator(vg1));
                        }
                    }

                    value_generator kg1(_key_size);
                    value_generator vg1(_value_size);

                    leveldb::ReadOptions ro;
                    ro.snapshot = db->GetSnapshot();
                    auto runner = [this, db, &ro, &kg1, &vg1]() {
                        std::size_t some_value_to_prevent_optimizaton = 0;
                        for (std::size_t i = 0; i < _ops; ++i){
                            std::string json;
                            std::string id = kg1();
                            db->Get(ro,id, &json);
                            std::unordered_set<document> docs;
                            auto p = docs.emplace(json,id);
                            some_value_to_prevent_optimizaton += (std::size_t) &p.first;
                        }
                        db->ReleaseSnapshot(ro.snapshot);
                        return some_value_to_prevent_optimizaton;
                    };

                    auto elapsed = timer<std::chrono::microseconds>{}(runner);

                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);

                    return result(elapsed,_ops,_key_size+_value_size);
                }catch (...){
                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);
                    throw;
                }
            }

#pragma GCC pop_options
        }
    }
}<commit_msg>fixed leveldb read key benchmark<commit_after>//
// Created by Edd on 04/11/2017.
//

#include <leveldb/db.h>
#include <leveldb/filter_policy.h>
#include <unordered_set>
#include <stor/document/document.h>
#include "leveldb_driver.h"
#include "utils.h"

namespace esft {
    namespace stor {
        namespace bmark {

#pragma GCC push_options
#pragma GCC optimize ("O0")

            leveldb_driver::leveldb_driver(std::size_t key_size, std::size_t value_size, std::size_t ops):
            _home{"_leveldb_benchmark"}, _key_size{key_size}, _value_size{value_size}, _ops{ops}
            {
                mkdir(_home);
            }

            leveldb_driver::~leveldb_driver() {
                rmdir(_home);
            }

            std::unordered_map<std::string, double> leveldb_driver::writes() const {
                std::string db_name = _home + "/bmark_db";

                leveldb::Options opt;
                opt.create_if_missing = true;
                opt.filter_policy = leveldb::NewBloomFilterPolicy(10);

                leveldb::DB *db;

                try{
                    leveldb::Status conn = leveldb::DB::Open(opt, db_name,&db);

                    if (!conn.ok()){
                        throw std::runtime_error{"Failed opening LevelDB"};
                    }

                    value_generator kg1(_key_size);
                    value_generator vg1(_value_size - 7 - 1);

                    leveldb::WriteOptions wo;
                    wo.sync = false;
                    auto runner = [this, db, &wo, &kg1, &vg1]() {
                        std::size_t some_value_to_prevent_optimizaton = 0;
                        for (std::size_t i = 0; i < _ops; ++i){
                            std::string id = kg1();
                            std::string jsn = json_generator(vg1);
                            document doc(jsn, id);
                            some_value_to_prevent_optimizaton += doc.id().size();
                            auto s = db->Put(wo,id, jsn);
                            some_value_to_prevent_optimizaton += (std::size_t) &s;
                        }
                        return some_value_to_prevent_optimizaton;
                    };

                    auto elapsed = timer<std::chrono::microseconds>{}(runner);

                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);

                    return result(elapsed,_ops,_key_size+_value_size);
                }catch (...){
                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);
                    throw;
                }
            }

            std::unordered_map<std::string, double> leveldb_driver::reads_by_key() const {
                std::string db_name = _home + "/bmark_db";

                leveldb::Options opt;
                opt.create_if_missing = true;
                opt.filter_policy = leveldb::NewBloomFilterPolicy(10);

                leveldb::DB *db;

                try{
                    leveldb::Status conn = leveldb::DB::Open(opt, db_name,&db);

                    if (!conn.ok()){
                        throw std::runtime_error{"Failed opening LevelDB"};
                    }

                    //fill
                    {
                        value_generator kg1(_key_size);
                        value_generator vg1(_value_size);

                        leveldb::WriteOptions wo;
                        wo.sync = false;
                        for (std::size_t i = 0; i < _ops; ++i){
                            auto s = db->Put(wo,kg1(),json_generator(vg1));
                        }
                    }

                    value_generator kg1(_key_size);
                    value_generator vg1(_value_size);

                    auto runner = [this, db, &kg1, &vg1]() {
                        std::size_t some_value_to_prevent_optimizaton = 0;
                        for (std::size_t i = 0; i < _ops; ++i){

                            leveldb::ReadOptions ro;
                            ro.snapshot = db->GetSnapshot();

                            std::string json;
                            std::string id = kg1();
                            db->Get(leveldb::ReadOptions{}, id, &json);

                            db->ReleaseSnapshot(ro.snapshot);

                            auto p = document(json,id);
                            some_value_to_prevent_optimizaton += p.id().size();
                        }
                        return some_value_to_prevent_optimizaton;
                    };

                    auto elapsed = timer<std::chrono::microseconds>{}(runner);

                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);

                    return result(elapsed,_ops,_key_size+_value_size);
                }catch (...){
                    delete db;
                    delete opt.filter_policy;
                    leveldb::DestroyDB(db_name, opt);
                    rmdir(db_name);
                    throw;
                }
            }

#pragma GCC pop_options
        }
    }
}<|endoftext|>


<commit_before>//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 1/11/06.
//
//===----------------------------------------------------------------------===//

#include "DNBDataRef.h"
#include "DNBLog.h"
#include <assert.h>
#include <ctype.h>
#include <libkern/OSByteOrder.h>

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------

DNBDataRef::DNBDataRef()
    : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0),
      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
      m_addrDATA(INVALID_NUB_ADDRESS) {}

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------

DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap)
    : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0),
      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
      m_addrDATA(INVALID_NUB_ADDRESS) {}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------

DNBDataRef::~DNBDataRef() {}

//----------------------------------------------------------------------
// Get8
//----------------------------------------------------------------------
uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {
  uint8_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    val = *(m_start + *offset_ptr);
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get16
//----------------------------------------------------------------------
uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {
  uint16_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    val = *(uint16_t *)p;

    if (m_swap)
      val = OSSwapInt16(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get32
//----------------------------------------------------------------------
uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {
  uint32_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    val = *(uint32_t *)p;
    if (m_swap)
      val = OSSwapInt32(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get64
//----------------------------------------------------------------------
uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {
  uint64_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    val = *(uint64_t *)p;
    if (m_swap)
      val = OSSwapInt64(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// GetMax32
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {
  switch (byte_size) {
  case 1:
    return Get8(offset_ptr);
    break;
  case 2:
    return Get16(offset_ptr);
    break;
  case 4:
    return Get32(offset_ptr);
    break;
  default:
    assert(!"GetMax32 unhandled case!");
    break;
  }
  return 0;
}

//----------------------------------------------------------------------
// GetMax64
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {
  switch (size) {
  case 1:
    return Get8(offset_ptr);
    break;
  case 2:
    return Get16(offset_ptr);
    break;
  case 4:
    return Get32(offset_ptr);
    break;
  case 8:
    return Get64(offset_ptr);
    break;
  default:
    assert(!"GetMax64 unhandled case!");
    break;
  }
  return 0;
}

//----------------------------------------------------------------------
// GetPointer
//
// Extract a pointer value from the buffer. The pointer size must be
// set prior to using this using one of the SetPointerSize functions.
//----------------------------------------------------------------------
uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const {
  // Must set pointer size prior to using this call
  assert(m_ptrSize != 0);
  return GetMax64(offset_ptr, m_ptrSize);
}
//----------------------------------------------------------------------
// GetCStr
//----------------------------------------------------------------------
const char *DNBDataRef::GetCStr(offset_t *offset_ptr,
                                uint32_t fixed_length) const {
  const char *s = NULL;
  if (m_start < m_end) {
    s = (char *)m_start + *offset_ptr;

    // Advance the offset
    if (fixed_length)
      *offset_ptr += fixed_length;
    else
      *offset_ptr += strlen(s) + 1;
  }
  return s;
}

//----------------------------------------------------------------------
// GetData
//----------------------------------------------------------------------
const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr,
                                   uint32_t length) const {
  const uint8_t *data = NULL;
  if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) {
    data = m_start + *offset_ptr;
    *offset_ptr += length;
  }
  return data;
}

//----------------------------------------------------------------------
// Get_ULEB128
//----------------------------------------------------------------------
uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {
  uint64_t result = 0;
  if (m_start < m_end) {
    int shift = 0;
    const uint8_t *src = m_start + *offset_ptr;
    uint8_t byte;
    int bytecount = 0;

    while (src < m_end) {
      bytecount++;
      byte = *src++;
      result |= (uint64_t)(byte & 0x7f) << shift;
      shift += 7;
      if ((byte & 0x80) == 0)
        break;
    }

    *offset_ptr += bytecount;
  }
  return result;
}

//----------------------------------------------------------------------
// Get_SLEB128
//----------------------------------------------------------------------
int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {
  int64_t result = 0;

  if (m_start < m_end) {
    int shift = 0;
    int size = sizeof(uint32_t) * 8;
    const uint8_t *src = m_start + *offset_ptr;

    uint8_t byte = 0;
    int bytecount = 0;

    while (src < m_end) {
      bytecount++;
      byte = *src++;
      result |= (int64_t)(byte & 0x7f) << shift;
      shift += 7;
      if ((byte & 0x80) == 0)
        break;
    }

    // Sign bit of byte is 2nd high order bit (0x40)
    if (shift < size && (byte & 0x40))
      result |= -(1ll << shift);

    *offset_ptr += bytecount;
  }
  return result;
}

//----------------------------------------------------------------------
// Skip_LEB128
//
// Skips past ULEB128 and SLEB128 numbers (just updates the offset)
//----------------------------------------------------------------------
void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const {
  if (m_start < m_end) {
    const uint8_t *start = m_start + *offset_ptr;
    const uint8_t *src = start;

    while ((src < m_end) && (*src++ & 0x80))
      /* Do nothing */;

    *offset_ptr += src - start;
  }
}

uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,
                          uint64_t offsetBase, DNBDataRef::Type type,
                          uint32_t numPerLine, const char *format) {
  uint32_t offset;
  uint32_t count;
  char str[1024];
  str[0] = '\0';
  size_t str_offset = 0;

  for (offset = startOffset, count = 0;
       ValidOffset(offset) && offset < endOffset; ++count) {
    if ((count % numPerLine) == 0) {
      // Print out any previous string
      if (str[0] != '\0')
        DNBLog("%s", str);
      // Reset string offset and fill the current line string with address:
      str_offset = 0;
      str_offset += snprintf(str, sizeof(str), "0x%8.8llx:",
                             (uint64_t)(offsetBase + (offset - startOffset)));
    }

    // Make sure we don't pass the bounds of our current string buffer on each
    // iteration through this loop
    if (str_offset >= sizeof(str)) {
      // The last snprintf consumed our string buffer, we will need to dump this
      // out
      // and reset the string with no address
      DNBLog("%s", str);
      str_offset = 0;
      str[0] = '\0';
    }

    // We already checked that there is at least some room in the string str
    // above, so it is safe to make
    // the snprintf call each time through this loop
    switch (type) {
    case TypeUInt8:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %2.2x", Get8(&offset));
      break;
    case TypeChar: {
      char ch = Get8(&offset);
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %c", isprint(ch) ? ch : ' ');
    } break;
    case TypeUInt16:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %4.4x", Get16(&offset));
      break;
    case TypeUInt32:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %8.8x", Get32(&offset));
      break;
    case TypeUInt64:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %16.16llx", Get64(&offset));
      break;
    case TypePointer:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " 0x%llx", GetPointer(&offset));
      break;
    case TypeULEB128:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " 0x%llx", Get_ULEB128(&offset));
      break;
    case TypeSLEB128:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %lld", Get_SLEB128(&offset));
      break;
    }
  }

  if (str[0] != '\0')
    DNBLog("%s", str);

  return offset; // Return the offset at which we ended up
}
<commit_msg>Fix warnings in DNBDataRef.cpp, NFC<commit_after>//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 1/11/06.
//
//===----------------------------------------------------------------------===//

#include "DNBDataRef.h"
#include "DNBLog.h"
#include <assert.h>
#include <ctype.h>
#include <libkern/OSByteOrder.h>

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------

DNBDataRef::DNBDataRef()
    : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0),
      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
      m_addrDATA(INVALID_NUB_ADDRESS) {}

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------

DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap)
    : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0),
      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
      m_addrDATA(INVALID_NUB_ADDRESS) {}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------

DNBDataRef::~DNBDataRef() {}

//----------------------------------------------------------------------
// Get8
//----------------------------------------------------------------------
uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {
  uint8_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    val = *(m_start + *offset_ptr);
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get16
//----------------------------------------------------------------------
uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {
  uint16_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    memcpy(&val, p, sizeof(uint16_t));

    if (m_swap)
      val = OSSwapInt16(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get32
//----------------------------------------------------------------------
uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {
  uint32_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    memcpy(&val, p, sizeof(uint32_t));
    if (m_swap)
      val = OSSwapInt32(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// Get64
//----------------------------------------------------------------------
uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {
  uint64_t val = 0;
  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
    const uint8_t *p = m_start + *offset_ptr;
    memcpy(&val, p, sizeof(uint64_t));
    if (m_swap)
      val = OSSwapInt64(val);

    // Advance the offset
    *offset_ptr += sizeof(val);
  }
  return val;
}

//----------------------------------------------------------------------
// GetMax32
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {
  switch (byte_size) {
  case 1:
    return Get8(offset_ptr);
    break;
  case 2:
    return Get16(offset_ptr);
    break;
  case 4:
    return Get32(offset_ptr);
    break;
  default:
    assert(false && "GetMax32 unhandled case!");
    break;
  }
  return 0;
}

//----------------------------------------------------------------------
// GetMax64
//
// Used for calls when the size can vary. Fill in extra cases if they
// are ever needed.
//----------------------------------------------------------------------
uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {
  switch (size) {
  case 1:
    return Get8(offset_ptr);
    break;
  case 2:
    return Get16(offset_ptr);
    break;
  case 4:
    return Get32(offset_ptr);
    break;
  case 8:
    return Get64(offset_ptr);
    break;
  default:
    assert(false && "GetMax64 unhandled case!");
    break;
  }
  return 0;
}

//----------------------------------------------------------------------
// GetPointer
//
// Extract a pointer value from the buffer. The pointer size must be
// set prior to using this using one of the SetPointerSize functions.
//----------------------------------------------------------------------
uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const {
  // Must set pointer size prior to using this call
  assert(m_ptrSize != 0);
  return GetMax64(offset_ptr, m_ptrSize);
}
//----------------------------------------------------------------------
// GetCStr
//----------------------------------------------------------------------
const char *DNBDataRef::GetCStr(offset_t *offset_ptr,
                                uint32_t fixed_length) const {
  const char *s = NULL;
  if (m_start < m_end) {
    s = (const char *)m_start + *offset_ptr;

    // Advance the offset
    if (fixed_length)
      *offset_ptr += fixed_length;
    else
      *offset_ptr += strlen(s) + 1;
  }
  return s;
}

//----------------------------------------------------------------------
// GetData
//----------------------------------------------------------------------
const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr,
                                   uint32_t length) const {
  const uint8_t *data = NULL;
  if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) {
    data = m_start + *offset_ptr;
    *offset_ptr += length;
  }
  return data;
}

//----------------------------------------------------------------------
// Get_ULEB128
//----------------------------------------------------------------------
uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {
  uint64_t result = 0;
  if (m_start < m_end) {
    int shift = 0;
    const uint8_t *src = m_start + *offset_ptr;
    uint8_t byte;
    int bytecount = 0;

    while (src < m_end) {
      bytecount++;
      byte = *src++;
      result |= (uint64_t)(byte & 0x7f) << shift;
      shift += 7;
      if ((byte & 0x80) == 0)
        break;
    }

    *offset_ptr += bytecount;
  }
  return result;
}

//----------------------------------------------------------------------
// Get_SLEB128
//----------------------------------------------------------------------
int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {
  int64_t result = 0;

  if (m_start < m_end) {
    int shift = 0;
    int size = sizeof(uint32_t) * 8;
    const uint8_t *src = m_start + *offset_ptr;

    uint8_t byte = 0;
    int bytecount = 0;

    while (src < m_end) {
      bytecount++;
      byte = *src++;
      result |= (int64_t)(byte & 0x7f) << shift;
      shift += 7;
      if ((byte & 0x80) == 0)
        break;
    }

    // Sign bit of byte is 2nd high order bit (0x40)
    if (shift < size && (byte & 0x40))
      result |= -(1ll << shift);

    *offset_ptr += bytecount;
  }
  return result;
}

//----------------------------------------------------------------------
// Skip_LEB128
//
// Skips past ULEB128 and SLEB128 numbers (just updates the offset)
//----------------------------------------------------------------------
void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const {
  if (m_start < m_end) {
    const uint8_t *start = m_start + *offset_ptr;
    const uint8_t *src = start;

    while ((src < m_end) && (*src++ & 0x80))
      /* Do nothing */;

    *offset_ptr += src - start;
  }
}

uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,
                          uint64_t offsetBase, DNBDataRef::Type type,
                          uint32_t numPerLine, const char *format) {
  uint32_t offset;
  uint32_t count;
  char str[1024];
  str[0] = '\0';
  size_t str_offset = 0;

  for (offset = startOffset, count = 0;
       ValidOffset(offset) && offset < endOffset; ++count) {
    if ((count % numPerLine) == 0) {
      // Print out any previous string
      if (str[0] != '\0')
        DNBLog("%s", str);
      // Reset string offset and fill the current line string with address:
      str_offset = 0;
      str_offset += snprintf(str, sizeof(str), "0x%8.8llx:",
                             (uint64_t)(offsetBase + (offset - startOffset)));
    }

    // Make sure we don't pass the bounds of our current string buffer on each
    // iteration through this loop
    if (str_offset >= sizeof(str)) {
      // The last snprintf consumed our string buffer, we will need to dump this
      // out
      // and reset the string with no address
      DNBLog("%s", str);
      str_offset = 0;
      str[0] = '\0';
    }

    // We already checked that there is at least some room in the string str
    // above, so it is safe to make
    // the snprintf call each time through this loop
    switch (type) {
    case TypeUInt8:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %2.2x", Get8(&offset));
      break;
    case TypeChar: {
      char ch = Get8(&offset);
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %c", isprint(ch) ? ch : ' ');
    } break;
    case TypeUInt16:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %4.4x", Get16(&offset));
      break;
    case TypeUInt32:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %8.8x", Get32(&offset));
      break;
    case TypeUInt64:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %16.16llx", Get64(&offset));
      break;
    case TypePointer:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " 0x%llx", GetPointer(&offset));
      break;
    case TypeULEB128:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " 0x%llx", Get_ULEB128(&offset));
      break;
    case TypeSLEB128:
      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
                             format ? format : " %lld", Get_SLEB128(&offset));
      break;
    }
  }

  if (str[0] != '\0')
    DNBLog("%s", str);

  return offset; // Return the offset at which we ended up
}
<|endoftext|>


<commit_before><commit_msg>core: scene: session: cp<commit_after><|endoftext|>